From 13a3fe52f7525d7b327f1f6766826fe9668bd749 Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Fri, 16 Dec 2011 14:36:59 -0700 Subject: ARM: OMAP2+: mux: add support for PAD wakeup interrupts OMAP mux now parses active wakeup events from pad registers and calls corresponding hwmod ISRs once a wakeup is detected. This is accomplished by registering an interrupt handler for PRCM IO event, which is raised every time the HW detects wakeups. [paul@pwsan.com: This patch is a merge of Govindraj R's "ARM: OMAP2+: hwmod: Add API to check IO PAD wakeup status" patch, Tero Kristo's "ARM: OMAP2+: mux: add support for PAD wakeup interrupts" patch, and part of Tero's "ARM: OMAP: mux: add support for selecting mpu_irq for each wakeup pad" patch.] Signed-off-by: Tero Kristo Cc: Govindraj.R Tested-by: Kevin Hilman Reviewed-by: Kevin Hilman Acked-by: Tony Lindgren [paul@pwsan.com: reduced indentation level; renamed omap_hwmod function; improved function documentation; modified to iterate only through dynamic pads; modified to skip pads where idle mode doesn't enable wakeups; split patches] Signed-off-by: Paul Walmsley --- arch/arm/plat-omap/include/plat/omap_hwmod.h | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h index 8b372ede17c1..f7054926f4e7 100644 --- a/arch/arm/plat-omap/include/plat/omap_hwmod.h +++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h @@ -97,6 +97,7 @@ struct omap_hwmod_mux_info { struct omap_device_pad *pads; int nr_pads_dynamic; struct omap_device_pad **pads_dynamic; + int *irqs; bool enabled; }; -- cgit v1.2.3-55-g7522 From abc2d5456334d548328978d0b0d22c0e5d44cdcd Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Fri, 16 Dec 2011 14:36:59 -0700 Subject: ARM: OMAP: hwmod: add support for selecting mpu_irq for each wakeup pad By default all registered pads will trigger mpu_irqs[0]. Now there is an API for selecting used mpu_irq on pad basis, which can be used to trigger different irq handlers for different pads in the same hwmod. Each pad that requires its interrupt to be re-routed this way must have a separate call to omap_hwmod_pad_route_irq(hwmod, pad, irq). Signed-off-by: Tero Kristo Acked-by: Tony Lindgren Tested-by: Kevin Hilman Reviewed-by: Kevin Hilman [paul@pwsan.com: moved fn to omap_hwmod.c; separated fn from mux scan_wakeups changes; added kerneldoc] Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/omap_hwmod.c | 55 ++++++++++++++++++++++++++++ arch/arm/plat-omap/include/plat/omap_hwmod.h | 2 + 2 files changed, 57 insertions(+) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index 21ffd8a831c3..7ea3df517d2b 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -136,6 +136,7 @@ #include #include #include +#include #include #include @@ -2709,3 +2710,57 @@ int omap_hwmod_no_setup_reset(struct omap_hwmod *oh) return 0; } + +/** + * omap_hwmod_pad_route_irq - route an I/O pad wakeup to a particular MPU IRQ + * @oh: struct omap_hwmod * containing hwmod mux entries + * @pad_idx: array index in oh->mux of the hwmod mux entry to route wakeup + * @irq_idx: the hwmod mpu_irqs array index of the IRQ to trigger on wakeup + * + * When an I/O pad wakeup arrives for the dynamic or wakeup hwmod mux + * entry number @pad_idx for the hwmod @oh, trigger the interrupt + * service routine for the hwmod's mpu_irqs array index @irq_idx. If + * this function is not called for a given pad_idx, then the ISR + * associated with @oh's first MPU IRQ will be triggered when an I/O + * pad wakeup occurs on that pad. Note that @pad_idx is the index of + * the _dynamic or wakeup_ entry: if there are other entries not + * marked with OMAP_DEVICE_PAD_WAKEUP or OMAP_DEVICE_PAD_REMUX, these + * entries are NOT COUNTED in the dynamic pad index. This function + * must be called separately for each pad that requires its interrupt + * to be re-routed this way. Returns -EINVAL if there is an argument + * problem or if @oh does not have hwmod mux entries or MPU IRQs; + * returns -ENOMEM if memory cannot be allocated; or 0 upon success. + * + * XXX This function interface is fragile. Rather than using array + * indexes, which are subject to unpredictable change, it should be + * using hwmod IRQ names, and some other stable key for the hwmod mux + * pad records. + */ +int omap_hwmod_pad_route_irq(struct omap_hwmod *oh, int pad_idx, int irq_idx) +{ + int nr_irqs; + + might_sleep(); + + if (!oh || !oh->mux || !oh->mpu_irqs || pad_idx < 0 || + pad_idx >= oh->mux->nr_pads_dynamic) + return -EINVAL; + + /* Check the number of available mpu_irqs */ + for (nr_irqs = 0; oh->mpu_irqs[nr_irqs].irq >= 0; nr_irqs++) + ; + + if (irq_idx >= nr_irqs) + return -EINVAL; + + if (!oh->mux->irqs) { + /* XXX What frees this? */ + oh->mux->irqs = kzalloc(sizeof(int) * oh->mux->nr_pads_dynamic, + GFP_KERNEL); + if (!oh->mux->irqs) + return -ENOMEM; + } + oh->mux->irqs[pad_idx] = irq_idx; + + return 0; +} diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h index f7054926f4e7..ef4bf313fe74 100644 --- a/arch/arm/plat-omap/include/plat/omap_hwmod.h +++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h @@ -605,6 +605,8 @@ int omap_hwmod_get_context_loss_count(struct omap_hwmod *oh); int omap_hwmod_no_setup_reset(struct omap_hwmod *oh); +int omap_hwmod_pad_route_irq(struct omap_hwmod *oh, int pad_idx, int irq_idx); + /* * Chip variant-specific hwmod init routines - XXX should be converted * to use initcalls once the initial boot ordering is straightened out -- cgit v1.2.3-55-g7522