summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYixun Lan <[email protected]>2026-04-21 04:47:50 +0000
committerAndre Przywara <[email protected]>2026-04-30 23:31:03 +0200
commit11b5cd22bae8372447a8089df7a2400ac21ed021 (patch)
tree4e48c7c46e37deedc21d054b7916266f8287eb25
parent7ad8e387d6d56bc07a978a8e888fdf5276325be5 (diff)
spi: sunxi: wait for TX/RX fifo reset done
Once reset SPI TX or RX fifo, the underlying hardware need to take some time to actually settle down, the two bits will automatically clear to 0, so use a poll mechanism to check status bits to make sure it's done correctly. On Cubie A7A board which using A733 SoC, we encoutered a SPI nor flash timeout issue, it turns out that the SPI fifo reset take a few time to settle down, Add a loop to poll the status. This was the error message shows on A7A board once this issue happened. => sf probe ERROR: sun4i_spi: Timeout transferring data Failed to initialize SPI flash at 0:0 (error -2) Signed-off-by: Yixun Lan <[email protected]> Reviewed-by: Jernej Skrabec <[email protected]> Acked-by: Andre Przywara <[email protected]>
-rw-r--r--drivers/spi/spi-sunxi.c9
1 files changed, 6 insertions, 3 deletions
diff --git a/drivers/spi/spi-sunxi.c b/drivers/spi/spi-sunxi.c
index 0bdc112d249..08b603f04a2 100644
--- a/drivers/spi/spi-sunxi.c
+++ b/drivers/spi/spi-sunxi.c
@@ -344,7 +344,7 @@ static int sun4i_spi_xfer(struct udevice *dev, unsigned int bitlen,
struct sun4i_spi_priv *priv = dev_get_priv(bus);
struct dm_spi_slave_plat *slave_plat = dev_get_parent_plat(dev);
- u32 len = bitlen / 8;
+ u32 rst, val, len = bitlen / 8;
u8 nbytes;
int ret;
@@ -360,8 +360,11 @@ static int sun4i_spi_xfer(struct udevice *dev, unsigned int bitlen,
sun4i_spi_set_cs(bus, slave_plat->cs[0], true);
/* Reset FIFOs */
- setbits_le32(SPI_REG(priv, SPI_FCR), SPI_BIT(priv, SPI_FCR_RF_RST) |
- SPI_BIT(priv, SPI_FCR_TF_RST));
+ rst = SPI_BIT(priv, SPI_FCR_RF_RST) | SPI_BIT(priv, SPI_FCR_TF_RST);
+ setbits_le32(SPI_REG(priv, SPI_FCR), rst);
+ ret = readl_poll_timeout(SPI_REG(priv, SPI_FCR), val, !(rst & val), 20);
+ if (ret)
+ return -EBUSY;
while (len) {
/* Setup the transfer now... */