summaryrefslogtreecommitdiff
path: root/drivers/devfreq
diff options
context:
space:
mode:
authorDmitry Osipenko <digetx@gmail.com>2019-05-02 02:38:00 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2019-10-11 18:18:30 +0200
commit938284992abe090fa170e9947b703ccd6f57c864 (patch)
tree4912a3243f12f40ca6a050edeffad4bb4e15824d /drivers/devfreq
parent5ff375e9dcb5a9ec75f460aaa61fd605a731dda9 (diff)
PM / devfreq: tegra: Fix kHz to Hz conversion
commit 62bacb06b9f08965c4ef10e17875450490c948c0 upstream. The kHz to Hz is incorrectly converted in a few places in the code, this results in a wrong frequency being calculated because devfreq core uses OPP frequencies that are given in Hz to clamp the rate, while tegra-devfreq gives to the core value in kHz and then it also expects to receive value in kHz from the core. In a result memory freq is always set to a value which is close to ULONG_MAX because of the bug. Hence the EMC frequency is always capped to the maximum and the driver doesn't do anything useful. This patch was tested on Tegra30 and Tegra124 SoC's, EMC frequency scaling works properly now. Cc: <stable@vger.kernel.org> # 4.14+ Tested-by: Steev Klimaszewski <steev@kali.org> Reviewed-by: Chanwoo Choi <cw00.choi@samsung.com> Signed-off-by: Dmitry Osipenko <digetx@gmail.com> Acked-by: Thierry Reding <treding@nvidia.com> Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/devfreq')
-rw-r--r--drivers/devfreq/tegra-devfreq.c12
1 files changed, 5 insertions, 7 deletions
diff --git a/drivers/devfreq/tegra-devfreq.c b/drivers/devfreq/tegra-devfreq.c
index ae712159246f..6627a7dce95c 100644
--- a/drivers/devfreq/tegra-devfreq.c
+++ b/drivers/devfreq/tegra-devfreq.c
@@ -485,11 +485,11 @@ static int tegra_devfreq_target(struct device *dev, unsigned long *freq,
{
struct tegra_devfreq *tegra = dev_get_drvdata(dev);
struct dev_pm_opp *opp;
- unsigned long rate = *freq * KHZ;
+ unsigned long rate;
- opp = devfreq_recommended_opp(dev, &rate, flags);
+ opp = devfreq_recommended_opp(dev, freq, flags);
if (IS_ERR(opp)) {
- dev_err(dev, "Failed to find opp for %lu KHz\n", *freq);
+ dev_err(dev, "Failed to find opp for %lu Hz\n", *freq);
return PTR_ERR(opp);
}
rate = dev_pm_opp_get_freq(opp);
@@ -498,8 +498,6 @@ static int tegra_devfreq_target(struct device *dev, unsigned long *freq,
clk_set_min_rate(tegra->emc_clock, rate);
clk_set_rate(tegra->emc_clock, 0);
- *freq = rate;
-
return 0;
}
@@ -509,7 +507,7 @@ static int tegra_devfreq_get_dev_status(struct device *dev,
struct tegra_devfreq *tegra = dev_get_drvdata(dev);
struct tegra_devfreq_device *actmon_dev;
- stat->current_frequency = tegra->cur_freq;
+ stat->current_frequency = tegra->cur_freq * KHZ;
/* To be used by the tegra governor */
stat->private_data = tegra;
@@ -564,7 +562,7 @@ static int tegra_governor_get_target(struct devfreq *devfreq,
target_freq = max(target_freq, dev->target_freq);
}
- *freq = target_freq;
+ *freq = target_freq * KHZ;
return 0;
}