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