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