xref: /linux/drivers/clk/aspeed/clk-ast2700.c (revision 502d45774af09f1c681c754c4b7cdfb5d7f72fd9)
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