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