diff options
author | York Sun <yorksun@freescale.com> | 2012-10-08 07:44:24 +0000 |
---|---|---|
committer | Andy Fleming <afleming@freescale.com> | 2012-10-22 14:31:27 -0500 |
commit | f31cfd19253713eea59311dec9e99df5d43b2db9 (patch) | |
tree | 61e6f45481b4efa6949c5456fe81dcf0135480e6 /arch/powerpc/cpu/mpc85xx/ddr-gen3.c | |
parent | 123922b1e583dc6bd6b8909af2d788f6e40a33a9 (diff) | |
download | u-boot-imx-f31cfd19253713eea59311dec9e99df5d43b2db9.zip u-boot-imx-f31cfd19253713eea59311dec9e99df5d43b2db9.tar.gz u-boot-imx-f31cfd19253713eea59311dec9e99df5d43b2db9.tar.bz2 |
powerpc/mpc8xxx: Fix DDR initialization waiting for D_INIT
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>
Diffstat (limited to 'arch/powerpc/cpu/mpc85xx/ddr-gen3.c')
-rw-r--r-- | arch/powerpc/cpu/mpc85xx/ddr-gen3.c | 80 |
1 files changed, 56 insertions, 24 deletions
diff --git a/arch/powerpc/cpu/mpc85xx/ddr-gen3.c b/arch/powerpc/cpu/mpc85xx/ddr-gen3.c index 088cf45..8bed5fe 100644 --- a/arch/powerpc/cpu/mpc85xx/ddr-gen3.c +++ b/arch/powerpc/cpu/mpc85xx/ddr-gen3.c @@ -18,12 +18,13 @@ 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); |