]> git.sur5r.net Git - u-boot/blob - drivers/clk/rockchip/clk_rk3328.c
Merge git://git.denx.de/u-boot-sunxi
[u-boot] / drivers / clk / rockchip / clk_rk3328.c
1 /*
2  * (C) Copyright 2017 Rockchip Electronics Co., Ltd
3  *
4  * SPDX-License-Identifier:     GPL-2.0
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/arch/clock.h>
14 #include <asm/arch/cru_rk3328.h>
15 #include <asm/arch/hardware.h>
16 #include <asm/io.h>
17 #include <dm/lists.h>
18 #include <dt-bindings/clock/rk3328-cru.h>
19
20 DECLARE_GLOBAL_DATA_PTR;
21
22 struct pll_div {
23         u32 refdiv;
24         u32 fbdiv;
25         u32 postdiv1;
26         u32 postdiv2;
27         u32 frac;
28 };
29
30 #define RATE_TO_DIV(input_rate, output_rate) \
31         ((input_rate) / (output_rate) - 1);
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
39 static const struct pll_div gpll_init_cfg = PLL_DIVISORS(GPLL_HZ, 1, 4, 1);
40 static const struct pll_div cpll_init_cfg = PLL_DIVISORS(CPLL_HZ, 2, 2, 1);
41
42 static const struct pll_div apll_816_cfg = PLL_DIVISORS(816 * MHz, 1, 2, 1);
43 static const struct pll_div apll_600_cfg = PLL_DIVISORS(600 * MHz, 1, 3, 1);
44
45 static const struct pll_div *apll_cfgs[] = {
46         [APLL_816_MHZ] = &apll_816_cfg,
47         [APLL_600_MHZ] = &apll_600_cfg,
48 };
49
50 enum {
51         /* PLL_CON0 */
52         PLL_POSTDIV1_SHIFT              = 12,
53         PLL_POSTDIV1_MASK               = 0x7 << PLL_POSTDIV1_SHIFT,
54         PLL_FBDIV_SHIFT                 = 0,
55         PLL_FBDIV_MASK                  = 0xfff,
56
57         /* PLL_CON1 */
58         PLL_DSMPD_SHIFT                 = 12,
59         PLL_DSMPD_MASK                  = 1 << PLL_DSMPD_SHIFT,
60         PLL_INTEGER_MODE                = 1,
61         PLL_LOCK_STATUS_SHIFT           = 10,
62         PLL_LOCK_STATUS_MASK            = 1 << PLL_LOCK_STATUS_SHIFT,
63         PLL_POSTDIV2_SHIFT              = 6,
64         PLL_POSTDIV2_MASK               = 0x7 << PLL_POSTDIV2_SHIFT,
65         PLL_REFDIV_SHIFT                = 0,
66         PLL_REFDIV_MASK                 = 0x3f,
67
68         /* PLL_CON2 */
69         PLL_FRACDIV_SHIFT               = 0,
70         PLL_FRACDIV_MASK                = 0xffffff,
71
72         /* MODE_CON */
73         APLL_MODE_SHIFT                 = 0,
74         NPLL_MODE_SHIFT                 = 1,
75         DPLL_MODE_SHIFT                 = 4,
76         CPLL_MODE_SHIFT                 = 8,
77         GPLL_MODE_SHIFT                 = 12,
78         PLL_MODE_SLOW                   = 0,
79         PLL_MODE_NORM,
80
81         /* CLKSEL_CON0 */
82         CLK_CORE_PLL_SEL_APLL           = 0,
83         CLK_CORE_PLL_SEL_GPLL,
84         CLK_CORE_PLL_SEL_DPLL,
85         CLK_CORE_PLL_SEL_NPLL,
86         CLK_CORE_PLL_SEL_SHIFT          = 6,
87         CLK_CORE_PLL_SEL_MASK           = 3 << CLK_CORE_PLL_SEL_SHIFT,
88         CLK_CORE_DIV_SHIFT              = 0,
89         CLK_CORE_DIV_MASK               = 0x1f,
90
91         /* CLKSEL_CON1 */
92         ACLKM_CORE_DIV_SHIFT            = 4,
93         ACLKM_CORE_DIV_MASK             = 0x7 << ACLKM_CORE_DIV_SHIFT,
94         PCLK_DBG_DIV_SHIFT              = 0,
95         PCLK_DBG_DIV_MASK               = 0xF << PCLK_DBG_DIV_SHIFT,
96
97         /* CLKSEL_CON28 */
98         ACLK_PERIHP_PLL_SEL_CPLL        = 0,
99         ACLK_PERIHP_PLL_SEL_GPLL,
100         ACLK_PERIHP_PLL_SEL_HDMIPHY,
101         ACLK_PERIHP_PLL_SEL_SHIFT       = 6,
102         ACLK_PERIHP_PLL_SEL_MASK        = 3 << ACLK_PERIHP_PLL_SEL_SHIFT,
103         ACLK_PERIHP_DIV_CON_SHIFT       = 0,
104         ACLK_PERIHP_DIV_CON_MASK        = 0x1f,
105
106         /* CLKSEL_CON29 */
107         PCLK_PERIHP_DIV_CON_SHIFT       = 4,
108         PCLK_PERIHP_DIV_CON_MASK        = 0x7 << PCLK_PERIHP_DIV_CON_SHIFT,
109         HCLK_PERIHP_DIV_CON_SHIFT       = 0,
110         HCLK_PERIHP_DIV_CON_MASK        = 3 << HCLK_PERIHP_DIV_CON_SHIFT,
111
112         /* CLKSEL_CON22 */
113         CLK_TSADC_DIV_CON_SHIFT         = 0,
114         CLK_TSADC_DIV_CON_MASK          = 0x3ff,
115
116         /* CLKSEL_CON23 */
117         CLK_SARADC_DIV_CON_SHIFT        = 0,
118         CLK_SARADC_DIV_CON_MASK         = GENMASK(9, 0),
119         CLK_SARADC_DIV_CON_WIDTH        = 10,
120
121         /* CLKSEL_CON24 */
122         CLK_PWM_PLL_SEL_CPLL            = 0,
123         CLK_PWM_PLL_SEL_GPLL,
124         CLK_PWM_PLL_SEL_SHIFT           = 15,
125         CLK_PWM_PLL_SEL_MASK            = 1 << CLK_PWM_PLL_SEL_SHIFT,
126         CLK_PWM_DIV_CON_SHIFT           = 8,
127         CLK_PWM_DIV_CON_MASK            = 0x7f << CLK_PWM_DIV_CON_SHIFT,
128
129         CLK_SPI_PLL_SEL_CPLL            = 0,
130         CLK_SPI_PLL_SEL_GPLL,
131         CLK_SPI_PLL_SEL_SHIFT           = 7,
132         CLK_SPI_PLL_SEL_MASK            = 1 << CLK_SPI_PLL_SEL_SHIFT,
133         CLK_SPI_DIV_CON_SHIFT           = 0,
134         CLK_SPI_DIV_CON_MASK            = 0x7f << CLK_SPI_DIV_CON_SHIFT,
135
136         /* CLKSEL_CON30 */
137         CLK_SDMMC_PLL_SEL_CPLL          = 0,
138         CLK_SDMMC_PLL_SEL_GPLL,
139         CLK_SDMMC_PLL_SEL_24M,
140         CLK_SDMMC_PLL_SEL_USBPHY,
141         CLK_SDMMC_PLL_SHIFT             = 8,
142         CLK_SDMMC_PLL_MASK              = 0x3 << CLK_SDMMC_PLL_SHIFT,
143         CLK_SDMMC_DIV_CON_SHIFT          = 0,
144         CLK_SDMMC_DIV_CON_MASK           = 0xff << CLK_SDMMC_DIV_CON_SHIFT,
145
146         /* CLKSEL_CON32 */
147         CLK_EMMC_PLL_SEL_CPLL           = 0,
148         CLK_EMMC_PLL_SEL_GPLL,
149         CLK_EMMC_PLL_SEL_24M,
150         CLK_EMMC_PLL_SEL_USBPHY,
151         CLK_EMMC_PLL_SHIFT              = 8,
152         CLK_EMMC_PLL_MASK               = 0x3 << CLK_EMMC_PLL_SHIFT,
153         CLK_EMMC_DIV_CON_SHIFT          = 0,
154         CLK_EMMC_DIV_CON_MASK           = 0xff << CLK_EMMC_DIV_CON_SHIFT,
155
156         /* CLKSEL_CON34 */
157         CLK_I2C_PLL_SEL_CPLL            = 0,
158         CLK_I2C_PLL_SEL_GPLL,
159         CLK_I2C_DIV_CON_MASK            = 0x7f,
160         CLK_I2C_PLL_SEL_MASK            = 1,
161         CLK_I2C1_PLL_SEL_SHIFT          = 15,
162         CLK_I2C1_DIV_CON_SHIFT          = 8,
163         CLK_I2C0_PLL_SEL_SHIFT          = 7,
164         CLK_I2C0_DIV_CON_SHIFT          = 0,
165
166         /* CLKSEL_CON35 */
167         CLK_I2C3_PLL_SEL_SHIFT          = 15,
168         CLK_I2C3_DIV_CON_SHIFT          = 8,
169         CLK_I2C2_PLL_SEL_SHIFT          = 7,
170         CLK_I2C2_DIV_CON_SHIFT          = 0,
171 };
172
173 #define VCO_MAX_KHZ     (3200 * (MHz / KHz))
174 #define VCO_MIN_KHZ     (800 * (MHz / KHz))
175 #define OUTPUT_MAX_KHZ  (3200 * (MHz / KHz))
176 #define OUTPUT_MIN_KHZ  (16 * (MHz / KHz))
177
178 /*
179  *  the div restructions of pll in integer mode, these are defined in
180  *  * CRU_*PLL_CON0 or PMUCRU_*PLL_CON0
181  */
182 #define PLL_DIV_MIN     16
183 #define PLL_DIV_MAX     3200
184
185 /*
186  * How to calculate the PLL(from TRM V0.3 Part 1 Page 63):
187  * Formulas also embedded within the Fractional PLL Verilog model:
188  * If DSMPD = 1 (DSM is disabled, "integer mode")
189  * FOUTVCO = FREF / REFDIV * FBDIV
190  * FOUTPOSTDIV = FOUTVCO / POSTDIV1 / POSTDIV2
191  * Where:
192  * FOUTVCO = Fractional PLL non-divided output frequency
193  * FOUTPOSTDIV = Fractional PLL divided output frequency
194  *               (output of second post divider)
195  * FREF = Fractional PLL input reference frequency, (the OSC_HZ 24MHz input)
196  * REFDIV = Fractional PLL input reference clock divider
197  * FBDIV = Integer value programmed into feedback divide
198  *
199  */
200 static void rkclk_set_pll(struct rk3328_cru *cru, enum rk_clk_id clk_id,
201                         const struct pll_div *div)
202 {
203         u32 *pll_con;
204         u32 mode_shift, mode_mask;
205
206         pll_con = NULL;
207         mode_shift = 0;
208         switch (clk_id) {
209         case CLK_ARM:
210                 pll_con = cru->apll_con;
211                 mode_shift = APLL_MODE_SHIFT;
212                 break;
213         case CLK_DDR:
214                 pll_con = cru->dpll_con;
215                 mode_shift = DPLL_MODE_SHIFT;
216                 break;
217         case CLK_CODEC:
218                 pll_con = cru->cpll_con;
219                 mode_shift = CPLL_MODE_SHIFT;
220                 break;
221         case CLK_GENERAL:
222                 pll_con = cru->gpll_con;
223                 mode_shift = GPLL_MODE_SHIFT;
224                 break;
225         case CLK_NEW:
226                 pll_con = cru->npll_con;
227                 mode_shift = NPLL_MODE_SHIFT;
228                 break;
229         default:
230                 break;
231         }
232         mode_mask = 1 << mode_shift;
233
234         /* All 8 PLLs have same VCO and output frequency range restrictions. */
235         u32 vco_khz = OSC_HZ / 1000 * div->fbdiv / div->refdiv;
236         u32 output_khz = vco_khz / div->postdiv1 / div->postdiv2;
237
238         debug("PLL at %p: fbdiv=%d, refdiv=%d, postdiv1=%d, \
239               postdiv2=%d, vco=%u khz, output=%u khz\n",
240               pll_con, div->fbdiv, div->refdiv, div->postdiv1,
241               div->postdiv2, vco_khz, output_khz);
242         assert(vco_khz >= VCO_MIN_KHZ && vco_khz <= VCO_MAX_KHZ &&
243                output_khz >= OUTPUT_MIN_KHZ && output_khz <= OUTPUT_MAX_KHZ &&
244                div->fbdiv >= PLL_DIV_MIN && div->fbdiv <= PLL_DIV_MAX);
245
246         /*
247          * When power on or changing PLL setting,
248          * we must force PLL into slow mode to ensure output stable clock.
249          */
250         rk_clrsetreg(&cru->mode_con, mode_mask, PLL_MODE_SLOW << mode_shift);
251
252         /* use integer mode */
253         rk_clrsetreg(&pll_con[1], PLL_DSMPD_MASK,
254                      PLL_INTEGER_MODE << PLL_DSMPD_SHIFT);
255
256         rk_clrsetreg(&pll_con[0],
257                      PLL_FBDIV_MASK | PLL_POSTDIV1_MASK,
258                      (div->fbdiv << PLL_FBDIV_SHIFT) |
259                      (div->postdiv1 << PLL_POSTDIV1_SHIFT));
260         rk_clrsetreg(&pll_con[1],
261                      PLL_POSTDIV2_MASK | PLL_REFDIV_MASK,
262                      (div->postdiv2 << PLL_POSTDIV2_SHIFT) |
263                      (div->refdiv << PLL_REFDIV_SHIFT));
264
265         /* waiting for pll lock */
266         while (!(readl(&pll_con[1]) & (1 << PLL_LOCK_STATUS_SHIFT)))
267                 udelay(1);
268
269         /* pll enter normal mode */
270         rk_clrsetreg(&cru->mode_con, mode_mask, PLL_MODE_NORM << mode_shift);
271 }
272
273 static void rkclk_init(struct rk3328_cru *cru)
274 {
275         u32 aclk_div;
276         u32 hclk_div;
277         u32 pclk_div;
278
279         /* configure gpll cpll */
280         rkclk_set_pll(cru, CLK_GENERAL, &gpll_init_cfg);
281         rkclk_set_pll(cru, CLK_CODEC, &cpll_init_cfg);
282
283         /* configure perihp aclk, hclk, pclk */
284         aclk_div = GPLL_HZ / PERIHP_ACLK_HZ - 1;
285         hclk_div = PERIHP_ACLK_HZ / PERIHP_HCLK_HZ - 1;
286         pclk_div = PERIHP_ACLK_HZ / PERIHP_PCLK_HZ - 1;
287
288         rk_clrsetreg(&cru->clksel_con[28],
289                      ACLK_PERIHP_PLL_SEL_MASK | ACLK_PERIHP_DIV_CON_MASK,
290                      ACLK_PERIHP_PLL_SEL_GPLL << ACLK_PERIHP_PLL_SEL_SHIFT |
291                      aclk_div << ACLK_PERIHP_DIV_CON_SHIFT);
292         rk_clrsetreg(&cru->clksel_con[29],
293                      PCLK_PERIHP_DIV_CON_MASK | HCLK_PERIHP_DIV_CON_MASK,
294                      pclk_div << PCLK_PERIHP_DIV_CON_SHIFT |
295                      hclk_div << HCLK_PERIHP_DIV_CON_SHIFT);
296 }
297
298 void rk3328_configure_cpu(struct rk3328_cru *cru,
299                           enum apll_frequencies apll_freq)
300 {
301         u32 clk_core_div;
302         u32 aclkm_div;
303         u32 pclk_dbg_div;
304
305         rkclk_set_pll(cru, CLK_ARM, apll_cfgs[apll_freq]);
306
307         clk_core_div = APLL_HZ / CLK_CORE_HZ - 1;
308         aclkm_div = APLL_HZ / ACLKM_CORE_HZ / (clk_core_div + 1) - 1;
309         pclk_dbg_div = APLL_HZ / PCLK_DBG_HZ / (clk_core_div + 1) - 1;
310
311         rk_clrsetreg(&cru->clksel_con[0],
312                      CLK_CORE_PLL_SEL_MASK | CLK_CORE_DIV_MASK,
313                      CLK_CORE_PLL_SEL_APLL << CLK_CORE_PLL_SEL_SHIFT |
314                      clk_core_div << CLK_CORE_DIV_SHIFT);
315
316         rk_clrsetreg(&cru->clksel_con[1],
317                      PCLK_DBG_DIV_MASK | ACLKM_CORE_DIV_MASK,
318                      pclk_dbg_div << PCLK_DBG_DIV_SHIFT |
319                      aclkm_div << ACLKM_CORE_DIV_SHIFT);
320 }
321
322
323 static ulong rk3328_i2c_get_clk(struct rk3328_cru *cru, ulong clk_id)
324 {
325         u32 div, con;
326
327         switch (clk_id) {
328         case SCLK_I2C0:
329                 con = readl(&cru->clksel_con[34]);
330                 div = con >> CLK_I2C0_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK;
331                 break;
332         case SCLK_I2C1:
333                 con = readl(&cru->clksel_con[34]);
334                 div = con >> CLK_I2C1_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK;
335                 break;
336         case SCLK_I2C2:
337                 con = readl(&cru->clksel_con[35]);
338                 div = con >> CLK_I2C2_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK;
339                 break;
340         case SCLK_I2C3:
341                 con = readl(&cru->clksel_con[35]);
342                 div = con >> CLK_I2C3_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK;
343                 break;
344         default:
345                 printf("do not support this i2c bus\n");
346                 return -EINVAL;
347         }
348
349         return DIV_TO_RATE(GPLL_HZ, div);
350 }
351
352 static ulong rk3328_i2c_set_clk(struct rk3328_cru *cru, ulong clk_id, uint hz)
353 {
354         int src_clk_div;
355
356         src_clk_div = GPLL_HZ / hz;
357         assert(src_clk_div - 1 < 127);
358
359         switch (clk_id) {
360         case SCLK_I2C0:
361                 rk_clrsetreg(&cru->clksel_con[34],
362                              CLK_I2C_DIV_CON_MASK << CLK_I2C0_DIV_CON_SHIFT |
363                              CLK_I2C_PLL_SEL_MASK << CLK_I2C0_PLL_SEL_SHIFT,
364                              (src_clk_div - 1) << CLK_I2C0_DIV_CON_SHIFT |
365                              CLK_I2C_PLL_SEL_GPLL << CLK_I2C0_PLL_SEL_SHIFT);
366                 break;
367         case SCLK_I2C1:
368                 rk_clrsetreg(&cru->clksel_con[34],
369                              CLK_I2C_DIV_CON_MASK << CLK_I2C1_DIV_CON_SHIFT |
370                              CLK_I2C_PLL_SEL_MASK << CLK_I2C1_PLL_SEL_SHIFT,
371                              (src_clk_div - 1) << CLK_I2C1_DIV_CON_SHIFT |
372                              CLK_I2C_PLL_SEL_GPLL << CLK_I2C1_PLL_SEL_SHIFT);
373                 break;
374         case SCLK_I2C2:
375                 rk_clrsetreg(&cru->clksel_con[35],
376                              CLK_I2C_DIV_CON_MASK << CLK_I2C2_DIV_CON_SHIFT |
377                              CLK_I2C_PLL_SEL_MASK << CLK_I2C2_PLL_SEL_SHIFT,
378                              (src_clk_div - 1) << CLK_I2C2_DIV_CON_SHIFT |
379                              CLK_I2C_PLL_SEL_GPLL << CLK_I2C2_PLL_SEL_SHIFT);
380                 break;
381         case SCLK_I2C3:
382                 rk_clrsetreg(&cru->clksel_con[35],
383                              CLK_I2C_DIV_CON_MASK << CLK_I2C3_DIV_CON_SHIFT |
384                              CLK_I2C_PLL_SEL_MASK << CLK_I2C3_PLL_SEL_SHIFT,
385                              (src_clk_div - 1) << CLK_I2C3_DIV_CON_SHIFT |
386                              CLK_I2C_PLL_SEL_GPLL << CLK_I2C3_PLL_SEL_SHIFT);
387                 break;
388         default:
389                 printf("do not support this i2c bus\n");
390                 return -EINVAL;
391         }
392
393         return DIV_TO_RATE(GPLL_HZ, src_clk_div);
394 }
395
396 static ulong rk3328_mmc_get_clk(struct rk3328_cru *cru, uint clk_id)
397 {
398         u32 div, con, con_id;
399
400         switch (clk_id) {
401         case HCLK_SDMMC:
402         case SCLK_SDMMC:
403                 con_id = 30;
404                 break;
405         case HCLK_EMMC:
406         case SCLK_EMMC:
407                 con_id = 32;
408                 break;
409         default:
410                 return -EINVAL;
411         }
412         con = readl(&cru->clksel_con[con_id]);
413         div = (con & CLK_EMMC_DIV_CON_MASK) >> CLK_EMMC_DIV_CON_SHIFT;
414
415         if ((con & CLK_EMMC_PLL_MASK) >> CLK_EMMC_PLL_SHIFT
416             == CLK_EMMC_PLL_SEL_24M)
417                 return DIV_TO_RATE(OSC_HZ, div) / 2;
418         else
419                 return DIV_TO_RATE(GPLL_HZ, div) / 2;
420 }
421
422 static ulong rk3328_mmc_set_clk(struct rk3328_cru *cru,
423                                 ulong clk_id, ulong set_rate)
424 {
425         int src_clk_div;
426         u32 con_id;
427
428         switch (clk_id) {
429         case HCLK_SDMMC:
430         case SCLK_SDMMC:
431                 con_id = 30;
432                 break;
433         case HCLK_EMMC:
434         case SCLK_EMMC:
435                 con_id = 32;
436                 break;
437         default:
438                 return -EINVAL;
439         }
440         /* Select clk_sdmmc/emmc source from GPLL by default */
441         /* mmc clock defaulg div 2 internal, need provide double in cru */
442         src_clk_div = DIV_ROUND_UP(GPLL_HZ / 2, set_rate);
443
444         if (src_clk_div > 127) {
445                 /* use 24MHz source for 400KHz clock */
446                 src_clk_div = DIV_ROUND_UP(OSC_HZ / 2, set_rate);
447                 rk_clrsetreg(&cru->clksel_con[con_id],
448                              CLK_EMMC_PLL_MASK | CLK_EMMC_DIV_CON_MASK,
449                              CLK_EMMC_PLL_SEL_24M << CLK_EMMC_PLL_SHIFT |
450                              (src_clk_div - 1) << CLK_EMMC_DIV_CON_SHIFT);
451         } else {
452                 rk_clrsetreg(&cru->clksel_con[con_id],
453                              CLK_EMMC_PLL_MASK | CLK_EMMC_DIV_CON_MASK,
454                              CLK_EMMC_PLL_SEL_GPLL << CLK_EMMC_PLL_SHIFT |
455                              (src_clk_div - 1) << CLK_EMMC_DIV_CON_SHIFT);
456         }
457
458         return rk3328_mmc_get_clk(cru, clk_id);
459 }
460
461 static ulong rk3328_pwm_get_clk(struct rk3328_cru *cru)
462 {
463         u32 div, con;
464
465         con = readl(&cru->clksel_con[24]);
466         div = (con & CLK_PWM_DIV_CON_MASK) >> CLK_PWM_DIV_CON_SHIFT;
467
468         return DIV_TO_RATE(GPLL_HZ, div);
469 }
470
471 static ulong rk3328_pwm_set_clk(struct rk3328_cru *cru, uint hz)
472 {
473         u32 div = GPLL_HZ / hz;
474
475         rk_clrsetreg(&cru->clksel_con[24],
476                      CLK_PWM_PLL_SEL_MASK | CLK_PWM_DIV_CON_MASK,
477                      CLK_PWM_PLL_SEL_GPLL << CLK_PWM_PLL_SEL_SHIFT |
478                      (div - 1) << CLK_PWM_DIV_CON_SHIFT);
479
480         return DIV_TO_RATE(GPLL_HZ, div);
481 }
482
483 static ulong rk3328_saradc_get_clk(struct rk3328_cru *cru)
484 {
485         u32 div, val;
486
487         val = readl(&cru->clksel_con[23]);
488         div = bitfield_extract(val, CLK_SARADC_DIV_CON_SHIFT,
489                                CLK_SARADC_DIV_CON_WIDTH);
490
491         return DIV_TO_RATE(OSC_HZ, div);
492 }
493
494 static ulong rk3328_saradc_set_clk(struct rk3328_cru *cru, uint hz)
495 {
496         int src_clk_div;
497
498         src_clk_div = DIV_ROUND_UP(OSC_HZ, hz) - 1;
499         assert(src_clk_div < 128);
500
501         rk_clrsetreg(&cru->clksel_con[23],
502                      CLK_SARADC_DIV_CON_MASK,
503                      src_clk_div << CLK_SARADC_DIV_CON_SHIFT);
504
505         return rk3328_saradc_get_clk(cru);
506 }
507
508 static ulong rk3328_clk_get_rate(struct clk *clk)
509 {
510         struct rk3328_clk_priv *priv = dev_get_priv(clk->dev);
511         ulong rate = 0;
512
513         switch (clk->id) {
514         case 0 ... 29:
515                 return 0;
516         case HCLK_SDMMC:
517         case HCLK_EMMC:
518         case SCLK_SDMMC:
519         case SCLK_EMMC:
520                 rate = rk3328_mmc_get_clk(priv->cru, clk->id);
521                 break;
522         case SCLK_I2C0:
523         case SCLK_I2C1:
524         case SCLK_I2C2:
525         case SCLK_I2C3:
526                 rate = rk3328_i2c_get_clk(priv->cru, clk->id);
527                 break;
528         case SCLK_PWM:
529                 rate = rk3328_pwm_get_clk(priv->cru);
530                 break;
531         case SCLK_SARADC:
532                 rate = rk3328_saradc_get_clk(priv->cru);
533                 break;
534         default:
535                 return -ENOENT;
536         }
537
538         return rate;
539 }
540
541 static ulong rk3328_clk_set_rate(struct clk *clk, ulong rate)
542 {
543         struct rk3328_clk_priv *priv = dev_get_priv(clk->dev);
544         ulong ret = 0;
545
546         switch (clk->id) {
547         case 0 ... 29:
548                 return 0;
549         case HCLK_SDMMC:
550         case HCLK_EMMC:
551         case SCLK_SDMMC:
552         case SCLK_EMMC:
553                 ret = rk3328_mmc_set_clk(priv->cru, clk->id, rate);
554                 break;
555         case SCLK_I2C0:
556         case SCLK_I2C1:
557         case SCLK_I2C2:
558         case SCLK_I2C3:
559                 ret = rk3328_i2c_set_clk(priv->cru, clk->id, rate);
560                 break;
561         case SCLK_PWM:
562                 ret = rk3328_pwm_set_clk(priv->cru, rate);
563                 break;
564         case SCLK_SARADC:
565                 ret = rk3328_saradc_set_clk(priv->cru, rate);
566                 break;
567         default:
568                 return -ENOENT;
569         }
570
571         return ret;
572 }
573
574 static struct clk_ops rk3328_clk_ops = {
575         .get_rate = rk3328_clk_get_rate,
576         .set_rate = rk3328_clk_set_rate,
577 };
578
579 static int rk3328_clk_probe(struct udevice *dev)
580 {
581         struct rk3328_clk_priv *priv = dev_get_priv(dev);
582
583         rkclk_init(priv->cru);
584
585         return 0;
586 }
587
588 static int rk3328_clk_ofdata_to_platdata(struct udevice *dev)
589 {
590         struct rk3328_clk_priv *priv = dev_get_priv(dev);
591
592         priv->cru = (struct rk3328_cru *)devfdt_get_addr(dev);
593
594         return 0;
595 }
596
597 static int rk3328_clk_bind(struct udevice *dev)
598 {
599         int ret;
600         struct udevice *sys_child;
601         struct sysreset_reg *priv;
602
603         /* The reset driver does not have a device node, so bind it here */
604         ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset",
605                                  &sys_child);
606         if (ret) {
607                 debug("Warning: No sysreset driver: ret=%d\n", ret);
608         } else {
609                 priv = malloc(sizeof(struct sysreset_reg));
610                 priv->glb_srst_fst_value = offsetof(struct rk3328_cru,
611                                                     glb_srst_fst_value);
612                 priv->glb_srst_snd_value = offsetof(struct rk3328_cru,
613                                                     glb_srst_snd_value);
614                 sys_child->priv = priv;
615         }
616
617         return ret;
618 }
619
620 static const struct udevice_id rk3328_clk_ids[] = {
621         { .compatible = "rockchip,rk3328-cru" },
622         { }
623 };
624
625 U_BOOT_DRIVER(rockchip_rk3328_cru) = {
626         .name           = "rockchip_rk3328_cru",
627         .id             = UCLASS_CLK,
628         .of_match       = rk3328_clk_ids,
629         .priv_auto_alloc_size = sizeof(struct rk3328_clk_priv),
630         .ofdata_to_platdata = rk3328_clk_ofdata_to_platdata,
631         .ops            = &rk3328_clk_ops,
632         .bind           = rk3328_clk_bind,
633         .probe          = rk3328_clk_probe,
634 };