mirror of
https://github.com/Fishwaldo/u-boot.git
synced 2025-03-21 06:31:31 +00:00
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>
This commit is contained in:
parent
123922b1e5
commit
f31cfd1925
4 changed files with 71 additions and 27 deletions
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue