]>
Commit | Line | Data |
---|---|---|
137e9590 JR |
1 | /* |
2 | * Copyright (C) 2007,2008 Freescale Semiconductor, Inc. All rights reserved. | |
3 | * | |
4 | * Author: John Rigby <jrigby@freescale.com> | |
5 | * | |
6 | * Implements the clk api defined in include/linux/clk.h | |
7 | * | |
8 | * Original based on linux/arch/arm/mach-integrator/clock.c | |
9 | * | |
10 | * Copyright (C) 2004 ARM Limited. | |
11 | * Written by Deep Blue Solutions Limited. | |
12 | * | |
13 | * This program is free software; you can redistribute it and/or modify | |
14 | * it under the terms of the GNU General Public License version 2 as | |
15 | * published by the Free Software Foundation. | |
16 | */ | |
17 | #include <linux/kernel.h> | |
18 | #include <linux/list.h> | |
19 | #include <linux/errno.h> | |
20 | #include <linux/err.h> | |
7dfe293c | 21 | #include <linux/module.h> |
137e9590 JR |
22 | #include <linux/string.h> |
23 | #include <linux/clk.h> | |
24 | #include <linux/mutex.h> | |
25 | #include <linux/io.h> | |
26 | ||
27 | #include <linux/of_platform.h> | |
87c441e5 | 28 | #include <asm/mpc5xxx.h> |
137e9590 JR |
29 | #include <asm/clk_interface.h> |
30 | ||
31 | #undef CLK_DEBUG | |
32 | ||
33 | static int clocks_initialized; | |
34 | ||
35 | #define CLK_HAS_RATE 0x1 /* has rate in MHz */ | |
36 | #define CLK_HAS_CTRL 0x2 /* has control reg and bit */ | |
37 | ||
38 | struct clk { | |
39 | struct list_head node; | |
40 | char name[32]; | |
41 | int flags; | |
42 | struct device *dev; | |
43 | unsigned long rate; | |
44 | struct module *owner; | |
45 | void (*calc) (struct clk *); | |
46 | struct clk *parent; | |
47 | int reg, bit; /* CLK_HAS_CTRL */ | |
48 | int div_shift; /* only used by generic_div_clk_calc */ | |
49 | }; | |
50 | ||
51 | static LIST_HEAD(clocks); | |
52 | static DEFINE_MUTEX(clocks_mutex); | |
53 | ||
54 | static struct clk *mpc5121_clk_get(struct device *dev, const char *id) | |
55 | { | |
56 | struct clk *p, *clk = ERR_PTR(-ENOENT); | |
57 | int dev_match = 0; | |
58 | int id_match = 0; | |
59 | ||
23faf631 | 60 | if (dev == NULL || id == NULL) |
59482fe5 | 61 | return clk; |
137e9590 JR |
62 | |
63 | mutex_lock(&clocks_mutex); | |
64 | list_for_each_entry(p, &clocks, node) { | |
23faf631 | 65 | if (dev == p->dev) |
137e9590 JR |
66 | dev_match++; |
67 | if (strcmp(id, p->name) == 0) | |
68 | id_match++; | |
69 | if ((dev_match || id_match) && try_module_get(p->owner)) { | |
70 | clk = p; | |
71 | break; | |
72 | } | |
73 | } | |
74 | mutex_unlock(&clocks_mutex); | |
75 | ||
76 | return clk; | |
77 | } | |
78 | ||
79 | #ifdef CLK_DEBUG | |
80 | static void dump_clocks(void) | |
81 | { | |
82 | struct clk *p; | |
83 | ||
84 | mutex_lock(&clocks_mutex); | |
85 | printk(KERN_INFO "CLOCKS:\n"); | |
86 | list_for_each_entry(p, &clocks, node) { | |
e7c5a4f2 | 87 | pr_info(" %s=%ld", p->name, p->rate); |
137e9590 | 88 | if (p->parent) |
e7c5a4f2 | 89 | pr_cont(" %s=%ld", p->parent->name, |
137e9590 JR |
90 | p->parent->rate); |
91 | if (p->flags & CLK_HAS_CTRL) | |
e7c5a4f2 WS |
92 | pr_cont(" reg/bit=%d/%d", p->reg, p->bit); |
93 | pr_cont("\n"); | |
137e9590 JR |
94 | } |
95 | mutex_unlock(&clocks_mutex); | |
96 | } | |
97 | #define DEBUG_CLK_DUMP() dump_clocks() | |
98 | #else | |
99 | #define DEBUG_CLK_DUMP() | |
100 | #endif | |
101 | ||
102 | ||
103 | static void mpc5121_clk_put(struct clk *clk) | |
104 | { | |
105 | module_put(clk->owner); | |
106 | } | |
107 | ||
108 | #define NRPSC 12 | |
109 | ||
110 | struct mpc512x_clockctl { | |
111 | u32 spmr; /* System PLL Mode Reg */ | |
112 | u32 sccr[2]; /* System Clk Ctrl Reg 1 & 2 */ | |
113 | u32 scfr1; /* System Clk Freq Reg 1 */ | |
114 | u32 scfr2; /* System Clk Freq Reg 2 */ | |
115 | u32 reserved; | |
116 | u32 bcr; /* Bread Crumb Reg */ | |
117 | u32 pccr[NRPSC]; /* PSC Clk Ctrl Reg 0-11 */ | |
118 | u32 spccr; /* SPDIF Clk Ctrl Reg */ | |
119 | u32 cccr; /* CFM Clk Ctrl Reg */ | |
120 | u32 dccr; /* DIU Clk Cnfg Reg */ | |
121 | }; | |
122 | ||
123 | struct mpc512x_clockctl __iomem *clockctl; | |
124 | ||
125 | static int mpc5121_clk_enable(struct clk *clk) | |
126 | { | |
127 | unsigned int mask; | |
128 | ||
129 | if (clk->flags & CLK_HAS_CTRL) { | |
130 | mask = in_be32(&clockctl->sccr[clk->reg]); | |
131 | mask |= 1 << clk->bit; | |
132 | out_be32(&clockctl->sccr[clk->reg], mask); | |
133 | } | |
134 | return 0; | |
135 | } | |
136 | ||
137 | static void mpc5121_clk_disable(struct clk *clk) | |
138 | { | |
139 | unsigned int mask; | |
140 | ||
141 | if (clk->flags & CLK_HAS_CTRL) { | |
142 | mask = in_be32(&clockctl->sccr[clk->reg]); | |
143 | mask &= ~(1 << clk->bit); | |
144 | out_be32(&clockctl->sccr[clk->reg], mask); | |
145 | } | |
146 | } | |
147 | ||
148 | static unsigned long mpc5121_clk_get_rate(struct clk *clk) | |
149 | { | |
150 | if (clk->flags & CLK_HAS_RATE) | |
151 | return clk->rate; | |
152 | else | |
153 | return 0; | |
154 | } | |
155 | ||
156 | static long mpc5121_clk_round_rate(struct clk *clk, unsigned long rate) | |
157 | { | |
158 | return rate; | |
159 | } | |
160 | ||
161 | static int mpc5121_clk_set_rate(struct clk *clk, unsigned long rate) | |
162 | { | |
163 | return 0; | |
164 | } | |
165 | ||
166 | static int clk_register(struct clk *clk) | |
167 | { | |
168 | mutex_lock(&clocks_mutex); | |
169 | list_add(&clk->node, &clocks); | |
170 | mutex_unlock(&clocks_mutex); | |
171 | return 0; | |
172 | } | |
173 | ||
174 | static unsigned long spmf_mult(void) | |
175 | { | |
176 | /* | |
177 | * Convert spmf to multiplier | |
178 | */ | |
179 | static int spmf_to_mult[] = { | |
180 | 68, 1, 12, 16, | |
181 | 20, 24, 28, 32, | |
182 | 36, 40, 44, 48, | |
183 | 52, 56, 60, 64 | |
184 | }; | |
185 | int spmf = (clockctl->spmr >> 24) & 0xf; | |
186 | return spmf_to_mult[spmf]; | |
187 | } | |
188 | ||
189 | static unsigned long sysdiv_div_x_2(void) | |
190 | { | |
191 | /* | |
192 | * Convert sysdiv to divisor x 2 | |
193 | * Some divisors have fractional parts so | |
194 | * multiply by 2 then divide by this value | |
195 | */ | |
196 | static int sysdiv_to_div_x_2[] = { | |
197 | 4, 5, 6, 7, | |
198 | 8, 9, 10, 14, | |
199 | 12, 16, 18, 22, | |
200 | 20, 24, 26, 30, | |
201 | 28, 32, 34, 38, | |
202 | 36, 40, 42, 46, | |
203 | 44, 48, 50, 54, | |
204 | 52, 56, 58, 62, | |
205 | 60, 64, 66, | |
206 | }; | |
207 | int sysdiv = (clockctl->scfr2 >> 26) & 0x3f; | |
208 | return sysdiv_to_div_x_2[sysdiv]; | |
209 | } | |
210 | ||
211 | static unsigned long ref_to_sys(unsigned long rate) | |
212 | { | |
213 | rate *= spmf_mult(); | |
214 | rate *= 2; | |
215 | rate /= sysdiv_div_x_2(); | |
216 | ||
217 | return rate; | |
218 | } | |
219 | ||
220 | static unsigned long sys_to_ref(unsigned long rate) | |
221 | { | |
222 | rate *= sysdiv_div_x_2(); | |
223 | rate /= 2; | |
224 | rate /= spmf_mult(); | |
225 | ||
226 | return rate; | |
227 | } | |
228 | ||
229 | static long ips_to_ref(unsigned long rate) | |
230 | { | |
231 | int ips_div = (clockctl->scfr1 >> 23) & 0x7; | |
232 | ||
233 | rate *= ips_div; /* csb_clk = ips_clk * ips_div */ | |
234 | rate *= 2; /* sys_clk = csb_clk * 2 */ | |
235 | return sys_to_ref(rate); | |
236 | } | |
237 | ||
238 | static unsigned long devtree_getfreq(char *clockname) | |
239 | { | |
240 | struct device_node *np; | |
241 | const unsigned int *prop; | |
242 | unsigned int val = 0; | |
243 | ||
244 | np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-immr"); | |
245 | if (np) { | |
246 | prop = of_get_property(np, clockname, NULL); | |
247 | if (prop) | |
248 | val = *prop; | |
249 | of_node_put(np); | |
250 | } | |
251 | return val; | |
252 | } | |
253 | ||
254 | static void ref_clk_calc(struct clk *clk) | |
255 | { | |
256 | unsigned long rate; | |
257 | ||
258 | rate = devtree_getfreq("bus-frequency"); | |
259 | if (rate == 0) { | |
260 | printk(KERN_ERR "No bus-frequency in dev tree\n"); | |
261 | clk->rate = 0; | |
262 | return; | |
263 | } | |
264 | clk->rate = ips_to_ref(rate); | |
265 | } | |
266 | ||
267 | static struct clk ref_clk = { | |
268 | .name = "ref_clk", | |
269 | .calc = ref_clk_calc, | |
270 | }; | |
271 | ||
272 | ||
273 | static void sys_clk_calc(struct clk *clk) | |
274 | { | |
275 | clk->rate = ref_to_sys(ref_clk.rate); | |
276 | } | |
277 | ||
278 | static struct clk sys_clk = { | |
279 | .name = "sys_clk", | |
280 | .calc = sys_clk_calc, | |
281 | }; | |
282 | ||
283 | static void diu_clk_calc(struct clk *clk) | |
284 | { | |
285 | int diudiv_x_2 = clockctl->scfr1 & 0xff; | |
286 | unsigned long rate; | |
287 | ||
288 | rate = sys_clk.rate; | |
289 | ||
290 | rate *= 2; | |
291 | rate /= diudiv_x_2; | |
292 | ||
293 | clk->rate = rate; | |
294 | } | |
295 | ||
9e2089cb AG |
296 | static void viu_clk_calc(struct clk *clk) |
297 | { | |
298 | unsigned long rate; | |
299 | ||
300 | rate = sys_clk.rate; | |
301 | rate /= 2; | |
302 | clk->rate = rate; | |
303 | } | |
304 | ||
137e9590 JR |
305 | static void half_clk_calc(struct clk *clk) |
306 | { | |
307 | clk->rate = clk->parent->rate / 2; | |
308 | } | |
309 | ||
310 | static void generic_div_clk_calc(struct clk *clk) | |
311 | { | |
312 | int div = (clockctl->scfr1 >> clk->div_shift) & 0x7; | |
313 | ||
314 | clk->rate = clk->parent->rate / div; | |
315 | } | |
316 | ||
317 | static void unity_clk_calc(struct clk *clk) | |
318 | { | |
319 | clk->rate = clk->parent->rate; | |
320 | } | |
321 | ||
322 | static struct clk csb_clk = { | |
323 | .name = "csb_clk", | |
324 | .calc = half_clk_calc, | |
325 | .parent = &sys_clk, | |
326 | }; | |
327 | ||
328 | static void e300_clk_calc(struct clk *clk) | |
329 | { | |
330 | int spmf = (clockctl->spmr >> 16) & 0xf; | |
331 | int ratex2 = clk->parent->rate * spmf; | |
332 | ||
333 | clk->rate = ratex2 / 2; | |
334 | } | |
335 | ||
336 | static struct clk e300_clk = { | |
337 | .name = "e300_clk", | |
338 | .calc = e300_clk_calc, | |
339 | .parent = &csb_clk, | |
340 | }; | |
341 | ||
342 | static struct clk ips_clk = { | |
343 | .name = "ips_clk", | |
344 | .calc = generic_div_clk_calc, | |
345 | .parent = &csb_clk, | |
346 | .div_shift = 23, | |
347 | }; | |
348 | ||
349 | /* | |
350 | * Clocks controlled by SCCR1 (.reg = 0) | |
351 | */ | |
352 | static struct clk lpc_clk = { | |
353 | .name = "lpc_clk", | |
354 | .flags = CLK_HAS_CTRL, | |
355 | .reg = 0, | |
356 | .bit = 30, | |
357 | .calc = generic_div_clk_calc, | |
358 | .parent = &ips_clk, | |
359 | .div_shift = 11, | |
360 | }; | |
361 | ||
362 | static struct clk nfc_clk = { | |
363 | .name = "nfc_clk", | |
364 | .flags = CLK_HAS_CTRL, | |
365 | .reg = 0, | |
366 | .bit = 29, | |
367 | .calc = generic_div_clk_calc, | |
368 | .parent = &ips_clk, | |
369 | .div_shift = 8, | |
370 | }; | |
371 | ||
372 | static struct clk pata_clk = { | |
373 | .name = "pata_clk", | |
374 | .flags = CLK_HAS_CTRL, | |
375 | .reg = 0, | |
376 | .bit = 28, | |
377 | .calc = unity_clk_calc, | |
378 | .parent = &ips_clk, | |
379 | }; | |
380 | ||
381 | /* | |
382 | * PSC clocks (bits 27 - 16) | |
383 | * are setup elsewhere | |
384 | */ | |
385 | ||
386 | static struct clk sata_clk = { | |
387 | .name = "sata_clk", | |
388 | .flags = CLK_HAS_CTRL, | |
389 | .reg = 0, | |
390 | .bit = 14, | |
391 | .calc = unity_clk_calc, | |
392 | .parent = &ips_clk, | |
393 | }; | |
394 | ||
395 | static struct clk fec_clk = { | |
396 | .name = "fec_clk", | |
397 | .flags = CLK_HAS_CTRL, | |
398 | .reg = 0, | |
399 | .bit = 13, | |
400 | .calc = unity_clk_calc, | |
401 | .parent = &ips_clk, | |
402 | }; | |
403 | ||
404 | static struct clk pci_clk = { | |
405 | .name = "pci_clk", | |
406 | .flags = CLK_HAS_CTRL, | |
407 | .reg = 0, | |
408 | .bit = 11, | |
409 | .calc = generic_div_clk_calc, | |
410 | .parent = &csb_clk, | |
411 | .div_shift = 20, | |
412 | }; | |
413 | ||
414 | /* | |
415 | * Clocks controlled by SCCR2 (.reg = 1) | |
416 | */ | |
417 | static struct clk diu_clk = { | |
418 | .name = "diu_clk", | |
419 | .flags = CLK_HAS_CTRL, | |
420 | .reg = 1, | |
421 | .bit = 31, | |
422 | .calc = diu_clk_calc, | |
423 | }; | |
424 | ||
9e2089cb AG |
425 | static struct clk viu_clk = { |
426 | .name = "viu_clk", | |
427 | .flags = CLK_HAS_CTRL, | |
428 | .reg = 1, | |
429 | .bit = 18, | |
430 | .calc = viu_clk_calc, | |
431 | }; | |
432 | ||
137e9590 JR |
433 | static struct clk axe_clk = { |
434 | .name = "axe_clk", | |
435 | .flags = CLK_HAS_CTRL, | |
436 | .reg = 1, | |
437 | .bit = 30, | |
438 | .calc = unity_clk_calc, | |
439 | .parent = &csb_clk, | |
440 | }; | |
441 | ||
442 | static struct clk usb1_clk = { | |
443 | .name = "usb1_clk", | |
444 | .flags = CLK_HAS_CTRL, | |
445 | .reg = 1, | |
446 | .bit = 28, | |
447 | .calc = unity_clk_calc, | |
448 | .parent = &csb_clk, | |
449 | }; | |
450 | ||
451 | static struct clk usb2_clk = { | |
452 | .name = "usb2_clk", | |
453 | .flags = CLK_HAS_CTRL, | |
454 | .reg = 1, | |
455 | .bit = 27, | |
456 | .calc = unity_clk_calc, | |
457 | .parent = &csb_clk, | |
458 | }; | |
459 | ||
460 | static struct clk i2c_clk = { | |
461 | .name = "i2c_clk", | |
462 | .flags = CLK_HAS_CTRL, | |
463 | .reg = 1, | |
464 | .bit = 26, | |
465 | .calc = unity_clk_calc, | |
466 | .parent = &ips_clk, | |
467 | }; | |
468 | ||
469 | static struct clk mscan_clk = { | |
470 | .name = "mscan_clk", | |
471 | .flags = CLK_HAS_CTRL, | |
472 | .reg = 1, | |
473 | .bit = 25, | |
474 | .calc = unity_clk_calc, | |
475 | .parent = &ips_clk, | |
476 | }; | |
477 | ||
478 | static struct clk sdhc_clk = { | |
479 | .name = "sdhc_clk", | |
480 | .flags = CLK_HAS_CTRL, | |
481 | .reg = 1, | |
482 | .bit = 24, | |
483 | .calc = unity_clk_calc, | |
484 | .parent = &ips_clk, | |
485 | }; | |
486 | ||
487 | static struct clk mbx_bus_clk = { | |
488 | .name = "mbx_bus_clk", | |
489 | .flags = CLK_HAS_CTRL, | |
490 | .reg = 1, | |
491 | .bit = 22, | |
492 | .calc = half_clk_calc, | |
493 | .parent = &csb_clk, | |
494 | }; | |
495 | ||
496 | static struct clk mbx_clk = { | |
497 | .name = "mbx_clk", | |
498 | .flags = CLK_HAS_CTRL, | |
499 | .reg = 1, | |
500 | .bit = 21, | |
501 | .calc = unity_clk_calc, | |
502 | .parent = &csb_clk, | |
503 | }; | |
504 | ||
505 | static struct clk mbx_3d_clk = { | |
506 | .name = "mbx_3d_clk", | |
507 | .flags = CLK_HAS_CTRL, | |
508 | .reg = 1, | |
509 | .bit = 20, | |
510 | .calc = generic_div_clk_calc, | |
511 | .parent = &mbx_bus_clk, | |
512 | .div_shift = 14, | |
513 | }; | |
514 | ||
515 | static void psc_mclk_in_calc(struct clk *clk) | |
516 | { | |
517 | clk->rate = devtree_getfreq("psc_mclk_in"); | |
518 | if (!clk->rate) | |
519 | clk->rate = 25000000; | |
520 | } | |
521 | ||
522 | static struct clk psc_mclk_in = { | |
523 | .name = "psc_mclk_in", | |
524 | .calc = psc_mclk_in_calc, | |
525 | }; | |
526 | ||
527 | static struct clk spdif_txclk = { | |
528 | .name = "spdif_txclk", | |
529 | .flags = CLK_HAS_CTRL, | |
530 | .reg = 1, | |
531 | .bit = 23, | |
532 | }; | |
533 | ||
534 | static struct clk spdif_rxclk = { | |
535 | .name = "spdif_rxclk", | |
536 | .flags = CLK_HAS_CTRL, | |
537 | .reg = 1, | |
538 | .bit = 23, | |
539 | }; | |
540 | ||
541 | static void ac97_clk_calc(struct clk *clk) | |
542 | { | |
543 | /* ac97 bit clock is always 24.567 MHz */ | |
544 | clk->rate = 24567000; | |
545 | } | |
546 | ||
547 | static struct clk ac97_clk = { | |
548 | .name = "ac97_clk_in", | |
549 | .calc = ac97_clk_calc, | |
550 | }; | |
551 | ||
552 | struct clk *rate_clks[] = { | |
553 | &ref_clk, | |
554 | &sys_clk, | |
555 | &diu_clk, | |
9e2089cb | 556 | &viu_clk, |
137e9590 JR |
557 | &csb_clk, |
558 | &e300_clk, | |
559 | &ips_clk, | |
560 | &fec_clk, | |
561 | &sata_clk, | |
562 | &pata_clk, | |
563 | &nfc_clk, | |
564 | &lpc_clk, | |
565 | &mbx_bus_clk, | |
566 | &mbx_clk, | |
567 | &mbx_3d_clk, | |
568 | &axe_clk, | |
569 | &usb1_clk, | |
570 | &usb2_clk, | |
571 | &i2c_clk, | |
572 | &mscan_clk, | |
573 | &sdhc_clk, | |
574 | &pci_clk, | |
575 | &psc_mclk_in, | |
576 | &spdif_txclk, | |
577 | &spdif_rxclk, | |
578 | &ac97_clk, | |
579 | NULL | |
580 | }; | |
581 | ||
582 | static void rate_clk_init(struct clk *clk) | |
583 | { | |
584 | if (clk->calc) { | |
585 | clk->calc(clk); | |
586 | clk->flags |= CLK_HAS_RATE; | |
587 | clk_register(clk); | |
588 | } else { | |
589 | printk(KERN_WARNING | |
590 | "Could not initialize clk %s without a calc routine\n", | |
591 | clk->name); | |
592 | } | |
593 | } | |
594 | ||
595 | static void rate_clks_init(void) | |
596 | { | |
597 | struct clk **cpp, *clk; | |
598 | ||
599 | cpp = rate_clks; | |
600 | while ((clk = *cpp++)) | |
601 | rate_clk_init(clk); | |
602 | } | |
603 | ||
604 | /* | |
605 | * There are two clk enable registers with 32 enable bits each | |
606 | * psc clocks and device clocks are all stored in dev_clks | |
607 | */ | |
608 | struct clk dev_clks[2][32]; | |
609 | ||
610 | /* | |
611 | * Given a psc number return the dev_clk | |
612 | * associated with it | |
613 | */ | |
614 | static struct clk *psc_dev_clk(int pscnum) | |
615 | { | |
616 | int reg, bit; | |
617 | struct clk *clk; | |
618 | ||
619 | reg = 0; | |
620 | bit = 27 - pscnum; | |
621 | ||
622 | clk = &dev_clks[reg][bit]; | |
623 | clk->reg = 0; | |
624 | clk->bit = bit; | |
625 | return clk; | |
626 | } | |
627 | ||
628 | /* | |
629 | * PSC clock rate calculation | |
630 | */ | |
631 | static void psc_calc_rate(struct clk *clk, int pscnum, struct device_node *np) | |
632 | { | |
633 | unsigned long mclk_src = sys_clk.rate; | |
634 | unsigned long mclk_div; | |
635 | ||
636 | /* | |
637 | * Can only change value of mclk divider | |
638 | * when the divider is disabled. | |
639 | * | |
640 | * Zero is not a valid divider so minimum | |
641 | * divider is 1 | |
642 | * | |
643 | * disable/set divider/enable | |
644 | */ | |
645 | out_be32(&clockctl->pccr[pscnum], 0); | |
646 | out_be32(&clockctl->pccr[pscnum], 0x00020000); | |
647 | out_be32(&clockctl->pccr[pscnum], 0x00030000); | |
648 | ||
649 | if (clockctl->pccr[pscnum] & 0x80) { | |
650 | clk->rate = spdif_rxclk.rate; | |
651 | return; | |
652 | } | |
653 | ||
654 | switch ((clockctl->pccr[pscnum] >> 14) & 0x3) { | |
655 | case 0: | |
656 | mclk_src = sys_clk.rate; | |
657 | break; | |
658 | case 1: | |
659 | mclk_src = ref_clk.rate; | |
660 | break; | |
661 | case 2: | |
662 | mclk_src = psc_mclk_in.rate; | |
663 | break; | |
664 | case 3: | |
665 | mclk_src = spdif_txclk.rate; | |
666 | break; | |
667 | } | |
668 | ||
669 | mclk_div = ((clockctl->pccr[pscnum] >> 17) & 0x7fff) + 1; | |
670 | clk->rate = mclk_src / mclk_div; | |
671 | } | |
672 | ||
673 | /* | |
674 | * Find all psc nodes in device tree and assign a clock | |
675 | * with name "psc%d_mclk" and dev pointing at the device | |
676 | * returned from of_find_device_by_node | |
677 | */ | |
678 | static void psc_clks_init(void) | |
679 | { | |
680 | struct device_node *np; | |
681 | const u32 *cell_index; | |
a454dc50 | 682 | struct platform_device *ofdev; |
137e9590 JR |
683 | |
684 | for_each_compatible_node(np, NULL, "fsl,mpc5121-psc") { | |
685 | cell_index = of_get_property(np, "cell-index", NULL); | |
686 | if (cell_index) { | |
687 | int pscnum = *cell_index; | |
688 | struct clk *clk = psc_dev_clk(pscnum); | |
689 | ||
690 | clk->flags = CLK_HAS_RATE | CLK_HAS_CTRL; | |
691 | ofdev = of_find_device_by_node(np); | |
692 | clk->dev = &ofdev->dev; | |
693 | /* | |
694 | * AC97 is special rate clock does | |
695 | * not go through normal path | |
696 | */ | |
697 | if (strcmp("ac97", np->name) == 0) | |
698 | clk->rate = ac97_clk.rate; | |
699 | else | |
700 | psc_calc_rate(clk, pscnum, np); | |
701 | sprintf(clk->name, "psc%d_mclk", pscnum); | |
702 | clk_register(clk); | |
703 | clk_enable(clk); | |
704 | } | |
705 | } | |
706 | } | |
707 | ||
708 | static struct clk_interface mpc5121_clk_functions = { | |
709 | .clk_get = mpc5121_clk_get, | |
710 | .clk_enable = mpc5121_clk_enable, | |
711 | .clk_disable = mpc5121_clk_disable, | |
712 | .clk_get_rate = mpc5121_clk_get_rate, | |
713 | .clk_put = mpc5121_clk_put, | |
714 | .clk_round_rate = mpc5121_clk_round_rate, | |
715 | .clk_set_rate = mpc5121_clk_set_rate, | |
716 | .clk_set_parent = NULL, | |
717 | .clk_get_parent = NULL, | |
718 | }; | |
719 | ||
284ed66f | 720 | int __init mpc5121_clk_init(void) |
137e9590 JR |
721 | { |
722 | struct device_node *np; | |
723 | ||
724 | np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-clock"); | |
725 | if (np) { | |
726 | clockctl = of_iomap(np, 0); | |
727 | of_node_put(np); | |
728 | } | |
729 | ||
730 | if (!clockctl) { | |
731 | printk(KERN_ERR "Could not map clock control registers\n"); | |
732 | return 0; | |
733 | } | |
734 | ||
735 | rate_clks_init(); | |
736 | psc_clks_init(); | |
737 | ||
738 | /* leave clockctl mapped forever */ | |
739 | /*iounmap(clockctl); */ | |
740 | DEBUG_CLK_DUMP(); | |
741 | clocks_initialized++; | |
742 | clk_functions = mpc5121_clk_functions; | |
743 | return 0; | |
744 | } |