DMC: exynos5420: Gate CLKM to when reading PHY_CON13
authorDoug Anderson <dianders@chromium.org>
Mon, 26 May 2014 13:49:05 +0000 (19:19 +0530)
committerMinkyu Kang <mk7.kang@samsung.com>
Fri, 13 Jun 2014 08:05:13 +0000 (17:05 +0900)
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@chromium.org>
Signed-off-by: Akshay Saraswat <akshay.s@samsung.com>
Acked-by: Simon Glass <sjg@chromium.org>
Tested-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Minkyu Kang <mk7.kang@samsung.com>
arch/arm/cpu/armv7/exynos/dmc_init_ddr3.c
arch/arm/cpu/armv7/exynos/exynos5_setup.h

index 1d6048cbfcc957bdbec713e0ff3de6354e9c009a..13003b86d521586215575c7a5ea03efbe6ef7423 100644 (file)
@@ -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;
index 314d6f4e57b8b20de748c9fde8f06f9b23ee08fb..d415c91f3a3cd8fb89fadb2569ae686ce0ed8e66 100644 (file)
 #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