xref: /rk3399_rockchip-uboot/drivers/clk/rockchip/clk_rk3308.c (revision 0c8b06ef74f1da4f6d51974c0d3d9d4bf7ed7e2e)
1 /*
2  * (C) Copyright 2017 Rockchip Electronics Co., Ltd
3  *
4  * SPDX-License-Identifier:	GPL-2.0
5  */
6 #include <common.h>
7 #include <bitfield.h>
8 #include <clk-uclass.h>
9 #include <dm.h>
10 #include <div64.h>
11 #include <errno.h>
12 #include <syscon.h>
13 #include <asm/arch/clock.h>
14 #include <asm/arch/cru_rk3308.h>
15 #include <asm/arch/hardware.h>
16 #include <asm/io.h>
17 #include <dm/lists.h>
18 #include <dt-bindings/clock/rk3308-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 RK3308_CLK_DUMP(_id, _name)		\
32 {						\
33 	.id = _id,				\
34 	.name = _name,				\
35 }
36 
37 #define RK3308_CPUCLK_RATE(_rate, _aclk_div, _pclk_div)		\
38 {								\
39 	.rate	= _rate##U,					\
40 	.aclk_div = _aclk_div,					\
41 	.pclk_div = _pclk_div,					\
42 }
43 
44 static struct rockchip_pll_rate_table rk3308_pll_rates[] = {
45 	/* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */
46 	RK3036_PLL_RATE(1300000000, 6, 325, 1, 1, 1, 0),
47 	RK3036_PLL_RATE(1200000000, 1, 50, 1, 1, 1, 0),
48 	RK3036_PLL_RATE(816000000, 1, 68, 2, 1, 1, 0),
49 	RK3036_PLL_RATE(748000000, 2, 187, 3, 1, 1, 0),
50 };
51 
52 static struct rockchip_cpu_rate_table rk3308_cpu_rates[] = {
53 	RK3308_CPUCLK_RATE(1200000000, 1, 5),
54 	RK3308_CPUCLK_RATE(1008000000, 1, 5),
55 	RK3308_CPUCLK_RATE(816000000, 1, 3),
56 	RK3308_CPUCLK_RATE(600000000, 1, 3),
57 	RK3308_CPUCLK_RATE(408000000, 1, 1),
58 };
59 
60 static const struct rk3308_clk_info clks_dump[] = {
61 	RK3308_CLK_DUMP(PLL_APLL, "apll"),
62 	RK3308_CLK_DUMP(PLL_DPLL, "dpll"),
63 	RK3308_CLK_DUMP(PLL_VPLL0, "vpll0"),
64 	RK3308_CLK_DUMP(PLL_VPLL1, "vpll1"),
65 	RK3308_CLK_DUMP(ACLK_BUS, "aclk_bus"),
66 	RK3308_CLK_DUMP(HCLK_BUS, "hclk_bus"),
67 	RK3308_CLK_DUMP(PCLK_BUS, "pclk_bus"),
68 	RK3308_CLK_DUMP(ACLK_PERI, "aclk_peri"),
69 	RK3308_CLK_DUMP(HCLK_PERI, "hclk_peri"),
70 	RK3308_CLK_DUMP(PCLK_PERI, "pclk_peri"),
71 	RK3308_CLK_DUMP(HCLK_AUDIO, "hclk_audio"),
72 	RK3308_CLK_DUMP(PCLK_AUDIO, "pclk_audio"),
73 };
74 
75 static struct rockchip_pll_clock rk3308_pll_clks[] = {
76 	[APLL] = PLL(pll_rk3328, PLL_APLL, RK3308_PLL_CON(0),
77 		     RK3308_MODE_CON, 0, 10, 0, rk3308_pll_rates),
78 	[DPLL] = PLL(pll_rk3328, PLL_DPLL, RK3308_PLL_CON(8),
79 		     RK3308_MODE_CON, 2, 10, 0, NULL),
80 	[VPLL0] = PLL(pll_rk3328, PLL_VPLL0, RK3308_PLL_CON(16),
81 		      RK3308_MODE_CON, 4, 10, 0, NULL),
82 	[VPLL1] = PLL(pll_rk3328, PLL_VPLL1, RK3308_PLL_CON(24),
83 		      RK3308_MODE_CON, 6, 10, 0, NULL),
84 };
85 
86 /*
87  *
88  * rational_best_approximation(31415, 10000,
89  *		(1 << 8) - 1, (1 << 5) - 1, &n, &d);
90  *
91  * you may look at given_numerator as a fixed point number,
92  * with the fractional part size described in given_denominator.
93  *
94  * for theoretical background, see:
95  * http://en.wikipedia.org/wiki/Continued_fraction
96  */
rational_best_approximation(unsigned long given_numerator,unsigned long given_denominator,unsigned long max_numerator,unsigned long max_denominator,unsigned long * best_numerator,unsigned long * best_denominator)97 static void rational_best_approximation(unsigned long given_numerator,
98 					unsigned long given_denominator,
99 					unsigned long max_numerator,
100 					unsigned long max_denominator,
101 					unsigned long *best_numerator,
102 					unsigned long *best_denominator)
103 {
104 	unsigned long n, d, n0, d0, n1, d1;
105 
106 	n = given_numerator;
107 	d = given_denominator;
108 	n0 = 0;
109 	d1 = 0;
110 	n1 = 1;
111 	d0 = 1;
112 	for (;;) {
113 		unsigned long t, a;
114 
115 		if (n1 > max_numerator || d1 > max_denominator) {
116 			n1 = n0;
117 			d1 = d0;
118 			break;
119 		}
120 		if (d == 0)
121 			break;
122 		t = d;
123 		a = n / d;
124 		d = n % d;
125 		n = t;
126 		t = n0 + a * n1;
127 		n0 = n1;
128 		n1 = t;
129 		t = d0 + a * d1;
130 		d0 = d1;
131 		d1 = t;
132 	}
133 	*best_numerator = n1;
134 	*best_denominator = d1;
135 }
136 
rk3308_armclk_set_clk(struct rk3308_clk_priv * priv,ulong hz)137 static ulong rk3308_armclk_set_clk(struct rk3308_clk_priv *priv, ulong hz)
138 {
139 	struct rk3308_cru *cru = priv->cru;
140 	const struct rockchip_cpu_rate_table *rate;
141 	ulong old_rate;
142 
143 	rate = rockchip_get_cpu_settings(rk3308_cpu_rates, hz);
144 	if (!rate) {
145 		printf("%s unsupport rate\n", __func__);
146 		return -EINVAL;
147 	}
148 
149 	/*
150 	 * select apll as cpu/core clock pll source and
151 	 * set up dependent divisors for PERI and ACLK clocks.
152 	 * core hz : apll = 1:1
153 	 */
154 	old_rate = rockchip_pll_get_rate(&rk3308_pll_clks[APLL],
155 					 priv->cru, APLL);
156 	if (old_rate > hz) {
157 		if (rockchip_pll_set_rate(&rk3308_pll_clks[APLL],
158 					  priv->cru, APLL, hz))
159 			return -EINVAL;
160 		rk_clrsetreg(&cru->clksel_con[0],
161 			     CORE_CLK_PLL_SEL_MASK | CORE_DIV_CON_MASK |
162 			     CORE_ACLK_DIV_MASK | CORE_DBG_DIV_MASK,
163 			     rate->aclk_div << CORE_ACLK_DIV_SHIFT |
164 			     rate->pclk_div << CORE_DBG_DIV_SHIFT |
165 			     CORE_CLK_PLL_SEL_APLL << CORE_CLK_PLL_SEL_SHIFT |
166 			     0 << CORE_DIV_CON_SHIFT);
167 	} else if (old_rate < hz) {
168 		rk_clrsetreg(&cru->clksel_con[0],
169 			     CORE_CLK_PLL_SEL_MASK | CORE_DIV_CON_MASK |
170 			     CORE_ACLK_DIV_MASK | CORE_DBG_DIV_MASK,
171 			     rate->aclk_div << CORE_ACLK_DIV_SHIFT |
172 			     rate->pclk_div << CORE_DBG_DIV_SHIFT |
173 			     CORE_CLK_PLL_SEL_APLL << CORE_CLK_PLL_SEL_SHIFT |
174 			     0 << CORE_DIV_CON_SHIFT);
175 		if (rockchip_pll_set_rate(&rk3308_pll_clks[APLL],
176 					  priv->cru, APLL, hz))
177 			return -EINVAL;
178 	}
179 
180 	return rockchip_pll_get_rate(&rk3308_pll_clks[APLL], priv->cru, APLL);
181 }
182 
rk3308_clk_get_pll_rate(struct rk3308_clk_priv * priv)183 static void rk3308_clk_get_pll_rate(struct rk3308_clk_priv *priv)
184 {
185 	if (!priv->dpll_hz)
186 		priv->dpll_hz = rockchip_pll_get_rate(&rk3308_pll_clks[DPLL],
187 						      priv->cru, DPLL);
188 	if (!priv->vpll0_hz)
189 		priv->vpll0_hz = rockchip_pll_get_rate(&rk3308_pll_clks[VPLL0],
190 						       priv->cru, VPLL0);
191 	if (!priv->vpll1_hz)
192 		priv->vpll1_hz = rockchip_pll_get_rate(&rk3308_pll_clks[VPLL1],
193 						       priv->cru, VPLL1);
194 }
195 
rk3308_i2c_get_clk(struct clk * clk)196 static ulong rk3308_i2c_get_clk(struct clk *clk)
197 {
198 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
199 	struct rk3308_cru *cru = priv->cru;
200 	u32 div, con, con_id;
201 
202 	switch (clk->id) {
203 	case SCLK_I2C0:
204 		con_id = 25;
205 		break;
206 	case SCLK_I2C1:
207 		con_id = 26;
208 		break;
209 	case SCLK_I2C2:
210 		con_id = 27;
211 		break;
212 	case SCLK_I2C3:
213 		con_id = 28;
214 		break;
215 	default:
216 		printf("do not support this i2c bus\n");
217 		return -EINVAL;
218 	}
219 
220 	con = readl(&cru->clksel_con[con_id]);
221 	div = con >> CLK_I2C_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK;
222 
223 	return DIV_TO_RATE(priv->dpll_hz, div);
224 }
225 
rk3308_i2c_set_clk(struct clk * clk,uint hz)226 static ulong rk3308_i2c_set_clk(struct clk *clk, uint hz)
227 {
228 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
229 	struct rk3308_cru *cru = priv->cru;
230 	u32 src_clk_div, con_id;
231 
232 	src_clk_div = DIV_ROUND_UP(priv->dpll_hz, hz);
233 	assert(src_clk_div - 1 <= 127);
234 
235 	switch (clk->id) {
236 	case SCLK_I2C0:
237 		con_id = 25;
238 		break;
239 	case SCLK_I2C1:
240 		con_id = 26;
241 		break;
242 	case SCLK_I2C2:
243 		con_id = 27;
244 		break;
245 	case SCLK_I2C3:
246 		con_id = 28;
247 		break;
248 	default:
249 		printf("do not support this i2c bus\n");
250 		return -EINVAL;
251 	}
252 	rk_clrsetreg(&cru->clksel_con[con_id],
253 		     CLK_I2C_PLL_SEL_MASK | CLK_I2C_DIV_CON_MASK,
254 		     CLK_I2C_PLL_SEL_DPLL << CLK_I2C_PLL_SEL_SHIFT |
255 		     (src_clk_div - 1) << CLK_I2C_DIV_CON_SHIFT);
256 
257 	return rk3308_i2c_get_clk(clk);
258 }
259 
rk3308_mac_set_clk(struct clk * clk,uint hz)260 static ulong rk3308_mac_set_clk(struct clk *clk, uint hz)
261 {
262 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
263 	struct rk3308_cru *cru = priv->cru;
264 	u32 con = readl(&cru->clksel_con[43]);
265 	ulong pll_rate;
266 	u8 div;
267 
268 	if ((con >> MAC_PLL_SHIFT) & MAC_SEL_VPLL0)
269 		pll_rate = rockchip_pll_get_rate(&rk3308_pll_clks[VPLL0],
270 						 priv->cru, VPLL0);
271 	else if ((con >> MAC_PLL_SHIFT) & MAC_SEL_VPLL1)
272 		pll_rate = rockchip_pll_get_rate(&rk3308_pll_clks[VPLL1],
273 						 priv->cru, VPLL1);
274 	else
275 		pll_rate = rockchip_pll_get_rate(&rk3308_pll_clks[DPLL],
276 						 priv->cru, DPLL);
277 
278 	/*default set 50MHZ for gmac*/
279 	if (!hz)
280 		hz = 50000000;
281 
282 	div = DIV_ROUND_UP(pll_rate, hz) - 1;
283 	assert(div < 32);
284 	rk_clrsetreg(&cru->clksel_con[43], MAC_DIV_MASK,
285 		     div << MAC_DIV_SHIFT);
286 
287 	return DIV_TO_RATE(pll_rate, div);
288 }
289 
rk3308_mac_set_speed_clk(struct clk * clk,uint hz)290 static int rk3308_mac_set_speed_clk(struct clk *clk, uint hz)
291 {
292 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
293 	struct rk3308_cru *cru = priv->cru;
294 
295 	if (hz != 2500000 && hz != 25000000) {
296 		debug("Unsupported mac speed:%d\n", hz);
297 		return -EINVAL;
298 	}
299 
300 	rk_clrsetreg(&cru->clksel_con[43], MAC_CLK_SPEED_SEL_MASK,
301 		     ((hz == 2500000) ? 0 : 1) << MAC_CLK_SPEED_SEL_SHIFT);
302 
303 	return 0;
304 }
305 
rk3308_mmc_get_clk(struct clk * clk)306 static ulong rk3308_mmc_get_clk(struct clk *clk)
307 {
308 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
309 	struct rk3308_cru *cru = priv->cru;
310 	u32 div, con, con_id;
311 
312 	switch (clk->id) {
313 	case HCLK_SDMMC:
314 	case SCLK_SDMMC:
315 		con_id = 39;
316 		break;
317 	case HCLK_EMMC:
318 	case SCLK_EMMC:
319 	case SCLK_EMMC_SAMPLE:
320 		con_id = 41;
321 		break;
322 	default:
323 		return -EINVAL;
324 	}
325 
326 	con = readl(&cru->clksel_con[con_id]);
327 	div = (con & EMMC_DIV_MASK) >> EMMC_DIV_SHIFT;
328 
329 	if ((con & EMMC_PLL_MASK) >> EMMC_PLL_SHIFT
330 	    == EMMC_SEL_24M)
331 		return DIV_TO_RATE(OSC_HZ, div) / 2;
332 	else
333 		return DIV_TO_RATE(priv->vpll0_hz, div) / 2;
334 }
335 
rk3308_mmc_set_clk(struct clk * clk,ulong set_rate)336 static ulong rk3308_mmc_set_clk(struct clk *clk, ulong set_rate)
337 {
338 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
339 	struct rk3308_cru *cru = priv->cru;
340 	int src_clk_div;
341 	u32 con_id;
342 
343 	debug("%s %ld %ld\n", __func__, clk->id, set_rate);
344 
345 	switch (clk->id) {
346 	case HCLK_SDMMC:
347 	case SCLK_SDMMC:
348 		con_id = 39;
349 		break;
350 	case HCLK_EMMC:
351 	case SCLK_EMMC:
352 		con_id = 41;
353 		break;
354 	default:
355 		return -EINVAL;
356 	}
357 	/* Select clk_sdmmc/emmc source from VPLL0 by default */
358 	/* mmc clock defaulg div 2 internal, need provide double in cru */
359 	src_clk_div = DIV_ROUND_UP(priv->vpll0_hz / 2, set_rate);
360 
361 	if (src_clk_div > 127) {
362 		/* use 24MHz source for 400KHz clock */
363 		src_clk_div = DIV_ROUND_UP(OSC_HZ / 2, set_rate);
364 		rk_clrsetreg(&cru->clksel_con[con_id],
365 			     EMMC_PLL_MASK | EMMC_DIV_MASK | EMMC_CLK_SEL_MASK,
366 			     EMMC_CLK_SEL_EMMC << EMMC_CLK_SEL_SHIFT |
367 			     EMMC_SEL_24M << EMMC_PLL_SHIFT |
368 			     (src_clk_div - 1) << EMMC_DIV_SHIFT);
369 	} else {
370 		rk_clrsetreg(&cru->clksel_con[con_id],
371 			     EMMC_PLL_MASK | EMMC_DIV_MASK | EMMC_CLK_SEL_MASK,
372 			     EMMC_CLK_SEL_EMMC << EMMC_CLK_SEL_SHIFT |
373 			     EMMC_SEL_VPLL0 << EMMC_PLL_SHIFT |
374 			     (src_clk_div - 1) << EMMC_DIV_SHIFT);
375 	}
376 
377 	return rk3308_mmc_get_clk(clk);
378 }
379 
rk3308_saradc_get_clk(struct clk * clk)380 static ulong rk3308_saradc_get_clk(struct clk *clk)
381 {
382 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
383 	struct rk3308_cru *cru = priv->cru;
384 	u32 div, con;
385 
386 	con = readl(&cru->clksel_con[34]);
387 	div = con >> CLK_SARADC_DIV_CON_SHIFT & CLK_SARADC_DIV_CON_MASK;
388 
389 	return DIV_TO_RATE(OSC_HZ, div);
390 }
391 
rk3308_saradc_set_clk(struct clk * clk,uint hz)392 static ulong rk3308_saradc_set_clk(struct clk *clk, uint hz)
393 {
394 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
395 	struct rk3308_cru *cru = priv->cru;
396 	int src_clk_div;
397 
398 	src_clk_div = DIV_ROUND_UP(OSC_HZ, hz);
399 	assert(src_clk_div - 1 <= 2047);
400 
401 	rk_clrsetreg(&cru->clksel_con[34],
402 		     CLK_SARADC_DIV_CON_MASK,
403 		     (src_clk_div - 1) << CLK_SARADC_DIV_CON_SHIFT);
404 
405 	return rk3308_saradc_get_clk(clk);
406 }
407 
rk3308_tsadc_get_clk(struct clk * clk)408 static ulong rk3308_tsadc_get_clk(struct clk *clk)
409 {
410 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
411 	struct rk3308_cru *cru = priv->cru;
412 	u32 div, con;
413 
414 	con = readl(&cru->clksel_con[33]);
415 	div = con >> CLK_SARADC_DIV_CON_SHIFT & CLK_SARADC_DIV_CON_MASK;
416 
417 	return DIV_TO_RATE(OSC_HZ, div);
418 }
419 
rk3308_tsadc_set_clk(struct clk * clk,uint hz)420 static ulong rk3308_tsadc_set_clk(struct clk *clk, uint hz)
421 {
422 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
423 	struct rk3308_cru *cru = priv->cru;
424 	int src_clk_div;
425 
426 	src_clk_div = DIV_ROUND_UP(OSC_HZ, hz);
427 	assert(src_clk_div - 1 <= 2047);
428 
429 	rk_clrsetreg(&cru->clksel_con[33],
430 		     CLK_SARADC_DIV_CON_MASK,
431 		     (src_clk_div - 1) << CLK_SARADC_DIV_CON_SHIFT);
432 
433 	return rk3308_tsadc_get_clk(clk);
434 }
435 
rk3308_spi_get_clk(struct clk * clk)436 static ulong rk3308_spi_get_clk(struct clk *clk)
437 {
438 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
439 	struct rk3308_cru *cru = priv->cru;
440 	u32 div, con, con_id;
441 
442 	switch (clk->id) {
443 	case SCLK_SPI0:
444 		con_id = 30;
445 		break;
446 	case SCLK_SPI1:
447 		con_id = 31;
448 		break;
449 	case SCLK_SPI2:
450 		con_id = 32;
451 		break;
452 	default:
453 		printf("do not support this spi bus\n");
454 		return -EINVAL;
455 	}
456 
457 	con = readl(&cru->clksel_con[con_id]);
458 	div = con >> CLK_SPI_DIV_CON_SHIFT & CLK_SPI_DIV_CON_MASK;
459 
460 	return DIV_TO_RATE(priv->dpll_hz, div);
461 }
462 
rk3308_spi_set_clk(struct clk * clk,uint hz)463 static ulong rk3308_spi_set_clk(struct clk *clk, uint hz)
464 {
465 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
466 	struct rk3308_cru *cru = priv->cru;
467 	u32 src_clk_div, con_id;
468 
469 	src_clk_div = DIV_ROUND_UP(priv->dpll_hz, hz);
470 	assert(src_clk_div - 1 <= 127);
471 
472 	switch (clk->id) {
473 	case SCLK_SPI0:
474 		con_id = 30;
475 		break;
476 	case SCLK_SPI1:
477 		con_id = 31;
478 		break;
479 	case SCLK_SPI2:
480 		con_id = 32;
481 		break;
482 	default:
483 		printf("do not support this spi bus\n");
484 		return -EINVAL;
485 	}
486 
487 	rk_clrsetreg(&cru->clksel_con[con_id],
488 		     CLK_SPI_PLL_SEL_MASK | CLK_SPI_DIV_CON_MASK,
489 		     CLK_SPI_PLL_SEL_DPLL << CLK_SPI_PLL_SEL_SHIFT |
490 		     (src_clk_div - 1) << CLK_SPI_DIV_CON_SHIFT);
491 
492 	return rk3308_spi_get_clk(clk);
493 }
494 
rk3308_pwm_get_clk(struct clk * clk)495 static ulong rk3308_pwm_get_clk(struct clk *clk)
496 {
497 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
498 	struct rk3308_cru *cru = priv->cru;
499 	u32 div, con;
500 
501 	con = readl(&cru->clksel_con[29]);
502 	div = con >> CLK_PWM_DIV_CON_SHIFT & CLK_PWM_DIV_CON_MASK;
503 
504 	return DIV_TO_RATE(priv->dpll_hz, div);
505 }
506 
rk3308_pwm_set_clk(struct clk * clk,uint hz)507 static ulong rk3308_pwm_set_clk(struct clk *clk, uint hz)
508 {
509 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
510 	struct rk3308_cru *cru = priv->cru;
511 	int src_clk_div;
512 
513 	src_clk_div = DIV_ROUND_UP(priv->dpll_hz, hz);
514 	assert(src_clk_div - 1 <= 127);
515 
516 	rk_clrsetreg(&cru->clksel_con[29],
517 		     CLK_PWM_PLL_SEL_MASK | CLK_PWM_DIV_CON_MASK,
518 		     CLK_PWM_PLL_SEL_DPLL << CLK_PWM_PLL_SEL_SHIFT |
519 		     (src_clk_div - 1) << CLK_PWM_DIV_CON_SHIFT);
520 
521 	return rk3308_pwm_get_clk(clk);
522 }
523 
rk3308_vop_get_clk(struct clk * clk)524 static ulong rk3308_vop_get_clk(struct clk *clk)
525 {
526 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
527 	struct rk3308_cru *cru = priv->cru;
528 	u32 div, pll_sel, vol_sel, con, parent;
529 
530 	con = readl(&cru->clksel_con[8]);
531 	vol_sel = (con & DCLK_VOP_SEL_MASK) >> DCLK_VOP_SEL_SHIFT;
532 	pll_sel = (con & DCLK_VOP_PLL_SEL_MASK) >> DCLK_VOP_PLL_SEL_SHIFT;
533 	div = con & DCLK_VOP_DIV_MASK;
534 
535 	if (vol_sel == DCLK_VOP_SEL_24M) {
536 		parent = OSC_HZ;
537 	} else if (vol_sel == DCLK_VOP_SEL_DIVOUT) {
538 		switch (pll_sel) {
539 		case DCLK_VOP_PLL_SEL_DPLL:
540 			parent = priv->dpll_hz;
541 			break;
542 		case DCLK_VOP_PLL_SEL_VPLL0:
543 			parent = priv->vpll0_hz;
544 			break;
545 		case DCLK_VOP_PLL_SEL_VPLL1:
546 			parent = priv->vpll0_hz;
547 			break;
548 		default:
549 			printf("do not support this vop pll sel\n");
550 			return -EINVAL;
551 		}
552 	} else {
553 		printf("do not support this vop sel\n");
554 		return -EINVAL;
555 	}
556 
557 	return DIV_TO_RATE(parent, div);
558 }
559 
rk3308_vop_set_clk(struct clk * clk,ulong hz)560 static ulong rk3308_vop_set_clk(struct clk *clk, ulong hz)
561 {
562 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
563 	struct rk3308_cru *cru = priv->cru;
564 	ulong pll_rate, now, best_rate = 0;
565 	u32 i, div, best_div = 0, best_sel = 0;
566 
567 	for (i = 0; i <= DCLK_VOP_PLL_SEL_VPLL1; i++) {
568 		switch (i) {
569 		case DCLK_VOP_PLL_SEL_DPLL:
570 			pll_rate = priv->dpll_hz;
571 			break;
572 		case DCLK_VOP_PLL_SEL_VPLL0:
573 			pll_rate = priv->vpll0_hz;
574 			break;
575 		case DCLK_VOP_PLL_SEL_VPLL1:
576 			pll_rate = priv->vpll1_hz;
577 			break;
578 		default:
579 			printf("do not support this vop pll sel\n");
580 			return -EINVAL;
581 		}
582 
583 		div = DIV_ROUND_UP(pll_rate, hz);
584 		if (div > 255)
585 			continue;
586 		now = pll_rate / div;
587 		if (abs(hz - now) < abs(hz - best_rate)) {
588 			best_rate = now;
589 			best_div = div;
590 			best_sel = i;
591 		}
592 		debug("pll_rate=%lu, best_rate=%lu, best_div=%u, best_sel=%u\n",
593 		      pll_rate, best_rate, best_div, best_sel);
594 	}
595 
596 	if (best_rate != hz && hz == OSC_HZ) {
597 		rk_clrsetreg(&cru->clksel_con[8],
598 			     DCLK_VOP_SEL_MASK,
599 			     DCLK_VOP_SEL_24M << DCLK_VOP_SEL_SHIFT);
600 	} else if (best_rate) {
601 		rk_clrsetreg(&cru->clksel_con[8],
602 			     DCLK_VOP_SEL_MASK | DCLK_VOP_PLL_SEL_MASK |
603 			     DCLK_VOP_DIV_MASK,
604 			     DCLK_VOP_SEL_DIVOUT << DCLK_VOP_SEL_SHIFT |
605 			     best_sel << DCLK_VOP_PLL_SEL_SHIFT |
606 			     (best_div - 1) << DCLK_VOP_DIV_SHIFT);
607 	} else {
608 		printf("do not support this vop freq\n");
609 		return -EINVAL;
610 	}
611 
612 	return rk3308_vop_get_clk(clk);
613 }
614 
rk3308_bus_get_clk(struct rk3308_clk_priv * priv,ulong clk_id)615 static ulong rk3308_bus_get_clk(struct rk3308_clk_priv *priv, ulong clk_id)
616 {
617 	struct rk3308_cru *cru = priv->cru;
618 	u32 div, con, parent = priv->dpll_hz;
619 
620 	switch (clk_id) {
621 	case ACLK_BUS:
622 		con = readl(&cru->clksel_con[5]);
623 		div = (con & BUS_ACLK_DIV_MASK) >> BUS_ACLK_DIV_SHIFT;
624 		break;
625 	case HCLK_BUS:
626 		con = readl(&cru->clksel_con[6]);
627 		div = (con & BUS_HCLK_DIV_MASK) >> BUS_HCLK_DIV_SHIFT;
628 		break;
629 	case PCLK_BUS:
630 	case PCLK_WDT:
631 		con = readl(&cru->clksel_con[6]);
632 		div = (con & BUS_PCLK_DIV_MASK) >> BUS_PCLK_DIV_SHIFT;
633 		break;
634 	default:
635 		return -ENOENT;
636 	}
637 
638 	return DIV_TO_RATE(parent, div);
639 }
640 
rk3308_bus_set_clk(struct rk3308_clk_priv * priv,ulong clk_id,ulong hz)641 static ulong rk3308_bus_set_clk(struct rk3308_clk_priv *priv, ulong clk_id,
642 				ulong hz)
643 {
644 	struct rk3308_cru *cru = priv->cru;
645 	int src_clk_div;
646 
647 	src_clk_div = DIV_ROUND_UP(priv->dpll_hz, hz);
648 	assert(src_clk_div - 1 <= 31);
649 
650 	/*
651 	 * select dpll as pd_bus bus clock source and
652 	 * set up dependent divisors for PCLK/HCLK and ACLK clocks.
653 	 */
654 	switch (clk_id) {
655 	case ACLK_BUS:
656 		rk_clrsetreg(&cru->clksel_con[5],
657 			     BUS_PLL_SEL_MASK | BUS_ACLK_DIV_MASK,
658 			     BUS_PLL_SEL_DPLL << BUS_PLL_SEL_SHIFT |
659 			     (src_clk_div - 1) << BUS_ACLK_DIV_SHIFT);
660 		break;
661 	case HCLK_BUS:
662 		rk_clrsetreg(&cru->clksel_con[6],
663 			     BUS_HCLK_DIV_MASK,
664 			     (src_clk_div - 1) << BUS_HCLK_DIV_SHIFT);
665 		break;
666 	case PCLK_BUS:
667 		rk_clrsetreg(&cru->clksel_con[6],
668 			     BUS_PCLK_DIV_MASK,
669 			     (src_clk_div - 1) << BUS_PCLK_DIV_SHIFT);
670 		break;
671 	default:
672 		printf("do not support this bus freq\n");
673 		return -EINVAL;
674 	}
675 
676 	return rk3308_bus_get_clk(priv, clk_id);
677 }
678 
rk3308_peri_get_clk(struct rk3308_clk_priv * priv,ulong clk_id)679 static ulong rk3308_peri_get_clk(struct rk3308_clk_priv *priv, ulong clk_id)
680 {
681 	struct rk3308_cru *cru = priv->cru;
682 	u32 div, con, parent = priv->dpll_hz;
683 
684 	switch (clk_id) {
685 	case ACLK_PERI:
686 		con = readl(&cru->clksel_con[36]);
687 		div = (con & PERI_ACLK_DIV_MASK) >> PERI_ACLK_DIV_SHIFT;
688 		break;
689 	case HCLK_PERI:
690 		con = readl(&cru->clksel_con[37]);
691 		div = (con & PERI_HCLK_DIV_MASK) >> PERI_HCLK_DIV_SHIFT;
692 		break;
693 	case PCLK_PERI:
694 		con = readl(&cru->clksel_con[37]);
695 		div = (con & PERI_PCLK_DIV_MASK) >> PERI_PCLK_DIV_SHIFT;
696 		break;
697 	default:
698 		return -ENOENT;
699 	}
700 
701 	return DIV_TO_RATE(parent, div);
702 }
703 
rk3308_peri_set_clk(struct rk3308_clk_priv * priv,ulong clk_id,ulong hz)704 static ulong rk3308_peri_set_clk(struct rk3308_clk_priv *priv, ulong clk_id,
705 				 ulong hz)
706 {
707 	struct rk3308_cru *cru = priv->cru;
708 	int src_clk_div;
709 
710 	src_clk_div = DIV_ROUND_UP(priv->dpll_hz, hz);
711 	assert(src_clk_div - 1 <= 31);
712 
713 	/*
714 	 * select dpll as pd_peri bus clock source and
715 	 * set up dependent divisors for PCLK/HCLK and ACLK clocks.
716 	 */
717 	switch (clk_id) {
718 	case ACLK_PERI:
719 		rk_clrsetreg(&cru->clksel_con[36],
720 			     PERI_PLL_SEL_MASK | PERI_ACLK_DIV_MASK,
721 			     PERI_PLL_DPLL << PERI_PLL_SEL_SHIFT |
722 			     (src_clk_div - 1) << PERI_ACLK_DIV_SHIFT);
723 		break;
724 	case HCLK_PERI:
725 		rk_clrsetreg(&cru->clksel_con[37],
726 			     PERI_HCLK_DIV_MASK,
727 			     (src_clk_div - 1) << PERI_HCLK_DIV_SHIFT);
728 		break;
729 	case PCLK_PERI:
730 		rk_clrsetreg(&cru->clksel_con[37],
731 			     PERI_PCLK_DIV_MASK,
732 			     (src_clk_div - 1) << PERI_PCLK_DIV_SHIFT);
733 		break;
734 	default:
735 		printf("do not support this peri freq\n");
736 		return -EINVAL;
737 	}
738 
739 	return rk3308_peri_get_clk(priv, clk_id);
740 }
741 
rk3308_audio_get_clk(struct rk3308_clk_priv * priv,ulong clk_id)742 static ulong rk3308_audio_get_clk(struct rk3308_clk_priv *priv, ulong clk_id)
743 {
744 	struct rk3308_cru *cru = priv->cru;
745 	u32 div, con, parent = priv->vpll0_hz;
746 
747 	switch (clk_id) {
748 	case HCLK_AUDIO:
749 		con = readl(&cru->clksel_con[45]);
750 		div = (con & AUDIO_HCLK_DIV_MASK) >> AUDIO_HCLK_DIV_SHIFT;
751 		break;
752 	case PCLK_AUDIO:
753 		con = readl(&cru->clksel_con[45]);
754 		div = (con & AUDIO_PCLK_DIV_MASK) >> AUDIO_PCLK_DIV_SHIFT;
755 		break;
756 	default:
757 		return -ENOENT;
758 	}
759 
760 	return DIV_TO_RATE(parent, div);
761 }
762 
rk3308_audio_set_clk(struct rk3308_clk_priv * priv,ulong clk_id,ulong hz)763 static ulong rk3308_audio_set_clk(struct rk3308_clk_priv *priv, ulong clk_id,
764 				  ulong hz)
765 {
766 	struct rk3308_cru *cru = priv->cru;
767 	int src_clk_div;
768 
769 	src_clk_div = DIV_ROUND_UP(priv->vpll0_hz, hz);
770 	assert(src_clk_div - 1 <= 31);
771 
772 	/*
773 	 * select vpll0 as audio bus clock source and
774 	 * set up dependent divisors for HCLK and PCLK clocks.
775 	 */
776 	switch (clk_id) {
777 	case HCLK_AUDIO:
778 		rk_clrsetreg(&cru->clksel_con[45],
779 			     AUDIO_PLL_SEL_MASK | AUDIO_HCLK_DIV_MASK,
780 			     AUDIO_PLL_VPLL0 << AUDIO_PLL_SEL_SHIFT |
781 			     (src_clk_div - 1) << AUDIO_HCLK_DIV_SHIFT);
782 		break;
783 	case PCLK_AUDIO:
784 		rk_clrsetreg(&cru->clksel_con[45],
785 			     AUDIO_PLL_SEL_MASK | AUDIO_PCLK_DIV_MASK,
786 			     AUDIO_PLL_VPLL0 << AUDIO_PLL_SEL_SHIFT |
787 			     (src_clk_div - 1) << AUDIO_PCLK_DIV_SHIFT);
788 		break;
789 	default:
790 		printf("do not support this audio freq\n");
791 		return -EINVAL;
792 	}
793 
794 	return rk3308_peri_get_clk(priv, clk_id);
795 }
796 
rk3308_crypto_get_clk(struct rk3308_clk_priv * priv,ulong clk_id)797 static ulong rk3308_crypto_get_clk(struct rk3308_clk_priv *priv, ulong clk_id)
798 {
799 	struct rk3308_cru *cru = priv->cru;
800 	u32 div, con, parent;
801 
802 	switch (clk_id) {
803 	case SCLK_CRYPTO:
804 		con = readl(&cru->clksel_con[7]);
805 		div = (con & CRYPTO_DIV_MASK) >> CRYPTO_DIV_SHIFT;
806 		parent = priv->vpll0_hz;
807 		break;
808 	case SCLK_CRYPTO_APK:
809 		con = readl(&cru->clksel_con[7]);
810 		div = (con & CRYPTO_APK_DIV_MASK) >> CRYPTO_APK_DIV_SHIFT;
811 		parent = priv->vpll0_hz;
812 		break;
813 	default:
814 		return -ENOENT;
815 	}
816 
817 	return DIV_TO_RATE(parent, div);
818 }
819 
rk3308_crypto_set_clk(struct rk3308_clk_priv * priv,ulong clk_id,ulong hz)820 static ulong rk3308_crypto_set_clk(struct rk3308_clk_priv *priv, ulong clk_id,
821 				   ulong hz)
822 {
823 	struct rk3308_cru *cru = priv->cru;
824 	int src_clk_div;
825 
826 	src_clk_div = DIV_ROUND_UP(priv->vpll0_hz, hz);
827 	assert(src_clk_div - 1 <= 31);
828 
829 	/*
830 	 * select gpll as crypto clock source and
831 	 * set up dependent divisors for crypto clocks.
832 	 */
833 	switch (clk_id) {
834 	case SCLK_CRYPTO:
835 		rk_clrsetreg(&cru->clksel_con[7],
836 			     CRYPTO_PLL_SEL_MASK | CRYPTO_DIV_MASK,
837 			     CRYPTO_PLL_SEL_VPLL0 << CRYPTO_PLL_SEL_SHIFT |
838 			     (src_clk_div - 1) << CRYPTO_DIV_SHIFT);
839 		break;
840 	case SCLK_CRYPTO_APK:
841 		rk_clrsetreg(&cru->clksel_con[7],
842 			     CRYPTO_APK_PLL_SEL_MASK | CRYPTO_APK_DIV_MASK,
843 			     CRYPTO_PLL_SEL_VPLL0 << CRYPTO_APK_SEL_SHIFT |
844 			     (src_clk_div - 1) << CRYPTO_APK_DIV_SHIFT);
845 		break;
846 	default:
847 		printf("do not support this peri freq\n");
848 		return -EINVAL;
849 	}
850 
851 	return rk3308_crypto_get_clk(priv, clk_id);
852 }
853 
rk3308_rtc32k_get_clk(struct rk3308_clk_priv * priv,ulong clk_id)854 static ulong rk3308_rtc32k_get_clk(struct rk3308_clk_priv *priv, ulong clk_id)
855 {
856 	struct rk3308_cru *cru = priv->cru;
857 	unsigned long m, n;
858 	u32 con, fracdiv;
859 
860 	con = readl(&cru->clksel_con[2]);
861 	if ((con & CLK_RTC32K_SEL_MASK) >> CLK_RTC32K_SEL_SHIFT !=
862 	    CLK_RTC32K_FRAC_DIV)
863 		return -EINVAL;
864 
865 	fracdiv = readl(&cru->clksel_con[3]);
866 	m = fracdiv & CLK_RTC32K_FRAC_NUMERATOR_MASK;
867 	m >>= CLK_RTC32K_FRAC_NUMERATOR_SHIFT;
868 	n = fracdiv & CLK_RTC32K_FRAC_DENOMINATOR_MASK;
869 	n >>= CLK_RTC32K_FRAC_DENOMINATOR_SHIFT;
870 
871 	return OSC_HZ * m / n;
872 }
873 
rk3308_rtc32k_set_clk(struct rk3308_clk_priv * priv,ulong clk_id,ulong hz)874 static ulong rk3308_rtc32k_set_clk(struct rk3308_clk_priv *priv, ulong clk_id,
875 				   ulong hz)
876 {
877 	struct rk3308_cru *cru = priv->cru;
878 	unsigned long m, n, val;
879 
880 	rational_best_approximation(hz, OSC_HZ,
881 				    GENMASK(16 - 1, 0),
882 				    GENMASK(16 - 1, 0),
883 				    &m, &n);
884 	val = m << CLK_RTC32K_FRAC_NUMERATOR_SHIFT | n;
885 	writel(val, &cru->clksel_con[3]);
886 	rk_clrsetreg(&cru->clksel_con[2], CLK_RTC32K_SEL_MASK,
887 		     CLK_RTC32K_FRAC_DIV << CLK_RTC32K_SEL_SHIFT);
888 
889 	return rk3308_rtc32k_get_clk(priv, clk_id);
890 }
891 
rk3308_sclk_sfc_get_clk(struct rk3308_clk_priv * priv)892 static ulong rk3308_sclk_sfc_get_clk(struct rk3308_clk_priv *priv)
893 {
894 	struct rk3308_cru *cru = priv->cru;
895 	u32 div, con, sel, parent;
896 
897 	con = readl(&cru->clksel_con[42]);
898 	div = (con & SCLK_SFC_DIV_MASK) >> SCLK_SFC_DIV_SHIFT;
899 	sel = (con & SCLK_SFC_SEL_MASK) >> SCLK_SFC_SEL_SHIFT;
900 
901 	if (sel == SCLK_SFC_SEL_DPLL)
902 		parent = priv->dpll_hz;
903 	else if (sel == SCLK_SFC_SEL_VPLL0)
904 		parent = priv->vpll0_hz;
905 	else if (sel == SCLK_SFC_SEL_VPLL1)
906 		parent = priv->vpll1_hz;
907 	else
908 		return -EINVAL;
909 
910 	return DIV_TO_RATE(parent, div);
911 }
912 
rk3308_sclk_sfc_set_clk(struct rk3308_clk_priv * priv,uint hz)913 static ulong rk3308_sclk_sfc_set_clk(struct rk3308_clk_priv *priv, uint hz)
914 {
915 	struct rk3308_cru *cru = priv->cru;
916 	int src_clk_div;
917 
918 	src_clk_div = DIV_ROUND_UP(priv->vpll0_hz, hz);
919 	assert(src_clk_div - 1 <= 127);
920 
921 	rk_clrsetreg(&cru->clksel_con[42],
922 		     SCLK_SFC_SEL_MASK | SCLK_SFC_DIV_MASK,
923 		     SCLK_SFC_SEL_VPLL0 << SCLK_SFC_SEL_SHIFT |
924 		     (src_clk_div - 1) << SCLK_SFC_DIV_SHIFT);
925 
926 	return rk3308_sclk_sfc_get_clk(priv);
927 }
928 
rk3308_clk_get_rate(struct clk * clk)929 static ulong rk3308_clk_get_rate(struct clk *clk)
930 {
931 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
932 	ulong rate = 0;
933 
934 	debug("%s id:%ld\n", __func__, clk->id);
935 
936 	switch (clk->id) {
937 	case PLL_APLL:
938 	case ARMCLK:
939 		rate = rockchip_pll_get_rate(&rk3308_pll_clks[APLL],
940 					     priv->cru, APLL);
941 		break;
942 	case PLL_DPLL:
943 		rate = rockchip_pll_get_rate(&rk3308_pll_clks[DPLL],
944 					     priv->cru, DPLL);
945 		break;
946 	case PLL_VPLL0:
947 		rate = rockchip_pll_get_rate(&rk3308_pll_clks[VPLL0],
948 					     priv->cru, VPLL0);
949 		break;
950 	case PLL_VPLL1:
951 		rate = rockchip_pll_get_rate(&rk3308_pll_clks[VPLL1],
952 					     priv->cru, VPLL1);
953 		break;
954 	case HCLK_SDMMC:
955 	case HCLK_EMMC:
956 	case SCLK_SDMMC:
957 	case SCLK_EMMC:
958 	case SCLK_EMMC_SAMPLE:
959 		rate = rk3308_mmc_get_clk(clk);
960 		break;
961 	case SCLK_I2C0:
962 	case SCLK_I2C1:
963 	case SCLK_I2C2:
964 	case SCLK_I2C3:
965 		rate = rk3308_i2c_get_clk(clk);
966 		break;
967 	case SCLK_SARADC:
968 		rate = rk3308_saradc_get_clk(clk);
969 		break;
970 	case SCLK_TSADC:
971 		rate = rk3308_tsadc_get_clk(clk);
972 		break;
973 	case SCLK_SPI0:
974 	case SCLK_SPI1:
975 		rate = rk3308_spi_get_clk(clk);
976 		break;
977 	case SCLK_PWM0:
978 	case SCLK_PWM1:
979 	case SCLK_PWM2:
980 		rate = rk3308_pwm_get_clk(clk);
981 		break;
982 	case DCLK_VOP:
983 		rate = rk3308_vop_get_clk(clk);
984 		break;
985 	case ACLK_BUS:
986 	case HCLK_BUS:
987 	case PCLK_BUS:
988 	case PCLK_WDT:
989 		rate = rk3308_bus_get_clk(priv, clk->id);
990 		break;
991 	case ACLK_PERI:
992 	case HCLK_PERI:
993 	case PCLK_PERI:
994 		rate = rk3308_peri_get_clk(priv, clk->id);
995 		break;
996 	case HCLK_AUDIO:
997 	case PCLK_AUDIO:
998 		rate = rk3308_audio_get_clk(priv, clk->id);
999 		break;
1000 	case SCLK_CRYPTO:
1001 	case SCLK_CRYPTO_APK:
1002 		rate = rk3308_crypto_get_clk(priv, clk->id);
1003 		break;
1004 	case SCLK_RTC32K:
1005 		rate = rk3308_rtc32k_get_clk(priv, clk->id);
1006 		break;
1007 	case SCLK_SFC:
1008 		rate = rk3308_sclk_sfc_get_clk(priv);
1009 		break;
1010 	default:
1011 		return -ENOENT;
1012 	}
1013 
1014 	return rate;
1015 }
1016 
rk3308_clk_set_rate(struct clk * clk,ulong rate)1017 static ulong rk3308_clk_set_rate(struct clk *clk, ulong rate)
1018 {
1019 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
1020 	ulong ret = 0;
1021 
1022 	debug("%s %ld %ld\n", __func__, clk->id, rate);
1023 
1024 	switch (clk->id) {
1025 	case PLL_DPLL:
1026 		ret = rockchip_pll_set_rate(&rk3308_pll_clks[DPLL], priv->cru,
1027 					    DPLL, rate);
1028 		priv->dpll_hz = rockchip_pll_get_rate(&rk3308_pll_clks[DPLL],
1029 						      priv->cru, DPLL);
1030 		break;
1031 	case ARMCLK:
1032 		/*
1033 		 * Why add `rate < rockchip_pll_get_rate(&rk3308_pll_clks[APLL],
1034 		 *					 priv->cru, APLL)` ?
1035 		 *
1036 		 * rockchip_wtemp_dvfs.c may decrease the arm freq, don't
1037 		 * limit this decrease operation here.
1038 		 */
1039 		if (priv->armclk_hz ||
1040 			(rate < rockchip_pll_get_rate(&rk3308_pll_clks[APLL],
1041 						      priv->cru, APLL)))
1042 			rk3308_armclk_set_clk(priv, rate);
1043 		priv->armclk_hz = rate;
1044 		break;
1045 	case HCLK_SDMMC:
1046 	case HCLK_EMMC:
1047 	case SCLK_SDMMC:
1048 	case SCLK_EMMC:
1049 		ret = rk3308_mmc_set_clk(clk, rate);
1050 		break;
1051 	case SCLK_I2C0:
1052 	case SCLK_I2C1:
1053 	case SCLK_I2C2:
1054 	case SCLK_I2C3:
1055 		ret = rk3308_i2c_set_clk(clk, rate);
1056 		break;
1057 	case SCLK_MAC:
1058 		ret = rk3308_mac_set_clk(clk, rate);
1059 		break;
1060 	case SCLK_MAC_RMII:
1061 		ret = rk3308_mac_set_speed_clk(clk, rate);
1062 		break;
1063 	case SCLK_SARADC:
1064 		ret = rk3308_saradc_set_clk(clk, rate);
1065 		break;
1066 	case SCLK_TSADC:
1067 		ret = rk3308_tsadc_set_clk(clk, rate);
1068 		break;
1069 	case SCLK_SPI0:
1070 	case SCLK_SPI1:
1071 		ret = rk3308_spi_set_clk(clk, rate);
1072 		break;
1073 	case SCLK_PWM0:
1074 	case SCLK_PWM1:
1075 	case SCLK_PWM2:
1076 		ret = rk3308_pwm_set_clk(clk, rate);
1077 		break;
1078 	case DCLK_VOP:
1079 		ret = rk3308_vop_set_clk(clk, rate);
1080 		break;
1081 	case ACLK_BUS:
1082 	case HCLK_BUS:
1083 	case PCLK_BUS:
1084 		rate = rk3308_bus_set_clk(priv, clk->id, rate);
1085 		break;
1086 	case ACLK_PERI:
1087 	case HCLK_PERI:
1088 	case PCLK_PERI:
1089 		rate = rk3308_peri_set_clk(priv, clk->id, rate);
1090 		break;
1091 	case HCLK_AUDIO:
1092 	case PCLK_AUDIO:
1093 		rate = rk3308_audio_set_clk(priv, clk->id, rate);
1094 		break;
1095 	case SCLK_CRYPTO:
1096 	case SCLK_CRYPTO_APK:
1097 		ret = rk3308_crypto_set_clk(priv, clk->id, rate);
1098 		break;
1099 	case SCLK_RTC32K:
1100 		ret = rk3308_rtc32k_set_clk(priv, clk->id, rate);
1101 		break;
1102 	case SCLK_SFC:
1103 		ret = rk3308_sclk_sfc_set_clk(priv, rate);
1104 		break;
1105 	default:
1106 		return -ENOENT;
1107 	}
1108 
1109 	return ret;
1110 }
1111 
1112 #define ROCKCHIP_MMC_DELAY_SEL		BIT(11)
1113 #define ROCKCHIP_MMC_DEGREE_OFFSET	1
1114 #define ROCKCHIP_MMC_DEGREE_MASK	(0x3 << ROCKCHIP_MMC_DEGREE_OFFSET)
1115 #define ROCKCHIP_MMC_DELAYNUM_OFFSET	3
1116 #define ROCKCHIP_MMC_DELAYNUM_MASK	(0xff << ROCKCHIP_MMC_DELAYNUM_OFFSET)
1117 
1118 #define PSECS_PER_SEC 1000000000000LL
1119 /*
1120  * Each fine delay is between 44ps-77ps. Assume each fine delay is 60ps to
1121  * simplify calculations. So 45degs could be anywhere between 33deg and 57.8deg.
1122  */
1123 #define ROCKCHIP_MMC_DELAY_ELEMENT_PSEC 60
1124 
rockchip_mmc_get_phase(struct clk * clk)1125 int rockchip_mmc_get_phase(struct clk *clk)
1126 {
1127 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
1128 	struct rk3308_cru *cru = priv->cru;
1129 	u32 raw_value, delay_num;
1130 	u16 degrees = 0;
1131 	ulong rate;
1132 
1133 	rate = rk3308_clk_get_rate(clk);
1134 
1135 	if (rate < 0)
1136 		return rate;
1137 
1138 	if (clk->id == SCLK_EMMC_SAMPLE)
1139 		raw_value = readl(&cru->emmc_con[1]);
1140 	else
1141 		raw_value = readl(&cru->sdmmc_con[1]);
1142 
1143 	raw_value &= ROCKCHIP_MMC_DEGREE_MASK;
1144 	degrees = (raw_value >>  ROCKCHIP_MMC_DEGREE_OFFSET) * 90;
1145 
1146 	if (raw_value & ROCKCHIP_MMC_DELAY_SEL) {
1147 		/* degrees/delaynum * 10000 */
1148 		unsigned long factor = (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10) *
1149 					36 * (rate / 1000000);
1150 
1151 		delay_num = (raw_value & ROCKCHIP_MMC_DELAYNUM_MASK);
1152 		delay_num >>= ROCKCHIP_MMC_DELAYNUM_OFFSET;
1153 		degrees += DIV_ROUND_CLOSEST(delay_num * factor, 10000);
1154 	}
1155 
1156 	return degrees % 360;
1157 
1158 }
1159 
rockchip_mmc_set_phase(struct clk * clk,u32 degrees)1160 int rockchip_mmc_set_phase(struct clk *clk, u32 degrees)
1161 {
1162 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
1163 	struct rk3308_cru *cru = priv->cru;
1164 	u8 nineties, remainder, delay_num;
1165 	u32 raw_value, delay;
1166 	ulong rate;
1167 
1168 	rate = rk3308_clk_get_rate(clk);
1169 
1170 	if (rate < 0)
1171 		return rate;
1172 
1173 	nineties = degrees / 90;
1174 	remainder = (degrees % 90);
1175 
1176 	/*
1177 	 * Convert to delay; do a little extra work to make sure we
1178 	 * don't overflow 32-bit / 64-bit numbers.
1179 	 */
1180 	delay = 10000000; /* PSECS_PER_SEC / 10000 / 10 */
1181 	delay *= remainder;
1182 	delay = DIV_ROUND_CLOSEST(delay, (rate / 1000) * 36 *
1183 				(ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10));
1184 
1185 	delay_num = (u8)min_t(u32, delay, 255);
1186 
1187 	raw_value = delay_num ? ROCKCHIP_MMC_DELAY_SEL : 0;
1188 	raw_value |= delay_num << ROCKCHIP_MMC_DELAYNUM_OFFSET;
1189 	raw_value |= nineties << ROCKCHIP_MMC_DEGREE_OFFSET;
1190 
1191 	if (clk->id == SCLK_EMMC_SAMPLE)
1192 		writel(raw_value | 0xffff0000, &cru->emmc_con[1]);
1193 	else
1194 		writel(raw_value | 0xffff0000, &cru->sdmmc_con[1]);
1195 
1196 	debug("mmc set_phase(%d) delay_nums=%u reg=%#x actual_degrees=%d\n",
1197 	      degrees, delay_num, raw_value, rockchip_mmc_get_phase(clk));
1198 
1199 	return 0;
1200 
1201 }
1202 
rk3308_clk_get_phase(struct clk * clk)1203 static int rk3308_clk_get_phase(struct clk *clk)
1204 {
1205 	int ret;
1206 
1207 	switch (clk->id) {
1208 	case SCLK_EMMC_SAMPLE:
1209 	case SCLK_SDMMC_SAMPLE:
1210 		ret = rockchip_mmc_get_phase(clk);
1211 		break;
1212 	default:
1213 		return -ENOENT;
1214 	}
1215 
1216 	return ret;
1217 }
1218 
rk3308_clk_set_phase(struct clk * clk,int degrees)1219 static int rk3308_clk_set_phase(struct clk *clk, int degrees)
1220 {
1221 	int ret;
1222 
1223 	switch (clk->id) {
1224 	case SCLK_EMMC_SAMPLE:
1225 	case SCLK_SDMMC_SAMPLE:
1226 		ret = rockchip_mmc_set_phase(clk, degrees);
1227 		break;
1228 	default:
1229 		return -ENOENT;
1230 	}
1231 
1232 	return ret;
1233 }
1234 
rk3308_mac_set_parent(struct clk * clk,struct clk * parent)1235 static int __maybe_unused rk3308_mac_set_parent(struct clk *clk, struct clk *parent)
1236 {
1237 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
1238 
1239 	/*
1240 	 * If the requested parent is in the same clock-controller and
1241 	 * the id is SCLK_MAC_SRC, switch to the internal clock.
1242 	 */
1243 	if (parent->id == SCLK_MAC_SRC) {
1244 		debug("%s: switching RMII to SCLK_MAC\n", __func__);
1245 		rk_clrreg(&priv->cru->clksel_con[43], BIT(14));
1246 	} else {
1247 		debug("%s: switching RMII to CLKIN\n", __func__);
1248 		rk_setreg(&priv->cru->clksel_con[43], BIT(14));
1249 	}
1250 
1251 	return 0;
1252 }
1253 
rk3308_clk_set_parent(struct clk * clk,struct clk * parent)1254 static int __maybe_unused rk3308_clk_set_parent(struct clk *clk, struct clk *parent)
1255 {
1256 	switch (clk->id) {
1257 	case SCLK_MAC:
1258 		return rk3308_mac_set_parent(clk, parent);
1259 	default:
1260 		break;
1261 	}
1262 
1263 	debug("%s: unsupported clk %ld\n", __func__, clk->id);
1264 	return -ENOENT;
1265 }
1266 
1267 static struct clk_ops rk3308_clk_ops = {
1268 	.get_rate = rk3308_clk_get_rate,
1269 	.set_rate = rk3308_clk_set_rate,
1270 	.get_phase	= rk3308_clk_get_phase,
1271 	.set_phase	= rk3308_clk_set_phase,
1272 #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
1273 	.set_parent = rk3308_clk_set_parent,
1274 #endif
1275 };
1276 
rk3308_clk_init(struct udevice * dev)1277 static void rk3308_clk_init(struct udevice *dev)
1278 {
1279 	struct rk3308_clk_priv *priv = dev_get_priv(dev);
1280 	int ret;
1281 
1282 	if (rockchip_pll_get_rate(&rk3308_pll_clks[APLL],
1283 				  priv->cru, APLL) != APLL_HZ) {
1284 		ret = rk3308_armclk_set_clk(priv, APLL_HZ);
1285 		if (ret < 0)
1286 			printf("%s failed to set armclk rate\n", __func__);
1287 	}
1288 
1289 	rk3308_clk_get_pll_rate(priv);
1290 
1291 	rk3308_bus_set_clk(priv, ACLK_BUS, BUS_ACLK_HZ);
1292 	rk3308_bus_set_clk(priv, HCLK_BUS, BUS_HCLK_HZ);
1293 	rk3308_bus_set_clk(priv, PCLK_BUS, BUS_PCLK_HZ);
1294 
1295 	rk3308_peri_set_clk(priv, ACLK_PERI, PERI_ACLK_HZ);
1296 	rk3308_peri_set_clk(priv, HCLK_PERI, PERI_HCLK_HZ);
1297 	rk3308_peri_set_clk(priv, PCLK_PERI, PERI_PCLK_HZ);
1298 
1299 	rk3308_audio_set_clk(priv, HCLK_AUDIO, AUDIO_HCLK_HZ);
1300 	rk3308_audio_set_clk(priv, PCLK_AUDIO, AUDIO_PCLK_HZ);
1301 }
1302 
rk3308_clk_probe(struct udevice * dev)1303 static int rk3308_clk_probe(struct udevice *dev)
1304 {
1305 	struct rk3308_clk_priv *priv = dev_get_priv(dev);
1306 	int ret;
1307 
1308 	priv->sync_kernel = false;
1309 	if (!priv->armclk_enter_hz)
1310 		priv->armclk_enter_hz =
1311 		rockchip_pll_get_rate(&rk3308_pll_clks[APLL],
1312 				      priv->cru, APLL);
1313 	rk3308_clk_init(dev);
1314 	if (!priv->armclk_init_hz)
1315 		priv->armclk_init_hz =
1316 		rockchip_pll_get_rate(&rk3308_pll_clks[APLL],
1317 				      priv->cru, APLL);
1318 
1319 	/* Process 'assigned-{clocks/clock-parents/clock-rates}' properties */
1320 	ret = clk_set_defaults(dev);
1321 	if (ret)
1322 		debug("%s clk_set_defaults failed %d\n", __func__, ret);
1323 	else
1324 		priv->sync_kernel = true;
1325 
1326 	return 0;
1327 }
1328 
rk3308_clk_ofdata_to_platdata(struct udevice * dev)1329 static int rk3308_clk_ofdata_to_platdata(struct udevice *dev)
1330 {
1331 	struct rk3308_clk_priv *priv = dev_get_priv(dev);
1332 
1333 	priv->cru = dev_read_addr_ptr(dev);
1334 
1335 	return 0;
1336 }
1337 
rk3308_clk_bind(struct udevice * dev)1338 static int rk3308_clk_bind(struct udevice *dev)
1339 {
1340 	int ret;
1341 	struct udevice *sys_child, *sf_child;
1342 	struct sysreset_reg *priv;
1343 	struct softreset_reg *sf_priv;
1344 
1345 	/* The reset driver does not have a device node, so bind it here */
1346 	ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset",
1347 				 &sys_child);
1348 	if (ret) {
1349 		debug("Warning: No sysreset driver: ret=%d\n", ret);
1350 	} else {
1351 		priv = malloc(sizeof(struct sysreset_reg));
1352 		priv->glb_srst_fst_value = offsetof(struct rk3308_cru,
1353 						    glb_srst_fst);
1354 		priv->glb_srst_snd_value = offsetof(struct rk3308_cru,
1355 						    glb_srst_snd);
1356 		sys_child->priv = priv;
1357 	}
1358 
1359 	ret = device_bind_driver_to_node(dev, "rockchip_reset", "reset",
1360 					 dev_ofnode(dev), &sf_child);
1361 	if (ret) {
1362 		debug("Warning: No rockchip reset driver: ret=%d\n", ret);
1363 	} else {
1364 		sf_priv = malloc(sizeof(struct softreset_reg));
1365 		sf_priv->sf_reset_offset = offsetof(struct rk3308_cru,
1366 						    softrst_con[0]);
1367 		sf_priv->sf_reset_num = 12;
1368 		sf_child->priv = sf_priv;
1369 	}
1370 
1371 	return 0;
1372 }
1373 
1374 static const struct udevice_id rk3308_clk_ids[] = {
1375 	{ .compatible = "rockchip,rk3308-cru" },
1376 	{ }
1377 };
1378 
1379 U_BOOT_DRIVER(rockchip_rk3308_cru) = {
1380 	.name		= "rockchip_rk3308_cru",
1381 	.id		= UCLASS_CLK,
1382 	.of_match	= rk3308_clk_ids,
1383 	.priv_auto_alloc_size = sizeof(struct rk3308_clk_priv),
1384 	.ofdata_to_platdata = rk3308_clk_ofdata_to_platdata,
1385 	.ops		= &rk3308_clk_ops,
1386 	.bind		= rk3308_clk_bind,
1387 	.probe		= rk3308_clk_probe,
1388 };
1389 
1390 /**
1391  * soc_clk_dump() - Print clock frequencies
1392  * Returns zero on success
1393  *
1394  * Implementation for the clk dump command.
1395  */
soc_clk_dump(void)1396 int soc_clk_dump(void)
1397 {
1398 	struct udevice *cru_dev;
1399 	struct rk3308_clk_priv *priv;
1400 	const struct rk3308_clk_info *clk_dump;
1401 	struct clk clk;
1402 	unsigned long clk_count = ARRAY_SIZE(clks_dump);
1403 	unsigned long rate;
1404 	int i, ret;
1405 
1406 	ret = uclass_get_device_by_driver(UCLASS_CLK,
1407 					  DM_GET_DRIVER(rockchip_rk3308_cru),
1408 					  &cru_dev);
1409 	if (ret) {
1410 		printf("%s failed to get cru device\n", __func__);
1411 		return ret;
1412 	}
1413 
1414 	priv = dev_get_priv(cru_dev);
1415 	printf("CLK: (%s. arm: enter %lu KHz, init %lu KHz, kernel %lu%s)\n",
1416 	       priv->sync_kernel ? "sync kernel" : "uboot",
1417 	       priv->armclk_enter_hz / 1000,
1418 	       priv->armclk_init_hz / 1000,
1419 	       priv->set_armclk_rate ? priv->armclk_hz / 1000 : 0,
1420 	       priv->set_armclk_rate ? " KHz" : "N/A");
1421 	for (i = 0; i < clk_count; i++) {
1422 		clk_dump = &clks_dump[i];
1423 		if (clk_dump->name) {
1424 			clk.id = clk_dump->id;
1425 			ret = clk_request(cru_dev, &clk);
1426 			if (ret < 0)
1427 				return ret;
1428 
1429 			rate = clk_get_rate(&clk);
1430 			clk_free(&clk);
1431 			if (i == 0) {
1432 				if (rate < 0)
1433 					printf("  %s %s\n", clk_dump->name,
1434 					       "unknown");
1435 				else
1436 					printf("  %s %lu KHz\n", clk_dump->name,
1437 					       rate / 1000);
1438 			} else {
1439 				if (rate < 0)
1440 					printf("  %s %s\n", clk_dump->name,
1441 					       "unknown");
1442 				else
1443 					printf("  %s %lu KHz\n", clk_dump->name,
1444 					       rate / 1000);
1445 			}
1446 		}
1447 	}
1448 
1449 	return 0;
1450 }
1451