xref: /rk3399_rockchip-uboot/drivers/clk/rockchip/clk_rk1808.c (revision 23ba6841ccdaeb51290dc49d4e32f175bd3baa34)
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_tsadc_get_clk(struct rk1808_clk_priv *priv)
357 {
358 	struct rk1808_cru *cru = priv->cru;
359 	u32 div, con;
360 
361 	con = readl(&cru->clksel_con[62]);
362 	div = con & CLK_SARADC_DIV_CON_MASK;
363 
364 	return DIV_TO_RATE(OSC_HZ, div);
365 }
366 
367 static ulong rk1808_tsadc_set_clk(struct rk1808_clk_priv *priv, uint hz)
368 {
369 	struct rk1808_cru *cru = priv->cru;
370 	int src_clk_div;
371 
372 	src_clk_div = DIV_ROUND_UP(OSC_HZ, hz);
373 	assert(src_clk_div - 1 < 2047);
374 
375 	rk_clrsetreg(&cru->clksel_con[62],
376 		     CLK_SARADC_DIV_CON_MASK,
377 		     (src_clk_div - 1) << CLK_SARADC_DIV_CON_SHIFT);
378 
379 	return rk1808_tsadc_get_clk(priv);
380 }
381 
382 static ulong rk1808_spi_get_clk(struct rk1808_clk_priv *priv, ulong clk_id)
383 {
384 	struct rk1808_cru *cru = priv->cru;
385 	u32 div, con;
386 
387 	switch (clk_id) {
388 	case SCLK_SPI0:
389 		con = readl(&cru->clksel_con[60]);
390 		div = (con & CLK_SPI0_DIV_CON_MASK) >> CLK_SPI0_DIV_CON_SHIFT;
391 		break;
392 	case SCLK_SPI1:
393 		con = readl(&cru->clksel_con[61]);
394 		div = (con & CLK_SPI1_DIV_CON_MASK) >> CLK_SPI1_DIV_CON_SHIFT;
395 		break;
396 	case SCLK_SPI2:
397 		con = readl(&cru->clksel_con[61]);
398 		div = (con & CLK_SPI2_DIV_CON_MASK) >> CLK_SPI2_DIV_CON_SHIFT;
399 		break;
400 	default:
401 		printf("do not support this pwm bus\n");
402 		return -EINVAL;
403 	}
404 
405 	return DIV_TO_RATE(priv->gpll_hz, div);
406 }
407 
408 static ulong rk1808_spi_set_clk(struct rk1808_clk_priv *priv,
409 				ulong clk_id, uint hz)
410 {
411 	struct rk1808_cru *cru = priv->cru;
412 	int src_clk_div;
413 
414 	src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
415 	assert(src_clk_div - 1 < 127);
416 
417 	switch (clk_id) {
418 	case SCLK_SPI0:
419 		rk_clrsetreg(&cru->clksel_con[60],
420 			     CLK_SPI0_DIV_CON_MASK | CLK_SPI0_PLL_SEL_MASK,
421 			     (src_clk_div - 1) << CLK_SPI0_DIV_CON_SHIFT |
422 			     CLK_SPI_PLL_SEL_GPLL << CLK_SPI0_PLL_SEL_SHIFT);
423 		break;
424 	case SCLK_SPI1:
425 		rk_clrsetreg(&cru->clksel_con[61],
426 			     CLK_SPI1_DIV_CON_MASK | CLK_SPI1_PLL_SEL_MASK,
427 			     (src_clk_div - 1) << CLK_SPI1_DIV_CON_SHIFT |
428 			     CLK_SPI_PLL_SEL_GPLL << CLK_SPI1_PLL_SEL_SHIFT);
429 		break;
430 	case SCLK_SPI2:
431 		rk_clrsetreg(&cru->clksel_con[61],
432 			     CLK_SPI2_DIV_CON_MASK | CLK_SPI2_PLL_SEL_MASK,
433 			     (src_clk_div - 1) << CLK_SPI2_DIV_CON_SHIFT |
434 			     CLK_SPI_PLL_SEL_GPLL << CLK_SPI2_PLL_SEL_SHIFT);
435 		break;
436 	default:
437 		printf("do not support this pwm bus\n");
438 		return -EINVAL;
439 	}
440 
441 	return rk1808_spi_get_clk(priv, clk_id);
442 }
443 
444 #define RK1808_VOP_PLL_LIMIT_FREQ		600 * 1000000
445 static ulong rk1808_vop_get_clk(struct rk1808_clk_priv *priv, ulong clk_id)
446 {
447 	struct rk1808_cru *cru = priv->cru;
448 	u32 div, con, parent;
449 
450 	switch (clk_id) {
451 	case ACLK_VOPRAW:
452 	case ACLK_VOPLITE:
453 		con = readl(&cru->clksel_con[4]);
454 		div = (con & ACLK_VOP_DIV_CON_MASK) >> ACLK_VOP_DIV_CON_SHIFT;
455 		parent = priv->gpll_hz;
456 		break;
457 	case HCLK_VOPRAW:
458 	case HCLK_VOPLITE:
459 		parent = rk1808_vop_get_clk(priv, ACLK_VOPRAW);
460 		con = readl(&cru->clksel_con[4]);
461 		div = (con & HCLK_VOP_DIV_CON_MASK) >> HCLK_VOP_DIV_CON_SHIFT;
462 		break;
463 	case DCLK_VOPRAW:
464 		con = readl(&cru->clksel_con[5]);
465 		div = con & DCLK_VOPRAW_DIV_CON_MASK;
466 		parent = rockchip_pll_get_rate(&rk1808_pll_clks[NPLL],
467 					       priv->cru, NPLL);
468 		break;
469 	case DCLK_VOPLITE:
470 		con = readl(&cru->clksel_con[7]);
471 		div = con & DCLK_VOPLITE_DIV_CON_MASK;
472 		parent = (con & DCLK_VOPLITE_PLL_SEL_MASK) >>
473 			 DCLK_VOPLITE_PLL_SEL_SHIFT;
474 		if (parent == DCLK_VOPLITE_PLL_SEL_NPLL)
475 			parent = rockchip_pll_get_rate(&rk1808_pll_clks[NPLL],
476 						       priv->cru, NPLL);
477 		else if (parent == DCLK_VOPLITE_PLL_SEL_CPLL)
478 			parent = priv->cpll_hz;
479 		else
480 			parent = priv->gpll_hz;
481 		break;
482 	default:
483 		return -ENOENT;
484 	}
485 
486 	return DIV_TO_RATE(parent, div);
487 }
488 
489 static ulong rk1808_vop_set_clk(struct rk1808_clk_priv *priv,
490 				ulong clk_id, uint hz)
491 {
492 	struct rk1808_cru *cru = priv->cru;
493 	int src_clk_div, parent;
494 
495 	src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
496 	assert(src_clk_div - 1 < 31);
497 
498 	switch (clk_id) {
499 	case ACLK_VOPRAW:
500 	case ACLK_VOPLITE:
501 		rk_clrsetreg(&cru->clksel_con[4],
502 			     ACLK_VOP_PLL_SEL_MASK | ACLK_VOP_DIV_CON_MASK,
503 			     ACLK_VOP_PLL_SEL_GPLL << ACLK_VOP_PLL_SEL_SHIFT |
504 			     (src_clk_div - 1) << ACLK_VOP_DIV_CON_SHIFT);
505 		break;
506 	case HCLK_VOPRAW:
507 	case HCLK_VOPLITE:
508 		src_clk_div =
509 			DIV_ROUND_UP(rk1808_vop_get_clk(priv, ACLK_VOPRAW), hz);
510 		assert(src_clk_div - 1 < 15);
511 		rk_clrsetreg(&cru->clksel_con[4],
512 			     HCLK_VOP_DIV_CON_MASK,
513 			     (src_clk_div - 1) << HCLK_VOP_DIV_CON_SHIFT);
514 		break;
515 	case DCLK_VOPRAW:
516 		/*
517 		 * vopb dclk source from npll, and equals to
518 		 */
519 		src_clk_div = DIV_ROUND_UP(RK1808_VOP_PLL_LIMIT_FREQ, hz);
520 		rockchip_pll_set_rate(&rk1808_pll_clks[NPLL],
521 				      priv->cru, NPLL, src_clk_div * hz);
522 		rk_clrsetreg(&cru->clksel_con[5],
523 			     DCLK_VOPRAW_SEL_MASK |
524 			     DCLK_VOPRAW_PLL_SEL_MASK |
525 			     DCLK_VOPRAW_DIV_CON_MASK,
526 			     DCLK_VOPRAW_SEL_VOPRAW <<
527 			     DCLK_VOPRAW_SEL_SHIFT |
528 			     DCLK_VOPRAW_PLL_SEL_NPLL <<
529 			     DCLK_VOPRAW_PLL_SEL_SHIFT |
530 			     (src_clk_div - 1) << DCLK_VOPRAW_DIV_CON_SHIFT);
531 		break;
532 	case DCLK_VOPLITE:
533 		/*
534 		 * vopl dclk source from cpll, and equals to
535 		 */
536 		if (!(priv->npll_hz % hz)) {
537 			parent = DCLK_VOPLITE_PLL_SEL_NPLL;
538 			src_clk_div = do_div(priv->npll_hz, hz);
539 		} else if (!(priv->cpll_hz % hz)) {
540 			parent = DCLK_VOPLITE_PLL_SEL_CPLL;
541 			src_clk_div = do_div(priv->cpll_hz, hz);
542 		} else {
543 			parent = DCLK_VOPLITE_PLL_SEL_GPLL;
544 			src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
545 		}
546 		rk_clrsetreg(&cru->clksel_con[7],
547 			     DCLK_VOPLITE_SEL_MASK | DCLK_VOPLITE_PLL_SEL_MASK |
548 			     DCLK_VOPLITE_DIV_CON_MASK,
549 			     DCLK_VOPLITE_SEL_VOPRAW << DCLK_VOPLITE_SEL_SHIFT |
550 			     parent << DCLK_VOPLITE_PLL_SEL_SHIFT |
551 			     (src_clk_div - 1) << DCLK_VOPLITE_DIV_CON_SHIFT);
552 		break;
553 	default:
554 		printf("do not support this vop freq\n");
555 		return -EINVAL;
556 	}
557 
558 	return rk1808_vop_get_clk(priv, clk_id);
559 }
560 #endif
561 
562 static ulong rk1808_bus_get_clk(struct rk1808_clk_priv *priv, ulong clk_id)
563 {
564 	struct rk1808_cru *cru = priv->cru;
565 	u32 div, con, parent;
566 
567 	switch (clk_id) {
568 	case HSCLK_BUS_PRE:
569 		con = readl(&cru->clksel_con[27]);
570 		div = (con & HSCLK_BUS_DIV_CON_MASK) >> HSCLK_BUS_DIV_CON_SHIFT;
571 		parent = priv->gpll_hz;
572 		break;
573 	case MSCLK_BUS_PRE:
574 		con = readl(&cru->clksel_con[28]);
575 		div = (con & MSCLK_BUS_DIV_CON_MASK) >> MSCLK_BUS_DIV_CON_SHIFT;
576 		parent = priv->gpll_hz;
577 		break;
578 	case LSCLK_BUS_PRE:
579 		con = readl(&cru->clksel_con[28]);
580 		div = (con & LSCLK_BUS_DIV_CON_MASK) >> LSCLK_BUS_DIV_CON_SHIFT;
581 		parent = priv->gpll_hz;
582 		break;
583 	default:
584 		return -ENOENT;
585 	}
586 
587 	return DIV_TO_RATE(parent, div);
588 }
589 
590 static ulong rk1808_bus_set_clk(struct rk1808_clk_priv *priv,
591 				ulong clk_id, ulong hz)
592 {
593 	struct rk1808_cru *cru = priv->cru;
594 	int src_clk_div;
595 
596 	/*
597 	 * select gpll as pd_bus bus clock source and
598 	 * set up dependent divisors for PCLK/HCLK and ACLK clocks.
599 	 */
600 	switch (clk_id) {
601 	case HSCLK_BUS_PRE:
602 		src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
603 		assert(src_clk_div - 1 < 31);
604 		rk_clrsetreg(&cru->clksel_con[27],
605 			     CLK_BUS_PLL_SEL_MASK | HSCLK_BUS_DIV_CON_MASK,
606 			     CLK_BUS_PLL_SEL_GPLL << CLK_BUS_PLL_SEL_SHIFT |
607 			     (src_clk_div - 1) << HSCLK_BUS_DIV_CON_SHIFT);
608 		break;
609 	case MSCLK_BUS_PRE:
610 		src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
611 		assert(src_clk_div - 1 < 31);
612 		rk_clrsetreg(&cru->clksel_con[28],
613 			     CLK_BUS_PLL_SEL_MASK | MSCLK_BUS_DIV_CON_MASK,
614 			     CLK_BUS_PLL_SEL_GPLL << CLK_BUS_PLL_SEL_SHIFT |
615 			     (src_clk_div - 1) << MSCLK_BUS_DIV_CON_SHIFT);
616 		break;
617 	case LSCLK_BUS_PRE:
618 		src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
619 		assert(src_clk_div - 1 < 31);
620 		rk_clrsetreg(&cru->clksel_con[28],
621 			     CLK_BUS_PLL_SEL_MASK | LSCLK_BUS_DIV_CON_MASK,
622 			     CLK_BUS_PLL_SEL_GPLL << CLK_BUS_PLL_SEL_SHIFT |
623 			     (src_clk_div - 1) << LSCLK_BUS_DIV_CON_SHIFT);
624 		break;
625 	default:
626 		printf("do not support this bus freq\n");
627 		return -EINVAL;
628 	}
629 
630 	return rk1808_bus_get_clk(priv, clk_id);
631 }
632 
633 static ulong rk1808_peri_get_clk(struct rk1808_clk_priv *priv, ulong clk_id)
634 {
635 	struct rk1808_cru *cru = priv->cru;
636 	u32 div, con, parent;
637 
638 	switch (clk_id) {
639 	case MSCLK_PERI:
640 		con = readl(&cru->clksel_con[19]);
641 		div = (con & MSCLK_PERI_DIV_CON_MASK) >>
642 		      MSCLK_PERI_DIV_CON_SHIFT;
643 		parent = priv->gpll_hz;
644 		break;
645 	case LSCLK_PERI:
646 		con = readl(&cru->clksel_con[19]);
647 		div = (con & LSCLK_PERI_DIV_CON_MASK) >>
648 		      LSCLK_PERI_DIV_CON_SHIFT;
649 		parent = priv->gpll_hz;
650 		break;
651 	default:
652 		return -ENOENT;
653 	}
654 
655 	return DIV_TO_RATE(parent, div);
656 }
657 
658 static ulong rk1808_peri_set_clk(struct rk1808_clk_priv *priv,
659 				 ulong clk_id, ulong hz)
660 {
661 	struct rk1808_cru *cru = priv->cru;
662 	int src_clk_div;
663 
664 	src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
665 	assert(src_clk_div - 1 < 31);
666 
667 	/*
668 	 * select gpll as pd_peri bus clock source and
669 	 * set up dependent divisors for HCLK and ACLK clocks.
670 	 */
671 	switch (clk_id) {
672 	case MSCLK_PERI:
673 		rk_clrsetreg(&cru->clksel_con[19],
674 			     CLK_PERI_PLL_SEL_MASK | MSCLK_PERI_DIV_CON_MASK,
675 			     CLK_PERI_PLL_SEL_GPLL << CLK_PERI_PLL_SEL_SHIFT |
676 			     (src_clk_div - 1) << MSCLK_PERI_DIV_CON_SHIFT);
677 		break;
678 	case LSCLK_PERI:
679 		rk_clrsetreg(&cru->clksel_con[19],
680 			     CLK_PERI_PLL_SEL_MASK | LSCLK_PERI_DIV_CON_MASK,
681 			     CLK_PERI_PLL_SEL_GPLL << CLK_PERI_PLL_SEL_SHIFT |
682 			     (src_clk_div - 1) << LSCLK_PERI_DIV_CON_SHIFT);
683 		break;
684 	default:
685 		printf("do not support this peri freq\n");
686 		return -EINVAL;
687 	}
688 
689 	return rk1808_peri_get_clk(priv, clk_id);
690 }
691 
692 static ulong rk1808_armclk_set_clk(struct rk1808_clk_priv *priv, ulong hz)
693 {
694 	struct rk1808_cru *cru = priv->cru;
695 	const struct rockchip_cpu_rate_table *rate;
696 	ulong old_rate;
697 
698 	rate = rockchip_get_cpu_settings(rk1808_cpu_rates, hz);
699 	if (!rate) {
700 		printf("%s unsupported rate\n", __func__);
701 		return -EINVAL;
702 	}
703 
704 	/*
705 	 * select apll as cpu/core clock pll source and
706 	 * set up dependent divisors for PERI and ACLK clocks.
707 	 * core hz : apll = 1:1
708 	 */
709 	old_rate = rockchip_pll_get_rate(&rk1808_pll_clks[APLL],
710 					 priv->cru, APLL);
711 	if (old_rate > hz) {
712 		if (rockchip_pll_set_rate(&rk1808_pll_clks[APLL],
713 					  priv->cru, APLL, hz))
714 			return -EINVAL;
715 		rk_clrsetreg(&cru->clksel_con[0],
716 			     CORE_CLK_PLL_SEL_MASK | CORE_DIV_CON_MASK |
717 			     CORE_ACLK_DIV_MASK | CORE_DBG_DIV_MASK,
718 			     rate->aclk_div << CORE_ACLK_DIV_SHIFT |
719 			     rate->pclk_div << CORE_DBG_DIV_SHIFT |
720 			     CORE_CLK_PLL_SEL_APLL << CORE_CLK_PLL_SEL_SHIFT |
721 			     0 << CORE_DIV_CON_SHIFT);
722 	} else if (old_rate < hz) {
723 		rk_clrsetreg(&cru->clksel_con[0],
724 			     CORE_CLK_PLL_SEL_MASK | CORE_DIV_CON_MASK |
725 			     CORE_ACLK_DIV_MASK | CORE_DBG_DIV_MASK,
726 			     rate->aclk_div << CORE_ACLK_DIV_SHIFT |
727 			     rate->pclk_div << CORE_DBG_DIV_SHIFT |
728 			     CORE_CLK_PLL_SEL_APLL << CORE_CLK_PLL_SEL_SHIFT |
729 			     0 << CORE_DIV_CON_SHIFT);
730 		if (rockchip_pll_set_rate(&rk1808_pll_clks[APLL],
731 					  priv->cru, APLL, hz))
732 			return -EINVAL;
733 	}
734 
735 	return rockchip_pll_get_rate(&rk1808_pll_clks[APLL], priv->cru, APLL);
736 }
737 
738 static ulong rk1808_clk_get_rate(struct clk *clk)
739 {
740 	struct rk1808_clk_priv *priv = dev_get_priv(clk->dev);
741 	ulong rate = 0;
742 
743 	debug("%s %ld\n", __func__, clk->id);
744 	switch (clk->id) {
745 	case PLL_APLL:
746 	case PLL_DPLL:
747 	case PLL_CPLL:
748 	case PLL_GPLL:
749 	case PLL_NPLL:
750 	case PLL_PPLL:
751 		rate = rockchip_pll_get_rate(&rk1808_pll_clks[clk->id - 1],
752 					     priv->cru, clk->id - 1);
753 		break;
754 	case ARMCLK:
755 		rate = rockchip_pll_get_rate(&rk1808_pll_clks[APLL],
756 					     priv->cru, APLL);
757 		break;
758 	case HCLK_SDMMC:
759 	case HCLK_EMMC:
760 	case HCLK_SDIO:
761 	case SCLK_SDMMC:
762 	case SCLK_EMMC:
763 	case SCLK_EMMC_SAMPLE:
764 	case SCLK_SDIO:
765 		rate = rk1808_mmc_get_clk(priv, clk->id);
766 		break;
767 #ifndef CONFIG_SPL_BUILD
768 	case SCLK_PMU_I2C0:
769 	case SCLK_I2C1:
770 	case SCLK_I2C2:
771 	case SCLK_I2C3:
772 	case SCLK_I2C4:
773 	case SCLK_I2C5:
774 		rate = rk1808_i2c_get_clk(priv, clk->id);
775 		break;
776 	case SCLK_PWM0:
777 	case SCLK_PWM1:
778 	case SCLK_PWM2:
779 		rate = rk1808_pwm_get_clk(priv, clk->id);
780 		break;
781 	case SCLK_SARADC:
782 		rate = rk1808_saradc_get_clk(priv);
783 		break;
784 	case SCLK_TSADC:
785 		rate = rk1808_tsadc_get_clk(priv);
786 		break;
787 	case SCLK_SPI0:
788 	case SCLK_SPI1:
789 	case SCLK_SPI2:
790 		rate = rk1808_spi_get_clk(priv, clk->id);
791 		break;
792 	case ACLK_VOPRAW:
793 	case DCLK_VOPRAW:
794 	case ACLK_VOPLITE:
795 	case DCLK_VOPLITE:
796 		rate = rk1808_vop_get_clk(priv, clk->id);
797 		break;
798 #endif
799 	case HSCLK_BUS_PRE:
800 	case MSCLK_BUS_PRE:
801 	case LSCLK_BUS_PRE:
802 		rate = rk1808_bus_get_clk(priv, clk->id);
803 		break;
804 	case MSCLK_PERI:
805 	case LSCLK_PERI:
806 		rate = rk1808_peri_get_clk(priv, clk->id);
807 		break;
808 	default:
809 		return -ENOENT;
810 	}
811 
812 	return rate;
813 }
814 
815 static ulong rk1808_clk_set_rate(struct clk *clk, ulong rate)
816 {
817 	struct rk1808_clk_priv *priv = dev_get_priv(clk->dev);
818 	ulong ret = 0;
819 
820 	debug("%s %ld %ld\n", __func__, clk->id, rate);
821 	switch (clk->id) {
822 	case PLL_APLL:
823 	case PLL_DPLL:
824 	case PLL_PPLL:
825 		ret = rockchip_pll_set_rate(&rk1808_pll_clks[clk->id - 1],
826 					    priv->cru, clk->id - 1, rate);
827 		break;
828 	case PLL_CPLL:
829 		ret = rockchip_pll_set_rate(&rk1808_pll_clks[CPLL],
830 					    priv->cru, CPLL, rate);
831 		if (ret == 0)
832 			priv->cpll_hz = rate;
833 		break;
834 	case PLL_GPLL:
835 		ret = rockchip_pll_set_rate(&rk1808_pll_clks[GPLL],
836 					    priv->cru, GPLL, rate);
837 		if (ret == 0)
838 			priv->gpll_hz = rate;
839 		break;
840 	case PLL_NPLL:
841 		ret = rockchip_pll_set_rate(&rk1808_pll_clks[NPLL],
842 					    priv->cru, NPLL, rate);
843 		if (ret == 0)
844 			priv->npll_hz = rate;
845 		break;
846 	case ARMCLK:
847 		if (priv->armclk_hz)
848 			rk1808_armclk_set_clk(priv, rate);
849 		priv->armclk_hz = rate;
850 		break;
851 	case HCLK_SDMMC:
852 	case HCLK_EMMC:
853 	case HCLK_SDIO:
854 	case SCLK_SDMMC:
855 	case SCLK_EMMC:
856 	case SCLK_SDIO:
857 		ret = rk1808_mmc_set_clk(priv, clk->id, rate);
858 		break;
859 #ifndef CONFIG_SPL_BUILD
860 	case SCLK_PMU_I2C0:
861 	case SCLK_I2C1:
862 	case SCLK_I2C2:
863 	case SCLK_I2C3:
864 	case SCLK_I2C4:
865 	case SCLK_I2C5:
866 		ret = rk1808_i2c_set_clk(priv, clk->id, rate);
867 		break;
868 	case SCLK_PWM0:
869 	case SCLK_PWM1:
870 	case SCLK_PWM2:
871 		ret = rk1808_pwm_set_clk(priv, clk->id, rate);
872 		break;
873 	case SCLK_SARADC:
874 		ret = rk1808_saradc_set_clk(priv, rate);
875 		break;
876 	case SCLK_TSADC:
877 		ret = rk1808_tsadc_set_clk(priv, rate);
878 		break;
879 	case SCLK_SPI0:
880 	case SCLK_SPI1:
881 	case SCLK_SPI2:
882 		ret = rk1808_spi_set_clk(priv, clk->id, rate);
883 		break;
884 	case ACLK_VOPRAW:
885 	case DCLK_VOPRAW:
886 	case ACLK_VOPLITE:
887 	case DCLK_VOPLITE:
888 		ret = rk1808_vop_set_clk(priv, clk->id, rate);
889 		break;
890 #endif
891 	case HSCLK_BUS_PRE:
892 	case MSCLK_BUS_PRE:
893 	case LSCLK_BUS_PRE:
894 		ret = rk1808_bus_set_clk(priv, clk->id, rate);
895 		break;
896 	case MSCLK_PERI:
897 	case LSCLK_PERI:
898 		ret = rk1808_peri_set_clk(priv, clk->id, rate);
899 		break;
900 	default:
901 		return -ENOENT;
902 	}
903 
904 	return ret;
905 }
906 
907 #define ROCKCHIP_MMC_DELAY_SEL		BIT(10)
908 #define ROCKCHIP_MMC_DEGREE_MASK	0x3
909 #define ROCKCHIP_MMC_DELAYNUM_OFFSET	2
910 #define ROCKCHIP_MMC_DELAYNUM_MASK	(0xff << ROCKCHIP_MMC_DELAYNUM_OFFSET)
911 
912 #define PSECS_PER_SEC 1000000000000LL
913 /*
914  * Each fine delay is between 44ps-77ps. Assume each fine delay is 60ps to
915  * simplify calculations. So 45degs could be anywhere between 33deg and 57.8deg.
916  */
917 #define ROCKCHIP_MMC_DELAY_ELEMENT_PSEC 60
918 
919 int rk1808_mmc_get_phase(struct clk *clk)
920 {
921 	struct rk1808_clk_priv *priv = dev_get_priv(clk->dev);
922 	struct rk1808_cru *cru = priv->cru;
923 	u32 raw_value, delay_num;
924 	u16 degrees = 0;
925 	ulong rate;
926 
927 	rate = rk1808_clk_get_rate(clk);
928 
929 	if (rate < 0)
930 		return rate;
931 
932 	if (clk->id == SCLK_EMMC_SAMPLE)
933 		raw_value = readl(&cru->emmc_con[1]);
934 	else if (clk->id == SCLK_SDMMC_SAMPLE)
935 		raw_value = readl(&cru->sdmmc_con[1]);
936 	else
937 		raw_value = readl(&cru->sdio_con[1]);
938 
939 	raw_value >>= 1;
940 	degrees = (raw_value & ROCKCHIP_MMC_DEGREE_MASK) * 90;
941 
942 	if (raw_value & ROCKCHIP_MMC_DELAY_SEL) {
943 		/* degrees/delaynum * 10000 */
944 		unsigned long factor = (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10) *
945 					36 * (rate / 1000000);
946 
947 		delay_num = (raw_value & ROCKCHIP_MMC_DELAYNUM_MASK);
948 		delay_num >>= ROCKCHIP_MMC_DELAYNUM_OFFSET;
949 		degrees += DIV_ROUND_CLOSEST(delay_num * factor, 10000);
950 	}
951 
952 	return degrees % 360;
953 }
954 
955 int rk1808_mmc_set_phase(struct clk *clk, u32 degrees)
956 {
957 	struct rk1808_clk_priv *priv = dev_get_priv(clk->dev);
958 	struct rk1808_cru *cru = priv->cru;
959 	u8 nineties, remainder, delay_num;
960 	u32 raw_value, delay;
961 	ulong rate;
962 
963 	rate = rk1808_clk_get_rate(clk);
964 
965 	if (rate < 0)
966 		return rate;
967 
968 	nineties = degrees / 90;
969 	remainder = (degrees % 90);
970 
971 	/*
972 	 * Convert to delay; do a little extra work to make sure we
973 	 * don't overflow 32-bit / 64-bit numbers.
974 	 */
975 	delay = 10000000; /* PSECS_PER_SEC / 10000 / 10 */
976 	delay *= remainder;
977 	delay = DIV_ROUND_CLOSEST(delay, (rate / 1000) * 36 *
978 				(ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10));
979 
980 	delay_num = (u8)min_t(u32, delay, 255);
981 
982 	raw_value = delay_num ? ROCKCHIP_MMC_DELAY_SEL : 0;
983 	raw_value |= delay_num << ROCKCHIP_MMC_DELAYNUM_OFFSET;
984 	raw_value |= nineties;
985 
986 	raw_value <<= 1;
987 	if (clk->id == SCLK_EMMC_SAMPLE)
988 		writel(raw_value | 0xffff0000, &cru->emmc_con[1]);
989 	else if (clk->id == SCLK_SDMMC_SAMPLE)
990 		writel(raw_value | 0xffff0000, &cru->sdmmc_con[1]);
991 	else
992 		writel(raw_value | 0xffff0000, &cru->sdio_con[1]);
993 
994 	debug("mmc set_phase(%d) delay_nums=%u reg=%#x actual_degrees=%d\n",
995 	      degrees, delay_num, raw_value, rk1808_mmc_get_phase(clk));
996 
997 	return 0;
998 }
999 
1000 static int rk1808_clk_get_phase(struct clk *clk)
1001 {
1002 	int ret;
1003 
1004 	debug("%s %ld\n", __func__, clk->id);
1005 	switch (clk->id) {
1006 	case SCLK_EMMC_SAMPLE:
1007 	case SCLK_SDMMC_SAMPLE:
1008 	case SCLK_SDIO_SAMPLE:
1009 		ret = rk1808_mmc_get_phase(clk);
1010 		break;
1011 	default:
1012 		return -ENOENT;
1013 	}
1014 
1015 	return ret;
1016 }
1017 
1018 static int rk1808_clk_set_phase(struct clk *clk, int degrees)
1019 {
1020 	int ret;
1021 
1022 	debug("%s %ld\n", __func__, clk->id);
1023 	switch (clk->id) {
1024 	case SCLK_EMMC_SAMPLE:
1025 	case SCLK_SDMMC_SAMPLE:
1026 	case SCLK_SDIO_SAMPLE:
1027 		ret = rk1808_mmc_set_phase(clk, degrees);
1028 		break;
1029 	default:
1030 		return -ENOENT;
1031 	}
1032 
1033 	return ret;
1034 }
1035 
1036 static struct clk_ops rk1808_clk_ops = {
1037 	.get_rate = rk1808_clk_get_rate,
1038 	.set_rate = rk1808_clk_set_rate,
1039 	.get_phase	= rk1808_clk_get_phase,
1040 	.set_phase	= rk1808_clk_set_phase,
1041 };
1042 
1043 static int rk1808_clk_probe(struct udevice *dev)
1044 {
1045 	struct rk1808_clk_priv *priv = dev_get_priv(dev);
1046 	int ret;
1047 
1048 	if (rockchip_pll_get_rate(&rk1808_pll_clks[APLL],
1049 				  priv->cru, APLL) != APLL_HZ) {
1050 		ret = rk1808_armclk_set_clk(priv, APLL_HZ);
1051 		if (ret < 0)
1052 			printf("%s failed to set armclk rate\n", __func__);
1053 	}
1054 
1055 	priv->cpll_hz = rockchip_pll_get_rate(&rk1808_pll_clks[CPLL],
1056 					      priv->cru, CPLL);
1057 	priv->gpll_hz = rockchip_pll_get_rate(&rk1808_pll_clks[GPLL],
1058 					      priv->cru, GPLL);
1059 
1060 	/* Process 'assigned-{clocks/clock-parents/clock-rates}' properties */
1061 	ret = clk_set_defaults(dev);
1062 	if (ret)
1063 		debug("%s clk_set_defaults failed %d\n", __func__, ret);
1064 
1065 	return 0;
1066 }
1067 
1068 static int rk1808_clk_ofdata_to_platdata(struct udevice *dev)
1069 {
1070 	struct rk1808_clk_priv *priv = dev_get_priv(dev);
1071 
1072 	priv->cru = dev_read_addr_ptr(dev);
1073 
1074 	return 0;
1075 }
1076 
1077 static int rk1808_clk_bind(struct udevice *dev)
1078 {
1079 	int ret;
1080 	struct udevice *sys_child, *sf_child;
1081 	struct sysreset_reg *priv;
1082 	struct softreset_reg *sf_priv;
1083 
1084 	/* The reset driver does not have a device node, so bind it here */
1085 	ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset",
1086 				 &sys_child);
1087 	if (ret) {
1088 		debug("Warning: No sysreset driver: ret=%d\n", ret);
1089 	} else {
1090 		priv = malloc(sizeof(struct sysreset_reg));
1091 		priv->glb_srst_fst_value = offsetof(struct rk1808_cru,
1092 						    glb_srst_fst);
1093 		priv->glb_srst_snd_value = offsetof(struct rk1808_cru,
1094 						    glb_srst_snd);
1095 		sys_child->priv = priv;
1096 	}
1097 
1098 	ret = device_bind_driver_to_node(dev, "rockchip_reset", "reset",
1099 					 dev_ofnode(dev), &sf_child);
1100 	if (ret) {
1101 		debug("Warning: No rockchip reset driver: ret=%d\n", ret);
1102 	} else {
1103 		sf_priv = malloc(sizeof(struct softreset_reg));
1104 		sf_priv->sf_reset_offset = offsetof(struct rk1808_cru,
1105 						    softrst_con[0]);
1106 		sf_priv->sf_reset_num = 16;
1107 		sf_child->priv = sf_priv;
1108 	}
1109 
1110 	return 0;
1111 }
1112 
1113 static const struct udevice_id rk1808_clk_ids[] = {
1114 	{ .compatible = "rockchip,rk1808-cru" },
1115 	{ }
1116 };
1117 
1118 U_BOOT_DRIVER(rockchip_rk1808_cru) = {
1119 	.name		= "rockchip_rk1808_cru",
1120 	.id		= UCLASS_CLK,
1121 	.of_match	= rk1808_clk_ids,
1122 	.priv_auto_alloc_size = sizeof(struct rk1808_clk_priv),
1123 	.ofdata_to_platdata = rk1808_clk_ofdata_to_platdata,
1124 	.ops		= &rk1808_clk_ops,
1125 	.bind		= rk1808_clk_bind,
1126 	.probe		= rk1808_clk_probe,
1127 };
1128 
1129 #ifndef CONFIG_SPL_BUILD
1130 /**
1131  * soc_clk_dump() - Print clock frequencies
1132  * Returns zero on success
1133  *
1134  * Implementation for the clk dump command.
1135  */
1136 int soc_clk_dump(void)
1137 {
1138 	struct udevice *cru_dev;
1139 	const struct rk1808_clk_info *clk_dump;
1140 	struct clk clk;
1141 	unsigned long clk_count = ARRAY_SIZE(clks_dump);
1142 	unsigned long rate;
1143 	int i, ret;
1144 
1145 	ret = uclass_get_device_by_driver(UCLASS_CLK,
1146 					  DM_GET_DRIVER(rockchip_rk1808_cru),
1147 					  &cru_dev);
1148 	if (ret) {
1149 		printf("%s failed to get cru device\n", __func__);
1150 		return ret;
1151 	}
1152 
1153 	printf("CLK:");
1154 	for (i = 0; i < clk_count; i++) {
1155 		clk_dump = &clks_dump[i];
1156 		if (clk_dump->name) {
1157 			clk.id = clk_dump->id;
1158 			if (clk_dump->is_cru)
1159 				ret = clk_request(cru_dev, &clk);
1160 			if (ret < 0)
1161 				return ret;
1162 
1163 			rate = clk_get_rate(&clk);
1164 			clk_free(&clk);
1165 			if (i == 0) {
1166 				if (rate < 0)
1167 					printf("%s %s\n", clk_dump->name,
1168 					       "unknown");
1169 				else
1170 					printf("%s %lu KHz\n", clk_dump->name,
1171 					       rate / 1000);
1172 			} else {
1173 				if (rate < 0)
1174 					printf("%s %s\n", clk_dump->name,
1175 					       "unknown");
1176 				else
1177 					printf("%s %lu KHz\n", clk_dump->name,
1178 					       rate / 1000);
1179 			}
1180 		}
1181 	}
1182 
1183 	return 0;
1184 }
1185 #endif
1186