a2a5939d4b122f5d8122d467fc86f4da71042853
[platform/kernel/u-boot.git] / drivers / clk / rockchip / clk_px30.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * (C) Copyright 2017 Rockchip Electronics Co., Ltd
4  */
5
6 #include <common.h>
7 #include <bitfield.h>
8 #include <clk-uclass.h>
9 #include <dm.h>
10 #include <errno.h>
11 #include <log.h>
12 #include <malloc.h>
13 #include <syscon.h>
14 #include <asm/arch-rockchip/clock.h>
15 #include <asm/arch-rockchip/cru_px30.h>
16 #include <asm/arch-rockchip/hardware.h>
17 #include <asm/io.h>
18 #include <dm/device-internal.h>
19 #include <dm/lists.h>
20 #include <dt-bindings/clock/px30-cru.h>
21 #include <linux/bitops.h>
22 #include <linux/delay.h>
23
24 DECLARE_GLOBAL_DATA_PTR;
25
26 enum {
27         VCO_MAX_HZ      = 3200U * 1000000,
28         VCO_MIN_HZ      = 800 * 1000000,
29         OUTPUT_MAX_HZ   = 3200U * 1000000,
30         OUTPUT_MIN_HZ   = 24 * 1000000,
31 };
32
33 #define PX30_VOP_PLL_LIMIT                      600000000
34
35 #define PX30_PLL_RATE(_rate, _refdiv, _fbdiv, _postdiv1,        \
36                         _postdiv2, _dsmpd, _frac)               \
37 {                                                               \
38         .rate   = _rate##U,                                     \
39         .fbdiv = _fbdiv,                                        \
40         .postdiv1 = _postdiv1,                                  \
41         .refdiv = _refdiv,                                      \
42         .postdiv2 = _postdiv2,                                  \
43         .dsmpd = _dsmpd,                                        \
44         .frac = _frac,                                          \
45 }
46
47 #define PX30_CPUCLK_RATE(_rate, _aclk_div, _pclk_div)           \
48 {                                                               \
49         .rate   = _rate##U,                                     \
50         .aclk_div = _aclk_div,                                  \
51         .pclk_div = _pclk_div,                                  \
52 }
53
54 #define DIV_TO_RATE(input_rate, div)    ((input_rate) / ((div) + 1))
55
56 #define PX30_CLK_DUMP(_id, _name, _iscru)       \
57 {                                               \
58         .id = _id,                              \
59         .name = _name,                          \
60         .is_cru = _iscru,                       \
61 }
62
63 static struct pll_rate_table px30_pll_rates[] = {
64         /* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */
65         PX30_PLL_RATE(1200000000, 1, 50, 1, 1, 1, 0),
66         PX30_PLL_RATE(1188000000, 2, 99, 1, 1, 1, 0),
67         PX30_PLL_RATE(1100000000, 12, 550, 1, 1, 1, 0),
68         PX30_PLL_RATE(1008000000, 1, 84, 2, 1, 1, 0),
69         PX30_PLL_RATE(1000000000, 6, 500, 2, 1, 1, 0),
70         PX30_PLL_RATE(816000000, 1, 68, 2, 1, 1, 0),
71         PX30_PLL_RATE(600000000, 1, 75, 3, 1, 1, 0),
72 };
73
74 static struct cpu_rate_table px30_cpu_rates[] = {
75         PX30_CPUCLK_RATE(1200000000, 1, 5),
76         PX30_CPUCLK_RATE(1008000000, 1, 5),
77         PX30_CPUCLK_RATE(816000000, 1, 3),
78         PX30_CPUCLK_RATE(600000000, 1, 3),
79         PX30_CPUCLK_RATE(408000000, 1, 1),
80 };
81
82 static u8 pll_mode_shift[PLL_COUNT] = {
83         APLL_MODE_SHIFT, DPLL_MODE_SHIFT, CPLL_MODE_SHIFT,
84         NPLL_MODE_SHIFT, GPLL_MODE_SHIFT
85 };
86
87 static u32 pll_mode_mask[PLL_COUNT] = {
88         APLL_MODE_MASK, DPLL_MODE_MASK, CPLL_MODE_MASK,
89         NPLL_MODE_MASK, GPLL_MODE_MASK
90 };
91
92 static struct pll_rate_table auto_table;
93
94 static ulong px30_clk_get_pll_rate(struct px30_clk_priv *priv,
95                                    enum px30_pll_id pll_id);
96
97 static struct pll_rate_table *pll_clk_set_by_auto(u32 drate)
98 {
99         struct pll_rate_table *rate = &auto_table;
100         u32 ref_khz = OSC_HZ / KHz, refdiv, fbdiv = 0;
101         u32 postdiv1, postdiv2 = 1;
102         u32 fref_khz;
103         u32 diff_khz, best_diff_khz;
104         const u32 max_refdiv = 63, max_fbdiv = 3200, min_fbdiv = 16;
105         const u32 max_postdiv1 = 7, max_postdiv2 = 7;
106         u32 vco_khz;
107         u32 rate_khz = drate / KHz;
108
109         if (!drate) {
110                 printf("%s: the frequency can't be 0 Hz\n", __func__);
111                 return NULL;
112         }
113
114         postdiv1 = DIV_ROUND_UP(VCO_MIN_HZ / 1000, rate_khz);
115         if (postdiv1 > max_postdiv1) {
116                 postdiv2 = DIV_ROUND_UP(postdiv1, max_postdiv1);
117                 postdiv1 = DIV_ROUND_UP(postdiv1, postdiv2);
118         }
119
120         vco_khz = rate_khz * postdiv1 * postdiv2;
121
122         if (vco_khz < (VCO_MIN_HZ / KHz) || vco_khz > (VCO_MAX_HZ / KHz) ||
123             postdiv2 > max_postdiv2) {
124                 printf("%s: Cannot find out a supported VCO for Freq (%uHz)\n",
125                        __func__, rate_khz);
126                 return NULL;
127         }
128
129         rate->postdiv1 = postdiv1;
130         rate->postdiv2 = postdiv2;
131
132         best_diff_khz = vco_khz;
133         for (refdiv = 1; refdiv < max_refdiv && best_diff_khz; refdiv++) {
134                 fref_khz = ref_khz / refdiv;
135
136                 fbdiv = vco_khz / fref_khz;
137                 if (fbdiv >= max_fbdiv || fbdiv <= min_fbdiv)
138                         continue;
139
140                 diff_khz = vco_khz - fbdiv * fref_khz;
141                 if (fbdiv + 1 < max_fbdiv && diff_khz > fref_khz / 2) {
142                         fbdiv++;
143                         diff_khz = fref_khz - diff_khz;
144                 }
145
146                 if (diff_khz >= best_diff_khz)
147                         continue;
148
149                 best_diff_khz = diff_khz;
150                 rate->refdiv = refdiv;
151                 rate->fbdiv = fbdiv;
152         }
153
154         if (best_diff_khz > 4 * (MHz / KHz)) {
155                 printf("%s: Failed to match output frequency %u bestis %u Hz\n",
156                        __func__, rate_khz,
157                        best_diff_khz * KHz);
158                 return NULL;
159         }
160
161         return rate;
162 }
163
164 static const struct pll_rate_table *get_pll_settings(unsigned long rate)
165 {
166         unsigned int rate_count = ARRAY_SIZE(px30_pll_rates);
167         int i;
168
169         for (i = 0; i < rate_count; i++) {
170                 if (rate == px30_pll_rates[i].rate)
171                         return &px30_pll_rates[i];
172         }
173
174         return pll_clk_set_by_auto(rate);
175 }
176
177 static const struct cpu_rate_table *get_cpu_settings(unsigned long rate)
178 {
179         unsigned int rate_count = ARRAY_SIZE(px30_cpu_rates);
180         int i;
181
182         for (i = 0; i < rate_count; i++) {
183                 if (rate == px30_cpu_rates[i].rate)
184                         return &px30_cpu_rates[i];
185         }
186
187         return NULL;
188 }
189
190 /*
191  * How to calculate the PLL(from TRM V0.3 Part 1 Page 63):
192  * Formulas also embedded within the Fractional PLL Verilog model:
193  * If DSMPD = 1 (DSM is disabled, "integer mode")
194  * FOUTVCO = FREF / REFDIV * FBDIV
195  * FOUTPOSTDIV = FOUTVCO / POSTDIV1 / POSTDIV2
196  * Where:
197  * FOUTVCO = Fractional PLL non-divided output frequency
198  * FOUTPOSTDIV = Fractional PLL divided output frequency
199  *               (output of second post divider)
200  * FREF = Fractional PLL input reference frequency, (the OSC_HZ 24MHz input)
201  * REFDIV = Fractional PLL input reference clock divider
202  * FBDIV = Integer value programmed into feedback divide
203  *
204  */
205 static int rkclk_set_pll(struct px30_pll *pll, unsigned int *mode,
206                          enum px30_pll_id pll_id,
207                          unsigned long drate)
208 {
209         const struct pll_rate_table *rate;
210         uint vco_hz, output_hz;
211
212         rate = get_pll_settings(drate);
213         if (!rate) {
214                 printf("%s unsupport rate\n", __func__);
215                 return -EINVAL;
216         }
217
218         /* All PLLs have same VCO and output frequency range restrictions. */
219         vco_hz = OSC_HZ / 1000 * rate->fbdiv / rate->refdiv * 1000;
220         output_hz = vco_hz / rate->postdiv1 / rate->postdiv2;
221
222         debug("PLL at %p: fb=%d, ref=%d, pst1=%d, pst2=%d, vco=%u Hz, output=%u Hz\n",
223               pll, rate->fbdiv, rate->refdiv, rate->postdiv1,
224               rate->postdiv2, vco_hz, output_hz);
225         assert(vco_hz >= VCO_MIN_HZ && vco_hz <= VCO_MAX_HZ &&
226                output_hz >= OUTPUT_MIN_HZ && output_hz <= OUTPUT_MAX_HZ);
227
228         /*
229          * When power on or changing PLL setting,
230          * we must force PLL into slow mode to ensure output stable clock.
231          */
232         rk_clrsetreg(mode, pll_mode_mask[pll_id],
233                      PLLMUX_FROM_XIN24M << pll_mode_shift[pll_id]);
234
235         /* use integer mode */
236         rk_setreg(&pll->con1, 1 << PLL_DSMPD_SHIFT);
237         /* Power down */
238         rk_setreg(&pll->con1, 1 << PLL_PD_SHIFT);
239
240         rk_clrsetreg(&pll->con0,
241                      PLL_POSTDIV1_MASK | PLL_FBDIV_MASK,
242                      (rate->postdiv1 << PLL_POSTDIV1_SHIFT) | rate->fbdiv);
243         rk_clrsetreg(&pll->con1, PLL_POSTDIV2_MASK | PLL_REFDIV_MASK,
244                      (rate->postdiv2 << PLL_POSTDIV2_SHIFT |
245                      rate->refdiv << PLL_REFDIV_SHIFT));
246
247         /* Power Up */
248         rk_clrreg(&pll->con1, 1 << PLL_PD_SHIFT);
249
250         /* waiting for pll lock */
251         while (!(readl(&pll->con1) & (1 << PLL_LOCK_STATUS_SHIFT)))
252                 udelay(1);
253
254         rk_clrsetreg(mode, pll_mode_mask[pll_id],
255                      PLLMUX_FROM_PLL << pll_mode_shift[pll_id]);
256
257         return 0;
258 }
259
260 static uint32_t rkclk_pll_get_rate(struct px30_pll *pll, unsigned int *mode,
261                                    enum px30_pll_id pll_id)
262 {
263         u32 refdiv, fbdiv, postdiv1, postdiv2;
264         u32 con, shift, mask;
265
266         con = readl(mode);
267         shift = pll_mode_shift[pll_id];
268         mask = pll_mode_mask[pll_id];
269
270         switch ((con & mask) >> shift) {
271         case PLLMUX_FROM_XIN24M:
272                 return OSC_HZ;
273         case PLLMUX_FROM_PLL:
274                 /* normal mode */
275                 con = readl(&pll->con0);
276                 postdiv1 = (con & PLL_POSTDIV1_MASK) >> PLL_POSTDIV1_SHIFT;
277                 fbdiv = (con & PLL_FBDIV_MASK) >> PLL_FBDIV_SHIFT;
278                 con = readl(&pll->con1);
279                 postdiv2 = (con & PLL_POSTDIV2_MASK) >> PLL_POSTDIV2_SHIFT;
280                 refdiv = (con & PLL_REFDIV_MASK) >> PLL_REFDIV_SHIFT;
281                 return (24 * fbdiv / (refdiv * postdiv1 * postdiv2)) * 1000000;
282         case PLLMUX_FROM_RTC32K:
283         default:
284                 return 32768;
285         }
286 }
287
288 static ulong px30_i2c_get_clk(struct px30_clk_priv *priv, ulong clk_id)
289 {
290         struct px30_cru *cru = priv->cru;
291         u32 div, con;
292
293         switch (clk_id) {
294         case SCLK_I2C0:
295                 con = readl(&cru->clksel_con[49]);
296                 div = con >> CLK_I2C0_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK;
297                 break;
298         case SCLK_I2C1:
299                 con = readl(&cru->clksel_con[49]);
300                 div = con >> CLK_I2C1_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK;
301                 break;
302         case SCLK_I2C2:
303                 con = readl(&cru->clksel_con[50]);
304                 div = con >> CLK_I2C2_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK;
305                 break;
306         case SCLK_I2C3:
307                 con = readl(&cru->clksel_con[50]);
308                 div = con >> CLK_I2C3_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK;
309                 break;
310         default:
311                 printf("do not support this i2c bus\n");
312                 return -EINVAL;
313         }
314
315         return DIV_TO_RATE(priv->gpll_hz, div);
316 }
317
318 static ulong px30_i2c_set_clk(struct px30_clk_priv *priv, ulong clk_id, uint hz)
319 {
320         struct px30_cru *cru = priv->cru;
321         int src_clk_div;
322
323         src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
324         assert(src_clk_div - 1 <= 127);
325
326         switch (clk_id) {
327         case SCLK_I2C0:
328                 rk_clrsetreg(&cru->clksel_con[49],
329                              CLK_I2C_DIV_CON_MASK << CLK_I2C0_DIV_CON_SHIFT |
330                              CLK_I2C_PLL_SEL_MASK << CLK_I2C0_PLL_SEL_SHIFT,
331                              (src_clk_div - 1) << CLK_I2C0_DIV_CON_SHIFT |
332                              CLK_I2C_PLL_SEL_GPLL << CLK_I2C0_PLL_SEL_SHIFT);
333                 break;
334         case SCLK_I2C1:
335                 rk_clrsetreg(&cru->clksel_con[49],
336                              CLK_I2C_DIV_CON_MASK << CLK_I2C1_DIV_CON_SHIFT |
337                              CLK_I2C_PLL_SEL_MASK << CLK_I2C1_PLL_SEL_SHIFT,
338                              (src_clk_div - 1) << CLK_I2C1_DIV_CON_SHIFT |
339                              CLK_I2C_PLL_SEL_GPLL << CLK_I2C1_PLL_SEL_SHIFT);
340                 break;
341         case SCLK_I2C2:
342                 rk_clrsetreg(&cru->clksel_con[50],
343                              CLK_I2C_DIV_CON_MASK << CLK_I2C2_DIV_CON_SHIFT |
344                              CLK_I2C_PLL_SEL_MASK << CLK_I2C2_PLL_SEL_SHIFT,
345                              (src_clk_div - 1) << CLK_I2C2_DIV_CON_SHIFT |
346                              CLK_I2C_PLL_SEL_GPLL << CLK_I2C2_PLL_SEL_SHIFT);
347                 break;
348         case SCLK_I2C3:
349                 rk_clrsetreg(&cru->clksel_con[50],
350                              CLK_I2C_DIV_CON_MASK << CLK_I2C3_DIV_CON_SHIFT |
351                              CLK_I2C_PLL_SEL_MASK << CLK_I2C3_PLL_SEL_SHIFT,
352                              (src_clk_div - 1) << CLK_I2C3_DIV_CON_SHIFT |
353                              CLK_I2C_PLL_SEL_GPLL << CLK_I2C3_PLL_SEL_SHIFT);
354                 break;
355         default:
356                 printf("do not support this i2c bus\n");
357                 return -EINVAL;
358         }
359
360         return px30_i2c_get_clk(priv, clk_id);
361 }
362
363 /*
364  * calculate best rational approximation for a given fraction
365  * taking into account restricted register size, e.g. to find
366  * appropriate values for a pll with 5 bit denominator and
367  * 8 bit numerator register fields, trying to set up with a
368  * frequency ratio of 3.1415, one would say:
369  *
370  * rational_best_approximation(31415, 10000,
371  *              (1 << 8) - 1, (1 << 5) - 1, &n, &d);
372  *
373  * you may look at given_numerator as a fixed point number,
374  * with the fractional part size described in given_denominator.
375  *
376  * for theoretical background, see:
377  * http://en.wikipedia.org/wiki/Continued_fraction
378  */
379 static void rational_best_approximation(unsigned long given_numerator,
380                                         unsigned long given_denominator,
381                                         unsigned long max_numerator,
382                                         unsigned long max_denominator,
383                                         unsigned long *best_numerator,
384                                         unsigned long *best_denominator)
385 {
386         unsigned long n, d, n0, d0, n1, d1;
387
388         n = given_numerator;
389         d = given_denominator;
390         n0 = 0;
391         d1 = 0;
392         n1 = 1;
393         d0 = 1;
394         for (;;) {
395                 unsigned long t, a;
396
397                 if (n1 > max_numerator || d1 > max_denominator) {
398                         n1 = n0;
399                         d1 = d0;
400                         break;
401                 }
402                 if (d == 0)
403                         break;
404                 t = d;
405                 a = n / d;
406                 d = n % d;
407                 n = t;
408                 t = n0 + a * n1;
409                 n0 = n1;
410                 n1 = t;
411                 t = d0 + a * d1;
412                 d0 = d1;
413                 d1 = t;
414         }
415         *best_numerator = n1;
416         *best_denominator = d1;
417 }
418
419 static ulong px30_i2s_get_clk(struct px30_clk_priv *priv, ulong clk_id)
420 {
421         u32 con, fracdiv, gate;
422         u32 clk_src = priv->gpll_hz / 2;
423         unsigned long m, n;
424         struct px30_cru *cru = priv->cru;
425
426         switch (clk_id) {
427         case SCLK_I2S1:
428                 con = readl(&cru->clksel_con[30]);
429                 fracdiv = readl(&cru->clksel_con[31]);
430                 gate = readl(&cru->clkgate_con[10]);
431                 m = fracdiv & CLK_I2S1_FRAC_NUMERATOR_MASK;
432                 m >>= CLK_I2S1_FRAC_NUMERATOR_SHIFT;
433                 n = fracdiv & CLK_I2S1_FRAC_DENOMINATOR_MASK;
434                 n >>= CLK_I2S1_FRAC_DENOMINATOR_SHIFT;
435                 debug("con30: 0x%x, gate: 0x%x, frac: 0x%x\n",
436                       con, gate, fracdiv);
437                 break;
438         default:
439                 printf("do not support this i2s bus\n");
440                 return -EINVAL;
441         }
442
443         return clk_src * n / m;
444 }
445
446 static ulong px30_i2s_set_clk(struct px30_clk_priv *priv, ulong clk_id, uint hz)
447 {
448         u32 clk_src;
449         unsigned long m, n, val;
450         struct px30_cru *cru = priv->cru;
451
452         clk_src = priv->gpll_hz / 2;
453         rational_best_approximation(hz, clk_src,
454                                     GENMASK(16 - 1, 0),
455                                     GENMASK(16 - 1, 0),
456                                     &m, &n);
457         switch (clk_id) {
458         case SCLK_I2S1:
459                 rk_clrsetreg(&cru->clksel_con[30],
460                              CLK_I2S1_PLL_SEL_MASK, CLK_I2S1_PLL_SEL_GPLL);
461                 rk_clrsetreg(&cru->clksel_con[30],
462                              CLK_I2S1_DIV_CON_MASK, 0x1);
463                 rk_clrsetreg(&cru->clksel_con[30],
464                              CLK_I2S1_SEL_MASK, CLK_I2S1_SEL_FRAC);
465                 val = m << CLK_I2S1_FRAC_NUMERATOR_SHIFT | n;
466                 writel(val, &cru->clksel_con[31]);
467                 rk_clrsetreg(&cru->clkgate_con[10],
468                              CLK_I2S1_OUT_MCLK_PAD_MASK,
469                              CLK_I2S1_OUT_MCLK_PAD_ENABLE);
470                 break;
471         default:
472                 printf("do not support this i2s bus\n");
473                 return -EINVAL;
474         }
475
476         return px30_i2s_get_clk(priv, clk_id);
477 }
478
479 static ulong px30_nandc_get_clk(struct px30_clk_priv *priv)
480 {
481         struct px30_cru *cru = priv->cru;
482         u32 div, con;
483
484         con = readl(&cru->clksel_con[15]);
485         div = (con & NANDC_DIV_MASK) >> NANDC_DIV_SHIFT;
486
487         return DIV_TO_RATE(priv->gpll_hz, div);
488 }
489
490 static ulong px30_nandc_set_clk(struct px30_clk_priv *priv,
491                                 ulong set_rate)
492 {
493         struct px30_cru *cru = priv->cru;
494         int src_clk_div;
495
496         /* Select nandc source from GPLL by default */
497         /* nandc clock defaulg div 2 internal, need provide double in cru */
498         src_clk_div = DIV_ROUND_UP(priv->gpll_hz, set_rate);
499         assert(src_clk_div - 1 <= 31);
500
501         rk_clrsetreg(&cru->clksel_con[15],
502                      NANDC_CLK_SEL_MASK | NANDC_PLL_MASK |
503                      NANDC_DIV_MASK,
504                      NANDC_CLK_SEL_NANDC << NANDC_CLK_SEL_SHIFT |
505                      NANDC_SEL_GPLL << NANDC_PLL_SHIFT |
506                      (src_clk_div - 1) << NANDC_DIV_SHIFT);
507
508         return px30_nandc_get_clk(priv);
509 }
510
511 static ulong px30_mmc_get_clk(struct px30_clk_priv *priv, uint clk_id)
512 {
513         struct px30_cru *cru = priv->cru;
514         u32 div, con, con_id;
515
516         switch (clk_id) {
517         case HCLK_SDMMC:
518         case SCLK_SDMMC:
519                 con_id = 16;
520                 break;
521         case HCLK_EMMC:
522         case SCLK_EMMC:
523         case SCLK_EMMC_SAMPLE:
524                 con_id = 20;
525                 break;
526         default:
527                 return -EINVAL;
528         }
529
530         con = readl(&cru->clksel_con[con_id]);
531         div = (con & EMMC_DIV_MASK) >> EMMC_DIV_SHIFT;
532
533         if ((con & EMMC_PLL_MASK) >> EMMC_PLL_SHIFT
534             == EMMC_SEL_24M)
535                 return DIV_TO_RATE(OSC_HZ, div) / 2;
536         else
537                 return DIV_TO_RATE(priv->gpll_hz, div) / 2;
538 }
539
540 static ulong px30_mmc_set_clk(struct px30_clk_priv *priv,
541                               ulong clk_id, ulong set_rate)
542 {
543         struct px30_cru *cru = priv->cru;
544         int src_clk_div;
545         u32 con_id;
546
547         switch (clk_id) {
548         case HCLK_SDMMC:
549         case SCLK_SDMMC:
550                 con_id = 16;
551                 break;
552         case HCLK_EMMC:
553         case SCLK_EMMC:
554                 con_id = 20;
555                 break;
556         default:
557                 return -EINVAL;
558         }
559
560         /* Select clk_sdmmc/emmc source from GPLL by default */
561         /* mmc clock defaulg div 2 internal, need provide double in cru */
562         src_clk_div = DIV_ROUND_UP(priv->gpll_hz / 2, set_rate);
563
564         if (src_clk_div > 127) {
565                 /* use 24MHz source for 400KHz clock */
566                 src_clk_div = DIV_ROUND_UP(OSC_HZ / 2, set_rate);
567                 rk_clrsetreg(&cru->clksel_con[con_id],
568                              EMMC_PLL_MASK | EMMC_DIV_MASK,
569                              EMMC_SEL_24M << EMMC_PLL_SHIFT |
570                              (src_clk_div - 1) << EMMC_DIV_SHIFT);
571         } else {
572                 rk_clrsetreg(&cru->clksel_con[con_id],
573                              EMMC_PLL_MASK | EMMC_DIV_MASK,
574                              EMMC_SEL_GPLL << EMMC_PLL_SHIFT |
575                              (src_clk_div - 1) << EMMC_DIV_SHIFT);
576         }
577         rk_clrsetreg(&cru->clksel_con[con_id + 1], EMMC_CLK_SEL_MASK,
578                      EMMC_CLK_SEL_EMMC);
579
580         return px30_mmc_get_clk(priv, clk_id);
581 }
582
583 static ulong px30_pwm_get_clk(struct px30_clk_priv *priv, ulong clk_id)
584 {
585         struct px30_cru *cru = priv->cru;
586         u32 div, con;
587
588         switch (clk_id) {
589         case SCLK_PWM0:
590                 con = readl(&cru->clksel_con[52]);
591                 div = con >> CLK_PWM0_DIV_CON_SHIFT & CLK_PWM_DIV_CON_MASK;
592                 break;
593         case SCLK_PWM1:
594                 con = readl(&cru->clksel_con[52]);
595                 div = con >> CLK_PWM1_DIV_CON_SHIFT & CLK_PWM_DIV_CON_MASK;
596                 break;
597         default:
598                 printf("do not support this pwm bus\n");
599                 return -EINVAL;
600         }
601
602         return DIV_TO_RATE(priv->gpll_hz, div);
603 }
604
605 static ulong px30_pwm_set_clk(struct px30_clk_priv *priv, ulong clk_id, uint hz)
606 {
607         struct px30_cru *cru = priv->cru;
608         int src_clk_div;
609
610         src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
611         assert(src_clk_div - 1 <= 127);
612
613         switch (clk_id) {
614         case SCLK_PWM0:
615                 rk_clrsetreg(&cru->clksel_con[52],
616                              CLK_PWM_DIV_CON_MASK << CLK_PWM0_DIV_CON_SHIFT |
617                              CLK_PWM_PLL_SEL_MASK << CLK_PWM0_PLL_SEL_SHIFT,
618                              (src_clk_div - 1) << CLK_PWM0_DIV_CON_SHIFT |
619                              CLK_PWM_PLL_SEL_GPLL << CLK_PWM0_PLL_SEL_SHIFT);
620                 break;
621         case SCLK_PWM1:
622                 rk_clrsetreg(&cru->clksel_con[52],
623                              CLK_PWM_DIV_CON_MASK << CLK_PWM1_DIV_CON_SHIFT |
624                              CLK_PWM_PLL_SEL_MASK << CLK_PWM1_PLL_SEL_SHIFT,
625                              (src_clk_div - 1) << CLK_PWM1_DIV_CON_SHIFT |
626                              CLK_PWM_PLL_SEL_GPLL << CLK_PWM1_PLL_SEL_SHIFT);
627                 break;
628         default:
629                 printf("do not support this pwm bus\n");
630                 return -EINVAL;
631         }
632
633         return px30_pwm_get_clk(priv, clk_id);
634 }
635
636 static ulong px30_saradc_get_clk(struct px30_clk_priv *priv)
637 {
638         struct px30_cru *cru = priv->cru;
639         u32 div, con;
640
641         con = readl(&cru->clksel_con[55]);
642         div = con >> CLK_SARADC_DIV_CON_SHIFT & CLK_SARADC_DIV_CON_MASK;
643
644         return DIV_TO_RATE(OSC_HZ, div);
645 }
646
647 static ulong px30_saradc_set_clk(struct px30_clk_priv *priv, uint hz)
648 {
649         struct px30_cru *cru = priv->cru;
650         int src_clk_div;
651
652         src_clk_div = DIV_ROUND_UP(OSC_HZ, hz);
653         assert(src_clk_div - 1 <= 2047);
654
655         rk_clrsetreg(&cru->clksel_con[55],
656                      CLK_SARADC_DIV_CON_MASK,
657                      (src_clk_div - 1) << CLK_SARADC_DIV_CON_SHIFT);
658
659         return px30_saradc_get_clk(priv);
660 }
661
662 static ulong px30_tsadc_get_clk(struct px30_clk_priv *priv)
663 {
664         struct px30_cru *cru = priv->cru;
665         u32 div, con;
666
667         con = readl(&cru->clksel_con[54]);
668         div = con >> CLK_SARADC_DIV_CON_SHIFT & CLK_SARADC_DIV_CON_MASK;
669
670         return DIV_TO_RATE(OSC_HZ, div);
671 }
672
673 static ulong px30_tsadc_set_clk(struct px30_clk_priv *priv, uint hz)
674 {
675         struct px30_cru *cru = priv->cru;
676         int src_clk_div;
677
678         src_clk_div = DIV_ROUND_UP(OSC_HZ, hz);
679         assert(src_clk_div - 1 <= 2047);
680
681         rk_clrsetreg(&cru->clksel_con[54],
682                      CLK_SARADC_DIV_CON_MASK,
683                      (src_clk_div - 1) << CLK_SARADC_DIV_CON_SHIFT);
684
685         return px30_tsadc_get_clk(priv);
686 }
687
688 static ulong px30_spi_get_clk(struct px30_clk_priv *priv, ulong clk_id)
689 {
690         struct px30_cru *cru = priv->cru;
691         u32 div, con;
692
693         switch (clk_id) {
694         case SCLK_SPI0:
695                 con = readl(&cru->clksel_con[53]);
696                 div = con >> CLK_SPI0_DIV_CON_SHIFT & CLK_SPI_DIV_CON_MASK;
697                 break;
698         case SCLK_SPI1:
699                 con = readl(&cru->clksel_con[53]);
700                 div = con >> CLK_SPI1_DIV_CON_SHIFT & CLK_SPI_DIV_CON_MASK;
701                 break;
702         default:
703                 printf("do not support this pwm bus\n");
704                 return -EINVAL;
705         }
706
707         return DIV_TO_RATE(priv->gpll_hz, div);
708 }
709
710 static ulong px30_spi_set_clk(struct px30_clk_priv *priv, ulong clk_id, uint hz)
711 {
712         struct px30_cru *cru = priv->cru;
713         int src_clk_div;
714
715         src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
716         assert(src_clk_div - 1 <= 127);
717
718         switch (clk_id) {
719         case SCLK_SPI0:
720                 rk_clrsetreg(&cru->clksel_con[53],
721                              CLK_SPI_DIV_CON_MASK << CLK_SPI0_DIV_CON_SHIFT |
722                              CLK_SPI_PLL_SEL_MASK << CLK_SPI0_PLL_SEL_SHIFT,
723                              (src_clk_div - 1) << CLK_SPI0_DIV_CON_SHIFT |
724                              CLK_SPI_PLL_SEL_GPLL << CLK_SPI0_PLL_SEL_SHIFT);
725                 break;
726         case SCLK_SPI1:
727                 rk_clrsetreg(&cru->clksel_con[53],
728                              CLK_SPI_DIV_CON_MASK << CLK_SPI1_DIV_CON_SHIFT |
729                              CLK_SPI_PLL_SEL_MASK << CLK_SPI1_PLL_SEL_SHIFT,
730                              (src_clk_div - 1) << CLK_SPI1_DIV_CON_SHIFT |
731                              CLK_SPI_PLL_SEL_GPLL << CLK_SPI1_PLL_SEL_SHIFT);
732                 break;
733         default:
734                 printf("do not support this pwm bus\n");
735                 return -EINVAL;
736         }
737
738         return px30_spi_get_clk(priv, clk_id);
739 }
740
741 static ulong px30_vop_get_clk(struct px30_clk_priv *priv, ulong clk_id)
742 {
743         struct px30_cru *cru = priv->cru;
744         u32 div, con, parent;
745
746         switch (clk_id) {
747         case ACLK_VOPB:
748         case ACLK_VOPL:
749                 con = readl(&cru->clksel_con[3]);
750                 div = con & ACLK_VO_DIV_MASK;
751                 parent = priv->gpll_hz;
752                 break;
753         case DCLK_VOPB:
754                 con = readl(&cru->clksel_con[5]);
755                 div = con & DCLK_VOPB_DIV_MASK;
756                 parent = rkclk_pll_get_rate(&cru->pll[CPLL], &cru->mode, CPLL);
757                 break;
758         case DCLK_VOPL:
759                 con = readl(&cru->clksel_con[8]);
760                 div = con & DCLK_VOPL_DIV_MASK;
761                 parent = rkclk_pll_get_rate(&cru->pll[NPLL], &cru->mode, NPLL);
762                 break;
763         default:
764                 return -ENOENT;
765         }
766
767         return DIV_TO_RATE(parent, div);
768 }
769
770 static ulong px30_vop_set_clk(struct px30_clk_priv *priv, ulong clk_id, uint hz)
771 {
772         struct px30_cru *cru = priv->cru;
773         ulong npll_hz;
774         int src_clk_div;
775
776         switch (clk_id) {
777         case ACLK_VOPB:
778         case ACLK_VOPL:
779                 src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
780                 assert(src_clk_div - 1 <= 31);
781                 rk_clrsetreg(&cru->clksel_con[3],
782                              ACLK_VO_PLL_MASK | ACLK_VO_DIV_MASK,
783                              ACLK_VO_SEL_GPLL << ACLK_VO_PLL_SHIFT |
784                              (src_clk_div - 1) << ACLK_VO_DIV_SHIFT);
785                 break;
786         case DCLK_VOPB:
787                 if (hz < PX30_VOP_PLL_LIMIT) {
788                         src_clk_div = DIV_ROUND_UP(PX30_VOP_PLL_LIMIT, hz);
789                         if (src_clk_div % 2)
790                                 src_clk_div = src_clk_div - 1;
791                 } else {
792                         src_clk_div = 1;
793                 }
794                 assert(src_clk_div - 1 <= 255);
795                 rkclk_set_pll(&cru->pll[CPLL], &cru->mode,
796                               CPLL, hz * src_clk_div);
797                 rk_clrsetreg(&cru->clksel_con[5],
798                              DCLK_VOPB_SEL_MASK | DCLK_VOPB_PLL_SEL_MASK |
799                              DCLK_VOPB_DIV_MASK,
800                              DCLK_VOPB_SEL_DIVOUT << DCLK_VOPB_SEL_SHIFT |
801                              DCLK_VOPB_PLL_SEL_CPLL << DCLK_VOPB_PLL_SEL_SHIFT |
802                              (src_clk_div - 1) << DCLK_VOPB_DIV_SHIFT);
803                 break;
804         case DCLK_VOPL:
805                 npll_hz = px30_clk_get_pll_rate(priv, NPLL);
806                 if (npll_hz >= PX30_VOP_PLL_LIMIT && npll_hz >= hz &&
807                     npll_hz % hz == 0) {
808                         src_clk_div = npll_hz / hz;
809                         assert(src_clk_div - 1 <= 255);
810                 } else {
811                         if (hz < PX30_VOP_PLL_LIMIT) {
812                                 src_clk_div = DIV_ROUND_UP(PX30_VOP_PLL_LIMIT,
813                                                            hz);
814                                 if (src_clk_div % 2)
815                                         src_clk_div = src_clk_div - 1;
816                         } else {
817                                 src_clk_div = 1;
818                         }
819                         assert(src_clk_div - 1 <= 255);
820                         rkclk_set_pll(&cru->pll[NPLL], &cru->mode, NPLL,
821                                       hz * src_clk_div);
822                 }
823                 rk_clrsetreg(&cru->clksel_con[8],
824                              DCLK_VOPL_SEL_MASK | DCLK_VOPL_PLL_SEL_MASK |
825                              DCLK_VOPL_DIV_MASK,
826                              DCLK_VOPL_SEL_DIVOUT << DCLK_VOPL_SEL_SHIFT |
827                              DCLK_VOPL_PLL_SEL_NPLL << DCLK_VOPL_PLL_SEL_SHIFT |
828                              (src_clk_div - 1) << DCLK_VOPL_DIV_SHIFT);
829                 break;
830         default:
831                 printf("do not support this vop freq\n");
832                 return -EINVAL;
833         }
834
835         return px30_vop_get_clk(priv, clk_id);
836 }
837
838 static ulong px30_bus_get_clk(struct px30_clk_priv *priv, ulong clk_id)
839 {
840         struct px30_cru *cru = priv->cru;
841         u32 div, con, parent;
842
843         switch (clk_id) {
844         case ACLK_BUS_PRE:
845                 con = readl(&cru->clksel_con[23]);
846                 div = (con & BUS_ACLK_DIV_MASK) >> BUS_ACLK_DIV_SHIFT;
847                 parent = priv->gpll_hz;
848                 break;
849         case HCLK_BUS_PRE:
850                 con = readl(&cru->clksel_con[24]);
851                 div = (con & BUS_HCLK_DIV_MASK) >> BUS_HCLK_DIV_SHIFT;
852                 parent = priv->gpll_hz;
853                 break;
854         case PCLK_BUS_PRE:
855         case PCLK_WDT_NS:
856                 parent = px30_bus_get_clk(priv, ACLK_BUS_PRE);
857                 con = readl(&cru->clksel_con[24]);
858                 div = (con & BUS_PCLK_DIV_MASK) >> BUS_PCLK_DIV_SHIFT;
859                 break;
860         default:
861                 return -ENOENT;
862         }
863
864         return DIV_TO_RATE(parent, div);
865 }
866
867 static ulong px30_bus_set_clk(struct px30_clk_priv *priv, ulong clk_id,
868                               ulong hz)
869 {
870         struct px30_cru *cru = priv->cru;
871         int src_clk_div;
872
873         /*
874          * select gpll as pd_bus bus clock source and
875          * set up dependent divisors for PCLK/HCLK and ACLK clocks.
876          */
877         switch (clk_id) {
878         case ACLK_BUS_PRE:
879                 src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
880                 assert(src_clk_div - 1 <= 31);
881                 rk_clrsetreg(&cru->clksel_con[23],
882                              BUS_PLL_SEL_MASK | BUS_ACLK_DIV_MASK,
883                              BUS_PLL_SEL_GPLL << BUS_PLL_SEL_SHIFT |
884                              (src_clk_div - 1) << BUS_ACLK_DIV_SHIFT);
885                 break;
886         case HCLK_BUS_PRE:
887                 src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
888                 assert(src_clk_div - 1 <= 31);
889                 rk_clrsetreg(&cru->clksel_con[24],
890                              BUS_PLL_SEL_MASK | BUS_HCLK_DIV_MASK,
891                              BUS_PLL_SEL_GPLL << BUS_PLL_SEL_SHIFT |
892                              (src_clk_div - 1) << BUS_HCLK_DIV_SHIFT);
893                 break;
894         case PCLK_BUS_PRE:
895                 src_clk_div =
896                         DIV_ROUND_UP(px30_bus_get_clk(priv, ACLK_BUS_PRE), hz);
897                 assert(src_clk_div - 1 <= 3);
898                 rk_clrsetreg(&cru->clksel_con[24],
899                              BUS_PCLK_DIV_MASK,
900                              (src_clk_div - 1) << BUS_PCLK_DIV_SHIFT);
901                 break;
902         default:
903                 printf("do not support this bus freq\n");
904                 return -EINVAL;
905         }
906
907         return px30_bus_get_clk(priv, clk_id);
908 }
909
910 static ulong px30_peri_get_clk(struct px30_clk_priv *priv, ulong clk_id)
911 {
912         struct px30_cru *cru = priv->cru;
913         u32 div, con, parent;
914
915         switch (clk_id) {
916         case ACLK_PERI_PRE:
917                 con = readl(&cru->clksel_con[14]);
918                 div = (con & PERI_ACLK_DIV_MASK) >> PERI_ACLK_DIV_SHIFT;
919                 parent = priv->gpll_hz;
920                 break;
921         case HCLK_PERI_PRE:
922                 con = readl(&cru->clksel_con[14]);
923                 div = (con & PERI_HCLK_DIV_MASK) >> PERI_HCLK_DIV_SHIFT;
924                 parent = priv->gpll_hz;
925                 break;
926         default:
927                 return -ENOENT;
928         }
929
930         return DIV_TO_RATE(parent, div);
931 }
932
933 static ulong px30_peri_set_clk(struct px30_clk_priv *priv, ulong clk_id,
934                                ulong hz)
935 {
936         struct px30_cru *cru = priv->cru;
937         int src_clk_div;
938
939         src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
940         assert(src_clk_div - 1 <= 31);
941
942         /*
943          * select gpll as pd_peri bus clock source and
944          * set up dependent divisors for HCLK and ACLK clocks.
945          */
946         switch (clk_id) {
947         case ACLK_PERI_PRE:
948                 rk_clrsetreg(&cru->clksel_con[14],
949                              PERI_PLL_SEL_MASK | PERI_ACLK_DIV_MASK,
950                              PERI_PLL_GPLL << PERI_PLL_SEL_SHIFT |
951                              (src_clk_div - 1) << PERI_ACLK_DIV_SHIFT);
952                 break;
953         case HCLK_PERI_PRE:
954                 rk_clrsetreg(&cru->clksel_con[14],
955                              PERI_PLL_SEL_MASK | PERI_HCLK_DIV_MASK,
956                              PERI_PLL_GPLL << PERI_PLL_SEL_SHIFT |
957                              (src_clk_div - 1) << PERI_HCLK_DIV_SHIFT);
958                 break;
959         default:
960                 printf("do not support this peri freq\n");
961                 return -EINVAL;
962         }
963
964         return px30_peri_get_clk(priv, clk_id);
965 }
966
967 #ifndef CONFIG_SPL_BUILD
968 static ulong px30_crypto_get_clk(struct px30_clk_priv *priv, ulong clk_id)
969 {
970         struct px30_cru *cru = priv->cru;
971         u32 div, con, parent;
972
973         switch (clk_id) {
974         case SCLK_CRYPTO:
975                 con = readl(&cru->clksel_con[25]);
976                 div = (con & CRYPTO_DIV_MASK) >> CRYPTO_DIV_SHIFT;
977                 parent = priv->gpll_hz;
978                 break;
979         case SCLK_CRYPTO_APK:
980                 con = readl(&cru->clksel_con[25]);
981                 div = (con & CRYPTO_APK_DIV_MASK) >> CRYPTO_APK_DIV_SHIFT;
982                 parent = priv->gpll_hz;
983                 break;
984         default:
985                 return -ENOENT;
986         }
987
988         return DIV_TO_RATE(parent, div);
989 }
990
991 static ulong px30_crypto_set_clk(struct px30_clk_priv *priv, ulong clk_id,
992                                  ulong hz)
993 {
994         struct px30_cru *cru = priv->cru;
995         int src_clk_div;
996
997         src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
998         assert(src_clk_div - 1 <= 31);
999
1000         /*
1001          * select gpll as crypto clock source and
1002          * set up dependent divisors for crypto clocks.
1003          */
1004         switch (clk_id) {
1005         case SCLK_CRYPTO:
1006                 rk_clrsetreg(&cru->clksel_con[25],
1007                              CRYPTO_PLL_SEL_MASK | CRYPTO_DIV_MASK,
1008                              CRYPTO_PLL_SEL_GPLL << CRYPTO_PLL_SEL_SHIFT |
1009                              (src_clk_div - 1) << CRYPTO_DIV_SHIFT);
1010                 break;
1011         case SCLK_CRYPTO_APK:
1012                 rk_clrsetreg(&cru->clksel_con[25],
1013                              CRYPTO_APK_PLL_SEL_MASK | CRYPTO_APK_DIV_MASK,
1014                              CRYPTO_PLL_SEL_GPLL << CRYPTO_APK_SEL_SHIFT |
1015                              (src_clk_div - 1) << CRYPTO_APK_DIV_SHIFT);
1016                 break;
1017         default:
1018                 printf("do not support this peri freq\n");
1019                 return -EINVAL;
1020         }
1021
1022         return px30_crypto_get_clk(priv, clk_id);
1023 }
1024
1025 static ulong px30_i2s1_mclk_get_clk(struct px30_clk_priv *priv, ulong clk_id)
1026 {
1027         struct px30_cru *cru = priv->cru;
1028         u32 con;
1029
1030         con = readl(&cru->clksel_con[30]);
1031
1032         if (!(con & CLK_I2S1_OUT_SEL_MASK))
1033                 return -ENOENT;
1034
1035         return 12000000;
1036 }
1037
1038 static ulong px30_i2s1_mclk_set_clk(struct px30_clk_priv *priv, ulong clk_id,
1039                                     ulong hz)
1040 {
1041         struct px30_cru *cru = priv->cru;
1042
1043         if (hz != 12000000) {
1044                 printf("do not support this i2s1_mclk freq\n");
1045                 return -EINVAL;
1046         }
1047
1048         rk_clrsetreg(&cru->clksel_con[30], CLK_I2S1_OUT_SEL_MASK,
1049                      CLK_I2S1_OUT_SEL_OSC);
1050         rk_clrsetreg(&cru->clkgate_con[10], CLK_I2S1_OUT_MCLK_PAD_MASK,
1051                      CLK_I2S1_OUT_MCLK_PAD_ENABLE);
1052
1053         return px30_i2s1_mclk_get_clk(priv, clk_id);
1054 }
1055
1056 static ulong px30_mac_set_clk(struct px30_clk_priv *priv, uint hz)
1057 {
1058         struct px30_cru *cru = priv->cru;
1059         u32 con = readl(&cru->clksel_con[22]);
1060         ulong pll_rate;
1061         u8 div;
1062
1063         if ((con >> GMAC_PLL_SEL_SHIFT) & GMAC_PLL_SEL_CPLL)
1064                 pll_rate = px30_clk_get_pll_rate(priv, CPLL);
1065         else if ((con >> GMAC_PLL_SEL_SHIFT) & GMAC_PLL_SEL_NPLL)
1066                 pll_rate = px30_clk_get_pll_rate(priv, NPLL);
1067         else
1068                 pll_rate = priv->gpll_hz;
1069
1070         /*default set 50MHZ for gmac*/
1071         if (!hz)
1072                 hz = 50000000;
1073
1074         div = DIV_ROUND_UP(pll_rate, hz) - 1;
1075         assert(div < 32);
1076         rk_clrsetreg(&cru->clksel_con[22], CLK_GMAC_DIV_MASK,
1077                      div << CLK_GMAC_DIV_SHIFT);
1078
1079         return DIV_TO_RATE(pll_rate, div);
1080 }
1081
1082 static int px30_mac_set_speed_clk(struct px30_clk_priv *priv, uint hz)
1083 {
1084         struct px30_cru *cru = priv->cru;
1085
1086         if (hz != 2500000 && hz != 25000000) {
1087                 debug("Unsupported mac speed:%d\n", hz);
1088                 return -EINVAL;
1089         }
1090
1091         rk_clrsetreg(&cru->clksel_con[23], RMII_CLK_SEL_MASK,
1092                      ((hz == 2500000) ? 0 : 1) << RMII_CLK_SEL_SHIFT);
1093
1094         return 0;
1095 }
1096
1097 #endif
1098
1099 static ulong px30_clk_get_pll_rate(struct px30_clk_priv *priv,
1100                                    enum px30_pll_id pll_id)
1101 {
1102         struct px30_cru *cru = priv->cru;
1103
1104         return rkclk_pll_get_rate(&cru->pll[pll_id], &cru->mode, pll_id);
1105 }
1106
1107 static ulong px30_clk_set_pll_rate(struct px30_clk_priv *priv,
1108                                    enum px30_pll_id pll_id, ulong hz)
1109 {
1110         struct px30_cru *cru = priv->cru;
1111
1112         if (rkclk_set_pll(&cru->pll[pll_id], &cru->mode, pll_id, hz))
1113                 return -EINVAL;
1114         return rkclk_pll_get_rate(&cru->pll[pll_id], &cru->mode, pll_id);
1115 }
1116
1117 static ulong px30_armclk_set_clk(struct px30_clk_priv *priv, ulong hz)
1118 {
1119         struct px30_cru *cru = priv->cru;
1120         const struct cpu_rate_table *rate;
1121         ulong old_rate;
1122
1123         rate = get_cpu_settings(hz);
1124         if (!rate) {
1125                 printf("%s unsupport rate\n", __func__);
1126                 return -EINVAL;
1127         }
1128
1129         /*
1130          * select apll as cpu/core clock pll source and
1131          * set up dependent divisors for PERI and ACLK clocks.
1132          * core hz : apll = 1:1
1133          */
1134         old_rate = px30_clk_get_pll_rate(priv, APLL);
1135         if (old_rate > hz) {
1136                 if (rkclk_set_pll(&cru->pll[APLL], &cru->mode, APLL, hz))
1137                         return -EINVAL;
1138                 rk_clrsetreg(&cru->clksel_con[0],
1139                              CORE_CLK_PLL_SEL_MASK | CORE_DIV_CON_MASK |
1140                              CORE_ACLK_DIV_MASK | CORE_DBG_DIV_MASK,
1141                              rate->aclk_div << CORE_ACLK_DIV_SHIFT |
1142                              rate->pclk_div << CORE_DBG_DIV_SHIFT |
1143                              CORE_CLK_PLL_SEL_APLL << CORE_CLK_PLL_SEL_SHIFT |
1144                              0 << CORE_DIV_CON_SHIFT);
1145         } else if (old_rate < hz) {
1146                 rk_clrsetreg(&cru->clksel_con[0],
1147                              CORE_CLK_PLL_SEL_MASK | CORE_DIV_CON_MASK |
1148                              CORE_ACLK_DIV_MASK | CORE_DBG_DIV_MASK,
1149                              rate->aclk_div << CORE_ACLK_DIV_SHIFT |
1150                              rate->pclk_div << CORE_DBG_DIV_SHIFT |
1151                              CORE_CLK_PLL_SEL_APLL << CORE_CLK_PLL_SEL_SHIFT |
1152                              0 << CORE_DIV_CON_SHIFT);
1153                 if (rkclk_set_pll(&cru->pll[APLL], &cru->mode, APLL, hz))
1154                         return -EINVAL;
1155         }
1156
1157         return px30_clk_get_pll_rate(priv, APLL);
1158 }
1159
1160 static ulong px30_clk_get_rate(struct clk *clk)
1161 {
1162         struct px30_clk_priv *priv = dev_get_priv(clk->dev);
1163         ulong rate = 0;
1164
1165         if (!priv->gpll_hz && clk->id > ARMCLK) {
1166                 printf("%s gpll=%lu\n", __func__, priv->gpll_hz);
1167                 return -ENOENT;
1168         }
1169
1170         debug("%s %ld\n", __func__, clk->id);
1171         switch (clk->id) {
1172         case PLL_APLL:
1173                 rate = px30_clk_get_pll_rate(priv, APLL);
1174                 break;
1175         case PLL_DPLL:
1176                 rate = px30_clk_get_pll_rate(priv, DPLL);
1177                 break;
1178         case PLL_CPLL:
1179                 rate = px30_clk_get_pll_rate(priv, CPLL);
1180                 break;
1181         case PLL_NPLL:
1182                 rate = px30_clk_get_pll_rate(priv, NPLL);
1183                 break;
1184         case ARMCLK:
1185                 rate = px30_clk_get_pll_rate(priv, APLL);
1186                 break;
1187         case HCLK_SDMMC:
1188         case HCLK_EMMC:
1189         case SCLK_SDMMC:
1190         case SCLK_EMMC:
1191         case SCLK_EMMC_SAMPLE:
1192                 rate = px30_mmc_get_clk(priv, clk->id);
1193                 break;
1194         case SCLK_I2C0:
1195         case SCLK_I2C1:
1196         case SCLK_I2C2:
1197         case SCLK_I2C3:
1198                 rate = px30_i2c_get_clk(priv, clk->id);
1199                 break;
1200         case SCLK_I2S1:
1201                 rate = px30_i2s_get_clk(priv, clk->id);
1202                 break;
1203         case SCLK_NANDC:
1204                 rate = px30_nandc_get_clk(priv);
1205                 break;
1206         case SCLK_PWM0:
1207         case SCLK_PWM1:
1208                 rate = px30_pwm_get_clk(priv, clk->id);
1209                 break;
1210         case SCLK_SARADC:
1211                 rate = px30_saradc_get_clk(priv);
1212                 break;
1213         case SCLK_TSADC:
1214                 rate = px30_tsadc_get_clk(priv);
1215                 break;
1216         case SCLK_SPI0:
1217         case SCLK_SPI1:
1218                 rate = px30_spi_get_clk(priv, clk->id);
1219                 break;
1220         case ACLK_VOPB:
1221         case ACLK_VOPL:
1222         case DCLK_VOPB:
1223         case DCLK_VOPL:
1224                 rate = px30_vop_get_clk(priv, clk->id);
1225                 break;
1226         case ACLK_BUS_PRE:
1227         case HCLK_BUS_PRE:
1228         case PCLK_BUS_PRE:
1229         case PCLK_WDT_NS:
1230                 rate = px30_bus_get_clk(priv, clk->id);
1231                 break;
1232         case ACLK_PERI_PRE:
1233         case HCLK_PERI_PRE:
1234                 rate = px30_peri_get_clk(priv, clk->id);
1235                 break;
1236 #ifndef CONFIG_SPL_BUILD
1237         case SCLK_CRYPTO:
1238         case SCLK_CRYPTO_APK:
1239                 rate = px30_crypto_get_clk(priv, clk->id);
1240                 break;
1241 #endif
1242         default:
1243                 return -ENOENT;
1244         }
1245
1246         return rate;
1247 }
1248
1249 static ulong px30_clk_set_rate(struct clk *clk, ulong rate)
1250 {
1251         struct px30_clk_priv *priv = dev_get_priv(clk->dev);
1252         ulong ret = 0;
1253
1254         if (!priv->gpll_hz && clk->id > ARMCLK) {
1255                 printf("%s gpll=%lu\n", __func__, priv->gpll_hz);
1256                 return -ENOENT;
1257         }
1258
1259         debug("%s %ld %ld\n", __func__, clk->id, rate);
1260         switch (clk->id) {
1261         case PLL_NPLL:
1262                 ret = px30_clk_set_pll_rate(priv, NPLL, rate);
1263                 break;
1264         case ARMCLK:
1265                 ret = px30_armclk_set_clk(priv, rate);
1266                 break;
1267         case HCLK_SDMMC:
1268         case HCLK_EMMC:
1269         case SCLK_SDMMC:
1270         case SCLK_EMMC:
1271                 ret = px30_mmc_set_clk(priv, clk->id, rate);
1272                 break;
1273         case SCLK_I2C0:
1274         case SCLK_I2C1:
1275         case SCLK_I2C2:
1276         case SCLK_I2C3:
1277                 ret = px30_i2c_set_clk(priv, clk->id, rate);
1278                 break;
1279         case SCLK_I2S1:
1280                 ret = px30_i2s_set_clk(priv, clk->id, rate);
1281                 break;
1282         case SCLK_NANDC:
1283                 ret = px30_nandc_set_clk(priv, rate);
1284                 break;
1285         case SCLK_PWM0:
1286         case SCLK_PWM1:
1287                 ret = px30_pwm_set_clk(priv, clk->id, rate);
1288                 break;
1289         case SCLK_SARADC:
1290                 ret = px30_saradc_set_clk(priv, rate);
1291                 break;
1292         case SCLK_TSADC:
1293                 ret = px30_tsadc_set_clk(priv, rate);
1294                 break;
1295         case SCLK_SPI0:
1296         case SCLK_SPI1:
1297                 ret = px30_spi_set_clk(priv, clk->id, rate);
1298                 break;
1299         case ACLK_VOPB:
1300         case ACLK_VOPL:
1301         case DCLK_VOPB:
1302         case DCLK_VOPL:
1303                 ret = px30_vop_set_clk(priv, clk->id, rate);
1304                 break;
1305         case ACLK_BUS_PRE:
1306         case HCLK_BUS_PRE:
1307         case PCLK_BUS_PRE:
1308                 ret = px30_bus_set_clk(priv, clk->id, rate);
1309                 break;
1310         case ACLK_PERI_PRE:
1311         case HCLK_PERI_PRE:
1312                 ret = px30_peri_set_clk(priv, clk->id, rate);
1313                 break;
1314 #ifndef CONFIG_SPL_BUILD
1315         case SCLK_CRYPTO:
1316         case SCLK_CRYPTO_APK:
1317                 ret = px30_crypto_set_clk(priv, clk->id, rate);
1318                 break;
1319         case SCLK_I2S1_OUT:
1320                 ret = px30_i2s1_mclk_set_clk(priv, clk->id, rate);
1321                 break;
1322         case SCLK_GMAC:
1323         case SCLK_GMAC_SRC:
1324                 ret = px30_mac_set_clk(priv, rate);
1325                 break;
1326         case SCLK_GMAC_RMII:
1327                 ret = px30_mac_set_speed_clk(priv, rate);
1328                 break;
1329 #endif
1330         default:
1331                 return -ENOENT;
1332         }
1333
1334         return ret;
1335 }
1336
1337 #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
1338 static int px30_gmac_set_parent(struct clk *clk, struct clk *parent)
1339 {
1340         struct px30_clk_priv *priv = dev_get_priv(clk->dev);
1341         struct px30_cru *cru = priv->cru;
1342
1343         if (parent->id == SCLK_GMAC_SRC) {
1344                 debug("%s: switching GAMC to SCLK_GMAC_SRC\n", __func__);
1345                 rk_clrsetreg(&cru->clksel_con[23], RMII_EXTCLK_SEL_MASK,
1346                              RMII_EXTCLK_SEL_INT << RMII_EXTCLK_SEL_SHIFT);
1347         } else {
1348                 debug("%s: switching GMAC to external clock\n", __func__);
1349                 rk_clrsetreg(&cru->clksel_con[23], RMII_EXTCLK_SEL_MASK,
1350                              RMII_EXTCLK_SEL_EXT << RMII_EXTCLK_SEL_SHIFT);
1351         }
1352         return 0;
1353 }
1354
1355 static int px30_clk_set_parent(struct clk *clk, struct clk *parent)
1356 {
1357         switch (clk->id) {
1358         case SCLK_GMAC:
1359                 return px30_gmac_set_parent(clk, parent);
1360         default:
1361                 return -ENOENT;
1362         }
1363 }
1364 #endif
1365
1366 static int px30_clk_enable(struct clk *clk)
1367 {
1368         switch (clk->id) {
1369         case HCLK_HOST:
1370         case SCLK_GMAC:
1371         case SCLK_GMAC_RX_TX:
1372         case SCLK_MAC_REF:
1373         case SCLK_MAC_REFOUT:
1374         case ACLK_GMAC:
1375         case PCLK_GMAC:
1376         case SCLK_GMAC_RMII:
1377                 /* Required to successfully probe the Designware GMAC driver */
1378                 return 0;
1379         }
1380
1381         debug("%s: unsupported clk %ld\n", __func__, clk->id);
1382         return -ENOENT;
1383 }
1384
1385 static struct clk_ops px30_clk_ops = {
1386         .get_rate = px30_clk_get_rate,
1387         .set_rate = px30_clk_set_rate,
1388 #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
1389         .set_parent = px30_clk_set_parent,
1390 #endif
1391         .enable = px30_clk_enable,
1392 };
1393
1394 static void px30_clk_init(struct px30_clk_priv *priv)
1395 {
1396         ulong npll_hz;
1397         int ret;
1398
1399         npll_hz = px30_clk_get_pll_rate(priv, NPLL);
1400         if (npll_hz != NPLL_HZ) {
1401                 ret = px30_clk_set_pll_rate(priv, NPLL, NPLL_HZ);
1402                 if (ret < 0)
1403                         printf("%s failed to set npll rate\n", __func__);
1404         }
1405
1406         px30_bus_set_clk(priv, ACLK_BUS_PRE, ACLK_BUS_HZ);
1407         px30_bus_set_clk(priv, HCLK_BUS_PRE, HCLK_BUS_HZ);
1408         px30_bus_set_clk(priv, PCLK_BUS_PRE, PCLK_BUS_HZ);
1409         px30_peri_set_clk(priv, ACLK_PERI_PRE, ACLK_PERI_HZ);
1410         px30_peri_set_clk(priv, HCLK_PERI_PRE, HCLK_PERI_HZ);
1411 }
1412
1413 static int px30_clk_probe(struct udevice *dev)
1414 {
1415         struct px30_clk_priv *priv = dev_get_priv(dev);
1416         struct clk clk_gpll;
1417         int ret;
1418
1419         if (px30_clk_get_pll_rate(priv, APLL) != APLL_HZ)
1420                 px30_armclk_set_clk(priv, APLL_HZ);
1421
1422         /* get the GPLL rate from the pmucru */
1423         ret = clk_get_by_name(dev, "gpll", &clk_gpll);
1424         if (ret) {
1425                 printf("%s: failed to get gpll clk from pmucru\n", __func__);
1426                 return ret;
1427         }
1428
1429         priv->gpll_hz = clk_get_rate(&clk_gpll);
1430
1431         px30_clk_init(priv);
1432
1433         return 0;
1434 }
1435
1436 static int px30_clk_of_to_plat(struct udevice *dev)
1437 {
1438         struct px30_clk_priv *priv = dev_get_priv(dev);
1439
1440         priv->cru = dev_read_addr_ptr(dev);
1441
1442         return 0;
1443 }
1444
1445 static int px30_clk_bind(struct udevice *dev)
1446 {
1447         int ret;
1448         struct udevice *sys_child;
1449         struct sysreset_reg *priv;
1450
1451         /* The reset driver does not have a device node, so bind it here */
1452         ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset",
1453                                  &sys_child);
1454         if (ret) {
1455                 debug("Warning: No sysreset driver: ret=%d\n", ret);
1456         } else {
1457                 priv = malloc(sizeof(struct sysreset_reg));
1458                 priv->glb_srst_fst_value = offsetof(struct px30_cru,
1459                                                     glb_srst_fst);
1460                 priv->glb_srst_snd_value = offsetof(struct px30_cru,
1461                                                     glb_srst_snd);
1462                 dev_set_priv(sys_child, priv);
1463         }
1464
1465 #if CONFIG_IS_ENABLED(RESET_ROCKCHIP)
1466         ret = offsetof(struct px30_cru, softrst_con[0]);
1467         ret = rockchip_reset_bind(dev, ret, 12);
1468         if (ret)
1469                 debug("Warning: software reset driver bind faile\n");
1470 #endif
1471
1472         return 0;
1473 }
1474
1475 static const struct udevice_id px30_clk_ids[] = {
1476         { .compatible = "rockchip,px30-cru" },
1477         { }
1478 };
1479
1480 U_BOOT_DRIVER(rockchip_px30_cru) = {
1481         .name           = "rockchip_px30_cru",
1482         .id             = UCLASS_CLK,
1483         .of_match       = px30_clk_ids,
1484         .priv_auto      = sizeof(struct px30_clk_priv),
1485         .of_to_plat = px30_clk_of_to_plat,
1486         .ops            = &px30_clk_ops,
1487         .bind           = px30_clk_bind,
1488         .probe          = px30_clk_probe,
1489 };
1490
1491 static ulong px30_pclk_pmu_get_pmuclk(struct px30_pmuclk_priv *priv)
1492 {
1493         struct px30_pmucru *pmucru = priv->pmucru;
1494         u32 div, con;
1495
1496         con = readl(&pmucru->pmu_clksel_con[0]);
1497         div = (con & CLK_PMU_PCLK_DIV_MASK) >> CLK_PMU_PCLK_DIV_SHIFT;
1498
1499         return DIV_TO_RATE(priv->gpll_hz, div);
1500 }
1501
1502 static ulong px30_pclk_pmu_set_pmuclk(struct px30_pmuclk_priv *priv, ulong hz)
1503 {
1504         struct px30_pmucru *pmucru = priv->pmucru;
1505         int src_clk_div;
1506
1507         src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
1508         assert(src_clk_div - 1 <= 31);
1509
1510         rk_clrsetreg(&pmucru->pmu_clksel_con[0],
1511                      CLK_PMU_PCLK_DIV_MASK,
1512                      (src_clk_div - 1) << CLK_PMU_PCLK_DIV_SHIFT);
1513
1514         return px30_pclk_pmu_get_pmuclk(priv);
1515 }
1516
1517 static ulong px30_pmuclk_get_gpll_rate(struct px30_pmuclk_priv *priv)
1518 {
1519         struct px30_pmucru *pmucru = priv->pmucru;
1520
1521         return rkclk_pll_get_rate(&pmucru->pll, &pmucru->pmu_mode, GPLL);
1522 }
1523
1524 static ulong px30_pmuclk_set_gpll_rate(struct px30_pmuclk_priv *priv, ulong hz)
1525 {
1526         struct px30_pmucru *pmucru = priv->pmucru;
1527         ulong pclk_pmu_rate;
1528         u32 div;
1529
1530         if (priv->gpll_hz == hz)
1531                 return priv->gpll_hz;
1532
1533         div = DIV_ROUND_UP(hz, priv->gpll_hz);
1534
1535         /* save clock rate */
1536         pclk_pmu_rate = px30_pclk_pmu_get_pmuclk(priv);
1537
1538         /* avoid rate too large, reduce rate first */
1539         px30_pclk_pmu_set_pmuclk(priv, pclk_pmu_rate / div);
1540
1541         /* change gpll rate */
1542         rkclk_set_pll(&pmucru->pll, &pmucru->pmu_mode, GPLL, hz);
1543         priv->gpll_hz = px30_pmuclk_get_gpll_rate(priv);
1544
1545         /* restore clock rate */
1546         px30_pclk_pmu_set_pmuclk(priv, pclk_pmu_rate);
1547
1548         return priv->gpll_hz;
1549 }
1550
1551 static ulong px30_pmuclk_get_rate(struct clk *clk)
1552 {
1553         struct px30_pmuclk_priv *priv = dev_get_priv(clk->dev);
1554         ulong rate = 0;
1555
1556         debug("%s %ld\n", __func__, clk->id);
1557         switch (clk->id) {
1558         case PLL_GPLL:
1559                 rate = px30_pmuclk_get_gpll_rate(priv);
1560                 break;
1561         case PCLK_PMU_PRE:
1562                 rate = px30_pclk_pmu_get_pmuclk(priv);
1563                 break;
1564         default:
1565                 return -ENOENT;
1566         }
1567
1568         return rate;
1569 }
1570
1571 static ulong px30_pmuclk_set_rate(struct clk *clk, ulong rate)
1572 {
1573         struct px30_pmuclk_priv *priv = dev_get_priv(clk->dev);
1574         ulong ret = 0;
1575
1576         debug("%s %ld %ld\n", __func__, clk->id, rate);
1577         switch (clk->id) {
1578         case PLL_GPLL:
1579                 ret = px30_pmuclk_set_gpll_rate(priv, rate);
1580                 break;
1581         case PCLK_PMU_PRE:
1582                 ret = px30_pclk_pmu_set_pmuclk(priv, rate);
1583                 break;
1584         default:
1585                 return -ENOENT;
1586         }
1587
1588         return ret;
1589 }
1590
1591 static struct clk_ops px30_pmuclk_ops = {
1592         .get_rate = px30_pmuclk_get_rate,
1593         .set_rate = px30_pmuclk_set_rate,
1594 };
1595
1596 static void px30_pmuclk_init(struct px30_pmuclk_priv *priv)
1597 {
1598         priv->gpll_hz = px30_pmuclk_get_gpll_rate(priv);
1599         px30_pmuclk_set_gpll_rate(priv, GPLL_HZ);
1600
1601         px30_pclk_pmu_set_pmuclk(priv, PCLK_PMU_HZ);
1602 }
1603
1604 static int px30_pmuclk_probe(struct udevice *dev)
1605 {
1606         struct px30_pmuclk_priv *priv = dev_get_priv(dev);
1607
1608         px30_pmuclk_init(priv);
1609
1610         return 0;
1611 }
1612
1613 static int px30_pmuclk_of_to_plat(struct udevice *dev)
1614 {
1615         struct px30_pmuclk_priv *priv = dev_get_priv(dev);
1616
1617         priv->pmucru = dev_read_addr_ptr(dev);
1618
1619         return 0;
1620 }
1621
1622 static const struct udevice_id px30_pmuclk_ids[] = {
1623         { .compatible = "rockchip,px30-pmucru" },
1624         { }
1625 };
1626
1627 U_BOOT_DRIVER(rockchip_px30_pmucru) = {
1628         .name           = "rockchip_px30_pmucru",
1629         .id             = UCLASS_CLK,
1630         .of_match       = px30_pmuclk_ids,
1631         .priv_auto      = sizeof(struct px30_pmuclk_priv),
1632         .of_to_plat = px30_pmuclk_of_to_plat,
1633         .ops            = &px30_pmuclk_ops,
1634         .probe          = px30_pmuclk_probe,
1635 };