blob: db1384dacd20be5058d6c6749e890888a1df7458 [file] [log] [blame]
Jagan Teki7d031ee2023-01-30 20:27:36 +05301// 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
Jagan Teki7d031ee2023-01-30 20:27:36 +05307#include <bitfield.h>
8#include <clk-uclass.h>
9#include <dm.h>
10#include <errno.h>
Jonas Karlmanb4505902023-04-17 19:07:20 +000011#include <scmi_protocols.h>
Jagan Teki7d031ee2023-01-30 20:27:36 +053012#include <syscon.h>
13#include <asm/arch-rockchip/cru_rk3588.h>
14#include <asm/arch-rockchip/clock.h>
15#include <asm/arch-rockchip/hardware.h>
Jagan Teki7d031ee2023-01-30 20:27:36 +053016#include <dm/device-internal.h>
17#include <dm/lists.h>
18#include <dt-bindings/clock/rockchip,rk3588-cru.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 rk3588_pll_rates[] = {
25 /* _mhz, _p, _m, _s, _k */
26 RK3588_PLL_RATE(1500000000, 2, 250, 1, 0),
27 RK3588_PLL_RATE(1200000000, 2, 200, 1, 0),
28 RK3588_PLL_RATE(1188000000, 2, 198, 1, 0),
29 RK3588_PLL_RATE(1100000000, 3, 550, 2, 0),
30 RK3588_PLL_RATE(1008000000, 2, 336, 2, 0),
31 RK3588_PLL_RATE(1000000000, 3, 500, 2, 0),
32 RK3588_PLL_RATE(900000000, 2, 300, 2, 0),
33 RK3588_PLL_RATE(850000000, 3, 425, 2, 0),
34 RK3588_PLL_RATE(816000000, 2, 272, 2, 0),
35 RK3588_PLL_RATE(786432000, 2, 262, 2, 9437),
36 RK3588_PLL_RATE(786000000, 1, 131, 2, 0),
Guochun Huang63f88d12023-10-11 18:29:44 +080037 RK3588_PLL_RATE(742500000, 4, 495, 2, 0),
Jagan Teki7d031ee2023-01-30 20:27:36 +053038 RK3588_PLL_RATE(722534400, 8, 963, 2, 24850),
Heiko Stuebner166a0472024-05-22 19:31:29 +020039 RK3588_PLL_RATE(702000000, 3, 351, 2, 0),
Jagan Teki7d031ee2023-01-30 20:27:36 +053040 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 rk3588_pll_clks[] = {
48 [B0PLL] = PLL(pll_rk3588, PLL_B0PLL, RK3588_B0_PLL_CON(0),
49 RK3588_B0_PLL_MODE_CON, 0, 15, 0,
50 rk3588_pll_rates),
51 [B1PLL] = PLL(pll_rk3588, PLL_B1PLL, RK3588_B1_PLL_CON(8),
52 RK3588_B1_PLL_MODE_CON, 0, 15, 0,
53 rk3588_pll_rates),
54 [LPLL] = PLL(pll_rk3588, PLL_LPLL, RK3588_LPLL_CON(16),
55 RK3588_LPLL_MODE_CON, 0, 15, 0, rk3588_pll_rates),
56 [V0PLL] = PLL(pll_rk3588, PLL_V0PLL, RK3588_PLL_CON(88),
57 RK3588_MODE_CON0, 4, 15, 0, rk3588_pll_rates),
58 [AUPLL] = PLL(pll_rk3588, PLL_AUPLL, RK3588_PLL_CON(96),
59 RK3588_MODE_CON0, 6, 15, 0, rk3588_pll_rates),
60 [CPLL] = PLL(pll_rk3588, PLL_CPLL, RK3588_PLL_CON(104),
61 RK3588_MODE_CON0, 8, 15, 0, rk3588_pll_rates),
62 [GPLL] = PLL(pll_rk3588, PLL_GPLL, RK3588_PLL_CON(112),
63 RK3588_MODE_CON0, 2, 15, 0, rk3588_pll_rates),
64 [NPLL] = PLL(pll_rk3588, PLL_NPLL, RK3588_PLL_CON(120),
65 RK3588_MODE_CON0, 0, 15, 0, rk3588_pll_rates),
66 [PPLL] = PLL(pll_rk3588, PLL_PPLL, RK3588_PMU_PLL_CON(128),
67 RK3588_MODE_CON0, 10, 15, 0, rk3588_pll_rates),
Heiko Stuebner166a0472024-05-22 19:31:29 +020068#ifdef CONFIG_SPL_BUILD
69 /*
70 * The SPLL is part of the SBUSCRU, not the main CRU and as
71 * such only directly accessible during the SPL stage.
72 */
73 [SPLL] = PLL(pll_rk3588, 0, RK3588_SBUSCRU_SPLL_CON(0),
74 RK3588_SBUSCRU_MODE_CON0, 0, 15, 0, rk3588_pll_rates),
75#endif
76
Jagan Teki7d031ee2023-01-30 20:27:36 +053077};
78
79#ifndef CONFIG_SPL_BUILD
80/*
81 *
82 * rational_best_approximation(31415, 10000,
83 * (1 << 8) - 1, (1 << 5) - 1, &n, &d);
84 *
85 * you may look at given_numerator as a fixed point number,
86 * with the fractional part size described in given_denominator.
87 *
88 * for theoretical background, see:
89 * http://en.wikipedia.org/wiki/Continued_fraction
90 */
91static void rational_best_approximation(unsigned long given_numerator,
92 unsigned long given_denominator,
93 unsigned long max_numerator,
94 unsigned long max_denominator,
95 unsigned long *best_numerator,
96 unsigned long *best_denominator)
97{
98 unsigned long n, d, n0, d0, n1, d1;
99
100 n = given_numerator;
101 d = given_denominator;
102 n0 = 0;
103 d1 = 0;
104 n1 = 1;
105 d0 = 1;
106 for (;;) {
107 unsigned long t, a;
108
109 if (n1 > max_numerator || d1 > max_denominator) {
110 n1 = n0;
111 d1 = d0;
112 break;
113 }
114 if (d == 0)
115 break;
116 t = d;
117 a = n / d;
118 d = n % d;
119 n = t;
120 t = n0 + a * n1;
121 n0 = n1;
122 n1 = t;
123 t = d0 + a * d1;
124 d0 = d1;
125 d1 = t;
126 }
127 *best_numerator = n1;
128 *best_denominator = d1;
129}
130#endif
131
132static ulong rk3588_center_get_clk(struct rk3588_clk_priv *priv, ulong clk_id)
133{
134 struct rk3588_cru *cru = priv->cru;
135 u32 con, sel, rate;
136
137 switch (clk_id) {
138 case ACLK_CENTER_ROOT:
139 con = readl(&cru->clksel_con[165]);
140 sel = (con & ACLK_CENTER_ROOT_SEL_MASK) >>
141 ACLK_CENTER_ROOT_SEL_SHIFT;
142 if (sel == ACLK_CENTER_ROOT_SEL_700M)
143 rate = 702 * MHz;
144 else if (sel == ACLK_CENTER_ROOT_SEL_400M)
145 rate = 396 * MHz;
146 else if (sel == ACLK_CENTER_ROOT_SEL_200M)
147 rate = 200 * MHz;
148 else
149 rate = OSC_HZ;
150 break;
151 case ACLK_CENTER_LOW_ROOT:
152 con = readl(&cru->clksel_con[165]);
153 sel = (con & ACLK_CENTER_LOW_ROOT_SEL_MASK) >>
154 ACLK_CENTER_LOW_ROOT_SEL_SHIFT;
155 if (sel == ACLK_CENTER_LOW_ROOT_SEL_500M)
156 rate = 500 * MHz;
157 else if (sel == ACLK_CENTER_LOW_ROOT_SEL_250M)
158 rate = 250 * MHz;
159 else if (sel == ACLK_CENTER_LOW_ROOT_SEL_100M)
160 rate = 100 * MHz;
161 else
162 rate = OSC_HZ;
163 break;
164 case HCLK_CENTER_ROOT:
165 con = readl(&cru->clksel_con[165]);
166 sel = (con & HCLK_CENTER_ROOT_SEL_MASK) >>
167 HCLK_CENTER_ROOT_SEL_SHIFT;
168 if (sel == HCLK_CENTER_ROOT_SEL_400M)
169 rate = 396 * MHz;
170 else if (sel == HCLK_CENTER_ROOT_SEL_200M)
171 rate = 200 * MHz;
172 else if (sel == HCLK_CENTER_ROOT_SEL_100M)
173 rate = 100 * MHz;
174 else
175 rate = OSC_HZ;
176 break;
177 case PCLK_CENTER_ROOT:
178 con = readl(&cru->clksel_con[165]);
179 sel = (con & PCLK_CENTER_ROOT_SEL_MASK) >>
180 PCLK_CENTER_ROOT_SEL_SHIFT;
181 if (sel == PCLK_CENTER_ROOT_SEL_200M)
182 rate = 200 * MHz;
183 else if (sel == PCLK_CENTER_ROOT_SEL_100M)
184 rate = 100 * MHz;
185 else if (sel == PCLK_CENTER_ROOT_SEL_50M)
186 rate = 50 * MHz;
187 else
188 rate = OSC_HZ;
189 break;
190 default:
191 return -ENOENT;
192 }
193
194 return rate;
195}
196
197static ulong rk3588_center_set_clk(struct rk3588_clk_priv *priv,
198 ulong clk_id, ulong rate)
199{
200 struct rk3588_cru *cru = priv->cru;
201 int src_clk;
202
203 switch (clk_id) {
204 case ACLK_CENTER_ROOT:
205 if (rate >= 700 * MHz)
206 src_clk = ACLK_CENTER_ROOT_SEL_700M;
207 else if (rate >= 396 * MHz)
208 src_clk = ACLK_CENTER_ROOT_SEL_400M;
209 else if (rate >= 200 * MHz)
210 src_clk = ACLK_CENTER_ROOT_SEL_200M;
211 else
212 src_clk = ACLK_CENTER_ROOT_SEL_24M;
213 rk_clrsetreg(&cru->clksel_con[165],
214 ACLK_CENTER_ROOT_SEL_MASK,
215 src_clk << ACLK_CENTER_ROOT_SEL_SHIFT);
216 break;
217 case ACLK_CENTER_LOW_ROOT:
218 if (rate >= 500 * MHz)
219 src_clk = ACLK_CENTER_LOW_ROOT_SEL_500M;
220 else if (rate >= 250 * MHz)
221 src_clk = ACLK_CENTER_LOW_ROOT_SEL_250M;
222 else if (rate >= 99 * MHz)
223 src_clk = ACLK_CENTER_LOW_ROOT_SEL_100M;
224 else
225 src_clk = ACLK_CENTER_LOW_ROOT_SEL_24M;
226 rk_clrsetreg(&cru->clksel_con[165],
227 ACLK_CENTER_LOW_ROOT_SEL_MASK,
228 src_clk << ACLK_CENTER_LOW_ROOT_SEL_SHIFT);
229 break;
230 case HCLK_CENTER_ROOT:
231 if (rate >= 396 * MHz)
232 src_clk = HCLK_CENTER_ROOT_SEL_400M;
233 else if (rate >= 198 * MHz)
234 src_clk = HCLK_CENTER_ROOT_SEL_200M;
235 else if (rate >= 99 * MHz)
236 src_clk = HCLK_CENTER_ROOT_SEL_100M;
237 else
238 src_clk = HCLK_CENTER_ROOT_SEL_24M;
239 rk_clrsetreg(&cru->clksel_con[165],
240 HCLK_CENTER_ROOT_SEL_MASK,
241 src_clk << HCLK_CENTER_ROOT_SEL_SHIFT);
242 break;
243 case PCLK_CENTER_ROOT:
244 if (rate >= 198 * MHz)
245 src_clk = PCLK_CENTER_ROOT_SEL_200M;
246 else if (rate >= 99 * MHz)
247 src_clk = PCLK_CENTER_ROOT_SEL_100M;
248 else if (rate >= 50 * MHz)
249 src_clk = PCLK_CENTER_ROOT_SEL_50M;
250 else
251 src_clk = PCLK_CENTER_ROOT_SEL_24M;
252 rk_clrsetreg(&cru->clksel_con[165],
253 PCLK_CENTER_ROOT_SEL_MASK,
254 src_clk << PCLK_CENTER_ROOT_SEL_SHIFT);
255 break;
256 default:
257 printf("do not support this center freq\n");
258 return -EINVAL;
259 }
260
261 return rk3588_center_get_clk(priv, clk_id);
262}
263
264static ulong rk3588_top_get_clk(struct rk3588_clk_priv *priv, ulong clk_id)
265{
266 struct rk3588_cru *cru = priv->cru;
267 u32 con, sel, div, rate, prate;
268
269 switch (clk_id) {
270 case ACLK_TOP_ROOT:
271 con = readl(&cru->clksel_con[8]);
272 div = (con & ACLK_TOP_ROOT_DIV_MASK) >>
273 ACLK_TOP_ROOT_DIV_SHIFT;
274 sel = (con & ACLK_TOP_ROOT_SRC_SEL_MASK) >>
275 ACLK_TOP_ROOT_SRC_SEL_SHIFT;
276 if (sel == ACLK_TOP_ROOT_SRC_SEL_CPLL)
277 prate = priv->cpll_hz;
278 else
279 prate = priv->gpll_hz;
280 return DIV_TO_RATE(prate, div);
281 case ACLK_LOW_TOP_ROOT:
282 con = readl(&cru->clksel_con[8]);
283 div = (con & ACLK_LOW_TOP_ROOT_DIV_MASK) >>
284 ACLK_LOW_TOP_ROOT_DIV_SHIFT;
285 sel = (con & ACLK_LOW_TOP_ROOT_SRC_SEL_MASK) >>
286 ACLK_LOW_TOP_ROOT_SRC_SEL_SHIFT;
287 if (sel == ACLK_LOW_TOP_ROOT_SRC_SEL_CPLL)
288 prate = priv->cpll_hz;
289 else
290 prate = priv->gpll_hz;
291 return DIV_TO_RATE(prate, div);
292 case PCLK_TOP_ROOT:
293 con = readl(&cru->clksel_con[8]);
294 sel = (con & PCLK_TOP_ROOT_SEL_MASK) >> PCLK_TOP_ROOT_SEL_SHIFT;
295 if (sel == PCLK_TOP_ROOT_SEL_100M)
296 rate = 100 * MHz;
297 else if (sel == PCLK_TOP_ROOT_SEL_50M)
298 rate = 50 * MHz;
299 else
300 rate = OSC_HZ;
301 break;
302 default:
303 return -ENOENT;
304 }
305
306 return rate;
307}
308
309static ulong rk3588_top_set_clk(struct rk3588_clk_priv *priv,
310 ulong clk_id, ulong rate)
311{
312 struct rk3588_cru *cru = priv->cru;
313 int src_clk, src_clk_div;
314
315 switch (clk_id) {
316 case ACLK_TOP_ROOT:
Elaine Zhang9aaa5ab2023-10-11 18:29:45 +0800317 if (!(priv->cpll_hz % rate)) {
318 src_clk = ACLK_TOP_ROOT_SRC_SEL_CPLL;
319 src_clk_div = DIV_ROUND_UP(priv->cpll_hz, rate);
320 } else {
321 src_clk = ACLK_TOP_ROOT_SRC_SEL_GPLL;
322 src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
323 }
Jagan Teki7d031ee2023-01-30 20:27:36 +0530324 assert(src_clk_div - 1 <= 31);
325 rk_clrsetreg(&cru->clksel_con[8],
326 ACLK_TOP_ROOT_DIV_MASK |
327 ACLK_TOP_ROOT_SRC_SEL_MASK,
Elaine Zhang9aaa5ab2023-10-11 18:29:45 +0800328 (src_clk <<
Jagan Teki7d031ee2023-01-30 20:27:36 +0530329 ACLK_TOP_ROOT_SRC_SEL_SHIFT) |
330 (src_clk_div - 1) << ACLK_TOP_ROOT_DIV_SHIFT);
331 break;
332 case ACLK_LOW_TOP_ROOT:
333 src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
334 assert(src_clk_div - 1 <= 31);
335 rk_clrsetreg(&cru->clksel_con[8],
336 ACLK_LOW_TOP_ROOT_DIV_MASK |
337 ACLK_LOW_TOP_ROOT_SRC_SEL_MASK,
338 (ACLK_LOW_TOP_ROOT_SRC_SEL_GPLL <<
339 ACLK_LOW_TOP_ROOT_SRC_SEL_SHIFT) |
340 (src_clk_div - 1) << ACLK_LOW_TOP_ROOT_DIV_SHIFT);
341 break;
342 case PCLK_TOP_ROOT:
343 if (rate == 100 * MHz)
344 src_clk = PCLK_TOP_ROOT_SEL_100M;
345 else if (rate == 50 * MHz)
346 src_clk = PCLK_TOP_ROOT_SEL_50M;
347 else
348 src_clk = PCLK_TOP_ROOT_SEL_24M;
349 rk_clrsetreg(&cru->clksel_con[8],
350 PCLK_TOP_ROOT_SEL_MASK,
351 src_clk << PCLK_TOP_ROOT_SEL_SHIFT);
352 break;
353 default:
354 printf("do not support this top freq\n");
355 return -EINVAL;
356 }
357
358 return rk3588_top_get_clk(priv, clk_id);
359}
360
361static ulong rk3588_i2c_get_clk(struct rk3588_clk_priv *priv, ulong clk_id)
362{
363 struct rk3588_cru *cru = priv->cru;
364 u32 sel, con;
365 ulong rate;
366
367 switch (clk_id) {
368 case CLK_I2C0:
369 con = readl(&cru->pmuclksel_con[3]);
370 sel = (con & CLK_I2C0_SEL_MASK) >> CLK_I2C0_SEL_SHIFT;
371 break;
372 case CLK_I2C1:
373 con = readl(&cru->clksel_con[38]);
374 sel = (con & CLK_I2C1_SEL_MASK) >> CLK_I2C1_SEL_SHIFT;
375 break;
376 case CLK_I2C2:
377 con = readl(&cru->clksel_con[38]);
378 sel = (con & CLK_I2C2_SEL_MASK) >> CLK_I2C2_SEL_SHIFT;
379 break;
380 case CLK_I2C3:
381 con = readl(&cru->clksel_con[38]);
382 sel = (con & CLK_I2C3_SEL_MASK) >> CLK_I2C3_SEL_SHIFT;
383 break;
384 case CLK_I2C4:
385 con = readl(&cru->clksel_con[38]);
386 sel = (con & CLK_I2C4_SEL_MASK) >> CLK_I2C4_SEL_SHIFT;
387 break;
388 case CLK_I2C5:
389 con = readl(&cru->clksel_con[38]);
390 sel = (con & CLK_I2C5_SEL_MASK) >> CLK_I2C5_SEL_SHIFT;
391 break;
392 case CLK_I2C6:
393 con = readl(&cru->clksel_con[38]);
394 sel = (con & CLK_I2C6_SEL_MASK) >> CLK_I2C6_SEL_SHIFT;
395 break;
396 case CLK_I2C7:
397 con = readl(&cru->clksel_con[38]);
398 sel = (con & CLK_I2C7_SEL_MASK) >> CLK_I2C7_SEL_SHIFT;
399 break;
400 case CLK_I2C8:
401 con = readl(&cru->clksel_con[38]);
402 sel = (con & CLK_I2C8_SEL_MASK) >> CLK_I2C8_SEL_SHIFT;
403 break;
404 default:
405 return -ENOENT;
406 }
407 if (sel == CLK_I2C_SEL_200M)
408 rate = 200 * MHz;
409 else
410 rate = 100 * MHz;
411
412 return rate;
413}
414
415static ulong rk3588_i2c_set_clk(struct rk3588_clk_priv *priv, ulong clk_id,
416 ulong rate)
417{
418 struct rk3588_cru *cru = priv->cru;
419 int src_clk;
420
421 if (rate >= 198 * MHz)
422 src_clk = CLK_I2C_SEL_200M;
423 else
424 src_clk = CLK_I2C_SEL_100M;
425
426 switch (clk_id) {
427 case CLK_I2C0:
428 rk_clrsetreg(&cru->pmuclksel_con[3], CLK_I2C0_SEL_MASK,
429 src_clk << CLK_I2C0_SEL_SHIFT);
430 break;
431 case CLK_I2C1:
432 rk_clrsetreg(&cru->clksel_con[38], CLK_I2C1_SEL_MASK,
433 src_clk << CLK_I2C1_SEL_SHIFT);
434 break;
435 case CLK_I2C2:
436 rk_clrsetreg(&cru->clksel_con[38], CLK_I2C2_SEL_MASK,
437 src_clk << CLK_I2C2_SEL_SHIFT);
438 break;
439 case CLK_I2C3:
440 rk_clrsetreg(&cru->clksel_con[38], CLK_I2C3_SEL_MASK,
441 src_clk << CLK_I2C3_SEL_SHIFT);
442 break;
443 case CLK_I2C4:
444 rk_clrsetreg(&cru->clksel_con[38], CLK_I2C4_SEL_MASK,
445 src_clk << CLK_I2C4_SEL_SHIFT);
446 break;
447 case CLK_I2C5:
448 rk_clrsetreg(&cru->clksel_con[38], CLK_I2C5_SEL_MASK,
449 src_clk << CLK_I2C5_SEL_SHIFT);
450 break;
451 case CLK_I2C6:
452 rk_clrsetreg(&cru->clksel_con[38], CLK_I2C6_SEL_MASK,
453 src_clk << CLK_I2C6_SEL_SHIFT);
454 break;
455 case CLK_I2C7:
456 rk_clrsetreg(&cru->clksel_con[38], CLK_I2C7_SEL_MASK,
457 src_clk << CLK_I2C7_SEL_SHIFT);
458 break;
459 case CLK_I2C8:
460 rk_clrsetreg(&cru->clksel_con[38], CLK_I2C8_SEL_MASK,
461 src_clk << CLK_I2C8_SEL_SHIFT);
462 break;
463 default:
464 return -ENOENT;
465 }
466
467 return rk3588_i2c_get_clk(priv, clk_id);
468}
469
470static ulong rk3588_spi_get_clk(struct rk3588_clk_priv *priv, ulong clk_id)
471{
472 struct rk3588_cru *cru = priv->cru;
473 u32 sel, con;
474
475 con = readl(&cru->clksel_con[59]);
476
477 switch (clk_id) {
478 case CLK_SPI0:
479 sel = (con & CLK_SPI0_SEL_MASK) >> CLK_SPI0_SEL_SHIFT;
480 break;
481 case CLK_SPI1:
482 sel = (con & CLK_SPI1_SEL_MASK) >> CLK_SPI1_SEL_SHIFT;
483 break;
484 case CLK_SPI2:
485 sel = (con & CLK_SPI2_SEL_MASK) >> CLK_SPI2_SEL_SHIFT;
486 break;
487 case CLK_SPI3:
488 sel = (con & CLK_SPI3_SEL_MASK) >> CLK_SPI3_SEL_SHIFT;
489 break;
490 case CLK_SPI4:
491 sel = (con & CLK_SPI4_SEL_MASK) >> CLK_SPI4_SEL_SHIFT;
492 break;
493 default:
494 return -ENOENT;
495 }
496
497 switch (sel) {
498 case CLK_SPI_SEL_200M:
499 return 200 * MHz;
500 case CLK_SPI_SEL_150M:
501 return 150 * MHz;
502 case CLK_SPI_SEL_24M:
503 return OSC_HZ;
504 default:
505 return -ENOENT;
506 }
507}
508
509static ulong rk3588_spi_set_clk(struct rk3588_clk_priv *priv,
510 ulong clk_id, ulong rate)
511{
512 struct rk3588_cru *cru = priv->cru;
513 int src_clk;
514
515 if (rate >= 198 * MHz)
516 src_clk = CLK_SPI_SEL_200M;
517 else if (rate >= 140 * MHz)
518 src_clk = CLK_SPI_SEL_150M;
519 else
520 src_clk = CLK_SPI_SEL_24M;
521
522 switch (clk_id) {
523 case CLK_SPI0:
524 rk_clrsetreg(&cru->clksel_con[59],
525 CLK_SPI0_SEL_MASK,
526 src_clk << CLK_SPI0_SEL_SHIFT);
527 break;
528 case CLK_SPI1:
529 rk_clrsetreg(&cru->clksel_con[59],
530 CLK_SPI1_SEL_MASK,
531 src_clk << CLK_SPI1_SEL_SHIFT);
532 break;
533 case CLK_SPI2:
534 rk_clrsetreg(&cru->clksel_con[59],
535 CLK_SPI2_SEL_MASK,
536 src_clk << CLK_SPI2_SEL_SHIFT);
537 break;
538 case CLK_SPI3:
539 rk_clrsetreg(&cru->clksel_con[59],
540 CLK_SPI3_SEL_MASK,
541 src_clk << CLK_SPI3_SEL_SHIFT);
542 break;
543 case CLK_SPI4:
544 rk_clrsetreg(&cru->clksel_con[59],
545 CLK_SPI4_SEL_MASK,
546 src_clk << CLK_SPI4_SEL_SHIFT);
547 break;
548 default:
549 return -ENOENT;
550 }
551
552 return rk3588_spi_get_clk(priv, clk_id);
553}
554
555static ulong rk3588_pwm_get_clk(struct rk3588_clk_priv *priv, ulong clk_id)
556{
557 struct rk3588_cru *cru = priv->cru;
558 u32 sel, con;
559
560 switch (clk_id) {
561 case CLK_PWM1:
562 con = readl(&cru->clksel_con[59]);
563 sel = (con & CLK_PWM1_SEL_MASK) >> CLK_PWM1_SEL_SHIFT;
564 break;
565 case CLK_PWM2:
566 con = readl(&cru->clksel_con[59]);
567 sel = (con & CLK_PWM2_SEL_MASK) >> CLK_PWM2_SEL_SHIFT;
568 break;
569 case CLK_PWM3:
570 con = readl(&cru->clksel_con[60]);
571 sel = (con & CLK_PWM3_SEL_MASK) >> CLK_PWM3_SEL_SHIFT;
572 break;
573 case CLK_PMU1PWM:
574 con = readl(&cru->pmuclksel_con[2]);
575 sel = (con & CLK_PMU1PWM_SEL_MASK) >> CLK_PMU1PWM_SEL_SHIFT;
576 break;
577 default:
578 return -ENOENT;
579 }
580
581 switch (sel) {
582 case CLK_PWM_SEL_100M:
583 return 100 * MHz;
584 case CLK_PWM_SEL_50M:
585 return 50 * MHz;
586 case CLK_PWM_SEL_24M:
587 return OSC_HZ;
588 default:
589 return -ENOENT;
590 }
591}
592
593static ulong rk3588_pwm_set_clk(struct rk3588_clk_priv *priv,
594 ulong clk_id, ulong rate)
595{
596 struct rk3588_cru *cru = priv->cru;
597 int src_clk;
598
599 if (rate >= 99 * MHz)
600 src_clk = CLK_PWM_SEL_100M;
601 else if (rate >= 50 * MHz)
602 src_clk = CLK_PWM_SEL_50M;
603 else
604 src_clk = CLK_PWM_SEL_24M;
605
606 switch (clk_id) {
607 case CLK_PWM1:
608 rk_clrsetreg(&cru->clksel_con[59],
609 CLK_PWM1_SEL_MASK,
610 src_clk << CLK_PWM1_SEL_SHIFT);
611 break;
612 case CLK_PWM2:
613 rk_clrsetreg(&cru->clksel_con[59],
614 CLK_PWM2_SEL_MASK,
615 src_clk << CLK_PWM2_SEL_SHIFT);
616 break;
617 case CLK_PWM3:
618 rk_clrsetreg(&cru->clksel_con[60],
619 CLK_PWM3_SEL_MASK,
620 src_clk << CLK_PWM3_SEL_SHIFT);
621 break;
622 case CLK_PMU1PWM:
623 rk_clrsetreg(&cru->pmuclksel_con[2],
624 CLK_PMU1PWM_SEL_MASK,
625 src_clk << CLK_PMU1PWM_SEL_SHIFT);
626 break;
627 default:
628 return -ENOENT;
629 }
630
631 return rk3588_pwm_get_clk(priv, clk_id);
632}
633
634static ulong rk3588_adc_get_clk(struct rk3588_clk_priv *priv, ulong clk_id)
635{
636 struct rk3588_cru *cru = priv->cru;
637 u32 div, sel, con, prate;
638
639 switch (clk_id) {
640 case CLK_SARADC:
641 con = readl(&cru->clksel_con[40]);
642 div = (con & CLK_SARADC_DIV_MASK) >> CLK_SARADC_DIV_SHIFT;
643 sel = (con & CLK_SARADC_SEL_MASK) >>
644 CLK_SARADC_SEL_SHIFT;
645 if (sel == CLK_SARADC_SEL_24M)
646 prate = OSC_HZ;
647 else
648 prate = priv->gpll_hz;
649 return DIV_TO_RATE(prate, div);
650 case CLK_TSADC:
651 con = readl(&cru->clksel_con[41]);
652 div = (con & CLK_TSADC_DIV_MASK) >>
653 CLK_TSADC_DIV_SHIFT;
654 sel = (con & CLK_TSADC_SEL_MASK) >>
655 CLK_TSADC_SEL_SHIFT;
656 if (sel == CLK_TSADC_SEL_24M)
657 prate = OSC_HZ;
658 else
659 prate = 100 * MHz;
660 return DIV_TO_RATE(prate, div);
661 default:
662 return -ENOENT;
663 }
664}
665
666static ulong rk3588_adc_set_clk(struct rk3588_clk_priv *priv,
667 ulong clk_id, ulong rate)
668{
669 struct rk3588_cru *cru = priv->cru;
670 int src_clk_div;
671
672 switch (clk_id) {
673 case CLK_SARADC:
674 if (!(OSC_HZ % rate)) {
675 src_clk_div = DIV_ROUND_UP(OSC_HZ, rate);
676 assert(src_clk_div - 1 <= 255);
677 rk_clrsetreg(&cru->clksel_con[40],
678 CLK_SARADC_SEL_MASK |
679 CLK_SARADC_DIV_MASK,
680 (CLK_SARADC_SEL_24M <<
681 CLK_SARADC_SEL_SHIFT) |
682 (src_clk_div - 1) <<
683 CLK_SARADC_DIV_SHIFT);
684 } else {
685 src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
686 assert(src_clk_div - 1 <= 255);
687 rk_clrsetreg(&cru->clksel_con[40],
688 CLK_SARADC_SEL_MASK |
689 CLK_SARADC_DIV_MASK,
690 (CLK_SARADC_SEL_GPLL <<
691 CLK_SARADC_SEL_SHIFT) |
692 (src_clk_div - 1) <<
693 CLK_SARADC_DIV_SHIFT);
694 }
695 break;
696 case CLK_TSADC:
697 if (!(OSC_HZ % rate)) {
698 src_clk_div = DIV_ROUND_UP(OSC_HZ, rate);
699 assert(src_clk_div - 1 <= 255);
700 rk_clrsetreg(&cru->clksel_con[41],
701 CLK_TSADC_SEL_MASK |
702 CLK_TSADC_DIV_MASK,
703 (CLK_TSADC_SEL_24M <<
704 CLK_TSADC_SEL_SHIFT) |
705 (src_clk_div - 1) <<
706 CLK_TSADC_DIV_SHIFT);
707 } else {
708 src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
709 assert(src_clk_div - 1 <= 7);
710 rk_clrsetreg(&cru->clksel_con[41],
711 CLK_TSADC_SEL_MASK |
712 CLK_TSADC_DIV_MASK,
713 (CLK_TSADC_SEL_GPLL <<
714 CLK_TSADC_SEL_SHIFT) |
715 (src_clk_div - 1) <<
716 CLK_TSADC_DIV_SHIFT);
717 }
718 break;
719 default:
720 return -ENOENT;
721 }
722 return rk3588_adc_get_clk(priv, clk_id);
723}
724
725static ulong rk3588_mmc_get_clk(struct rk3588_clk_priv *priv, ulong clk_id)
726{
727 struct rk3588_cru *cru = priv->cru;
728 u32 sel, con, div, prate;
729
730 switch (clk_id) {
731 case CCLK_SRC_SDIO:
732 con = readl(&cru->clksel_con[172]);
733 div = (con & CCLK_SDIO_SRC_DIV_MASK) >> CCLK_SDIO_SRC_DIV_SHIFT;
734 sel = (con & CCLK_SDIO_SRC_SEL_MASK) >>
735 CCLK_SDIO_SRC_SEL_SHIFT;
736 if (sel == CCLK_SDIO_SRC_SEL_GPLL)
737 prate = priv->gpll_hz;
738 else if (sel == CCLK_SDIO_SRC_SEL_CPLL)
739 prate = priv->cpll_hz;
740 else
741 prate = OSC_HZ;
742 return DIV_TO_RATE(prate, div);
743 case CCLK_EMMC:
744 con = readl(&cru->clksel_con[77]);
745 div = (con & CCLK_EMMC_DIV_MASK) >> CCLK_EMMC_DIV_SHIFT;
746 sel = (con & CCLK_EMMC_SEL_MASK) >>
747 CCLK_EMMC_SEL_SHIFT;
748 if (sel == CCLK_EMMC_SEL_GPLL)
749 prate = priv->gpll_hz;
750 else if (sel == CCLK_EMMC_SEL_CPLL)
751 prate = priv->cpll_hz;
752 else
753 prate = OSC_HZ;
754 return DIV_TO_RATE(prate, div);
755 case BCLK_EMMC:
756 con = readl(&cru->clksel_con[78]);
757 div = (con & BCLK_EMMC_DIV_MASK) >> BCLK_EMMC_DIV_SHIFT;
758 sel = (con & BCLK_EMMC_SEL_MASK) >>
759 BCLK_EMMC_SEL_SHIFT;
760 if (sel == CCLK_EMMC_SEL_CPLL)
761 prate = priv->cpll_hz;
762 else
763 prate = priv->gpll_hz;
764 return DIV_TO_RATE(prate, div);
765 case SCLK_SFC:
766 con = readl(&cru->clksel_con[78]);
767 div = (con & SCLK_SFC_DIV_MASK) >> SCLK_SFC_DIV_SHIFT;
768 sel = (con & SCLK_SFC_SEL_MASK) >>
769 SCLK_SFC_SEL_SHIFT;
770 if (sel == SCLK_SFC_SEL_GPLL)
771 prate = priv->gpll_hz;
772 else if (sel == SCLK_SFC_SEL_CPLL)
773 prate = priv->cpll_hz;
774 else
775 prate = OSC_HZ;
776 return DIV_TO_RATE(prate, div);
777 case DCLK_DECOM:
778 con = readl(&cru->clksel_con[62]);
779 div = (con & DCLK_DECOM_DIV_MASK) >> DCLK_DECOM_DIV_SHIFT;
780 sel = (con & DCLK_DECOM_SEL_MASK) >>
781 DCLK_DECOM_SEL_SHIFT;
782 if (sel == DCLK_DECOM_SEL_SPLL)
783 prate = 702 * MHz;
784 else
785 prate = priv->gpll_hz;
786 return DIV_TO_RATE(prate, div);
787 default:
788 return -ENOENT;
789 }
790}
791
792static ulong rk3588_mmc_set_clk(struct rk3588_clk_priv *priv,
793 ulong clk_id, ulong rate)
794{
795 struct rk3588_cru *cru = priv->cru;
796 int src_clk, div;
797
798 switch (clk_id) {
799 case CCLK_SRC_SDIO:
800 case CCLK_EMMC:
801 case SCLK_SFC:
802 if (!(OSC_HZ % rate)) {
803 src_clk = SCLK_SFC_SEL_24M;
804 div = DIV_ROUND_UP(OSC_HZ, rate);
805 } else if (!(priv->cpll_hz % rate)) {
806 src_clk = SCLK_SFC_SEL_CPLL;
807 div = DIV_ROUND_UP(priv->cpll_hz, rate);
808 } else {
809 src_clk = SCLK_SFC_SEL_GPLL;
810 div = DIV_ROUND_UP(priv->gpll_hz, rate);
811 }
812 break;
813 case BCLK_EMMC:
814 if (!(priv->cpll_hz % rate)) {
815 src_clk = CCLK_EMMC_SEL_CPLL;
816 div = DIV_ROUND_UP(priv->cpll_hz, rate);
817 } else {
818 src_clk = CCLK_EMMC_SEL_GPLL;
819 div = DIV_ROUND_UP(priv->gpll_hz, rate);
820 }
821 break;
822 case DCLK_DECOM:
823 if (!(702 * MHz % rate)) {
824 src_clk = DCLK_DECOM_SEL_SPLL;
825 div = DIV_ROUND_UP(702 * MHz, rate);
826 } else {
827 src_clk = DCLK_DECOM_SEL_GPLL;
828 div = DIV_ROUND_UP(priv->gpll_hz, rate);
829 }
830 break;
831 default:
832 return -ENOENT;
833 }
834
835 switch (clk_id) {
836 case CCLK_SRC_SDIO:
837 rk_clrsetreg(&cru->clksel_con[172],
838 CCLK_SDIO_SRC_SEL_MASK |
839 CCLK_SDIO_SRC_DIV_MASK,
840 (src_clk << CCLK_SDIO_SRC_SEL_SHIFT) |
841 (div - 1) << CCLK_SDIO_SRC_DIV_SHIFT);
842 break;
843 case CCLK_EMMC:
844 rk_clrsetreg(&cru->clksel_con[77],
845 CCLK_EMMC_SEL_MASK |
846 CCLK_EMMC_DIV_MASK,
847 (src_clk << CCLK_EMMC_SEL_SHIFT) |
848 (div - 1) << CCLK_EMMC_DIV_SHIFT);
849 break;
850 case BCLK_EMMC:
851 rk_clrsetreg(&cru->clksel_con[78],
852 BCLK_EMMC_DIV_MASK |
853 BCLK_EMMC_SEL_MASK,
854 (src_clk << BCLK_EMMC_SEL_SHIFT) |
855 (div - 1) << BCLK_EMMC_DIV_SHIFT);
856 break;
857 case SCLK_SFC:
858 rk_clrsetreg(&cru->clksel_con[78],
859 SCLK_SFC_DIV_MASK |
860 SCLK_SFC_SEL_MASK,
861 (src_clk << SCLK_SFC_SEL_SHIFT) |
862 (div - 1) << SCLK_SFC_DIV_SHIFT);
863 break;
864 case DCLK_DECOM:
865 rk_clrsetreg(&cru->clksel_con[62],
866 DCLK_DECOM_DIV_MASK |
867 DCLK_DECOM_SEL_MASK,
868 (src_clk << DCLK_DECOM_SEL_SHIFT) |
869 (div - 1) << DCLK_DECOM_DIV_SHIFT);
870 break;
871 default:
872 return -ENOENT;
873 }
874
875 return rk3588_mmc_get_clk(priv, clk_id);
876}
877
878#ifndef CONFIG_SPL_BUILD
879static ulong rk3588_aux16m_get_clk(struct rk3588_clk_priv *priv, ulong clk_id)
880{
881 struct rk3588_cru *cru = priv->cru;
882 u32 div, con, parent;
883
884 parent = priv->gpll_hz;
885 con = readl(&cru->clksel_con[117]);
886
887 switch (clk_id) {
888 case CLK_AUX16M_0:
889 div = (con & CLK_AUX16MHZ_0_DIV_MASK) >> CLK_AUX16MHZ_0_DIV_SHIFT;
890 return DIV_TO_RATE(parent, div);
891 case CLK_AUX16M_1:
892 div = (con & CLK_AUX16MHZ_1_DIV_MASK) >> CLK_AUX16MHZ_1_DIV_SHIFT;
893 return DIV_TO_RATE(parent, div);
894 default:
895 return -ENOENT;
896 }
897}
898
899static ulong rk3588_aux16m_set_clk(struct rk3588_clk_priv *priv,
900 ulong clk_id, ulong rate)
901{
902 struct rk3588_cru *cru = priv->cru;
903 u32 div;
904
905 if (!priv->gpll_hz) {
906 printf("%s gpll=%lu\n", __func__, priv->gpll_hz);
907 return -ENOENT;
908 }
909
910 div = DIV_ROUND_UP(priv->gpll_hz, rate);
911
912 switch (clk_id) {
913 case CLK_AUX16M_0:
914 rk_clrsetreg(&cru->clksel_con[117], CLK_AUX16MHZ_0_DIV_MASK,
915 (div - 1) << CLK_AUX16MHZ_0_DIV_SHIFT);
916 break;
917 case CLK_AUX16M_1:
918 rk_clrsetreg(&cru->clksel_con[117], CLK_AUX16MHZ_1_DIV_MASK,
919 (div - 1) << CLK_AUX16MHZ_1_DIV_SHIFT);
920 break;
921 default:
922 return -ENOENT;
923 }
924
925 return rk3588_aux16m_get_clk(priv, clk_id);
926}
927
928static ulong rk3588_aclk_vop_get_clk(struct rk3588_clk_priv *priv, ulong clk_id)
929{
930 struct rk3588_cru *cru = priv->cru;
931 u32 div, sel, con, parent;
932
933 switch (clk_id) {
934 case ACLK_VOP_ROOT:
935 case ACLK_VOP:
936 con = readl(&cru->clksel_con[110]);
937 div = (con & ACLK_VOP_ROOT_DIV_MASK) >> ACLK_VOP_ROOT_DIV_SHIFT;
938 sel = (con & ACLK_VOP_ROOT_SEL_MASK) >> ACLK_VOP_ROOT_SEL_SHIFT;
939 if (sel == ACLK_VOP_ROOT_SEL_GPLL)
940 parent = priv->gpll_hz;
941 else if (sel == ACLK_VOP_ROOT_SEL_CPLL)
942 parent = priv->cpll_hz;
943 else if (sel == ACLK_VOP_ROOT_SEL_AUPLL)
944 parent = priv->aupll_hz;
945 else if (sel == ACLK_VOP_ROOT_SEL_NPLL)
946 parent = priv->npll_hz;
947 else
948 parent = 702 * MHz;
949 return DIV_TO_RATE(parent, div);
950 case ACLK_VOP_LOW_ROOT:
951 con = readl(&cru->clksel_con[110]);
952 sel = (con & ACLK_VOP_LOW_ROOT_SEL_MASK) >>
953 ACLK_VOP_LOW_ROOT_SEL_SHIFT;
954 if (sel == ACLK_VOP_LOW_ROOT_SEL_400M)
955 return 396 * MHz;
956 else if (sel == ACLK_VOP_LOW_ROOT_SEL_200M)
957 return 200 * MHz;
958 else if (sel == ACLK_VOP_LOW_ROOT_SEL_100M)
959 return 100 * MHz;
960 else
961 return OSC_HZ;
962 case HCLK_VOP_ROOT:
963 con = readl(&cru->clksel_con[110]);
964 sel = (con & HCLK_VOP_ROOT_SEL_MASK) >> HCLK_VOP_ROOT_SEL_SHIFT;
965 if (sel == HCLK_VOP_ROOT_SEL_200M)
966 return 200 * MHz;
967 else if (sel == HCLK_VOP_ROOT_SEL_100M)
968 return 100 * MHz;
969 else if (sel == HCLK_VOP_ROOT_SEL_50M)
970 return 50 * MHz;
971 else
972 return OSC_HZ;
973 default:
974 return -ENOENT;
975 }
976}
977
978static ulong rk3588_aclk_vop_set_clk(struct rk3588_clk_priv *priv,
979 ulong clk_id, ulong rate)
980{
981 struct rk3588_cru *cru = priv->cru;
982 int src_clk, div;
983
984 switch (clk_id) {
985 case ACLK_VOP_ROOT:
986 case ACLK_VOP:
987 if (rate >= 850 * MHz) {
988 src_clk = ACLK_VOP_ROOT_SEL_NPLL;
989 div = 1;
990 } else if (rate >= 750 * MHz) {
991 src_clk = ACLK_VOP_ROOT_SEL_CPLL;
992 div = 2;
993 } else if (rate >= 700 * MHz) {
994 src_clk = ACLK_VOP_ROOT_SEL_SPLL;
995 div = 1;
996 } else if (!(priv->cpll_hz % rate)) {
997 src_clk = ACLK_VOP_ROOT_SEL_CPLL;
998 div = DIV_ROUND_UP(priv->cpll_hz, rate);
999 } else {
1000 src_clk = ACLK_VOP_ROOT_SEL_GPLL;
1001 div = DIV_ROUND_UP(priv->gpll_hz, rate);
1002 }
1003 rk_clrsetreg(&cru->clksel_con[110],
1004 ACLK_VOP_ROOT_DIV_MASK |
1005 ACLK_VOP_ROOT_SEL_MASK,
1006 (src_clk << ACLK_VOP_ROOT_SEL_SHIFT) |
1007 (div - 1) << ACLK_VOP_ROOT_DIV_SHIFT);
1008 break;
1009 case ACLK_VOP_LOW_ROOT:
1010 if (rate == 400 * MHz || rate == 396 * MHz)
1011 src_clk = ACLK_VOP_LOW_ROOT_SEL_400M;
1012 else if (rate == 200 * MHz)
1013 src_clk = ACLK_VOP_LOW_ROOT_SEL_200M;
1014 else if (rate == 100 * MHz)
1015 src_clk = ACLK_VOP_LOW_ROOT_SEL_100M;
1016 else
1017 src_clk = ACLK_VOP_LOW_ROOT_SEL_24M;
1018 rk_clrsetreg(&cru->clksel_con[110],
1019 ACLK_VOP_LOW_ROOT_SEL_MASK,
1020 src_clk << ACLK_VOP_LOW_ROOT_SEL_SHIFT);
1021 break;
1022 case HCLK_VOP_ROOT:
1023 if (rate == 200 * MHz)
1024 src_clk = HCLK_VOP_ROOT_SEL_200M;
1025 else if (rate == 100 * MHz)
1026 src_clk = HCLK_VOP_ROOT_SEL_100M;
1027 else if (rate == 50 * MHz)
1028 src_clk = HCLK_VOP_ROOT_SEL_50M;
1029 else
1030 src_clk = HCLK_VOP_ROOT_SEL_24M;
1031 rk_clrsetreg(&cru->clksel_con[110],
1032 HCLK_VOP_ROOT_SEL_MASK,
1033 src_clk << HCLK_VOP_ROOT_SEL_SHIFT);
1034 break;
1035 default:
1036 return -ENOENT;
1037 }
1038
1039 return rk3588_aclk_vop_get_clk(priv, clk_id);
1040}
1041
1042static ulong rk3588_dclk_vop_get_clk(struct rk3588_clk_priv *priv, ulong clk_id)
1043{
1044 struct rk3588_cru *cru = priv->cru;
1045 u32 div, sel, con, parent;
1046
1047 switch (clk_id) {
1048 case DCLK_VOP0:
1049 case DCLK_VOP0_SRC:
1050 con = readl(&cru->clksel_con[111]);
1051 div = (con & DCLK0_VOP_SRC_DIV_MASK) >> DCLK0_VOP_SRC_DIV_SHIFT;
1052 sel = (con & DCLK0_VOP_SRC_SEL_MASK) >> DCLK0_VOP_SRC_SEL_SHIFT;
1053 break;
1054 case DCLK_VOP1:
1055 case DCLK_VOP1_SRC:
1056 con = readl(&cru->clksel_con[111]);
1057 div = (con & DCLK1_VOP_SRC_DIV_MASK) >> DCLK1_VOP_SRC_DIV_SHIFT;
1058 sel = (con & DCLK1_VOP_SRC_SEL_MASK) >> DCLK1_VOP_SRC_SEL_SHIFT;
1059 break;
1060 case DCLK_VOP2:
1061 case DCLK_VOP2_SRC:
1062 con = readl(&cru->clksel_con[112]);
1063 div = (con & DCLK2_VOP_SRC_DIV_MASK) >> DCLK2_VOP_SRC_DIV_SHIFT;
1064 sel = (con & DCLK2_VOP_SRC_SEL_MASK) >> DCLK2_VOP_SRC_SEL_SHIFT;
1065 break;
1066 case DCLK_VOP3:
1067 con = readl(&cru->clksel_con[113]);
1068 div = (con & DCLK3_VOP_SRC_DIV_MASK) >> DCLK3_VOP_SRC_DIV_SHIFT;
1069 sel = (con & DCLK3_VOP_SRC_SEL_MASK) >> DCLK3_VOP_SRC_SEL_SHIFT;
1070 break;
1071 default:
1072 return -ENOENT;
1073 }
1074
1075 if (sel == DCLK_VOP_SRC_SEL_AUPLL)
1076 parent = priv->aupll_hz;
1077 else if (sel == DCLK_VOP_SRC_SEL_V0PLL)
1078 parent = rockchip_pll_get_rate(&rk3588_pll_clks[V0PLL],
1079 priv->cru, V0PLL);
1080 else if (sel == DCLK_VOP_SRC_SEL_GPLL)
1081 parent = priv->gpll_hz;
1082 else if (sel == DCLK_VOP_SRC_SEL_CPLL)
1083 parent = priv->cpll_hz;
1084 else
1085 return -ENOENT;
1086
1087 return DIV_TO_RATE(parent, div);
1088}
1089
1090#define RK3588_VOP_PLL_LIMIT_FREQ 600000000
1091
1092static ulong rk3588_dclk_vop_set_clk(struct rk3588_clk_priv *priv,
1093 ulong clk_id, ulong rate)
1094{
1095 struct rk3588_cru *cru = priv->cru;
1096 ulong pll_rate, now, best_rate = 0;
1097 u32 i, conid, con, sel, div, best_div = 0, best_sel = 0;
1098 u32 mask, div_shift, sel_shift;
1099
1100 switch (clk_id) {
1101 case DCLK_VOP0:
1102 case DCLK_VOP0_SRC:
1103 conid = 111;
1104 con = readl(&cru->clksel_con[111]);
1105 sel = (con & DCLK0_VOP_SRC_SEL_MASK) >> DCLK0_VOP_SRC_SEL_SHIFT;
1106 mask = DCLK0_VOP_SRC_SEL_MASK | DCLK0_VOP_SRC_DIV_MASK;
1107 div_shift = DCLK0_VOP_SRC_DIV_SHIFT;
1108 sel_shift = DCLK0_VOP_SRC_SEL_SHIFT;
1109 break;
1110 case DCLK_VOP1:
1111 case DCLK_VOP1_SRC:
1112 conid = 111;
1113 con = readl(&cru->clksel_con[111]);
1114 sel = (con & DCLK1_VOP_SRC_SEL_MASK) >> DCLK1_VOP_SRC_SEL_SHIFT;
1115 mask = DCLK1_VOP_SRC_SEL_MASK | DCLK1_VOP_SRC_DIV_MASK;
1116 div_shift = DCLK1_VOP_SRC_DIV_SHIFT;
1117 sel_shift = DCLK1_VOP_SRC_SEL_SHIFT;
1118 break;
1119 case DCLK_VOP2:
1120 case DCLK_VOP2_SRC:
1121 conid = 112;
1122 con = readl(&cru->clksel_con[112]);
1123 sel = (con & DCLK2_VOP_SRC_SEL_MASK) >> DCLK2_VOP_SRC_SEL_SHIFT;
1124 mask = DCLK2_VOP_SRC_SEL_MASK | DCLK2_VOP_SRC_DIV_MASK;
1125 div_shift = DCLK2_VOP_SRC_DIV_SHIFT;
1126 sel_shift = DCLK2_VOP_SRC_SEL_SHIFT;
1127 break;
1128 case DCLK_VOP3:
1129 conid = 113;
1130 con = readl(&cru->clksel_con[113]);
1131 sel = (con & DCLK3_VOP_SRC_SEL_MASK) >> DCLK3_VOP_SRC_SEL_SHIFT;
1132 mask = DCLK3_VOP_SRC_SEL_MASK | DCLK3_VOP_SRC_DIV_MASK;
1133 div_shift = DCLK3_VOP_SRC_DIV_SHIFT;
1134 sel_shift = DCLK3_VOP_SRC_SEL_SHIFT;
1135 break;
1136 default:
1137 return -ENOENT;
1138 }
1139
1140 if (sel == DCLK_VOP_SRC_SEL_V0PLL) {
Elaine Zhang28920742023-10-12 18:18:12 +08001141 pll_rate = rockchip_pll_get_rate(&rk3588_pll_clks[V0PLL],
1142 priv->cru, V0PLL);
1143 if (pll_rate >= RK3588_VOP_PLL_LIMIT_FREQ && pll_rate % rate == 0) {
1144 div = DIV_ROUND_UP(pll_rate, rate);
1145 rk_clrsetreg(&cru->clksel_con[conid],
1146 mask,
1147 DCLK_VOP_SRC_SEL_V0PLL << sel_shift |
1148 ((div - 1) << div_shift));
1149 } else {
1150 div = DIV_ROUND_UP(RK3588_VOP_PLL_LIMIT_FREQ, rate);
1151 rk_clrsetreg(&cru->clksel_con[conid],
1152 mask,
1153 DCLK_VOP_SRC_SEL_V0PLL << sel_shift |
1154 ((div - 1) << div_shift));
1155 rockchip_pll_set_rate(&rk3588_pll_clks[V0PLL],
1156 priv->cru, V0PLL, div * rate);
1157 }
Jagan Teki7d031ee2023-01-30 20:27:36 +05301158 } else {
1159 for (i = 0; i <= DCLK_VOP_SRC_SEL_AUPLL; i++) {
1160 switch (i) {
1161 case DCLK_VOP_SRC_SEL_GPLL:
1162 pll_rate = priv->gpll_hz;
1163 break;
1164 case DCLK_VOP_SRC_SEL_CPLL:
1165 pll_rate = priv->cpll_hz;
1166 break;
1167 case DCLK_VOP_SRC_SEL_AUPLL:
1168 pll_rate = priv->aupll_hz;
1169 break;
1170 case DCLK_VOP_SRC_SEL_V0PLL:
1171 pll_rate = 0;
1172 break;
1173 default:
1174 printf("do not support this vop pll sel\n");
1175 return -EINVAL;
1176 }
1177
1178 div = DIV_ROUND_UP(pll_rate, rate);
1179 if (div > 255)
1180 continue;
1181 now = pll_rate / div;
1182 if (abs(rate - now) < abs(rate - best_rate)) {
1183 best_rate = now;
1184 best_div = div;
1185 best_sel = i;
1186 }
1187 debug("p_rate=%lu, best_rate=%lu, div=%u, sel=%u\n",
1188 pll_rate, best_rate, best_div, best_sel);
1189 }
1190
1191 if (best_rate) {
1192 rk_clrsetreg(&cru->clksel_con[conid],
1193 mask,
1194 best_sel << sel_shift |
1195 (best_div - 1) << div_shift);
1196 } else {
1197 printf("do not support this vop freq %lu\n", rate);
1198 return -EINVAL;
1199 }
1200 }
1201 return rk3588_dclk_vop_get_clk(priv, clk_id);
1202}
1203
1204static ulong rk3588_gmac_get_clk(struct rk3588_clk_priv *priv, ulong clk_id)
1205{
1206 struct rk3588_cru *cru = priv->cru;
1207 u32 con, div;
1208
1209 switch (clk_id) {
1210 case CLK_GMAC0_PTP_REF:
1211 con = readl(&cru->clksel_con[81]);
1212 div = (con & CLK_GMAC0_PTP_DIV_MASK) >> CLK_GMAC0_PTP_DIV_SHIFT;
1213 return DIV_TO_RATE(priv->cpll_hz, div);
1214 case CLK_GMAC1_PTP_REF:
1215 con = readl(&cru->clksel_con[81]);
1216 div = (con & CLK_GMAC1_PTP_DIV_MASK) >> CLK_GMAC1_PTP_DIV_SHIFT;
1217 return DIV_TO_RATE(priv->cpll_hz, div);
1218 case CLK_GMAC_125M:
1219 con = readl(&cru->clksel_con[83]);
1220 div = (con & CLK_GMAC_125M_DIV_MASK) >> CLK_GMAC_125M_DIV_SHIFT;
1221 return DIV_TO_RATE(priv->cpll_hz, div);
1222 case CLK_GMAC_50M:
1223 con = readl(&cru->clksel_con[84]);
1224 div = (con & CLK_GMAC_50M_DIV_MASK) >> CLK_GMAC_50M_DIV_SHIFT;
1225 return DIV_TO_RATE(priv->cpll_hz, div);
1226 default:
1227 return -ENOENT;
1228 }
1229}
1230
1231static ulong rk3588_gmac_set_clk(struct rk3588_clk_priv *priv,
1232 ulong clk_id, ulong rate)
1233{
1234 struct rk3588_cru *cru = priv->cru;
1235 int div;
1236
1237 div = DIV_ROUND_UP(priv->cpll_hz, rate);
1238
1239 switch (clk_id) {
1240 case CLK_GMAC0_PTP_REF:
1241 rk_clrsetreg(&cru->clksel_con[81],
1242 CLK_GMAC0_PTP_DIV_MASK | CLK_GMAC0_PTP_SEL_MASK,
1243 CLK_GMAC0_PTP_SEL_CPLL << CLK_GMAC0_PTP_SEL_SHIFT |
1244 (div - 1) << CLK_GMAC0_PTP_DIV_SHIFT);
1245 break;
1246 case CLK_GMAC1_PTP_REF:
1247 rk_clrsetreg(&cru->clksel_con[81],
1248 CLK_GMAC1_PTP_DIV_MASK | CLK_GMAC1_PTP_SEL_MASK,
1249 CLK_GMAC1_PTP_SEL_CPLL << CLK_GMAC1_PTP_SEL_SHIFT |
1250 (div - 1) << CLK_GMAC1_PTP_DIV_SHIFT);
1251 break;
1252
1253 case CLK_GMAC_125M:
1254 rk_clrsetreg(&cru->clksel_con[83],
1255 CLK_GMAC_125M_DIV_MASK | CLK_GMAC_125M_SEL_MASK,
1256 CLK_GMAC_125M_SEL_CPLL << CLK_GMAC_125M_SEL_SHIFT |
1257 (div - 1) << CLK_GMAC_125M_DIV_SHIFT);
1258 break;
1259 case CLK_GMAC_50M:
1260 rk_clrsetreg(&cru->clksel_con[84],
1261 CLK_GMAC_50M_DIV_MASK | CLK_GMAC_50M_SEL_MASK,
1262 CLK_GMAC_50M_SEL_CPLL << CLK_GMAC_50M_SEL_SHIFT |
1263 (div - 1) << CLK_GMAC_50M_DIV_SHIFT);
1264 break;
1265 default:
1266 return -ENOENT;
1267 }
1268
1269 return rk3588_gmac_get_clk(priv, clk_id);
1270}
1271
1272static ulong rk3588_uart_get_rate(struct rk3588_clk_priv *priv, ulong clk_id)
1273{
1274 struct rk3588_cru *cru = priv->cru;
1275 u32 reg, con, fracdiv, div, src, p_src, p_rate;
1276 unsigned long m, n;
1277
1278 switch (clk_id) {
1279 case SCLK_UART1:
1280 reg = 41;
1281 break;
1282 case SCLK_UART2:
1283 reg = 43;
1284 break;
1285 case SCLK_UART3:
1286 reg = 45;
1287 break;
1288 case SCLK_UART4:
1289 reg = 47;
1290 break;
1291 case SCLK_UART5:
1292 reg = 49;
1293 break;
1294 case SCLK_UART6:
1295 reg = 51;
1296 break;
1297 case SCLK_UART7:
1298 reg = 53;
1299 break;
1300 case SCLK_UART8:
1301 reg = 55;
1302 break;
1303 case SCLK_UART9:
1304 reg = 57;
1305 break;
1306 default:
1307 return -ENOENT;
1308 }
1309 con = readl(&cru->clksel_con[reg + 2]);
1310 src = (con & CLK_UART_SEL_MASK) >> CLK_UART_SEL_SHIFT;
1311 con = readl(&cru->clksel_con[reg]);
1312 div = (con & CLK_UART_SRC_DIV_MASK) >> CLK_UART_SRC_DIV_SHIFT;
1313 p_src = (con & CLK_UART_SRC_SEL_MASK) >> CLK_UART_SRC_SEL_SHIFT;
1314 if (p_src == CLK_UART_SRC_SEL_GPLL)
1315 p_rate = priv->gpll_hz;
1316 else
1317 p_rate = priv->cpll_hz;
1318
1319 if (src == CLK_UART_SEL_SRC) {
1320 return DIV_TO_RATE(p_rate, div);
1321 } else if (src == CLK_UART_SEL_FRAC) {
1322 fracdiv = readl(&cru->clksel_con[reg + 1]);
1323 n = fracdiv & CLK_UART_FRAC_NUMERATOR_MASK;
1324 n >>= CLK_UART_FRAC_NUMERATOR_SHIFT;
1325 m = fracdiv & CLK_UART_FRAC_DENOMINATOR_MASK;
1326 m >>= CLK_UART_FRAC_DENOMINATOR_SHIFT;
1327 return DIV_TO_RATE(p_rate, div) * n / m;
1328 } else {
1329 return OSC_HZ;
1330 }
1331}
1332
1333static ulong rk3588_uart_set_rate(struct rk3588_clk_priv *priv,
1334 ulong clk_id, ulong rate)
1335{
1336 struct rk3588_cru *cru = priv->cru;
1337 u32 reg, clk_src, uart_src, div;
1338 unsigned long m = 0, n = 0, val;
1339
1340 if (priv->gpll_hz % rate == 0) {
1341 clk_src = CLK_UART_SRC_SEL_GPLL;
1342 uart_src = CLK_UART_SEL_SRC;
1343 div = DIV_ROUND_UP(priv->gpll_hz, rate);
1344 } else if (priv->cpll_hz % rate == 0) {
1345 clk_src = CLK_UART_SRC_SEL_CPLL;
1346 uart_src = CLK_UART_SEL_SRC;
1347 div = DIV_ROUND_UP(priv->gpll_hz, rate);
1348 } else if (rate == OSC_HZ) {
1349 clk_src = CLK_UART_SRC_SEL_GPLL;
1350 uart_src = CLK_UART_SEL_XIN24M;
1351 div = 2;
1352 } else {
1353 clk_src = CLK_UART_SRC_SEL_GPLL;
1354 uart_src = CLK_UART_SEL_FRAC;
1355 div = 2;
1356 rational_best_approximation(rate, priv->gpll_hz / div,
1357 GENMASK(16 - 1, 0),
1358 GENMASK(16 - 1, 0),
1359 &m, &n);
1360 }
1361
1362 switch (clk_id) {
1363 case SCLK_UART1:
1364 reg = 41;
1365 break;
1366 case SCLK_UART2:
1367 reg = 43;
1368 break;
1369 case SCLK_UART3:
1370 reg = 45;
1371 break;
1372 case SCLK_UART4:
1373 reg = 47;
1374 break;
1375 case SCLK_UART5:
1376 reg = 49;
1377 break;
1378 case SCLK_UART6:
1379 reg = 51;
1380 break;
1381 case SCLK_UART7:
1382 reg = 53;
1383 break;
1384 case SCLK_UART8:
1385 reg = 55;
1386 break;
1387 case SCLK_UART9:
1388 reg = 57;
1389 break;
1390 default:
1391 return -ENOENT;
1392 }
1393 rk_clrsetreg(&cru->clksel_con[reg],
1394 CLK_UART_SRC_SEL_MASK |
1395 CLK_UART_SRC_DIV_MASK,
1396 (clk_src << CLK_UART_SRC_SEL_SHIFT) |
1397 ((div - 1) << CLK_UART_SRC_DIV_SHIFT));
1398 rk_clrsetreg(&cru->clksel_con[reg + 2],
1399 CLK_UART_SEL_MASK,
1400 (uart_src << CLK_UART_SEL_SHIFT));
1401 if (m && n) {
1402 val = m << CLK_UART_FRAC_NUMERATOR_SHIFT | n;
1403 writel(val, &cru->clksel_con[reg + 1]);
1404 }
1405
1406 return rk3588_uart_get_rate(priv, clk_id);
1407}
1408
1409static ulong rk3588_pciephy_get_rate(struct rk3588_clk_priv *priv, ulong clk_id)
1410{
1411 struct rk3588_cru *cru = priv->cru;
1412 u32 con, div, src;
1413
1414 switch (clk_id) {
1415 case CLK_REF_PIPE_PHY0:
1416 con = readl(&cru->clksel_con[177]);
1417 src = (con & CLK_PCIE_PHY0_REF_SEL_MASK) >> CLK_PCIE_PHY0_REF_SEL_SHIFT;
1418 con = readl(&cru->clksel_con[176]);
1419 div = (con & CLK_PCIE_PHY0_PLL_DIV_MASK) >> CLK_PCIE_PHY0_PLL_DIV_SHIFT;
1420 break;
1421 case CLK_REF_PIPE_PHY1:
1422 con = readl(&cru->clksel_con[177]);
1423 src = (con & CLK_PCIE_PHY1_REF_SEL_MASK) >> CLK_PCIE_PHY1_REF_SEL_SHIFT;
1424 con = readl(&cru->clksel_con[176]);
1425 div = (con & CLK_PCIE_PHY1_PLL_DIV_MASK) >> CLK_PCIE_PHY1_PLL_DIV_SHIFT;
1426 break;
1427 case CLK_REF_PIPE_PHY2:
1428 con = readl(&cru->clksel_con[177]);
1429 src = (con & CLK_PCIE_PHY2_REF_SEL_MASK) >> CLK_PCIE_PHY2_REF_SEL_SHIFT;
1430 div = (con & CLK_PCIE_PHY2_PLL_DIV_MASK) >> CLK_PCIE_PHY2_PLL_DIV_SHIFT;
1431 break;
1432 default:
1433 return -ENOENT;
1434 }
1435
1436 if (src == CLK_PCIE_PHY_REF_SEL_PPLL)
1437 return DIV_TO_RATE(priv->ppll_hz, div);
1438 else
1439 return OSC_HZ;
1440}
1441
1442static ulong rk3588_pciephy_set_rate(struct rk3588_clk_priv *priv,
1443 ulong clk_id, ulong rate)
1444{
1445 struct rk3588_cru *cru = priv->cru;
1446 u32 clk_src, div;
1447
1448 if (rate == OSC_HZ) {
1449 clk_src = CLK_PCIE_PHY_REF_SEL_24M;
1450 div = 1;
1451 } else {
1452 clk_src = CLK_PCIE_PHY_REF_SEL_PPLL;
1453 div = DIV_ROUND_UP(priv->ppll_hz, rate);
1454 }
1455
1456 switch (clk_id) {
1457 case CLK_REF_PIPE_PHY0:
1458 rk_clrsetreg(&cru->clksel_con[177], CLK_PCIE_PHY0_REF_SEL_MASK,
1459 (clk_src << CLK_PCIE_PHY0_REF_SEL_SHIFT));
1460 rk_clrsetreg(&cru->clksel_con[176], CLK_PCIE_PHY0_PLL_DIV_MASK,
1461 ((div - 1) << CLK_PCIE_PHY0_PLL_DIV_SHIFT));
1462 break;
1463 case CLK_REF_PIPE_PHY1:
1464 rk_clrsetreg(&cru->clksel_con[177], CLK_PCIE_PHY1_REF_SEL_MASK,
1465 (clk_src << CLK_PCIE_PHY1_REF_SEL_SHIFT));
1466 rk_clrsetreg(&cru->clksel_con[176], CLK_PCIE_PHY1_PLL_DIV_MASK,
1467 ((div - 1) << CLK_PCIE_PHY1_PLL_DIV_SHIFT));
1468 break;
1469 case CLK_REF_PIPE_PHY2:
1470 rk_clrsetreg(&cru->clksel_con[177], CLK_PCIE_PHY2_REF_SEL_MASK |
1471 CLK_PCIE_PHY2_PLL_DIV_MASK,
1472 (clk_src << CLK_PCIE_PHY2_REF_SEL_SHIFT) |
1473 ((div - 1) << CLK_PCIE_PHY2_PLL_DIV_SHIFT));
1474 break;
1475 default:
1476 return -ENOENT;
1477 }
1478
1479 return rk3588_pciephy_get_rate(priv, clk_id);
1480}
1481#endif
1482
1483static ulong rk3588_clk_get_rate(struct clk *clk)
1484{
1485 struct rk3588_clk_priv *priv = dev_get_priv(clk->dev);
1486 ulong rate = 0;
1487
1488 if (!priv->gpll_hz) {
1489 printf("%s gpll=%lu\n", __func__, priv->gpll_hz);
1490 return -ENOENT;
1491 }
1492
1493 if (!priv->ppll_hz) {
1494 priv->ppll_hz = rockchip_pll_get_rate(&rk3588_pll_clks[PPLL],
1495 priv->cru, PPLL);
1496 }
1497
1498 switch (clk->id) {
1499 case PLL_LPLL:
1500 rate = rockchip_pll_get_rate(&rk3588_pll_clks[LPLL], priv->cru,
1501 LPLL);
1502 break;
1503 case PLL_B0PLL:
1504 rate = rockchip_pll_get_rate(&rk3588_pll_clks[B0PLL], priv->cru,
1505 B0PLL);
1506 break;
1507 case PLL_B1PLL:
1508 rate = rockchip_pll_get_rate(&rk3588_pll_clks[B1PLL], priv->cru,
1509 B1PLL);
1510 break;
1511 case PLL_GPLL:
1512 rate = rockchip_pll_get_rate(&rk3588_pll_clks[GPLL], priv->cru,
1513 GPLL);
1514 break;
1515 case PLL_CPLL:
1516 rate = rockchip_pll_get_rate(&rk3588_pll_clks[CPLL], priv->cru,
1517 CPLL);
1518 break;
1519 case PLL_NPLL:
1520 rate = rockchip_pll_get_rate(&rk3588_pll_clks[NPLL], priv->cru,
1521 NPLL);
1522 break;
1523 case PLL_V0PLL:
1524 rate = rockchip_pll_get_rate(&rk3588_pll_clks[V0PLL], priv->cru,
1525 V0PLL);
1526 break;
1527 case PLL_AUPLL:
1528 rate = rockchip_pll_get_rate(&rk3588_pll_clks[AUPLL], priv->cru,
1529 AUPLL);
1530 break;
1531 case PLL_PPLL:
1532 rate = rockchip_pll_get_rate(&rk3588_pll_clks[PPLL], priv->cru,
1533 PPLL);
1534 break;
1535 case ACLK_CENTER_ROOT:
1536 case PCLK_CENTER_ROOT:
1537 case HCLK_CENTER_ROOT:
1538 case ACLK_CENTER_LOW_ROOT:
1539 rate = rk3588_center_get_clk(priv, clk->id);
1540 break;
1541 case ACLK_TOP_ROOT:
1542 case PCLK_TOP_ROOT:
1543 case ACLK_LOW_TOP_ROOT:
1544 rate = rk3588_top_get_clk(priv, clk->id);
1545 break;
1546 case CLK_I2C0:
1547 case CLK_I2C1:
1548 case CLK_I2C2:
1549 case CLK_I2C3:
1550 case CLK_I2C4:
1551 case CLK_I2C5:
1552 case CLK_I2C6:
1553 case CLK_I2C7:
1554 case CLK_I2C8:
1555 rate = rk3588_i2c_get_clk(priv, clk->id);
1556 break;
1557 case CLK_SPI0:
1558 case CLK_SPI1:
1559 case CLK_SPI2:
1560 case CLK_SPI3:
1561 case CLK_SPI4:
1562 rate = rk3588_spi_get_clk(priv, clk->id);
1563 break;
1564 case CLK_PWM1:
1565 case CLK_PWM2:
1566 case CLK_PWM3:
1567 case CLK_PMU1PWM:
1568 rate = rk3588_pwm_get_clk(priv, clk->id);
1569 break;
1570 case CLK_SARADC:
1571 case CLK_TSADC:
1572 rate = rk3588_adc_get_clk(priv, clk->id);
1573 break;
1574 case CCLK_SRC_SDIO:
1575 case CCLK_EMMC:
1576 case BCLK_EMMC:
1577 case SCLK_SFC:
1578 case DCLK_DECOM:
1579 rate = rk3588_mmc_get_clk(priv, clk->id);
1580 break;
Jonas Karlman4b6be5a2024-04-22 06:28:39 +00001581 case REF_CLK_USB3OTG0:
1582 case REF_CLK_USB3OTG1:
1583 case REF_CLK_USB3OTG2:
Jonas Karlman291343a2023-04-18 16:46:42 +00001584 case TMCLK_EMMC:
Jagan Teki7d031ee2023-01-30 20:27:36 +05301585 case TCLK_WDT0:
1586 rate = OSC_HZ;
1587 break;
Eugen Hristev3d3f4072023-04-13 14:36:45 +03001588 case PCLK_PMU0_ROOT:
1589 rate = 100000000;
1590 break;
1591 case HCLK_PMU_CM0_ROOT:
1592 rate = 200000000;
1593 break;
1594 case ACLK_BUS_ROOT:
1595 rate = 375000000;
1596 break;
1597 case CLK_150M_SRC:
1598 rate = 150000000;
1599 break;
1600 case CLK_GPU:
1601 rate = 200000000;
1602 break;
Jagan Teki7d031ee2023-01-30 20:27:36 +05301603#ifndef CONFIG_SPL_BUILD
1604 case CLK_AUX16M_0:
1605 case CLK_AUX16M_1:
Jonas Karlman55152232023-03-14 00:38:27 +00001606 rate = rk3588_aux16m_get_clk(priv, clk->id);
Jagan Teki7d031ee2023-01-30 20:27:36 +05301607 break;
1608 case ACLK_VOP_ROOT:
1609 case ACLK_VOP:
1610 case ACLK_VOP_LOW_ROOT:
1611 case HCLK_VOP_ROOT:
1612 rate = rk3588_aclk_vop_get_clk(priv, clk->id);
1613 break;
1614 case DCLK_VOP0:
1615 case DCLK_VOP0_SRC:
1616 case DCLK_VOP1:
1617 case DCLK_VOP1_SRC:
1618 case DCLK_VOP2:
1619 case DCLK_VOP2_SRC:
1620 case DCLK_VOP3:
1621 rate = rk3588_dclk_vop_get_clk(priv, clk->id);
1622 break;
1623 case CLK_GMAC0_PTP_REF:
1624 case CLK_GMAC1_PTP_REF:
1625 case CLK_GMAC_125M:
1626 case CLK_GMAC_50M:
1627 rate = rk3588_gmac_get_clk(priv, clk->id);
1628 break;
1629 case SCLK_UART1:
1630 case SCLK_UART2:
1631 case SCLK_UART3:
1632 case SCLK_UART4:
1633 case SCLK_UART5:
1634 case SCLK_UART6:
1635 case SCLK_UART7:
1636 case SCLK_UART8:
1637 case SCLK_UART9:
1638 rate = rk3588_uart_get_rate(priv, clk->id);
1639 break;
1640 case CLK_REF_PIPE_PHY0:
1641 case CLK_REF_PIPE_PHY1:
1642 case CLK_REF_PIPE_PHY2:
1643 rate = rk3588_pciephy_get_rate(priv, clk->id);
1644 break;
1645#endif
1646 default:
1647 return -ENOENT;
1648 }
1649
1650 return rate;
1651};
1652
1653static ulong rk3588_clk_set_rate(struct clk *clk, ulong rate)
1654{
1655 struct rk3588_clk_priv *priv = dev_get_priv(clk->dev);
1656 ulong ret = 0;
1657
1658 if (!priv->gpll_hz) {
1659 printf("%s gpll=%lu\n", __func__, priv->gpll_hz);
1660 return -ENOENT;
1661 }
1662
1663 if (!priv->ppll_hz) {
1664 priv->ppll_hz = rockchip_pll_get_rate(&rk3588_pll_clks[PPLL],
1665 priv->cru, PPLL);
1666 }
1667
1668 switch (clk->id) {
1669 case PLL_CPLL:
1670 ret = rockchip_pll_set_rate(&rk3588_pll_clks[CPLL], priv->cru,
1671 CPLL, rate);
1672 priv->cpll_hz = rockchip_pll_get_rate(&rk3588_pll_clks[CPLL],
1673 priv->cru, CPLL);
1674 break;
1675 case PLL_GPLL:
1676 ret = rockchip_pll_set_rate(&rk3588_pll_clks[GPLL], priv->cru,
1677 GPLL, rate);
1678 priv->gpll_hz = rockchip_pll_get_rate(&rk3588_pll_clks[GPLL],
1679 priv->cru, GPLL);
1680 break;
1681 case PLL_NPLL:
1682 ret = rockchip_pll_set_rate(&rk3588_pll_clks[NPLL], priv->cru,
1683 NPLL, rate);
1684 break;
1685 case PLL_V0PLL:
1686 ret = rockchip_pll_set_rate(&rk3588_pll_clks[V0PLL], priv->cru,
1687 V0PLL, rate);
1688 priv->v0pll_hz = rockchip_pll_get_rate(&rk3588_pll_clks[V0PLL],
1689 priv->cru, V0PLL);
1690 break;
1691 case PLL_AUPLL:
1692 ret = rockchip_pll_set_rate(&rk3588_pll_clks[AUPLL], priv->cru,
1693 AUPLL, rate);
1694 priv->aupll_hz = rockchip_pll_get_rate(&rk3588_pll_clks[AUPLL],
1695 priv->cru, AUPLL);
1696 break;
1697 case PLL_PPLL:
1698 ret = rockchip_pll_set_rate(&rk3588_pll_clks[PPLL], priv->cru,
1699 PPLL, rate);
1700 priv->ppll_hz = rockchip_pll_get_rate(&rk3588_pll_clks[PPLL],
1701 priv->cru, PPLL);
1702 break;
1703 case ACLK_CENTER_ROOT:
1704 case PCLK_CENTER_ROOT:
1705 case HCLK_CENTER_ROOT:
1706 case ACLK_CENTER_LOW_ROOT:
1707 ret = rk3588_center_set_clk(priv, clk->id, rate);
1708 break;
1709 case ACLK_TOP_ROOT:
1710 case PCLK_TOP_ROOT:
1711 case ACLK_LOW_TOP_ROOT:
1712 ret = rk3588_top_set_clk(priv, clk->id, rate);
1713 break;
1714 case CLK_I2C0:
1715 case CLK_I2C1:
1716 case CLK_I2C2:
1717 case CLK_I2C3:
1718 case CLK_I2C4:
1719 case CLK_I2C5:
1720 case CLK_I2C6:
1721 case CLK_I2C7:
1722 case CLK_I2C8:
1723 ret = rk3588_i2c_set_clk(priv, clk->id, rate);
1724 break;
1725 case CLK_SPI0:
1726 case CLK_SPI1:
1727 case CLK_SPI2:
1728 case CLK_SPI3:
1729 case CLK_SPI4:
1730 ret = rk3588_spi_set_clk(priv, clk->id, rate);
1731 break;
1732 case CLK_PWM1:
1733 case CLK_PWM2:
1734 case CLK_PWM3:
1735 case CLK_PMU1PWM:
1736 ret = rk3588_pwm_set_clk(priv, clk->id, rate);
1737 break;
1738 case CLK_SARADC:
1739 case CLK_TSADC:
1740 ret = rk3588_adc_set_clk(priv, clk->id, rate);
1741 break;
1742 case CCLK_SRC_SDIO:
1743 case CCLK_EMMC:
1744 case BCLK_EMMC:
1745 case SCLK_SFC:
1746 case DCLK_DECOM:
1747 ret = rk3588_mmc_set_clk(priv, clk->id, rate);
1748 break;
Jonas Karlman4b6be5a2024-04-22 06:28:39 +00001749 case REF_CLK_USB3OTG0:
1750 case REF_CLK_USB3OTG1:
1751 case REF_CLK_USB3OTG2:
Jonas Karlman291343a2023-04-18 16:46:42 +00001752 case TMCLK_EMMC:
Jagan Teki7d031ee2023-01-30 20:27:36 +05301753 case TCLK_WDT0:
1754 ret = OSC_HZ;
1755 break;
Eugen Hristev3d3f4072023-04-13 14:36:45 +03001756 case PCLK_PMU0_ROOT:
1757 case CLK_GPU:
1758 case HCLK_PMU_CM0_ROOT:
1759 case ACLK_BUS_ROOT:
1760 case CLK_150M_SRC:
1761 ret = 0;
1762 break;
Jagan Teki7d031ee2023-01-30 20:27:36 +05301763#ifndef CONFIG_SPL_BUILD
1764 case CLK_AUX16M_0:
1765 case CLK_AUX16M_1:
Jonas Karlman55152232023-03-14 00:38:27 +00001766 ret = rk3588_aux16m_set_clk(priv, clk->id, rate);
Jagan Teki7d031ee2023-01-30 20:27:36 +05301767 break;
1768 case ACLK_VOP_ROOT:
1769 case ACLK_VOP:
1770 case ACLK_VOP_LOW_ROOT:
1771 case HCLK_VOP_ROOT:
1772 ret = rk3588_aclk_vop_set_clk(priv, clk->id, rate);
1773 break;
1774 case DCLK_VOP0:
1775 case DCLK_VOP0_SRC:
1776 case DCLK_VOP1:
1777 case DCLK_VOP1_SRC:
1778 case DCLK_VOP2:
1779 case DCLK_VOP2_SRC:
1780 case DCLK_VOP3:
1781 ret = rk3588_dclk_vop_set_clk(priv, clk->id, rate);
1782 break;
1783 case CLK_GMAC0_PTP_REF:
1784 case CLK_GMAC1_PTP_REF:
1785 case CLK_GMAC_125M:
1786 case CLK_GMAC_50M:
1787 ret = rk3588_gmac_set_clk(priv, clk->id, rate);
1788 break;
1789 case SCLK_UART1:
1790 case SCLK_UART2:
1791 case SCLK_UART3:
1792 case SCLK_UART4:
1793 case SCLK_UART5:
1794 case SCLK_UART6:
1795 case SCLK_UART7:
1796 case SCLK_UART8:
1797 case SCLK_UART9:
1798 ret = rk3588_uart_set_rate(priv, clk->id, rate);
1799 break;
1800 case CLK_REF_PIPE_PHY0:
1801 case CLK_REF_PIPE_PHY1:
1802 case CLK_REF_PIPE_PHY2:
1803 ret = rk3588_pciephy_set_rate(priv, clk->id, rate);
1804 break;
1805#endif
1806 default:
1807 return -ENOENT;
1808 }
1809
1810 return ret;
1811};
1812
1813#define ROCKCHIP_MMC_DELAY_SEL BIT(10)
1814#define ROCKCHIP_MMC_DEGREE_MASK 0x3
1815#define ROCKCHIP_MMC_DELAYNUM_OFFSET 2
1816#define ROCKCHIP_MMC_DELAYNUM_MASK (0xff << ROCKCHIP_MMC_DELAYNUM_OFFSET)
1817
1818#define PSECS_PER_SEC 1000000000000LL
1819/*
1820 * Each fine delay is between 44ps-77ps. Assume each fine delay is 60ps to
1821 * simplify calculations. So 45degs could be anywhere between 33deg and 57.8deg.
1822 */
1823#define ROCKCHIP_MMC_DELAY_ELEMENT_PSEC 60
1824
1825#if (IS_ENABLED(OF_CONTROL)) || (!IS_ENABLED(OF_PLATDATA))
1826static int __maybe_unused rk3588_dclk_vop_set_parent(struct clk *clk,
1827 struct clk *parent)
1828{
1829 struct rk3588_clk_priv *priv = dev_get_priv(clk->dev);
1830 struct rk3588_cru *cru = priv->cru;
1831 u32 sel;
1832 const char *clock_dev_name = parent->dev->name;
1833
1834 if (parent->id == PLL_V0PLL)
1835 sel = 2;
1836 else if (parent->id == PLL_GPLL)
1837 sel = 0;
1838 else if (parent->id == PLL_CPLL)
1839 sel = 1;
1840 else
1841 sel = 3;
1842
1843 switch (clk->id) {
1844 case DCLK_VOP0_SRC:
1845 rk_clrsetreg(&cru->clksel_con[111], DCLK0_VOP_SRC_SEL_MASK,
1846 sel << DCLK0_VOP_SRC_SEL_SHIFT);
1847 break;
1848 case DCLK_VOP1_SRC:
1849 rk_clrsetreg(&cru->clksel_con[111], DCLK1_VOP_SRC_SEL_MASK,
1850 sel << DCLK1_VOP_SRC_SEL_SHIFT);
1851 break;
1852 case DCLK_VOP2_SRC:
1853 rk_clrsetreg(&cru->clksel_con[112], DCLK2_VOP_SRC_SEL_MASK,
1854 sel << DCLK2_VOP_SRC_SEL_SHIFT);
1855 break;
1856 case DCLK_VOP3:
1857 rk_clrsetreg(&cru->clksel_con[113], DCLK3_VOP_SRC_SEL_MASK,
1858 sel << DCLK3_VOP_SRC_SEL_SHIFT);
1859 break;
1860 case DCLK_VOP0:
1861 if (!strcmp(clock_dev_name, "hdmiphypll_clk0"))
1862 sel = 1;
1863 else if (!strcmp(clock_dev_name, "hdmiphypll_clk1"))
1864 sel = 2;
1865 else
1866 sel = 0;
1867 rk_clrsetreg(&cru->clksel_con[112], DCLK0_VOP_SEL_MASK,
1868 sel << DCLK0_VOP_SEL_SHIFT);
1869 break;
1870 case DCLK_VOP1:
1871 if (!strcmp(clock_dev_name, "hdmiphypll_clk0"))
1872 sel = 1;
1873 else if (!strcmp(clock_dev_name, "hdmiphypll_clk1"))
1874 sel = 2;
1875 else
1876 sel = 0;
1877 rk_clrsetreg(&cru->clksel_con[112], DCLK1_VOP_SEL_MASK,
1878 sel << DCLK1_VOP_SEL_SHIFT);
1879 break;
1880 case DCLK_VOP2:
1881 if (!strcmp(clock_dev_name, "hdmiphypll_clk0"))
1882 sel = 1;
1883 else if (!strcmp(clock_dev_name, "hdmiphypll_clk1"))
1884 sel = 2;
1885 else
1886 sel = 0;
1887 rk_clrsetreg(&cru->clksel_con[112], DCLK2_VOP_SEL_MASK,
1888 sel << DCLK2_VOP_SEL_SHIFT);
1889 break;
1890 default:
1891 return -EINVAL;
1892 }
1893 return 0;
1894}
1895
1896static int rk3588_clk_set_parent(struct clk *clk, struct clk *parent)
1897{
1898 switch (clk->id) {
1899 case DCLK_VOP0_SRC:
1900 case DCLK_VOP1_SRC:
1901 case DCLK_VOP2_SRC:
1902 case DCLK_VOP0:
1903 case DCLK_VOP1:
1904 case DCLK_VOP2:
1905 case DCLK_VOP3:
1906 return rk3588_dclk_vop_set_parent(clk, parent);
1907 default:
1908 return -ENOENT;
1909 }
1910
1911 return 0;
1912}
1913#endif
1914
1915static struct clk_ops rk3588_clk_ops = {
1916 .get_rate = rk3588_clk_get_rate,
1917 .set_rate = rk3588_clk_set_rate,
1918#if (IS_ENABLED(OF_CONTROL)) || (!IS_ENABLED(OF_PLATDATA))
1919 .set_parent = rk3588_clk_set_parent,
1920#endif
1921};
1922
1923static void rk3588_clk_init(struct rk3588_clk_priv *priv)
1924{
1925 int ret, div;
1926
1927 div = DIV_ROUND_UP(GPLL_HZ, 300 * MHz);
1928 rk_clrsetreg(&priv->cru->clksel_con[38],
1929 ACLK_BUS_ROOT_SEL_MASK |
1930 ACLK_BUS_ROOT_DIV_MASK,
1931 div << ACLK_BUS_ROOT_DIV_SHIFT);
1932
1933 if (priv->cpll_hz != CPLL_HZ) {
1934 ret = rockchip_pll_set_rate(&rk3588_pll_clks[CPLL], priv->cru,
1935 CPLL, CPLL_HZ);
1936 if (!ret)
1937 priv->cpll_hz = CPLL_HZ;
1938 }
1939 if (priv->gpll_hz != GPLL_HZ) {
1940 ret = rockchip_pll_set_rate(&rk3588_pll_clks[GPLL], priv->cru,
1941 GPLL, GPLL_HZ);
1942 if (!ret)
1943 priv->gpll_hz = GPLL_HZ;
1944 }
1945
1946#ifdef CONFIG_PCI
1947 if (priv->ppll_hz != PPLL_HZ) {
1948 ret = rockchip_pll_set_rate(&rk3588_pll_clks[PPLL], priv->cru,
1949 PPLL, PPLL_HZ);
1950 priv->ppll_hz = rockchip_pll_get_rate(&rk3588_pll_clks[PPLL],
1951 priv->cru, PPLL);
1952 }
1953#endif
1954 rk_clrsetreg(&priv->cru->clksel_con[9],
1955 ACLK_TOP_S400_SEL_MASK |
1956 ACLK_TOP_S200_SEL_MASK,
1957 (ACLK_TOP_S400_SEL_400M << ACLK_TOP_S400_SEL_SHIFT) |
1958 (ACLK_TOP_S200_SEL_200M << ACLK_TOP_S200_SEL_SHIFT));
1959}
1960
1961static int rk3588_clk_probe(struct udevice *dev)
1962{
1963 struct rk3588_clk_priv *priv = dev_get_priv(dev);
1964 int ret;
1965
1966 priv->sync_kernel = false;
1967
1968#ifdef CONFIG_SPL_BUILD
1969 rockchip_pll_set_rate(&rk3588_pll_clks[B0PLL], priv->cru,
1970 B0PLL, LPLL_HZ);
1971 rockchip_pll_set_rate(&rk3588_pll_clks[B1PLL], priv->cru,
1972 B1PLL, LPLL_HZ);
1973 if (!priv->armclk_enter_hz) {
1974 ret = rockchip_pll_set_rate(&rk3588_pll_clks[LPLL], priv->cru,
1975 LPLL, LPLL_HZ);
1976 priv->armclk_enter_hz =
1977 rockchip_pll_get_rate(&rk3588_pll_clks[LPLL],
1978 priv->cru, LPLL);
1979 priv->armclk_init_hz = priv->armclk_enter_hz;
1980 }
1981#endif
1982
1983 priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
1984 if (IS_ERR(priv->grf))
1985 return PTR_ERR(priv->grf);
1986
1987 rk3588_clk_init(priv);
1988
1989 /* Process 'assigned-{clocks/clock-parents/clock-rates}' properties */
1990 ret = clk_set_defaults(dev, 1);
1991 if (ret)
1992 debug("%s clk_set_defaults failed %d\n", __func__, ret);
1993 else
1994 priv->sync_kernel = true;
1995
1996 return 0;
1997}
1998
1999static int rk3588_clk_ofdata_to_platdata(struct udevice *dev)
2000{
2001 struct rk3588_clk_priv *priv = dev_get_priv(dev);
2002
2003 priv->cru = dev_read_addr_ptr(dev);
2004
2005 return 0;
2006}
2007
2008static int rk3588_clk_bind(struct udevice *dev)
2009{
2010 int ret;
2011 struct udevice *sys_child;
2012 struct sysreset_reg *priv;
2013
2014 /* The reset driver does not have a device node, so bind it here */
2015 ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset",
2016 &sys_child);
2017 if (ret) {
2018 debug("Warning: No sysreset driver: ret=%d\n", ret);
2019 } else {
2020 priv = malloc(sizeof(struct sysreset_reg));
2021 priv->glb_srst_fst_value = offsetof(struct rk3588_cru,
2022 glb_srst_fst);
2023 priv->glb_srst_snd_value = offsetof(struct rk3588_cru,
2024 glb_srsr_snd);
2025 dev_set_priv(sys_child, priv);
2026 }
2027
2028#if CONFIG_IS_ENABLED(RESET_ROCKCHIP)
2029 ret = offsetof(struct rk3588_cru, softrst_con[0]);
Eugen Hristev2f550822023-05-15 13:55:04 +03002030 ret = rk3588_reset_bind_lut(dev, ret, 49158);
Jagan Teki7d031ee2023-01-30 20:27:36 +05302031 if (ret)
Eugen Hristevf1798262023-04-11 10:17:56 +03002032 debug("Warning: software reset driver bind failed\n");
Jagan Teki7d031ee2023-01-30 20:27:36 +05302033#endif
2034
2035 return 0;
2036}
2037
2038static const struct udevice_id rk3588_clk_ids[] = {
2039 { .compatible = "rockchip,rk3588-cru" },
2040 { }
2041};
2042
2043U_BOOT_DRIVER(rockchip_rk3588_cru) = {
2044 .name = "rockchip_rk3588_cru",
2045 .id = UCLASS_CLK,
2046 .of_match = rk3588_clk_ids,
2047 .priv_auto = sizeof(struct rk3588_clk_priv),
2048 .of_to_plat = rk3588_clk_ofdata_to_platdata,
2049 .ops = &rk3588_clk_ops,
2050 .bind = rk3588_clk_bind,
2051 .probe = rk3588_clk_probe,
2052};
Jonas Karlmanb4505902023-04-17 19:07:20 +00002053
2054#ifdef CONFIG_SPL_BUILD
2055#define SCRU_BASE 0xfd7d0000
Heiko Stuebner166a0472024-05-22 19:31:29 +02002056#define SBUSCRU_BASE 0xfd7d8000
Jonas Karlmanb4505902023-04-17 19:07:20 +00002057
2058static ulong rk3588_scru_clk_get_rate(struct clk *clk)
2059{
2060 u32 con, div, sel, parent;
2061
2062 switch (clk->id) {
2063 case SCMI_CCLK_SD:
2064 con = readl(SCRU_BASE + RK3588_CLKSEL_CON(3));
2065 sel = (con & SCMI_CCLK_SD_SEL_MASK) >> SCMI_CCLK_SD_SEL_SHIFT;
2066 div = (con & SCMI_CCLK_SD_DIV_MASK) >> SCMI_CCLK_SD_DIV_SHIFT;
2067 if (sel == SCMI_CCLK_SD_SEL_GPLL)
2068 parent = GPLL_HZ;
2069 else if (sel == SCMI_CCLK_SD_SEL_SPLL)
2070 parent = SPLL_HZ;
2071 else
2072 parent = OSC_HZ;
2073 return DIV_TO_RATE(parent, div);
2074 case SCMI_HCLK_SD:
2075 con = readl(SCRU_BASE + RK3588_CLKSEL_CON(1));
2076 sel = (con & SCMI_HCLK_SD_SEL_MASK) >> SCMI_HCLK_SD_SEL_SHIFT;
2077 if (sel == SCMI_HCLK_SD_SEL_150M)
2078 return 150 * MHz;
2079 else if (sel == SCMI_HCLK_SD_SEL_100M)
2080 return 100 * MHz;
2081 else if (sel == SCMI_HCLK_SD_SEL_50M)
2082 return 50 * MHz;
2083 else
2084 return OSC_HZ;
2085 default:
2086 return -ENOENT;
2087 }
2088}
2089
2090static ulong rk3588_scru_clk_set_rate(struct clk *clk, ulong rate)
2091{
2092 u32 div, sel;
2093
2094 switch (clk->id) {
2095 case SCMI_CCLK_SD:
2096 if ((OSC_HZ % rate) == 0) {
2097 sel = SCMI_CCLK_SD_SEL_24M;
2098 div = DIV_ROUND_UP(OSC_HZ, rate);
2099 } else if ((SPLL_HZ % rate) == 0) {
2100 sel = SCMI_CCLK_SD_SEL_SPLL;
2101 div = DIV_ROUND_UP(SPLL_HZ, rate);
2102 } else {
2103 sel = SCMI_CCLK_SD_SEL_GPLL;
2104 div = DIV_ROUND_UP(GPLL_HZ, rate);
2105 }
2106 rk_clrsetreg(SCRU_BASE + RK3588_CLKSEL_CON(3),
2107 SCMI_CCLK_SD_SEL_MASK | SCMI_CCLK_SD_DIV_MASK,
2108 sel << SCMI_CCLK_SD_SEL_SHIFT |
2109 (div - 1) << SCMI_CCLK_SD_DIV_SHIFT);
2110 break;
2111 case SCMI_HCLK_SD:
2112 if (rate >= 150 * MHz)
2113 sel = SCMI_HCLK_SD_SEL_150M;
2114 else if (rate >= 100 * MHz)
2115 sel = SCMI_HCLK_SD_SEL_100M;
2116 else if (rate >= 50 * MHz)
2117 sel = SCMI_HCLK_SD_SEL_50M;
2118 else
2119 sel = SCMI_HCLK_SD_SEL_24M;
2120 rk_clrsetreg(SCRU_BASE + RK3588_CLKSEL_CON(1),
2121 SCMI_HCLK_SD_SEL_MASK,
2122 sel << SCMI_HCLK_SD_SEL_SHIFT);
2123 break;
2124 default:
2125 return -ENOENT;
2126 }
2127
2128 return rk3588_scru_clk_get_rate(clk);
2129}
2130
Heiko Stuebner166a0472024-05-22 19:31:29 +02002131static int rk3588_scru_clk_probe(struct udevice *dev)
2132{
2133 int ret;
2134
2135 ret = rockchip_pll_set_rate(&rk3588_pll_clks[SPLL],
2136 (void *)SBUSCRU_BASE, SPLL, SPLL_HZ);
2137 if (ret)
2138 debug("%s setting spll rate failed %d\n", __func__, ret);
2139
2140 return 0;
2141}
2142
Jonas Karlmanb4505902023-04-17 19:07:20 +00002143static const struct clk_ops rk3588_scru_clk_ops = {
2144 .get_rate = rk3588_scru_clk_get_rate,
2145 .set_rate = rk3588_scru_clk_set_rate,
2146};
2147
2148U_BOOT_DRIVER(rockchip_rk3588_scru) = {
Heiko Stuebner166a0472024-05-22 19:31:29 +02002149 .name = "rockchip_rk3588_scru",
2150 .id = UCLASS_CLK,
2151 .ops = &rk3588_scru_clk_ops,
2152 .probe = rk3588_scru_clk_probe,
Jonas Karlmanb4505902023-04-17 19:07:20 +00002153};
2154
2155static int rk3588_scmi_spl_glue_bind(struct udevice *dev)
2156{
2157 ofnode node;
2158 u32 protocol_id;
2159 const char *name;
2160
2161 dev_for_each_subnode(node, dev) {
2162 if (!ofnode_is_enabled(node))
2163 continue;
2164
2165 if (ofnode_read_u32(node, "reg", &protocol_id))
2166 continue;
2167
2168 if (protocol_id != SCMI_PROTOCOL_ID_CLOCK)
2169 continue;
2170
2171 name = ofnode_get_name(node);
2172 return device_bind_driver_to_node(dev, "rockchip_rk3588_scru",
2173 name, node, NULL);
2174 }
2175
2176 return -ENOENT;
2177}
2178
2179static const struct udevice_id rk3588_scmi_spl_glue_ids[] = {
2180 { .compatible = "arm,scmi-smc" },
2181 { }
2182};
2183
2184U_BOOT_DRIVER(rk3588_scmi_spl_glue) = {
2185 .name = "rk3588_scmi_spl_glue",
2186 .id = UCLASS_NOP,
2187 .of_match = rk3588_scmi_spl_glue_ids,
2188 .bind = rk3588_scmi_spl_glue_bind,
2189};
2190#endif