diff options
-rw-r--r-- | arch/powerpc/cpu/mpc85xx/ddr-gen3.c | 80 | ||||
-rw-r--r-- | arch/powerpc/cpu/mpc8xxx/ddr/main.c | 12 | ||||
-rw-r--r-- | arch/powerpc/cpu/mpc8xxx/ddr/util.c | 4 | ||||
-rw-r--r-- | arch/powerpc/include/asm/fsl_ddr_sdram.h | 2 |
4 files changed, 71 insertions, 27 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); diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/main.c b/arch/powerpc/cpu/mpc8xxx/ddr/main.c index b47268c..2885906 100644 --- a/arch/powerpc/cpu/mpc8xxx/ddr/main.c +++ b/arch/powerpc/cpu/mpc8xxx/ddr/main.c @@ -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); } diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/util.c b/arch/powerpc/cpu/mpc8xxx/ddr/util.c index b439cc9..afc5fae 100644 --- a/arch/powerpc/cpu/mpc8xxx/ddr/util.c +++ b/arch/powerpc/cpu/mpc8xxx/ddr/util.c @@ -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 diff --git a/arch/powerpc/include/asm/fsl_ddr_sdram.h b/arch/powerpc/include/asm/fsl_ddr_sdram.h index bb79335..640d329 100644 --- a/arch/powerpc/include/asm/fsl_ddr_sdram.h +++ b/arch/powerpc/include/asm/fsl_ddr_sdram.h @@ -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 |