1
2
3
4
5
6
7
8
9
10#include <linux/bitops.h>
11#include <linux/clk.h>
12#include <linux/clk-provider.h>
13#include <linux/clkdev.h>
14#include <linux/device.h>
15#include <linux/errno.h>
16#include <linux/io.h>
17#include <linux/of.h>
18#include <linux/of_address.h>
19
20#include <asm/mpc5121.h>
21#include <dt-bindings/clock/mpc512x-clock.h>
22
23#include "mpc512x.h"
24
25
26enum {
27 MCLK_IDX_MUX0,
28 MCLK_IDX_EN0,
29 MCLK_IDX_DIV0,
30 MCLK_MAX_IDX,
31};
32
33#define NR_PSCS 12
34#define NR_MSCANS 4
35#define NR_SPDIFS 1
36#define NR_OUTCLK 4
37#define NR_MCLKS (NR_PSCS + NR_MSCANS + NR_SPDIFS + NR_OUTCLK)
38
39
40enum {
41
42 MPC512x_CLK_START_PRIVATE = MPC512x_CLK_LAST_PUBLIC,
43
44 MPC512x_CLK_DDR,
45 MPC512x_CLK_MEM,
46 MPC512x_CLK_IIM,
47
48 MPC512x_CLK_DDR_UG,
49 MPC512x_CLK_SDHC_x4,
50 MPC512x_CLK_SDHC_UG,
51 MPC512x_CLK_SDHC2_UG,
52 MPC512x_CLK_DIU_x4,
53 MPC512x_CLK_DIU_UG,
54 MPC512x_CLK_MBX_BUS_UG,
55 MPC512x_CLK_MBX_UG,
56 MPC512x_CLK_MBX_3D_UG,
57 MPC512x_CLK_PCI_UG,
58 MPC512x_CLK_NFC_UG,
59 MPC512x_CLK_LPC_UG,
60 MPC512x_CLK_SPDIF_TX_IN,
61
62 MPC512x_CLK_MCLKS_FIRST,
63 MPC512x_CLK_MCLKS_LAST = MPC512x_CLK_MCLKS_FIRST
64 + NR_MCLKS * MCLK_MAX_IDX,
65
66 MPC512x_CLK_LAST_PRIVATE,
67};
68
69
70static struct clk *clks[MPC512x_CLK_LAST_PRIVATE];
71static struct clk_onecell_data clk_data;
72
73
74static struct mpc512x_ccm __iomem *clkregs;
75static DEFINE_SPINLOCK(clklock);
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94static enum soc_type {
95 MPC512x_SOC_MPC5121,
96 MPC512x_SOC_MPC5123,
97 MPC512x_SOC_MPC5125,
98} soc;
99
100static void mpc512x_clk_determine_soc(void)
101{
102 if (of_machine_is_compatible("fsl,mpc5121")) {
103 soc = MPC512x_SOC_MPC5121;
104 return;
105 }
106 if (of_machine_is_compatible("fsl,mpc5123")) {
107 soc = MPC512x_SOC_MPC5123;
108 return;
109 }
110 if (of_machine_is_compatible("fsl,mpc5125")) {
111 soc = MPC512x_SOC_MPC5125;
112 return;
113 }
114}
115
116static bool soc_has_mbx(void)
117{
118 if (soc == MPC512x_SOC_MPC5121)
119 return true;
120 return false;
121}
122
123static bool soc_has_axe(void)
124{
125 if (soc == MPC512x_SOC_MPC5125)
126 return false;
127 return true;
128}
129
130static bool soc_has_viu(void)
131{
132 if (soc == MPC512x_SOC_MPC5125)
133 return false;
134 return true;
135}
136
137static bool soc_has_spdif(void)
138{
139 if (soc == MPC512x_SOC_MPC5125)
140 return false;
141 return true;
142}
143
144static bool soc_has_pata(void)
145{
146 if (soc == MPC512x_SOC_MPC5125)
147 return false;
148 return true;
149}
150
151static bool soc_has_sata(void)
152{
153 if (soc == MPC512x_SOC_MPC5125)
154 return false;
155 return true;
156}
157
158static bool soc_has_pci(void)
159{
160 if (soc == MPC512x_SOC_MPC5125)
161 return false;
162 return true;
163}
164
165static bool soc_has_fec2(void)
166{
167 if (soc == MPC512x_SOC_MPC5125)
168 return true;
169 return false;
170}
171
172static int soc_max_pscnum(void)
173{
174 if (soc == MPC512x_SOC_MPC5125)
175 return 10;
176 return 12;
177}
178
179static bool soc_has_sdhc2(void)
180{
181 if (soc == MPC512x_SOC_MPC5125)
182 return true;
183 return false;
184}
185
186static bool soc_has_nfc_5125(void)
187{
188 if (soc == MPC512x_SOC_MPC5125)
189 return true;
190 return false;
191}
192
193static bool soc_has_outclk(void)
194{
195 if (soc == MPC512x_SOC_MPC5125)
196 return true;
197 return false;
198}
199
200static bool soc_has_cpmf_0_bypass(void)
201{
202 if (soc == MPC512x_SOC_MPC5125)
203 return true;
204 return false;
205}
206
207static bool soc_has_mclk_mux0_canin(void)
208{
209 if (soc == MPC512x_SOC_MPC5125)
210 return true;
211 return false;
212}
213
214
215
216
217
218static inline struct clk *mpc512x_clk_fixed(const char *name, int rate)
219{
220 return clk_register_fixed_rate(NULL, name, NULL, 0, rate);
221}
222
223static inline struct clk *mpc512x_clk_factor(
224 const char *name, const char *parent_name,
225 int mul, int div)
226{
227 int clkflags;
228
229 clkflags = CLK_SET_RATE_PARENT;
230 return clk_register_fixed_factor(NULL, name, parent_name, clkflags,
231 mul, div);
232}
233
234static inline struct clk *mpc512x_clk_divider(
235 const char *name, const char *parent_name, u8 clkflags,
236 u32 __iomem *reg, u8 pos, u8 len, int divflags)
237{
238 divflags |= CLK_DIVIDER_BIG_ENDIAN;
239 return clk_register_divider(NULL, name, parent_name, clkflags,
240 reg, pos, len, divflags, &clklock);
241}
242
243static inline struct clk *mpc512x_clk_divtable(
244 const char *name, const char *parent_name,
245 u32 __iomem *reg, u8 pos, u8 len,
246 const struct clk_div_table *divtab)
247{
248 u8 divflags;
249
250 divflags = CLK_DIVIDER_BIG_ENDIAN;
251 return clk_register_divider_table(NULL, name, parent_name, 0,
252 reg, pos, len, divflags,
253 divtab, &clklock);
254}
255
256static inline struct clk *mpc512x_clk_gated(
257 const char *name, const char *parent_name,
258 u32 __iomem *reg, u8 pos)
259{
260 int clkflags;
261 u8 gateflags;
262
263 clkflags = CLK_SET_RATE_PARENT;
264 gateflags = CLK_GATE_BIG_ENDIAN;
265 return clk_register_gate(NULL, name, parent_name, clkflags,
266 reg, pos, gateflags, &clklock);
267}
268
269static inline struct clk *mpc512x_clk_muxed(const char *name,
270 const char **parent_names, int parent_count,
271 u32 __iomem *reg, u8 pos, u8 len)
272{
273 int clkflags;
274 u8 muxflags;
275
276 clkflags = CLK_SET_RATE_PARENT;
277 muxflags = CLK_MUX_BIG_ENDIAN;
278 return clk_register_mux(NULL, name,
279 parent_names, parent_count, clkflags,
280 reg, pos, len, muxflags, &clklock);
281}
282
283
284
285
286static inline int get_bit_field(uint32_t __iomem *reg, uint8_t pos, uint8_t len)
287{
288 uint32_t val;
289
290 val = in_be32(reg);
291 val >>= pos;
292 val &= (1 << len) - 1;
293 return val;
294}
295
296
297static int get_spmf_mult(void)
298{
299 static int spmf_to_mult[] = {
300 68, 1, 12, 16, 20, 24, 28, 32,
301 36, 40, 44, 48, 52, 56, 60, 64,
302 };
303 int spmf;
304
305 spmf = get_bit_field(&clkregs->spmr, 24, 4);
306 return spmf_to_mult[spmf];
307}
308
309
310
311
312
313
314
315static int get_sys_div_x2(void)
316{
317 static int sysdiv_code_to_x2[] = {
318 4, 5, 6, 7, 8, 9, 10, 14,
319 12, 16, 18, 22, 20, 24, 26, 30,
320 28, 32, 34, 38, 36, 40, 42, 46,
321 44, 48, 50, 54, 52, 56, 58, 62,
322 60, 64, 66,
323 };
324 int divcode;
325
326 divcode = get_bit_field(&clkregs->scfr2, 26, 6);
327 return sysdiv_code_to_x2[divcode];
328}
329
330
331
332
333
334
335
336static int get_cpmf_mult_x2(void)
337{
338 static int cpmf_to_mult_x36[] = {
339
340 72, 2, 2, 3, 4, 5, 6, 7,
341 };
342 static int cpmf_to_mult_0by[] = {
343
344 2, 2, 2, 3, 4, 5, 6, 7,
345 };
346
347 int *cpmf_to_mult;
348 int cpmf;
349
350 cpmf = get_bit_field(&clkregs->spmr, 16, 4);
351 if (soc_has_cpmf_0_bypass())
352 cpmf_to_mult = cpmf_to_mult_0by;
353 else
354 cpmf_to_mult = cpmf_to_mult_x36;
355 return cpmf_to_mult[cpmf];
356}
357
358
359
360
361
362
363
364
365static const struct clk_div_table divtab_2346[] = {
366 { .val = 2, .div = 2, },
367 { .val = 3, .div = 3, },
368 { .val = 4, .div = 4, },
369 { .val = 6, .div = 6, },
370 { .div = 0, },
371};
372
373
374static const struct clk_div_table divtab_1234[] = {
375 { .val = 1, .div = 1, },
376 { .val = 2, .div = 2, },
377 { .val = 3, .div = 3, },
378 { .val = 4, .div = 4, },
379 { .div = 0, },
380};
381
382static int get_freq_from_dt(char *propname)
383{
384 struct device_node *np;
385 const unsigned int *prop;
386 int val;
387
388 val = 0;
389 np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-immr");
390 if (np) {
391 prop = of_get_property(np, propname, NULL);
392 if (prop)
393 val = *prop;
394 of_node_put(np);
395 }
396 return val;
397}
398
399static void mpc512x_clk_preset_data(void)
400{
401 size_t i;
402
403 for (i = 0; i < ARRAY_SIZE(clks); i++)
404 clks[i] = ERR_PTR(-ENODEV);
405}
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421static void mpc512x_clk_setup_ref_clock(struct device_node *np, int bus_freq,
422 int *sys_mul, int *sys_div,
423 int *ips_div)
424{
425 struct clk *osc_clk;
426 int calc_freq;
427
428
429 *sys_mul = get_spmf_mult();
430 *sys_mul *= 2;
431 *sys_div = get_sys_div_x2();
432 *ips_div = get_bit_field(&clkregs->scfr1, 23, 3);
433
434
435 osc_clk = of_clk_get_by_name(np, "osc");
436
437
438
439
440
441
442
443
444
445 if (!IS_ERR(osc_clk)) {
446 clks[MPC512x_CLK_REF] = mpc512x_clk_factor("ref", "osc", 1, 1);
447 calc_freq = clk_get_rate(clks[MPC512x_CLK_REF]);
448 calc_freq *= *sys_mul;
449 calc_freq /= *sys_div;
450 calc_freq /= 2;
451 calc_freq /= *ips_div;
452 if (bus_freq && calc_freq != bus_freq)
453 pr_warn("calc rate %d != OF spec %d\n",
454 calc_freq, bus_freq);
455 } else {
456 calc_freq = bus_freq;
457 calc_freq *= *ips_div;
458 calc_freq *= 2;
459 calc_freq *= *sys_div;
460 calc_freq /= *sys_mul;
461 clks[MPC512x_CLK_REF] = mpc512x_clk_fixed("ref", calc_freq);
462 }
463}
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500static const char *parent_names_mux0_spdif[] = {
501 "sys", "ref", "psc-mclk-in", "spdif-tx",
502};
503
504static const char *parent_names_mux0_canin[] = {
505 "sys", "ref", "psc-mclk-in", "can-clk-in",
506};
507
508enum mclk_type {
509 MCLK_TYPE_PSC,
510 MCLK_TYPE_MSCAN,
511 MCLK_TYPE_SPDIF,
512 MCLK_TYPE_OUTCLK,
513};
514
515struct mclk_setup_data {
516 enum mclk_type type;
517 bool has_mclk1;
518 const char *name_mux0;
519 const char *name_en0;
520 const char *name_div0;
521 const char *parent_names_mux1[2];
522 const char *name_mclk;
523};
524
525#define MCLK_SETUP_DATA_PSC(id) { \
526 MCLK_TYPE_PSC, 0, \
527 "psc" #id "-mux0", \
528 "psc" #id "-en0", \
529 "psc" #id "_mclk_div", \
530 { "psc" #id "_mclk_div", "dummy", }, \
531 "psc" #id "_mclk", \
532}
533
534#define MCLK_SETUP_DATA_MSCAN(id) { \
535 MCLK_TYPE_MSCAN, 0, \
536 "mscan" #id "-mux0", \
537 "mscan" #id "-en0", \
538 "mscan" #id "_mclk_div", \
539 { "mscan" #id "_mclk_div", "dummy", }, \
540 "mscan" #id "_mclk", \
541}
542
543#define MCLK_SETUP_DATA_SPDIF { \
544 MCLK_TYPE_SPDIF, 1, \
545 "spdif-mux0", \
546 "spdif-en0", \
547 "spdif_mclk_div", \
548 { "spdif_mclk_div", "spdif-rx", }, \
549 "spdif_mclk", \
550}
551
552#define MCLK_SETUP_DATA_OUTCLK(id) { \
553 MCLK_TYPE_OUTCLK, 0, \
554 "out" #id "-mux0", \
555 "out" #id "-en0", \
556 "out" #id "_mclk_div", \
557 { "out" #id "_mclk_div", "dummy", }, \
558 "out" #id "_clk", \
559}
560
561static struct mclk_setup_data mclk_psc_data[] = {
562 MCLK_SETUP_DATA_PSC(0),
563 MCLK_SETUP_DATA_PSC(1),
564 MCLK_SETUP_DATA_PSC(2),
565 MCLK_SETUP_DATA_PSC(3),
566 MCLK_SETUP_DATA_PSC(4),
567 MCLK_SETUP_DATA_PSC(5),
568 MCLK_SETUP_DATA_PSC(6),
569 MCLK_SETUP_DATA_PSC(7),
570 MCLK_SETUP_DATA_PSC(8),
571 MCLK_SETUP_DATA_PSC(9),
572 MCLK_SETUP_DATA_PSC(10),
573 MCLK_SETUP_DATA_PSC(11),
574};
575
576static struct mclk_setup_data mclk_mscan_data[] = {
577 MCLK_SETUP_DATA_MSCAN(0),
578 MCLK_SETUP_DATA_MSCAN(1),
579 MCLK_SETUP_DATA_MSCAN(2),
580 MCLK_SETUP_DATA_MSCAN(3),
581};
582
583static struct mclk_setup_data mclk_spdif_data[] = {
584 MCLK_SETUP_DATA_SPDIF,
585};
586
587static struct mclk_setup_data mclk_outclk_data[] = {
588 MCLK_SETUP_DATA_OUTCLK(0),
589 MCLK_SETUP_DATA_OUTCLK(1),
590 MCLK_SETUP_DATA_OUTCLK(2),
591 MCLK_SETUP_DATA_OUTCLK(3),
592};
593
594
595static void mpc512x_clk_setup_mclk(struct mclk_setup_data *entry, size_t idx)
596{
597 size_t clks_idx_pub, clks_idx_int;
598 u32 __iomem *mccr_reg;
599 int div;
600
601
602 switch (entry->type) {
603 case MCLK_TYPE_PSC:
604 clks_idx_pub = MPC512x_CLK_PSC0_MCLK + idx;
605 clks_idx_int = MPC512x_CLK_MCLKS_FIRST
606 + (idx) * MCLK_MAX_IDX;
607 mccr_reg = &clkregs->psc_ccr[idx];
608 break;
609 case MCLK_TYPE_MSCAN:
610 clks_idx_pub = MPC512x_CLK_MSCAN0_MCLK + idx;
611 clks_idx_int = MPC512x_CLK_MCLKS_FIRST
612 + (NR_PSCS + idx) * MCLK_MAX_IDX;
613 mccr_reg = &clkregs->mscan_ccr[idx];
614 break;
615 case MCLK_TYPE_SPDIF:
616 clks_idx_pub = MPC512x_CLK_SPDIF_MCLK;
617 clks_idx_int = MPC512x_CLK_MCLKS_FIRST
618 + (NR_PSCS + NR_MSCANS) * MCLK_MAX_IDX;
619 mccr_reg = &clkregs->spccr;
620 break;
621 case MCLK_TYPE_OUTCLK:
622 clks_idx_pub = MPC512x_CLK_OUT0_CLK + idx;
623 clks_idx_int = MPC512x_CLK_MCLKS_FIRST
624 + (NR_PSCS + NR_MSCANS + NR_SPDIFS + idx)
625 * MCLK_MAX_IDX;
626 mccr_reg = &clkregs->out_ccr[idx];
627 break;
628 default:
629 return;
630 }
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650 div = clk_get_rate(clks[MPC512x_CLK_SYS]);
651 div /= clk_get_rate(clks[MPC512x_CLK_IPS]);
652 out_be32(mccr_reg, (0 << 16));
653 out_be32(mccr_reg, (0 << 16) | ((div - 1) << 17));
654 out_be32(mccr_reg, (1 << 16) | ((div - 1) << 17));
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674 clks[clks_idx_int + MCLK_IDX_MUX0] = mpc512x_clk_muxed(
675 entry->name_mux0,
676 soc_has_mclk_mux0_canin()
677 ? &parent_names_mux0_canin[0]
678 : &parent_names_mux0_spdif[0],
679 ARRAY_SIZE(parent_names_mux0_spdif),
680 mccr_reg, 14, 2);
681 clks[clks_idx_int + MCLK_IDX_EN0] = mpc512x_clk_gated(
682 entry->name_en0, entry->name_mux0,
683 mccr_reg, 16);
684 clks[clks_idx_int + MCLK_IDX_DIV0] = mpc512x_clk_divider(
685 entry->name_div0,
686 entry->name_en0, CLK_SET_RATE_GATE,
687 mccr_reg, 17, 15, 0);
688 if (entry->has_mclk1) {
689 clks[clks_idx_pub] = mpc512x_clk_muxed(
690 entry->name_mclk,
691 &entry->parent_names_mux1[0],
692 ARRAY_SIZE(entry->parent_names_mux1),
693 mccr_reg, 7, 1);
694 } else {
695 clks[clks_idx_pub] = mpc512x_clk_factor(
696 entry->name_mclk,
697 entry->parent_names_mux1[0],
698 1, 1);
699 }
700}
701
702
703
704static void mpc512x_clk_setup_clock_tree(struct device_node *np, int busfreq)
705{
706 int sys_mul, sys_div, ips_div;
707 int mul, div;
708 size_t mclk_idx;
709 int freq;
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732 mpc512x_clk_setup_ref_clock(np, busfreq, &sys_mul, &sys_div, &ips_div);
733
734
735 clks[MPC512x_CLK_SYS] = mpc512x_clk_factor("sys", "ref",
736 sys_mul, sys_div);
737 clks[MPC512x_CLK_CSB] = mpc512x_clk_factor("csb", "sys", 1, 2);
738 clks[MPC512x_CLK_IPS] = mpc512x_clk_divtable("ips", "csb",
739 &clkregs->scfr1, 23, 3,
740 divtab_2346);
741
742
743 clks[MPC512x_CLK_DDR_UG] = mpc512x_clk_factor("ddr-ug", "sys", 1, 2);
744
745
746
747
748
749
750
751
752
753
754
755
756 clks[MPC512x_CLK_SDHC_x4] = mpc512x_clk_factor("sdhc-x4", "csb", 2, 1);
757 clks[MPC512x_CLK_SDHC_UG] = mpc512x_clk_divider("sdhc-ug", "sdhc-x4", 0,
758 &clkregs->scfr2, 1, 7,
759 CLK_DIVIDER_ONE_BASED);
760 if (soc_has_sdhc2()) {
761 clks[MPC512x_CLK_SDHC2_UG] = mpc512x_clk_divider(
762 "sdhc2-ug", "sdhc-x4", 0, &clkregs->scfr2,
763 9, 7, CLK_DIVIDER_ONE_BASED);
764 }
765
766 clks[MPC512x_CLK_DIU_x4] = mpc512x_clk_factor("diu-x4", "csb", 4, 1);
767 clks[MPC512x_CLK_DIU_UG] = mpc512x_clk_divider("diu-ug", "diu-x4", 0,
768 &clkregs->scfr1, 0, 8,
769 CLK_DIVIDER_ONE_BASED);
770
771
772
773
774
775
776
777
778 mul = get_cpmf_mult_x2();
779 div = 2;
780 clks[MPC512x_CLK_E300] = mpc512x_clk_factor("e300", "csb", mul, div);
781
782 if (soc_has_mbx()) {
783 clks[MPC512x_CLK_MBX_BUS_UG] = mpc512x_clk_factor(
784 "mbx-bus-ug", "csb", 1, 2);
785 clks[MPC512x_CLK_MBX_UG] = mpc512x_clk_divtable(
786 "mbx-ug", "mbx-bus-ug", &clkregs->scfr1,
787 14, 3, divtab_1234);
788 clks[MPC512x_CLK_MBX_3D_UG] = mpc512x_clk_factor(
789 "mbx-3d-ug", "mbx-ug", 1, 1);
790 }
791 if (soc_has_pci()) {
792 clks[MPC512x_CLK_PCI_UG] = mpc512x_clk_divtable(
793 "pci-ug", "csb", &clkregs->scfr1,
794 20, 3, divtab_2346);
795 }
796 if (soc_has_nfc_5125()) {
797
798
799
800
801
802 clks[MPC512x_CLK_NFC_UG] = ERR_PTR(-ENOTSUPP);
803 } else {
804 clks[MPC512x_CLK_NFC_UG] = mpc512x_clk_divtable(
805 "nfc-ug", "ips", &clkregs->scfr1,
806 8, 3, divtab_1234);
807 }
808 clks[MPC512x_CLK_LPC_UG] = mpc512x_clk_divtable("lpc-ug", "ips",
809 &clkregs->scfr1, 11, 3,
810 divtab_1234);
811
812 clks[MPC512x_CLK_LPC] = mpc512x_clk_gated("lpc", "lpc-ug",
813 &clkregs->sccr1, 30);
814 clks[MPC512x_CLK_NFC] = mpc512x_clk_gated("nfc", "nfc-ug",
815 &clkregs->sccr1, 29);
816 if (soc_has_pata()) {
817 clks[MPC512x_CLK_PATA] = mpc512x_clk_gated(
818 "pata", "ips", &clkregs->sccr1, 28);
819 }
820
821 for (mclk_idx = 0; mclk_idx < soc_max_pscnum(); mclk_idx++) {
822 char name[12];
823 snprintf(name, sizeof(name), "psc%d", mclk_idx);
824 clks[MPC512x_CLK_PSC0 + mclk_idx] = mpc512x_clk_gated(
825 name, "ips", &clkregs->sccr1, 27 - mclk_idx);
826 mpc512x_clk_setup_mclk(&mclk_psc_data[mclk_idx], mclk_idx);
827 }
828 clks[MPC512x_CLK_PSC_FIFO] = mpc512x_clk_gated("psc-fifo", "ips",
829 &clkregs->sccr1, 15);
830 if (soc_has_sata()) {
831 clks[MPC512x_CLK_SATA] = mpc512x_clk_gated(
832 "sata", "ips", &clkregs->sccr1, 14);
833 }
834 clks[MPC512x_CLK_FEC] = mpc512x_clk_gated("fec", "ips",
835 &clkregs->sccr1, 13);
836 if (soc_has_pci()) {
837 clks[MPC512x_CLK_PCI] = mpc512x_clk_gated(
838 "pci", "pci-ug", &clkregs->sccr1, 11);
839 }
840 clks[MPC512x_CLK_DDR] = mpc512x_clk_gated("ddr", "ddr-ug",
841 &clkregs->sccr1, 10);
842 if (soc_has_fec2()) {
843 clks[MPC512x_CLK_FEC2] = mpc512x_clk_gated(
844 "fec2", "ips", &clkregs->sccr1, 9);
845 }
846
847 clks[MPC512x_CLK_DIU] = mpc512x_clk_gated("diu", "diu-ug",
848 &clkregs->sccr2, 31);
849 if (soc_has_axe()) {
850 clks[MPC512x_CLK_AXE] = mpc512x_clk_gated(
851 "axe", "csb", &clkregs->sccr2, 30);
852 }
853 clks[MPC512x_CLK_MEM] = mpc512x_clk_gated("mem", "ips",
854 &clkregs->sccr2, 29);
855 clks[MPC512x_CLK_USB1] = mpc512x_clk_gated("usb1", "csb",
856 &clkregs->sccr2, 28);
857 clks[MPC512x_CLK_USB2] = mpc512x_clk_gated("usb2", "csb",
858 &clkregs->sccr2, 27);
859 clks[MPC512x_CLK_I2C] = mpc512x_clk_gated("i2c", "ips",
860 &clkregs->sccr2, 26);
861
862 clks[MPC512x_CLK_BDLC] = mpc512x_clk_gated("bdlc", "ips",
863 &clkregs->sccr2, 25);
864 for (mclk_idx = 0; mclk_idx < ARRAY_SIZE(mclk_mscan_data); mclk_idx++)
865 mpc512x_clk_setup_mclk(&mclk_mscan_data[mclk_idx], mclk_idx);
866 clks[MPC512x_CLK_SDHC] = mpc512x_clk_gated("sdhc", "sdhc-ug",
867 &clkregs->sccr2, 24);
868
869 if (soc_has_spdif()) {
870 clks[MPC512x_CLK_SPDIF] = mpc512x_clk_gated(
871 "spdif", "ips", &clkregs->sccr2, 23);
872 mpc512x_clk_setup_mclk(&mclk_spdif_data[0], 0);
873 }
874 if (soc_has_mbx()) {
875 clks[MPC512x_CLK_MBX_BUS] = mpc512x_clk_gated(
876 "mbx-bus", "mbx-bus-ug", &clkregs->sccr2, 22);
877 clks[MPC512x_CLK_MBX] = mpc512x_clk_gated(
878 "mbx", "mbx-ug", &clkregs->sccr2, 21);
879 clks[MPC512x_CLK_MBX_3D] = mpc512x_clk_gated(
880 "mbx-3d", "mbx-3d-ug", &clkregs->sccr2, 20);
881 }
882 clks[MPC512x_CLK_IIM] = mpc512x_clk_gated("iim", "csb",
883 &clkregs->sccr2, 19);
884 if (soc_has_viu()) {
885 clks[MPC512x_CLK_VIU] = mpc512x_clk_gated(
886 "viu", "csb", &clkregs->sccr2, 18);
887 }
888 if (soc_has_sdhc2()) {
889 clks[MPC512x_CLK_SDHC2] = mpc512x_clk_gated(
890 "sdhc-2", "sdhc2-ug", &clkregs->sccr2, 17);
891 }
892
893 if (soc_has_outclk()) {
894 size_t idx;
895 for (idx = 0; idx < ARRAY_SIZE(mclk_outclk_data); idx++)
896 mpc512x_clk_setup_mclk(&mclk_outclk_data[idx], idx);
897 }
898
899
900
901
902
903 freq = get_freq_from_dt("psc_mclk_in");
904 if (!freq)
905 freq = 25000000;
906 clks[MPC512x_CLK_PSC_MCLK_IN] = mpc512x_clk_fixed("psc_mclk_in", freq);
907 if (soc_has_mclk_mux0_canin()) {
908 freq = get_freq_from_dt("can_clk_in");
909 clks[MPC512x_CLK_CAN_CLK_IN] = mpc512x_clk_fixed(
910 "can_clk_in", freq);
911 } else {
912 freq = get_freq_from_dt("spdif_tx_in");
913 clks[MPC512x_CLK_SPDIF_TX_IN] = mpc512x_clk_fixed(
914 "spdif_tx_in", freq);
915 freq = get_freq_from_dt("spdif_rx_in");
916 clks[MPC512x_CLK_SPDIF_TX_IN] = mpc512x_clk_fixed(
917 "spdif_rx_in", freq);
918 }
919
920
921 clks[MPC512x_CLK_AC97] = mpc512x_clk_fixed("ac97", 24567000);
922
923
924
925
926
927
928 clk_prepare_enable(clks[MPC512x_CLK_DUMMY]);
929 clk_prepare_enable(clks[MPC512x_CLK_E300]);
930 clk_prepare_enable(clks[MPC512x_CLK_DDR]);
931 clk_prepare_enable(clks[MPC512x_CLK_MEM]);
932 clk_prepare_enable(clks[MPC512x_CLK_IPS]);
933 clk_prepare_enable(clks[MPC512x_CLK_LPC]);
934}
935
936
937
938
939
940static void mpc5121_clk_register_of_provider(struct device_node *np)
941{
942 clk_data.clks = clks;
943 clk_data.clk_num = MPC512x_CLK_LAST_PUBLIC + 1;
944 of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
945}
946
947
948
949
950
951static void mpc5121_clk_provide_migration_support(void)
952{
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972 clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);
973 if (of_find_compatible_node(NULL, "pci", "fsl,mpc5121-pci"))
974 clk_prepare_enable(clks[MPC512x_CLK_PCI]);
975}
976
977
978
979
980
981
982#define FOR_NODES(compatname) \
983 for_each_compatible_node(np, NULL, compatname)
984
985#define NODE_PREP do { \
986 of_address_to_resource(np, 0, &res); \
987 snprintf(devname, sizeof(devname), "%08x.%s", res.start, np->name); \
988} while (0)
989
990#define NODE_CHK(clkname, clkitem, regnode, regflag) do { \
991 struct clk *clk; \
992 clk = of_clk_get_by_name(np, clkname); \
993 if (IS_ERR(clk)) { \
994 clk = clkitem; \
995 clk_register_clkdev(clk, clkname, devname); \
996 if (regnode) \
997 clk_register_clkdev(clk, clkname, np->name); \
998 did_register |= DID_REG_ ## regflag; \
999 pr_debug("clock alias name '%s' for dev '%s' pointer %p\n", \
1000 clkname, devname, clk); \
1001 } else { \
1002 clk_put(clk); \
1003 } \
1004} while (0)
1005
1006
1007
1008
1009
1010
1011
1012static void mpc5121_clk_provide_backwards_compat(void)
1013{
1014 enum did_reg_flags {
1015 DID_REG_PSC = BIT(0),
1016 DID_REG_PSCFIFO = BIT(1),
1017 DID_REG_NFC = BIT(2),
1018 DID_REG_CAN = BIT(3),
1019 DID_REG_I2C = BIT(4),
1020 DID_REG_DIU = BIT(5),
1021 DID_REG_VIU = BIT(6),
1022 DID_REG_FEC = BIT(7),
1023 DID_REG_USB = BIT(8),
1024 DID_REG_PATA = BIT(9),
1025 };
1026
1027 int did_register;
1028 struct device_node *np;
1029 struct resource res;
1030 int idx;
1031 char devname[32];
1032
1033 did_register = 0;
1034
1035 FOR_NODES(mpc512x_select_psc_compat()) {
1036 NODE_PREP;
1037 idx = (res.start >> 8) & 0xf;
1038 NODE_CHK("ipg", clks[MPC512x_CLK_PSC0 + idx], 0, PSC);
1039 NODE_CHK("mclk", clks[MPC512x_CLK_PSC0_MCLK + idx], 0, PSC);
1040 }
1041
1042 FOR_NODES("fsl,mpc5121-psc-fifo") {
1043 NODE_PREP;
1044 NODE_CHK("ipg", clks[MPC512x_CLK_PSC_FIFO], 1, PSCFIFO);
1045 }
1046
1047 FOR_NODES("fsl,mpc5121-nfc") {
1048 NODE_PREP;
1049 NODE_CHK("ipg", clks[MPC512x_CLK_NFC], 0, NFC);
1050 }
1051
1052 FOR_NODES("fsl,mpc5121-mscan") {
1053 NODE_PREP;
1054 idx = 0;
1055 idx += (res.start & 0x2000) ? 2 : 0;
1056 idx += (res.start & 0x0080) ? 1 : 0;
1057 NODE_CHK("ipg", clks[MPC512x_CLK_BDLC], 0, CAN);
1058 NODE_CHK("mclk", clks[MPC512x_CLK_MSCAN0_MCLK + idx], 0, CAN);
1059 }
1060
1061
1062
1063
1064
1065
1066 if (did_register & DID_REG_CAN) {
1067 clk_register_clkdev(clks[MPC512x_CLK_IPS], "ips", NULL);
1068 clk_register_clkdev(clks[MPC512x_CLK_SYS], "sys", NULL);
1069 clk_register_clkdev(clks[MPC512x_CLK_REF], "ref", NULL);
1070 }
1071
1072 FOR_NODES("fsl,mpc5121-i2c") {
1073 NODE_PREP;
1074 NODE_CHK("ipg", clks[MPC512x_CLK_I2C], 0, I2C);
1075 }
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092 if (did_register & DID_REG_I2C)
1093 clk_prepare_enable(clks[MPC512x_CLK_I2C]);
1094
1095 FOR_NODES("fsl,mpc5121-diu") {
1096 NODE_PREP;
1097 NODE_CHK("ipg", clks[MPC512x_CLK_DIU], 1, DIU);
1098 }
1099
1100 FOR_NODES("fsl,mpc5121-viu") {
1101 NODE_PREP;
1102 NODE_CHK("ipg", clks[MPC512x_CLK_VIU], 0, VIU);
1103 }
1104
1105
1106
1107
1108
1109
1110
1111
1112 FOR_NODES("fsl,mpc5121-fec") {
1113 NODE_PREP;
1114 NODE_CHK("per", clks[MPC512x_CLK_FEC], 0, FEC);
1115 }
1116 FOR_NODES("fsl,mpc5121-fec-mdio") {
1117 NODE_PREP;
1118 NODE_CHK("per", clks[MPC512x_CLK_FEC], 0, FEC);
1119 }
1120
1121
1122
1123
1124
1125
1126 FOR_NODES("fsl,mpc5125-fec") {
1127 NODE_PREP;
1128 if (res.start & 0x4000)
1129 idx = MPC512x_CLK_FEC2;
1130 else
1131 idx = MPC512x_CLK_FEC;
1132 NODE_CHK("per", clks[idx], 0, FEC);
1133 }
1134
1135 FOR_NODES("fsl,mpc5121-usb2-dr") {
1136 NODE_PREP;
1137 idx = (res.start & 0x4000) ? 1 : 0;
1138 NODE_CHK("ipg", clks[MPC512x_CLK_USB1 + idx], 0, USB);
1139 }
1140
1141 FOR_NODES("fsl,mpc5121-pata") {
1142 NODE_PREP;
1143 NODE_CHK("ipg", clks[MPC512x_CLK_PATA], 0, PATA);
1144 }
1145
1146
1147
1148
1149
1150
1151
1152
1153 if (did_register) {
1154 pr_notice("device tree lacks clock specs, adding fallbacks (0x%x,%s%s%s%s%s%s%s%s%s%s)\n",
1155 did_register,
1156 (did_register & DID_REG_PSC) ? " PSC" : "",
1157 (did_register & DID_REG_PSCFIFO) ? " PSCFIFO" : "",
1158 (did_register & DID_REG_NFC) ? " NFC" : "",
1159 (did_register & DID_REG_CAN) ? " CAN" : "",
1160 (did_register & DID_REG_I2C) ? " I2C" : "",
1161 (did_register & DID_REG_DIU) ? " DIU" : "",
1162 (did_register & DID_REG_VIU) ? " VIU" : "",
1163 (did_register & DID_REG_FEC) ? " FEC" : "",
1164 (did_register & DID_REG_USB) ? " USB" : "",
1165 (did_register & DID_REG_PATA) ? " PATA" : "");
1166 } else {
1167 pr_debug("device tree has clock specs, no fallbacks added\n");
1168 }
1169}
1170
1171
1172
1173
1174
1175
1176int __init mpc5121_clk_init(void)
1177{
1178 struct device_node *clk_np;
1179 int busfreq;
1180
1181
1182 clk_np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-clock");
1183 if (!clk_np)
1184 return -ENODEV;
1185 clkregs = of_iomap(clk_np, 0);
1186 WARN_ON(!clkregs);
1187
1188
1189 mpc512x_clk_determine_soc();
1190
1191
1192 mpc512x_clk_preset_data();
1193
1194
1195
1196
1197
1198 clks[MPC512x_CLK_DUMMY] = mpc512x_clk_fixed("dummy", 0);
1199
1200
1201
1202
1203
1204
1205 busfreq = get_freq_from_dt("bus-frequency");
1206 mpc512x_clk_setup_clock_tree(clk_np, busfreq);
1207
1208
1209 mpc5121_clk_register_of_provider(clk_np);
1210
1211
1212
1213
1214
1215
1216 mpc5121_clk_provide_migration_support();
1217 mpc5121_clk_provide_backwards_compat();
1218
1219 return 0;
1220}
1221