diff mbox

[v3,3/6] spi: davinci: use rx buffer as dummy tx buffer

Message ID 1487872921-26628-4-git-send-email-fisaksen@baylibre.com (mailing list archive)
State New, archived
Headers show

Commit Message

Frode Isaksen Feb. 23, 2017, 6:01 p.m. UTC
When doing rx-only transfer, the transfer will fail
if the number of SG entries exceeds 20.
This happens because the eDMA DMA engine is limited
to 20 SG entries in one transaction, and when the
DMA transcation is resumed (which takes > 150us),
rx errors occurs because the slave is still transmitting.
Fix this by using the rx buffer as the dummy tx buffer,
so that resuming the rx transcation happens at the same
time as resuming the tx transcation.

Signed-off-by: Frode Isaksen <fisaksen@baylibre.com>
---
 drivers/spi/spi-davinci.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

Comments

Mark Brown March 15, 2017, 7:35 p.m. UTC | #1
On Thu, Feb 23, 2017 at 07:01:58PM +0100, Frode Isaksen wrote:
> When doing rx-only transfer, the transfer will fail
> if the number of SG entries exceeds 20.
> This happens because the eDMA DMA engine is limited
> to 20 SG entries in one transaction, and when the
> DMA transcation is resumed (which takes > 150us),
> rx errors occurs because the slave is still transmitting.
> Fix this by using the rx buffer as the dummy tx buffer,
> so that resuming the rx transcation happens at the same
> time as resuming the tx transcation.

Please submit a followup patch adding a comment explaing what's going
in the actual code as someone's going to clean this up at some point.
diff mbox

Patch

diff --git a/drivers/spi/spi-davinci.c b/drivers/spi/spi-davinci.c
index 1e24395..ca12216 100644
--- a/drivers/spi/spi-davinci.c
+++ b/drivers/spi/spi-davinci.c
@@ -655,6 +655,12 @@  static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t)
 		if (!rxdesc)
 			goto err_desc;
 
+		if (!t->tx_buf) {
+			/* use rx buffer as dummy tx buffer */
+			t->tx_sg.sgl = t->rx_sg.sgl;
+			t->tx_sg.nents = t->rx_sg.nents;
+		}
+
 		txdesc = dmaengine_prep_slave_sg(dspi->dma_tx,
 				t->tx_sg.sgl, t->tx_sg.nents, DMA_MEM_TO_DEV,
 				DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
@@ -957,7 +963,7 @@  static int davinci_spi_probe(struct platform_device *pdev)
 	master->bus_num = pdev->id;
 	master->num_chipselect = pdata->num_chipselect;
 	master->bits_per_word_mask = SPI_BPW_RANGE_MASK(2, 16);
-	master->flags = (SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX);
+	master->flags = SPI_MASTER_MUST_RX;
 	master->setup = davinci_spi_setup;
 	master->cleanup = davinci_spi_cleanup;
 	master->can_dma = davinci_spi_can_dma;