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@example.com> Signed-off-by: Lukas Wunner <firstname.lastname@example.org> Cc: email@example.com # v4.2+ Cc: Martin Sperl <firstname.lastname@example.org> Acked-by: Stefan Wahren <email@example.com> Link: https://firstname.lastname@example.org Signed-off-by: Mark Brown <email@example.com> Signed-off-by: Greg Kroah-Hartman <firstname.lastname@example.org>
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;