aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm')
-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;
61 * that any peripheral wake-up events occurring while attempting to 61 * that any peripheral wake-up events occurring while attempting to
62 * clear the PM_WKST_x are detected and cleared. 62 * clear the PM_WKST_x are detected and cleared.
63 */ 63 */
64static void prcm_clear_mod_irqs(s16 module, u8 regs) 64static int prcm_clear_mod_irqs(s16 module, u8 regs)
65{ 65{
66 u32 wkst, fclk, iclk; 66 u32 wkst, fclk, iclk;
67 u16 wkst_off = (regs == 3) ? OMAP3430ES2_PM_WKST3 : PM_WKST1; 67 u16 wkst_off = (regs == 3) ? OMAP3430ES2_PM_WKST3 : PM_WKST1;
@@ -69,6 +69,7 @@ static void prcm_clear_mod_irqs(s16 module, u8 regs)
69 u16 iclk_off = (regs == 3) ? CM_ICLKEN3 : CM_ICLKEN1; 69 u16 iclk_off = (regs == 3) ? CM_ICLKEN3 : CM_ICLKEN1;
70 u16 grpsel_off = (regs == 3) ? 70 u16 grpsel_off = (regs == 3) ?
71 OMAP3430ES2_PM_MPUGRPSEL3 : OMAP3430_PM_MPUGRPSEL; 71 OMAP3430ES2_PM_MPUGRPSEL3 : OMAP3430_PM_MPUGRPSEL;
72 int c = 0;
72 73
73 wkst = prm_read_mod_reg(module, wkst_off); 74 wkst = prm_read_mod_reg(module, wkst_off);
74 wkst &= prm_read_mod_reg(module, grpsel_off); 75 wkst &= prm_read_mod_reg(module, grpsel_off);
@@ -80,10 +81,28 @@ static void prcm_clear_mod_irqs(s16 module, u8 regs)
80 cm_set_mod_reg_bits(wkst, module, fclk_off); 81 cm_set_mod_reg_bits(wkst, module, fclk_off);
81 prm_write_mod_reg(wkst, module, wkst_off); 82 prm_write_mod_reg(wkst, module, wkst_off);
82 wkst = prm_read_mod_reg(module, wkst_off); 83 wkst = prm_read_mod_reg(module, wkst_off);
84 c++;
83 } 85 }
84 cm_write_mod_reg(iclk, module, iclk_off); 86 cm_write_mod_reg(iclk, module, iclk_off);
85 cm_write_mod_reg(fclk, module, fclk_off); 87 cm_write_mod_reg(fclk, module, fclk_off);
86 } 88 }
89
90 return c;
91}
92
93static int _prcm_int_handle_wakeup(void)
94{
95 int c;
96
97 c = prcm_clear_mod_irqs(WKUP_MOD, 1);
98 c += prcm_clear_mod_irqs(CORE_MOD, 1);
99 c += prcm_clear_mod_irqs(OMAP3430_PER_MOD, 1);
100 if (omap_rev() > OMAP3430_REV_ES1_0) {
101 c += prcm_clear_mod_irqs(CORE_MOD, 3);
102 c += prcm_clear_mod_irqs(OMAP3430ES2_USBHOST_MOD, 1);
103 }
104
105 return c;
87} 106}
88 107
89/* 108/*
@@ -106,18 +125,27 @@ static void prcm_clear_mod_irqs(s16 module, u8 regs)
106static irqreturn_t prcm_interrupt_handler (int irq, void *dev_id) 125static irqreturn_t prcm_interrupt_handler (int irq, void *dev_id)
107{ 126{
108 u32 irqstatus_mpu; 127 u32 irqstatus_mpu;
128 int c = 0;
109 129
110 do { 130 do {
111 prcm_clear_mod_irqs(WKUP_MOD, 1);
112 prcm_clear_mod_irqs(CORE_MOD, 1);
113 prcm_clear_mod_irqs(OMAP3430_PER_MOD, 1);
114 if (omap_rev() > OMAP3430_REV_ES1_0) {
115 prcm_clear_mod_irqs(CORE_MOD, 3);
116 prcm_clear_mod_irqs(OMAP3430ES2_USBHOST_MOD, 1);
117 }
118
119 irqstatus_mpu = prm_read_mod_reg(OCP_MOD, 131 irqstatus_mpu = prm_read_mod_reg(OCP_MOD,
120 OMAP3_PRM_IRQSTATUS_MPU_OFFSET); 132 OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
133
134 if (irqstatus_mpu & (OMAP3430_WKUP_ST | OMAP3430_IO_ST)) {
135 c = _prcm_int_handle_wakeup();
136
137 /*
138 * Is the MPU PRCM interrupt handler racing with the
139 * IVA2 PRCM interrupt handler ?
140 */
141 WARN(c == 0, "prcm: WARNING: PRCM indicated MPU wakeup "
142 "but no wakeup sources are marked\n");
143 } else {
144 /* XXX we need to expand our PRCM interrupt handler */
145 WARN(1, "prcm: WARNING: PRCM interrupt received, but "
146 "no code to handle it (%08x)\n", irqstatus_mpu);
147 }
148
121 prm_write_mod_reg(irqstatus_mpu, OCP_MOD, 149 prm_write_mod_reg(irqstatus_mpu, OCP_MOD,
122 OMAP3_PRM_IRQSTATUS_MPU_OFFSET); 150 OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
123 151