Prepare v2023.10
[platform/kernel/u-boot.git] / drivers / clk / rockchip / clk_rv1108.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * (C) Copyright 2016 Rockchip Electronics Co., Ltd
4  * Author: Andy Yan <andy.yan@rock-chips.com>
5  */
6
7 #include <common.h>
8 #include <bitfield.h>
9 #include <clk-uclass.h>
10 #include <dm.h>
11 #include <errno.h>
12 #include <log.h>
13 #include <malloc.h>
14 #include <syscon.h>
15 #include <asm/global_data.h>
16 #include <asm/io.h>
17 #include <asm/arch-rockchip/clock.h>
18 #include <asm/arch-rockchip/cru_rv1108.h>
19 #include <asm/arch-rockchip/hardware.h>
20 #include <dm/device-internal.h>
21 #include <dm/lists.h>
22 #include <dt-bindings/clock/rv1108-cru.h>
23 #include <linux/delay.h>
24 #include <linux/stringify.h>
25
26 DECLARE_GLOBAL_DATA_PTR;
27
28 enum {
29         VCO_MAX_HZ      = 2400U * 1000000,
30         VCO_MIN_HZ      = 600 * 1000000,
31         OUTPUT_MAX_HZ   = 2400U * 1000000,
32         OUTPUT_MIN_HZ   = 24 * 1000000,
33 };
34
35 #define DIV_TO_RATE(input_rate, div)    ((input_rate) / ((div) + 1))
36
37 #define PLL_DIVISORS(hz, _refdiv, _postdiv1, _postdiv2) {\
38         .refdiv = _refdiv,\
39         .fbdiv = (u32)((u64)hz * _refdiv * _postdiv1 * _postdiv2 / OSC_HZ),\
40         .postdiv1 = _postdiv1, .postdiv2 = _postdiv2};\
41         _Static_assert(((u64)hz * _refdiv * _postdiv1 * _postdiv2 / OSC_HZ) *\
42                          OSC_HZ / (_refdiv * _postdiv1 * _postdiv2) == hz,\
43                          #hz "Hz cannot be hit with PLL "\
44                          "divisors on line " __stringify(__LINE__));
45
46 static const struct pll_div apll_init_cfg = PLL_DIVISORS(APLL_HZ, 1, 3, 1);
47 static const struct pll_div gpll_init_cfg = PLL_DIVISORS(GPLL_HZ, 2, 2, 1);
48
49 /* use integer mode */
50 static inline int rv1108_pll_id(enum rk_clk_id clk_id)
51 {
52         int id = 0;
53
54         switch (clk_id) {
55         case CLK_ARM:
56         case CLK_DDR:
57                 id = clk_id - 1;
58                 break;
59         case CLK_GENERAL:
60                 id = 2;
61                 break;
62         default:
63                 printf("invalid pll id:%d\n", clk_id);
64                 id = -1;
65                 break;
66         }
67
68         return id;
69 }
70
71 static int rkclk_set_pll(struct rv1108_cru *cru, enum rk_clk_id clk_id,
72                          const struct pll_div *div)
73 {
74         int pll_id = rv1108_pll_id(clk_id);
75         struct rv1108_pll *pll = &cru->pll[pll_id];
76
77         /* All PLLs have same VCO and output frequency range restrictions. */
78         uint vco_hz = OSC_HZ / 1000 * div->fbdiv / div->refdiv * 1000;
79         uint output_hz = vco_hz / div->postdiv1 / div->postdiv2;
80
81         debug("PLL at %p: fb=%d, ref=%d, pst1=%d, pst2=%d, vco=%u Hz, output=%u Hz\n",
82               pll, div->fbdiv, div->refdiv, div->postdiv1,
83               div->postdiv2, vco_hz, output_hz);
84         assert(vco_hz >= VCO_MIN_HZ && vco_hz <= VCO_MAX_HZ &&
85                output_hz >= OUTPUT_MIN_HZ && output_hz <= OUTPUT_MAX_HZ);
86
87         /*
88          * When power on or changing PLL setting,
89          * we must force PLL into slow mode to ensure output stable clock.
90          */
91         rk_clrsetreg(&pll->con3, WORK_MODE_MASK,
92                      WORK_MODE_SLOW << WORK_MODE_SHIFT);
93
94         /* use integer mode */
95         rk_setreg(&pll->con3, 1 << DSMPD_SHIFT);
96         /* Power down */
97         rk_setreg(&pll->con3, 1 << GLOBAL_POWER_DOWN_SHIFT);
98
99         rk_clrsetreg(&pll->con0, FBDIV_MASK, div->fbdiv << FBDIV_SHIFT);
100         rk_clrsetreg(&pll->con1, POSTDIV1_MASK | POSTDIV2_MASK | REFDIV_MASK,
101                      (div->postdiv1 << POSTDIV1_SHIFT |
102                      div->postdiv2 << POSTDIV2_SHIFT |
103                      div->refdiv << REFDIV_SHIFT));
104         rk_clrsetreg(&pll->con2, FRACDIV_MASK,
105                      (div->refdiv << REFDIV_SHIFT));
106
107         /* Power Up */
108         rk_clrreg(&pll->con3, 1 << GLOBAL_POWER_DOWN_SHIFT);
109
110         /* waiting for pll lock */
111         while (readl(&pll->con2) & (1 << LOCK_STA_SHIFT))
112                 udelay(1);
113
114         /*
115          * set PLL into normal mode.
116          */
117         rk_clrsetreg(&pll->con3, WORK_MODE_MASK,
118                      WORK_MODE_NORMAL << WORK_MODE_SHIFT);
119
120         return 0;
121 }
122
123 static uint32_t rkclk_pll_get_rate(struct rv1108_cru *cru,
124                                    enum rk_clk_id clk_id)
125 {
126         uint32_t refdiv, fbdiv, postdiv1, postdiv2;
127         uint32_t con0, con1, con3;
128         int pll_id = rv1108_pll_id(clk_id);
129         struct rv1108_pll *pll = &cru->pll[pll_id];
130         uint32_t freq;
131
132         con3 = readl(&pll->con3);
133
134         if (con3 & WORK_MODE_MASK) {
135                 con0 = readl(&pll->con0);
136                 con1 = readl(&pll->con1);
137                 fbdiv = (con0 >> FBDIV_SHIFT) & FBDIV_MASK;
138                 postdiv1 = (con1 & POSTDIV1_MASK) >> POSTDIV1_SHIFT;
139                 postdiv2 = (con1 & POSTDIV2_MASK) >> POSTDIV2_SHIFT;
140                 refdiv = (con1 >> REFDIV_SHIFT) & REFDIV_MASK;
141                 freq = (24 * fbdiv / (refdiv * postdiv1 * postdiv2)) * 1000000;
142         } else {
143                 freq = OSC_HZ;
144         }
145
146         return freq;
147 }
148
149 static int rv1108_mac_set_clk(struct rv1108_cru *cru, ulong rate)
150 {
151         uint32_t con = readl(&cru->clksel_con[24]);
152         ulong pll_rate;
153         uint8_t div;
154
155         if ((con >> MAC_PLL_SEL_SHIFT) & MAC_PLL_SEL_GPLL)
156                 pll_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
157         else
158                 pll_rate = rkclk_pll_get_rate(cru, CLK_ARM);
159
160         /*default set 50MHZ for gmac*/
161         if (!rate)
162                 rate = 50000000;
163
164         div = DIV_ROUND_UP(pll_rate, rate) - 1;
165         if (div <= 0x1f)
166                 rk_clrsetreg(&cru->clksel_con[24], MAC_CLK_DIV_MASK,
167                              div << MAC_CLK_DIV_SHIFT);
168         else
169                 debug("Unsupported div for gmac:%d\n", div);
170
171         return DIV_TO_RATE(pll_rate, div);
172 }
173
174 static int rv1108_sfc_set_clk(struct rv1108_cru *cru, uint rate)
175 {
176         u32 con = readl(&cru->clksel_con[27]);
177         u32 pll_rate;
178         u32 div;
179
180         if ((con >> SFC_PLL_SEL_SHIFT) && SFC_PLL_SEL_GPLL)
181                 pll_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
182         else
183                 pll_rate = rkclk_pll_get_rate(cru, CLK_DDR);
184
185         div = DIV_ROUND_UP(pll_rate, rate) - 1;
186         if (div <= 0x3f)
187                 rk_clrsetreg(&cru->clksel_con[27], SFC_CLK_DIV_MASK,
188                              div << SFC_CLK_DIV_SHIFT);
189         else
190                 debug("Unsupported sfc clk rate:%d\n", rate);
191
192         return DIV_TO_RATE(pll_rate, div);
193 }
194
195 static ulong rv1108_saradc_get_clk(struct rv1108_cru *cru)
196 {
197         u32 div, val;
198
199         val = readl(&cru->clksel_con[22]);
200         div = bitfield_extract(val, CLK_SARADC_DIV_CON_SHIFT,
201                                CLK_SARADC_DIV_CON_WIDTH);
202
203         return DIV_TO_RATE(OSC_HZ, div);
204 }
205
206 static ulong rv1108_saradc_set_clk(struct rv1108_cru *cru, uint hz)
207 {
208         int src_clk_div;
209
210         src_clk_div = DIV_ROUND_UP(OSC_HZ, hz) - 1;
211         assert(src_clk_div < 128);
212
213         rk_clrsetreg(&cru->clksel_con[22],
214                      CLK_SARADC_DIV_CON_MASK,
215                      src_clk_div << CLK_SARADC_DIV_CON_SHIFT);
216
217         return rv1108_saradc_get_clk(cru);
218 }
219
220 static ulong rv1108_aclk_vio1_get_clk(struct rv1108_cru *cru)
221 {
222         u32 div, val;
223
224         val = readl(&cru->clksel_con[28]);
225         div = bitfield_extract(val, ACLK_VIO1_CLK_DIV_SHIFT,
226                                CLK_VIO_DIV_CON_WIDTH);
227
228         return DIV_TO_RATE(GPLL_HZ, div);
229 }
230
231 static ulong rv1108_aclk_vio1_set_clk(struct rv1108_cru *cru, uint hz)
232 {
233         int src_clk_div;
234
235         src_clk_div = DIV_ROUND_UP(GPLL_HZ, hz) - 1;
236         assert(src_clk_div < 32);
237
238         rk_clrsetreg(&cru->clksel_con[28],
239                      ACLK_VIO1_CLK_DIV_MASK | ACLK_VIO1_PLL_SEL_MASK,
240                      (src_clk_div << ACLK_VIO1_CLK_DIV_SHIFT) |
241                      (VIO_PLL_SEL_GPLL << ACLK_VIO1_PLL_SEL_SHIFT));
242
243         return rv1108_aclk_vio1_get_clk(cru);
244 }
245
246 static ulong rv1108_aclk_vio0_get_clk(struct rv1108_cru *cru)
247 {
248         u32 div, val;
249
250         val = readl(&cru->clksel_con[28]);
251         div = bitfield_extract(val, ACLK_VIO0_CLK_DIV_SHIFT,
252                                CLK_VIO_DIV_CON_WIDTH);
253
254         return DIV_TO_RATE(GPLL_HZ, div);
255 }
256
257 static ulong rv1108_aclk_vio0_set_clk(struct rv1108_cru *cru, uint hz)
258 {
259         int src_clk_div;
260
261         src_clk_div = DIV_ROUND_UP(GPLL_HZ, hz) - 1;
262         assert(src_clk_div < 32);
263
264         rk_clrsetreg(&cru->clksel_con[28],
265                      ACLK_VIO0_CLK_DIV_MASK | ACLK_VIO0_PLL_SEL_MASK,
266                      (src_clk_div << ACLK_VIO0_CLK_DIV_SHIFT) |
267                      (VIO_PLL_SEL_GPLL << ACLK_VIO0_PLL_SEL_SHIFT));
268
269         /*HCLK_VIO default div = 4*/
270         rk_clrsetreg(&cru->clksel_con[29],
271                      HCLK_VIO_CLK_DIV_MASK,
272                      3 << HCLK_VIO_CLK_DIV_SHIFT);
273         /*PCLK_VIO default div = 4*/
274         rk_clrsetreg(&cru->clksel_con[29],
275                      PCLK_VIO_CLK_DIV_MASK,
276                      3 << PCLK_VIO_CLK_DIV_SHIFT);
277
278         return rv1108_aclk_vio0_get_clk(cru);
279 }
280
281 static ulong rv1108_dclk_vop_get_clk(struct rv1108_cru *cru)
282 {
283         u32 div, val;
284
285         val = readl(&cru->clksel_con[32]);
286         div = bitfield_extract(val, DCLK_VOP_CLK_DIV_SHIFT,
287                                DCLK_VOP_DIV_CON_WIDTH);
288
289         return DIV_TO_RATE(GPLL_HZ, div);
290 }
291
292 static ulong rv1108_dclk_vop_set_clk(struct rv1108_cru *cru, uint hz)
293 {
294         int src_clk_div;
295
296         src_clk_div = DIV_ROUND_UP(GPLL_HZ, hz) - 1;
297         assert(src_clk_div < 64);
298
299         rk_clrsetreg(&cru->clksel_con[32],
300                      DCLK_VOP_CLK_DIV_MASK | DCLK_VOP_PLL_SEL_MASK |
301                      DCLK_VOP_SEL_SHIFT,
302                      (src_clk_div << DCLK_VOP_CLK_DIV_SHIFT) |
303                      (DCLK_VOP_PLL_SEL_GPLL << DCLK_VOP_PLL_SEL_SHIFT) |
304                      (DCLK_VOP_SEL_PLL << DCLK_VOP_SEL_SHIFT));
305
306         return rv1108_dclk_vop_get_clk(cru);
307 }
308
309 static ulong rv1108_aclk_bus_get_clk(struct rv1108_cru *cru)
310 {
311         u32 div, val;
312         ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
313
314         val = readl(&cru->clksel_con[2]);
315         div = bitfield_extract(val, ACLK_BUS_DIV_CON_SHIFT,
316                                ACLK_BUS_DIV_CON_WIDTH);
317
318         return DIV_TO_RATE(parent_rate, div);
319 }
320
321 static ulong rv1108_aclk_bus_set_clk(struct rv1108_cru *cru, uint hz)
322 {
323         int src_clk_div;
324         ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
325
326         src_clk_div = DIV_ROUND_UP(parent_rate, hz) - 1;
327         assert(src_clk_div < 32);
328
329         rk_clrsetreg(&cru->clksel_con[2],
330                      ACLK_BUS_DIV_CON_MASK | ACLK_BUS_PLL_SEL_MASK,
331                      (src_clk_div << ACLK_BUS_DIV_CON_SHIFT) |
332                      (ACLK_BUS_PLL_SEL_GPLL << ACLK_BUS_PLL_SEL_SHIFT));
333
334         return rv1108_aclk_bus_get_clk(cru);
335 }
336
337 static ulong rv1108_aclk_peri_get_clk(struct rv1108_cru *cru)
338 {
339         u32 div, val;
340         ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
341
342         val = readl(&cru->clksel_con[23]);
343         div = bitfield_extract(val, ACLK_PERI_DIV_CON_SHIFT,
344                                PERI_DIV_CON_WIDTH);
345
346         return DIV_TO_RATE(parent_rate, div);
347 }
348
349 static ulong rv1108_hclk_peri_get_clk(struct rv1108_cru *cru)
350 {
351         u32 div, val;
352         ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
353
354         val = readl(&cru->clksel_con[23]);
355         div = bitfield_extract(val, HCLK_PERI_DIV_CON_SHIFT,
356                                PERI_DIV_CON_WIDTH);
357
358         return DIV_TO_RATE(parent_rate, div);
359 }
360
361 static ulong rv1108_pclk_peri_get_clk(struct rv1108_cru *cru)
362 {
363         u32 div, val;
364         ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
365
366         val = readl(&cru->clksel_con[23]);
367         div = bitfield_extract(val, PCLK_PERI_DIV_CON_SHIFT,
368                                PERI_DIV_CON_WIDTH);
369
370         return DIV_TO_RATE(parent_rate, div);
371 }
372
373 static ulong rv1108_aclk_peri_set_clk(struct rv1108_cru *cru, uint hz)
374 {
375         int src_clk_div;
376         ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
377
378         src_clk_div = DIV_ROUND_UP(parent_rate, hz) - 1;
379         assert(src_clk_div < 32);
380
381         rk_clrsetreg(&cru->clksel_con[23],
382                      ACLK_PERI_DIV_CON_MASK | ACLK_PERI_PLL_SEL_MASK,
383                      (src_clk_div << ACLK_PERI_DIV_CON_SHIFT) |
384                      (ACLK_PERI_PLL_SEL_GPLL << ACLK_PERI_PLL_SEL_SHIFT));
385
386         return rv1108_aclk_peri_get_clk(cru);
387 }
388
389 static ulong rv1108_hclk_peri_set_clk(struct rv1108_cru *cru, uint hz)
390 {
391         int src_clk_div;
392         ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
393
394         src_clk_div = DIV_ROUND_UP(parent_rate, hz) - 1;
395         assert(src_clk_div < 32);
396
397         rk_clrsetreg(&cru->clksel_con[23],
398                      HCLK_PERI_DIV_CON_MASK,
399                      (src_clk_div << HCLK_PERI_DIV_CON_SHIFT));
400
401         return rv1108_hclk_peri_get_clk(cru);
402 }
403
404 static ulong rv1108_pclk_peri_set_clk(struct rv1108_cru *cru, uint hz)
405 {
406         int src_clk_div;
407         ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
408
409         src_clk_div = DIV_ROUND_UP(parent_rate, hz) - 1;
410         assert(src_clk_div < 32);
411
412         rk_clrsetreg(&cru->clksel_con[23],
413                      PCLK_PERI_DIV_CON_MASK,
414                      (src_clk_div << PCLK_PERI_DIV_CON_SHIFT));
415
416         return rv1108_pclk_peri_get_clk(cru);
417 }
418
419 static ulong rv1108_i2c_get_clk(struct rv1108_cru *cru, ulong clk_id)
420 {
421         u32 div, con;
422
423         switch (clk_id) {
424         case SCLK_I2C0_PMU:
425                 con = readl(&cru->clksel_con[19]);
426                 div = bitfield_extract(con, CLK_I2C0_DIV_CON_SHIFT,
427                                        I2C_DIV_CON_WIDTH);
428                 break;
429         case SCLK_I2C1:
430                 con = readl(&cru->clksel_con[19]);
431                 div = bitfield_extract(con, CLK_I2C1_DIV_CON_SHIFT,
432                                        I2C_DIV_CON_WIDTH);
433                 break;
434         case SCLK_I2C2:
435                 con = readl(&cru->clksel_con[20]);
436                 div = bitfield_extract(con, CLK_I2C2_DIV_CON_SHIFT,
437                                        I2C_DIV_CON_WIDTH);
438                 break;
439         case SCLK_I2C3:
440                 con = readl(&cru->clksel_con[20]);
441                 div = bitfield_extract(con, CLK_I2C3_DIV_CON_SHIFT,
442                                        I2C_DIV_CON_WIDTH);
443                 break;
444         default:
445                 printf("do not support this i2c bus\n");
446                 return -EINVAL;
447         }
448
449         return DIV_TO_RATE(GPLL_HZ, div);
450 }
451
452 static ulong rv1108_i2c_set_clk(struct rv1108_cru *cru, ulong clk_id, uint hz)
453 {
454         int src_clk_div;
455
456         /* i2c0,4,8 src clock from ppll, i2c1,2,3,5,6,7 src clock from gpll*/
457         src_clk_div = GPLL_HZ / hz;
458         assert(src_clk_div - 1 <= 127);
459
460         switch (clk_id) {
461         case SCLK_I2C0_PMU:
462                 rk_clrsetreg(&cru->clksel_con[19],
463                              CLK_I2C0_DIV_CON_MASK | CLK_I2C1_PLL_SEL_MASK,
464                              (src_clk_div << CLK_I2C0_DIV_CON_SHIFT) |
465                              (CLK_I2C1_PLL_SEL_GPLL << CLK_I2C1_PLL_SEL_SHIFT));
466                 break;
467         case SCLK_I2C1:
468                 rk_clrsetreg(&cru->clksel_con[19],
469                              CLK_I2C1_DIV_CON_MASK | CLK_I2C1_PLL_SEL_MASK,
470                              (src_clk_div << CLK_I2C1_DIV_CON_SHIFT) |
471                              (CLK_I2C1_PLL_SEL_GPLL << CLK_I2C1_PLL_SEL_SHIFT));
472                 break;
473         case SCLK_I2C2:
474                 rk_clrsetreg(&cru->clksel_con[20],
475                              CLK_I2C2_DIV_CON_MASK | CLK_I2C3_PLL_SEL_MASK,
476                              (src_clk_div << CLK_I2C2_DIV_CON_SHIFT) |
477                              (CLK_I2C3_PLL_SEL_GPLL << CLK_I2C3_PLL_SEL_SHIFT));
478                 break;
479         case SCLK_I2C3:
480                 rk_clrsetreg(&cru->clksel_con[20],
481                              CLK_I2C3_DIV_CON_MASK | CLK_I2C3_PLL_SEL_MASK,
482                              (src_clk_div << CLK_I2C3_DIV_CON_SHIFT) |
483                              (CLK_I2C3_PLL_SEL_GPLL << CLK_I2C3_PLL_SEL_SHIFT));
484                 break;
485         default:
486                 printf("do not support this i2c bus\n");
487                 return -EINVAL;
488         }
489
490         return rv1108_i2c_get_clk(cru, clk_id);
491 }
492
493 static ulong rv1108_mmc_get_clk(struct rv1108_cru *cru)
494 {
495         u32 div, con;
496         ulong mmc_clk;
497
498         con = readl(&cru->clksel_con[26]);
499         div = bitfield_extract(con, EMMC_CLK_DIV_SHIFT, 8);
500
501         con = readl(&cru->clksel_con[25]);
502
503         if ((con & EMMC_PLL_SEL_MASK) >> EMMC_PLL_SEL_SHIFT == EMMC_PLL_SEL_OSC)
504                 mmc_clk = DIV_TO_RATE(OSC_HZ, div) / 2;
505         else
506                 mmc_clk = DIV_TO_RATE(GPLL_HZ, div) / 2;
507
508         debug("%s div %d get_clk %ld\n", __func__, div, mmc_clk);
509         return mmc_clk;
510 }
511
512 static ulong rv1108_mmc_set_clk(struct rv1108_cru *cru, ulong rate)
513 {
514         int div;
515         u32 pll_rate;
516
517         div = DIV_ROUND_UP(rkclk_pll_get_rate(cru, CLK_GENERAL), rate);
518
519         if (div < 127) {
520                 debug("%s source gpll\n", __func__);
521                 rk_clrsetreg(&cru->clksel_con[25], EMMC_PLL_SEL_MASK,
522                             (EMMC_PLL_SEL_GPLL << EMMC_PLL_SEL_SHIFT));
523                 pll_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
524         } else {
525                 debug("%s source 24m\n", __func__);
526                 rk_clrsetreg(&cru->clksel_con[25], EMMC_PLL_SEL_MASK,
527                             (EMMC_PLL_SEL_OSC << EMMC_PLL_SEL_SHIFT));
528                 pll_rate = OSC_HZ;
529         }
530
531         div = DIV_ROUND_UP(pll_rate / 2, rate);
532         rk_clrsetreg(&cru->clksel_con[26], EMMC_CLK_DIV_MASK,
533                     ((div - 1) << EMMC_CLK_DIV_SHIFT));
534
535         debug("%s set_rate %ld div %d\n", __func__,  rate, div);
536
537         return DIV_TO_RATE(pll_rate, div);
538 }
539
540 static ulong rv1108_clk_get_rate(struct clk *clk)
541 {
542         struct rv1108_clk_priv *priv = dev_get_priv(clk->dev);
543
544         switch (clk->id) {
545         case 0 ... 63:
546                 return rkclk_pll_get_rate(priv->cru, clk->id);
547         case SCLK_SARADC:
548                 return rv1108_saradc_get_clk(priv->cru);
549         case ACLK_VIO0:
550                 return rv1108_aclk_vio0_get_clk(priv->cru);
551         case ACLK_VIO1:
552                 return rv1108_aclk_vio1_get_clk(priv->cru);
553         case DCLK_VOP:
554                 return rv1108_dclk_vop_get_clk(priv->cru);
555         case ACLK_PRE:
556                 return rv1108_aclk_bus_get_clk(priv->cru);
557         case ACLK_PERI:
558                 return rv1108_aclk_peri_get_clk(priv->cru);
559         case HCLK_PERI:
560                 return rv1108_hclk_peri_get_clk(priv->cru);
561         case PCLK_PERI:
562                 return rv1108_pclk_peri_get_clk(priv->cru);
563         case SCLK_I2C0_PMU:
564         case SCLK_I2C1:
565         case SCLK_I2C2:
566         case SCLK_I2C3:
567                 return rv1108_i2c_get_clk(priv->cru, clk->id);
568         case HCLK_EMMC:
569         case SCLK_EMMC:
570         case SCLK_EMMC_SAMPLE:
571                 return rv1108_mmc_get_clk(priv->cru);
572         default:
573                 return -ENOENT;
574         }
575 }
576
577 static ulong rv1108_clk_set_rate(struct clk *clk, ulong rate)
578 {
579         struct rv1108_clk_priv *priv = dev_get_priv(clk->dev);
580         ulong new_rate;
581
582         switch (clk->id) {
583         case SCLK_MAC:
584                 new_rate = rv1108_mac_set_clk(priv->cru, rate);
585                 break;
586         case SCLK_SFC:
587                 new_rate = rv1108_sfc_set_clk(priv->cru, rate);
588                 break;
589         case SCLK_SARADC:
590                 new_rate = rv1108_saradc_set_clk(priv->cru, rate);
591                 break;
592         case ACLK_VIO0:
593                 new_rate = rv1108_aclk_vio0_set_clk(priv->cru, rate);
594                 break;
595         case ACLK_VIO1:
596                 new_rate = rv1108_aclk_vio1_set_clk(priv->cru, rate);
597                 break;
598         case DCLK_VOP:
599                 new_rate = rv1108_dclk_vop_set_clk(priv->cru, rate);
600                 break;
601         case ACLK_PRE:
602                 new_rate = rv1108_aclk_bus_set_clk(priv->cru, rate);
603                 break;
604         case ACLK_PERI:
605                 new_rate = rv1108_aclk_peri_set_clk(priv->cru, rate);
606                 break;
607         case HCLK_PERI:
608                 new_rate = rv1108_hclk_peri_set_clk(priv->cru, rate);
609                 break;
610         case PCLK_PERI:
611                 new_rate = rv1108_pclk_peri_set_clk(priv->cru, rate);
612                 break;
613         case SCLK_I2C0_PMU:
614         case SCLK_I2C1:
615         case SCLK_I2C2:
616         case SCLK_I2C3:
617                 new_rate = rv1108_i2c_set_clk(priv->cru, clk->id, rate);
618                 break;
619         case HCLK_EMMC:
620         case SCLK_EMMC:
621                 new_rate = rv1108_mmc_set_clk(priv->cru, rate);
622                 break;
623         default:
624                 return -ENOENT;
625         }
626
627         return new_rate;
628 }
629
630 static const struct clk_ops rv1108_clk_ops = {
631         .get_rate       = rv1108_clk_get_rate,
632         .set_rate       = rv1108_clk_set_rate,
633 };
634
635 static void rkclk_init(struct rv1108_cru *cru)
636 {
637         unsigned int apll, dpll, gpll;
638         unsigned int aclk_bus, aclk_peri, hclk_peri, pclk_peri;
639
640         aclk_bus = rv1108_aclk_bus_set_clk(cru, ACLK_BUS_HZ / 2);
641         aclk_peri = rv1108_aclk_peri_set_clk(cru, ACLK_PERI_HZ / 2);
642         hclk_peri = rv1108_hclk_peri_set_clk(cru, HCLK_PERI_HZ / 2);
643         pclk_peri = rv1108_pclk_peri_set_clk(cru, PCLK_PERI_HZ / 2);
644         rv1108_aclk_vio0_set_clk(cru, 297000000);
645         rv1108_aclk_vio1_set_clk(cru, 297000000);
646
647         /* configure apll */
648         rkclk_set_pll(cru, CLK_ARM, &apll_init_cfg);
649         rkclk_set_pll(cru, CLK_GENERAL, &gpll_init_cfg);
650         aclk_bus = rv1108_aclk_bus_set_clk(cru, ACLK_BUS_HZ);
651         aclk_peri = rv1108_aclk_peri_set_clk(cru, ACLK_PERI_HZ);
652         hclk_peri = rv1108_hclk_peri_set_clk(cru, HCLK_PERI_HZ);
653         pclk_peri = rv1108_pclk_peri_set_clk(cru, PCLK_PERI_HZ);
654
655         apll = rkclk_pll_get_rate(cru, CLK_ARM);
656         dpll = rkclk_pll_get_rate(cru, CLK_DDR);
657         gpll = rkclk_pll_get_rate(cru, CLK_GENERAL);
658
659         rk_clrsetreg(&cru->clksel_con[0], CORE_CLK_DIV_MASK,
660                      0 << MAC_CLK_DIV_SHIFT);
661
662         printf("APLL: %d DPLL:%d GPLL:%d\n", apll, dpll, gpll);
663         printf("ACLK_BUS: %d ACLK_PERI:%d HCLK_PERI:%d PCLK_PERI:%d\n",
664                aclk_bus, aclk_peri, hclk_peri, pclk_peri);
665 }
666
667 static int rv1108_clk_of_to_plat(struct udevice *dev)
668 {
669         struct rv1108_clk_priv *priv = dev_get_priv(dev);
670
671         priv->cru = dev_read_addr_ptr(dev);
672
673         return 0;
674 }
675
676 static int rv1108_clk_probe(struct udevice *dev)
677 {
678         struct rv1108_clk_priv *priv = dev_get_priv(dev);
679
680         rkclk_init(priv->cru);
681
682         return 0;
683 }
684
685 static int rv1108_clk_bind(struct udevice *dev)
686 {
687         int ret;
688         struct udevice *sys_child;
689         struct sysreset_reg *priv;
690
691         /* The reset driver does not have a device node, so bind it here */
692         ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset",
693                                  &sys_child);
694         if (ret) {
695                 debug("Warning: No sysreset driver: ret=%d\n", ret);
696         } else {
697                 priv = malloc(sizeof(struct sysreset_reg));
698                 priv->glb_srst_fst_value = offsetof(struct rv1108_cru,
699                                                     glb_srst_fst_val);
700                 priv->glb_srst_snd_value = offsetof(struct rv1108_cru,
701                                                     glb_srst_snd_val);
702                 dev_set_priv(sys_child, priv);
703         }
704
705 #if CONFIG_IS_ENABLED(RESET_ROCKCHIP)
706         ret = offsetof(struct rv1108_cru, softrst_con[0]);
707         ret = rockchip_reset_bind(dev, ret, 13);
708         if (ret)
709                 debug("Warning: software reset driver bind failed\n");
710 #endif
711
712         return 0;
713 }
714
715 static const struct udevice_id rv1108_clk_ids[] = {
716         { .compatible = "rockchip,rv1108-cru" },
717         { }
718 };
719
720 U_BOOT_DRIVER(clk_rv1108) = {
721         .name           = "clk_rv1108",
722         .id             = UCLASS_CLK,
723         .of_match       = rv1108_clk_ids,
724         .priv_auto      = sizeof(struct rv1108_clk_priv),
725         .ops            = &rv1108_clk_ops,
726         .bind           = rv1108_clk_bind,
727         .of_to_plat     = rv1108_clk_of_to_plat,
728         .probe          = rv1108_clk_probe,
729 };