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