浏览代码

OMAP3: PM: Disable interrupt controller AUTOIDLE before WFI

OMAP interrupt controller goes to unknown state when there is right
combination of l3,l4 sleep/wake-up transitions, l4 autoidle in
interrupt controller and some interrupt. When this happens, interrupts
are not delivered to ARM anymore and ARM will remain in WFI (wait for
interrupt) until interrupt controller is forced to wake-up
(i.e. lauterbach).

Signed-off-by: Tero Kristo <tero.kristo@nokia.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
Tero Kristo 16 年之前
父节点
当前提交
f18cc2ff5e
共有 3 个文件被更改,包括 16 次插入0 次删除
  1. 12 0
      arch/arm/mach-omap2/irq.c
  2. 2 0
      arch/arm/mach-omap2/pm34xx.c
  3. 2 0
      arch/arm/plat-omap/include/plat/irqs.h

+ 12 - 0
arch/arm/mach-omap2/irq.c

@@ -280,4 +280,16 @@ void omap3_intc_suspend(void)
 	/* A pending interrupt would prevent OMAP from entering suspend */
 	/* A pending interrupt would prevent OMAP from entering suspend */
 	omap_ack_irq(0);
 	omap_ack_irq(0);
 }
 }
+
+void omap3_intc_prepare_idle(void)
+{
+	/* Disable autoidle as it can stall interrupt controller */
+	intc_bank_write_reg(0, &irq_banks[0], INTC_SYSCONFIG);
+}
+
+void omap3_intc_resume_idle(void)
+{
+	/* Re-enable autoidle */
+	intc_bank_write_reg(1, &irq_banks[0], INTC_SYSCONFIG);
+}
 #endif /* CONFIG_ARCH_OMAP3 */
 #endif /* CONFIG_ARCH_OMAP3 */

+ 2 - 0
arch/arm/mach-omap2/pm34xx.c

@@ -392,6 +392,7 @@ void omap_sram_idle(void)
 		prm_set_mod_reg_bits(OMAP3430_EN_IO, WKUP_MOD, PM_WKEN);
 		prm_set_mod_reg_bits(OMAP3430_EN_IO, WKUP_MOD, PM_WKEN);
 		omap3_enable_io_chain();
 		omap3_enable_io_chain();
 	}
 	}
+	omap3_intc_prepare_idle();
 
 
 	/*
 	/*
 	* On EMU/HS devices ROM code restores a SRDC value
 	* On EMU/HS devices ROM code restores a SRDC value
@@ -438,6 +439,7 @@ void omap_sram_idle(void)
 					       OMAP3430_GR_MOD,
 					       OMAP3430_GR_MOD,
 					       OMAP3_PRM_VOLTCTRL_OFFSET);
 					       OMAP3_PRM_VOLTCTRL_OFFSET);
 	}
 	}
+	omap3_intc_resume_idle();
 
 
 	/* PER */
 	/* PER */
 	if (per_next_state < PWRDM_POWER_ON) {
 	if (per_next_state < PWRDM_POWER_ON) {

+ 2 - 0
arch/arm/plat-omap/include/plat/irqs.h

@@ -500,6 +500,8 @@ extern int omap_irq_pending(void);
 void omap_intc_save_context(void);
 void omap_intc_save_context(void);
 void omap_intc_restore_context(void);
 void omap_intc_restore_context(void);
 void omap3_intc_suspend(void);
 void omap3_intc_suspend(void);
+void omap3_intc_prepare_idle(void);
+void omap3_intc_resume_idle(void);
 #endif
 #endif
 
 
 #include <mach/hardware.h>
 #include <mach/hardware.h>