diff options
Diffstat (limited to 'drivers/mmc/host/tmio_mmc_pio.c')
-rw-r--r-- | drivers/mmc/host/tmio_mmc_pio.c | 57 |
1 files changed, 54 insertions, 3 deletions
diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c index 710339a85c84..8b05d3ceb29c 100644 --- a/drivers/mmc/host/tmio_mmc_pio.c +++ b/drivers/mmc/host/tmio_mmc_pio.c | |||
@@ -39,6 +39,7 @@ | |||
39 | #include <linux/module.h> | 39 | #include <linux/module.h> |
40 | #include <linux/pagemap.h> | 40 | #include <linux/pagemap.h> |
41 | #include <linux/platform_device.h> | 41 | #include <linux/platform_device.h> |
42 | #include <linux/pm_runtime.h> | ||
42 | #include <linux/scatterlist.h> | 43 | #include <linux/scatterlist.h> |
43 | #include <linux/workqueue.h> | 44 | #include <linux/workqueue.h> |
44 | #include <linux/spinlock.h> | 45 | #include <linux/spinlock.h> |
@@ -834,12 +835,17 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host, | |||
834 | else | 835 | else |
835 | mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; | 836 | mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; |
836 | 837 | ||
838 | pm_runtime_enable(&pdev->dev); | ||
839 | ret = pm_runtime_resume(&pdev->dev); | ||
840 | if (ret < 0) | ||
841 | goto pm_disable; | ||
842 | |||
837 | tmio_mmc_clk_stop(_host); | 843 | tmio_mmc_clk_stop(_host); |
838 | tmio_mmc_reset(_host); | 844 | tmio_mmc_reset(_host); |
839 | 845 | ||
840 | ret = platform_get_irq(pdev, 0); | 846 | ret = platform_get_irq(pdev, 0); |
841 | if (ret < 0) | 847 | if (ret < 0) |
842 | goto unmap_ctl; | 848 | goto pm_suspend; |
843 | 849 | ||
844 | _host->irq = ret; | 850 | _host->irq = ret; |
845 | 851 | ||
@@ -850,7 +856,7 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host, | |||
850 | ret = request_irq(_host->irq, tmio_mmc_irq, IRQF_DISABLED | | 856 | ret = request_irq(_host->irq, tmio_mmc_irq, IRQF_DISABLED | |
851 | IRQF_TRIGGER_FALLING, dev_name(&pdev->dev), _host); | 857 | IRQF_TRIGGER_FALLING, dev_name(&pdev->dev), _host); |
852 | if (ret) | 858 | if (ret) |
853 | goto unmap_ctl; | 859 | goto pm_suspend; |
854 | 860 | ||
855 | spin_lock_init(&_host->lock); | 861 | spin_lock_init(&_host->lock); |
856 | 862 | ||
@@ -860,6 +866,9 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host, | |||
860 | /* See if we also get DMA */ | 866 | /* See if we also get DMA */ |
861 | tmio_mmc_request_dma(_host, pdata); | 867 | tmio_mmc_request_dma(_host, pdata); |
862 | 868 | ||
869 | /* We have to keep the device powered for its card detection to work */ | ||
870 | pm_runtime_get_noresume(&pdev->dev); | ||
871 | |||
863 | mmc_add_host(mmc); | 872 | mmc_add_host(mmc); |
864 | 873 | ||
865 | /* Unmask the IRQs we want to know about */ | 874 | /* Unmask the IRQs we want to know about */ |
@@ -874,7 +883,10 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host, | |||
874 | 883 | ||
875 | return 0; | 884 | return 0; |
876 | 885 | ||
877 | unmap_ctl: | 886 | pm_suspend: |
887 | pm_runtime_suspend(&pdev->dev); | ||
888 | pm_disable: | ||
889 | pm_runtime_disable(&pdev->dev); | ||
878 | iounmap(_host->ctl); | 890 | iounmap(_host->ctl); |
879 | host_free: | 891 | host_free: |
880 | mmc_free_host(mmc); | 892 | mmc_free_host(mmc); |
@@ -885,13 +897,52 @@ EXPORT_SYMBOL(tmio_mmc_host_probe); | |||
885 | 897 | ||
886 | void tmio_mmc_host_remove(struct tmio_mmc_host *host) | 898 | void tmio_mmc_host_remove(struct tmio_mmc_host *host) |
887 | { | 899 | { |
900 | struct platform_device *pdev = host->pdev; | ||
901 | |||
888 | mmc_remove_host(host->mmc); | 902 | mmc_remove_host(host->mmc); |
889 | cancel_delayed_work_sync(&host->delayed_reset_work); | 903 | cancel_delayed_work_sync(&host->delayed_reset_work); |
890 | tmio_mmc_release_dma(host); | 904 | tmio_mmc_release_dma(host); |
891 | free_irq(host->irq, host); | 905 | free_irq(host->irq, host); |
892 | iounmap(host->ctl); | 906 | iounmap(host->ctl); |
893 | mmc_free_host(host->mmc); | 907 | mmc_free_host(host->mmc); |
908 | |||
909 | /* Compensate for pm_runtime_get_sync() in probe() above */ | ||
910 | pm_runtime_put_sync(&pdev->dev); | ||
911 | pm_runtime_disable(&pdev->dev); | ||
894 | } | 912 | } |
895 | EXPORT_SYMBOL(tmio_mmc_host_remove); | 913 | EXPORT_SYMBOL(tmio_mmc_host_remove); |
896 | 914 | ||
915 | #ifdef CONFIG_PM | ||
916 | int tmio_mmc_host_suspend(struct device *dev) | ||
917 | { | ||
918 | struct mmc_host *mmc = dev_get_drvdata(dev); | ||
919 | struct tmio_mmc_host *host = mmc_priv(mmc); | ||
920 | int ret = mmc_suspend_host(mmc); | ||
921 | |||
922 | if (!ret) | ||
923 | tmio_mmc_disable_mmc_irqs(host, TMIO_MASK_ALL); | ||
924 | |||
925 | host->pm_error = pm_runtime_put_sync(dev); | ||
926 | |||
927 | return ret; | ||
928 | } | ||
929 | EXPORT_SYMBOL(tmio_mmc_host_suspend); | ||
930 | |||
931 | int tmio_mmc_host_resume(struct device *dev) | ||
932 | { | ||
933 | struct mmc_host *mmc = dev_get_drvdata(dev); | ||
934 | struct tmio_mmc_host *host = mmc_priv(mmc); | ||
935 | |||
936 | if (!host->pm_error) | ||
937 | pm_runtime_get_sync(dev); | ||
938 | |||
939 | tmio_mmc_reset(mmc_priv(mmc)); | ||
940 | tmio_mmc_request_dma(host, host->pdata); | ||
941 | |||
942 | return mmc_resume_host(mmc); | ||
943 | } | ||
944 | EXPORT_SYMBOL(tmio_mmc_host_resume); | ||
945 | |||
946 | #endif /* CONFIG_PM */ | ||
947 | |||
897 | MODULE_LICENSE("GPL v2"); | 948 | MODULE_LICENSE("GPL v2"); |