]> git.kernelconcepts.de Git - karo-tx-uboot.git/commitdiff
ARM: DRA7/OMAP5: EMIF: Add workaround for bug 0039
authorSRICHARAN R <r.sricharan@ti.com>
Fri, 8 Nov 2013 12:10:38 +0000 (17:40 +0530)
committerTom Rini <trini@ti.com>
Wed, 4 Dec 2013 13:12:08 +0000 (08:12 -0500)
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>
arch/arm/cpu/armv7/omap-common/emif-common.c
arch/arm/cpu/armv7/omap4/sdram_elpida.c
arch/arm/cpu/armv7/omap5/sdram.c
arch/arm/include/asm/emif.h

index dc1ea1d96d8f06e10b76f38f294ac5ca416c05c1..5a3f2858cda7d1d152aae202874acd60a83ab8b0 100644 (file)
@@ -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");
 }
index e4c8316370955355f0506af6b46d1ee158e17ab3..811e7764c1bfcae8a88ecf07c2ef10c5112a1607 100644 (file)
@@ -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;
+}
index 2aae3efb7100d4bc5dad28ca6a2dc189ffbfe6c1..2e1870609a4b78589ef2f3d456d320ec08f372b0 100644 (file)
@@ -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)
index c12beea0cab8c49903aa541cd00794978bd7ca51..d9d521a51505728eff9e04674516aba66ce3b222 100644 (file)
@@ -640,7 +640,9 @@ struct emif_reg_struct {
        u32 emif_ddr_phy_ctrl_2;
        u32 padding7[12];
        u32 emif_rd_wr_exec_thresh;
-       u32 padding8[55];
+       u32 padding8[7];
+       u32 emif_ddr_phy_status[21];
+       u32 padding9[27];
        u32 emif_ddr_ext_phy_ctrl_1;
        u32 emif_ddr_ext_phy_ctrl_1_shdw;
        u32 emif_ddr_ext_phy_ctrl_2;
@@ -1141,6 +1143,11 @@ struct lpddr2_mr_regs {
        s8 mr16;
 };
 
+struct read_write_regs {
+       u32 read_reg;
+       u32 write_reg;
+};
+
 /* assert macros */
 #if defined(DEBUG)
 #define emif_assert(c) ({ if (!(c)) for (;;); })
@@ -1169,4 +1176,5 @@ extern u32 *const T_den;
 
 void config_data_eye_leveling_samples(u32 emif_base);
 u32 emif_sdram_type(void);
+const struct read_write_regs *get_bug_regs(u32 *iterations);
 #endif