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 
berlin2_clock_setup(struct device_node * np)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);
687