gpio: create an API to detect open drain/source on lines
authorLinus Walleij <linus.walleij@linaro.org>
Tue, 16 Feb 2016 14:41:42 +0000 (15:41 +0100)
committerLinus Walleij <linus.walleij@linaro.org>
Tue, 16 Feb 2016 14:41:42 +0000 (15:41 +0100)
My left hand merges code to privatize the descriptor handling
while my right hand merges drivers that poke around and
disrespect with the same gpiolib internals.

So let's expose the proper APIs for drivers to ask the gpiolib
core if a line is marked as open drain or open source and
get some order around things so this driver compiles again.

Reported-by: Stephen Rothwell <sfr@canb.auug.org.au>
Cc: Nicolas Saenz Julienne <nicolassaenzj@gmail.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
drivers/gpio/gpio-tps65218.c
drivers/gpio/gpiolib.c
include/linux/gpio/driver.h

index 7b02f7be9bc986d8b0748bb3fc82e024e44deda1..9eb1a5ab2d95372a3da7c62b926f4dd83c18f9f2 100644 (file)
@@ -71,17 +71,16 @@ static int tps65218_gpio_request(struct gpio_chip *gc, unsigned offset)
 {
        struct tps65218_gpio *tps65218_gpio = gpiochip_get_data(gc);
        struct tps65218 *tps65218 = tps65218_gpio->tps65218;
-       unsigned long flags = gc->desc[offset].flags;
        int ret;
 
-       if (flags & FLAG_OPEN_SOURCE) {
+       if (gpiochip_line_is_open_source(gc, offset)) {
                dev_err(gc->parent, "can't work as open source\n");
                return -EINVAL;
        }
 
        switch (offset) {
        case 0:
-               if (!(flags & FLAG_OPEN_DRAIN)) {
+               if (!gpiochip_line_is_open_drain(gc, offset)) {
                        dev_err(gc->parent, "GPO1 works only as open drain\n");
                        return -EINVAL;
                }
@@ -103,7 +102,7 @@ static int tps65218_gpio_request(struct gpio_chip *gc, unsigned offset)
                break;
        case 1:
                /* GP02 is push-pull by default, can be set as open drain. */
-               if (flags & FLAG_OPEN_DRAIN) {
+               if (gpiochip_line_is_open_drain(gc, offset)) {
                        ret = tps65218_clear_bits(tps65218,
                                                  TPS65218_REG_CONFIG1,
                                                  TPS65218_CONFIG1_GPO2_BUF,
@@ -122,7 +121,7 @@ static int tps65218_gpio_request(struct gpio_chip *gc, unsigned offset)
                break;
 
        case 2:
-               if (!(flags & FLAG_OPEN_DRAIN)) {
+               if (!gpiochip_line_is_open_drain(gc, offset)) {
                        dev_err(gc->parent, "GPO3 works only as open drain\n");
                        return -EINVAL;
                }
index aa4a60e19339b8b564641a945907e7710ae23023..d8511cd68e7b86a32db571d1d2b21b4389696e78 100644 (file)
@@ -1901,6 +1901,24 @@ bool gpiochip_line_is_irq(struct gpio_chip *chip, unsigned int offset)
 }
 EXPORT_SYMBOL_GPL(gpiochip_line_is_irq);
 
+bool gpiochip_line_is_open_drain(struct gpio_chip *chip, unsigned int offset)
+{
+       if (offset >= chip->ngpio)
+               return false;
+
+       return test_bit(FLAG_OPEN_DRAIN, &chip->gpiodev->descs[offset].flags);
+}
+EXPORT_SYMBOL_GPL(gpiochip_line_is_open_drain);
+
+bool gpiochip_line_is_open_source(struct gpio_chip *chip, unsigned int offset)
+{
+       if (offset >= chip->ngpio)
+               return false;
+
+       return test_bit(FLAG_OPEN_SOURCE, &chip->gpiodev->descs[offset].flags);
+}
+EXPORT_SYMBOL_GPL(gpiochip_line_is_open_source);
+
 /**
  * gpiod_get_raw_value_cansleep() - return a gpio's raw value
  * @desc: gpio whose value will be returned
index b92ab9efdb692f2e42b81e994d0d1ee219c255c3..ff96d0f9fceb1dd0d9ae52ab38b8675e00ff05f4 100644 (file)
@@ -199,6 +199,10 @@ int gpiochip_lock_as_irq(struct gpio_chip *chip, unsigned int offset);
 void gpiochip_unlock_as_irq(struct gpio_chip *chip, unsigned int offset);
 bool gpiochip_line_is_irq(struct gpio_chip *chip, unsigned int offset);
 
+/* Line status inquiry for drivers */
+bool gpiochip_line_is_open_drain(struct gpio_chip *chip, unsigned int offset);
+bool gpiochip_line_is_open_source(struct gpio_chip *chip, unsigned int offset);
+
 /* get driver data */
 void *gpiochip_get_data(struct gpio_chip *chip);