kernel: bump 4.9 to 4.9.127
[openwrt/openwrt.git] / target / linux / layerscape / patches-4.9 / 803-cpufreq-support-layerscape.patch
1 From b018e44a68dc2f4df819ae194e39e07313841dad Mon Sep 17 00:00:00 2001
2 From: Yangbo Lu <yangbo.lu@nxp.com>
3 Date: Wed, 17 Jan 2018 15:27:58 +0800
4 Subject: [PATCH 15/30] cpufreq: support layerscape
5
6 This is an 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 drivers/soc/fsl/rcpm.c | 158 ++++++++++++++++++++++++++++++++++++
15 4 files changed, 235 insertions(+), 113 deletions(-)
16 create mode 100644 drivers/soc/fsl/rcpm.c
17
18 --- a/drivers/cpufreq/Kconfig
19 +++ b/drivers/cpufreq/Kconfig
20 @@ -334,7 +334,7 @@ endif
21
22 config QORIQ_CPUFREQ
23 tristate "CPU frequency scaling driver for Freescale QorIQ SoCs"
24 - depends on OF && COMMON_CLK && (PPC_E500MC || ARM)
25 + depends on OF && COMMON_CLK && (PPC_E500MC || ARM || ARM64)
26 depends on !CPU_THERMAL || THERMAL
27 select CLK_QORIQ
28 help
29 --- a/drivers/cpufreq/qoriq-cpufreq.c
30 +++ b/drivers/cpufreq/qoriq-cpufreq.c
31 @@ -11,6 +11,7 @@
32 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
33
34 #include <linux/clk.h>
35 +#include <linux/clk-provider.h>
36 #include <linux/cpufreq.h>
37 #include <linux/cpu_cooling.h>
38 #include <linux/errno.h>
39 @@ -22,10 +23,6 @@
40 #include <linux/slab.h>
41 #include <linux/smp.h>
42
43 -#if !defined(CONFIG_ARM)
44 -#include <asm/smp.h> /* for get_hard_smp_processor_id() in UP configs */
45 -#endif
46 -
47 /**
48 * struct cpu_data
49 * @pclk: the parent clock of cpu
50 @@ -37,73 +34,51 @@ struct cpu_data {
51 struct thermal_cooling_device *cdev;
52 };
53
54 +/*
55 + * Don't use cpufreq on this SoC -- used when the SoC would have otherwise
56 + * matched a more generic compatible.
57 + */
58 +#define SOC_BLACKLIST 1
59 +
60 /**
61 * struct soc_data - SoC specific data
62 - * @freq_mask: mask the disallowed frequencies
63 - * @flag: unique flags
64 + * @flags: SOC_xxx
65 */
66 struct soc_data {
67 - u32 freq_mask[4];
68 - u32 flag;
69 -};
70 -
71 -#define FREQ_MASK 1
72 -/* see hardware specification for the allowed frqeuencies */
73 -static const struct soc_data sdata[] = {
74 - { /* used by p2041 and p3041 */
75 - .freq_mask = {0x8, 0x8, 0x2, 0x2},
76 - .flag = FREQ_MASK,
77 - },
78 - { /* used by p5020 */
79 - .freq_mask = {0x8, 0x2},
80 - .flag = FREQ_MASK,
81 - },
82 - { /* used by p4080, p5040 */
83 - .freq_mask = {0},
84 - .flag = 0,
85 - },
86 + u32 flags;
87 };
88
89 -/*
90 - * the minimum allowed core frequency, in Hz
91 - * for chassis v1.0, >= platform frequency
92 - * for chassis v2.0, >= platform frequency / 2
93 - */
94 -static u32 min_cpufreq;
95 -static const u32 *fmask;
96 -
97 -#if defined(CONFIG_ARM)
98 -static int get_cpu_physical_id(int cpu)
99 -{
100 - return topology_core_id(cpu);
101 -}
102 -#else
103 -static int get_cpu_physical_id(int cpu)
104 -{
105 - return get_hard_smp_processor_id(cpu);
106 -}
107 -#endif
108 -
109 static u32 get_bus_freq(void)
110 {
111 struct device_node *soc;
112 u32 sysfreq;
113 + struct clk *pltclk;
114 + int ret;
115
116 + /* get platform freq by searching bus-frequency property */
117 soc = of_find_node_by_type(NULL, "soc");
118 - if (!soc)
119 - return 0;
120 -
121 - if (of_property_read_u32(soc, "bus-frequency", &sysfreq))
122 - sysfreq = 0;
123 + if (soc) {
124 + ret = of_property_read_u32(soc, "bus-frequency", &sysfreq);
125 + of_node_put(soc);
126 + if (!ret)
127 + return sysfreq;
128 + }
129
130 - of_node_put(soc);
131 + /* get platform freq by its clock name */
132 + pltclk = clk_get(NULL, "cg-pll0-div1");
133 + if (IS_ERR(pltclk)) {
134 + pr_err("%s: can't get bus frequency %ld\n",
135 + __func__, PTR_ERR(pltclk));
136 + return PTR_ERR(pltclk);
137 + }
138
139 - return sysfreq;
140 + return clk_get_rate(pltclk);
141 }
142
143 -static struct device_node *cpu_to_clk_node(int cpu)
144 +static struct clk *cpu_to_clk(int cpu)
145 {
146 - struct device_node *np, *clk_np;
147 + struct device_node *np;
148 + struct clk *clk;
149
150 if (!cpu_present(cpu))
151 return NULL;
152 @@ -112,37 +87,28 @@ static struct device_node *cpu_to_clk_no
153 if (!np)
154 return NULL;
155
156 - clk_np = of_parse_phandle(np, "clocks", 0);
157 - if (!clk_np)
158 - return NULL;
159 -
160 + clk = of_clk_get(np, 0);
161 of_node_put(np);
162 -
163 - return clk_np;
164 + return clk;
165 }
166
167 /* traverse cpu nodes to get cpu mask of sharing clock wire */
168 static void set_affected_cpus(struct cpufreq_policy *policy)
169 {
170 - struct device_node *np, *clk_np;
171 struct cpumask *dstp = policy->cpus;
172 + struct clk *clk;
173 int i;
174
175 - np = cpu_to_clk_node(policy->cpu);
176 - if (!np)
177 - return;
178 -
179 for_each_present_cpu(i) {
180 - clk_np = cpu_to_clk_node(i);
181 - if (!clk_np)
182 + clk = cpu_to_clk(i);
183 + if (IS_ERR(clk)) {
184 + pr_err("%s: no clock for cpu %d\n", __func__, i);
185 continue;
186 + }
187
188 - if (clk_np == np)
189 + if (clk_is_match(policy->clk, clk))
190 cpumask_set_cpu(i, dstp);
191 -
192 - of_node_put(clk_np);
193 }
194 - of_node_put(np);
195 }
196
197 /* reduce the duplicated frequencies in frequency table */
198 @@ -198,10 +164,11 @@ static void freq_table_sort(struct cpufr
199
200 static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy)
201 {
202 - struct device_node *np, *pnode;
203 + struct device_node *np;
204 int i, count, ret;
205 - u32 freq, mask;
206 + u32 freq;
207 struct clk *clk;
208 + const struct clk_hw *hwclk;
209 struct cpufreq_frequency_table *table;
210 struct cpu_data *data;
211 unsigned int cpu = policy->cpu;
212 @@ -221,17 +188,13 @@ static int qoriq_cpufreq_cpu_init(struct
213 goto err_nomem2;
214 }
215
216 - pnode = of_parse_phandle(np, "clocks", 0);
217 - if (!pnode) {
218 - pr_err("%s: could not get clock information\n", __func__);
219 - goto err_nomem2;
220 - }
221 + hwclk = __clk_get_hw(policy->clk);
222 + count = clk_hw_get_num_parents(hwclk);
223
224 - count = of_property_count_strings(pnode, "clock-names");
225 data->pclk = kcalloc(count, sizeof(struct clk *), GFP_KERNEL);
226 if (!data->pclk) {
227 pr_err("%s: no memory\n", __func__);
228 - goto err_node;
229 + goto err_nomem2;
230 }
231
232 table = kcalloc(count + 1, sizeof(*table), GFP_KERNEL);
233 @@ -240,23 +203,11 @@ static int qoriq_cpufreq_cpu_init(struct
234 goto err_pclk;
235 }
236
237 - if (fmask)
238 - mask = fmask[get_cpu_physical_id(cpu)];
239 - else
240 - mask = 0x0;
241 -
242 for (i = 0; i < count; i++) {
243 - clk = of_clk_get(pnode, i);
244 + clk = clk_hw_get_parent_by_index(hwclk, i)->clk;
245 data->pclk[i] = clk;
246 freq = clk_get_rate(clk);
247 - /*
248 - * the clock is valid if its frequency is not masked
249 - * and large than minimum allowed frequency.
250 - */
251 - if (freq < min_cpufreq || (mask & (1 << i)))
252 - table[i].frequency = CPUFREQ_ENTRY_INVALID;
253 - else
254 - table[i].frequency = freq / 1000;
255 + table[i].frequency = freq / 1000;
256 table[i].driver_data = i;
257 }
258 freq_table_redup(table, count);
259 @@ -282,7 +233,6 @@ static int qoriq_cpufreq_cpu_init(struct
260 policy->cpuinfo.transition_latency = u64temp + 1;
261
262 of_node_put(np);
263 - of_node_put(pnode);
264
265 return 0;
266
267 @@ -290,10 +240,7 @@ err_nomem1:
268 kfree(table);
269 err_pclk:
270 kfree(data->pclk);
271 -err_node:
272 - of_node_put(pnode);
273 err_nomem2:
274 - policy->driver_data = NULL;
275 kfree(data);
276 err_np:
277 of_node_put(np);
278 @@ -357,12 +304,25 @@ static struct cpufreq_driver qoriq_cpufr
279 .attr = cpufreq_generic_attr,
280 };
281
282 +static const struct soc_data blacklist = {
283 + .flags = SOC_BLACKLIST,
284 +};
285 +
286 static const struct of_device_id node_matches[] __initconst = {
287 - { .compatible = "fsl,p2041-clockgen", .data = &sdata[0], },
288 - { .compatible = "fsl,p3041-clockgen", .data = &sdata[0], },
289 - { .compatible = "fsl,p5020-clockgen", .data = &sdata[1], },
290 - { .compatible = "fsl,p4080-clockgen", .data = &sdata[2], },
291 - { .compatible = "fsl,p5040-clockgen", .data = &sdata[2], },
292 + /* e6500 cannot use cpufreq due to erratum A-008083 */
293 + { .compatible = "fsl,b4420-clockgen", &blacklist },
294 + { .compatible = "fsl,b4860-clockgen", &blacklist },
295 + { .compatible = "fsl,t2080-clockgen", &blacklist },
296 + { .compatible = "fsl,t4240-clockgen", &blacklist },
297 +
298 + { .compatible = "fsl,ls1012a-clockgen", },
299 + { .compatible = "fsl,ls1021a-clockgen", },
300 + { .compatible = "fsl,ls1043a-clockgen", },
301 + { .compatible = "fsl,ls1046a-clockgen", },
302 + { .compatible = "fsl,ls1088a-clockgen", },
303 + { .compatible = "fsl,ls2080a-clockgen", },
304 + { .compatible = "fsl,p4080-clockgen", },
305 + { .compatible = "fsl,qoriq-clockgen-1.0", },
306 { .compatible = "fsl,qoriq-clockgen-2.0", },
307 {}
308 };
309 @@ -380,16 +340,12 @@ static int __init qoriq_cpufreq_init(voi
310
311 match = of_match_node(node_matches, np);
312 data = match->data;
313 - if (data) {
314 - if (data->flag)
315 - fmask = data->freq_mask;
316 - min_cpufreq = get_bus_freq();
317 - } else {
318 - min_cpufreq = get_bus_freq() / 2;
319 - }
320
321 of_node_put(np);
322
323 + if (data && data->flags & SOC_BLACKLIST)
324 + return -ENODEV;
325 +
326 ret = cpufreq_register_driver(&qoriq_cpufreq_driver);
327 if (!ret)
328 pr_info("Freescale QorIQ CPU frequency scaling driver\n");
329 --- a/drivers/firmware/psci.c
330 +++ b/drivers/firmware/psci.c
331 @@ -437,8 +437,12 @@ CPUIDLE_METHOD_OF_DECLARE(psci, "psci",
332
333 static int psci_system_suspend(unsigned long unused)
334 {
335 - return invoke_psci_fn(PSCI_FN_NATIVE(1_0, SYSTEM_SUSPEND),
336 - virt_to_phys(cpu_resume), 0, 0);
337 + u32 state;
338 +
339 + state = ( 2 << PSCI_0_2_POWER_STATE_AFFL_SHIFT) |
340 + (1 << PSCI_0_2_POWER_STATE_TYPE_SHIFT);
341 +
342 + return psci_cpu_suspend(state, virt_to_phys(cpu_resume));
343 }
344
345 static int psci_system_suspend_enter(suspend_state_t state)
346 @@ -458,6 +462,8 @@ static void __init psci_init_system_susp
347 if (!IS_ENABLED(CONFIG_SUSPEND))
348 return;
349
350 + suspend_set_ops(&psci_suspend_ops);
351 +
352 ret = psci_features(PSCI_FN_NATIVE(1_0, SYSTEM_SUSPEND));
353
354 if (ret != PSCI_RET_NOT_SUPPORTED)
355 @@ -562,6 +568,8 @@ static void __init psci_0_2_set_function
356 arm_pm_restart = psci_sys_reset;
357
358 pm_power_off = psci_sys_poweroff;
359 + psci_init_system_suspend();
360 + suspend_set_ops(&psci_suspend_ops);
361 }
362
363 /*
364 --- /dev/null
365 +++ b/drivers/soc/fsl/rcpm.c
366 @@ -0,0 +1,158 @@
367 +/*
368 + * Run Control and Power Management (RCPM) driver
369 + *
370 + * Copyright 2016 NXP
371 + *
372 + * This program is free software; you can redistribute it and/or modify
373 + * it under the terms of the GNU General Public License as published by
374 + * the Free Software Foundation; either version 2 of the License, or
375 + * (at your option) any later version.
376 + *
377 + * This program is distributed in the hope that it will be useful,
378 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
379 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
380 + * GNU General Public License for more details.
381 + *
382 + */
383 +#define pr_fmt(fmt) "RCPM: %s: " fmt, __func__
384 +
385 +#include <linux/kernel.h>
386 +#include <linux/io.h>
387 +#include <linux/of_platform.h>
388 +#include <linux/of_address.h>
389 +#include <linux/suspend.h>
390 +
391 +/* RCPM register offset */
392 +#define RCPM_IPPDEXPCR0 0x140
393 +
394 +#define RCPM_WAKEUP_CELL_SIZE 2
395 +
396 +struct rcpm_config {
397 + int ipp_num;
398 + int ippdexpcr_offset;
399 + u32 ippdexpcr[2];
400 + void *rcpm_reg_base;
401 +};
402 +
403 +static struct rcpm_config *rcpm;
404 +
405 +static inline void rcpm_reg_write(u32 offset, u32 value)
406 +{
407 + iowrite32be(value, rcpm->rcpm_reg_base + offset);
408 +}
409 +
410 +static inline u32 rcpm_reg_read(u32 offset)
411 +{
412 + return ioread32be(rcpm->rcpm_reg_base + offset);
413 +}
414 +
415 +static void rcpm_wakeup_fixup(struct device *dev, void *data)
416 +{
417 + struct device_node *node = dev ? dev->of_node : NULL;
418 + u32 value[RCPM_WAKEUP_CELL_SIZE];
419 + int ret, i;
420 +
421 + if (!dev || !node || !device_may_wakeup(dev))
422 + return;
423 +
424 + /*
425 + * Get the values in the "rcpm-wakeup" property.
426 + * Three values are:
427 + * The first is a pointer to the RCPM node.
428 + * The second is the value of the ippdexpcr0 register.
429 + * The third is the value of the ippdexpcr1 register.
430 + */
431 + ret = of_property_read_u32_array(node, "fsl,rcpm-wakeup",
432 + value, RCPM_WAKEUP_CELL_SIZE);
433 + if (ret)
434 + return;
435 +
436 + pr_debug("wakeup source: the device %s\n", node->full_name);
437 +
438 + for (i = 0; i < rcpm->ipp_num; i++)
439 + rcpm->ippdexpcr[i] |= value[i + 1];
440 +}
441 +
442 +static int rcpm_suspend_prepare(void)
443 +{
444 + int i;
445 + u32 val;
446 +
447 + BUG_ON(!rcpm);
448 +
449 + for (i = 0; i < rcpm->ipp_num; i++)
450 + rcpm->ippdexpcr[i] = 0;
451 +
452 + dpm_for_each_dev(NULL, rcpm_wakeup_fixup);
453 +
454 + for (i = 0; i < rcpm->ipp_num; i++) {
455 + if (rcpm->ippdexpcr[i]) {
456 + val = rcpm_reg_read(rcpm->ippdexpcr_offset + 4 * i);
457 + rcpm_reg_write(rcpm->ippdexpcr_offset + 4 * i,
458 + val | rcpm->ippdexpcr[i]);
459 + pr_debug("ippdexpcr%d = 0x%x\n", i, rcpm->ippdexpcr[i]);
460 + }
461 + }
462 +
463 + return 0;
464 +}
465 +
466 +static int rcpm_suspend_notifier_call(struct notifier_block *bl,
467 + unsigned long state,
468 + void *unused)
469 +{
470 + switch (state) {
471 + case PM_SUSPEND_PREPARE:
472 + rcpm_suspend_prepare();
473 + break;
474 + }
475 +
476 + return NOTIFY_DONE;
477 +}
478 +
479 +static struct rcpm_config rcpm_default_config = {
480 + .ipp_num = 1,
481 + .ippdexpcr_offset = RCPM_IPPDEXPCR0,
482 +};
483 +
484 +static const struct of_device_id rcpm_matches[] = {
485 + {
486 + .compatible = "fsl,qoriq-rcpm-2.1",
487 + .data = &rcpm_default_config,
488 + },
489 + {}
490 +};
491 +
492 +static struct notifier_block rcpm_suspend_notifier = {
493 + .notifier_call = rcpm_suspend_notifier_call,
494 +};
495 +
496 +static int __init layerscape_rcpm_init(void)
497 +{
498 + const struct of_device_id *match;
499 + struct device_node *np;
500 +
501 + np = of_find_matching_node_and_match(NULL, rcpm_matches, &match);
502 + if (!np) {
503 + pr_err("Can't find the RCPM node.\n");
504 + return -EINVAL;
505 + }
506 +
507 + if (match->data)
508 + rcpm = (struct rcpm_config *)match->data;
509 + else
510 + return -EINVAL;
511 +
512 + rcpm->rcpm_reg_base = of_iomap(np, 0);
513 + of_node_put(np);
514 + if (!rcpm->rcpm_reg_base)
515 + return -ENOMEM;
516 +
517 + register_pm_notifier(&rcpm_suspend_notifier);
518 +
519 + pr_info("The RCPM driver initialized.\n");
520 +
521 + return 0;
522 +}
523 +
524 +subsys_initcall(layerscape_rcpm_init);