xref: /rk3399_rockchip-uboot/drivers/clk/rockchip/clk_px30.c (revision d5f538dc02e53c7267fcd4a914104071fca889b5)
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, 1, 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 static u8 pll_mode_shift[PLL_COUNT] = {
46 	APLL_MODE_SHIFT, DPLL_MODE_SHIFT, CPLL_MODE_SHIFT,
47 	NPLL_MODE_SHIFT, GPLL_MODE_SHIFT
48 };
49 static u32 pll_mode_mask[PLL_COUNT] = {
50 	APLL_MODE_MASK, DPLL_MODE_MASK, CPLL_MODE_MASK,
51 	NPLL_MODE_MASK, GPLL_MODE_MASK
52 };
53 
54 /*
55  *  the div restructions of pll in integer mode, these are defined in
56  *  * CRU_*PLL_CON0 or PMUCRU_*PLL_CON0
57  */
58 #define PLL_DIV_MIN	16
59 #define PLL_DIV_MAX	3200
60 
61 /*
62  * How to calculate the PLL(from TRM V0.3 Part 1 Page 63):
63  * Formulas also embedded within the Fractional PLL Verilog model:
64  * If DSMPD = 1 (DSM is disabled, "integer mode")
65  * FOUTVCO = FREF / REFDIV * FBDIV
66  * FOUTPOSTDIV = FOUTVCO / POSTDIV1 / POSTDIV2
67  * Where:
68  * FOUTVCO = Fractional PLL non-divided output frequency
69  * FOUTPOSTDIV = Fractional PLL divided output frequency
70  *               (output of second post divider)
71  * FREF = Fractional PLL input reference frequency, (the OSC_HZ 24MHz input)
72  * REFDIV = Fractional PLL input reference clock divider
73  * FBDIV = Integer value programmed into feedback divide
74  *
75  */
76 static void rkclk_set_pll(struct px30_cru *cru, enum px30_pll_id pll_id,
77 			  const struct pll_div *div)
78 {
79 	struct px30_pll *pll;
80 	unsigned int *mode;
81 	/* All PLLs have same VCO and output frequency range restrictions. */
82 	uint vco_hz = OSC_HZ / 1000 * div->fbdiv / div->refdiv * 1000;
83 	uint output_hz = vco_hz / div->postdiv1 / div->postdiv2;
84 
85 	if (pll_id == GPLL) {
86 		pll = &cru->gpll;
87 		mode = &cru->pmu_mode;
88 	} else {
89 		pll = &cru->pll[pll_id];
90 		mode = &cru->mode;
91 	};
92 
93 	debug("PLL at %p: fb=%d, ref=%d, pst1=%d, pst2=%d, vco=%u Hz, output=%u Hz\n",
94 	      pll, div->fbdiv, div->refdiv, div->postdiv1,
95 	      div->postdiv2, vco_hz, output_hz);
96 	assert(vco_hz >= VCO_MIN_HZ && vco_hz <= VCO_MAX_HZ &&
97 	       output_hz >= OUTPUT_MIN_HZ && output_hz <= OUTPUT_MAX_HZ);
98 
99 	/*
100 	 * When power on or changing PLL setting,
101 	 * we must force PLL into slow mode to ensure output stable clock.
102 	 */
103 	rk_clrsetreg(mode, pll_mode_mask[pll_id],
104 		     PLLMUX_FROM_XIN24M << pll_mode_shift[pll_id]);
105 
106 	/* use integer mode */
107 	rk_setreg(&pll->con1, 1 << PLL_DSMPD_SHIFT);
108 	/* Power down */
109 	rk_setreg(&pll->con1, 1 << PLL_PD_SHIFT);
110 
111 	rk_clrsetreg(&pll->con0,
112 		     PLL_POSTDIV1_MASK | PLL_FBDIV_MASK,
113 		     (div->postdiv1 << PLL_POSTDIV1_SHIFT) | div->fbdiv);
114 	rk_clrsetreg(&pll->con1, PLL_POSTDIV2_MASK | PLL_REFDIV_MASK,
115 		     (div->postdiv2 << PLL_POSTDIV2_SHIFT |
116 		     div->refdiv << PLL_REFDIV_SHIFT));
117 
118 	/* Power Up */
119 	rk_clrreg(&pll->con1, 1 << PLL_PD_SHIFT);
120 
121 	/* waiting for pll lock */
122 	while (!(readl(&pll->con1) & (1 << PLL_LOCK_STATUS_SHIFT)))
123 		udelay(1);
124 
125 	rk_clrsetreg(mode, pll_mode_mask[pll_id],
126 		     PLLMUX_FROM_PLL << pll_mode_shift[pll_id]);
127 
128 	return;
129 }
130 
131 static uint32_t rkclk_pll_get_rate(struct px30_cru *cru,
132 				   enum px30_pll_id pll_id)
133 {
134 	u32 refdiv, fbdiv, postdiv1, postdiv2;
135 	u32 con;
136 	struct px30_pll *pll;
137 	uint shift;
138 	uint mask;
139 
140 	if (pll_id == GPLL) {
141 		pll = &cru->gpll;
142 		con = readl(&cru->pmu_mode);
143 	} else {
144 		pll = &cru->pll[pll_id];
145 		con = readl(&cru->mode);
146 	}
147 
148 	shift = pll_mode_shift[pll_id];
149 	mask = pll_mode_mask[pll_id];
150 
151 	switch ((con & mask) >> shift) {
152 	case PLLMUX_FROM_XIN24M:
153 		return OSC_HZ;
154 	case PLLMUX_FROM_PLL:
155 		/* normal mode */
156 		con = readl(&pll->con0);
157 		postdiv1 = (con & PLL_POSTDIV1_MASK) >> PLL_POSTDIV1_SHIFT;
158 		fbdiv = (con & PLL_FBDIV_MASK) >> PLL_FBDIV_SHIFT;
159 		con = readl(&pll->con1);
160 		postdiv2 = (con & PLL_POSTDIV2_MASK) >> PLL_POSTDIV2_SHIFT;
161 		refdiv = (con & PLL_REFDIV_MASK) >> PLL_REFDIV_SHIFT;
162 		return (24 * fbdiv / (refdiv * postdiv1 * postdiv2)) * 1000000;
163 	case PLLMUX_FROM_RTC32K:
164 	default:
165 		return 32768;
166 	}
167 }
168 
169 static int pll_para_config(u32 freq_hz, struct pll_div *div)
170 {
171 	u32 ref_khz = OSC_HZ / KHz, refdiv, fbdiv = 0;
172 	u32 postdiv1, postdiv2 = 1;
173 	u32 fref_khz;
174 	u32 diff_khz, best_diff_khz;
175 	const u32 max_refdiv = 63, max_fbdiv = 3200, min_fbdiv = 16;
176 	const u32 max_postdiv1 = 7, max_postdiv2 = 7;
177 	u32 vco_khz;
178 	u32 freq_khz = freq_hz / KHz;
179 
180 	if (!freq_hz) {
181 		printf("%s: the frequency can't be 0 Hz\n", __func__);
182 		return -1;
183 	}
184 
185 	postdiv1 = DIV_ROUND_UP(VCO_MIN_HZ / 1000, freq_khz);
186 	if (postdiv1 > max_postdiv1) {
187 		postdiv2 = DIV_ROUND_UP(postdiv1, max_postdiv1);
188 		postdiv1 = DIV_ROUND_UP(postdiv1, postdiv2);
189 	}
190 
191 	vco_khz = freq_khz * postdiv1 * postdiv2;
192 
193 	if (vco_khz < (VCO_MIN_HZ / KHz) || vco_khz > (VCO_MAX_HZ / KHz) ||
194 	    postdiv2 > max_postdiv2) {
195 		printf("%s: Cannot find out a supported VCO for Freq (%uHz)\n",
196 		       __func__, freq_hz);
197 		return -1;
198 	}
199 
200 	div->postdiv1 = postdiv1;
201 	div->postdiv2 = postdiv2;
202 
203 	best_diff_khz = vco_khz;
204 	for (refdiv = 1; refdiv < max_refdiv && best_diff_khz; refdiv++) {
205 		fref_khz = ref_khz / refdiv;
206 
207 		fbdiv = vco_khz / fref_khz;
208 		if ((fbdiv >= max_fbdiv) || (fbdiv <= min_fbdiv))
209 			continue;
210 		diff_khz = vco_khz - fbdiv * fref_khz;
211 		if (fbdiv + 1 < max_fbdiv && diff_khz > fref_khz / 2) {
212 			fbdiv++;
213 			diff_khz = fref_khz - diff_khz;
214 		}
215 
216 		if (diff_khz >= best_diff_khz)
217 			continue;
218 
219 		best_diff_khz = diff_khz;
220 		div->refdiv = refdiv;
221 		div->fbdiv = fbdiv;
222 	}
223 
224 	if (best_diff_khz > 4 * (MHz / KHz)) {
225 		printf("%s: Failed to match output frequency %u bestis %u Hz\n",
226 		       __func__, freq_hz,
227 		       best_diff_khz * KHz);
228 		return -1;
229 	}
230 	return 0;
231 }
232 
233 static void rkclk_init(struct px30_cru *cru)
234 {
235 	u32 aclk_div;
236 	u32 hclk_div;
237 	u32 pclk_div;
238 
239 	/* init pll */
240 	rkclk_set_pll(cru, APLL, apll_cfgs[APLL_816_MHZ]);
241 	rkclk_set_pll(cru, GPLL, &gpll_init_cfg);
242 
243 	/*
244 	 * select apll as cpu/core clock pll source and
245 	 * set up dependent divisors for PERI and ACLK clocks.
246 	 * core hz : apll = 1:1
247 	 */
248 	aclk_div = APLL_HZ / CORE_ACLK_HZ - 1;
249 	rk_clrsetreg(&cru->clksel_con[0],
250 		     CORE_CLK_PLL_SEL_MASK | CORE_DIV_CON_MASK |
251 		     CORE_ACLK_DIV_MASK,
252 		     aclk_div << CORE_ACLK_DIV_SHIFT |
253 		     CORE_CLK_PLL_SEL_APLL << CORE_CLK_PLL_SEL_SHIFT |
254 		     0 << CORE_DIV_CON_SHIFT);
255 
256 	/*
257 	 * select gpll as pd_bus bus clock source and
258 	 * set up dependent divisors for PCLK/HCLK and ACLK clocks.
259 	 */
260 	aclk_div = GPLL_HZ / BUS_ACLK_HZ - 1;
261 	hclk_div = GPLL_HZ / BUS_HCLK_HZ - 1;
262 	pclk_div = BUS_ACLK_HZ / BUS_PCLK_HZ - 1;
263 
264 	rk_clrsetreg(&cru->clksel_con[23],
265 		     BUS_PLL_SEL_MASK | BUS_ACLK_DIV_MASK,
266 		     BUS_PLL_SEL_GPLL << BUS_PLL_SEL_SHIFT |
267 		     aclk_div << BUS_ACLK_DIV_SHIFT);
268 
269 	rk_clrsetreg(&cru->clksel_con[24],
270 		     BUS_PCLK_DIV_MASK | BUS_HCLK_DIV_MASK,
271 		     pclk_div << BUS_PCLK_DIV_SHIFT |
272 		     hclk_div << BUS_HCLK_DIV_SHIFT);
273 
274 	/*
275 	 * select gpll as pd_peri bus clock source and
276 	 * set up dependent divisors for PCLK/HCLK and ACLK clocks.
277 	 */
278 	aclk_div = GPLL_HZ / PERI_ACLK_HZ - 1;
279 	hclk_div = GPLL_HZ / PERI_HCLK_HZ - 1;
280 
281 	rk_clrsetreg(&cru->clksel_con[14],
282 		     PERI_PLL_SEL_MASK |
283 		     PERI_HCLK_DIV_MASK | PERI_ACLK_DIV_MASK,
284 		     PERI_PLL_GPLL << PERI_PLL_SEL_SHIFT |
285 		     hclk_div << PERI_HCLK_DIV_SHIFT |
286 		     aclk_div << PERI_ACLK_DIV_SHIFT);
287 }
288 
289 static ulong px30_i2c_get_clk(struct px30_cru *cru, ulong clk_id)
290 {
291 	u32 div, con;
292 
293 	switch (clk_id) {
294 	case SCLK_I2C0:
295 		con = readl(&cru->clksel_con[49]);
296 		div = con >> CLK_I2C0_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK;
297 		break;
298 	case SCLK_I2C1:
299 		con = readl(&cru->clksel_con[49]);
300 		div = con >> CLK_I2C1_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK;
301 		break;
302 	case SCLK_I2C2:
303 		con = readl(&cru->clksel_con[50]);
304 		div = con >> CLK_I2C2_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK;
305 		break;
306 	case SCLK_I2C3:
307 		con = readl(&cru->clksel_con[50]);
308 		div = con >> CLK_I2C3_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK;
309 		break;
310 	default:
311 		printf("do not support this i2c bus\n");
312 		return -EINVAL;
313 	}
314 
315 	return DIV_TO_RATE(GPLL_HZ, div);
316 }
317 
318 static ulong px30_i2c_set_clk(struct px30_cru *cru, ulong clk_id, uint hz)
319 {
320 	int src_clk_div;
321 
322 	src_clk_div = GPLL_HZ / hz;
323 	assert(src_clk_div - 1 < 127);
324 
325 	switch (clk_id) {
326 	case SCLK_I2C0:
327 		rk_clrsetreg(&cru->clksel_con[49],
328 			     CLK_I2C_DIV_CON_MASK << CLK_I2C0_DIV_CON_SHIFT |
329 			     CLK_I2C_PLL_SEL_MASK << CLK_I2C0_PLL_SEL_SHIFT,
330 			     (src_clk_div - 1) << CLK_I2C0_DIV_CON_SHIFT |
331 			     CLK_I2C_PLL_SEL_GPLL << CLK_I2C0_PLL_SEL_SHIFT);
332 		break;
333 	case SCLK_I2C1:
334 		rk_clrsetreg(&cru->clksel_con[49],
335 			     CLK_I2C_DIV_CON_MASK << CLK_I2C1_DIV_CON_SHIFT |
336 			     CLK_I2C_PLL_SEL_MASK << CLK_I2C1_PLL_SEL_SHIFT,
337 			     (src_clk_div - 1) << CLK_I2C1_DIV_CON_SHIFT |
338 			     CLK_I2C_PLL_SEL_GPLL << CLK_I2C1_PLL_SEL_SHIFT);
339 		break;
340 	case SCLK_I2C2:
341 		rk_clrsetreg(&cru->clksel_con[50],
342 			     CLK_I2C_DIV_CON_MASK << CLK_I2C2_DIV_CON_SHIFT |
343 			     CLK_I2C_PLL_SEL_MASK << CLK_I2C2_PLL_SEL_SHIFT,
344 			     (src_clk_div - 1) << CLK_I2C2_DIV_CON_SHIFT |
345 			     CLK_I2C_PLL_SEL_GPLL << CLK_I2C2_PLL_SEL_SHIFT);
346 		break;
347 	case SCLK_I2C3:
348 		rk_clrsetreg(&cru->clksel_con[50],
349 			     CLK_I2C_DIV_CON_MASK << CLK_I2C3_DIV_CON_SHIFT |
350 			     CLK_I2C_PLL_SEL_MASK << CLK_I2C3_PLL_SEL_SHIFT,
351 			     (src_clk_div - 1) << CLK_I2C3_DIV_CON_SHIFT |
352 			     CLK_I2C_PLL_SEL_GPLL << CLK_I2C3_PLL_SEL_SHIFT);
353 		break;
354 	default:
355 		printf("do not support this i2c bus\n");
356 		return -EINVAL;
357 	}
358 
359 	return px30_i2c_get_clk(cru, clk_id);
360 }
361 
362 static ulong px30_mmc_get_clk(struct px30_cru *cru, uint clk_id)
363 {
364 	u32 div, con, con_id;
365 
366 	switch (clk_id) {
367 	case HCLK_SDMMC:
368 	case SCLK_SDMMC:
369 		con_id = 16;
370 		break;
371 	case HCLK_EMMC:
372 	case SCLK_EMMC:
373 	case SCLK_EMMC_SAMPLE:
374 		con_id = 20;
375 		break;
376 	default:
377 		return -EINVAL;
378 	}
379 
380 	con = readl(&cru->clksel_con[con_id]);
381 	div = (con & EMMC_DIV_MASK) >> EMMC_DIV_SHIFT;
382 
383 	if ((con & EMMC_PLL_MASK) >> EMMC_PLL_SHIFT
384 	    == EMMC_SEL_24M)
385 		return DIV_TO_RATE(OSC_HZ, div) / 2;
386 	else
387 		return DIV_TO_RATE(GPLL_HZ, div) / 2;
388 
389 }
390 
391 static ulong px30_mmc_set_clk(struct px30_cru *cru,
392 				ulong clk_id, ulong set_rate)
393 {
394 	int src_clk_div;
395 	u32 con_id;
396 
397 	debug("%s %ld %ld\n", __func__, clk_id, set_rate);
398 	switch (clk_id) {
399 	case HCLK_SDMMC:
400 	case SCLK_SDMMC:
401 		con_id = 16;
402 		break;
403 	case HCLK_EMMC:
404 	case SCLK_EMMC:
405 		con_id = 20;
406 		break;
407 	default:
408 		return -EINVAL;
409 	}
410 	/* Select clk_sdmmc/emmc source from GPLL by default */
411 	/* mmc clock defaulg div 2 internal, need provide double in cru */
412 	src_clk_div = DIV_ROUND_UP(GPLL_HZ / 2, set_rate);
413 
414 	if (src_clk_div > 127) {
415 		/* use 24MHz source for 400KHz clock */
416 		src_clk_div = DIV_ROUND_UP(OSC_HZ / 2, set_rate);
417 		rk_clrsetreg(&cru->clksel_con[con_id],
418 			     EMMC_PLL_MASK | EMMC_DIV_MASK,
419 			     EMMC_SEL_24M << EMMC_PLL_SHIFT |
420 			     (src_clk_div - 1) << EMMC_DIV_SHIFT);
421 	} else {
422 		rk_clrsetreg(&cru->clksel_con[con_id],
423 			     EMMC_PLL_MASK | EMMC_DIV_MASK,
424 			     EMMC_SEL_GPLL << EMMC_PLL_SHIFT |
425 			     (src_clk_div - 1) << EMMC_DIV_SHIFT);
426 	}
427 	rk_clrsetreg(&cru->clksel_con[con_id +1], EMMC_CLK_SEL_MASK,
428 		     EMMC_CLK_SEL_EMMC);
429 
430 	return px30_mmc_get_clk(cru, clk_id);
431 }
432 
433 static ulong px30_pwm_get_clk(struct px30_cru *cru, ulong clk_id)
434 {
435 	u32 div, con;
436 
437 	switch (clk_id) {
438 	case SCLK_PWM0:
439 		con = readl(&cru->clksel_con[52]);
440 		div = con >> CLK_PWM0_DIV_CON_SHIFT & CLK_PWM_DIV_CON_MASK;
441 		break;
442 	case SCLK_PWM1:
443 		con = readl(&cru->clksel_con[52]);
444 		div = con >> CLK_PWM1_DIV_CON_SHIFT & CLK_PWM_DIV_CON_MASK;
445 		break;
446 	default:
447 		printf("do not support this pwm bus\n");
448 		return -EINVAL;
449 	}
450 
451 	return DIV_TO_RATE(GPLL_HZ, div);
452 }
453 
454 static ulong px30_pwm_set_clk(struct px30_cru *cru, ulong clk_id, uint hz)
455 {
456 	int src_clk_div;
457 
458 	src_clk_div = GPLL_HZ / hz;
459 	assert(src_clk_div - 1 < 127);
460 
461 	switch (clk_id) {
462 	case SCLK_PWM0:
463 		rk_clrsetreg(&cru->clksel_con[52],
464 			     CLK_PWM_DIV_CON_MASK << CLK_PWM0_DIV_CON_SHIFT |
465 			     CLK_PWM_PLL_SEL_MASK << CLK_PWM0_PLL_SEL_SHIFT,
466 			     (src_clk_div - 1) << CLK_PWM0_DIV_CON_SHIFT |
467 			     CLK_PWM_PLL_SEL_GPLL << CLK_PWM0_PLL_SEL_SHIFT);
468 		break;
469 	case SCLK_PWM1:
470 		rk_clrsetreg(&cru->clksel_con[52],
471 			     CLK_PWM_DIV_CON_MASK << CLK_PWM1_DIV_CON_SHIFT |
472 			     CLK_PWM_PLL_SEL_MASK << CLK_PWM1_PLL_SEL_SHIFT,
473 			     (src_clk_div - 1) << CLK_PWM1_DIV_CON_SHIFT |
474 			     CLK_PWM_PLL_SEL_GPLL << CLK_PWM1_PLL_SEL_SHIFT);
475 		break;
476 	default:
477 		printf("do not support this pwm bus\n");
478 		return -EINVAL;
479 	}
480 
481 	return px30_pwm_get_clk(cru, clk_id);
482 }
483 
484 static ulong px30_saradc_get_clk(struct px30_cru *cru)
485 {
486 	u32 div, con;
487 
488 	con = readl(&cru->clksel_con[55]);
489 	div = con >> CLK_SARADC_DIV_CON_SHIFT & CLK_SARADC_DIV_CON_MASK;
490 
491 	return DIV_TO_RATE(OSC_HZ, div);
492 }
493 
494 static ulong px30_saradc_set_clk(struct px30_cru *cru, uint hz)
495 {
496 	int src_clk_div;
497 
498 	src_clk_div = OSC_HZ / hz;
499 	assert(src_clk_div - 1 < 2047);
500 
501 	rk_clrsetreg(&cru->clksel_con[55],
502 		     CLK_SARADC_DIV_CON_MASK,
503 		     (src_clk_div - 1) << CLK_SARADC_DIV_CON_SHIFT);
504 
505 	return px30_saradc_get_clk(cru);
506 }
507 
508 static ulong px30_spi_get_clk(struct px30_cru *cru, ulong clk_id)
509 {
510 	u32 div, con;
511 
512 	switch (clk_id) {
513 	case SCLK_SPI0:
514 		con = readl(&cru->clksel_con[53]);
515 		div = con >> CLK_SPI0_DIV_CON_SHIFT & CLK_SPI_DIV_CON_MASK;
516 		break;
517 	case SCLK_SPI1:
518 		con = readl(&cru->clksel_con[53]);
519 		div = con >> CLK_SPI1_DIV_CON_SHIFT & CLK_SPI_DIV_CON_MASK;
520 		break;
521 	default:
522 		printf("do not support this pwm bus\n");
523 		return -EINVAL;
524 	}
525 
526 	return DIV_TO_RATE(GPLL_HZ, div);
527 }
528 
529 static ulong px30_spi_set_clk(struct px30_cru *cru, ulong clk_id, uint hz)
530 {
531 	int src_clk_div;
532 
533 	src_clk_div = GPLL_HZ / hz;
534 	assert(src_clk_div - 1 < 127);
535 
536 	switch (clk_id) {
537 	case SCLK_SPI0:
538 		rk_clrsetreg(&cru->clksel_con[53],
539 			     CLK_SPI_DIV_CON_MASK << CLK_SPI0_DIV_CON_SHIFT |
540 			     CLK_SPI_PLL_SEL_MASK << CLK_SPI0_PLL_SEL_SHIFT,
541 			     (src_clk_div - 1) << CLK_SPI0_DIV_CON_SHIFT |
542 			     CLK_SPI_PLL_SEL_GPLL << CLK_SPI0_PLL_SEL_SHIFT);
543 		break;
544 	case SCLK_SPI1:
545 		rk_clrsetreg(&cru->clksel_con[53],
546 			     CLK_SPI_DIV_CON_MASK << CLK_SPI1_DIV_CON_SHIFT |
547 			     CLK_SPI_PLL_SEL_MASK << CLK_SPI1_PLL_SEL_SHIFT,
548 			     (src_clk_div - 1) << CLK_SPI1_DIV_CON_SHIFT |
549 			     CLK_SPI_PLL_SEL_GPLL << CLK_SPI1_PLL_SEL_SHIFT);
550 		break;
551 	default:
552 		printf("do not support this pwm bus\n");
553 		return -EINVAL;
554 	}
555 
556 	return px30_spi_get_clk(cru, clk_id);
557 }
558 
559 static ulong px30_vop_get_clk(struct px30_cru *cru, ulong clk_id)
560 {
561 	u32 div, con, parent;
562 
563 	switch (clk_id) {
564 	case ACLK_VOPB:
565 		con = readl(&cru->clksel_con[3]);
566 		div = con & ACLK_VO_DIV_MASK;
567 		parent = GPLL_HZ;
568 		break;
569 	case DCLK_VOPB:
570 		con = readl(&cru->clksel_con[5]);
571 		div = con & DCLK_VOPB_DIV_MASK;
572 		parent = rkclk_pll_get_rate(cru, CPLL);
573 		break;
574 	default:
575 		return -ENOENT;
576 	}
577 
578 	return DIV_TO_RATE(parent, div);
579 }
580 
581 static ulong px30_vop_set_clk(struct px30_cru *cru, ulong clk_id, uint hz)
582 {
583 	int src_clk_div;
584 	struct pll_div cpll_config = {0};
585 
586 	src_clk_div = GPLL_HZ / hz;
587 	assert(src_clk_div - 1 < 31);
588 
589 	switch (clk_id) {
590 	case ACLK_VOPB:
591 		rk_clrsetreg(&cru->clksel_con[3],
592 			     ACLK_VO_PLL_MASK | ACLK_VO_DIV_MASK,
593 			     ACLK_VO_SEL_GPLL << ACLK_VO_PLL_SHIFT |
594 			     (src_clk_div - 1) << ACLK_VO_DIV_SHIFT);
595 		break;
596 	case DCLK_VOPB:
597 		/*
598 		 * vopb dclk source from cpll, and equals to
599 		 * cpll(means div == 1)
600 		 */
601 		if (pll_para_config(hz, &cpll_config))
602 			return -1;
603 		rkclk_set_pll(cru, CPLL, &cpll_config);
604 
605 		rk_clrsetreg(&cru->clksel_con[5],
606 			     DCLK_VOPB_SEL_MASK | DCLK_VOPB_PLL_SEL_MASK |
607 			     DCLK_VOPB_DIV_MASK,
608 			     DCLK_VOPB_SEL_DIVOUT << DCLK_VOPB_SEL_SHIFT |
609 			     DCLK_VOPB_PLL_SEL_CPLL << DCLK_VOPB_PLL_SEL_SHIFT |
610 			     (1 - 1) << DCLK_VOPB_DIV_SHIFT);
611 		break;
612 	default:
613 		printf("do not support this vop freq\n");
614 		return -EINVAL;
615 	}
616 
617 	return hz;
618 }
619 
620 static ulong px30_clk_get_rate(struct clk *clk)
621 {
622 	struct px30_clk_priv *priv = dev_get_priv(clk->dev);
623 	ulong rate = 0;
624 
625 	switch (clk->id) {
626 	case 0 ... 15:
627 		return 0;
628 	case HCLK_SDMMC:
629 	case HCLK_EMMC:
630 	case SCLK_SDMMC:
631 	case SCLK_EMMC:
632 	case SCLK_EMMC_SAMPLE:
633 		rate = px30_mmc_get_clk(priv->cru, clk->id);
634 		break;
635 	case SCLK_I2C0:
636 	case SCLK_I2C1:
637 	case SCLK_I2C2:
638 	case SCLK_I2C3:
639 		rate = px30_i2c_get_clk(priv->cru, clk->id);
640 		break;
641 	case SCLK_PWM0:
642 	case SCLK_PWM1:
643 		rate = px30_pwm_get_clk(priv->cru, clk->id);
644 		break;
645 	case SCLK_SARADC:
646 		rate = px30_saradc_get_clk(priv->cru);
647 		break;
648 	case SCLK_SPI0:
649 	case SCLK_SPI1:
650 		rate = px30_spi_get_clk(priv->cru, clk->id);
651 		break;
652 	case ACLK_VOPB:
653 	case DCLK_VOPB:
654 		rate = px30_vop_get_clk(priv->cru, clk->id);
655 		break;
656 	default:
657 		return -ENOENT;
658 	}
659 
660 	return rate;
661 }
662 
663 static ulong px30_clk_set_rate(struct clk *clk, ulong rate)
664 {
665 	struct px30_clk_priv *priv = dev_get_priv(clk->dev);
666 	ulong ret = 0;
667 
668 	debug("%s %ld %ld\n", __func__, clk->id, rate);
669 	switch (clk->id) {
670 	case 0 ... 15:
671 		return 0;
672 	case HCLK_SDMMC:
673 	case HCLK_EMMC:
674 	case SCLK_SDMMC:
675 	case SCLK_EMMC:
676 		ret = px30_mmc_set_clk(priv->cru, clk->id, rate);
677 		break;
678 	case SCLK_I2C0:
679 	case SCLK_I2C1:
680 	case SCLK_I2C2:
681 	case SCLK_I2C3:
682 		ret = px30_i2c_set_clk(priv->cru, clk->id, rate);
683 		break;
684 	case SCLK_PWM0:
685 	case SCLK_PWM1:
686 		ret = px30_pwm_set_clk(priv->cru, clk->id, rate);
687 		break;
688 	case SCLK_SARADC:
689 		ret = px30_saradc_set_clk(priv->cru, rate);
690 		break;
691 	case SCLK_SPI0:
692 	case SCLK_SPI1:
693 		ret = px30_spi_set_clk(priv->cru, clk->id, rate);
694 		break;
695 	case ACLK_VOPB:
696 	case DCLK_VOPB:
697 		ret = px30_vop_set_clk(priv->cru, clk->id, rate);
698 		break;
699 	default:
700 		return -ENOENT;
701 	}
702 
703 	return ret;
704 }
705 
706 #define ROCKCHIP_MMC_DELAY_SEL		BIT(10)
707 #define ROCKCHIP_MMC_DEGREE_MASK	0x3
708 #define ROCKCHIP_MMC_DELAYNUM_OFFSET	2
709 #define ROCKCHIP_MMC_DELAYNUM_MASK	(0xff << ROCKCHIP_MMC_DELAYNUM_OFFSET)
710 
711 #define PSECS_PER_SEC 1000000000000LL
712 /*
713  * Each fine delay is between 44ps-77ps. Assume each fine delay is 60ps to
714  * simplify calculations. So 45degs could be anywhere between 33deg and 57.8deg.
715  */
716 #define ROCKCHIP_MMC_DELAY_ELEMENT_PSEC 60
717 
718 int rockchip_mmc_get_phase(struct clk *clk)
719 {
720 	struct px30_clk_priv *priv = dev_get_priv(clk->dev);
721 	struct px30_cru *cru = priv->cru;
722 	u32 raw_value, delay_num;
723 	u16 degrees = 0;
724 	ulong rate;
725 
726 	rate = px30_clk_get_rate(clk);
727 
728 	if (rate < 0)
729 		return rate;
730 
731 	if (clk->id == SCLK_EMMC_SAMPLE)
732 		raw_value = readl(&cru->emmc_con[1]);
733 	else
734 		raw_value = readl(&cru->sdmmc_con[1]);
735 
736 	raw_value >>= 1;
737 	degrees = (raw_value & ROCKCHIP_MMC_DEGREE_MASK) * 90;
738 
739 	if (raw_value & ROCKCHIP_MMC_DELAY_SEL) {
740 		/* degrees/delaynum * 10000 */
741 		unsigned long factor = (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10) *
742 					36 * (rate / 1000000);
743 
744 		delay_num = (raw_value & ROCKCHIP_MMC_DELAYNUM_MASK);
745 		delay_num >>= ROCKCHIP_MMC_DELAYNUM_OFFSET;
746 		degrees += DIV_ROUND_CLOSEST(delay_num * factor, 10000);
747 	}
748 
749 	return degrees % 360;
750 }
751 
752 int rockchip_mmc_set_phase(struct clk *clk, u32 degrees)
753 {
754 	struct px30_clk_priv *priv = dev_get_priv(clk->dev);
755 	struct px30_cru *cru = priv->cru;
756 	u8 nineties, remainder, delay_num;
757 	u32 raw_value, delay;
758 	ulong rate;
759 
760 	rate = px30_clk_get_rate(clk);
761 
762 	if (rate < 0)
763 		return rate;
764 
765 	nineties = degrees / 90;
766 	remainder = (degrees % 90);
767 
768 	/*
769 	 * Convert to delay; do a little extra work to make sure we
770 	 * don't overflow 32-bit / 64-bit numbers.
771 	 */
772 	delay = 10000000; /* PSECS_PER_SEC / 10000 / 10 */
773 	delay *= remainder;
774 	delay = DIV_ROUND_CLOSEST(delay, (rate / 1000) * 36 *
775 				(ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10));
776 
777 	delay_num = (u8)min_t(u32, delay, 255);
778 
779 	raw_value = delay_num ? ROCKCHIP_MMC_DELAY_SEL : 0;
780 	raw_value |= delay_num << ROCKCHIP_MMC_DELAYNUM_OFFSET;
781 	raw_value |= nineties;
782 
783 	raw_value <<= 1;
784 	if (clk->id == SCLK_EMMC_SAMPLE)
785 		writel(raw_value | 0xffff0000, &cru->emmc_con[1]);
786 	else
787 		writel(raw_value | 0xffff0000, &cru->sdmmc_con[1]);
788 
789 	debug("mmc set_phase(%d) delay_nums=%u reg=%#x actual_degrees=%d\n",
790 	      degrees, delay_num, raw_value, rockchip_mmc_get_phase(clk));
791 
792 	return 0;
793 }
794 
795 static int px30_clk_get_phase(struct clk *clk)
796 {
797 	int ret;
798 
799 	switch (clk->id) {
800 	case SCLK_EMMC_SAMPLE:
801 	case SCLK_SDMMC_SAMPLE:
802 		ret = rockchip_mmc_get_phase(clk);
803 		break;
804 	default:
805 		return -ENOENT;
806 	}
807 
808 	return ret;
809 }
810 
811 static int px30_clk_set_phase(struct clk *clk, int degrees)
812 {
813 	int ret;
814 
815 	switch (clk->id) {
816 	case SCLK_EMMC_SAMPLE:
817 	case SCLK_SDMMC_SAMPLE:
818 		ret = rockchip_mmc_set_phase(clk, degrees);
819 		break;
820 	default:
821 		return -ENOENT;
822 	}
823 
824 	return ret;
825 }
826 
827 static struct clk_ops px30_clk_ops = {
828 	.get_rate = px30_clk_get_rate,
829 	.set_rate = px30_clk_set_rate,
830 	.get_phase	= px30_clk_get_phase,
831 	.set_phase	= px30_clk_set_phase,
832 };
833 
834 static int px30_clk_probe(struct udevice *dev)
835 {
836 	struct px30_clk_priv *priv = dev_get_priv(dev);
837 	u32 reg = readl(&priv->cru->clksel_con[23]);
838 
839 	/* Only do the rkclk_init() one time for boot up */
840 	if (((reg & BUS_ACLK_DIV_MASK) >> BUS_ACLK_DIV_SHIFT) !=
841 	    (GPLL_HZ / BUS_ACLK_HZ - 1))
842 		rkclk_init(priv->cru);
843 
844 	return 0;
845 }
846 
847 static int px30_clk_ofdata_to_platdata(struct udevice *dev)
848 {
849 	struct px30_clk_priv *priv = dev_get_priv(dev);
850 
851 	priv->cru = dev_read_addr_ptr(dev);
852 
853 	return 0;
854 }
855 
856 static int px30_clk_bind(struct udevice *dev)
857 {
858 	int ret;
859 	struct udevice *sys_child, *sf_child;
860 	struct sysreset_reg *priv;
861 	struct softreset_reg *sf_priv;
862 
863 	/* The reset driver does not have a device node, so bind it here */
864 	ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset",
865 				 &sys_child);
866 	if (ret) {
867 		debug("Warning: No sysreset driver: ret=%d\n", ret);
868 	} else {
869 		priv = malloc(sizeof(struct sysreset_reg));
870 		priv->glb_srst_fst_value = offsetof(struct px30_cru,
871 						    glb_srst_fst);
872 		priv->glb_srst_snd_value = offsetof(struct px30_cru,
873 						    glb_srst_snd);
874 		sys_child->priv = priv;
875 	}
876 
877 	ret = device_bind_driver_to_node(dev, "rockchip_reset", "reset",
878 					 dev_ofnode(dev), &sf_child);
879 	if (ret) {
880 		debug("Warning: No rockchip reset driver: ret=%d\n", ret);
881 	} else {
882 		sf_priv = malloc(sizeof(struct softreset_reg));
883 		sf_priv->sf_reset_offset = offsetof(struct px30_cru,
884 						    softrst_con[0]);
885 		sf_priv->sf_reset_num = 12;
886 		sf_child->priv = sf_priv;
887 	}
888 
889 	return 0;
890 }
891 
892 static const struct udevice_id px30_clk_ids[] = {
893 	{ .compatible = "rockchip,px30-cru" },
894 	{ }
895 };
896 
897 U_BOOT_DRIVER(rockchip_px30_cru) = {
898 	.name		= "rockchip_px30_cru",
899 	.id		= UCLASS_CLK,
900 	.of_match	= px30_clk_ids,
901 	.priv_auto_alloc_size = sizeof(struct px30_clk_priv),
902 	.ofdata_to_platdata = px30_clk_ofdata_to_platdata,
903 	.ops		= &px30_clk_ops,
904 	.bind		= px30_clk_bind,
905 	.probe		= px30_clk_probe,
906 };
907