diff mbox

[PATCHv4,2/9] PRCM: Add support for PAD wakeup interrupts

Message ID 1309338303-2086-3-git-send-email-t-kristo@ti.com (mailing list archive)
State Changes Requested
Delegated to: Kevin Hilman
Headers show

Commit Message

Tero Kristo June 29, 2011, 9:04 a.m. UTC
PRCM interrupt handler will now parse registered pads to see whether there
is an active wakeup event. If there is a pending wakeup event, the registered
ISR will be called.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 arch/arm/mach-omap2/prcm.c             |   94 ++++++++++++++++++++++++++++++++
 arch/arm/plat-omap/include/plat/prcm.h |    5 ++
 2 files changed, 99 insertions(+), 0 deletions(-)

Comments

Govindraj R June 30, 2011, 5:10 p.m. UTC | #1
On Wed, Jun 29, 2011 at 2:34 PM, Tero Kristo <t-kristo@ti.com> wrote:
> PRCM interrupt handler will now parse registered pads to see whether there
> is an active wakeup event. If there is a pending wakeup event, the registered
> ISR will be called.
>
> Signed-off-by: Tero Kristo <t-kristo@ti.com>
> ---
>  arch/arm/mach-omap2/prcm.c             |   94 ++++++++++++++++++++++++++++++++
>  arch/arm/plat-omap/include/plat/prcm.h |    5 ++
>  2 files changed, 99 insertions(+), 0 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/prcm.c b/arch/arm/mach-omap2/prcm.c
> index 794e451..6b603eb 100644
> --- a/arch/arm/mach-omap2/prcm.c
> +++ b/arch/arm/mach-omap2/prcm.c
> @@ -30,6 +30,7 @@
>  #include <plat/common.h>
>  #include <plat/prcm.h>
>  #include <plat/irqs.h>
> +#include <plat/omap_hwmod.h>
>
>  #include "clock.h"
>  #include "clock2xxx.h"
> @@ -40,6 +41,7 @@
>  #include "prm-regbits-24xx.h"
>  #include "prm-regbits-44xx.h"
>  #include "control.h"
> +#include "mux.h"
>
>  void __iomem *prm_base;
>  void __iomem *cm_base;
> @@ -50,6 +52,15 @@ void __iomem *cm2_base;
>  /* Setup for the interrupt handling based on used platform */
>  static struct omap_prcm_irq_setup *irq_setup;
>
> +/* PAD handlers list */
> +struct pad_def {
> +       struct omap_device_pad *pad;
> +       unsigned int irq;
> +       struct list_head node;
> +};
> +
> +static LIST_HEAD(pad_handler_list);
> +
>  static void prcm_irq_ack(struct irq_data *data)
>  {
>        unsigned int prcm_irq = data->irq - OMAP_PRCM_IRQ_BASE;
> @@ -71,6 +82,24 @@ static void prcm_irq_unmask(struct irq_data *data)
>  static struct irq_chip_generic *prcm_irq_chips[OMAP_PRCM_MAX_NR_PENDING_REG];
>
>  /*
> + * Handler for PAD irqs, called from PRCM interrupt handler
> + */
> +static void omap_prcm_handle_pad_irqs(void)
> +{
> +       struct pad_def *def;
> +       u16 val = 0;
> +       list_for_each_entry(def, &pad_handler_list, node) {
> +               /* Read padconf value */
> +               val = omap_mux_read(def->pad->partition,
> +                       def->pad->mux->reg_offset);
> +
> +               /* If pad wakeupevent is active, call registered ISR */
> +               if (val & OMAP3_PADCONF_WAKEUPEVENT0)
> +                       generic_handle_irq(def->irq);
> +       }
> +}
> +
> +/*
>  * PRCM Interrupt Handler
>  *
>  * The PRM_IRQSTATUS_MPU register indicates if there are any pending
> @@ -92,6 +121,9 @@ static void prcm_irq_handler(unsigned int irq, struct irq_desc *desc)
>        unsigned long pending[OMAP_PRCM_MAX_NR_PENDING_REG];
>        struct irq_chip *chip = irq_desc_get_chip(desc);
>
> +       /* Handle PAD events first, we don't want to ack them before parse */
> +       omap_prcm_handle_pad_irqs();
> +
>        /*
>         * Loop until all pending irqs are handled, since
>         * generic_handle_irq(), called by prcm_irq_handle_virtirqs()
> @@ -139,6 +171,68 @@ int omap_prcm_event_to_irq(const char *name)
>  }
>
>  /*
> + * Register interrupt handler for a given omap_hwmod_mux. When the PRCM
> + * interrupt handler detects wakeupevent on the corresponding pad, the
> + * ISR will be called.
> + */
> +int omap_prcm_register_pad_irqs(struct omap_hwmod_mux_info *mux,
> +                               unsigned int irq)
> +{
> +       struct pad_def *def;
> +       int i;
> +       u16 val;
> +
> +       if (!mux)
> +               return 0;
> +
> +       for (i = 0; i < mux->nr_pads; i++) {
> +               if (!(mux->pads[i].enable & OMAP_PIN_INPUT))
> +                       continue;
> +

cant be some thing like below considering my pad has entry as [1]

if(!(mux->pads[i].flags & ( OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP))
        continue;


> +               def = kmalloc(sizeof(struct pad_def), GFP_ATOMIC);
> +               if (!def)
> +                       return -ENOMEM;
> +
> +               def->pad = mux->pads + i;
> +               def->irq = irq;
> +
> +               /* Enable pad wakeup */
> +               val = omap_mux_read(def->pad->partition,
> +                       def->pad->mux->reg_offset);
> +               val |= OMAP_WAKEUP_EN;
> +               omap_mux_write(def->pad->partition, val,
> +                       def->pad->mux->reg_offset);


I think all direct read write to mux data can be avoided,

just cant we do

mux->pads[i].idle |= OMAP_WAKEUP_EN;

considering if if I have a uart pad entry for rx as below,

[1]:

{
	.name   = "uart1_rx.uart1_rx",
	.flags  = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
	.enable = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0,
	.idle = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0,
},




> +
> +               list_add(&def->node, &pad_handler_list);
> +       }
> +       return 0;
> +}
> +
> +/*
> + * Unregister pad irqs associated with a hwmod mux
> + */
> +void omap_prcm_unregister_pad_irqs(struct omap_hwmod_mux_info *mux)
> +{
> +       struct pad_def *def;
> +       int i;
> +       u16 val;
> +
> +       list_for_each_entry(def, &pad_handler_list, node)
> +               for (i = 0; i < mux->nr_pads; i++)
> +                       if (def->pad == mux->pads + i) {
> +                               list_del(&def->node);
> +
> +                               /* Disable pad wakeup */
> +                               val = omap_mux_read(def->pad->partition,
> +                                       def->pad->mux->reg_offset);
> +                               val &= ~OMAP_WAKEUP_EN;

same here.

mux->pads[i].idle &= ~OMAP_WAKEUP_EN;

--
Thanks,
Govindraj.R


> +                               omap_mux_write(def->pad->partition, val,
> +                                       def->pad->mux->reg_offset);
> +                               kfree(def);
> +                       }
> +}
> +
> +/*
>  * Prepare the array of PRCM events corresponding to the current SoC,
>  * and set-up the chained interrupt handler mechanism.
>  */
> diff --git a/arch/arm/plat-omap/include/plat/prcm.h b/arch/arm/plat-omap/include/plat/prcm.h
> index 205b9b1..7987819 100644
> --- a/arch/arm/plat-omap/include/plat/prcm.h
> +++ b/arch/arm/plat-omap/include/plat/prcm.h
> @@ -66,10 +66,15 @@ struct omap_prcm_irq_setup {
>        int irq;
>  };
>
> +struct omap_hwmod_mux_info;
> +
>  int omap_prcm_event_to_irq(const char *name);
>  int omap_prcm_irq_init(void);
>  void omap_prcm_irq_setup(struct omap_prcm_irq_setup *setup);
>  void omap_prcm_irq_cleanup(void);
> +int omap_prcm_register_pad_irqs(struct omap_hwmod_mux_info *mux,
> +                               unsigned int irq);
> +void omap_prcm_unregister_pad_irqs(struct omap_hwmod_mux_info *mux);
>  u32 omap_prcm_get_reset_sources(void);
>  int omap2_cm_wait_idlest(void __iomem *reg, u32 mask, u8 idlest,
>                         const char *name);
> --
> 1.7.4.1
>
>
> Texas Instruments Oy, Tekniikantie 12, 02150 Espoo. Y-tunnus: 0115040-6. Kotipaikka: Helsinki
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Kevin Hilman July 1, 2011, 10:03 p.m. UTC | #2
Tero Kristo <t-kristo@ti.com> writes:

> PRCM interrupt handler will now parse registered pads to see whether there
> is an active wakeup event. If there is a pending wakeup event, the registered
> ISR will be called.
>
> Signed-off-by: Tero Kristo <t-kristo@ti.com>

This patch adds a new, duplicate mapping of pad-to-IRQ which is already
contained in each omap_hwmod.  See my comments on the v3 version of this
patch[1] which describes how I think this should be handled.

Kevin

[1] http://marc.info/?l=linux-omap&m=130895127714616&w=2
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/arch/arm/mach-omap2/prcm.c b/arch/arm/mach-omap2/prcm.c
index 794e451..6b603eb 100644
--- a/arch/arm/mach-omap2/prcm.c
+++ b/arch/arm/mach-omap2/prcm.c
@@ -30,6 +30,7 @@ 
 #include <plat/common.h>
 #include <plat/prcm.h>
 #include <plat/irqs.h>
+#include <plat/omap_hwmod.h>
 
 #include "clock.h"
 #include "clock2xxx.h"
@@ -40,6 +41,7 @@ 
 #include "prm-regbits-24xx.h"
 #include "prm-regbits-44xx.h"
 #include "control.h"
+#include "mux.h"
 
 void __iomem *prm_base;
 void __iomem *cm_base;
@@ -50,6 +52,15 @@  void __iomem *cm2_base;
 /* Setup for the interrupt handling based on used platform */
 static struct omap_prcm_irq_setup *irq_setup;
 
+/* PAD handlers list */
+struct pad_def {
+	struct omap_device_pad *pad;
+	unsigned int irq;
+	struct list_head node;
+};
+
+static LIST_HEAD(pad_handler_list);
+
 static void prcm_irq_ack(struct irq_data *data)
 {
 	unsigned int prcm_irq = data->irq - OMAP_PRCM_IRQ_BASE;
@@ -71,6 +82,24 @@  static void prcm_irq_unmask(struct irq_data *data)
 static struct irq_chip_generic *prcm_irq_chips[OMAP_PRCM_MAX_NR_PENDING_REG];
 
 /*
+ * Handler for PAD irqs, called from PRCM interrupt handler
+ */
+static void omap_prcm_handle_pad_irqs(void)
+{
+	struct pad_def *def;
+	u16 val = 0;
+	list_for_each_entry(def, &pad_handler_list, node) {
+		/* Read padconf value */
+		val = omap_mux_read(def->pad->partition,
+			def->pad->mux->reg_offset);
+
+		/* If pad wakeupevent is active, call registered ISR */
+		if (val & OMAP3_PADCONF_WAKEUPEVENT0)
+			generic_handle_irq(def->irq);
+	}
+}
+
+/*
  * PRCM Interrupt Handler
  *
  * The PRM_IRQSTATUS_MPU register indicates if there are any pending
@@ -92,6 +121,9 @@  static void prcm_irq_handler(unsigned int irq, struct irq_desc *desc)
 	unsigned long pending[OMAP_PRCM_MAX_NR_PENDING_REG];
 	struct irq_chip *chip = irq_desc_get_chip(desc);
 
+	/* Handle PAD events first, we don't want to ack them before parse */
+	omap_prcm_handle_pad_irqs();
+
 	/*
 	 * Loop until all pending irqs are handled, since
 	 * generic_handle_irq(), called by prcm_irq_handle_virtirqs()
@@ -139,6 +171,68 @@  int omap_prcm_event_to_irq(const char *name)
 }
 
 /*
+ * Register interrupt handler for a given omap_hwmod_mux. When the PRCM
+ * interrupt handler detects wakeupevent on the corresponding pad, the
+ * ISR will be called.
+ */
+int omap_prcm_register_pad_irqs(struct omap_hwmod_mux_info *mux,
+				unsigned int irq)
+{
+	struct pad_def *def;
+	int i;
+	u16 val;
+
+	if (!mux)
+		return 0;
+
+	for (i = 0; i < mux->nr_pads; i++) {
+		if (!(mux->pads[i].enable & OMAP_PIN_INPUT))
+			continue;
+
+		def = kmalloc(sizeof(struct pad_def), GFP_ATOMIC);
+		if (!def)
+			return -ENOMEM;
+
+		def->pad = mux->pads + i;
+		def->irq = irq;
+
+		/* Enable pad wakeup */
+		val = omap_mux_read(def->pad->partition,
+			def->pad->mux->reg_offset);
+		val |= OMAP_WAKEUP_EN;
+		omap_mux_write(def->pad->partition, val,
+			def->pad->mux->reg_offset);
+
+		list_add(&def->node, &pad_handler_list);
+	}
+	return 0;
+}
+
+/*
+ * Unregister pad irqs associated with a hwmod mux
+ */
+void omap_prcm_unregister_pad_irqs(struct omap_hwmod_mux_info *mux)
+{
+	struct pad_def *def;
+	int i;
+	u16 val;
+
+	list_for_each_entry(def, &pad_handler_list, node)
+		for (i = 0; i < mux->nr_pads; i++)
+			if (def->pad == mux->pads + i) {
+				list_del(&def->node);
+
+				/* Disable pad wakeup */
+				val = omap_mux_read(def->pad->partition,
+					def->pad->mux->reg_offset);
+				val &= ~OMAP_WAKEUP_EN;
+				omap_mux_write(def->pad->partition, val,
+					def->pad->mux->reg_offset);
+				kfree(def);
+			}
+}
+
+/*
  * Prepare the array of PRCM events corresponding to the current SoC,
  * and set-up the chained interrupt handler mechanism.
  */
diff --git a/arch/arm/plat-omap/include/plat/prcm.h b/arch/arm/plat-omap/include/plat/prcm.h
index 205b9b1..7987819 100644
--- a/arch/arm/plat-omap/include/plat/prcm.h
+++ b/arch/arm/plat-omap/include/plat/prcm.h
@@ -66,10 +66,15 @@  struct omap_prcm_irq_setup {
 	int irq;
 };
 
+struct omap_hwmod_mux_info;
+
 int omap_prcm_event_to_irq(const char *name);
 int omap_prcm_irq_init(void);
 void omap_prcm_irq_setup(struct omap_prcm_irq_setup *setup);
 void omap_prcm_irq_cleanup(void);
+int omap_prcm_register_pad_irqs(struct omap_hwmod_mux_info *mux,
+				unsigned int irq);
+void omap_prcm_unregister_pad_irqs(struct omap_hwmod_mux_info *mux);
 u32 omap_prcm_get_reset_sources(void);
 int omap2_cm_wait_idlest(void __iomem *reg, u32 mask, u8 idlest,
 			 const char *name);