xref: /rk3399_rockchip-uboot/drivers/clk/rockchip/clk_rk3308.c (revision b33ebddfc88565975ea3dfa5b425f2aa45f2da80)
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;
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 vpll0 as pd_peri bus clock source and
188 	 * set up dependent divisors for PCLK/HCLK and ACLK clocks.
189 	 */
190 	vpll0_hz = rkclk_pll_get_rate(cru, VPLL0);
191 	aclk_div = vpll0_hz / PERI_ACLK_HZ - 1;
192 	hclk_div = vpll0_hz / PERI_HCLK_HZ - 1;
193 	pclk_div = vpll0_hz / PERI_PCLK_HZ - 1;
194 	rk_clrsetreg(&cru->clksel_con[36],
195 		     PERI_PLL_SEL_MASK | PERI_ACLK_DIV_MASK,
196 		     PERI_PLL_VPLL0 << PERI_PLL_SEL_SHIFT |
197 		     aclk_div << PERI_ACLK_DIV_SHIFT);
198 	rk_clrsetreg(&cru->clksel_con[37],
199 		     PERI_PCLK_DIV_MASK | PERI_HCLK_DIV_MASK,
200 		     pclk_div << PERI_PCLK_DIV_SHIFT |
201 		     hclk_div << PERI_HCLK_DIV_SHIFT);
202 }
203 
204 static ulong rk3308_i2c_get_clk(struct rk3308_cru *cru, ulong clk_id)
205 {
206 	u32 div, con, con_id;
207 
208 	switch (clk_id) {
209 	case SCLK_I2C0:
210 		con_id = 25;
211 		break;
212 	case SCLK_I2C1:
213 		con_id = 26;
214 		break;
215 	case SCLK_I2C2:
216 		con_id = 27;
217 		break;
218 	case SCLK_I2C3:
219 		con_id = 28;
220 		break;
221 	default:
222 		printf("do not support this i2c bus\n");
223 		return -EINVAL;
224 	}
225 
226 	con = readl(&cru->clksel_con[con_id]);
227 	div = con >> CLK_I2C_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK;
228 
229 	return DIV_TO_RATE(dpll_hz, div);
230 }
231 
232 static ulong rk3308_i2c_set_clk(struct rk3308_cru *cru, ulong clk_id, uint hz)
233 {
234 	u32 src_clk_div, con_id;
235 
236 	src_clk_div = dpll_hz / hz;
237 	assert(src_clk_div - 1 < 127);
238 
239 	switch (clk_id) {
240 	case SCLK_I2C0:
241 		con_id = 25;
242 		break;
243 	case SCLK_I2C1:
244 		con_id = 26;
245 		break;
246 	case SCLK_I2C2:
247 		con_id = 27;
248 		break;
249 	case SCLK_I2C3:
250 		con_id = 28;
251 		break;
252 	default:
253 		printf("do not support this i2c bus\n");
254 		return -EINVAL;
255 	}
256 	rk_clrsetreg(&cru->clksel_con[con_id],
257 		     CLK_I2C_PLL_SEL_MASK | CLK_I2C_DIV_CON_MASK,
258 		     CLK_I2C_PLL_SEL_DPLL << CLK_I2C_PLL_SEL_SHIFT |
259 		     (src_clk_div - 1) << CLK_I2C_DIV_CON_SHIFT);
260 
261 	return rk3308_i2c_get_clk(cru, clk_id);
262 }
263 
264 static ulong rk3308_mmc_get_clk(struct rk3308_cru *cru, uint clk_id)
265 {
266 	u32 div, con, con_id;
267 
268 	switch (clk_id) {
269 	case HCLK_SDMMC:
270 	case SCLK_SDMMC:
271 		con_id = 39;
272 		break;
273 	case HCLK_EMMC:
274 	case SCLK_EMMC:
275 	case SCLK_EMMC_SAMPLE:
276 		con_id = 41;
277 		break;
278 	default:
279 		return -EINVAL;
280 	}
281 
282 	con = readl(&cru->clksel_con[con_id]);
283 	div = (con & EMMC_DIV_MASK) >> EMMC_DIV_SHIFT;
284 
285 	if ((con & EMMC_PLL_MASK) >> EMMC_PLL_SHIFT
286 	    == EMMC_SEL_24M)
287 		return DIV_TO_RATE(OSC_HZ, div) / 2;
288 	else
289 		return DIV_TO_RATE(vpll0_hz, div) / 2;
290 }
291 
292 static ulong rk3308_mmc_set_clk(struct rk3308_cru *cru,
293 				ulong clk_id, ulong set_rate)
294 {
295 	int src_clk_div;
296 	u32 con_id;
297 
298 	debug("%s %ld %ld\n", __func__, clk_id, set_rate);
299 
300 	switch (clk_id) {
301 	case HCLK_SDMMC:
302 	case SCLK_SDMMC:
303 		con_id = 39;
304 		break;
305 	case HCLK_EMMC:
306 	case SCLK_EMMC:
307 		con_id = 41;
308 		break;
309 	default:
310 		return -EINVAL;
311 	}
312 	/* Select clk_sdmmc/emmc source from VPLL0 by default */
313 	/* mmc clock defaulg div 2 internal, need provide double in cru */
314 	src_clk_div = DIV_ROUND_UP(vpll0_hz / 2, set_rate);
315 
316 	if (src_clk_div > 127) {
317 		/* use 24MHz source for 400KHz clock */
318 		src_clk_div = DIV_ROUND_UP(OSC_HZ / 2, set_rate);
319 		rk_clrsetreg(&cru->clksel_con[con_id],
320 			     EMMC_PLL_MASK | EMMC_DIV_MASK | EMMC_CLK_SEL_MASK,
321 			     EMMC_CLK_SEL_EMMC << EMMC_CLK_SEL_SHIFT |
322 			     EMMC_SEL_24M << EMMC_PLL_SHIFT |
323 			     (src_clk_div - 1) << EMMC_DIV_SHIFT);
324 	} else {
325 		rk_clrsetreg(&cru->clksel_con[con_id],
326 			     EMMC_PLL_MASK | EMMC_DIV_MASK | EMMC_CLK_SEL_MASK,
327 			     EMMC_CLK_SEL_EMMC << EMMC_CLK_SEL_SHIFT |
328 			     EMMC_SEL_VPLL0 << EMMC_PLL_SHIFT |
329 			     (src_clk_div - 1) << EMMC_DIV_SHIFT);
330 	}
331 
332 	return rk3308_mmc_get_clk(cru, clk_id);
333 }
334 
335 static ulong rk3308_saradc_get_clk(struct rk3308_cru *cru)
336 {
337 	u32 div, con;
338 
339 	con = readl(&cru->clksel_con[34]);
340 	div = con >> CLK_SARADC_DIV_CON_SHIFT & CLK_SARADC_DIV_CON_MASK;
341 
342 	return DIV_TO_RATE(OSC_HZ, div);
343 }
344 
345 static ulong rk3308_saradc_set_clk(struct rk3308_cru *cru, uint hz)
346 {
347 	int src_clk_div;
348 
349 	src_clk_div = OSC_HZ / hz;
350 	assert(src_clk_div - 1 < 2047);
351 
352 	rk_clrsetreg(&cru->clksel_con[34],
353 		     CLK_SARADC_DIV_CON_MASK,
354 		     (src_clk_div - 1) << CLK_SARADC_DIV_CON_SHIFT);
355 
356 	return rk3308_saradc_get_clk(cru);
357 }
358 
359 static ulong rk3308_spi_get_clk(struct rk3308_cru *cru, ulong clk_id)
360 {
361 	u32 div, con, con_id;
362 
363 	switch (clk_id) {
364 	case SCLK_SPI0:
365 		con_id = 30;
366 		break;
367 	case SCLK_SPI1:
368 		con_id = 31;
369 		break;
370 	case SCLK_SPI2:
371 		con_id = 32;
372 		break;
373 	default:
374 		printf("do not support this spi bus\n");
375 		return -EINVAL;
376 	}
377 
378 	con = readl(&cru->clksel_con[con_id]);
379 	div = con >> CLK_SPI_DIV_CON_SHIFT & CLK_SPI_DIV_CON_MASK;
380 
381 	return DIV_TO_RATE(dpll_hz, div);
382 }
383 
384 static ulong rk3308_spi_set_clk(struct rk3308_cru *cru, ulong clk_id, uint hz)
385 {
386 	u32 src_clk_div, con_id;
387 
388 	src_clk_div = dpll_hz / hz;
389 	assert(src_clk_div - 1 < 127);
390 
391 	switch (clk_id) {
392 	case SCLK_SPI0:
393 		con_id = 30;
394 		break;
395 	case SCLK_SPI1:
396 		con_id = 31;
397 		break;
398 	case SCLK_SPI2:
399 		con_id = 32;
400 		break;
401 	default:
402 		printf("do not support this spi bus\n");
403 		return -EINVAL;
404 	}
405 
406 	rk_clrsetreg(&cru->clksel_con[con_id],
407 		     CLK_SPI_PLL_SEL_MASK | CLK_SPI_DIV_CON_MASK,
408 		     CLK_SPI_PLL_SEL_DPLL << CLK_SPI_PLL_SEL_SHIFT |
409 		     (src_clk_div - 1) << CLK_SPI_DIV_CON_SHIFT);
410 
411 	return rk3308_spi_get_clk(cru, clk_id);
412 }
413 
414 static ulong rk3308_pwm_get_clk(struct rk3308_cru *cru)
415 {
416 	u32 div, con;
417 
418 	con = readl(&cru->clksel_con[29]);
419 	div = con >> CLK_PWM_DIV_CON_SHIFT & CLK_PWM_DIV_CON_MASK;
420 
421 	return DIV_TO_RATE(dpll_hz, div);
422 }
423 
424 static ulong rk3308_pwm_set_clk(struct rk3308_cru *cru, uint hz)
425 {
426 	int src_clk_div;
427 
428 	src_clk_div = dpll_hz / hz;
429 	assert(src_clk_div - 1 < 127);
430 
431 	rk_clrsetreg(&cru->clksel_con[29],
432 		     CLK_PWM_PLL_SEL_MASK | CLK_PWM_DIV_CON_MASK,
433 		     CLK_PWM_PLL_SEL_DPLL << CLK_PWM_PLL_SEL_SHIFT |
434 		     (src_clk_div - 1) << CLK_PWM_DIV_CON_SHIFT);
435 
436 	return rk3308_pwm_get_clk(cru);
437 }
438 
439 static ulong rk3308_clk_get_rate(struct clk *clk)
440 {
441 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
442 	ulong rate = 0;
443 
444 	debug("%s id:%ld\n", __func__, clk->id);
445 
446 	switch (clk->id) {
447 	case 0 ... 15:
448 		return 0;
449 	case HCLK_SDMMC:
450 	case HCLK_EMMC:
451 	case SCLK_SDMMC:
452 	case SCLK_EMMC:
453 	case SCLK_EMMC_SAMPLE:
454 		rate = rk3308_mmc_get_clk(priv->cru, clk->id);
455 		break;
456 	case SCLK_I2C0:
457 	case SCLK_I2C1:
458 	case SCLK_I2C2:
459 	case SCLK_I2C3:
460 		rate = rk3308_i2c_get_clk(priv->cru, clk->id);
461 		break;
462 	case SCLK_SARADC:
463 		rate = rk3308_saradc_get_clk(priv->cru);
464 		break;
465 	case SCLK_SPI0:
466 	case SCLK_SPI1:
467 		rate = rk3308_spi_get_clk(priv->cru, clk->id);
468 		break;
469 	case SCLK_PWM:
470 		rate = rk3308_pwm_get_clk(priv->cru);
471 		break;
472 	default:
473 		return -ENOENT;
474 	}
475 
476 	return rate;
477 }
478 
479 static ulong rk3308_clk_set_rate(struct clk *clk, ulong rate)
480 {
481 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
482 	ulong ret = 0;
483 
484 	debug("%s %ld %ld\n", __func__, clk->id, rate);
485 	switch (clk->id) {
486 	case 0 ... 15:
487 		return 0;
488 	case HCLK_SDMMC:
489 	case HCLK_EMMC:
490 	case SCLK_SDMMC:
491 	case SCLK_EMMC:
492 		ret = rk3308_mmc_set_clk(priv->cru, clk->id, rate);
493 		break;
494 	case SCLK_I2C0:
495 	case SCLK_I2C1:
496 	case SCLK_I2C2:
497 	case SCLK_I2C3:
498 		ret = rk3308_i2c_set_clk(priv->cru, clk->id, rate);
499 		break;
500 	case SCLK_SARADC:
501 		ret = rk3308_saradc_set_clk(priv->cru, rate);
502 		break;
503 	case SCLK_SPI0:
504 	case SCLK_SPI1:
505 		ret = rk3308_spi_set_clk(priv->cru, clk->id, rate);
506 		break;
507 	case SCLK_PWM:
508 		ret = rk3308_pwm_set_clk(priv->cru, rate);
509 		break;
510 	default:
511 		return -ENOENT;
512 	}
513 
514 	return ret;
515 }
516 
517 #define ROCKCHIP_MMC_DELAY_SEL		BIT(11)
518 #define ROCKCHIP_MMC_DEGREE_OFFSET	1
519 #define ROCKCHIP_MMC_DEGREE_MASK	(0x3 << ROCKCHIP_MMC_DEGREE_OFFSET)
520 #define ROCKCHIP_MMC_DELAYNUM_OFFSET	3
521 #define ROCKCHIP_MMC_DELAYNUM_MASK	(0xff << ROCKCHIP_MMC_DELAYNUM_OFFSET)
522 
523 #define PSECS_PER_SEC 1000000000000LL
524 /*
525  * Each fine delay is between 44ps-77ps. Assume each fine delay is 60ps to
526  * simplify calculations. So 45degs could be anywhere between 33deg and 57.8deg.
527  */
528 #define ROCKCHIP_MMC_DELAY_ELEMENT_PSEC 60
529 
530 int rockchip_mmc_get_phase(struct clk *clk)
531 {
532 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
533 	struct rk3308_cru *cru = priv->cru;
534 	u32 raw_value, delay_num;
535 	u16 degrees = 0;
536 	ulong rate;
537 
538 	rate = rk3308_clk_get_rate(clk);
539 
540 	if (rate < 0)
541 		return rate;
542 
543 	if (clk->id == SCLK_EMMC_SAMPLE)
544 		raw_value = readl(&cru->emmc_con[1]);
545 	else
546 		raw_value = readl(&cru->sdmmc_con[1]);
547 
548 	raw_value &= ROCKCHIP_MMC_DEGREE_MASK;
549 	degrees = (raw_value >>  ROCKCHIP_MMC_DEGREE_OFFSET) * 90;
550 
551 	if (raw_value & ROCKCHIP_MMC_DELAY_SEL) {
552 		/* degrees/delaynum * 10000 */
553 		unsigned long factor = (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10) *
554 					36 * (rate / 1000000);
555 
556 		delay_num = (raw_value & ROCKCHIP_MMC_DELAYNUM_MASK);
557 		delay_num >>= ROCKCHIP_MMC_DELAYNUM_OFFSET;
558 		degrees += DIV_ROUND_CLOSEST(delay_num * factor, 10000);
559 	}
560 
561 	return degrees % 360;
562 
563 }
564 
565 int rockchip_mmc_set_phase(struct clk *clk, u32 degrees)
566 {
567 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
568 	struct rk3308_cru *cru = priv->cru;
569 	u8 nineties, remainder, delay_num;
570 	u32 raw_value, delay;
571 	ulong rate;
572 
573 	rate = rk3308_clk_get_rate(clk);
574 
575 	if (rate < 0)
576 		return rate;
577 
578 	nineties = degrees / 90;
579 	remainder = (degrees % 90);
580 
581 	/*
582 	 * Convert to delay; do a little extra work to make sure we
583 	 * don't overflow 32-bit / 64-bit numbers.
584 	 */
585 	delay = 10000000; /* PSECS_PER_SEC / 10000 / 10 */
586 	delay *= remainder;
587 	delay = DIV_ROUND_CLOSEST(delay, (rate / 1000) * 36 *
588 				(ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10));
589 
590 	delay_num = (u8)min_t(u32, delay, 255);
591 
592 	raw_value = delay_num ? ROCKCHIP_MMC_DELAY_SEL : 0;
593 	raw_value |= delay_num << ROCKCHIP_MMC_DELAYNUM_OFFSET;
594 	raw_value |= nineties << ROCKCHIP_MMC_DEGREE_OFFSET;
595 
596 	if (clk->id == SCLK_EMMC_SAMPLE)
597 		writel(raw_value | 0xffff0000, &cru->emmc_con[1]);
598 	else
599 		writel(raw_value | 0xffff0000, &cru->sdmmc_con[1]);
600 
601 	debug("mmc set_phase(%d) delay_nums=%u reg=%#x actual_degrees=%d\n",
602 	      degrees, delay_num, raw_value, rockchip_mmc_get_phase(clk));
603 
604 	return 0;
605 
606 }
607 
608 static int rk3308_clk_get_phase(struct clk *clk)
609 {
610 	int ret;
611 
612 	switch (clk->id) {
613 	case SCLK_EMMC_SAMPLE:
614 	case SCLK_SDMMC_SAMPLE:
615 		ret = rockchip_mmc_get_phase(clk);
616 		break;
617 	default:
618 		return -ENOENT;
619 	}
620 
621 	return ret;
622 }
623 
624 static int rk3308_clk_set_phase(struct clk *clk, int degrees)
625 {
626 	int ret;
627 
628 	switch (clk->id) {
629 	case SCLK_EMMC_SAMPLE:
630 	case SCLK_SDMMC_SAMPLE:
631 		ret = rockchip_mmc_set_phase(clk, degrees);
632 		break;
633 	default:
634 		return -ENOENT;
635 	}
636 
637 	return ret;
638 }
639 
640 static struct clk_ops rk3308_clk_ops = {
641 	.get_rate = rk3308_clk_get_rate,
642 	.set_rate = rk3308_clk_set_rate,
643 	.get_phase	= rk3308_clk_get_phase,
644 	.set_phase	= rk3308_clk_set_phase,
645 };
646 
647 static int rk3308_clk_probe(struct udevice *dev)
648 {
649 	struct rk3308_clk_priv *priv = dev_get_priv(dev);
650 
651 	rkclk_init(priv->cru);
652 
653 	return 0;
654 }
655 
656 static int rk3308_clk_ofdata_to_platdata(struct udevice *dev)
657 {
658 	struct rk3308_clk_priv *priv = dev_get_priv(dev);
659 
660 	priv->cru = dev_read_addr_ptr(dev);
661 
662 	return 0;
663 }
664 
665 static int rk3308_clk_bind(struct udevice *dev)
666 {
667 	int ret;
668 	struct udevice *sys_child, *sf_child;
669 	struct sysreset_reg *priv;
670 	struct softreset_reg *sf_priv;
671 
672 	/* The reset driver does not have a device node, so bind it here */
673 	ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset",
674 				 &sys_child);
675 	if (ret) {
676 		debug("Warning: No sysreset driver: ret=%d\n", ret);
677 	} else {
678 		priv = malloc(sizeof(struct sysreset_reg));
679 		priv->glb_srst_fst_value = offsetof(struct rk3308_cru,
680 						    glb_srst_fst);
681 		priv->glb_srst_snd_value = offsetof(struct rk3308_cru,
682 						    glb_srst_snd);
683 		sys_child->priv = priv;
684 	}
685 
686 	ret = device_bind_driver_to_node(dev, "rockchip_reset", "reset",
687 					 dev_ofnode(dev), &sf_child);
688 	if (ret) {
689 		debug("Warning: No rockchip reset driver: ret=%d\n", ret);
690 	} else {
691 		sf_priv = malloc(sizeof(struct softreset_reg));
692 		sf_priv->sf_reset_offset = offsetof(struct rk3308_cru,
693 						    softrst_con[0]);
694 		sf_priv->sf_reset_num = 12;
695 		sf_child->priv = sf_priv;
696 	}
697 
698 	return 0;
699 }
700 
701 static const struct udevice_id rk3308_clk_ids[] = {
702 	{ .compatible = "rockchip,rk3308-cru" },
703 	{ }
704 };
705 
706 U_BOOT_DRIVER(rockchip_rk3308_cru) = {
707 	.name		= "rockchip_rk3308_cru",
708 	.id		= UCLASS_CLK,
709 	.of_match	= rk3308_clk_ids,
710 	.priv_auto_alloc_size = sizeof(struct rk3308_clk_priv),
711 	.ofdata_to_platdata = rk3308_clk_ofdata_to_platdata,
712 	.ops		= &rk3308_clk_ops,
713 	.bind		= rk3308_clk_bind,
714 	.probe		= rk3308_clk_probe,
715 };
716