diff mbox series

cadence_qspi: fix odd byte read issue in STIG mode

Message ID 20241105071014.188568-1-prasad.kummari@amd.com
State New
Headers show
Series cadence_qspi: fix odd byte read issue in STIG mode | expand

Commit Message

Prasad Kummari Nov. 5, 2024, 7:10 a.m. UTC
In DDR mode, even bytes are read using DMA, while the remaining odd
bytes are read using STIG mode. However, the data is not correctly
transferred into the flash read data lower register because the
supplementary byte of the STIG opcode is not being written to the
opcode extension register, resulting in incorrect data being read.

To resolve this issue, when using STIG transactions, the corresponding
supplementary byte of any STIG opcode must be defined in the Opcode
Extension Register (Lower).

Signed-off-by: Prasad Kummari <prasad.kummari@amd.com>
---
 drivers/spi/cadence_ospi_versal.c | 12 +++++++++++-
 drivers/spi/cadence_qspi.h        |  3 +++
 drivers/spi/cadence_qspi_apb.c    |  6 +++---
 3 files changed, 17 insertions(+), 4 deletions(-)
diff mbox series

Patch

diff --git a/drivers/spi/cadence_ospi_versal.c b/drivers/spi/cadence_ospi_versal.c
index 222f828f54..b9b312d550 100644
--- a/drivers/spi/cadence_ospi_versal.c
+++ b/drivers/spi/cadence_ospi_versal.c
@@ -20,7 +20,7 @@ 
 int cadence_qspi_apb_dma_read(struct cadence_spi_priv *priv,
 			      const struct spi_mem_op *op)
 {
-	u32 reg, ret, rx_rem, n_rx, bytes_to_dma, data;
+	u32 reg, ret, rx_rem, n_rx, bytes_to_dma, data, status;
 	u8 opcode, addr_bytes, *rxbuf, dummy_cycles;
 
 	n_rx = op->data.nbytes;
@@ -80,6 +80,16 @@  int cadence_qspi_apb_dma_read(struct cadence_spi_priv *priv,
 				   CQSPI_REG_SIZE_ADDRESS_MASK;
 
 		opcode = CMD_4BYTE_FAST_READ;
+
+		/* Set up command opcode extension. */
+		status = readl(priv->regbase + CQSPI_REG_CONFIG);
+		if (status & CQSPI_REG_CONFIG_DTR_PROTO) {
+			ret = cadence_qspi_setup_opcode_ext(priv, op,
+							    CQSPI_REG_OP_EXT_STIG_LSB);
+			if (ret)
+				return ret;
+		}
+
 		dummy_cycles = 8;
 		writel((dummy_cycles << CQSPI_REG_RD_INSTR_DUMMY_LSB) | opcode,
 		       priv->regbase + CQSPI_REG_RD_INSTR);
diff --git a/drivers/spi/cadence_qspi.h b/drivers/spi/cadence_qspi.h
index 693474a287..cc7947435c 100644
--- a/drivers/spi/cadence_qspi.h
+++ b/drivers/spi/cadence_qspi.h
@@ -310,5 +310,8 @@  int cadence_qspi_apb_exec_flash_cmd(void *reg_base, unsigned int reg);
 int cadence_qspi_versal_flash_reset(struct udevice *dev);
 ofnode cadence_qspi_get_subnode(struct udevice *dev);
 void cadence_qspi_apb_enable_linear_mode(bool enable);
+int cadence_qspi_setup_opcode_ext(struct cadence_spi_priv *priv,
+				  const struct spi_mem_op *op,
+				  unsigned int shift);
 
 #endif /* __CADENCE_QSPI_H__ */
diff --git a/drivers/spi/cadence_qspi_apb.c b/drivers/spi/cadence_qspi_apb.c
index 93ab2b5635..6a289cba96 100644
--- a/drivers/spi/cadence_qspi_apb.c
+++ b/drivers/spi/cadence_qspi_apb.c
@@ -380,9 +380,9 @@  int cadence_qspi_apb_exec_flash_cmd(void *reg_base, unsigned int reg)
 	return 0;
 }
 
-static int cadence_qspi_setup_opcode_ext(struct cadence_spi_priv *priv,
-					 const struct spi_mem_op *op,
-					 unsigned int shift)
+int cadence_qspi_setup_opcode_ext(struct cadence_spi_priv *priv,
+				  const struct spi_mem_op *op,
+				  unsigned int shift)
 {
 	unsigned int reg;
 	u8 ext;