2 * (C) Copyright 2015 Google, Inc
4 * SPDX-License-Identifier: GPL-2.0
13 #include <asm/arch/clock.h>
14 #include <asm/arch/cru_rk3288.h>
15 #include <asm/arch/grf_rk3288.h>
16 #include <asm/arch/hardware.h>
17 #include <asm/arch/periph.h>
20 DECLARE_GLOBAL_DATA_PTR
;
22 struct rk3288_clk_plat
{
23 enum rk_clk_id clk_id
;
26 struct rk3288_clk_priv
{
27 struct rk3288_grf
*grf
;
28 struct rk3288_cru
*cru
;
39 VCO_MAX_HZ
= 2200U * 1000000,
40 VCO_MIN_HZ
= 440 * 1000000,
41 OUTPUT_MAX_HZ
= 2200U * 1000000,
42 OUTPUT_MIN_HZ
= 27500000,
43 FREF_MAX_HZ
= 2200U * 1000000,
44 FREF_MIN_HZ
= 269 * 1000000,
55 PLL_BWADJ_MASK
= 0x0fff,
60 /* CLKSEL1: pd bus clk pll sel: codec or general */
61 PD_BUS_SEL_PLL_MASK
= 15,
65 /* pd bus pclk div: pclk = pd_bus_aclk /(div + 1) */
66 PD_BUS_PCLK_DIV_SHIFT
= 12,
67 PD_BUS_PCLK_DIV_MASK
= 7,
69 /* pd bus hclk div: aclk_bus: hclk_bus = 1:1 or 2:1 or 4:1 */
70 PD_BUS_HCLK_DIV_SHIFT
= 8,
71 PD_BUS_HCLK_DIV_MASK
= 3,
73 /* pd bus aclk div: pd_bus_aclk = pd_bus_src_clk /(div0 * div1) */
74 PD_BUS_ACLK_DIV0_SHIFT
= 3,
75 PD_BUS_ACLK_DIV0_MASK
= 0x1f,
76 PD_BUS_ACLK_DIV1_SHIFT
= 0,
77 PD_BUS_ACLK_DIV1_MASK
= 0x7,
81 * peripheral bus pclk div:
82 * aclk_bus: pclk_bus = 1:1 or 2:1 or 4:1 or 8:1
84 PERI_PCLK_DIV_SHIFT
= 12,
85 PERI_PCLK_DIV_MASK
= 7,
87 /* peripheral bus hclk div: aclk_bus: hclk_bus = 1:1 or 2:1 or 4:1 */
88 PERI_HCLK_DIV_SHIFT
= 8,
89 PERI_HCLK_DIV_MASK
= 3,
92 * peripheral bus aclk div:
93 * aclk_periph = periph_clk_src / (peri_aclk_div_con + 1)
95 PERI_ACLK_DIV_SHIFT
= 0,
96 PERI_ACLK_DIV_MASK
= 0x1f,
110 GPLL_MODE_SHIFT
= 12,
115 NPLL_MODE_SHIFT
= 14,
119 SOCSTS_DPLL_LOCK
= 1 << 5,
120 SOCSTS_APLL_LOCK
= 1 << 6,
121 SOCSTS_CPLL_LOCK
= 1 << 7,
122 SOCSTS_GPLL_LOCK
= 1 << 8,
123 SOCSTS_NPLL_LOCK
= 1 << 9,
126 #define RATE_TO_DIV(input_rate, output_rate) \
127 ((input_rate) / (output_rate) - 1);
129 #define DIV_TO_RATE(input_rate, div) ((input_rate) / ((div) + 1))
131 #define PLL_DIVISORS(hz, _nr, _no) {\
132 .nr = _nr, .nf = (u32)((u64)hz * _nr * _no / OSC_HZ), .no = _no};\
133 _Static_assert(((u64)hz * _nr * _no / OSC_HZ) * OSC_HZ /\
134 (_nr * _no) == hz, #hz "Hz cannot be hit with PLL "\
135 "divisors on line " __stringify(__LINE__));
137 /* Keep divisors as low as possible to reduce jitter and power usage */
138 static const struct pll_div apll_init_cfg
= PLL_DIVISORS(APLL_HZ
, 1, 1);
139 static const struct pll_div gpll_init_cfg
= PLL_DIVISORS(GPLL_HZ
, 2, 2);
140 static const struct pll_div cpll_init_cfg
= PLL_DIVISORS(CPLL_HZ
, 1, 2);
142 static int rkclk_set_pll(struct rk3288_cru
*cru
, enum rk_clk_id clk_id
,
143 const struct pll_div
*div
)
145 int pll_id
= rk_pll_id(clk_id
);
146 struct rk3288_pll
*pll
= &cru
->pll
[pll_id
];
147 /* All PLLs have same VCO and output frequency range restrictions. */
148 uint vco_hz
= OSC_HZ
/ 1000 * div
->nf
/ div
->nr
* 1000;
149 uint output_hz
= vco_hz
/ div
->no
;
151 debug("PLL at %p: nf=%d, nr=%d, no=%d, vco=%u Hz, output=%u Hz\n",
152 pll
, div
->nf
, div
->nr
, div
->no
, vco_hz
, output_hz
);
153 assert(vco_hz
>= VCO_MIN_HZ
&& vco_hz
<= VCO_MAX_HZ
&&
154 output_hz
>= OUTPUT_MIN_HZ
&& output_hz
<= OUTPUT_MAX_HZ
&&
155 (div
->no
== 1 || !(div
->no
% 2)));
158 rk_setreg(&pll
->con3
, 1 << PLL_RESET_SHIFT
);
160 rk_clrsetreg(&pll
->con0
,
161 CLKR_MASK
<< CLKR_SHIFT
| PLL_OD_MASK
,
162 ((div
->nr
- 1) << CLKR_SHIFT
) | (div
->no
- 1));
163 rk_clrsetreg(&pll
->con1
, CLKF_MASK
, div
->nf
- 1);
164 rk_clrsetreg(&pll
->con2
, PLL_BWADJ_MASK
, (div
->nf
>> 1) - 1);
168 /* return form rest */
169 rk_clrreg(&pll
->con3
, 1 << PLL_RESET_SHIFT
);
174 static inline unsigned int log2(unsigned int value
)
176 return fls(value
) - 1;
179 static int rkclk_configure_ddr(struct rk3288_cru
*cru
, struct rk3288_grf
*grf
,
182 static const struct pll_div dpll_cfg
[] = {
183 {.nf
= 25, .nr
= 2, .no
= 1},
184 {.nf
= 400, .nr
= 9, .no
= 2},
185 {.nf
= 500, .nr
= 9, .no
= 2},
186 {.nf
= 100, .nr
= 3, .no
= 1},
190 debug("%s: cru=%p, grf=%p, hz=%u\n", __func__
, cru
, grf
, hz
);
195 case 533000000: /* actually 533.3P MHz */
198 case 666000000: /* actually 666.6P MHz */
205 debug("Unsupported SDRAM frequency, add to clock.c!");
209 /* pll enter slow-mode */
210 rk_clrsetreg(&cru
->cru_mode_con
, DPLL_MODE_MASK
<< DPLL_MODE_SHIFT
,
211 DPLL_MODE_SLOW
<< DPLL_MODE_SHIFT
);
213 rkclk_set_pll(cru
, CLK_DDR
, &dpll_cfg
[cfg
]);
215 /* wait for pll lock */
216 while (!(readl(&grf
->soc_status
[1]) & SOCSTS_DPLL_LOCK
))
219 /* PLL enter normal-mode */
220 rk_clrsetreg(&cru
->cru_mode_con
, DPLL_MODE_MASK
<< DPLL_MODE_SHIFT
,
221 DPLL_MODE_NORM
<< DPLL_MODE_SHIFT
);
226 #ifdef CONFIG_SPL_BUILD
227 static void rkclk_init(struct rk3288_cru
*cru
, struct rk3288_grf
*grf
)
233 /* pll enter slow-mode */
234 rk_clrsetreg(&cru
->cru_mode_con
,
235 GPLL_MODE_MASK
<< GPLL_MODE_SHIFT
|
236 CPLL_MODE_MASK
<< CPLL_MODE_SHIFT
,
237 GPLL_MODE_SLOW
<< GPLL_MODE_SHIFT
|
238 CPLL_MODE_SLOW
<< CPLL_MODE_SHIFT
);
241 rkclk_set_pll(cru
, CLK_GENERAL
, &gpll_init_cfg
);
242 rkclk_set_pll(cru
, CLK_CODEC
, &cpll_init_cfg
);
244 /* waiting for pll lock */
245 while ((readl(&grf
->soc_status
[1]) &
246 (SOCSTS_CPLL_LOCK
| SOCSTS_GPLL_LOCK
)) !=
247 (SOCSTS_CPLL_LOCK
| SOCSTS_GPLL_LOCK
))
251 * pd_bus clock pll source selection and
252 * set up dependent divisors for PCLK/HCLK and ACLK clocks.
254 aclk_div
= GPLL_HZ
/ PD_BUS_ACLK_HZ
- 1;
255 assert((aclk_div
+ 1) * PD_BUS_ACLK_HZ
== GPLL_HZ
&& aclk_div
< 0x1f);
256 hclk_div
= PD_BUS_ACLK_HZ
/ PD_BUS_HCLK_HZ
- 1;
257 assert((hclk_div
+ 1) * PD_BUS_HCLK_HZ
==
258 PD_BUS_ACLK_HZ
&& (hclk_div
< 0x4) && (hclk_div
!= 0x2));
260 pclk_div
= PD_BUS_ACLK_HZ
/ PD_BUS_PCLK_HZ
- 1;
261 assert((pclk_div
+ 1) * PD_BUS_PCLK_HZ
==
262 PD_BUS_ACLK_HZ
&& pclk_div
< 0x7);
264 rk_clrsetreg(&cru
->cru_clksel_con
[1],
265 PD_BUS_PCLK_DIV_MASK
<< PD_BUS_PCLK_DIV_SHIFT
|
266 PD_BUS_HCLK_DIV_MASK
<< PD_BUS_HCLK_DIV_SHIFT
|
267 PD_BUS_ACLK_DIV0_MASK
<< PD_BUS_ACLK_DIV0_SHIFT
|
268 PD_BUS_ACLK_DIV1_MASK
<< PD_BUS_ACLK_DIV1_SHIFT
,
269 pclk_div
<< PD_BUS_PCLK_DIV_SHIFT
|
270 hclk_div
<< PD_BUS_HCLK_DIV_SHIFT
|
271 aclk_div
<< PD_BUS_ACLK_DIV0_SHIFT
|
275 * peri clock pll source selection and
276 * set up dependent divisors for PCLK/HCLK and ACLK clocks.
278 aclk_div
= GPLL_HZ
/ PERI_ACLK_HZ
- 1;
279 assert((aclk_div
+ 1) * PERI_ACLK_HZ
== GPLL_HZ
&& aclk_div
< 0x1f);
281 hclk_div
= log2(PERI_ACLK_HZ
/ PERI_HCLK_HZ
);
282 assert((1 << hclk_div
) * PERI_HCLK_HZ
==
283 PERI_ACLK_HZ
&& (hclk_div
< 0x4));
285 pclk_div
= log2(PERI_ACLK_HZ
/ PERI_PCLK_HZ
);
286 assert((1 << pclk_div
) * PERI_PCLK_HZ
==
287 PERI_ACLK_HZ
&& (pclk_div
< 0x4));
289 rk_clrsetreg(&cru
->cru_clksel_con
[10],
290 PERI_PCLK_DIV_MASK
<< PERI_PCLK_DIV_SHIFT
|
291 PERI_HCLK_DIV_MASK
<< PERI_HCLK_DIV_SHIFT
|
292 PERI_ACLK_DIV_MASK
<< PERI_ACLK_DIV_SHIFT
,
293 pclk_div
<< PERI_PCLK_DIV_SHIFT
|
294 hclk_div
<< PERI_HCLK_DIV_SHIFT
|
295 aclk_div
<< PERI_ACLK_DIV_SHIFT
);
297 /* PLL enter normal-mode */
298 rk_clrsetreg(&cru
->cru_mode_con
,
299 GPLL_MODE_MASK
<< GPLL_MODE_SHIFT
|
300 CPLL_MODE_MASK
<< CPLL_MODE_SHIFT
,
301 GPLL_MODE_NORM
<< GPLL_MODE_SHIFT
|
302 GPLL_MODE_NORM
<< CPLL_MODE_SHIFT
);
306 /* Get pll rate by id */
307 static uint32_t rkclk_pll_get_rate(struct rk3288_cru
*cru
,
308 enum rk_clk_id clk_id
)
312 int pll_id
= rk_pll_id(clk_id
);
313 struct rk3288_pll
*pll
= &cru
->pll
[pll_id
];
314 static u8 clk_shift
[CLK_COUNT
] = {
315 0xff, APLL_WORK_SHIFT
, DPLL_WORK_SHIFT
, CPLL_WORK_SHIFT
,
316 GPLL_WORK_SHIFT
, NPLL_WORK_SHIFT
320 con
= readl(&cru
->cru_mode_con
);
321 shift
= clk_shift
[clk_id
];
322 switch ((con
>> shift
) & APLL_WORK_MASK
) {
325 case APLL_WORK_NORMAL
:
327 con
= readl(&pll
->con0
);
328 no
= ((con
>> CLKOD_SHIFT
) & CLKOD_MASK
) + 1;
329 nr
= ((con
>> CLKR_SHIFT
) & CLKR_MASK
) + 1;
330 con
= readl(&pll
->con1
);
331 nf
= ((con
>> CLKF_SHIFT
) & CLKF_MASK
) + 1;
333 return (24 * nf
/ (nr
* no
)) * 1000000;
340 static ulong
rk3288_clk_get_rate(struct udevice
*dev
)
342 struct rk3288_clk_plat
*plat
= dev_get_platdata(dev
);
343 struct rk3288_clk_priv
*priv
= dev_get_priv(dev
);
345 debug("%s\n", dev
->name
);
346 return rkclk_pll_get_rate(priv
->cru
, plat
->clk_id
);
349 static ulong
rk3288_clk_set_rate(struct udevice
*dev
, ulong rate
)
351 struct rk3288_clk_plat
*plat
= dev_get_platdata(dev
);
352 struct rk3288_clk_priv
*priv
= dev_get_priv(dev
);
354 debug("%s\n", dev
->name
);
355 switch (plat
->clk_id
) {
357 rkclk_configure_ddr(priv
->cru
, priv
->grf
, rate
);
366 static ulong
rockchip_mmc_get_clk(struct rk3288_cru
*cru
, uint clk_general_rate
,
367 enum periph_id periph
)
375 con
= readl(&cru
->cru_clksel_con
[12]);
376 mux
= (con
>> EMMC_PLL_SHIFT
) & EMMC_PLL_MASK
;
377 div
= (con
>> EMMC_DIV_SHIFT
) & EMMC_DIV_MASK
;
379 case PERIPH_ID_SDCARD
:
380 con
= readl(&cru
->cru_clksel_con
[12]);
381 mux
= (con
>> MMC0_PLL_SHIFT
) & MMC0_PLL_MASK
;
382 div
= (con
>> MMC0_DIV_SHIFT
) & MMC0_DIV_MASK
;
384 case PERIPH_ID_SDMMC2
:
385 con
= readl(&cru
->cru_clksel_con
[12]);
386 mux
= (con
>> SDIO0_PLL_SHIFT
) & SDIO0_PLL_MASK
;
387 div
= (con
>> SDIO0_DIV_SHIFT
) & SDIO0_DIV_MASK
;
393 src_rate
= mux
== EMMC_PLL_SELECT_24MHZ
? OSC_HZ
: clk_general_rate
;
394 return DIV_TO_RATE(src_rate
, div
);
397 static ulong
rockchip_mmc_set_clk(struct rk3288_cru
*cru
, uint clk_general_rate
,
398 enum periph_id periph
, uint freq
)
403 debug("%s: clk_general_rate=%u\n", __func__
, clk_general_rate
);
404 src_clk_div
= RATE_TO_DIV(clk_general_rate
, freq
);
406 if (src_clk_div
> 0x3f) {
407 src_clk_div
= RATE_TO_DIV(OSC_HZ
, freq
);
408 mux
= EMMC_PLL_SELECT_24MHZ
;
409 assert((int)EMMC_PLL_SELECT_24MHZ
==
410 (int)MMC0_PLL_SELECT_24MHZ
);
412 mux
= EMMC_PLL_SELECT_GENERAL
;
413 assert((int)EMMC_PLL_SELECT_GENERAL
==
414 (int)MMC0_PLL_SELECT_GENERAL
);
418 rk_clrsetreg(&cru
->cru_clksel_con
[12],
419 EMMC_PLL_MASK
<< EMMC_PLL_SHIFT
|
420 EMMC_DIV_MASK
<< EMMC_DIV_SHIFT
,
421 mux
<< EMMC_PLL_SHIFT
|
422 (src_clk_div
- 1) << EMMC_DIV_SHIFT
);
424 case PERIPH_ID_SDCARD
:
425 rk_clrsetreg(&cru
->cru_clksel_con
[11],
426 MMC0_PLL_MASK
<< MMC0_PLL_SHIFT
|
427 MMC0_DIV_MASK
<< MMC0_DIV_SHIFT
,
428 mux
<< MMC0_PLL_SHIFT
|
429 (src_clk_div
- 1) << MMC0_DIV_SHIFT
);
431 case PERIPH_ID_SDMMC2
:
432 rk_clrsetreg(&cru
->cru_clksel_con
[12],
433 SDIO0_PLL_MASK
<< SDIO0_PLL_SHIFT
|
434 SDIO0_DIV_MASK
<< SDIO0_DIV_SHIFT
,
435 mux
<< SDIO0_PLL_SHIFT
|
436 (src_clk_div
- 1) << SDIO0_DIV_SHIFT
);
442 return rockchip_mmc_get_clk(cru
, clk_general_rate
, periph
);
445 static ulong
rockchip_spi_get_clk(struct rk3288_cru
*cru
, uint clk_general_rate
,
446 enum periph_id periph
)
453 con
= readl(&cru
->cru_clksel_con
[25]);
454 mux
= (con
>> SPI0_PLL_SHIFT
) & SPI0_PLL_MASK
;
455 div
= (con
>> SPI0_DIV_SHIFT
) & SPI0_DIV_MASK
;
458 con
= readl(&cru
->cru_clksel_con
[25]);
459 mux
= (con
>> SPI1_PLL_SHIFT
) & SPI1_PLL_MASK
;
460 div
= (con
>> SPI1_DIV_SHIFT
) & SPI1_DIV_MASK
;
463 con
= readl(&cru
->cru_clksel_con
[39]);
464 mux
= (con
>> SPI2_PLL_SHIFT
) & SPI2_PLL_MASK
;
465 div
= (con
>> SPI2_DIV_SHIFT
) & SPI2_DIV_MASK
;
470 assert(mux
== SPI0_PLL_SELECT_GENERAL
);
472 return DIV_TO_RATE(clk_general_rate
, div
);
475 static ulong
rockchip_spi_set_clk(struct rk3288_cru
*cru
, uint clk_general_rate
,
476 enum periph_id periph
, uint freq
)
480 debug("%s: clk_general_rate=%u\n", __func__
, clk_general_rate
);
481 src_clk_div
= RATE_TO_DIV(clk_general_rate
, freq
);
484 rk_clrsetreg(&cru
->cru_clksel_con
[25],
485 SPI0_PLL_MASK
<< SPI0_PLL_SHIFT
|
486 SPI0_DIV_MASK
<< SPI0_DIV_SHIFT
,
487 SPI0_PLL_SELECT_GENERAL
<< SPI0_PLL_SHIFT
|
488 src_clk_div
<< SPI0_DIV_SHIFT
);
491 rk_clrsetreg(&cru
->cru_clksel_con
[25],
492 SPI1_PLL_MASK
<< SPI1_PLL_SHIFT
|
493 SPI1_DIV_MASK
<< SPI1_DIV_SHIFT
,
494 SPI1_PLL_SELECT_GENERAL
<< SPI1_PLL_SHIFT
|
495 src_clk_div
<< SPI1_DIV_SHIFT
);
498 rk_clrsetreg(&cru
->cru_clksel_con
[39],
499 SPI2_PLL_MASK
<< SPI2_PLL_SHIFT
|
500 SPI2_DIV_MASK
<< SPI2_DIV_SHIFT
,
501 SPI2_PLL_SELECT_GENERAL
<< SPI2_PLL_SHIFT
|
502 src_clk_div
<< SPI2_DIV_SHIFT
);
508 return rockchip_spi_get_clk(cru
, clk_general_rate
, periph
);
511 ulong
rk3288_set_periph_rate(struct udevice
*dev
, int periph
, ulong rate
)
513 struct rk3288_clk_priv
*priv
= dev_get_priv(dev
);
518 case PERIPH_ID_SDCARD
:
519 new_rate
= rockchip_mmc_set_clk(priv
->cru
, clk_get_rate(dev
),
525 new_rate
= rockchip_spi_set_clk(priv
->cru
, clk_get_rate(dev
),
535 static struct clk_ops rk3288_clk_ops
= {
536 .get_rate
= rk3288_clk_get_rate
,
537 .set_rate
= rk3288_clk_set_rate
,
538 .set_periph_rate
= rk3288_set_periph_rate
,
541 static int rk3288_clk_probe(struct udevice
*dev
)
543 struct rk3288_clk_plat
*plat
= dev_get_platdata(dev
);
544 struct rk3288_clk_priv
*priv
= dev_get_priv(dev
);
546 if (plat
->clk_id
!= CLK_OSC
) {
547 struct rk3288_clk_priv
*parent_priv
= dev_get_priv(dev
->parent
);
549 priv
->cru
= parent_priv
->cru
;
550 priv
->grf
= parent_priv
->grf
;
553 priv
->cru
= (struct rk3288_cru
*)dev_get_addr(dev
);
554 priv
->grf
= syscon_get_first_range(ROCKCHIP_SYSCON_GRF
);
555 #ifdef CONFIG_SPL_BUILD
556 rkclk_init(priv
->cru
, priv
->grf
);
562 static const char *const clk_name
[CLK_COUNT
] = {
571 static int rk3288_clk_bind(struct udevice
*dev
)
573 struct rk3288_clk_plat
*plat
= dev_get_platdata(dev
);
576 /* We only need to set up the root clock */
577 if (dev
->of_offset
== -1) {
578 plat
->clk_id
= CLK_OSC
;
582 /* Create devices for P main clocks */
583 for (pll
= 1; pll
< CLK_COUNT
; pll
++) {
584 struct udevice
*child
;
585 struct rk3288_clk_plat
*cplat
;
587 debug("%s %s\n", __func__
, clk_name
[pll
]);
588 ret
= device_bind_driver(dev
, "clk_rk3288", clk_name
[pll
],
592 cplat
= dev_get_platdata(child
);
596 /* The reset driver does not have a device node, so bind it here */
597 ret
= device_bind_driver(gd
->dm_root
, "rk3288_reset", "reset", &dev
);
599 debug("Warning: No RK3288 reset driver: ret=%d\n", ret
);
604 static const struct udevice_id rk3288_clk_ids
[] = {
605 { .compatible
= "rockchip,rk3288-cru" },
609 U_BOOT_DRIVER(clk_rk3288
) = {
610 .name
= "clk_rk3288",
612 .of_match
= rk3288_clk_ids
,
613 .priv_auto_alloc_size
= sizeof(struct rk3288_clk_priv
),
614 .platdata_auto_alloc_size
= sizeof(struct rk3288_clk_plat
),
615 .ops
= &rk3288_clk_ops
,
616 .bind
= rk3288_clk_bind
,
617 .probe
= rk3288_clk_probe
,