diff options
author | Anson Huang <b20788@freescale.com> | 2013-07-04 09:37:34 +0800 |
---|---|---|
committer | Anson Huang <b20788@freescale.com> | 2013-07-05 08:26:02 +0800 |
commit | 04b5224599fef16ef3a1856dd1b3205360b772c1 (patch) | |
tree | 1eb723e3033f48a11e8a4bdbf368b1f30ea7aab6 | |
parent | d3e5374cb5cdb478f524d76166712c753f69dd54 (diff) |
ENGR00269616 mx6: Unexpected enter WAIT mode cause IPU underrun
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.
Signed-off-by: Anson Huang <b20788@freescale.com>
-rw-r--r-- | arch/arm/mach-mx6/system.c | 30 |
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); |