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