layerscape: add LS1021AIOT board support
[openwrt/openwrt.git] / target / linux / layerscape / patches-4.9 / 803-cpufreq-support-layerscape.patch
1 From d78d78ccbaded757e8bea0d13c4120518bdd4660 Mon Sep 17 00:00:00 2001
2 From: Yangbo Lu <yangbo.lu@nxp.com>
3 Date: Thu, 5 Jul 2018 17:21:38 +0800
4 Subject: [PATCH 15/32] 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 .../devicetree/bindings/powerpc/fsl/pmc.txt | 59 ++--
12 drivers/cpufreq/Kconfig | 2 +-
13 drivers/cpufreq/qoriq-cpufreq.c | 176 +++++------
14 drivers/firmware/psci.c | 12 +-
15 drivers/soc/fsl/rcpm.c | 158 ++++++++++
16 drivers/soc/fsl/sleep_fsm.c | 279 ++++++++++++++++++
17 drivers/soc/fsl/sleep_fsm.h | 130 ++++++++
18 7 files changed, 678 insertions(+), 138 deletions(-)
19 create mode 100644 drivers/soc/fsl/rcpm.c
20 create mode 100644 drivers/soc/fsl/sleep_fsm.c
21 create mode 100644 drivers/soc/fsl/sleep_fsm.h
22
23 --- a/Documentation/devicetree/bindings/powerpc/fsl/pmc.txt
24 +++ b/Documentation/devicetree/bindings/powerpc/fsl/pmc.txt
25 @@ -9,15 +9,20 @@ Properties:
26
27 "fsl,mpc8548-pmc" should be listed for any chip whose PMC is
28 compatible. "fsl,mpc8536-pmc" should also be listed for any chip
29 - whose PMC is compatible, and implies deep-sleep capability.
30 + whose PMC is compatible, and implies deep-sleep capability and
31 + wake on user defined packet(wakeup on ARP).
32 +
33 + "fsl,p1022-pmc" should be listed for any chip whose PMC is
34 + compatible, and implies lossless Ethernet capability during sleep.
35
36 "fsl,mpc8641d-pmc" should be listed for any chip whose PMC is
37 compatible; all statements below that apply to "fsl,mpc8548-pmc" also
38 apply to "fsl,mpc8641d-pmc".
39
40 Compatibility does not include bit assignments in SCCR/PMCDR/DEVDISR; these
41 - bit assignments are indicated via the sleep specifier in each device's
42 - sleep property.
43 + bit assignments are indicated via the clock nodes. Device which has a
44 + controllable clock source should have a "fsl,pmc-handle" property pointing
45 + to the clock node.
46
47 - reg: For devices compatible with "fsl,mpc8349-pmc", the first resource
48 is the PMC block, and the second resource is the Clock Configuration
49 @@ -33,31 +38,35 @@ Properties:
50 this is a phandle to an "fsl,gtm" node on which timer 4 can be used as
51 a wakeup source from deep sleep.
52
53 -Sleep specifiers:
54 -
55 - fsl,mpc8349-pmc: Sleep specifiers consist of one cell. For each bit
56 - that is set in the cell, the corresponding bit in SCCR will be saved
57 - and cleared on suspend, and restored on resume. This sleep controller
58 - supports disabling and resuming devices at any time.
59 -
60 - fsl,mpc8536-pmc: Sleep specifiers consist of three cells, the third of
61 - which will be ORed into PMCDR upon suspend, and cleared from PMCDR
62 - upon resume. The first two cells are as described for fsl,mpc8578-pmc.
63 - This sleep controller only supports disabling devices during system
64 - sleep, or permanently.
65 -
66 - fsl,mpc8548-pmc: Sleep specifiers consist of one or two cells, the
67 - first of which will be ORed into DEVDISR (and the second into
68 - DEVDISR2, if present -- this cell should be zero or absent if the
69 - hardware does not have DEVDISR2) upon a request for permanent device
70 - disabling. This sleep controller does not support configuring devices
71 - to disable during system sleep (unless supported by another compatible
72 - match), or dynamically.
73 +Clock nodes:
74 +The clock nodes are to describe the masks in PM controller registers for each
75 +soc clock.
76 +- fsl,pmcdr-mask: For "fsl,mpc8548-pmc"-compatible devices, the mask will be
77 + ORed into PMCDR before suspend if the device using this clock is the wake-up
78 + source and need to be running during low power mode; clear the mask if
79 + otherwise.
80 +
81 +- fsl,sccr-mask: For "fsl,mpc8349-pmc"-compatible devices, the corresponding
82 + bit specified by the mask in SCCR will be saved and cleared on suspend, and
83 + restored on resume.
84 +
85 +- fsl,devdisr-mask: Contain one or two cells, depending on the availability of
86 + DEVDISR2 register. For compatible devices, the mask will be ORed into DEVDISR
87 + or DEVDISR2 when the clock should be permenently disabled.
88
89 Example:
90
91 - power@b00 {
92 - compatible = "fsl,mpc8313-pmc", "fsl,mpc8349-pmc";
93 - reg = <0xb00 0x100 0xa00 0x100>;
94 - interrupts = <80 8>;
95 + power@e0070 {
96 + compatible = "fsl,mpc8536-pmc", "fsl,mpc8548-pmc";
97 + reg = <0xe0070 0x20>;
98 +
99 + etsec1_clk: soc-clk@24 {
100 + fsl,pmcdr-mask = <0x00000080>;
101 + };
102 + etsec2_clk: soc-clk@25 {
103 + fsl,pmcdr-mask = <0x00000040>;
104 + };
105 + etsec3_clk: soc-clk@26 {
106 + fsl,pmcdr-mask = <0x00000020>;
107 + };
108 };
109 --- a/drivers/cpufreq/Kconfig
110 +++ b/drivers/cpufreq/Kconfig
111 @@ -334,7 +334,7 @@ endif
112
113 config QORIQ_CPUFREQ
114 tristate "CPU frequency scaling driver for Freescale QorIQ SoCs"
115 - depends on OF && COMMON_CLK && (PPC_E500MC || ARM)
116 + depends on OF && COMMON_CLK && (PPC_E500MC || ARM || ARM64)
117 depends on !CPU_THERMAL || THERMAL
118 select CLK_QORIQ
119 help
120 --- a/drivers/cpufreq/qoriq-cpufreq.c
121 +++ b/drivers/cpufreq/qoriq-cpufreq.c
122 @@ -11,6 +11,7 @@
123 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
124
125 #include <linux/clk.h>
126 +#include <linux/clk-provider.h>
127 #include <linux/cpufreq.h>
128 #include <linux/cpu_cooling.h>
129 #include <linux/errno.h>
130 @@ -22,10 +23,6 @@
131 #include <linux/slab.h>
132 #include <linux/smp.h>
133
134 -#if !defined(CONFIG_ARM)
135 -#include <asm/smp.h> /* for get_hard_smp_processor_id() in UP configs */
136 -#endif
137 -
138 /**
139 * struct cpu_data
140 * @pclk: the parent clock of cpu
141 @@ -37,73 +34,51 @@ struct cpu_data {
142 struct thermal_cooling_device *cdev;
143 };
144
145 +/*
146 + * Don't use cpufreq on this SoC -- used when the SoC would have otherwise
147 + * matched a more generic compatible.
148 + */
149 +#define SOC_BLACKLIST 1
150 +
151 /**
152 * struct soc_data - SoC specific data
153 - * @freq_mask: mask the disallowed frequencies
154 - * @flag: unique flags
155 + * @flags: SOC_xxx
156 */
157 struct soc_data {
158 - u32 freq_mask[4];
159 - u32 flag;
160 -};
161 -
162 -#define FREQ_MASK 1
163 -/* see hardware specification for the allowed frqeuencies */
164 -static const struct soc_data sdata[] = {
165 - { /* used by p2041 and p3041 */
166 - .freq_mask = {0x8, 0x8, 0x2, 0x2},
167 - .flag = FREQ_MASK,
168 - },
169 - { /* used by p5020 */
170 - .freq_mask = {0x8, 0x2},
171 - .flag = FREQ_MASK,
172 - },
173 - { /* used by p4080, p5040 */
174 - .freq_mask = {0},
175 - .flag = 0,
176 - },
177 + u32 flags;
178 };
179
180 -/*
181 - * the minimum allowed core frequency, in Hz
182 - * for chassis v1.0, >= platform frequency
183 - * for chassis v2.0, >= platform frequency / 2
184 - */
185 -static u32 min_cpufreq;
186 -static const u32 *fmask;
187 -
188 -#if defined(CONFIG_ARM)
189 -static int get_cpu_physical_id(int cpu)
190 -{
191 - return topology_core_id(cpu);
192 -}
193 -#else
194 -static int get_cpu_physical_id(int cpu)
195 -{
196 - return get_hard_smp_processor_id(cpu);
197 -}
198 -#endif
199 -
200 static u32 get_bus_freq(void)
201 {
202 struct device_node *soc;
203 u32 sysfreq;
204 + struct clk *pltclk;
205 + int ret;
206
207 + /* get platform freq by searching bus-frequency property */
208 soc = of_find_node_by_type(NULL, "soc");
209 - if (!soc)
210 - return 0;
211 -
212 - if (of_property_read_u32(soc, "bus-frequency", &sysfreq))
213 - sysfreq = 0;
214 + if (soc) {
215 + ret = of_property_read_u32(soc, "bus-frequency", &sysfreq);
216 + of_node_put(soc);
217 + if (!ret)
218 + return sysfreq;
219 + }
220
221 - of_node_put(soc);
222 + /* get platform freq by its clock name */
223 + pltclk = clk_get(NULL, "cg-pll0-div1");
224 + if (IS_ERR(pltclk)) {
225 + pr_err("%s: can't get bus frequency %ld\n",
226 + __func__, PTR_ERR(pltclk));
227 + return PTR_ERR(pltclk);
228 + }
229
230 - return sysfreq;
231 + return clk_get_rate(pltclk);
232 }
233
234 -static struct device_node *cpu_to_clk_node(int cpu)
235 +static struct clk *cpu_to_clk(int cpu)
236 {
237 - struct device_node *np, *clk_np;
238 + struct device_node *np;
239 + struct clk *clk;
240
241 if (!cpu_present(cpu))
242 return NULL;
243 @@ -112,37 +87,28 @@ static struct device_node *cpu_to_clk_no
244 if (!np)
245 return NULL;
246
247 - clk_np = of_parse_phandle(np, "clocks", 0);
248 - if (!clk_np)
249 - return NULL;
250 -
251 + clk = of_clk_get(np, 0);
252 of_node_put(np);
253 -
254 - return clk_np;
255 + return clk;
256 }
257
258 /* traverse cpu nodes to get cpu mask of sharing clock wire */
259 static void set_affected_cpus(struct cpufreq_policy *policy)
260 {
261 - struct device_node *np, *clk_np;
262 struct cpumask *dstp = policy->cpus;
263 + struct clk *clk;
264 int i;
265
266 - np = cpu_to_clk_node(policy->cpu);
267 - if (!np)
268 - return;
269 -
270 for_each_present_cpu(i) {
271 - clk_np = cpu_to_clk_node(i);
272 - if (!clk_np)
273 + clk = cpu_to_clk(i);
274 + if (IS_ERR(clk)) {
275 + pr_err("%s: no clock for cpu %d\n", __func__, i);
276 continue;
277 + }
278
279 - if (clk_np == np)
280 + if (clk_is_match(policy->clk, clk))
281 cpumask_set_cpu(i, dstp);
282 -
283 - of_node_put(clk_np);
284 }
285 - of_node_put(np);
286 }
287
288 /* reduce the duplicated frequencies in frequency table */
289 @@ -198,10 +164,11 @@ static void freq_table_sort(struct cpufr
290
291 static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy)
292 {
293 - struct device_node *np, *pnode;
294 + struct device_node *np;
295 int i, count, ret;
296 - u32 freq, mask;
297 + u32 freq;
298 struct clk *clk;
299 + const struct clk_hw *hwclk;
300 struct cpufreq_frequency_table *table;
301 struct cpu_data *data;
302 unsigned int cpu = policy->cpu;
303 @@ -221,17 +188,13 @@ static int qoriq_cpufreq_cpu_init(struct
304 goto err_nomem2;
305 }
306
307 - pnode = of_parse_phandle(np, "clocks", 0);
308 - if (!pnode) {
309 - pr_err("%s: could not get clock information\n", __func__);
310 - goto err_nomem2;
311 - }
312 + hwclk = __clk_get_hw(policy->clk);
313 + count = clk_hw_get_num_parents(hwclk);
314
315 - count = of_property_count_strings(pnode, "clock-names");
316 data->pclk = kcalloc(count, sizeof(struct clk *), GFP_KERNEL);
317 if (!data->pclk) {
318 pr_err("%s: no memory\n", __func__);
319 - goto err_node;
320 + goto err_nomem2;
321 }
322
323 table = kcalloc(count + 1, sizeof(*table), GFP_KERNEL);
324 @@ -240,23 +203,11 @@ static int qoriq_cpufreq_cpu_init(struct
325 goto err_pclk;
326 }
327
328 - if (fmask)
329 - mask = fmask[get_cpu_physical_id(cpu)];
330 - else
331 - mask = 0x0;
332 -
333 for (i = 0; i < count; i++) {
334 - clk = of_clk_get(pnode, i);
335 + clk = clk_hw_get_parent_by_index(hwclk, i)->clk;
336 data->pclk[i] = clk;
337 freq = clk_get_rate(clk);
338 - /*
339 - * the clock is valid if its frequency is not masked
340 - * and large than minimum allowed frequency.
341 - */
342 - if (freq < min_cpufreq || (mask & (1 << i)))
343 - table[i].frequency = CPUFREQ_ENTRY_INVALID;
344 - else
345 - table[i].frequency = freq / 1000;
346 + table[i].frequency = freq / 1000;
347 table[i].driver_data = i;
348 }
349 freq_table_redup(table, count);
350 @@ -282,7 +233,6 @@ static int qoriq_cpufreq_cpu_init(struct
351 policy->cpuinfo.transition_latency = u64temp + 1;
352
353 of_node_put(np);
354 - of_node_put(pnode);
355
356 return 0;
357
358 @@ -290,10 +240,7 @@ err_nomem1:
359 kfree(table);
360 err_pclk:
361 kfree(data->pclk);
362 -err_node:
363 - of_node_put(pnode);
364 err_nomem2:
365 - policy->driver_data = NULL;
366 kfree(data);
367 err_np:
368 of_node_put(np);
369 @@ -357,12 +304,25 @@ static struct cpufreq_driver qoriq_cpufr
370 .attr = cpufreq_generic_attr,
371 };
372
373 +static const struct soc_data blacklist = {
374 + .flags = SOC_BLACKLIST,
375 +};
376 +
377 static const struct of_device_id node_matches[] __initconst = {
378 - { .compatible = "fsl,p2041-clockgen", .data = &sdata[0], },
379 - { .compatible = "fsl,p3041-clockgen", .data = &sdata[0], },
380 - { .compatible = "fsl,p5020-clockgen", .data = &sdata[1], },
381 - { .compatible = "fsl,p4080-clockgen", .data = &sdata[2], },
382 - { .compatible = "fsl,p5040-clockgen", .data = &sdata[2], },
383 + /* e6500 cannot use cpufreq due to erratum A-008083 */
384 + { .compatible = "fsl,b4420-clockgen", &blacklist },
385 + { .compatible = "fsl,b4860-clockgen", &blacklist },
386 + { .compatible = "fsl,t2080-clockgen", &blacklist },
387 + { .compatible = "fsl,t4240-clockgen", &blacklist },
388 +
389 + { .compatible = "fsl,ls1012a-clockgen", },
390 + { .compatible = "fsl,ls1021a-clockgen", },
391 + { .compatible = "fsl,ls1043a-clockgen", },
392 + { .compatible = "fsl,ls1046a-clockgen", },
393 + { .compatible = "fsl,ls1088a-clockgen", },
394 + { .compatible = "fsl,ls2080a-clockgen", },
395 + { .compatible = "fsl,p4080-clockgen", },
396 + { .compatible = "fsl,qoriq-clockgen-1.0", },
397 { .compatible = "fsl,qoriq-clockgen-2.0", },
398 {}
399 };
400 @@ -380,16 +340,12 @@ static int __init qoriq_cpufreq_init(voi
401
402 match = of_match_node(node_matches, np);
403 data = match->data;
404 - if (data) {
405 - if (data->flag)
406 - fmask = data->freq_mask;
407 - min_cpufreq = get_bus_freq();
408 - } else {
409 - min_cpufreq = get_bus_freq() / 2;
410 - }
411
412 of_node_put(np);
413
414 + if (data && data->flags & SOC_BLACKLIST)
415 + return -ENODEV;
416 +
417 ret = cpufreq_register_driver(&qoriq_cpufreq_driver);
418 if (!ret)
419 pr_info("Freescale QorIQ CPU frequency scaling driver\n");
420 --- a/drivers/firmware/psci.c
421 +++ b/drivers/firmware/psci.c
422 @@ -437,8 +437,12 @@ CPUIDLE_METHOD_OF_DECLARE(psci, "psci",
423
424 static int psci_system_suspend(unsigned long unused)
425 {
426 - return invoke_psci_fn(PSCI_FN_NATIVE(1_0, SYSTEM_SUSPEND),
427 - virt_to_phys(cpu_resume), 0, 0);
428 + u32 state;
429 +
430 + state = ( 2 << PSCI_0_2_POWER_STATE_AFFL_SHIFT) |
431 + (1 << PSCI_0_2_POWER_STATE_TYPE_SHIFT);
432 +
433 + return psci_cpu_suspend(state, virt_to_phys(cpu_resume));
434 }
435
436 static int psci_system_suspend_enter(suspend_state_t state)
437 @@ -458,6 +462,8 @@ static void __init psci_init_system_susp
438 if (!IS_ENABLED(CONFIG_SUSPEND))
439 return;
440
441 + suspend_set_ops(&psci_suspend_ops);
442 +
443 ret = psci_features(PSCI_FN_NATIVE(1_0, SYSTEM_SUSPEND));
444
445 if (ret != PSCI_RET_NOT_SUPPORTED)
446 @@ -562,6 +568,8 @@ static void __init psci_0_2_set_function
447 arm_pm_restart = psci_sys_reset;
448
449 pm_power_off = psci_sys_poweroff;
450 + psci_init_system_suspend();
451 + suspend_set_ops(&psci_suspend_ops);
452 }
453
454 /*
455 --- /dev/null
456 +++ b/drivers/soc/fsl/rcpm.c
457 @@ -0,0 +1,158 @@
458 +/*
459 + * Run Control and Power Management (RCPM) driver
460 + *
461 + * Copyright 2016 NXP
462 + *
463 + * This program is free software; you can redistribute it and/or modify
464 + * it under the terms of the GNU General Public License as published by
465 + * the Free Software Foundation; either version 2 of the License, or
466 + * (at your option) any later version.
467 + *
468 + * This program is distributed in the hope that it will be useful,
469 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
470 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
471 + * GNU General Public License for more details.
472 + *
473 + */
474 +#define pr_fmt(fmt) "RCPM: %s: " fmt, __func__
475 +
476 +#include <linux/kernel.h>
477 +#include <linux/io.h>
478 +#include <linux/of_platform.h>
479 +#include <linux/of_address.h>
480 +#include <linux/suspend.h>
481 +
482 +/* RCPM register offset */
483 +#define RCPM_IPPDEXPCR0 0x140
484 +
485 +#define RCPM_WAKEUP_CELL_SIZE 2
486 +
487 +struct rcpm_config {
488 + int ipp_num;
489 + int ippdexpcr_offset;
490 + u32 ippdexpcr[2];
491 + void *rcpm_reg_base;
492 +};
493 +
494 +static struct rcpm_config *rcpm;
495 +
496 +static inline void rcpm_reg_write(u32 offset, u32 value)
497 +{
498 + iowrite32be(value, rcpm->rcpm_reg_base + offset);
499 +}
500 +
501 +static inline u32 rcpm_reg_read(u32 offset)
502 +{
503 + return ioread32be(rcpm->rcpm_reg_base + offset);
504 +}
505 +
506 +static void rcpm_wakeup_fixup(struct device *dev, void *data)
507 +{
508 + struct device_node *node = dev ? dev->of_node : NULL;
509 + u32 value[RCPM_WAKEUP_CELL_SIZE];
510 + int ret, i;
511 +
512 + if (!dev || !node || !device_may_wakeup(dev))
513 + return;
514 +
515 + /*
516 + * Get the values in the "rcpm-wakeup" property.
517 + * Three values are:
518 + * The first is a pointer to the RCPM node.
519 + * The second is the value of the ippdexpcr0 register.
520 + * The third is the value of the ippdexpcr1 register.
521 + */
522 + ret = of_property_read_u32_array(node, "fsl,rcpm-wakeup",
523 + value, RCPM_WAKEUP_CELL_SIZE);
524 + if (ret)
525 + return;
526 +
527 + pr_debug("wakeup source: the device %s\n", node->full_name);
528 +
529 + for (i = 0; i < rcpm->ipp_num; i++)
530 + rcpm->ippdexpcr[i] |= value[i + 1];
531 +}
532 +
533 +static int rcpm_suspend_prepare(void)
534 +{
535 + int i;
536 + u32 val;
537 +
538 + BUG_ON(!rcpm);
539 +
540 + for (i = 0; i < rcpm->ipp_num; i++)
541 + rcpm->ippdexpcr[i] = 0;
542 +
543 + dpm_for_each_dev(NULL, rcpm_wakeup_fixup);
544 +
545 + for (i = 0; i < rcpm->ipp_num; i++) {
546 + if (rcpm->ippdexpcr[i]) {
547 + val = rcpm_reg_read(rcpm->ippdexpcr_offset + 4 * i);
548 + rcpm_reg_write(rcpm->ippdexpcr_offset + 4 * i,
549 + val | rcpm->ippdexpcr[i]);
550 + pr_debug("ippdexpcr%d = 0x%x\n", i, rcpm->ippdexpcr[i]);
551 + }
552 + }
553 +
554 + return 0;
555 +}
556 +
557 +static int rcpm_suspend_notifier_call(struct notifier_block *bl,
558 + unsigned long state,
559 + void *unused)
560 +{
561 + switch (state) {
562 + case PM_SUSPEND_PREPARE:
563 + rcpm_suspend_prepare();
564 + break;
565 + }
566 +
567 + return NOTIFY_DONE;
568 +}
569 +
570 +static struct rcpm_config rcpm_default_config = {
571 + .ipp_num = 1,
572 + .ippdexpcr_offset = RCPM_IPPDEXPCR0,
573 +};
574 +
575 +static const struct of_device_id rcpm_matches[] = {
576 + {
577 + .compatible = "fsl,qoriq-rcpm-2.1",
578 + .data = &rcpm_default_config,
579 + },
580 + {}
581 +};
582 +
583 +static struct notifier_block rcpm_suspend_notifier = {
584 + .notifier_call = rcpm_suspend_notifier_call,
585 +};
586 +
587 +static int __init layerscape_rcpm_init(void)
588 +{
589 + const struct of_device_id *match;
590 + struct device_node *np;
591 +
592 + np = of_find_matching_node_and_match(NULL, rcpm_matches, &match);
593 + if (!np) {
594 + pr_err("Can't find the RCPM node.\n");
595 + return -EINVAL;
596 + }
597 +
598 + if (match->data)
599 + rcpm = (struct rcpm_config *)match->data;
600 + else
601 + return -EINVAL;
602 +
603 + rcpm->rcpm_reg_base = of_iomap(np, 0);
604 + of_node_put(np);
605 + if (!rcpm->rcpm_reg_base)
606 + return -ENOMEM;
607 +
608 + register_pm_notifier(&rcpm_suspend_notifier);
609 +
610 + pr_info("The RCPM driver initialized.\n");
611 +
612 + return 0;
613 +}
614 +
615 +subsys_initcall(layerscape_rcpm_init);
616 --- /dev/null
617 +++ b/drivers/soc/fsl/sleep_fsm.c
618 @@ -0,0 +1,279 @@
619 +/*
620 + * deep sleep FSM (finite-state machine) configuration
621 + *
622 + * Copyright 2018 NXP
623 + *
624 + * Author: Hongbo Zhang <hongbo.zhang@freescale.com>
625 + * Chenhui Zhao <chenhui.zhao@freescale.com>
626 + *
627 + * Redistribution and use in source and binary forms, with or without
628 + * modification, are permitted provided that the following conditions are met:
629 + * * Redistributions of source code must retain the above copyright
630 + * notice, this list of conditions and the following disclaimer.
631 + * * Redistributions in binary form must reproduce the above copyright
632 + * notice, this list of conditions and the following disclaimer in the
633 + * documentation and/or other materials provided with the distribution.
634 + * * Neither the name of the above-listed copyright holders nor the
635 + * names of any contributors may be used to endorse or promote products
636 + * derived from this software without specific prior written permission.
637 + *
638 + * ALTERNATIVELY, this software may be distributed under the terms of the
639 + * GNU General Public License ("GPL") as published by the Free Software
640 + * Foundation, either version 2 of that License or (at your option) any
641 + * later version.
642 + *
643 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
644 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
645 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
646 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
647 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
648 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
649 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
650 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
651 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
652 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
653 + * POSSIBILITY OF SUCH DAMAGE.
654 + */
655 +
656 +#include <linux/kernel.h>
657 +#include <linux/io.h>
658 +#include <linux/types.h>
659 +
660 +#include "sleep_fsm.h"
661 +/*
662 + * These values are from chip's reference manual. For example,
663 + * the values for T1040 can be found in "8.4.3.8 Programming
664 + * supporting deep sleep mode" of Chapter 8 "Run Control and
665 + * Power Management (RCPM)".
666 + * The default value can be applied to T104x, LS1021.
667 + */
668 +struct fsm_reg_vals epu_default_val[] = {
669 + /* EPGCR (Event Processor Global Control Register) */
670 + {EPGCR, 0},
671 + /* EPECR (Event Processor Event Control Registers) */
672 + {EPECR0 + EPECR_STRIDE * 0, 0},
673 + {EPECR0 + EPECR_STRIDE * 1, 0},
674 + {EPECR0 + EPECR_STRIDE * 2, 0xF0004004},
675 + {EPECR0 + EPECR_STRIDE * 3, 0x80000084},
676 + {EPECR0 + EPECR_STRIDE * 4, 0x20000084},
677 + {EPECR0 + EPECR_STRIDE * 5, 0x08000004},
678 + {EPECR0 + EPECR_STRIDE * 6, 0x80000084},
679 + {EPECR0 + EPECR_STRIDE * 7, 0x80000084},
680 + {EPECR0 + EPECR_STRIDE * 8, 0x60000084},
681 + {EPECR0 + EPECR_STRIDE * 9, 0x08000084},
682 + {EPECR0 + EPECR_STRIDE * 10, 0x42000084},
683 + {EPECR0 + EPECR_STRIDE * 11, 0x90000084},
684 + {EPECR0 + EPECR_STRIDE * 12, 0x80000084},
685 + {EPECR0 + EPECR_STRIDE * 13, 0x08000084},
686 + {EPECR0 + EPECR_STRIDE * 14, 0x02000084},
687 + {EPECR0 + EPECR_STRIDE * 15, 0x00000004},
688 + /*
689 + * EPEVTCR (Event Processor EVT Pin Control Registers)
690 + * SCU8 triger EVT2, and SCU11 triger EVT9
691 + */
692 + {EPEVTCR0 + EPEVTCR_STRIDE * 0, 0},
693 + {EPEVTCR0 + EPEVTCR_STRIDE * 1, 0},
694 + {EPEVTCR0 + EPEVTCR_STRIDE * 2, 0x80000001},
695 + {EPEVTCR0 + EPEVTCR_STRIDE * 3, 0},
696 + {EPEVTCR0 + EPEVTCR_STRIDE * 4, 0},
697 + {EPEVTCR0 + EPEVTCR_STRIDE * 5, 0},
698 + {EPEVTCR0 + EPEVTCR_STRIDE * 6, 0},
699 + {EPEVTCR0 + EPEVTCR_STRIDE * 7, 0},
700 + {EPEVTCR0 + EPEVTCR_STRIDE * 8, 0},
701 + {EPEVTCR0 + EPEVTCR_STRIDE * 9, 0xB0000001},
702 + /* EPCMPR (Event Processor Counter Compare Registers) */
703 + {EPCMPR0 + EPCMPR_STRIDE * 0, 0},
704 + {EPCMPR0 + EPCMPR_STRIDE * 1, 0},
705 + {EPCMPR0 + EPCMPR_STRIDE * 2, 0x000000FF},
706 + {EPCMPR0 + EPCMPR_STRIDE * 3, 0},
707 + {EPCMPR0 + EPCMPR_STRIDE * 4, 0x000000FF},
708 + {EPCMPR0 + EPCMPR_STRIDE * 5, 0x00000020},
709 + {EPCMPR0 + EPCMPR_STRIDE * 6, 0},
710 + {EPCMPR0 + EPCMPR_STRIDE * 7, 0},
711 + {EPCMPR0 + EPCMPR_STRIDE * 8, 0x000000FF},
712 + {EPCMPR0 + EPCMPR_STRIDE * 9, 0x000000FF},
713 + {EPCMPR0 + EPCMPR_STRIDE * 10, 0x000000FF},
714 + {EPCMPR0 + EPCMPR_STRIDE * 11, 0x000000FF},
715 + {EPCMPR0 + EPCMPR_STRIDE * 12, 0x000000FF},
716 + {EPCMPR0 + EPCMPR_STRIDE * 13, 0},
717 + {EPCMPR0 + EPCMPR_STRIDE * 14, 0x000000FF},
718 + {EPCMPR0 + EPCMPR_STRIDE * 15, 0x000000FF},
719 + /* EPCCR (Event Processor Counter Control Registers) */
720 + {EPCCR0 + EPCCR_STRIDE * 0, 0},
721 + {EPCCR0 + EPCCR_STRIDE * 1, 0},
722 + {EPCCR0 + EPCCR_STRIDE * 2, 0x92840000},
723 + {EPCCR0 + EPCCR_STRIDE * 3, 0},
724 + {EPCCR0 + EPCCR_STRIDE * 4, 0x92840000},
725 + {EPCCR0 + EPCCR_STRIDE * 5, 0x92840000},
726 + {EPCCR0 + EPCCR_STRIDE * 6, 0},
727 + {EPCCR0 + EPCCR_STRIDE * 7, 0},
728 + {EPCCR0 + EPCCR_STRIDE * 8, 0x92840000},
729 + {EPCCR0 + EPCCR_STRIDE * 9, 0x92840000},
730 + {EPCCR0 + EPCCR_STRIDE * 10, 0x92840000},
731 + {EPCCR0 + EPCCR_STRIDE * 11, 0x92840000},
732 + {EPCCR0 + EPCCR_STRIDE * 12, 0x92840000},
733 + {EPCCR0 + EPCCR_STRIDE * 13, 0},
734 + {EPCCR0 + EPCCR_STRIDE * 14, 0x92840000},
735 + {EPCCR0 + EPCCR_STRIDE * 15, 0x92840000},
736 + /* EPSMCR (Event Processor SCU Mux Control Registers) */
737 + {EPSMCR0 + EPSMCR_STRIDE * 0, 0},
738 + {EPSMCR0 + EPSMCR_STRIDE * 1, 0},
739 + {EPSMCR0 + EPSMCR_STRIDE * 2, 0x6C700000},
740 + {EPSMCR0 + EPSMCR_STRIDE * 3, 0x2F000000},
741 + {EPSMCR0 + EPSMCR_STRIDE * 4, 0x002F0000},
742 + {EPSMCR0 + EPSMCR_STRIDE * 5, 0x00002E00},
743 + {EPSMCR0 + EPSMCR_STRIDE * 6, 0x7C000000},
744 + {EPSMCR0 + EPSMCR_STRIDE * 7, 0x30000000},
745 + {EPSMCR0 + EPSMCR_STRIDE * 8, 0x64300000},
746 + {EPSMCR0 + EPSMCR_STRIDE * 9, 0x00003000},
747 + {EPSMCR0 + EPSMCR_STRIDE * 10, 0x65000030},
748 + {EPSMCR0 + EPSMCR_STRIDE * 11, 0x31740000},
749 + {EPSMCR0 + EPSMCR_STRIDE * 12, 0x7F000000},
750 + {EPSMCR0 + EPSMCR_STRIDE * 13, 0x00003100},
751 + {EPSMCR0 + EPSMCR_STRIDE * 14, 0x00000031},
752 + {EPSMCR0 + EPSMCR_STRIDE * 15, 0x76000000},
753 + /* EPACR (Event Processor Action Control Registers) */
754 + {EPACR0 + EPACR_STRIDE * 0, 0},
755 + {EPACR0 + EPACR_STRIDE * 1, 0},
756 + {EPACR0 + EPACR_STRIDE * 2, 0},
757 + {EPACR0 + EPACR_STRIDE * 3, 0x00000080},
758 + {EPACR0 + EPACR_STRIDE * 4, 0},
759 + {EPACR0 + EPACR_STRIDE * 5, 0x00000040},
760 + {EPACR0 + EPACR_STRIDE * 6, 0},
761 + {EPACR0 + EPACR_STRIDE * 7, 0},
762 + {EPACR0 + EPACR_STRIDE * 8, 0},
763 + {EPACR0 + EPACR_STRIDE * 9, 0x0000001C},
764 + {EPACR0 + EPACR_STRIDE * 10, 0x00000020},
765 + {EPACR0 + EPACR_STRIDE * 11, 0},
766 + {EPACR0 + EPACR_STRIDE * 12, 0x00000003},
767 + {EPACR0 + EPACR_STRIDE * 13, 0x06000000},
768 + {EPACR0 + EPACR_STRIDE * 14, 0x04000000},
769 + {EPACR0 + EPACR_STRIDE * 15, 0x02000000},
770 + /* EPIMCR (Event Processor Input Mux Control Registers) */
771 + {EPIMCR0 + EPIMCR_STRIDE * 0, 0},
772 + {EPIMCR0 + EPIMCR_STRIDE * 1, 0},
773 + {EPIMCR0 + EPIMCR_STRIDE * 2, 0},
774 + {EPIMCR0 + EPIMCR_STRIDE * 3, 0},
775 + {EPIMCR0 + EPIMCR_STRIDE * 4, 0x44000000},
776 + {EPIMCR0 + EPIMCR_STRIDE * 5, 0x40000000},
777 + {EPIMCR0 + EPIMCR_STRIDE * 6, 0},
778 + {EPIMCR0 + EPIMCR_STRIDE * 7, 0},
779 + {EPIMCR0 + EPIMCR_STRIDE * 8, 0},
780 + {EPIMCR0 + EPIMCR_STRIDE * 9, 0},
781 + {EPIMCR0 + EPIMCR_STRIDE * 10, 0},
782 + {EPIMCR0 + EPIMCR_STRIDE * 11, 0},
783 + {EPIMCR0 + EPIMCR_STRIDE * 12, 0x44000000},
784 + {EPIMCR0 + EPIMCR_STRIDE * 13, 0},
785 + {EPIMCR0 + EPIMCR_STRIDE * 14, 0},
786 + {EPIMCR0 + EPIMCR_STRIDE * 15, 0},
787 + {EPIMCR0 + EPIMCR_STRIDE * 16, 0x6A000000},
788 + {EPIMCR0 + EPIMCR_STRIDE * 17, 0},
789 + {EPIMCR0 + EPIMCR_STRIDE * 18, 0},
790 + {EPIMCR0 + EPIMCR_STRIDE * 19, 0},
791 + {EPIMCR0 + EPIMCR_STRIDE * 20, 0x48000000},
792 + {EPIMCR0 + EPIMCR_STRIDE * 21, 0},
793 + {EPIMCR0 + EPIMCR_STRIDE * 22, 0x6C000000},
794 + {EPIMCR0 + EPIMCR_STRIDE * 23, 0},
795 + {EPIMCR0 + EPIMCR_STRIDE * 24, 0},
796 + {EPIMCR0 + EPIMCR_STRIDE * 25, 0},
797 + {EPIMCR0 + EPIMCR_STRIDE * 26, 0},
798 + {EPIMCR0 + EPIMCR_STRIDE * 27, 0},
799 + {EPIMCR0 + EPIMCR_STRIDE * 28, 0x76000000},
800 + {EPIMCR0 + EPIMCR_STRIDE * 29, 0},
801 + {EPIMCR0 + EPIMCR_STRIDE * 30, 0},
802 + {EPIMCR0 + EPIMCR_STRIDE * 31, 0x76000000},
803 + /* EPXTRIGCR (Event Processor Crosstrigger Control Register) */
804 + {EPXTRIGCR, 0x0000FFDF},
805 + /* end */
806 + {FSM_END_FLAG, 0},
807 +};
808 +
809 +struct fsm_reg_vals npc_default_val[] = {
810 + /* NPC triggered Memory-Mapped Access Registers */
811 + {NCR, 0x80000000},
812 + {MCCR1, 0},
813 + {MCSR1, 0},
814 + {MMAR1LO, 0},
815 + {MMAR1HI, 0},
816 + {MMDR1, 0},
817 + {MCSR2, 0},
818 + {MMAR2LO, 0},
819 + {MMAR2HI, 0},
820 + {MMDR2, 0},
821 + {MCSR3, 0x80000000},
822 + {MMAR3LO, 0x000E2130},
823 + {MMAR3HI, 0x00030000},
824 + {MMDR3, 0x00020000},
825 + /* end */
826 + {FSM_END_FLAG, 0},
827 +};
828 +
829 +/**
830 + * fsl_fsm_setup - Configure EPU's FSM registers
831 + * @base: the base address of registers
832 + * @val: Pointer to address-value pairs for FSM registers
833 + */
834 +void fsl_fsm_setup(void __iomem *base, struct fsm_reg_vals *val)
835 +{
836 + struct fsm_reg_vals *data = val;
837 +
838 + WARN_ON(!base || !data);
839 + while (data->offset != FSM_END_FLAG) {
840 + iowrite32be(data->value, base + data->offset);
841 + data++;
842 + }
843 +}
844 +
845 +void fsl_epu_setup_default(void __iomem *epu_base)
846 +{
847 + fsl_fsm_setup(epu_base, epu_default_val);
848 +}
849 +
850 +void fsl_npc_setup_default(void __iomem *npc_base)
851 +{
852 + fsl_fsm_setup(npc_base, npc_default_val);
853 +}
854 +
855 +void fsl_epu_clean_default(void __iomem *epu_base)
856 +{
857 + u32 offset;
858 +
859 + /* follow the exact sequence to clear the registers */
860 + /* Clear EPACRn */
861 + for (offset = EPACR0; offset <= EPACR15; offset += EPACR_STRIDE)
862 + iowrite32be(0, epu_base + offset);
863 +
864 + /* Clear EPEVTCRn */
865 + for (offset = EPEVTCR0; offset <= EPEVTCR9; offset += EPEVTCR_STRIDE)
866 + iowrite32be(0, epu_base + offset);
867 +
868 + /* Clear EPGCR */
869 + iowrite32be(0, epu_base + EPGCR);
870 +
871 + /* Clear EPSMCRn */
872 + for (offset = EPSMCR0; offset <= EPSMCR15; offset += EPSMCR_STRIDE)
873 + iowrite32be(0, epu_base + offset);
874 +
875 + /* Clear EPCCRn */
876 + for (offset = EPCCR0; offset <= EPCCR31; offset += EPCCR_STRIDE)
877 + iowrite32be(0, epu_base + offset);
878 +
879 + /* Clear EPCMPRn */
880 + for (offset = EPCMPR0; offset <= EPCMPR31; offset += EPCMPR_STRIDE)
881 + iowrite32be(0, epu_base + offset);
882 +
883 + /* Clear EPCTRn */
884 + for (offset = EPCTR0; offset <= EPCTR31; offset += EPCTR_STRIDE)
885 + iowrite32be(0, epu_base + offset);
886 +
887 + /* Clear EPIMCRn */
888 + for (offset = EPIMCR0; offset <= EPIMCR31; offset += EPIMCR_STRIDE)
889 + iowrite32be(0, epu_base + offset);
890 +
891 + /* Clear EPXTRIGCRn */
892 + iowrite32be(0, epu_base + EPXTRIGCR);
893 +
894 + /* Clear EPECRn */
895 + for (offset = EPECR0; offset <= EPECR15; offset += EPECR_STRIDE)
896 + iowrite32be(0, epu_base + offset);
897 +}
898 --- /dev/null
899 +++ b/drivers/soc/fsl/sleep_fsm.h
900 @@ -0,0 +1,130 @@
901 +/*
902 + * deep sleep FSM (finite-state machine) configuration
903 + *
904 + * Copyright 2018 NXP
905 + *
906 + * Redistribution and use in source and binary forms, with or without
907 + * modification, are permitted provided that the following conditions are met:
908 + * * Redistributions of source code must retain the above copyright
909 + * notice, this list of conditions and the following disclaimer.
910 + * * Redistributions in binary form must reproduce the above copyright
911 + * notice, this list of conditions and the following disclaimer in the
912 + * documentation and/or other materials provided with the distribution.
913 + * * Neither the name of the above-listed copyright holders nor the
914 + * names of any contributors may be used to endorse or promote products
915 + * derived from this software without specific prior written permission.
916 + *
917 + *
918 + * ALTERNATIVELY, this software may be distributed under the terms of the
919 + * GNU General Public License ("GPL") as published by the Free Software
920 + * Foundation, either version 2 of that License or (at your option) any
921 + * later version.
922 + *
923 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
924 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
925 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
926 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
927 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
928 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
929 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
930 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
931 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
932 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
933 + * POSSIBILITY OF SUCH DAMAGE.
934 + */
935 +
936 +#ifndef _FSL_SLEEP_FSM_H
937 +#define _FSL_SLEEP_FSM_H
938 +
939 +#define FSL_STRIDE_4B 4
940 +#define FSL_STRIDE_8B 8
941 +
942 +/* End flag */
943 +#define FSM_END_FLAG 0xFFFFFFFFUL
944 +
945 +/* Block offsets */
946 +#define RCPM_BLOCK_OFFSET 0x00022000
947 +#define EPU_BLOCK_OFFSET 0x00000000
948 +#define NPC_BLOCK_OFFSET 0x00001000
949 +
950 +/* EPGCR (Event Processor Global Control Register) */
951 +#define EPGCR 0x000
952 +
953 +/* EPEVTCR0-9 (Event Processor EVT Pin Control Registers) */
954 +#define EPEVTCR0 0x050
955 +#define EPEVTCR9 0x074
956 +#define EPEVTCR_STRIDE FSL_STRIDE_4B
957 +
958 +/* EPXTRIGCR (Event Processor Crosstrigger Control Register) */
959 +#define EPXTRIGCR 0x090
960 +
961 +/* EPIMCR0-31 (Event Processor Input Mux Control Registers) */
962 +#define EPIMCR0 0x100
963 +#define EPIMCR31 0x17C
964 +#define EPIMCR_STRIDE FSL_STRIDE_4B
965 +
966 +/* EPSMCR0-15 (Event Processor SCU Mux Control Registers) */
967 +#define EPSMCR0 0x200
968 +#define EPSMCR15 0x278
969 +#define EPSMCR_STRIDE FSL_STRIDE_8B
970 +
971 +/* EPECR0-15 (Event Processor Event Control Registers) */
972 +#define EPECR0 0x300
973 +#define EPECR15 0x33C
974 +#define EPECR_STRIDE FSL_STRIDE_4B
975 +
976 +/* EPACR0-15 (Event Processor Action Control Registers) */
977 +#define EPACR0 0x400
978 +#define EPACR15 0x43C
979 +#define EPACR_STRIDE FSL_STRIDE_4B
980 +
981 +/* EPCCRi0-15 (Event Processor Counter Control Registers) */
982 +#define EPCCR0 0x800
983 +#define EPCCR15 0x83C
984 +#define EPCCR31 0x87C
985 +#define EPCCR_STRIDE FSL_STRIDE_4B
986 +
987 +/* EPCMPR0-15 (Event Processor Counter Compare Registers) */
988 +#define EPCMPR0 0x900
989 +#define EPCMPR15 0x93C
990 +#define EPCMPR31 0x97C
991 +#define EPCMPR_STRIDE FSL_STRIDE_4B
992 +
993 +/* EPCTR0-31 (Event Processor Counter Register) */
994 +#define EPCTR0 0xA00
995 +#define EPCTR31 0xA7C
996 +#define EPCTR_STRIDE FSL_STRIDE_4B
997 +
998 +/* NPC triggered Memory-Mapped Access Registers */
999 +#define NCR 0x000
1000 +#define MCCR1 0x0CC
1001 +#define MCSR1 0x0D0
1002 +#define MMAR1LO 0x0D4
1003 +#define MMAR1HI 0x0D8
1004 +#define MMDR1 0x0DC
1005 +#define MCSR2 0x0E0
1006 +#define MMAR2LO 0x0E4
1007 +#define MMAR2HI 0x0E8
1008 +#define MMDR2 0x0EC
1009 +#define MCSR3 0x0F0
1010 +#define MMAR3LO 0x0F4
1011 +#define MMAR3HI 0x0F8
1012 +#define MMDR3 0x0FC
1013 +
1014 +/* RCPM Core State Action Control Register 0 */
1015 +#define CSTTACR0 0xB00
1016 +
1017 +/* RCPM Core Group 1 Configuration Register 0 */
1018 +#define CG1CR0 0x31C
1019 +
1020 +struct fsm_reg_vals {
1021 + u32 offset;
1022 + u32 value;
1023 +};
1024 +
1025 +void fsl_fsm_setup(void __iomem *base, struct fsm_reg_vals *val);
1026 +void fsl_epu_setup_default(void __iomem *epu_base);
1027 +void fsl_npc_setup_default(void __iomem *npc_base);
1028 +void fsl_epu_clean_default(void __iomem *epu_base);
1029 +
1030 +#endif /* _FSL_SLEEP_FSM_H */