]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
OPP: Extend support for the opp-level beyond required-opps
authorUlf Hansson <ulf.hansson@linaro.org>
Mon, 25 Sep 2023 13:17:12 +0000 (15:17 +0200)
committerViresh Kumar <viresh.kumar@linaro.org>
Fri, 6 Oct 2023 07:07:34 +0000 (12:37 +0530)
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>
drivers/opp/core.c

index 60dca60ac4af8bddb0b08e552aec351111642706..8978e94c9ca1ac573566acdecbec0d7c16a87aea 100644 (file)
@@ -1107,6 +1107,28 @@ void _update_set_required_opps(struct opp_table *opp_table)
                opp_table->set_required_opps = _opp_set_required_opps_generic;
 }
 
+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_domain_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);
@@ -1154,8 +1176,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;
 }
@@ -1198,6 +1225,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);
@@ -1241,6 +1272,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);