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