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