aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpio
diff options
context:
space:
mode:
authorLinus Walleij <linus.walleij@linaro.org>2016-05-25 04:56:03 -0400
committerLinus Walleij <linus.walleij@linaro.org>2016-05-30 03:42:03 -0400
commit9c10280d85c14a20751ab6c1185ad725172936d6 (patch)
treef72f8ad76edba5852dd72714dfd0bf8a5ac3bd8c /drivers/gpio
parent320a6480ef24b03655e1854bd01c9b0a8b8d4a3f (diff)
gpio: flush direction status in gpiochip_lock_as_irq()
As irqchip and gpiochip functions are orthogonal, the IRQ set-up or something else can have changed the direction of the GPIO line from what the GPIO descriptor knows when we get into gpiochip_lock_as_irq(). Make sure to re-read the direction setting if we have the .get_direction() callback enabled for the chip. Else we get problems like this: iio iio:device2: interrupts on the rising edge gpio gpiochip2: (8012e080.gpio): gpiochip_lock_as_irq: tried to flag a GPIO set as output for IRQ gpio gpiochip2: (8012e080.gpio): unable to lock HW IRQ 0 for IRQ genirq: Failed to request resources for l3g4200d-trigger (irq 111) on irqchip nmk1-32-63 iio iio:device2: failed to request trigger IRQ. st-gyro-i2c: probe of 2-0068 failed with error -22 Fixes: 72d320006177 ("gpio: set up initial state from .get_direction()") Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/gpio')
-rw-r--r--drivers/gpio/gpiolib.c21
1 files changed, 17 insertions, 4 deletions
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index d407f904a31c..e901d2666b46 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -2066,17 +2066,30 @@ EXPORT_SYMBOL_GPL(gpiod_to_irq);
2066 */ 2066 */
2067int gpiochip_lock_as_irq(struct gpio_chip *chip, unsigned int offset) 2067int gpiochip_lock_as_irq(struct gpio_chip *chip, unsigned int offset)
2068{ 2068{
2069 if (offset >= chip->ngpio) 2069 struct gpio_desc *desc;
2070 return -EINVAL; 2070
2071 desc = gpiochip_get_desc(chip, offset);
2072 if (IS_ERR(desc))
2073 return PTR_ERR(desc);
2074
2075 /* Flush direction if something changed behind our back */
2076 if (chip->get_direction) {
2077 int dir = chip->get_direction(chip, offset);
2078
2079 if (dir)
2080 clear_bit(FLAG_IS_OUT, &desc->flags);
2081 else
2082 set_bit(FLAG_IS_OUT, &desc->flags);
2083 }
2071 2084
2072 if (test_bit(FLAG_IS_OUT, &chip->gpiodev->descs[offset].flags)) { 2085 if (test_bit(FLAG_IS_OUT, &desc->flags)) {
2073 chip_err(chip, 2086 chip_err(chip,
2074 "%s: tried to flag a GPIO set as output for IRQ\n", 2087 "%s: tried to flag a GPIO set as output for IRQ\n",
2075 __func__); 2088 __func__);
2076 return -EIO; 2089 return -EIO;
2077 } 2090 }
2078 2091
2079 set_bit(FLAG_USED_AS_IRQ, &chip->gpiodev->descs[offset].flags); 2092 set_bit(FLAG_USED_AS_IRQ, &desc->flags);
2080 return 0; 2093 return 0;
2081} 2094}
2082EXPORT_SYMBOL_GPL(gpiochip_lock_as_irq); 2095EXPORT_SYMBOL_GPL(gpiochip_lock_as_irq);