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