summaryrefslogtreecommitdiff
path: root/drivers/gpio
diff options
context:
space:
mode:
authorLinus Walleij <linus.walleij@linaro.org>2020-05-27 16:07:58 +0200
committerLinus Walleij <linus.walleij@linaro.org>2020-05-29 14:01:49 +0200
commite9bdf7e655b9ee81ee912fae1d59df48ce7311b6 (patch)
tree58ac91fc243f77957978b35243b73ec66b295917 /drivers/gpio
parentad3073bcb903674b11ba3395361f3b94806bb2b6 (diff)
gpio: fix locking open drain IRQ lines
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>
Diffstat (limited to 'drivers/gpio')
-rw-r--r--drivers/gpio/gpiolib.c11
1 files changed, 9 insertions, 2 deletions
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index b4b5792fe2ff..c14f0784274a 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -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);
}
}