On Mon, Mar 2, 2020 at 12:59 PM Daniel Baluta <daniel.baluta@xxxxxxxxxxx> wrote: > From: Daniel Baluta <daniel.baluta@xxxxxxx> > > This patch introduces helpers support for multi PM domains. > > API consists of: > > 1) dev_multi_pm_attach - powers up all PM domains associated with a given > device. Because we can attach one PM domain per device, we create > virtual devices (children of initial device) and associate PM domains > one per virtual device. > > 2) dev_multi_pm_detach - detaches all virtual devices from PM domains > attached with. > > Signed-off-by: Daniel Baluta <daniel.baluta@xxxxxxx> > --- > drivers/base/power/common.c | 93 +++++++++++++++++++++++++++++++++++++ > include/linux/pm_domain.h | 19 ++++++++ > 2 files changed, 112 insertions(+) > > diff --git a/drivers/base/power/common.c b/drivers/base/power/common.c > index bbddb267c2e6..a90cc6b476e4 100644 > --- a/drivers/base/power/common.c > +++ b/drivers/base/power/common.c > @@ -228,3 +228,96 @@ void dev_pm_domain_set(struct device *dev, struct > dev_pm_domain *pd) > device_pm_check_callbacks(dev); > } > EXPORT_SYMBOL_GPL(dev_pm_domain_set); > + > +/** > + * dev_multi_pm_attach - power up device associated power domains > + * @dev: The device used to lookup the PM domains > + * > + * Parse device's OF node to find all PM domains specifiers. For each > power > + * domain found, create a virtual device and associate it with the > + * current power domain. > + * > + * This function should typically be invoked by a driver during the > + * probe phase, in the case its device requires power management through > + * multiple PM domains. > + * > + * Returns a pointer to @dev_multi_pm_domain_data if successfully > attached PM > + * domains, NULL if 0 or 1 PM domains specified, else an ERR_PTR() in > case of > + * failures. > + */ > +struct dev_multi_pm_domain_data *dev_multi_pm_attach(struct device *dev) > +{ > + struct dev_multi_pm_domain_data *mpd, *retp; > + int num_domains; > + int i; > + > + num_domains = of_count_phandle_with_args(dev->of_node, > "power-domains", > + "#power-domain-cells"); > + if (num_domains < 2) > Hi Daniel, Just out of curiosity, should it be an error when num_domains is 1? Is it an error because the expectation is that the caller would use dev_pm_domain_attach() in that case? + return NULL; > + > + mpd = devm_kzalloc(dev, GFP_KERNEL, sizeof(*mpd)); > + if (!mpd) > + return ERR_PTR(-ENOMEM); > + > + mpd->dev = dev; > + mpd->num_domains = num_domains; > + > + mpd->virt_devs = devm_kmalloc_array(dev, mpd->num_domains, > + sizeof(*mpd->virt_devs), > + GFP_KERNEL); > + if (!mpd->virt_devs) > + return ERR_PTR(-ENOMEM); > + > + mpd->links = devm_kmalloc_array(dev, mpd->num_domains, > + sizeof(*mpd->links), GFP_KERNEL); > + if (!mpd->links) > + return ERR_PTR(-ENOMEM); > + > + for (i = 0; i < mpd->num_domains; i++) { > + mpd->virt_devs[i] = dev_pm_domain_attach_by_id(dev, i); > + if (IS_ERR(mpd->virt_devs[i])) { > + retp = (struct dev_multi_pm_domain_data *) > + mpd->virt_devs[i]; > Should retp be PTR_ERR(mpd->virt_devs[i]) here? Thanks, Ranjani