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