| From 896e44c328f1ab6c44097333ba1db7ae3a08ff5d Mon Sep 17 00:00:00 2001 |
| From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> |
| Date: Thu, 26 May 2011 15:33:30 +0200 |
| Subject: 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> |
| (cherry picked from commit c9b0cef23f8d2a16c97623d25d6e8f8e93a56e4b) |
| |
| Signed-off-by: Simon Horman <horms@verge.net.au> |
| --- |
| drivers/mmc/host/sh_mmcif.c | 27 ++++++++++++++++++--------- |
| 1 file changed, 18 insertions(+), 9 deletions(-) |
| |
| diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c |
| index 14f8edb..557886b 100644 |
| --- a/drivers/mmc/host/sh_mmcif.c |
| +++ b/drivers/mmc/host/sh_mmcif.c |
| @@ -175,6 +175,7 @@ struct sh_mmcif_host { |
| enum mmcif_state state; |
| spinlock_t lock; |
| bool power; |
| + bool card_present; |
| |
| /* DMA support */ |
| struct dma_chan *chan_rx; |
| @@ -877,23 +878,23 @@ static void sh_mmcif_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) |
| spin_unlock_irqrestore(&host->lock, flags); |
| |
| if (ios->power_mode == MMC_POWER_UP) { |
| - if (p->set_pwr) |
| - p->set_pwr(host->pd, ios->power_mode); |
| - if (!host->power) { |
| + if (!host->card_present) { |
| /* See if we also get DMA */ |
| sh_mmcif_request_dma(host, host->pd->dev.platform_data); |
| - pm_runtime_get_sync(&host->pd->dev); |
| - host->power = true; |
| + host->card_present = true; |
| } |
| } else if (ios->power_mode == MMC_POWER_OFF || !ios->clock) { |
| /* clock stop */ |
| sh_mmcif_clock_control(host, 0); |
| if (ios->power_mode == MMC_POWER_OFF) { |
| - if (host->power) { |
| - pm_runtime_put(&host->pd->dev); |
| + if (host->card_present) { |
| sh_mmcif_release_dma(host); |
| - host->power = false; |
| + host->card_present = false; |
| } |
| + } |
| + if (host->power) { |
| + pm_runtime_put(&host->pd->dev); |
| + host->power = false; |
| if (p->down_pwr) |
| p->down_pwr(host->pd); |
| } |
| @@ -901,8 +902,16 @@ static void sh_mmcif_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) |
| return; |
| } |
| |
| - if (ios->clock) |
| + if (ios->clock) { |
| + if (!host->power) { |
| + if (p->set_pwr) |
| + p->set_pwr(host->pd, ios->power_mode); |
| + pm_runtime_get_sync(&host->pd->dev); |
| + host->power = true; |
| + sh_mmcif_sync_reset(host); |
| + } |
| sh_mmcif_clock_control(host, ios->clock); |
| + } |
| |
| host->bus_width = ios->bus_width; |
| host->state = STATE_IDLE; |
| -- |
| 1.7.10.2.565.gbd578b5 |
| |