[RFC] spi: Using Trigger number to transmit/receive data

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




From: Hiep Cao Minh <cm-hiep@xxxxxxxxxxx>

In order to transmit and receive data when have 32 bytes of data that
ready has prepared on Transmit/Receive Buffer to transmit or receive.
Instead transmits/receives a byte data using Transmit/Receive Buffer
Data Triggering Number will improve the speed of transfer data.

Signed-off-by: Hiep Cao Minh <cm-hiep@xxxxxxxxxxx>
---
 drivers/spi/spi-rspi.c |  144 +++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 124 insertions(+), 20 deletions(-)

diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c
index 28987d9..772a942 100644
--- a/drivers/spi/spi-rspi.c
+++ b/drivers/spi/spi-rspi.c
@@ -174,6 +174,12 @@
 #define SPBFCR_RXRST		0x40	/* Receive Buffer Data Reset (qspi only) */
 #define SPBFCR_TXTRG_MASK	0x30	/* Transmit Buffer Data Triggering Number */
 #define SPBFCR_RXTRG_MASK	0x07	/* Receive Buffer Data Triggering Number */
+#define SPBFCR_TXTRG_31B	0x00	/* QSPI only */
+#define SPBFCR_TXTRG_0B		0x30	/* QSPI only */
+#define SPBFCR_RXTRG_1B		0x00	/* QSPI only */
+#define SPBFCR_RXTRG_32B	0x07	/* QSPI only */
+
+#define QSPI_BUFFER_SIZE        32
 
 #define DUMMY_DATA		0x00
 
@@ -224,6 +230,16 @@ static u16 rspi_read16(const struct rspi_data *rspi, u16 offset)
 	return ioread16(rspi->addr + offset);
 }
 
+static void qspi_update(const struct rspi_data *rspi, u8 mask, u8 val, u8 reg)
+{
+	u8 data;
+
+	data = rspi_read8(rspi, reg);
+	data &= ~mask;
+	data |= (val & mask);
+	rspi_write8(rspi, data, reg);
+}
+
 /* optional functions */
 struct spi_ops {
 	int (*set_config_register)(const struct rspi_data *rspi,
@@ -358,6 +374,44 @@ static void rspi_negate_ssl(const struct rspi_data *rspi)
 	rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) & ~SPCR_SPE, RSPI_SPCR);
 }
 
+static int qspi_set_send_trigger(struct rspi_data *rspi, int remain)
+{
+	int n;
+
+	n = min(remain, QSPI_BUFFER_SIZE);
+
+	if (remain >= QSPI_BUFFER_SIZE) {
+		/* sets triggering number to 32 bytes */
+		qspi_update(rspi, SPBFCR_TXTRG_MASK,
+			     SPBFCR_TXTRG_0B, QSPI_SPBFCR);
+	} else {
+		/* sets triggering number to 1 byte */
+		qspi_update(rspi, SPBFCR_TXTRG_MASK,
+			     SPBFCR_TXTRG_31B, QSPI_SPBFCR);
+	}
+
+	return n;
+}
+
+static int qspi_set_receive_trigger(struct rspi_data *rspi, int remain)
+{
+	int n;
+
+	n = min(remain, QSPI_BUFFER_SIZE);
+
+	if (remain >= QSPI_BUFFER_SIZE) {
+		/* sets triggering number to 32 bytes */
+		qspi_update(rspi, SPBFCR_RXTRG_MASK,
+			     SPBFCR_RXTRG_32B, QSPI_SPBFCR);
+	} else {
+		/* sets triggering number to 1 byte */
+		qspi_update(rspi, SPBFCR_RXTRG_MASK,
+			     SPBFCR_RXTRG_1B, QSPI_SPBFCR);
+	}
+
+	return n;
+}
+
 static int rspi_send_pio(struct rspi_data *rspi, struct spi_message *mesg,
 			 struct spi_transfer *t)
 {
@@ -389,9 +443,10 @@ static int qspi_send_pio(struct rspi_data *rspi, struct spi_message *mesg,
 {
 	int remain = t->len;
 	const u8 *data = t->tx_buf;
+	int i, n;
 
 	rspi_write8(rspi, SPBFCR_TXRST, QSPI_SPBFCR);
-	rspi_write8(rspi, 0x00, QSPI_SPBFCR);
+	rspi_write8(rspi, DUMMY_DATA, QSPI_SPBFCR);
 
 	while (remain > 0) {
 
@@ -400,16 +455,38 @@ static int qspi_send_pio(struct rspi_data *rspi, struct spi_message *mesg,
 				"%s: tx empty timeout\n", __func__);
 			return -ETIMEDOUT;
 		}
-		rspi_write8(rspi, *data++, RSPI_SPDR);
-
-		if (rspi_wait_for_interrupt(rspi, SPSR_SPRF, SPCR_SPRIE) < 0) {
-			dev_err(&rspi->master->dev,
-				"%s: receive timeout\n", __func__);
-			return -ETIMEDOUT;
+		n = qspi_set_send_trigger(rspi, remain);
+		if (n >= QSPI_BUFFER_SIZE) {
+			for (i = 0; i < n; i++)
+				rspi_write8(rspi, *data++, RSPI_SPDR);
+			if (rspi_wait_for_interrupt(rspi, SPSR_SPRF,
+						    SPCR_SPRIE) < 0) {
+				dev_err(&rspi->master->dev,
+					"%s: receive timeout\n", __func__);
+				return -ETIMEDOUT;
+			}
+			for (i = 0; i < n; i++)
+				rspi_read8(rspi, RSPI_SPDR);
+		} else {
+			for (i = 0; i < n; i++) {
+				if (rspi_wait_for_interrupt(rspi, SPSR_SPTEF,
+							    SPCR_SPTIE) < 0) {
+					dev_err(&rspi->master->dev,
+					   "%s: tx empty timeout\n", __func__);
+				return -ETIMEDOUT;
+				}
+				rspi_write8(rspi, *data++, RSPI_SPDR);
+
+				if (rspi_wait_for_interrupt(rspi, SPSR_SPRF,
+							    SPCR_SPRIE) < 0) {
+					dev_err(&rspi->master->dev,
+					   "%s: receive timeout\n", __func__);
+				return -ETIMEDOUT;
+				}
+				rspi_read8(rspi, RSPI_SPDR);
+			}
 		}
-		rspi_read8(rspi, RSPI_SPDR);
-
-		remain--;
+		remain -= n;
 	}
 
 	/* Waiting for the last transmission */
@@ -603,6 +680,7 @@ static int qspi_receive_pio(struct rspi_data *rspi, struct spi_message *mesg,
 {
 	int remain = t->len;
 	u8 *data;
+	int i, n;
 
 	qspi_receive_init(rspi);
 
@@ -614,17 +692,43 @@ static int qspi_receive_pio(struct rspi_data *rspi, struct spi_message *mesg,
 				"%s: tx empty timeout\n", __func__);
 			return -ETIMEDOUT;
 		}
-		/* dummy write for generate clock */
-		rspi_write8(rspi, DUMMY_DATA, RSPI_SPDR);
-
-		if (rspi_wait_for_interrupt(rspi, SPSR_SPRF, SPCR_SPRIE) < 0) {
-			dev_err(&rspi->master->dev,
-				"%s: receive timeout\n", __func__);
-			return -ETIMEDOUT;
+		n = qspi_set_receive_trigger(rspi, remain);
+		if (n >= QSPI_BUFFER_SIZE) {
+			/* dummy write for generate clock */
+			for (i = 0; i < n; i++)
+				rspi_write8(rspi, DUMMY_DATA, RSPI_SPDR);
+
+			if (rspi_wait_for_interrupt(rspi, SPSR_SPRF,
+						    SPCR_SPRIE) < 0) {
+				dev_err(&rspi->master->dev,
+					"%s: receive timeout\n", __func__);
+				return -ETIMEDOUT;
+			}
+			/* SPDR allows 8, 16 or 32-bit access */
+			for (i = 0; i < n; i++)
+				*data++ = rspi_read8(rspi, RSPI_SPDR);
+		} else {
+			for (i = 0; i < n; i++) {
+				if (rspi_wait_for_interrupt(rspi, SPSR_SPTEF,
+							    SPCR_SPTIE) < 0) {
+					dev_err(&rspi->master->dev,
+					   "%s: tx empty timeout\n", __func__);
+					return -ETIMEDOUT;
+				}
+				/* dummy write for generate clock */
+				rspi_write8(rspi, DUMMY_DATA, RSPI_SPDR);
+
+				if (rspi_wait_for_interrupt(rspi, SPSR_SPRF,
+							    SPCR_SPRIE) < 0) {
+					dev_err(&rspi->master->dev,
+					   "%s: receive timeout\n", __func__);
+					return -ETIMEDOUT;
+				}
+				/* SPDR allows 8, 16 or 32-bit access */
+				*data++ = rspi_read8(rspi, RSPI_SPDR);
+			}
 		}
-		/* SPDR allows 8, 16 or 32-bit access */
-		*data++ = rspi_read8(rspi, RSPI_SPDR);
-		remain--;
+		remain -= n;
 	}
 
 	return 0;
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Device Tree Compilter]     [Device Tree Spec]     [Linux Driver Backports]     [Video for Linux]     [Linux USB Devel]     [Linux PCI Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Yosemite Backpacking]
  Powered by Linux