diff options
Diffstat (limited to 'drivers/gpio/gpio-pcf857x.c')
| -rw-r--r-- | drivers/gpio/gpio-pcf857x.c | 16 |
1 files changed, 15 insertions, 1 deletions
diff --git a/drivers/gpio/gpio-pcf857x.c b/drivers/gpio/gpio-pcf857x.c index c1f5e10a3c20..1ba6a09542f3 100644 --- a/drivers/gpio/gpio-pcf857x.c +++ b/drivers/gpio/gpio-pcf857x.c @@ -71,8 +71,9 @@ MODULE_DEVICE_TABLE(of, pcf857x_of_table); struct pcf857x { struct gpio_chip chip; struct i2c_client *client; - struct mutex lock; /* protect 'out' */ + struct mutex lock; /* protect 'out' and 'dir' */ unsigned int out; /* software latch */ + unsigned int dir; /* direction latch (1 = input) */ unsigned int status; /* current status */ unsigned int irq_enabled; /* enabled irqs */ @@ -126,12 +127,21 @@ static int pcf857x_input(struct gpio_chip *chip, unsigned int offset) mutex_lock(&gpio->lock); gpio->out |= (1 << offset); + gpio->dir |= (1 << offset); status = gpio->write(gpio->client, gpio->out); mutex_unlock(&gpio->lock); return status; } +static int pcf857x_get_direction(struct gpio_chip *chip, unsigned int offset) +{ + struct pcf857x *gpio = gpiochip_get_data(chip); + + return (gpio->dir & (1 << offset)) ? GPIO_LINE_DIRECTION_IN + : GPIO_LINE_DIRECTION_OUT; +} + static int pcf857x_get(struct gpio_chip *chip, unsigned int offset) { struct pcf857x *gpio = gpiochip_get_data(chip); @@ -167,6 +177,7 @@ static int pcf857x_output(struct gpio_chip *chip, unsigned int offset, int value gpio->out |= bit; else gpio->out &= ~bit; + gpio->dir &= ~bit; status = gpio->write(gpio->client, gpio->out); mutex_unlock(&gpio->lock); @@ -187,6 +198,7 @@ static int pcf857x_set_multiple(struct gpio_chip *chip, unsigned long *mask, mutex_lock(&gpio->lock); gpio->out &= ~*mask; gpio->out |= *bits & *mask; + gpio->dir &= ~*mask; status = gpio->write(gpio->client, gpio->out); mutex_unlock(&gpio->lock); @@ -301,6 +313,7 @@ static int pcf857x_probe(struct i2c_client *client) gpio->chip.set_multiple = pcf857x_set_multiple; gpio->chip.direction_input = pcf857x_input; gpio->chip.direction_output = pcf857x_output; + gpio->chip.get_direction = pcf857x_get_direction; gpio->chip.ngpio = (uintptr_t)i2c_get_match_data(client); reset_gpio = devm_gpiod_get_optional(&client->dev, "reset", GPIOD_OUT_HIGH); @@ -396,6 +409,7 @@ static int pcf857x_probe(struct i2c_client *client) * reset state. Otherwise it flags pins to be driven low. */ gpio->out = ~n_latch; + gpio->dir = ~n_latch; gpio->status = gpio->read(gpio->client); /* Enable irqchip if we have an interrupt */ |
