xref: /openbmc/u-boot/arch/arm/mach-imx/mx7ulp/scg.c (revision e8f80a5a)
1*83d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
2552a848eSStefano Babic /*
3552a848eSStefano Babic  * Copyright (C) 2016 Freescale Semiconductor, Inc.
4552a848eSStefano Babic  */
5552a848eSStefano Babic 
6552a848eSStefano Babic #include <common.h>
7552a848eSStefano Babic #include <div64.h>
8552a848eSStefano Babic #include <asm/io.h>
9552a848eSStefano Babic #include <errno.h>
10552a848eSStefano Babic #include <asm/arch/imx-regs.h>
11552a848eSStefano Babic #include <asm/arch/pcc.h>
12552a848eSStefano Babic #include <asm/arch/sys_proto.h>
13552a848eSStefano Babic 
14552a848eSStefano Babic scg_p scg1_regs = (scg_p)SCG1_RBASE;
15552a848eSStefano Babic 
scg_src_get_rate(enum scg_clk clksrc)16552a848eSStefano Babic static u32 scg_src_get_rate(enum scg_clk clksrc)
17552a848eSStefano Babic {
18552a848eSStefano Babic 	u32 reg;
19552a848eSStefano Babic 
20552a848eSStefano Babic 	switch (clksrc) {
21552a848eSStefano Babic 	case SCG_SOSC_CLK:
22552a848eSStefano Babic 		reg = readl(&scg1_regs->sosccsr);
23552a848eSStefano Babic 		if (!(reg & SCG_SOSC_CSR_SOSCVLD_MASK))
24552a848eSStefano Babic 			return 0;
25552a848eSStefano Babic 
26552a848eSStefano Babic 		return 24000000;
27552a848eSStefano Babic 	case SCG_FIRC_CLK:
28552a848eSStefano Babic 		reg = readl(&scg1_regs->firccsr);
29552a848eSStefano Babic 		if (!(reg & SCG_FIRC_CSR_FIRCVLD_MASK))
30552a848eSStefano Babic 			return 0;
31552a848eSStefano Babic 
32552a848eSStefano Babic 		return 48000000;
33552a848eSStefano Babic 	case SCG_SIRC_CLK:
34552a848eSStefano Babic 		reg = readl(&scg1_regs->sirccsr);
35552a848eSStefano Babic 		if (!(reg & SCG_SIRC_CSR_SIRCVLD_MASK))
36552a848eSStefano Babic 			return 0;
37552a848eSStefano Babic 
38552a848eSStefano Babic 		return 16000000;
39552a848eSStefano Babic 	case SCG_ROSC_CLK:
40552a848eSStefano Babic 		reg = readl(&scg1_regs->rtccsr);
41552a848eSStefano Babic 		if (!(reg & SCG_ROSC_CSR_ROSCVLD_MASK))
42552a848eSStefano Babic 			return 0;
43552a848eSStefano Babic 
44552a848eSStefano Babic 		return 32768;
45552a848eSStefano Babic 	default:
46552a848eSStefano Babic 		break;
47552a848eSStefano Babic 	}
48552a848eSStefano Babic 
49552a848eSStefano Babic 	return 0;
50552a848eSStefano Babic }
51552a848eSStefano Babic 
scg_sircdiv_get_rate(enum scg_clk clk)52552a848eSStefano Babic static u32 scg_sircdiv_get_rate(enum scg_clk clk)
53552a848eSStefano Babic {
54552a848eSStefano Babic 	u32 reg, val, rate;
55552a848eSStefano Babic 	u32 shift, mask;
56552a848eSStefano Babic 
57552a848eSStefano Babic 	switch (clk) {
58552a848eSStefano Babic 	case SCG_SIRC_DIV1_CLK:
59552a848eSStefano Babic 		mask = SCG_SIRCDIV_DIV1_MASK;
60552a848eSStefano Babic 		shift = SCG_SIRCDIV_DIV1_SHIFT;
61552a848eSStefano Babic 		break;
62552a848eSStefano Babic 	case SCG_SIRC_DIV2_CLK:
63552a848eSStefano Babic 		mask = SCG_SIRCDIV_DIV2_MASK;
64552a848eSStefano Babic 		shift = SCG_SIRCDIV_DIV2_SHIFT;
65552a848eSStefano Babic 		break;
66552a848eSStefano Babic 	case SCG_SIRC_DIV3_CLK:
67552a848eSStefano Babic 		mask = SCG_SIRCDIV_DIV3_MASK;
68552a848eSStefano Babic 		shift = SCG_SIRCDIV_DIV3_SHIFT;
69552a848eSStefano Babic 		break;
70552a848eSStefano Babic 	default:
71552a848eSStefano Babic 		return 0;
72552a848eSStefano Babic 	}
73552a848eSStefano Babic 
74552a848eSStefano Babic 	reg = readl(&scg1_regs->sirccsr);
75552a848eSStefano Babic 	if (!(reg & SCG_SIRC_CSR_SIRCVLD_MASK))
76552a848eSStefano Babic 		return 0;
77552a848eSStefano Babic 
78552a848eSStefano Babic 	reg = readl(&scg1_regs->sircdiv);
79552a848eSStefano Babic 	val = (reg & mask) >> shift;
80552a848eSStefano Babic 
81552a848eSStefano Babic 	if (!val) /*clock disabled*/
82552a848eSStefano Babic 		return 0;
83552a848eSStefano Babic 
84552a848eSStefano Babic 	rate = scg_src_get_rate(SCG_SIRC_CLK);
85552a848eSStefano Babic 	rate = rate / (1 << (val - 1));
86552a848eSStefano Babic 
87552a848eSStefano Babic 	return rate;
88552a848eSStefano Babic }
89552a848eSStefano Babic 
scg_fircdiv_get_rate(enum scg_clk clk)90552a848eSStefano Babic static u32 scg_fircdiv_get_rate(enum scg_clk clk)
91552a848eSStefano Babic {
92552a848eSStefano Babic 	u32 reg, val, rate;
93552a848eSStefano Babic 	u32 shift, mask;
94552a848eSStefano Babic 
95552a848eSStefano Babic 	switch (clk) {
96552a848eSStefano Babic 	case SCG_FIRC_DIV1_CLK:
97552a848eSStefano Babic 		mask = SCG_FIRCDIV_DIV1_MASK;
98552a848eSStefano Babic 		shift = SCG_FIRCDIV_DIV1_SHIFT;
99552a848eSStefano Babic 		break;
100552a848eSStefano Babic 	case SCG_FIRC_DIV2_CLK:
101552a848eSStefano Babic 		mask = SCG_FIRCDIV_DIV2_MASK;
102552a848eSStefano Babic 		shift = SCG_FIRCDIV_DIV2_SHIFT;
103552a848eSStefano Babic 		break;
104552a848eSStefano Babic 	case SCG_FIRC_DIV3_CLK:
105552a848eSStefano Babic 		mask = SCG_FIRCDIV_DIV3_MASK;
106552a848eSStefano Babic 		shift = SCG_FIRCDIV_DIV3_SHIFT;
107552a848eSStefano Babic 		break;
108552a848eSStefano Babic 	default:
109552a848eSStefano Babic 		return 0;
110552a848eSStefano Babic 	}
111552a848eSStefano Babic 
112552a848eSStefano Babic 	reg = readl(&scg1_regs->firccsr);
113552a848eSStefano Babic 	if (!(reg & SCG_FIRC_CSR_FIRCVLD_MASK))
114552a848eSStefano Babic 		return 0;
115552a848eSStefano Babic 
116552a848eSStefano Babic 	reg = readl(&scg1_regs->fircdiv);
117552a848eSStefano Babic 	val = (reg & mask) >> shift;
118552a848eSStefano Babic 
119552a848eSStefano Babic 	if (!val) /*clock disabled*/
120552a848eSStefano Babic 		return 0;
121552a848eSStefano Babic 
122552a848eSStefano Babic 	rate = scg_src_get_rate(SCG_FIRC_CLK);
123552a848eSStefano Babic 	rate = rate / (1 << (val - 1));
124552a848eSStefano Babic 
125552a848eSStefano Babic 	return rate;
126552a848eSStefano Babic }
127552a848eSStefano Babic 
scg_soscdiv_get_rate(enum scg_clk clk)128552a848eSStefano Babic static u32 scg_soscdiv_get_rate(enum scg_clk clk)
129552a848eSStefano Babic {
130552a848eSStefano Babic 	u32 reg, val, rate;
131552a848eSStefano Babic 	u32 shift, mask;
132552a848eSStefano Babic 
133552a848eSStefano Babic 	switch (clk) {
134552a848eSStefano Babic 	case SCG_SOSC_DIV1_CLK:
135552a848eSStefano Babic 		mask = SCG_SOSCDIV_DIV1_MASK;
136552a848eSStefano Babic 		shift = SCG_SOSCDIV_DIV1_SHIFT;
137552a848eSStefano Babic 		break;
138552a848eSStefano Babic 	case SCG_SOSC_DIV2_CLK:
139552a848eSStefano Babic 		mask = SCG_SOSCDIV_DIV2_MASK;
140552a848eSStefano Babic 		shift = SCG_SOSCDIV_DIV2_SHIFT;
141552a848eSStefano Babic 		break;
142552a848eSStefano Babic 	case SCG_SOSC_DIV3_CLK:
143552a848eSStefano Babic 		mask = SCG_SOSCDIV_DIV3_MASK;
144552a848eSStefano Babic 		shift = SCG_SOSCDIV_DIV3_SHIFT;
145552a848eSStefano Babic 		break;
146552a848eSStefano Babic 	default:
147552a848eSStefano Babic 		return 0;
148552a848eSStefano Babic 	}
149552a848eSStefano Babic 
150552a848eSStefano Babic 	reg = readl(&scg1_regs->sosccsr);
151552a848eSStefano Babic 	if (!(reg & SCG_SOSC_CSR_SOSCVLD_MASK))
152552a848eSStefano Babic 		return 0;
153552a848eSStefano Babic 
154552a848eSStefano Babic 	reg = readl(&scg1_regs->soscdiv);
155552a848eSStefano Babic 	val = (reg & mask) >> shift;
156552a848eSStefano Babic 
157552a848eSStefano Babic 	if (!val) /*clock disabled*/
158552a848eSStefano Babic 		return 0;
159552a848eSStefano Babic 
160552a848eSStefano Babic 	rate = scg_src_get_rate(SCG_SOSC_CLK);
161552a848eSStefano Babic 	rate = rate / (1 << (val - 1));
162552a848eSStefano Babic 
163552a848eSStefano Babic 	return rate;
164552a848eSStefano Babic }
165552a848eSStefano Babic 
scg_apll_pfd_get_rate(enum scg_clk clk)166552a848eSStefano Babic static u32 scg_apll_pfd_get_rate(enum scg_clk clk)
167552a848eSStefano Babic {
168552a848eSStefano Babic 	u32 reg, val, rate;
169552a848eSStefano Babic 	u32 shift, mask, gate, valid;
170552a848eSStefano Babic 
171552a848eSStefano Babic 	switch (clk) {
172552a848eSStefano Babic 	case SCG_APLL_PFD0_CLK:
173552a848eSStefano Babic 		gate = SCG_PLL_PFD0_GATE_MASK;
174552a848eSStefano Babic 		valid = SCG_PLL_PFD0_VALID_MASK;
175552a848eSStefano Babic 		mask = SCG_PLL_PFD0_FRAC_MASK;
176552a848eSStefano Babic 		shift = SCG_PLL_PFD0_FRAC_SHIFT;
177552a848eSStefano Babic 		break;
178552a848eSStefano Babic 	case SCG_APLL_PFD1_CLK:
179552a848eSStefano Babic 		gate = SCG_PLL_PFD1_GATE_MASK;
180552a848eSStefano Babic 		valid = SCG_PLL_PFD1_VALID_MASK;
181552a848eSStefano Babic 		mask = SCG_PLL_PFD1_FRAC_MASK;
182552a848eSStefano Babic 		shift = SCG_PLL_PFD1_FRAC_SHIFT;
183552a848eSStefano Babic 		break;
184552a848eSStefano Babic 	case SCG_APLL_PFD2_CLK:
185552a848eSStefano Babic 		gate = SCG_PLL_PFD2_GATE_MASK;
186552a848eSStefano Babic 		valid = SCG_PLL_PFD2_VALID_MASK;
187552a848eSStefano Babic 		mask = SCG_PLL_PFD2_FRAC_MASK;
188552a848eSStefano Babic 		shift = SCG_PLL_PFD2_FRAC_SHIFT;
189552a848eSStefano Babic 		break;
190552a848eSStefano Babic 	case SCG_APLL_PFD3_CLK:
191552a848eSStefano Babic 		gate = SCG_PLL_PFD3_GATE_MASK;
192552a848eSStefano Babic 		valid = SCG_PLL_PFD3_VALID_MASK;
193552a848eSStefano Babic 		mask = SCG_PLL_PFD3_FRAC_MASK;
194552a848eSStefano Babic 		shift = SCG_PLL_PFD3_FRAC_SHIFT;
195552a848eSStefano Babic 		break;
196552a848eSStefano Babic 	default:
197552a848eSStefano Babic 		return 0;
198552a848eSStefano Babic 	}
199552a848eSStefano Babic 
200552a848eSStefano Babic 	reg = readl(&scg1_regs->apllpfd);
201552a848eSStefano Babic 	if (reg & gate || !(reg & valid))
202552a848eSStefano Babic 		return 0;
203552a848eSStefano Babic 
204552a848eSStefano Babic 	clk_debug("scg_apll_pfd_get_rate reg 0x%x\n", reg);
205552a848eSStefano Babic 
206552a848eSStefano Babic 	val = (reg & mask) >> shift;
207552a848eSStefano Babic 	rate = decode_pll(PLL_A7_APLL);
208552a848eSStefano Babic 
209552a848eSStefano Babic 	rate = rate / val * 18;
210552a848eSStefano Babic 
211552a848eSStefano Babic 	clk_debug("scg_apll_pfd_get_rate rate %u\n", rate);
212552a848eSStefano Babic 
213552a848eSStefano Babic 	return rate;
214552a848eSStefano Babic }
215552a848eSStefano Babic 
scg_spll_pfd_get_rate(enum scg_clk clk)216552a848eSStefano Babic static u32 scg_spll_pfd_get_rate(enum scg_clk clk)
217552a848eSStefano Babic {
218552a848eSStefano Babic 	u32 reg, val, rate;
219552a848eSStefano Babic 	u32 shift, mask, gate, valid;
220552a848eSStefano Babic 
221552a848eSStefano Babic 	switch (clk) {
222552a848eSStefano Babic 	case SCG_SPLL_PFD0_CLK:
223552a848eSStefano Babic 		gate = SCG_PLL_PFD0_GATE_MASK;
224552a848eSStefano Babic 		valid = SCG_PLL_PFD0_VALID_MASK;
225552a848eSStefano Babic 		mask = SCG_PLL_PFD0_FRAC_MASK;
226552a848eSStefano Babic 		shift = SCG_PLL_PFD0_FRAC_SHIFT;
227552a848eSStefano Babic 		break;
228552a848eSStefano Babic 	case SCG_SPLL_PFD1_CLK:
229552a848eSStefano Babic 		gate = SCG_PLL_PFD1_GATE_MASK;
230552a848eSStefano Babic 		valid = SCG_PLL_PFD1_VALID_MASK;
231552a848eSStefano Babic 		mask = SCG_PLL_PFD1_FRAC_MASK;
232552a848eSStefano Babic 		shift = SCG_PLL_PFD1_FRAC_SHIFT;
233552a848eSStefano Babic 		break;
234552a848eSStefano Babic 	case SCG_SPLL_PFD2_CLK:
235552a848eSStefano Babic 		gate = SCG_PLL_PFD2_GATE_MASK;
236552a848eSStefano Babic 		valid = SCG_PLL_PFD2_VALID_MASK;
237552a848eSStefano Babic 		mask = SCG_PLL_PFD2_FRAC_MASK;
238552a848eSStefano Babic 		shift = SCG_PLL_PFD2_FRAC_SHIFT;
239552a848eSStefano Babic 		break;
240552a848eSStefano Babic 	case SCG_SPLL_PFD3_CLK:
241552a848eSStefano Babic 		gate = SCG_PLL_PFD3_GATE_MASK;
242552a848eSStefano Babic 		valid = SCG_PLL_PFD3_VALID_MASK;
243552a848eSStefano Babic 		mask = SCG_PLL_PFD3_FRAC_MASK;
244552a848eSStefano Babic 		shift = SCG_PLL_PFD3_FRAC_SHIFT;
245552a848eSStefano Babic 		break;
246552a848eSStefano Babic 	default:
247552a848eSStefano Babic 		return 0;
248552a848eSStefano Babic 	}
249552a848eSStefano Babic 
250552a848eSStefano Babic 	reg = readl(&scg1_regs->spllpfd);
251552a848eSStefano Babic 	if (reg & gate || !(reg & valid))
252552a848eSStefano Babic 		return 0;
253552a848eSStefano Babic 
254552a848eSStefano Babic 	clk_debug("scg_spll_pfd_get_rate reg 0x%x\n", reg);
255552a848eSStefano Babic 
256552a848eSStefano Babic 	val = (reg & mask) >> shift;
257552a848eSStefano Babic 	rate = decode_pll(PLL_A7_SPLL);
258552a848eSStefano Babic 
259552a848eSStefano Babic 	rate = rate / val * 18;
260552a848eSStefano Babic 
261552a848eSStefano Babic 	clk_debug("scg_spll_pfd_get_rate rate %u\n", rate);
262552a848eSStefano Babic 
263552a848eSStefano Babic 	return rate;
264552a848eSStefano Babic }
265552a848eSStefano Babic 
scg_apll_get_rate(void)266552a848eSStefano Babic static u32 scg_apll_get_rate(void)
267552a848eSStefano Babic {
268552a848eSStefano Babic 	u32 reg, val, rate;
269552a848eSStefano Babic 
270552a848eSStefano Babic 	reg = readl(&scg1_regs->apllcfg);
271552a848eSStefano Babic 	val = (reg & SCG_PLL_CFG_PLLSEL_MASK) >> SCG_PLL_CFG_PLLSEL_SHIFT;
272552a848eSStefano Babic 
273552a848eSStefano Babic 	if (!val) {
274552a848eSStefano Babic 		/* APLL clock after two dividers */
275552a848eSStefano Babic 		rate = decode_pll(PLL_A7_APLL);
276552a848eSStefano Babic 
277552a848eSStefano Babic 		val = (reg & SCG_PLL_CFG_POSTDIV1_MASK) >>
278552a848eSStefano Babic 			SCG_PLL_CFG_POSTDIV1_SHIFT;
279552a848eSStefano Babic 		rate = rate / (val + 1);
280552a848eSStefano Babic 
281552a848eSStefano Babic 		val = (reg & SCG_PLL_CFG_POSTDIV2_MASK) >>
282552a848eSStefano Babic 			SCG_PLL_CFG_POSTDIV2_SHIFT;
283552a848eSStefano Babic 		rate = rate / (val + 1);
284552a848eSStefano Babic 	} else {
285552a848eSStefano Babic 		/* APLL PFD clock */
286552a848eSStefano Babic 		val = (reg & SCG_PLL_CFG_PFDSEL_MASK) >>
287552a848eSStefano Babic 			SCG_PLL_CFG_PFDSEL_SHIFT;
288552a848eSStefano Babic 		rate = scg_apll_pfd_get_rate(SCG_APLL_PFD0_CLK + val);
289552a848eSStefano Babic 	}
290552a848eSStefano Babic 
291552a848eSStefano Babic 	return rate;
292552a848eSStefano Babic }
293552a848eSStefano Babic 
scg_spll_get_rate(void)294552a848eSStefano Babic static u32 scg_spll_get_rate(void)
295552a848eSStefano Babic {
296552a848eSStefano Babic 	u32 reg, val, rate;
297552a848eSStefano Babic 
298552a848eSStefano Babic 	reg = readl(&scg1_regs->spllcfg);
299552a848eSStefano Babic 	val = (reg & SCG_PLL_CFG_PLLSEL_MASK) >> SCG_PLL_CFG_PLLSEL_SHIFT;
300552a848eSStefano Babic 
301552a848eSStefano Babic 	clk_debug("scg_spll_get_rate reg 0x%x\n", reg);
302552a848eSStefano Babic 
303552a848eSStefano Babic 	if (!val) {
304552a848eSStefano Babic 		/* APLL clock after two dividers */
305552a848eSStefano Babic 		rate = decode_pll(PLL_A7_SPLL);
306552a848eSStefano Babic 
307552a848eSStefano Babic 		val = (reg & SCG_PLL_CFG_POSTDIV1_MASK) >>
308552a848eSStefano Babic 			SCG_PLL_CFG_POSTDIV1_SHIFT;
309552a848eSStefano Babic 		rate = rate / (val + 1);
310552a848eSStefano Babic 
311552a848eSStefano Babic 		val = (reg & SCG_PLL_CFG_POSTDIV2_MASK) >>
312552a848eSStefano Babic 			SCG_PLL_CFG_POSTDIV2_SHIFT;
313552a848eSStefano Babic 		rate = rate / (val + 1);
314552a848eSStefano Babic 
315552a848eSStefano Babic 		clk_debug("scg_spll_get_rate SPLL %u\n", rate);
316552a848eSStefano Babic 
317552a848eSStefano Babic 	} else {
318552a848eSStefano Babic 		/* APLL PFD clock */
319552a848eSStefano Babic 		val = (reg & SCG_PLL_CFG_PFDSEL_MASK) >>
320552a848eSStefano Babic 			SCG_PLL_CFG_PFDSEL_SHIFT;
321552a848eSStefano Babic 		rate = scg_spll_pfd_get_rate(SCG_SPLL_PFD0_CLK + val);
322552a848eSStefano Babic 
323552a848eSStefano Babic 		clk_debug("scg_spll_get_rate PFD %u\n", rate);
324552a848eSStefano Babic 	}
325552a848eSStefano Babic 
326552a848eSStefano Babic 	return rate;
327552a848eSStefano Babic }
328552a848eSStefano Babic 
scg_ddr_get_rate(void)329552a848eSStefano Babic static u32 scg_ddr_get_rate(void)
330552a848eSStefano Babic {
331552a848eSStefano Babic 	u32 reg, val, rate, div;
332552a848eSStefano Babic 
333552a848eSStefano Babic 	reg = readl(&scg1_regs->ddrccr);
334552a848eSStefano Babic 	val = (reg & SCG_DDRCCR_DDRCS_MASK) >> SCG_DDRCCR_DDRCS_SHIFT;
335552a848eSStefano Babic 	div = (reg & SCG_DDRCCR_DDRDIV_MASK) >> SCG_DDRCCR_DDRDIV_SHIFT;
336552a848eSStefano Babic 
337552a848eSStefano Babic 	if (!div)
338552a848eSStefano Babic 		return 0;
339552a848eSStefano Babic 
340552a848eSStefano Babic 	if (!val) {
341552a848eSStefano Babic 		reg = readl(&scg1_regs->apllcfg);
342552a848eSStefano Babic 		val = (reg & SCG_PLL_CFG_PFDSEL_MASK) >>
343552a848eSStefano Babic 			SCG_PLL_CFG_PFDSEL_SHIFT;
344552a848eSStefano Babic 		rate = scg_apll_pfd_get_rate(SCG_APLL_PFD0_CLK + val);
345552a848eSStefano Babic 	} else {
346552a848eSStefano Babic 		rate = decode_pll(PLL_USB);
347552a848eSStefano Babic 	}
348552a848eSStefano Babic 
349552a848eSStefano Babic 	rate = rate / (1 << (div - 1));
350552a848eSStefano Babic 	return rate;
351552a848eSStefano Babic }
352552a848eSStefano Babic 
scg_nic_get_rate(enum scg_clk clk)353552a848eSStefano Babic static u32 scg_nic_get_rate(enum scg_clk clk)
354552a848eSStefano Babic {
355552a848eSStefano Babic 	u32 reg, val, rate;
356552a848eSStefano Babic 	u32 shift, mask;
357552a848eSStefano Babic 
358552a848eSStefano Babic 	reg = readl(&scg1_regs->niccsr);
359552a848eSStefano Babic 	val = (reg & SCG_NICCSR_NICCS_MASK) >> SCG_NICCSR_NICCS_SHIFT;
360552a848eSStefano Babic 
361552a848eSStefano Babic 	clk_debug("scg_nic_get_rate niccsr 0x%x\n", reg);
362552a848eSStefano Babic 
363552a848eSStefano Babic 	if (!val)
364552a848eSStefano Babic 		rate = scg_src_get_rate(SCG_FIRC_CLK);
365552a848eSStefano Babic 	else
366552a848eSStefano Babic 		rate = scg_ddr_get_rate();
367552a848eSStefano Babic 
368552a848eSStefano Babic 	clk_debug("scg_nic_get_rate parent rate %u\n", rate);
369552a848eSStefano Babic 
370552a848eSStefano Babic 	val = (reg & SCG_NICCSR_NIC0DIV_MASK) >> SCG_NICCSR_NIC0DIV_SHIFT;
371552a848eSStefano Babic 
372552a848eSStefano Babic 	rate = rate / (val + 1);
373552a848eSStefano Babic 
374552a848eSStefano Babic 	clk_debug("scg_nic_get_rate NIC0 rate %u\n", rate);
375552a848eSStefano Babic 
376552a848eSStefano Babic 	switch (clk) {
377552a848eSStefano Babic 	case SCG_NIC0_CLK:
378552a848eSStefano Babic 		return rate;
379552a848eSStefano Babic 	case SCG_GPU_CLK:
380552a848eSStefano Babic 		mask = SCG_NICCSR_GPUDIV_MASK;
381552a848eSStefano Babic 		shift = SCG_NICCSR_GPUDIV_SHIFT;
382552a848eSStefano Babic 		break;
383552a848eSStefano Babic 	case SCG_NIC1_EXT_CLK:
384552a848eSStefano Babic 	case SCG_NIC1_BUS_CLK:
385552a848eSStefano Babic 	case SCG_NIC1_CLK:
386552a848eSStefano Babic 		mask = SCG_NICCSR_NIC1DIV_MASK;
387552a848eSStefano Babic 		shift = SCG_NICCSR_NIC1DIV_SHIFT;
388552a848eSStefano Babic 		break;
389552a848eSStefano Babic 	default:
390552a848eSStefano Babic 		return 0;
391552a848eSStefano Babic 	}
392552a848eSStefano Babic 
393552a848eSStefano Babic 	val = (reg & mask) >> shift;
394552a848eSStefano Babic 	rate = rate / (val + 1);
395552a848eSStefano Babic 
396552a848eSStefano Babic 	clk_debug("scg_nic_get_rate NIC1 rate %u\n", rate);
397552a848eSStefano Babic 
398552a848eSStefano Babic 	switch (clk) {
399552a848eSStefano Babic 	case SCG_GPU_CLK:
400552a848eSStefano Babic 	case SCG_NIC1_CLK:
401552a848eSStefano Babic 		return rate;
402552a848eSStefano Babic 	case SCG_NIC1_EXT_CLK:
403552a848eSStefano Babic 		mask = SCG_NICCSR_NIC1EXTDIV_MASK;
404552a848eSStefano Babic 		shift = SCG_NICCSR_NIC1EXTDIV_SHIFT;
405552a848eSStefano Babic 		break;
406552a848eSStefano Babic 	case SCG_NIC1_BUS_CLK:
407552a848eSStefano Babic 		mask = SCG_NICCSR_NIC1BUSDIV_MASK;
408552a848eSStefano Babic 		shift = SCG_NICCSR_NIC1BUSDIV_SHIFT;
409552a848eSStefano Babic 		break;
410552a848eSStefano Babic 	default:
411552a848eSStefano Babic 		return 0;
412552a848eSStefano Babic 	}
413552a848eSStefano Babic 
414552a848eSStefano Babic 	val = (reg & mask) >> shift;
415552a848eSStefano Babic 	rate = rate / (val + 1);
416552a848eSStefano Babic 
417552a848eSStefano Babic 	clk_debug("scg_nic_get_rate NIC1 bus rate %u\n", rate);
418552a848eSStefano Babic 	return rate;
419552a848eSStefano Babic }
420552a848eSStefano Babic 
421552a848eSStefano Babic 
422552a848eSStefano Babic static enum scg_clk scg_scs_array[4] = {
423552a848eSStefano Babic 	SCG_SOSC_CLK, SCG_SIRC_CLK, SCG_FIRC_CLK, SCG_ROSC_CLK,
424552a848eSStefano Babic };
425552a848eSStefano Babic 
scg_sys_get_rate(enum scg_clk clk)426552a848eSStefano Babic static u32 scg_sys_get_rate(enum scg_clk clk)
427552a848eSStefano Babic {
428552a848eSStefano Babic 	u32 reg, val, rate;
429552a848eSStefano Babic 
430552a848eSStefano Babic 	if (clk != SCG_CORE_CLK && clk != SCG_BUS_CLK)
431552a848eSStefano Babic 		return 0;
432552a848eSStefano Babic 
433552a848eSStefano Babic 	reg = readl(&scg1_regs->csr);
434552a848eSStefano Babic 	val = (reg & SCG_CCR_SCS_MASK) >> SCG_CCR_SCS_SHIFT;
435552a848eSStefano Babic 
436552a848eSStefano Babic 	clk_debug("scg_sys_get_rate reg 0x%x\n", reg);
437552a848eSStefano Babic 
438552a848eSStefano Babic 	switch (val) {
439552a848eSStefano Babic 	case SCG_SCS_SYS_OSC:
440552a848eSStefano Babic 	case SCG_SCS_SLOW_IRC:
441552a848eSStefano Babic 	case SCG_SCS_FAST_IRC:
442552a848eSStefano Babic 	case SCG_SCS_RTC_OSC:
443552a848eSStefano Babic 		rate = scg_src_get_rate(scg_scs_array[val]);
444552a848eSStefano Babic 		break;
445552a848eSStefano Babic 	case 5:
446552a848eSStefano Babic 		rate = scg_apll_get_rate();
447552a848eSStefano Babic 		break;
448552a848eSStefano Babic 	case 6:
449552a848eSStefano Babic 		rate = scg_spll_get_rate();
450552a848eSStefano Babic 		break;
451552a848eSStefano Babic 	default:
452552a848eSStefano Babic 		return 0;
453552a848eSStefano Babic 	}
454552a848eSStefano Babic 
455552a848eSStefano Babic 	clk_debug("scg_sys_get_rate parent rate %u\n", rate);
456552a848eSStefano Babic 
457552a848eSStefano Babic 	val = (reg & SCG_CCR_DIVCORE_MASK) >> SCG_CCR_DIVCORE_SHIFT;
458552a848eSStefano Babic 
459552a848eSStefano Babic 	rate = rate / (val + 1);
460552a848eSStefano Babic 
461552a848eSStefano Babic 	if (clk == SCG_BUS_CLK) {
462552a848eSStefano Babic 		val = (reg & SCG_CCR_DIVBUS_MASK) >> SCG_CCR_DIVBUS_SHIFT;
463552a848eSStefano Babic 		rate = rate / (val + 1);
464552a848eSStefano Babic 	}
465552a848eSStefano Babic 
466552a848eSStefano Babic 	return rate;
467552a848eSStefano Babic }
468552a848eSStefano Babic 
decode_pll(enum pll_clocks pll)469552a848eSStefano Babic u32 decode_pll(enum pll_clocks pll)
470552a848eSStefano Babic {
471552a848eSStefano Babic 	u32 reg,  pre_div, infreq, mult;
472552a848eSStefano Babic 	u32 num, denom;
473552a848eSStefano Babic 
474552a848eSStefano Babic 	/*
475552a848eSStefano Babic 	 * Alought there are four choices for the bypass src,
476552a848eSStefano Babic 	 * we choose OSC_24M which is the default set in ROM.
477552a848eSStefano Babic 	 */
478552a848eSStefano Babic 	switch (pll) {
479552a848eSStefano Babic 	case PLL_A7_SPLL:
480552a848eSStefano Babic 		reg = readl(&scg1_regs->spllcsr);
481552a848eSStefano Babic 
482552a848eSStefano Babic 		if (!(reg & SCG_SPLL_CSR_SPLLVLD_MASK))
483552a848eSStefano Babic 			return 0;
484552a848eSStefano Babic 
485552a848eSStefano Babic 		reg = readl(&scg1_regs->spllcfg);
486552a848eSStefano Babic 
487552a848eSStefano Babic 		pre_div = (reg & SCG_PLL_CFG_PREDIV_MASK) >>
488552a848eSStefano Babic 			   SCG_PLL_CFG_PREDIV_SHIFT;
489552a848eSStefano Babic 		pre_div += 1;
490552a848eSStefano Babic 
491552a848eSStefano Babic 		mult = (reg & SCG1_SPLL_CFG_MULT_MASK) >>
492552a848eSStefano Babic 			   SCG_PLL_CFG_MULT_SHIFT;
493552a848eSStefano Babic 
494552a848eSStefano Babic 		infreq = (reg & SCG_PLL_CFG_CLKSRC_MASK) >>
495552a848eSStefano Babic 			   SCG_PLL_CFG_CLKSRC_SHIFT;
496552a848eSStefano Babic 		if (!infreq)
497552a848eSStefano Babic 			infreq = scg_src_get_rate(SCG_SOSC_CLK);
498552a848eSStefano Babic 		else
499552a848eSStefano Babic 			infreq = scg_src_get_rate(SCG_FIRC_CLK);
500552a848eSStefano Babic 
501552a848eSStefano Babic 		num = readl(&scg1_regs->spllnum);
502552a848eSStefano Babic 		denom = readl(&scg1_regs->splldenom);
503552a848eSStefano Babic 
504552a848eSStefano Babic 		infreq = infreq / pre_div;
505552a848eSStefano Babic 
506552a848eSStefano Babic 		return infreq * mult + infreq * num / denom;
507552a848eSStefano Babic 
508552a848eSStefano Babic 	case PLL_A7_APLL:
509552a848eSStefano Babic 		reg = readl(&scg1_regs->apllcsr);
510552a848eSStefano Babic 
511552a848eSStefano Babic 		if (!(reg & SCG_APLL_CSR_APLLVLD_MASK))
512552a848eSStefano Babic 			return 0;
513552a848eSStefano Babic 
514552a848eSStefano Babic 		reg = readl(&scg1_regs->apllcfg);
515552a848eSStefano Babic 
516552a848eSStefano Babic 		pre_div = (reg & SCG_PLL_CFG_PREDIV_MASK) >>
517552a848eSStefano Babic 			   SCG_PLL_CFG_PREDIV_SHIFT;
518552a848eSStefano Babic 		pre_div += 1;
519552a848eSStefano Babic 
520552a848eSStefano Babic 		mult = (reg & SCG_APLL_CFG_MULT_MASK) >>
521552a848eSStefano Babic 			   SCG_PLL_CFG_MULT_SHIFT;
522552a848eSStefano Babic 
523552a848eSStefano Babic 		infreq = (reg & SCG_PLL_CFG_CLKSRC_MASK) >>
524552a848eSStefano Babic 			   SCG_PLL_CFG_CLKSRC_SHIFT;
525552a848eSStefano Babic 		if (!infreq)
526552a848eSStefano Babic 			infreq = scg_src_get_rate(SCG_SOSC_CLK);
527552a848eSStefano Babic 		else
528552a848eSStefano Babic 			infreq = scg_src_get_rate(SCG_FIRC_CLK);
529552a848eSStefano Babic 
530552a848eSStefano Babic 		num = readl(&scg1_regs->apllnum);
531552a848eSStefano Babic 		denom = readl(&scg1_regs->aplldenom);
532552a848eSStefano Babic 
533552a848eSStefano Babic 		infreq = infreq / pre_div;
534552a848eSStefano Babic 
535552a848eSStefano Babic 		return infreq * mult + infreq * num / denom;
536552a848eSStefano Babic 
537552a848eSStefano Babic 	case PLL_USB:
538552a848eSStefano Babic 		reg = readl(&scg1_regs->upllcsr);
539552a848eSStefano Babic 
540552a848eSStefano Babic 		if (!(reg & SCG_UPLL_CSR_UPLLVLD_MASK))
541552a848eSStefano Babic 			return 0;
542552a848eSStefano Babic 
543552a848eSStefano Babic 		return 480000000u;
544552a848eSStefano Babic 
545552a848eSStefano Babic 	case PLL_MIPI:
546552a848eSStefano Babic 		return 480000000u;
547552a848eSStefano Babic 	default:
548552a848eSStefano Babic 		printf("Unsupported pll clocks %d\n", pll);
549552a848eSStefano Babic 		break;
550552a848eSStefano Babic 	}
551552a848eSStefano Babic 
552552a848eSStefano Babic 	return 0;
553552a848eSStefano Babic }
554552a848eSStefano Babic 
scg_clk_get_rate(enum scg_clk clk)555552a848eSStefano Babic u32 scg_clk_get_rate(enum scg_clk clk)
556552a848eSStefano Babic {
557552a848eSStefano Babic 	switch (clk) {
558552a848eSStefano Babic 	case SCG_SIRC_DIV1_CLK:
559552a848eSStefano Babic 	case SCG_SIRC_DIV2_CLK:
560552a848eSStefano Babic 	case SCG_SIRC_DIV3_CLK:
561552a848eSStefano Babic 		return scg_sircdiv_get_rate(clk);
562552a848eSStefano Babic 
563552a848eSStefano Babic 	case SCG_FIRC_DIV1_CLK:
564552a848eSStefano Babic 	case SCG_FIRC_DIV2_CLK:
565552a848eSStefano Babic 	case SCG_FIRC_DIV3_CLK:
566552a848eSStefano Babic 		return scg_fircdiv_get_rate(clk);
567552a848eSStefano Babic 
568552a848eSStefano Babic 	case SCG_SOSC_DIV1_CLK:
569552a848eSStefano Babic 	case SCG_SOSC_DIV2_CLK:
570552a848eSStefano Babic 	case SCG_SOSC_DIV3_CLK:
571552a848eSStefano Babic 		return scg_soscdiv_get_rate(clk);
572552a848eSStefano Babic 
573552a848eSStefano Babic 	case SCG_CORE_CLK:
574552a848eSStefano Babic 	case SCG_BUS_CLK:
575552a848eSStefano Babic 		return scg_sys_get_rate(clk);
576552a848eSStefano Babic 
577552a848eSStefano Babic 	case SCG_SPLL_PFD0_CLK:
578552a848eSStefano Babic 	case SCG_SPLL_PFD1_CLK:
579552a848eSStefano Babic 	case SCG_SPLL_PFD2_CLK:
580552a848eSStefano Babic 	case SCG_SPLL_PFD3_CLK:
581552a848eSStefano Babic 		return scg_spll_pfd_get_rate(clk);
582552a848eSStefano Babic 
583552a848eSStefano Babic 	case SCG_APLL_PFD0_CLK:
584552a848eSStefano Babic 	case SCG_APLL_PFD1_CLK:
585552a848eSStefano Babic 	case SCG_APLL_PFD2_CLK:
586552a848eSStefano Babic 	case SCG_APLL_PFD3_CLK:
587552a848eSStefano Babic 		return scg_apll_pfd_get_rate(clk);
588552a848eSStefano Babic 
589552a848eSStefano Babic 	case SCG_DDR_CLK:
590552a848eSStefano Babic 		return scg_ddr_get_rate();
591552a848eSStefano Babic 
592552a848eSStefano Babic 	case SCG_NIC0_CLK:
593552a848eSStefano Babic 	case SCG_GPU_CLK:
594552a848eSStefano Babic 	case SCG_NIC1_CLK:
595552a848eSStefano Babic 	case SCG_NIC1_BUS_CLK:
596552a848eSStefano Babic 	case SCG_NIC1_EXT_CLK:
597552a848eSStefano Babic 		return scg_nic_get_rate(clk);
598552a848eSStefano Babic 
599552a848eSStefano Babic 	case USB_PLL_OUT:
600552a848eSStefano Babic 		return decode_pll(PLL_USB);
601552a848eSStefano Babic 
602552a848eSStefano Babic 	case MIPI_PLL_OUT:
603552a848eSStefano Babic 		return decode_pll(PLL_MIPI);
604552a848eSStefano Babic 
605552a848eSStefano Babic 	case SCG_SOSC_CLK:
606552a848eSStefano Babic 	case SCG_FIRC_CLK:
607552a848eSStefano Babic 	case SCG_SIRC_CLK:
608552a848eSStefano Babic 	case SCG_ROSC_CLK:
609552a848eSStefano Babic 		return scg_src_get_rate(clk);
610552a848eSStefano Babic 	default:
611552a848eSStefano Babic 		return 0;
612552a848eSStefano Babic 	}
613552a848eSStefano Babic }
614552a848eSStefano Babic 
scg_enable_pll_pfd(enum scg_clk clk,u32 frac)615552a848eSStefano Babic int scg_enable_pll_pfd(enum scg_clk clk, u32 frac)
616552a848eSStefano Babic {
617552a848eSStefano Babic 	u32 reg;
618552a848eSStefano Babic 	u32 shift, mask, gate, valid;
619552a848eSStefano Babic 	u32 addr;
620552a848eSStefano Babic 
621552a848eSStefano Babic 	if (frac < 12 || frac > 35)
622552a848eSStefano Babic 		return -EINVAL;
623552a848eSStefano Babic 
624552a848eSStefano Babic 	switch (clk) {
625552a848eSStefano Babic 	case SCG_SPLL_PFD0_CLK:
626552a848eSStefano Babic 	case SCG_APLL_PFD0_CLK:
627552a848eSStefano Babic 		gate = SCG_PLL_PFD0_GATE_MASK;
628552a848eSStefano Babic 		valid = SCG_PLL_PFD0_VALID_MASK;
629552a848eSStefano Babic 		mask = SCG_PLL_PFD0_FRAC_MASK;
630552a848eSStefano Babic 		shift = SCG_PLL_PFD0_FRAC_SHIFT;
631552a848eSStefano Babic 
632552a848eSStefano Babic 		if (clk == SCG_SPLL_PFD0_CLK)
633552a848eSStefano Babic 			addr = (u32)(&scg1_regs->spllpfd);
634552a848eSStefano Babic 		else
635552a848eSStefano Babic 			addr = (u32)(&scg1_regs->apllpfd);
636552a848eSStefano Babic 		break;
637552a848eSStefano Babic 	case SCG_SPLL_PFD1_CLK:
638552a848eSStefano Babic 	case SCG_APLL_PFD1_CLK:
639552a848eSStefano Babic 		gate = SCG_PLL_PFD1_GATE_MASK;
640552a848eSStefano Babic 		valid = SCG_PLL_PFD1_VALID_MASK;
641552a848eSStefano Babic 		mask = SCG_PLL_PFD1_FRAC_MASK;
642552a848eSStefano Babic 		shift = SCG_PLL_PFD1_FRAC_SHIFT;
643552a848eSStefano Babic 
644552a848eSStefano Babic 		if (clk == SCG_SPLL_PFD1_CLK)
645552a848eSStefano Babic 			addr = (u32)(&scg1_regs->spllpfd);
646552a848eSStefano Babic 		else
647552a848eSStefano Babic 			addr = (u32)(&scg1_regs->apllpfd);
648552a848eSStefano Babic 		break;
649552a848eSStefano Babic 	case SCG_SPLL_PFD2_CLK:
650552a848eSStefano Babic 	case SCG_APLL_PFD2_CLK:
651552a848eSStefano Babic 		gate = SCG_PLL_PFD2_GATE_MASK;
652552a848eSStefano Babic 		valid = SCG_PLL_PFD2_VALID_MASK;
653552a848eSStefano Babic 		mask = SCG_PLL_PFD2_FRAC_MASK;
654552a848eSStefano Babic 		shift = SCG_PLL_PFD2_FRAC_SHIFT;
655552a848eSStefano Babic 
656552a848eSStefano Babic 		if (clk == SCG_SPLL_PFD2_CLK)
657552a848eSStefano Babic 			addr = (u32)(&scg1_regs->spllpfd);
658552a848eSStefano Babic 		else
659552a848eSStefano Babic 			addr = (u32)(&scg1_regs->apllpfd);
660552a848eSStefano Babic 		break;
661552a848eSStefano Babic 	case SCG_SPLL_PFD3_CLK:
662552a848eSStefano Babic 	case SCG_APLL_PFD3_CLK:
663552a848eSStefano Babic 		gate = SCG_PLL_PFD3_GATE_MASK;
664552a848eSStefano Babic 		valid = SCG_PLL_PFD3_VALID_MASK;
665552a848eSStefano Babic 		mask = SCG_PLL_PFD3_FRAC_MASK;
666552a848eSStefano Babic 		shift = SCG_PLL_PFD3_FRAC_SHIFT;
667552a848eSStefano Babic 
668552a848eSStefano Babic 		if (clk == SCG_SPLL_PFD3_CLK)
669552a848eSStefano Babic 			addr = (u32)(&scg1_regs->spllpfd);
670552a848eSStefano Babic 		else
671552a848eSStefano Babic 			addr = (u32)(&scg1_regs->apllpfd);
672552a848eSStefano Babic 		break;
673552a848eSStefano Babic 	default:
674552a848eSStefano Babic 		return -EINVAL;
675552a848eSStefano Babic 	}
676552a848eSStefano Babic 
677552a848eSStefano Babic 	/* Gate the PFD */
678552a848eSStefano Babic 	reg = readl(addr);
679552a848eSStefano Babic 	reg |= gate;
680552a848eSStefano Babic 	writel(reg, addr);
681552a848eSStefano Babic 
682552a848eSStefano Babic 	/* Write Frac divider */
683552a848eSStefano Babic 	reg &= ~mask;
684552a848eSStefano Babic 	reg |= (frac << shift) & mask;
685552a848eSStefano Babic 	writel(reg, addr);
686552a848eSStefano Babic 
687552a848eSStefano Babic 	/*
688552a848eSStefano Babic 	 * Un-gate the PFD
689552a848eSStefano Babic 	 * (Need un-gate before checking valid, not align with RM)
690552a848eSStefano Babic 	 */
691552a848eSStefano Babic 	reg &= ~gate;
692552a848eSStefano Babic 	writel(reg, addr);
693552a848eSStefano Babic 
694552a848eSStefano Babic 	/* Wait for PFD clock being valid */
695552a848eSStefano Babic 	do {
696552a848eSStefano Babic 		reg = readl(addr);
697552a848eSStefano Babic 	} while (!(reg & valid));
698552a848eSStefano Babic 
699552a848eSStefano Babic 	return 0;
700552a848eSStefano Babic }
701552a848eSStefano Babic 
702552a848eSStefano Babic #define SIM_MISC_CTRL0_USB_PLL_EN_MASK (0x1 << 2)
scg_enable_usb_pll(bool usb_control)703552a848eSStefano Babic int scg_enable_usb_pll(bool usb_control)
704552a848eSStefano Babic {
705552a848eSStefano Babic 	u32 sosc_rate;
706552a848eSStefano Babic 	s32 timeout = 1000000;
707552a848eSStefano Babic 	u32 reg;
708552a848eSStefano Babic 
709552a848eSStefano Babic 	struct usbphy_regs *usbphy =
710552a848eSStefano Babic 		(struct usbphy_regs *)USBPHY_RBASE;
711552a848eSStefano Babic 
712552a848eSStefano Babic 	sosc_rate = scg_src_get_rate(SCG_SOSC_CLK);
713552a848eSStefano Babic 	if (!sosc_rate)
714552a848eSStefano Babic 		return -EPERM;
715552a848eSStefano Babic 
716552a848eSStefano Babic 	reg = readl(SIM0_RBASE + 0x3C);
717552a848eSStefano Babic 	if (usb_control)
718552a848eSStefano Babic 		reg &= ~SIM_MISC_CTRL0_USB_PLL_EN_MASK;
719552a848eSStefano Babic 	else
720552a848eSStefano Babic 		reg |= SIM_MISC_CTRL0_USB_PLL_EN_MASK;
721552a848eSStefano Babic 	writel(reg, SIM0_RBASE + 0x3C);
722552a848eSStefano Babic 
723552a848eSStefano Babic 	if (!(readl(&usbphy->usb1_pll_480_ctrl) & PLL_USB_LOCK_MASK)) {
724552a848eSStefano Babic 		writel(0x1c00000, &usbphy->usb1_pll_480_ctrl_clr);
725552a848eSStefano Babic 
726552a848eSStefano Babic 		switch (sosc_rate) {
727552a848eSStefano Babic 		case 24000000:
728552a848eSStefano Babic 			writel(0xc00000, &usbphy->usb1_pll_480_ctrl_set);
729552a848eSStefano Babic 			break;
730552a848eSStefano Babic 
731552a848eSStefano Babic 		case 30000000:
732552a848eSStefano Babic 			writel(0x800000, &usbphy->usb1_pll_480_ctrl_set);
733552a848eSStefano Babic 			break;
734552a848eSStefano Babic 
735552a848eSStefano Babic 		case 19200000:
736552a848eSStefano Babic 			writel(0x1400000, &usbphy->usb1_pll_480_ctrl_set);
737552a848eSStefano Babic 			break;
738552a848eSStefano Babic 
739552a848eSStefano Babic 		default:
740552a848eSStefano Babic 			writel(0xc00000, &usbphy->usb1_pll_480_ctrl_set);
741552a848eSStefano Babic 			break;
742552a848eSStefano Babic 		}
743552a848eSStefano Babic 
744552a848eSStefano Babic 		/* Enable the regulator first */
745552a848eSStefano Babic 		writel(PLL_USB_REG_ENABLE_MASK,
746552a848eSStefano Babic 		       &usbphy->usb1_pll_480_ctrl_set);
747552a848eSStefano Babic 
748552a848eSStefano Babic 		/* Wait at least 15us */
749552a848eSStefano Babic 		udelay(15);
750552a848eSStefano Babic 
751552a848eSStefano Babic 		/* Enable the power */
752552a848eSStefano Babic 		writel(PLL_USB_PWR_MASK, &usbphy->usb1_pll_480_ctrl_set);
753552a848eSStefano Babic 
754552a848eSStefano Babic 		/* Wait lock */
755552a848eSStefano Babic 		while (timeout--) {
756552a848eSStefano Babic 			if (readl(&usbphy->usb1_pll_480_ctrl) &
757552a848eSStefano Babic 			    PLL_USB_LOCK_MASK)
758552a848eSStefano Babic 				break;
759552a848eSStefano Babic 		}
760552a848eSStefano Babic 
761552a848eSStefano Babic 		if (timeout <= 0) {
762552a848eSStefano Babic 			/* If timeout, we power down the pll */
763552a848eSStefano Babic 			writel(PLL_USB_PWR_MASK,
764552a848eSStefano Babic 			       &usbphy->usb1_pll_480_ctrl_clr);
765552a848eSStefano Babic 			return -ETIME;
766552a848eSStefano Babic 		}
767552a848eSStefano Babic 	}
768552a848eSStefano Babic 
769552a848eSStefano Babic 	/* Clear the bypass */
770552a848eSStefano Babic 	writel(PLL_USB_BYPASS_MASK, &usbphy->usb1_pll_480_ctrl_clr);
771552a848eSStefano Babic 
772552a848eSStefano Babic 	/* Enable the PLL clock out to USB */
773552a848eSStefano Babic 	writel((PLL_USB_EN_USB_CLKS_MASK | PLL_USB_ENABLE_MASK),
774552a848eSStefano Babic 	       &usbphy->usb1_pll_480_ctrl_set);
775552a848eSStefano Babic 
776552a848eSStefano Babic 	if (!usb_control) {
777552a848eSStefano Babic 		while (timeout--) {
778552a848eSStefano Babic 			if (readl(&scg1_regs->upllcsr) &
779552a848eSStefano Babic 			    SCG_UPLL_CSR_UPLLVLD_MASK)
780552a848eSStefano Babic 				break;
781552a848eSStefano Babic 		}
782552a848eSStefano Babic 
783552a848eSStefano Babic 		if (timeout <= 0) {
784552a848eSStefano Babic 			reg = readl(SIM0_RBASE + 0x3C);
785552a848eSStefano Babic 			reg &= ~SIM_MISC_CTRL0_USB_PLL_EN_MASK;
786552a848eSStefano Babic 			writel(reg, SIM0_RBASE + 0x3C);
787552a848eSStefano Babic 			return -ETIME;
788552a848eSStefano Babic 		}
789552a848eSStefano Babic 	}
790552a848eSStefano Babic 
791552a848eSStefano Babic 	return 0;
792552a848eSStefano Babic }
793552a848eSStefano Babic 
794552a848eSStefano Babic 
795552a848eSStefano Babic /* A7 domain system clock source is SPLL */
796552a848eSStefano Babic #define SCG1_RCCR_SCS_NUM	((SCG_SCS_SYS_PLL) << SCG_CCR_SCS_SHIFT)
797552a848eSStefano Babic 
798552a848eSStefano Babic /* A7 Core clck = SPLL PFD0 / 1 = 500MHz / 1 = 500MHz */
799552a848eSStefano Babic #define SCG1_RCCR_DIVCORE_NUM	((0x0)  << SCG_CCR_DIVCORE_SHIFT)
800552a848eSStefano Babic #define SCG1_RCCR_CFG_MASK	(SCG_CCR_SCS_MASK | SCG_CCR_DIVBUS_MASK)
801552a848eSStefano Babic 
802552a848eSStefano Babic /* A7 Plat clck = A7 Core Clock / 2 = 250MHz / 1 = 250MHz */
803552a848eSStefano Babic #define SCG1_RCCR_DIVBUS_NUM	((0x1)  << SCG_CCR_DIVBUS_SHIFT)
804552a848eSStefano Babic #define SCG1_RCCR_CFG_NUM	(SCG1_RCCR_SCS_NUM | SCG1_RCCR_DIVBUS_NUM)
805552a848eSStefano Babic 
scg_a7_rccr_init(void)806552a848eSStefano Babic void scg_a7_rccr_init(void)
807552a848eSStefano Babic {
808552a848eSStefano Babic 	u32 rccr_reg_val = 0;
809552a848eSStefano Babic 
810552a848eSStefano Babic 	rccr_reg_val = readl(&scg1_regs->rccr);
811552a848eSStefano Babic 
812552a848eSStefano Babic 	rccr_reg_val &= (~SCG1_RCCR_CFG_MASK);
813552a848eSStefano Babic 	rccr_reg_val |= (SCG1_RCCR_CFG_NUM);
814552a848eSStefano Babic 
815552a848eSStefano Babic 	writel(rccr_reg_val, &scg1_regs->rccr);
816552a848eSStefano Babic }
817552a848eSStefano Babic 
818552a848eSStefano Babic /* POSTDIV2 = 1 */
819552a848eSStefano Babic #define SCG1_SPLL_CFG_POSTDIV2_NUM	((0x0)  << SCG_PLL_CFG_POSTDIV2_SHIFT)
820552a848eSStefano Babic /* POSTDIV1 = 1 */
821552a848eSStefano Babic #define SCG1_SPLL_CFG_POSTDIV1_NUM	((0x0)  << SCG_PLL_CFG_POSTDIV1_SHIFT)
822552a848eSStefano Babic 
823552a848eSStefano Babic /* MULT = 22 */
824552a848eSStefano Babic #define SCG1_SPLL_CFG_MULT_NUM		((22)   << SCG_PLL_CFG_MULT_SHIFT)
825552a848eSStefano Babic 
826552a848eSStefano Babic /* PFD0 output clock selected */
827552a848eSStefano Babic #define SCG1_SPLL_CFG_PFDSEL_NUM	((0) << SCG_PLL_CFG_PFDSEL_SHIFT)
828552a848eSStefano Babic /* PREDIV = 1 */
829552a848eSStefano Babic #define SCG1_SPLL_CFG_PREDIV_NUM	((0x0)  << SCG_PLL_CFG_PREDIV_SHIFT)
830552a848eSStefano Babic /* SPLL output clocks (including PFD outputs) selected */
831552a848eSStefano Babic #define SCG1_SPLL_CFG_BYPASS_NUM	((0x0)  << SCG_PLL_CFG_BYPASS_SHIFT)
832552a848eSStefano Babic /* SPLL PFD output clock selected */
833552a848eSStefano Babic #define SCG1_SPLL_CFG_PLLSEL_NUM	((0x1)  << SCG_PLL_CFG_PLLSEL_SHIFT)
834552a848eSStefano Babic /* Clock source is System OSC */
835552a848eSStefano Babic #define SCG1_SPLL_CFG_CLKSRC_NUM	((0x0)  << SCG_PLL_CFG_CLKSRC_SHIFT)
836552a848eSStefano Babic #define SCG1_SPLL_CFG_NUM_24M_OSC	(SCG1_SPLL_CFG_POSTDIV2_NUM	| \
837552a848eSStefano Babic 					 SCG1_SPLL_CFG_POSTDIV1_NUM     | \
838552a848eSStefano Babic 					 (22 << SCG_PLL_CFG_MULT_SHIFT) | \
839552a848eSStefano Babic 					 SCG1_SPLL_CFG_PFDSEL_NUM       | \
840552a848eSStefano Babic 					 SCG1_SPLL_CFG_PREDIV_NUM       | \
841552a848eSStefano Babic 					 SCG1_SPLL_CFG_BYPASS_NUM       | \
842552a848eSStefano Babic 					 SCG1_SPLL_CFG_PLLSEL_NUM       | \
843552a848eSStefano Babic 					 SCG1_SPLL_CFG_CLKSRC_NUM)
844552a848eSStefano Babic /*413Mhz = A7 SPLL(528MHz) * 18/23 */
845552a848eSStefano Babic #define SCG1_SPLL_PFD0_FRAC_NUM		((23) << SCG_PLL_PFD0_FRAC_SHIFT)
846552a848eSStefano Babic 
scg_a7_spll_init(void)847552a848eSStefano Babic void scg_a7_spll_init(void)
848552a848eSStefano Babic {
849552a848eSStefano Babic 	u32 val = 0;
850552a848eSStefano Babic 
851552a848eSStefano Babic 	/* Disable A7 System PLL */
852552a848eSStefano Babic 	val = readl(&scg1_regs->spllcsr);
853552a848eSStefano Babic 	val &= ~SCG_SPLL_CSR_SPLLEN_MASK;
854552a848eSStefano Babic 	writel(val, &scg1_regs->spllcsr);
855552a848eSStefano Babic 
856552a848eSStefano Babic 	/*
857552a848eSStefano Babic 	 * Per block guide,
858552a848eSStefano Babic 	 * "When changing PFD values, it is recommneded PFDx clock
859552a848eSStefano Babic 	 * gets gated first by writing a value of 1 to PFDx_CLKGATE register,
860552a848eSStefano Babic 	 * then program the new PFD value, then poll the PFDx_VALID
861552a848eSStefano Babic 	 * flag to set before writing a value of 0 to PFDx_CLKGATE
862552a848eSStefano Babic 	 * to ungate the PFDx clock and allow PFDx clock to run"
863552a848eSStefano Babic 	 */
864552a848eSStefano Babic 
865552a848eSStefano Babic 	/* Gate off A7 SPLL PFD0 ~ PDF4  */
866552a848eSStefano Babic 	val = readl(&scg1_regs->spllpfd);
867552a848eSStefano Babic 	val |= (SCG_PLL_PFD3_GATE_MASK |
868552a848eSStefano Babic 			SCG_PLL_PFD2_GATE_MASK |
869552a848eSStefano Babic 			SCG_PLL_PFD1_GATE_MASK |
870552a848eSStefano Babic 			SCG_PLL_PFD0_GATE_MASK);
871552a848eSStefano Babic 	writel(val, &scg1_regs->spllpfd);
872552a848eSStefano Babic 
873552a848eSStefano Babic 	/* ================ A7 SPLL Configuration Start ============== */
874552a848eSStefano Babic 
875552a848eSStefano Babic 	/* Configure A7 System PLL */
876552a848eSStefano Babic 	writel(SCG1_SPLL_CFG_NUM_24M_OSC, &scg1_regs->spllcfg);
877552a848eSStefano Babic 
878552a848eSStefano Babic 	/* Enable A7 System PLL */
879552a848eSStefano Babic 	val = readl(&scg1_regs->spllcsr);
880552a848eSStefano Babic 	val |= SCG_SPLL_CSR_SPLLEN_MASK;
881552a848eSStefano Babic 	writel(val, &scg1_regs->spllcsr);
882552a848eSStefano Babic 
883552a848eSStefano Babic 	/* Wait for A7 SPLL clock ready */
884552a848eSStefano Babic 	while (!(readl(&scg1_regs->spllcsr) & SCG_SPLL_CSR_SPLLVLD_MASK))
885552a848eSStefano Babic 		;
886552a848eSStefano Babic 
887552a848eSStefano Babic 	/* Configure A7 SPLL PFD0 */
888552a848eSStefano Babic 	val = readl(&scg1_regs->spllpfd);
889552a848eSStefano Babic 	val &= ~SCG_PLL_PFD0_FRAC_MASK;
890552a848eSStefano Babic 	val |= SCG1_SPLL_PFD0_FRAC_NUM;
891552a848eSStefano Babic 	writel(val, &scg1_regs->spllpfd);
892552a848eSStefano Babic 
893552a848eSStefano Babic 	/* Un-gate A7 SPLL PFD0 */
894552a848eSStefano Babic 	val = readl(&scg1_regs->spllpfd);
895552a848eSStefano Babic 	val &= ~SCG_PLL_PFD0_GATE_MASK;
896552a848eSStefano Babic 	writel(val, &scg1_regs->spllpfd);
897552a848eSStefano Babic 
898552a848eSStefano Babic 	/* Wait for A7 SPLL PFD0 clock being valid */
899552a848eSStefano Babic 	while (!(readl(&scg1_regs->spllpfd) & SCG_PLL_PFD0_VALID_MASK))
900552a848eSStefano Babic 		;
901552a848eSStefano Babic 
902552a848eSStefano Babic 	/* ================ A7 SPLL Configuration End ============== */
903552a848eSStefano Babic }
904552a848eSStefano Babic 
905552a848eSStefano Babic /* DDR clock source is APLL PFD0 (396MHz) */
906552a848eSStefano Babic #define SCG1_DDRCCR_DDRCS_NUM		((0x0) << SCG_DDRCCR_DDRCS_SHIFT)
907552a848eSStefano Babic /* DDR clock = APLL PFD0 / 1 = 396MHz / 1 = 396MHz */
908552a848eSStefano Babic #define SCG1_DDRCCR_DDRDIV_NUM		((0x1) << SCG_DDRCCR_DDRDIV_SHIFT)
909552a848eSStefano Babic /* DDR clock = APLL PFD0 / 2 = 396MHz / 2 = 198MHz */
910552a848eSStefano Babic #define SCG1_DDRCCR_DDRDIV_LF_NUM	((0x2) << SCG_DDRCCR_DDRDIV_SHIFT)
911552a848eSStefano Babic #define SCG1_DDRCCR_CFG_NUM		(SCG1_DDRCCR_DDRCS_NUM  | \
912552a848eSStefano Babic 					 SCG1_DDRCCR_DDRDIV_NUM)
913552a848eSStefano Babic #define SCG1_DDRCCR_CFG_LF_NUM		(SCG1_DDRCCR_DDRCS_NUM  | \
914552a848eSStefano Babic 					 SCG1_DDRCCR_DDRDIV_LF_NUM)
scg_a7_ddrclk_init(void)915552a848eSStefano Babic void scg_a7_ddrclk_init(void)
916552a848eSStefano Babic {
917552a848eSStefano Babic 	writel(SCG1_DDRCCR_CFG_NUM, &scg1_regs->ddrccr);
918552a848eSStefano Babic }
919552a848eSStefano Babic 
920552a848eSStefano Babic /* SCG1(A7) APLLCFG configurations */
921552a848eSStefano Babic /* divide by 1 <<28 */
922552a848eSStefano Babic #define SCG1_APLL_CFG_POSTDIV2_NUM      ((0x0) << SCG_PLL_CFG_POSTDIV2_SHIFT)
923552a848eSStefano Babic /* divide by 1 <<24 */
924552a848eSStefano Babic #define SCG1_APLL_CFG_POSTDIV1_NUM      ((0x0) << SCG_PLL_CFG_POSTDIV1_SHIFT)
925552a848eSStefano Babic /* MULT is 22  <<16 */
926552a848eSStefano Babic #define SCG1_APLL_CFG_MULT_NUM          ((22)  << SCG_PLL_CFG_MULT_SHIFT)
927552a848eSStefano Babic /* PFD0 output clock selected  <<14 */
928552a848eSStefano Babic #define SCG1_APLL_CFG_PFDSEL_NUM        ((0) << SCG_PLL_CFG_PFDSEL_SHIFT)
929552a848eSStefano Babic /* PREDIV = 1	<<8 */
930552a848eSStefano Babic #define SCG1_APLL_CFG_PREDIV_NUM        ((0x0) << SCG_PLL_CFG_PREDIV_SHIFT)
931552a848eSStefano Babic /* APLL output clocks (including PFD outputs) selected	<<2 */
932552a848eSStefano Babic #define SCG1_APLL_CFG_BYPASS_NUM        ((0x0) << SCG_PLL_CFG_BYPASS_SHIFT)
933552a848eSStefano Babic /* APLL PFD output clock selected <<1 */
934552a848eSStefano Babic #define SCG1_APLL_CFG_PLLSEL_NUM        ((0x0) << SCG_PLL_CFG_PLLSEL_SHIFT)
935552a848eSStefano Babic /* Clock source is System OSC <<0 */
936552a848eSStefano Babic #define SCG1_APLL_CFG_CLKSRC_NUM        ((0x0) << SCG_PLL_CFG_CLKSRC_SHIFT)
937552a848eSStefano Babic 
938552a848eSStefano Babic /*
939552a848eSStefano Babic  * A7 APLL = 24MHz / 1 * 22 / 1 / 1 = 528MHz,
940552a848eSStefano Babic  * system PLL is sourced from APLL,
941552a848eSStefano Babic  * APLL clock source is system OSC (24MHz)
942552a848eSStefano Babic  */
943552a848eSStefano Babic #define SCG1_APLL_CFG_NUM_24M_OSC (SCG1_APLL_CFG_POSTDIV2_NUM     |   \
944552a848eSStefano Babic 				   SCG1_APLL_CFG_POSTDIV1_NUM     |   \
945552a848eSStefano Babic 				   (22 << SCG_PLL_CFG_MULT_SHIFT) |   \
946552a848eSStefano Babic 				   SCG1_APLL_CFG_PFDSEL_NUM       |   \
947552a848eSStefano Babic 				   SCG1_APLL_CFG_PREDIV_NUM       |   \
948552a848eSStefano Babic 				   SCG1_APLL_CFG_BYPASS_NUM       |   \
949552a848eSStefano Babic 				   SCG1_APLL_CFG_PLLSEL_NUM       |   \
950552a848eSStefano Babic 				   SCG1_APLL_CFG_CLKSRC_NUM)
951552a848eSStefano Babic 
952552a848eSStefano Babic /* PFD0 Freq = A7 APLL(528MHz) * 18 / 27 = 352MHz */
953552a848eSStefano Babic #define SCG1_APLL_PFD0_FRAC_NUM (27)
954552a848eSStefano Babic 
955552a848eSStefano Babic 
scg_a7_apll_init(void)956552a848eSStefano Babic void scg_a7_apll_init(void)
957552a848eSStefano Babic {
958552a848eSStefano Babic 	u32 val = 0;
959552a848eSStefano Babic 
960552a848eSStefano Babic 	/* Disable A7 Auxiliary PLL */
961552a848eSStefano Babic 	val = readl(&scg1_regs->apllcsr);
962552a848eSStefano Babic 	val &= ~SCG_APLL_CSR_APLLEN_MASK;
963552a848eSStefano Babic 	writel(val, &scg1_regs->apllcsr);
964552a848eSStefano Babic 
965552a848eSStefano Babic 	/* Gate off A7 APLL PFD0 ~ PDF4  */
966552a848eSStefano Babic 	val = readl(&scg1_regs->apllpfd);
967552a848eSStefano Babic 	val |= 0x80808080;
968552a848eSStefano Babic 	writel(val, &scg1_regs->apllpfd);
969552a848eSStefano Babic 
970552a848eSStefano Babic 	/* ================ A7 APLL Configuration Start ============== */
971552a848eSStefano Babic 	/* Configure A7 Auxiliary PLL */
972552a848eSStefano Babic 	writel(SCG1_APLL_CFG_NUM_24M_OSC, &scg1_regs->apllcfg);
973552a848eSStefano Babic 
974552a848eSStefano Babic 	/* Enable A7 Auxiliary PLL */
975552a848eSStefano Babic 	val = readl(&scg1_regs->apllcsr);
976552a848eSStefano Babic 	val |= SCG_APLL_CSR_APLLEN_MASK;
977552a848eSStefano Babic 	writel(val, &scg1_regs->apllcsr);
978552a848eSStefano Babic 
979552a848eSStefano Babic 	/* Wait for A7 APLL clock ready */
980552a848eSStefano Babic 	while (!(readl(&scg1_regs->apllcsr) & SCG_APLL_CSR_APLLVLD_MASK))
981552a848eSStefano Babic 		;
982552a848eSStefano Babic 
983552a848eSStefano Babic 	/* Configure A7 APLL PFD0 */
984552a848eSStefano Babic 	val = readl(&scg1_regs->apllpfd);
985552a848eSStefano Babic 	val &= ~SCG_PLL_PFD0_FRAC_MASK;
986552a848eSStefano Babic 	val |= SCG1_APLL_PFD0_FRAC_NUM;
987552a848eSStefano Babic 	writel(val, &scg1_regs->apllpfd);
988552a848eSStefano Babic 
989552a848eSStefano Babic 	/* Un-gate A7 APLL PFD0 */
990552a848eSStefano Babic 	val = readl(&scg1_regs->apllpfd);
991552a848eSStefano Babic 	val &= ~SCG_PLL_PFD0_GATE_MASK;
992552a848eSStefano Babic 	writel(val, &scg1_regs->apllpfd);
993552a848eSStefano Babic 
994552a848eSStefano Babic 	/* Wait for A7 APLL PFD0 clock being valid */
995552a848eSStefano Babic 	while (!(readl(&scg1_regs->apllpfd) & SCG_PLL_PFD0_VALID_MASK))
996552a848eSStefano Babic 		;
997552a848eSStefano Babic }
998552a848eSStefano Babic 
999552a848eSStefano Babic /* SCG1(A7) FIRC DIV configurations */
1000552a848eSStefano Babic /* Disable FIRC DIV3 */
1001552a848eSStefano Babic #define SCG1_FIRCDIV_DIV3_NUM           ((0x0) << SCG_FIRCDIV_DIV3_SHIFT)
1002552a848eSStefano Babic /* FIRC DIV2 = 48MHz / 1 = 48MHz */
1003552a848eSStefano Babic #define SCG1_FIRCDIV_DIV2_NUM           ((0x1) << SCG_FIRCDIV_DIV2_SHIFT)
1004552a848eSStefano Babic /* Disable FIRC DIV1 */
1005552a848eSStefano Babic #define SCG1_FIRCDIV_DIV1_NUM           ((0x0) << SCG_FIRCDIV_DIV1_SHIFT)
1006552a848eSStefano Babic 
scg_a7_firc_init(void)1007552a848eSStefano Babic void scg_a7_firc_init(void)
1008552a848eSStefano Babic {
1009552a848eSStefano Babic 	/* Wait for FIRC clock ready */
1010552a848eSStefano Babic 	while (!(readl(&scg1_regs->firccsr) & SCG_FIRC_CSR_FIRCVLD_MASK))
1011552a848eSStefano Babic 		;
1012552a848eSStefano Babic 
1013552a848eSStefano Babic 	/* Configure A7 FIRC DIV1 ~ DIV3 */
1014552a848eSStefano Babic 	writel((SCG1_FIRCDIV_DIV3_NUM |
1015552a848eSStefano Babic 			SCG1_FIRCDIV_DIV2_NUM |
1016552a848eSStefano Babic 			SCG1_FIRCDIV_DIV1_NUM), &scg1_regs->fircdiv);
1017552a848eSStefano Babic }
1018552a848eSStefano Babic 
1019552a848eSStefano Babic /* SCG1(A7) NICCCR configurations */
1020552a848eSStefano Babic /* NIC clock source is DDR clock (396/198MHz) */
1021552a848eSStefano Babic #define SCG1_NICCCR_NICCS_NUM		((0x1) << SCG_NICCCR_NICCS_SHIFT)
1022552a848eSStefano Babic 
1023552a848eSStefano Babic /* NIC0 clock = DDR Clock / 2 = 396MHz / 2 = 198MHz */
1024552a848eSStefano Babic #define SCG1_NICCCR_NIC0_DIV_NUM	((0x1) << SCG_NICCCR_NIC0_DIV_SHIFT)
1025552a848eSStefano Babic /* NIC0 clock = DDR Clock / 1 = 198MHz / 1 = 198MHz */
1026552a848eSStefano Babic #define SCG1_NICCCR_NIC0_DIV_LF_NUM	((0x0) << SCG_NICCCR_NIC0_DIV_SHIFT)
1027552a848eSStefano Babic /* NIC1 clock = NIC0 Clock / 1 = 198MHz / 2 = 198MHz */
1028552a848eSStefano Babic #define SCG1_NICCCR_NIC1_DIV_NUM	((0x0) << SCG_NICCCR_NIC1_DIV_SHIFT)
1029552a848eSStefano Babic /* NIC1 bus clock = NIC1 Clock / 3 = 198MHz / 3 = 66MHz */
1030552a848eSStefano Babic #define SCG1_NICCCR_NIC1_DIVBUS_NUM	((0x2) << SCG_NICCCR_NIC1_DIVBUS_SHIFT)
1031552a848eSStefano Babic #define SCG1_NICCCR_CFG_NUM		(SCG1_NICCCR_NICCS_NUM      | \
1032552a848eSStefano Babic 					 SCG1_NICCCR_NIC0_DIV_NUM   | \
1033552a848eSStefano Babic 					 SCG1_NICCCR_NIC1_DIV_NUM   | \
1034552a848eSStefano Babic 					 SCG1_NICCCR_NIC1_DIVBUS_NUM)
1035552a848eSStefano Babic 
scg_a7_nicclk_init(void)1036552a848eSStefano Babic void scg_a7_nicclk_init(void)
1037552a848eSStefano Babic {
1038552a848eSStefano Babic 	writel(SCG1_NICCCR_CFG_NUM, &scg1_regs->nicccr);
1039552a848eSStefano Babic }
1040552a848eSStefano Babic 
1041552a848eSStefano Babic /* SCG1(A7) FIRC DIV configurations */
1042552a848eSStefano Babic /* Enable FIRC DIV3 */
1043552a848eSStefano Babic #define SCG1_SOSCDIV_DIV3_NUM		((0x1) << SCG_SOSCDIV_DIV3_SHIFT)
1044552a848eSStefano Babic /* FIRC DIV2 = 48MHz / 1 = 48MHz */
1045552a848eSStefano Babic #define SCG1_SOSCDIV_DIV2_NUM		((0x1) << SCG_SOSCDIV_DIV2_SHIFT)
1046552a848eSStefano Babic /* Enable FIRC DIV1 */
1047552a848eSStefano Babic #define SCG1_SOSCDIV_DIV1_NUM		((0x1) << SCG_SOSCDIV_DIV1_SHIFT)
1048552a848eSStefano Babic 
scg_a7_soscdiv_init(void)1049552a848eSStefano Babic void scg_a7_soscdiv_init(void)
1050552a848eSStefano Babic {
1051552a848eSStefano Babic 	/* Wait for FIRC clock ready */
1052552a848eSStefano Babic 	while (!(readl(&scg1_regs->sosccsr) & SCG_SOSC_CSR_SOSCVLD_MASK))
1053552a848eSStefano Babic 		;
1054552a848eSStefano Babic 
1055552a848eSStefano Babic 	/* Configure A7 FIRC DIV1 ~ DIV3 */
1056552a848eSStefano Babic 	writel((SCG1_SOSCDIV_DIV3_NUM | SCG1_SOSCDIV_DIV2_NUM |
1057552a848eSStefano Babic 	       SCG1_SOSCDIV_DIV1_NUM), &scg1_regs->soscdiv);
1058552a848eSStefano Babic }
1059552a848eSStefano Babic 
scg_a7_sys_clk_sel(enum scg_sys_src clk)1060552a848eSStefano Babic void scg_a7_sys_clk_sel(enum scg_sys_src clk)
1061552a848eSStefano Babic {
1062552a848eSStefano Babic 	u32 rccr_reg_val = 0;
1063552a848eSStefano Babic 
1064552a848eSStefano Babic 	clk_debug("%s: system clock selected as %s\n", "[SCG]",
1065552a848eSStefano Babic 		  clk == SCG_SCS_SYS_OSC ? "SYS_OSC" :
1066552a848eSStefano Babic 		  clk == SCG_SCS_SLOW_IRC  ? "SLOW_IRC" :
1067552a848eSStefano Babic 		  clk == SCG_SCS_FAST_IRC  ? "FAST_IRC" :
1068552a848eSStefano Babic 		  clk == SCG_SCS_RTC_OSC   ? "RTC_OSC" :
1069552a848eSStefano Babic 		  clk == SCG_SCS_AUX_PLL   ? "AUX_PLL" :
1070552a848eSStefano Babic 		  clk == SCG_SCS_SYS_PLL   ? "SYS_PLL" :
1071552a848eSStefano Babic 		  clk == SCG_SCS_USBPHY_PLL ? "USBPHY_PLL" :
1072552a848eSStefano Babic 		  "Invalid source"
1073552a848eSStefano Babic 	);
1074552a848eSStefano Babic 
1075552a848eSStefano Babic 	rccr_reg_val = readl(&scg1_regs->rccr);
1076552a848eSStefano Babic 	rccr_reg_val &= ~SCG_CCR_SCS_MASK;
1077552a848eSStefano Babic 	rccr_reg_val |= (clk << SCG_CCR_SCS_SHIFT);
1078552a848eSStefano Babic 	writel(rccr_reg_val, &scg1_regs->rccr);
1079552a848eSStefano Babic }
1080552a848eSStefano Babic 
scg_a7_info(void)1081552a848eSStefano Babic void scg_a7_info(void)
1082552a848eSStefano Babic {
1083552a848eSStefano Babic 	debug("SCG Version: 0x%x\n", readl(&scg1_regs->verid));
1084552a848eSStefano Babic 	debug("SCG Parameter: 0x%x\n", readl(&scg1_regs->param));
1085552a848eSStefano Babic 	debug("SCG RCCR Value: 0x%x\n", readl(&scg1_regs->rccr));
1086552a848eSStefano Babic 	debug("SCG Clock Status: 0x%x\n", readl(&scg1_regs->csr));
1087552a848eSStefano Babic }
1088