[PATCH 2/4] spi: gpio: Fix reading for 3WIRE

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



If he GPIO bitbanged host is registered using just one line,
MISO, naturally the DT parser will flag the host as
SPI_MASTER_NO_RX.

This makes the GPIO SPI driver assign word transfer functions
that enforce the SPI master flags SPI_MASTER_NO_RX (or
SPI_MASTER_NO_TX) to the flags on each call down to the
inlined bitbang functions such as bitbang_txrx_be_cpha0().

In the 3WIRE case, enforcing this flag is wrong, because the
master can then do both TX and RX (albeit not at the same time)
using the same line, by just switching the direction of the
line and keep clocking in bits.

Augment spi_gpio_spec_txrx_word_mode[0123] to account for
this.

Cc: Andrzej Hajda <a.hajda@xxxxxxxxxxx>
Cc: Lorenzo Bianconi <lorenzo.bianconi@xxxxxxxxxx>
Signed-off-by: Linus Walleij <linus.walleij@xxxxxxxxxx>
---
 drivers/spi/spi-gpio.c | 17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/drivers/spi/spi-gpio.c b/drivers/spi/spi-gpio.c
index 9f4882f82c3c..6bd692304b92 100644
--- a/drivers/spi/spi-gpio.c
+++ b/drivers/spi/spi-gpio.c
@@ -183,33 +183,42 @@ static u32 spi_gpio_txrx_word_mode3(struct spi_device *spi,
  * speed in the generic case (when both MISO and MOSI lines are
  * available), as optimiser will remove the checks when argument is
  * constant.
+ *
+ * A special kludge is needed for 3WIRE SPI, as this mode can use
+ * the same line for RX and TX and should not enforce the host
+ * flag - we will just switch MISO from output to input mode when
+ * needed.
  */
 
 static u32 spi_gpio_spec_txrx_word_mode0(struct spi_device *spi,
 		unsigned nsecs, u32 word, u8 bits, unsigned flags)
 {
-	flags = spi->master->flags;
+	if (!(spi->mode & SPI_3WIRE))
+		flags = spi->master->flags;
 	return bitbang_txrx_be_cpha0(spi, nsecs, 0, flags, word, bits);
 }
 
 static u32 spi_gpio_spec_txrx_word_mode1(struct spi_device *spi,
 		unsigned nsecs, u32 word, u8 bits, unsigned flags)
 {
-	flags = spi->master->flags;
+	if (!(spi->mode & SPI_3WIRE))
+		flags = spi->master->flags;
 	return bitbang_txrx_be_cpha1(spi, nsecs, 0, flags, word, bits);
 }
 
 static u32 spi_gpio_spec_txrx_word_mode2(struct spi_device *spi,
 		unsigned nsecs, u32 word, u8 bits, unsigned flags)
 {
-	flags = spi->master->flags;
+	if (!(spi->mode & SPI_3WIRE))
+		flags = spi->master->flags;
 	return bitbang_txrx_be_cpha0(spi, nsecs, 1, flags, word, bits);
 }
 
 static u32 spi_gpio_spec_txrx_word_mode3(struct spi_device *spi,
 		unsigned nsecs, u32 word, u8 bits, unsigned flags)
 {
-	flags = spi->master->flags;
+	if (!(spi->mode & SPI_3WIRE))
+		flags = spi->master->flags;
 	return bitbang_txrx_be_cpha1(spi, nsecs, 1, flags, word, bits);
 }
 
-- 
2.17.1




[Index of Archives]     [Linux SPI]     [Linux Kernel]     [Linux ARM (vger)]     [Linux ARM MSM]     [Linux Omap]     [Linux Arm]     [Linux Tegra]     [Fedora ARM]     [Linux for Samsung SOC]     [eCos]     [Linux Fastboot]     [Gcc Help]     [Git]     [DCCP]     [IETF Announce]     [Security]     [Linux MIPS]     [Yosemite Campsites]

  Powered by Linux