Commit c6e633ad authored by Daniel Drake's avatar Daniel Drake Committed by Chris Ball

mmc: sdio: reset card during power_restore

mmc_sdio_power_restore() skips some steps that are performed in other
power-related codepaths which are necessary to fully reset the card.
Without this, runtime PM fails for SD8686 SDIO wifi on OLPC XO-1.5.
Signed-off-by: default avatarDaniel Drake <dsd@laptop.org>
Signed-off-by: default avatarChris Ball <cjb@laptop.org>
parent e9e8bcb8
...@@ -691,15 +691,54 @@ static int mmc_sdio_resume(struct mmc_host *host) ...@@ -691,15 +691,54 @@ static int mmc_sdio_resume(struct mmc_host *host)
static int mmc_sdio_power_restore(struct mmc_host *host) static int mmc_sdio_power_restore(struct mmc_host *host)
{ {
int ret; int ret;
u32 ocr;
BUG_ON(!host); BUG_ON(!host);
BUG_ON(!host->card); BUG_ON(!host->card);
mmc_claim_host(host); mmc_claim_host(host);
/*
* Reset the card by performing the same steps that are taken by
* mmc_rescan_try_freq() and mmc_attach_sdio() during a "normal" probe.
*
* sdio_reset() is technically not needed. Having just powered up the
* hardware, it should already be in reset state. However, some
* platforms (such as SD8686 on OLPC) do not instantly cut power,
* meaning that a reset is required when restoring power soon after
* powering off. It is harmless in other cases.
*
* The CMD5 reset (mmc_send_io_op_cond()), according to the SDIO spec,
* is not necessary for non-removable cards. However, it is required
* for OLPC SD8686 (which expects a [CMD5,5,3,7] init sequence), and
* harmless in other situations.
*
* With these steps taken, mmc_select_voltage() is also required to
* restore the correct voltage setting of the card.
*/
sdio_reset(host);
mmc_go_idle(host);
mmc_send_if_cond(host, host->ocr_avail);
ret = mmc_send_io_op_cond(host, 0, &ocr);
if (ret)
goto out;
if (host->ocr_avail_sdio)
host->ocr_avail = host->ocr_avail_sdio;
host->ocr = mmc_select_voltage(host, ocr & ~0x7F);
if (!host->ocr) {
ret = -EINVAL;
goto out;
}
ret = mmc_sdio_init_card(host, host->ocr, host->card, ret = mmc_sdio_init_card(host, host->ocr, host->card,
mmc_card_keep_power(host)); mmc_card_keep_power(host));
if (!ret && host->sdio_irqs) if (!ret && host->sdio_irqs)
mmc_signal_sdio_irq(host); mmc_signal_sdio_irq(host);
out:
mmc_release_host(host); mmc_release_host(host);
return ret; return ret;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment