blob: e84a0943a940df12ad7d914141892b0f7038b5ec [file] [log] [blame]
Elaine Zhang7f7e3232025-04-15 23:51:18 +02001// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (c) 2021 Fuzhou Rockchip Electronics Co., Ltd
4 * Author: Elaine Zhang <zhangqing@rock-chips.com>
5 */
6
7#include <bitfield.h>
8#include <clk-uclass.h>
9#include <dm.h>
10#include <errno.h>
11#include <syscon.h>
12#include <asm/arch-rockchip/cru_rk3576.h>
13#include <asm/arch-rockchip/clock.h>
14#include <asm/arch-rockchip/hardware.h>
15#include <dm/device-internal.h>
16#include <dm/lists.h>
17#include <dt-bindings/clock/rockchip,rk3576-cru.h>
18#include <linux/delay.h>
19
20DECLARE_GLOBAL_DATA_PTR;
21
22#define DIV_TO_RATE(input_rate, div) ((input_rate) / ((div) + 1))
23
24static struct rockchip_pll_rate_table rk3576_24m_pll_rates[] = {
25 /* _mhz, _p, _m, _s, _k */
26 RK3588_PLL_RATE(1500000000, 2, 250, 1, 0),
27 RK3588_PLL_RATE(1200000000, 1, 100, 1, 0),
28 RK3588_PLL_RATE(1188000000, 2, 198, 1, 0),
29 RK3588_PLL_RATE(1150000000, 3, 575, 2, 0),
30 RK3588_PLL_RATE(1100000000, 3, 550, 2, 0),
31 RK3588_PLL_RATE(1008000000, 2, 336, 2, 0),
32 RK3588_PLL_RATE(1000000000, 3, 500, 2, 0),
33 RK3588_PLL_RATE(900000000, 2, 300, 2, 0),
34 RK3588_PLL_RATE(850000000, 3, 425, 2, 0),
35 RK3588_PLL_RATE(816000000, 2, 272, 2, 0),
36 RK3588_PLL_RATE(786432000, 2, 262, 2, 9437),
37 RK3588_PLL_RATE(786000000, 1, 131, 2, 0),
38 RK3588_PLL_RATE(742500000, 4, 495, 2, 0),
39 RK3588_PLL_RATE(722534400, 8, 963, 2, 24850),
40 RK3588_PLL_RATE(600000000, 2, 200, 2, 0),
41 RK3588_PLL_RATE(594000000, 2, 198, 2, 0),
42 RK3588_PLL_RATE(200000000, 3, 400, 4, 0),
43 RK3588_PLL_RATE(100000000, 3, 400, 5, 0),
44 { /* sentinel */ },
45};
46
47static struct rockchip_pll_clock rk3576_pll_clks[] = {
48 [BPLL] = PLL(pll_rk3588, PLL_BPLL, RK3576_PLL_CON(0),
49 RK3576_BPLL_MODE_CON0, 0, 15, 0,
50 rk3576_24m_pll_rates),
51 [LPLL] = PLL(pll_rk3588, PLL_LPLL, RK3576_LPLL_CON(16),
52 RK3576_LPLL_MODE_CON0, 0, 15, 0, rk3576_24m_pll_rates),
53 [VPLL] = PLL(pll_rk3588, PLL_VPLL, RK3576_PLL_CON(88),
54 RK3576_LPLL_MODE_CON0, 4, 15, 0, rk3576_24m_pll_rates),
55 [AUPLL] = PLL(pll_rk3588, PLL_AUPLL, RK3576_PLL_CON(96),
56 RK3576_MODE_CON0, 6, 15, 0, rk3576_24m_pll_rates),
57 [CPLL] = PLL(pll_rk3588, PLL_CPLL, RK3576_PLL_CON(104),
58 RK3576_MODE_CON0, 8, 15, 0, rk3576_24m_pll_rates),
59 [GPLL] = PLL(pll_rk3588, PLL_GPLL, RK3576_PLL_CON(112),
60 RK3576_MODE_CON0, 2, 15, 0, rk3576_24m_pll_rates),
61 [PPLL] = PLL(pll_rk3588, PLL_PPLL, RK3576_PMU_PLL_CON(128),
62 RK3576_MODE_CON0, 10, 15, 0, rk3576_24m_pll_rates),
63};
64
65#ifdef CONFIG_SPL_BUILD
66#ifndef BITS_WITH_WMASK
67#define BITS_WITH_WMASK(bits, msk, shift) \
68 ((bits) << (shift)) | ((msk) << ((shift) + 16))
69#endif
70#endif
71
72#ifndef CONFIG_SPL_BUILD
73/*
74 *
75 * rational_best_approximation(31415, 10000,
76 * (1 << 8) - 1, (1 << 5) - 1, &n, &d);
77 *
78 * you may look at given_numerator as a fixed point number,
79 * with the fractional part size described in given_denominator.
80 *
81 * for theoretical background, see:
82 * http://en.wikipedia.org/wiki/Continued_fraction
83 */
84static void rational_best_approximation(unsigned long given_numerator,
85 unsigned long given_denominator,
86 unsigned long max_numerator,
87 unsigned long max_denominator,
88 unsigned long *best_numerator,
89 unsigned long *best_denominator)
90{
91 unsigned long n, d, n0, d0, n1, d1;
92
93 n = given_numerator;
94 d = given_denominator;
95 n0 = 0;
96 d1 = 0;
97 n1 = 1;
98 d0 = 1;
99 for (;;) {
100 unsigned long t, a;
101
102 if (n1 > max_numerator || d1 > max_denominator) {
103 n1 = n0;
104 d1 = d0;
105 break;
106 }
107 if (d == 0)
108 break;
109 t = d;
110 a = n / d;
111 d = n % d;
112 n = t;
113 t = n0 + a * n1;
114 n0 = n1;
115 n1 = t;
116 t = d0 + a * d1;
117 d0 = d1;
118 d1 = t;
119 }
120 *best_numerator = n1;
121 *best_denominator = d1;
122}
123#endif
124
125static ulong rk3576_bus_get_clk(struct rk3576_clk_priv *priv, ulong clk_id)
126{
127 struct rk3576_cru *cru = priv->cru;
128 u32 con, sel, div, rate;
129
130 switch (clk_id) {
131 case ACLK_BUS_ROOT:
132 con = readl(&cru->clksel_con[55]);
133 sel = (con & ACLK_BUS_ROOT_SEL_MASK) >>
134 ACLK_BUS_ROOT_SEL_SHIFT;
135 div = (con & ACLK_BUS_ROOT_DIV_MASK) >>
136 ACLK_BUS_ROOT_DIV_SHIFT;
137 if (sel == ACLK_BUS_ROOT_SEL_CPLL)
138 rate = DIV_TO_RATE(priv->cpll_hz, div);
139 else
140 rate = DIV_TO_RATE(priv->gpll_hz, div);
141 break;
142 case HCLK_BUS_ROOT:
143 con = readl(&cru->clksel_con[55]);
144 sel = (con & HCLK_BUS_ROOT_SEL_MASK) >>
145 HCLK_BUS_ROOT_SEL_SHIFT;
146 if (sel == HCLK_BUS_ROOT_SEL_200M)
147 rate = 198 * MHz;
148 else if (sel == HCLK_BUS_ROOT_SEL_100M)
149 rate = 100 * MHz;
150 else if (sel == HCLK_BUS_ROOT_SEL_50M)
151 rate = 50 * MHz;
152 else
153 rate = OSC_HZ;
154 break;
155 case PCLK_BUS_ROOT:
156 con = readl(&cru->clksel_con[55]);
157 sel = (con & PCLK_BUS_ROOT_SEL_MASK) >>
158 PCLK_BUS_ROOT_SEL_SHIFT;
159 if (sel == PCLK_BUS_ROOT_SEL_100M)
160 rate = 100 * MHz;
161 else if (sel == PCLK_BUS_ROOT_SEL_50M)
162 rate = 50 * MHz;
163 else
164 rate = OSC_HZ;
165 break;
166 default:
167 return -ENOENT;
168 }
169
170 return rate;
171}
172
173static ulong rk3576_bus_set_clk(struct rk3576_clk_priv *priv,
174 ulong clk_id, ulong rate)
175{
176 struct rk3576_cru *cru = priv->cru;
177 int src_clk, src_clk_div;
178
179 switch (clk_id) {
180 case ACLK_BUS_ROOT:
181 if (!(priv->cpll_hz % rate)) {
182 src_clk = ACLK_BUS_ROOT_SEL_CPLL;
183 src_clk_div = DIV_ROUND_UP(priv->cpll_hz, rate);
184 } else {
185 src_clk = ACLK_BUS_ROOT_SEL_GPLL;
186 src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
187 }
188 rk_clrsetreg(&cru->clksel_con[55],
189 ACLK_BUS_ROOT_SEL_MASK,
190 src_clk << ACLK_BUS_ROOT_SEL_SHIFT);
191 assert(src_clk_div - 1 <= 31);
192 rk_clrsetreg(&cru->clksel_con[55],
193 ACLK_BUS_ROOT_DIV_MASK |
194 ACLK_BUS_ROOT_SEL_MASK,
195 (src_clk <<
196 ACLK_BUS_ROOT_SEL_SHIFT) |
197 (src_clk_div - 1) << ACLK_BUS_ROOT_DIV_SHIFT);
198 break;
199 case HCLK_BUS_ROOT:
200 if (rate >= 198 * MHz)
201 src_clk = HCLK_BUS_ROOT_SEL_200M;
202 else if (rate >= 99 * MHz)
203 src_clk = HCLK_BUS_ROOT_SEL_100M;
204 else if (rate >= 50 * MHz)
205 src_clk = HCLK_BUS_ROOT_SEL_50M;
206 else
207 src_clk = HCLK_BUS_ROOT_SEL_OSC;
208 rk_clrsetreg(&cru->clksel_con[55],
209 HCLK_BUS_ROOT_SEL_MASK,
210 src_clk << HCLK_BUS_ROOT_SEL_SHIFT);
211 break;
212 case PCLK_BUS_ROOT:
213 if (rate >= 99 * MHz)
214 src_clk = PCLK_BUS_ROOT_SEL_100M;
215 else if (rate >= 50 * MHz)
216 src_clk = PCLK_BUS_ROOT_SEL_50M;
217 else
218 src_clk = PCLK_BUS_ROOT_SEL_OSC;
219 rk_clrsetreg(&cru->clksel_con[55],
220 PCLK_BUS_ROOT_SEL_MASK,
221 src_clk << PCLK_BUS_ROOT_SEL_SHIFT);
222 break;
223 default:
224 printf("do not support this center freq\n");
225 return -EINVAL;
226 }
227
228 return rk3576_bus_get_clk(priv, clk_id);
229}
230
231static ulong rk3576_top_get_clk(struct rk3576_clk_priv *priv, ulong clk_id)
232{
233 struct rk3576_cru *cru = priv->cru;
234 u32 con, sel, div, rate, prate;
235
236 switch (clk_id) {
237 case ACLK_TOP:
238 con = readl(&cru->clksel_con[9]);
239 div = (con & ACLK_TOP_DIV_MASK) >>
240 ACLK_TOP_DIV_SHIFT;
241 sel = (con & ACLK_TOP_SEL_MASK) >>
242 ACLK_TOP_SEL_SHIFT;
243 if (sel == ACLK_TOP_SEL_CPLL)
244 prate = priv->cpll_hz;
245 else if (sel == ACLK_TOP_SEL_AUPLL)
246 prate = priv->aupll_hz;
247 else
248 prate = priv->gpll_hz;
249 return DIV_TO_RATE(prate, div);
250 case ACLK_TOP_MID:
251 con = readl(&cru->clksel_con[10]);
252 div = (con & ACLK_TOP_MID_DIV_MASK) >>
253 ACLK_TOP_MID_DIV_SHIFT;
254 sel = (con & ACLK_TOP_MID_SEL_MASK) >>
255 ACLK_TOP_MID_SEL_SHIFT;
256 if (sel == ACLK_TOP_MID_SEL_CPLL)
257 prate = priv->cpll_hz;
258 else
259 prate = priv->gpll_hz;
260 return DIV_TO_RATE(prate, div);
261 case PCLK_TOP_ROOT:
262 con = readl(&cru->clksel_con[8]);
263 sel = (con & PCLK_TOP_SEL_MASK) >> PCLK_TOP_SEL_SHIFT;
264 if (sel == PCLK_TOP_SEL_100M)
265 rate = 100 * MHz;
266 else if (sel == PCLK_TOP_SEL_50M)
267 rate = 50 * MHz;
268 else
269 rate = OSC_HZ;
270 break;
271 case HCLK_TOP:
272 con = readl(&cru->clksel_con[19]);
273 sel = (con & HCLK_TOP_SEL_MASK) >> HCLK_TOP_SEL_SHIFT;
274 if (sel == HCLK_TOP_SEL_200M)
275 rate = 200 * MHz;
276 else if (sel == HCLK_TOP_SEL_100M)
277 rate = 100 * MHz;
278 else if (sel == HCLK_TOP_SEL_50M)
279 rate = 50 * MHz;
280 else
281 rate = OSC_HZ;
282 break;
283 default:
284 return -ENOENT;
285 }
286
287 return rate;
288}
289
290static ulong rk3576_top_set_clk(struct rk3576_clk_priv *priv,
291 ulong clk_id, ulong rate)
292{
293 struct rk3576_cru *cru = priv->cru;
294 int src_clk, src_clk_div;
295
296 switch (clk_id) {
297 case ACLK_TOP:
298 if (!(priv->cpll_hz % rate)) {
299 src_clk = ACLK_TOP_SEL_CPLL;
300 src_clk_div = DIV_ROUND_UP(priv->cpll_hz, rate);
301 } else {
302 src_clk = ACLK_TOP_SEL_GPLL;
303 src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
304 }
305 assert(src_clk_div - 1 <= 31);
306 rk_clrsetreg(&cru->clksel_con[9],
307 ACLK_TOP_DIV_MASK |
308 ACLK_TOP_SEL_MASK,
309 (src_clk <<
310 ACLK_TOP_SEL_SHIFT) |
311 (src_clk_div - 1) << ACLK_TOP_SEL_SHIFT);
312 break;
313 case ACLK_TOP_MID:
314 if (!(priv->cpll_hz % rate)) {
315 src_clk = ACLK_TOP_MID_SEL_CPLL;
316 src_clk_div = DIV_ROUND_UP(priv->cpll_hz, rate);
317 } else {
318 src_clk = ACLK_TOP_MID_SEL_GPLL;
319 src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
320 }
321 rk_clrsetreg(&cru->clksel_con[10],
322 ACLK_TOP_MID_DIV_MASK |
323 ACLK_TOP_MID_SEL_MASK,
324 (ACLK_TOP_MID_SEL_GPLL <<
325 ACLK_TOP_MID_SEL_SHIFT) |
326 (src_clk_div - 1) << ACLK_TOP_MID_DIV_SHIFT);
327 break;
328 case PCLK_TOP_ROOT:
329 if (rate >= 99 * MHz)
330 src_clk = PCLK_TOP_SEL_100M;
331 else if (rate >= 50 * MHz)
332 src_clk = PCLK_TOP_SEL_50M;
333 else
334 src_clk = PCLK_TOP_SEL_OSC;
335 rk_clrsetreg(&cru->clksel_con[8],
336 PCLK_TOP_SEL_MASK,
337 src_clk << PCLK_TOP_SEL_SHIFT);
338 break;
339 case HCLK_TOP:
340 if (rate >= 198 * MHz)
341 src_clk = HCLK_TOP_SEL_200M;
342 else if (rate >= 99 * MHz)
343 src_clk = HCLK_TOP_SEL_100M;
344 else if (rate >= 50 * MHz)
345 src_clk = HCLK_TOP_SEL_50M;
346 else
347 src_clk = HCLK_TOP_SEL_OSC;
348 rk_clrsetreg(&cru->clksel_con[19],
349 HCLK_TOP_SEL_MASK,
350 src_clk << HCLK_TOP_SEL_SHIFT);
351 break;
352 default:
353 printf("do not support this top freq\n");
354 return -EINVAL;
355 }
356
357 return rk3576_top_get_clk(priv, clk_id);
358}
359
360static ulong rk3576_i2c_get_clk(struct rk3576_clk_priv *priv, ulong clk_id)
361{
362 struct rk3576_cru *cru = priv->cru;
363 u32 sel, con;
364 ulong rate;
365
366 switch (clk_id) {
367 case CLK_I2C0:
368 con = readl(&cru->pmuclksel_con[6]);
369 sel = (con & CLK_I2C0_SEL_MASK) >> CLK_I2C0_SEL_SHIFT;
370 break;
371 case CLK_I2C1:
372 con = readl(&cru->clksel_con[57]);
373 sel = (con & CLK_I2C1_SEL_MASK) >> CLK_I2C1_SEL_SHIFT;
374 break;
375 case CLK_I2C2:
376 con = readl(&cru->clksel_con[57]);
377 sel = (con & CLK_I2C2_SEL_MASK) >> CLK_I2C2_SEL_SHIFT;
378 break;
379 case CLK_I2C3:
380 con = readl(&cru->clksel_con[57]);
381 sel = (con & CLK_I2C3_SEL_MASK) >> CLK_I2C3_SEL_SHIFT;
382 break;
383 case CLK_I2C4:
384 con = readl(&cru->clksel_con[57]);
385 sel = (con & CLK_I2C4_SEL_MASK) >> CLK_I2C4_SEL_SHIFT;
386 break;
387 case CLK_I2C5:
388 con = readl(&cru->clksel_con[57]);
389 sel = (con & CLK_I2C5_SEL_MASK) >> CLK_I2C5_SEL_SHIFT;
390 break;
391 case CLK_I2C6:
392 con = readl(&cru->clksel_con[57]);
393 sel = (con & CLK_I2C6_SEL_MASK) >> CLK_I2C6_SEL_SHIFT;
394 break;
395 case CLK_I2C7:
396 con = readl(&cru->clksel_con[57]);
397 sel = (con & CLK_I2C7_SEL_MASK) >> CLK_I2C7_SEL_SHIFT;
398 break;
399 case CLK_I2C8:
400 con = readl(&cru->clksel_con[57]);
401 sel = (con & CLK_I2C8_SEL_MASK) >> CLK_I2C8_SEL_SHIFT;
402 break;
403 case CLK_I2C9:
404 con = readl(&cru->clksel_con[58]);
405 sel = (con & CLK_I2C9_SEL_MASK) >> CLK_I2C9_SEL_SHIFT;
406 break;
407
408 default:
409 return -ENOENT;
410 }
411 if (sel == CLK_I2C_SEL_200M)
412 rate = 200 * MHz;
413 else if (sel == CLK_I2C_SEL_100M)
414 rate = 100 * MHz;
415 else if (sel == CLK_I2C_SEL_50M)
416 rate = 50 * MHz;
417 else
418 rate = OSC_HZ;
419
420 return rate;
421}
422
423static ulong rk3576_i2c_set_clk(struct rk3576_clk_priv *priv, ulong clk_id,
424 ulong rate)
425{
426 struct rk3576_cru *cru = priv->cru;
427 int src_clk;
428
429 if (rate >= 198 * MHz)
430 src_clk = CLK_I2C_SEL_200M;
431 else if (rate >= 99 * MHz)
432 src_clk = CLK_I2C_SEL_100M;
433 if (rate >= 50 * MHz)
434 src_clk = CLK_I2C_SEL_50M;
435 else
436 src_clk = CLK_I2C_SEL_OSC;
437
438 switch (clk_id) {
439 case CLK_I2C0:
440 rk_clrsetreg(&cru->pmuclksel_con[6], CLK_I2C0_SEL_MASK,
441 src_clk << CLK_I2C0_SEL_SHIFT);
442 break;
443 case CLK_I2C1:
444 rk_clrsetreg(&cru->clksel_con[57], CLK_I2C1_SEL_MASK,
445 src_clk << CLK_I2C1_SEL_SHIFT);
446 break;
447 case CLK_I2C2:
448 rk_clrsetreg(&cru->clksel_con[57], CLK_I2C2_SEL_MASK,
449 src_clk << CLK_I2C2_SEL_SHIFT);
450 break;
451 case CLK_I2C3:
452 rk_clrsetreg(&cru->clksel_con[57], CLK_I2C3_SEL_MASK,
453 src_clk << CLK_I2C3_SEL_SHIFT);
454 break;
455 case CLK_I2C4:
456 rk_clrsetreg(&cru->clksel_con[57], CLK_I2C4_SEL_MASK,
457 src_clk << CLK_I2C4_SEL_SHIFT);
458 break;
459 case CLK_I2C5:
460 rk_clrsetreg(&cru->clksel_con[57], CLK_I2C5_SEL_MASK,
461 src_clk << CLK_I2C5_SEL_SHIFT);
462 break;
463 case CLK_I2C6:
464 rk_clrsetreg(&cru->clksel_con[57], CLK_I2C6_SEL_MASK,
465 src_clk << CLK_I2C6_SEL_SHIFT);
466 break;
467 case CLK_I2C7:
468 rk_clrsetreg(&cru->clksel_con[57], CLK_I2C7_SEL_MASK,
469 src_clk << CLK_I2C7_SEL_SHIFT);
470 break;
471 case CLK_I2C8:
472 rk_clrsetreg(&cru->clksel_con[57], CLK_I2C8_SEL_MASK,
473 src_clk << CLK_I2C8_SEL_SHIFT);
474 case CLK_I2C9:
475 rk_clrsetreg(&cru->clksel_con[58], CLK_I2C9_SEL_MASK,
476 src_clk << CLK_I2C9_SEL_SHIFT);
477 break;
478 default:
479 return -ENOENT;
480 }
481
482 return rk3576_i2c_get_clk(priv, clk_id);
483}
484
485static ulong rk3576_spi_get_clk(struct rk3576_clk_priv *priv, ulong clk_id)
486{
487 struct rk3576_cru *cru = priv->cru;
488 u32 sel, con;
489
490 switch (clk_id) {
491 case CLK_SPI0:
492 con = readl(&cru->clksel_con[70]);
493 sel = (con & CLK_SPI0_SEL_MASK) >> CLK_SPI0_SEL_SHIFT;
494 break;
495 case CLK_SPI1:
496 con = readl(&cru->clksel_con[71]);
497 sel = (con & CLK_SPI1_SEL_MASK) >> CLK_SPI1_SEL_SHIFT;
498 break;
499 case CLK_SPI2:
500 con = readl(&cru->clksel_con[71]);
501 sel = (con & CLK_SPI2_SEL_MASK) >> CLK_SPI2_SEL_SHIFT;
502 break;
503 case CLK_SPI3:
504 con = readl(&cru->clksel_con[71]);
505 sel = (con & CLK_SPI3_SEL_MASK) >> CLK_SPI3_SEL_SHIFT;
506 break;
507 case CLK_SPI4:
508 con = readl(&cru->clksel_con[71]);
509 sel = (con & CLK_SPI4_SEL_MASK) >> CLK_SPI4_SEL_SHIFT;
510 break;
511 default:
512 return -ENOENT;
513 }
514
515 switch (sel) {
516 case CLK_SPI_SEL_200M:
517 return 200 * MHz;
518 case CLK_SPI_SEL_100M:
519 return 100 * MHz;
520 case CLK_SPI_SEL_50M:
521 return 50 * MHz;
522 case CLK_SPI_SEL_OSC:
523 return OSC_HZ;
524 default:
525 return -ENOENT;
526 }
527}
528
529static ulong rk3576_spi_set_clk(struct rk3576_clk_priv *priv,
530 ulong clk_id, ulong rate)
531{
532 struct rk3576_cru *cru = priv->cru;
533 int src_clk;
534
535 if (rate >= 198 * MHz)
536 src_clk = CLK_SPI_SEL_200M;
537 else if (rate >= 99 * MHz)
538 src_clk = CLK_SPI_SEL_100M;
539 else if (rate >= 50 * MHz)
540 src_clk = CLK_SPI_SEL_50M;
541 else
542 src_clk = CLK_SPI_SEL_OSC;
543
544 switch (clk_id) {
545 case CLK_SPI0:
546 rk_clrsetreg(&cru->clksel_con[70],
547 CLK_SPI0_SEL_MASK,
548 src_clk << CLK_SPI0_SEL_SHIFT);
549 break;
550 case CLK_SPI1:
551 rk_clrsetreg(&cru->clksel_con[71],
552 CLK_SPI1_SEL_MASK,
553 src_clk << CLK_SPI1_SEL_SHIFT);
554 break;
555 case CLK_SPI2:
556 rk_clrsetreg(&cru->clksel_con[71],
557 CLK_SPI2_SEL_MASK,
558 src_clk << CLK_SPI2_SEL_SHIFT);
559 break;
560 case CLK_SPI3:
561 rk_clrsetreg(&cru->clksel_con[71],
562 CLK_SPI3_SEL_MASK,
563 src_clk << CLK_SPI3_SEL_SHIFT);
564 break;
565 case CLK_SPI4:
566 rk_clrsetreg(&cru->clksel_con[71],
567 CLK_SPI4_SEL_MASK,
568 src_clk << CLK_SPI4_SEL_SHIFT);
569 break;
570 default:
571 return -ENOENT;
572 }
573
574 return rk3576_spi_get_clk(priv, clk_id);
575}
576
577static ulong rk3576_pwm_get_clk(struct rk3576_clk_priv *priv, ulong clk_id)
578{
579 struct rk3576_cru *cru = priv->cru;
580 u32 sel, con;
581
582 switch (clk_id) {
583 case CLK_PWM1:
584 con = readl(&cru->clksel_con[71]);
585 sel = (con & CLK_PWM1_SEL_MASK) >> CLK_PWM1_SEL_SHIFT;
586 break;
587 case CLK_PWM2:
588 con = readl(&cru->clksel_con[74]);
589 sel = (con & CLK_PWM2_SEL_MASK) >> CLK_PWM2_SEL_SHIFT;
590 break;
591 case CLK_PMU1PWM:
592 con = readl(&cru->pmuclksel_con[5]);
593 sel = (con & CLK_PMU1PWM_SEL_MASK) >> CLK_PMU1PWM_SEL_SHIFT;
594 break;
595 default:
596 return -ENOENT;
597 }
598
599 switch (sel) {
600 case CLK_PWM_SEL_100M:
601 return 100 * MHz;
602 case CLK_PWM_SEL_50M:
603 return 50 * MHz;
604 case CLK_PWM_SEL_OSC:
605 return OSC_HZ;
606 default:
607 return -ENOENT;
608 }
609}
610
611static ulong rk3576_pwm_set_clk(struct rk3576_clk_priv *priv,
612 ulong clk_id, ulong rate)
613{
614 struct rk3576_cru *cru = priv->cru;
615 int src_clk;
616
617 if (rate >= 99 * MHz)
618 src_clk = CLK_PWM_SEL_100M;
619 else if (rate >= 50 * MHz)
620 src_clk = CLK_PWM_SEL_50M;
621 else
622 src_clk = CLK_PWM_SEL_OSC;
623
624 switch (clk_id) {
625 case CLK_PWM1:
626 rk_clrsetreg(&cru->clksel_con[71],
627 CLK_PWM1_SEL_MASK,
628 src_clk << CLK_PWM1_SEL_SHIFT);
629 break;
630 case CLK_PWM2:
631 rk_clrsetreg(&cru->clksel_con[74],
632 CLK_PWM2_SEL_MASK,
633 src_clk << CLK_PWM2_SEL_SHIFT);
634 break;
635 case CLK_PMU1PWM:
636 rk_clrsetreg(&cru->pmuclksel_con[5],
637 CLK_PMU1PWM_SEL_MASK,
638 src_clk << CLK_PMU1PWM_SEL_SHIFT);
639 break;
640 default:
641 return -ENOENT;
642 }
643
644 return rk3576_pwm_get_clk(priv, clk_id);
645}
646
647static ulong rk3576_adc_get_clk(struct rk3576_clk_priv *priv, ulong clk_id)
648{
649 struct rk3576_cru *cru = priv->cru;
650 u32 div, sel, con, prate;
651
652 switch (clk_id) {
653 case CLK_SARADC:
654 con = readl(&cru->clksel_con[58]);
655 div = (con & CLK_SARADC_DIV_MASK) >> CLK_SARADC_DIV_SHIFT;
656 sel = (con & CLK_SARADC_SEL_MASK) >>
657 CLK_SARADC_SEL_SHIFT;
658 if (sel == CLK_SARADC_SEL_OSC)
659 prate = OSC_HZ;
660 else
661 prate = priv->gpll_hz;
662 return DIV_TO_RATE(prate, div);
663 case CLK_TSADC:
664 con = readl(&cru->clksel_con[59]);
665 div = (con & CLK_TSADC_DIV_MASK) >>
666 CLK_TSADC_DIV_SHIFT;
667 prate = OSC_HZ;
668 return DIV_TO_RATE(prate, div);
669 default:
670 return -ENOENT;
671 }
672}
673
674static ulong rk3576_adc_set_clk(struct rk3576_clk_priv *priv,
675 ulong clk_id, ulong rate)
676{
677 struct rk3576_cru *cru = priv->cru;
678 int src_clk_div;
679
680 switch (clk_id) {
681 case CLK_SARADC:
682 if (!(OSC_HZ % rate)) {
683 src_clk_div = DIV_ROUND_UP(OSC_HZ, rate);
684 assert(src_clk_div - 1 <= 255);
685 rk_clrsetreg(&cru->clksel_con[58],
686 CLK_SARADC_SEL_MASK |
687 CLK_SARADC_DIV_MASK,
688 (CLK_SARADC_SEL_OSC <<
689 CLK_SARADC_SEL_SHIFT) |
690 (src_clk_div - 1) <<
691 CLK_SARADC_DIV_SHIFT);
692 } else {
693 src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
694 assert(src_clk_div - 1 <= 255);
695 rk_clrsetreg(&cru->clksel_con[59],
696 CLK_SARADC_SEL_MASK |
697 CLK_SARADC_DIV_MASK,
698 (CLK_SARADC_SEL_GPLL <<
699 CLK_SARADC_SEL_SHIFT) |
700 (src_clk_div - 1) <<
701 CLK_SARADC_DIV_SHIFT);
702 }
703 break;
704 case CLK_TSADC:
705 src_clk_div = DIV_ROUND_UP(OSC_HZ, rate);
706 assert(src_clk_div - 1 <= 255);
707 rk_clrsetreg(&cru->clksel_con[58],
708 CLK_TSADC_DIV_MASK,
709 (src_clk_div - 1) <<
710 CLK_TSADC_DIV_SHIFT);
711 break;
712 default:
713 return -ENOENT;
714 }
715 return rk3576_adc_get_clk(priv, clk_id);
716}
717
718static ulong rk3576_mmc_get_clk(struct rk3576_clk_priv *priv, ulong clk_id)
719{
720 struct rk3576_cru *cru = priv->cru;
721 u32 sel, con, prate, div = 0;
722
723 switch (clk_id) {
724 case CCLK_SRC_SDIO:
725 case HCLK_SDIO:
726 con = readl(&cru->clksel_con[104]);
727 div = (con & CCLK_SDIO_SRC_DIV_MASK) >> CCLK_SDIO_SRC_DIV_SHIFT;
728 sel = (con & CCLK_SDIO_SRC_SEL_MASK) >>
729 CCLK_SDIO_SRC_SEL_SHIFT;
730 if (sel == CCLK_SDIO_SRC_SEL_GPLL)
731 prate = priv->gpll_hz;
732 else if (sel == CCLK_SDIO_SRC_SEL_CPLL)
733 prate = priv->cpll_hz;
734 else
735 prate = OSC_HZ;
736 return DIV_TO_RATE(prate, div);
737 case CCLK_SRC_SDMMC0:
738 case HCLK_SDMMC0:
739 con = readl(&cru->clksel_con[105]);
740 div = (con & CCLK_SDMMC0_SRC_DIV_MASK) >> CCLK_SDMMC0_SRC_DIV_SHIFT;
741 sel = (con & CCLK_SDMMC0_SRC_SEL_MASK) >>
742 CCLK_SDMMC0_SRC_SEL_SHIFT;
743 if (sel == CCLK_SDMMC0_SRC_SEL_GPLL)
744 prate = priv->gpll_hz;
745 else if (sel == CCLK_SDMMC0_SRC_SEL_CPLL)
746 prate = priv->cpll_hz;
747 else
748 prate = OSC_HZ;
749 return DIV_TO_RATE(prate, div);
750 case CCLK_SRC_EMMC:
751 case HCLK_EMMC:
752 con = readl(&cru->clksel_con[89]);
753 div = (con & CCLK_EMMC_DIV_MASK) >> CCLK_EMMC_DIV_SHIFT;
754 sel = (con & CCLK_EMMC_SEL_MASK) >>
755 CCLK_EMMC_SEL_SHIFT;
756 if (sel == CCLK_EMMC_SEL_GPLL)
757 prate = priv->gpll_hz;
758 else if (sel == CCLK_EMMC_SEL_CPLL)
759 prate = priv->cpll_hz;
760 else
761 prate = OSC_HZ;
762 return DIV_TO_RATE(prate, div);
763 case BCLK_EMMC:
764 con = readl(&cru->clksel_con[90]);
765 sel = (con & BCLK_EMMC_SEL_MASK) >>
766 BCLK_EMMC_SEL_SHIFT;
767 if (sel == BCLK_EMMC_SEL_200M)
768 prate = 200 * MHz;
769 else if (sel == BCLK_EMMC_SEL_100M)
770 prate = 100 * MHz;
771 else if (sel == BCLK_EMMC_SEL_50M)
772 prate = 50 * MHz;
773 else
774 prate = OSC_HZ;
775 return DIV_TO_RATE(prate, div);
776 case SCLK_FSPI_X2:
777 con = readl(&cru->clksel_con[89]);
778 div = (con & SCLK_FSPI_DIV_MASK) >> SCLK_FSPI_DIV_SHIFT;
779 sel = (con & SCLK_FSPI_SEL_MASK) >>
780 SCLK_FSPI_SEL_SHIFT;
781 if (sel == SCLK_FSPI_SEL_GPLL)
782 prate = priv->gpll_hz;
783 else if (sel == SCLK_FSPI_SEL_CPLL)
784 prate = priv->cpll_hz;
785 else
786 prate = OSC_HZ;
787 return DIV_TO_RATE(prate, div);
788 case SCLK_FSPI1_X2:
789 con = readl(&cru->clksel_con[106]);
790 div = (con & SCLK_FSPI_DIV_MASK) >> SCLK_FSPI_DIV_SHIFT;
791 sel = (con & SCLK_FSPI_SEL_MASK) >>
792 SCLK_FSPI_SEL_SHIFT;
793 if (sel == SCLK_FSPI_SEL_GPLL)
794 prate = priv->gpll_hz;
795 else if (sel == SCLK_FSPI_SEL_CPLL)
796 prate = priv->cpll_hz;
797 else
798 prate = OSC_HZ;
799 return DIV_TO_RATE(prate, div);
800 case DCLK_DECOM:
801 con = readl(&cru->clksel_con[72]);
802 div = (con & DCLK_DECOM_DIV_MASK) >> DCLK_DECOM_DIV_SHIFT;
803 sel = (con & DCLK_DECOM_SEL_MASK) >> DCLK_DECOM_SEL_SHIFT;
804 if (sel == DCLK_DECOM_SEL_SPLL)
805 prate = priv->spll_hz;
806 else
807 prate = priv->gpll_hz;
808 return DIV_TO_RATE(prate, div);
809
810 default:
811 return -ENOENT;
812 }
813}
814
815static ulong rk3576_mmc_set_clk(struct rk3576_clk_priv *priv,
816 ulong clk_id, ulong rate)
817{
818 struct rk3576_cru *cru = priv->cru;
819 int src_clk, div = 0;
820
821 switch (clk_id) {
822 case CCLK_SRC_SDIO:
823 case CCLK_SRC_SDMMC0:
824 case CCLK_SRC_EMMC:
825 case SCLK_FSPI_X2:
826 case SCLK_FSPI1_X2:
827 case HCLK_SDMMC0:
828 case HCLK_EMMC:
829 case HCLK_SDIO:
830 if (!(OSC_HZ % rate)) {
831 src_clk = SCLK_FSPI_SEL_OSC;
832 div = DIV_ROUND_UP(OSC_HZ, rate);
833 } else if (!(priv->cpll_hz % rate)) {
834 src_clk = SCLK_FSPI_SEL_CPLL;
835 div = DIV_ROUND_UP(priv->cpll_hz, rate);
836 } else {
837 src_clk = SCLK_FSPI_SEL_GPLL;
838 div = DIV_ROUND_UP(priv->gpll_hz, rate);
839 }
840 break;
841 case BCLK_EMMC:
842 if (rate >= 198 * MHz)
843 src_clk = BCLK_EMMC_SEL_200M;
844 else if (rate >= 99 * MHz)
845 src_clk = BCLK_EMMC_SEL_100M;
846 else if (rate >= 50 * MHz)
847 src_clk = BCLK_EMMC_SEL_50M;
848 else
849 src_clk = BCLK_EMMC_SEL_OSC;
850 break;
851 case DCLK_DECOM:
852 if (!(priv->spll_hz % rate)) {
853 src_clk = DCLK_DECOM_SEL_SPLL;
854 div = DIV_ROUND_UP(priv->spll_hz, rate);
855 } else {
856 src_clk = DCLK_DECOM_SEL_GPLL;
857 div = DIV_ROUND_UP(priv->gpll_hz, rate);
858 }
859 break;
860 default:
861 return -ENOENT;
862 }
863
864 switch (clk_id) {
865 case CCLK_SRC_SDIO:
866 case HCLK_SDIO:
867 rk_clrsetreg(&cru->clksel_con[104],
868 CCLK_SDIO_SRC_SEL_MASK |
869 CCLK_SDIO_SRC_DIV_MASK,
870 (src_clk << CCLK_SDIO_SRC_SEL_SHIFT) |
871 (div - 1) << CCLK_SDIO_SRC_DIV_SHIFT);
872 break;
873 case CCLK_SRC_SDMMC0:
874 case HCLK_SDMMC0:
875 rk_clrsetreg(&cru->clksel_con[105],
876 CCLK_SDMMC0_SRC_SEL_MASK |
877 CCLK_SDMMC0_SRC_DIV_MASK,
878 (src_clk << CCLK_SDMMC0_SRC_SEL_SHIFT) |
879 (div - 1) << CCLK_SDMMC0_SRC_DIV_SHIFT);
880 break;
881 case CCLK_SRC_EMMC:
882 case HCLK_EMMC:
883 rk_clrsetreg(&cru->clksel_con[89],
884 CCLK_EMMC_DIV_MASK |
885 CCLK_EMMC_SEL_MASK,
886 (src_clk << CCLK_EMMC_SEL_SHIFT) |
887 (div - 1) << CCLK_EMMC_DIV_SHIFT);
888 break;
889 case SCLK_FSPI_X2:
890 rk_clrsetreg(&cru->clksel_con[89],
891 SCLK_FSPI_DIV_MASK |
892 SCLK_FSPI_SEL_MASK,
893 (src_clk << SCLK_FSPI_SEL_SHIFT) |
894 (div - 1) << SCLK_FSPI_DIV_SHIFT);
895 break;
896 case SCLK_FSPI1_X2:
897 rk_clrsetreg(&cru->clksel_con[106],
898 SCLK_FSPI_DIV_MASK |
899 SCLK_FSPI_SEL_MASK,
900 (src_clk << SCLK_FSPI_SEL_SHIFT) |
901 (div - 1) << SCLK_FSPI_DIV_SHIFT);
902 break;
903 case BCLK_EMMC:
904 rk_clrsetreg(&cru->clksel_con[90],
905 BCLK_EMMC_SEL_MASK,
906 src_clk << BCLK_EMMC_SEL_SHIFT);
907 break;
908 case DCLK_DECOM:
909 rk_clrsetreg(&cru->clksel_con[72],
910 DCLK_DECOM_DIV_MASK |
911 DCLK_DECOM_SEL_MASK,
912 (src_clk << DCLK_DECOM_SEL_SHIFT) |
913 (div - 1) << DCLK_DECOM_DIV_SHIFT);
914 break;
915
916 default:
917 return -ENOENT;
918 }
919
920 return rk3576_mmc_get_clk(priv, clk_id);
921}
922
923#ifndef CONFIG_SPL_BUILD
924
925static ulong rk3576_aclk_vop_get_clk(struct rk3576_clk_priv *priv, ulong clk_id)
926{
927 struct rk3576_cru *cru = priv->cru;
928 u32 div, sel, con, parent = 0;
929
930 switch (clk_id) {
931 case ACLK_VOP_ROOT:
932 case ACLK_VOP:
933 con = readl(&cru->clksel_con[144]);
934 div = (con & ACLK_VOP_ROOT_DIV_MASK) >> ACLK_VOP_ROOT_DIV_SHIFT;
935 sel = (con & ACLK_VOP_ROOT_SEL_MASK) >> ACLK_VOP_ROOT_SEL_SHIFT;
936 if (sel == ACLK_VOP_ROOT_SEL_GPLL)
937 parent = priv->gpll_hz;
938 else if (sel == ACLK_VOP_ROOT_SEL_CPLL)
939 parent = priv->cpll_hz;
940 else if (sel == ACLK_VOP_ROOT_SEL_AUPLL)
941 parent = priv->aupll_hz;
942 else if (sel == ACLK_VOP_ROOT_SEL_SPLL)
943 parent = priv->spll_hz;
944 else if (sel == ACLK_VOP_ROOT_SEL_LPLL)
945 parent = priv->lpll_hz / 2;
946 return DIV_TO_RATE(parent, div);
947 case ACLK_VO0_ROOT:
948 con = readl(&cru->clksel_con[149]);
949 div = (con & ACLK_VO0_ROOT_DIV_MASK) >> ACLK_VO0_ROOT_DIV_SHIFT;
950 sel = (con & ACLK_VO0_ROOT_SEL_MASK) >> ACLK_VO0_ROOT_SEL_SHIFT;
951 if (sel == ACLK_VO0_ROOT_SEL_GPLL)
952 parent = priv->gpll_hz;
953 else if (sel == ACLK_VO0_ROOT_SEL_CPLL)
954 parent = priv->cpll_hz;
955 else if (sel == ACLK_VO0_ROOT_SEL_LPLL)
956 parent = priv->lpll_hz / 2;
957 else if (sel == ACLK_VO0_ROOT_SEL_BPLL)
958 parent = priv->bpll_hz / 4;
959 return DIV_TO_RATE(parent, div);
960 case ACLK_VO1_ROOT:
961 con = readl(&cru->clksel_con[158]);
962 div = (con & ACLK_VO0_ROOT_DIV_MASK) >> ACLK_VO0_ROOT_DIV_SHIFT;
963 sel = (con & ACLK_VO0_ROOT_SEL_MASK) >> ACLK_VO0_ROOT_SEL_SHIFT;
964 if (sel == ACLK_VO0_ROOT_SEL_GPLL)
965 parent = priv->gpll_hz;
966 else if (sel == ACLK_VO0_ROOT_SEL_CPLL)
967 parent = priv->cpll_hz;
968 else if (sel == ACLK_VO0_ROOT_SEL_LPLL)
969 parent = priv->lpll_hz / 2;
970 else if (sel == ACLK_VO0_ROOT_SEL_BPLL)
971 parent = priv->bpll_hz / 4;
972 return DIV_TO_RATE(parent, div);
973 case HCLK_VOP_ROOT:
974 con = readl(&cru->clksel_con[144]);
975 sel = (con & HCLK_VOP_ROOT_SEL_MASK) >> HCLK_VOP_ROOT_SEL_SHIFT;
976 if (sel == HCLK_VOP_ROOT_SEL_200M)
977 return 200 * MHz;
978 else if (sel == HCLK_VOP_ROOT_SEL_100M)
979 return 100 * MHz;
980 else if (sel == HCLK_VOP_ROOT_SEL_50M)
981 return 50 * MHz;
982 else
983 return OSC_HZ;
984 case PCLK_VOP_ROOT:
985 con = readl(&cru->clksel_con[144]);
986 sel = (con & PCLK_VOP_ROOT_SEL_MASK) >> PCLK_VOP_ROOT_SEL_SHIFT;
987 if (sel == PCLK_VOP_ROOT_SEL_100M)
988 return 100 * MHz;
989 else if (sel == PCLK_VOP_ROOT_SEL_50M)
990 return 50 * MHz;
991 else
992 return OSC_HZ;
993
994 default:
995 return -ENOENT;
996 }
997}
998
999static ulong rk3576_aclk_vop_set_clk(struct rk3576_clk_priv *priv,
1000 ulong clk_id, ulong rate)
1001{
1002 struct rk3576_cru *cru = priv->cru;
1003 int src_clk, div;
1004
1005 switch (clk_id) {
1006 case ACLK_VOP_ROOT:
1007 case ACLK_VOP:
1008 if (rate == 700 * MHz) {
1009 src_clk = ACLK_VOP_ROOT_SEL_SPLL;
1010 div = 1;
1011 } else if (!(priv->cpll_hz % rate)) {
1012 src_clk = ACLK_VOP_ROOT_SEL_CPLL;
1013 div = DIV_ROUND_UP(priv->cpll_hz, rate);
1014 } else {
1015 src_clk = ACLK_VOP_ROOT_SEL_GPLL;
1016 div = DIV_ROUND_UP(priv->gpll_hz, rate);
1017 }
1018 rk_clrsetreg(&cru->clksel_con[144],
1019 ACLK_VOP_ROOT_DIV_MASK |
1020 ACLK_VOP_ROOT_SEL_MASK,
1021 (src_clk << ACLK_VOP_ROOT_SEL_SHIFT) |
1022 (div - 1) << ACLK_VOP_ROOT_DIV_SHIFT);
1023 break;
1024 case ACLK_VO0_ROOT:
1025 if (!(priv->cpll_hz % rate)) {
1026 src_clk = ACLK_VO0_ROOT_SEL_CPLL;
1027 div = DIV_ROUND_UP(priv->cpll_hz, rate);
1028 } else {
1029 src_clk = ACLK_VO0_ROOT_SEL_GPLL;
1030 div = DIV_ROUND_UP(priv->gpll_hz, rate);
1031 }
1032 rk_clrsetreg(&cru->clksel_con[149],
1033 ACLK_VO0_ROOT_DIV_MASK |
1034 ACLK_VO0_ROOT_SEL_MASK,
1035 (src_clk << ACLK_VO0_ROOT_SEL_SHIFT) |
1036 (div - 1) << ACLK_VO0_ROOT_DIV_SHIFT);
1037 break;
1038 case ACLK_VO1_ROOT:
1039 if (!(priv->cpll_hz % rate)) {
1040 src_clk = ACLK_VO0_ROOT_SEL_CPLL;
1041 div = DIV_ROUND_UP(priv->cpll_hz, rate);
1042 } else {
1043 src_clk = ACLK_VO0_ROOT_SEL_GPLL;
1044 div = DIV_ROUND_UP(priv->gpll_hz, rate);
1045 }
1046 rk_clrsetreg(&cru->clksel_con[158],
1047 ACLK_VO0_ROOT_DIV_MASK |
1048 ACLK_VO0_ROOT_SEL_MASK,
1049 (src_clk << ACLK_VO0_ROOT_SEL_SHIFT) |
1050 (div - 1) << ACLK_VO0_ROOT_DIV_SHIFT);
1051 break;
1052 case HCLK_VOP_ROOT:
1053 if (rate == 200 * MHz)
1054 src_clk = HCLK_VOP_ROOT_SEL_200M;
1055 else if (rate == 100 * MHz)
1056 src_clk = HCLK_VOP_ROOT_SEL_100M;
1057 else if (rate == 50 * MHz)
1058 src_clk = HCLK_VOP_ROOT_SEL_50M;
1059 else
1060 src_clk = HCLK_VOP_ROOT_SEL_OSC;
1061 rk_clrsetreg(&cru->clksel_con[144],
1062 HCLK_VOP_ROOT_SEL_MASK,
1063 src_clk << HCLK_VOP_ROOT_SEL_SHIFT);
1064 break;
1065 case PCLK_VOP_ROOT:
1066 if (rate == 100 * MHz)
1067 src_clk = PCLK_VOP_ROOT_SEL_100M;
1068 else if (rate == 50 * MHz)
1069 src_clk = PCLK_VOP_ROOT_SEL_50M;
1070 else
1071 src_clk = PCLK_VOP_ROOT_SEL_OSC;
1072 rk_clrsetreg(&cru->clksel_con[144],
1073 PCLK_VOP_ROOT_SEL_MASK,
1074 src_clk << PCLK_VOP_ROOT_SEL_SHIFT);
1075 break;
1076
1077 default:
1078 return -ENOENT;
1079 }
1080
1081 return rk3576_aclk_vop_get_clk(priv, clk_id);
1082}
1083
1084static ulong rk3576_dclk_vop_get_clk(struct rk3576_clk_priv *priv, ulong clk_id)
1085{
1086 struct rk3576_cru *cru = priv->cru;
1087 u32 div, sel, con, parent;
1088
1089 switch (clk_id) {
1090 case DCLK_VP0:
1091 case DCLK_VP0_SRC:
1092 con = readl(&cru->clksel_con[145]);
1093 div = (con & DCLK0_VOP_SRC_DIV_MASK) >> DCLK0_VOP_SRC_DIV_SHIFT;
1094 sel = (con & DCLK0_VOP_SRC_SEL_MASK) >> DCLK0_VOP_SRC_SEL_SHIFT;
1095 break;
1096 case DCLK_VP1:
1097 case DCLK_VP1_SRC:
1098 con = readl(&cru->clksel_con[146]);
1099 div = (con & DCLK0_VOP_SRC_DIV_MASK) >> DCLK0_VOP_SRC_DIV_SHIFT;
1100 sel = (con & DCLK0_VOP_SRC_SEL_MASK) >> DCLK0_VOP_SRC_SEL_SHIFT;
1101 break;
1102 case DCLK_VP2:
1103 case DCLK_VP2_SRC:
1104 con = readl(&cru->clksel_con[147]);
1105 div = (con & DCLK0_VOP_SRC_DIV_MASK) >> DCLK0_VOP_SRC_DIV_SHIFT;
1106 sel = (con & DCLK0_VOP_SRC_SEL_MASK) >> DCLK0_VOP_SRC_SEL_SHIFT;
1107 break;
1108 default:
1109 return -ENOENT;
1110 }
1111
1112 if (sel == DCLK_VOP_SRC_SEL_VPLL)
1113 parent = priv->vpll_hz;
1114 else if (sel == DCLK_VOP_SRC_SEL_BPLL)
1115 parent = priv->bpll_hz / 4;
1116 else if (sel == DCLK_VOP_SRC_SEL_LPLL)
1117 parent = priv->lpll_hz / 2;
1118 else if (sel == DCLK_VOP_SRC_SEL_GPLL)
1119 parent = priv->gpll_hz;
1120 else
1121 parent = priv->cpll_hz;
1122
1123 return DIV_TO_RATE(parent, div);
1124}
1125
1126#define RK3576_VOP_PLL_LIMIT_FREQ 600000000
1127
1128static ulong rk3576_dclk_vop_set_clk(struct rk3576_clk_priv *priv,
1129 ulong clk_id, ulong rate)
1130{
1131 struct rk3576_cru *cru = priv->cru;
1132 ulong pll_rate, now, best_rate = 0;
1133 u32 i, conid, con, sel, div, best_div = 0, best_sel = 0;
1134 u32 mask, div_shift, sel_shift;
1135
1136 switch (clk_id) {
1137 case DCLK_VP0:
1138 case DCLK_VP0_SRC:
1139 conid = 145;
1140 con = readl(&cru->clksel_con[conid]);
1141 sel = (con & DCLK0_VOP_SRC_SEL_MASK) >> DCLK0_VOP_SRC_SEL_SHIFT;
1142 mask = DCLK0_VOP_SRC_SEL_MASK | DCLK0_VOP_SRC_DIV_MASK;
1143 div_shift = DCLK0_VOP_SRC_DIV_SHIFT;
1144 sel_shift = DCLK0_VOP_SRC_SEL_SHIFT;
1145 break;
1146 case DCLK_VP1:
1147 case DCLK_VP1_SRC:
1148 conid = 146;
1149 con = readl(&cru->clksel_con[conid]);
1150 sel = (con & DCLK0_VOP_SRC_SEL_MASK) >> DCLK0_VOP_SRC_SEL_SHIFT;
1151 mask = DCLK0_VOP_SRC_SEL_MASK | DCLK0_VOP_SRC_DIV_MASK;
1152 div_shift = DCLK0_VOP_SRC_DIV_SHIFT;
1153 sel_shift = DCLK0_VOP_SRC_SEL_SHIFT;
1154 break;
1155 case DCLK_VP2:
1156 case DCLK_VP2_SRC:
1157 conid = 147;
1158 con = readl(&cru->clksel_con[conid]);
1159 sel = (con & DCLK0_VOP_SRC_SEL_MASK) >> DCLK0_VOP_SRC_SEL_SHIFT;
1160 mask = DCLK0_VOP_SRC_SEL_MASK | DCLK0_VOP_SRC_DIV_MASK;
1161 div_shift = DCLK0_VOP_SRC_DIV_SHIFT;
1162 sel_shift = DCLK0_VOP_SRC_SEL_SHIFT;
1163 break;
1164 default:
1165 return -ENOENT;
1166 }
1167
1168 if (sel == DCLK_VOP_SRC_SEL_VPLL) {
1169 pll_rate = rockchip_pll_get_rate(&rk3576_pll_clks[VPLL],
1170 priv->cru, VPLL);
1171 if (pll_rate >= RK3576_VOP_PLL_LIMIT_FREQ && pll_rate % rate == 0) {
1172 div = DIV_ROUND_UP(pll_rate, rate);
1173 rk_clrsetreg(&cru->clksel_con[conid],
1174 mask,
1175 DCLK_VOP_SRC_SEL_VPLL << sel_shift |
1176 ((div - 1) << div_shift));
1177 } else {
1178 div = DIV_ROUND_UP(RK3576_VOP_PLL_LIMIT_FREQ, rate);
1179 if (div % 2)
1180 div = div + 1;
1181 rk_clrsetreg(&cru->clksel_con[conid],
1182 mask,
1183 DCLK_VOP_SRC_SEL_VPLL << sel_shift |
1184 ((div - 1) << div_shift));
1185 rockchip_pll_set_rate(&rk3576_pll_clks[VPLL],
1186 priv->cru, VPLL, div * rate);
1187 priv->vpll_hz = rockchip_pll_get_rate(&rk3576_pll_clks[VPLL],
1188 priv->cru, VPLL);
1189 }
1190 } else {
1191 for (i = 0; i <= DCLK_VOP_SRC_SEL_LPLL; i++) {
1192 switch (i) {
1193 case DCLK_VOP_SRC_SEL_GPLL:
1194 pll_rate = priv->gpll_hz;
1195 break;
1196 case DCLK_VOP_SRC_SEL_CPLL:
1197 pll_rate = priv->cpll_hz;
1198 break;
1199 case DCLK_VOP_SRC_SEL_BPLL:
1200 pll_rate = 0;
1201 break;
1202 case DCLK_VOP_SRC_SEL_LPLL:
1203 pll_rate = 0;
1204 break;
1205 case DCLK_VOP_SRC_SEL_VPLL:
1206 pll_rate = 0;
1207 break;
1208 default:
1209 printf("do not support this vop pll sel\n");
1210 return -EINVAL;
1211 }
1212
1213 div = DIV_ROUND_UP(pll_rate, rate);
1214 if (div > 255)
1215 continue;
1216 now = pll_rate / div;
1217 if (abs(rate - now) < abs(rate - best_rate)) {
1218 best_rate = now;
1219 best_div = div;
1220 best_sel = i;
1221 }
1222 debug("p_rate=%lu, best_rate=%lu, div=%u, sel=%u\n",
1223 pll_rate, best_rate, best_div, best_sel);
1224 }
1225
1226 if (best_rate) {
1227 rk_clrsetreg(&cru->clksel_con[conid],
1228 mask,
1229 best_sel << sel_shift |
1230 (best_div - 1) << div_shift);
1231 } else {
1232 printf("do not support this vop freq %lu\n", rate);
1233 return -EINVAL;
1234 }
1235 }
1236
1237 return rk3576_dclk_vop_get_clk(priv, clk_id);
1238}
1239
1240static ulong rk3576_clk_csihost_get_clk(struct rk3576_clk_priv *priv, ulong clk_id)
1241{
1242 struct rk3576_cru *cru = priv->cru;
1243 u32 div, sel, con, parent;
1244
1245 switch (clk_id) {
1246 case CLK_DSIHOST0:
1247 con = readl(&cru->clksel_con[151]);
1248 div = (con & CLK_DSIHOST0_DIV_MASK) >> CLK_DSIHOST0_DIV_SHIFT;
1249 sel = (con & CLK_DSIHOST0_SEL_MASK) >> CLK_DSIHOST0_SEL_SHIFT;
1250 break;
1251 default:
1252 return -ENOENT;
1253 }
1254
1255 if (sel == CLK_DSIHOST0_SEL_VPLL)
1256 parent = priv->vpll_hz;
1257 else if (sel == CLK_DSIHOST0_SEL_BPLL)
1258 parent = priv->bpll_hz / 4;
1259 else if (sel == CLK_DSIHOST0_SEL_LPLL)
1260 parent = priv->lpll_hz / 2;
1261 else if (sel == CLK_DSIHOST0_SEL_GPLL)
1262 parent = priv->gpll_hz;
1263 else if (sel == CLK_DSIHOST0_SEL_SPLL)
1264 parent = priv->spll_hz;
1265 else
1266 parent = priv->cpll_hz;
1267
1268 return DIV_TO_RATE(parent, div);
1269}
1270
1271static ulong rk3576_clk_csihost_set_clk(struct rk3576_clk_priv *priv,
1272 ulong clk_id, ulong rate)
1273{
1274 struct rk3576_cru *cru = priv->cru;
1275 ulong pll_rate, now, best_rate = 0;
1276 u32 i, con, div, best_div = 0, best_sel = 0;
1277 u32 mask, div_shift, sel_shift;
1278
1279 switch (clk_id) {
1280 case CLK_DSIHOST0:
1281 con = 151;
1282 mask = CLK_DSIHOST0_SEL_MASK | CLK_DSIHOST0_DIV_MASK;
1283 div_shift = CLK_DSIHOST0_DIV_SHIFT;
1284 sel_shift = CLK_DSIHOST0_SEL_SHIFT;
1285 break;
1286 default:
1287 return -ENOENT;
1288 }
1289 for (i = 0; i <= CLK_DSIHOST0_SEL_LPLL; i++) {
1290 switch (i) {
1291 case CLK_DSIHOST0_SEL_GPLL:
1292 pll_rate = priv->gpll_hz;
1293 break;
1294 case CLK_DSIHOST0_SEL_CPLL:
1295 pll_rate = priv->cpll_hz;
1296 break;
1297 case CLK_DSIHOST0_SEL_BPLL:
1298 pll_rate = 0;
1299 break;
1300 case CLK_DSIHOST0_SEL_LPLL:
1301 pll_rate = 0;
1302 break;
1303 case CLK_DSIHOST0_SEL_VPLL:
1304 pll_rate = 0;
1305 break;
1306 case CLK_DSIHOST0_SEL_SPLL:
1307 pll_rate = priv->spll_hz;
1308 break;
1309 default:
1310 printf("do not support this vop pll sel\n");
1311 return -EINVAL;
1312 }
1313
1314 div = DIV_ROUND_UP(pll_rate, rate);
1315 if (div > 255)
1316 continue;
1317 now = pll_rate / div;
1318 if (abs(rate - now) < abs(rate - best_rate)) {
1319 best_rate = now;
1320 best_div = div;
1321 best_sel = i;
1322 }
1323 debug("p_rate=%lu, best_rate=%lu, div=%u, sel=%u\n",
1324 pll_rate, best_rate, best_div, best_sel);
1325 }
1326
1327 if (best_rate) {
1328 rk_clrsetreg(&cru->clksel_con[con],
1329 mask,
1330 best_sel << sel_shift |
1331 (best_div - 1) << div_shift);
1332 } else {
1333 printf("do not support this vop freq %lu\n", rate);
1334 return -EINVAL;
1335 }
1336
1337 return rk3576_clk_csihost_get_clk(priv, clk_id);
1338}
1339
1340static ulong rk3576_dclk_ebc_get_clk(struct rk3576_clk_priv *priv, ulong clk_id)
1341{
1342 struct rk3576_cru *cru = priv->cru;
1343 u32 div, sel, con, parent;
1344 unsigned long m = 0, n = 0;
1345
1346 switch (clk_id) {
1347 case DCLK_EBC:
1348 con = readl(&cru->clksel_con[123]);
1349 div = (con & DCLK_EBC_DIV_MASK) >> DCLK_EBC_DIV_SHIFT;
1350 sel = (con & DCLK_EBC_SEL_MASK) >> DCLK_EBC_SEL_SHIFT;
1351 if (sel == DCLK_EBC_SEL_CPLL)
1352 parent = priv->cpll_hz;
1353 else if (sel == DCLK_EBC_SEL_VPLL)
1354 parent = priv->vpll_hz;
1355 else if (sel == DCLK_EBC_SEL_AUPLL)
1356 parent = priv->aupll_hz;
1357 else if (sel == DCLK_EBC_SEL_LPLL)
1358 parent = priv->lpll_hz / 2;
1359 else if (sel == DCLK_EBC_SEL_GPLL)
1360 parent = priv->gpll_hz;
1361 else if (sel == DCLK_EBC_SEL_FRAC_SRC)
1362 parent = rk3576_dclk_ebc_get_clk(priv, DCLK_EBC_FRAC_SRC);
1363 else
1364 parent = OSC_HZ;
1365 return DIV_TO_RATE(parent, div);
1366 case DCLK_EBC_FRAC_SRC:
1367 con = readl(&cru->clksel_con[123]);
1368 div = readl(&cru->clksel_con[122]);
1369 sel = (con & DCLK_EBC_FRAC_SRC_SEL_MASK) >> DCLK_EBC_FRAC_SRC_SEL_SHIFT;
1370 if (sel == DCLK_EBC_FRAC_SRC_SEL_GPLL)
1371 parent = priv->gpll_hz;
1372 else if (sel == DCLK_EBC_FRAC_SRC_SEL_CPLL)
1373 parent = priv->cpll_hz;
1374 else if (sel == DCLK_EBC_FRAC_SRC_SEL_VPLL)
1375 parent = priv->vpll_hz;
1376 else if (sel == DCLK_EBC_FRAC_SRC_SEL_AUPLL)
1377 parent = priv->aupll_hz;
1378 else
1379 parent = OSC_HZ;
1380
1381 n = div & CLK_UART_FRAC_NUMERATOR_MASK;
1382 n >>= CLK_UART_FRAC_NUMERATOR_SHIFT;
1383 m = div & CLK_UART_FRAC_DENOMINATOR_MASK;
1384 m >>= CLK_UART_FRAC_DENOMINATOR_SHIFT;
1385 return parent * n / m;
1386 default:
1387 return -ENOENT;
1388 }
1389}
1390
1391static ulong rk3576_dclk_ebc_set_clk(struct rk3576_clk_priv *priv,
1392 ulong clk_id, ulong rate)
1393{
1394 struct rk3576_cru *cru = priv->cru;
1395 ulong pll_rate, now, best_rate = 0;
1396 u32 i, con, sel, div, best_div = 0, best_sel = 0;
1397 unsigned long m = 0, n = 0, val;
1398
1399 switch (clk_id) {
1400 case DCLK_EBC:
1401 con = readl(&cru->clksel_con[123]);
1402 sel = (con & DCLK_EBC_SEL_MASK) >> DCLK_EBC_SEL_SHIFT;
1403 if (sel == DCLK_EBC_SEL_VPLL) {
1404 pll_rate = rockchip_pll_get_rate(&rk3576_pll_clks[VPLL],
1405 priv->cru, VPLL);
1406 if (pll_rate >= RK3576_VOP_PLL_LIMIT_FREQ &&
1407 pll_rate % rate == 0) {
1408 div = DIV_ROUND_UP(pll_rate, rate);
1409 rk_clrsetreg(&cru->clksel_con[123],
1410 DCLK_EBC_DIV_MASK,
1411 (div - 1) << DCLK_EBC_DIV_SHIFT);
1412 } else {
1413 div = DIV_ROUND_UP(RK3576_VOP_PLL_LIMIT_FREQ,
1414 rate);
1415 if (div % 2)
1416 div = div + 1;
1417 rk_clrsetreg(&cru->clksel_con[123],
1418 DCLK_EBC_DIV_MASK,
1419 (div - 1) << DCLK_EBC_DIV_SHIFT);
1420 rockchip_pll_set_rate(&rk3576_pll_clks[VPLL],
1421 priv->cru,
1422 VPLL, div * rate);
1423 priv->vpll_hz = rockchip_pll_get_rate(&rk3576_pll_clks[VPLL],
1424 priv->cru,
1425 VPLL);
1426 }
1427 } else if (sel == DCLK_EBC_SEL_FRAC_SRC) {
1428 rk3576_dclk_ebc_set_clk(priv, DCLK_EBC_FRAC_SRC, rate);
1429 div = rk3576_dclk_ebc_get_clk(priv, DCLK_EBC_FRAC_SRC) / rate;
1430 rk_clrsetreg(&cru->clksel_con[123],
1431 DCLK_EBC_DIV_MASK,
1432 (div - 1) << DCLK_EBC_DIV_SHIFT);
1433 } else {
1434 for (i = 0; i <= DCLK_EBC_SEL_LPLL; i++) {
1435 switch (i) {
1436 case DCLK_EBC_SEL_GPLL:
1437 pll_rate = priv->gpll_hz;
1438 break;
1439 case DCLK_EBC_SEL_CPLL:
1440 pll_rate = priv->cpll_hz;
1441 break;
1442 case DCLK_EBC_SEL_VPLL:
1443 pll_rate = 0;
1444 break;
1445 case DCLK_EBC_SEL_AUPLL:
1446 pll_rate = priv->aupll_hz;
1447 break;
1448 case DCLK_EBC_SEL_LPLL:
1449 pll_rate = 0;
1450 break;
1451 default:
1452 printf("not support ebc pll sel\n");
1453 return -EINVAL;
1454 }
1455
1456 div = DIV_ROUND_UP(pll_rate, rate);
1457 if (div > 255)
1458 continue;
1459 now = pll_rate / div;
1460 if (abs(rate - now) < abs(rate - best_rate)) {
1461 best_rate = now;
1462 best_div = div;
1463 best_sel = i;
1464 }
1465 }
1466
1467 if (best_rate) {
1468 rk_clrsetreg(&cru->clksel_con[123],
1469 DCLK_EBC_DIV_MASK |
1470 DCLK_EBC_SEL_MASK,
1471 best_sel <<
1472 DCLK_EBC_SEL_SHIFT |
1473 (best_div - 1) <<
1474 DCLK_EBC_DIV_SHIFT);
1475 } else {
1476 printf("do not support this vop freq %lu\n",
1477 rate);
1478 return -EINVAL;
1479 }
1480 }
1481 break;
1482 case DCLK_EBC_FRAC_SRC:
1483 sel = DCLK_EBC_FRAC_SRC_SEL_GPLL;
1484 div = 1;
1485 rational_best_approximation(rate, priv->gpll_hz,
1486 GENMASK(16 - 1, 0),
1487 GENMASK(16 - 1, 0),
1488 &m, &n);
1489
1490 if (m < 4 && m != 0) {
1491 if (n % 2 == 0)
1492 val = 1;
1493 else
1494 val = DIV_ROUND_UP(4, m);
1495
1496 n *= val;
1497 m *= val;
1498 if (n > 0xffff)
1499 n = 0xffff;
1500 }
1501
1502 rk_clrsetreg(&cru->clksel_con[123],
1503 DCLK_EBC_FRAC_SRC_SEL_MASK,
1504 (sel << DCLK_EBC_FRAC_SRC_SEL_SHIFT));
1505 if (m && n) {
1506 val = m << CLK_UART_FRAC_NUMERATOR_SHIFT | n;
1507 writel(val, &cru->clksel_con[122]);
1508 }
1509 break;
1510 default:
1511 return -ENOENT;
1512 }
1513 return rk3576_dclk_ebc_get_clk(priv, clk_id);
1514}
1515
1516static ulong rk3576_gmac_get_clk(struct rk3576_clk_priv *priv, ulong clk_id)
1517{
1518 struct rk3576_cru *cru = priv->cru;
1519 u32 con, div, src, p_rate;
1520
1521 switch (clk_id) {
1522 case CLK_GMAC0_PTP_REF_SRC:
1523 case CLK_GMAC0_PTP_REF:
1524 con = readl(&cru->clksel_con[105]);
1525 div = (con & CLK_GMAC0_PTP_DIV_MASK) >> CLK_GMAC0_PTP_DIV_SHIFT;
1526 src = (con & CLK_GMAC0_PTP_SEL_MASK) >> CLK_GMAC0_PTP_SEL_SHIFT;
1527 if (src == CLK_GMAC0_PTP_SEL_GPLL)
1528 p_rate = priv->gpll_hz;
1529 else if (src == CLK_GMAC0_PTP_SEL_CPLL)
1530 p_rate = priv->cpll_hz;
1531 else
1532 p_rate = GMAC0_PTP_REFCLK_IN;
1533 return DIV_TO_RATE(p_rate, div);
1534 case CLK_GMAC1_PTP_REF_SRC:
1535 case CLK_GMAC1_PTP_REF:
1536 con = readl(&cru->clksel_con[104]);
1537 div = (con & CLK_GMAC1_PTP_DIV_MASK) >> CLK_GMAC0_PTP_DIV_SHIFT;
1538 src = (con & CLK_GMAC1_PTP_SEL_MASK) >> CLK_GMAC1_PTP_SEL_SHIFT;
1539 if (src == CLK_GMAC1_PTP_SEL_GPLL)
1540 p_rate = priv->gpll_hz;
1541 else if (src == CLK_GMAC1_PTP_SEL_CPLL)
1542 p_rate = priv->cpll_hz;
1543 else
1544 p_rate = GMAC1_PTP_REFCLK_IN;
1545 return DIV_TO_RATE(p_rate, div);
1546 case CLK_GMAC0_125M_SRC:
1547 con = readl(&cru->clksel_con[30]);
1548 div = (con & CLK_GMAC0_125M_DIV_MASK) >> CLK_GMAC0_125M_DIV_SHIFT;
1549 return DIV_TO_RATE(priv->cpll_hz, div);
1550 case CLK_GMAC1_125M_SRC:
1551 con = readl(&cru->clksel_con[31]);
1552 div = (con & CLK_GMAC1_125M_DIV_MASK) >> CLK_GMAC1_125M_DIV_SHIFT;
1553 return DIV_TO_RATE(priv->cpll_hz, div);
1554 default:
1555 return -ENOENT;
1556 }
1557}
1558
1559static ulong rk3576_gmac_set_clk(struct rk3576_clk_priv *priv,
1560 ulong clk_id, ulong rate)
1561{
1562 struct rk3576_cru *cru = priv->cru;
1563 int div, src;
1564
1565 div = DIV_ROUND_UP(priv->cpll_hz, rate);
1566
1567 switch (clk_id) {
1568 case CLK_GMAC0_PTP_REF_SRC:
1569 case CLK_GMAC0_PTP_REF:
1570 if (rate == GMAC0_PTP_REFCLK_IN) {
1571 src = CLK_GMAC0_PTP_SEL_REFIN;
1572 div = 1;
1573 } else if (!(priv->gpll_hz % rate)) {
1574 src = CLK_GMAC0_PTP_SEL_GPLL;
1575 div = priv->gpll_hz / rate;
1576 } else {
1577 src = CLK_GMAC0_PTP_SEL_CPLL;
1578 div = priv->cpll_hz / rate;
1579 }
1580 rk_clrsetreg(&cru->clksel_con[105],
1581 CLK_GMAC0_PTP_DIV_MASK | CLK_GMAC0_PTP_SEL_MASK,
1582 src << CLK_GMAC0_PTP_SEL_SHIFT |
1583 (div - 1) << CLK_GMAC0_PTP_DIV_SHIFT);
1584 break;
1585 case CLK_GMAC1_PTP_REF_SRC:
1586 case CLK_GMAC1_PTP_REF:
1587 if (rate == GMAC1_PTP_REFCLK_IN) {
1588 src = CLK_GMAC1_PTP_SEL_REFIN;
1589 div = 1;
1590 } else if (!(priv->gpll_hz % rate)) {
1591 src = CLK_GMAC1_PTP_SEL_GPLL;
1592 div = priv->gpll_hz / rate;
1593 } else {
1594 src = CLK_GMAC1_PTP_SEL_CPLL;
1595 div = priv->cpll_hz / rate;
1596 }
1597 rk_clrsetreg(&cru->clksel_con[104],
1598 CLK_GMAC1_PTP_DIV_MASK | CLK_GMAC1_PTP_SEL_MASK,
1599 src << CLK_GMAC1_PTP_SEL_SHIFT |
1600 (div - 1) << CLK_GMAC1_PTP_DIV_SHIFT);
1601 break;
1602
1603 case CLK_GMAC0_125M_SRC:
1604 rk_clrsetreg(&cru->clksel_con[30],
1605 CLK_GMAC0_125M_DIV_MASK,
1606 (div - 1) << CLK_GMAC0_125M_DIV_SHIFT);
1607 break;
1608 case CLK_GMAC1_125M_SRC:
1609 rk_clrsetreg(&cru->clksel_con[31],
1610 CLK_GMAC1_125M_DIV_MASK,
1611 (div - 1) << CLK_GMAC1_125M_DIV_SHIFT);
1612 break;
1613 default:
1614 return -ENOENT;
1615 }
1616
1617 return rk3576_gmac_get_clk(priv, clk_id);
1618}
1619
1620static ulong rk3576_uart_frac_get_rate(struct rk3576_clk_priv *priv, ulong clk_id)
1621{
1622 struct rk3576_cru *cru = priv->cru;
1623 u32 reg, con, fracdiv, p_src, p_rate;
1624 unsigned long m, n;
1625
1626 switch (clk_id) {
1627 case CLK_UART_FRAC_0:
1628 reg = 21;
1629 break;
1630 case CLK_UART_FRAC_1:
1631 reg = 23;
1632 break;
1633 case CLK_UART_FRAC_2:
1634 reg = 25;
1635 break;
1636 default:
1637 return -ENOENT;
1638 }
1639 con = readl(&cru->clksel_con[reg + 1]);
1640 p_src = (con & CLK_UART_SRC_SEL_MASK) >> CLK_UART_SRC_SEL_SHIFT;
1641 if (p_src == CLK_UART_SRC_SEL_GPLL)
1642 p_rate = priv->gpll_hz;
1643 else if (p_src == CLK_UART_SRC_SEL_CPLL)
1644 p_rate = priv->cpll_hz;
1645 else if (p_src == CLK_UART_SRC_SEL_AUPLL)
1646 p_rate = priv->aupll_hz;
1647 else
1648 p_rate = OSC_HZ;
1649
1650 fracdiv = readl(&cru->clksel_con[reg]);
1651 n = fracdiv & CLK_UART_FRAC_NUMERATOR_MASK;
1652 n >>= CLK_UART_FRAC_NUMERATOR_SHIFT;
1653 m = fracdiv & CLK_UART_FRAC_DENOMINATOR_MASK;
1654 m >>= CLK_UART_FRAC_DENOMINATOR_SHIFT;
1655 return p_rate * n / m;
1656}
1657
1658static ulong rk3576_uart_frac_set_rate(struct rk3576_clk_priv *priv,
1659 ulong clk_id, ulong rate)
1660{
1661 struct rk3576_cru *cru = priv->cru;
1662 u32 reg, clk_src, p_rate;
1663 unsigned long m = 0, n = 0, val;
1664
1665 if (priv->cpll_hz % rate == 0) {
1666 clk_src = CLK_UART_SRC_SEL_CPLL;
1667 p_rate = priv->cpll_hz;
1668 } else if (rate == OSC_HZ) {
1669 clk_src = CLK_UART_SRC_SEL_OSC;
1670 p_rate = OSC_HZ;
1671 } else {
1672 clk_src = CLK_UART_SRC_SEL_GPLL;
1673 p_rate = priv->cpll_hz;
1674 }
1675
1676 rational_best_approximation(rate, p_rate, GENMASK(16 - 1, 0),
1677 GENMASK(16 - 1, 0), &m, &n);
1678
1679 if (m < 4 && m != 0) {
1680 if (n % 2 == 0)
1681 val = 1;
1682 else
1683 val = DIV_ROUND_UP(4, m);
1684
1685 n *= val;
1686 m *= val;
1687 if (n > 0xffff)
1688 n = 0xffff;
1689 }
1690
1691 switch (clk_id) {
1692 case CLK_UART_FRAC_0:
1693 reg = 21;
1694 break;
1695 case CLK_UART_FRAC_1:
1696 reg = 23;
1697 break;
1698 case CLK_UART_FRAC_2:
1699 reg = 25;
1700 break;
1701 default:
1702 return -ENOENT;
1703 }
1704
1705 rk_clrsetreg(&cru->clksel_con[reg + 1],
1706 CLK_UART_SRC_SEL_MASK,
1707 (clk_src << CLK_UART_SRC_SEL_SHIFT));
1708 if (m && n) {
1709 val = m << CLK_UART_FRAC_NUMERATOR_SHIFT | n;
1710 writel(val, &cru->clksel_con[reg]);
1711 }
1712
1713 return rk3576_uart_frac_get_rate(priv, clk_id);
1714}
1715
1716static ulong rk3576_uart_get_rate(struct rk3576_clk_priv *priv, ulong clk_id)
1717{
1718 struct rk3576_cru *cru = priv->cru;
1719 u32 con, div, src, p_rate;
1720
1721 switch (clk_id) {
1722 case SCLK_UART0:
1723 con = readl(&cru->clksel_con[60]);
1724 break;
1725 case SCLK_UART1:
1726 con = readl(&cru->pmuclksel_con[8]);
1727 src = (con & CLK_UART1_SEL_MASK) >> CLK_UART1_SEL_SHIFT;
1728 if (src == CLK_UART1_SEL_OSC)
1729 return OSC_HZ;
1730 con = readl(&cru->clksel_con[27]);
1731 break;
1732 case SCLK_UART2:
1733 con = readl(&cru->clksel_con[61]);
1734 break;
1735 case SCLK_UART3:
1736 con = readl(&cru->clksel_con[62]);
1737 break;
1738 case SCLK_UART4:
1739 con = readl(&cru->clksel_con[63]);
1740 break;
1741 case SCLK_UART5:
1742 con = readl(&cru->clksel_con[64]);
1743 break;
1744 case SCLK_UART6:
1745 con = readl(&cru->clksel_con[65]);
1746 break;
1747 case SCLK_UART7:
1748 con = readl(&cru->clksel_con[66]);
1749 break;
1750 case SCLK_UART8:
1751 con = readl(&cru->clksel_con[67]);
1752 break;
1753 case SCLK_UART9:
1754 con = readl(&cru->clksel_con[68]);
1755 break;
1756 case SCLK_UART10:
1757 con = readl(&cru->clksel_con[69]);
1758 break;
1759 case SCLK_UART11:
1760 con = readl(&cru->clksel_con[70]);
1761 break;
1762 default:
1763 return -ENOENT;
1764 }
1765 if (clk_id == SCLK_UART1) {
1766 src = (con & CLK_UART1_SRC_SEL_SHIFT) >> CLK_UART1_SRC_SEL_SHIFT;
1767 div = (con & CLK_UART1_SRC_DIV_MASK) >> CLK_UART1_SRC_DIV_SHIFT;
1768 } else {
1769 src = (con & CLK_UART_SEL_MASK) >> CLK_UART_SEL_SHIFT;
1770 div = (con & CLK_UART_DIV_MASK) >> CLK_UART_DIV_SHIFT;
1771 }
1772 if (src == CLK_UART_SEL_GPLL)
1773 p_rate = priv->gpll_hz;
1774 else if (src == CLK_UART_SEL_CPLL)
1775 p_rate = priv->cpll_hz;
1776 else if (src == CLK_UART_SEL_AUPLL)
1777 p_rate = priv->aupll_hz;
1778 else if (src == CLK_UART_SEL_FRAC0)
1779 p_rate = rk3576_uart_frac_get_rate(priv, CLK_UART_FRAC_0);
1780 else if (src == CLK_UART_SEL_FRAC1)
1781 p_rate = rk3576_uart_frac_get_rate(priv, CLK_UART_FRAC_1);
1782 else if (src == CLK_UART_SEL_FRAC2)
1783 p_rate = rk3576_uart_frac_get_rate(priv, CLK_UART_FRAC_2);
1784 else
1785 p_rate = OSC_HZ;
1786
1787 return DIV_TO_RATE(p_rate, div);
1788}
1789
1790static ulong rk3576_uart_set_rate(struct rk3576_clk_priv *priv,
1791 ulong clk_id, ulong rate)
1792{
1793 struct rk3576_cru *cru = priv->cru;
1794 u32 reg, clk_src = 0, div = 0;
1795
1796 if (!(priv->gpll_hz % rate)) {
1797 clk_src = CLK_UART_SEL_GPLL;
1798 div = DIV_ROUND_UP(priv->gpll_hz, rate);
1799 } else if (!(priv->cpll_hz % rate)) {
1800 clk_src = CLK_UART_SEL_CPLL;
1801 div = DIV_ROUND_UP(priv->gpll_hz, rate);
1802 } else if (!(rk3576_uart_frac_get_rate(priv, CLK_UART_FRAC_0) % rate)) {
1803 clk_src = CLK_UART_SEL_FRAC0;
1804 div = DIV_ROUND_UP(rk3576_uart_frac_get_rate(priv, CLK_UART_FRAC_0), rate);
1805 } else if (!(rk3576_uart_frac_get_rate(priv, CLK_UART_FRAC_1) % rate)) {
1806 clk_src = CLK_UART_SEL_FRAC1;
1807 div = DIV_ROUND_UP(rk3576_uart_frac_get_rate(priv, CLK_UART_FRAC_1), rate);
1808 } else if (!(rk3576_uart_frac_get_rate(priv, CLK_UART_FRAC_2) % rate)) {
1809 clk_src = CLK_UART_SEL_FRAC2;
1810 div = DIV_ROUND_UP(rk3576_uart_frac_get_rate(priv, CLK_UART_FRAC_2), rate);
1811 } else if (!(OSC_HZ % rate)) {
1812 clk_src = CLK_UART_SEL_OSC;
1813 div = DIV_ROUND_UP(OSC_HZ, rate);
1814 }
1815
1816 switch (clk_id) {
1817 case SCLK_UART0:
1818 reg = 60;
1819 break;
1820 case SCLK_UART1:
1821 if (rate == OSC_HZ) {
1822 rk_clrsetreg(&cru->pmuclksel_con[8],
1823 CLK_UART1_SEL_MASK,
1824 CLK_UART1_SEL_OSC << CLK_UART1_SEL_SHIFT);
1825 return 0;
1826 }
1827
1828 rk_clrsetreg(&cru->clksel_con[27],
1829 CLK_UART1_SRC_SEL_MASK | CLK_UART1_SRC_DIV_MASK,
1830 (clk_src << CLK_UART1_SRC_SEL_SHIFT) |
1831 ((div - 1) << CLK_UART1_SRC_DIV_SHIFT));
1832 rk_clrsetreg(&cru->pmuclksel_con[8],
1833 CLK_UART1_SEL_MASK,
1834 CLK_UART1_SEL_TOP << CLK_UART1_SEL_SHIFT);
1835 return 0;
1836 case SCLK_UART2:
1837 reg = 61;
1838 break;
1839 case SCLK_UART3:
1840 reg = 62;
1841 break;
1842 case SCLK_UART4:
1843 reg = 63;
1844 break;
1845 case SCLK_UART5:
1846 reg = 64;
1847 break;
1848 case SCLK_UART6:
1849 reg = 65;
1850 break;
1851 case SCLK_UART7:
1852 reg = 66;
1853 break;
1854 case SCLK_UART8:
1855 reg = 67;
1856 break;
1857 case SCLK_UART9:
1858 reg = 68;
1859 break;
1860 case SCLK_UART10:
1861 reg = 69;
1862 break;
1863 case SCLK_UART11:
1864 reg = 70;
1865 break;
1866 default:
1867 return -ENOENT;
1868 }
1869
1870 rk_clrsetreg(&cru->clksel_con[reg],
1871 CLK_UART_SEL_MASK |
1872 CLK_UART_DIV_MASK,
1873 (clk_src << CLK_UART_SEL_SHIFT) |
1874 ((div - 1) << CLK_UART_DIV_SHIFT));
1875
1876 return rk3576_uart_get_rate(priv, clk_id);
1877}
1878#endif
1879
1880static ulong rk3576_ufs_ref_get_rate(struct rk3576_clk_priv *priv, ulong clk_id)
1881{
1882 struct rk3576_cru *cru = priv->cru;
1883 u32 src, div;
1884
1885 src = readl(&cru->pmuclksel_con[3]) & 0x3;
1886 div = readl(&cru->pmuclksel_con[1]) & 0xff;
1887 if (src == 0)
1888 return OSC_HZ;
1889 else if (src == 2)
1890 return priv->ppll_hz / (div + 1);
1891 else
1892 return 26000000;
1893}
1894
1895static ulong rk3576_clk_get_rate(struct clk *clk)
1896{
1897 struct rk3576_clk_priv *priv = dev_get_priv(clk->dev);
1898 ulong rate = 0;
1899
1900 if (!priv->gpll_hz) {
1901 printf("%s gpll=%lu\n", __func__, priv->gpll_hz);
1902 return -ENOENT;
1903 }
1904
1905 if (!priv->ppll_hz) {
1906 priv->ppll_hz = rockchip_pll_get_rate(&rk3576_pll_clks[PPLL],
1907 priv->cru, PPLL);
1908 }
1909
1910 switch (clk->id) {
1911 case PLL_LPLL:
1912 rate = rockchip_pll_get_rate(&rk3576_pll_clks[LPLL], priv->cru,
1913 LPLL);
1914 priv->lpll_hz = rate;
1915 break;
1916 case PLL_BPLL:
1917 rate = rockchip_pll_get_rate(&rk3576_pll_clks[BPLL], priv->cru,
1918 BPLL);
1919 priv->bpll_hz = rate;
1920 break;
1921 case PLL_GPLL:
1922 rate = rockchip_pll_get_rate(&rk3576_pll_clks[GPLL], priv->cru,
1923 GPLL);
1924 break;
1925 case PLL_CPLL:
1926 rate = rockchip_pll_get_rate(&rk3576_pll_clks[CPLL], priv->cru,
1927 CPLL);
1928 break;
1929 case PLL_VPLL:
1930 rate = rockchip_pll_get_rate(&rk3576_pll_clks[VPLL], priv->cru,
1931 VPLL);
1932 break;
1933 case PLL_AUPLL:
1934 rate = rockchip_pll_get_rate(&rk3576_pll_clks[AUPLL], priv->cru,
1935 AUPLL);
1936 break;
1937 case PLL_PPLL:
1938 rate = rockchip_pll_get_rate(&rk3576_pll_clks[PPLL], priv->cru,
1939 PPLL) * 2;
1940 break;
1941 case ACLK_BUS_ROOT:
1942 case HCLK_BUS_ROOT:
1943 case PCLK_BUS_ROOT:
1944 rate = rk3576_bus_get_clk(priv, clk->id);
1945 break;
1946 case ACLK_TOP:
1947 case HCLK_TOP:
1948 case PCLK_TOP_ROOT:
1949 case ACLK_TOP_MID:
1950 rate = rk3576_top_get_clk(priv, clk->id);
1951 break;
1952 case CLK_I2C0:
1953 case CLK_I2C1:
1954 case CLK_I2C2:
1955 case CLK_I2C3:
1956 case CLK_I2C4:
1957 case CLK_I2C5:
1958 case CLK_I2C6:
1959 case CLK_I2C7:
1960 case CLK_I2C8:
1961 case CLK_I2C9:
1962 rate = rk3576_i2c_get_clk(priv, clk->id);
1963 break;
1964 case CLK_SPI0:
1965 case CLK_SPI1:
1966 case CLK_SPI2:
1967 case CLK_SPI3:
1968 case CLK_SPI4:
1969 rate = rk3576_spi_get_clk(priv, clk->id);
1970 break;
1971 case CLK_PWM1:
1972 case CLK_PWM2:
1973 case CLK_PMU1PWM:
1974 rate = rk3576_pwm_get_clk(priv, clk->id);
1975 break;
1976 case CLK_SARADC:
1977 case CLK_TSADC:
1978 rate = rk3576_adc_get_clk(priv, clk->id);
1979 break;
1980 case CCLK_SRC_SDIO:
1981 case CCLK_SRC_SDMMC0:
1982 case CCLK_SRC_EMMC:
1983 case BCLK_EMMC:
1984 case SCLK_FSPI_X2:
1985 case SCLK_FSPI1_X2:
1986 case DCLK_DECOM:
1987 case HCLK_SDMMC0:
1988 case HCLK_EMMC:
1989 case HCLK_SDIO:
1990 rate = rk3576_mmc_get_clk(priv, clk->id);
1991 break;
1992 case TCLK_EMMC:
1993 case TCLK_WDT0:
1994 rate = OSC_HZ;
1995 break;
1996#ifndef CONFIG_SPL_BUILD
1997 case ACLK_VOP_ROOT:
1998 case ACLK_VOP:
1999 case ACLK_VO0_ROOT:
2000 case ACLK_VO1_ROOT:
2001 case HCLK_VOP_ROOT:
2002 case PCLK_VOP_ROOT:
2003 rate = rk3576_aclk_vop_get_clk(priv, clk->id);
2004 break;
2005 case DCLK_VP0:
2006 case DCLK_VP0_SRC:
2007 case DCLK_VP1:
2008 case DCLK_VP1_SRC:
2009 case DCLK_VP2:
2010 case DCLK_VP2_SRC:
2011 rate = rk3576_dclk_vop_get_clk(priv, clk->id);
2012 break;
2013 case CLK_GMAC0_PTP_REF_SRC:
2014 case CLK_GMAC1_PTP_REF_SRC:
2015 case CLK_GMAC0_PTP_REF:
2016 case CLK_GMAC1_PTP_REF:
2017 case CLK_GMAC0_125M_SRC:
2018 case CLK_GMAC1_125M_SRC:
2019 rate = rk3576_gmac_get_clk(priv, clk->id);
2020 break;
2021 case CLK_UART_FRAC_0:
2022 case CLK_UART_FRAC_1:
2023 case CLK_UART_FRAC_2:
2024 rate = rk3576_uart_frac_get_rate(priv, clk->id);
2025 break;
2026 case SCLK_UART0:
2027 case SCLK_UART1:
2028 case SCLK_UART2:
2029 case SCLK_UART3:
2030 case SCLK_UART4:
2031 case SCLK_UART5:
2032 case SCLK_UART6:
2033 case SCLK_UART7:
2034 case SCLK_UART8:
2035 case SCLK_UART9:
2036 case SCLK_UART10:
2037 case SCLK_UART11:
2038 rate = rk3576_uart_get_rate(priv, clk->id);
2039 break;
2040 case CLK_DSIHOST0:
2041 rate = rk3576_clk_csihost_get_clk(priv, clk->id);
2042 break;
2043 case DCLK_EBC:
2044 case DCLK_EBC_FRAC_SRC:
2045 rate = rk3576_dclk_ebc_get_clk(priv, clk->id);
2046 break;
2047#endif
2048 case CLK_REF_UFS_CLKOUT:
2049 case CLK_REF_OSC_MPHY:
2050 rate = rk3576_ufs_ref_get_rate(priv, clk->id);
2051 break;
2052
2053 default:
2054 return -ENOENT;
2055 }
2056
2057 return rate;
2058};
2059
2060static ulong rk3576_clk_set_rate(struct clk *clk, ulong rate)
2061{
2062 struct rk3576_clk_priv *priv = dev_get_priv(clk->dev);
2063 ulong ret = 0;
2064
2065 if (!priv->ppll_hz) {
2066 priv->ppll_hz = rockchip_pll_get_rate(&rk3576_pll_clks[PPLL],
2067 priv->cru, PPLL);
2068 }
2069 if (!priv->aupll_hz) {
2070 priv->aupll_hz = rockchip_pll_get_rate(&rk3576_pll_clks[AUPLL],
2071 priv->cru, AUPLL);
2072 }
2073
2074 switch (clk->id) {
2075 case PLL_CPLL:
2076 ret = rockchip_pll_set_rate(&rk3576_pll_clks[CPLL], priv->cru,
2077 CPLL, rate);
2078 priv->cpll_hz = rockchip_pll_get_rate(&rk3576_pll_clks[CPLL],
2079 priv->cru, CPLL);
2080 break;
2081 case PLL_GPLL:
2082 ret = rockchip_pll_set_rate(&rk3576_pll_clks[GPLL], priv->cru,
2083 GPLL, rate);
2084 priv->gpll_hz = rockchip_pll_get_rate(&rk3576_pll_clks[GPLL],
2085 priv->cru, GPLL);
2086 break;
2087 case PLL_VPLL:
2088 ret = rockchip_pll_set_rate(&rk3576_pll_clks[VPLL], priv->cru,
2089 VPLL, rate);
2090 priv->vpll_hz = rockchip_pll_get_rate(&rk3576_pll_clks[VPLL],
2091 priv->cru, VPLL);
2092 break;
2093 case PLL_AUPLL:
2094 ret = rockchip_pll_set_rate(&rk3576_pll_clks[AUPLL], priv->cru,
2095 AUPLL, rate);
2096 priv->aupll_hz = rockchip_pll_get_rate(&rk3576_pll_clks[AUPLL],
2097 priv->cru, AUPLL);
2098 break;
2099 case PLL_PPLL:
2100 ret = rockchip_pll_set_rate(&rk3576_pll_clks[PPLL], priv->cru,
2101 PPLL, rate);
2102 priv->ppll_hz = rockchip_pll_get_rate(&rk3576_pll_clks[PPLL],
2103 priv->cru, PPLL) * 2;
2104 break;
2105 case ACLK_BUS_ROOT:
2106 case HCLK_BUS_ROOT:
2107 case PCLK_BUS_ROOT:
2108 ret = rk3576_bus_set_clk(priv, clk->id, rate);
2109 break;
2110 case ACLK_TOP:
2111 case HCLK_TOP:
2112 case PCLK_TOP_ROOT:
2113 case ACLK_TOP_MID:
2114 ret = rk3576_top_set_clk(priv, clk->id, rate);
2115 break;
2116 case CLK_I2C0:
2117 case CLK_I2C1:
2118 case CLK_I2C2:
2119 case CLK_I2C3:
2120 case CLK_I2C4:
2121 case CLK_I2C5:
2122 case CLK_I2C6:
2123 case CLK_I2C7:
2124 case CLK_I2C8:
2125 case CLK_I2C9:
2126 ret = rk3576_i2c_set_clk(priv, clk->id, rate);
2127 break;
2128 case CLK_SPI0:
2129 case CLK_SPI1:
2130 case CLK_SPI2:
2131 case CLK_SPI3:
2132 case CLK_SPI4:
2133 ret = rk3576_spi_set_clk(priv, clk->id, rate);
2134 break;
2135 case CLK_PWM1:
2136 case CLK_PWM2:
2137 case CLK_PMU1PWM:
2138 ret = rk3576_pwm_set_clk(priv, clk->id, rate);
2139 break;
2140 case CLK_SARADC:
2141 case CLK_TSADC:
2142 ret = rk3576_adc_set_clk(priv, clk->id, rate);
2143 break;
2144 case CCLK_SRC_SDIO:
2145 case CCLK_SRC_SDMMC0:
2146 case CCLK_SRC_EMMC:
2147 case BCLK_EMMC:
2148 case SCLK_FSPI_X2:
2149 case SCLK_FSPI1_X2:
2150 case DCLK_DECOM:
2151 case HCLK_SDMMC0:
2152 case HCLK_EMMC:
2153 case HCLK_SDIO:
2154 ret = rk3576_mmc_set_clk(priv, clk->id, rate);
2155 break;
2156 case TCLK_EMMC:
2157 case TCLK_WDT0:
2158 ret = OSC_HZ;
2159 break;
2160
2161 /* Might occur in cru assigned-clocks, can be ignored here */
2162 case CLK_AUDIO_FRAC_0:
2163 case CLK_AUDIO_FRAC_1:
2164 case CLK_AUDIO_FRAC_0_SRC:
2165 case CLK_AUDIO_FRAC_1_SRC:
2166 case CLK_CPLL_DIV2:
2167 case CLK_CPLL_DIV4:
2168 case CLK_CPLL_DIV10:
2169 case FCLK_DDR_CM0_CORE:
2170 case ACLK_PHP_ROOT:
2171 ret = 0;
2172 break;
2173#ifndef CONFIG_SPL_BUILD
2174 case ACLK_VOP_ROOT:
2175 case ACLK_VOP:
2176 case ACLK_VO0_ROOT:
2177 case ACLK_VO1_ROOT:
2178 case HCLK_VOP_ROOT:
2179 case PCLK_VOP_ROOT:
2180 ret = rk3576_aclk_vop_set_clk(priv, clk->id, rate);
2181 break;
2182 case DCLK_VP0:
2183 case DCLK_VP0_SRC:
2184 case DCLK_VP1:
2185 case DCLK_VP1_SRC:
2186 case DCLK_VP2:
2187 case DCLK_VP2_SRC:
2188 ret = rk3576_dclk_vop_set_clk(priv, clk->id, rate);
2189 break;
2190 case CLK_GMAC0_PTP_REF_SRC:
2191 case CLK_GMAC1_PTP_REF_SRC:
2192 case CLK_GMAC0_PTP_REF:
2193 case CLK_GMAC1_PTP_REF:
2194 case CLK_GMAC0_125M_SRC:
2195 case CLK_GMAC1_125M_SRC:
2196 ret = rk3576_gmac_set_clk(priv, clk->id, rate);
2197 break;
2198 case CLK_UART_FRAC_0:
2199 case CLK_UART_FRAC_1:
2200 case CLK_UART_FRAC_2:
2201 ret = rk3576_uart_frac_set_rate(priv, clk->id, rate);
2202 break;
2203 case SCLK_UART0:
2204 case SCLK_UART1:
2205 case SCLK_UART2:
2206 case SCLK_UART3:
2207 case SCLK_UART4:
2208 case SCLK_UART5:
2209 case SCLK_UART6:
2210 case SCLK_UART7:
2211 case SCLK_UART8:
2212 case SCLK_UART9:
2213 case SCLK_UART10:
2214 case SCLK_UART11:
2215 ret = rk3576_uart_set_rate(priv, clk->id, rate);
2216 break;
2217 case CLK_DSIHOST0:
2218 ret = rk3576_clk_csihost_set_clk(priv, clk->id, rate);
2219 break;
2220 case DCLK_EBC:
2221 case DCLK_EBC_FRAC_SRC:
2222 ret = rk3576_dclk_ebc_set_clk(priv, clk->id, rate);
2223 break;
2224#endif
2225 default:
2226 return -ENOENT;
2227 }
2228
2229 return ret;
2230};
2231
2232#if (IS_ENABLED(OF_CONTROL)) || (!IS_ENABLED(OF_PLATDATA))
2233static int __maybe_unused rk3576_dclk_vop_set_parent(struct clk *clk,
2234 struct clk *parent)
2235{
2236 struct rk3576_clk_priv *priv = dev_get_priv(clk->dev);
2237 struct rk3576_cru *cru = priv->cru;
2238 u32 sel;
2239 const char *clock_dev_name = parent->dev->name;
2240
2241 if (parent->id == PLL_VPLL)
2242 sel = 2;
2243 else if (parent->id == PLL_GPLL)
2244 sel = 0;
2245 else if (parent->id == PLL_CPLL)
2246 sel = 1;
2247 else if (parent->id == PLL_BPLL)
2248 sel = 3;
2249 else
2250 sel = 4;
2251
2252 switch (clk->id) {
2253 case DCLK_VP0_SRC:
2254 rk_clrsetreg(&cru->clksel_con[145], DCLK0_VOP_SRC_SEL_MASK,
2255 sel << DCLK0_VOP_SRC_SEL_SHIFT);
2256 break;
2257 case DCLK_VP1_SRC:
2258 rk_clrsetreg(&cru->clksel_con[146], DCLK0_VOP_SRC_SEL_MASK,
2259 sel << DCLK0_VOP_SRC_SEL_SHIFT);
2260 break;
2261 case DCLK_VP2_SRC:
2262 rk_clrsetreg(&cru->clksel_con[147], DCLK0_VOP_SRC_SEL_MASK,
2263 sel << DCLK0_VOP_SRC_SEL_SHIFT);
2264 break;
2265 case DCLK_VP0:
2266 if (!strcmp(clock_dev_name, "hdmiphypll_clk0"))
2267 sel = 1;
2268 else
2269 sel = 0;
2270 rk_clrsetreg(&cru->clksel_con[147], DCLK0_VOP_SEL_MASK,
2271 sel << DCLK0_VOP_SEL_SHIFT);
2272 break;
2273 case DCLK_VP1:
2274 if (!strcmp(clock_dev_name, "hdmiphypll_clk0"))
2275 sel = 1;
2276 else
2277 sel = 0;
2278 rk_clrsetreg(&cru->clksel_con[147], DCLK1_VOP_SEL_MASK,
2279 sel << DCLK1_VOP_SEL_SHIFT);
2280 break;
2281 case DCLK_VP2:
2282 if (!strcmp(clock_dev_name, "hdmiphypll_clk0"))
2283 sel = 1;
2284 else
2285 sel = 0;
2286 rk_clrsetreg(&cru->clksel_con[147], DCLK2_VOP_SEL_MASK,
2287 sel << DCLK2_VOP_SEL_SHIFT);
2288 break;
2289 case DCLK_EBC:
2290 if (parent->id == PLL_GPLL)
2291 sel = 0;
2292 else if (parent->id == PLL_CPLL)
2293 sel = 1;
2294 else if (parent->id == PLL_VPLL)
2295 sel = 2;
2296 else if (parent->id == PLL_AUPLL)
2297 sel = 3;
2298 else if (parent->id == PLL_LPLL)
2299 sel = 4;
2300 else if (parent->id == DCLK_EBC_FRAC_SRC)
2301 sel = 5;
2302 else
2303 sel = 6;
2304 rk_clrsetreg(&cru->clksel_con[123], DCLK_EBC_SEL_MASK,
2305 sel << DCLK_EBC_SEL_SHIFT);
2306 break;
2307 default:
2308 return -EINVAL;
2309 }
2310 return 0;
2311}
2312
2313static int __maybe_unused rk3576_ufs_ref_set_parent(struct clk *clk,
2314 struct clk *parent)
2315{
2316 struct rk3576_clk_priv *priv = dev_get_priv(clk->dev);
2317 struct rk3576_cru *cru = priv->cru;
2318 u32 sel;
2319 const char *clock_dev_name = parent->dev->name;
2320
2321 if (parent->id == CLK_REF_MPHY_26M)
2322 sel = 2;
2323 else if (!strcmp(clock_dev_name, "xin24m"))
2324 sel = 0;
2325 else
2326 sel = 1;
2327
2328 rk_clrsetreg(&cru->pmuclksel_con[3], 0x3, sel << 0);
2329 return 0;
2330}
2331
2332static int rk3576_clk_set_parent(struct clk *clk, struct clk *parent)
2333{
2334 switch (clk->id) {
2335 case DCLK_VP0_SRC:
2336 case DCLK_VP1_SRC:
2337 case DCLK_VP2_SRC:
2338 case DCLK_VP0:
2339 case DCLK_VP1:
2340 case DCLK_VP2:
2341 case DCLK_EBC:
2342 return rk3576_dclk_vop_set_parent(clk, parent);
2343 case CLK_REF_OSC_MPHY:
2344 return rk3576_ufs_ref_set_parent(clk, parent);
2345 case CLK_AUDIO_FRAC_0_SRC:
2346 case CLK_AUDIO_FRAC_1_SRC:
2347 /* Might occur in cru assigned-clocks, can be ignored here */
2348 return 0;
2349 default:
2350 return -ENOENT;
2351 }
2352
2353 return 0;
2354}
2355#endif
2356
2357static struct clk_ops rk3576_clk_ops = {
2358 .get_rate = rk3576_clk_get_rate,
2359 .set_rate = rk3576_clk_set_rate,
2360#if (IS_ENABLED(OF_CONTROL)) || (!IS_ENABLED(OF_PLATDATA))
2361 .set_parent = rk3576_clk_set_parent,
2362#endif
2363};
2364
2365static void rk3576_clk_init(struct rk3576_clk_priv *priv)
2366{
2367 int ret;
2368
2369 priv->spll_hz = 702000000;
2370
2371 if (priv->cpll_hz != CPLL_HZ) {
2372 ret = rockchip_pll_set_rate(&rk3576_pll_clks[CPLL], priv->cru,
2373 CPLL, CPLL_HZ);
2374 if (!ret)
2375 priv->cpll_hz = CPLL_HZ;
2376 }
2377 if (priv->gpll_hz != GPLL_HZ) {
2378 ret = rockchip_pll_set_rate(&rk3576_pll_clks[GPLL], priv->cru,
2379 GPLL, GPLL_HZ);
2380 if (!ret)
2381 priv->gpll_hz = GPLL_HZ;
2382 }
2383 rk_clrsetreg(&priv->cru->clksel_con[123],
2384 DCLK_EBC_FRAC_SRC_SEL_MASK,
2385 (DCLK_EBC_FRAC_SRC_SEL_GPLL <<
2386 DCLK_EBC_FRAC_SRC_SEL_SHIFT));
2387}
2388
2389static int rk3576_clk_probe(struct udevice *dev)
2390{
2391 struct rk3576_clk_priv *priv = dev_get_priv(dev);
2392 int ret;
2393
2394 priv->sync_kernel = false;
2395
2396#ifdef CONFIG_SPL_BUILD
2397 /* relase presetn_bigcore_biu/cru/grf */
2398 writel(0x1c001c00, 0x26010010);
2399 /* set spll to normal mode */
2400 writel(BITS_WITH_WMASK(2, 0x7U, 6),
2401 RK3576_SCRU_BASE + RK3576_PLL_CON(137));
2402 writel(BITS_WITH_WMASK(1, 0x3U, 0),
2403 RK3576_SCRU_BASE + RK3576_MODE_CON0);
2404 /* fix ppll\aupll\cpll */
2405 writel(BITS_WITH_WMASK(2, 0x7U, 6),
2406 RK3576_CRU_BASE + RK3576_PMU_PLL_CON(129));
2407 writel(BITS_WITH_WMASK(2, 0x7U, 6),
2408 RK3576_CRU_BASE + RK3576_PLL_CON(97));
2409 writel(BITS_WITH_WMASK(2, 0x7U, 6),
2410 RK3576_CRU_BASE + RK3576_PLL_CON(105));
2411 writel(BITS_WITH_WMASK(1, 0x3U, 6),
2412 RK3576_CRU_BASE + RK3576_MODE_CON0);
2413 writel(BITS_WITH_WMASK(1, 0x3U, 8),
2414 RK3576_CRU_BASE + RK3576_MODE_CON0);
2415 /* init cci */
2416 writel(0xffff0000, RK3576_CRU_BASE + RK3576_CCI_CLKSEL_CON(4));
2417 rockchip_pll_set_rate(&rk3576_pll_clks[BPLL], priv->cru,
2418 BPLL, LPLL_HZ);
2419 if (!priv->armclk_enter_hz) {
2420 ret = rockchip_pll_set_rate(&rk3576_pll_clks[LPLL], priv->cru,
2421 LPLL, LPLL_HZ);
2422 priv->armclk_enter_hz =
2423 rockchip_pll_get_rate(&rk3576_pll_clks[LPLL],
2424 priv->cru, LPLL);
2425 priv->armclk_init_hz = priv->armclk_enter_hz;
2426 rk_clrsetreg(&priv->cru->litclksel_con[0], CLK_LITCORE_DIV_MASK,
2427 0 << CLK_LITCORE_DIV_SHIFT);
2428 }
2429 /* init cci */
2430 writel(0xffff20cb, RK3576_CRU_BASE + RK3576_CCI_CLKSEL_CON(4));
2431
2432 /* Change bigcore rm from 4 to 3 */
2433 writel(0x001c000c, RK3576_BIGCORE_GRF_BASE + 0x3c);
2434 writel(0x001c000c, RK3576_BIGCORE_GRF_BASE + 0x44);
2435 writel(0x00020002, RK3576_BIGCORE_GRF_BASE + 0x38);
2436 udelay(1);
2437 writel(0x00020000, RK3576_BIGCORE_GRF_BASE + 0x38);
2438 /* Change litcore rm from 4 to 3 */
2439 writel(0x001c000c, RK3576_LITCORE_GRF_BASE + 0x3c);
2440 writel(0x001c000c, RK3576_LITCORE_GRF_BASE + 0x44);
2441 writel(0x00020002, RK3576_LITCORE_GRF_BASE + 0x38);
2442 udelay(1);
2443 writel(0x00020000, RK3576_LITCORE_GRF_BASE + 0x38);
2444 /* Change cci rm form 4 to 3 */
2445 writel(0x001c000c, RK3576_CCI_GRF_BASE + 0x54);
2446#endif
2447
2448 rk3576_clk_init(priv);
2449
2450 /* Process 'assigned-{clocks/clock-parents/clock-rates}' properties */
2451 ret = clk_set_defaults(dev, 1);
2452 if (ret)
2453 debug("%s clk_set_defaults failed %d\n", __func__, ret);
2454 else
2455 priv->sync_kernel = true;
2456
2457 return 0;
2458}
2459
2460static int rk3576_clk_ofdata_to_platdata(struct udevice *dev)
2461{
2462 struct rk3576_clk_priv *priv = dev_get_priv(dev);
2463
2464 priv->cru = dev_read_addr_ptr(dev);
2465
2466 return 0;
2467}
2468
2469static int rk3576_clk_bind(struct udevice *dev)
2470{
2471 int ret;
2472 struct udevice *sys_child;
2473 struct sysreset_reg *priv;
2474
2475 /* The reset driver does not have a device node, so bind it here */
2476 ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset",
2477 &sys_child);
2478 if (ret) {
2479 debug("Warning: No sysreset driver: ret=%d\n", ret);
2480 } else {
2481 priv = malloc(sizeof(struct sysreset_reg));
2482 priv->glb_srst_fst_value = offsetof(struct rk3576_cru,
2483 glb_srst_fst);
2484 priv->glb_srst_snd_value = offsetof(struct rk3576_cru,
2485 glb_srsr_snd);
2486 dev_set_priv(sys_child, priv);
2487 }
2488
2489#if CONFIG_IS_ENABLED(RESET_ROCKCHIP)
2490 ret = offsetof(struct rk3576_cru, softrst_con[0]);
2491 ret = rk3576_reset_bind_lut(dev, ret, 32776);
2492 if (ret)
2493 debug("Warning: software reset driver bind failed\n");
2494#endif
2495
2496 return 0;
2497}
2498
2499static const struct udevice_id rk3576_clk_ids[] = {
2500 { .compatible = "rockchip,rk3576-cru" },
2501 { }
2502};
2503
2504U_BOOT_DRIVER(rockchip_rk3576_cru) = {
2505 .name = "rockchip_rk3576_cru",
2506 .id = UCLASS_CLK,
2507 .of_match = rk3576_clk_ids,
2508 .priv_auto = sizeof(struct rk3576_clk_priv),
2509 .of_to_plat = rk3576_clk_ofdata_to_platdata,
2510 .ops = &rk3576_clk_ops,
2511 .bind = rk3576_clk_bind,
2512 .probe = rk3576_clk_probe,
2513};