0ba9471ffa71283c94c8c67b5c71acec19b894d6
[openwrt/staging/ldir.git] /
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()
6
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.
9
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.
12
13 - Use 'sram_min_volt' and 'sram_max_volt' to determine the voltage boundary
14 of sram regulator.
15 - Use (sram_min_volt - min_volt_shift) and 'proc_max_volt' to determine the
16 voltage boundary of vproc regulator.
17
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.
23
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>
28 ---
29 drivers/cpufreq/mediatek-cpufreq.c | 147 ++++++++++-------------------
30 1 file changed, 51 insertions(+), 96 deletions(-)
31
32 --- a/drivers/cpufreq/mediatek-cpufreq.c
33 +++ b/drivers/cpufreq/mediatek-cpufreq.c
34 @@ -8,6 +8,7 @@
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>
40 #include <linux/of.h>
41 #include <linux/of_platform.h>
42 @@ -15,8 +16,6 @@
43 #include <linux/pm_opp.h>
44 #include <linux/regulator/consumer.h>
45
46 -#define VOLT_TOL (10000)
47 -
48 struct mtk_cpufreq_platform_data {
49 int min_volt_shift;
50 int max_volt_shift;
51 @@ -48,6 +47,7 @@ struct mtk_cpu_dvfs_info {
52 bool need_voltage_tracking;
53 int pre_vproc;
54 const struct mtk_cpufreq_platform_data *soc_data;
55 + int vtrack_max;
56 };
57
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;
64
65 pre_vproc = regulator_get_voltage(proc_reg);
66 if (pre_vproc < 0) {
67 @@ -80,91 +81,44 @@ static int mtk_cpufreq_voltage_tracking(
68 "invalid Vproc value: %d\n", pre_vproc);
69 return pre_vproc;
70 }
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);
74 -
75 - if (pre_vproc < new_vproc) {
76 - /*
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.
81 - */
82 - do {
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);
87 - return pre_vsram;
88 - }
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);
93 - return pre_vproc;
94 - }
95
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);
101 + return pre_vsram;
102 + }
103
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);
108 +
109 + do {
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);
115
116 - /*
117 - * If the target Vsram hits the maximum voltage,
118 - * try to set the exact voltage value first.
119 - */
120 - ret = regulator_set_voltage(sram_reg, vsram,
121 - vsram);
122 - if (ret)
123 - ret = regulator_set_voltage(sram_reg,
124 - vsram - VOLT_TOL,
125 - vsram);
126 + if (ret)
127 + return ret;
128
129 + if (vsram == soc_data->sram_max_volt ||
130 + new_vsram == soc_data->sram_min_volt)
131 vproc = new_vproc;
132 - } else {
133 - ret = regulator_set_voltage(sram_reg, vsram,
134 - vsram + VOLT_TOL);
135 -
136 + else
137 vproc = vsram - soc_data->min_volt_shift;
138 - }
139 - if (ret)
140 - return ret;
141
142 ret = regulator_set_voltage(proc_reg, vproc,
143 - vproc + VOLT_TOL);
144 + soc_data->proc_max_volt);
145 if (ret) {
146 regulator_set_voltage(sram_reg, pre_vsram,
147 - pre_vsram);
148 + soc_data->sram_max_volt);
149 return ret;
150 }
151 - } while (vproc < new_vproc || vsram < new_vsram);
152 - } else if (pre_vproc > new_vproc) {
153 - /*
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.
158 - */
159 - do {
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);
164 - return pre_vproc;
165 - }
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);
170 - return pre_vsram;
171 - }
172 -
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,
177 - vproc + VOLT_TOL);
178 + soc_data->proc_max_volt);
179 if (ret)
180 return ret;
181
182 @@ -174,32 +128,24 @@ static int mtk_cpufreq_voltage_tracking(
183 vsram = max(new_vsram,
184 vproc + soc_data->min_volt_shift);
185
186 - if (vsram + VOLT_TOL >= soc_data->sram_max_volt) {
187 - vsram = soc_data->sram_max_volt;
188 -
189 - /*
190 - * If the target Vsram hits the maximum voltage,
191 - * try to set the exact voltage value first.
192 - */
193 - ret = regulator_set_voltage(sram_reg, vsram,
194 - vsram);
195 - if (ret)
196 - ret = regulator_set_voltage(sram_reg,
197 - vsram - VOLT_TOL,
198 - vsram);
199 - } else {
200 - ret = regulator_set_voltage(sram_reg, vsram,
201 - vsram + VOLT_TOL);
202 - }
203 -
204 + ret = regulator_set_voltage(sram_reg, vsram,
205 + soc_data->sram_max_volt);
206 if (ret) {
207 regulator_set_voltage(proc_reg, pre_vproc,
208 - pre_vproc);
209 + soc_data->proc_max_volt);
210 return ret;
211 }
212 - } while (vproc > new_vproc + VOLT_TOL ||
213 - vsram > new_vsram + VOLT_TOL);
214 - }
215 + }
216 +
217 + pre_vproc = vproc;
218 + pre_vsram = vsram;
219 +
220 + if (--retry < 0) {
221 + dev_err(info->cpu_dev,
222 + "over loop count, failed to set voltage\n");
223 + return -EINVAL;
224 + }
225 + } while (vproc != new_vproc || vsram != new_vsram);
226
227 return 0;
228 }
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.
232 */
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);
238 if (ret) {
239 dev_err(cpu_dev,
240 @@ -417,6 +363,15 @@ static int mtk_cpu_dvfs_info_init(struct
241 */
242 info->need_voltage_tracking = (info->sram_reg != NULL);
243
244 + /*
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.
248 + */
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);
252 +
253 return 0;
254
255 out_disable_inter_clock: