aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms
diff options
context:
space:
mode:
authorGerhard Sittig <gsi@denx.de>2013-12-10 08:11:36 -0500
committerAnatolij Gustschin <agust@denx.de>2014-01-12 12:59:36 -0500
commit319bbe0ef513e33ecf1a3f40099b5b369122afbd (patch)
tree07d7cbef2353a81ec2edefb20d6da56a0e80d342 /arch/powerpc/platforms
parent76922ebb02fb531142285682352ccdd7091a2bfb (diff)
powerpc/512x: clk: support MPC5121/5123/5125 SoC variants
improve the common clock support code for MPC512x - expand the CCM register set declaration with MPC5125 related registers (which reside in the previously "reserved" area) - tell the MPC5121, MPC5123, and MPC5125 SoC variants apart, and derive the availability of components and their clocks from the detected SoC (MBX, AXE, VIU, SPDIF, PATA, SATA, PCI, second FEC, second SDHC, number of PSC components, type of NAND flash controller, interpretation of the CPMF bitfield, PSC/CAN mux0 stage input clocks, output clocks on SoC pins) - add backwards compatibility (allow operation against a device tree which lacks clock related specs) for MPC5125 FECs, too telling SoC variants apart and adjusting the clock tree's generation occurs at runtime, a common generic binary supports all of the chips the MPC5125 approach to the NFC clock (one register with two counters for the high and low periods of the clock) is not implemented, as there are no users and there is no common implementation which supports this kind of clock -- the new implementation would be unused and could not get verified, so it shall wait until there is demand Signed-off-by: Gerhard Sittig <gsi@denx.de> Acked-by: Mike Turquette <mturquette@linaro.org> Signed-off-by: Anatolij Gustschin <agust@denx.de>
Diffstat (limited to 'arch/powerpc/platforms')
-rw-r--r--arch/powerpc/platforms/512x/clock-commonclk.c339
1 files changed, 295 insertions, 44 deletions
diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
index 16569376b259..6eb614a271fb 100644
--- a/arch/powerpc/platforms/512x/clock-commonclk.c
+++ b/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -36,7 +36,8 @@ enum {
36#define NR_PSCS 12 36#define NR_PSCS 12
37#define NR_MSCANS 4 37#define NR_MSCANS 4
38#define NR_SPDIFS 1 38#define NR_SPDIFS 1
39#define NR_MCLKS (NR_PSCS + NR_MSCANS + NR_SPDIFS) 39#define NR_OUTCLK 4
40#define NR_MCLKS (NR_PSCS + NR_MSCANS + NR_SPDIFS + NR_OUTCLK)
40 41
41/* extend the public set of clocks by adding internal slots for management */ 42/* extend the public set of clocks by adding internal slots for management */
42enum { 43enum {
@@ -46,11 +47,11 @@ enum {
46 MPC512x_CLK_DDR, 47 MPC512x_CLK_DDR,
47 MPC512x_CLK_MEM, 48 MPC512x_CLK_MEM,
48 MPC512x_CLK_IIM, 49 MPC512x_CLK_IIM,
49 MPC512x_CLK_SDHC_2,
50 /* intermediates in div+gate combos or fractional dividers */ 50 /* intermediates in div+gate combos or fractional dividers */
51 MPC512x_CLK_DDR_UG, 51 MPC512x_CLK_DDR_UG,
52 MPC512x_CLK_SDHC_x4, 52 MPC512x_CLK_SDHC_x4,
53 MPC512x_CLK_SDHC_UG, 53 MPC512x_CLK_SDHC_UG,
54 MPC512x_CLK_SDHC2_UG,
54 MPC512x_CLK_DIU_x4, 55 MPC512x_CLK_DIU_x4,
55 MPC512x_CLK_DIU_UG, 56 MPC512x_CLK_DIU_UG,
56 MPC512x_CLK_MBX_BUS_UG, 57 MPC512x_CLK_MBX_BUS_UG,
@@ -76,6 +77,144 @@ static struct clk_onecell_data clk_data;
76static struct mpc512x_ccm __iomem *clkregs; 77static struct mpc512x_ccm __iomem *clkregs;
77static DEFINE_SPINLOCK(clklock); 78static DEFINE_SPINLOCK(clklock);
78 79
80/* SoC variants {{{ */
81
82/*
83 * tell SoC variants apart as they are rather similar yet not identical,
84 * cache the result in an enum to not repeatedly run the expensive OF test
85 *
86 * MPC5123 is an MPC5121 without the MBX graphics accelerator
87 *
88 * MPC5125 has many more differences: no MBX, no AXE, no VIU, no SPDIF,
89 * no PATA, no SATA, no PCI, two FECs (of different compatibility name),
90 * only 10 PSCs (of different compatibility name), two SDHCs, different
91 * NFC IP block, output clocks, system PLL status query, different CPMF
92 * interpretation, no CFM, different fourth PSC/CAN mux0 input -- yet
93 * those differences can get folded into this clock provider support
94 * code and don't warrant a separate highly redundant implementation
95 */
96
97static enum soc_type {
98 MPC512x_SOC_MPC5121,
99 MPC512x_SOC_MPC5123,
100 MPC512x_SOC_MPC5125,
101} soc;
102
103static void mpc512x_clk_determine_soc(void)
104{
105 if (of_machine_is_compatible("fsl,mpc5121")) {
106 soc = MPC512x_SOC_MPC5121;
107 return;
108 }
109 if (of_machine_is_compatible("fsl,mpc5123")) {
110 soc = MPC512x_SOC_MPC5123;
111 return;
112 }
113 if (of_machine_is_compatible("fsl,mpc5125")) {
114 soc = MPC512x_SOC_MPC5125;
115 return;
116 }
117}
118
119static bool soc_has_mbx(void)
120{
121 if (soc == MPC512x_SOC_MPC5121)
122 return true;
123 return false;
124}
125
126static bool soc_has_axe(void)
127{
128 if (soc == MPC512x_SOC_MPC5125)
129 return false;
130 return true;
131}
132
133static bool soc_has_viu(void)
134{
135 if (soc == MPC512x_SOC_MPC5125)
136 return false;
137 return true;
138}
139
140static bool soc_has_spdif(void)
141{
142 if (soc == MPC512x_SOC_MPC5125)
143 return false;
144 return true;
145}
146
147static bool soc_has_pata(void)
148{
149 if (soc == MPC512x_SOC_MPC5125)
150 return false;
151 return true;
152}
153
154static bool soc_has_sata(void)
155{
156 if (soc == MPC512x_SOC_MPC5125)
157 return false;
158 return true;
159}
160
161static bool soc_has_pci(void)
162{
163 if (soc == MPC512x_SOC_MPC5125)
164 return false;
165 return true;
166}
167
168static bool soc_has_fec2(void)
169{
170 if (soc == MPC512x_SOC_MPC5125)
171 return true;
172 return false;
173}
174
175static int soc_max_pscnum(void)
176{
177 if (soc == MPC512x_SOC_MPC5125)
178 return 10;
179 return 12;
180}
181
182static bool soc_has_sdhc2(void)
183{
184 if (soc == MPC512x_SOC_MPC5125)
185 return true;
186 return false;
187}
188
189static bool soc_has_nfc_5125(void)
190{
191 if (soc == MPC512x_SOC_MPC5125)
192 return true;
193 return false;
194}
195
196static bool soc_has_outclk(void)
197{
198 if (soc == MPC512x_SOC_MPC5125)
199 return true;
200 return false;
201}
202
203static bool soc_has_cpmf_0_bypass(void)
204{
205 if (soc == MPC512x_SOC_MPC5125)
206 return true;
207 return false;
208}
209
210static bool soc_has_mclk_mux0_canin(void)
211{
212 if (soc == MPC512x_SOC_MPC5125)
213 return true;
214 return false;
215}
216
217/* }}} SoC variants */
79/* common clk API wrappers {{{ */ 218/* common clk API wrappers {{{ */
80 219
81/* convenience wrappers around the common clk API */ 220/* convenience wrappers around the common clk API */
@@ -196,12 +335,23 @@ static int get_sys_div_x2(void)
196 */ 335 */
197static int get_cpmf_mult_x2(void) 336static int get_cpmf_mult_x2(void)
198{ 337{
199 static int cpmf_to_mult[] = { 338 static int cpmf_to_mult_x36[] = {
339 /* 0b000 is "times 36" */
200 72, 2, 2, 3, 4, 5, 6, 7, 340 72, 2, 2, 3, 4, 5, 6, 7,
201 }; 341 };
342 static int cpmf_to_mult_0by[] = {
343 /* 0b000 is "bypass" */
344 2, 2, 2, 3, 4, 5, 6, 7,
345 };
346
347 int *cpmf_to_mult;
202 int cpmf; 348 int cpmf;
203 349
204 cpmf = get_bit_field(&clkregs->spmr, 16, 4); 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;
205 return cpmf_to_mult[cpmf]; 355 return cpmf_to_mult[cpmf];
206} 356}
207 357
@@ -347,14 +497,19 @@ static void mpc512x_clk_setup_ref_clock(struct device_node *np, int bus_freq,
347 * it's the very data type dictated by <linux/clk-provider.h>, 497 * it's the very data type dictated by <linux/clk-provider.h>,
348 * "fixing" this warning will break compilation 498 * "fixing" this warning will break compilation
349 */ 499 */
350static const char *parent_names_mux0[] = { 500static const char *parent_names_mux0_spdif[] = {
351 "sys", "ref", "psc-mclk-in", "spdif-tx", 501 "sys", "ref", "psc-mclk-in", "spdif-tx",
352}; 502};
353 503
504static const char *parent_names_mux0_canin[] = {
505 "sys", "ref", "psc-mclk-in", "can-clk-in",
506};
507
354enum mclk_type { 508enum mclk_type {
355 MCLK_TYPE_PSC, 509 MCLK_TYPE_PSC,
356 MCLK_TYPE_MSCAN, 510 MCLK_TYPE_MSCAN,
357 MCLK_TYPE_SPDIF, 511 MCLK_TYPE_SPDIF,
512 MCLK_TYPE_OUTCLK,
358}; 513};
359 514
360struct mclk_setup_data { 515struct mclk_setup_data {
@@ -394,6 +549,15 @@ struct mclk_setup_data {
394 "spdif_mclk", \ 549 "spdif_mclk", \
395} 550}
396 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
397static struct mclk_setup_data mclk_psc_data[] = { 561static struct mclk_setup_data mclk_psc_data[] = {
398 MCLK_SETUP_DATA_PSC(0), 562 MCLK_SETUP_DATA_PSC(0),
399 MCLK_SETUP_DATA_PSC(1), 563 MCLK_SETUP_DATA_PSC(1),
@@ -420,6 +584,13 @@ static struct mclk_setup_data mclk_spdif_data[] = {
420 MCLK_SETUP_DATA_SPDIF, 584 MCLK_SETUP_DATA_SPDIF,
421}; 585};
422 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
423/* setup the MCLK clock subtree of an individual PSC/MSCAN/SPDIF */ 594/* setup the MCLK clock subtree of an individual PSC/MSCAN/SPDIF */
424static void mpc512x_clk_setup_mclk(struct mclk_setup_data *entry, size_t idx) 595static void mpc512x_clk_setup_mclk(struct mclk_setup_data *entry, size_t idx)
425{ 596{
@@ -447,6 +618,13 @@ static void mpc512x_clk_setup_mclk(struct mclk_setup_data *entry, size_t idx)
447 + (NR_PSCS + NR_MSCANS) * MCLK_MAX_IDX; 618 + (NR_PSCS + NR_MSCANS) * MCLK_MAX_IDX;
448 mccr_reg = &clkregs->spccr; 619 mccr_reg = &clkregs->spccr;
449 break; 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;
450 default: 628 default:
451 return; 629 return;
452 } 630 }
@@ -495,7 +673,10 @@ static void mpc512x_clk_setup_mclk(struct mclk_setup_data *entry, size_t idx)
495 */ 673 */
496 clks[clks_idx_int + MCLK_IDX_MUX0] = mpc512x_clk_muxed( 674 clks[clks_idx_int + MCLK_IDX_MUX0] = mpc512x_clk_muxed(
497 entry->name_mux0, 675 entry->name_mux0,
498 &parent_names_mux0[0], ARRAY_SIZE(parent_names_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),
499 mccr_reg, 14, 2); 680 mccr_reg, 14, 2);
500 clks[clks_idx_int + MCLK_IDX_EN0] = mpc512x_clk_gated( 681 clks[clks_idx_int + MCLK_IDX_EN0] = mpc512x_clk_gated(
501 entry->name_en0, entry->name_mux0, 682 entry->name_en0, entry->name_mux0,
@@ -576,6 +757,12 @@ static void mpc512x_clk_setup_clock_tree(struct device_node *np, int busfreq)
576 clks[MPC512x_CLK_SDHC_UG] = mpc512x_clk_divider("sdhc-ug", "sdhc-x4", 0, 757 clks[MPC512x_CLK_SDHC_UG] = mpc512x_clk_divider("sdhc-ug", "sdhc-x4", 0,
577 &clkregs->scfr2, 1, 7, 758 &clkregs->scfr2, 1, 7,
578 CLK_DIVIDER_ONE_BASED); 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
579 clks[MPC512x_CLK_DIU_x4] = mpc512x_clk_factor("diu-x4", "csb", 4, 1); 766 clks[MPC512x_CLK_DIU_x4] = mpc512x_clk_factor("diu-x4", "csb", 4, 1);
580 clks[MPC512x_CLK_DIU_UG] = mpc512x_clk_divider("diu-ug", "diu-x4", 0, 767 clks[MPC512x_CLK_DIU_UG] = mpc512x_clk_divider("diu-ug", "diu-x4", 0,
581 &clkregs->scfr1, 0, 8, 768 &clkregs->scfr1, 0, 8,
@@ -592,19 +779,32 @@ static void mpc512x_clk_setup_clock_tree(struct device_node *np, int busfreq)
592 div = 2; /* compensate for the fractional factor */ 779 div = 2; /* compensate for the fractional factor */
593 clks[MPC512x_CLK_E300] = mpc512x_clk_factor("e300", "csb", mul, div); 780 clks[MPC512x_CLK_E300] = mpc512x_clk_factor("e300", "csb", mul, div);
594 781
595 clks[MPC512x_CLK_MBX_BUS_UG] = mpc512x_clk_factor("mbx-bus-ug", "csb", 782 if (soc_has_mbx()) {
596 1, 2); 783 clks[MPC512x_CLK_MBX_BUS_UG] = mpc512x_clk_factor(
597 clks[MPC512x_CLK_MBX_UG] = mpc512x_clk_divtable("mbx-ug", "mbx-bus-ug", 784 "mbx-bus-ug", "csb", 1, 2);
598 &clkregs->scfr1, 14, 3, 785 clks[MPC512x_CLK_MBX_UG] = mpc512x_clk_divtable(
599 divtab_1234); 786 "mbx-ug", "mbx-bus-ug", &clkregs->scfr1,
600 clks[MPC512x_CLK_MBX_3D_UG] = mpc512x_clk_factor("mbx-3d-ug", "mbx-ug", 787 14, 3, divtab_1234);
601 1, 1); 788 clks[MPC512x_CLK_MBX_3D_UG] = mpc512x_clk_factor(
602 clks[MPC512x_CLK_PCI_UG] = mpc512x_clk_divtable("pci-ug", "csb", 789 "mbx-3d-ug", "mbx-ug", 1, 1);
603 &clkregs->scfr1, 20, 3, 790 }
604 divtab_2346); 791 if (soc_has_pci()) {
605 clks[MPC512x_CLK_NFC_UG] = mpc512x_clk_divtable("nfc-ug", "ips", 792 clks[MPC512x_CLK_PCI_UG] = mpc512x_clk_divtable(
606 &clkregs->scfr1, 8, 3, 793 "pci-ug", "csb", &clkregs->scfr1,
607 divtab_1234); 794 20, 3, divtab_2346);
795 }
796 if (soc_has_nfc_5125()) {
797 /*
798 * XXX TODO implement 5125 NFC clock setup logic,
799 * with high/low period counters in clkregs->scfr3,
800 * currently there are no users so it's ENOIMPL
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 }
608 clks[MPC512x_CLK_LPC_UG] = mpc512x_clk_divtable("lpc-ug", "ips", 808 clks[MPC512x_CLK_LPC_UG] = mpc512x_clk_divtable("lpc-ug", "ips",
609 &clkregs->scfr1, 11, 3, 809 &clkregs->scfr1, 11, 3,
610 divtab_1234); 810 divtab_1234);
@@ -613,10 +813,12 @@ static void mpc512x_clk_setup_clock_tree(struct device_node *np, int busfreq)
613 &clkregs->sccr1, 30); 813 &clkregs->sccr1, 30);
614 clks[MPC512x_CLK_NFC] = mpc512x_clk_gated("nfc", "nfc-ug", 814 clks[MPC512x_CLK_NFC] = mpc512x_clk_gated("nfc", "nfc-ug",
615 &clkregs->sccr1, 29); 815 &clkregs->sccr1, 29);
616 clks[MPC512x_CLK_PATA] = mpc512x_clk_gated("pata", "ips", 816 if (soc_has_pata()) {
617 &clkregs->sccr1, 28); 817 clks[MPC512x_CLK_PATA] = mpc512x_clk_gated(
818 "pata", "ips", &clkregs->sccr1, 28);
819 }
618 /* for PSCs there is a "registers" gate and a bitrate MCLK subtree */ 820 /* for PSCs there is a "registers" gate and a bitrate MCLK subtree */
619 for (mclk_idx = 0; mclk_idx < ARRAY_SIZE(mclk_psc_data); mclk_idx++) { 821 for (mclk_idx = 0; mclk_idx < soc_max_pscnum(); mclk_idx++) {
620 char name[12]; 822 char name[12];
621 snprintf(name, sizeof(name), "psc%d", mclk_idx); 823 snprintf(name, sizeof(name), "psc%d", mclk_idx);
622 clks[MPC512x_CLK_PSC0 + mclk_idx] = mpc512x_clk_gated( 824 clks[MPC512x_CLK_PSC0 + mclk_idx] = mpc512x_clk_gated(
@@ -625,19 +827,29 @@ static void mpc512x_clk_setup_clock_tree(struct device_node *np, int busfreq)
625 } 827 }
626 clks[MPC512x_CLK_PSC_FIFO] = mpc512x_clk_gated("psc-fifo", "ips", 828 clks[MPC512x_CLK_PSC_FIFO] = mpc512x_clk_gated("psc-fifo", "ips",
627 &clkregs->sccr1, 15); 829 &clkregs->sccr1, 15);
628 clks[MPC512x_CLK_SATA] = mpc512x_clk_gated("sata", "ips", 830 if (soc_has_sata()) {
629 &clkregs->sccr1, 14); 831 clks[MPC512x_CLK_SATA] = mpc512x_clk_gated(
832 "sata", "ips", &clkregs->sccr1, 14);
833 }
630 clks[MPC512x_CLK_FEC] = mpc512x_clk_gated("fec", "ips", 834 clks[MPC512x_CLK_FEC] = mpc512x_clk_gated("fec", "ips",
631 &clkregs->sccr1, 13); 835 &clkregs->sccr1, 13);
632 clks[MPC512x_CLK_PCI] = mpc512x_clk_gated("pci", "pci-ug", 836 if (soc_has_pci()) {
633 &clkregs->sccr1, 11); 837 clks[MPC512x_CLK_PCI] = mpc512x_clk_gated(
838 "pci", "pci-ug", &clkregs->sccr1, 11);
839 }
634 clks[MPC512x_CLK_DDR] = mpc512x_clk_gated("ddr", "ddr-ug", 840 clks[MPC512x_CLK_DDR] = mpc512x_clk_gated("ddr", "ddr-ug",
635 &clkregs->sccr1, 10); 841 &clkregs->sccr1, 10);
842 if (soc_has_fec2()) {
843 clks[MPC512x_CLK_FEC2] = mpc512x_clk_gated(
844 "fec2", "ips", &clkregs->sccr1, 9);
845 }
636 846
637 clks[MPC512x_CLK_DIU] = mpc512x_clk_gated("diu", "diu-ug", 847 clks[MPC512x_CLK_DIU] = mpc512x_clk_gated("diu", "diu-ug",
638 &clkregs->sccr2, 31); 848 &clkregs->sccr2, 31);
639 clks[MPC512x_CLK_AXE] = mpc512x_clk_gated("axe", "csb", 849 if (soc_has_axe()) {
640 &clkregs->sccr2, 30); 850 clks[MPC512x_CLK_AXE] = mpc512x_clk_gated(
851 "axe", "csb", &clkregs->sccr2, 30);
852 }
641 clks[MPC512x_CLK_MEM] = mpc512x_clk_gated("mem", "ips", 853 clks[MPC512x_CLK_MEM] = mpc512x_clk_gated("mem", "ips",
642 &clkregs->sccr2, 29); 854 &clkregs->sccr2, 29);
643 clks[MPC512x_CLK_USB1] = mpc512x_clk_gated("usb1", "csb", 855 clks[MPC512x_CLK_USB1] = mpc512x_clk_gated("usb1", "csb",
@@ -654,21 +866,35 @@ static void mpc512x_clk_setup_clock_tree(struct device_node *np, int busfreq)
654 clks[MPC512x_CLK_SDHC] = mpc512x_clk_gated("sdhc", "sdhc-ug", 866 clks[MPC512x_CLK_SDHC] = mpc512x_clk_gated("sdhc", "sdhc-ug",
655 &clkregs->sccr2, 24); 867 &clkregs->sccr2, 24);
656 /* there is only one SPDIF component, which shares MCLK support code */ 868 /* there is only one SPDIF component, which shares MCLK support code */
657 clks[MPC512x_CLK_SPDIF] = mpc512x_clk_gated("spdif", "ips", 869 if (soc_has_spdif()) {
658 &clkregs->sccr2, 23); 870 clks[MPC512x_CLK_SPDIF] = mpc512x_clk_gated(
659 mpc512x_clk_setup_mclk(&mclk_spdif_data[0], 0); 871 "spdif", "ips", &clkregs->sccr2, 23);
660 clks[MPC512x_CLK_MBX_BUS] = mpc512x_clk_gated("mbx-bus", "mbx-bus-ug", 872 mpc512x_clk_setup_mclk(&mclk_spdif_data[0], 0);
661 &clkregs->sccr2, 22); 873 }
662 clks[MPC512x_CLK_MBX] = mpc512x_clk_gated("mbx", "mbx-ug", 874 if (soc_has_mbx()) {
663 &clkregs->sccr2, 21); 875 clks[MPC512x_CLK_MBX_BUS] = mpc512x_clk_gated(
664 clks[MPC512x_CLK_MBX_3D] = mpc512x_clk_gated("mbx-3d", "mbx-3d-ug", 876 "mbx-bus", "mbx-bus-ug", &clkregs->sccr2, 22);
665 &clkregs->sccr2, 20); 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 }
666 clks[MPC512x_CLK_IIM] = mpc512x_clk_gated("iim", "csb", 882 clks[MPC512x_CLK_IIM] = mpc512x_clk_gated("iim", "csb",
667 &clkregs->sccr2, 19); 883 &clkregs->sccr2, 19);
668 clks[MPC512x_CLK_VIU] = mpc512x_clk_gated("viu", "csb", 884 if (soc_has_viu()) {
669 &clkregs->sccr2, 18); 885 clks[MPC512x_CLK_VIU] = mpc512x_clk_gated(
670 clks[MPC512x_CLK_SDHC_2] = mpc512x_clk_gated("sdhc-2", "sdhc-ug", 886 "viu", "csb", &clkregs->sccr2, 18);
671 &clkregs->sccr2, 17); 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; /* used as mclk_idx, just to trim line length */
895 for (idx = 0; idx < ARRAY_SIZE(mclk_outclk_data); idx++)
896 mpc512x_clk_setup_mclk(&mclk_outclk_data[idx], idx);
897 }
672 898
673 /* 899 /*
674 * externally provided clocks (when implemented in hardware, 900 * externally provided clocks (when implemented in hardware,
@@ -678,10 +904,18 @@ static void mpc512x_clk_setup_clock_tree(struct device_node *np, int busfreq)
678 if (!freq) 904 if (!freq)
679 freq = 25000000; 905 freq = 25000000;
680 clks[MPC512x_CLK_PSC_MCLK_IN] = mpc512x_clk_fixed("psc_mclk_in", freq); 906 clks[MPC512x_CLK_PSC_MCLK_IN] = mpc512x_clk_fixed("psc_mclk_in", freq);
681 freq = get_freq_from_dt("spdif_tx_in"); 907 if (soc_has_mclk_mux0_canin()) {
682 clks[MPC512x_CLK_SPDIF_TX_IN] = mpc512x_clk_fixed("spdif_tx_in", freq); 908 freq = get_freq_from_dt("can_clk_in");
683 freq = get_freq_from_dt("spdif_rx_in"); 909 clks[MPC512x_CLK_CAN_CLK_IN] = mpc512x_clk_fixed(
684 clks[MPC512x_CLK_SPDIF_TX_IN] = mpc512x_clk_fixed("spdif_rx_in", freq); 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 }
685 919
686 /* fixed frequency for AC97, always 24.567MHz */ 920 /* fixed frequency for AC97, always 24.567MHz */
687 clks[MPC512x_CLK_AC97] = mpc512x_clk_fixed("ac97", 24567000); 921 clks[MPC512x_CLK_AC97] = mpc512x_clk_fixed("ac97", 24567000);
@@ -883,6 +1117,20 @@ static void mpc5121_clk_provide_backwards_compat(void)
883 NODE_PREP; 1117 NODE_PREP;
884 NODE_CHK("per", clks[MPC512x_CLK_FEC], 0, FEC); 1118 NODE_CHK("per", clks[MPC512x_CLK_FEC], 0, FEC);
885 } 1119 }
1120 /*
1121 * MPC5125 has two FECs: FEC1 at 0x2800, FEC2 at 0x4800;
1122 * the clock items don't "form an array" since FEC2 was
1123 * added only later and was not allowed to shift all other
1124 * clock item indices, so the numbers aren't adjacent
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 }
886 1134
887 FOR_NODES("fsl,mpc5121-usb2-dr") { 1135 FOR_NODES("fsl,mpc5121-usb2-dr") {
888 NODE_PREP; 1136 NODE_PREP;
@@ -932,6 +1180,9 @@ int __init mpc5121_clk_init(void)
932 clkregs = of_iomap(clk_np, 0); 1180 clkregs = of_iomap(clk_np, 0);
933 WARN_ON(!clkregs); 1181 WARN_ON(!clkregs);
934 1182
1183 /* determine the SoC variant we run on */
1184 mpc512x_clk_determine_soc();
1185
935 /* invalidate all not yet registered clock slots */ 1186 /* invalidate all not yet registered clock slots */
936 mpc512x_clk_preset_data(); 1187 mpc512x_clk_preset_data();
937 1188