diff options
| author | Kaustabh Chakraborty <[email protected]> | 2025-10-17 20:54:08 +0530 |
|---|---|---|
| committer | Peng Fan <[email protected]> | 2025-10-30 10:11:17 +0800 |
| commit | ae4601959202f4ea21c8a1aa42c5d2d894b03d57 (patch) | |
| tree | 2814bf4e085cd48537e61abdde013f87a351058a /drivers | |
| parent | 3a5b187b5c03eff681d4e41823313dfa28dfe845 (diff) | |
mmc: dw_mmc: properly address command completion in dwmci_control_clken()
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]>
Signed-off-by: Peng Fan <[email protected]>
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/mmc/dw_mmc.c | 17 |
1 files changed, 9 insertions, 8 deletions
diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c index 130a5bb57f3..1aa992c352c 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; } |
