diff options
author | Linus Walleij <linus.walleij@linaro.org> | 2018-06-27 11:00:44 +0200 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2018-07-02 16:00:49 +0200 |
commit | 4455a82a400ba462db8abb642c670555d505bccc (patch) | |
tree | e0d3d9d0123bd497a79e00c4be8af445125a1ca4 /drivers/gpio/gpio-sch311x.c | |
parent | 4a2398d7211f8f750b717ce4a2b0d117385f2a4a (diff) | |
download | linux-4455a82a400ba462db8abb642c670555d505bccc.tar.gz linux-4455a82a400ba462db8abb642c670555d505bccc.tar.bz2 linux-4455a82a400ba462db8abb642c670555d505bccc.zip |
gpio: sch311x: Implement open drain support
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>
Diffstat (limited to 'drivers/gpio/gpio-sch311x.c')
-rw-r--r-- | drivers/gpio/gpio-sch311x.c | 29 |
1 files changed, 29 insertions, 0 deletions
diff --git a/drivers/gpio/gpio-sch311x.c b/drivers/gpio/gpio-sch311x.c index faf44178f97b..1d2af9f97a91 100644 --- a/drivers/gpio/gpio-sch311x.c +++ b/drivers/gpio/gpio-sch311x.c @@ -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; |