GNU Linux-libre 5.10.153-gnu1
[releases.git] / drivers / clk / berlin / bg2.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2014 Marvell Technology Group Ltd.
4  *
5  * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
6  * Alexandre Belloni <alexandre.belloni@free-electrons.com>
7  */
8
9 #include <linux/clk.h>
10 #include <linux/clk-provider.h>
11 #include <linux/io.h>
12 #include <linux/kernel.h>
13 #include <linux/of.h>
14 #include <linux/of_address.h>
15 #include <linux/slab.h>
16
17 #include <dt-bindings/clock/berlin2.h>
18
19 #include "berlin2-avpll.h"
20 #include "berlin2-div.h"
21 #include "berlin2-pll.h"
22 #include "common.h"
23
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
60
61 /*
62  * BG2/BG2CD SoCs have the following audio/video I/O units:
63  *
64  * audiohd: HDMI TX audio
65  * audio0:  7.1ch TX
66  * audio1:  2ch TX
67  * audio2:  2ch RX
68  * audio3:  SPDIF TX
69  * video0:  HDMI video
70  * video1:  Secondary video
71  * video2:  SD auxiliary video
72  *
73  * There are no external audio clocks (ACLKI0, ACLKI1) and
74  * only one external video clock (VCLKI0).
75  *
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
81  *
82  */
83
84 #define MAX_CLKS 41
85 static struct clk_hw_onecell_data *clk_data;
86 static DEFINE_SPINLOCK(lock);
87 static void __iomem *gbase;
88
89 enum {
90         REFCLK, VIDEO_EXT0,
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,
100 };
101
102 static const char *clk_names[] = {
103         [REFCLK]                = "refclk",
104         [VIDEO_EXT0]            = "video_ext0",
105         [SYSPLL]                = "syspll",
106         [MEMPLL]                = "mempll",
107         [CPUPLL]                = "cpupll",
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",
132 };
133
134 static const struct berlin2_pll_map bg2_pll_map __initconst = {
135         .vcodiv         = {10, 15, 20, 25, 30, 40, 50, 60, 80},
136         .mult           = 10,
137         .fbdiv_shift    = 6,
138         .rfdiv_shift    = 1,
139         .divsel_shift   = 7,
140 };
141
142 static const u8 default_parent_ids[] = {
143         SYSPLL, AVPLL_B4, AVPLL_A5, AVPLL_B6, AVPLL_B7, SYSPLL
144 };
145
146 static const struct berlin2_div_data bg2_divs[] __initconst = {
147         {
148                 .name = "sys",
149                 .parent_ids = (const u8 []){
150                         SYSPLL, AVPLL_B4, AVPLL_B5, AVPLL_B6, AVPLL_B7, SYSPLL
151                 },
152                 .num_parents = 6,
153                 .map = {
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),
160                 },
161                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
162                 .flags = CLK_IGNORE_UNUSED,
163         },
164         {
165                 .name = "cpu",
166                 .parent_ids = (const u8 []){
167                         CPUPLL, MEMPLL, MEMPLL, MEMPLL, MEMPLL
168                 },
169                 .num_parents = 5,
170                 .map = {
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),
176                 },
177                 .div_flags = BERLIN2_DIV_HAS_MUX,
178                 .flags = 0,
179         },
180         {
181                 .name = "drmfigo",
182                 .parent_ids = default_parent_ids,
183                 .num_parents = ARRAY_SIZE(default_parent_ids),
184                 .map = {
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),
191                 },
192                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
193                 .flags = 0,
194         },
195         {
196                 .name = "cfg",
197                 .parent_ids = default_parent_ids,
198                 .num_parents = ARRAY_SIZE(default_parent_ids),
199                 .map = {
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),
206                 },
207                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
208                 .flags = 0,
209         },
210         {
211                 .name = "gfx",
212                 .parent_ids = default_parent_ids,
213                 .num_parents = ARRAY_SIZE(default_parent_ids),
214                 .map = {
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),
221                 },
222                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
223                 .flags = 0,
224         },
225         {
226                 .name = "zsp",
227                 .parent_ids = default_parent_ids,
228                 .num_parents = ARRAY_SIZE(default_parent_ids),
229                 .map = {
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),
236                 },
237                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
238                 .flags = 0,
239         },
240         {
241                 .name = "perif",
242                 .parent_ids = default_parent_ids,
243                 .num_parents = ARRAY_SIZE(default_parent_ids),
244                 .map = {
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),
251                 },
252                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
253                 .flags = CLK_IGNORE_UNUSED,
254         },
255         {
256                 .name = "pcube",
257                 .parent_ids = default_parent_ids,
258                 .num_parents = ARRAY_SIZE(default_parent_ids),
259                 .map = {
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),
266                 },
267                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
268                 .flags = 0,
269         },
270         {
271                 .name = "vscope",
272                 .parent_ids = default_parent_ids,
273                 .num_parents = ARRAY_SIZE(default_parent_ids),
274                 .map = {
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),
281                 },
282                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
283                 .flags = 0,
284         },
285         {
286                 .name = "nfc_ecc",
287                 .parent_ids = default_parent_ids,
288                 .num_parents = ARRAY_SIZE(default_parent_ids),
289                 .map = {
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),
296                 },
297                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
298                 .flags = 0,
299         },
300         {
301                 .name = "vpp",
302                 .parent_ids = default_parent_ids,
303                 .num_parents = ARRAY_SIZE(default_parent_ids),
304                 .map = {
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),
311                 },
312                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
313                 .flags = 0,
314         },
315         {
316                 .name = "app",
317                 .parent_ids = default_parent_ids,
318                 .num_parents = ARRAY_SIZE(default_parent_ids),
319                 .map = {
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),
326                 },
327                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
328                 .flags = 0,
329         },
330         {
331                 .name = "audio0",
332                 .parent_ids = (const u8 []){ AUDIO_FAST_PLL },
333                 .num_parents = 1,
334                 .map = {
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),
339                 },
340                 .div_flags = BERLIN2_DIV_HAS_GATE,
341                 .flags = 0,
342         },
343         {
344                 .name = "audio2",
345                 .parent_ids = (const u8 []){ AUDIO_FAST_PLL },
346                 .num_parents = 1,
347                 .map = {
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),
352                 },
353                 .div_flags = BERLIN2_DIV_HAS_GATE,
354                 .flags = 0,
355         },
356         {
357                 .name = "audio3",
358                 .parent_ids = (const u8 []){ AUDIO_FAST_PLL },
359                 .num_parents = 1,
360                 .map = {
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),
365                 },
366                 .div_flags = BERLIN2_DIV_HAS_GATE,
367                 .flags = 0,
368         },
369         {
370                 .name = "audio1",
371                 .parent_ids = (const u8 []){ AUDIO1_PLL },
372                 .num_parents = 1,
373                 .map = {
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),
378                 },
379                 .div_flags = BERLIN2_DIV_HAS_GATE,
380                 .flags = 0,
381         },
382         {
383                 .name = "gfx3d_core",
384                 .parent_ids = default_parent_ids,
385                 .num_parents = ARRAY_SIZE(default_parent_ids),
386                 .map = {
387                         BERLIN2_SINGLE_DIV(REG_GFX3DCORE_CLKCTL),
388                 },
389                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
390                 .flags = 0,
391         },
392         {
393                 .name = "gfx3d_sys",
394                 .parent_ids = default_parent_ids,
395                 .num_parents = ARRAY_SIZE(default_parent_ids),
396                 .map = {
397                         BERLIN2_SINGLE_DIV(REG_GFX3DSYS_CLKCTL),
398                 },
399                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
400                 .flags = 0,
401         },
402         {
403                 .name = "arc",
404                 .parent_ids = default_parent_ids,
405                 .num_parents = ARRAY_SIZE(default_parent_ids),
406                 .map = {
407                         BERLIN2_SINGLE_DIV(REG_ARC_CLKCTL),
408                 },
409                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
410                 .flags = 0,
411         },
412         {
413                 .name = "vip",
414                 .parent_ids = default_parent_ids,
415                 .num_parents = ARRAY_SIZE(default_parent_ids),
416                 .map = {
417                         BERLIN2_SINGLE_DIV(REG_VIP_CLKCTL),
418                 },
419                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
420                 .flags = 0,
421         },
422         {
423                 .name = "sdio0xin",
424                 .parent_ids = default_parent_ids,
425                 .num_parents = ARRAY_SIZE(default_parent_ids),
426                 .map = {
427                         BERLIN2_SINGLE_DIV(REG_SDIO0XIN_CLKCTL),
428                 },
429                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
430                 .flags = 0,
431         },
432         {
433                 .name = "sdio1xin",
434                 .parent_ids = default_parent_ids,
435                 .num_parents = ARRAY_SIZE(default_parent_ids),
436                 .map = {
437                         BERLIN2_SINGLE_DIV(REG_SDIO1XIN_CLKCTL),
438                 },
439                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
440                 .flags = 0,
441         },
442         {
443                 .name = "gfx3d_extra",
444                 .parent_ids = default_parent_ids,
445                 .num_parents = ARRAY_SIZE(default_parent_ids),
446                 .map = {
447                         BERLIN2_SINGLE_DIV(REG_GFX3DEXTRA_CLKCTL),
448                 },
449                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
450                 .flags = 0,
451         },
452         {
453                 .name = "gc360",
454                 .parent_ids = default_parent_ids,
455                 .num_parents = ARRAY_SIZE(default_parent_ids),
456                 .map = {
457                         BERLIN2_SINGLE_DIV(REG_GC360_CLKCTL),
458                 },
459                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
460                 .flags = 0,
461         },
462         {
463                 .name = "sdio_dllmst",
464                 .parent_ids = default_parent_ids,
465                 .num_parents = ARRAY_SIZE(default_parent_ids),
466                 .map = {
467                         BERLIN2_SINGLE_DIV(REG_SDIO_DLLMST_CLKCTL),
468                 },
469                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
470                 .flags = 0,
471         },
472 };
473
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 },
490 };
491
492 static void __init berlin2_clock_setup(struct device_node *np)
493 {
494         struct device_node *parent_np = of_get_parent(np);
495         const char *parent_names[9];
496         struct clk *clk;
497         struct clk_hw *hw;
498         struct clk_hw **hws;
499         u8 avpll_flags = 0;
500         int n, ret;
501
502         clk_data = kzalloc(struct_size(clk_data, hws, MAX_CLKS), GFP_KERNEL);
503         if (!clk_data) {
504                 of_node_put(parent_np);
505                 return;
506         }
507         clk_data->num = MAX_CLKS;
508         hws = clk_data->hws;
509
510         gbase = of_iomap(parent_np, 0);
511         of_node_put(parent_np);
512         if (!gbase)
513                 return;
514
515         /* overwrite default clock names with DT provided ones */
516         clk = of_clk_get_by_name(np, clk_names[REFCLK]);
517         if (!IS_ERR(clk)) {
518                 clk_names[REFCLK] = __clk_get_name(clk);
519                 clk_put(clk);
520         }
521
522         clk = of_clk_get_by_name(np, clk_names[VIDEO_EXT0]);
523         if (!IS_ERR(clk)) {
524                 clk_names[VIDEO_EXT0] = __clk_get_name(clk);
525                 clk_put(clk);
526         }
527
528         /* simple register PLLs */
529         ret = berlin2_pll_register(&bg2_pll_map, gbase + REG_SYSPLLCTL0,
530                                    clk_names[SYSPLL], clk_names[REFCLK], 0);
531         if (ret)
532                 goto bg2_fail;
533
534         ret = berlin2_pll_register(&bg2_pll_map, gbase + REG_MEMPLLCTL0,
535                                    clk_names[MEMPLL], clk_names[REFCLK], 0);
536         if (ret)
537                 goto bg2_fail;
538
539         ret = berlin2_pll_register(&bg2_pll_map, gbase + REG_CPUPLLCTL0,
540                                    clk_names[CPUPLL], clk_names[REFCLK], 0);
541         if (ret)
542                 goto bg2_fail;
543
544         if (of_device_is_compatible(np, "marvell,berlin2-global-register"))
545                 avpll_flags |= BERLIN2_AVPLL_SCRAMBLE_QUIRK;
546
547         /* audio/video VCOs */
548         ret = berlin2_avpll_vco_register(gbase + REG_AVPLLCTL0, "avpll_vcoA",
549                          clk_names[REFCLK], avpll_flags, 0);
550         if (ret)
551                 goto bg2_fail;
552
553         for (n = 0; n < 8; n++) {
554                 ret = berlin2_avpll_channel_register(gbase + REG_AVPLLCTL0,
555                              clk_names[AVPLL_A1 + n], n, "avpll_vcoA",
556                              avpll_flags, 0);
557                 if (ret)
558                         goto bg2_fail;
559         }
560
561         ret = berlin2_avpll_vco_register(gbase + REG_AVPLLCTL31, "avpll_vcoB",
562                                  clk_names[REFCLK], BERLIN2_AVPLL_BIT_QUIRK |
563                                  avpll_flags, 0);
564         if (ret)
565                 goto bg2_fail;
566
567         for (n = 0; n < 8; n++) {
568                 ret = berlin2_avpll_channel_register(gbase + REG_AVPLLCTL31,
569                              clk_names[AVPLL_B1 + n], n, "avpll_vcoB",
570                              BERLIN2_AVPLL_BIT_QUIRK | avpll_flags, 0);
571                 if (ret)
572                         goto bg2_fail;
573         }
574
575         /* reference clock bypass switches */
576         parent_names[0] = clk_names[SYSPLL];
577         parent_names[1] = clk_names[REFCLK];
578         hw = clk_hw_register_mux(NULL, "syspll_byp", parent_names, 2,
579                                0, gbase + REG_CLKSWITCH0, 0, 1, 0, &lock);
580         if (IS_ERR(hw))
581                 goto bg2_fail;
582         clk_names[SYSPLL] = clk_hw_get_name(hw);
583
584         parent_names[0] = clk_names[MEMPLL];
585         parent_names[1] = clk_names[REFCLK];
586         hw = clk_hw_register_mux(NULL, "mempll_byp", parent_names, 2,
587                                0, gbase + REG_CLKSWITCH0, 1, 1, 0, &lock);
588         if (IS_ERR(hw))
589                 goto bg2_fail;
590         clk_names[MEMPLL] = clk_hw_get_name(hw);
591
592         parent_names[0] = clk_names[CPUPLL];
593         parent_names[1] = clk_names[REFCLK];
594         hw = clk_hw_register_mux(NULL, "cpupll_byp", parent_names, 2,
595                                0, gbase + REG_CLKSWITCH0, 2, 1, 0, &lock);
596         if (IS_ERR(hw))
597                 goto bg2_fail;
598         clk_names[CPUPLL] = clk_hw_get_name(hw);
599
600         /* clock muxes */
601         parent_names[0] = clk_names[AVPLL_B3];
602         parent_names[1] = clk_names[AVPLL_A3];
603         hw = clk_hw_register_mux(NULL, clk_names[AUDIO1_PLL], parent_names, 2,
604                                0, gbase + REG_CLKSELECT2, 29, 1, 0, &lock);
605         if (IS_ERR(hw))
606                 goto bg2_fail;
607
608         parent_names[0] = clk_names[VIDEO0_PLL];
609         parent_names[1] = clk_names[VIDEO_EXT0];
610         hw = clk_hw_register_mux(NULL, clk_names[VIDEO0_IN], parent_names, 2,
611                                0, gbase + REG_CLKSELECT3, 4, 1, 0, &lock);
612         if (IS_ERR(hw))
613                 goto bg2_fail;
614
615         parent_names[0] = clk_names[VIDEO1_PLL];
616         parent_names[1] = clk_names[VIDEO_EXT0];
617         hw = clk_hw_register_mux(NULL, clk_names[VIDEO1_IN], parent_names, 2,
618                                0, gbase + REG_CLKSELECT3, 6, 1, 0, &lock);
619         if (IS_ERR(hw))
620                 goto bg2_fail;
621
622         parent_names[0] = clk_names[AVPLL_A2];
623         parent_names[1] = clk_names[AVPLL_B2];
624         hw = clk_hw_register_mux(NULL, clk_names[VIDEO1_PLL], parent_names, 2,
625                                0, gbase + REG_CLKSELECT3, 7, 1, 0, &lock);
626         if (IS_ERR(hw))
627                 goto bg2_fail;
628
629         parent_names[0] = clk_names[VIDEO2_PLL];
630         parent_names[1] = clk_names[VIDEO_EXT0];
631         hw = clk_hw_register_mux(NULL, clk_names[VIDEO2_IN], parent_names, 2,
632                                0, gbase + REG_CLKSELECT3, 9, 1, 0, &lock);
633         if (IS_ERR(hw))
634                 goto bg2_fail;
635
636         parent_names[0] = clk_names[AVPLL_B1];
637         parent_names[1] = clk_names[AVPLL_A5];
638         hw = clk_hw_register_mux(NULL, clk_names[VIDEO2_PLL], parent_names, 2,
639                                0, gbase + REG_CLKSELECT3, 10, 1, 0, &lock);
640         if (IS_ERR(hw))
641                 goto bg2_fail;
642
643         /* clock divider cells */
644         for (n = 0; n < ARRAY_SIZE(bg2_divs); n++) {
645                 const struct berlin2_div_data *dd = &bg2_divs[n];
646                 int k;
647
648                 for (k = 0; k < dd->num_parents; k++)
649                         parent_names[k] = clk_names[dd->parent_ids[k]];
650
651                 hws[CLKID_SYS + n] = berlin2_div_register(&dd->map, gbase,
652                                 dd->name, dd->div_flags, parent_names,
653                                 dd->num_parents, dd->flags, &lock);
654         }
655
656         /* clock gate cells */
657         for (n = 0; n < ARRAY_SIZE(bg2_gates); n++) {
658                 const struct berlin2_gate_data *gd = &bg2_gates[n];
659
660                 hws[CLKID_GETH0 + n] = clk_hw_register_gate(NULL, gd->name,
661                             gd->parent_name, gd->flags, gbase + REG_CLKENABLE,
662                             gd->bit_idx, 0, &lock);
663         }
664
665         /* twdclk is derived from cpu/3 */
666         hws[CLKID_TWD] =
667                 clk_hw_register_fixed_factor(NULL, "twd", "cpu", 0, 1, 3);
668
669         /* check for errors on leaf clocks */
670         for (n = 0; n < MAX_CLKS; n++) {
671                 if (!IS_ERR(hws[n]))
672                         continue;
673
674                 pr_err("%pOF: Unable to register leaf clock %d\n", np, n);
675                 goto bg2_fail;
676         }
677
678         /* register clk-provider */
679         of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_data);
680
681         return;
682
683 bg2_fail:
684         iounmap(gbase);
685 }
686 CLK_OF_DECLARE(berlin2_clk, "marvell,berlin2-clk",
687                berlin2_clock_setup);