blob: f83335df6db6b42ad86b3fb112233f741dd02765 [file] [log] [blame]
Paweł Jaroszbca89a52022-04-16 17:09:39 +02001// SPDX-License-Identifier: GPL-2.0
2/*
3 * (C) Copyright 2015 Google, Inc
4 * (C) Copyright 2016 Heiko Stuebner <heiko@sntech.de>
5 */
6
7#include <bitfield.h>
8#include <common.h>
9#include <clk-uclass.h>
10#include <dm.h>
11#include <dt-structs.h>
12#include <errno.h>
13#include <log.h>
14#include <malloc.h>
15#include <mapmem.h>
16#include <syscon.h>
Paweł Jaroszbca89a52022-04-16 17:09:39 +020017#include <asm/arch-rockchip/clock.h>
18#include <asm/arch-rockchip/cru_rk3066.h>
19#include <asm/arch-rockchip/grf_rk3066.h>
20#include <asm/arch-rockchip/hardware.h>
21#include <dt-bindings/clock/rk3066a-cru.h>
22#include <dm/device_compat.h>
23#include <dm/device-internal.h>
24#include <dm/lists.h>
25#include <dm/uclass-internal.h>
26#include <linux/delay.h>
27#include <linux/err.h>
28#include <linux/log2.h>
29#include <linux/stringify.h>
30
31struct rk3066_clk_plat {
32#if CONFIG_IS_ENABLED(OF_PLATDATA)
33 struct dtd_rockchip_rk3066a_cru dtd;
34#endif
35};
36
37struct pll_div {
38 u32 nr;
39 u32 nf;
40 u32 no;
41};
42
43enum {
44 VCO_MAX_HZ = 1416U * 1000000,
45 VCO_MIN_HZ = 300 * 1000000,
46 OUTPUT_MAX_HZ = 1416U * 1000000,
47 OUTPUT_MIN_HZ = 30 * 1000000,
48 FREF_MAX_HZ = 1416U * 1000000,
49 FREF_MIN_HZ = 30 * 1000,
50};
51
52enum {
53 /* PLL CON0 */
54 PLL_OD_MASK = GENMASK(3, 0),
55
56 /* PLL CON1 */
57 PLL_NF_MASK = GENMASK(12, 0),
58
59 /* PLL CON2 */
60 PLL_BWADJ_MASK = GENMASK(11, 0),
61
62 /* PLL CON3 */
63 PLL_RESET_SHIFT = 5,
64
65 /* GRF_SOC_STATUS0 */
66 SOCSTS_DPLL_LOCK = BIT(4),
67 SOCSTS_APLL_LOCK = BIT(5),
68 SOCSTS_CPLL_LOCK = BIT(6),
69 SOCSTS_GPLL_LOCK = BIT(7),
70};
71
72#define DIV_TO_RATE(input_rate, div) ((input_rate) / ((div) + 1))
73
74#define PLL_DIVISORS(hz, _nr, _no) {\
75 .nr = _nr, .nf = (u32)((u64)hz * _nr * _no / OSC_HZ), .no = _no};\
76 _Static_assert(((u64)hz * _nr * _no / OSC_HZ) * OSC_HZ /\
77 (_nr * _no) == hz, #hz "Hz cannot be hit with PLL "\
78 "divisors on line " __stringify(__LINE__))
79
80/* Keep divisors as low as possible to reduce jitter and power usage. */
81static const struct pll_div gpll_init_cfg = PLL_DIVISORS(GPLL_HZ, 2, 2);
82static const struct pll_div cpll_init_cfg = PLL_DIVISORS(CPLL_HZ, 1, 2);
83
84static int rk3066_clk_set_pll(struct rk3066_cru *cru, enum rk_clk_id clk_id,
85 const struct pll_div *div)
86{
87 int pll_id = rk_pll_id(clk_id);
88 struct rk3066_pll *pll = &cru->pll[pll_id];
89 /* All PLLs have the same VCO and output frequency range restrictions. */
90 uint vco_hz = OSC_HZ / 1000 * div->nf / div->nr * 1000;
91 uint output_hz = vco_hz / div->no;
92
93 debug("%s: PLL at %x: nf=%d, nr=%d, no=%d, vco=%u Hz, output=%u Hz\n", __func__,
94 (uint)pll, div->nf, div->nr, div->no, vco_hz, output_hz);
95 assert(vco_hz >= VCO_MIN_HZ && vco_hz <= VCO_MAX_HZ &&
96 output_hz >= OUTPUT_MIN_HZ && output_hz <= OUTPUT_MAX_HZ &&
97 (div->no == 1 || !(div->no % 2)));
98
99 /* Enter reset. */
100 rk_setreg(&pll->con3, BIT(PLL_RESET_SHIFT));
101
102 rk_clrsetreg(&pll->con0,
103 CLKR_MASK | PLL_OD_MASK,
104 ((div->nr - 1) << CLKR_SHIFT) | (div->no - 1));
105 rk_clrsetreg(&pll->con1, CLKF_MASK, div->nf - 1);
106
107 rk_clrsetreg(&pll->con2, PLL_BWADJ_MASK, (div->nf >> 1) - 1);
108
109 /* Exit reset. */
110 rk_clrreg(&pll->con3, BIT(PLL_RESET_SHIFT));
111
112 return 0;
113}
114
115static int rk3066_clk_configure_ddr(struct rk3066_cru *cru, struct rk3066_grf *grf,
116 unsigned int hz)
117{
118 static const struct pll_div dpll_cfg[] = {
119 {.nf = 25, .nr = 2, .no = 1},
120 {.nf = 400, .nr = 9, .no = 2},
121 {.nf = 500, .nr = 9, .no = 2},
122 {.nf = 100, .nr = 3, .no = 1},
123 };
124 int cfg;
125
126 switch (hz) {
127 case 300000000:
128 cfg = 0;
129 break;
130 case 533000000: /* actually 533.3P MHz */
131 cfg = 1;
132 break;
133 case 666000000: /* actually 666.6P MHz */
134 cfg = 2;
135 break;
136 case 800000000:
137 cfg = 3;
138 break;
139 default:
140 debug("%s: unsupported SDRAM frequency", __func__);
141 return -EINVAL;
142 }
143
144 /* Enter PLL slow mode. */
145 rk_clrsetreg(&cru->cru_mode_con, DPLL_MODE_MASK,
146 PLL_MODE_SLOW << DPLL_MODE_SHIFT);
147
148 rk3066_clk_set_pll(cru, CLK_DDR, &dpll_cfg[cfg]);
149
150 /* Wait for PLL lock. */
151 while (!(readl(&grf->soc_status0) & SOCSTS_DPLL_LOCK))
152 udelay(1);
153
154 /* Enter PLL normal mode. */
155 rk_clrsetreg(&cru->cru_mode_con, DPLL_MODE_MASK,
156 PLL_MODE_NORMAL << DPLL_MODE_SHIFT);
157
158 return 0;
159}
160
161static int rk3066_clk_configure_cpu(struct rk3066_cru *cru, struct rk3066_grf *grf,
162 unsigned int hz)
163{
164 static const struct pll_div apll_cfg[] = {
165 {.nf = 50, .nr = 1, .no = 2},
166 {.nf = 59, .nr = 1, .no = 1},
167 };
168 int div_core_peri, div_cpu_aclk, cfg;
169
170 /*
171 * We support two possible frequencies, the safe 600MHz
172 * which will work with default pmic settings and will
173 * be set to get away from the 24MHz default and
174 * the maximum of 1.416Ghz, which boards can set if they
175 * were able to get pmic support for it.
176 */
177 switch (hz) {
178 case APLL_SAFE_HZ:
179 cfg = 0;
180 div_core_peri = 1;
181 div_cpu_aclk = 3;
182 break;
183 case APLL_HZ:
184 cfg = 1;
185 div_core_peri = 2;
186 div_cpu_aclk = 3;
187 break;
188 default:
189 debug("unsupported ARMCLK frequency");
190 return -EINVAL;
191 }
192
193 /* Enter PLL slow mode. */
194 rk_clrsetreg(&cru->cru_mode_con, APLL_MODE_MASK,
195 PLL_MODE_SLOW << APLL_MODE_SHIFT);
196
197 rk3066_clk_set_pll(cru, CLK_ARM, &apll_cfg[cfg]);
198
199 /* Wait for PLL lock. */
200 while (!(readl(&grf->soc_status0) & SOCSTS_APLL_LOCK))
201 udelay(1);
202
203 /* Set divider for peripherals attached to the CPU core. */
204 rk_clrsetreg(&cru->cru_clksel_con[0],
205 CORE_PERI_DIV_MASK,
206 div_core_peri << CORE_PERI_DIV_SHIFT);
207
208 /* Set up dependent divisor for cpu_aclk. */
209 rk_clrsetreg(&cru->cru_clksel_con[1],
210 CPU_ACLK_DIV_MASK,
211 div_cpu_aclk << CPU_ACLK_DIV_SHIFT);
212
213 /* Enter PLL normal mode. */
214 rk_clrsetreg(&cru->cru_mode_con, APLL_MODE_MASK,
215 PLL_MODE_NORMAL << APLL_MODE_SHIFT);
216
217 return hz;
218}
219
220static uint32_t rk3066_clk_pll_get_rate(struct rk3066_cru *cru,
221 enum rk_clk_id clk_id)
222{
223 u32 nr, no, nf;
224 u32 con;
225 int pll_id = rk_pll_id(clk_id);
226 struct rk3066_pll *pll = &cru->pll[pll_id];
227 static u8 clk_shift[CLK_COUNT] = {
228 0xff, APLL_MODE_SHIFT, DPLL_MODE_SHIFT, CPLL_MODE_SHIFT,
229 GPLL_MODE_SHIFT
230 };
231 uint shift;
232
233 con = readl(&cru->cru_mode_con);
234 shift = clk_shift[clk_id];
235 switch (FIELD_GET(APLL_MODE_MASK, con >> shift)) {
236 case PLL_MODE_SLOW:
237 return OSC_HZ;
238 case PLL_MODE_NORMAL:
239 /* normal mode */
240 con = readl(&pll->con0);
241 no = bitfield_extract_by_mask(con, CLKOD_MASK) + 1;
242 nr = bitfield_extract_by_mask(con, CLKR_MASK) + 1;
243 con = readl(&pll->con1);
244 nf = bitfield_extract_by_mask(con, CLKF_MASK) + 1;
245
246 return (OSC_HZ * nf) / (nr * no);
247 case PLL_MODE_DEEP:
248 default:
249 return 32768;
250 }
251}
252
253static ulong rk3066_clk_mmc_get_clk(struct rk3066_cru *cru, uint gclk_rate,
254 int periph)
255{
256 uint div;
257 u32 con;
258
259 switch (periph) {
260 case HCLK_EMMC:
261 case SCLK_EMMC:
262 con = readl(&cru->cru_clksel_con[12]);
263 div = bitfield_extract_by_mask(con, EMMC_DIV_MASK);
264 break;
265 case HCLK_SDMMC:
266 case SCLK_SDMMC:
267 con = readl(&cru->cru_clksel_con[11]);
268 div = bitfield_extract_by_mask(con, MMC0_DIV_MASK);
269 break;
270 case HCLK_SDIO:
271 case SCLK_SDIO:
272 con = readl(&cru->cru_clksel_con[12]);
273 div = bitfield_extract_by_mask(con, SDIO_DIV_MASK);
274 break;
275 default:
276 return -EINVAL;
277 }
278
279 return DIV_TO_RATE(gclk_rate, div) / 2;
280}
281
282static ulong rk3066_clk_mmc_set_clk(struct rk3066_cru *cru, uint gclk_rate,
283 int periph, uint freq)
284{
285 int src_clk_div;
286
287 debug("%s: gclk_rate=%u\n", __func__, gclk_rate);
288 /* MMC clock by default divides by 2 internally, so need to provide double in CRU. */
289 src_clk_div = DIV_ROUND_UP(gclk_rate / 2, freq) - 1;
290 assert(src_clk_div <= 0x3f);
291
292 switch (periph) {
293 case HCLK_EMMC:
294 case SCLK_EMMC:
295 rk_clrsetreg(&cru->cru_clksel_con[12],
296 EMMC_DIV_MASK,
297 src_clk_div << EMMC_DIV_SHIFT);
298 break;
299 case HCLK_SDMMC:
300 case SCLK_SDMMC:
301 rk_clrsetreg(&cru->cru_clksel_con[11],
302 MMC0_DIV_MASK,
303 src_clk_div << MMC0_DIV_SHIFT);
304 break;
305 case HCLK_SDIO:
306 case SCLK_SDIO:
307 rk_clrsetreg(&cru->cru_clksel_con[12],
308 SDIO_DIV_MASK,
309 src_clk_div << SDIO_DIV_SHIFT);
310 break;
311 default:
312 return -EINVAL;
313 }
314
315 return rk3066_clk_mmc_get_clk(cru, gclk_rate, periph);
316}
317
318static ulong rk3066_clk_spi_get_clk(struct rk3066_cru *cru, uint gclk_rate,
319 int periph)
320{
321 uint div;
322 u32 con;
323
324 switch (periph) {
325 case SCLK_SPI0:
326 con = readl(&cru->cru_clksel_con[25]);
327 div = bitfield_extract_by_mask(con, SPI0_DIV_MASK);
328 break;
329 case SCLK_SPI1:
330 con = readl(&cru->cru_clksel_con[25]);
331 div = bitfield_extract_by_mask(con, SPI1_DIV_MASK);
332 break;
333 default:
334 return -EINVAL;
335 }
336
337 return DIV_TO_RATE(gclk_rate, div);
338}
339
340static ulong rk3066_clk_spi_set_clk(struct rk3066_cru *cru, uint gclk_rate,
341 int periph, uint freq)
342{
343 int src_clk_div = DIV_ROUND_UP(gclk_rate, freq) - 1;
344
345 assert(src_clk_div < 128);
346 switch (periph) {
347 case SCLK_SPI0:
348 assert(src_clk_div <= SPI0_DIV_MASK >> SPI0_DIV_SHIFT);
349 rk_clrsetreg(&cru->cru_clksel_con[25],
350 SPI0_DIV_MASK,
351 src_clk_div << SPI0_DIV_SHIFT);
352 break;
353 case SCLK_SPI1:
354 assert(src_clk_div <= SPI1_DIV_MASK >> SPI1_DIV_SHIFT);
355 rk_clrsetreg(&cru->cru_clksel_con[25],
356 SPI1_DIV_MASK,
357 src_clk_div << SPI1_DIV_SHIFT);
358 break;
359 default:
360 return -EINVAL;
361 }
362
363 return rk3066_clk_spi_get_clk(cru, gclk_rate, periph);
364}
365
366static ulong rk3066_clk_saradc_get_clk(struct rk3066_cru *cru, int periph)
367{
368 u32 div, con;
369
370 switch (periph) {
371 case SCLK_SARADC:
372 con = readl(&cru->cru_clksel_con[24]);
373 div = bitfield_extract_by_mask(con, SARADC_DIV_MASK);
374 break;
375 case SCLK_TSADC:
376 con = readl(&cru->cru_clksel_con[34]);
377 div = bitfield_extract_by_mask(con, TSADC_DIV_MASK);
378 break;
379 default:
380 return -EINVAL;
381 }
382 return DIV_TO_RATE(PERI_PCLK_HZ, div);
383}
384
385static ulong rk3066_clk_saradc_set_clk(struct rk3066_cru *cru, uint hz,
386 int periph)
387{
388 int src_clk_div;
389
390 src_clk_div = DIV_ROUND_UP(PERI_PCLK_HZ, hz) - 1;
391 assert(src_clk_div < 128);
392
393 switch (periph) {
394 case SCLK_SARADC:
395 rk_clrsetreg(&cru->cru_clksel_con[24],
396 SARADC_DIV_MASK,
397 src_clk_div << SARADC_DIV_SHIFT);
398 break;
399 case SCLK_TSADC:
400 rk_clrsetreg(&cru->cru_clksel_con[34],
401 SARADC_DIV_MASK,
402 src_clk_div << SARADC_DIV_SHIFT);
403 break;
404 default:
405 return -EINVAL;
406 }
407
408 return rk3066_clk_saradc_get_clk(cru, periph);
409}
410
411static void rk3066_clk_init(struct rk3066_cru *cru, struct rk3066_grf *grf)
412{
413 u32 aclk_div, hclk_div, pclk_div, h2p_div;
414
415 /* Enter PLL slow mode. */
416 rk_clrsetreg(&cru->cru_mode_con,
417 GPLL_MODE_MASK |
418 CPLL_MODE_MASK,
419 PLL_MODE_SLOW << GPLL_MODE_SHIFT |
420 PLL_MODE_SLOW << CPLL_MODE_SHIFT);
421
422 /* Init PLL. */
423 rk3066_clk_set_pll(cru, CLK_GENERAL, &gpll_init_cfg);
424 rk3066_clk_set_pll(cru, CLK_CODEC, &cpll_init_cfg);
425
426 /* Wait for PLL lock. */
427 while ((readl(&grf->soc_status0) &
428 (SOCSTS_CPLL_LOCK | SOCSTS_GPLL_LOCK)) !=
429 (SOCSTS_CPLL_LOCK | SOCSTS_GPLL_LOCK))
430 udelay(1);
431
432 /*
433 * Select CPU clock PLL source and
434 * reparent aclk_cpu_pre from APPL to GPLL.
435 * Set up dependent divisors for PCLK/HCLK and ACLK clocks.
436 */
437 aclk_div = DIV_ROUND_UP(GPLL_HZ, CPU_ACLK_HZ) - 1;
438 assert((aclk_div + 1) * CPU_ACLK_HZ == GPLL_HZ && aclk_div <= 0x1f);
439
440 rk_clrsetreg(&cru->cru_clksel_con[0],
441 CPU_ACLK_PLL_MASK |
442 A9_CORE_DIV_MASK,
443 CPU_ACLK_PLL_SELECT_GPLL << CPU_ACLK_PLL_SHIFT |
444 aclk_div << A9_CORE_DIV_SHIFT);
445
446 hclk_div = ilog2(CPU_ACLK_HZ / CPU_HCLK_HZ);
447 assert((1 << hclk_div) * CPU_HCLK_HZ == CPU_ACLK_HZ && hclk_div < 0x3);
448 pclk_div = ilog2(CPU_ACLK_HZ / CPU_PCLK_HZ);
449 assert((1 << pclk_div) * CPU_PCLK_HZ == CPU_ACLK_HZ && pclk_div < 0x4);
450 h2p_div = ilog2(CPU_HCLK_HZ / CPU_H2P_HZ);
451 assert((1 << h2p_div) * CPU_H2P_HZ == CPU_HCLK_HZ && pclk_div < 0x3);
452
453 rk_clrsetreg(&cru->cru_clksel_con[1],
454 AHB2APB_DIV_MASK |
455 CPU_PCLK_DIV_MASK |
456 CPU_HCLK_DIV_MASK,
457 h2p_div << AHB2APB_DIV_SHIFT |
458 pclk_div << CPU_PCLK_DIV_SHIFT |
459 hclk_div << CPU_HCLK_DIV_SHIFT);
460
461 /*
462 * Select PERI clock PLL source and
463 * set up dependent divisors for PCLK/HCLK and ACLK clocks.
464 */
465 aclk_div = GPLL_HZ / PERI_ACLK_HZ - 1;
466 assert((aclk_div + 1) * PERI_ACLK_HZ == GPLL_HZ && aclk_div < 0x1f);
467
468 hclk_div = ilog2(PERI_ACLK_HZ / PERI_HCLK_HZ);
469 assert((1 << hclk_div) * PERI_HCLK_HZ ==
470 PERI_ACLK_HZ && (hclk_div < 0x4));
471
472 pclk_div = ilog2(PERI_ACLK_HZ / PERI_PCLK_HZ);
473 assert((1 << pclk_div) * PERI_PCLK_HZ ==
474 PERI_ACLK_HZ && (pclk_div < 0x4));
475
476 rk_clrsetreg(&cru->cru_clksel_con[10],
477 PERI_PCLK_DIV_MASK |
478 PERI_HCLK_DIV_MASK |
479 PERI_ACLK_DIV_MASK,
480 PERI_SEL_GPLL << PERI_SEL_PLL_SHIFT |
481 pclk_div << PERI_PCLK_DIV_SHIFT |
482 hclk_div << PERI_HCLK_DIV_SHIFT |
483 aclk_div << PERI_ACLK_DIV_SHIFT);
484
485 /* Enter PLL normal mode. */
486 rk_clrsetreg(&cru->cru_mode_con,
487 GPLL_MODE_MASK |
488 CPLL_MODE_MASK,
489 PLL_MODE_NORMAL << GPLL_MODE_SHIFT |
490 PLL_MODE_NORMAL << CPLL_MODE_SHIFT);
491
492 rk3066_clk_mmc_set_clk(cru, PERI_HCLK_HZ, HCLK_SDMMC, 16000000);
493}
494
495static ulong rk3066_clk_get_rate(struct clk *clk)
496{
497 struct rk3066_clk_priv *priv = dev_get_priv(clk->dev);
498 ulong new_rate, gclk_rate;
499
500 gclk_rate = rk3066_clk_pll_get_rate(priv->cru, CLK_GENERAL);
501 switch (clk->id) {
502 case 1 ... 4:
503 new_rate = rk3066_clk_pll_get_rate(priv->cru, clk->id);
504 break;
505 case HCLK_EMMC:
506 case HCLK_SDMMC:
507 case HCLK_SDIO:
508 case SCLK_EMMC:
509 case SCLK_SDMMC:
510 case SCLK_SDIO:
511 new_rate = rk3066_clk_mmc_get_clk(priv->cru, PERI_HCLK_HZ,
512 clk->id);
513 break;
514 case SCLK_SPI0:
515 case SCLK_SPI1:
516 new_rate = rk3066_clk_spi_get_clk(priv->cru, PERI_PCLK_HZ,
517 clk->id);
518 break;
519 case PCLK_I2C0:
520 case PCLK_I2C1:
521 case PCLK_I2C2:
522 case PCLK_I2C3:
523 case PCLK_I2C4:
524 return gclk_rate;
525 case SCLK_SARADC:
526 case SCLK_TSADC:
527 new_rate = rk3066_clk_saradc_get_clk(priv->cru, clk->id);
528 break;
529 case SCLK_TIMER0:
530 case SCLK_TIMER1:
531 case SCLK_TIMER2:
532 case SCLK_UART0:
533 case SCLK_UART1:
534 case SCLK_UART2:
535 case SCLK_UART3:
536 return OSC_HZ;
537 default:
538 return -ENOENT;
539 }
540
541 return new_rate;
542}
543
544static ulong rk3066_clk_set_rate(struct clk *clk, ulong rate)
545{
546 struct rk3066_clk_priv *priv = dev_get_priv(clk->dev);
547 struct rk3066_cru *cru = priv->cru;
548 ulong new_rate;
549
550 switch (clk->id) {
551 case PLL_APLL:
552 new_rate = rk3066_clk_configure_cpu(priv->cru, priv->grf, rate);
553 break;
554 case CLK_DDR:
555 new_rate = rk3066_clk_configure_ddr(priv->cru, priv->grf, rate);
556 break;
557 case HCLK_EMMC:
558 case HCLK_SDMMC:
559 case HCLK_SDIO:
560 case SCLK_EMMC:
561 case SCLK_SDMMC:
562 case SCLK_SDIO:
563 new_rate = rk3066_clk_mmc_set_clk(cru, PERI_HCLK_HZ,
564 clk->id, rate);
565 break;
566 case SCLK_SPI0:
567 case SCLK_SPI1:
568 new_rate = rk3066_clk_spi_set_clk(cru, PERI_PCLK_HZ,
569 clk->id, rate);
570 break;
571 case SCLK_SARADC:
572 case SCLK_TSADC:
573 new_rate = rk3066_clk_saradc_set_clk(cru, rate, clk->id);
574 break;
575 case PLL_CPLL:
576 case PLL_GPLL:
577 case ACLK_CPU:
578 case HCLK_CPU:
579 case PCLK_CPU:
580 case ACLK_PERI:
581 case HCLK_PERI:
582 case PCLK_PERI:
583 return 0;
584 default:
585 return -ENOENT;
586 }
587
588 return new_rate;
589}
590
591static int rk3066_clk_enable(struct clk *clk)
592{
593 struct rk3066_clk_priv *priv = dev_get_priv(clk->dev);
594
595 switch (clk->id) {
596 case HCLK_NANDC0:
597 rk_clrreg(&priv->cru->cru_clkgate_con[5], BIT(9));
598 break;
599 case HCLK_SDMMC:
600 rk_clrreg(&priv->cru->cru_clkgate_con[5], BIT(10));
601 break;
602 case HCLK_SDIO:
603 rk_clrreg(&priv->cru->cru_clkgate_con[5], BIT(11));
604 break;
605 }
606
607 return 0;
608}
609
610static int rk3066_clk_disable(struct clk *clk)
611{
612 struct rk3066_clk_priv *priv = dev_get_priv(clk->dev);
613
614 switch (clk->id) {
615 case HCLK_NANDC0:
616 rk_setreg(&priv->cru->cru_clkgate_con[5], BIT(9));
617 break;
618 case HCLK_SDMMC:
619 rk_setreg(&priv->cru->cru_clkgate_con[5], BIT(10));
620 break;
621 case HCLK_SDIO:
622 rk_setreg(&priv->cru->cru_clkgate_con[5], BIT(11));
623 break;
624 }
625
626 return 0;
627}
628
629static struct clk_ops rk3066_clk_ops = {
630 .disable = rk3066_clk_disable,
631 .enable = rk3066_clk_enable,
632 .get_rate = rk3066_clk_get_rate,
633 .set_rate = rk3066_clk_set_rate,
634};
635
636static int rk3066_clk_of_to_plat(struct udevice *dev)
637{
638 if (CONFIG_IS_ENABLED(OF_REAL)) {
639 struct rk3066_clk_priv *priv = dev_get_priv(dev);
640
641 priv->cru = dev_read_addr_ptr(dev);
642 }
643
644 return 0;
645}
646
647static int rk3066_clk_probe(struct udevice *dev)
648{
649 struct rk3066_clk_priv *priv = dev_get_priv(dev);
650
651 priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
652 if (IS_ERR(priv->grf))
653 return PTR_ERR(priv->grf);
654
655#if CONFIG_IS_ENABLED(OF_PLATDATA)
656 struct rk3066_clk_plat *plat = dev_get_plat(dev);
657
658 priv->cru = map_sysmem(plat->dtd.reg[0], plat->dtd.reg[1]);
659#endif
660
661 if (IS_ENABLED(CONFIG_TPL_BUILD)) {
662 rk3066_clk_init(priv->cru, priv->grf);
663
664 /* Init CPU frequency. */
665 rk3066_clk_configure_cpu(priv->cru, priv->grf, APLL_SAFE_HZ);
666 }
667
668 return 0;
669}
670
671static int rk3066_clk_bind(struct udevice *dev)
672{
673 struct udevice *sys_child;
674 struct sysreset_reg *priv;
675 int reg_offset, ret;
676
677 /* The reset driver does not have a device node, so bind it here. */
678 ret = device_bind(dev, DM_DRIVER_GET(sysreset_rockchip), "sysreset",
679 NULL, ofnode_null(), &sys_child);
680 if (ret) {
681 dev_dbg(dev, "Warning: No sysreset driver: ret=%d\n", ret);
682 } else {
683 priv = malloc(sizeof(struct sysreset_reg));
684 priv->glb_srst_fst_value = offsetof(struct rk3066_cru,
685 cru_glb_srst_fst_value);
686 priv->glb_srst_snd_value = offsetof(struct rk3066_cru,
687 cru_glb_srst_snd_value);
688 dev_set_priv(sys_child, priv);
689 }
690
691 if (CONFIG_IS_ENABLED(RESET_ROCKCHIP)) {
692 reg_offset = offsetof(struct rk3066_cru, cru_softrst_con[0]);
693 ret = rockchip_reset_bind(dev, reg_offset, 9);
694 if (ret)
695 dev_dbg(dev, "Warning: software reset driver bind failed\n");
696 }
697
698 return 0;
699}
700
701static const struct udevice_id rk3066_clk_ids[] = {
702 { .compatible = "rockchip,rk3066a-cru" },
703 { }
704};
705
706U_BOOT_DRIVER(rockchip_rk3066a_cru) = {
707 .name = "rockchip_rk3066a_cru",
708 .id = UCLASS_CLK,
709 .ops = &rk3066_clk_ops,
710 .probe = rk3066_clk_probe,
711 .bind = rk3066_clk_bind,
712 .of_match = rk3066_clk_ids,
713 .of_to_plat = rk3066_clk_of_to_plat,
714 .priv_auto = sizeof(struct rk3066_clk_priv),
715 .plat_auto = sizeof(struct rk3066_clk_plat),
716};