public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
* [U-Boot] [PATCH 0/2] OMAP5/DRA7: EMIF fixes for lowpower usecases
@ 2013-11-07 14:47 Sricharan R
  2013-11-07 14:47 ` [U-Boot] [PATCH 1/2] ARM: DRA: EMIF: Change DDR3 settings to use hw leveling Sricharan R
  2013-11-07 14:47 ` [U-Boot] [PATCH 2/2] ARM: DRA7/OMAP5: EMIF: Add workaround for bug 0039 Sricharan R
  0 siblings, 2 replies; 5+ messages in thread
From: Sricharan R @ 2013-11-07 14:47 UTC (permalink / raw)
  To: u-boot

1)  Currently the DDR3 memory on DRA7 ES1.0 evm board is enabled using
    software leveling. This was done since hardware leveling was not
    working. Now that the right sequence to do hw leveling is identified,
    use it. This is required for EMIF clockdomain to idle and come back
    during lowpower usecases

2)  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.

Sricharan R (2):
  ARM: DRA: EMIF: Change DDR3 settings to use hw leveling
  ARM: DRA7/OMAP5: EMIF: Add workaround for bug 0039

 arch/arm/cpu/armv7/omap-common/emif-common.c |  174 ++++++++++++++-------
 arch/arm/cpu/armv7/omap5/hw_data.c           |    9 +-
 arch/arm/cpu/armv7/omap5/hwinit.c            |   12 +-
 arch/arm/cpu/armv7/omap5/sdram.c             |  215 ++++++++++++++++++--------
 arch/arm/include/asm/arch-omap5/omap.h       |    1 +
 arch/arm/include/asm/emif.h                  |   14 +-
 6 files changed, 301 insertions(+), 124 deletions(-)

-- 
1.7.9.5

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [U-Boot] [PATCH 1/2] ARM: DRA: EMIF: Change DDR3 settings to use hw leveling
  2013-11-07 14:47 [U-Boot] [PATCH 0/2] OMAP5/DRA7: EMIF fixes for lowpower usecases Sricharan R
@ 2013-11-07 14:47 ` Sricharan R
  2013-11-07 15:03   ` Tom Rini
  2013-11-07 14:47 ` [U-Boot] [PATCH 2/2] ARM: DRA7/OMAP5: EMIF: Add workaround for bug 0039 Sricharan R
  1 sibling, 1 reply; 5+ messages in thread
From: Sricharan R @ 2013-11-07 14:47 UTC (permalink / raw)
  To: u-boot

Currently the DDR3 memory on DRA7 ES1.0 evm board is enabled using
software leveling. This was done since hardware leveling was not
working. Now that the right sequence to do hw leveling is identified,
use it. This is required for EMIF clockdomain to idle and come back
during lowpower usecases.

Signed-off-by: Sricharan R <r.sricharan@ti.com>
---
 arch/arm/cpu/armv7/omap-common/emif-common.c |  133 +++++++++++++----------
 arch/arm/cpu/armv7/omap5/hw_data.c           |    9 +-
 arch/arm/cpu/armv7/omap5/hwinit.c            |   12 ++-
 arch/arm/cpu/armv7/omap5/sdram.c             |  146 +++++++++++++++-----------
 arch/arm/include/asm/arch-omap5/omap.h       |    1 +
 arch/arm/include/asm/emif.h                  |    4 +-
 6 files changed, 182 insertions(+), 123 deletions(-)

diff --git a/arch/arm/cpu/armv7/omap-common/emif-common.c b/arch/arm/cpu/armv7/omap-common/emif-common.c
index b0e1caa..c1f5838 100644
--- a/arch/arm/cpu/armv7/omap-common/emif-common.c
+++ b/arch/arm/cpu/armv7/omap-common/emif-common.c
@@ -210,54 +210,76 @@ static void ddr3_leveling(u32 base, const struct emif_regs *regs)
 {
 	struct emif_reg_struct *emif = (struct emif_reg_struct *)base;
 
-	/* keep sdram in self-refresh */
-	writel(((LP_MODE_SELF_REFRESH << EMIF_REG_LP_MODE_SHIFT)
-		& EMIF_REG_LP_MODE_MASK), &emif->emif_pwr_mgmt_ctrl);
-	__udelay(130);
-
-	/*
-	 * Set invert_clkout (if activated)--DDR_PHYCTRL_1
-	 * Invert clock adds an additional half cycle delay on the command
-	 * interface.  The additional half cycle, is usually meant to enable
-	 * leveling in the situation that DQS is later than CK on the board.It
-	 * also helps provide some additional margin for leveling.
-	 */
-	writel(regs->emif_ddr_phy_ctlr_1, &emif->emif_ddr_phy_ctrl_1);
-	writel(regs->emif_ddr_phy_ctlr_1, &emif->emif_ddr_phy_ctrl_1_shdw);
-	__udelay(130);
-
-	writel(((LP_MODE_DISABLE << EMIF_REG_LP_MODE_SHIFT)
-		& EMIF_REG_LP_MODE_MASK), &emif->emif_pwr_mgmt_ctrl);
-
-	/* Launch Full leveling */
-	writel(DDR3_FULL_LVL, &emif->emif_rd_wr_lvl_ctl);
+	if (omap_revision() != DRA752_ES1_0)	{
+		/* keep sdram in self-refresh */
+		writel(((LP_MODE_SELF_REFRESH << EMIF_REG_LP_MODE_SHIFT)
+			& EMIF_REG_LP_MODE_MASK), &emif->emif_pwr_mgmt_ctrl);
+		__udelay(130);
+
+		/*
+		 * Set invert_clkout (if activated)--DDR_PHYCTRL_1
+		 * Invert clock adds an additional half cycle delay on the
+		 * command interface.  The additional half cycle, is usually
+		 * meant to enable leveling in the situation that DQS is later
+		 * than CK on the board.It also helps provide some additional
+		 * margin for leveling.
+		 */
+		writel(regs->emif_ddr_phy_ctlr_1,
+		       &emif->emif_ddr_phy_ctrl_1);
+
+		writel(regs->emif_ddr_phy_ctlr_1,
+		       &emif->emif_ddr_phy_ctrl_1_shdw);
+		__udelay(130);
+
+		writel(((LP_MODE_DISABLE << EMIF_REG_LP_MODE_SHIFT)
+			& EMIF_REG_LP_MODE_MASK), &emif->emif_pwr_mgmt_ctrl);
+
+		/* Launch Full leveling */
+		writel(DDR3_FULL_LVL, &emif->emif_rd_wr_lvl_ctl);
+
+		/* Wait till full leveling is complete */
+		readl(&emif->emif_rd_wr_lvl_ctl);
+		__udelay(130);
+
+		/* Read data eye leveling no of samples */
+		config_data_eye_leveling_samples(base);
+
+		/*
+		 * Launch 8 incremental WR_LVL- to compensate for
+		 * PHY limitation.
+		 */
+		writel(0x2 << EMIF_REG_WRLVLINC_INT_SHIFT,
+		       &emif->emif_rd_wr_lvl_ctl);
+
+		__udelay(130);
+
+		/* Launch Incremental leveling */
+		writel(DDR3_INC_LVL, &emif->emif_rd_wr_lvl_ctl);
+		__udelay(130);
+	} else {
+		u32 fifo_reg;
 
-	/* Wait till full leveling is complete */
-	readl(&emif->emif_rd_wr_lvl_ctl);
-	__udelay(130);
+		fifo_reg = readl(&emif->emif_ddr_fifo_misaligned_clear_1);
+		writel(fifo_reg | 0x00000100,
+		       &emif->emif_ddr_fifo_misaligned_clear_1);
 
-	/* Read data eye leveling no of samples */
-	config_data_eye_leveling_samples(base);
+		fifo_reg = readl(&emif->emif_ddr_fifo_misaligned_clear_2);
+		writel(fifo_reg | 0x00000100,
+		       &emif->emif_ddr_fifo_misaligned_clear_2);
 
-	/* Launch 8 incremental WR_LVL- to compensate for PHY limitation */
-	writel(0x2 << EMIF_REG_WRLVLINC_INT_SHIFT, &emif->emif_rd_wr_lvl_ctl);
-	__udelay(130);
+		/* Launch Full leveling */
+		writel(DDR3_FULL_LVL, &emif->emif_rd_wr_lvl_ctl);
 
-	/* Launch Incremental leveling */
-	writel(DDR3_INC_LVL, &emif->emif_rd_wr_lvl_ctl);
-	__udelay(130);
-}
+		/* Wait till full leveling is complete */
+		readl(&emif->emif_rd_wr_lvl_ctl);
+		__udelay(130);
 
-static void ddr3_sw_leveling(u32 base, const struct emif_regs *regs)
-{
-	struct emif_reg_struct *emif = (struct emif_reg_struct *)base;
-
-	writel(regs->emif_ddr_phy_ctlr_1, &emif->emif_ddr_phy_ctrl_1);
-	writel(regs->emif_ddr_phy_ctlr_1, &emif->emif_ddr_phy_ctrl_1_shdw);
-	config_data_eye_leveling_samples(base);
+		/* Read data eye leveling no of samples */
+		config_data_eye_leveling_samples(base);
 
-	writel(regs->emif_rd_wr_lvl_ctl, &emif->emif_rd_wr_lvl_ctl);
-	writel(regs->sdram_config, &emif->emif_sdram_config);
+		/* Disable leveling */
+		writel(0x0, &emif->emif_rd_wr_lvl_rmp_ctl);
+	}
 }
 
 static void ddr3_init(u32 base, const struct emif_regs *regs)
@@ -270,9 +292,6 @@ static void ddr3_init(u32 base, const struct emif_regs *regs)
 	 * defined, contents of mode Registers must be fully initialized.
 	 * H/W takes care of this initialization
 	 */
-	writel(regs->sdram_config2, &emif->emif_lpddr2_nvm_config);
-	writel(regs->sdram_config_init, &emif->emif_sdram_config);
-
 	writel(regs->emif_ddr_phy_ctlr_1_init, &emif->emif_ddr_phy_ctrl_1);
 
 	/* Update timing registers */
@@ -283,15 +302,24 @@ static void ddr3_init(u32 base, const struct emif_regs *regs)
 	writel(regs->ref_ctrl, &emif->emif_sdram_ref_ctrl);
 	writel(regs->read_idle_ctrl, &emif->emif_read_idlectrl);
 
-	do_ext_phy_settings(base, regs);
+	/*
+	 * The same sequence should work on OMAP5432 as well. But strange that
+	 * it is not working
+	 */
+	if (omap_revision() == DRA752_ES1_0) {
+		do_ext_phy_settings(base, regs);
+		writel(regs->sdram_config2, &emif->emif_lpddr2_nvm_config);
+		writel(regs->sdram_config_init, &emif->emif_sdram_config);
+	} else {
+		writel(regs->sdram_config2, &emif->emif_lpddr2_nvm_config);
+		writel(regs->sdram_config_init, &emif->emif_sdram_config);
+		do_ext_phy_settings(base, regs);
+	}
 
 	/* enable leveling */
 	writel(regs->emif_rd_wr_lvl_rmp_ctl, &emif->emif_rd_wr_lvl_rmp_ctl);
 
-	if (omap_revision() == DRA752_ES1_0)
-		ddr3_sw_leveling(base, regs);
-	else
-		ddr3_leveling(base, regs);
+	ddr3_leveling(base, regs);
 }
 
 #ifndef CONFIG_SYS_EMIF_PRECALCULATED_TIMING_REGS
@@ -1079,10 +1107,7 @@ static void do_sdram_init(u32 base)
 	if (warm_reset() && (emif_sdram_type() == EMIF_SDRAM_TYPE_DDR3)) {
 		set_lpmode_selfrefresh(base);
 		emif_reset_phy(base);
-		if (omap_revision() == DRA752_ES1_0)
-			ddr3_sw_leveling(base, regs);
-		else
-			ddr3_leveling(base, regs);
+		ddr3_leveling(base, regs);
 	}
 
 	/* Write to the shadow registers */
diff --git a/arch/arm/cpu/armv7/omap5/hw_data.c b/arch/arm/cpu/armv7/omap5/hw_data.c
index a1b249e..82910e8 100644
--- a/arch/arm/cpu/armv7/omap5/hw_data.c
+++ b/arch/arm/cpu/armv7/omap5/hw_data.c
@@ -600,6 +600,7 @@ const struct ctrl_ioregs ioregs_omap5432_es1 = {
 	.ctrl_ddrio_1 = DDR_IO_1_VREF_CELLS_DDR3_VALUE,
 	.ctrl_ddrio_2 = DDR_IO_2_VREF_CELLS_DDR3_VALUE,
 	.ctrl_emif_sdram_config_ext = SDRAM_CONFIG_EXT_RD_LVL_11_SAMPLES,
+	.ctrl_emif_sdram_config_ext_final = SDRAM_CONFIG_EXT_RD_LVL_4_SAMPLES,
 };
 
 const struct ctrl_ioregs ioregs_omap5432_es2 = {
@@ -610,16 +611,18 @@ const struct ctrl_ioregs ioregs_omap5432_es2 = {
 	.ctrl_ddrio_1 = DDR_IO_1_VREF_CELLS_DDR3_VALUE_ES2,
 	.ctrl_ddrio_2 = DDR_IO_2_VREF_CELLS_DDR3_VALUE_ES2,
 	.ctrl_emif_sdram_config_ext = SDRAM_CONFIG_EXT_RD_LVL_11_SAMPLES,
+	.ctrl_emif_sdram_config_ext_final = SDRAM_CONFIG_EXT_RD_LVL_4_SAMPLES,
 };
 
 const struct ctrl_ioregs ioregs_dra7xx_es1 = {
 	.ctrl_ddrch = 0x40404040,
 	.ctrl_lpddr2ch = 0x40404040,
 	.ctrl_ddr3ch = 0x80808080,
-	.ctrl_ddrio_0 = 0xbae8c631,
-	.ctrl_ddrio_1 = 0xb46318d8,
+	.ctrl_ddrio_0 = 0xA2084210,
+	.ctrl_ddrio_1 = 0x84210840,
 	.ctrl_ddrio_2 = 0x84210000,
-	.ctrl_emif_sdram_config_ext = 0xb2c00000,
+	.ctrl_emif_sdram_config_ext = 0x0001C1A7,
+	.ctrl_emif_sdram_config_ext_final = 0x000101A7,
 	.ctrl_ddr_ctrl_ext_0 = 0xA2000000,
 };
 
diff --git a/arch/arm/cpu/armv7/omap5/hwinit.c b/arch/arm/cpu/armv7/omap5/hwinit.c
index 1065891..82c8638 100644
--- a/arch/arm/cpu/armv7/omap5/hwinit.c
+++ b/arch/arm/cpu/armv7/omap5/hwinit.c
@@ -297,13 +297,17 @@ void srcomp_enable(void)
 
 void config_data_eye_leveling_samples(u32 emif_base)
 {
+	const struct ctrl_ioregs *ioregs;
+
+	get_ioregs(&ioregs);
+
 	/*EMIF_SDRAM_CONFIG_EXT-Read data eye leveling no of samples =4*/
 	if (emif_base == EMIF1_BASE)
-		writel(SDRAM_CONFIG_EXT_RD_LVL_4_SAMPLES,
-			(*ctrl)->control_emif1_sdram_config_ext);
+		writel(ioregs->ctrl_emif_sdram_config_ext_final,
+		       (*ctrl)->control_emif1_sdram_config_ext);
 	else if (emif_base == EMIF2_BASE)
-		writel(SDRAM_CONFIG_EXT_RD_LVL_4_SAMPLES,
-			(*ctrl)->control_emif2_sdram_config_ext);
+		writel(ioregs->ctrl_emif_sdram_config_ext_final,
+		       (*ctrl)->control_emif2_sdram_config_ext);
 }
 
 void init_omap_revision(void)
diff --git a/arch/arm/cpu/armv7/omap5/sdram.c b/arch/arm/cpu/armv7/omap5/sdram.c
index e65c116..2aae3ef 100644
--- a/arch/arm/cpu/armv7/omap5/sdram.c
+++ b/arch/arm/cpu/armv7/omap5/sdram.c
@@ -148,13 +148,13 @@ const struct emif_regs emif_1_regs_ddr3_532_mhz_1cs_dra_es1 = {
 	.read_idle_ctrl                 = 0x00050000,
 	.zq_config                      = 0x0007190B,
 	.temp_alert_config              = 0x00000000,
-	.emif_ddr_phy_ctlr_1_init       = 0x0E20400A,
-	.emif_ddr_phy_ctlr_1            = 0x0E24400A,
-	.emif_ddr_ext_phy_ctrl_1        = 0x04040100,
-	.emif_ddr_ext_phy_ctrl_2        = 0x009E009E,
-	.emif_ddr_ext_phy_ctrl_3        = 0x009E009E,
-	.emif_ddr_ext_phy_ctrl_4        = 0x009E009E,
-	.emif_ddr_ext_phy_ctrl_5        = 0x009E009E,
+	.emif_ddr_phy_ctlr_1_init       = 0x0024400A,
+	.emif_ddr_phy_ctlr_1            = 0x0024400A,
+	.emif_ddr_ext_phy_ctrl_1        = 0x10040100,
+	.emif_ddr_ext_phy_ctrl_2        = 0x00B000B0,
+	.emif_ddr_ext_phy_ctrl_3        = 0x00B000B0,
+	.emif_ddr_ext_phy_ctrl_4        = 0x00B000B0,
+	.emif_ddr_ext_phy_ctrl_5        = 0x00B000B0,
 	.emif_rd_wr_lvl_rmp_win         = 0x00000000,
 	.emif_rd_wr_lvl_rmp_ctl         = 0x80000000,
 	.emif_rd_wr_lvl_ctl             = 0x00000000,
@@ -172,13 +172,13 @@ const struct emif_regs emif_2_regs_ddr3_532_mhz_1cs_dra_es1 = {
 	.read_idle_ctrl                 = 0x00050000,
 	.zq_config                      = 0x0007190B,
 	.temp_alert_config              = 0x00000000,
-	.emif_ddr_phy_ctlr_1_init       = 0x0020400A,
-	.emif_ddr_phy_ctlr_1            = 0x0E24400A,
-	.emif_ddr_ext_phy_ctrl_1        = 0x04040100,
-	.emif_ddr_ext_phy_ctrl_2        = 0x009D009D,
-	.emif_ddr_ext_phy_ctrl_3        = 0x009D009D,
-	.emif_ddr_ext_phy_ctrl_4        = 0x009D009D,
-	.emif_ddr_ext_phy_ctrl_5        = 0x009D009D,
+	.emif_ddr_phy_ctlr_1_init       = 0x0024400A,
+	.emif_ddr_phy_ctlr_1            = 0x0024400A,
+	.emif_ddr_ext_phy_ctrl_1        = 0x10040100,
+	.emif_ddr_ext_phy_ctrl_2        = 0x00B000B0,
+	.emif_ddr_ext_phy_ctrl_3        = 0x00B000B0,
+	.emif_ddr_ext_phy_ctrl_4        = 0x00B000B0,
+	.emif_ddr_ext_phy_ctrl_5        = 0x00B000B0,
 	.emif_rd_wr_lvl_rmp_win         = 0x00000000,
 	.emif_rd_wr_lvl_rmp_ctl         = 0x80000000,
 	.emif_rd_wr_lvl_ctl             = 0x00000000,
@@ -306,7 +306,7 @@ void emif_get_device_details(u32 emif_nr,
 
 #endif /* CONFIG_SYS_EMIF_PRECALCULATED_TIMING_REGS */
 
-const u32 ext_phy_ctrl_const_base[EMIF_EXT_PHY_CTRL_CONST_REG] = {
+const u32 ext_phy_ctrl_const_base[] = {
 	0x01004010,
 	0x00001004,
 	0x04010040,
@@ -329,7 +329,7 @@ const u32 ext_phy_ctrl_const_base[EMIF_EXT_PHY_CTRL_CONST_REG] = {
 	0x0
 };
 
-const u32 ddr3_ext_phy_ctrl_const_base_es1[EMIF_EXT_PHY_CTRL_CONST_REG] = {
+const u32 ddr3_ext_phy_ctrl_const_base_es1[] = {
 	0x01004010,
 	0x00001004,
 	0x04010040,
@@ -352,7 +352,7 @@ const u32 ddr3_ext_phy_ctrl_const_base_es1[EMIF_EXT_PHY_CTRL_CONST_REG] = {
 	0x0
 };
 
-const u32 ddr3_ext_phy_ctrl_const_base_es2[EMIF_EXT_PHY_CTRL_CONST_REG] = {
+const u32 ddr3_ext_phy_ctrl_const_base_es2[] = {
 	0x50D4350D,
 	0x00000D43,
 	0x04010040,
@@ -376,51 +376,61 @@ const u32 ddr3_ext_phy_ctrl_const_base_es2[EMIF_EXT_PHY_CTRL_CONST_REG] = {
 };
 
 const u32
-dra_ddr3_ext_phy_ctrl_const_base_es1_emif1[EMIF_EXT_PHY_CTRL_CONST_REG] = {
-	0x009E009E,
-	0x002E002E,
-	0x002E002E,
-	0x002E002E,
-	0x002E002E,
-	0x002E002E,
-	0x004D004D,
-	0x004D004D,
-	0x004D004D,
-	0x004D004D,
-	0x004D004D,
-	0x004D004D,
-	0x004D004D,
-	0x004D004D,
-	0x004D004D,
-	0x004D004D,
-	0x0,
-	0x600020,
+dra_ddr3_ext_phy_ctrl_const_base_es1_emif1[] = {
+	0x00B000B0,
+	0x00400040,
+	0x00400040,
+	0x00400040,
+	0x00400040,
+	0x00400040,
+	0x00800080,
+	0x00800080,
+	0x00800080,
+	0x00800080,
+	0x00800080,
+	0x00600060,
+	0x00600060,
+	0x00600060,
+	0x00600060,
+	0x00600060,
+	0x00800080,
+	0x00800080,
 	0x40010080,
-	0x8102040
+	0x08102040,
+	0x0,
+	0x0,
+	0x0,
+	0x0,
+	0x0
 };
 
 const u32
-dra_ddr3_ext_phy_ctrl_const_base_es1_emif2[EMIF_EXT_PHY_CTRL_CONST_REG] = {
-	0x009D009D,
-	0x002D002D,
-	0x002D002D,
-	0x002D002D,
-	0x002D002D,
-	0x002D002D,
-	0x00570057,
-	0x00570057,
-	0x00570057,
-	0x00570057,
-	0x00570057,
-	0x00570057,
-	0x00570057,
-	0x00570057,
-	0x00570057,
-	0x00570057,
+dra_ddr3_ext_phy_ctrl_const_base_es1_emif2[] = {
+	0x00BB00BB,
+	0x00440044,
+	0x00440044,
+	0x00440044,
+	0x00440044,
+	0x00440044,
+	0x007F007F,
+	0x007F007F,
+	0x007F007F,
+	0x007F007F,
+	0x007F007F,
+	0x00600060,
+	0x00600060,
+	0x00600060,
+	0x00600060,
+	0x00600060,
 	0x0,
-	0x600020,
+	0x00600020,
 	0x40010080,
-	0x8102040
+	0x08102040,
+	0x0,
+	0x0,
+	0x0,
+	0x0,
+	0x0
 };
 
 const struct lpddr2_mr_regs mr_regs = {
@@ -431,27 +441,38 @@ const struct lpddr2_mr_regs mr_regs = {
 	.mr16	= MR16_REF_FULL_ARRAY
 };
 
-static void emif_get_ext_phy_ctrl_const_regs(u32 emif_nr, const u32 **regs)
+static void emif_get_ext_phy_ctrl_const_regs(u32 emif_nr,
+					     const u32 **regs,
+					     u32 *size)
 {
 	switch (omap_revision()) {
 	case OMAP5430_ES1_0:
 	case OMAP5430_ES2_0:
 		*regs = ext_phy_ctrl_const_base;
+		*size = ARRAY_SIZE(ext_phy_ctrl_const_base);
 		break;
 	case OMAP5432_ES1_0:
 		*regs = ddr3_ext_phy_ctrl_const_base_es1;
+		*size = ARRAY_SIZE(ddr3_ext_phy_ctrl_const_base_es1);
 		break;
 	case OMAP5432_ES2_0:
 		*regs = ddr3_ext_phy_ctrl_const_base_es2;
+		*size = ARRAY_SIZE(ddr3_ext_phy_ctrl_const_base_es2);
 		break;
 	case DRA752_ES1_0:
-		if (emif_nr == 1)
+		if (emif_nr == 1) {
 			*regs = dra_ddr3_ext_phy_ctrl_const_base_es1_emif1;
-		else
+			*size =
+			ARRAY_SIZE(dra_ddr3_ext_phy_ctrl_const_base_es1_emif1);
+		} else {
 			*regs = dra_ddr3_ext_phy_ctrl_const_base_es1_emif2;
+			*size =
+			ARRAY_SIZE(dra_ddr3_ext_phy_ctrl_const_base_es1_emif2);
+		}
 		break;
 	default:
 		*regs = ddr3_ext_phy_ctrl_const_base_es2;
+		*size = ARRAY_SIZE(ddr3_ext_phy_ctrl_const_base_es2);
 
 	}
 }
@@ -468,6 +489,7 @@ void do_ext_phy_settings(u32 base, const struct emif_regs *regs)
 	u32 emif_nr;
 	const u32 *ext_phy_ctrl_const_regs;
 	u32 i = 0;
+	u32 size;
 
 	emif_nr = (base == EMIF1_BASE) ? 1 : 2;
 
@@ -487,8 +509,10 @@ void do_ext_phy_settings(u32 base, const struct emif_regs *regs)
 	 * external phy 6-24 registers do not change with
 	 * ddr frequency
 	 */
-	emif_get_ext_phy_ctrl_const_regs(emif_nr, &ext_phy_ctrl_const_regs);
-	for (i = 0; i < EMIF_EXT_PHY_CTRL_CONST_REG; i++) {
+	emif_get_ext_phy_ctrl_const_regs(emif_nr,
+					 &ext_phy_ctrl_const_regs, &size);
+
+	for (i = 0; i < size; i++) {
 		writel(ext_phy_ctrl_const_regs[i],
 		       emif_ext_phy_ctrl_base++);
 		/* Update shadow registers */
diff --git a/arch/arm/include/asm/arch-omap5/omap.h b/arch/arm/include/asm/arch-omap5/omap.h
index 414d37a..92aebe5 100644
--- a/arch/arm/include/asm/arch-omap5/omap.h
+++ b/arch/arm/include/asm/arch-omap5/omap.h
@@ -239,6 +239,7 @@ struct ctrl_ioregs {
 	u32 ctrl_ddrio_1;
 	u32 ctrl_ddrio_2;
 	u32 ctrl_emif_sdram_config_ext;
+	u32 ctrl_emif_sdram_config_ext_final;
 	u32 ctrl_ddr_ctrl_ext_0;
 };
 
diff --git a/arch/arm/include/asm/emif.h b/arch/arm/include/asm/emif.h
index 1b94a99..c12beea 100644
--- a/arch/arm/include/asm/emif.h
+++ b/arch/arm/include/asm/emif.h
@@ -581,7 +581,6 @@
 	(0xFF << EMIF_SYS_ADDR_SHIFT))
 
 #define EMIF_EXT_PHY_CTRL_TIMING_REG	0x5
-#define EMIF_EXT_PHY_CTRL_CONST_REG	0x14
 
 /* Reg mapping structure */
 struct emif_reg_struct {
@@ -690,6 +689,9 @@ struct emif_reg_struct {
 	u32 emif_ddr_ext_phy_ctrl_23_shdw;
 	u32 emif_ddr_ext_phy_ctrl_24;
 	u32 emif_ddr_ext_phy_ctrl_24_shdw;
+	u32 padding[22];
+	u32 emif_ddr_fifo_misaligned_clear_1;
+	u32 emif_ddr_fifo_misaligned_clear_2;
 };
 
 struct dmm_lisa_map_regs {
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [U-Boot] [PATCH 2/2] ARM: DRA7/OMAP5: EMIF: Add workaround for bug 0039
  2013-11-07 14:47 [U-Boot] [PATCH 0/2] OMAP5/DRA7: EMIF fixes for lowpower usecases Sricharan R
  2013-11-07 14:47 ` [U-Boot] [PATCH 1/2] ARM: DRA: EMIF: Change DDR3 settings to use hw leveling Sricharan R
@ 2013-11-07 14:47 ` Sricharan R
  1 sibling, 0 replies; 5+ messages in thread
From: Sricharan R @ 2013-11-07 14:47 UTC (permalink / raw)
  To: u-boot

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 |   41 +++++++++++++++
 arch/arm/cpu/armv7/omap5/sdram.c             |   69 ++++++++++++++++++++++++++
 arch/arm/include/asm/emif.h                  |   10 +++-
 3 files changed, 119 insertions(+), 1 deletion(-)

diff --git a/arch/arm/cpu/armv7/omap-common/emif-common.c b/arch/arm/cpu/armv7/omap-common/emif-common.c
index c1f5838..cad6ffe 100644
--- a/arch/arm/cpu/armv7/omap-common/emif-common.c
+++ b/arch/arm/cpu/armv7/omap-common/emif-common.c
@@ -1269,6 +1269,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 (omap_revision() == DRA752_ES1_0)
+		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:
@@ -1344,5 +1380,10 @@ void sdram_init(void)
 			debug("get_ram_size() successful");
 	}
 
+	if (!in_sdram && !warm_reset()) {
+		do_bug0039_workaround(EMIF1_BASE);
+		do_bug0039_workaround(EMIF2_BASE);
+	}
+
 	debug("<<sdram_init()\n");
 }
diff --git a/arch/arm/cpu/armv7/omap5/sdram.c b/arch/arm/cpu/armv7/omap5/sdram.c
index 2aae3ef..b5bf196 100644
--- a/arch/arm/cpu/armv7/omap5/sdram.c
+++ b/arch/arm/cpu/armv7/omap5/sdram.c
@@ -569,6 +569,75 @@ 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]);
+		printf("\n DRA iterations=%d", *iterations);
+		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)
diff --git a/arch/arm/include/asm/emif.h b/arch/arm/include/asm/emif.h
index c12beea..d9d521a 100644
--- a/arch/arm/include/asm/emif.h
+++ b/arch/arm/include/asm/emif.h
@@ -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
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [U-Boot] [PATCH 1/2] ARM: DRA: EMIF: Change DDR3 settings to use hw leveling
  2013-11-07 14:47 ` [U-Boot] [PATCH 1/2] ARM: DRA: EMIF: Change DDR3 settings to use hw leveling Sricharan R
@ 2013-11-07 15:03   ` Tom Rini
  2013-11-08  6:03     ` Sricharan R
  0 siblings, 1 reply; 5+ messages in thread
From: Tom Rini @ 2013-11-07 15:03 UTC (permalink / raw)
  To: u-boot

On Thu, Nov 07, 2013 at 08:17:39PM +0530, Sricharan R wrote:

> Currently the DDR3 memory on DRA7 ES1.0 evm board is enabled using
> software leveling. This was done since hardware leveling was not
> working. Now that the right sequence to do hw leveling is identified,
> use it. This is required for EMIF clockdomain to idle and come back
> during lowpower usecases.
[snip]
> @@ -210,54 +210,76 @@ static void ddr3_leveling(u32 base, const struct emif_regs *regs)
>  {
>  	struct emif_reg_struct *emif = (struct emif_reg_struct *)base;
>  
> -	/* keep sdram in self-refresh */
[snip]
> +	if (omap_revision() != DRA752_ES1_0)	{
> +		/* keep sdram in self-refresh */
[snip]
> +	} else {
> +		u32 fifo_reg;
[snip]
> +		/* Disable leveling */
> +		writel(0x0, &emif->emif_rd_wr_lvl_rmp_ctl);
> +	}

Two things here.  First, it seems that now ddr3_leveling has one
sequence for "not DRA752_ES1_0" (so likely to get wrong when used on
DRA752 whatever comes after ES1.0) and another for DRA752_ES1_0.  This
would be because the it's different EMIF blocks and related HW, so it's
a different sequence, yes?  Second, the comment at the end of this
function about "Disable leveling" seems misleading, but maybe it's just
me.  We're saying "leveling sequence is complete now", yes?

For the second issue, we can expand / clarify the comment.  For the
first issue, maybe we shouldn't have a single "ddr3_leveling" function
but per family ones?  There's nothing in common between the two cases
here, so we're just gaining an indentation level when we could be
excluding code from the final binary instead (either ifdef or maybe just
separate files?).

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20131107/fa97d026/attachment.pgp>

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [U-Boot] [PATCH 1/2] ARM: DRA: EMIF: Change DDR3 settings to use hw leveling
  2013-11-07 15:03   ` Tom Rini
@ 2013-11-08  6:03     ` Sricharan R
  0 siblings, 0 replies; 5+ messages in thread
From: Sricharan R @ 2013-11-08  6:03 UTC (permalink / raw)
  To: u-boot

Hi Tom,

On Thursday 07 November 2013 08:33 PM, Tom Rini wrote:
> On Thu, Nov 07, 2013 at 08:17:39PM +0530, Sricharan R wrote:
>
>> Currently the DDR3 memory on DRA7 ES1.0 evm board is enabled using
>> software leveling. This was done since hardware leveling was not
>> working. Now that the right sequence to do hw leveling is identified,
>> use it. This is required for EMIF clockdomain to idle and come back
>> during lowpower usecases.
> [snip]
>> @@ -210,54 +210,76 @@ static void ddr3_leveling(u32 base, const struct emif_regs *regs)
>>  {
>>  	struct emif_reg_struct *emif = (struct emif_reg_struct *)base;
>>  
>> -	/* keep sdram in self-refresh */
> [snip]
>> +	if (omap_revision() != DRA752_ES1_0)	{
>> +		/* keep sdram in self-refresh */
> [snip]
>> +	} else {
>> +		u32 fifo_reg;
> [snip]
>> +		/* Disable leveling */
>> +		writel(0x0, &emif->emif_rd_wr_lvl_rmp_ctl);
>> +	}
> Two things here.  First, it seems that now ddr3_leveling has one
> sequence for "not DRA752_ES1_0" (so likely to get wrong when used on
> DRA752 whatever comes after ES1.0) and another for DRA752_ES1_0.  This
> would be because the it's different EMIF blocks and related HW, so it's
> a different sequence, yes?  Second, the comment at the end of this
> function about "Disable leveling" seems misleading, but maybe it's just
> me.  We're saying "leveling sequence is complete now", yes?
>
> For the second issue, we can expand / clarify the comment.  For the
> first issue, maybe we shouldn't have a single "ddr3_leveling" function
> but per family ones?  There's nothing in common between the two cases
> here, so we're just gaining an indentation level when we could be
> excluding code from the final binary instead (either ifdef or maybe just
> separate files?).
>
 Yes, i also thought about having a separate function for OMAP5/DRA.
 I will do that. For the point about disable leveling, it was intentional.
 
 After we are done with a leveling once during boot, we do not intend to
 enable it anymore. We see that the PHY misbehaves by triggering a wrong
 leveling sequence when EMIF hits idle, which results in wrong delay values
 if it is left enabled. I will add this comment in V2

Regards,
 Sricharan

 

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2013-11-08  6:03 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-11-07 14:47 [U-Boot] [PATCH 0/2] OMAP5/DRA7: EMIF fixes for lowpower usecases Sricharan R
2013-11-07 14:47 ` [U-Boot] [PATCH 1/2] ARM: DRA: EMIF: Change DDR3 settings to use hw leveling Sricharan R
2013-11-07 15:03   ` Tom Rini
2013-11-08  6:03     ` Sricharan R
2013-11-07 14:47 ` [U-Boot] [PATCH 2/2] ARM: DRA7/OMAP5: EMIF: Add workaround for bug 0039 Sricharan R

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox