mmc: dw_mmc: properly address command completion in dwmci_control_clken()
authorKaustabh Chakraborty <kauschluss@disroot.org>
Fri, 17 Oct 2025 15:24:08 +0000 (20:54 +0530)
committerPeng Fan <peng.fan@nxp.com>
Thu, 30 Oct 2025 02:11:17 +0000 (10:11 +0800)
The current implementation polls for the DWMCI_CMD register, for the
DWMCI_CMD_START bit to turn off, which indicates that the command has
been completed. The problem with this approach is that it doesn't
address the DWMCI_INTMSK_CDONE bit in the interrupt register,
DWMCI_RINTSTS. As a result, subsequent commands result in timeout errors.

Re-implement the waiting logic by polling for said interrupt status bit
and setting it low if raised.

Signed-off-by: Kaustabh Chakraborty <kauschluss@disroot.org>
Signed-off-by: Peng Fan <peng.fan@nxp.com>
drivers/mmc/dw_mmc.c

index 130a5bb..1aa992c 100644 (file)
@@ -507,20 +507,21 @@ static int dwmci_control_clken(struct dwmci_host *host, bool on)
 {
        const u32 val = on ? DWMCI_CLKEN_ENABLE | DWMCI_CLKEN_LOW_PWR : 0;
        const u32 cmd_only_clk = DWMCI_CMD_PRV_DAT_WAIT | DWMCI_CMD_UPD_CLK;
-       int timeout = 10000;
-       u32 status;
+       int i, timeout = 10000;
+       u32 mask;
 
        dwmci_writel(host, DWMCI_CLKENA, val);
 
        /* Inform CIU */
        dwmci_writel(host, DWMCI_CMD, DWMCI_CMD_START | cmd_only_clk);
-       do {
-               status = dwmci_readl(host, DWMCI_CMD);
-               if (timeout-- < 0) {
-                       debug("%s: Timeout!\n", __func__);
-                       return -ETIMEDOUT;
+
+       for (i = 0; i < timeout; i++) {
+               mask = dwmci_readl(host, DWMCI_RINTSTS);
+               if (mask & DWMCI_INTMSK_CDONE) {
+                       dwmci_writel(host, DWMCI_RINTSTS, DWMCI_INTMSK_CDONE);
+                       break;
                }
-       } while (status & DWMCI_CMD_START);
+       }
 
        return 0;
 }