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