summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUlf Hansson <ulf.hansson@stericsson.com>2011-12-05 18:35:59 +0100
committerPhilippe Langlais <philippe.langlais@stericsson.com>2012-05-22 11:03:00 +0200
commit0c13ac50ca4263239e4937ae560ffe79f1c9e7c9 (patch)
treed3f0496804418cc0eb5172460ee64778bdcf7dda
parent3d08684763fe0d1b9ca53c14ca8e558e53c60e9c (diff)
mmc: mmci: Implement PM runtime callbacks to save power
In the runtime_suspend callback we make use of mmci_save to disable the VCORE regulator and the MCLK to decrease current consumption. At runtime resume, we use mmci_restore to re-enable the resourses again. From now on this will mean that especially the mmci_restore function must be fast to execute since otherwise request latency will be introduced. For the ARM Primcell PL180, the MMCIPOWER register is used to control an external power supply to the card. Thus we need to prevent the runtime callbacks from doing save and restore, otherwise the power to card will be cut. This is done by adding a new flag to the variant data. 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> Change-Id: Ic6af2f59e57df82acb4be730bb855e1d39c9439b Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/44398 Reviewed-by: QABUILD
-rw-r--r--drivers/mmc/host/mmci.c43
1 files changed, 42 insertions, 1 deletions
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index 5370858044b..70ae28efb3c 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -59,6 +59,7 @@ static unsigned int fmax = 515633;
* @pwrreg_powerup: power up value for MMCIPOWER register
* @signal_direction: input/out direction of bus signals can be indicated
* @non_power_of_2_blksize: true if block sizes can be other than power of two
+ * @pwrreg_ctrl_power: bits in MMCIPOWER register controls ext. power supply
*/
struct variant_data {
unsigned int clkreg;
@@ -73,6 +74,7 @@ struct variant_data {
u32 pwrreg_powerup;
bool signal_direction;
bool non_power_of_2_blksize;
+ bool pwrreg_ctrl_power;
};
static struct variant_data variant_arm = {
@@ -80,6 +82,7 @@ static struct variant_data variant_arm = {
.fifohalfsize = 8 * 4,
.datalength_bits = 16,
.pwrreg_powerup = MCI_PWR_UP,
+ .pwrreg_ctrl_power = true,
};
static struct variant_data variant_arm_extended_fifo = {
@@ -87,6 +90,7 @@ static struct variant_data variant_arm_extended_fifo = {
.fifohalfsize = 64 * 4,
.datalength_bits = 16,
.pwrreg_powerup = MCI_PWR_UP,
+ .pwrreg_ctrl_power = true,
};
static struct variant_data variant_u300 = {
@@ -1553,7 +1557,7 @@ static int __devexit mmci_remove(struct amba_device *dev)
return 0;
}
-#ifdef CONFIG_SUSPEND
+#if defined(CONFIG_SUSPEND) || defined(CONFIG_PM_RUNTIME)
static int mmci_save(struct amba_device *dev)
{
struct mmc_host *mmc = amba_get_drvdata(dev);
@@ -1605,7 +1609,9 @@ static int mmci_restore(struct amba_device *dev)
return 0;
}
+#endif
+#ifdef CONFIG_SUSPEND
static int mmci_suspend(struct device *dev)
{
struct amba_device *adev = to_amba_device(dev);
@@ -1642,8 +1648,43 @@ static int mmci_resume(struct device *dev)
}
#endif
+#ifdef CONFIG_PM_RUNTIME
+static int mmci_runtime_suspend(struct device *dev)
+{
+ struct amba_device *adev = to_amba_device(dev);
+ struct mmc_host *mmc = amba_get_drvdata(adev);
+ int ret = 0;
+
+ if (mmc) {
+ struct mmci_host *host = mmc_priv(mmc);
+ struct variant_data *variant = host->variant;
+ if (!variant->pwrreg_ctrl_power)
+ ret = mmci_save(adev);
+ }
+
+ return ret;
+}
+
+static int mmci_runtime_resume(struct device *dev)
+{
+ struct amba_device *adev = to_amba_device(dev);
+ struct mmc_host *mmc = amba_get_drvdata(adev);
+ int ret = 0;
+
+ if (mmc) {
+ struct mmci_host *host = mmc_priv(mmc);
+ struct variant_data *variant = host->variant;
+ if (!variant->pwrreg_ctrl_power)
+ ret = mmci_restore(adev);
+ }
+
+ return ret;
+}
+#endif
+
static const struct dev_pm_ops mmci_dev_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(mmci_suspend, mmci_resume)
+ SET_RUNTIME_PM_OPS(mmci_runtime_suspend, mmci_runtime_resume, NULL)
};
static struct amba_id mmci_ids[] = {