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