]> asedeno.scripts.mit.edu Git - linux.git/blob - drivers/cpufreq/qoriq-cpufreq.c
Merge branches 'pm-core', 'pm-qos', 'pm-domains' and 'pm-opp'
[linux.git] / drivers / cpufreq / qoriq-cpufreq.c
1 /*
2  * Copyright 2013 Freescale Semiconductor, Inc.
3  *
4  * CPU Frequency Scaling driver for Freescale QorIQ SoCs.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  */
10
11 #define pr_fmt(fmt)     KBUILD_MODNAME ": " fmt
12
13 #include <linux/clk.h>
14 #include <linux/clk-provider.h>
15 #include <linux/cpufreq.h>
16 #include <linux/cpu_cooling.h>
17 #include <linux/errno.h>
18 #include <linux/init.h>
19 #include <linux/kernel.h>
20 #include <linux/module.h>
21 #include <linux/mutex.h>
22 #include <linux/of.h>
23 #include <linux/slab.h>
24 #include <linux/smp.h>
25
26 #if !defined(CONFIG_ARM)
27 #include <asm/smp.h>    /* for get_hard_smp_processor_id() in UP configs */
28 #endif
29
30 /**
31  * struct cpu_data
32  * @pclk: the parent clock of cpu
33  * @table: frequency table
34  */
35 struct cpu_data {
36         struct clk **pclk;
37         struct cpufreq_frequency_table *table;
38         struct thermal_cooling_device *cdev;
39 };
40
41 /*
42  * Don't use cpufreq on this SoC -- used when the SoC would have otherwise
43  * matched a more generic compatible.
44  */
45 #define SOC_BLACKLIST           1
46
47 /**
48  * struct soc_data - SoC specific data
49  * @flags: SOC_xxx
50  */
51 struct soc_data {
52         u32 flags;
53 };
54
55 static u32 get_bus_freq(void)
56 {
57         struct device_node *soc;
58         u32 sysfreq;
59
60         soc = of_find_node_by_type(NULL, "soc");
61         if (!soc)
62                 return 0;
63
64         if (of_property_read_u32(soc, "bus-frequency", &sysfreq))
65                 sysfreq = 0;
66
67         of_node_put(soc);
68
69         return sysfreq;
70 }
71
72 static struct clk *cpu_to_clk(int cpu)
73 {
74         struct device_node *np;
75         struct clk *clk;
76
77         if (!cpu_present(cpu))
78                 return NULL;
79
80         np = of_get_cpu_node(cpu, NULL);
81         if (!np)
82                 return NULL;
83
84         clk = of_clk_get(np, 0);
85         of_node_put(np);
86         return clk;
87 }
88
89 /* traverse cpu nodes to get cpu mask of sharing clock wire */
90 static void set_affected_cpus(struct cpufreq_policy *policy)
91 {
92         struct cpumask *dstp = policy->cpus;
93         struct clk *clk;
94         int i;
95
96         for_each_present_cpu(i) {
97                 clk = cpu_to_clk(i);
98                 if (IS_ERR(clk)) {
99                         pr_err("%s: no clock for cpu %d\n", __func__, i);
100                         continue;
101                 }
102
103                 if (clk_is_match(policy->clk, clk))
104                         cpumask_set_cpu(i, dstp);
105         }
106 }
107
108 /* reduce the duplicated frequencies in frequency table */
109 static void freq_table_redup(struct cpufreq_frequency_table *freq_table,
110                 int count)
111 {
112         int i, j;
113
114         for (i = 1; i < count; i++) {
115                 for (j = 0; j < i; j++) {
116                         if (freq_table[j].frequency == CPUFREQ_ENTRY_INVALID ||
117                                         freq_table[j].frequency !=
118                                         freq_table[i].frequency)
119                                 continue;
120
121                         freq_table[i].frequency = CPUFREQ_ENTRY_INVALID;
122                         break;
123                 }
124         }
125 }
126
127 /* sort the frequencies in frequency table in descenting order */
128 static void freq_table_sort(struct cpufreq_frequency_table *freq_table,
129                 int count)
130 {
131         int i, j, ind;
132         unsigned int freq, max_freq;
133         struct cpufreq_frequency_table table;
134
135         for (i = 0; i < count - 1; i++) {
136                 max_freq = freq_table[i].frequency;
137                 ind = i;
138                 for (j = i + 1; j < count; j++) {
139                         freq = freq_table[j].frequency;
140                         if (freq == CPUFREQ_ENTRY_INVALID ||
141                                         freq <= max_freq)
142                                 continue;
143                         ind = j;
144                         max_freq = freq;
145                 }
146
147                 if (ind != i) {
148                         /* exchange the frequencies */
149                         table.driver_data = freq_table[i].driver_data;
150                         table.frequency = freq_table[i].frequency;
151                         freq_table[i].driver_data = freq_table[ind].driver_data;
152                         freq_table[i].frequency = freq_table[ind].frequency;
153                         freq_table[ind].driver_data = table.driver_data;
154                         freq_table[ind].frequency = table.frequency;
155                 }
156         }
157 }
158
159 static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy)
160 {
161         struct device_node *np;
162         int i, count, ret;
163         u32 freq;
164         struct clk *clk;
165         const struct clk_hw *hwclk;
166         struct cpufreq_frequency_table *table;
167         struct cpu_data *data;
168         unsigned int cpu = policy->cpu;
169         u64 u64temp;
170
171         np = of_get_cpu_node(cpu, NULL);
172         if (!np)
173                 return -ENODEV;
174
175         data = kzalloc(sizeof(*data), GFP_KERNEL);
176         if (!data)
177                 goto err_np;
178
179         policy->clk = of_clk_get(np, 0);
180         if (IS_ERR(policy->clk)) {
181                 pr_err("%s: no clock information\n", __func__);
182                 goto err_nomem2;
183         }
184
185         hwclk = __clk_get_hw(policy->clk);
186         count = clk_hw_get_num_parents(hwclk);
187
188         data->pclk = kcalloc(count, sizeof(struct clk *), GFP_KERNEL);
189         if (!data->pclk) {
190                 pr_err("%s: no memory\n", __func__);
191                 goto err_nomem2;
192         }
193
194         table = kcalloc(count + 1, sizeof(*table), GFP_KERNEL);
195         if (!table) {
196                 pr_err("%s: no memory\n", __func__);
197                 goto err_pclk;
198         }
199
200         for (i = 0; i < count; i++) {
201                 clk = clk_hw_get_parent_by_index(hwclk, i)->clk;
202                 data->pclk[i] = clk;
203                 freq = clk_get_rate(clk);
204                 table[i].frequency = freq / 1000;
205                 table[i].driver_data = i;
206         }
207         freq_table_redup(table, count);
208         freq_table_sort(table, count);
209         table[i].frequency = CPUFREQ_TABLE_END;
210
211         /* set the min and max frequency properly */
212         ret = cpufreq_table_validate_and_show(policy, table);
213         if (ret) {
214                 pr_err("invalid frequency table: %d\n", ret);
215                 goto err_nomem1;
216         }
217
218         data->table = table;
219
220         /* update ->cpus if we have cluster, no harm if not */
221         set_affected_cpus(policy);
222         policy->driver_data = data;
223
224         /* Minimum transition latency is 12 platform clocks */
225         u64temp = 12ULL * NSEC_PER_SEC;
226         do_div(u64temp, get_bus_freq());
227         policy->cpuinfo.transition_latency = u64temp + 1;
228
229         of_node_put(np);
230
231         return 0;
232
233 err_nomem1:
234         kfree(table);
235 err_pclk:
236         kfree(data->pclk);
237 err_nomem2:
238         kfree(data);
239 err_np:
240         of_node_put(np);
241
242         return -ENODEV;
243 }
244
245 static int qoriq_cpufreq_cpu_exit(struct cpufreq_policy *policy)
246 {
247         struct cpu_data *data = policy->driver_data;
248
249         cpufreq_cooling_unregister(data->cdev);
250         kfree(data->pclk);
251         kfree(data->table);
252         kfree(data);
253         policy->driver_data = NULL;
254
255         return 0;
256 }
257
258 static int qoriq_cpufreq_target(struct cpufreq_policy *policy,
259                 unsigned int index)
260 {
261         struct clk *parent;
262         struct cpu_data *data = policy->driver_data;
263
264         parent = data->pclk[data->table[index].driver_data];
265         return clk_set_parent(policy->clk, parent);
266 }
267
268
269 static void qoriq_cpufreq_ready(struct cpufreq_policy *policy)
270 {
271         struct cpu_data *cpud = policy->driver_data;
272         struct device_node *np = of_get_cpu_node(policy->cpu, NULL);
273
274         if (of_find_property(np, "#cooling-cells", NULL)) {
275                 cpud->cdev = of_cpufreq_cooling_register(np,
276                                                          policy->related_cpus);
277
278                 if (IS_ERR(cpud->cdev) && PTR_ERR(cpud->cdev) != -ENOSYS) {
279                         pr_err("cpu%d is not running as cooling device: %ld\n",
280                                         policy->cpu, PTR_ERR(cpud->cdev));
281
282                         cpud->cdev = NULL;
283                 }
284         }
285
286         of_node_put(np);
287 }
288
289 static struct cpufreq_driver qoriq_cpufreq_driver = {
290         .name           = "qoriq_cpufreq",
291         .flags          = CPUFREQ_CONST_LOOPS,
292         .init           = qoriq_cpufreq_cpu_init,
293         .exit           = qoriq_cpufreq_cpu_exit,
294         .verify         = cpufreq_generic_frequency_table_verify,
295         .target_index   = qoriq_cpufreq_target,
296         .get            = cpufreq_generic_get,
297         .ready          = qoriq_cpufreq_ready,
298         .attr           = cpufreq_generic_attr,
299 };
300
301 static const struct soc_data blacklist = {
302         .flags = SOC_BLACKLIST,
303 };
304
305 static const struct of_device_id node_matches[] __initconst = {
306         /* e6500 cannot use cpufreq due to erratum A-008083 */
307         { .compatible = "fsl,b4420-clockgen", &blacklist },
308         { .compatible = "fsl,b4860-clockgen", &blacklist },
309         { .compatible = "fsl,t2080-clockgen", &blacklist },
310         { .compatible = "fsl,t4240-clockgen", &blacklist },
311
312         { .compatible = "fsl,ls1012a-clockgen", },
313         { .compatible = "fsl,ls1021a-clockgen", },
314         { .compatible = "fsl,ls1043a-clockgen", },
315         { .compatible = "fsl,ls1046a-clockgen", },
316         { .compatible = "fsl,ls1088a-clockgen", },
317         { .compatible = "fsl,ls2080a-clockgen", },
318         { .compatible = "fsl,p4080-clockgen", },
319         { .compatible = "fsl,qoriq-clockgen-1.0", },
320         { .compatible = "fsl,qoriq-clockgen-2.0", },
321         {}
322 };
323
324 static int __init qoriq_cpufreq_init(void)
325 {
326         int ret;
327         struct device_node  *np;
328         const struct of_device_id *match;
329         const struct soc_data *data;
330
331         np = of_find_matching_node(NULL, node_matches);
332         if (!np)
333                 return -ENODEV;
334
335         match = of_match_node(node_matches, np);
336         data = match->data;
337
338         of_node_put(np);
339
340         if (data && data->flags & SOC_BLACKLIST)
341                 return -ENODEV;
342
343         ret = cpufreq_register_driver(&qoriq_cpufreq_driver);
344         if (!ret)
345                 pr_info("Freescale QorIQ CPU frequency scaling driver\n");
346
347         return ret;
348 }
349 module_init(qoriq_cpufreq_init);
350
351 static void __exit qoriq_cpufreq_exit(void)
352 {
353         cpufreq_unregister_driver(&qoriq_cpufreq_driver);
354 }
355 module_exit(qoriq_cpufreq_exit);
356
357 MODULE_LICENSE("GPL");
358 MODULE_AUTHOR("Tang Yuantian <Yuantian.Tang@freescale.com>");
359 MODULE_DESCRIPTION("cpufreq driver for Freescale QorIQ series SoCs");