diff mbox series

[v3] spi: gpio: Support 3WIRE high-impedance turn-around

Message ID 20181101212504.11723-1-linus.walleij@linaro.org
State Accepted
Commit 5132b3d283710d196cd8af99b5585507e8b30709
Headers show
Series [v3] spi: gpio: Support 3WIRE high-impedance turn-around | expand

Commit Message

Linus Walleij Nov. 1, 2018, 9:25 p.m. UTC
Some devices such as the TPO TPG110 display panel require
a "high-impedance turn-around", in effect a clock cycle after
switching the line from output to input mode.

Support this in the GPIO driver to begin with. Other driver
may implement it if they can, it is unclear if this can
be achieved with anything else than GPIO bit-banging.

Cc: Andrzej Hajda <a.hajda@samsung.com>
Acked-by: Lorenzo Bianconi <lorenzo.bianconi@redhat.com>

Signed-off-by: Linus Walleij <linus.walleij@linaro.org>

---
ChangeLog v2->v3:
- Drop the device tree parsing (and the device tree bindings)
  for high-impedance turn-around. This is a client property,
  so let the drivers using it simply set the flag.
ChangeLog v1->v2:
- Change some spelling to use dashes, high-impedance
  turn-around.
- Collect Lorenzo's ACK.
---
 drivers/spi/spi-gpio.c  | 24 +++++++++++++++++++++---
 include/linux/spi/spi.h |  1 +
 2 files changed, 22 insertions(+), 3 deletions(-)

-- 
2.19.1

Comments

Linus Walleij Nov. 1, 2018, 9:31 p.m. UTC | #1
On Thu, Nov 1, 2018 at 10:25 PM Linus Walleij <linus.walleij@linaro.org> wrote:

> Some devices such as the TPO TPG110 display panel require

> a "high-impedance turn-around", in effect a clock cycle after

> switching the line from output to input mode.

>

> Support this in the GPIO driver to begin with. Other driver

> may implement it if they can, it is unclear if this can

> be achieved with anything else than GPIO bit-banging.

>

> Cc: Andrzej Hajda <a.hajda@samsung.com>

> Acked-by: Lorenzo Bianconi <lorenzo.bianconi@redhat.com>

> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>

> ---

> ChangeLog v2->v3:

> - Drop the device tree parsing (and the device tree bindings)

>   for high-impedance turn-around. This is a client property,

>   so let the drivers using it simply set the flag.


PS Mark: if this is OK now, then I guess it'd be best if I could
get an ACK and apply it to the DRM tree where the panel
driver using the flag will end up, as that will now get a compile-time
dependence on this patch as it sets the flag in the driver
code.

I guess we could also make an immutable branch in the SPI
tree if you think you might e.g. have more new slave flags this
kernel cycle. I have no idea to pull that into drm-misc but I
guess I'd just ask dvetter if I have to.

Yours,
Linus Walleij
Mark Brown Nov. 7, 2018, 4:21 p.m. UTC | #2
On Thu, Nov 01, 2018 at 10:25:04PM +0100, Linus Walleij wrote:
> Some devices such as the TPO TPG110 display panel require

> a "high-impedance turn-around", in effect a clock cycle after

> switching the line from output to input mode.


The following changes since commit 651022382c7f8da46cb4872a545ee1da6d097d2a:

  Linux 4.20-rc1 (2018-11-04 15:37:52 -0800)

are available in the Git repository at:

  https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git tags/spi-3wire

for you to fetch changes up to 5132b3d283710d196cd8af99b5585507e8b30709:

  spi: gpio: Support 3WIRE high-impedance turn-around (2018-11-07 16:15:49 +0000)

----------------------------------------------------------------
spi: Support 3WIRE high-impedance turn-around with GPIO controller

Add support for another fun variation of the SPI protocol.

----------------------------------------------------------------
Linus Walleij (1):
      spi: gpio: Support 3WIRE high-impedance turn-around

 drivers/spi/spi-gpio.c  | 24 +++++++++++++++++++++---
 include/linux/spi/spi.h |  1 +
 2 files changed, 22 insertions(+), 3 deletions(-)
diff mbox series

Patch

diff --git a/drivers/spi/spi-gpio.c b/drivers/spi/spi-gpio.c
index 45973ee3ae11..a4aee26028cd 100644
--- a/drivers/spi/spi-gpio.c
+++ b/drivers/spi/spi-gpio.c
@@ -256,11 +256,29 @@  static int spi_gpio_setup(struct spi_device *spi)
 static int spi_gpio_set_direction(struct spi_device *spi, bool output)
 {
 	struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi);
+	int ret;
 
 	if (output)
 		return gpiod_direction_output(spi_gpio->mosi, 1);
-	else
-		return gpiod_direction_input(spi_gpio->mosi);
+
+	ret = gpiod_direction_input(spi_gpio->mosi);
+	if (ret)
+		return ret;
+	/*
+	 * Send a turnaround high impedance cycle when switching
+	 * from output to input. Theoretically there should be
+	 * a clock delay here, but as has been noted above, the
+	 * nsec delay function for bit-banged GPIO is simply
+	 * {} because bit-banging just doesn't get fast enough
+	 * anyway.
+	 */
+	if (spi->mode & SPI_3WIRE_HIZ) {
+		gpiod_set_value_cansleep(spi_gpio->sck,
+					 !(spi->mode & SPI_CPOL));
+		gpiod_set_value_cansleep(spi_gpio->sck,
+					 !!(spi->mode & SPI_CPOL));
+	}
+	return 0;
 }
 
 static void spi_gpio_cleanup(struct spi_device *spi)
@@ -410,7 +428,7 @@  static int spi_gpio_probe(struct platform_device *pdev)
 		return status;
 
 	master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32);
-	master->mode_bits = SPI_3WIRE | SPI_CPHA | SPI_CPOL;
+	master->mode_bits = SPI_3WIRE | SPI_3WIRE_HIZ | SPI_CPHA | SPI_CPOL;
 	master->flags = master_flags;
 	master->bus_num = pdev->id;
 	/* The master needs to think there is a chipselect even if not connected */
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
index 6be77fa5ab90..3ced58eebe1b 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -155,6 +155,7 @@  struct spi_device {
 #define	SPI_RX_DUAL	0x400			/* receive with 2 wires */
 #define	SPI_RX_QUAD	0x800			/* receive with 4 wires */
 #define SPI_CS_WORD	0x1000			/* toggle cs after each word */
+#define	SPI_3WIRE_HIZ	0x2000			/* high impedance turnaround */
 	int			irq;
 	void			*controller_state;
 	void			*controller_data;