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>
This commit is contained in:
parent
651022382c
commit
5132b3d283
|
@ -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)
|
static int spi_gpio_set_direction(struct spi_device *spi, bool output)
|
||||||
{
|
{
|
||||||
struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi);
|
struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi);
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (output)
|
if (output)
|
||||||
return gpiod_direction_output(spi_gpio->mosi, 1);
|
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)
|
static void spi_gpio_cleanup(struct spi_device *spi)
|
||||||
|
@ -410,7 +428,7 @@ static int spi_gpio_probe(struct platform_device *pdev)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32);
|
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->flags = master_flags;
|
||||||
master->bus_num = pdev->id;
|
master->bus_num = pdev->id;
|
||||||
/* The master needs to think there is a chipselect even if not connected */
|
/* The master needs to think there is a chipselect even if not connected */
|
||||||
|
|
|
@ -155,6 +155,7 @@ struct spi_device {
|
||||||
#define SPI_RX_DUAL 0x400 /* receive with 2 wires */
|
#define SPI_RX_DUAL 0x400 /* receive with 2 wires */
|
||||||
#define SPI_RX_QUAD 0x800 /* receive with 4 wires */
|
#define SPI_RX_QUAD 0x800 /* receive with 4 wires */
|
||||||
#define SPI_CS_WORD 0x1000 /* toggle cs after each word */
|
#define SPI_CS_WORD 0x1000 /* toggle cs after each word */
|
||||||
|
#define SPI_3WIRE_HIZ 0x2000 /* high impedance turnaround */
|
||||||
int irq;
|
int irq;
|
||||||
void *controller_state;
|
void *controller_state;
|
||||||
void *controller_data;
|
void *controller_data;
|
||||||
|
|
Loading…
Reference in New Issue