spi: bcm2835: Fix 3-wire mode if DMA is enabled [Linux 4.4.189]

This Linux kernel change "spi: bcm2835: Fix 3-wire mode if DMA is enabled" is included in the Linux 4.4.189 release. This change is authored by Lukas Wunner <lukas [at] wunner.de> on Wed Jul 3 12:29:31 2019 +0200. The commit for this change in Linux stable tree is 68522ac (patch) which is from upstream commit 8d8bef5. The same Linux upstream change may have been applied to various maintained Linux releases and you can find all Linux releases containing changes from upstream 8d8bef5.

spi: bcm2835: Fix 3-wire mode if DMA is enabled

commit 8d8bef50365847134b51c1ec46786bc2873e4e47 upstream.

Commit 6935224da248 ("spi: bcm2835: enable support of 3-wire mode")
added 3-wire support to the BCM2835 SPI driver by setting the REN bit
(Read Enable) in the CS register when receiving data.  The REN bit puts
the transmitter in high-impedance state.  The driver recognizes that
data is to be received by checking whether the rx_buf of a transfer is
non-NULL.

Commit 3ecd37edaa2a ("spi: bcm2835: enable dma modes for transfers
meeting certain conditions") subsequently broke 3-wire support because
it set the SPI_MASTER_MUST_RX flag which causes spi_map_msg() to replace
rx_buf with a dummy buffer if it is NULL.  As a result, rx_buf is
*always* non-NULL if DMA is enabled.

Reinstate 3-wire support by not only checking whether rx_buf is non-NULL,
but also checking that it is not the dummy buffer.

Fixes: 3ecd37edaa2a ("spi: bcm2835: enable dma modes for transfers meeting certain conditions")
Reported-by: Nuno Sá <[email protected]>
Signed-off-by: Lukas Wunner <[email protected]>
Cc: [email protected] # v4.2+
Cc: Martin Sperl <[email protected]>
Acked-by: Stefan Wahren <[email protected]>
Link: https://lore.kernel.org/r/[email protected]nner.de
Signed-off-by: Mark Brown <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

There are 3 lines of Linux source code added/deleted in this change. Code changes to Linux kernel are as follows.

 drivers/spi/spi-bcm2835.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c
index 1a1368f..25daebd 100644
--- a/drivers/spi/spi-bcm2835.c
+++ b/drivers/spi/spi-bcm2835.c
@@ -554,7 +554,8 @@ static int bcm2835_spi_transfer_one(struct spi_master *master,
    bcm2835_wr(bs, BCM2835_SPI_CLK, cdiv);

    /* handle all the 3-wire mode */
-   if ((spi->mode & SPI_3WIRE) && (tfr->rx_buf))
+   if (spi->mode & SPI_3WIRE && tfr->rx_buf &&
+       tfr->rx_buf != master->dummy_rx)
        cs |= BCM2835_SPI_CS_REN;
    else
        cs &= ~BCM2835_SPI_CS_REN;

Leave a Reply

Your email address will not be published. Required fields are marked *