[U-Boot] [PATCH 1/7] ARM: DRA7: DDR3: Add support for HW leveling

Lokesh Vutla lokeshvutla at ti.com
Wed Jun 3 11:13:21 CEST 2015


DRA7 EMIF supports Full leveling for DDR3.
Adding support for the Full leveling sequence.

Signed-off-by: Lokesh Vutla <lokeshvutla at ti.com>
---
 arch/arm/cpu/armv7/omap-common/emif-common.c | 146 +++++++++++++++++++++++----
 arch/arm/cpu/armv7/omap5/sdram.c             |  76 +++++++++++++-
 arch/arm/include/asm/emif.h                  |   9 ++
 board/ti/beagle_x15/board.c                  |  15 ++-
 4 files changed, 220 insertions(+), 26 deletions(-)

diff --git a/arch/arm/cpu/armv7/omap-common/emif-common.c b/arch/arm/cpu/armv7/omap-common/emif-common.c
index c01a98f..3ee4695 100644
--- a/arch/arm/cpu/armv7/omap-common/emif-common.c
+++ b/arch/arm/cpu/armv7/omap-common/emif-common.c
@@ -242,13 +242,122 @@ static void omap5_ddr3_leveling(u32 base, const struct emif_regs *regs)
 	       __udelay(130);
 }
 
-static void ddr3_leveling(u32 base, const struct emif_regs *regs)
+static void update_hwleveling_output(u32 base, const struct emif_regs *regs)
 {
-	if (is_omap54xx())
-		omap5_ddr3_leveling(base, regs);
+	struct emif_reg_struct *emif = (struct emif_reg_struct *)base;
+	u32 *emif_ext_phy_ctrl_reg, *emif_phy_status;
+	u32 reg, i;
+
+	emif_phy_status = (u32 *)&emif->emif_ddr_phy_status[7];
+
+	/* Update PHY_REG_RDDQS_RATIO */
+	emif_ext_phy_ctrl_reg = (u32 *)&emif->emif_ddr_ext_phy_ctrl_7;
+	for (i = 0; i < PHY_RDDQS_RATIO_REGS; i++) {
+		reg = readl(emif_phy_status++);
+		writel(reg, emif_ext_phy_ctrl_reg++);
+		writel(reg, emif_ext_phy_ctrl_reg++);
+	}
+
+	/* Update PHY_REG_FIFO_WE_SLAVE_RATIO */
+	emif_ext_phy_ctrl_reg = (u32 *)&emif->emif_ddr_ext_phy_ctrl_2;
+	for (i = 0; i < PHY_FIFO_WE_SLAVE_RATIO_REGS; i++) {
+		reg = readl(emif_phy_status++);
+		writel(reg, emif_ext_phy_ctrl_reg++);
+		writel(reg, emif_ext_phy_ctrl_reg++);
+	}
+
+	/* Update PHY_REG_WR_DQ/DQS_SLAVE_RATIO */
+	emif_ext_phy_ctrl_reg = (u32 *)&emif->emif_ddr_ext_phy_ctrl_12;
+	for (i = 0; i < PHY_REG_WR_DQ_SLAVE_RATIO_REGS; i++) {
+		reg = readl(emif_phy_status++);
+		writel(reg, emif_ext_phy_ctrl_reg++);
+		writel(reg, emif_ext_phy_ctrl_reg++);
+	}
+
+	/* Disable 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);
+	writel(0x0, &emif->emif_rd_wr_lvl_rmp_ctl);
 }
 
-static void ddr3_init(u32 base, const struct emif_regs *regs)
+static void dra7_ddr3_leveling(u32 base, const struct emif_regs *regs)
+{
+	struct emif_reg_struct *emif = (struct emif_reg_struct *)base;
+
+	/* Clear Error Status */
+	clrsetbits_le32(&emif->emif_ddr_ext_phy_ctrl_36,
+			EMIF_REG_PHY_FIFO_WE_IN_MISALINED_CLR,
+			EMIF_REG_PHY_FIFO_WE_IN_MISALINED_CLR);
+
+	clrsetbits_le32(&emif->emif_ddr_ext_phy_ctrl_36_shdw,
+			EMIF_REG_PHY_FIFO_WE_IN_MISALINED_CLR,
+			EMIF_REG_PHY_FIFO_WE_IN_MISALINED_CLR);
+
+	/* Disable refreshed before leveling */
+	clrsetbits_le32(&emif->emif_sdram_ref_ctrl, EMIF_REG_INITREF_DIS_SHIFT,
+			EMIF_REG_INITREF_DIS_SHIFT);
+
+	/* Start Full leveling */
+	writel(DDR3_FULL_LVL, &emif->emif_rd_wr_lvl_ctl);
+
+	__udelay(300);
+
+	/* Check for leveling timeout */
+	if (readl(&emif->emif_status) & EMIF_REG_LEVELING_TO_MASK) {
+		printf("Leveling timeout on EMIF%d\n", emif_num(base));
+		return;
+	}
+
+	/* Enable refreshes after leveling */
+	clrbits_le32(&emif->emif_sdram_ref_ctrl, EMIF_REG_INITREF_DIS_SHIFT);
+
+	debug("HW leveling success\n");
+	/*
+	 * Update slave ratios in EXT_PHY_CTRLx registers
+	 * as per HW leveling output
+	 */
+	update_hwleveling_output(base, regs);
+}
+
+static void dra7_ddr3_init(u32 base, const struct emif_regs *regs)
+{
+	struct emif_reg_struct *emif = (struct emif_reg_struct *)base;
+
+	if (warm_reset())
+		emif_reset_phy(base);
+	do_ext_phy_settings(base, regs);
+
+	writel(regs->ref_ctrl | EMIF_REG_INITREF_DIS_MASK,
+	       &emif->emif_sdram_ref_ctrl);
+	/* Update timing registers */
+	writel(regs->sdram_tim1, &emif->emif_sdram_tim_1);
+	writel(regs->sdram_tim2, &emif->emif_sdram_tim_2);
+	writel(regs->sdram_tim3, &emif->emif_sdram_tim_3);
+
+	writel(EMIF_L3_CONFIG_VAL_SYS_10_MPU_5_LL_0, &emif->emif_l3_config);
+	writel(regs->read_idle_ctrl, &emif->emif_read_idlectrl);
+	writel(regs->zq_config, &emif->emif_zq_config);
+	writel(regs->temp_alert_config, &emif->emif_temp_alert_config);
+	writel(regs->emif_rd_wr_lvl_rmp_ctl, &emif->emif_rd_wr_lvl_rmp_ctl);
+	writel(regs->emif_rd_wr_lvl_ctl, &emif->emif_rd_wr_lvl_ctl);
+
+	writel(regs->emif_ddr_phy_ctlr_1_init, &emif->emif_ddr_phy_ctrl_1);
+	writel(regs->emif_rd_wr_exec_thresh, &emif->emif_rd_wr_exec_thresh);
+
+	writel(regs->ref_ctrl, &emif->emif_sdram_ref_ctrl);
+
+	writel(regs->sdram_config2, &emif->emif_lpddr2_nvm_config);
+	writel(regs->sdram_config_init, &emif->emif_sdram_config);
+
+	__udelay(1000);
+
+	writel(regs->ref_ctrl_final, &emif->emif_sdram_ref_ctrl);
+
+	if (regs->emif_rd_wr_lvl_rmp_ctl & EMIF_REG_RDWRLVL_EN_MASK)
+		dra7_ddr3_leveling(base, regs);
+}
+
+static void omap5_ddr3_init(u32 base, const struct emif_regs *regs)
 {
 	struct emif_reg_struct *emif = (struct emif_reg_struct *)base;
 
@@ -269,25 +378,20 @@ static void ddr3_init(u32 base, const struct emif_regs *regs)
 
 	writel(regs->read_idle_ctrl, &emif->emif_read_idlectrl);
 
-	/*
-	 * The same sequence should work on OMAP5432 as well. But strange that
-	 * it is not working
-	 */
-	if (is_dra7xx()) {
-		do_ext_phy_settings(base, regs);
-		writel(regs->ref_ctrl_final, &emif->emif_sdram_ref_ctrl);
-		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);
-	}
+	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);
+	omap5_ddr3_leveling(base, regs);
+}
 
-	ddr3_leveling(base, regs);
+static void ddr3_init(u32 base, const struct emif_regs *regs)
+{
+	if (is_omap54xx())
+		omap5_ddr3_init(base, regs);
+	else
+		dra7_ddr3_init(base, regs);
 }
 
 #ifndef CONFIG_SYS_EMIF_PRECALCULATED_TIMING_REGS
@@ -1075,7 +1179,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);
-		ddr3_leveling(base, regs);
+		omap5_ddr3_leveling(base, regs);
 	}
 
 	/* Write to the shadow registers */
diff --git a/arch/arm/cpu/armv7/omap5/sdram.c b/arch/arm/cpu/armv7/omap5/sdram.c
index 5f8daa1..2e23852 100644
--- a/arch/arm/cpu/armv7/omap5/sdram.c
+++ b/arch/arm/cpu/armv7/omap5/sdram.c
@@ -421,8 +421,14 @@ const u32 ddr3_ext_phy_ctrl_const_base_es2[] = {
 	0x0
 };
 
+/* Ext phy ctrl 1-35 regs */
 const u32
 dra_ddr3_ext_phy_ctrl_const_base_es1_emif1[] = {
+	0x10040100,
+	0x00910091,
+	0x00950095,
+	0x009B009B,
+	0x009E009E,
 	0x00980098,
 	0x00340034,
 	0x00350035,
@@ -441,7 +447,7 @@ dra_ddr3_ext_phy_ctrl_const_base_es1_emif1[] = {
 	0x00500050,
 	0x00000000,
 	0x00600020,
-	0x40010080,
+	0x40011080,
 	0x08102040,
 	0x0,
 	0x0,
@@ -450,8 +456,14 @@ dra_ddr3_ext_phy_ctrl_const_base_es1_emif1[] = {
 	0x0
 };
 
+/* Ext phy ctrl 1-35 regs */
 const u32
 dra_ddr3_ext_phy_ctrl_const_base_es1_emif2[] = {
+	0x10040100,
+	0x00910091,
+	0x00950095,
+	0x009B009B,
+	0x009E009E,
 	0x00980098,
 	0x00330033,
 	0x00330033,
@@ -470,7 +482,7 @@ dra_ddr3_ext_phy_ctrl_const_base_es1_emif2[] = {
 	0x00500050,
 	0x00000000,
 	0x00600020,
-	0x40010080,
+	0x40011080,
 	0x08102040,
 	0x0,
 	0x0,
@@ -479,8 +491,14 @@ dra_ddr3_ext_phy_ctrl_const_base_es1_emif2[] = {
 	0x0
 };
 
+/* Ext phy ctrl 1-35 regs */
 const u32
 dra_ddr3_ext_phy_ctrl_const_base_666MHz[] = {
+	0x10040100,
+	0x00A400A4,
+	0x00A900A9,
+	0x00B000B0,
+	0x00B000B0,
 	0x00A400A4,
 	0x00390039,
 	0x00320032,
@@ -562,7 +580,7 @@ void get_lpddr2_mr_regs(const struct lpddr2_mr_regs **regs)
 	*regs = &mr_regs;
 }
 
-void do_ext_phy_settings(u32 base, const struct emif_regs *regs)
+static void do_ext_phy_settings_omap5(u32 base, const struct emif_regs *regs)
 {
 	u32 *ext_phy_ctrl_base = 0;
 	u32 *emif_ext_phy_ctrl_base = 0;
@@ -601,6 +619,58 @@ void do_ext_phy_settings(u32 base, const struct emif_regs *regs)
 	}
 }
 
+static void do_ext_phy_settings_dra7(u32 base, const struct emif_regs *regs)
+{
+	struct emif_reg_struct *emif = (struct emif_reg_struct *)base;
+	u32 *emif_ext_phy_ctrl_base = 0;
+	u32 emif_nr;
+	const u32 *ext_phy_ctrl_const_regs;
+	u32 i, hw_leveling, size;
+
+	emif_nr = (base == EMIF1_BASE) ? 1 : 2;
+
+	hw_leveling = regs->emif_rd_wr_lvl_rmp_ctl >> EMIF_REG_RDWRLVL_EN_SHIFT;
+
+	emif_ext_phy_ctrl_base = (u32 *)&(emif->emif_ddr_ext_phy_ctrl_1);
+
+	emif_get_ext_phy_ctrl_const_regs(emif_nr,
+					 &ext_phy_ctrl_const_regs, &size);
+
+	writel(ext_phy_ctrl_const_regs[0], &emif_ext_phy_ctrl_base[0]);
+	writel(ext_phy_ctrl_const_regs[0], &emif_ext_phy_ctrl_base[1]);
+
+	if (!hw_leveling) {
+		/*
+		 * Copy the predefined PHY register values
+		 * in case of sw leveling
+		 */
+		for (i = 1; i < 25; i++) {
+			writel(ext_phy_ctrl_const_regs[i],
+			       &emif_ext_phy_ctrl_base[i * 2]);
+			writel(ext_phy_ctrl_const_regs[i],
+			       &emif_ext_phy_ctrl_base[i * 2 + 1]);
+		}
+	} else {
+		/*
+		 * Write the init value for HW levling to occur
+		 */
+		for (i = 21; i < 35; i++) {
+			writel(ext_phy_ctrl_const_regs[i],
+			       &emif_ext_phy_ctrl_base[i * 2]);
+			writel(ext_phy_ctrl_const_regs[i],
+			       &emif_ext_phy_ctrl_base[i * 2 + 1]);
+		}
+	}
+}
+
+void do_ext_phy_settings(u32 base, const struct emif_regs *regs)
+{
+	if (is_omap54xx())
+		do_ext_phy_settings_omap5(base, regs);
+	else
+		do_ext_phy_settings_dra7(base, regs);
+}
+
 #ifndef CONFIG_SYS_DEFAULT_LPDDR2_TIMINGS
 static const struct lpddr2_ac_timings timings_jedec_532_mhz = {
 	.max_freq	= 532000000,
diff --git a/arch/arm/include/asm/emif.h b/arch/arm/include/asm/emif.h
index 7a545ea..a97d2fd 100644
--- a/arch/arm/include/asm/emif.h
+++ b/arch/arm/include/asm/emif.h
@@ -44,6 +44,8 @@
 #define EMIF_REG_DUAL_CLK_MODE_MASK			(1 << 30)
 #define EMIF_REG_FAST_INIT_SHIFT			29
 #define EMIF_REG_FAST_INIT_MASK			(1 << 29)
+#define EMIF_REG_LEVLING_TO_SHIFT		4
+#define EMIF_REG_LEVELING_TO_MASK		(7 << 4)
 #define EMIF_REG_PHY_DLL_READY_SHIFT		2
 #define EMIF_REG_PHY_DLL_READY_MASK			(1 << 2)
 
@@ -509,6 +511,13 @@
 #define EMIF_REG_RDWRLVLINC_RMP_WIN_SHIFT	0
 #define EMIF_REG_RDWRLVLINC_RMP_WIN_MASK	(0x1FFF << 0)
 
+/* EMIF_PHY_CTRL_36 */
+#define EMIF_REG_PHY_FIFO_WE_IN_MISALINED_CLR	(1 << 8)
+
+#define PHY_RDDQS_RATIO_REGS		5
+#define PHY_FIFO_WE_SLAVE_RATIO_REGS	5
+#define PHY_REG_WR_DQ_SLAVE_RATIO_REGS	10
+
 /*Leveling Fields */
 #define DDR3_WR_LVL_INT		0x73
 #define DDR3_RD_LVL_INT		0x33
diff --git a/board/ti/beagle_x15/board.c b/board/ti/beagle_x15/board.c
index 3a7e04d..75dd8e8 100644
--- a/board/ti/beagle_x15/board.c
+++ b/board/ti/beagle_x15/board.c
@@ -68,7 +68,13 @@ static const struct emif_regs beagle_x15_emif1_ddr3_532mhz_emif_regs = {
 	.emif_rd_wr_exec_thresh	= 0x00000305
 };
 
+/* Ext phy ctrl regs 1-35 */
 static const u32 beagle_x15_emif1_ddr3_ext_phy_ctrl_const_regs[] = {
+	0x10040100,
+	0x00740074,
+	0x00780078,
+	0x007c007c,
+	0x007b007b,
 	0x00800080,
 	0x00360036,
 	0x00340034,
@@ -90,7 +96,7 @@ static const u32 beagle_x15_emif1_ddr3_ext_phy_ctrl_const_regs[] = {
 
 	0x00000000,
 	0x00600020,
-	0x40010080,
+	0x40011080,
 	0x08102040,
 
 	0x00400040,
@@ -126,6 +132,11 @@ static const struct emif_regs beagle_x15_emif2_ddr3_532mhz_emif_regs = {
 };
 
 static const u32 beagle_x15_emif2_ddr3_ext_phy_ctrl_const_regs[] = {
+	0x10040100,
+	0x00820082,
+	0x008b008b,
+	0x00800080,
+	0x007e007e,
 	0x00800080,
 	0x00370037,
 	0x00390039,
@@ -145,7 +156,7 @@ static const u32 beagle_x15_emif2_ddr3_ext_phy_ctrl_const_regs[] = {
 
 	0x00000000,
 	0x00600020,
-	0x40010080,
+	0x40011080,
 	0x08102040,
 
 	0x00400040,
-- 
1.9.1



More information about the U-Boot mailing list