mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 20:07:46 +09:00
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:
@@ -1011,6 +1011,28 @@ static int _set_required_opps(struct device *dev,
|
|||||||
return ret;
|
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)
|
static void _find_current_opp(struct device *dev, struct opp_table *opp_table)
|
||||||
{
|
{
|
||||||
struct dev_pm_opp *opp = ERR_PTR(-ENODEV);
|
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)
|
if (opp_table->regulators)
|
||||||
regulator_disable(opp_table->regulators[0]);
|
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);
|
ret = _set_required_opps(dev, opp_table, NULL, false);
|
||||||
|
|
||||||
|
out:
|
||||||
opp_table->enabled = false;
|
opp_table->enabled = false;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -1102,6 +1129,10 @@ static int _set_opp(struct device *dev, struct opp_table *opp_table,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = _set_opp_level(dev, opp_table, opp);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
ret = _set_opp_bw(opp_table, opp, dev);
|
ret = _set_opp_bw(opp_table, opp, dev);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(dev, "Failed to set bw: %d\n", 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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = _set_opp_level(dev, opp_table, opp);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
ret = _set_required_opps(dev, opp_table, opp, false);
|
ret = _set_required_opps(dev, opp_table, opp, false);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(dev, "Failed to set required opps: %d\n", ret);
|
dev_err(dev, "Failed to set required opps: %d\n", ret);
|
||||||
|
|||||||
Reference in New Issue
Block a user