1 From 944b041c91f1e1cd762c39c1222f078550149486 Mon Sep 17 00:00:00 2001
2 From: Jia-Wei Chang <jia-wei.chang@mediatek.com>
3 Date: Thu, 5 May 2022 19:52:20 +0800
4 Subject: [PATCH 10/21] cpufreq: mediatek: Refine
5 mtk_cpufreq_voltage_tracking()
7 Because the difference of sram and proc should in a range of min_volt_shift
8 and max_volt_shift. We need to adjust the sram and proc step by step.
10 We replace VOLT_TOL (voltage tolerance) with the platform data and update the
11 logic to determine the voltage boundary and invoking regulator_set_voltage.
13 - Use 'sram_min_volt' and 'sram_max_volt' to determine the voltage boundary
15 - Use (sram_min_volt - min_volt_shift) and 'proc_max_volt' to determine the
16 voltage boundary of vproc regulator.
18 Moreover, to prevent infinite loop when tracking voltage, we calculate the
19 maximum value for each platform data.
20 We assume min voltage is 0 and tracking target voltage using
21 min_volt_shift for each iteration.
22 The retry_max is 3 times of expeted iteration count.
24 Signed-off-by: Jia-Wei Chang <jia-wei.chang@mediatek.com>
25 Signed-off-by: Rex-BC Chen <rex-bc.chen@mediatek.com>
26 Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
27 Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
29 drivers/cpufreq/mediatek-cpufreq.c | 147 ++++++++++-------------------
30 1 file changed, 51 insertions(+), 96 deletions(-)
32 --- a/drivers/cpufreq/mediatek-cpufreq.c
33 +++ b/drivers/cpufreq/mediatek-cpufreq.c
35 #include <linux/cpu.h>
36 #include <linux/cpufreq.h>
37 #include <linux/cpumask.h>
38 +#include <linux/minmax.h>
39 #include <linux/module.h>
41 #include <linux/of_platform.h>
43 #include <linux/pm_opp.h>
44 #include <linux/regulator/consumer.h>
46 -#define VOLT_TOL (10000)
48 struct mtk_cpufreq_platform_data {
51 @@ -48,6 +47,7 @@ struct mtk_cpu_dvfs_info {
52 bool need_voltage_tracking;
54 const struct mtk_cpufreq_platform_data *soc_data;
58 static struct platform_device *cpufreq_pdev;
59 @@ -73,6 +73,7 @@ static int mtk_cpufreq_voltage_tracking(
60 struct regulator *proc_reg = info->proc_reg;
61 struct regulator *sram_reg = info->sram_reg;
62 int pre_vproc, pre_vsram, new_vsram, vsram, vproc, ret;
63 + int retry = info->vtrack_max;
65 pre_vproc = regulator_get_voltage(proc_reg);
67 @@ -80,91 +81,44 @@ static int mtk_cpufreq_voltage_tracking(
68 "invalid Vproc value: %d\n", pre_vproc);
71 - /* Vsram should not exceed the maximum allowed voltage of SoC. */
72 - new_vsram = min(new_vproc + soc_data->min_volt_shift,
73 - soc_data->sram_max_volt);
75 - if (pre_vproc < new_vproc) {
77 - * When scaling up voltages, Vsram and Vproc scale up step
78 - * by step. At each step, set Vsram to (Vproc + 200mV) first,
79 - * then set Vproc to (Vsram - 100mV).
80 - * Keep doing it until Vsram and Vproc hit target voltages.
83 - pre_vsram = regulator_get_voltage(sram_reg);
84 - if (pre_vsram < 0) {
85 - dev_err(info->cpu_dev,
86 - "invalid Vsram value: %d\n", pre_vsram);
89 - pre_vproc = regulator_get_voltage(proc_reg);
90 - if (pre_vproc < 0) {
91 - dev_err(info->cpu_dev,
92 - "invalid Vproc value: %d\n", pre_vproc);
96 - vsram = min(new_vsram,
97 - pre_vproc + soc_data->min_volt_shift);
98 + pre_vsram = regulator_get_voltage(sram_reg);
99 + if (pre_vsram < 0) {
100 + dev_err(info->cpu_dev, "invalid Vsram value: %d\n", pre_vsram);
104 - if (vsram + VOLT_TOL >= soc_data->sram_max_volt) {
105 - vsram = soc_data->sram_max_volt;
106 + new_vsram = clamp(new_vproc + soc_data->min_volt_shift,
107 + soc_data->sram_min_volt, soc_data->sram_max_volt);
110 + if (pre_vproc <= new_vproc) {
111 + vsram = clamp(pre_vproc + soc_data->max_volt_shift,
112 + soc_data->sram_min_volt, new_vsram);
113 + ret = regulator_set_voltage(sram_reg, vsram,
114 + soc_data->sram_max_volt);
117 - * If the target Vsram hits the maximum voltage,
118 - * try to set the exact voltage value first.
120 - ret = regulator_set_voltage(sram_reg, vsram,
123 - ret = regulator_set_voltage(sram_reg,
129 + if (vsram == soc_data->sram_max_volt ||
130 + new_vsram == soc_data->sram_min_volt)
133 - ret = regulator_set_voltage(sram_reg, vsram,
137 vproc = vsram - soc_data->min_volt_shift;
142 ret = regulator_set_voltage(proc_reg, vproc,
144 + soc_data->proc_max_volt);
146 regulator_set_voltage(sram_reg, pre_vsram,
148 + soc_data->sram_max_volt);
151 - } while (vproc < new_vproc || vsram < new_vsram);
152 - } else if (pre_vproc > new_vproc) {
154 - * When scaling down voltages, Vsram and Vproc scale down step
155 - * by step. At each step, set Vproc to (Vsram - 200mV) first,
156 - * then set Vproc to (Vproc + 100mV).
157 - * Keep doing it until Vsram and Vproc hit target voltages.
160 - pre_vproc = regulator_get_voltage(proc_reg);
161 - if (pre_vproc < 0) {
162 - dev_err(info->cpu_dev,
163 - "invalid Vproc value: %d\n", pre_vproc);
166 - pre_vsram = regulator_get_voltage(sram_reg);
167 - if (pre_vsram < 0) {
168 - dev_err(info->cpu_dev,
169 - "invalid Vsram value: %d\n", pre_vsram);
173 + } else if (pre_vproc > new_vproc) {
174 vproc = max(new_vproc,
175 pre_vsram - soc_data->max_volt_shift);
176 ret = regulator_set_voltage(proc_reg, vproc,
178 + soc_data->proc_max_volt);
182 @@ -174,32 +128,24 @@ static int mtk_cpufreq_voltage_tracking(
183 vsram = max(new_vsram,
184 vproc + soc_data->min_volt_shift);
186 - if (vsram + VOLT_TOL >= soc_data->sram_max_volt) {
187 - vsram = soc_data->sram_max_volt;
190 - * If the target Vsram hits the maximum voltage,
191 - * try to set the exact voltage value first.
193 - ret = regulator_set_voltage(sram_reg, vsram,
196 - ret = regulator_set_voltage(sram_reg,
200 - ret = regulator_set_voltage(sram_reg, vsram,
204 + ret = regulator_set_voltage(sram_reg, vsram,
205 + soc_data->sram_max_volt);
207 regulator_set_voltage(proc_reg, pre_vproc,
209 + soc_data->proc_max_volt);
212 - } while (vproc > new_vproc + VOLT_TOL ||
213 - vsram > new_vsram + VOLT_TOL);
221 + dev_err(info->cpu_dev,
222 + "over loop count, failed to set voltage\n");
225 + } while (vproc != new_vproc || vsram != new_vsram);
229 @@ -261,8 +207,8 @@ static int mtk_cpufreq_set_target(struct
230 * If the new voltage or the intermediate voltage is higher than the
231 * current voltage, scale up voltage first.
233 - target_vproc = (inter_vproc > vproc) ? inter_vproc : vproc;
234 - if (pre_vproc < target_vproc) {
235 + target_vproc = max(inter_vproc, vproc);
236 + if (pre_vproc <= target_vproc) {
237 ret = mtk_cpufreq_set_voltage(info, target_vproc);
240 @@ -417,6 +363,15 @@ static int mtk_cpu_dvfs_info_init(struct
242 info->need_voltage_tracking = (info->sram_reg != NULL);
245 + * We assume min voltage is 0 and tracking target voltage using
246 + * min_volt_shift for each iteration.
247 + * The vtrack_max is 3 times of expeted iteration count.
249 + info->vtrack_max = 3 * DIV_ROUND_UP(max(info->soc_data->sram_max_volt,
250 + info->soc_data->proc_max_volt),
251 + info->soc_data->min_volt_shift);
255 out_disable_inter_clock: