diff mbox series

[V2,2/3] spi: cadence-quadspi: Use STIG mode for all ops with small payload

Message ID 20230412105856.3565220-3-d-gole@ti.com
State Accepted
Commit 8077d296adff235e13c1478f92ef42c08e17ec33
Delegated to: Jagannadha Sutradharudu Teki
Headers show
Series spi: cadence_qspi: Fixes for DTR ops and improve STIG support | expand

Commit Message

Dhruva Gole April 12, 2023, 10:58 a.m. UTC
From: Apurva Nandan <a-nandan@ti.com>

OSPI controller supports all types of op variants in STIG mode,
only limitation being that the data payload should be less than
8 bytes when not using memory banks.

STIG mode is more stable for operations that send small data
payload and is more efficient than using DMA for few bytes of
memory accesses. It overcomes the limitation of minimum 4 bytes
read from flash into RAM seen in DAC mode.

Use STIG mode for all read and write operations that require
data input/output of less than 8 bytes from the flash, and thereby
support all four phases, cmd/address/dummy/data, through OSPI STIG.

Also, remove the reorder address chunk in apb_command_write since we now
setup ADDR BIT field that does the same job in a cleaner way.

Signed-off-by: Apurva Nandan <a-nandan@ti.com>
Signed-off-by: Dhruva Gole <d-gole@ti.com>
---
 drivers/spi/cadence_qspi.c     |  5 ++--
 drivers/spi/cadence_qspi_apb.c | 42 ++++++++++++++++++----------------
 2 files changed, 24 insertions(+), 23 deletions(-)
diff mbox series

Patch

diff --git a/drivers/spi/cadence_qspi.c b/drivers/spi/cadence_qspi.c
index a858a62888e4..f931e4cf3e2f 100644
--- a/drivers/spi/cadence_qspi.c
+++ b/drivers/spi/cadence_qspi.c
@@ -312,13 +312,12 @@  static int cadence_spi_mem_exec_op(struct spi_slave *spi,
 		 * which is unsupported on some flash devices during register
 		 * reads, prefer STIG mode for such small reads.
 		 */
-		if (!op->addr.nbytes ||
-		    op->data.nbytes <= CQSPI_STIG_DATA_LEN_MAX)
+		if (op->data.nbytes <= CQSPI_STIG_DATA_LEN_MAX)
 			mode = CQSPI_STIG_READ;
 		else
 			mode = CQSPI_READ;
 	} else {
-		if (!op->addr.nbytes || !op->data.buf.out)
+		if (op->data.nbytes <= CQSPI_STIG_DATA_LEN_MAX)
 			mode = CQSPI_STIG_WRITE;
 		else
 			mode = CQSPI_WRITE;
diff --git a/drivers/spi/cadence_qspi_apb.c b/drivers/spi/cadence_qspi_apb.c
index dfcdeff80545..4c055a05807e 100644
--- a/drivers/spi/cadence_qspi_apb.c
+++ b/drivers/spi/cadence_qspi_apb.c
@@ -462,11 +462,6 @@  int cadence_qspi_apb_command_read(struct cadence_spi_priv *priv,
 	unsigned int dummy_clk;
 	u8 opcode;
 
-	if (rxlen > CQSPI_STIG_DATA_LEN_MAX || !rxbuf) {
-		printf("QSPI: Invalid input arguments rxlen %u\n", rxlen);
-		return -EINVAL;
-	}
-
 	if (priv->dtr)
 		opcode = op->cmd.opcode >> 8;
 	else
@@ -549,26 +544,12 @@  int cadence_qspi_apb_command_write(struct cadence_spi_priv *priv,
 	unsigned int reg = 0;
 	unsigned int wr_data;
 	unsigned int wr_len;
+	unsigned int dummy_clk;
 	unsigned int txlen = op->data.nbytes;
 	const void *txbuf = op->data.buf.out;
 	void *reg_base = priv->regbase;
-	u32 addr;
 	u8 opcode;
 
-	/* Reorder address to SPI bus order if only transferring address */
-	if (!txlen) {
-		addr = cpu_to_be32(op->addr.val);
-		if (op->addr.nbytes == 3)
-			addr >>= 8;
-		txbuf = &addr;
-		txlen = op->addr.nbytes;
-	}
-
-	if (txlen > CQSPI_STIG_DATA_LEN_MAX) {
-		printf("QSPI: Invalid input arguments txlen %u\n", txlen);
-		return -EINVAL;
-	}
-
 	if (priv->dtr)
 		opcode = op->cmd.opcode >> 8;
 	else
@@ -576,6 +557,27 @@  int cadence_qspi_apb_command_write(struct cadence_spi_priv *priv,
 
 	reg |= opcode << CQSPI_REG_CMDCTRL_OPCODE_LSB;
 
+	/* setup ADDR BIT field */
+	if (op->addr.nbytes) {
+		writel(op->addr.val, priv->regbase + CQSPI_REG_CMDADDRESS);
+		/*
+		 * address bytes are zero indexed
+		 */
+		reg |= (((op->addr.nbytes - 1) &
+			  CQSPI_REG_CMDCTRL_ADD_BYTES_MASK) <<
+			  CQSPI_REG_CMDCTRL_ADD_BYTES_LSB);
+		reg |= (0x1 << CQSPI_REG_CMDCTRL_ADDR_EN_LSB);
+	}
+
+	/* Set up dummy cycles. */
+	dummy_clk = cadence_qspi_calc_dummy(op, priv->dtr);
+	if (dummy_clk > CQSPI_DUMMY_CLKS_MAX)
+		return -EOPNOTSUPP;
+
+	if (dummy_clk)
+		reg |= (dummy_clk & CQSPI_REG_CMDCTRL_DUMMY_MASK)
+		     << CQSPI_REG_CMDCTRL_DUMMY_LSB;
+
 	if (txlen) {
 		/* writing data = yes */
 		reg |= (0x1 << CQSPI_REG_CMDCTRL_WR_EN_LSB);