Warning: That file was not part of the compilation database. It may have many parsing errors.
1 | // SPDX-License-Identifier: GPL-2.0 |
---|---|
2 | #include <linux/clk-provider.h> |
3 | #include <linux/clk/at91_pmc.h> |
4 | #include <linux/of.h> |
5 | #include <linux/mfd/syscon.h> |
6 | #include <linux/regmap.h> |
7 | #include <linux/slab.h> |
8 | |
9 | #include "pmc.h" |
10 | |
11 | #define MASTER_SOURCE_MAX 4 |
12 | |
13 | #define PERIPHERAL_AT91RM9200 0 |
14 | #define PERIPHERAL_AT91SAM9X5 1 |
15 | |
16 | #define PERIPHERAL_MAX 64 |
17 | |
18 | #define PERIPHERAL_ID_MIN 2 |
19 | |
20 | #define PROG_SOURCE_MAX 5 |
21 | #define PROG_ID_MAX 7 |
22 | |
23 | #define SYSTEM_MAX_ID 31 |
24 | |
25 | #ifdef CONFIG_HAVE_AT91_AUDIO_PLL |
26 | static void __init of_sama5d2_clk_audio_pll_frac_setup(struct device_node *np) |
27 | { |
28 | struct clk_hw *hw; |
29 | const char *name = np->name; |
30 | const char *parent_name; |
31 | struct regmap *regmap; |
32 | |
33 | regmap = syscon_node_to_regmap(of_get_parent(np)); |
34 | if (IS_ERR(regmap)) |
35 | return; |
36 | |
37 | parent_name = of_clk_get_parent_name(np, 0); |
38 | |
39 | hw = at91_clk_register_audio_pll_frac(regmap, name, parent_name); |
40 | if (IS_ERR(hw)) |
41 | return; |
42 | |
43 | of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw); |
44 | } |
45 | CLK_OF_DECLARE(of_sama5d2_clk_audio_pll_frac_setup, |
46 | "atmel,sama5d2-clk-audio-pll-frac", |
47 | of_sama5d2_clk_audio_pll_frac_setup); |
48 | |
49 | static void __init of_sama5d2_clk_audio_pll_pad_setup(struct device_node *np) |
50 | { |
51 | struct clk_hw *hw; |
52 | const char *name = np->name; |
53 | const char *parent_name; |
54 | struct regmap *regmap; |
55 | |
56 | regmap = syscon_node_to_regmap(of_get_parent(np)); |
57 | if (IS_ERR(regmap)) |
58 | return; |
59 | |
60 | parent_name = of_clk_get_parent_name(np, 0); |
61 | |
62 | hw = at91_clk_register_audio_pll_pad(regmap, name, parent_name); |
63 | if (IS_ERR(hw)) |
64 | return; |
65 | |
66 | of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw); |
67 | } |
68 | CLK_OF_DECLARE(of_sama5d2_clk_audio_pll_pad_setup, |
69 | "atmel,sama5d2-clk-audio-pll-pad", |
70 | of_sama5d2_clk_audio_pll_pad_setup); |
71 | |
72 | static void __init of_sama5d2_clk_audio_pll_pmc_setup(struct device_node *np) |
73 | { |
74 | struct clk_hw *hw; |
75 | const char *name = np->name; |
76 | const char *parent_name; |
77 | struct regmap *regmap; |
78 | |
79 | regmap = syscon_node_to_regmap(of_get_parent(np)); |
80 | if (IS_ERR(regmap)) |
81 | return; |
82 | |
83 | parent_name = of_clk_get_parent_name(np, 0); |
84 | |
85 | hw = at91_clk_register_audio_pll_pmc(regmap, name, parent_name); |
86 | if (IS_ERR(hw)) |
87 | return; |
88 | |
89 | of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw); |
90 | } |
91 | CLK_OF_DECLARE(of_sama5d2_clk_audio_pll_pmc_setup, |
92 | "atmel,sama5d2-clk-audio-pll-pmc", |
93 | of_sama5d2_clk_audio_pll_pmc_setup); |
94 | #endif /* CONFIG_HAVE_AT91_AUDIO_PLL */ |
95 | |
96 | #ifdef CONFIG_HAVE_AT91_GENERATED_CLK |
97 | #define GENERATED_SOURCE_MAX 6 |
98 | |
99 | #define GCK_ID_I2S0 54 |
100 | #define GCK_ID_I2S1 55 |
101 | #define GCK_ID_CLASSD 59 |
102 | |
103 | static void __init of_sama5d2_clk_generated_setup(struct device_node *np) |
104 | { |
105 | int num; |
106 | u32 id; |
107 | const char *name; |
108 | struct clk_hw *hw; |
109 | unsigned int num_parents; |
110 | const char *parent_names[GENERATED_SOURCE_MAX]; |
111 | struct device_node *gcknp; |
112 | struct clk_range range = CLK_RANGE(0, 0); |
113 | struct regmap *regmap; |
114 | |
115 | num_parents = of_clk_get_parent_count(np); |
116 | if (num_parents == 0 || num_parents > GENERATED_SOURCE_MAX) |
117 | return; |
118 | |
119 | of_clk_parent_fill(np, parent_names, num_parents); |
120 | |
121 | num = of_get_child_count(np); |
122 | if (!num || num > PERIPHERAL_MAX) |
123 | return; |
124 | |
125 | regmap = syscon_node_to_regmap(of_get_parent(np)); |
126 | if (IS_ERR(regmap)) |
127 | return; |
128 | |
129 | for_each_child_of_node(np, gcknp) { |
130 | bool pll_audio = false; |
131 | |
132 | if (of_property_read_u32(gcknp, "reg", &id)) |
133 | continue; |
134 | |
135 | if (id < PERIPHERAL_ID_MIN || id >= PERIPHERAL_MAX) |
136 | continue; |
137 | |
138 | if (of_property_read_string(np, "clock-output-names", &name)) |
139 | name = gcknp->name; |
140 | |
141 | of_at91_get_clk_range(gcknp, "atmel,clk-output-range", |
142 | &range); |
143 | |
144 | if (of_device_is_compatible(np, "atmel,sama5d2-clk-generated") && |
145 | (id == GCK_ID_I2S0 || id == GCK_ID_I2S1 || |
146 | id == GCK_ID_CLASSD)) |
147 | pll_audio = true; |
148 | |
149 | hw = at91_clk_register_generated(regmap, &pmc_pcr_lock, name, |
150 | parent_names, num_parents, |
151 | id, pll_audio, &range); |
152 | if (IS_ERR(hw)) |
153 | continue; |
154 | |
155 | of_clk_add_hw_provider(gcknp, of_clk_hw_simple_get, hw); |
156 | } |
157 | } |
158 | CLK_OF_DECLARE(of_sama5d2_clk_generated_setup, "atmel,sama5d2-clk-generated", |
159 | of_sama5d2_clk_generated_setup); |
160 | #endif /* CONFIG_HAVE_AT91_GENERATED_CLK */ |
161 | |
162 | #ifdef CONFIG_HAVE_AT91_H32MX |
163 | static void __init of_sama5d4_clk_h32mx_setup(struct device_node *np) |
164 | { |
165 | struct clk_hw *hw; |
166 | const char *name = np->name; |
167 | const char *parent_name; |
168 | struct regmap *regmap; |
169 | |
170 | regmap = syscon_node_to_regmap(of_get_parent(np)); |
171 | if (IS_ERR(regmap)) |
172 | return; |
173 | |
174 | parent_name = of_clk_get_parent_name(np, 0); |
175 | |
176 | hw = at91_clk_register_h32mx(regmap, name, parent_name); |
177 | if (IS_ERR(hw)) |
178 | return; |
179 | |
180 | of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw); |
181 | } |
182 | CLK_OF_DECLARE(of_sama5d4_clk_h32mx_setup, "atmel,sama5d4-clk-h32mx", |
183 | of_sama5d4_clk_h32mx_setup); |
184 | #endif /* CONFIG_HAVE_AT91_H32MX */ |
185 | |
186 | #ifdef CONFIG_HAVE_AT91_I2S_MUX_CLK |
187 | #define I2S_BUS_NR 2 |
188 | |
189 | static void __init of_sama5d2_clk_i2s_mux_setup(struct device_node *np) |
190 | { |
191 | struct regmap *regmap_sfr; |
192 | u8 bus_id; |
193 | const char *parent_names[2]; |
194 | struct device_node *i2s_mux_np; |
195 | struct clk_hw *hw; |
196 | int ret; |
197 | |
198 | regmap_sfr = syscon_regmap_lookup_by_compatible("atmel,sama5d2-sfr"); |
199 | if (IS_ERR(regmap_sfr)) |
200 | return; |
201 | |
202 | for_each_child_of_node(np, i2s_mux_np) { |
203 | if (of_property_read_u8(i2s_mux_np, "reg", &bus_id)) |
204 | continue; |
205 | |
206 | if (bus_id > I2S_BUS_NR) |
207 | continue; |
208 | |
209 | ret = of_clk_parent_fill(i2s_mux_np, parent_names, 2); |
210 | if (ret != 2) |
211 | continue; |
212 | |
213 | hw = at91_clk_i2s_mux_register(regmap_sfr, i2s_mux_np->name, |
214 | parent_names, 2, bus_id); |
215 | if (IS_ERR(hw)) |
216 | continue; |
217 | |
218 | of_clk_add_hw_provider(i2s_mux_np, of_clk_hw_simple_get, hw); |
219 | } |
220 | } |
221 | CLK_OF_DECLARE(sama5d2_clk_i2s_mux, "atmel,sama5d2-clk-i2s-mux", |
222 | of_sama5d2_clk_i2s_mux_setup); |
223 | #endif /* CONFIG_HAVE_AT91_I2S_MUX_CLK */ |
224 | |
225 | static void __init of_at91rm9200_clk_main_osc_setup(struct device_node *np) |
226 | { |
227 | struct clk_hw *hw; |
228 | const char *name = np->name; |
229 | const char *parent_name; |
230 | struct regmap *regmap; |
231 | bool bypass; |
232 | |
233 | of_property_read_string(np, "clock-output-names", &name); |
234 | bypass = of_property_read_bool(np, "atmel,osc-bypass"); |
235 | parent_name = of_clk_get_parent_name(np, 0); |
236 | |
237 | regmap = syscon_node_to_regmap(of_get_parent(np)); |
238 | if (IS_ERR(regmap)) |
239 | return; |
240 | |
241 | hw = at91_clk_register_main_osc(regmap, name, parent_name, bypass); |
242 | if (IS_ERR(hw)) |
243 | return; |
244 | |
245 | of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw); |
246 | } |
247 | CLK_OF_DECLARE(at91rm9200_clk_main_osc, "atmel,at91rm9200-clk-main-osc", |
248 | of_at91rm9200_clk_main_osc_setup); |
249 | |
250 | static void __init of_at91sam9x5_clk_main_rc_osc_setup(struct device_node *np) |
251 | { |
252 | struct clk_hw *hw; |
253 | u32 frequency = 0; |
254 | u32 accuracy = 0; |
255 | const char *name = np->name; |
256 | struct regmap *regmap; |
257 | |
258 | of_property_read_string(np, "clock-output-names", &name); |
259 | of_property_read_u32(np, "clock-frequency", &frequency); |
260 | of_property_read_u32(np, "clock-accuracy", &accuracy); |
261 | |
262 | regmap = syscon_node_to_regmap(of_get_parent(np)); |
263 | if (IS_ERR(regmap)) |
264 | return; |
265 | |
266 | hw = at91_clk_register_main_rc_osc(regmap, name, frequency, accuracy); |
267 | if (IS_ERR(hw)) |
268 | return; |
269 | |
270 | of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw); |
271 | } |
272 | CLK_OF_DECLARE(at91sam9x5_clk_main_rc_osc, "atmel,at91sam9x5-clk-main-rc-osc", |
273 | of_at91sam9x5_clk_main_rc_osc_setup); |
274 | |
275 | static void __init of_at91rm9200_clk_main_setup(struct device_node *np) |
276 | { |
277 | struct clk_hw *hw; |
278 | const char *parent_name; |
279 | const char *name = np->name; |
280 | struct regmap *regmap; |
281 | |
282 | parent_name = of_clk_get_parent_name(np, 0); |
283 | of_property_read_string(np, "clock-output-names", &name); |
284 | |
285 | regmap = syscon_node_to_regmap(of_get_parent(np)); |
286 | if (IS_ERR(regmap)) |
287 | return; |
288 | |
289 | hw = at91_clk_register_rm9200_main(regmap, name, parent_name); |
290 | if (IS_ERR(hw)) |
291 | return; |
292 | |
293 | of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw); |
294 | } |
295 | CLK_OF_DECLARE(at91rm9200_clk_main, "atmel,at91rm9200-clk-main", |
296 | of_at91rm9200_clk_main_setup); |
297 | |
298 | static void __init of_at91sam9x5_clk_main_setup(struct device_node *np) |
299 | { |
300 | struct clk_hw *hw; |
301 | const char *parent_names[2]; |
302 | unsigned int num_parents; |
303 | const char *name = np->name; |
304 | struct regmap *regmap; |
305 | |
306 | num_parents = of_clk_get_parent_count(np); |
307 | if (num_parents == 0 || num_parents > 2) |
308 | return; |
309 | |
310 | of_clk_parent_fill(np, parent_names, num_parents); |
311 | regmap = syscon_node_to_regmap(of_get_parent(np)); |
312 | if (IS_ERR(regmap)) |
313 | return; |
314 | |
315 | of_property_read_string(np, "clock-output-names", &name); |
316 | |
317 | hw = at91_clk_register_sam9x5_main(regmap, name, parent_names, |
318 | num_parents); |
319 | if (IS_ERR(hw)) |
320 | return; |
321 | |
322 | of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw); |
323 | } |
324 | CLK_OF_DECLARE(at91sam9x5_clk_main, "atmel,at91sam9x5-clk-main", |
325 | of_at91sam9x5_clk_main_setup); |
326 | |
327 | static struct clk_master_characteristics * __init |
328 | of_at91_clk_master_get_characteristics(struct device_node *np) |
329 | { |
330 | struct clk_master_characteristics *characteristics; |
331 | |
332 | characteristics = kzalloc(sizeof(*characteristics), GFP_KERNEL); |
333 | if (!characteristics) |
334 | return NULL; |
335 | |
336 | if (of_at91_get_clk_range(np, "atmel,clk-output-range", &characteristics->output)) |
337 | goto out_free_characteristics; |
338 | |
339 | of_property_read_u32_array(np, "atmel,clk-divisors", |
340 | characteristics->divisors, 4); |
341 | |
342 | characteristics->have_div3_pres = |
343 | of_property_read_bool(np, "atmel,master-clk-have-div3-pres"); |
344 | |
345 | return characteristics; |
346 | |
347 | out_free_characteristics: |
348 | kfree(characteristics); |
349 | return NULL; |
350 | } |
351 | |
352 | static void __init |
353 | of_at91_clk_master_setup(struct device_node *np, |
354 | const struct clk_master_layout *layout) |
355 | { |
356 | struct clk_hw *hw; |
357 | unsigned int num_parents; |
358 | const char *parent_names[MASTER_SOURCE_MAX]; |
359 | const char *name = np->name; |
360 | struct clk_master_characteristics *characteristics; |
361 | struct regmap *regmap; |
362 | |
363 | num_parents = of_clk_get_parent_count(np); |
364 | if (num_parents == 0 || num_parents > MASTER_SOURCE_MAX) |
365 | return; |
366 | |
367 | of_clk_parent_fill(np, parent_names, num_parents); |
368 | |
369 | of_property_read_string(np, "clock-output-names", &name); |
370 | |
371 | characteristics = of_at91_clk_master_get_characteristics(np); |
372 | if (!characteristics) |
373 | return; |
374 | |
375 | regmap = syscon_node_to_regmap(of_get_parent(np)); |
376 | if (IS_ERR(regmap)) |
377 | return; |
378 | |
379 | hw = at91_clk_register_master(regmap, name, num_parents, |
380 | parent_names, layout, |
381 | characteristics); |
382 | if (IS_ERR(hw)) |
383 | goto out_free_characteristics; |
384 | |
385 | of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw); |
386 | return; |
387 | |
388 | out_free_characteristics: |
389 | kfree(characteristics); |
390 | } |
391 | |
392 | static void __init of_at91rm9200_clk_master_setup(struct device_node *np) |
393 | { |
394 | of_at91_clk_master_setup(np, &at91rm9200_master_layout); |
395 | } |
396 | CLK_OF_DECLARE(at91rm9200_clk_master, "atmel,at91rm9200-clk-master", |
397 | of_at91rm9200_clk_master_setup); |
398 | |
399 | static void __init of_at91sam9x5_clk_master_setup(struct device_node *np) |
400 | { |
401 | of_at91_clk_master_setup(np, &at91sam9x5_master_layout); |
402 | } |
403 | CLK_OF_DECLARE(at91sam9x5_clk_master, "atmel,at91sam9x5-clk-master", |
404 | of_at91sam9x5_clk_master_setup); |
405 | |
406 | static void __init |
407 | of_at91_clk_periph_setup(struct device_node *np, u8 type) |
408 | { |
409 | int num; |
410 | u32 id; |
411 | struct clk_hw *hw; |
412 | const char *parent_name; |
413 | const char *name; |
414 | struct device_node *periphclknp; |
415 | struct regmap *regmap; |
416 | |
417 | parent_name = of_clk_get_parent_name(np, 0); |
418 | if (!parent_name) |
419 | return; |
420 | |
421 | num = of_get_child_count(np); |
422 | if (!num || num > PERIPHERAL_MAX) |
423 | return; |
424 | |
425 | regmap = syscon_node_to_regmap(of_get_parent(np)); |
426 | if (IS_ERR(regmap)) |
427 | return; |
428 | |
429 | for_each_child_of_node(np, periphclknp) { |
430 | if (of_property_read_u32(periphclknp, "reg", &id)) |
431 | continue; |
432 | |
433 | if (id >= PERIPHERAL_MAX) |
434 | continue; |
435 | |
436 | if (of_property_read_string(np, "clock-output-names", &name)) |
437 | name = periphclknp->name; |
438 | |
439 | if (type == PERIPHERAL_AT91RM9200) { |
440 | hw = at91_clk_register_peripheral(regmap, name, |
441 | parent_name, id); |
442 | } else { |
443 | struct clk_range range = CLK_RANGE(0, 0); |
444 | |
445 | of_at91_get_clk_range(periphclknp, |
446 | "atmel,clk-output-range", |
447 | &range); |
448 | |
449 | hw = at91_clk_register_sam9x5_peripheral(regmap, |
450 | &pmc_pcr_lock, |
451 | name, |
452 | parent_name, |
453 | id, &range); |
454 | } |
455 | |
456 | if (IS_ERR(hw)) |
457 | continue; |
458 | |
459 | of_clk_add_hw_provider(periphclknp, of_clk_hw_simple_get, hw); |
460 | } |
461 | } |
462 | |
463 | static void __init of_at91rm9200_clk_periph_setup(struct device_node *np) |
464 | { |
465 | of_at91_clk_periph_setup(np, PERIPHERAL_AT91RM9200); |
466 | } |
467 | CLK_OF_DECLARE(at91rm9200_clk_periph, "atmel,at91rm9200-clk-peripheral", |
468 | of_at91rm9200_clk_periph_setup); |
469 | |
470 | static void __init of_at91sam9x5_clk_periph_setup(struct device_node *np) |
471 | { |
472 | of_at91_clk_periph_setup(np, PERIPHERAL_AT91SAM9X5); |
473 | } |
474 | CLK_OF_DECLARE(at91sam9x5_clk_periph, "atmel,at91sam9x5-clk-peripheral", |
475 | of_at91sam9x5_clk_periph_setup); |
476 | |
477 | static struct clk_pll_characteristics * __init |
478 | of_at91_clk_pll_get_characteristics(struct device_node *np) |
479 | { |
480 | int i; |
481 | int offset; |
482 | u32 tmp; |
483 | int num_output; |
484 | u32 num_cells; |
485 | struct clk_range input; |
486 | struct clk_range *output; |
487 | u8 *out = NULL; |
488 | u16 *icpll = NULL; |
489 | struct clk_pll_characteristics *characteristics; |
490 | |
491 | if (of_at91_get_clk_range(np, "atmel,clk-input-range", &input)) |
492 | return NULL; |
493 | |
494 | if (of_property_read_u32(np, "#atmel,pll-clk-output-range-cells", |
495 | &num_cells)) |
496 | return NULL; |
497 | |
498 | if (num_cells < 2 || num_cells > 4) |
499 | return NULL; |
500 | |
501 | if (!of_get_property(np, "atmel,pll-clk-output-ranges", &tmp)) |
502 | return NULL; |
503 | num_output = tmp / (sizeof(u32) * num_cells); |
504 | |
505 | characteristics = kzalloc(sizeof(*characteristics), GFP_KERNEL); |
506 | if (!characteristics) |
507 | return NULL; |
508 | |
509 | output = kcalloc(num_output, sizeof(*output), GFP_KERNEL); |
510 | if (!output) |
511 | goto out_free_characteristics; |
512 | |
513 | if (num_cells > 2) { |
514 | out = kcalloc(num_output, sizeof(*out), GFP_KERNEL); |
515 | if (!out) |
516 | goto out_free_output; |
517 | } |
518 | |
519 | if (num_cells > 3) { |
520 | icpll = kcalloc(num_output, sizeof(*icpll), GFP_KERNEL); |
521 | if (!icpll) |
522 | goto out_free_output; |
523 | } |
524 | |
525 | for (i = 0; i < num_output; i++) { |
526 | offset = i * num_cells; |
527 | if (of_property_read_u32_index(np, |
528 | "atmel,pll-clk-output-ranges", |
529 | offset, &tmp)) |
530 | goto out_free_output; |
531 | output[i].min = tmp; |
532 | if (of_property_read_u32_index(np, |
533 | "atmel,pll-clk-output-ranges", |
534 | offset + 1, &tmp)) |
535 | goto out_free_output; |
536 | output[i].max = tmp; |
537 | |
538 | if (num_cells == 2) |
539 | continue; |
540 | |
541 | if (of_property_read_u32_index(np, |
542 | "atmel,pll-clk-output-ranges", |
543 | offset + 2, &tmp)) |
544 | goto out_free_output; |
545 | out[i] = tmp; |
546 | |
547 | if (num_cells == 3) |
548 | continue; |
549 | |
550 | if (of_property_read_u32_index(np, |
551 | "atmel,pll-clk-output-ranges", |
552 | offset + 3, &tmp)) |
553 | goto out_free_output; |
554 | icpll[i] = tmp; |
555 | } |
556 | |
557 | characteristics->input = input; |
558 | characteristics->num_output = num_output; |
559 | characteristics->output = output; |
560 | characteristics->out = out; |
561 | characteristics->icpll = icpll; |
562 | return characteristics; |
563 | |
564 | out_free_output: |
565 | kfree(icpll); |
566 | kfree(out); |
567 | kfree(output); |
568 | out_free_characteristics: |
569 | kfree(characteristics); |
570 | return NULL; |
571 | } |
572 | |
573 | static void __init |
574 | of_at91_clk_pll_setup(struct device_node *np, |
575 | const struct clk_pll_layout *layout) |
576 | { |
577 | u32 id; |
578 | struct clk_hw *hw; |
579 | struct regmap *regmap; |
580 | const char *parent_name; |
581 | const char *name = np->name; |
582 | struct clk_pll_characteristics *characteristics; |
583 | |
584 | if (of_property_read_u32(np, "reg", &id)) |
585 | return; |
586 | |
587 | parent_name = of_clk_get_parent_name(np, 0); |
588 | |
589 | of_property_read_string(np, "clock-output-names", &name); |
590 | |
591 | regmap = syscon_node_to_regmap(of_get_parent(np)); |
592 | if (IS_ERR(regmap)) |
593 | return; |
594 | |
595 | characteristics = of_at91_clk_pll_get_characteristics(np); |
596 | if (!characteristics) |
597 | return; |
598 | |
599 | hw = at91_clk_register_pll(regmap, name, parent_name, id, layout, |
600 | characteristics); |
601 | if (IS_ERR(hw)) |
602 | goto out_free_characteristics; |
603 | |
604 | of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw); |
605 | return; |
606 | |
607 | out_free_characteristics: |
608 | kfree(characteristics); |
609 | } |
610 | |
611 | static void __init of_at91rm9200_clk_pll_setup(struct device_node *np) |
612 | { |
613 | of_at91_clk_pll_setup(np, &at91rm9200_pll_layout); |
614 | } |
615 | CLK_OF_DECLARE(at91rm9200_clk_pll, "atmel,at91rm9200-clk-pll", |
616 | of_at91rm9200_clk_pll_setup); |
617 | |
618 | static void __init of_at91sam9g45_clk_pll_setup(struct device_node *np) |
619 | { |
620 | of_at91_clk_pll_setup(np, &at91sam9g45_pll_layout); |
621 | } |
622 | CLK_OF_DECLARE(at91sam9g45_clk_pll, "atmel,at91sam9g45-clk-pll", |
623 | of_at91sam9g45_clk_pll_setup); |
624 | |
625 | static void __init of_at91sam9g20_clk_pllb_setup(struct device_node *np) |
626 | { |
627 | of_at91_clk_pll_setup(np, &at91sam9g20_pllb_layout); |
628 | } |
629 | CLK_OF_DECLARE(at91sam9g20_clk_pllb, "atmel,at91sam9g20-clk-pllb", |
630 | of_at91sam9g20_clk_pllb_setup); |
631 | |
632 | static void __init of_sama5d3_clk_pll_setup(struct device_node *np) |
633 | { |
634 | of_at91_clk_pll_setup(np, &sama5d3_pll_layout); |
635 | } |
636 | CLK_OF_DECLARE(sama5d3_clk_pll, "atmel,sama5d3-clk-pll", |
637 | of_sama5d3_clk_pll_setup); |
638 | |
639 | static void __init |
640 | of_at91sam9x5_clk_plldiv_setup(struct device_node *np) |
641 | { |
642 | struct clk_hw *hw; |
643 | const char *parent_name; |
644 | const char *name = np->name; |
645 | struct regmap *regmap; |
646 | |
647 | parent_name = of_clk_get_parent_name(np, 0); |
648 | |
649 | of_property_read_string(np, "clock-output-names", &name); |
650 | |
651 | regmap = syscon_node_to_regmap(of_get_parent(np)); |
652 | if (IS_ERR(regmap)) |
653 | return; |
654 | |
655 | hw = at91_clk_register_plldiv(regmap, name, parent_name); |
656 | if (IS_ERR(hw)) |
657 | return; |
658 | |
659 | of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw); |
660 | } |
661 | CLK_OF_DECLARE(at91sam9x5_clk_plldiv, "atmel,at91sam9x5-clk-plldiv", |
662 | of_at91sam9x5_clk_plldiv_setup); |
663 | |
664 | static void __init |
665 | of_at91_clk_prog_setup(struct device_node *np, |
666 | const struct clk_programmable_layout *layout) |
667 | { |
668 | int num; |
669 | u32 id; |
670 | struct clk_hw *hw; |
671 | unsigned int num_parents; |
672 | const char *parent_names[PROG_SOURCE_MAX]; |
673 | const char *name; |
674 | struct device_node *progclknp; |
675 | struct regmap *regmap; |
676 | |
677 | num_parents = of_clk_get_parent_count(np); |
678 | if (num_parents == 0 || num_parents > PROG_SOURCE_MAX) |
679 | return; |
680 | |
681 | of_clk_parent_fill(np, parent_names, num_parents); |
682 | |
683 | num = of_get_child_count(np); |
684 | if (!num || num > (PROG_ID_MAX + 1)) |
685 | return; |
686 | |
687 | regmap = syscon_node_to_regmap(of_get_parent(np)); |
688 | if (IS_ERR(regmap)) |
689 | return; |
690 | |
691 | for_each_child_of_node(np, progclknp) { |
692 | if (of_property_read_u32(progclknp, "reg", &id)) |
693 | continue; |
694 | |
695 | if (of_property_read_string(np, "clock-output-names", &name)) |
696 | name = progclknp->name; |
697 | |
698 | hw = at91_clk_register_programmable(regmap, name, |
699 | parent_names, num_parents, |
700 | id, layout); |
701 | if (IS_ERR(hw)) |
702 | continue; |
703 | |
704 | of_clk_add_hw_provider(progclknp, of_clk_hw_simple_get, hw); |
705 | } |
706 | } |
707 | |
708 | static void __init of_at91rm9200_clk_prog_setup(struct device_node *np) |
709 | { |
710 | of_at91_clk_prog_setup(np, &at91rm9200_programmable_layout); |
711 | } |
712 | CLK_OF_DECLARE(at91rm9200_clk_prog, "atmel,at91rm9200-clk-programmable", |
713 | of_at91rm9200_clk_prog_setup); |
714 | |
715 | static void __init of_at91sam9g45_clk_prog_setup(struct device_node *np) |
716 | { |
717 | of_at91_clk_prog_setup(np, &at91sam9g45_programmable_layout); |
718 | } |
719 | CLK_OF_DECLARE(at91sam9g45_clk_prog, "atmel,at91sam9g45-clk-programmable", |
720 | of_at91sam9g45_clk_prog_setup); |
721 | |
722 | static void __init of_at91sam9x5_clk_prog_setup(struct device_node *np) |
723 | { |
724 | of_at91_clk_prog_setup(np, &at91sam9x5_programmable_layout); |
725 | } |
726 | CLK_OF_DECLARE(at91sam9x5_clk_prog, "atmel,at91sam9x5-clk-programmable", |
727 | of_at91sam9x5_clk_prog_setup); |
728 | |
729 | static void __init of_at91sam9260_clk_slow_setup(struct device_node *np) |
730 | { |
731 | struct clk_hw *hw; |
732 | const char *parent_names[2]; |
733 | unsigned int num_parents; |
734 | const char *name = np->name; |
735 | struct regmap *regmap; |
736 | |
737 | num_parents = of_clk_get_parent_count(np); |
738 | if (num_parents != 2) |
739 | return; |
740 | |
741 | of_clk_parent_fill(np, parent_names, num_parents); |
742 | regmap = syscon_node_to_regmap(of_get_parent(np)); |
743 | if (IS_ERR(regmap)) |
744 | return; |
745 | |
746 | of_property_read_string(np, "clock-output-names", &name); |
747 | |
748 | hw = at91_clk_register_sam9260_slow(regmap, name, parent_names, |
749 | num_parents); |
750 | if (IS_ERR(hw)) |
751 | return; |
752 | |
753 | of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw); |
754 | } |
755 | CLK_OF_DECLARE(at91sam9260_clk_slow, "atmel,at91sam9260-clk-slow", |
756 | of_at91sam9260_clk_slow_setup); |
757 | |
758 | #ifdef CONFIG_HAVE_AT91_SMD |
759 | #define SMD_SOURCE_MAX 2 |
760 | |
761 | static void __init of_at91sam9x5_clk_smd_setup(struct device_node *np) |
762 | { |
763 | struct clk_hw *hw; |
764 | unsigned int num_parents; |
765 | const char *parent_names[SMD_SOURCE_MAX]; |
766 | const char *name = np->name; |
767 | struct regmap *regmap; |
768 | |
769 | num_parents = of_clk_get_parent_count(np); |
770 | if (num_parents == 0 || num_parents > SMD_SOURCE_MAX) |
771 | return; |
772 | |
773 | of_clk_parent_fill(np, parent_names, num_parents); |
774 | |
775 | of_property_read_string(np, "clock-output-names", &name); |
776 | |
777 | regmap = syscon_node_to_regmap(of_get_parent(np)); |
778 | if (IS_ERR(regmap)) |
779 | return; |
780 | |
781 | hw = at91sam9x5_clk_register_smd(regmap, name, parent_names, |
782 | num_parents); |
783 | if (IS_ERR(hw)) |
784 | return; |
785 | |
786 | of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw); |
787 | } |
788 | CLK_OF_DECLARE(at91sam9x5_clk_smd, "atmel,at91sam9x5-clk-smd", |
789 | of_at91sam9x5_clk_smd_setup); |
790 | #endif /* CONFIG_HAVE_AT91_SMD */ |
791 | |
792 | static void __init of_at91rm9200_clk_sys_setup(struct device_node *np) |
793 | { |
794 | int num; |
795 | u32 id; |
796 | struct clk_hw *hw; |
797 | const char *name; |
798 | struct device_node *sysclknp; |
799 | const char *parent_name; |
800 | struct regmap *regmap; |
801 | |
802 | num = of_get_child_count(np); |
803 | if (num > (SYSTEM_MAX_ID + 1)) |
804 | return; |
805 | |
806 | regmap = syscon_node_to_regmap(of_get_parent(np)); |
807 | if (IS_ERR(regmap)) |
808 | return; |
809 | |
810 | for_each_child_of_node(np, sysclknp) { |
811 | if (of_property_read_u32(sysclknp, "reg", &id)) |
812 | continue; |
813 | |
814 | if (of_property_read_string(np, "clock-output-names", &name)) |
815 | name = sysclknp->name; |
816 | |
817 | parent_name = of_clk_get_parent_name(sysclknp, 0); |
818 | |
819 | hw = at91_clk_register_system(regmap, name, parent_name, id); |
820 | if (IS_ERR(hw)) |
821 | continue; |
822 | |
823 | of_clk_add_hw_provider(sysclknp, of_clk_hw_simple_get, hw); |
824 | } |
825 | } |
826 | CLK_OF_DECLARE(at91rm9200_clk_sys, "atmel,at91rm9200-clk-system", |
827 | of_at91rm9200_clk_sys_setup); |
828 | |
829 | #ifdef CONFIG_HAVE_AT91_USB_CLK |
830 | #define USB_SOURCE_MAX 2 |
831 | |
832 | static void __init of_at91sam9x5_clk_usb_setup(struct device_node *np) |
833 | { |
834 | struct clk_hw *hw; |
835 | unsigned int num_parents; |
836 | const char *parent_names[USB_SOURCE_MAX]; |
837 | const char *name = np->name; |
838 | struct regmap *regmap; |
839 | |
840 | num_parents = of_clk_get_parent_count(np); |
841 | if (num_parents == 0 || num_parents > USB_SOURCE_MAX) |
842 | return; |
843 | |
844 | of_clk_parent_fill(np, parent_names, num_parents); |
845 | |
846 | of_property_read_string(np, "clock-output-names", &name); |
847 | |
848 | regmap = syscon_node_to_regmap(of_get_parent(np)); |
849 | if (IS_ERR(regmap)) |
850 | return; |
851 | |
852 | hw = at91sam9x5_clk_register_usb(regmap, name, parent_names, |
853 | num_parents); |
854 | if (IS_ERR(hw)) |
855 | return; |
856 | |
857 | of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw); |
858 | } |
859 | CLK_OF_DECLARE(at91sam9x5_clk_usb, "atmel,at91sam9x5-clk-usb", |
860 | of_at91sam9x5_clk_usb_setup); |
861 | |
862 | static void __init of_at91sam9n12_clk_usb_setup(struct device_node *np) |
863 | { |
864 | struct clk_hw *hw; |
865 | const char *parent_name; |
866 | const char *name = np->name; |
867 | struct regmap *regmap; |
868 | |
869 | parent_name = of_clk_get_parent_name(np, 0); |
870 | if (!parent_name) |
871 | return; |
872 | |
873 | of_property_read_string(np, "clock-output-names", &name); |
874 | |
875 | regmap = syscon_node_to_regmap(of_get_parent(np)); |
876 | if (IS_ERR(regmap)) |
877 | return; |
878 | |
879 | hw = at91sam9n12_clk_register_usb(regmap, name, parent_name); |
880 | if (IS_ERR(hw)) |
881 | return; |
882 | |
883 | of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw); |
884 | } |
885 | CLK_OF_DECLARE(at91sam9n12_clk_usb, "atmel,at91sam9n12-clk-usb", |
886 | of_at91sam9n12_clk_usb_setup); |
887 | |
888 | static void __init of_at91rm9200_clk_usb_setup(struct device_node *np) |
889 | { |
890 | struct clk_hw *hw; |
891 | const char *parent_name; |
892 | const char *name = np->name; |
893 | u32 divisors[4] = {0, 0, 0, 0}; |
894 | struct regmap *regmap; |
895 | |
896 | parent_name = of_clk_get_parent_name(np, 0); |
897 | if (!parent_name) |
898 | return; |
899 | |
900 | of_property_read_u32_array(np, "atmel,clk-divisors", divisors, 4); |
901 | if (!divisors[0]) |
902 | return; |
903 | |
904 | of_property_read_string(np, "clock-output-names", &name); |
905 | |
906 | regmap = syscon_node_to_regmap(of_get_parent(np)); |
907 | if (IS_ERR(regmap)) |
908 | return; |
909 | hw = at91rm9200_clk_register_usb(regmap, name, parent_name, divisors); |
910 | if (IS_ERR(hw)) |
911 | return; |
912 | |
913 | of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw); |
914 | } |
915 | CLK_OF_DECLARE(at91rm9200_clk_usb, "atmel,at91rm9200-clk-usb", |
916 | of_at91rm9200_clk_usb_setup); |
917 | #endif /* CONFIG_HAVE_AT91_USB_CLK */ |
918 | |
919 | #ifdef CONFIG_HAVE_AT91_UTMI |
920 | static void __init of_at91sam9x5_clk_utmi_setup(struct device_node *np) |
921 | { |
922 | struct clk_hw *hw; |
923 | const char *parent_name; |
924 | const char *name = np->name; |
925 | struct regmap *regmap_pmc, *regmap_sfr; |
926 | |
927 | parent_name = of_clk_get_parent_name(np, 0); |
928 | |
929 | of_property_read_string(np, "clock-output-names", &name); |
930 | |
931 | regmap_pmc = syscon_node_to_regmap(of_get_parent(np)); |
932 | if (IS_ERR(regmap_pmc)) |
933 | return; |
934 | |
935 | /* |
936 | * If the device supports different mainck rates, this value has to be |
937 | * set in the UTMI Clock Trimming register. |
938 | * - 9x5: mainck supports several rates but it is indicated that a |
939 | * 12 MHz is needed in case of USB. |
940 | * - sama5d3 and sama5d2: mainck supports several rates. Configuring |
941 | * the FREQ field of the UTMI Clock Trimming register is mandatory. |
942 | * - sama5d4: mainck is at 12 MHz. |
943 | * |
944 | * We only need to retrieve sama5d3 or sama5d2 sfr regmap. |
945 | */ |
946 | regmap_sfr = syscon_regmap_lookup_by_compatible("atmel,sama5d3-sfr"); |
947 | if (IS_ERR(regmap_sfr)) { |
948 | regmap_sfr = syscon_regmap_lookup_by_compatible("atmel,sama5d2-sfr"); |
949 | if (IS_ERR(regmap_sfr)) |
950 | regmap_sfr = NULL; |
951 | } |
952 | |
953 | hw = at91_clk_register_utmi(regmap_pmc, regmap_sfr, name, parent_name); |
954 | if (IS_ERR(hw)) |
955 | return; |
956 | |
957 | of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw); |
958 | } |
959 | CLK_OF_DECLARE(at91sam9x5_clk_utmi, "atmel,at91sam9x5-clk-utmi", |
960 | of_at91sam9x5_clk_utmi_setup); |
961 | #endif /* CONFIG_HAVE_AT91_UTMI */ |
962 |
Warning: That file was not part of the compilation database. It may have many parsing errors.