Skip to content

Commit 0025ff6

Browse files
storulfvireshk
authored andcommitted
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 <[email protected]> [ Viresh: Handle NULL opp in _set_opp_level() ] Signed-off-by: Viresh Kumar <[email protected]>
1 parent 892c60c commit 0025ff6

File tree

1 file changed

+35
-0
lines changed

1 file changed

+35
-0
lines changed

drivers/opp/core.c

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1107,6 +1107,28 @@ void _update_set_required_opps(struct opp_table *opp_table)
11071107
opp_table->set_required_opps = _opp_set_required_opps_generic;
11081108
}
11091109

1110+
static int _set_opp_level(struct device *dev, struct opp_table *opp_table,
1111+
struct dev_pm_opp *opp)
1112+
{
1113+
unsigned int level = 0;
1114+
int ret = 0;
1115+
1116+
if (opp) {
1117+
if (!opp->level)
1118+
return 0;
1119+
1120+
level = opp->level;
1121+
}
1122+
1123+
/* Request a new performance state through the device's PM domain. */
1124+
ret = dev_pm_domain_set_performance_state(dev, level);
1125+
if (ret)
1126+
dev_err(dev, "Failed to set performance state %u (%d)\n", level,
1127+
ret);
1128+
1129+
return ret;
1130+
}
1131+
11101132
static void _find_current_opp(struct device *dev, struct opp_table *opp_table)
11111133
{
11121134
struct dev_pm_opp *opp = ERR_PTR(-ENODEV);
@@ -1154,8 +1176,13 @@ static int _disable_opp_table(struct device *dev, struct opp_table *opp_table)
11541176
if (opp_table->regulators)
11551177
regulator_disable(opp_table->regulators[0]);
11561178

1179+
ret = _set_opp_level(dev, opp_table, NULL);
1180+
if (ret)
1181+
goto out;
1182+
11571183
ret = _set_required_opps(dev, opp_table, NULL, false);
11581184

1185+
out:
11591186
opp_table->enabled = false;
11601187
return ret;
11611188
}
@@ -1198,6 +1225,10 @@ static int _set_opp(struct device *dev, struct opp_table *opp_table,
11981225
return ret;
11991226
}
12001227

1228+
ret = _set_opp_level(dev, opp_table, opp);
1229+
if (ret)
1230+
return ret;
1231+
12011232
ret = _set_opp_bw(opp_table, opp, dev);
12021233
if (ret) {
12031234
dev_err(dev, "Failed to set bw: %d\n", ret);
@@ -1241,6 +1272,10 @@ static int _set_opp(struct device *dev, struct opp_table *opp_table,
12411272
return ret;
12421273
}
12431274

1275+
ret = _set_opp_level(dev, opp_table, opp);
1276+
if (ret)
1277+
return ret;
1278+
12441279
ret = _set_required_opps(dev, opp_table, opp, false);
12451280
if (ret) {
12461281
dev_err(dev, "Failed to set required opps: %d\n", ret);

0 commit comments

Comments
 (0)