Merge tag 'rtc-4.14' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux
[sfrench/cifs-2.6.git] / drivers / clk / berlin / bg2.c
1 /*
2  * Copyright (c) 2014 Marvell Technology Group Ltd.
3  *
4  * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
5  * Alexandre Belloni <alexandre.belloni@free-electrons.com>
6  *
7  * This program is free software; you can redistribute it and/or modify it
8  * under the terms and conditions of the GNU General Public License,
9  * version 2, as published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
14  * more details.
15  *
16  * You should have received a copy of the GNU General Public License along with
17  * this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <linux/clk.h>
21 #include <linux/clk-provider.h>
22 #include <linux/kernel.h>
23 #include <linux/of.h>
24 #include <linux/of_address.h>
25 #include <linux/slab.h>
26
27 #include <dt-bindings/clock/berlin2.h>
28
29 #include "berlin2-avpll.h"
30 #include "berlin2-div.h"
31 #include "berlin2-pll.h"
32 #include "common.h"
33
34 #define REG_PINMUX0             0x0000
35 #define REG_PINMUX1             0x0004
36 #define REG_SYSPLLCTL0          0x0014
37 #define REG_SYSPLLCTL4          0x0024
38 #define REG_MEMPLLCTL0          0x0028
39 #define REG_MEMPLLCTL4          0x0038
40 #define REG_CPUPLLCTL0          0x003c
41 #define REG_CPUPLLCTL4          0x004c
42 #define REG_AVPLLCTL0           0x0050
43 #define REG_AVPLLCTL31          0x00cc
44 #define REG_AVPLLCTL62          0x0148
45 #define REG_PLLSTATUS           0x014c
46 #define REG_CLKENABLE           0x0150
47 #define REG_CLKSELECT0          0x0154
48 #define REG_CLKSELECT1          0x0158
49 #define REG_CLKSELECT2          0x015c
50 #define REG_CLKSELECT3          0x0160
51 #define REG_CLKSWITCH0          0x0164
52 #define REG_CLKSWITCH1          0x0168
53 #define REG_RESET_TRIGGER       0x0178
54 #define REG_RESET_STATUS0       0x017c
55 #define REG_RESET_STATUS1       0x0180
56 #define REG_SW_GENERIC0         0x0184
57 #define REG_SW_GENERIC3         0x0190
58 #define REG_PRODUCTID           0x01cc
59 #define REG_PRODUCTID_EXT       0x01d0
60 #define REG_GFX3DCORE_CLKCTL    0x022c
61 #define REG_GFX3DSYS_CLKCTL     0x0230
62 #define REG_ARC_CLKCTL          0x0234
63 #define REG_VIP_CLKCTL          0x0238
64 #define REG_SDIO0XIN_CLKCTL     0x023c
65 #define REG_SDIO1XIN_CLKCTL     0x0240
66 #define REG_GFX3DEXTRA_CLKCTL   0x0244
67 #define REG_GFX3D_RESET         0x0248
68 #define REG_GC360_CLKCTL        0x024c
69 #define REG_SDIO_DLLMST_CLKCTL  0x0250
70
71 /*
72  * BG2/BG2CD SoCs have the following audio/video I/O units:
73  *
74  * audiohd: HDMI TX audio
75  * audio0:  7.1ch TX
76  * audio1:  2ch TX
77  * audio2:  2ch RX
78  * audio3:  SPDIF TX
79  * video0:  HDMI video
80  * video1:  Secondary video
81  * video2:  SD auxiliary video
82  *
83  * There are no external audio clocks (ACLKI0, ACLKI1) and
84  * only one external video clock (VCLKI0).
85  *
86  * Currently missing bits and pieces:
87  * - audio_fast_pll is unknown
88  * - audiohd_pll is unknown
89  * - video0_pll is unknown
90  * - audio[023], audiohd parent pll is assumed to be audio_fast_pll
91  *
92  */
93
94 #define MAX_CLKS 41
95 static struct clk_hw_onecell_data *clk_data;
96 static DEFINE_SPINLOCK(lock);
97 static void __iomem *gbase;
98
99 enum {
100         REFCLK, VIDEO_EXT0,
101         SYSPLL, MEMPLL, CPUPLL,
102         AVPLL_A1, AVPLL_A2, AVPLL_A3, AVPLL_A4,
103         AVPLL_A5, AVPLL_A6, AVPLL_A7, AVPLL_A8,
104         AVPLL_B1, AVPLL_B2, AVPLL_B3, AVPLL_B4,
105         AVPLL_B5, AVPLL_B6, AVPLL_B7, AVPLL_B8,
106         AUDIO1_PLL, AUDIO_FAST_PLL,
107         VIDEO0_PLL, VIDEO0_IN,
108         VIDEO1_PLL, VIDEO1_IN,
109         VIDEO2_PLL, VIDEO2_IN,
110 };
111
112 static const char *clk_names[] = {
113         [REFCLK]                = "refclk",
114         [VIDEO_EXT0]            = "video_ext0",
115         [SYSPLL]                = "syspll",
116         [MEMPLL]                = "mempll",
117         [CPUPLL]                = "cpupll",
118         [AVPLL_A1]              = "avpll_a1",
119         [AVPLL_A2]              = "avpll_a2",
120         [AVPLL_A3]              = "avpll_a3",
121         [AVPLL_A4]              = "avpll_a4",
122         [AVPLL_A5]              = "avpll_a5",
123         [AVPLL_A6]              = "avpll_a6",
124         [AVPLL_A7]              = "avpll_a7",
125         [AVPLL_A8]              = "avpll_a8",
126         [AVPLL_B1]              = "avpll_b1",
127         [AVPLL_B2]              = "avpll_b2",
128         [AVPLL_B3]              = "avpll_b3",
129         [AVPLL_B4]              = "avpll_b4",
130         [AVPLL_B5]              = "avpll_b5",
131         [AVPLL_B6]              = "avpll_b6",
132         [AVPLL_B7]              = "avpll_b7",
133         [AVPLL_B8]              = "avpll_b8",
134         [AUDIO1_PLL]            = "audio1_pll",
135         [AUDIO_FAST_PLL]        = "audio_fast_pll",
136         [VIDEO0_PLL]            = "video0_pll",
137         [VIDEO0_IN]             = "video0_in",
138         [VIDEO1_PLL]            = "video1_pll",
139         [VIDEO1_IN]             = "video1_in",
140         [VIDEO2_PLL]            = "video2_pll",
141         [VIDEO2_IN]             = "video2_in",
142 };
143
144 static const struct berlin2_pll_map bg2_pll_map __initconst = {
145         .vcodiv         = {10, 15, 20, 25, 30, 40, 50, 60, 80},
146         .mult           = 10,
147         .fbdiv_shift    = 6,
148         .rfdiv_shift    = 1,
149         .divsel_shift   = 7,
150 };
151
152 static const u8 default_parent_ids[] = {
153         SYSPLL, AVPLL_B4, AVPLL_A5, AVPLL_B6, AVPLL_B7, SYSPLL
154 };
155
156 static const struct berlin2_div_data bg2_divs[] __initconst = {
157         {
158                 .name = "sys",
159                 .parent_ids = (const u8 []){
160                         SYSPLL, AVPLL_B4, AVPLL_B5, AVPLL_B6, AVPLL_B7, SYSPLL
161                 },
162                 .num_parents = 6,
163                 .map = {
164                         BERLIN2_DIV_GATE(REG_CLKENABLE, 0),
165                         BERLIN2_PLL_SELECT(REG_CLKSELECT0, 0),
166                         BERLIN2_DIV_SELECT(REG_CLKSELECT0, 3),
167                         BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 3),
168                         BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 4),
169                         BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 5),
170                 },
171                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
172                 .flags = CLK_IGNORE_UNUSED,
173         },
174         {
175                 .name = "cpu",
176                 .parent_ids = (const u8 []){
177                         CPUPLL, MEMPLL, MEMPLL, MEMPLL, MEMPLL
178                 },
179                 .num_parents = 5,
180                 .map = {
181                         BERLIN2_PLL_SELECT(REG_CLKSELECT0, 6),
182                         BERLIN2_DIV_SELECT(REG_CLKSELECT0, 9),
183                         BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 6),
184                         BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 7),
185                         BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 8),
186                 },
187                 .div_flags = BERLIN2_DIV_HAS_MUX,
188                 .flags = 0,
189         },
190         {
191                 .name = "drmfigo",
192                 .parent_ids = default_parent_ids,
193                 .num_parents = ARRAY_SIZE(default_parent_ids),
194                 .map = {
195                         BERLIN2_DIV_GATE(REG_CLKENABLE, 16),
196                         BERLIN2_PLL_SELECT(REG_CLKSELECT0, 17),
197                         BERLIN2_DIV_SELECT(REG_CLKSELECT0, 20),
198                         BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 12),
199                         BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 13),
200                         BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 14),
201                 },
202                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
203                 .flags = 0,
204         },
205         {
206                 .name = "cfg",
207                 .parent_ids = default_parent_ids,
208                 .num_parents = ARRAY_SIZE(default_parent_ids),
209                 .map = {
210                         BERLIN2_DIV_GATE(REG_CLKENABLE, 1),
211                         BERLIN2_PLL_SELECT(REG_CLKSELECT0, 23),
212                         BERLIN2_DIV_SELECT(REG_CLKSELECT0, 26),
213                         BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 15),
214                         BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 16),
215                         BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 17),
216                 },
217                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
218                 .flags = 0,
219         },
220         {
221                 .name = "gfx",
222                 .parent_ids = default_parent_ids,
223                 .num_parents = ARRAY_SIZE(default_parent_ids),
224                 .map = {
225                         BERLIN2_DIV_GATE(REG_CLKENABLE, 4),
226                         BERLIN2_PLL_SELECT(REG_CLKSELECT0, 29),
227                         BERLIN2_DIV_SELECT(REG_CLKSELECT1, 0),
228                         BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 18),
229                         BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 19),
230                         BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 20),
231                 },
232                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
233                 .flags = 0,
234         },
235         {
236                 .name = "zsp",
237                 .parent_ids = default_parent_ids,
238                 .num_parents = ARRAY_SIZE(default_parent_ids),
239                 .map = {
240                         BERLIN2_DIV_GATE(REG_CLKENABLE, 5),
241                         BERLIN2_PLL_SELECT(REG_CLKSELECT1, 3),
242                         BERLIN2_DIV_SELECT(REG_CLKSELECT1, 6),
243                         BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 21),
244                         BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 22),
245                         BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 23),
246                 },
247                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
248                 .flags = 0,
249         },
250         {
251                 .name = "perif",
252                 .parent_ids = default_parent_ids,
253                 .num_parents = ARRAY_SIZE(default_parent_ids),
254                 .map = {
255                         BERLIN2_DIV_GATE(REG_CLKENABLE, 6),
256                         BERLIN2_PLL_SELECT(REG_CLKSELECT1, 9),
257                         BERLIN2_DIV_SELECT(REG_CLKSELECT1, 12),
258                         BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 24),
259                         BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 25),
260                         BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 26),
261                 },
262                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
263                 .flags = CLK_IGNORE_UNUSED,
264         },
265         {
266                 .name = "pcube",
267                 .parent_ids = default_parent_ids,
268                 .num_parents = ARRAY_SIZE(default_parent_ids),
269                 .map = {
270                         BERLIN2_DIV_GATE(REG_CLKENABLE, 2),
271                         BERLIN2_PLL_SELECT(REG_CLKSELECT1, 15),
272                         BERLIN2_DIV_SELECT(REG_CLKSELECT1, 18),
273                         BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 27),
274                         BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 28),
275                         BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 29),
276                 },
277                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
278                 .flags = 0,
279         },
280         {
281                 .name = "vscope",
282                 .parent_ids = default_parent_ids,
283                 .num_parents = ARRAY_SIZE(default_parent_ids),
284                 .map = {
285                         BERLIN2_DIV_GATE(REG_CLKENABLE, 3),
286                         BERLIN2_PLL_SELECT(REG_CLKSELECT1, 21),
287                         BERLIN2_DIV_SELECT(REG_CLKSELECT1, 24),
288                         BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 30),
289                         BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 31),
290                         BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 0),
291                 },
292                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
293                 .flags = 0,
294         },
295         {
296                 .name = "nfc_ecc",
297                 .parent_ids = default_parent_ids,
298                 .num_parents = ARRAY_SIZE(default_parent_ids),
299                 .map = {
300                         BERLIN2_DIV_GATE(REG_CLKENABLE, 18),
301                         BERLIN2_PLL_SELECT(REG_CLKSELECT1, 27),
302                         BERLIN2_DIV_SELECT(REG_CLKSELECT2, 0),
303                         BERLIN2_PLL_SWITCH(REG_CLKSWITCH1, 1),
304                         BERLIN2_DIV_SWITCH(REG_CLKSWITCH1, 2),
305                         BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 3),
306                 },
307                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
308                 .flags = 0,
309         },
310         {
311                 .name = "vpp",
312                 .parent_ids = default_parent_ids,
313                 .num_parents = ARRAY_SIZE(default_parent_ids),
314                 .map = {
315                         BERLIN2_DIV_GATE(REG_CLKENABLE, 21),
316                         BERLIN2_PLL_SELECT(REG_CLKSELECT2, 3),
317                         BERLIN2_DIV_SELECT(REG_CLKSELECT2, 6),
318                         BERLIN2_PLL_SWITCH(REG_CLKSWITCH1, 4),
319                         BERLIN2_DIV_SWITCH(REG_CLKSWITCH1, 5),
320                         BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 6),
321                 },
322                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
323                 .flags = 0,
324         },
325         {
326                 .name = "app",
327                 .parent_ids = default_parent_ids,
328                 .num_parents = ARRAY_SIZE(default_parent_ids),
329                 .map = {
330                         BERLIN2_DIV_GATE(REG_CLKENABLE, 20),
331                         BERLIN2_PLL_SELECT(REG_CLKSELECT2, 9),
332                         BERLIN2_DIV_SELECT(REG_CLKSELECT2, 12),
333                         BERLIN2_PLL_SWITCH(REG_CLKSWITCH1, 7),
334                         BERLIN2_DIV_SWITCH(REG_CLKSWITCH1, 8),
335                         BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 9),
336                 },
337                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
338                 .flags = 0,
339         },
340         {
341                 .name = "audio0",
342                 .parent_ids = (const u8 []){ AUDIO_FAST_PLL },
343                 .num_parents = 1,
344                 .map = {
345                         BERLIN2_DIV_GATE(REG_CLKENABLE, 22),
346                         BERLIN2_DIV_SELECT(REG_CLKSELECT2, 17),
347                         BERLIN2_DIV_SWITCH(REG_CLKSWITCH1, 10),
348                         BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 11),
349                 },
350                 .div_flags = BERLIN2_DIV_HAS_GATE,
351                 .flags = 0,
352         },
353         {
354                 .name = "audio2",
355                 .parent_ids = (const u8 []){ AUDIO_FAST_PLL },
356                 .num_parents = 1,
357                 .map = {
358                         BERLIN2_DIV_GATE(REG_CLKENABLE, 24),
359                         BERLIN2_DIV_SELECT(REG_CLKSELECT2, 20),
360                         BERLIN2_DIV_SWITCH(REG_CLKSWITCH1, 14),
361                         BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 15),
362                 },
363                 .div_flags = BERLIN2_DIV_HAS_GATE,
364                 .flags = 0,
365         },
366         {
367                 .name = "audio3",
368                 .parent_ids = (const u8 []){ AUDIO_FAST_PLL },
369                 .num_parents = 1,
370                 .map = {
371                         BERLIN2_DIV_GATE(REG_CLKENABLE, 25),
372                         BERLIN2_DIV_SELECT(REG_CLKSELECT2, 23),
373                         BERLIN2_DIV_SWITCH(REG_CLKSWITCH1, 16),
374                         BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 17),
375                 },
376                 .div_flags = BERLIN2_DIV_HAS_GATE,
377                 .flags = 0,
378         },
379         {
380                 .name = "audio1",
381                 .parent_ids = (const u8 []){ AUDIO1_PLL },
382                 .num_parents = 1,
383                 .map = {
384                         BERLIN2_DIV_GATE(REG_CLKENABLE, 23),
385                         BERLIN2_DIV_SELECT(REG_CLKSELECT3, 0),
386                         BERLIN2_DIV_SWITCH(REG_CLKSWITCH1, 12),
387                         BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 13),
388                 },
389                 .div_flags = BERLIN2_DIV_HAS_GATE,
390                 .flags = 0,
391         },
392         {
393                 .name = "gfx3d_core",
394                 .parent_ids = default_parent_ids,
395                 .num_parents = ARRAY_SIZE(default_parent_ids),
396                 .map = {
397                         BERLIN2_SINGLE_DIV(REG_GFX3DCORE_CLKCTL),
398                 },
399                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
400                 .flags = 0,
401         },
402         {
403                 .name = "gfx3d_sys",
404                 .parent_ids = default_parent_ids,
405                 .num_parents = ARRAY_SIZE(default_parent_ids),
406                 .map = {
407                         BERLIN2_SINGLE_DIV(REG_GFX3DSYS_CLKCTL),
408                 },
409                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
410                 .flags = 0,
411         },
412         {
413                 .name = "arc",
414                 .parent_ids = default_parent_ids,
415                 .num_parents = ARRAY_SIZE(default_parent_ids),
416                 .map = {
417                         BERLIN2_SINGLE_DIV(REG_ARC_CLKCTL),
418                 },
419                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
420                 .flags = 0,
421         },
422         {
423                 .name = "vip",
424                 .parent_ids = default_parent_ids,
425                 .num_parents = ARRAY_SIZE(default_parent_ids),
426                 .map = {
427                         BERLIN2_SINGLE_DIV(REG_VIP_CLKCTL),
428                 },
429                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
430                 .flags = 0,
431         },
432         {
433                 .name = "sdio0xin",
434                 .parent_ids = default_parent_ids,
435                 .num_parents = ARRAY_SIZE(default_parent_ids),
436                 .map = {
437                         BERLIN2_SINGLE_DIV(REG_SDIO0XIN_CLKCTL),
438                 },
439                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
440                 .flags = 0,
441         },
442         {
443                 .name = "sdio1xin",
444                 .parent_ids = default_parent_ids,
445                 .num_parents = ARRAY_SIZE(default_parent_ids),
446                 .map = {
447                         BERLIN2_SINGLE_DIV(REG_SDIO1XIN_CLKCTL),
448                 },
449                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
450                 .flags = 0,
451         },
452         {
453                 .name = "gfx3d_extra",
454                 .parent_ids = default_parent_ids,
455                 .num_parents = ARRAY_SIZE(default_parent_ids),
456                 .map = {
457                         BERLIN2_SINGLE_DIV(REG_GFX3DEXTRA_CLKCTL),
458                 },
459                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
460                 .flags = 0,
461         },
462         {
463                 .name = "gc360",
464                 .parent_ids = default_parent_ids,
465                 .num_parents = ARRAY_SIZE(default_parent_ids),
466                 .map = {
467                         BERLIN2_SINGLE_DIV(REG_GC360_CLKCTL),
468                 },
469                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
470                 .flags = 0,
471         },
472         {
473                 .name = "sdio_dllmst",
474                 .parent_ids = default_parent_ids,
475                 .num_parents = ARRAY_SIZE(default_parent_ids),
476                 .map = {
477                         BERLIN2_SINGLE_DIV(REG_SDIO_DLLMST_CLKCTL),
478                 },
479                 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
480                 .flags = 0,
481         },
482 };
483
484 static const struct berlin2_gate_data bg2_gates[] __initconst = {
485         { "geth0",      "perif",        7 },
486         { "geth1",      "perif",        8 },
487         { "sata",       "perif",        9 },
488         { "ahbapb",     "perif",        10, CLK_IGNORE_UNUSED },
489         { "usb0",       "perif",        11 },
490         { "usb1",       "perif",        12 },
491         { "pbridge",    "perif",        13, CLK_IGNORE_UNUSED },
492         { "sdio0",      "perif",        14 },
493         { "sdio1",      "perif",        15 },
494         { "nfc",        "perif",        17 },
495         { "smemc",      "perif",        19 },
496         { "audiohd",    "audiohd_pll",  26 },
497         { "video0",     "video0_in",    27 },
498         { "video1",     "video1_in",    28 },
499         { "video2",     "video2_in",    29 },
500 };
501
502 static void __init berlin2_clock_setup(struct device_node *np)
503 {
504         struct device_node *parent_np = of_get_parent(np);
505         const char *parent_names[9];
506         struct clk *clk;
507         struct clk_hw *hw;
508         struct clk_hw **hws;
509         u8 avpll_flags = 0;
510         int n, ret;
511
512         clk_data = kzalloc(sizeof(*clk_data) +
513                            sizeof(*clk_data->hws) * MAX_CLKS, GFP_KERNEL);
514         if (!clk_data)
515                 return;
516         clk_data->num = MAX_CLKS;
517         hws = clk_data->hws;
518
519         gbase = of_iomap(parent_np, 0);
520         if (!gbase)
521                 return;
522
523         /* overwrite default clock names with DT provided ones */
524         clk = of_clk_get_by_name(np, clk_names[REFCLK]);
525         if (!IS_ERR(clk)) {
526                 clk_names[REFCLK] = __clk_get_name(clk);
527                 clk_put(clk);
528         }
529
530         clk = of_clk_get_by_name(np, clk_names[VIDEO_EXT0]);
531         if (!IS_ERR(clk)) {
532                 clk_names[VIDEO_EXT0] = __clk_get_name(clk);
533                 clk_put(clk);
534         }
535
536         /* simple register PLLs */
537         ret = berlin2_pll_register(&bg2_pll_map, gbase + REG_SYSPLLCTL0,
538                                    clk_names[SYSPLL], clk_names[REFCLK], 0);
539         if (ret)
540                 goto bg2_fail;
541
542         ret = berlin2_pll_register(&bg2_pll_map, gbase + REG_MEMPLLCTL0,
543                                    clk_names[MEMPLL], clk_names[REFCLK], 0);
544         if (ret)
545                 goto bg2_fail;
546
547         ret = berlin2_pll_register(&bg2_pll_map, gbase + REG_CPUPLLCTL0,
548                                    clk_names[CPUPLL], clk_names[REFCLK], 0);
549         if (ret)
550                 goto bg2_fail;
551
552         if (of_device_is_compatible(np, "marvell,berlin2-global-register"))
553                 avpll_flags |= BERLIN2_AVPLL_SCRAMBLE_QUIRK;
554
555         /* audio/video VCOs */
556         ret = berlin2_avpll_vco_register(gbase + REG_AVPLLCTL0, "avpll_vcoA",
557                          clk_names[REFCLK], avpll_flags, 0);
558         if (ret)
559                 goto bg2_fail;
560
561         for (n = 0; n < 8; n++) {
562                 ret = berlin2_avpll_channel_register(gbase + REG_AVPLLCTL0,
563                              clk_names[AVPLL_A1 + n], n, "avpll_vcoA",
564                              avpll_flags, 0);
565                 if (ret)
566                         goto bg2_fail;
567         }
568
569         ret = berlin2_avpll_vco_register(gbase + REG_AVPLLCTL31, "avpll_vcoB",
570                                  clk_names[REFCLK], BERLIN2_AVPLL_BIT_QUIRK |
571                                  avpll_flags, 0);
572         if (ret)
573                 goto bg2_fail;
574
575         for (n = 0; n < 8; n++) {
576                 ret = berlin2_avpll_channel_register(gbase + REG_AVPLLCTL31,
577                              clk_names[AVPLL_B1 + n], n, "avpll_vcoB",
578                              BERLIN2_AVPLL_BIT_QUIRK | avpll_flags, 0);
579                 if (ret)
580                         goto bg2_fail;
581         }
582
583         /* reference clock bypass switches */
584         parent_names[0] = clk_names[SYSPLL];
585         parent_names[1] = clk_names[REFCLK];
586         hw = clk_hw_register_mux(NULL, "syspll_byp", parent_names, 2,
587                                0, gbase + REG_CLKSWITCH0, 0, 1, 0, &lock);
588         if (IS_ERR(hw))
589                 goto bg2_fail;
590         clk_names[SYSPLL] = clk_hw_get_name(hw);
591
592         parent_names[0] = clk_names[MEMPLL];
593         parent_names[1] = clk_names[REFCLK];
594         hw = clk_hw_register_mux(NULL, "mempll_byp", parent_names, 2,
595                                0, gbase + REG_CLKSWITCH0, 1, 1, 0, &lock);
596         if (IS_ERR(hw))
597                 goto bg2_fail;
598         clk_names[MEMPLL] = clk_hw_get_name(hw);
599
600         parent_names[0] = clk_names[CPUPLL];
601         parent_names[1] = clk_names[REFCLK];
602         hw = clk_hw_register_mux(NULL, "cpupll_byp", parent_names, 2,
603                                0, gbase + REG_CLKSWITCH0, 2, 1, 0, &lock);
604         if (IS_ERR(hw))
605                 goto bg2_fail;
606         clk_names[CPUPLL] = clk_hw_get_name(hw);
607
608         /* clock muxes */
609         parent_names[0] = clk_names[AVPLL_B3];
610         parent_names[1] = clk_names[AVPLL_A3];
611         hw = clk_hw_register_mux(NULL, clk_names[AUDIO1_PLL], parent_names, 2,
612                                0, gbase + REG_CLKSELECT2, 29, 1, 0, &lock);
613         if (IS_ERR(hw))
614                 goto bg2_fail;
615
616         parent_names[0] = clk_names[VIDEO0_PLL];
617         parent_names[1] = clk_names[VIDEO_EXT0];
618         hw = clk_hw_register_mux(NULL, clk_names[VIDEO0_IN], parent_names, 2,
619                                0, gbase + REG_CLKSELECT3, 4, 1, 0, &lock);
620         if (IS_ERR(hw))
621                 goto bg2_fail;
622
623         parent_names[0] = clk_names[VIDEO1_PLL];
624         parent_names[1] = clk_names[VIDEO_EXT0];
625         hw = clk_hw_register_mux(NULL, clk_names[VIDEO1_IN], parent_names, 2,
626                                0, gbase + REG_CLKSELECT3, 6, 1, 0, &lock);
627         if (IS_ERR(hw))
628                 goto bg2_fail;
629
630         parent_names[0] = clk_names[AVPLL_A2];
631         parent_names[1] = clk_names[AVPLL_B2];
632         hw = clk_hw_register_mux(NULL, clk_names[VIDEO1_PLL], parent_names, 2,
633                                0, gbase + REG_CLKSELECT3, 7, 1, 0, &lock);
634         if (IS_ERR(hw))
635                 goto bg2_fail;
636
637         parent_names[0] = clk_names[VIDEO2_PLL];
638         parent_names[1] = clk_names[VIDEO_EXT0];
639         hw = clk_hw_register_mux(NULL, clk_names[VIDEO2_IN], parent_names, 2,
640                                0, gbase + REG_CLKSELECT3, 9, 1, 0, &lock);
641         if (IS_ERR(hw))
642                 goto bg2_fail;
643
644         parent_names[0] = clk_names[AVPLL_B1];
645         parent_names[1] = clk_names[AVPLL_A5];
646         hw = clk_hw_register_mux(NULL, clk_names[VIDEO2_PLL], parent_names, 2,
647                                0, gbase + REG_CLKSELECT3, 10, 1, 0, &lock);
648         if (IS_ERR(hw))
649                 goto bg2_fail;
650
651         /* clock divider cells */
652         for (n = 0; n < ARRAY_SIZE(bg2_divs); n++) {
653                 const struct berlin2_div_data *dd = &bg2_divs[n];
654                 int k;
655
656                 for (k = 0; k < dd->num_parents; k++)
657                         parent_names[k] = clk_names[dd->parent_ids[k]];
658
659                 hws[CLKID_SYS + n] = berlin2_div_register(&dd->map, gbase,
660                                 dd->name, dd->div_flags, parent_names,
661                                 dd->num_parents, dd->flags, &lock);
662         }
663
664         /* clock gate cells */
665         for (n = 0; n < ARRAY_SIZE(bg2_gates); n++) {
666                 const struct berlin2_gate_data *gd = &bg2_gates[n];
667
668                 hws[CLKID_GETH0 + n] = clk_hw_register_gate(NULL, gd->name,
669                             gd->parent_name, gd->flags, gbase + REG_CLKENABLE,
670                             gd->bit_idx, 0, &lock);
671         }
672
673         /* twdclk is derived from cpu/3 */
674         hws[CLKID_TWD] =
675                 clk_hw_register_fixed_factor(NULL, "twd", "cpu", 0, 1, 3);
676
677         /* check for errors on leaf clocks */
678         for (n = 0; n < MAX_CLKS; n++) {
679                 if (!IS_ERR(hws[n]))
680                         continue;
681
682                 pr_err("%s: Unable to register leaf clock %d\n",
683                        np->full_name, n);
684                 goto bg2_fail;
685         }
686
687         /* register clk-provider */
688         of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_data);
689
690         return;
691
692 bg2_fail:
693         iounmap(gbase);
694 }
695 CLK_OF_DECLARE(berlin2_clk, "marvell,berlin2-clk",
696                berlin2_clock_setup);