blob: b4f2ea875af210ef8e8b551ff9142a1d414ed853 [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{
355 u32 reg, val, rate;
356 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);
373
374 clk_debug("scg_nic_get_rate NIC0 rate %u\n", rate);
375
376 switch (clk) {
377 case SCG_NIC0_CLK:
378 return rate;
379 case SCG_GPU_CLK:
380 mask = SCG_NICCSR_GPUDIV_MASK;
381 shift = SCG_NICCSR_GPUDIV_SHIFT;
382 break;
383 case SCG_NIC1_EXT_CLK:
384 case SCG_NIC1_BUS_CLK:
385 case SCG_NIC1_CLK:
386 mask = SCG_NICCSR_NIC1DIV_MASK;
387 shift = SCG_NICCSR_NIC1DIV_SHIFT;
388 break;
389 default:
390 return 0;
391 }
392
393 val = (reg & mask) >> shift;
394 rate = rate / (val + 1);
395
396 clk_debug("scg_nic_get_rate NIC1 rate %u\n", rate);
397
398 switch (clk) {
399 case SCG_GPU_CLK:
400 case SCG_NIC1_CLK:
401 return rate;
402 case SCG_NIC1_EXT_CLK:
403 mask = SCG_NICCSR_NIC1EXTDIV_MASK;
404 shift = SCG_NICCSR_NIC1EXTDIV_SHIFT;
405 break;
406 case SCG_NIC1_BUS_CLK:
407 mask = SCG_NICCSR_NIC1BUSDIV_MASK;
408 shift = SCG_NICCSR_NIC1BUSDIV_SHIFT;
409 break;
410 default:
411 return 0;
412 }
413
414 val = (reg & mask) >> shift;
415 rate = rate / (val + 1);
416
417 clk_debug("scg_nic_get_rate NIC1 bus rate %u\n", rate);
418 return rate;
419}
420
421
422static enum scg_clk scg_scs_array[4] = {
423 SCG_SOSC_CLK, SCG_SIRC_CLK, SCG_FIRC_CLK, SCG_ROSC_CLK,
424};
425
426static u32 scg_sys_get_rate(enum scg_clk clk)
427{
428 u32 reg, val, rate;
429
430 if (clk != SCG_CORE_CLK && clk != SCG_BUS_CLK)
431 return 0;
432
433 reg = readl(&scg1_regs->csr);
434 val = (reg & SCG_CCR_SCS_MASK) >> SCG_CCR_SCS_SHIFT;
435
436 clk_debug("scg_sys_get_rate reg 0x%x\n", reg);
437
438 switch (val) {
439 case SCG_SCS_SYS_OSC:
440 case SCG_SCS_SLOW_IRC:
441 case SCG_SCS_FAST_IRC:
442 case SCG_SCS_RTC_OSC:
443 rate = scg_src_get_rate(scg_scs_array[val]);
444 break;
445 case 5:
446 rate = scg_apll_get_rate();
447 break;
448 case 6:
449 rate = scg_spll_get_rate();
450 break;
451 default:
452 return 0;
453 }
454
455 clk_debug("scg_sys_get_rate parent rate %u\n", rate);
456
457 val = (reg & SCG_CCR_DIVCORE_MASK) >> SCG_CCR_DIVCORE_SHIFT;
458
459 rate = rate / (val + 1);
460
461 if (clk == SCG_BUS_CLK) {
462 val = (reg & SCG_CCR_DIVBUS_MASK) >> SCG_CCR_DIVBUS_SHIFT;
463 rate = rate / (val + 1);
464 }
465
466 return rate;
467}
468
469u32 decode_pll(enum pll_clocks pll)
470{
471 u32 reg, pre_div, infreq, mult;
472 u32 num, denom;
473
474 /*
475 * Alought there are four choices for the bypass src,
476 * we choose OSC_24M which is the default set in ROM.
477 */
478 switch (pll) {
479 case PLL_A7_SPLL:
480 reg = readl(&scg1_regs->spllcsr);
481
482 if (!(reg & SCG_SPLL_CSR_SPLLVLD_MASK))
483 return 0;
484
485 reg = readl(&scg1_regs->spllcfg);
486
487 pre_div = (reg & SCG_PLL_CFG_PREDIV_MASK) >>
488 SCG_PLL_CFG_PREDIV_SHIFT;
489 pre_div += 1;
490
491 mult = (reg & SCG1_SPLL_CFG_MULT_MASK) >>
492 SCG_PLL_CFG_MULT_SHIFT;
493
494 infreq = (reg & SCG_PLL_CFG_CLKSRC_MASK) >>
495 SCG_PLL_CFG_CLKSRC_SHIFT;
496 if (!infreq)
497 infreq = scg_src_get_rate(SCG_SOSC_CLK);
498 else
499 infreq = scg_src_get_rate(SCG_FIRC_CLK);
500
501 num = readl(&scg1_regs->spllnum);
502 denom = readl(&scg1_regs->splldenom);
503
Ye Lidb305e52017-04-05 10:36:58 +0800504 infreq = infreq / pre_div;
505
506 return infreq * mult + infreq * num / denom;
Peng Fan684ccd92017-02-22 16:21:42 +0800507
508 case PLL_A7_APLL:
509 reg = readl(&scg1_regs->apllcsr);
510
511 if (!(reg & SCG_APLL_CSR_APLLVLD_MASK))
512 return 0;
513
514 reg = readl(&scg1_regs->apllcfg);
515
516 pre_div = (reg & SCG_PLL_CFG_PREDIV_MASK) >>
517 SCG_PLL_CFG_PREDIV_SHIFT;
518 pre_div += 1;
519
520 mult = (reg & SCG_APLL_CFG_MULT_MASK) >>
521 SCG_PLL_CFG_MULT_SHIFT;
522
523 infreq = (reg & SCG_PLL_CFG_CLKSRC_MASK) >>
524 SCG_PLL_CFG_CLKSRC_SHIFT;
525 if (!infreq)
526 infreq = scg_src_get_rate(SCG_SOSC_CLK);
527 else
528 infreq = scg_src_get_rate(SCG_FIRC_CLK);
529
530 num = readl(&scg1_regs->apllnum);
531 denom = readl(&scg1_regs->aplldenom);
532
Ye Lidb305e52017-04-05 10:36:58 +0800533 infreq = infreq / pre_div;
534
535 return infreq * mult + infreq * num / denom;
Peng Fan684ccd92017-02-22 16:21:42 +0800536
537 case PLL_USB:
538 reg = readl(&scg1_regs->upllcsr);
539
540 if (!(reg & SCG_UPLL_CSR_UPLLVLD_MASK))
541 return 0;
542
543 return 480000000u;
544
545 case PLL_MIPI:
546 return 480000000u;
547 default:
548 printf("Unsupported pll clocks %d\n", pll);
549 break;
550 }
551
552 return 0;
553}
554
555u32 scg_clk_get_rate(enum scg_clk clk)
556{
557 switch (clk) {
558 case SCG_SIRC_DIV1_CLK:
559 case SCG_SIRC_DIV2_CLK:
560 case SCG_SIRC_DIV3_CLK:
561 return scg_sircdiv_get_rate(clk);
562
563 case SCG_FIRC_DIV1_CLK:
564 case SCG_FIRC_DIV2_CLK:
565 case SCG_FIRC_DIV3_CLK:
566 return scg_fircdiv_get_rate(clk);
567
568 case SCG_SOSC_DIV1_CLK:
569 case SCG_SOSC_DIV2_CLK:
570 case SCG_SOSC_DIV3_CLK:
571 return scg_soscdiv_get_rate(clk);
572
573 case SCG_CORE_CLK:
574 case SCG_BUS_CLK:
575 return scg_sys_get_rate(clk);
576
577 case SCG_SPLL_PFD0_CLK:
578 case SCG_SPLL_PFD1_CLK:
579 case SCG_SPLL_PFD2_CLK:
580 case SCG_SPLL_PFD3_CLK:
581 return scg_spll_pfd_get_rate(clk);
582
583 case SCG_APLL_PFD0_CLK:
584 case SCG_APLL_PFD1_CLK:
585 case SCG_APLL_PFD2_CLK:
586 case SCG_APLL_PFD3_CLK:
587 return scg_apll_pfd_get_rate(clk);
588
589 case SCG_DDR_CLK:
590 return scg_ddr_get_rate();
591
592 case SCG_NIC0_CLK:
593 case SCG_GPU_CLK:
594 case SCG_NIC1_CLK:
595 case SCG_NIC1_BUS_CLK:
596 case SCG_NIC1_EXT_CLK:
597 return scg_nic_get_rate(clk);
598
599 case USB_PLL_OUT:
600 return decode_pll(PLL_USB);
601
602 case MIPI_PLL_OUT:
603 return decode_pll(PLL_MIPI);
604
605 case SCG_SOSC_CLK:
606 case SCG_FIRC_CLK:
607 case SCG_SIRC_CLK:
608 case SCG_ROSC_CLK:
609 return scg_src_get_rate(clk);
610 default:
611 return 0;
612 }
613}
614
615int scg_enable_pll_pfd(enum scg_clk clk, u32 frac)
616{
617 u32 reg;
618 u32 shift, mask, gate, valid;
619 u32 addr;
620
621 if (frac < 12 || frac > 35)
622 return -EINVAL;
623
624 switch (clk) {
625 case SCG_SPLL_PFD0_CLK:
626 case SCG_APLL_PFD0_CLK:
627 gate = SCG_PLL_PFD0_GATE_MASK;
628 valid = SCG_PLL_PFD0_VALID_MASK;
629 mask = SCG_PLL_PFD0_FRAC_MASK;
630 shift = SCG_PLL_PFD0_FRAC_SHIFT;
631
632 if (clk == SCG_SPLL_PFD0_CLK)
633 addr = (u32)(&scg1_regs->spllpfd);
634 else
635 addr = (u32)(&scg1_regs->apllpfd);
636 break;
637 case SCG_SPLL_PFD1_CLK:
638 case SCG_APLL_PFD1_CLK:
639 gate = SCG_PLL_PFD1_GATE_MASK;
640 valid = SCG_PLL_PFD1_VALID_MASK;
641 mask = SCG_PLL_PFD1_FRAC_MASK;
642 shift = SCG_PLL_PFD1_FRAC_SHIFT;
643
644 if (clk == SCG_SPLL_PFD1_CLK)
645 addr = (u32)(&scg1_regs->spllpfd);
646 else
647 addr = (u32)(&scg1_regs->apllpfd);
648 break;
649 case SCG_SPLL_PFD2_CLK:
650 case SCG_APLL_PFD2_CLK:
651 gate = SCG_PLL_PFD2_GATE_MASK;
652 valid = SCG_PLL_PFD2_VALID_MASK;
653 mask = SCG_PLL_PFD2_FRAC_MASK;
654 shift = SCG_PLL_PFD2_FRAC_SHIFT;
655
656 if (clk == SCG_SPLL_PFD2_CLK)
657 addr = (u32)(&scg1_regs->spllpfd);
658 else
659 addr = (u32)(&scg1_regs->apllpfd);
660 break;
661 case SCG_SPLL_PFD3_CLK:
662 case SCG_APLL_PFD3_CLK:
663 gate = SCG_PLL_PFD3_GATE_MASK;
664 valid = SCG_PLL_PFD3_VALID_MASK;
665 mask = SCG_PLL_PFD3_FRAC_MASK;
666 shift = SCG_PLL_PFD3_FRAC_SHIFT;
667
668 if (clk == SCG_SPLL_PFD3_CLK)
669 addr = (u32)(&scg1_regs->spllpfd);
670 else
671 addr = (u32)(&scg1_regs->apllpfd);
672 break;
673 default:
674 return -EINVAL;
675 }
676
677 /* Gate the PFD */
678 reg = readl(addr);
679 reg |= gate;
680 writel(reg, addr);
681
682 /* Write Frac divider */
683 reg &= ~mask;
684 reg |= (frac << shift) & mask;
685 writel(reg, addr);
686
687 /*
688 * Un-gate the PFD
689 * (Need un-gate before checking valid, not align with RM)
690 */
691 reg &= ~gate;
692 writel(reg, addr);
693
694 /* Wait for PFD clock being valid */
695 do {
696 reg = readl(addr);
697 } while (!(reg & valid));
698
699 return 0;
700}
701
702#define SIM_MISC_CTRL0_USB_PLL_EN_MASK (0x1 << 2)
703int scg_enable_usb_pll(bool usb_control)
704{
705 u32 sosc_rate;
706 s32 timeout = 1000000;
707 u32 reg;
708
709 struct usbphy_regs *usbphy =
710 (struct usbphy_regs *)USBPHY_RBASE;
711
712 sosc_rate = scg_src_get_rate(SCG_SOSC_CLK);
713 if (!sosc_rate)
714 return -EPERM;
715
716 reg = readl(SIM0_RBASE + 0x3C);
717 if (usb_control)
718 reg &= ~SIM_MISC_CTRL0_USB_PLL_EN_MASK;
719 else
720 reg |= SIM_MISC_CTRL0_USB_PLL_EN_MASK;
721 writel(reg, SIM0_RBASE + 0x3C);
722
723 if (!(readl(&usbphy->usb1_pll_480_ctrl) & PLL_USB_LOCK_MASK)) {
724 writel(0x1c00000, &usbphy->usb1_pll_480_ctrl_clr);
725
726 switch (sosc_rate) {
727 case 24000000:
728 writel(0xc00000, &usbphy->usb1_pll_480_ctrl_set);
729 break;
730
731 case 30000000:
732 writel(0x800000, &usbphy->usb1_pll_480_ctrl_set);
733 break;
734
735 case 19200000:
736 writel(0x1400000, &usbphy->usb1_pll_480_ctrl_set);
737 break;
738
739 default:
740 writel(0xc00000, &usbphy->usb1_pll_480_ctrl_set);
741 break;
742 }
743
744 /* Enable the regulator first */
745 writel(PLL_USB_REG_ENABLE_MASK,
746 &usbphy->usb1_pll_480_ctrl_set);
747
748 /* Wait at least 15us */
749 udelay(15);
750
751 /* Enable the power */
752 writel(PLL_USB_PWR_MASK, &usbphy->usb1_pll_480_ctrl_set);
753
754 /* Wait lock */
755 while (timeout--) {
756 if (readl(&usbphy->usb1_pll_480_ctrl) &
757 PLL_USB_LOCK_MASK)
758 break;
759 }
760
761 if (timeout <= 0) {
762 /* If timeout, we power down the pll */
763 writel(PLL_USB_PWR_MASK,
764 &usbphy->usb1_pll_480_ctrl_clr);
765 return -ETIME;
766 }
767 }
768
769 /* Clear the bypass */
770 writel(PLL_USB_BYPASS_MASK, &usbphy->usb1_pll_480_ctrl_clr);
771
772 /* Enable the PLL clock out to USB */
773 writel((PLL_USB_EN_USB_CLKS_MASK | PLL_USB_ENABLE_MASK),
774 &usbphy->usb1_pll_480_ctrl_set);
775
776 if (!usb_control) {
777 while (timeout--) {
778 if (readl(&scg1_regs->upllcsr) &
779 SCG_UPLL_CSR_UPLLVLD_MASK)
780 break;
781 }
782
783 if (timeout <= 0) {
784 reg = readl(SIM0_RBASE + 0x3C);
785 reg &= ~SIM_MISC_CTRL0_USB_PLL_EN_MASK;
786 writel(reg, SIM0_RBASE + 0x3C);
787 return -ETIME;
788 }
789 }
790
791 return 0;
792}
793
794
795/* A7 domain system clock source is SPLL */
796#define SCG1_RCCR_SCS_NUM ((SCG_SCS_SYS_PLL) << SCG_CCR_SCS_SHIFT)
797
798/* A7 Core clck = SPLL PFD0 / 1 = 500MHz / 1 = 500MHz */
799#define SCG1_RCCR_DIVCORE_NUM ((0x0) << SCG_CCR_DIVCORE_SHIFT)
800#define SCG1_RCCR_CFG_MASK (SCG_CCR_SCS_MASK | SCG_CCR_DIVBUS_MASK)
801
802/* A7 Plat clck = A7 Core Clock / 2 = 250MHz / 1 = 250MHz */
803#define SCG1_RCCR_DIVBUS_NUM ((0x1) << SCG_CCR_DIVBUS_SHIFT)
804#define SCG1_RCCR_CFG_NUM (SCG1_RCCR_SCS_NUM | SCG1_RCCR_DIVBUS_NUM)
805
806void scg_a7_rccr_init(void)
807{
808 u32 rccr_reg_val = 0;
809
810 rccr_reg_val = readl(&scg1_regs->rccr);
811
812 rccr_reg_val &= (~SCG1_RCCR_CFG_MASK);
813 rccr_reg_val |= (SCG1_RCCR_CFG_NUM);
814
815 writel(rccr_reg_val, &scg1_regs->rccr);
816}
817
818/* POSTDIV2 = 1 */
819#define SCG1_SPLL_CFG_POSTDIV2_NUM ((0x0) << SCG_PLL_CFG_POSTDIV2_SHIFT)
820/* POSTDIV1 = 1 */
821#define SCG1_SPLL_CFG_POSTDIV1_NUM ((0x0) << SCG_PLL_CFG_POSTDIV1_SHIFT)
822
823/* MULT = 22 */
824#define SCG1_SPLL_CFG_MULT_NUM ((22) << SCG_PLL_CFG_MULT_SHIFT)
825
826/* PFD0 output clock selected */
827#define SCG1_SPLL_CFG_PFDSEL_NUM ((0) << SCG_PLL_CFG_PFDSEL_SHIFT)
828/* PREDIV = 1 */
829#define SCG1_SPLL_CFG_PREDIV_NUM ((0x0) << SCG_PLL_CFG_PREDIV_SHIFT)
830/* SPLL output clocks (including PFD outputs) selected */
831#define SCG1_SPLL_CFG_BYPASS_NUM ((0x0) << SCG_PLL_CFG_BYPASS_SHIFT)
832/* SPLL PFD output clock selected */
833#define SCG1_SPLL_CFG_PLLSEL_NUM ((0x1) << SCG_PLL_CFG_PLLSEL_SHIFT)
834/* Clock source is System OSC */
835#define SCG1_SPLL_CFG_CLKSRC_NUM ((0x0) << SCG_PLL_CFG_CLKSRC_SHIFT)
836#define SCG1_SPLL_CFG_NUM_24M_OSC (SCG1_SPLL_CFG_POSTDIV2_NUM | \
837 SCG1_SPLL_CFG_POSTDIV1_NUM | \
838 (22 << SCG_PLL_CFG_MULT_SHIFT) | \
839 SCG1_SPLL_CFG_PFDSEL_NUM | \
840 SCG1_SPLL_CFG_PREDIV_NUM | \
841 SCG1_SPLL_CFG_BYPASS_NUM | \
842 SCG1_SPLL_CFG_PLLSEL_NUM | \
843 SCG1_SPLL_CFG_CLKSRC_NUM)
844/*413Mhz = A7 SPLL(528MHz) * 18/23 */
845#define SCG1_SPLL_PFD0_FRAC_NUM ((23) << SCG_PLL_PFD0_FRAC_SHIFT)
846
847void scg_a7_spll_init(void)
848{
849 u32 val = 0;
850
851 /* Disable A7 System PLL */
852 val = readl(&scg1_regs->spllcsr);
853 val &= ~SCG_SPLL_CSR_SPLLEN_MASK;
854 writel(val, &scg1_regs->spllcsr);
855
856 /*
857 * Per block guide,
858 * "When changing PFD values, it is recommneded PFDx clock
859 * gets gated first by writing a value of 1 to PFDx_CLKGATE register,
860 * then program the new PFD value, then poll the PFDx_VALID
861 * flag to set before writing a value of 0 to PFDx_CLKGATE
862 * to ungate the PFDx clock and allow PFDx clock to run"
863 */
864
865 /* Gate off A7 SPLL PFD0 ~ PDF4 */
866 val = readl(&scg1_regs->spllpfd);
867 val |= (SCG_PLL_PFD3_GATE_MASK |
868 SCG_PLL_PFD2_GATE_MASK |
869 SCG_PLL_PFD1_GATE_MASK |
870 SCG_PLL_PFD0_GATE_MASK);
871 writel(val, &scg1_regs->spllpfd);
872
873 /* ================ A7 SPLL Configuration Start ============== */
874
875 /* Configure A7 System PLL */
876 writel(SCG1_SPLL_CFG_NUM_24M_OSC, &scg1_regs->spllcfg);
877
878 /* Enable A7 System PLL */
879 val = readl(&scg1_regs->spllcsr);
880 val |= SCG_SPLL_CSR_SPLLEN_MASK;
881 writel(val, &scg1_regs->spllcsr);
882
883 /* Wait for A7 SPLL clock ready */
884 while (!(readl(&scg1_regs->spllcsr) & SCG_SPLL_CSR_SPLLVLD_MASK))
885 ;
886
887 /* Configure A7 SPLL PFD0 */
888 val = readl(&scg1_regs->spllpfd);
889 val &= ~SCG_PLL_PFD0_FRAC_MASK;
890 val |= SCG1_SPLL_PFD0_FRAC_NUM;
891 writel(val, &scg1_regs->spllpfd);
892
893 /* Un-gate A7 SPLL PFD0 */
894 val = readl(&scg1_regs->spllpfd);
895 val &= ~SCG_PLL_PFD0_GATE_MASK;
896 writel(val, &scg1_regs->spllpfd);
897
898 /* Wait for A7 SPLL PFD0 clock being valid */
899 while (!(readl(&scg1_regs->spllpfd) & SCG_PLL_PFD0_VALID_MASK))
900 ;
901
902 /* ================ A7 SPLL Configuration End ============== */
903}
904
905/* DDR clock source is APLL PFD0 (396MHz) */
906#define SCG1_DDRCCR_DDRCS_NUM ((0x0) << SCG_DDRCCR_DDRCS_SHIFT)
907/* DDR clock = APLL PFD0 / 1 = 396MHz / 1 = 396MHz */
908#define SCG1_DDRCCR_DDRDIV_NUM ((0x1) << SCG_DDRCCR_DDRDIV_SHIFT)
909/* DDR clock = APLL PFD0 / 2 = 396MHz / 2 = 198MHz */
910#define SCG1_DDRCCR_DDRDIV_LF_NUM ((0x2) << SCG_DDRCCR_DDRDIV_SHIFT)
911#define SCG1_DDRCCR_CFG_NUM (SCG1_DDRCCR_DDRCS_NUM | \
912 SCG1_DDRCCR_DDRDIV_NUM)
913#define SCG1_DDRCCR_CFG_LF_NUM (SCG1_DDRCCR_DDRCS_NUM | \
914 SCG1_DDRCCR_DDRDIV_LF_NUM)
915void scg_a7_ddrclk_init(void)
916{
917 writel(SCG1_DDRCCR_CFG_NUM, &scg1_regs->ddrccr);
918}
919
920/* SCG1(A7) APLLCFG configurations */
921/* divide by 1 <<28 */
922#define SCG1_APLL_CFG_POSTDIV2_NUM ((0x0) << SCG_PLL_CFG_POSTDIV2_SHIFT)
923/* divide by 1 <<24 */
924#define SCG1_APLL_CFG_POSTDIV1_NUM ((0x0) << SCG_PLL_CFG_POSTDIV1_SHIFT)
925/* MULT is 22 <<16 */
926#define SCG1_APLL_CFG_MULT_NUM ((22) << SCG_PLL_CFG_MULT_SHIFT)
927/* PFD0 output clock selected <<14 */
928#define SCG1_APLL_CFG_PFDSEL_NUM ((0) << SCG_PLL_CFG_PFDSEL_SHIFT)
929/* PREDIV = 1 <<8 */
930#define SCG1_APLL_CFG_PREDIV_NUM ((0x0) << SCG_PLL_CFG_PREDIV_SHIFT)
931/* APLL output clocks (including PFD outputs) selected <<2 */
932#define SCG1_APLL_CFG_BYPASS_NUM ((0x0) << SCG_PLL_CFG_BYPASS_SHIFT)
933/* APLL PFD output clock selected <<1 */
934#define SCG1_APLL_CFG_PLLSEL_NUM ((0x0) << SCG_PLL_CFG_PLLSEL_SHIFT)
935/* Clock source is System OSC <<0 */
936#define SCG1_APLL_CFG_CLKSRC_NUM ((0x0) << SCG_PLL_CFG_CLKSRC_SHIFT)
937
938/*
939 * A7 APLL = 24MHz / 1 * 22 / 1 / 1 = 528MHz,
940 * system PLL is sourced from APLL,
941 * APLL clock source is system OSC (24MHz)
942 */
943#define SCG1_APLL_CFG_NUM_24M_OSC (SCG1_APLL_CFG_POSTDIV2_NUM | \
944 SCG1_APLL_CFG_POSTDIV1_NUM | \
945 (22 << SCG_PLL_CFG_MULT_SHIFT) | \
946 SCG1_APLL_CFG_PFDSEL_NUM | \
947 SCG1_APLL_CFG_PREDIV_NUM | \
948 SCG1_APLL_CFG_BYPASS_NUM | \
949 SCG1_APLL_CFG_PLLSEL_NUM | \
950 SCG1_APLL_CFG_CLKSRC_NUM)
951
952/* PFD0 Freq = A7 APLL(528MHz) * 18 / 27 = 352MHz */
953#define SCG1_APLL_PFD0_FRAC_NUM (27)
954
955
956void scg_a7_apll_init(void)
957{
958 u32 val = 0;
959
960 /* Disable A7 Auxiliary PLL */
961 val = readl(&scg1_regs->apllcsr);
962 val &= ~SCG_APLL_CSR_APLLEN_MASK;
963 writel(val, &scg1_regs->apllcsr);
964
965 /* Gate off A7 APLL PFD0 ~ PDF4 */
966 val = readl(&scg1_regs->apllpfd);
967 val |= 0x80808080;
968 writel(val, &scg1_regs->apllpfd);
969
970 /* ================ A7 APLL Configuration Start ============== */
971 /* Configure A7 Auxiliary PLL */
972 writel(SCG1_APLL_CFG_NUM_24M_OSC, &scg1_regs->apllcfg);
973
974 /* Enable A7 Auxiliary PLL */
975 val = readl(&scg1_regs->apllcsr);
976 val |= SCG_APLL_CSR_APLLEN_MASK;
977 writel(val, &scg1_regs->apllcsr);
978
979 /* Wait for A7 APLL clock ready */
980 while (!(readl(&scg1_regs->apllcsr) & SCG_APLL_CSR_APLLVLD_MASK))
981 ;
982
983 /* Configure A7 APLL PFD0 */
984 val = readl(&scg1_regs->apllpfd);
985 val &= ~SCG_PLL_PFD0_FRAC_MASK;
986 val |= SCG1_APLL_PFD0_FRAC_NUM;
987 writel(val, &scg1_regs->apllpfd);
988
989 /* Un-gate A7 APLL PFD0 */
990 val = readl(&scg1_regs->apllpfd);
991 val &= ~SCG_PLL_PFD0_GATE_MASK;
992 writel(val, &scg1_regs->apllpfd);
993
994 /* Wait for A7 APLL PFD0 clock being valid */
995 while (!(readl(&scg1_regs->apllpfd) & SCG_PLL_PFD0_VALID_MASK))
996 ;
997}
998
999/* SCG1(A7) FIRC DIV configurations */
1000/* Disable FIRC DIV3 */
1001#define SCG1_FIRCDIV_DIV3_NUM ((0x0) << SCG_FIRCDIV_DIV3_SHIFT)
1002/* FIRC DIV2 = 48MHz / 1 = 48MHz */
1003#define SCG1_FIRCDIV_DIV2_NUM ((0x1) << SCG_FIRCDIV_DIV2_SHIFT)
1004/* Disable FIRC DIV1 */
1005#define SCG1_FIRCDIV_DIV1_NUM ((0x0) << SCG_FIRCDIV_DIV1_SHIFT)
1006
1007void scg_a7_firc_init(void)
1008{
1009 /* Wait for FIRC clock ready */
1010 while (!(readl(&scg1_regs->firccsr) & SCG_FIRC_CSR_FIRCVLD_MASK))
1011 ;
1012
1013 /* Configure A7 FIRC DIV1 ~ DIV3 */
1014 writel((SCG1_FIRCDIV_DIV3_NUM |
1015 SCG1_FIRCDIV_DIV2_NUM |
1016 SCG1_FIRCDIV_DIV1_NUM), &scg1_regs->fircdiv);
1017}
1018
1019/* SCG1(A7) NICCCR configurations */
1020/* NIC clock source is DDR clock (396/198MHz) */
1021#define SCG1_NICCCR_NICCS_NUM ((0x1) << SCG_NICCCR_NICCS_SHIFT)
1022
1023/* NIC0 clock = DDR Clock / 2 = 396MHz / 2 = 198MHz */
1024#define SCG1_NICCCR_NIC0_DIV_NUM ((0x1) << SCG_NICCCR_NIC0_DIV_SHIFT)
1025/* NIC0 clock = DDR Clock / 1 = 198MHz / 1 = 198MHz */
1026#define SCG1_NICCCR_NIC0_DIV_LF_NUM ((0x0) << SCG_NICCCR_NIC0_DIV_SHIFT)
1027/* NIC1 clock = NIC0 Clock / 1 = 198MHz / 2 = 198MHz */
1028#define SCG1_NICCCR_NIC1_DIV_NUM ((0x0) << SCG_NICCCR_NIC1_DIV_SHIFT)
1029/* NIC1 bus clock = NIC1 Clock / 3 = 198MHz / 3 = 66MHz */
1030#define SCG1_NICCCR_NIC1_DIVBUS_NUM ((0x2) << SCG_NICCCR_NIC1_DIVBUS_SHIFT)
1031#define SCG1_NICCCR_CFG_NUM (SCG1_NICCCR_NICCS_NUM | \
1032 SCG1_NICCCR_NIC0_DIV_NUM | \
1033 SCG1_NICCCR_NIC1_DIV_NUM | \
1034 SCG1_NICCCR_NIC1_DIVBUS_NUM)
1035
1036void scg_a7_nicclk_init(void)
1037{
1038 writel(SCG1_NICCCR_CFG_NUM, &scg1_regs->nicccr);
1039}
1040
1041/* SCG1(A7) FIRC DIV configurations */
1042/* Enable FIRC DIV3 */
1043#define SCG1_SOSCDIV_DIV3_NUM ((0x1) << SCG_SOSCDIV_DIV3_SHIFT)
1044/* FIRC DIV2 = 48MHz / 1 = 48MHz */
1045#define SCG1_SOSCDIV_DIV2_NUM ((0x1) << SCG_SOSCDIV_DIV2_SHIFT)
1046/* Enable FIRC DIV1 */
1047#define SCG1_SOSCDIV_DIV1_NUM ((0x1) << SCG_SOSCDIV_DIV1_SHIFT)
1048
1049void scg_a7_soscdiv_init(void)
1050{
1051 /* Wait for FIRC clock ready */
1052 while (!(readl(&scg1_regs->sosccsr) & SCG_SOSC_CSR_SOSCVLD_MASK))
1053 ;
1054
1055 /* Configure A7 FIRC DIV1 ~ DIV3 */
1056 writel((SCG1_SOSCDIV_DIV3_NUM | SCG1_SOSCDIV_DIV2_NUM |
1057 SCG1_SOSCDIV_DIV1_NUM), &scg1_regs->soscdiv);
1058}
1059
1060void scg_a7_sys_clk_sel(enum scg_sys_src clk)
1061{
1062 u32 rccr_reg_val = 0;
1063
1064 clk_debug("%s: system clock selected as %s\n", "[SCG]",
1065 clk == SCG_SCS_SYS_OSC ? "SYS_OSC" :
1066 clk == SCG_SCS_SLOW_IRC ? "SLOW_IRC" :
1067 clk == SCG_SCS_FAST_IRC ? "FAST_IRC" :
1068 clk == SCG_SCS_RTC_OSC ? "RTC_OSC" :
1069 clk == SCG_SCS_AUX_PLL ? "AUX_PLL" :
1070 clk == SCG_SCS_SYS_PLL ? "SYS_PLL" :
1071 clk == SCG_SCS_USBPHY_PLL ? "USBPHY_PLL" :
1072 "Invalid source"
1073 );
1074
1075 rccr_reg_val = readl(&scg1_regs->rccr);
1076 rccr_reg_val &= ~SCG_CCR_SCS_MASK;
1077 rccr_reg_val |= (clk << SCG_CCR_SCS_SHIFT);
1078 writel(rccr_reg_val, &scg1_regs->rccr);
1079}
1080
1081void scg_a7_info(void)
1082{
1083 debug("SCG Version: 0x%x\n", readl(&scg1_regs->verid));
1084 debug("SCG Parameter: 0x%x\n", readl(&scg1_regs->param));
1085 debug("SCG RCCR Value: 0x%x\n", readl(&scg1_regs->rccr));
1086 debug("SCG Clock Status: 0x%x\n", readl(&scg1_regs->csr));
1087}