xref: /rk3399_rockchip-uboot/drivers/clk/rockchip/clk_rk3308.c (revision 5e8564cf419797f9095431e6eb6f0c00dfa423d2)
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 #ifndef CONFIG_SPL_BUILD
747 static ulong rk3308_crypto_get_clk(struct rk3308_clk_priv *priv, ulong clk_id)
748 {
749 	struct rk3308_cru *cru = priv->cru;
750 	u32 div, con, parent;
751 
752 	switch (clk_id) {
753 	case SCLK_CRYPTO:
754 		con = readl(&cru->clksel_con[7]);
755 		div = (con & CRYPTO_DIV_MASK) >> CRYPTO_DIV_SHIFT;
756 		parent = priv->vpll0_hz;
757 		break;
758 	case SCLK_CRYPTO_APK:
759 		con = readl(&cru->clksel_con[7]);
760 		div = (con & CRYPTO_APK_DIV_MASK) >> CRYPTO_APK_DIV_SHIFT;
761 		parent = priv->vpll0_hz;
762 		break;
763 	default:
764 		return -ENOENT;
765 	}
766 
767 	return DIV_TO_RATE(parent, div);
768 }
769 
770 static ulong rk3308_crypto_set_clk(struct rk3308_clk_priv *priv, ulong clk_id,
771 				   ulong hz)
772 {
773 	struct rk3308_cru *cru = priv->cru;
774 	int src_clk_div;
775 
776 	src_clk_div = DIV_ROUND_UP(priv->vpll0_hz, hz);
777 	assert(src_clk_div - 1 <= 31);
778 
779 	/*
780 	 * select gpll as crypto clock source and
781 	 * set up dependent divisors for crypto clocks.
782 	 */
783 	switch (clk_id) {
784 	case SCLK_CRYPTO:
785 		rk_clrsetreg(&cru->clksel_con[7],
786 			     CRYPTO_PLL_SEL_MASK | CRYPTO_DIV_MASK,
787 			     CRYPTO_PLL_SEL_VPLL0 << CRYPTO_PLL_SEL_SHIFT |
788 			     (src_clk_div - 1) << CRYPTO_DIV_SHIFT);
789 		break;
790 	case SCLK_CRYPTO_APK:
791 		rk_clrsetreg(&cru->clksel_con[7],
792 			     CRYPTO_APK_PLL_SEL_MASK | CRYPTO_APK_DIV_MASK,
793 			     CRYPTO_PLL_SEL_VPLL0 << CRYPTO_APK_SEL_SHIFT |
794 			     (src_clk_div - 1) << CRYPTO_APK_DIV_SHIFT);
795 		break;
796 	default:
797 		printf("do not support this peri freq\n");
798 		return -EINVAL;
799 	}
800 
801 	return rk3308_crypto_get_clk(priv, clk_id);
802 }
803 #endif
804 
805 static ulong rk3308_clk_get_rate(struct clk *clk)
806 {
807 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
808 	ulong rate = 0;
809 
810 	debug("%s id:%ld\n", __func__, clk->id);
811 
812 	switch (clk->id) {
813 	case PLL_APLL:
814 	case ARMCLK:
815 		rate = rockchip_pll_get_rate(&rk3308_pll_clks[APLL],
816 					     priv->cru, APLL);
817 		break;
818 	case PLL_DPLL:
819 		rate = rockchip_pll_get_rate(&rk3308_pll_clks[DPLL],
820 					     priv->cru, DPLL);
821 		break;
822 	case PLL_VPLL0:
823 		rate = rockchip_pll_get_rate(&rk3308_pll_clks[VPLL0],
824 					     priv->cru, VPLL0);
825 		break;
826 	case PLL_VPLL1:
827 		rate = rockchip_pll_get_rate(&rk3308_pll_clks[VPLL1],
828 					     priv->cru, VPLL1);
829 		break;
830 	case HCLK_SDMMC:
831 	case HCLK_EMMC:
832 	case SCLK_SDMMC:
833 	case SCLK_EMMC:
834 	case SCLK_EMMC_SAMPLE:
835 		rate = rk3308_mmc_get_clk(clk);
836 		break;
837 	case SCLK_I2C0:
838 	case SCLK_I2C1:
839 	case SCLK_I2C2:
840 	case SCLK_I2C3:
841 		rate = rk3308_i2c_get_clk(clk);
842 		break;
843 	case SCLK_SARADC:
844 		rate = rk3308_saradc_get_clk(clk);
845 		break;
846 	case SCLK_TSADC:
847 		rate = rk3308_tsadc_get_clk(clk);
848 		break;
849 	case SCLK_SPI0:
850 	case SCLK_SPI1:
851 		rate = rk3308_spi_get_clk(clk);
852 		break;
853 	case SCLK_PWM:
854 		rate = rk3308_pwm_get_clk(clk);
855 		break;
856 	case DCLK_VOP:
857 		rate = rk3308_vop_get_clk(clk);
858 		break;
859 	case ACLK_BUS:
860 	case HCLK_BUS:
861 	case PCLK_BUS:
862 	case PCLK_WDT:
863 		rate = rk3308_bus_get_clk(priv, clk->id);
864 		break;
865 	case ACLK_PERI:
866 	case HCLK_PERI:
867 	case PCLK_PERI:
868 		rate = rk3308_peri_get_clk(priv, clk->id);
869 		break;
870 	case HCLK_AUDIO:
871 	case PCLK_AUDIO:
872 		rate = rk3308_audio_get_clk(priv, clk->id);
873 		break;
874 #ifndef CONFIG_SPL_BUILD
875 	case SCLK_CRYPTO:
876 	case SCLK_CRYPTO_APK:
877 		rate = rk3308_crypto_get_clk(priv, clk->id);
878 		break;
879 #endif
880 	default:
881 		return -ENOENT;
882 	}
883 
884 	return rate;
885 }
886 
887 static ulong rk3308_clk_set_rate(struct clk *clk, ulong rate)
888 {
889 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
890 	ulong ret = 0;
891 
892 	debug("%s %ld %ld\n", __func__, clk->id, rate);
893 
894 	switch (clk->id) {
895 	case PLL_DPLL:
896 		ret = rockchip_pll_set_rate(&rk3308_pll_clks[DPLL], priv->cru,
897 					    DPLL, rate);
898 		priv->dpll_hz = rockchip_pll_get_rate(&rk3308_pll_clks[DPLL],
899 						      priv->cru, DPLL);
900 		break;
901 	case ARMCLK:
902 		if (priv->armclk_hz)
903 			rk3308_armclk_set_clk(priv, rate);
904 		priv->armclk_hz = rate;
905 		break;
906 	case HCLK_SDMMC:
907 	case HCLK_EMMC:
908 	case SCLK_SDMMC:
909 	case SCLK_EMMC:
910 		ret = rk3308_mmc_set_clk(clk, rate);
911 		break;
912 	case SCLK_I2C0:
913 	case SCLK_I2C1:
914 	case SCLK_I2C2:
915 	case SCLK_I2C3:
916 		ret = rk3308_i2c_set_clk(clk, rate);
917 		break;
918 	case SCLK_MAC:
919 		ret = rk3308_mac_set_clk(clk, rate);
920 		break;
921 	case SCLK_MAC_RMII:
922 		ret = rk3308_mac_set_speed_clk(clk, rate);
923 		break;
924 	case SCLK_SARADC:
925 		ret = rk3308_saradc_set_clk(clk, rate);
926 		break;
927 	case SCLK_TSADC:
928 		ret = rk3308_tsadc_set_clk(clk, rate);
929 		break;
930 	case SCLK_SPI0:
931 	case SCLK_SPI1:
932 		ret = rk3308_spi_set_clk(clk, rate);
933 		break;
934 	case SCLK_PWM:
935 		ret = rk3308_pwm_set_clk(clk, rate);
936 		break;
937 	case DCLK_VOP:
938 		ret = rk3308_vop_set_clk(clk, rate);
939 		break;
940 	case ACLK_BUS:
941 	case HCLK_BUS:
942 	case PCLK_BUS:
943 		rate = rk3308_bus_set_clk(priv, clk->id, rate);
944 		break;
945 	case ACLK_PERI:
946 	case HCLK_PERI:
947 	case PCLK_PERI:
948 		rate = rk3308_peri_set_clk(priv, clk->id, rate);
949 		break;
950 	case HCLK_AUDIO:
951 	case PCLK_AUDIO:
952 		rate = rk3308_audio_set_clk(priv, clk->id, rate);
953 		break;
954 #ifndef CONFIG_SPL_BUILD
955 	case SCLK_CRYPTO:
956 	case SCLK_CRYPTO_APK:
957 		ret = rk3308_crypto_set_clk(priv, clk->id, rate);
958 		break;
959 #endif
960 	default:
961 		return -ENOENT;
962 	}
963 
964 	return ret;
965 }
966 
967 #define ROCKCHIP_MMC_DELAY_SEL		BIT(11)
968 #define ROCKCHIP_MMC_DEGREE_OFFSET	1
969 #define ROCKCHIP_MMC_DEGREE_MASK	(0x3 << ROCKCHIP_MMC_DEGREE_OFFSET)
970 #define ROCKCHIP_MMC_DELAYNUM_OFFSET	3
971 #define ROCKCHIP_MMC_DELAYNUM_MASK	(0xff << ROCKCHIP_MMC_DELAYNUM_OFFSET)
972 
973 #define PSECS_PER_SEC 1000000000000LL
974 /*
975  * Each fine delay is between 44ps-77ps. Assume each fine delay is 60ps to
976  * simplify calculations. So 45degs could be anywhere between 33deg and 57.8deg.
977  */
978 #define ROCKCHIP_MMC_DELAY_ELEMENT_PSEC 60
979 
980 int rockchip_mmc_get_phase(struct clk *clk)
981 {
982 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
983 	struct rk3308_cru *cru = priv->cru;
984 	u32 raw_value, delay_num;
985 	u16 degrees = 0;
986 	ulong rate;
987 
988 	rate = rk3308_clk_get_rate(clk);
989 
990 	if (rate < 0)
991 		return rate;
992 
993 	if (clk->id == SCLK_EMMC_SAMPLE)
994 		raw_value = readl(&cru->emmc_con[1]);
995 	else
996 		raw_value = readl(&cru->sdmmc_con[1]);
997 
998 	raw_value &= ROCKCHIP_MMC_DEGREE_MASK;
999 	degrees = (raw_value >>  ROCKCHIP_MMC_DEGREE_OFFSET) * 90;
1000 
1001 	if (raw_value & ROCKCHIP_MMC_DELAY_SEL) {
1002 		/* degrees/delaynum * 10000 */
1003 		unsigned long factor = (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10) *
1004 					36 * (rate / 1000000);
1005 
1006 		delay_num = (raw_value & ROCKCHIP_MMC_DELAYNUM_MASK);
1007 		delay_num >>= ROCKCHIP_MMC_DELAYNUM_OFFSET;
1008 		degrees += DIV_ROUND_CLOSEST(delay_num * factor, 10000);
1009 	}
1010 
1011 	return degrees % 360;
1012 
1013 }
1014 
1015 int rockchip_mmc_set_phase(struct clk *clk, u32 degrees)
1016 {
1017 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
1018 	struct rk3308_cru *cru = priv->cru;
1019 	u8 nineties, remainder, delay_num;
1020 	u32 raw_value, delay;
1021 	ulong rate;
1022 
1023 	rate = rk3308_clk_get_rate(clk);
1024 
1025 	if (rate < 0)
1026 		return rate;
1027 
1028 	nineties = degrees / 90;
1029 	remainder = (degrees % 90);
1030 
1031 	/*
1032 	 * Convert to delay; do a little extra work to make sure we
1033 	 * don't overflow 32-bit / 64-bit numbers.
1034 	 */
1035 	delay = 10000000; /* PSECS_PER_SEC / 10000 / 10 */
1036 	delay *= remainder;
1037 	delay = DIV_ROUND_CLOSEST(delay, (rate / 1000) * 36 *
1038 				(ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10));
1039 
1040 	delay_num = (u8)min_t(u32, delay, 255);
1041 
1042 	raw_value = delay_num ? ROCKCHIP_MMC_DELAY_SEL : 0;
1043 	raw_value |= delay_num << ROCKCHIP_MMC_DELAYNUM_OFFSET;
1044 	raw_value |= nineties << ROCKCHIP_MMC_DEGREE_OFFSET;
1045 
1046 	if (clk->id == SCLK_EMMC_SAMPLE)
1047 		writel(raw_value | 0xffff0000, &cru->emmc_con[1]);
1048 	else
1049 		writel(raw_value | 0xffff0000, &cru->sdmmc_con[1]);
1050 
1051 	debug("mmc set_phase(%d) delay_nums=%u reg=%#x actual_degrees=%d\n",
1052 	      degrees, delay_num, raw_value, rockchip_mmc_get_phase(clk));
1053 
1054 	return 0;
1055 
1056 }
1057 
1058 static int rk3308_clk_get_phase(struct clk *clk)
1059 {
1060 	int ret;
1061 
1062 	switch (clk->id) {
1063 	case SCLK_EMMC_SAMPLE:
1064 	case SCLK_SDMMC_SAMPLE:
1065 		ret = rockchip_mmc_get_phase(clk);
1066 		break;
1067 	default:
1068 		return -ENOENT;
1069 	}
1070 
1071 	return ret;
1072 }
1073 
1074 static int rk3308_clk_set_phase(struct clk *clk, int degrees)
1075 {
1076 	int ret;
1077 
1078 	switch (clk->id) {
1079 	case SCLK_EMMC_SAMPLE:
1080 	case SCLK_SDMMC_SAMPLE:
1081 		ret = rockchip_mmc_set_phase(clk, degrees);
1082 		break;
1083 	default:
1084 		return -ENOENT;
1085 	}
1086 
1087 	return ret;
1088 }
1089 
1090 static int __maybe_unused rk3308_mac_set_parent(struct clk *clk, struct clk *parent)
1091 {
1092 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
1093 
1094 	/*
1095 	 * If the requested parent is in the same clock-controller and
1096 	 * the id is SCLK_MAC_SRC, switch to the internal clock.
1097 	 */
1098 	if (parent->id == SCLK_MAC_SRC) {
1099 		debug("%s: switching RMII to SCLK_MAC\n", __func__);
1100 		rk_clrreg(&priv->cru->clksel_con[43], BIT(14));
1101 	} else {
1102 		debug("%s: switching RMII to CLKIN\n", __func__);
1103 		rk_setreg(&priv->cru->clksel_con[43], BIT(14));
1104 	}
1105 
1106 	return 0;
1107 }
1108 
1109 static int __maybe_unused rk3308_clk_set_parent(struct clk *clk, struct clk *parent)
1110 {
1111 	switch (clk->id) {
1112 	case SCLK_MAC:
1113 		return rk3308_mac_set_parent(clk, parent);
1114 	default:
1115 		break;
1116 	}
1117 
1118 	debug("%s: unsupported clk %ld\n", __func__, clk->id);
1119 	return -ENOENT;
1120 }
1121 
1122 static struct clk_ops rk3308_clk_ops = {
1123 	.get_rate = rk3308_clk_get_rate,
1124 	.set_rate = rk3308_clk_set_rate,
1125 	.get_phase	= rk3308_clk_get_phase,
1126 	.set_phase	= rk3308_clk_set_phase,
1127 #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
1128 	.set_parent = rk3308_clk_set_parent,
1129 #endif
1130 };
1131 
1132 static void rk3308_clk_init(struct udevice *dev)
1133 {
1134 	struct rk3308_clk_priv *priv = dev_get_priv(dev);
1135 	int ret;
1136 
1137 	if (rockchip_pll_get_rate(&rk3308_pll_clks[APLL],
1138 				  priv->cru, APLL) != APLL_HZ) {
1139 		ret = rk3308_armclk_set_clk(priv, APLL_HZ);
1140 		if (ret < 0)
1141 			printf("%s failed to set armclk rate\n", __func__);
1142 	}
1143 
1144 	rk3308_clk_get_pll_rate(priv);
1145 
1146 	rk3308_bus_set_clk(priv, ACLK_BUS, BUS_ACLK_HZ);
1147 	rk3308_bus_set_clk(priv, HCLK_BUS, BUS_HCLK_HZ);
1148 	rk3308_bus_set_clk(priv, PCLK_BUS, BUS_PCLK_HZ);
1149 
1150 	rk3308_peri_set_clk(priv, ACLK_PERI, PERI_ACLK_HZ);
1151 	rk3308_peri_set_clk(priv, HCLK_PERI, PERI_HCLK_HZ);
1152 	rk3308_peri_set_clk(priv, PCLK_PERI, PERI_PCLK_HZ);
1153 
1154 	rk3308_audio_set_clk(priv, HCLK_AUDIO, AUDIO_HCLK_HZ);
1155 	rk3308_audio_set_clk(priv, PCLK_AUDIO, AUDIO_PCLK_HZ);
1156 }
1157 
1158 static int rk3308_clk_probe(struct udevice *dev)
1159 {
1160 	struct rk3308_clk_priv *priv = dev_get_priv(dev);
1161 	int ret;
1162 
1163 	priv->sync_kernel = false;
1164 	if (!priv->armclk_enter_hz)
1165 		priv->armclk_enter_hz =
1166 		rockchip_pll_get_rate(&rk3308_pll_clks[APLL],
1167 				      priv->cru, APLL);
1168 	rk3308_clk_init(dev);
1169 	if (!priv->armclk_init_hz)
1170 		priv->armclk_init_hz =
1171 		rockchip_pll_get_rate(&rk3308_pll_clks[APLL],
1172 				      priv->cru, APLL);
1173 
1174 	/* Process 'assigned-{clocks/clock-parents/clock-rates}' properties */
1175 	ret = clk_set_defaults(dev);
1176 	if (ret)
1177 		debug("%s clk_set_defaults failed %d\n", __func__, ret);
1178 	else
1179 		priv->sync_kernel = true;
1180 
1181 	return 0;
1182 }
1183 
1184 static int rk3308_clk_ofdata_to_platdata(struct udevice *dev)
1185 {
1186 	struct rk3308_clk_priv *priv = dev_get_priv(dev);
1187 
1188 	priv->cru = dev_read_addr_ptr(dev);
1189 
1190 	return 0;
1191 }
1192 
1193 static int rk3308_clk_bind(struct udevice *dev)
1194 {
1195 	int ret;
1196 	struct udevice *sys_child, *sf_child;
1197 	struct sysreset_reg *priv;
1198 	struct softreset_reg *sf_priv;
1199 
1200 	/* The reset driver does not have a device node, so bind it here */
1201 	ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset",
1202 				 &sys_child);
1203 	if (ret) {
1204 		debug("Warning: No sysreset driver: ret=%d\n", ret);
1205 	} else {
1206 		priv = malloc(sizeof(struct sysreset_reg));
1207 		priv->glb_srst_fst_value = offsetof(struct rk3308_cru,
1208 						    glb_srst_fst);
1209 		priv->glb_srst_snd_value = offsetof(struct rk3308_cru,
1210 						    glb_srst_snd);
1211 		sys_child->priv = priv;
1212 	}
1213 
1214 	ret = device_bind_driver_to_node(dev, "rockchip_reset", "reset",
1215 					 dev_ofnode(dev), &sf_child);
1216 	if (ret) {
1217 		debug("Warning: No rockchip reset driver: ret=%d\n", ret);
1218 	} else {
1219 		sf_priv = malloc(sizeof(struct softreset_reg));
1220 		sf_priv->sf_reset_offset = offsetof(struct rk3308_cru,
1221 						    softrst_con[0]);
1222 		sf_priv->sf_reset_num = 12;
1223 		sf_child->priv = sf_priv;
1224 	}
1225 
1226 	return 0;
1227 }
1228 
1229 static const struct udevice_id rk3308_clk_ids[] = {
1230 	{ .compatible = "rockchip,rk3308-cru" },
1231 	{ }
1232 };
1233 
1234 U_BOOT_DRIVER(rockchip_rk3308_cru) = {
1235 	.name		= "rockchip_rk3308_cru",
1236 	.id		= UCLASS_CLK,
1237 	.of_match	= rk3308_clk_ids,
1238 	.priv_auto_alloc_size = sizeof(struct rk3308_clk_priv),
1239 	.ofdata_to_platdata = rk3308_clk_ofdata_to_platdata,
1240 	.ops		= &rk3308_clk_ops,
1241 	.bind		= rk3308_clk_bind,
1242 	.probe		= rk3308_clk_probe,
1243 };
1244 
1245 /**
1246  * soc_clk_dump() - Print clock frequencies
1247  * Returns zero on success
1248  *
1249  * Implementation for the clk dump command.
1250  */
1251 int soc_clk_dump(void)
1252 {
1253 	struct udevice *cru_dev;
1254 	struct rk3308_clk_priv *priv;
1255 	const struct rk3308_clk_info *clk_dump;
1256 	struct clk clk;
1257 	unsigned long clk_count = ARRAY_SIZE(clks_dump);
1258 	unsigned long rate;
1259 	int i, ret;
1260 
1261 	ret = uclass_get_device_by_driver(UCLASS_CLK,
1262 					  DM_GET_DRIVER(rockchip_rk3308_cru),
1263 					  &cru_dev);
1264 	if (ret) {
1265 		printf("%s failed to get cru device\n", __func__);
1266 		return ret;
1267 	}
1268 
1269 	priv = dev_get_priv(cru_dev);
1270 	printf("CLK: (%s. arm: enter %lu KHz, init %lu KHz, kernel %lu%s)\n",
1271 	       priv->sync_kernel ? "sync kernel" : "uboot",
1272 	       priv->armclk_enter_hz / 1000,
1273 	       priv->armclk_init_hz / 1000,
1274 	       priv->set_armclk_rate ? priv->armclk_hz / 1000 : 0,
1275 	       priv->set_armclk_rate ? " KHz" : "N/A");
1276 	for (i = 0; i < clk_count; i++) {
1277 		clk_dump = &clks_dump[i];
1278 		if (clk_dump->name) {
1279 			clk.id = clk_dump->id;
1280 			ret = clk_request(cru_dev, &clk);
1281 			if (ret < 0)
1282 				return ret;
1283 
1284 			rate = clk_get_rate(&clk);
1285 			clk_free(&clk);
1286 			if (i == 0) {
1287 				if (rate < 0)
1288 					printf("  %s %s\n", clk_dump->name,
1289 					       "unknown");
1290 				else
1291 					printf("  %s %lu KHz\n", clk_dump->name,
1292 					       rate / 1000);
1293 			} else {
1294 				if (rate < 0)
1295 					printf("  %s %s\n", clk_dump->name,
1296 					       "unknown");
1297 				else
1298 					printf("  %s %lu KHz\n", clk_dump->name,
1299 					       rate / 1000);
1300 			}
1301 		}
1302 	}
1303 
1304 	return 0;
1305 }
1306