1
2
3
4
5
6
7
8#include <common.h>
9#include <asm/io.h>
10#include <asm/arch/clock.h>
11#include <asm/arch/clk.h>
12
13#define CLK_M 0
14#define CLK_D 1
15#define CLK_P 2
16
17#define CFG_SYS_CLK_FREQ_C100 12000000
18#define CFG_SYS_CLK_FREQ_C110 24000000
19
20
21static unsigned long s5pc100_get_pll_clk(int pllreg)
22{
23 struct s5pc100_clock *clk =
24 (struct s5pc100_clock *)samsung_get_base_clock();
25 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
48
49
50
51
52 if (pllreg == APLL)
53 mask = 0x3ff;
54 else
55 mask = 0x0ff;
56
57 m = (r >> 16) & mask;
58
59
60 p = (r >> 8) & 0x3f;
61
62 s = r & 0x7;
63
64
65 freq = CFG_SYS_CLK_FREQ_C100;
66 fout = m * (freq / (p * (1 << s)));
67
68 return fout;
69}
70
71
72static unsigned long s5pc110_get_pll_clk(int pllreg)
73{
74 struct s5pc110_clock *clk =
75 (struct s5pc110_clock *)samsung_get_base_clock();
76 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
99
100
101
102
103 if (pllreg == APLL || pllreg == MPLL)
104 mask = 0x3ff;
105 else
106 mask = 0x1ff;
107
108 m = (r >> 16) & mask;
109
110
111 p = (r >> 8) & 0x3f;
112
113 s = r & 0x7;
114
115 freq = CFG_SYS_CLK_FREQ_C110;
116 if (pllreg == APLL) {
117 if (s < 1)
118 s = 1;
119
120 fout = m * (freq / (p * (1 << (s - 1))));
121 } else
122
123 fout = m * (freq / (p * (1 << s)));
124
125 return fout;
126}
127
128
129static unsigned long s5pc110_get_arm_clk(void)
130{
131 struct s5pc110_clock *clk =
132 (struct s5pc110_clock *)samsung_get_base_clock();
133 unsigned long div;
134 unsigned long dout_apll, armclk;
135 unsigned int apll_ratio;
136
137 div = readl(&clk->div0);
138
139
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
149static unsigned long s5pc100_get_arm_clk(void)
150{
151 struct s5pc100_clock *clk =
152 (struct s5pc100_clock *)samsung_get_base_clock();
153 unsigned long div;
154 unsigned long dout_apll, armclk;
155 unsigned int apll_ratio, arm_ratio;
156
157 div = readl(&clk->div0);
158
159
160 arm_ratio = (div >> 4) & 0x7;
161
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
171static unsigned long get_hclk(void)
172{
173 struct s5pc100_clock *clk =
174 (struct s5pc100_clock *)samsung_get_base_clock();
175 unsigned long hclkd0;
176 uint div, d0_bus_ratio;
177
178 div = readl(&clk->div0);
179
180 d0_bus_ratio = (div >> 8) & 0x7;
181
182 hclkd0 = get_arm_clk() / (d0_bus_ratio + 1);
183
184 return hclkd0;
185}
186
187
188static unsigned long get_pclkd1(void)
189{
190 struct s5pc100_clock *clk =
191 (struct s5pc100_clock *)samsung_get_base_clock();
192 unsigned long d1_bus, pclkd1;
193 uint div, d1_bus_ratio, pclkd1_ratio;
194
195 div = readl(&clk->div0);
196
197 d1_bus_ratio = (div >> 12) & 0x7;
198
199 pclkd1_ratio = (div >> 16) & 0x7;
200
201
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
209static unsigned long get_hclk_sys(int dom)
210{
211 struct s5pc110_clock *clk =
212 (struct s5pc110_clock *)samsung_get_base_clock();
213 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
225
226
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
238static unsigned long get_pclk_sys(int dom)
239{
240 struct s5pc110_clock *clk =
241 (struct s5pc110_clock *)samsung_get_base_clock();
242 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
251
252
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
264static unsigned long s5pc110_get_pclk(void)
265{
266 return get_pclk_sys(CLK_P);
267}
268
269
270static unsigned long s5pc100_get_pclk(void)
271{
272 return get_pclkd1();
273}
274
275
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
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
293unsigned long get_pll_clk(int pllreg)
294{
295 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);
317}
318
319void set_mmc_clk(int dev_index, unsigned int div)
320{
321
322}
323