summaryrefslogtreecommitdiffstats
path: root/drivers/opp/core.c
diff options
context:
space:
mode:
authorStephen Boyd <swboyd@chromium.org>2019-03-20 15:19:08 +0530
committerViresh Kumar <viresh.kumar@linaro.org>2019-06-17 09:47:32 +0530
commitb3e3759ee4abd72bedbf4b109ff1749d3aea6f21 (patch)
tree1fdb241064ffe49fc2374369815154c87dae5896 /drivers/opp/core.c
parentc0ab9e0812da8e2134dd63d030c8a8abd2112a5a (diff)
downloadblackbird-op-linux-b3e3759ee4abd72bedbf4b109ff1749d3aea6f21.tar.gz
blackbird-op-linux-b3e3759ee4abd72bedbf4b109ff1749d3aea6f21.zip
opp: Don't overwrite rounded clk rate
The OPP table normally contains 'fmax' values corresponding to the voltage or performance levels of each OPP, but we don't necessarily want all the devices to run at fmax all the time. Running at fmax makes sense for devices like CPU/GPU, which have a finite amount of work to do and since a specific amount of energy is consumed at an OPP, its better to run at the highest possible frequency for that voltage value. On the other hand, we have IO devices which need to run at specific frequencies only for their proper functioning, instead of maximum possible frequency. The OPP core currently roundup to the next possible OPP for a frequency and select the fmax value. To support the IO devices by the OPP core, lets do the roundup to fetch the voltage or performance state values, but not use the OPP frequency value. Rather use the value returned by clk_round_rate(). The current user, cpufreq, of dev_pm_opp_set_rate() already does the rounding to the next OPP before calling this routine and it won't have any side affects because of this change. Signed-off-by: Stephen Boyd <swboyd@chromium.org> Signed-off-by: Rajendra Nayak <rnayak@codeaurora.org> [ Viresh: Massaged changelog, added comment and use temp_opp variable instead ] Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Diffstat (limited to 'drivers/opp/core.c')
-rw-r--r--drivers/opp/core.c15
1 files changed, 10 insertions, 5 deletions
diff --git a/drivers/opp/core.c b/drivers/opp/core.c
index 764e05a2fa66..bae94bfa1e96 100644
--- a/drivers/opp/core.c
+++ b/drivers/opp/core.c
@@ -751,13 +751,16 @@ static int _set_required_opps(struct device *dev,
* @dev: device for which we do this operation
* @target_freq: frequency to achieve
*
- * This configures the power-supplies and clock source to the levels specified
- * by the OPP corresponding to the target_freq.
+ * This configures the power-supplies to the levels specified by the OPP
+ * corresponding to the target_freq, and programs the clock to a value <=
+ * target_freq, as rounded by clk_round_rate(). Device wanting to run at fmax
+ * provided by the opp, should have already rounded to the target OPP's
+ * frequency.
*/
int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq)
{
struct opp_table *opp_table;
- unsigned long freq, old_freq;
+ unsigned long freq, old_freq, temp_freq;
struct dev_pm_opp *old_opp, *opp;
struct clk *clk;
int ret;
@@ -796,13 +799,15 @@ int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq)
goto put_opp_table;
}
- old_opp = _find_freq_ceil(opp_table, &old_freq);
+ temp_freq = old_freq;
+ old_opp = _find_freq_ceil(opp_table, &temp_freq);
if (IS_ERR(old_opp)) {
dev_err(dev, "%s: failed to find current OPP for freq %lu (%ld)\n",
__func__, old_freq, PTR_ERR(old_opp));
}
- opp = _find_freq_ceil(opp_table, &freq);
+ temp_freq = freq;
+ opp = _find_freq_ceil(opp_table, &temp_freq);
if (IS_ERR(opp)) {
ret = PTR_ERR(opp);
dev_err(dev, "%s: failed to find OPP for freq %lu (%d)\n",
OpenPOWER on IntegriCloud