aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--drivers/base/power/domain.c57
-rw-r--r--include/linux/pm_domain.h16
-rw-r--r--kernel/power/Kconfig4
3 files changed, 71 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
diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h
index a7d6172922d4..ab83cf3dfaac 100644
--- a/include/linux/pm_domain.h
+++ b/include/linux/pm_domain.h
@@ -258,4 +258,20 @@ static inline void genpd_queue_power_off_work(struct generic_pm_domain *gpd) {}
258static inline void pm_genpd_poweroff_unused(void) {} 258static inline void pm_genpd_poweroff_unused(void) {}
259#endif 259#endif
260 260
261#ifdef CONFIG_PM_GENERIC_DOMAINS_SLEEP
262extern void pm_genpd_syscore_switch(struct device *dev, bool suspend);
263#else
264static inline void pm_genpd_syscore_switch(struct device *dev, bool suspend) {}
265#endif
266
267static inline void pm_genpd_syscore_poweroff(struct device *dev)
268{
269 pm_genpd_syscore_switch(dev, true);
270}
271
272static inline void pm_genpd_syscore_poweron(struct device *dev)
273{
274 pm_genpd_syscore_switch(dev, false);
275}
276
261#endif /* _LINUX_PM_DOMAIN_H */ 277#endif /* _LINUX_PM_DOMAIN_H */
diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
index a70518c9d82f..5dfdc9ea180b 100644
--- a/kernel/power/Kconfig
+++ b/kernel/power/Kconfig
@@ -263,6 +263,10 @@ config PM_GENERIC_DOMAINS
263 bool 263 bool
264 depends on PM 264 depends on PM
265 265
266config PM_GENERIC_DOMAINS_SLEEP
267 def_bool y
268 depends on PM_SLEEP && PM_GENERIC_DOMAINS
269
266config PM_GENERIC_DOMAINS_RUNTIME 270config PM_GENERIC_DOMAINS_RUNTIME
267 def_bool y 271 def_bool y
268 depends on PM_RUNTIME && PM_GENERIC_DOMAINS 272 depends on PM_RUNTIME && PM_GENERIC_DOMAINS