MAINTAINERS: Add selftests/timers to the timekeeping maintainance list
[cascardo/linux.git] / drivers / cpufreq / ppc-corenet-cpufreq.c
1 /*
2  * Copyright 2013 Freescale Semiconductor, Inc.
3  *
4  * CPU Frequency Scaling driver for Freescale PowerPC corenet 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/cpufreq.h>
15 #include <linux/errno.h>
16 #include <linux/init.h>
17 #include <linux/kernel.h>
18 #include <linux/module.h>
19 #include <linux/mutex.h>
20 #include <linux/of.h>
21 #include <linux/slab.h>
22 #include <linux/smp.h>
23 #include <sysdev/fsl_soc.h>
24
25 #include <asm/smp.h>    /* for get_hard_smp_processor_id() in UP configs */
26
27 /**
28  * struct cpu_data - per CPU data struct
29  * @parent: the parent node of cpu clock
30  * @table: frequency table
31  */
32 struct cpu_data {
33         struct device_node *parent;
34         struct cpufreq_frequency_table *table;
35 };
36
37 /**
38  * struct soc_data - SoC specific data
39  * @freq_mask: mask the disallowed frequencies
40  * @flag: unique flags
41  */
42 struct soc_data {
43         u32 freq_mask[4];
44         u32 flag;
45 };
46
47 #define FREQ_MASK       1
48 /* see hardware specification for the allowed frqeuencies */
49 static const struct soc_data sdata[] = {
50         { /* used by p2041 and p3041 */
51                 .freq_mask = {0x8, 0x8, 0x2, 0x2},
52                 .flag = FREQ_MASK,
53         },
54         { /* used by p5020 */
55                 .freq_mask = {0x8, 0x2},
56                 .flag = FREQ_MASK,
57         },
58         { /* used by p4080, p5040 */
59                 .freq_mask = {0},
60                 .flag = 0,
61         },
62 };
63
64 /*
65  * the minimum allowed core frequency, in Hz
66  * for chassis v1.0, >= platform frequency
67  * for chassis v2.0, >= platform frequency / 2
68  */
69 static u32 min_cpufreq;
70 static const u32 *fmask;
71
72 static DEFINE_PER_CPU(struct cpu_data *, cpu_data);
73
74 /* cpumask in a cluster */
75 static DEFINE_PER_CPU(cpumask_var_t, cpu_mask);
76
77 #ifndef CONFIG_SMP
78 static inline const struct cpumask *cpu_core_mask(int cpu)
79 {
80         return cpumask_of(0);
81 }
82 #endif
83
84 /* reduce the duplicated frequencies in frequency table */
85 static void freq_table_redup(struct cpufreq_frequency_table *freq_table,
86                 int count)
87 {
88         int i, j;
89
90         for (i = 1; i < count; i++) {
91                 for (j = 0; j < i; j++) {
92                         if (freq_table[j].frequency == CPUFREQ_ENTRY_INVALID ||
93                                         freq_table[j].frequency !=
94                                         freq_table[i].frequency)
95                                 continue;
96
97                         freq_table[i].frequency = CPUFREQ_ENTRY_INVALID;
98                         break;
99                 }
100         }
101 }
102
103 /* sort the frequencies in frequency table in descenting order */
104 static void freq_table_sort(struct cpufreq_frequency_table *freq_table,
105                 int count)
106 {
107         int i, j, ind;
108         unsigned int freq, max_freq;
109         struct cpufreq_frequency_table table;
110         for (i = 0; i < count - 1; i++) {
111                 max_freq = freq_table[i].frequency;
112                 ind = i;
113                 for (j = i + 1; j < count; j++) {
114                         freq = freq_table[j].frequency;
115                         if (freq == CPUFREQ_ENTRY_INVALID ||
116                                         freq <= max_freq)
117                                 continue;
118                         ind = j;
119                         max_freq = freq;
120                 }
121
122                 if (ind != i) {
123                         /* exchange the frequencies */
124                         table.driver_data = freq_table[i].driver_data;
125                         table.frequency = freq_table[i].frequency;
126                         freq_table[i].driver_data = freq_table[ind].driver_data;
127                         freq_table[i].frequency = freq_table[ind].frequency;
128                         freq_table[ind].driver_data = table.driver_data;
129                         freq_table[ind].frequency = table.frequency;
130                 }
131         }
132 }
133
134 static int corenet_cpufreq_cpu_init(struct cpufreq_policy *policy)
135 {
136         struct device_node *np;
137         int i, count, ret;
138         u32 freq, mask;
139         struct clk *clk;
140         struct cpufreq_frequency_table *table;
141         struct cpu_data *data;
142         unsigned int cpu = policy->cpu;
143         u64 u64temp;
144
145         np = of_get_cpu_node(cpu, NULL);
146         if (!np)
147                 return -ENODEV;
148
149         data = kzalloc(sizeof(*data), GFP_KERNEL);
150         if (!data) {
151                 pr_err("%s: no memory\n", __func__);
152                 goto err_np;
153         }
154
155         policy->clk = of_clk_get(np, 0);
156         if (IS_ERR(policy->clk)) {
157                 pr_err("%s: no clock information\n", __func__);
158                 goto err_nomem2;
159         }
160
161         data->parent = of_parse_phandle(np, "clocks", 0);
162         if (!data->parent) {
163                 pr_err("%s: could not get clock information\n", __func__);
164                 goto err_nomem2;
165         }
166
167         count = of_property_count_strings(data->parent, "clock-names");
168         table = kcalloc(count + 1, sizeof(*table), GFP_KERNEL);
169         if (!table) {
170                 pr_err("%s: no memory\n", __func__);
171                 goto err_node;
172         }
173
174         if (fmask)
175                 mask = fmask[get_hard_smp_processor_id(cpu)];
176         else
177                 mask = 0x0;
178
179         for (i = 0; i < count; i++) {
180                 clk = of_clk_get(data->parent, i);
181                 freq = clk_get_rate(clk);
182                 /*
183                  * the clock is valid if its frequency is not masked
184                  * and large than minimum allowed frequency.
185                  */
186                 if (freq < min_cpufreq || (mask & (1 << i)))
187                         table[i].frequency = CPUFREQ_ENTRY_INVALID;
188                 else
189                         table[i].frequency = freq / 1000;
190                 table[i].driver_data = i;
191         }
192         freq_table_redup(table, count);
193         freq_table_sort(table, count);
194         table[i].frequency = CPUFREQ_TABLE_END;
195
196         /* set the min and max frequency properly */
197         ret = cpufreq_table_validate_and_show(policy, table);
198         if (ret) {
199                 pr_err("invalid frequency table: %d\n", ret);
200                 goto err_nomem1;
201         }
202
203         data->table = table;
204
205         /* update ->cpus if we have cluster, no harm if not */
206         cpumask_copy(policy->cpus, per_cpu(cpu_mask, cpu));
207         for_each_cpu(i, per_cpu(cpu_mask, cpu))
208                 per_cpu(cpu_data, i) = data;
209
210         /* Minimum transition latency is 12 platform clocks */
211         u64temp = 12ULL * NSEC_PER_SEC;
212         do_div(u64temp, fsl_get_sys_freq());
213         policy->cpuinfo.transition_latency = u64temp + 1;
214
215         of_node_put(np);
216
217         return 0;
218
219 err_nomem1:
220         kfree(table);
221 err_node:
222         of_node_put(data->parent);
223 err_nomem2:
224         per_cpu(cpu_data, cpu) = NULL;
225         kfree(data);
226 err_np:
227         of_node_put(np);
228
229         return -ENODEV;
230 }
231
232 static int __exit corenet_cpufreq_cpu_exit(struct cpufreq_policy *policy)
233 {
234         struct cpu_data *data = per_cpu(cpu_data, policy->cpu);
235         unsigned int cpu;
236
237         of_node_put(data->parent);
238         kfree(data->table);
239         kfree(data);
240
241         for_each_cpu(cpu, per_cpu(cpu_mask, policy->cpu))
242                 per_cpu(cpu_data, cpu) = NULL;
243
244         return 0;
245 }
246
247 static int corenet_cpufreq_target(struct cpufreq_policy *policy,
248                 unsigned int index)
249 {
250         struct clk *parent;
251         struct cpu_data *data = per_cpu(cpu_data, policy->cpu);
252
253         parent = of_clk_get(data->parent, data->table[index].driver_data);
254         return clk_set_parent(policy->clk, parent);
255 }
256
257 static struct cpufreq_driver ppc_corenet_cpufreq_driver = {
258         .name           = "ppc_cpufreq",
259         .flags          = CPUFREQ_CONST_LOOPS,
260         .init           = corenet_cpufreq_cpu_init,
261         .exit           = __exit_p(corenet_cpufreq_cpu_exit),
262         .verify         = cpufreq_generic_frequency_table_verify,
263         .target_index   = corenet_cpufreq_target,
264         .get            = cpufreq_generic_get,
265         .attr           = cpufreq_generic_attr,
266 };
267
268 static const struct of_device_id node_matches[] __initdata = {
269         { .compatible = "fsl,p2041-clockgen", .data = &sdata[0], },
270         { .compatible = "fsl,p3041-clockgen", .data = &sdata[0], },
271         { .compatible = "fsl,p5020-clockgen", .data = &sdata[1], },
272         { .compatible = "fsl,p4080-clockgen", .data = &sdata[2], },
273         { .compatible = "fsl,p5040-clockgen", .data = &sdata[2], },
274         { .compatible = "fsl,qoriq-clockgen-2.0", },
275         {}
276 };
277
278 static int __init ppc_corenet_cpufreq_init(void)
279 {
280         int ret;
281         struct device_node  *np;
282         const struct of_device_id *match;
283         const struct soc_data *data;
284         unsigned int cpu;
285
286         np = of_find_matching_node(NULL, node_matches);
287         if (!np)
288                 return -ENODEV;
289
290         for_each_possible_cpu(cpu) {
291                 if (!alloc_cpumask_var(&per_cpu(cpu_mask, cpu), GFP_KERNEL))
292                         goto err_mask;
293                 cpumask_copy(per_cpu(cpu_mask, cpu), cpu_core_mask(cpu));
294         }
295
296         match = of_match_node(node_matches, np);
297         data = match->data;
298         if (data) {
299                 if (data->flag)
300                         fmask = data->freq_mask;
301                 min_cpufreq = fsl_get_sys_freq();
302         } else {
303                 min_cpufreq = fsl_get_sys_freq() / 2;
304         }
305
306         of_node_put(np);
307
308         ret = cpufreq_register_driver(&ppc_corenet_cpufreq_driver);
309         if (!ret)
310                 pr_info("Freescale PowerPC corenet CPU frequency scaling driver\n");
311
312         return ret;
313
314 err_mask:
315         for_each_possible_cpu(cpu)
316                 free_cpumask_var(per_cpu(cpu_mask, cpu));
317
318         return -ENOMEM;
319 }
320 module_init(ppc_corenet_cpufreq_init);
321
322 static void __exit ppc_corenet_cpufreq_exit(void)
323 {
324         unsigned int cpu;
325
326         for_each_possible_cpu(cpu)
327                 free_cpumask_var(per_cpu(cpu_mask, cpu));
328
329         cpufreq_unregister_driver(&ppc_corenet_cpufreq_driver);
330 }
331 module_exit(ppc_corenet_cpufreq_exit);
332
333 MODULE_LICENSE("GPL");
334 MODULE_AUTHOR("Tang Yuantian <Yuantian.Tang@freescale.com>");
335 MODULE_DESCRIPTION("cpufreq driver for Freescale e500mc series SoCs");