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