summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-mx6/system.c30
1 files changed, 30 insertions, 0 deletions
diff --git a/arch/arm/mach-mx6/system.c b/arch/arm/mach-mx6/system.c
index f1c2e2927362..ff1feda30f5b 100644
--- a/arch/arm/mach-mx6/system.c
+++ b/arch/arm/mach-mx6/system.c
@@ -82,6 +82,22 @@ void gpc_set_wakeup(unsigned int irq[4])
return;
}
+void gpc_mask_single_irq(int irq, bool enable)
+{
+ void __iomem *reg;
+ u32 val;
+
+ reg = gpc_base + 0x8 + (irq / 32 - 1) * 4;
+ val = __raw_readl(reg);
+ if (enable)
+ val |= 1 << (irq % 32);
+ else
+ val &= ~(1 << (irq % 32));
+ __raw_writel(val, reg);
+
+ return;
+}
+
/* set cpu low power mode before WFI instruction */
void mxc_cpu_lp_set(enum mxc_cpu_pwr_mode mode)
{
@@ -91,6 +107,18 @@ void mxc_cpu_lp_set(enum mxc_cpu_pwr_mode mode)
u32 ccm_clpcr, anatop_val;
ccm_clpcr = __raw_readl(MXC_CCM_CLPCR) & ~(MXC_CCM_CLPCR_LPM_MASK);
+ /*
+ * CCM state machine has restriction that, everytime enable
+ * LPM mode, we need to make sure last wakeup from LPM mode
+ * is a dsm_wakeup_signal, which means the wakeup source
+ * must be seen by GPC, then CCM will clean its state machine
+ * and re-sample necessary signal to decide whether it can
+ * enter LPM mode. Here we use the forever pending irq #125,
+ * unmask it before we enable LPM mode and mask it after LPM
+ * is enabled, this flow will make sure CCM state machine in
+ * reliable state before we enter LPM mode.
+ */
+ gpc_mask_single_irq(MXC_INT_CHEETAH_PARITY, false);
switch (mode) {
case WAIT_CLOCKED:
@@ -149,6 +177,7 @@ void mxc_cpu_lp_set(enum mxc_cpu_pwr_mode mode)
break;
default:
printk(KERN_WARNING "UNKNOWN cpu power mode: %d\n", mode);
+ gpc_mask_single_irq(MXC_INT_CHEETAH_PARITY, true);
return;
}
@@ -246,6 +275,7 @@ void mxc_cpu_lp_set(enum mxc_cpu_pwr_mode mode)
}
}
__raw_writel(ccm_clpcr, MXC_CCM_CLPCR);
+ gpc_mask_single_irq(MXC_INT_CHEETAH_PARITY, true);
}
extern int tick_broadcast_oneshot_active(void);