Message ID | 20241126-b4-linux-next-24-11-18-clock-multiple-power-domains-v3-3-836dad33521a@linaro.org (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | clk: qcom: Add support for multiple power-domains for a clock controller. | expand |
On Tue, Nov 26, 2024 at 11:44:29PM +0000, Bryan O'Donoghue wrote: > When a clock-controller has multiple power-domains we need to attach parent > GDSCs in that clock-controller as subdomains of each of the power-domains. > This is a bit sparse, in particular it would be nice to capture the open questions about whether every GDSC always should be parented by all defined power-domains, and if performance-state should be applied equally across all those power-domains (and/or if this actually happens). PS. Please drop "drivers: " and s/subdomain list/GDSC/ in subject. Regards, Bjorn > Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> > --- > drivers/clk/qcom/common.c | 1 + > drivers/clk/qcom/gdsc.c | 35 +++++++++++++++++++++++++++++++++++ > drivers/clk/qcom/gdsc.h | 1 + > 3 files changed, 37 insertions(+) > > diff --git a/drivers/clk/qcom/common.c b/drivers/clk/qcom/common.c > index 7727295c57c8f6672d46d2380e1ff5ec2ac68d42..58a8397eefe51da237a4285d4e7cee967e19948f 100644 > --- a/drivers/clk/qcom/common.c > +++ b/drivers/clk/qcom/common.c > @@ -338,6 +338,7 @@ int qcom_cc_really_probe(struct device *dev, > scd->dev = dev; > scd->scs = desc->gdscs; > scd->num = desc->num_gdscs; > + scd->pd_list = cc->pd_list; > ret = gdsc_register(scd, &reset->rcdev, regmap); > if (ret) > return ret; > diff --git a/drivers/clk/qcom/gdsc.c b/drivers/clk/qcom/gdsc.c > index 4fc6f957d0b846cc90e50ef243f23a7a27e66899..cb4afa6d584899f3dafa380d5e01be6de9711737 100644 > --- a/drivers/clk/qcom/gdsc.c > +++ b/drivers/clk/qcom/gdsc.c > @@ -506,6 +506,36 @@ static int gdsc_init(struct gdsc *sc) > return ret; > } > > +static int gdsc_add_subdomain_list(struct dev_pm_domain_list *pd_list, > + struct generic_pm_domain *subdomain) > +{ > + int i, ret; > + > + for (i = 0; i < pd_list->num_pds; i++) { > + struct device *dev = pd_list->pd_devs[i]; > + struct generic_pm_domain *genpd = pd_to_genpd(dev->pm_domain); > + > + ret = pm_genpd_add_subdomain(genpd, subdomain); > + if (ret) > + return ret; > + } > + > + return 0; > +} > + > +static void gdsc_remove_subdomain_list(struct dev_pm_domain_list *pd_list, > + struct generic_pm_domain *subdomain) > +{ > + int i; > + > + for (i = 0; i < pd_list->num_pds; i++) { > + struct device *dev = pd_list->pd_devs[i]; > + struct generic_pm_domain *genpd = pd_to_genpd(dev->pm_domain); > + > + pm_genpd_remove_subdomain(genpd, subdomain); > + } > +} > + > int gdsc_register(struct gdsc_desc *desc, > struct reset_controller_dev *rcdev, struct regmap *regmap) > { > @@ -558,6 +588,9 @@ int gdsc_register(struct gdsc_desc *desc, > ret = pm_genpd_add_subdomain(scs[i]->parent, &scs[i]->pd); > else if (!IS_ERR_OR_NULL(dev->pm_domain)) > ret = pm_genpd_add_subdomain(pd_to_genpd(dev->pm_domain), &scs[i]->pd); > + else if (desc->pd_list) > + ret = gdsc_add_subdomain_list(desc->pd_list, &scs[i]->pd); > + > if (ret) > return ret; > } > @@ -580,6 +613,8 @@ void gdsc_unregister(struct gdsc_desc *desc) > pm_genpd_remove_subdomain(scs[i]->parent, &scs[i]->pd); > else if (!IS_ERR_OR_NULL(dev->pm_domain)) > pm_genpd_remove_subdomain(pd_to_genpd(dev->pm_domain), &scs[i]->pd); > + else if (desc->pd_list) > + gdsc_remove_subdomain_list(desc->pd_list, &scs[i]->pd); > } > of_genpd_del_provider(dev->of_node); > } > diff --git a/drivers/clk/qcom/gdsc.h b/drivers/clk/qcom/gdsc.h > index 1e2779b823d1c8ca077c9b4cd0a0dbdf5f9457ef..dd843e86c05b2f30e6d9e978681580016333839d 100644 > --- a/drivers/clk/qcom/gdsc.h > +++ b/drivers/clk/qcom/gdsc.h > @@ -80,6 +80,7 @@ struct gdsc_desc { > struct device *dev; > struct gdsc **scs; > size_t num; > + struct dev_pm_domain_list *pd_list; > }; > > #ifdef CONFIG_QCOM_GDSC > > -- > 2.45.2 >
diff --git a/drivers/clk/qcom/common.c b/drivers/clk/qcom/common.c index 7727295c57c8f6672d46d2380e1ff5ec2ac68d42..58a8397eefe51da237a4285d4e7cee967e19948f 100644 --- a/drivers/clk/qcom/common.c +++ b/drivers/clk/qcom/common.c @@ -338,6 +338,7 @@ int qcom_cc_really_probe(struct device *dev, scd->dev = dev; scd->scs = desc->gdscs; scd->num = desc->num_gdscs; + scd->pd_list = cc->pd_list; ret = gdsc_register(scd, &reset->rcdev, regmap); if (ret) return ret; diff --git a/drivers/clk/qcom/gdsc.c b/drivers/clk/qcom/gdsc.c index 4fc6f957d0b846cc90e50ef243f23a7a27e66899..cb4afa6d584899f3dafa380d5e01be6de9711737 100644 --- a/drivers/clk/qcom/gdsc.c +++ b/drivers/clk/qcom/gdsc.c @@ -506,6 +506,36 @@ static int gdsc_init(struct gdsc *sc) return ret; } +static int gdsc_add_subdomain_list(struct dev_pm_domain_list *pd_list, + struct generic_pm_domain *subdomain) +{ + int i, ret; + + for (i = 0; i < pd_list->num_pds; i++) { + struct device *dev = pd_list->pd_devs[i]; + struct generic_pm_domain *genpd = pd_to_genpd(dev->pm_domain); + + ret = pm_genpd_add_subdomain(genpd, subdomain); + if (ret) + return ret; + } + + return 0; +} + +static void gdsc_remove_subdomain_list(struct dev_pm_domain_list *pd_list, + struct generic_pm_domain *subdomain) +{ + int i; + + for (i = 0; i < pd_list->num_pds; i++) { + struct device *dev = pd_list->pd_devs[i]; + struct generic_pm_domain *genpd = pd_to_genpd(dev->pm_domain); + + pm_genpd_remove_subdomain(genpd, subdomain); + } +} + int gdsc_register(struct gdsc_desc *desc, struct reset_controller_dev *rcdev, struct regmap *regmap) { @@ -558,6 +588,9 @@ int gdsc_register(struct gdsc_desc *desc, ret = pm_genpd_add_subdomain(scs[i]->parent, &scs[i]->pd); else if (!IS_ERR_OR_NULL(dev->pm_domain)) ret = pm_genpd_add_subdomain(pd_to_genpd(dev->pm_domain), &scs[i]->pd); + else if (desc->pd_list) + ret = gdsc_add_subdomain_list(desc->pd_list, &scs[i]->pd); + if (ret) return ret; } @@ -580,6 +613,8 @@ void gdsc_unregister(struct gdsc_desc *desc) pm_genpd_remove_subdomain(scs[i]->parent, &scs[i]->pd); else if (!IS_ERR_OR_NULL(dev->pm_domain)) pm_genpd_remove_subdomain(pd_to_genpd(dev->pm_domain), &scs[i]->pd); + else if (desc->pd_list) + gdsc_remove_subdomain_list(desc->pd_list, &scs[i]->pd); } of_genpd_del_provider(dev->of_node); } diff --git a/drivers/clk/qcom/gdsc.h b/drivers/clk/qcom/gdsc.h index 1e2779b823d1c8ca077c9b4cd0a0dbdf5f9457ef..dd843e86c05b2f30e6d9e978681580016333839d 100644 --- a/drivers/clk/qcom/gdsc.h +++ b/drivers/clk/qcom/gdsc.h @@ -80,6 +80,7 @@ struct gdsc_desc { struct device *dev; struct gdsc **scs; size_t num; + struct dev_pm_domain_list *pd_list; }; #ifdef CONFIG_QCOM_GDSC
When a clock-controller has multiple power-domains we need to attach parent GDSCs in that clock-controller as subdomains of each of the power-domains. Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> --- drivers/clk/qcom/common.c | 1 + drivers/clk/qcom/gdsc.c | 35 +++++++++++++++++++++++++++++++++++ drivers/clk/qcom/gdsc.h | 1 + 3 files changed, 37 insertions(+)