diff options
author | Mark Brown <broonie@kernel.org> | 2018-12-04 17:31:49 +0000 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2018-12-04 17:31:49 +0000 |
commit | ae218f7847fcf32e75ba82b1f3ab01fe53731d7a (patch) | |
tree | aeb782a46c38b1fa561aef92c65125bf29cbafa6 /drivers/spi | |
parent | 32215a6c6beb8dcda4bb0759b04ce3c30927963b (diff) | |
parent | 5132b3d283710d196cd8af99b5585507e8b30709 (diff) |
Merge branch 'topic/3wire-gpio' of https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi into spi-4.21 mode conflict
Diffstat (limited to 'drivers/spi')
-rw-r--r-- | drivers/spi/spi-gpio.c | 24 |
1 files changed, 21 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 */ |