Skip to content

Commit 2c59138

Browse files
stephan-ghvireshk
authored andcommitted
opp: Set required OPPs in reverse order when scaling down
The OPP core already has well-defined semantics to ensure required OPPs/regulators are set before/after the frequency change, depending on if we scale up or down. Similar requirements might exist for the order of required OPPs when multiple power domains need to be scaled for a frequency change. For example, on Qualcomm platforms using CPR (Core Power Reduction), we need to scale the VDDMX and CPR power domain. When scaling up, MX should be scaled up before CPR. When scaling down, CPR should be scaled down before MX. In general, if there are multiple "required-opps" in the device tree I would expect that the order is either irrelevant, or there is some dependency between the power domains. In that case, the power domains should be scaled down in reverse order. This commit updates _set_required_opps() to set required OPPs in reverse order when scaling down. Signed-off-by: Stephan Gerhold <stephan@gerhold.net> [ Viresh: Fix rebase conflict and minor rearrangement of the code ] Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
1 parent 60cdeae commit 2c59138

1 file changed

Lines changed: 19 additions & 8 deletions

File tree

drivers/opp/core.c

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -800,7 +800,7 @@ static int _set_required_opp(struct device *dev, struct device *pd_dev,
800800
/* This is only called for PM domain for now */
801801
static int _set_required_opps(struct device *dev,
802802
struct opp_table *opp_table,
803-
struct dev_pm_opp *opp)
803+
struct dev_pm_opp *opp, bool up)
804804
{
805805
struct opp_table **required_opp_tables = opp_table->required_opp_tables;
806806
struct device **genpd_virt_devs = opp_table->genpd_virt_devs;
@@ -820,11 +820,22 @@ static int _set_required_opps(struct device *dev,
820820
* after it is freed from another thread.
821821
*/
822822
mutex_lock(&opp_table->genpd_virt_dev_lock);
823-
for (i = 0; i < opp_table->required_opp_count; i++) {
824-
ret = _set_required_opp(dev, genpd_virt_devs[i], opp, i);
825-
if (ret)
826-
break;
823+
824+
/* Scaling up? Set required OPPs in normal order, else reverse */
825+
if (up) {
826+
for (i = 0; i < opp_table->required_opp_count; i++) {
827+
ret = _set_required_opp(dev, genpd_virt_devs[i], opp, i);
828+
if (ret)
829+
break;
830+
}
831+
} else {
832+
for (i = opp_table->required_opp_count - 1; i >= 0; i--) {
833+
ret = _set_required_opp(dev, genpd_virt_devs[i], opp, i);
834+
if (ret)
835+
break;
836+
}
827837
}
838+
828839
mutex_unlock(&opp_table->genpd_virt_dev_lock);
829840

830841
return ret;
@@ -883,7 +894,7 @@ static int _opp_set_rate_zero(struct device *dev, struct opp_table *opp_table)
883894
if (opp_table->regulators)
884895
regulator_disable(opp_table->regulators[0]);
885896

886-
ret = _set_required_opps(dev, opp_table, NULL);
897+
ret = _set_required_opps(dev, opp_table, NULL, false);
887898

888899
opp_table->enabled = false;
889900
return ret;
@@ -974,7 +985,7 @@ int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq)
974985

975986
/* Scaling up? Configure required OPPs before frequency */
976987
if (freq >= old_freq) {
977-
ret = _set_required_opps(dev, opp_table, opp);
988+
ret = _set_required_opps(dev, opp_table, opp, true);
978989
if (ret)
979990
goto put_opp;
980991
}
@@ -994,7 +1005,7 @@ int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq)
9941005

9951006
/* Scaling down? Configure required OPPs after frequency */
9961007
if (!ret && freq < old_freq) {
997-
ret = _set_required_opps(dev, opp_table, opp);
1008+
ret = _set_required_opps(dev, opp_table, opp, false);
9981009
if (ret)
9991010
dev_err(dev, "Failed to set required opps: %d\n", ret);
10001011
}

0 commit comments

Comments
 (0)