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 |
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
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 --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;