aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/host/sh_mmcif.c
diff options
context:
space:
mode:
authorGuennadi Liakhovetski <g.liakhovetski@gmx.de>2011-05-26 09:33:30 -0400
committerChris Ball <cjb@laptop.org>2011-07-21 10:35:06 -0400
commitc9b0cef23f8d2a16c97623d25d6e8f8e93a56e4b (patch)
treee611d4955d57d3be4593bbc1fa40c1a6468bbd40 /drivers/mmc/host/sh_mmcif.c
parent71d111cd34ee119c93d056ad9e84dc0e82367f82 (diff)
mmc: sh_mmcif: maximize power saving
This patch uses runtime PM to allow the system to power down the MMC controller, when the MMC closk is switched off. Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers/mmc/host/sh_mmcif.c')
-rw-r--r--drivers/mmc/host/sh_mmcif.c27
1 files changed, 18 insertions, 9 deletions
diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c
index 14f8edbaa195..557886bee9ce 100644
--- a/drivers/mmc/host/sh_mmcif.c
+++ b/drivers/mmc/host/sh_mmcif.c
@@ -175,6 +175,7 @@ struct sh_mmcif_host {
175 enum mmcif_state state; 175 enum mmcif_state state;
176 spinlock_t lock; 176 spinlock_t lock;
177 bool power; 177 bool power;
178 bool card_present;
178 179
179 /* DMA support */ 180 /* DMA support */
180 struct dma_chan *chan_rx; 181 struct dma_chan *chan_rx;
@@ -877,23 +878,23 @@ static void sh_mmcif_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
877 spin_unlock_irqrestore(&host->lock, flags); 878 spin_unlock_irqrestore(&host->lock, flags);
878 879
879 if (ios->power_mode == MMC_POWER_UP) { 880 if (ios->power_mode == MMC_POWER_UP) {
880 if (p->set_pwr) 881 if (!host->card_present) {
881 p->set_pwr(host->pd, ios->power_mode);
882 if (!host->power) {
883 /* See if we also get DMA */ 882 /* See if we also get DMA */
884 sh_mmcif_request_dma(host, host->pd->dev.platform_data); 883 sh_mmcif_request_dma(host, host->pd->dev.platform_data);
885 pm_runtime_get_sync(&host->pd->dev); 884 host->card_present = true;
886 host->power = true;
887 } 885 }
888 } else if (ios->power_mode == MMC_POWER_OFF || !ios->clock) { 886 } else if (ios->power_mode == MMC_POWER_OFF || !ios->clock) {
889 /* clock stop */ 887 /* clock stop */
890 sh_mmcif_clock_control(host, 0); 888 sh_mmcif_clock_control(host, 0);
891 if (ios->power_mode == MMC_POWER_OFF) { 889 if (ios->power_mode == MMC_POWER_OFF) {
892 if (host->power) { 890 if (host->card_present) {
893 pm_runtime_put(&host->pd->dev);
894 sh_mmcif_release_dma(host); 891 sh_mmcif_release_dma(host);
895 host->power = false; 892 host->card_present = false;
896 } 893 }
894 }
895 if (host->power) {
896 pm_runtime_put(&host->pd->dev);
897 host->power = false;
897 if (p->down_pwr) 898 if (p->down_pwr)
898 p->down_pwr(host->pd); 899 p->down_pwr(host->pd);
899 } 900 }
@@ -901,8 +902,16 @@ static void sh_mmcif_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
901 return; 902 return;
902 } 903 }
903 904
904 if (ios->clock) 905 if (ios->clock) {
906 if (!host->power) {
907 if (p->set_pwr)
908 p->set_pwr(host->pd, ios->power_mode);
909 pm_runtime_get_sync(&host->pd->dev);
910 host->power = true;
911 sh_mmcif_sync_reset(host);
912 }
905 sh_mmcif_clock_control(host, ios->clock); 913 sh_mmcif_clock_control(host, ios->clock);
914 }
906 915
907 host->bus_width = ios->bus_width; 916 host->bus_width = ios->bus_width;
908 host->state = STATE_IDLE; 917 host->state = STATE_IDLE;