1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * (C) Copyright 2016 Rockchip Electronics Co., Ltd
4  * Author: Andy Yan <andy.yan@rock-chips.com>
5  */
6 
7 #include <common.h>
8 #include <bitfield.h>
9 #include <clk-uclass.h>
10 #include <dm.h>
11 #include <errno.h>
12 #include <syscon.h>
13 #include <asm/io.h>
14 #include <asm/arch/clock.h>
15 #include <asm/arch/cru_rv1108.h>
16 #include <asm/arch/hardware.h>
17 #include <dm/lists.h>
18 #include <dt-bindings/clock/rv1108-cru.h>
19 
20 DECLARE_GLOBAL_DATA_PTR;
21 
22 enum {
23 	VCO_MAX_HZ	= 2400U * 1000000,
24 	VCO_MIN_HZ	= 600 * 1000000,
25 	OUTPUT_MAX_HZ	= 2400U * 1000000,
26 	OUTPUT_MIN_HZ	= 24 * 1000000,
27 };
28 
29 #define DIV_TO_RATE(input_rate, div)	((input_rate) / ((div) + 1))
30 
31 #define PLL_DIVISORS(hz, _refdiv, _postdiv1, _postdiv2) {\
32 	.refdiv = _refdiv,\
33 	.fbdiv = (u32)((u64)hz * _refdiv * _postdiv1 * _postdiv2 / OSC_HZ),\
34 	.postdiv1 = _postdiv1, .postdiv2 = _postdiv2};\
35 	_Static_assert(((u64)hz * _refdiv * _postdiv1 * _postdiv2 / OSC_HZ) *\
36 			 OSC_HZ / (_refdiv * _postdiv1 * _postdiv2) == hz,\
37 			 #hz "Hz cannot be hit with PLL "\
38 			 "divisors on line " __stringify(__LINE__));
39 
40 static const struct pll_div apll_init_cfg = PLL_DIVISORS(APLL_HZ, 1, 3, 1);
41 static const struct pll_div gpll_init_cfg = PLL_DIVISORS(GPLL_HZ, 2, 2, 1);
42 
43 /* use integer mode */
44 static inline int rv1108_pll_id(enum rk_clk_id clk_id)
45 {
46 	int id = 0;
47 
48 	switch (clk_id) {
49 	case CLK_ARM:
50 	case CLK_DDR:
51 		id = clk_id - 1;
52 		break;
53 	case CLK_GENERAL:
54 		id = 2;
55 		break;
56 	default:
57 		printf("invalid pll id:%d\n", clk_id);
58 		id = -1;
59 		break;
60 	}
61 
62 	return id;
63 }
64 
65 static int rkclk_set_pll(struct rv1108_cru *cru, enum rk_clk_id clk_id,
66 			 const struct pll_div *div)
67 {
68 	int pll_id = rv1108_pll_id(clk_id);
69 	struct rv1108_pll *pll = &cru->pll[pll_id];
70 
71 	/* All PLLs have same VCO and output frequency range restrictions. */
72 	uint vco_hz = OSC_HZ / 1000 * div->fbdiv / div->refdiv * 1000;
73 	uint output_hz = vco_hz / div->postdiv1 / div->postdiv2;
74 
75 	debug("PLL at %p: fb=%d, ref=%d, pst1=%d, pst2=%d, vco=%u Hz, output=%u Hz\n",
76 	      pll, div->fbdiv, div->refdiv, div->postdiv1,
77 	      div->postdiv2, vco_hz, output_hz);
78 	assert(vco_hz >= VCO_MIN_HZ && vco_hz <= VCO_MAX_HZ &&
79 	       output_hz >= OUTPUT_MIN_HZ && output_hz <= OUTPUT_MAX_HZ);
80 
81 	/*
82 	 * When power on or changing PLL setting,
83 	 * we must force PLL into slow mode to ensure output stable clock.
84 	 */
85 	rk_clrsetreg(&pll->con3, WORK_MODE_MASK,
86 		     WORK_MODE_SLOW << WORK_MODE_SHIFT);
87 
88 	/* use integer mode */
89 	rk_setreg(&pll->con3, 1 << DSMPD_SHIFT);
90 	/* Power down */
91 	rk_setreg(&pll->con3, 1 << GLOBAL_POWER_DOWN_SHIFT);
92 
93 	rk_clrsetreg(&pll->con0, FBDIV_MASK, div->fbdiv << FBDIV_SHIFT);
94 	rk_clrsetreg(&pll->con1, POSTDIV1_MASK | POSTDIV2_MASK | REFDIV_MASK,
95 		     (div->postdiv1 << POSTDIV1_SHIFT |
96 		     div->postdiv2 << POSTDIV2_SHIFT |
97 		     div->refdiv << REFDIV_SHIFT));
98 	rk_clrsetreg(&pll->con2, FRACDIV_MASK,
99 		     (div->refdiv << REFDIV_SHIFT));
100 
101 	/* Power Up */
102 	rk_clrreg(&pll->con3, 1 << GLOBAL_POWER_DOWN_SHIFT);
103 
104 	/* waiting for pll lock */
105 	while (readl(&pll->con2) & (1 << LOCK_STA_SHIFT))
106 		udelay(1);
107 
108 	/*
109 	 * set PLL into normal mode.
110 	 */
111 	rk_clrsetreg(&pll->con3, WORK_MODE_MASK,
112 		     WORK_MODE_NORMAL << WORK_MODE_SHIFT);
113 
114 	return 0;
115 }
116 
117 static uint32_t rkclk_pll_get_rate(struct rv1108_cru *cru,
118 				   enum rk_clk_id clk_id)
119 {
120 	uint32_t refdiv, fbdiv, postdiv1, postdiv2;
121 	uint32_t con0, con1, con3;
122 	int pll_id = rv1108_pll_id(clk_id);
123 	struct rv1108_pll *pll = &cru->pll[pll_id];
124 	uint32_t freq;
125 
126 	con3 = readl(&pll->con3);
127 
128 	if (con3 & WORK_MODE_MASK) {
129 		con0 = readl(&pll->con0);
130 		con1 = readl(&pll->con1);
131 		fbdiv = (con0 >> FBDIV_SHIFT) & FBDIV_MASK;
132 		postdiv1 = (con1 & POSTDIV1_MASK) >> POSTDIV1_SHIFT;
133 		postdiv2 = (con1 & POSTDIV2_MASK) >> POSTDIV2_SHIFT;
134 		refdiv = (con1 >> REFDIV_SHIFT) & REFDIV_MASK;
135 		freq = (24 * fbdiv / (refdiv * postdiv1 * postdiv2)) * 1000000;
136 	} else {
137 		freq = OSC_HZ;
138 	}
139 
140 	return freq;
141 }
142 
143 static int rv1108_mac_set_clk(struct rv1108_cru *cru, ulong rate)
144 {
145 	uint32_t con = readl(&cru->clksel_con[24]);
146 	ulong pll_rate;
147 	uint8_t div;
148 
149 	if ((con >> MAC_PLL_SEL_SHIFT) & MAC_PLL_SEL_GPLL)
150 		pll_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
151 	else
152 		pll_rate = rkclk_pll_get_rate(cru, CLK_ARM);
153 
154 	/*default set 50MHZ for gmac*/
155 	if (!rate)
156 		rate = 50000000;
157 
158 	div = DIV_ROUND_UP(pll_rate, rate) - 1;
159 	if (div <= 0x1f)
160 		rk_clrsetreg(&cru->clksel_con[24], MAC_CLK_DIV_MASK,
161 			     div << MAC_CLK_DIV_SHIFT);
162 	else
163 		debug("Unsupported div for gmac:%d\n", div);
164 
165 	return DIV_TO_RATE(pll_rate, div);
166 }
167 
168 static int rv1108_sfc_set_clk(struct rv1108_cru *cru, uint rate)
169 {
170 	u32 con = readl(&cru->clksel_con[27]);
171 	u32 pll_rate;
172 	u32 div;
173 
174 	if ((con >> SFC_PLL_SEL_SHIFT) && SFC_PLL_SEL_GPLL)
175 		pll_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
176 	else
177 		pll_rate = rkclk_pll_get_rate(cru, CLK_DDR);
178 
179 	div = DIV_ROUND_UP(pll_rate, rate) - 1;
180 	if (div <= 0x3f)
181 		rk_clrsetreg(&cru->clksel_con[27], SFC_CLK_DIV_MASK,
182 			     div << SFC_CLK_DIV_SHIFT);
183 	else
184 		debug("Unsupported sfc clk rate:%d\n", rate);
185 
186 	return DIV_TO_RATE(pll_rate, div);
187 }
188 
189 static ulong rv1108_saradc_get_clk(struct rv1108_cru *cru)
190 {
191 	u32 div, val;
192 
193 	val = readl(&cru->clksel_con[22]);
194 	div = bitfield_extract(val, CLK_SARADC_DIV_CON_SHIFT,
195 			       CLK_SARADC_DIV_CON_WIDTH);
196 
197 	return DIV_TO_RATE(OSC_HZ, div);
198 }
199 
200 static ulong rv1108_saradc_set_clk(struct rv1108_cru *cru, uint hz)
201 {
202 	int src_clk_div;
203 
204 	src_clk_div = DIV_ROUND_UP(OSC_HZ, hz) - 1;
205 	assert(src_clk_div < 128);
206 
207 	rk_clrsetreg(&cru->clksel_con[22],
208 		     CLK_SARADC_DIV_CON_MASK,
209 		     src_clk_div << CLK_SARADC_DIV_CON_SHIFT);
210 
211 	return rv1108_saradc_get_clk(cru);
212 }
213 
214 static ulong rv1108_aclk_vio1_get_clk(struct rv1108_cru *cru)
215 {
216 	u32 div, val;
217 
218 	val = readl(&cru->clksel_con[28]);
219 	div = bitfield_extract(val, ACLK_VIO1_CLK_DIV_SHIFT,
220 			       CLK_VIO_DIV_CON_WIDTH);
221 
222 	return DIV_TO_RATE(GPLL_HZ, div);
223 }
224 
225 static ulong rv1108_aclk_vio1_set_clk(struct rv1108_cru *cru, uint hz)
226 {
227 	int src_clk_div;
228 
229 	src_clk_div = DIV_ROUND_UP(GPLL_HZ, hz) - 1;
230 	assert(src_clk_div < 32);
231 
232 	rk_clrsetreg(&cru->clksel_con[28],
233 		     ACLK_VIO1_CLK_DIV_MASK | ACLK_VIO1_PLL_SEL_MASK,
234 		     (src_clk_div << ACLK_VIO1_CLK_DIV_SHIFT) |
235 		     (VIO_PLL_SEL_GPLL << ACLK_VIO1_PLL_SEL_SHIFT));
236 
237 	return rv1108_aclk_vio1_get_clk(cru);
238 }
239 
240 static ulong rv1108_aclk_vio0_get_clk(struct rv1108_cru *cru)
241 {
242 	u32 div, val;
243 
244 	val = readl(&cru->clksel_con[28]);
245 	div = bitfield_extract(val, ACLK_VIO0_CLK_DIV_SHIFT,
246 			       CLK_VIO_DIV_CON_WIDTH);
247 
248 	return DIV_TO_RATE(GPLL_HZ, div);
249 }
250 
251 static ulong rv1108_aclk_vio0_set_clk(struct rv1108_cru *cru, uint hz)
252 {
253 	int src_clk_div;
254 
255 	src_clk_div = DIV_ROUND_UP(GPLL_HZ, hz) - 1;
256 	assert(src_clk_div < 32);
257 
258 	rk_clrsetreg(&cru->clksel_con[28],
259 		     ACLK_VIO0_CLK_DIV_MASK | ACLK_VIO0_PLL_SEL_MASK,
260 		     (src_clk_div << ACLK_VIO0_CLK_DIV_SHIFT) |
261 		     (VIO_PLL_SEL_GPLL << ACLK_VIO0_PLL_SEL_SHIFT));
262 
263 	/*HCLK_VIO default div = 4*/
264 	rk_clrsetreg(&cru->clksel_con[29],
265 		     HCLK_VIO_CLK_DIV_MASK,
266 		     3 << HCLK_VIO_CLK_DIV_SHIFT);
267 	/*PCLK_VIO default div = 4*/
268 	rk_clrsetreg(&cru->clksel_con[29],
269 		     PCLK_VIO_CLK_DIV_MASK,
270 		     3 << PCLK_VIO_CLK_DIV_SHIFT);
271 
272 	return rv1108_aclk_vio0_get_clk(cru);
273 }
274 
275 static ulong rv1108_dclk_vop_get_clk(struct rv1108_cru *cru)
276 {
277 	u32 div, val;
278 
279 	val = readl(&cru->clksel_con[32]);
280 	div = bitfield_extract(val, DCLK_VOP_CLK_DIV_SHIFT,
281 			       DCLK_VOP_DIV_CON_WIDTH);
282 
283 	return DIV_TO_RATE(GPLL_HZ, div);
284 }
285 
286 static ulong rv1108_dclk_vop_set_clk(struct rv1108_cru *cru, uint hz)
287 {
288 	int src_clk_div;
289 
290 	src_clk_div = DIV_ROUND_UP(GPLL_HZ, hz) - 1;
291 	assert(src_clk_div < 64);
292 
293 	rk_clrsetreg(&cru->clksel_con[32],
294 		     DCLK_VOP_CLK_DIV_MASK | DCLK_VOP_PLL_SEL_MASK |
295 		     DCLK_VOP_SEL_SHIFT,
296 		     (src_clk_div << DCLK_VOP_CLK_DIV_SHIFT) |
297 		     (DCLK_VOP_PLL_SEL_GPLL << DCLK_VOP_PLL_SEL_SHIFT) |
298 		     (DCLK_VOP_SEL_PLL << DCLK_VOP_SEL_SHIFT));
299 
300 	return rv1108_dclk_vop_get_clk(cru);
301 }
302 
303 static ulong rv1108_aclk_bus_get_clk(struct rv1108_cru *cru)
304 {
305 	u32 div, val;
306 	ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
307 
308 	val = readl(&cru->clksel_con[2]);
309 	div = bitfield_extract(val, ACLK_BUS_DIV_CON_SHIFT,
310 			       ACLK_BUS_DIV_CON_WIDTH);
311 
312 	return DIV_TO_RATE(parent_rate, div);
313 }
314 
315 static ulong rv1108_aclk_bus_set_clk(struct rv1108_cru *cru, uint hz)
316 {
317 	int src_clk_div;
318 	ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
319 
320 	src_clk_div = DIV_ROUND_UP(parent_rate, hz) - 1;
321 	assert(src_clk_div < 32);
322 
323 	rk_clrsetreg(&cru->clksel_con[2],
324 		     ACLK_BUS_DIV_CON_MASK | ACLK_BUS_PLL_SEL_MASK,
325 		     (src_clk_div << ACLK_BUS_DIV_CON_SHIFT) |
326 		     (ACLK_BUS_PLL_SEL_GPLL << ACLK_BUS_PLL_SEL_SHIFT));
327 
328 	return rv1108_aclk_bus_get_clk(cru);
329 }
330 
331 static ulong rv1108_aclk_peri_get_clk(struct rv1108_cru *cru)
332 {
333 	u32 div, val;
334 	ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
335 
336 	val = readl(&cru->clksel_con[23]);
337 	div = bitfield_extract(val, ACLK_PERI_DIV_CON_SHIFT,
338 			       PERI_DIV_CON_WIDTH);
339 
340 	return DIV_TO_RATE(parent_rate, div);
341 }
342 
343 static ulong rv1108_hclk_peri_get_clk(struct rv1108_cru *cru)
344 {
345 	u32 div, val;
346 	ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
347 
348 	val = readl(&cru->clksel_con[23]);
349 	div = bitfield_extract(val, HCLK_PERI_DIV_CON_SHIFT,
350 			       PERI_DIV_CON_WIDTH);
351 
352 	return DIV_TO_RATE(parent_rate, div);
353 }
354 
355 static ulong rv1108_pclk_peri_get_clk(struct rv1108_cru *cru)
356 {
357 	u32 div, val;
358 	ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
359 
360 	val = readl(&cru->clksel_con[23]);
361 	div = bitfield_extract(val, PCLK_PERI_DIV_CON_SHIFT,
362 			       PERI_DIV_CON_WIDTH);
363 
364 	return DIV_TO_RATE(parent_rate, div);
365 }
366 
367 static ulong rv1108_aclk_peri_set_clk(struct rv1108_cru *cru, uint hz)
368 {
369 	int src_clk_div;
370 	ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
371 
372 	src_clk_div = DIV_ROUND_UP(parent_rate, hz) - 1;
373 	assert(src_clk_div < 32);
374 
375 	rk_clrsetreg(&cru->clksel_con[23],
376 		     ACLK_PERI_DIV_CON_MASK | ACLK_PERI_PLL_SEL_MASK,
377 		     (src_clk_div << ACLK_PERI_DIV_CON_SHIFT) |
378 		     (ACLK_PERI_PLL_SEL_GPLL << ACLK_PERI_PLL_SEL_SHIFT));
379 
380 	return rv1108_aclk_peri_get_clk(cru);
381 }
382 
383 static ulong rv1108_hclk_peri_set_clk(struct rv1108_cru *cru, uint hz)
384 {
385 	int src_clk_div;
386 	ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
387 
388 	src_clk_div = DIV_ROUND_UP(parent_rate, hz) - 1;
389 	assert(src_clk_div < 32);
390 
391 	rk_clrsetreg(&cru->clksel_con[23],
392 		     HCLK_PERI_DIV_CON_MASK,
393 		     (src_clk_div << HCLK_PERI_DIV_CON_SHIFT));
394 
395 	return rv1108_hclk_peri_get_clk(cru);
396 }
397 
398 static ulong rv1108_pclk_peri_set_clk(struct rv1108_cru *cru, uint hz)
399 {
400 	int src_clk_div;
401 	ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
402 
403 	src_clk_div = DIV_ROUND_UP(parent_rate, hz) - 1;
404 	assert(src_clk_div < 32);
405 
406 	rk_clrsetreg(&cru->clksel_con[23],
407 		     PCLK_PERI_DIV_CON_MASK,
408 		     (src_clk_div << PCLK_PERI_DIV_CON_SHIFT));
409 
410 	return rv1108_pclk_peri_get_clk(cru);
411 }
412 
413 static ulong rv1108_i2c_get_clk(struct rv1108_cru *cru, ulong clk_id)
414 {
415 	u32 div, con;
416 
417 	switch (clk_id) {
418 	case SCLK_I2C0_PMU:
419 		con = readl(&cru->clksel_con[19]);
420 		div = bitfield_extract(con, CLK_I2C0_DIV_CON_SHIFT,
421 				       I2C_DIV_CON_WIDTH);
422 		break;
423 	case SCLK_I2C1:
424 		con = readl(&cru->clksel_con[19]);
425 		div = bitfield_extract(con, CLK_I2C1_DIV_CON_SHIFT,
426 				       I2C_DIV_CON_WIDTH);
427 		break;
428 	case SCLK_I2C2:
429 		con = readl(&cru->clksel_con[20]);
430 		div = bitfield_extract(con, CLK_I2C2_DIV_CON_SHIFT,
431 				       I2C_DIV_CON_WIDTH);
432 		break;
433 	case SCLK_I2C3:
434 		con = readl(&cru->clksel_con[20]);
435 		div = bitfield_extract(con, CLK_I2C3_DIV_CON_SHIFT,
436 				       I2C_DIV_CON_WIDTH);
437 		break;
438 	default:
439 		printf("do not support this i2c bus\n");
440 		return -EINVAL;
441 	}
442 
443 	return DIV_TO_RATE(GPLL_HZ, div);
444 }
445 
446 static ulong rv1108_i2c_set_clk(struct rv1108_cru *cru, ulong clk_id, uint hz)
447 {
448 	int src_clk_div;
449 
450 	/* i2c0,4,8 src clock from ppll, i2c1,2,3,5,6,7 src clock from gpll*/
451 	src_clk_div = GPLL_HZ / hz;
452 	assert(src_clk_div - 1 <= 127);
453 
454 	switch (clk_id) {
455 	case SCLK_I2C0_PMU:
456 		rk_clrsetreg(&cru->clksel_con[19],
457 			     CLK_I2C0_DIV_CON_MASK | CLK_I2C1_PLL_SEL_MASK,
458 			     (src_clk_div << CLK_I2C0_DIV_CON_SHIFT) |
459 			     (CLK_I2C1_PLL_SEL_GPLL << CLK_I2C1_PLL_SEL_SHIFT));
460 		break;
461 	case SCLK_I2C1:
462 		rk_clrsetreg(&cru->clksel_con[19],
463 			     CLK_I2C1_DIV_CON_MASK | CLK_I2C1_PLL_SEL_MASK,
464 			     (src_clk_div << CLK_I2C1_DIV_CON_SHIFT) |
465 			     (CLK_I2C1_PLL_SEL_GPLL << CLK_I2C1_PLL_SEL_SHIFT));
466 		break;
467 	case SCLK_I2C2:
468 		rk_clrsetreg(&cru->clksel_con[20],
469 			     CLK_I2C2_DIV_CON_MASK | CLK_I2C3_PLL_SEL_MASK,
470 			     (src_clk_div << CLK_I2C2_DIV_CON_SHIFT) |
471 			     (CLK_I2C3_PLL_SEL_GPLL << CLK_I2C3_PLL_SEL_SHIFT));
472 		break;
473 	case SCLK_I2C3:
474 		rk_clrsetreg(&cru->clksel_con[20],
475 			     CLK_I2C3_DIV_CON_MASK | CLK_I2C3_PLL_SEL_MASK,
476 			     (src_clk_div << CLK_I2C3_DIV_CON_SHIFT) |
477 			     (CLK_I2C3_PLL_SEL_GPLL << CLK_I2C3_PLL_SEL_SHIFT));
478 		break;
479 	default:
480 		printf("do not support this i2c bus\n");
481 		return -EINVAL;
482 	}
483 
484 	return rv1108_i2c_get_clk(cru, clk_id);
485 }
486 
487 static ulong rv1108_mmc_get_clk(struct rv1108_cru *cru)
488 {
489 	u32 div, con;
490 	ulong mmc_clk;
491 
492 	con = readl(&cru->clksel_con[26]);
493 	div = bitfield_extract(con, EMMC_CLK_DIV_SHIFT, 8);
494 
495 	con = readl(&cru->clksel_con[25]);
496 
497 	if ((con & EMMC_PLL_SEL_MASK) >> EMMC_PLL_SEL_SHIFT == EMMC_PLL_SEL_OSC)
498 		mmc_clk = DIV_TO_RATE(OSC_HZ, div) / 2;
499 	else
500 		mmc_clk = DIV_TO_RATE(GPLL_HZ, div) / 2;
501 
502 	debug("%s div %d get_clk %ld\n", __func__, div, mmc_clk);
503 	return mmc_clk;
504 }
505 
506 static ulong rv1108_mmc_set_clk(struct rv1108_cru *cru, ulong rate)
507 {
508 	int div;
509 	u32 pll_rate;
510 
511 	div = DIV_ROUND_UP(rkclk_pll_get_rate(cru, CLK_GENERAL), rate);
512 
513 	if (div < 127) {
514 		debug("%s source gpll\n", __func__);
515 		rk_clrsetreg(&cru->clksel_con[25], EMMC_PLL_SEL_MASK,
516 			    (EMMC_PLL_SEL_GPLL << EMMC_PLL_SEL_SHIFT));
517 		pll_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
518 	} else {
519 		debug("%s source 24m\n", __func__);
520 		rk_clrsetreg(&cru->clksel_con[25], EMMC_PLL_SEL_MASK,
521 			    (EMMC_PLL_SEL_OSC << EMMC_PLL_SEL_SHIFT));
522 		pll_rate = OSC_HZ;
523 	}
524 
525 	div = DIV_ROUND_UP(pll_rate / 2, rate);
526 	rk_clrsetreg(&cru->clksel_con[26], EMMC_CLK_DIV_MASK,
527 		    ((div - 1) << EMMC_CLK_DIV_SHIFT));
528 
529 	debug("%s set_rate %ld div %d\n", __func__,  rate, div);
530 
531 	return DIV_TO_RATE(pll_rate, div);
532 }
533 
534 static ulong rv1108_clk_get_rate(struct clk *clk)
535 {
536 	struct rv1108_clk_priv *priv = dev_get_priv(clk->dev);
537 
538 	switch (clk->id) {
539 	case 0 ... 63:
540 		return rkclk_pll_get_rate(priv->cru, clk->id);
541 	case SCLK_SARADC:
542 		return rv1108_saradc_get_clk(priv->cru);
543 	case ACLK_VIO0:
544 		return rv1108_aclk_vio0_get_clk(priv->cru);
545 	case ACLK_VIO1:
546 		return rv1108_aclk_vio1_get_clk(priv->cru);
547 	case DCLK_VOP:
548 		return rv1108_dclk_vop_get_clk(priv->cru);
549 	case ACLK_PRE:
550 		return rv1108_aclk_bus_get_clk(priv->cru);
551 	case ACLK_PERI:
552 		return rv1108_aclk_peri_get_clk(priv->cru);
553 	case HCLK_PERI:
554 		return rv1108_hclk_peri_get_clk(priv->cru);
555 	case PCLK_PERI:
556 		return rv1108_pclk_peri_get_clk(priv->cru);
557 	case SCLK_I2C0_PMU:
558 	case SCLK_I2C1:
559 	case SCLK_I2C2:
560 	case SCLK_I2C3:
561 		return rv1108_i2c_get_clk(priv->cru, clk->id);
562 	case HCLK_EMMC:
563 	case SCLK_EMMC:
564 	case SCLK_EMMC_SAMPLE:
565 		return rv1108_mmc_get_clk(priv->cru);
566 	default:
567 		return -ENOENT;
568 	}
569 }
570 
571 static ulong rv1108_clk_set_rate(struct clk *clk, ulong rate)
572 {
573 	struct rv1108_clk_priv *priv = dev_get_priv(clk->dev);
574 	ulong new_rate;
575 
576 	switch (clk->id) {
577 	case SCLK_MAC:
578 		new_rate = rv1108_mac_set_clk(priv->cru, rate);
579 		break;
580 	case SCLK_SFC:
581 		new_rate = rv1108_sfc_set_clk(priv->cru, rate);
582 		break;
583 	case SCLK_SARADC:
584 		new_rate = rv1108_saradc_set_clk(priv->cru, rate);
585 		break;
586 	case ACLK_VIO0:
587 		new_rate = rv1108_aclk_vio0_set_clk(priv->cru, rate);
588 		break;
589 	case ACLK_VIO1:
590 		new_rate = rv1108_aclk_vio1_set_clk(priv->cru, rate);
591 		break;
592 	case DCLK_VOP:
593 		new_rate = rv1108_dclk_vop_set_clk(priv->cru, rate);
594 		break;
595 	case ACLK_PRE:
596 		new_rate = rv1108_aclk_bus_set_clk(priv->cru, rate);
597 		break;
598 	case ACLK_PERI:
599 		new_rate = rv1108_aclk_peri_set_clk(priv->cru, rate);
600 		break;
601 	case HCLK_PERI:
602 		new_rate = rv1108_hclk_peri_set_clk(priv->cru, rate);
603 		break;
604 	case PCLK_PERI:
605 		new_rate = rv1108_pclk_peri_set_clk(priv->cru, rate);
606 		break;
607 	case SCLK_I2C0_PMU:
608 	case SCLK_I2C1:
609 	case SCLK_I2C2:
610 	case SCLK_I2C3:
611 		new_rate = rv1108_i2c_set_clk(priv->cru, clk->id, rate);
612 		break;
613 	case HCLK_EMMC:
614 	case SCLK_EMMC:
615 		new_rate = rv1108_mmc_set_clk(priv->cru, rate);
616 		break;
617 	default:
618 		return -ENOENT;
619 	}
620 
621 	return new_rate;
622 }
623 
624 static const struct clk_ops rv1108_clk_ops = {
625 	.get_rate	= rv1108_clk_get_rate,
626 	.set_rate	= rv1108_clk_set_rate,
627 };
628 
629 static void rkclk_init(struct rv1108_cru *cru)
630 {
631 	unsigned int apll, dpll, gpll;
632 	unsigned int aclk_bus, aclk_peri, hclk_peri, pclk_peri;
633 
634 	aclk_bus = rv1108_aclk_bus_set_clk(cru, ACLK_BUS_HZ / 2);
635 	aclk_peri = rv1108_aclk_peri_set_clk(cru, ACLK_PERI_HZ / 2);
636 	hclk_peri = rv1108_hclk_peri_set_clk(cru, HCLK_PERI_HZ / 2);
637 	pclk_peri = rv1108_pclk_peri_set_clk(cru, PCLK_PERI_HZ / 2);
638 	rv1108_aclk_vio0_set_clk(cru, 297000000);
639 	rv1108_aclk_vio1_set_clk(cru, 297000000);
640 
641 	/* configure apll */
642 	rkclk_set_pll(cru, CLK_ARM, &apll_init_cfg);
643 	rkclk_set_pll(cru, CLK_GENERAL, &gpll_init_cfg);
644 	aclk_bus = rv1108_aclk_bus_set_clk(cru, ACLK_BUS_HZ);
645 	aclk_peri = rv1108_aclk_peri_set_clk(cru, ACLK_PERI_HZ);
646 	hclk_peri = rv1108_hclk_peri_set_clk(cru, HCLK_PERI_HZ);
647 	pclk_peri = rv1108_pclk_peri_set_clk(cru, PCLK_PERI_HZ);
648 
649 	apll = rkclk_pll_get_rate(cru, CLK_ARM);
650 	dpll = rkclk_pll_get_rate(cru, CLK_DDR);
651 	gpll = rkclk_pll_get_rate(cru, CLK_GENERAL);
652 
653 	rk_clrsetreg(&cru->clksel_con[0], CORE_CLK_DIV_MASK,
654 		     0 << MAC_CLK_DIV_SHIFT);
655 
656 	printf("APLL: %d DPLL:%d GPLL:%d\n", apll, dpll, gpll);
657 	printf("ACLK_BUS: %d ACLK_PERI:%d HCLK_PERI:%d PCLK_PERI:%d\n",
658 	       aclk_bus, aclk_peri, hclk_peri, pclk_peri);
659 }
660 
661 static int rv1108_clk_ofdata_to_platdata(struct udevice *dev)
662 {
663 	struct rv1108_clk_priv *priv = dev_get_priv(dev);
664 
665 	priv->cru = dev_read_addr_ptr(dev);
666 
667 	return 0;
668 }
669 
670 static int rv1108_clk_probe(struct udevice *dev)
671 {
672 	struct rv1108_clk_priv *priv = dev_get_priv(dev);
673 
674 	rkclk_init(priv->cru);
675 
676 	return 0;
677 }
678 
679 static int rv1108_clk_bind(struct udevice *dev)
680 {
681 	int ret;
682 	struct udevice *sys_child, *sf_child;
683 	struct sysreset_reg *priv;
684 	struct softreset_reg *sf_priv;
685 
686 	/* The reset driver does not have a device node, so bind it here */
687 	ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset",
688 				 &sys_child);
689 	if (ret) {
690 		debug("Warning: No sysreset driver: ret=%d\n", ret);
691 	} else {
692 		priv = malloc(sizeof(struct sysreset_reg));
693 		priv->glb_srst_fst_value = offsetof(struct rv1108_cru,
694 						    glb_srst_fst_val);
695 		priv->glb_srst_snd_value = offsetof(struct rv1108_cru,
696 						    glb_srst_snd_val);
697 		sys_child->priv = priv;
698 	}
699 
700 #if CONFIG_IS_ENABLED(CONFIG_RESET_ROCKCHIP)
701 	ret = offsetof(struct rk3368_cru, softrst_con[0]);
702 	ret = rockchip_reset_bind(dev, ret, 13);
703 	if (ret)
704 		debug("Warning: software reset driver bind faile\n");
705 #endif
706 	ret = device_bind_driver_to_node(dev, "rockchip_reset", "reset",
707 					 dev_ofnode(dev), &sf_child);
708 	if (ret) {
709 		debug("Warning: No rockchip reset driver: ret=%d\n", ret);
710 	} else {
711 		sf_priv = malloc(sizeof(struct softreset_reg));
712 		sf_priv->sf_reset_offset = offsetof(struct rv1108_cru,
713 						    softrst_con[0]);
714 		sf_priv->sf_reset_num = 13;
715 		sf_child->priv = sf_priv;
716 	}
717 
718 	return 0;
719 }
720 
721 static const struct udevice_id rv1108_clk_ids[] = {
722 	{ .compatible = "rockchip,rv1108-cru" },
723 	{ }
724 };
725 
726 U_BOOT_DRIVER(clk_rv1108) = {
727 	.name		= "clk_rv1108",
728 	.id		= UCLASS_CLK,
729 	.of_match	= rv1108_clk_ids,
730 	.priv_auto_alloc_size = sizeof(struct rv1108_clk_priv),
731 	.ops		= &rv1108_clk_ops,
732 	.bind		= rv1108_clk_bind,
733 	.ofdata_to_platdata	= rv1108_clk_ofdata_to_platdata,
734 	.probe		= rv1108_clk_probe,
735 };
736