2bc0f24f720f3e0352c6b04b29f0d1c3b19f8373
[openwrt/openwrt.git] / target / linux / layerscape / patches-4.9 / 803-cpufreq-support-layerscape.patch
1 From a9ebdf9fa18fd317a4e97f46e8c5263898094864 Mon Sep 17 00:00:00 2001
2 From: Yangbo Lu <yangbo.lu@nxp.com>
3 Date: Mon, 25 Sep 2017 12:20:10 +0800
4 Subject: [PATCH] cpufreq: support layerscape
5
6 This is a integrated patch for layerscape pm support.
7
8 Signed-off-by: Tang Yuantian <Yuantian.Tang@nxp.com>
9 Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
10 ---
11 drivers/cpufreq/Kconfig | 2 +-
12 drivers/cpufreq/qoriq-cpufreq.c | 176 +++++++++++++++-------------------------
13 drivers/firmware/psci.c | 12 ++-
14 3 files changed, 77 insertions(+), 113 deletions(-)
15
16 --- a/drivers/cpufreq/Kconfig
17 +++ b/drivers/cpufreq/Kconfig
18 @@ -332,7 +332,7 @@ endif
19
20 config QORIQ_CPUFREQ
21 tristate "CPU frequency scaling driver for Freescale QorIQ SoCs"
22 - depends on OF && COMMON_CLK && (PPC_E500MC || ARM)
23 + depends on OF && COMMON_CLK && (PPC_E500MC || ARM || ARM64)
24 depends on !CPU_THERMAL || THERMAL
25 select CLK_QORIQ
26 help
27 --- a/drivers/cpufreq/qoriq-cpufreq.c
28 +++ b/drivers/cpufreq/qoriq-cpufreq.c
29 @@ -11,6 +11,7 @@
30 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
31
32 #include <linux/clk.h>
33 +#include <linux/clk-provider.h>
34 #include <linux/cpufreq.h>
35 #include <linux/cpu_cooling.h>
36 #include <linux/errno.h>
37 @@ -22,10 +23,6 @@
38 #include <linux/slab.h>
39 #include <linux/smp.h>
40
41 -#if !defined(CONFIG_ARM)
42 -#include <asm/smp.h> /* for get_hard_smp_processor_id() in UP configs */
43 -#endif
44 -
45 /**
46 * struct cpu_data
47 * @pclk: the parent clock of cpu
48 @@ -37,73 +34,51 @@ struct cpu_data {
49 struct thermal_cooling_device *cdev;
50 };
51
52 +/*
53 + * Don't use cpufreq on this SoC -- used when the SoC would have otherwise
54 + * matched a more generic compatible.
55 + */
56 +#define SOC_BLACKLIST 1
57 +
58 /**
59 * struct soc_data - SoC specific data
60 - * @freq_mask: mask the disallowed frequencies
61 - * @flag: unique flags
62 + * @flags: SOC_xxx
63 */
64 struct soc_data {
65 - u32 freq_mask[4];
66 - u32 flag;
67 -};
68 -
69 -#define FREQ_MASK 1
70 -/* see hardware specification for the allowed frqeuencies */
71 -static const struct soc_data sdata[] = {
72 - { /* used by p2041 and p3041 */
73 - .freq_mask = {0x8, 0x8, 0x2, 0x2},
74 - .flag = FREQ_MASK,
75 - },
76 - { /* used by p5020 */
77 - .freq_mask = {0x8, 0x2},
78 - .flag = FREQ_MASK,
79 - },
80 - { /* used by p4080, p5040 */
81 - .freq_mask = {0},
82 - .flag = 0,
83 - },
84 + u32 flags;
85 };
86
87 -/*
88 - * the minimum allowed core frequency, in Hz
89 - * for chassis v1.0, >= platform frequency
90 - * for chassis v2.0, >= platform frequency / 2
91 - */
92 -static u32 min_cpufreq;
93 -static const u32 *fmask;
94 -
95 -#if defined(CONFIG_ARM)
96 -static int get_cpu_physical_id(int cpu)
97 -{
98 - return topology_core_id(cpu);
99 -}
100 -#else
101 -static int get_cpu_physical_id(int cpu)
102 -{
103 - return get_hard_smp_processor_id(cpu);
104 -}
105 -#endif
106 -
107 static u32 get_bus_freq(void)
108 {
109 struct device_node *soc;
110 u32 sysfreq;
111 + struct clk *pltclk;
112 + int ret;
113
114 + /* get platform freq by searching bus-frequency property */
115 soc = of_find_node_by_type(NULL, "soc");
116 - if (!soc)
117 - return 0;
118 -
119 - if (of_property_read_u32(soc, "bus-frequency", &sysfreq))
120 - sysfreq = 0;
121 + if (soc) {
122 + ret = of_property_read_u32(soc, "bus-frequency", &sysfreq);
123 + of_node_put(soc);
124 + if (!ret)
125 + return sysfreq;
126 + }
127
128 - of_node_put(soc);
129 + /* get platform freq by its clock name */
130 + pltclk = clk_get(NULL, "cg-pll0-div1");
131 + if (IS_ERR(pltclk)) {
132 + pr_err("%s: can't get bus frequency %ld\n",
133 + __func__, PTR_ERR(pltclk));
134 + return PTR_ERR(pltclk);
135 + }
136
137 - return sysfreq;
138 + return clk_get_rate(pltclk);
139 }
140
141 -static struct device_node *cpu_to_clk_node(int cpu)
142 +static struct clk *cpu_to_clk(int cpu)
143 {
144 - struct device_node *np, *clk_np;
145 + struct device_node *np;
146 + struct clk *clk;
147
148 if (!cpu_present(cpu))
149 return NULL;
150 @@ -112,37 +87,28 @@ static struct device_node *cpu_to_clk_no
151 if (!np)
152 return NULL;
153
154 - clk_np = of_parse_phandle(np, "clocks", 0);
155 - if (!clk_np)
156 - return NULL;
157 -
158 + clk = of_clk_get(np, 0);
159 of_node_put(np);
160 -
161 - return clk_np;
162 + return clk;
163 }
164
165 /* traverse cpu nodes to get cpu mask of sharing clock wire */
166 static void set_affected_cpus(struct cpufreq_policy *policy)
167 {
168 - struct device_node *np, *clk_np;
169 struct cpumask *dstp = policy->cpus;
170 + struct clk *clk;
171 int i;
172
173 - np = cpu_to_clk_node(policy->cpu);
174 - if (!np)
175 - return;
176 -
177 for_each_present_cpu(i) {
178 - clk_np = cpu_to_clk_node(i);
179 - if (!clk_np)
180 + clk = cpu_to_clk(i);
181 + if (IS_ERR(clk)) {
182 + pr_err("%s: no clock for cpu %d\n", __func__, i);
183 continue;
184 + }
185
186 - if (clk_np == np)
187 + if (clk_is_match(policy->clk, clk))
188 cpumask_set_cpu(i, dstp);
189 -
190 - of_node_put(clk_np);
191 }
192 - of_node_put(np);
193 }
194
195 /* reduce the duplicated frequencies in frequency table */
196 @@ -198,10 +164,11 @@ static void freq_table_sort(struct cpufr
197
198 static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy)
199 {
200 - struct device_node *np, *pnode;
201 + struct device_node *np;
202 int i, count, ret;
203 - u32 freq, mask;
204 + u32 freq;
205 struct clk *clk;
206 + const struct clk_hw *hwclk;
207 struct cpufreq_frequency_table *table;
208 struct cpu_data *data;
209 unsigned int cpu = policy->cpu;
210 @@ -221,17 +188,13 @@ static int qoriq_cpufreq_cpu_init(struct
211 goto err_nomem2;
212 }
213
214 - pnode = of_parse_phandle(np, "clocks", 0);
215 - if (!pnode) {
216 - pr_err("%s: could not get clock information\n", __func__);
217 - goto err_nomem2;
218 - }
219 + hwclk = __clk_get_hw(policy->clk);
220 + count = clk_hw_get_num_parents(hwclk);
221
222 - count = of_property_count_strings(pnode, "clock-names");
223 data->pclk = kcalloc(count, sizeof(struct clk *), GFP_KERNEL);
224 if (!data->pclk) {
225 pr_err("%s: no memory\n", __func__);
226 - goto err_node;
227 + goto err_nomem2;
228 }
229
230 table = kcalloc(count + 1, sizeof(*table), GFP_KERNEL);
231 @@ -240,23 +203,11 @@ static int qoriq_cpufreq_cpu_init(struct
232 goto err_pclk;
233 }
234
235 - if (fmask)
236 - mask = fmask[get_cpu_physical_id(cpu)];
237 - else
238 - mask = 0x0;
239 -
240 for (i = 0; i < count; i++) {
241 - clk = of_clk_get(pnode, i);
242 + clk = clk_hw_get_parent_by_index(hwclk, i)->clk;
243 data->pclk[i] = clk;
244 freq = clk_get_rate(clk);
245 - /*
246 - * the clock is valid if its frequency is not masked
247 - * and large than minimum allowed frequency.
248 - */
249 - if (freq < min_cpufreq || (mask & (1 << i)))
250 - table[i].frequency = CPUFREQ_ENTRY_INVALID;
251 - else
252 - table[i].frequency = freq / 1000;
253 + table[i].frequency = freq / 1000;
254 table[i].driver_data = i;
255 }
256 freq_table_redup(table, count);
257 @@ -282,7 +233,6 @@ static int qoriq_cpufreq_cpu_init(struct
258 policy->cpuinfo.transition_latency = u64temp + 1;
259
260 of_node_put(np);
261 - of_node_put(pnode);
262
263 return 0;
264
265 @@ -290,10 +240,7 @@ err_nomem1:
266 kfree(table);
267 err_pclk:
268 kfree(data->pclk);
269 -err_node:
270 - of_node_put(pnode);
271 err_nomem2:
272 - policy->driver_data = NULL;
273 kfree(data);
274 err_np:
275 of_node_put(np);
276 @@ -357,12 +304,25 @@ static struct cpufreq_driver qoriq_cpufr
277 .attr = cpufreq_generic_attr,
278 };
279
280 +static const struct soc_data blacklist = {
281 + .flags = SOC_BLACKLIST,
282 +};
283 +
284 static const struct of_device_id node_matches[] __initconst = {
285 - { .compatible = "fsl,p2041-clockgen", .data = &sdata[0], },
286 - { .compatible = "fsl,p3041-clockgen", .data = &sdata[0], },
287 - { .compatible = "fsl,p5020-clockgen", .data = &sdata[1], },
288 - { .compatible = "fsl,p4080-clockgen", .data = &sdata[2], },
289 - { .compatible = "fsl,p5040-clockgen", .data = &sdata[2], },
290 + /* e6500 cannot use cpufreq due to erratum A-008083 */
291 + { .compatible = "fsl,b4420-clockgen", &blacklist },
292 + { .compatible = "fsl,b4860-clockgen", &blacklist },
293 + { .compatible = "fsl,t2080-clockgen", &blacklist },
294 + { .compatible = "fsl,t4240-clockgen", &blacklist },
295 +
296 + { .compatible = "fsl,ls1012a-clockgen", },
297 + { .compatible = "fsl,ls1021a-clockgen", },
298 + { .compatible = "fsl,ls1043a-clockgen", },
299 + { .compatible = "fsl,ls1046a-clockgen", },
300 + { .compatible = "fsl,ls1088a-clockgen", },
301 + { .compatible = "fsl,ls2080a-clockgen", },
302 + { .compatible = "fsl,p4080-clockgen", },
303 + { .compatible = "fsl,qoriq-clockgen-1.0", },
304 { .compatible = "fsl,qoriq-clockgen-2.0", },
305 {}
306 };
307 @@ -380,16 +340,12 @@ static int __init qoriq_cpufreq_init(voi
308
309 match = of_match_node(node_matches, np);
310 data = match->data;
311 - if (data) {
312 - if (data->flag)
313 - fmask = data->freq_mask;
314 - min_cpufreq = get_bus_freq();
315 - } else {
316 - min_cpufreq = get_bus_freq() / 2;
317 - }
318
319 of_node_put(np);
320
321 + if (data && data->flags & SOC_BLACKLIST)
322 + return -ENODEV;
323 +
324 ret = cpufreq_register_driver(&qoriq_cpufreq_driver);
325 if (!ret)
326 pr_info("Freescale QorIQ CPU frequency scaling driver\n");
327 --- a/drivers/firmware/psci.c
328 +++ b/drivers/firmware/psci.c
329 @@ -418,8 +418,12 @@ CPUIDLE_METHOD_OF_DECLARE(psci, "psci",
330
331 static int psci_system_suspend(unsigned long unused)
332 {
333 - return invoke_psci_fn(PSCI_FN_NATIVE(1_0, SYSTEM_SUSPEND),
334 - virt_to_phys(cpu_resume), 0, 0);
335 + u32 state;
336 +
337 + state = ( 2 << PSCI_0_2_POWER_STATE_AFFL_SHIFT) |
338 + (1 << PSCI_0_2_POWER_STATE_TYPE_SHIFT);
339 +
340 + return psci_cpu_suspend(state, virt_to_phys(cpu_resume));
341 }
342
343 static int psci_system_suspend_enter(suspend_state_t state)
344 @@ -439,6 +443,8 @@ static void __init psci_init_system_susp
345 if (!IS_ENABLED(CONFIG_SUSPEND))
346 return;
347
348 + suspend_set_ops(&psci_suspend_ops);
349 +
350 ret = psci_features(PSCI_FN_NATIVE(1_0, SYSTEM_SUSPEND));
351
352 if (ret != PSCI_RET_NOT_SUPPORTED)
353 @@ -516,6 +522,8 @@ static void __init psci_0_2_set_function
354 arm_pm_restart = psci_sys_reset;
355
356 pm_power_off = psci_sys_poweroff;
357 + psci_init_system_suspend();
358 + suspend_set_ops(&psci_suspend_ops);
359 }
360
361 /*