summaryrefslogtreecommitdiff
path: root/arch/arm/cpu/armv7
diff options
context:
space:
mode:
authorSRICHARAN R <r.sricharan@ti.com>2013-11-08 17:40:38 +0530
committerTom Rini <trini@ti.com>2013-12-04 08:12:08 -0500
commit54d022e76c42d824315e28ea06c89c2452f98861 (patch)
tree7fd2255daf8be37b1a535c75358953fc7f4647a5 /arch/arm/cpu/armv7
parent6c70935d7525a4b2b144b49457d2bae85f1d111a (diff)
downloadu-boot-imx-54d022e76c42d824315e28ea06c89c2452f98861.zip
u-boot-imx-54d022e76c42d824315e28ea06c89c2452f98861.tar.gz
u-boot-imx-54d022e76c42d824315e28ea06c89c2452f98861.tar.bz2
ARM: DRA7/OMAP5: EMIF: Add workaround for bug 0039
When core power domain hits oswr, then DDR3 memories does not come back while resuming. This is because when EMIF registers are lost, then the controller takes care of copying the values from the shadow registers. If the shadow registers are not updated with the right values, then this results in incorrect settings while resuming. So updating the shadow registers with the corresponding status registers here during the boot. Signed-off-by: Sricharan R <r.sricharan@ti.com>
Diffstat (limited to 'arch/arm/cpu/armv7')
-rw-r--r--arch/arm/cpu/armv7/omap-common/emif-common.c42
-rw-r--r--arch/arm/cpu/armv7/omap4/sdram_elpida.c5
-rw-r--r--arch/arm/cpu/armv7/omap5/sdram.c68
3 files changed, 115 insertions, 0 deletions
diff --git a/arch/arm/cpu/armv7/omap-common/emif-common.c b/arch/arm/cpu/armv7/omap-common/emif-common.c
index dc1ea1d..5a3f285 100644
--- a/arch/arm/cpu/armv7/omap-common/emif-common.c
+++ b/arch/arm/cpu/armv7/omap-common/emif-common.c
@@ -1286,6 +1286,42 @@ void dmm_init(u32 base)
}
+static void do_bug0039_workaround(u32 base)
+{
+ u32 val, i, clkctrl;
+ struct emif_reg_struct *emif_base = (struct emif_reg_struct *)base;
+ const struct read_write_regs *bug_00339_regs;
+ u32 iterations;
+ u32 *phy_status_base = &emif_base->emif_ddr_phy_status[0];
+ u32 *phy_ctrl_base = &emif_base->emif_ddr_ext_phy_ctrl_1;
+
+ if (is_dra7xx())
+ phy_status_base++;
+
+ bug_00339_regs = get_bug_regs(&iterations);
+
+ /* Put EMIF in to idle */
+ clkctrl = __raw_readl((*prcm)->cm_memif_clkstctrl);
+ __raw_writel(0x0, (*prcm)->cm_memif_clkstctrl);
+
+ /* Copy the phy status registers in to phy ctrl shadow registers */
+ for (i = 0; i < iterations; i++) {
+ val = __raw_readl(phy_status_base +
+ bug_00339_regs[i].read_reg - 1);
+
+ __raw_writel(val, phy_ctrl_base +
+ ((bug_00339_regs[i].write_reg - 1) << 1));
+
+ __raw_writel(val, phy_ctrl_base +
+ (bug_00339_regs[i].write_reg << 1) - 1);
+ }
+
+ /* Disable leveling */
+ writel(0x0, &emif_base->emif_rd_wr_lvl_rmp_ctl);
+
+ __raw_writel(clkctrl, (*prcm)->cm_memif_clkstctrl);
+}
+
/*
* SDRAM initialization:
* SDRAM initialization has two parts:
@@ -1361,5 +1397,11 @@ void sdram_init(void)
debug("get_ram_size() successful");
}
+ if (sdram_type == EMIF_SDRAM_TYPE_DDR3 &&
+ (!in_sdram && !warm_reset())) {
+ do_bug0039_workaround(EMIF1_BASE);
+ do_bug0039_workaround(EMIF2_BASE);
+ }
+
debug("<<sdram_init()\n");
}
diff --git a/arch/arm/cpu/armv7/omap4/sdram_elpida.c b/arch/arm/cpu/armv7/omap4/sdram_elpida.c
index e4c8316..811e776 100644
--- a/arch/arm/cpu/armv7/omap4/sdram_elpida.c
+++ b/arch/arm/cpu/armv7/omap4/sdram_elpida.c
@@ -321,3 +321,8 @@ void get_lpddr2_mr_regs(const struct lpddr2_mr_regs **regs)
{
*regs = &mr_regs;
}
+
+__weak const struct read_write_regs *get_bug_regs(u32 *iterations)
+{
+ return 0;
+}
diff --git a/arch/arm/cpu/armv7/omap5/sdram.c b/arch/arm/cpu/armv7/omap5/sdram.c
index 2aae3ef..2e18706 100644
--- a/arch/arm/cpu/armv7/omap5/sdram.c
+++ b/arch/arm/cpu/armv7/omap5/sdram.c
@@ -569,6 +569,74 @@ static const struct lpddr2_device_timings dev_4G_S4_timings = {
.min_tck = &min_tck,
};
+/*
+ * List of status registers to be controlled back to control registers
+ * after initial leveling
+ * readreg, writereg
+ */
+const struct read_write_regs omap5_bug_00339_regs[] = {
+ { 8, 5 },
+ { 9, 6 },
+ { 10, 7 },
+ { 14, 8 },
+ { 15, 9 },
+ { 16, 10 },
+ { 11, 2 },
+ { 12, 3 },
+ { 13, 4 },
+ { 17, 11 },
+ { 18, 12 },
+ { 19, 13 },
+};
+
+const struct read_write_regs dra_bug_00339_regs[] = {
+ { 7, 7 },
+ { 8, 8 },
+ { 9, 9 },
+ { 10, 10 },
+ { 11, 11 },
+ { 12, 2 },
+ { 13, 3 },
+ { 14, 4 },
+ { 15, 5 },
+ { 16, 6 },
+ { 17, 12 },
+ { 18, 13 },
+ { 19, 14 },
+ { 20, 15 },
+ { 21, 16 },
+ { 22, 17 },
+ { 23, 18 },
+ { 24, 19 },
+ { 25, 20 },
+ { 26, 21}
+};
+
+const struct read_write_regs *get_bug_regs(u32 *iterations)
+{
+ const struct read_write_regs *bug_00339_regs_ptr = NULL;
+
+ switch (omap_revision()) {
+ case OMAP5430_ES1_0:
+ case OMAP5430_ES2_0:
+ case OMAP5432_ES1_0:
+ case OMAP5432_ES2_0:
+ bug_00339_regs_ptr = omap5_bug_00339_regs;
+ *iterations = sizeof(omap5_bug_00339_regs)/
+ sizeof(omap5_bug_00339_regs[0]);
+ break;
+ case DRA752_ES1_0:
+ bug_00339_regs_ptr = dra_bug_00339_regs;
+ *iterations = sizeof(dra_bug_00339_regs)/
+ sizeof(dra_bug_00339_regs[0]);
+ break;
+ default:
+ printf("\n Error: UnKnown SOC");
+ }
+
+ return bug_00339_regs_ptr;
+}
+
void emif_get_device_timings_sdp(u32 emif_nr,
const struct lpddr2_device_timings **cs0_device_timings,
const struct lpddr2_device_timings **cs1_device_timings)