@@ -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
@@ -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);
@@ -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
@@ -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();
}