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