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