aboutsummaryrefslogtreecommitdiff
path: root/arch/powerpc/cpu/ppc4xx
diff options
context:
space:
mode:
authorSteven A. Falco2011-05-05 10:08:35 -0400
committerStefan Roese2011-05-12 16:10:51 +0200
commit644362c40aa8d356d2cc0d230ce0c3bad279c23c (patch)
tree2f13f72006f88a509749e804bbc08864bb031f3e /arch/powerpc/cpu/ppc4xx
parent264eaa0ea967bac32214b87d60cfc86c8b22cac6 (diff)
PPC405EX CHIP_21 erratum
APM errata CHIP_21 for the 405EX/EXr (from the rev 1.09 document dated 4/27/11) states that rev D processors may wake up with the wrong feature set. This patch implements the APM-proposed workaround. To enable this patch for your board, add the appropriate define for your CPU to your board header file. See kilauea.h for more information. The following variants are supported: #define CONFIG_SYS_4xx_CHIP_21_405EX_NO_SECURITY #define CONFIG_SYS_4xx_CHIP_21_405EX_SECURITY #define CONFIG_SYS_4xx_CHIP_21_405EXr_NO_SECURITY #define CONFIG_SYS_4xx_CHIP_21_405EXr_SECURITY Please note that if you select the wrong define, your board will not boot, and JTAG will be required to recover. Tested on custom boards using: CONFIG_SYS_4xx_CHIP_21_405EX_NO_SECURITY <sfalco@harris.com> CONFIG_SYS_4xx_CHIP_21_405EX_SECURITY <eibach@gdsys.de> Signed-off-by: Steve Falco <sfalco@harris.com> Acked-by: Dirk Eibach <eibach@gdsys.de> Signed-off-by: Stefan Roese <sr@denx.de>
Diffstat (limited to 'arch/powerpc/cpu/ppc4xx')
-rw-r--r--arch/powerpc/cpu/ppc4xx/cpu_init.c64
1 files changed, 64 insertions, 0 deletions
diff --git a/arch/powerpc/cpu/ppc4xx/cpu_init.c b/arch/powerpc/cpu/ppc4xx/cpu_init.c
index bf208adfe6f..970a8c1e2dc 100644
--- a/arch/powerpc/cpu/ppc4xx/cpu_init.c
+++ b/arch/powerpc/cpu/ppc4xx/cpu_init.c
@@ -221,6 +221,66 @@ void reconfigure_pll(u32 new_cpu_freq)
#endif
}
+#ifdef CONFIG_SYS_4xx_CHIP_21_ERRATA
+void
+chip_21_errata(void)
+{
+ /*
+ * See rev 1.09 of the 405EX/405EXr errata. CHIP_21 says that
+ * sometimes reading the PVR and/or SDR0_ECID results in incorrect
+ * values. Since the rev-D chip uses the SDR0_ECID bits to control
+ * internal features, that means the second PCIe or ethernet of an EX
+ * variant could fail to work. Also, security features of both EX and
+ * EXr might be incorrectly disabled.
+ *
+ * The suggested workaround is as follows (covering rev-C and rev-D):
+ *
+ * 1.Read the PVR and SDR0_ECID3.
+ *
+ * 2.If the PVR matches an expected Revision C PVR value AND if
+ * SDR0_ECID3[12:15] is different from PVR[28:31], then processor is
+ * Revision C: continue executing the initialization code (no reset
+ * required). else go to step 3.
+ *
+ * 3.If the PVR matches an expected Revision D PVR value AND if
+ * SDR0_ECID3[10:11] matches its expected value, then continue
+ * executing initialization code, no reset required. else write
+ * DBCR0[RST] = 0b11 to generate a SysReset.
+ */
+
+ u32 pvr;
+ u32 pvr_28_31;
+ u32 ecid3;
+ u32 ecid3_10_11;
+ u32 ecid3_12_15;
+
+ /* Step 1: */
+ pvr = get_pvr();
+ mfsdr(SDR0_ECID3, ecid3);
+
+ /* Step 2: */
+ pvr_28_31 = pvr & 0xf;
+ ecid3_10_11 = (ecid3 >> 20) & 0x3;
+ ecid3_12_15 = (ecid3 >> 16) & 0xf;
+ if ((pvr == CONFIG_405EX_CHIP21_PVR_REV_C) &&
+ (pvr_28_31 != ecid3_12_15)) {
+ /* No reset required. */
+ return;
+ }
+
+ /* Step 3: */
+ if ((pvr == CONFIG_405EX_CHIP21_PVR_REV_D) &&
+ (ecid3_10_11 == CONFIG_405EX_CHIP21_ECID3_REV_D)) {
+ /* No reset required. */
+ return;
+ }
+
+ /* Reset required. */
+ __asm__ __volatile__ ("sync; isync");
+ mtspr(SPRN_DBCR0, 0x30000000);
+}
+#endif
+
/*
* Breath some life into the CPU...
*
@@ -235,6 +295,10 @@ cpu_init_f (void)
u32 val;
#endif
+#ifdef CONFIG_SYS_4xx_CHIP_21_ERRATA
+ chip_21_errata();
+#endif
+
reconfigure_pll(CONFIG_SYS_PLL_RECONFIG);
#if (defined(CONFIG_405EP) || defined (CONFIG_405EX)) && \