diff options
-rw-r--r-- | arch/powerpc/cpu/ppc4xx/cpu_init.c | 64 | ||||
-rw-r--r-- | arch/powerpc/include/asm/ppc405ex.h | 5 | ||||
-rw-r--r-- | arch/powerpc/include/asm/processor.h | 31 | ||||
-rw-r--r-- | include/configs/kilauea.h | 14 |
4 files changed, 114 insertions, 0 deletions
diff --git a/arch/powerpc/cpu/ppc4xx/cpu_init.c b/arch/powerpc/cpu/ppc4xx/cpu_init.c index bf208ad..970a8c1 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)) && \ diff --git a/arch/powerpc/include/asm/ppc405ex.h b/arch/powerpc/include/asm/ppc405ex.h index 36d3149..8070385 100644 --- a/arch/powerpc/include/asm/ppc405ex.h +++ b/arch/powerpc/include/asm/ppc405ex.h @@ -43,6 +43,11 @@ #define SDR0_PFC1 0x4101 #define SDR0_MFR 0x4300 /* SDR0_MFR reg */ +#define SDR0_ECID0 0x0080 +#define SDR0_ECID1 0x0081 +#define SDR0_ECID2 0x0082 +#define SDR0_ECID3 0x0083 + #define SDR0_SDCS_SDD (0x80000000 >> 31) #define SDR0_SRST_DMC (0x80000000 >> 10) diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h index f5bf4dd..c5b03b4 100644 --- a/arch/powerpc/include/asm/processor.h +++ b/arch/powerpc/include/asm/processor.h @@ -974,6 +974,37 @@ #define PVR_5200B 0x80822014 /* + * 405EX/EXr CHIP_21 Errata + */ +#ifdef CONFIG_SYS_4xx_CHIP_21_405EX_SECURITY +#define CONFIG_SYS_4xx_CHIP_21_ERRATA +#define CONFIG_405EX_CHIP21_PVR_REV_C PVR_405EX1_RC +#define CONFIG_405EX_CHIP21_PVR_REV_D PVR_405EX1_RD +#define CONFIG_405EX_CHIP21_ECID3_REV_D 0x0 +#endif + +#ifdef CONFIG_SYS_4xx_CHIP_21_405EX_NO_SECURITY +#define CONFIG_SYS_4xx_CHIP_21_ERRATA +#define CONFIG_405EX_CHIP21_PVR_REV_C PVR_405EX2_RC +#define CONFIG_405EX_CHIP21_PVR_REV_D PVR_405EX2_RD +#define CONFIG_405EX_CHIP21_ECID3_REV_D 0x1 +#endif + +#ifdef CONFIG_SYS_4xx_CHIP_21_405EXr_SECURITY +#define CONFIG_SYS_4xx_CHIP_21_ERRATA +#define CONFIG_405EX_CHIP21_PVR_REV_C PVR_405EXR1_RC +#define CONFIG_405EX_CHIP21_PVR_REV_D PVR_405EXR1_RD +#define CONFIG_405EX_CHIP21_ECID3_REV_D 0x2 +#endif + +#ifdef CONFIG_SYS_4xx_CHIP_21_405EXr_NO_SECURITY +#define CONFIG_SYS_4xx_CHIP_21_ERRATA +#define CONFIG_405EX_CHIP21_PVR_REV_C PVR_405EXR2_RC +#define CONFIG_405EX_CHIP21_PVR_REV_D PVR_405EXR2_RD +#define CONFIG_405EX_CHIP21_ECID3_REV_D 0x3 +#endif + +/* * System Version Register */ diff --git a/include/configs/kilauea.h b/include/configs/kilauea.h index 031f8fb..e66aadf 100644 --- a/include/configs/kilauea.h +++ b/include/configs/kilauea.h @@ -44,6 +44,20 @@ #endif /* + * CHIP_21 errata - you must set this to match your exact CPU, else your + * board will not boot. DO NOT enable this unless you have JTAG available + * for recovery, in the event you get it wrong. + * + * Kilauea uses the 405EX, while Haleakala uses the 405EXr. Either board + * may be equipped for security or not. You must look at the CPU part + * number to be sure what you have. + */ +/* #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 */ + +/* * Include common defines/options for all AMCC eval boards */ #define CONFIG_HOSTNAME kilauea |