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>
This commit is contained in:
parent
802d8b49a7
commit
77f827de07
|
@ -697,6 +697,24 @@ static inline void genpd_power_off_work_fn(struct work_struct *work) {}
|
||||||
|
|
||||||
#ifdef CONFIG_PM_SLEEP
|
#ifdef CONFIG_PM_SLEEP
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pm_genpd_present - Check if the given PM domain has been initialized.
|
||||||
|
* @genpd: PM domain to check.
|
||||||
|
*/
|
||||||
|
static bool pm_genpd_present(struct generic_pm_domain *genpd)
|
||||||
|
{
|
||||||
|
struct generic_pm_domain *gpd;
|
||||||
|
|
||||||
|
if (IS_ERR_OR_NULL(genpd))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
list_for_each_entry(gpd, &gpd_list, gpd_list_node)
|
||||||
|
if (gpd == genpd)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static bool genpd_dev_active_wakeup(struct generic_pm_domain *genpd,
|
static bool genpd_dev_active_wakeup(struct generic_pm_domain *genpd,
|
||||||
struct device *dev)
|
struct device *dev)
|
||||||
{
|
{
|
||||||
|
@ -750,9 +768,10 @@ static int genpd_thaw_dev(struct generic_pm_domain *genpd, struct device *dev)
|
||||||
* Check if the given PM domain can be powered off (during system suspend or
|
* Check if the given PM domain can be powered off (during system suspend or
|
||||||
* hibernation) and do that if so. Also, in that case propagate to its masters.
|
* hibernation) and do that if so. Also, in that case propagate to its masters.
|
||||||
*
|
*
|
||||||
* This function is only called in "noirq" stages of system power transitions,
|
* This function is only called in "noirq" and "syscore" stages of system power
|
||||||
* so it need not acquire locks (all of the "noirq" callbacks are executed
|
* transitions, so it need not acquire locks (all of the "noirq" callbacks are
|
||||||
* sequentially, so it is guaranteed that it will never run twice in parallel).
|
* executed sequentially, so it is guaranteed that it will never run twice in
|
||||||
|
* parallel).
|
||||||
*/
|
*/
|
||||||
static void pm_genpd_sync_poweroff(struct generic_pm_domain *genpd)
|
static void pm_genpd_sync_poweroff(struct generic_pm_domain *genpd)
|
||||||
{
|
{
|
||||||
|
@ -780,9 +799,10 @@ static void pm_genpd_sync_poweroff(struct generic_pm_domain *genpd)
|
||||||
* pm_genpd_sync_poweron - Synchronously power on a PM domain and its masters.
|
* pm_genpd_sync_poweron - Synchronously power on a PM domain and its masters.
|
||||||
* @genpd: PM domain to power on.
|
* @genpd: PM domain to power on.
|
||||||
*
|
*
|
||||||
* This function is only called in "noirq" stage of system power transitions, so
|
* This function is only called in "noirq" and "syscore" stages of system power
|
||||||
* it need not acquire locks (all of the "noirq" callbacks are executed
|
* transitions, so it need not acquire locks (all of the "noirq" callbacks are
|
||||||
* sequentially, so it is guaranteed that it will never run twice in parallel).
|
* executed sequentially, so it is guaranteed that it will never run twice in
|
||||||
|
* parallel).
|
||||||
*/
|
*/
|
||||||
static void pm_genpd_sync_poweron(struct generic_pm_domain *genpd)
|
static void pm_genpd_sync_poweron(struct generic_pm_domain *genpd)
|
||||||
{
|
{
|
||||||
|
@ -1272,6 +1292,31 @@ static void pm_genpd_complete(struct device *dev)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pm_genpd_syscore_switch - Switch power during system core suspend or resume.
|
||||||
|
* @dev: Device that normally is marked as "always on" to switch power for.
|
||||||
|
*
|
||||||
|
* This routine may only be called during the system core (syscore) suspend or
|
||||||
|
* resume phase for devices whose "always on" flags are set.
|
||||||
|
*/
|
||||||
|
void pm_genpd_syscore_switch(struct device *dev, bool suspend)
|
||||||
|
{
|
||||||
|
struct generic_pm_domain *genpd;
|
||||||
|
|
||||||
|
genpd = dev_to_genpd(dev);
|
||||||
|
if (!pm_genpd_present(genpd))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (suspend) {
|
||||||
|
genpd->suspended_count++;
|
||||||
|
pm_genpd_sync_poweroff(genpd);
|
||||||
|
} else {
|
||||||
|
pm_genpd_sync_poweron(genpd);
|
||||||
|
genpd->suspended_count--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(pm_genpd_syscore_switch);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#define pm_genpd_prepare NULL
|
#define pm_genpd_prepare NULL
|
||||||
|
|
|
@ -258,4 +258,20 @@ static inline void genpd_queue_power_off_work(struct generic_pm_domain *gpd) {}
|
||||||
static inline void pm_genpd_poweroff_unused(void) {}
|
static inline void pm_genpd_poweroff_unused(void) {}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM_GENERIC_DOMAINS_SLEEP
|
||||||
|
extern void pm_genpd_syscore_switch(struct device *dev, bool suspend);
|
||||||
|
#else
|
||||||
|
static inline void pm_genpd_syscore_switch(struct device *dev, bool suspend) {}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static inline void pm_genpd_syscore_poweroff(struct device *dev)
|
||||||
|
{
|
||||||
|
pm_genpd_syscore_switch(dev, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void pm_genpd_syscore_poweron(struct device *dev)
|
||||||
|
{
|
||||||
|
pm_genpd_syscore_switch(dev, false);
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* _LINUX_PM_DOMAIN_H */
|
#endif /* _LINUX_PM_DOMAIN_H */
|
||||||
|
|
|
@ -263,6 +263,10 @@ config PM_GENERIC_DOMAINS
|
||||||
bool
|
bool
|
||||||
depends on PM
|
depends on PM
|
||||||
|
|
||||||
|
config PM_GENERIC_DOMAINS_SLEEP
|
||||||
|
def_bool y
|
||||||
|
depends on PM_SLEEP && PM_GENERIC_DOMAINS
|
||||||
|
|
||||||
config PM_GENERIC_DOMAINS_RUNTIME
|
config PM_GENERIC_DOMAINS_RUNTIME
|
||||||
def_bool y
|
def_bool y
|
||||||
depends on PM_RUNTIME && PM_GENERIC_DOMAINS
|
depends on PM_RUNTIME && PM_GENERIC_DOMAINS
|
||||||
|
|
Loading…
Reference in New Issue