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