* [RFC] omap: mux: add support for selecting mpu_irq for each wakeup pad
2011-10-28 12:03 [RFC 0/1] change prcm chain handler to support pad to irq mapping Tero Kristo
@ 2011-10-28 12:03 ` Tero Kristo
2011-11-08 0:17 ` Kevin Hilman
0 siblings, 1 reply; 3+ messages in thread
From: Tero Kristo @ 2011-10-28 12:03 UTC (permalink / raw)
To: linux-omap; +Cc: paul
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>
---
arch/arm/mach-omap2/mux.c | 53 +++++++++++++++++++++++---
arch/arm/mach-omap2/omap_hwmod.c | 7 ---
arch/arm/plat-omap/include/plat/omap_hwmod.h | 4 ++
3 files changed, 51 insertions(+), 13 deletions(-)
diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c
index 642fe3f..cfe36ee 100644
--- a/arch/arm/mach-omap2/mux.c
+++ b/arch/arm/mach-omap2/mux.c
@@ -354,6 +354,33 @@ err1:
return NULL;
}
+int omap_hwmod_pad_route_irq(struct omap_hwmod *oh, int pad_idx,
+ int irq_idx)
+{
+ int nr_irqs;
+
+ 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) {
+ 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;
+}
+
/**
* omap_hwmod_mux_get_wake_status - omap hwmod check pad wakeup
* @hmux: Pads for a hwmod
@@ -362,11 +389,13 @@ err1:
* Returns true if wakeup event is set for pad else false
* if wakeup is not occured or pads are not avialable.
*/
-bool omap_hwmod_mux_get_wake_status(struct omap_hwmod_mux_info *hmux)
+static bool omap_hwmod_mux_scan_wakeups(struct omap_hwmod_mux_info *hmux,
+ struct omap_hwmod_irq_info *mpu_irqs)
{
int i;
unsigned int val;
- u8 ret = false;
+ u32 handled_irqs = 0;
+ int irq;
for (i = 0; i < hmux->nr_pads; i++) {
struct omap_device_pad *pad = &hmux->pads[i];
@@ -375,15 +404,27 @@ bool omap_hwmod_mux_get_wake_status(struct omap_hwmod_mux_info *hmux)
val = omap_mux_read(pad->partition,
pad->mux->reg_offset);
if (val & OMAP_WAKEUP_EVENT) {
- ret = true;
pr_info("wkup detected: %04x\n",
pad->mux->reg_offset);
- break;
+ if (hmux->irqs) {
+ irq = hmux->irqs[i];
+ /*
+ * make sure we only handle each
+ * irq once
+ */
+ if (handled_irqs & 1 << irq)
+ continue;
+
+ handled_irqs |= 1 << irq;
+
+ generic_handle_irq(mpu_irqs[irq].irq);
+ } else
+ return true;
}
}
}
- return ret;
+ return false;
}
/**
@@ -396,7 +437,7 @@ static int _omap_hwmod_mux_handle_irq(struct omap_hwmod *oh, void *data)
{
if (!oh->mux || !oh->mux->enabled)
return 0;
- if (omap_hwmod_mux_get_wake_status(oh->mux))
+ if (omap_hwmod_mux_scan_wakeups(oh->mux, oh->mpu_irqs))
generic_handle_irq(oh->mpu_irqs[0].irq);
return 0;
}
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index a8b24d7..e751dd9 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -2724,10 +2724,3 @@ int omap_hwmod_no_setup_reset(struct omap_hwmod *oh)
return 0;
}
-
-int omap_hwmod_pad_get_wakeup_status(struct omap_hwmod *oh)
-{
- if (oh && oh->mux)
- return omap_hwmod_mux_get_wake_status(oh->mux);
- return -EINVAL;
-}
diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h
index 9c70cc8..4a89a06 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;
};
@@ -607,6 +608,9 @@ u32 omap_hwmod_get_context_loss_count(struct omap_hwmod *oh);
int omap_hwmod_no_setup_reset(struct omap_hwmod *oh);
int omap_hwmod_pad_get_wakeup_status(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
--
1.7.4.1
Texas Instruments Oy, Porkkalankatu 22, 00180 Helsinki, Finland. Business ID: 0115040-6. Domicile: Helsinki
^ permalink raw reply related [flat|nested] 3+ messages in thread