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@xxxxxxxxx> --- drivers/gpio/gpio-pcf857x.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) 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; -- 2.39.0