Message ID | 1309338303-2086-3-git-send-email-t-kristo@ti.com (mailing list archive) |
---|---|
State | Changes Requested |
Delegated to: | Kevin Hilman |
Headers | show |
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
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 --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);
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(-)