OPP: Add function to look up required OPP's for a given OPP

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>
This commit is contained in:
Saravana Kannan 2021-02-04 16:14:22 +08:00 committed by Viresh Kumar
parent 1d61492031
commit 7d8658ef65
2 changed files with 62 additions and 0 deletions

View 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.

View 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;