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