From 0bcd59706aeda8a5d48ba656bab74cb26f2b423e Mon Sep 17 00:00:00 2001 From: Wang YuWei <1973615295@qq.com> Date: Mon, 6 Jul 2026 11:33:13 +0800 Subject: [PATCH 1/2] spi: dw-dma: Wait for controller idle before completing Tx dw_spi_dma_wait_tx_done() polls dw_spi_dma_tx_busy(), which only checks DW_SPI_SR_TF_EMPT. An empty TX FIFO merely means the last data word has been moved into the shift register; the transfer is not complete on the bus until DW_SPI_SR_BUSY is also cleared. As a result the wait can return while the controller is still shifting out the final word. Any caller that tears down or reconfigures the controller right after the transfer can then lose the tail of the transfer. The memory-operation path in spi-dw-core.c already waits for both DW_SPI_SR_BUSY == 0 and DW_SPI_SR_TF_EMPT == 1. Use the same completion condition in the DMA path so the transfer is guaranteed to be finished on the bus before the wait returns. Signed-off-by: Wang YuWei <1973615295@qq.com> Link: https://patch.msgid.link/tencent_4EA7B5C94669ED4C38A5F6C1C9126E5D9106@qq.com Signed-off-by: Mark Brown --- drivers/spi/spi-dw-dma.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-dw-dma.c b/drivers/spi/spi-dw-dma.c index bd70a7ed8067..f7d848fec9ab 100644 --- a/drivers/spi/spi-dw-dma.c +++ b/drivers/spi/spi-dw-dma.c @@ -282,7 +282,8 @@ static int dw_spi_dma_wait(struct dw_spi *dws, unsigned int len, u32 speed) static inline bool dw_spi_dma_tx_busy(struct dw_spi *dws) { - return !(dw_readl(dws, DW_SPI_SR) & DW_SPI_SR_TF_EMPT); + return (dw_readl(dws, DW_SPI_SR) & + (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, From e919ca35a6e84b5adf085da9ffa1544c01d4ce1e Mon Sep 17 00:00:00 2001 From: Srikanth Boyapally Date: Wed, 8 Jul 2026 10:21:48 +0530 Subject: [PATCH 2/2] spi: cadence-quadspi: Fix indirect write timeout when DMA read mode is enabled When use_dma_read is enabled, the IRQ handler unconditionally overwrites irq_status with the return value of get_dma_status(). For write operations, DMA status returns 0 since no DMA read is in progress, causing irq_status to become 0. The subsequent completion signal is never triggered and the write operation times out with -ETIMEDOUT: cadence-qspi f1010000.spi: Indirect write timeout spi-nor spi0.1: operation failed with -110 Fix this by separating the DMA completion path from the write interrupt path. If get_dma_status() indicates DMA read completion, signal completion and return immediately. Otherwise, preserve the original irq_status so that write completion interrupts are correctly recognized and signalled. Fixes: aac733a96636 ("spi: cadence-qspi: Fix style and improve readability") Signed-off-by: Srikanth Boyapally Reviewed-by: Radhey Shyam Pandey Link: https://patch.msgid.link/20260708045148.2993313-1-srikanth.boyapally@amd.com Signed-off-by: Mark Brown --- drivers/spi/spi-cadence-quadspi.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/spi/spi-cadence-quadspi.c b/drivers/spi/spi-cadence-quadspi.c index aaba1a3ad577..ecb0be394696 100644 --- a/drivers/spi/spi-cadence-quadspi.c +++ b/drivers/spi/spi-cadence-quadspi.c @@ -382,12 +382,16 @@ static irqreturn_t cqspi_irq_handler(int this_irq, void *dev) /* Clear interrupt */ writel(irq_status, cqspi->iobase + CQSPI_REG_IRQSTATUS); - if (cqspi->use_dma_read && ddata && ddata->get_dma_status) - irq_status = ddata->get_dma_status(cqspi); - else if (cqspi->slow_sram) + if (cqspi->use_dma_read && ddata && ddata->get_dma_status) { + if (ddata->get_dma_status(cqspi)) { + complete(&cqspi->transfer_complete); + return IRQ_HANDLED; + } + } else if (cqspi->slow_sram) { irq_status &= CQSPI_IRQ_MASK_RD_SLOW_SRAM | CQSPI_IRQ_MASK_WR; - else + } else { irq_status &= CQSPI_IRQ_MASK_RD | CQSPI_IRQ_MASK_WR; + } if (irq_status) complete(&cqspi->transfer_complete);