Message ID | 20200622214548.265417-1-paul@crapouillou.net |
---|---|
State | Accepted |
Commit | 1c95348ba327fe8621d3680890c2341523d3524a |
Headers | show |
Series | [1/2] pinctrl: ingenic: Enhance support for IRQ_TYPE_EDGE_BOTH | expand |
On Mon, Jun 22, 2020 at 11:46 PM Paul Cercueil <paul@crapouillou.net> wrote: > Ingenic SoCs don't natively support registering an interrupt for both > rising and falling edges. This has to be emulated in software. > > Until now, this was emulated by switching back and forth between > IRQ_TYPE_EDGE_RISING and IRQ_TYPE_EDGE_FALLING according to the level of > the GPIO. While this worked most of the time, when used with GPIOs that > need debouncing, some events would be lost. For instance, between the > time a falling-edge interrupt happens and the interrupt handler > configures the hardware for rising-edge, the level of the pin may have > already risen, and the rising-edge event is lost. > > To address that issue, instead of switching back and forth between > IRQ_TYPE_EDGE_RISING and IRQ_TYPE_EDGE_FALLING, we now switch back and > forth between IRQ_TYPE_LEVEL_LOW and IRQ_TYPE_LEVEL_HIGH. Since we > always switch in the interrupt handler, they actually permit to detect > level changes. In the example above, if the pin level rises before > switching the IRQ type from IRQ_TYPE_LEVEL_LOW to IRQ_TYPE_LEVEL_HIGH, > a new interrupt will raise as soon as the handler exits, and the > rising-edge event will be properly detected. > > Cc: stable@vger.kernel.org > Fixes: e72394e2ea19 ("pinctrl: ingenic: Merge GPIO functionality") > Reported-by: João Henrique <johnnyonflame@hotmail.com> > Tested-by: João Henrique <johnnyonflame@hotmail.com> > Signed-off-by: Paul Cercueil <paul@crapouillou.net> I have applied these two as non-urgent fixes for v5.9. Are they urgent? Are they causing regressions? Tell me if they need to be merged to v5.8-rcs. Yours, Linus Walleij
diff --git a/drivers/pinctrl/pinctrl-ingenic.c b/drivers/pinctrl/pinctrl-ingenic.c index fc0d10411aa9..241e563d5814 100644 --- a/drivers/pinctrl/pinctrl-ingenic.c +++ b/drivers/pinctrl/pinctrl-ingenic.c @@ -1813,9 +1813,9 @@ static void ingenic_gpio_irq_ack(struct irq_data *irqd) */ high = ingenic_gpio_get_value(jzgc, irq); if (high) - irq_set_type(jzgc, irq, IRQ_TYPE_EDGE_FALLING); + irq_set_type(jzgc, irq, IRQ_TYPE_LEVEL_LOW); else - irq_set_type(jzgc, irq, IRQ_TYPE_EDGE_RISING); + irq_set_type(jzgc, irq, IRQ_TYPE_LEVEL_HIGH); } if (jzgc->jzpc->info->version >= ID_JZ4760) @@ -1851,7 +1851,7 @@ static int ingenic_gpio_irq_set_type(struct irq_data *irqd, unsigned int type) */ bool high = ingenic_gpio_get_value(jzgc, irqd->hwirq); - type = high ? IRQ_TYPE_EDGE_FALLING : IRQ_TYPE_EDGE_RISING; + type = high ? IRQ_TYPE_LEVEL_LOW : IRQ_TYPE_LEVEL_HIGH; } irq_set_type(jzgc, irqd->hwirq, type);