diff options
Diffstat (limited to 'arch/arm/mach-omap2/prm2xxx_3xxx.c')
-rw-r--r-- | arch/arm/mach-omap2/prm2xxx_3xxx.c | 97 |
1 files changed, 96 insertions, 1 deletions
diff --git a/arch/arm/mach-omap2/prm2xxx_3xxx.c b/arch/arm/mach-omap2/prm2xxx_3xxx.c index 9a08ba397327..c1c4d86a79a8 100644 --- a/arch/arm/mach-omap2/prm2xxx_3xxx.c +++ b/arch/arm/mach-omap2/prm2xxx_3xxx.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * OMAP2/3 PRM module functions | 2 | * OMAP2/3 PRM module functions |
3 | * | 3 | * |
4 | * Copyright (C) 2010 Texas Instruments, Inc. | 4 | * Copyright (C) 2010-2011 Texas Instruments, Inc. |
5 | * Copyright (C) 2010 Nokia Corporation | 5 | * Copyright (C) 2010 Nokia Corporation |
6 | * Benoît Cousson | 6 | * Benoît Cousson |
7 | * Paul Walmsley | 7 | * Paul Walmsley |
@@ -27,6 +27,24 @@ | |||
27 | #include "prm-regbits-24xx.h" | 27 | #include "prm-regbits-24xx.h" |
28 | #include "prm-regbits-34xx.h" | 28 | #include "prm-regbits-34xx.h" |
29 | 29 | ||
30 | static const struct omap_prcm_irq omap3_prcm_irqs[] = { | ||
31 | OMAP_PRCM_IRQ("wkup", 0, 0), | ||
32 | OMAP_PRCM_IRQ("io", 9, 1), | ||
33 | }; | ||
34 | |||
35 | static struct omap_prcm_irq_setup omap3_prcm_irq_setup = { | ||
36 | .ack = OMAP3_PRM_IRQSTATUS_MPU_OFFSET, | ||
37 | .mask = OMAP3_PRM_IRQENABLE_MPU_OFFSET, | ||
38 | .nr_regs = 1, | ||
39 | .irqs = omap3_prcm_irqs, | ||
40 | .nr_irqs = ARRAY_SIZE(omap3_prcm_irqs), | ||
41 | .irq = INT_34XX_PRCM_MPU_IRQ, | ||
42 | .read_pending_irqs = &omap3xxx_prm_read_pending_irqs, | ||
43 | .ocp_barrier = &omap3xxx_prm_ocp_barrier, | ||
44 | .save_and_clear_irqen = &omap3xxx_prm_save_and_clear_irqen, | ||
45 | .restore_irqen = &omap3xxx_prm_restore_irqen, | ||
46 | }; | ||
47 | |||
30 | u32 omap2_prm_read_mod_reg(s16 module, u16 idx) | 48 | u32 omap2_prm_read_mod_reg(s16 module, u16 idx) |
31 | { | 49 | { |
32 | return __raw_readl(prm_base + module + idx); | 50 | return __raw_readl(prm_base + module + idx); |
@@ -212,3 +230,80 @@ u32 omap3_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset) | |||
212 | { | 230 | { |
213 | return omap2_prm_rmw_mod_reg_bits(mask, bits, OMAP3430_GR_MOD, offset); | 231 | return omap2_prm_rmw_mod_reg_bits(mask, bits, OMAP3430_GR_MOD, offset); |
214 | } | 232 | } |
233 | |||
234 | /** | ||
235 | * omap3xxx_prm_read_pending_irqs - read pending PRM MPU IRQs into @events | ||
236 | * @events: ptr to a u32, preallocated by caller | ||
237 | * | ||
238 | * Read PRM_IRQSTATUS_MPU bits, AND'ed with the currently-enabled PRM | ||
239 | * MPU IRQs, and store the result into the u32 pointed to by @events. | ||
240 | * No return value. | ||
241 | */ | ||
242 | void omap3xxx_prm_read_pending_irqs(unsigned long *events) | ||
243 | { | ||
244 | u32 mask, st; | ||
245 | |||
246 | /* XXX Can the mask read be avoided (e.g., can it come from RAM?) */ | ||
247 | mask = omap2_prm_read_mod_reg(OCP_MOD, OMAP3_PRM_IRQENABLE_MPU_OFFSET); | ||
248 | st = omap2_prm_read_mod_reg(OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET); | ||
249 | |||
250 | events[0] = mask & st; | ||
251 | } | ||
252 | |||
253 | /** | ||
254 | * omap3xxx_prm_ocp_barrier - force buffered MPU writes to the PRM to complete | ||
255 | * | ||
256 | * Force any buffered writes to the PRM IP block to complete. Needed | ||
257 | * by the PRM IRQ handler, which reads and writes directly to the IP | ||
258 | * block, to avoid race conditions after acknowledging or clearing IRQ | ||
259 | * bits. No return value. | ||
260 | */ | ||
261 | void omap3xxx_prm_ocp_barrier(void) | ||
262 | { | ||
263 | omap2_prm_read_mod_reg(OCP_MOD, OMAP3_PRM_REVISION_OFFSET); | ||
264 | } | ||
265 | |||
266 | /** | ||
267 | * omap3xxx_prm_save_and_clear_irqen - save/clear PRM_IRQENABLE_MPU reg | ||
268 | * @saved_mask: ptr to a u32 array to save IRQENABLE bits | ||
269 | * | ||
270 | * Save the PRM_IRQENABLE_MPU register to @saved_mask. @saved_mask | ||
271 | * must be allocated by the caller. Intended to be used in the PRM | ||
272 | * interrupt handler suspend callback. The OCP barrier is needed to | ||
273 | * ensure the write to disable PRM interrupts reaches the PRM before | ||
274 | * returning; otherwise, spurious interrupts might occur. No return | ||
275 | * value. | ||
276 | */ | ||
277 | void omap3xxx_prm_save_and_clear_irqen(u32 *saved_mask) | ||
278 | { | ||
279 | saved_mask[0] = omap2_prm_read_mod_reg(OCP_MOD, | ||
280 | OMAP3_PRM_IRQENABLE_MPU_OFFSET); | ||
281 | omap2_prm_write_mod_reg(0, OCP_MOD, OMAP3_PRM_IRQENABLE_MPU_OFFSET); | ||
282 | |||
283 | /* OCP barrier */ | ||
284 | omap2_prm_read_mod_reg(OCP_MOD, OMAP3_PRM_REVISION_OFFSET); | ||
285 | } | ||
286 | |||
287 | /** | ||
288 | * omap3xxx_prm_restore_irqen - set PRM_IRQENABLE_MPU register from args | ||
289 | * @saved_mask: ptr to a u32 array of IRQENABLE bits saved previously | ||
290 | * | ||
291 | * Restore the PRM_IRQENABLE_MPU register from @saved_mask. Intended | ||
292 | * to be used in the PRM interrupt handler resume callback to restore | ||
293 | * values saved by omap3xxx_prm_save_and_clear_irqen(). No OCP | ||
294 | * barrier should be needed here; any pending PRM interrupts will fire | ||
295 | * once the writes reach the PRM. No return value. | ||
296 | */ | ||
297 | void omap3xxx_prm_restore_irqen(u32 *saved_mask) | ||
298 | { | ||
299 | omap2_prm_write_mod_reg(saved_mask[0], OCP_MOD, | ||
300 | OMAP3_PRM_IRQENABLE_MPU_OFFSET); | ||
301 | } | ||
302 | |||
303 | static int __init omap3xxx_prcm_init(void) | ||
304 | { | ||
305 | if (cpu_is_omap34xx()) | ||
306 | return omap_prcm_register_chain_handler(&omap3_prcm_irq_setup); | ||
307 | return 0; | ||
308 | } | ||
309 | subsys_initcall(omap3xxx_prcm_init); | ||