mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-12-01 08:59:33 +00:00
DMC: exynos5420: Gate CLKM to when reading PHY_CON13
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>
This commit is contained in:
parent
aacdd79095
commit
c9334fcda9
2 changed files with 39 additions and 5 deletions
|
@ -230,6 +230,7 @@ int ddr3_mem_ctrl_init(struct mem_timings *mem, int reset)
|
||||||
struct exynos5420_dmc *drex0, *drex1;
|
struct exynos5420_dmc *drex0, *drex1;
|
||||||
struct exynos5420_tzasc *tzasc0, *tzasc1;
|
struct exynos5420_tzasc *tzasc0, *tzasc1;
|
||||||
uint32_t val, n_lock_r, n_lock_w_phy0, n_lock_w_phy1;
|
uint32_t val, n_lock_r, n_lock_w_phy0, n_lock_w_phy1;
|
||||||
|
uint32_t lock0_info, lock1_info;
|
||||||
int chip;
|
int chip;
|
||||||
int i;
|
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, &drex0->directcmd);
|
||||||
dmc_config_mrs(mem, &drex1->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
|
* During Suspend-Resume & S/W-Reset, as soon as PMU releases
|
||||||
* pad retention, CKE goes high. This causes memory contents
|
* 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);
|
val |= (RDLVL_PASS_ADJ_VAL << RDLVL_PASS_ADJ_OFFSET);
|
||||||
writel(val, &phy1_ctrl->phy_con1);
|
writel(val, &phy1_ctrl->phy_con1);
|
||||||
|
|
||||||
n_lock_r = readl(&phy0_ctrl->phy_con13);
|
n_lock_w_phy0 = (lock0_info & CTRL_LOCK_COARSE_MASK) >> 2;
|
||||||
n_lock_w_phy0 = (n_lock_r & CTRL_LOCK_COARSE_MASK) >> 2;
|
|
||||||
n_lock_r = readl(&phy0_ctrl->phy_con12);
|
n_lock_r = readl(&phy0_ctrl->phy_con12);
|
||||||
n_lock_r &= ~CTRL_DLL_ON;
|
n_lock_r &= ~CTRL_DLL_ON;
|
||||||
n_lock_r |= n_lock_w_phy0;
|
n_lock_r |= n_lock_w_phy0;
|
||||||
writel(n_lock_r, &phy0_ctrl->phy_con12);
|
writel(n_lock_r, &phy0_ctrl->phy_con12);
|
||||||
|
|
||||||
n_lock_r = readl(&phy1_ctrl->phy_con13);
|
n_lock_w_phy1 = (lock1_info & CTRL_LOCK_COARSE_MASK) >> 2;
|
||||||
n_lock_w_phy1 = (n_lock_r & CTRL_LOCK_COARSE_MASK) >> 2;
|
|
||||||
n_lock_r = readl(&phy1_ctrl->phy_con12);
|
n_lock_r = readl(&phy1_ctrl->phy_con12);
|
||||||
n_lock_r &= ~CTRL_DLL_ON;
|
n_lock_r &= ~CTRL_DLL_ON;
|
||||||
n_lock_r |= n_lock_w_phy1;
|
n_lock_r |= n_lock_w_phy1;
|
||||||
|
|
|
@ -284,6 +284,7 @@
|
||||||
#define CTRL_DLL_ON (1 << 5)
|
#define CTRL_DLL_ON (1 << 5)
|
||||||
#define CTRL_FORCE_MASK (0x7F << 8)
|
#define CTRL_FORCE_MASK (0x7F << 8)
|
||||||
#define CTRL_LOCK_COARSE_MASK (0x7F << 10)
|
#define CTRL_LOCK_COARSE_MASK (0x7F << 10)
|
||||||
|
#define CTRL_FINE_LOCKED 0x7
|
||||||
|
|
||||||
#define CTRL_OFFSETD_RESET_VAL 0x8
|
#define CTRL_OFFSETD_RESET_VAL 0x8
|
||||||
#define CTRL_OFFSETD_VAL 0x7F
|
#define CTRL_OFFSETD_VAL 0x7F
|
||||||
|
|
Loading…
Reference in a new issue