diff options
author | Radu Rendec <radu.rendec@gmail.com> | 2023-01-06 11:04:19 -0500 |
---|---|---|
committer | Bartosz Golaszewski <bartosz.golaszewski@linaro.org> | 2023-01-30 15:55:29 +0100 |
commit | 64d2f4594e33b84d4e091efb8b2c3282fe82e72f (patch) | |
tree | f6e247bf417e97f31ec99b4f14a1f18d86913c5e /drivers/gpio | |
parent | 17a5f49b49fdd9a5b8b2ed6a30d0b8efc9b1e9b9 (diff) |
gpio: pcf857x: Implement get_multiple/set_multiple methods
This change allows the GPIO core to read/change multiple pins in a
single driver call and subsequent I2C transfer. It helps a lot with
PCF857x devices, since their I2C protocol always reads/changes all
existing pins anyway. Therefore, when the GPIO client code does a bulk
operation on multiple pins, the driver makes a single I2C transfer.
Signed-off-by: Radu Rendec <radu.rendec@gmail.com>
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
Diffstat (limited to 'drivers/gpio')
-rw-r--r-- | drivers/gpio/gpio-pcf857x.c | 29 |
1 files changed, 29 insertions, 0 deletions
diff --git a/drivers/gpio/gpio-pcf857x.c b/drivers/gpio/gpio-pcf857x.c index 1026973bc998..d9db878802b7 100644 --- a/drivers/gpio/gpio-pcf857x.c +++ b/drivers/gpio/gpio-pcf857x.c @@ -141,6 +141,21 @@ static int pcf857x_get(struct gpio_chip *chip, unsigned int offset) return (value < 0) ? value : !!(value & (1 << offset)); } +static int pcf857x_get_multiple(struct gpio_chip *chip, unsigned long *mask, + unsigned long *bits) +{ + struct pcf857x *gpio = gpiochip_get_data(chip); + int value = gpio->read(gpio->client); + + if (value < 0) + return value; + + *bits &= ~*mask; + *bits |= value & *mask; + + return 0; +} + static int pcf857x_output(struct gpio_chip *chip, unsigned int offset, int value) { struct pcf857x *gpio = gpiochip_get_data(chip); @@ -163,6 +178,18 @@ static void pcf857x_set(struct gpio_chip *chip, unsigned int offset, int value) pcf857x_output(chip, offset, value); } +static void pcf857x_set_multiple(struct gpio_chip *chip, unsigned long *mask, + unsigned long *bits) +{ + struct pcf857x *gpio = gpiochip_get_data(chip); + + mutex_lock(&gpio->lock); + gpio->out &= ~*mask; + gpio->out |= *bits & *mask; + gpio->write(gpio->client, gpio->out); + mutex_unlock(&gpio->lock); +} + /*-------------------------------------------------------------------------*/ static irqreturn_t pcf857x_irq(int irq, void *data) @@ -275,7 +302,9 @@ static int pcf857x_probe(struct i2c_client *client) gpio->chip.parent = &client->dev; gpio->chip.owner = THIS_MODULE; gpio->chip.get = pcf857x_get; + gpio->chip.get_multiple = pcf857x_get_multiple; gpio->chip.set = pcf857x_set; + gpio->chip.set_multiple = pcf857x_set_multiple; gpio->chip.direction_input = pcf857x_input; gpio->chip.direction_output = pcf857x_output; gpio->chip.ngpio = id->driver_data; |