Skip to content

Commit 5132b3d

Browse files
Linus Walleijbroonie
authored andcommitted
spi: gpio: Support 3WIRE high-impedance turn-around
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> Signed-off-by: Mark Brown <broonie@kernel.org>
1 parent 6510223 commit 5132b3d

File tree

2 files changed

+22
-3
lines changed

2 files changed

+22
-3
lines changed

drivers/spi/spi-gpio.c

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -256,11 +256,29 @@ static int spi_gpio_setup(struct spi_device *spi)
256256
static int spi_gpio_set_direction(struct spi_device *spi, bool output)
257257
{
258258
struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi);
259+
int ret;
259260

260261
if (output)
261262
return gpiod_direction_output(spi_gpio->mosi, 1);
262-
else
263-
return gpiod_direction_input(spi_gpio->mosi);
263+
264+
ret = gpiod_direction_input(spi_gpio->mosi);
265+
if (ret)
266+
return ret;
267+
/*
268+
* Send a turnaround high impedance cycle when switching
269+
* from output to input. Theoretically there should be
270+
* a clock delay here, but as has been noted above, the
271+
* nsec delay function for bit-banged GPIO is simply
272+
* {} because bit-banging just doesn't get fast enough
273+
* anyway.
274+
*/
275+
if (spi->mode & SPI_3WIRE_HIZ) {
276+
gpiod_set_value_cansleep(spi_gpio->sck,
277+
!(spi->mode & SPI_CPOL));
278+
gpiod_set_value_cansleep(spi_gpio->sck,
279+
!!(spi->mode & SPI_CPOL));
280+
}
281+
return 0;
264282
}
265283

266284
static void spi_gpio_cleanup(struct spi_device *spi)
@@ -410,7 +428,7 @@ static int spi_gpio_probe(struct platform_device *pdev)
410428
return status;
411429

412430
master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32);
413-
master->mode_bits = SPI_3WIRE | SPI_CPHA | SPI_CPOL;
431+
master->mode_bits = SPI_3WIRE | SPI_3WIRE_HIZ | SPI_CPHA | SPI_CPOL;
414432
master->flags = master_flags;
415433
master->bus_num = pdev->id;
416434
/* The master needs to think there is a chipselect even if not connected */

include/linux/spi/spi.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ struct spi_device {
155155
#define SPI_RX_DUAL 0x400 /* receive with 2 wires */
156156
#define SPI_RX_QUAD 0x800 /* receive with 4 wires */
157157
#define SPI_CS_WORD 0x1000 /* toggle cs after each word */
158+
#define SPI_3WIRE_HIZ 0x2000 /* high impedance turnaround */
158159
int irq;
159160
void *controller_state;
160161
void *controller_data;

0 commit comments

Comments
 (0)