xref: /rk3399_rockchip-uboot/drivers/clk/rockchip/clk_rk1808.c (revision 5b2bcb4f4876b482fa1a7e95cccab65aad50f90b)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2018 Fuzhou Rockchip Electronics Co., Ltd
4  */
5 
6 #include <common.h>
7 #include <bitfield.h>
8 #include <clk-uclass.h>
9 #include <dm.h>
10 #include <errno.h>
11 #include <syscon.h>
12 #include <clk.h>
13 #include <asm/arch/clock.h>
14 #include <asm/arch/cru_rk1808.h>
15 #include <asm/arch/hardware.h>
16 #include <asm/io.h>
17 #include <dm/lists.h>
18 #include <dt-bindings/clock/rk1808-cru.h>
19 #include <div64.h>
20 
21 DECLARE_GLOBAL_DATA_PTR;
22 
23 #define RK1808_CPUCLK_RATE(_rate, _aclk_div, _pclk_div)		\
24 {								\
25 	.rate	= _rate##U,					\
26 	.aclk_div = _aclk_div,					\
27 	.pclk_div = _pclk_div,					\
28 }
29 
30 #define DIV_TO_RATE(input_rate, div)    ((input_rate) / ((div) + 1))
31 
32 static struct rockchip_pll_rate_table rk1808_pll_rates[] = {
33 	/* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */
34 	RK3036_PLL_RATE(1200000000, 1, 50, 1, 1, 1, 0),
35 	RK3036_PLL_RATE(1188000000, 2, 99, 1, 1, 1, 0),
36 	RK3036_PLL_RATE(1100000000, 12, 550, 1, 1, 1, 0),
37 	RK3036_PLL_RATE(1008000000, 1, 84, 2, 1, 1, 0),
38 	RK3036_PLL_RATE(1000000000, 6, 500, 2, 1, 1, 0),
39 	RK3036_PLL_RATE(816000000, 1, 68, 2, 1, 1, 0),
40 	RK3036_PLL_RATE(800000000, 6, 400, 2, 1, 1, 0),
41 	RK3036_PLL_RATE(600000000, 1, 75, 3, 1, 1, 0),
42 	RK3036_PLL_RATE(594000000, 2, 99, 2, 1, 1, 0),
43 	RK3036_PLL_RATE(500000000, 6, 250, 2, 1, 1, 0),
44 	RK3036_PLL_RATE(200000000, 1, 200, 6, 4, 1, 0),
45 	{ /* sentinel */ },
46 };
47 
48 #ifndef CONFIG_SPL_BUILD
49 #define RK1808_CLK_DUMP(_id, _name, _iscru)	\
50 {						\
51 	.id = _id,				\
52 	.name = _name,				\
53 	.is_cru = _iscru,			\
54 }
55 
56 static const struct rk1808_clk_info clks_dump[] = {
57 	RK1808_CLK_DUMP(PLL_APLL, "apll", true),
58 	RK1808_CLK_DUMP(PLL_DPLL, "dpll", true),
59 	RK1808_CLK_DUMP(PLL_CPLL, "cpll", true),
60 	RK1808_CLK_DUMP(PLL_GPLL, "gpll", true),
61 	RK1808_CLK_DUMP(PLL_NPLL, "npll", true),
62 	RK1808_CLK_DUMP(PLL_PPLL, "ppll", true),
63 	RK1808_CLK_DUMP(HSCLK_BUS_PRE, "hsclk_bus", true),
64 	RK1808_CLK_DUMP(MSCLK_BUS_PRE, "msclk_bus", true),
65 	RK1808_CLK_DUMP(LSCLK_BUS_PRE, "lsclk_bus", true),
66 	RK1808_CLK_DUMP(MSCLK_PERI, "msclk_peri", true),
67 	RK1808_CLK_DUMP(LSCLK_PERI, "lsclk_peri", true),
68 };
69 #endif
70 
71 static struct rockchip_cpu_rate_table rk1808_cpu_rates[] = {
72 	RK1808_CPUCLK_RATE(1200000000, 1, 5),
73 	RK1808_CPUCLK_RATE(1008000000, 1, 5),
74 	RK1808_CPUCLK_RATE(816000000, 1, 3),
75 	RK1808_CPUCLK_RATE(600000000, 1, 3),
76 };
77 
78 static struct rockchip_pll_clock rk1808_pll_clks[] = {
79 	[APLL] = PLL(pll_rk3036, PLL_APLL, RK1808_PLL_CON(0),
80 		     RK1808_MODE_CON, 0, 10, 0, rk1808_pll_rates),
81 	[DPLL] = PLL(pll_rk3036, PLL_DPLL, RK1808_PLL_CON(8),
82 		     RK1808_MODE_CON, 2, 10, 0, NULL),
83 	[CPLL] = PLL(pll_rk3036, PLL_CPLL, RK1808_PLL_CON(16),
84 		    RK1808_MODE_CON, 4, 10, 0, rk1808_pll_rates),
85 	[GPLL] = PLL(pll_rk3036, PLL_GPLL, RK1808_PLL_CON(24),
86 		     RK1808_MODE_CON, 6, 10, 0, rk1808_pll_rates),
87 	[NPLL] = PLL(pll_rk3036, PLL_NPLL, RK1808_PLL_CON(24),
88 		     RK1808_MODE_CON, 8, 10, 0, rk1808_pll_rates),
89 	[PPLL] = PLL(pll_rk3036, PLL_PPLL, RK1808_PMU_PLL_CON(0),
90 		     RK1808_PMU_MODE_CON, 0, 10, 0, rk1808_pll_rates),
91 };
92 
93 #ifndef CONFIG_SPL_BUILD
94 static ulong rk1808_i2c_get_clk(struct rk1808_clk_priv *priv, ulong clk_id)
95 {
96 	struct rk1808_cru *cru = priv->cru;
97 	u32 div, con;
98 
99 	switch (clk_id) {
100 	case SCLK_PMU_I2C0:
101 		con = readl(&cru->pmu_clksel_con[7]);
102 		div = (con & CLK_I2C0_DIV_CON_MASK) >> CLK_I2C0_DIV_CON_SHIFT;
103 		break;
104 	case SCLK_I2C1:
105 		con = readl(&cru->clksel_con[59]);
106 		div = (con & CLK_I2C1_DIV_CON_MASK)  >> CLK_I2C1_DIV_CON_SHIFT;
107 		break;
108 	case SCLK_I2C2:
109 		con = readl(&cru->clksel_con[59]);
110 		div = (con & CLK_I2C2_DIV_CON_MASK) >> CLK_I2C2_DIV_CON_SHIFT;
111 		break;
112 	case SCLK_I2C3:
113 		con = readl(&cru->clksel_con[60]);
114 		div = (con & CLK_I2C3_DIV_CON_MASK) >> CLK_I2C3_DIV_CON_SHIFT;
115 		break;
116 	case SCLK_I2C4:
117 		con = readl(&cru->clksel_con[71]);
118 		div = (con & CLK_I2C4_DIV_CON_MASK) >> CLK_I2C4_DIV_CON_SHIFT;
119 		break;
120 	case SCLK_I2C5:
121 		con = readl(&cru->clksel_con[71]);
122 		div = (con & CLK_I2C5_DIV_CON_MASK) >> CLK_I2C5_DIV_CON_SHIFT;
123 		break;
124 	default:
125 		printf("do not support this i2c bus\n");
126 		return -EINVAL;
127 	}
128 
129 	return DIV_TO_RATE(priv->gpll_hz, div);
130 }
131 
132 static ulong rk1808_i2c_set_clk(struct rk1808_clk_priv *priv,
133 				ulong clk_id, uint hz)
134 {
135 	struct rk1808_cru *cru = priv->cru;
136 	int src_clk_div;
137 
138 	src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
139 	assert(src_clk_div - 1 < 127);
140 
141 	switch (clk_id) {
142 	case SCLK_PMU_I2C0:
143 		rk_clrsetreg(&cru->pmu_clksel_con[7],
144 			     CLK_I2C0_DIV_CON_MASK | CLK_I2C0_PLL_SEL_MASK,
145 			     (src_clk_div - 1) << CLK_I2C0_DIV_CON_SHIFT |
146 			     CLK_I2C0_PLL_SEL_PPLL << CLK_I2C0_PLL_SEL_SHIFT);
147 		break;
148 	case SCLK_I2C1:
149 		rk_clrsetreg(&cru->clksel_con[59],
150 			     CLK_I2C1_DIV_CON_MASK | CLK_I2C1_PLL_SEL_MASK,
151 			     (src_clk_div - 1) << CLK_I2C1_DIV_CON_SHIFT |
152 			     CLK_I2C_PLL_SEL_GPLL << CLK_I2C1_PLL_SEL_SHIFT);
153 		break;
154 	case SCLK_I2C2:
155 		rk_clrsetreg(&cru->clksel_con[59],
156 			     CLK_I2C2_DIV_CON_MASK | CLK_I2C2_PLL_SEL_MASK,
157 			     (src_clk_div - 1) << CLK_I2C2_DIV_CON_SHIFT |
158 			     CLK_I2C_PLL_SEL_GPLL << CLK_I2C2_PLL_SEL_SHIFT);
159 		break;
160 	case SCLK_I2C3:
161 		rk_clrsetreg(&cru->clksel_con[60],
162 			     CLK_I2C3_DIV_CON_MASK | CLK_I2C3_PLL_SEL_MASK,
163 			     (src_clk_div - 1) << CLK_I2C3_DIV_CON_SHIFT |
164 			     CLK_I2C_PLL_SEL_GPLL << CLK_I2C3_PLL_SEL_SHIFT);
165 		break;
166 	case SCLK_I2C4:
167 		rk_clrsetreg(&cru->clksel_con[71],
168 			     CLK_I2C4_DIV_CON_MASK | CLK_I2C4_PLL_SEL_MASK,
169 			     (src_clk_div - 1) << CLK_I2C4_DIV_CON_SHIFT |
170 			     CLK_I2C_PLL_SEL_GPLL << CLK_I2C4_PLL_SEL_SHIFT);
171 		break;
172 	case SCLK_I2C5:
173 		rk_clrsetreg(&cru->clksel_con[71],
174 			     CLK_I2C5_DIV_CON_MASK | CLK_I2C5_PLL_SEL_MASK,
175 			     (src_clk_div - 1) << CLK_I2C5_DIV_CON_SHIFT |
176 			     CLK_I2C_PLL_SEL_GPLL << CLK_I2C5_PLL_SEL_SHIFT);
177 		break;
178 	default:
179 		printf("do not support this i2c bus\n");
180 		return -EINVAL;
181 	}
182 
183 	return rk1808_i2c_get_clk(priv, clk_id);
184 }
185 #endif
186 
187 static ulong rk1808_mmc_get_clk(struct rk1808_clk_priv *priv, uint clk_id)
188 {
189 	struct rk1808_cru *cru = priv->cru;
190 	u32 div, con, con_id;
191 
192 	switch (clk_id) {
193 	case HCLK_SDMMC:
194 	case SCLK_SDMMC:
195 		con_id = 20;
196 		break;
197 	case HCLK_SDIO:
198 	case SCLK_SDIO:
199 		con_id = 22;
200 		break;
201 	case HCLK_EMMC:
202 	case SCLK_EMMC:
203 	case SCLK_EMMC_SAMPLE:
204 		con_id = 24;
205 		break;
206 	default:
207 		return -EINVAL;
208 	}
209 
210 	con = readl(&cru->clksel_con[con_id]);
211 	div = (con & EMMC_DIV_MASK) >> EMMC_DIV_SHIFT;
212 
213 	if ((con & EMMC_PLL_MASK) >> EMMC_PLL_SHIFT
214 	    == EMMC_SEL_24M)
215 		return DIV_TO_RATE(OSC_HZ, div) / 2;
216 	else
217 		return DIV_TO_RATE(priv->gpll_hz, div) / 2;
218 }
219 
220 static ulong rk1808_mmc_set_clk(struct rk1808_clk_priv *priv,
221 				ulong clk_id, ulong set_rate)
222 {
223 	struct rk1808_cru *cru = priv->cru;
224 	int src_clk_div;
225 	u32 con_id;
226 
227 	switch (clk_id) {
228 	case HCLK_SDMMC:
229 	case SCLK_SDMMC:
230 		con_id = 20;
231 		break;
232 	case HCLK_SDIO:
233 	case SCLK_SDIO:
234 		con_id = 22;
235 		break;
236 	case HCLK_EMMC:
237 	case SCLK_EMMC:
238 		con_id = 24;
239 		break;
240 	default:
241 		return -EINVAL;
242 	}
243 
244 	/* Select clk_sdmmc/emmc source from GPLL by default */
245 	/* mmc clock defaulg div 2 internal, need provide double in cru */
246 	src_clk_div = DIV_ROUND_UP(priv->gpll_hz / 2, set_rate);
247 
248 	if (src_clk_div > 127) {
249 		/* use 24MHz source for 400KHz clock */
250 		src_clk_div = DIV_ROUND_UP(OSC_HZ / 2, set_rate);
251 		rk_clrsetreg(&cru->clksel_con[con_id],
252 			     EMMC_PLL_MASK | EMMC_DIV_MASK,
253 			     EMMC_SEL_24M << EMMC_PLL_SHIFT |
254 			     (src_clk_div - 1) << EMMC_DIV_SHIFT);
255 	} else {
256 		rk_clrsetreg(&cru->clksel_con[con_id],
257 			     EMMC_PLL_MASK | EMMC_DIV_MASK,
258 			     EMMC_SEL_GPLL << EMMC_PLL_SHIFT |
259 			     (src_clk_div - 1) << EMMC_DIV_SHIFT);
260 	}
261 	rk_clrsetreg(&cru->clksel_con[con_id + 1], EMMC_CLK_SEL_MASK,
262 		     EMMC_CLK_SEL_EMMC);
263 
264 	return rk1808_mmc_get_clk(priv, clk_id);
265 }
266 
267 #ifndef CONFIG_SPL_BUILD
268 static ulong rk1808_pwm_get_clk(struct rk1808_clk_priv *priv, ulong clk_id)
269 {
270 	struct rk1808_cru *cru = priv->cru;
271 	u32 div, con;
272 
273 	switch (clk_id) {
274 	case SCLK_PWM0:
275 		con = readl(&cru->clksel_con[69]);
276 		div = (con & CLK_PWM0_DIV_CON_MASK) >> CLK_PWM0_DIV_CON_SHIFT;
277 		break;
278 	case SCLK_PWM1:
279 		con = readl(&cru->clksel_con[69]);
280 		div = (con & CLK_PWM1_DIV_CON_MASK) >> CLK_PWM1_DIV_CON_SHIFT;
281 		break;
282 	case SCLK_PWM2:
283 		con = readl(&cru->clksel_con[70]);
284 		div = (con & CLK_PWM2_DIV_CON_MASK) >> CLK_PWM2_DIV_CON_SHIFT;
285 		break;
286 	default:
287 		printf("do not support this pwm bus\n");
288 		return -EINVAL;
289 	}
290 
291 	return DIV_TO_RATE(priv->gpll_hz, div);
292 }
293 
294 static ulong rk1808_pwm_set_clk(struct rk1808_clk_priv *priv,
295 				ulong clk_id, uint hz)
296 {
297 	struct rk1808_cru *cru = priv->cru;
298 	int src_clk_div;
299 
300 	src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
301 	assert(src_clk_div - 1 < 127);
302 
303 	switch (clk_id) {
304 	case SCLK_PWM0:
305 		rk_clrsetreg(&cru->clksel_con[69],
306 			     CLK_PWM0_DIV_CON_MASK | CLK_PWM0_PLL_SEL_MASK,
307 			     (src_clk_div - 1) << CLK_PWM0_DIV_CON_SHIFT |
308 			     CLK_PWM_PLL_SEL_GPLL << CLK_PWM0_PLL_SEL_SHIFT);
309 		break;
310 	case SCLK_PWM1:
311 		rk_clrsetreg(&cru->clksel_con[69],
312 			     CLK_PWM1_DIV_CON_MASK | CLK_PWM1_PLL_SEL_MASK,
313 			     (src_clk_div - 1) << CLK_PWM1_DIV_CON_SHIFT |
314 			     CLK_PWM_PLL_SEL_GPLL << CLK_PWM1_PLL_SEL_SHIFT);
315 		break;
316 	case SCLK_PWM2:
317 		rk_clrsetreg(&cru->clksel_con[70],
318 			     CLK_PWM2_DIV_CON_MASK | CLK_PWM2_PLL_SEL_MASK,
319 			     (src_clk_div - 1) << CLK_PWM2_DIV_CON_SHIFT |
320 			     CLK_PWM_PLL_SEL_GPLL << CLK_PWM2_PLL_SEL_SHIFT);
321 		break;
322 	default:
323 		printf("do not support this pwm bus\n");
324 		return -EINVAL;
325 	}
326 
327 	return rk1808_pwm_get_clk(priv, clk_id);
328 }
329 
330 static ulong rk1808_saradc_get_clk(struct rk1808_clk_priv *priv)
331 {
332 	struct rk1808_cru *cru = priv->cru;
333 	u32 div, con;
334 
335 	con = readl(&cru->clksel_con[63]);
336 	div = con & CLK_SARADC_DIV_CON_MASK;
337 
338 	return DIV_TO_RATE(OSC_HZ, div);
339 }
340 
341 static ulong rk1808_saradc_set_clk(struct rk1808_clk_priv *priv, uint hz)
342 {
343 	struct rk1808_cru *cru = priv->cru;
344 	int src_clk_div;
345 
346 	src_clk_div = DIV_ROUND_UP(OSC_HZ, hz);
347 	assert(src_clk_div - 1 < 2047);
348 
349 	rk_clrsetreg(&cru->clksel_con[63],
350 		     CLK_SARADC_DIV_CON_MASK,
351 		     (src_clk_div - 1) << CLK_SARADC_DIV_CON_SHIFT);
352 
353 	return rk1808_saradc_get_clk(priv);
354 }
355 
356 static ulong rk1808_spi_get_clk(struct rk1808_clk_priv *priv, ulong clk_id)
357 {
358 	struct rk1808_cru *cru = priv->cru;
359 	u32 div, con;
360 
361 	switch (clk_id) {
362 	case SCLK_SPI0:
363 		con = readl(&cru->clksel_con[60]);
364 		div = (con & CLK_SPI0_DIV_CON_MASK) >> CLK_SPI0_DIV_CON_SHIFT;
365 		break;
366 	case SCLK_SPI1:
367 		con = readl(&cru->clksel_con[61]);
368 		div = (con & CLK_SPI1_DIV_CON_MASK) >> CLK_SPI1_DIV_CON_SHIFT;
369 		break;
370 	case SCLK_SPI2:
371 		con = readl(&cru->clksel_con[61]);
372 		div = (con & CLK_SPI2_DIV_CON_MASK) >> CLK_SPI2_DIV_CON_SHIFT;
373 		break;
374 	default:
375 		printf("do not support this pwm bus\n");
376 		return -EINVAL;
377 	}
378 
379 	return DIV_TO_RATE(priv->gpll_hz, div);
380 }
381 
382 static ulong rk1808_spi_set_clk(struct rk1808_clk_priv *priv,
383 				ulong clk_id, uint hz)
384 {
385 	struct rk1808_cru *cru = priv->cru;
386 	int src_clk_div;
387 
388 	src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
389 	assert(src_clk_div - 1 < 127);
390 
391 	switch (clk_id) {
392 	case SCLK_SPI0:
393 		rk_clrsetreg(&cru->clksel_con[60],
394 			     CLK_SPI0_DIV_CON_MASK | CLK_SPI0_PLL_SEL_MASK,
395 			     (src_clk_div - 1) << CLK_SPI0_DIV_CON_SHIFT |
396 			     CLK_SPI_PLL_SEL_GPLL << CLK_SPI0_PLL_SEL_SHIFT);
397 		break;
398 	case SCLK_SPI1:
399 		rk_clrsetreg(&cru->clksel_con[61],
400 			     CLK_SPI1_DIV_CON_MASK | CLK_SPI1_PLL_SEL_MASK,
401 			     (src_clk_div - 1) << CLK_SPI1_DIV_CON_SHIFT |
402 			     CLK_SPI_PLL_SEL_GPLL << CLK_SPI1_PLL_SEL_SHIFT);
403 		break;
404 	case SCLK_SPI2:
405 		rk_clrsetreg(&cru->clksel_con[61],
406 			     CLK_SPI2_DIV_CON_MASK | CLK_SPI2_PLL_SEL_MASK,
407 			     (src_clk_div - 1) << CLK_SPI2_DIV_CON_SHIFT |
408 			     CLK_SPI_PLL_SEL_GPLL << CLK_SPI2_PLL_SEL_SHIFT);
409 		break;
410 	default:
411 		printf("do not support this pwm bus\n");
412 		return -EINVAL;
413 	}
414 
415 	return rk1808_spi_get_clk(priv, clk_id);
416 }
417 
418 #define RK1808_VOP_PLL_LIMIT_FREQ		600 * 1000000
419 static ulong rk1808_vop_get_clk(struct rk1808_clk_priv *priv, ulong clk_id)
420 {
421 	struct rk1808_cru *cru = priv->cru;
422 	u32 div, con, parent;
423 
424 	switch (clk_id) {
425 	case ACLK_VOPRAW:
426 	case ACLK_VOPLITE:
427 		con = readl(&cru->clksel_con[4]);
428 		div = (con & ACLK_VOP_DIV_CON_MASK) >> ACLK_VOP_DIV_CON_SHIFT;
429 		parent = priv->gpll_hz;
430 		break;
431 	case HCLK_VOPRAW:
432 	case HCLK_VOPLITE:
433 		parent = rk1808_vop_get_clk(priv, ACLK_VOPRAW);
434 		con = readl(&cru->clksel_con[4]);
435 		div = (con & HCLK_VOP_DIV_CON_MASK) >> HCLK_VOP_DIV_CON_SHIFT;
436 		break;
437 	case DCLK_VOPRAW:
438 		con = readl(&cru->clksel_con[5]);
439 		div = con & DCLK_VOPRAW_DIV_CON_MASK;
440 		parent = rockchip_pll_get_rate(&rk1808_pll_clks[NPLL],
441 					       priv->cru, NPLL);
442 		break;
443 	case DCLK_VOPLITE:
444 		con = readl(&cru->clksel_con[7]);
445 		div = con & DCLK_VOPLITE_DIV_CON_MASK;
446 		parent = (con & DCLK_VOPLITE_PLL_SEL_MASK) >>
447 			 DCLK_VOPLITE_PLL_SEL_SHIFT;
448 		if (parent == DCLK_VOPLITE_PLL_SEL_NPLL)
449 			parent = rockchip_pll_get_rate(&rk1808_pll_clks[NPLL],
450 						       priv->cru, NPLL);
451 		else if (parent == DCLK_VOPLITE_PLL_SEL_CPLL)
452 			parent = priv->cpll_hz;
453 		else
454 			parent = priv->gpll_hz;
455 		break;
456 	default:
457 		return -ENOENT;
458 	}
459 
460 	return DIV_TO_RATE(parent, div);
461 }
462 
463 static ulong rk1808_vop_set_clk(struct rk1808_clk_priv *priv,
464 				ulong clk_id, uint hz)
465 {
466 	struct rk1808_cru *cru = priv->cru;
467 	int src_clk_div, parent;
468 
469 	src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
470 	assert(src_clk_div - 1 < 31);
471 
472 	switch (clk_id) {
473 	case ACLK_VOPRAW:
474 	case ACLK_VOPLITE:
475 		rk_clrsetreg(&cru->clksel_con[4],
476 			     ACLK_VOP_PLL_SEL_MASK | ACLK_VOP_DIV_CON_MASK,
477 			     ACLK_VOP_PLL_SEL_GPLL << ACLK_VOP_PLL_SEL_SHIFT |
478 			     (src_clk_div - 1) << ACLK_VOP_DIV_CON_SHIFT);
479 		break;
480 	case HCLK_VOPRAW:
481 	case HCLK_VOPLITE:
482 		src_clk_div =
483 			DIV_ROUND_UP(rk1808_vop_get_clk(priv, ACLK_VOPRAW), hz);
484 		assert(src_clk_div - 1 < 15);
485 		rk_clrsetreg(&cru->clksel_con[4],
486 			     HCLK_VOP_DIV_CON_MASK,
487 			     (src_clk_div - 1) << HCLK_VOP_DIV_CON_SHIFT);
488 		break;
489 	case DCLK_VOPRAW:
490 		/*
491 		 * vopb dclk source from npll, and equals to
492 		 */
493 		src_clk_div = DIV_ROUND_UP(RK1808_VOP_PLL_LIMIT_FREQ, hz);
494 		rockchip_pll_set_rate(&rk1808_pll_clks[NPLL],
495 				      priv->cru, NPLL, src_clk_div * hz);
496 		rk_clrsetreg(&cru->clksel_con[5],
497 			     DCLK_VOPRAW_SEL_MASK |
498 			     DCLK_VOPRAW_PLL_SEL_MASK |
499 			     DCLK_VOPRAW_DIV_CON_MASK,
500 			     DCLK_VOPRAW_SEL_VOPRAW <<
501 			     DCLK_VOPRAW_SEL_SHIFT |
502 			     DCLK_VOPRAW_PLL_SEL_NPLL <<
503 			     DCLK_VOPRAW_PLL_SEL_SHIFT |
504 			     (src_clk_div - 1) << DCLK_VOPRAW_DIV_CON_SHIFT);
505 		break;
506 	case DCLK_VOPLITE:
507 		/*
508 		 * vopl dclk source from cpll, and equals to
509 		 */
510 		if (!(priv->npll_hz % hz)) {
511 			parent = DCLK_VOPLITE_PLL_SEL_NPLL;
512 			src_clk_div = do_div(priv->npll_hz, hz);
513 		} else if (!(priv->cpll_hz % hz)) {
514 			parent = DCLK_VOPLITE_PLL_SEL_CPLL;
515 			src_clk_div = do_div(priv->cpll_hz, hz);
516 		} else {
517 			parent = DCLK_VOPLITE_PLL_SEL_GPLL;
518 			src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
519 		}
520 		rk_clrsetreg(&cru->clksel_con[7],
521 			     DCLK_VOPLITE_SEL_MASK | DCLK_VOPLITE_PLL_SEL_MASK |
522 			     DCLK_VOPLITE_DIV_CON_MASK,
523 			     DCLK_VOPLITE_SEL_VOPRAW << DCLK_VOPLITE_SEL_SHIFT |
524 			     parent << DCLK_VOPLITE_PLL_SEL_SHIFT |
525 			     (src_clk_div - 1) << DCLK_VOPLITE_DIV_CON_SHIFT);
526 		break;
527 	default:
528 		printf("do not support this vop freq\n");
529 		return -EINVAL;
530 	}
531 
532 	return rk1808_vop_get_clk(priv, clk_id);
533 }
534 #endif
535 
536 static ulong rk1808_bus_get_clk(struct rk1808_clk_priv *priv, ulong clk_id)
537 {
538 	struct rk1808_cru *cru = priv->cru;
539 	u32 div, con, parent;
540 
541 	switch (clk_id) {
542 	case HSCLK_BUS_PRE:
543 		con = readl(&cru->clksel_con[27]);
544 		div = (con & HSCLK_BUS_DIV_CON_MASK) >> HSCLK_BUS_DIV_CON_SHIFT;
545 		parent = priv->gpll_hz;
546 		break;
547 	case MSCLK_BUS_PRE:
548 		con = readl(&cru->clksel_con[28]);
549 		div = (con & MSCLK_BUS_DIV_CON_MASK) >> MSCLK_BUS_DIV_CON_SHIFT;
550 		parent = priv->gpll_hz;
551 		break;
552 	case LSCLK_BUS_PRE:
553 		con = readl(&cru->clksel_con[28]);
554 		div = (con & LSCLK_BUS_DIV_CON_MASK) >> LSCLK_BUS_DIV_CON_SHIFT;
555 		parent = priv->gpll_hz;
556 		break;
557 	default:
558 		return -ENOENT;
559 	}
560 
561 	return DIV_TO_RATE(parent, div);
562 }
563 
564 static ulong rk1808_bus_set_clk(struct rk1808_clk_priv *priv,
565 				ulong clk_id, ulong hz)
566 {
567 	struct rk1808_cru *cru = priv->cru;
568 	int src_clk_div;
569 
570 	/*
571 	 * select gpll as pd_bus bus clock source and
572 	 * set up dependent divisors for PCLK/HCLK and ACLK clocks.
573 	 */
574 	switch (clk_id) {
575 	case HSCLK_BUS_PRE:
576 		src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
577 		assert(src_clk_div - 1 < 31);
578 		rk_clrsetreg(&cru->clksel_con[27],
579 			     CLK_BUS_PLL_SEL_MASK | HSCLK_BUS_DIV_CON_MASK,
580 			     CLK_BUS_PLL_SEL_GPLL << CLK_BUS_PLL_SEL_SHIFT |
581 			     (src_clk_div - 1) << HSCLK_BUS_DIV_CON_SHIFT);
582 		break;
583 	case MSCLK_BUS_PRE:
584 		src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
585 		assert(src_clk_div - 1 < 31);
586 		rk_clrsetreg(&cru->clksel_con[28],
587 			     CLK_BUS_PLL_SEL_MASK | MSCLK_BUS_DIV_CON_MASK,
588 			     CLK_BUS_PLL_SEL_GPLL << CLK_BUS_PLL_SEL_SHIFT |
589 			     (src_clk_div - 1) << MSCLK_BUS_DIV_CON_SHIFT);
590 		break;
591 	case LSCLK_BUS_PRE:
592 		src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
593 		assert(src_clk_div - 1 < 31);
594 		rk_clrsetreg(&cru->clksel_con[28],
595 			     CLK_BUS_PLL_SEL_MASK | LSCLK_BUS_DIV_CON_MASK,
596 			     CLK_BUS_PLL_SEL_GPLL << CLK_BUS_PLL_SEL_SHIFT |
597 			     (src_clk_div - 1) << LSCLK_BUS_DIV_CON_SHIFT);
598 		break;
599 	default:
600 		printf("do not support this bus freq\n");
601 		return -EINVAL;
602 	}
603 
604 	return rk1808_bus_get_clk(priv, clk_id);
605 }
606 
607 static ulong rk1808_peri_get_clk(struct rk1808_clk_priv *priv, ulong clk_id)
608 {
609 	struct rk1808_cru *cru = priv->cru;
610 	u32 div, con, parent;
611 
612 	switch (clk_id) {
613 	case MSCLK_PERI:
614 		con = readl(&cru->clksel_con[19]);
615 		div = (con & MSCLK_PERI_DIV_CON_MASK) >>
616 		      MSCLK_PERI_DIV_CON_SHIFT;
617 		parent = priv->gpll_hz;
618 		break;
619 	case LSCLK_PERI:
620 		con = readl(&cru->clksel_con[19]);
621 		div = (con & LSCLK_PERI_DIV_CON_MASK) >>
622 		      LSCLK_PERI_DIV_CON_SHIFT;
623 		parent = priv->gpll_hz;
624 		break;
625 	default:
626 		return -ENOENT;
627 	}
628 
629 	return DIV_TO_RATE(parent, div);
630 }
631 
632 static ulong rk1808_peri_set_clk(struct rk1808_clk_priv *priv,
633 				 ulong clk_id, ulong hz)
634 {
635 	struct rk1808_cru *cru = priv->cru;
636 	int src_clk_div;
637 
638 	src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
639 	assert(src_clk_div - 1 < 31);
640 
641 	/*
642 	 * select gpll as pd_peri bus clock source and
643 	 * set up dependent divisors for HCLK and ACLK clocks.
644 	 */
645 	switch (clk_id) {
646 	case MSCLK_PERI:
647 		rk_clrsetreg(&cru->clksel_con[19],
648 			     CLK_PERI_PLL_SEL_MASK | MSCLK_PERI_DIV_CON_MASK,
649 			     CLK_PERI_PLL_SEL_GPLL << CLK_PERI_PLL_SEL_SHIFT |
650 			     (src_clk_div - 1) << MSCLK_PERI_DIV_CON_SHIFT);
651 		break;
652 	case LSCLK_PERI:
653 		rk_clrsetreg(&cru->clksel_con[19],
654 			     CLK_PERI_PLL_SEL_MASK | LSCLK_PERI_DIV_CON_MASK,
655 			     CLK_PERI_PLL_SEL_GPLL << CLK_PERI_PLL_SEL_SHIFT |
656 			     (src_clk_div - 1) << LSCLK_PERI_DIV_CON_SHIFT);
657 		break;
658 	default:
659 		printf("do not support this peri freq\n");
660 		return -EINVAL;
661 	}
662 
663 	return rk1808_peri_get_clk(priv, clk_id);
664 }
665 
666 static ulong rk1808_armclk_set_clk(struct rk1808_clk_priv *priv, ulong hz)
667 {
668 	struct rk1808_cru *cru = priv->cru;
669 	const struct rockchip_cpu_rate_table *rate;
670 	ulong old_rate;
671 
672 	rate = rockchip_get_cpu_settings(rk1808_cpu_rates, hz);
673 	if (!rate) {
674 		printf("%s unsupported rate\n", __func__);
675 		return -EINVAL;
676 	}
677 
678 	/*
679 	 * select apll as cpu/core clock pll source and
680 	 * set up dependent divisors for PERI and ACLK clocks.
681 	 * core hz : apll = 1:1
682 	 */
683 	old_rate = rockchip_pll_get_rate(&rk1808_pll_clks[APLL],
684 					 priv->cru, APLL);
685 	if (old_rate > hz) {
686 		if (rockchip_pll_set_rate(&rk1808_pll_clks[APLL],
687 					  priv->cru, APLL, hz))
688 			return -EINVAL;
689 		rk_clrsetreg(&cru->clksel_con[0],
690 			     CORE_CLK_PLL_SEL_MASK | CORE_DIV_CON_MASK |
691 			     CORE_ACLK_DIV_MASK | CORE_DBG_DIV_MASK,
692 			     rate->aclk_div << CORE_ACLK_DIV_SHIFT |
693 			     rate->pclk_div << CORE_DBG_DIV_SHIFT |
694 			     CORE_CLK_PLL_SEL_APLL << CORE_CLK_PLL_SEL_SHIFT |
695 			     0 << CORE_DIV_CON_SHIFT);
696 	} else if (old_rate < hz) {
697 		rk_clrsetreg(&cru->clksel_con[0],
698 			     CORE_CLK_PLL_SEL_MASK | CORE_DIV_CON_MASK |
699 			     CORE_ACLK_DIV_MASK | CORE_DBG_DIV_MASK,
700 			     rate->aclk_div << CORE_ACLK_DIV_SHIFT |
701 			     rate->pclk_div << CORE_DBG_DIV_SHIFT |
702 			     CORE_CLK_PLL_SEL_APLL << CORE_CLK_PLL_SEL_SHIFT |
703 			     0 << CORE_DIV_CON_SHIFT);
704 		if (rockchip_pll_set_rate(&rk1808_pll_clks[APLL],
705 					  priv->cru, APLL, hz))
706 			return -EINVAL;
707 	}
708 
709 	return rockchip_pll_get_rate(&rk1808_pll_clks[APLL], priv->cru, APLL);
710 }
711 
712 static ulong rk1808_clk_get_rate(struct clk *clk)
713 {
714 	struct rk1808_clk_priv *priv = dev_get_priv(clk->dev);
715 	ulong rate = 0;
716 
717 	debug("%s %ld\n", __func__, clk->id);
718 	switch (clk->id) {
719 	case PLL_APLL:
720 	case PLL_DPLL:
721 	case PLL_CPLL:
722 	case PLL_GPLL:
723 	case PLL_NPLL:
724 	case PLL_PPLL:
725 		rate = rockchip_pll_get_rate(&rk1808_pll_clks[clk->id - 1],
726 					     priv->cru, clk->id - 1);
727 		break;
728 	case ARMCLK:
729 		rate = rockchip_pll_get_rate(&rk1808_pll_clks[APLL],
730 					     priv->cru, APLL);
731 		break;
732 	case HCLK_SDMMC:
733 	case HCLK_EMMC:
734 	case HCLK_SDIO:
735 	case SCLK_SDMMC:
736 	case SCLK_EMMC:
737 	case SCLK_EMMC_SAMPLE:
738 	case SCLK_SDIO:
739 		rate = rk1808_mmc_get_clk(priv, clk->id);
740 		break;
741 #ifndef CONFIG_SPL_BUILD
742 	case SCLK_PMU_I2C0:
743 	case SCLK_I2C1:
744 	case SCLK_I2C2:
745 	case SCLK_I2C3:
746 	case SCLK_I2C4:
747 	case SCLK_I2C5:
748 		rate = rk1808_i2c_get_clk(priv, clk->id);
749 		break;
750 	case SCLK_PWM0:
751 	case SCLK_PWM1:
752 	case SCLK_PWM2:
753 		rate = rk1808_pwm_get_clk(priv, clk->id);
754 		break;
755 	case SCLK_SARADC:
756 		rate = rk1808_saradc_get_clk(priv);
757 		break;
758 	case SCLK_SPI0:
759 	case SCLK_SPI1:
760 	case SCLK_SPI2:
761 		rate = rk1808_spi_get_clk(priv, clk->id);
762 		break;
763 	case ACLK_VOPRAW:
764 	case DCLK_VOPRAW:
765 	case ACLK_VOPLITE:
766 	case DCLK_VOPLITE:
767 		rate = rk1808_vop_get_clk(priv, clk->id);
768 		break;
769 #endif
770 	case HSCLK_BUS_PRE:
771 	case MSCLK_BUS_PRE:
772 	case LSCLK_BUS_PRE:
773 		rate = rk1808_bus_get_clk(priv, clk->id);
774 		break;
775 	case MSCLK_PERI:
776 	case LSCLK_PERI:
777 		rate = rk1808_peri_get_clk(priv, clk->id);
778 		break;
779 	default:
780 		return -ENOENT;
781 	}
782 
783 	return rate;
784 }
785 
786 static ulong rk1808_clk_set_rate(struct clk *clk, ulong rate)
787 {
788 	struct rk1808_clk_priv *priv = dev_get_priv(clk->dev);
789 	ulong ret = 0;
790 
791 	debug("%s %ld %ld\n", __func__, clk->id, rate);
792 	switch (clk->id) {
793 	case PLL_APLL:
794 	case PLL_DPLL:
795 	case PLL_PPLL:
796 		ret = rockchip_pll_set_rate(&rk1808_pll_clks[clk->id - 1],
797 					    priv->cru, clk->id - 1, rate);
798 		break;
799 	case PLL_CPLL:
800 		ret = rockchip_pll_set_rate(&rk1808_pll_clks[CPLL],
801 					    priv->cru, CPLL, rate);
802 		if (ret == 0)
803 			priv->cpll_hz = rate;
804 		break;
805 	case PLL_GPLL:
806 		ret = rockchip_pll_set_rate(&rk1808_pll_clks[GPLL],
807 					    priv->cru, GPLL, rate);
808 		if (ret == 0)
809 			priv->gpll_hz = rate;
810 		break;
811 	case PLL_NPLL:
812 		ret = rockchip_pll_set_rate(&rk1808_pll_clks[NPLL],
813 					    priv->cru, NPLL, rate);
814 		if (ret == 0)
815 			priv->npll_hz = rate;
816 		break;
817 	case ARMCLK:
818 		if (priv->armclk_hz)
819 			rk1808_armclk_set_clk(priv, rate);
820 		priv->armclk_hz = rate;
821 		break;
822 	case HCLK_SDMMC:
823 	case HCLK_EMMC:
824 	case HCLK_SDIO:
825 	case SCLK_SDMMC:
826 	case SCLK_EMMC:
827 	case SCLK_SDIO:
828 		ret = rk1808_mmc_set_clk(priv, clk->id, rate);
829 		break;
830 #ifndef CONFIG_SPL_BUILD
831 	case SCLK_PMU_I2C0:
832 	case SCLK_I2C1:
833 	case SCLK_I2C2:
834 	case SCLK_I2C3:
835 	case SCLK_I2C4:
836 	case SCLK_I2C5:
837 		ret = rk1808_i2c_set_clk(priv, clk->id, rate);
838 		break;
839 	case SCLK_PWM0:
840 	case SCLK_PWM1:
841 	case SCLK_PWM2:
842 		ret = rk1808_pwm_set_clk(priv, clk->id, rate);
843 		break;
844 	case SCLK_SARADC:
845 		ret = rk1808_saradc_set_clk(priv, rate);
846 		break;
847 	case SCLK_SPI0:
848 	case SCLK_SPI1:
849 	case SCLK_SPI2:
850 		ret = rk1808_spi_set_clk(priv, clk->id, rate);
851 		break;
852 	case ACLK_VOPRAW:
853 	case DCLK_VOPRAW:
854 	case ACLK_VOPLITE:
855 	case DCLK_VOPLITE:
856 		ret = rk1808_vop_set_clk(priv, clk->id, rate);
857 		break;
858 #endif
859 	case HSCLK_BUS_PRE:
860 	case MSCLK_BUS_PRE:
861 	case LSCLK_BUS_PRE:
862 		ret = rk1808_bus_set_clk(priv, clk->id, rate);
863 		break;
864 	case MSCLK_PERI:
865 	case LSCLK_PERI:
866 		ret = rk1808_peri_set_clk(priv, clk->id, rate);
867 		break;
868 	default:
869 		return -ENOENT;
870 	}
871 
872 	return ret;
873 }
874 
875 #define ROCKCHIP_MMC_DELAY_SEL		BIT(10)
876 #define ROCKCHIP_MMC_DEGREE_MASK	0x3
877 #define ROCKCHIP_MMC_DELAYNUM_OFFSET	2
878 #define ROCKCHIP_MMC_DELAYNUM_MASK	(0xff << ROCKCHIP_MMC_DELAYNUM_OFFSET)
879 
880 #define PSECS_PER_SEC 1000000000000LL
881 /*
882  * Each fine delay is between 44ps-77ps. Assume each fine delay is 60ps to
883  * simplify calculations. So 45degs could be anywhere between 33deg and 57.8deg.
884  */
885 #define ROCKCHIP_MMC_DELAY_ELEMENT_PSEC 60
886 
887 int rk1808_mmc_get_phase(struct clk *clk)
888 {
889 	struct rk1808_clk_priv *priv = dev_get_priv(clk->dev);
890 	struct rk1808_cru *cru = priv->cru;
891 	u32 raw_value, delay_num;
892 	u16 degrees = 0;
893 	ulong rate;
894 
895 	rate = rk1808_clk_get_rate(clk);
896 
897 	if (rate < 0)
898 		return rate;
899 
900 	if (clk->id == SCLK_EMMC_SAMPLE)
901 		raw_value = readl(&cru->emmc_con[1]);
902 	else if (clk->id == SCLK_SDMMC_SAMPLE)
903 		raw_value = readl(&cru->sdmmc_con[1]);
904 	else
905 		raw_value = readl(&cru->sdio_con[1]);
906 
907 	raw_value >>= 1;
908 	degrees = (raw_value & ROCKCHIP_MMC_DEGREE_MASK) * 90;
909 
910 	if (raw_value & ROCKCHIP_MMC_DELAY_SEL) {
911 		/* degrees/delaynum * 10000 */
912 		unsigned long factor = (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10) *
913 					36 * (rate / 1000000);
914 
915 		delay_num = (raw_value & ROCKCHIP_MMC_DELAYNUM_MASK);
916 		delay_num >>= ROCKCHIP_MMC_DELAYNUM_OFFSET;
917 		degrees += DIV_ROUND_CLOSEST(delay_num * factor, 10000);
918 	}
919 
920 	return degrees % 360;
921 }
922 
923 int rk1808_mmc_set_phase(struct clk *clk, u32 degrees)
924 {
925 	struct rk1808_clk_priv *priv = dev_get_priv(clk->dev);
926 	struct rk1808_cru *cru = priv->cru;
927 	u8 nineties, remainder, delay_num;
928 	u32 raw_value, delay;
929 	ulong rate;
930 
931 	rate = rk1808_clk_get_rate(clk);
932 
933 	if (rate < 0)
934 		return rate;
935 
936 	nineties = degrees / 90;
937 	remainder = (degrees % 90);
938 
939 	/*
940 	 * Convert to delay; do a little extra work to make sure we
941 	 * don't overflow 32-bit / 64-bit numbers.
942 	 */
943 	delay = 10000000; /* PSECS_PER_SEC / 10000 / 10 */
944 	delay *= remainder;
945 	delay = DIV_ROUND_CLOSEST(delay, (rate / 1000) * 36 *
946 				(ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10));
947 
948 	delay_num = (u8)min_t(u32, delay, 255);
949 
950 	raw_value = delay_num ? ROCKCHIP_MMC_DELAY_SEL : 0;
951 	raw_value |= delay_num << ROCKCHIP_MMC_DELAYNUM_OFFSET;
952 	raw_value |= nineties;
953 
954 	raw_value <<= 1;
955 	if (clk->id == SCLK_EMMC_SAMPLE)
956 		writel(raw_value | 0xffff0000, &cru->emmc_con[1]);
957 	else if (clk->id == SCLK_SDMMC_SAMPLE)
958 		writel(raw_value | 0xffff0000, &cru->sdmmc_con[1]);
959 	else
960 		writel(raw_value | 0xffff0000, &cru->sdio_con[1]);
961 
962 	debug("mmc set_phase(%d) delay_nums=%u reg=%#x actual_degrees=%d\n",
963 	      degrees, delay_num, raw_value, rk1808_mmc_get_phase(clk));
964 
965 	return 0;
966 }
967 
968 static int rk1808_clk_get_phase(struct clk *clk)
969 {
970 	int ret;
971 
972 	debug("%s %ld\n", __func__, clk->id);
973 	switch (clk->id) {
974 	case SCLK_EMMC_SAMPLE:
975 	case SCLK_SDMMC_SAMPLE:
976 	case SCLK_SDIO_SAMPLE:
977 		ret = rk1808_mmc_get_phase(clk);
978 		break;
979 	default:
980 		return -ENOENT;
981 	}
982 
983 	return ret;
984 }
985 
986 static int rk1808_clk_set_phase(struct clk *clk, int degrees)
987 {
988 	int ret;
989 
990 	debug("%s %ld\n", __func__, clk->id);
991 	switch (clk->id) {
992 	case SCLK_EMMC_SAMPLE:
993 	case SCLK_SDMMC_SAMPLE:
994 	case SCLK_SDIO_SAMPLE:
995 		ret = rk1808_mmc_set_phase(clk, degrees);
996 		break;
997 	default:
998 		return -ENOENT;
999 	}
1000 
1001 	return ret;
1002 }
1003 
1004 static struct clk_ops rk1808_clk_ops = {
1005 	.get_rate = rk1808_clk_get_rate,
1006 	.set_rate = rk1808_clk_set_rate,
1007 	.get_phase	= rk1808_clk_get_phase,
1008 	.set_phase	= rk1808_clk_set_phase,
1009 };
1010 
1011 static int rk1808_clk_probe(struct udevice *dev)
1012 {
1013 	struct rk1808_clk_priv *priv = dev_get_priv(dev);
1014 	int ret;
1015 
1016 	if (rockchip_pll_get_rate(&rk1808_pll_clks[APLL],
1017 				  priv->cru, APLL) != APLL_HZ) {
1018 		ret = rk1808_armclk_set_clk(priv, APLL_HZ);
1019 		if (ret < 0)
1020 			printf("%s failed to set armclk rate\n", __func__);
1021 	}
1022 
1023 	priv->cpll_hz = rockchip_pll_get_rate(&rk1808_pll_clks[CPLL],
1024 					      priv->cru, CPLL);
1025 	priv->gpll_hz = rockchip_pll_get_rate(&rk1808_pll_clks[GPLL],
1026 					      priv->cru, GPLL);
1027 
1028 	/* Process 'assigned-{clocks/clock-parents/clock-rates}' properties */
1029 	ret = clk_set_defaults(dev);
1030 	if (ret)
1031 		debug("%s clk_set_defaults failed %d\n", __func__, ret);
1032 
1033 	return 0;
1034 }
1035 
1036 static int rk1808_clk_ofdata_to_platdata(struct udevice *dev)
1037 {
1038 	struct rk1808_clk_priv *priv = dev_get_priv(dev);
1039 
1040 	priv->cru = dev_read_addr_ptr(dev);
1041 
1042 	return 0;
1043 }
1044 
1045 static int rk1808_clk_bind(struct udevice *dev)
1046 {
1047 	int ret;
1048 	struct udevice *sys_child, *sf_child;
1049 	struct sysreset_reg *priv;
1050 	struct softreset_reg *sf_priv;
1051 
1052 	/* The reset driver does not have a device node, so bind it here */
1053 	ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset",
1054 				 &sys_child);
1055 	if (ret) {
1056 		debug("Warning: No sysreset driver: ret=%d\n", ret);
1057 	} else {
1058 		priv = malloc(sizeof(struct sysreset_reg));
1059 		priv->glb_srst_fst_value = offsetof(struct rk1808_cru,
1060 						    glb_srst_fst);
1061 		priv->glb_srst_snd_value = offsetof(struct rk1808_cru,
1062 						    glb_srst_snd);
1063 		sys_child->priv = priv;
1064 	}
1065 
1066 	ret = device_bind_driver_to_node(dev, "rockchip_reset", "reset",
1067 					 dev_ofnode(dev), &sf_child);
1068 	if (ret) {
1069 		debug("Warning: No rockchip reset driver: ret=%d\n", ret);
1070 	} else {
1071 		sf_priv = malloc(sizeof(struct softreset_reg));
1072 		sf_priv->sf_reset_offset = offsetof(struct rk1808_cru,
1073 						    softrst_con[0]);
1074 		sf_priv->sf_reset_num = 16;
1075 		sf_child->priv = sf_priv;
1076 	}
1077 
1078 	return 0;
1079 }
1080 
1081 static const struct udevice_id rk1808_clk_ids[] = {
1082 	{ .compatible = "rockchip,rk1808-cru" },
1083 	{ }
1084 };
1085 
1086 U_BOOT_DRIVER(rockchip_rk1808_cru) = {
1087 	.name		= "rockchip_rk1808_cru",
1088 	.id		= UCLASS_CLK,
1089 	.of_match	= rk1808_clk_ids,
1090 	.priv_auto_alloc_size = sizeof(struct rk1808_clk_priv),
1091 	.ofdata_to_platdata = rk1808_clk_ofdata_to_platdata,
1092 	.ops		= &rk1808_clk_ops,
1093 	.bind		= rk1808_clk_bind,
1094 	.probe		= rk1808_clk_probe,
1095 };
1096 
1097 #ifndef CONFIG_SPL_BUILD
1098 /**
1099  * soc_clk_dump() - Print clock frequencies
1100  * Returns zero on success
1101  *
1102  * Implementation for the clk dump command.
1103  */
1104 int soc_clk_dump(void)
1105 {
1106 	struct udevice *cru_dev;
1107 	const struct rk1808_clk_info *clk_dump;
1108 	struct clk clk;
1109 	unsigned long clk_count = ARRAY_SIZE(clks_dump);
1110 	unsigned long rate;
1111 	int i, ret;
1112 
1113 	ret = uclass_get_device_by_driver(UCLASS_CLK,
1114 					  DM_GET_DRIVER(rockchip_rk1808_cru),
1115 					  &cru_dev);
1116 	if (ret) {
1117 		printf("%s failed to get cru device\n", __func__);
1118 		return ret;
1119 	}
1120 
1121 	printf("CLK:");
1122 	for (i = 0; i < clk_count; i++) {
1123 		clk_dump = &clks_dump[i];
1124 		if (clk_dump->name) {
1125 			clk.id = clk_dump->id;
1126 			if (clk_dump->is_cru)
1127 				ret = clk_request(cru_dev, &clk);
1128 			if (ret < 0)
1129 				return ret;
1130 
1131 			rate = clk_get_rate(&clk);
1132 			clk_free(&clk);
1133 			if (i == 0) {
1134 				if (rate < 0)
1135 					printf("%s %s\n", clk_dump->name,
1136 					       "unknown");
1137 				else
1138 					printf("%s %lu KHz\n", clk_dump->name,
1139 					       rate / 1000);
1140 			} else {
1141 				if (rate < 0)
1142 					printf("%s %s\n", clk_dump->name,
1143 					       "unknown");
1144 				else
1145 					printf("%s %lu KHz\n", clk_dump->name,
1146 					       rate / 1000);
1147 			}
1148 		}
1149 	}
1150 
1151 	return 0;
1152 }
1153 #endif
1154