diff options
Diffstat (limited to 'drivers/base/power/domain.c')
-rw-r--r-- | drivers/base/power/domain.c | 57 |
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 | */ | ||
704 | static 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 | |||
700 | static bool genpd_dev_active_wakeup(struct generic_pm_domain *genpd, | 718 | static 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 | */ |
757 | static void pm_genpd_sync_poweroff(struct generic_pm_domain *genpd) | 776 | static 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 | */ |
787 | static void pm_genpd_sync_poweron(struct generic_pm_domain *genpd) | 807 | static 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 | */ | ||
1302 | void 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 | } | ||
1318 | EXPORT_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 |