diff options
author | Guennadi Liakhovetski <g.liakhovetski@gmx.de> | 2011-05-26 09:33:30 -0400 |
---|---|---|
committer | Chris Ball <cjb@laptop.org> | 2011-07-21 10:35:06 -0400 |
commit | c9b0cef23f8d2a16c97623d25d6e8f8e93a56e4b (patch) | |
tree | e611d4955d57d3be4593bbc1fa40c1a6468bbd40 /drivers/mmc/host/sh_mmcif.c | |
parent | 71d111cd34ee119c93d056ad9e84dc0e82367f82 (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.c | 27 |
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; |