From 5c99cb15169d6336c446d079f803e1b13916960f Mon Sep 17 00:00:00 2001 From: Changhuang Liang Date: Wed, 30 Sep 2026 00:15:33 -0700 Subject: [PATCH] spi: dw: Convert the Tx done delay from SCK cycles to time Currently the delay in dw_spi_dma_wait_tx_done() is expressed in SCK cycles, which requires passing a valid struct spi_transfer pointer. This does not work for enhanced SPI memory operations, which are not described by a spi_transfer. Compute the delay in ns or us based on an explicit bus speed instead, so that the helper can also be used for those transfers. Signed-off-by: Changhuang Liang Link: https://patch.msgid.link/20260930071535.7947-2-changhuang.liang@starfivetech.com Signed-off-by: Mark Brown --- drivers/spi/spi-dw-dma.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/drivers/spi/spi-dw-dma.c b/drivers/spi/spi-dw-dma.c index f7d848fec9ab..d0b1a03682e6 100644 --- a/drivers/spi/spi-dw-dma.c +++ b/drivers/spi/spi-dw-dma.c @@ -286,19 +286,27 @@ static inline bool dw_spi_dma_tx_busy(struct dw_spi *dws) (DW_SPI_SR_BUSY | DW_SPI_SR_TF_EMPT)) != DW_SPI_SR_TF_EMPT; } -static int dw_spi_dma_wait_tx_done(struct dw_spi *dws, - struct spi_transfer *xfer) +static int dw_spi_dma_wait_tx_done(struct dw_spi *dws, u32 speed_hz) { int retry = DW_SPI_WAIT_RETRIES; struct spi_delay delay; + unsigned long ns, us; u32 nents; nents = dw_readl(dws, DW_SPI_TXFLR); - delay.unit = SPI_DELAY_UNIT_SCK; - delay.value = nents * dws->n_bytes * BITS_PER_BYTE; + ns = DIV_ROUND_UP(NSEC_PER_SEC, speed_hz) * nents * + dws->n_bytes * BITS_PER_BYTE; + if (ns <= NSEC_PER_USEC) { + delay.unit = SPI_DELAY_UNIT_NSECS; + delay.value = ns; + } else { + us = DIV_ROUND_UP(ns, NSEC_PER_USEC); + delay.unit = SPI_DELAY_UNIT_USECS; + delay.value = clamp_val(us, 0, USHRT_MAX); + } while (dw_spi_dma_tx_busy(dws) && retry--) - spi_delay_exec(&delay, xfer); + spi_delay_exec(&delay, NULL); if (retry < 0) { dev_err(&dws->ctlr->dev, "Tx hanged up\n"); @@ -659,7 +667,7 @@ static int dw_spi_dma_transfer(struct dw_spi *dws, struct spi_transfer *xfer) return ret; if (dws->ctlr->cur_msg->status == -EINPROGRESS) { - ret = dw_spi_dma_wait_tx_done(dws, xfer); + ret = dw_spi_dma_wait_tx_done(dws, xfer->effective_speed_hz); if (ret) return ret; }