[PATCH 13/14] spi: dw: Support clock stretching

Sean Anderson seanga2 at gmail.com
Mon Feb 1 01:34:35 CET 2021


We don't always read/write to the FIFO fast enough. Enable clock stretching
for enhanced SPI transfers. This is only possible with DWC SSI devices more
recent than 1.01a. We also need to set the RXFTLR register to tell the
device when to start reciving again. In particular, the default of 0 will
result in the device never restarting reception if there is an overflow. On
the transmit side, we need to set CTRL1 so that the device knows when to
keep stretching the clock if the FIFO is empty.

Signed-off-by: Sean Anderson <seanga2 at gmail.com>
---

 drivers/spi/designware_spi.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/spi/designware_spi.c b/drivers/spi/designware_spi.c
index 4796d55b20..78da490c3e 100644
--- a/drivers/spi/designware_spi.c
+++ b/drivers/spi/designware_spi.c
@@ -254,7 +254,8 @@ static u32 dw_spi_update_spi_cr0(const struct spi_mem_op *op)
 	return FIELD_PREP(SPI_CTRLR0_TRANS_TYPE, trans_type)
 	       | FIELD_PREP(SPI_CTRLR0_ADDR_L_MASK, op->addr.nbytes * 2)
 	       | FIELD_PREP(SPI_CTRLR0_INST_L_MASK, 2)
-	       | FIELD_PREP(SPI_CTRLR0_WAIT_CYCLES_MASK, wait_cycles);
+	       | FIELD_PREP(SPI_CTRLR0_WAIT_CYCLES_MASK, wait_cycles)
+	       | SPI_CTRLR0_CLK_STRETCH_EN;
 }
 
 static int request_gpio_cs(struct udevice *bus)
@@ -356,6 +357,9 @@ static void spi_hw_init(struct udevice *bus, struct dw_spi_priv *priv)
 		priv->fifo_len = (fifo == 1) ? 0 : fifo;
 		dw_write(priv, DW_SPI_TXFTLR, 0);
 	}
+
+	/* Set receive fifo interrupt level register for clock stretching */
+	dw_write(priv, DW_SPI_RXFTLR, priv->fifo_len - 1);
 }
 
 /*
@@ -778,8 +782,7 @@ static int dw_spi_exec_op(struct spi_slave *slave, const struct spi_mem_op *op)
 
 	dw_write(priv, DW_SPI_SSIENR, 0);
 	dw_write(priv, DW_SPI_CTRLR0, cr0);
-	if (read)
-		dw_write(priv, DW_SPI_CTRLR1, op->data.nbytes - 1);
+	dw_write(priv, DW_SPI_CTRLR1, op->data.nbytes - 1);
 	if (priv->spi_frf != CTRLR0_SPI_FRF_BYTE)
 		dw_write(priv, DW_SPI_SPI_CTRL0, spi_cr0);
 	dw_write(priv, DW_SPI_SSIENR, 1);
-- 
2.29.2



More information about the U-Boot mailing list