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: Daniel Drake <dsd@laptop.org>
Signed-off-by: Chris Ball <cjb@laptop.org>

authored by

Daniel Drake and committed by
Chris Ball
c6e633ad e9e8bcb8

+39
+39
drivers/mmc/core/sdio.c
··· 691 691 static int mmc_sdio_power_restore(struct mmc_host *host) 692 692 { 693 693 int ret; 694 + u32 ocr; 694 695 695 696 BUG_ON(!host); 696 697 BUG_ON(!host->card); 697 698 698 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 736 ret = mmc_sdio_init_card(host, host->ocr, host->card, 700 737 mmc_card_keep_power(host)); 701 738 if (!ret && host->sdio_irqs) 702 739 mmc_signal_sdio_irq(host); 740 + 741 + out: 703 742 mmc_release_host(host); 704 743 705 744 return ret;