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