summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorApurva Nandan <a-nandan@ti.com>2023-01-23 23:13:12 +0530
committerPraneeth Bajjuri <praneeth@ti.com>2023-01-25 14:10:19 -0600
commit0ee34f16d01b555742d9943e3dcdc72a9662d2cd (patch)
treecdcec17013b53d3c17548116cad7f167badb9796 /drivers
parent55ca31ac4384cec499c05f888f3f49fd38cb0e8f (diff)
spi: cadence-quadspi: Use STIG mode for all ops with small payload
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. Signed-off-by: Apurva Nandan <a-nandan@ti.com> Reviewed-by: Dhruva Gole <d-gole@ti.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/spi/cadence_qspi.c5
-rw-r--r--drivers/spi/cadence_qspi_apb.c67
2 files changed, 38 insertions, 34 deletions
diff --git a/drivers/spi/cadence_qspi.c b/drivers/spi/cadence_qspi.c
index 748ed20cb8..c7b6178a12 100644
--- a/drivers/spi/cadence_qspi.c
+++ b/drivers/spi/cadence_qspi.c
@@ -831,13 +831,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 00abd7c11f..0f6941ec3f 100644
--- a/drivers/spi/cadence_qspi_apb.c
+++ b/drivers/spi/cadence_qspi_apb.c
@@ -639,6 +639,8 @@ static int cadence_qspi_apb_exec_flash_cmd(void *reg_base,
if (!cadence_qspi_wait_idle(reg_base))
return -EIO;
+ /* Flush the CMDCTRL reg after the execution */
+ writel(0, reg_base + CQSPI_REG_CMDCTRL);
return 0;
}
@@ -725,11 +727,6 @@ int cadence_qspi_apb_command_read(struct cadence_spi_platdata *plat,
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 (plat->dtr)
opcode = op->cmd.opcode >> 8;
else
@@ -737,6 +734,18 @@ int cadence_qspi_apb_command_read(struct cadence_spi_platdata *plat,
reg = opcode << CQSPI_REG_CMDCTRL_OPCODE_LSB;
+ /* setup ADDR BIT field */
+ if (op->addr.nbytes) {
+ writel(op->addr.val, plat->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 |= CQSPI_REG_CMDCTRL_ADDR_EN;
+ }
+
/* Set up dummy cycles. */
dummy_clk = cadence_qspi_calc_dummy(op, plat->dtr);
if (dummy_clk > CQSPI_DUMMY_CLKS_MAX)
@@ -752,18 +761,6 @@ int cadence_qspi_apb_command_read(struct cadence_spi_platdata *plat,
reg |= (((rxlen - 1) & CQSPI_REG_CMDCTRL_RD_BYTES_MASK)
<< CQSPI_REG_CMDCTRL_RD_BYTES_LSB);
- /* setup ADDR BIT field */
- if (op->addr.nbytes) {
- writel(op->addr.val, plat->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 |= CQSPI_REG_CMDCTRL_ADDR_EN;
- }
-
status = cadence_qspi_apb_exec_flash_cmd(reg_base, reg);
if (status != 0)
return status;
@@ -812,25 +809,12 @@ int cadence_qspi_apb_command_write(struct cadence_spi_platdata *plat,
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 = plat->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 (plat->dtr)
opcode = op->cmd.opcode >> 8;
@@ -839,6 +823,27 @@ int cadence_qspi_apb_command_write(struct cadence_spi_platdata *plat,
reg |= opcode << CQSPI_REG_CMDCTRL_OPCODE_LSB;
+ /* setup ADDR BIT field */
+ if (op->addr.nbytes) {
+ writel(op->addr.val, plat->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 |= CQSPI_REG_CMDCTRL_ADDR_EN;
+ }
+
+ /* Set up dummy cycles. */
+ dummy_clk = cadence_qspi_calc_dummy(op, plat->dtr);
+ if (dummy_clk > CQSPI_DUMMY_CLKS_MAX)
+ return -ENOTSUPP;
+
+ 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);