gpio: add core support for pull-up/pull-down configuration
authorThomas Petazzoni <thomas.petazzoni@bootlin.com>
Thu, 7 Feb 2019 16:28:58 +0000 (17:28 +0100)
committerLinus Walleij <linus.walleij@linaro.org>
Wed, 13 Feb 2019 08:10:14 +0000 (09:10 +0100)
This commit adds support for configuring the pull-up and pull-down
resistors available in some GPIO controllers. While configuring
pull-up/pull-down is already possible through the pinctrl subsystem,
some GPIO controllers, especially simple ones such as GPIO expanders
on I2C, don't have any pinmuxing capability and therefore do not use
the pinctrl subsystem.

This commit implements the GPIO_PULL_UP and GPIO_PULL_DOWN flags,
which can be used from the Device Tree, to enable a pull-up or
pull-down resistor on a given GPIO.

The flag is simply propagated all the way to the core GPIO subsystem,
where it is used to call the gpio_chip ->set_config callback with the
appropriate existing PIN_CONFIG_BIAS_* values.

Signed-off-by: Thomas Petazzoni <thomas.petazzoni@bootlin.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
drivers/gpio/gpiolib-of.c
drivers/gpio/gpiolib.c
drivers/gpio/gpiolib.h
include/linux/gpio/machine.h
include/linux/of_gpio.h

index a6e1891217e26880cb94bd2ec6b08289733f8c42..9a8b78477f792de412dd08d204a1e9ad16a9dad7 100644 (file)
@@ -345,6 +345,11 @@ struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id,
        if (of_flags & OF_GPIO_TRANSITORY)
                *flags |= GPIO_TRANSITORY;
 
+       if (of_flags & OF_GPIO_PULL_UP)
+               *flags |= GPIO_PULL_UP;
+       if (of_flags & OF_GPIO_PULL_DOWN)
+               *flags |= GPIO_PULL_DOWN;
+
        return desc;
 }
 
index 1f239aac43df06f2785f6fd27d97c7a0cadd556c..22d8b37f531974d476650cfea6cd12f85f4a8249 100644 (file)
@@ -2573,6 +2573,13 @@ int gpiod_direction_input(struct gpio_desc *desc)
        if (status == 0)
                clear_bit(FLAG_IS_OUT, &desc->flags);
 
+       if (test_bit(FLAG_PULL_UP, &desc->flags))
+               gpio_set_config(chip, gpio_chip_hwgpio(desc),
+                               PIN_CONFIG_BIAS_PULL_UP);
+       else if (test_bit(FLAG_PULL_DOWN, &desc->flags))
+               gpio_set_config(chip, gpio_chip_hwgpio(desc),
+                               PIN_CONFIG_BIAS_PULL_DOWN);
+
        trace_gpio_direction(desc_to_gpio(desc), 1, status);
 
        return status;
@@ -4050,6 +4057,17 @@ int gpiod_configure_flags(struct gpio_desc *desc, const char *con_id,
        if (lflags & GPIO_OPEN_SOURCE)
                set_bit(FLAG_OPEN_SOURCE, &desc->flags);
 
+       if ((lflags & GPIO_PULL_UP) && (lflags & GPIO_PULL_DOWN)) {
+               gpiod_err(desc,
+                         "both pull-up and pull-down enabled, invalid configuration\n");
+               return -EINVAL;
+       }
+
+       if (lflags & GPIO_PULL_UP)
+               set_bit(FLAG_PULL_UP, &desc->flags);
+       else if (lflags & GPIO_PULL_DOWN)
+               set_bit(FLAG_PULL_DOWN, &desc->flags);
+
        status = gpiod_set_transitory(desc, (lflags & GPIO_TRANSITORY));
        if (status < 0)
                return status;
index bc57f0dc59532f9c0d085e74b9ebc0f0e5bb6841..078ab17b96bf4e84d52d2e159b4f6ee5b5adad77 100644 (file)
@@ -219,6 +219,8 @@ struct gpio_desc {
 #define FLAG_IRQ_IS_ENABLED 10 /* GPIO is connected to an enabled IRQ */
 #define FLAG_IS_HOGGED 11      /* GPIO is hogged */
 #define FLAG_TRANSITORY 12     /* GPIO may lose value in sleep or reset */
+#define FLAG_PULL_UP    13     /* GPIO has pull up enabled */
+#define FLAG_PULL_DOWN  14     /* GPIO has pull down enabled */
 
        /* Connection label */
        const char              *label;
index daa44eac9241b008a3848ad76ef6b73dbf6495d0..69673be10213d94a839ac6c6d97bdc1e27e1aa57 100644 (file)
@@ -12,6 +12,8 @@ enum gpio_lookup_flags {
        GPIO_OPEN_SOURCE = (1 << 2),
        GPIO_PERSISTENT = (0 << 3),
        GPIO_TRANSITORY = (1 << 3),
+       GPIO_PULL_UP = (1 << 4),
+       GPIO_PULL_DOWN = (1 << 5),
 };
 
 /**
index 163b79ecd01a39fb141ae8f6052f74fc86b93210..f9737dea9d1f945a574c25aea05d02144e185b13 100644 (file)
@@ -28,6 +28,8 @@ enum of_gpio_flags {
        OF_GPIO_SINGLE_ENDED = 0x2,
        OF_GPIO_OPEN_DRAIN = 0x4,
        OF_GPIO_TRANSITORY = 0x8,
+       OF_GPIO_PULL_UP = 0x10,
+       OF_GPIO_PULL_DOWN = 0x20,
 };
 
 #ifdef CONFIG_OF_GPIO