| From 223ecaf140b1dd1c1d2a1a1d96281efc5c906984 Mon Sep 17 00:00:00 2001 |
| From: Michael Wu <michael.wu@vatics.com> |
| Date: Mon, 8 Jul 2019 13:23:08 +0800 |
| Subject: gpiolib: fix incorrect IRQ requesting of an active-low lineevent |
| |
| From: Michael Wu <michael.wu@vatics.com> |
| |
| commit 223ecaf140b1dd1c1d2a1a1d96281efc5c906984 upstream. |
| |
| When a pin is active-low, logical trigger edge should be inverted to match |
| the same interrupt opportunity. |
| |
| For example, a button pushed triggers falling edge in ACTIVE_HIGH case; in |
| ACTIVE_LOW case, the button pushed triggers rising edge. For user space the |
| IRQ requesting doesn't need to do any modification except to configuring |
| GPIOHANDLE_REQUEST_ACTIVE_LOW. |
| |
| For example, we want to catch the event when the button is pushed. The |
| button on the original board drives level to be low when it is pushed, and |
| drives level to be high when it is released. |
| |
| In user space we can do: |
| |
| req.handleflags = GPIOHANDLE_REQUEST_INPUT; |
| req.eventflags = GPIOEVENT_REQUEST_FALLING_EDGE; |
| |
| while (1) { |
| read(fd, &dat, sizeof(dat)); |
| if (dat.id == GPIOEVENT_EVENT_FALLING_EDGE) |
| printf("button pushed\n"); |
| } |
| |
| Run the same logic on another board which the polarity of the button is |
| inverted; it drives level to be high when pushed, and level to be low when |
| released. For this inversion we add flag GPIOHANDLE_REQUEST_ACTIVE_LOW: |
| |
| req.handleflags = GPIOHANDLE_REQUEST_INPUT | |
| GPIOHANDLE_REQUEST_ACTIVE_LOW; |
| req.eventflags = GPIOEVENT_REQUEST_FALLING_EDGE; |
| |
| At the result, there are no any events caught when the button is pushed. |
| By the way, button releasing will emit a "falling" event. The timing of |
| "falling" catching is not expected. |
| |
| Cc: stable@vger.kernel.org |
| Signed-off-by: Michael Wu <michael.wu@vatics.com> |
| Tested-by: Bartosz Golaszewski <bgolaszewski@baylibre.com> |
| Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/gpio/gpiolib.c | 6 ++++-- |
| 1 file changed, 4 insertions(+), 2 deletions(-) |
| |
| --- a/drivers/gpio/gpiolib.c |
| +++ b/drivers/gpio/gpiolib.c |
| @@ -817,9 +817,11 @@ static int lineevent_create(struct gpio_ |
| } |
| |
| if (eflags & GPIOEVENT_REQUEST_RISING_EDGE) |
| - irqflags |= IRQF_TRIGGER_RISING; |
| + irqflags |= test_bit(FLAG_ACTIVE_LOW, &desc->flags) ? |
| + IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING; |
| if (eflags & GPIOEVENT_REQUEST_FALLING_EDGE) |
| - irqflags |= IRQF_TRIGGER_FALLING; |
| + irqflags |= test_bit(FLAG_ACTIVE_LOW, &desc->flags) ? |
| + IRQF_TRIGGER_RISING : IRQF_TRIGGER_FALLING; |
| irqflags |= IRQF_ONESHOT; |
| irqflags |= IRQF_SHARED; |
| |