Loading drivers/base/power/domain.c +26 −0 Original line number Diff line number Diff line Loading @@ -519,6 +519,31 @@ ktime_t dev_pm_genpd_get_next_hrtimer(struct device *dev) } EXPORT_SYMBOL_GPL(dev_pm_genpd_get_next_hrtimer); /* * dev_pm_genpd_synced_poweroff - Next power off should be synchronous * * @dev: A device that is attached to the genpd. * * Allows a consumer of the genpd to notify the provider that the next power off * should be synchronous. * * It is assumed that the users guarantee that the genpd wouldn't be detached * while this routine is getting called. */ void dev_pm_genpd_synced_poweroff(struct device *dev) { struct generic_pm_domain *genpd; genpd = dev_to_genpd_safe(dev); if (!genpd) return; genpd_lock(genpd); genpd->synced_poweroff = true; genpd_unlock(genpd); } EXPORT_SYMBOL_GPL(dev_pm_genpd_synced_poweroff); static int _genpd_power_on(struct generic_pm_domain *genpd, bool timed) { unsigned int state_idx = genpd->state_idx; Loading Loading @@ -562,6 +587,7 @@ static int _genpd_power_on(struct generic_pm_domain *genpd, bool timed) out: raw_notifier_call_chain(&genpd->power_notifiers, GENPD_NOTIFY_ON, NULL); genpd->synced_poweroff = false; return 0; err: raw_notifier_call_chain(&genpd->power_notifiers, GENPD_NOTIFY_OFF, Loading drivers/clk/qcom/gdsc.c +6 −5 Original line number Diff line number Diff line Loading @@ -136,7 +136,8 @@ static int gdsc_update_collapse_bit(struct gdsc *sc, bool val) return 0; } static int gdsc_toggle_logic(struct gdsc *sc, enum gdsc_status status) static int gdsc_toggle_logic(struct gdsc *sc, enum gdsc_status status, bool wait) { int ret; Loading @@ -149,7 +150,7 @@ static int gdsc_toggle_logic(struct gdsc *sc, enum gdsc_status status) ret = gdsc_update_collapse_bit(sc, status == GDSC_OFF); /* If disabling votable gdscs, don't poll on status */ if ((sc->flags & VOTABLE) && status == GDSC_OFF) { if ((sc->flags & VOTABLE) && status == GDSC_OFF && !wait) { /* * Add a short delay here to ensure that an enable * right after it was disabled does not put it in an Loading Loading @@ -275,7 +276,7 @@ static int gdsc_enable(struct generic_pm_domain *domain) gdsc_deassert_clamp_io(sc); } ret = gdsc_toggle_logic(sc, GDSC_ON); ret = gdsc_toggle_logic(sc, GDSC_ON, false); if (ret) return ret; Loading Loading @@ -352,7 +353,7 @@ static int gdsc_disable(struct generic_pm_domain *domain) if (sc->pwrsts == PWRSTS_RET_ON) return 0; ret = gdsc_toggle_logic(sc, GDSC_OFF); ret = gdsc_toggle_logic(sc, GDSC_OFF, domain->synced_poweroff); if (ret) return ret; Loading Loading @@ -392,7 +393,7 @@ static int gdsc_init(struct gdsc *sc) /* Force gdsc ON if only ON state is supported */ if (sc->pwrsts == PWRSTS_ON) { ret = gdsc_toggle_logic(sc, GDSC_ON); ret = gdsc_toggle_logic(sc, GDSC_ON, false); if (ret) return ret; } Loading include/linux/pm_domain.h +5 −0 Original line number Diff line number Diff line Loading @@ -136,6 +136,7 @@ struct generic_pm_domain { unsigned int prepared_count; /* Suspend counter of prepared devices */ unsigned int performance_state; /* Aggregated max performance state */ cpumask_var_t cpus; /* A cpumask of the attached CPUs */ bool synced_poweroff; /* A consumer needs a synced poweroff */ int (*power_off)(struct generic_pm_domain *domain); int (*power_on)(struct generic_pm_domain *domain); struct raw_notifier_head power_notifiers; /* Power on/off notifiers */ Loading Loading @@ -235,6 +236,7 @@ int dev_pm_genpd_add_notifier(struct device *dev, struct notifier_block *nb); int dev_pm_genpd_remove_notifier(struct device *dev); void dev_pm_genpd_set_next_wakeup(struct device *dev, ktime_t next); ktime_t dev_pm_genpd_get_next_hrtimer(struct device *dev); void dev_pm_genpd_synced_poweroff(struct device *dev); extern struct dev_power_governor simple_qos_governor; extern struct dev_power_governor pm_domain_always_on_gov; Loading Loading @@ -300,6 +302,9 @@ static inline ktime_t dev_pm_genpd_get_next_hrtimer(struct device *dev) { return KTIME_MAX; } static inline void dev_pm_genpd_synced_poweroff(struct device *dev) { } #define simple_qos_governor (*(struct dev_power_governor *)(NULL)) #define pm_domain_always_on_gov (*(struct dev_power_governor *)(NULL)) #endif Loading Loading
drivers/base/power/domain.c +26 −0 Original line number Diff line number Diff line Loading @@ -519,6 +519,31 @@ ktime_t dev_pm_genpd_get_next_hrtimer(struct device *dev) } EXPORT_SYMBOL_GPL(dev_pm_genpd_get_next_hrtimer); /* * dev_pm_genpd_synced_poweroff - Next power off should be synchronous * * @dev: A device that is attached to the genpd. * * Allows a consumer of the genpd to notify the provider that the next power off * should be synchronous. * * It is assumed that the users guarantee that the genpd wouldn't be detached * while this routine is getting called. */ void dev_pm_genpd_synced_poweroff(struct device *dev) { struct generic_pm_domain *genpd; genpd = dev_to_genpd_safe(dev); if (!genpd) return; genpd_lock(genpd); genpd->synced_poweroff = true; genpd_unlock(genpd); } EXPORT_SYMBOL_GPL(dev_pm_genpd_synced_poweroff); static int _genpd_power_on(struct generic_pm_domain *genpd, bool timed) { unsigned int state_idx = genpd->state_idx; Loading Loading @@ -562,6 +587,7 @@ static int _genpd_power_on(struct generic_pm_domain *genpd, bool timed) out: raw_notifier_call_chain(&genpd->power_notifiers, GENPD_NOTIFY_ON, NULL); genpd->synced_poweroff = false; return 0; err: raw_notifier_call_chain(&genpd->power_notifiers, GENPD_NOTIFY_OFF, Loading
drivers/clk/qcom/gdsc.c +6 −5 Original line number Diff line number Diff line Loading @@ -136,7 +136,8 @@ static int gdsc_update_collapse_bit(struct gdsc *sc, bool val) return 0; } static int gdsc_toggle_logic(struct gdsc *sc, enum gdsc_status status) static int gdsc_toggle_logic(struct gdsc *sc, enum gdsc_status status, bool wait) { int ret; Loading @@ -149,7 +150,7 @@ static int gdsc_toggle_logic(struct gdsc *sc, enum gdsc_status status) ret = gdsc_update_collapse_bit(sc, status == GDSC_OFF); /* If disabling votable gdscs, don't poll on status */ if ((sc->flags & VOTABLE) && status == GDSC_OFF) { if ((sc->flags & VOTABLE) && status == GDSC_OFF && !wait) { /* * Add a short delay here to ensure that an enable * right after it was disabled does not put it in an Loading Loading @@ -275,7 +276,7 @@ static int gdsc_enable(struct generic_pm_domain *domain) gdsc_deassert_clamp_io(sc); } ret = gdsc_toggle_logic(sc, GDSC_ON); ret = gdsc_toggle_logic(sc, GDSC_ON, false); if (ret) return ret; Loading Loading @@ -352,7 +353,7 @@ static int gdsc_disable(struct generic_pm_domain *domain) if (sc->pwrsts == PWRSTS_RET_ON) return 0; ret = gdsc_toggle_logic(sc, GDSC_OFF); ret = gdsc_toggle_logic(sc, GDSC_OFF, domain->synced_poweroff); if (ret) return ret; Loading Loading @@ -392,7 +393,7 @@ static int gdsc_init(struct gdsc *sc) /* Force gdsc ON if only ON state is supported */ if (sc->pwrsts == PWRSTS_ON) { ret = gdsc_toggle_logic(sc, GDSC_ON); ret = gdsc_toggle_logic(sc, GDSC_ON, false); if (ret) return ret; } Loading
include/linux/pm_domain.h +5 −0 Original line number Diff line number Diff line Loading @@ -136,6 +136,7 @@ struct generic_pm_domain { unsigned int prepared_count; /* Suspend counter of prepared devices */ unsigned int performance_state; /* Aggregated max performance state */ cpumask_var_t cpus; /* A cpumask of the attached CPUs */ bool synced_poweroff; /* A consumer needs a synced poweroff */ int (*power_off)(struct generic_pm_domain *domain); int (*power_on)(struct generic_pm_domain *domain); struct raw_notifier_head power_notifiers; /* Power on/off notifiers */ Loading Loading @@ -235,6 +236,7 @@ int dev_pm_genpd_add_notifier(struct device *dev, struct notifier_block *nb); int dev_pm_genpd_remove_notifier(struct device *dev); void dev_pm_genpd_set_next_wakeup(struct device *dev, ktime_t next); ktime_t dev_pm_genpd_get_next_hrtimer(struct device *dev); void dev_pm_genpd_synced_poweroff(struct device *dev); extern struct dev_power_governor simple_qos_governor; extern struct dev_power_governor pm_domain_always_on_gov; Loading Loading @@ -300,6 +302,9 @@ static inline ktime_t dev_pm_genpd_get_next_hrtimer(struct device *dev) { return KTIME_MAX; } static inline void dev_pm_genpd_synced_poweroff(struct device *dev) { } #define simple_qos_governor (*(struct dev_power_governor *)(NULL)) #define pm_domain_always_on_gov (*(struct dev_power_governor *)(NULL)) #endif Loading