xref: /rk3399_rockchip-uboot/arch/arm/mach-s5pc1xx/clock.c (revision a71d99ac03c8d5d9622962344485b04aade27b67)
1*225f5eecSMinkyu Kang /*
2*225f5eecSMinkyu Kang  * Copyright (C) 2009 Samsung Electronics
3*225f5eecSMinkyu Kang  * Minkyu Kang <mk7.kang@samsung.com>
4*225f5eecSMinkyu Kang  * Heungjun Kim <riverful.kim@samsung.com>
5*225f5eecSMinkyu Kang  *
6*225f5eecSMinkyu Kang  * SPDX-License-Identifier:	GPL-2.0+
7*225f5eecSMinkyu Kang  */
8*225f5eecSMinkyu Kang 
9*225f5eecSMinkyu Kang #include <common.h>
10*225f5eecSMinkyu Kang #include <asm/io.h>
11*225f5eecSMinkyu Kang #include <asm/arch/clock.h>
12*225f5eecSMinkyu Kang #include <asm/arch/clk.h>
13*225f5eecSMinkyu Kang 
14*225f5eecSMinkyu Kang #define CLK_M	0
15*225f5eecSMinkyu Kang #define CLK_D	1
16*225f5eecSMinkyu Kang #define CLK_P	2
17*225f5eecSMinkyu Kang 
18*225f5eecSMinkyu Kang #ifndef CONFIG_SYS_CLK_FREQ_C100
19*225f5eecSMinkyu Kang #define CONFIG_SYS_CLK_FREQ_C100	12000000
20*225f5eecSMinkyu Kang #endif
21*225f5eecSMinkyu Kang #ifndef CONFIG_SYS_CLK_FREQ_C110
22*225f5eecSMinkyu Kang #define CONFIG_SYS_CLK_FREQ_C110	24000000
23*225f5eecSMinkyu Kang #endif
24*225f5eecSMinkyu Kang 
25*225f5eecSMinkyu Kang /* s5pc110: return pll clock frequency */
s5pc100_get_pll_clk(int pllreg)26*225f5eecSMinkyu Kang static unsigned long s5pc100_get_pll_clk(int pllreg)
27*225f5eecSMinkyu Kang {
28*225f5eecSMinkyu Kang 	struct s5pc100_clock *clk =
29*225f5eecSMinkyu Kang 		(struct s5pc100_clock *)samsung_get_base_clock();
30*225f5eecSMinkyu Kang 	unsigned long r, m, p, s, mask, fout;
31*225f5eecSMinkyu Kang 	unsigned int freq;
32*225f5eecSMinkyu Kang 
33*225f5eecSMinkyu Kang 	switch (pllreg) {
34*225f5eecSMinkyu Kang 	case APLL:
35*225f5eecSMinkyu Kang 		r = readl(&clk->apll_con);
36*225f5eecSMinkyu Kang 		break;
37*225f5eecSMinkyu Kang 	case MPLL:
38*225f5eecSMinkyu Kang 		r = readl(&clk->mpll_con);
39*225f5eecSMinkyu Kang 		break;
40*225f5eecSMinkyu Kang 	case EPLL:
41*225f5eecSMinkyu Kang 		r = readl(&clk->epll_con);
42*225f5eecSMinkyu Kang 		break;
43*225f5eecSMinkyu Kang 	case HPLL:
44*225f5eecSMinkyu Kang 		r = readl(&clk->hpll_con);
45*225f5eecSMinkyu Kang 		break;
46*225f5eecSMinkyu Kang 	default:
47*225f5eecSMinkyu Kang 		printf("Unsupported PLL (%d)\n", pllreg);
48*225f5eecSMinkyu Kang 		return 0;
49*225f5eecSMinkyu Kang 	}
50*225f5eecSMinkyu Kang 
51*225f5eecSMinkyu Kang 	/*
52*225f5eecSMinkyu Kang 	 * APLL_CON: MIDV [25:16]
53*225f5eecSMinkyu Kang 	 * MPLL_CON: MIDV [23:16]
54*225f5eecSMinkyu Kang 	 * EPLL_CON: MIDV [23:16]
55*225f5eecSMinkyu Kang 	 * HPLL_CON: MIDV [23:16]
56*225f5eecSMinkyu Kang 	 */
57*225f5eecSMinkyu Kang 	if (pllreg == APLL)
58*225f5eecSMinkyu Kang 		mask = 0x3ff;
59*225f5eecSMinkyu Kang 	else
60*225f5eecSMinkyu Kang 		mask = 0x0ff;
61*225f5eecSMinkyu Kang 
62*225f5eecSMinkyu Kang 	m = (r >> 16) & mask;
63*225f5eecSMinkyu Kang 
64*225f5eecSMinkyu Kang 	/* PDIV [13:8] */
65*225f5eecSMinkyu Kang 	p = (r >> 8) & 0x3f;
66*225f5eecSMinkyu Kang 	/* SDIV [2:0] */
67*225f5eecSMinkyu Kang 	s = r & 0x7;
68*225f5eecSMinkyu Kang 
69*225f5eecSMinkyu Kang 	/* FOUT = MDIV * FIN / (PDIV * 2^SDIV) */
70*225f5eecSMinkyu Kang 	freq = CONFIG_SYS_CLK_FREQ_C100;
71*225f5eecSMinkyu Kang 	fout = m * (freq / (p * (1 << s)));
72*225f5eecSMinkyu Kang 
73*225f5eecSMinkyu Kang 	return fout;
74*225f5eecSMinkyu Kang }
75*225f5eecSMinkyu Kang 
76*225f5eecSMinkyu Kang /* s5pc100: return pll clock frequency */
s5pc110_get_pll_clk(int pllreg)77*225f5eecSMinkyu Kang static unsigned long s5pc110_get_pll_clk(int pllreg)
78*225f5eecSMinkyu Kang {
79*225f5eecSMinkyu Kang 	struct s5pc110_clock *clk =
80*225f5eecSMinkyu Kang 		(struct s5pc110_clock *)samsung_get_base_clock();
81*225f5eecSMinkyu Kang 	unsigned long r, m, p, s, mask, fout;
82*225f5eecSMinkyu Kang 	unsigned int freq;
83*225f5eecSMinkyu Kang 
84*225f5eecSMinkyu Kang 	switch (pllreg) {
85*225f5eecSMinkyu Kang 	case APLL:
86*225f5eecSMinkyu Kang 		r = readl(&clk->apll_con);
87*225f5eecSMinkyu Kang 		break;
88*225f5eecSMinkyu Kang 	case MPLL:
89*225f5eecSMinkyu Kang 		r = readl(&clk->mpll_con);
90*225f5eecSMinkyu Kang 		break;
91*225f5eecSMinkyu Kang 	case EPLL:
92*225f5eecSMinkyu Kang 		r = readl(&clk->epll_con);
93*225f5eecSMinkyu Kang 		break;
94*225f5eecSMinkyu Kang 	case VPLL:
95*225f5eecSMinkyu Kang 		r = readl(&clk->vpll_con);
96*225f5eecSMinkyu Kang 		break;
97*225f5eecSMinkyu Kang 	default:
98*225f5eecSMinkyu Kang 		printf("Unsupported PLL (%d)\n", pllreg);
99*225f5eecSMinkyu Kang 		return 0;
100*225f5eecSMinkyu Kang 	}
101*225f5eecSMinkyu Kang 
102*225f5eecSMinkyu Kang 	/*
103*225f5eecSMinkyu Kang 	 * APLL_CON: MIDV [25:16]
104*225f5eecSMinkyu Kang 	 * MPLL_CON: MIDV [25:16]
105*225f5eecSMinkyu Kang 	 * EPLL_CON: MIDV [24:16]
106*225f5eecSMinkyu Kang 	 * VPLL_CON: MIDV [24:16]
107*225f5eecSMinkyu Kang 	 */
108*225f5eecSMinkyu Kang 	if (pllreg == APLL || pllreg == MPLL)
109*225f5eecSMinkyu Kang 		mask = 0x3ff;
110*225f5eecSMinkyu Kang 	else
111*225f5eecSMinkyu Kang 		mask = 0x1ff;
112*225f5eecSMinkyu Kang 
113*225f5eecSMinkyu Kang 	m = (r >> 16) & mask;
114*225f5eecSMinkyu Kang 
115*225f5eecSMinkyu Kang 	/* PDIV [13:8] */
116*225f5eecSMinkyu Kang 	p = (r >> 8) & 0x3f;
117*225f5eecSMinkyu Kang 	/* SDIV [2:0] */
118*225f5eecSMinkyu Kang 	s = r & 0x7;
119*225f5eecSMinkyu Kang 
120*225f5eecSMinkyu Kang 	freq = CONFIG_SYS_CLK_FREQ_C110;
121*225f5eecSMinkyu Kang 	if (pllreg == APLL) {
122*225f5eecSMinkyu Kang 		if (s < 1)
123*225f5eecSMinkyu Kang 			s = 1;
124*225f5eecSMinkyu Kang 		/* FOUT = MDIV * FIN / (PDIV * 2^(SDIV - 1)) */
125*225f5eecSMinkyu Kang 		fout = m * (freq / (p * (1 << (s - 1))));
126*225f5eecSMinkyu Kang 	} else
127*225f5eecSMinkyu Kang 		/* FOUT = MDIV * FIN / (PDIV * 2^SDIV) */
128*225f5eecSMinkyu Kang 		fout = m * (freq / (p * (1 << s)));
129*225f5eecSMinkyu Kang 
130*225f5eecSMinkyu Kang 	return fout;
131*225f5eecSMinkyu Kang }
132*225f5eecSMinkyu Kang 
133*225f5eecSMinkyu Kang /* s5pc110: return ARM clock frequency */
s5pc110_get_arm_clk(void)134*225f5eecSMinkyu Kang static unsigned long s5pc110_get_arm_clk(void)
135*225f5eecSMinkyu Kang {
136*225f5eecSMinkyu Kang 	struct s5pc110_clock *clk =
137*225f5eecSMinkyu Kang 		(struct s5pc110_clock *)samsung_get_base_clock();
138*225f5eecSMinkyu Kang 	unsigned long div;
139*225f5eecSMinkyu Kang 	unsigned long dout_apll, armclk;
140*225f5eecSMinkyu Kang 	unsigned int apll_ratio;
141*225f5eecSMinkyu Kang 
142*225f5eecSMinkyu Kang 	div = readl(&clk->div0);
143*225f5eecSMinkyu Kang 
144*225f5eecSMinkyu Kang 	/* APLL_RATIO: [2:0] */
145*225f5eecSMinkyu Kang 	apll_ratio = div & 0x7;
146*225f5eecSMinkyu Kang 
147*225f5eecSMinkyu Kang 	dout_apll = get_pll_clk(APLL) / (apll_ratio + 1);
148*225f5eecSMinkyu Kang 	armclk = dout_apll;
149*225f5eecSMinkyu Kang 
150*225f5eecSMinkyu Kang 	return armclk;
151*225f5eecSMinkyu Kang }
152*225f5eecSMinkyu Kang 
153*225f5eecSMinkyu Kang /* s5pc100: return ARM clock frequency */
s5pc100_get_arm_clk(void)154*225f5eecSMinkyu Kang static unsigned long s5pc100_get_arm_clk(void)
155*225f5eecSMinkyu Kang {
156*225f5eecSMinkyu Kang 	struct s5pc100_clock *clk =
157*225f5eecSMinkyu Kang 		(struct s5pc100_clock *)samsung_get_base_clock();
158*225f5eecSMinkyu Kang 	unsigned long div;
159*225f5eecSMinkyu Kang 	unsigned long dout_apll, armclk;
160*225f5eecSMinkyu Kang 	unsigned int apll_ratio, arm_ratio;
161*225f5eecSMinkyu Kang 
162*225f5eecSMinkyu Kang 	div = readl(&clk->div0);
163*225f5eecSMinkyu Kang 
164*225f5eecSMinkyu Kang 	/* ARM_RATIO: [6:4] */
165*225f5eecSMinkyu Kang 	arm_ratio = (div >> 4) & 0x7;
166*225f5eecSMinkyu Kang 	/* APLL_RATIO: [0] */
167*225f5eecSMinkyu Kang 	apll_ratio = div & 0x1;
168*225f5eecSMinkyu Kang 
169*225f5eecSMinkyu Kang 	dout_apll = get_pll_clk(APLL) / (apll_ratio + 1);
170*225f5eecSMinkyu Kang 	armclk = dout_apll / (arm_ratio + 1);
171*225f5eecSMinkyu Kang 
172*225f5eecSMinkyu Kang 	return armclk;
173*225f5eecSMinkyu Kang }
174*225f5eecSMinkyu Kang 
175*225f5eecSMinkyu Kang /* s5pc100: return HCLKD0 frequency */
get_hclk(void)176*225f5eecSMinkyu Kang static unsigned long get_hclk(void)
177*225f5eecSMinkyu Kang {
178*225f5eecSMinkyu Kang 	struct s5pc100_clock *clk =
179*225f5eecSMinkyu Kang 		(struct s5pc100_clock *)samsung_get_base_clock();
180*225f5eecSMinkyu Kang 	unsigned long hclkd0;
181*225f5eecSMinkyu Kang 	uint div, d0_bus_ratio;
182*225f5eecSMinkyu Kang 
183*225f5eecSMinkyu Kang 	div = readl(&clk->div0);
184*225f5eecSMinkyu Kang 	/* D0_BUS_RATIO: [10:8] */
185*225f5eecSMinkyu Kang 	d0_bus_ratio = (div >> 8) & 0x7;
186*225f5eecSMinkyu Kang 
187*225f5eecSMinkyu Kang 	hclkd0 = get_arm_clk() / (d0_bus_ratio + 1);
188*225f5eecSMinkyu Kang 
189*225f5eecSMinkyu Kang 	return hclkd0;
190*225f5eecSMinkyu Kang }
191*225f5eecSMinkyu Kang 
192*225f5eecSMinkyu Kang /* s5pc100: return PCLKD1 frequency */
get_pclkd1(void)193*225f5eecSMinkyu Kang static unsigned long get_pclkd1(void)
194*225f5eecSMinkyu Kang {
195*225f5eecSMinkyu Kang 	struct s5pc100_clock *clk =
196*225f5eecSMinkyu Kang 		(struct s5pc100_clock *)samsung_get_base_clock();
197*225f5eecSMinkyu Kang 	unsigned long d1_bus, pclkd1;
198*225f5eecSMinkyu Kang 	uint div, d1_bus_ratio, pclkd1_ratio;
199*225f5eecSMinkyu Kang 
200*225f5eecSMinkyu Kang 	div = readl(&clk->div0);
201*225f5eecSMinkyu Kang 	/* D1_BUS_RATIO: [14:12] */
202*225f5eecSMinkyu Kang 	d1_bus_ratio = (div >> 12) & 0x7;
203*225f5eecSMinkyu Kang 	/* PCLKD1_RATIO: [18:16] */
204*225f5eecSMinkyu Kang 	pclkd1_ratio = (div >> 16) & 0x7;
205*225f5eecSMinkyu Kang 
206*225f5eecSMinkyu Kang 	/* ASYNC Mode */
207*225f5eecSMinkyu Kang 	d1_bus = get_pll_clk(MPLL) / (d1_bus_ratio + 1);
208*225f5eecSMinkyu Kang 	pclkd1 = d1_bus / (pclkd1_ratio + 1);
209*225f5eecSMinkyu Kang 
210*225f5eecSMinkyu Kang 	return pclkd1;
211*225f5eecSMinkyu Kang }
212*225f5eecSMinkyu Kang 
213*225f5eecSMinkyu Kang /* s5pc110: return HCLKs frequency */
get_hclk_sys(int dom)214*225f5eecSMinkyu Kang static unsigned long get_hclk_sys(int dom)
215*225f5eecSMinkyu Kang {
216*225f5eecSMinkyu Kang 	struct s5pc110_clock *clk =
217*225f5eecSMinkyu Kang 		(struct s5pc110_clock *)samsung_get_base_clock();
218*225f5eecSMinkyu Kang 	unsigned long hclk;
219*225f5eecSMinkyu Kang 	unsigned int div;
220*225f5eecSMinkyu Kang 	unsigned int offset;
221*225f5eecSMinkyu Kang 	unsigned int hclk_sys_ratio;
222*225f5eecSMinkyu Kang 
223*225f5eecSMinkyu Kang 	if (dom == CLK_M)
224*225f5eecSMinkyu Kang 		return get_hclk();
225*225f5eecSMinkyu Kang 
226*225f5eecSMinkyu Kang 	div = readl(&clk->div0);
227*225f5eecSMinkyu Kang 
228*225f5eecSMinkyu Kang 	/*
229*225f5eecSMinkyu Kang 	 * HCLK_MSYS_RATIO: [10:8]
230*225f5eecSMinkyu Kang 	 * HCLK_DSYS_RATIO: [19:16]
231*225f5eecSMinkyu Kang 	 * HCLK_PSYS_RATIO: [27:24]
232*225f5eecSMinkyu Kang 	 */
233*225f5eecSMinkyu Kang 	offset = 8 + (dom << 0x3);
234*225f5eecSMinkyu Kang 
235*225f5eecSMinkyu Kang 	hclk_sys_ratio = (div >> offset) & 0xf;
236*225f5eecSMinkyu Kang 
237*225f5eecSMinkyu Kang 	hclk = get_pll_clk(MPLL) / (hclk_sys_ratio + 1);
238*225f5eecSMinkyu Kang 
239*225f5eecSMinkyu Kang 	return hclk;
240*225f5eecSMinkyu Kang }
241*225f5eecSMinkyu Kang 
242*225f5eecSMinkyu Kang /* s5pc110: return PCLKs frequency */
get_pclk_sys(int dom)243*225f5eecSMinkyu Kang static unsigned long get_pclk_sys(int dom)
244*225f5eecSMinkyu Kang {
245*225f5eecSMinkyu Kang 	struct s5pc110_clock *clk =
246*225f5eecSMinkyu Kang 		(struct s5pc110_clock *)samsung_get_base_clock();
247*225f5eecSMinkyu Kang 	unsigned long pclk;
248*225f5eecSMinkyu Kang 	unsigned int div;
249*225f5eecSMinkyu Kang 	unsigned int offset;
250*225f5eecSMinkyu Kang 	unsigned int pclk_sys_ratio;
251*225f5eecSMinkyu Kang 
252*225f5eecSMinkyu Kang 	div = readl(&clk->div0);
253*225f5eecSMinkyu Kang 
254*225f5eecSMinkyu Kang 	/*
255*225f5eecSMinkyu Kang 	 * PCLK_MSYS_RATIO: [14:12]
256*225f5eecSMinkyu Kang 	 * PCLK_DSYS_RATIO: [22:20]
257*225f5eecSMinkyu Kang 	 * PCLK_PSYS_RATIO: [30:28]
258*225f5eecSMinkyu Kang 	 */
259*225f5eecSMinkyu Kang 	offset = 12 + (dom << 0x3);
260*225f5eecSMinkyu Kang 
261*225f5eecSMinkyu Kang 	pclk_sys_ratio = (div >> offset) & 0x7;
262*225f5eecSMinkyu Kang 
263*225f5eecSMinkyu Kang 	pclk = get_hclk_sys(dom) / (pclk_sys_ratio + 1);
264*225f5eecSMinkyu Kang 
265*225f5eecSMinkyu Kang 	return pclk;
266*225f5eecSMinkyu Kang }
267*225f5eecSMinkyu Kang 
268*225f5eecSMinkyu Kang /* s5pc110: return peripheral clock frequency */
s5pc110_get_pclk(void)269*225f5eecSMinkyu Kang static unsigned long s5pc110_get_pclk(void)
270*225f5eecSMinkyu Kang {
271*225f5eecSMinkyu Kang 	return get_pclk_sys(CLK_P);
272*225f5eecSMinkyu Kang }
273*225f5eecSMinkyu Kang 
274*225f5eecSMinkyu Kang /* s5pc100: return peripheral clock frequency */
s5pc100_get_pclk(void)275*225f5eecSMinkyu Kang static unsigned long s5pc100_get_pclk(void)
276*225f5eecSMinkyu Kang {
277*225f5eecSMinkyu Kang 	return get_pclkd1();
278*225f5eecSMinkyu Kang }
279*225f5eecSMinkyu Kang 
280*225f5eecSMinkyu Kang /* s5pc1xx: return uart clock frequency */
s5pc1xx_get_uart_clk(int dev_index)281*225f5eecSMinkyu Kang static unsigned long s5pc1xx_get_uart_clk(int dev_index)
282*225f5eecSMinkyu Kang {
283*225f5eecSMinkyu Kang 	if (cpu_is_s5pc110())
284*225f5eecSMinkyu Kang 		return s5pc110_get_pclk();
285*225f5eecSMinkyu Kang 	else
286*225f5eecSMinkyu Kang 		return s5pc100_get_pclk();
287*225f5eecSMinkyu Kang }
288*225f5eecSMinkyu Kang 
289*225f5eecSMinkyu Kang /* s5pc1xx: return pwm clock frequency */
s5pc1xx_get_pwm_clk(void)290*225f5eecSMinkyu Kang static unsigned long s5pc1xx_get_pwm_clk(void)
291*225f5eecSMinkyu Kang {
292*225f5eecSMinkyu Kang 	if (cpu_is_s5pc110())
293*225f5eecSMinkyu Kang 		return s5pc110_get_pclk();
294*225f5eecSMinkyu Kang 	else
295*225f5eecSMinkyu Kang 		return s5pc100_get_pclk();
296*225f5eecSMinkyu Kang }
297*225f5eecSMinkyu Kang 
get_pll_clk(int pllreg)298*225f5eecSMinkyu Kang unsigned long get_pll_clk(int pllreg)
299*225f5eecSMinkyu Kang {
300*225f5eecSMinkyu Kang 	if (cpu_is_s5pc110())
301*225f5eecSMinkyu Kang 		return s5pc110_get_pll_clk(pllreg);
302*225f5eecSMinkyu Kang 	else
303*225f5eecSMinkyu Kang 		return s5pc100_get_pll_clk(pllreg);
304*225f5eecSMinkyu Kang }
305*225f5eecSMinkyu Kang 
get_arm_clk(void)306*225f5eecSMinkyu Kang unsigned long get_arm_clk(void)
307*225f5eecSMinkyu Kang {
308*225f5eecSMinkyu Kang 	if (cpu_is_s5pc110())
309*225f5eecSMinkyu Kang 		return s5pc110_get_arm_clk();
310*225f5eecSMinkyu Kang 	else
311*225f5eecSMinkyu Kang 		return s5pc100_get_arm_clk();
312*225f5eecSMinkyu Kang }
313*225f5eecSMinkyu Kang 
get_pwm_clk(void)314*225f5eecSMinkyu Kang unsigned long get_pwm_clk(void)
315*225f5eecSMinkyu Kang {
316*225f5eecSMinkyu Kang 	return s5pc1xx_get_pwm_clk();
317*225f5eecSMinkyu Kang }
318*225f5eecSMinkyu Kang 
get_uart_clk(int dev_index)319*225f5eecSMinkyu Kang unsigned long get_uart_clk(int dev_index)
320*225f5eecSMinkyu Kang {
321*225f5eecSMinkyu Kang 	return s5pc1xx_get_uart_clk(dev_index);
322*225f5eecSMinkyu Kang }
323*225f5eecSMinkyu Kang 
set_mmc_clk(int dev_index,unsigned int div)324*225f5eecSMinkyu Kang void set_mmc_clk(int dev_index, unsigned int div)
325*225f5eecSMinkyu Kang {
326*225f5eecSMinkyu Kang 	/* Do NOTHING */
327*225f5eecSMinkyu Kang }
328