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>
11 #include <linux/kernel.h>
13 #include <linux/of_address.h>
14 #include <linux/slab.h>
16 #include <dt-bindings/clock/berlin2.h>
18 #include "berlin2-avpll.h"
19 #include "berlin2-div.h"
20 #include "berlin2-pll.h"
23 #define REG_PINMUX0 0x0000
24 #define REG_PINMUX1 0x0004
25 #define REG_SYSPLLCTL0 0x0014
26 #define REG_SYSPLLCTL4 0x0024
27 #define REG_MEMPLLCTL0 0x0028
28 #define REG_MEMPLLCTL4 0x0038
29 #define REG_CPUPLLCTL0 0x003c
30 #define REG_CPUPLLCTL4 0x004c
31 #define REG_AVPLLCTL0 0x0050
32 #define REG_AVPLLCTL31 0x00cc
33 #define REG_AVPLLCTL62 0x0148
34 #define REG_PLLSTATUS 0x014c
35 #define REG_CLKENABLE 0x0150
36 #define REG_CLKSELECT0 0x0154
37 #define REG_CLKSELECT1 0x0158
38 #define REG_CLKSELECT2 0x015c
39 #define REG_CLKSELECT3 0x0160
40 #define REG_CLKSWITCH0 0x0164
41 #define REG_CLKSWITCH1 0x0168
42 #define REG_RESET_TRIGGER 0x0178
43 #define REG_RESET_STATUS0 0x017c
44 #define REG_RESET_STATUS1 0x0180
45 #define REG_SW_GENERIC0 0x0184
46 #define REG_SW_GENERIC3 0x0190
47 #define REG_PRODUCTID 0x01cc
48 #define REG_PRODUCTID_EXT 0x01d0
49 #define REG_GFX3DCORE_CLKCTL 0x022c
50 #define REG_GFX3DSYS_CLKCTL 0x0230
51 #define REG_ARC_CLKCTL 0x0234
52 #define REG_VIP_CLKCTL 0x0238
53 #define REG_SDIO0XIN_CLKCTL 0x023c
54 #define REG_SDIO1XIN_CLKCTL 0x0240
55 #define REG_GFX3DEXTRA_CLKCTL 0x0244
56 #define REG_GFX3D_RESET 0x0248
57 #define REG_GC360_CLKCTL 0x024c
58 #define REG_SDIO_DLLMST_CLKCTL 0x0250
61 * BG2/BG2CD SoCs have the following audio/video I/O units:
63 * audiohd: HDMI TX audio
69 * video1: Secondary video
70 * video2: SD auxiliary video
72 * There are no external audio clocks (ACLKI0, ACLKI1) and
73 * only one external video clock (VCLKI0).
75 * Currently missing bits and pieces:
76 * - audio_fast_pll is unknown
77 * - audiohd_pll is unknown
78 * - video0_pll is unknown
79 * - audio[023], audiohd parent pll is assumed to be audio_fast_pll
84 static struct clk_hw_onecell_data
*clk_data
;
85 static DEFINE_SPINLOCK(lock
);
86 static void __iomem
*gbase
;
90 SYSPLL
, MEMPLL
, CPUPLL
,
91 AVPLL_A1
, AVPLL_A2
, AVPLL_A3
, AVPLL_A4
,
92 AVPLL_A5
, AVPLL_A6
, AVPLL_A7
, AVPLL_A8
,
93 AVPLL_B1
, AVPLL_B2
, AVPLL_B3
, AVPLL_B4
,
94 AVPLL_B5
, AVPLL_B6
, AVPLL_B7
, AVPLL_B8
,
95 AUDIO1_PLL
, AUDIO_FAST_PLL
,
96 VIDEO0_PLL
, VIDEO0_IN
,
97 VIDEO1_PLL
, VIDEO1_IN
,
98 VIDEO2_PLL
, VIDEO2_IN
,
101 static const char *clk_names
[] = {
103 [VIDEO_EXT0
] = "video_ext0",
107 [AVPLL_A1
] = "avpll_a1",
108 [AVPLL_A2
] = "avpll_a2",
109 [AVPLL_A3
] = "avpll_a3",
110 [AVPLL_A4
] = "avpll_a4",
111 [AVPLL_A5
] = "avpll_a5",
112 [AVPLL_A6
] = "avpll_a6",
113 [AVPLL_A7
] = "avpll_a7",
114 [AVPLL_A8
] = "avpll_a8",
115 [AVPLL_B1
] = "avpll_b1",
116 [AVPLL_B2
] = "avpll_b2",
117 [AVPLL_B3
] = "avpll_b3",
118 [AVPLL_B4
] = "avpll_b4",
119 [AVPLL_B5
] = "avpll_b5",
120 [AVPLL_B6
] = "avpll_b6",
121 [AVPLL_B7
] = "avpll_b7",
122 [AVPLL_B8
] = "avpll_b8",
123 [AUDIO1_PLL
] = "audio1_pll",
124 [AUDIO_FAST_PLL
] = "audio_fast_pll",
125 [VIDEO0_PLL
] = "video0_pll",
126 [VIDEO0_IN
] = "video0_in",
127 [VIDEO1_PLL
] = "video1_pll",
128 [VIDEO1_IN
] = "video1_in",
129 [VIDEO2_PLL
] = "video2_pll",
130 [VIDEO2_IN
] = "video2_in",
133 static const struct berlin2_pll_map bg2_pll_map __initconst
= {
134 .vcodiv
= {10, 15, 20, 25, 30, 40, 50, 60, 80},
141 static const u8 default_parent_ids
[] = {
142 SYSPLL
, AVPLL_B4
, AVPLL_A5
, AVPLL_B6
, AVPLL_B7
, SYSPLL
145 static const struct berlin2_div_data bg2_divs
[] __initconst
= {
148 .parent_ids
= (const u8
[]){
149 SYSPLL
, AVPLL_B4
, AVPLL_B5
, AVPLL_B6
, AVPLL_B7
, SYSPLL
153 BERLIN2_DIV_GATE(REG_CLKENABLE
, 0),
154 BERLIN2_PLL_SELECT(REG_CLKSELECT0
, 0),
155 BERLIN2_DIV_SELECT(REG_CLKSELECT0
, 3),
156 BERLIN2_PLL_SWITCH(REG_CLKSWITCH0
, 3),
157 BERLIN2_DIV_SWITCH(REG_CLKSWITCH0
, 4),
158 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0
, 5),
160 .div_flags
= BERLIN2_DIV_HAS_GATE
| BERLIN2_DIV_HAS_MUX
,
161 .flags
= CLK_IGNORE_UNUSED
,
165 .parent_ids
= (const u8
[]){
166 CPUPLL
, MEMPLL
, MEMPLL
, MEMPLL
, MEMPLL
170 BERLIN2_PLL_SELECT(REG_CLKSELECT0
, 6),
171 BERLIN2_DIV_SELECT(REG_CLKSELECT0
, 9),
172 BERLIN2_PLL_SWITCH(REG_CLKSWITCH0
, 6),
173 BERLIN2_DIV_SWITCH(REG_CLKSWITCH0
, 7),
174 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0
, 8),
176 .div_flags
= BERLIN2_DIV_HAS_MUX
,
181 .parent_ids
= default_parent_ids
,
182 .num_parents
= ARRAY_SIZE(default_parent_ids
),
184 BERLIN2_DIV_GATE(REG_CLKENABLE
, 16),
185 BERLIN2_PLL_SELECT(REG_CLKSELECT0
, 17),
186 BERLIN2_DIV_SELECT(REG_CLKSELECT0
, 20),
187 BERLIN2_PLL_SWITCH(REG_CLKSWITCH0
, 12),
188 BERLIN2_DIV_SWITCH(REG_CLKSWITCH0
, 13),
189 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0
, 14),
191 .div_flags
= BERLIN2_DIV_HAS_GATE
| BERLIN2_DIV_HAS_MUX
,
196 .parent_ids
= default_parent_ids
,
197 .num_parents
= ARRAY_SIZE(default_parent_ids
),
199 BERLIN2_DIV_GATE(REG_CLKENABLE
, 1),
200 BERLIN2_PLL_SELECT(REG_CLKSELECT0
, 23),
201 BERLIN2_DIV_SELECT(REG_CLKSELECT0
, 26),
202 BERLIN2_PLL_SWITCH(REG_CLKSWITCH0
, 15),
203 BERLIN2_DIV_SWITCH(REG_CLKSWITCH0
, 16),
204 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0
, 17),
206 .div_flags
= BERLIN2_DIV_HAS_GATE
| BERLIN2_DIV_HAS_MUX
,
211 .parent_ids
= default_parent_ids
,
212 .num_parents
= ARRAY_SIZE(default_parent_ids
),
214 BERLIN2_DIV_GATE(REG_CLKENABLE
, 4),
215 BERLIN2_PLL_SELECT(REG_CLKSELECT0
, 29),
216 BERLIN2_DIV_SELECT(REG_CLKSELECT1
, 0),
217 BERLIN2_PLL_SWITCH(REG_CLKSWITCH0
, 18),
218 BERLIN2_DIV_SWITCH(REG_CLKSWITCH0
, 19),
219 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0
, 20),
221 .div_flags
= BERLIN2_DIV_HAS_GATE
| BERLIN2_DIV_HAS_MUX
,
226 .parent_ids
= default_parent_ids
,
227 .num_parents
= ARRAY_SIZE(default_parent_ids
),
229 BERLIN2_DIV_GATE(REG_CLKENABLE
, 5),
230 BERLIN2_PLL_SELECT(REG_CLKSELECT1
, 3),
231 BERLIN2_DIV_SELECT(REG_CLKSELECT1
, 6),
232 BERLIN2_PLL_SWITCH(REG_CLKSWITCH0
, 21),
233 BERLIN2_DIV_SWITCH(REG_CLKSWITCH0
, 22),
234 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0
, 23),
236 .div_flags
= BERLIN2_DIV_HAS_GATE
| BERLIN2_DIV_HAS_MUX
,
241 .parent_ids
= default_parent_ids
,
242 .num_parents
= ARRAY_SIZE(default_parent_ids
),
244 BERLIN2_DIV_GATE(REG_CLKENABLE
, 6),
245 BERLIN2_PLL_SELECT(REG_CLKSELECT1
, 9),
246 BERLIN2_DIV_SELECT(REG_CLKSELECT1
, 12),
247 BERLIN2_PLL_SWITCH(REG_CLKSWITCH0
, 24),
248 BERLIN2_DIV_SWITCH(REG_CLKSWITCH0
, 25),
249 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0
, 26),
251 .div_flags
= BERLIN2_DIV_HAS_GATE
| BERLIN2_DIV_HAS_MUX
,
252 .flags
= CLK_IGNORE_UNUSED
,
256 .parent_ids
= default_parent_ids
,
257 .num_parents
= ARRAY_SIZE(default_parent_ids
),
259 BERLIN2_DIV_GATE(REG_CLKENABLE
, 2),
260 BERLIN2_PLL_SELECT(REG_CLKSELECT1
, 15),
261 BERLIN2_DIV_SELECT(REG_CLKSELECT1
, 18),
262 BERLIN2_PLL_SWITCH(REG_CLKSWITCH0
, 27),
263 BERLIN2_DIV_SWITCH(REG_CLKSWITCH0
, 28),
264 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0
, 29),
266 .div_flags
= BERLIN2_DIV_HAS_GATE
| BERLIN2_DIV_HAS_MUX
,
271 .parent_ids
= default_parent_ids
,
272 .num_parents
= ARRAY_SIZE(default_parent_ids
),
274 BERLIN2_DIV_GATE(REG_CLKENABLE
, 3),
275 BERLIN2_PLL_SELECT(REG_CLKSELECT1
, 21),
276 BERLIN2_DIV_SELECT(REG_CLKSELECT1
, 24),
277 BERLIN2_PLL_SWITCH(REG_CLKSWITCH0
, 30),
278 BERLIN2_DIV_SWITCH(REG_CLKSWITCH0
, 31),
279 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1
, 0),
281 .div_flags
= BERLIN2_DIV_HAS_GATE
| BERLIN2_DIV_HAS_MUX
,
286 .parent_ids
= default_parent_ids
,
287 .num_parents
= ARRAY_SIZE(default_parent_ids
),
289 BERLIN2_DIV_GATE(REG_CLKENABLE
, 18),
290 BERLIN2_PLL_SELECT(REG_CLKSELECT1
, 27),
291 BERLIN2_DIV_SELECT(REG_CLKSELECT2
, 0),
292 BERLIN2_PLL_SWITCH(REG_CLKSWITCH1
, 1),
293 BERLIN2_DIV_SWITCH(REG_CLKSWITCH1
, 2),
294 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1
, 3),
296 .div_flags
= BERLIN2_DIV_HAS_GATE
| BERLIN2_DIV_HAS_MUX
,
301 .parent_ids
= default_parent_ids
,
302 .num_parents
= ARRAY_SIZE(default_parent_ids
),
304 BERLIN2_DIV_GATE(REG_CLKENABLE
, 21),
305 BERLIN2_PLL_SELECT(REG_CLKSELECT2
, 3),
306 BERLIN2_DIV_SELECT(REG_CLKSELECT2
, 6),
307 BERLIN2_PLL_SWITCH(REG_CLKSWITCH1
, 4),
308 BERLIN2_DIV_SWITCH(REG_CLKSWITCH1
, 5),
309 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1
, 6),
311 .div_flags
= BERLIN2_DIV_HAS_GATE
| BERLIN2_DIV_HAS_MUX
,
316 .parent_ids
= default_parent_ids
,
317 .num_parents
= ARRAY_SIZE(default_parent_ids
),
319 BERLIN2_DIV_GATE(REG_CLKENABLE
, 20),
320 BERLIN2_PLL_SELECT(REG_CLKSELECT2
, 9),
321 BERLIN2_DIV_SELECT(REG_CLKSELECT2
, 12),
322 BERLIN2_PLL_SWITCH(REG_CLKSWITCH1
, 7),
323 BERLIN2_DIV_SWITCH(REG_CLKSWITCH1
, 8),
324 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1
, 9),
326 .div_flags
= BERLIN2_DIV_HAS_GATE
| BERLIN2_DIV_HAS_MUX
,
331 .parent_ids
= (const u8
[]){ AUDIO_FAST_PLL
},
334 BERLIN2_DIV_GATE(REG_CLKENABLE
, 22),
335 BERLIN2_DIV_SELECT(REG_CLKSELECT2
, 17),
336 BERLIN2_DIV_SWITCH(REG_CLKSWITCH1
, 10),
337 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1
, 11),
339 .div_flags
= BERLIN2_DIV_HAS_GATE
,
344 .parent_ids
= (const u8
[]){ AUDIO_FAST_PLL
},
347 BERLIN2_DIV_GATE(REG_CLKENABLE
, 24),
348 BERLIN2_DIV_SELECT(REG_CLKSELECT2
, 20),
349 BERLIN2_DIV_SWITCH(REG_CLKSWITCH1
, 14),
350 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1
, 15),
352 .div_flags
= BERLIN2_DIV_HAS_GATE
,
357 .parent_ids
= (const u8
[]){ AUDIO_FAST_PLL
},
360 BERLIN2_DIV_GATE(REG_CLKENABLE
, 25),
361 BERLIN2_DIV_SELECT(REG_CLKSELECT2
, 23),
362 BERLIN2_DIV_SWITCH(REG_CLKSWITCH1
, 16),
363 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1
, 17),
365 .div_flags
= BERLIN2_DIV_HAS_GATE
,
370 .parent_ids
= (const u8
[]){ AUDIO1_PLL
},
373 BERLIN2_DIV_GATE(REG_CLKENABLE
, 23),
374 BERLIN2_DIV_SELECT(REG_CLKSELECT3
, 0),
375 BERLIN2_DIV_SWITCH(REG_CLKSWITCH1
, 12),
376 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1
, 13),
378 .div_flags
= BERLIN2_DIV_HAS_GATE
,
382 .name
= "gfx3d_core",
383 .parent_ids
= default_parent_ids
,
384 .num_parents
= ARRAY_SIZE(default_parent_ids
),
386 BERLIN2_SINGLE_DIV(REG_GFX3DCORE_CLKCTL
),
388 .div_flags
= BERLIN2_DIV_HAS_GATE
| BERLIN2_DIV_HAS_MUX
,
393 .parent_ids
= default_parent_ids
,
394 .num_parents
= ARRAY_SIZE(default_parent_ids
),
396 BERLIN2_SINGLE_DIV(REG_GFX3DSYS_CLKCTL
),
398 .div_flags
= BERLIN2_DIV_HAS_GATE
| BERLIN2_DIV_HAS_MUX
,
403 .parent_ids
= default_parent_ids
,
404 .num_parents
= ARRAY_SIZE(default_parent_ids
),
406 BERLIN2_SINGLE_DIV(REG_ARC_CLKCTL
),
408 .div_flags
= BERLIN2_DIV_HAS_GATE
| BERLIN2_DIV_HAS_MUX
,
413 .parent_ids
= default_parent_ids
,
414 .num_parents
= ARRAY_SIZE(default_parent_ids
),
416 BERLIN2_SINGLE_DIV(REG_VIP_CLKCTL
),
418 .div_flags
= BERLIN2_DIV_HAS_GATE
| BERLIN2_DIV_HAS_MUX
,
423 .parent_ids
= default_parent_ids
,
424 .num_parents
= ARRAY_SIZE(default_parent_ids
),
426 BERLIN2_SINGLE_DIV(REG_SDIO0XIN_CLKCTL
),
428 .div_flags
= BERLIN2_DIV_HAS_GATE
| BERLIN2_DIV_HAS_MUX
,
433 .parent_ids
= default_parent_ids
,
434 .num_parents
= ARRAY_SIZE(default_parent_ids
),
436 BERLIN2_SINGLE_DIV(REG_SDIO1XIN_CLKCTL
),
438 .div_flags
= BERLIN2_DIV_HAS_GATE
| BERLIN2_DIV_HAS_MUX
,
442 .name
= "gfx3d_extra",
443 .parent_ids
= default_parent_ids
,
444 .num_parents
= ARRAY_SIZE(default_parent_ids
),
446 BERLIN2_SINGLE_DIV(REG_GFX3DEXTRA_CLKCTL
),
448 .div_flags
= BERLIN2_DIV_HAS_GATE
| BERLIN2_DIV_HAS_MUX
,
453 .parent_ids
= default_parent_ids
,
454 .num_parents
= ARRAY_SIZE(default_parent_ids
),
456 BERLIN2_SINGLE_DIV(REG_GC360_CLKCTL
),
458 .div_flags
= BERLIN2_DIV_HAS_GATE
| BERLIN2_DIV_HAS_MUX
,
462 .name
= "sdio_dllmst",
463 .parent_ids
= default_parent_ids
,
464 .num_parents
= ARRAY_SIZE(default_parent_ids
),
466 BERLIN2_SINGLE_DIV(REG_SDIO_DLLMST_CLKCTL
),
468 .div_flags
= BERLIN2_DIV_HAS_GATE
| BERLIN2_DIV_HAS_MUX
,
473 static const struct berlin2_gate_data bg2_gates
[] __initconst
= {
474 { "geth0", "perif", 7 },
475 { "geth1", "perif", 8 },
476 { "sata", "perif", 9 },
477 { "ahbapb", "perif", 10, CLK_IGNORE_UNUSED
},
478 { "usb0", "perif", 11 },
479 { "usb1", "perif", 12 },
480 { "pbridge", "perif", 13, CLK_IGNORE_UNUSED
},
481 { "sdio0", "perif", 14 },
482 { "sdio1", "perif", 15 },
483 { "nfc", "perif", 17 },
484 { "smemc", "perif", 19 },
485 { "audiohd", "audiohd_pll", 26 },
486 { "video0", "video0_in", 27 },
487 { "video1", "video1_in", 28 },
488 { "video2", "video2_in", 29 },
491 static void __init
berlin2_clock_setup(struct device_node
*np
)
493 struct device_node
*parent_np
= of_get_parent(np
);
494 const char *parent_names
[9];
501 clk_data
= kzalloc(struct_size(clk_data
, hws
, MAX_CLKS
), GFP_KERNEL
);
504 clk_data
->num
= MAX_CLKS
;
507 gbase
= of_iomap(parent_np
, 0);
511 /* overwrite default clock names with DT provided ones */
512 clk
= of_clk_get_by_name(np
, clk_names
[REFCLK
]);
514 clk_names
[REFCLK
] = __clk_get_name(clk
);
518 clk
= of_clk_get_by_name(np
, clk_names
[VIDEO_EXT0
]);
520 clk_names
[VIDEO_EXT0
] = __clk_get_name(clk
);
524 /* simple register PLLs */
525 ret
= berlin2_pll_register(&bg2_pll_map
, gbase
+ REG_SYSPLLCTL0
,
526 clk_names
[SYSPLL
], clk_names
[REFCLK
], 0);
530 ret
= berlin2_pll_register(&bg2_pll_map
, gbase
+ REG_MEMPLLCTL0
,
531 clk_names
[MEMPLL
], clk_names
[REFCLK
], 0);
535 ret
= berlin2_pll_register(&bg2_pll_map
, gbase
+ REG_CPUPLLCTL0
,
536 clk_names
[CPUPLL
], clk_names
[REFCLK
], 0);
540 if (of_device_is_compatible(np
, "marvell,berlin2-global-register"))
541 avpll_flags
|= BERLIN2_AVPLL_SCRAMBLE_QUIRK
;
543 /* audio/video VCOs */
544 ret
= berlin2_avpll_vco_register(gbase
+ REG_AVPLLCTL0
, "avpll_vcoA",
545 clk_names
[REFCLK
], avpll_flags
, 0);
549 for (n
= 0; n
< 8; n
++) {
550 ret
= berlin2_avpll_channel_register(gbase
+ REG_AVPLLCTL0
,
551 clk_names
[AVPLL_A1
+ n
], n
, "avpll_vcoA",
557 ret
= berlin2_avpll_vco_register(gbase
+ REG_AVPLLCTL31
, "avpll_vcoB",
558 clk_names
[REFCLK
], BERLIN2_AVPLL_BIT_QUIRK
|
563 for (n
= 0; n
< 8; n
++) {
564 ret
= berlin2_avpll_channel_register(gbase
+ REG_AVPLLCTL31
,
565 clk_names
[AVPLL_B1
+ n
], n
, "avpll_vcoB",
566 BERLIN2_AVPLL_BIT_QUIRK
| avpll_flags
, 0);
571 /* reference clock bypass switches */
572 parent_names
[0] = clk_names
[SYSPLL
];
573 parent_names
[1] = clk_names
[REFCLK
];
574 hw
= clk_hw_register_mux(NULL
, "syspll_byp", parent_names
, 2,
575 0, gbase
+ REG_CLKSWITCH0
, 0, 1, 0, &lock
);
578 clk_names
[SYSPLL
] = clk_hw_get_name(hw
);
580 parent_names
[0] = clk_names
[MEMPLL
];
581 parent_names
[1] = clk_names
[REFCLK
];
582 hw
= clk_hw_register_mux(NULL
, "mempll_byp", parent_names
, 2,
583 0, gbase
+ REG_CLKSWITCH0
, 1, 1, 0, &lock
);
586 clk_names
[MEMPLL
] = clk_hw_get_name(hw
);
588 parent_names
[0] = clk_names
[CPUPLL
];
589 parent_names
[1] = clk_names
[REFCLK
];
590 hw
= clk_hw_register_mux(NULL
, "cpupll_byp", parent_names
, 2,
591 0, gbase
+ REG_CLKSWITCH0
, 2, 1, 0, &lock
);
594 clk_names
[CPUPLL
] = clk_hw_get_name(hw
);
597 parent_names
[0] = clk_names
[AVPLL_B3
];
598 parent_names
[1] = clk_names
[AVPLL_A3
];
599 hw
= clk_hw_register_mux(NULL
, clk_names
[AUDIO1_PLL
], parent_names
, 2,
600 0, gbase
+ REG_CLKSELECT2
, 29, 1, 0, &lock
);
604 parent_names
[0] = clk_names
[VIDEO0_PLL
];
605 parent_names
[1] = clk_names
[VIDEO_EXT0
];
606 hw
= clk_hw_register_mux(NULL
, clk_names
[VIDEO0_IN
], parent_names
, 2,
607 0, gbase
+ REG_CLKSELECT3
, 4, 1, 0, &lock
);
611 parent_names
[0] = clk_names
[VIDEO1_PLL
];
612 parent_names
[1] = clk_names
[VIDEO_EXT0
];
613 hw
= clk_hw_register_mux(NULL
, clk_names
[VIDEO1_IN
], parent_names
, 2,
614 0, gbase
+ REG_CLKSELECT3
, 6, 1, 0, &lock
);
618 parent_names
[0] = clk_names
[AVPLL_A2
];
619 parent_names
[1] = clk_names
[AVPLL_B2
];
620 hw
= clk_hw_register_mux(NULL
, clk_names
[VIDEO1_PLL
], parent_names
, 2,
621 0, gbase
+ REG_CLKSELECT3
, 7, 1, 0, &lock
);
625 parent_names
[0] = clk_names
[VIDEO2_PLL
];
626 parent_names
[1] = clk_names
[VIDEO_EXT0
];
627 hw
= clk_hw_register_mux(NULL
, clk_names
[VIDEO2_IN
], parent_names
, 2,
628 0, gbase
+ REG_CLKSELECT3
, 9, 1, 0, &lock
);
632 parent_names
[0] = clk_names
[AVPLL_B1
];
633 parent_names
[1] = clk_names
[AVPLL_A5
];
634 hw
= clk_hw_register_mux(NULL
, clk_names
[VIDEO2_PLL
], parent_names
, 2,
635 0, gbase
+ REG_CLKSELECT3
, 10, 1, 0, &lock
);
639 /* clock divider cells */
640 for (n
= 0; n
< ARRAY_SIZE(bg2_divs
); n
++) {
641 const struct berlin2_div_data
*dd
= &bg2_divs
[n
];
644 for (k
= 0; k
< dd
->num_parents
; k
++)
645 parent_names
[k
] = clk_names
[dd
->parent_ids
[k
]];
647 hws
[CLKID_SYS
+ n
] = berlin2_div_register(&dd
->map
, gbase
,
648 dd
->name
, dd
->div_flags
, parent_names
,
649 dd
->num_parents
, dd
->flags
, &lock
);
652 /* clock gate cells */
653 for (n
= 0; n
< ARRAY_SIZE(bg2_gates
); n
++) {
654 const struct berlin2_gate_data
*gd
= &bg2_gates
[n
];
656 hws
[CLKID_GETH0
+ n
] = clk_hw_register_gate(NULL
, gd
->name
,
657 gd
->parent_name
, gd
->flags
, gbase
+ REG_CLKENABLE
,
658 gd
->bit_idx
, 0, &lock
);
661 /* twdclk is derived from cpu/3 */
663 clk_hw_register_fixed_factor(NULL
, "twd", "cpu", 0, 1, 3);
665 /* check for errors on leaf clocks */
666 for (n
= 0; n
< MAX_CLKS
; n
++) {
670 pr_err("%pOF: Unable to register leaf clock %d\n", np
, n
);
674 /* register clk-provider */
675 of_clk_add_hw_provider(np
, of_clk_hw_onecell_get
, clk_data
);
682 CLK_OF_DECLARE(berlin2_clk
, "marvell,berlin2-clk",
683 berlin2_clock_setup
);