blob: c46b58e31626e34569423fb3afe454d908636605 [file] [log] [blame]
Finley Xiaoafa71602019-11-14 11:21:13 +08001// SPDX-License-Identifier: GPL-2.0
2/*
3 * (C) Copyright 2017-2019 Rockchip Electronics Co., Ltd
4 */
5#include <common.h>
6#include <bitfield.h>
7#include <clk-uclass.h>
8#include <dm.h>
9#include <div64.h>
10#include <errno.h>
Simon Glass0f2af882020-05-10 11:40:05 -060011#include <log.h>
Simon Glass9bc15642020-02-03 07:36:16 -070012#include <malloc.h>
Finley Xiaoafa71602019-11-14 11:21:13 +080013#include <syscon.h>
Simon Glass3ba929a2020-10-30 21:38:53 -060014#include <asm/global_data.h>
Finley Xiaoafa71602019-11-14 11:21:13 +080015#include <asm/arch/cru_rk3308.h>
16#include <asm/arch-rockchip/clock.h>
17#include <asm/arch-rockchip/hardware.h>
Simon Glass95588622020-12-22 19:30:28 -070018#include <dm/device-internal.h>
Finley Xiaoafa71602019-11-14 11:21:13 +080019#include <dm/lists.h>
20#include <dt-bindings/clock/rk3308-cru.h>
Simon Glass4dcacfc2020-05-10 11:40:13 -060021#include <linux/bitops.h>
Finley Xiaoafa71602019-11-14 11:21:13 +080022
23DECLARE_GLOBAL_DATA_PTR;
24
25enum {
26 VCO_MAX_HZ = 3200U * 1000000,
27 VCO_MIN_HZ = 800 * 1000000,
28 OUTPUT_MAX_HZ = 3200U * 1000000,
29 OUTPUT_MIN_HZ = 24 * 1000000,
30};
31
32#define DIV_TO_RATE(input_rate, div) ((input_rate) / ((div) + 1))
33
34#define RK3308_CPUCLK_RATE(_rate, _aclk_div, _pclk_div) \
35{ \
36 .rate = _rate##U, \
37 .aclk_div = _aclk_div, \
38 .pclk_div = _pclk_div, \
39}
40
41static struct rockchip_pll_rate_table rk3308_pll_rates[] = {
42 /* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */
43 RK3036_PLL_RATE(1300000000, 6, 325, 1, 1, 1, 0),
44 RK3036_PLL_RATE(1200000000, 1, 50, 1, 1, 1, 0),
45 RK3036_PLL_RATE(816000000, 1, 68, 2, 1, 1, 0),
46 RK3036_PLL_RATE(748000000, 2, 187, 3, 1, 1, 0),
47};
48
49static struct rockchip_cpu_rate_table rk3308_cpu_rates[] = {
50 RK3308_CPUCLK_RATE(1200000000, 1, 5),
51 RK3308_CPUCLK_RATE(1008000000, 1, 5),
52 RK3308_CPUCLK_RATE(816000000, 1, 3),
53 RK3308_CPUCLK_RATE(600000000, 1, 3),
54 RK3308_CPUCLK_RATE(408000000, 1, 1),
55};
56
57static struct rockchip_pll_clock rk3308_pll_clks[] = {
58 [APLL] = PLL(pll_rk3328, PLL_APLL, RK3308_PLL_CON(0),
59 RK3308_MODE_CON, 0, 10, 0, rk3308_pll_rates),
60 [DPLL] = PLL(pll_rk3328, PLL_DPLL, RK3308_PLL_CON(8),
61 RK3308_MODE_CON, 2, 10, 0, NULL),
62 [VPLL0] = PLL(pll_rk3328, PLL_VPLL0, RK3308_PLL_CON(16),
63 RK3308_MODE_CON, 4, 10, 0, NULL),
64 [VPLL1] = PLL(pll_rk3328, PLL_VPLL1, RK3308_PLL_CON(24),
65 RK3308_MODE_CON, 6, 10, 0, NULL),
66};
67
Finley Xiao37241492024-04-08 18:14:04 +000068/*
69 *
70 * rational_best_approximation(31415, 10000,
71 * (1 << 8) - 1, (1 << 5) - 1, &n, &d);
72 *
73 * you may look at given_numerator as a fixed point number,
74 * with the fractional part size described in given_denominator.
75 *
76 * for theoretical background, see:
77 * http://en.wikipedia.org/wiki/Continued_fraction
78 */
79static void rational_best_approximation(unsigned long given_numerator,
80 unsigned long given_denominator,
81 unsigned long max_numerator,
82 unsigned long max_denominator,
83 unsigned long *best_numerator,
84 unsigned long *best_denominator)
85{
86 unsigned long n, d, n0, d0, n1, d1;
87
88 n = given_numerator;
89 d = given_denominator;
90 n0 = 0;
91 d1 = 0;
92 n1 = 1;
93 d0 = 1;
94 for (;;) {
95 unsigned long t, a;
96
97 if (n1 > max_numerator || d1 > max_denominator) {
98 n1 = n0;
99 d1 = d0;
100 break;
101 }
102 if (d == 0)
103 break;
104 t = d;
105 a = n / d;
106 d = n % d;
107 n = t;
108 t = n0 + a * n1;
109 n0 = n1;
110 n1 = t;
111 t = d0 + a * d1;
112 d0 = d1;
113 d1 = t;
114 }
115 *best_numerator = n1;
116 *best_denominator = d1;
117}
118
Finley Xiaoafa71602019-11-14 11:21:13 +0800119static ulong rk3308_armclk_set_clk(struct rk3308_clk_priv *priv, ulong hz)
120{
121 struct rk3308_cru *cru = priv->cru;
122 const struct rockchip_cpu_rate_table *rate;
123 ulong old_rate;
124
125 rate = rockchip_get_cpu_settings(rk3308_cpu_rates, hz);
126 if (!rate) {
127 printf("%s unsupport rate\n", __func__);
128 return -EINVAL;
129 }
130
131 /*
132 * select apll as cpu/core clock pll source and
133 * set up dependent divisors for PERI and ACLK clocks.
134 * core hz : apll = 1:1
135 */
136 old_rate = rockchip_pll_get_rate(&rk3308_pll_clks[APLL],
137 priv->cru, APLL);
138 if (old_rate > hz) {
139 if (rockchip_pll_set_rate(&rk3308_pll_clks[APLL],
140 priv->cru, APLL, hz))
141 return -EINVAL;
142 rk_clrsetreg(&cru->clksel_con[0],
143 CORE_CLK_PLL_SEL_MASK | CORE_DIV_CON_MASK |
144 CORE_ACLK_DIV_MASK | CORE_DBG_DIV_MASK,
145 rate->aclk_div << CORE_ACLK_DIV_SHIFT |
146 rate->pclk_div << CORE_DBG_DIV_SHIFT |
147 CORE_CLK_PLL_SEL_APLL << CORE_CLK_PLL_SEL_SHIFT |
148 0 << CORE_DIV_CON_SHIFT);
149 } else if (old_rate < hz) {
150 rk_clrsetreg(&cru->clksel_con[0],
151 CORE_CLK_PLL_SEL_MASK | CORE_DIV_CON_MASK |
152 CORE_ACLK_DIV_MASK | CORE_DBG_DIV_MASK,
153 rate->aclk_div << CORE_ACLK_DIV_SHIFT |
154 rate->pclk_div << CORE_DBG_DIV_SHIFT |
155 CORE_CLK_PLL_SEL_APLL << CORE_CLK_PLL_SEL_SHIFT |
156 0 << CORE_DIV_CON_SHIFT);
157 if (rockchip_pll_set_rate(&rk3308_pll_clks[APLL],
158 priv->cru, APLL, hz))
159 return -EINVAL;
160 }
161
162 return rockchip_pll_get_rate(&rk3308_pll_clks[APLL], priv->cru, APLL);
163}
164
165static void rk3308_clk_get_pll_rate(struct rk3308_clk_priv *priv)
166{
167 if (!priv->dpll_hz)
168 priv->dpll_hz = rockchip_pll_get_rate(&rk3308_pll_clks[DPLL],
169 priv->cru, DPLL);
170 if (!priv->vpll0_hz)
171 priv->vpll0_hz = rockchip_pll_get_rate(&rk3308_pll_clks[VPLL0],
172 priv->cru, VPLL0);
173 if (!priv->vpll1_hz)
174 priv->vpll1_hz = rockchip_pll_get_rate(&rk3308_pll_clks[VPLL1],
175 priv->cru, VPLL1);
176}
177
178static ulong rk3308_i2c_get_clk(struct clk *clk)
179{
180 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
181 struct rk3308_cru *cru = priv->cru;
182 u32 div, con, con_id;
183
184 switch (clk->id) {
185 case SCLK_I2C0:
186 con_id = 25;
187 break;
188 case SCLK_I2C1:
189 con_id = 26;
190 break;
191 case SCLK_I2C2:
192 con_id = 27;
193 break;
194 case SCLK_I2C3:
195 con_id = 28;
196 break;
197 default:
198 printf("do not support this i2c bus\n");
199 return -EINVAL;
200 }
201
202 con = readl(&cru->clksel_con[con_id]);
Massimo Pegorer00a8fa32023-08-03 13:08:11 +0200203 div = (con & CLK_I2C_DIV_CON_MASK) >> CLK_I2C_DIV_CON_SHIFT;
Finley Xiaoafa71602019-11-14 11:21:13 +0800204
205 return DIV_TO_RATE(priv->dpll_hz, div);
206}
207
208static ulong rk3308_i2c_set_clk(struct clk *clk, uint hz)
209{
210 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
211 struct rk3308_cru *cru = priv->cru;
212 u32 src_clk_div, con_id;
213
214 src_clk_div = DIV_ROUND_UP(priv->dpll_hz, hz);
215 assert(src_clk_div - 1 <= 127);
216
217 switch (clk->id) {
218 case SCLK_I2C0:
219 con_id = 25;
220 break;
221 case SCLK_I2C1:
222 con_id = 26;
223 break;
224 case SCLK_I2C2:
225 con_id = 27;
226 break;
227 case SCLK_I2C3:
228 con_id = 28;
229 break;
230 default:
231 printf("do not support this i2c bus\n");
232 return -EINVAL;
233 }
234 rk_clrsetreg(&cru->clksel_con[con_id],
235 CLK_I2C_PLL_SEL_MASK | CLK_I2C_DIV_CON_MASK,
236 CLK_I2C_PLL_SEL_DPLL << CLK_I2C_PLL_SEL_SHIFT |
237 (src_clk_div - 1) << CLK_I2C_DIV_CON_SHIFT);
238
239 return rk3308_i2c_get_clk(clk);
240}
241
242static ulong rk3308_mac_set_clk(struct clk *clk, uint hz)
243{
244 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
245 struct rk3308_cru *cru = priv->cru;
246 u32 con = readl(&cru->clksel_con[43]);
247 ulong pll_rate;
248 u8 div;
249
250 if ((con >> MAC_PLL_SHIFT) & MAC_SEL_VPLL0)
251 pll_rate = rockchip_pll_get_rate(&rk3308_pll_clks[VPLL0],
252 priv->cru, VPLL0);
253 else if ((con >> MAC_PLL_SHIFT) & MAC_SEL_VPLL1)
254 pll_rate = rockchip_pll_get_rate(&rk3308_pll_clks[VPLL1],
255 priv->cru, VPLL1);
256 else
257 pll_rate = rockchip_pll_get_rate(&rk3308_pll_clks[DPLL],
258 priv->cru, DPLL);
259
260 /*default set 50MHZ for gmac*/
261 if (!hz)
262 hz = 50000000;
263
264 div = DIV_ROUND_UP(pll_rate, hz) - 1;
265 assert(div < 32);
266 rk_clrsetreg(&cru->clksel_con[43], MAC_DIV_MASK,
267 div << MAC_DIV_SHIFT);
268
269 return DIV_TO_RATE(pll_rate, div);
270}
271
272static int rk3308_mac_set_speed_clk(struct clk *clk, uint hz)
273{
274 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
275 struct rk3308_cru *cru = priv->cru;
276
277 if (hz != 2500000 && hz != 25000000) {
278 debug("Unsupported mac speed:%d\n", hz);
279 return -EINVAL;
280 }
281
282 rk_clrsetreg(&cru->clksel_con[43], MAC_CLK_SPEED_SEL_MASK,
283 ((hz == 2500000) ? 0 : 1) << MAC_CLK_SPEED_SEL_SHIFT);
284
285 return 0;
286}
287
288static ulong rk3308_mmc_get_clk(struct clk *clk)
289{
290 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
291 struct rk3308_cru *cru = priv->cru;
292 u32 div, con, con_id;
293
294 switch (clk->id) {
295 case HCLK_SDMMC:
296 case SCLK_SDMMC:
297 con_id = 39;
298 break;
299 case HCLK_EMMC:
300 case SCLK_EMMC:
301 case SCLK_EMMC_SAMPLE:
302 con_id = 41;
303 break;
304 default:
305 return -EINVAL;
306 }
307
308 con = readl(&cru->clksel_con[con_id]);
309 div = (con & EMMC_DIV_MASK) >> EMMC_DIV_SHIFT;
310
311 if ((con & EMMC_PLL_MASK) >> EMMC_PLL_SHIFT
312 == EMMC_SEL_24M)
313 return DIV_TO_RATE(OSC_HZ, div) / 2;
314 else
315 return DIV_TO_RATE(priv->vpll0_hz, div) / 2;
316}
317
318static ulong rk3308_mmc_set_clk(struct clk *clk, ulong set_rate)
319{
320 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
321 struct rk3308_cru *cru = priv->cru;
322 int src_clk_div;
323 u32 con_id;
324
325 switch (clk->id) {
326 case HCLK_SDMMC:
327 case SCLK_SDMMC:
328 con_id = 39;
329 break;
330 case HCLK_EMMC:
331 case SCLK_EMMC:
332 con_id = 41;
333 break;
334 default:
335 return -EINVAL;
336 }
337 /* Select clk_sdmmc/emmc source from VPLL0 by default */
338 /* mmc clock defaulg div 2 internal, need provide double in cru */
339 src_clk_div = DIV_ROUND_UP(priv->vpll0_hz / 2, set_rate);
340
341 if (src_clk_div > 127) {
342 /* use 24MHz source for 400KHz clock */
343 src_clk_div = DIV_ROUND_UP(OSC_HZ / 2, set_rate);
344 rk_clrsetreg(&cru->clksel_con[con_id],
345 EMMC_PLL_MASK | EMMC_DIV_MASK | EMMC_CLK_SEL_MASK,
346 EMMC_CLK_SEL_EMMC << EMMC_CLK_SEL_SHIFT |
347 EMMC_SEL_24M << EMMC_PLL_SHIFT |
348 (src_clk_div - 1) << EMMC_DIV_SHIFT);
349 } else {
350 rk_clrsetreg(&cru->clksel_con[con_id],
351 EMMC_PLL_MASK | EMMC_DIV_MASK | EMMC_CLK_SEL_MASK,
352 EMMC_CLK_SEL_EMMC << EMMC_CLK_SEL_SHIFT |
353 EMMC_SEL_VPLL0 << EMMC_PLL_SHIFT |
354 (src_clk_div - 1) << EMMC_DIV_SHIFT);
355 }
356
357 return rk3308_mmc_get_clk(clk);
358}
359
360static ulong rk3308_saradc_get_clk(struct clk *clk)
361{
362 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
363 struct rk3308_cru *cru = priv->cru;
364 u32 div, con;
365
366 con = readl(&cru->clksel_con[34]);
Massimo Pegorer00a8fa32023-08-03 13:08:11 +0200367 div = (con & CLK_SARADC_DIV_CON_MASK) >> CLK_SARADC_DIV_CON_SHIFT;
Finley Xiaoafa71602019-11-14 11:21:13 +0800368
369 return DIV_TO_RATE(OSC_HZ, div);
370}
371
372static ulong rk3308_saradc_set_clk(struct clk *clk, uint hz)
373{
374 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
375 struct rk3308_cru *cru = priv->cru;
376 int src_clk_div;
377
378 src_clk_div = DIV_ROUND_UP(OSC_HZ, hz);
379 assert(src_clk_div - 1 <= 2047);
380
381 rk_clrsetreg(&cru->clksel_con[34],
382 CLK_SARADC_DIV_CON_MASK,
383 (src_clk_div - 1) << CLK_SARADC_DIV_CON_SHIFT);
384
385 return rk3308_saradc_get_clk(clk);
386}
387
388static ulong rk3308_tsadc_get_clk(struct clk *clk)
389{
390 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
391 struct rk3308_cru *cru = priv->cru;
392 u32 div, con;
393
394 con = readl(&cru->clksel_con[33]);
Massimo Pegorer00a8fa32023-08-03 13:08:11 +0200395 div = (con & CLK_SARADC_DIV_CON_MASK) >> CLK_SARADC_DIV_CON_SHIFT;
Finley Xiaoafa71602019-11-14 11:21:13 +0800396
397 return DIV_TO_RATE(OSC_HZ, div);
398}
399
400static ulong rk3308_tsadc_set_clk(struct clk *clk, uint hz)
401{
402 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
403 struct rk3308_cru *cru = priv->cru;
404 int src_clk_div;
405
406 src_clk_div = DIV_ROUND_UP(OSC_HZ, hz);
407 assert(src_clk_div - 1 <= 2047);
408
409 rk_clrsetreg(&cru->clksel_con[33],
410 CLK_SARADC_DIV_CON_MASK,
411 (src_clk_div - 1) << CLK_SARADC_DIV_CON_SHIFT);
412
413 return rk3308_tsadc_get_clk(clk);
414}
415
416static ulong rk3308_spi_get_clk(struct clk *clk)
417{
418 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
419 struct rk3308_cru *cru = priv->cru;
420 u32 div, con, con_id;
421
422 switch (clk->id) {
423 case SCLK_SPI0:
424 con_id = 30;
425 break;
426 case SCLK_SPI1:
427 con_id = 31;
428 break;
429 case SCLK_SPI2:
430 con_id = 32;
431 break;
432 default:
433 printf("do not support this spi bus\n");
434 return -EINVAL;
435 }
436
437 con = readl(&cru->clksel_con[con_id]);
Massimo Pegorer00a8fa32023-08-03 13:08:11 +0200438 div = (con & CLK_SPI_DIV_CON_MASK) >> CLK_SPI_DIV_CON_SHIFT;
Finley Xiaoafa71602019-11-14 11:21:13 +0800439
440 return DIV_TO_RATE(priv->dpll_hz, div);
441}
442
443static ulong rk3308_spi_set_clk(struct clk *clk, uint hz)
444{
445 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
446 struct rk3308_cru *cru = priv->cru;
447 u32 src_clk_div, con_id;
448
449 src_clk_div = DIV_ROUND_UP(priv->dpll_hz, hz);
450 assert(src_clk_div - 1 <= 127);
451
452 switch (clk->id) {
453 case SCLK_SPI0:
454 con_id = 30;
455 break;
456 case SCLK_SPI1:
457 con_id = 31;
458 break;
459 case SCLK_SPI2:
460 con_id = 32;
461 break;
462 default:
463 printf("do not support this spi bus\n");
464 return -EINVAL;
465 }
466
467 rk_clrsetreg(&cru->clksel_con[con_id],
468 CLK_SPI_PLL_SEL_MASK | CLK_SPI_DIV_CON_MASK,
469 CLK_SPI_PLL_SEL_DPLL << CLK_SPI_PLL_SEL_SHIFT |
470 (src_clk_div - 1) << CLK_SPI_DIV_CON_SHIFT);
471
472 return rk3308_spi_get_clk(clk);
473}
474
475static ulong rk3308_pwm_get_clk(struct clk *clk)
476{
477 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
478 struct rk3308_cru *cru = priv->cru;
479 u32 div, con;
480
481 con = readl(&cru->clksel_con[29]);
Massimo Pegorer00a8fa32023-08-03 13:08:11 +0200482 div = (con & CLK_PWM_DIV_CON_MASK) >> CLK_PWM_DIV_CON_SHIFT;
Finley Xiaoafa71602019-11-14 11:21:13 +0800483
484 return DIV_TO_RATE(priv->dpll_hz, div);
485}
486
487static ulong rk3308_pwm_set_clk(struct clk *clk, uint hz)
488{
489 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
490 struct rk3308_cru *cru = priv->cru;
491 int src_clk_div;
492
493 src_clk_div = DIV_ROUND_UP(priv->dpll_hz, hz);
494 assert(src_clk_div - 1 <= 127);
495
496 rk_clrsetreg(&cru->clksel_con[29],
497 CLK_PWM_PLL_SEL_MASK | CLK_PWM_DIV_CON_MASK,
498 CLK_PWM_PLL_SEL_DPLL << CLK_PWM_PLL_SEL_SHIFT |
499 (src_clk_div - 1) << CLK_PWM_DIV_CON_SHIFT);
500
501 return rk3308_pwm_get_clk(clk);
502}
503
Massimo Pegorer2d7b0d02023-08-03 13:08:12 +0200504static ulong rk3308_uart_get_clk(struct clk *clk)
505{
506 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
507 struct rk3308_cru *cru = priv->cru;
508 u32 div, pll_sel, con, con_id, parent;
509
510 switch (clk->id) {
511 case SCLK_UART0:
512 con_id = 10;
513 break;
514 case SCLK_UART1:
515 con_id = 13;
516 break;
517 case SCLK_UART2:
518 con_id = 16;
519 break;
520 case SCLK_UART3:
521 con_id = 19;
522 break;
523 case SCLK_UART4:
524 con_id = 22;
525 break;
526 default:
527 printf("do not support this uart interface\n");
528 return -EINVAL;
529 }
530
531 con = readl(&cru->clksel_con[con_id]);
532 pll_sel = (con & CLK_UART_PLL_SEL_MASK) >> CLK_UART_PLL_SEL_SHIFT;
533 div = (con & CLK_UART_DIV_CON_MASK) >> CLK_UART_DIV_CON_SHIFT;
534
535 switch (pll_sel) {
536 case CLK_UART_PLL_SEL_DPLL:
537 parent = priv->dpll_hz;
538 break;
539 case CLK_UART_PLL_SEL_VPLL0:
540 parent = priv->vpll0_hz;
541 break;
542 case CLK_UART_PLL_SEL_VPLL1:
543 parent = priv->vpll0_hz;
544 break;
545 case CLK_UART_PLL_SEL_24M:
546 parent = OSC_HZ;
547 break;
548 default:
549 printf("do not support this uart pll sel\n");
550 return -EINVAL;
551 }
552
553 return DIV_TO_RATE(parent, div);
554}
555
Finley Xiaoafa71602019-11-14 11:21:13 +0800556static ulong rk3308_vop_get_clk(struct clk *clk)
557{
558 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
559 struct rk3308_cru *cru = priv->cru;
560 u32 div, pll_sel, vol_sel, con, parent;
561
562 con = readl(&cru->clksel_con[8]);
563 vol_sel = (con & DCLK_VOP_SEL_MASK) >> DCLK_VOP_SEL_SHIFT;
564 pll_sel = (con & DCLK_VOP_PLL_SEL_MASK) >> DCLK_VOP_PLL_SEL_SHIFT;
565 div = con & DCLK_VOP_DIV_MASK;
566
567 if (vol_sel == DCLK_VOP_SEL_24M) {
568 parent = OSC_HZ;
569 } else if (vol_sel == DCLK_VOP_SEL_DIVOUT) {
570 switch (pll_sel) {
571 case DCLK_VOP_PLL_SEL_DPLL:
572 parent = priv->dpll_hz;
573 break;
574 case DCLK_VOP_PLL_SEL_VPLL0:
575 parent = priv->vpll0_hz;
576 break;
577 case DCLK_VOP_PLL_SEL_VPLL1:
578 parent = priv->vpll0_hz;
579 break;
580 default:
581 printf("do not support this vop pll sel\n");
582 return -EINVAL;
583 }
584 } else {
585 printf("do not support this vop sel\n");
586 return -EINVAL;
587 }
588
589 return DIV_TO_RATE(parent, div);
590}
591
592static ulong rk3308_vop_set_clk(struct clk *clk, ulong hz)
593{
594 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
595 struct rk3308_cru *cru = priv->cru;
596 ulong pll_rate, now, best_rate = 0;
597 u32 i, div, best_div = 0, best_sel = 0;
598
599 for (i = 0; i <= DCLK_VOP_PLL_SEL_VPLL1; i++) {
600 switch (i) {
601 case DCLK_VOP_PLL_SEL_DPLL:
602 pll_rate = priv->dpll_hz;
603 break;
604 case DCLK_VOP_PLL_SEL_VPLL0:
605 pll_rate = priv->vpll0_hz;
606 break;
607 case DCLK_VOP_PLL_SEL_VPLL1:
608 pll_rate = priv->vpll1_hz;
609 break;
610 default:
611 printf("do not support this vop pll sel\n");
612 return -EINVAL;
613 }
614
615 div = DIV_ROUND_UP(pll_rate, hz);
616 if (div > 255)
617 continue;
618 now = pll_rate / div;
619 if (abs(hz - now) < abs(hz - best_rate)) {
620 best_rate = now;
621 best_div = div;
622 best_sel = i;
623 }
624 debug("pll_rate=%lu, best_rate=%lu, best_div=%u, best_sel=%u\n",
625 pll_rate, best_rate, best_div, best_sel);
626 }
627
628 if (best_rate != hz && hz == OSC_HZ) {
629 rk_clrsetreg(&cru->clksel_con[8],
630 DCLK_VOP_SEL_MASK,
631 DCLK_VOP_SEL_24M << DCLK_VOP_SEL_SHIFT);
632 } else if (best_rate) {
633 rk_clrsetreg(&cru->clksel_con[8],
634 DCLK_VOP_SEL_MASK | DCLK_VOP_PLL_SEL_MASK |
635 DCLK_VOP_DIV_MASK,
636 DCLK_VOP_SEL_DIVOUT << DCLK_VOP_SEL_SHIFT |
637 best_sel << DCLK_VOP_PLL_SEL_SHIFT |
638 (best_div - 1) << DCLK_VOP_DIV_SHIFT);
639 } else {
640 printf("do not support this vop freq\n");
641 return -EINVAL;
642 }
643
644 return rk3308_vop_get_clk(clk);
645}
646
647static ulong rk3308_bus_get_clk(struct rk3308_clk_priv *priv, ulong clk_id)
648{
649 struct rk3308_cru *cru = priv->cru;
650 u32 div, con, parent = priv->dpll_hz;
651
652 switch (clk_id) {
653 case ACLK_BUS:
654 con = readl(&cru->clksel_con[5]);
655 div = (con & BUS_ACLK_DIV_MASK) >> BUS_ACLK_DIV_SHIFT;
656 break;
657 case HCLK_BUS:
658 con = readl(&cru->clksel_con[6]);
659 div = (con & BUS_HCLK_DIV_MASK) >> BUS_HCLK_DIV_SHIFT;
660 break;
661 case PCLK_BUS:
662 case PCLK_WDT:
663 con = readl(&cru->clksel_con[6]);
664 div = (con & BUS_PCLK_DIV_MASK) >> BUS_PCLK_DIV_SHIFT;
665 break;
666 default:
667 return -ENOENT;
668 }
669
670 return DIV_TO_RATE(parent, div);
671}
672
673static ulong rk3308_bus_set_clk(struct rk3308_clk_priv *priv, ulong clk_id,
674 ulong hz)
675{
676 struct rk3308_cru *cru = priv->cru;
677 int src_clk_div;
678
679 src_clk_div = DIV_ROUND_UP(priv->dpll_hz, hz);
680 assert(src_clk_div - 1 <= 31);
681
682 /*
683 * select dpll as pd_bus bus clock source and
684 * set up dependent divisors for PCLK/HCLK and ACLK clocks.
685 */
686 switch (clk_id) {
687 case ACLK_BUS:
688 rk_clrsetreg(&cru->clksel_con[5],
689 BUS_PLL_SEL_MASK | BUS_ACLK_DIV_MASK,
690 BUS_PLL_SEL_DPLL << BUS_PLL_SEL_SHIFT |
691 (src_clk_div - 1) << BUS_ACLK_DIV_SHIFT);
692 break;
693 case HCLK_BUS:
694 rk_clrsetreg(&cru->clksel_con[6],
695 BUS_HCLK_DIV_MASK,
696 (src_clk_div - 1) << BUS_HCLK_DIV_SHIFT);
697 break;
698 case PCLK_BUS:
699 rk_clrsetreg(&cru->clksel_con[6],
700 BUS_PCLK_DIV_MASK,
701 (src_clk_div - 1) << BUS_PCLK_DIV_SHIFT);
702 break;
703 default:
704 printf("do not support this bus freq\n");
705 return -EINVAL;
706 }
707
708 return rk3308_bus_get_clk(priv, clk_id);
709}
710
711static ulong rk3308_peri_get_clk(struct rk3308_clk_priv *priv, ulong clk_id)
712{
713 struct rk3308_cru *cru = priv->cru;
714 u32 div, con, parent = priv->dpll_hz;
715
716 switch (clk_id) {
717 case ACLK_PERI:
718 con = readl(&cru->clksel_con[36]);
719 div = (con & PERI_ACLK_DIV_MASK) >> PERI_ACLK_DIV_SHIFT;
720 break;
721 case HCLK_PERI:
722 con = readl(&cru->clksel_con[37]);
723 div = (con & PERI_HCLK_DIV_MASK) >> PERI_HCLK_DIV_SHIFT;
724 break;
725 case PCLK_PERI:
726 con = readl(&cru->clksel_con[37]);
727 div = (con & PERI_PCLK_DIV_MASK) >> PERI_PCLK_DIV_SHIFT;
728 break;
729 default:
730 return -ENOENT;
731 }
732
733 return DIV_TO_RATE(parent, div);
734}
735
736static ulong rk3308_peri_set_clk(struct rk3308_clk_priv *priv, ulong clk_id,
737 ulong hz)
738{
739 struct rk3308_cru *cru = priv->cru;
740 int src_clk_div;
741
742 src_clk_div = DIV_ROUND_UP(priv->dpll_hz, hz);
743 assert(src_clk_div - 1 <= 31);
744
745 /*
746 * select dpll as pd_peri bus clock source and
747 * set up dependent divisors for PCLK/HCLK and ACLK clocks.
748 */
749 switch (clk_id) {
750 case ACLK_PERI:
751 rk_clrsetreg(&cru->clksel_con[36],
752 PERI_PLL_SEL_MASK | PERI_ACLK_DIV_MASK,
753 PERI_PLL_DPLL << PERI_PLL_SEL_SHIFT |
754 (src_clk_div - 1) << PERI_ACLK_DIV_SHIFT);
755 break;
756 case HCLK_PERI:
757 rk_clrsetreg(&cru->clksel_con[37],
758 PERI_HCLK_DIV_MASK,
759 (src_clk_div - 1) << PERI_HCLK_DIV_SHIFT);
760 break;
761 case PCLK_PERI:
762 rk_clrsetreg(&cru->clksel_con[37],
763 PERI_PCLK_DIV_MASK,
764 (src_clk_div - 1) << PERI_PCLK_DIV_SHIFT);
765 break;
766 default:
767 printf("do not support this peri freq\n");
768 return -EINVAL;
769 }
770
771 return rk3308_peri_get_clk(priv, clk_id);
772}
773
774static ulong rk3308_audio_get_clk(struct rk3308_clk_priv *priv, ulong clk_id)
775{
776 struct rk3308_cru *cru = priv->cru;
777 u32 div, con, parent = priv->vpll0_hz;
778
779 switch (clk_id) {
780 case HCLK_AUDIO:
781 con = readl(&cru->clksel_con[45]);
782 div = (con & AUDIO_HCLK_DIV_MASK) >> AUDIO_HCLK_DIV_SHIFT;
783 break;
784 case PCLK_AUDIO:
785 con = readl(&cru->clksel_con[45]);
786 div = (con & AUDIO_PCLK_DIV_MASK) >> AUDIO_PCLK_DIV_SHIFT;
787 break;
788 default:
789 return -ENOENT;
790 }
791
792 return DIV_TO_RATE(parent, div);
793}
794
795static ulong rk3308_audio_set_clk(struct rk3308_clk_priv *priv, ulong clk_id,
796 ulong hz)
797{
798 struct rk3308_cru *cru = priv->cru;
799 int src_clk_div;
800
801 src_clk_div = DIV_ROUND_UP(priv->vpll0_hz, hz);
802 assert(src_clk_div - 1 <= 31);
803
804 /*
805 * select vpll0 as audio bus clock source and
806 * set up dependent divisors for HCLK and PCLK clocks.
807 */
808 switch (clk_id) {
809 case HCLK_AUDIO:
810 rk_clrsetreg(&cru->clksel_con[45],
811 AUDIO_PLL_SEL_MASK | AUDIO_HCLK_DIV_MASK,
812 AUDIO_PLL_VPLL0 << AUDIO_PLL_SEL_SHIFT |
813 (src_clk_div - 1) << AUDIO_HCLK_DIV_SHIFT);
814 break;
815 case PCLK_AUDIO:
816 rk_clrsetreg(&cru->clksel_con[45],
817 AUDIO_PLL_SEL_MASK | AUDIO_PCLK_DIV_MASK,
818 AUDIO_PLL_VPLL0 << AUDIO_PLL_SEL_SHIFT |
819 (src_clk_div - 1) << AUDIO_PCLK_DIV_SHIFT);
820 break;
821 default:
822 printf("do not support this audio freq\n");
823 return -EINVAL;
824 }
825
826 return rk3308_peri_get_clk(priv, clk_id);
827}
828
829static ulong rk3308_crypto_get_clk(struct rk3308_clk_priv *priv, ulong clk_id)
830{
831 struct rk3308_cru *cru = priv->cru;
832 u32 div, con, parent;
833
834 switch (clk_id) {
835 case SCLK_CRYPTO:
836 con = readl(&cru->clksel_con[7]);
837 div = (con & CRYPTO_DIV_MASK) >> CRYPTO_DIV_SHIFT;
838 parent = priv->vpll0_hz;
839 break;
840 case SCLK_CRYPTO_APK:
841 con = readl(&cru->clksel_con[7]);
842 div = (con & CRYPTO_APK_DIV_MASK) >> CRYPTO_APK_DIV_SHIFT;
843 parent = priv->vpll0_hz;
844 break;
845 default:
846 return -ENOENT;
847 }
848
849 return DIV_TO_RATE(parent, div);
850}
851
852static ulong rk3308_crypto_set_clk(struct rk3308_clk_priv *priv, ulong clk_id,
853 ulong hz)
854{
855 struct rk3308_cru *cru = priv->cru;
856 int src_clk_div;
857
858 src_clk_div = DIV_ROUND_UP(priv->vpll0_hz, hz);
859 assert(src_clk_div - 1 <= 31);
860
861 /*
862 * select gpll as crypto clock source and
863 * set up dependent divisors for crypto clocks.
864 */
865 switch (clk_id) {
866 case SCLK_CRYPTO:
867 rk_clrsetreg(&cru->clksel_con[7],
868 CRYPTO_PLL_SEL_MASK | CRYPTO_DIV_MASK,
869 CRYPTO_PLL_SEL_VPLL0 << CRYPTO_PLL_SEL_SHIFT |
870 (src_clk_div - 1) << CRYPTO_DIV_SHIFT);
871 break;
872 case SCLK_CRYPTO_APK:
873 rk_clrsetreg(&cru->clksel_con[7],
874 CRYPTO_APK_PLL_SEL_MASK | CRYPTO_APK_DIV_MASK,
875 CRYPTO_PLL_SEL_VPLL0 << CRYPTO_APK_SEL_SHIFT |
876 (src_clk_div - 1) << CRYPTO_APK_DIV_SHIFT);
877 break;
878 default:
879 printf("do not support this peri freq\n");
880 return -EINVAL;
881 }
882
883 return rk3308_crypto_get_clk(priv, clk_id);
884}
885
Finley Xiao37241492024-04-08 18:14:04 +0000886static ulong rk3308_rtc32k_get_clk(struct rk3308_clk_priv *priv, ulong clk_id)
887{
888 struct rk3308_cru *cru = priv->cru;
889 unsigned long m, n;
890 u32 con, fracdiv;
891
892 con = readl(&cru->clksel_con[2]);
893 if ((con & CLK_RTC32K_SEL_MASK) >> CLK_RTC32K_SEL_SHIFT !=
894 CLK_RTC32K_FRAC_DIV)
895 return -EINVAL;
896
897 fracdiv = readl(&cru->clksel_con[3]);
898 m = fracdiv & CLK_RTC32K_FRAC_NUMERATOR_MASK;
899 m >>= CLK_RTC32K_FRAC_NUMERATOR_SHIFT;
900 n = fracdiv & CLK_RTC32K_FRAC_DENOMINATOR_MASK;
901 n >>= CLK_RTC32K_FRAC_DENOMINATOR_SHIFT;
902
903 return OSC_HZ * m / n;
904}
905
906static ulong rk3308_rtc32k_set_clk(struct rk3308_clk_priv *priv, ulong clk_id,
907 ulong hz)
908{
909 struct rk3308_cru *cru = priv->cru;
910 unsigned long m, n, val;
911
912 rational_best_approximation(hz, OSC_HZ,
913 GENMASK(16 - 1, 0),
914 GENMASK(16 - 1, 0),
915 &m, &n);
916 val = m << CLK_RTC32K_FRAC_NUMERATOR_SHIFT | n;
917 writel(val, &cru->clksel_con[3]);
918 rk_clrsetreg(&cru->clksel_con[2], CLK_RTC32K_SEL_MASK,
919 CLK_RTC32K_FRAC_DIV << CLK_RTC32K_SEL_SHIFT);
920
921 return rk3308_rtc32k_get_clk(priv, clk_id);
922}
923
Finley Xiaoafa71602019-11-14 11:21:13 +0800924static ulong rk3308_clk_get_rate(struct clk *clk)
925{
926 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
927 ulong rate = 0;
928
929 debug("%s id:%ld\n", __func__, clk->id);
930
931 switch (clk->id) {
932 case PLL_APLL:
933 case ARMCLK:
934 rate = rockchip_pll_get_rate(&rk3308_pll_clks[APLL],
935 priv->cru, APLL);
936 break;
937 case PLL_DPLL:
938 rate = rockchip_pll_get_rate(&rk3308_pll_clks[DPLL],
939 priv->cru, DPLL);
940 break;
941 case PLL_VPLL0:
942 rate = rockchip_pll_get_rate(&rk3308_pll_clks[VPLL0],
943 priv->cru, VPLL0);
944 break;
945 case PLL_VPLL1:
946 rate = rockchip_pll_get_rate(&rk3308_pll_clks[VPLL1],
947 priv->cru, VPLL1);
948 break;
949 case HCLK_SDMMC:
950 case HCLK_EMMC:
951 case SCLK_SDMMC:
952 case SCLK_EMMC:
953 case SCLK_EMMC_SAMPLE:
954 rate = rk3308_mmc_get_clk(clk);
955 break;
Massimo Pegorer2d7b0d02023-08-03 13:08:12 +0200956 case SCLK_UART0:
957 case SCLK_UART1:
958 case SCLK_UART2:
959 case SCLK_UART3:
960 case SCLK_UART4:
961 rate = rk3308_uart_get_clk(clk);
962 break;
Finley Xiaoafa71602019-11-14 11:21:13 +0800963 case SCLK_I2C0:
964 case SCLK_I2C1:
965 case SCLK_I2C2:
966 case SCLK_I2C3:
967 rate = rk3308_i2c_get_clk(clk);
968 break;
969 case SCLK_SARADC:
970 rate = rk3308_saradc_get_clk(clk);
971 break;
972 case SCLK_TSADC:
973 rate = rk3308_tsadc_get_clk(clk);
974 break;
975 case SCLK_SPI0:
976 case SCLK_SPI1:
977 rate = rk3308_spi_get_clk(clk);
978 break;
979 case SCLK_PWM0:
980 rate = rk3308_pwm_get_clk(clk);
981 break;
982 case DCLK_VOP:
983 rate = rk3308_vop_get_clk(clk);
984 break;
985 case ACLK_BUS:
986 case HCLK_BUS:
987 case PCLK_BUS:
988 case PCLK_WDT:
989 rate = rk3308_bus_get_clk(priv, clk->id);
990 break;
991 case ACLK_PERI:
992 case HCLK_PERI:
993 case PCLK_PERI:
994 rate = rk3308_peri_get_clk(priv, clk->id);
995 break;
996 case HCLK_AUDIO:
997 case PCLK_AUDIO:
998 rate = rk3308_audio_get_clk(priv, clk->id);
999 break;
1000 case SCLK_CRYPTO:
1001 case SCLK_CRYPTO_APK:
1002 rate = rk3308_crypto_get_clk(priv, clk->id);
1003 break;
Finley Xiao37241492024-04-08 18:14:04 +00001004 case SCLK_RTC32K:
1005 rate = rk3308_rtc32k_get_clk(priv, clk->id);
1006 break;
Finley Xiaoafa71602019-11-14 11:21:13 +08001007 default:
1008 return -ENOENT;
1009 }
1010
1011 return rate;
1012}
1013
1014static ulong rk3308_clk_set_rate(struct clk *clk, ulong rate)
1015{
1016 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
1017 ulong ret = 0;
1018
1019 debug("%s %ld %ld\n", __func__, clk->id, rate);
1020
1021 switch (clk->id) {
1022 case PLL_DPLL:
1023 ret = rockchip_pll_set_rate(&rk3308_pll_clks[DPLL], priv->cru,
1024 DPLL, rate);
1025 priv->dpll_hz = rockchip_pll_get_rate(&rk3308_pll_clks[DPLL],
1026 priv->cru, DPLL);
1027 break;
1028 case ARMCLK:
1029 if (priv->armclk_hz)
1030 rk3308_armclk_set_clk(priv, rate);
1031 priv->armclk_hz = rate;
1032 break;
1033 case HCLK_SDMMC:
1034 case HCLK_EMMC:
1035 case SCLK_SDMMC:
1036 case SCLK_EMMC:
1037 ret = rk3308_mmc_set_clk(clk, rate);
1038 break;
1039 case SCLK_I2C0:
1040 case SCLK_I2C1:
1041 case SCLK_I2C2:
1042 case SCLK_I2C3:
1043 ret = rk3308_i2c_set_clk(clk, rate);
1044 break;
1045 case SCLK_MAC:
1046 ret = rk3308_mac_set_clk(clk, rate);
1047 break;
1048 case SCLK_MAC_RMII:
1049 ret = rk3308_mac_set_speed_clk(clk, rate);
1050 break;
1051 case SCLK_SARADC:
1052 ret = rk3308_saradc_set_clk(clk, rate);
1053 break;
1054 case SCLK_TSADC:
1055 ret = rk3308_tsadc_set_clk(clk, rate);
1056 break;
1057 case SCLK_SPI0:
1058 case SCLK_SPI1:
1059 ret = rk3308_spi_set_clk(clk, rate);
1060 break;
1061 case SCLK_PWM0:
1062 ret = rk3308_pwm_set_clk(clk, rate);
1063 break;
1064 case DCLK_VOP:
1065 ret = rk3308_vop_set_clk(clk, rate);
1066 break;
1067 case ACLK_BUS:
1068 case HCLK_BUS:
1069 case PCLK_BUS:
1070 rate = rk3308_bus_set_clk(priv, clk->id, rate);
1071 break;
1072 case ACLK_PERI:
1073 case HCLK_PERI:
1074 case PCLK_PERI:
1075 rate = rk3308_peri_set_clk(priv, clk->id, rate);
1076 break;
1077 case HCLK_AUDIO:
1078 case PCLK_AUDIO:
1079 rate = rk3308_audio_set_clk(priv, clk->id, rate);
1080 break;
1081 case SCLK_CRYPTO:
1082 case SCLK_CRYPTO_APK:
1083 ret = rk3308_crypto_set_clk(priv, clk->id, rate);
1084 break;
Finley Xiao37241492024-04-08 18:14:04 +00001085 case SCLK_RTC32K:
1086 ret = rk3308_rtc32k_set_clk(priv, clk->id, rate);
1087 break;
Jonas Karlmanab61e092024-04-08 18:14:05 +00001088 case USB480M:
1089 return 0;
Finley Xiaoafa71602019-11-14 11:21:13 +08001090 default:
1091 return -ENOENT;
1092 }
1093
1094 return ret;
1095}
1096
Simon Glass3580f6d2021-08-07 07:24:03 -06001097#if CONFIG_IS_ENABLED(OF_REAL)
Finley Xiaoafa71602019-11-14 11:21:13 +08001098static int __maybe_unused rk3308_mac_set_parent(struct clk *clk, struct clk *parent)
1099{
1100 struct rk3308_clk_priv *priv = dev_get_priv(clk->dev);
1101
1102 /*
1103 * If the requested parent is in the same clock-controller and
1104 * the id is SCLK_MAC_SRC, switch to the internal clock.
1105 */
1106 if (parent->id == SCLK_MAC_SRC) {
1107 debug("%s: switching RMII to SCLK_MAC\n", __func__);
1108 rk_clrreg(&priv->cru->clksel_con[43], BIT(14));
1109 } else {
1110 debug("%s: switching RMII to CLKIN\n", __func__);
1111 rk_setreg(&priv->cru->clksel_con[43], BIT(14));
1112 }
1113
1114 return 0;
1115}
1116
1117static int __maybe_unused rk3308_clk_set_parent(struct clk *clk, struct clk *parent)
1118{
1119 switch (clk->id) {
1120 case SCLK_MAC:
1121 return rk3308_mac_set_parent(clk, parent);
Jonas Karlmanab61e092024-04-08 18:14:05 +00001122 case USB480M:
1123 return 0;
Finley Xiaoafa71602019-11-14 11:21:13 +08001124 default:
1125 break;
1126 }
1127
1128 debug("%s: unsupported clk %ld\n", __func__, clk->id);
1129 return -ENOENT;
1130}
1131#endif
1132
1133static struct clk_ops rk3308_clk_ops = {
1134 .get_rate = rk3308_clk_get_rate,
1135 .set_rate = rk3308_clk_set_rate,
Simon Glass3580f6d2021-08-07 07:24:03 -06001136#if CONFIG_IS_ENABLED(OF_REAL)
Finley Xiaoafa71602019-11-14 11:21:13 +08001137 .set_parent = rk3308_clk_set_parent,
1138#endif
1139};
1140
1141static void rk3308_clk_init(struct udevice *dev)
1142{
1143 struct rk3308_clk_priv *priv = dev_get_priv(dev);
1144 int ret;
1145
1146 if (rockchip_pll_get_rate(&rk3308_pll_clks[APLL],
1147 priv->cru, APLL) != APLL_HZ) {
1148 ret = rk3308_armclk_set_clk(priv, APLL_HZ);
1149 if (ret < 0)
1150 printf("%s failed to set armclk rate\n", __func__);
1151 }
1152
1153 rk3308_clk_get_pll_rate(priv);
1154
1155 rk3308_bus_set_clk(priv, ACLK_BUS, BUS_ACLK_HZ);
1156 rk3308_bus_set_clk(priv, HCLK_BUS, BUS_HCLK_HZ);
1157 rk3308_bus_set_clk(priv, PCLK_BUS, BUS_PCLK_HZ);
1158
1159 rk3308_peri_set_clk(priv, ACLK_PERI, PERI_ACLK_HZ);
1160 rk3308_peri_set_clk(priv, HCLK_PERI, PERI_HCLK_HZ);
1161 rk3308_peri_set_clk(priv, PCLK_PERI, PERI_PCLK_HZ);
1162
1163 rk3308_audio_set_clk(priv, HCLK_AUDIO, AUDIO_HCLK_HZ);
1164 rk3308_audio_set_clk(priv, PCLK_AUDIO, AUDIO_PCLK_HZ);
1165}
1166
1167static int rk3308_clk_probe(struct udevice *dev)
1168{
1169 int ret;
1170
1171 rk3308_clk_init(dev);
1172
1173 /* Process 'assigned-{clocks/clock-parents/clock-rates}' properties */
Sean Anderson08d531c2021-06-11 00:16:07 -04001174 ret = clk_set_defaults(dev, CLK_DEFAULTS_POST);
Finley Xiaoafa71602019-11-14 11:21:13 +08001175 if (ret)
1176 debug("%s clk_set_defaults failed %d\n", __func__, ret);
1177
1178 return ret;
1179}
1180
Simon Glassaad29ae2020-12-03 16:55:21 -07001181static int rk3308_clk_of_to_plat(struct udevice *dev)
Finley Xiaoafa71602019-11-14 11:21:13 +08001182{
1183 struct rk3308_clk_priv *priv = dev_get_priv(dev);
1184
1185 priv->cru = dev_read_addr_ptr(dev);
1186
1187 return 0;
1188}
1189
1190static int rk3308_clk_bind(struct udevice *dev)
1191{
1192 int ret;
1193 struct udevice *sys_child;
1194 struct sysreset_reg *priv;
1195
1196 /* The reset driver does not have a device node, so bind it here */
1197 ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset",
1198 &sys_child);
1199 if (ret) {
1200 debug("Warning: No sysreset driver: ret=%d\n", ret);
1201 } else {
1202 priv = malloc(sizeof(struct sysreset_reg));
1203 priv->glb_srst_fst_value = offsetof(struct rk3308_cru,
1204 glb_srst_fst);
1205 priv->glb_srst_snd_value = offsetof(struct rk3308_cru,
1206 glb_srst_snd);
Simon Glass95588622020-12-22 19:30:28 -07001207 dev_set_priv(sys_child, priv);
Finley Xiaoafa71602019-11-14 11:21:13 +08001208 }
1209
1210#if CONFIG_IS_ENABLED(RESET_ROCKCHIP)
1211 ret = offsetof(struct rk3308_cru, softrst_con[0]);
1212 ret = rockchip_reset_bind(dev, ret, 12);
1213 if (ret)
Eugen Hristevf1798262023-04-11 10:17:56 +03001214 debug("Warning: software reset driver bind failed\n");
Finley Xiaoafa71602019-11-14 11:21:13 +08001215#endif
1216
1217 return 0;
1218}
1219
1220static const struct udevice_id rk3308_clk_ids[] = {
1221 { .compatible = "rockchip,rk3308-cru" },
1222 { }
1223};
1224
1225U_BOOT_DRIVER(rockchip_rk3308_cru) = {
1226 .name = "rockchip_rk3308_cru",
1227 .id = UCLASS_CLK,
1228 .of_match = rk3308_clk_ids,
Simon Glass8a2b47f2020-12-03 16:55:17 -07001229 .priv_auto = sizeof(struct rk3308_clk_priv),
Simon Glassaad29ae2020-12-03 16:55:21 -07001230 .of_to_plat = rk3308_clk_of_to_plat,
Finley Xiaoafa71602019-11-14 11:21:13 +08001231 .ops = &rk3308_clk_ops,
1232 .bind = rk3308_clk_bind,
1233 .probe = rk3308_clk_probe,
1234};