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>
This commit is contained in:
Radu Rendec 2023-01-06 11:04:19 -05:00 committed by Bartosz Golaszewski
parent 17a5f49b49
commit 64d2f4594e

View file

@ -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;