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