On Fri, 2012-04-06 at 07:52 +0000, Mohammed, Afzal wrote: > Hi Paul, > > On Fri, Apr 06, 2012 at 12:43:06, Paul Walmsley wrote: > > Perhaps you might be willing to add some debugging to omap_mux_late_init() > > to find out what part of that function is causing it to hang? > > It is getting hung as interrupt handler "omap_hwmod_mux_handle_irq" > is being repeatedly called. > Hi Afzal, can you try the attached patch with this branch and omap3evm board? I don't have the board myself so I can't test it myself (I tested this with omap3beagle and it works with that one.) -Tero
>From 26733dd988ccc9e72355a39e01b2d6e9215a892d Mon Sep 17 00:00:00 2001 From: Tero Kristo <t-kristo@xxxxxx> Date: Mon, 23 Apr 2012 12:14:46 +0300 Subject: [PATCH] ARM: OMAP3: PM: move wakeup event ack to hwmod_io handler PRCM IO interrupts are handled with a shared interrupt handler logic. Currently hwmod_io is processing the actual event, but the acking of the IO wakeups is done from the PM code with a separate handler. If a wakeup event is detected during init before the PM code is in place, the interrupt handler can hang in an infinite loop. Fix this by removing the pm_io handler, and calling its functionality from within the hwmod_io handler. This fix applies only to OMAP3, as OMAP4 does not have similar wakeup handling logic. Signed-off-by: Tero Kristo <t-kristo@xxxxxx> --- arch/arm/mach-omap2/mux.c | 18 +++++++++++++++++- arch/arm/mach-omap2/pm.h | 1 + arch/arm/mach-omap2/pm34xx.c | 18 ++---------------- 3 files changed, 20 insertions(+), 17 deletions(-) diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c index 65c3391..17349e3 100644 --- a/arch/arm/mach-omap2/mux.c +++ b/arch/arm/mach-omap2/mux.c @@ -41,6 +41,7 @@ #include "control.h" #include "mux.h" #include "prm.h" +#include "pm.h" #define OMAP_MUX_BASE_OFFSET 0x30 /* Offset from CTRL_BASE */ #define OMAP_MUX_BASE_SZ 0x5ca @@ -427,6 +428,13 @@ static irqreturn_t omap_hwmod_mux_handle_irq(int irq, void *unused) return IRQ_HANDLED; } +static irqreturn_t omap34xx_hwmod_mux_handle_irq(int irq, void *unused) +{ + omap_hwmod_for_each(_omap_hwmod_mux_handle_irq, NULL); + prcm_int_ack_io(); + return IRQ_HANDLED; +} + /* Assumes the calling function takes care of locking */ void omap_hwmod_mux(struct omap_hwmod_mux_info *hmux, u8 state) { @@ -792,6 +800,7 @@ static int __init omap_mux_late_init(void) { struct omap_mux_partition *partition; int ret; + irq_handler_t irq_handler; list_for_each_entry(partition, &mux_partitions, node) { struct omap_mux_entry *e, *tmp; @@ -812,12 +821,19 @@ static int __init omap_mux_late_init(void) } } +#ifdef CONFIG_PM + if (cpu_is_omap34xx()) + irq_handler = omap34xx_hwmod_mux_handle_irq; + else + irq_handler = omap_hwmod_mux_handle_irq; + ret = request_irq(omap_prcm_event_to_irq("io"), - omap_hwmod_mux_handle_irq, IRQF_SHARED | IRQF_NO_SUSPEND, + irq_handler, IRQF_SHARED | IRQF_NO_SUSPEND, "hwmod_io", omap_mux_late_init); if (ret) pr_warning("mux: Failed to setup hwmod io irq %d\n", ret); +#endif omap_mux_dbg_init(); diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h index 36fa90b..09ba9e7 100644 --- a/arch/arm/mach-omap2/pm.h +++ b/arch/arm/mach-omap2/pm.h @@ -20,6 +20,7 @@ extern void omap3_pm_off_mode_enable(int); extern void omap_sram_idle(void); extern int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state); extern int omap3_idle_init(void); +extern void prcm_int_ack_io(void); extern int omap4_idle_init(void); extern int omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused); extern int (*omap_pm_suspend)(void); diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c index afe3dda..cea4408 100644 --- a/arch/arm/mach-omap2/pm34xx.c +++ b/arch/arm/mach-omap2/pm34xx.c @@ -182,14 +182,10 @@ static int prcm_clear_mod_irqs(s16 module, u8 regs, u32 ignore_bits) return c; } -static irqreturn_t _prcm_int_handle_io(int irq, void *unused) +void prcm_int_ack_io(void) { - int c; - - c = prcm_clear_mod_irqs(WKUP_MOD, 1, + prcm_clear_mod_irqs(WKUP_MOD, 1, ~(OMAP3430_ST_IO_MASK | OMAP3430_ST_IO_CHAIN_MASK)); - - return c ? IRQ_HANDLED : IRQ_NONE; } static irqreturn_t _prcm_int_handle_wakeup(int irq, void *unused) @@ -683,16 +679,6 @@ static int __init omap3_pm_init(void) goto err1; } - /* IO interrupt is shared with mux code */ - ret = request_irq(omap_prcm_event_to_irq("io"), - _prcm_int_handle_io, IRQF_SHARED | IRQF_NO_SUSPEND, "pm_io", - omap3_pm_init); - - if (ret) { - pr_err("pm: Failed to request pm_io irq\n"); - goto err1; - } - ret = pwrdm_for_each(pwrdms_setup, NULL); if (ret) { printk(KERN_ERR "Failed to setup powerdomains\n"); -- 1.7.4.1