X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=arch%2Fpowerpc%2Fcpu%2Fmpc85xx%2Fddr-gen3.c;h=ef0dd1da64ccb5a2f0e211dfbbd5000747b8a1b4;hb=e76cd5d4cf311da7d40adc5d6e9b425509cf0205;hp=fa7e09f3933959dfd401b3122277365a419005b0;hpb=5aebe3b07254d9ec8f7ae23a4525a6c535a7f858;p=u-boot diff --git a/arch/powerpc/cpu/mpc85xx/ddr-gen3.c b/arch/powerpc/cpu/mpc85xx/ddr-gen3.c index fa7e09f393..ef0dd1da64 100644 --- a/arch/powerpc/cpu/mpc85xx/ddr-gen3.c +++ b/arch/powerpc/cpu/mpc85xx/ddr-gen3.c @@ -1,5 +1,5 @@ /* - * Copyright 2008-2011 Freescale Semiconductor, Inc. + * Copyright 2008-2012 Freescale Semiconductor, Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -18,24 +18,64 @@ 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; +#ifdef CONFIG_SYS_FSL_ERRATUM_DDR111_DDR134 + int timeout_save; + volatile ccsr_local_ecm_t *ecm = (void *)CONFIG_SYS_MPC85xx_ECM_ADDR; + unsigned int csn_bnds_backup = 0, cs_sa, cs_ea, *csn_bnds_t; + int csn = -1; +#endif switch (ctrl_num) { case 0: - ddr = (void *)CONFIG_SYS_MPC85xx_DDR_ADDR; + ddr = (void *)CONFIG_SYS_MPC8xxx_DDR_ADDR; break; +#if defined(CONFIG_SYS_MPC8xxx_DDR2_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 1) case 1: - ddr = (void *)CONFIG_SYS_MPC85xx_DDR2_ADDR; + ddr = (void *)CONFIG_SYS_MPC8xxx_DDR2_ADDR; + break; +#endif +#if defined(CONFIG_SYS_MPC8xxx_DDR3_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 2) + case 2: + ddr = (void *)CONFIG_SYS_MPC8xxx_DDR3_ADDR; + break; +#endif +#if defined(CONFIG_SYS_MPC8xxx_DDR4_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 3) + case 3: + ddr = (void *)CONFIG_SYS_MPC8xxx_DDR4_ADDR; break; +#endif default: printf("%s unexpected ctrl_num = %u\n", __FUNCTION__, ctrl_num); 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++) { + cs_sa = (regs->cs[i].bnds >> 16) & 0xfff; + cs_ea = regs->cs[i].bnds & 0xfff; + if ((cs_sa <= 0xff) && (cs_ea >= 0xff)) { + csn = i; + csn_bnds_backup = regs->cs[i].bnds; + csn_bnds_t = (unsigned int *) ®s->cs[i].bnds; + if (cs_ea > 0xeff) + *csn_bnds_t = regs->cs[i].bnds + 0x01000000; + else + *csn_bnds_t = regs->cs[i].bnds + 0x01000100; + debug("Found cs%d_bns (0x%08x) covering 0xff000000, " + "change it to 0x%x\n", + csn, csn_bnds_backup, regs->cs[i].bnds); + break; + } + } +#endif for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) { if (i == 0) { out_be32(&ddr->cs0_bnds, regs->cs[i].bnds); @@ -83,6 +123,11 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs, out_be32(&ddr->timing_cfg_5, regs->timing_cfg_5); out_be32(&ddr->ddr_zq_cntl, regs->ddr_zq_cntl); out_be32(&ddr->ddr_wrlvl_cntl, regs->ddr_wrlvl_cntl); + if (regs->ddr_wrlvl_cntl_2) + out_be32(&ddr->ddr_wrlvl_cntl_2, regs->ddr_wrlvl_cntl_2); + if (regs->ddr_wrlvl_cntl_3) + out_be32(&ddr->ddr_wrlvl_cntl_3, regs->ddr_wrlvl_cntl_3); + out_be32(&ddr->ddr_sr_cntr, regs->ddr_sr_cntr); out_be32(&ddr->ddr_sdram_rcw_1, regs->ddr_sdram_rcw_1); out_be32(&ddr->ddr_sdram_rcw_2, regs->ddr_sdram_rcw_2); @@ -90,14 +135,27 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs, out_be32(&ddr->ddr_cdr2, regs->ddr_cdr2); out_be32(&ddr->err_disable, regs->err_disable); out_be32(&ddr->err_int_en, regs->err_int_en); - for (i = 0; i < 32; i++) - out_be32(&ddr->debug[i], regs->debug[i]); + for (i = 0; i < 32; i++) { + if (regs->debug[i]) { + debug("Write to debug_%d as %08x\n", i+1, regs->debug[i]); + out_be32(&ddr->debug[i], regs->debug[i]); + } + } +#ifdef CONFIG_SYS_FSL_ERRATUM_A_004934 + out_be32(&ddr->debug[28], 0x00003000); +#endif + +#ifdef CONFIG_SYS_FSL_ERRATUM_DDR_A003474 + out_be32(&ddr->debug[12], 0x00000015); + out_be32(&ddr->debug[21], 0x24000000); +#endif /* CONFIG_SYS_FSL_ERRATUM_DDR_A003474 */ /* Set, but do not enable the memory */ 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 + debug("Workaround for ERRATUM_DDR_A003\n"); if (regs->ddr_sdram_rcw_2 & 0x00f00000) { out_be32(&ddr->timing_cfg_2, regs->timing_cfg_2 & 0xf07fffff); out_be32(&ddr->debug[2], 0x00000400); @@ -178,13 +236,35 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs, * when operatiing in 32-bit bus mode with 4-beat bursts, * This erratum does not affect DDR3 mode, only for DDR2 mode. */ -#ifdef CONFIG_MPC8572 +#ifdef CONFIG_SYS_FSL_ERRATUM_DDR_115 + debug("Workaround for ERRATUM_DDR_115\n"); if ((((in_be32(&ddr->sdram_cfg) >> 24) & 0x7) == SDRAM_TYPE_DDR2) && in_be32(&ddr->sdram_cfg) & 0x80000) { /* set DEBUG_1[31] */ setbits_be32(&ddr->debug[0], 1); } #endif +#ifdef CONFIG_SYS_FSL_ERRATUM_DDR111_DDR134 + debug("Workaround for ERRATUM_DDR111_DDR134\n"); + /* + * This is the combined workaround for DDR111 and DDR134 + * following the published errata for MPC8572 + */ + + /* 1. Set EEBACR[3] */ + setbits_be32(&ecm->eebacr, 0x10000000); + debug("Setting EEBACR[3] to 0x%08x\n", in_be32(&ecm->eebacr)); + + /* 2. Set DINIT in SDRAM_CFG_2*/ + setbits_be32(&ddr->sdram_cfg_2, SDRAM_CFG2_D_INIT); + debug("Setting sdram_cfg_2[D_INIT] to 0x%08x\n", + in_be32(&ddr->sdram_cfg_2)); + + /* 3. Set DEBUG_3[21] */ + setbits_be32(&ddr->debug[2], 0x400); + debug("Setting DEBUG_3[21] to 0x%08x\n", in_be32(&ddr->debug[2])); + +#endif /* part 1 of the workaound */ /* * 500 painful micro-seconds must elapse between @@ -199,11 +279,152 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs, 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)) - ; + + 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; +#ifdef CONFIG_SYS_FSL_ERRATUM_DDR111_DDR134 + timeout_save = timeout; +#endif + 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) & 0x10) { + 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 */ + + /* 4. Clear DEBUG3[21] */ + clrbits_be32(&ddr->debug[2], 0x400); + debug("Clearing D3[21] to 0x%08x\n", in_be32(&ddr->debug[2])); + + /* DDR134 workaround starts */ + /* A: Clear sdram_cfg_2[odt_cfg] */ + clrbits_be32(&ddr->sdram_cfg_2, SDRAM_CFG2_ODT_CFG_MASK); + debug("Clearing SDRAM_CFG2[ODT_CFG] to 0x%08x\n", + in_be32(&ddr->sdram_cfg_2)); + + /* B: Set DEBUG1[15] */ + setbits_be32(&ddr->debug[0], 0x10000); + debug("Setting D1[15] to 0x%08x\n", in_be32(&ddr->debug[0])); + + /* C: Set timing_cfg_2[cpo] to 0b11111 */ + setbits_be32(&ddr->timing_cfg_2, TIMING_CFG_2_CPO_MASK); + debug("Setting TMING_CFG_2[CPO] to 0x%08x\n", + in_be32(&ddr->timing_cfg_2)); + + /* D: Set D6 to 0x9f9f9f9f */ + out_be32(&ddr->debug[5], 0x9f9f9f9f); + debug("Setting D6 to 0x%08x\n", in_be32(&ddr->debug[5])); + + /* E: Set D7 to 0x9f9f9f9f */ + out_be32(&ddr->debug[6], 0x9f9f9f9f); + debug("Setting D7 to 0x%08x\n", in_be32(&ddr->debug[6])); + + /* F: Set D2[20] */ + setbits_be32(&ddr->debug[1], 0x800); + debug("Setting D2[20] to 0x%08x\n", in_be32(&ddr->debug[1])); + + /* G: Poll on D2[20] until cleared */ + while (in_be32(&ddr->debug[1]) & 0x800) + udelay(10000); /* throttle polling rate */ + + /* H: Clear D1[15] */ + clrbits_be32(&ddr->debug[0], 0x10000); + debug("Setting D1[15] to 0x%08x\n", in_be32(&ddr->debug[0])); + + /* I: Set sdram_cfg_2[odt_cfg] */ + setbits_be32(&ddr->sdram_cfg_2, + regs->ddr_sdram_cfg_2 & SDRAM_CFG2_ODT_CFG_MASK); + debug("Setting sdram_cfg_2 to 0x%08x\n", in_be32(&ddr->sdram_cfg_2)); + + /* Continuing with the DDR111 workaround */ + /* 5. Set D2[21] */ + setbits_be32(&ddr->debug[1], 0x400); + debug("Setting D2[21] to 0x%08x\n", in_be32(&ddr->debug[1])); + + /* 6. Poll D2[21] until its cleared */ + while (in_be32(&ddr->debug[1]) & 0x400) + udelay(10000); /* throttle polling rate */ + + /* 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, + regs->ddr_sdram_cfg_2 & SDRAM_CFG2_D_INIT); + debug("Setting sdram_cfg_2 to 0x%08x\n", in_be32(&ddr->sdram_cfg_2)); + + /* 9. Poll until dinit is cleared */ + 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); + debug("Clearing EEBACR[3] to 0x%08x\n", in_be32(&ecm->eebacr)); + + if (csn != -1) { + csn_bnds_t = (unsigned int *) ®s->cs[csn].bnds; + *csn_bnds_t = csn_bnds_backup; + debug("Change cs%d_bnds back to 0x%08x\n", + csn, regs->cs[csn].bnds); + setbits_be32(&ddr->sdram_cfg, 0x2); /* MEM_HALT */ + switch (csn) { + case 0: + out_be32(&ddr->cs0_bnds, regs->cs[csn].bnds); + break; + case 1: + out_be32(&ddr->cs1_bnds, regs->cs[csn].bnds); + break; + case 2: + out_be32(&ddr->cs2_bnds, regs->cs[csn].bnds); + break; + case 3: + out_be32(&ddr->cs3_bnds, regs->cs[csn].bnds); + break; + } + clrbits_be32(&ddr->sdram_cfg, 0x2); } +#endif /* CONFIG_SYS_FSL_ERRATUM_DDR111_DDR134 */ }