]> git.sur5r.net Git - u-boot/commitdiff
powerpc/mpc8xxx: Fix DDR initialization waiting for D_INIT
authorYork Sun <yorksun@freescale.com>
Mon, 8 Oct 2012 07:44:24 +0000 (07:44 +0000)
committerAndy Fleming <afleming@freescale.com>
Mon, 22 Oct 2012 19:31:27 +0000 (14:31 -0500)
When ECC is enabled, DDR controller needs to initialize the data and ecc.
The wait time can be calcuated with total memory size, bus width, bus speed
and interleaving mode. If it went wrong, it is bettert to timeout than
waiting for D_INIT to clear, where it probably hangs.

Signed-off-by: York Sun <yorksun@freescale.com>
Signed-off-by: Andy Fleming <afleming@freescale.com>
arch/powerpc/cpu/mpc85xx/ddr-gen3.c
arch/powerpc/cpu/mpc8xxx/ddr/main.c
arch/powerpc/cpu/mpc8xxx/ddr/util.c
arch/powerpc/include/asm/fsl_ddr_sdram.h

index 088cf4564718949733cd8c70609b35c328481837..8bed5fe925b8130ecc1d14aba850881c8242fa02 100644 (file)
 void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
                             unsigned int ctrl_num)
 {
-       unsigned int i;
+       unsigned int i, bus_width;
        volatile ccsr_ddr_t *ddr;
        u32 temp_sdram_cfg;
+       u32 total_gb_size_per_controller;
+       int timeout, timeout_save;
 #ifdef CONFIG_SYS_FSL_ERRATUM_DDR111_DDR134
        volatile ccsr_local_ecm_t *ecm = (void *)CONFIG_SYS_MPC85xx_ECM_ADDR;
-       u32 total_gb_size_per_controller;
        unsigned int csn_bnds_backup = 0, cs_sa, cs_ea, *csn_bnds_t;
        int csn = -1;
 #endif
@@ -52,8 +53,8 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
                return;
        }
 
-       out_be32(&ddr->eor, regs->ddr_eor);
-
+       if (regs->ddr_eor)
+               out_be32(&ddr->eor, regs->ddr_eor);
 #ifdef CONFIG_SYS_FSL_ERRATUM_DDR111_DDR134
        debug("Workaround for ERRATUM_DDR111_DDR134\n");
        for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
@@ -275,9 +276,46 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
        out_be32(&ddr->sdram_cfg, temp_sdram_cfg | SDRAM_CFG_MEM_EN);
        asm volatile("sync;isync");
 
+       total_gb_size_per_controller = 0;
+       for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
+               if (!(regs->cs[i].config & 0x80000000))
+                       continue;
+               total_gb_size_per_controller += 1 << (
+                       ((regs->cs[i].config >> 14) & 0x3) + 2 +
+                       ((regs->cs[i].config >> 8) & 0x7) + 12 +
+                       ((regs->cs[i].config >> 0) & 0x7) + 8 +
+                       3 - ((regs->ddr_sdram_cfg >> 19) & 0x3) -
+                       26);                    /* minus 26 (count of 64M) */
+       }
+       if (fsl_ddr_get_intl3r() & 0x80000000)  /* 3-way interleaving */
+               total_gb_size_per_controller *= 3;
+       else if (regs->cs[0].config & 0x20000000) /* 2-way interleaving */
+               total_gb_size_per_controller <<= 1;
+       /*
+        * total memory / bus width = transactions needed
+        * transactions needed / data rate = seconds
+        * to add plenty of buffer, double the time
+        * For example, 2GB on 666MT/s 64-bit bus takes about 402ms
+        * Let's wait for 800ms
+        */
+       bus_width = 3 - ((ddr->sdram_cfg & SDRAM_CFG_DBW_MASK)
+                       >> SDRAM_CFG_DBW_SHIFT);
+       timeout = ((total_gb_size_per_controller << (6 - bus_width)) * 100 /
+               (get_ddr_freq(0) >> 20)) << 1;
+       timeout_save = timeout;
+       total_gb_size_per_controller >>= 4;     /* shift down to gb size */
+       debug("total %d GB\n", total_gb_size_per_controller);
+       debug("Need to wait up to %d * 10ms\n", timeout);
+
        /* Poll DDR_SDRAM_CFG_2[D_INIT] bit until auto-data init is done.  */
-       while (in_be32(&ddr->sdram_cfg_2) & SDRAM_CFG2_D_INIT)
+       while ((in_be32(&ddr->sdram_cfg_2) & SDRAM_CFG2_D_INIT) &&
+               (timeout >= 0)) {
                udelay(10000);          /* throttle polling rate */
+               timeout--;
+       }
+
+       if (timeout <= 0)
+               printf("Waiting for D_INIT timeout. Memory may not work.\n");
 
 #ifdef CONFIG_SYS_FSL_ERRATUM_DDR111_DDR134
        /* continue this workaround */
@@ -335,23 +373,9 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
        while (in_be32(&ddr->debug[1]) & 0x400)
                udelay(10000);          /* throttle polling rate */
 
-       /* 7. Wait for 400ms/GB */
-       total_gb_size_per_controller = 0;
-       for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
-               if (i == csn) {
-                       total_gb_size_per_controller +=
-                               ((csn_bnds_backup & 0xFFFF) >> 6)
-                               - (csn_bnds_backup >> 22) + 1;
-               } else {
-                       total_gb_size_per_controller +=
-                               ((regs->cs[i].bnds & 0xFFFF) >> 6)
-                               - (regs->cs[i].bnds >> 22) + 1;
-               }
-       }
-       if (in_be32(&ddr->sdram_cfg) & 0x80000)
-               total_gb_size_per_controller <<= 1;
-       debug("Wait for %d ms\n", total_gb_size_per_controller * 400);
-       udelay(total_gb_size_per_controller * 400000);
+       /* 7. Wait for state machine 2nd run, roughly 400ms/GB */
+       debug("Wait for %d * 10ms\n", timeout_save);
+       udelay(timeout_save * 10000);
 
        /* 8. Set sdram_cfg_2[dinit] if options requires */
        setbits_be32(&ddr->sdram_cfg_2,
@@ -359,8 +383,16 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
        debug("Setting sdram_cfg_2 to 0x%08x\n", in_be32(&ddr->sdram_cfg_2));
 
        /* 9. Poll until dinit is cleared */
-       while (in_be32(&ddr->sdram_cfg_2) & SDRAM_CFG2_D_INIT)
-               udelay(10000);
+       timeout = timeout_save;
+       debug("Need to wait up to %d * 10ms\n", timeout);
+       while ((in_be32(&ddr->sdram_cfg_2) & SDRAM_CFG2_D_INIT) &&
+               (timeout >= 0)) {
+               udelay(10000);          /* throttle polling rate */
+               timeout--;
+       }
+
+       if (timeout <= 0)
+               printf("Waiting for D_INIT timeout. Memory may not work.\n");
 
        /* 10. Clear EEBACR[3] */
        clrbits_be32(&ecm->eebacr, 10000000);
index b47268c20eacc22e31fe1314e3c18999b24ab9e4..2885906e875c6498136f9c6be35c9d1d38193655 100644 (file)
@@ -526,6 +526,17 @@ phys_size_t fsl_ddr_sdram(void)
 #endif
                total_memory = fsl_ddr_compute(&info, STEP_GET_SPD, 0);
 
+       /* setup 3-way interleaving before enabling DDRC */
+       switch (info.memctl_opts[0].memctl_interleaving_mode) {
+       case FSL_DDR_3WAY_1KB_INTERLEAVING:
+       case FSL_DDR_3WAY_4KB_INTERLEAVING:
+       case FSL_DDR_3WAY_8KB_INTERLEAVING:
+               fsl_ddr_set_intl3r(info.memctl_opts[0].memctl_interleaving_mode);
+               break;
+       default:
+               break;
+       }
+
        /* Program configuration registers. */
        for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
                debug("Programming controller %u\n", i);
@@ -561,7 +572,6 @@ phys_size_t fsl_ddr_sdram(void)
                        case FSL_DDR_3WAY_8KB_INTERLEAVING:
                                law_memctl = LAW_TRGT_IF_DDR_INTLV_123;
                                if (i == 0) {
-                                       fsl_ddr_set_intl3r(info.memctl_opts[i].memctl_interleaving_mode);
                                        fsl_ddr_set_lawbar(&info.common_timing_params[i],
                                                law_memctl, i);
                                }
index b439cc9750d33533e0bed793cac2240d8ac2d4b3..afc5fae497a3c9a1e4ee2cc726959ff82f1c9d28 100644 (file)
@@ -142,13 +142,13 @@ void board_add_ram_info(int use_default)
 
 #if CONFIG_NUM_DDR_CONTROLLERS >= 2
        if (!(sdram_cfg & SDRAM_CFG_MEM_EN)) {
-               ddr = (void *)CONFIG_SYS_MPC85xx_DDR2_ADDR;
+               ddr = (void __iomem *)CONFIG_SYS_MPC85xx_DDR2_ADDR;
                sdram_cfg = in_be32(&ddr->sdram_cfg);
        }
 #endif
 #if CONFIG_NUM_DDR_CONTROLLERS >= 3
        if (!(sdram_cfg & SDRAM_CFG_MEM_EN)) {
-               ddr = (void *)CONFIG_SYS_MPC85xx_DDR3_ADDR;
+               ddr = (void __iomem *)CONFIG_SYS_MPC85xx_DDR3_ADDR;
                sdram_cfg = in_be32(&ddr->sdram_cfg);
        }
 #endif
index bb79335b188ec896889ceb62c738b5cc49237454..640d3297d6c89a36725eacd1413911e045d1456c 100644 (file)
@@ -98,6 +98,7 @@ typedef ddr3_spd_eeprom_t generic_spd_eeprom_t;
 #define SDRAM_CFG_SDRAM_TYPE_SHIFT     24
 #define SDRAM_CFG_DYN_PWR              0x00200000
 #define SDRAM_CFG_DBW_MASK             0x00180000
+#define SDRAM_CFG_DBW_SHIFT            19
 #define SDRAM_CFG_32_BE                        0x00080000
 #define SDRAM_CFG_16_BE                        0x00100000
 #define SDRAM_CFG_8_BE                 0x00040000
@@ -330,6 +331,7 @@ extern phys_size_t fsl_ddr_sdram_size(void);
 extern int fsl_use_spd(void);
 extern void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
                                        unsigned int ctrl_num);
+u32 fsl_ddr_get_intl3r(void);
 
 /*
  * The 85xx boards have a common prototype for fixed_sdram so put the