clk: baikal-t1: Convert to platform device driver
[platform/kernel/linux-starfive.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                 return;
505         clk_data->num = MAX_CLKS;
506         hws = clk_data->hws;
507
508         gbase = of_iomap(parent_np, 0);
509         if (!gbase)
510                 return;
511
512         /* overwrite default clock names with DT provided ones */
513         clk = of_clk_get_by_name(np, clk_names[REFCLK]);
514         if (!IS_ERR(clk)) {
515                 clk_names[REFCLK] = __clk_get_name(clk);
516                 clk_put(clk);
517         }
518
519         clk = of_clk_get_by_name(np, clk_names[VIDEO_EXT0]);
520         if (!IS_ERR(clk)) {
521                 clk_names[VIDEO_EXT0] = __clk_get_name(clk);
522                 clk_put(clk);
523         }
524
525         /* simple register PLLs */
526         ret = berlin2_pll_register(&bg2_pll_map, gbase + REG_SYSPLLCTL0,
527                                    clk_names[SYSPLL], clk_names[REFCLK], 0);
528         if (ret)
529                 goto bg2_fail;
530
531         ret = berlin2_pll_register(&bg2_pll_map, gbase + REG_MEMPLLCTL0,
532                                    clk_names[MEMPLL], clk_names[REFCLK], 0);
533         if (ret)
534                 goto bg2_fail;
535
536         ret = berlin2_pll_register(&bg2_pll_map, gbase + REG_CPUPLLCTL0,
537                                    clk_names[CPUPLL], clk_names[REFCLK], 0);
538         if (ret)
539                 goto bg2_fail;
540
541         if (of_device_is_compatible(np, "marvell,berlin2-global-register"))
542                 avpll_flags |= BERLIN2_AVPLL_SCRAMBLE_QUIRK;
543
544         /* audio/video VCOs */
545         ret = berlin2_avpll_vco_register(gbase + REG_AVPLLCTL0, "avpll_vcoA",
546                          clk_names[REFCLK], avpll_flags, 0);
547         if (ret)
548                 goto bg2_fail;
549
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",
553                              avpll_flags, 0);
554                 if (ret)
555                         goto bg2_fail;
556         }
557
558         ret = berlin2_avpll_vco_register(gbase + REG_AVPLLCTL31, "avpll_vcoB",
559                                  clk_names[REFCLK], BERLIN2_AVPLL_BIT_QUIRK |
560                                  avpll_flags, 0);
561         if (ret)
562                 goto bg2_fail;
563
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);
568                 if (ret)
569                         goto bg2_fail;
570         }
571
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);
577         if (IS_ERR(hw))
578                 goto bg2_fail;
579         clk_names[SYSPLL] = clk_hw_get_name(hw);
580
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);
585         if (IS_ERR(hw))
586                 goto bg2_fail;
587         clk_names[MEMPLL] = clk_hw_get_name(hw);
588
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);
593         if (IS_ERR(hw))
594                 goto bg2_fail;
595         clk_names[CPUPLL] = clk_hw_get_name(hw);
596
597         /* clock muxes */
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);
602         if (IS_ERR(hw))
603                 goto bg2_fail;
604
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);
609         if (IS_ERR(hw))
610                 goto bg2_fail;
611
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);
616         if (IS_ERR(hw))
617                 goto bg2_fail;
618
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);
623         if (IS_ERR(hw))
624                 goto bg2_fail;
625
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);
630         if (IS_ERR(hw))
631                 goto bg2_fail;
632
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);
637         if (IS_ERR(hw))
638                 goto bg2_fail;
639
640         /* clock divider cells */
641         for (n = 0; n < ARRAY_SIZE(bg2_divs); n++) {
642                 const struct berlin2_div_data *dd = &bg2_divs[n];
643                 int k;
644
645                 for (k = 0; k < dd->num_parents; k++)
646                         parent_names[k] = clk_names[dd->parent_ids[k]];
647
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);
651         }
652
653         /* clock gate cells */
654         for (n = 0; n < ARRAY_SIZE(bg2_gates); n++) {
655                 const struct berlin2_gate_data *gd = &bg2_gates[n];
656
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);
660         }
661
662         /* twdclk is derived from cpu/3 */
663         hws[CLKID_TWD] =
664                 clk_hw_register_fixed_factor(NULL, "twd", "cpu", 0, 1, 3);
665
666         /* check for errors on leaf clocks */
667         for (n = 0; n < MAX_CLKS; n++) {
668                 if (!IS_ERR(hws[n]))
669                         continue;
670
671                 pr_err("%pOF: Unable to register leaf clock %d\n", np, n);
672                 goto bg2_fail;
673         }
674
675         /* register clk-provider */
676         of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_data);
677
678         return;
679
680 bg2_fail:
681         iounmap(gbase);
682 }
683 CLK_OF_DECLARE(berlin2_clk, "marvell,berlin2-clk",
684                berlin2_clock_setup);