Re: [PATCH v3] mmc: sunxi: reset the controller after an update-clock timeout

From: Ulf Hansson

Date: Fri Oct 30 2026 - 09:48:43 EST


On Wed, Oct 28, 2026 at 12:43 PM Tam Do <tam.do@xxxxxxxxxxxxxxx> wrote:
>
> If the clock-update command times out it stays pending in the
> controller, and every later clock update times out as well, so the
> card cannot be initialised until the next probe.
>
> This happens on an R16 board whose SDIO Wi-Fi holds DAT0 busy while
> its supply comes up during the first clock update.

It would be nice if you could elaborate a bit more on what goes on here.

I assume it's sunxi_mmc_oclk_onoff() that is being called and it's the
loop in there that times out. The question is then, under what
circumstances are sunxi_mmc_oclk_onoff() being called when we are also
waiting for the SDIO card to release the busy indication on DAT0?

>
> Reset the controller on timeout so the next attempt can succeed. This
> runs sunxi_mmc_init_host() with the interrupt enabled for the first
> time, so write REG_IMASK from sdio_imask under host->lock, as
> sunxi_mmc_enable_sdio_irq() updates both under that lock.
>
> Fixes: 3cbcb16095f9 ("mmc: sunxi: Add driver for SD/MMC hosts found on Allwinner sunxi SoCs")
> Cc: stable@xxxxxxxxxxxxxxx
> Signed-off-by: Tam Do <tam.do@xxxxxxxxxxxxxxx>

Kind regards
Uffe

> ---
> v3: take host->lock only around the REG_IMASK write in
> sunxi_mmc_init_host(), not across the reset; v2 polled the reset on
> jiffies with interrupts off. The return value stays unchecked, as in
> sunxi_mmc_runtime_resume(): if the reset itself times out the
> controller is wedged either way.
> v2: held host->lock across the reset (not posted)
> v1: https://lore.kernel.org/all/179307312104.39863.12372814163472848752@xxxxxxxxxxxxxxx/
>
> drivers/mmc/host/sunxi-mmc.c | 4 ++++
> 1 file changed, 4 insertions(+)
>
> diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c
> index fe4c0f6d73f3..55313780d06d 100644
> --- a/drivers/mmc/host/sunxi-mmc.c
> +++ b/drivers/mmc/host/sunxi-mmc.c
> @@ -322,6 +322,7 @@ static int sunxi_mmc_reset_host(struct sunxi_mmc_host *host)
>
> static int sunxi_mmc_init_host(struct sunxi_mmc_host *host)
> {
> + unsigned long flags;
> u32 rval;
>
> if (sunxi_mmc_reset_host(host))
> @@ -336,7 +337,9 @@ static int sunxi_mmc_init_host(struct sunxi_mmc_host *host)
> /* Maximum timeout value */
> mmc_writel(host, REG_TMOUT, 0xffffffff);
> /* Unmask SDIO interrupt if needed */
> + spin_lock_irqsave(&host->lock, flags);
> mmc_writel(host, REG_IMASK, host->sdio_imask);
> + spin_unlock_irqrestore(&host->lock, flags);
> /* Clear all pending interrupts */
> mmc_writel(host, REG_RINTR, 0xffffffff);
> /* Debug register? undocumented */
> @@ -688,6 +691,7 @@ static int sunxi_mmc_oclk_onoff(struct sunxi_mmc_host *host, u32 oclk_en)
>
> if (rval & SDXC_START) {
> dev_err(mmc_dev(host->mmc), "fatal err update clk timeout\n");
> + sunxi_mmc_init_host(host);
> return -EIO;
> }
>
> --
> 2.39.5
>