aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPadmarao Begari <padmarao.begari@amd.com>2025-01-06 15:21:20 +0530
committerMichal Simek <michal.simek@amd.com>2025-02-05 16:22:55 +0100
commit1621851495d341efb9c62c07a3d82feaa12cd03e (patch)
tree9a2e56ae72f92441d4b72843dcc111ca3473d8c5
parenta1319b5487522b1cdf981ae8bb02118fc53a801f (diff)
downloadu-boot-1621851495d341efb9c62c07a3d82feaa12cd03e.tar.gz
spi: cadence_qspi: Fix OSPI DDR mode alignment issue
If the least significant bit of the address is set to one when using the DDR protocol for data transfer then the results are indeterminate for few flash devices. To fix this the least significant bit of the address is set to zero. Signed-off-by: Padmarao Begari <padmarao.begari@amd.com> Link: https://lore.kernel.org/r/20250106095120.800753-1-padmarao.begari@amd.com Signed-off-by: Michal Simek <michal.simek@amd.com>
-rw-r--r--drivers/spi/cadence_ospi_versal.c12
1 files changed, 12 insertions, 0 deletions
diff --git a/drivers/spi/cadence_ospi_versal.c b/drivers/spi/cadence_ospi_versal.c
index dcf28c75596..816916de16d 100644
--- a/drivers/spi/cadence_ospi_versal.c
+++ b/drivers/spi/cadence_ospi_versal.c
@@ -24,6 +24,13 @@ int cadence_qspi_apb_dma_read(struct cadence_spi_priv *priv,
u8 opcode, addr_bytes, *rxbuf, dummy_cycles;
n_rx = op->data.nbytes;
+
+ if (op->addr.dtr && (op->addr.val % 2)) {
+ n_rx += 1;
+ writel(op->addr.val & ~0x1,
+ priv->regbase + CQSPI_REG_INDIRECTRDSTARTADDR);
+ }
+
rxbuf = op->data.buf.in;
rx_rem = n_rx % 4;
bytes_to_dma = n_rx - rx_rem;
@@ -104,6 +111,11 @@ int cadence_qspi_apb_dma_read(struct cadence_spi_priv *priv,
memcpy(rxbuf, &data, rx_rem);
}
+ if (op->addr.dtr && (op->addr.val % 2)) {
+ rxbuf -= bytes_to_dma;
+ memcpy(rxbuf, rxbuf + 1, n_rx - 1);
+ }
+
return 0;
}