xref: /openbmc/linux/drivers/clk/berlin/bg2.c (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
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  
berlin2_clock_setup(struct device_node * np)492  static void __init berlin2_clock_setup(struct device_node *np)
493  {
494  	struct device_node *parent_np = of_get_parent(np);
495  	const char *parent_names[9];
496  	struct clk *clk;
497  	struct clk_hw *hw;
498  	struct clk_hw **hws;
499  	u8 avpll_flags = 0;
500  	int n, ret;
501  
502  	clk_data = kzalloc(struct_size(clk_data, hws, MAX_CLKS), GFP_KERNEL);
503  	if (!clk_data) {
504  		of_node_put(parent_np);
505  		return;
506  	}
507  	clk_data->num = MAX_CLKS;
508  	hws = clk_data->hws;
509  
510  	gbase = of_iomap(parent_np, 0);
511  	of_node_put(parent_np);
512  	if (!gbase)
513  		return;
514  
515  	/* overwrite default clock names with DT provided ones */
516  	clk = of_clk_get_by_name(np, clk_names[REFCLK]);
517  	if (!IS_ERR(clk)) {
518  		clk_names[REFCLK] = __clk_get_name(clk);
519  		clk_put(clk);
520  	}
521  
522  	clk = of_clk_get_by_name(np, clk_names[VIDEO_EXT0]);
523  	if (!IS_ERR(clk)) {
524  		clk_names[VIDEO_EXT0] = __clk_get_name(clk);
525  		clk_put(clk);
526  	}
527  
528  	/* simple register PLLs */
529  	ret = berlin2_pll_register(&bg2_pll_map, gbase + REG_SYSPLLCTL0,
530  				   clk_names[SYSPLL], clk_names[REFCLK], 0);
531  	if (ret)
532  		goto bg2_fail;
533  
534  	ret = berlin2_pll_register(&bg2_pll_map, gbase + REG_MEMPLLCTL0,
535  				   clk_names[MEMPLL], clk_names[REFCLK], 0);
536  	if (ret)
537  		goto bg2_fail;
538  
539  	ret = berlin2_pll_register(&bg2_pll_map, gbase + REG_CPUPLLCTL0,
540  				   clk_names[CPUPLL], clk_names[REFCLK], 0);
541  	if (ret)
542  		goto bg2_fail;
543  
544  	if (of_device_is_compatible(np, "marvell,berlin2-global-register"))
545  		avpll_flags |= BERLIN2_AVPLL_SCRAMBLE_QUIRK;
546  
547  	/* audio/video VCOs */
548  	ret = berlin2_avpll_vco_register(gbase + REG_AVPLLCTL0, "avpll_vcoA",
549  			 clk_names[REFCLK], avpll_flags, 0);
550  	if (ret)
551  		goto bg2_fail;
552  
553  	for (n = 0; n < 8; n++) {
554  		ret = berlin2_avpll_channel_register(gbase + REG_AVPLLCTL0,
555  			     clk_names[AVPLL_A1 + n], n, "avpll_vcoA",
556  			     avpll_flags, 0);
557  		if (ret)
558  			goto bg2_fail;
559  	}
560  
561  	ret = berlin2_avpll_vco_register(gbase + REG_AVPLLCTL31, "avpll_vcoB",
562  				 clk_names[REFCLK], BERLIN2_AVPLL_BIT_QUIRK |
563  				 avpll_flags, 0);
564  	if (ret)
565  		goto bg2_fail;
566  
567  	for (n = 0; n < 8; n++) {
568  		ret = berlin2_avpll_channel_register(gbase + REG_AVPLLCTL31,
569  			     clk_names[AVPLL_B1 + n], n, "avpll_vcoB",
570  			     BERLIN2_AVPLL_BIT_QUIRK | avpll_flags, 0);
571  		if (ret)
572  			goto bg2_fail;
573  	}
574  
575  	/* reference clock bypass switches */
576  	parent_names[0] = clk_names[SYSPLL];
577  	parent_names[1] = clk_names[REFCLK];
578  	hw = clk_hw_register_mux(NULL, "syspll_byp", parent_names, 2,
579  			       0, gbase + REG_CLKSWITCH0, 0, 1, 0, &lock);
580  	if (IS_ERR(hw))
581  		goto bg2_fail;
582  	clk_names[SYSPLL] = clk_hw_get_name(hw);
583  
584  	parent_names[0] = clk_names[MEMPLL];
585  	parent_names[1] = clk_names[REFCLK];
586  	hw = clk_hw_register_mux(NULL, "mempll_byp", parent_names, 2,
587  			       0, gbase + REG_CLKSWITCH0, 1, 1, 0, &lock);
588  	if (IS_ERR(hw))
589  		goto bg2_fail;
590  	clk_names[MEMPLL] = clk_hw_get_name(hw);
591  
592  	parent_names[0] = clk_names[CPUPLL];
593  	parent_names[1] = clk_names[REFCLK];
594  	hw = clk_hw_register_mux(NULL, "cpupll_byp", parent_names, 2,
595  			       0, gbase + REG_CLKSWITCH0, 2, 1, 0, &lock);
596  	if (IS_ERR(hw))
597  		goto bg2_fail;
598  	clk_names[CPUPLL] = clk_hw_get_name(hw);
599  
600  	/* clock muxes */
601  	parent_names[0] = clk_names[AVPLL_B3];
602  	parent_names[1] = clk_names[AVPLL_A3];
603  	hw = clk_hw_register_mux(NULL, clk_names[AUDIO1_PLL], parent_names, 2,
604  			       0, gbase + REG_CLKSELECT2, 29, 1, 0, &lock);
605  	if (IS_ERR(hw))
606  		goto bg2_fail;
607  
608  	parent_names[0] = clk_names[VIDEO0_PLL];
609  	parent_names[1] = clk_names[VIDEO_EXT0];
610  	hw = clk_hw_register_mux(NULL, clk_names[VIDEO0_IN], parent_names, 2,
611  			       0, gbase + REG_CLKSELECT3, 4, 1, 0, &lock);
612  	if (IS_ERR(hw))
613  		goto bg2_fail;
614  
615  	parent_names[0] = clk_names[VIDEO1_PLL];
616  	parent_names[1] = clk_names[VIDEO_EXT0];
617  	hw = clk_hw_register_mux(NULL, clk_names[VIDEO1_IN], parent_names, 2,
618  			       0, gbase + REG_CLKSELECT3, 6, 1, 0, &lock);
619  	if (IS_ERR(hw))
620  		goto bg2_fail;
621  
622  	parent_names[0] = clk_names[AVPLL_A2];
623  	parent_names[1] = clk_names[AVPLL_B2];
624  	hw = clk_hw_register_mux(NULL, clk_names[VIDEO1_PLL], parent_names, 2,
625  			       0, gbase + REG_CLKSELECT3, 7, 1, 0, &lock);
626  	if (IS_ERR(hw))
627  		goto bg2_fail;
628  
629  	parent_names[0] = clk_names[VIDEO2_PLL];
630  	parent_names[1] = clk_names[VIDEO_EXT0];
631  	hw = clk_hw_register_mux(NULL, clk_names[VIDEO2_IN], parent_names, 2,
632  			       0, gbase + REG_CLKSELECT3, 9, 1, 0, &lock);
633  	if (IS_ERR(hw))
634  		goto bg2_fail;
635  
636  	parent_names[0] = clk_names[AVPLL_B1];
637  	parent_names[1] = clk_names[AVPLL_A5];
638  	hw = clk_hw_register_mux(NULL, clk_names[VIDEO2_PLL], parent_names, 2,
639  			       0, gbase + REG_CLKSELECT3, 10, 1, 0, &lock);
640  	if (IS_ERR(hw))
641  		goto bg2_fail;
642  
643  	/* clock divider cells */
644  	for (n = 0; n < ARRAY_SIZE(bg2_divs); n++) {
645  		const struct berlin2_div_data *dd = &bg2_divs[n];
646  		int k;
647  
648  		for (k = 0; k < dd->num_parents; k++)
649  			parent_names[k] = clk_names[dd->parent_ids[k]];
650  
651  		hws[CLKID_SYS + n] = berlin2_div_register(&dd->map, gbase,
652  				dd->name, dd->div_flags, parent_names,
653  				dd->num_parents, dd->flags, &lock);
654  	}
655  
656  	/* clock gate cells */
657  	for (n = 0; n < ARRAY_SIZE(bg2_gates); n++) {
658  		const struct berlin2_gate_data *gd = &bg2_gates[n];
659  
660  		hws[CLKID_GETH0 + n] = clk_hw_register_gate(NULL, gd->name,
661  			    gd->parent_name, gd->flags, gbase + REG_CLKENABLE,
662  			    gd->bit_idx, 0, &lock);
663  	}
664  
665  	/* twdclk is derived from cpu/3 */
666  	hws[CLKID_TWD] =
667  		clk_hw_register_fixed_factor(NULL, "twd", "cpu", 0, 1, 3);
668  
669  	/* check for errors on leaf clocks */
670  	for (n = 0; n < MAX_CLKS; n++) {
671  		if (!IS_ERR(hws[n]))
672  			continue;
673  
674  		pr_err("%pOF: Unable to register leaf clock %d\n", np, n);
675  		goto bg2_fail;
676  	}
677  
678  	/* register clk-provider */
679  	of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_data);
680  
681  	return;
682  
683  bg2_fail:
684  	iounmap(gbase);
685  }
686  CLK_OF_DECLARE(berlin2_clk, "marvell,berlin2-clk",
687  	       berlin2_clock_setup);
688