summaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2/pm34xx.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-omap2/pm34xx.c')
-rw-r--r--arch/arm/mach-omap2/pm34xx.c46
1 files changed, 37 insertions, 9 deletions
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 0e7bd8e55f76..d9440a18bd00 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -61,7 +61,7 @@ static struct powerdomain *mpu_pwrdm;
* that any peripheral wake-up events occurring while attempting to
* clear the PM_WKST_x are detected and cleared.
*/
-static void prcm_clear_mod_irqs(s16 module, u8 regs)
+static int prcm_clear_mod_irqs(s16 module, u8 regs)
{
u32 wkst, fclk, iclk;
u16 wkst_off = (regs == 3) ? OMAP3430ES2_PM_WKST3 : PM_WKST1;
@@ -69,6 +69,7 @@ static void prcm_clear_mod_irqs(s16 module, u8 regs)
u16 iclk_off = (regs == 3) ? CM_ICLKEN3 : CM_ICLKEN1;
u16 grpsel_off = (regs == 3) ?
OMAP3430ES2_PM_MPUGRPSEL3 : OMAP3430_PM_MPUGRPSEL;
+ int c = 0;
wkst = prm_read_mod_reg(module, wkst_off);
wkst &= prm_read_mod_reg(module, grpsel_off);
@@ -80,10 +81,28 @@ static void prcm_clear_mod_irqs(s16 module, u8 regs)
cm_set_mod_reg_bits(wkst, module, fclk_off);
prm_write_mod_reg(wkst, module, wkst_off);
wkst = prm_read_mod_reg(module, wkst_off);
+ c++;
}
cm_write_mod_reg(iclk, module, iclk_off);
cm_write_mod_reg(fclk, module, fclk_off);
}
+
+ return c;
+}
+
+static int _prcm_int_handle_wakeup(void)
+{
+ int c;
+
+ c = prcm_clear_mod_irqs(WKUP_MOD, 1);
+ c += prcm_clear_mod_irqs(CORE_MOD, 1);
+ c += prcm_clear_mod_irqs(OMAP3430_PER_MOD, 1);
+ if (omap_rev() > OMAP3430_REV_ES1_0) {
+ c += prcm_clear_mod_irqs(CORE_MOD, 3);
+ c += prcm_clear_mod_irqs(OMAP3430ES2_USBHOST_MOD, 1);
+ }
+
+ return c;
}
/*
@@ -106,18 +125,27 @@ static void prcm_clear_mod_irqs(s16 module, u8 regs)
static irqreturn_t prcm_interrupt_handler (int irq, void *dev_id)
{
u32 irqstatus_mpu;
+ int c = 0;
do {
- prcm_clear_mod_irqs(WKUP_MOD, 1);
- prcm_clear_mod_irqs(CORE_MOD, 1);
- prcm_clear_mod_irqs(OMAP3430_PER_MOD, 1);
- if (omap_rev() > OMAP3430_REV_ES1_0) {
- prcm_clear_mod_irqs(CORE_MOD, 3);
- prcm_clear_mod_irqs(OMAP3430ES2_USBHOST_MOD, 1);
- }
-
irqstatus_mpu = prm_read_mod_reg(OCP_MOD,
OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
+
+ if (irqstatus_mpu & (OMAP3430_WKUP_ST | OMAP3430_IO_ST)) {
+ c = _prcm_int_handle_wakeup();
+
+ /*
+ * Is the MPU PRCM interrupt handler racing with the
+ * IVA2 PRCM interrupt handler ?
+ */
+ WARN(c == 0, "prcm: WARNING: PRCM indicated MPU wakeup "
+ "but no wakeup sources are marked\n");
+ } else {
+ /* XXX we need to expand our PRCM interrupt handler */
+ WARN(1, "prcm: WARNING: PRCM interrupt received, but "
+ "no code to handle it (%08x)\n", irqstatus_mpu);
+ }
+
prm_write_mod_reg(irqstatus_mpu, OCP_MOD,
OMAP3_PRM_IRQSTATUS_MPU_OFFSET);