xref: /rk3399_rockchip-uboot/drivers/clk/rockchip/clk_px30.c (revision 15a7587bba2ffa33a2e08d02a707fe54b7e24d94)
1 /*
2  * (C) Copyright 2017 Rockchip Electronics Co., Ltd
3  *
4  * SPDX-License-Identifier:	GPL-2.0
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/arch/clock.h>
14 #include <asm/arch/cru_px30.h>
15 #include <asm/arch/hardware.h>
16 #include <asm/io.h>
17 #include <dm/lists.h>
18 #include <dt-bindings/clock/px30-cru.h>
19 
20 DECLARE_GLOBAL_DATA_PTR;
21 
22 enum {
23 	VCO_MAX_HZ	= 3200U * 1000000,
24 	VCO_MIN_HZ	= 800 * 1000000,
25 	OUTPUT_MAX_HZ	= 3200U * 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 const struct pll_div gpll_init_cfg = PLL_DIVISORS(GPLL_HZ, 1, 4, 1);
36 
37 static const struct pll_div apll_816_cfg = PLL_DIVISORS(816 * MHz, 1, 2, 1);
38 static const struct pll_div apll_600_cfg = PLL_DIVISORS(600 * MHz, 1, 3, 1);
39 
40 static const struct pll_div *apll_cfgs[] = {
41 	[APLL_816_MHZ] = &apll_816_cfg,
42 	[APLL_600_MHZ] = &apll_600_cfg,
43 };
44 
45 /*
46  *  the div restructions of pll in integer mode, these are defined in
47  *  * CRU_*PLL_CON0 or PMUCRU_*PLL_CON0
48  */
49 #define PLL_DIV_MIN	16
50 #define PLL_DIV_MAX	3200
51 
52 /*
53  * How to calculate the PLL(from TRM V0.3 Part 1 Page 63):
54  * Formulas also embedded within the Fractional PLL Verilog model:
55  * If DSMPD = 1 (DSM is disabled, "integer mode")
56  * FOUTVCO = FREF / REFDIV * FBDIV
57  * FOUTPOSTDIV = FOUTVCO / POSTDIV1 / POSTDIV2
58  * Where:
59  * FOUTVCO = Fractional PLL non-divided output frequency
60  * FOUTPOSTDIV = Fractional PLL divided output frequency
61  *               (output of second post divider)
62  * FREF = Fractional PLL input reference frequency, (the OSC_HZ 24MHz input)
63  * REFDIV = Fractional PLL input reference clock divider
64  * FBDIV = Integer value programmed into feedback divide
65  *
66  */
67 static void rkclk_set_pll(void *pll_base, const struct pll_div *div)
68 {
69 	struct px30_pll *pll = (struct px30_pll *)pll_base;
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 	debug("PLL at %p: fb=%d, ref=%d, pst1=%d, pst2=%d, vco=%u Hz, output=%u Hz\n",
75 	      pll, div->fbdiv, div->refdiv, div->postdiv1,
76 	      div->postdiv2, vco_hz, output_hz);
77 	assert(vco_hz >= VCO_MIN_HZ && vco_hz <= VCO_MAX_HZ &&
78 	       output_hz >= OUTPUT_MIN_HZ && output_hz <= OUTPUT_MAX_HZ);
79 
80 	/* use integer mode */
81 	rk_setreg(&pll->con1, 1 << PLL_DSMPD_SHIFT);
82 	/* Power down */
83 	rk_setreg(&pll->con1, 1 << PLL_PD_SHIFT);
84 
85 	rk_clrsetreg(&pll->con0,
86 		     PLL_POSTDIV1_MASK | PLL_FBDIV_MASK,
87 		     (div->postdiv1 << PLL_POSTDIV1_SHIFT) | div->fbdiv);
88 	rk_clrsetreg(&pll->con1, PLL_POSTDIV2_MASK | PLL_REFDIV_MASK,
89 		     (div->postdiv2 << PLL_POSTDIV2_SHIFT |
90 		     div->refdiv << PLL_REFDIV_SHIFT));
91 
92 	/* Power Up */
93 	rk_clrreg(&pll->con1, 1 << PLL_PD_SHIFT);
94 
95 	/* waiting for pll lock */
96 	while (readl(&pll->con1) & (1 << PLL_LOCK_STATUS_SHIFT))
97 		udelay(1);
98 
99 	return;
100 }
101 
102 static void rkclk_init(struct px30_cru *cru)
103 {
104 	u32 aclk_div;
105 	u32 hclk_div;
106 	u32 pclk_div;
107 
108 	rk_clrsetreg(&cru->mode, APLL_MODE_MASK,
109 		     PLLMUX_FROM_XIN24M << APLL_MODE_SHIFT);
110 	rk_clrsetreg(&cru->pmu_mode, GPLL_MODE_MASK,
111 		     PLLMUX_FROM_XIN24M << GPLL_MODE_SHIFT);
112 
113 	/* init pll */
114 	rkclk_set_pll(&cru->pll[0] , apll_cfgs[APLL_816_MHZ]);
115 	rkclk_set_pll(&cru->gpll, &gpll_init_cfg);
116 
117 	/*
118 	 * select apll as cpu/core clock pll source and
119 	 * set up dependent divisors for PERI and ACLK clocks.
120 	 * core hz : apll = 1:1
121 	 */
122 	aclk_div = APLL_HZ / CORE_ACLK_HZ - 1;
123 	rk_clrsetreg(&cru->clksel_con[0],
124 		     CORE_CLK_PLL_SEL_MASK | CORE_DIV_CON_MASK |
125 		     CORE_ACLK_DIV_MASK,
126 		     aclk_div << CORE_ACLK_DIV_SHIFT |
127 		     CORE_CLK_PLL_SEL_APLL << CORE_CLK_PLL_SEL_SHIFT |
128 		     0 << CORE_DIV_CON_SHIFT);
129 
130 	/*
131 	 * select gpll as pd_bus bus clock source and
132 	 * set up dependent divisors for PCLK/HCLK and ACLK clocks.
133 	 */
134 	aclk_div = GPLL_HZ / BUS_ACLK_HZ - 1;
135 	hclk_div = GPLL_HZ / BUS_HCLK_HZ - 1;
136 	pclk_div = BUS_ACLK_HZ / BUS_PCLK_HZ - 1;
137 
138 	rk_clrsetreg(&cru->clksel_con[23],
139 		     BUS_PLL_SEL_MASK | BUS_ACLK_DIV_MASK,
140 		     BUS_PLL_SEL_GPLL << BUS_PLL_SEL_SHIFT |
141 		     aclk_div << BUS_ACLK_DIV_SHIFT);
142 
143 	rk_clrsetreg(&cru->clksel_con[24],
144 		     BUS_PCLK_DIV_MASK | BUS_HCLK_DIV_MASK,
145 		     pclk_div << BUS_PCLK_DIV_SHIFT |
146 		     hclk_div << BUS_HCLK_DIV_SHIFT);
147 
148 	/*
149 	 * select gpll as pd_peri bus clock source and
150 	 * set up dependent divisors for PCLK/HCLK and ACLK clocks.
151 	 */
152 	aclk_div = GPLL_HZ / PERI_ACLK_HZ - 1;
153 	hclk_div = GPLL_HZ / PERI_HCLK_HZ - 1;
154 
155 	rk_clrsetreg(&cru->clksel_con[14],
156 		     PERI_PLL_SEL_MASK |
157 		     PERI_HCLK_DIV_MASK | PERI_ACLK_DIV_MASK,
158 		     PERI_PLL_GPLL << PERI_PLL_SEL_SHIFT |
159 		     hclk_div << PERI_HCLK_DIV_SHIFT |
160 		     aclk_div << PERI_ACLK_DIV_SHIFT);
161 
162 	rk_clrsetreg(&cru->mode, APLL_MODE_MASK,
163 		     PLLMUX_FROM_PLL << APLL_MODE_SHIFT);
164 	rk_clrsetreg(&cru->pmu_mode, GPLL_MODE_MASK,
165 		     PLLMUX_FROM_PLL << GPLL_MODE_SHIFT);
166 }
167 
168 static ulong px30_i2c_get_clk(struct px30_cru *cru, ulong clk_id)
169 {
170 	u32 div, con;
171 
172 	switch (clk_id) {
173 	case SCLK_I2C0:
174 		con = readl(&cru->clksel_con[49]);
175 		div = con >> CLK_I2C0_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK;
176 		break;
177 	case SCLK_I2C1:
178 		con = readl(&cru->clksel_con[49]);
179 		div = con >> CLK_I2C1_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK;
180 		break;
181 	case SCLK_I2C2:
182 		con = readl(&cru->clksel_con[50]);
183 		div = con >> CLK_I2C2_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK;
184 		break;
185 	case SCLK_I2C3:
186 		con = readl(&cru->clksel_con[50]);
187 		div = con >> CLK_I2C3_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK;
188 		break;
189 	default:
190 		printf("do not support this i2c bus\n");
191 		return -EINVAL;
192 	}
193 
194 	return DIV_TO_RATE(GPLL_HZ, div);
195 }
196 
197 static ulong px30_i2c_set_clk(struct px30_cru *cru, ulong clk_id, uint hz)
198 {
199 	int src_clk_div;
200 
201 	src_clk_div = GPLL_HZ / hz;
202 	assert(src_clk_div - 1 < 127);
203 
204 	switch (clk_id) {
205 	case SCLK_I2C0:
206 		rk_clrsetreg(&cru->clksel_con[49],
207 			     CLK_I2C_DIV_CON_MASK << CLK_I2C0_DIV_CON_SHIFT |
208 			     CLK_I2C_PLL_SEL_MASK << CLK_I2C0_PLL_SEL_SHIFT,
209 			     (src_clk_div - 1) << CLK_I2C0_DIV_CON_SHIFT |
210 			     CLK_I2C_PLL_SEL_GPLL << CLK_I2C0_PLL_SEL_SHIFT);
211 		break;
212 	case SCLK_I2C1:
213 		rk_clrsetreg(&cru->clksel_con[49],
214 			     CLK_I2C_DIV_CON_MASK << CLK_I2C1_DIV_CON_SHIFT |
215 			     CLK_I2C_PLL_SEL_MASK << CLK_I2C1_PLL_SEL_SHIFT,
216 			     (src_clk_div - 1) << CLK_I2C1_DIV_CON_SHIFT |
217 			     CLK_I2C_PLL_SEL_GPLL << CLK_I2C1_PLL_SEL_SHIFT);
218 		break;
219 	case SCLK_I2C2:
220 		rk_clrsetreg(&cru->clksel_con[50],
221 			     CLK_I2C_DIV_CON_MASK << CLK_I2C2_DIV_CON_SHIFT |
222 			     CLK_I2C_PLL_SEL_MASK << CLK_I2C2_PLL_SEL_SHIFT,
223 			     (src_clk_div - 1) << CLK_I2C2_DIV_CON_SHIFT |
224 			     CLK_I2C_PLL_SEL_GPLL << CLK_I2C2_PLL_SEL_SHIFT);
225 		break;
226 	case SCLK_I2C3:
227 		rk_clrsetreg(&cru->clksel_con[50],
228 			     CLK_I2C_DIV_CON_MASK << CLK_I2C3_DIV_CON_SHIFT |
229 			     CLK_I2C_PLL_SEL_MASK << CLK_I2C3_PLL_SEL_SHIFT,
230 			     (src_clk_div - 1) << CLK_I2C3_DIV_CON_SHIFT |
231 			     CLK_I2C_PLL_SEL_GPLL << CLK_I2C3_PLL_SEL_SHIFT);
232 		break;
233 	default:
234 		printf("do not support this i2c bus\n");
235 		return -EINVAL;
236 	}
237 
238 	return DIV_TO_RATE(GPLL_HZ, src_clk_div);
239 }
240 
241 static ulong px30_mmc_get_clk(struct px30_cru *cru, uint clk_id)
242 {
243 	u32 div, con, con_id;
244 
245 	switch (clk_id) {
246 	case HCLK_SDMMC:
247 	case SCLK_SDMMC:
248 		con_id = 16;
249 		break;
250 	case HCLK_EMMC:
251 	case SCLK_EMMC:
252 		con_id = 20;
253 		break;
254 	default:
255 		return -EINVAL;
256 	}
257 
258 	con = readl(&cru->clksel_con[con_id]);
259 	div = (con & EMMC_DIV_MASK) >> EMMC_DIV_SHIFT;
260 
261 	if ((con & EMMC_PLL_MASK) >> EMMC_PLL_SHIFT
262 	    == EMMC_SEL_24M)
263 		return DIV_TO_RATE(OSC_HZ, div) / 2;
264 	else
265 		return DIV_TO_RATE(GPLL_HZ, div) / 2;
266 
267 }
268 
269 static ulong px30_mmc_set_clk(struct px30_cru *cru,
270 				ulong clk_id, ulong set_rate)
271 {
272 	int src_clk_div;
273 	u32 con_id;
274 
275 	debug("%s %ld %ld\n", __func__, clk_id, set_rate);
276 	switch (clk_id) {
277 	case HCLK_SDMMC:
278 	case SCLK_SDMMC:
279 		con_id = 16;
280 		break;
281 	case HCLK_EMMC:
282 	case SCLK_EMMC:
283 		con_id = 20;
284 		break;
285 	default:
286 		return -EINVAL;
287 	}
288 	/* Select clk_sdmmc/emmc source from GPLL by default */
289 	/* mmc clock defaulg div 2 internal, need provide double in cru */
290 	src_clk_div = DIV_ROUND_UP(GPLL_HZ / 2, set_rate);
291 
292 	if (src_clk_div > 127) {
293 		/* use 24MHz source for 400KHz clock */
294 		src_clk_div = DIV_ROUND_UP(OSC_HZ / 2, set_rate);
295 		rk_clrsetreg(&cru->clksel_con[con_id],
296 			     EMMC_PLL_MASK | EMMC_DIV_MASK,
297 			     EMMC_SEL_24M << EMMC_PLL_SHIFT |
298 			     (src_clk_div - 1) << EMMC_DIV_SHIFT);
299 	} else {
300 		rk_clrsetreg(&cru->clksel_con[con_id],
301 			     EMMC_PLL_MASK | EMMC_DIV_MASK,
302 			     EMMC_SEL_GPLL << EMMC_PLL_SHIFT |
303 			     (src_clk_div - 1) << EMMC_DIV_SHIFT);
304 	}
305 	rk_clrsetreg(&cru->clksel_con[con_id +1], EMMC_CLK_SEL_MASK,
306 		     EMMC_CLK_SEL_EMMC);
307 
308 	return px30_mmc_get_clk(cru, clk_id);
309 }
310 
311 static ulong px30_pwm_get_clk(struct px30_cru *cru, ulong clk_id)
312 {
313 	u32 div, con;
314 
315 	switch (clk_id) {
316 	case SCLK_PWM0:
317 		con = readl(&cru->clksel_con[52]);
318 		div = con >> CLK_PWM0_DIV_CON_SHIFT & CLK_PWM_DIV_CON_MASK;
319 		break;
320 	case SCLK_PWM1:
321 		con = readl(&cru->clksel_con[52]);
322 		div = con >> CLK_PWM1_DIV_CON_SHIFT & CLK_PWM_DIV_CON_MASK;
323 		break;
324 	default:
325 		printf("do not support this pwm bus\n");
326 		return -EINVAL;
327 	}
328 
329 	return DIV_TO_RATE(GPLL_HZ, div);
330 }
331 
332 static ulong px30_pwm_set_clk(struct px30_cru *cru, ulong clk_id, uint hz)
333 {
334 	int src_clk_div;
335 
336 	src_clk_div = GPLL_HZ / hz;
337 	assert(src_clk_div - 1 < 127);
338 
339 	switch (clk_id) {
340 	case SCLK_PWM0:
341 		rk_clrsetreg(&cru->clksel_con[52],
342 			     CLK_PWM_DIV_CON_MASK << CLK_PWM0_DIV_CON_SHIFT |
343 			     CLK_PWM_PLL_SEL_MASK << CLK_PWM0_PLL_SEL_SHIFT,
344 			     (src_clk_div - 1) << CLK_PWM0_DIV_CON_SHIFT |
345 			     CLK_PWM_PLL_SEL_GPLL << CLK_PWM0_PLL_SEL_SHIFT);
346 		break;
347 	case SCLK_PWM1:
348 		rk_clrsetreg(&cru->clksel_con[52],
349 			     CLK_PWM_DIV_CON_MASK << CLK_PWM1_DIV_CON_SHIFT |
350 			     CLK_PWM_PLL_SEL_MASK << CLK_PWM1_PLL_SEL_SHIFT,
351 			     (src_clk_div - 1) << CLK_PWM1_DIV_CON_SHIFT |
352 			     CLK_PWM_PLL_SEL_GPLL << CLK_PWM1_PLL_SEL_SHIFT);
353 		break;
354 	default:
355 		printf("do not support this pwm bus\n");
356 		return -EINVAL;
357 	}
358 
359 	return DIV_TO_RATE(GPLL_HZ, src_clk_div);
360 }
361 
362 static ulong px30_saradc_get_clk(struct px30_cru *cru)
363 {
364 	u32 div, con;
365 
366 	con = readl(&cru->clksel_con[55]);
367 	div = con >> CLK_SARADC_DIV_CON_SHIFT & CLK_PWM_DIV_CON_MASK;
368 
369 	return DIV_TO_RATE(OSC_HZ, div);
370 }
371 
372 static ulong px30_saradc_set_clk(struct px30_cru *cru, uint hz)
373 {
374 	int src_clk_div;
375 
376 	src_clk_div = OSC_HZ / hz;
377 	assert(src_clk_div - 1 < 2047);
378 
379 	rk_clrsetreg(&cru->clksel_con[55],
380 		     CLK_SARADC_DIV_CON_MASK,
381 		     src_clk_div << CLK_SARADC_DIV_CON_SHIFT);
382 
383 	return DIV_TO_RATE(OSC_HZ, src_clk_div);
384 }
385 
386 static ulong px30_spi_get_clk(struct px30_cru *cru, ulong clk_id)
387 {
388 	u32 div, con;
389 
390 	switch (clk_id) {
391 	case SCLK_PWM0:
392 		con = readl(&cru->clksel_con[53]);
393 		div = con >> CLK_SPI0_DIV_CON_SHIFT & CLK_SPI_DIV_CON_MASK;
394 		break;
395 	case SCLK_PWM1:
396 		con = readl(&cru->clksel_con[53]);
397 		div = con >> CLK_SPI1_DIV_CON_SHIFT & CLK_SPI_DIV_CON_MASK;
398 		break;
399 	default:
400 		printf("do not support this pwm bus\n");
401 		return -EINVAL;
402 	}
403 
404 	return DIV_TO_RATE(GPLL_HZ, div);
405 }
406 
407 static ulong px30_spi_set_clk(struct px30_cru *cru, ulong clk_id, uint hz)
408 {
409 	int src_clk_div;
410 
411 	src_clk_div = GPLL_HZ / hz;
412 	assert(src_clk_div - 1 < 127);
413 
414 	switch (clk_id) {
415 	case SCLK_SPI0:
416 		rk_clrsetreg(&cru->clksel_con[53],
417 			     CLK_SPI_DIV_CON_MASK << CLK_SPI0_DIV_CON_SHIFT |
418 			     CLK_SPI_PLL_SEL_MASK << CLK_SPI0_PLL_SEL_SHIFT,
419 			     (src_clk_div - 1) << CLK_SPI0_DIV_CON_SHIFT |
420 			     CLK_SPI_PLL_SEL_GPLL << CLK_SPI0_PLL_SEL_SHIFT);
421 		break;
422 	case SCLK_SPI1:
423 		rk_clrsetreg(&cru->clksel_con[53],
424 			     CLK_SPI_DIV_CON_MASK << CLK_SPI1_DIV_CON_SHIFT |
425 			     CLK_SPI_PLL_SEL_MASK << CLK_SPI1_PLL_SEL_SHIFT,
426 			     (src_clk_div - 1) << CLK_SPI1_DIV_CON_SHIFT |
427 			     CLK_SPI_PLL_SEL_GPLL << CLK_SPI1_PLL_SEL_SHIFT);
428 		break;
429 	default:
430 		printf("do not support this pwm bus\n");
431 		return -EINVAL;
432 	}
433 
434 	return DIV_TO_RATE(GPLL_HZ, src_clk_div);
435 }
436 
437 static ulong px30_clk_get_rate(struct clk *clk)
438 {
439 	struct px30_clk_priv *priv = dev_get_priv(clk->dev);
440 	ulong rate = 0;
441 
442 	switch (clk->id) {
443 	case 0 ... 15:
444 		return 0;
445 	case HCLK_SDMMC:
446 	case HCLK_EMMC:
447 	case SCLK_SDMMC:
448 	case SCLK_EMMC:
449 		rate = px30_mmc_get_clk(priv->cru, clk->id);
450 		break;
451 	case SCLK_I2C0:
452 	case SCLK_I2C1:
453 	case SCLK_I2C2:
454 	case SCLK_I2C3:
455 		rate = px30_i2c_get_clk(priv->cru, clk->id);
456 		break;
457 	case SCLK_PWM0:
458 		rate = px30_pwm_get_clk(priv->cru, clk->id);
459 		break;
460 	case SCLK_SARADC:
461 		rate = px30_saradc_get_clk(priv->cru);
462 		break;
463 	case SCLK_SPI0:
464 	case SCLK_SPI1:
465 		rate = px30_spi_get_clk(priv->cru, clk->id);
466 		break;
467 	default:
468 		return -ENOENT;
469 	}
470 
471 	return rate;
472 }
473 
474 static ulong px30_clk_set_rate(struct clk *clk, ulong rate)
475 {
476 	struct px30_clk_priv *priv = dev_get_priv(clk->dev);
477 	ulong ret = 0;
478 
479 	debug("%s %ld %ld\n", __func__, clk->id, rate);
480 	switch (clk->id) {
481 	case 0 ... 15:
482 		return 0;
483 	case HCLK_SDMMC:
484 	case HCLK_EMMC:
485 	case SCLK_SDMMC:
486 	case SCLK_EMMC:
487 		ret = px30_mmc_set_clk(priv->cru, clk->id, rate);
488 		break;
489 	case SCLK_I2C0:
490 	case SCLK_I2C1:
491 	case SCLK_I2C2:
492 	case SCLK_I2C3:
493 		ret = px30_i2c_set_clk(priv->cru, clk->id, rate);
494 		break;
495 	case SCLK_PWM0:
496 	case SCLK_PWM1:
497 		ret = px30_pwm_set_clk(priv->cru, clk->id, rate);
498 		break;
499 	case SCLK_SARADC:
500 		ret = px30_saradc_set_clk(priv->cru, rate);
501 		break;
502 	case SCLK_SPI0:
503 	case SCLK_SPI1:
504 		ret = px30_spi_set_clk(priv->cru, clk->id, rate);
505 		break;
506 	default:
507 		return -ENOENT;
508 	}
509 
510 	return ret;
511 }
512 
513 #define ROCKCHIP_MMC_DELAY_SEL		BIT(10)
514 #define ROCKCHIP_MMC_DEGREE_MASK	0x3
515 #define ROCKCHIP_MMC_DELAYNUM_OFFSET	2
516 #define ROCKCHIP_MMC_DELAYNUM_MASK	(0xff << ROCKCHIP_MMC_DELAYNUM_OFFSET)
517 
518 #define PSECS_PER_SEC 1000000000000LL
519 /*
520  * Each fine delay is between 44ps-77ps. Assume each fine delay is 60ps to
521  * simplify calculations. So 45degs could be anywhere between 33deg and 57.8deg.
522  */
523 #define ROCKCHIP_MMC_DELAY_ELEMENT_PSEC 60
524 
525 int rockchip_mmc_get_phase(struct clk *clk)
526 {
527 	struct px30_clk_priv *priv = dev_get_priv(clk->dev);
528 	struct px30_cru *cru = priv->cru;
529 	u32 raw_value, delay_num;
530 	u16 degrees = 0;
531 	ulong rate;
532 
533 	rate = px30_clk_get_rate(clk);
534 
535 	if (rate < 0)
536 		return rate;
537 
538 	if (clk->id == SCLK_EMMC_SAMPLE)
539 		raw_value = readl(&cru->emmc_con[1]);
540 	else
541 		raw_value = readl(&cru->sdmmc_con[1]);
542 
543 	degrees = (raw_value & ROCKCHIP_MMC_DEGREE_MASK) * 90;
544 
545 	if (raw_value & ROCKCHIP_MMC_DELAY_SEL) {
546 		/* degrees/delaynum * 10000 */
547 		unsigned long factor = (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10) *
548 					36 * (rate / 1000000);
549 
550 		delay_num = (raw_value & ROCKCHIP_MMC_DELAYNUM_MASK);
551 		delay_num >>= ROCKCHIP_MMC_DELAYNUM_OFFSET;
552 		degrees += DIV_ROUND_CLOSEST(delay_num * factor, 10000);
553 	}
554 
555 	return degrees % 360;
556 }
557 
558 int rockchip_mmc_set_phase(struct clk *clk, u32 degrees)
559 {
560 	struct px30_clk_priv *priv = dev_get_priv(clk->dev);
561 	struct px30_cru *cru = priv->cru;
562 	u8 nineties, remainder, delay_num;
563 	u32 raw_value, delay;
564 	ulong rate;
565 
566 	rate = px30_clk_get_rate(clk);
567 
568 	if (rate < 0)
569 		return rate;
570 
571 	nineties = degrees / 90;
572 	remainder = (degrees % 90);
573 
574 	/*
575 	 * Convert to delay; do a little extra work to make sure we
576 	 * don't overflow 32-bit / 64-bit numbers.
577 	 */
578 	delay = 10000000; /* PSECS_PER_SEC / 10000 / 10 */
579 	delay *= remainder;
580 	delay = DIV_ROUND_CLOSEST(delay, (rate / 1000) * 36 *
581 				(ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10));
582 
583 	delay_num = (u8)min_t(u32, delay, 255);
584 
585 	raw_value = delay_num ? ROCKCHIP_MMC_DELAY_SEL : 0;
586 	raw_value |= delay_num << ROCKCHIP_MMC_DELAYNUM_OFFSET;
587 	raw_value |= nineties;
588 
589 	if (clk->id == SCLK_EMMC_SAMPLE)
590 		writel(raw_value | 0xffff0000, &cru->emmc_con[1]);
591 	else
592 		writel(raw_value | 0xffff0000, &cru->sdmmc_con[1]);
593 
594 	debug("mmc set_phase(%d) delay_nums=%u reg=%#x actual_degrees=%d\n",
595 	      degrees, delay_num, raw_value, rockchip_mmc_get_phase(clk));
596 
597 	return 0;
598 }
599 
600 static int px30_clk_get_phase(struct clk *clk)
601 {
602 	int ret;
603 
604 	switch (clk->id) {
605 	case SCLK_EMMC_SAMPLE:
606 	case SCLK_SDMMC_SAMPLE:
607 		ret = rockchip_mmc_get_phase(clk);
608 		break;
609 	default:
610 		return -ENOENT;
611 	}
612 
613 	return ret;
614 }
615 
616 static int px30_clk_set_phase(struct clk *clk, int degrees)
617 {
618 	int ret;
619 
620 	switch (clk->id) {
621 	case SCLK_EMMC_SAMPLE:
622 	case SCLK_SDMMC_SAMPLE:
623 		ret = rockchip_mmc_set_phase(clk, degrees);
624 		break;
625 	default:
626 		return -ENOENT;
627 	}
628 
629 	return ret;
630 }
631 
632 static struct clk_ops px30_clk_ops = {
633 	.get_rate = px30_clk_get_rate,
634 	.set_rate = px30_clk_set_rate,
635 	.get_phase	= px30_clk_get_phase,
636 	.set_phase	= px30_clk_set_phase,
637 };
638 
639 static int px30_clk_probe(struct udevice *dev)
640 {
641 	struct px30_clk_priv *priv = dev_get_priv(dev);
642 
643 	rkclk_init(priv->cru);
644 
645 	return 0;
646 }
647 
648 static int px30_clk_ofdata_to_platdata(struct udevice *dev)
649 {
650 	struct px30_clk_priv *priv = dev_get_priv(dev);
651 
652 	priv->cru = dev_read_addr_ptr(dev);
653 
654 	return 0;
655 }
656 
657 static int px30_clk_bind(struct udevice *dev)
658 {
659 	int ret;
660 	struct udevice *sys_child, *sf_child;
661 	struct sysreset_reg *priv;
662 	struct softreset_reg *sf_priv;
663 
664 	/* The reset driver does not have a device node, so bind it here */
665 	ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset",
666 				 &sys_child);
667 	if (ret) {
668 		debug("Warning: No sysreset driver: ret=%d\n", ret);
669 	} else {
670 		priv = malloc(sizeof(struct sysreset_reg));
671 		priv->glb_srst_fst_value = offsetof(struct px30_cru,
672 						    glb_srst_fst);
673 		priv->glb_srst_snd_value = offsetof(struct px30_cru,
674 						    glb_srst_snd);
675 		sys_child->priv = priv;
676 	}
677 
678 	ret = device_bind_driver_to_node(dev, "rockchip_reset", "reset",
679 					 dev_ofnode(dev), &sf_child);
680 	if (ret) {
681 		debug("Warning: No rockchip reset driver: ret=%d\n", ret);
682 	} else {
683 		sf_priv = malloc(sizeof(struct softreset_reg));
684 		sf_priv->sf_reset_offset = offsetof(struct px30_cru,
685 						    softrst_con[0]);
686 		sf_priv->sf_reset_num = 12;
687 		sf_child->priv = sf_priv;
688 	}
689 
690 	return 0;
691 }
692 
693 static const struct udevice_id px30_clk_ids[] = {
694 	{ .compatible = "rockchip,px30-cru" },
695 	{ }
696 };
697 
698 U_BOOT_DRIVER(rockchip_px30_cru) = {
699 	.name		= "rockchip_px30_cru",
700 	.id		= UCLASS_CLK,
701 	.of_match	= px30_clk_ids,
702 	.priv_auto_alloc_size = sizeof(struct px30_clk_priv),
703 	.ofdata_to_platdata = px30_clk_ofdata_to_platdata,
704 	.ops		= &px30_clk_ops,
705 	.bind		= px30_clk_bind,
706 	.probe		= px30_clk_probe,
707 };
708