]> git.ipfire.org Git - thirdparty/u-boot.git/commitdiff
cadence_qspi: fix odd byte read issue in STIG mode
authorVenkatesh Yadav Abbarapu <venkatesh.abbarapu@amd.com>
Wed, 2 Jul 2025 05:39:53 +0000 (11:09 +0530)
committerMichal Simek <michal.simek@amd.com>
Tue, 8 Jul 2025 13:01:25 +0000 (15:01 +0200)
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). Issue has been observed on the Macronix
MX66UM2G45G flashes.

Signed-off-by: Prasad Kummari <prasad.kummari@amd.com>
Signed-off-by: Venkatesh Yadav Abbarapu <venkatesh.abbarapu@amd.com>
Link: https://lore.kernel.org/r/20250702053953.640046-1-venkatesh.abbarapu@amd.com
Signed-off-by: Michal Simek <michal.simek@amd.com>
drivers/spi/cadence_ospi_versal.c
drivers/spi/cadence_qspi.h
drivers/spi/cadence_qspi_apb.c

index fbeb0c6a85c6e1dd8a4373668019b71def3d9bca..6dc6fbe5a5b01c4040c2b20bada306519ae23b93 100644 (file)
@@ -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;
@@ -87,6 +87,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);
index 80510f2542be6897e0edef826b57c7a3f66c5bec..879e7f8dbfb8343bce58048bd0087b97ff6b0601 100644 (file)
@@ -320,5 +320,7 @@ int cadence_qspi_flash_reset(struct udevice *dev);
 ofnode cadence_qspi_get_subnode(struct udevice *dev);
 void cadence_qspi_apb_enable_linear_mode(bool enable);
 int cadence_device_reset(struct udevice *dev);
-
+int cadence_qspi_setup_opcode_ext(struct cadence_spi_priv *priv,
+                                 const struct spi_mem_op *op,
+                                 unsigned int shift);
 #endif /* __CADENCE_QSPI_H__ */
index ebfcae9a5b350db034881ecdf0f43b56748d0e78..6f89d3add5d50f71c333bffefaebe5be40213051 100644 (file)
@@ -384,9 +384,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;