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