1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (c) 2024 ASPEED Technology Inc.
4 * Author: Ryan Chen <ryan_chen@aspeedtech.com>
5 */
6 #include <linux/auxiliary_bus.h>
7 #include <linux/bitfield.h>
8 #include <linux/clk-provider.h>
9 #include <linux/io.h>
10 #include <linux/platform_device.h>
11 #include <linux/slab.h>
12 #include <linux/units.h>
13
14 #include <dt-bindings/clock/aspeed,ast2700-scu.h>
15
16 /* SOC0 */
17 #define SCU0_HWSTRAP1 0x010
18 #define SCU0_CLK_STOP 0x240
19 #define SCU0_CLK_SEL1 0x280
20 #define SCU0_CLK_SEL2 0x284
21 #define GET_USB_REFCLK_DIV(x) ((GENMASK(23, 20) & (x)) >> 20)
22 #define UART_DIV13_EN BIT(30)
23 #define SCU0_HPLL_PARAM 0x300
24 #define SCU0_DPLL_PARAM 0x308
25 #define SCU0_MPLL_PARAM 0x310
26 #define SCU0_D0CLK_PARAM 0x320
27 #define SCU0_D1CLK_PARAM 0x330
28 #define SCU0_CRT0CLK_PARAM 0x340
29 #define SCU0_CRT1CLK_PARAM 0x350
30 #define SCU0_MPHYCLK_PARAM 0x360
31
32 /* SOC1 */
33 #define SCU1_REVISION_ID 0x0
34 #define REVISION_ID GENMASK(23, 16)
35 #define SCU1_CLK_STOP 0x240
36 #define SCU1_CLK_STOP2 0x260
37 #define SCU1_CLK_SEL1 0x280
38 #define SCU1_CLK_SEL2 0x284
39 #define SCU1_CLK_I3C_DIV_MASK GENMASK(25, 23)
40 #define SCU1_CLK_I3C_DIV(n) ((n) - 1)
41 #define UXCLK_MASK GENMASK(1, 0)
42 #define HUXCLK_MASK GENMASK(4, 3)
43 #define SCU1_HPLL_PARAM 0x300
44 #define SCU1_APLL_PARAM 0x310
45 #define SCU1_DPLL_PARAM 0x320
46 #define SCU1_UXCLK_CTRL 0x330
47 #define SCU1_HUXCLK_CTRL 0x334
48 #define SCU1_MAC12_CLK_DLY 0x390
49 #define SCU1_MAC12_CLK_DLY_100M 0x394
50 #define SCU1_MAC12_CLK_DLY_10M 0x398
51
52 enum ast2700_clk_type {
53 CLK_MUX,
54 CLK_PLL,
55 CLK_HPLL,
56 CLK_GATE,
57 CLK_MISC,
58 CLK_FIXED,
59 CLK_DIVIDER,
60 CLK_UART_PLL,
61 CLK_GATE_ASPEED,
62 CLK_FIXED_FACTOR,
63 CLK_FIXED_DISPLAY,
64 };
65
66 struct ast2700_clk_fixed_factor_data {
67 unsigned int mult;
68 unsigned int div;
69 int parent_id;
70 };
71
72 struct ast2700_clk_gate_data {
73 int parent_id;
74 u32 flags;
75 u32 reg;
76 u8 bit;
77 };
78
79 struct ast2700_clk_mux_data {
80 const struct clk_hw **parent_hws;
81 const unsigned int *parent_ids;
82 unsigned int num_parents;
83 u8 bit_shift;
84 u8 bit_width;
85 u32 reg;
86 };
87
88 struct ast2700_clk_div_data {
89 const struct clk_div_table *div_table;
90 unsigned int parent_id;
91 u8 bit_shift;
92 u8 bit_width;
93 u32 reg;
94 };
95
96 struct ast2700_clk_pll_data {
97 unsigned int parent_id;
98 u32 reg;
99 };
100
101 struct ast2700_clk_fixed_rate_data {
102 unsigned long fixed_rate;
103 };
104
105 struct ast2700_clk_display_fixed_data {
106 u32 reg;
107 };
108
109 struct ast2700_clk_info {
110 const char *name;
111 u32 id;
112 u32 reg;
113 u32 type;
114 union {
115 struct ast2700_clk_fixed_factor_data factor;
116 struct ast2700_clk_fixed_rate_data rate;
117 struct ast2700_clk_display_fixed_data display_rate;
118 struct ast2700_clk_gate_data gate;
119 struct ast2700_clk_div_data div;
120 struct ast2700_clk_pll_data pll;
121 struct ast2700_clk_mux_data mux;
122 } data;
123 };
124
125 struct ast2700_clk_data {
126 const struct ast2700_clk_info *clk_info;
127 unsigned int nr_clks;
128 const int scu;
129 };
130
131 struct ast2700_clk_ctrl {
132 const struct ast2700_clk_data *clk_data;
133 struct device *dev;
134 void __iomem *base;
135 spinlock_t lock; /* clk lock */
136 };
137
138 static const struct clk_div_table ast2700_rgmii_div_table[] = {
139 { 0x0, 4 },
140 { 0x1, 4 },
141 { 0x2, 6 },
142 { 0x3, 8 },
143 { 0x4, 10 },
144 { 0x5, 12 },
145 { 0x6, 14 },
146 { 0x7, 16 },
147 { 0 }
148 };
149
150 static const struct clk_div_table ast2700_rmii_div_table[] = {
151 { 0x0, 8 },
152 { 0x1, 8 },
153 { 0x2, 12 },
154 { 0x3, 16 },
155 { 0x4, 20 },
156 { 0x5, 24 },
157 { 0x6, 28 },
158 { 0x7, 32 },
159 { 0 }
160 };
161
162 static const struct clk_div_table ast2700_clk_div_table[] = {
163 { 0x0, 2 },
164 { 0x1, 2 },
165 { 0x2, 3 },
166 { 0x3, 4 },
167 { 0x4, 5 },
168 { 0x5, 6 },
169 { 0x6, 7 },
170 { 0x7, 8 },
171 { 0 }
172 };
173
174 static const struct clk_div_table ast2700_clk_div_table2[] = {
175 { 0x0, 2 },
176 { 0x1, 4 },
177 { 0x2, 6 },
178 { 0x3, 8 },
179 { 0x4, 10 },
180 { 0x5, 12 },
181 { 0x6, 14 },
182 { 0x7, 16 },
183 { 0 }
184 };
185
186 static const struct clk_div_table ast2700_hclk_div_table[] = {
187 { 0x0, 6 },
188 { 0x1, 5 },
189 { 0x2, 4 },
190 { 0x3, 7 },
191 { 0 }
192 };
193
194 static const struct clk_div_table ast2700_clk_uart_div_table[] = {
195 { 0x0, 1 },
196 { 0x1, 13 },
197 { 0 }
198 };
199
200 /* soc 0 */
201 static const unsigned int psp_parent_ids[] = {
202 SCU0_CLK_MPLL,
203 SCU0_CLK_HPLL,
204 SCU0_CLK_HPLL,
205 SCU0_CLK_HPLL,
206 SCU0_CLK_MPLL_DIV2,
207 SCU0_CLK_HPLL_DIV2,
208 SCU0_CLK_HPLL,
209 SCU0_CLK_HPLL
210 };
211
212 static const struct clk_hw *psp_parent_hws[ARRAY_SIZE(psp_parent_ids)];
213
214 static const unsigned int hclk_parent_ids[] = {
215 SCU0_CLK_HPLL,
216 SCU0_CLK_MPLL
217 };
218
219 static const struct clk_hw *hclk_parent_hws[ARRAY_SIZE(hclk_parent_ids)];
220
221 static const unsigned int emmc_parent_ids[] = {
222 SCU0_CLK_MPLL_DIV4,
223 SCU0_CLK_HPLL_DIV4
224 };
225
226 static const struct clk_hw *emmc_parent_hws[ARRAY_SIZE(emmc_parent_ids)];
227
228 static const unsigned int mphy_parent_ids[] = {
229 SCU0_CLK_MPLL,
230 SCU0_CLK_HPLL,
231 SCU0_CLK_DPLL,
232 SCU0_CLK_192M
233 };
234
235 static const struct clk_hw *mphy_parent_hws[ARRAY_SIZE(mphy_parent_ids)];
236
237 static const unsigned int u2phy_parent_ids[] = {
238 SCU0_CLK_MPLL,
239 SCU0_CLK_HPLL
240 };
241
242 static const struct clk_hw *u2phy_parent_hws[ARRAY_SIZE(u2phy_parent_ids)];
243
244 static const unsigned int uart_parent_ids[] = {
245 SCU0_CLK_24M,
246 SCU0_CLK_192M
247 };
248
249 static const struct clk_hw *uart_parent_hws[ARRAY_SIZE(uart_parent_ids)];
250
251 /* soc 1 */
252 static const unsigned int uartx_parent_ids[] = {
253 SCU1_CLK_UARTX,
254 SCU1_CLK_HUARTX
255 };
256
257 static const struct clk_hw *uartx_parent_hws[ARRAY_SIZE(uartx_parent_ids)];
258
259 static const unsigned int uxclk_parent_ids[] = {
260 SCU1_CLK_APLL_DIV4,
261 SCU1_CLK_APLL_DIV2,
262 SCU1_CLK_APLL,
263 SCU1_CLK_HPLL
264 };
265
266 static const struct clk_hw *uxclk_parent_hws[ARRAY_SIZE(uxclk_parent_ids)];
267
268 static const unsigned int sdclk_parent_ids[] = {
269 SCU1_CLK_HPLL,
270 SCU1_CLK_APLL
271 };
272
273 static const struct clk_hw *sdclk_parent_hws[ARRAY_SIZE(sdclk_parent_ids)];
274
275 static const unsigned int peciclk_parent_ids[] = {
276 SCU1_CLKIN,
277 SCU1_CLK_HPLL_DIV4
278 };
279
280 static const struct clk_hw *peciclk_parent_hws[ARRAY_SIZE(peciclk_parent_ids)];
281
282 #define FIXED_CLK(_id, _name, _rate) \
283 { \
284 .id = _id, \
285 .type = CLK_FIXED, \
286 .name = _name, \
287 .data = { .rate = { .fixed_rate = _rate, } }, \
288 }
289
290 #define FIXED_DISPLAY_CLK(_id, _name, _reg) \
291 { \
292 .id = _id, \
293 .type = CLK_FIXED_DISPLAY, \
294 .name = _name, \
295 .data = { .display_rate = { .reg = _reg } }, \
296 }
297
298 #define PLL_CLK(_id, _type, _name, _parent_id, _reg) \
299 { \
300 .id = _id, \
301 .type = _type, \
302 .name = _name, \
303 .data = { .pll = { \
304 .parent_id = _parent_id, \
305 .reg = _reg, \
306 } }, \
307 }
308
309 #define MUX_CLK(_id, _name, _parent_ids, _num_parents, _parent_hws, _reg, _shift, _width) \
310 { \
311 .id = _id, \
312 .type = CLK_MUX, \
313 .name = _name, \
314 .data = { \
315 .mux = { \
316 .parent_ids = _parent_ids, \
317 .parent_hws = _parent_hws, \
318 .num_parents = _num_parents, \
319 .reg = (_reg), \
320 .bit_shift = _shift, \
321 .bit_width = _width, \
322 }, \
323 }, \
324 }
325
326 #define DIVIDER_CLK(_id, _name, _parent_id, _reg, _shift, _width, _div_table) \
327 { \
328 .id = _id, \
329 .type = CLK_DIVIDER, \
330 .name = _name, \
331 .data = { \
332 .div = { \
333 .parent_id = _parent_id, \
334 .reg = _reg, \
335 .bit_shift = _shift, \
336 .bit_width = _width, \
337 .div_table = _div_table, \
338 }, \
339 }, \
340 }
341
342 #define FIXED_FACTOR_CLK(_id, _name, _parent_id, _mult, _div) \
343 { \
344 .id = _id, \
345 .type = CLK_FIXED_FACTOR, \
346 .name = _name, \
347 .data = { .factor = { .parent_id = _parent_id, .mult = _mult, .div = _div, } }, \
348 }
349
350 #define GATE_CLK(_id, _type, _name, _parent_id, _reg, _bit, _flags) \
351 { \
352 .id = _id, \
353 .type = _type, \
354 .name = _name, \
355 .data = { \
356 .gate = { \
357 .parent_id = _parent_id, \
358 .reg = _reg, \
359 .bit = _bit, \
360 .flags = _flags, \
361 }, \
362 }, \
363 }
364
365 static const struct ast2700_clk_info ast2700_scu0_clk_info[] __initconst = {
366 FIXED_CLK(SCU0_CLKIN, "soc0-clkin", 25 * HZ_PER_MHZ),
367 FIXED_CLK(SCU0_CLK_24M, "soc0-clk24Mhz", 24 * HZ_PER_MHZ),
368 FIXED_CLK(SCU0_CLK_192M, "soc0-clk192Mhz", 192 * HZ_PER_MHZ),
369 FIXED_CLK(SCU0_CLK_U2PHY_CLK12M, "u2phy_clk12m", 12 * HZ_PER_MHZ),
370 FIXED_DISPLAY_CLK(SCU0_CLK_D0, "d0clk", SCU0_D0CLK_PARAM),
371 FIXED_DISPLAY_CLK(SCU0_CLK_D1, "d1clk", SCU0_D1CLK_PARAM),
372 FIXED_DISPLAY_CLK(SCU0_CLK_CRT0, "crt0clk", SCU0_CRT0CLK_PARAM),
373 FIXED_DISPLAY_CLK(SCU0_CLK_CRT1, "crt1clk", SCU0_CRT1CLK_PARAM),
374 PLL_CLK(SCU0_CLK_HPLL, CLK_HPLL, "soc0-hpll", SCU0_CLKIN, SCU0_HPLL_PARAM),
375 PLL_CLK(SCU0_CLK_DPLL, CLK_PLL, "soc0-dpll", SCU0_CLKIN, SCU0_DPLL_PARAM),
376 PLL_CLK(SCU0_CLK_MPLL, CLK_PLL, "soc0-mpll", SCU0_CLKIN, SCU0_MPLL_PARAM),
377 FIXED_FACTOR_CLK(SCU0_CLK_HPLL_DIV2, "soc0-hpll_div2", SCU0_CLK_HPLL, 1, 2),
378 FIXED_FACTOR_CLK(SCU0_CLK_HPLL_DIV4, "soc0-hpll_div4", SCU0_CLK_HPLL, 1, 4),
379 FIXED_FACTOR_CLK(SCU0_CLK_MPLL_DIV2, "soc0-mpll_div2", SCU0_CLK_MPLL, 1, 2),
380 FIXED_FACTOR_CLK(SCU0_CLK_MPLL_DIV4, "soc0-mpll_div4", SCU0_CLK_MPLL, 1, 4),
381 FIXED_FACTOR_CLK(SCU0_CLK_MPLL_DIV8, "soc0-mpll_div8", SCU0_CLK_MPLL, 1, 8),
382 FIXED_FACTOR_CLK(SCU0_CLK_AXI1, "axi1clk", SCU0_CLK_MPLL, 1, 4),
383 MUX_CLK(SCU0_CLK_PSP, "pspclk", psp_parent_ids, ARRAY_SIZE(psp_parent_ids),
384 psp_parent_hws, SCU0_HWSTRAP1, 2, 3),
385 FIXED_FACTOR_CLK(SCU0_CLK_AXI0, "axi0clk", SCU0_CLK_PSP, 1, 2),
386 MUX_CLK(SCU0_CLK_AHBMUX, "soc0-ahbmux", hclk_parent_ids, ARRAY_SIZE(hclk_parent_ids),
387 hclk_parent_hws, SCU0_HWSTRAP1, 7, 1),
388 MUX_CLK(SCU0_CLK_EMMCMUX, "emmcsrc-mux", emmc_parent_ids, ARRAY_SIZE(emmc_parent_ids),
389 emmc_parent_hws, SCU0_CLK_SEL1, 11, 1),
390 MUX_CLK(SCU0_CLK_MPHYSRC, "mphysrc", mphy_parent_ids, ARRAY_SIZE(mphy_parent_ids),
391 mphy_parent_hws, SCU0_CLK_SEL2, 18, 2),
392 MUX_CLK(SCU0_CLK_U2PHY_REFCLKSRC, "u2phy_refclksrc", u2phy_parent_ids,
393 ARRAY_SIZE(u2phy_parent_ids), u2phy_parent_hws, SCU0_CLK_SEL2, 23, 1),
394 MUX_CLK(SCU0_CLK_UART, "soc0-uartclk", uart_parent_ids, ARRAY_SIZE(uart_parent_ids),
395 uart_parent_hws, SCU0_CLK_SEL2, 14, 1),
396 PLL_CLK(SCU0_CLK_MPHY, CLK_MISC, "mphyclk", SCU0_CLK_MPHYSRC, SCU0_MPHYCLK_PARAM),
397 PLL_CLK(SCU0_CLK_U2PHY_REFCLK, CLK_MISC, "u2phy_refclk", SCU0_CLK_U2PHY_REFCLKSRC,
398 SCU0_CLK_SEL2),
399 DIVIDER_CLK(SCU0_CLK_AHB, "soc0-ahb", SCU0_CLK_AHBMUX,
400 SCU0_HWSTRAP1, 5, 2, ast2700_hclk_div_table),
401 DIVIDER_CLK(SCU0_CLK_EMMC, "emmcclk", SCU0_CLK_EMMCMUX,
402 SCU0_CLK_SEL1, 12, 3, ast2700_clk_div_table2),
403 DIVIDER_CLK(SCU0_CLK_APB, "soc0-apb", SCU0_CLK_AXI0,
404 SCU0_CLK_SEL1, 23, 3, ast2700_clk_div_table2),
405 DIVIDER_CLK(SCU0_CLK_HPLL_DIV_AHB, "soc0-hpll-ahb", SCU0_CLK_HPLL,
406 SCU0_HWSTRAP1, 5, 2, ast2700_hclk_div_table),
407 DIVIDER_CLK(SCU0_CLK_MPLL_DIV_AHB, "soc0-mpll-ahb", SCU0_CLK_MPLL,
408 SCU0_HWSTRAP1, 5, 2, ast2700_hclk_div_table),
409 DIVIDER_CLK(SCU0_CLK_UART4, "uart4clk", SCU0_CLK_UART,
410 SCU0_CLK_SEL2, 30, 1, ast2700_clk_uart_div_table),
411 GATE_CLK(SCU0_CLK_GATE_MCLK, CLK_GATE_ASPEED, "mclk-gate", SCU0_CLK_MPLL,
412 SCU0_CLK_STOP, 0, CLK_IS_CRITICAL),
413 GATE_CLK(SCU0_CLK_GATE_ECLK, CLK_GATE_ASPEED, "eclk-gate", -1, SCU0_CLK_STOP, 1, 0),
414 GATE_CLK(SCU0_CLK_GATE_2DCLK, CLK_GATE_ASPEED, "gclk-gate", -1, SCU0_CLK_STOP, 2, 0),
415 GATE_CLK(SCU0_CLK_GATE_VCLK, CLK_GATE_ASPEED, "vclk-gate", -1, SCU0_CLK_STOP, 3, 0),
416 GATE_CLK(SCU0_CLK_GATE_BCLK, CLK_GATE_ASPEED, "bclk-gate", -1,
417 SCU0_CLK_STOP, 4, CLK_IS_CRITICAL),
418 GATE_CLK(SCU0_CLK_GATE_VGA0CLK, CLK_GATE_ASPEED, "vga0clk-gate", -1,
419 SCU0_CLK_STOP, 5, CLK_IS_CRITICAL),
420 GATE_CLK(SCU0_CLK_GATE_REFCLK, CLK_GATE_ASPEED, "soc0-refclk-gate", SCU0_CLKIN,
421 SCU0_CLK_STOP, 6, CLK_IS_CRITICAL),
422 GATE_CLK(SCU0_CLK_GATE_PORTBUSB2CLK, CLK_GATE_ASPEED, "portb-usb2clk-gate", -1,
423 SCU0_CLK_STOP, 7, 0),
424 GATE_CLK(SCU0_CLK_GATE_UHCICLK, CLK_GATE_ASPEED, "uhciclk-gate", -1, SCU0_CLK_STOP, 9, 0),
425 GATE_CLK(SCU0_CLK_GATE_VGA1CLK, CLK_GATE_ASPEED, "vga1clk-gate", -1,
426 SCU0_CLK_STOP, 10, CLK_IS_CRITICAL),
427 GATE_CLK(SCU0_CLK_GATE_DDRPHYCLK, CLK_GATE_ASPEED, "ddrphy-gate", -1,
428 SCU0_CLK_STOP, 11, CLK_IS_CRITICAL),
429 GATE_CLK(SCU0_CLK_GATE_E2M0CLK, CLK_GATE_ASPEED, "e2m0clk-gate", -1,
430 SCU0_CLK_STOP, 12, CLK_IS_CRITICAL),
431 GATE_CLK(SCU0_CLK_GATE_HACCLK, CLK_GATE_ASPEED, "hacclk-gate", -1, SCU0_CLK_STOP, 13, 0),
432 GATE_CLK(SCU0_CLK_GATE_PORTAUSB2CLK, CLK_GATE_ASPEED, "porta-usb2clk-gate", -1,
433 SCU0_CLK_STOP, 14, 0),
434 GATE_CLK(SCU0_CLK_GATE_UART4CLK, CLK_GATE_ASPEED, "uart4clk-gate", SCU0_CLK_UART4,
435 SCU0_CLK_STOP, 15, CLK_IS_CRITICAL),
436 GATE_CLK(SCU0_CLK_GATE_SLICLK, CLK_GATE_ASPEED, "soc0-sliclk-gate", -1,
437 SCU0_CLK_STOP, 16, CLK_IS_CRITICAL),
438 GATE_CLK(SCU0_CLK_GATE_DACCLK, CLK_GATE_ASPEED, "dacclk-gate", -1,
439 SCU0_CLK_STOP, 17, CLK_IS_CRITICAL),
440 GATE_CLK(SCU0_CLK_GATE_DP, CLK_GATE_ASPEED, "dpclk-gate", -1,
441 SCU0_CLK_STOP, 18, CLK_IS_CRITICAL),
442 GATE_CLK(SCU0_CLK_GATE_E2M1CLK, CLK_GATE_ASPEED, "e2m1clk-gate", -1,
443 SCU0_CLK_STOP, 19, CLK_IS_CRITICAL),
444 GATE_CLK(SCU0_CLK_GATE_CRT0CLK, CLK_GATE_ASPEED, "crt0clk-gate", -1,
445 SCU0_CLK_STOP, 20, 0),
446 GATE_CLK(SCU0_CLK_GATE_CRT1CLK, CLK_GATE_ASPEED, "crt1clk-gate", -1,
447 SCU0_CLK_STOP, 21, 0),
448 GATE_CLK(SCU0_CLK_GATE_ECDSACLK, CLK_GATE_ASPEED, "eccclk-gate", -1,
449 SCU0_CLK_STOP, 23, 0),
450 GATE_CLK(SCU0_CLK_GATE_RSACLK, CLK_GATE_ASPEED, "rsaclk-gate", -1,
451 SCU0_CLK_STOP, 24, 0),
452 GATE_CLK(SCU0_CLK_GATE_RVAS0CLK, CLK_GATE_ASPEED, "rvas0clk-gate", -1,
453 SCU0_CLK_STOP, 25, 0),
454 GATE_CLK(SCU0_CLK_GATE_UFSCLK, CLK_GATE_ASPEED, "ufsclk-gate", -1,
455 SCU0_CLK_STOP, 26, 0),
456 GATE_CLK(SCU0_CLK_GATE_EMMCCLK, CLK_GATE_ASPEED, "emmcclk-gate", SCU0_CLK_EMMC,
457 SCU0_CLK_STOP, 27, 0),
458 GATE_CLK(SCU0_CLK_GATE_RVAS1CLK, CLK_GATE_ASPEED, "rvas1clk-gate", -1,
459 SCU0_CLK_STOP, 28, 0),
460 };
461
462 static const struct ast2700_clk_info ast2700_scu1_clk_info[] __initconst = {
463 FIXED_CLK(SCU1_CLKIN, "soc1-clkin", 25 * HZ_PER_MHZ),
464 PLL_CLK(SCU1_CLK_HPLL, CLK_PLL, "soc1-hpll", SCU1_CLKIN, SCU1_HPLL_PARAM),
465 PLL_CLK(SCU1_CLK_APLL, CLK_PLL, "soc1-apll", SCU1_CLKIN, SCU1_APLL_PARAM),
466 PLL_CLK(SCU1_CLK_DPLL, CLK_PLL, "soc1-dpll", SCU1_CLKIN, SCU1_DPLL_PARAM),
467 FIXED_FACTOR_CLK(SCU1_CLK_HPLL_DIV4, "soc1-hpll_div4", SCU1_CLK_HPLL, 1, 4),
468 FIXED_FACTOR_CLK(SCU1_CLK_APLL_DIV2, "soc1-apll_div2", SCU1_CLK_APLL, 1, 2),
469 FIXED_FACTOR_CLK(SCU1_CLK_APLL_DIV4, "soc1-apll_div4", SCU1_CLK_APLL, 1, 4),
470 FIXED_FACTOR_CLK(SCU1_CLK_CAN, "canclk", SCU1_CLK_APLL, 1, 10),
471 DIVIDER_CLK(SCU1_CLK_APB, "soc1-apb", SCU1_CLK_HPLL,
472 SCU1_CLK_SEL1, 18, 3, ast2700_clk_div_table2),
473 DIVIDER_CLK(SCU1_CLK_RMII, "rmii", SCU1_CLK_HPLL,
474 SCU1_CLK_SEL1, 21, 3, ast2700_rmii_div_table),
475 DIVIDER_CLK(SCU1_CLK_RGMII, "rgmii", SCU1_CLK_HPLL,
476 SCU1_CLK_SEL1, 25, 3, ast2700_rgmii_div_table),
477 DIVIDER_CLK(SCU1_CLK_MACHCLK, "machclk", SCU1_CLK_HPLL,
478 SCU1_CLK_SEL1, 29, 3, ast2700_clk_div_table),
479 DIVIDER_CLK(SCU1_CLK_APLL_DIVN, "soc1-apll_divn",
480 SCU1_CLK_APLL, SCU1_CLK_SEL2, 8, 3, ast2700_clk_div_table),
481 DIVIDER_CLK(SCU1_CLK_AHB, "soc1-ahb", SCU1_CLK_HPLL,
482 SCU1_CLK_SEL2, 20, 3, ast2700_clk_div_table),
483 DIVIDER_CLK(SCU1_CLK_I3C, "soc1-i3c", SCU1_CLK_HPLL,
484 SCU1_CLK_SEL2, 23, 3, ast2700_clk_div_table),
485 MUX_CLK(SCU1_CLK_SDMUX, "sdclk-mux", sdclk_parent_ids, ARRAY_SIZE(sdclk_parent_ids),
486 sdclk_parent_hws, SCU1_CLK_SEL1, 13, 1),
487 MUX_CLK(SCU1_CLK_UXCLK, "uxclk", uxclk_parent_ids, ARRAY_SIZE(uxclk_parent_ids),
488 uxclk_parent_hws, SCU1_CLK_SEL2, 0, 2),
489 MUX_CLK(SCU1_CLK_HUXCLK, "huxclk", uxclk_parent_ids, ARRAY_SIZE(uxclk_parent_ids),
490 uxclk_parent_hws, SCU1_CLK_SEL2, 3, 2),
491 MUX_CLK(SCU1_CLK_PECI, "peciclk", peciclk_parent_ids, ARRAY_SIZE(peciclk_parent_ids),
492 peciclk_parent_hws, SCU1_CLK_SEL2, 16, 1),
493 DIVIDER_CLK(SCU1_CLK_SDCLK, "sdclk", SCU1_CLK_SDMUX,
494 SCU1_CLK_SEL1, 14, 3, ast2700_clk_div_table),
495 PLL_CLK(SCU1_CLK_UARTX, CLK_UART_PLL, "uartxclk", SCU1_CLK_UXCLK, SCU1_UXCLK_CTRL),
496 PLL_CLK(SCU1_CLK_HUARTX, CLK_UART_PLL, "huartxclk", SCU1_CLK_HUXCLK, SCU1_HUXCLK_CTRL),
497 MUX_CLK(SCU1_CLK_UART0, "uart0clk", uartx_parent_ids, ARRAY_SIZE(uartx_parent_ids),
498 uartx_parent_hws, SCU1_CLK_SEL1, 0, 1),
499 MUX_CLK(SCU1_CLK_UART1, "uart1clk", uartx_parent_ids, ARRAY_SIZE(uartx_parent_ids),
500 uartx_parent_hws, SCU1_CLK_SEL1, 1, 1),
501 MUX_CLK(SCU1_CLK_UART2, "uart2clk", uartx_parent_ids, ARRAY_SIZE(uartx_parent_ids),
502 uartx_parent_hws, SCU1_CLK_SEL1, 2, 1),
503 MUX_CLK(SCU1_CLK_UART3, "uart3clk", uartx_parent_ids, ARRAY_SIZE(uartx_parent_ids),
504 uartx_parent_hws, SCU1_CLK_SEL1, 3, 1),
505 MUX_CLK(SCU1_CLK_UART5, "uart5clk", uartx_parent_ids, ARRAY_SIZE(uartx_parent_ids),
506 uartx_parent_hws, SCU1_CLK_SEL1, 5, 1),
507 MUX_CLK(SCU1_CLK_UART6, "uart6clk", uartx_parent_ids, ARRAY_SIZE(uartx_parent_ids),
508 uartx_parent_hws, SCU1_CLK_SEL1, 6, 1),
509 MUX_CLK(SCU1_CLK_UART7, "uart7clk", uartx_parent_ids, ARRAY_SIZE(uartx_parent_ids),
510 uartx_parent_hws, SCU1_CLK_SEL1, 7, 1),
511 MUX_CLK(SCU1_CLK_UART8, "uart8clk", uartx_parent_ids, ARRAY_SIZE(uartx_parent_ids),
512 uartx_parent_hws, SCU1_CLK_SEL1, 8, 1),
513 MUX_CLK(SCU1_CLK_UART9, "uart9clk", uartx_parent_ids, ARRAY_SIZE(uartx_parent_ids),
514 uartx_parent_hws, SCU1_CLK_SEL1, 9, 1),
515 MUX_CLK(SCU1_CLK_UART10, "uart10clk", uartx_parent_ids, ARRAY_SIZE(uartx_parent_ids),
516 uartx_parent_hws, SCU1_CLK_SEL1, 10, 1),
517 MUX_CLK(SCU1_CLK_UART11, "uart11clk", uartx_parent_ids, ARRAY_SIZE(uartx_parent_ids),
518 uartx_parent_hws, SCU1_CLK_SEL1, 11, 1),
519 MUX_CLK(SCU1_CLK_UART12, "uart12clk", uartx_parent_ids, ARRAY_SIZE(uartx_parent_ids),
520 uartx_parent_hws, SCU1_CLK_SEL1, 12, 1),
521 FIXED_FACTOR_CLK(SCU1_CLK_UART13, "uart13clk", SCU1_CLK_HUARTX, 1, 1),
522 FIXED_FACTOR_CLK(SCU1_CLK_UART14, "uart14clk", SCU1_CLK_HUARTX, 1, 1),
523 GATE_CLK(SCU1_CLK_MAC0RCLK, CLK_GATE, "mac0rclk-gate", SCU1_CLK_RMII,
524 SCU1_MAC12_CLK_DLY, 29, 0),
525 GATE_CLK(SCU1_CLK_MAC1RCLK, CLK_GATE, "mac1rclk-gate", SCU1_CLK_RMII,
526 SCU1_MAC12_CLK_DLY, 30, 0),
527 GATE_CLK(SCU1_CLK_GATE_LCLK0, CLK_GATE_ASPEED, "lclk0-gate", -1,
528 SCU1_CLK_STOP, 0, CLK_IS_CRITICAL),
529 GATE_CLK(SCU1_CLK_GATE_LCLK1, CLK_GATE_ASPEED, "lclk1-gate", -1,
530 SCU1_CLK_STOP, 1, CLK_IS_CRITICAL),
531 GATE_CLK(SCU1_CLK_GATE_ESPI0CLK, CLK_GATE_ASPEED, "espi0clk-gate", -1,
532 SCU1_CLK_STOP, 2, CLK_IS_CRITICAL),
533 GATE_CLK(SCU1_CLK_GATE_ESPI1CLK, CLK_GATE_ASPEED, "espi1clk-gate", -1,
534 SCU1_CLK_STOP, 3, CLK_IS_CRITICAL),
535 GATE_CLK(SCU1_CLK_GATE_SDCLK, CLK_GATE_ASPEED, "sdclk-gate", SCU1_CLK_SDCLK,
536 SCU1_CLK_STOP, 4, CLK_IS_CRITICAL),
537 GATE_CLK(SCU1_CLK_GATE_IPEREFCLK, CLK_GATE_ASPEED, "soc1-iperefclk-gate", -1,
538 SCU1_CLK_STOP, 5, CLK_IS_CRITICAL),
539 GATE_CLK(SCU1_CLK_GATE_REFCLK, CLK_GATE_ASPEED, "soc1-refclk-gate", -1,
540 SCU1_CLK_STOP, 6, CLK_IS_CRITICAL),
541 GATE_CLK(SCU1_CLK_GATE_LPCHCLK, CLK_GATE_ASPEED, "lpchclk-gate", -1,
542 SCU1_CLK_STOP, 7, CLK_IS_CRITICAL),
543 GATE_CLK(SCU1_CLK_GATE_MAC0CLK, CLK_GATE_ASPEED, "mac0clk-gate", -1,
544 SCU1_CLK_STOP, 8, 0),
545 GATE_CLK(SCU1_CLK_GATE_MAC1CLK, CLK_GATE_ASPEED, "mac1clk-gate", -1,
546 SCU1_CLK_STOP, 9, 0),
547 GATE_CLK(SCU1_CLK_GATE_MAC2CLK, CLK_GATE_ASPEED, "mac2clk-gate", -1,
548 SCU1_CLK_STOP, 10, 0),
549 GATE_CLK(SCU1_CLK_GATE_UART0CLK, CLK_GATE_ASPEED, "uart0clk-gate", SCU1_CLK_UART0,
550 SCU1_CLK_STOP, 11, CLK_IS_CRITICAL),
551 GATE_CLK(SCU1_CLK_GATE_UART1CLK, CLK_GATE_ASPEED, "uart1clk-gate", SCU1_CLK_UART1,
552 SCU1_CLK_STOP, 12, CLK_IS_CRITICAL),
553 GATE_CLK(SCU1_CLK_GATE_UART2CLK, CLK_GATE_ASPEED, "uart2clk-gate", SCU1_CLK_UART2,
554 SCU1_CLK_STOP, 13, CLK_IS_CRITICAL),
555 GATE_CLK(SCU1_CLK_GATE_UART3CLK, CLK_GATE_ASPEED, "uart3clk-gate", SCU1_CLK_UART3,
556 SCU1_CLK_STOP, 14, CLK_IS_CRITICAL),
557 GATE_CLK(SCU1_CLK_GATE_I2CCLK, CLK_GATE_ASPEED, "i2cclk-gate", -1, SCU1_CLK_STOP, 15, 0),
558 GATE_CLK(SCU1_CLK_GATE_I3C0CLK, CLK_GATE_ASPEED, "i3c0clk-gate", SCU1_CLK_I3C,
559 SCU1_CLK_STOP, 16, 0),
560 GATE_CLK(SCU1_CLK_GATE_I3C1CLK, CLK_GATE_ASPEED, "i3c1clk-gate", SCU1_CLK_I3C,
561 SCU1_CLK_STOP, 17, 0),
562 GATE_CLK(SCU1_CLK_GATE_I3C2CLK, CLK_GATE_ASPEED, "i3c2clk-gate", SCU1_CLK_I3C,
563 SCU1_CLK_STOP, 18, 0),
564 GATE_CLK(SCU1_CLK_GATE_I3C3CLK, CLK_GATE_ASPEED, "i3c3clk-gate", SCU1_CLK_I3C,
565 SCU1_CLK_STOP, 19, 0),
566 GATE_CLK(SCU1_CLK_GATE_I3C4CLK, CLK_GATE_ASPEED, "i3c4clk-gate", SCU1_CLK_I3C,
567 SCU1_CLK_STOP, 20, 0),
568 GATE_CLK(SCU1_CLK_GATE_I3C5CLK, CLK_GATE_ASPEED, "i3c5clk-gate", SCU1_CLK_I3C,
569 SCU1_CLK_STOP, 21, 0),
570 GATE_CLK(SCU1_CLK_GATE_I3C6CLK, CLK_GATE_ASPEED, "i3c6clk-gate", SCU1_CLK_I3C,
571 SCU1_CLK_STOP, 22, 0),
572 GATE_CLK(SCU1_CLK_GATE_I3C7CLK, CLK_GATE_ASPEED, "i3c7clk-gate", SCU1_CLK_I3C,
573 SCU1_CLK_STOP, 23, 0),
574 GATE_CLK(SCU1_CLK_GATE_I3C8CLK, CLK_GATE_ASPEED, "i3c8clk-gate", SCU1_CLK_I3C,
575 SCU1_CLK_STOP, 24, 0),
576 GATE_CLK(SCU1_CLK_GATE_I3C9CLK, CLK_GATE_ASPEED, "i3c9clk-gate", SCU1_CLK_I3C,
577 SCU1_CLK_STOP, 25, 0),
578 GATE_CLK(SCU1_CLK_GATE_I3C10CLK, CLK_GATE_ASPEED, "i3c10clk-gate", SCU1_CLK_I3C,
579 SCU1_CLK_STOP, 26, 0),
580 GATE_CLK(SCU1_CLK_GATE_I3C11CLK, CLK_GATE_ASPEED, "i3c11clk-gate", SCU1_CLK_I3C,
581 SCU1_CLK_STOP, 27, 0),
582 GATE_CLK(SCU1_CLK_GATE_I3C12CLK, CLK_GATE_ASPEED, "i3c12clk-gate", SCU1_CLK_I3C,
583 SCU1_CLK_STOP, 28, 0),
584 GATE_CLK(SCU1_CLK_GATE_I3C13CLK, CLK_GATE_ASPEED, "i3c13clk-gate", SCU1_CLK_I3C,
585 SCU1_CLK_STOP, 29, 0),
586 GATE_CLK(SCU1_CLK_GATE_I3C14CLK, CLK_GATE_ASPEED, "i3c14clk-gate", SCU1_CLK_I3C,
587 SCU1_CLK_STOP, 30, 0),
588 GATE_CLK(SCU1_CLK_GATE_I3C15CLK, CLK_GATE_ASPEED, "i3c15clk-gate", SCU1_CLK_I3C,
589 SCU1_CLK_STOP, 31, 0),
590 GATE_CLK(SCU1_CLK_GATE_UART5CLK, CLK_GATE_ASPEED, "uart5clk-gate", SCU1_CLK_UART5,
591 SCU1_CLK_STOP2, 0, CLK_IS_CRITICAL),
592 GATE_CLK(SCU1_CLK_GATE_UART6CLK, CLK_GATE_ASPEED, "uart6clk-gate", SCU1_CLK_UART6,
593 SCU1_CLK_STOP2, 1, CLK_IS_CRITICAL),
594 GATE_CLK(SCU1_CLK_GATE_UART7CLK, CLK_GATE_ASPEED, "uart7clk-gate", SCU1_CLK_UART7,
595 SCU1_CLK_STOP2, 2, CLK_IS_CRITICAL),
596 GATE_CLK(SCU1_CLK_GATE_UART8CLK, CLK_GATE_ASPEED, "uart8clk-gate", SCU1_CLK_UART8,
597 SCU1_CLK_STOP2, 3, CLK_IS_CRITICAL),
598 GATE_CLK(SCU1_CLK_GATE_UART9CLK, CLK_GATE_ASPEED, "uart9clk-gate", SCU1_CLK_UART9,
599 SCU1_CLK_STOP2, 4, 0),
600 GATE_CLK(SCU1_CLK_GATE_UART10CLK, CLK_GATE_ASPEED, "uart10clk-gate", SCU1_CLK_UART10,
601 SCU1_CLK_STOP2, 5, 0),
602 GATE_CLK(SCU1_CLK_GATE_UART11CLK, CLK_GATE_ASPEED, "uart11clk-gate", SCU1_CLK_UART11,
603 SCU1_CLK_STOP2, 6, 0),
604 GATE_CLK(SCU1_CLK_GATE_UART12CLK, CLK_GATE_ASPEED, "uart12clk-gate", SCU1_CLK_UART12,
605 SCU1_CLK_STOP2, 7, 0),
606 GATE_CLK(SCU1_CLK_GATE_FSICLK, CLK_GATE_ASPEED, "fsiclk-gate", -1, SCU1_CLK_STOP2, 8, 0),
607 GATE_CLK(SCU1_CLK_GATE_LTPIPHYCLK, CLK_GATE_ASPEED, "ltpiphyclk-gate", -1,
608 SCU1_CLK_STOP2, 9, 0),
609 GATE_CLK(SCU1_CLK_GATE_LTPICLK, CLK_GATE_ASPEED, "ltpiclk-gate", -1,
610 SCU1_CLK_STOP2, 10, 0),
611 GATE_CLK(SCU1_CLK_GATE_VGALCLK, CLK_GATE_ASPEED, "vgalclk-gate", -1,
612 SCU1_CLK_STOP2, 11, CLK_IS_CRITICAL),
613 GATE_CLK(SCU1_CLK_GATE_UHCICLK, CLK_GATE_ASPEED, "usbuartclk-gate", -1,
614 SCU1_CLK_STOP2, 12, 0),
615 GATE_CLK(SCU1_CLK_GATE_CANCLK, CLK_GATE_ASPEED, "canclk-gate", SCU1_CLK_CAN,
616 SCU1_CLK_STOP2, 13, 0),
617 GATE_CLK(SCU1_CLK_GATE_PCICLK, CLK_GATE_ASPEED, "pciclk-gate", -1,
618 SCU1_CLK_STOP2, 14, 0),
619 GATE_CLK(SCU1_CLK_GATE_SLICLK, CLK_GATE_ASPEED, "soc1-sliclk-gate", -1,
620 SCU1_CLK_STOP2, 15, CLK_IS_CRITICAL),
621 GATE_CLK(SCU1_CLK_GATE_E2MCLK, CLK_GATE_ASPEED, "soc1-e2m-gate", -1,
622 SCU1_CLK_STOP2, 16, CLK_IS_CRITICAL),
623 GATE_CLK(SCU1_CLK_GATE_PORTCUSB2CLK, CLK_GATE_ASPEED, "portcusb2-gate", -1,
624 SCU1_CLK_STOP2, 17, 0),
625 GATE_CLK(SCU1_CLK_GATE_PORTDUSB2CLK, CLK_GATE_ASPEED, "portdusb2-gate", -1,
626 SCU1_CLK_STOP2, 18, 0),
627 GATE_CLK(SCU1_CLK_GATE_LTPI1TXCLK, CLK_GATE_ASPEED, "ltp1tx-gate", -1,
628 SCU1_CLK_STOP2, 19, 0),
629 };
630
ast2700_clk_hw_register_fixed_display(void __iomem * reg,const char * name,struct ast2700_clk_ctrl * clk_ctrl)631 static struct clk_hw *ast2700_clk_hw_register_fixed_display(void __iomem *reg, const char *name,
632 struct ast2700_clk_ctrl *clk_ctrl)
633 {
634 unsigned int mult, div, r, n;
635 u32 xdclk;
636 u32 val;
637
638 val = readl(clk_ctrl->base + SCU0_CLK_SEL2);
639 if (val & BIT(29))
640 xdclk = 800 * HZ_PER_MHZ;
641 else
642 xdclk = 1000 * HZ_PER_MHZ;
643
644 val = readl(reg);
645 r = val & GENMASK(15, 0);
646 n = (val >> 16) & GENMASK(15, 0);
647 mult = r;
648 div = 2 * n;
649
650 return devm_clk_hw_register_fixed_rate(clk_ctrl->dev, name, NULL, 0, (xdclk * mult) / div);
651 }
652
ast2700_clk_hw_register_hpll(void __iomem * reg,const char * name,const struct clk_hw * parent_hw,struct ast2700_clk_ctrl * clk_ctrl)653 static struct clk_hw *ast2700_clk_hw_register_hpll(void __iomem *reg,
654 const char *name, const struct clk_hw *parent_hw,
655 struct ast2700_clk_ctrl *clk_ctrl)
656 {
657 unsigned int mult, div;
658 u32 val;
659
660 val = readl(clk_ctrl->base + SCU0_HWSTRAP1);
661 if ((readl(clk_ctrl->base) & REVISION_ID) && (val & BIT(3))) {
662 switch ((val & GENMASK(4, 2)) >> 2) {
663 case 2:
664 return devm_clk_hw_register_fixed_rate(clk_ctrl->dev, name, NULL,
665 0, 1800 * HZ_PER_MHZ);
666 case 3:
667 return devm_clk_hw_register_fixed_rate(clk_ctrl->dev, name, NULL,
668 0, 1700 * HZ_PER_MHZ);
669 case 6:
670 return devm_clk_hw_register_fixed_rate(clk_ctrl->dev, name, NULL,
671 0, 1200 * HZ_PER_MHZ);
672 case 7:
673 return devm_clk_hw_register_fixed_rate(clk_ctrl->dev, name, NULL,
674 0, 800 * HZ_PER_MHZ);
675 default:
676 return ERR_PTR(-EINVAL);
677 }
678 } else if ((val & GENMASK(3, 2)) != 0) {
679 switch ((val & GENMASK(3, 2)) >> 2) {
680 case 1:
681 return devm_clk_hw_register_fixed_rate(clk_ctrl->dev, name, NULL,
682 0, 1900 * HZ_PER_MHZ);
683 case 2:
684 return devm_clk_hw_register_fixed_rate(clk_ctrl->dev, name, NULL,
685 0, 1800 * HZ_PER_MHZ);
686 case 3:
687 return devm_clk_hw_register_fixed_rate(clk_ctrl->dev, name, NULL,
688 0, 1700 * HZ_PER_MHZ);
689 default:
690 return ERR_PTR(-EINVAL);
691 }
692 } else {
693 val = readl(reg);
694
695 if (val & BIT(24)) {
696 /* Pass through mode */
697 mult = 1;
698 div = 1;
699 } else {
700 u32 m = val & 0x1fff;
701 u32 n = (val >> 13) & 0x3f;
702 u32 p = (val >> 19) & 0xf;
703
704 mult = (m + 1) / (2 * (n + 1));
705 div = p + 1;
706 }
707 }
708
709 return devm_clk_hw_register_fixed_factor_parent_hw(clk_ctrl->dev, name,
710 parent_hw, 0, mult, div);
711 }
712
ast2700_clk_hw_register_pll(int clk_idx,void __iomem * reg,const char * name,const struct clk_hw * parent_hw,struct ast2700_clk_ctrl * clk_ctrl)713 static struct clk_hw *ast2700_clk_hw_register_pll(int clk_idx, void __iomem *reg,
714 const char *name, const struct clk_hw *parent_hw,
715 struct ast2700_clk_ctrl *clk_ctrl)
716 {
717 int scu = clk_ctrl->clk_data->scu;
718 unsigned int mult, div;
719 u32 val = readl(reg);
720
721 if (val & BIT(24)) {
722 /* Pass through mode */
723 mult = 1;
724 div = 1;
725 } else {
726 u32 m = val & 0x1fff;
727 u32 n = (val >> 13) & 0x3f;
728 u32 p = (val >> 19) & 0xf;
729
730 if (scu) {
731 mult = (m + 1) / (n + 1);
732 div = p + 1;
733 } else {
734 if (clk_idx == SCU0_CLK_MPLL) {
735 mult = m / (n + 1);
736 div = p + 1;
737 } else {
738 mult = (m + 1) / (2 * (n + 1));
739 div = p + 1;
740 }
741 }
742 }
743
744 return devm_clk_hw_register_fixed_factor_parent_hw(clk_ctrl->dev, name,
745 parent_hw, 0, mult, div);
746 }
747
ast2700_clk_hw_register_uartpll(void __iomem * reg,const char * name,const struct clk_hw * parent_hw,struct ast2700_clk_ctrl * clk_ctrl)748 static struct clk_hw *ast2700_clk_hw_register_uartpll(void __iomem *reg, const char *name,
749 const struct clk_hw *parent_hw,
750 struct ast2700_clk_ctrl *clk_ctrl)
751 {
752 unsigned int mult, div;
753 u32 val = readl(reg);
754 u32 r = val & 0xff;
755 u32 n = (val >> 8) & 0x3ff;
756
757 mult = r;
758 div = n * 2;
759
760 return devm_clk_hw_register_fixed_factor_parent_hw(clk_ctrl->dev, name,
761 parent_hw, 0, mult, div);
762 }
763
ast2700_clk_hw_register_misc(int clk_idx,void __iomem * reg,const char * name,const struct clk_hw * parent_hw,struct ast2700_clk_ctrl * clk_ctrl)764 static struct clk_hw *ast2700_clk_hw_register_misc(int clk_idx, void __iomem *reg,
765 const char *name, const struct clk_hw *parent_hw,
766 struct ast2700_clk_ctrl *clk_ctrl)
767 {
768 u32 div = 0;
769
770 if (clk_idx == SCU0_CLK_MPHY) {
771 div = readl(reg) + 1;
772 } else if (clk_idx == SCU0_CLK_U2PHY_REFCLK) {
773 if (readl(clk_ctrl->base) & REVISION_ID)
774 div = (GET_USB_REFCLK_DIV(readl(reg)) + 1) << 4;
775 else
776 div = (GET_USB_REFCLK_DIV(readl(reg)) + 1) << 1;
777 } else {
778 return ERR_PTR(-EINVAL);
779 }
780
781 return devm_clk_hw_register_fixed_factor_parent_hw(clk_ctrl->dev, name,
782 parent_hw, 0, 1, div);
783 }
784
ast2700_clk_is_enabled(struct clk_hw * hw)785 static int ast2700_clk_is_enabled(struct clk_hw *hw)
786 {
787 struct clk_gate *gate = to_clk_gate(hw);
788 u32 clk = BIT(gate->bit_idx);
789 u32 reg;
790
791 reg = readl(gate->reg);
792
793 return !(reg & clk);
794 }
795
ast2700_clk_enable(struct clk_hw * hw)796 static int ast2700_clk_enable(struct clk_hw *hw)
797 {
798 struct clk_gate *gate = to_clk_gate(hw);
799 u32 clk = BIT(gate->bit_idx);
800
801 if (readl(gate->reg) & clk)
802 writel(clk, gate->reg + 0x04);
803
804 return 0;
805 }
806
ast2700_clk_disable(struct clk_hw * hw)807 static void ast2700_clk_disable(struct clk_hw *hw)
808 {
809 struct clk_gate *gate = to_clk_gate(hw);
810 u32 clk = BIT(gate->bit_idx);
811
812 /* Clock is set to enable, so use write to set register */
813 writel(clk, gate->reg);
814 }
815
816 static const struct clk_ops ast2700_clk_gate_ops = {
817 .enable = ast2700_clk_enable,
818 .disable = ast2700_clk_disable,
819 .is_enabled = ast2700_clk_is_enabled,
820 };
821
ast2700_clk_hw_register_gate(struct device * dev,const char * name,const struct clk_hw * parent_hw,void __iomem * reg,u8 clock_idx,unsigned long flags,spinlock_t * lock)822 static struct clk_hw *ast2700_clk_hw_register_gate(struct device *dev, const char *name,
823 const struct clk_hw *parent_hw,
824 void __iomem *reg, u8 clock_idx,
825 unsigned long flags, spinlock_t *lock)
826 {
827 struct clk_init_data init;
828 struct clk_gate *gate;
829 struct clk_hw *hw;
830 int ret = -EINVAL;
831
832 gate = kzalloc_obj(*gate);
833 if (!gate)
834 return ERR_PTR(-ENOMEM);
835
836 init.name = name;
837 init.ops = &ast2700_clk_gate_ops;
838 init.flags = flags;
839 init.parent_names = NULL;
840 init.parent_hws = parent_hw ? &parent_hw : NULL;
841 init.parent_data = NULL;
842 init.num_parents = parent_hw ? 1 : 0;
843
844 gate->reg = reg;
845 gate->bit_idx = clock_idx;
846 gate->flags = 0;
847 gate->lock = lock;
848 gate->hw.init = &init;
849
850 hw = &gate->hw;
851 ret = clk_hw_register(dev, hw);
852 if (ret) {
853 kfree(gate);
854 hw = ERR_PTR(ret);
855 }
856
857 return hw;
858 }
859
ast2700_soc1_configure_i3c_clk(struct ast2700_clk_ctrl * clk_ctrl)860 static void ast2700_soc1_configure_i3c_clk(struct ast2700_clk_ctrl *clk_ctrl)
861 {
862 if (readl(clk_ctrl->base) & REVISION_ID) {
863 u32 val;
864
865 /* I3C 250MHz = HPLL/4 */
866 val = readl(clk_ctrl->base + SCU1_CLK_SEL2) & ~SCU1_CLK_I3C_DIV_MASK;
867 val |= FIELD_PREP(SCU1_CLK_I3C_DIV_MASK, SCU1_CLK_I3C_DIV(4));
868 writel(val, clk_ctrl->base + SCU1_CLK_SEL2);
869 }
870 }
871
get_parent_hw_or_null(struct clk_hw ** hws,int idx)872 static inline const struct clk_hw *get_parent_hw_or_null(struct clk_hw **hws, int idx)
873 {
874 if (idx < 0)
875 return NULL;
876 else
877 return hws[idx];
878 }
879
ast2700_soc_clk_probe(struct platform_device * pdev)880 static int ast2700_soc_clk_probe(struct platform_device *pdev)
881 {
882 const struct ast2700_clk_data *clk_data;
883 struct clk_hw_onecell_data *clk_hw_data;
884 struct ast2700_clk_ctrl *clk_ctrl;
885 struct device *dev = &pdev->dev;
886 struct auxiliary_device *adev;
887 void __iomem *clk_base;
888 struct clk_hw **hws;
889 char *reset_name;
890 int ret;
891 int i;
892
893 clk_ctrl = devm_kzalloc(dev, sizeof(*clk_ctrl), GFP_KERNEL);
894 if (!clk_ctrl)
895 return -ENOMEM;
896 clk_ctrl->dev = dev;
897 dev_set_drvdata(&pdev->dev, clk_ctrl);
898
899 spin_lock_init(&clk_ctrl->lock);
900
901 clk_base = devm_platform_ioremap_resource(pdev, 0);
902 if (IS_ERR(clk_base))
903 return PTR_ERR(clk_base);
904
905 clk_ctrl->base = clk_base;
906
907 clk_data = device_get_match_data(dev);
908 if (!clk_data)
909 return -ENODEV;
910
911 clk_ctrl->clk_data = clk_data;
912 reset_name = devm_kasprintf(dev, GFP_KERNEL, "reset%d", clk_data->scu);
913
914 clk_hw_data = devm_kzalloc(dev, struct_size(clk_hw_data, hws, clk_data->nr_clks),
915 GFP_KERNEL);
916 if (!clk_hw_data)
917 return -ENOMEM;
918
919 clk_hw_data->num = clk_data->nr_clks;
920 hws = clk_hw_data->hws;
921
922 if (clk_data->scu)
923 ast2700_soc1_configure_i3c_clk(clk_ctrl);
924
925 for (i = 0; i < clk_data->nr_clks; i++) {
926 const struct ast2700_clk_info *clk = &clk_data->clk_info[i];
927 const struct clk_hw *phw = NULL;
928 unsigned int id = clk->id;
929 void __iomem *reg = NULL;
930
931 if (id >= clk_hw_data->num || hws[id]) {
932 dev_err(dev, "clk id %u invalid for %s\n", id, clk->name);
933 return -EINVAL;
934 }
935
936 if (clk->type == CLK_FIXED) {
937 const struct ast2700_clk_fixed_rate_data *fixed_rate = &clk->data.rate;
938
939 hws[id] = devm_clk_hw_register_fixed_rate(dev, clk->name, NULL, 0,
940 fixed_rate->fixed_rate);
941 } else if (clk->type == CLK_FIXED_FACTOR) {
942 const struct ast2700_clk_fixed_factor_data *factor = &clk->data.factor;
943
944 phw = hws[factor->parent_id];
945 hws[id] = devm_clk_hw_register_fixed_factor_parent_hw(dev, clk->name,
946 phw, 0, factor->mult,
947 factor->div);
948 } else if (clk->type == CLK_FIXED_DISPLAY) {
949 reg = clk_ctrl->base + clk->data.display_rate.reg;
950
951 hws[id] = ast2700_clk_hw_register_fixed_display(reg, clk->name, clk_ctrl);
952 } else if (clk->type == CLK_HPLL) {
953 const struct ast2700_clk_pll_data *pll = &clk->data.pll;
954
955 reg = clk_ctrl->base + pll->reg;
956 phw = hws[pll->parent_id];
957 hws[id] = ast2700_clk_hw_register_hpll(reg, clk->name, phw, clk_ctrl);
958 } else if (clk->type == CLK_PLL) {
959 const struct ast2700_clk_pll_data *pll = &clk->data.pll;
960
961 reg = clk_ctrl->base + pll->reg;
962 phw = hws[pll->parent_id];
963 hws[id] = ast2700_clk_hw_register_pll(id, reg, clk->name, phw, clk_ctrl);
964 } else if (clk->type == CLK_UART_PLL) {
965 const struct ast2700_clk_pll_data *pll = &clk->data.pll;
966
967 reg = clk_ctrl->base + pll->reg;
968 phw = hws[pll->parent_id];
969 hws[id] = ast2700_clk_hw_register_uartpll(reg, clk->name, phw, clk_ctrl);
970 } else if (clk->type == CLK_MUX) {
971 const struct ast2700_clk_mux_data *mux = &clk->data.mux;
972
973 reg = clk_ctrl->base + mux->reg;
974 for (int j = 0; j < mux->num_parents; j++) {
975 unsigned int pid = mux->parent_ids[j];
976
977 mux->parent_hws[j] = hws[pid];
978 }
979
980 hws[id] = devm_clk_hw_register_mux_parent_hws(dev, clk->name,
981 mux->parent_hws,
982 mux->num_parents, 0,
983 reg, mux->bit_shift,
984 mux->bit_width, 0,
985 &clk_ctrl->lock);
986 } else if (clk->type == CLK_MISC) {
987 const struct ast2700_clk_pll_data *pll = &clk->data.pll;
988
989 reg = clk_ctrl->base + pll->reg;
990 phw = hws[pll->parent_id];
991 hws[id] = ast2700_clk_hw_register_misc(id, reg, clk->name, phw, clk_ctrl);
992 } else if (clk->type == CLK_DIVIDER) {
993 const struct ast2700_clk_div_data *divider = &clk->data.div;
994
995 reg = clk_ctrl->base + divider->reg;
996 phw = hws[divider->parent_id];
997 hws[id] = clk_hw_register_divider_table_parent_hw(dev, clk->name,
998 phw,
999 0, reg,
1000 divider->bit_shift,
1001 divider->bit_width, 0,
1002 divider->div_table,
1003 &clk_ctrl->lock);
1004 } else if (clk->type == CLK_GATE_ASPEED) {
1005 const struct ast2700_clk_gate_data *gate = &clk->data.gate;
1006
1007 phw = get_parent_hw_or_null(hws, gate->parent_id);
1008 reg = clk_ctrl->base + gate->reg;
1009 hws[id] = ast2700_clk_hw_register_gate(dev, clk->name, phw, reg, gate->bit,
1010 gate->flags, &clk_ctrl->lock);
1011 } else {
1012 const struct ast2700_clk_gate_data *gate = &clk->data.gate;
1013
1014 phw = get_parent_hw_or_null(hws, gate->parent_id);
1015 reg = clk_ctrl->base + gate->reg;
1016 hws[id] = devm_clk_hw_register_gate_parent_hw(dev, clk->name, phw,
1017 gate->flags, reg, gate->bit,
1018 0, &clk_ctrl->lock);
1019 }
1020
1021 if (IS_ERR(hws[id]))
1022 return PTR_ERR(hws[id]);
1023 }
1024
1025 ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, clk_hw_data);
1026 if (ret)
1027 return ret;
1028
1029 adev = devm_auxiliary_device_create(dev, reset_name, (__force void *)clk_base);
1030 if (!adev)
1031 return -ENODEV;
1032
1033 return 0;
1034 }
1035
1036 static const struct ast2700_clk_data ast2700_clk0_data = {
1037 .scu = 0,
1038 .nr_clks = ARRAY_SIZE(ast2700_scu0_clk_info),
1039 .clk_info = ast2700_scu0_clk_info,
1040 };
1041
1042 static const struct ast2700_clk_data ast2700_clk1_data = {
1043 .scu = 1,
1044 .nr_clks = ARRAY_SIZE(ast2700_scu1_clk_info),
1045 .clk_info = ast2700_scu1_clk_info,
1046 };
1047
1048 static const struct of_device_id ast2700_scu_match[] = {
1049 { .compatible = "aspeed,ast2700-scu0", .data = &ast2700_clk0_data },
1050 { .compatible = "aspeed,ast2700-scu1", .data = &ast2700_clk1_data },
1051 { /* sentinel */ }
1052 };
1053
1054 MODULE_DEVICE_TABLE(of, ast2700_scu_match);
1055
1056 static struct platform_driver ast2700_scu_driver = {
1057 .probe = ast2700_soc_clk_probe,
1058 .driver = {
1059 .name = "clk-ast2700",
1060 .of_match_table = ast2700_scu_match,
1061 },
1062 };
1063
1064 module_platform_driver(ast2700_scu_driver);
1065