[PATCH] cadence_qspi: fix odd byte read issue in STIG mode
Michal Simek
michal.simek at amd.com
Tue Jul 8 15:03:53 CEST 2025
On 7/2/25 07:39, Venkatesh Yadav Abbarapu wrote:
> 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 at amd.com>
> Signed-off-by: Venkatesh Yadav Abbarapu <venkatesh.abbarapu at amd.com>
> ---
> drivers/spi/cadence_ospi_versal.c | 12 +++++++++++-
> drivers/spi/cadence_qspi.h | 4 +++-
> drivers/spi/cadence_qspi_apb.c | 6 +++---
> 3 files changed, 17 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/spi/cadence_ospi_versal.c b/drivers/spi/cadence_ospi_versal.c
> index fbeb0c6a85c..6dc6fbe5a5b 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;
> @@ -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);
> diff --git a/drivers/spi/cadence_qspi.h b/drivers/spi/cadence_qspi.h
> index 80510f2542b..879e7f8dbfb 100644
> --- a/drivers/spi/cadence_qspi.h
> +++ b/drivers/spi/cadence_qspi.h
> @@ -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__ */
> diff --git a/drivers/spi/cadence_qspi_apb.c b/drivers/spi/cadence_qspi_apb.c
> index c38bb523806..ecfa4ca222c 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;
Applied.
M
More information about the U-Boot
mailing list