1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2014 Marvell Technology Group Ltd.
5 * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
6 * Alexandre Belloni <alexandre.belloni@free-electrons.com>
10 #include <linux/clk-provider.h>
12 #include <linux/kernel.h>
14 #include <linux/of_address.h>
15 #include <linux/slab.h>
17 #include <dt-bindings/clock/berlin2.h>
19 #include "berlin2-avpll.h"
20 #include "berlin2-div.h"
21 #include "berlin2-pll.h"
24 #define REG_PINMUX0 0x0000
25 #define REG_PINMUX1 0x0004
26 #define REG_SYSPLLCTL0 0x0014
27 #define REG_SYSPLLCTL4 0x0024
28 #define REG_MEMPLLCTL0 0x0028
29 #define REG_MEMPLLCTL4 0x0038
30 #define REG_CPUPLLCTL0 0x003c
31 #define REG_CPUPLLCTL4 0x004c
32 #define REG_AVPLLCTL0 0x0050
33 #define REG_AVPLLCTL31 0x00cc
34 #define REG_AVPLLCTL62 0x0148
35 #define REG_PLLSTATUS 0x014c
36 #define REG_CLKENABLE 0x0150
37 #define REG_CLKSELECT0 0x0154
38 #define REG_CLKSELECT1 0x0158
39 #define REG_CLKSELECT2 0x015c
40 #define REG_CLKSELECT3 0x0160
41 #define REG_CLKSWITCH0 0x0164
42 #define REG_CLKSWITCH1 0x0168
43 #define REG_RESET_TRIGGER 0x0178
44 #define REG_RESET_STATUS0 0x017c
45 #define REG_RESET_STATUS1 0x0180
46 #define REG_SW_GENERIC0 0x0184
47 #define REG_SW_GENERIC3 0x0190
48 #define REG_PRODUCTID 0x01cc
49 #define REG_PRODUCTID_EXT 0x01d0
50 #define REG_GFX3DCORE_CLKCTL 0x022c
51 #define REG_GFX3DSYS_CLKCTL 0x0230
52 #define REG_ARC_CLKCTL 0x0234
53 #define REG_VIP_CLKCTL 0x0238
54 #define REG_SDIO0XIN_CLKCTL 0x023c
55 #define REG_SDIO1XIN_CLKCTL 0x0240
56 #define REG_GFX3DEXTRA_CLKCTL 0x0244
57 #define REG_GFX3D_RESET 0x0248
58 #define REG_GC360_CLKCTL 0x024c
59 #define REG_SDIO_DLLMST_CLKCTL 0x0250
62 * BG2/BG2CD SoCs have the following audio/video I/O units:
64 * audiohd: HDMI TX audio
70 * video1: Secondary video
71 * video2: SD auxiliary video
73 * There are no external audio clocks (ACLKI0, ACLKI1) and
74 * only one external video clock (VCLKI0).
76 * Currently missing bits and pieces:
77 * - audio_fast_pll is unknown
78 * - audiohd_pll is unknown
79 * - video0_pll is unknown
80 * - audio[023], audiohd parent pll is assumed to be audio_fast_pll
85 static struct clk_hw_onecell_data
*clk_data
;
86 static DEFINE_SPINLOCK(lock
);
87 static void __iomem
*gbase
;
91 SYSPLL
, MEMPLL
, CPUPLL
,
92 AVPLL_A1
, AVPLL_A2
, AVPLL_A3
, AVPLL_A4
,
93 AVPLL_A5
, AVPLL_A6
, AVPLL_A7
, AVPLL_A8
,
94 AVPLL_B1
, AVPLL_B2
, AVPLL_B3
, AVPLL_B4
,
95 AVPLL_B5
, AVPLL_B6
, AVPLL_B7
, AVPLL_B8
,
96 AUDIO1_PLL
, AUDIO_FAST_PLL
,
97 VIDEO0_PLL
, VIDEO0_IN
,
98 VIDEO1_PLL
, VIDEO1_IN
,
99 VIDEO2_PLL
, VIDEO2_IN
,
102 static const char *clk_names
[] = {
104 [VIDEO_EXT0
] = "video_ext0",
108 [AVPLL_A1
] = "avpll_a1",
109 [AVPLL_A2
] = "avpll_a2",
110 [AVPLL_A3
] = "avpll_a3",
111 [AVPLL_A4
] = "avpll_a4",
112 [AVPLL_A5
] = "avpll_a5",
113 [AVPLL_A6
] = "avpll_a6",
114 [AVPLL_A7
] = "avpll_a7",
115 [AVPLL_A8
] = "avpll_a8",
116 [AVPLL_B1
] = "avpll_b1",
117 [AVPLL_B2
] = "avpll_b2",
118 [AVPLL_B3
] = "avpll_b3",
119 [AVPLL_B4
] = "avpll_b4",
120 [AVPLL_B5
] = "avpll_b5",
121 [AVPLL_B6
] = "avpll_b6",
122 [AVPLL_B7
] = "avpll_b7",
123 [AVPLL_B8
] = "avpll_b8",
124 [AUDIO1_PLL
] = "audio1_pll",
125 [AUDIO_FAST_PLL
] = "audio_fast_pll",
126 [VIDEO0_PLL
] = "video0_pll",
127 [VIDEO0_IN
] = "video0_in",
128 [VIDEO1_PLL
] = "video1_pll",
129 [VIDEO1_IN
] = "video1_in",
130 [VIDEO2_PLL
] = "video2_pll",
131 [VIDEO2_IN
] = "video2_in",
134 static const struct berlin2_pll_map bg2_pll_map __initconst
= {
135 .vcodiv
= {10, 15, 20, 25, 30, 40, 50, 60, 80},
142 static const u8 default_parent_ids
[] = {
143 SYSPLL
, AVPLL_B4
, AVPLL_A5
, AVPLL_B6
, AVPLL_B7
, SYSPLL
146 static const struct berlin2_div_data bg2_divs
[] __initconst
= {
149 .parent_ids
= (const u8
[]){
150 SYSPLL
, AVPLL_B4
, AVPLL_B5
, AVPLL_B6
, AVPLL_B7
, SYSPLL
154 BERLIN2_DIV_GATE(REG_CLKENABLE
, 0),
155 BERLIN2_PLL_SELECT(REG_CLKSELECT0
, 0),
156 BERLIN2_DIV_SELECT(REG_CLKSELECT0
, 3),
157 BERLIN2_PLL_SWITCH(REG_CLKSWITCH0
, 3),
158 BERLIN2_DIV_SWITCH(REG_CLKSWITCH0
, 4),
159 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0
, 5),
161 .div_flags
= BERLIN2_DIV_HAS_GATE
| BERLIN2_DIV_HAS_MUX
,
162 .flags
= CLK_IGNORE_UNUSED
,
166 .parent_ids
= (const u8
[]){
167 CPUPLL
, MEMPLL
, MEMPLL
, MEMPLL
, MEMPLL
171 BERLIN2_PLL_SELECT(REG_CLKSELECT0
, 6),
172 BERLIN2_DIV_SELECT(REG_CLKSELECT0
, 9),
173 BERLIN2_PLL_SWITCH(REG_CLKSWITCH0
, 6),
174 BERLIN2_DIV_SWITCH(REG_CLKSWITCH0
, 7),
175 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0
, 8),
177 .div_flags
= BERLIN2_DIV_HAS_MUX
,
182 .parent_ids
= default_parent_ids
,
183 .num_parents
= ARRAY_SIZE(default_parent_ids
),
185 BERLIN2_DIV_GATE(REG_CLKENABLE
, 16),
186 BERLIN2_PLL_SELECT(REG_CLKSELECT0
, 17),
187 BERLIN2_DIV_SELECT(REG_CLKSELECT0
, 20),
188 BERLIN2_PLL_SWITCH(REG_CLKSWITCH0
, 12),
189 BERLIN2_DIV_SWITCH(REG_CLKSWITCH0
, 13),
190 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0
, 14),
192 .div_flags
= BERLIN2_DIV_HAS_GATE
| BERLIN2_DIV_HAS_MUX
,
197 .parent_ids
= default_parent_ids
,
198 .num_parents
= ARRAY_SIZE(default_parent_ids
),
200 BERLIN2_DIV_GATE(REG_CLKENABLE
, 1),
201 BERLIN2_PLL_SELECT(REG_CLKSELECT0
, 23),
202 BERLIN2_DIV_SELECT(REG_CLKSELECT0
, 26),
203 BERLIN2_PLL_SWITCH(REG_CLKSWITCH0
, 15),
204 BERLIN2_DIV_SWITCH(REG_CLKSWITCH0
, 16),
205 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0
, 17),
207 .div_flags
= BERLIN2_DIV_HAS_GATE
| BERLIN2_DIV_HAS_MUX
,
212 .parent_ids
= default_parent_ids
,
213 .num_parents
= ARRAY_SIZE(default_parent_ids
),
215 BERLIN2_DIV_GATE(REG_CLKENABLE
, 4),
216 BERLIN2_PLL_SELECT(REG_CLKSELECT0
, 29),
217 BERLIN2_DIV_SELECT(REG_CLKSELECT1
, 0),
218 BERLIN2_PLL_SWITCH(REG_CLKSWITCH0
, 18),
219 BERLIN2_DIV_SWITCH(REG_CLKSWITCH0
, 19),
220 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0
, 20),
222 .div_flags
= BERLIN2_DIV_HAS_GATE
| BERLIN2_DIV_HAS_MUX
,
227 .parent_ids
= default_parent_ids
,
228 .num_parents
= ARRAY_SIZE(default_parent_ids
),
230 BERLIN2_DIV_GATE(REG_CLKENABLE
, 5),
231 BERLIN2_PLL_SELECT(REG_CLKSELECT1
, 3),
232 BERLIN2_DIV_SELECT(REG_CLKSELECT1
, 6),
233 BERLIN2_PLL_SWITCH(REG_CLKSWITCH0
, 21),
234 BERLIN2_DIV_SWITCH(REG_CLKSWITCH0
, 22),
235 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0
, 23),
237 .div_flags
= BERLIN2_DIV_HAS_GATE
| BERLIN2_DIV_HAS_MUX
,
242 .parent_ids
= default_parent_ids
,
243 .num_parents
= ARRAY_SIZE(default_parent_ids
),
245 BERLIN2_DIV_GATE(REG_CLKENABLE
, 6),
246 BERLIN2_PLL_SELECT(REG_CLKSELECT1
, 9),
247 BERLIN2_DIV_SELECT(REG_CLKSELECT1
, 12),
248 BERLIN2_PLL_SWITCH(REG_CLKSWITCH0
, 24),
249 BERLIN2_DIV_SWITCH(REG_CLKSWITCH0
, 25),
250 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0
, 26),
252 .div_flags
= BERLIN2_DIV_HAS_GATE
| BERLIN2_DIV_HAS_MUX
,
253 .flags
= CLK_IGNORE_UNUSED
,
257 .parent_ids
= default_parent_ids
,
258 .num_parents
= ARRAY_SIZE(default_parent_ids
),
260 BERLIN2_DIV_GATE(REG_CLKENABLE
, 2),
261 BERLIN2_PLL_SELECT(REG_CLKSELECT1
, 15),
262 BERLIN2_DIV_SELECT(REG_CLKSELECT1
, 18),
263 BERLIN2_PLL_SWITCH(REG_CLKSWITCH0
, 27),
264 BERLIN2_DIV_SWITCH(REG_CLKSWITCH0
, 28),
265 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0
, 29),
267 .div_flags
= BERLIN2_DIV_HAS_GATE
| BERLIN2_DIV_HAS_MUX
,
272 .parent_ids
= default_parent_ids
,
273 .num_parents
= ARRAY_SIZE(default_parent_ids
),
275 BERLIN2_DIV_GATE(REG_CLKENABLE
, 3),
276 BERLIN2_PLL_SELECT(REG_CLKSELECT1
, 21),
277 BERLIN2_DIV_SELECT(REG_CLKSELECT1
, 24),
278 BERLIN2_PLL_SWITCH(REG_CLKSWITCH0
, 30),
279 BERLIN2_DIV_SWITCH(REG_CLKSWITCH0
, 31),
280 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1
, 0),
282 .div_flags
= BERLIN2_DIV_HAS_GATE
| BERLIN2_DIV_HAS_MUX
,
287 .parent_ids
= default_parent_ids
,
288 .num_parents
= ARRAY_SIZE(default_parent_ids
),
290 BERLIN2_DIV_GATE(REG_CLKENABLE
, 18),
291 BERLIN2_PLL_SELECT(REG_CLKSELECT1
, 27),
292 BERLIN2_DIV_SELECT(REG_CLKSELECT2
, 0),
293 BERLIN2_PLL_SWITCH(REG_CLKSWITCH1
, 1),
294 BERLIN2_DIV_SWITCH(REG_CLKSWITCH1
, 2),
295 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1
, 3),
297 .div_flags
= BERLIN2_DIV_HAS_GATE
| BERLIN2_DIV_HAS_MUX
,
302 .parent_ids
= default_parent_ids
,
303 .num_parents
= ARRAY_SIZE(default_parent_ids
),
305 BERLIN2_DIV_GATE(REG_CLKENABLE
, 21),
306 BERLIN2_PLL_SELECT(REG_CLKSELECT2
, 3),
307 BERLIN2_DIV_SELECT(REG_CLKSELECT2
, 6),
308 BERLIN2_PLL_SWITCH(REG_CLKSWITCH1
, 4),
309 BERLIN2_DIV_SWITCH(REG_CLKSWITCH1
, 5),
310 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1
, 6),
312 .div_flags
= BERLIN2_DIV_HAS_GATE
| BERLIN2_DIV_HAS_MUX
,
317 .parent_ids
= default_parent_ids
,
318 .num_parents
= ARRAY_SIZE(default_parent_ids
),
320 BERLIN2_DIV_GATE(REG_CLKENABLE
, 20),
321 BERLIN2_PLL_SELECT(REG_CLKSELECT2
, 9),
322 BERLIN2_DIV_SELECT(REG_CLKSELECT2
, 12),
323 BERLIN2_PLL_SWITCH(REG_CLKSWITCH1
, 7),
324 BERLIN2_DIV_SWITCH(REG_CLKSWITCH1
, 8),
325 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1
, 9),
327 .div_flags
= BERLIN2_DIV_HAS_GATE
| BERLIN2_DIV_HAS_MUX
,
332 .parent_ids
= (const u8
[]){ AUDIO_FAST_PLL
},
335 BERLIN2_DIV_GATE(REG_CLKENABLE
, 22),
336 BERLIN2_DIV_SELECT(REG_CLKSELECT2
, 17),
337 BERLIN2_DIV_SWITCH(REG_CLKSWITCH1
, 10),
338 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1
, 11),
340 .div_flags
= BERLIN2_DIV_HAS_GATE
,
345 .parent_ids
= (const u8
[]){ AUDIO_FAST_PLL
},
348 BERLIN2_DIV_GATE(REG_CLKENABLE
, 24),
349 BERLIN2_DIV_SELECT(REG_CLKSELECT2
, 20),
350 BERLIN2_DIV_SWITCH(REG_CLKSWITCH1
, 14),
351 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1
, 15),
353 .div_flags
= BERLIN2_DIV_HAS_GATE
,
358 .parent_ids
= (const u8
[]){ AUDIO_FAST_PLL
},
361 BERLIN2_DIV_GATE(REG_CLKENABLE
, 25),
362 BERLIN2_DIV_SELECT(REG_CLKSELECT2
, 23),
363 BERLIN2_DIV_SWITCH(REG_CLKSWITCH1
, 16),
364 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1
, 17),
366 .div_flags
= BERLIN2_DIV_HAS_GATE
,
371 .parent_ids
= (const u8
[]){ AUDIO1_PLL
},
374 BERLIN2_DIV_GATE(REG_CLKENABLE
, 23),
375 BERLIN2_DIV_SELECT(REG_CLKSELECT3
, 0),
376 BERLIN2_DIV_SWITCH(REG_CLKSWITCH1
, 12),
377 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1
, 13),
379 .div_flags
= BERLIN2_DIV_HAS_GATE
,
383 .name
= "gfx3d_core",
384 .parent_ids
= default_parent_ids
,
385 .num_parents
= ARRAY_SIZE(default_parent_ids
),
387 BERLIN2_SINGLE_DIV(REG_GFX3DCORE_CLKCTL
),
389 .div_flags
= BERLIN2_DIV_HAS_GATE
| BERLIN2_DIV_HAS_MUX
,
394 .parent_ids
= default_parent_ids
,
395 .num_parents
= ARRAY_SIZE(default_parent_ids
),
397 BERLIN2_SINGLE_DIV(REG_GFX3DSYS_CLKCTL
),
399 .div_flags
= BERLIN2_DIV_HAS_GATE
| BERLIN2_DIV_HAS_MUX
,
404 .parent_ids
= default_parent_ids
,
405 .num_parents
= ARRAY_SIZE(default_parent_ids
),
407 BERLIN2_SINGLE_DIV(REG_ARC_CLKCTL
),
409 .div_flags
= BERLIN2_DIV_HAS_GATE
| BERLIN2_DIV_HAS_MUX
,
414 .parent_ids
= default_parent_ids
,
415 .num_parents
= ARRAY_SIZE(default_parent_ids
),
417 BERLIN2_SINGLE_DIV(REG_VIP_CLKCTL
),
419 .div_flags
= BERLIN2_DIV_HAS_GATE
| BERLIN2_DIV_HAS_MUX
,
424 .parent_ids
= default_parent_ids
,
425 .num_parents
= ARRAY_SIZE(default_parent_ids
),
427 BERLIN2_SINGLE_DIV(REG_SDIO0XIN_CLKCTL
),
429 .div_flags
= BERLIN2_DIV_HAS_GATE
| BERLIN2_DIV_HAS_MUX
,
434 .parent_ids
= default_parent_ids
,
435 .num_parents
= ARRAY_SIZE(default_parent_ids
),
437 BERLIN2_SINGLE_DIV(REG_SDIO1XIN_CLKCTL
),
439 .div_flags
= BERLIN2_DIV_HAS_GATE
| BERLIN2_DIV_HAS_MUX
,
443 .name
= "gfx3d_extra",
444 .parent_ids
= default_parent_ids
,
445 .num_parents
= ARRAY_SIZE(default_parent_ids
),
447 BERLIN2_SINGLE_DIV(REG_GFX3DEXTRA_CLKCTL
),
449 .div_flags
= BERLIN2_DIV_HAS_GATE
| BERLIN2_DIV_HAS_MUX
,
454 .parent_ids
= default_parent_ids
,
455 .num_parents
= ARRAY_SIZE(default_parent_ids
),
457 BERLIN2_SINGLE_DIV(REG_GC360_CLKCTL
),
459 .div_flags
= BERLIN2_DIV_HAS_GATE
| BERLIN2_DIV_HAS_MUX
,
463 .name
= "sdio_dllmst",
464 .parent_ids
= default_parent_ids
,
465 .num_parents
= ARRAY_SIZE(default_parent_ids
),
467 BERLIN2_SINGLE_DIV(REG_SDIO_DLLMST_CLKCTL
),
469 .div_flags
= BERLIN2_DIV_HAS_GATE
| BERLIN2_DIV_HAS_MUX
,
474 static const struct berlin2_gate_data bg2_gates
[] __initconst
= {
475 { "geth0", "perif", 7 },
476 { "geth1", "perif", 8 },
477 { "sata", "perif", 9 },
478 { "ahbapb", "perif", 10, CLK_IGNORE_UNUSED
},
479 { "usb0", "perif", 11 },
480 { "usb1", "perif", 12 },
481 { "pbridge", "perif", 13, CLK_IGNORE_UNUSED
},
482 { "sdio0", "perif", 14 },
483 { "sdio1", "perif", 15 },
484 { "nfc", "perif", 17 },
485 { "smemc", "perif", 19 },
486 { "audiohd", "audiohd_pll", 26 },
487 { "video0", "video0_in", 27 },
488 { "video1", "video1_in", 28 },
489 { "video2", "video2_in", 29 },
492 static void __init
berlin2_clock_setup(struct device_node
*np
)
494 struct device_node
*parent_np
= of_get_parent(np
);
495 const char *parent_names
[9];
502 clk_data
= kzalloc(struct_size(clk_data
, hws
, MAX_CLKS
), GFP_KERNEL
);
505 clk_data
->num
= MAX_CLKS
;
508 gbase
= of_iomap(parent_np
, 0);
512 /* overwrite default clock names with DT provided ones */
513 clk
= of_clk_get_by_name(np
, clk_names
[REFCLK
]);
515 clk_names
[REFCLK
] = __clk_get_name(clk
);
519 clk
= of_clk_get_by_name(np
, clk_names
[VIDEO_EXT0
]);
521 clk_names
[VIDEO_EXT0
] = __clk_get_name(clk
);
525 /* simple register PLLs */
526 ret
= berlin2_pll_register(&bg2_pll_map
, gbase
+ REG_SYSPLLCTL0
,
527 clk_names
[SYSPLL
], clk_names
[REFCLK
], 0);
531 ret
= berlin2_pll_register(&bg2_pll_map
, gbase
+ REG_MEMPLLCTL0
,
532 clk_names
[MEMPLL
], clk_names
[REFCLK
], 0);
536 ret
= berlin2_pll_register(&bg2_pll_map
, gbase
+ REG_CPUPLLCTL0
,
537 clk_names
[CPUPLL
], clk_names
[REFCLK
], 0);
541 if (of_device_is_compatible(np
, "marvell,berlin2-global-register"))
542 avpll_flags
|= BERLIN2_AVPLL_SCRAMBLE_QUIRK
;
544 /* audio/video VCOs */
545 ret
= berlin2_avpll_vco_register(gbase
+ REG_AVPLLCTL0
, "avpll_vcoA",
546 clk_names
[REFCLK
], avpll_flags
, 0);
550 for (n
= 0; n
< 8; n
++) {
551 ret
= berlin2_avpll_channel_register(gbase
+ REG_AVPLLCTL0
,
552 clk_names
[AVPLL_A1
+ n
], n
, "avpll_vcoA",
558 ret
= berlin2_avpll_vco_register(gbase
+ REG_AVPLLCTL31
, "avpll_vcoB",
559 clk_names
[REFCLK
], BERLIN2_AVPLL_BIT_QUIRK
|
564 for (n
= 0; n
< 8; n
++) {
565 ret
= berlin2_avpll_channel_register(gbase
+ REG_AVPLLCTL31
,
566 clk_names
[AVPLL_B1
+ n
], n
, "avpll_vcoB",
567 BERLIN2_AVPLL_BIT_QUIRK
| avpll_flags
, 0);
572 /* reference clock bypass switches */
573 parent_names
[0] = clk_names
[SYSPLL
];
574 parent_names
[1] = clk_names
[REFCLK
];
575 hw
= clk_hw_register_mux(NULL
, "syspll_byp", parent_names
, 2,
576 0, gbase
+ REG_CLKSWITCH0
, 0, 1, 0, &lock
);
579 clk_names
[SYSPLL
] = clk_hw_get_name(hw
);
581 parent_names
[0] = clk_names
[MEMPLL
];
582 parent_names
[1] = clk_names
[REFCLK
];
583 hw
= clk_hw_register_mux(NULL
, "mempll_byp", parent_names
, 2,
584 0, gbase
+ REG_CLKSWITCH0
, 1, 1, 0, &lock
);
587 clk_names
[MEMPLL
] = clk_hw_get_name(hw
);
589 parent_names
[0] = clk_names
[CPUPLL
];
590 parent_names
[1] = clk_names
[REFCLK
];
591 hw
= clk_hw_register_mux(NULL
, "cpupll_byp", parent_names
, 2,
592 0, gbase
+ REG_CLKSWITCH0
, 2, 1, 0, &lock
);
595 clk_names
[CPUPLL
] = clk_hw_get_name(hw
);
598 parent_names
[0] = clk_names
[AVPLL_B3
];
599 parent_names
[1] = clk_names
[AVPLL_A3
];
600 hw
= clk_hw_register_mux(NULL
, clk_names
[AUDIO1_PLL
], parent_names
, 2,
601 0, gbase
+ REG_CLKSELECT2
, 29, 1, 0, &lock
);
605 parent_names
[0] = clk_names
[VIDEO0_PLL
];
606 parent_names
[1] = clk_names
[VIDEO_EXT0
];
607 hw
= clk_hw_register_mux(NULL
, clk_names
[VIDEO0_IN
], parent_names
, 2,
608 0, gbase
+ REG_CLKSELECT3
, 4, 1, 0, &lock
);
612 parent_names
[0] = clk_names
[VIDEO1_PLL
];
613 parent_names
[1] = clk_names
[VIDEO_EXT0
];
614 hw
= clk_hw_register_mux(NULL
, clk_names
[VIDEO1_IN
], parent_names
, 2,
615 0, gbase
+ REG_CLKSELECT3
, 6, 1, 0, &lock
);
619 parent_names
[0] = clk_names
[AVPLL_A2
];
620 parent_names
[1] = clk_names
[AVPLL_B2
];
621 hw
= clk_hw_register_mux(NULL
, clk_names
[VIDEO1_PLL
], parent_names
, 2,
622 0, gbase
+ REG_CLKSELECT3
, 7, 1, 0, &lock
);
626 parent_names
[0] = clk_names
[VIDEO2_PLL
];
627 parent_names
[1] = clk_names
[VIDEO_EXT0
];
628 hw
= clk_hw_register_mux(NULL
, clk_names
[VIDEO2_IN
], parent_names
, 2,
629 0, gbase
+ REG_CLKSELECT3
, 9, 1, 0, &lock
);
633 parent_names
[0] = clk_names
[AVPLL_B1
];
634 parent_names
[1] = clk_names
[AVPLL_A5
];
635 hw
= clk_hw_register_mux(NULL
, clk_names
[VIDEO2_PLL
], parent_names
, 2,
636 0, gbase
+ REG_CLKSELECT3
, 10, 1, 0, &lock
);
640 /* clock divider cells */
641 for (n
= 0; n
< ARRAY_SIZE(bg2_divs
); n
++) {
642 const struct berlin2_div_data
*dd
= &bg2_divs
[n
];
645 for (k
= 0; k
< dd
->num_parents
; k
++)
646 parent_names
[k
] = clk_names
[dd
->parent_ids
[k
]];
648 hws
[CLKID_SYS
+ n
] = berlin2_div_register(&dd
->map
, gbase
,
649 dd
->name
, dd
->div_flags
, parent_names
,
650 dd
->num_parents
, dd
->flags
, &lock
);
653 /* clock gate cells */
654 for (n
= 0; n
< ARRAY_SIZE(bg2_gates
); n
++) {
655 const struct berlin2_gate_data
*gd
= &bg2_gates
[n
];
657 hws
[CLKID_GETH0
+ n
] = clk_hw_register_gate(NULL
, gd
->name
,
658 gd
->parent_name
, gd
->flags
, gbase
+ REG_CLKENABLE
,
659 gd
->bit_idx
, 0, &lock
);
662 /* twdclk is derived from cpu/3 */
664 clk_hw_register_fixed_factor(NULL
, "twd", "cpu", 0, 1, 3);
666 /* check for errors on leaf clocks */
667 for (n
= 0; n
< MAX_CLKS
; n
++) {
671 pr_err("%pOF: Unable to register leaf clock %d\n", np
, n
);
675 /* register clk-provider */
676 of_clk_add_hw_provider(np
, of_clk_hw_onecell_get
, clk_data
);
683 CLK_OF_DECLARE(berlin2_clk
, "marvell,berlin2-clk",
684 berlin2_clock_setup
);