diff mbox

[34/49] spi: davinci: always start receive DMA

Message ID 1289990661-30126-35-git-send-email-nsekhar@ti.com (mailing list archive)
State Awaiting Upstream
Headers show

Commit Message

Sekhar Nori Nov. 17, 2010, 10:44 a.m. UTC
None
diff mbox

Patch

diff --git a/drivers/spi/davinci_spi.c b/drivers/spi/davinci_spi.c
index f512939..705d006 100644
--- a/drivers/spi/davinci_spi.c
+++ b/drivers/spi/davinci_spi.c
@@ -138,6 +138,8 @@  struct davinci_spi {
 
 	const void		*tx;
 	void			*rx;
+#define SPI_TMP_BUFSZ	(SMP_CACHE_BYTES + 1)
+	u8			rx_tmp_buf[SPI_TMP_BUFSZ];
 	int			rcount;
 	int			wcount;
 	struct davinci_spi_dma	dma_channels;
@@ -716,10 +718,12 @@  static int davinci_spi_bufs_dma(struct spi_device *spi, struct spi_transfer *t)
 	struct davinci_spi *davinci_spi;
 	int int_status = 0;
 	int count;
+	unsigned rx_buf_count;
 	struct davinci_spi_dma *davinci_spi_dma;
 	int data_type, ret;
 	unsigned long tx_reg, rx_reg;
 	struct davinci_spi_platform_data *pdata;
+	void *rx_buf;
 	struct device *sdev;
 
 	davinci_spi = spi_master_get_devdata(spi->master);
@@ -778,50 +782,60 @@  static int davinci_spi_bufs_dma(struct spi_device *spi, struct spi_transfer *t)
 			t->tx_buf ? data_type : 0, 0);
 	edma_set_dest_index(davinci_spi_dma->dma_tx_channel, 0, 0);
 
+	/*
+	 * Receive DMA setup
+	 *
+	 * If there is receive buffer, use it to receive data. If there
+	 * is none provided, use a temporary receive buffer. Set the
+	 * destination B index to 0 so effectively only one byte is used
+	 * in the temporary buffer (address does not increment).
+	 *
+	 * The source of receive data is the receive data register. The
+	 * source address never increments.
+	 */
+
 	if (t->rx_buf) {
-		t->rx_dma = dma_map_single(&spi->dev, (void *)t->rx_buf, count,
-				DMA_FROM_DEVICE);
-		if (dma_mapping_error(&spi->dev, t->rx_dma)) {
-			dev_dbg(sdev, "Couldn't DMA map a %d bytes RX buffer\n",
-					count);
-			if (t->tx_buf != NULL)
-				dma_unmap_single(NULL, t->tx_dma,
-						 count, DMA_TO_DEVICE);
-			return -ENOMEM;
-		}
-		edma_set_transfer_params(davinci_spi_dma->dma_rx_channel,
-				data_type, count, 1, 0, ASYNC);
-		edma_set_src(davinci_spi_dma->dma_rx_channel,
-				rx_reg, INCR, W8BIT);
-		edma_set_dest(davinci_spi_dma->dma_rx_channel,
-				t->rx_dma, INCR, W8BIT);
-		edma_set_src_index(davinci_spi_dma->dma_rx_channel, 0, 0);
-		edma_set_dest_index(davinci_spi_dma->dma_rx_channel,
-				data_type, 0);
+		rx_buf = t->rx_buf;
+		rx_buf_count = count;
+	} else {
+		rx_buf = davinci_spi->rx_tmp_buf;
+		rx_buf_count = sizeof(davinci_spi->rx_tmp_buf);
+	}
+
+	t->rx_dma = dma_map_single(&spi->dev, rx_buf, rx_buf_count,
+							DMA_FROM_DEVICE);
+	if (dma_mapping_error(&spi->dev, t->rx_dma)) {
+		dev_dbg(sdev, "Couldn't DMA map a %d bytes RX buffer\n",
+								rx_buf_count);
+		if (t->tx_buf)
+			dma_unmap_single(NULL, t->tx_dma, count, DMA_TO_DEVICE);
+		return -ENOMEM;
 	}
 
+	edma_set_transfer_params(davinci_spi_dma->dma_rx_channel, data_type,
+							count, 1, 0, ASYNC);
+	edma_set_src(davinci_spi_dma->dma_rx_channel, rx_reg, INCR, W8BIT);
+	edma_set_dest(davinci_spi_dma->dma_rx_channel, t->rx_dma, INCR, W8BIT);
+	edma_set_src_index(davinci_spi_dma->dma_rx_channel, 0, 0);
+	edma_set_dest_index(davinci_spi_dma->dma_rx_channel,
+						t->rx_buf ? data_type : 0, 0);
+
 	if (pdata->cshold_bug) {
 		u16 spidat1 = ioread16(davinci_spi->base + SPIDAT1 + 2);
 		iowrite16(spidat1, davinci_spi->base + SPIDAT1 + 2);
 	}
 
-	if (t->rx_buf)
-		edma_start(davinci_spi_dma->dma_rx_channel);
-
+	edma_start(davinci_spi_dma->dma_rx_channel);
 	edma_start(davinci_spi_dma->dma_tx_channel);
 	davinci_spi_set_dma_req(spi, 1);
 
 	wait_for_completion_interruptible(&davinci_spi_dma->dma_tx_completion);
-
-	if (t->rx_buf)
-		wait_for_completion_interruptible(
-				&davinci_spi_dma->dma_rx_completion);
+	wait_for_completion_interruptible(&davinci_spi_dma->dma_rx_completion);
 
 	if (t->tx_buf)
 		dma_unmap_single(NULL, t->tx_dma, count, DMA_TO_DEVICE);
 
-	if (t->rx_buf)
-		dma_unmap_single(NULL, t->rx_dma, count, DMA_FROM_DEVICE);
+	dma_unmap_single(NULL, t->rx_dma, rx_buf_count, DMA_FROM_DEVICE);
 
 	/*
 	 * Check for bit error, desync error,parity error,timeout error and