mmc: core: fix improper clock frequency being passed to set_ios
This bug was introduced in the 'MMC-4.5 Power OFF Notify Rework' fix.
Prior to the aforementioned patch, during resume mmc_init_card was being
invoked. The aforesaid patch invokes mmc_card_awake, prior to which
mmc_power_up has already set the clock frequency to 400Khz. Since the card
init is not done again, this frequency stays as is and results in data
time-out errors.
Two new functions
* mmc_save_ios
* mmc_restore_ios
were added.
The mmc_save_ios is invoked during mmc_suspend process and it saves the
current ios values, while mmc_restore_ios is invoked during mmc_resume process
and restores the previous ios values before sending the awake command. This
ensures that the clock, timing, bus-width etc are set properly before any
request is sent to the driver.
Signed-off-by: Asutosh Das <asutoshd@codeaurora.org>
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index cb7ccd6..3438bc91 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -1431,6 +1431,31 @@
}
/*
+ * Save ios settings
+ */
+static void mmc_save_ios(struct mmc_host *host)
+{
+ BUG_ON(!host);
+
+ mmc_host_clk_hold(host);
+
+ memcpy(&host->saved_ios, &host->ios, sizeof(struct mmc_ios));
+
+ mmc_host_clk_release(host);
+}
+
+/*
+ * Restore ios setting
+ */
+static void mmc_restore_ios(struct mmc_host *host)
+{
+ BUG_ON(!host);
+
+ memcpy(&host->ios, &host->saved_ios, sizeof(struct mmc_ios));
+ mmc_set_ios(host);
+}
+
+/*
* Suspend callback from host.
*/
static int mmc_suspend(struct mmc_host *host)
@@ -1441,6 +1466,7 @@
BUG_ON(!host->card);
mmc_claim_host(host);
+ mmc_save_ios(host);
if (mmc_can_poweroff_notify(host->card) &&
(host->caps2 & MMC_CAP2_POWER_OFF_VCCQ_DURING_SUSPEND)) {
err = mmc_poweroff_notify(host, MMC_PW_OFF_NOTIFY_SHORT);
@@ -1473,6 +1499,7 @@
mmc_claim_host(host);
if (mmc_card_is_sleep(host->card)) {
+ mmc_restore_ios(host);
err = mmc_card_awake(host);
} else
err = mmc_init_card(host, host->ocr, host->card);
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index 4d948ea..71484da 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -355,6 +355,7 @@
bool perf_enable;
#endif
+ struct mmc_ios saved_ios;
unsigned long private[0] ____cacheline_aligned;
};