[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