xref: /rk3399_rockchip-uboot/drivers/clk/rockchip/clk_px30.c (revision e7b5bb3cc9527752c2c01acb4325fc0721fb75aa)
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 PX30_PLL_RATE(_rate, _refdiv, _fbdiv, _postdiv1,	\
30 			_postdiv2, _dsmpd, _frac)		\
31 {								\
32 	.rate	= _rate##U,					\
33 	.fbdiv = _fbdiv,					\
34 	.postdiv1 = _postdiv1,					\
35 	.refdiv = _refdiv,					\
36 	.postdiv2 = _postdiv2,					\
37 	.dsmpd = _dsmpd,					\
38 	.frac = _frac,						\
39 }
40 
41 #define PX30_CPUCLK_RATE(_rate, _aclk_div, _pclk_div)		\
42 {								\
43 	.rate	= _rate##U,					\
44 	.aclk_div = _aclk_div,					\
45 	.pclk_div = _pclk_div,					\
46 }
47 
48 #define DIV_TO_RATE(input_rate, div)    ((input_rate) / ((div) + 1))
49 
50 #define PX30_CLK_DUMP(_id, _name, _iscru)	\
51 {						\
52 	.id = _id,				\
53 	.name = _name,				\
54 	.is_cru = _iscru,			\
55 }
56 
57 static struct pll_rate_table px30_pll_rates[] = {
58 	/* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */
59 	PX30_PLL_RATE(1200000000, 1, 50, 1, 1, 1, 0),
60 	PX30_PLL_RATE(1188000000, 2, 99, 1, 1, 1, 0),
61 	PX30_PLL_RATE(1100000000, 12, 550, 1, 1, 1, 0),
62 	PX30_PLL_RATE(1008000000, 1, 84, 2, 1, 1, 0),
63 	PX30_PLL_RATE(1000000000, 6, 500, 2, 1, 1, 0),
64 	PX30_PLL_RATE(816000000, 1, 68, 2, 1, 1, 0),
65 	PX30_PLL_RATE(600000000, 1, 75, 3, 1, 1, 0),
66 };
67 
68 static const struct px30_clk_info clks_dump[] = {
69 	PX30_CLK_DUMP(PLL_APLL, "apll", true),
70 	PX30_CLK_DUMP(PLL_DPLL, "dpll", true),
71 	PX30_CLK_DUMP(PLL_CPLL, "cpll", true),
72 	PX30_CLK_DUMP(PLL_NPLL, "npll", true),
73 	PX30_CLK_DUMP(PLL_GPLL, "gpll", false),
74 	PX30_CLK_DUMP(ACLK_BUS_PRE, "aclk_bus", true),
75 	PX30_CLK_DUMP(HCLK_BUS_PRE, "hclk_bus", true),
76 	PX30_CLK_DUMP(PCLK_BUS_PRE, "pclk_bus", true),
77 	PX30_CLK_DUMP(ACLK_PERI_PRE, "aclk_peri", true),
78 	PX30_CLK_DUMP(HCLK_PERI_PRE, "hclk_peri", true),
79 	PX30_CLK_DUMP(PCLK_PMU_PRE, "pclk_pmu", false),
80 };
81 
82 static struct cpu_rate_table px30_cpu_rates[] = {
83 	PX30_CPUCLK_RATE(1200000000, 1, 5),
84 	PX30_CPUCLK_RATE(1008000000, 1, 5),
85 	PX30_CPUCLK_RATE(816000000, 1, 3),
86 	PX30_CPUCLK_RATE(600000000, 1, 3),
87 };
88 
89 static u8 pll_mode_shift[PLL_COUNT] = {
90 	APLL_MODE_SHIFT, DPLL_MODE_SHIFT, CPLL_MODE_SHIFT,
91 	NPLL_MODE_SHIFT, GPLL_MODE_SHIFT
92 };
93 static u32 pll_mode_mask[PLL_COUNT] = {
94 	APLL_MODE_MASK, DPLL_MODE_MASK, CPLL_MODE_MASK,
95 	NPLL_MODE_MASK, GPLL_MODE_MASK
96 };
97 
98 static struct pll_rate_table auto_table;
99 
100 static struct pll_rate_table *pll_clk_set_by_auto(u32 drate)
101 {
102 	struct pll_rate_table *rate = &auto_table;
103 	u32 ref_khz = OSC_HZ / KHz, refdiv, fbdiv = 0;
104 	u32 postdiv1, postdiv2 = 1;
105 	u32 fref_khz;
106 	u32 diff_khz, best_diff_khz;
107 	const u32 max_refdiv = 63, max_fbdiv = 3200, min_fbdiv = 16;
108 	const u32 max_postdiv1 = 7, max_postdiv2 = 7;
109 	u32 vco_khz;
110 	u32 rate_khz = drate / KHz;
111 
112 	if (!drate) {
113 		printf("%s: the frequency can't be 0 Hz\n", __func__);
114 		return NULL;
115 	}
116 
117 	postdiv1 = DIV_ROUND_UP(VCO_MIN_HZ / 1000, rate_khz);
118 	if (postdiv1 > max_postdiv1) {
119 		postdiv2 = DIV_ROUND_UP(postdiv1, max_postdiv1);
120 		postdiv1 = DIV_ROUND_UP(postdiv1, postdiv2);
121 	}
122 
123 	vco_khz = rate_khz * postdiv1 * postdiv2;
124 
125 	if (vco_khz < (VCO_MIN_HZ / KHz) || vco_khz > (VCO_MAX_HZ / KHz) ||
126 	    postdiv2 > max_postdiv2) {
127 		printf("%s: Cannot find out a supported VCO for Freq (%uHz)\n",
128 		       __func__, rate_khz);
129 		return NULL;
130 	}
131 
132 	rate->postdiv1 = postdiv1;
133 	rate->postdiv2 = postdiv2;
134 
135 	best_diff_khz = vco_khz;
136 	for (refdiv = 1; refdiv < max_refdiv && best_diff_khz; refdiv++) {
137 		fref_khz = ref_khz / refdiv;
138 
139 		fbdiv = vco_khz / fref_khz;
140 		if ((fbdiv >= max_fbdiv) || (fbdiv <= min_fbdiv))
141 			continue;
142 		diff_khz = vco_khz - fbdiv * fref_khz;
143 		if (fbdiv + 1 < max_fbdiv && diff_khz > fref_khz / 2) {
144 			fbdiv++;
145 			diff_khz = fref_khz - diff_khz;
146 		}
147 
148 		if (diff_khz >= best_diff_khz)
149 			continue;
150 
151 		best_diff_khz = diff_khz;
152 		rate->refdiv = refdiv;
153 		rate->fbdiv = fbdiv;
154 	}
155 
156 	if (best_diff_khz > 4 * (MHz / KHz)) {
157 		printf("%s: Failed to match output frequency %u bestis %u Hz\n",
158 		       __func__, rate_khz,
159 		       best_diff_khz * KHz);
160 		return NULL;
161 	}
162 
163 	return rate;
164 }
165 
166 static const struct pll_rate_table *get_pll_settings(unsigned long rate)
167 {
168 	unsigned int rate_count = ARRAY_SIZE(px30_pll_rates);
169 	int i;
170 
171 	for (i = 0; i < rate_count; i++) {
172 		if (rate == px30_pll_rates[i].rate)
173 			return &px30_pll_rates[i];
174 	}
175 
176 	return pll_clk_set_by_auto(rate);
177 }
178 
179 static const struct cpu_rate_table *get_cpu_settings(unsigned long rate)
180 {
181 	unsigned int rate_count = ARRAY_SIZE(px30_cpu_rates);
182 	int i;
183 
184 	for (i = 0; i < rate_count; i++) {
185 		if (rate == px30_cpu_rates[i].rate)
186 			return &px30_cpu_rates[i];
187 	}
188 
189 	return NULL;
190 }
191 
192 /*
193  * How to calculate the PLL(from TRM V0.3 Part 1 Page 63):
194  * Formulas also embedded within the Fractional PLL Verilog model:
195  * If DSMPD = 1 (DSM is disabled, "integer mode")
196  * FOUTVCO = FREF / REFDIV * FBDIV
197  * FOUTPOSTDIV = FOUTVCO / POSTDIV1 / POSTDIV2
198  * Where:
199  * FOUTVCO = Fractional PLL non-divided output frequency
200  * FOUTPOSTDIV = Fractional PLL divided output frequency
201  *               (output of second post divider)
202  * FREF = Fractional PLL input reference frequency, (the OSC_HZ 24MHz input)
203  * REFDIV = Fractional PLL input reference clock divider
204  * FBDIV = Integer value programmed into feedback divide
205  *
206  */
207 static int rkclk_set_pll(struct px30_pll *pll, unsigned int *mode,
208 			 enum px30_pll_id pll_id,
209 			 unsigned long drate)
210 {
211 	const struct pll_rate_table *rate;
212 	uint vco_hz, output_hz;
213 
214 	rate = get_pll_settings(drate);
215 	if (!rate) {
216 		printf("%s unsupport rate\n", __func__);
217 		return -EINVAL;
218 	}
219 
220 	/* All PLLs have same VCO and output frequency range restrictions. */
221 	vco_hz = OSC_HZ / 1000 * rate->fbdiv / rate->refdiv * 1000;
222 	output_hz = vco_hz / rate->postdiv1 / rate->postdiv2;
223 
224 	debug("PLL at %p: fb=%d, ref=%d, pst1=%d, pst2=%d, vco=%u Hz, output=%u Hz\n",
225 	      pll, rate->fbdiv, rate->refdiv, rate->postdiv1,
226 	      rate->postdiv2, vco_hz, output_hz);
227 	assert(vco_hz >= VCO_MIN_HZ && vco_hz <= VCO_MAX_HZ &&
228 	       output_hz >= OUTPUT_MIN_HZ && output_hz <= OUTPUT_MAX_HZ);
229 
230 	/*
231 	 * When power on or changing PLL setting,
232 	 * we must force PLL into slow mode to ensure output stable clock.
233 	 */
234 	rk_clrsetreg(mode, pll_mode_mask[pll_id],
235 		     PLLMUX_FROM_XIN24M << pll_mode_shift[pll_id]);
236 
237 	/* use integer mode */
238 	rk_setreg(&pll->con1, 1 << PLL_DSMPD_SHIFT);
239 	/* Power down */
240 	rk_setreg(&pll->con1, 1 << PLL_PD_SHIFT);
241 
242 	rk_clrsetreg(&pll->con0,
243 		     PLL_POSTDIV1_MASK | PLL_FBDIV_MASK,
244 		     (rate->postdiv1 << PLL_POSTDIV1_SHIFT) | rate->fbdiv);
245 	rk_clrsetreg(&pll->con1, PLL_POSTDIV2_MASK | PLL_REFDIV_MASK,
246 		     (rate->postdiv2 << PLL_POSTDIV2_SHIFT |
247 		     rate->refdiv << PLL_REFDIV_SHIFT));
248 
249 	/* Power Up */
250 	rk_clrreg(&pll->con1, 1 << PLL_PD_SHIFT);
251 
252 	/* waiting for pll lock */
253 	while (!(readl(&pll->con1) & (1 << PLL_LOCK_STATUS_SHIFT)))
254 		udelay(1);
255 
256 	rk_clrsetreg(mode, pll_mode_mask[pll_id],
257 		     PLLMUX_FROM_PLL << pll_mode_shift[pll_id]);
258 
259 	return 0;
260 }
261 
262 static uint32_t rkclk_pll_get_rate(struct px30_pll *pll, unsigned int *mode,
263 				   enum px30_pll_id pll_id)
264 {
265 	u32 refdiv, fbdiv, postdiv1, postdiv2;
266 	u32 con, shift, mask;
267 
268 	con = readl(mode);
269 	shift = pll_mode_shift[pll_id];
270 	mask = pll_mode_mask[pll_id];
271 
272 	switch ((con & mask) >> shift) {
273 	case PLLMUX_FROM_XIN24M:
274 		return OSC_HZ;
275 	case PLLMUX_FROM_PLL:
276 		/* normal mode */
277 		con = readl(&pll->con0);
278 		postdiv1 = (con & PLL_POSTDIV1_MASK) >> PLL_POSTDIV1_SHIFT;
279 		fbdiv = (con & PLL_FBDIV_MASK) >> PLL_FBDIV_SHIFT;
280 		con = readl(&pll->con1);
281 		postdiv2 = (con & PLL_POSTDIV2_MASK) >> PLL_POSTDIV2_SHIFT;
282 		refdiv = (con & PLL_REFDIV_MASK) >> PLL_REFDIV_SHIFT;
283 		return (24 * fbdiv / (refdiv * postdiv1 * postdiv2)) * 1000000;
284 	case PLLMUX_FROM_RTC32K:
285 	default:
286 		return 32768;
287 	}
288 }
289 
290 static ulong px30_i2c_get_clk(struct px30_clk_priv *priv, ulong clk_id)
291 {
292 	struct px30_cru *cru = priv->cru;
293 	u32 div, con;
294 
295 	switch (clk_id) {
296 	case SCLK_I2C0:
297 		con = readl(&cru->clksel_con[49]);
298 		div = con >> CLK_I2C0_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK;
299 		break;
300 	case SCLK_I2C1:
301 		con = readl(&cru->clksel_con[49]);
302 		div = con >> CLK_I2C1_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK;
303 		break;
304 	case SCLK_I2C2:
305 		con = readl(&cru->clksel_con[50]);
306 		div = con >> CLK_I2C2_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK;
307 		break;
308 	case SCLK_I2C3:
309 		con = readl(&cru->clksel_con[50]);
310 		div = con >> CLK_I2C3_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK;
311 		break;
312 	default:
313 		printf("do not support this i2c bus\n");
314 		return -EINVAL;
315 	}
316 
317 	return DIV_TO_RATE(priv->gpll_hz, div);
318 }
319 
320 static ulong px30_i2c_set_clk(struct px30_clk_priv *priv, ulong clk_id, uint hz)
321 {
322 	struct px30_cru *cru = priv->cru;
323 	int src_clk_div;
324 
325 	src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
326 	assert(src_clk_div - 1 < 127);
327 
328 	switch (clk_id) {
329 	case SCLK_I2C0:
330 		rk_clrsetreg(&cru->clksel_con[49],
331 			     CLK_I2C_DIV_CON_MASK << CLK_I2C0_DIV_CON_SHIFT |
332 			     CLK_I2C_PLL_SEL_MASK << CLK_I2C0_PLL_SEL_SHIFT,
333 			     (src_clk_div - 1) << CLK_I2C0_DIV_CON_SHIFT |
334 			     CLK_I2C_PLL_SEL_GPLL << CLK_I2C0_PLL_SEL_SHIFT);
335 		break;
336 	case SCLK_I2C1:
337 		rk_clrsetreg(&cru->clksel_con[49],
338 			     CLK_I2C_DIV_CON_MASK << CLK_I2C1_DIV_CON_SHIFT |
339 			     CLK_I2C_PLL_SEL_MASK << CLK_I2C1_PLL_SEL_SHIFT,
340 			     (src_clk_div - 1) << CLK_I2C1_DIV_CON_SHIFT |
341 			     CLK_I2C_PLL_SEL_GPLL << CLK_I2C1_PLL_SEL_SHIFT);
342 		break;
343 	case SCLK_I2C2:
344 		rk_clrsetreg(&cru->clksel_con[50],
345 			     CLK_I2C_DIV_CON_MASK << CLK_I2C2_DIV_CON_SHIFT |
346 			     CLK_I2C_PLL_SEL_MASK << CLK_I2C2_PLL_SEL_SHIFT,
347 			     (src_clk_div - 1) << CLK_I2C2_DIV_CON_SHIFT |
348 			     CLK_I2C_PLL_SEL_GPLL << CLK_I2C2_PLL_SEL_SHIFT);
349 		break;
350 	case SCLK_I2C3:
351 		rk_clrsetreg(&cru->clksel_con[50],
352 			     CLK_I2C_DIV_CON_MASK << CLK_I2C3_DIV_CON_SHIFT |
353 			     CLK_I2C_PLL_SEL_MASK << CLK_I2C3_PLL_SEL_SHIFT,
354 			     (src_clk_div - 1) << CLK_I2C3_DIV_CON_SHIFT |
355 			     CLK_I2C_PLL_SEL_GPLL << CLK_I2C3_PLL_SEL_SHIFT);
356 		break;
357 	default:
358 		printf("do not support this i2c bus\n");
359 		return -EINVAL;
360 	}
361 
362 	return px30_i2c_get_clk(priv, clk_id);
363 }
364 
365 static ulong px30_nandc_get_clk(struct px30_clk_priv *priv)
366 {
367 	struct px30_cru *cru = priv->cru;
368 	u32 div, con;
369 
370 	con = readl(&cru->clksel_con[15]);
371 	div = (con & NANDC_DIV_MASK) >> NANDC_DIV_SHIFT;
372 
373 	return DIV_TO_RATE(priv->gpll_hz, div);
374 }
375 
376 static ulong px30_nandc_set_clk(struct px30_clk_priv *priv,
377 				ulong set_rate)
378 {
379 	struct px30_cru *cru = priv->cru;
380 	int src_clk_div;
381 
382 	/* Select nandc source from GPLL by default */
383 	/* nandc clock defaulg div 2 internal, need provide double in cru */
384 	src_clk_div = DIV_ROUND_UP(priv->gpll_hz, set_rate);
385 	assert(src_clk_div - 1 < 31);
386 
387 	rk_clrsetreg(&cru->clksel_con[15],
388 		     NANDC_CLK_SEL_MASK | NANDC_PLL_MASK |
389 		     NANDC_DIV_MASK,
390 		     NANDC_CLK_SEL_NANDC << NANDC_CLK_SEL_SHIFT |
391 		     NANDC_SEL_GPLL << NANDC_PLL_SHIFT |
392 		     (src_clk_div - 1) << NANDC_DIV_SHIFT);
393 
394 	return px30_nandc_get_clk(priv);
395 }
396 
397 static ulong px30_mmc_get_clk(struct px30_clk_priv *priv, uint clk_id)
398 {
399 	struct px30_cru *cru = priv->cru;
400 	u32 div, con, con_id;
401 
402 	switch (clk_id) {
403 	case HCLK_SDMMC:
404 	case SCLK_SDMMC:
405 		con_id = 16;
406 		break;
407 	case HCLK_EMMC:
408 	case SCLK_EMMC:
409 	case SCLK_EMMC_SAMPLE:
410 		con_id = 20;
411 		break;
412 	default:
413 		return -EINVAL;
414 	}
415 
416 	con = readl(&cru->clksel_con[con_id]);
417 	div = (con & EMMC_DIV_MASK) >> EMMC_DIV_SHIFT;
418 
419 	if ((con & EMMC_PLL_MASK) >> EMMC_PLL_SHIFT
420 	    == EMMC_SEL_24M)
421 		return DIV_TO_RATE(OSC_HZ, div) / 2;
422 	else
423 		return DIV_TO_RATE(priv->gpll_hz, div) / 2;
424 
425 }
426 
427 static ulong px30_mmc_set_clk(struct px30_clk_priv *priv,
428 			      ulong clk_id, ulong set_rate)
429 {
430 	struct px30_cru *cru = priv->cru;
431 	int src_clk_div;
432 	u32 con_id;
433 
434 	switch (clk_id) {
435 	case HCLK_SDMMC:
436 	case SCLK_SDMMC:
437 		con_id = 16;
438 		break;
439 	case HCLK_EMMC:
440 	case SCLK_EMMC:
441 		con_id = 20;
442 		break;
443 	default:
444 		return -EINVAL;
445 	}
446 
447 	/* Select clk_sdmmc/emmc source from GPLL by default */
448 	/* mmc clock defaulg div 2 internal, need provide double in cru */
449 	src_clk_div = DIV_ROUND_UP(priv->gpll_hz / 2, set_rate);
450 
451 	if (src_clk_div > 127) {
452 		/* use 24MHz source for 400KHz clock */
453 		src_clk_div = DIV_ROUND_UP(OSC_HZ / 2, set_rate);
454 		rk_clrsetreg(&cru->clksel_con[con_id],
455 			     EMMC_PLL_MASK | EMMC_DIV_MASK,
456 			     EMMC_SEL_24M << EMMC_PLL_SHIFT |
457 			     (src_clk_div - 1) << EMMC_DIV_SHIFT);
458 	} else {
459 		rk_clrsetreg(&cru->clksel_con[con_id],
460 			     EMMC_PLL_MASK | EMMC_DIV_MASK,
461 			     EMMC_SEL_GPLL << EMMC_PLL_SHIFT |
462 			     (src_clk_div - 1) << EMMC_DIV_SHIFT);
463 	}
464 	rk_clrsetreg(&cru->clksel_con[con_id +1], EMMC_CLK_SEL_MASK,
465 		     EMMC_CLK_SEL_EMMC);
466 
467 	return px30_mmc_get_clk(priv, clk_id);
468 }
469 
470 static ulong px30_pwm_get_clk(struct px30_clk_priv *priv, ulong clk_id)
471 {
472 	struct px30_cru *cru = priv->cru;
473 	u32 div, con;
474 
475 	switch (clk_id) {
476 	case SCLK_PWM0:
477 		con = readl(&cru->clksel_con[52]);
478 		div = con >> CLK_PWM0_DIV_CON_SHIFT & CLK_PWM_DIV_CON_MASK;
479 		break;
480 	case SCLK_PWM1:
481 		con = readl(&cru->clksel_con[52]);
482 		div = con >> CLK_PWM1_DIV_CON_SHIFT & CLK_PWM_DIV_CON_MASK;
483 		break;
484 	default:
485 		printf("do not support this pwm bus\n");
486 		return -EINVAL;
487 	}
488 
489 	return DIV_TO_RATE(priv->gpll_hz, div);
490 }
491 
492 static ulong px30_pwm_set_clk(struct px30_clk_priv *priv, ulong clk_id, uint hz)
493 {
494 	struct px30_cru *cru = priv->cru;
495 	int src_clk_div;
496 
497 	src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
498 	assert(src_clk_div - 1 < 127);
499 
500 	switch (clk_id) {
501 	case SCLK_PWM0:
502 		rk_clrsetreg(&cru->clksel_con[52],
503 			     CLK_PWM_DIV_CON_MASK << CLK_PWM0_DIV_CON_SHIFT |
504 			     CLK_PWM_PLL_SEL_MASK << CLK_PWM0_PLL_SEL_SHIFT,
505 			     (src_clk_div - 1) << CLK_PWM0_DIV_CON_SHIFT |
506 			     CLK_PWM_PLL_SEL_GPLL << CLK_PWM0_PLL_SEL_SHIFT);
507 		break;
508 	case SCLK_PWM1:
509 		rk_clrsetreg(&cru->clksel_con[52],
510 			     CLK_PWM_DIV_CON_MASK << CLK_PWM1_DIV_CON_SHIFT |
511 			     CLK_PWM_PLL_SEL_MASK << CLK_PWM1_PLL_SEL_SHIFT,
512 			     (src_clk_div - 1) << CLK_PWM1_DIV_CON_SHIFT |
513 			     CLK_PWM_PLL_SEL_GPLL << CLK_PWM1_PLL_SEL_SHIFT);
514 		break;
515 	default:
516 		printf("do not support this pwm bus\n");
517 		return -EINVAL;
518 	}
519 
520 	return px30_pwm_get_clk(priv, clk_id);
521 }
522 
523 static ulong px30_saradc_get_clk(struct px30_clk_priv *priv)
524 {
525 	struct px30_cru *cru = priv->cru;
526 	u32 div, con;
527 
528 	con = readl(&cru->clksel_con[55]);
529 	div = con >> CLK_SARADC_DIV_CON_SHIFT & CLK_SARADC_DIV_CON_MASK;
530 
531 	return DIV_TO_RATE(OSC_HZ, div);
532 }
533 
534 static ulong px30_saradc_set_clk(struct px30_clk_priv *priv, uint hz)
535 {
536 	struct px30_cru *cru = priv->cru;
537 	int src_clk_div;
538 
539 	src_clk_div = DIV_ROUND_UP(OSC_HZ, hz);
540 	assert(src_clk_div - 1 < 2047);
541 
542 	rk_clrsetreg(&cru->clksel_con[55],
543 		     CLK_SARADC_DIV_CON_MASK,
544 		     (src_clk_div - 1) << CLK_SARADC_DIV_CON_SHIFT);
545 
546 	return px30_saradc_get_clk(priv);
547 }
548 
549 static ulong px30_spi_get_clk(struct px30_clk_priv *priv, ulong clk_id)
550 {
551 	struct px30_cru *cru = priv->cru;
552 	u32 div, con;
553 
554 	switch (clk_id) {
555 	case SCLK_SPI0:
556 		con = readl(&cru->clksel_con[53]);
557 		div = con >> CLK_SPI0_DIV_CON_SHIFT & CLK_SPI_DIV_CON_MASK;
558 		break;
559 	case SCLK_SPI1:
560 		con = readl(&cru->clksel_con[53]);
561 		div = con >> CLK_SPI1_DIV_CON_SHIFT & CLK_SPI_DIV_CON_MASK;
562 		break;
563 	default:
564 		printf("do not support this pwm bus\n");
565 		return -EINVAL;
566 	}
567 
568 	return DIV_TO_RATE(priv->gpll_hz, div);
569 }
570 
571 static ulong px30_spi_set_clk(struct px30_clk_priv *priv, ulong clk_id, uint hz)
572 {
573 	struct px30_cru *cru = priv->cru;
574 	int src_clk_div;
575 
576 	src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
577 	assert(src_clk_div - 1 < 127);
578 
579 	switch (clk_id) {
580 	case SCLK_SPI0:
581 		rk_clrsetreg(&cru->clksel_con[53],
582 			     CLK_SPI_DIV_CON_MASK << CLK_SPI0_DIV_CON_SHIFT |
583 			     CLK_SPI_PLL_SEL_MASK << CLK_SPI0_PLL_SEL_SHIFT,
584 			     (src_clk_div - 1) << CLK_SPI0_DIV_CON_SHIFT |
585 			     CLK_SPI_PLL_SEL_GPLL << CLK_SPI0_PLL_SEL_SHIFT);
586 		break;
587 	case SCLK_SPI1:
588 		rk_clrsetreg(&cru->clksel_con[53],
589 			     CLK_SPI_DIV_CON_MASK << CLK_SPI1_DIV_CON_SHIFT |
590 			     CLK_SPI_PLL_SEL_MASK << CLK_SPI1_PLL_SEL_SHIFT,
591 			     (src_clk_div - 1) << CLK_SPI1_DIV_CON_SHIFT |
592 			     CLK_SPI_PLL_SEL_GPLL << CLK_SPI1_PLL_SEL_SHIFT);
593 		break;
594 	default:
595 		printf("do not support this pwm bus\n");
596 		return -EINVAL;
597 	}
598 
599 	return px30_spi_get_clk(priv, clk_id);
600 }
601 
602 static ulong px30_vop_get_clk(struct px30_clk_priv *priv, ulong clk_id)
603 {
604 	struct px30_cru *cru = priv->cru;
605 	u32 div, con, parent;
606 
607 	switch (clk_id) {
608 	case ACLK_VOPB:
609 		con = readl(&cru->clksel_con[3]);
610 		div = con & ACLK_VO_DIV_MASK;
611 		parent = priv->gpll_hz;
612 		break;
613 	case DCLK_VOPB:
614 		con = readl(&cru->clksel_con[5]);
615 		div = con & DCLK_VOPB_DIV_MASK;
616 		parent = rkclk_pll_get_rate(&cru->pll[CPLL], &cru->mode, CPLL);
617 		break;
618 	default:
619 		return -ENOENT;
620 	}
621 
622 	return DIV_TO_RATE(parent, div);
623 }
624 
625 static ulong px30_vop_set_clk(struct px30_clk_priv *priv, ulong clk_id, uint hz)
626 {
627 	struct px30_cru *cru = priv->cru;
628 	int src_clk_div;
629 
630 	src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
631 	assert(src_clk_div - 1 < 31);
632 
633 	switch (clk_id) {
634 	case ACLK_VOPB:
635 		rk_clrsetreg(&cru->clksel_con[3],
636 			     ACLK_VO_PLL_MASK | ACLK_VO_DIV_MASK,
637 			     ACLK_VO_SEL_GPLL << ACLK_VO_PLL_SHIFT |
638 			     (src_clk_div - 1) << ACLK_VO_DIV_SHIFT);
639 		break;
640 	case DCLK_VOPB:
641 		/*
642 		 * vopb dclk source from cpll, and equals to
643 		 * cpll(means div == 1)
644 		 */
645 		rkclk_set_pll(&cru->pll[CPLL], &cru->mode, CPLL, hz);
646 
647 		rk_clrsetreg(&cru->clksel_con[5],
648 			     DCLK_VOPB_SEL_MASK | DCLK_VOPB_PLL_SEL_MASK |
649 			     DCLK_VOPB_DIV_MASK,
650 			     DCLK_VOPB_SEL_DIVOUT << DCLK_VOPB_SEL_SHIFT |
651 			     DCLK_VOPB_PLL_SEL_CPLL << DCLK_VOPB_PLL_SEL_SHIFT |
652 			     (1 - 1) << DCLK_VOPB_DIV_SHIFT);
653 		break;
654 	default:
655 		printf("do not support this vop freq\n");
656 		return -EINVAL;
657 	}
658 
659 	return px30_vop_get_clk(priv, clk_id);
660 }
661 
662 static ulong px30_bus_get_clk(struct px30_clk_priv *priv, ulong clk_id)
663 {
664 	struct px30_cru *cru = priv->cru;
665 	u32 div, con, parent;
666 
667 	switch (clk_id) {
668 	case ACLK_BUS_PRE:
669 		con = readl(&cru->clksel_con[23]);
670 		div = (con & BUS_ACLK_DIV_MASK) >> BUS_ACLK_DIV_SHIFT;
671 		parent = priv->gpll_hz;
672 		break;
673 	case HCLK_BUS_PRE:
674 		con = readl(&cru->clksel_con[24]);
675 		div = (con & BUS_HCLK_DIV_MASK) >> BUS_HCLK_DIV_SHIFT;
676 		parent = priv->gpll_hz;
677 		break;
678 	case PCLK_BUS_PRE:
679 		parent = px30_bus_get_clk(priv, ACLK_BUS_PRE);
680 		con = readl(&cru->clksel_con[24]);
681 		div = (con & BUS_PCLK_DIV_MASK) >> BUS_PCLK_DIV_SHIFT;
682 		break;
683 	default:
684 		return -ENOENT;
685 	}
686 
687 	return DIV_TO_RATE(parent, div);
688 }
689 
690 static ulong px30_bus_set_clk(struct px30_clk_priv *priv, ulong clk_id,
691 			      ulong hz)
692 {
693 	struct px30_cru *cru = priv->cru;
694 	int src_clk_div;
695 
696 	/*
697 	 * select gpll as pd_bus bus clock source and
698 	 * set up dependent divisors for PCLK/HCLK and ACLK clocks.
699 	 */
700 	switch (clk_id) {
701 	case ACLK_BUS_PRE:
702 		src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
703 		assert(src_clk_div - 1 < 31);
704 		rk_clrsetreg(&cru->clksel_con[23],
705 			     BUS_PLL_SEL_MASK | BUS_ACLK_DIV_MASK,
706 			     BUS_PLL_SEL_GPLL << BUS_PLL_SEL_SHIFT |
707 			     (src_clk_div - 1) << BUS_ACLK_DIV_SHIFT);
708 		break;
709 	case HCLK_BUS_PRE:
710 		src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
711 		assert(src_clk_div - 1 < 31);
712 		rk_clrsetreg(&cru->clksel_con[24],
713 			     BUS_PLL_SEL_MASK | BUS_HCLK_DIV_MASK,
714 			     BUS_PLL_SEL_GPLL << BUS_PLL_SEL_SHIFT |
715 			     (src_clk_div - 1) << BUS_HCLK_DIV_SHIFT);
716 		break;
717 	case PCLK_BUS_PRE:
718 		src_clk_div =
719 			DIV_ROUND_UP(px30_bus_get_clk(priv, ACLK_BUS_PRE), hz);
720 		assert(src_clk_div - 1 < 3);
721 		rk_clrsetreg(&cru->clksel_con[24],
722 			     BUS_PCLK_DIV_MASK,
723 			     (src_clk_div - 1) << BUS_PCLK_DIV_SHIFT);
724 		break;
725 	default:
726 		printf("do not support this bus freq\n");
727 		return -EINVAL;
728 	}
729 
730 	return px30_bus_get_clk(priv, clk_id);
731 }
732 
733 static ulong px30_peri_get_clk(struct px30_clk_priv *priv, ulong clk_id)
734 {
735 	struct px30_cru *cru = priv->cru;
736 	u32 div, con, parent;
737 
738 	switch (clk_id) {
739 	case ACLK_PERI_PRE:
740 		con = readl(&cru->clksel_con[14]);
741 		div = (con & PERI_ACLK_DIV_MASK) >> PERI_ACLK_DIV_SHIFT;
742 		parent = priv->gpll_hz;
743 		break;
744 	case HCLK_PERI_PRE:
745 		con = readl(&cru->clksel_con[14]);
746 		div = (con & PERI_HCLK_DIV_MASK) >> PERI_HCLK_DIV_SHIFT;
747 		parent = priv->gpll_hz;
748 		break;
749 	default:
750 		return -ENOENT;
751 	}
752 
753 	return DIV_TO_RATE(parent, div);
754 }
755 
756 static ulong px30_peri_set_clk(struct px30_clk_priv *priv, ulong clk_id,
757 			       ulong hz)
758 {
759 	struct px30_cru *cru = priv->cru;
760 	int src_clk_div;
761 
762 	src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
763 	assert(src_clk_div - 1 < 31);
764 
765 	/*
766 	 * select gpll as pd_peri bus clock source and
767 	 * set up dependent divisors for HCLK and ACLK clocks.
768 	 */
769 	switch (clk_id) {
770 	case ACLK_PERI_PRE:
771 		rk_clrsetreg(&cru->clksel_con[14],
772 			     PERI_PLL_SEL_MASK | PERI_ACLK_DIV_MASK,
773 			     PERI_PLL_GPLL << PERI_PLL_SEL_SHIFT |
774 			     (src_clk_div - 1) << PERI_ACLK_DIV_SHIFT);
775 		break;
776 	case HCLK_PERI_PRE:
777 		rk_clrsetreg(&cru->clksel_con[14],
778 			     PERI_PLL_SEL_MASK | PERI_HCLK_DIV_MASK,
779 			     PERI_PLL_GPLL << PERI_PLL_SEL_SHIFT |
780 			     (src_clk_div - 1) << PERI_HCLK_DIV_SHIFT);
781 		break;
782 	default:
783 		printf("do not support this peri freq\n");
784 		return -EINVAL;
785 	}
786 
787 	return px30_peri_get_clk(priv, clk_id);
788 }
789 
790 static int px30_clk_get_gpll_rate(ulong *rate)
791 {
792 	struct udevice *pmucru_dev;
793 	struct px30_pmuclk_priv *priv;
794 	struct px30_pmucru *pmucru;
795 	int ret;
796 
797 	ret = uclass_get_device_by_driver(UCLASS_CLK,
798 					  DM_GET_DRIVER(rockchip_px30_pmucru),
799 					  &pmucru_dev);
800 	if (ret) {
801 		printf("%s: could not find pmucru device\n", __func__);
802 		return ret;
803 	}
804 	priv = dev_get_priv(pmucru_dev);
805 	pmucru = priv->pmucru;
806 	*rate =  rkclk_pll_get_rate(&pmucru->pll, &pmucru->pmu_mode, GPLL);
807 
808 	return 0;
809 }
810 
811 static ulong px30_clk_get_pll_rate(struct px30_clk_priv *priv,
812 				   enum px30_pll_id pll_id)
813 {
814 	struct px30_cru *cru = priv->cru;
815 
816 	return rkclk_pll_get_rate(&cru->pll[pll_id], &cru->mode, pll_id);
817 }
818 
819 static ulong px30_armclk_set_clk(struct px30_clk_priv *priv, ulong hz)
820 {
821 	struct px30_cru *cru = priv->cru;
822 	const struct cpu_rate_table *rate;
823 	ulong old_rate;
824 
825 	rate = get_cpu_settings(hz);
826 	if (!rate) {
827 		printf("%s unsupport rate\n", __func__);
828 		return -EINVAL;
829 	}
830 
831 	/*
832 	 * select apll as cpu/core clock pll source and
833 	 * set up dependent divisors for PERI and ACLK clocks.
834 	 * core hz : apll = 1:1
835 	 */
836 	old_rate = px30_clk_get_pll_rate(priv, APLL);
837 	if (old_rate > hz) {
838 		if (rkclk_set_pll(&cru->pll[APLL], &cru->mode, APLL, hz))
839 			return -EINVAL;
840 		rk_clrsetreg(&cru->clksel_con[0],
841 			     CORE_CLK_PLL_SEL_MASK | CORE_DIV_CON_MASK |
842 			     CORE_ACLK_DIV_MASK | CORE_DBG_DIV_MASK,
843 			     rate->aclk_div << CORE_ACLK_DIV_SHIFT |
844 			     rate->pclk_div << CORE_DBG_DIV_SHIFT |
845 			     CORE_CLK_PLL_SEL_APLL << CORE_CLK_PLL_SEL_SHIFT |
846 			     0 << CORE_DIV_CON_SHIFT);
847 	} else if (old_rate < hz) {
848 		rk_clrsetreg(&cru->clksel_con[0],
849 			     CORE_CLK_PLL_SEL_MASK | CORE_DIV_CON_MASK |
850 			     CORE_ACLK_DIV_MASK | CORE_DBG_DIV_MASK,
851 			     rate->aclk_div << CORE_ACLK_DIV_SHIFT |
852 			     rate->pclk_div << CORE_DBG_DIV_SHIFT |
853 			     CORE_CLK_PLL_SEL_APLL << CORE_CLK_PLL_SEL_SHIFT |
854 			     0 << CORE_DIV_CON_SHIFT);
855 		if (rkclk_set_pll(&cru->pll[APLL], &cru->mode, APLL, hz))
856 			return -EINVAL;
857 	}
858 
859 	return px30_clk_get_pll_rate(priv, APLL);
860 }
861 
862 static ulong px30_clk_get_rate(struct clk *clk)
863 {
864 	struct px30_clk_priv *priv = dev_get_priv(clk->dev);
865 	ulong rate = 0;
866 	int ret;
867 
868 	if (!priv->gpll_hz) {
869 		ret = px30_clk_get_gpll_rate(&priv->gpll_hz);
870 		if (ret) {
871 			printf("%s failed to get gpll rate\n", __func__);
872 			return ret;
873 		}
874 		debug("%s gpll=%lu\n", __func__, priv->gpll_hz);
875 	}
876 
877 	debug("%s %ld\n", __func__, clk->id);
878 	switch (clk->id) {
879 	case PLL_APLL:
880 		rate = px30_clk_get_pll_rate(priv, APLL);
881 		break;
882 	case PLL_DPLL:
883 		rate = px30_clk_get_pll_rate(priv, DPLL);
884 		break;
885 	case PLL_CPLL:
886 		rate = px30_clk_get_pll_rate(priv, CPLL);
887 		break;
888 	case PLL_NPLL:
889 		rate = px30_clk_get_pll_rate(priv, NPLL);
890 		break;
891 	case ARMCLK:
892 		rate = px30_clk_get_pll_rate(priv, APLL);
893 		break;
894 	case HCLK_SDMMC:
895 	case HCLK_EMMC:
896 	case SCLK_SDMMC:
897 	case SCLK_EMMC:
898 	case SCLK_EMMC_SAMPLE:
899 		rate = px30_mmc_get_clk(priv, clk->id);
900 		break;
901 	case SCLK_I2C0:
902 	case SCLK_I2C1:
903 	case SCLK_I2C2:
904 	case SCLK_I2C3:
905 		rate = px30_i2c_get_clk(priv, clk->id);
906 		break;
907 	case SCLK_PWM0:
908 	case SCLK_PWM1:
909 		rate = px30_pwm_get_clk(priv, clk->id);
910 		break;
911 	case SCLK_SARADC:
912 		rate = px30_saradc_get_clk(priv);
913 		break;
914 	case SCLK_SPI0:
915 	case SCLK_SPI1:
916 		rate = px30_spi_get_clk(priv, clk->id);
917 		break;
918 	case ACLK_VOPB:
919 	case DCLK_VOPB:
920 		rate = px30_vop_get_clk(priv, clk->id);
921 		break;
922 	case ACLK_BUS_PRE:
923 	case HCLK_BUS_PRE:
924 	case PCLK_BUS_PRE:
925 		rate = px30_bus_get_clk(priv, clk->id);
926 		break;
927 	case ACLK_PERI_PRE:
928 	case HCLK_PERI_PRE:
929 		rate = px30_peri_get_clk(priv, clk->id);
930 		break;
931 	default:
932 		return -ENOENT;
933 	}
934 
935 	return rate;
936 }
937 
938 static ulong px30_clk_set_rate(struct clk *clk, ulong rate)
939 {
940 	struct px30_clk_priv *priv = dev_get_priv(clk->dev);
941 	ulong ret = 0;
942 
943 	if (!priv->gpll_hz) {
944 		ret = px30_clk_get_gpll_rate(&priv->gpll_hz);
945 		if (ret) {
946 			printf("%s failed to get gpll rate\n", __func__);
947 			return ret;
948 		}
949 		debug("%s gpll=%lu\n", __func__, priv->gpll_hz);
950 	}
951 
952 	debug("%s %ld %ld\n", __func__, clk->id, rate);
953 	switch (clk->id) {
954 	case ARMCLK:
955 		if (priv->armclk_hz)
956 			px30_armclk_set_clk(priv, rate);
957 		priv->armclk_hz = rate;
958 		break;
959 	case HCLK_SDMMC:
960 	case HCLK_EMMC:
961 	case SCLK_SDMMC:
962 	case SCLK_EMMC:
963 		ret = px30_mmc_set_clk(priv, clk->id, rate);
964 		break;
965 	case SCLK_I2C0:
966 	case SCLK_I2C1:
967 	case SCLK_I2C2:
968 	case SCLK_I2C3:
969 		ret = px30_i2c_set_clk(priv, clk->id, rate);
970 		break;
971 	case SCLK_PWM0:
972 	case SCLK_PWM1:
973 		ret = px30_pwm_set_clk(priv, clk->id, rate);
974 		break;
975 	case SCLK_SARADC:
976 		ret = px30_saradc_set_clk(priv, rate);
977 		break;
978 	case SCLK_SPI0:
979 	case SCLK_SPI1:
980 		ret = px30_spi_set_clk(priv, clk->id, rate);
981 		break;
982 	case ACLK_VOPB:
983 	case DCLK_VOPB:
984 		ret = px30_vop_set_clk(priv, clk->id, rate);
985 		break;
986 	case ACLK_BUS_PRE:
987 	case HCLK_BUS_PRE:
988 	case PCLK_BUS_PRE:
989 		ret = px30_bus_set_clk(priv, clk->id, rate);
990 		break;
991 	case ACLK_PERI_PRE:
992 	case HCLK_PERI_PRE:
993 		ret = px30_peri_set_clk(priv, clk->id, rate);
994 		break;
995 	default:
996 		return -ENOENT;
997 	}
998 
999 	return ret;
1000 }
1001 
1002 #define ROCKCHIP_MMC_DELAY_SEL		BIT(10)
1003 #define ROCKCHIP_MMC_DEGREE_MASK	0x3
1004 #define ROCKCHIP_MMC_DELAYNUM_OFFSET	2
1005 #define ROCKCHIP_MMC_DELAYNUM_MASK	(0xff << ROCKCHIP_MMC_DELAYNUM_OFFSET)
1006 
1007 #define PSECS_PER_SEC 1000000000000LL
1008 /*
1009  * Each fine delay is between 44ps-77ps. Assume each fine delay is 60ps to
1010  * simplify calculations. So 45degs could be anywhere between 33deg and 57.8deg.
1011  */
1012 #define ROCKCHIP_MMC_DELAY_ELEMENT_PSEC 60
1013 
1014 int rockchip_mmc_get_phase(struct clk *clk)
1015 {
1016 	struct px30_clk_priv *priv = dev_get_priv(clk->dev);
1017 	struct px30_cru *cru = priv->cru;
1018 	u32 raw_value, delay_num;
1019 	u16 degrees = 0;
1020 	ulong rate;
1021 
1022 	rate = px30_clk_get_rate(clk);
1023 
1024 	if (rate < 0)
1025 		return rate;
1026 
1027 	if (clk->id == SCLK_EMMC_SAMPLE)
1028 		raw_value = readl(&cru->emmc_con[1]);
1029 	else
1030 		raw_value = readl(&cru->sdmmc_con[1]);
1031 
1032 	raw_value >>= 1;
1033 	degrees = (raw_value & ROCKCHIP_MMC_DEGREE_MASK) * 90;
1034 
1035 	if (raw_value & ROCKCHIP_MMC_DELAY_SEL) {
1036 		/* degrees/delaynum * 10000 */
1037 		unsigned long factor = (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10) *
1038 					36 * (rate / 1000000);
1039 
1040 		delay_num = (raw_value & ROCKCHIP_MMC_DELAYNUM_MASK);
1041 		delay_num >>= ROCKCHIP_MMC_DELAYNUM_OFFSET;
1042 		degrees += DIV_ROUND_CLOSEST(delay_num * factor, 10000);
1043 	}
1044 
1045 	return degrees % 360;
1046 }
1047 
1048 int rockchip_mmc_set_phase(struct clk *clk, u32 degrees)
1049 {
1050 	struct px30_clk_priv *priv = dev_get_priv(clk->dev);
1051 	struct px30_cru *cru = priv->cru;
1052 	u8 nineties, remainder, delay_num;
1053 	u32 raw_value, delay;
1054 	ulong rate;
1055 
1056 	rate = px30_clk_get_rate(clk);
1057 
1058 	if (rate < 0)
1059 		return rate;
1060 
1061 	nineties = degrees / 90;
1062 	remainder = (degrees % 90);
1063 
1064 	/*
1065 	 * Convert to delay; do a little extra work to make sure we
1066 	 * don't overflow 32-bit / 64-bit numbers.
1067 	 */
1068 	delay = 10000000; /* PSECS_PER_SEC / 10000 / 10 */
1069 	delay *= remainder;
1070 	delay = DIV_ROUND_CLOSEST(delay, (rate / 1000) * 36 *
1071 				(ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10));
1072 
1073 	delay_num = (u8)min_t(u32, delay, 255);
1074 
1075 	raw_value = delay_num ? ROCKCHIP_MMC_DELAY_SEL : 0;
1076 	raw_value |= delay_num << ROCKCHIP_MMC_DELAYNUM_OFFSET;
1077 	raw_value |= nineties;
1078 
1079 	raw_value <<= 1;
1080 	if (clk->id == SCLK_EMMC_SAMPLE)
1081 		writel(raw_value | 0xffff0000, &cru->emmc_con[1]);
1082 	else
1083 		writel(raw_value | 0xffff0000, &cru->sdmmc_con[1]);
1084 
1085 	debug("mmc set_phase(%d) delay_nums=%u reg=%#x actual_degrees=%d\n",
1086 	      degrees, delay_num, raw_value, rockchip_mmc_get_phase(clk));
1087 
1088 	return 0;
1089 }
1090 
1091 static int px30_clk_get_phase(struct clk *clk)
1092 {
1093 	int ret;
1094 	debug("%s %ld\n", __func__, clk->id);
1095 	switch (clk->id) {
1096 	case SCLK_EMMC_SAMPLE:
1097 	case SCLK_SDMMC_SAMPLE:
1098 		ret = rockchip_mmc_get_phase(clk);
1099 		break;
1100 	default:
1101 		return -ENOENT;
1102 	}
1103 
1104 	return ret;
1105 }
1106 
1107 static int px30_clk_set_phase(struct clk *clk, int degrees)
1108 {
1109 	int ret;
1110 
1111 	debug("%s %ld\n", __func__, clk->id);
1112 	switch (clk->id) {
1113 	case SCLK_EMMC_SAMPLE:
1114 	case SCLK_SDMMC_SAMPLE:
1115 		ret = rockchip_mmc_set_phase(clk, degrees);
1116 		break;
1117 	default:
1118 		return -ENOENT;
1119 	}
1120 
1121 	return ret;
1122 }
1123 
1124 static struct clk_ops px30_clk_ops = {
1125 	.get_rate = px30_clk_get_rate,
1126 	.set_rate = px30_clk_set_rate,
1127 	.get_phase	= px30_clk_get_phase,
1128 	.set_phase	= px30_clk_set_phase,
1129 };
1130 
1131 static int px30_clk_probe(struct udevice *dev)
1132 {
1133 	struct px30_clk_priv *priv = dev_get_priv(dev);
1134 
1135 	if (px30_clk_get_pll_rate(priv, APLL) == APLL_HZ)
1136 		return 0;
1137 
1138 	if (px30_armclk_set_clk(priv, APLL_HZ))
1139 		return -EINVAL;
1140 
1141 	return 0;
1142 }
1143 
1144 static int px30_clk_ofdata_to_platdata(struct udevice *dev)
1145 {
1146 	struct px30_clk_priv *priv = dev_get_priv(dev);
1147 
1148 	priv->cru = dev_read_addr_ptr(dev);
1149 
1150 	return 0;
1151 }
1152 
1153 static int px30_clk_bind(struct udevice *dev)
1154 {
1155 	int ret;
1156 	struct udevice *sys_child, *sf_child;
1157 	struct sysreset_reg *priv;
1158 	struct softreset_reg *sf_priv;
1159 
1160 	/* The reset driver does not have a device node, so bind it here */
1161 	ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset",
1162 				 &sys_child);
1163 	if (ret) {
1164 		debug("Warning: No sysreset driver: ret=%d\n", ret);
1165 	} else {
1166 		priv = malloc(sizeof(struct sysreset_reg));
1167 		priv->glb_srst_fst_value = offsetof(struct px30_cru,
1168 						    glb_srst_fst);
1169 		priv->glb_srst_snd_value = offsetof(struct px30_cru,
1170 						    glb_srst_snd);
1171 		sys_child->priv = priv;
1172 	}
1173 
1174 	ret = device_bind_driver_to_node(dev, "rockchip_reset", "reset",
1175 					 dev_ofnode(dev), &sf_child);
1176 	if (ret) {
1177 		debug("Warning: No rockchip reset driver: ret=%d\n", ret);
1178 	} else {
1179 		sf_priv = malloc(sizeof(struct softreset_reg));
1180 		sf_priv->sf_reset_offset = offsetof(struct px30_cru,
1181 						    softrst_con[0]);
1182 		sf_priv->sf_reset_num = 12;
1183 		sf_child->priv = sf_priv;
1184 	}
1185 
1186 	return 0;
1187 }
1188 
1189 static const struct udevice_id px30_clk_ids[] = {
1190 	{ .compatible = "rockchip,px30-cru" },
1191 	{ }
1192 };
1193 
1194 U_BOOT_DRIVER(rockchip_px30_cru) = {
1195 	.name		= "rockchip_px30_cru",
1196 	.id		= UCLASS_CLK,
1197 	.of_match	= px30_clk_ids,
1198 	.priv_auto_alloc_size = sizeof(struct px30_clk_priv),
1199 	.ofdata_to_platdata = px30_clk_ofdata_to_platdata,
1200 	.ops		= &px30_clk_ops,
1201 	.bind		= px30_clk_bind,
1202 	.probe		= px30_clk_probe,
1203 };
1204 
1205 static ulong px30_pclk_pmu_get_pmuclk(struct px30_pmuclk_priv *priv)
1206 {
1207 	struct px30_pmucru *pmucru = priv->pmucru;
1208 	u32 div, con;
1209 
1210 	con = readl(&pmucru->pmu_clksel_con[0]);
1211 	div = (con & CLK_PMU_PCLK_DIV_MASK) >> CLK_PMU_PCLK_DIV_SHIFT;
1212 
1213 	return DIV_TO_RATE(priv->gpll_hz, div);
1214 }
1215 
1216 static ulong px30_pclk_pmu_set_pmuclk(struct px30_pmuclk_priv *priv, ulong hz)
1217 {
1218 	struct px30_pmucru *pmucru = priv->pmucru;
1219 	int src_clk_div;
1220 
1221 	src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
1222 	assert(src_clk_div - 1 < 31);
1223 
1224 	rk_clrsetreg(&pmucru->pmu_clksel_con[0],
1225 		     CLK_PMU_PCLK_DIV_MASK,
1226 		     (src_clk_div - 1) << CLK_PMU_PCLK_DIV_SHIFT);
1227 
1228 	return px30_pclk_pmu_get_pmuclk(priv);
1229 }
1230 
1231 static ulong px30_gpll_get_pmuclk(struct px30_pmuclk_priv *priv)
1232 {
1233 	struct px30_pmucru *pmucru = priv->pmucru;
1234 
1235 	return rkclk_pll_get_rate(&pmucru->pll, &pmucru->pmu_mode, GPLL);
1236 }
1237 
1238 static ulong px30_gpll_set_pmuclk(struct px30_pmuclk_priv *priv, ulong hz)
1239 {
1240 	struct udevice *cru_dev;
1241 	struct px30_clk_priv *cru_priv;
1242 	struct px30_pmucru *pmucru = priv->pmucru;
1243 	u32 div;
1244 	ulong emmc_rate, sdmmc_rate, nandc_rate;
1245 	int ret;
1246 
1247 	priv->gpll_hz = px30_gpll_get_pmuclk(priv);
1248 
1249 	ret = uclass_get_device_by_name(UCLASS_CLK,
1250 					"clock-controller@ff2b0000",
1251 					 &cru_dev);
1252 	if (ret) {
1253 		printf("%s failed to get cru device\n", __func__);
1254 		return ret;
1255 	}
1256 	cru_priv = dev_get_priv(cru_dev);
1257 	cru_priv->gpll_hz = priv->gpll_hz;
1258 
1259 	div = DIV_ROUND_UP(hz, priv->gpll_hz);
1260 
1261 	/*
1262 	 * avoid bus and peri clock rate too large, reduce rate first.
1263 	 * they will be assigned by clk_set_defaults.
1264 	 */
1265 	px30_bus_set_clk(cru_priv, ACLK_BUS_PRE,
1266 			 px30_bus_get_clk(cru_priv, ACLK_BUS_PRE) / div);
1267 	px30_bus_set_clk(cru_priv, HCLK_BUS_PRE,
1268 			 px30_bus_get_clk(cru_priv, HCLK_BUS_PRE) / div);
1269 	px30_bus_set_clk(cru_priv, PCLK_BUS_PRE,
1270 			 px30_bus_get_clk(cru_priv, PCLK_BUS_PRE) / div);
1271 	px30_peri_set_clk(cru_priv, ACLK_PERI_PRE,
1272 			  px30_bus_get_clk(cru_priv, ACLK_PERI_PRE) / div);
1273 	px30_peri_set_clk(cru_priv, HCLK_PERI_PRE,
1274 			  px30_bus_get_clk(cru_priv, HCLK_PERI_PRE) / div);
1275 	px30_pclk_pmu_set_pmuclk(priv, px30_pclk_pmu_get_pmuclk(priv) / div);
1276 
1277 	/*
1278 	 * save emmc, sdmmc and nandc clock rate,
1279 	 * nandc clock rate should less than or equal to 150Mhz.
1280 	 */
1281 	emmc_rate = px30_mmc_get_clk(cru_priv, SCLK_EMMC);
1282 	sdmmc_rate = px30_mmc_get_clk(cru_priv, SCLK_SDMMC);
1283 	nandc_rate = px30_nandc_get_clk(cru_priv);
1284 	debug("%s emmc=%lu, sdmmc=%lu, nandc=%lu\n", __func__, emmc_rate,
1285 	      sdmmc_rate, nandc_rate);
1286 	/* avoid rate too large, reduce rate first */
1287 	px30_mmc_set_clk(cru_priv, SCLK_EMMC, emmc_rate / div);
1288 	px30_mmc_set_clk(cru_priv, SCLK_SDMMC, sdmmc_rate / div);
1289 	px30_nandc_set_clk(cru_priv, nandc_rate / div);
1290 
1291 	rkclk_set_pll(&pmucru->pll, &pmucru->pmu_mode, GPLL, hz);
1292 	priv->gpll_hz = px30_gpll_get_pmuclk(priv);
1293 	cru_priv->gpll_hz = priv->gpll_hz;
1294 
1295 	/* restore emmc, sdmmc and nandc clock rate */
1296 	px30_mmc_set_clk(cru_priv, SCLK_EMMC, emmc_rate);
1297 	px30_mmc_set_clk(cru_priv, SCLK_SDMMC, sdmmc_rate);
1298 	px30_nandc_set_clk(cru_priv, nandc_rate);
1299 
1300 	return priv->gpll_hz;
1301 }
1302 
1303 static ulong px30_pmuclk_get_rate(struct clk *clk)
1304 {
1305 	struct px30_pmuclk_priv *priv = dev_get_priv(clk->dev);
1306 	ulong rate = 0;
1307 
1308 	debug("%s %ld\n", __func__, clk->id);
1309 	switch (clk->id) {
1310 	case PLL_GPLL:
1311 		rate = px30_gpll_get_pmuclk(priv);
1312 		break;
1313 	case PCLK_PMU_PRE:
1314 		rate = px30_pclk_pmu_get_pmuclk(priv);
1315 		break;
1316 	default:
1317 		return -ENOENT;
1318 	}
1319 
1320 	return rate;
1321 }
1322 
1323 static ulong px30_pmuclk_set_rate(struct clk *clk, ulong rate)
1324 {
1325 	struct px30_pmuclk_priv *priv = dev_get_priv(clk->dev);
1326 	ulong ret = 0;
1327 
1328 	debug("%s %ld %ld\n", __func__, clk->id, rate);
1329 	switch (clk->id) {
1330 	case PLL_GPLL:
1331 		ret = px30_gpll_set_pmuclk(priv, rate);
1332 		break;
1333 	case PCLK_PMU_PRE:
1334 		ret = px30_pclk_pmu_set_pmuclk(priv, rate);
1335 		break;
1336 	default:
1337 		return -ENOENT;
1338 	}
1339 
1340 	return ret;
1341 }
1342 
1343 static struct clk_ops px30_pmuclk_ops = {
1344 	.get_rate = px30_pmuclk_get_rate,
1345 	.set_rate = px30_pmuclk_set_rate,
1346 };
1347 
1348 static int px30_pmuclk_probe(struct udevice *dev)
1349 {
1350 	return 0;
1351 }
1352 
1353 static int px30_pmuclk_ofdata_to_platdata(struct udevice *dev)
1354 {
1355 	struct px30_pmuclk_priv *priv = dev_get_priv(dev);
1356 
1357 	priv->pmucru = dev_read_addr_ptr(dev);
1358 
1359 	return 0;
1360 }
1361 
1362 static const struct udevice_id px30_pmuclk_ids[] = {
1363 	{ .compatible = "rockchip,px30-pmucru" },
1364 	{ }
1365 };
1366 
1367 U_BOOT_DRIVER(rockchip_px30_pmucru) = {
1368 	.name		= "rockchip_px30_pmucru",
1369 	.id		= UCLASS_CLK,
1370 	.of_match	= px30_pmuclk_ids,
1371 	.priv_auto_alloc_size = sizeof(struct px30_pmuclk_priv),
1372 	.ofdata_to_platdata = px30_pmuclk_ofdata_to_platdata,
1373 	.ops		= &px30_pmuclk_ops,
1374 	.probe		= px30_pmuclk_probe,
1375 };
1376 
1377 /**
1378  * soc_clk_dump() - Print clock frequencies
1379  * Returns zero on success
1380  *
1381  * Implementation for the clk dump command.
1382  */
1383 int soc_clk_dump(void)
1384 {
1385 	struct udevice *cru_dev, *pmucru_dev;
1386 	const struct px30_clk_info *clk_dump;
1387 	struct clk clk;
1388 	unsigned long clk_count = ARRAY_SIZE(clks_dump);
1389 	unsigned long rate;
1390 	int i, ret;
1391 
1392 	ret = uclass_get_device_by_driver(UCLASS_CLK,
1393 					  DM_GET_DRIVER(rockchip_px30_cru),
1394 					  &cru_dev);
1395 	if (ret) {
1396 		printf("%s failed to get cru device\n", __func__);
1397 		return ret;
1398 	}
1399 
1400 	ret = uclass_get_device_by_driver(UCLASS_CLK,
1401 					  DM_GET_DRIVER(rockchip_px30_pmucru),
1402 					  &pmucru_dev);
1403 	if (ret) {
1404 		printf("%s failed to get pmucru device\n", __func__);
1405 		return ret;
1406 	}
1407 
1408 	printf("CLK:");
1409 	for (i = 0; i < clk_count; i++) {
1410 		clk_dump = &clks_dump[i];
1411 		if (clk_dump->name) {
1412 			clk.id = clk_dump->id;
1413 			if (clk_dump->is_cru)
1414 				ret = clk_request(cru_dev, &clk);
1415 			else
1416 				ret = clk_request(pmucru_dev, &clk);
1417 			if (ret < 0)
1418 				return ret;
1419 
1420 			rate = clk_get_rate(&clk);
1421 			clk_free(&clk);
1422 			if (i == 0) {
1423 				if (rate < 0)
1424 					printf("%10s%20s\n", clk_dump->name,
1425 					       "unknown");
1426 				else
1427 					printf("%10s%20lu Hz\n", clk_dump->name,
1428 					       rate);
1429 			} else {
1430 				if (rate < 0)
1431 					printf("%14s%20s\n", clk_dump->name,
1432 					       "unknown");
1433 				else
1434 					printf("%14s%20lu Hz\n", clk_dump->name,
1435 					       rate);
1436 			}
1437 		}
1438 	}
1439 
1440 	return 0;
1441 }
1442