No subject


Mon Mar 3 09:42:13 CET 2014


when CLKM is running.  If we stop CLKM when sampling it the glitches
all go away, so we'll do that as per Samsung suggestion.

We also check the "is it locked" bits of PHY_CON13 and loop until they
show the the value sampled actually represents a locked value.  It
doesn't appear that the glitching and "is it locked" are related, but
it seems wise to wait until the PHY tells us the value is good before
we use it.  In practice we will not loop more than a couple times (and
usually won't loop at all).

Signed-off-by: Doug Anderson <dianders at chromium.org>
Signed-off-by: Akshay Saraswat <akshay.s at samsung.com>
Acked-by: Simon Glass <sjg at chromium.org>
---
Changes since v1:
	- Added "Acked-by".

 arch/arm/cpu/armv7/exynos/dmc_init_ddr3.c | 43 +++++++++++++++++++++++++++----
 arch/arm/cpu/armv7/exynos/exynos5_setup.h |  1 +
 2 files changed, 39 insertions(+), 5 deletions(-)

diff --git a/arch/arm/cpu/armv7/exynos/dmc_init_ddr3.c b/arch/arm/cpu/armv7/exynos/dmc_init_ddr3.c
index 1d6048c..13003b8 100644
--- a/arch/arm/cpu/armv7/exynos/dmc_init_ddr3.c
+++ b/arch/arm/cpu/armv7/exynos/dmc_init_ddr3.c
@@ -230,6 +230,7 @@ int ddr3_mem_ctrl_init(struct mem_timings *mem, int reset)
 	struct exynos5420_dmc *drex0, *drex1;
 	struct exynos5420_tzasc *tzasc0, *tzasc1;
 	uint32_t val, n_lock_r, n_lock_w_phy0, n_lock_w_phy1;
+	uint32_t lock0_info, lock1_info;
 	int chip;
 	int i;
 
@@ -391,7 +392,41 @@ int ddr3_mem_ctrl_init(struct mem_timings *mem, int reset)
 		 */
 		dmc_config_mrs(mem, &drex0->directcmd);
 		dmc_config_mrs(mem, &drex1->directcmd);
-	} else {
+	}
+
+	/*
+	 * Get PHY_CON13 from both phys.  Gate CLKM around reading since
+	 * PHY_CON13 is glitchy when CLKM is running.  We're paranoid and
+	 * wait until we get a "fine lock", though a coarse lock is probably
+	 * OK (we only use the coarse numbers below).  We try to gate the
+	 * clock for as short a time as possible in case SDRAM is somehow
+	 * sensitive.  sdelay(10) in the loop is arbitrary to make sure
+	 * there is some time for PHY_CON13 to get updated.  In practice
+	 * no delay appears to be needed.
+	 */
+	val = readl(&clk->gate_bus_cdrex);
+	while (true) {
+		writel(val & ~0x1, &clk->gate_bus_cdrex);
+		lock0_info = readl(&phy0_ctrl->phy_con13);
+		writel(val, &clk->gate_bus_cdrex);
+
+		if ((lock0_info & CTRL_FINE_LOCKED) == CTRL_FINE_LOCKED)
+			break;
+
+		sdelay(10);
+	}
+	while (true) {
+		writel(val & ~0x2, &clk->gate_bus_cdrex);
+		lock1_info = readl(&phy1_ctrl->phy_con13);
+		writel(val, &clk->gate_bus_cdrex);
+
+		if ((lock1_info & CTRL_FINE_LOCKED) == CTRL_FINE_LOCKED)
+			break;
+
+		sdelay(10);
+	}
+
+	if (!reset) {
 		/*
 		 * During Suspend-Resume & S/W-Reset, as soon as PMU releases
 		 * pad retention, CKE goes high. This causes memory contents
@@ -442,15 +477,13 @@ int ddr3_mem_ctrl_init(struct mem_timings *mem, int reset)
 		val |= (RDLVL_PASS_ADJ_VAL << RDLVL_PASS_ADJ_OFFSET);
 		writel(val, &phy1_ctrl->phy_con1);
 
-		n_lock_r = readl(&phy0_ctrl->phy_con13);
-		n_lock_w_phy0 = (n_lock_r & CTRL_LOCK_COARSE_MASK) >> 2;
+		n_lock_w_phy0 = (lock0_info & CTRL_LOCK_COARSE_MASK) >> 2;
 		n_lock_r = readl(&phy0_ctrl->phy_con12);
 		n_lock_r &= ~CTRL_DLL_ON;
 		n_lock_r |= n_lock_w_phy0;
 		writel(n_lock_r, &phy0_ctrl->phy_con12);
 
-		n_lock_r = readl(&phy1_ctrl->phy_con13);
-		n_lock_w_phy1 = (n_lock_r & CTRL_LOCK_COARSE_MASK) >> 2;
+		n_lock_w_phy1 = (lock1_info & CTRL_LOCK_COARSE_MASK) >> 2;
 		n_lock_r = readl(&phy1_ctrl->phy_con12);
 		n_lock_r &= ~CTRL_DLL_ON;
 		n_lock_r |= n_lock_w_phy1;
diff --git a/arch/arm/cpu/armv7/exynos/exynos5_setup.h b/arch/arm/cpu/armv7/exynos/exynos5_setup.h
index 4542bd1..583be27 100644
--- a/arch/arm/cpu/armv7/exynos/exynos5_setup.h
+++ b/arch/arm/cpu/armv7/exynos/exynos5_setup.h
@@ -284,6 +284,7 @@
 #define CTRL_DLL_ON		(1 << 5)
 #define CTRL_FORCE_MASK		(0x7F << 8)
 #define CTRL_LOCK_COARSE_MASK	(0x7F << 10)
+#define CTRL_FINE_LOCKED	0x7
 
 #define CTRL_OFFSETD_RESET_VAL	0x8
 #define CTRL_OFFSETD_VAL	0x7F
-- 
1.8.3.2



More information about the U-Boot mailing list