xref: /rk3399_rockchip-uboot/drivers/clk/rockchip/clk_rk3576.c (revision 257c8a70660eec65519a481f1dd33e4e060766c8)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2021 Fuzhou Rockchip Electronics Co., Ltd
4  * Author: Elaine Zhang <zhangqing@rock-chips.com>
5  */
6 
7 #include <common.h>
8 #include <bitfield.h>
9 #include <clk-uclass.h>
10 #include <dm.h>
11 #include <errno.h>
12 #include <syscon.h>
13 #include <asm/arch/clock.h>
14 #include <asm/arch/cru_rk3576.h>
15 #include <asm/arch/hardware.h>
16 #include <asm/io.h>
17 #include <dm/lists.h>
18 #include <dt-bindings/clock/rockchip,rk3576-cru.h>
19 
20 DECLARE_GLOBAL_DATA_PTR;
21 
22 #define DIV_TO_RATE(input_rate, div)	((input_rate) / ((div) + 1))
23 
24 #if 1
25 static struct rockchip_pll_rate_table rk3576_24m_pll_rates[] = {
26 	/* _mhz, _p, _m, _s, _k */
27 	RK3588_PLL_RATE(1500000000, 2, 250, 1, 0),
28 	RK3588_PLL_RATE(1200000000, 1, 100, 1, 0),
29 	RK3588_PLL_RATE(1188000000, 2, 198, 1, 0),
30 	RK3588_PLL_RATE(1100000000, 3, 550, 2, 0),
31 	RK3588_PLL_RATE(1008000000, 2, 336, 2, 0),
32 	RK3588_PLL_RATE(1000000000, 3, 500, 2, 0),
33 	RK3588_PLL_RATE(900000000, 2, 300, 2, 0),
34 	RK3588_PLL_RATE(850000000, 3, 425, 2, 0),
35 	RK3588_PLL_RATE(816000000, 2, 272, 2, 0),
36 	RK3588_PLL_RATE(786432000, 2, 262, 2, 9437),
37 	RK3588_PLL_RATE(786000000, 1, 131, 2, 0),
38 	RK3588_PLL_RATE(742500000, 4, 495, 2, 0),
39 	RK3588_PLL_RATE(722534400, 8, 963, 2, 24850),
40 	RK3588_PLL_RATE(600000000, 2, 200, 2, 0),
41 	RK3588_PLL_RATE(594000000, 2, 198, 2, 0),
42 	RK3588_PLL_RATE(200000000, 3, 400, 4, 0),
43 	RK3588_PLL_RATE(100000000, 3, 400, 5, 0),
44 	{ /* sentinel */ },
45 };
46 #else
47 static struct rockchip_pll_rate_table rk3576_26m_pll_rates[] = {
48 	/* _mhz, _p, _m, _s, _k */
49 	RK3588_PLL_RATE(1188000000, 2, 183, 1, 50412),
50 	RK3588_PLL_RATE(1100000000, 2, 338, 2, 30247),
51 	RK3588_PLL_RATE(1014000000, 1, 156, 2, 0),
52 	RK3588_PLL_RATE(1000000000, 2, 308, 2, 45371),
53 	RK3588_PLL_RATE(858000000, 1, 132, 2, 0),
54 	RK3588_PLL_RATE(806000000, 1, 124, 2, 0),
55 	RK3588_PLL_RATE(786432000, 2, 242, 2, 64165),
56 	RK3588_PLL_RATE(594000000, 2, 183, 2, 50412),
57 	RK3588_PLL_RATE(297000000, 2, 183, 3, 50412),
58 	RK3588_PLL_RATE(148500000, 2, 183, 4, 50412),
59 	{ /* sentinel */ },
60 };
61 #endif
62 
63 static struct rockchip_pll_clock rk3576_pll_clks[] = {
64 	[BPLL] = PLL(pll_rk3588, PLL_BPLL, RK3576_PLL_CON(0),
65 		      RK3576_BPLL_MODE_CON0, 0, 15, 0,
66 		      rk3576_24m_pll_rates),
67 	[LPLL] = PLL(pll_rk3588, PLL_LPLL, RK3576_LPLL_CON(16),
68 		     RK3576_LPLL_MODE_CON0, 0, 15, 0, rk3576_24m_pll_rates),
69 	[VPLL] = PLL(pll_rk3588, PLL_VPLL, RK3576_PLL_CON(88),
70 		      RK3576_LPLL_MODE_CON0, 4, 15, 0, rk3576_24m_pll_rates),
71 	[AUPLL] = PLL(pll_rk3588, PLL_AUPLL, RK3576_PLL_CON(96),
72 		      RK3576_MODE_CON0, 6, 15, 0, rk3576_24m_pll_rates),
73 	[CPLL] = PLL(pll_rk3588, PLL_CPLL, RK3576_PLL_CON(104),
74 		     RK3576_MODE_CON0, 8, 15, 0, rk3576_24m_pll_rates),
75 	[GPLL] = PLL(pll_rk3588, PLL_GPLL, RK3576_PLL_CON(112),
76 		     RK3576_MODE_CON0, 2, 15, 0, rk3576_24m_pll_rates),
77 	[PPLL] = PLL(pll_rk3588, PLL_PPLL, RK3576_PMU_PLL_CON(128),
78 		     RK3576_MODE_CON0, 10, 15, 0, rk3576_24m_pll_rates),
79 };
80 
81 #ifndef CONFIG_SPL_BUILD
82 #define RK3576_CLK_DUMP(_id, _name, _iscru)	\
83 {						\
84 	.id = _id,				\
85 	.name = _name,				\
86 	.is_cru = _iscru,			\
87 }
88 
89 static const struct rk3576_clk_info clks_dump[] = {
90 	RK3576_CLK_DUMP(PLL_BPLL, "bpll", true),
91 	RK3576_CLK_DUMP(PLL_LPLL, "lpll", true),
92 	RK3576_CLK_DUMP(PLL_VPLL, "vpll", true),
93 	RK3576_CLK_DUMP(PLL_AUPLL, "aupll", true),
94 	RK3576_CLK_DUMP(PLL_CPLL, "cpll", true),
95 	RK3576_CLK_DUMP(PLL_GPLL, "gpll", true),
96 	RK3576_CLK_DUMP(PLL_PPLL, "ppll", true),
97 	RK3576_CLK_DUMP(ACLK_BUS_ROOT, "aclk_bus_root", true),
98 	RK3576_CLK_DUMP(PCLK_BUS_ROOT, "pclk_bus_root", true),
99 	RK3576_CLK_DUMP(HCLK_BUS_ROOT, "hclk_bus_root", true),
100 	RK3576_CLK_DUMP(ACLK_TOP, "aclk_top", true),
101 	RK3576_CLK_DUMP(ACLK_TOP_MID, "aclk_top_mid", true),
102 	RK3576_CLK_DUMP(PCLK_TOP_ROOT, "pclk_top", true),
103 	RK3576_CLK_DUMP(HCLK_TOP, "hclk_top", true),
104 };
105 #endif
106 
107 #ifdef CONFIG_SPL_BUILD
108 #ifndef BITS_WITH_WMASK
109 #define BITS_WITH_WMASK(bits, msk, shift) \
110 	((bits) << (shift)) | ((msk) << ((shift) + 16))
111 #endif
112 #endif
113 
114 #ifndef CONFIG_SPL_BUILD
115 /*
116  *
117  * rational_best_approximation(31415, 10000,
118  *		(1 << 8) - 1, (1 << 5) - 1, &n, &d);
119  *
120  * you may look at given_numerator as a fixed point number,
121  * with the fractional part size described in given_denominator.
122  *
123  * for theoretical background, see:
124  * http://en.wikipedia.org/wiki/Continued_fraction
125  */
126 static void rational_best_approximation(unsigned long given_numerator,
127 					unsigned long given_denominator,
128 					unsigned long max_numerator,
129 					unsigned long max_denominator,
130 					unsigned long *best_numerator,
131 					unsigned long *best_denominator)
132 {
133 	unsigned long n, d, n0, d0, n1, d1;
134 
135 	n = given_numerator;
136 	d = given_denominator;
137 	n0 = 0;
138 	d1 = 0;
139 	n1 = 1;
140 	d0 = 1;
141 	for (;;) {
142 		unsigned long t, a;
143 
144 		if (n1 > max_numerator || d1 > max_denominator) {
145 			n1 = n0;
146 			d1 = d0;
147 			break;
148 		}
149 		if (d == 0)
150 			break;
151 		t = d;
152 		a = n / d;
153 		d = n % d;
154 		n = t;
155 		t = n0 + a * n1;
156 		n0 = n1;
157 		n1 = t;
158 		t = d0 + a * d1;
159 		d0 = d1;
160 		d1 = t;
161 	}
162 	*best_numerator = n1;
163 	*best_denominator = d1;
164 }
165 #endif
166 
167 static ulong rk3576_bus_get_clk(struct rk3576_clk_priv *priv, ulong clk_id)
168 {
169 	struct rk3576_cru *cru = priv->cru;
170 	u32 con, sel, div, rate;
171 
172 	switch (clk_id) {
173 	case ACLK_BUS_ROOT:
174 		con = readl(&cru->clksel_con[55]);
175 		sel = (con & ACLK_BUS_ROOT_SEL_MASK) >>
176 		      ACLK_BUS_ROOT_SEL_SHIFT;
177 		div = (con & ACLK_BUS_ROOT_DIV_MASK) >>
178 		      ACLK_BUS_ROOT_DIV_SHIFT;
179 		if (sel == ACLK_BUS_ROOT_SEL_CPLL)
180 			rate = DIV_TO_RATE(priv->cpll_hz , div);
181 		else
182 			rate = DIV_TO_RATE(priv->gpll_hz, div);
183 		break;
184 	case HCLK_BUS_ROOT:
185 		con = readl(&cru->clksel_con[55]);
186 		sel = (con & HCLK_BUS_ROOT_SEL_MASK) >>
187 		      HCLK_BUS_ROOT_SEL_SHIFT;
188 		if (sel == HCLK_BUS_ROOT_SEL_200M)
189 			rate = 198 * MHz;
190 		else if (sel == HCLK_BUS_ROOT_SEL_100M)
191 			rate = 100 * MHz;
192 		else if (sel == HCLK_BUS_ROOT_SEL_50M)
193 			rate = 50 * MHz;
194 		else
195 			rate = OSC_HZ;
196 		break;
197 	case PCLK_BUS_ROOT:
198 		con = readl(&cru->clksel_con[55]);
199 		sel = (con & PCLK_BUS_ROOT_SEL_MASK) >>
200 		      PCLK_BUS_ROOT_SEL_SHIFT;
201 		if (sel == PCLK_BUS_ROOT_SEL_100M)
202 			rate = 100 * MHz;
203 		else if (sel == PCLK_BUS_ROOT_SEL_50M)
204 			rate = 50 * MHz;
205 		else
206 			rate = OSC_HZ;
207 		break;
208 	default:
209 		return -ENOENT;
210 	}
211 
212 	return rate;
213 }
214 
215 static ulong rk3576_bus_set_clk(struct rk3576_clk_priv *priv,
216 				   ulong clk_id, ulong rate)
217 {
218 	struct rk3576_cru *cru = priv->cru;
219 	int src_clk, src_clk_div;
220 
221 	switch (clk_id) {
222 	case ACLK_BUS_ROOT:
223 		if (!(priv->cpll_hz % rate)) {
224 			src_clk = ACLK_BUS_ROOT_SEL_CPLL;
225 			src_clk_div = DIV_ROUND_UP(priv->cpll_hz, rate);
226 		} else {
227 			src_clk = ACLK_BUS_ROOT_SEL_GPLL;
228 			src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
229 		}
230 		rk_clrsetreg(&cru->clksel_con[55],
231 			     ACLK_BUS_ROOT_SEL_MASK,
232 			     src_clk << ACLK_BUS_ROOT_SEL_SHIFT);
233 		assert(src_clk_div - 1 <= 31);
234 		rk_clrsetreg(&cru->clksel_con[55],
235 			     ACLK_BUS_ROOT_DIV_MASK |
236 			     ACLK_BUS_ROOT_SEL_MASK,
237 			     (src_clk <<
238 			      ACLK_BUS_ROOT_SEL_SHIFT) |
239 			     (src_clk_div - 1) << ACLK_BUS_ROOT_DIV_SHIFT);
240 		break;
241 	case HCLK_BUS_ROOT:
242 		if (rate >= 198 * MHz)
243 			src_clk = HCLK_BUS_ROOT_SEL_200M;
244 		else if (rate >= 99 * MHz)
245 			src_clk = HCLK_BUS_ROOT_SEL_100M;
246 		else if (rate >= 50 * MHz)
247 			src_clk = HCLK_BUS_ROOT_SEL_50M;
248 		else
249 			src_clk = HCLK_BUS_ROOT_SEL_OSC;
250 		rk_clrsetreg(&cru->clksel_con[55],
251 			     HCLK_BUS_ROOT_SEL_MASK,
252 			     src_clk << HCLK_BUS_ROOT_SEL_SHIFT);
253 		break;
254 	case PCLK_BUS_ROOT:
255 		if (rate >= 99 * MHz)
256 			src_clk = PCLK_BUS_ROOT_SEL_100M;
257 		else if (rate >= 50 * MHz)
258 			src_clk = PCLK_BUS_ROOT_SEL_50M;
259 		else
260 			src_clk = PCLK_BUS_ROOT_SEL_OSC;
261 		rk_clrsetreg(&cru->clksel_con[55],
262 			     PCLK_BUS_ROOT_SEL_MASK,
263 			     src_clk << PCLK_BUS_ROOT_SEL_SHIFT);
264 		break;
265 	default:
266 		printf("do not support this center freq\n");
267 		return -EINVAL;
268 	}
269 
270 	return rk3576_bus_get_clk(priv, clk_id);
271 }
272 
273 static ulong rk3576_top_get_clk(struct rk3576_clk_priv *priv, ulong clk_id)
274 {
275 	struct rk3576_cru *cru = priv->cru;
276 	u32 con, sel, div, rate, prate;
277 
278 	switch (clk_id) {
279 	case ACLK_TOP:
280 		con = readl(&cru->clksel_con[9]);
281 		div = (con & ACLK_TOP_DIV_MASK) >>
282 		      ACLK_TOP_DIV_SHIFT;
283 		sel = (con & ACLK_TOP_SEL_MASK) >>
284 		      ACLK_TOP_SEL_SHIFT;
285 		if (sel == ACLK_TOP_SEL_CPLL)
286 			prate = priv->cpll_hz;
287 		else if (sel == ACLK_TOP_SEL_AUPLL)
288 			prate = priv->aupll_hz;
289 		else
290 			prate = priv->gpll_hz;
291 		return DIV_TO_RATE(prate, div);
292 	case ACLK_TOP_MID:
293 		con = readl(&cru->clksel_con[10]);
294 		div = (con & ACLK_TOP_MID_DIV_MASK) >>
295 		      ACLK_TOP_MID_DIV_SHIFT;
296 		sel = (con & ACLK_TOP_MID_SEL_MASK) >>
297 		      ACLK_TOP_MID_SEL_SHIFT;
298 		if (sel == ACLK_TOP_MID_SEL_CPLL)
299 			prate = priv->cpll_hz;
300 		else
301 			prate = priv->gpll_hz;
302 		return DIV_TO_RATE(prate, div);
303 	case PCLK_TOP_ROOT:
304 		con = readl(&cru->clksel_con[8]);
305 		sel = (con & PCLK_TOP_SEL_MASK) >> PCLK_TOP_SEL_SHIFT;
306 		if (sel == PCLK_TOP_SEL_100M)
307 			rate = 100 * MHz;
308 		else if (sel == PCLK_TOP_SEL_50M)
309 			rate = 50 * MHz;
310 		else
311 			rate = OSC_HZ;
312 		break;
313 	case HCLK_TOP:
314 		con = readl(&cru->clksel_con[19]);
315 		sel = (con & HCLK_TOP_SEL_MASK) >> HCLK_TOP_SEL_SHIFT;
316 		if (sel == HCLK_TOP_SEL_200M)
317 			rate = 200 * MHz;
318 		else if (sel == HCLK_TOP_SEL_100M)
319 			rate = 100 * MHz;
320 		else if (sel == HCLK_TOP_SEL_50M)
321 			rate = 50 * MHz;
322 		else
323 			rate = OSC_HZ;
324 		break;
325 	default:
326 		return -ENOENT;
327 	}
328 
329 	return rate;
330 }
331 
332 static ulong rk3576_top_set_clk(struct rk3576_clk_priv *priv,
333 				ulong clk_id, ulong rate)
334 {
335 	struct rk3576_cru *cru = priv->cru;
336 	int src_clk, src_clk_div;
337 
338 	switch (clk_id) {
339 	case ACLK_TOP:
340 		if (!(priv->cpll_hz % rate)) {
341 			src_clk = ACLK_TOP_SEL_CPLL;
342 			src_clk_div = DIV_ROUND_UP(priv->cpll_hz, rate);
343 		} else {
344 			src_clk = ACLK_TOP_SEL_GPLL;
345 			src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
346 		}
347 		assert(src_clk_div - 1 <= 31);
348 		rk_clrsetreg(&cru->clksel_con[9],
349 			     ACLK_TOP_DIV_MASK |
350 			     ACLK_TOP_SEL_MASK,
351 			     (src_clk <<
352 			      ACLK_TOP_SEL_SHIFT) |
353 			     (src_clk_div - 1) << ACLK_TOP_SEL_SHIFT);
354 		break;
355 	case ACLK_TOP_MID:
356 		if (!(priv->cpll_hz % rate)) {
357 			src_clk = ACLK_TOP_MID_SEL_CPLL;
358 			src_clk_div = DIV_ROUND_UP(priv->cpll_hz, rate);
359 		} else {
360 			src_clk = ACLK_TOP_MID_SEL_GPLL;
361 			src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
362 		}
363 		rk_clrsetreg(&cru->clksel_con[10],
364 			     ACLK_TOP_MID_DIV_MASK |
365 			     ACLK_TOP_MID_SEL_MASK,
366 			     (ACLK_TOP_MID_SEL_GPLL <<
367 			      ACLK_TOP_MID_SEL_SHIFT) |
368 			     (src_clk_div - 1) << ACLK_TOP_MID_DIV_SHIFT);
369 		break;
370 	case PCLK_TOP_ROOT:
371 		if (rate >= 99 * MHz)
372 			src_clk = PCLK_TOP_SEL_100M;
373 		else if (rate >= 50 * MHz)
374 			src_clk = PCLK_TOP_SEL_50M;
375 		else
376 			src_clk = PCLK_TOP_SEL_OSC;
377 		rk_clrsetreg(&cru->clksel_con[8],
378 			     PCLK_TOP_SEL_MASK,
379 			     src_clk << PCLK_TOP_SEL_SHIFT);
380 		break;
381 	case HCLK_TOP:
382 		if (rate >= 198 * MHz)
383 			src_clk = HCLK_TOP_SEL_200M;
384 		else if (rate >= 99 * MHz)
385 			src_clk = HCLK_TOP_SEL_100M;
386 		else if (rate >= 50 * MHz)
387 			src_clk = HCLK_TOP_SEL_50M;
388 		else
389 			src_clk = HCLK_TOP_SEL_OSC;
390 		rk_clrsetreg(&cru->clksel_con[19],
391 			     HCLK_TOP_SEL_MASK,
392 			     src_clk << HCLK_TOP_SEL_SHIFT);
393 		break;
394 	default:
395 		printf("do not support this top freq\n");
396 		return -EINVAL;
397 	}
398 
399 	return rk3576_top_get_clk(priv, clk_id);
400 }
401 
402 static ulong rk3576_i2c_get_clk(struct rk3576_clk_priv *priv, ulong clk_id)
403 {
404 	struct rk3576_cru *cru = priv->cru;
405 	u32 sel, con;
406 	ulong rate;
407 
408 	switch (clk_id) {
409 	case CLK_I2C0:
410 		con = readl(&cru->pmuclksel_con[6]);
411 		sel = (con & CLK_I2C0_SEL_MASK) >> CLK_I2C0_SEL_SHIFT;
412 		break;
413 	case CLK_I2C1:
414 		con = readl(&cru->clksel_con[57]);
415 		sel = (con & CLK_I2C1_SEL_MASK) >> CLK_I2C1_SEL_SHIFT;
416 		break;
417 	case CLK_I2C2:
418 		con = readl(&cru->clksel_con[57]);
419 		sel = (con & CLK_I2C2_SEL_MASK) >> CLK_I2C2_SEL_SHIFT;
420 		break;
421 	case CLK_I2C3:
422 		con = readl(&cru->clksel_con[57]);
423 		sel = (con & CLK_I2C3_SEL_MASK) >> CLK_I2C3_SEL_SHIFT;
424 		break;
425 	case CLK_I2C4:
426 		con = readl(&cru->clksel_con[57]);
427 		sel = (con & CLK_I2C4_SEL_MASK) >> CLK_I2C4_SEL_SHIFT;
428 		break;
429 	case CLK_I2C5:
430 		con = readl(&cru->clksel_con[57]);
431 		sel = (con & CLK_I2C5_SEL_MASK) >> CLK_I2C5_SEL_SHIFT;
432 		break;
433 	case CLK_I2C6:
434 		con = readl(&cru->clksel_con[57]);
435 		sel = (con & CLK_I2C6_SEL_MASK) >> CLK_I2C6_SEL_SHIFT;
436 		break;
437 	case CLK_I2C7:
438 		con = readl(&cru->clksel_con[57]);
439 		sel = (con & CLK_I2C7_SEL_MASK) >> CLK_I2C7_SEL_SHIFT;
440 		break;
441 	case CLK_I2C8:
442 		con = readl(&cru->clksel_con[57]);
443 		sel = (con & CLK_I2C8_SEL_MASK) >> CLK_I2C8_SEL_SHIFT;
444 		break;
445 	case CLK_I2C9:
446 		con = readl(&cru->clksel_con[58]);
447 		sel = (con & CLK_I2C9_SEL_MASK) >> CLK_I2C9_SEL_SHIFT;
448 		break;
449 
450 	default:
451 		return -ENOENT;
452 	}
453 	if (sel == CLK_I2C_SEL_200M)
454 		rate = 200 * MHz;
455 	else if (sel == CLK_I2C_SEL_100M)
456 		rate = 100 * MHz;
457 	else if (sel == CLK_I2C_SEL_50M)
458 		rate = 50 * MHz;
459 	else
460 		rate = OSC_HZ;
461 
462 	return rate;
463 }
464 
465 static ulong rk3576_i2c_set_clk(struct rk3576_clk_priv *priv, ulong clk_id,
466 				ulong rate)
467 {
468 	struct rk3576_cru *cru = priv->cru;
469 	int src_clk;
470 
471 	if (rate >= 198 * MHz)
472 		src_clk = CLK_I2C_SEL_200M;
473 	else if (rate >= 99 * MHz)
474 		src_clk = CLK_I2C_SEL_100M;
475 	if (rate >= 50 * MHz)
476 		src_clk = CLK_I2C_SEL_50M;
477 	else
478 		src_clk = CLK_I2C_SEL_OSC;
479 
480 	switch (clk_id) {
481 	case CLK_I2C0:
482 		rk_clrsetreg(&cru->pmuclksel_con[6], CLK_I2C0_SEL_MASK,
483 			     src_clk << CLK_I2C0_SEL_SHIFT);
484 		break;
485 	case CLK_I2C1:
486 		rk_clrsetreg(&cru->clksel_con[57], CLK_I2C1_SEL_MASK,
487 			     src_clk << CLK_I2C1_SEL_SHIFT);
488 		break;
489 	case CLK_I2C2:
490 		rk_clrsetreg(&cru->clksel_con[57], CLK_I2C2_SEL_MASK,
491 			     src_clk << CLK_I2C2_SEL_SHIFT);
492 		break;
493 	case CLK_I2C3:
494 		rk_clrsetreg(&cru->clksel_con[57], CLK_I2C3_SEL_MASK,
495 			     src_clk << CLK_I2C3_SEL_SHIFT);
496 		break;
497 	case CLK_I2C4:
498 		rk_clrsetreg(&cru->clksel_con[57], CLK_I2C4_SEL_MASK,
499 			     src_clk << CLK_I2C4_SEL_SHIFT);
500 		break;
501 	case CLK_I2C5:
502 		rk_clrsetreg(&cru->clksel_con[57], CLK_I2C5_SEL_MASK,
503 			     src_clk << CLK_I2C5_SEL_SHIFT);
504 		break;
505 	case CLK_I2C6:
506 		rk_clrsetreg(&cru->clksel_con[57], CLK_I2C6_SEL_MASK,
507 			     src_clk << CLK_I2C6_SEL_SHIFT);
508 		break;
509 	case CLK_I2C7:
510 		rk_clrsetreg(&cru->clksel_con[57], CLK_I2C7_SEL_MASK,
511 			     src_clk << CLK_I2C7_SEL_SHIFT);
512 		break;
513 	case CLK_I2C8:
514 		rk_clrsetreg(&cru->clksel_con[57], CLK_I2C8_SEL_MASK,
515 			     src_clk << CLK_I2C8_SEL_SHIFT);
516 	case CLK_I2C9:
517 		rk_clrsetreg(&cru->clksel_con[58], CLK_I2C9_SEL_MASK,
518 			     src_clk << CLK_I2C9_SEL_SHIFT);
519 		break;
520 	default:
521 		return -ENOENT;
522 	}
523 
524 	return rk3576_i2c_get_clk(priv, clk_id);
525 }
526 
527 static ulong rk3576_spi_get_clk(struct rk3576_clk_priv *priv, ulong clk_id)
528 {
529 	struct rk3576_cru *cru = priv->cru;
530 	u32 sel, con;
531 
532 	switch (clk_id) {
533 	case CLK_SPI0:
534 		con = readl(&cru->clksel_con[70]);
535 		sel = (con & CLK_SPI0_SEL_MASK) >> CLK_SPI0_SEL_SHIFT;
536 		break;
537 	case CLK_SPI1:
538 		con = readl(&cru->clksel_con[71]);
539 		sel = (con & CLK_SPI1_SEL_MASK) >> CLK_SPI1_SEL_SHIFT;
540 		break;
541 	case CLK_SPI2:
542 		con = readl(&cru->clksel_con[71]);
543 		sel = (con & CLK_SPI2_SEL_MASK) >> CLK_SPI2_SEL_SHIFT;
544 		break;
545 	case CLK_SPI3:
546 		con = readl(&cru->clksel_con[71]);
547 		sel = (con & CLK_SPI3_SEL_MASK) >> CLK_SPI3_SEL_SHIFT;
548 		break;
549 	case CLK_SPI4:
550 		con = readl(&cru->clksel_con[71]);
551 		sel = (con & CLK_SPI4_SEL_MASK) >> CLK_SPI4_SEL_SHIFT;
552 		break;
553 	default:
554 		return -ENOENT;
555 	}
556 
557 	switch (sel) {
558 	case CLK_SPI_SEL_200M:
559 		return 200 * MHz;
560 	case CLK_SPI_SEL_100M:
561 		return 100 * MHz;
562 	case CLK_SPI_SEL_50M:
563 		return 50 * MHz;
564 	case CLK_SPI_SEL_OSC:
565 		return OSC_HZ;
566 	default:
567 		return -ENOENT;
568 	}
569 }
570 
571 static ulong rk3576_spi_set_clk(struct rk3576_clk_priv *priv,
572 				ulong clk_id, ulong rate)
573 {
574 	struct rk3576_cru *cru = priv->cru;
575 	int src_clk;
576 
577 	if (rate >= 198 * MHz)
578 		src_clk = CLK_SPI_SEL_200M;
579 	else if (rate >= 99 * MHz)
580 		src_clk = CLK_SPI_SEL_100M;
581 	else if (rate >= 50 * MHz)
582 		src_clk = CLK_SPI_SEL_50M;
583 	else
584 		src_clk = CLK_SPI_SEL_OSC;
585 
586 	switch (clk_id) {
587 	case CLK_SPI0:
588 		rk_clrsetreg(&cru->clksel_con[70],
589 			     CLK_SPI0_SEL_MASK,
590 			     src_clk << CLK_SPI0_SEL_SHIFT);
591 		break;
592 	case CLK_SPI1:
593 		rk_clrsetreg(&cru->clksel_con[71],
594 			     CLK_SPI1_SEL_MASK,
595 			     src_clk << CLK_SPI1_SEL_SHIFT);
596 		break;
597 	case CLK_SPI2:
598 		rk_clrsetreg(&cru->clksel_con[71],
599 			     CLK_SPI2_SEL_MASK,
600 			     src_clk << CLK_SPI2_SEL_SHIFT);
601 		break;
602 	case CLK_SPI3:
603 		rk_clrsetreg(&cru->clksel_con[71],
604 			     CLK_SPI3_SEL_MASK,
605 			     src_clk << CLK_SPI3_SEL_SHIFT);
606 		break;
607 	case CLK_SPI4:
608 		rk_clrsetreg(&cru->clksel_con[71],
609 			     CLK_SPI4_SEL_MASK,
610 			     src_clk << CLK_SPI4_SEL_SHIFT);
611 		break;
612 	default:
613 		return -ENOENT;
614 	}
615 
616 	return rk3576_spi_get_clk(priv, clk_id);
617 }
618 
619 static ulong rk3576_pwm_get_clk(struct rk3576_clk_priv *priv, ulong clk_id)
620 {
621 	struct rk3576_cru *cru = priv->cru;
622 	u32 sel, con;
623 
624 	switch (clk_id) {
625 	case CLK_PWM1:
626 		con = readl(&cru->clksel_con[71]);
627 		sel = (con & CLK_PWM1_SEL_MASK) >> CLK_PWM1_SEL_SHIFT;
628 		break;
629 	case CLK_PWM2:
630 		con = readl(&cru->clksel_con[74]);
631 		sel = (con & CLK_PWM2_SEL_MASK) >> CLK_PWM2_SEL_SHIFT;
632 		break;
633 	case CLK_PMU1PWM:
634 		con = readl(&cru->pmuclksel_con[5]);
635 		sel = (con & CLK_PMU1PWM_SEL_MASK) >> CLK_PMU1PWM_SEL_SHIFT;
636 		break;
637 	default:
638 		return -ENOENT;
639 	}
640 
641 	switch (sel) {
642 	case CLK_PWM_SEL_100M:
643 		return 100 * MHz;
644 	case CLK_PWM_SEL_50M:
645 		return 50 * MHz;
646 	case CLK_PWM_SEL_OSC:
647 		return OSC_HZ;
648 	default:
649 		return -ENOENT;
650 	}
651 }
652 
653 static ulong rk3576_pwm_set_clk(struct rk3576_clk_priv *priv,
654 				ulong clk_id, ulong rate)
655 {
656 	struct rk3576_cru *cru = priv->cru;
657 	int src_clk;
658 
659 	if (rate >= 99 * MHz)
660 		src_clk = CLK_PWM_SEL_100M;
661 	else if (rate >= 50 * MHz)
662 		src_clk = CLK_PWM_SEL_50M;
663 	else
664 		src_clk = CLK_PWM_SEL_OSC;
665 
666 	switch (clk_id) {
667 	case CLK_PWM1:
668 		rk_clrsetreg(&cru->clksel_con[71],
669 			     CLK_PWM1_SEL_MASK,
670 			     src_clk << CLK_PWM1_SEL_SHIFT);
671 		break;
672 	case CLK_PWM2:
673 		rk_clrsetreg(&cru->clksel_con[74],
674 			     CLK_PWM2_SEL_MASK,
675 			     src_clk << CLK_PWM2_SEL_SHIFT);
676 		break;
677 	case CLK_PMU1PWM:
678 		rk_clrsetreg(&cru->pmuclksel_con[5],
679 			     CLK_PMU1PWM_SEL_MASK,
680 			     src_clk << CLK_PMU1PWM_SEL_SHIFT);
681 		break;
682 	default:
683 		return -ENOENT;
684 	}
685 
686 	return rk3576_pwm_get_clk(priv, clk_id);
687 }
688 
689 static ulong rk3576_adc_get_clk(struct rk3576_clk_priv *priv, ulong clk_id)
690 {
691 	struct rk3576_cru *cru = priv->cru;
692 	u32 div, sel, con, prate;
693 
694 	switch (clk_id) {
695 	case CLK_SARADC:
696 		con = readl(&cru->clksel_con[58]);
697 		div = (con & CLK_SARADC_DIV_MASK) >> CLK_SARADC_DIV_SHIFT;
698 		sel = (con & CLK_SARADC_SEL_MASK) >>
699 		      CLK_SARADC_SEL_SHIFT;
700 		if (sel == CLK_SARADC_SEL_OSC)
701 			prate = OSC_HZ;
702 		else
703 			prate = priv->gpll_hz;
704 		return DIV_TO_RATE(prate, div);
705 	case CLK_TSADC:
706 		con = readl(&cru->clksel_con[59]);
707 		div = (con & CLK_TSADC_DIV_MASK) >>
708 		      CLK_TSADC_DIV_SHIFT;
709 		prate = OSC_HZ;
710 		return DIV_TO_RATE(prate, div);
711 	default:
712 		return -ENOENT;
713 	}
714 }
715 
716 static ulong rk3576_adc_set_clk(struct rk3576_clk_priv *priv,
717 				ulong clk_id, ulong rate)
718 {
719 	struct rk3576_cru *cru = priv->cru;
720 	int src_clk_div;
721 
722 	switch (clk_id) {
723 	case CLK_SARADC:
724 		if (!(OSC_HZ % rate)) {
725 			src_clk_div = DIV_ROUND_UP(OSC_HZ, rate);
726 			assert(src_clk_div - 1 <= 255);
727 			rk_clrsetreg(&cru->clksel_con[58],
728 				     CLK_SARADC_SEL_MASK |
729 				     CLK_SARADC_DIV_MASK,
730 				     (CLK_SARADC_SEL_OSC <<
731 				      CLK_SARADC_SEL_SHIFT) |
732 				     (src_clk_div - 1) <<
733 				     CLK_SARADC_DIV_SHIFT);
734 		} else {
735 			src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
736 			assert(src_clk_div - 1 <= 255);
737 			rk_clrsetreg(&cru->clksel_con[59],
738 				     CLK_SARADC_SEL_MASK |
739 				     CLK_SARADC_DIV_MASK,
740 				     (CLK_SARADC_SEL_GPLL <<
741 				      CLK_SARADC_SEL_SHIFT) |
742 				     (src_clk_div - 1) <<
743 				     CLK_SARADC_DIV_SHIFT);
744 		}
745 		break;
746 	case CLK_TSADC:
747 		src_clk_div = DIV_ROUND_UP(OSC_HZ, rate);
748 		assert(src_clk_div - 1 <= 255);
749 		rk_clrsetreg(&cru->clksel_con[58],
750 			     CLK_TSADC_DIV_MASK,
751 			     (src_clk_div - 1) <<
752 			     CLK_TSADC_DIV_SHIFT);
753 		break;
754 	default:
755 		return -ENOENT;
756 	}
757 	return rk3576_adc_get_clk(priv, clk_id);
758 }
759 
760 static ulong rk3576_mmc_get_clk(struct rk3576_clk_priv *priv, ulong clk_id)
761 {
762 	struct rk3576_cru *cru = priv->cru;
763 	u32 sel, con, prate, div = 0;
764 
765 	switch (clk_id) {
766 	case CCLK_SRC_SDIO:
767 		con = readl(&cru->clksel_con[104]);
768 		div = (con & CCLK_SDIO_SRC_DIV_MASK) >> CCLK_SDIO_SRC_DIV_SHIFT;
769 		sel = (con & CCLK_SDIO_SRC_SEL_MASK) >>
770 		      CCLK_SDIO_SRC_SEL_SHIFT;
771 		if (sel == CCLK_SDIO_SRC_SEL_GPLL)
772 			prate = priv->gpll_hz;
773 		else if (sel == CCLK_SDIO_SRC_SEL_CPLL)
774 			prate = priv->cpll_hz;
775 		else
776 			prate = OSC_HZ;
777 		return DIV_TO_RATE(prate, div);
778 	case CCLK_SRC_SDMMC0:
779 		con = readl(&cru->clksel_con[105]);
780 		div = (con & CCLK_SDMMC0_SRC_DIV_MASK) >> CCLK_SDMMC0_SRC_DIV_SHIFT;
781 		sel = (con & CCLK_SDMMC0_SRC_SEL_MASK) >>
782 		      CCLK_SDMMC0_SRC_SEL_SHIFT;
783 		if (sel == CCLK_SDMMC0_SRC_SEL_GPLL)
784 			prate = priv->gpll_hz;
785 		else if (sel == CCLK_SDMMC0_SRC_SEL_CPLL)
786 			prate = priv->cpll_hz;
787 		else
788 			prate = OSC_HZ;
789 		return DIV_TO_RATE(prate, div);
790 	case CCLK_SRC_EMMC:
791 		con = readl(&cru->clksel_con[89]);
792 		div = (con & CCLK_EMMC_DIV_MASK) >> CCLK_EMMC_DIV_SHIFT;
793 		sel = (con & CCLK_EMMC_SEL_MASK) >>
794 		      CCLK_EMMC_SEL_SHIFT;
795 		if (sel == CCLK_EMMC_SEL_GPLL)
796 			prate = priv->gpll_hz;
797 		else if (sel == CCLK_EMMC_SEL_CPLL)
798 			prate = priv->cpll_hz;
799 		else
800 			prate = OSC_HZ;
801 		return DIV_TO_RATE(prate, div);
802 	case BCLK_EMMC:
803 		con = readl(&cru->clksel_con[90]);
804 		sel = (con & BCLK_EMMC_SEL_MASK) >>
805 		      BCLK_EMMC_SEL_SHIFT;
806 		if (sel == BCLK_EMMC_SEL_200M)
807 			prate = 200 * MHz;
808 		else if (sel == BCLK_EMMC_SEL_100M)
809 			prate = 100 * MHz;
810 		else if (sel == BCLK_EMMC_SEL_50M)
811 			prate = 50 * MHz;
812 		else
813 			prate = OSC_HZ;
814 		return DIV_TO_RATE(prate, div);
815 	case SCLK_FSPI_X2:
816 		con = readl(&cru->clksel_con[89]);
817 		div = (con & SCLK_FSPI_DIV_MASK) >> SCLK_FSPI_DIV_SHIFT;
818 		sel = (con & SCLK_FSPI_SEL_MASK) >>
819 		      SCLK_FSPI_SEL_SHIFT;
820 		if (sel == SCLK_FSPI_SEL_GPLL)
821 			prate = priv->gpll_hz;
822 		else if (sel == SCLK_FSPI_SEL_CPLL)
823 			prate = priv->cpll_hz;
824 		else
825 			prate = OSC_HZ;
826 		return DIV_TO_RATE(prate, div);
827 	case SCLK_FSPI1_X2:
828 		con = readl(&cru->clksel_con[106]);
829 		div = (con & SCLK_FSPI_DIV_MASK) >> SCLK_FSPI_DIV_SHIFT;
830 		sel = (con & SCLK_FSPI_SEL_MASK) >>
831 		      SCLK_FSPI_SEL_SHIFT;
832 		if (sel == SCLK_FSPI_SEL_GPLL)
833 			prate = priv->gpll_hz;
834 		else if (sel == SCLK_FSPI_SEL_CPLL)
835 			prate = priv->cpll_hz;
836 		else
837 			prate = OSC_HZ;
838 		return DIV_TO_RATE(prate, div);
839 	default:
840 		return -ENOENT;
841 	}
842 }
843 
844 static ulong rk3576_mmc_set_clk(struct rk3576_clk_priv *priv,
845 				ulong clk_id, ulong rate)
846 {
847 	struct rk3576_cru *cru = priv->cru;
848 	int src_clk, div = 0;
849 
850 	switch (clk_id) {
851 	case CCLK_SRC_SDIO:
852 	case CCLK_SRC_SDMMC0:
853 	case CCLK_SRC_EMMC:
854 	case SCLK_FSPI_X2:
855 	case SCLK_FSPI1_X2:
856 		if (!(OSC_HZ % rate)) {
857 			src_clk = SCLK_FSPI_SEL_OSC;
858 			div = DIV_ROUND_UP(OSC_HZ, rate);
859 		} else if (!(priv->cpll_hz % rate)) {
860 			src_clk = SCLK_FSPI_SEL_CPLL;
861 			div = DIV_ROUND_UP(priv->cpll_hz, rate);
862 		} else {
863 			src_clk = SCLK_FSPI_SEL_GPLL;
864 			div = DIV_ROUND_UP(priv->gpll_hz, rate);
865 		}
866 		break;
867 	case BCLK_EMMC:
868 		if (rate >= 198 * MHz)
869 			src_clk = BCLK_EMMC_SEL_200M;
870 		else if (rate >= 99 * MHz)
871 			src_clk = BCLK_EMMC_SEL_100M;
872 		else if (rate >= 50 * MHz)
873 			src_clk = BCLK_EMMC_SEL_50M;
874 		else
875 			src_clk = BCLK_EMMC_SEL_OSC;
876 		break;
877 	default:
878 		return -ENOENT;
879 	}
880 
881 	switch (clk_id) {
882 	case CCLK_SRC_SDIO:
883 		rk_clrsetreg(&cru->clksel_con[104],
884 			     CCLK_SDIO_SRC_SEL_MASK |
885 			     CCLK_SDIO_SRC_DIV_MASK,
886 			     (src_clk << CCLK_SDIO_SRC_SEL_SHIFT) |
887 			     (div - 1) << CCLK_SDIO_SRC_DIV_SHIFT);
888 		break;
889 	case CCLK_SRC_SDMMC0:
890 		rk_clrsetreg(&cru->clksel_con[105],
891 			     CCLK_EMMC_SEL_MASK |
892 			     CCLK_EMMC_DIV_MASK,
893 			     (src_clk << CCLK_EMMC_SEL_SHIFT) |
894 			     (div - 1) << CCLK_EMMC_DIV_SHIFT);
895 		break;
896 	case CCLK_SRC_EMMC:
897 		rk_clrsetreg(&cru->clksel_con[89],
898 			     CCLK_EMMC_DIV_MASK |
899 			     CCLK_EMMC_SEL_MASK,
900 			     (src_clk << CCLK_EMMC_SEL_SHIFT) |
901 			     (div - 1) << CCLK_EMMC_DIV_SHIFT);
902 		break;
903 	case SCLK_FSPI_X2:
904 		rk_clrsetreg(&cru->clksel_con[89],
905 			     SCLK_FSPI_DIV_MASK |
906 			     SCLK_FSPI_SEL_MASK,
907 			     (src_clk << SCLK_FSPI_SEL_SHIFT) |
908 			     (div - 1) << SCLK_FSPI_DIV_SHIFT);
909 		break;
910 	case SCLK_FSPI1_X2:
911 		rk_clrsetreg(&cru->clksel_con[106],
912 			     SCLK_FSPI_DIV_MASK |
913 			     SCLK_FSPI_SEL_MASK,
914 			     (src_clk << SCLK_FSPI_SEL_SHIFT) |
915 			     (div - 1) << SCLK_FSPI_DIV_SHIFT);
916 		break;
917 	case BCLK_EMMC:
918 		rk_clrsetreg(&cru->clksel_con[90],
919 			     BCLK_EMMC_SEL_MASK,
920 			     src_clk << BCLK_EMMC_SEL_SHIFT);
921 		break;
922 	default:
923 		return -ENOENT;
924 	}
925 
926 	return rk3576_mmc_get_clk(priv, clk_id);
927 }
928 
929 #ifndef CONFIG_SPL_BUILD
930 
931 static ulong rk3576_aclk_vop_get_clk(struct rk3576_clk_priv *priv, ulong clk_id)
932 {
933 	struct rk3576_cru *cru = priv->cru;
934 	u32 div, sel, con, parent = 0;
935 
936 	switch (clk_id) {
937 	case ACLK_VOP_ROOT:
938 	case ACLK_VOP:
939 		con = readl(&cru->clksel_con[144]);
940 		div = (con & ACLK_VOP_ROOT_DIV_MASK) >> ACLK_VOP_ROOT_DIV_SHIFT;
941 		sel = (con & ACLK_VOP_ROOT_SEL_MASK) >> ACLK_VOP_ROOT_SEL_SHIFT;
942 		if (sel == ACLK_VOP_ROOT_SEL_GPLL)
943 			parent = priv->gpll_hz;
944 		else if (sel == ACLK_VOP_ROOT_SEL_CPLL)
945 			parent = priv->cpll_hz;
946 		else if (sel == ACLK_VOP_ROOT_SEL_AUPLL)
947 			parent = priv->aupll_hz;
948 		else if (sel == ACLK_VOP_ROOT_SEL_SPLL)
949 			parent = priv->spll_hz;
950 		else if (sel == ACLK_VOP_ROOT_SEL_LPLL)
951 			parent = priv->lpll_hz / 2;
952 		return DIV_TO_RATE(parent, div);
953 	case ACLK_VO0_ROOT:
954 		con = readl(&cru->clksel_con[149]);
955 		div = (con & ACLK_VO0_ROOT_DIV_MASK) >> ACLK_VO0_ROOT_DIV_SHIFT;
956 		sel = (con & ACLK_VO0_ROOT_SEL_MASK) >> ACLK_VO0_ROOT_SEL_SHIFT;
957 		if (sel == ACLK_VO0_ROOT_SEL_GPLL)
958 			parent = priv->gpll_hz;
959 		else if (sel == ACLK_VO0_ROOT_SEL_CPLL)
960 			parent = priv->cpll_hz;
961 		else if (sel == ACLK_VO0_ROOT_SEL_LPLL)
962 			parent = priv->lpll_hz / 2;
963 		else if (sel == ACLK_VO0_ROOT_SEL_BPLL)
964 			parent = priv->bpll_hz / 4;
965 		return DIV_TO_RATE(parent, div);
966 	case ACLK_VO1_ROOT:
967 		con = readl(&cru->clksel_con[158]);
968 		div = (con & ACLK_VO0_ROOT_DIV_MASK) >> ACLK_VO0_ROOT_DIV_SHIFT;
969 		sel = (con & ACLK_VO0_ROOT_SEL_MASK) >> ACLK_VO0_ROOT_SEL_SHIFT;
970 		if (sel == ACLK_VO0_ROOT_SEL_GPLL)
971 			parent = priv->gpll_hz;
972 		else if (sel == ACLK_VO0_ROOT_SEL_CPLL)
973 			parent = priv->cpll_hz;
974 		else if (sel == ACLK_VO0_ROOT_SEL_LPLL)
975 			parent = priv->lpll_hz / 2;
976 		else if (sel == ACLK_VO0_ROOT_SEL_BPLL)
977 			parent = priv->bpll_hz / 4;
978 		return DIV_TO_RATE(parent, div);
979 	case HCLK_VOP_ROOT:
980 		con = readl(&cru->clksel_con[144]);
981 		sel = (con & HCLK_VOP_ROOT_SEL_MASK) >> HCLK_VOP_ROOT_SEL_SHIFT;
982 		if (sel == HCLK_VOP_ROOT_SEL_200M)
983 			return 200 * MHz;
984 		else if (sel == HCLK_VOP_ROOT_SEL_100M)
985 			return 100 * MHz;
986 		else if (sel == HCLK_VOP_ROOT_SEL_50M)
987 			return 50 * MHz;
988 		else
989 			return OSC_HZ;
990 	case PCLK_VOP_ROOT:
991 		con = readl(&cru->clksel_con[144]);
992 		sel = (con & PCLK_VOP_ROOT_SEL_MASK) >> PCLK_VOP_ROOT_SEL_SHIFT;
993 		if (sel == PCLK_VOP_ROOT_SEL_100M)
994 			return 100 * MHz;
995 		else if (sel == PCLK_VOP_ROOT_SEL_50M)
996 			return 50 * MHz;
997 		else
998 			return OSC_HZ;
999 
1000 	default:
1001 		return -ENOENT;
1002 	}
1003 }
1004 
1005 static ulong rk3576_aclk_vop_set_clk(struct rk3576_clk_priv *priv,
1006 				     ulong clk_id, ulong rate)
1007 {
1008 	struct rk3576_cru *cru = priv->cru;
1009 	int src_clk, div;
1010 
1011 	switch (clk_id) {
1012 	case ACLK_VOP_ROOT:
1013 	case ACLK_VOP:
1014 		if (rate == 700 * MHz) {
1015 			src_clk = ACLK_VOP_ROOT_SEL_SPLL;
1016 			div = 1;
1017 		} else if (!(priv->cpll_hz % rate)) {
1018 			src_clk = ACLK_VOP_ROOT_SEL_CPLL;
1019 			div = DIV_ROUND_UP(priv->cpll_hz, rate);
1020 		} else {
1021 			src_clk = ACLK_VOP_ROOT_SEL_GPLL;
1022 			div = DIV_ROUND_UP(priv->gpll_hz, rate);
1023 		}
1024 		rk_clrsetreg(&cru->clksel_con[144],
1025 			     ACLK_VOP_ROOT_DIV_MASK |
1026 			     ACLK_VOP_ROOT_SEL_MASK,
1027 			     (src_clk << ACLK_VOP_ROOT_SEL_SHIFT) |
1028 			     (div - 1) << ACLK_VOP_ROOT_DIV_SHIFT);
1029 		break;
1030 	case ACLK_VO0_ROOT:
1031 		if (!(priv->cpll_hz % rate)) {
1032 			src_clk = ACLK_VO0_ROOT_SEL_CPLL;
1033 			div = DIV_ROUND_UP(priv->cpll_hz, rate);
1034 		} else {
1035 			src_clk = ACLK_VO0_ROOT_SEL_GPLL;
1036 			div = DIV_ROUND_UP(priv->gpll_hz, rate);
1037 		}
1038 		rk_clrsetreg(&cru->clksel_con[149],
1039 			     ACLK_VO0_ROOT_DIV_MASK |
1040 			     ACLK_VO0_ROOT_SEL_MASK,
1041 			     (src_clk << ACLK_VO0_ROOT_SEL_SHIFT) |
1042 			     (div - 1) << ACLK_VO0_ROOT_DIV_SHIFT);
1043 		break;
1044 	case ACLK_VO1_ROOT:
1045 		if (!(priv->cpll_hz % rate)) {
1046 			src_clk = ACLK_VO0_ROOT_SEL_CPLL;
1047 			div = DIV_ROUND_UP(priv->cpll_hz, rate);
1048 		} else {
1049 			src_clk = ACLK_VO0_ROOT_SEL_GPLL;
1050 			div = DIV_ROUND_UP(priv->gpll_hz, rate);
1051 		}
1052 		rk_clrsetreg(&cru->clksel_con[158],
1053 			     ACLK_VO0_ROOT_DIV_MASK |
1054 			     ACLK_VO0_ROOT_SEL_MASK,
1055 			     (src_clk << ACLK_VO0_ROOT_SEL_SHIFT) |
1056 			     (div - 1) << ACLK_VO0_ROOT_DIV_SHIFT);
1057 		break;
1058 	case HCLK_VOP_ROOT:
1059 		if (rate == 200 * MHz)
1060 			src_clk = HCLK_VOP_ROOT_SEL_200M;
1061 		else if (rate == 100 * MHz)
1062 			src_clk = HCLK_VOP_ROOT_SEL_100M;
1063 		else if (rate == 50 * MHz)
1064 			src_clk = HCLK_VOP_ROOT_SEL_50M;
1065 		else
1066 			src_clk = HCLK_VOP_ROOT_SEL_OSC;
1067 		rk_clrsetreg(&cru->clksel_con[144],
1068 			     HCLK_VOP_ROOT_SEL_MASK,
1069 			     src_clk << HCLK_VOP_ROOT_SEL_SHIFT);
1070 		break;
1071 	case PCLK_VOP_ROOT:
1072 		if (rate == 100 * MHz)
1073 			src_clk = PCLK_VOP_ROOT_SEL_100M;
1074 		else if (rate == 50 * MHz)
1075 			src_clk = PCLK_VOP_ROOT_SEL_50M;
1076 		else
1077 			src_clk = PCLK_VOP_ROOT_SEL_OSC;
1078 		rk_clrsetreg(&cru->clksel_con[144],
1079 			     PCLK_VOP_ROOT_SEL_MASK,
1080 			     src_clk << PCLK_VOP_ROOT_SEL_SHIFT);
1081 		break;
1082 
1083 	default:
1084 		return -ENOENT;
1085 	}
1086 
1087 	return rk3576_aclk_vop_get_clk(priv, clk_id);
1088 }
1089 
1090 static ulong rk3576_dclk_vop_get_clk(struct rk3576_clk_priv *priv, ulong clk_id)
1091 {
1092 	struct rk3576_cru *cru = priv->cru;
1093 	u32 div, sel, con, parent;
1094 
1095 	switch (clk_id) {
1096 	case DCLK_VP0:
1097 	case DCLK_VP0_SRC:
1098 		con = readl(&cru->clksel_con[145]);
1099 		div = (con & DCLK0_VOP_SRC_DIV_MASK) >> DCLK0_VOP_SRC_DIV_SHIFT;
1100 		sel = (con & DCLK0_VOP_SRC_SEL_MASK) >> DCLK0_VOP_SRC_SEL_SHIFT;
1101 		break;
1102 	case DCLK_VP1:
1103 	case DCLK_VP1_SRC:
1104 		con = readl(&cru->clksel_con[146]);
1105 		div = (con & DCLK0_VOP_SRC_DIV_MASK) >> DCLK0_VOP_SRC_DIV_SHIFT;
1106 		sel = (con & DCLK0_VOP_SRC_SEL_MASK) >> DCLK0_VOP_SRC_SEL_SHIFT;
1107 		break;
1108 	case DCLK_VP2:
1109 	case DCLK_VP2_SRC:
1110 		con = readl(&cru->clksel_con[147]);
1111 		div = (con & DCLK0_VOP_SRC_DIV_MASK) >> DCLK0_VOP_SRC_DIV_SHIFT;
1112 		sel = (con & DCLK0_VOP_SRC_SEL_MASK) >> DCLK0_VOP_SRC_SEL_SHIFT;
1113 		break;
1114 	default:
1115 		return -ENOENT;
1116 	}
1117 
1118 	if (sel == DCLK_VOP_SRC_SEL_VPLL)
1119 		parent = priv->vpll_hz;
1120 	else if (sel == DCLK_VOP_SRC_SEL_BPLL)
1121 		parent = priv->bpll_hz / 4;
1122 	else if (sel == DCLK_VOP_SRC_SEL_LPLL)
1123 		parent = priv->lpll_hz / 2;
1124 	else if (sel == DCLK_VOP_SRC_SEL_GPLL)
1125 		parent = priv->gpll_hz;
1126 	else
1127 		parent = priv->cpll_hz;
1128 
1129 	return DIV_TO_RATE(parent, div);
1130 }
1131 
1132 #define RK3576_VOP_PLL_LIMIT_FREQ 600000000
1133 
1134 static ulong rk3576_dclk_vop_set_clk(struct rk3576_clk_priv *priv,
1135 				     ulong clk_id, ulong rate)
1136 {
1137 	struct rk3576_cru *cru = priv->cru;
1138 	ulong pll_rate, now, best_rate = 0;
1139 	u32 i, conid, con, sel, div, best_div = 0, best_sel = 0;
1140 	u32 mask, div_shift, sel_shift;
1141 
1142 	switch (clk_id) {
1143 	case DCLK_VP0:
1144 	case DCLK_VP0_SRC:
1145 		conid = 145;
1146 		con = readl(&cru->clksel_con[conid]);
1147 		sel = (con & DCLK0_VOP_SRC_SEL_MASK) >> DCLK0_VOP_SRC_SEL_SHIFT;
1148 		mask = DCLK0_VOP_SRC_SEL_MASK | DCLK0_VOP_SRC_DIV_MASK;
1149 		div_shift = DCLK0_VOP_SRC_DIV_SHIFT;
1150 		sel_shift = DCLK0_VOP_SRC_SEL_SHIFT;
1151 		break;
1152 	case DCLK_VP1:
1153 	case DCLK_VP1_SRC:
1154 		conid = 146;
1155 		con = readl(&cru->clksel_con[conid]);
1156 		sel = (con & DCLK0_VOP_SRC_SEL_MASK) >> DCLK0_VOP_SRC_SEL_SHIFT;
1157 		mask = DCLK0_VOP_SRC_SEL_MASK | DCLK0_VOP_SRC_DIV_MASK;
1158 		div_shift = DCLK0_VOP_SRC_DIV_SHIFT;
1159 		sel_shift = DCLK0_VOP_SRC_SEL_SHIFT;
1160 		break;
1161 	case DCLK_VP2:
1162 	case DCLK_VP2_SRC:
1163 		conid = 147;
1164 		con = readl(&cru->clksel_con[conid]);
1165 		sel = (con & DCLK0_VOP_SRC_SEL_MASK) >> DCLK0_VOP_SRC_SEL_SHIFT;
1166 		mask = DCLK0_VOP_SRC_SEL_MASK | DCLK0_VOP_SRC_DIV_MASK;
1167 		div_shift = DCLK0_VOP_SRC_DIV_SHIFT;
1168 		sel_shift = DCLK0_VOP_SRC_SEL_SHIFT;
1169 		break;
1170 	default:
1171 		return -ENOENT;
1172 	}
1173 
1174 	if (sel == DCLK_VOP_SRC_SEL_VPLL) {
1175 		pll_rate = rockchip_pll_get_rate(&rk3576_pll_clks[VPLL],
1176 						 priv->cru, VPLL);
1177 		if (pll_rate >= RK3576_VOP_PLL_LIMIT_FREQ && pll_rate % rate == 0) {
1178 			div = DIV_ROUND_UP(pll_rate, rate);
1179 			rk_clrsetreg(&cru->clksel_con[conid],
1180 				     mask,
1181 				     DCLK_VOP_SRC_SEL_VPLL << sel_shift |
1182 				     ((div - 1) << div_shift));
1183 		} else {
1184 			div = DIV_ROUND_UP(RK3576_VOP_PLL_LIMIT_FREQ, rate);
1185 			if (div % 2)
1186 				div = div + 1;
1187 			rk_clrsetreg(&cru->clksel_con[conid],
1188 				     mask,
1189 				     DCLK_VOP_SRC_SEL_VPLL << sel_shift |
1190 				     ((div - 1) << div_shift));
1191 			rockchip_pll_set_rate(&rk3576_pll_clks[VPLL],
1192 					      priv->cru, VPLL, div * rate);
1193 			priv->vpll_hz = rockchip_pll_get_rate(&rk3576_pll_clks[VPLL],
1194 							      priv->cru, VPLL);
1195 		}
1196 	} else {
1197 		for (i = 0; i <= DCLK_VOP_SRC_SEL_LPLL; i++) {
1198 			switch (i) {
1199 			case DCLK_VOP_SRC_SEL_GPLL:
1200 				pll_rate = priv->gpll_hz;
1201 				break;
1202 			case DCLK_VOP_SRC_SEL_CPLL:
1203 				pll_rate = priv->cpll_hz;
1204 				break;
1205 			case DCLK_VOP_SRC_SEL_BPLL:
1206 				pll_rate = 0;
1207 				break;
1208 			case DCLK_VOP_SRC_SEL_LPLL:
1209 				pll_rate = 0;
1210 				break;
1211 			case DCLK_VOP_SRC_SEL_VPLL:
1212 				pll_rate = 0;
1213 				break;
1214 			default:
1215 				printf("do not support this vop pll sel\n");
1216 				return -EINVAL;
1217 			}
1218 
1219 			div = DIV_ROUND_UP(pll_rate, rate);
1220 			if (div > 255)
1221 				continue;
1222 			now = pll_rate / div;
1223 			if (abs(rate - now) < abs(rate - best_rate)) {
1224 				best_rate = now;
1225 				best_div = div;
1226 				best_sel = i;
1227 			}
1228 			debug("p_rate=%lu, best_rate=%lu, div=%u, sel=%u\n",
1229 			      pll_rate, best_rate, best_div, best_sel);
1230 		}
1231 
1232 		if (best_rate) {
1233 			rk_clrsetreg(&cru->clksel_con[conid],
1234 				     mask,
1235 				     best_sel << sel_shift |
1236 				     (best_div - 1) << div_shift);
1237 		} else {
1238 			printf("do not support this vop freq %lu\n", rate);
1239 			return -EINVAL;
1240 		}
1241 	}
1242 	return rk3576_dclk_vop_get_clk(priv, clk_id);
1243 }
1244 
1245 static ulong rk3576_clk_csihost_get_clk(struct rk3576_clk_priv *priv, ulong clk_id)
1246 {
1247 	struct rk3576_cru *cru = priv->cru;
1248 	u32 div, sel, con, parent;
1249 
1250 	switch (clk_id) {
1251 		case CLK_DSIHOST0:
1252 		con = readl(&cru->clksel_con[151]);
1253 		div = (con & CLK_DSIHOST0_DIV_MASK) >> CLK_DSIHOST0_DIV_SHIFT;
1254 		sel = (con & CLK_DSIHOST0_SEL_MASK) >> CLK_DSIHOST0_SEL_SHIFT;
1255 		break;
1256 	default:
1257 		return -ENOENT;
1258 	}
1259 
1260 	if (sel == CLK_DSIHOST0_SEL_VPLL)
1261 		parent = priv->vpll_hz;
1262 	else if (sel == CLK_DSIHOST0_SEL_BPLL)
1263 		parent = priv->bpll_hz / 4;
1264 	else if (sel == CLK_DSIHOST0_SEL_LPLL)
1265 		parent = priv->lpll_hz / 2;
1266 	else if (sel == CLK_DSIHOST0_SEL_GPLL)
1267 		parent = priv->gpll_hz;
1268 	else if (sel == CLK_DSIHOST0_SEL_SPLL)
1269 		parent = priv->spll_hz;
1270 	else
1271 		parent = priv->cpll_hz;
1272 
1273 	return DIV_TO_RATE(parent, div);
1274 }
1275 
1276 static ulong rk3576_clk_csihost_set_clk(struct rk3576_clk_priv *priv,
1277 				     ulong clk_id, ulong rate)
1278 {
1279 	struct rk3576_cru *cru = priv->cru;
1280 	ulong pll_rate, now, best_rate = 0;
1281 	u32 i, con, div, best_div = 0, best_sel = 0;
1282 	u32 mask, div_shift, sel_shift;
1283 
1284 	switch (clk_id) {
1285 	case CLK_DSIHOST0:
1286 		con = 151;
1287 		mask = CLK_DSIHOST0_SEL_MASK | CLK_DSIHOST0_DIV_MASK;
1288 		div_shift = CLK_DSIHOST0_DIV_SHIFT;
1289 		sel_shift = CLK_DSIHOST0_SEL_SHIFT;
1290 		break;
1291 	default:
1292 		return -ENOENT;
1293 	}
1294 	for (i = 0; i <= CLK_DSIHOST0_SEL_LPLL; i++) {
1295 		switch (i) {
1296 		case CLK_DSIHOST0_SEL_GPLL:
1297 			pll_rate = priv->gpll_hz;
1298 			break;
1299 		case CLK_DSIHOST0_SEL_CPLL:
1300 			pll_rate = priv->cpll_hz;
1301 			break;
1302 		case CLK_DSIHOST0_SEL_BPLL:
1303 			pll_rate = 0;
1304 			break;
1305 		case CLK_DSIHOST0_SEL_LPLL:
1306 			pll_rate = 0;
1307 			break;
1308 		case CLK_DSIHOST0_SEL_VPLL:
1309 			pll_rate = 0;
1310 			break;
1311 		case CLK_DSIHOST0_SEL_SPLL:
1312 			pll_rate = priv->spll_hz;
1313 			break;
1314 		default:
1315 			printf("do not support this vop pll sel\n");
1316 			return -EINVAL;
1317 		}
1318 
1319 		div = DIV_ROUND_UP(pll_rate, rate);
1320 		if (div > 255)
1321 			continue;
1322 		now = pll_rate / div;
1323 		if (abs(rate - now) < abs(rate - best_rate)) {
1324 			best_rate = now;
1325 			best_div = div;
1326 			best_sel = i;
1327 		}
1328 		debug("p_rate=%lu, best_rate=%lu, div=%u, sel=%u\n",
1329 		      pll_rate, best_rate, best_div, best_sel);
1330 	}
1331 	if (best_rate) {
1332 		rk_clrsetreg(&cru->clksel_con[con],
1333 			     mask,
1334 			     best_sel << sel_shift |
1335 			     (best_div - 1) << div_shift);
1336 	} else {
1337 		printf("do not support this vop freq %lu\n", rate);
1338 		return -EINVAL;
1339 	}
1340 	return rk3576_clk_csihost_get_clk(priv, clk_id);
1341 }
1342 
1343 static ulong rk3576_dclk_ebc_get_clk(struct rk3576_clk_priv *priv, ulong clk_id)
1344 {
1345 	struct rk3576_cru *cru = priv->cru;
1346 	u32 div, sel, con, parent;
1347 	unsigned long m = 0, n = 0;
1348 
1349 	switch (clk_id) {
1350 	case DCLK_EBC:
1351 		con = readl(&cru->clksel_con[123]);
1352 		div = (con & DCLK_EBC_DIV_MASK) >> DCLK_EBC_DIV_SHIFT;
1353 		sel = (con & DCLK_EBC_SEL_MASK) >> DCLK_EBC_SEL_SHIFT;
1354 		if (sel == DCLK_EBC_SEL_CPLL)
1355 			parent = priv->cpll_hz;
1356 		else if (sel == DCLK_EBC_SEL_VPLL)
1357 			parent = priv->vpll_hz;
1358 		else if (sel == DCLK_EBC_SEL_AUPLL)
1359 			parent = priv->aupll_hz;
1360 		else if (sel == DCLK_EBC_SEL_LPLL)
1361 			parent = priv->lpll_hz / 2;
1362 		else if (sel == DCLK_EBC_SEL_GPLL)
1363 			parent = priv->gpll_hz;
1364 		else if (sel == DCLK_EBC_SEL_FRAC_SRC)
1365 			parent = rk3576_dclk_ebc_get_clk(priv, DCLK_EBC_FRAC_SRC);
1366 		else
1367 			parent = OSC_HZ;
1368 		return DIV_TO_RATE(parent, div);
1369 	case DCLK_EBC_FRAC_SRC:
1370 		con = readl(&cru->clksel_con[123]);
1371 		div = readl(&cru->clksel_con[122]);
1372 		sel = (con & DCLK_EBC_FRAC_SRC_SEL_MASK) >> DCLK_EBC_FRAC_SRC_SEL_SHIFT;
1373 		if (sel == DCLK_EBC_FRAC_SRC_SEL_GPLL)
1374 			parent = priv->gpll_hz;
1375 		else if (sel == DCLK_EBC_FRAC_SRC_SEL_CPLL)
1376 			parent = priv->cpll_hz;
1377 		else if (sel == DCLK_EBC_FRAC_SRC_SEL_VPLL)
1378 			parent = priv->vpll_hz;
1379 		else if (sel == DCLK_EBC_FRAC_SRC_SEL_AUPLL)
1380 			parent = priv->aupll_hz;
1381 		else
1382 			parent = OSC_HZ;
1383 
1384 		n = div & CLK_UART_FRAC_NUMERATOR_MASK;
1385 		n >>= CLK_UART_FRAC_NUMERATOR_SHIFT;
1386 		m = div & CLK_UART_FRAC_DENOMINATOR_MASK;
1387 		m >>= CLK_UART_FRAC_DENOMINATOR_SHIFT;
1388 		return parent * n / m;
1389 	default:
1390 		return -ENOENT;
1391 	}
1392 }
1393 
1394 static ulong rk3576_dclk_ebc_set_clk(struct rk3576_clk_priv *priv,
1395 				     ulong clk_id, ulong rate)
1396 {
1397 	struct rk3576_cru *cru = priv->cru;
1398 	u32 div, sel;
1399 	unsigned long m = 0, n = 0, val;
1400 
1401 	switch (clk_id) {
1402 	case DCLK_EBC:
1403 		if (!(priv->gpll_hz % rate)) {
1404 			sel = DCLK_EBC_SEL_GPLL;
1405 			div = priv->gpll_hz / rate;
1406 		} else if (!(priv->cpll_hz % rate)) {
1407 			sel = DCLK_EBC_SEL_CPLL;
1408 			div = priv->cpll_hz / rate;
1409 		} else if (!(priv->aupll_hz % rate)) {
1410 			sel = DCLK_EBC_SEL_AUPLL;
1411 			div = priv->aupll_hz / rate;
1412 		} else if (!(priv->vpll_hz % rate)) {
1413 			sel = DCLK_EBC_SEL_VPLL;
1414 			div = priv->vpll_hz / rate;
1415 		} else if (!(OSC_HZ % rate)) {
1416 			sel = DCLK_EBC_SEL_OSC;
1417 			div = OSC_HZ / rate;
1418 		} else {
1419 			sel = DCLK_EBC_SEL_FRAC_SRC;
1420 			rk3576_dclk_ebc_set_clk(priv, DCLK_EBC_FRAC_SRC, rate);
1421 			div = rk3576_dclk_ebc_get_clk(priv, DCLK_EBC_FRAC_SRC) / rate;
1422 		}
1423 		rk_clrsetreg(&cru->clksel_con[123],
1424 			     DCLK_EBC_SEL_MASK | DCLK_EBC_DIV_MASK,
1425 			     (sel << DCLK_EBC_SEL_SHIFT) |
1426 			     (div - 1) << DCLK_EBC_DIV_SHIFT);
1427 		break;
1428 	case DCLK_EBC_FRAC_SRC:
1429 		sel = DCLK_EBC_FRAC_SRC_SEL_GPLL;
1430 		div = 1;
1431 		rational_best_approximation(rate, priv->gpll_hz,
1432 					    GENMASK(16 - 1, 0),
1433 					    GENMASK(16 - 1, 0),
1434 					    &m, &n);
1435 
1436 		if (m < 4 && m != 0) {
1437 			if (n % 2 == 0)
1438 				val = 1;
1439 			else
1440 				val = DIV_ROUND_UP(4, m);
1441 
1442 			n *= val;
1443 			m *= val;
1444 			if (n > 0xffff) {
1445 				n = 0xffff;
1446 			}
1447 		}
1448 
1449 		rk_clrsetreg(&cru->clksel_con[123],
1450 		     DCLK_EBC_FRAC_SRC_SEL_MASK,
1451 		     (sel << DCLK_EBC_FRAC_SRC_SEL_SHIFT));
1452 		if (m && n) {
1453 			val = m << CLK_UART_FRAC_NUMERATOR_SHIFT | n;
1454 			writel(val, &cru->clksel_con[122]);
1455 		}
1456 		break;
1457 	default:
1458 		return -ENOENT;
1459 	}
1460 	return rk3576_dclk_ebc_get_clk(priv, clk_id);
1461 }
1462 
1463 static ulong rk3576_gmac_get_clk(struct rk3576_clk_priv *priv, ulong clk_id)
1464 {
1465 	struct rk3576_cru *cru = priv->cru;
1466 	u32 con, div, src, p_rate;
1467 
1468 	switch (clk_id) {
1469 	case CLK_GMAC0_PTP_REF_SRC:
1470 	case CLK_GMAC0_PTP_REF:
1471 		con = readl(&cru->clksel_con[105]);
1472 		div = (con & CLK_GMAC0_PTP_DIV_MASK) >> CLK_GMAC0_PTP_DIV_SHIFT;
1473 		src = (con & CLK_GMAC0_PTP_SEL_MASK) >> CLK_GMAC0_PTP_SEL_SHIFT;
1474 		if (src == CLK_GMAC0_PTP_SEL_GPLL)
1475 			p_rate = priv->gpll_hz;
1476 		else if (src == CLK_GMAC0_PTP_SEL_CPLL)
1477 			p_rate = priv->cpll_hz;
1478 		else
1479 			p_rate = GMAC0_PTP_REFCLK_IN;
1480 		return DIV_TO_RATE(p_rate, div);
1481 	case CLK_GMAC1_PTP_REF_SRC:
1482 	case CLK_GMAC1_PTP_REF:
1483 		con = readl(&cru->clksel_con[104]);
1484 		div = (con & CLK_GMAC1_PTP_DIV_MASK) >> CLK_GMAC0_PTP_DIV_SHIFT;
1485 		src = (con & CLK_GMAC1_PTP_SEL_MASK) >> CLK_GMAC1_PTP_SEL_SHIFT;
1486 		if (src == CLK_GMAC1_PTP_SEL_GPLL)
1487 			p_rate = priv->gpll_hz;
1488 		else if (src == CLK_GMAC1_PTP_SEL_CPLL)
1489 			p_rate = priv->cpll_hz;
1490 		else
1491 			p_rate = GMAC1_PTP_REFCLK_IN;
1492 		return DIV_TO_RATE(p_rate, div);
1493 	case CLK_GMAC0_125M_SRC:
1494 		con = readl(&cru->clksel_con[30]);
1495 		div = (con & CLK_GMAC0_125M_DIV_MASK) >> CLK_GMAC0_125M_DIV_SHIFT;
1496 		return DIV_TO_RATE(priv->cpll_hz, div);
1497 	case CLK_GMAC1_125M_SRC:
1498 		con = readl(&cru->clksel_con[31]);
1499 		div = (con & CLK_GMAC1_125M_DIV_MASK) >> CLK_GMAC1_125M_DIV_SHIFT;
1500 		return DIV_TO_RATE(priv->cpll_hz, div);
1501 	default:
1502 		return -ENOENT;
1503 	}
1504 }
1505 
1506 static ulong rk3576_gmac_set_clk(struct rk3576_clk_priv *priv,
1507 				 ulong clk_id, ulong rate)
1508 {
1509 	struct rk3576_cru *cru = priv->cru;
1510 	int div, src;
1511 
1512 	div = DIV_ROUND_UP(priv->cpll_hz, rate);
1513 
1514 	switch (clk_id) {
1515 	case CLK_GMAC0_PTP_REF_SRC:
1516 	case CLK_GMAC0_PTP_REF:
1517 		if (rate == GMAC0_PTP_REFCLK_IN) {
1518 			src = CLK_GMAC0_PTP_SEL_REFIN;
1519 			div = 1;
1520 		} else if (!(priv->gpll_hz % rate)) {
1521 			src = CLK_GMAC0_PTP_SEL_GPLL;
1522 			div = priv->gpll_hz / rate;
1523 		} else {
1524 			src = CLK_GMAC0_PTP_SEL_CPLL;
1525 			div = priv->cpll_hz / rate;
1526 		}
1527 		rk_clrsetreg(&cru->clksel_con[105],
1528 			     CLK_GMAC0_PTP_DIV_MASK | CLK_GMAC0_PTP_SEL_MASK,
1529 			     src << CLK_GMAC0_PTP_SEL_SHIFT |
1530 			     (div - 1) << CLK_GMAC0_PTP_DIV_SHIFT);
1531 		break;
1532 	case CLK_GMAC1_PTP_REF_SRC:
1533 	case CLK_GMAC1_PTP_REF:
1534 		if (rate == GMAC1_PTP_REFCLK_IN) {
1535 			src = CLK_GMAC1_PTP_SEL_REFIN;
1536 			div = 1;
1537 		} else if (!(priv->gpll_hz % rate)) {
1538 			src = CLK_GMAC1_PTP_SEL_GPLL;
1539 			div = priv->gpll_hz / rate;
1540 		} else {
1541 			src = CLK_GMAC1_PTP_SEL_CPLL;
1542 			div = priv->cpll_hz / rate;
1543 		}
1544 		rk_clrsetreg(&cru->clksel_con[104],
1545 			     CLK_GMAC1_PTP_DIV_MASK | CLK_GMAC1_PTP_SEL_MASK,
1546 			     src << CLK_GMAC1_PTP_SEL_SHIFT |
1547 			     (div - 1) << CLK_GMAC1_PTP_DIV_SHIFT);
1548 		break;
1549 
1550 	case CLK_GMAC0_125M_SRC:
1551 		rk_clrsetreg(&cru->clksel_con[30],
1552 			     CLK_GMAC0_125M_DIV_MASK,
1553 			     (div - 1) << CLK_GMAC0_125M_DIV_SHIFT);
1554 		break;
1555 	case CLK_GMAC1_125M_SRC:
1556 		rk_clrsetreg(&cru->clksel_con[31],
1557 			     CLK_GMAC1_125M_DIV_MASK,
1558 			     (div - 1) << CLK_GMAC1_125M_DIV_SHIFT);
1559 		break;
1560 	default:
1561 		return -ENOENT;
1562 	}
1563 
1564 	return rk3576_gmac_get_clk(priv, clk_id);
1565 }
1566 
1567 static ulong rk3576_uart_frac_get_rate(struct rk3576_clk_priv *priv, ulong clk_id)
1568 {
1569 	struct rk3576_cru *cru = priv->cru;
1570 	u32 reg, con, fracdiv, p_src, p_rate;
1571 	unsigned long m, n;
1572 
1573 	switch (clk_id) {
1574 	case CLK_UART_FRAC_0:
1575 		reg = 21;
1576 		break;
1577 	case CLK_UART_FRAC_1:
1578 		reg = 23;
1579 		break;
1580 	case CLK_UART_FRAC_2:
1581 		reg = 25;
1582 		break;
1583 	default:
1584 		return -ENOENT;
1585 	}
1586 	con = readl(&cru->clksel_con[reg + 1]);
1587 	p_src = (con & CLK_UART_SRC_SEL_MASK) >> CLK_UART_SRC_SEL_SHIFT;
1588 	if (p_src == CLK_UART_SRC_SEL_GPLL)
1589 		p_rate = priv->gpll_hz;
1590 	else if (p_src == CLK_UART_SRC_SEL_CPLL)
1591 		p_rate = priv->cpll_hz;
1592 	else if (p_src == CLK_UART_SRC_SEL_AUPLL)
1593 		p_rate = priv->aupll_hz;
1594 	else
1595 		p_rate = OSC_HZ;
1596 
1597 	fracdiv = readl(&cru->clksel_con[reg]);
1598 	n = fracdiv & CLK_UART_FRAC_NUMERATOR_MASK;
1599 	n >>= CLK_UART_FRAC_NUMERATOR_SHIFT;
1600 	m = fracdiv & CLK_UART_FRAC_DENOMINATOR_MASK;
1601 	m >>= CLK_UART_FRAC_DENOMINATOR_SHIFT;
1602 	return p_rate * n / m;
1603 }
1604 
1605 static ulong rk3576_uart_frac_set_rate(struct rk3576_clk_priv *priv,
1606 				  ulong clk_id, ulong rate)
1607 {
1608 	struct rk3576_cru *cru = priv->cru;
1609 	u32 reg, clk_src, p_rate;
1610 	unsigned long m = 0, n = 0, val;
1611 
1612 	if (priv->cpll_hz % rate == 0) {
1613 		clk_src = CLK_UART_SRC_SEL_CPLL;
1614 		p_rate = priv->cpll_hz;
1615 	} else if (rate == OSC_HZ) {
1616 		clk_src = CLK_UART_SRC_SEL_OSC;
1617 		p_rate = OSC_HZ;
1618 	} else {
1619 		clk_src = CLK_UART_SRC_SEL_GPLL;
1620 		p_rate = priv->cpll_hz;
1621 	}
1622 	rational_best_approximation(rate, p_rate,
1623 					    GENMASK(16 - 1, 0),
1624 					    GENMASK(16 - 1, 0),
1625 					    &m, &n);
1626 
1627 	if (m < 4 && m != 0) {
1628 		if (n % 2 == 0)
1629 			val = 1;
1630 		else
1631 			val = DIV_ROUND_UP(4, m);
1632 
1633 		n *= val;
1634 		m *= val;
1635 		if (n > 0xffff) {
1636 			n = 0xffff;
1637 		}
1638 	}
1639 
1640 
1641 	switch (clk_id) {
1642 	case CLK_UART_FRAC_0:
1643 		reg = 21;
1644 		break;
1645 	case CLK_UART_FRAC_1:
1646 		reg = 23;
1647 		break;
1648 	case CLK_UART_FRAC_2:
1649 		reg = 25;
1650 		break;
1651 	default:
1652 		return -ENOENT;
1653 	}
1654 	rk_clrsetreg(&cru->clksel_con[reg +1],
1655 		     CLK_UART_SRC_SEL_MASK,
1656 		     (clk_src << CLK_UART_SRC_SEL_SHIFT));
1657 	if (m && n) {
1658 		val = m << CLK_UART_FRAC_NUMERATOR_SHIFT | n;
1659 		writel(val, &cru->clksel_con[reg]);
1660 	}
1661 
1662 	return rk3576_uart_frac_get_rate(priv, clk_id);
1663 }
1664 
1665 
1666 static ulong rk3576_uart_get_rate(struct rk3576_clk_priv *priv, ulong clk_id)
1667 {
1668 	struct rk3576_cru *cru = priv->cru;
1669 	u32 con, div, src, p_rate;
1670 
1671 	switch (clk_id) {
1672 	case SCLK_UART0:
1673 		con = readl(&cru->clksel_con[60]);
1674 		break;
1675 	case SCLK_UART1:
1676 		con = readl(&cru->pmuclksel_con[8]);
1677 		src = (con & CLK_UART1_SEL_MASK) >> CLK_UART1_SEL_SHIFT;
1678 		if (src == CLK_UART1_SEL_OSC)
1679 			return OSC_HZ;
1680 		con = readl(&cru->clksel_con[27]);
1681 		break;
1682 	case SCLK_UART2:
1683 		con = readl(&cru->clksel_con[61]);
1684 		break;
1685 	case SCLK_UART3:
1686 		con = readl(&cru->clksel_con[62]);
1687 		break;
1688 	case SCLK_UART4:
1689 		con = readl(&cru->clksel_con[63]);
1690 		break;
1691 	case SCLK_UART5:
1692 		con = readl(&cru->clksel_con[64]);
1693 		break;
1694 	case SCLK_UART6:
1695 		con = readl(&cru->clksel_con[65]);
1696 		break;
1697 	case SCLK_UART7:
1698 		con = readl(&cru->clksel_con[66]);
1699 		break;
1700 	case SCLK_UART8:
1701 		con = readl(&cru->clksel_con[67]);
1702 		break;
1703 	case SCLK_UART9:
1704 		con = readl(&cru->clksel_con[68]);
1705 		break;
1706 	case SCLK_UART10:
1707 		con = readl(&cru->clksel_con[69]);
1708 		break;
1709 	case SCLK_UART11:
1710 		con = readl(&cru->clksel_con[70]);
1711 		break;
1712 	default:
1713 		return -ENOENT;
1714 	}
1715 	if (clk_id == SCLK_UART1) {
1716 		src = (con & CLK_UART1_SRC_SEL_SHIFT) >> CLK_UART1_SRC_SEL_SHIFT;
1717 		div = (con & CLK_UART1_SRC_DIV_MASK) >> CLK_UART1_SRC_DIV_SHIFT;
1718 	} else {
1719 		src = (con & CLK_UART_SEL_MASK) >> CLK_UART_SEL_SHIFT;
1720 		div = (con & CLK_UART_DIV_MASK) >> CLK_UART_DIV_SHIFT;
1721 	}
1722 	if (src == CLK_UART_SEL_GPLL)
1723 		p_rate = priv->gpll_hz;
1724 	else  if (src == CLK_UART_SEL_CPLL)
1725 		p_rate = priv->cpll_hz;
1726 	else  if (src == CLK_UART_SEL_AUPLL)
1727 		p_rate = priv->aupll_hz;
1728 	else  if (src == CLK_UART_SEL_FRAC0)
1729 		p_rate = rk3576_uart_frac_get_rate(priv, CLK_UART_FRAC_0);
1730 	else  if (src == CLK_UART_SEL_FRAC1)
1731 		p_rate = rk3576_uart_frac_get_rate(priv, CLK_UART_FRAC_1);
1732 	else  if (src == CLK_UART_SEL_FRAC2)
1733 		p_rate = rk3576_uart_frac_get_rate(priv, CLK_UART_FRAC_2);
1734 	else
1735 		p_rate = OSC_HZ;
1736 
1737 	return DIV_TO_RATE(p_rate, div);
1738 }
1739 
1740 static ulong rk3576_uart_set_rate(struct rk3576_clk_priv *priv,
1741 				  ulong clk_id, ulong rate)
1742 {
1743 	struct rk3576_cru *cru = priv->cru;
1744 	u32 reg, clk_src = 0, div = 0;
1745 
1746 	if (!(priv->gpll_hz % rate)) {
1747 		clk_src = CLK_UART_SEL_GPLL;
1748 		div = DIV_ROUND_UP(priv->gpll_hz, rate);
1749 	} else if (!(priv->cpll_hz % rate)) {
1750 		clk_src = CLK_UART_SEL_CPLL;
1751 		div = DIV_ROUND_UP(priv->gpll_hz, rate);
1752 	} else if (!(rk3576_uart_frac_get_rate(priv, CLK_UART_FRAC_0) % rate)) {
1753 		clk_src = CLK_UART_SEL_FRAC0;
1754 		div = DIV_ROUND_UP(rk3576_uart_frac_get_rate(priv, CLK_UART_FRAC_0), rate);
1755 	} else if (!(rk3576_uart_frac_get_rate(priv, CLK_UART_FRAC_1) % rate)) {
1756 		clk_src = CLK_UART_SEL_FRAC1;
1757 		div = DIV_ROUND_UP(rk3576_uart_frac_get_rate(priv, CLK_UART_FRAC_1), rate);
1758 	} else if (!(rk3576_uart_frac_get_rate(priv, CLK_UART_FRAC_2) % rate)) {
1759 		clk_src = CLK_UART_SEL_FRAC2;
1760 		div = DIV_ROUND_UP(rk3576_uart_frac_get_rate(priv, CLK_UART_FRAC_2), rate);
1761 	} else if (!(OSC_HZ % rate)) {
1762 		clk_src = CLK_UART_SEL_OSC;
1763 		div = DIV_ROUND_UP(OSC_HZ, rate);
1764 	}
1765 
1766 	switch (clk_id) {
1767 	case SCLK_UART0:
1768 		reg = 60;
1769 		break;
1770 	case SCLK_UART1:
1771 		if (rate == OSC_HZ) {
1772 			rk_clrsetreg(&cru->pmuclksel_con[8],
1773 		     CLK_UART1_SEL_MASK,
1774 		     (CLK_UART1_SEL_OSC << CLK_UART1_SEL_SHIFT));
1775 			return 0;
1776 		} else {
1777 		rk_clrsetreg(&cru->clksel_con[27],
1778 		     CLK_UART1_SRC_SEL_MASK |
1779 		     CLK_UART1_SRC_DIV_MASK,
1780 		     (clk_src << CLK_UART1_SRC_SEL_SHIFT) |
1781 		     ((div - 1) << CLK_UART1_SRC_DIV_SHIFT));
1782 		rk_clrsetreg(&cru->pmuclksel_con[8],
1783 		     CLK_UART1_SEL_MASK,
1784 		     (CLK_UART1_SEL_TOP << CLK_UART1_SEL_SHIFT));
1785 		return 0;
1786 		}
1787 		break;
1788 	case SCLK_UART2:
1789 		reg = 61;
1790 		break;
1791 	case SCLK_UART3:
1792 		reg = 62;
1793 		break;
1794 	case SCLK_UART4:
1795 		reg = 63;
1796 		break;
1797 	case SCLK_UART5:
1798 		reg = 64;
1799 		break;
1800 	case SCLK_UART6:
1801 		reg = 65;
1802 		break;
1803 	case SCLK_UART7:
1804 		reg = 66;
1805 		break;
1806 	case SCLK_UART8:
1807 		reg = 67;
1808 		break;
1809 	case SCLK_UART9:
1810 		reg = 68;
1811 		break;
1812 	case SCLK_UART10:
1813 		reg = 69;
1814 		break;
1815 	case SCLK_UART11:
1816 		reg = 70;
1817 		break;
1818 	default:
1819 		return -ENOENT;
1820 	}
1821 	rk_clrsetreg(&cru->clksel_con[reg],
1822 		     CLK_UART_SEL_MASK |
1823 		     CLK_UART_DIV_MASK,
1824 		     (clk_src << CLK_UART_SEL_SHIFT) |
1825 		     ((div - 1) << CLK_UART_DIV_SHIFT));
1826 
1827 	return rk3576_uart_get_rate(priv, clk_id);
1828 }
1829 #endif
1830 
1831 static ulong rk3576_ufs_ref_get_rate(struct rk3576_clk_priv *priv, ulong clk_id)
1832 {
1833 	struct rk3576_cru *cru = priv->cru;
1834 	u32 src, div;
1835 
1836 	src = readl(&cru->pmuclksel_con[3]) & 0x3;
1837 	div= readl(&cru->pmuclksel_con[1]) & 0xff;
1838 	if (src == 0)
1839 		return OSC_HZ;
1840 	else if (src == 2)
1841 		return priv->ppll_hz / (div + 1);
1842 	else
1843 		return 26000000;
1844 
1845 }
1846 
1847 static ulong rk3576_clk_get_rate(struct clk *clk)
1848 {
1849 	struct rk3576_clk_priv *priv = dev_get_priv(clk->dev);
1850 	ulong rate = 0;
1851 
1852 	if (!priv->gpll_hz) {
1853 		printf("%s gpll=%lu\n", __func__, priv->gpll_hz);
1854 		return -ENOENT;
1855 	}
1856 
1857 	if (!priv->ppll_hz) {
1858 		priv->ppll_hz = rockchip_pll_get_rate(&rk3576_pll_clks[PPLL],
1859 						      priv->cru, PPLL);
1860 	}
1861 
1862 	switch (clk->id) {
1863 	case PLL_LPLL:
1864 		rate = rockchip_pll_get_rate(&rk3576_pll_clks[LPLL], priv->cru,
1865 					     LPLL);
1866 		priv->lpll_hz = rate;
1867 		break;
1868 	case PLL_BPLL:
1869 		rate = rockchip_pll_get_rate(&rk3576_pll_clks[BPLL], priv->cru,
1870 					     BPLL);
1871 		priv->bpll_hz = rate;
1872 		break;
1873 	case PLL_GPLL:
1874 		rate = rockchip_pll_get_rate(&rk3576_pll_clks[GPLL], priv->cru,
1875 					     GPLL);
1876 		break;
1877 	case PLL_CPLL:
1878 		rate = rockchip_pll_get_rate(&rk3576_pll_clks[CPLL], priv->cru,
1879 					     CPLL);
1880 		break;
1881 	case PLL_VPLL:
1882 		rate = rockchip_pll_get_rate(&rk3576_pll_clks[VPLL], priv->cru,
1883 					     VPLL);
1884 		break;
1885 	case PLL_AUPLL:
1886 		rate = rockchip_pll_get_rate(&rk3576_pll_clks[AUPLL], priv->cru,
1887 					     AUPLL);
1888 		break;
1889 	case PLL_PPLL:
1890 		rate = rockchip_pll_get_rate(&rk3576_pll_clks[PPLL], priv->cru,
1891 					     PPLL) * 2;
1892 		break;
1893 	case ACLK_BUS_ROOT:
1894 	case HCLK_BUS_ROOT:
1895 	case PCLK_BUS_ROOT:
1896 		rate = rk3576_bus_get_clk(priv, clk->id);
1897 		break;
1898 	case ACLK_TOP:
1899 	case HCLK_TOP:
1900 	case PCLK_TOP_ROOT:
1901 	case ACLK_TOP_MID:
1902 		rate = rk3576_top_get_clk(priv, clk->id);
1903 		break;
1904 	case CLK_I2C0:
1905 	case CLK_I2C1:
1906 	case CLK_I2C2:
1907 	case CLK_I2C3:
1908 	case CLK_I2C4:
1909 	case CLK_I2C5:
1910 	case CLK_I2C6:
1911 	case CLK_I2C7:
1912 	case CLK_I2C8:
1913 	case CLK_I2C9:
1914 		rate = rk3576_i2c_get_clk(priv, clk->id);
1915 		break;
1916 	case CLK_SPI0:
1917 	case CLK_SPI1:
1918 	case CLK_SPI2:
1919 	case CLK_SPI3:
1920 	case CLK_SPI4:
1921 		rate = rk3576_spi_get_clk(priv, clk->id);
1922 		break;
1923 	case CLK_PWM1:
1924 	case CLK_PWM2:
1925 	case CLK_PMU1PWM:
1926 		rate = rk3576_pwm_get_clk(priv, clk->id);
1927 		break;
1928 	case CLK_SARADC:
1929 	case CLK_TSADC:
1930 		rate = rk3576_adc_get_clk(priv, clk->id);
1931 		break;
1932 	case CCLK_SRC_SDIO:
1933 	case CCLK_SRC_SDMMC0:
1934 	case CCLK_SRC_EMMC:
1935 	case BCLK_EMMC:
1936 	case SCLK_FSPI_X2:
1937 	case SCLK_FSPI1_X2:
1938 		rate = rk3576_mmc_get_clk(priv, clk->id);
1939 		break;
1940 	case TCLK_WDT0:
1941 		rate = OSC_HZ;
1942 		break;
1943 #ifndef CONFIG_SPL_BUILD
1944 	case ACLK_VOP_ROOT:
1945 	case ACLK_VOP:
1946 	case ACLK_VO0_ROOT:
1947 	case ACLK_VO1_ROOT:
1948 	case HCLK_VOP_ROOT:
1949 	case PCLK_VOP_ROOT:
1950 		rate = rk3576_aclk_vop_get_clk(priv, clk->id);
1951 		break;
1952 	case DCLK_VP0:
1953 	case DCLK_VP0_SRC:
1954 	case DCLK_VP1:
1955 	case DCLK_VP1_SRC:
1956 	case DCLK_VP2:
1957 	case DCLK_VP2_SRC:
1958 		rate = rk3576_dclk_vop_get_clk(priv, clk->id);
1959 		break;
1960 	case CLK_GMAC0_PTP_REF_SRC:
1961 	case CLK_GMAC1_PTP_REF_SRC:
1962 	case CLK_GMAC0_PTP_REF:
1963 	case CLK_GMAC1_PTP_REF:
1964 	case CLK_GMAC0_125M_SRC:
1965 	case CLK_GMAC1_125M_SRC:
1966 		rate = rk3576_gmac_get_clk(priv, clk->id);
1967 		break;
1968 	case CLK_UART_FRAC_0:
1969 	case CLK_UART_FRAC_1:
1970 	case CLK_UART_FRAC_2:
1971 		rate = rk3576_uart_frac_get_rate(priv, clk->id);
1972 		break;
1973 	case SCLK_UART0:
1974 	case SCLK_UART1:
1975 	case SCLK_UART2:
1976 	case SCLK_UART3:
1977 	case SCLK_UART4:
1978 	case SCLK_UART5:
1979 	case SCLK_UART6:
1980 	case SCLK_UART7:
1981 	case SCLK_UART8:
1982 	case SCLK_UART9:
1983 	case SCLK_UART10:
1984 	case SCLK_UART11:
1985 		rate = rk3576_uart_get_rate(priv, clk->id);
1986 		break;
1987 	case CLK_DSIHOST0:
1988 		rate = rk3576_clk_csihost_get_clk(priv, clk->id);
1989 		break;
1990 	case DCLK_EBC:
1991 	case DCLK_EBC_FRAC_SRC:
1992 		rate = rk3576_dclk_ebc_get_clk(priv, clk->id);
1993 		break;
1994 #endif
1995 	case CLK_REF_UFS_CLKOUT:
1996 	case CLK_REF_OSC_MPHY:
1997 		rate = rk3576_ufs_ref_get_rate(priv, clk->id);
1998 		break;
1999 
2000 	default:
2001 		return -ENOENT;
2002 	}
2003 
2004 	return rate;
2005 };
2006 
2007 static ulong rk3576_clk_set_rate(struct clk *clk, ulong rate)
2008 {
2009 	struct rk3576_clk_priv *priv = dev_get_priv(clk->dev);
2010 	ulong ret = 0;
2011 
2012 	if (!priv->ppll_hz) {
2013 		priv->ppll_hz = rockchip_pll_get_rate(&rk3576_pll_clks[PPLL],
2014 						      priv->cru, PPLL);
2015 	}
2016 	if (!priv->aupll_hz) {
2017 		priv->aupll_hz = rockchip_pll_get_rate(&rk3576_pll_clks[AUPLL],
2018 						      priv->cru, AUPLL);
2019 	}
2020 
2021 	switch (clk->id) {
2022 	case PLL_CPLL:
2023 		ret = rockchip_pll_set_rate(&rk3576_pll_clks[CPLL], priv->cru,
2024 					    CPLL, rate);
2025 		priv->cpll_hz = rockchip_pll_get_rate(&rk3576_pll_clks[CPLL],
2026 						      priv->cru, CPLL);
2027 		break;
2028 	case PLL_GPLL:
2029 		ret = rockchip_pll_set_rate(&rk3576_pll_clks[GPLL], priv->cru,
2030 					    GPLL, rate);
2031 		priv->gpll_hz = rockchip_pll_get_rate(&rk3576_pll_clks[GPLL],
2032 						      priv->cru, GPLL);
2033 		break;
2034 	case PLL_VPLL:
2035 		ret = rockchip_pll_set_rate(&rk3576_pll_clks[VPLL], priv->cru,
2036 					    VPLL, rate);
2037 		priv->vpll_hz = rockchip_pll_get_rate(&rk3576_pll_clks[VPLL],
2038 						       priv->cru, VPLL);
2039 		break;
2040 	case PLL_AUPLL:
2041 		ret = rockchip_pll_set_rate(&rk3576_pll_clks[AUPLL], priv->cru,
2042 					    AUPLL, rate);
2043 		priv->aupll_hz = rockchip_pll_get_rate(&rk3576_pll_clks[AUPLL],
2044 						       priv->cru, AUPLL);
2045 		break;
2046 	case PLL_PPLL:
2047 		ret = rockchip_pll_set_rate(&rk3576_pll_clks[PPLL], priv->cru,
2048 					    PPLL, rate);
2049 		priv->ppll_hz = rockchip_pll_get_rate(&rk3576_pll_clks[PPLL],
2050 						      priv->cru, PPLL) * 2;
2051 		break;
2052 	case ACLK_BUS_ROOT:
2053 	case HCLK_BUS_ROOT:
2054 	case PCLK_BUS_ROOT:
2055 		ret = rk3576_bus_set_clk(priv, clk->id, rate);
2056 		break;
2057 	case ACLK_TOP:
2058 	case HCLK_TOP:
2059 	case PCLK_TOP_ROOT:
2060 	case ACLK_TOP_MID:
2061 		ret = rk3576_top_set_clk(priv, clk->id, rate);
2062 		break;
2063 	case CLK_I2C0:
2064 	case CLK_I2C1:
2065 	case CLK_I2C2:
2066 	case CLK_I2C3:
2067 	case CLK_I2C4:
2068 	case CLK_I2C5:
2069 	case CLK_I2C6:
2070 	case CLK_I2C7:
2071 	case CLK_I2C8:
2072 	case CLK_I2C9:
2073 		ret = rk3576_i2c_set_clk(priv, clk->id, rate);
2074 		break;
2075 	case CLK_SPI0:
2076 	case CLK_SPI1:
2077 	case CLK_SPI2:
2078 	case CLK_SPI3:
2079 	case CLK_SPI4:
2080 		ret = rk3576_spi_set_clk(priv, clk->id, rate);
2081 		break;
2082 	case CLK_PWM1:
2083 	case CLK_PWM2:
2084 	case CLK_PMU1PWM:
2085 		ret = rk3576_pwm_set_clk(priv, clk->id, rate);
2086 		break;
2087 	case CLK_SARADC:
2088 	case CLK_TSADC:
2089 		ret = rk3576_adc_set_clk(priv, clk->id, rate);
2090 		break;
2091 	case CCLK_SRC_SDIO:
2092 	case CCLK_SRC_SDMMC0:
2093 	case CCLK_SRC_EMMC:
2094 	case BCLK_EMMC:
2095 	case SCLK_FSPI_X2:
2096 	case SCLK_FSPI1_X2:
2097 		ret = rk3576_mmc_set_clk(priv, clk->id, rate);
2098 		break;
2099 	case TCLK_WDT0:
2100 		ret = OSC_HZ;
2101 		break;
2102 #ifndef CONFIG_SPL_BUILD
2103 	case ACLK_VOP_ROOT:
2104 	case ACLK_VOP:
2105 	case ACLK_VO0_ROOT:
2106 	case ACLK_VO1_ROOT:
2107 	case HCLK_VOP_ROOT:
2108 	case PCLK_VOP_ROOT:
2109 		ret = rk3576_aclk_vop_set_clk(priv, clk->id, rate);
2110 		break;
2111 	case DCLK_VP0:
2112 	case DCLK_VP0_SRC:
2113 	case DCLK_VP1:
2114 	case DCLK_VP1_SRC:
2115 	case DCLK_VP2:
2116 	case DCLK_VP2_SRC:
2117 		ret = rk3576_dclk_vop_set_clk(priv, clk->id, rate);
2118 		break;
2119 	case CLK_GMAC0_PTP_REF_SRC:
2120 	case CLK_GMAC1_PTP_REF_SRC:
2121 	case CLK_GMAC0_PTP_REF:
2122 	case CLK_GMAC1_PTP_REF:
2123 	case CLK_GMAC0_125M_SRC:
2124 	case CLK_GMAC1_125M_SRC:
2125 		ret = rk3576_gmac_set_clk(priv, clk->id, rate);
2126 		break;
2127 	case CLK_UART_FRAC_0:
2128 	case CLK_UART_FRAC_1:
2129 	case CLK_UART_FRAC_2:
2130 		ret = rk3576_uart_frac_set_rate(priv, clk->id, rate);
2131 		break;
2132 	case SCLK_UART0:
2133 	case SCLK_UART1:
2134 	case SCLK_UART2:
2135 	case SCLK_UART3:
2136 	case SCLK_UART4:
2137 	case SCLK_UART5:
2138 	case SCLK_UART6:
2139 	case SCLK_UART7:
2140 	case SCLK_UART8:
2141 	case SCLK_UART9:
2142 	case SCLK_UART10:
2143 	case SCLK_UART11:
2144 		ret = rk3576_uart_set_rate(priv, clk->id, rate);
2145 		break;
2146 	case CLK_DSIHOST0:
2147 		ret = rk3576_clk_csihost_set_clk(priv, clk->id, rate);
2148 		break;
2149 	case DCLK_EBC:
2150 	case DCLK_EBC_FRAC_SRC:
2151 		ret = rk3576_dclk_ebc_set_clk(priv, clk->id, rate);
2152 		break;
2153 #endif
2154 	default:
2155 		return -ENOENT;
2156 	}
2157 
2158 	return ret;
2159 };
2160 
2161 #if (IS_ENABLED(OF_CONTROL)) || (!IS_ENABLED(OF_PLATDATA))
2162 static int __maybe_unused rk3576_dclk_vop_set_parent(struct clk *clk,
2163 						     struct clk *parent)
2164 {
2165 	struct rk3576_clk_priv *priv = dev_get_priv(clk->dev);
2166 	struct rk3576_cru *cru = priv->cru;
2167 	u32 sel;
2168 	const char *clock_dev_name = parent->dev->name;
2169 
2170 	if (parent->id == PLL_VPLL)
2171 		sel = 2;
2172 	else if (parent->id == PLL_GPLL)
2173 		sel = 0;
2174 	else if (parent->id == PLL_CPLL)
2175 		sel = 1;
2176 	else if (parent->id == PLL_BPLL)
2177 		sel = 3;
2178 	else
2179 		sel = 4;
2180 
2181 	switch (clk->id) {
2182 	case DCLK_VP0_SRC:
2183 		rk_clrsetreg(&cru->clksel_con[145], DCLK0_VOP_SRC_SEL_MASK,
2184 			     sel << DCLK0_VOP_SRC_SEL_SHIFT);
2185 		break;
2186 	case DCLK_VP1_SRC:
2187 		rk_clrsetreg(&cru->clksel_con[146], DCLK0_VOP_SRC_SEL_MASK,
2188 			     sel << DCLK0_VOP_SRC_SEL_SHIFT);
2189 		break;
2190 	case DCLK_VP2_SRC:
2191 		rk_clrsetreg(&cru->clksel_con[147], DCLK0_VOP_SRC_SEL_MASK,
2192 			     sel << DCLK0_VOP_SRC_SEL_SHIFT);
2193 		break;
2194 	case DCLK_VP0:
2195 		if (!strcmp(clock_dev_name, "hdmiphypll_clk0"))
2196 			sel = 1;
2197 		else
2198 			sel = 0;
2199 		rk_clrsetreg(&cru->clksel_con[147], DCLK0_VOP_SEL_MASK,
2200 			     sel << DCLK0_VOP_SEL_SHIFT);
2201 		break;
2202 	case DCLK_VP1:
2203 		if (!strcmp(clock_dev_name, "hdmiphypll_clk0"))
2204 			sel = 1;
2205 		else
2206 			sel = 0;
2207 		rk_clrsetreg(&cru->clksel_con[147], DCLK1_VOP_SEL_MASK,
2208 			     sel << DCLK1_VOP_SEL_SHIFT);
2209 		break;
2210 	case DCLK_VP2:
2211 		if (!strcmp(clock_dev_name, "hdmiphypll_clk0"))
2212 			sel = 1;
2213 		else
2214 			sel = 0;
2215 		rk_clrsetreg(&cru->clksel_con[147], DCLK2_VOP_SEL_MASK,
2216 			     sel << DCLK2_VOP_SEL_SHIFT);
2217 		break;
2218 	default:
2219 		return -EINVAL;
2220 	}
2221 	return 0;
2222 }
2223 
2224 static int __maybe_unused rk3576_ufs_ref_set_parent(struct clk *clk,
2225 						     struct clk *parent)
2226 {
2227 	struct rk3576_clk_priv *priv = dev_get_priv(clk->dev);
2228 	struct rk3576_cru *cru = priv->cru;
2229 	u32 sel;
2230 	const char *clock_dev_name = parent->dev->name;
2231 
2232 	if (parent->id == CLK_REF_MPHY_26M)
2233 		sel = 2;
2234 	else if (!strcmp(clock_dev_name, "xin24m"))
2235 		sel = 0;
2236 	else
2237 		sel = 1;
2238 
2239 	rk_clrsetreg(&cru->pmuclksel_con[3], 0x3, sel << 0);
2240 	return 0;
2241 }
2242 
2243 static int rk3576_clk_set_parent(struct clk *clk, struct clk *parent)
2244 {
2245 	switch (clk->id) {
2246 	case DCLK_VP0_SRC:
2247 	case DCLK_VP1_SRC:
2248 	case DCLK_VP2_SRC:
2249 	case DCLK_VP0:
2250 	case DCLK_VP1:
2251 	case DCLK_VP2:
2252 		return rk3576_dclk_vop_set_parent(clk, parent);
2253 	case CLK_REF_OSC_MPHY:
2254 		return rk3576_ufs_ref_set_parent(clk, parent);
2255 
2256 	default:
2257 		return -ENOENT;
2258 	}
2259 
2260 	return 0;
2261 }
2262 #endif
2263 
2264 static struct clk_ops rk3576_clk_ops = {
2265 	.get_rate = rk3576_clk_get_rate,
2266 	.set_rate = rk3576_clk_set_rate,
2267 #if (IS_ENABLED(OF_CONTROL)) || (!IS_ENABLED(OF_PLATDATA))
2268 	.set_parent = rk3576_clk_set_parent,
2269 #endif
2270 };
2271 
2272 static void rk3576_clk_init(struct rk3576_clk_priv *priv)
2273 {
2274 	int ret;
2275 
2276 	priv->spll_hz = 702000000;
2277 
2278 	if (priv->cpll_hz != CPLL_HZ) {
2279 		ret = rockchip_pll_set_rate(&rk3576_pll_clks[CPLL], priv->cru,
2280 					    CPLL, CPLL_HZ);
2281 		if (!ret)
2282 			priv->cpll_hz = CPLL_HZ;
2283 	}
2284 	if (priv->gpll_hz != GPLL_HZ) {
2285 		ret = rockchip_pll_set_rate(&rk3576_pll_clks[GPLL], priv->cru,
2286 					    GPLL, GPLL_HZ);
2287 		if (!ret)
2288 			priv->gpll_hz = GPLL_HZ;
2289 	}
2290 }
2291 
2292 static int rk3576_clk_probe(struct udevice *dev)
2293 {
2294 	struct rk3576_clk_priv *priv = dev_get_priv(dev);
2295 	int ret;
2296 
2297 	priv->sync_kernel = false;
2298 
2299 #ifdef CONFIG_SPL_BUILD
2300 	/* relase presetn_bigcore_biu/cru/grf */
2301 	writel(0x1c001c00, 0x26010010);
2302 	/* set spll to normal mode */
2303 	writel(BITS_WITH_WMASK(2, 0x7U, 6),
2304 	       RK3576_SCRU_BASE + RK3576_PLL_CON(137));
2305 	writel(BITS_WITH_WMASK(1, 0x3U, 0),
2306 	       RK3576_SCRU_BASE + RK3576_MODE_CON0);
2307 	/* fix ppll\aupll\cpll */
2308 	writel(BITS_WITH_WMASK(2, 0x7U, 6),
2309 	       RK3576_CRU_BASE + RK3576_PMU_PLL_CON(129));
2310 	writel(BITS_WITH_WMASK(2, 0x7U, 6),
2311 	       RK3576_CRU_BASE + RK3576_PLL_CON(97));
2312 	writel(BITS_WITH_WMASK(2, 0x7U, 6),
2313 	       RK3576_CRU_BASE + RK3576_PLL_CON(105));
2314 	writel(BITS_WITH_WMASK(1, 0x3U, 6),
2315 	       RK3576_CRU_BASE + RK3576_MODE_CON0);
2316 	writel(BITS_WITH_WMASK(1, 0x3U, 8),
2317 	       RK3576_CRU_BASE + RK3576_MODE_CON0);
2318 	/* init cci */
2319 	writel(0xffff0000, RK3576_CRU_BASE + RK3576_CCI_CLKSEL_CON(4));
2320 	rockchip_pll_set_rate(&rk3576_pll_clks[BPLL], priv->cru,
2321 			      BPLL, LPLL_HZ);
2322 	if (!priv->armclk_enter_hz) {
2323 		ret = rockchip_pll_set_rate(&rk3576_pll_clks[LPLL], priv->cru,
2324 					    LPLL, LPLL_HZ);
2325 		priv->armclk_enter_hz =
2326 			rockchip_pll_get_rate(&rk3576_pll_clks[LPLL],
2327 					      priv->cru, LPLL);
2328 		priv->armclk_init_hz = priv->armclk_enter_hz;
2329 		rk_clrsetreg(&priv->cru->litclksel_con[0], CLK_LITCORE_DIV_MASK,
2330 			     0 << CLK_LITCORE_DIV_SHIFT);
2331 	}
2332 #endif
2333 
2334 	priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
2335 	if (IS_ERR(priv->grf))
2336 		return PTR_ERR(priv->grf);
2337 
2338 	rk3576_clk_init(priv);
2339 	/* init cci */
2340 	writel(0xffff20cb, RK3576_CRU_BASE + RK3576_CCI_CLKSEL_CON(4));
2341 
2342 	/* Process 'assigned-{clocks/clock-parents/clock-rates}' properties */
2343 	ret = clk_set_defaults(dev);
2344 	if (ret)
2345 		debug("%s clk_set_defaults failed %d\n", __func__, ret);
2346 	else
2347 		priv->sync_kernel = true;
2348 
2349 	return 0;
2350 }
2351 
2352 static int rk3576_clk_ofdata_to_platdata(struct udevice *dev)
2353 {
2354 	struct rk3576_clk_priv *priv = dev_get_priv(dev);
2355 
2356 	priv->cru = dev_read_addr_ptr(dev);
2357 
2358 	return 0;
2359 }
2360 
2361 static int rk3576_clk_bind(struct udevice *dev)
2362 {
2363 	int ret;
2364 	struct udevice *sys_child, *sf_child;
2365 	struct sysreset_reg *priv;
2366 	struct softreset_reg *sf_priv;
2367 
2368 	/* The reset driver does not have a device node, so bind it here */
2369 	ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset",
2370 				 &sys_child);
2371 	if (ret) {
2372 		debug("Warning: No sysreset driver: ret=%d\n", ret);
2373 	} else {
2374 		priv = malloc(sizeof(struct sysreset_reg));
2375 		priv->glb_srst_fst_value = offsetof(struct rk3576_cru,
2376 						    glb_srst_fst);
2377 		priv->glb_srst_snd_value = offsetof(struct rk3576_cru,
2378 						    glb_srsr_snd);
2379 		sys_child->priv = priv;
2380 	}
2381 
2382 	ret = device_bind_driver_to_node(dev, "rockchip_reset", "reset",
2383 					 dev_ofnode(dev), &sf_child);
2384 	if (ret) {
2385 		debug("Warning: No rockchip reset driver: ret=%d\n", ret);
2386 	} else {
2387 		sf_priv = malloc(sizeof(struct softreset_reg));
2388 		sf_priv->sf_reset_offset = offsetof(struct rk3576_cru,
2389 						    softrst_con[0]);
2390 		sf_priv->sf_reset_num = 524454;
2391 		sf_child->priv = sf_priv;
2392 	}
2393 
2394 	return 0;
2395 }
2396 
2397 static const struct udevice_id rk3576_clk_ids[] = {
2398 	{ .compatible = "rockchip,rk3576-cru" },
2399 	{ }
2400 };
2401 
2402 U_BOOT_DRIVER(rockchip_rk3576_cru) = {
2403 	.name		= "rockchip_rk3576_cru",
2404 	.id		= UCLASS_CLK,
2405 	.of_match	= rk3576_clk_ids,
2406 	.priv_auto_alloc_size = sizeof(struct rk3576_clk_priv),
2407 	.ofdata_to_platdata = rk3576_clk_ofdata_to_platdata,
2408 	.ops		= &rk3576_clk_ops,
2409 	.bind		= rk3576_clk_bind,
2410 	.probe		= rk3576_clk_probe,
2411 };
2412 
2413 #ifndef CONFIG_SPL_BUILD
2414 /**
2415  * soc_clk_dump() - Print clock frequencies
2416  * Returns zero on success
2417  *
2418  * Implementation for the clk dump command.
2419  */
2420 int soc_clk_dump(void)
2421 {
2422 	struct udevice *cru_dev;
2423 	struct rk3576_clk_priv *priv;
2424 	const struct rk3576_clk_info *clk_dump;
2425 	struct clk clk;
2426 	unsigned long clk_count = ARRAY_SIZE(clks_dump);
2427 	unsigned long rate;
2428 	int i, ret;
2429 
2430 	ret = uclass_get_device_by_driver(UCLASS_CLK,
2431 					  DM_GET_DRIVER(rockchip_rk3576_cru),
2432 					  &cru_dev);
2433 	if (ret) {
2434 		printf("%s failed to get cru device\n", __func__);
2435 		return ret;
2436 	}
2437 
2438 	priv = dev_get_priv(cru_dev);
2439 	printf("CLK: (%s. arm: enter %lu KHz, init %lu KHz, kernel %lu%s)\n",
2440 	       priv->sync_kernel ? "sync kernel" : "uboot",
2441 	       priv->armclk_enter_hz / 1000,
2442 	       priv->armclk_init_hz / 1000,
2443 	       priv->set_armclk_rate ? priv->armclk_hz / 1000 : 0,
2444 	       priv->set_armclk_rate ? " KHz" : "N/A");
2445 	for (i = 0; i < clk_count; i++) {
2446 		clk_dump = &clks_dump[i];
2447 		if (clk_dump->name) {
2448 			memset(&clk, 0, sizeof(struct clk));
2449 			clk.id = clk_dump->id;
2450 			if (clk_dump->is_cru)
2451 				ret = clk_request(cru_dev, &clk);
2452 			if (ret < 0)
2453 				return ret;
2454 
2455 			rate = clk_get_rate(&clk);
2456 			clk_free(&clk);
2457 			if (rate < 0)
2458 				printf("  %s %s\n", clk_dump->name,
2459 				       "unknown");
2460 			else
2461 				printf("  %s %lu KHz\n", clk_dump->name,
2462 				       rate / 1000);
2463 		}
2464 	}
2465 
2466 	return 0;
2467 }
2468 #endif
2469