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