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