
Erratum DDRA003 requires workaround to correctly set RCW10 for registered DIMM. Also adding polling after enabling DDR controller to ensure completion.
Signed-off-by: York Sun yorksun@freescale.com --- arch/powerpc/cpu/mpc85xx/ddr-gen3.c | 53 ++++++++++++++++++++++++++++++++++- include/configs/P4080DS.h | 1 + 2 files changed, 53 insertions(+), 1 deletions(-)
diff --git a/arch/powerpc/cpu/mpc85xx/ddr-gen3.c b/arch/powerpc/cpu/mpc85xx/ddr-gen3.c index 568f9f4..0815ba4 100644 --- a/arch/powerpc/cpu/mpc85xx/ddr-gen3.c +++ b/arch/powerpc/cpu/mpc85xx/ddr-gen3.c @@ -108,6 +108,55 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs, temp_sdram_cfg = regs->ddr_sdram_cfg; temp_sdram_cfg &= ~(SDRAM_CFG_MEM_EN); out_be32(&ddr->sdram_cfg, temp_sdram_cfg); +#ifdef CONFIG_SYS_P4080_ERRATUM_DDRA003 + if (regs->ddr_sdram_rcw_2 & 0x00f00000) { + out_be32(&ddr->timing_cfg_2, regs->timing_cfg_2 & 0xf07fffff); + out_be32(&ddr->debug[2], 0x00000400); + out_be32(&ddr->ddr_zq_cntl, regs->ddr_zq_cntl & 0x7fffffff); + out_be32(&ddr->ddr_wrlvl_cntl, regs->ddr_wrlvl_cntl & 0x7fffffff); + out_be32(&ddr->sdram_cfg_2, regs->ddr_sdram_cfg_2 & 0xffffffeb); + out_be32(&ddr->mtcr, 0); + out_be32(&ddr->debug[12], 0x00000015); + out_be32(&ddr->debug[21], 0x24000000); + out_be32(&ddr->sdram_interval, regs->ddr_sdram_interval & 0xffff); + out_be32(&ddr->sdram_cfg, temp_sdram_cfg | SDRAM_CFG_BI | SDRAM_CFG_MEM_EN); + + asm volatile("sync;isync"); + while (!(in_be32(&ddr->debug[1]) & 0x2)); + + switch (regs->ddr_sdram_rcw_2 & 0x00f00000) { + case 0x00000000: + out_be32(&ddr->sdram_md_cntl, 0xc4080002); + break; + case 0x00100000: + out_be32(&ddr->sdram_md_cntl, 0xc408000a); + break; + case 0x00200000: + out_be32(&ddr->sdram_md_cntl, 0xc4080012); + break; + case 0x00300000: + out_be32(&ddr->sdram_md_cntl, 0xc408001a); + break; + default: + out_be32(&ddr->sdram_md_cntl, 0xc4080002); + printf("Unsupported RC10\n"); + break; + } + + while (in_be32(&ddr->sdram_md_cntl) & 0x80000000); + udelay(6); + out_be32(&ddr->sdram_cfg, temp_sdram_cfg); + out_be32(&ddr->timing_cfg_2, regs->timing_cfg_2); + out_be32(&ddr->debug[2], 0x0); + out_be32(&ddr->ddr_zq_cntl, regs->ddr_zq_cntl); + out_be32(&ddr->ddr_wrlvl_cntl, regs->ddr_wrlvl_cntl); + out_be32(&ddr->sdram_cfg_2, regs->ddr_sdram_cfg_2); + out_be32(&ddr->debug[12], 0x0); + out_be32(&ddr->debug[21], 0x0); + out_be32(&ddr->sdram_interval, regs->ddr_sdram_interval); + + } +#endif /* * For 8572 DDR1 erratum - DDR controller may enter illegal state * when operatiing in 32-bit bus mode with 4-beat bursts, @@ -131,8 +180,10 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs, asm volatile("sync;isync");
/* Let the controller go */ - temp_sdram_cfg = in_be32(&ddr->sdram_cfg); + temp_sdram_cfg = in_be32(&ddr->sdram_cfg) & ~SDRAM_CFG_BI; out_be32(&ddr->sdram_cfg, temp_sdram_cfg | SDRAM_CFG_MEM_EN); + asm volatile("sync;isync"); + while (!(in_be32(&ddr->debug[1]) & 0x2));
/* Poll DDR_SDRAM_CFG_2[D_INIT] bit until auto-data init is done. */ while (in_be32(&ddr->sdram_cfg_2) & 0x10) { diff --git a/include/configs/P4080DS.h b/include/configs/P4080DS.h index d210016..c19bd39 100644 --- a/include/configs/P4080DS.h +++ b/include/configs/P4080DS.h @@ -45,6 +45,7 @@ #define CONFIG_SYS_P4080_ERRATUM_CPC9 #define CONFIG_SYS_P4080_ERRATUM_DDR1 #define CONFIG_SYS_P4080_ERRATUM_DDR7 +#define CONFIG_SYS_P4080_ERRATUM_DDRA003 #define CONFIG_SYS_P4080_ERRATUM_ESDHC1 #define CONFIG_SYS_P4080_ERRATUM_ESDHC9 #define CONFIG_SYS_P4080_ERRATUM_ESDHC11