diff options
Diffstat (limited to 'arch/powerpc/cpu/mpc85xx/cpu_init.c')
-rw-r--r-- | arch/powerpc/cpu/mpc85xx/cpu_init.c | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/arch/powerpc/cpu/mpc85xx/cpu_init.c b/arch/powerpc/cpu/mpc85xx/cpu_init.c index 0a33e8dbc1..941c20e00a 100644 --- a/arch/powerpc/cpu/mpc85xx/cpu_init.c +++ b/arch/powerpc/cpu/mpc85xx/cpu_init.c @@ -280,6 +280,71 @@ static void corenet_tb_init(void) } #endif +#ifdef CONFIG_SYS_FSL_ERRATUM_A007212 +void fsl_erratum_a007212_workaround(void) +{ + ccsr_gur_t __iomem *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); + u32 ddr_pll_ratio; + u32 __iomem *plldgdcr1 = (void *)(CONFIG_SYS_DCSRBAR + 0x21c20); + u32 __iomem *plldadcr1 = (void *)(CONFIG_SYS_DCSRBAR + 0x21c28); + u32 __iomem *dpdovrcr4 = (void *)(CONFIG_SYS_DCSRBAR + 0x21e80); +#if (CONFIG_NUM_DDR_CONTROLLERS >= 2) + u32 __iomem *plldgdcr2 = (void *)(CONFIG_SYS_DCSRBAR + 0x21c40); + u32 __iomem *plldadcr2 = (void *)(CONFIG_SYS_DCSRBAR + 0x21c48); +#if (CONFIG_NUM_DDR_CONTROLLERS >= 3) + u32 __iomem *plldgdcr3 = (void *)(CONFIG_SYS_DCSRBAR + 0x21c60); + u32 __iomem *plldadcr3 = (void *)(CONFIG_SYS_DCSRBAR + 0x21c68); +#endif +#endif + /* + * Even this workaround applies to selected version of SoCs, it is + * safe to apply to all versions, with the limitation of odd ratios. + * If RCW has disabled DDR PLL, we have to apply this workaround, + * otherwise DDR will not work. + */ + ddr_pll_ratio = (in_be32(&gur->rcwsr[0]) >> + FSL_CORENET_RCWSR0_MEM_PLL_RAT_SHIFT) & + FSL_CORENET_RCWSR0_MEM_PLL_RAT_MASK; + /* check if RCW sets ratio to 0, required by this workaround */ + if (ddr_pll_ratio != 0) + return; + ddr_pll_ratio = (in_be32(&gur->rcwsr[0]) >> + FSL_CORENET_RCWSR0_MEM_PLL_RAT_RESV_SHIFT) & + FSL_CORENET_RCWSR0_MEM_PLL_RAT_MASK; + /* check if reserved bits have the desired ratio */ + if (ddr_pll_ratio == 0) { + printf("Error: Unknown DDR PLL ratio!\n"); + return; + } + ddr_pll_ratio >>= 1; + + setbits_be32(plldadcr1, 0x02000001); +#if (CONFIG_NUM_DDR_CONTROLLERS >= 2) + setbits_be32(plldadcr2, 0x02000001); +#if (CONFIG_NUM_DDR_CONTROLLERS >= 3) + setbits_be32(plldadcr3, 0x02000001); +#endif +#endif + setbits_be32(dpdovrcr4, 0xe0000000); + out_be32(plldgdcr1, 0x08000001 | (ddr_pll_ratio << 1)); +#if (CONFIG_NUM_DDR_CONTROLLERS >= 2) + out_be32(plldgdcr2, 0x08000001 | (ddr_pll_ratio << 1)); +#if (CONFIG_NUM_DDR_CONTROLLERS >= 3) + out_be32(plldgdcr3, 0x08000001 | (ddr_pll_ratio << 1)); +#endif +#endif + udelay(100); + clrbits_be32(plldadcr1, 0x02000001); +#if (CONFIG_NUM_DDR_CONTROLLERS >= 2) + clrbits_be32(plldadcr2, 0x02000001); +#if (CONFIG_NUM_DDR_CONTROLLERS >= 3) + clrbits_be32(plldadcr3, 0x02000001); +#endif +#endif + clrbits_be32(dpdovrcr4, 0xe0000000); +} +#endif + void cpu_init_f (void) { extern void m8560_cpm_reset (void); @@ -349,6 +414,10 @@ void cpu_init_f (void) in_be32(&gur->dcsrcr); #endif +#ifdef CONFIG_SYS_FSL_ERRATUM_A007212 + fsl_erratum_a007212_workaround(); +#endif + } /* Implement a dummy function for those platforms w/o SERDES */ |