diff options
author | Tero Kristo <t-kristo@ti.com> | 2011-12-16 16:36:59 -0500 |
---|---|---|
committer | Paul Walmsley <paul@pwsan.com> | 2011-12-16 16:36:59 -0500 |
commit | abc2d5456334d548328978d0b0d22c0e5d44cdcd (patch) | |
tree | e274951ab35883a19abbbdf2b497afe95dc88ae3 /arch/arm/mach-omap2/omap_hwmod.c | |
parent | 13a3fe52f7525d7b327f1f6766826fe9668bd749 (diff) |
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 <t-kristo@ti.com>
Acked-by: Tony Lindgren <tony@atomide.com>
Tested-by: Kevin Hilman <khilman@ti.com>
Reviewed-by: Kevin Hilman <khilman@ti.com>
[paul@pwsan.com: moved fn to omap_hwmod.c; separated fn from mux scan_wakeups
changes; added kerneldoc]
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Diffstat (limited to 'arch/arm/mach-omap2/omap_hwmod.c')
-rw-r--r-- | arch/arm/mach-omap2/omap_hwmod.c | 55 |
1 files changed, 55 insertions, 0 deletions
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 @@ | |||
136 | #include <linux/list.h> | 136 | #include <linux/list.h> |
137 | #include <linux/mutex.h> | 137 | #include <linux/mutex.h> |
138 | #include <linux/spinlock.h> | 138 | #include <linux/spinlock.h> |
139 | #include <linux/slab.h> | ||
139 | 140 | ||
140 | #include <plat/common.h> | 141 | #include <plat/common.h> |
141 | #include <plat/cpu.h> | 142 | #include <plat/cpu.h> |
@@ -2709,3 +2710,57 @@ int omap_hwmod_no_setup_reset(struct omap_hwmod *oh) | |||
2709 | 2710 | ||
2710 | return 0; | 2711 | return 0; |
2711 | } | 2712 | } |
2713 | |||
2714 | /** | ||
2715 | * omap_hwmod_pad_route_irq - route an I/O pad wakeup to a particular MPU IRQ | ||
2716 | * @oh: struct omap_hwmod * containing hwmod mux entries | ||
2717 | * @pad_idx: array index in oh->mux of the hwmod mux entry to route wakeup | ||
2718 | * @irq_idx: the hwmod mpu_irqs array index of the IRQ to trigger on wakeup | ||
2719 | * | ||
2720 | * When an I/O pad wakeup arrives for the dynamic or wakeup hwmod mux | ||
2721 | * entry number @pad_idx for the hwmod @oh, trigger the interrupt | ||
2722 | * service routine for the hwmod's mpu_irqs array index @irq_idx. If | ||
2723 | * this function is not called for a given pad_idx, then the ISR | ||
2724 | * associated with @oh's first MPU IRQ will be triggered when an I/O | ||
2725 | * pad wakeup occurs on that pad. Note that @pad_idx is the index of | ||
2726 | * the _dynamic or wakeup_ entry: if there are other entries not | ||
2727 | * marked with OMAP_DEVICE_PAD_WAKEUP or OMAP_DEVICE_PAD_REMUX, these | ||
2728 | * entries are NOT COUNTED in the dynamic pad index. This function | ||
2729 | * must be called separately for each pad that requires its interrupt | ||
2730 | * to be re-routed this way. Returns -EINVAL if there is an argument | ||
2731 | * problem or if @oh does not have hwmod mux entries or MPU IRQs; | ||
2732 | * returns -ENOMEM if memory cannot be allocated; or 0 upon success. | ||
2733 | * | ||
2734 | * XXX This function interface is fragile. Rather than using array | ||
2735 | * indexes, which are subject to unpredictable change, it should be | ||
2736 | * using hwmod IRQ names, and some other stable key for the hwmod mux | ||
2737 | * pad records. | ||
2738 | */ | ||
2739 | int omap_hwmod_pad_route_irq(struct omap_hwmod *oh, int pad_idx, int irq_idx) | ||
2740 | { | ||
2741 | int nr_irqs; | ||
2742 | |||
2743 | might_sleep(); | ||
2744 | |||
2745 | if (!oh || !oh->mux || !oh->mpu_irqs || pad_idx < 0 || | ||
2746 | pad_idx >= oh->mux->nr_pads_dynamic) | ||
2747 | return -EINVAL; | ||
2748 | |||
2749 | /* Check the number of available mpu_irqs */ | ||
2750 | for (nr_irqs = 0; oh->mpu_irqs[nr_irqs].irq >= 0; nr_irqs++) | ||
2751 | ; | ||
2752 | |||
2753 | if (irq_idx >= nr_irqs) | ||
2754 | return -EINVAL; | ||
2755 | |||
2756 | if (!oh->mux->irqs) { | ||
2757 | /* XXX What frees this? */ | ||
2758 | oh->mux->irqs = kzalloc(sizeof(int) * oh->mux->nr_pads_dynamic, | ||
2759 | GFP_KERNEL); | ||
2760 | if (!oh->mux->irqs) | ||
2761 | return -ENOMEM; | ||
2762 | } | ||
2763 | oh->mux->irqs[pad_idx] = irq_idx; | ||
2764 | |||
2765 | return 0; | ||
2766 | } | ||