summaryrefslogtreecommitdiffstats
path: root/drivers/gpio/gpio-sch311x.c
diff options
context:
space:
mode:
authorLinus Walleij <linus.walleij@linaro.org>2018-06-27 11:00:44 +0200
committerLinus Walleij <linus.walleij@linaro.org>2018-07-02 16:00:49 +0200
commit4455a82a400ba462db8abb642c670555d505bccc (patch)
treee0d3d9d0123bd497a79e00c4be8af445125a1ca4 /drivers/gpio/gpio-sch311x.c
parent4a2398d7211f8f750b717ce4a2b0d117385f2a4a (diff)
downloadlinux-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.c29
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;