Merge branch 'topic/jack' into for-linus
[pandora-kernel.git] / arch / arm / mach-s3c2443 / clock.c
1 /* linux/arch/arm/mach-s3c2443/clock.c
2  *
3  * Copyright (c) 2007, 2010 Simtec Electronics
4  *      Ben Dooks <ben@simtec.co.uk>
5  *
6  * S3C2443 Clock control 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 as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21 */
22
23 #include <linux/init.h>
24 #include <linux/module.h>
25 #include <linux/kernel.h>
26 #include <linux/list.h>
27 #include <linux/errno.h>
28 #include <linux/err.h>
29 #include <linux/sysdev.h>
30 #include <linux/clk.h>
31 #include <linux/mutex.h>
32 #include <linux/serial_core.h>
33 #include <linux/io.h>
34
35 #include <asm/mach/map.h>
36
37 #include <mach/hardware.h>
38
39 #include <mach/regs-s3c2443-clock.h>
40
41 #include <plat/cpu-freq.h>
42
43 #include <plat/s3c2443.h>
44 #include <plat/clock.h>
45 #include <plat/clock-clksrc.h>
46 #include <plat/cpu.h>
47
48 /* We currently have to assume that the system is running
49  * from the XTPll input, and that all ***REFCLKs are being
50  * fed from it, as we cannot read the state of OM[4] from
51  * software.
52  *
53  * It would be possible for each board initialisation to
54  * set the correct muxing at initialisation
55 */
56
57 static int s3c2443_gate(void __iomem *reg, struct clk *clk, int enable)
58 {
59         u32 ctrlbit = clk->ctrlbit;
60         u32 con = __raw_readl(reg);
61
62         if (enable)
63                 con |= ctrlbit;
64         else
65                 con &= ~ctrlbit;
66
67         __raw_writel(con, reg);
68         return 0;
69 }
70
71 static int s3c2443_clkcon_enable_h(struct clk *clk, int enable)
72 {
73         return s3c2443_gate(S3C2443_HCLKCON, clk, enable);
74 }
75
76 static int s3c2443_clkcon_enable_p(struct clk *clk, int enable)
77 {
78         return s3c2443_gate(S3C2443_PCLKCON, clk, enable);
79 }
80
81 static int s3c2443_clkcon_enable_s(struct clk *clk, int enable)
82 {
83         return s3c2443_gate(S3C2443_SCLKCON, clk, enable);
84 }
85
86 /* clock selections */
87
88 /* mpllref is a direct descendant of clk_xtal by default, but it is not
89  * elided as the EPLL can be either sourced by the XTAL or EXTCLK and as
90  * such directly equating the two source clocks is impossible.
91  */
92 static struct clk clk_mpllref = {
93         .name           = "mpllref",
94         .parent         = &clk_xtal,
95         .id             = -1,
96 };
97
98 static struct clk clk_i2s_ext = {
99         .name           = "i2s-ext",
100         .id             = -1,
101 };
102
103 static struct clk *clk_epllref_sources[] = {
104         [0] = &clk_mpllref,
105         [1] = &clk_mpllref,
106         [2] = &clk_xtal,
107         [3] = &clk_ext,
108 };
109
110 static struct clksrc_clk clk_epllref = {
111         .clk    = {
112                 .name           = "epllref",
113                 .id             = -1,
114         },
115         .sources = &(struct clksrc_sources) {
116                 .sources = clk_epllref_sources,
117                 .nr_sources = ARRAY_SIZE(clk_epllref_sources),
118         },
119         .reg_src = { .reg = S3C2443_CLKSRC, .size = 2, .shift = 7 },
120 };
121
122 static unsigned long s3c2443_getrate_mdivclk(struct clk *clk)
123 {
124         unsigned long parent_rate = clk_get_rate(clk->parent);
125         unsigned long div = __raw_readl(S3C2443_CLKDIV0);
126
127         div  &= S3C2443_CLKDIV0_EXTDIV_MASK;
128         div >>= (S3C2443_CLKDIV0_EXTDIV_SHIFT-1);       /* x2 */
129
130         return parent_rate / (div + 1);
131 }
132
133 static struct clk clk_mdivclk = {
134         .name           = "mdivclk",
135         .parent         = &clk_mpllref,
136         .id             = -1,
137         .ops            = &(struct clk_ops) {
138                 .get_rate       = s3c2443_getrate_mdivclk,
139         },
140 };
141
142 static struct clk *clk_msysclk_sources[] = {
143         [0] = &clk_mpllref,
144         [1] = &clk_mpll,
145         [2] = &clk_mdivclk,
146         [3] = &clk_mpllref,
147 };
148
149 static struct clksrc_clk clk_msysclk = {
150         .clk    = {
151                 .name           = "msysclk",
152                 .parent         = &clk_xtal,
153                 .id             = -1,
154         },
155         .sources = &(struct clksrc_sources) {
156                 .sources = clk_msysclk_sources,
157                 .nr_sources = ARRAY_SIZE(clk_msysclk_sources),
158         },
159         .reg_src = { .reg = S3C2443_CLKSRC, .size = 2, .shift = 3 },
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 /* armdiv divisor table */
169
170 static unsigned int armdiv[16] = {
171         [S3C2443_CLKDIV0_ARMDIV_1 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]      = 1,
172         [S3C2443_CLKDIV0_ARMDIV_2 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]      = 2,
173         [S3C2443_CLKDIV0_ARMDIV_3 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]      = 3,
174         [S3C2443_CLKDIV0_ARMDIV_4 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]      = 4,
175         [S3C2443_CLKDIV0_ARMDIV_6 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]      = 6,
176         [S3C2443_CLKDIV0_ARMDIV_8 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]      = 8,
177         [S3C2443_CLKDIV0_ARMDIV_12 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]     = 12,
178         [S3C2443_CLKDIV0_ARMDIV_16 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]     = 16,
179 };
180
181 static inline unsigned int s3c2443_fclk_div(unsigned long clkcon0)
182 {
183         clkcon0 &= S3C2443_CLKDIV0_ARMDIV_MASK;
184
185         return armdiv[clkcon0 >> S3C2443_CLKDIV0_ARMDIV_SHIFT];
186 }
187
188 static unsigned long s3c2443_armclk_roundrate(struct clk *clk,
189                                               unsigned long rate)
190 {
191         unsigned long parent = clk_get_rate(clk->parent);
192         unsigned long calc;
193         unsigned best = 256; /* bigger than any value */
194         unsigned div;
195         int ptr;
196
197         for (ptr = 0; ptr < ARRAY_SIZE(armdiv); ptr++) {
198                 div = armdiv[ptr];
199                 calc = parent / div;
200                 if (calc <= rate && div < best)
201                         best = div;
202         }
203
204         return parent / best;
205 }
206
207 static int s3c2443_armclk_setrate(struct clk *clk, unsigned long rate)
208 {
209         unsigned long parent = clk_get_rate(clk->parent);
210         unsigned long calc;
211         unsigned div;
212         unsigned best = 256; /* bigger than any value */
213         int ptr;
214         int val = -1;
215
216         for (ptr = 0; ptr < ARRAY_SIZE(armdiv); ptr++) {
217                 div = armdiv[ptr];
218                 calc = parent / div;
219                 if (calc <= rate && div < best) {
220                         best = div;
221                         val = ptr;
222                 }
223         }
224
225         if (val >= 0) {
226                 unsigned long clkcon0;
227
228                 clkcon0 = __raw_readl(S3C2443_CLKDIV0);
229                 clkcon0 &= S3C2443_CLKDIV0_ARMDIV_MASK;
230                 clkcon0 |= val << S3C2443_CLKDIV0_ARMDIV_SHIFT;
231                 __raw_writel(clkcon0, S3C2443_CLKDIV0);
232         }
233
234         return (val == -1) ? -EINVAL : 0;
235 }
236
237 static struct clk clk_armdiv = {
238         .name           = "armdiv",
239         .id             = -1,
240         .parent         = &clk_msysclk.clk,
241         .ops            = &(struct clk_ops) {
242                 .round_rate = s3c2443_armclk_roundrate,
243                 .set_rate = s3c2443_armclk_setrate,
244         },
245 };
246
247 /* armclk
248  *
249  * this is the clock fed into the ARM core itself, from armdiv or from hclk.
250  */
251
252 static struct clk *clk_arm_sources[] = {
253         [0] = &clk_armdiv,
254         [1] = &clk_h,
255 };
256
257 static struct clksrc_clk clk_arm = {
258         .clk    = {
259                 .name           = "armclk",
260                 .id             = -1,
261         },
262         .sources = &(struct clksrc_sources) {
263                 .sources = clk_arm_sources,
264                 .nr_sources = ARRAY_SIZE(clk_arm_sources),
265         },
266         .reg_src = { .reg = S3C2443_CLKDIV0, .size = 1, .shift = 13 },
267 };
268
269 /* esysclk
270  *
271  * this is sourced from either the EPLL or the EPLLref clock
272 */
273
274 static struct clk *clk_sysclk_sources[] = {
275         [0] = &clk_epllref.clk,
276         [1] = &clk_epll,
277 };
278
279 static struct clksrc_clk clk_esysclk = {
280         .clk    = {
281                 .name           = "esysclk",
282                 .parent         = &clk_epll,
283                 .id             = -1,
284         },
285         .sources = &(struct clksrc_sources) {
286                 .sources = clk_sysclk_sources,
287                 .nr_sources = ARRAY_SIZE(clk_sysclk_sources),
288         },
289         .reg_src = { .reg = S3C2443_CLKSRC, .size = 1, .shift = 6 },
290 };
291
292 /* uartclk
293  *
294  * UART baud-rate clock sourced from esysclk via a divisor
295 */
296
297 static struct clksrc_clk clk_uart = {
298         .clk    = {
299                 .name           = "uartclk",
300                 .id             = -1,
301                 .parent         = &clk_esysclk.clk,
302         },
303         .reg_div = { .reg = S3C2443_CLKDIV1, .size = 4, .shift = 8 },
304 };
305
306
307 /* hsspi
308  *
309  * high-speed spi clock, sourced from esysclk
310 */
311
312 static struct clksrc_clk clk_hsspi = {
313         .clk    = {
314                 .name           = "hsspi",
315                 .id             = -1,
316                 .parent         = &clk_esysclk.clk,
317                 .ctrlbit        = S3C2443_SCLKCON_HSSPICLK,
318                 .enable         = s3c2443_clkcon_enable_s,
319         },
320         .reg_div = { .reg = S3C2443_CLKDIV1, .size = 2, .shift = 4 },
321 };
322
323 /* usbhost
324  *
325  * usb host bus-clock, usually 48MHz to provide USB bus clock timing
326 */
327
328 static struct clksrc_clk clk_usb_bus_host = {
329         .clk    = {
330                 .name           = "usb-bus-host-parent",
331                 .id             = -1,
332                 .parent         = &clk_esysclk.clk,
333                 .ctrlbit        = S3C2443_SCLKCON_USBHOST,
334                 .enable         = s3c2443_clkcon_enable_s,
335         },
336         .reg_div = { .reg = S3C2443_CLKDIV1, .size = 2, .shift = 4 },
337 };
338
339 /* clk_hsmcc_div
340  *
341  * this clock is sourced from epll, and is fed through a divider,
342  * to a mux controlled by sclkcon where either it or a extclk can
343  * be fed to the hsmmc block
344 */
345
346 static struct clksrc_clk clk_hsmmc_div = {
347         .clk    = {
348                 .name           = "hsmmc-div",
349                 .id             = -1,
350                 .parent         = &clk_esysclk.clk,
351         },
352         .reg_div = { .reg = S3C2443_CLKDIV1, .size = 2, .shift = 6 },
353 };
354
355 static int s3c2443_setparent_hsmmc(struct clk *clk, struct clk *parent)
356 {
357         unsigned long clksrc = __raw_readl(S3C2443_SCLKCON);
358
359         clksrc &= ~(S3C2443_SCLKCON_HSMMCCLK_EXT |
360                     S3C2443_SCLKCON_HSMMCCLK_EPLL);
361
362         if (parent == &clk_epll)
363                 clksrc |= S3C2443_SCLKCON_HSMMCCLK_EPLL;
364         else if (parent == &clk_ext)
365                 clksrc |= S3C2443_SCLKCON_HSMMCCLK_EXT;
366         else
367                 return -EINVAL;
368
369         if (clk->usage > 0) {
370                 __raw_writel(clksrc, S3C2443_SCLKCON);
371         }
372
373         clk->parent = parent;
374         return 0;
375 }
376
377 static int s3c2443_enable_hsmmc(struct clk *clk, int enable)
378 {
379         return s3c2443_setparent_hsmmc(clk, clk->parent);
380 }
381
382 static struct clk clk_hsmmc = {
383         .name           = "hsmmc-if",
384         .id             = -1,
385         .parent         = &clk_hsmmc_div.clk,
386         .enable         = s3c2443_enable_hsmmc,
387         .ops            = &(struct clk_ops) {
388                 .set_parent     = s3c2443_setparent_hsmmc,
389         },
390 };
391
392 /* i2s_eplldiv
393  *
394  * This clock is the output from the I2S divisor of ESYSCLK, and is seperate
395  * from the mux that comes after it (cannot merge into one single clock)
396 */
397
398 static struct clksrc_clk clk_i2s_eplldiv = {
399         .clk    = {
400                 .name           = "i2s-eplldiv",
401                 .id             = -1,
402                 .parent         = &clk_esysclk.clk,
403         },
404         .reg_div = { .reg = S3C2443_CLKDIV1, .size = 4, .shift = 12, },
405 };
406
407 /* i2s-ref
408  *
409  * i2s bus reference clock, selectable from external, esysclk or epllref
410  *
411  * Note, this used to be two clocks, but was compressed into one.
412 */
413
414 struct clk *clk_i2s_srclist[] = {
415         [0] = &clk_i2s_eplldiv.clk,
416         [1] = &clk_i2s_ext,
417         [2] = &clk_epllref.clk,
418         [3] = &clk_epllref.clk,
419 };
420
421 static struct clksrc_clk clk_i2s = {
422         .clk    = {
423                 .name           = "i2s-if",
424                 .id             = -1,
425                 .ctrlbit        = S3C2443_SCLKCON_I2SCLK,
426                 .enable         = s3c2443_clkcon_enable_s,
427
428         },
429         .sources = &(struct clksrc_sources) {
430                 .sources = clk_i2s_srclist,
431                 .nr_sources = ARRAY_SIZE(clk_i2s_srclist),
432         },
433         .reg_src = { .reg = S3C2443_CLKSRC, .size = 2, .shift = 14 },
434 };
435
436 /* cam-if
437  *
438  * camera interface bus-clock, divided down from esysclk
439 */
440
441 static struct clksrc_clk clk_cam = {
442         .clk    = {
443                 .name           = "camif-upll", /* same as 2440 name */
444                 .id             = -1,
445                 .parent         = &clk_esysclk.clk,
446                 .ctrlbit        = S3C2443_SCLKCON_CAMCLK,
447                 .enable         = s3c2443_clkcon_enable_s,
448         },
449         .reg_div = { .reg = S3C2443_CLKDIV1, .size = 4, .shift = 26 },
450 };
451
452 /* display-if
453  *
454  * display interface clock, divided from esysclk
455 */
456
457 static struct clksrc_clk clk_display = {
458         .clk    = {
459                 .name           = "display-if",
460                 .id             = -1,
461                 .parent         = &clk_esysclk.clk,
462                 .ctrlbit        = S3C2443_SCLKCON_DISPCLK,
463                 .enable         = s3c2443_clkcon_enable_s,
464         },
465         .reg_div = { .reg = S3C2443_CLKDIV1, .size = 8, .shift = 16 },
466 };
467
468 /* prediv
469  *
470  * this divides the msysclk down to pass to h/p/etc.
471  */
472
473 static unsigned long s3c2443_prediv_getrate(struct clk *clk)
474 {
475         unsigned long rate = clk_get_rate(clk->parent);
476         unsigned long clkdiv0 = __raw_readl(S3C2443_CLKDIV0);
477
478         clkdiv0 &= S3C2443_CLKDIV0_PREDIV_MASK;
479         clkdiv0 >>= S3C2443_CLKDIV0_PREDIV_SHIFT;
480
481         return rate / (clkdiv0 + 1);
482 }
483
484 static struct clk clk_prediv = {
485         .name           = "prediv",
486         .id             = -1,
487         .parent         = &clk_msysclk.clk,
488         .ops            = &(struct clk_ops) {
489                 .get_rate       = s3c2443_prediv_getrate,
490         },
491 };
492
493 /* standard clock definitions */
494
495 static struct clk init_clocks_disable[] = {
496         {
497                 .name           = "nand",
498                 .id             = -1,
499                 .parent         = &clk_h,
500         }, {
501                 .name           = "sdi",
502                 .id             = -1,
503                 .parent         = &clk_p,
504                 .enable         = s3c2443_clkcon_enable_p,
505                 .ctrlbit        = S3C2443_PCLKCON_SDI,
506         }, {
507                 .name           = "adc",
508                 .id             = -1,
509                 .parent         = &clk_p,
510                 .enable         = s3c2443_clkcon_enable_p,
511                 .ctrlbit        = S3C2443_PCLKCON_ADC,
512         }, {
513                 .name           = "i2c",
514                 .id             = -1,
515                 .parent         = &clk_p,
516                 .enable         = s3c2443_clkcon_enable_p,
517                 .ctrlbit        = S3C2443_PCLKCON_IIC,
518         }, {
519                 .name           = "iis",
520                 .id             = -1,
521                 .parent         = &clk_p,
522                 .enable         = s3c2443_clkcon_enable_p,
523                 .ctrlbit        = S3C2443_PCLKCON_IIS,
524         }, {
525                 .name           = "spi",
526                 .id             = 0,
527                 .parent         = &clk_p,
528                 .enable         = s3c2443_clkcon_enable_p,
529                 .ctrlbit        = S3C2443_PCLKCON_SPI0,
530         }, {
531                 .name           = "spi",
532                 .id             = 1,
533                 .parent         = &clk_p,
534                 .enable         = s3c2443_clkcon_enable_p,
535                 .ctrlbit        = S3C2443_PCLKCON_SPI1,
536         }
537 };
538
539 static struct clk init_clocks[] = {
540         {
541                 .name           = "dma",
542                 .id             = 0,
543                 .parent         = &clk_h,
544                 .enable         = s3c2443_clkcon_enable_h,
545                 .ctrlbit        = S3C2443_HCLKCON_DMA0,
546         }, {
547                 .name           = "dma",
548                 .id             = 1,
549                 .parent         = &clk_h,
550                 .enable         = s3c2443_clkcon_enable_h,
551                 .ctrlbit        = S3C2443_HCLKCON_DMA1,
552         }, {
553                 .name           = "dma",
554                 .id             = 2,
555                 .parent         = &clk_h,
556                 .enable         = s3c2443_clkcon_enable_h,
557                 .ctrlbit        = S3C2443_HCLKCON_DMA2,
558         }, {
559                 .name           = "dma",
560                 .id             = 3,
561                 .parent         = &clk_h,
562                 .enable         = s3c2443_clkcon_enable_h,
563                 .ctrlbit        = S3C2443_HCLKCON_DMA3,
564         }, {
565                 .name           = "dma",
566                 .id             = 4,
567                 .parent         = &clk_h,
568                 .enable         = s3c2443_clkcon_enable_h,
569                 .ctrlbit        = S3C2443_HCLKCON_DMA4,
570         }, {
571                 .name           = "dma",
572                 .id             = 5,
573                 .parent         = &clk_h,
574                 .enable         = s3c2443_clkcon_enable_h,
575                 .ctrlbit        = S3C2443_HCLKCON_DMA5,
576         }, {
577                 .name           = "lcd",
578                 .id             = -1,
579                 .parent         = &clk_h,
580                 .enable         = s3c2443_clkcon_enable_h,
581                 .ctrlbit        = S3C2443_HCLKCON_LCDC,
582         }, {
583                 .name           = "gpio",
584                 .id             = -1,
585                 .parent         = &clk_p,
586                 .enable         = s3c2443_clkcon_enable_p,
587                 .ctrlbit        = S3C2443_PCLKCON_GPIO,
588         }, {
589                 .name           = "usb-host",
590                 .id             = -1,
591                 .parent         = &clk_h,
592                 .enable         = s3c2443_clkcon_enable_h,
593                 .ctrlbit        = S3C2443_HCLKCON_USBH,
594         }, {
595                 .name           = "usb-device",
596                 .id             = -1,
597                 .parent         = &clk_h,
598                 .enable         = s3c2443_clkcon_enable_h,
599                 .ctrlbit        = S3C2443_HCLKCON_USBD,
600         }, {
601                 .name           = "hsmmc",
602                 .id             = -1,
603                 .parent         = &clk_h,
604                 .enable         = s3c2443_clkcon_enable_h,
605                 .ctrlbit        = S3C2443_HCLKCON_HSMMC,
606         }, {
607                 .name           = "cfc",
608                 .id             = -1,
609                 .parent         = &clk_h,
610                 .enable         = s3c2443_clkcon_enable_h,
611                 .ctrlbit        = S3C2443_HCLKCON_CFC,
612         }, {
613                 .name           = "ssmc",
614                 .id             = -1,
615                 .parent         = &clk_h,
616                 .enable         = s3c2443_clkcon_enable_h,
617                 .ctrlbit        = S3C2443_HCLKCON_SSMC,
618         }, {
619                 .name           = "timers",
620                 .id             = -1,
621                 .parent         = &clk_p,
622                 .enable         = s3c2443_clkcon_enable_p,
623                 .ctrlbit        = S3C2443_PCLKCON_PWMT,
624         }, {
625                 .name           = "uart",
626                 .id             = 0,
627                 .parent         = &clk_p,
628                 .enable         = s3c2443_clkcon_enable_p,
629                 .ctrlbit        = S3C2443_PCLKCON_UART0,
630         }, {
631                 .name           = "uart",
632                 .id             = 1,
633                 .parent         = &clk_p,
634                 .enable         = s3c2443_clkcon_enable_p,
635                 .ctrlbit        = S3C2443_PCLKCON_UART1,
636         }, {
637                 .name           = "uart",
638                 .id             = 2,
639                 .parent         = &clk_p,
640                 .enable         = s3c2443_clkcon_enable_p,
641                 .ctrlbit        = S3C2443_PCLKCON_UART2,
642         }, {
643                 .name           = "uart",
644                 .id             = 3,
645                 .parent         = &clk_p,
646                 .enable         = s3c2443_clkcon_enable_p,
647                 .ctrlbit        = S3C2443_PCLKCON_UART3,
648         }, {
649                 .name           = "rtc",
650                 .id             = -1,
651                 .parent         = &clk_p,
652                 .enable         = s3c2443_clkcon_enable_p,
653                 .ctrlbit        = S3C2443_PCLKCON_RTC,
654         }, {
655                 .name           = "watchdog",
656                 .id             = -1,
657                 .parent         = &clk_p,
658                 .ctrlbit        = S3C2443_PCLKCON_WDT,
659         }, {
660                 .name           = "usb-bus-host",
661                 .id             = -1,
662                 .parent         = &clk_usb_bus_host.clk,
663         }, {
664                 .name           = "ac97",
665                 .id             = -1,
666                 .parent         = &clk_p,
667                 .ctrlbit        = S3C2443_PCLKCON_AC97,
668         }
669 };
670
671 /* clocks to add where we need to check their parentage */
672
673 static struct clksrc_clk __initdata *init_list[] = {
674         &clk_epllref, /* should be first */
675         &clk_esysclk,
676         &clk_msysclk,
677         &clk_arm,
678         &clk_i2s_eplldiv,
679         &clk_i2s,
680         &clk_cam,
681         &clk_uart,
682         &clk_display,
683         &clk_hsmmc_div,
684         &clk_usb_bus_host,
685 };
686
687 static void __init s3c2443_clk_initparents(void)
688 {
689         int ptr;
690
691         for (ptr = 0; ptr < ARRAY_SIZE(init_list); ptr++)
692                 s3c_set_clksrc(init_list[ptr], true);
693 }
694
695 static inline unsigned long s3c2443_get_hdiv(unsigned long clkcon0)
696 {
697         clkcon0 &= S3C2443_CLKDIV0_HCLKDIV_MASK;
698
699         return clkcon0 + 1;
700 }
701
702 /* clocks to add straight away */
703
704 static struct clksrc_clk *clksrcs[] __initdata = {
705         &clk_usb_bus_host,
706         &clk_epllref,
707         &clk_esysclk,
708         &clk_msysclk,
709         &clk_arm,
710         &clk_uart,
711         &clk_display,
712         &clk_cam,
713         &clk_i2s_eplldiv,
714         &clk_i2s,
715         &clk_hsspi,
716         &clk_hsmmc_div,
717 };
718
719 static struct clk *clks[] __initdata = {
720         &clk_ext,
721         &clk_epll,
722         &clk_usb_bus,
723         &clk_mpllref,
724         &clk_hsmmc,
725         &clk_armdiv,
726         &clk_prediv,
727 };
728
729 void __init_or_cpufreq s3c2443_setup_clocks(void)
730 {
731         unsigned long mpllcon = __raw_readl(S3C2443_MPLLCON);
732         unsigned long clkdiv0 = __raw_readl(S3C2443_CLKDIV0);
733         struct clk *xtal_clk;
734         unsigned long xtal;
735         unsigned long pll;
736         unsigned long fclk;
737         unsigned long hclk;
738         unsigned long pclk;
739
740         xtal_clk = clk_get(NULL, "xtal");
741         xtal = clk_get_rate(xtal_clk);
742         clk_put(xtal_clk);
743
744         pll = s3c2443_get_mpll(mpllcon, xtal);
745         clk_msysclk.clk.rate = pll;
746
747         fclk = pll / s3c2443_fclk_div(clkdiv0);
748         hclk = s3c2443_prediv_getrate(&clk_prediv);
749         hclk /= s3c2443_get_hdiv(clkdiv0);
750         pclk = hclk / ((clkdiv0 & S3C2443_CLKDIV0_HALF_PCLK) ? 2 : 1);
751
752         s3c24xx_setup_clocks(fclk, hclk, pclk);
753
754         printk("S3C2443: mpll %s %ld.%03ld MHz, cpu %ld.%03ld MHz, mem %ld.%03ld MHz, pclk %ld.%03ld MHz\n",
755                (mpllcon & S3C2443_PLLCON_OFF) ? "off":"on",
756                print_mhz(pll), print_mhz(fclk),
757                print_mhz(hclk), print_mhz(pclk));
758
759         s3c24xx_setup_clocks(fclk, hclk, pclk);
760 }
761
762 void __init s3c2443_init_clocks(int xtal)
763 {
764         struct clk *clkp;
765         unsigned long epllcon = __raw_readl(S3C2443_EPLLCON);
766         int ret;
767         int ptr;
768
769         /* s3c2443 parents h and p clocks from prediv */
770         clk_h.parent = &clk_prediv;
771         clk_p.parent = &clk_prediv;
772
773         s3c24xx_register_baseclocks(xtal);
774         s3c2443_setup_clocks();
775         s3c2443_clk_initparents();
776
777         for (ptr = 0; ptr < ARRAY_SIZE(clks); ptr++) {
778                 clkp = clks[ptr];
779
780                 ret = s3c24xx_register_clock(clkp);
781                 if (ret < 0) {
782                         printk(KERN_ERR "Failed to register clock %s (%d)\n",
783                                clkp->name, ret);
784                 }
785         }
786
787         for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
788                 s3c_register_clksrc(clksrcs[ptr], 1);
789
790         clk_epll.rate = s3c2443_get_epll(epllcon, xtal);
791         clk_epll.parent = &clk_epllref.clk;
792         clk_usb_bus.parent = &clk_usb_bus_host.clk;
793
794         /* ensure usb bus clock is within correct rate of 48MHz */
795
796         if (clk_get_rate(&clk_usb_bus_host.clk) != (48 * 1000 * 1000)) {
797                 printk(KERN_INFO "Warning: USB host bus not at 48MHz\n");
798                 clk_set_rate(&clk_usb_bus_host.clk, 48*1000*1000);
799         }
800
801         printk("S3C2443: epll %s %ld.%03ld MHz, usb-bus %ld.%03ld MHz\n",
802                (epllcon & S3C2443_PLLCON_OFF) ? "off":"on",
803                print_mhz(clk_get_rate(&clk_epll)),
804                print_mhz(clk_get_rate(&clk_usb_bus)));
805
806         /* register clocks from clock array */
807
808         s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
809
810         /* We must be careful disabling the clocks we are not intending to
811          * be using at boot time, as subsystems such as the LCD which do
812          * their own DMA requests to the bus can cause the system to lockup
813          * if they where in the middle of requesting bus access.
814          *
815          * Disabling the LCD clock if the LCD is active is very dangerous,
816          * and therefore the bootloader should be careful to not enable
817          * the LCD clock if it is not needed.
818         */
819
820         /* install (and disable) the clocks we do not need immediately */
821
822         clkp = init_clocks_disable;
823         for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
824
825                 ret = s3c24xx_register_clock(clkp);
826                 if (ret < 0) {
827                         printk(KERN_ERR "Failed to register clock %s (%d)\n",
828                                clkp->name, ret);
829                 }
830
831                 (clkp->enable)(clkp, 0);
832         }
833
834         s3c_pwmclk_init();
835 }