diff options
-rw-r--r-- | drivers/gpio/gpio-tc3589x.c | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/drivers/gpio/gpio-tc3589x.c b/drivers/gpio/gpio-tc3589x.c index 2845653..15552fd 100644 --- a/drivers/gpio/gpio-tc3589x.c +++ b/drivers/gpio/gpio-tc3589x.c @@ -85,6 +85,46 @@ static int tc3589x_gpio_direction_input(struct gpio_chip *chip, return tc3589x_set_bits(tc3589x, reg, BIT(pos), 0); } +static int tc3589x_gpio_single_ended(struct gpio_chip *chip, + unsigned offset, + enum single_ended_mode mode) +{ + struct tc3589x_gpio *tc3589x_gpio = gpiochip_get_data(chip); + struct tc3589x *tc3589x = tc3589x_gpio->tc3589x; + /* + * These registers are alterated at each second address + * ODM bit 0 = drive to GND or Hi-Z (open drain) + * ODM bit 1 = drive to VDD or Hi-Z (open source) + */ + u8 odmreg = TC3589x_GPIOODM0 + (offset / 8) * 2; + u8 odereg = TC3589x_GPIOODE0 + (offset / 8) * 2; + unsigned pos = offset % 8; + int ret; + + switch(mode) { + case LINE_MODE_OPEN_DRAIN: + /* Set open drain mode */ + ret = tc3589x_set_bits(tc3589x, odmreg, BIT(pos), 0); + if (ret) + return ret; + /* Enable open drain/source mode */ + return tc3589x_set_bits(tc3589x, odereg, BIT(pos), BIT(pos)); + case LINE_MODE_OPEN_SOURCE: + /* Set open source mode */ + ret = tc3589x_set_bits(tc3589x, odmreg, BIT(pos), BIT(pos)); + if (ret) + return ret; + /* Enable open drain/source mode */ + return tc3589x_set_bits(tc3589x, odereg, BIT(pos), BIT(pos)); + case LINE_MODE_PUSH_PULL: + /* Disable open drain/source mode */ + return tc3589x_set_bits(tc3589x, odereg, BIT(pos), 0); + default: + break; + } + return -ENOTSUPP; +} + static struct gpio_chip template_chip = { .label = "tc3589x", .owner = THIS_MODULE, @@ -92,6 +132,7 @@ static struct gpio_chip template_chip = { .get = tc3589x_gpio_get, .direction_output = tc3589x_gpio_direction_output, .set = tc3589x_gpio_set, + .set_single_ended = tc3589x_gpio_single_ended, .can_sleep = true, }; |