Skip to contentSkip to conversation

gpio: pcf857x: Implement get_multiple/set_multiple methods

PATCH Applied Radu Rendec 2 participants 5 messages Jan 6, 2023 – Jan 11, 2023 GPIO

lore
Share & tools
lore
#0 lore raw

v2 cover gpio: pcf857x: Implement get_multiple/set_multiple methods

The first two patches are just cosmetic changes. The actual changes are in the third patch. They are all bundled together in a patch series just because the third patch doesn't apply cleanly without the other two.

Change description from the third patch:

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.

Radu Rendec (3):
gpio: pcf857x: Replace 'unsigned' with 'unsigned int'
gpio: pcf857x: Fix indentation of variable declarations
gpio: pcf857x: Implement get_multiple/set_multiple methods

 drivers/gpio/gpio-pcf857x.c | 79 +++++++++++++++++++++++++------------
 1 file changed, 54 insertions(+), 25 deletions(-)
Signature · 1 line
2.39.0
#1 lore raw

PATCH v2 1/3 gpio: pcf857x: Replace 'unsigned' with 'unsigned int'

Cosmetic change only to improve the coding style. No functional change, since 'unsigned' and 'unsigned int' are identical as far as the compiler is concerned.

---
 drivers/gpio/gpio-pcf857x.c | 22 +++++++++++-----------
 1 file changed, 11 insertions(+), 11 deletions(-)
drivers/gpio/gpio-pcf857x.c +11 -11
index cec2f2c78255..14656d4f3a3d 100644
@@ -73,11 +73,11 @@ struct pcf857x {
 	struct gpio_chip	chip;
 	struct i2c_client	*client;
 	struct mutex		lock;		/* protect 'out' */
-	unsigned		out;		/* software latch */
-	unsigned		status;		/* current status */
-	unsigned		irq_enabled;	/* enabled irqs */
+	unsigned int		out;		/* software latch */
+	unsigned int		status;		/* current status */
+	unsigned int		irq_enabled;	/* enabled irqs */
 
-	int (*write)(struct i2c_client *client, unsigned data);
+	int (*write)(struct i2c_client *client, unsigned int data);
 	int (*read)(struct i2c_client *client);
 };
 
@@ -85,7 +85,7 @@ struct pcf857x {
 
 /* Talk to 8-bit I/O expander */
 
-static int i2c_write_le8(struct i2c_client *client, unsigned data)
+static int i2c_write_le8(struct i2c_client *client, unsigned int data)
 {
 	return i2c_smbus_write_byte(client, data);
 }
@@ -97,7 +97,7 @@ static int i2c_read_le8(struct i2c_client *client)
 
 /* Talk to 16-bit I/O expander */
 
-static int i2c_write_le16(struct i2c_client *client, unsigned word)
+static int i2c_write_le16(struct i2c_client *client, unsigned int word)
 {
 	u8 buf[2] = { word & 0xff, word >> 8, };
 	int status;
@@ -119,7 +119,7 @@ static int i2c_read_le16(struct i2c_client *client)
 
 /*-------------------------------------------------------------------------*/
 
-static int pcf857x_input(struct gpio_chip *chip, unsigned offset)
+static int pcf857x_input(struct gpio_chip *chip, unsigned int offset)
 {
 	struct pcf857x	*gpio = gpiochip_get_data(chip);
 	int		status;
@@ -132,7 +132,7 @@ static int pcf857x_input(struct gpio_chip *chip, unsigned offset)
 	return status;
 }
 
-static int pcf857x_get(struct gpio_chip *chip, unsigned offset)
+static int pcf857x_get(struct gpio_chip *chip, unsigned int offset)
 {
 	struct pcf857x	*gpio = gpiochip_get_data(chip);
 	int		value;
@@ -141,10 +141,10 @@ static int pcf857x_get(struct gpio_chip *chip, unsigned offset)
 	return (value < 0) ? value : !!(value & (1 << offset));
 }
 
-static int pcf857x_output(struct gpio_chip *chip, unsigned offset, int value)
+static int pcf857x_output(struct gpio_chip *chip, unsigned int offset, int value)
 {
 	struct pcf857x	*gpio = gpiochip_get_data(chip);
-	unsigned	bit = 1 << offset;
+	unsigned int	bit = 1 << offset;
 	int		status;
 
 	mutex_lock(&gpio->lock);
@@ -158,7 +158,7 @@ static int pcf857x_output(struct gpio_chip *chip, unsigned offset, int value)
 	return status;
 }
 
-static void pcf857x_set(struct gpio_chip *chip, unsigned offset, int value)
+static void pcf857x_set(struct gpio_chip *chip, unsigned int offset, int value)
 {
 	pcf857x_output(chip, offset, value);
 }
Signature · 1 line
2.39.0
#2 lore raw

PATCH v2 2/3 gpio: pcf857x: Fix indentation of variable declarations

In reply to Radu Rendec

No functional changes. This is a whitespace change only.

---
 drivers/gpio/gpio-pcf857x.c | 30 +++++++++++++++---------------
 1 file changed, 15 insertions(+), 15 deletions(-)
drivers/gpio/gpio-pcf857x.c +15 -15
index 14656d4f3a3d..1026973bc998 100644
@@ -121,8 +121,8 @@ static int i2c_read_le16(struct i2c_client *client)
 
 static int pcf857x_input(struct gpio_chip *chip, unsigned int offset)
 {
-	struct pcf857x	*gpio = gpiochip_get_data(chip);
-	int		status;
+	struct pcf857x *gpio = gpiochip_get_data(chip);
+	int status;
 
 	mutex_lock(&gpio->lock);
 	gpio->out |= (1 << offset);
@@ -134,8 +134,8 @@ static int pcf857x_input(struct gpio_chip *chip, unsigned int offset)
 
 static int pcf857x_get(struct gpio_chip *chip, unsigned int offset)
 {
-	struct pcf857x	*gpio = gpiochip_get_data(chip);
-	int		value;
+	struct pcf857x *gpio = gpiochip_get_data(chip);
+	int value;
 
 	value = gpio->read(gpio->client);
 	return (value < 0) ? value : !!(value & (1 << offset));
@@ -143,9 +143,9 @@ static int pcf857x_get(struct gpio_chip *chip, unsigned int offset)
 
 static int pcf857x_output(struct gpio_chip *chip, unsigned int offset, int value)
 {
-	struct pcf857x	*gpio = gpiochip_get_data(chip);
-	unsigned int	bit = 1 << offset;
-	int		status;
+	struct pcf857x *gpio = gpiochip_get_data(chip);
+	unsigned int bit = 1 << offset;
+	int status;
 
 	mutex_lock(&gpio->lock);
 	if (value)
@@ -167,7 +167,7 @@ static void pcf857x_set(struct gpio_chip *chip, unsigned int offset, int value)
 
 static irqreturn_t pcf857x_irq(int irq, void *data)
 {
-	struct pcf857x  *gpio = data;
+	struct pcf857x *gpio = data;
 	unsigned long change, i, status;
 
 	status = gpio->read(gpio->client);
@@ -250,11 +250,11 @@ static const struct irq_chip pcf857x_irq_chip = {
 static int pcf857x_probe(struct i2c_client *client)
 {
 	const struct i2c_device_id *id = i2c_client_get_device_id(client);
-	struct pcf857x_platform_data	*pdata = dev_get_platdata(&client->dev);
-	struct device_node		*np = client->dev.of_node;
-	struct pcf857x			*gpio;
-	unsigned int			n_latch = 0;
-	int				status;
+	struct pcf857x_platform_data *pdata = dev_get_platdata(&client->dev);
+	struct device_node *np = client->dev.of_node;
+	struct pcf857x *gpio;
+	unsigned int n_latch = 0;
+	int status;
 
 	if (IS_ENABLED(CONFIG_OF) && np)
 		of_property_read_u32(np, "lines-initial-states", &n_latch);
@@ -401,8 +401,8 @@ static int pcf857x_probe(struct i2c_client *client)
 
 static void pcf857x_remove(struct i2c_client *client)
 {
-	struct pcf857x_platform_data	*pdata = dev_get_platdata(&client->dev);
-	struct pcf857x			*gpio = i2c_get_clientdata(client);
+	struct pcf857x_platform_data *pdata = dev_get_platdata(&client->dev);
+	struct pcf857x *gpio = i2c_get_clientdata(client);
 
 	if (pdata && pdata->teardown)
 		pdata->teardown(client, gpio->chip.base, gpio->chip.ngpio,
Signature · 1 line
2.39.0
#3 lore raw

PATCH v2 3/3 gpio: pcf857x: Implement get_multiple/set_multiple methods

In reply to Radu Rendec

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.

---
 drivers/gpio/gpio-pcf857x.c | 29 +++++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)
drivers/gpio/gpio-pcf857x.c +29 -0
index 1026973bc998..d9db878802b7 100644
@@ -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;
Signature · 1 line
2.39.0
#4 lore raw
In reply to Radu Rendec
Quoted 18 lines · Radu Rendec

The first two patches are just cosmetic changes. The actual changes are in the third patch. They are all bundled together in a patch series just because the third patch doesn't apply cleanly without the other two.

Change description from the third patch:

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.

Radu Rendec (3):
gpio: pcf857x: Replace 'unsigned' with 'unsigned int'
gpio: pcf857x: Fix indentation of variable declarations
gpio: pcf857x: Implement get_multiple/set_multiple methods

Quoted 6 lines
 drivers/gpio/gpio-pcf857x.c | 79 +++++++++++++++++++++++++------------
 1 file changed, 54 insertions(+), 25 deletions(-)

--
2.39.0

Applied, thanks!

Bart