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