diff mbox

[26/49] spi: davinci: simplify poll mode transfers

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

Commit Message

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

Patch

diff --git a/drivers/spi/davinci_spi.c b/drivers/spi/davinci_spi.c
index 198f062..cd37697 100644
--- a/drivers/spi/davinci_spi.c
+++ b/drivers/spi/davinci_spi.c
@@ -91,6 +91,10 @@ 
 #define SPIFLG_BITERR_MASK		BIT(4)
 #define SPIFLG_OVRRUN_MASK		BIT(6)
 #define SPIFLG_BUF_INIT_ACTIVE_MASK	BIT(24)
+#define SPIFLG_ERROR_MASK		(SPIFLG_DLEN_ERR_MASK \
+				| SPIFLG_TIMEOUT_MASK | SPIFLG_PARERR_MASK \
+				| SPIFLG_DESYNC_MASK | SPIFLG_BITERR_MASK \
+				| SPIFLG_OVRRUN_MASK)
 
 #define SPIINT_DMA_REQ_EN	BIT(16)
 
@@ -601,10 +605,10 @@  static int davinci_spi_check_error(struct davinci_spi *davinci_spi,
 static int davinci_spi_bufs_pio(struct spi_device *spi, struct spi_transfer *t)
 {
 	struct davinci_spi *davinci_spi;
-	int status, count, ret;
-	u8 conv;
+	int ret;
+	int rcount, wcount;
 	u32 tx_data, data1_reg_val;
-	u32 buf_val, flg_val;
+	u32 errors = 0;
 	struct davinci_spi_platform_data *pdata;
 
 	davinci_spi = spi_master_get_devdata(spi->master);
@@ -612,70 +616,51 @@  static int davinci_spi_bufs_pio(struct spi_device *spi, struct spi_transfer *t)
 
 	davinci_spi->tx = t->tx_buf;
 	davinci_spi->rx = t->rx_buf;
-
-	/* convert len to words based on bits_per_word */
-	conv = davinci_spi->bytes_per_word[spi->chip_select];
-	data1_reg_val = ioread32(davinci_spi->base + SPIDAT1);
+	wcount = t->len / davinci_spi->bytes_per_word[spi->chip_select];
+	rcount = wcount;
 
 	ret = davinci_spi_bufs_prep(spi, davinci_spi);
 	if (ret)
 		return ret;
 
+	data1_reg_val = ioread32(davinci_spi->base + SPIDAT1);
+
 	/* Enable SPI */
 	set_io_bits(davinci_spi->base + SPIGCR1, SPIGCR1_SPIENA_MASK);
 
-	count = t->len / conv;
-
 	clear_io_bits(davinci_spi->base + SPIINT, SPIINT_MASKALL);
 
-	/* Determine the command to execute READ or WRITE */
-	if (t->tx_buf) {
+	/* start the transfer */
+	wcount--;
+	tx_data = davinci_spi->get_tx(davinci_spi);
+	data1_reg_val &= 0xFFFF0000;
+	data1_reg_val |= tx_data & 0xFFFF;
+	iowrite32(data1_reg_val, davinci_spi->base + SPIDAT1);
 
-		while (1) {
-			tx_data = davinci_spi->get_tx(davinci_spi);
+	while (rcount > 0 || wcount > 0) {
 
-			data1_reg_val &= ~(0xFFFF);
-			data1_reg_val |= (0xFFFF & tx_data);
-
-			buf_val = ioread32(davinci_spi->base + SPIBUF);
-			if ((buf_val & SPIBUF_TXFULL_MASK) == 0) {
-				iowrite32(data1_reg_val,
-						davinci_spi->base + SPIDAT1);
-
-				count--;
-			}
-			while (ioread32(davinci_spi->base + SPIBUF)
-					& SPIBUF_RXEMPTY_MASK)
-				cpu_relax();
-
-			/* getting the returned byte */
-			if (t->rx_buf) {
-				buf_val = ioread32(davinci_spi->base + SPIBUF);
-				davinci_spi->get_rx(buf_val, davinci_spi);
-			}
-			if (count <= 0)
-				break;
-		}
-	} else {
-		while (1) {
-			/* keeps the serial clock going */
-			if ((ioread32(davinci_spi->base + SPIBUF)
-					& SPIBUF_TXFULL_MASK) == 0)
-				iowrite32(data1_reg_val,
-					davinci_spi->base + SPIDAT1);
+		u32 buf, status;
 
-				while (ioread32(davinci_spi->base + SPIBUF) &
-							SPIBUF_RXEMPTY_MASK)
-					cpu_relax();
+		buf = ioread32(davinci_spi->base + SPIBUF);
 
-			flg_val = ioread32(davinci_spi->base + SPIFLG);
-			buf_val = ioread32(davinci_spi->base + SPIBUF);
+		if (!(buf & SPIBUF_RXEMPTY_MASK)) {
+			davinci_spi->get_rx(buf & 0xFFFF, davinci_spi);
+			rcount--;
+		}
 
-			davinci_spi->get_rx(buf_val, davinci_spi);
+		status = ioread32(davinci_spi->base + SPIFLG);
 
-			count--;
-			if (count <= 0)
-				break;
+		if (unlikely(status & SPIFLG_ERROR_MASK)) {
+			errors = status & SPIFLG_ERROR_MASK;
+			break;
+		}
+
+		if (wcount > 0 && !(buf & SPIBUF_TXFULL_MASK)) {
+			wcount--;
+			tx_data = davinci_spi->get_tx(davinci_spi);
+			data1_reg_val &= ~0xFFFF;
+			data1_reg_val |= 0xFFFF & tx_data;
+			iowrite32(data1_reg_val, davinci_spi->base + SPIDAT1);
 		}
 	}
 
@@ -683,11 +668,12 @@  static int davinci_spi_bufs_pio(struct spi_device *spi, struct spi_transfer *t)
 	 * Check for bit error, desync error,parity error,timeout error and
 	 * receive overflow errors
 	 */
-	status = ioread32(davinci_spi->base + SPIFLG);
-
-	ret = davinci_spi_check_error(davinci_spi, status);
-	if (ret != 0)
+	if (errors) {
+		ret = davinci_spi_check_error(davinci_spi, errors);
+		WARN(!ret, "%s: error reported but no error found!\n",
+							dev_name(&spi->dev));
 		return ret;
+	}
 
 	return t->len;
 }