BACKPORT: OPP: Extend support for the opp-level beyond required-opps

At this point the level (performance state) for an OPP is currently limited
to be requested for a device that is attached to a PM domain.  Moreover,
the device needs to have the so called required-opps assigned to it, which
are based upon OPP tables being described in DT.

To extend the support beyond required-opps and DT, let's enable the level
to be set for all OPPs. More precisely, if the requested OPP has a valid
level let's try to request it through the device's optional PM domain, via
calling dev_pm_domain_set_performance_state().

Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
[ Viresh: Handle NULL opp in _set_opp_level() ]
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>

Bug: 323966425
Change-Id: I6176127586d50324fbb96f099ddad60bb3c910e5
(cherry picked from commit 0025ff64ffcf6bd6ece5484e7818401f77bf115f)
[nikunj: Resolved minor conflict in drivers/opp/core.c ]
[anantg: Use dev_pm_genpd_set_performance_state in drivers/opp/core.c ]
Signed-off-by: Nikunj Kela <quic_nkela@quicinc.com>
Signed-off-by: Anant Goel <quic_anantg@quicinc.com>
This commit is contained in:
Ulf Hansson
2023-09-25 15:17:12 +02:00
committed by Anant Goel
parent 9ba5e19e0d
commit b50a013d33

View File

@@ -1011,6 +1011,28 @@ static int _set_required_opps(struct device *dev,
return ret;
}
static int _set_opp_level(struct device *dev, struct opp_table *opp_table,
struct dev_pm_opp *opp)
{
unsigned int level = 0;
int ret = 0;
if (opp) {
if (!opp->level)
return 0;
level = opp->level;
}
/* Request a new performance state through the device's PM domain. */
ret = dev_pm_genpd_set_performance_state(dev, level);
if (ret)
dev_err(dev, "Failed to set performance state %u (%d)\n", level,
ret);
return ret;
}
static void _find_current_opp(struct device *dev, struct opp_table *opp_table)
{
struct dev_pm_opp *opp = ERR_PTR(-ENODEV);
@@ -1058,8 +1080,13 @@ static int _disable_opp_table(struct device *dev, struct opp_table *opp_table)
if (opp_table->regulators)
regulator_disable(opp_table->regulators[0]);
ret = _set_opp_level(dev, opp_table, NULL);
if (ret)
goto out;
ret = _set_required_opps(dev, opp_table, NULL, false);
out:
opp_table->enabled = false;
return ret;
}
@@ -1102,6 +1129,10 @@ static int _set_opp(struct device *dev, struct opp_table *opp_table,
return ret;
}
ret = _set_opp_level(dev, opp_table, opp);
if (ret)
return ret;
ret = _set_opp_bw(opp_table, opp, dev);
if (ret) {
dev_err(dev, "Failed to set bw: %d\n", ret);
@@ -1145,6 +1176,10 @@ static int _set_opp(struct device *dev, struct opp_table *opp_table,
return ret;
}
ret = _set_opp_level(dev, opp_table, opp);
if (ret)
return ret;
ret = _set_required_opps(dev, opp_table, opp, false);
if (ret) {
dev_err(dev, "Failed to set required opps: %d\n", ret);