| From bdda05c237a396cd7d0e7199a74e21e554762712 Mon Sep 17 00:00:00 2001 |
| From: Dmitry Osipenko <digetx@gmail.com> |
| Date: Thu, 2 May 2019 02:38:00 +0300 |
| Subject: [PATCH] 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: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/drivers/devfreq/tegra-devfreq.c b/drivers/devfreq/tegra-devfreq.c |
| index 35c38aad8b4f..cd15c96dd27f 100644 |
| --- a/drivers/devfreq/tegra-devfreq.c |
| +++ b/drivers/devfreq/tegra-devfreq.c |
| @@ -474,11 +474,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); |
| @@ -487,8 +487,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; |
| } |
| |
| @@ -498,7 +496,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; |
| @@ -553,7 +551,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; |
| } |
| -- |
| 2.7.4 |
| |