Skip to content

Commit

Permalink
gpio: add core support for pull-up/pull-down configuration
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Thomas Petazzoni authored and Linus Walleij committed Feb 13, 2019
1 parent 6581eaf commit d449991
Show file tree
Hide file tree
Showing 5 changed files with 29 additions and 0 deletions.
5 changes: 5 additions & 0 deletions drivers/gpio/gpiolib-of.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
18 changes: 18 additions & 0 deletions drivers/gpio/gpiolib.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions drivers/gpio/gpiolib.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions include/linux/gpio/machine.h
Original file line number Diff line number Diff line change
Expand Up @@ -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),
};

/**
Expand Down
2 changes: 2 additions & 0 deletions include/linux/of_gpio.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit d449991

Please sign in to comment.