* [PATCH v2] gpio/omap: implement irq_enable/disable using mask/unmask. @ 2013-04-12 9:13 Andreas Fenkart 2013-04-12 9:13 ` [PATCH] " Andreas Fenkart 0 siblings, 1 reply; 18+ messages in thread From: Andreas Fenkart @ 2013-04-12 9:13 UTC (permalink / raw) To: santosh.shilimkar Cc: khilman, grant.likely, linus.walleij, linux-omap, daniel, jon-hunter, Andreas Fenkart This is a resend. The single change is the added changelog https://patchwork.kernel.org/patch/1886421/ Andreas Fenkart (1): gpio/omap: implement irq_enable/disable using mask/unmask. drivers/gpio/gpio-omap.c | 2 ++ 1 file changed, 2 insertions(+) -- 1.7.10.4 ^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH] gpio/omap: implement irq_enable/disable using mask/unmask. 2013-04-12 9:13 [PATCH v2] gpio/omap: implement irq_enable/disable using mask/unmask Andreas Fenkart @ 2013-04-12 9:13 ` Andreas Fenkart 2013-04-12 10:19 ` Santosh Shilimkar 0 siblings, 1 reply; 18+ messages in thread From: Andreas Fenkart @ 2013-04-12 9:13 UTC (permalink / raw) To: santosh.shilimkar Cc: khilman, grant.likely, linus.walleij, linux-omap, daniel, jon-hunter, Andreas Fenkart In PM suspend, some omaps can't detect sdio irqs via the sdio interface. The way to implement this, is to declare the corresponding pin as part of the sdio interface and as a gpio input via pinctrl-single states. The MMC driver request states "default" "active" and "idle" during the probe, then toggles between active and idle during the runtime. This requires low overhead functions for enable/disable of gpio irqs. For level triggered interrupt there is no difference between masking and disabling an interrupt. For edge interrupt interrupts there is. When masked, interrupts should still be latched to the interrupt status register so when unmasked later there is an interrupt straight away. However, if the interrupt is disabled then gpio events occurring will not be latched/stored. Hence proposed patch is incomplete for edge type interrupts. Signed-off-by: Andreas Fenkart <andreas.fenkart@streamunlimited.com> --- drivers/gpio/gpio-omap.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 159f5c5..69ef2d8 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -815,6 +815,8 @@ static struct irq_chip gpio_irq_chip = { .irq_unmask = gpio_unmask_irq, .irq_set_type = gpio_irq_type, .irq_set_wake = gpio_wake_enable, + .irq_disable = gpio_mask_irq, /* FIXME for edge type IRQ */ + .irq_enable = gpio_unmask_irq, }; /*---------------------------------------------------------------------*/ -- 1.7.10.4 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH] gpio/omap: implement irq_enable/disable using mask/unmask. 2013-04-12 9:13 ` [PATCH] " Andreas Fenkart @ 2013-04-12 10:19 ` Santosh Shilimkar 2013-04-12 11:07 ` Felipe Balbi 2013-04-19 19:20 ` [PATCH v2] gpio/omap: implement irq mask/disable with proper semantic Andreas Fenkart 0 siblings, 2 replies; 18+ messages in thread From: Santosh Shilimkar @ 2013-04-12 10:19 UTC (permalink / raw) To: Andreas Fenkart, jon-hunter Cc: khilman, grant.likely, linus.walleij, linux-omap, daniel On Friday 12 April 2013 02:43 PM, Andreas Fenkart wrote: > In PM suspend, some omaps can't detect sdio irqs via the sdio interface. > The way to implement this, is to declare the corresponding pin as part > of the sdio interface and as a gpio input via pinctrl-single states. > The MMC driver request states "default" "active" and "idle" during the > probe, then toggles between active and idle during the runtime. This > requires low overhead functions for enable/disable of gpio irqs. > > For level triggered interrupt there is no difference between masking > and disabling an interrupt. For edge interrupt interrupts there is. > When masked, interrupts should still be latched to the interrupt status > register so when unmasked later there is an interrupt straight away. > However, if the interrupt is disabled then gpio events occurring will not > be latched/stored. Hence proposed patch is incomplete for edge type > interrupts. > > Signed-off-by: Andreas Fenkart <andreas.fenkart@streamunlimited.com> > --- Patch is incomplete and still confusing ;-) if some one reads the patch without the thread. I think you have already ask the question/ suggestion in past but its better to split masking/disabling functions and make them behave properly. Mapping enable/disable to mask/unmask to get around the issue seems more of a hack. Also I think, we can address the edge type IRQ issue along with this patch to be complete. Before you go ahead with the update, I would like to hear Jon's opinion on the edge IRQ related fixing. > drivers/gpio/gpio-omap.c | 2 ++ > 1 file changed, 2 insertions(+) > > diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c > index 159f5c5..69ef2d8 100644 > --- a/drivers/gpio/gpio-omap.c > +++ b/drivers/gpio/gpio-omap.c > @@ -815,6 +815,8 @@ static struct irq_chip gpio_irq_chip = { > .irq_unmask = gpio_unmask_irq, > .irq_set_type = gpio_irq_type, > .irq_set_wake = gpio_wake_enable, > + .irq_disable = gpio_mask_irq, /* FIXME for edge type IRQ */ > + .irq_enable = gpio_unmask_irq, > }; > > /*---------------------------------------------------------------------*/ > Sorry to make you wait for the proposal discussion. Regards, Santosh ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH] gpio/omap: implement irq_enable/disable using mask/unmask. 2013-04-12 10:19 ` Santosh Shilimkar @ 2013-04-12 11:07 ` Felipe Balbi 2013-04-19 19:25 ` Andreas Fenkart 2013-04-19 19:20 ` [PATCH v2] gpio/omap: implement irq mask/disable with proper semantic Andreas Fenkart 1 sibling, 1 reply; 18+ messages in thread From: Felipe Balbi @ 2013-04-12 11:07 UTC (permalink / raw) To: Santosh Shilimkar Cc: Andreas Fenkart, jon-hunter, khilman, grant.likely, linus.walleij, linux-omap, daniel [-- Attachment #1: Type: text/plain, Size: 2475 bytes --] Hi, On Fri, Apr 12, 2013 at 03:49:52PM +0530, Santosh Shilimkar wrote: > On Friday 12 April 2013 02:43 PM, Andreas Fenkart wrote: > > In PM suspend, some omaps can't detect sdio irqs via the sdio interface. > > The way to implement this, is to declare the corresponding pin as part > > of the sdio interface and as a gpio input via pinctrl-single states. > > The MMC driver request states "default" "active" and "idle" during the > > probe, then toggles between active and idle during the runtime. This > > requires low overhead functions for enable/disable of gpio irqs. > > > > For level triggered interrupt there is no difference between masking > > and disabling an interrupt. For edge interrupt interrupts there is. > > When masked, interrupts should still be latched to the interrupt status > > register so when unmasked later there is an interrupt straight away. > > However, if the interrupt is disabled then gpio events occurring will not > > be latched/stored. Hence proposed patch is incomplete for edge type > > interrupts. > > > > Signed-off-by: Andreas Fenkart <andreas.fenkart@streamunlimited.com> > > --- > Patch is incomplete and still confusing ;-) if some one reads the > patch without the thread. I think you have already ask the question/ > suggestion in past but its better to split masking/disabling functions > and make them behave properly. Mapping enable/disable to mask/unmask > to get around the issue seems more of a hack. right, specially since IRQ susystem will already do that for irq_enable(): kernel/irq/chip.c::irq_enable() 192 void irq_enable(struct irq_desc *desc) 193 { 194 irq_state_clr_disabled(desc); 195 if (desc->irq_data.chip->irq_enable) 196 desc->irq_data.chip->irq_enable(&desc->irq_data); 197 else 198 desc->irq_data.chip->irq_unmask(&desc->irq_data); 199 irq_state_clr_masked(desc); 200 } In fact this patch shouldn't be necessary if only IRQ subsystem would do the same for irq_disable() (though it doesn't and I haven't fully read the code you to understand why, however there's definitely a reason): 202 void irq_disable(struct irq_desc *desc) 203 { 204 irq_state_set_disabled(desc); 205 if (desc->irq_data.chip->irq_disable) { 206 desc->irq_data.chip->irq_disable(&desc->irq_data); 207 irq_state_set_masked(desc); 208 } 209 } -- balbi [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 836 bytes --] ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH] gpio/omap: implement irq_enable/disable using mask/unmask. 2013-04-12 11:07 ` Felipe Balbi @ 2013-04-19 19:25 ` Andreas Fenkart 0 siblings, 0 replies; 18+ messages in thread From: Andreas Fenkart @ 2013-04-19 19:25 UTC (permalink / raw) To: Felipe Balbi Cc: Santosh Shilimkar, Andreas Fenkart, jon-hunter, khilman, grant.likely, linus.walleij, linux-omap, daniel Hi Felipe, On Fri, Apr 12, 2013 at 02:07:01PM +0300, Felipe Balbi wrote: [snip] > > > Signed-off-by: Andreas Fenkart <andreas.fenkart@streamunlimited.com> > > > --- > > Patch is incomplete and still confusing ;-) if some one reads the > > patch without the thread. I think you have already ask the question/ > > suggestion in past but its better to split masking/disabling functions > > and make them behave properly. Mapping enable/disable to mask/unmask > > to get around the issue seems more of a hack. > > right, specially since IRQ susystem will already do that for > irq_enable(): > > kernel/irq/chip.c::irq_enable() > > 192 void irq_enable(struct irq_desc *desc) > 193 { > 194 irq_state_clr_disabled(desc); > 195 if (desc->irq_data.chip->irq_enable) > 196 desc->irq_data.chip->irq_enable(&desc->irq_data); > 197 else > 198 desc->irq_data.chip->irq_unmask(&desc->irq_data); > 199 irq_state_clr_masked(desc); > 200 } > > In fact this patch shouldn't be necessary if only IRQ subsystem would do > the same for irq_disable() (though it doesn't and I haven't fully read > the code you to understand why, however there's definitely a reason): > > 202 void irq_disable(struct irq_desc *desc) > 203 { > 204 irq_state_set_disabled(desc); > 205 if (desc->irq_data.chip->irq_disable) { > 206 desc->irq_data.chip->irq_disable(&desc->irq_data); > 207 irq_state_set_masked(desc); > 208 } > 209 } I started some other thread over here: [PATCH] genirq: use irq_mask as fallback for irq_disable. https://lkml.org/lkml/2013/4/19/229 /Andi ^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH v2] gpio/omap: implement irq mask/disable with proper semantic. 2013-04-12 10:19 ` Santosh Shilimkar 2013-04-12 11:07 ` Felipe Balbi @ 2013-04-19 19:20 ` Andreas Fenkart 2013-04-20 12:35 ` Santosh Shilimkar 2013-04-26 7:56 ` [PATCH v2] " Linus Walleij 1 sibling, 2 replies; 18+ messages in thread From: Andreas Fenkart @ 2013-04-19 19:20 UTC (permalink / raw) To: santosh.shilimkar Cc: khilman, grant.likely, linus.walleij, balbi, linux-omap, daniel, jon-hunter, Andreas Fenkart When a gpio interrupt is masked, the gpio event will still be latched in the interrupt status register so when you unmask it later you may get an interrupt straight away. However, if the interrupt is disabled then gpio events occurring will not be latched/stored. Signed-off-by: Andreas Fenkart <andreas.fenkart@streamunlimited.com> --- drivers/gpio/gpio-omap.c | 45 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 9 deletions(-) diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 159f5c5..9ab7ba5 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -780,7 +780,7 @@ static void gpio_mask_irq(struct irq_data *d) spin_lock_irqsave(&bank->lock, flags); _set_gpio_irqenable(bank, gpio, 0); - _set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), IRQ_TYPE_NONE); + /* latching new IRQ, but don't signal */ spin_unlock_irqrestore(&bank->lock, flags); } @@ -789,24 +789,48 @@ static void gpio_unmask_irq(struct irq_data *d) struct gpio_bank *bank = irq_data_get_irq_chip_data(d); unsigned int gpio = irq_to_gpio(bank, d->irq); unsigned int irq_mask = GPIO_BIT(bank, gpio); - u32 trigger = irqd_get_trigger_type(d); unsigned long flags; spin_lock_irqsave(&bank->lock, flags); - if (trigger) - _set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), trigger); - /* For level-triggered GPIOs, the clearing must be done after - * the HW source is cleared, thus after the handler has run */ - if (bank->level_mask & irq_mask) { - _set_gpio_irqenable(bank, gpio, 0); + /* For level-triggered GPIOs, clear the IRQ. If the HW + * still needs service, IRQ will be latched again */ + if (bank->level_mask & irq_mask) _clear_gpio_irqstatus(bank, gpio); - } _set_gpio_irqenable(bank, gpio, 1); spin_unlock_irqrestore(&bank->lock, flags); } +static void gpio_disable_irq(struct irq_data *d) +{ + struct gpio_bank *bank = irq_data_get_irq_chip_data(d); + unsigned int gpio = irq_to_gpio(bank, d->irq); + unsigned long flags; + + spin_lock_irqsave(&bank->lock, flags); + /* stop latching new IRQ */ + _set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), IRQ_TYPE_NONE); + _set_gpio_irqenable(bank, gpio, 0); + spin_unlock_irqrestore(&bank->lock, flags); +} + +static void gpio_enable_irq(struct irq_data *d) +{ + struct gpio_bank *bank = irq_data_get_irq_chip_data(d); + unsigned int gpio = irq_to_gpio(bank, d->irq); + unsigned int irq_mask = GPIO_BIT(bank, gpio); + u32 trigger = irqd_get_trigger_type(d); + unsigned long flags; + + spin_lock_irqsave(&bank->lock, flags); + if (trigger) + _set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), trigger); + _clear_gpio_irqstatus(bank, gpio); + _set_gpio_irqenable(bank, gpio, 1); + spin_unlock_irqrestore(&bank->lock, flags); +} + static struct irq_chip gpio_irq_chip = { .name = "GPIO", .irq_shutdown = gpio_irq_shutdown, @@ -815,6 +839,9 @@ static struct irq_chip gpio_irq_chip = { .irq_unmask = gpio_unmask_irq, .irq_set_type = gpio_irq_type, .irq_set_wake = gpio_wake_enable, + .irq_disable = gpio_disable_irq, + .irq_enable = gpio_enable_irq, + }; /*---------------------------------------------------------------------*/ -- 1.7.10.4 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH v2] gpio/omap: implement irq mask/disable with proper semantic. 2013-04-19 19:20 ` [PATCH v2] gpio/omap: implement irq mask/disable with proper semantic Andreas Fenkart @ 2013-04-20 12:35 ` Santosh Shilimkar 2013-04-22 8:54 ` [PATCH v3] gpio/omap: implement irq mask/disable with proper Andreas Fenkart 2013-04-26 7:56 ` [PATCH v2] " Linus Walleij 1 sibling, 1 reply; 18+ messages in thread From: Santosh Shilimkar @ 2013-04-20 12:35 UTC (permalink / raw) To: Andreas Fenkart Cc: khilman, grant.likely, linus.walleij, balbi, linux-omap, daniel, jon-hunter On Saturday 20 April 2013 12:50 AM, Andreas Fenkart wrote: > When a gpio interrupt is masked, the gpio event will still be latched in > the interrupt status register so when you unmask it later you may get an > interrupt straight away. However, if the interrupt is disabled then gpio > events occurring will not be latched/stored. > > Signed-off-by: Andreas Fenkart <andreas.fenkart@streamunlimited.com> > --- > drivers/gpio/gpio-omap.c | 45 ++++++++++++++++++++++++++++++++++++--------- > 1 file changed, 36 insertions(+), 9 deletions(-) > > diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c > index 159f5c5..9ab7ba5 100644 > --- a/drivers/gpio/gpio-omap.c > +++ b/drivers/gpio/gpio-omap.c > @@ -780,7 +780,7 @@ static void gpio_mask_irq(struct irq_data *d) > > spin_lock_irqsave(&bank->lock, flags); > _set_gpio_irqenable(bank, gpio, 0); > - _set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), IRQ_TYPE_NONE); > + /* latching new IRQ, but don't signal */ You can add the comment in begining of the function. Comment just before spin_lock release will be confusing. > spin_unlock_irqrestore(&bank->lock, flags); > } > > @@ -789,24 +789,48 @@ static void gpio_unmask_irq(struct irq_data *d) > struct gpio_bank *bank = irq_data_get_irq_chip_data(d); > unsigned int gpio = irq_to_gpio(bank, d->irq); > unsigned int irq_mask = GPIO_BIT(bank, gpio); > - u32 trigger = irqd_get_trigger_type(d); > unsigned long flags; > > spin_lock_irqsave(&bank->lock, flags); > - if (trigger) > - _set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), trigger); > > - /* For level-triggered GPIOs, the clearing must be done after > - * the HW source is cleared, thus after the handler has run */ > - if (bank->level_mask & irq_mask) { > - _set_gpio_irqenable(bank, gpio, 0); > + /* For level-triggered GPIOs, clear the IRQ. If the HW > + * still needs service, IRQ will be latched again */ While at this, please fix the comment style /* * */ > + if (bank->level_mask & irq_mask) > _clear_gpio_irqstatus(bank, gpio); > - } > > _set_gpio_irqenable(bank, gpio, 1); > spin_unlock_irqrestore(&bank->lock, flags); > } > > +static void gpio_disable_irq(struct irq_data *d) > +{ > + struct gpio_bank *bank = irq_data_get_irq_chip_data(d); > + unsigned int gpio = irq_to_gpio(bank, d->irq); > + unsigned long flags; > + > + spin_lock_irqsave(&bank->lock, flags); > + /* stop latching new IRQ */ Best thing is you add kernel doc for all these function and describe them clearly. mask/unmask, disable/enable > + _set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), IRQ_TYPE_NONE); > + _set_gpio_irqenable(bank, gpio, 0); > + spin_unlock_irqrestore(&bank->lock, flags); > +} > + > +static void gpio_enable_irq(struct irq_data *d) > +{ > + struct gpio_bank *bank = irq_data_get_irq_chip_data(d); > + unsigned int gpio = irq_to_gpio(bank, d->irq); > + unsigned int irq_mask = GPIO_BIT(bank, gpio); > + u32 trigger = irqd_get_trigger_type(d); > + unsigned long flags; > + > + spin_lock_irqsave(&bank->lock, flags); > + if (trigger) > + _set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), trigger); > + _clear_gpio_irqstatus(bank, gpio); > + _set_gpio_irqenable(bank, gpio, 1); > + spin_unlock_irqrestore(&bank->lock, flags); > +} > + > static struct irq_chip gpio_irq_chip = { > .name = "GPIO", > .irq_shutdown = gpio_irq_shutdown, > @@ -815,6 +839,9 @@ static struct irq_chip gpio_irq_chip = { > .irq_unmask = gpio_unmask_irq, > .irq_set_type = gpio_irq_type, > .irq_set_wake = gpio_wake_enable, > + .irq_disable = gpio_disable_irq, > + .irq_enable = gpio_enable_irq, > + Drop above extra line. > }; > > /*---------------------------------------------------------------------*/ > ^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH v3] gpio/omap: implement irq mask/disable with proper 2013-04-20 12:35 ` Santosh Shilimkar @ 2013-04-22 8:54 ` Andreas Fenkart 2013-04-22 8:54 ` [PATCH v3] gpio/omap: implement irq mask/disable with proper semantic Andreas Fenkart 0 siblings, 1 reply; 18+ messages in thread From: Andreas Fenkart @ 2013-04-22 8:54 UTC (permalink / raw) To: santosh.shilimkar Cc: khilman, grant.likely, linus.walleij, balbi, linux-omap, daniel, jon-hunter, Andreas Fenkart Added kernel doc for mask/unmask, disable/enable functions. Andreas Fenkart (1): gpio/omap: implement irq mask/disable with proper semantic. drivers/gpio/gpio-omap.c | 69 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 60 insertions(+), 9 deletions(-) -- 1.7.10.4 ^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH v3] gpio/omap: implement irq mask/disable with proper semantic. 2013-04-22 8:54 ` [PATCH v3] gpio/omap: implement irq mask/disable with proper Andreas Fenkart @ 2013-04-22 8:54 ` Andreas Fenkart 2013-04-23 23:38 ` Kevin Hilman ` (3 more replies) 0 siblings, 4 replies; 18+ messages in thread From: Andreas Fenkart @ 2013-04-22 8:54 UTC (permalink / raw) To: santosh.shilimkar Cc: khilman, grant.likely, linus.walleij, balbi, linux-omap, daniel, jon-hunter, Andreas Fenkart When a gpio interrupt is masked, the gpio event will still be latched in the interrupt status register so when you unmask it later you may get an interrupt straight away. However, if the interrupt is disabled then gpio events occurring will not be latched/stored. Signed-off-by: Andreas Fenkart <andreas.fenkart@streamunlimited.com> --- drivers/gpio/gpio-omap.c | 69 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 60 insertions(+), 9 deletions(-) diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 159f5c5..0b66c45 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -772,6 +772,12 @@ static void gpio_ack_irq(struct irq_data *d) _clear_gpio_irqstatus(bank, gpio); } +/** + * gpio_mask_irq - mask IRQ signalling + * @d : the gpio data we're acting upon + * + * Only signalling disabled. New IRQ still latched to IRQ status register. + */ static void gpio_mask_irq(struct irq_data *d) { struct gpio_bank *bank = irq_data_get_irq_chip_data(d); @@ -780,33 +786,76 @@ static void gpio_mask_irq(struct irq_data *d) spin_lock_irqsave(&bank->lock, flags); _set_gpio_irqenable(bank, gpio, 0); - _set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), IRQ_TYPE_NONE); spin_unlock_irqrestore(&bank->lock, flags); } +/** + * gpio_unmask_irq - unmask IRQ signalling + * @d : the gpio data we're acting upon + * + * If an IRQ occured while IRQ was masked, you will get an IRQ straight away. + */ static void gpio_unmask_irq(struct irq_data *d) { struct gpio_bank *bank = irq_data_get_irq_chip_data(d); unsigned int gpio = irq_to_gpio(bank, d->irq); unsigned int irq_mask = GPIO_BIT(bank, gpio); - u32 trigger = irqd_get_trigger_type(d); unsigned long flags; spin_lock_irqsave(&bank->lock, flags); - if (trigger) - _set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), trigger); - /* For level-triggered GPIOs, the clearing must be done after - * the HW source is cleared, thus after the handler has run */ - if (bank->level_mask & irq_mask) { - _set_gpio_irqenable(bank, gpio, 0); + /* + * For level-triggered GPIOs, clear the IRQ. If the HW + * still needs service, IRQ will be latched again + */ + if (bank->level_mask & irq_mask) _clear_gpio_irqstatus(bank, gpio); - } _set_gpio_irqenable(bank, gpio, 1); spin_unlock_irqrestore(&bank->lock, flags); } +/** + * gpio_disable_irq - disable the interrupt + * @d : the gpio data we're acting upon + * + * While disabled all IRQ events are ignored. No latching to IRQ status + * register. + */ +static void gpio_disable_irq(struct irq_data *d) +{ + struct gpio_bank *bank = irq_data_get_irq_chip_data(d); + unsigned int gpio = irq_to_gpio(bank, d->irq); + unsigned long flags; + + spin_lock_irqsave(&bank->lock, flags); + _set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), IRQ_TYPE_NONE); + _set_gpio_irqenable(bank, gpio, 0); + spin_unlock_irqrestore(&bank->lock, flags); +} + +/** + * gpio_enable_irq - enable the interrupt + * @d : the gpio data we're acting upon + * + * Enables latching and signalling IRQ. + */ +static void gpio_enable_irq(struct irq_data *d) +{ + struct gpio_bank *bank = irq_data_get_irq_chip_data(d); + unsigned int gpio = irq_to_gpio(bank, d->irq); + unsigned int irq_mask = GPIO_BIT(bank, gpio); + u32 trigger = irqd_get_trigger_type(d); + unsigned long flags; + + spin_lock_irqsave(&bank->lock, flags); + if (trigger) + _set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), trigger); + _clear_gpio_irqstatus(bank, gpio); + _set_gpio_irqenable(bank, gpio, 1); + spin_unlock_irqrestore(&bank->lock, flags); +} + static struct irq_chip gpio_irq_chip = { .name = "GPIO", .irq_shutdown = gpio_irq_shutdown, @@ -815,6 +864,8 @@ static struct irq_chip gpio_irq_chip = { .irq_unmask = gpio_unmask_irq, .irq_set_type = gpio_irq_type, .irq_set_wake = gpio_wake_enable, + .irq_disable = gpio_disable_irq, + .irq_enable = gpio_enable_irq, }; /*---------------------------------------------------------------------*/ -- 1.7.10.4 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH v3] gpio/omap: implement irq mask/disable with proper semantic. 2013-04-22 8:54 ` [PATCH v3] gpio/omap: implement irq mask/disable with proper semantic Andreas Fenkart @ 2013-04-23 23:38 ` Kevin Hilman 2013-04-25 19:30 ` Jon Hunter ` (2 subsequent siblings) 3 siblings, 0 replies; 18+ messages in thread From: Kevin Hilman @ 2013-04-23 23:38 UTC (permalink / raw) To: Andreas Fenkart Cc: santosh.shilimkar, grant.likely, linus.walleij, balbi, linux-omap, daniel, jon-hunter Andreas Fenkart <andreas.fenkart@streamunlimited.com> writes: > When a gpio interrupt is masked, the gpio event will still be latched in > the interrupt status register so when you unmask it later you may get an > interrupt straight away. However, if the interrupt is disabled then gpio > events occurring will not be latched/stored. > > Signed-off-by: Andreas Fenkart <andreas.fenkart@streamunlimited.com> The approach seems OK to me, but the changelog is still missing quite a bit of information. I know it's been hashed over in the various threads, but the changelog needs all that discussion summarized. The changelog should at least: - describe the problem/bug being fixed - describe the fix - answer "why" the approach was taken (not how.) This part is very important to reviewers and maintainers. - how it was tested, and on what platforms In addition, I'd like to see a description of how (or whether) this affects the genirq lazy disable functionality, and how it was tested. Kevin ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v3] gpio/omap: implement irq mask/disable with proper semantic. 2013-04-22 8:54 ` [PATCH v3] gpio/omap: implement irq mask/disable with proper semantic Andreas Fenkart 2013-04-23 23:38 ` Kevin Hilman @ 2013-04-25 19:30 ` Jon Hunter 2013-04-25 19:40 ` Jon Hunter 2013-04-26 15:46 ` Jon Hunter 3 siblings, 0 replies; 18+ messages in thread From: Jon Hunter @ 2013-04-25 19:30 UTC (permalink / raw) To: Andreas Fenkart Cc: santosh.shilimkar, khilman, grant.likely, linus.walleij, balbi, linux-omap, daniel On 04/22/2013 03:54 AM, Andreas Fenkart wrote: > When a gpio interrupt is masked, the gpio event will still be latched in > the interrupt status register so when you unmask it later you may get an > interrupt straight away. However, if the interrupt is disabled then gpio > events occurring will not be latched/stored. > > Signed-off-by: Andreas Fenkart <andreas.fenkart@streamunlimited.com> > --- > drivers/gpio/gpio-omap.c | 69 ++++++++++++++++++++++++++++++++++++++++------ > 1 file changed, 60 insertions(+), 9 deletions(-) > > diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c > index 159f5c5..0b66c45 100644 > --- a/drivers/gpio/gpio-omap.c > +++ b/drivers/gpio/gpio-omap.c > @@ -772,6 +772,12 @@ static void gpio_ack_irq(struct irq_data *d) > _clear_gpio_irqstatus(bank, gpio); > } > > +/** > + * gpio_mask_irq - mask IRQ signalling > + * @d : the gpio data we're acting upon > + * > + * Only signalling disabled. New IRQ still latched to IRQ status register. > + */ > static void gpio_mask_irq(struct irq_data *d) > { > struct gpio_bank *bank = irq_data_get_irq_chip_data(d); > @@ -780,33 +786,76 @@ static void gpio_mask_irq(struct irq_data *d) > > spin_lock_irqsave(&bank->lock, flags); > _set_gpio_irqenable(bank, gpio, 0); > - _set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), IRQ_TYPE_NONE); My only concern here is that _set_gpio_triggering() is also handling the wake-up enable register. So by clearing the triggering here it was also clearing the wake-up enable. Ideally, I would think that when masking the interrupt we would also want to disable the wake-up generation too (if enabled). I think it would only be a problem if someone called gpio_enable_irq() and the gpio_mask_irq(). Ideally the wake-up enable stuff should be removed from the triggering function. May be we could add explicit calls to _set_gpio_wakeup(). > spin_unlock_irqrestore(&bank->lock, flags); > } > > +/** > + * gpio_unmask_irq - unmask IRQ signalling > + * @d : the gpio data we're acting upon > + * > + * If an IRQ occured while IRQ was masked, you will get an IRQ straight away. > + */ > static void gpio_unmask_irq(struct irq_data *d) > { > struct gpio_bank *bank = irq_data_get_irq_chip_data(d); > unsigned int gpio = irq_to_gpio(bank, d->irq); > unsigned int irq_mask = GPIO_BIT(bank, gpio); > - u32 trigger = irqd_get_trigger_type(d); > unsigned long flags; > > spin_lock_irqsave(&bank->lock, flags); > - if (trigger) > - _set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), trigger); > > - /* For level-triggered GPIOs, the clearing must be done after > - * the HW source is cleared, thus after the handler has run */ > - if (bank->level_mask & irq_mask) { > - _set_gpio_irqenable(bank, gpio, 0); > + /* > + * For level-triggered GPIOs, clear the IRQ. If the HW > + * still needs service, IRQ will be latched again > + */ > + if (bank->level_mask & irq_mask) > _clear_gpio_irqstatus(bank, gpio); > - } > > _set_gpio_irqenable(bank, gpio, 1); > spin_unlock_irqrestore(&bank->lock, flags); > } Similarly here, can we ensure the wake-up enable is set? Cheers Jon ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v3] gpio/omap: implement irq mask/disable with proper semantic. 2013-04-22 8:54 ` [PATCH v3] gpio/omap: implement irq mask/disable with proper semantic Andreas Fenkart 2013-04-23 23:38 ` Kevin Hilman 2013-04-25 19:30 ` Jon Hunter @ 2013-04-25 19:40 ` Jon Hunter 2013-04-26 15:46 ` Jon Hunter 3 siblings, 0 replies; 18+ messages in thread From: Jon Hunter @ 2013-04-25 19:40 UTC (permalink / raw) To: Andreas Fenkart Cc: santosh.shilimkar, khilman, grant.likely, linus.walleij, balbi, linux-omap, daniel On 04/22/2013 03:54 AM, Andreas Fenkart wrote: > When a gpio interrupt is masked, the gpio event will still be latched in > the interrupt status register so when you unmask it later you may get an > interrupt straight away. However, if the interrupt is disabled then gpio > events occurring will not be latched/stored. > > Signed-off-by: Andreas Fenkart <andreas.fenkart@streamunlimited.com> > --- > drivers/gpio/gpio-omap.c | 69 ++++++++++++++++++++++++++++++++++++++++------ > 1 file changed, 60 insertions(+), 9 deletions(-) > > diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c > index 159f5c5..0b66c45 100644 > --- a/drivers/gpio/gpio-omap.c > +++ b/drivers/gpio/gpio-omap.c > @@ -772,6 +772,12 @@ static void gpio_ack_irq(struct irq_data *d) > _clear_gpio_irqstatus(bank, gpio); > } > > +/** > + * gpio_mask_irq - mask IRQ signalling > + * @d : the gpio data we're acting upon > + * > + * Only signalling disabled. New IRQ still latched to IRQ status register. > + */ > static void gpio_mask_irq(struct irq_data *d) > { > struct gpio_bank *bank = irq_data_get_irq_chip_data(d); > @@ -780,33 +786,76 @@ static void gpio_mask_irq(struct irq_data *d) > > spin_lock_irqsave(&bank->lock, flags); > _set_gpio_irqenable(bank, gpio, 0); > - _set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), IRQ_TYPE_NONE); > spin_unlock_irqrestore(&bank->lock, flags); > } > > +/** > + * gpio_unmask_irq - unmask IRQ signalling > + * @d : the gpio data we're acting upon > + * > + * If an IRQ occured while IRQ was masked, you will get an IRQ straight away. > + */ > static void gpio_unmask_irq(struct irq_data *d) > { > struct gpio_bank *bank = irq_data_get_irq_chip_data(d); > unsigned int gpio = irq_to_gpio(bank, d->irq); > unsigned int irq_mask = GPIO_BIT(bank, gpio); > - u32 trigger = irqd_get_trigger_type(d); > unsigned long flags; > > spin_lock_irqsave(&bank->lock, flags); > - if (trigger) > - _set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), trigger); > > - /* For level-triggered GPIOs, the clearing must be done after > - * the HW source is cleared, thus after the handler has run */ > - if (bank->level_mask & irq_mask) { > - _set_gpio_irqenable(bank, gpio, 0); > + /* > + * For level-triggered GPIOs, clear the IRQ. If the HW > + * still needs service, IRQ will be latched again > + */ > + if (bank->level_mask & irq_mask) > _clear_gpio_irqstatus(bank, gpio); > - } > > _set_gpio_irqenable(bank, gpio, 1); > spin_unlock_irqrestore(&bank->lock, flags); > } > > +/** > + * gpio_disable_irq - disable the interrupt > + * @d : the gpio data we're acting upon > + * > + * While disabled all IRQ events are ignored. No latching to IRQ status > + * register. > + */ > +static void gpio_disable_irq(struct irq_data *d) > +{ > + struct gpio_bank *bank = irq_data_get_irq_chip_data(d); > + unsigned int gpio = irq_to_gpio(bank, d->irq); > + unsigned long flags; > + > + spin_lock_irqsave(&bank->lock, flags); > + _set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), IRQ_TYPE_NONE); > + _set_gpio_irqenable(bank, gpio, 0); > + spin_unlock_irqrestore(&bank->lock, flags); > +} > + > +/** > + * gpio_enable_irq - enable the interrupt > + * @d : the gpio data we're acting upon > + * > + * Enables latching and signalling IRQ. > + */ > +static void gpio_enable_irq(struct irq_data *d) > +{ > + struct gpio_bank *bank = irq_data_get_irq_chip_data(d); > + unsigned int gpio = irq_to_gpio(bank, d->irq); > + unsigned int irq_mask = GPIO_BIT(bank, gpio); > + u32 trigger = irqd_get_trigger_type(d); > + unsigned long flags; > + > + spin_lock_irqsave(&bank->lock, flags); > + if (trigger) > + _set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), trigger); > + _clear_gpio_irqstatus(bank, gpio); > + _set_gpio_irqenable(bank, gpio, 1); > + spin_unlock_irqrestore(&bank->lock, flags); > +} This generates the following warning ... drivers/gpio/gpio-omap.c: In function 'gpio_enable_irq': drivers/gpio/gpio-omap.c:852:15: warning: unused variable 'irq_mask' [-Wunused-variable] So you can get rid of irq_mask in the above function. Jon ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v3] gpio/omap: implement irq mask/disable with proper semantic. 2013-04-22 8:54 ` [PATCH v3] gpio/omap: implement irq mask/disable with proper semantic Andreas Fenkart ` (2 preceding siblings ...) 2013-04-25 19:40 ` Jon Hunter @ 2013-04-26 15:46 ` Jon Hunter 3 siblings, 0 replies; 18+ messages in thread From: Jon Hunter @ 2013-04-26 15:46 UTC (permalink / raw) To: Andreas Fenkart Cc: santosh.shilimkar, khilman, grant.likely, linus.walleij, balbi, linux-omap, daniel On 04/22/2013 03:54 AM, Andreas Fenkart wrote: > When a gpio interrupt is masked, the gpio event will still be latched in > the interrupt status register so when you unmask it later you may get an > interrupt straight away. However, if the interrupt is disabled then gpio > events occurring will not be latched/stored. > > Signed-off-by: Andreas Fenkart <andreas.fenkart@streamunlimited.com> > --- > drivers/gpio/gpio-omap.c | 69 ++++++++++++++++++++++++++++++++++++++++------ > 1 file changed, 60 insertions(+), 9 deletions(-) > > diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c > index 159f5c5..0b66c45 100644 > --- a/drivers/gpio/gpio-omap.c > +++ b/drivers/gpio/gpio-omap.c > @@ -772,6 +772,12 @@ static void gpio_ack_irq(struct irq_data *d) > _clear_gpio_irqstatus(bank, gpio); > } > > +/** > + * gpio_mask_irq - mask IRQ signalling > + * @d : the gpio data we're acting upon > + * > + * Only signalling disabled. New IRQ still latched to IRQ status register. > + */ > static void gpio_mask_irq(struct irq_data *d) > { > struct gpio_bank *bank = irq_data_get_irq_chip_data(d); > @@ -780,33 +786,76 @@ static void gpio_mask_irq(struct irq_data *d) > > spin_lock_irqsave(&bank->lock, flags); > _set_gpio_irqenable(bank, gpio, 0); > - _set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), IRQ_TYPE_NONE); > spin_unlock_irqrestore(&bank->lock, flags); > } > > +/** > + * gpio_unmask_irq - unmask IRQ signalling > + * @d : the gpio data we're acting upon > + * > + * If an IRQ occured while IRQ was masked, you will get an IRQ straight away. > + */ > static void gpio_unmask_irq(struct irq_data *d) > { > struct gpio_bank *bank = irq_data_get_irq_chip_data(d); > unsigned int gpio = irq_to_gpio(bank, d->irq); > unsigned int irq_mask = GPIO_BIT(bank, gpio); > - u32 trigger = irqd_get_trigger_type(d); > unsigned long flags; > > spin_lock_irqsave(&bank->lock, flags); > - if (trigger) > - _set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), trigger); > > - /* For level-triggered GPIOs, the clearing must be done after > - * the HW source is cleared, thus after the handler has run */ > - if (bank->level_mask & irq_mask) { > - _set_gpio_irqenable(bank, gpio, 0); > + /* > + * For level-triggered GPIOs, clear the IRQ. If the HW > + * still needs service, IRQ will be latched again > + */ > + if (bank->level_mask & irq_mask) > _clear_gpio_irqstatus(bank, gpio); > - } > > _set_gpio_irqenable(bank, gpio, 1); > spin_unlock_irqrestore(&bank->lock, flags); > } > > +/** > + * gpio_disable_irq - disable the interrupt > + * @d : the gpio data we're acting upon > + * > + * While disabled all IRQ events are ignored. No latching to IRQ status > + * register. > + */ > +static void gpio_disable_irq(struct irq_data *d) > +{ > + struct gpio_bank *bank = irq_data_get_irq_chip_data(d); > + unsigned int gpio = irq_to_gpio(bank, d->irq); > + unsigned long flags; > + > + spin_lock_irqsave(&bank->lock, flags); > + _set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), IRQ_TYPE_NONE); > + _set_gpio_irqenable(bank, gpio, 0); > + spin_unlock_irqrestore(&bank->lock, flags); > +} > + > +/** > + * gpio_enable_irq - enable the interrupt > + * @d : the gpio data we're acting upon > + * > + * Enables latching and signalling IRQ. > + */ > +static void gpio_enable_irq(struct irq_data *d) > +{ > + struct gpio_bank *bank = irq_data_get_irq_chip_data(d); > + unsigned int gpio = irq_to_gpio(bank, d->irq); > + unsigned int irq_mask = GPIO_BIT(bank, gpio); > + u32 trigger = irqd_get_trigger_type(d); > + unsigned long flags; > + > + spin_lock_irqsave(&bank->lock, flags); > + if (trigger) > + _set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), trigger); > + _clear_gpio_irqstatus(bank, gpio); > + _set_gpio_irqenable(bank, gpio, 1); > + spin_unlock_irqrestore(&bank->lock, flags); > +} > + > static struct irq_chip gpio_irq_chip = { > .name = "GPIO", > .irq_shutdown = gpio_irq_shutdown, > @@ -815,6 +864,8 @@ static struct irq_chip gpio_irq_chip = { > .irq_unmask = gpio_unmask_irq, > .irq_set_type = gpio_irq_type, > .irq_set_wake = gpio_wake_enable, > + .irq_disable = gpio_disable_irq, > + .irq_enable = gpio_enable_irq, > }; I tested the above patch on some omap2/3/4 boards and this appears to break ethernet support (which is using a gpio as an interrupt). I am guessing this is related to the wake-up enable, so this needs some more work. Cheers Jon ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v2] gpio/omap: implement irq mask/disable with proper semantic. 2013-04-19 19:20 ` [PATCH v2] gpio/omap: implement irq mask/disable with proper semantic Andreas Fenkart 2013-04-20 12:35 ` Santosh Shilimkar @ 2013-04-26 7:56 ` Linus Walleij 1 sibling, 0 replies; 18+ messages in thread From: Linus Walleij @ 2013-04-26 7:56 UTC (permalink / raw) To: Andreas Fenkart Cc: santosh.shilimkar@ti.com, ext Kevin Hilman, Grant Likely, Felipe Balbi, Linux-OMAP, daniel, Jon Hunter On Fri, Apr 19, 2013 at 9:20 PM, Andreas Fenkart <andreas.fenkart@streamunlimited.com> wrote: > When a gpio interrupt is masked, the gpio event will still be latched in > the interrupt status register so when you unmask it later you may get an > interrupt straight away. However, if the interrupt is disabled then gpio > events occurring will not be latched/stored. > > Signed-off-by: Andreas Fenkart <andreas.fenkart@streamunlimited.com> Have to defer this to the next development cycle as no consensus seem to have been reached with the maintainers of this driver. Keep going. Thanks, Linus Walleij ^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH] gpio/omap: implement irq_enable/disable using mask/unmask. @ 2012-12-17 9:27 Andreas Fenkart 2012-12-20 5:59 ` Santosh Shilimkar 0 siblings, 1 reply; 18+ messages in thread From: Andreas Fenkart @ 2012-12-17 9:27 UTC (permalink / raw) To: santosh.shilimkar, khilman, grant.likely, linus.walleij, linux-omap Cc: Andreas Fenkart Signed-off-by: Andreas Fenkart <andreas.fenkart@streamunlimited.com> --- drivers/gpio/gpio-omap.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index d335af1..c1951ec 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -815,6 +815,8 @@ static struct irq_chip gpio_irq_chip = { .irq_unmask = gpio_unmask_irq, .irq_set_type = gpio_irq_type, .irq_set_wake = gpio_wake_enable, + .irq_disable = gpio_mask_irq, + .irq_enable = gpio_unmask_irq, }; /*---------------------------------------------------------------------*/ -- 1.7.10.4 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH] gpio/omap: implement irq_enable/disable using mask/unmask. 2012-12-17 9:27 [PATCH] gpio/omap: implement irq_enable/disable using mask/unmask Andreas Fenkart @ 2012-12-20 5:59 ` Santosh Shilimkar 2012-12-20 16:16 ` Jon Hunter 0 siblings, 1 reply; 18+ messages in thread From: Santosh Shilimkar @ 2012-12-20 5:59 UTC (permalink / raw) To: Andreas Fenkart; +Cc: Kevin Hilman, grant.likely, linus.walleij, linux-omap On Monday 17 December 2012 02:57 PM, Andreas Fenkart wrote: Please add some changelog here too. > Signed-off-by: Andreas Fenkart <andreas.fenkart@streamunlimited.com> > --- Patch seems straight forward thought will be interesting where you found the need of it. > drivers/gpio/gpio-omap.c | 2 ++ > 1 file changed, 2 insertions(+) > > diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c > index d335af1..c1951ec 100644 > --- a/drivers/gpio/gpio-omap.c > +++ b/drivers/gpio/gpio-omap.c > @@ -815,6 +815,8 @@ static struct irq_chip gpio_irq_chip = { > .irq_unmask = gpio_unmask_irq, > .irq_set_type = gpio_irq_type, > .irq_set_wake = gpio_wake_enable, > + .irq_disable = gpio_mask_irq, > + .irq_enable = gpio_unmask_irq, > }; > > /*---------------------------------------------------------------------*/ > ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH] gpio/omap: implement irq_enable/disable using mask/unmask. 2012-12-20 5:59 ` Santosh Shilimkar @ 2012-12-20 16:16 ` Jon Hunter 2013-03-25 22:24 ` Andreas Fenkart 0 siblings, 1 reply; 18+ messages in thread From: Jon Hunter @ 2012-12-20 16:16 UTC (permalink / raw) To: Santosh Shilimkar Cc: Andreas Fenkart, Kevin Hilman, grant.likely, linus.walleij, linux-omap On 12/19/2012 11:59 PM, Santosh Shilimkar wrote: > On Monday 17 December 2012 02:57 PM, Andreas Fenkart wrote: > > Please add some changelog here too. > >> Signed-off-by: Andreas Fenkart <andreas.fenkart@streamunlimited.com> >> --- > Patch seems straight forward thought will be interesting where you found > the need of it. The only item that I was thinking of if the behaviour of mask/unmask should be different from enable/disable? When a gpio interrupt is masked, the gpio event will still be latched in the interrupt status register so when you unmask it later you may get an interrupt straight away. However, if the interrupt is disabled then gpio events occurring will not be latched/stored. I am also interested in the need for this, and if we should have a true enable/disable here. Cheers Jon > >> drivers/gpio/gpio-omap.c | 2 ++ >> 1 file changed, 2 insertions(+) >> >> diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c >> index d335af1..c1951ec 100644 >> --- a/drivers/gpio/gpio-omap.c >> +++ b/drivers/gpio/gpio-omap.c >> @@ -815,6 +815,8 @@ static struct irq_chip gpio_irq_chip = { >> .irq_unmask = gpio_unmask_irq, >> .irq_set_type = gpio_irq_type, >> .irq_set_wake = gpio_wake_enable, >> + .irq_disable = gpio_mask_irq, >> + .irq_enable = gpio_unmask_irq, >> }; >> >> >> /*---------------------------------------------------------------------*/ >> > > -- > 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 ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH] gpio/omap: implement irq_enable/disable using mask/unmask. 2012-12-20 16:16 ` Jon Hunter @ 2013-03-25 22:24 ` Andreas Fenkart 0 siblings, 0 replies; 18+ messages in thread From: Andreas Fenkart @ 2013-03-25 22:24 UTC (permalink / raw) To: Jon Hunter Cc: Santosh Shilimkar, Andreas Fenkart, Kevin Hilman, grant.likely, linus.walleij, linux-omap, Daniel Mack Hi, On Thu, Dec 20, 2012 at 10:16:56AM -0600, Jon Hunter wrote: > > On 12/19/2012 11:59 PM, Santosh Shilimkar wrote: > > On Monday 17 December 2012 02:57 PM, Andreas Fenkart wrote: > > > > Please add some changelog here too. :: In pm suspend the omap_hsmmc driver can't detect SDIO IRQs. This is worked around by reconfiguring the SDIO IRQ pin (dat1) as a GPIO before entering suspend and back upon resume. This requires low overhead functions for enable/disable of GPIO IRQs. > > > >> Signed-off-by: Andreas Fenkart <andreas.fenkart@streamunlimited.com> > >> --- > > Patch seems straight forward thought will be interesting where you found > > the need of it. > > The only item that I was thinking of if the behaviour of mask/unmask > should be different from enable/disable? > > When a gpio interrupt is masked, the gpio event will still be latched in > the interrupt status register so when you unmask it later you may get an > interrupt straight away. However, if the interrupt is disabled then gpio > events occurring will not be latched/stored. Thanks for clarification. The HW seems to support this, see Fig 25-3 in the manual. https://www.google.com/search?q=spruh73c This problem though, applies only to edge triggered irqs. In the case of level triggered the mask/unmask implementation clears irqs upon resume. This is safe, because if the level still indicates irq, it will be latched again and if not, the HW needs no service. For edge triggered the current implementation of mask/unmask seems to behave more like enable/disable: - irq detection is disabled during the masking period, which is like disable according above description. But leaves a small window for latching another one that is not served immediately, which is more like masking static void gpio_mask_irq(struct irq_data *d) { spin_lock_irqsave(&bank->lock, flags); _set_gpio_irqenable(bank, gpio, 0); <--- new irqs latched here ---> _set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), IRQ_TYPE_NONE); spin_unlock_irqrestore(&bank->lock, flags); } - does not clear latched irqs upon resume. So not all irq raised after unmask are new, on the other hand some irqs that occured during the masking period might be lost. > I am also interested in the need for this, and if we should have a true > enable/disable here. Since SDIO irqs are level triggered, I'm still okay with my patch. For edge triggered though, it probably needs some more thoughts. Suggestions? Should I split masking/disabling functions and make them behave properly according above semantics or are you fine with the interim solution of mapping enable/disable to mask/unmask? rgds, Andi > >> drivers/gpio/gpio-omap.c | 2 ++ > >> 1 file changed, 2 insertions(+) > >> > >> diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c > >> index d335af1..c1951ec 100644 > >> --- a/drivers/gpio/gpio-omap.c > >> +++ b/drivers/gpio/gpio-omap.c > >> @@ -815,6 +815,8 @@ static struct irq_chip gpio_irq_chip = { > >> .irq_unmask = gpio_unmask_irq, > >> .irq_set_type = gpio_irq_type, > >> .irq_set_wake = gpio_wake_enable, > >> + .irq_disable = gpio_mask_irq, > >> + .irq_enable = gpio_unmask_irq, > >> }; > >> ^ permalink raw reply [flat|nested] 18+ messages in thread
end of thread, other threads:[~2013-04-26 15:46 UTC | newest] Thread overview: 18+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2013-04-12 9:13 [PATCH v2] gpio/omap: implement irq_enable/disable using mask/unmask Andreas Fenkart 2013-04-12 9:13 ` [PATCH] " Andreas Fenkart 2013-04-12 10:19 ` Santosh Shilimkar 2013-04-12 11:07 ` Felipe Balbi 2013-04-19 19:25 ` Andreas Fenkart 2013-04-19 19:20 ` [PATCH v2] gpio/omap: implement irq mask/disable with proper semantic Andreas Fenkart 2013-04-20 12:35 ` Santosh Shilimkar 2013-04-22 8:54 ` [PATCH v3] gpio/omap: implement irq mask/disable with proper Andreas Fenkart 2013-04-22 8:54 ` [PATCH v3] gpio/omap: implement irq mask/disable with proper semantic Andreas Fenkart 2013-04-23 23:38 ` Kevin Hilman 2013-04-25 19:30 ` Jon Hunter 2013-04-25 19:40 ` Jon Hunter 2013-04-26 15:46 ` Jon Hunter 2013-04-26 7:56 ` [PATCH v2] " Linus Walleij -- strict thread matches above, loose matches on Subject: below -- 2012-12-17 9:27 [PATCH] gpio/omap: implement irq_enable/disable using mask/unmask Andreas Fenkart 2012-12-20 5:59 ` Santosh Shilimkar 2012-12-20 16:16 ` Jon Hunter 2013-03-25 22:24 ` Andreas Fenkart
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).