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