aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc
diff options
context:
space:
mode:
authorGuennadi Liakhovetski <g.liakhovetski@gmx.de>2011-05-11 12:51:11 -0400
committerChris Ball <cjb@laptop.org>2011-05-24 23:53:55 -0400
commit7311bef0697bcfbbcb898c3c22e61e23f203ae9d (patch)
tree0ef14a5a255472ba32473c54679af43866265387 /drivers/mmc
parentd6a1f863433bdf3f8406dedfa33fa79ee9259db3 (diff)
mmc: tmio: runtime suspend the controller, where possible
The TMIO MMC controller cannot be powered off to save power, when no card is plugged in, because then it will not be able to detect a new card-insertion event. On some implementations, however, it is possible to switch to using another source to detect card insertion. This patch adds support for such implementations. Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/host/tmio_mmc.h3
-rw-r--r--drivers/mmc/host/tmio_mmc_pio.c64
2 files changed, 61 insertions, 6 deletions
diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h
index c6bf726c8f44..8260bc2c34e3 100644
--- a/drivers/mmc/host/tmio_mmc.h
+++ b/drivers/mmc/host/tmio_mmc.h
@@ -131,4 +131,7 @@ int tmio_mmc_host_resume(struct device *dev);
131#define tmio_mmc_host_resume NULL 131#define tmio_mmc_host_resume NULL
132#endif 132#endif
133 133
134int tmio_mmc_host_runtime_suspend(struct device *dev);
135int tmio_mmc_host_runtime_resume(struct device *dev);
136
134#endif 137#endif
diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c
index af5d4f6d2233..ad6347bb02dd 100644
--- a/drivers/mmc/host/tmio_mmc_pio.c
+++ b/drivers/mmc/host/tmio_mmc_pio.c
@@ -746,6 +746,7 @@ fail:
746static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) 746static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
747{ 747{
748 struct tmio_mmc_host *host = mmc_priv(mmc); 748 struct tmio_mmc_host *host = mmc_priv(mmc);
749 struct tmio_mmc_data *pdata = host->pdata;
749 unsigned long flags; 750 unsigned long flags;
750 751
751 spin_lock_irqsave(&host->lock, flags); 752 spin_lock_irqsave(&host->lock, flags);
@@ -775,13 +776,24 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
775 776
776 /* Power sequence - OFF -> UP -> ON */ 777 /* Power sequence - OFF -> UP -> ON */
777 if (ios->power_mode == MMC_POWER_UP) { 778 if (ios->power_mode == MMC_POWER_UP) {
779 if ((pdata->flags & TMIO_MMC_HAS_COLD_CD) && !pdata->power) {
780 pm_runtime_get_sync(&host->pdev->dev);
781 pdata->power = true;
782 }
778 /* power up SD bus */ 783 /* power up SD bus */
779 if (host->set_pwr) 784 if (host->set_pwr)
780 host->set_pwr(host->pdev, 1); 785 host->set_pwr(host->pdev, 1);
781 } else if (ios->power_mode == MMC_POWER_OFF || !ios->clock) { 786 } else if (ios->power_mode == MMC_POWER_OFF || !ios->clock) {
782 /* power down SD bus */ 787 /* power down SD bus */
783 if (ios->power_mode == MMC_POWER_OFF && host->set_pwr) 788 if (ios->power_mode == MMC_POWER_OFF) {
784 host->set_pwr(host->pdev, 0); 789 if (host->set_pwr)
790 host->set_pwr(host->pdev, 0);
791 if ((pdata->flags & TMIO_MMC_HAS_COLD_CD) &&
792 pdata->power) {
793 pdata->power = false;
794 pm_runtime_put(&host->pdev->dev);
795 }
796 }
785 tmio_mmc_clk_stop(host); 797 tmio_mmc_clk_stop(host);
786 } else { 798 } else {
787 /* start bus clock */ 799 /* start bus clock */
@@ -853,6 +865,7 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,
853 if (!mmc) 865 if (!mmc)
854 return -ENOMEM; 866 return -ENOMEM;
855 867
868 pdata->dev = &pdev->dev;
856 _host = mmc_priv(mmc); 869 _host = mmc_priv(mmc);
857 _host->pdata = pdata; 870 _host->pdata = pdata;
858 _host->mmc = mmc; 871 _host->mmc = mmc;
@@ -886,6 +899,7 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,
886 else 899 else
887 mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; 900 mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
888 901
902 pdata->power = false;
889 pm_runtime_enable(&pdev->dev); 903 pm_runtime_enable(&pdev->dev);
890 ret = pm_runtime_resume(&pdev->dev); 904 ret = pm_runtime_resume(&pdev->dev);
891 if (ret < 0) 905 if (ret < 0)
@@ -907,7 +921,8 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,
907 tmio_mmc_request_dma(_host, pdata); 921 tmio_mmc_request_dma(_host, pdata);
908 922
909 /* We have to keep the device powered for its card detection to work */ 923 /* We have to keep the device powered for its card detection to work */
910 pm_runtime_get_noresume(&pdev->dev); 924 if (!(pdata->flags & TMIO_MMC_HAS_COLD_CD))
925 pm_runtime_get_noresume(&pdev->dev);
911 926
912 mmc_add_host(mmc); 927 mmc_add_host(mmc);
913 928
@@ -937,15 +952,25 @@ void tmio_mmc_host_remove(struct tmio_mmc_host *host)
937{ 952{
938 struct platform_device *pdev = host->pdev; 953 struct platform_device *pdev = host->pdev;
939 954
955 /*
956 * We don't have to manipulate pdata->power here: if there is a card in
957 * the slot, the runtime PM is active and our .runtime_resume() will not
958 * be run. If there is no card in the slot and the platform can suspend
959 * the controller, the runtime PM is suspended and pdata->power == false,
960 * so, our .runtime_resume() will not try to detect a card in the slot.
961 */
962 if (host->pdata->flags & TMIO_MMC_HAS_COLD_CD)
963 pm_runtime_get_sync(&pdev->dev);
964
940 mmc_remove_host(host->mmc); 965 mmc_remove_host(host->mmc);
941 cancel_delayed_work_sync(&host->delayed_reset_work); 966 cancel_delayed_work_sync(&host->delayed_reset_work);
942 tmio_mmc_release_dma(host); 967 tmio_mmc_release_dma(host);
943 iounmap(host->ctl);
944 mmc_free_host(host->mmc);
945 968
946 /* Compensate for pm_runtime_get_sync() in probe() above */
947 pm_runtime_put_sync(&pdev->dev); 969 pm_runtime_put_sync(&pdev->dev);
948 pm_runtime_disable(&pdev->dev); 970 pm_runtime_disable(&pdev->dev);
971
972 iounmap(host->ctl);
973 mmc_free_host(host->mmc);
949} 974}
950EXPORT_SYMBOL(tmio_mmc_host_remove); 975EXPORT_SYMBOL(tmio_mmc_host_remove);
951 976
@@ -970,6 +995,9 @@ int tmio_mmc_host_resume(struct device *dev)
970 struct mmc_host *mmc = dev_get_drvdata(dev); 995 struct mmc_host *mmc = dev_get_drvdata(dev);
971 struct tmio_mmc_host *host = mmc_priv(mmc); 996 struct tmio_mmc_host *host = mmc_priv(mmc);
972 997
998 /* The MMC core will perform the complete set up */
999 host->pdata->power = false;
1000
973 if (!host->pm_error) 1001 if (!host->pm_error)
974 pm_runtime_get_sync(dev); 1002 pm_runtime_get_sync(dev);
975 1003
@@ -982,4 +1010,28 @@ EXPORT_SYMBOL(tmio_mmc_host_resume);
982 1010
983#endif /* CONFIG_PM */ 1011#endif /* CONFIG_PM */
984 1012
1013int tmio_mmc_host_runtime_suspend(struct device *dev)
1014{
1015 return 0;
1016}
1017EXPORT_SYMBOL(tmio_mmc_host_runtime_suspend);
1018
1019int tmio_mmc_host_runtime_resume(struct device *dev)
1020{
1021 struct mmc_host *mmc = dev_get_drvdata(dev);
1022 struct tmio_mmc_host *host = mmc_priv(mmc);
1023 struct tmio_mmc_data *pdata = host->pdata;
1024
1025 tmio_mmc_reset(host);
1026
1027 if (pdata->power) {
1028 /* Only entered after a card-insert interrupt */
1029 tmio_mmc_set_ios(mmc, &mmc->ios);
1030 mmc_detect_change(mmc, msecs_to_jiffies(100));
1031 }
1032
1033 return 0;
1034}
1035EXPORT_SYMBOL(tmio_mmc_host_runtime_resume);
1036
985MODULE_LICENSE("GPL v2"); 1037MODULE_LICENSE("GPL v2");