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