summaryrefslogtreecommitdiff
path: root/arch/arm/mach-imx/gpc.c
diff options
context:
space:
mode:
authorAnson Huang <b20788@freescale.com>2014-10-31 16:33:56 +0800
committerAnson Huang <b20788@freescale.com>2014-11-07 16:55:29 +0800
commita1cd44f66213cc385adc7ad5e12268c44d3ec5dc (patch)
tree973a50adf42c2cbad87f438f6d89c7b82895b0fb /arch/arm/mach-imx/gpc.c
parent8c77b47ceef14f425d5338a46d2c0d600f201706 (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.c7
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;
}