]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
PM: domains: Support required OPPs in dev_pm_domain_attach_list()
authorUlf Hansson <ulf.hansson@linaro.org>
Wed, 2 Oct 2024 12:22:25 +0000 (14:22 +0200)
committerUlf Hansson <ulf.hansson@linaro.org>
Thu, 10 Oct 2024 12:13:49 +0000 (14:13 +0200)
In the multiple PM domain case we need platform code to specify the index
of the corresponding required OPP in DT for a device, which is what
*_opp_attach_genpd() is there to help us with.

However, attaching a device to its PM domains is in general better done
with dev_pm_domain_attach_list(). To avoid having two different ways to
manage this and to prepare for the removal of *_opp_attach_genpd(), let's
extend dev_pm_domain_attach|detach_list() to manage the required OPPs too.

Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
Link: https://lore.kernel.org/r/20241002122232.194245-5-ulf.hansson@linaro.org
drivers/base/power/common.c
include/linux/pm_domain.h

index cca2fd0a1aed64b368c8c8e33ec4a8ad554b37af..781968a128ff75c1051da83fbc631406ad481289 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/pm_clock.h>
 #include <linux/acpi.h>
 #include <linux/pm_domain.h>
+#include <linux/pm_opp.h>
 
 #include "power.h"
 
@@ -222,13 +223,15 @@ int dev_pm_domain_attach_list(struct device *dev,
        if (!pds)
                return -ENOMEM;
 
-       size = sizeof(*pds->pd_devs) + sizeof(*pds->pd_links);
+       size = sizeof(*pds->pd_devs) + sizeof(*pds->pd_links) +
+              sizeof(*pds->opp_tokens);
        pds->pd_devs = kcalloc(num_pds, size, GFP_KERNEL);
        if (!pds->pd_devs) {
                ret = -ENOMEM;
                goto free_pds;
        }
        pds->pd_links = (void *)(pds->pd_devs + num_pds);
+       pds->opp_tokens = (void *)(pds->pd_links + num_pds);
 
        if (link_flags && pd_flags & PD_FLAG_DEV_LINK_ON)
                link_flags |= DL_FLAG_RPM_ACTIVE;
@@ -244,6 +247,19 @@ int dev_pm_domain_attach_list(struct device *dev,
                        goto err_attach;
                }
 
+               if (pd_flags & PD_FLAG_REQUIRED_OPP) {
+                       struct dev_pm_opp_config config = {
+                               .required_dev = pd_dev,
+                               .required_dev_index = i,
+                       };
+
+                       ret = dev_pm_opp_set_config(dev, &config);
+                       if (ret < 0)
+                               goto err_link;
+
+                       pds->opp_tokens[i] = ret;
+               }
+
                if (link_flags) {
                        struct device_link *link;
 
@@ -264,9 +280,11 @@ int dev_pm_domain_attach_list(struct device *dev,
        return num_pds;
 
 err_link:
+       dev_pm_opp_clear_config(pds->opp_tokens[i]);
        dev_pm_domain_detach(pd_dev, true);
 err_attach:
        while (--i >= 0) {
+               dev_pm_opp_clear_config(pds->opp_tokens[i]);
                if (pds->pd_links[i])
                        device_link_del(pds->pd_links[i]);
                dev_pm_domain_detach(pds->pd_devs[i], true);
@@ -361,6 +379,7 @@ void dev_pm_domain_detach_list(struct dev_pm_domain_list *list)
                return;
 
        for (i = 0; i < list->num_pds; i++) {
+               dev_pm_opp_clear_config(list->opp_tokens[i]);
                if (list->pd_links[i])
                        device_link_del(list->pd_links[i]);
                dev_pm_domain_detach(list->pd_devs[i], true);
index b637ec14025f9dcb0bb70522a342c831bafb08bb..92f9d56f623dc722db8f3e7fea40bba95f2e51c6 100644 (file)
  *                             supplier and its PM domain when creating the
  *                             device-links.
  *
+ * PD_FLAG_REQUIRED_OPP:       Assign required_devs for the required OPPs. The
+ *                             index of the required OPP must correspond to the
+ *                             index in the array of the pd_names. If pd_names
+ *                             isn't specified, the index just follows the
+ *                             index for the attached PM domain.
+ *
  */
 #define PD_FLAG_NO_DEV_LINK            BIT(0)
 #define PD_FLAG_DEV_LINK_ON            BIT(1)
+#define PD_FLAG_REQUIRED_OPP           BIT(2)
 
 struct dev_pm_domain_attach_data {
        const char * const *pd_names;
@@ -43,6 +50,7 @@ struct dev_pm_domain_attach_data {
 struct dev_pm_domain_list {
        struct device **pd_devs;
        struct device_link **pd_links;
+       u32 *opp_tokens;
        u32 num_pds;
 };