···519519}520520EXPORT_SYMBOL_GPL(dev_pm_genpd_get_next_hrtimer);521521522522+/*523523+ * dev_pm_genpd_synced_poweroff - Next power off should be synchronous524524+ *525525+ * @dev: A device that is attached to the genpd.526526+ *527527+ * Allows a consumer of the genpd to notify the provider that the next power off528528+ * should be synchronous.529529+ *530530+ * It is assumed that the users guarantee that the genpd wouldn't be detached531531+ * while this routine is getting called.532532+ */533533+void dev_pm_genpd_synced_poweroff(struct device *dev)534534+{535535+ struct generic_pm_domain *genpd;536536+537537+ genpd = dev_to_genpd_safe(dev);538538+ if (!genpd)539539+ return;540540+541541+ genpd_lock(genpd);542542+ genpd->synced_poweroff = true;543543+ genpd_unlock(genpd);544544+}545545+EXPORT_SYMBOL_GPL(dev_pm_genpd_synced_poweroff);546546+522547static int _genpd_power_on(struct generic_pm_domain *genpd, bool timed)523548{524549 unsigned int state_idx = genpd->state_idx;···587562588563out:589564 raw_notifier_call_chain(&genpd->power_notifiers, GENPD_NOTIFY_ON, NULL);565565+ genpd->synced_poweroff = false;590566 return 0;591567err:592568 raw_notifier_call_chain(&genpd->power_notifiers, GENPD_NOTIFY_OFF,
+6-5
drivers/clk/qcom/gdsc.c
···136136 return 0;137137}138138139139-static int gdsc_toggle_logic(struct gdsc *sc, enum gdsc_status status)139139+static int gdsc_toggle_logic(struct gdsc *sc, enum gdsc_status status,140140+ bool wait)140141{141142 int ret;142143···150149 ret = gdsc_update_collapse_bit(sc, status == GDSC_OFF);151150152151 /* If disabling votable gdscs, don't poll on status */153153- if ((sc->flags & VOTABLE) && status == GDSC_OFF) {152152+ if ((sc->flags & VOTABLE) && status == GDSC_OFF && !wait) {154153 /*155154 * Add a short delay here to ensure that an enable156155 * right after it was disabled does not put it in an···276275 gdsc_deassert_clamp_io(sc);277276 }278277279279- ret = gdsc_toggle_logic(sc, GDSC_ON);278278+ ret = gdsc_toggle_logic(sc, GDSC_ON, false);280279 if (ret)281280 return ret;282281···353352 if (sc->pwrsts == PWRSTS_RET_ON)354353 return 0;355354356356- ret = gdsc_toggle_logic(sc, GDSC_OFF);355355+ ret = gdsc_toggle_logic(sc, GDSC_OFF, domain->synced_poweroff);357356 if (ret)358357 return ret;359358···393392394393 /* Force gdsc ON if only ON state is supported */395394 if (sc->pwrsts == PWRSTS_ON) {396396- ret = gdsc_toggle_logic(sc, GDSC_ON);395395+ ret = gdsc_toggle_logic(sc, GDSC_ON, false);397396 if (ret)398397 return ret;399398 }
+5
include/linux/pm_domain.h
···136136 unsigned int prepared_count; /* Suspend counter of prepared devices */137137 unsigned int performance_state; /* Aggregated max performance state */138138 cpumask_var_t cpus; /* A cpumask of the attached CPUs */139139+ bool synced_poweroff; /* A consumer needs a synced poweroff */139140 int (*power_off)(struct generic_pm_domain *domain);140141 int (*power_on)(struct generic_pm_domain *domain);141142 struct raw_notifier_head power_notifiers; /* Power on/off notifiers */···236235int dev_pm_genpd_remove_notifier(struct device *dev);237236void dev_pm_genpd_set_next_wakeup(struct device *dev, ktime_t next);238237ktime_t dev_pm_genpd_get_next_hrtimer(struct device *dev);238238+void dev_pm_genpd_synced_poweroff(struct device *dev);239239240240extern struct dev_power_governor simple_qos_governor;241241extern struct dev_power_governor pm_domain_always_on_gov;···302300{303301 return KTIME_MAX;304302}303303+static inline void dev_pm_genpd_synced_poweroff(struct device *dev)304304+{ }305305+305306#define simple_qos_governor (*(struct dev_power_governor *)(NULL))306307#define pm_domain_always_on_gov (*(struct dev_power_governor *)(NULL))307308#endif