]> git.ipfire.org Git - people/ms/u-boot.git/blobdiff - arch/powerpc/cpu/mpc85xx/ddr-gen3.c
mpc85xx: Implement workaround for erratum DDR-A003
[people/ms/u-boot.git] / arch / powerpc / cpu / mpc85xx / ddr-gen3.c
index 9bc36f3211b0f5dd4430637c3373c52835c496ff..fa7e09f3933959dfd401b3122277365a419005b0 100644 (file)
@@ -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 & 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,
+                               MD_CNTL_MD_EN           |
+                               MD_CNTL_CS_SEL_CS0_CS1  |
+                               0x04000000              |
+                               MD_CNTL_WRCW            |
+                               MD_CNTL_MD_VALUE(0x02));
+                       break;
+               case 0x00100000:
+                       out_be32(&ddr->sdram_md_cntl,
+                               MD_CNTL_MD_EN           |
+                               MD_CNTL_CS_SEL_CS0_CS1  |
+                               0x04000000              |
+                               MD_CNTL_WRCW            |
+                               MD_CNTL_MD_VALUE(0x0a));
+                       break;
+               case 0x00200000:
+                       out_be32(&ddr->sdram_md_cntl,
+                               MD_CNTL_MD_EN           |
+                               MD_CNTL_CS_SEL_CS0_CS1  |
+                               0x04000000              |
+                               MD_CNTL_WRCW            |
+                               MD_CNTL_MD_VALUE(0x12));
+                       break;
+               case 0x00300000:
+                       out_be32(&ddr->sdram_md_cntl,
+                               MD_CNTL_MD_EN           |
+                               MD_CNTL_CS_SEL_CS0_CS1  |
+                               0x04000000              |
+                               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  |
+                               0x04000000              |
+                               MD_CNTL_WRCW            |
+                               MD_CNTL_MD_VALUE(0x02));
+                       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,
@@ -120,8 +196,11 @@ 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) {