diff options
author | Maksim Kiselev <bigunclemax@gmail.com> | 2023-12-21 13:13:30 +0300 |
---|---|---|
committer | Jagan Teki <jagan@edgeble.ai> | 2024-01-29 17:18:12 +0530 |
commit | 26bb23b0bd303fae3412f36be6df3b7e87ed7cce (patch) | |
tree | 32b5fa01c650d6a3f30a92946507524be71c24d3 | |
parent | 526a865fe4fea59fb2638726c26e39557eb97fdd (diff) | |
download | u-boot-26bb23b0bd303fae3412f36be6df3b7e87ed7cce.zip u-boot-26bb23b0bd303fae3412f36be6df3b7e87ed7cce.tar.gz u-boot-26bb23b0bd303fae3412f36be6df3b7e87ed7cce.tar.bz2 |
spi: dw: add check for Rx FIFO overflow
If even one byte is lost due to Rx FIFO overflow then we will never
exit the read loop. Because the (priv->rx != priv->rx_end) condition will
be always true.
Let's check if Rx FIFO overflow occurred and exit the read loop
in this case.
Signed-off-by: Maksim Kiselev <bigunclemax@gmail.com>
Reviewed-by: Jagan Teki <jagan@amarulasolutions.com>
-rw-r--r-- | drivers/spi/designware_spi.c | 18 |
1 files changed, 15 insertions, 3 deletions
diff --git a/drivers/spi/designware_spi.c b/drivers/spi/designware_spi.c index 1c7d0ca..98908c5 100644 --- a/drivers/spi/designware_spi.c +++ b/drivers/spi/designware_spi.c @@ -111,6 +111,9 @@ #define SR_TX_ERR BIT(5) #define SR_DCOL BIT(6) +/* Bit field in RISR */ +#define RISR_INT_RXOI BIT(3) + #define RX_TIMEOUT 1000 /* timeout in ms */ struct dw_spi_plat { @@ -588,7 +591,7 @@ static int dw_spi_exec_op(struct spi_slave *slave, const struct spi_mem_op *op) struct dw_spi_priv *priv = dev_get_priv(bus); u8 op_len = op->cmd.nbytes + op->addr.nbytes + op->dummy.nbytes; u8 op_buf[op_len]; - u32 cr0; + u32 cr0, sts; if (read) priv->tmode = CTRLR0_TMOD_EPROMREAD; @@ -632,12 +635,21 @@ static int dw_spi_exec_op(struct spi_slave *slave, const struct spi_mem_op *op) * them to fail because we are not reading/writing the fifo fast enough. */ if (read) { - priv->rx = op->data.buf.in; + void *prev_rx = priv->rx = op->data.buf.in; priv->rx_end = priv->rx + op->data.nbytes; dw_write(priv, DW_SPI_SER, 1 << spi_chip_select(slave->dev)); - while (priv->rx != priv->rx_end) + while (priv->rx != priv->rx_end) { dw_reader(priv); + if (prev_rx == priv->rx) { + sts = dw_read(priv, DW_SPI_RISR); + if (sts & RISR_INT_RXOI) { + dev_err(bus, "FIFO overflow on Rx\n"); + return -EIO; + } + } + prev_rx = priv->rx; + } } else { u32 val; |