|
@@ -1876,6 +1876,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
|
|
|
|
|
|
/**
|
|
@@ -2264,6 +2277,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;
|
|
@@ -2280,32 +2301,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:
|
|
@@ -2376,17 +2390,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);
|
|
|
|