xref: /OK3568_Linux_fs/u-boot/drivers/clk/rockchip/clk_rk3308.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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_PWM:
978 		rate = rk3308_pwm_get_clk(clk);
979 		break;
980 	case DCLK_VOP:
981 		rate = rk3308_vop_get_clk(clk);
982 		break;
983 	case ACLK_BUS:
984 	case HCLK_BUS:
985 	case PCLK_BUS:
986 	case PCLK_WDT:
987 		rate = rk3308_bus_get_clk(priv, clk->id);
988 		break;
989 	case ACLK_PERI:
990 	case HCLK_PERI:
991 	case PCLK_PERI:
992 		rate = rk3308_peri_get_clk(priv, clk->id);
993 		break;
994 	case HCLK_AUDIO:
995 	case PCLK_AUDIO:
996 		rate = rk3308_audio_get_clk(priv, clk->id);
997 		break;
998 	case SCLK_CRYPTO:
999 	case SCLK_CRYPTO_APK:
1000 		rate = rk3308_crypto_get_clk(priv, clk->id);
1001 		break;
1002 	case SCLK_RTC32K:
1003 		rate = rk3308_rtc32k_get_clk(priv, clk->id);
1004 		break;
1005 	case SCLK_SFC:
1006 		rate = rk3308_sclk_sfc_get_clk(priv);
1007 		break;
1008 	default:
1009 		return -ENOENT;
1010 	}
1011 
1012 	return rate;
1013 }
1014 
rk3308_clk_set_rate(struct clk * clk,ulong rate)1015 static ulong rk3308_clk_set_rate(struct clk *clk, ulong rate)
1016 {
1017 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
1018 	ulong ret = 0;
1019 
1020 	debug("%s %ld %ld\n", __func__, clk->id, rate);
1021 
1022 	switch (clk->id) {
1023 	case PLL_DPLL:
1024 		ret = rockchip_pll_set_rate(&rk3308_pll_clks[DPLL], priv->cru,
1025 					    DPLL, rate);
1026 		priv->dpll_hz = rockchip_pll_get_rate(&rk3308_pll_clks[DPLL],
1027 						      priv->cru, DPLL);
1028 		break;
1029 	case ARMCLK:
1030 		if (priv->armclk_hz)
1031 			rk3308_armclk_set_clk(priv, rate);
1032 		priv->armclk_hz = rate;
1033 		break;
1034 	case HCLK_SDMMC:
1035 	case HCLK_EMMC:
1036 	case SCLK_SDMMC:
1037 	case SCLK_EMMC:
1038 		ret = rk3308_mmc_set_clk(clk, rate);
1039 		break;
1040 	case SCLK_I2C0:
1041 	case SCLK_I2C1:
1042 	case SCLK_I2C2:
1043 	case SCLK_I2C3:
1044 		ret = rk3308_i2c_set_clk(clk, rate);
1045 		break;
1046 	case SCLK_MAC:
1047 		ret = rk3308_mac_set_clk(clk, rate);
1048 		break;
1049 	case SCLK_MAC_RMII:
1050 		ret = rk3308_mac_set_speed_clk(clk, rate);
1051 		break;
1052 	case SCLK_SARADC:
1053 		ret = rk3308_saradc_set_clk(clk, rate);
1054 		break;
1055 	case SCLK_TSADC:
1056 		ret = rk3308_tsadc_set_clk(clk, rate);
1057 		break;
1058 	case SCLK_SPI0:
1059 	case SCLK_SPI1:
1060 		ret = rk3308_spi_set_clk(clk, rate);
1061 		break;
1062 	case SCLK_PWM:
1063 		ret = rk3308_pwm_set_clk(clk, rate);
1064 		break;
1065 	case DCLK_VOP:
1066 		ret = rk3308_vop_set_clk(clk, rate);
1067 		break;
1068 	case ACLK_BUS:
1069 	case HCLK_BUS:
1070 	case PCLK_BUS:
1071 		rate = rk3308_bus_set_clk(priv, clk->id, rate);
1072 		break;
1073 	case ACLK_PERI:
1074 	case HCLK_PERI:
1075 	case PCLK_PERI:
1076 		rate = rk3308_peri_set_clk(priv, clk->id, rate);
1077 		break;
1078 	case HCLK_AUDIO:
1079 	case PCLK_AUDIO:
1080 		rate = rk3308_audio_set_clk(priv, clk->id, rate);
1081 		break;
1082 	case SCLK_CRYPTO:
1083 	case SCLK_CRYPTO_APK:
1084 		ret = rk3308_crypto_set_clk(priv, clk->id, rate);
1085 		break;
1086 	case SCLK_RTC32K:
1087 		ret = rk3308_rtc32k_set_clk(priv, clk->id, rate);
1088 		break;
1089 	case SCLK_SFC:
1090 		ret = rk3308_sclk_sfc_set_clk(priv, rate);
1091 		break;
1092 	default:
1093 		return -ENOENT;
1094 	}
1095 
1096 	return ret;
1097 }
1098 
1099 #define ROCKCHIP_MMC_DELAY_SEL		BIT(11)
1100 #define ROCKCHIP_MMC_DEGREE_OFFSET	1
1101 #define ROCKCHIP_MMC_DEGREE_MASK	(0x3 << ROCKCHIP_MMC_DEGREE_OFFSET)
1102 #define ROCKCHIP_MMC_DELAYNUM_OFFSET	3
1103 #define ROCKCHIP_MMC_DELAYNUM_MASK	(0xff << ROCKCHIP_MMC_DELAYNUM_OFFSET)
1104 
1105 #define PSECS_PER_SEC 1000000000000LL
1106 /*
1107  * Each fine delay is between 44ps-77ps. Assume each fine delay is 60ps to
1108  * simplify calculations. So 45degs could be anywhere between 33deg and 57.8deg.
1109  */
1110 #define ROCKCHIP_MMC_DELAY_ELEMENT_PSEC 60
1111 
rockchip_mmc_get_phase(struct clk * clk)1112 int rockchip_mmc_get_phase(struct clk *clk)
1113 {
1114 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
1115 	struct rk3308_cru *cru = priv->cru;
1116 	u32 raw_value, delay_num;
1117 	u16 degrees = 0;
1118 	ulong rate;
1119 
1120 	rate = rk3308_clk_get_rate(clk);
1121 
1122 	if (rate < 0)
1123 		return rate;
1124 
1125 	if (clk->id == SCLK_EMMC_SAMPLE)
1126 		raw_value = readl(&cru->emmc_con[1]);
1127 	else
1128 		raw_value = readl(&cru->sdmmc_con[1]);
1129 
1130 	raw_value &= ROCKCHIP_MMC_DEGREE_MASK;
1131 	degrees = (raw_value >>  ROCKCHIP_MMC_DEGREE_OFFSET) * 90;
1132 
1133 	if (raw_value & ROCKCHIP_MMC_DELAY_SEL) {
1134 		/* degrees/delaynum * 10000 */
1135 		unsigned long factor = (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10) *
1136 					36 * (rate / 1000000);
1137 
1138 		delay_num = (raw_value & ROCKCHIP_MMC_DELAYNUM_MASK);
1139 		delay_num >>= ROCKCHIP_MMC_DELAYNUM_OFFSET;
1140 		degrees += DIV_ROUND_CLOSEST(delay_num * factor, 10000);
1141 	}
1142 
1143 	return degrees % 360;
1144 
1145 }
1146 
rockchip_mmc_set_phase(struct clk * clk,u32 degrees)1147 int rockchip_mmc_set_phase(struct clk *clk, u32 degrees)
1148 {
1149 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
1150 	struct rk3308_cru *cru = priv->cru;
1151 	u8 nineties, remainder, delay_num;
1152 	u32 raw_value, delay;
1153 	ulong rate;
1154 
1155 	rate = rk3308_clk_get_rate(clk);
1156 
1157 	if (rate < 0)
1158 		return rate;
1159 
1160 	nineties = degrees / 90;
1161 	remainder = (degrees % 90);
1162 
1163 	/*
1164 	 * Convert to delay; do a little extra work to make sure we
1165 	 * don't overflow 32-bit / 64-bit numbers.
1166 	 */
1167 	delay = 10000000; /* PSECS_PER_SEC / 10000 / 10 */
1168 	delay *= remainder;
1169 	delay = DIV_ROUND_CLOSEST(delay, (rate / 1000) * 36 *
1170 				(ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10));
1171 
1172 	delay_num = (u8)min_t(u32, delay, 255);
1173 
1174 	raw_value = delay_num ? ROCKCHIP_MMC_DELAY_SEL : 0;
1175 	raw_value |= delay_num << ROCKCHIP_MMC_DELAYNUM_OFFSET;
1176 	raw_value |= nineties << ROCKCHIP_MMC_DEGREE_OFFSET;
1177 
1178 	if (clk->id == SCLK_EMMC_SAMPLE)
1179 		writel(raw_value | 0xffff0000, &cru->emmc_con[1]);
1180 	else
1181 		writel(raw_value | 0xffff0000, &cru->sdmmc_con[1]);
1182 
1183 	debug("mmc set_phase(%d) delay_nums=%u reg=%#x actual_degrees=%d\n",
1184 	      degrees, delay_num, raw_value, rockchip_mmc_get_phase(clk));
1185 
1186 	return 0;
1187 
1188 }
1189 
rk3308_clk_get_phase(struct clk * clk)1190 static int rk3308_clk_get_phase(struct clk *clk)
1191 {
1192 	int ret;
1193 
1194 	switch (clk->id) {
1195 	case SCLK_EMMC_SAMPLE:
1196 	case SCLK_SDMMC_SAMPLE:
1197 		ret = rockchip_mmc_get_phase(clk);
1198 		break;
1199 	default:
1200 		return -ENOENT;
1201 	}
1202 
1203 	return ret;
1204 }
1205 
rk3308_clk_set_phase(struct clk * clk,int degrees)1206 static int rk3308_clk_set_phase(struct clk *clk, int degrees)
1207 {
1208 	int ret;
1209 
1210 	switch (clk->id) {
1211 	case SCLK_EMMC_SAMPLE:
1212 	case SCLK_SDMMC_SAMPLE:
1213 		ret = rockchip_mmc_set_phase(clk, degrees);
1214 		break;
1215 	default:
1216 		return -ENOENT;
1217 	}
1218 
1219 	return ret;
1220 }
1221 
rk3308_mac_set_parent(struct clk * clk,struct clk * parent)1222 static int __maybe_unused rk3308_mac_set_parent(struct clk *clk, struct clk *parent)
1223 {
1224 	struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
1225 
1226 	/*
1227 	 * If the requested parent is in the same clock-controller and
1228 	 * the id is SCLK_MAC_SRC, switch to the internal clock.
1229 	 */
1230 	if (parent->id == SCLK_MAC_SRC) {
1231 		debug("%s: switching RMII to SCLK_MAC\n", __func__);
1232 		rk_clrreg(&priv->cru->clksel_con[43], BIT(14));
1233 	} else {
1234 		debug("%s: switching RMII to CLKIN\n", __func__);
1235 		rk_setreg(&priv->cru->clksel_con[43], BIT(14));
1236 	}
1237 
1238 	return 0;
1239 }
1240 
rk3308_clk_set_parent(struct clk * clk,struct clk * parent)1241 static int __maybe_unused rk3308_clk_set_parent(struct clk *clk, struct clk *parent)
1242 {
1243 	switch (clk->id) {
1244 	case SCLK_MAC:
1245 		return rk3308_mac_set_parent(clk, parent);
1246 	default:
1247 		break;
1248 	}
1249 
1250 	debug("%s: unsupported clk %ld\n", __func__, clk->id);
1251 	return -ENOENT;
1252 }
1253 
1254 static struct clk_ops rk3308_clk_ops = {
1255 	.get_rate = rk3308_clk_get_rate,
1256 	.set_rate = rk3308_clk_set_rate,
1257 	.get_phase	= rk3308_clk_get_phase,
1258 	.set_phase	= rk3308_clk_set_phase,
1259 #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
1260 	.set_parent = rk3308_clk_set_parent,
1261 #endif
1262 };
1263 
rk3308_clk_init(struct udevice * dev)1264 static void rk3308_clk_init(struct udevice *dev)
1265 {
1266 	struct rk3308_clk_priv *priv = dev_get_priv(dev);
1267 	int ret;
1268 
1269 	if (rockchip_pll_get_rate(&rk3308_pll_clks[APLL],
1270 				  priv->cru, APLL) != APLL_HZ) {
1271 		ret = rk3308_armclk_set_clk(priv, APLL_HZ);
1272 		if (ret < 0)
1273 			printf("%s failed to set armclk rate\n", __func__);
1274 	}
1275 
1276 	rk3308_clk_get_pll_rate(priv);
1277 
1278 	rk3308_bus_set_clk(priv, ACLK_BUS, BUS_ACLK_HZ);
1279 	rk3308_bus_set_clk(priv, HCLK_BUS, BUS_HCLK_HZ);
1280 	rk3308_bus_set_clk(priv, PCLK_BUS, BUS_PCLK_HZ);
1281 
1282 	rk3308_peri_set_clk(priv, ACLK_PERI, PERI_ACLK_HZ);
1283 	rk3308_peri_set_clk(priv, HCLK_PERI, PERI_HCLK_HZ);
1284 	rk3308_peri_set_clk(priv, PCLK_PERI, PERI_PCLK_HZ);
1285 
1286 	rk3308_audio_set_clk(priv, HCLK_AUDIO, AUDIO_HCLK_HZ);
1287 	rk3308_audio_set_clk(priv, PCLK_AUDIO, AUDIO_PCLK_HZ);
1288 }
1289 
rk3308_clk_probe(struct udevice * dev)1290 static int rk3308_clk_probe(struct udevice *dev)
1291 {
1292 	struct rk3308_clk_priv *priv = dev_get_priv(dev);
1293 	int ret;
1294 
1295 	priv->sync_kernel = false;
1296 	if (!priv->armclk_enter_hz)
1297 		priv->armclk_enter_hz =
1298 		rockchip_pll_get_rate(&rk3308_pll_clks[APLL],
1299 				      priv->cru, APLL);
1300 	rk3308_clk_init(dev);
1301 	if (!priv->armclk_init_hz)
1302 		priv->armclk_init_hz =
1303 		rockchip_pll_get_rate(&rk3308_pll_clks[APLL],
1304 				      priv->cru, APLL);
1305 
1306 	/* Process 'assigned-{clocks/clock-parents/clock-rates}' properties */
1307 	ret = clk_set_defaults(dev);
1308 	if (ret)
1309 		debug("%s clk_set_defaults failed %d\n", __func__, ret);
1310 	else
1311 		priv->sync_kernel = true;
1312 
1313 	return 0;
1314 }
1315 
rk3308_clk_ofdata_to_platdata(struct udevice * dev)1316 static int rk3308_clk_ofdata_to_platdata(struct udevice *dev)
1317 {
1318 	struct rk3308_clk_priv *priv = dev_get_priv(dev);
1319 
1320 	priv->cru = dev_read_addr_ptr(dev);
1321 
1322 	return 0;
1323 }
1324 
rk3308_clk_bind(struct udevice * dev)1325 static int rk3308_clk_bind(struct udevice *dev)
1326 {
1327 	int ret;
1328 	struct udevice *sys_child, *sf_child;
1329 	struct sysreset_reg *priv;
1330 	struct softreset_reg *sf_priv;
1331 
1332 	/* The reset driver does not have a device node, so bind it here */
1333 	ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset",
1334 				 &sys_child);
1335 	if (ret) {
1336 		debug("Warning: No sysreset driver: ret=%d\n", ret);
1337 	} else {
1338 		priv = malloc(sizeof(struct sysreset_reg));
1339 		priv->glb_srst_fst_value = offsetof(struct rk3308_cru,
1340 						    glb_srst_fst);
1341 		priv->glb_srst_snd_value = offsetof(struct rk3308_cru,
1342 						    glb_srst_snd);
1343 		sys_child->priv = priv;
1344 	}
1345 
1346 	ret = device_bind_driver_to_node(dev, "rockchip_reset", "reset",
1347 					 dev_ofnode(dev), &sf_child);
1348 	if (ret) {
1349 		debug("Warning: No rockchip reset driver: ret=%d\n", ret);
1350 	} else {
1351 		sf_priv = malloc(sizeof(struct softreset_reg));
1352 		sf_priv->sf_reset_offset = offsetof(struct rk3308_cru,
1353 						    softrst_con[0]);
1354 		sf_priv->sf_reset_num = 12;
1355 		sf_child->priv = sf_priv;
1356 	}
1357 
1358 	return 0;
1359 }
1360 
1361 static const struct udevice_id rk3308_clk_ids[] = {
1362 	{ .compatible = "rockchip,rk3308-cru" },
1363 	{ }
1364 };
1365 
1366 U_BOOT_DRIVER(rockchip_rk3308_cru) = {
1367 	.name		= "rockchip_rk3308_cru",
1368 	.id		= UCLASS_CLK,
1369 	.of_match	= rk3308_clk_ids,
1370 	.priv_auto_alloc_size = sizeof(struct rk3308_clk_priv),
1371 	.ofdata_to_platdata = rk3308_clk_ofdata_to_platdata,
1372 	.ops		= &rk3308_clk_ops,
1373 	.bind		= rk3308_clk_bind,
1374 	.probe		= rk3308_clk_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  */
soc_clk_dump(void)1383 int soc_clk_dump(void)
1384 {
1385 	struct udevice *cru_dev;
1386 	struct rk3308_clk_priv *priv;
1387 	const struct rk3308_clk_info *clk_dump;
1388 	struct clk clk;
1389 	unsigned long clk_count = ARRAY_SIZE(clks_dump);
1390 	unsigned long rate;
1391 	int i, ret;
1392 
1393 	ret = uclass_get_device_by_driver(UCLASS_CLK,
1394 					  DM_GET_DRIVER(rockchip_rk3308_cru),
1395 					  &cru_dev);
1396 	if (ret) {
1397 		printf("%s failed to get cru device\n", __func__);
1398 		return ret;
1399 	}
1400 
1401 	priv = dev_get_priv(cru_dev);
1402 	printf("CLK: (%s. arm: enter %lu KHz, init %lu KHz, kernel %lu%s)\n",
1403 	       priv->sync_kernel ? "sync kernel" : "uboot",
1404 	       priv->armclk_enter_hz / 1000,
1405 	       priv->armclk_init_hz / 1000,
1406 	       priv->set_armclk_rate ? priv->armclk_hz / 1000 : 0,
1407 	       priv->set_armclk_rate ? " KHz" : "N/A");
1408 	for (i = 0; i < clk_count; i++) {
1409 		clk_dump = &clks_dump[i];
1410 		if (clk_dump->name) {
1411 			clk.id = clk_dump->id;
1412 			ret = clk_request(cru_dev, &clk);
1413 			if (ret < 0)
1414 				return ret;
1415 
1416 			rate = clk_get_rate(&clk);
1417 			clk_free(&clk);
1418 			if (i == 0) {
1419 				if (rate < 0)
1420 					printf("  %s %s\n", clk_dump->name,
1421 					       "unknown");
1422 				else
1423 					printf("  %s %lu KHz\n", clk_dump->name,
1424 					       rate / 1000);
1425 			} else {
1426 				if (rate < 0)
1427 					printf("  %s %s\n", clk_dump->name,
1428 					       "unknown");
1429 				else
1430 					printf("  %s %lu KHz\n", clk_dump->name,
1431 					       rate / 1000);
1432 			}
1433 		}
1434 	}
1435 
1436 	return 0;
1437 }
1438