OPP: Add function to look up required OPP's for a given OPP
authorSaravana Kannan <saravanak@google.com>
Thu, 4 Feb 2021 08:14:22 +0000 (16:14 +0800)
committerViresh Kumar <viresh.kumar@linaro.org>
Thu, 4 Feb 2021 11:00:14 +0000 (16:30 +0530)
Add a function that allows looking up required OPPs given a source OPP
table, destination OPP table and the source OPP.

Signed-off-by: Saravana Kannan <saravanak@google.com>
Signed-off-by: Hsin-Yi Wang <hsinyi@chromium.org>
[ Viresh: Rearranged code, fixed return errors ]
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
drivers/opp/core.c
include/linux/pm_opp.h

index dc95d29..c3f3d92 100644 (file)
@@ -2398,6 +2398,61 @@ devm_pm_opp_attach_genpd(struct device *dev, const char **names,
 }
 EXPORT_SYMBOL_GPL(devm_pm_opp_attach_genpd);
 
+/**
+ * dev_pm_opp_xlate_required_opp() - Find required OPP for @src_table OPP.
+ * @src_table: OPP table which has @dst_table as one of its required OPP table.
+ * @dst_table: Required OPP table of the @src_table.
+ * @src_opp: OPP from the @src_table.
+ *
+ * This function returns the OPP (present in @dst_table) pointed out by the
+ * "required-opps" property of the @src_opp (present in @src_table).
+ *
+ * The callers are required to call dev_pm_opp_put() for the returned OPP after
+ * use.
+ *
+ * Return: pointer to 'struct dev_pm_opp' on success and errorno otherwise.
+ */
+struct dev_pm_opp *dev_pm_opp_xlate_required_opp(struct opp_table *src_table,
+                                                struct opp_table *dst_table,
+                                                struct dev_pm_opp *src_opp)
+{
+       struct dev_pm_opp *opp, *dest_opp = ERR_PTR(-ENODEV);
+       int i;
+
+       if (!src_table || !dst_table || !src_opp ||
+           !src_table->required_opp_tables)
+               return ERR_PTR(-EINVAL);
+
+       /* required-opps not fully initialized yet */
+       if (lazy_linking_pending(src_table))
+               return ERR_PTR(-EBUSY);
+
+       for (i = 0; i < src_table->required_opp_count; i++) {
+               if (src_table->required_opp_tables[i] == dst_table) {
+                       mutex_lock(&src_table->lock);
+
+                       list_for_each_entry(opp, &src_table->opp_list, node) {
+                               if (opp == src_opp) {
+                                       dest_opp = opp->required_opps[i];
+                                       dev_pm_opp_get(dest_opp);
+                                       break;
+                               }
+                       }
+
+                       mutex_unlock(&src_table->lock);
+                       break;
+               }
+       }
+
+       if (IS_ERR(dest_opp)) {
+               pr_err("%s: Couldn't find matching OPP (%p: %p)\n", __func__,
+                      src_table, dst_table);
+       }
+
+       return dest_opp;
+}
+EXPORT_SYMBOL_GPL(dev_pm_opp_xlate_required_opp);
+
 /**
  * dev_pm_opp_xlate_performance_state() - Find required OPP's pstate for src_table.
  * @src_table: OPP table which has dst_table as one of its required OPP table.
index ab1d15c..c0371ef 100644 (file)
@@ -156,6 +156,7 @@ struct opp_table *devm_pm_opp_register_set_opp_helper(struct device *dev, int (*
 struct opp_table *dev_pm_opp_attach_genpd(struct device *dev, const char **names, struct device ***virt_devs);
 void dev_pm_opp_detach_genpd(struct opp_table *opp_table);
 struct opp_table *devm_pm_opp_attach_genpd(struct device *dev, const char **names, struct device ***virt_devs);
+struct dev_pm_opp *dev_pm_opp_xlate_required_opp(struct opp_table *src_table, struct opp_table *dst_table, struct dev_pm_opp *src_opp);
 int dev_pm_opp_xlate_performance_state(struct opp_table *src_table, struct opp_table *dst_table, unsigned int pstate);
 int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq);
 int dev_pm_opp_set_opp(struct device *dev, struct dev_pm_opp *opp);
@@ -367,6 +368,12 @@ static inline struct opp_table *devm_pm_opp_attach_genpd(struct device *dev,
        return ERR_PTR(-EOPNOTSUPP);
 }
 
+static inline struct dev_pm_opp *dev_pm_opp_xlate_required_opp(struct opp_table *src_table,
+                               struct opp_table *dst_table, struct dev_pm_opp *src_opp)
+{
+       return ERR_PTR(-EOPNOTSUPP);
+}
+
 static inline int dev_pm_opp_xlate_performance_state(struct opp_table *src_table, struct opp_table *dst_table, unsigned int pstate)
 {
        return -EOPNOTSUPP;