aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2012-08-05 19:39:57 -0400
committerRafael J. Wysocki <rjw@sisk.pl>2012-09-03 19:36:01 -0400
commit77f827de07432a74821cf0f831d699544b2d474f (patch)
treec7abd8f50c25b43ff32ba5a4200cf5e4fcd31f89 /drivers/base
parent802d8b49a7705298b62ac35a59b867f1288caaf3 (diff)
PM / Domains: Add power off/on function for system core suspend stage
Introduce function pm_genpd_syscore_switch() and two wrappers around it, pm_genpd_syscore_poweroff() and pm_genpd_syscore_poweron(), allowing the callers to let the generic PM domains framework know that the given device is not necessary any more and its PM domain can be turned off (the former) or that the given device will be required immediately, so its PM domain has to be turned on (the latter) during the system core (syscore) stage of system suspend (or hibernation) and resume. These functions will be used for handling devices registered as clock sources and clock event devices that belong to PM domains. Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Diffstat (limited to 'drivers/base')
-rw-r--r--drivers/base/power/domain.c57
1 files changed, 51 insertions, 6 deletions
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index 55c39f5b7a59..515c8ecf01ce 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -697,6 +697,24 @@ static inline void genpd_power_off_work_fn(struct work_struct *work) {}
697 697
698#ifdef CONFIG_PM_SLEEP 698#ifdef CONFIG_PM_SLEEP
699 699
700/**
701 * pm_genpd_present - Check if the given PM domain has been initialized.
702 * @genpd: PM domain to check.
703 */
704static bool pm_genpd_present(struct generic_pm_domain *genpd)
705{
706 struct generic_pm_domain *gpd;
707
708 if (IS_ERR_OR_NULL(genpd))
709 return false;
710
711 list_for_each_entry(gpd, &gpd_list, gpd_list_node)
712 if (gpd == genpd)
713 return true;
714
715 return false;
716}
717
700static bool genpd_dev_active_wakeup(struct generic_pm_domain *genpd, 718static bool genpd_dev_active_wakeup(struct generic_pm_domain *genpd,
701 struct device *dev) 719 struct device *dev)
702{ 720{
@@ -750,9 +768,10 @@ static int genpd_thaw_dev(struct generic_pm_domain *genpd, struct device *dev)
750 * Check if the given PM domain can be powered off (during system suspend or 768 * Check if the given PM domain can be powered off (during system suspend or
751 * hibernation) and do that if so. Also, in that case propagate to its masters. 769 * hibernation) and do that if so. Also, in that case propagate to its masters.
752 * 770 *
753 * This function is only called in "noirq" stages of system power transitions, 771 * This function is only called in "noirq" and "syscore" stages of system power
754 * so it need not acquire locks (all of the "noirq" callbacks are executed 772 * transitions, so it need not acquire locks (all of the "noirq" callbacks are
755 * sequentially, so it is guaranteed that it will never run twice in parallel). 773 * executed sequentially, so it is guaranteed that it will never run twice in
774 * parallel).
756 */ 775 */
757static void pm_genpd_sync_poweroff(struct generic_pm_domain *genpd) 776static void pm_genpd_sync_poweroff(struct generic_pm_domain *genpd)
758{ 777{
@@ -780,9 +799,10 @@ static void pm_genpd_sync_poweroff(struct generic_pm_domain *genpd)
780 * pm_genpd_sync_poweron - Synchronously power on a PM domain and its masters. 799 * pm_genpd_sync_poweron - Synchronously power on a PM domain and its masters.
781 * @genpd: PM domain to power on. 800 * @genpd: PM domain to power on.
782 * 801 *
783 * This function is only called in "noirq" stage of system power transitions, so 802 * This function is only called in "noirq" and "syscore" stages of system power
784 * it need not acquire locks (all of the "noirq" callbacks are executed 803 * transitions, so it need not acquire locks (all of the "noirq" callbacks are
785 * sequentially, so it is guaranteed that it will never run twice in parallel). 804 * executed sequentially, so it is guaranteed that it will never run twice in
805 * parallel).
786 */ 806 */
787static void pm_genpd_sync_poweron(struct generic_pm_domain *genpd) 807static void pm_genpd_sync_poweron(struct generic_pm_domain *genpd)
788{ 808{
@@ -1272,6 +1292,31 @@ static void pm_genpd_complete(struct device *dev)
1272 } 1292 }
1273} 1293}
1274 1294
1295/**
1296 * pm_genpd_syscore_switch - Switch power during system core suspend or resume.
1297 * @dev: Device that normally is marked as "always on" to switch power for.
1298 *
1299 * This routine may only be called during the system core (syscore) suspend or
1300 * resume phase for devices whose "always on" flags are set.
1301 */
1302void pm_genpd_syscore_switch(struct device *dev, bool suspend)
1303{
1304 struct generic_pm_domain *genpd;
1305
1306 genpd = dev_to_genpd(dev);
1307 if (!pm_genpd_present(genpd))
1308 return;
1309
1310 if (suspend) {
1311 genpd->suspended_count++;
1312 pm_genpd_sync_poweroff(genpd);
1313 } else {
1314 pm_genpd_sync_poweron(genpd);
1315 genpd->suspended_count--;
1316 }
1317}
1318EXPORT_SYMBOL_GPL(pm_genpd_syscore_switch);
1319
1275#else 1320#else
1276 1321
1277#define pm_genpd_prepare NULL 1322#define pm_genpd_prepare NULL