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 <[email protected]> --- drivers/mmc/dw_mmc.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c index 130a5bb57f3cddc50b3cd0df2f40981de680e852..1aa992c352c3f11ccdd1c02745fa988646952261 100644 --- a/drivers/mmc/dw_mmc.c +++ b/drivers/mmc/dw_mmc.c @@ -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; } -- 2.51.0

