blob: da9c48b962ab636e4178b630af779437d02e60cf [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0
Andy Yan6d95cd52017-06-01 18:00:36 +08002/*
3 * (C) Copyright 2016 Rockchip Electronics Co., Ltd
4 * Author: Andy Yan <andy.yan@rock-chips.com>
Andy Yan6d95cd52017-06-01 18:00:36 +08005 */
6
7#include <common.h>
David Wu0f106cc2017-09-20 14:28:18 +08008#include <bitfield.h>
Andy Yan6d95cd52017-06-01 18:00:36 +08009#include <clk-uclass.h>
10#include <dm.h>
11#include <errno.h>
Simon Glass9bc15642020-02-03 07:36:16 -070012#include <malloc.h>
Andy Yan6d95cd52017-06-01 18:00:36 +080013#include <syscon.h>
14#include <asm/io.h>
Kever Yang9fbe17c2019-03-28 11:01:23 +080015#include <asm/arch-rockchip/clock.h>
16#include <asm/arch-rockchip/cru_rv1108.h>
17#include <asm/arch-rockchip/hardware.h>
Andy Yan6d95cd52017-06-01 18:00:36 +080018#include <dm/lists.h>
19#include <dt-bindings/clock/rv1108-cru.h>
20
Otavio Salvador3afae5e2018-11-30 11:34:12 -020021DECLARE_GLOBAL_DATA_PTR;
22
Andy Yan6d95cd52017-06-01 18:00:36 +080023enum {
24 VCO_MAX_HZ = 2400U * 1000000,
25 VCO_MIN_HZ = 600 * 1000000,
26 OUTPUT_MAX_HZ = 2400U * 1000000,
27 OUTPUT_MIN_HZ = 24 * 1000000,
28};
29
Andy Yan6d95cd52017-06-01 18:00:36 +080030#define DIV_TO_RATE(input_rate, div) ((input_rate) / ((div) + 1))
31
32#define PLL_DIVISORS(hz, _refdiv, _postdiv1, _postdiv2) {\
33 .refdiv = _refdiv,\
34 .fbdiv = (u32)((u64)hz * _refdiv * _postdiv1 * _postdiv2 / OSC_HZ),\
35 .postdiv1 = _postdiv1, .postdiv2 = _postdiv2};\
36 _Static_assert(((u64)hz * _refdiv * _postdiv1 * _postdiv2 / OSC_HZ) *\
37 OSC_HZ / (_refdiv * _postdiv1 * _postdiv2) == hz,\
38 #hz "Hz cannot be hit with PLL "\
39 "divisors on line " __stringify(__LINE__));
40
Otavio Salvador3afae5e2018-11-30 11:34:12 -020041static const struct pll_div apll_init_cfg = PLL_DIVISORS(APLL_HZ, 1, 3, 1);
42static const struct pll_div gpll_init_cfg = PLL_DIVISORS(GPLL_HZ, 2, 2, 1);
43
David Wu0f106cc2017-09-20 14:28:18 +080044/* use integer mode */
Andy Yan6d95cd52017-06-01 18:00:36 +080045static inline int rv1108_pll_id(enum rk_clk_id clk_id)
46{
47 int id = 0;
48
49 switch (clk_id) {
50 case CLK_ARM:
51 case CLK_DDR:
52 id = clk_id - 1;
53 break;
54 case CLK_GENERAL:
55 id = 2;
56 break;
57 default:
58 printf("invalid pll id:%d\n", clk_id);
59 id = -1;
60 break;
61 }
62
63 return id;
64}
65
Otavio Salvador3afae5e2018-11-30 11:34:12 -020066static int rkclk_set_pll(struct rv1108_cru *cru, enum rk_clk_id clk_id,
67 const struct pll_div *div)
68{
69 int pll_id = rv1108_pll_id(clk_id);
70 struct rv1108_pll *pll = &cru->pll[pll_id];
71
72 /* All PLLs have same VCO and output frequency range restrictions. */
73 uint vco_hz = OSC_HZ / 1000 * div->fbdiv / div->refdiv * 1000;
74 uint output_hz = vco_hz / div->postdiv1 / div->postdiv2;
75
76 debug("PLL at %p: fb=%d, ref=%d, pst1=%d, pst2=%d, vco=%u Hz, output=%u Hz\n",
77 pll, div->fbdiv, div->refdiv, div->postdiv1,
78 div->postdiv2, vco_hz, output_hz);
79 assert(vco_hz >= VCO_MIN_HZ && vco_hz <= VCO_MAX_HZ &&
80 output_hz >= OUTPUT_MIN_HZ && output_hz <= OUTPUT_MAX_HZ);
81
82 /*
83 * When power on or changing PLL setting,
84 * we must force PLL into slow mode to ensure output stable clock.
85 */
86 rk_clrsetreg(&pll->con3, WORK_MODE_MASK,
87 WORK_MODE_SLOW << WORK_MODE_SHIFT);
88
89 /* use integer mode */
90 rk_setreg(&pll->con3, 1 << DSMPD_SHIFT);
91 /* Power down */
92 rk_setreg(&pll->con3, 1 << GLOBAL_POWER_DOWN_SHIFT);
93
94 rk_clrsetreg(&pll->con0, FBDIV_MASK, div->fbdiv << FBDIV_SHIFT);
95 rk_clrsetreg(&pll->con1, POSTDIV1_MASK | POSTDIV2_MASK | REFDIV_MASK,
96 (div->postdiv1 << POSTDIV1_SHIFT |
97 div->postdiv2 << POSTDIV2_SHIFT |
98 div->refdiv << REFDIV_SHIFT));
99 rk_clrsetreg(&pll->con2, FRACDIV_MASK,
100 (div->refdiv << REFDIV_SHIFT));
101
102 /* Power Up */
103 rk_clrreg(&pll->con3, 1 << GLOBAL_POWER_DOWN_SHIFT);
104
105 /* waiting for pll lock */
106 while (readl(&pll->con2) & (1 << LOCK_STA_SHIFT))
107 udelay(1);
108
109 /*
110 * set PLL into normal mode.
111 */
112 rk_clrsetreg(&pll->con3, WORK_MODE_MASK,
113 WORK_MODE_NORMAL << WORK_MODE_SHIFT);
114
115 return 0;
116}
117
Andy Yan6d95cd52017-06-01 18:00:36 +0800118static uint32_t rkclk_pll_get_rate(struct rv1108_cru *cru,
119 enum rk_clk_id clk_id)
120{
121 uint32_t refdiv, fbdiv, postdiv1, postdiv2;
122 uint32_t con0, con1, con3;
123 int pll_id = rv1108_pll_id(clk_id);
124 struct rv1108_pll *pll = &cru->pll[pll_id];
125 uint32_t freq;
126
127 con3 = readl(&pll->con3);
128
129 if (con3 & WORK_MODE_MASK) {
130 con0 = readl(&pll->con0);
131 con1 = readl(&pll->con1);
132 fbdiv = (con0 >> FBDIV_SHIFT) & FBDIV_MASK;
133 postdiv1 = (con1 & POSTDIV1_MASK) >> POSTDIV1_SHIFT;
134 postdiv2 = (con1 & POSTDIV2_MASK) >> POSTDIV2_SHIFT;
Otavio Salvador3afae5e2018-11-30 11:34:12 -0200135 refdiv = (con1 >> REFDIV_SHIFT) & REFDIV_MASK;
Andy Yan6d95cd52017-06-01 18:00:36 +0800136 freq = (24 * fbdiv / (refdiv * postdiv1 * postdiv2)) * 1000000;
137 } else {
138 freq = OSC_HZ;
139 }
140
141 return freq;
142}
143
144static int rv1108_mac_set_clk(struct rv1108_cru *cru, ulong rate)
145{
146 uint32_t con = readl(&cru->clksel_con[24]);
147 ulong pll_rate;
148 uint8_t div;
149
150 if ((con >> MAC_PLL_SEL_SHIFT) & MAC_PLL_SEL_GPLL)
151 pll_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
152 else
153 pll_rate = rkclk_pll_get_rate(cru, CLK_ARM);
154
155 /*default set 50MHZ for gmac*/
156 if (!rate)
157 rate = 50000000;
158
159 div = DIV_ROUND_UP(pll_rate, rate) - 1;
160 if (div <= 0x1f)
161 rk_clrsetreg(&cru->clksel_con[24], MAC_CLK_DIV_MASK,
162 div << MAC_CLK_DIV_SHIFT);
163 else
164 debug("Unsupported div for gmac:%d\n", div);
165
166 return DIV_TO_RATE(pll_rate, div);
167}
168
169static int rv1108_sfc_set_clk(struct rv1108_cru *cru, uint rate)
170{
171 u32 con = readl(&cru->clksel_con[27]);
172 u32 pll_rate;
173 u32 div;
174
175 if ((con >> SFC_PLL_SEL_SHIFT) && SFC_PLL_SEL_GPLL)
176 pll_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
177 else
178 pll_rate = rkclk_pll_get_rate(cru, CLK_DDR);
179
180 div = DIV_ROUND_UP(pll_rate, rate) - 1;
181 if (div <= 0x3f)
182 rk_clrsetreg(&cru->clksel_con[27], SFC_CLK_DIV_MASK,
183 div << SFC_CLK_DIV_SHIFT);
184 else
185 debug("Unsupported sfc clk rate:%d\n", rate);
186
187 return DIV_TO_RATE(pll_rate, div);
188}
189
David Wu0f106cc2017-09-20 14:28:18 +0800190static ulong rv1108_saradc_get_clk(struct rv1108_cru *cru)
191{
192 u32 div, val;
193
194 val = readl(&cru->clksel_con[22]);
195 div = bitfield_extract(val, CLK_SARADC_DIV_CON_SHIFT,
196 CLK_SARADC_DIV_CON_WIDTH);
197
198 return DIV_TO_RATE(OSC_HZ, div);
199}
200
201static ulong rv1108_saradc_set_clk(struct rv1108_cru *cru, uint hz)
202{
203 int src_clk_div;
204
205 src_clk_div = DIV_ROUND_UP(OSC_HZ, hz) - 1;
206 assert(src_clk_div < 128);
207
208 rk_clrsetreg(&cru->clksel_con[22],
209 CLK_SARADC_DIV_CON_MASK,
210 src_clk_div << CLK_SARADC_DIV_CON_SHIFT);
211
212 return rv1108_saradc_get_clk(cru);
213}
214
Otavio Salvador3afae5e2018-11-30 11:34:12 -0200215static ulong rv1108_aclk_vio1_get_clk(struct rv1108_cru *cru)
216{
217 u32 div, val;
218
219 val = readl(&cru->clksel_con[28]);
220 div = bitfield_extract(val, ACLK_VIO1_CLK_DIV_SHIFT,
221 CLK_VIO_DIV_CON_WIDTH);
222
223 return DIV_TO_RATE(GPLL_HZ, div);
224}
225
226static ulong rv1108_aclk_vio1_set_clk(struct rv1108_cru *cru, uint hz)
227{
228 int src_clk_div;
229
230 src_clk_div = DIV_ROUND_UP(GPLL_HZ, hz) - 1;
231 assert(src_clk_div < 32);
232
233 rk_clrsetreg(&cru->clksel_con[28],
234 ACLK_VIO1_CLK_DIV_MASK | ACLK_VIO1_PLL_SEL_MASK,
235 (src_clk_div << ACLK_VIO1_CLK_DIV_SHIFT) |
236 (VIO_PLL_SEL_GPLL << ACLK_VIO1_PLL_SEL_SHIFT));
237
238 return rv1108_aclk_vio1_get_clk(cru);
239}
240
241static ulong rv1108_aclk_vio0_get_clk(struct rv1108_cru *cru)
242{
243 u32 div, val;
244
245 val = readl(&cru->clksel_con[28]);
246 div = bitfield_extract(val, ACLK_VIO0_CLK_DIV_SHIFT,
247 CLK_VIO_DIV_CON_WIDTH);
248
249 return DIV_TO_RATE(GPLL_HZ, div);
250}
251
252static ulong rv1108_aclk_vio0_set_clk(struct rv1108_cru *cru, uint hz)
253{
254 int src_clk_div;
255
256 src_clk_div = DIV_ROUND_UP(GPLL_HZ, hz) - 1;
257 assert(src_clk_div < 32);
258
259 rk_clrsetreg(&cru->clksel_con[28],
260 ACLK_VIO0_CLK_DIV_MASK | ACLK_VIO0_PLL_SEL_MASK,
261 (src_clk_div << ACLK_VIO0_CLK_DIV_SHIFT) |
262 (VIO_PLL_SEL_GPLL << ACLK_VIO0_PLL_SEL_SHIFT));
263
264 /*HCLK_VIO default div = 4*/
265 rk_clrsetreg(&cru->clksel_con[29],
266 HCLK_VIO_CLK_DIV_MASK,
267 3 << HCLK_VIO_CLK_DIV_SHIFT);
268 /*PCLK_VIO default div = 4*/
269 rk_clrsetreg(&cru->clksel_con[29],
270 PCLK_VIO_CLK_DIV_MASK,
271 3 << PCLK_VIO_CLK_DIV_SHIFT);
272
273 return rv1108_aclk_vio0_get_clk(cru);
274}
275
276static ulong rv1108_dclk_vop_get_clk(struct rv1108_cru *cru)
277{
278 u32 div, val;
279
280 val = readl(&cru->clksel_con[32]);
281 div = bitfield_extract(val, DCLK_VOP_CLK_DIV_SHIFT,
282 DCLK_VOP_DIV_CON_WIDTH);
283
284 return DIV_TO_RATE(GPLL_HZ, div);
285}
286
287static ulong rv1108_dclk_vop_set_clk(struct rv1108_cru *cru, uint hz)
288{
289 int src_clk_div;
290
291 src_clk_div = DIV_ROUND_UP(GPLL_HZ, hz) - 1;
292 assert(src_clk_div < 64);
293
294 rk_clrsetreg(&cru->clksel_con[32],
295 DCLK_VOP_CLK_DIV_MASK | DCLK_VOP_PLL_SEL_MASK |
296 DCLK_VOP_SEL_SHIFT,
297 (src_clk_div << DCLK_VOP_CLK_DIV_SHIFT) |
298 (DCLK_VOP_PLL_SEL_GPLL << DCLK_VOP_PLL_SEL_SHIFT) |
299 (DCLK_VOP_SEL_PLL << DCLK_VOP_SEL_SHIFT));
300
301 return rv1108_dclk_vop_get_clk(cru);
302}
303
304static ulong rv1108_aclk_bus_get_clk(struct rv1108_cru *cru)
305{
306 u32 div, val;
307 ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
308
309 val = readl(&cru->clksel_con[2]);
310 div = bitfield_extract(val, ACLK_BUS_DIV_CON_SHIFT,
311 ACLK_BUS_DIV_CON_WIDTH);
312
313 return DIV_TO_RATE(parent_rate, div);
314}
315
316static ulong rv1108_aclk_bus_set_clk(struct rv1108_cru *cru, uint hz)
317{
318 int src_clk_div;
319 ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
320
321 src_clk_div = DIV_ROUND_UP(parent_rate, hz) - 1;
322 assert(src_clk_div < 32);
323
324 rk_clrsetreg(&cru->clksel_con[2],
325 ACLK_BUS_DIV_CON_MASK | ACLK_BUS_PLL_SEL_MASK,
326 (src_clk_div << ACLK_BUS_DIV_CON_SHIFT) |
327 (ACLK_BUS_PLL_SEL_GPLL << ACLK_BUS_PLL_SEL_SHIFT));
328
329 return rv1108_aclk_bus_get_clk(cru);
330}
331
332static ulong rv1108_aclk_peri_get_clk(struct rv1108_cru *cru)
333{
334 u32 div, val;
335 ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
336
337 val = readl(&cru->clksel_con[23]);
338 div = bitfield_extract(val, ACLK_PERI_DIV_CON_SHIFT,
339 PERI_DIV_CON_WIDTH);
340
341 return DIV_TO_RATE(parent_rate, div);
342}
343
344static ulong rv1108_hclk_peri_get_clk(struct rv1108_cru *cru)
345{
346 u32 div, val;
347 ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
348
349 val = readl(&cru->clksel_con[23]);
350 div = bitfield_extract(val, HCLK_PERI_DIV_CON_SHIFT,
351 PERI_DIV_CON_WIDTH);
352
353 return DIV_TO_RATE(parent_rate, div);
354}
355
356static ulong rv1108_pclk_peri_get_clk(struct rv1108_cru *cru)
357{
358 u32 div, val;
359 ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
360
361 val = readl(&cru->clksel_con[23]);
362 div = bitfield_extract(val, PCLK_PERI_DIV_CON_SHIFT,
363 PERI_DIV_CON_WIDTH);
364
365 return DIV_TO_RATE(parent_rate, div);
366}
367
368static ulong rv1108_aclk_peri_set_clk(struct rv1108_cru *cru, uint hz)
369{
370 int src_clk_div;
371 ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
372
373 src_clk_div = DIV_ROUND_UP(parent_rate, hz) - 1;
374 assert(src_clk_div < 32);
375
376 rk_clrsetreg(&cru->clksel_con[23],
377 ACLK_PERI_DIV_CON_MASK | ACLK_PERI_PLL_SEL_MASK,
378 (src_clk_div << ACLK_PERI_DIV_CON_SHIFT) |
379 (ACLK_PERI_PLL_SEL_GPLL << ACLK_PERI_PLL_SEL_SHIFT));
380
381 return rv1108_aclk_peri_get_clk(cru);
382}
383
384static ulong rv1108_hclk_peri_set_clk(struct rv1108_cru *cru, uint hz)
385{
386 int src_clk_div;
387 ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
388
389 src_clk_div = DIV_ROUND_UP(parent_rate, hz) - 1;
390 assert(src_clk_div < 32);
391
392 rk_clrsetreg(&cru->clksel_con[23],
393 HCLK_PERI_DIV_CON_MASK,
394 (src_clk_div << HCLK_PERI_DIV_CON_SHIFT));
395
396 return rv1108_hclk_peri_get_clk(cru);
397}
398
399static ulong rv1108_pclk_peri_set_clk(struct rv1108_cru *cru, uint hz)
400{
401 int src_clk_div;
402 ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
403
404 src_clk_div = DIV_ROUND_UP(parent_rate, hz) - 1;
405 assert(src_clk_div < 32);
406
407 rk_clrsetreg(&cru->clksel_con[23],
408 PCLK_PERI_DIV_CON_MASK,
409 (src_clk_div << PCLK_PERI_DIV_CON_SHIFT));
410
411 return rv1108_pclk_peri_get_clk(cru);
412}
413
414static ulong rv1108_i2c_get_clk(struct rv1108_cru *cru, ulong clk_id)
415{
416 u32 div, con;
417
418 switch (clk_id) {
419 case SCLK_I2C0_PMU:
420 con = readl(&cru->clksel_con[19]);
421 div = bitfield_extract(con, CLK_I2C0_DIV_CON_SHIFT,
422 I2C_DIV_CON_WIDTH);
423 break;
424 case SCLK_I2C1:
425 con = readl(&cru->clksel_con[19]);
426 div = bitfield_extract(con, CLK_I2C1_DIV_CON_SHIFT,
427 I2C_DIV_CON_WIDTH);
428 break;
429 case SCLK_I2C2:
430 con = readl(&cru->clksel_con[20]);
431 div = bitfield_extract(con, CLK_I2C2_DIV_CON_SHIFT,
432 I2C_DIV_CON_WIDTH);
433 break;
434 case SCLK_I2C3:
435 con = readl(&cru->clksel_con[20]);
436 div = bitfield_extract(con, CLK_I2C3_DIV_CON_SHIFT,
437 I2C_DIV_CON_WIDTH);
438 break;
439 default:
440 printf("do not support this i2c bus\n");
441 return -EINVAL;
442 }
443
444 return DIV_TO_RATE(GPLL_HZ, div);
445}
446
447static ulong rv1108_i2c_set_clk(struct rv1108_cru *cru, ulong clk_id, uint hz)
448{
449 int src_clk_div;
450
451 /* i2c0,4,8 src clock from ppll, i2c1,2,3,5,6,7 src clock from gpll*/
452 src_clk_div = GPLL_HZ / hz;
453 assert(src_clk_div - 1 <= 127);
454
455 switch (clk_id) {
456 case SCLK_I2C0_PMU:
457 rk_clrsetreg(&cru->clksel_con[19],
458 CLK_I2C0_DIV_CON_MASK | CLK_I2C1_PLL_SEL_MASK,
459 (src_clk_div << CLK_I2C0_DIV_CON_SHIFT) |
460 (CLK_I2C1_PLL_SEL_GPLL << CLK_I2C1_PLL_SEL_SHIFT));
461 break;
462 case SCLK_I2C1:
463 rk_clrsetreg(&cru->clksel_con[19],
464 CLK_I2C1_DIV_CON_MASK | CLK_I2C1_PLL_SEL_MASK,
465 (src_clk_div << CLK_I2C1_DIV_CON_SHIFT) |
466 (CLK_I2C1_PLL_SEL_GPLL << CLK_I2C1_PLL_SEL_SHIFT));
467 break;
468 case SCLK_I2C2:
469 rk_clrsetreg(&cru->clksel_con[20],
470 CLK_I2C2_DIV_CON_MASK | CLK_I2C3_PLL_SEL_MASK,
471 (src_clk_div << CLK_I2C2_DIV_CON_SHIFT) |
472 (CLK_I2C3_PLL_SEL_GPLL << CLK_I2C3_PLL_SEL_SHIFT));
473 break;
474 case SCLK_I2C3:
475 rk_clrsetreg(&cru->clksel_con[20],
476 CLK_I2C3_DIV_CON_MASK | CLK_I2C3_PLL_SEL_MASK,
477 (src_clk_div << CLK_I2C3_DIV_CON_SHIFT) |
478 (CLK_I2C3_PLL_SEL_GPLL << CLK_I2C3_PLL_SEL_SHIFT));
479 break;
480 default:
481 printf("do not support this i2c bus\n");
482 return -EINVAL;
483 }
484
485 return rv1108_i2c_get_clk(cru, clk_id);
486}
487
488static ulong rv1108_mmc_get_clk(struct rv1108_cru *cru)
489{
490 u32 div, con;
491 ulong mmc_clk;
492
493 con = readl(&cru->clksel_con[26]);
494 div = bitfield_extract(con, EMMC_CLK_DIV_SHIFT, 8);
495
496 con = readl(&cru->clksel_con[25]);
497
498 if ((con & EMMC_PLL_SEL_MASK) >> EMMC_PLL_SEL_SHIFT == EMMC_PLL_SEL_OSC)
499 mmc_clk = DIV_TO_RATE(OSC_HZ, div) / 2;
500 else
501 mmc_clk = DIV_TO_RATE(GPLL_HZ, div) / 2;
502
503 debug("%s div %d get_clk %ld\n", __func__, div, mmc_clk);
504 return mmc_clk;
505}
506
507static ulong rv1108_mmc_set_clk(struct rv1108_cru *cru, ulong rate)
508{
509 int div;
510 u32 pll_rate;
511
512 div = DIV_ROUND_UP(rkclk_pll_get_rate(cru, CLK_GENERAL), rate);
513
514 if (div < 127) {
515 debug("%s source gpll\n", __func__);
516 rk_clrsetreg(&cru->clksel_con[25], EMMC_PLL_SEL_MASK,
517 (EMMC_PLL_SEL_GPLL << EMMC_PLL_SEL_SHIFT));
518 pll_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
519 } else {
520 debug("%s source 24m\n", __func__);
521 rk_clrsetreg(&cru->clksel_con[25], EMMC_PLL_SEL_MASK,
522 (EMMC_PLL_SEL_OSC << EMMC_PLL_SEL_SHIFT));
523 pll_rate = OSC_HZ;
524 }
525
526 div = DIV_ROUND_UP(pll_rate / 2, rate);
527 rk_clrsetreg(&cru->clksel_con[26], EMMC_CLK_DIV_MASK,
528 ((div - 1) << EMMC_CLK_DIV_SHIFT));
529
530 debug("%s set_rate %ld div %d\n", __func__, rate, div);
531
532 return DIV_TO_RATE(pll_rate, div);
533}
534
Andy Yan6d95cd52017-06-01 18:00:36 +0800535static ulong rv1108_clk_get_rate(struct clk *clk)
536{
537 struct rv1108_clk_priv *priv = dev_get_priv(clk->dev);
538
539 switch (clk->id) {
540 case 0 ... 63:
541 return rkclk_pll_get_rate(priv->cru, clk->id);
David Wu0f106cc2017-09-20 14:28:18 +0800542 case SCLK_SARADC:
543 return rv1108_saradc_get_clk(priv->cru);
Otavio Salvador3afae5e2018-11-30 11:34:12 -0200544 case ACLK_VIO0:
545 return rv1108_aclk_vio0_get_clk(priv->cru);
546 case ACLK_VIO1:
547 return rv1108_aclk_vio1_get_clk(priv->cru);
548 case DCLK_VOP:
549 return rv1108_dclk_vop_get_clk(priv->cru);
550 case ACLK_PRE:
551 return rv1108_aclk_bus_get_clk(priv->cru);
552 case ACLK_PERI:
553 return rv1108_aclk_peri_get_clk(priv->cru);
554 case HCLK_PERI:
555 return rv1108_hclk_peri_get_clk(priv->cru);
556 case PCLK_PERI:
557 return rv1108_pclk_peri_get_clk(priv->cru);
558 case SCLK_I2C0_PMU:
559 case SCLK_I2C1:
560 case SCLK_I2C2:
561 case SCLK_I2C3:
562 return rv1108_i2c_get_clk(priv->cru, clk->id);
563 case HCLK_EMMC:
564 case SCLK_EMMC:
565 case SCLK_EMMC_SAMPLE:
566 return rv1108_mmc_get_clk(priv->cru);
Andy Yan6d95cd52017-06-01 18:00:36 +0800567 default:
568 return -ENOENT;
569 }
570}
571
572static ulong rv1108_clk_set_rate(struct clk *clk, ulong rate)
573{
574 struct rv1108_clk_priv *priv = dev_get_priv(clk->dev);
575 ulong new_rate;
576
577 switch (clk->id) {
578 case SCLK_MAC:
579 new_rate = rv1108_mac_set_clk(priv->cru, rate);
580 break;
581 case SCLK_SFC:
582 new_rate = rv1108_sfc_set_clk(priv->cru, rate);
583 break;
David Wu0f106cc2017-09-20 14:28:18 +0800584 case SCLK_SARADC:
585 new_rate = rv1108_saradc_set_clk(priv->cru, rate);
586 break;
Otavio Salvador3afae5e2018-11-30 11:34:12 -0200587 case ACLK_VIO0:
588 new_rate = rv1108_aclk_vio0_set_clk(priv->cru, rate);
589 break;
590 case ACLK_VIO1:
591 new_rate = rv1108_aclk_vio1_set_clk(priv->cru, rate);
592 break;
593 case DCLK_VOP:
594 new_rate = rv1108_dclk_vop_set_clk(priv->cru, rate);
595 break;
596 case ACLK_PRE:
597 new_rate = rv1108_aclk_bus_set_clk(priv->cru, rate);
598 break;
599 case ACLK_PERI:
600 new_rate = rv1108_aclk_peri_set_clk(priv->cru, rate);
601 break;
602 case HCLK_PERI:
603 new_rate = rv1108_hclk_peri_set_clk(priv->cru, rate);
604 break;
605 case PCLK_PERI:
606 new_rate = rv1108_pclk_peri_set_clk(priv->cru, rate);
607 break;
608 case SCLK_I2C0_PMU:
609 case SCLK_I2C1:
610 case SCLK_I2C2:
611 case SCLK_I2C3:
612 new_rate = rv1108_i2c_set_clk(priv->cru, clk->id, rate);
613 break;
614 case HCLK_EMMC:
615 case SCLK_EMMC:
616 new_rate = rv1108_mmc_set_clk(priv->cru, rate);
617 break;
Andy Yan6d95cd52017-06-01 18:00:36 +0800618 default:
619 return -ENOENT;
620 }
621
622 return new_rate;
623}
624
625static const struct clk_ops rv1108_clk_ops = {
626 .get_rate = rv1108_clk_get_rate,
627 .set_rate = rv1108_clk_set_rate,
628};
629
630static void rkclk_init(struct rv1108_cru *cru)
631{
Otavio Salvador3afae5e2018-11-30 11:34:12 -0200632 unsigned int apll, dpll, gpll;
633 unsigned int aclk_bus, aclk_peri, hclk_peri, pclk_peri;
634
635 aclk_bus = rv1108_aclk_bus_set_clk(cru, ACLK_BUS_HZ / 2);
636 aclk_peri = rv1108_aclk_peri_set_clk(cru, ACLK_PERI_HZ / 2);
637 hclk_peri = rv1108_hclk_peri_set_clk(cru, HCLK_PERI_HZ / 2);
638 pclk_peri = rv1108_pclk_peri_set_clk(cru, PCLK_PERI_HZ / 2);
639 rv1108_aclk_vio0_set_clk(cru, 297000000);
640 rv1108_aclk_vio1_set_clk(cru, 297000000);
641
642 /* configure apll */
643 rkclk_set_pll(cru, CLK_ARM, &apll_init_cfg);
644 rkclk_set_pll(cru, CLK_GENERAL, &gpll_init_cfg);
645 aclk_bus = rv1108_aclk_bus_set_clk(cru, ACLK_BUS_HZ);
646 aclk_peri = rv1108_aclk_peri_set_clk(cru, ACLK_PERI_HZ);
647 hclk_peri = rv1108_hclk_peri_set_clk(cru, HCLK_PERI_HZ);
648 pclk_peri = rv1108_pclk_peri_set_clk(cru, PCLK_PERI_HZ);
649
650 apll = rkclk_pll_get_rate(cru, CLK_ARM);
651 dpll = rkclk_pll_get_rate(cru, CLK_DDR);
652 gpll = rkclk_pll_get_rate(cru, CLK_GENERAL);
Andy Yan6d95cd52017-06-01 18:00:36 +0800653
654 rk_clrsetreg(&cru->clksel_con[0], CORE_CLK_DIV_MASK,
655 0 << MAC_CLK_DIV_SHIFT);
656
657 printf("APLL: %d DPLL:%d GPLL:%d\n", apll, dpll, gpll);
Otavio Salvador3afae5e2018-11-30 11:34:12 -0200658 printf("ACLK_BUS: %d ACLK_PERI:%d HCLK_PERI:%d PCLK_PERI:%d\n",
659 aclk_bus, aclk_peri, hclk_peri, pclk_peri);
Andy Yan6d95cd52017-06-01 18:00:36 +0800660}
661
Kever Yang216cccb2018-04-24 11:27:08 +0800662static int rv1108_clk_ofdata_to_platdata(struct udevice *dev)
Andy Yan6d95cd52017-06-01 18:00:36 +0800663{
664 struct rv1108_clk_priv *priv = dev_get_priv(dev);
665
Kever Yanga70fe322018-02-11 11:53:10 +0800666 priv->cru = dev_read_addr_ptr(dev);
Andy Yan6d95cd52017-06-01 18:00:36 +0800667
Kever Yang216cccb2018-04-24 11:27:08 +0800668 return 0;
669}
670
671static int rv1108_clk_probe(struct udevice *dev)
672{
673 struct rv1108_clk_priv *priv = dev_get_priv(dev);
674
Andy Yan6d95cd52017-06-01 18:00:36 +0800675 rkclk_init(priv->cru);
676
677 return 0;
678}
679
680static int rv1108_clk_bind(struct udevice *dev)
681{
682 int ret;
Heiko Stuebnerc82c06d2019-11-09 00:06:29 +0100683 struct udevice *sys_child;
Kever Yang4fbb6c22017-11-03 15:16:13 +0800684 struct sysreset_reg *priv;
Andy Yan6d95cd52017-06-01 18:00:36 +0800685
686 /* The reset driver does not have a device node, so bind it here */
Kever Yang4fbb6c22017-11-03 15:16:13 +0800687 ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset",
688 &sys_child);
689 if (ret) {
690 debug("Warning: No sysreset driver: ret=%d\n", ret);
691 } else {
692 priv = malloc(sizeof(struct sysreset_reg));
693 priv->glb_srst_fst_value = offsetof(struct rv1108_cru,
694 glb_srst_fst_val);
695 priv->glb_srst_snd_value = offsetof(struct rv1108_cru,
696 glb_srst_snd_val);
697 sys_child->priv = priv;
698 }
Andy Yan6d95cd52017-06-01 18:00:36 +0800699
Heiko Stuebner416f8d32019-11-09 00:06:30 +0100700#if CONFIG_IS_ENABLED(RESET_ROCKCHIP)
Heiko Stuebnerc82c06d2019-11-09 00:06:29 +0100701 ret = offsetof(struct rv1108_cru, softrst_con[0]);
Elaine Zhang432976f2017-12-19 18:22:38 +0800702 ret = rockchip_reset_bind(dev, ret, 13);
703 if (ret)
704 debug("Warning: software reset driver bind faile\n");
705#endif
706
Andy Yan6d95cd52017-06-01 18:00:36 +0800707 return 0;
708}
709
710static const struct udevice_id rv1108_clk_ids[] = {
711 { .compatible = "rockchip,rv1108-cru" },
712 { }
713};
714
715U_BOOT_DRIVER(clk_rv1108) = {
716 .name = "clk_rv1108",
717 .id = UCLASS_CLK,
718 .of_match = rv1108_clk_ids,
719 .priv_auto_alloc_size = sizeof(struct rv1108_clk_priv),
Andy Yan6d95cd52017-06-01 18:00:36 +0800720 .ops = &rv1108_clk_ops,
721 .bind = rv1108_clk_bind,
Otavio Salvador3afae5e2018-11-30 11:34:12 -0200722 .ofdata_to_platdata = rv1108_clk_ofdata_to_platdata,
Andy Yan6d95cd52017-06-01 18:00:36 +0800723 .probe = rv1108_clk_probe,
724};