diff options
author | Ulf Hansson <ulf.hansson@linaro.org> | 2013-10-24 10:42:33 -0400 |
---|---|---|
committer | Ulf Hansson <ulf.hansson@linaro.org> | 2014-09-09 07:59:08 -0400 |
commit | 0369483efc1719f47249fa94329aa94155edf69d (patch) | |
tree | 770e6f1460f5214798d99917f010abd683a5fbf8 /drivers/mmc/host/tmio_mmc_pio.c | |
parent | 7501c4315faf46b088ed4de4d8695a91d7d63869 (diff) |
mmc: tmio: Keep host active while serving requests
Use runtime PM to keep the host active during I/O operations and other
requests which requires the tmio hardware to be powered.
Additionally make use of the runtime PM autosuspend feature with a
default timeout of 50 ms.
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Acked-by: Geert Uytterhoeven <geert+renesas@glider.be>
Diffstat (limited to 'drivers/mmc/host/tmio_mmc_pio.c')
-rw-r--r-- | drivers/mmc/host/tmio_mmc_pio.c | 55 |
1 files changed, 32 insertions, 23 deletions
diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c index 5c2e5a36258a..d63d292933b4 100644 --- a/drivers/mmc/host/tmio_mmc_pio.c +++ b/drivers/mmc/host/tmio_mmc_pio.c | |||
@@ -144,7 +144,8 @@ static void tmio_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable) | |||
144 | sd_ctrl_write16(host, CTL_TRANSACTION_CTL, 0x0000); | 144 | sd_ctrl_write16(host, CTL_TRANSACTION_CTL, 0x0000); |
145 | 145 | ||
146 | host->sdio_irq_enabled = false; | 146 | host->sdio_irq_enabled = false; |
147 | pm_runtime_put(mmc_dev(mmc)); | 147 | pm_runtime_mark_last_busy(mmc_dev(mmc)); |
148 | pm_runtime_put_autosuspend(mmc_dev(mmc)); | ||
148 | } | 149 | } |
149 | } | 150 | } |
150 | 151 | ||
@@ -252,6 +253,9 @@ static void tmio_mmc_reset_work(struct work_struct *work) | |||
252 | 253 | ||
253 | tmio_mmc_abort_dma(host); | 254 | tmio_mmc_abort_dma(host); |
254 | mmc_request_done(host->mmc, mrq); | 255 | mmc_request_done(host->mmc, mrq); |
256 | |||
257 | pm_runtime_mark_last_busy(mmc_dev(host->mmc)); | ||
258 | pm_runtime_put_autosuspend(mmc_dev(host->mmc)); | ||
255 | } | 259 | } |
256 | 260 | ||
257 | /* called with host->lock held, interrupts disabled */ | 261 | /* called with host->lock held, interrupts disabled */ |
@@ -281,6 +285,9 @@ static void tmio_mmc_finish_request(struct tmio_mmc_host *host) | |||
281 | tmio_mmc_abort_dma(host); | 285 | tmio_mmc_abort_dma(host); |
282 | 286 | ||
283 | mmc_request_done(host->mmc, mrq); | 287 | mmc_request_done(host->mmc, mrq); |
288 | |||
289 | pm_runtime_mark_last_busy(mmc_dev(host->mmc)); | ||
290 | pm_runtime_put_autosuspend(mmc_dev(host->mmc)); | ||
284 | } | 291 | } |
285 | 292 | ||
286 | static void tmio_mmc_done_work(struct work_struct *work) | 293 | static void tmio_mmc_done_work(struct work_struct *work) |
@@ -735,6 +742,8 @@ static void tmio_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq) | |||
735 | 742 | ||
736 | spin_unlock_irqrestore(&host->lock, flags); | 743 | spin_unlock_irqrestore(&host->lock, flags); |
737 | 744 | ||
745 | pm_runtime_get_sync(mmc_dev(mmc)); | ||
746 | |||
738 | if (mrq->data) { | 747 | if (mrq->data) { |
739 | ret = tmio_mmc_start_data(host, mrq->data); | 748 | ret = tmio_mmc_start_data(host, mrq->data); |
740 | if (ret) | 749 | if (ret) |
@@ -753,6 +762,9 @@ fail: | |||
753 | host->mrq = NULL; | 762 | host->mrq = NULL; |
754 | mrq->cmd->error = ret; | 763 | mrq->cmd->error = ret; |
755 | mmc_request_done(mmc, mrq); | 764 | mmc_request_done(mmc, mrq); |
765 | |||
766 | pm_runtime_mark_last_busy(mmc_dev(mmc)); | ||
767 | pm_runtime_put_autosuspend(mmc_dev(mmc)); | ||
756 | } | 768 | } |
757 | 769 | ||
758 | static int tmio_mmc_clk_update(struct mmc_host *mmc) | 770 | static int tmio_mmc_clk_update(struct mmc_host *mmc) |
@@ -831,6 +843,8 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
831 | struct device *dev = &host->pdev->dev; | 843 | struct device *dev = &host->pdev->dev; |
832 | unsigned long flags; | 844 | unsigned long flags; |
833 | 845 | ||
846 | pm_runtime_get_sync(mmc_dev(mmc)); | ||
847 | |||
834 | mutex_lock(&host->ios_lock); | 848 | mutex_lock(&host->ios_lock); |
835 | 849 | ||
836 | spin_lock_irqsave(&host->lock, flags); | 850 | spin_lock_irqsave(&host->lock, flags); |
@@ -866,7 +880,6 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
866 | if (ios->power_mode == MMC_POWER_ON && ios->clock) { | 880 | if (ios->power_mode == MMC_POWER_ON && ios->clock) { |
867 | if (host->power != TMIO_MMC_ON_RUN) { | 881 | if (host->power != TMIO_MMC_ON_RUN) { |
868 | tmio_mmc_clk_update(mmc); | 882 | tmio_mmc_clk_update(mmc); |
869 | pm_runtime_get_sync(dev); | ||
870 | if (host->resuming) { | 883 | if (host->resuming) { |
871 | tmio_mmc_reset(host); | 884 | tmio_mmc_reset(host); |
872 | host->resuming = false; | 885 | host->resuming = false; |
@@ -896,7 +909,6 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
896 | 909 | ||
897 | if (old_power == TMIO_MMC_ON_RUN) { | 910 | if (old_power == TMIO_MMC_ON_RUN) { |
898 | tmio_mmc_clk_stop(host); | 911 | tmio_mmc_clk_stop(host); |
899 | pm_runtime_put(dev); | ||
900 | if (pdata->clk_disable) | 912 | if (pdata->clk_disable) |
901 | pdata->clk_disable(host->pdev); | 913 | pdata->clk_disable(host->pdev); |
902 | } | 914 | } |
@@ -923,6 +935,9 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
923 | host->mrq = NULL; | 935 | host->mrq = NULL; |
924 | 936 | ||
925 | mutex_unlock(&host->ios_lock); | 937 | mutex_unlock(&host->ios_lock); |
938 | |||
939 | pm_runtime_mark_last_busy(mmc_dev(mmc)); | ||
940 | pm_runtime_put_autosuspend(mmc_dev(mmc)); | ||
926 | } | 941 | } |
927 | 942 | ||
928 | static int tmio_mmc_get_ro(struct mmc_host *mmc) | 943 | static int tmio_mmc_get_ro(struct mmc_host *mmc) |
@@ -933,8 +948,13 @@ static int tmio_mmc_get_ro(struct mmc_host *mmc) | |||
933 | if (ret >= 0) | 948 | if (ret >= 0) |
934 | return ret; | 949 | return ret; |
935 | 950 | ||
936 | return !((pdata->flags & TMIO_MMC_WRPROTECT_DISABLE) || | 951 | pm_runtime_get_sync(mmc_dev(mmc)); |
937 | (sd_ctrl_read32(host, CTL_STATUS) & TMIO_STAT_WRPROTECT)); | 952 | ret = !((pdata->flags & TMIO_MMC_WRPROTECT_DISABLE) || |
953 | (sd_ctrl_read32(host, CTL_STATUS) & TMIO_STAT_WRPROTECT)); | ||
954 | pm_runtime_mark_last_busy(mmc_dev(mmc)); | ||
955 | pm_runtime_put_autosuspend(mmc_dev(mmc)); | ||
956 | |||
957 | return ret; | ||
938 | } | 958 | } |
939 | 959 | ||
940 | static const struct mmc_host_ops tmio_mmc_ops = { | 960 | static const struct mmc_host_ops tmio_mmc_ops = { |
@@ -1040,27 +1060,14 @@ int tmio_mmc_host_probe(struct tmio_mmc_host **host, | |||
1040 | mmc->slot.cd_irq >= 0); | 1060 | mmc->slot.cd_irq >= 0); |
1041 | 1061 | ||
1042 | _host->power = TMIO_MMC_OFF_STOP; | 1062 | _host->power = TMIO_MMC_OFF_STOP; |
1043 | pm_runtime_enable(&pdev->dev); | ||
1044 | ret = pm_runtime_resume(&pdev->dev); | ||
1045 | if (ret < 0) | ||
1046 | goto pm_disable; | ||
1047 | |||
1048 | if (tmio_mmc_clk_update(mmc) < 0) { | 1063 | if (tmio_mmc_clk_update(mmc) < 0) { |
1049 | mmc->f_max = pdata->hclk; | 1064 | mmc->f_max = pdata->hclk; |
1050 | mmc->f_min = mmc->f_max / 512; | 1065 | mmc->f_min = mmc->f_max / 512; |
1051 | } | 1066 | } |
1052 | 1067 | ||
1053 | /* | 1068 | /* |
1054 | * There are 4 different scenarios for the card detection: | 1069 | * While using internal tmio hardware logic for card detection, we need |
1055 | * 1) an external gpio irq handles the cd (best for power savings) | 1070 | * to ensure it stays powered for it to work. |
1056 | * 2) internal sdhi irq handles the cd | ||
1057 | * 3) a worker thread polls the sdhi - indicated by MMC_CAP_NEEDS_POLL | ||
1058 | * 4) the medium is non-removable - indicated by MMC_CAP_NONREMOVABLE | ||
1059 | * | ||
1060 | * While we increment the runtime PM counter for all scenarios when | ||
1061 | * the mmc core activates us by calling an appropriate set_ios(), we | ||
1062 | * must additionally ensure that in case 2) the tmio mmc hardware stays | ||
1063 | * powered on during runtime for the card detection to work. | ||
1064 | */ | 1071 | */ |
1065 | if (_host->native_hotplug) | 1072 | if (_host->native_hotplug) |
1066 | pm_runtime_get_noresume(&pdev->dev); | 1073 | pm_runtime_get_noresume(&pdev->dev); |
@@ -1098,6 +1105,11 @@ int tmio_mmc_host_probe(struct tmio_mmc_host **host, | |||
1098 | /* See if we also get DMA */ | 1105 | /* See if we also get DMA */ |
1099 | tmio_mmc_request_dma(_host, pdata); | 1106 | tmio_mmc_request_dma(_host, pdata); |
1100 | 1107 | ||
1108 | pm_runtime_set_active(&pdev->dev); | ||
1109 | pm_runtime_set_autosuspend_delay(&pdev->dev, 50); | ||
1110 | pm_runtime_use_autosuspend(&pdev->dev); | ||
1111 | pm_runtime_enable(&pdev->dev); | ||
1112 | |||
1101 | ret = mmc_add_host(mmc); | 1113 | ret = mmc_add_host(mmc); |
1102 | if (pdata->clk_disable) | 1114 | if (pdata->clk_disable) |
1103 | pdata->clk_disable(pdev); | 1115 | pdata->clk_disable(pdev); |
@@ -1120,9 +1132,6 @@ int tmio_mmc_host_probe(struct tmio_mmc_host **host, | |||
1120 | 1132 | ||
1121 | return 0; | 1133 | return 0; |
1122 | 1134 | ||
1123 | pm_disable: | ||
1124 | pm_runtime_disable(&pdev->dev); | ||
1125 | iounmap(_host->ctl); | ||
1126 | host_free: | 1135 | host_free: |
1127 | mmc_free_host(mmc); | 1136 | mmc_free_host(mmc); |
1128 | 1137 | ||