]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
spi: dw: add check for Rx FIFO overflow
authorMaksim Kiselev <bigunclemax@gmail.com>
Thu, 21 Dec 2023 10:13:30 +0000 (13:13 +0300)
committerJagan Teki <jagan@edgeble.ai>
Mon, 29 Jan 2024 11:48:12 +0000 (17:18 +0530)
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>
drivers/spi/designware_spi.c

index 1c7d0ca310b6e8d0c37b23bf41b2e9dd36192a62..98908c5217fd600b0712378965055325911ec84d 100644 (file)
 #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;