diff options
author | Changhwan Youn <chaos.youn@samsung.com> | 2010-07-27 04:52:39 -0400 |
---|---|---|
committer | Kukjin Kim <kgene.kim@samsung.com> | 2010-08-05 05:32:41 -0400 |
commit | c8bef14051b261f86278fad84ccc23c891242d25 (patch) | |
tree | 196e3abd37764ef4521c0a54853a107a317b15b0 | |
parent | 2b12b5c4ff9e0f1c5f4e5d5bde57b919fe522df2 (diff) |
ARM: S5PV310: Add Clock and PLL support
This patch adds clock and pll support for S5PV310.
Signed-off-by: Changhwan Youn <chaos.youn@samsung.com>
Signed-off-by: Jongpill Lee <boyko.lee@samsung.com>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
-rw-r--r-- | arch/arm/mach-s5pv310/clock.c | 544 | ||||
-rw-r--r-- | arch/arm/mach-s5pv310/include/mach/regs-clock.h | 62 | ||||
-rw-r--r-- | arch/arm/plat-s5p/include/plat/pll.h | 41 |
3 files changed, 647 insertions, 0 deletions
diff --git a/arch/arm/mach-s5pv310/clock.c b/arch/arm/mach-s5pv310/clock.c new file mode 100644 index 000000000000..77f2b4d85e6b --- /dev/null +++ b/arch/arm/mach-s5pv310/clock.c | |||
@@ -0,0 +1,544 @@ | |||
1 | /* linux/arch/arm/mach-s5pv310/clock.c | ||
2 | * | ||
3 | * Copyright (c) 2010 Samsung Electronics Co., Ltd. | ||
4 | * http://www.samsung.com/ | ||
5 | * | ||
6 | * S5PV310 - Clock support | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/err.h> | ||
15 | #include <linux/io.h> | ||
16 | |||
17 | #include <plat/cpu-freq.h> | ||
18 | #include <plat/clock.h> | ||
19 | #include <plat/cpu.h> | ||
20 | #include <plat/pll.h> | ||
21 | #include <plat/s5p-clock.h> | ||
22 | #include <plat/clock-clksrc.h> | ||
23 | |||
24 | #include <mach/map.h> | ||
25 | #include <mach/regs-clock.h> | ||
26 | |||
27 | static struct clk clk_sclk_hdmi27m = { | ||
28 | .name = "sclk_hdmi27m", | ||
29 | .id = -1, | ||
30 | .rate = 27000000, | ||
31 | }; | ||
32 | |||
33 | /* Core list of CMU_CPU side */ | ||
34 | |||
35 | static struct clksrc_clk clk_mout_apll = { | ||
36 | .clk = { | ||
37 | .name = "mout_apll", | ||
38 | .id = -1, | ||
39 | }, | ||
40 | .sources = &clk_src_apll, | ||
41 | .reg_src = { .reg = S5P_CLKSRC_CPU, .shift = 0, .size = 1 }, | ||
42 | .reg_div = { .reg = S5P_CLKDIV_CPU, .shift = 24, .size = 3 }, | ||
43 | }; | ||
44 | |||
45 | static struct clksrc_clk clk_mout_epll = { | ||
46 | .clk = { | ||
47 | .name = "mout_epll", | ||
48 | .id = -1, | ||
49 | }, | ||
50 | .sources = &clk_src_epll, | ||
51 | .reg_src = { .reg = S5P_CLKSRC_TOP0, .shift = 4, .size = 1 }, | ||
52 | }; | ||
53 | |||
54 | static struct clksrc_clk clk_mout_mpll = { | ||
55 | .clk = { | ||
56 | .name = "mout_mpll", | ||
57 | .id = -1, | ||
58 | }, | ||
59 | .sources = &clk_src_mpll, | ||
60 | .reg_src = { .reg = S5P_CLKSRC_CPU, .shift = 8, .size = 1 }, | ||
61 | }; | ||
62 | |||
63 | static struct clk *clkset_moutcore_list[] = { | ||
64 | [0] = &clk_mout_apll.clk, | ||
65 | [1] = &clk_mout_mpll.clk, | ||
66 | }; | ||
67 | |||
68 | static struct clksrc_sources clkset_moutcore = { | ||
69 | .sources = clkset_moutcore_list, | ||
70 | .nr_sources = ARRAY_SIZE(clkset_moutcore_list), | ||
71 | }; | ||
72 | |||
73 | static struct clksrc_clk clk_moutcore = { | ||
74 | .clk = { | ||
75 | .name = "moutcore", | ||
76 | .id = -1, | ||
77 | }, | ||
78 | .sources = &clkset_moutcore, | ||
79 | .reg_src = { .reg = S5P_CLKSRC_CPU, .shift = 16, .size = 1 }, | ||
80 | }; | ||
81 | |||
82 | static struct clksrc_clk clk_coreclk = { | ||
83 | .clk = { | ||
84 | .name = "core_clk", | ||
85 | .id = -1, | ||
86 | .parent = &clk_moutcore.clk, | ||
87 | }, | ||
88 | .reg_div = { .reg = S5P_CLKDIV_CPU, .shift = 0, .size = 3 }, | ||
89 | }; | ||
90 | |||
91 | static struct clksrc_clk clk_armclk = { | ||
92 | .clk = { | ||
93 | .name = "armclk", | ||
94 | .id = -1, | ||
95 | .parent = &clk_coreclk.clk, | ||
96 | }, | ||
97 | }; | ||
98 | |||
99 | static struct clksrc_clk clk_aclk_corem0 = { | ||
100 | .clk = { | ||
101 | .name = "aclk_corem0", | ||
102 | .id = -1, | ||
103 | .parent = &clk_coreclk.clk, | ||
104 | }, | ||
105 | .reg_div = { .reg = S5P_CLKDIV_CPU, .shift = 4, .size = 3 }, | ||
106 | }; | ||
107 | |||
108 | static struct clksrc_clk clk_aclk_cores = { | ||
109 | .clk = { | ||
110 | .name = "aclk_cores", | ||
111 | .id = -1, | ||
112 | .parent = &clk_coreclk.clk, | ||
113 | }, | ||
114 | .reg_div = { .reg = S5P_CLKDIV_CPU, .shift = 4, .size = 3 }, | ||
115 | }; | ||
116 | |||
117 | static struct clksrc_clk clk_aclk_corem1 = { | ||
118 | .clk = { | ||
119 | .name = "aclk_corem1", | ||
120 | .id = -1, | ||
121 | .parent = &clk_coreclk.clk, | ||
122 | }, | ||
123 | .reg_div = { .reg = S5P_CLKDIV_CPU, .shift = 8, .size = 3 }, | ||
124 | }; | ||
125 | |||
126 | static struct clksrc_clk clk_periphclk = { | ||
127 | .clk = { | ||
128 | .name = "periphclk", | ||
129 | .id = -1, | ||
130 | .parent = &clk_coreclk.clk, | ||
131 | }, | ||
132 | .reg_div = { .reg = S5P_CLKDIV_CPU, .shift = 12, .size = 3 }, | ||
133 | }; | ||
134 | |||
135 | static struct clksrc_clk clk_atclk = { | ||
136 | .clk = { | ||
137 | .name = "atclk", | ||
138 | .id = -1, | ||
139 | .parent = &clk_moutcore.clk, | ||
140 | }, | ||
141 | .reg_div = { .reg = S5P_CLKDIV_CPU, .shift = 16, .size = 3 }, | ||
142 | }; | ||
143 | |||
144 | static struct clksrc_clk clk_pclk_dbg = { | ||
145 | .clk = { | ||
146 | .name = "pclk_dbg", | ||
147 | .id = -1, | ||
148 | .parent = &clk_atclk.clk, | ||
149 | }, | ||
150 | .reg_div = { .reg = S5P_CLKDIV_CPU, .shift = 20, .size = 3 }, | ||
151 | }; | ||
152 | |||
153 | /* Core list of CMU_CORE side */ | ||
154 | |||
155 | static struct clk *clkset_corebus_list[] = { | ||
156 | [0] = &clk_mout_mpll.clk, | ||
157 | [1] = &clk_mout_apll.clk, | ||
158 | }; | ||
159 | |||
160 | static struct clksrc_sources clkset_mout_corebus = { | ||
161 | .sources = clkset_corebus_list, | ||
162 | .nr_sources = ARRAY_SIZE(clkset_corebus_list), | ||
163 | }; | ||
164 | |||
165 | static struct clksrc_clk clk_mout_corebus = { | ||
166 | .clk = { | ||
167 | .name = "mout_corebus", | ||
168 | .id = -1, | ||
169 | }, | ||
170 | .sources = &clkset_mout_corebus, | ||
171 | .reg_src = { .reg = S5P_CLKSRC_CORE, .shift = 4, .size = 1 }, | ||
172 | }; | ||
173 | |||
174 | static struct clksrc_clk clk_sclk_dmc = { | ||
175 | .clk = { | ||
176 | .name = "sclk_dmc", | ||
177 | .id = -1, | ||
178 | .parent = &clk_mout_corebus.clk, | ||
179 | }, | ||
180 | .reg_div = { .reg = S5P_CLKDIV_CORE0, .shift = 12, .size = 3 }, | ||
181 | }; | ||
182 | |||
183 | static struct clksrc_clk clk_aclk_cored = { | ||
184 | .clk = { | ||
185 | .name = "aclk_cored", | ||
186 | .id = -1, | ||
187 | .parent = &clk_sclk_dmc.clk, | ||
188 | }, | ||
189 | .reg_div = { .reg = S5P_CLKDIV_CORE0, .shift = 16, .size = 3 }, | ||
190 | }; | ||
191 | |||
192 | static struct clksrc_clk clk_aclk_corep = { | ||
193 | .clk = { | ||
194 | .name = "aclk_corep", | ||
195 | .id = -1, | ||
196 | .parent = &clk_aclk_cored.clk, | ||
197 | }, | ||
198 | .reg_div = { .reg = S5P_CLKDIV_CORE0, .shift = 20, .size = 3 }, | ||
199 | }; | ||
200 | |||
201 | static struct clksrc_clk clk_aclk_acp = { | ||
202 | .clk = { | ||
203 | .name = "aclk_acp", | ||
204 | .id = -1, | ||
205 | .parent = &clk_mout_corebus.clk, | ||
206 | }, | ||
207 | .reg_div = { .reg = S5P_CLKDIV_CORE0, .shift = 0, .size = 3 }, | ||
208 | }; | ||
209 | |||
210 | static struct clksrc_clk clk_pclk_acp = { | ||
211 | .clk = { | ||
212 | .name = "pclk_acp", | ||
213 | .id = -1, | ||
214 | .parent = &clk_aclk_acp.clk, | ||
215 | }, | ||
216 | .reg_div = { .reg = S5P_CLKDIV_CORE0, .shift = 4, .size = 3 }, | ||
217 | }; | ||
218 | |||
219 | /* Core list of CMU_TOP side */ | ||
220 | |||
221 | static struct clk *clkset_aclk_top_list[] = { | ||
222 | [0] = &clk_mout_mpll.clk, | ||
223 | [1] = &clk_mout_apll.clk, | ||
224 | }; | ||
225 | |||
226 | static struct clksrc_sources clkset_aclk_200 = { | ||
227 | .sources = clkset_aclk_top_list, | ||
228 | .nr_sources = ARRAY_SIZE(clkset_aclk_top_list), | ||
229 | }; | ||
230 | |||
231 | static struct clksrc_clk clk_aclk_200 = { | ||
232 | .clk = { | ||
233 | .name = "aclk_200", | ||
234 | .id = -1, | ||
235 | }, | ||
236 | .sources = &clkset_aclk_200, | ||
237 | .reg_src = { .reg = S5P_CLKSRC_TOP0, .shift = 12, .size = 1 }, | ||
238 | .reg_div = { .reg = S5P_CLKDIV_TOP, .shift = 0, .size = 3 }, | ||
239 | }; | ||
240 | |||
241 | static struct clksrc_sources clkset_aclk_100 = { | ||
242 | .sources = clkset_aclk_top_list, | ||
243 | .nr_sources = ARRAY_SIZE(clkset_aclk_top_list), | ||
244 | }; | ||
245 | |||
246 | static struct clksrc_clk clk_aclk_100 = { | ||
247 | .clk = { | ||
248 | .name = "aclk_100", | ||
249 | .id = -1, | ||
250 | }, | ||
251 | .sources = &clkset_aclk_100, | ||
252 | .reg_src = { .reg = S5P_CLKSRC_TOP0, .shift = 16, .size = 1 }, | ||
253 | .reg_div = { .reg = S5P_CLKDIV_TOP, .shift = 4, .size = 4 }, | ||
254 | }; | ||
255 | |||
256 | static struct clksrc_sources clkset_aclk_160 = { | ||
257 | .sources = clkset_aclk_top_list, | ||
258 | .nr_sources = ARRAY_SIZE(clkset_aclk_top_list), | ||
259 | }; | ||
260 | |||
261 | static struct clksrc_clk clk_aclk_160 = { | ||
262 | .clk = { | ||
263 | .name = "aclk_160", | ||
264 | .id = -1, | ||
265 | }, | ||
266 | .sources = &clkset_aclk_160, | ||
267 | .reg_src = { .reg = S5P_CLKSRC_TOP0, .shift = 20, .size = 1 }, | ||
268 | .reg_div = { .reg = S5P_CLKDIV_TOP, .shift = 8, .size = 3 }, | ||
269 | }; | ||
270 | |||
271 | static struct clksrc_sources clkset_aclk_133 = { | ||
272 | .sources = clkset_aclk_top_list, | ||
273 | .nr_sources = ARRAY_SIZE(clkset_aclk_top_list), | ||
274 | }; | ||
275 | |||
276 | static struct clksrc_clk clk_aclk_133 = { | ||
277 | .clk = { | ||
278 | .name = "aclk_133", | ||
279 | .id = -1, | ||
280 | }, | ||
281 | .sources = &clkset_aclk_133, | ||
282 | .reg_src = { .reg = S5P_CLKSRC_TOP0, .shift = 24, .size = 1 }, | ||
283 | .reg_div = { .reg = S5P_CLKDIV_TOP, .shift = 12, .size = 3 }, | ||
284 | }; | ||
285 | |||
286 | static struct clk *clkset_vpllsrc_list[] = { | ||
287 | [0] = &clk_fin_vpll, | ||
288 | [1] = &clk_sclk_hdmi27m, | ||
289 | }; | ||
290 | |||
291 | static struct clksrc_sources clkset_vpllsrc = { | ||
292 | .sources = clkset_vpllsrc_list, | ||
293 | .nr_sources = ARRAY_SIZE(clkset_vpllsrc_list), | ||
294 | }; | ||
295 | |||
296 | static struct clksrc_clk clk_vpllsrc = { | ||
297 | .clk = { | ||
298 | .name = "vpll_src", | ||
299 | .id = -1, | ||
300 | }, | ||
301 | .sources = &clkset_vpllsrc, | ||
302 | .reg_src = { .reg = S5P_CLKSRC_TOP1, .shift = 0, .size = 1 }, | ||
303 | }; | ||
304 | |||
305 | static struct clk *clkset_sclk_vpll_list[] = { | ||
306 | [0] = &clk_vpllsrc.clk, | ||
307 | [1] = &clk_fout_vpll, | ||
308 | }; | ||
309 | |||
310 | static struct clksrc_sources clkset_sclk_vpll = { | ||
311 | .sources = clkset_sclk_vpll_list, | ||
312 | .nr_sources = ARRAY_SIZE(clkset_sclk_vpll_list), | ||
313 | }; | ||
314 | |||
315 | static struct clksrc_clk clk_sclk_vpll = { | ||
316 | .clk = { | ||
317 | .name = "sclk_vpll", | ||
318 | .id = -1, | ||
319 | }, | ||
320 | .sources = &clkset_sclk_vpll, | ||
321 | .reg_src = { .reg = S5P_CLKSRC_TOP0, .shift = 8, .size = 1 }, | ||
322 | }; | ||
323 | |||
324 | static int s5pv310_clk_ip_peril_ctrl(struct clk *clk, int enable) | ||
325 | { | ||
326 | return s5p_gatectrl(S5P_CLKGATE_IP_PERIL, clk, enable); | ||
327 | } | ||
328 | |||
329 | static struct clk init_clocks_disable[] = { | ||
330 | { | ||
331 | .name = "timers", | ||
332 | .id = -1, | ||
333 | .parent = &clk_aclk_100.clk, | ||
334 | .enable = s5pv310_clk_ip_peril_ctrl, | ||
335 | .ctrlbit = (1<<24), | ||
336 | } | ||
337 | }; | ||
338 | |||
339 | static struct clk init_clocks[] = { | ||
340 | /* Nothing here yet */ | ||
341 | }; | ||
342 | |||
343 | static struct clk *clkset_group_list[] = { | ||
344 | [0] = &clk_ext_xtal_mux, | ||
345 | [1] = &clk_xusbxti, | ||
346 | [2] = &clk_sclk_hdmi27m, | ||
347 | [6] = &clk_mout_mpll.clk, | ||
348 | [7] = &clk_mout_epll.clk, | ||
349 | [8] = &clk_sclk_vpll.clk, | ||
350 | }; | ||
351 | |||
352 | static struct clksrc_sources clkset_group = { | ||
353 | .sources = clkset_group_list, | ||
354 | .nr_sources = ARRAY_SIZE(clkset_group_list), | ||
355 | }; | ||
356 | |||
357 | static struct clksrc_clk clksrcs[] = { | ||
358 | { | ||
359 | .clk = { | ||
360 | .name = "uclk1", | ||
361 | .id = 0, | ||
362 | .ctrlbit = (1 << 0), | ||
363 | .enable = s5pv310_clk_ip_peril_ctrl, | ||
364 | }, | ||
365 | .sources = &clkset_group, | ||
366 | .reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 0, .size = 4 }, | ||
367 | .reg_div = { .reg = S5P_CLKDIV_PERIL0, .shift = 0, .size = 4 }, | ||
368 | }, { | ||
369 | .clk = { | ||
370 | .name = "uclk1", | ||
371 | .id = 1, | ||
372 | .enable = s5pv310_clk_ip_peril_ctrl, | ||
373 | .ctrlbit = (1 << 1), | ||
374 | }, | ||
375 | .sources = &clkset_group, | ||
376 | .reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 4, .size = 4 }, | ||
377 | .reg_div = { .reg = S5P_CLKDIV_PERIL0, .shift = 4, .size = 4 }, | ||
378 | }, { | ||
379 | .clk = { | ||
380 | .name = "uclk1", | ||
381 | .id = 2, | ||
382 | .enable = s5pv310_clk_ip_peril_ctrl, | ||
383 | .ctrlbit = (1 << 2), | ||
384 | }, | ||
385 | .sources = &clkset_group, | ||
386 | .reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 8, .size = 4 }, | ||
387 | .reg_div = { .reg = S5P_CLKDIV_PERIL0, .shift = 8, .size = 4 }, | ||
388 | }, { | ||
389 | .clk = { | ||
390 | .name = "uclk1", | ||
391 | .id = 3, | ||
392 | .enable = s5pv310_clk_ip_peril_ctrl, | ||
393 | .ctrlbit = (1 << 3), | ||
394 | }, | ||
395 | .sources = &clkset_group, | ||
396 | .reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 12, .size = 4 }, | ||
397 | .reg_div = { .reg = S5P_CLKDIV_PERIL0, .shift = 12, .size = 4 }, | ||
398 | }, { | ||
399 | .clk = { | ||
400 | .name = "sclk_pwm", | ||
401 | .id = -1, | ||
402 | .enable = s5pv310_clk_ip_peril_ctrl, | ||
403 | .ctrlbit = (1 << 24), | ||
404 | }, | ||
405 | .sources = &clkset_group, | ||
406 | .reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 24, .size = 4 }, | ||
407 | .reg_div = { .reg = S5P_CLKDIV_PERIL3, .shift = 0, .size = 4 }, | ||
408 | }, | ||
409 | }; | ||
410 | |||
411 | /* Clock initialization code */ | ||
412 | static struct clksrc_clk *sysclks[] = { | ||
413 | &clk_mout_apll, | ||
414 | &clk_mout_epll, | ||
415 | &clk_mout_mpll, | ||
416 | &clk_moutcore, | ||
417 | &clk_coreclk, | ||
418 | &clk_armclk, | ||
419 | &clk_aclk_corem0, | ||
420 | &clk_aclk_cores, | ||
421 | &clk_aclk_corem1, | ||
422 | &clk_periphclk, | ||
423 | &clk_atclk, | ||
424 | &clk_pclk_dbg, | ||
425 | &clk_mout_corebus, | ||
426 | &clk_sclk_dmc, | ||
427 | &clk_aclk_cored, | ||
428 | &clk_aclk_corep, | ||
429 | &clk_aclk_acp, | ||
430 | &clk_pclk_acp, | ||
431 | &clk_vpllsrc, | ||
432 | &clk_sclk_vpll, | ||
433 | &clk_aclk_200, | ||
434 | &clk_aclk_100, | ||
435 | &clk_aclk_160, | ||
436 | &clk_aclk_133, | ||
437 | }; | ||
438 | |||
439 | void __init_or_cpufreq s5pv310_setup_clocks(void) | ||
440 | { | ||
441 | struct clk *xtal_clk; | ||
442 | unsigned long apll; | ||
443 | unsigned long mpll; | ||
444 | unsigned long epll; | ||
445 | unsigned long vpll; | ||
446 | unsigned long vpllsrc; | ||
447 | unsigned long xtal; | ||
448 | unsigned long armclk; | ||
449 | unsigned long aclk_corem0; | ||
450 | unsigned long aclk_cores; | ||
451 | unsigned long aclk_corem1; | ||
452 | unsigned long periphclk; | ||
453 | unsigned long sclk_dmc; | ||
454 | unsigned long aclk_cored; | ||
455 | unsigned long aclk_corep; | ||
456 | unsigned long aclk_acp; | ||
457 | unsigned long pclk_acp; | ||
458 | unsigned int ptr; | ||
459 | |||
460 | printk(KERN_DEBUG "%s: registering clocks\n", __func__); | ||
461 | |||
462 | xtal_clk = clk_get(NULL, "xtal"); | ||
463 | BUG_ON(IS_ERR(xtal_clk)); | ||
464 | |||
465 | xtal = clk_get_rate(xtal_clk); | ||
466 | clk_put(xtal_clk); | ||
467 | |||
468 | printk(KERN_DEBUG "%s: xtal is %ld\n", __func__, xtal); | ||
469 | |||
470 | apll = s5p_get_pll45xx(xtal, __raw_readl(S5P_APLL_CON0), pll_4508); | ||
471 | mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P_MPLL_CON0), pll_4508); | ||
472 | epll = s5p_get_pll46xx(xtal, __raw_readl(S5P_EPLL_CON0), | ||
473 | __raw_readl(S5P_EPLL_CON1), pll_4500); | ||
474 | |||
475 | vpllsrc = clk_get_rate(&clk_vpllsrc.clk); | ||
476 | vpll = s5p_get_pll46xx(vpllsrc, __raw_readl(S5P_VPLL_CON0), | ||
477 | __raw_readl(S5P_VPLL_CON1), pll_4502); | ||
478 | |||
479 | clk_fout_apll.rate = apll; | ||
480 | clk_fout_mpll.rate = mpll; | ||
481 | clk_fout_epll.rate = epll; | ||
482 | clk_fout_vpll.rate = vpll; | ||
483 | |||
484 | printk(KERN_INFO "S5PV310: PLL settings, A=%ld, M=%ld, E=%ld V=%ld", | ||
485 | apll, mpll, epll, vpll); | ||
486 | |||
487 | armclk = clk_get_rate(&clk_armclk.clk); | ||
488 | aclk_corem0 = clk_get_rate(&clk_aclk_corem0.clk); | ||
489 | aclk_cores = clk_get_rate(&clk_aclk_cores.clk); | ||
490 | aclk_corem1 = clk_get_rate(&clk_aclk_corem1.clk); | ||
491 | periphclk = clk_get_rate(&clk_periphclk.clk); | ||
492 | sclk_dmc = clk_get_rate(&clk_sclk_dmc.clk); | ||
493 | aclk_cored = clk_get_rate(&clk_aclk_cored.clk); | ||
494 | aclk_corep = clk_get_rate(&clk_aclk_corep.clk); | ||
495 | aclk_acp = clk_get_rate(&clk_aclk_acp.clk); | ||
496 | pclk_acp = clk_get_rate(&clk_pclk_acp.clk); | ||
497 | |||
498 | printk(KERN_INFO "S5PV310: ARMCLK=%ld, COREM0=%ld, CORES=%ld\n" | ||
499 | "COREM1=%ld, PERI=%ld, DMC=%ld, CORED=%ld\n" | ||
500 | "COREP=%ld, ACLK_ACP=%ld, PCLK_ACP=%ld", | ||
501 | armclk, aclk_corem0, aclk_cores, aclk_corem1, | ||
502 | periphclk, sclk_dmc, aclk_cored, aclk_corep, | ||
503 | aclk_acp, pclk_acp); | ||
504 | |||
505 | clk_f.rate = armclk; | ||
506 | clk_h.rate = sclk_dmc; | ||
507 | clk_p.rate = periphclk; | ||
508 | |||
509 | for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++) | ||
510 | s3c_set_clksrc(&clksrcs[ptr], true); | ||
511 | } | ||
512 | |||
513 | static struct clk *clks[] __initdata = { | ||
514 | /* Nothing here yet */ | ||
515 | }; | ||
516 | |||
517 | void __init s5pv310_register_clocks(void) | ||
518 | { | ||
519 | struct clk *clkp; | ||
520 | int ret; | ||
521 | int ptr; | ||
522 | |||
523 | ret = s3c24xx_register_clocks(clks, ARRAY_SIZE(clks)); | ||
524 | if (ret > 0) | ||
525 | printk(KERN_ERR "Failed to register %u clocks\n", ret); | ||
526 | |||
527 | for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++) | ||
528 | s3c_register_clksrc(sysclks[ptr], 1); | ||
529 | |||
530 | s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs)); | ||
531 | s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks)); | ||
532 | |||
533 | clkp = init_clocks_disable; | ||
534 | for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) { | ||
535 | ret = s3c24xx_register_clock(clkp); | ||
536 | if (ret < 0) { | ||
537 | printk(KERN_ERR "Failed to register clock %s (%d)\n", | ||
538 | clkp->name, ret); | ||
539 | } | ||
540 | (clkp->enable)(clkp, 0); | ||
541 | } | ||
542 | |||
543 | s3c_pwmclk_init(); | ||
544 | } | ||
diff --git a/arch/arm/mach-s5pv310/include/mach/regs-clock.h b/arch/arm/mach-s5pv310/include/mach/regs-clock.h new file mode 100644 index 000000000000..59e3a7e94d80 --- /dev/null +++ b/arch/arm/mach-s5pv310/include/mach/regs-clock.h | |||
@@ -0,0 +1,62 @@ | |||
1 | /* linux/arch/arm/mach-s5pv310/include/mach/regs-clock.h | ||
2 | * | ||
3 | * Copyright (c) 2010 Samsung Electronics Co., Ltd. | ||
4 | * http://www.samsung.com/ | ||
5 | * | ||
6 | * S5PV310 - Clock register definitions | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #ifndef __ASM_ARCH_REGS_CLOCK_H | ||
14 | #define __ASM_ARCH_REGS_CLOCK_H __FILE__ | ||
15 | |||
16 | #include <mach/map.h> | ||
17 | |||
18 | #define S5P_CLKREG(x) (S3C_VA_SYS + (x)) | ||
19 | |||
20 | #define S5P_INFORM0 S5P_CLKREG(0x800) | ||
21 | |||
22 | #define S5P_EPLL_CON0 S5P_CLKREG(0x1C110) | ||
23 | #define S5P_EPLL_CON1 S5P_CLKREG(0x1C114) | ||
24 | #define S5P_VPLL_CON0 S5P_CLKREG(0x1C120) | ||
25 | #define S5P_VPLL_CON1 S5P_CLKREG(0x1C124) | ||
26 | |||
27 | #define S5P_CLKSRC_TOP0 S5P_CLKREG(0x1C210) | ||
28 | #define S5P_CLKSRC_TOP1 S5P_CLKREG(0x1C214) | ||
29 | |||
30 | #define S5P_CLKSRC_PERIL0 S5P_CLKREG(0x1C250) | ||
31 | |||
32 | #define S5P_CLKDIV_TOP S5P_CLKREG(0x1C510) | ||
33 | |||
34 | #define S5P_CLKDIV_PERIL0 S5P_CLKREG(0x1C550) | ||
35 | #define S5P_CLKDIV_PERIL1 S5P_CLKREG(0x1C554) | ||
36 | #define S5P_CLKDIV_PERIL2 S5P_CLKREG(0x1C558) | ||
37 | #define S5P_CLKDIV_PERIL3 S5P_CLKREG(0x1C55C) | ||
38 | #define S5P_CLKDIV_PERIL4 S5P_CLKREG(0x1C560) | ||
39 | #define S5P_CLKDIV_PERIL5 S5P_CLKREG(0x1C564) | ||
40 | |||
41 | #define S5P_CLKGATE_IP_PERIL S5P_CLKREG(0x1C950) | ||
42 | |||
43 | #define S5P_CLKSRC_CORE S5P_CLKREG(0x20200) | ||
44 | |||
45 | #define S5P_CLKDIV_CORE0 S5P_CLKREG(0x20500) | ||
46 | |||
47 | #define S5P_APLL_LOCK S5P_CLKREG(0x24000) | ||
48 | #define S5P_MPLL_LOCK S5P_CLKREG(0x24004) | ||
49 | #define S5P_APLL_CON0 S5P_CLKREG(0x24100) | ||
50 | #define S5P_APLL_CON1 S5P_CLKREG(0x24104) | ||
51 | #define S5P_MPLL_CON0 S5P_CLKREG(0x24108) | ||
52 | #define S5P_MPLL_CON1 S5P_CLKREG(0x2410C) | ||
53 | |||
54 | #define S5P_CLKSRC_CPU S5P_CLKREG(0x24200) | ||
55 | #define S5P_CLKMUX_STATCPU S5P_CLKREG(0x24400) | ||
56 | |||
57 | #define S5P_CLKDIV_CPU S5P_CLKREG(0x24500) | ||
58 | #define S5P_CLKDIV_STATCPU S5P_CLKREG(0x24600) | ||
59 | |||
60 | #define S5P_CLKGATE_SCLKCPU S5P_CLKREG(0x24800) | ||
61 | |||
62 | #endif /* __ASM_ARCH_REGS_CLOCK_H */ | ||
diff --git a/arch/arm/plat-s5p/include/plat/pll.h b/arch/arm/plat-s5p/include/plat/pll.h index 7db322726bc2..4e8fe08cb70d 100644 --- a/arch/arm/plat-s5p/include/plat/pll.h +++ b/arch/arm/plat-s5p/include/plat/pll.h | |||
@@ -46,6 +46,47 @@ static inline unsigned long s5p_get_pll45xx(unsigned long baseclk, u32 pll_con, | |||
46 | return (unsigned long)fvco; | 46 | return (unsigned long)fvco; |
47 | } | 47 | } |
48 | 48 | ||
49 | #define PLL46XX_KDIV_MASK (0xFFFF) | ||
50 | #define PLL46XX_MDIV_MASK (0x1FF) | ||
51 | #define PLL46XX_PDIV_MASK (0x3F) | ||
52 | #define PLL46XX_SDIV_MASK (0x7) | ||
53 | #define PLL46XX_MDIV_SHIFT (16) | ||
54 | #define PLL46XX_PDIV_SHIFT (8) | ||
55 | #define PLL46XX_SDIV_SHIFT (0) | ||
56 | |||
57 | enum pll46xx_type_t { | ||
58 | pll_4600, | ||
59 | pll_4650, | ||
60 | }; | ||
61 | |||
62 | static inline unsigned long s5p_get_pll46xx(unsigned long baseclk, | ||
63 | u32 pll_con0, u32 pll_con1, | ||
64 | enum pll46xx_type_t pll_type) | ||
65 | { | ||
66 | unsigned long result; | ||
67 | u32 mdiv, pdiv, sdiv, kdiv; | ||
68 | u64 tmp; | ||
69 | |||
70 | mdiv = (pll_con0 >> PLL46XX_MDIV_SHIFT) & PLL46XX_MDIV_MASK; | ||
71 | pdiv = (pll_con0 >> PLL46XX_PDIV_SHIFT) & PLL46XX_PDIV_MASK; | ||
72 | sdiv = (pll_con0 >> PLL46XX_SDIV_SHIFT) & PLL46XX_SDIV_MASK; | ||
73 | kdiv = pll_con1 & PLL46XX_KDIV_MASK; | ||
74 | |||
75 | tmp = baseclk; | ||
76 | |||
77 | if (pll_type == pll_4600) { | ||
78 | tmp *= (mdiv << 16) + kdiv; | ||
79 | do_div(tmp, (pdiv << sdiv)); | ||
80 | result = tmp >> 16; | ||
81 | } else { | ||
82 | tmp *= (mdiv << 10) + kdiv; | ||
83 | do_div(tmp, (pdiv << sdiv)); | ||
84 | result = tmp >> 10; | ||
85 | } | ||
86 | |||
87 | return result; | ||
88 | } | ||
89 | |||
49 | #define PLL90XX_MDIV_MASK (0xFF) | 90 | #define PLL90XX_MDIV_MASK (0xFF) |
50 | #define PLL90XX_PDIV_MASK (0x3F) | 91 | #define PLL90XX_PDIV_MASK (0x3F) |
51 | #define PLL90XX_SDIV_MASK (0x7) | 92 | #define PLL90XX_SDIV_MASK (0x7) |