]> git.proxmox.com Git - mirror_ubuntu-kernels.git/commitdiff
gpio: fix locking open drain IRQ lines
authorLinus Walleij <linus.walleij@linaro.org>
Wed, 27 May 2020 14:07:58 +0000 (16:07 +0200)
committerLinus Walleij <linus.walleij@linaro.org>
Fri, 29 May 2020 12:01:49 +0000 (14:01 +0200)
We provided the right semantics on open drain lines being
by definition output but incidentally the irq set up function
would only allow IRQs on lines that were "not output".

Fix the semantics to allow output open drain lines to be used
for IRQs.

Reported-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
Tested-by: Hans Verkuil <hverkuil@xs4all.nl>
Cc: Russell King <linux@armlinux.org.uk>
Cc: stable@vger.kernel.org # v5.3+
Link: https://lore.kernel.org/r/20200527140758.162280-1-linus.walleij@linaro.org
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
drivers/gpio/gpiolib.c

index b4b5792fe2ffc471329ed89dbdf2ed082663415c..c14f0784274ae8ab7780a69791ae1682480c3f2e 100644 (file)
@@ -4220,7 +4220,9 @@ int gpiochip_lock_as_irq(struct gpio_chip *gc, unsigned int offset)
                }
        }
 
-       if (test_bit(FLAG_IS_OUT, &desc->flags)) {
+       /* To be valid for IRQ the line needs to be input or open drain */
+       if (test_bit(FLAG_IS_OUT, &desc->flags) &&
+           !test_bit(FLAG_OPEN_DRAIN, &desc->flags)) {
                chip_err(gc,
                         "%s: tried to flag a GPIO set as output for IRQ\n",
                         __func__);
@@ -4283,7 +4285,12 @@ void gpiochip_enable_irq(struct gpio_chip *gc, unsigned int offset)
 
        if (!IS_ERR(desc) &&
            !WARN_ON(!test_bit(FLAG_USED_AS_IRQ, &desc->flags))) {
-               WARN_ON(test_bit(FLAG_IS_OUT, &desc->flags));
+               /*
+                * We must not be output when using IRQ UNLESS we are
+                * open drain.
+                */
+               WARN_ON(test_bit(FLAG_IS_OUT, &desc->flags) &&
+                       !test_bit(FLAG_OPEN_DRAIN, &desc->flags));
                set_bit(FLAG_IRQ_IS_ENABLED, &desc->flags);
        }
 }