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