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>
This commit is contained in:
committed by
Stephen Boyd
parent
06d8e2a3ad
commit
460cee698a
@@ -1430,6 +1430,31 @@ static void mmc_detect(struct mmc_host *host)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.
|
* Suspend callback from host.
|
||||||
*/
|
*/
|
||||||
@@ -1441,6 +1466,7 @@ static int mmc_suspend(struct mmc_host *host)
|
|||||||
BUG_ON(!host->card);
|
BUG_ON(!host->card);
|
||||||
|
|
||||||
mmc_claim_host(host);
|
mmc_claim_host(host);
|
||||||
|
mmc_save_ios(host);
|
||||||
if (mmc_can_poweroff_notify(host->card) &&
|
if (mmc_can_poweroff_notify(host->card) &&
|
||||||
(host->caps2 & MMC_CAP2_POWER_OFF_VCCQ_DURING_SUSPEND)) {
|
(host->caps2 & MMC_CAP2_POWER_OFF_VCCQ_DURING_SUSPEND)) {
|
||||||
err = mmc_poweroff_notify(host, MMC_PW_OFF_NOTIFY_SHORT);
|
err = mmc_poweroff_notify(host, MMC_PW_OFF_NOTIFY_SHORT);
|
||||||
@@ -1473,6 +1499,7 @@ static int mmc_resume(struct mmc_host *host)
|
|||||||
|
|
||||||
mmc_claim_host(host);
|
mmc_claim_host(host);
|
||||||
if (mmc_card_is_sleep(host->card)) {
|
if (mmc_card_is_sleep(host->card)) {
|
||||||
|
mmc_restore_ios(host);
|
||||||
err = mmc_card_awake(host);
|
err = mmc_card_awake(host);
|
||||||
} else
|
} else
|
||||||
err = mmc_init_card(host, host->ocr, host->card);
|
err = mmc_init_card(host, host->ocr, host->card);
|
||||||
|
|||||||
@@ -352,6 +352,7 @@ struct mmc_host {
|
|||||||
} perf;
|
} perf;
|
||||||
bool perf_enable;
|
bool perf_enable;
|
||||||
#endif
|
#endif
|
||||||
|
struct mmc_ios saved_ios;
|
||||||
unsigned long private[0] ____cacheline_aligned;
|
unsigned long private[0] ____cacheline_aligned;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user