
Per dw_mmc databook, it's recommend that reset the host contoller if some data-related error occurre during tuning progress.
Signed-off-by: Ziyuan Xu xzy.xu@rock-chips.com ---
drivers/mmc/dw_mmc.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-)
diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c index c05288c..e862eb2 100644 --- a/drivers/mmc/dw_mmc.c +++ b/drivers/mmc/dw_mmc.c @@ -97,7 +97,7 @@ static int dwmci_data_transfer(struct dwmci_host *host, struct mmc_data *data) { int ret = 0; u32 timeout = 240000; - u32 mask, size, i, len = 0; + u32 status, ctrl, mask, size, i, len = 0; u32 *buf = NULL; ulong start = get_timer(0); u32 fifo_depth = (((host->fifoth_val & RX_WMARK_MASK) >> @@ -114,6 +114,23 @@ static int dwmci_data_transfer(struct dwmci_host *host, struct mmc_data *data) /* Error during data transfer. */ if (mask & (DWMCI_DATA_ERR | DWMCI_DATA_TOUT)) { debug("%s: DATA ERROR!\n", __func__); + + dwmci_wait_reset(host, DWMCI_RESET_ALL); + dwmci_writel(host, DWMCI_CMD, DWMCI_CMD_PRV_DAT_WAIT | + DWMCI_CMD_UPD_CLK | DWMCI_CMD_START); + + do { + status = dwmci_readl(host, DWMCI_CMD); + if (timeout-- < 0) + ret = -ETIMEDOUT; + } while (status & DWMCI_CMD_START); + + if (!host->fifo_mode) { + ctrl = dwmci_readl(host, DWMCI_BMOD); + ctrl |= DWMCI_BMOD_IDMAC_RESET; + dwmci_writel(host, DWMCI_BMOD, ctrl); + } + ret = -EINVAL; break; }