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