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