diff options
Diffstat (limited to 'arch/arm/cpu/armv7/keystone/ddr3.c')
-rw-r--r-- | arch/arm/cpu/armv7/keystone/ddr3.c | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/arch/arm/cpu/armv7/keystone/ddr3.c b/arch/arm/cpu/armv7/keystone/ddr3.c index 2391e794e8..2eabec10f9 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 |