aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUlf Hansson <ulf.hansson@stericsson.com>2011-12-05 18:35:58 +0100
committerPhilippe Langlais <philippe.langlais@linaro.org>2012-03-06 17:30:13 +0100
commitea98206492a524ceb203751d3e19eb1349318a98 (patch)
treeb1d1aa9f9637cc69b3dab2349c984fa5a30b5bbb
parent4308f37150774fc1512fdb399a72ac7134ad46a5 (diff)
mmc: mmci: Decrease current consumption in suspend
To decrease current consumption in suspend state the VCORE regulator, the MCLK and PCLK for the ARM PL18x are now disabled. When resuming the resourses are re-enabled and register values for MMCICLOCK, MMCIPOWER and MMCIMASK0 are restored. Change-Id: I400237bf67fa37861d6fb47c4a2fd493b58c3a60 Tested-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Ulf Hansson <ulf.hansson@stericsson.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/44397 Reviewed-by: QABUILD
-rw-r--r--drivers/mmc/host/mmci.c62
1 files changed, 56 insertions, 6 deletions
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index 91aadad6ec2..e384c3b1fb0 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -1550,6 +1550,58 @@ static int __devexit mmci_remove(struct amba_device *dev)
}
#ifdef CONFIG_SUSPEND
+static int mmci_save(struct amba_device *dev)
+{
+ struct mmc_host *mmc = amba_get_drvdata(dev);
+ unsigned long flags;
+
+ if (mmc) {
+ struct mmci_host *host = mmc_priv(mmc);
+
+ spin_lock_irqsave(&host->lock, flags);
+
+ /*
+ * Make sure we do not get any interrupts when we disabled the
+ * clock and the regulator and as well make sure to clear the
+ * registers for clock and power.
+ */
+ writel(0, host->base + MMCIMASK0);
+ writel(0, host->base + MMCIPOWER);
+ writel(0, host->base + MMCICLOCK);
+
+ spin_unlock_irqrestore(&host->lock, flags);
+
+ clk_disable(host->clk);
+ amba_vcore_disable(dev);
+ }
+
+ return 0;
+}
+
+static int mmci_restore(struct amba_device *dev)
+{
+ struct mmc_host *mmc = amba_get_drvdata(dev);
+ unsigned long flags;
+
+ if (mmc) {
+ struct mmci_host *host = mmc_priv(mmc);
+
+ amba_vcore_enable(dev);
+ clk_enable(host->clk);
+
+ spin_lock_irqsave(&host->lock, flags);
+
+ /* Restore registers and re-enable interrupts. */
+ writel(host->clk_reg, host->base + MMCICLOCK);
+ writel(host->pwr_reg, host->base + MMCIPOWER);
+ writel(MCI_IRQENABLE, host->base + MMCIMASK0);
+
+ spin_unlock_irqrestore(&host->lock, flags);
+ }
+
+ return 0;
+}
+
static int mmci_suspend(struct device *dev)
{
struct amba_device *adev = to_amba_device(dev);
@@ -1557,12 +1609,11 @@ static int mmci_suspend(struct device *dev)
int ret = 0;
if (mmc) {
- struct mmci_host *host = mmc_priv(mmc);
-
ret = mmc_suspend_host(mmc);
if (ret == 0) {
pm_runtime_get_sync(dev);
- writel(0, host->base + MMCIMASK0);
+ mmci_save(adev);
+ amba_pclk_disable(adev);
}
}
@@ -1576,9 +1627,8 @@ static int mmci_resume(struct device *dev)
int ret = 0;
if (mmc) {
- struct mmci_host *host = mmc_priv(mmc);
-
- writel(MCI_IRQENABLE, host->base + MMCIMASK0);
+ amba_pclk_enable(adev);
+ mmci_restore(adev);
pm_runtime_put(dev);
ret = mmc_resume_host(mmc);