diff options
Diffstat (limited to 'arch/powerpc/cpu/ppc4xx/cpu_init.c')
| -rw-r--r-- | arch/powerpc/cpu/ppc4xx/cpu_init.c | 64 | 
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 bf208adfe..970a8c1e2 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)) && \ |