xref: /rk3399_rockchip-uboot/drivers/clk/rockchip/clk_rk3576.c (revision e63a27f7a96beae2cdcc4ca813c8b95c07c7d2e6)
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 #endif
1924 
1925 static ulong rk3576_ufs_ref_get_rate(struct rk3576_clk_priv *priv, ulong clk_id)
1926 {
1927 	struct rk3576_cru *cru = priv->cru;
1928 	u32 src, div;
1929 
1930 	src = readl(&cru->pmuclksel_con[3]) & 0x3;
1931 	div= readl(&cru->pmuclksel_con[1]) & 0xff;
1932 	if (src == 0)
1933 		return OSC_HZ;
1934 	else if (src == 2)
1935 		return priv->ppll_hz / (div + 1);
1936 	else
1937 		return 26000000;
1938 
1939 }
1940 
1941 static ulong rk3576_clk_get_rate(struct clk *clk)
1942 {
1943 	struct rk3576_clk_priv *priv = dev_get_priv(clk->dev);
1944 	ulong rate = 0;
1945 
1946 	if (!priv->gpll_hz) {
1947 		printf("%s gpll=%lu\n", __func__, priv->gpll_hz);
1948 		return -ENOENT;
1949 	}
1950 
1951 	if (!priv->ppll_hz) {
1952 		priv->ppll_hz = rockchip_pll_get_rate(&rk3576_pll_clks[PPLL],
1953 						      priv->cru, PPLL);
1954 	}
1955 
1956 	switch (clk->id) {
1957 	case PLL_LPLL:
1958 		rate = rockchip_pll_get_rate(&rk3576_pll_clks[LPLL], priv->cru,
1959 					     LPLL);
1960 		priv->lpll_hz = rate;
1961 		break;
1962 	case PLL_BPLL:
1963 		rate = rockchip_pll_get_rate(&rk3576_pll_clks[BPLL], priv->cru,
1964 					     BPLL);
1965 		priv->bpll_hz = rate;
1966 		break;
1967 	case PLL_GPLL:
1968 		rate = rockchip_pll_get_rate(&rk3576_pll_clks[GPLL], priv->cru,
1969 					     GPLL);
1970 		break;
1971 	case PLL_CPLL:
1972 		rate = rockchip_pll_get_rate(&rk3576_pll_clks[CPLL], priv->cru,
1973 					     CPLL);
1974 		break;
1975 	case PLL_VPLL:
1976 		rate = rockchip_pll_get_rate(&rk3576_pll_clks[VPLL], priv->cru,
1977 					     VPLL);
1978 		break;
1979 	case PLL_AUPLL:
1980 		rate = rockchip_pll_get_rate(&rk3576_pll_clks[AUPLL], priv->cru,
1981 					     AUPLL);
1982 		break;
1983 	case PLL_PPLL:
1984 		rate = rockchip_pll_get_rate(&rk3576_pll_clks[PPLL], priv->cru,
1985 					     PPLL) * 2;
1986 		break;
1987 	case ACLK_BUS_ROOT:
1988 	case HCLK_BUS_ROOT:
1989 	case PCLK_BUS_ROOT:
1990 		rate = rk3576_bus_get_clk(priv, clk->id);
1991 		break;
1992 	case ACLK_TOP:
1993 	case HCLK_TOP:
1994 	case PCLK_TOP_ROOT:
1995 	case ACLK_TOP_MID:
1996 		rate = rk3576_top_get_clk(priv, clk->id);
1997 		break;
1998 	case CLK_I2C0:
1999 	case CLK_I2C1:
2000 	case CLK_I2C2:
2001 	case CLK_I2C3:
2002 	case CLK_I2C4:
2003 	case CLK_I2C5:
2004 	case CLK_I2C6:
2005 	case CLK_I2C7:
2006 	case CLK_I2C8:
2007 	case CLK_I2C9:
2008 		rate = rk3576_i2c_get_clk(priv, clk->id);
2009 		break;
2010 	case CLK_SPI0:
2011 	case CLK_SPI1:
2012 	case CLK_SPI2:
2013 	case CLK_SPI3:
2014 	case CLK_SPI4:
2015 		rate = rk3576_spi_get_clk(priv, clk->id);
2016 		break;
2017 	case CLK_PWM1:
2018 	case CLK_PWM2:
2019 	case CLK_PMU1PWM:
2020 		rate = rk3576_pwm_get_clk(priv, clk->id);
2021 		break;
2022 	case CLK_SARADC:
2023 	case CLK_TSADC:
2024 		rate = rk3576_adc_get_clk(priv, clk->id);
2025 		break;
2026 	case CCLK_SRC_SDIO:
2027 	case CCLK_SRC_SDMMC0:
2028 	case CCLK_SRC_EMMC:
2029 	case BCLK_EMMC:
2030 	case SCLK_FSPI_X2:
2031 	case SCLK_FSPI1_X2:
2032 	case DCLK_DECOM:
2033 	case HCLK_SDMMC0:
2034 	case HCLK_EMMC:
2035 	case HCLK_SDIO:
2036 		rate = rk3576_mmc_get_clk(priv, clk->id);
2037 		break;
2038 	case TCLK_WDT0:
2039 		rate = OSC_HZ;
2040 		break;
2041 #ifndef CONFIG_SPL_BUILD
2042 	case ACLK_VOP_ROOT:
2043 	case ACLK_VOP:
2044 	case ACLK_VO0_ROOT:
2045 	case ACLK_VO1_ROOT:
2046 	case HCLK_VOP_ROOT:
2047 	case PCLK_VOP_ROOT:
2048 		rate = rk3576_aclk_vop_get_clk(priv, clk->id);
2049 		break;
2050 	case DCLK_VP0:
2051 	case DCLK_VP0_SRC:
2052 	case DCLK_VP1:
2053 	case DCLK_VP1_SRC:
2054 	case DCLK_VP2:
2055 	case DCLK_VP2_SRC:
2056 		rate = rk3576_dclk_vop_get_clk(priv, clk->id);
2057 		break;
2058 	case CLK_GMAC0_PTP_REF_SRC:
2059 	case CLK_GMAC1_PTP_REF_SRC:
2060 	case CLK_GMAC0_PTP_REF:
2061 	case CLK_GMAC1_PTP_REF:
2062 	case CLK_GMAC0_125M_SRC:
2063 	case CLK_GMAC1_125M_SRC:
2064 		rate = rk3576_gmac_get_clk(priv, clk->id);
2065 		break;
2066 	case CLK_UART_FRAC_0:
2067 	case CLK_UART_FRAC_1:
2068 	case CLK_UART_FRAC_2:
2069 		rate = rk3576_uart_frac_get_rate(priv, clk->id);
2070 		break;
2071 	case SCLK_UART0:
2072 	case SCLK_UART1:
2073 	case SCLK_UART2:
2074 	case SCLK_UART3:
2075 	case SCLK_UART4:
2076 	case SCLK_UART5:
2077 	case SCLK_UART6:
2078 	case SCLK_UART7:
2079 	case SCLK_UART8:
2080 	case SCLK_UART9:
2081 	case SCLK_UART10:
2082 	case SCLK_UART11:
2083 		rate = rk3576_uart_get_rate(priv, clk->id);
2084 		break;
2085 	case CLK_DSIHOST0:
2086 		rate = rk3576_clk_csihost_get_clk(priv, clk->id);
2087 		break;
2088 	case DCLK_EBC:
2089 	case DCLK_EBC_FRAC_SRC:
2090 		rate = rk3576_dclk_ebc_get_clk(priv, clk->id);
2091 		break;
2092 #endif
2093 	case CLK_REF_UFS_CLKOUT:
2094 	case CLK_REF_OSC_MPHY:
2095 		rate = rk3576_ufs_ref_get_rate(priv, clk->id);
2096 		break;
2097 
2098 	default:
2099 		return -ENOENT;
2100 	}
2101 
2102 	return rate;
2103 };
2104 
2105 static ulong rk3576_clk_set_rate(struct clk *clk, ulong rate)
2106 {
2107 	struct rk3576_clk_priv *priv = dev_get_priv(clk->dev);
2108 	ulong ret = 0;
2109 
2110 	if (!priv->ppll_hz) {
2111 		priv->ppll_hz = rockchip_pll_get_rate(&rk3576_pll_clks[PPLL],
2112 						      priv->cru, PPLL);
2113 	}
2114 	if (!priv->aupll_hz) {
2115 		priv->aupll_hz = rockchip_pll_get_rate(&rk3576_pll_clks[AUPLL],
2116 						      priv->cru, AUPLL);
2117 	}
2118 
2119 	switch (clk->id) {
2120 	case PLL_CPLL:
2121 		ret = rockchip_pll_set_rate(&rk3576_pll_clks[CPLL], priv->cru,
2122 					    CPLL, rate);
2123 		priv->cpll_hz = rockchip_pll_get_rate(&rk3576_pll_clks[CPLL],
2124 						      priv->cru, CPLL);
2125 		break;
2126 	case PLL_GPLL:
2127 		ret = rockchip_pll_set_rate(&rk3576_pll_clks[GPLL], priv->cru,
2128 					    GPLL, rate);
2129 		priv->gpll_hz = rockchip_pll_get_rate(&rk3576_pll_clks[GPLL],
2130 						      priv->cru, GPLL);
2131 		break;
2132 	case PLL_VPLL:
2133 		ret = rockchip_pll_set_rate(&rk3576_pll_clks[VPLL], priv->cru,
2134 					    VPLL, rate);
2135 		priv->vpll_hz = rockchip_pll_get_rate(&rk3576_pll_clks[VPLL],
2136 						       priv->cru, VPLL);
2137 		break;
2138 	case PLL_AUPLL:
2139 		ret = rockchip_pll_set_rate(&rk3576_pll_clks[AUPLL], priv->cru,
2140 					    AUPLL, rate);
2141 		priv->aupll_hz = rockchip_pll_get_rate(&rk3576_pll_clks[AUPLL],
2142 						       priv->cru, AUPLL);
2143 		break;
2144 	case PLL_PPLL:
2145 		ret = rockchip_pll_set_rate(&rk3576_pll_clks[PPLL], priv->cru,
2146 					    PPLL, rate);
2147 		priv->ppll_hz = rockchip_pll_get_rate(&rk3576_pll_clks[PPLL],
2148 						      priv->cru, PPLL) * 2;
2149 		break;
2150 	case ACLK_BUS_ROOT:
2151 	case HCLK_BUS_ROOT:
2152 	case PCLK_BUS_ROOT:
2153 		ret = rk3576_bus_set_clk(priv, clk->id, rate);
2154 		break;
2155 	case ACLK_TOP:
2156 	case HCLK_TOP:
2157 	case PCLK_TOP_ROOT:
2158 	case ACLK_TOP_MID:
2159 		ret = rk3576_top_set_clk(priv, clk->id, rate);
2160 		break;
2161 	case CLK_I2C0:
2162 	case CLK_I2C1:
2163 	case CLK_I2C2:
2164 	case CLK_I2C3:
2165 	case CLK_I2C4:
2166 	case CLK_I2C5:
2167 	case CLK_I2C6:
2168 	case CLK_I2C7:
2169 	case CLK_I2C8:
2170 	case CLK_I2C9:
2171 		ret = rk3576_i2c_set_clk(priv, clk->id, rate);
2172 		break;
2173 	case CLK_SPI0:
2174 	case CLK_SPI1:
2175 	case CLK_SPI2:
2176 	case CLK_SPI3:
2177 	case CLK_SPI4:
2178 		ret = rk3576_spi_set_clk(priv, clk->id, rate);
2179 		break;
2180 	case CLK_PWM1:
2181 	case CLK_PWM2:
2182 	case CLK_PMU1PWM:
2183 		ret = rk3576_pwm_set_clk(priv, clk->id, rate);
2184 		break;
2185 	case CLK_SARADC:
2186 	case CLK_TSADC:
2187 		ret = rk3576_adc_set_clk(priv, clk->id, rate);
2188 		break;
2189 	case CCLK_SRC_SDIO:
2190 	case CCLK_SRC_SDMMC0:
2191 	case CCLK_SRC_EMMC:
2192 	case BCLK_EMMC:
2193 	case SCLK_FSPI_X2:
2194 	case SCLK_FSPI1_X2:
2195 	case DCLK_DECOM:
2196 	case HCLK_SDMMC0:
2197 	case HCLK_EMMC:
2198 	case HCLK_SDIO:
2199 		ret = rk3576_mmc_set_clk(priv, clk->id, rate);
2200 		break;
2201 	case TCLK_WDT0:
2202 		ret = OSC_HZ;
2203 		break;
2204 #ifndef CONFIG_SPL_BUILD
2205 	case ACLK_VOP_ROOT:
2206 	case ACLK_VOP:
2207 	case ACLK_VO0_ROOT:
2208 	case ACLK_VO1_ROOT:
2209 	case HCLK_VOP_ROOT:
2210 	case PCLK_VOP_ROOT:
2211 		ret = rk3576_aclk_vop_set_clk(priv, clk->id, rate);
2212 		break;
2213 	case DCLK_VP0:
2214 	case DCLK_VP0_SRC:
2215 	case DCLK_VP1:
2216 	case DCLK_VP1_SRC:
2217 	case DCLK_VP2:
2218 	case DCLK_VP2_SRC:
2219 		ret = rk3576_dclk_vop_set_clk(priv, clk->id, rate);
2220 		break;
2221 	case CLK_GMAC0_PTP_REF_SRC:
2222 	case CLK_GMAC1_PTP_REF_SRC:
2223 	case CLK_GMAC0_PTP_REF:
2224 	case CLK_GMAC1_PTP_REF:
2225 	case CLK_GMAC0_125M_SRC:
2226 	case CLK_GMAC1_125M_SRC:
2227 		ret = rk3576_gmac_set_clk(priv, clk->id, rate);
2228 		break;
2229 	case CLK_UART_FRAC_0:
2230 	case CLK_UART_FRAC_1:
2231 	case CLK_UART_FRAC_2:
2232 		ret = rk3576_uart_frac_set_rate(priv, clk->id, rate);
2233 		break;
2234 	case SCLK_UART0:
2235 	case SCLK_UART1:
2236 	case SCLK_UART2:
2237 	case SCLK_UART3:
2238 	case SCLK_UART4:
2239 	case SCLK_UART5:
2240 	case SCLK_UART6:
2241 	case SCLK_UART7:
2242 	case SCLK_UART8:
2243 	case SCLK_UART9:
2244 	case SCLK_UART10:
2245 	case SCLK_UART11:
2246 		ret = rk3576_uart_set_rate(priv, clk->id, rate);
2247 		break;
2248 	case CLK_DSIHOST0:
2249 		ret = rk3576_clk_csihost_set_clk(priv, clk->id, rate);
2250 		break;
2251 	case DCLK_EBC:
2252 	case DCLK_EBC_FRAC_SRC:
2253 		ret = rk3576_dclk_ebc_set_clk(priv, clk->id, rate);
2254 		break;
2255 #endif
2256 	default:
2257 		return -ENOENT;
2258 	}
2259 
2260 	return ret;
2261 };
2262 
2263 #if (IS_ENABLED(OF_CONTROL)) || (!IS_ENABLED(OF_PLATDATA))
2264 static int __maybe_unused rk3576_dclk_vop_set_parent(struct clk *clk,
2265 						     struct clk *parent)
2266 {
2267 	struct rk3576_clk_priv *priv = dev_get_priv(clk->dev);
2268 	struct rk3576_cru *cru = priv->cru;
2269 	u32 sel;
2270 	const char *clock_dev_name = parent->dev->name;
2271 
2272 	if (parent->id == PLL_VPLL)
2273 		sel = 2;
2274 	else if (parent->id == PLL_GPLL)
2275 		sel = 0;
2276 	else if (parent->id == PLL_CPLL)
2277 		sel = 1;
2278 	else if (parent->id == PLL_BPLL)
2279 		sel = 3;
2280 	else
2281 		sel = 4;
2282 
2283 	switch (clk->id) {
2284 	case DCLK_VP0_SRC:
2285 		rk_clrsetreg(&cru->clksel_con[145], DCLK0_VOP_SRC_SEL_MASK,
2286 			     sel << DCLK0_VOP_SRC_SEL_SHIFT);
2287 		break;
2288 	case DCLK_VP1_SRC:
2289 		rk_clrsetreg(&cru->clksel_con[146], DCLK0_VOP_SRC_SEL_MASK,
2290 			     sel << DCLK0_VOP_SRC_SEL_SHIFT);
2291 		break;
2292 	case DCLK_VP2_SRC:
2293 		rk_clrsetreg(&cru->clksel_con[147], DCLK0_VOP_SRC_SEL_MASK,
2294 			     sel << DCLK0_VOP_SRC_SEL_SHIFT);
2295 		break;
2296 	case DCLK_VP0:
2297 		if (!strcmp(clock_dev_name, "hdmiphypll_clk0"))
2298 			sel = 1;
2299 		else
2300 			sel = 0;
2301 		rk_clrsetreg(&cru->clksel_con[147], DCLK0_VOP_SEL_MASK,
2302 			     sel << DCLK0_VOP_SEL_SHIFT);
2303 		break;
2304 	case DCLK_VP1:
2305 		if (!strcmp(clock_dev_name, "hdmiphypll_clk0"))
2306 			sel = 1;
2307 		else
2308 			sel = 0;
2309 		rk_clrsetreg(&cru->clksel_con[147], DCLK1_VOP_SEL_MASK,
2310 			     sel << DCLK1_VOP_SEL_SHIFT);
2311 		break;
2312 	case DCLK_VP2:
2313 		if (!strcmp(clock_dev_name, "hdmiphypll_clk0"))
2314 			sel = 1;
2315 		else
2316 			sel = 0;
2317 		rk_clrsetreg(&cru->clksel_con[147], DCLK2_VOP_SEL_MASK,
2318 			     sel << DCLK2_VOP_SEL_SHIFT);
2319 		break;
2320 	case DCLK_EBC:
2321 		if (parent->id == PLL_GPLL)
2322 			sel = 0;
2323 		else if (parent->id == PLL_CPLL)
2324 			sel = 1;
2325 		else if (parent->id == PLL_VPLL)
2326 			sel = 2;
2327 		else if (parent->id == PLL_AUPLL)
2328 			sel = 3;
2329 		else if (parent->id == PLL_LPLL)
2330 			sel = 4;
2331 		else if (parent->id == DCLK_EBC_FRAC_SRC)
2332 			sel = 5;
2333 		else
2334 			sel = 6;
2335 		rk_clrsetreg(&cru->clksel_con[123], DCLK_EBC_SEL_MASK,
2336 			     sel << DCLK_EBC_SEL_SHIFT);
2337 		break;
2338 	default:
2339 		return -EINVAL;
2340 	}
2341 	return 0;
2342 }
2343 
2344 static int __maybe_unused rk3576_ufs_ref_set_parent(struct clk *clk,
2345 						     struct clk *parent)
2346 {
2347 	struct rk3576_clk_priv *priv = dev_get_priv(clk->dev);
2348 	struct rk3576_cru *cru = priv->cru;
2349 	u32 sel;
2350 	const char *clock_dev_name = parent->dev->name;
2351 
2352 	if (parent->id == CLK_REF_MPHY_26M)
2353 		sel = 2;
2354 	else if (!strcmp(clock_dev_name, "xin24m"))
2355 		sel = 0;
2356 	else
2357 		sel = 1;
2358 
2359 	rk_clrsetreg(&cru->pmuclksel_con[3], 0x3, sel << 0);
2360 	return 0;
2361 }
2362 
2363 static int rk3576_clk_set_parent(struct clk *clk, struct clk *parent)
2364 {
2365 	switch (clk->id) {
2366 	case DCLK_VP0_SRC:
2367 	case DCLK_VP1_SRC:
2368 	case DCLK_VP2_SRC:
2369 	case DCLK_VP0:
2370 	case DCLK_VP1:
2371 	case DCLK_VP2:
2372 	case DCLK_EBC:
2373 		return rk3576_dclk_vop_set_parent(clk, parent);
2374 	case CLK_REF_OSC_MPHY:
2375 		return rk3576_ufs_ref_set_parent(clk, parent);
2376 
2377 	default:
2378 		return -ENOENT;
2379 	}
2380 
2381 	return 0;
2382 }
2383 #endif
2384 
2385 static struct clk_ops rk3576_clk_ops = {
2386 	.get_rate = rk3576_clk_get_rate,
2387 	.set_rate = rk3576_clk_set_rate,
2388 #if (IS_ENABLED(OF_CONTROL)) || (!IS_ENABLED(OF_PLATDATA))
2389 	.set_parent = rk3576_clk_set_parent,
2390 #endif
2391 };
2392 
2393 static void rk3576_clk_init(struct rk3576_clk_priv *priv)
2394 {
2395 	int ret;
2396 
2397 	priv->spll_hz = 702000000;
2398 
2399 	if (priv->cpll_hz != CPLL_HZ) {
2400 		ret = rockchip_pll_set_rate(&rk3576_pll_clks[CPLL], priv->cru,
2401 					    CPLL, CPLL_HZ);
2402 		if (!ret)
2403 			priv->cpll_hz = CPLL_HZ;
2404 	}
2405 	if (priv->gpll_hz != GPLL_HZ) {
2406 		ret = rockchip_pll_set_rate(&rk3576_pll_clks[GPLL], priv->cru,
2407 					    GPLL, GPLL_HZ);
2408 		if (!ret)
2409 			priv->gpll_hz = GPLL_HZ;
2410 	}
2411 	rk_clrsetreg(&priv->cru->clksel_con[123],
2412 		     DCLK_EBC_FRAC_SRC_SEL_MASK,
2413 		     (DCLK_EBC_FRAC_SRC_SEL_GPLL <<
2414 		      DCLK_EBC_FRAC_SRC_SEL_SHIFT));
2415 }
2416 
2417 static int rk3576_clk_probe(struct udevice *dev)
2418 {
2419 	struct rk3576_clk_priv *priv = dev_get_priv(dev);
2420 	int ret;
2421 #if CONFIG_IS_ENABLED(CLK_SCMI)
2422 	struct clk clk;
2423 #endif
2424 
2425 	priv->sync_kernel = false;
2426 
2427 #ifdef CONFIG_SPL_BUILD
2428 	/* relase presetn_bigcore_biu/cru/grf */
2429 	writel(0x1c001c00, 0x26010010);
2430 	/* set spll to normal mode */
2431 	writel(BITS_WITH_WMASK(2, 0x7U, 6),
2432 	       RK3576_SCRU_BASE + RK3576_PLL_CON(137));
2433 	writel(BITS_WITH_WMASK(1, 0x3U, 0),
2434 	       RK3576_SCRU_BASE + RK3576_MODE_CON0);
2435 	/* fix ppll\aupll\cpll */
2436 	writel(BITS_WITH_WMASK(2, 0x7U, 6),
2437 	       RK3576_CRU_BASE + RK3576_PMU_PLL_CON(129));
2438 	writel(BITS_WITH_WMASK(2, 0x7U, 6),
2439 	       RK3576_CRU_BASE + RK3576_PLL_CON(97));
2440 	writel(BITS_WITH_WMASK(2, 0x7U, 6),
2441 	       RK3576_CRU_BASE + RK3576_PLL_CON(105));
2442 	writel(BITS_WITH_WMASK(1, 0x3U, 6),
2443 	       RK3576_CRU_BASE + RK3576_MODE_CON0);
2444 	writel(BITS_WITH_WMASK(1, 0x3U, 8),
2445 	       RK3576_CRU_BASE + RK3576_MODE_CON0);
2446 	/* init cci */
2447 	writel(0xffff0000, RK3576_CRU_BASE + RK3576_CCI_CLKSEL_CON(4));
2448 	rockchip_pll_set_rate(&rk3576_pll_clks[BPLL], priv->cru,
2449 			      BPLL, LPLL_HZ);
2450 	if (!priv->armclk_enter_hz) {
2451 		ret = rockchip_pll_set_rate(&rk3576_pll_clks[LPLL], priv->cru,
2452 					    LPLL, LPLL_HZ);
2453 		priv->armclk_enter_hz =
2454 			rockchip_pll_get_rate(&rk3576_pll_clks[LPLL],
2455 					      priv->cru, LPLL);
2456 		priv->armclk_init_hz = priv->armclk_enter_hz;
2457 		rk_clrsetreg(&priv->cru->litclksel_con[0], CLK_LITCORE_DIV_MASK,
2458 			     0 << CLK_LITCORE_DIV_SHIFT);
2459 	}
2460 	/* init cci */
2461 	writel(0xffff20cb, RK3576_CRU_BASE + RK3576_CCI_CLKSEL_CON(4));
2462 
2463 	/* Change bigcore rm from 4 to 3 */
2464 	writel(0x001c000c, RK3576_BIGCORE_GRF_BASE + 0x3c);
2465 	writel(0x001c000c, RK3576_BIGCORE_GRF_BASE + 0x44);
2466 	writel(0x00020002, RK3576_BIGCORE_GRF_BASE + 0x38);
2467 	udelay(1);
2468 	writel(0x00020000, RK3576_BIGCORE_GRF_BASE + 0x38);
2469 	/* Change litcore rm from 4 to 3 */
2470 	writel(0x001c000c, RK3576_LITCORE_GRF_BASE + 0x3c);
2471 	writel(0x001c000c, RK3576_LITCORE_GRF_BASE + 0x44);
2472 	writel(0x00020002, RK3576_LITCORE_GRF_BASE + 0x38);
2473 	udelay(1);
2474 	writel(0x00020000, RK3576_LITCORE_GRF_BASE + 0x38);
2475 	/* Change cci rm form 4 to 3 */
2476 	writel(0x001c000c, RK3576_CCI_GRF_BASE + 0x54);
2477 #endif
2478 
2479 	priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
2480 	if (IS_ERR(priv->grf))
2481 		return PTR_ERR(priv->grf);
2482 
2483 	rk3576_clk_init(priv);
2484 
2485 #if CONFIG_IS_ENABLED(CLK_SCMI)
2486 #ifndef CONFIG_SPL_BUILD
2487 	ret = rockchip_get_scmi_clk(&clk.dev);
2488 	if (ret) {
2489 		printf("Failed to get scmi clk dev, ret=%d\n", ret);
2490 		return ret;
2491 	}
2492 	if (!priv->armclk_enter_hz) {
2493 		clk.id = ARMCLK_L;
2494 		ret = clk_set_rate(&clk, CPU_PVTPLL_HZ);
2495 		if (ret < 0) {
2496 			printf("Failed to set cpubl, ret=%d\n", ret);
2497 		} else {
2498 			priv->armclk_enter_hz = CPU_PVTPLL_HZ;
2499 			priv->armclk_init_hz = CPU_PVTPLL_HZ;
2500 		}
2501 	}
2502 	clk.id = ARMCLK_B;
2503 	ret = clk_set_rate(&clk, CPU_PVTPLL_HZ);
2504 	if (ret < 0)
2505 		printf("Failed to set cpub, ret=%d\n", ret);
2506 #endif
2507 #endif
2508 
2509 	/* Process 'assigned-{clocks/clock-parents/clock-rates}' properties */
2510 	ret = clk_set_defaults(dev);
2511 	if (ret)
2512 		debug("%s clk_set_defaults failed %d\n", __func__, ret);
2513 	else
2514 		priv->sync_kernel = true;
2515 
2516 	return 0;
2517 }
2518 
2519 static int rk3576_clk_ofdata_to_platdata(struct udevice *dev)
2520 {
2521 	struct rk3576_clk_priv *priv = dev_get_priv(dev);
2522 
2523 	priv->cru = dev_read_addr_ptr(dev);
2524 
2525 	return 0;
2526 }
2527 
2528 static int rk3576_clk_bind(struct udevice *dev)
2529 {
2530 	int ret;
2531 	struct udevice *sys_child, *sf_child;
2532 	struct sysreset_reg *priv;
2533 	struct softreset_reg *sf_priv;
2534 
2535 	/* The reset driver does not have a device node, so bind it here */
2536 	ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset",
2537 				 &sys_child);
2538 	if (ret) {
2539 		debug("Warning: No sysreset driver: ret=%d\n", ret);
2540 	} else {
2541 		priv = malloc(sizeof(struct sysreset_reg));
2542 		priv->glb_srst_fst_value = offsetof(struct rk3576_cru,
2543 						    glb_srst_fst);
2544 		priv->glb_srst_snd_value = offsetof(struct rk3576_cru,
2545 						    glb_srsr_snd);
2546 		sys_child->priv = priv;
2547 	}
2548 
2549 	ret = device_bind_driver_to_node(dev, "rockchip_reset", "reset",
2550 					 dev_ofnode(dev), &sf_child);
2551 	if (ret) {
2552 		debug("Warning: No rockchip reset driver: ret=%d\n", ret);
2553 	} else {
2554 		sf_priv = malloc(sizeof(struct softreset_reg));
2555 		sf_priv->sf_reset_offset = offsetof(struct rk3576_cru,
2556 						    softrst_con[0]);
2557 		sf_priv->sf_reset_num = 524454;
2558 		sf_child->priv = sf_priv;
2559 	}
2560 
2561 	return 0;
2562 }
2563 
2564 static const struct udevice_id rk3576_clk_ids[] = {
2565 	{ .compatible = "rockchip,rk3576-cru" },
2566 	{ }
2567 };
2568 
2569 U_BOOT_DRIVER(rockchip_rk3576_cru) = {
2570 	.name		= "rockchip_rk3576_cru",
2571 	.id		= UCLASS_CLK,
2572 	.of_match	= rk3576_clk_ids,
2573 	.priv_auto_alloc_size = sizeof(struct rk3576_clk_priv),
2574 	.ofdata_to_platdata = rk3576_clk_ofdata_to_platdata,
2575 	.ops		= &rk3576_clk_ops,
2576 	.bind		= rk3576_clk_bind,
2577 	.probe		= rk3576_clk_probe,
2578 };
2579 
2580 #ifndef CONFIG_SPL_BUILD
2581 /**
2582  * soc_clk_dump() - Print clock frequencies
2583  * Returns zero on success
2584  *
2585  * Implementation for the clk dump command.
2586  */
2587 int soc_clk_dump(void)
2588 {
2589 	struct udevice *cru_dev;
2590 	struct rk3576_clk_priv *priv;
2591 	const struct rk3576_clk_info *clk_dump;
2592 	struct clk clk;
2593 	unsigned long clk_count = ARRAY_SIZE(clks_dump);
2594 	unsigned long rate;
2595 	int i, ret;
2596 
2597 	ret = uclass_get_device_by_driver(UCLASS_CLK,
2598 					  DM_GET_DRIVER(rockchip_rk3576_cru),
2599 					  &cru_dev);
2600 	if (ret) {
2601 		printf("%s failed to get cru device\n", __func__);
2602 		return ret;
2603 	}
2604 
2605 	priv = dev_get_priv(cru_dev);
2606 	printf("CLK: (%s. arm: enter %lu KHz, init %lu KHz, kernel %lu%s)\n",
2607 	       priv->sync_kernel ? "sync kernel" : "uboot",
2608 	       priv->armclk_enter_hz / 1000,
2609 	       priv->armclk_init_hz / 1000,
2610 	       priv->set_armclk_rate ? priv->armclk_hz / 1000 : 0,
2611 	       priv->set_armclk_rate ? " KHz" : "N/A");
2612 	for (i = 0; i < clk_count; i++) {
2613 		clk_dump = &clks_dump[i];
2614 		if (clk_dump->name) {
2615 			memset(&clk, 0, sizeof(struct clk));
2616 			clk.id = clk_dump->id;
2617 			if (clk_dump->is_cru)
2618 				ret = clk_request(cru_dev, &clk);
2619 			if (ret < 0)
2620 				return ret;
2621 
2622 			rate = clk_get_rate(&clk);
2623 			clk_free(&clk);
2624 			if (rate < 0)
2625 				printf("  %s %s\n", clk_dump->name,
2626 				       "unknown");
2627 			else
2628 				printf("  %s %lu KHz\n", clk_dump->name,
2629 				       rate / 1000);
2630 		}
2631 	}
2632 
2633 	return 0;
2634 }
2635 #endif
2636