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