SPDX: Convert all of our single license tags to Linux Kernel style
[oweals/u-boot.git] / drivers / clk / rockchip / clk_rk3188.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * (C) Copyright 2015 Google, Inc
4  * (C) Copyright 2016 Heiko Stuebner <heiko@sntech.de>
5  */
6
7 #include <common.h>
8 #include <clk-uclass.h>
9 #include <dm.h>
10 #include <dt-structs.h>
11 #include <errno.h>
12 #include <mapmem.h>
13 #include <syscon.h>
14 #include <asm/io.h>
15 #include <asm/arch/clock.h>
16 #include <asm/arch/cru_rk3188.h>
17 #include <asm/arch/grf_rk3188.h>
18 #include <asm/arch/hardware.h>
19 #include <dt-bindings/clock/rk3188-cru.h>
20 #include <dm/device-internal.h>
21 #include <dm/lists.h>
22 #include <dm/uclass-internal.h>
23 #include <linux/log2.h>
24
25 enum rk3188_clk_type {
26         RK3188_CRU,
27         RK3188A_CRU,
28 };
29
30 struct rk3188_clk_plat {
31 #if CONFIG_IS_ENABLED(OF_PLATDATA)
32         struct dtd_rockchip_rk3188_cru dtd;
33 #endif
34 };
35
36 struct pll_div {
37         u32 nr;
38         u32 nf;
39         u32 no;
40 };
41
42 enum {
43         VCO_MAX_HZ      = 2200U * 1000000,
44         VCO_MIN_HZ      = 440 * 1000000,
45         OUTPUT_MAX_HZ   = 2200U * 1000000,
46         OUTPUT_MIN_HZ   = 30 * 1000000,
47         FREF_MAX_HZ     = 2200U * 1000000,
48         FREF_MIN_HZ     = 30 * 1000,
49 };
50
51 enum {
52         /* PLL CON0 */
53         PLL_OD_MASK             = 0x0f,
54
55         /* PLL CON1 */
56         PLL_NF_MASK             = 0x1fff,
57
58         /* PLL CON2 */
59         PLL_BWADJ_MASK          = 0x0fff,
60
61         /* PLL CON3 */
62         PLL_RESET_SHIFT         = 5,
63
64         /* GRF_SOC_STATUS0 */
65         SOCSTS_DPLL_LOCK        = 1 << 5,
66         SOCSTS_APLL_LOCK        = 1 << 6,
67         SOCSTS_CPLL_LOCK        = 1 << 7,
68         SOCSTS_GPLL_LOCK        = 1 << 8,
69 };
70
71 #define DIV_TO_RATE(input_rate, div)    ((input_rate) / ((div) + 1))
72
73 #define PLL_DIVISORS(hz, _nr, _no) {\
74         .nr = _nr, .nf = (u32)((u64)hz * _nr * _no / OSC_HZ), .no = _no};\
75         _Static_assert(((u64)hz * _nr * _no / OSC_HZ) * OSC_HZ /\
76                        (_nr * _no) == hz, #hz "Hz cannot be hit with PLL "\
77                        "divisors on line " __stringify(__LINE__));
78
79 /* Keep divisors as low as possible to reduce jitter and power usage */
80 #ifdef CONFIG_SPL_BUILD
81 static const struct pll_div gpll_init_cfg = PLL_DIVISORS(GPLL_HZ, 2, 2);
82 static const struct pll_div cpll_init_cfg = PLL_DIVISORS(CPLL_HZ, 1, 2);
83 #endif
84
85 static int rkclk_set_pll(struct rk3188_cru *cru, enum rk_clk_id clk_id,
86                          const struct pll_div *div, bool has_bwadj)
87 {
88         int pll_id = rk_pll_id(clk_id);
89         struct rk3188_pll *pll = &cru->pll[pll_id];
90         /* All PLLs have same VCO and output frequency range restrictions. */
91         uint vco_hz = OSC_HZ / 1000 * div->nf / div->nr * 1000;
92         uint output_hz = vco_hz / div->no;
93
94         debug("PLL at %x: nf=%d, nr=%d, no=%d, vco=%u Hz, output=%u Hz\n",
95               (uint)pll, div->nf, div->nr, div->no, vco_hz, output_hz);
96         assert(vco_hz >= VCO_MIN_HZ && vco_hz <= VCO_MAX_HZ &&
97                output_hz >= OUTPUT_MIN_HZ && output_hz <= OUTPUT_MAX_HZ &&
98                (div->no == 1 || !(div->no % 2)));
99
100         /* enter reset */
101         rk_setreg(&pll->con3, 1 << PLL_RESET_SHIFT);
102
103         rk_clrsetreg(&pll->con0,
104                      CLKR_MASK << CLKR_SHIFT | PLL_OD_MASK,
105                      ((div->nr - 1) << CLKR_SHIFT) | (div->no - 1));
106         rk_clrsetreg(&pll->con1, CLKF_MASK, div->nf - 1);
107
108         if (has_bwadj)
109                 rk_clrsetreg(&pll->con2, PLL_BWADJ_MASK, (div->nf >> 1) - 1);
110
111         udelay(10);
112
113         /* return from reset */
114         rk_clrreg(&pll->con3, 1 << PLL_RESET_SHIFT);
115
116         return 0;
117 }
118
119 static int rkclk_configure_ddr(struct rk3188_cru *cru, struct rk3188_grf *grf,
120                                unsigned int hz, bool has_bwadj)
121 {
122         static const struct pll_div dpll_cfg[] = {
123                 {.nf = 75, .nr = 1, .no = 6},
124                 {.nf = 400, .nr = 9, .no = 2},
125                 {.nf = 500, .nr = 9, .no = 2},
126                 {.nf = 100, .nr = 3, .no = 1},
127         };
128         int cfg;
129
130         switch (hz) {
131         case 300000000:
132                 cfg = 0;
133                 break;
134         case 533000000: /* actually 533.3P MHz */
135                 cfg = 1;
136                 break;
137         case 666000000: /* actually 666.6P MHz */
138                 cfg = 2;
139                 break;
140         case 800000000:
141                 cfg = 3;
142                 break;
143         default:
144                 debug("Unsupported SDRAM frequency");
145                 return -EINVAL;
146         }
147
148         /* pll enter slow-mode */
149         rk_clrsetreg(&cru->cru_mode_con, DPLL_MODE_MASK << DPLL_MODE_SHIFT,
150                      DPLL_MODE_SLOW << DPLL_MODE_SHIFT);
151
152         rkclk_set_pll(cru, CLK_DDR, &dpll_cfg[cfg], has_bwadj);
153
154         /* wait for pll lock */
155         while (!(readl(&grf->soc_status0) & SOCSTS_DPLL_LOCK))
156                 udelay(1);
157
158         /* PLL enter normal-mode */
159         rk_clrsetreg(&cru->cru_mode_con, DPLL_MODE_MASK << DPLL_MODE_SHIFT,
160                      DPLL_MODE_NORMAL << DPLL_MODE_SHIFT);
161
162         return 0;
163 }
164
165 static int rkclk_configure_cpu(struct rk3188_cru *cru, struct rk3188_grf *grf,
166                               unsigned int hz, bool has_bwadj)
167 {
168         static const struct pll_div apll_cfg[] = {
169                 {.nf = 50, .nr = 1, .no = 2},
170                 {.nf = 67, .nr = 1, .no = 1},
171         };
172         int div_core_peri, div_aclk_core, cfg;
173
174         /*
175          * We support two possible frequencies, the safe 600MHz
176          * which will work with default pmic settings and will
177          * be set in SPL to get away from the 24MHz default and
178          * the maximum of 1.6Ghz, which boards can set if they
179          * were able to get pmic support for it.
180          */
181         switch (hz) {
182         case APLL_SAFE_HZ:
183                 cfg = 0;
184                 div_core_peri = 1;
185                 div_aclk_core = 3;
186                 break;
187         case APLL_HZ:
188                 cfg = 1;
189                 div_core_peri = 2;
190                 div_aclk_core = 3;
191                 break;
192         default:
193                 debug("Unsupported ARMCLK frequency");
194                 return -EINVAL;
195         }
196
197         /* pll enter slow-mode */
198         rk_clrsetreg(&cru->cru_mode_con, APLL_MODE_MASK << APLL_MODE_SHIFT,
199                      APLL_MODE_SLOW << APLL_MODE_SHIFT);
200
201         rkclk_set_pll(cru, CLK_ARM, &apll_cfg[cfg], has_bwadj);
202
203         /* waiting for pll lock */
204         while (!(readl(&grf->soc_status0) & SOCSTS_APLL_LOCK))
205                 udelay(1);
206
207         /* Set divider for peripherals attached to the cpu core. */
208         rk_clrsetreg(&cru->cru_clksel_con[0],
209                 CORE_PERI_DIV_MASK << CORE_PERI_DIV_SHIFT,
210                 div_core_peri << CORE_PERI_DIV_SHIFT);
211
212         /* set up dependent divisor for aclk_core */
213         rk_clrsetreg(&cru->cru_clksel_con[1],
214                 CORE_ACLK_DIV_MASK << CORE_ACLK_DIV_SHIFT,
215                 div_aclk_core << CORE_ACLK_DIV_SHIFT);
216
217         /* PLL enter normal-mode */
218         rk_clrsetreg(&cru->cru_mode_con, APLL_MODE_MASK << APLL_MODE_SHIFT,
219                      APLL_MODE_NORMAL << APLL_MODE_SHIFT);
220
221         return hz;
222 }
223
224 /* Get pll rate by id */
225 static uint32_t rkclk_pll_get_rate(struct rk3188_cru *cru,
226                                    enum rk_clk_id clk_id)
227 {
228         uint32_t nr, no, nf;
229         uint32_t con;
230         int pll_id = rk_pll_id(clk_id);
231         struct rk3188_pll *pll = &cru->pll[pll_id];
232         static u8 clk_shift[CLK_COUNT] = {
233                 0xff, APLL_MODE_SHIFT, DPLL_MODE_SHIFT, CPLL_MODE_SHIFT,
234                 GPLL_MODE_SHIFT
235         };
236         uint shift;
237
238         con = readl(&cru->cru_mode_con);
239         shift = clk_shift[clk_id];
240         switch ((con >> shift) & APLL_MODE_MASK) {
241         case APLL_MODE_SLOW:
242                 return OSC_HZ;
243         case APLL_MODE_NORMAL:
244                 /* normal mode */
245                 con = readl(&pll->con0);
246                 no = ((con >> CLKOD_SHIFT) & CLKOD_MASK) + 1;
247                 nr = ((con >> CLKR_SHIFT) & CLKR_MASK) + 1;
248                 con = readl(&pll->con1);
249                 nf = ((con >> CLKF_SHIFT) & CLKF_MASK) + 1;
250
251                 return (24 * nf / (nr * no)) * 1000000;
252         case APLL_MODE_DEEP:
253         default:
254                 return 32768;
255         }
256 }
257
258 static ulong rockchip_mmc_get_clk(struct rk3188_cru *cru, uint gclk_rate,
259                                   int periph)
260 {
261         uint div;
262         u32 con;
263
264         switch (periph) {
265         case HCLK_EMMC:
266         case SCLK_EMMC:
267                 con = readl(&cru->cru_clksel_con[12]);
268                 div = (con >> EMMC_DIV_SHIFT) & EMMC_DIV_MASK;
269                 break;
270         case HCLK_SDMMC:
271         case SCLK_SDMMC:
272                 con = readl(&cru->cru_clksel_con[11]);
273                 div = (con >> MMC0_DIV_SHIFT) & MMC0_DIV_MASK;
274                 break;
275         case HCLK_SDIO:
276         case SCLK_SDIO:
277                 con = readl(&cru->cru_clksel_con[12]);
278                 div = (con >> SDIO_DIV_SHIFT) & SDIO_DIV_MASK;
279                 break;
280         default:
281                 return -EINVAL;
282         }
283
284         return DIV_TO_RATE(gclk_rate, div) / 2;
285 }
286
287 static ulong rockchip_mmc_set_clk(struct rk3188_cru *cru, uint gclk_rate,
288                                   int  periph, uint freq)
289 {
290         int src_clk_div;
291
292         debug("%s: gclk_rate=%u\n", __func__, gclk_rate);
293         /* mmc clock defaulg div 2 internal, need provide double in cru */
294         src_clk_div = DIV_ROUND_UP(gclk_rate / 2, freq) - 1;
295         assert(src_clk_div <= 0x3f);
296
297         switch (periph) {
298         case HCLK_EMMC:
299         case SCLK_EMMC:
300                 rk_clrsetreg(&cru->cru_clksel_con[12],
301                              EMMC_DIV_MASK << EMMC_DIV_SHIFT,
302                              src_clk_div << EMMC_DIV_SHIFT);
303                 break;
304         case HCLK_SDMMC:
305         case SCLK_SDMMC:
306                 rk_clrsetreg(&cru->cru_clksel_con[11],
307                              MMC0_DIV_MASK << MMC0_DIV_SHIFT,
308                              src_clk_div << MMC0_DIV_SHIFT);
309                 break;
310         case HCLK_SDIO:
311         case SCLK_SDIO:
312                 rk_clrsetreg(&cru->cru_clksel_con[12],
313                              SDIO_DIV_MASK << SDIO_DIV_SHIFT,
314                              src_clk_div << SDIO_DIV_SHIFT);
315                 break;
316         default:
317                 return -EINVAL;
318         }
319
320         return rockchip_mmc_get_clk(cru, gclk_rate, periph);
321 }
322
323 static ulong rockchip_spi_get_clk(struct rk3188_cru *cru, uint gclk_rate,
324                                   int periph)
325 {
326         uint div;
327         u32 con;
328
329         switch (periph) {
330         case SCLK_SPI0:
331                 con = readl(&cru->cru_clksel_con[25]);
332                 div = (con >> SPI0_DIV_SHIFT) & SPI0_DIV_MASK;
333                 break;
334         case SCLK_SPI1:
335                 con = readl(&cru->cru_clksel_con[25]);
336                 div = (con >> SPI1_DIV_SHIFT) & SPI1_DIV_MASK;
337                 break;
338         default:
339                 return -EINVAL;
340         }
341
342         return DIV_TO_RATE(gclk_rate, div);
343 }
344
345 static ulong rockchip_spi_set_clk(struct rk3188_cru *cru, uint gclk_rate,
346                                   int periph, uint freq)
347 {
348         int src_clk_div = DIV_ROUND_UP(gclk_rate, freq) - 1;
349
350         assert(src_clk_div < 128);
351         switch (periph) {
352         case SCLK_SPI0:
353                 assert(src_clk_div <= SPI0_DIV_MASK);
354                 rk_clrsetreg(&cru->cru_clksel_con[25],
355                              SPI0_DIV_MASK << SPI0_DIV_SHIFT,
356                              src_clk_div << SPI0_DIV_SHIFT);
357                 break;
358         case SCLK_SPI1:
359                 assert(src_clk_div <= SPI1_DIV_MASK);
360                 rk_clrsetreg(&cru->cru_clksel_con[25],
361                              SPI1_DIV_MASK << SPI1_DIV_SHIFT,
362                              src_clk_div << SPI1_DIV_SHIFT);
363                 break;
364         default:
365                 return -EINVAL;
366         }
367
368         return rockchip_spi_get_clk(cru, gclk_rate, periph);
369 }
370
371 #ifdef CONFIG_SPL_BUILD
372 static void rkclk_init(struct rk3188_cru *cru, struct rk3188_grf *grf,
373                        bool has_bwadj)
374 {
375         u32 aclk_div, hclk_div, pclk_div, h2p_div;
376
377         /* pll enter slow-mode */
378         rk_clrsetreg(&cru->cru_mode_con,
379                      GPLL_MODE_MASK << GPLL_MODE_SHIFT |
380                      CPLL_MODE_MASK << CPLL_MODE_SHIFT,
381                      GPLL_MODE_SLOW << GPLL_MODE_SHIFT |
382                      CPLL_MODE_SLOW << CPLL_MODE_SHIFT);
383
384         /* init pll */
385         rkclk_set_pll(cru, CLK_GENERAL, &gpll_init_cfg, has_bwadj);
386         rkclk_set_pll(cru, CLK_CODEC, &cpll_init_cfg, has_bwadj);
387
388         /* waiting for pll lock */
389         while ((readl(&grf->soc_status0) &
390                         (SOCSTS_CPLL_LOCK | SOCSTS_GPLL_LOCK)) !=
391                         (SOCSTS_CPLL_LOCK | SOCSTS_GPLL_LOCK))
392                 udelay(1);
393
394         /*
395          * cpu clock pll source selection and
396          * reparent aclk_cpu_pre from apll to gpll
397          * set up dependent divisors for PCLK/HCLK and ACLK clocks.
398          */
399         aclk_div = DIV_ROUND_UP(GPLL_HZ, CPU_ACLK_HZ) - 1;
400         assert((aclk_div + 1) * CPU_ACLK_HZ == GPLL_HZ && aclk_div <= 0x1f);
401
402         rk_clrsetreg(&cru->cru_clksel_con[0],
403                      CPU_ACLK_PLL_MASK << CPU_ACLK_PLL_SHIFT |
404                      A9_CPU_DIV_MASK << A9_CPU_DIV_SHIFT,
405                      CPU_ACLK_PLL_SELECT_GPLL << CPU_ACLK_PLL_SHIFT |
406                      aclk_div << A9_CPU_DIV_SHIFT);
407
408         hclk_div = ilog2(CPU_ACLK_HZ / CPU_HCLK_HZ);
409         assert((1 << hclk_div) * CPU_HCLK_HZ == CPU_ACLK_HZ && hclk_div < 0x3);
410         pclk_div = ilog2(CPU_ACLK_HZ / CPU_PCLK_HZ);
411         assert((1 << pclk_div) * CPU_PCLK_HZ == CPU_ACLK_HZ && pclk_div < 0x4);
412         h2p_div = ilog2(CPU_HCLK_HZ / CPU_H2P_HZ);
413         assert((1 << h2p_div) * CPU_H2P_HZ == CPU_HCLK_HZ && pclk_div < 0x3);
414
415         rk_clrsetreg(&cru->cru_clksel_con[1],
416                      AHB2APB_DIV_MASK << AHB2APB_DIV_SHIFT |
417                      CPU_PCLK_DIV_MASK << CPU_PCLK_DIV_SHIFT |
418                      CPU_HCLK_DIV_MASK << CPU_HCLK_DIV_SHIFT,
419                      h2p_div << AHB2APB_DIV_SHIFT |
420                      pclk_div << CPU_PCLK_DIV_SHIFT |
421                      hclk_div << CPU_HCLK_DIV_SHIFT);
422
423         /*
424          * peri clock pll source selection and
425          * set up dependent divisors for PCLK/HCLK and ACLK clocks.
426          */
427         aclk_div = GPLL_HZ / PERI_ACLK_HZ - 1;
428         assert((aclk_div + 1) * PERI_ACLK_HZ == GPLL_HZ && aclk_div < 0x1f);
429
430         hclk_div = ilog2(PERI_ACLK_HZ / PERI_HCLK_HZ);
431         assert((1 << hclk_div) * PERI_HCLK_HZ ==
432                 PERI_ACLK_HZ && (hclk_div < 0x4));
433
434         pclk_div = ilog2(PERI_ACLK_HZ / PERI_PCLK_HZ);
435         assert((1 << pclk_div) * PERI_PCLK_HZ ==
436                 PERI_ACLK_HZ && (pclk_div < 0x4));
437
438         rk_clrsetreg(&cru->cru_clksel_con[10],
439                      PERI_PCLK_DIV_MASK << PERI_PCLK_DIV_SHIFT |
440                      PERI_HCLK_DIV_MASK << PERI_HCLK_DIV_SHIFT |
441                      PERI_ACLK_DIV_MASK << PERI_ACLK_DIV_SHIFT,
442                      PERI_SEL_GPLL << PERI_SEL_PLL_SHIFT |
443                      pclk_div << PERI_PCLK_DIV_SHIFT |
444                      hclk_div << PERI_HCLK_DIV_SHIFT |
445                      aclk_div << PERI_ACLK_DIV_SHIFT);
446
447         /* PLL enter normal-mode */
448         rk_clrsetreg(&cru->cru_mode_con,
449                      GPLL_MODE_MASK << GPLL_MODE_SHIFT |
450                      CPLL_MODE_MASK << CPLL_MODE_SHIFT,
451                      GPLL_MODE_NORMAL << GPLL_MODE_SHIFT |
452                      CPLL_MODE_NORMAL << CPLL_MODE_SHIFT);
453
454         rockchip_mmc_set_clk(cru, PERI_HCLK_HZ, HCLK_SDMMC, 16000000);
455 }
456 #endif
457
458 static ulong rk3188_clk_get_rate(struct clk *clk)
459 {
460         struct rk3188_clk_priv *priv = dev_get_priv(clk->dev);
461         ulong new_rate, gclk_rate;
462
463         gclk_rate = rkclk_pll_get_rate(priv->cru, CLK_GENERAL);
464         switch (clk->id) {
465         case 1 ... 4:
466                 new_rate = rkclk_pll_get_rate(priv->cru, clk->id);
467                 break;
468         case HCLK_EMMC:
469         case HCLK_SDMMC:
470         case HCLK_SDIO:
471         case SCLK_EMMC:
472         case SCLK_SDMMC:
473         case SCLK_SDIO:
474                 new_rate = rockchip_mmc_get_clk(priv->cru, PERI_HCLK_HZ,
475                                                 clk->id);
476                 break;
477         case SCLK_SPI0:
478         case SCLK_SPI1:
479                 new_rate = rockchip_spi_get_clk(priv->cru, PERI_PCLK_HZ,
480                                                 clk->id);
481                 break;
482         case PCLK_I2C0:
483         case PCLK_I2C1:
484         case PCLK_I2C2:
485         case PCLK_I2C3:
486         case PCLK_I2C4:
487                 return gclk_rate;
488         default:
489                 return -ENOENT;
490         }
491
492         return new_rate;
493 }
494
495 static ulong rk3188_clk_set_rate(struct clk *clk, ulong rate)
496 {
497         struct rk3188_clk_priv *priv = dev_get_priv(clk->dev);
498         struct rk3188_cru *cru = priv->cru;
499         ulong new_rate;
500
501         switch (clk->id) {
502         case PLL_APLL:
503                 new_rate = rkclk_configure_cpu(priv->cru, priv->grf, rate,
504                                                priv->has_bwadj);
505                 break;
506         case CLK_DDR:
507                 new_rate = rkclk_configure_ddr(priv->cru, priv->grf, rate,
508                                                priv->has_bwadj);
509                 break;
510         case HCLK_EMMC:
511         case HCLK_SDMMC:
512         case HCLK_SDIO:
513         case SCLK_EMMC:
514         case SCLK_SDMMC:
515         case SCLK_SDIO:
516                 new_rate = rockchip_mmc_set_clk(cru, PERI_HCLK_HZ,
517                                                 clk->id, rate);
518                 break;
519         case SCLK_SPI0:
520         case SCLK_SPI1:
521                 new_rate = rockchip_spi_set_clk(cru, PERI_PCLK_HZ,
522                                                 clk->id, rate);
523                 break;
524         default:
525                 return -ENOENT;
526         }
527
528         return new_rate;
529 }
530
531 static struct clk_ops rk3188_clk_ops = {
532         .get_rate       = rk3188_clk_get_rate,
533         .set_rate       = rk3188_clk_set_rate,
534 };
535
536 static int rk3188_clk_ofdata_to_platdata(struct udevice *dev)
537 {
538 #if !CONFIG_IS_ENABLED(OF_PLATDATA)
539         struct rk3188_clk_priv *priv = dev_get_priv(dev);
540
541         priv->cru = dev_read_addr_ptr(dev);
542 #endif
543
544         return 0;
545 }
546
547 static int rk3188_clk_probe(struct udevice *dev)
548 {
549         struct rk3188_clk_priv *priv = dev_get_priv(dev);
550         enum rk3188_clk_type type = dev_get_driver_data(dev);
551
552         priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
553         if (IS_ERR(priv->grf))
554                 return PTR_ERR(priv->grf);
555         priv->has_bwadj = (type == RK3188A_CRU) ? 1 : 0;
556
557 #ifdef CONFIG_SPL_BUILD
558 #if CONFIG_IS_ENABLED(OF_PLATDATA)
559         struct rk3188_clk_plat *plat = dev_get_platdata(dev);
560
561         priv->cru = map_sysmem(plat->dtd.reg[0], plat->dtd.reg[1]);
562 #endif
563
564         rkclk_init(priv->cru, priv->grf, priv->has_bwadj);
565 #endif
566
567         return 0;
568 }
569
570 static int rk3188_clk_bind(struct udevice *dev)
571 {
572         int ret;
573         struct udevice *sys_child;
574         struct sysreset_reg *priv;
575
576         /* The reset driver does not have a device node, so bind it here */
577         ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset",
578                                  &sys_child);
579         if (ret) {
580                 debug("Warning: No sysreset driver: ret=%d\n", ret);
581         } else {
582                 priv = malloc(sizeof(struct sysreset_reg));
583                 priv->glb_srst_fst_value = offsetof(struct rk3188_cru,
584                                                     cru_glb_srst_fst_value);
585                 priv->glb_srst_snd_value = offsetof(struct rk3188_cru,
586                                                     cru_glb_srst_snd_value);
587                 sys_child->priv = priv;
588         }
589
590 #if CONFIG_IS_ENABLED(CONFIG_RESET_ROCKCHIP)
591         ret = offsetof(struct rk3188_cru, cru_softrst_con[0]);
592         ret = rockchip_reset_bind(dev, ret, 9);
593         if (ret)
594                 debug("Warning: software reset driver bind faile\n");
595 #endif
596
597         return 0;
598 }
599
600 static const struct udevice_id rk3188_clk_ids[] = {
601         { .compatible = "rockchip,rk3188-cru", .data = RK3188_CRU },
602         { .compatible = "rockchip,rk3188a-cru", .data = RK3188A_CRU },
603         { }
604 };
605
606 U_BOOT_DRIVER(rockchip_rk3188_cru) = {
607         .name                   = "rockchip_rk3188_cru",
608         .id                     = UCLASS_CLK,
609         .of_match               = rk3188_clk_ids,
610         .priv_auto_alloc_size   = sizeof(struct rk3188_clk_priv),
611         .platdata_auto_alloc_size = sizeof(struct rk3188_clk_plat),
612         .ops                    = &rk3188_clk_ops,
613         .bind                   = rk3188_clk_bind,
614         .ofdata_to_platdata     = rk3188_clk_ofdata_to_platdata,
615         .probe                  = rk3188_clk_probe,
616 };