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 <[email protected]>
---
 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
 

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to