xref: /rk3399_rockchip-uboot/drivers/clk/rockchip/clk_rk3308.c (revision a66fd6dcbc6344967fabd3e7a5f8ec6bb585d0e2)
1 /*
2  * (C) Copyright 2017 Rockchip Electronics Co., Ltd
3  *
4  * SPDX-License-Identifier:	GPL-2.0
5  */
6 #include <common.h>
7 #include <bitfield.h>
8 #include <clk-uclass.h>
9 #include <dm.h>
10 #include <errno.h>
11 #include <syscon.h>
12 #include <asm/arch/clock.h>
13 #include <asm/arch/cru_rk3308.h>
14 #include <asm/arch/hardware.h>
15 #include <asm/io.h>
16 #include <dm/lists.h>
17 #include <dt-bindings/clock/rk3308-cru.h>
18 
19 DECLARE_GLOBAL_DATA_PTR;
20 
21 enum {
22 	VCO_MAX_HZ	= 3200U * 1000000,
23 	VCO_MIN_HZ	= 800 * 1000000,
24 	OUTPUT_MAX_HZ	= 3200U * 1000000,
25 	OUTPUT_MIN_HZ	= 24 * 1000000,
26 };
27 
28 #define DIV_TO_RATE(input_rate, div)    ((input_rate) / ((div) + 1))
29 
30 #define PLL_DIVISORS(hz, _refdiv, _postdiv1, _postdiv2) {\
31 	.refdiv = _refdiv,\
32 	.fbdiv = (u32)((u64)hz * _refdiv * _postdiv1 * _postdiv2 / OSC_HZ),\
33 	.postdiv1 = _postdiv1, .postdiv2 = _postdiv2};
34 
35 static const struct pll_div apll_816_cfg = PLL_DIVISORS(816 * MHz, 1, 2, 1);
36 
37 static u8 pll_mode_shift[PLL_COUNT] = {
38 	APLL_MODE_SHIFT, DPLL_MODE_SHIFT, VPLL0_MODE_SHIFT,
39 	VPLL1_MODE_SHIFT
40 };
41 
42 static u32 pll_mode_mask[PLL_COUNT] = {
43 	APLL_MODE_MASK, DPLL_MODE_MASK, VPLL0_MODE_MASK,
44 	VPLL1_MODE_MASK
45 };
46 
47 static ulong apll_hz, dpll_hz, vpll0_hz, vpll1_hz;
48 
49 /*
50  * How to calculate the PLL:
51  * Formulas also embedded within the Fractional PLL Verilog model:
52  * If DSMPD = 1 (DSM is disabled, "integer mode")
53  * FOUTVCO = FREF / REFDIV * FBDIV
54  * FOUTPOSTDIV = FOUTVCO / POSTDIV1 / POSTDIV2
55  * Where:
56  * FOUTVCO = Fractional PLL non-divided output frequency
57  * FOUTPOSTDIV = Fractional PLL divided output frequency
58  *               (output of second post divider)
59  * FREF = Fractional PLL input reference frequency, (the OSC_HZ 24MHz input)
60  * REFDIV = Fractional PLL input reference clock divider
61  * FBDIV = Integer value programmed into feedback divide
62  *
63  */
64 
65 static void rkclk_set_pll(struct rk3308_cru *cru, enum rk3308_pll_id pll_id,
66 			  const struct pll_div *div)
67 {
68 	struct rk3308_pll *pll;
69 	unsigned int *mode;
70 	/* All PLLs have same VCO and output frequency range restrictions. */
71 	uint vco_hz = OSC_HZ / 1000 * div->fbdiv / div->refdiv * 1000;
72 	uint output_hz = vco_hz / div->postdiv1 / div->postdiv2;
73 
74 	pll = &cru->pll[pll_id];
75 	mode = &cru->mode;
76 
77 	debug("PLL at %p: fb=%d, ref=%d, pst1=%d, pst2=%d, vco=%u Hz, output=%u Hz\n",
78 	      pll, div->fbdiv, div->refdiv, div->postdiv1,
79 	      div->postdiv2, vco_hz, output_hz);
80 	assert(vco_hz >= VCO_MIN_HZ && vco_hz <= VCO_MAX_HZ &&
81 	       output_hz >= OUTPUT_MIN_HZ && output_hz <= OUTPUT_MAX_HZ);
82 
83 	/*
84 	 * When power on or changing PLL setting,
85 	 * we must force PLL into slow mode to ensure output stable clock.
86 	 */
87 	rk_clrsetreg(mode, pll_mode_mask[pll_id],
88 		     PLLMUX_FROM_XIN24M << pll_mode_shift[pll_id]);
89 
90 	/* use integer mode */
91 	rk_setreg(&pll->con1, 1 << PLL_DSMPD_SHIFT);
92 	/* Power down */
93 	rk_setreg(&pll->con1, 1 << PLL_PD_SHIFT);
94 
95 	rk_clrsetreg(&pll->con0,
96 		     PLL_POSTDIV1_MASK | PLL_FBDIV_MASK,
97 		     (div->postdiv1 << PLL_POSTDIV1_SHIFT) | div->fbdiv);
98 	rk_clrsetreg(&pll->con1, PLL_POSTDIV2_MASK | PLL_REFDIV_MASK,
99 		     (div->postdiv2 << PLL_POSTDIV2_SHIFT |
100 		     div->refdiv << PLL_REFDIV_SHIFT));
101 
102 	/* Power Up */
103 	rk_clrreg(&pll->con1, 1 << PLL_PD_SHIFT);
104 
105 	/* waiting for pll lock */
106 	while (!(readl(&pll->con1) & (1 << PLL_LOCK_STATUS_SHIFT)))
107 		udelay(1);
108 
109 	rk_clrsetreg(mode, pll_mode_mask[pll_id],
110 		     PLLMUX_FROM_PLL << pll_mode_shift[pll_id]);
111 }
112 
113 static uint32_t rkclk_pll_get_rate(struct rk3308_cru *cru,
114 				   enum rk3308_pll_id pll_id)
115 {
116 	u32 refdiv, fbdiv, postdiv1, postdiv2;
117 	u32 con;
118 	struct rk3308_pll *pll;
119 	uint shift;
120 	uint mask;
121 
122 	pll = &cru->pll[pll_id];
123 	con = readl(&cru->mode);
124 
125 	shift = pll_mode_shift[pll_id];
126 	mask = pll_mode_mask[pll_id];
127 
128 	switch ((con & mask) >> shift) {
129 	case PLLMUX_FROM_XIN24M:
130 		return OSC_HZ;
131 	case PLLMUX_FROM_PLL:
132 		/* normal mode */
133 		con = readl(&pll->con0);
134 		postdiv1 = (con & PLL_POSTDIV1_MASK) >> PLL_POSTDIV1_SHIFT;
135 		fbdiv = (con & PLL_FBDIV_MASK) >> PLL_FBDIV_SHIFT;
136 		con = readl(&pll->con1);
137 		postdiv2 = (con & PLL_POSTDIV2_MASK) >> PLL_POSTDIV2_SHIFT;
138 		refdiv = (con & PLL_REFDIV_MASK) >> PLL_REFDIV_SHIFT;
139 		return (24 * fbdiv / (refdiv * postdiv1 * postdiv2)) * 1000000;
140 	case PLLMUX_FROM_RTC32K:
141 	default:
142 		return 32768;
143 	}
144 }
145 
146 static void rkclk_init(struct rk3308_cru *cru)
147 {
148 	u32 aclk_div, hclk_div, pclk_div;
149 
150 	/* init pll */
151 	rkclk_set_pll(cru, APLL, &apll_816_cfg);
152 
153 	/*
154 	 * select apll as cpu/core clock pll source and
155 	 * set up dependent divisors for PCLK and ACLK clocks.
156 	 * core hz : apll = 1:1
157 	 */
158 	apll_hz = rkclk_pll_get_rate(cru, APLL);
159 	aclk_div = apll_hz / CORE_ACLK_HZ - 1;
160 	pclk_div = apll_hz / CORE_DBG_HZ - 1;
161 	rk_clrsetreg(&cru->clksel_con[0],
162 		     CORE_ACLK_DIV_MASK | CORE_DBG_DIV_MASK |
163 		     CORE_CLK_PLL_SEL_MASK | CORE_DIV_CON_MASK,
164 		     aclk_div << CORE_ACLK_DIV_SHIFT |
165 		     pclk_div << CORE_DBG_DIV_SHIFT |
166 		     CORE_CLK_PLL_SEL_APLL << CORE_CLK_PLL_SEL_SHIFT |
167 		     0 << CORE_DIV_CON_SHIFT);
168 
169 	/*
170 	 * select dpll as pd_bus bus clock source and
171 	 * set up dependent divisors for PCLK/HCLK and ACLK clocks.
172 	 */
173 	dpll_hz = rkclk_pll_get_rate(cru, DPLL);
174 	aclk_div = dpll_hz / BUS_ACLK_HZ - 1;
175 	hclk_div = dpll_hz / BUS_HCLK_HZ - 1;
176 	pclk_div = dpll_hz / BUS_PCLK_HZ - 1;
177 	rk_clrsetreg(&cru->clksel_con[5],
178 		     BUS_PLL_SEL_MASK | BUS_ACLK_DIV_MASK,
179 		     BUS_PLL_SEL_DPLL << BUS_PLL_SEL_SHIFT |
180 		     aclk_div << BUS_ACLK_DIV_SHIFT);
181 	rk_clrsetreg(&cru->clksel_con[6],
182 		     BUS_PCLK_DIV_MASK | BUS_HCLK_DIV_MASK,
183 		     pclk_div << BUS_PCLK_DIV_SHIFT |
184 		     hclk_div << BUS_HCLK_DIV_SHIFT);
185 
186 	/*
187 	 * select dpll as pd_peri bus clock source and
188 	 * set up dependent divisors for PCLK/HCLK and ACLK clocks.
189 	 */
190 	aclk_div = dpll_hz / PERI_ACLK_HZ - 1;
191 	hclk_div = dpll_hz / PERI_HCLK_HZ - 1;
192 	pclk_div = dpll_hz / PERI_PCLK_HZ - 1;
193 	rk_clrsetreg(&cru->clksel_con[36],
194 		     PERI_PLL_SEL_MASK | PERI_ACLK_DIV_MASK,
195 		     BUS_PLL_SEL_DPLL << PERI_PLL_SEL_SHIFT |
196 		     aclk_div << PERI_ACLK_DIV_SHIFT);
197 	rk_clrsetreg(&cru->clksel_con[37],
198 		     PERI_PCLK_DIV_MASK | PERI_HCLK_DIV_MASK,
199 		     pclk_div << PERI_PCLK_DIV_SHIFT |
200 		     hclk_div << PERI_HCLK_DIV_SHIFT);
201 
202 	vpll0_hz = rkclk_pll_get_rate(cru, VPLL0);
203 	vpll1_hz = rkclk_pll_get_rate(cru, VPLL1);
204 }
205 
206 static ulong rk3308_i2c_get_clk(struct rk3308_cru *cru, ulong clk_id)
207 {
208 	u32 div, con, con_id;
209 
210 	switch (clk_id) {
211 	case SCLK_I2C0:
212 		con_id = 25;
213 		break;
214 	case SCLK_I2C1:
215 		con_id = 26;
216 		break;
217 	case SCLK_I2C2:
218 		con_id = 27;
219 		break;
220 	case SCLK_I2C3:
221 		con_id = 28;
222 		break;
223 	default:
224 		printf("do not support this i2c bus\n");
225 		return -EINVAL;
226 	}
227 
228 	con = readl(&cru->clksel_con[con_id]);
229 	div = con >> CLK_I2C_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK;
230 
231 	return DIV_TO_RATE(dpll_hz, div);
232 }
233 
234 static ulong rk3308_i2c_set_clk(struct rk3308_cru *cru, ulong clk_id, uint hz)
235 {
236 	u32 src_clk_div, con_id;
237 
238 	src_clk_div = dpll_hz / hz;
239 	assert(src_clk_div - 1 < 127);
240 
241 	switch (clk_id) {
242 	case SCLK_I2C0:
243 		con_id = 25;
244 		break;
245 	case SCLK_I2C1:
246 		con_id = 26;
247 		break;
248 	case SCLK_I2C2:
249 		con_id = 27;
250 		break;
251 	case SCLK_I2C3:
252 		con_id = 28;
253 		break;
254 	default:
255 		printf("do not support this i2c bus\n");
256 		return -EINVAL;
257 	}
258 	rk_clrsetreg(&cru->clksel_con[con_id],
259 		     CLK_I2C_PLL_SEL_MASK | CLK_I2C_DIV_CON_MASK,
260 		     CLK_I2C_PLL_SEL_DPLL << CLK_I2C_PLL_SEL_SHIFT |
261 		     (src_clk_div - 1) << CLK_I2C_DIV_CON_SHIFT);
262 
263 	return rk3308_i2c_get_clk(cru, clk_id);
264 }
265 
266 static ulong rk3308_mmc_get_clk(struct rk3308_cru *cru, uint clk_id)
267 {
268 	u32 div, con, con_id;
269 
270 	switch (clk_id) {
271 	case HCLK_SDMMC:
272 	case SCLK_SDMMC:
273 		con_id = 39;
274 		break;
275 	case HCLK_EMMC:
276 	case SCLK_EMMC:
277 	case SCLK_EMMC_SAMPLE:
278 		con_id = 41;
279 		break;
280 	default:
281 		return -EINVAL;
282 	}
283 
284 	con = readl(&cru->clksel_con[con_id]);
285 	div = (con & EMMC_DIV_MASK) >> EMMC_DIV_SHIFT;
286 
287 	if ((con & EMMC_PLL_MASK) >> EMMC_PLL_SHIFT
288 	    == EMMC_SEL_24M)
289 		return DIV_TO_RATE(OSC_HZ, div) / 2;
290 	else
291 		return DIV_TO_RATE(vpll0_hz, div) / 2;
292 }
293 
294 static ulong rk3308_mmc_set_clk(struct rk3308_cru *cru,
295 				ulong clk_id, ulong set_rate)
296 {
297 	int src_clk_div;
298 	u32 con_id;
299 
300 	debug("%s %ld %ld\n", __func__, clk_id, set_rate);
301 
302 	switch (clk_id) {
303 	case HCLK_SDMMC:
304 	case SCLK_SDMMC:
305 		con_id = 39;
306 		break;
307 	case HCLK_EMMC:
308 	case SCLK_EMMC:
309 		con_id = 41;
310 		break;
311 	default:
312 		return -EINVAL;
313 	}
314 	/* Select clk_sdmmc/emmc source from VPLL0 by default */
315 	/* mmc clock defaulg div 2 internal, need provide double in cru */
316 	src_clk_div = DIV_ROUND_UP(vpll0_hz / 2, set_rate);
317 
318 	if (src_clk_div > 127) {
319 		/* use 24MHz source for 400KHz clock */
320 		src_clk_div = DIV_ROUND_UP(OSC_HZ / 2, set_rate);
321 		rk_clrsetreg(&cru->clksel_con[con_id],
322 			     EMMC_PLL_MASK | EMMC_DIV_MASK | EMMC_CLK_SEL_MASK,
323 			     EMMC_CLK_SEL_EMMC << EMMC_CLK_SEL_SHIFT |
324 			     EMMC_SEL_24M << EMMC_PLL_SHIFT |
325 			     (src_clk_div - 1) << EMMC_DIV_SHIFT);
326 	} else {
327 		rk_clrsetreg(&cru->clksel_con[con_id],
328 			     EMMC_PLL_MASK | EMMC_DIV_MASK | EMMC_CLK_SEL_MASK,
329 			     EMMC_CLK_SEL_EMMC << EMMC_CLK_SEL_SHIFT |
330 			     EMMC_SEL_VPLL0 << EMMC_PLL_SHIFT |
331 			     (src_clk_div - 1) << EMMC_DIV_SHIFT);
332 	}
333 
334 	return rk3308_mmc_get_clk(cru, clk_id);
335 }
336 
337 static ulong rk3308_saradc_get_clk(struct rk3308_cru *cru)
338 {
339 	u32 div, con;
340 
341 	con = readl(&cru->clksel_con[34]);
342 	div = con >> CLK_SARADC_DIV_CON_SHIFT & CLK_SARADC_DIV_CON_MASK;
343 
344 	return DIV_TO_RATE(OSC_HZ, div);
345 }
346 
347 static ulong rk3308_saradc_set_clk(struct rk3308_cru *cru, uint hz)
348 {
349 	int src_clk_div;
350 
351 	src_clk_div = OSC_HZ / hz;
352 	assert(src_clk_div - 1 < 2047);
353 
354 	rk_clrsetreg(&cru->clksel_con[34],
355 		     CLK_SARADC_DIV_CON_MASK,
356 		     (src_clk_div - 1) << CLK_SARADC_DIV_CON_SHIFT);
357 
358 	return rk3308_saradc_get_clk(cru);
359 }
360 
361 static ulong rk3308_spi_get_clk(struct rk3308_cru *cru, ulong clk_id)
362 {
363 	u32 div, con, con_id;
364 
365 	switch (clk_id) {
366 	case SCLK_SPI0:
367 		con_id = 30;
368 		break;
369 	case SCLK_SPI1:
370 		con_id = 31;
371 		break;
372 	case SCLK_SPI2:
373 		con_id = 32;
374 		break;
375 	default:
376 		printf("do not support this spi bus\n");
377 		return -EINVAL;
378 	}
379 
380 	con = readl(&cru->clksel_con[con_id]);
381 	div = con >> CLK_SPI_DIV_CON_SHIFT & CLK_SPI_DIV_CON_MASK;
382 
383 	return DIV_TO_RATE(dpll_hz, div);
384 }
385 
386 static ulong rk3308_spi_set_clk(struct rk3308_cru *cru, ulong clk_id, uint hz)
387 {
388 	u32 src_clk_div, con_id;
389 
390 	src_clk_div = dpll_hz / hz;
391 	assert(src_clk_div - 1 < 127);
392 
393 	switch (clk_id) {
394 	case SCLK_SPI0:
395 		con_id = 30;
396 		break;
397 	case SCLK_SPI1:
398 		con_id = 31;
399 		break;
400 	case SCLK_SPI2:
401 		con_id = 32;
402 		break;
403 	default:
404 		printf("do not support this spi bus\n");
405 		return -EINVAL;
406 	}
407 
408 	rk_clrsetreg(&cru->clksel_con[con_id],
409 		     CLK_SPI_PLL_SEL_MASK | CLK_SPI_DIV_CON_MASK,
410 		     CLK_SPI_PLL_SEL_DPLL << CLK_SPI_PLL_SEL_SHIFT |
411 		     (src_clk_div - 1) << CLK_SPI_DIV_CON_SHIFT);
412 
413 	return rk3308_spi_get_clk(cru, clk_id);
414 }
415 
416 static ulong rk3308_pwm_get_clk(struct rk3308_cru *cru)
417 {
418 	u32 div, con;
419 
420 	con = readl(&cru->clksel_con[29]);
421 	div = con >> CLK_PWM_DIV_CON_SHIFT & CLK_PWM_DIV_CON_MASK;
422 
423 	return DIV_TO_RATE(dpll_hz, div);
424 }
425 
426 static ulong rk3308_pwm_set_clk(struct rk3308_cru *cru, uint hz)
427 {
428 	int src_clk_div;
429 
430 	src_clk_div = dpll_hz / hz;
431 	assert(src_clk_div - 1 < 127);
432 
433 	rk_clrsetreg(&cru->clksel_con[29],
434 		     CLK_PWM_PLL_SEL_MASK | CLK_PWM_DIV_CON_MASK,
435 		     CLK_PWM_PLL_SEL_DPLL << CLK_PWM_PLL_SEL_SHIFT |
436 		     (src_clk_div - 1) << CLK_PWM_DIV_CON_SHIFT);
437 
438 	return rk3308_pwm_get_clk(cru);
439 }
440 
441 static ulong rk3308_vop_get_clk(struct rk3308_cru *cru)
442 {
443 	u32 div, pll_sel, vol_sel, con, parent;
444 
445 	con = readl(&cru->clksel_con[8]);
446 	vol_sel = (con & DCLK_VOP_SEL_MASK) >> DCLK_VOP_SEL_SHIFT;
447 	pll_sel = (con & DCLK_VOP_PLL_SEL_MASK) >> DCLK_VOP_PLL_SEL_SHIFT;
448 	div = con & DCLK_VOP_DIV_MASK;
449 
450 	if (vol_sel == DCLK_VOP_SEL_24M) {
451 		parent = OSC_HZ;
452 	} else if (vol_sel == DCLK_VOP_SEL_DIVOUT) {
453 		switch (pll_sel) {
454 		case DCLK_VOP_PLL_SEL_DPLL:
455 			parent = rkclk_pll_get_rate(cru, DPLL);
456 			break;
457 		case DCLK_VOP_PLL_SEL_VPLL0:
458 			parent = rkclk_pll_get_rate(cru, VPLL0);
459 			break;
460 		case DCLK_VOP_PLL_SEL_VPLL1:
461 			parent = rkclk_pll_get_rate(cru, VPLL1);
462 			break;
463 		default:
464 			printf("do not support this vop pll sel\n");
465 			return -EINVAL;
466 		}
467 	} else {
468 		printf("do not support this vop sel\n");
469 		return -EINVAL;
470 	}
471 
472 	return DIV_TO_RATE(parent, div);
473 }
474 
475 static ulong rk3308_vop_set_clk(struct rk3308_cru *cru, ulong hz)
476 {
477 	ulong pll_rate, now, best_rate = 0;
478 	u32 i, div, best_div = 0, best_sel = 0;
479 
480 	for (i = 0; i <= DCLK_VOP_PLL_SEL_VPLL1; i++) {
481 		switch (i) {
482 		case DCLK_VOP_PLL_SEL_DPLL:
483 			pll_rate = dpll_hz;
484 			break;
485 		case DCLK_VOP_PLL_SEL_VPLL0:
486 			pll_rate = vpll0_hz;
487 			break;
488 		case DCLK_VOP_PLL_SEL_VPLL1:
489 			pll_rate = vpll1_hz;
490 			break;
491 		default:
492 			printf("do not support this vop pll sel\n");
493 			return -EINVAL;
494 		}
495 
496 		div = DIV_ROUND_UP(pll_rate, hz);
497 		if (div > 255)
498 			continue;
499 		now = pll_rate / div;
500 		if (abs(hz - now) < abs(hz - best_rate)) {
501 			best_rate = now;
502 			best_div = div;
503 			best_sel = i;
504 		}
505 		debug("pll_rate=%lu, best_rate=%lu, best_div=%u, best_sel=%u\n",
506 		      pll_rate, best_rate, best_div, best_sel);
507 	}
508 
509 	if (best_rate != hz && hz == OSC_HZ) {
510 		rk_clrsetreg(&cru->clksel_con[8],
511 			     DCLK_VOP_SEL_MASK,
512 			     DCLK_VOP_SEL_24M << DCLK_VOP_SEL_SHIFT);
513 	} else if (best_rate) {
514 		rk_clrsetreg(&cru->clksel_con[8],
515 			     DCLK_VOP_SEL_MASK | DCLK_VOP_PLL_SEL_MASK |
516 			     DCLK_VOP_DIV_MASK,
517 			     DCLK_VOP_SEL_DIVOUT << DCLK_VOP_SEL_SHIFT |
518 			     best_sel << DCLK_VOP_PLL_SEL_SHIFT |
519 			     (best_div - 1) << DCLK_VOP_DIV_SHIFT);
520 	} else {
521 		printf("do not support this vop freq\n");
522 		return -EINVAL;
523 	}
524 
525 	return rk3308_vop_get_clk(cru);
526 }
527 
528 static ulong rk3308_clk_get_rate(struct clk *clk)
529 {
530 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
531 	ulong rate = 0;
532 
533 	debug("%s id:%ld\n", __func__, clk->id);
534 
535 	switch (clk->id) {
536 	case 0 ... 15:
537 		return 0;
538 	case HCLK_SDMMC:
539 	case HCLK_EMMC:
540 	case SCLK_SDMMC:
541 	case SCLK_EMMC:
542 	case SCLK_EMMC_SAMPLE:
543 		rate = rk3308_mmc_get_clk(priv->cru, clk->id);
544 		break;
545 	case SCLK_I2C0:
546 	case SCLK_I2C1:
547 	case SCLK_I2C2:
548 	case SCLK_I2C3:
549 		rate = rk3308_i2c_get_clk(priv->cru, clk->id);
550 		break;
551 	case SCLK_SARADC:
552 		rate = rk3308_saradc_get_clk(priv->cru);
553 		break;
554 	case SCLK_SPI0:
555 	case SCLK_SPI1:
556 		rate = rk3308_spi_get_clk(priv->cru, clk->id);
557 		break;
558 	case SCLK_PWM:
559 		rate = rk3308_pwm_get_clk(priv->cru);
560 		break;
561 	case DCLK_VOP:
562 		rate = rk3308_vop_get_clk(priv->cru);
563 		break;
564 	default:
565 		return -ENOENT;
566 	}
567 
568 	return rate;
569 }
570 
571 static ulong rk3308_clk_set_rate(struct clk *clk, ulong rate)
572 {
573 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
574 	ulong ret = 0;
575 
576 	debug("%s %ld %ld\n", __func__, clk->id, rate);
577 	switch (clk->id) {
578 	case 0 ... 15:
579 		return 0;
580 	case HCLK_SDMMC:
581 	case HCLK_EMMC:
582 	case SCLK_SDMMC:
583 	case SCLK_EMMC:
584 		ret = rk3308_mmc_set_clk(priv->cru, clk->id, rate);
585 		break;
586 	case SCLK_I2C0:
587 	case SCLK_I2C1:
588 	case SCLK_I2C2:
589 	case SCLK_I2C3:
590 		ret = rk3308_i2c_set_clk(priv->cru, clk->id, rate);
591 		break;
592 	case SCLK_SARADC:
593 		ret = rk3308_saradc_set_clk(priv->cru, rate);
594 		break;
595 	case SCLK_SPI0:
596 	case SCLK_SPI1:
597 		ret = rk3308_spi_set_clk(priv->cru, clk->id, rate);
598 		break;
599 	case SCLK_PWM:
600 		ret = rk3308_pwm_set_clk(priv->cru, rate);
601 		break;
602 	case DCLK_VOP:
603 		ret = rk3308_vop_set_clk(priv->cru, rate);
604 		break;
605 	default:
606 		return -ENOENT;
607 	}
608 
609 	return ret;
610 }
611 
612 #define ROCKCHIP_MMC_DELAY_SEL		BIT(11)
613 #define ROCKCHIP_MMC_DEGREE_OFFSET	1
614 #define ROCKCHIP_MMC_DEGREE_MASK	(0x3 << ROCKCHIP_MMC_DEGREE_OFFSET)
615 #define ROCKCHIP_MMC_DELAYNUM_OFFSET	3
616 #define ROCKCHIP_MMC_DELAYNUM_MASK	(0xff << ROCKCHIP_MMC_DELAYNUM_OFFSET)
617 
618 #define PSECS_PER_SEC 1000000000000LL
619 /*
620  * Each fine delay is between 44ps-77ps. Assume each fine delay is 60ps to
621  * simplify calculations. So 45degs could be anywhere between 33deg and 57.8deg.
622  */
623 #define ROCKCHIP_MMC_DELAY_ELEMENT_PSEC 60
624 
625 int rockchip_mmc_get_phase(struct clk *clk)
626 {
627 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
628 	struct rk3308_cru *cru = priv->cru;
629 	u32 raw_value, delay_num;
630 	u16 degrees = 0;
631 	ulong rate;
632 
633 	rate = rk3308_clk_get_rate(clk);
634 
635 	if (rate < 0)
636 		return rate;
637 
638 	if (clk->id == SCLK_EMMC_SAMPLE)
639 		raw_value = readl(&cru->emmc_con[1]);
640 	else
641 		raw_value = readl(&cru->sdmmc_con[1]);
642 
643 	raw_value &= ROCKCHIP_MMC_DEGREE_MASK;
644 	degrees = (raw_value >>  ROCKCHIP_MMC_DEGREE_OFFSET) * 90;
645 
646 	if (raw_value & ROCKCHIP_MMC_DELAY_SEL) {
647 		/* degrees/delaynum * 10000 */
648 		unsigned long factor = (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10) *
649 					36 * (rate / 1000000);
650 
651 		delay_num = (raw_value & ROCKCHIP_MMC_DELAYNUM_MASK);
652 		delay_num >>= ROCKCHIP_MMC_DELAYNUM_OFFSET;
653 		degrees += DIV_ROUND_CLOSEST(delay_num * factor, 10000);
654 	}
655 
656 	return degrees % 360;
657 
658 }
659 
660 int rockchip_mmc_set_phase(struct clk *clk, u32 degrees)
661 {
662 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
663 	struct rk3308_cru *cru = priv->cru;
664 	u8 nineties, remainder, delay_num;
665 	u32 raw_value, delay;
666 	ulong rate;
667 
668 	rate = rk3308_clk_get_rate(clk);
669 
670 	if (rate < 0)
671 		return rate;
672 
673 	nineties = degrees / 90;
674 	remainder = (degrees % 90);
675 
676 	/*
677 	 * Convert to delay; do a little extra work to make sure we
678 	 * don't overflow 32-bit / 64-bit numbers.
679 	 */
680 	delay = 10000000; /* PSECS_PER_SEC / 10000 / 10 */
681 	delay *= remainder;
682 	delay = DIV_ROUND_CLOSEST(delay, (rate / 1000) * 36 *
683 				(ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10));
684 
685 	delay_num = (u8)min_t(u32, delay, 255);
686 
687 	raw_value = delay_num ? ROCKCHIP_MMC_DELAY_SEL : 0;
688 	raw_value |= delay_num << ROCKCHIP_MMC_DELAYNUM_OFFSET;
689 	raw_value |= nineties << ROCKCHIP_MMC_DEGREE_OFFSET;
690 
691 	if (clk->id == SCLK_EMMC_SAMPLE)
692 		writel(raw_value | 0xffff0000, &cru->emmc_con[1]);
693 	else
694 		writel(raw_value | 0xffff0000, &cru->sdmmc_con[1]);
695 
696 	debug("mmc set_phase(%d) delay_nums=%u reg=%#x actual_degrees=%d\n",
697 	      degrees, delay_num, raw_value, rockchip_mmc_get_phase(clk));
698 
699 	return 0;
700 
701 }
702 
703 static int rk3308_clk_get_phase(struct clk *clk)
704 {
705 	int ret;
706 
707 	switch (clk->id) {
708 	case SCLK_EMMC_SAMPLE:
709 	case SCLK_SDMMC_SAMPLE:
710 		ret = rockchip_mmc_get_phase(clk);
711 		break;
712 	default:
713 		return -ENOENT;
714 	}
715 
716 	return ret;
717 }
718 
719 static int rk3308_clk_set_phase(struct clk *clk, int degrees)
720 {
721 	int ret;
722 
723 	switch (clk->id) {
724 	case SCLK_EMMC_SAMPLE:
725 	case SCLK_SDMMC_SAMPLE:
726 		ret = rockchip_mmc_set_phase(clk, degrees);
727 		break;
728 	default:
729 		return -ENOENT;
730 	}
731 
732 	return ret;
733 }
734 
735 static struct clk_ops rk3308_clk_ops = {
736 	.get_rate = rk3308_clk_get_rate,
737 	.set_rate = rk3308_clk_set_rate,
738 	.get_phase	= rk3308_clk_get_phase,
739 	.set_phase	= rk3308_clk_set_phase,
740 };
741 
742 static int rk3308_clk_probe(struct udevice *dev)
743 {
744 	struct rk3308_clk_priv *priv = dev_get_priv(dev);
745 
746 	rkclk_init(priv->cru);
747 
748 	return 0;
749 }
750 
751 static int rk3308_clk_ofdata_to_platdata(struct udevice *dev)
752 {
753 	struct rk3308_clk_priv *priv = dev_get_priv(dev);
754 
755 	priv->cru = dev_read_addr_ptr(dev);
756 
757 	return 0;
758 }
759 
760 static int rk3308_clk_bind(struct udevice *dev)
761 {
762 	int ret;
763 	struct udevice *sys_child, *sf_child;
764 	struct sysreset_reg *priv;
765 	struct softreset_reg *sf_priv;
766 
767 	/* The reset driver does not have a device node, so bind it here */
768 	ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset",
769 				 &sys_child);
770 	if (ret) {
771 		debug("Warning: No sysreset driver: ret=%d\n", ret);
772 	} else {
773 		priv = malloc(sizeof(struct sysreset_reg));
774 		priv->glb_srst_fst_value = offsetof(struct rk3308_cru,
775 						    glb_srst_fst);
776 		priv->glb_srst_snd_value = offsetof(struct rk3308_cru,
777 						    glb_srst_snd);
778 		sys_child->priv = priv;
779 	}
780 
781 	ret = device_bind_driver_to_node(dev, "rockchip_reset", "reset",
782 					 dev_ofnode(dev), &sf_child);
783 	if (ret) {
784 		debug("Warning: No rockchip reset driver: ret=%d\n", ret);
785 	} else {
786 		sf_priv = malloc(sizeof(struct softreset_reg));
787 		sf_priv->sf_reset_offset = offsetof(struct rk3308_cru,
788 						    softrst_con[0]);
789 		sf_priv->sf_reset_num = 12;
790 		sf_child->priv = sf_priv;
791 	}
792 
793 	return 0;
794 }
795 
796 static const struct udevice_id rk3308_clk_ids[] = {
797 	{ .compatible = "rockchip,rk3308-cru" },
798 	{ }
799 };
800 
801 U_BOOT_DRIVER(rockchip_rk3308_cru) = {
802 	.name		= "rockchip_rk3308_cru",
803 	.id		= UCLASS_CLK,
804 	.of_match	= rk3308_clk_ids,
805 	.priv_auto_alloc_size = sizeof(struct rk3308_clk_priv),
806 	.ofdata_to_platdata = rk3308_clk_ofdata_to_platdata,
807 	.ops		= &rk3308_clk_ops,
808 	.bind		= rk3308_clk_bind,
809 	.probe		= rk3308_clk_probe,
810 };
811