summaryrefslogtreecommitdiff
path: root/drivers/base
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2011-02-16 21:53:17 +0100
committerUlf Hansson <ulf.hansson@stericsson.com>2011-09-19 15:14:37 +0200
commitc81bda3b18b40b4266935094cbbc2290fa14b165 (patch)
tree75ec646f1291e3c511892cd73db47e792ff71ee4 /drivers/base
parent4a1b01c50d8a64822cf0dba1de6342b9f6244e8f (diff)
PM: Add support for device power domains
The platform bus type is often used to handle Systems-on-a-Chip (SoC) where all devices are represented by objects of type struct platform_device. In those cases the same "platform" device driver may be used with multiple different system configurations, but the actions needed to put the devices it handles into a low-power state and back into the full-power state may depend on the design of the given SoC. The driver, however, cannot possibly include all the information necessary for the power management of its device on all the systems it is used with. Moreover, the device hierarchy in its current form also is not suitable for representing this kind of information. The patch below attempts to address this problem by introducing objects of type struct dev_power_domain that can be used for representing power domains within a SoC. Every struct dev_power_domain object provides a sets of device power management callbacks that can be used to perform what's needed for device power management in addition to the operations carried out by the device's driver and subsystem. Namely, if a struct dev_power_domain object is pointed to by the pwr_domain field in a struct device, the callbacks provided by its ops member will be executed in addition to the corresponding callbacks provided by the device's subsystem and driver during all power transitions. Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> Tested-and-acked-by: Kevin Hilman <khilman@ti.com> ST-Ericsson Linux next: - ST-Ericsson ID: ER323382 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I1f21456339aaa75905694bf4d87912b762c9d85e Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/16674 Tested-by: Rabin VINCENT <rabin.vincent@stericsson.com> Reviewed-by: Jonas ABERG <jonas.aberg@stericsson.com>
Diffstat (limited to 'drivers/base')
-rw-r--r--drivers/base/power/main.c7
-rw-r--r--drivers/base/power/runtime.c16
2 files changed, 21 insertions, 2 deletions
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index 06f09bf89cb..d0ca74d7f36 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -885,6 +885,13 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
pm_dev_dbg(dev, state, "legacy ");
error = legacy_suspend(dev, state, dev->bus->suspend);
}
+ if (error)
+ goto End;
+ }
+
+ if (dev->pwr_domain) {
+ pm_dev_dbg(dev, state, "power domain ");
+ pm_op(dev, &dev->pwr_domain->ops, state);
}
End:
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index 0d4587b15c5..69d6f1d4805 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -168,6 +168,7 @@ static int rpm_check_suspend_allowed(struct device *dev)
static int rpm_idle(struct device *dev, int rpmflags)
{
int (*callback)(struct device *);
+ int (*domain_callback)(struct device *);
int retval;
retval = rpm_check_suspend_allowed(dev);
@@ -224,10 +225,19 @@ static int rpm_idle(struct device *dev, int rpmflags)
else
callback = NULL;
- if (callback) {
+ if (dev->pwr_domain)
+ domain_callback = dev->pwr_domain->ops.runtime_idle;
+ else
+ domain_callback = NULL;
+
+ if (callback || domain_callback) {
spin_unlock_irq(&dev->power.lock);
- callback(dev);
+ if (domain_callback)
+ retval = domain_callback(dev);
+
+ if (!retval && callback)
+ callback(dev);
spin_lock_irq(&dev->power.lock);
}
@@ -394,6 +404,8 @@ static int rpm_suspend(struct device *dev, int rpmflags)
else
pm_runtime_cancel_pending(dev);
} else {
+ if (dev->pwr_domain)
+ rpm_callback(dev->pwr_domain->ops.runtime_suspend, dev);
no_callback:
__update_runtime_status(dev, RPM_SUSPENDED);
pm_runtime_deactivate_timer(dev);