diff options
Diffstat (limited to 'drivers/gpio/gpiolib.c')
-rw-r--r-- | drivers/gpio/gpiolib.c | 56 |
1 files changed, 36 insertions, 20 deletions
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 14ee088c80dd..18a173fc4a21 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1875,6 +1875,19 @@ void gpiochip_generic_free(struct gpio_chip *chip, unsigned offset) } EXPORT_SYMBOL_GPL(gpiochip_generic_free); +/** + * gpiochip_generic_config() - apply configuration for a pin + * @chip: the gpiochip owning the GPIO + * @offset: the offset of the GPIO to apply the configuration + * @config: the configuration to be applied + */ +int gpiochip_generic_config(struct gpio_chip *chip, unsigned offset, + unsigned long config) +{ + return pinctrl_gpio_set_config(chip->gpiodev->base + offset, config); +} +EXPORT_SYMBOL_GPL(gpiochip_generic_config); + #ifdef CONFIG_PINCTRL /** @@ -2263,6 +2276,14 @@ int gpiod_direction_input(struct gpio_desc *desc) } EXPORT_SYMBOL_GPL(gpiod_direction_input); +static int gpio_set_drive_single_ended(struct gpio_chip *gc, unsigned offset, + enum pin_config_param mode) +{ + unsigned long config = { PIN_CONF_PACKED(mode, 0) }; + + return gc->set_config ? gc->set_config(gc, offset, config) : -ENOTSUPP; +} + static int _gpiod_direction_output_raw(struct gpio_desc *desc, int value) { struct gpio_chip *gc = desc->gdev->chip; @@ -2279,32 +2300,25 @@ static int _gpiod_direction_output_raw(struct gpio_desc *desc, int value) if (test_bit(FLAG_OPEN_DRAIN, &desc->flags)) { /* First see if we can enable open drain in hardware */ - if (gc->set_single_ended) { - ret = gc->set_single_ended(gc, gpio_chip_hwgpio(desc), - LINE_MODE_OPEN_DRAIN); - if (!ret) - goto set_output_value; - } + ret = gpio_set_drive_single_ended(gc, gpio_chip_hwgpio(desc), + PIN_CONFIG_DRIVE_OPEN_DRAIN); + if (!ret) + goto set_output_value; /* Emulate open drain by not actively driving the line high */ if (val) return gpiod_direction_input(desc); } else if (test_bit(FLAG_OPEN_SOURCE, &desc->flags)) { - if (gc->set_single_ended) { - ret = gc->set_single_ended(gc, gpio_chip_hwgpio(desc), - LINE_MODE_OPEN_SOURCE); - if (!ret) - goto set_output_value; - } + ret = gpio_set_drive_single_ended(gc, gpio_chip_hwgpio(desc), + PIN_CONFIG_DRIVE_OPEN_SOURCE); + if (!ret) + goto set_output_value; /* Emulate open source by not actively driving the line low */ if (!val) return gpiod_direction_input(desc); } else { - /* Make sure to disable open drain/source hardware, if any */ - if (gc->set_single_ended) - gc->set_single_ended(gc, - gpio_chip_hwgpio(desc), - LINE_MODE_PUSH_PULL); + gpio_set_drive_single_ended(gc, gpio_chip_hwgpio(desc), + PIN_CONFIG_DRIVE_PUSH_PULL); } set_output_value: @@ -2375,17 +2389,19 @@ EXPORT_SYMBOL_GPL(gpiod_direction_output); int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce) { struct gpio_chip *chip; + unsigned long config; VALIDATE_DESC(desc); chip = desc->gdev->chip; - if (!chip->set || !chip->set_debounce) { + if (!chip->set || !chip->set_config) { gpiod_dbg(desc, - "%s: missing set() or set_debounce() operations\n", + "%s: missing set() or set_config() operations\n", __func__); return -ENOTSUPP; } - return chip->set_debounce(chip, gpio_chip_hwgpio(desc), debounce); + config = pinconf_to_config_packed(PIN_CONFIG_INPUT_DEBOUNCE, debounce); + return chip->set_config(chip, gpio_chip_hwgpio(desc), config); } EXPORT_SYMBOL_GPL(gpiod_set_debounce); |