diff options
author | Robin Gong <b38343@freescale.com> | 2014-07-04 16:05:46 +0800 |
---|---|---|
committer | Robin Gong <b38343@freescale.com> | 2014-07-04 17:24:08 +0800 |
commit | 295dcfe35d2708721917d136493b7a0cc84adb76 (patch) | |
tree | 65a47902032cbe7640515c6ac2b57d9e61c43c99 /arch | |
parent | 982f8797664030b41e0bb0ad39f138767ab89c7c (diff) |
ENGR00321288 ARM: imx: gpc: fix VADC power off while pu management active
bit17/bit18 of GPC_CNTR worked as VADC power state control, that's function looks
different with other bits of this register: write 1 raise power request and write
0 do nothing. Need read and write only the related bit fields of the register to
avoid touch bit17/bit18 on i.mx6sx. Also fix the same for pcie power on/off.
Signed-off-by: Robin Gong <b38343@freescale.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mach-imx/gpc.c | 44 |
1 files changed, 36 insertions, 8 deletions
diff --git a/arch/arm/mach-imx/gpc.c b/arch/arm/mach-imx/gpc.c index 9a0d6b4e87ce..29dca3eb1b60 100644 --- a/arch/arm/mach-imx/gpc.c +++ b/arch/arm/mach-imx/gpc.c @@ -336,16 +336,42 @@ static void imx_gpc_pu_enable(bool enable) imx_pu_clk(true); writel_relaxed(1, gpc_base + GPC_PGC_GPU_PDN); - writel_relaxed(1 << GPC_CNTR_PU_UP_REQ_SHIFT, - gpc_base + GPC_CNTR); + /* + * bit17 and bit18 as VADC power state control are different + * as the other bits in GPC_CNTR whose request is set by + * 1 and nothing involved if set by 0. On imx6sx, zero of bit + * 17 and bit18 will power off VADC directly, so read GPC_CNTR + * firstly before write to avoid touching other bits. + */ + if (cpu_is_imx6sx()) { + u32 value = readl_relaxed(gpc_base + GPC_CNTR); + + value |= 1 << GPC_CNTR_PU_UP_REQ_SHIFT; + writel_relaxed(value, gpc_base + GPC_CNTR); + } else + writel_relaxed(1 << GPC_CNTR_PU_UP_REQ_SHIFT, + gpc_base + GPC_CNTR); while (readl_relaxed(gpc_base + GPC_CNTR) & (1 << GPC_CNTR_PU_UP_REQ_SHIFT)) ; imx_pu_clk(false); } else { writel_relaxed(1, gpc_base + GPC_PGC_GPU_PDN); - writel_relaxed(1 << GPC_CNTR_PU_DOWN_REQ_SHIFT, - gpc_base + GPC_CNTR); + /* + * bit17 and bit18 as VADC power state control are different + * as the other bits in GPC_CNTR whose request is set by + * 1 and nothing involved if set by 0. On imx6sx, zero of bit + * 17 and bit18 will power off VADC directly, so read GPC_CNTR + * firstly before write to avoid touching other bits. + */ + if (cpu_is_imx6sx()) { + u32 value = readl_relaxed(gpc_base + GPC_CNTR); + + value |= 1 << GPC_CNTR_PU_DOWN_REQ_SHIFT; + writel_relaxed(value, gpc_base + GPC_CNTR); + } else + writel_relaxed(1 << GPC_CNTR_PU_DOWN_REQ_SHIFT, + gpc_base + GPC_CNTR); while (readl_relaxed(gpc_base + GPC_CNTR) & (1 << GPC_CNTR_PU_DOWN_REQ_SHIFT)) ; @@ -389,15 +415,17 @@ static int imx_pcie_regulator_notify(struct notifier_block *nb, unsigned long event, void *ignored) { + u32 value = readl_relaxed(gpc_base + GPC_CNTR); + switch (event) { case REGULATOR_EVENT_VOLTAGE_CHANGE: case REGULATOR_EVENT_ENABLE: - writel_relaxed(1 << GPC_CNTR_PCIE_PHY_PDU_SHIFT, - gpc_base + GPC_CNTR); + value |= 1 << GPC_CNTR_PCIE_PHY_PDU_SHIFT; + writel_relaxed(value, gpc_base + GPC_CNTR); break; case REGULATOR_EVENT_PRE_DISABLE: - writel_relaxed(1 << GPC_CNTR_PCIE_PHY_PDN_SHIFT, - gpc_base + GPC_CNTR); + value |= 1 << GPC_CNTR_PCIE_PHY_PDN_SHIFT; + writel_relaxed(value, gpc_base + GPC_CNTR); writel_relaxed(PGC_PCIE_PHY_PDN_EN, gpc_base + PGC_PCIE_PHY_CTRL); break; |