From patchwork Thu May 26 13:33:30 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Guennadi Liakhovetski X-Patchwork-Id: 820852 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter2.kernel.org (8.14.4/8.14.3) with ESMTP id p4QDXYYC028729 for ; Thu, 26 May 2011 13:33:34 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755213Ab1EZNdd (ORCPT ); Thu, 26 May 2011 09:33:33 -0400 Received: from moutng.kundenserver.de ([212.227.126.186]:52195 "EHLO moutng.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752965Ab1EZNdd (ORCPT ); Thu, 26 May 2011 09:33:33 -0400 Received: from axis700.grange (dslb-178-001-148-120.pools.arcor-ip.net [178.1.148.120]) by mrelayeu.kundenserver.de (node=mreu1) with ESMTP (Nemesis) id 0MYJ3F-1QCcH42hO5-00V7GH; Thu, 26 May 2011 15:33:31 +0200 Received: by axis700.grange (Postfix, from userid 1000) id 1D651189B6D; Thu, 26 May 2011 15:33:31 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by axis700.grange (Postfix) with ESMTP id 13F32189B6B; Thu, 26 May 2011 15:33:31 +0200 (CEST) Date: Thu, 26 May 2011 15:33:30 +0200 (CEST) From: Guennadi Liakhovetski X-X-Sender: lyakh@axis700.grange To: linux-mmc@vger.kernel.org cc: linux-sh@vger.kernel.org, Magnus Damm Subject: [PATCH/RFC] mmc: sh_mmcif: maximize power saving Message-ID: MIME-Version: 1.0 X-Provags-ID: V02:K0:+fvrCLE6znhxm8KFkYklmTFKTWu1aUKDrNztQGPmK2I +6tG7GS9zkSLgjWfRa+ZZ2oeBLVydMj16Ev+tr1ZEhY9nitQBI xXIgieddn9s8/Bt+zqdl3L6HtV1+eK7IrIs1hnjC3AnaRDF4I8 kpxDMgIB0WDViNT30xs2qRzatIs2yVsJC+vvVYYVErENn9SDNc stkjWKEPjuBftlAN+ZifW/UChDoNwxlGGtiaEJzsWI= Sender: linux-mmc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter2.kernel.org [140.211.167.43]); Thu, 26 May 2011 13:33:34 +0000 (UTC) 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 --- Patches have been submitted earlier for SDHCI to accomplish something similar, but they have complicated dependencies upon other different subsystems, especially on PCI. MMCIF is easier - it only exists in different SoCs, so, this change should also be easier to review, verify and test. 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 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;