gpio: sch311x: Implement open drain support
authorLinus Walleij <linus.walleij@linaro.org>
Wed, 27 Jun 2018 09:00:44 +0000 (11:00 +0200)
committerLinus Walleij <linus.walleij@linaro.org>
Mon, 2 Jul 2018 14:00:49 +0000 (16:00 +0200)
The chip has a bit for controlling open drain, and it is
easy to implement the callback to support open drain when
needed, so let's implement it.

Cc: Bruno Randolf <br1@einfach.org>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
drivers/gpio/gpio-sch311x.c

index faf44178f97b259d6e67a2258fe2158f5d815f1e..1d2af9f97a91bc993d4f1908ee5efee014d9503f 100644 (file)
@@ -235,6 +235,34 @@ static int sch311x_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
        return !!(data & SCH311X_GPIO_CONF_DIR);
 }
 
+static int sch311x_gpio_set_config(struct gpio_chip *chip, unsigned offset,
+                                  unsigned long config)
+{
+       struct sch311x_gpio_block *block = gpiochip_get_data(chip);
+       enum pin_config_param param = pinconf_to_config_param(config);
+       unsigned char data;
+
+       switch (param) {
+       case PIN_CONFIG_DRIVE_OPEN_DRAIN:
+               spin_lock(&block->lock);
+               data = inb(block->runtime_reg + block->config_regs[offset]);
+               data |= SCH311X_GPIO_CONF_OPEN_DRAIN;
+               outb(data, block->runtime_reg + block->config_regs[offset]);
+               spin_unlock(&block->lock);
+               return 0;
+       case PIN_CONFIG_DRIVE_PUSH_PULL:
+               spin_lock(&block->lock);
+               data = inb(block->runtime_reg + block->config_regs[offset]);
+               data &= ~SCH311X_GPIO_CONF_OPEN_DRAIN;
+               outb(data, block->runtime_reg + block->config_regs[offset]);
+               spin_unlock(&block->lock);
+               return 0;
+       default:
+               break;
+       }
+       return -ENOTSUPP;
+}
+
 static int sch311x_gpio_probe(struct platform_device *pdev)
 {
        struct sch311x_pdev_data *pdata = dev_get_platdata(&pdev->dev);
@@ -268,6 +296,7 @@ static int sch311x_gpio_probe(struct platform_device *pdev)
                block->chip.direction_input = sch311x_gpio_direction_in;
                block->chip.direction_output = sch311x_gpio_direction_out;
                block->chip.get_direction = sch311x_gpio_get_direction;
+               block->chip.set_config = sch311x_gpio_set_config;
                block->chip.get = sch311x_gpio_get;
                block->chip.set = sch311x_gpio_set;
                block->chip.ngpio = 8;