RE: [PATCH v2] spi: imx: reconfigure for PIO when DMA cannot be started

From: Carlos Song

Date: Wed Jun 24 2026 - 11:31:23 EST




> -----Original Message-----
> From: Javier Fernandez Pastrana <javier.pastrana@xxxxxxxxxxxxx>
> Sent: Wednesday, June 24, 2026 11:20 PM
> To: Mark Brown <broonie@xxxxxxxxxx>; Frank Li <frank.li@xxxxxxx>; Sascha
> Hauer <s.hauer@xxxxxxxxxxxxxx>; Pengutronix Kernel Team
> <kernel@xxxxxxxxxxxxxx>; Fabio Estevam <festevam@xxxxxxxxx>; Carlos Song
> <carlos.song@xxxxxxx>; linux-spi@xxxxxxxxxxxxxxx; imx@xxxxxxxxxxxxxxx;
> linux-arm-kernel@xxxxxxxxxxxxxxxxxxx; linux-kernel@xxxxxxxxxxxxxxx
> Cc: javier.pastrana@xxxxxxxxxxxxx; stable@xxxxxxxxxxxxxxx
> Subject: [EXT] [PATCH v2] spi: imx: reconfigure for PIO when DMA cannot be
> started
>
> [Some people who received this message don't often get email from
> javier.pastrana@xxxxxxxxxxxxx. Learn why this is important at
> https://aka.ms/LearnAboutSenderIdentification ]
>
> Caution: This is an external email. Please take care when clicking links or opening
> attachments. When in doubt, report the message using the 'Report this email'
> button
>
>
> When spi_imx_can_dma() selects DMA, the ECSPI is configured for DMA:
> spi_imx_setupxfer() sets CTRL.SMC and clears dynamic_burst, and
> spi_imx_dma_transfer() programs the dynamic-burst BURST_LENGTH and the
> SDMA watermarks.
>
> If the DMA descriptor cannot be prepared (dmaengine_prep_slave_single()
> returns NULL), the transfer is failed with SPI_TRANS_FAIL_NO_START and falls
> back to PIO. The dynamic-burst DMA path uses its own bounce buffers instead of
> the SPI core's mapping, so xfer->{tx,rx}_sg_mapped are not set and the core's
> DMA->PIO retry is skipped; the driver falls back to PIO internally. But none of the
> DMA-mode configuration is undone, so the PIO transfer runs with CTRL.SMC set,
> the wrong burst length and dynamic_burst cleared, and the transferred data is
> corrupted.
>
> This is easily hit on i.MX8MP boards that describe ECSPI DMA in the device tree
> but run SDMA on ROM firmware (no external sdma-imx7d.bin):
> every ECSPI DMA prepare fails. An Infineon SLB9670 TPM on ECSPI1 then returns
> shifted TPM2_GetCapability data, is flagged "field failure mode", /dev/tpmrm0 is
> never created.
>
> Set controller->fallback before re-running spi_imx_setupxfer() so the ECSPI is
> reconfigured exactly like a normal PIO transfer. With
> controller->fallback set, spi_imx_setupxfer() sees spi_imx_can_dma()
> return false, so it clears spi_imx->usedma and reprograms the controller (clears
> CTRL.SMC, restores dynamic_burst and the PIO burst length). No explicit
> spi_imx->usedma = false is needed: setupxfer() already updates it from the
> can_dma() result.
>
> Fixes: faa8e404ad8e ("spi: imx: support dynamic burst length for ECSPI DMA
> mode")
> Cc: stable@xxxxxxxxxxxxxxx
> Signed-off-by: Javier Fernandez Pastrana <javier.pastrana@xxxxxxxxxxxxx>

Hi,

LGTM. Thank you!

Acked-by: Carlos Song <carlos.song@xxxxxxx>

> ---
> v2: drop redundant spi_imx->usedma = false; spi_imx_setupxfer() already
> clears it via spi_imx_can_dma() (Carlos Song)
>
> drivers/spi/spi-imx.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index
> 480d1e8b281f..1837cc7b0b96 100644
> --- a/drivers/spi/spi-imx.c
> +++ b/drivers/spi/spi-imx.c
> @@ -2152,7 +2152,8 @@ static int spi_imx_transfer_one(struct spi_controller
> *controller,
> if (spi_imx->usedma) {
> ret = spi_imx_dma_transfer(spi_imx, transfer);
> if (transfer->error & SPI_TRANS_FAIL_NO_START) {
> - spi_imx->usedma = false;
> + controller->fallback = true;
> + spi_imx_setupxfer(spi, transfer);
> if (spi_imx->target_mode)
> return spi_imx_pio_transfer_target(spi,
> transfer);
> else
> --
> 2.47.3