xref: /rk3399_rockchip-uboot/drivers/clk/rockchip/clk_rk3576.c (revision 3f3f40cd59320e8b274fce3e3becf4dd08c2c8a4)
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 	ulong pll_rate, now, best_rate = 0;
1436 	u32 i, con, sel, div, best_div = 0, best_sel = 0;
1437 	unsigned long m = 0, n = 0, val;
1438 
1439 	switch (clk_id) {
1440 	case DCLK_EBC:
1441 		con = readl(&cru->clksel_con[123]);
1442 		sel = (con & DCLK_EBC_SEL_MASK) >> DCLK_EBC_SEL_SHIFT;
1443 		if (sel == DCLK_EBC_SEL_VPLL) {
1444 			pll_rate = rockchip_pll_get_rate(&rk3576_pll_clks[VPLL],
1445 							 priv->cru, VPLL);
1446 			if (pll_rate >= RK3576_VOP_PLL_LIMIT_FREQ &&
1447 			    pll_rate % rate == 0) {
1448 				div = DIV_ROUND_UP(pll_rate, rate);
1449 				rk_clrsetreg(&cru->clksel_con[123],
1450 					     DCLK_EBC_DIV_MASK,
1451 					     (div - 1) << DCLK_EBC_DIV_SHIFT);
1452 			} else {
1453 				div = DIV_ROUND_UP(RK3576_VOP_PLL_LIMIT_FREQ,
1454 						   rate);
1455 				if (div % 2)
1456 					div = div + 1;
1457 				rk_clrsetreg(&cru->clksel_con[123],
1458 					     DCLK_EBC_DIV_MASK,
1459 					     (div - 1) << DCLK_EBC_DIV_SHIFT);
1460 				rockchip_pll_set_rate(&rk3576_pll_clks[VPLL],
1461 						      priv->cru,
1462 						      VPLL, div * rate);
1463 				priv->vpll_hz = rockchip_pll_get_rate(&rk3576_pll_clks[VPLL],
1464 								      priv->cru,
1465 								      VPLL);
1466 			}
1467 		} else if (sel == DCLK_EBC_SEL_FRAC_SRC) {
1468 			rk3576_dclk_ebc_set_clk(priv, DCLK_EBC_FRAC_SRC, rate);
1469 			div = rk3576_dclk_ebc_get_clk(priv, DCLK_EBC_FRAC_SRC) / rate;
1470 			rk_clrsetreg(&cru->clksel_con[123],
1471 				     DCLK_EBC_DIV_MASK,
1472 				     (div - 1) << DCLK_EBC_DIV_SHIFT);
1473 		} else {
1474 			for (i = 0; i <= DCLK_EBC_SEL_LPLL; i++) {
1475 				switch (i) {
1476 				case DCLK_EBC_SEL_GPLL:
1477 					pll_rate = priv->gpll_hz;
1478 					break;
1479 				case DCLK_EBC_SEL_CPLL:
1480 					pll_rate = priv->cpll_hz;
1481 					break;
1482 				case DCLK_EBC_SEL_VPLL:
1483 					pll_rate = 0;
1484 					break;
1485 				case DCLK_EBC_SEL_AUPLL:
1486 					pll_rate = priv->aupll_hz;
1487 					break;
1488 				case DCLK_EBC_SEL_LPLL:
1489 					pll_rate = 0;
1490 					break;
1491 				default:
1492 					printf("not support ebc pll sel\n");
1493 					return -EINVAL;
1494 				}
1495 
1496 				div = DIV_ROUND_UP(pll_rate, rate);
1497 				if (div > 255)
1498 					continue;
1499 				now = pll_rate / div;
1500 				if (abs(rate - now) < abs(rate - best_rate)) {
1501 					best_rate = now;
1502 					best_div = div;
1503 					best_sel = i;
1504 				}
1505 			}
1506 
1507 			if (best_rate) {
1508 				rk_clrsetreg(&cru->clksel_con[123],
1509 					     DCLK_EBC_DIV_MASK |
1510 					     DCLK_EBC_SEL_MASK,
1511 					     best_sel <<
1512 					     DCLK_EBC_SEL_SHIFT |
1513 					     (best_div - 1) <<
1514 					     DCLK_EBC_DIV_SHIFT);
1515 			} else {
1516 				printf("do not support this vop freq %lu\n",
1517 				       rate);
1518 				return -EINVAL;
1519 			}
1520 		}
1521 		break;
1522 	case DCLK_EBC_FRAC_SRC:
1523 		sel = DCLK_EBC_FRAC_SRC_SEL_GPLL;
1524 		div = 1;
1525 		rational_best_approximation(rate, priv->gpll_hz,
1526 					    GENMASK(16 - 1, 0),
1527 					    GENMASK(16 - 1, 0),
1528 					    &m, &n);
1529 
1530 		if (m < 4 && m != 0) {
1531 			if (n % 2 == 0)
1532 				val = 1;
1533 			else
1534 				val = DIV_ROUND_UP(4, m);
1535 
1536 			n *= val;
1537 			m *= val;
1538 			if (n > 0xffff) {
1539 				n = 0xffff;
1540 			}
1541 		}
1542 
1543 		rk_clrsetreg(&cru->clksel_con[123],
1544 		     DCLK_EBC_FRAC_SRC_SEL_MASK,
1545 		     (sel << DCLK_EBC_FRAC_SRC_SEL_SHIFT));
1546 		if (m && n) {
1547 			val = m << CLK_UART_FRAC_NUMERATOR_SHIFT | n;
1548 			writel(val, &cru->clksel_con[122]);
1549 		}
1550 		break;
1551 	default:
1552 		return -ENOENT;
1553 	}
1554 	return rk3576_dclk_ebc_get_clk(priv, clk_id);
1555 }
1556 
1557 static ulong rk3576_gmac_get_clk(struct rk3576_clk_priv *priv, ulong clk_id)
1558 {
1559 	struct rk3576_cru *cru = priv->cru;
1560 	u32 con, div, src, p_rate;
1561 
1562 	switch (clk_id) {
1563 	case CLK_GMAC0_PTP_REF_SRC:
1564 	case CLK_GMAC0_PTP_REF:
1565 		con = readl(&cru->clksel_con[105]);
1566 		div = (con & CLK_GMAC0_PTP_DIV_MASK) >> CLK_GMAC0_PTP_DIV_SHIFT;
1567 		src = (con & CLK_GMAC0_PTP_SEL_MASK) >> CLK_GMAC0_PTP_SEL_SHIFT;
1568 		if (src == CLK_GMAC0_PTP_SEL_GPLL)
1569 			p_rate = priv->gpll_hz;
1570 		else if (src == CLK_GMAC0_PTP_SEL_CPLL)
1571 			p_rate = priv->cpll_hz;
1572 		else
1573 			p_rate = GMAC0_PTP_REFCLK_IN;
1574 		return DIV_TO_RATE(p_rate, div);
1575 	case CLK_GMAC1_PTP_REF_SRC:
1576 	case CLK_GMAC1_PTP_REF:
1577 		con = readl(&cru->clksel_con[104]);
1578 		div = (con & CLK_GMAC1_PTP_DIV_MASK) >> CLK_GMAC0_PTP_DIV_SHIFT;
1579 		src = (con & CLK_GMAC1_PTP_SEL_MASK) >> CLK_GMAC1_PTP_SEL_SHIFT;
1580 		if (src == CLK_GMAC1_PTP_SEL_GPLL)
1581 			p_rate = priv->gpll_hz;
1582 		else if (src == CLK_GMAC1_PTP_SEL_CPLL)
1583 			p_rate = priv->cpll_hz;
1584 		else
1585 			p_rate = GMAC1_PTP_REFCLK_IN;
1586 		return DIV_TO_RATE(p_rate, div);
1587 	case CLK_GMAC0_125M_SRC:
1588 		con = readl(&cru->clksel_con[30]);
1589 		div = (con & CLK_GMAC0_125M_DIV_MASK) >> CLK_GMAC0_125M_DIV_SHIFT;
1590 		return DIV_TO_RATE(priv->cpll_hz, div);
1591 	case CLK_GMAC1_125M_SRC:
1592 		con = readl(&cru->clksel_con[31]);
1593 		div = (con & CLK_GMAC1_125M_DIV_MASK) >> CLK_GMAC1_125M_DIV_SHIFT;
1594 		return DIV_TO_RATE(priv->cpll_hz, div);
1595 	default:
1596 		return -ENOENT;
1597 	}
1598 }
1599 
1600 static ulong rk3576_gmac_set_clk(struct rk3576_clk_priv *priv,
1601 				 ulong clk_id, ulong rate)
1602 {
1603 	struct rk3576_cru *cru = priv->cru;
1604 	int div, src;
1605 
1606 	div = DIV_ROUND_UP(priv->cpll_hz, rate);
1607 
1608 	switch (clk_id) {
1609 	case CLK_GMAC0_PTP_REF_SRC:
1610 	case CLK_GMAC0_PTP_REF:
1611 		if (rate == GMAC0_PTP_REFCLK_IN) {
1612 			src = CLK_GMAC0_PTP_SEL_REFIN;
1613 			div = 1;
1614 		} else if (!(priv->gpll_hz % rate)) {
1615 			src = CLK_GMAC0_PTP_SEL_GPLL;
1616 			div = priv->gpll_hz / rate;
1617 		} else {
1618 			src = CLK_GMAC0_PTP_SEL_CPLL;
1619 			div = priv->cpll_hz / rate;
1620 		}
1621 		rk_clrsetreg(&cru->clksel_con[105],
1622 			     CLK_GMAC0_PTP_DIV_MASK | CLK_GMAC0_PTP_SEL_MASK,
1623 			     src << CLK_GMAC0_PTP_SEL_SHIFT |
1624 			     (div - 1) << CLK_GMAC0_PTP_DIV_SHIFT);
1625 		break;
1626 	case CLK_GMAC1_PTP_REF_SRC:
1627 	case CLK_GMAC1_PTP_REF:
1628 		if (rate == GMAC1_PTP_REFCLK_IN) {
1629 			src = CLK_GMAC1_PTP_SEL_REFIN;
1630 			div = 1;
1631 		} else if (!(priv->gpll_hz % rate)) {
1632 			src = CLK_GMAC1_PTP_SEL_GPLL;
1633 			div = priv->gpll_hz / rate;
1634 		} else {
1635 			src = CLK_GMAC1_PTP_SEL_CPLL;
1636 			div = priv->cpll_hz / rate;
1637 		}
1638 		rk_clrsetreg(&cru->clksel_con[104],
1639 			     CLK_GMAC1_PTP_DIV_MASK | CLK_GMAC1_PTP_SEL_MASK,
1640 			     src << CLK_GMAC1_PTP_SEL_SHIFT |
1641 			     (div - 1) << CLK_GMAC1_PTP_DIV_SHIFT);
1642 		break;
1643 
1644 	case CLK_GMAC0_125M_SRC:
1645 		rk_clrsetreg(&cru->clksel_con[30],
1646 			     CLK_GMAC0_125M_DIV_MASK,
1647 			     (div - 1) << CLK_GMAC0_125M_DIV_SHIFT);
1648 		break;
1649 	case CLK_GMAC1_125M_SRC:
1650 		rk_clrsetreg(&cru->clksel_con[31],
1651 			     CLK_GMAC1_125M_DIV_MASK,
1652 			     (div - 1) << CLK_GMAC1_125M_DIV_SHIFT);
1653 		break;
1654 	default:
1655 		return -ENOENT;
1656 	}
1657 
1658 	return rk3576_gmac_get_clk(priv, clk_id);
1659 }
1660 
1661 static ulong rk3576_uart_frac_get_rate(struct rk3576_clk_priv *priv, ulong clk_id)
1662 {
1663 	struct rk3576_cru *cru = priv->cru;
1664 	u32 reg, con, fracdiv, p_src, p_rate;
1665 	unsigned long m, n;
1666 
1667 	switch (clk_id) {
1668 	case CLK_UART_FRAC_0:
1669 		reg = 21;
1670 		break;
1671 	case CLK_UART_FRAC_1:
1672 		reg = 23;
1673 		break;
1674 	case CLK_UART_FRAC_2:
1675 		reg = 25;
1676 		break;
1677 	default:
1678 		return -ENOENT;
1679 	}
1680 	con = readl(&cru->clksel_con[reg + 1]);
1681 	p_src = (con & CLK_UART_SRC_SEL_MASK) >> CLK_UART_SRC_SEL_SHIFT;
1682 	if (p_src == CLK_UART_SRC_SEL_GPLL)
1683 		p_rate = priv->gpll_hz;
1684 	else if (p_src == CLK_UART_SRC_SEL_CPLL)
1685 		p_rate = priv->cpll_hz;
1686 	else if (p_src == CLK_UART_SRC_SEL_AUPLL)
1687 		p_rate = priv->aupll_hz;
1688 	else
1689 		p_rate = OSC_HZ;
1690 
1691 	fracdiv = readl(&cru->clksel_con[reg]);
1692 	n = fracdiv & CLK_UART_FRAC_NUMERATOR_MASK;
1693 	n >>= CLK_UART_FRAC_NUMERATOR_SHIFT;
1694 	m = fracdiv & CLK_UART_FRAC_DENOMINATOR_MASK;
1695 	m >>= CLK_UART_FRAC_DENOMINATOR_SHIFT;
1696 	return p_rate * n / m;
1697 }
1698 
1699 static ulong rk3576_uart_frac_set_rate(struct rk3576_clk_priv *priv,
1700 				  ulong clk_id, ulong rate)
1701 {
1702 	struct rk3576_cru *cru = priv->cru;
1703 	u32 reg, clk_src, p_rate;
1704 	unsigned long m = 0, n = 0, val;
1705 
1706 	if (priv->cpll_hz % rate == 0) {
1707 		clk_src = CLK_UART_SRC_SEL_CPLL;
1708 		p_rate = priv->cpll_hz;
1709 	} else if (rate == OSC_HZ) {
1710 		clk_src = CLK_UART_SRC_SEL_OSC;
1711 		p_rate = OSC_HZ;
1712 	} else {
1713 		clk_src = CLK_UART_SRC_SEL_GPLL;
1714 		p_rate = priv->cpll_hz;
1715 	}
1716 	rational_best_approximation(rate, p_rate,
1717 					    GENMASK(16 - 1, 0),
1718 					    GENMASK(16 - 1, 0),
1719 					    &m, &n);
1720 
1721 	if (m < 4 && m != 0) {
1722 		if (n % 2 == 0)
1723 			val = 1;
1724 		else
1725 			val = DIV_ROUND_UP(4, m);
1726 
1727 		n *= val;
1728 		m *= val;
1729 		if (n > 0xffff) {
1730 			n = 0xffff;
1731 		}
1732 	}
1733 
1734 
1735 	switch (clk_id) {
1736 	case CLK_UART_FRAC_0:
1737 		reg = 21;
1738 		break;
1739 	case CLK_UART_FRAC_1:
1740 		reg = 23;
1741 		break;
1742 	case CLK_UART_FRAC_2:
1743 		reg = 25;
1744 		break;
1745 	default:
1746 		return -ENOENT;
1747 	}
1748 	rk_clrsetreg(&cru->clksel_con[reg +1],
1749 		     CLK_UART_SRC_SEL_MASK,
1750 		     (clk_src << CLK_UART_SRC_SEL_SHIFT));
1751 	if (m && n) {
1752 		val = m << CLK_UART_FRAC_NUMERATOR_SHIFT | n;
1753 		writel(val, &cru->clksel_con[reg]);
1754 	}
1755 
1756 	return rk3576_uart_frac_get_rate(priv, clk_id);
1757 }
1758 
1759 
1760 static ulong rk3576_uart_get_rate(struct rk3576_clk_priv *priv, ulong clk_id)
1761 {
1762 	struct rk3576_cru *cru = priv->cru;
1763 	u32 con, div, src, p_rate;
1764 
1765 	switch (clk_id) {
1766 	case SCLK_UART0:
1767 		con = readl(&cru->clksel_con[60]);
1768 		break;
1769 	case SCLK_UART1:
1770 		con = readl(&cru->pmuclksel_con[8]);
1771 		src = (con & CLK_UART1_SEL_MASK) >> CLK_UART1_SEL_SHIFT;
1772 		if (src == CLK_UART1_SEL_OSC)
1773 			return OSC_HZ;
1774 		con = readl(&cru->clksel_con[27]);
1775 		break;
1776 	case SCLK_UART2:
1777 		con = readl(&cru->clksel_con[61]);
1778 		break;
1779 	case SCLK_UART3:
1780 		con = readl(&cru->clksel_con[62]);
1781 		break;
1782 	case SCLK_UART4:
1783 		con = readl(&cru->clksel_con[63]);
1784 		break;
1785 	case SCLK_UART5:
1786 		con = readl(&cru->clksel_con[64]);
1787 		break;
1788 	case SCLK_UART6:
1789 		con = readl(&cru->clksel_con[65]);
1790 		break;
1791 	case SCLK_UART7:
1792 		con = readl(&cru->clksel_con[66]);
1793 		break;
1794 	case SCLK_UART8:
1795 		con = readl(&cru->clksel_con[67]);
1796 		break;
1797 	case SCLK_UART9:
1798 		con = readl(&cru->clksel_con[68]);
1799 		break;
1800 	case SCLK_UART10:
1801 		con = readl(&cru->clksel_con[69]);
1802 		break;
1803 	case SCLK_UART11:
1804 		con = readl(&cru->clksel_con[70]);
1805 		break;
1806 	default:
1807 		return -ENOENT;
1808 	}
1809 	if (clk_id == SCLK_UART1) {
1810 		src = (con & CLK_UART1_SRC_SEL_SHIFT) >> CLK_UART1_SRC_SEL_SHIFT;
1811 		div = (con & CLK_UART1_SRC_DIV_MASK) >> CLK_UART1_SRC_DIV_SHIFT;
1812 	} else {
1813 		src = (con & CLK_UART_SEL_MASK) >> CLK_UART_SEL_SHIFT;
1814 		div = (con & CLK_UART_DIV_MASK) >> CLK_UART_DIV_SHIFT;
1815 	}
1816 	if (src == CLK_UART_SEL_GPLL)
1817 		p_rate = priv->gpll_hz;
1818 	else  if (src == CLK_UART_SEL_CPLL)
1819 		p_rate = priv->cpll_hz;
1820 	else  if (src == CLK_UART_SEL_AUPLL)
1821 		p_rate = priv->aupll_hz;
1822 	else  if (src == CLK_UART_SEL_FRAC0)
1823 		p_rate = rk3576_uart_frac_get_rate(priv, CLK_UART_FRAC_0);
1824 	else  if (src == CLK_UART_SEL_FRAC1)
1825 		p_rate = rk3576_uart_frac_get_rate(priv, CLK_UART_FRAC_1);
1826 	else  if (src == CLK_UART_SEL_FRAC2)
1827 		p_rate = rk3576_uart_frac_get_rate(priv, CLK_UART_FRAC_2);
1828 	else
1829 		p_rate = OSC_HZ;
1830 
1831 	return DIV_TO_RATE(p_rate, div);
1832 }
1833 
1834 static ulong rk3576_uart_set_rate(struct rk3576_clk_priv *priv,
1835 				  ulong clk_id, ulong rate)
1836 {
1837 	struct rk3576_cru *cru = priv->cru;
1838 	u32 reg, clk_src = 0, div = 0;
1839 
1840 	if (!(priv->gpll_hz % rate)) {
1841 		clk_src = CLK_UART_SEL_GPLL;
1842 		div = DIV_ROUND_UP(priv->gpll_hz, rate);
1843 	} else if (!(priv->cpll_hz % rate)) {
1844 		clk_src = CLK_UART_SEL_CPLL;
1845 		div = DIV_ROUND_UP(priv->gpll_hz, rate);
1846 	} else if (!(rk3576_uart_frac_get_rate(priv, CLK_UART_FRAC_0) % rate)) {
1847 		clk_src = CLK_UART_SEL_FRAC0;
1848 		div = DIV_ROUND_UP(rk3576_uart_frac_get_rate(priv, CLK_UART_FRAC_0), rate);
1849 	} else if (!(rk3576_uart_frac_get_rate(priv, CLK_UART_FRAC_1) % rate)) {
1850 		clk_src = CLK_UART_SEL_FRAC1;
1851 		div = DIV_ROUND_UP(rk3576_uart_frac_get_rate(priv, CLK_UART_FRAC_1), rate);
1852 	} else if (!(rk3576_uart_frac_get_rate(priv, CLK_UART_FRAC_2) % rate)) {
1853 		clk_src = CLK_UART_SEL_FRAC2;
1854 		div = DIV_ROUND_UP(rk3576_uart_frac_get_rate(priv, CLK_UART_FRAC_2), rate);
1855 	} else if (!(OSC_HZ % rate)) {
1856 		clk_src = CLK_UART_SEL_OSC;
1857 		div = DIV_ROUND_UP(OSC_HZ, rate);
1858 	}
1859 
1860 	switch (clk_id) {
1861 	case SCLK_UART0:
1862 		reg = 60;
1863 		break;
1864 	case SCLK_UART1:
1865 		if (rate == OSC_HZ) {
1866 			rk_clrsetreg(&cru->pmuclksel_con[8],
1867 		     CLK_UART1_SEL_MASK,
1868 		     (CLK_UART1_SEL_OSC << CLK_UART1_SEL_SHIFT));
1869 			return 0;
1870 		} else {
1871 		rk_clrsetreg(&cru->clksel_con[27],
1872 		     CLK_UART1_SRC_SEL_MASK |
1873 		     CLK_UART1_SRC_DIV_MASK,
1874 		     (clk_src << CLK_UART1_SRC_SEL_SHIFT) |
1875 		     ((div - 1) << CLK_UART1_SRC_DIV_SHIFT));
1876 		rk_clrsetreg(&cru->pmuclksel_con[8],
1877 		     CLK_UART1_SEL_MASK,
1878 		     (CLK_UART1_SEL_TOP << CLK_UART1_SEL_SHIFT));
1879 		return 0;
1880 		}
1881 		break;
1882 	case SCLK_UART2:
1883 		reg = 61;
1884 		break;
1885 	case SCLK_UART3:
1886 		reg = 62;
1887 		break;
1888 	case SCLK_UART4:
1889 		reg = 63;
1890 		break;
1891 	case SCLK_UART5:
1892 		reg = 64;
1893 		break;
1894 	case SCLK_UART6:
1895 		reg = 65;
1896 		break;
1897 	case SCLK_UART7:
1898 		reg = 66;
1899 		break;
1900 	case SCLK_UART8:
1901 		reg = 67;
1902 		break;
1903 	case SCLK_UART9:
1904 		reg = 68;
1905 		break;
1906 	case SCLK_UART10:
1907 		reg = 69;
1908 		break;
1909 	case SCLK_UART11:
1910 		reg = 70;
1911 		break;
1912 	default:
1913 		return -ENOENT;
1914 	}
1915 	rk_clrsetreg(&cru->clksel_con[reg],
1916 		     CLK_UART_SEL_MASK |
1917 		     CLK_UART_DIV_MASK,
1918 		     (clk_src << CLK_UART_SEL_SHIFT) |
1919 		     ((div - 1) << CLK_UART_DIV_SHIFT));
1920 
1921 	return rk3576_uart_get_rate(priv, clk_id);
1922 }
1923 
1924 static ulong rk3576_ref_clkout_get_clk(struct rk3576_clk_priv *priv,
1925 				       ulong clk_id)
1926 {
1927 	struct rk3576_cru *cru = priv->cru;
1928 	u32 reg, con, div, src, p_rate;
1929 
1930 	switch (clk_id) {
1931 	case REF_CLK0_OUT_PLL:
1932 		reg = 33;
1933 		break;
1934 	case REF_CLK1_OUT_PLL:
1935 		reg = 34;
1936 		break;
1937 	case REF_CLK2_OUT_PLL:
1938 		reg = 35;
1939 		break;
1940 	default:
1941 		return -ENOENT;
1942 	}
1943 	con = readl(&cru->clksel_con[reg]);
1944 	div = (con & REF_CLK0_OUT_PLL_DIV_MASK) >> REF_CLK0_OUT_PLL_DIV_SHIFT;
1945 	src = (con & REF_CLK0_OUT_PLL_SEL_MASK) >> REF_CLK0_OUT_PLL_SEL_SHIFT;
1946 	if (src == REF_CLK0_OUT_PLL_SEL_GPLL)
1947 		p_rate = priv->gpll_hz;
1948 	else if (src == REF_CLK0_OUT_PLL_SEL_CPLL)
1949 		p_rate = priv->cpll_hz;
1950 	else if (src == REF_CLK0_OUT_PLL_SEL_SPLL)
1951 		p_rate = priv->spll_hz;
1952 	else if (src == REF_CLK0_OUT_PLL_SEL_AUPLL)
1953 		p_rate = priv->aupll_hz;
1954 	else if (src == REF_CLK0_OUT_PLL_SEL_LPLL)
1955 		p_rate = priv->lpll_hz / 2;
1956 	else
1957 		p_rate = OSC_HZ;
1958 	return DIV_TO_RATE(p_rate, div);
1959 }
1960 
1961 static ulong rk3576_ref_clkout_set_clk(struct rk3576_clk_priv *priv,
1962 				       ulong clk_id, ulong rate)
1963 {
1964 	struct rk3576_cru *cru = priv->cru;
1965 	ulong p_rate, now, best_rate = 0;
1966 	u32 i, con, div, best_div = 0, best_sel = 0;
1967 
1968 	switch (clk_id) {
1969 	case REF_CLK0_OUT_PLL:
1970 		con = 33;
1971 		break;
1972 	case REF_CLK1_OUT_PLL:
1973 		con = 34;
1974 		break;
1975 	case REF_CLK2_OUT_PLL:
1976 		con = 35;
1977 		break;
1978 	default:
1979 		return -ENOENT;
1980 	}
1981 
1982 	for (i = 0; i <= REF_CLK0_OUT_PLL_SEL_OSC; i++) {
1983 		switch (i) {
1984 		case REF_CLK0_OUT_PLL_SEL_GPLL:
1985 			p_rate = priv->gpll_hz;
1986 			break;
1987 		case REF_CLK0_OUT_PLL_SEL_CPLL:
1988 			p_rate = priv->cpll_hz;
1989 			break;
1990 		case REF_CLK0_OUT_PLL_SEL_SPLL:
1991 			p_rate = priv->spll_hz;
1992 			break;
1993 		case REF_CLK0_OUT_PLL_SEL_AUPLL:
1994 			p_rate = priv->aupll_hz;
1995 			break;
1996 		case REF_CLK0_OUT_PLL_SEL_LPLL:
1997 			p_rate = 0;
1998 			break;
1999 		case REF_CLK0_OUT_PLL_SEL_OSC:
2000 			p_rate = OSC_HZ;
2001 			break;
2002 		default:
2003 			printf("do not support this vop pll sel\n");
2004 			return -EINVAL;
2005 		}
2006 
2007 		div = DIV_ROUND_UP(p_rate, rate);
2008 		if (div > 255)
2009 			continue;
2010 		now = p_rate / div;
2011 		if (abs(rate - now) < abs(rate - best_rate)) {
2012 			best_rate = now;
2013 			best_div = div;
2014 			best_sel = i;
2015 		}
2016 		debug("p_rate=%lu, best_rate=%lu, div=%u, sel=%u\n",
2017 		      p_rate, best_rate, best_div, best_sel);
2018 	}
2019 	if (best_rate) {
2020 		rk_clrsetreg(&cru->clksel_con[con],
2021 			     REF_CLK0_OUT_PLL_DIV_MASK |
2022 			     REF_CLK0_OUT_PLL_SEL_MASK,
2023 			     best_sel << REF_CLK0_OUT_PLL_SEL_SHIFT |
2024 			     (best_div - 1) << REF_CLK0_OUT_PLL_DIV_SHIFT);
2025 	} else {
2026 		printf("do not support this vop freq %lu\n", rate);
2027 		return -EINVAL;
2028 	}
2029 
2030 	return rk3576_ref_clkout_get_clk(priv, clk_id);
2031 }
2032 
2033 #endif
2034 
2035 static ulong rk3576_ufs_ref_get_rate(struct rk3576_clk_priv *priv, ulong clk_id)
2036 {
2037 	struct rk3576_cru *cru = priv->cru;
2038 	u32 src, div;
2039 
2040 	src = readl(&cru->pmuclksel_con[3]) & 0x3;
2041 	div= readl(&cru->pmuclksel_con[1]) & 0xff;
2042 	if (src == 0)
2043 		return OSC_HZ;
2044 	else if (src == 2)
2045 		return priv->ppll_hz / (div + 1);
2046 	else
2047 		return 26000000;
2048 
2049 }
2050 
2051 static ulong rk3576_clk_get_rate(struct clk *clk)
2052 {
2053 	struct rk3576_clk_priv *priv = dev_get_priv(clk->dev);
2054 	ulong rate = 0;
2055 
2056 	if (!priv->gpll_hz) {
2057 		printf("%s gpll=%lu\n", __func__, priv->gpll_hz);
2058 		return -ENOENT;
2059 	}
2060 
2061 	if (!priv->ppll_hz) {
2062 		priv->ppll_hz = rockchip_pll_get_rate(&rk3576_pll_clks[PPLL],
2063 						      priv->cru, PPLL);
2064 	}
2065 
2066 	switch (clk->id) {
2067 	case PLL_LPLL:
2068 		rate = rockchip_pll_get_rate(&rk3576_pll_clks[LPLL], priv->cru,
2069 					     LPLL);
2070 		priv->lpll_hz = rate;
2071 		break;
2072 	case PLL_BPLL:
2073 		rate = rockchip_pll_get_rate(&rk3576_pll_clks[BPLL], priv->cru,
2074 					     BPLL);
2075 		priv->bpll_hz = rate;
2076 		break;
2077 	case PLL_GPLL:
2078 		rate = rockchip_pll_get_rate(&rk3576_pll_clks[GPLL], priv->cru,
2079 					     GPLL);
2080 		break;
2081 	case PLL_CPLL:
2082 		rate = rockchip_pll_get_rate(&rk3576_pll_clks[CPLL], priv->cru,
2083 					     CPLL);
2084 		break;
2085 	case PLL_VPLL:
2086 		rate = rockchip_pll_get_rate(&rk3576_pll_clks[VPLL], priv->cru,
2087 					     VPLL);
2088 		break;
2089 	case PLL_AUPLL:
2090 		rate = rockchip_pll_get_rate(&rk3576_pll_clks[AUPLL], priv->cru,
2091 					     AUPLL);
2092 		break;
2093 	case PLL_PPLL:
2094 		rate = rockchip_pll_get_rate(&rk3576_pll_clks[PPLL], priv->cru,
2095 					     PPLL) * 2;
2096 		break;
2097 	case ACLK_BUS_ROOT:
2098 	case HCLK_BUS_ROOT:
2099 	case PCLK_BUS_ROOT:
2100 		rate = rk3576_bus_get_clk(priv, clk->id);
2101 		break;
2102 	case ACLK_TOP:
2103 	case HCLK_TOP:
2104 	case PCLK_TOP_ROOT:
2105 	case ACLK_TOP_MID:
2106 		rate = rk3576_top_get_clk(priv, clk->id);
2107 		break;
2108 	case CLK_I2C0:
2109 	case CLK_I2C1:
2110 	case CLK_I2C2:
2111 	case CLK_I2C3:
2112 	case CLK_I2C4:
2113 	case CLK_I2C5:
2114 	case CLK_I2C6:
2115 	case CLK_I2C7:
2116 	case CLK_I2C8:
2117 	case CLK_I2C9:
2118 		rate = rk3576_i2c_get_clk(priv, clk->id);
2119 		break;
2120 	case CLK_SPI0:
2121 	case CLK_SPI1:
2122 	case CLK_SPI2:
2123 	case CLK_SPI3:
2124 	case CLK_SPI4:
2125 		rate = rk3576_spi_get_clk(priv, clk->id);
2126 		break;
2127 	case CLK_PWM1:
2128 	case CLK_PWM2:
2129 	case CLK_PMU1PWM:
2130 		rate = rk3576_pwm_get_clk(priv, clk->id);
2131 		break;
2132 	case CLK_SARADC:
2133 	case CLK_TSADC:
2134 		rate = rk3576_adc_get_clk(priv, clk->id);
2135 		break;
2136 	case CCLK_SRC_SDIO:
2137 	case CCLK_SRC_SDMMC0:
2138 	case CCLK_SRC_EMMC:
2139 	case BCLK_EMMC:
2140 	case SCLK_FSPI_X2:
2141 	case SCLK_FSPI1_X2:
2142 	case DCLK_DECOM:
2143 	case HCLK_SDMMC0:
2144 	case HCLK_EMMC:
2145 	case HCLK_SDIO:
2146 		rate = rk3576_mmc_get_clk(priv, clk->id);
2147 		break;
2148 	case TCLK_WDT0:
2149 		rate = OSC_HZ;
2150 		break;
2151 #ifndef CONFIG_SPL_BUILD
2152 	case ACLK_VOP_ROOT:
2153 	case ACLK_VOP:
2154 	case ACLK_VO0_ROOT:
2155 	case ACLK_VO1_ROOT:
2156 	case HCLK_VOP_ROOT:
2157 	case PCLK_VOP_ROOT:
2158 		rate = rk3576_aclk_vop_get_clk(priv, clk->id);
2159 		break;
2160 	case DCLK_VP0:
2161 	case DCLK_VP0_SRC:
2162 	case DCLK_VP1:
2163 	case DCLK_VP1_SRC:
2164 	case DCLK_VP2:
2165 	case DCLK_VP2_SRC:
2166 		rate = rk3576_dclk_vop_get_clk(priv, clk->id);
2167 		break;
2168 	case CLK_GMAC0_PTP_REF_SRC:
2169 	case CLK_GMAC1_PTP_REF_SRC:
2170 	case CLK_GMAC0_PTP_REF:
2171 	case CLK_GMAC1_PTP_REF:
2172 	case CLK_GMAC0_125M_SRC:
2173 	case CLK_GMAC1_125M_SRC:
2174 		rate = rk3576_gmac_get_clk(priv, clk->id);
2175 		break;
2176 	case CLK_UART_FRAC_0:
2177 	case CLK_UART_FRAC_1:
2178 	case CLK_UART_FRAC_2:
2179 		rate = rk3576_uart_frac_get_rate(priv, clk->id);
2180 		break;
2181 	case SCLK_UART0:
2182 	case SCLK_UART1:
2183 	case SCLK_UART2:
2184 	case SCLK_UART3:
2185 	case SCLK_UART4:
2186 	case SCLK_UART5:
2187 	case SCLK_UART6:
2188 	case SCLK_UART7:
2189 	case SCLK_UART8:
2190 	case SCLK_UART9:
2191 	case SCLK_UART10:
2192 	case SCLK_UART11:
2193 		rate = rk3576_uart_get_rate(priv, clk->id);
2194 		break;
2195 	case CLK_DSIHOST0:
2196 		rate = rk3576_clk_csihost_get_clk(priv, clk->id);
2197 		break;
2198 	case DCLK_EBC:
2199 	case DCLK_EBC_FRAC_SRC:
2200 		rate = rk3576_dclk_ebc_get_clk(priv, clk->id);
2201 		break;
2202 	case REF_CLK0_OUT_PLL:
2203 	case REF_CLK1_OUT_PLL:
2204 	case REF_CLK2_OUT_PLL:
2205 		rate = rk3576_ref_clkout_get_clk(priv, clk->id);
2206 		break;
2207 #endif
2208 	case CLK_REF_UFS_CLKOUT:
2209 	case CLK_REF_OSC_MPHY:
2210 		rate = rk3576_ufs_ref_get_rate(priv, clk->id);
2211 		break;
2212 
2213 	default:
2214 		return -ENOENT;
2215 	}
2216 
2217 	return rate;
2218 };
2219 
2220 static ulong rk3576_clk_set_rate(struct clk *clk, ulong rate)
2221 {
2222 	struct rk3576_clk_priv *priv = dev_get_priv(clk->dev);
2223 	ulong ret = 0;
2224 
2225 	if (!priv->ppll_hz) {
2226 		priv->ppll_hz = rockchip_pll_get_rate(&rk3576_pll_clks[PPLL],
2227 						      priv->cru, PPLL);
2228 	}
2229 	if (!priv->aupll_hz) {
2230 		priv->aupll_hz = rockchip_pll_get_rate(&rk3576_pll_clks[AUPLL],
2231 						      priv->cru, AUPLL);
2232 	}
2233 
2234 	switch (clk->id) {
2235 	case PLL_CPLL:
2236 		ret = rockchip_pll_set_rate(&rk3576_pll_clks[CPLL], priv->cru,
2237 					    CPLL, rate);
2238 		priv->cpll_hz = rockchip_pll_get_rate(&rk3576_pll_clks[CPLL],
2239 						      priv->cru, CPLL);
2240 		break;
2241 	case PLL_GPLL:
2242 		ret = rockchip_pll_set_rate(&rk3576_pll_clks[GPLL], priv->cru,
2243 					    GPLL, rate);
2244 		priv->gpll_hz = rockchip_pll_get_rate(&rk3576_pll_clks[GPLL],
2245 						      priv->cru, GPLL);
2246 		break;
2247 	case PLL_VPLL:
2248 		ret = rockchip_pll_set_rate(&rk3576_pll_clks[VPLL], priv->cru,
2249 					    VPLL, rate);
2250 		priv->vpll_hz = rockchip_pll_get_rate(&rk3576_pll_clks[VPLL],
2251 						       priv->cru, VPLL);
2252 		break;
2253 	case PLL_AUPLL:
2254 		ret = rockchip_pll_set_rate(&rk3576_pll_clks[AUPLL], priv->cru,
2255 					    AUPLL, rate);
2256 		priv->aupll_hz = rockchip_pll_get_rate(&rk3576_pll_clks[AUPLL],
2257 						       priv->cru, AUPLL);
2258 		break;
2259 	case PLL_PPLL:
2260 		ret = rockchip_pll_set_rate(&rk3576_pll_clks[PPLL], priv->cru,
2261 					    PPLL, rate);
2262 		priv->ppll_hz = rockchip_pll_get_rate(&rk3576_pll_clks[PPLL],
2263 						      priv->cru, PPLL) * 2;
2264 		break;
2265 	case ACLK_BUS_ROOT:
2266 	case HCLK_BUS_ROOT:
2267 	case PCLK_BUS_ROOT:
2268 		ret = rk3576_bus_set_clk(priv, clk->id, rate);
2269 		break;
2270 	case ACLK_TOP:
2271 	case HCLK_TOP:
2272 	case PCLK_TOP_ROOT:
2273 	case ACLK_TOP_MID:
2274 		ret = rk3576_top_set_clk(priv, clk->id, rate);
2275 		break;
2276 	case CLK_I2C0:
2277 	case CLK_I2C1:
2278 	case CLK_I2C2:
2279 	case CLK_I2C3:
2280 	case CLK_I2C4:
2281 	case CLK_I2C5:
2282 	case CLK_I2C6:
2283 	case CLK_I2C7:
2284 	case CLK_I2C8:
2285 	case CLK_I2C9:
2286 		ret = rk3576_i2c_set_clk(priv, clk->id, rate);
2287 		break;
2288 	case CLK_SPI0:
2289 	case CLK_SPI1:
2290 	case CLK_SPI2:
2291 	case CLK_SPI3:
2292 	case CLK_SPI4:
2293 		ret = rk3576_spi_set_clk(priv, clk->id, rate);
2294 		break;
2295 	case CLK_PWM1:
2296 	case CLK_PWM2:
2297 	case CLK_PMU1PWM:
2298 		ret = rk3576_pwm_set_clk(priv, clk->id, rate);
2299 		break;
2300 	case CLK_SARADC:
2301 	case CLK_TSADC:
2302 		ret = rk3576_adc_set_clk(priv, clk->id, rate);
2303 		break;
2304 	case CCLK_SRC_SDIO:
2305 	case CCLK_SRC_SDMMC0:
2306 	case CCLK_SRC_EMMC:
2307 	case BCLK_EMMC:
2308 	case SCLK_FSPI_X2:
2309 	case SCLK_FSPI1_X2:
2310 	case DCLK_DECOM:
2311 	case HCLK_SDMMC0:
2312 	case HCLK_EMMC:
2313 	case HCLK_SDIO:
2314 		ret = rk3576_mmc_set_clk(priv, clk->id, rate);
2315 		break;
2316 	case TCLK_WDT0:
2317 		ret = OSC_HZ;
2318 		break;
2319 #ifndef CONFIG_SPL_BUILD
2320 	case ACLK_VOP_ROOT:
2321 	case ACLK_VOP:
2322 	case ACLK_VO0_ROOT:
2323 	case ACLK_VO1_ROOT:
2324 	case HCLK_VOP_ROOT:
2325 	case PCLK_VOP_ROOT:
2326 		ret = rk3576_aclk_vop_set_clk(priv, clk->id, rate);
2327 		break;
2328 	case DCLK_VP0:
2329 	case DCLK_VP0_SRC:
2330 	case DCLK_VP1:
2331 	case DCLK_VP1_SRC:
2332 	case DCLK_VP2:
2333 	case DCLK_VP2_SRC:
2334 		ret = rk3576_dclk_vop_set_clk(priv, clk->id, rate);
2335 		break;
2336 	case CLK_GMAC0_PTP_REF_SRC:
2337 	case CLK_GMAC1_PTP_REF_SRC:
2338 	case CLK_GMAC0_PTP_REF:
2339 	case CLK_GMAC1_PTP_REF:
2340 	case CLK_GMAC0_125M_SRC:
2341 	case CLK_GMAC1_125M_SRC:
2342 		ret = rk3576_gmac_set_clk(priv, clk->id, rate);
2343 		break;
2344 	case CLK_UART_FRAC_0:
2345 	case CLK_UART_FRAC_1:
2346 	case CLK_UART_FRAC_2:
2347 		ret = rk3576_uart_frac_set_rate(priv, clk->id, rate);
2348 		break;
2349 	case SCLK_UART0:
2350 	case SCLK_UART1:
2351 	case SCLK_UART2:
2352 	case SCLK_UART3:
2353 	case SCLK_UART4:
2354 	case SCLK_UART5:
2355 	case SCLK_UART6:
2356 	case SCLK_UART7:
2357 	case SCLK_UART8:
2358 	case SCLK_UART9:
2359 	case SCLK_UART10:
2360 	case SCLK_UART11:
2361 		ret = rk3576_uart_set_rate(priv, clk->id, rate);
2362 		break;
2363 	case CLK_DSIHOST0:
2364 		ret = rk3576_clk_csihost_set_clk(priv, clk->id, rate);
2365 		break;
2366 	case DCLK_EBC:
2367 	case DCLK_EBC_FRAC_SRC:
2368 		ret = rk3576_dclk_ebc_set_clk(priv, clk->id, rate);
2369 		break;
2370 	case REF_CLK0_OUT_PLL:
2371 	case REF_CLK1_OUT_PLL:
2372 	case REF_CLK2_OUT_PLL:
2373 		ret = rk3576_ref_clkout_set_clk(priv, clk->id, rate);
2374 		break;
2375 #endif
2376 	default:
2377 		return -ENOENT;
2378 	}
2379 
2380 	return ret;
2381 };
2382 
2383 #if (IS_ENABLED(OF_CONTROL)) || (!IS_ENABLED(OF_PLATDATA))
2384 static int __maybe_unused rk3576_dclk_vop_set_parent(struct clk *clk,
2385 						     struct clk *parent)
2386 {
2387 	struct rk3576_clk_priv *priv = dev_get_priv(clk->dev);
2388 	struct rk3576_cru *cru = priv->cru;
2389 	u32 sel;
2390 	const char *clock_dev_name = parent->dev->name;
2391 
2392 	if (parent->id == PLL_VPLL)
2393 		sel = 2;
2394 	else if (parent->id == PLL_GPLL)
2395 		sel = 0;
2396 	else if (parent->id == PLL_CPLL)
2397 		sel = 1;
2398 	else if (parent->id == PLL_BPLL)
2399 		sel = 3;
2400 	else
2401 		sel = 4;
2402 
2403 	switch (clk->id) {
2404 	case DCLK_VP0_SRC:
2405 		rk_clrsetreg(&cru->clksel_con[145], DCLK0_VOP_SRC_SEL_MASK,
2406 			     sel << DCLK0_VOP_SRC_SEL_SHIFT);
2407 		break;
2408 	case DCLK_VP1_SRC:
2409 		rk_clrsetreg(&cru->clksel_con[146], DCLK0_VOP_SRC_SEL_MASK,
2410 			     sel << DCLK0_VOP_SRC_SEL_SHIFT);
2411 		break;
2412 	case DCLK_VP2_SRC:
2413 		rk_clrsetreg(&cru->clksel_con[147], DCLK0_VOP_SRC_SEL_MASK,
2414 			     sel << DCLK0_VOP_SRC_SEL_SHIFT);
2415 		break;
2416 	case DCLK_VP0:
2417 		if (!strcmp(clock_dev_name, "hdmiphypll_clk0"))
2418 			sel = 1;
2419 		else
2420 			sel = 0;
2421 		rk_clrsetreg(&cru->clksel_con[147], DCLK0_VOP_SEL_MASK,
2422 			     sel << DCLK0_VOP_SEL_SHIFT);
2423 		break;
2424 	case DCLK_VP1:
2425 		if (!strcmp(clock_dev_name, "hdmiphypll_clk0"))
2426 			sel = 1;
2427 		else
2428 			sel = 0;
2429 		rk_clrsetreg(&cru->clksel_con[147], DCLK1_VOP_SEL_MASK,
2430 			     sel << DCLK1_VOP_SEL_SHIFT);
2431 		break;
2432 	case DCLK_VP2:
2433 		if (!strcmp(clock_dev_name, "hdmiphypll_clk0"))
2434 			sel = 1;
2435 		else
2436 			sel = 0;
2437 		rk_clrsetreg(&cru->clksel_con[147], DCLK2_VOP_SEL_MASK,
2438 			     sel << DCLK2_VOP_SEL_SHIFT);
2439 		break;
2440 	case DCLK_EBC:
2441 		if (parent->id == PLL_GPLL)
2442 			sel = 0;
2443 		else if (parent->id == PLL_CPLL)
2444 			sel = 1;
2445 		else if (parent->id == PLL_VPLL)
2446 			sel = 2;
2447 		else if (parent->id == PLL_AUPLL)
2448 			sel = 3;
2449 		else if (parent->id == PLL_LPLL)
2450 			sel = 4;
2451 		else if (parent->id == DCLK_EBC_FRAC_SRC)
2452 			sel = 5;
2453 		else
2454 			sel = 6;
2455 		rk_clrsetreg(&cru->clksel_con[123], DCLK_EBC_SEL_MASK,
2456 			     sel << DCLK_EBC_SEL_SHIFT);
2457 		break;
2458 	default:
2459 		return -EINVAL;
2460 	}
2461 	return 0;
2462 }
2463 
2464 static int __maybe_unused rk3576_ufs_ref_set_parent(struct clk *clk,
2465 						     struct clk *parent)
2466 {
2467 	struct rk3576_clk_priv *priv = dev_get_priv(clk->dev);
2468 	struct rk3576_cru *cru = priv->cru;
2469 	u32 sel;
2470 	const char *clock_dev_name = parent->dev->name;
2471 
2472 	if (parent->id == CLK_REF_MPHY_26M)
2473 		sel = 2;
2474 	else if (!strcmp(clock_dev_name, "xin24m"))
2475 		sel = 0;
2476 	else
2477 		sel = 1;
2478 
2479 	rk_clrsetreg(&cru->pmuclksel_con[3], 0x3, sel << 0);
2480 	return 0;
2481 }
2482 
2483 static int rk3576_clk_set_parent(struct clk *clk, struct clk *parent)
2484 {
2485 	switch (clk->id) {
2486 	case DCLK_VP0_SRC:
2487 	case DCLK_VP1_SRC:
2488 	case DCLK_VP2_SRC:
2489 	case DCLK_VP0:
2490 	case DCLK_VP1:
2491 	case DCLK_VP2:
2492 	case DCLK_EBC:
2493 		return rk3576_dclk_vop_set_parent(clk, parent);
2494 	case CLK_REF_OSC_MPHY:
2495 		return rk3576_ufs_ref_set_parent(clk, parent);
2496 
2497 	default:
2498 		return -ENOENT;
2499 	}
2500 
2501 	return 0;
2502 }
2503 #endif
2504 
2505 static struct clk_ops rk3576_clk_ops = {
2506 	.get_rate = rk3576_clk_get_rate,
2507 	.set_rate = rk3576_clk_set_rate,
2508 #if (IS_ENABLED(OF_CONTROL)) || (!IS_ENABLED(OF_PLATDATA))
2509 	.set_parent = rk3576_clk_set_parent,
2510 #endif
2511 };
2512 
2513 static void rk3576_clk_init(struct rk3576_clk_priv *priv)
2514 {
2515 	int ret;
2516 
2517 	priv->spll_hz = 702000000;
2518 
2519 	if (priv->cpll_hz != CPLL_HZ) {
2520 		ret = rockchip_pll_set_rate(&rk3576_pll_clks[CPLL], priv->cru,
2521 					    CPLL, CPLL_HZ);
2522 		if (!ret)
2523 			priv->cpll_hz = CPLL_HZ;
2524 	}
2525 	if (priv->gpll_hz != GPLL_HZ) {
2526 		ret = rockchip_pll_set_rate(&rk3576_pll_clks[GPLL], priv->cru,
2527 					    GPLL, GPLL_HZ);
2528 		if (!ret)
2529 			priv->gpll_hz = GPLL_HZ;
2530 	}
2531 	rk_clrsetreg(&priv->cru->clksel_con[123],
2532 		     DCLK_EBC_FRAC_SRC_SEL_MASK,
2533 		     (DCLK_EBC_FRAC_SRC_SEL_GPLL <<
2534 		      DCLK_EBC_FRAC_SRC_SEL_SHIFT));
2535 }
2536 
2537 static int rk3576_clk_probe(struct udevice *dev)
2538 {
2539 	struct rk3576_clk_priv *priv = dev_get_priv(dev);
2540 	int ret;
2541 #if CONFIG_IS_ENABLED(CLK_SCMI)
2542 	struct clk clk;
2543 #endif
2544 
2545 	priv->sync_kernel = false;
2546 
2547 #ifdef CONFIG_SPL_BUILD
2548 	/* relase presetn_bigcore_biu/cru/grf */
2549 	writel(0x1c001c00, 0x26010010);
2550 	/* set spll to normal mode */
2551 	writel(BITS_WITH_WMASK(2, 0x7U, 6),
2552 	       RK3576_SCRU_BASE + RK3576_PLL_CON(137));
2553 	writel(BITS_WITH_WMASK(1, 0x3U, 0),
2554 	       RK3576_SCRU_BASE + RK3576_MODE_CON0);
2555 	/* fix ppll\aupll\cpll */
2556 	writel(BITS_WITH_WMASK(2, 0x7U, 6),
2557 	       RK3576_CRU_BASE + RK3576_PMU_PLL_CON(129));
2558 	writel(BITS_WITH_WMASK(2, 0x7U, 6),
2559 	       RK3576_CRU_BASE + RK3576_PLL_CON(97));
2560 	writel(BITS_WITH_WMASK(2, 0x7U, 6),
2561 	       RK3576_CRU_BASE + RK3576_PLL_CON(105));
2562 	writel(BITS_WITH_WMASK(1, 0x3U, 6),
2563 	       RK3576_CRU_BASE + RK3576_MODE_CON0);
2564 	writel(BITS_WITH_WMASK(1, 0x3U, 8),
2565 	       RK3576_CRU_BASE + RK3576_MODE_CON0);
2566 	/* init cci */
2567 	writel(0xffff0000, RK3576_CRU_BASE + RK3576_CCI_CLKSEL_CON(4));
2568 	rockchip_pll_set_rate(&rk3576_pll_clks[BPLL], priv->cru,
2569 			      BPLL, LPLL_HZ);
2570 	if (!priv->armclk_enter_hz) {
2571 		ret = rockchip_pll_set_rate(&rk3576_pll_clks[LPLL], priv->cru,
2572 					    LPLL, LPLL_HZ);
2573 		priv->armclk_enter_hz =
2574 			rockchip_pll_get_rate(&rk3576_pll_clks[LPLL],
2575 					      priv->cru, LPLL);
2576 		priv->armclk_init_hz = priv->armclk_enter_hz;
2577 		rk_clrsetreg(&priv->cru->litclksel_con[0], CLK_LITCORE_DIV_MASK,
2578 			     0 << CLK_LITCORE_DIV_SHIFT);
2579 	}
2580 	/* init cci */
2581 	writel(0xffff20cb, RK3576_CRU_BASE + RK3576_CCI_CLKSEL_CON(4));
2582 
2583 	/* Change bigcore rm from 4 to 3 */
2584 	writel(0x001c000c, RK3576_BIGCORE_GRF_BASE + 0x3c);
2585 	writel(0x001c000c, RK3576_BIGCORE_GRF_BASE + 0x44);
2586 	writel(0x00020002, RK3576_BIGCORE_GRF_BASE + 0x38);
2587 	udelay(1);
2588 	writel(0x00020000, RK3576_BIGCORE_GRF_BASE + 0x38);
2589 	/* Change litcore rm from 4 to 3 */
2590 	writel(0x001c000c, RK3576_LITCORE_GRF_BASE + 0x3c);
2591 	writel(0x001c000c, RK3576_LITCORE_GRF_BASE + 0x44);
2592 	writel(0x00020002, RK3576_LITCORE_GRF_BASE + 0x38);
2593 	udelay(1);
2594 	writel(0x00020000, RK3576_LITCORE_GRF_BASE + 0x38);
2595 	/* Change cci rm form 4 to 3 */
2596 	writel(0x001c000c, RK3576_CCI_GRF_BASE + 0x54);
2597 #endif
2598 
2599 	priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
2600 	if (IS_ERR(priv->grf))
2601 		return PTR_ERR(priv->grf);
2602 
2603 	rk3576_clk_init(priv);
2604 
2605 #if CONFIG_IS_ENABLED(CLK_SCMI)
2606 #ifndef CONFIG_SPL_BUILD
2607 	ret = rockchip_get_scmi_clk(&clk.dev);
2608 	if (ret) {
2609 		printf("Failed to get scmi clk dev, ret=%d\n", ret);
2610 		return ret;
2611 	}
2612 	if (!priv->armclk_enter_hz) {
2613 		clk.id = ARMCLK_L;
2614 		ret = clk_set_rate(&clk, CPU_PVTPLL_HZ);
2615 		if (ret < 0) {
2616 			printf("Failed to set cpubl, ret=%d\n", ret);
2617 		} else {
2618 			priv->armclk_enter_hz = CPU_PVTPLL_HZ;
2619 			priv->armclk_init_hz = CPU_PVTPLL_HZ;
2620 		}
2621 	}
2622 	clk.id = ARMCLK_B;
2623 	ret = clk_set_rate(&clk, CPU_PVTPLL_HZ);
2624 	if (ret < 0)
2625 		printf("Failed to set cpub, ret=%d\n", ret);
2626 #endif
2627 #endif
2628 
2629 	/* Process 'assigned-{clocks/clock-parents/clock-rates}' properties */
2630 	ret = clk_set_defaults(dev);
2631 	if (ret)
2632 		debug("%s clk_set_defaults failed %d\n", __func__, ret);
2633 	else
2634 		priv->sync_kernel = true;
2635 
2636 	return 0;
2637 }
2638 
2639 static int rk3576_clk_ofdata_to_platdata(struct udevice *dev)
2640 {
2641 	struct rk3576_clk_priv *priv = dev_get_priv(dev);
2642 
2643 	priv->cru = dev_read_addr_ptr(dev);
2644 
2645 	return 0;
2646 }
2647 
2648 static int rk3576_clk_bind(struct udevice *dev)
2649 {
2650 	int ret;
2651 	struct udevice *sys_child, *sf_child;
2652 	struct sysreset_reg *priv;
2653 	struct softreset_reg *sf_priv;
2654 
2655 	/* The reset driver does not have a device node, so bind it here */
2656 	ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset",
2657 				 &sys_child);
2658 	if (ret) {
2659 		debug("Warning: No sysreset driver: ret=%d\n", ret);
2660 	} else {
2661 		priv = malloc(sizeof(struct sysreset_reg));
2662 		priv->glb_srst_fst_value = offsetof(struct rk3576_cru,
2663 						    glb_srst_fst);
2664 		priv->glb_srst_snd_value = offsetof(struct rk3576_cru,
2665 						    glb_srsr_snd);
2666 		sys_child->priv = priv;
2667 	}
2668 
2669 	ret = device_bind_driver_to_node(dev, "rockchip_reset", "reset",
2670 					 dev_ofnode(dev), &sf_child);
2671 	if (ret) {
2672 		debug("Warning: No rockchip reset driver: ret=%d\n", ret);
2673 	} else {
2674 		sf_priv = malloc(sizeof(struct softreset_reg));
2675 		sf_priv->sf_reset_offset = offsetof(struct rk3576_cru,
2676 						    softrst_con[0]);
2677 		sf_priv->sf_reset_num = 524454;
2678 		sf_child->priv = sf_priv;
2679 	}
2680 
2681 	return 0;
2682 }
2683 
2684 static const struct udevice_id rk3576_clk_ids[] = {
2685 	{ .compatible = "rockchip,rk3576-cru" },
2686 	{ }
2687 };
2688 
2689 U_BOOT_DRIVER(rockchip_rk3576_cru) = {
2690 	.name		= "rockchip_rk3576_cru",
2691 	.id		= UCLASS_CLK,
2692 	.of_match	= rk3576_clk_ids,
2693 	.priv_auto_alloc_size = sizeof(struct rk3576_clk_priv),
2694 	.ofdata_to_platdata = rk3576_clk_ofdata_to_platdata,
2695 	.ops		= &rk3576_clk_ops,
2696 	.bind		= rk3576_clk_bind,
2697 	.probe		= rk3576_clk_probe,
2698 };
2699 
2700 #ifndef CONFIG_SPL_BUILD
2701 /**
2702  * soc_clk_dump() - Print clock frequencies
2703  * Returns zero on success
2704  *
2705  * Implementation for the clk dump command.
2706  */
2707 int soc_clk_dump(void)
2708 {
2709 	struct udevice *cru_dev;
2710 	struct rk3576_clk_priv *priv;
2711 	const struct rk3576_clk_info *clk_dump;
2712 	struct clk clk;
2713 	unsigned long clk_count = ARRAY_SIZE(clks_dump);
2714 	unsigned long rate;
2715 	int i, ret;
2716 
2717 	ret = uclass_get_device_by_driver(UCLASS_CLK,
2718 					  DM_GET_DRIVER(rockchip_rk3576_cru),
2719 					  &cru_dev);
2720 	if (ret) {
2721 		printf("%s failed to get cru device\n", __func__);
2722 		return ret;
2723 	}
2724 
2725 	priv = dev_get_priv(cru_dev);
2726 	printf("CLK: (%s. arm: enter %lu KHz, init %lu KHz, kernel %lu%s)\n",
2727 	       priv->sync_kernel ? "sync kernel" : "uboot",
2728 	       priv->armclk_enter_hz / 1000,
2729 	       priv->armclk_init_hz / 1000,
2730 	       priv->set_armclk_rate ? priv->armclk_hz / 1000 : 0,
2731 	       priv->set_armclk_rate ? " KHz" : "N/A");
2732 	for (i = 0; i < clk_count; i++) {
2733 		clk_dump = &clks_dump[i];
2734 		if (clk_dump->name) {
2735 			memset(&clk, 0, sizeof(struct clk));
2736 			clk.id = clk_dump->id;
2737 			if (clk_dump->is_cru)
2738 				ret = clk_request(cru_dev, &clk);
2739 			if (ret < 0)
2740 				return ret;
2741 
2742 			rate = clk_get_rate(&clk);
2743 			clk_free(&clk);
2744 			if (rate < 0)
2745 				printf("  %s %s\n", clk_dump->name,
2746 				       "unknown");
2747 			else
2748 				printf("  %s %lu KHz\n", clk_dump->name,
2749 				       rate / 1000);
2750 		}
2751 	}
2752 
2753 	return 0;
2754 }
2755 #endif
2756