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