xref: /rk3399_rockchip-uboot/drivers/clk/rockchip/clk_rk3308.c (revision 73b4df6a98d2d973cbf1e2b18947abbdbdb82bc1)
1 /*
2  * (C) Copyright 2017 Rockchip Electronics Co., Ltd
3  *
4  * SPDX-License-Identifier:	GPL-2.0
5  */
6 #include <common.h>
7 #include <bitfield.h>
8 #include <clk-uclass.h>
9 #include <dm.h>
10 #include <div64.h>
11 #include <errno.h>
12 #include <syscon.h>
13 #include <asm/arch/clock.h>
14 #include <asm/arch/cru_rk3308.h>
15 #include <asm/arch/hardware.h>
16 #include <asm/io.h>
17 #include <dm/lists.h>
18 #include <dt-bindings/clock/rk3308-cru.h>
19 
20 DECLARE_GLOBAL_DATA_PTR;
21 
22 enum {
23 	VCO_MAX_HZ	= 3200U * 1000000,
24 	VCO_MIN_HZ	= 800 * 1000000,
25 	OUTPUT_MAX_HZ	= 3200U * 1000000,
26 	OUTPUT_MIN_HZ	= 24 * 1000000,
27 };
28 
29 #define DIV_TO_RATE(input_rate, div)    ((input_rate) / ((div) + 1))
30 
31 #define RK3308_CLK_DUMP(_id, _name)		\
32 {						\
33 	.id = _id,				\
34 	.name = _name,				\
35 }
36 
37 #define RK3308_CPUCLK_RATE(_rate, _aclk_div, _pclk_div)		\
38 {								\
39 	.rate	= _rate##U,					\
40 	.aclk_div = _aclk_div,					\
41 	.pclk_div = _pclk_div,					\
42 }
43 
44 static struct rockchip_pll_rate_table rk3308_pll_rates[] = {
45 	/* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */
46 	RK3036_PLL_RATE(1300000000, 6, 325, 1, 1, 1, 0),
47 	RK3036_PLL_RATE(1200000000, 1, 50, 1, 1, 1, 0),
48 	RK3036_PLL_RATE(816000000, 1, 68, 2, 1, 1, 0),
49 	RK3036_PLL_RATE(748000000, 2, 187, 3, 1, 1, 0),
50 };
51 
52 static struct rockchip_cpu_rate_table rk3308_cpu_rates[] = {
53 	RK3308_CPUCLK_RATE(1200000000, 1, 5),
54 	RK3308_CPUCLK_RATE(1008000000, 1, 5),
55 	RK3308_CPUCLK_RATE(816000000, 1, 3),
56 	RK3308_CPUCLK_RATE(600000000, 1, 3),
57 	RK3308_CPUCLK_RATE(408000000, 1, 1),
58 };
59 
60 static const struct rk3308_clk_info clks_dump[] = {
61 	RK3308_CLK_DUMP(PLL_APLL, "apll"),
62 	RK3308_CLK_DUMP(PLL_DPLL, "dpll"),
63 	RK3308_CLK_DUMP(PLL_VPLL0, "vpll0"),
64 	RK3308_CLK_DUMP(PLL_VPLL1, "vpll1"),
65 	RK3308_CLK_DUMP(ACLK_BUS, "aclk_bus"),
66 	RK3308_CLK_DUMP(HCLK_BUS, "hclk_bus"),
67 	RK3308_CLK_DUMP(PCLK_BUS, "pclk_bus"),
68 	RK3308_CLK_DUMP(ACLK_PERI, "aclk_peri"),
69 	RK3308_CLK_DUMP(HCLK_PERI, "hclk_peri"),
70 	RK3308_CLK_DUMP(PCLK_PERI, "pclk_peri"),
71 	RK3308_CLK_DUMP(HCLK_AUDIO, "hclk_audio"),
72 	RK3308_CLK_DUMP(PCLK_AUDIO, "pclk_audio"),
73 };
74 
75 static struct rockchip_pll_clock rk3308_pll_clks[] = {
76 	[APLL] = PLL(pll_rk3328, PLL_APLL, RK3308_PLL_CON(0),
77 		     RK3308_MODE_CON, 0, 10, 0, rk3308_pll_rates),
78 	[DPLL] = PLL(pll_rk3328, PLL_DPLL, RK3308_PLL_CON(8),
79 		     RK3308_MODE_CON, 2, 10, 0, NULL),
80 	[VPLL0] = PLL(pll_rk3328, PLL_VPLL0, RK3308_PLL_CON(16),
81 		      RK3308_MODE_CON, 4, 10, 0, NULL),
82 	[VPLL1] = PLL(pll_rk3328, PLL_VPLL1, RK3308_PLL_CON(24),
83 		      RK3308_MODE_CON, 6, 10, 0, NULL),
84 };
85 
86 static ulong rk3308_armclk_set_clk(struct rk3308_clk_priv *priv, ulong hz)
87 {
88 	struct rk3308_cru *cru = priv->cru;
89 	const struct rockchip_cpu_rate_table *rate;
90 	ulong old_rate;
91 
92 	rate = rockchip_get_cpu_settings(rk3308_cpu_rates, hz);
93 	if (!rate) {
94 		printf("%s unsupport rate\n", __func__);
95 		return -EINVAL;
96 	}
97 
98 	/*
99 	 * select apll as cpu/core clock pll source and
100 	 * set up dependent divisors for PERI and ACLK clocks.
101 	 * core hz : apll = 1:1
102 	 */
103 	old_rate = rockchip_pll_get_rate(&rk3308_pll_clks[APLL],
104 					 priv->cru, APLL);
105 	if (old_rate > hz) {
106 		if (rockchip_pll_set_rate(&rk3308_pll_clks[APLL],
107 					  priv->cru, APLL, hz))
108 			return -EINVAL;
109 		rk_clrsetreg(&cru->clksel_con[0],
110 			     CORE_CLK_PLL_SEL_MASK | CORE_DIV_CON_MASK |
111 			     CORE_ACLK_DIV_MASK | CORE_DBG_DIV_MASK,
112 			     rate->aclk_div << CORE_ACLK_DIV_SHIFT |
113 			     rate->pclk_div << CORE_DBG_DIV_SHIFT |
114 			     CORE_CLK_PLL_SEL_APLL << CORE_CLK_PLL_SEL_SHIFT |
115 			     0 << CORE_DIV_CON_SHIFT);
116 	} else if (old_rate < hz) {
117 		rk_clrsetreg(&cru->clksel_con[0],
118 			     CORE_CLK_PLL_SEL_MASK | CORE_DIV_CON_MASK |
119 			     CORE_ACLK_DIV_MASK | CORE_DBG_DIV_MASK,
120 			     rate->aclk_div << CORE_ACLK_DIV_SHIFT |
121 			     rate->pclk_div << CORE_DBG_DIV_SHIFT |
122 			     CORE_CLK_PLL_SEL_APLL << CORE_CLK_PLL_SEL_SHIFT |
123 			     0 << CORE_DIV_CON_SHIFT);
124 		if (rockchip_pll_set_rate(&rk3308_pll_clks[APLL],
125 					  priv->cru, APLL, hz))
126 			return -EINVAL;
127 	}
128 
129 	return rockchip_pll_get_rate(&rk3308_pll_clks[APLL], priv->cru, APLL);
130 }
131 
132 static void rk3308_clk_get_pll_rate(struct rk3308_clk_priv *priv)
133 {
134 	if (!priv->dpll_hz)
135 		priv->dpll_hz = rockchip_pll_get_rate(&rk3308_pll_clks[DPLL],
136 						      priv->cru, DPLL);
137 	if (!priv->vpll0_hz)
138 		priv->vpll0_hz = rockchip_pll_get_rate(&rk3308_pll_clks[VPLL0],
139 						       priv->cru, VPLL0);
140 	if (!priv->vpll1_hz)
141 		priv->vpll1_hz = rockchip_pll_get_rate(&rk3308_pll_clks[VPLL1],
142 						       priv->cru, VPLL1);
143 }
144 
145 static ulong rk3308_i2c_get_clk(struct clk *clk)
146 {
147 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
148 	struct rk3308_cru *cru = priv->cru;
149 	u32 div, con, con_id;
150 
151 	switch (clk->id) {
152 	case SCLK_I2C0:
153 		con_id = 25;
154 		break;
155 	case SCLK_I2C1:
156 		con_id = 26;
157 		break;
158 	case SCLK_I2C2:
159 		con_id = 27;
160 		break;
161 	case SCLK_I2C3:
162 		con_id = 28;
163 		break;
164 	default:
165 		printf("do not support this i2c bus\n");
166 		return -EINVAL;
167 	}
168 
169 	con = readl(&cru->clksel_con[con_id]);
170 	div = con >> CLK_I2C_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK;
171 
172 	return DIV_TO_RATE(priv->dpll_hz, div);
173 }
174 
175 static ulong rk3308_i2c_set_clk(struct clk *clk, uint hz)
176 {
177 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
178 	struct rk3308_cru *cru = priv->cru;
179 	u32 src_clk_div, con_id;
180 
181 	src_clk_div = DIV_ROUND_UP(priv->dpll_hz, hz);
182 	assert(src_clk_div - 1 <= 127);
183 
184 	switch (clk->id) {
185 	case SCLK_I2C0:
186 		con_id = 25;
187 		break;
188 	case SCLK_I2C1:
189 		con_id = 26;
190 		break;
191 	case SCLK_I2C2:
192 		con_id = 27;
193 		break;
194 	case SCLK_I2C3:
195 		con_id = 28;
196 		break;
197 	default:
198 		printf("do not support this i2c bus\n");
199 		return -EINVAL;
200 	}
201 	rk_clrsetreg(&cru->clksel_con[con_id],
202 		     CLK_I2C_PLL_SEL_MASK | CLK_I2C_DIV_CON_MASK,
203 		     CLK_I2C_PLL_SEL_DPLL << CLK_I2C_PLL_SEL_SHIFT |
204 		     (src_clk_div - 1) << CLK_I2C_DIV_CON_SHIFT);
205 
206 	return rk3308_i2c_get_clk(clk);
207 }
208 
209 static ulong rk3308_mac_set_clk(struct clk *clk, uint hz)
210 {
211 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
212 	struct rk3308_cru *cru = priv->cru;
213 	u32 con = readl(&cru->clksel_con[43]);
214 	ulong pll_rate;
215 	u8 div;
216 
217 	if ((con >> MAC_PLL_SHIFT) & MAC_SEL_VPLL0)
218 		pll_rate = rockchip_pll_get_rate(&rk3308_pll_clks[VPLL0],
219 						 priv->cru, VPLL0);
220 	else if ((con >> MAC_PLL_SHIFT) & MAC_SEL_VPLL1)
221 		pll_rate = rockchip_pll_get_rate(&rk3308_pll_clks[VPLL1],
222 						 priv->cru, VPLL1);
223 	else
224 		pll_rate = rockchip_pll_get_rate(&rk3308_pll_clks[DPLL],
225 						 priv->cru, DPLL);
226 
227 	/*default set 50MHZ for gmac*/
228 	if (!hz)
229 		hz = 50000000;
230 
231 	div = DIV_ROUND_UP(pll_rate, hz) - 1;
232 	assert(div < 32);
233 	rk_clrsetreg(&cru->clksel_con[43], MAC_DIV_MASK,
234 		     div << MAC_DIV_SHIFT);
235 
236 	return DIV_TO_RATE(pll_rate, div);
237 }
238 
239 static int rk3308_mac_set_speed_clk(struct clk *clk, uint hz)
240 {
241 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
242 	struct rk3308_cru *cru = priv->cru;
243 
244 	if (hz != 2500000 && hz != 25000000) {
245 		debug("Unsupported mac speed:%d\n", hz);
246 		return -EINVAL;
247 	}
248 
249 	rk_clrsetreg(&cru->clksel_con[43], MAC_CLK_SPEED_SEL_MASK,
250 		     ((hz == 2500000) ? 0 : 1) << MAC_CLK_SPEED_SEL_SHIFT);
251 
252 	return 0;
253 }
254 
255 static ulong rk3308_mmc_get_clk(struct clk *clk)
256 {
257 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
258 	struct rk3308_cru *cru = priv->cru;
259 	u32 div, con, con_id;
260 
261 	switch (clk->id) {
262 	case HCLK_SDMMC:
263 	case SCLK_SDMMC:
264 		con_id = 39;
265 		break;
266 	case HCLK_EMMC:
267 	case SCLK_EMMC:
268 	case SCLK_EMMC_SAMPLE:
269 		con_id = 41;
270 		break;
271 	default:
272 		return -EINVAL;
273 	}
274 
275 	con = readl(&cru->clksel_con[con_id]);
276 	div = (con & EMMC_DIV_MASK) >> EMMC_DIV_SHIFT;
277 
278 	if ((con & EMMC_PLL_MASK) >> EMMC_PLL_SHIFT
279 	    == EMMC_SEL_24M)
280 		return DIV_TO_RATE(OSC_HZ, div) / 2;
281 	else
282 		return DIV_TO_RATE(priv->vpll0_hz, div) / 2;
283 }
284 
285 static ulong rk3308_mmc_set_clk(struct clk *clk, ulong set_rate)
286 {
287 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
288 	struct rk3308_cru *cru = priv->cru;
289 	int src_clk_div;
290 	u32 con_id;
291 
292 	debug("%s %ld %ld\n", __func__, clk->id, set_rate);
293 
294 	switch (clk->id) {
295 	case HCLK_SDMMC:
296 	case SCLK_SDMMC:
297 		con_id = 39;
298 		break;
299 	case HCLK_EMMC:
300 	case SCLK_EMMC:
301 		con_id = 41;
302 		break;
303 	default:
304 		return -EINVAL;
305 	}
306 	/* Select clk_sdmmc/emmc source from VPLL0 by default */
307 	/* mmc clock defaulg div 2 internal, need provide double in cru */
308 	src_clk_div = DIV_ROUND_UP(priv->vpll0_hz / 2, set_rate);
309 
310 	if (src_clk_div > 127) {
311 		/* use 24MHz source for 400KHz clock */
312 		src_clk_div = DIV_ROUND_UP(OSC_HZ / 2, set_rate);
313 		rk_clrsetreg(&cru->clksel_con[con_id],
314 			     EMMC_PLL_MASK | EMMC_DIV_MASK | EMMC_CLK_SEL_MASK,
315 			     EMMC_CLK_SEL_EMMC << EMMC_CLK_SEL_SHIFT |
316 			     EMMC_SEL_24M << EMMC_PLL_SHIFT |
317 			     (src_clk_div - 1) << EMMC_DIV_SHIFT);
318 	} else {
319 		rk_clrsetreg(&cru->clksel_con[con_id],
320 			     EMMC_PLL_MASK | EMMC_DIV_MASK | EMMC_CLK_SEL_MASK,
321 			     EMMC_CLK_SEL_EMMC << EMMC_CLK_SEL_SHIFT |
322 			     EMMC_SEL_VPLL0 << EMMC_PLL_SHIFT |
323 			     (src_clk_div - 1) << EMMC_DIV_SHIFT);
324 	}
325 
326 	return rk3308_mmc_get_clk(clk);
327 }
328 
329 static ulong rk3308_saradc_get_clk(struct clk *clk)
330 {
331 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
332 	struct rk3308_cru *cru = priv->cru;
333 	u32 div, con;
334 
335 	con = readl(&cru->clksel_con[34]);
336 	div = con >> CLK_SARADC_DIV_CON_SHIFT & CLK_SARADC_DIV_CON_MASK;
337 
338 	return DIV_TO_RATE(OSC_HZ, div);
339 }
340 
341 static ulong rk3308_saradc_set_clk(struct clk *clk, uint hz)
342 {
343 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
344 	struct rk3308_cru *cru = priv->cru;
345 	int src_clk_div;
346 
347 	src_clk_div = DIV_ROUND_UP(OSC_HZ, hz);
348 	assert(src_clk_div - 1 <= 2047);
349 
350 	rk_clrsetreg(&cru->clksel_con[34],
351 		     CLK_SARADC_DIV_CON_MASK,
352 		     (src_clk_div - 1) << CLK_SARADC_DIV_CON_SHIFT);
353 
354 	return rk3308_saradc_get_clk(clk);
355 }
356 
357 static ulong rk3308_tsadc_get_clk(struct clk *clk)
358 {
359 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
360 	struct rk3308_cru *cru = priv->cru;
361 	u32 div, con;
362 
363 	con = readl(&cru->clksel_con[33]);
364 	div = con >> CLK_SARADC_DIV_CON_SHIFT & CLK_SARADC_DIV_CON_MASK;
365 
366 	return DIV_TO_RATE(OSC_HZ, div);
367 }
368 
369 static ulong rk3308_tsadc_set_clk(struct clk *clk, uint hz)
370 {
371 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
372 	struct rk3308_cru *cru = priv->cru;
373 	int src_clk_div;
374 
375 	src_clk_div = DIV_ROUND_UP(OSC_HZ, hz);
376 	assert(src_clk_div - 1 <= 2047);
377 
378 	rk_clrsetreg(&cru->clksel_con[33],
379 		     CLK_SARADC_DIV_CON_MASK,
380 		     (src_clk_div - 1) << CLK_SARADC_DIV_CON_SHIFT);
381 
382 	return rk3308_tsadc_get_clk(clk);
383 }
384 
385 static ulong rk3308_spi_get_clk(struct clk *clk)
386 {
387 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
388 	struct rk3308_cru *cru = priv->cru;
389 	u32 div, con, con_id;
390 
391 	switch (clk->id) {
392 	case SCLK_SPI0:
393 		con_id = 30;
394 		break;
395 	case SCLK_SPI1:
396 		con_id = 31;
397 		break;
398 	case SCLK_SPI2:
399 		con_id = 32;
400 		break;
401 	default:
402 		printf("do not support this spi bus\n");
403 		return -EINVAL;
404 	}
405 
406 	con = readl(&cru->clksel_con[con_id]);
407 	div = con >> CLK_SPI_DIV_CON_SHIFT & CLK_SPI_DIV_CON_MASK;
408 
409 	return DIV_TO_RATE(priv->dpll_hz, div);
410 }
411 
412 static ulong rk3308_spi_set_clk(struct clk *clk, uint hz)
413 {
414 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
415 	struct rk3308_cru *cru = priv->cru;
416 	u32 src_clk_div, con_id;
417 
418 	src_clk_div = DIV_ROUND_UP(priv->dpll_hz, hz);
419 	assert(src_clk_div - 1 <= 127);
420 
421 	switch (clk->id) {
422 	case SCLK_SPI0:
423 		con_id = 30;
424 		break;
425 	case SCLK_SPI1:
426 		con_id = 31;
427 		break;
428 	case SCLK_SPI2:
429 		con_id = 32;
430 		break;
431 	default:
432 		printf("do not support this spi bus\n");
433 		return -EINVAL;
434 	}
435 
436 	rk_clrsetreg(&cru->clksel_con[con_id],
437 		     CLK_SPI_PLL_SEL_MASK | CLK_SPI_DIV_CON_MASK,
438 		     CLK_SPI_PLL_SEL_DPLL << CLK_SPI_PLL_SEL_SHIFT |
439 		     (src_clk_div - 1) << CLK_SPI_DIV_CON_SHIFT);
440 
441 	return rk3308_spi_get_clk(clk);
442 }
443 
444 static ulong rk3308_pwm_get_clk(struct clk *clk)
445 {
446 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
447 	struct rk3308_cru *cru = priv->cru;
448 	u32 div, con;
449 
450 	con = readl(&cru->clksel_con[29]);
451 	div = con >> CLK_PWM_DIV_CON_SHIFT & CLK_PWM_DIV_CON_MASK;
452 
453 	return DIV_TO_RATE(priv->dpll_hz, div);
454 }
455 
456 static ulong rk3308_pwm_set_clk(struct clk *clk, uint hz)
457 {
458 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
459 	struct rk3308_cru *cru = priv->cru;
460 	int src_clk_div;
461 
462 	src_clk_div = DIV_ROUND_UP(priv->dpll_hz, hz);
463 	assert(src_clk_div - 1 <= 127);
464 
465 	rk_clrsetreg(&cru->clksel_con[29],
466 		     CLK_PWM_PLL_SEL_MASK | CLK_PWM_DIV_CON_MASK,
467 		     CLK_PWM_PLL_SEL_DPLL << CLK_PWM_PLL_SEL_SHIFT |
468 		     (src_clk_div - 1) << CLK_PWM_DIV_CON_SHIFT);
469 
470 	return rk3308_pwm_get_clk(clk);
471 }
472 
473 static ulong rk3308_vop_get_clk(struct clk *clk)
474 {
475 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
476 	struct rk3308_cru *cru = priv->cru;
477 	u32 div, pll_sel, vol_sel, con, parent;
478 
479 	con = readl(&cru->clksel_con[8]);
480 	vol_sel = (con & DCLK_VOP_SEL_MASK) >> DCLK_VOP_SEL_SHIFT;
481 	pll_sel = (con & DCLK_VOP_PLL_SEL_MASK) >> DCLK_VOP_PLL_SEL_SHIFT;
482 	div = con & DCLK_VOP_DIV_MASK;
483 
484 	if (vol_sel == DCLK_VOP_SEL_24M) {
485 		parent = OSC_HZ;
486 	} else if (vol_sel == DCLK_VOP_SEL_DIVOUT) {
487 		switch (pll_sel) {
488 		case DCLK_VOP_PLL_SEL_DPLL:
489 			parent = priv->dpll_hz;
490 			break;
491 		case DCLK_VOP_PLL_SEL_VPLL0:
492 			parent = priv->vpll0_hz;
493 			break;
494 		case DCLK_VOP_PLL_SEL_VPLL1:
495 			parent = priv->vpll0_hz;
496 			break;
497 		default:
498 			printf("do not support this vop pll sel\n");
499 			return -EINVAL;
500 		}
501 	} else {
502 		printf("do not support this vop sel\n");
503 		return -EINVAL;
504 	}
505 
506 	return DIV_TO_RATE(parent, div);
507 }
508 
509 static ulong rk3308_vop_set_clk(struct clk *clk, ulong hz)
510 {
511 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
512 	struct rk3308_cru *cru = priv->cru;
513 	ulong pll_rate, now, best_rate = 0;
514 	u32 i, div, best_div = 0, best_sel = 0;
515 
516 	for (i = 0; i <= DCLK_VOP_PLL_SEL_VPLL1; i++) {
517 		switch (i) {
518 		case DCLK_VOP_PLL_SEL_DPLL:
519 			pll_rate = priv->dpll_hz;
520 			break;
521 		case DCLK_VOP_PLL_SEL_VPLL0:
522 			pll_rate = priv->vpll0_hz;
523 			break;
524 		case DCLK_VOP_PLL_SEL_VPLL1:
525 			pll_rate = priv->vpll1_hz;
526 			break;
527 		default:
528 			printf("do not support this vop pll sel\n");
529 			return -EINVAL;
530 		}
531 
532 		div = DIV_ROUND_UP(pll_rate, hz);
533 		if (div > 255)
534 			continue;
535 		now = pll_rate / div;
536 		if (abs(hz - now) < abs(hz - best_rate)) {
537 			best_rate = now;
538 			best_div = div;
539 			best_sel = i;
540 		}
541 		debug("pll_rate=%lu, best_rate=%lu, best_div=%u, best_sel=%u\n",
542 		      pll_rate, best_rate, best_div, best_sel);
543 	}
544 
545 	if (best_rate != hz && hz == OSC_HZ) {
546 		rk_clrsetreg(&cru->clksel_con[8],
547 			     DCLK_VOP_SEL_MASK,
548 			     DCLK_VOP_SEL_24M << DCLK_VOP_SEL_SHIFT);
549 	} else if (best_rate) {
550 		rk_clrsetreg(&cru->clksel_con[8],
551 			     DCLK_VOP_SEL_MASK | DCLK_VOP_PLL_SEL_MASK |
552 			     DCLK_VOP_DIV_MASK,
553 			     DCLK_VOP_SEL_DIVOUT << DCLK_VOP_SEL_SHIFT |
554 			     best_sel << DCLK_VOP_PLL_SEL_SHIFT |
555 			     (best_div - 1) << DCLK_VOP_DIV_SHIFT);
556 	} else {
557 		printf("do not support this vop freq\n");
558 		return -EINVAL;
559 	}
560 
561 	return rk3308_vop_get_clk(clk);
562 }
563 
564 static ulong rk3308_bus_get_clk(struct rk3308_clk_priv *priv, ulong clk_id)
565 {
566 	struct rk3308_cru *cru = priv->cru;
567 	u32 div, con, parent = priv->dpll_hz;
568 
569 	switch (clk_id) {
570 	case ACLK_BUS:
571 		con = readl(&cru->clksel_con[5]);
572 		div = (con & BUS_ACLK_DIV_MASK) >> BUS_ACLK_DIV_SHIFT;
573 		break;
574 	case HCLK_BUS:
575 		con = readl(&cru->clksel_con[6]);
576 		div = (con & BUS_HCLK_DIV_MASK) >> BUS_HCLK_DIV_SHIFT;
577 		break;
578 	case PCLK_BUS:
579 	case PCLK_WDT:
580 		con = readl(&cru->clksel_con[6]);
581 		div = (con & BUS_PCLK_DIV_MASK) >> BUS_PCLK_DIV_SHIFT;
582 		break;
583 	default:
584 		return -ENOENT;
585 	}
586 
587 	return DIV_TO_RATE(parent, div);
588 }
589 
590 static ulong rk3308_bus_set_clk(struct rk3308_clk_priv *priv, ulong clk_id,
591 				ulong hz)
592 {
593 	struct rk3308_cru *cru = priv->cru;
594 	int src_clk_div;
595 
596 	src_clk_div = DIV_ROUND_UP(priv->dpll_hz, hz);
597 	assert(src_clk_div - 1 <= 31);
598 
599 	/*
600 	 * select dpll as pd_bus bus clock source and
601 	 * set up dependent divisors for PCLK/HCLK and ACLK clocks.
602 	 */
603 	switch (clk_id) {
604 	case ACLK_BUS:
605 		rk_clrsetreg(&cru->clksel_con[5],
606 			     BUS_PLL_SEL_MASK | BUS_ACLK_DIV_MASK,
607 			     BUS_PLL_SEL_DPLL << BUS_PLL_SEL_SHIFT |
608 			     (src_clk_div - 1) << BUS_ACLK_DIV_SHIFT);
609 		break;
610 	case HCLK_BUS:
611 		rk_clrsetreg(&cru->clksel_con[6],
612 			     BUS_HCLK_DIV_MASK,
613 			     (src_clk_div - 1) << BUS_HCLK_DIV_SHIFT);
614 		break;
615 	case PCLK_BUS:
616 		rk_clrsetreg(&cru->clksel_con[6],
617 			     BUS_PCLK_DIV_MASK,
618 			     (src_clk_div - 1) << BUS_PCLK_DIV_SHIFT);
619 		break;
620 	default:
621 		printf("do not support this bus freq\n");
622 		return -EINVAL;
623 	}
624 
625 	return rk3308_bus_get_clk(priv, clk_id);
626 }
627 
628 static ulong rk3308_peri_get_clk(struct rk3308_clk_priv *priv, ulong clk_id)
629 {
630 	struct rk3308_cru *cru = priv->cru;
631 	u32 div, con, parent = priv->dpll_hz;
632 
633 	switch (clk_id) {
634 	case ACLK_PERI:
635 		con = readl(&cru->clksel_con[36]);
636 		div = (con & PERI_ACLK_DIV_MASK) >> PERI_ACLK_DIV_SHIFT;
637 		break;
638 	case HCLK_PERI:
639 		con = readl(&cru->clksel_con[37]);
640 		div = (con & PERI_HCLK_DIV_MASK) >> PERI_HCLK_DIV_SHIFT;
641 		break;
642 	case PCLK_PERI:
643 		con = readl(&cru->clksel_con[37]);
644 		div = (con & PERI_PCLK_DIV_MASK) >> PERI_PCLK_DIV_SHIFT;
645 		break;
646 	default:
647 		return -ENOENT;
648 	}
649 
650 	return DIV_TO_RATE(parent, div);
651 }
652 
653 static ulong rk3308_peri_set_clk(struct rk3308_clk_priv *priv, ulong clk_id,
654 				 ulong hz)
655 {
656 	struct rk3308_cru *cru = priv->cru;
657 	int src_clk_div;
658 
659 	src_clk_div = DIV_ROUND_UP(priv->dpll_hz, hz);
660 	assert(src_clk_div - 1 <= 31);
661 
662 	/*
663 	 * select dpll as pd_peri bus clock source and
664 	 * set up dependent divisors for PCLK/HCLK and ACLK clocks.
665 	 */
666 	switch (clk_id) {
667 	case ACLK_PERI:
668 		rk_clrsetreg(&cru->clksel_con[36],
669 			     PERI_PLL_SEL_MASK | PERI_ACLK_DIV_MASK,
670 			     PERI_PLL_DPLL << PERI_PLL_SEL_SHIFT |
671 			     (src_clk_div - 1) << PERI_ACLK_DIV_SHIFT);
672 		break;
673 	case HCLK_PERI:
674 		rk_clrsetreg(&cru->clksel_con[37],
675 			     PERI_HCLK_DIV_MASK,
676 			     (src_clk_div - 1) << PERI_HCLK_DIV_SHIFT);
677 		break;
678 	case PCLK_PERI:
679 		rk_clrsetreg(&cru->clksel_con[37],
680 			     PERI_PCLK_DIV_MASK,
681 			     (src_clk_div - 1) << PERI_PCLK_DIV_SHIFT);
682 		break;
683 	default:
684 		printf("do not support this peri freq\n");
685 		return -EINVAL;
686 	}
687 
688 	return rk3308_peri_get_clk(priv, clk_id);
689 }
690 
691 static ulong rk3308_audio_get_clk(struct rk3308_clk_priv *priv, ulong clk_id)
692 {
693 	struct rk3308_cru *cru = priv->cru;
694 	u32 div, con, parent = priv->vpll0_hz;
695 
696 	switch (clk_id) {
697 	case HCLK_AUDIO:
698 		con = readl(&cru->clksel_con[45]);
699 		div = (con & AUDIO_HCLK_DIV_MASK) >> AUDIO_HCLK_DIV_SHIFT;
700 		break;
701 	case PCLK_AUDIO:
702 		con = readl(&cru->clksel_con[45]);
703 		div = (con & AUDIO_PCLK_DIV_MASK) >> AUDIO_PCLK_DIV_SHIFT;
704 		break;
705 	default:
706 		return -ENOENT;
707 	}
708 
709 	return DIV_TO_RATE(parent, div);
710 }
711 
712 static ulong rk3308_audio_set_clk(struct rk3308_clk_priv *priv, ulong clk_id,
713 				  ulong hz)
714 {
715 	struct rk3308_cru *cru = priv->cru;
716 	int src_clk_div;
717 
718 	src_clk_div = DIV_ROUND_UP(priv->vpll0_hz, hz);
719 	assert(src_clk_div - 1 <= 31);
720 
721 	/*
722 	 * select vpll0 as audio bus clock source and
723 	 * set up dependent divisors for HCLK and PCLK clocks.
724 	 */
725 	switch (clk_id) {
726 	case HCLK_AUDIO:
727 		rk_clrsetreg(&cru->clksel_con[45],
728 			     AUDIO_PLL_SEL_MASK | AUDIO_HCLK_DIV_MASK,
729 			     AUDIO_PLL_VPLL0 << AUDIO_PLL_SEL_SHIFT |
730 			     (src_clk_div - 1) << AUDIO_HCLK_DIV_SHIFT);
731 		break;
732 	case PCLK_AUDIO:
733 		rk_clrsetreg(&cru->clksel_con[45],
734 			     AUDIO_PLL_SEL_MASK | AUDIO_PCLK_DIV_MASK,
735 			     AUDIO_PLL_VPLL0 << AUDIO_PLL_SEL_SHIFT |
736 			     (src_clk_div - 1) << AUDIO_PCLK_DIV_SHIFT);
737 		break;
738 	default:
739 		printf("do not support this audio freq\n");
740 		return -EINVAL;
741 	}
742 
743 	return rk3308_peri_get_clk(priv, clk_id);
744 }
745 
746 static ulong rk3308_crypto_get_clk(struct rk3308_clk_priv *priv, ulong clk_id)
747 {
748 	struct rk3308_cru *cru = priv->cru;
749 	u32 div, con, parent;
750 
751 	switch (clk_id) {
752 	case SCLK_CRYPTO:
753 		con = readl(&cru->clksel_con[7]);
754 		div = (con & CRYPTO_DIV_MASK) >> CRYPTO_DIV_SHIFT;
755 		parent = priv->vpll0_hz;
756 		break;
757 	case SCLK_CRYPTO_APK:
758 		con = readl(&cru->clksel_con[7]);
759 		div = (con & CRYPTO_APK_DIV_MASK) >> CRYPTO_APK_DIV_SHIFT;
760 		parent = priv->vpll0_hz;
761 		break;
762 	default:
763 		return -ENOENT;
764 	}
765 
766 	return DIV_TO_RATE(parent, div);
767 }
768 
769 static ulong rk3308_crypto_set_clk(struct rk3308_clk_priv *priv, ulong clk_id,
770 				   ulong hz)
771 {
772 	struct rk3308_cru *cru = priv->cru;
773 	int src_clk_div;
774 
775 	src_clk_div = DIV_ROUND_UP(priv->vpll0_hz, hz);
776 	assert(src_clk_div - 1 <= 31);
777 
778 	/*
779 	 * select gpll as crypto clock source and
780 	 * set up dependent divisors for crypto clocks.
781 	 */
782 	switch (clk_id) {
783 	case SCLK_CRYPTO:
784 		rk_clrsetreg(&cru->clksel_con[7],
785 			     CRYPTO_PLL_SEL_MASK | CRYPTO_DIV_MASK,
786 			     CRYPTO_PLL_SEL_VPLL0 << CRYPTO_PLL_SEL_SHIFT |
787 			     (src_clk_div - 1) << CRYPTO_DIV_SHIFT);
788 		break;
789 	case SCLK_CRYPTO_APK:
790 		rk_clrsetreg(&cru->clksel_con[7],
791 			     CRYPTO_APK_PLL_SEL_MASK | CRYPTO_APK_DIV_MASK,
792 			     CRYPTO_PLL_SEL_VPLL0 << CRYPTO_APK_SEL_SHIFT |
793 			     (src_clk_div - 1) << CRYPTO_APK_DIV_SHIFT);
794 		break;
795 	default:
796 		printf("do not support this peri freq\n");
797 		return -EINVAL;
798 	}
799 
800 	return rk3308_crypto_get_clk(priv, clk_id);
801 }
802 
803 static ulong rk3308_clk_get_rate(struct clk *clk)
804 {
805 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
806 	ulong rate = 0;
807 
808 	debug("%s id:%ld\n", __func__, clk->id);
809 
810 	switch (clk->id) {
811 	case PLL_APLL:
812 	case ARMCLK:
813 		rate = rockchip_pll_get_rate(&rk3308_pll_clks[APLL],
814 					     priv->cru, APLL);
815 		break;
816 	case PLL_DPLL:
817 		rate = rockchip_pll_get_rate(&rk3308_pll_clks[DPLL],
818 					     priv->cru, DPLL);
819 		break;
820 	case PLL_VPLL0:
821 		rate = rockchip_pll_get_rate(&rk3308_pll_clks[VPLL0],
822 					     priv->cru, VPLL0);
823 		break;
824 	case PLL_VPLL1:
825 		rate = rockchip_pll_get_rate(&rk3308_pll_clks[VPLL1],
826 					     priv->cru, VPLL1);
827 		break;
828 	case HCLK_SDMMC:
829 	case HCLK_EMMC:
830 	case SCLK_SDMMC:
831 	case SCLK_EMMC:
832 	case SCLK_EMMC_SAMPLE:
833 		rate = rk3308_mmc_get_clk(clk);
834 		break;
835 	case SCLK_I2C0:
836 	case SCLK_I2C1:
837 	case SCLK_I2C2:
838 	case SCLK_I2C3:
839 		rate = rk3308_i2c_get_clk(clk);
840 		break;
841 	case SCLK_SARADC:
842 		rate = rk3308_saradc_get_clk(clk);
843 		break;
844 	case SCLK_TSADC:
845 		rate = rk3308_tsadc_get_clk(clk);
846 		break;
847 	case SCLK_SPI0:
848 	case SCLK_SPI1:
849 		rate = rk3308_spi_get_clk(clk);
850 		break;
851 	case SCLK_PWM:
852 		rate = rk3308_pwm_get_clk(clk);
853 		break;
854 	case DCLK_VOP:
855 		rate = rk3308_vop_get_clk(clk);
856 		break;
857 	case ACLK_BUS:
858 	case HCLK_BUS:
859 	case PCLK_BUS:
860 	case PCLK_WDT:
861 		rate = rk3308_bus_get_clk(priv, clk->id);
862 		break;
863 	case ACLK_PERI:
864 	case HCLK_PERI:
865 	case PCLK_PERI:
866 		rate = rk3308_peri_get_clk(priv, clk->id);
867 		break;
868 	case HCLK_AUDIO:
869 	case PCLK_AUDIO:
870 		rate = rk3308_audio_get_clk(priv, clk->id);
871 		break;
872 	case SCLK_CRYPTO:
873 	case SCLK_CRYPTO_APK:
874 		rate = rk3308_crypto_get_clk(priv, clk->id);
875 		break;
876 	default:
877 		return -ENOENT;
878 	}
879 
880 	return rate;
881 }
882 
883 static ulong rk3308_clk_set_rate(struct clk *clk, ulong rate)
884 {
885 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
886 	ulong ret = 0;
887 
888 	debug("%s %ld %ld\n", __func__, clk->id, rate);
889 
890 	switch (clk->id) {
891 	case PLL_DPLL:
892 		ret = rockchip_pll_set_rate(&rk3308_pll_clks[DPLL], priv->cru,
893 					    DPLL, rate);
894 		priv->dpll_hz = rockchip_pll_get_rate(&rk3308_pll_clks[DPLL],
895 						      priv->cru, DPLL);
896 		break;
897 	case ARMCLK:
898 		if (priv->armclk_hz)
899 			rk3308_armclk_set_clk(priv, rate);
900 		priv->armclk_hz = rate;
901 		break;
902 	case HCLK_SDMMC:
903 	case HCLK_EMMC:
904 	case SCLK_SDMMC:
905 	case SCLK_EMMC:
906 		ret = rk3308_mmc_set_clk(clk, rate);
907 		break;
908 	case SCLK_I2C0:
909 	case SCLK_I2C1:
910 	case SCLK_I2C2:
911 	case SCLK_I2C3:
912 		ret = rk3308_i2c_set_clk(clk, rate);
913 		break;
914 	case SCLK_MAC:
915 		ret = rk3308_mac_set_clk(clk, rate);
916 		break;
917 	case SCLK_MAC_RMII:
918 		ret = rk3308_mac_set_speed_clk(clk, rate);
919 		break;
920 	case SCLK_SARADC:
921 		ret = rk3308_saradc_set_clk(clk, rate);
922 		break;
923 	case SCLK_TSADC:
924 		ret = rk3308_tsadc_set_clk(clk, rate);
925 		break;
926 	case SCLK_SPI0:
927 	case SCLK_SPI1:
928 		ret = rk3308_spi_set_clk(clk, rate);
929 		break;
930 	case SCLK_PWM:
931 		ret = rk3308_pwm_set_clk(clk, rate);
932 		break;
933 	case DCLK_VOP:
934 		ret = rk3308_vop_set_clk(clk, rate);
935 		break;
936 	case ACLK_BUS:
937 	case HCLK_BUS:
938 	case PCLK_BUS:
939 		rate = rk3308_bus_set_clk(priv, clk->id, rate);
940 		break;
941 	case ACLK_PERI:
942 	case HCLK_PERI:
943 	case PCLK_PERI:
944 		rate = rk3308_peri_set_clk(priv, clk->id, rate);
945 		break;
946 	case HCLK_AUDIO:
947 	case PCLK_AUDIO:
948 		rate = rk3308_audio_set_clk(priv, clk->id, rate);
949 		break;
950 	case SCLK_CRYPTO:
951 	case SCLK_CRYPTO_APK:
952 		ret = rk3308_crypto_set_clk(priv, clk->id, rate);
953 		break;
954 	default:
955 		return -ENOENT;
956 	}
957 
958 	return ret;
959 }
960 
961 #define ROCKCHIP_MMC_DELAY_SEL		BIT(11)
962 #define ROCKCHIP_MMC_DEGREE_OFFSET	1
963 #define ROCKCHIP_MMC_DEGREE_MASK	(0x3 << ROCKCHIP_MMC_DEGREE_OFFSET)
964 #define ROCKCHIP_MMC_DELAYNUM_OFFSET	3
965 #define ROCKCHIP_MMC_DELAYNUM_MASK	(0xff << ROCKCHIP_MMC_DELAYNUM_OFFSET)
966 
967 #define PSECS_PER_SEC 1000000000000LL
968 /*
969  * Each fine delay is between 44ps-77ps. Assume each fine delay is 60ps to
970  * simplify calculations. So 45degs could be anywhere between 33deg and 57.8deg.
971  */
972 #define ROCKCHIP_MMC_DELAY_ELEMENT_PSEC 60
973 
974 int rockchip_mmc_get_phase(struct clk *clk)
975 {
976 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
977 	struct rk3308_cru *cru = priv->cru;
978 	u32 raw_value, delay_num;
979 	u16 degrees = 0;
980 	ulong rate;
981 
982 	rate = rk3308_clk_get_rate(clk);
983 
984 	if (rate < 0)
985 		return rate;
986 
987 	if (clk->id == SCLK_EMMC_SAMPLE)
988 		raw_value = readl(&cru->emmc_con[1]);
989 	else
990 		raw_value = readl(&cru->sdmmc_con[1]);
991 
992 	raw_value &= ROCKCHIP_MMC_DEGREE_MASK;
993 	degrees = (raw_value >>  ROCKCHIP_MMC_DEGREE_OFFSET) * 90;
994 
995 	if (raw_value & ROCKCHIP_MMC_DELAY_SEL) {
996 		/* degrees/delaynum * 10000 */
997 		unsigned long factor = (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10) *
998 					36 * (rate / 1000000);
999 
1000 		delay_num = (raw_value & ROCKCHIP_MMC_DELAYNUM_MASK);
1001 		delay_num >>= ROCKCHIP_MMC_DELAYNUM_OFFSET;
1002 		degrees += DIV_ROUND_CLOSEST(delay_num * factor, 10000);
1003 	}
1004 
1005 	return degrees % 360;
1006 
1007 }
1008 
1009 int rockchip_mmc_set_phase(struct clk *clk, u32 degrees)
1010 {
1011 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
1012 	struct rk3308_cru *cru = priv->cru;
1013 	u8 nineties, remainder, delay_num;
1014 	u32 raw_value, delay;
1015 	ulong rate;
1016 
1017 	rate = rk3308_clk_get_rate(clk);
1018 
1019 	if (rate < 0)
1020 		return rate;
1021 
1022 	nineties = degrees / 90;
1023 	remainder = (degrees % 90);
1024 
1025 	/*
1026 	 * Convert to delay; do a little extra work to make sure we
1027 	 * don't overflow 32-bit / 64-bit numbers.
1028 	 */
1029 	delay = 10000000; /* PSECS_PER_SEC / 10000 / 10 */
1030 	delay *= remainder;
1031 	delay = DIV_ROUND_CLOSEST(delay, (rate / 1000) * 36 *
1032 				(ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10));
1033 
1034 	delay_num = (u8)min_t(u32, delay, 255);
1035 
1036 	raw_value = delay_num ? ROCKCHIP_MMC_DELAY_SEL : 0;
1037 	raw_value |= delay_num << ROCKCHIP_MMC_DELAYNUM_OFFSET;
1038 	raw_value |= nineties << ROCKCHIP_MMC_DEGREE_OFFSET;
1039 
1040 	if (clk->id == SCLK_EMMC_SAMPLE)
1041 		writel(raw_value | 0xffff0000, &cru->emmc_con[1]);
1042 	else
1043 		writel(raw_value | 0xffff0000, &cru->sdmmc_con[1]);
1044 
1045 	debug("mmc set_phase(%d) delay_nums=%u reg=%#x actual_degrees=%d\n",
1046 	      degrees, delay_num, raw_value, rockchip_mmc_get_phase(clk));
1047 
1048 	return 0;
1049 
1050 }
1051 
1052 static int rk3308_clk_get_phase(struct clk *clk)
1053 {
1054 	int ret;
1055 
1056 	switch (clk->id) {
1057 	case SCLK_EMMC_SAMPLE:
1058 	case SCLK_SDMMC_SAMPLE:
1059 		ret = rockchip_mmc_get_phase(clk);
1060 		break;
1061 	default:
1062 		return -ENOENT;
1063 	}
1064 
1065 	return ret;
1066 }
1067 
1068 static int rk3308_clk_set_phase(struct clk *clk, int degrees)
1069 {
1070 	int ret;
1071 
1072 	switch (clk->id) {
1073 	case SCLK_EMMC_SAMPLE:
1074 	case SCLK_SDMMC_SAMPLE:
1075 		ret = rockchip_mmc_set_phase(clk, degrees);
1076 		break;
1077 	default:
1078 		return -ENOENT;
1079 	}
1080 
1081 	return ret;
1082 }
1083 
1084 static int __maybe_unused rk3308_mac_set_parent(struct clk *clk, struct clk *parent)
1085 {
1086 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
1087 
1088 	/*
1089 	 * If the requested parent is in the same clock-controller and
1090 	 * the id is SCLK_MAC_SRC, switch to the internal clock.
1091 	 */
1092 	if (parent->id == SCLK_MAC_SRC) {
1093 		debug("%s: switching RMII to SCLK_MAC\n", __func__);
1094 		rk_clrreg(&priv->cru->clksel_con[43], BIT(14));
1095 	} else {
1096 		debug("%s: switching RMII to CLKIN\n", __func__);
1097 		rk_setreg(&priv->cru->clksel_con[43], BIT(14));
1098 	}
1099 
1100 	return 0;
1101 }
1102 
1103 static int __maybe_unused rk3308_clk_set_parent(struct clk *clk, struct clk *parent)
1104 {
1105 	switch (clk->id) {
1106 	case SCLK_MAC:
1107 		return rk3308_mac_set_parent(clk, parent);
1108 	default:
1109 		break;
1110 	}
1111 
1112 	debug("%s: unsupported clk %ld\n", __func__, clk->id);
1113 	return -ENOENT;
1114 }
1115 
1116 static struct clk_ops rk3308_clk_ops = {
1117 	.get_rate = rk3308_clk_get_rate,
1118 	.set_rate = rk3308_clk_set_rate,
1119 	.get_phase	= rk3308_clk_get_phase,
1120 	.set_phase	= rk3308_clk_set_phase,
1121 #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
1122 	.set_parent = rk3308_clk_set_parent,
1123 #endif
1124 };
1125 
1126 static void rk3308_clk_init(struct udevice *dev)
1127 {
1128 	struct rk3308_clk_priv *priv = dev_get_priv(dev);
1129 	int ret;
1130 
1131 	if (rockchip_pll_get_rate(&rk3308_pll_clks[APLL],
1132 				  priv->cru, APLL) != APLL_HZ) {
1133 		ret = rk3308_armclk_set_clk(priv, APLL_HZ);
1134 		if (ret < 0)
1135 			printf("%s failed to set armclk rate\n", __func__);
1136 	}
1137 
1138 	rk3308_clk_get_pll_rate(priv);
1139 
1140 	rk3308_bus_set_clk(priv, ACLK_BUS, BUS_ACLK_HZ);
1141 	rk3308_bus_set_clk(priv, HCLK_BUS, BUS_HCLK_HZ);
1142 	rk3308_bus_set_clk(priv, PCLK_BUS, BUS_PCLK_HZ);
1143 
1144 	rk3308_peri_set_clk(priv, ACLK_PERI, PERI_ACLK_HZ);
1145 	rk3308_peri_set_clk(priv, HCLK_PERI, PERI_HCLK_HZ);
1146 	rk3308_peri_set_clk(priv, PCLK_PERI, PERI_PCLK_HZ);
1147 
1148 	rk3308_audio_set_clk(priv, HCLK_AUDIO, AUDIO_HCLK_HZ);
1149 	rk3308_audio_set_clk(priv, PCLK_AUDIO, AUDIO_PCLK_HZ);
1150 }
1151 
1152 static int rk3308_clk_probe(struct udevice *dev)
1153 {
1154 	struct rk3308_clk_priv *priv = dev_get_priv(dev);
1155 	int ret;
1156 
1157 	priv->sync_kernel = false;
1158 	if (!priv->armclk_enter_hz)
1159 		priv->armclk_enter_hz =
1160 		rockchip_pll_get_rate(&rk3308_pll_clks[APLL],
1161 				      priv->cru, APLL);
1162 	rk3308_clk_init(dev);
1163 	if (!priv->armclk_init_hz)
1164 		priv->armclk_init_hz =
1165 		rockchip_pll_get_rate(&rk3308_pll_clks[APLL],
1166 				      priv->cru, APLL);
1167 
1168 	/* Process 'assigned-{clocks/clock-parents/clock-rates}' properties */
1169 	ret = clk_set_defaults(dev);
1170 	if (ret)
1171 		debug("%s clk_set_defaults failed %d\n", __func__, ret);
1172 	else
1173 		priv->sync_kernel = true;
1174 
1175 	return 0;
1176 }
1177 
1178 static int rk3308_clk_ofdata_to_platdata(struct udevice *dev)
1179 {
1180 	struct rk3308_clk_priv *priv = dev_get_priv(dev);
1181 
1182 	priv->cru = dev_read_addr_ptr(dev);
1183 
1184 	return 0;
1185 }
1186 
1187 static int rk3308_clk_bind(struct udevice *dev)
1188 {
1189 	int ret;
1190 	struct udevice *sys_child, *sf_child;
1191 	struct sysreset_reg *priv;
1192 	struct softreset_reg *sf_priv;
1193 
1194 	/* The reset driver does not have a device node, so bind it here */
1195 	ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset",
1196 				 &sys_child);
1197 	if (ret) {
1198 		debug("Warning: No sysreset driver: ret=%d\n", ret);
1199 	} else {
1200 		priv = malloc(sizeof(struct sysreset_reg));
1201 		priv->glb_srst_fst_value = offsetof(struct rk3308_cru,
1202 						    glb_srst_fst);
1203 		priv->glb_srst_snd_value = offsetof(struct rk3308_cru,
1204 						    glb_srst_snd);
1205 		sys_child->priv = priv;
1206 	}
1207 
1208 	ret = device_bind_driver_to_node(dev, "rockchip_reset", "reset",
1209 					 dev_ofnode(dev), &sf_child);
1210 	if (ret) {
1211 		debug("Warning: No rockchip reset driver: ret=%d\n", ret);
1212 	} else {
1213 		sf_priv = malloc(sizeof(struct softreset_reg));
1214 		sf_priv->sf_reset_offset = offsetof(struct rk3308_cru,
1215 						    softrst_con[0]);
1216 		sf_priv->sf_reset_num = 12;
1217 		sf_child->priv = sf_priv;
1218 	}
1219 
1220 	return 0;
1221 }
1222 
1223 static const struct udevice_id rk3308_clk_ids[] = {
1224 	{ .compatible = "rockchip,rk3308-cru" },
1225 	{ }
1226 };
1227 
1228 U_BOOT_DRIVER(rockchip_rk3308_cru) = {
1229 	.name		= "rockchip_rk3308_cru",
1230 	.id		= UCLASS_CLK,
1231 	.of_match	= rk3308_clk_ids,
1232 	.priv_auto_alloc_size = sizeof(struct rk3308_clk_priv),
1233 	.ofdata_to_platdata = rk3308_clk_ofdata_to_platdata,
1234 	.ops		= &rk3308_clk_ops,
1235 	.bind		= rk3308_clk_bind,
1236 	.probe		= rk3308_clk_probe,
1237 };
1238 
1239 /**
1240  * soc_clk_dump() - Print clock frequencies
1241  * Returns zero on success
1242  *
1243  * Implementation for the clk dump command.
1244  */
1245 int soc_clk_dump(void)
1246 {
1247 	struct udevice *cru_dev;
1248 	struct rk3308_clk_priv *priv;
1249 	const struct rk3308_clk_info *clk_dump;
1250 	struct clk clk;
1251 	unsigned long clk_count = ARRAY_SIZE(clks_dump);
1252 	unsigned long rate;
1253 	int i, ret;
1254 
1255 	ret = uclass_get_device_by_driver(UCLASS_CLK,
1256 					  DM_GET_DRIVER(rockchip_rk3308_cru),
1257 					  &cru_dev);
1258 	if (ret) {
1259 		printf("%s failed to get cru device\n", __func__);
1260 		return ret;
1261 	}
1262 
1263 	priv = dev_get_priv(cru_dev);
1264 	printf("CLK: (%s. arm: enter %lu KHz, init %lu KHz, kernel %lu%s)\n",
1265 	       priv->sync_kernel ? "sync kernel" : "uboot",
1266 	       priv->armclk_enter_hz / 1000,
1267 	       priv->armclk_init_hz / 1000,
1268 	       priv->set_armclk_rate ? priv->armclk_hz / 1000 : 0,
1269 	       priv->set_armclk_rate ? " KHz" : "N/A");
1270 	for (i = 0; i < clk_count; i++) {
1271 		clk_dump = &clks_dump[i];
1272 		if (clk_dump->name) {
1273 			clk.id = clk_dump->id;
1274 			ret = clk_request(cru_dev, &clk);
1275 			if (ret < 0)
1276 				return ret;
1277 
1278 			rate = clk_get_rate(&clk);
1279 			clk_free(&clk);
1280 			if (i == 0) {
1281 				if (rate < 0)
1282 					printf("  %s %s\n", clk_dump->name,
1283 					       "unknown");
1284 				else
1285 					printf("  %s %lu KHz\n", clk_dump->name,
1286 					       rate / 1000);
1287 			} else {
1288 				if (rate < 0)
1289 					printf("  %s %s\n", clk_dump->name,
1290 					       "unknown");
1291 				else
1292 					printf("  %s %lu KHz\n", clk_dump->name,
1293 					       rate / 1000);
1294 			}
1295 		}
1296 	}
1297 
1298 	return 0;
1299 }
1300