Erratum DDR-A003 requires workaround to correctly set RCW10 for registered DIMM.
Also adding polling after enabling DDR controller to ensure completion.
Signed-off-by: York Sun york...@freescale.com
---
arch/powerpc/cpu/mpc85xx/cmd_errata.c|4 ++
arch/powerpc/cpu/mpc85xx/ddr-gen3.c | 81 +-
arch/powerpc/include/asm/fsl_ddr_sdram.h | 19 +++
include/configs/P4080DS.h|1 +
4 files changed, 104 insertions(+), 1 deletions(-)
diff --git a/arch/powerpc/cpu/mpc85xx/cmd_errata.c
b/arch/powerpc/cpu/mpc85xx/cmd_errata.c
index d73f3d7..7d9a074 100644
--- a/arch/powerpc/cpu/mpc85xx/cmd_errata.c
+++ b/arch/powerpc/cpu/mpc85xx/cmd_errata.c
@@ -47,6 +47,10 @@ static int do_errata(cmd_tbl_t *cmdtp, int flag, int argc,
char * const argv[])
#if defined(CONFIG_SYS_P4080_ERRATUM_CPU22)
puts(Work-around for Erratum CPU22 enabled\n);
#endif
+#ifdef CONFIG_SYS_FSL_ERRATUM_DDR_A003
+ puts(Work-around for Erratum DDR-A003 enabled\n);
+#endif
+
return 0;
}
diff --git a/arch/powerpc/cpu/mpc85xx/ddr-gen3.c
b/arch/powerpc/cpu/mpc85xx/ddr-gen3.c
index 5f1848f..1e15111 100644
--- a/arch/powerpc/cpu/mpc85xx/ddr-gen3.c
+++ b/arch/powerpc/cpu/mpc85xx/ddr-gen3.c
@@ -97,6 +97,82 @@ 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_FSL_ERRATUM_DDR_A003
+ if (regs-ddr_sdram_rcw_2 0x00f0) {
+ out_be32(ddr-timing_cfg_2, regs-timing_cfg_2 0xf07f);
+ out_be32(ddr-debug[2], 0x0400);
+ out_be32(ddr-ddr_zq_cntl, regs-ddr_zq_cntl 0x7fff);
+ out_be32(ddr-ddr_wrlvl_cntl, regs-ddr_wrlvl_cntl
0x7fff);
+ out_be32(ddr-sdram_cfg_2, regs-ddr_sdram_cfg_2 0xffeb);
+ out_be32(ddr-mtcr, 0);
+ out_be32(ddr-debug[12], 0x0015);
+ out_be32(ddr-debug[21], 0x2400);
+ out_be32(ddr-sdram_interval, regs-ddr_sdram_interval
0x);
+ 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 0x00f0) {
+ case 0x:
+ out_be32(ddr-sdram_md_cntl,
+ MD_CNTL_MD_EN |
+ MD_CNTL_CS_SEL_CS0_CS1 |
+ 0x0400 |
+ MD_CNTL_WRCW|
+ MD_CNTL_MD_VALUE(0x02));
+ break;
+ case 0x0010:
+ out_be32(ddr-sdram_md_cntl,
+ MD_CNTL_MD_EN |
+ MD_CNTL_CS_SEL_CS0_CS1 |
+ 0x0400 |
+ MD_CNTL_WRCW|
+ MD_CNTL_MD_VALUE(0x0a));
+ break;
+ case 0x0020:
+ out_be32(ddr-sdram_md_cntl,
+ MD_CNTL_MD_EN |
+ MD_CNTL_CS_SEL_CS0_CS1 |
+ 0x0400 |
+ MD_CNTL_WRCW|
+ MD_CNTL_MD_VALUE(0x12));
+ break;
+ case 0x0030:
+ out_be32(ddr-sdram_md_cntl,
+ MD_CNTL_MD_EN |
+ MD_CNTL_CS_SEL_CS0_CS1 |
+ 0x0400 |
+ MD_CNTL_WRCW|
+ MD_CNTL_MD_VALUE(0x1a));
+ break;
+ default:
+ out_be32(ddr-sdram_md_cntl,
+ MD_CNTL_MD_EN |
+ MD_CNTL_CS_SEL_CS0_CS1 |
+ 0x0400 |
+ MD_CNTL_WRCW|
+ MD_CNTL_MD_VALUE(0x02));
+ printf(Unsupported RC10\n);
+ break;
+ }
+
+ while (in_be32(ddr-sdram_md_cntl) 0x8000)
+ ;
+ 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);
+