Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

gpio: add core support for pull-up/pull-down configuration

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>

authored by

Thomas Petazzoni and committed by
Linus Walleij
d449991c 6581eaf0

+29
+5
drivers/gpio/gpiolib-of.c
··· 345 345 if (of_flags & OF_GPIO_TRANSITORY) 346 346 *flags |= GPIO_TRANSITORY; 347 347 348 + if (of_flags & OF_GPIO_PULL_UP) 349 + *flags |= GPIO_PULL_UP; 350 + if (of_flags & OF_GPIO_PULL_DOWN) 351 + *flags |= GPIO_PULL_DOWN; 352 + 348 353 return desc; 349 354 } 350 355
+18
drivers/gpio/gpiolib.c
··· 2573 2573 if (status == 0) 2574 2574 clear_bit(FLAG_IS_OUT, &desc->flags); 2575 2575 2576 + if (test_bit(FLAG_PULL_UP, &desc->flags)) 2577 + gpio_set_config(chip, gpio_chip_hwgpio(desc), 2578 + PIN_CONFIG_BIAS_PULL_UP); 2579 + else if (test_bit(FLAG_PULL_DOWN, &desc->flags)) 2580 + gpio_set_config(chip, gpio_chip_hwgpio(desc), 2581 + PIN_CONFIG_BIAS_PULL_DOWN); 2582 + 2576 2583 trace_gpio_direction(desc_to_gpio(desc), 1, status); 2577 2584 2578 2585 return status; ··· 4056 4049 4057 4050 if (lflags & GPIO_OPEN_SOURCE) 4058 4051 set_bit(FLAG_OPEN_SOURCE, &desc->flags); 4052 + 4053 + if ((lflags & GPIO_PULL_UP) && (lflags & GPIO_PULL_DOWN)) { 4054 + gpiod_err(desc, 4055 + "both pull-up and pull-down enabled, invalid configuration\n"); 4056 + return -EINVAL; 4057 + } 4058 + 4059 + if (lflags & GPIO_PULL_UP) 4060 + set_bit(FLAG_PULL_UP, &desc->flags); 4061 + else if (lflags & GPIO_PULL_DOWN) 4062 + set_bit(FLAG_PULL_DOWN, &desc->flags); 4059 4063 4060 4064 status = gpiod_set_transitory(desc, (lflags & GPIO_TRANSITORY)); 4061 4065 if (status < 0)
+2
drivers/gpio/gpiolib.h
··· 219 219 #define FLAG_IRQ_IS_ENABLED 10 /* GPIO is connected to an enabled IRQ */ 220 220 #define FLAG_IS_HOGGED 11 /* GPIO is hogged */ 221 221 #define FLAG_TRANSITORY 12 /* GPIO may lose value in sleep or reset */ 222 + #define FLAG_PULL_UP 13 /* GPIO has pull up enabled */ 223 + #define FLAG_PULL_DOWN 14 /* GPIO has pull down enabled */ 222 224 223 225 /* Connection label */ 224 226 const char *label;
+2
include/linux/gpio/machine.h
··· 12 12 GPIO_OPEN_SOURCE = (1 << 2), 13 13 GPIO_PERSISTENT = (0 << 3), 14 14 GPIO_TRANSITORY = (1 << 3), 15 + GPIO_PULL_UP = (1 << 4), 16 + GPIO_PULL_DOWN = (1 << 5), 15 17 }; 16 18 17 19 /**
+2
include/linux/of_gpio.h
··· 28 28 OF_GPIO_SINGLE_ENDED = 0x2, 29 29 OF_GPIO_OPEN_DRAIN = 0x4, 30 30 OF_GPIO_TRANSITORY = 0x8, 31 + OF_GPIO_PULL_UP = 0x10, 32 + OF_GPIO_PULL_DOWN = 0x20, 31 33 }; 32 34 33 35 #ifdef CONFIG_OF_GPIO