From: Ulf Hansson Date: Tue, 1 Jul 2025 11:47:09 +0000 (+0200) Subject: pmdomain: core: Export a common ->sync_state() helper for genpd providers X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6c3b746fd536b7612b23e5c2041365014b85082e;p=thirdparty%2Flinux.git pmdomain: core: Export a common ->sync_state() helper for genpd providers In some cases the typical platform driver that act as genpd provider, may need its own ->sync_state() callback to manage various things. In this regards, the provider most likely wants to allow its corresponding genpds to be powered-off. For this reason, let's introduce a new genpd helper function, of_genpd_sync_state() that helps genpd provider drivers to achieve this. Suggested-by: Saravana Kannan Reviewed-by: Abel Vesa Tested-by: Hiago De Franco # Colibri iMX8X Tested-by: Tomi Valkeinen # TI AM62A,Xilinx ZynqMP ZCU106 Signed-off-by: Ulf Hansson Link: https://lore.kernel.org/r/20250701114733.636510-8-ulf.hansson@linaro.org --- diff --git a/drivers/pmdomain/core.c b/drivers/pmdomain/core.c index 79dc0bf406f0b..0a6593a1b1c8d 100644 --- a/drivers/pmdomain/core.c +++ b/drivers/pmdomain/core.c @@ -3396,6 +3396,33 @@ int of_genpd_parse_idle_states(struct device_node *dn, } EXPORT_SYMBOL_GPL(of_genpd_parse_idle_states); +/** + * of_genpd_sync_state() - A common sync_state function for genpd providers + * @np: The device node the genpd provider is associated with. + * + * The @np that corresponds to a genpd provider may provide one or multiple + * genpds. This function makes use @np to find the genpds that belongs to the + * provider. For each genpd we try a power-off. + */ +void of_genpd_sync_state(struct device_node *np) +{ + struct generic_pm_domain *genpd; + + if (!np) + return; + + mutex_lock(&gpd_list_lock); + list_for_each_entry(genpd, &gpd_list, gpd_list_node) { + if (genpd->provider == of_fwnode_handle(np)) { + genpd_lock(genpd); + genpd_power_off(genpd, false, 0); + genpd_unlock(genpd); + } + } + mutex_unlock(&gpd_list_lock); +} +EXPORT_SYMBOL_GPL(of_genpd_sync_state); + static int genpd_provider_probe(struct device *dev) { return 0; diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h index 0b18160901a2c..3578196e6626b 100644 --- a/include/linux/pm_domain.h +++ b/include/linux/pm_domain.h @@ -431,6 +431,7 @@ int of_genpd_remove_subdomain(const struct of_phandle_args *parent_spec, struct generic_pm_domain *of_genpd_remove_last(struct device_node *np); int of_genpd_parse_idle_states(struct device_node *dn, struct genpd_power_state **states, int *n); +void of_genpd_sync_state(struct device_node *np); int genpd_dev_pm_attach(struct device *dev); struct device *genpd_dev_pm_attach_by_id(struct device *dev, @@ -476,6 +477,8 @@ static inline int of_genpd_parse_idle_states(struct device_node *dn, return -ENODEV; } +static inline void of_genpd_sync_state(struct device_node *np) {} + static inline int genpd_dev_pm_attach(struct device *dev) { return 0;