diff options
Diffstat (limited to 'drivers/opp')
-rw-r--r-- | drivers/opp/core.c | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/drivers/opp/core.c b/drivers/opp/core.c index 0eaa954b3f6c..eec1b60d7781 100644 --- a/drivers/opp/core.c +++ b/drivers/opp/core.c @@ -1708,6 +1708,69 @@ void dev_pm_opp_put_genpd_virt_dev(struct opp_table *opp_table, } /** + * 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. + * @dst_table: Required OPP table of the src_table. + * @pstate: Current performance state of the src_table. + * + * This Returns pstate of the OPP (present in @dst_table) pointed out by the + * "required-opps" property of the OPP (present in @src_table) which has + * performance state set to @pstate. + * + * Return: Zero or positive performance state on success, otherwise negative + * value on errors. + */ +int dev_pm_opp_xlate_performance_state(struct opp_table *src_table, + struct opp_table *dst_table, + unsigned int pstate) +{ + struct dev_pm_opp *opp; + int dest_pstate = -EINVAL; + int i; + + if (!pstate) + return 0; + + /* + * Normally the src_table will have the "required_opps" property set to + * point to one of the OPPs in the dst_table, but in some cases the + * genpd and its master have one to one mapping of performance states + * and so none of them have the "required-opps" property set. Return the + * pstate of the src_table as it is in such cases. + */ + if (!src_table->required_opp_count) + return pstate; + + for (i = 0; i < src_table->required_opp_count; i++) { + if (src_table->required_opp_tables[i]->np == dst_table->np) + break; + } + + if (unlikely(i == src_table->required_opp_count)) { + pr_err("%s: Couldn't find matching OPP table (%p: %p)\n", + __func__, src_table, dst_table); + return -EINVAL; + } + + mutex_lock(&src_table->lock); + + list_for_each_entry(opp, &src_table->opp_list, node) { + if (opp->pstate == pstate) { + dest_pstate = opp->required_opps[i]->pstate; + goto unlock; + } + } + + pr_err("%s: Couldn't find matching OPP (%p: %p)\n", __func__, src_table, + dst_table); + +unlock: + mutex_unlock(&src_table->lock); + + return dest_pstate; +} + +/** * dev_pm_opp_add() - Add an OPP table from a table definitions * @dev: device for which we do this operation * @freq: Frequency in Hz for this OPP |