All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/2] gpio: 74x164: Misc improvements
@ 2015-11-30 14:35 Geert Uytterhoeven
  2015-11-30 14:35 ` [PATCH 1/2] gpio: 74x164: Allocate buffer with gen_74x164_chip Geert Uytterhoeven
  2015-11-30 14:35 ` [PATCH 2/2] gpio: 74x164: Use a single SPI transfer instead of multiple transfers Geert Uytterhoeven
  0 siblings, 2 replies; 5+ messages in thread
From: Geert Uytterhoeven @ 2015-11-30 14:35 UTC (permalink / raw)
  To: Linus Walleij, Alexandre Courbot, Maxime Ripard
  Cc: linux-gpio, Geert Uytterhoeven

	Hi Linus, Alex,

This patch series contains two improvements to the 74x164 GPIO driver.
It was tested with 2 daisy-chained 74HC595 shift registers, connected to
a Renesas MSIOF SPI master, which cannot keep its hardware chip select
asserted in between multiple transfers without using cs-gpios.

Thanks!

Geert Uytterhoeven (2):
  gpio: 74x164: Allocate buffer with gen_74x164_chip
  gpio: 74x164: Use a single SPI transfer instead of multiple transfers

 drivers/gpio/gpio-74x164.c | 69 +++++++++++++++++-----------------------------
 1 file changed, 25 insertions(+), 44 deletions(-)

-- 
1.9.1

Gr{oetje,eeting}s,

						Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
							    -- Linus Torvalds

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 1/2] gpio: 74x164: Allocate buffer with gen_74x164_chip
  2015-11-30 14:35 [PATCH 0/2] gpio: 74x164: Misc improvements Geert Uytterhoeven
@ 2015-11-30 14:35 ` Geert Uytterhoeven
  2015-12-10 16:14   ` Linus Walleij
  2015-11-30 14:35 ` [PATCH 2/2] gpio: 74x164: Use a single SPI transfer instead of multiple transfers Geert Uytterhoeven
  1 sibling, 1 reply; 5+ messages in thread
From: Geert Uytterhoeven @ 2015-11-30 14:35 UTC (permalink / raw)
  To: Linus Walleij, Alexandre Courbot, Maxime Ripard
  Cc: linux-gpio, Geert Uytterhoeven

By moving the internal buffer to the end of struct gen_74x164_chip and
converting it from a pointer to a zero-sized array, it can be allocated
together with gen_74x164_chip, reducing the number of managed
allocations.

Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
 drivers/gpio/gpio-74x164.c | 23 +++++++++++------------
 1 file changed, 11 insertions(+), 12 deletions(-)

diff --git a/drivers/gpio/gpio-74x164.c b/drivers/gpio/gpio-74x164.c
index 60172f835d15f139..6664b26523084e12 100644
--- a/drivers/gpio/gpio-74x164.c
+++ b/drivers/gpio/gpio-74x164.c
@@ -20,10 +20,10 @@
 #define GEN_74X164_NUMBER_GPIOS	8
 
 struct gen_74x164_chip {
-	u8			*buffer;
 	struct gpio_chip	gpio_chip;
 	struct mutex		lock;
 	u32			registers;
+	u8			buffer[0];
 };
 
 static struct gen_74x164_chip *gpio_to_74x164_chip(struct gpio_chip *gc)
@@ -107,6 +107,7 @@ static int gen_74x164_direction_output(struct gpio_chip *gc,
 static int gen_74x164_probe(struct spi_device *spi)
 {
 	struct gen_74x164_chip *chip;
+	u32 nregs;
 	int ret;
 
 	/*
@@ -118,7 +119,14 @@ static int gen_74x164_probe(struct spi_device *spi)
 	if (ret < 0)
 		return ret;
 
-	chip = devm_kzalloc(&spi->dev, sizeof(*chip), GFP_KERNEL);
+	if (of_property_read_u32(spi->dev.of_node, "registers-number",
+				 &nregs)) {
+		dev_err(&spi->dev,
+			"Missing registers-number property in the DT.\n");
+		return -EINVAL;
+	}
+
+	chip = devm_kzalloc(&spi->dev, sizeof(*chip) + nregs, GFP_KERNEL);
 	if (!chip)
 		return -ENOMEM;
 
@@ -130,17 +138,8 @@ static int gen_74x164_probe(struct spi_device *spi)
 	chip->gpio_chip.set = gen_74x164_set_value;
 	chip->gpio_chip.base = -1;
 
-	if (of_property_read_u32(spi->dev.of_node, "registers-number",
-				 &chip->registers)) {
-		dev_err(&spi->dev,
-			"Missing registers-number property in the DT.\n");
-		return -EINVAL;
-	}
-
+	chip->registers = nregs;
 	chip->gpio_chip.ngpio = GEN_74X164_NUMBER_GPIOS * chip->registers;
-	chip->buffer = devm_kzalloc(&spi->dev, chip->registers, GFP_KERNEL);
-	if (!chip->buffer)
-		return -ENOMEM;
 
 	chip->gpio_chip.can_sleep = true;
 	chip->gpio_chip.dev = &spi->dev;
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 2/2] gpio: 74x164: Use a single SPI transfer instead of multiple transfers
  2015-11-30 14:35 [PATCH 0/2] gpio: 74x164: Misc improvements Geert Uytterhoeven
  2015-11-30 14:35 ` [PATCH 1/2] gpio: 74x164: Allocate buffer with gen_74x164_chip Geert Uytterhoeven
@ 2015-11-30 14:35 ` Geert Uytterhoeven
  2015-12-10 16:20   ` Linus Walleij
  1 sibling, 1 reply; 5+ messages in thread
From: Geert Uytterhoeven @ 2015-11-30 14:35 UTC (permalink / raw)
  To: Linus Walleij, Alexandre Courbot, Maxime Ripard
  Cc: linux-gpio, Geert Uytterhoeven, Mark Brown

Currently the 74x164 driver assembles an SPI message from an array of
one-byte SPI transfers, one for each daisy-chained shift register, as
the first byte sent will end up in the last register.
This array is allocated and deallocated on each GPIO write access.

By storing the data in the internal buffer in reverse order, we can
use a single SPI transfer with the internal buffer directly, simplifying
the code a lot, and avoiding memory (de)allocations.

This also avoids transient values on the GPIO outputs when using an SPI
master that cannot keep the hardware chip select asserted in between
multiple transfers (and would need cs-gpios for proper operation).

Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Cc: Mark Brown <broonie@kernel.org>
---
 drivers/gpio/gpio-74x164.c | 46 ++++++++++++++--------------------------------
 1 file changed, 14 insertions(+), 32 deletions(-)

diff --git a/drivers/gpio/gpio-74x164.c b/drivers/gpio/gpio-74x164.c
index 6664b26523084e12..2eca859ce8da9854 100644
--- a/drivers/gpio/gpio-74x164.c
+++ b/drivers/gpio/gpio-74x164.c
@@ -23,6 +23,13 @@ struct gen_74x164_chip {
 	struct gpio_chip	gpio_chip;
 	struct mutex		lock;
 	u32			registers;
+	/*
+	 * Since the registers are chained, every byte sent will make
+	 * the previous byte shift to the next register in the
+	 * chain. Thus, the first byte sent will end up in the last
+	 * register at the end of the transfer. So, to have a logical
+	 * numbering, store the bytes in reverse order.
+	 */
 	u8			buffer[0];
 };
 
@@ -33,43 +40,18 @@ static struct gen_74x164_chip *gpio_to_74x164_chip(struct gpio_chip *gc)
 
 static int __gen_74x164_write_config(struct gen_74x164_chip *chip)
 {
-	struct spi_device *spi = to_spi_device(chip->gpio_chip.dev);
-	struct spi_message message;
-	struct spi_transfer *msg_buf;
-	int i, ret = 0;
-
-	msg_buf = kzalloc(chip->registers * sizeof(struct spi_transfer),
-			GFP_KERNEL);
-	if (!msg_buf)
-		return -ENOMEM;
-
-	spi_message_init(&message);
+	struct spi_transfer xfer = {
+		.tx_buf = chip->buffer,
+		.len = chip->registers,
+	};
 
-	/*
-	 * Since the registers are chained, every byte sent will make
-	 * the previous byte shift to the next register in the
-	 * chain. Thus, the first byte send will end up in the last
-	 * register at the end of the transfer. So, to have a logical
-	 * numbering, send the bytes in reverse order so that the last
-	 * byte of the buffer will end up in the last register.
-	 */
-	for (i = chip->registers - 1; i >= 0; i--) {
-		msg_buf[i].tx_buf = chip->buffer + i;
-		msg_buf[i].len = sizeof(u8);
-		spi_message_add_tail(msg_buf + i, &message);
-	}
-
-	ret = spi_sync(spi, &message);
-
-	kfree(msg_buf);
-
-	return ret;
+	return spi_sync_transfer(to_spi_device(chip->gpio_chip.dev), &xfer, 1);
 }
 
 static int gen_74x164_get_value(struct gpio_chip *gc, unsigned offset)
 {
 	struct gen_74x164_chip *chip = gpio_to_74x164_chip(gc);
-	u8 bank = offset / 8;
+	u8 bank = chip->registers - 1 - offset / 8;
 	u8 pin = offset % 8;
 	int ret;
 
@@ -84,7 +66,7 @@ static void gen_74x164_set_value(struct gpio_chip *gc,
 		unsigned offset, int val)
 {
 	struct gen_74x164_chip *chip = gpio_to_74x164_chip(gc);
-	u8 bank = offset / 8;
+	u8 bank = chip->registers - 1 - offset / 8;
 	u8 pin = offset % 8;
 
 	mutex_lock(&chip->lock);
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH 1/2] gpio: 74x164: Allocate buffer with gen_74x164_chip
  2015-11-30 14:35 ` [PATCH 1/2] gpio: 74x164: Allocate buffer with gen_74x164_chip Geert Uytterhoeven
@ 2015-12-10 16:14   ` Linus Walleij
  0 siblings, 0 replies; 5+ messages in thread
From: Linus Walleij @ 2015-12-10 16:14 UTC (permalink / raw)
  To: Geert Uytterhoeven; +Cc: Alexandre Courbot, Maxime Ripard, linux-gpio

On Mon, Nov 30, 2015 at 3:35 PM, Geert Uytterhoeven
<geert+renesas@glider.be> wrote:

> By moving the internal buffer to the end of struct gen_74x164_chip and
> converting it from a pointer to a zero-sized array, it can be allocated
> together with gen_74x164_chip, reducing the number of managed
> allocations.
>
> Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>

Patch applied.

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH 2/2] gpio: 74x164: Use a single SPI transfer instead of multiple transfers
  2015-11-30 14:35 ` [PATCH 2/2] gpio: 74x164: Use a single SPI transfer instead of multiple transfers Geert Uytterhoeven
@ 2015-12-10 16:20   ` Linus Walleij
  0 siblings, 0 replies; 5+ messages in thread
From: Linus Walleij @ 2015-12-10 16:20 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Alexandre Courbot, Maxime Ripard, linux-gpio, Mark Brown

On Mon, Nov 30, 2015 at 3:35 PM, Geert Uytterhoeven
<geert+renesas@glider.be> wrote:

> Currently the 74x164 driver assembles an SPI message from an array of
> one-byte SPI transfers, one for each daisy-chained shift register, as
> the first byte sent will end up in the last register.
> This array is allocated and deallocated on each GPIO write access.
>
> By storing the data in the internal buffer in reverse order, we can
> use a single SPI transfer with the internal buffer directly, simplifying
> the code a lot, and avoiding memory (de)allocations.
>
> This also avoids transient values on the GPIO outputs when using an SPI
> master that cannot keep the hardware chip select asserted in between
> multiple transfers (and would need cs-gpios for proper operation).
>
> Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
> Cc: Mark Brown <broonie@kernel.org>

Patch rebased and applied. (Accounting for .dev -> .parent refactoring.)

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2015-12-10 16:20 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-11-30 14:35 [PATCH 0/2] gpio: 74x164: Misc improvements Geert Uytterhoeven
2015-11-30 14:35 ` [PATCH 1/2] gpio: 74x164: Allocate buffer with gen_74x164_chip Geert Uytterhoeven
2015-12-10 16:14   ` Linus Walleij
2015-11-30 14:35 ` [PATCH 2/2] gpio: 74x164: Use a single SPI transfer instead of multiple transfers Geert Uytterhoeven
2015-12-10 16:20   ` Linus Walleij

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.