blob: 580c0b1b0cf3019e35dd277d6f39d3df0175ffed [file] [log] [blame]
Jagan Teki674d1b92022-12-14 23:21:00 +05301// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd
4 * Copyright (c) 2022 Edgeble AI Technologies Pvt. Ltd.
5 * Author: Finley Xiao <finley.xiao@rock-chips.com>
6 */
7
8#include <common.h>
9#include <bitfield.h>
10#include <clk-uclass.h>
11#include <dm.h>
12#include <errno.h>
13#include <syscon.h>
14#include <asm/arch-rockchip/clock.h>
15#include <asm/arch-rockchip/cru_rv1126.h>
16#include <asm/arch-rockchip/grf_rv1126.h>
17#include <asm/arch-rockchip/hardware.h>
18#include <dm/device-internal.h>
19#include <asm/io.h>
20#include <dm/lists.h>
21#include <dt-bindings/clock/rockchip,rv1126-cru.h>
22
23DECLARE_GLOBAL_DATA_PTR;
24
25#define RV1126_CPUCLK_RATE(_rate, _aclk_div, _pclk_div) \
26{ \
27 .rate = _rate##U, \
28 .aclk_div = _aclk_div, \
29 .pclk_div = _pclk_div, \
30}
31
32#define DIV_TO_RATE(input_rate, div) ((input_rate) / ((div) + 1))
33
34static struct rockchip_cpu_rate_table rv1126_cpu_rates[] = {
35 RV1126_CPUCLK_RATE(1200000000, 1, 5),
36 RV1126_CPUCLK_RATE(1008000000, 1, 5),
37 RV1126_CPUCLK_RATE(816000000, 1, 3),
38 RV1126_CPUCLK_RATE(600000000, 1, 3),
39 RV1126_CPUCLK_RATE(408000000, 1, 1),
40};
41
42static struct rockchip_pll_rate_table rv1126_pll_rates[] = {
43 /* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */
44 RK3036_PLL_RATE(1600000000, 3, 200, 1, 1, 1, 0),
45 RK3036_PLL_RATE(1400000000, 3, 350, 2, 1, 1, 0),
46 RK3036_PLL_RATE(1200000000, 1, 100, 2, 1, 1, 0),
47 RK3036_PLL_RATE(1188000000, 1, 99, 2, 1, 1, 0),
48 RK3036_PLL_RATE(1100000000, 3, 275, 2, 1, 1, 0),
49 RK3036_PLL_RATE(1008000000, 1, 84, 2, 1, 1, 0),
50 RK3036_PLL_RATE(1000000000, 3, 250, 2, 1, 1, 0),
51 RK3036_PLL_RATE(816000000, 1, 68, 2, 1, 1, 0),
52 RK3036_PLL_RATE(800000000, 3, 200, 2, 1, 1, 0),
53 RK3036_PLL_RATE(600000000, 1, 100, 4, 1, 1, 0),
54 RK3036_PLL_RATE(594000000, 1, 99, 4, 1, 1, 0),
55 RK3036_PLL_RATE(500000000, 1, 125, 6, 1, 1, 0),
56 RK3036_PLL_RATE(200000000, 1, 100, 6, 2, 1, 0),
57 RK3036_PLL_RATE(100000000, 1, 100, 6, 4, 1, 0),
58 { /* sentinel */ },
59};
60
61static struct rockchip_pll_clock rv1126_pll_clks[] = {
62 [APLL] = PLL(pll_rk3328, PLL_APLL, RV1126_PLL_CON(0),
63 RV1126_MODE_CON, 0, 10, 0, rv1126_pll_rates),
64 [DPLL] = PLL(pll_rk3328, PLL_DPLL, RV1126_PLL_CON(8),
65 RV1126_MODE_CON, 2, 10, 0, NULL),
66 [CPLL] = PLL(pll_rk3328, PLL_CPLL, RV1126_PLL_CON(16),
67 RV1126_MODE_CON, 4, 10, 0, rv1126_pll_rates),
68 [HPLL] = PLL(pll_rk3328, PLL_HPLL, RV1126_PLL_CON(24),
69 RV1126_MODE_CON, 6, 10, 0, rv1126_pll_rates),
70 [GPLL] = PLL(pll_rk3328, PLL_GPLL, RV1126_PMU_PLL_CON(0),
71 RV1126_PMU_MODE, 0, 10, 0, rv1126_pll_rates),
72};
73
74static ulong rv1126_gpll_set_rate(struct rv1126_clk_priv *priv,
75 struct rv1126_pmuclk_priv *pmu_priv,
76 ulong rate);
77/*
78 *
79 * rational_best_approximation(31415, 10000,
80 * (1 << 8) - 1, (1 << 5) - 1, &n, &d);
81 *
82 * you may look at given_numerator as a fixed point number,
83 * with the fractional part size described in given_denominator.
84 *
85 * for theoretical background, see:
86 * http://en.wikipedia.org/wiki/Continued_fraction
87 */
88static void rational_best_approximation(unsigned long given_numerator,
89 unsigned long given_denominator,
90 unsigned long max_numerator,
91 unsigned long max_denominator,
92 unsigned long *best_numerator,
93 unsigned long *best_denominator)
94{
95 unsigned long n, d, n0, d0, n1, d1;
96
97 n = given_numerator;
98 d = given_denominator;
99 n0 = 0;
100 d1 = 0;
101 n1 = 1;
102 d0 = 1;
103 for (;;) {
104 unsigned long t, a;
105
106 if (n1 > max_numerator || d1 > max_denominator) {
107 n1 = n0;
108 d1 = d0;
109 break;
110 }
111 if (d == 0)
112 break;
113 t = d;
114 a = n / d;
115 d = n % d;
116 n = t;
117 t = n0 + a * n1;
118 n0 = n1;
119 n1 = t;
120 t = d0 + a * d1;
121 d0 = d1;
122 d1 = t;
123 }
124 *best_numerator = n1;
125 *best_denominator = d1;
126}
127
128static ulong rv1126_gpll_get_pmuclk(struct rv1126_pmuclk_priv *priv)
129{
130 return rockchip_pll_get_rate(&rv1126_pll_clks[GPLL],
131 priv->pmucru, GPLL);
132}
133
134static ulong rv1126_gpll_set_pmuclk(struct rv1126_pmuclk_priv *pmu_priv, ulong rate)
135{
136 struct udevice *cru_dev;
137 struct rv1126_clk_priv *priv;
138 int ret;
139
140 ret = uclass_get_device_by_driver(UCLASS_CLK,
141 DM_DRIVER_GET(rockchip_rv1126_cru),
142 &cru_dev);
143 if (ret) {
144 printf("%s: could not find cru device\n", __func__);
145 return ret;
146 }
147 priv = dev_get_priv(cru_dev);
148
149 if (rv1126_gpll_set_rate(priv, pmu_priv, rate)) {
150 printf("%s: failed to set gpll rate %lu\n", __func__, rate);
151 return -EINVAL;
152 }
153 return 0;
154}
155
156static ulong rv1126_rtc32k_get_pmuclk(struct rv1126_pmuclk_priv *priv)
157{
158 struct rv1126_pmucru *pmucru = priv->pmucru;
159 unsigned long m, n;
160 u32 fracdiv;
161
162 fracdiv = readl(&pmucru->pmu_clksel_con[13]);
163 m = fracdiv & CLK_RTC32K_FRAC_NUMERATOR_MASK;
164 m >>= CLK_RTC32K_FRAC_NUMERATOR_SHIFT;
165 n = fracdiv & CLK_RTC32K_FRAC_DENOMINATOR_MASK;
166 n >>= CLK_RTC32K_FRAC_DENOMINATOR_SHIFT;
167
168 return OSC_HZ * m / n;
169}
170
171static ulong rv1126_rtc32k_set_pmuclk(struct rv1126_pmuclk_priv *priv,
172 ulong rate)
173{
174 struct rv1126_pmucru *pmucru = priv->pmucru;
175 unsigned long m, n, val;
176
177 rk_clrsetreg(&pmucru->pmu_clksel_con[0], RTC32K_SEL_MASK,
178 RTC32K_SEL_OSC0_DIV32K << RTC32K_SEL_SHIFT);
179
180 rational_best_approximation(rate, OSC_HZ,
181 GENMASK(16 - 1, 0),
182 GENMASK(16 - 1, 0),
183 &m, &n);
184 val = m << CLK_RTC32K_FRAC_NUMERATOR_SHIFT | n;
185 writel(val, &pmucru->pmu_clksel_con[13]);
186
187 return rv1126_rtc32k_get_pmuclk(priv);
188}
189
190static ulong rv1126_i2c_get_pmuclk(struct rv1126_pmuclk_priv *priv,
191 ulong clk_id)
192{
193 struct rv1126_pmucru *pmucru = priv->pmucru;
194 u32 div, con;
195
196 switch (clk_id) {
197 case CLK_I2C0:
198 con = readl(&pmucru->pmu_clksel_con[2]);
199 div = (con & CLK_I2C0_DIV_MASK) >> CLK_I2C0_DIV_SHIFT;
200 break;
201 case CLK_I2C2:
202 con = readl(&pmucru->pmu_clksel_con[3]);
203 div = (con & CLK_I2C1_DIV_MASK) >> CLK_I2C1_DIV_SHIFT;
204 break;
205 default:
206 return -ENOENT;
207 }
208
209 return DIV_TO_RATE(priv->gpll_hz, div);
210}
211
212static ulong rv1126_i2c_set_pmuclk(struct rv1126_pmuclk_priv *priv,
213 ulong clk_id, ulong rate)
214{
215 struct rv1126_pmucru *pmucru = priv->pmucru;
216 int src_clk_div;
217
218 src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
219 assert(src_clk_div - 1 <= 127);
220
221 switch (clk_id) {
222 case CLK_I2C0:
223 rk_clrsetreg(&pmucru->pmu_clksel_con[2], CLK_I2C0_DIV_MASK,
224 (src_clk_div - 1) << CLK_I2C0_DIV_SHIFT);
225 break;
226 case CLK_I2C2:
227 rk_clrsetreg(&pmucru->pmu_clksel_con[3], CLK_I2C2_DIV_MASK,
228 (src_clk_div - 1) << CLK_I2C2_DIV_SHIFT);
229 break;
230 default:
231 return -ENOENT;
232 }
233
234 return rv1126_i2c_get_pmuclk(priv, clk_id);
235}
236
237static ulong rv1126_pwm_get_pmuclk(struct rv1126_pmuclk_priv *priv,
238 ulong clk_id)
239{
240 struct rv1126_pmucru *pmucru = priv->pmucru;
241 u32 div, sel, con;
242
243 switch (clk_id) {
244 case CLK_PWM0:
245 con = readl(&pmucru->pmu_clksel_con[6]);
246 sel = (con & CLK_PWM0_SEL_MASK) >> CLK_PWM0_SEL_SHIFT;
247 div = (con & CLK_PWM0_DIV_MASK) >> CLK_PWM0_DIV_SHIFT;
248 if (sel == CLK_PWM0_SEL_XIN24M)
249 return OSC_HZ;
250 break;
251 case CLK_PWM1:
252 con = readl(&pmucru->pmu_clksel_con[6]);
253 sel = (con & CLK_PWM1_SEL_MASK) >> CLK_PWM1_SEL_SHIFT;
254 div = (con & CLK_PWM1_DIV_MASK) >> CLK_PWM1_DIV_SHIFT;
255 if (sel == CLK_PWM1_SEL_XIN24M)
256 return OSC_HZ;
257 break;
258 default:
259 return -ENOENT;
260 }
261
262 return DIV_TO_RATE(priv->gpll_hz, div);
263}
264
265static ulong rv1126_pwm_set_pmuclk(struct rv1126_pmuclk_priv *priv,
266 ulong clk_id, ulong rate)
267{
268 struct rv1126_pmucru *pmucru = priv->pmucru;
269 int src_clk_div;
270
271 switch (clk_id) {
272 case CLK_PWM0:
273 if (rate == OSC_HZ) {
274 rk_clrsetreg(&pmucru->pmu_clksel_con[6],
275 CLK_PWM0_SEL_MASK,
276 CLK_PWM0_SEL_XIN24M << CLK_PWM0_SEL_SHIFT);
277 rk_clrsetreg(&pmucru->pmu_clksel_con[6],
278 CLK_PWM0_DIV_MASK, 0);
279 } else {
280 src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
281 assert(src_clk_div - 1 <= 127);
282 rk_clrsetreg(&pmucru->pmu_clksel_con[6],
283 CLK_PWM0_DIV_MASK,
284 (src_clk_div - 1) << CLK_PWM0_DIV_SHIFT);
285 rk_clrsetreg(&pmucru->pmu_clksel_con[6],
286 CLK_PWM0_SEL_MASK,
287 CLK_PWM0_SEL_GPLL << CLK_PWM0_SEL_SHIFT);
288 }
289 break;
290 case CLK_PWM1:
291 if (rate == OSC_HZ) {
292 rk_clrsetreg(&pmucru->pmu_clksel_con[6],
293 CLK_PWM1_SEL_MASK,
294 CLK_PWM1_SEL_XIN24M << CLK_PWM1_SEL_SHIFT);
295 rk_clrsetreg(&pmucru->pmu_clksel_con[6],
296 CLK_PWM1_DIV_MASK, 0);
297 } else {
298 src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
299 assert(src_clk_div - 1 <= 127);
300 rk_clrsetreg(&pmucru->pmu_clksel_con[6],
301 CLK_PWM1_DIV_MASK,
302 (src_clk_div - 1) << CLK_PWM1_DIV_SHIFT);
303 rk_clrsetreg(&pmucru->pmu_clksel_con[6],
304 CLK_PWM1_SEL_MASK,
305 CLK_PWM1_SEL_GPLL << CLK_PWM1_SEL_SHIFT);
306 }
307 break;
308 default:
309 return -ENOENT;
310 }
311
312 return rv1126_pwm_get_pmuclk(priv, clk_id);
313}
314
315static ulong rv1126_spi_get_pmuclk(struct rv1126_pmuclk_priv *priv)
316{
317 struct rv1126_pmucru *pmucru = priv->pmucru;
318 u32 div, con;
319
320 con = readl(&pmucru->pmu_clksel_con[9]);
321 div = (con & CLK_SPI0_DIV_MASK) >> CLK_SPI0_DIV_SHIFT;
322
323 return DIV_TO_RATE(priv->gpll_hz, div);
324}
325
326static ulong rv1126_spi_set_pmuclk(struct rv1126_pmuclk_priv *priv,
327 ulong rate)
328{
329 struct rv1126_pmucru *pmucru = priv->pmucru;
330 int src_clk_div;
331
332 src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
333 assert(src_clk_div - 1 <= 127);
334
335 rk_clrsetreg(&pmucru->pmu_clksel_con[9],
336 CLK_SPI0_SEL_MASK | CLK_SPI0_DIV_MASK,
337 CLK_SPI0_SEL_GPLL << CLK_SPI0_SEL_SHIFT |
338 (src_clk_div - 1) << CLK_SPI0_DIV_SHIFT);
339
340 return rv1126_spi_get_pmuclk(priv);
341}
342
343static ulong rv1126_pdpmu_get_pmuclk(struct rv1126_pmuclk_priv *priv)
344{
345 struct rv1126_pmucru *pmucru = priv->pmucru;
346 u32 div, con;
347
348 con = readl(&pmucru->pmu_clksel_con[1]);
349 div = (con & PCLK_PDPMU_DIV_MASK) >> PCLK_PDPMU_DIV_SHIFT;
350
351 return DIV_TO_RATE(priv->gpll_hz, div);
352}
353
354static ulong rv1126_pdpmu_set_pmuclk(struct rv1126_pmuclk_priv *priv,
355 ulong rate)
356{
357 struct rv1126_pmucru *pmucru = priv->pmucru;
358 int src_clk_div;
359
360 src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
361 assert(src_clk_div - 1 <= 31);
362
363 rk_clrsetreg(&pmucru->pmu_clksel_con[1],
364 PCLK_PDPMU_DIV_MASK,
365 (src_clk_div - 1) << PCLK_PDPMU_DIV_SHIFT);
366
367 return rv1126_pdpmu_get_pmuclk(priv);
368}
369
370static ulong rv1126_pmuclk_get_rate(struct clk *clk)
371{
372 struct rv1126_pmuclk_priv *priv = dev_get_priv(clk->dev);
373 ulong rate = 0;
374
375 if (!priv->gpll_hz) {
376 printf("%s gpll=%lu\n", __func__, priv->gpll_hz);
377 return -ENOENT;
378 }
379
380 debug("%s %ld\n", __func__, clk->id);
381 switch (clk->id) {
382 case PLL_GPLL:
383 rate = rv1126_gpll_get_pmuclk(priv);
384 break;
385 case CLK_RTC32K:
386 rate = rv1126_rtc32k_get_pmuclk(priv);
387 break;
388 case CLK_I2C0:
389 case CLK_I2C2:
390 rate = rv1126_i2c_get_pmuclk(priv, clk->id);
391 break;
392 case CLK_PWM0:
393 case CLK_PWM1:
394 rate = rv1126_pwm_get_pmuclk(priv, clk->id);
395 break;
396 case CLK_SPI0:
397 rate = rv1126_spi_get_pmuclk(priv);
398 break;
399 case PCLK_PDPMU:
400 rate = rv1126_pdpmu_get_pmuclk(priv);
401 break;
402 default:
403 debug("%s: Unsupported CLK#%ld\n", __func__, clk->id);
404 return -ENOENT;
405 }
406
407 return rate;
408}
409
410static ulong rv1126_pmuclk_set_rate(struct clk *clk, ulong rate)
411{
412 struct rv1126_pmuclk_priv *priv = dev_get_priv(clk->dev);
413 ulong ret = 0;
414
415 if (!priv->gpll_hz) {
416 printf("%s gpll=%lu\n", __func__, priv->gpll_hz);
417 return -ENOENT;
418 }
419
420 debug("%s %ld %ld\n", __func__, clk->id, rate);
421 switch (clk->id) {
422 case PLL_GPLL:
423 ret = rv1126_gpll_set_pmuclk(priv, rate);
424 break;
425 case CLK_RTC32K:
426 ret = rv1126_rtc32k_set_pmuclk(priv, rate);
427 break;
428 case CLK_I2C0:
429 case CLK_I2C2:
430 ret = rv1126_i2c_set_pmuclk(priv, clk->id, rate);
431 break;
432 case CLK_PWM0:
433 case CLK_PWM1:
434 ret = rv1126_pwm_set_pmuclk(priv, clk->id, rate);
435 break;
436 case CLK_SPI0:
437 ret = rv1126_spi_set_pmuclk(priv, rate);
438 break;
439 case PCLK_PDPMU:
440 ret = rv1126_pdpmu_set_pmuclk(priv, rate);
441 break;
442 default:
443 debug("%s: Unsupported CLK#%ld\n", __func__, clk->id);
444 return -ENOENT;
445 }
446
447 return ret;
448}
449
450static int rv1126_rtc32k_set_parent(struct clk *clk, struct clk *parent)
451{
452 struct rv1126_pmuclk_priv *priv = dev_get_priv(clk->dev);
453 struct rv1126_pmucru *pmucru = priv->pmucru;
454
455 if (parent->id == CLK_OSC0_DIV32K)
456 rk_clrsetreg(&pmucru->pmu_clksel_con[0], RTC32K_SEL_MASK,
457 RTC32K_SEL_OSC0_DIV32K << RTC32K_SEL_SHIFT);
458 else
459 rk_clrsetreg(&pmucru->pmu_clksel_con[0], RTC32K_SEL_MASK,
460 RTC32K_SEL_OSC1_32K << RTC32K_SEL_SHIFT);
461
462 return 0;
463}
464
465static int rv1126_pmuclk_set_parent(struct clk *clk, struct clk *parent)
466{
467 switch (clk->id) {
468 case CLK_RTC32K:
469 return rv1126_rtc32k_set_parent(clk, parent);
470 default:
471 debug("%s: Unsupported CLK#%ld\n", __func__, clk->id);
472 return -ENOENT;
473 }
474}
475
476static struct clk_ops rv1126_pmuclk_ops = {
477 .get_rate = rv1126_pmuclk_get_rate,
478 .set_rate = rv1126_pmuclk_set_rate,
479 .set_parent = rv1126_pmuclk_set_parent,
480};
481
482static int rv1126_pmuclk_probe(struct udevice *dev)
483{
484 struct rv1126_pmuclk_priv *priv = dev_get_priv(dev);
485
486 priv->gpll_hz = rv1126_gpll_get_pmuclk(priv);
487
488 return 0;
489}
490
491static int rv1126_pmuclk_of_to_plat(struct udevice *dev)
492{
493 struct rv1126_pmuclk_priv *priv = dev_get_priv(dev);
494
495 priv->pmucru = dev_read_addr_ptr(dev);
496
497 return 0;
498}
499
500static int rv1126_pmuclk_bind(struct udevice *dev)
501{
502#if CONFIG_IS_ENABLED(RESET_ROCKCHIP)
503 int ret;
504
505 ret = offsetof(struct rv1126_pmucru, pmu_softrst_con[0]);
506 ret = rockchip_reset_bind(dev, ret, 2);
507 if (ret)
Eugen Hristevf1798262023-04-11 10:17:56 +0300508 debug("Warning: software reset driver bind failed\n");
Jagan Teki674d1b92022-12-14 23:21:00 +0530509#endif
510 return 0;
511}
512
513static const struct udevice_id rv1126_pmuclk_ids[] = {
514 { .compatible = "rockchip,rv1126-pmucru" },
515 { }
516};
517
518U_BOOT_DRIVER(rockchip_rv1126_pmucru) = {
519 .name = "rockchip_rv1126_pmucru",
520 .id = UCLASS_CLK,
521 .of_match = rv1126_pmuclk_ids,
522 .priv_auto = sizeof(struct rv1126_pmuclk_priv),
523 .of_to_plat = rv1126_pmuclk_of_to_plat,
524 .ops = &rv1126_pmuclk_ops,
525 .bind = rv1126_pmuclk_bind,
526 .probe = rv1126_pmuclk_probe,
527};
528
529static int rv1126_armclk_set_clk(struct rv1126_clk_priv *priv, ulong hz)
530{
531 struct rv1126_cru *cru = priv->cru;
532 const struct rockchip_cpu_rate_table *rate;
533 ulong old_rate;
534
535 rate = rockchip_get_cpu_settings(rv1126_cpu_rates, hz);
536 if (!rate) {
537 printf("%s unsupported rate\n", __func__);
538 return -EINVAL;
539 }
540
541 /*
542 * set up dependent divisors for DBG and ACLK clocks.
543 */
544 old_rate = rockchip_pll_get_rate(&rv1126_pll_clks[APLL],
545 priv->cru, APLL);
546 if (old_rate > hz) {
547 if (rockchip_pll_set_rate(&rv1126_pll_clks[APLL],
548 priv->cru, APLL, hz))
549 return -EINVAL;
550 rk_clrsetreg(&cru->clksel_con[1],
551 CORE_DBG_DIV_MASK | CORE_ACLK_DIV_MASK,
552 rate->pclk_div << CORE_DBG_DIV_SHIFT |
553 rate->aclk_div << CORE_ACLK_DIV_SHIFT);
554 } else if (old_rate < hz) {
555 rk_clrsetreg(&cru->clksel_con[1],
556 CORE_DBG_DIV_MASK | CORE_ACLK_DIV_MASK,
557 rate->pclk_div << CORE_DBG_DIV_SHIFT |
558 rate->aclk_div << CORE_ACLK_DIV_SHIFT);
559 if (rockchip_pll_set_rate(&rv1126_pll_clks[APLL],
560 priv->cru, APLL, hz))
561 return -EINVAL;
562 }
563
564 return 0;
565}
566
567static ulong rv1126_pdcore_get_clk(struct rv1126_clk_priv *priv)
568{
569 struct rv1126_cru *cru = priv->cru;
570 u32 con, div;
571
572 con = readl(&cru->clksel_con[0]);
573 div = (con & CORE_HCLK_DIV_MASK) >> CORE_HCLK_DIV_SHIFT;
574
575 return DIV_TO_RATE(priv->gpll_hz, div);
576}
577
578static ulong rv1126_pdcore_set_clk(struct rv1126_clk_priv *priv, ulong rate)
579{
580 struct rv1126_cru *cru = priv->cru;
581 int src_clk_div;
582
583 src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
584 assert(src_clk_div - 1 <= 31);
585
586 rk_clrsetreg(&cru->clksel_con[0], CORE_HCLK_DIV_MASK,
587 (src_clk_div - 1) << CORE_HCLK_DIV_SHIFT);
588
589 return rv1126_pdcore_get_clk(priv);
590}
591
592static ulong rv1126_pdbus_get_clk(struct rv1126_clk_priv *priv, ulong clk_id)
593{
594 struct rv1126_cru *cru = priv->cru;
595 u32 con, div, sel, parent;
596
597 switch (clk_id) {
598 case ACLK_PDBUS:
599 con = readl(&cru->clksel_con[2]);
600 div = (con & ACLK_PDBUS_DIV_MASK) >> ACLK_PDBUS_DIV_SHIFT;
601 sel = (con & ACLK_PDBUS_SEL_MASK) >> ACLK_PDBUS_SEL_SHIFT;
602 if (sel == ACLK_PDBUS_SEL_GPLL)
603 parent = priv->gpll_hz;
604 else if (sel == ACLK_PDBUS_SEL_CPLL)
605 parent = priv->cpll_hz;
606 else
607 return -ENOENT;
608 break;
609 case HCLK_PDBUS:
610 con = readl(&cru->clksel_con[2]);
611 div = (con & HCLK_PDBUS_DIV_MASK) >> HCLK_PDBUS_DIV_SHIFT;
612 sel = (con & HCLK_PDBUS_SEL_MASK) >> HCLK_PDBUS_SEL_SHIFT;
613 if (sel == HCLK_PDBUS_SEL_GPLL)
614 parent = priv->gpll_hz;
615 else if (sel == HCLK_PDBUS_SEL_CPLL)
616 parent = priv->cpll_hz;
617 else
618 return -ENOENT;
619 break;
620 case PCLK_PDBUS:
621 case PCLK_WDT:
622 con = readl(&cru->clksel_con[3]);
623 div = (con & PCLK_PDBUS_DIV_MASK) >> PCLK_PDBUS_DIV_SHIFT;
624 sel = (con & PCLK_PDBUS_SEL_MASK) >> PCLK_PDBUS_SEL_SHIFT;
625 if (sel == PCLK_PDBUS_SEL_GPLL)
626 parent = priv->gpll_hz;
627 else if (sel == PCLK_PDBUS_SEL_CPLL)
628 parent = priv->cpll_hz;
629 else
630 return -ENOENT;
631 break;
632 default:
633 return -ENOENT;
634 }
635
636 return DIV_TO_RATE(parent, div);
637}
638
639static ulong rv1126_pdbus_set_clk(struct rv1126_clk_priv *priv, ulong clk_id,
640 ulong rate)
641{
642 struct rv1126_cru *cru = priv->cru;
643 int src_clk_div, clk_sel;
644
645 switch (clk_id) {
646 case ACLK_PDBUS:
647 if (CPLL_HZ % rate) {
648 src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
649 clk_sel = ACLK_PDBUS_SEL_GPLL;
650 } else {
651 src_clk_div = DIV_ROUND_UP(priv->cpll_hz, rate);
652 clk_sel = ACLK_PDBUS_SEL_CPLL;
653 }
654 assert(src_clk_div - 1 <= 31);
655 rk_clrsetreg(&cru->clksel_con[2],
656 ACLK_PDBUS_SEL_MASK | ACLK_PDBUS_DIV_MASK,
657 clk_sel << ACLK_PDBUS_SEL_SHIFT |
658 (src_clk_div - 1) << ACLK_PDBUS_DIV_SHIFT);
659 break;
660 case HCLK_PDBUS:
661 src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
662 assert(src_clk_div - 1 <= 31);
663 rk_clrsetreg(&cru->clksel_con[2],
664 HCLK_PDBUS_SEL_MASK | HCLK_PDBUS_DIV_MASK,
665 HCLK_PDBUS_SEL_GPLL << HCLK_PDBUS_SEL_SHIFT |
666 (src_clk_div - 1) << HCLK_PDBUS_DIV_SHIFT);
667 break;
668 case PCLK_PDBUS:
669 case PCLK_WDT:
670 src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
671 assert(src_clk_div - 1 <= 31);
672 rk_clrsetreg(&cru->clksel_con[3],
673 PCLK_PDBUS_SEL_MASK | PCLK_PDBUS_DIV_MASK,
674 PCLK_PDBUS_SEL_GPLL << PCLK_PDBUS_SEL_SHIFT |
675 (src_clk_div - 1) << PCLK_PDBUS_DIV_SHIFT);
676 break;
677
678 default:
679 printf("do not support this pdbus freq\n");
680 return -EINVAL;
681 }
682
683 return rv1126_pdbus_get_clk(priv, clk_id);
684}
685
686static ulong rv1126_pdphp_get_clk(struct rv1126_clk_priv *priv, ulong clk_id)
687{
688 struct rv1126_cru *cru = priv->cru;
689 u32 con, div, parent;
690
691 switch (clk_id) {
692 case ACLK_PDPHP:
693 con = readl(&cru->clksel_con[53]);
694 div = (con & ACLK_PDPHP_DIV_MASK) >> ACLK_PDPHP_DIV_SHIFT;
695 parent = priv->gpll_hz;
696 break;
697 case HCLK_PDPHP:
698 con = readl(&cru->clksel_con[53]);
699 div = (con & HCLK_PDPHP_DIV_MASK) >> HCLK_PDPHP_DIV_SHIFT;
700 parent = priv->gpll_hz;
701 break;
702 default:
703 return -ENOENT;
704 }
705
706 return DIV_TO_RATE(parent, div);
707}
708
709static ulong rv1126_pdphp_set_clk(struct rv1126_clk_priv *priv, ulong clk_id,
710 ulong rate)
711{
712 struct rv1126_cru *cru = priv->cru;
713 int src_clk_div;
714
715 src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
716 assert(src_clk_div - 1 <= 31);
717
718 switch (clk_id) {
719 case ACLK_PDPHP:
720 rk_clrsetreg(&cru->clksel_con[53],
721 ACLK_PDPHP_SEL_MASK | ACLK_PDPHP_DIV_MASK,
722 ACLK_PDPHP_SEL_GPLL << ACLK_PDPHP_SEL_SHIFT |
723 (src_clk_div - 1) << ACLK_PDPHP_DIV_SHIFT);
724 break;
725 case HCLK_PDPHP:
726 rk_clrsetreg(&cru->clksel_con[53],
727 HCLK_PDPHP_DIV_MASK,
728 (src_clk_div - 1) << HCLK_PDPHP_DIV_SHIFT);
729 break;
730 default:
731 printf("do not support this pdphp freq\n");
732 return -EINVAL;
733 }
734
735 return rv1126_pdphp_get_clk(priv, clk_id);
736}
737
738static ulong rv1126_pdaudio_get_clk(struct rv1126_clk_priv *priv)
739{
740 struct rv1126_cru *cru = priv->cru;
741 u32 con, div;
742
743 con = readl(&cru->clksel_con[26]);
744 div = (con & HCLK_PDAUDIO_DIV_MASK) >> HCLK_PDAUDIO_DIV_SHIFT;
745
746 return DIV_TO_RATE(priv->gpll_hz, div);
747}
748
749static ulong rv1126_pdaudio_set_clk(struct rv1126_clk_priv *priv, ulong rate)
750{
751 struct rv1126_cru *cru = priv->cru;
752 int src_clk_div;
753
754 src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
755 assert(src_clk_div - 1 <= 31);
756
757 rk_clrsetreg(&cru->clksel_con[26], HCLK_PDAUDIO_DIV_MASK,
758 (src_clk_div - 1) << HCLK_PDAUDIO_DIV_SHIFT);
759
760 return rv1126_pdaudio_get_clk(priv);
761}
762
763static ulong rv1126_i2c_get_clk(struct rv1126_clk_priv *priv, ulong clk_id)
764{
765 struct rv1126_cru *cru = priv->cru;
766 u32 div, con;
767
768 switch (clk_id) {
769 case CLK_I2C1:
770 con = readl(&cru->clksel_con[5]);
771 div = (con & CLK_I2C1_DIV_MASK) >> CLK_I2C1_DIV_SHIFT;
772 break;
773 case CLK_I2C3:
774 con = readl(&cru->clksel_con[5]);
775 div = (con & CLK_I2C3_DIV_MASK) >> CLK_I2C3_DIV_SHIFT;
776 break;
777 case CLK_I2C4:
778 con = readl(&cru->clksel_con[6]);
779 div = (con & CLK_I2C4_DIV_MASK) >> CLK_I2C4_DIV_SHIFT;
780 break;
781 case CLK_I2C5:
782 con = readl(&cru->clksel_con[6]);
783 div = (con & CLK_I2C5_DIV_MASK) >> CLK_I2C5_DIV_SHIFT;
784 break;
785 default:
786 return -ENOENT;
787 }
788
789 return DIV_TO_RATE(priv->gpll_hz, div);
790}
791
792static ulong rv1126_i2c_set_clk(struct rv1126_clk_priv *priv, ulong clk_id,
793 ulong rate)
794{
795 struct rv1126_cru *cru = priv->cru;
796 int src_clk_div;
797
798 src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
799 assert(src_clk_div - 1 <= 127);
800
801 switch (clk_id) {
802 case CLK_I2C1:
803 rk_clrsetreg(&cru->clksel_con[5], CLK_I2C1_DIV_MASK,
804 (src_clk_div - 1) << CLK_I2C1_DIV_SHIFT);
805 break;
806 case CLK_I2C3:
807 rk_clrsetreg(&cru->clksel_con[5], CLK_I2C3_DIV_MASK,
808 (src_clk_div - 1) << CLK_I2C3_DIV_SHIFT);
809 break;
810 case CLK_I2C4:
811 rk_clrsetreg(&cru->clksel_con[6], CLK_I2C4_DIV_MASK,
812 (src_clk_div - 1) << CLK_I2C4_DIV_SHIFT);
813 break;
814 case CLK_I2C5:
815 rk_clrsetreg(&cru->clksel_con[6], CLK_I2C5_DIV_MASK,
816 (src_clk_div - 1) << CLK_I2C5_DIV_SHIFT);
817 break;
818 default:
819 return -ENOENT;
820 }
821
822 return rv1126_i2c_get_clk(priv, clk_id);
823}
824
825static ulong rv1126_spi_get_clk(struct rv1126_clk_priv *priv)
826{
827 struct rv1126_cru *cru = priv->cru;
828 u32 div, con;
829
830 con = readl(&cru->clksel_con[8]);
831 div = (con & CLK_SPI1_DIV_MASK) >> CLK_SPI1_DIV_SHIFT;
832
833 return DIV_TO_RATE(priv->gpll_hz, div);
834}
835
836static ulong rv1126_spi_set_clk(struct rv1126_clk_priv *priv, ulong rate)
837{
838 struct rv1126_cru *cru = priv->cru;
839 int src_clk_div;
840
841 src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
842 assert(src_clk_div - 1 <= 127);
843
844 rk_clrsetreg(&cru->clksel_con[8],
845 CLK_SPI1_SEL_MASK | CLK_SPI1_DIV_MASK,
846 CLK_SPI1_SEL_GPLL << CLK_SPI1_SEL_SHIFT |
847 (src_clk_div - 1) << CLK_SPI1_DIV_SHIFT);
848
849 return rv1126_spi_get_clk(priv);
850}
851
852static ulong rv1126_pwm_get_clk(struct rv1126_clk_priv *priv)
853{
854 struct rv1126_cru *cru = priv->cru;
855 u32 div, sel, con;
856
857 con = readl(&cru->clksel_con[9]);
858 sel = (con & CLK_PWM2_SEL_MASK) >> CLK_PWM2_SEL_SHIFT;
859 div = (con & CLK_PWM2_DIV_MASK) >> CLK_PWM2_DIV_SHIFT;
860 if (sel == CLK_PWM2_SEL_XIN24M)
861 return OSC_HZ;
862
863 return DIV_TO_RATE(priv->gpll_hz, div);
864}
865
866static ulong rv1126_pwm_set_clk(struct rv1126_clk_priv *priv, ulong rate)
867{
868 struct rv1126_cru *cru = priv->cru;
869 int src_clk_div;
870
871 if (rate == OSC_HZ) {
872 rk_clrsetreg(&cru->clksel_con[9], CLK_PWM2_SEL_MASK,
873 CLK_PWM2_SEL_XIN24M << CLK_PWM2_SEL_SHIFT);
874 rk_clrsetreg(&cru->clksel_con[9], CLK_PWM2_DIV_MASK, 0);
875 } else {
876 src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
877 assert(src_clk_div - 1 <= 127);
878 rk_clrsetreg(&cru->clksel_con[9], CLK_PWM2_DIV_MASK,
879 (src_clk_div - 1) << CLK_PWM2_DIV_SHIFT);
880 rk_clrsetreg(&cru->clksel_con[9], CLK_PWM2_SEL_MASK,
881 CLK_PWM2_SEL_GPLL << CLK_PWM2_SEL_SHIFT);
882 }
883
884 return rv1126_pwm_get_clk(priv);
885}
886
887static ulong rv1126_saradc_get_clk(struct rv1126_clk_priv *priv)
888{
889 struct rv1126_cru *cru = priv->cru;
890 u32 div, con;
891
892 con = readl(&cru->clksel_con[20]);
893 div = (con & CLK_SARADC_DIV_MASK) >> CLK_SARADC_DIV_SHIFT;
894
895 return DIV_TO_RATE(OSC_HZ, div);
896}
897
898static ulong rv1126_saradc_set_clk(struct rv1126_clk_priv *priv, ulong rate)
899{
900 struct rv1126_cru *cru = priv->cru;
901 int src_clk_div;
902
903 src_clk_div = DIV_ROUND_UP(OSC_HZ, rate);
904 assert(src_clk_div - 1 <= 2047);
905 rk_clrsetreg(&cru->clksel_con[20], CLK_SARADC_DIV_MASK,
906 (src_clk_div - 1) << CLK_SARADC_DIV_SHIFT);
907
908 return rv1126_saradc_get_clk(priv);
909}
910
911static ulong rv1126_crypto_get_clk(struct rv1126_clk_priv *priv, ulong clk_id)
912{
913 struct rv1126_cru *cru = priv->cru;
914 u32 div, sel, con, parent;
915
916 switch (clk_id) {
917 case CLK_CRYPTO_CORE:
918 con = readl(&cru->clksel_con[7]);
919 div = (con & CLK_CRYPTO_CORE_DIV_MASK) >> CLK_CRYPTO_CORE_DIV_SHIFT;
920 sel = (con & CLK_CRYPTO_CORE_SEL_MASK) >> CLK_CRYPTO_CORE_SEL_SHIFT;
921 if (sel == CLK_CRYPTO_CORE_SEL_GPLL)
922 parent = priv->gpll_hz;
923 else if (sel == CLK_CRYPTO_CORE_SEL_CPLL)
924 parent = priv->cpll_hz;
925 else
926 return -ENOENT;
927 break;
928 case CLK_CRYPTO_PKA:
929 con = readl(&cru->clksel_con[7]);
930 div = (con & CLK_CRYPTO_PKA_DIV_MASK) >> CLK_CRYPTO_PKA_DIV_SHIFT;
931 sel = (con & CLK_CRYPTO_PKA_SEL_MASK) >> CLK_CRYPTO_PKA_SEL_SHIFT;
932 if (sel == CLK_CRYPTO_PKA_SEL_GPLL)
933 parent = priv->gpll_hz;
934 else if (sel == CLK_CRYPTO_PKA_SEL_CPLL)
935 parent = priv->cpll_hz;
936 else
937 return -ENOENT;
938 break;
939 case ACLK_CRYPTO:
940 con = readl(&cru->clksel_con[4]);
941 div = (con & ACLK_CRYPTO_DIV_MASK) >> ACLK_CRYPTO_DIV_SHIFT;
942 sel = (con & ACLK_CRYPTO_SEL_MASK) >> ACLK_CRYPTO_SEL_SHIFT;
943 if (sel == ACLK_CRYPTO_SEL_GPLL)
944 parent = priv->gpll_hz;
945 else if (sel == ACLK_CRYPTO_SEL_CPLL)
946 parent = priv->cpll_hz;
947 else
948 return -ENOENT;
949 break;
950 default:
951 return -ENOENT;
952 }
953
954 return DIV_TO_RATE(parent, div);
955}
956
957static ulong rv1126_crypto_set_clk(struct rv1126_clk_priv *priv, ulong clk_id,
958 ulong rate)
959{
960 struct rv1126_cru *cru = priv->cru;
961 int src_clk_div;
962
963 src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
964 assert(src_clk_div - 1 <= 31);
965
966 switch (clk_id) {
967 case CLK_CRYPTO_CORE:
968 rk_clrsetreg(&cru->clksel_con[7],
969 CLK_CRYPTO_CORE_SEL_MASK |
970 CLK_CRYPTO_CORE_DIV_MASK,
971 CLK_CRYPTO_CORE_SEL_GPLL <<
972 CLK_CRYPTO_CORE_SEL_SHIFT |
973 (src_clk_div - 1) << CLK_CRYPTO_CORE_DIV_SHIFT);
974 break;
975 case CLK_CRYPTO_PKA:
976 rk_clrsetreg(&cru->clksel_con[7],
977 CLK_CRYPTO_PKA_SEL_MASK |
978 CLK_CRYPTO_PKA_DIV_MASK,
979 CLK_CRYPTO_PKA_SEL_GPLL <<
980 CLK_CRYPTO_PKA_SEL_SHIFT |
981 (src_clk_div - 1) << CLK_CRYPTO_PKA_DIV_SHIFT);
982 break;
983 case ACLK_CRYPTO:
984 rk_clrsetreg(&cru->clksel_con[4],
985 ACLK_CRYPTO_SEL_MASK | ACLK_CRYPTO_DIV_MASK,
986 ACLK_CRYPTO_SEL_GPLL << ACLK_CRYPTO_SEL_SHIFT |
987 (src_clk_div - 1) << ACLK_CRYPTO_DIV_SHIFT);
988 break;
989 default:
990 return -ENOENT;
991 }
992
993 return rv1126_crypto_get_clk(priv, clk_id);
994}
995
996static ulong rv1126_mmc_get_clk(struct rv1126_clk_priv *priv, ulong clk_id)
997{
998 struct rv1126_cru *cru = priv->cru;
999 u32 div, sel, con, con_id;
1000
1001 switch (clk_id) {
1002 case HCLK_SDMMC:
1003 case CLK_SDMMC:
1004 con_id = 55;
1005 break;
1006 case HCLK_SDIO:
1007 case CLK_SDIO:
1008 con_id = 56;
1009 break;
1010 case HCLK_EMMC:
1011 case CLK_EMMC:
1012 case SCLK_EMMC_SAMPLE:
1013 con_id = 57;
1014 break;
1015 default:
1016 return -ENOENT;
1017 }
1018
1019 con = readl(&cru->clksel_con[con_id]);
1020 div = (con & EMMC_DIV_MASK) >> EMMC_DIV_SHIFT;
1021 sel = (con & EMMC_SEL_MASK) >> EMMC_SEL_SHIFT;
1022 if (sel == EMMC_SEL_GPLL)
1023 return DIV_TO_RATE(priv->gpll_hz, div) / 2;
1024 else if (sel == EMMC_SEL_CPLL)
1025 return DIV_TO_RATE(priv->cpll_hz, div) / 2;
1026 else if (sel == EMMC_SEL_XIN24M)
1027 return DIV_TO_RATE(OSC_HZ, div) / 2;
1028
1029 return -ENOENT;
1030}
1031
1032static ulong rv1126_mmc_set_clk(struct rv1126_clk_priv *priv, ulong clk_id,
1033 ulong rate)
1034{
1035 struct rv1126_cru *cru = priv->cru;
1036 int src_clk_div;
1037 u32 con_id;
1038
1039 switch (clk_id) {
1040 case HCLK_SDMMC:
1041 case CLK_SDMMC:
1042 con_id = 55;
1043 break;
1044 case HCLK_SDIO:
1045 case CLK_SDIO:
1046 con_id = 56;
1047 break;
1048 case HCLK_EMMC:
1049 case CLK_EMMC:
1050 con_id = 57;
1051 break;
1052 default:
1053 return -ENOENT;
1054 }
1055
1056 /* Select clk_sdmmc/emmc source from GPLL by default */
1057 /* mmc clock defaulg div 2 internal, need provide double in cru */
1058 src_clk_div = DIV_ROUND_UP(priv->gpll_hz / 2, rate);
1059
1060 if (src_clk_div > 127) {
1061 /* use 24MHz source for 400KHz clock */
1062 src_clk_div = DIV_ROUND_UP(OSC_HZ / 2, rate);
1063 rk_clrsetreg(&cru->clksel_con[con_id],
1064 EMMC_SEL_MASK | EMMC_DIV_MASK,
1065 EMMC_SEL_XIN24M << EMMC_SEL_SHIFT |
1066 (src_clk_div - 1) << EMMC_DIV_SHIFT);
1067 } else {
1068 rk_clrsetreg(&cru->clksel_con[con_id],
1069 EMMC_SEL_MASK | EMMC_DIV_MASK,
1070 EMMC_SEL_GPLL << EMMC_SEL_SHIFT |
1071 (src_clk_div - 1) << EMMC_DIV_SHIFT);
1072 }
1073
1074 return rv1126_mmc_get_clk(priv, clk_id);
1075}
1076
1077static ulong rv1126_sfc_get_clk(struct rv1126_clk_priv *priv)
1078{
1079 struct rv1126_cru *cru = priv->cru;
1080 u32 div, sel, con, parent;
1081
1082 con = readl(&cru->clksel_con[58]);
1083 div = (con & SCLK_SFC_DIV_MASK) >> SCLK_SFC_DIV_SHIFT;
1084 sel = (con & SCLK_SFC_SEL_MASK) >> SCLK_SFC_SEL_SHIFT;
1085 if (sel == SCLK_SFC_SEL_GPLL)
1086 parent = priv->gpll_hz;
1087 else if (sel == SCLK_SFC_SEL_CPLL)
1088 parent = priv->cpll_hz;
1089 else
1090 return -ENOENT;
1091
1092 return DIV_TO_RATE(parent, div);
1093}
1094
1095static ulong rv1126_sfc_set_clk(struct rv1126_clk_priv *priv, ulong rate)
1096{
1097 struct rv1126_cru *cru = priv->cru;
1098 int src_clk_div;
1099
1100 src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
1101 rk_clrsetreg(&cru->clksel_con[58],
1102 SCLK_SFC_SEL_MASK | SCLK_SFC_DIV_MASK,
1103 SCLK_SFC_SEL_GPLL << SCLK_SFC_SEL_SHIFT |
1104 (src_clk_div - 1) << SCLK_SFC_DIV_SHIFT);
1105
1106 return rv1126_sfc_get_clk(priv);
1107}
1108
1109static ulong rv1126_nand_get_clk(struct rv1126_clk_priv *priv)
1110{
1111 struct rv1126_cru *cru = priv->cru;
1112 u32 div, sel, con, parent;
1113
1114 con = readl(&cru->clksel_con[59]);
1115 div = (con & CLK_NANDC_DIV_MASK) >> CLK_NANDC_DIV_SHIFT;
1116 sel = (con & CLK_NANDC_SEL_MASK) >> CLK_NANDC_SEL_SHIFT;
1117 if (sel == CLK_NANDC_SEL_GPLL)
1118 parent = priv->gpll_hz;
1119 else if (sel == CLK_NANDC_SEL_CPLL)
1120 parent = priv->cpll_hz;
1121 else
1122 return -ENOENT;
1123
1124 return DIV_TO_RATE(parent, div);
1125}
1126
1127static ulong rv1126_nand_set_clk(struct rv1126_clk_priv *priv, ulong rate)
1128{
1129 struct rv1126_cru *cru = priv->cru;
1130 int src_clk_div;
1131
1132 src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
1133 rk_clrsetreg(&cru->clksel_con[59],
1134 CLK_NANDC_SEL_MASK | CLK_NANDC_DIV_MASK,
1135 CLK_NANDC_SEL_GPLL << CLK_NANDC_SEL_SHIFT |
1136 (src_clk_div - 1) << CLK_NANDC_DIV_SHIFT);
1137
1138 return rv1126_nand_get_clk(priv);
1139}
1140
1141static ulong rv1126_aclk_vop_get_clk(struct rv1126_clk_priv *priv)
1142{
1143 struct rv1126_cru *cru = priv->cru;
1144 u32 div, sel, con, parent;
1145
1146 con = readl(&cru->clksel_con[45]);
1147 div = (con & ACLK_PDVO_DIV_MASK) >> ACLK_PDVO_DIV_SHIFT;
1148 sel = (con & ACLK_PDVO_SEL_MASK) >> ACLK_PDVO_SEL_SHIFT;
1149 if (sel == ACLK_PDVO_SEL_GPLL)
1150 parent = priv->gpll_hz;
1151 else if (sel == ACLK_PDVO_SEL_CPLL)
1152 parent = priv->cpll_hz;
1153 else
1154 return -ENOENT;
1155
1156 return DIV_TO_RATE(parent, div);
1157}
1158
1159static ulong rv1126_aclk_vop_set_clk(struct rv1126_clk_priv *priv, ulong rate)
1160{
1161 struct rv1126_cru *cru = priv->cru;
1162 int src_clk_div;
1163
1164 src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
1165 assert(src_clk_div - 1 <= 31);
1166 rk_clrsetreg(&cru->clksel_con[45],
1167 ACLK_PDVO_SEL_MASK | ACLK_PDVO_DIV_MASK,
1168 ACLK_PDVO_SEL_GPLL << ACLK_PDVO_SEL_SHIFT |
1169 (src_clk_div - 1) << ACLK_PDVO_DIV_SHIFT);
1170
1171 return rv1126_aclk_vop_get_clk(priv);
1172}
1173
1174static ulong rv1126_dclk_vop_get_clk(struct rv1126_clk_priv *priv)
1175{
1176 struct rv1126_cru *cru = priv->cru;
1177 u32 div, sel, con, parent;
1178
1179 con = readl(&cru->clksel_con[47]);
1180 div = (con & DCLK_VOP_DIV_MASK) >> DCLK_VOP_DIV_SHIFT;
1181 sel = (con & DCLK_VOP_SEL_MASK) >> DCLK_VOP_SEL_SHIFT;
1182 if (sel == DCLK_VOP_SEL_GPLL)
1183 parent = priv->gpll_hz;
1184 else if (sel == DCLK_VOP_SEL_CPLL)
1185 parent = priv->cpll_hz;
1186 else
1187 return -ENOENT;
1188
1189 return DIV_TO_RATE(parent, div);
1190}
1191
1192static ulong rv1126_dclk_vop_set_clk(struct rv1126_clk_priv *priv, ulong rate)
1193{
1194 struct rv1126_cru *cru = priv->cru;
1195 ulong pll_rate, now, best_rate = 0;
1196 u32 i, div, best_div = 0, best_sel = 0;
1197
1198 for (i = 0; i <= DCLK_VOP_SEL_CPLL; i++) {
1199 switch (i) {
1200 case DCLK_VOP_SEL_GPLL:
1201 pll_rate = priv->gpll_hz;
1202 break;
1203 case DCLK_VOP_SEL_CPLL:
1204 pll_rate = priv->cpll_hz;
1205 break;
1206 default:
1207 printf("do not support this vop pll sel\n");
1208 return -EINVAL;
1209 }
1210
1211 div = DIV_ROUND_UP(pll_rate, rate);
1212 if (div > 255)
1213 continue;
1214 now = pll_rate / div;
1215 if (abs(rate - now) < abs(rate - best_rate)) {
1216 best_rate = now;
1217 best_div = div;
1218 best_sel = i;
1219 }
1220 debug("pll_rate=%lu, best_rate=%lu, best_div=%u, best_sel=%u\n",
1221 pll_rate, best_rate, best_div, best_sel);
1222 }
1223
1224 if (best_rate) {
1225 rk_clrsetreg(&cru->clksel_con[47],
1226 DCLK_VOP_SEL_MASK | DCLK_VOP_DIV_MASK,
1227 best_sel << DCLK_VOP_SEL_SHIFT |
1228 (best_div - 1) << DCLK_VOP_DIV_SHIFT);
1229 } else {
1230 printf("do not support this vop freq %lu\n", rate);
1231 return -EINVAL;
1232 }
1233
1234 return rv1126_dclk_vop_get_clk(priv);
1235}
1236
1237static ulong rv1126_scr1_get_clk(struct rv1126_clk_priv *priv)
1238{
1239 struct rv1126_cru *cru = priv->cru;
1240 u32 div, sel, con, parent;
1241
1242 con = readl(&cru->clksel_con[3]);
1243 div = (con & CLK_SCR1_DIV_MASK) >> CLK_SCR1_DIV_SHIFT;
1244 sel = (con & CLK_SCR1_SEL_MASK) >> CLK_SCR1_SEL_SHIFT;
1245 if (sel == CLK_SCR1_SEL_GPLL)
1246 parent = priv->gpll_hz;
1247 else if (sel == CLK_SCR1_SEL_CPLL)
1248 parent = priv->cpll_hz;
1249 else
1250 return -ENOENT;
1251
1252 return DIV_TO_RATE(parent, div);
1253}
1254
1255static ulong rv1126_scr1_set_clk(struct rv1126_clk_priv *priv, ulong rate)
1256{
1257 struct rv1126_cru *cru = priv->cru;
1258 int src_clk_div;
1259
1260 src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
1261 assert(src_clk_div - 1 <= 31);
1262 rk_clrsetreg(&cru->clksel_con[3],
1263 CLK_SCR1_SEL_MASK | CLK_SCR1_DIV_MASK,
1264 CLK_SCR1_SEL_GPLL << CLK_SCR1_SEL_SHIFT |
1265 (src_clk_div - 1) << CLK_SCR1_DIV_SHIFT);
1266
1267 return rv1126_scr1_get_clk(priv);
1268}
1269
1270static ulong rv1126_gmac_src_get_clk(struct rv1126_clk_priv *priv)
1271{
1272 struct rv1126_cru *cru = priv->cru;
1273 u32 div, sel, con, parent;
1274
1275 con = readl(&cru->clksel_con[63]);
1276 div = (con & CLK_GMAC_SRC_DIV_MASK) >> CLK_GMAC_SRC_DIV_SHIFT;
1277 sel = (con & CLK_GMAC_SRC_SEL_MASK) >> CLK_GMAC_SRC_SEL_SHIFT;
1278 if (sel == CLK_GMAC_SRC_SEL_CPLL)
1279 parent = priv->cpll_hz;
1280 else if (sel == CLK_GMAC_SRC_SEL_GPLL)
1281 parent = priv->gpll_hz;
1282 else
1283 return -ENOENT;
1284
1285 return DIV_TO_RATE(parent, div);
1286}
1287
1288static ulong rv1126_gmac_src_set_clk(struct rv1126_clk_priv *priv, ulong rate)
1289{
1290 struct rv1126_cru *cru = priv->cru;
1291 int src_clk_div;
1292
1293 src_clk_div = DIV_ROUND_UP(priv->cpll_hz, rate);
1294 assert(src_clk_div - 1 <= 31);
1295 rk_clrsetreg(&cru->clksel_con[63],
1296 CLK_GMAC_SRC_SEL_MASK | CLK_GMAC_SRC_DIV_MASK,
1297 CLK_GMAC_SRC_SEL_CPLL << CLK_GMAC_SRC_SEL_SHIFT |
1298 (src_clk_div - 1) << CLK_GMAC_SRC_DIV_SHIFT);
1299
1300 return rv1126_gmac_src_get_clk(priv);
1301}
1302
1303static ulong rv1126_gmac_out_get_clk(struct rv1126_clk_priv *priv)
1304{
1305 struct rv1126_cru *cru = priv->cru;
1306 u32 div, sel, con, parent;
1307
1308 con = readl(&cru->clksel_con[61]);
1309 div = (con & CLK_GMAC_OUT_DIV_MASK) >> CLK_GMAC_OUT_DIV_SHIFT;
1310 sel = (con & CLK_GMAC_OUT_SEL_MASK) >> CLK_GMAC_OUT_SEL_SHIFT;
1311 if (sel == CLK_GMAC_OUT_SEL_CPLL)
1312 parent = priv->cpll_hz;
1313 else if (sel == CLK_GMAC_OUT_SEL_GPLL)
1314 parent = priv->gpll_hz;
1315 else
1316 return -ENOENT;
1317
1318 return DIV_TO_RATE(parent, div);
1319}
1320
1321static ulong rv1126_gmac_out_set_clk(struct rv1126_clk_priv *priv, ulong rate)
1322{
1323 struct rv1126_cru *cru = priv->cru;
1324 int src_clk_div;
1325
1326 src_clk_div = DIV_ROUND_UP(priv->cpll_hz, rate);
1327 assert(src_clk_div - 1 <= 31);
1328 rk_clrsetreg(&cru->clksel_con[61],
1329 CLK_GMAC_OUT_SEL_MASK | CLK_GMAC_OUT_DIV_MASK,
1330 CLK_GMAC_OUT_SEL_CPLL << CLK_GMAC_OUT_SEL_SHIFT |
1331 (src_clk_div - 1) << CLK_GMAC_OUT_DIV_SHIFT);
1332
1333 return rv1126_gmac_out_get_clk(priv);
1334}
1335
1336static ulong rv1126_gmac_tx_rx_set_clk(struct rv1126_clk_priv *priv, ulong rate)
1337{
1338 struct rv1126_cru *cru = priv->cru;
1339 u32 con, sel, div_sel;
1340
1341 con = readl(&cru->gmac_con);
1342 sel = (con & GMAC_MODE_SEL_MASK) >> GMAC_MODE_SEL_SHIFT;
1343
1344 if (sel == GMAC_RGMII_MODE) {
1345 if (rate == 2500000)
1346 div_sel = RGMII_CLK_DIV50;
1347 else if (rate == 25000000)
1348 div_sel = RGMII_CLK_DIV5;
1349 else
1350 div_sel = RGMII_CLK_DIV0;
1351 rk_clrsetreg(&cru->gmac_con, RGMII_CLK_SEL_MASK,
1352 div_sel << RGMII_CLK_SEL_SHIFT);
1353 } else if (sel == GMAC_RMII_MODE) {
1354 if (rate == 2500000)
1355 div_sel = RMII_CLK_DIV20;
1356 else
1357 div_sel = RMII_CLK_DIV2;
1358 rk_clrsetreg(&cru->gmac_con, RMII_CLK_SEL_MASK,
1359 div_sel << RMII_CLK_SEL_SHIFT);
1360 }
1361
1362 return 0;
1363}
1364
1365static ulong rv1126_pclk_gmac_get_clk(struct rv1126_clk_priv *priv)
1366{
1367 struct rv1126_cru *cru = priv->cru;
1368 u32 div, con, parent;
1369
1370 parent = rv1126_pdphp_get_clk(priv, ACLK_PDPHP);
1371
1372 con = readl(&cru->clksel_con[63]);
1373 div = (con & PCLK_GMAC_DIV_MASK) >> PCLK_GMAC_DIV_SHIFT;
1374
1375 return DIV_TO_RATE(parent, div);
1376}
1377
1378static ulong rv1126_dclk_decom_get_clk(struct rv1126_clk_priv *priv)
1379{
1380 struct rv1126_cru *cru = priv->cru;
1381 u32 div, sel, con, parent;
1382
1383 con = readl(&cru->clksel_con[25]);
1384 div = (con & DCLK_DECOM_DIV_MASK) >> DCLK_DECOM_DIV_SHIFT;
1385 sel = (con & DCLK_DECOM_SEL_MASK) >> DCLK_DECOM_SEL_SHIFT;
1386 if (sel == DCLK_DECOM_SEL_GPLL)
1387 parent = priv->gpll_hz;
1388 else if (sel == DCLK_DECOM_SEL_CPLL)
1389 parent = priv->cpll_hz;
1390 else
1391 return -ENOENT;
1392
1393 return DIV_TO_RATE(parent, div);
1394}
1395
1396static ulong rv1126_dclk_decom_set_clk(struct rv1126_clk_priv *priv, ulong rate)
1397{
1398 struct rv1126_cru *cru = priv->cru;
1399 u32 src_clk_div;
1400
1401 src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
1402 assert(src_clk_div - 1 <= 127);
1403 rk_clrsetreg(&cru->clksel_con[25],
1404 DCLK_DECOM_SEL_MASK | DCLK_DECOM_DIV_MASK,
1405 DCLK_DECOM_SEL_GPLL << DCLK_DECOM_SEL_SHIFT |
1406 (src_clk_div - 1) << DCLK_DECOM_DIV_SHIFT);
1407
1408 return rv1126_dclk_decom_get_clk(priv);
1409}
1410
1411static ulong rv1126_clk_get_rate(struct clk *clk)
1412{
1413 struct rv1126_clk_priv *priv = dev_get_priv(clk->dev);
1414 ulong rate = 0;
1415
1416 if (!priv->gpll_hz) {
1417 printf("%s gpll=%lu\n", __func__, priv->gpll_hz);
1418 return -ENOENT;
1419 }
1420
1421 switch (clk->id) {
1422 case PLL_APLL:
1423 case ARMCLK:
1424 rate = rockchip_pll_get_rate(&rv1126_pll_clks[APLL], priv->cru,
1425 APLL);
1426 break;
1427 case PLL_CPLL:
1428 rate = rockchip_pll_get_rate(&rv1126_pll_clks[CPLL], priv->cru,
1429 CPLL);
1430 break;
1431 case PLL_HPLL:
1432 rate = rockchip_pll_get_rate(&rv1126_pll_clks[HPLL], priv->cru,
1433 HPLL);
1434 break;
1435 case PLL_DPLL:
1436 rate = rockchip_pll_get_rate(&rv1126_pll_clks[DPLL], priv->cru,
1437 DPLL);
1438 break;
1439 case HCLK_PDCORE_NIU:
1440 rate = rv1126_pdcore_get_clk(priv);
1441 break;
1442 case ACLK_PDBUS:
1443 case HCLK_PDBUS:
1444 case PCLK_PDBUS:
1445 case PCLK_WDT:
1446 rate = rv1126_pdbus_get_clk(priv, clk->id);
1447 break;
1448 case ACLK_PDPHP:
1449 case HCLK_PDPHP:
1450 rate = rv1126_pdphp_get_clk(priv, clk->id);
1451 break;
1452 case HCLK_PDAUDIO:
1453 rate = rv1126_pdaudio_get_clk(priv);
1454 break;
1455 case CLK_I2C1:
1456 case CLK_I2C3:
1457 case CLK_I2C4:
1458 case CLK_I2C5:
1459 rate = rv1126_i2c_get_clk(priv, clk->id);
1460 break;
1461 case CLK_SPI1:
1462 rate = rv1126_spi_get_clk(priv);
1463 break;
1464 case CLK_PWM2:
1465 rate = rv1126_pwm_get_clk(priv);
1466 break;
1467 case CLK_SARADC:
1468 rate = rv1126_saradc_get_clk(priv);
1469 break;
1470 case CLK_CRYPTO_CORE:
1471 case CLK_CRYPTO_PKA:
1472 case ACLK_CRYPTO:
1473 rate = rv1126_crypto_get_clk(priv, clk->id);
1474 break;
1475 case CLK_SDMMC:
1476 case HCLK_SDMMC:
1477 case CLK_SDIO:
1478 case HCLK_SDIO:
1479 case CLK_EMMC:
1480 case HCLK_EMMC:
1481 case SCLK_EMMC_SAMPLE:
1482 rate = rv1126_mmc_get_clk(priv, clk->id);
1483 break;
1484 case SCLK_SFC:
1485 rate = rv1126_sfc_get_clk(priv);
1486 break;
1487 case CLK_NANDC:
1488 rate = rv1126_nand_get_clk(priv);
1489 break;
1490 case ACLK_PDVO:
1491 case ACLK_VOP:
1492 rate = rv1126_aclk_vop_get_clk(priv);
1493 break;
1494 case DCLK_VOP:
1495 rate = rv1126_dclk_vop_get_clk(priv);
1496 break;
1497 case CLK_SCR1_CORE:
1498 rate = rv1126_scr1_get_clk(priv);
1499 break;
1500 case CLK_GMAC_SRC:
1501 rate = rv1126_gmac_src_get_clk(priv);
1502 break;
1503 case CLK_GMAC_ETHERNET_OUT:
1504 rate = rv1126_gmac_out_get_clk(priv);
1505 break;
1506 case PCLK_GMAC:
1507 rate = rv1126_pclk_gmac_get_clk(priv);
1508 break;
1509 case DCLK_DECOM:
1510 rate = rv1126_dclk_decom_get_clk(priv);
1511 break;
1512 default:
1513 debug("%s: Unsupported CLK#%ld\n", __func__, clk->id);
1514 return -ENOENT;
1515 }
1516
1517 return rate;
1518};
1519
1520static ulong rv1126_clk_set_rate(struct clk *clk, ulong rate)
1521{
1522 struct rv1126_clk_priv *priv = dev_get_priv(clk->dev);
1523 ulong ret = 0;
1524
1525 if (!priv->gpll_hz) {
1526 printf("%s gpll=%lu\n", __func__, priv->gpll_hz);
1527 return -ENOENT;
1528 }
1529
1530 switch (clk->id) {
1531 case PLL_APLL:
1532 case ARMCLK:
1533 if (priv->armclk_hz)
1534 rv1126_armclk_set_clk(priv, rate);
1535 priv->armclk_hz = rate;
1536 break;
1537 case PLL_CPLL:
1538 ret = rockchip_pll_set_rate(&rv1126_pll_clks[CPLL], priv->cru,
1539 CPLL, rate);
1540 break;
1541 case PLL_HPLL:
1542 ret = rockchip_pll_set_rate(&rv1126_pll_clks[HPLL], priv->cru,
1543 HPLL, rate);
1544 break;
1545 case ACLK_PDBUS:
1546 case HCLK_PDBUS:
1547 case PCLK_PDBUS:
1548 case PCLK_WDT:
1549 ret = rv1126_pdbus_set_clk(priv, clk->id, rate);
1550 break;
1551 case ACLK_PDPHP:
1552 case HCLK_PDPHP:
1553 ret = rv1126_pdphp_set_clk(priv, clk->id, rate);
1554 break;
1555 case HCLK_PDCORE_NIU:
1556 ret = rv1126_pdcore_set_clk(priv, rate);
1557 break;
1558 case HCLK_PDAUDIO:
1559 ret = rv1126_pdaudio_set_clk(priv, rate);
1560 break;
1561 case CLK_I2C1:
1562 case CLK_I2C3:
1563 case CLK_I2C4:
1564 case CLK_I2C5:
1565 ret = rv1126_i2c_set_clk(priv, clk->id, rate);
1566 break;
1567 case CLK_SPI1:
1568 ret = rv1126_spi_set_clk(priv, rate);
1569 break;
1570 case CLK_PWM2:
1571 ret = rv1126_pwm_set_clk(priv, rate);
1572 break;
1573 case CLK_SARADC:
1574 ret = rv1126_saradc_set_clk(priv, rate);
1575 break;
1576 case CLK_CRYPTO_CORE:
1577 case CLK_CRYPTO_PKA:
1578 case ACLK_CRYPTO:
1579 ret = rv1126_crypto_set_clk(priv, clk->id, rate);
1580 break;
1581 case CLK_SDMMC:
1582 case HCLK_SDMMC:
1583 case CLK_SDIO:
1584 case HCLK_SDIO:
1585 case CLK_EMMC:
1586 case HCLK_EMMC:
1587 ret = rv1126_mmc_set_clk(priv, clk->id, rate);
1588 break;
1589 case SCLK_SFC:
1590 ret = rv1126_sfc_set_clk(priv, rate);
1591 break;
1592 case CLK_NANDC:
1593 ret = rv1126_nand_set_clk(priv, rate);
1594 break;
1595 case ACLK_PDVO:
1596 case ACLK_VOP:
1597 ret = rv1126_aclk_vop_set_clk(priv, rate);
1598 break;
1599 case DCLK_VOP:
1600 ret = rv1126_dclk_vop_set_clk(priv, rate);
1601 break;
1602 case CLK_SCR1_CORE:
1603 ret = rv1126_scr1_set_clk(priv, rate);
1604 break;
1605 case CLK_GMAC_SRC:
1606 ret = rv1126_gmac_src_set_clk(priv, rate);
1607 break;
1608 case CLK_GMAC_ETHERNET_OUT:
1609 ret = rv1126_gmac_out_set_clk(priv, rate);
1610 break;
1611 case CLK_GMAC_TX_RX:
1612 ret = rv1126_gmac_tx_rx_set_clk(priv, rate);
1613 break;
1614 case DCLK_DECOM:
1615 ret = rv1126_dclk_decom_set_clk(priv, rate);
1616 break;
1617 default:
1618 debug("%s: Unsupported CLK#%ld\n", __func__, clk->id);
1619 return -ENOENT;
1620 }
1621
1622 return ret;
1623};
1624
1625#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
1626static int rv1126_gmac_src_set_parent(struct clk *clk, struct clk *parent)
1627{
1628 struct rv1126_clk_priv *priv = dev_get_priv(clk->dev);
1629 struct rv1126_grf *grf = priv->grf;
1630
1631 if (parent->id == CLK_GMAC_SRC_M0)
1632 rk_clrsetreg(&grf->iofunc_con1, GMAC_SRC_SEL_MASK,
1633 GMAC_SRC_SEL_M0 << GMAC_SRC_SEL_SHIFT);
1634 else if (parent->id == CLK_GMAC_SRC_M1)
1635 rk_clrsetreg(&grf->iofunc_con1, GMAC_SRC_SEL_MASK,
1636 GMAC_SRC_SEL_M1 << GMAC_SRC_SEL_SHIFT);
1637
1638 return 0;
1639}
1640
1641static int rv1126_gmac_src_m0_set_parent(struct clk *clk, struct clk *parent)
1642{
1643 struct rv1126_clk_priv *priv = dev_get_priv(clk->dev);
1644 struct rv1126_cru *cru = priv->cru;
1645
1646 if (parent->id == CLK_GMAC_DIV)
1647 rk_clrsetreg(&cru->gmac_con, GMAC_SRC_M0_SEL_MASK,
1648 GMAC_SRC_M0_SEL_INT << GMAC_SRC_M0_SEL_SHIFT);
1649 else
1650 rk_clrsetreg(&cru->gmac_con, GMAC_SRC_M0_SEL_MASK,
1651 GMAC_SRC_M0_SEL_EXT << GMAC_SRC_M0_SEL_SHIFT);
1652
1653 return 0;
1654}
1655
1656static int rv1126_gmac_src_m1_set_parent(struct clk *clk, struct clk *parent)
1657{
1658 struct rv1126_clk_priv *priv = dev_get_priv(clk->dev);
1659 struct rv1126_cru *cru = priv->cru;
1660
1661 if (parent->id == CLK_GMAC_DIV)
1662 rk_clrsetreg(&cru->gmac_con, GMAC_SRC_M1_SEL_MASK,
1663 GMAC_SRC_M1_SEL_INT << GMAC_SRC_M1_SEL_SHIFT);
1664 else
1665 rk_clrsetreg(&cru->gmac_con, GMAC_SRC_M1_SEL_MASK,
1666 GMAC_SRC_M1_SEL_EXT << GMAC_SRC_M1_SEL_SHIFT);
1667
1668 return 0;
1669}
1670
1671static int rv1126_gmac_tx_rx_set_parent(struct clk *clk, struct clk *parent)
1672{
1673 struct rv1126_clk_priv *priv = dev_get_priv(clk->dev);
1674 struct rv1126_cru *cru = priv->cru;
1675
1676 if (parent->id == RGMII_MODE_CLK)
1677 rk_clrsetreg(&cru->gmac_con, GMAC_MODE_SEL_MASK,
1678 GMAC_RGMII_MODE << GMAC_MODE_SEL_SHIFT);
1679 else
1680 rk_clrsetreg(&cru->gmac_con, GMAC_MODE_SEL_MASK,
1681 GMAC_RMII_MODE << GMAC_MODE_SEL_SHIFT);
1682
1683 return 0;
1684}
1685
1686static int rv1126_clk_set_parent(struct clk *clk, struct clk *parent)
1687{
1688 switch (clk->id) {
1689 case CLK_GMAC_SRC:
1690 return rv1126_gmac_src_set_parent(clk, parent);
1691 case CLK_GMAC_SRC_M0:
1692 return rv1126_gmac_src_m0_set_parent(clk, parent);
1693 case CLK_GMAC_SRC_M1:
1694 return rv1126_gmac_src_m1_set_parent(clk, parent);
1695 case CLK_GMAC_TX_RX:
1696 return rv1126_gmac_tx_rx_set_parent(clk, parent);
1697 default:
1698 return -ENOENT;
1699 }
1700
1701 return 0;
1702}
1703#endif
1704
1705static struct clk_ops rv1126_clk_ops = {
1706 .get_rate = rv1126_clk_get_rate,
1707 .set_rate = rv1126_clk_set_rate,
1708#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
1709 .set_parent = rv1126_clk_set_parent,
1710#endif
1711};
1712
1713static ulong rv1126_gpll_set_rate(struct rv1126_clk_priv *priv,
1714 struct rv1126_pmuclk_priv *pmu_priv,
1715 ulong rate)
1716{
1717 ulong emmc_rate, sfc_rate, nandc_rate;
1718 bool restore = false;
1719
1720 if (priv->gpll_hz != OSC_HZ) {
1721 emmc_rate = rv1126_mmc_get_clk(priv, CLK_EMMC);
1722 sfc_rate = rv1126_sfc_get_clk(priv);
1723 nandc_rate = rv1126_nand_get_clk(priv);
1724 debug("%s emmc=%lu, sfc=%lu, nandc=%lu\n", __func__,
1725 emmc_rate, sfc_rate, nandc_rate);
1726 restore = true;
1727 }
1728
1729 /*
1730 * the child div is big enough for gpll 1188MHz,
1731 * even maskrom has change some clocks.
1732 */
1733 if (rockchip_pll_set_rate(&rv1126_pll_clks[GPLL],
1734 pmu_priv->pmucru, GPLL, rate))
1735 return -EINVAL;
1736 pmu_priv->gpll_hz = rate;
1737 priv->gpll_hz = rate;
1738
1739 if (restore) {
1740 rv1126_mmc_set_clk(priv, CLK_EMMC, emmc_rate);
1741 rv1126_sfc_set_clk(priv, sfc_rate);
1742 rv1126_nand_set_clk(priv, nandc_rate);
1743 }
1744
1745 return 0;
1746}
1747
1748static int rv1126_gpll_set_clk(struct rv1126_clk_priv *priv, ulong rate)
1749{
1750 struct udevice *pmucru_dev;
1751 struct rv1126_pmuclk_priv *pmu_priv;
1752 int ret;
1753
1754 ret = uclass_get_device_by_driver(UCLASS_CLK,
1755 DM_DRIVER_GET(rockchip_rv1126_pmucru),
1756 &pmucru_dev);
1757 if (ret) {
1758 printf("%s: could not find pmucru device\n", __func__);
1759 return ret;
1760 }
1761 pmu_priv = dev_get_priv(pmucru_dev);
1762 priv->gpll_hz = pmu_priv->gpll_hz;
1763
1764 if (rv1126_gpll_set_rate(priv, pmu_priv, rate)) {
1765 printf("%s: failed to set gpll rate %lu\n", __func__, rate);
1766 return -EINVAL;
1767 }
1768
1769 rv1126_pdpmu_set_pmuclk(pmu_priv, PCLK_PDPMU_HZ);
1770 rv1126_rtc32k_set_pmuclk(pmu_priv, CLK_OSC0_DIV_HZ);
1771
1772 return 0;
1773}
1774
1775static void rv1126_clk_init(struct rv1126_clk_priv *priv)
1776{
1777 int ret;
1778
1779 priv->sync_kernel = false;
1780 if (!priv->armclk_enter_hz) {
1781 priv->armclk_enter_hz =
1782 rockchip_pll_get_rate(&rv1126_pll_clks[APLL],
1783 priv->cru, APLL);
1784 priv->armclk_init_hz = priv->armclk_enter_hz;
1785 }
1786
1787 if (priv->armclk_init_hz != APLL_HZ) {
1788 ret = rv1126_armclk_set_clk(priv, APLL_HZ);
1789 if (!ret)
1790 priv->armclk_init_hz = APLL_HZ;
1791 }
1792 if (priv->cpll_hz != CPLL_HZ) {
1793 ret = rockchip_pll_set_rate(&rv1126_pll_clks[CPLL], priv->cru,
1794 CPLL, CPLL_HZ);
1795 if (!ret)
1796 priv->cpll_hz = CPLL_HZ;
1797 }
1798 if (priv->hpll_hz != HPLL_HZ) {
1799 ret = rockchip_pll_set_rate(&rv1126_pll_clks[HPLL], priv->cru,
1800 HPLL, HPLL_HZ);
1801 if (!ret)
1802 priv->hpll_hz = HPLL_HZ;
1803 }
1804 if (priv->gpll_hz != GPLL_HZ)
1805 rv1126_gpll_set_clk(priv, GPLL_HZ);
1806
1807 rv1126_pdbus_set_clk(priv, ACLK_PDBUS, ACLK_PDBUS_HZ);
1808 rv1126_pdbus_set_clk(priv, HCLK_PDBUS, HCLK_PDBUS_HZ);
1809 rv1126_pdbus_set_clk(priv, PCLK_PDBUS, PCLK_PDBUS_HZ);
1810 rv1126_pdphp_set_clk(priv, ACLK_PDPHP, ACLK_PDPHP_HZ);
1811 rv1126_pdphp_set_clk(priv, HCLK_PDPHP, HCLK_PDPHP_HZ);
1812 rv1126_pdcore_set_clk(priv, HCLK_PDCORE_HZ);
1813 rv1126_pdaudio_set_clk(priv, HCLK_PDAUDIO_HZ);
1814}
1815
1816static int rv1126_clk_probe(struct udevice *dev)
1817{
1818 struct rv1126_clk_priv *priv = dev_get_priv(dev);
1819 int ret;
1820
1821 priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
1822 if (IS_ERR(priv->grf))
1823 return PTR_ERR(priv->grf);
1824
1825 rv1126_clk_init(priv);
1826
1827 /* Process 'assigned-{clocks/clock-parents/clock-rates}' properties */
1828 ret = clk_set_defaults(dev, 1);
1829 if (ret)
1830 debug("%s clk_set_defaults failed %d\n", __func__, ret);
1831 else
1832 priv->sync_kernel = true;
1833
1834 return 0;
1835}
1836
1837static int rv1126_clk_of_to_plat(struct udevice *dev)
1838{
1839 struct rv1126_clk_priv *priv = dev_get_priv(dev);
1840
1841 priv->cru = dev_read_addr_ptr(dev);
1842
1843 return 0;
1844}
1845
1846static int rv1126_clk_bind(struct udevice *dev)
1847{
1848 int ret;
1849 struct udevice *sys_child;
1850 struct sysreset_reg *priv;
1851
1852 /* The reset driver does not have a device node, so bind it here */
1853 ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset",
1854 &sys_child);
1855 if (ret) {
1856 debug("Warning: No sysreset driver: ret=%d\n", ret);
1857 } else {
1858 priv = malloc(sizeof(struct sysreset_reg));
1859 priv->glb_srst_fst_value = offsetof(struct rv1126_cru,
1860 glb_srst_fst);
1861 priv->glb_srst_snd_value = offsetof(struct rv1126_cru,
1862 glb_srst_snd);
1863 dev_set_priv(sys_child, priv);
1864 }
1865
1866#if CONFIG_IS_ENABLED(RESET_ROCKCHIP)
1867 ret = offsetof(struct rv1126_cru, softrst_con[0]);
1868 ret = rockchip_reset_bind(dev, ret, 15);
1869 if (ret)
Eugen Hristevf1798262023-04-11 10:17:56 +03001870 debug("Warning: software reset driver bind failed\n");
Jagan Teki674d1b92022-12-14 23:21:00 +05301871#endif
1872 return 0;
1873}
1874
1875static const struct udevice_id rv1126_clk_ids[] = {
1876 { .compatible = "rockchip,rv1126-cru" },
1877 { }
1878};
1879
1880U_BOOT_DRIVER(rockchip_rv1126_cru) = {
1881 .name = "rockchip_rv1126_cru",
1882 .id = UCLASS_CLK,
1883 .of_match = rv1126_clk_ids,
1884 .priv_auto = sizeof(struct rv1126_clk_priv),
1885 .of_to_plat = rv1126_clk_of_to_plat,
1886 .ops = &rv1126_clk_ops,
1887 .bind = rv1126_clk_bind,
1888 .probe = rv1126_clk_probe,
1889};