Re: [PATCH v3] mmc: sunxi: reset the controller after an update-clock timeout
From: Ulf Hansson
Date: Tue Nov 10 2026 - 06:50:27 EST
On Fri, Oct 30, 2026 at 11:41 PM <tam.do@xxxxxxxxxxxxxxx> wrote:
>
> > 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?
>
> Yes. It's the first update after probe, from the MMC_POWER_UP set_ios:
> sunxi_mmc_oclk_onoff+0x17c/0x1a0
> sunxi_mmc_clk_set_rate+0x1c/0x2c8
> sunxi_mmc_set_ios+0xe4/0x144
> mmc_power_up.part.0+0x40/0x150
> mmc_start_host+0x90/0x9c
> mmc_add_host+0x6c/0xa0
> sunxi_mmc_probe+0x35c/0x478
>
> STAS already reads 0x206 there, before anything has been sent to the
> card; on good boots it's 0x106. So the card is holding DAT0 when Linux
> takes over. These are warm boots from the vendor firmware and it
> happens on roughly half of them.
I see. So perhaps check DAT0 during the probe and make a reset already
at that point instead?
>
> The supply explanation in the commit message is wrong, sorry. The rails
> are up ~20 ms later and the command is still pending at the 750 ms
> timeout. From then on every update times out until the controller is
> reset. Rebinding with the card idle never hit it (0/20 tries).
> I'll fix the commit message in v4.
Thanks for the explanation. I will wait for the v4 then.
Kind regards
Uffe
>
> Tam
>
>
> > On Oct 30, 2026, at 8:48 AM, Ulf Hansson <ulf.hansson@xxxxxxxxxxxxxxxx> wrote:
> >
> > 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
> >>
>