Commit 64d2f459 authored by Radu Rendec's avatar Radu Rendec Committed by Bartosz Golaszewski
Browse files

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: default avatarRadu Rendec <radu.rendec@gmail.com>
Signed-off-by: default avatarBartosz Golaszewski <bartosz.golaszewski@linaro.org>
parent 17a5f49b
Loading
Loading
Loading
Loading
+29 −0
Original line number Diff line number Diff line
@@ -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;