From: Murali Karicheri <m-kariche...@ti.com>

This patch implements a workaround to fix DDR3 memory issue.
The code for workaround detects PGSR0 errors and then preps for
and executes a software-controlled hard reset.In board_early_init,
where logic has been added to identify whether or not the previous
reset was a PORz. PLL initialization is skipped in the case of a
software-controlled hard reset.

Signed-off-by: Murali Karicheri <m-kariche...@ti.com>
Signed-off-by: Keegan Garcia <kgar...@ti.com>
Signed-off-by: Ivan Khoronzhuk <ivan.khoronz...@ti.com>
---

Based on
"[U-boot] [Patch v2 0/6] keystone2: add k2l SoC and k2l_evm board support"
https://www.mail-archive.com/u-boot@lists.denx.de/msg146721.html

v2..v1
        Moved ddr3_err_reset_workaround() under CONFIG_SOC_K2HK
        No functional changes

 arch/arm/cpu/armv7/keystone/ddr3.c            | 75 +++++++++++++++++++++++++++
 arch/arm/include/asm/arch-keystone/ddr3.h     |  1 +
 arch/arm/include/asm/arch-keystone/hardware.h |  2 +
 board/ti/ks2_evm/ddr3_k2hk.c                  |  4 ++
 4 files changed, 82 insertions(+)

diff --git a/arch/arm/cpu/armv7/keystone/ddr3.c 
b/arch/arm/cpu/armv7/keystone/ddr3.c
index 2391e79..2eabec1 100644
--- a/arch/arm/cpu/armv7/keystone/ddr3.c
+++ b/arch/arm/cpu/armv7/keystone/ddr3.c
@@ -10,6 +10,7 @@
 #include <asm/io.h>
 #include <common.h>
 #include <asm/arch/ddr3.h>
+#include <asm/arch/psc_defs.h>
 
 void ddr3_init_ddrphy(u32 base, struct ddr3_phy_config *phy_cfg)
 {
@@ -86,3 +87,77 @@ void ddr3_reset_ddrphy(void)
        tmp &= ~KS2_DDR3_PLLCTRL_PHY_RESET;
        __raw_writel(tmp, KS2_DDR3APLLCTL1);
 }
+
+#ifdef CONFIG_SOC_K2HK
+/**
+ * ddr3_reset_workaround - reset workaround in case if leveling error
+ * detected for PG 1.0 and 1.1 k2hk SoCs
+ */
+void ddr3_err_reset_workaround(void)
+{
+       unsigned int tmp;
+       unsigned int tmp_a;
+       unsigned int tmp_b;
+
+       /*
+        * Check for PGSR0 error bits of DDR3 PHY.
+        * Check for WLERR, QSGERR, WLAERR,
+        * RDERR, WDERR, REERR, WEERR error to see if they are set or not
+        */
+       tmp_a = __raw_readl(KS2_DDR3A_DDRPHYC + KS2_DDRPHY_PGSR0_OFFSET);
+       tmp_b = __raw_readl(KS2_DDR3B_DDRPHYC + KS2_DDRPHY_PGSR0_OFFSET);
+
+       if (((tmp_a & 0x0FE00000) != 0) || ((tmp_b & 0x0FE00000) != 0)) {
+               printf("DDR Leveling Error Detected!\n");
+               printf("DDR3A PGSR0 = 0x%x\n", tmp_a);
+               printf("DDR3B PGSR0 = 0x%x\n", tmp_b);
+
+               /*
+                * Write Keys to KICK registers to enable writes to registers
+                * in boot config space
+                */
+               __raw_writel(KS2_KICK0_MAGIC, KS2_KICK0);
+               __raw_writel(KS2_KICK1_MAGIC, KS2_KICK1);
+
+               /*
+                * Move DDR3A Module out of reset isolation by setting
+                * MDCTL23[12] = 0
+                */
+               tmp_a = __raw_readl(KS2_PSC_BASE +
+                                   PSC_REG_MDCTL(KS2_LPSC_EMIF4F_DDR3A));
+
+               tmp_a = PSC_REG_MDCTL_SET_RESET_ISO(tmp_a, 0);
+               __raw_writel(tmp_a, KS2_PSC_BASE +
+                            PSC_REG_MDCTL(KS2_LPSC_EMIF4F_DDR3A));
+
+               /*
+                * Move DDR3B Module out of reset isolation by setting
+                * MDCTL24[12] = 0
+                */
+               tmp_b = __raw_readl(KS2_PSC_BASE +
+                                   PSC_REG_MDCTL(KS2_LPSC_EMIF4F_DDR3B));
+               tmp_b = PSC_REG_MDCTL_SET_RESET_ISO(tmp_b, 0);
+               __raw_writel(tmp_b, KS2_PSC_BASE +
+                            PSC_REG_MDCTL(KS2_LPSC_EMIF4F_DDR3B));
+
+               /*
+                * Write 0x5A69 Key to RSTCTRL[15:0] to unlock writes
+                * to RSTCTRL and RSTCFG
+                */
+               tmp = __raw_readl(KS2_RSTCTRL);
+               tmp &= KS2_RSTCTRL_MASK;
+               tmp |= KS2_RSTCTRL_KEY;
+               __raw_writel(tmp, KS2_RSTCTRL);
+
+               /*
+                * Set PLL Controller to drive hard reset on SW trigger by
+                * setting RSTCFG[13] = 0
+                */
+               tmp = __raw_readl(KS2_RSTCTRL_RSCFG);
+               tmp &= ~KS2_RSTYPE_PLL_SOFT;
+               __raw_writel(tmp, KS2_RSTCTRL_RSCFG);
+
+               reset_cpu(0);
+       }
+}
+#endif
diff --git a/arch/arm/include/asm/arch-keystone/ddr3.h 
b/arch/arm/include/asm/arch-keystone/ddr3.h
index 4d229a2..6bf35d3 100644
--- a/arch/arm/include/asm/arch-keystone/ddr3.h
+++ b/arch/arm/include/asm/arch-keystone/ddr3.h
@@ -50,6 +50,7 @@ struct ddr3_emif_config {
 
 void ddr3_init(void);
 void ddr3_reset_ddrphy(void);
+void ddr3_err_reset_workaround(void);
 void ddr3_init_ddrphy(u32 base, struct ddr3_phy_config *phy_cfg);
 void ddr3_init_ddremif(u32 base, struct ddr3_emif_config *emif_cfg);
 
diff --git a/arch/arm/include/asm/arch-keystone/hardware.h 
b/arch/arm/include/asm/arch-keystone/hardware.h
index 2eec4e7..29f7bf1 100644
--- a/arch/arm/include/asm/arch-keystone/hardware.h
+++ b/arch/arm/include/asm/arch-keystone/hardware.h
@@ -121,9 +121,11 @@ typedef volatile unsigned int   *dv_reg_p;
 #define KS2_CLOCK_BASE                 KS2_PLL_CNTRL_BASE
 #define KS2_RSTCTRL_RSTYPE             (KS2_PLL_CNTRL_BASE + 0xe4)
 #define KS2_RSTCTRL                    (KS2_PLL_CNTRL_BASE + 0xe8)
+#define KS2_RSTCTRL_RSCFG              (KS2_PLL_CNTRL_BASE + 0xec)
 #define KS2_RSTCTRL_KEY                        0x5a69
 #define KS2_RSTCTRL_MASK               0xffff0000
 #define KS2_RSTCTRL_SWRST              0xfffe0000
+#define KS2_RSTYPE_PLL_SOFT            BIT(13)
 
 /* SPI */
 #define KS2_SPI0_BASE                  0x21000400
diff --git a/board/ti/ks2_evm/ddr3_k2hk.c b/board/ti/ks2_evm/ddr3_k2hk.c
index 21a5a0a..6070a99 100644
--- a/board/ti/ks2_evm/ddr3_k2hk.c
+++ b/board/ti/ks2_evm/ddr3_k2hk.c
@@ -81,4 +81,8 @@ void ddr3_init(void)
                while (1)
                        ;
        }
+
+       /* Apply the workaround for PG 1.0 and 1.1 Silicons */
+       if (cpu_revision() <= 1)
+               ddr3_err_reset_workaround();
 }
-- 
1.8.3.2

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to