blob: 4c066557c1cafbebfd1520278d49cee5fe3752c5 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Peng Fan684ccd92017-02-22 16:21:42 +08002/*
3 * Copyright (C) 2016 Freescale Semiconductor, Inc.
Peng Fan684ccd92017-02-22 16:21:42 +08004 */
5
6#include <common.h>
7#include <div64.h>
Simon Glass0f2af882020-05-10 11:40:05 -06008#include <log.h>
Peng Fan684ccd92017-02-22 16:21:42 +08009#include <asm/io.h>
10#include <errno.h>
11#include <asm/arch/imx-regs.h>
12#include <asm/arch/pcc.h>
13#include <asm/arch/sys_proto.h>
Simon Glassdbd79542020-05-10 11:40:11 -060014#include <linux/delay.h>
Peng Fan684ccd92017-02-22 16:21:42 +080015
Peng Fan684ccd92017-02-22 16:21:42 +080016scg_p scg1_regs = (scg_p)SCG1_RBASE;
17
18static u32 scg_src_get_rate(enum scg_clk clksrc)
19{
20 u32 reg;
21
22 switch (clksrc) {
23 case SCG_SOSC_CLK:
24 reg = readl(&scg1_regs->sosccsr);
25 if (!(reg & SCG_SOSC_CSR_SOSCVLD_MASK))
26 return 0;
27
28 return 24000000;
29 case SCG_FIRC_CLK:
30 reg = readl(&scg1_regs->firccsr);
31 if (!(reg & SCG_FIRC_CSR_FIRCVLD_MASK))
32 return 0;
33
34 return 48000000;
35 case SCG_SIRC_CLK:
36 reg = readl(&scg1_regs->sirccsr);
37 if (!(reg & SCG_SIRC_CSR_SIRCVLD_MASK))
38 return 0;
39
40 return 16000000;
41 case SCG_ROSC_CLK:
42 reg = readl(&scg1_regs->rtccsr);
43 if (!(reg & SCG_ROSC_CSR_ROSCVLD_MASK))
44 return 0;
45
46 return 32768;
47 default:
48 break;
49 }
50
51 return 0;
52}
53
54static u32 scg_sircdiv_get_rate(enum scg_clk clk)
55{
56 u32 reg, val, rate;
57 u32 shift, mask;
58
59 switch (clk) {
60 case SCG_SIRC_DIV1_CLK:
61 mask = SCG_SIRCDIV_DIV1_MASK;
62 shift = SCG_SIRCDIV_DIV1_SHIFT;
63 break;
64 case SCG_SIRC_DIV2_CLK:
65 mask = SCG_SIRCDIV_DIV2_MASK;
66 shift = SCG_SIRCDIV_DIV2_SHIFT;
67 break;
68 case SCG_SIRC_DIV3_CLK:
69 mask = SCG_SIRCDIV_DIV3_MASK;
70 shift = SCG_SIRCDIV_DIV3_SHIFT;
71 break;
72 default:
73 return 0;
74 }
75
76 reg = readl(&scg1_regs->sirccsr);
77 if (!(reg & SCG_SIRC_CSR_SIRCVLD_MASK))
78 return 0;
79
80 reg = readl(&scg1_regs->sircdiv);
81 val = (reg & mask) >> shift;
82
83 if (!val) /*clock disabled*/
84 return 0;
85
86 rate = scg_src_get_rate(SCG_SIRC_CLK);
87 rate = rate / (1 << (val - 1));
88
89 return rate;
90}
91
92static u32 scg_fircdiv_get_rate(enum scg_clk clk)
93{
94 u32 reg, val, rate;
95 u32 shift, mask;
96
97 switch (clk) {
98 case SCG_FIRC_DIV1_CLK:
99 mask = SCG_FIRCDIV_DIV1_MASK;
100 shift = SCG_FIRCDIV_DIV1_SHIFT;
101 break;
102 case SCG_FIRC_DIV2_CLK:
103 mask = SCG_FIRCDIV_DIV2_MASK;
104 shift = SCG_FIRCDIV_DIV2_SHIFT;
105 break;
106 case SCG_FIRC_DIV3_CLK:
107 mask = SCG_FIRCDIV_DIV3_MASK;
108 shift = SCG_FIRCDIV_DIV3_SHIFT;
109 break;
110 default:
111 return 0;
112 }
113
114 reg = readl(&scg1_regs->firccsr);
115 if (!(reg & SCG_FIRC_CSR_FIRCVLD_MASK))
116 return 0;
117
118 reg = readl(&scg1_regs->fircdiv);
119 val = (reg & mask) >> shift;
120
121 if (!val) /*clock disabled*/
122 return 0;
123
124 rate = scg_src_get_rate(SCG_FIRC_CLK);
125 rate = rate / (1 << (val - 1));
126
127 return rate;
128}
129
130static u32 scg_soscdiv_get_rate(enum scg_clk clk)
131{
132 u32 reg, val, rate;
133 u32 shift, mask;
134
135 switch (clk) {
136 case SCG_SOSC_DIV1_CLK:
137 mask = SCG_SOSCDIV_DIV1_MASK;
138 shift = SCG_SOSCDIV_DIV1_SHIFT;
139 break;
140 case SCG_SOSC_DIV2_CLK:
141 mask = SCG_SOSCDIV_DIV2_MASK;
142 shift = SCG_SOSCDIV_DIV2_SHIFT;
143 break;
144 case SCG_SOSC_DIV3_CLK:
145 mask = SCG_SOSCDIV_DIV3_MASK;
146 shift = SCG_SOSCDIV_DIV3_SHIFT;
147 break;
148 default:
149 return 0;
150 }
151
152 reg = readl(&scg1_regs->sosccsr);
153 if (!(reg & SCG_SOSC_CSR_SOSCVLD_MASK))
154 return 0;
155
156 reg = readl(&scg1_regs->soscdiv);
157 val = (reg & mask) >> shift;
158
159 if (!val) /*clock disabled*/
160 return 0;
161
162 rate = scg_src_get_rate(SCG_SOSC_CLK);
163 rate = rate / (1 << (val - 1));
164
165 return rate;
166}
167
168static u32 scg_apll_pfd_get_rate(enum scg_clk clk)
169{
170 u32 reg, val, rate;
171 u32 shift, mask, gate, valid;
172
173 switch (clk) {
174 case SCG_APLL_PFD0_CLK:
175 gate = SCG_PLL_PFD0_GATE_MASK;
176 valid = SCG_PLL_PFD0_VALID_MASK;
177 mask = SCG_PLL_PFD0_FRAC_MASK;
178 shift = SCG_PLL_PFD0_FRAC_SHIFT;
179 break;
180 case SCG_APLL_PFD1_CLK:
181 gate = SCG_PLL_PFD1_GATE_MASK;
182 valid = SCG_PLL_PFD1_VALID_MASK;
183 mask = SCG_PLL_PFD1_FRAC_MASK;
184 shift = SCG_PLL_PFD1_FRAC_SHIFT;
185 break;
186 case SCG_APLL_PFD2_CLK:
187 gate = SCG_PLL_PFD2_GATE_MASK;
188 valid = SCG_PLL_PFD2_VALID_MASK;
189 mask = SCG_PLL_PFD2_FRAC_MASK;
190 shift = SCG_PLL_PFD2_FRAC_SHIFT;
191 break;
192 case SCG_APLL_PFD3_CLK:
193 gate = SCG_PLL_PFD3_GATE_MASK;
194 valid = SCG_PLL_PFD3_VALID_MASK;
195 mask = SCG_PLL_PFD3_FRAC_MASK;
196 shift = SCG_PLL_PFD3_FRAC_SHIFT;
197 break;
198 default:
199 return 0;
200 }
201
202 reg = readl(&scg1_regs->apllpfd);
203 if (reg & gate || !(reg & valid))
204 return 0;
205
206 clk_debug("scg_apll_pfd_get_rate reg 0x%x\n", reg);
207
208 val = (reg & mask) >> shift;
209 rate = decode_pll(PLL_A7_APLL);
210
211 rate = rate / val * 18;
212
213 clk_debug("scg_apll_pfd_get_rate rate %u\n", rate);
214
215 return rate;
216}
217
218static u32 scg_spll_pfd_get_rate(enum scg_clk clk)
219{
220 u32 reg, val, rate;
221 u32 shift, mask, gate, valid;
222
223 switch (clk) {
224 case SCG_SPLL_PFD0_CLK:
225 gate = SCG_PLL_PFD0_GATE_MASK;
226 valid = SCG_PLL_PFD0_VALID_MASK;
227 mask = SCG_PLL_PFD0_FRAC_MASK;
228 shift = SCG_PLL_PFD0_FRAC_SHIFT;
229 break;
230 case SCG_SPLL_PFD1_CLK:
231 gate = SCG_PLL_PFD1_GATE_MASK;
232 valid = SCG_PLL_PFD1_VALID_MASK;
233 mask = SCG_PLL_PFD1_FRAC_MASK;
234 shift = SCG_PLL_PFD1_FRAC_SHIFT;
235 break;
236 case SCG_SPLL_PFD2_CLK:
237 gate = SCG_PLL_PFD2_GATE_MASK;
238 valid = SCG_PLL_PFD2_VALID_MASK;
239 mask = SCG_PLL_PFD2_FRAC_MASK;
240 shift = SCG_PLL_PFD2_FRAC_SHIFT;
241 break;
242 case SCG_SPLL_PFD3_CLK:
243 gate = SCG_PLL_PFD3_GATE_MASK;
244 valid = SCG_PLL_PFD3_VALID_MASK;
245 mask = SCG_PLL_PFD3_FRAC_MASK;
246 shift = SCG_PLL_PFD3_FRAC_SHIFT;
247 break;
248 default:
249 return 0;
250 }
251
252 reg = readl(&scg1_regs->spllpfd);
253 if (reg & gate || !(reg & valid))
254 return 0;
255
256 clk_debug("scg_spll_pfd_get_rate reg 0x%x\n", reg);
257
258 val = (reg & mask) >> shift;
259 rate = decode_pll(PLL_A7_SPLL);
260
261 rate = rate / val * 18;
262
263 clk_debug("scg_spll_pfd_get_rate rate %u\n", rate);
264
265 return rate;
266}
267
268static u32 scg_apll_get_rate(void)
269{
270 u32 reg, val, rate;
271
272 reg = readl(&scg1_regs->apllcfg);
273 val = (reg & SCG_PLL_CFG_PLLSEL_MASK) >> SCG_PLL_CFG_PLLSEL_SHIFT;
274
275 if (!val) {
276 /* APLL clock after two dividers */
277 rate = decode_pll(PLL_A7_APLL);
278
279 val = (reg & SCG_PLL_CFG_POSTDIV1_MASK) >>
280 SCG_PLL_CFG_POSTDIV1_SHIFT;
281 rate = rate / (val + 1);
282
283 val = (reg & SCG_PLL_CFG_POSTDIV2_MASK) >>
284 SCG_PLL_CFG_POSTDIV2_SHIFT;
285 rate = rate / (val + 1);
286 } else {
287 /* APLL PFD clock */
288 val = (reg & SCG_PLL_CFG_PFDSEL_MASK) >>
289 SCG_PLL_CFG_PFDSEL_SHIFT;
290 rate = scg_apll_pfd_get_rate(SCG_APLL_PFD0_CLK + val);
291 }
292
293 return rate;
294}
295
296static u32 scg_spll_get_rate(void)
297{
298 u32 reg, val, rate;
299
300 reg = readl(&scg1_regs->spllcfg);
301 val = (reg & SCG_PLL_CFG_PLLSEL_MASK) >> SCG_PLL_CFG_PLLSEL_SHIFT;
302
303 clk_debug("scg_spll_get_rate reg 0x%x\n", reg);
304
305 if (!val) {
306 /* APLL clock after two dividers */
307 rate = decode_pll(PLL_A7_SPLL);
308
309 val = (reg & SCG_PLL_CFG_POSTDIV1_MASK) >>
310 SCG_PLL_CFG_POSTDIV1_SHIFT;
311 rate = rate / (val + 1);
312
313 val = (reg & SCG_PLL_CFG_POSTDIV2_MASK) >>
314 SCG_PLL_CFG_POSTDIV2_SHIFT;
315 rate = rate / (val + 1);
316
317 clk_debug("scg_spll_get_rate SPLL %u\n", rate);
318
319 } else {
320 /* APLL PFD clock */
321 val = (reg & SCG_PLL_CFG_PFDSEL_MASK) >>
322 SCG_PLL_CFG_PFDSEL_SHIFT;
323 rate = scg_spll_pfd_get_rate(SCG_SPLL_PFD0_CLK + val);
324
325 clk_debug("scg_spll_get_rate PFD %u\n", rate);
326 }
327
328 return rate;
329}
330
331static u32 scg_ddr_get_rate(void)
332{
333 u32 reg, val, rate, div;
334
335 reg = readl(&scg1_regs->ddrccr);
336 val = (reg & SCG_DDRCCR_DDRCS_MASK) >> SCG_DDRCCR_DDRCS_SHIFT;
337 div = (reg & SCG_DDRCCR_DDRDIV_MASK) >> SCG_DDRCCR_DDRDIV_SHIFT;
338
339 if (!div)
340 return 0;
341
342 if (!val) {
343 reg = readl(&scg1_regs->apllcfg);
344 val = (reg & SCG_PLL_CFG_PFDSEL_MASK) >>
345 SCG_PLL_CFG_PFDSEL_SHIFT;
346 rate = scg_apll_pfd_get_rate(SCG_APLL_PFD0_CLK + val);
347 } else {
348 rate = decode_pll(PLL_USB);
349 }
350
351 rate = rate / (1 << (div - 1));
352 return rate;
353}
354
355static u32 scg_nic_get_rate(enum scg_clk clk)
356{
Ye Li94993cf2019-07-22 01:25:10 +0000357 u32 reg, val, rate, nic0_rate;
Peng Fan684ccd92017-02-22 16:21:42 +0800358 u32 shift, mask;
359
360 reg = readl(&scg1_regs->niccsr);
361 val = (reg & SCG_NICCSR_NICCS_MASK) >> SCG_NICCSR_NICCS_SHIFT;
362
363 clk_debug("scg_nic_get_rate niccsr 0x%x\n", reg);
364
365 if (!val)
366 rate = scg_src_get_rate(SCG_FIRC_CLK);
367 else
368 rate = scg_ddr_get_rate();
369
370 clk_debug("scg_nic_get_rate parent rate %u\n", rate);
371
372 val = (reg & SCG_NICCSR_NIC0DIV_MASK) >> SCG_NICCSR_NIC0DIV_SHIFT;
373
374 rate = rate / (val + 1);
Ye Li94993cf2019-07-22 01:25:10 +0000375 nic0_rate = rate;
Peng Fan684ccd92017-02-22 16:21:42 +0800376
377 clk_debug("scg_nic_get_rate NIC0 rate %u\n", rate);
378
379 switch (clk) {
380 case SCG_NIC0_CLK:
381 return rate;
382 case SCG_GPU_CLK:
383 mask = SCG_NICCSR_GPUDIV_MASK;
384 shift = SCG_NICCSR_GPUDIV_SHIFT;
385 break;
386 case SCG_NIC1_EXT_CLK:
387 case SCG_NIC1_BUS_CLK:
388 case SCG_NIC1_CLK:
389 mask = SCG_NICCSR_NIC1DIV_MASK;
390 shift = SCG_NICCSR_NIC1DIV_SHIFT;
391 break;
392 default:
393 return 0;
394 }
395
396 val = (reg & mask) >> shift;
397 rate = rate / (val + 1);
398
399 clk_debug("scg_nic_get_rate NIC1 rate %u\n", rate);
400
401 switch (clk) {
402 case SCG_GPU_CLK:
403 case SCG_NIC1_CLK:
404 return rate;
405 case SCG_NIC1_EXT_CLK:
406 mask = SCG_NICCSR_NIC1EXTDIV_MASK;
407 shift = SCG_NICCSR_NIC1EXTDIV_SHIFT;
408 break;
409 case SCG_NIC1_BUS_CLK:
410 mask = SCG_NICCSR_NIC1BUSDIV_MASK;
411 shift = SCG_NICCSR_NIC1BUSDIV_SHIFT;
412 break;
413 default:
414 return 0;
415 }
416
Ye Li94993cf2019-07-22 01:25:10 +0000417 /*
418 * On RevB, the nic_bus and nic_ext dividers are parallel
419 * not chained with nic div
420 */
421 if (soc_rev() >= CHIP_REV_2_0)
422 rate = nic0_rate;
423
Peng Fan684ccd92017-02-22 16:21:42 +0800424 val = (reg & mask) >> shift;
425 rate = rate / (val + 1);
426
427 clk_debug("scg_nic_get_rate NIC1 bus rate %u\n", rate);
428 return rate;
429}
430
431
432static enum scg_clk scg_scs_array[4] = {
433 SCG_SOSC_CLK, SCG_SIRC_CLK, SCG_FIRC_CLK, SCG_ROSC_CLK,
434};
435
436static u32 scg_sys_get_rate(enum scg_clk clk)
437{
438 u32 reg, val, rate;
439
440 if (clk != SCG_CORE_CLK && clk != SCG_BUS_CLK)
441 return 0;
442
443 reg = readl(&scg1_regs->csr);
444 val = (reg & SCG_CCR_SCS_MASK) >> SCG_CCR_SCS_SHIFT;
445
446 clk_debug("scg_sys_get_rate reg 0x%x\n", reg);
447
448 switch (val) {
449 case SCG_SCS_SYS_OSC:
450 case SCG_SCS_SLOW_IRC:
451 case SCG_SCS_FAST_IRC:
452 case SCG_SCS_RTC_OSC:
Bai Ping6e2af912019-07-22 01:24:45 +0000453 rate = scg_src_get_rate(scg_scs_array[val - 1]);
Peng Fan684ccd92017-02-22 16:21:42 +0800454 break;
455 case 5:
456 rate = scg_apll_get_rate();
457 break;
458 case 6:
459 rate = scg_spll_get_rate();
460 break;
461 default:
462 return 0;
463 }
464
465 clk_debug("scg_sys_get_rate parent rate %u\n", rate);
466
467 val = (reg & SCG_CCR_DIVCORE_MASK) >> SCG_CCR_DIVCORE_SHIFT;
468
469 rate = rate / (val + 1);
470
471 if (clk == SCG_BUS_CLK) {
472 val = (reg & SCG_CCR_DIVBUS_MASK) >> SCG_CCR_DIVBUS_SHIFT;
473 rate = rate / (val + 1);
474 }
475
476 return rate;
477}
478
479u32 decode_pll(enum pll_clocks pll)
480{
481 u32 reg, pre_div, infreq, mult;
482 u32 num, denom;
483
484 /*
485 * Alought there are four choices for the bypass src,
486 * we choose OSC_24M which is the default set in ROM.
487 */
488 switch (pll) {
489 case PLL_A7_SPLL:
490 reg = readl(&scg1_regs->spllcsr);
491
492 if (!(reg & SCG_SPLL_CSR_SPLLVLD_MASK))
493 return 0;
494
495 reg = readl(&scg1_regs->spllcfg);
496
497 pre_div = (reg & SCG_PLL_CFG_PREDIV_MASK) >>
498 SCG_PLL_CFG_PREDIV_SHIFT;
499 pre_div += 1;
500
501 mult = (reg & SCG1_SPLL_CFG_MULT_MASK) >>
502 SCG_PLL_CFG_MULT_SHIFT;
503
504 infreq = (reg & SCG_PLL_CFG_CLKSRC_MASK) >>
505 SCG_PLL_CFG_CLKSRC_SHIFT;
506 if (!infreq)
507 infreq = scg_src_get_rate(SCG_SOSC_CLK);
508 else
509 infreq = scg_src_get_rate(SCG_FIRC_CLK);
510
511 num = readl(&scg1_regs->spllnum);
512 denom = readl(&scg1_regs->splldenom);
513
Ye Lidb305e52017-04-05 10:36:58 +0800514 infreq = infreq / pre_div;
515
Ye Li2e553a92019-07-22 01:25:00 +0000516 if (denom)
517 return infreq * mult + infreq * num / denom;
518 else
519 return infreq * mult;
Peng Fan684ccd92017-02-22 16:21:42 +0800520
521 case PLL_A7_APLL:
522 reg = readl(&scg1_regs->apllcsr);
523
524 if (!(reg & SCG_APLL_CSR_APLLVLD_MASK))
525 return 0;
526
527 reg = readl(&scg1_regs->apllcfg);
528
529 pre_div = (reg & SCG_PLL_CFG_PREDIV_MASK) >>
530 SCG_PLL_CFG_PREDIV_SHIFT;
531 pre_div += 1;
532
533 mult = (reg & SCG_APLL_CFG_MULT_MASK) >>
534 SCG_PLL_CFG_MULT_SHIFT;
535
536 infreq = (reg & SCG_PLL_CFG_CLKSRC_MASK) >>
537 SCG_PLL_CFG_CLKSRC_SHIFT;
538 if (!infreq)
539 infreq = scg_src_get_rate(SCG_SOSC_CLK);
540 else
541 infreq = scg_src_get_rate(SCG_FIRC_CLK);
542
543 num = readl(&scg1_regs->apllnum);
544 denom = readl(&scg1_regs->aplldenom);
545
Ye Lidb305e52017-04-05 10:36:58 +0800546 infreq = infreq / pre_div;
547
Ye Li2e553a92019-07-22 01:25:00 +0000548 if (denom)
549 return infreq * mult + infreq * num / denom;
550 else
551 return infreq * mult;
Peng Fan684ccd92017-02-22 16:21:42 +0800552
553 case PLL_USB:
554 reg = readl(&scg1_regs->upllcsr);
555
556 if (!(reg & SCG_UPLL_CSR_UPLLVLD_MASK))
557 return 0;
558
559 return 480000000u;
560
561 case PLL_MIPI:
562 return 480000000u;
563 default:
564 printf("Unsupported pll clocks %d\n", pll);
565 break;
566 }
567
568 return 0;
569}
570
571u32 scg_clk_get_rate(enum scg_clk clk)
572{
573 switch (clk) {
574 case SCG_SIRC_DIV1_CLK:
575 case SCG_SIRC_DIV2_CLK:
576 case SCG_SIRC_DIV3_CLK:
577 return scg_sircdiv_get_rate(clk);
578
579 case SCG_FIRC_DIV1_CLK:
580 case SCG_FIRC_DIV2_CLK:
581 case SCG_FIRC_DIV3_CLK:
582 return scg_fircdiv_get_rate(clk);
583
584 case SCG_SOSC_DIV1_CLK:
585 case SCG_SOSC_DIV2_CLK:
586 case SCG_SOSC_DIV3_CLK:
587 return scg_soscdiv_get_rate(clk);
588
589 case SCG_CORE_CLK:
590 case SCG_BUS_CLK:
591 return scg_sys_get_rate(clk);
592
593 case SCG_SPLL_PFD0_CLK:
594 case SCG_SPLL_PFD1_CLK:
595 case SCG_SPLL_PFD2_CLK:
596 case SCG_SPLL_PFD3_CLK:
597 return scg_spll_pfd_get_rate(clk);
598
599 case SCG_APLL_PFD0_CLK:
600 case SCG_APLL_PFD1_CLK:
601 case SCG_APLL_PFD2_CLK:
602 case SCG_APLL_PFD3_CLK:
603 return scg_apll_pfd_get_rate(clk);
604
605 case SCG_DDR_CLK:
606 return scg_ddr_get_rate();
607
608 case SCG_NIC0_CLK:
609 case SCG_GPU_CLK:
610 case SCG_NIC1_CLK:
611 case SCG_NIC1_BUS_CLK:
612 case SCG_NIC1_EXT_CLK:
613 return scg_nic_get_rate(clk);
614
615 case USB_PLL_OUT:
616 return decode_pll(PLL_USB);
617
618 case MIPI_PLL_OUT:
619 return decode_pll(PLL_MIPI);
620
621 case SCG_SOSC_CLK:
622 case SCG_FIRC_CLK:
623 case SCG_SIRC_CLK:
624 case SCG_ROSC_CLK:
625 return scg_src_get_rate(clk);
626 default:
627 return 0;
628 }
629}
630
631int scg_enable_pll_pfd(enum scg_clk clk, u32 frac)
632{
633 u32 reg;
634 u32 shift, mask, gate, valid;
635 u32 addr;
636
637 if (frac < 12 || frac > 35)
638 return -EINVAL;
639
640 switch (clk) {
641 case SCG_SPLL_PFD0_CLK:
642 case SCG_APLL_PFD0_CLK:
643 gate = SCG_PLL_PFD0_GATE_MASK;
644 valid = SCG_PLL_PFD0_VALID_MASK;
645 mask = SCG_PLL_PFD0_FRAC_MASK;
646 shift = SCG_PLL_PFD0_FRAC_SHIFT;
647
648 if (clk == SCG_SPLL_PFD0_CLK)
649 addr = (u32)(&scg1_regs->spllpfd);
650 else
651 addr = (u32)(&scg1_regs->apllpfd);
652 break;
653 case SCG_SPLL_PFD1_CLK:
654 case SCG_APLL_PFD1_CLK:
655 gate = SCG_PLL_PFD1_GATE_MASK;
656 valid = SCG_PLL_PFD1_VALID_MASK;
657 mask = SCG_PLL_PFD1_FRAC_MASK;
658 shift = SCG_PLL_PFD1_FRAC_SHIFT;
659
660 if (clk == SCG_SPLL_PFD1_CLK)
661 addr = (u32)(&scg1_regs->spllpfd);
662 else
663 addr = (u32)(&scg1_regs->apllpfd);
664 break;
665 case SCG_SPLL_PFD2_CLK:
666 case SCG_APLL_PFD2_CLK:
667 gate = SCG_PLL_PFD2_GATE_MASK;
668 valid = SCG_PLL_PFD2_VALID_MASK;
669 mask = SCG_PLL_PFD2_FRAC_MASK;
670 shift = SCG_PLL_PFD2_FRAC_SHIFT;
671
672 if (clk == SCG_SPLL_PFD2_CLK)
673 addr = (u32)(&scg1_regs->spllpfd);
674 else
675 addr = (u32)(&scg1_regs->apllpfd);
676 break;
677 case SCG_SPLL_PFD3_CLK:
678 case SCG_APLL_PFD3_CLK:
679 gate = SCG_PLL_PFD3_GATE_MASK;
680 valid = SCG_PLL_PFD3_VALID_MASK;
681 mask = SCG_PLL_PFD3_FRAC_MASK;
682 shift = SCG_PLL_PFD3_FRAC_SHIFT;
683
684 if (clk == SCG_SPLL_PFD3_CLK)
685 addr = (u32)(&scg1_regs->spllpfd);
686 else
687 addr = (u32)(&scg1_regs->apllpfd);
688 break;
689 default:
690 return -EINVAL;
691 }
692
693 /* Gate the PFD */
694 reg = readl(addr);
695 reg |= gate;
696 writel(reg, addr);
697
698 /* Write Frac divider */
699 reg &= ~mask;
700 reg |= (frac << shift) & mask;
701 writel(reg, addr);
702
703 /*
704 * Un-gate the PFD
705 * (Need un-gate before checking valid, not align with RM)
706 */
707 reg &= ~gate;
708 writel(reg, addr);
709
710 /* Wait for PFD clock being valid */
711 do {
712 reg = readl(addr);
713 } while (!(reg & valid));
714
715 return 0;
716}
717
718#define SIM_MISC_CTRL0_USB_PLL_EN_MASK (0x1 << 2)
719int scg_enable_usb_pll(bool usb_control)
720{
721 u32 sosc_rate;
722 s32 timeout = 1000000;
723 u32 reg;
724
725 struct usbphy_regs *usbphy =
726 (struct usbphy_regs *)USBPHY_RBASE;
727
728 sosc_rate = scg_src_get_rate(SCG_SOSC_CLK);
729 if (!sosc_rate)
730 return -EPERM;
731
732 reg = readl(SIM0_RBASE + 0x3C);
733 if (usb_control)
734 reg &= ~SIM_MISC_CTRL0_USB_PLL_EN_MASK;
735 else
736 reg |= SIM_MISC_CTRL0_USB_PLL_EN_MASK;
737 writel(reg, SIM0_RBASE + 0x3C);
738
739 if (!(readl(&usbphy->usb1_pll_480_ctrl) & PLL_USB_LOCK_MASK)) {
740 writel(0x1c00000, &usbphy->usb1_pll_480_ctrl_clr);
741
742 switch (sosc_rate) {
743 case 24000000:
744 writel(0xc00000, &usbphy->usb1_pll_480_ctrl_set);
745 break;
746
747 case 30000000:
748 writel(0x800000, &usbphy->usb1_pll_480_ctrl_set);
749 break;
750
751 case 19200000:
752 writel(0x1400000, &usbphy->usb1_pll_480_ctrl_set);
753 break;
754
755 default:
756 writel(0xc00000, &usbphy->usb1_pll_480_ctrl_set);
757 break;
758 }
759
760 /* Enable the regulator first */
761 writel(PLL_USB_REG_ENABLE_MASK,
762 &usbphy->usb1_pll_480_ctrl_set);
763
764 /* Wait at least 15us */
765 udelay(15);
766
767 /* Enable the power */
768 writel(PLL_USB_PWR_MASK, &usbphy->usb1_pll_480_ctrl_set);
769
770 /* Wait lock */
771 while (timeout--) {
772 if (readl(&usbphy->usb1_pll_480_ctrl) &
773 PLL_USB_LOCK_MASK)
774 break;
775 }
776
777 if (timeout <= 0) {
778 /* If timeout, we power down the pll */
779 writel(PLL_USB_PWR_MASK,
780 &usbphy->usb1_pll_480_ctrl_clr);
781 return -ETIME;
782 }
783 }
784
785 /* Clear the bypass */
786 writel(PLL_USB_BYPASS_MASK, &usbphy->usb1_pll_480_ctrl_clr);
787
788 /* Enable the PLL clock out to USB */
789 writel((PLL_USB_EN_USB_CLKS_MASK | PLL_USB_ENABLE_MASK),
790 &usbphy->usb1_pll_480_ctrl_set);
791
792 if (!usb_control) {
793 while (timeout--) {
794 if (readl(&scg1_regs->upllcsr) &
795 SCG_UPLL_CSR_UPLLVLD_MASK)
796 break;
797 }
798
799 if (timeout <= 0) {
800 reg = readl(SIM0_RBASE + 0x3C);
801 reg &= ~SIM_MISC_CTRL0_USB_PLL_EN_MASK;
802 writel(reg, SIM0_RBASE + 0x3C);
803 return -ETIME;
804 }
805 }
806
807 return 0;
808}
809
810
811/* A7 domain system clock source is SPLL */
812#define SCG1_RCCR_SCS_NUM ((SCG_SCS_SYS_PLL) << SCG_CCR_SCS_SHIFT)
813
814/* A7 Core clck = SPLL PFD0 / 1 = 500MHz / 1 = 500MHz */
815#define SCG1_RCCR_DIVCORE_NUM ((0x0) << SCG_CCR_DIVCORE_SHIFT)
816#define SCG1_RCCR_CFG_MASK (SCG_CCR_SCS_MASK | SCG_CCR_DIVBUS_MASK)
817
818/* A7 Plat clck = A7 Core Clock / 2 = 250MHz / 1 = 250MHz */
819#define SCG1_RCCR_DIVBUS_NUM ((0x1) << SCG_CCR_DIVBUS_SHIFT)
820#define SCG1_RCCR_CFG_NUM (SCG1_RCCR_SCS_NUM | SCG1_RCCR_DIVBUS_NUM)
821
822void scg_a7_rccr_init(void)
823{
824 u32 rccr_reg_val = 0;
825
826 rccr_reg_val = readl(&scg1_regs->rccr);
827
828 rccr_reg_val &= (~SCG1_RCCR_CFG_MASK);
829 rccr_reg_val |= (SCG1_RCCR_CFG_NUM);
830
831 writel(rccr_reg_val, &scg1_regs->rccr);
832}
833
834/* POSTDIV2 = 1 */
835#define SCG1_SPLL_CFG_POSTDIV2_NUM ((0x0) << SCG_PLL_CFG_POSTDIV2_SHIFT)
836/* POSTDIV1 = 1 */
837#define SCG1_SPLL_CFG_POSTDIV1_NUM ((0x0) << SCG_PLL_CFG_POSTDIV1_SHIFT)
838
839/* MULT = 22 */
840#define SCG1_SPLL_CFG_MULT_NUM ((22) << SCG_PLL_CFG_MULT_SHIFT)
841
842/* PFD0 output clock selected */
843#define SCG1_SPLL_CFG_PFDSEL_NUM ((0) << SCG_PLL_CFG_PFDSEL_SHIFT)
844/* PREDIV = 1 */
845#define SCG1_SPLL_CFG_PREDIV_NUM ((0x0) << SCG_PLL_CFG_PREDIV_SHIFT)
846/* SPLL output clocks (including PFD outputs) selected */
847#define SCG1_SPLL_CFG_BYPASS_NUM ((0x0) << SCG_PLL_CFG_BYPASS_SHIFT)
848/* SPLL PFD output clock selected */
849#define SCG1_SPLL_CFG_PLLSEL_NUM ((0x1) << SCG_PLL_CFG_PLLSEL_SHIFT)
850/* Clock source is System OSC */
851#define SCG1_SPLL_CFG_CLKSRC_NUM ((0x0) << SCG_PLL_CFG_CLKSRC_SHIFT)
852#define SCG1_SPLL_CFG_NUM_24M_OSC (SCG1_SPLL_CFG_POSTDIV2_NUM | \
853 SCG1_SPLL_CFG_POSTDIV1_NUM | \
854 (22 << SCG_PLL_CFG_MULT_SHIFT) | \
855 SCG1_SPLL_CFG_PFDSEL_NUM | \
856 SCG1_SPLL_CFG_PREDIV_NUM | \
857 SCG1_SPLL_CFG_BYPASS_NUM | \
858 SCG1_SPLL_CFG_PLLSEL_NUM | \
859 SCG1_SPLL_CFG_CLKSRC_NUM)
860/*413Mhz = A7 SPLL(528MHz) * 18/23 */
861#define SCG1_SPLL_PFD0_FRAC_NUM ((23) << SCG_PLL_PFD0_FRAC_SHIFT)
862
863void scg_a7_spll_init(void)
864{
865 u32 val = 0;
866
867 /* Disable A7 System PLL */
868 val = readl(&scg1_regs->spllcsr);
869 val &= ~SCG_SPLL_CSR_SPLLEN_MASK;
870 writel(val, &scg1_regs->spllcsr);
871
872 /*
873 * Per block guide,
874 * "When changing PFD values, it is recommneded PFDx clock
875 * gets gated first by writing a value of 1 to PFDx_CLKGATE register,
876 * then program the new PFD value, then poll the PFDx_VALID
877 * flag to set before writing a value of 0 to PFDx_CLKGATE
878 * to ungate the PFDx clock and allow PFDx clock to run"
879 */
880
881 /* Gate off A7 SPLL PFD0 ~ PDF4 */
882 val = readl(&scg1_regs->spllpfd);
883 val |= (SCG_PLL_PFD3_GATE_MASK |
884 SCG_PLL_PFD2_GATE_MASK |
885 SCG_PLL_PFD1_GATE_MASK |
886 SCG_PLL_PFD0_GATE_MASK);
887 writel(val, &scg1_regs->spllpfd);
888
889 /* ================ A7 SPLL Configuration Start ============== */
890
891 /* Configure A7 System PLL */
892 writel(SCG1_SPLL_CFG_NUM_24M_OSC, &scg1_regs->spllcfg);
893
894 /* Enable A7 System PLL */
895 val = readl(&scg1_regs->spllcsr);
896 val |= SCG_SPLL_CSR_SPLLEN_MASK;
897 writel(val, &scg1_regs->spllcsr);
898
899 /* Wait for A7 SPLL clock ready */
900 while (!(readl(&scg1_regs->spllcsr) & SCG_SPLL_CSR_SPLLVLD_MASK))
901 ;
902
903 /* Configure A7 SPLL PFD0 */
904 val = readl(&scg1_regs->spllpfd);
905 val &= ~SCG_PLL_PFD0_FRAC_MASK;
906 val |= SCG1_SPLL_PFD0_FRAC_NUM;
907 writel(val, &scg1_regs->spllpfd);
908
909 /* Un-gate A7 SPLL PFD0 */
910 val = readl(&scg1_regs->spllpfd);
911 val &= ~SCG_PLL_PFD0_GATE_MASK;
912 writel(val, &scg1_regs->spllpfd);
913
914 /* Wait for A7 SPLL PFD0 clock being valid */
915 while (!(readl(&scg1_regs->spllpfd) & SCG_PLL_PFD0_VALID_MASK))
916 ;
917
918 /* ================ A7 SPLL Configuration End ============== */
919}
920
921/* DDR clock source is APLL PFD0 (396MHz) */
922#define SCG1_DDRCCR_DDRCS_NUM ((0x0) << SCG_DDRCCR_DDRCS_SHIFT)
923/* DDR clock = APLL PFD0 / 1 = 396MHz / 1 = 396MHz */
924#define SCG1_DDRCCR_DDRDIV_NUM ((0x1) << SCG_DDRCCR_DDRDIV_SHIFT)
925/* DDR clock = APLL PFD0 / 2 = 396MHz / 2 = 198MHz */
926#define SCG1_DDRCCR_DDRDIV_LF_NUM ((0x2) << SCG_DDRCCR_DDRDIV_SHIFT)
927#define SCG1_DDRCCR_CFG_NUM (SCG1_DDRCCR_DDRCS_NUM | \
928 SCG1_DDRCCR_DDRDIV_NUM)
929#define SCG1_DDRCCR_CFG_LF_NUM (SCG1_DDRCCR_DDRCS_NUM | \
930 SCG1_DDRCCR_DDRDIV_LF_NUM)
931void scg_a7_ddrclk_init(void)
932{
933 writel(SCG1_DDRCCR_CFG_NUM, &scg1_regs->ddrccr);
934}
935
936/* SCG1(A7) APLLCFG configurations */
937/* divide by 1 <<28 */
938#define SCG1_APLL_CFG_POSTDIV2_NUM ((0x0) << SCG_PLL_CFG_POSTDIV2_SHIFT)
939/* divide by 1 <<24 */
940#define SCG1_APLL_CFG_POSTDIV1_NUM ((0x0) << SCG_PLL_CFG_POSTDIV1_SHIFT)
941/* MULT is 22 <<16 */
942#define SCG1_APLL_CFG_MULT_NUM ((22) << SCG_PLL_CFG_MULT_SHIFT)
943/* PFD0 output clock selected <<14 */
944#define SCG1_APLL_CFG_PFDSEL_NUM ((0) << SCG_PLL_CFG_PFDSEL_SHIFT)
945/* PREDIV = 1 <<8 */
946#define SCG1_APLL_CFG_PREDIV_NUM ((0x0) << SCG_PLL_CFG_PREDIV_SHIFT)
947/* APLL output clocks (including PFD outputs) selected <<2 */
948#define SCG1_APLL_CFG_BYPASS_NUM ((0x0) << SCG_PLL_CFG_BYPASS_SHIFT)
949/* APLL PFD output clock selected <<1 */
950#define SCG1_APLL_CFG_PLLSEL_NUM ((0x0) << SCG_PLL_CFG_PLLSEL_SHIFT)
951/* Clock source is System OSC <<0 */
952#define SCG1_APLL_CFG_CLKSRC_NUM ((0x0) << SCG_PLL_CFG_CLKSRC_SHIFT)
953
Peng Fan684ccd92017-02-22 16:21:42 +0800954/* SCG1(A7) FIRC DIV configurations */
955/* Disable FIRC DIV3 */
956#define SCG1_FIRCDIV_DIV3_NUM ((0x0) << SCG_FIRCDIV_DIV3_SHIFT)
957/* FIRC DIV2 = 48MHz / 1 = 48MHz */
958#define SCG1_FIRCDIV_DIV2_NUM ((0x1) << SCG_FIRCDIV_DIV2_SHIFT)
959/* Disable FIRC DIV1 */
960#define SCG1_FIRCDIV_DIV1_NUM ((0x0) << SCG_FIRCDIV_DIV1_SHIFT)
961
962void scg_a7_firc_init(void)
963{
964 /* Wait for FIRC clock ready */
965 while (!(readl(&scg1_regs->firccsr) & SCG_FIRC_CSR_FIRCVLD_MASK))
966 ;
967
968 /* Configure A7 FIRC DIV1 ~ DIV3 */
969 writel((SCG1_FIRCDIV_DIV3_NUM |
970 SCG1_FIRCDIV_DIV2_NUM |
971 SCG1_FIRCDIV_DIV1_NUM), &scg1_regs->fircdiv);
972}
973
974/* SCG1(A7) NICCCR configurations */
975/* NIC clock source is DDR clock (396/198MHz) */
976#define SCG1_NICCCR_NICCS_NUM ((0x1) << SCG_NICCCR_NICCS_SHIFT)
977
978/* NIC0 clock = DDR Clock / 2 = 396MHz / 2 = 198MHz */
979#define SCG1_NICCCR_NIC0_DIV_NUM ((0x1) << SCG_NICCCR_NIC0_DIV_SHIFT)
980/* NIC0 clock = DDR Clock / 1 = 198MHz / 1 = 198MHz */
981#define SCG1_NICCCR_NIC0_DIV_LF_NUM ((0x0) << SCG_NICCCR_NIC0_DIV_SHIFT)
982/* NIC1 clock = NIC0 Clock / 1 = 198MHz / 2 = 198MHz */
983#define SCG1_NICCCR_NIC1_DIV_NUM ((0x0) << SCG_NICCCR_NIC1_DIV_SHIFT)
984/* NIC1 bus clock = NIC1 Clock / 3 = 198MHz / 3 = 66MHz */
985#define SCG1_NICCCR_NIC1_DIVBUS_NUM ((0x2) << SCG_NICCCR_NIC1_DIVBUS_SHIFT)
986#define SCG1_NICCCR_CFG_NUM (SCG1_NICCCR_NICCS_NUM | \
987 SCG1_NICCCR_NIC0_DIV_NUM | \
988 SCG1_NICCCR_NIC1_DIV_NUM | \
989 SCG1_NICCCR_NIC1_DIVBUS_NUM)
990
991void scg_a7_nicclk_init(void)
992{
993 writel(SCG1_NICCCR_CFG_NUM, &scg1_regs->nicccr);
994}
995
996/* SCG1(A7) FIRC DIV configurations */
997/* Enable FIRC DIV3 */
998#define SCG1_SOSCDIV_DIV3_NUM ((0x1) << SCG_SOSCDIV_DIV3_SHIFT)
999/* FIRC DIV2 = 48MHz / 1 = 48MHz */
1000#define SCG1_SOSCDIV_DIV2_NUM ((0x1) << SCG_SOSCDIV_DIV2_SHIFT)
1001/* Enable FIRC DIV1 */
1002#define SCG1_SOSCDIV_DIV1_NUM ((0x1) << SCG_SOSCDIV_DIV1_SHIFT)
1003
1004void scg_a7_soscdiv_init(void)
1005{
1006 /* Wait for FIRC clock ready */
1007 while (!(readl(&scg1_regs->sosccsr) & SCG_SOSC_CSR_SOSCVLD_MASK))
1008 ;
1009
1010 /* Configure A7 FIRC DIV1 ~ DIV3 */
1011 writel((SCG1_SOSCDIV_DIV3_NUM | SCG1_SOSCDIV_DIV2_NUM |
1012 SCG1_SOSCDIV_DIV1_NUM), &scg1_regs->soscdiv);
1013}
1014
1015void scg_a7_sys_clk_sel(enum scg_sys_src clk)
1016{
1017 u32 rccr_reg_val = 0;
1018
1019 clk_debug("%s: system clock selected as %s\n", "[SCG]",
1020 clk == SCG_SCS_SYS_OSC ? "SYS_OSC" :
1021 clk == SCG_SCS_SLOW_IRC ? "SLOW_IRC" :
1022 clk == SCG_SCS_FAST_IRC ? "FAST_IRC" :
1023 clk == SCG_SCS_RTC_OSC ? "RTC_OSC" :
1024 clk == SCG_SCS_AUX_PLL ? "AUX_PLL" :
1025 clk == SCG_SCS_SYS_PLL ? "SYS_PLL" :
1026 clk == SCG_SCS_USBPHY_PLL ? "USBPHY_PLL" :
1027 "Invalid source"
1028 );
1029
1030 rccr_reg_val = readl(&scg1_regs->rccr);
1031 rccr_reg_val &= ~SCG_CCR_SCS_MASK;
1032 rccr_reg_val |= (clk << SCG_CCR_SCS_SHIFT);
1033 writel(rccr_reg_val, &scg1_regs->rccr);
1034}
1035
1036void scg_a7_info(void)
1037{
1038 debug("SCG Version: 0x%x\n", readl(&scg1_regs->verid));
1039 debug("SCG Parameter: 0x%x\n", readl(&scg1_regs->param));
1040 debug("SCG RCCR Value: 0x%x\n", readl(&scg1_regs->rccr));
1041 debug("SCG Clock Status: 0x%x\n", readl(&scg1_regs->csr));
1042}
Ye Li73df56a2019-07-22 01:25:08 +00001043
1044void scg_a7_init_core_clk(void)
1045{
1046 u32 val = 0;
1047
1048 /*
1049 * The normal target frequency for ULP B0 is 500Mhz,
1050 * but ROM set it to 413Mhz, need to change SPLL PFD0 FRAC
1051 */
1052 if (soc_rev() >= CHIP_REV_2_0) {
1053 /* Switch RCCR SCG to SOSC, firstly check the SOSC is valid */
1054 if ((readl(&scg1_regs->sosccsr) & SCG_SOSC_CSR_SOSCVLD_MASK)) {
1055 val = readl(&scg1_regs->rccr);
1056 val &= (~SCG_CCR_SCS_MASK);
1057 val |= ((SCG_SCS_SYS_OSC) << SCG_CCR_SCS_SHIFT);
1058 writel(val, &scg1_regs->rccr);
1059
1060 /* Switch the PLLS to SPLL clk */
1061 val = readl(&scg1_regs->spllcfg);
1062 val &= ~SCG_PLL_CFG_PLLSEL_MASK;
1063 writel(val, &scg1_regs->spllcfg);
1064
1065 /*
1066 * Re-configure PFD0 to 19,
1067 * A7 SPLL(528MHz) * 18 / 19 = 500MHz
1068 */
1069 scg_enable_pll_pfd(SCG_SPLL_PFD0_CLK, 19);
1070
1071 /* Switch the PLLS to SPLL PFD0 */
1072 val = readl(&scg1_regs->spllcfg);
1073 val |= SCG_PLL_CFG_PLLSEL_MASK;
1074 writel(val, &scg1_regs->spllcfg);
1075
1076 /* Set RCCR SCG to SPLL clk out */
1077 val = readl(&scg1_regs->rccr);
1078 val &= (~SCG_CCR_SCS_MASK);
1079 val |= ((SCG_SCS_SYS_PLL) << SCG_CCR_SCS_SHIFT);
1080 writel(val, &scg1_regs->rccr);
1081 }
1082 }
1083}