diff options
| -rw-r--r-- | drivers/mmc/core/sdio.c | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index 4d0c15bfa514..262fff019177 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c | |||
| @@ -691,15 +691,54 @@ static int mmc_sdio_resume(struct mmc_host *host) | |||
| 691 | static int mmc_sdio_power_restore(struct mmc_host *host) | 691 | static int mmc_sdio_power_restore(struct mmc_host *host) |
| 692 | { | 692 | { |
| 693 | int ret; | 693 | int ret; |
| 694 | u32 ocr; | ||
| 694 | 695 | ||
| 695 | BUG_ON(!host); | 696 | BUG_ON(!host); |
| 696 | BUG_ON(!host->card); | 697 | BUG_ON(!host->card); |
| 697 | 698 | ||
| 698 | mmc_claim_host(host); | 699 | mmc_claim_host(host); |
| 700 | |||
| 701 | /* | ||
| 702 | * Reset the card by performing the same steps that are taken by | ||
| 703 | * mmc_rescan_try_freq() and mmc_attach_sdio() during a "normal" probe. | ||
| 704 | * | ||
| 705 | * sdio_reset() is technically not needed. Having just powered up the | ||
| 706 | * hardware, it should already be in reset state. However, some | ||
| 707 | * platforms (such as SD8686 on OLPC) do not instantly cut power, | ||
| 708 | * meaning that a reset is required when restoring power soon after | ||
| 709 | * powering off. It is harmless in other cases. | ||
| 710 | * | ||
| 711 | * The CMD5 reset (mmc_send_io_op_cond()), according to the SDIO spec, | ||
| 712 | * is not necessary for non-removable cards. However, it is required | ||
| 713 | * for OLPC SD8686 (which expects a [CMD5,5,3,7] init sequence), and | ||
| 714 | * harmless in other situations. | ||
| 715 | * | ||
| 716 | * With these steps taken, mmc_select_voltage() is also required to | ||
| 717 | * restore the correct voltage setting of the card. | ||
| 718 | */ | ||
| 719 | sdio_reset(host); | ||
| 720 | mmc_go_idle(host); | ||
| 721 | mmc_send_if_cond(host, host->ocr_avail); | ||
| 722 | |||
| 723 | ret = mmc_send_io_op_cond(host, 0, &ocr); | ||
| 724 | if (ret) | ||
| 725 | goto out; | ||
| 726 | |||
| 727 | if (host->ocr_avail_sdio) | ||
| 728 | host->ocr_avail = host->ocr_avail_sdio; | ||
| 729 | |||
| 730 | host->ocr = mmc_select_voltage(host, ocr & ~0x7F); | ||
| 731 | if (!host->ocr) { | ||
| 732 | ret = -EINVAL; | ||
| 733 | goto out; | ||
| 734 | } | ||
| 735 | |||
| 699 | ret = mmc_sdio_init_card(host, host->ocr, host->card, | 736 | ret = mmc_sdio_init_card(host, host->ocr, host->card, |
| 700 | mmc_card_keep_power(host)); | 737 | mmc_card_keep_power(host)); |
| 701 | if (!ret && host->sdio_irqs) | 738 | if (!ret && host->sdio_irqs) |
| 702 | mmc_signal_sdio_irq(host); | 739 | mmc_signal_sdio_irq(host); |
| 740 | |||
| 741 | out: | ||
| 703 | mmc_release_host(host); | 742 | mmc_release_host(host); |
| 704 | 743 | ||
| 705 | return ret; | 744 | return ret; |
