summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorRobin Gong <b38343@freescale.com>2014-07-04 16:05:46 +0800
committerRobin Gong <b38343@freescale.com>2014-07-04 17:24:08 +0800
commit295dcfe35d2708721917d136493b7a0cc84adb76 (patch)
tree65a47902032cbe7640515c6ac2b57d9e61c43c99 /arch
parent982f8797664030b41e0bb0ad39f138767ab89c7c (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.c44
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;