diff options
author | Heiko Stuebner <heiko@sntech.de> | 2012-03-02 17:49:12 -0500 |
---|---|---|
committer | Kukjin Kim <kgene.kim@samsung.com> | 2012-03-02 18:55:59 -0500 |
commit | 8c3d7c30c306d83ff9c303f42307765a5a7bc254 (patch) | |
tree | f3874d2a4fa20881b10c23e1610e75c2975ed236 /arch/arm/plat-s3c24xx/s3c2443-clock.c | |
parent | 8fe2ff766d458453f8b5624291f14db9efe2ef20 (diff) |
ARM: S3C24XX: Move s3c2443-clock.c to mach-s3c24xx
S3C-SoCs starting with the S3C2443 can share a lot of functionality.
The file can collect more common code of these SocS later on and
therefore gets a new name to reflect this future purpose.
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
Diffstat (limited to 'arch/arm/plat-s3c24xx/s3c2443-clock.c')
-rw-r--r-- | arch/arm/plat-s3c24xx/s3c2443-clock.c | 635 |
1 files changed, 0 insertions, 635 deletions
diff --git a/arch/arm/plat-s3c24xx/s3c2443-clock.c b/arch/arm/plat-s3c24xx/s3c2443-clock.c deleted file mode 100644 index 363306061c89..000000000000 --- a/arch/arm/plat-s3c24xx/s3c2443-clock.c +++ /dev/null | |||
@@ -1,635 +0,0 @@ | |||
1 | /* linux/arch/arm/plat-s3c24xx/s3c2443-clock.c | ||
2 | * | ||
3 | * Copyright (c) 2007, 2010 Simtec Electronics | ||
4 | * Ben Dooks <ben@simtec.co.uk> | ||
5 | * | ||
6 | * S3C2443 Clock control suport - common code | ||
7 | */ | ||
8 | |||
9 | #include <linux/init.h> | ||
10 | #include <linux/clk.h> | ||
11 | #include <linux/io.h> | ||
12 | |||
13 | #include <mach/regs-s3c2443-clock.h> | ||
14 | |||
15 | #include <plat/clock.h> | ||
16 | #include <plat/clock-clksrc.h> | ||
17 | #include <plat/cpu.h> | ||
18 | |||
19 | #include <plat/cpu-freq.h> | ||
20 | |||
21 | |||
22 | static int s3c2443_gate(void __iomem *reg, struct clk *clk, int enable) | ||
23 | { | ||
24 | u32 ctrlbit = clk->ctrlbit; | ||
25 | u32 con = __raw_readl(reg); | ||
26 | |||
27 | if (enable) | ||
28 | con |= ctrlbit; | ||
29 | else | ||
30 | con &= ~ctrlbit; | ||
31 | |||
32 | __raw_writel(con, reg); | ||
33 | return 0; | ||
34 | } | ||
35 | |||
36 | int s3c2443_clkcon_enable_h(struct clk *clk, int enable) | ||
37 | { | ||
38 | return s3c2443_gate(S3C2443_HCLKCON, clk, enable); | ||
39 | } | ||
40 | |||
41 | int s3c2443_clkcon_enable_p(struct clk *clk, int enable) | ||
42 | { | ||
43 | return s3c2443_gate(S3C2443_PCLKCON, clk, enable); | ||
44 | } | ||
45 | |||
46 | int s3c2443_clkcon_enable_s(struct clk *clk, int enable) | ||
47 | { | ||
48 | return s3c2443_gate(S3C2443_SCLKCON, clk, enable); | ||
49 | } | ||
50 | |||
51 | /* mpllref is a direct descendant of clk_xtal by default, but it is not | ||
52 | * elided as the EPLL can be either sourced by the XTAL or EXTCLK and as | ||
53 | * such directly equating the two source clocks is impossible. | ||
54 | */ | ||
55 | struct clk clk_mpllref = { | ||
56 | .name = "mpllref", | ||
57 | .parent = &clk_xtal, | ||
58 | }; | ||
59 | |||
60 | static struct clk *clk_epllref_sources[] = { | ||
61 | [0] = &clk_mpllref, | ||
62 | [1] = &clk_mpllref, | ||
63 | [2] = &clk_xtal, | ||
64 | [3] = &clk_ext, | ||
65 | }; | ||
66 | |||
67 | struct clksrc_clk clk_epllref = { | ||
68 | .clk = { | ||
69 | .name = "epllref", | ||
70 | }, | ||
71 | .sources = &(struct clksrc_sources) { | ||
72 | .sources = clk_epllref_sources, | ||
73 | .nr_sources = ARRAY_SIZE(clk_epllref_sources), | ||
74 | }, | ||
75 | .reg_src = { .reg = S3C2443_CLKSRC, .size = 2, .shift = 7 }, | ||
76 | }; | ||
77 | |||
78 | /* esysclk | ||
79 | * | ||
80 | * this is sourced from either the EPLL or the EPLLref clock | ||
81 | */ | ||
82 | |||
83 | static struct clk *clk_sysclk_sources[] = { | ||
84 | [0] = &clk_epllref.clk, | ||
85 | [1] = &clk_epll, | ||
86 | }; | ||
87 | |||
88 | struct clksrc_clk clk_esysclk = { | ||
89 | .clk = { | ||
90 | .name = "esysclk", | ||
91 | .parent = &clk_epll, | ||
92 | }, | ||
93 | .sources = &(struct clksrc_sources) { | ||
94 | .sources = clk_sysclk_sources, | ||
95 | .nr_sources = ARRAY_SIZE(clk_sysclk_sources), | ||
96 | }, | ||
97 | .reg_src = { .reg = S3C2443_CLKSRC, .size = 1, .shift = 6 }, | ||
98 | }; | ||
99 | |||
100 | static unsigned long s3c2443_getrate_mdivclk(struct clk *clk) | ||
101 | { | ||
102 | unsigned long parent_rate = clk_get_rate(clk->parent); | ||
103 | unsigned long div = __raw_readl(S3C2443_CLKDIV0); | ||
104 | |||
105 | div &= S3C2443_CLKDIV0_EXTDIV_MASK; | ||
106 | div >>= (S3C2443_CLKDIV0_EXTDIV_SHIFT-1); /* x2 */ | ||
107 | |||
108 | return parent_rate / (div + 1); | ||
109 | } | ||
110 | |||
111 | static struct clk clk_mdivclk = { | ||
112 | .name = "mdivclk", | ||
113 | .parent = &clk_mpllref, | ||
114 | .ops = &(struct clk_ops) { | ||
115 | .get_rate = s3c2443_getrate_mdivclk, | ||
116 | }, | ||
117 | }; | ||
118 | |||
119 | static struct clk *clk_msysclk_sources[] = { | ||
120 | [0] = &clk_mpllref, | ||
121 | [1] = &clk_mpll, | ||
122 | [2] = &clk_mdivclk, | ||
123 | [3] = &clk_mpllref, | ||
124 | }; | ||
125 | |||
126 | struct clksrc_clk clk_msysclk = { | ||
127 | .clk = { | ||
128 | .name = "msysclk", | ||
129 | .parent = &clk_xtal, | ||
130 | }, | ||
131 | .sources = &(struct clksrc_sources) { | ||
132 | .sources = clk_msysclk_sources, | ||
133 | .nr_sources = ARRAY_SIZE(clk_msysclk_sources), | ||
134 | }, | ||
135 | .reg_src = { .reg = S3C2443_CLKSRC, .size = 2, .shift = 3 }, | ||
136 | }; | ||
137 | |||
138 | /* prediv | ||
139 | * | ||
140 | * this divides the msysclk down to pass to h/p/etc. | ||
141 | */ | ||
142 | |||
143 | static unsigned long s3c2443_prediv_getrate(struct clk *clk) | ||
144 | { | ||
145 | unsigned long rate = clk_get_rate(clk->parent); | ||
146 | unsigned long clkdiv0 = __raw_readl(S3C2443_CLKDIV0); | ||
147 | |||
148 | clkdiv0 &= S3C2443_CLKDIV0_PREDIV_MASK; | ||
149 | clkdiv0 >>= S3C2443_CLKDIV0_PREDIV_SHIFT; | ||
150 | |||
151 | return rate / (clkdiv0 + 1); | ||
152 | } | ||
153 | |||
154 | static struct clk clk_prediv = { | ||
155 | .name = "prediv", | ||
156 | .parent = &clk_msysclk.clk, | ||
157 | .ops = &(struct clk_ops) { | ||
158 | .get_rate = s3c2443_prediv_getrate, | ||
159 | }, | ||
160 | }; | ||
161 | |||
162 | /* armdiv | ||
163 | * | ||
164 | * this clock is sourced from msysclk and can have a number of | ||
165 | * divider values applied to it to then be fed into armclk. | ||
166 | */ | ||
167 | |||
168 | static unsigned int *armdiv; | ||
169 | static int nr_armdiv; | ||
170 | static int armdivmask; | ||
171 | |||
172 | static unsigned long s3c2443_armclk_roundrate(struct clk *clk, | ||
173 | unsigned long rate) | ||
174 | { | ||
175 | unsigned long parent = clk_get_rate(clk->parent); | ||
176 | unsigned long calc; | ||
177 | unsigned best = 256; /* bigger than any value */ | ||
178 | unsigned div; | ||
179 | int ptr; | ||
180 | |||
181 | if (!nr_armdiv) | ||
182 | return -EINVAL; | ||
183 | |||
184 | for (ptr = 0; ptr < nr_armdiv; ptr++) { | ||
185 | div = armdiv[ptr]; | ||
186 | if (div) { | ||
187 | /* cpufreq provides 266mhz as 266666000 not 266666666 */ | ||
188 | calc = (parent / div / 1000) * 1000; | ||
189 | if (calc <= rate && div < best) | ||
190 | best = div; | ||
191 | } | ||
192 | } | ||
193 | |||
194 | return parent / best; | ||
195 | } | ||
196 | |||
197 | static unsigned long s3c2443_armclk_getrate(struct clk *clk) | ||
198 | { | ||
199 | unsigned long rate = clk_get_rate(clk->parent); | ||
200 | unsigned long clkcon0; | ||
201 | int val; | ||
202 | |||
203 | if (!nr_armdiv || !armdivmask) | ||
204 | return -EINVAL; | ||
205 | |||
206 | clkcon0 = __raw_readl(S3C2443_CLKDIV0); | ||
207 | clkcon0 &= armdivmask; | ||
208 | val = clkcon0 >> S3C2443_CLKDIV0_ARMDIV_SHIFT; | ||
209 | |||
210 | return rate / armdiv[val]; | ||
211 | } | ||
212 | |||
213 | static int s3c2443_armclk_setrate(struct clk *clk, unsigned long rate) | ||
214 | { | ||
215 | unsigned long parent = clk_get_rate(clk->parent); | ||
216 | unsigned long calc; | ||
217 | unsigned div; | ||
218 | unsigned best = 256; /* bigger than any value */ | ||
219 | int ptr; | ||
220 | int val = -1; | ||
221 | |||
222 | if (!nr_armdiv || !armdivmask) | ||
223 | return -EINVAL; | ||
224 | |||
225 | for (ptr = 0; ptr < nr_armdiv; ptr++) { | ||
226 | div = armdiv[ptr]; | ||
227 | if (div) { | ||
228 | /* cpufreq provides 266mhz as 266666000 not 266666666 */ | ||
229 | calc = (parent / div / 1000) * 1000; | ||
230 | if (calc <= rate && div < best) { | ||
231 | best = div; | ||
232 | val = ptr; | ||
233 | } | ||
234 | } | ||
235 | } | ||
236 | |||
237 | if (val >= 0) { | ||
238 | unsigned long clkcon0; | ||
239 | |||
240 | clkcon0 = __raw_readl(S3C2443_CLKDIV0); | ||
241 | clkcon0 &= ~armdivmask; | ||
242 | clkcon0 |= val << S3C2443_CLKDIV0_ARMDIV_SHIFT; | ||
243 | __raw_writel(clkcon0, S3C2443_CLKDIV0); | ||
244 | } | ||
245 | |||
246 | return (val == -1) ? -EINVAL : 0; | ||
247 | } | ||
248 | |||
249 | static struct clk clk_armdiv = { | ||
250 | .name = "armdiv", | ||
251 | .parent = &clk_msysclk.clk, | ||
252 | .ops = &(struct clk_ops) { | ||
253 | .round_rate = s3c2443_armclk_roundrate, | ||
254 | .get_rate = s3c2443_armclk_getrate, | ||
255 | .set_rate = s3c2443_armclk_setrate, | ||
256 | }, | ||
257 | }; | ||
258 | |||
259 | /* armclk | ||
260 | * | ||
261 | * this is the clock fed into the ARM core itself, from armdiv or from hclk. | ||
262 | */ | ||
263 | |||
264 | static struct clk *clk_arm_sources[] = { | ||
265 | [0] = &clk_armdiv, | ||
266 | [1] = &clk_h, | ||
267 | }; | ||
268 | |||
269 | static struct clksrc_clk clk_arm = { | ||
270 | .clk = { | ||
271 | .name = "armclk", | ||
272 | }, | ||
273 | .sources = &(struct clksrc_sources) { | ||
274 | .sources = clk_arm_sources, | ||
275 | .nr_sources = ARRAY_SIZE(clk_arm_sources), | ||
276 | }, | ||
277 | .reg_src = { .reg = S3C2443_CLKDIV0, .size = 1, .shift = 13 }, | ||
278 | }; | ||
279 | |||
280 | /* usbhost | ||
281 | * | ||
282 | * usb host bus-clock, usually 48MHz to provide USB bus clock timing | ||
283 | */ | ||
284 | |||
285 | static struct clksrc_clk clk_usb_bus_host = { | ||
286 | .clk = { | ||
287 | .name = "usb-bus-host-parent", | ||
288 | .parent = &clk_esysclk.clk, | ||
289 | .ctrlbit = S3C2443_SCLKCON_USBHOST, | ||
290 | .enable = s3c2443_clkcon_enable_s, | ||
291 | }, | ||
292 | .reg_div = { .reg = S3C2443_CLKDIV1, .size = 2, .shift = 4 }, | ||
293 | }; | ||
294 | |||
295 | /* common clksrc clocks */ | ||
296 | |||
297 | static struct clksrc_clk clksrc_clks[] = { | ||
298 | { | ||
299 | /* camera interface bus-clock, divided down from esysclk */ | ||
300 | .clk = { | ||
301 | .name = "camif-upll", /* same as 2440 name */ | ||
302 | .parent = &clk_esysclk.clk, | ||
303 | .ctrlbit = S3C2443_SCLKCON_CAMCLK, | ||
304 | .enable = s3c2443_clkcon_enable_s, | ||
305 | }, | ||
306 | .reg_div = { .reg = S3C2443_CLKDIV1, .size = 4, .shift = 26 }, | ||
307 | }, { | ||
308 | .clk = { | ||
309 | .name = "display-if", | ||
310 | .parent = &clk_esysclk.clk, | ||
311 | .ctrlbit = S3C2443_SCLKCON_DISPCLK, | ||
312 | .enable = s3c2443_clkcon_enable_s, | ||
313 | }, | ||
314 | .reg_div = { .reg = S3C2443_CLKDIV1, .size = 8, .shift = 16 }, | ||
315 | }, | ||
316 | }; | ||
317 | |||
318 | static struct clksrc_clk clk_esys_uart = { | ||
319 | /* ART baud-rate clock sourced from esysclk via a divisor */ | ||
320 | .clk = { | ||
321 | .name = "uartclk", | ||
322 | .parent = &clk_esysclk.clk, | ||
323 | }, | ||
324 | .reg_div = { .reg = S3C2443_CLKDIV1, .size = 4, .shift = 8 }, | ||
325 | }; | ||
326 | |||
327 | static struct clk clk_i2s_ext = { | ||
328 | .name = "i2s-ext", | ||
329 | }; | ||
330 | |||
331 | /* i2s_eplldiv | ||
332 | * | ||
333 | * This clock is the output from the I2S divisor of ESYSCLK, and is separate | ||
334 | * from the mux that comes after it (cannot merge into one single clock) | ||
335 | */ | ||
336 | |||
337 | static struct clksrc_clk clk_i2s_eplldiv = { | ||
338 | .clk = { | ||
339 | .name = "i2s-eplldiv", | ||
340 | .parent = &clk_esysclk.clk, | ||
341 | }, | ||
342 | .reg_div = { .reg = S3C2443_CLKDIV1, .size = 4, .shift = 12, }, | ||
343 | }; | ||
344 | |||
345 | /* i2s-ref | ||
346 | * | ||
347 | * i2s bus reference clock, selectable from external, esysclk or epllref | ||
348 | * | ||
349 | * Note, this used to be two clocks, but was compressed into one. | ||
350 | */ | ||
351 | |||
352 | static struct clk *clk_i2s_srclist[] = { | ||
353 | [0] = &clk_i2s_eplldiv.clk, | ||
354 | [1] = &clk_i2s_ext, | ||
355 | [2] = &clk_epllref.clk, | ||
356 | [3] = &clk_epllref.clk, | ||
357 | }; | ||
358 | |||
359 | static struct clksrc_clk clk_i2s = { | ||
360 | .clk = { | ||
361 | .name = "i2s-if", | ||
362 | .ctrlbit = S3C2443_SCLKCON_I2SCLK, | ||
363 | .enable = s3c2443_clkcon_enable_s, | ||
364 | |||
365 | }, | ||
366 | .sources = &(struct clksrc_sources) { | ||
367 | .sources = clk_i2s_srclist, | ||
368 | .nr_sources = ARRAY_SIZE(clk_i2s_srclist), | ||
369 | }, | ||
370 | .reg_src = { .reg = S3C2443_CLKSRC, .size = 2, .shift = 14 }, | ||
371 | }; | ||
372 | |||
373 | static struct clk init_clocks_off[] = { | ||
374 | { | ||
375 | .name = "iis", | ||
376 | .parent = &clk_p, | ||
377 | .enable = s3c2443_clkcon_enable_p, | ||
378 | .ctrlbit = S3C2443_PCLKCON_IIS, | ||
379 | }, { | ||
380 | .name = "hsspi", | ||
381 | .parent = &clk_p, | ||
382 | .enable = s3c2443_clkcon_enable_p, | ||
383 | .ctrlbit = S3C2443_PCLKCON_HSSPI, | ||
384 | }, { | ||
385 | .name = "adc", | ||
386 | .parent = &clk_p, | ||
387 | .enable = s3c2443_clkcon_enable_p, | ||
388 | .ctrlbit = S3C2443_PCLKCON_ADC, | ||
389 | }, { | ||
390 | .name = "i2c", | ||
391 | .parent = &clk_p, | ||
392 | .enable = s3c2443_clkcon_enable_p, | ||
393 | .ctrlbit = S3C2443_PCLKCON_IIC, | ||
394 | } | ||
395 | }; | ||
396 | |||
397 | static struct clk init_clocks[] = { | ||
398 | { | ||
399 | .name = "dma", | ||
400 | .parent = &clk_h, | ||
401 | .enable = s3c2443_clkcon_enable_h, | ||
402 | .ctrlbit = S3C2443_HCLKCON_DMA0, | ||
403 | }, { | ||
404 | .name = "dma", | ||
405 | .parent = &clk_h, | ||
406 | .enable = s3c2443_clkcon_enable_h, | ||
407 | .ctrlbit = S3C2443_HCLKCON_DMA1, | ||
408 | }, { | ||
409 | .name = "dma", | ||
410 | .parent = &clk_h, | ||
411 | .enable = s3c2443_clkcon_enable_h, | ||
412 | .ctrlbit = S3C2443_HCLKCON_DMA2, | ||
413 | }, { | ||
414 | .name = "dma", | ||
415 | .parent = &clk_h, | ||
416 | .enable = s3c2443_clkcon_enable_h, | ||
417 | .ctrlbit = S3C2443_HCLKCON_DMA3, | ||
418 | }, { | ||
419 | .name = "dma", | ||
420 | .parent = &clk_h, | ||
421 | .enable = s3c2443_clkcon_enable_h, | ||
422 | .ctrlbit = S3C2443_HCLKCON_DMA4, | ||
423 | }, { | ||
424 | .name = "dma", | ||
425 | .parent = &clk_h, | ||
426 | .enable = s3c2443_clkcon_enable_h, | ||
427 | .ctrlbit = S3C2443_HCLKCON_DMA5, | ||
428 | }, { | ||
429 | .name = "gpio", | ||
430 | .parent = &clk_p, | ||
431 | .enable = s3c2443_clkcon_enable_p, | ||
432 | .ctrlbit = S3C2443_PCLKCON_GPIO, | ||
433 | }, { | ||
434 | .name = "usb-host", | ||
435 | .parent = &clk_h, | ||
436 | .enable = s3c2443_clkcon_enable_h, | ||
437 | .ctrlbit = S3C2443_HCLKCON_USBH, | ||
438 | }, { | ||
439 | .name = "usb-device", | ||
440 | .parent = &clk_h, | ||
441 | .enable = s3c2443_clkcon_enable_h, | ||
442 | .ctrlbit = S3C2443_HCLKCON_USBD, | ||
443 | }, { | ||
444 | .name = "lcd", | ||
445 | .parent = &clk_h, | ||
446 | .enable = s3c2443_clkcon_enable_h, | ||
447 | .ctrlbit = S3C2443_HCLKCON_LCDC, | ||
448 | |||
449 | }, { | ||
450 | .name = "timers", | ||
451 | .parent = &clk_p, | ||
452 | .enable = s3c2443_clkcon_enable_p, | ||
453 | .ctrlbit = S3C2443_PCLKCON_PWMT, | ||
454 | }, { | ||
455 | .name = "cfc", | ||
456 | .parent = &clk_h, | ||
457 | .enable = s3c2443_clkcon_enable_h, | ||
458 | .ctrlbit = S3C2443_HCLKCON_CFC, | ||
459 | }, { | ||
460 | .name = "ssmc", | ||
461 | .parent = &clk_h, | ||
462 | .enable = s3c2443_clkcon_enable_h, | ||
463 | .ctrlbit = S3C2443_HCLKCON_SSMC, | ||
464 | }, { | ||
465 | .name = "uart", | ||
466 | .devname = "s3c2440-uart.0", | ||
467 | .parent = &clk_p, | ||
468 | .enable = s3c2443_clkcon_enable_p, | ||
469 | .ctrlbit = S3C2443_PCLKCON_UART0, | ||
470 | }, { | ||
471 | .name = "uart", | ||
472 | .devname = "s3c2440-uart.1", | ||
473 | .parent = &clk_p, | ||
474 | .enable = s3c2443_clkcon_enable_p, | ||
475 | .ctrlbit = S3C2443_PCLKCON_UART1, | ||
476 | }, { | ||
477 | .name = "uart", | ||
478 | .devname = "s3c2440-uart.2", | ||
479 | .parent = &clk_p, | ||
480 | .enable = s3c2443_clkcon_enable_p, | ||
481 | .ctrlbit = S3C2443_PCLKCON_UART2, | ||
482 | }, { | ||
483 | .name = "uart", | ||
484 | .devname = "s3c2440-uart.3", | ||
485 | .parent = &clk_p, | ||
486 | .enable = s3c2443_clkcon_enable_p, | ||
487 | .ctrlbit = S3C2443_PCLKCON_UART3, | ||
488 | }, { | ||
489 | .name = "rtc", | ||
490 | .parent = &clk_p, | ||
491 | .enable = s3c2443_clkcon_enable_p, | ||
492 | .ctrlbit = S3C2443_PCLKCON_RTC, | ||
493 | }, { | ||
494 | .name = "watchdog", | ||
495 | .parent = &clk_p, | ||
496 | .ctrlbit = S3C2443_PCLKCON_WDT, | ||
497 | }, { | ||
498 | .name = "ac97", | ||
499 | .parent = &clk_p, | ||
500 | .ctrlbit = S3C2443_PCLKCON_AC97, | ||
501 | }, { | ||
502 | .name = "nand", | ||
503 | .parent = &clk_h, | ||
504 | }, { | ||
505 | .name = "usb-bus-host", | ||
506 | .parent = &clk_usb_bus_host.clk, | ||
507 | } | ||
508 | }; | ||
509 | |||
510 | static struct clk hsmmc1_clk = { | ||
511 | .name = "hsmmc", | ||
512 | .devname = "s3c-sdhci.1", | ||
513 | .parent = &clk_h, | ||
514 | .enable = s3c2443_clkcon_enable_h, | ||
515 | .ctrlbit = S3C2443_HCLKCON_HSMMC, | ||
516 | }; | ||
517 | |||
518 | static inline unsigned long s3c2443_get_hdiv(unsigned long clkcon0) | ||
519 | { | ||
520 | clkcon0 &= S3C2443_CLKDIV0_HCLKDIV_MASK; | ||
521 | |||
522 | return clkcon0 + 1; | ||
523 | } | ||
524 | |||
525 | /* EPLLCON compatible enough to get on/off information */ | ||
526 | |||
527 | void __init_or_cpufreq s3c2443_common_setup_clocks(pll_fn get_mpll) | ||
528 | { | ||
529 | unsigned long epllcon = __raw_readl(S3C2443_EPLLCON); | ||
530 | unsigned long mpllcon = __raw_readl(S3C2443_MPLLCON); | ||
531 | unsigned long clkdiv0 = __raw_readl(S3C2443_CLKDIV0); | ||
532 | struct clk *xtal_clk; | ||
533 | unsigned long xtal; | ||
534 | unsigned long pll; | ||
535 | unsigned long fclk; | ||
536 | unsigned long hclk; | ||
537 | unsigned long pclk; | ||
538 | int ptr; | ||
539 | |||
540 | xtal_clk = clk_get(NULL, "xtal"); | ||
541 | xtal = clk_get_rate(xtal_clk); | ||
542 | clk_put(xtal_clk); | ||
543 | |||
544 | pll = get_mpll(mpllcon, xtal); | ||
545 | clk_msysclk.clk.rate = pll; | ||
546 | |||
547 | fclk = clk_get_rate(&clk_armdiv); | ||
548 | hclk = s3c2443_prediv_getrate(&clk_prediv); | ||
549 | hclk /= s3c2443_get_hdiv(clkdiv0); | ||
550 | pclk = hclk / ((clkdiv0 & S3C2443_CLKDIV0_HALF_PCLK) ? 2 : 1); | ||
551 | |||
552 | s3c24xx_setup_clocks(fclk, hclk, pclk); | ||
553 | |||
554 | printk("CPU: MPLL %s %ld.%03ld MHz, cpu %ld.%03ld MHz, mem %ld.%03ld MHz, pclk %ld.%03ld MHz\n", | ||
555 | (mpllcon & S3C2443_PLLCON_OFF) ? "off":"on", | ||
556 | print_mhz(pll), print_mhz(fclk), | ||
557 | print_mhz(hclk), print_mhz(pclk)); | ||
558 | |||
559 | for (ptr = 0; ptr < ARRAY_SIZE(clksrc_clks); ptr++) | ||
560 | s3c_set_clksrc(&clksrc_clks[ptr], true); | ||
561 | |||
562 | /* ensure usb bus clock is within correct rate of 48MHz */ | ||
563 | |||
564 | if (clk_get_rate(&clk_usb_bus_host.clk) != (48 * 1000 * 1000)) { | ||
565 | printk(KERN_INFO "Warning: USB host bus not at 48MHz\n"); | ||
566 | clk_set_rate(&clk_usb_bus_host.clk, 48*1000*1000); | ||
567 | } | ||
568 | |||
569 | printk("CPU: EPLL %s %ld.%03ld MHz, usb-bus %ld.%03ld MHz\n", | ||
570 | (epllcon & S3C2443_PLLCON_OFF) ? "off":"on", | ||
571 | print_mhz(clk_get_rate(&clk_epll)), | ||
572 | print_mhz(clk_get_rate(&clk_usb_bus))); | ||
573 | } | ||
574 | |||
575 | static struct clk *clks[] __initdata = { | ||
576 | &clk_prediv, | ||
577 | &clk_mpllref, | ||
578 | &clk_mdivclk, | ||
579 | &clk_ext, | ||
580 | &clk_epll, | ||
581 | &clk_usb_bus, | ||
582 | &clk_armdiv, | ||
583 | &hsmmc1_clk, | ||
584 | }; | ||
585 | |||
586 | static struct clksrc_clk *clksrcs[] __initdata = { | ||
587 | &clk_i2s_eplldiv, | ||
588 | &clk_i2s, | ||
589 | &clk_usb_bus_host, | ||
590 | &clk_epllref, | ||
591 | &clk_esysclk, | ||
592 | &clk_msysclk, | ||
593 | &clk_arm, | ||
594 | }; | ||
595 | |||
596 | static struct clk_lookup s3c2443_clk_lookup[] = { | ||
597 | CLKDEV_INIT(NULL, "clk_uart_baud1", &s3c24xx_uclk), | ||
598 | CLKDEV_INIT(NULL, "clk_uart_baud2", &clk_p), | ||
599 | CLKDEV_INIT(NULL, "clk_uart_baud3", &clk_esys_uart.clk), | ||
600 | CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.0", &hsmmc1_clk), | ||
601 | }; | ||
602 | |||
603 | void __init s3c2443_common_init_clocks(int xtal, pll_fn get_mpll, | ||
604 | unsigned int *divs, int nr_divs, | ||
605 | int divmask) | ||
606 | { | ||
607 | int ptr; | ||
608 | |||
609 | armdiv = divs; | ||
610 | nr_armdiv = nr_divs; | ||
611 | armdivmask = divmask; | ||
612 | |||
613 | /* s3c2443 parents h and p clocks from prediv */ | ||
614 | clk_h.parent = &clk_prediv; | ||
615 | clk_p.parent = &clk_prediv; | ||
616 | |||
617 | clk_usb_bus.parent = &clk_usb_bus_host.clk; | ||
618 | clk_epll.parent = &clk_epllref.clk; | ||
619 | |||
620 | s3c24xx_register_baseclocks(xtal); | ||
621 | s3c24xx_register_clocks(clks, ARRAY_SIZE(clks)); | ||
622 | |||
623 | for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++) | ||
624 | s3c_register_clksrc(clksrcs[ptr], 1); | ||
625 | |||
626 | s3c_register_clksrc(clksrc_clks, ARRAY_SIZE(clksrc_clks)); | ||
627 | s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks)); | ||
628 | |||
629 | /* See s3c2443/etc notes on disabling clocks at init time */ | ||
630 | s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off)); | ||
631 | s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off)); | ||
632 | clkdev_add_table(s3c2443_clk_lookup, ARRAY_SIZE(s3c2443_clk_lookup)); | ||
633 | |||
634 | s3c2443_common_setup_clocks(get_mpll); | ||
635 | } | ||