From 54d022e76c42d824315e28ea06c89c2452f98861 Mon Sep 17 00:00:00 2001 From: SRICHARAN R Date: Fri, 8 Nov 2013 17:40:38 +0530 Subject: 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 --- arch/arm/cpu/armv7/omap-common/emif-common.c | 42 +++++++++++++++++ arch/arm/cpu/armv7/omap4/sdram_elpida.c | 5 ++ arch/arm/cpu/armv7/omap5/sdram.c | 68 ++++++++++++++++++++++++++++ arch/arm/include/asm/emif.h | 10 +++- 4 files changed, 124 insertions(+), 1 deletion(-) (limited to 'arch/arm') diff --git a/arch/arm/cpu/armv7/omap-common/emif-common.c b/arch/arm/cpu/armv7/omap-common/emif-common.c index dc1ea1d96d..5a3f2858cd 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("<