kernel: bump 4.9 to 4.9.117 for 18.06
[oweals/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);