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