blob: 99c195b3afe3d6edabe97b2f157f54dd6c1dc36e [file] [log] [blame]
Elaine Zhang4a262fe2021-06-02 11:39:24 +08001// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (c) 2021 Rockchip Electronics Co., Ltd
4 * Author: Elaine Zhang <zhangqing@rock-chips.com>
5 */
6
7#include <common.h>
8#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/cru_rk3568.h>
14#include <asm/arch-rockchip/clock.h>
15#include <asm/arch-rockchip/hardware.h>
16#include <asm/io.h>
17#include <dm/lists.h>
18#include <dt-bindings/clock/rk3568-cru.h>
19
20DECLARE_GLOBAL_DATA_PTR;
21
22#if CONFIG_IS_ENABLED(OF_PLATDATA)
23struct rk3568_clk_plat {
24 struct dtd_rockchip_rk3568_cru dtd;
25};
26
27struct rk3568_pmuclk_plat {
28 struct dtd_rockchip_rk3568_pmucru dtd;
29};
30#endif
31
32#define RK3568_CPUCLK_RATE(_rate, _aclk_div, _pclk_div) \
33{ \
34 .rate = _rate##U, \
35 .aclk_div = _aclk_div, \
36 .pclk_div = _pclk_div, \
37}
38
39#define DIV_TO_RATE(input_rate, div) ((input_rate) / ((div) + 1))
40
41static struct rockchip_cpu_rate_table rk3568_cpu_rates[] = {
42 RK3568_CPUCLK_RATE(1416000000, 1, 5),
43 RK3568_CPUCLK_RATE(1296000000, 1, 5),
44 RK3568_CPUCLK_RATE(1200000000, 1, 3),
45 RK3568_CPUCLK_RATE(1104000000, 1, 3),
46 RK3568_CPUCLK_RATE(1008000000, 1, 3),
47 RK3568_CPUCLK_RATE(912000000, 1, 3),
48 RK3568_CPUCLK_RATE(816000000, 1, 3),
49 RK3568_CPUCLK_RATE(600000000, 1, 1),
50 RK3568_CPUCLK_RATE(408000000, 1, 1),
51 { /* sentinel */ },
52};
53
54static struct rockchip_pll_rate_table rk3568_pll_rates[] = {
55 /* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */
56 RK3036_PLL_RATE(1608000000, 1, 67, 1, 1, 1, 0),
57 RK3036_PLL_RATE(1416000000, 1, 118, 2, 1, 1, 0),
58 RK3036_PLL_RATE(1296000000, 1, 108, 2, 1, 1, 0),
59 RK3036_PLL_RATE(1200000000, 1, 100, 2, 1, 1, 0),
60 RK3036_PLL_RATE(1188000000, 1, 99, 2, 1, 1, 0),
61 RK3036_PLL_RATE(1104000000, 1, 92, 2, 1, 1, 0),
62 RK3036_PLL_RATE(1008000000, 1, 84, 2, 1, 1, 0),
63 RK3036_PLL_RATE(1000000000, 3, 250, 2, 1, 1, 0),
64 RK3036_PLL_RATE(912000000, 1, 76, 2, 1, 1, 0),
65 RK3036_PLL_RATE(816000000, 1, 68, 2, 1, 1, 0),
66 RK3036_PLL_RATE(600000000, 1, 100, 4, 1, 1, 0),
67 RK3036_PLL_RATE(594000000, 1, 99, 4, 1, 1, 0),
68 RK3036_PLL_RATE(500000000, 1, 125, 6, 1, 1, 0),
69 RK3036_PLL_RATE(408000000, 1, 68, 2, 2, 1, 0),
70 RK3036_PLL_RATE(400000000, 1, 100, 6, 1, 1, 0),
71 RK3036_PLL_RATE(200000000, 1, 100, 6, 2, 1, 0),
72 RK3036_PLL_RATE(100000000, 1, 150, 6, 6, 1, 0),
73 { /* sentinel */ },
74};
75
76static struct rockchip_pll_clock rk3568_pll_clks[] = {
77 [APLL] = PLL(pll_rk3328, PLL_APLL, RK3568_PLL_CON(0),
78 RK3568_MODE_CON, 0, 10, 0, rk3568_pll_rates),
79 [DPLL] = PLL(pll_rk3328, PLL_DPLL, RK3568_PLL_CON(8),
80 RK3568_MODE_CON, 2, 10, 0, NULL),
81 [CPLL] = PLL(pll_rk3328, PLL_CPLL, RK3568_PLL_CON(24),
82 RK3568_MODE_CON, 4, 10, 0, rk3568_pll_rates),
83 [GPLL] = PLL(pll_rk3328, PLL_HPLL, RK3568_PLL_CON(16),
84 RK3568_MODE_CON, 6, 10, 0, rk3568_pll_rates),
85 [NPLL] = PLL(pll_rk3328, PLL_NPLL, RK3568_PLL_CON(32),
86 RK3568_MODE_CON, 10, 10, 0, rk3568_pll_rates),
87 [VPLL] = PLL(pll_rk3328, PLL_VPLL, RK3568_PLL_CON(40),
88 RK3568_MODE_CON, 12, 10, 0, rk3568_pll_rates),
89 [PPLL] = PLL(pll_rk3328, PLL_PPLL, RK3568_PMU_PLL_CON(0),
90 RK3568_PMU_MODE, 0, 10, 0, rk3568_pll_rates),
91 [HPLL] = PLL(pll_rk3328, PLL_HPLL, RK3568_PMU_PLL_CON(16),
92 RK3568_PMU_MODE, 2, 10, 0, rk3568_pll_rates),
93};
94
95#ifndef CONFIG_SPL_BUILD
96static ulong
97rk3568_pmu_pll_set_rate(struct rk3568_clk_priv *priv,
98 ulong pll_id, ulong rate)
99{
100 struct udevice *pmucru_dev;
101 struct rk3568_pmuclk_priv *pmu_priv;
102 int ret;
103
104 ret = uclass_get_device_by_driver(UCLASS_CLK,
105 DM_DRIVER_GET(rockchip_rk3568_pmucru),
106 &pmucru_dev);
107 if (ret) {
108 printf("%s: could not find pmucru device\n", __func__);
109 return ret;
110 }
111 pmu_priv = dev_get_priv(pmucru_dev);
112
113 rockchip_pll_set_rate(&rk3568_pll_clks[pll_id],
114 pmu_priv->pmucru, pll_id, rate);
115
116 return 0;
117}
118#endif
119
120static ulong rk3568_pmu_pll_get_rate(struct rk3568_clk_priv *priv,
121 ulong pll_id)
122{
123 struct udevice *pmucru_dev;
124 struct rk3568_pmuclk_priv *pmu_priv;
125 int ret;
126
127 ret = uclass_get_device_by_driver(UCLASS_CLK,
128 DM_DRIVER_GET(rockchip_rk3568_pmucru),
129 &pmucru_dev);
130 if (ret) {
131 printf("%s: could not find pmucru device\n", __func__);
132 return ret;
133 }
134 pmu_priv = dev_get_priv(pmucru_dev);
135
136 return rockchip_pll_get_rate(&rk3568_pll_clks[pll_id],
137 pmu_priv->pmucru, pll_id);
138}
139
140/*
141 *
142 * rational_best_approximation(31415, 10000,
143 * (1 << 8) - 1, (1 << 5) - 1, &n, &d);
144 *
145 * you may look at given_numerator as a fixed point number,
146 * with the fractional part size described in given_denominator.
147 *
148 * for theoretical background, see:
149 * http://en.wikipedia.org/wiki/Continued_fraction
150 */
151static void rational_best_approximation(unsigned long given_numerator,
152 unsigned long given_denominator,
153 unsigned long max_numerator,
154 unsigned long max_denominator,
155 unsigned long *best_numerator,
156 unsigned long *best_denominator)
157{
158 unsigned long n, d, n0, d0, n1, d1;
159
160 n = given_numerator;
161 d = given_denominator;
162 n0 = 0;
163 d1 = 0;
164 n1 = 1;
165 d0 = 1;
166 for (;;) {
167 unsigned long t, a;
168
169 if (n1 > max_numerator || d1 > max_denominator) {
170 n1 = n0;
171 d1 = d0;
172 break;
173 }
174 if (d == 0)
175 break;
176 t = d;
177 a = n / d;
178 d = n % d;
179 n = t;
180 t = n0 + a * n1;
181 n0 = n1;
182 n1 = t;
183 t = d0 + a * d1;
184 d0 = d1;
185 d1 = t;
186 }
187 *best_numerator = n1;
188 *best_denominator = d1;
189}
190
191static ulong rk3568_rtc32k_get_pmuclk(struct rk3568_pmuclk_priv *priv)
192{
193 struct rk3568_pmucru *pmucru = priv->pmucru;
194 unsigned long m, n;
195 u32 fracdiv;
196
197 fracdiv = readl(&pmucru->pmu_clksel_con[1]);
198 m = fracdiv & RTC32K_FRAC_NUMERATOR_MASK;
199 m >>= RTC32K_FRAC_NUMERATOR_SHIFT;
200 n = fracdiv & RTC32K_FRAC_DENOMINATOR_MASK;
201 n >>= RTC32K_FRAC_DENOMINATOR_SHIFT;
202
203 return OSC_HZ * m / n;
204}
205
206static ulong rk3568_rtc32k_set_pmuclk(struct rk3568_pmuclk_priv *priv,
207 ulong rate)
208{
209 struct rk3568_pmucru *pmucru = priv->pmucru;
210 unsigned long m, n, val;
211
212 rk_clrsetreg(&pmucru->pmu_clksel_con[0], RTC32K_SEL_MASK,
213 RTC32K_SEL_OSC0_DIV32K << RTC32K_SEL_SHIFT);
214
215 rational_best_approximation(rate, OSC_HZ,
216 GENMASK(16 - 1, 0),
217 GENMASK(16 - 1, 0),
218 &m, &n);
219 val = m << RTC32K_FRAC_NUMERATOR_SHIFT | n;
220 writel(val, &pmucru->pmu_clksel_con[1]);
221
222 return rk3568_rtc32k_get_pmuclk(priv);
223}
224
225static ulong rk3568_i2c_get_pmuclk(struct rk3568_pmuclk_priv *priv,
226 ulong clk_id)
227{
228 struct rk3568_pmucru *pmucru = priv->pmucru;
229 u32 div, con;
230
231 switch (clk_id) {
232 case CLK_I2C0:
233 con = readl(&pmucru->pmu_clksel_con[3]);
234 div = (con & CLK_I2C0_DIV_MASK) >> CLK_I2C0_DIV_SHIFT;
235 break;
236 default:
237 return -ENOENT;
238 }
239
240 return DIV_TO_RATE(priv->ppll_hz, div);
241}
242
243static ulong rk3568_i2c_set_pmuclk(struct rk3568_pmuclk_priv *priv,
244 ulong clk_id, ulong rate)
245{
246 struct rk3568_pmucru *pmucru = priv->pmucru;
247 int src_clk_div;
248
249 src_clk_div = DIV_ROUND_UP(priv->ppll_hz, rate);
250 assert(src_clk_div - 1 <= 127);
251
252 switch (clk_id) {
253 case CLK_I2C0:
254 rk_clrsetreg(&pmucru->pmu_clksel_con[3], CLK_I2C0_DIV_MASK,
255 (src_clk_div - 1) << CLK_I2C0_DIV_SHIFT);
256 break;
257 default:
258 return -ENOENT;
259 }
260
261 return rk3568_i2c_get_pmuclk(priv, clk_id);
262}
263
264static ulong rk3568_pwm_get_pmuclk(struct rk3568_pmuclk_priv *priv,
265 ulong clk_id)
266{
267 struct rk3568_pmucru *pmucru = priv->pmucru;
268 u32 div, sel, con, parent;
269
270 switch (clk_id) {
271 case CLK_PWM0:
272 con = readl(&pmucru->pmu_clksel_con[6]);
273 sel = (con & CLK_PWM0_SEL_MASK) >> CLK_PWM0_SEL_SHIFT;
274 div = (con & CLK_PWM0_DIV_MASK) >> CLK_PWM0_DIV_SHIFT;
275 if (sel == CLK_PWM0_SEL_XIN24M)
276 parent = OSC_HZ;
277 else
278 parent = priv->ppll_hz;
279 break;
280 default:
281 return -ENOENT;
282 }
283
284 return DIV_TO_RATE(parent, div);
285}
286
287static ulong rk3568_pwm_set_pmuclk(struct rk3568_pmuclk_priv *priv,
288 ulong clk_id, ulong rate)
289{
290 struct rk3568_pmucru *pmucru = priv->pmucru;
291 int src_clk_div;
292
293 switch (clk_id) {
294 case CLK_PWM0:
295 if (rate == OSC_HZ) {
296 rk_clrsetreg(&pmucru->pmu_clksel_con[6],
297 CLK_PWM0_SEL_MASK | CLK_PWM0_DIV_MASK,
298 (CLK_PWM0_SEL_XIN24M <<
299 CLK_PWM0_SEL_SHIFT) |
300 0 << CLK_PWM0_SEL_SHIFT);
301 } else {
302 src_clk_div = DIV_ROUND_UP(priv->ppll_hz, rate);
303 assert(src_clk_div - 1 <= 127);
304 rk_clrsetreg(&pmucru->pmu_clksel_con[6],
305 CLK_PWM0_DIV_MASK | CLK_PWM0_DIV_MASK,
306 (CLK_PWM0_SEL_PPLL << CLK_PWM0_SEL_SHIFT) |
307 (src_clk_div - 1) << CLK_PWM0_DIV_SHIFT);
308 }
309 break;
310 default:
311 return -ENOENT;
312 }
313
314 return rk3568_pwm_get_pmuclk(priv, clk_id);
315}
316
317static ulong rk3568_pmu_get_pmuclk(struct rk3568_pmuclk_priv *priv)
318{
319 struct rk3568_pmucru *pmucru = priv->pmucru;
320 u32 div, con, sel, parent;
321
322 con = readl(&pmucru->pmu_clksel_con[2]);
323 sel = (con & PCLK_PDPMU_SEL_MASK) >> PCLK_PDPMU_SEL_SHIFT;
324 div = (con & PCLK_PDPMU_DIV_MASK) >> PCLK_PDPMU_DIV_SHIFT;
325 if (sel)
326 parent = GPLL_HZ;
327 else
328 parent = priv->ppll_hz;
329
330 return DIV_TO_RATE(parent, div);
331}
332
333static ulong rk3568_pmu_set_pmuclk(struct rk3568_pmuclk_priv *priv,
334 ulong rate)
335{
336 struct rk3568_pmucru *pmucru = priv->pmucru;
337 int src_clk_div;
338
339 src_clk_div = DIV_ROUND_UP(priv->ppll_hz, rate);
340 assert(src_clk_div - 1 <= 31);
341
342 rk_clrsetreg(&pmucru->pmu_clksel_con[2],
343 PCLK_PDPMU_DIV_MASK | PCLK_PDPMU_SEL_MASK,
344 (PCLK_PDPMU_SEL_PPLL << PCLK_PDPMU_SEL_SHIFT) |
345 ((src_clk_div - 1) << PCLK_PDPMU_DIV_SHIFT));
346
347 return rk3568_pmu_get_pmuclk(priv);
348}
349
350static ulong rk3568_pmuclk_get_rate(struct clk *clk)
351{
352 struct rk3568_pmuclk_priv *priv = dev_get_priv(clk->dev);
353 ulong rate = 0;
354
355 if (!priv->ppll_hz) {
356 printf("%s ppll=%lu\n", __func__, priv->ppll_hz);
357 return -ENOENT;
358 }
359
360 debug("%s %ld\n", __func__, clk->id);
361 switch (clk->id) {
362 case PLL_PPLL:
363 rate = rockchip_pll_get_rate(&rk3568_pll_clks[PPLL],
364 priv->pmucru, PPLL);
365 break;
366 case PLL_HPLL:
367 rate = rockchip_pll_get_rate(&rk3568_pll_clks[HPLL],
368 priv->pmucru, HPLL);
369 break;
370 case CLK_RTC_32K:
371 case CLK_RTC32K_FRAC:
372 rate = rk3568_rtc32k_get_pmuclk(priv);
373 break;
374 case CLK_I2C0:
375 rate = rk3568_i2c_get_pmuclk(priv, clk->id);
376 break;
377 case CLK_PWM0:
378 rate = rk3568_pwm_get_pmuclk(priv, clk->id);
379 break;
380 case PCLK_PMU:
381 rate = rk3568_pmu_get_pmuclk(priv);
382 break;
383 default:
384 return -ENOENT;
385 }
386
387 return rate;
388}
389
390static ulong rk3568_pmuclk_set_rate(struct clk *clk, ulong rate)
391{
392 struct rk3568_pmuclk_priv *priv = dev_get_priv(clk->dev);
393 ulong ret = 0;
394
395 if (!priv->ppll_hz) {
396 printf("%s ppll=%lu\n", __func__, priv->ppll_hz);
397 return -ENOENT;
398 }
399
400 debug("%s %ld %ld\n", __func__, clk->id, rate);
401 switch (clk->id) {
402 case PLL_PPLL:
403 ret = rockchip_pll_set_rate(&rk3568_pll_clks[PPLL],
404 priv->pmucru, PPLL, rate);
405 priv->ppll_hz = rockchip_pll_get_rate(&rk3568_pll_clks[PPLL],
406 priv->pmucru, PPLL);
407 break;
408 case PLL_HPLL:
409 ret = rockchip_pll_set_rate(&rk3568_pll_clks[HPLL],
410 priv->pmucru, HPLL, rate);
411 priv->hpll_hz = rockchip_pll_get_rate(&rk3568_pll_clks[HPLL],
412 priv->pmucru, HPLL);
413 break;
414 case CLK_RTC_32K:
415 case CLK_RTC32K_FRAC:
416 ret = rk3568_rtc32k_set_pmuclk(priv, rate);
417 break;
418 case CLK_I2C0:
419 ret = rk3568_i2c_set_pmuclk(priv, clk->id, rate);
420 break;
421 case CLK_PWM0:
422 ret = rk3568_pwm_set_pmuclk(priv, clk->id, rate);
423 break;
424 case PCLK_PMU:
425 ret = rk3568_pmu_set_pmuclk(priv, rate);
426 break;
427 default:
428 return -ENOENT;
429 }
430
431 return ret;
432}
433
434static int rk3568_rtc32k_set_parent(struct clk *clk, struct clk *parent)
435{
436 struct rk3568_pmuclk_priv *priv = dev_get_priv(clk->dev);
437 struct rk3568_pmucru *pmucru = priv->pmucru;
438
439 if (parent->id == CLK_RTC32K_FRAC)
440 rk_clrsetreg(&pmucru->pmu_clksel_con[0], RTC32K_SEL_MASK,
441 RTC32K_SEL_OSC0_DIV32K << RTC32K_SEL_SHIFT);
442 else
443 rk_clrsetreg(&pmucru->pmu_clksel_con[0], RTC32K_SEL_MASK,
444 RTC32K_SEL_OSC1_32K << RTC32K_SEL_SHIFT);
445
446 return 0;
447}
448
449static int rk3568_pmuclk_set_parent(struct clk *clk, struct clk *parent)
450{
451 switch (clk->id) {
452 case CLK_RTC_32K:
453 return rk3568_rtc32k_set_parent(clk, parent);
454 default:
455 return -ENOENT;
456 }
457}
458
459static struct clk_ops rk3568_pmuclk_ops = {
460 .get_rate = rk3568_pmuclk_get_rate,
461 .set_rate = rk3568_pmuclk_set_rate,
462 .set_parent = rk3568_pmuclk_set_parent,
463};
464
465static int rk3568_pmuclk_probe(struct udevice *dev)
466{
467 struct rk3568_pmuclk_priv *priv = dev_get_priv(dev);
468 int ret = 0;
469
470 if (priv->ppll_hz != PPLL_HZ) {
471 ret = rockchip_pll_set_rate(&rk3568_pll_clks[PPLL],
472 priv->pmucru,
473 PPLL, PPLL_HZ);
474 if (!ret)
475 priv->ppll_hz = PPLL_HZ;
476 }
477
478 /* Ungate PCIe30phy refclk_m and refclk_n */
479 rk_clrsetreg(&priv->pmucru->pmu_clkgate_con[2], 0x3 << 13, 0 << 13);
480 return 0;
481}
482
483static int rk3568_pmuclk_ofdata_to_platdata(struct udevice *dev)
484{
485 struct rk3568_pmuclk_priv *priv = dev_get_priv(dev);
486
487 priv->pmucru = dev_read_addr_ptr(dev);
488
489 return 0;
490}
491
492static int rk3568_pmuclk_bind(struct udevice *dev)
493{
494#if CONFIG_IS_ENABLED(RESET_ROCKCHIP)
495 int ret = 0;
496
497 ret = offsetof(struct rk3568_pmucru, pmu_softrst_con[0]);
498 ret = rockchip_reset_bind(dev, ret, 1);
499 if (ret)
500 debug("Warning: pmucru software reset driver bind faile\n");
501#endif
502
503 return 0;
504}
505
506static const struct udevice_id rk3568_pmuclk_ids[] = {
507 { .compatible = "rockchip,rk3568-pmucru" },
508 { }
509};
510
511U_BOOT_DRIVER(rockchip_rk3568_pmucru) = {
512 .name = "rockchip_rk3568_pmucru",
513 .id = UCLASS_CLK,
514 .of_match = rk3568_pmuclk_ids,
515 .priv_auto = sizeof(struct rk3568_pmuclk_priv),
516 .of_to_plat = rk3568_pmuclk_ofdata_to_platdata,
517 .ops = &rk3568_pmuclk_ops,
518 .bind = rk3568_pmuclk_bind,
519 .probe = rk3568_pmuclk_probe,
520#if CONFIG_IS_ENABLED(OF_PLATDATA)
521 .plat_auto = sizeof(struct rk3568_pmuclk_plat),
522#endif
523
524};
525
526static int rk3568_armclk_set_clk(struct rk3568_clk_priv *priv, ulong hz)
527{
528 struct rk3568_cru *cru = priv->cru;
529 const struct rockchip_cpu_rate_table *rate;
530 ulong old_rate;
531
532 rate = rockchip_get_cpu_settings(rk3568_cpu_rates, hz);
533 if (!rate) {
534 printf("%s unsupported rate\n", __func__);
535 return -EINVAL;
536 }
537
538 rk_clrsetreg(&cru->clksel_con[0],
539 CLK_CORE_PRE_SEL_MASK,
540 (CLK_CORE_PRE_SEL_SRC << CLK_CORE_PRE_SEL_SHIFT));
541 rk_clrsetreg(&cru->clksel_con[2],
542 SCLK_CORE_PRE_SEL_MASK |
543 SCLK_CORE_SRC_SEL_MASK |
544 SCLK_CORE_SRC_DIV_MASK,
545 (SCLK_CORE_PRE_SEL_SRC <<
546 SCLK_CORE_PRE_SEL_SHIFT) |
547 (SCLK_CORE_SRC_SEL_APLL <<
548 SCLK_CORE_SRC_SEL_SHIFT) |
549 (1 << SCLK_CORE_SRC_DIV_SHIFT));
550
551 /*
552 * set up dependent divisors for DBG and ACLK clocks.
553 */
554 old_rate = rockchip_pll_get_rate(&rk3568_pll_clks[APLL],
555 priv->cru, APLL);
556 if (old_rate > hz) {
557 if (rockchip_pll_set_rate(&rk3568_pll_clks[APLL],
558 priv->cru, APLL, hz))
559 return -EINVAL;
560 rk_clrsetreg(&cru->clksel_con[3],
561 GICCLK_CORE_DIV_MASK | ATCLK_CORE_DIV_MASK,
562 rate->pclk_div << GICCLK_CORE_DIV_SHIFT |
563 rate->pclk_div << ATCLK_CORE_DIV_SHIFT);
564 rk_clrsetreg(&cru->clksel_con[4],
565 PERIPHCLK_CORE_PRE_DIV_MASK |
566 PCLK_CORE_PRE_DIV_MASK,
567 rate->pclk_div << PCLK_CORE_PRE_DIV_SHIFT |
568 rate->pclk_div << PERIPHCLK_CORE_PRE_DIV_SHIFT);
569 rk_clrsetreg(&cru->clksel_con[5],
570 ACLK_CORE_NDFT_DIV_MASK,
571 rate->aclk_div << ACLK_CORE_NDFT_DIV_SHIFT);
572 } else if (old_rate < hz) {
573 rk_clrsetreg(&cru->clksel_con[3],
574 GICCLK_CORE_DIV_MASK | ATCLK_CORE_DIV_MASK,
575 rate->pclk_div << GICCLK_CORE_DIV_SHIFT |
576 rate->pclk_div << ATCLK_CORE_DIV_SHIFT);
577 rk_clrsetreg(&cru->clksel_con[4],
578 PERIPHCLK_CORE_PRE_DIV_MASK |
579 PCLK_CORE_PRE_DIV_MASK,
580 rate->pclk_div << PCLK_CORE_PRE_DIV_SHIFT |
581 rate->pclk_div << PERIPHCLK_CORE_PRE_DIV_SHIFT);
582 rk_clrsetreg(&cru->clksel_con[5],
583 ACLK_CORE_NDFT_DIV_MASK,
584 rate->aclk_div << ACLK_CORE_NDFT_DIV_SHIFT);
585 if (rockchip_pll_set_rate(&rk3568_pll_clks[APLL],
586 priv->cru, APLL, hz))
587 return -EINVAL;
588 }
589
590 return 0;
591}
592
593static ulong rk3568_cpll_div_get_rate(struct rk3568_clk_priv *priv,
594 ulong clk_id)
595{
596 struct rk3568_cru *cru = priv->cru;
597 int div, mask, shift, con;
598
599 switch (clk_id) {
600 case CPLL_500M:
601 con = 78;
602 mask = CPLL_500M_DIV_MASK;
603 shift = CPLL_500M_DIV_SHIFT;
604 break;
605 case CPLL_333M:
606 con = 79;
607 mask = CPLL_333M_DIV_MASK;
608 shift = CPLL_333M_DIV_SHIFT;
609 break;
610 case CPLL_250M:
611 con = 79;
612 mask = CPLL_250M_DIV_MASK;
613 shift = CPLL_250M_DIV_SHIFT;
614 break;
615 case CPLL_125M:
616 con = 80;
617 mask = CPLL_125M_DIV_MASK;
618 shift = CPLL_125M_DIV_SHIFT;
619 break;
620 case CPLL_100M:
621 con = 82;
622 mask = CPLL_100M_DIV_MASK;
623 shift = CPLL_100M_DIV_SHIFT;
624 break;
625 case CPLL_62P5M:
626 con = 80;
627 mask = CPLL_62P5M_DIV_MASK;
628 shift = CPLL_62P5M_DIV_SHIFT;
629 break;
630 case CPLL_50M:
631 con = 81;
632 mask = CPLL_50M_DIV_MASK;
633 shift = CPLL_50M_DIV_SHIFT;
634 break;
635 case CPLL_25M:
636 con = 81;
637 mask = CPLL_25M_DIV_MASK;
638 shift = CPLL_25M_DIV_SHIFT;
639 break;
640 default:
641 return -ENOENT;
642 }
643
644 div = (readl(&cru->clksel_con[con]) & mask) >> shift;
645 return DIV_TO_RATE(priv->cpll_hz, div);
646}
647
648static ulong rk3568_cpll_div_set_rate(struct rk3568_clk_priv *priv,
649 ulong clk_id, ulong rate)
650{
651 struct rk3568_cru *cru = priv->cru;
652 int div, mask, shift, con;
653
654 switch (clk_id) {
655 case CPLL_500M:
656 con = 78;
657 mask = CPLL_500M_DIV_MASK;
658 shift = CPLL_500M_DIV_SHIFT;
659 break;
660 case CPLL_333M:
661 con = 79;
662 mask = CPLL_333M_DIV_MASK;
663 shift = CPLL_333M_DIV_SHIFT;
664 break;
665 case CPLL_250M:
666 con = 79;
667 mask = CPLL_250M_DIV_MASK;
668 shift = CPLL_250M_DIV_SHIFT;
669 break;
670 case CPLL_125M:
671 con = 80;
672 mask = CPLL_125M_DIV_MASK;
673 shift = CPLL_125M_DIV_SHIFT;
674 break;
675 case CPLL_100M:
676 con = 82;
677 mask = CPLL_100M_DIV_MASK;
678 shift = CPLL_100M_DIV_SHIFT;
679 break;
680 case CPLL_62P5M:
681 con = 80;
682 mask = CPLL_62P5M_DIV_MASK;
683 shift = CPLL_62P5M_DIV_SHIFT;
684 break;
685 case CPLL_50M:
686 con = 81;
687 mask = CPLL_50M_DIV_MASK;
688 shift = CPLL_50M_DIV_SHIFT;
689 break;
690 case CPLL_25M:
691 con = 81;
692 mask = CPLL_25M_DIV_MASK;
693 shift = CPLL_25M_DIV_SHIFT;
694 break;
695 default:
696 return -ENOENT;
697 }
698
699 div = DIV_ROUND_UP(priv->cpll_hz, rate);
700 assert(div - 1 <= 31);
701 rk_clrsetreg(&cru->clksel_con[con],
702 mask, (div - 1) << shift);
703 return rk3568_cpll_div_get_rate(priv, clk_id);
704}
705
706static ulong rk3568_bus_get_clk(struct rk3568_clk_priv *priv, ulong clk_id)
707{
708 struct rk3568_cru *cru = priv->cru;
709 u32 con, sel, rate;
710
711 switch (clk_id) {
712 case ACLK_BUS:
713 con = readl(&cru->clksel_con[50]);
714 sel = (con & ACLK_BUS_SEL_MASK) >> ACLK_BUS_SEL_SHIFT;
715 if (sel == ACLK_BUS_SEL_200M)
716 rate = 200 * MHz;
717 else if (sel == ACLK_BUS_SEL_150M)
718 rate = 150 * MHz;
719 else if (sel == ACLK_BUS_SEL_100M)
720 rate = 100 * MHz;
721 else
722 rate = OSC_HZ;
723 break;
724 case PCLK_BUS:
725 case PCLK_WDT_NS:
726 con = readl(&cru->clksel_con[50]);
727 sel = (con & PCLK_BUS_SEL_MASK) >> PCLK_BUS_SEL_SHIFT;
728 if (sel == PCLK_BUS_SEL_100M)
729 rate = 100 * MHz;
730 else if (sel == PCLK_BUS_SEL_75M)
731 rate = 75 * MHz;
732 else if (sel == PCLK_BUS_SEL_50M)
733 rate = 50 * MHz;
734 else
735 rate = OSC_HZ;
736 break;
737 default:
738 return -ENOENT;
739 }
740
741 return rate;
742}
743
744static ulong rk3568_bus_set_clk(struct rk3568_clk_priv *priv,
745 ulong clk_id, ulong rate)
746{
747 struct rk3568_cru *cru = priv->cru;
748 int src_clk;
749
750 switch (clk_id) {
751 case ACLK_BUS:
752 if (rate == 200 * MHz)
753 src_clk = ACLK_BUS_SEL_200M;
754 else if (rate == 150 * MHz)
755 src_clk = ACLK_BUS_SEL_150M;
756 else if (rate == 100 * MHz)
757 src_clk = ACLK_BUS_SEL_100M;
758 else
759 src_clk = ACLK_BUS_SEL_24M;
760 rk_clrsetreg(&cru->clksel_con[50],
761 ACLK_BUS_SEL_MASK,
762 src_clk << ACLK_BUS_SEL_SHIFT);
763 break;
764 case PCLK_BUS:
765 case PCLK_WDT_NS:
766 if (rate == 100 * MHz)
767 src_clk = PCLK_BUS_SEL_100M;
768 else if (rate == 75 * MHz)
769 src_clk = PCLK_BUS_SEL_75M;
770 else if (rate == 50 * MHz)
771 src_clk = PCLK_BUS_SEL_50M;
772 else
773 src_clk = PCLK_BUS_SEL_24M;
774 rk_clrsetreg(&cru->clksel_con[50],
775 PCLK_BUS_SEL_MASK,
776 src_clk << PCLK_BUS_SEL_SHIFT);
777 break;
778
779 default:
780 printf("do not support this bus freq\n");
781 return -EINVAL;
782 }
783
784 return rk3568_bus_get_clk(priv, clk_id);
785}
786
787static ulong rk3568_perimid_get_clk(struct rk3568_clk_priv *priv, ulong clk_id)
788{
789 struct rk3568_cru *cru = priv->cru;
790 u32 con, sel, rate;
791
792 switch (clk_id) {
793 case ACLK_PERIMID:
794 con = readl(&cru->clksel_con[10]);
795 sel = (con & ACLK_PERIMID_SEL_MASK) >> ACLK_PERIMID_SEL_SHIFT;
796 if (sel == ACLK_PERIMID_SEL_300M)
797 rate = 300 * MHz;
798 else if (sel == ACLK_PERIMID_SEL_200M)
799 rate = 200 * MHz;
800 else if (sel == ACLK_PERIMID_SEL_100M)
801 rate = 100 * MHz;
802 else
803 rate = OSC_HZ;
804 break;
805 case HCLK_PERIMID:
806 con = readl(&cru->clksel_con[10]);
807 sel = (con & HCLK_PERIMID_SEL_MASK) >> HCLK_PERIMID_SEL_SHIFT;
808 if (sel == HCLK_PERIMID_SEL_150M)
809 rate = 150 * MHz;
810 else if (sel == HCLK_PERIMID_SEL_100M)
811 rate = 100 * MHz;
812 else if (sel == HCLK_PERIMID_SEL_75M)
813 rate = 75 * MHz;
814 else
815 rate = OSC_HZ;
816 break;
817 default:
818 return -ENOENT;
819 }
820
821 return rate;
822}
823
824static ulong rk3568_perimid_set_clk(struct rk3568_clk_priv *priv,
825 ulong clk_id, ulong rate)
826{
827 struct rk3568_cru *cru = priv->cru;
828 int src_clk;
829
830 switch (clk_id) {
831 case ACLK_PERIMID:
832 if (rate == 300 * MHz)
833 src_clk = ACLK_PERIMID_SEL_300M;
834 else if (rate == 200 * MHz)
835 src_clk = ACLK_PERIMID_SEL_200M;
836 else if (rate == 100 * MHz)
837 src_clk = ACLK_PERIMID_SEL_100M;
838 else
839 src_clk = ACLK_PERIMID_SEL_24M;
840 rk_clrsetreg(&cru->clksel_con[10],
841 ACLK_PERIMID_SEL_MASK,
842 src_clk << ACLK_PERIMID_SEL_SHIFT);
843 break;
844 case HCLK_PERIMID:
845 if (rate == 150 * MHz)
846 src_clk = HCLK_PERIMID_SEL_150M;
847 else if (rate == 100 * MHz)
848 src_clk = HCLK_PERIMID_SEL_100M;
849 else if (rate == 75 * MHz)
850 src_clk = HCLK_PERIMID_SEL_75M;
851 else
852 src_clk = HCLK_PERIMID_SEL_24M;
853 rk_clrsetreg(&cru->clksel_con[10],
854 HCLK_PERIMID_SEL_MASK,
855 src_clk << HCLK_PERIMID_SEL_SHIFT);
856 break;
857
858 default:
859 printf("do not support this permid freq\n");
860 return -EINVAL;
861 }
862
863 return rk3568_perimid_get_clk(priv, clk_id);
864}
865
866static ulong rk3568_top_get_clk(struct rk3568_clk_priv *priv, ulong clk_id)
867{
868 struct rk3568_cru *cru = priv->cru;
869 u32 con, sel, rate;
870
871 switch (clk_id) {
872 case ACLK_TOP_HIGH:
873 con = readl(&cru->clksel_con[73]);
874 sel = (con & ACLK_TOP_HIGH_SEL_MASK) >> ACLK_TOP_HIGH_SEL_SHIFT;
875 if (sel == ACLK_TOP_HIGH_SEL_500M)
876 rate = 500 * MHz;
877 else if (sel == ACLK_TOP_HIGH_SEL_400M)
878 rate = 400 * MHz;
879 else if (sel == ACLK_TOP_HIGH_SEL_300M)
880 rate = 300 * MHz;
881 else
882 rate = OSC_HZ;
883 break;
884 case ACLK_TOP_LOW:
885 con = readl(&cru->clksel_con[73]);
886 sel = (con & ACLK_TOP_LOW_SEL_MASK) >> ACLK_TOP_LOW_SEL_SHIFT;
887 if (sel == ACLK_TOP_LOW_SEL_400M)
888 rate = 400 * MHz;
889 else if (sel == ACLK_TOP_LOW_SEL_300M)
890 rate = 300 * MHz;
891 else if (sel == ACLK_TOP_LOW_SEL_200M)
892 rate = 200 * MHz;
893 else
894 rate = OSC_HZ;
895 break;
896 case HCLK_TOP:
897 con = readl(&cru->clksel_con[73]);
898 sel = (con & HCLK_TOP_SEL_MASK) >> HCLK_TOP_SEL_SHIFT;
899 if (sel == HCLK_TOP_SEL_150M)
900 rate = 150 * MHz;
901 else if (sel == HCLK_TOP_SEL_100M)
902 rate = 100 * MHz;
903 else if (sel == HCLK_TOP_SEL_75M)
904 rate = 75 * MHz;
905 else
906 rate = OSC_HZ;
907 break;
908 case PCLK_TOP:
909 con = readl(&cru->clksel_con[73]);
910 sel = (con & PCLK_TOP_SEL_MASK) >> PCLK_TOP_SEL_SHIFT;
911 if (sel == PCLK_TOP_SEL_100M)
912 rate = 100 * MHz;
913 else if (sel == PCLK_TOP_SEL_75M)
914 rate = 75 * MHz;
915 else if (sel == PCLK_TOP_SEL_50M)
916 rate = 50 * MHz;
917 else
918 rate = OSC_HZ;
919 break;
920 default:
921 return -ENOENT;
922 }
923
924 return rate;
925}
926
927static ulong rk3568_top_set_clk(struct rk3568_clk_priv *priv,
928 ulong clk_id, ulong rate)
929{
930 struct rk3568_cru *cru = priv->cru;
931 int src_clk;
932
933 switch (clk_id) {
934 case ACLK_TOP_HIGH:
935 if (rate == 500 * MHz)
936 src_clk = ACLK_TOP_HIGH_SEL_500M;
937 else if (rate == 400 * MHz)
938 src_clk = ACLK_TOP_HIGH_SEL_400M;
939 else if (rate == 300 * MHz)
940 src_clk = ACLK_TOP_HIGH_SEL_300M;
941 else
942 src_clk = ACLK_TOP_HIGH_SEL_24M;
943 rk_clrsetreg(&cru->clksel_con[73],
944 ACLK_TOP_HIGH_SEL_MASK,
945 src_clk << ACLK_TOP_HIGH_SEL_SHIFT);
946 break;
947 case ACLK_TOP_LOW:
948 if (rate == 400 * MHz)
949 src_clk = ACLK_TOP_LOW_SEL_400M;
950 else if (rate == 300 * MHz)
951 src_clk = ACLK_TOP_LOW_SEL_300M;
952 else if (rate == 200 * MHz)
953 src_clk = ACLK_TOP_LOW_SEL_200M;
954 else
955 src_clk = ACLK_TOP_LOW_SEL_24M;
956 rk_clrsetreg(&cru->clksel_con[73],
957 ACLK_TOP_LOW_SEL_MASK,
958 src_clk << ACLK_TOP_LOW_SEL_SHIFT);
959 break;
960 case HCLK_TOP:
961 if (rate == 150 * MHz)
962 src_clk = HCLK_TOP_SEL_150M;
963 else if (rate == 100 * MHz)
964 src_clk = HCLK_TOP_SEL_100M;
965 else if (rate == 75 * MHz)
966 src_clk = HCLK_TOP_SEL_75M;
967 else
968 src_clk = HCLK_TOP_SEL_24M;
969 rk_clrsetreg(&cru->clksel_con[73],
970 HCLK_TOP_SEL_MASK,
971 src_clk << HCLK_TOP_SEL_SHIFT);
972 break;
973 case PCLK_TOP:
974 if (rate == 100 * MHz)
975 src_clk = PCLK_TOP_SEL_100M;
976 else if (rate == 75 * MHz)
977 src_clk = PCLK_TOP_SEL_75M;
978 else if (rate == 50 * MHz)
979 src_clk = PCLK_TOP_SEL_50M;
980 else
981 src_clk = PCLK_TOP_SEL_24M;
982 rk_clrsetreg(&cru->clksel_con[73],
983 PCLK_TOP_SEL_MASK,
984 src_clk << PCLK_TOP_SEL_SHIFT);
985 break;
986
987 default:
988 printf("do not support this permid freq\n");
989 return -EINVAL;
990 }
991
992 return rk3568_top_get_clk(priv, clk_id);
993}
994
995static ulong rk3568_i2c_get_clk(struct rk3568_clk_priv *priv, ulong clk_id)
996{
997 struct rk3568_cru *cru = priv->cru;
998 u32 sel, con;
999 ulong rate;
1000
1001 switch (clk_id) {
1002 case CLK_I2C1:
1003 case CLK_I2C2:
1004 case CLK_I2C3:
1005 case CLK_I2C4:
1006 case CLK_I2C5:
1007 con = readl(&cru->clksel_con[71]);
1008 sel = (con & CLK_I2C_SEL_MASK) >> CLK_I2C_SEL_SHIFT;
1009 if (sel == CLK_I2C_SEL_200M)
1010 rate = 200 * MHz;
1011 else if (sel == CLK_I2C_SEL_100M)
1012 rate = 100 * MHz;
1013 else if (sel == CLK_I2C_SEL_CPLL_100M)
1014 rate = 100 * MHz;
1015 else
1016 rate = OSC_HZ;
1017 break;
1018 default:
1019 return -ENOENT;
1020 }
1021
1022 return rate;
1023}
1024
1025static ulong rk3568_i2c_set_clk(struct rk3568_clk_priv *priv, ulong clk_id,
1026 ulong rate)
1027{
1028 struct rk3568_cru *cru = priv->cru;
1029 int src_clk;
1030
1031 if (rate == 200 * MHz)
1032 src_clk = CLK_I2C_SEL_200M;
1033 else if (rate == 100 * MHz)
1034 src_clk = CLK_I2C_SEL_100M;
1035 else
1036 src_clk = CLK_I2C_SEL_24M;
1037
1038 switch (clk_id) {
1039 case CLK_I2C1:
1040 case CLK_I2C2:
1041 case CLK_I2C3:
1042 case CLK_I2C4:
1043 case CLK_I2C5:
1044 rk_clrsetreg(&cru->clksel_con[71], CLK_I2C_SEL_MASK,
1045 src_clk << CLK_I2C_SEL_SHIFT);
1046 break;
1047 default:
1048 return -ENOENT;
1049 }
1050
1051 return rk3568_i2c_get_clk(priv, clk_id);
1052}
1053
1054static ulong rk3568_spi_get_clk(struct rk3568_clk_priv *priv, ulong clk_id)
1055{
1056 struct rk3568_cru *cru = priv->cru;
1057 u32 sel, con;
1058
1059 con = readl(&cru->clksel_con[72]);
1060
1061 switch (clk_id) {
1062 case CLK_SPI0:
1063 sel = (con & CLK_SPI0_SEL_MASK) >> CLK_SPI0_SEL_SHIFT;
1064 break;
1065 case CLK_SPI1:
1066 sel = (con & CLK_SPI1_SEL_MASK) >> CLK_SPI1_SEL_SHIFT;
1067 break;
1068 case CLK_SPI2:
1069 sel = (con & CLK_SPI2_SEL_MASK) >> CLK_SPI2_SEL_SHIFT;
1070 break;
1071 case CLK_SPI3:
1072 sel = (con & CLK_SPI3_SEL_MASK) >> CLK_SPI3_SEL_SHIFT;
1073 break;
1074 default:
1075 return -ENOENT;
1076 }
1077
1078 switch (sel) {
1079 case CLK_SPI_SEL_200M:
1080 return 200 * MHz;
1081 case CLK_SPI_SEL_24M:
1082 return OSC_HZ;
1083 case CLK_SPI_SEL_CPLL_100M:
1084 return 100 * MHz;
1085 default:
1086 return -ENOENT;
1087 }
1088}
1089
1090static ulong rk3568_spi_set_clk(struct rk3568_clk_priv *priv,
1091 ulong clk_id, ulong rate)
1092{
1093 struct rk3568_cru *cru = priv->cru;
1094 int src_clk;
1095
1096 if (rate == 200 * MHz)
1097 src_clk = CLK_SPI_SEL_200M;
1098 else if (rate == 100 * MHz)
1099 src_clk = CLK_SPI_SEL_CPLL_100M;
1100 else
1101 src_clk = CLK_SPI_SEL_24M;
1102
1103 switch (clk_id) {
1104 case CLK_SPI0:
1105 rk_clrsetreg(&cru->clksel_con[72],
1106 CLK_SPI0_SEL_MASK,
1107 src_clk << CLK_SPI0_SEL_SHIFT);
1108 break;
1109 case CLK_SPI1:
1110 rk_clrsetreg(&cru->clksel_con[72],
1111 CLK_SPI1_SEL_MASK,
1112 src_clk << CLK_SPI1_SEL_SHIFT);
1113 break;
1114 case CLK_SPI2:
1115 rk_clrsetreg(&cru->clksel_con[72],
1116 CLK_SPI2_SEL_MASK,
1117 src_clk << CLK_SPI2_SEL_SHIFT);
1118 break;
1119 case CLK_SPI3:
1120 rk_clrsetreg(&cru->clksel_con[72],
1121 CLK_SPI3_SEL_MASK,
1122 src_clk << CLK_SPI3_SEL_SHIFT);
1123 break;
1124 default:
1125 return -ENOENT;
1126 }
1127
1128 return rk3568_spi_get_clk(priv, clk_id);
1129}
1130
1131static ulong rk3568_pwm_get_clk(struct rk3568_clk_priv *priv, ulong clk_id)
1132{
1133 struct rk3568_cru *cru = priv->cru;
1134 u32 sel, con;
1135
1136 con = readl(&cru->clksel_con[72]);
1137
1138 switch (clk_id) {
1139 case CLK_PWM1:
1140 sel = (con & CLK_PWM1_SEL_MASK) >> CLK_PWM3_SEL_SHIFT;
1141 break;
1142 case CLK_PWM2:
1143 sel = (con & CLK_PWM2_SEL_MASK) >> CLK_PWM2_SEL_SHIFT;
1144 break;
1145 case CLK_PWM3:
1146 sel = (con & CLK_PWM3_SEL_MASK) >> CLK_PWM3_SEL_SHIFT;
1147 break;
1148 default:
1149 return -ENOENT;
1150 }
1151
1152 switch (sel) {
1153 case CLK_PWM_SEL_100M:
1154 return 100 * MHz;
1155 case CLK_PWM_SEL_24M:
1156 return OSC_HZ;
1157 case CLK_PWM_SEL_CPLL_100M:
1158 return 100 * MHz;
1159 default:
1160 return -ENOENT;
1161 }
1162}
1163
1164static ulong rk3568_pwm_set_clk(struct rk3568_clk_priv *priv,
1165 ulong clk_id, ulong rate)
1166{
1167 struct rk3568_cru *cru = priv->cru;
1168 int src_clk;
1169
1170 if (rate == 100 * MHz)
1171 src_clk = CLK_PWM_SEL_100M;
1172 else
1173 src_clk = CLK_PWM_SEL_24M;
1174
1175 switch (clk_id) {
1176 case CLK_PWM1:
1177 rk_clrsetreg(&cru->clksel_con[72],
1178 CLK_PWM1_SEL_MASK,
1179 src_clk << CLK_PWM1_SEL_SHIFT);
1180 break;
1181 case CLK_PWM2:
1182 rk_clrsetreg(&cru->clksel_con[72],
1183 CLK_PWM2_SEL_MASK,
1184 src_clk << CLK_PWM2_SEL_SHIFT);
1185 break;
1186 case CLK_PWM3:
1187 rk_clrsetreg(&cru->clksel_con[72],
1188 CLK_PWM3_SEL_MASK,
1189 src_clk << CLK_PWM3_SEL_SHIFT);
1190 break;
1191 default:
1192 return -ENOENT;
1193 }
1194
1195 return rk3568_pwm_get_clk(priv, clk_id);
1196}
1197
1198static ulong rk3568_adc_get_clk(struct rk3568_clk_priv *priv, ulong clk_id)
1199{
1200 struct rk3568_cru *cru = priv->cru;
1201 u32 div, sel, con, prate;
1202
1203 switch (clk_id) {
1204 case CLK_SARADC:
1205 return OSC_HZ;
1206 case CLK_TSADC_TSEN:
1207 con = readl(&cru->clksel_con[51]);
1208 div = (con & CLK_TSADC_TSEN_DIV_MASK) >>
1209 CLK_TSADC_TSEN_DIV_SHIFT;
1210 sel = (con & CLK_TSADC_TSEN_SEL_MASK) >>
1211 CLK_TSADC_TSEN_SEL_SHIFT;
1212 if (sel == CLK_TSADC_TSEN_SEL_24M)
1213 prate = OSC_HZ;
1214 else
1215 prate = 100 * MHz;
1216 return DIV_TO_RATE(prate, div);
1217 case CLK_TSADC:
1218 con = readl(&cru->clksel_con[51]);
1219 div = (con & CLK_TSADC_DIV_MASK) >> CLK_TSADC_DIV_SHIFT;
1220 prate = rk3568_adc_get_clk(priv, CLK_TSADC_TSEN);
1221 return DIV_TO_RATE(prate, div);
1222 default:
1223 return -ENOENT;
1224 }
1225}
1226
1227static ulong rk3568_adc_set_clk(struct rk3568_clk_priv *priv,
1228 ulong clk_id, ulong rate)
1229{
1230 struct rk3568_cru *cru = priv->cru;
1231 int src_clk_div;
1232 ulong prate = 0;
1233
1234 switch (clk_id) {
1235 case CLK_SARADC:
1236 return OSC_HZ;
1237 case CLK_TSADC_TSEN:
1238 if (!(OSC_HZ % rate)) {
1239 src_clk_div = DIV_ROUND_UP(OSC_HZ, rate);
1240 assert(src_clk_div - 1 <= 7);
1241 rk_clrsetreg(&cru->clksel_con[51],
1242 CLK_TSADC_TSEN_SEL_MASK |
1243 CLK_TSADC_TSEN_DIV_MASK,
1244 (CLK_TSADC_TSEN_SEL_24M <<
1245 CLK_TSADC_TSEN_SEL_SHIFT) |
1246 (src_clk_div - 1) <<
1247 CLK_TSADC_TSEN_DIV_SHIFT);
1248 } else {
1249 src_clk_div = DIV_ROUND_UP(100 * MHz, rate);
1250 assert(src_clk_div - 1 <= 7);
1251 rk_clrsetreg(&cru->clksel_con[51],
1252 CLK_TSADC_TSEN_SEL_MASK |
1253 CLK_TSADC_TSEN_DIV_MASK,
1254 (CLK_TSADC_TSEN_SEL_100M <<
1255 CLK_TSADC_TSEN_SEL_SHIFT) |
1256 (src_clk_div - 1) <<
1257 CLK_TSADC_TSEN_DIV_SHIFT);
1258 }
1259 break;
1260 case CLK_TSADC:
1261 prate = rk3568_adc_get_clk(priv, CLK_TSADC_TSEN);
1262 src_clk_div = DIV_ROUND_UP(prate, rate);
1263 assert(src_clk_div - 1 <= 128);
1264 rk_clrsetreg(&cru->clksel_con[51],
1265 CLK_TSADC_DIV_MASK,
1266 (src_clk_div - 1) << CLK_TSADC_DIV_SHIFT);
1267 break;
1268 default:
1269 return -ENOENT;
1270 }
1271 return rk3568_adc_get_clk(priv, clk_id);
1272}
1273
1274static ulong rk3568_crypto_get_rate(struct rk3568_clk_priv *priv, ulong clk_id)
1275{
1276 struct rk3568_cru *cru = priv->cru;
1277 u32 sel, con;
1278
1279 switch (clk_id) {
1280 case ACLK_SECURE_FLASH:
1281 case ACLK_CRYPTO_NS:
1282 con = readl(&cru->clksel_con[27]);
1283 sel = (con & ACLK_SECURE_FLASH_SEL_MASK) >>
1284 ACLK_SECURE_FLASH_SEL_SHIFT;
1285 if (sel == ACLK_SECURE_FLASH_SEL_200M)
1286 return 200 * MHz;
1287 else if (sel == ACLK_SECURE_FLASH_SEL_150M)
1288 return 150 * MHz;
1289 else if (sel == ACLK_SECURE_FLASH_SEL_100M)
1290 return 100 * MHz;
1291 else
1292 return 24 * MHz;
1293 case HCLK_SECURE_FLASH:
1294 case HCLK_CRYPTO_NS:
1295 case CLK_CRYPTO_NS_RNG:
1296 con = readl(&cru->clksel_con[27]);
1297 sel = (con & HCLK_SECURE_FLASH_SEL_MASK) >>
1298 HCLK_SECURE_FLASH_SEL_SHIFT;
1299 if (sel == HCLK_SECURE_FLASH_SEL_150M)
1300 return 150 * MHz;
1301 else if (sel == HCLK_SECURE_FLASH_SEL_100M)
1302 return 100 * MHz;
1303 else if (sel == HCLK_SECURE_FLASH_SEL_75M)
1304 return 75 * MHz;
1305 else
1306 return 24 * MHz;
1307 case CLK_CRYPTO_NS_CORE:
1308 con = readl(&cru->clksel_con[27]);
1309 sel = (con & CLK_CRYPTO_CORE_SEL_MASK) >>
1310 CLK_CRYPTO_CORE_SEL_SHIFT;
1311 if (sel == CLK_CRYPTO_CORE_SEL_200M)
1312 return 200 * MHz;
1313 else if (sel == CLK_CRYPTO_CORE_SEL_150M)
1314 return 150 * MHz;
1315 else
1316 return 100 * MHz;
1317 case CLK_CRYPTO_NS_PKA:
1318 con = readl(&cru->clksel_con[27]);
1319 sel = (con & CLK_CRYPTO_PKA_SEL_MASK) >>
1320 CLK_CRYPTO_PKA_SEL_SHIFT;
1321 if (sel == CLK_CRYPTO_PKA_SEL_300M)
1322 return 300 * MHz;
1323 else if (sel == CLK_CRYPTO_PKA_SEL_200M)
1324 return 200 * MHz;
1325 else
1326 return 100 * MHz;
1327 default:
1328 return -ENOENT;
1329 }
1330}
1331
1332static ulong rk3568_crypto_set_rate(struct rk3568_clk_priv *priv,
1333 ulong clk_id, ulong rate)
1334{
1335 struct rk3568_cru *cru = priv->cru;
1336 u32 src_clk, mask, shift;
1337
1338 switch (clk_id) {
1339 case ACLK_SECURE_FLASH:
1340 case ACLK_CRYPTO_NS:
1341 mask = ACLK_SECURE_FLASH_SEL_MASK;
1342 shift = ACLK_SECURE_FLASH_SEL_SHIFT;
1343 if (rate == 200 * MHz)
1344 src_clk = ACLK_SECURE_FLASH_SEL_200M;
1345 else if (rate == 150 * MHz)
1346 src_clk = ACLK_SECURE_FLASH_SEL_150M;
1347 else if (rate == 100 * MHz)
1348 src_clk = ACLK_SECURE_FLASH_SEL_100M;
1349 else
1350 src_clk = ACLK_SECURE_FLASH_SEL_24M;
1351 break;
1352 case HCLK_SECURE_FLASH:
1353 case HCLK_CRYPTO_NS:
1354 case CLK_CRYPTO_NS_RNG:
1355 mask = HCLK_SECURE_FLASH_SEL_MASK;
1356 shift = HCLK_SECURE_FLASH_SEL_SHIFT;
1357 if (rate == 150 * MHz)
1358 src_clk = HCLK_SECURE_FLASH_SEL_150M;
1359 else if (rate == 100 * MHz)
1360 src_clk = HCLK_SECURE_FLASH_SEL_100M;
1361 else if (rate == 75 * MHz)
1362 src_clk = HCLK_SECURE_FLASH_SEL_75M;
1363 else
1364 src_clk = HCLK_SECURE_FLASH_SEL_24M;
1365 break;
1366 case CLK_CRYPTO_NS_CORE:
1367 mask = CLK_CRYPTO_CORE_SEL_MASK;
1368 shift = CLK_CRYPTO_CORE_SEL_SHIFT;
1369 if (rate == 200 * MHz)
1370 src_clk = CLK_CRYPTO_CORE_SEL_200M;
1371 else if (rate == 150 * MHz)
1372 src_clk = CLK_CRYPTO_CORE_SEL_150M;
1373 else
1374 src_clk = CLK_CRYPTO_CORE_SEL_100M;
1375 break;
1376 case CLK_CRYPTO_NS_PKA:
1377 mask = CLK_CRYPTO_PKA_SEL_MASK;
1378 shift = CLK_CRYPTO_PKA_SEL_SHIFT;
1379 if (rate == 300 * MHz)
1380 src_clk = CLK_CRYPTO_PKA_SEL_300M;
1381 else if (rate == 200 * MHz)
1382 src_clk = CLK_CRYPTO_PKA_SEL_200M;
1383 else
1384 src_clk = CLK_CRYPTO_PKA_SEL_100M;
1385 break;
1386 default:
1387 return -ENOENT;
1388 }
1389
1390 rk_clrsetreg(&cru->clksel_con[27], mask, src_clk << shift);
1391
1392 return rk3568_crypto_get_rate(priv, clk_id);
1393}
1394
1395static ulong rk3568_sdmmc_get_clk(struct rk3568_clk_priv *priv, ulong clk_id)
1396{
1397 struct rk3568_cru *cru = priv->cru;
1398 u32 sel, con;
1399
1400 switch (clk_id) {
1401 case HCLK_SDMMC0:
1402 case CLK_SDMMC0:
1403 con = readl(&cru->clksel_con[30]);
1404 sel = (con & CLK_SDMMC0_SEL_MASK) >> CLK_SDMMC0_SEL_SHIFT;
1405 break;
1406 case CLK_SDMMC1:
1407 con = readl(&cru->clksel_con[30]);
1408 sel = (con & CLK_SDMMC1_SEL_MASK) >> CLK_SDMMC1_SEL_SHIFT;
1409 break;
1410 case CLK_SDMMC2:
1411 con = readl(&cru->clksel_con[32]);
1412 sel = (con & CLK_SDMMC2_SEL_MASK) >> CLK_SDMMC2_SEL_SHIFT;
1413 break;
1414 default:
1415 return -ENOENT;
1416 }
1417
1418 switch (sel) {
1419 case CLK_SDMMC_SEL_24M:
1420 return OSC_HZ;
1421 case CLK_SDMMC_SEL_400M:
1422 return 400 * MHz;
1423 case CLK_SDMMC_SEL_300M:
1424 return 300 * MHz;
1425 case CLK_SDMMC_SEL_100M:
1426 return 100 * MHz;
1427 case CLK_SDMMC_SEL_50M:
1428 return 50 * MHz;
1429 case CLK_SDMMC_SEL_750K:
1430 return 750 * KHz;
1431 default:
1432 return -ENOENT;
1433 }
1434}
1435
1436static ulong rk3568_sdmmc_set_clk(struct rk3568_clk_priv *priv,
1437 ulong clk_id, ulong rate)
1438{
1439 struct rk3568_cru *cru = priv->cru;
1440 int src_clk;
1441
1442 switch (rate) {
1443 case OSC_HZ:
Elaine Zhangf2cdd442021-10-12 16:43:00 +08001444 case 26 * MHz:
Vasily Khoruzhickf0eb3652023-02-23 13:03:32 -08001445 case 25 * MHz:
Elaine Zhang4a262fe2021-06-02 11:39:24 +08001446 src_clk = CLK_SDMMC_SEL_24M;
1447 break;
1448 case 400 * MHz:
1449 src_clk = CLK_SDMMC_SEL_400M;
1450 break;
1451 case 300 * MHz:
1452 src_clk = CLK_SDMMC_SEL_300M;
1453 break;
1454 case 100 * MHz:
1455 src_clk = CLK_SDMMC_SEL_100M;
1456 break;
1457 case 52 * MHz:
1458 case 50 * MHz:
1459 src_clk = CLK_SDMMC_SEL_50M;
1460 break;
1461 case 750 * KHz:
1462 case 400 * KHz:
1463 src_clk = CLK_SDMMC_SEL_750K;
1464 break;
1465 default:
1466 return -ENOENT;
1467 }
1468
1469 switch (clk_id) {
1470 case HCLK_SDMMC0:
1471 case CLK_SDMMC0:
1472 rk_clrsetreg(&cru->clksel_con[30],
1473 CLK_SDMMC0_SEL_MASK,
1474 src_clk << CLK_SDMMC0_SEL_SHIFT);
1475 break;
1476 case CLK_SDMMC1:
1477 rk_clrsetreg(&cru->clksel_con[30],
1478 CLK_SDMMC1_SEL_MASK,
1479 src_clk << CLK_SDMMC1_SEL_SHIFT);
1480 break;
1481 case CLK_SDMMC2:
1482 rk_clrsetreg(&cru->clksel_con[32],
1483 CLK_SDMMC2_SEL_MASK,
1484 src_clk << CLK_SDMMC2_SEL_SHIFT);
1485 break;
1486 default:
1487 return -ENOENT;
1488 }
1489
1490 return rk3568_sdmmc_get_clk(priv, clk_id);
1491}
1492
1493static ulong rk3568_sfc_get_clk(struct rk3568_clk_priv *priv)
1494{
1495 struct rk3568_cru *cru = priv->cru;
1496 u32 sel, con;
1497
1498 con = readl(&cru->clksel_con[28]);
1499 sel = (con & SCLK_SFC_SEL_MASK) >> SCLK_SFC_SEL_SHIFT;
1500 switch (sel) {
1501 case SCLK_SFC_SEL_24M:
1502 return OSC_HZ;
1503 case SCLK_SFC_SEL_50M:
1504 return 50 * MHz;
1505 case SCLK_SFC_SEL_75M:
1506 return 75 * MHz;
1507 case SCLK_SFC_SEL_100M:
1508 return 100 * MHz;
1509 case SCLK_SFC_SEL_125M:
1510 return 125 * MHz;
1511 case SCLK_SFC_SEL_150M:
Elaine Zhangf2cdd442021-10-12 16:43:00 +08001512 return 150 * MHz;
Elaine Zhang4a262fe2021-06-02 11:39:24 +08001513 default:
1514 return -ENOENT;
1515 }
1516}
1517
1518static ulong rk3568_sfc_set_clk(struct rk3568_clk_priv *priv, ulong rate)
1519{
1520 struct rk3568_cru *cru = priv->cru;
1521 int src_clk;
1522
1523 switch (rate) {
1524 case OSC_HZ:
1525 src_clk = SCLK_SFC_SEL_24M;
1526 break;
1527 case 50 * MHz:
1528 src_clk = SCLK_SFC_SEL_50M;
1529 break;
1530 case 75 * MHz:
1531 src_clk = SCLK_SFC_SEL_75M;
1532 break;
1533 case 100 * MHz:
1534 src_clk = SCLK_SFC_SEL_100M;
1535 break;
1536 case 125 * MHz:
1537 src_clk = SCLK_SFC_SEL_125M;
1538 break;
Elaine Zhangf2cdd442021-10-12 16:43:00 +08001539 case 150 * MHz:
Elaine Zhang4a262fe2021-06-02 11:39:24 +08001540 src_clk = SCLK_SFC_SEL_150M;
1541 break;
1542 default:
1543 return -ENOENT;
1544 }
1545
1546 rk_clrsetreg(&cru->clksel_con[28],
1547 SCLK_SFC_SEL_MASK,
1548 src_clk << SCLK_SFC_SEL_SHIFT);
1549
1550 return rk3568_sfc_get_clk(priv);
1551}
1552
1553static ulong rk3568_nand_get_clk(struct rk3568_clk_priv *priv)
1554{
1555 struct rk3568_cru *cru = priv->cru;
1556 u32 sel, con;
1557
1558 con = readl(&cru->clksel_con[28]);
1559 sel = (con & NCLK_NANDC_SEL_MASK) >> NCLK_NANDC_SEL_SHIFT;
1560 switch (sel) {
1561 case NCLK_NANDC_SEL_200M:
1562 return 200 * MHz;
1563 case NCLK_NANDC_SEL_150M:
1564 return 150 * MHz;
1565 case NCLK_NANDC_SEL_100M:
1566 return 100 * MHz;
1567 case NCLK_NANDC_SEL_24M:
1568 return OSC_HZ;
1569 default:
1570 return -ENOENT;
1571 }
1572}
1573
1574static ulong rk3568_nand_set_clk(struct rk3568_clk_priv *priv, ulong rate)
1575{
1576 struct rk3568_cru *cru = priv->cru;
1577 int src_clk;
1578
1579 switch (rate) {
1580 case OSC_HZ:
1581 src_clk = NCLK_NANDC_SEL_24M;
1582 break;
1583 case 100 * MHz:
1584 src_clk = NCLK_NANDC_SEL_100M;
1585 break;
1586 case 150 * MHz:
1587 src_clk = NCLK_NANDC_SEL_150M;
1588 break;
1589 case 200 * MHz:
1590 src_clk = NCLK_NANDC_SEL_200M;
1591 break;
1592 default:
1593 return -ENOENT;
1594 }
1595
1596 rk_clrsetreg(&cru->clksel_con[28],
1597 NCLK_NANDC_SEL_MASK,
1598 src_clk << NCLK_NANDC_SEL_SHIFT);
1599
1600 return rk3568_nand_get_clk(priv);
1601}
1602
1603static ulong rk3568_emmc_get_clk(struct rk3568_clk_priv *priv)
1604{
1605 struct rk3568_cru *cru = priv->cru;
1606 u32 sel, con;
1607
1608 con = readl(&cru->clksel_con[28]);
1609 sel = (con & CCLK_EMMC_SEL_MASK) >> CCLK_EMMC_SEL_SHIFT;
1610 switch (sel) {
1611 case CCLK_EMMC_SEL_200M:
1612 return 200 * MHz;
1613 case CCLK_EMMC_SEL_150M:
1614 return 150 * MHz;
1615 case CCLK_EMMC_SEL_100M:
1616 return 100 * MHz;
1617 case CCLK_EMMC_SEL_50M:
1618 return 50 * MHz;
1619 case CCLK_EMMC_SEL_375K:
1620 return 375 * KHz;
1621 case CCLK_EMMC_SEL_24M:
1622 return OSC_HZ;
1623 default:
1624 return -ENOENT;
1625 }
1626}
1627
1628static ulong rk3568_emmc_set_clk(struct rk3568_clk_priv *priv, ulong rate)
1629{
1630 struct rk3568_cru *cru = priv->cru;
1631 int src_clk;
1632
1633 switch (rate) {
1634 case OSC_HZ:
Vasily Khoruzhickf0eb3652023-02-23 13:03:32 -08001635 case 26 * MHz:
1636 case 25 * MHz:
Elaine Zhang4a262fe2021-06-02 11:39:24 +08001637 src_clk = CCLK_EMMC_SEL_24M;
1638 break;
1639 case 52 * MHz:
1640 case 50 * MHz:
1641 src_clk = CCLK_EMMC_SEL_50M;
1642 break;
1643 case 100 * MHz:
1644 src_clk = CCLK_EMMC_SEL_100M;
1645 break;
1646 case 150 * MHz:
1647 src_clk = CCLK_EMMC_SEL_150M;
1648 break;
1649 case 200 * MHz:
1650 src_clk = CCLK_EMMC_SEL_200M;
1651 break;
1652 case 400 * KHz:
1653 case 375 * KHz:
1654 src_clk = CCLK_EMMC_SEL_375K;
1655 break;
1656 default:
1657 return -ENOENT;
1658 }
1659
1660 rk_clrsetreg(&cru->clksel_con[28],
1661 CCLK_EMMC_SEL_MASK,
1662 src_clk << CCLK_EMMC_SEL_SHIFT);
1663
1664 return rk3568_emmc_get_clk(priv);
1665}
1666
1667static ulong rk3568_emmc_get_bclk(struct rk3568_clk_priv *priv)
1668{
1669 struct rk3568_cru *cru = priv->cru;
1670 u32 sel, con;
1671
1672 con = readl(&cru->clksel_con[28]);
1673 sel = (con & BCLK_EMMC_SEL_MASK) >> BCLK_EMMC_SEL_SHIFT;
1674 switch (sel) {
1675 case BCLK_EMMC_SEL_200M:
1676 return 200 * MHz;
1677 case BCLK_EMMC_SEL_150M:
1678 return 150 * MHz;
1679 case BCLK_EMMC_SEL_125M:
1680 return 125 * MHz;
1681 default:
1682 return -ENOENT;
1683 }
1684}
1685
1686static ulong rk3568_emmc_set_bclk(struct rk3568_clk_priv *priv, ulong rate)
1687{
1688 struct rk3568_cru *cru = priv->cru;
1689 int src_clk;
1690
1691 switch (rate) {
1692 case 200 * MHz:
1693 src_clk = BCLK_EMMC_SEL_200M;
1694 break;
1695 case 150 * MHz:
1696 src_clk = BCLK_EMMC_SEL_150M;
1697 break;
1698 case 125 * MHz:
1699 src_clk = BCLK_EMMC_SEL_125M;
1700 break;
1701 default:
1702 return -ENOENT;
1703 }
1704
1705 rk_clrsetreg(&cru->clksel_con[28],
1706 BCLK_EMMC_SEL_MASK,
1707 src_clk << BCLK_EMMC_SEL_SHIFT);
1708
1709 return rk3568_emmc_get_bclk(priv);
1710}
1711
1712#ifndef CONFIG_SPL_BUILD
1713static ulong rk3568_aclk_vop_get_clk(struct rk3568_clk_priv *priv)
1714{
1715 struct rk3568_cru *cru = priv->cru;
1716 u32 div, sel, con, parent;
1717
1718 con = readl(&cru->clksel_con[38]);
1719 div = (con & ACLK_VOP_PRE_DIV_MASK) >> ACLK_VOP_PRE_DIV_SHIFT;
1720 sel = (con & ACLK_VOP_PRE_SEL_MASK) >> ACLK_VOP_PRE_SEL_SHIFT;
1721 if (sel == ACLK_VOP_PRE_SEL_GPLL)
1722 parent = priv->gpll_hz;
1723 else if (sel == ACLK_VOP_PRE_SEL_CPLL)
1724 parent = priv->cpll_hz;
1725 else if (sel == ACLK_VOP_PRE_SEL_VPLL)
1726 parent = priv->vpll_hz;
1727 else
1728 parent = priv->hpll_hz;
1729
1730 return DIV_TO_RATE(parent, div);
1731}
1732
1733static ulong rk3568_aclk_vop_set_clk(struct rk3568_clk_priv *priv, ulong rate)
1734{
1735 struct rk3568_cru *cru = priv->cru;
1736 int src_clk_div, src_clk_mux;
1737
1738 if ((priv->cpll_hz % rate) == 0) {
1739 src_clk_div = DIV_ROUND_UP(priv->cpll_hz, rate);
1740 src_clk_mux = ACLK_VOP_PRE_SEL_CPLL;
1741 } else {
1742 src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
1743 src_clk_mux = ACLK_VOP_PRE_SEL_GPLL;
1744 }
1745 assert(src_clk_div - 1 <= 31);
1746 rk_clrsetreg(&cru->clksel_con[38],
1747 ACLK_VOP_PRE_SEL_MASK | ACLK_VOP_PRE_DIV_MASK,
1748 src_clk_mux << ACLK_VOP_PRE_SEL_SHIFT |
1749 (src_clk_div - 1) << ACLK_VOP_PRE_DIV_SHIFT);
1750
1751 return rk3568_aclk_vop_get_clk(priv);
1752}
1753
1754static ulong rk3568_dclk_vop_get_clk(struct rk3568_clk_priv *priv, ulong clk_id)
1755{
1756 struct rk3568_cru *cru = priv->cru;
1757 u32 conid, div, sel, con, parent;
1758
1759 switch (clk_id) {
1760 case DCLK_VOP0:
1761 conid = 39;
1762 break;
1763 case DCLK_VOP1:
1764 conid = 40;
1765 break;
1766 case DCLK_VOP2:
1767 conid = 41;
1768 break;
1769 default:
1770 return -ENOENT;
1771 }
1772
1773 con = readl(&cru->clksel_con[conid]);
1774 div = (con & DCLK0_VOP_DIV_MASK) >> DCLK0_VOP_DIV_SHIFT;
1775 sel = (con & DCLK0_VOP_SEL_MASK) >> DCLK0_VOP_SEL_SHIFT;
1776 if (sel == DCLK_VOP_SEL_HPLL)
1777 parent = rk3568_pmu_pll_get_rate(priv, HPLL);
1778 else if (sel == DCLK_VOP_SEL_VPLL)
1779 parent = rockchip_pll_get_rate(&rk3568_pll_clks[VPLL],
1780 priv->cru, VPLL);
1781 else if (sel == DCLK_VOP_SEL_GPLL)
1782 parent = priv->gpll_hz;
1783 else if (sel == DCLK_VOP_SEL_CPLL)
1784 parent = priv->cpll_hz;
1785 else
1786 return -ENOENT;
1787
1788 return DIV_TO_RATE(parent, div);
1789}
1790
1791#define RK3568_VOP_PLL_LIMIT_FREQ 600000000
1792
1793static ulong rk3568_dclk_vop_set_clk(struct rk3568_clk_priv *priv,
1794 ulong clk_id, ulong rate)
1795{
1796 struct rk3568_cru *cru = priv->cru;
1797 ulong pll_rate, now, best_rate = 0;
1798 u32 i, conid, con, sel, div, best_div = 0, best_sel = 0;
1799
1800 switch (clk_id) {
1801 case DCLK_VOP0:
1802 conid = 39;
1803 break;
1804 case DCLK_VOP1:
1805 conid = 40;
1806 break;
1807 case DCLK_VOP2:
1808 conid = 41;
1809 break;
1810 default:
1811 return -ENOENT;
1812 }
1813
1814 con = readl(&cru->clksel_con[conid]);
1815 sel = (con & DCLK0_VOP_SEL_MASK) >> DCLK0_VOP_SEL_SHIFT;
1816
1817 if (sel == DCLK_VOP_SEL_HPLL) {
1818 div = 1;
1819 rk_clrsetreg(&cru->clksel_con[conid],
1820 DCLK0_VOP_DIV_MASK | DCLK0_VOP_SEL_MASK,
1821 (DCLK_VOP_SEL_HPLL << DCLK0_VOP_SEL_SHIFT) |
1822 ((div - 1) << DCLK0_VOP_DIV_SHIFT));
1823 rk3568_pmu_pll_set_rate(priv, HPLL, div * rate);
1824 } else if (sel == DCLK_VOP_SEL_VPLL) {
1825 div = DIV_ROUND_UP(RK3568_VOP_PLL_LIMIT_FREQ, rate);
1826 rk_clrsetreg(&cru->clksel_con[conid],
1827 DCLK0_VOP_DIV_MASK | DCLK0_VOP_SEL_MASK,
1828 (DCLK_VOP_SEL_VPLL << DCLK0_VOP_SEL_SHIFT) |
1829 ((div - 1) << DCLK0_VOP_DIV_SHIFT));
1830 rockchip_pll_set_rate(&rk3568_pll_clks[VPLL],
1831 priv->cru, VPLL, div * rate);
1832 } else {
1833 for (i = 0; i <= DCLK_VOP_SEL_CPLL; i++) {
1834 switch (i) {
1835 case DCLK_VOP_SEL_GPLL:
1836 pll_rate = priv->gpll_hz;
1837 break;
1838 case DCLK_VOP_SEL_CPLL:
1839 pll_rate = priv->cpll_hz;
1840 break;
1841 default:
1842 printf("do not support this vop pll sel\n");
1843 return -EINVAL;
1844 }
1845
1846 div = DIV_ROUND_UP(pll_rate, rate);
1847 if (div > 255)
1848 continue;
1849 now = pll_rate / div;
1850 if (abs(rate - now) < abs(rate - best_rate)) {
1851 best_rate = now;
1852 best_div = div;
1853 best_sel = i;
1854 }
1855 debug("p_rate=%lu, best_rate=%lu, div=%u, sel=%u\n",
1856 pll_rate, best_rate, best_div, best_sel);
1857 }
1858
1859 if (best_rate) {
1860 rk_clrsetreg(&cru->clksel_con[conid],
1861 DCLK0_VOP_DIV_MASK | DCLK0_VOP_SEL_MASK,
1862 best_sel << DCLK0_VOP_SEL_SHIFT |
1863 (best_div - 1) << DCLK0_VOP_DIV_SHIFT);
1864 } else {
1865 printf("do not support this vop freq %lu\n", rate);
1866 return -EINVAL;
1867 }
1868 }
1869 return rk3568_dclk_vop_get_clk(priv, clk_id);
1870}
1871
1872static ulong rk3568_gmac_src_get_clk(struct rk3568_clk_priv *priv,
1873 ulong mac_id)
1874{
1875 struct rk3568_cru *cru = priv->cru;
1876 u32 sel, con;
1877
1878 con = readl(&cru->clksel_con[31 + mac_id * 2]);
1879 sel = (con & CLK_MAC0_2TOP_SEL_MASK) >> CLK_MAC0_2TOP_SEL_SHIFT;
1880
1881 switch (sel) {
1882 case CLK_MAC0_2TOP_SEL_125M:
1883 return 125 * MHz;
1884 case CLK_MAC0_2TOP_SEL_50M:
1885 return 50 * MHz;
1886 case CLK_MAC0_2TOP_SEL_25M:
1887 return 25 * MHz;
1888 case CLK_MAC0_2TOP_SEL_PPLL:
1889 return rk3568_pmu_pll_get_rate(priv, HPLL);
1890 default:
1891 return -ENOENT;
1892 }
1893}
1894
1895static ulong rk3568_gmac_src_set_clk(struct rk3568_clk_priv *priv,
1896 ulong mac_id, ulong rate)
1897{
1898 struct rk3568_cru *cru = priv->cru;
1899 int src_clk;
1900
1901 switch (rate) {
1902 case 125 * MHz:
1903 src_clk = CLK_MAC0_2TOP_SEL_125M;
1904 break;
1905 case 50 * MHz:
1906 src_clk = CLK_MAC0_2TOP_SEL_50M;
1907 break;
1908 case 25 * MHz:
1909 src_clk = CLK_MAC0_2TOP_SEL_25M;
1910 break;
1911 default:
1912 return -ENOENT;
1913 }
1914
1915 rk_clrsetreg(&cru->clksel_con[31 + mac_id * 2],
1916 CLK_MAC0_2TOP_SEL_MASK,
1917 src_clk << CLK_MAC0_2TOP_SEL_SHIFT);
1918
1919 return rk3568_gmac_src_get_clk(priv, mac_id);
1920}
1921
1922static ulong rk3568_gmac_out_get_clk(struct rk3568_clk_priv *priv,
1923 ulong mac_id)
1924{
1925 struct rk3568_cru *cru = priv->cru;
1926 u32 sel, con;
1927
1928 con = readl(&cru->clksel_con[31 + mac_id * 2]);
1929 sel = (con & CLK_MAC0_OUT_SEL_MASK) >> CLK_MAC0_OUT_SEL_SHIFT;
1930
1931 switch (sel) {
1932 case CLK_MAC0_OUT_SEL_125M:
1933 return 125 * MHz;
1934 case CLK_MAC0_OUT_SEL_50M:
1935 return 50 * MHz;
1936 case CLK_MAC0_OUT_SEL_25M:
1937 return 25 * MHz;
1938 case CLK_MAC0_OUT_SEL_24M:
1939 return OSC_HZ;
1940 default:
1941 return -ENOENT;
1942 }
1943}
1944
1945static ulong rk3568_gmac_out_set_clk(struct rk3568_clk_priv *priv,
1946 ulong mac_id, ulong rate)
1947{
1948 struct rk3568_cru *cru = priv->cru;
1949 int src_clk;
1950
1951 switch (rate) {
1952 case 125 * MHz:
1953 src_clk = CLK_MAC0_OUT_SEL_125M;
1954 break;
1955 case 50 * MHz:
1956 src_clk = CLK_MAC0_OUT_SEL_50M;
1957 break;
1958 case 25 * MHz:
1959 src_clk = CLK_MAC0_OUT_SEL_25M;
1960 break;
1961 case 24 * MHz:
1962 src_clk = CLK_MAC0_OUT_SEL_24M;
1963 break;
1964 default:
1965 return -ENOENT;
1966 }
1967
1968 rk_clrsetreg(&cru->clksel_con[31 + mac_id * 2],
1969 CLK_MAC0_OUT_SEL_MASK,
1970 src_clk << CLK_MAC0_OUT_SEL_SHIFT);
1971
1972 return rk3568_gmac_out_get_clk(priv, mac_id);
1973}
1974
1975static ulong rk3568_gmac_ptp_ref_get_clk(struct rk3568_clk_priv *priv,
1976 ulong mac_id)
1977{
1978 struct rk3568_cru *cru = priv->cru;
1979 u32 sel, con;
1980
1981 con = readl(&cru->clksel_con[31 + mac_id * 2]);
1982 sel = (con & CLK_GMAC0_PTP_REF_SEL_MASK) >> CLK_GMAC0_PTP_REF_SEL_SHIFT;
1983
1984 switch (sel) {
1985 case CLK_GMAC0_PTP_REF_SEL_62_5M:
1986 return 62500 * KHz;
1987 case CLK_GMAC0_PTP_REF_SEL_100M:
1988 return 100 * MHz;
1989 case CLK_GMAC0_PTP_REF_SEL_50M:
1990 return 50 * MHz;
1991 case CLK_GMAC0_PTP_REF_SEL_24M:
1992 return OSC_HZ;
1993 default:
1994 return -ENOENT;
1995 }
1996}
1997
1998static ulong rk3568_gmac_ptp_ref_set_clk(struct rk3568_clk_priv *priv,
1999 ulong mac_id, ulong rate)
2000{
2001 struct rk3568_cru *cru = priv->cru;
2002 int src_clk;
2003
2004 switch (rate) {
2005 case 62500 * KHz:
2006 src_clk = CLK_GMAC0_PTP_REF_SEL_62_5M;
2007 break;
2008 case 100 * MHz:
2009 src_clk = CLK_GMAC0_PTP_REF_SEL_100M;
2010 break;
2011 case 50 * MHz:
2012 src_clk = CLK_GMAC0_PTP_REF_SEL_50M;
2013 break;
2014 case 24 * MHz:
2015 src_clk = CLK_GMAC0_PTP_REF_SEL_24M;
2016 break;
2017 default:
2018 return -ENOENT;
2019 }
2020
2021 rk_clrsetreg(&cru->clksel_con[31 + mac_id * 2],
2022 CLK_GMAC0_PTP_REF_SEL_MASK,
2023 src_clk << CLK_GMAC0_PTP_REF_SEL_SHIFT);
2024
2025 return rk3568_gmac_ptp_ref_get_clk(priv, mac_id);
2026}
2027
2028static ulong rk3568_gmac_tx_rx_set_clk(struct rk3568_clk_priv *priv,
2029 ulong mac_id, ulong rate)
2030{
2031 struct rk3568_cru *cru = priv->cru;
2032 u32 con, sel, div_sel;
2033
2034 con = readl(&cru->clksel_con[31 + mac_id * 2]);
2035 sel = (con & RMII0_MODE_MASK) >> RMII0_MODE_SHIFT;
2036
2037 if (sel == RMII0_MODE_SEL_RGMII) {
2038 if (rate == 2500000)
2039 div_sel = RGMII0_CLK_SEL_2_5M;
2040 else if (rate == 25000000)
2041 div_sel = RGMII0_CLK_SEL_25M;
2042 else
2043 div_sel = RGMII0_CLK_SEL_125M;
2044 rk_clrsetreg(&cru->clksel_con[31 + mac_id * 2],
2045 RGMII0_CLK_SEL_MASK,
2046 div_sel << RGMII0_CLK_SEL_SHIFT);
2047 } else if (sel == RMII0_MODE_SEL_RMII) {
2048 if (rate == 2500000)
2049 div_sel = RMII0_CLK_SEL_2_5M;
2050 else
2051 div_sel = RMII0_CLK_SEL_25M;
2052 rk_clrsetreg(&cru->clksel_con[31 + mac_id * 2],
2053 RMII0_CLK_SEL_MASK,
2054 div_sel << RMII0_CLK_SEL_SHIFT);
2055 }
2056
2057 return 0;
2058}
2059
2060static ulong rk3568_ebc_get_clk(struct rk3568_clk_priv *priv)
2061{
2062 struct rk3568_cru *cru = priv->cru;
2063 u32 con, div, p_rate;
2064
2065 con = readl(&cru->clksel_con[79]);
2066 div = (con & CPLL_333M_DIV_MASK) >> CPLL_333M_DIV_SHIFT;
2067 p_rate = DIV_TO_RATE(priv->cpll_hz, div);
2068
2069 con = readl(&cru->clksel_con[43]);
2070 div = (con & DCLK_EBC_SEL_MASK) >> DCLK_EBC_SEL_SHIFT;
2071 switch (div) {
2072 case DCLK_EBC_SEL_GPLL_400M:
2073 return 400 * MHz;
2074 case DCLK_EBC_SEL_CPLL_333M:
2075 return p_rate;
2076 case DCLK_EBC_SEL_GPLL_200M:
2077 return 200 * MHz;
2078 default:
2079 return -ENOENT;
2080 }
2081}
2082
2083static ulong rk3568_ebc_set_clk(struct rk3568_clk_priv *priv, ulong rate)
2084{
2085 struct rk3568_cru *cru = priv->cru;
2086 int src_clk_div;
2087
2088 src_clk_div = DIV_ROUND_UP(priv->cpll_hz, rate);
2089 assert(src_clk_div - 1 <= 31);
2090 rk_clrsetreg(&cru->clksel_con[79],
2091 CPLL_333M_DIV_MASK,
2092 (src_clk_div - 1) << CPLL_333M_DIV_SHIFT);
2093 rk_clrsetreg(&cru->clksel_con[43],
2094 DCLK_EBC_SEL_MASK,
2095 DCLK_EBC_SEL_CPLL_333M << DCLK_EBC_SEL_SHIFT);
2096
2097 return rk3568_ebc_get_clk(priv);
2098}
2099
2100static ulong rk3568_rkvdec_get_clk(struct rk3568_clk_priv *priv, ulong clk_id)
2101{
2102 struct rk3568_cru *cru = priv->cru;
2103 u32 con, div, src, p_rate;
2104
2105 switch (clk_id) {
2106 case ACLK_RKVDEC_PRE:
2107 case ACLK_RKVDEC:
2108 con = readl(&cru->clksel_con[47]);
2109 src = (con & ACLK_RKVDEC_SEL_MASK) >> ACLK_RKVDEC_SEL_SHIFT;
2110 div = (con & ACLK_RKVDEC_DIV_MASK) >> ACLK_RKVDEC_DIV_SHIFT;
2111 if (src == ACLK_RKVDEC_SEL_CPLL)
2112 p_rate = priv->cpll_hz;
2113 else
2114 p_rate = priv->gpll_hz;
2115 return DIV_TO_RATE(p_rate, div);
2116 case CLK_RKVDEC_CORE:
2117 con = readl(&cru->clksel_con[49]);
2118 src = (con & CLK_RKVDEC_CORE_SEL_MASK)
2119 >> CLK_RKVDEC_CORE_SEL_SHIFT;
2120 div = (con & CLK_RKVDEC_CORE_DIV_MASK)
2121 >> CLK_RKVDEC_CORE_DIV_SHIFT;
2122 if (src == CLK_RKVDEC_CORE_SEL_CPLL)
2123 p_rate = priv->cpll_hz;
2124 else if (src == CLK_RKVDEC_CORE_SEL_NPLL)
2125 p_rate = priv->npll_hz;
2126 else if (src == CLK_RKVDEC_CORE_SEL_VPLL)
2127 p_rate = priv->vpll_hz;
2128 else
2129 p_rate = priv->gpll_hz;
2130 return DIV_TO_RATE(p_rate, div);
2131 default:
2132 return -ENOENT;
2133 }
2134}
2135
2136static ulong rk3568_rkvdec_set_clk(struct rk3568_clk_priv *priv,
2137 ulong clk_id, ulong rate)
2138{
2139 struct rk3568_cru *cru = priv->cru;
2140 int src_clk_div, src, p_rate;
2141
2142 switch (clk_id) {
2143 case ACLK_RKVDEC_PRE:
2144 case ACLK_RKVDEC:
2145 src = (readl(&cru->clksel_con[47]) & ACLK_RKVDEC_SEL_MASK)
2146 >> ACLK_RKVDEC_SEL_SHIFT;
2147 if (src == ACLK_RKVDEC_SEL_CPLL)
2148 p_rate = priv->cpll_hz;
2149 else
2150 p_rate = priv->gpll_hz;
2151 src_clk_div = DIV_ROUND_UP(p_rate, rate);
2152 assert(src_clk_div - 1 <= 31);
2153 rk_clrsetreg(&cru->clksel_con[47],
2154 ACLK_RKVDEC_SEL_MASK |
2155 ACLK_RKVDEC_DIV_MASK,
2156 (src << ACLK_RKVDEC_SEL_SHIFT) |
2157 (src_clk_div - 1) << ACLK_RKVDEC_DIV_SHIFT);
2158 break;
2159 case CLK_RKVDEC_CORE:
2160 src = (readl(&cru->clksel_con[49]) & CLK_RKVDEC_CORE_SEL_MASK)
2161 >> CLK_RKVDEC_CORE_SEL_SHIFT;
2162 if (src == CLK_RKVDEC_CORE_SEL_CPLL)
2163 p_rate = priv->cpll_hz;
2164 else if (src == CLK_RKVDEC_CORE_SEL_NPLL)
2165 p_rate = priv->npll_hz;
2166 else if (src == CLK_RKVDEC_CORE_SEL_VPLL)
2167 p_rate = priv->vpll_hz;
2168 else
2169 p_rate = priv->gpll_hz;
2170 src_clk_div = DIV_ROUND_UP(p_rate, rate);
2171 assert(src_clk_div - 1 <= 31);
2172 rk_clrsetreg(&cru->clksel_con[49],
2173 CLK_RKVDEC_CORE_SEL_MASK |
2174 CLK_RKVDEC_CORE_DIV_MASK,
2175 (src << CLK_RKVDEC_CORE_SEL_SHIFT) |
2176 (src_clk_div - 1) << CLK_RKVDEC_CORE_DIV_SHIFT);
2177 break;
2178 default:
2179 return -ENOENT;
2180 }
2181
2182 return rk3568_rkvdec_get_clk(priv, clk_id);
2183}
2184
2185static ulong rk3568_uart_get_rate(struct rk3568_clk_priv *priv, ulong clk_id)
2186{
2187 struct rk3568_cru *cru = priv->cru;
2188 u32 reg, con, fracdiv, div, src, p_src, p_rate;
2189 unsigned long m, n;
2190
2191 switch (clk_id) {
2192 case SCLK_UART1:
2193 reg = 52;
2194 break;
2195 case SCLK_UART2:
2196 reg = 54;
2197 break;
2198 case SCLK_UART3:
2199 reg = 56;
2200 break;
2201 case SCLK_UART4:
2202 reg = 58;
2203 break;
2204 case SCLK_UART5:
2205 reg = 60;
2206 break;
2207 case SCLK_UART6:
2208 reg = 62;
2209 break;
2210 case SCLK_UART7:
2211 reg = 64;
2212 break;
2213 case SCLK_UART8:
2214 reg = 66;
2215 break;
2216 case SCLK_UART9:
2217 reg = 68;
2218 break;
2219 default:
2220 return -ENOENT;
2221 }
2222 con = readl(&cru->clksel_con[reg]);
2223 src = (con & CLK_UART_SEL_MASK) >> CLK_UART_SEL_SHIFT;
2224 div = (con & CLK_UART_SRC_DIV_MASK) >> CLK_UART_SRC_DIV_SHIFT;
2225 p_src = (con & CLK_UART_SRC_SEL_MASK) >> CLK_UART_SRC_SEL_SHIFT;
2226 if (p_src == CLK_UART_SRC_SEL_GPLL)
2227 p_rate = priv->gpll_hz;
2228 else if (p_src == CLK_UART_SRC_SEL_CPLL)
2229 p_rate = priv->cpll_hz;
2230 else
2231 p_rate = 480000000;
2232 if (src == CLK_UART_SEL_SRC) {
2233 return DIV_TO_RATE(p_rate, div);
2234 } else if (src == CLK_UART_SEL_FRAC) {
2235 fracdiv = readl(&cru->clksel_con[reg + 1]);
2236 n = fracdiv & CLK_UART_FRAC_NUMERATOR_MASK;
2237 n >>= CLK_UART_FRAC_NUMERATOR_SHIFT;
2238 m = fracdiv & CLK_UART_FRAC_DENOMINATOR_MASK;
2239 m >>= CLK_UART_FRAC_DENOMINATOR_SHIFT;
2240 return DIV_TO_RATE(p_rate, div) * n / m;
2241 } else {
2242 return OSC_HZ;
2243 }
2244}
2245
2246static ulong rk3568_uart_set_rate(struct rk3568_clk_priv *priv,
2247 ulong clk_id, ulong rate)
2248{
2249 struct rk3568_cru *cru = priv->cru;
2250 u32 reg, clk_src, uart_src, div;
2251 unsigned long m = 0, n = 0, val;
2252
2253 if (priv->gpll_hz % rate == 0) {
2254 clk_src = CLK_UART_SRC_SEL_GPLL;
2255 uart_src = CLK_UART_SEL_SRC;
2256 div = DIV_ROUND_UP(priv->gpll_hz, rate);
2257 } else if (priv->cpll_hz % rate == 0) {
2258 clk_src = CLK_UART_SRC_SEL_CPLL;
2259 uart_src = CLK_UART_SEL_SRC;
2260 div = DIV_ROUND_UP(priv->gpll_hz, rate);
2261 } else if (rate == OSC_HZ) {
2262 clk_src = CLK_UART_SRC_SEL_GPLL;
2263 uart_src = CLK_UART_SEL_XIN24M;
2264 div = 2;
2265 } else {
2266 clk_src = CLK_UART_SRC_SEL_GPLL;
2267 uart_src = CLK_UART_SEL_FRAC;
2268 div = 2;
2269 rational_best_approximation(rate, priv->gpll_hz / div,
2270 GENMASK(16 - 1, 0),
2271 GENMASK(16 - 1, 0),
2272 &m, &n);
2273 }
2274
2275 switch (clk_id) {
2276 case SCLK_UART1:
2277 reg = 52;
2278 break;
2279 case SCLK_UART2:
2280 reg = 54;
2281 break;
2282 case SCLK_UART3:
2283 reg = 56;
2284 break;
2285 case SCLK_UART4:
2286 reg = 58;
2287 break;
2288 case SCLK_UART5:
2289 reg = 60;
2290 break;
2291 case SCLK_UART6:
2292 reg = 62;
2293 break;
2294 case SCLK_UART7:
2295 reg = 64;
2296 break;
2297 case SCLK_UART8:
2298 reg = 66;
2299 break;
2300 case SCLK_UART9:
2301 reg = 68;
2302 break;
2303 default:
2304 return -ENOENT;
2305 }
2306 rk_clrsetreg(&cru->clksel_con[reg],
2307 CLK_UART_SEL_MASK | CLK_UART_SRC_SEL_MASK |
2308 CLK_UART_SRC_DIV_MASK,
2309 (clk_src << CLK_UART_SRC_SEL_SHIFT) |
2310 (uart_src << CLK_UART_SEL_SHIFT) |
2311 ((div - 1) << CLK_UART_SRC_DIV_SHIFT));
2312 if (m && n) {
2313 val = m << CLK_UART_FRAC_NUMERATOR_SHIFT | n;
2314 writel(val, &cru->clksel_con[reg + 1]);
2315 }
2316
2317 return rk3568_uart_get_rate(priv, clk_id);
2318}
2319#endif
2320
2321static ulong rk3568_clk_get_rate(struct clk *clk)
2322{
2323 struct rk3568_clk_priv *priv = dev_get_priv(clk->dev);
2324 ulong rate = 0;
2325
2326 if (!priv->gpll_hz) {
2327 printf("%s gpll=%lu\n", __func__, priv->gpll_hz);
2328 return -ENOENT;
2329 }
2330
2331 switch (clk->id) {
2332 case PLL_APLL:
2333 case ARMCLK:
2334 rate = rockchip_pll_get_rate(&rk3568_pll_clks[APLL], priv->cru,
2335 APLL);
2336 break;
2337 case PLL_CPLL:
2338 rate = rockchip_pll_get_rate(&rk3568_pll_clks[CPLL], priv->cru,
2339 CPLL);
2340 break;
2341 case PLL_GPLL:
2342 rate = rockchip_pll_get_rate(&rk3568_pll_clks[GPLL], priv->cru,
2343 GPLL);
2344 break;
2345 case PLL_NPLL:
2346 rate = rockchip_pll_get_rate(&rk3568_pll_clks[NPLL], priv->cru,
2347 NPLL);
2348 break;
2349 case PLL_VPLL:
2350 rate = rockchip_pll_get_rate(&rk3568_pll_clks[VPLL], priv->cru,
2351 VPLL);
2352 break;
2353 case PLL_DPLL:
2354 rate = rockchip_pll_get_rate(&rk3568_pll_clks[DPLL], priv->cru,
2355 DPLL);
2356 break;
2357 case ACLK_BUS:
2358 case PCLK_BUS:
2359 case PCLK_WDT_NS:
2360 rate = rk3568_bus_get_clk(priv, clk->id);
2361 break;
2362 case ACLK_PERIMID:
2363 case HCLK_PERIMID:
2364 rate = rk3568_perimid_get_clk(priv, clk->id);
2365 break;
2366 case ACLK_TOP_HIGH:
2367 case ACLK_TOP_LOW:
2368 case HCLK_TOP:
2369 case PCLK_TOP:
2370 rate = rk3568_top_get_clk(priv, clk->id);
2371 break;
2372 case CLK_I2C1:
2373 case CLK_I2C2:
2374 case CLK_I2C3:
2375 case CLK_I2C4:
2376 case CLK_I2C5:
2377 rate = rk3568_i2c_get_clk(priv, clk->id);
2378 break;
2379 case CLK_SPI0:
2380 case CLK_SPI1:
2381 case CLK_SPI2:
2382 case CLK_SPI3:
2383 rate = rk3568_spi_get_clk(priv, clk->id);
2384 break;
2385 case CLK_PWM1:
2386 case CLK_PWM2:
2387 case CLK_PWM3:
2388 rate = rk3568_pwm_get_clk(priv, clk->id);
2389 break;
2390 case CLK_SARADC:
2391 case CLK_TSADC_TSEN:
2392 case CLK_TSADC:
2393 rate = rk3568_adc_get_clk(priv, clk->id);
2394 break;
2395 case HCLK_SDMMC0:
2396 case CLK_SDMMC0:
2397 case CLK_SDMMC1:
2398 case CLK_SDMMC2:
2399 rate = rk3568_sdmmc_get_clk(priv, clk->id);
2400 break;
2401 case SCLK_SFC:
2402 rate = rk3568_sfc_get_clk(priv);
2403 break;
2404 case NCLK_NANDC:
2405 rate = rk3568_nand_get_clk(priv);
2406 break;
2407 case CCLK_EMMC:
2408 rate = rk3568_emmc_get_clk(priv);
2409 break;
2410 case BCLK_EMMC:
2411 rate = rk3568_emmc_get_bclk(priv);
2412 break;
Elaine Zhangf2cdd442021-10-12 16:43:00 +08002413 case TCLK_EMMC:
2414 rate = OSC_HZ;
2415 break;
Elaine Zhang4a262fe2021-06-02 11:39:24 +08002416#ifndef CONFIG_SPL_BUILD
2417 case ACLK_VOP:
2418 rate = rk3568_aclk_vop_get_clk(priv);
2419 break;
2420 case DCLK_VOP0:
2421 case DCLK_VOP1:
2422 case DCLK_VOP2:
2423 rate = rk3568_dclk_vop_get_clk(priv, clk->id);
2424 break;
2425 case SCLK_GMAC0:
2426 case CLK_MAC0_2TOP:
2427 case CLK_MAC0_REFOUT:
2428 rate = rk3568_gmac_src_get_clk(priv, 0);
2429 break;
2430 case CLK_MAC0_OUT:
2431 rate = rk3568_gmac_out_get_clk(priv, 0);
2432 break;
2433 case CLK_GMAC0_PTP_REF:
2434 rate = rk3568_gmac_ptp_ref_get_clk(priv, 0);
2435 break;
2436 case SCLK_GMAC1:
2437 case CLK_MAC1_2TOP:
2438 case CLK_MAC1_REFOUT:
2439 rate = rk3568_gmac_src_get_clk(priv, 1);
2440 break;
2441 case CLK_MAC1_OUT:
2442 rate = rk3568_gmac_out_get_clk(priv, 1);
2443 break;
2444 case CLK_GMAC1_PTP_REF:
2445 rate = rk3568_gmac_ptp_ref_get_clk(priv, 1);
2446 break;
2447 case DCLK_EBC:
2448 rate = rk3568_ebc_get_clk(priv);
2449 break;
2450 case ACLK_RKVDEC_PRE:
2451 case ACLK_RKVDEC:
2452 case CLK_RKVDEC_CORE:
2453 rate = rk3568_rkvdec_get_clk(priv, clk->id);
2454 break;
2455 case TCLK_WDT_NS:
2456 rate = OSC_HZ;
2457 break;
2458 case SCLK_UART1:
2459 case SCLK_UART2:
2460 case SCLK_UART3:
2461 case SCLK_UART4:
2462 case SCLK_UART5:
2463 case SCLK_UART6:
2464 case SCLK_UART7:
2465 case SCLK_UART8:
2466 case SCLK_UART9:
2467 rate = rk3568_uart_get_rate(priv, clk->id);
2468 break;
2469#endif
2470 case ACLK_SECURE_FLASH:
2471 case ACLK_CRYPTO_NS:
2472 case HCLK_SECURE_FLASH:
2473 case HCLK_CRYPTO_NS:
2474 case CLK_CRYPTO_NS_RNG:
2475 case CLK_CRYPTO_NS_CORE:
2476 case CLK_CRYPTO_NS_PKA:
2477 rate = rk3568_crypto_get_rate(priv, clk->id);
2478 break;
2479 case CPLL_500M:
2480 case CPLL_333M:
2481 case CPLL_250M:
2482 case CPLL_125M:
2483 case CPLL_100M:
2484 case CPLL_62P5M:
2485 case CPLL_50M:
2486 case CPLL_25M:
2487 rate = rk3568_cpll_div_get_rate(priv, clk->id);
2488 break;
2489 default:
2490 return -ENOENT;
2491 }
2492
2493 return rate;
2494};
2495
2496static ulong rk3568_clk_set_rate(struct clk *clk, ulong rate)
2497{
2498 struct rk3568_clk_priv *priv = dev_get_priv(clk->dev);
2499 ulong ret = 0;
2500
2501 if (!priv->gpll_hz) {
2502 printf("%s gpll=%lu\n", __func__, priv->gpll_hz);
2503 return -ENOENT;
2504 }
2505
2506 switch (clk->id) {
2507 case PLL_APLL:
2508 case ARMCLK:
2509 if (priv->armclk_hz)
2510 rk3568_armclk_set_clk(priv, rate);
2511 priv->armclk_hz = rate;
2512 break;
2513 case PLL_CPLL:
2514 ret = rockchip_pll_set_rate(&rk3568_pll_clks[CPLL], priv->cru,
2515 CPLL, rate);
2516 priv->cpll_hz = rockchip_pll_get_rate(&rk3568_pll_clks[CPLL],
2517 priv->cru, CPLL);
2518 break;
2519 case PLL_GPLL:
2520 ret = rockchip_pll_set_rate(&rk3568_pll_clks[GPLL], priv->cru,
2521 GPLL, rate);
2522 priv->gpll_hz = rockchip_pll_get_rate(&rk3568_pll_clks[GPLL],
2523 priv->cru, GPLL);
2524 break;
2525 case PLL_NPLL:
2526 ret = rockchip_pll_set_rate(&rk3568_pll_clks[NPLL], priv->cru,
2527 NPLL, rate);
2528 break;
2529 case PLL_VPLL:
2530 ret = rockchip_pll_set_rate(&rk3568_pll_clks[VPLL], priv->cru,
2531 VPLL, rate);
2532 priv->vpll_hz = rockchip_pll_get_rate(&rk3568_pll_clks[VPLL],
2533 priv->cru,
2534 VPLL);
2535 break;
2536 case ACLK_BUS:
2537 case PCLK_BUS:
2538 case PCLK_WDT_NS:
2539 ret = rk3568_bus_set_clk(priv, clk->id, rate);
2540 break;
2541 case ACLK_PERIMID:
2542 case HCLK_PERIMID:
2543 ret = rk3568_perimid_set_clk(priv, clk->id, rate);
2544 break;
2545 case ACLK_TOP_HIGH:
2546 case ACLK_TOP_LOW:
2547 case HCLK_TOP:
2548 case PCLK_TOP:
2549 ret = rk3568_top_set_clk(priv, clk->id, rate);
2550 break;
2551 case CLK_I2C1:
2552 case CLK_I2C2:
2553 case CLK_I2C3:
2554 case CLK_I2C4:
2555 case CLK_I2C5:
2556 ret = rk3568_i2c_set_clk(priv, clk->id, rate);
2557 break;
2558 case CLK_SPI0:
2559 case CLK_SPI1:
2560 case CLK_SPI2:
2561 case CLK_SPI3:
2562 ret = rk3568_spi_set_clk(priv, clk->id, rate);
2563 break;
2564 case CLK_PWM1:
2565 case CLK_PWM2:
2566 case CLK_PWM3:
2567 ret = rk3568_pwm_set_clk(priv, clk->id, rate);
2568 break;
2569 case CLK_SARADC:
2570 case CLK_TSADC_TSEN:
2571 case CLK_TSADC:
2572 ret = rk3568_adc_set_clk(priv, clk->id, rate);
2573 break;
2574 case HCLK_SDMMC0:
2575 case CLK_SDMMC0:
2576 case CLK_SDMMC1:
2577 case CLK_SDMMC2:
2578 ret = rk3568_sdmmc_set_clk(priv, clk->id, rate);
2579 break;
2580 case SCLK_SFC:
2581 ret = rk3568_sfc_set_clk(priv, rate);
2582 break;
2583 case NCLK_NANDC:
2584 ret = rk3568_nand_set_clk(priv, rate);
2585 break;
2586 case CCLK_EMMC:
2587 ret = rk3568_emmc_set_clk(priv, rate);
2588 break;
2589 case BCLK_EMMC:
2590 ret = rk3568_emmc_set_bclk(priv, rate);
2591 break;
Elaine Zhangf2cdd442021-10-12 16:43:00 +08002592 case TCLK_EMMC:
2593 ret = OSC_HZ;
2594 break;
Elaine Zhang4a262fe2021-06-02 11:39:24 +08002595#ifndef CONFIG_SPL_BUILD
2596 case ACLK_VOP:
2597 ret = rk3568_aclk_vop_set_clk(priv, rate);
2598 break;
2599 case DCLK_VOP0:
2600 case DCLK_VOP1:
2601 case DCLK_VOP2:
2602 ret = rk3568_dclk_vop_set_clk(priv, clk->id, rate);
2603 break;
2604 case SCLK_GMAC0:
2605 case CLK_MAC0_2TOP:
2606 case CLK_MAC0_REFOUT:
2607 ret = rk3568_gmac_src_set_clk(priv, 0, rate);
2608 break;
2609 case CLK_MAC0_OUT:
2610 ret = rk3568_gmac_out_set_clk(priv, 0, rate);
2611 break;
2612 case SCLK_GMAC0_RX_TX:
2613 ret = rk3568_gmac_tx_rx_set_clk(priv, 0, rate);
2614 break;
2615 case CLK_GMAC0_PTP_REF:
2616 ret = rk3568_gmac_ptp_ref_set_clk(priv, 0, rate);
2617 break;
2618 case SCLK_GMAC1:
2619 case CLK_MAC1_2TOP:
2620 case CLK_MAC1_REFOUT:
2621 ret = rk3568_gmac_src_set_clk(priv, 1, rate);
2622 break;
2623 case CLK_MAC1_OUT:
2624 ret = rk3568_gmac_out_set_clk(priv, 1, rate);
2625 break;
2626 case SCLK_GMAC1_RX_TX:
2627 ret = rk3568_gmac_tx_rx_set_clk(priv, 1, rate);
2628 break;
2629 case CLK_GMAC1_PTP_REF:
2630 ret = rk3568_gmac_ptp_ref_set_clk(priv, 1, rate);
2631 break;
2632 case DCLK_EBC:
2633 ret = rk3568_ebc_set_clk(priv, rate);
2634 break;
2635 case ACLK_RKVDEC_PRE:
2636 case ACLK_RKVDEC:
2637 case CLK_RKVDEC_CORE:
2638 ret = rk3568_rkvdec_set_clk(priv, clk->id, rate);
2639 break;
2640 case TCLK_WDT_NS:
2641 ret = OSC_HZ;
2642 break;
2643 case SCLK_UART1:
2644 case SCLK_UART2:
2645 case SCLK_UART3:
2646 case SCLK_UART4:
2647 case SCLK_UART5:
2648 case SCLK_UART6:
2649 case SCLK_UART7:
2650 case SCLK_UART8:
2651 case SCLK_UART9:
2652 ret = rk3568_uart_set_rate(priv, clk->id, rate);
2653 break;
2654#endif
2655 case ACLK_SECURE_FLASH:
2656 case ACLK_CRYPTO_NS:
2657 case HCLK_SECURE_FLASH:
2658 case HCLK_CRYPTO_NS:
2659 case CLK_CRYPTO_NS_RNG:
2660 case CLK_CRYPTO_NS_CORE:
2661 case CLK_CRYPTO_NS_PKA:
2662 ret = rk3568_crypto_set_rate(priv, clk->id, rate);
2663 break;
2664 case CPLL_500M:
2665 case CPLL_333M:
2666 case CPLL_250M:
2667 case CPLL_125M:
2668 case CPLL_100M:
2669 case CPLL_62P5M:
2670 case CPLL_50M:
2671 case CPLL_25M:
2672 ret = rk3568_cpll_div_set_rate(priv, clk->id, rate);
2673 break;
2674 default:
2675 return -ENOENT;
2676 }
2677
2678 return ret;
2679};
2680
2681#if (IS_ENABLED(OF_CONTROL)) || (!IS_ENABLED(OF_PLATDATA))
2682static int rk3568_gmac0_src_set_parent(struct clk *clk, struct clk *parent)
2683{
2684 struct rk3568_clk_priv *priv = dev_get_priv(clk->dev);
2685 struct rk3568_cru *cru = priv->cru;
2686
2687 if (parent->id == CLK_MAC0_2TOP)
2688 rk_clrsetreg(&cru->clksel_con[31],
2689 RMII0_EXTCLK_SEL_MASK,
2690 RMII0_EXTCLK_SEL_MAC0_TOP <<
2691 RMII0_EXTCLK_SEL_SHIFT);
2692 else
2693 rk_clrsetreg(&cru->clksel_con[31],
2694 RMII0_EXTCLK_SEL_MASK,
2695 RMII0_EXTCLK_SEL_IO << RMII0_EXTCLK_SEL_SHIFT);
2696 return 0;
2697}
2698
2699static int rk3568_gmac1_src_set_parent(struct clk *clk, struct clk *parent)
2700{
2701 struct rk3568_clk_priv *priv = dev_get_priv(clk->dev);
2702 struct rk3568_cru *cru = priv->cru;
2703
2704 if (parent->id == CLK_MAC1_2TOP)
2705 rk_clrsetreg(&cru->clksel_con[33],
2706 RMII0_EXTCLK_SEL_MASK,
2707 RMII0_EXTCLK_SEL_MAC0_TOP <<
2708 RMII0_EXTCLK_SEL_SHIFT);
2709 else
2710 rk_clrsetreg(&cru->clksel_con[33],
2711 RMII0_EXTCLK_SEL_MASK,
2712 RMII0_EXTCLK_SEL_IO << RMII0_EXTCLK_SEL_SHIFT);
2713 return 0;
2714}
2715
2716static int rk3568_gmac0_tx_rx_set_parent(struct clk *clk, struct clk *parent)
2717{
2718 struct rk3568_clk_priv *priv = dev_get_priv(clk->dev);
2719 struct rk3568_cru *cru = priv->cru;
2720
2721 if (parent->id == SCLK_GMAC0_RGMII_SPEED)
2722 rk_clrsetreg(&cru->clksel_con[31],
2723 RMII0_MODE_MASK,
2724 RMII0_MODE_SEL_RGMII << RMII0_MODE_SHIFT);
2725 else if (parent->id == SCLK_GMAC0_RMII_SPEED)
2726 rk_clrsetreg(&cru->clksel_con[31],
2727 RMII0_MODE_MASK,
2728 RMII0_MODE_SEL_RMII << RMII0_MODE_SHIFT);
2729 else
2730 rk_clrsetreg(&cru->clksel_con[31],
2731 RMII0_MODE_MASK,
2732 RMII0_MODE_SEL_GMII << RMII0_MODE_SHIFT);
2733
2734 return 0;
2735}
2736
2737static int rk3568_gmac1_tx_rx_set_parent(struct clk *clk, struct clk *parent)
2738{
2739 struct rk3568_clk_priv *priv = dev_get_priv(clk->dev);
2740 struct rk3568_cru *cru = priv->cru;
2741
2742 if (parent->id == SCLK_GMAC1_RGMII_SPEED)
2743 rk_clrsetreg(&cru->clksel_con[33],
2744 RMII0_MODE_MASK,
2745 RMII0_MODE_SEL_RGMII << RMII0_MODE_SHIFT);
2746 else if (parent->id == SCLK_GMAC1_RMII_SPEED)
2747 rk_clrsetreg(&cru->clksel_con[33],
2748 RMII0_MODE_MASK,
2749 RMII0_MODE_SEL_RMII << RMII0_MODE_SHIFT);
2750 else
2751 rk_clrsetreg(&cru->clksel_con[33],
2752 RMII0_MODE_MASK,
2753 RMII0_MODE_SEL_GMII << RMII0_MODE_SHIFT);
2754
2755 return 0;
2756}
2757
2758static int rk3568_dclk_vop_set_parent(struct clk *clk, struct clk *parent)
2759{
2760 struct rk3568_clk_priv *priv = dev_get_priv(clk->dev);
2761 struct rk3568_cru *cru = priv->cru;
2762 u32 con_id;
2763
2764 switch (clk->id) {
2765 case DCLK_VOP0:
2766 con_id = 39;
2767 break;
2768 case DCLK_VOP1:
2769 con_id = 40;
2770 break;
2771 case DCLK_VOP2:
2772 con_id = 41;
2773 break;
2774 default:
2775 return -EINVAL;
2776 }
2777 if (parent->id == PLL_VPLL) {
2778 rk_clrsetreg(&cru->clksel_con[con_id], DCLK0_VOP_SEL_MASK,
2779 DCLK_VOP_SEL_VPLL << DCLK0_VOP_SEL_SHIFT);
2780 } else {
2781 rk_clrsetreg(&cru->clksel_con[con_id], DCLK0_VOP_SEL_MASK,
2782 DCLK_VOP_SEL_HPLL << DCLK0_VOP_SEL_SHIFT);
2783 }
2784
2785 return 0;
2786}
2787
2788static int rk3568_rkvdec_set_parent(struct clk *clk, struct clk *parent)
2789{
2790 struct rk3568_clk_priv *priv = dev_get_priv(clk->dev);
2791 struct rk3568_cru *cru = priv->cru;
2792 u32 con_id, mask, shift;
2793
2794 switch (clk->id) {
2795 case ACLK_RKVDEC_PRE:
2796 con_id = 47;
2797 mask = ACLK_RKVDEC_SEL_MASK;
2798 shift = ACLK_RKVDEC_SEL_SHIFT;
2799 break;
2800 case CLK_RKVDEC_CORE:
2801 con_id = 49;
2802 mask = CLK_RKVDEC_CORE_SEL_MASK;
2803 shift = CLK_RKVDEC_CORE_SEL_SHIFT;
2804 break;
2805 default:
2806 return -EINVAL;
2807 }
2808 if (parent->id == PLL_CPLL) {
2809 rk_clrsetreg(&cru->clksel_con[con_id], mask,
2810 ACLK_RKVDEC_SEL_CPLL << shift);
2811 } else {
2812 rk_clrsetreg(&cru->clksel_con[con_id], mask,
2813 ACLK_RKVDEC_SEL_GPLL << shift);
2814 }
2815
2816 return 0;
2817}
2818
2819static int rk3568_clk_set_parent(struct clk *clk, struct clk *parent)
2820{
2821 switch (clk->id) {
2822 case SCLK_GMAC0:
2823 return rk3568_gmac0_src_set_parent(clk, parent);
2824 case SCLK_GMAC1:
2825 return rk3568_gmac1_src_set_parent(clk, parent);
2826 case SCLK_GMAC0_RX_TX:
2827 return rk3568_gmac0_tx_rx_set_parent(clk, parent);
2828 case SCLK_GMAC1_RX_TX:
2829 return rk3568_gmac1_tx_rx_set_parent(clk, parent);
2830 case DCLK_VOP0:
2831 case DCLK_VOP1:
2832 case DCLK_VOP2:
2833 return rk3568_dclk_vop_set_parent(clk, parent);
2834 case ACLK_RKVDEC_PRE:
2835 case CLK_RKVDEC_CORE:
2836 return rk3568_rkvdec_set_parent(clk, parent);
2837 default:
2838 return -ENOENT;
2839 }
2840
2841 return 0;
2842}
2843#endif
2844
2845static struct clk_ops rk3568_clk_ops = {
2846 .get_rate = rk3568_clk_get_rate,
2847 .set_rate = rk3568_clk_set_rate,
2848#if (IS_ENABLED(OF_CONTROL)) || (!IS_ENABLED(OF_PLATDATA))
2849 .set_parent = rk3568_clk_set_parent,
2850#endif
2851};
2852
2853static void rk3568_clk_init(struct rk3568_clk_priv *priv)
2854{
2855 int ret;
2856
2857 priv->sync_kernel = false;
2858 if (!priv->armclk_enter_hz) {
2859 priv->armclk_enter_hz =
2860 rockchip_pll_get_rate(&rk3568_pll_clks[APLL],
2861 priv->cru, APLL);
2862 priv->armclk_init_hz = priv->armclk_enter_hz;
2863 }
2864
2865 if (priv->armclk_init_hz != APLL_HZ) {
2866 ret = rk3568_armclk_set_clk(priv, APLL_HZ);
2867 if (!ret)
2868 priv->armclk_init_hz = APLL_HZ;
2869 }
2870 if (priv->cpll_hz != CPLL_HZ) {
2871 ret = rockchip_pll_set_rate(&rk3568_pll_clks[CPLL], priv->cru,
2872 CPLL, CPLL_HZ);
2873 if (!ret)
2874 priv->cpll_hz = CPLL_HZ;
2875 }
2876 if (priv->gpll_hz != GPLL_HZ) {
2877 ret = rockchip_pll_set_rate(&rk3568_pll_clks[GPLL], priv->cru,
2878 GPLL, GPLL_HZ);
2879 if (!ret)
2880 priv->gpll_hz = GPLL_HZ;
2881 }
2882
2883#ifdef CONFIG_SPL_BUILD
2884 ret = rk3568_bus_set_clk(priv, ACLK_BUS, 150000000);
2885 if (ret < 0)
2886 printf("Fail to set the ACLK_BUS clock.\n");
2887#endif
2888
2889 priv->ppll_hz = rk3568_pmu_pll_get_rate(priv, PPLL);
2890 priv->hpll_hz = rk3568_pmu_pll_get_rate(priv, HPLL);
2891}
2892
2893static int rk3568_clk_probe(struct udevice *dev)
2894{
2895 struct rk3568_clk_priv *priv = dev_get_priv(dev);
2896 int ret;
2897
2898 priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
2899 if (IS_ERR(priv->grf))
2900 return PTR_ERR(priv->grf);
2901
2902 rk3568_clk_init(priv);
2903
2904 /* Process 'assigned-{clocks/clock-parents/clock-rates}' properties */
2905 ret = clk_set_defaults(dev, 1);
2906 if (ret)
2907 debug("%s clk_set_defaults failed %d\n", __func__, ret);
2908 else
2909 priv->sync_kernel = true;
2910
2911 return 0;
2912}
2913
2914static int rk3568_clk_ofdata_to_platdata(struct udevice *dev)
2915{
2916 struct rk3568_clk_priv *priv = dev_get_priv(dev);
2917
2918 priv->cru = dev_read_addr_ptr(dev);
2919
2920 return 0;
2921}
2922
2923static int rk3568_clk_bind(struct udevice *dev)
2924{
2925 int ret;
2926 struct udevice *sys_child;
2927 struct sysreset_reg *priv;
2928
2929 /* The reset driver does not have a device node, so bind it here */
2930 ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset",
2931 &sys_child);
2932 if (ret) {
2933 debug("Warning: No sysreset driver: ret=%d\n", ret);
2934 } else {
2935 priv = malloc(sizeof(struct sysreset_reg));
2936 priv->glb_srst_fst_value = offsetof(struct rk3568_cru,
2937 glb_srst_fst);
2938 priv->glb_srst_snd_value = offsetof(struct rk3568_cru,
2939 glb_srsr_snd);
2940 }
2941
2942#if CONFIG_IS_ENABLED(RESET_ROCKCHIP)
2943 ret = offsetof(struct rk3568_cru, softrst_con[0]);
2944 ret = rockchip_reset_bind(dev, ret, 30);
2945 if (ret)
2946 debug("Warning: software reset driver bind faile\n");
2947#endif
2948
2949 return 0;
2950}
2951
2952static const struct udevice_id rk3568_clk_ids[] = {
2953 { .compatible = "rockchip,rk3568-cru" },
2954 { }
2955};
2956
2957U_BOOT_DRIVER(rockchip_rk3568_cru) = {
2958 .name = "rockchip_rk3568_cru",
2959 .id = UCLASS_CLK,
2960 .of_match = rk3568_clk_ids,
2961 .priv_auto = sizeof(struct rk3568_clk_priv),
2962 .of_to_plat = rk3568_clk_ofdata_to_platdata,
2963 .ops = &rk3568_clk_ops,
2964 .bind = rk3568_clk_bind,
2965 .probe = rk3568_clk_probe,
2966#if CONFIG_IS_ENABLED(OF_PLATDATA)
2967 .plat_auto = sizeof(struct rk3568_clk_plat),
2968#endif
2969};