diff mbox

[1/5] mmc: dw_mmc: Invalidate cache of current_speed after suspend/resume

Message ID 1373391071-6312-2-git-send-email-dianders@chromium.org (mailing list archive)
State New, archived
Headers show

Commit Message

Doug Anderson July 9, 2013, 5:31 p.m. UTC
The dw_mmc driver keeps a cache of the current slot->clock in order to
avoid doing a whole lot of work every time set_ios() is called.
However, after suspend/resume the register values are bogus so we need
to ensure that the cached value is invalidated.

In many cases we got by without this since the core mmc code fiddles
with the clock a lot.  If we've got a card present we're probably
running it at something like 50MHz and the core will temporarily
switch us to 400kHz after resume.  One case that didn't work (for me)
is the case of having no card in the slot.  The slot is initted to
400kHz at boot time.  After suspend/resume the slot thinks it's still
at 400kHz (due to the cache) so doesn't adjust timing.  When it tries
to send the command at probe time it just times out and gets left in a
bad state.

Invalidating the current_speed also means that we don't need to call:
  dw_mci_setup_bus(slot, true);
...to force an update of the clock in the case when the slot was left
powered.

Signed-off-by: Doug Anderson <dianders@chromium.org>
---
 drivers/mmc/host/dw_mmc.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)
diff mbox

Patch

diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index bc3a1bc..f20273e 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -2488,13 +2488,18 @@  int dw_mci_resume(struct dw_mci *host)
 		   DW_MCI_ERROR_FLAGS | SDMMC_INT_CD);
 	mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE);
 
+	/*
+	 * Invalidate the 'current_speed' value since CLKDIV has some up in
+	 * default state and our cache is incorrect.
+	 */
+	host->current_speed = 0xFFFFFFFF;
+
 	for (i = 0; i < host->num_slots; i++) {
 		struct dw_mci_slot *slot = host->slot[i];
 		if (!slot)
 			continue;
 		if (slot->mmc->pm_flags & MMC_PM_KEEP_POWER) {
 			dw_mci_set_ios(slot->mmc, &slot->mmc->ios);
-			dw_mci_setup_bus(slot, true);
 		}
 
 		ret = mmc_resume_host(host->slot[i]->mmc);