diff options
author | Anson Huang <b20788@freescale.com> | 2014-10-31 16:33:56 +0800 |
---|---|---|
committer | Anson Huang <b20788@freescale.com> | 2014-11-07 16:55:29 +0800 |
commit | a1cd44f66213cc385adc7ad5e12268c44d3ec5dc (patch) | |
tree | 973a50adf42c2cbad87f438f6d89c7b82895b0fb /arch/arm/mach-imx/gpc.c | |
parent | 8c77b47ceef14f425d5338a46d2c0d600f201706 (diff) |
MLK-9799 arm: imx: improve M4-A9 wakeup source mechanism for low power mode
1. Enable MU as wakeup source always: as when M4 is busy, A9 suspend
only enters WAIT mode, when M4 is from busy to idle, it will send
A9 a message via MU, so we need to make sure MU message can wake
up A9 and provide chance for A9 to enter DSM mode;
2. Make sure MU is disabled when last message is NOT handled: as we
use delay work to handle MU message, and this message maybe over
written if there is another MU message coming, to make it more
robust, disable MU receive interrupt until last message has been
handled;
3. Make MU interrupt as early resume source to speed up MU message
handle and avoid message over written issue during resume process;
4. Enable GIC interrupt of those wakeup soucres from M4: this is to
cover the cornor case of suspend, when there is wakeup source of
M4 enabled in GPC but NOT in GIC, but it is pending before suspend,
CCM will NOT enter low power mode, and A9 is in wfi, to make sure
this interrupt can wake up A9 from wfi, make sure it is also enabled
in GIC and create a dummy action to handle this interrupt, only
for those modules that are NOT enabled in A9.
Signed-off-by: Anson Huang <b20788@freescale.com>
Diffstat (limited to 'arch/arm/mach-imx/gpc.c')
-rw-r--r-- | arch/arm/mach-imx/gpc.c | 7 |
1 files changed, 7 insertions, 0 deletions
diff --git a/arch/arm/mach-imx/gpc.c b/arch/arm/mach-imx/gpc.c index 3c38371225ce..7aa0fa5803c7 100644 --- a/arch/arm/mach-imx/gpc.c +++ b/arch/arm/mach-imx/gpc.c @@ -63,6 +63,7 @@ #define IMR_NUM 4 +static DEFINE_SPINLOCK(gpc_lock); static void __iomem *gpc_base; static u32 gpc_mf_irqs[IMR_NUM]; static u32 gpc_wake_irqs[IMR_NUM]; @@ -168,6 +169,7 @@ static void imx_gpc_dispmix_off(void) void imx_gpc_add_m4_wake_up_irq(u32 irq, bool enable) { unsigned int idx = irq / 32 - 1; + unsigned long flags; u32 mask; /* Sanity check for SPI irq */ @@ -175,8 +177,10 @@ void imx_gpc_add_m4_wake_up_irq(u32 irq, bool enable) return; mask = 1 << irq % 32; + spin_lock_irqsave(&gpc_lock, flags); gpc_wake_irqs[idx] = enable ? gpc_wake_irqs[idx] | mask : gpc_wake_irqs[idx] & ~mask; + spin_unlock_irqrestore(&gpc_lock, flags); } unsigned int imx_gpc_is_m4_sleeping(void) @@ -273,6 +277,7 @@ void imx_gpc_post_resume(void) static int imx_gpc_irq_set_wake(struct irq_data *d, unsigned int on) { unsigned int idx = d->irq / 32 - 1; + unsigned long flags; u32 mask; /* Sanity check for SPI irq */ @@ -280,8 +285,10 @@ static int imx_gpc_irq_set_wake(struct irq_data *d, unsigned int on) return -EINVAL; mask = 1 << d->irq % 32; + spin_lock_irqsave(&gpc_lock, flags); gpc_wake_irqs[idx] = on ? gpc_wake_irqs[idx] | mask : gpc_wake_irqs[idx] & ~mask; + spin_unlock_irqrestore(&gpc_lock, flags); return 0; } |