[ARM] S3C2443: Add armdiv and arm clocks
[pandora-kernel.git] / arch / arm / mach-s3c2443 / clock.c
1 /* linux/arch/arm/mach-s3c2443/clock.c
2  *
3  * Copyright (c) 2007 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/delay.h>
33 #include <linux/serial_core.h>
34
35 #include <asm/mach/map.h>
36
37 #include <asm/hardware.h>
38 #include <asm/io.h>
39
40 #include <asm/arch/regs-s3c2443-clock.h>
41
42 #include <asm/plat-s3c24xx/s3c2443.h>
43 #include <asm/plat-s3c24xx/clock.h>
44 #include <asm/plat-s3c24xx/cpu.h>
45
46 /* We currently have to assume that the system is running
47  * from the XTPll input, and that all ***REFCLKs are being
48  * fed from it, as we cannot read the state of OM[4] from
49  * software.
50  *
51  * It would be possible for each board initialisation to
52  * set the correct muxing at initialisation
53 */
54
55 static int s3c2443_clkcon_enable_h(struct clk *clk, int enable)
56 {
57         unsigned int clocks = clk->ctrlbit;
58         unsigned long clkcon;
59
60         clkcon = __raw_readl(S3C2443_HCLKCON);
61
62         if (enable)
63                 clkcon |= clocks;
64         else
65                 clkcon &= ~clocks;
66
67         __raw_writel(clkcon, S3C2443_HCLKCON);
68
69         return 0;
70 }
71
72 static int s3c2443_clkcon_enable_p(struct clk *clk, int enable)
73 {
74         unsigned int clocks = clk->ctrlbit;
75         unsigned long clkcon;
76
77         clkcon = __raw_readl(S3C2443_PCLKCON);
78
79         if (enable)
80                 clkcon |= clocks;
81         else
82                 clkcon &= ~clocks;
83
84         __raw_writel(clkcon, S3C2443_PCLKCON);
85
86         return 0;
87 }
88
89 static int s3c2443_clkcon_enable_s(struct clk *clk, int enable)
90 {
91         unsigned int clocks = clk->ctrlbit;
92         unsigned long clkcon;
93
94         clkcon = __raw_readl(S3C2443_SCLKCON);
95
96         if (enable)
97                 clkcon |= clocks;
98         else
99                 clkcon &= ~clocks;
100
101         __raw_writel(clkcon, S3C2443_SCLKCON);
102
103         return 0;
104 }
105
106 static unsigned long s3c2443_roundrate_clksrc(struct clk *clk,
107                                               unsigned long rate,
108                                               unsigned int max)
109 {
110         unsigned long parent_rate = clk_get_rate(clk->parent);
111         int div;
112
113         if (rate > parent_rate)
114                 return parent_rate;
115
116         /* note, we remove the +/- 1 calculations as they cancel out */
117
118         div = (rate / parent_rate);
119
120         if (div < 1)
121                 div = 1;
122         else if (div > max)
123                 div = max;
124
125         return parent_rate / div;
126 }
127
128 static unsigned long s3c2443_roundrate_clksrc4(struct clk *clk,
129                                                unsigned long rate)
130 {
131         return s3c2443_roundrate_clksrc(clk, rate, 4);
132 }
133
134 static unsigned long s3c2443_roundrate_clksrc16(struct clk *clk,
135                                                 unsigned long rate)
136 {
137         return s3c2443_roundrate_clksrc(clk, rate, 16);
138 }
139
140 static unsigned long s3c2443_roundrate_clksrc256(struct clk *clk,
141                                                  unsigned long rate)
142 {
143         return s3c2443_roundrate_clksrc(clk, rate, 256);
144 }
145
146 /* clock selections */
147
148 /* CPU EXTCLK input */
149 static struct clk clk_ext = {
150         .name           = "ext",
151         .id             = -1,
152 };
153
154 static struct clk clk_mpllref = {
155         .name           = "mpllref",
156         .parent         = &clk_xtal,
157         .id             = -1,
158 };
159
160 #if 0
161 static struct clk clk_mpll = {
162         .name           = "mpll",
163         .parent         = &clk_mpllref,
164         .id             = -1,
165 };
166 #endif
167
168 static struct clk clk_epllref;
169
170 static struct clk clk_epll = {
171         .name           = "epll",
172         .parent         = &clk_epllref,
173         .id             = -1,
174 };
175
176 static struct clk clk_i2s_ext = {
177         .name           = "i2s-ext",
178         .id             = -1,
179 };
180
181 static int s3c2443_setparent_epllref(struct clk *clk, struct clk *parent)
182 {
183         unsigned long clksrc = __raw_readl(S3C2443_CLKSRC);
184
185         clksrc &= ~S3C2443_CLKSRC_EPLLREF_MASK;
186
187         if (parent == &clk_xtal)
188                 clksrc |= S3C2443_CLKSRC_EPLLREF_XTAL;
189         else if (parent == &clk_ext)
190                 clksrc |= S3C2443_CLKSRC_EPLLREF_EXTCLK;
191         else if (parent != &clk_mpllref)
192                 return -EINVAL;
193
194         __raw_writel(clksrc, S3C2443_CLKSRC);
195         clk->parent = parent;
196
197         return 0;
198 }
199
200 static struct clk clk_epllref = {
201         .name           = "epllref",
202         .id             = -1,
203         .set_parent     = s3c2443_setparent_epllref,
204 };
205
206 static unsigned long s3c2443_getrate_mdivclk(struct clk *clk)
207 {
208         unsigned long parent_rate = clk_get_rate(clk->parent);
209         unsigned long div = __raw_readl(S3C2443_CLKDIV0);
210
211         div  &= S3C2443_CLKDIV0_EXTDIV_MASK;
212         div >>= (S3C2443_CLKDIV0_EXTDIV_SHIFT-1);       /* x2 */
213
214         return parent_rate / (div + 1);
215 }
216
217 static struct clk clk_mdivclk = {
218         .name           = "mdivclk",
219         .parent         = &clk_mpllref,
220         .id             = -1,
221         .get_rate       = s3c2443_getrate_mdivclk,
222 };
223
224 static int s3c2443_setparent_msysclk(struct clk *clk, struct clk *parent)
225 {
226         unsigned long clksrc = __raw_readl(S3C2443_CLKSRC);
227
228         clksrc &= ~(S3C2443_CLKSRC_MSYSCLK_MPLL |
229                     S3C2443_CLKSRC_EXTCLK_DIV);
230
231         if (parent == &clk_mpll)
232                 clksrc |= S3C2443_CLKSRC_MSYSCLK_MPLL;
233         else if (parent == &clk_mdivclk)
234                 clksrc |= S3C2443_CLKSRC_EXTCLK_DIV;
235         else if (parent != &clk_mpllref)
236                 return -EINVAL;
237
238         __raw_writel(clksrc, S3C2443_CLKSRC);
239         clk->parent = parent;
240
241         return 0;
242 }
243
244 static struct clk clk_msysclk = {
245         .name           = "msysclk",
246         .parent         = &clk_xtal,
247         .id             = -1,
248         .set_parent     = s3c2443_setparent_msysclk,
249 };
250
251 /* armdiv
252  *
253  * this clock is sourced from msysclk and can have a number of
254  * divider values applied to it to then be fed into armclk.
255 */
256
257 static struct clk clk_armdiv = {
258         .name           = "armdiv",
259         .id             = -1,
260         .parent         = &clk_msysclk,
261 };
262
263 /* armclk
264  *
265  * this is the clock fed into the ARM core itself, either from
266  * armdiv or from hclk.
267  */
268
269 static int s3c2443_setparent_armclk(struct clk *clk, struct clk *parent)
270 {
271         unsigned long clkdiv0;
272
273         clkdiv0 = __raw_readl(S3C2443_CLKDIV0);
274
275         if (parent == &clk_armdiv)
276                 clkdiv0 &= ~S3C2443_CLKDIV0_DVS;
277         else if (parent == &clk_h)
278                 clkdiv0 |= S3C2443_CLKDIV0_DVS;
279         else
280                 return -EINVAL;
281
282         __raw_writel(clkdiv0, S3C2443_CLKDIV0);
283         return 0;
284 }
285
286 static struct clk clk_arm = {
287         .name           = "armclk",
288         .id             = -1,
289         .set_parent     = s3c2443_setparent_armclk,
290 };
291
292 /* esysclk
293  *
294  * this is sourced from either the EPLL or the EPLLref clock
295 */
296
297 static int s3c2443_setparent_esysclk(struct clk *clk, struct clk *parent)
298 {
299         unsigned long clksrc = __raw_readl(S3C2443_CLKSRC);
300
301         if (parent == &clk_epll)
302                 clksrc |= S3C2443_CLKSRC_ESYSCLK_EPLL;
303         else if (parent == &clk_epllref)
304                 clksrc &= ~S3C2443_CLKSRC_ESYSCLK_EPLL;
305         else
306                 return -EINVAL;
307
308         __raw_writel(clksrc, S3C2443_CLKSRC);
309         clk->parent = parent;
310
311         return 0;
312 }
313
314 static struct clk clk_esysclk = {
315         .name           = "esysclk",
316         .parent         = &clk_epll,
317         .id             = -1,
318         .set_parent     = s3c2443_setparent_esysclk,
319 };
320
321 /* uartclk
322  *
323  * UART baud-rate clock sourced from esysclk via a divisor
324 */
325
326 static unsigned long s3c2443_getrate_uart(struct clk *clk)
327 {
328         unsigned long parent_rate = clk_get_rate(clk->parent);
329         unsigned long div = __raw_readl(S3C2443_CLKDIV1);
330
331         div &= S3C2443_CLKDIV1_UARTDIV_MASK;
332         div >>= S3C2443_CLKDIV1_UARTDIV_SHIFT;
333
334         return parent_rate / (div + 1);
335 }
336
337
338 static int s3c2443_setrate_uart(struct clk *clk, unsigned long rate)
339 {
340         unsigned long parent_rate = clk_get_rate(clk->parent);
341         unsigned long clkdivn = __raw_readl(S3C2443_CLKDIV1);
342
343         rate = s3c2443_roundrate_clksrc16(clk, rate);
344         rate = parent_rate / rate;
345
346         clkdivn &= ~S3C2443_CLKDIV1_UARTDIV_MASK;
347         clkdivn |= (rate - 1) << S3C2443_CLKDIV1_UARTDIV_SHIFT;
348
349         __raw_writel(clkdivn, S3C2443_CLKDIV1);
350         return 0;
351 }
352
353 static struct clk clk_uart = {
354         .name           = "uartclk",
355         .id             = -1,
356         .parent         = &clk_esysclk,
357         .get_rate       = s3c2443_getrate_uart,
358         .set_rate       = s3c2443_setrate_uart,
359         .round_rate     = s3c2443_roundrate_clksrc16,
360 };
361
362 /* hsspi
363  *
364  * high-speed spi clock, sourced from esysclk
365 */
366
367 static unsigned long s3c2443_getrate_hsspi(struct clk *clk)
368 {
369         unsigned long parent_rate = clk_get_rate(clk->parent);
370         unsigned long div = __raw_readl(S3C2443_CLKDIV1);
371
372         div &= S3C2443_CLKDIV1_HSSPIDIV_MASK;
373         div >>= S3C2443_CLKDIV1_HSSPIDIV_SHIFT;
374
375         return parent_rate / (div + 1);
376 }
377
378
379 static int s3c2443_setrate_hsspi(struct clk *clk, unsigned long rate)
380 {
381         unsigned long parent_rate = clk_get_rate(clk->parent);
382         unsigned long clkdivn = __raw_readl(S3C2443_CLKDIV1);
383
384         rate = s3c2443_roundrate_clksrc4(clk, rate);
385         rate = parent_rate / rate;
386
387         clkdivn &= ~S3C2443_CLKDIV1_HSSPIDIV_MASK;
388         clkdivn |= (rate - 1) << S3C2443_CLKDIV1_HSSPIDIV_SHIFT;
389
390         __raw_writel(clkdivn, S3C2443_CLKDIV1);
391         return 0;
392 }
393
394 static struct clk clk_hsspi = {
395         .name           = "hsspi",
396         .id             = -1,
397         .parent         = &clk_esysclk,
398         .ctrlbit        = S3C2443_SCLKCON_HSSPICLK,
399         .enable         = s3c2443_clkcon_enable_s,
400         .get_rate       = s3c2443_getrate_hsspi,
401         .set_rate       = s3c2443_setrate_hsspi,
402         .round_rate     = s3c2443_roundrate_clksrc4,
403 };
404
405 /* usbhost
406  *
407  * usb host bus-clock, usually 48MHz to provide USB bus clock timing
408 */
409
410 static unsigned long s3c2443_getrate_usbhost(struct clk *clk)
411 {
412         unsigned long parent_rate = clk_get_rate(clk->parent);
413         unsigned long div = __raw_readl(S3C2443_CLKDIV1);
414
415         div &= S3C2443_CLKDIV1_USBHOSTDIV_MASK;
416         div >>= S3C2443_CLKDIV1_USBHOSTDIV_SHIFT;
417
418         return parent_rate / (div + 1);
419 }
420
421 static int s3c2443_setrate_usbhost(struct clk *clk, unsigned long rate)
422 {
423         unsigned long parent_rate = clk_get_rate(clk->parent);
424         unsigned long clkdivn = __raw_readl(S3C2443_CLKDIV1);
425
426         rate = s3c2443_roundrate_clksrc4(clk, rate);
427         rate = parent_rate / rate;
428
429         clkdivn &= ~S3C2443_CLKDIV1_USBHOSTDIV_MASK;
430         clkdivn |= (rate - 1) << S3C2443_CLKDIV1_USBHOSTDIV_SHIFT;
431
432         __raw_writel(clkdivn, S3C2443_CLKDIV1);
433         return 0;
434 }
435
436 static struct clk clk_usb_bus_host = {
437         .name           = "usb-bus-host-parent",
438         .id             = -1,
439         .parent         = &clk_esysclk,
440         .ctrlbit        = S3C2443_SCLKCON_USBHOST,
441         .enable         = s3c2443_clkcon_enable_s,
442         .get_rate       = s3c2443_getrate_usbhost,
443         .set_rate       = s3c2443_setrate_usbhost,
444         .round_rate     = s3c2443_roundrate_clksrc4,
445 };
446
447 /* clk_hsmcc_div
448  *
449  * this clock is sourced from epll, and is fed through a divider,
450  * to a mux controlled by sclkcon where either it or a extclk can
451  * be fed to the hsmmc block
452 */
453
454 static unsigned long s3c2443_getrate_hsmmc_div(struct clk *clk)
455 {
456         unsigned long parent_rate = clk_get_rate(clk->parent);
457         unsigned long div = __raw_readl(S3C2443_CLKDIV1);
458
459         div &= S3C2443_CLKDIV1_HSMMCDIV_MASK;
460         div >>= S3C2443_CLKDIV1_HSMMCDIV_SHIFT;
461
462         return parent_rate / (div + 1);
463 }
464
465 static int s3c2443_setrate_hsmmc_div(struct clk *clk, unsigned long rate)
466 {
467         unsigned long parent_rate = clk_get_rate(clk->parent);
468         unsigned long clkdivn = __raw_readl(S3C2443_CLKDIV1);
469
470         rate = s3c2443_roundrate_clksrc4(clk, rate);
471         rate = parent_rate / rate;
472
473         clkdivn &= ~S3C2443_CLKDIV1_HSMMCDIV_MASK;
474         clkdivn |= (rate - 1) << S3C2443_CLKDIV1_HSMMCDIV_SHIFT;
475
476         __raw_writel(clkdivn, S3C2443_CLKDIV1);
477         return 0;
478 }
479
480 static struct clk clk_hsmmc_div = {
481         .name           = "hsmmc-div",
482         .id             = -1,
483         .parent         = &clk_esysclk,
484         .get_rate       = s3c2443_getrate_hsmmc_div,
485         .set_rate       = s3c2443_setrate_hsmmc_div,
486         .round_rate     = s3c2443_roundrate_clksrc4,
487 };
488
489 static int s3c2443_setparent_hsmmc(struct clk *clk, struct clk *parent)
490 {
491         unsigned long clksrc = __raw_readl(S3C2443_SCLKCON);
492
493         clksrc &= ~(S3C2443_SCLKCON_HSMMCCLK_EXT |
494                     S3C2443_SCLKCON_HSMMCCLK_EPLL);
495
496         if (parent == &clk_epll)
497                 clksrc |= S3C2443_SCLKCON_HSMMCCLK_EPLL;
498         else if (parent == &clk_ext)
499                 clksrc |= S3C2443_SCLKCON_HSMMCCLK_EXT;
500         else
501                 return -EINVAL;
502
503         if (clk->usage > 0) {
504                 __raw_writel(clksrc, S3C2443_SCLKCON);
505         }
506
507         clk->parent = parent;
508         return 0;
509 }
510
511 static int s3c2443_enable_hsmmc(struct clk *clk, int enable)
512 {
513         return s3c2443_setparent_hsmmc(clk, clk->parent);
514 }
515
516 static struct clk clk_hsmmc = {
517         .name           = "hsmmc-if",
518         .id             = -1,
519         .parent         = &clk_hsmmc_div,
520         .enable         = s3c2443_enable_hsmmc,
521         .set_parent     = s3c2443_setparent_hsmmc,
522 };
523
524 /* i2s_eplldiv
525  *
526  * this clock is the output from the i2s divisor of esysclk
527 */
528
529 static unsigned long s3c2443_getrate_i2s_eplldiv(struct clk *clk)
530 {
531         unsigned long parent_rate = clk_get_rate(clk->parent);
532         unsigned long div = __raw_readl(S3C2443_CLKDIV1);
533
534         div &= S3C2443_CLKDIV1_I2SDIV_MASK;
535         div >>= S3C2443_CLKDIV1_I2SDIV_SHIFT;
536
537         return parent_rate / (div + 1);
538 }
539
540 static int s3c2443_setrate_i2s_eplldiv(struct clk *clk, unsigned long rate)
541 {
542         unsigned long parent_rate = clk_get_rate(clk->parent);
543         unsigned long clkdivn = __raw_readl(S3C2443_CLKDIV1);
544
545         rate = s3c2443_roundrate_clksrc16(clk, rate);
546         rate = parent_rate / rate;
547
548         clkdivn &= ~S3C2443_CLKDIV1_I2SDIV_MASK;
549         clkdivn |= (rate - 1) << S3C2443_CLKDIV1_I2SDIV_SHIFT;
550
551         __raw_writel(clkdivn, S3C2443_CLKDIV1);
552         return 0;
553 }
554
555 static struct clk clk_i2s_eplldiv = {
556         .name           = "i2s-eplldiv",
557         .id             = -1,
558         .parent         = &clk_esysclk,
559         .get_rate       = s3c2443_getrate_i2s_eplldiv,
560         .set_rate       = s3c2443_setrate_i2s_eplldiv,
561         .round_rate     = s3c2443_roundrate_clksrc16,
562 };
563
564 /* i2s-ref
565  *
566  * i2s bus reference clock, selectable from external, esysclk or epllref
567 */
568
569 static int s3c2443_setparent_i2s(struct clk *clk, struct clk *parent)
570 {
571         unsigned long clksrc = __raw_readl(S3C2443_CLKSRC);
572
573         clksrc &= ~S3C2443_CLKSRC_I2S_MASK;
574
575         if (parent == &clk_epllref)
576                 clksrc |= S3C2443_CLKSRC_I2S_EPLLREF;
577         else if (parent == &clk_i2s_ext)
578                 clksrc |= S3C2443_CLKSRC_I2S_EXT;
579         else if (parent != &clk_i2s_eplldiv)
580                 return -EINVAL;
581
582         clk->parent = parent;
583         __raw_writel(clksrc, S3C2443_CLKSRC);
584
585         return 0;
586 }
587
588 static struct clk clk_i2s = {
589         .name           = "i2s-if",
590         .id             = -1,
591         .parent         = &clk_i2s_eplldiv,
592         .ctrlbit        = S3C2443_SCLKCON_I2SCLK,
593         .enable         = s3c2443_clkcon_enable_s,
594         .set_parent     = s3c2443_setparent_i2s,
595 };
596
597 /* cam-if
598  *
599  * camera interface bus-clock, divided down from esysclk
600 */
601
602 static unsigned long s3c2443_getrate_cam(struct clk *clk)
603 {
604         unsigned long parent_rate = clk_get_rate(clk->parent);
605         unsigned long div = __raw_readl(S3C2443_CLKDIV1);
606
607         div  &= S3C2443_CLKDIV1_CAMDIV_MASK;
608         div >>= S3C2443_CLKDIV1_CAMDIV_SHIFT;
609
610         return parent_rate / (div + 1);
611 }
612
613 static int s3c2443_setrate_cam(struct clk *clk, unsigned long rate)
614 {
615         unsigned long parent_rate = clk_get_rate(clk->parent);
616         unsigned long clkdiv1 = __raw_readl(S3C2443_CLKDIV1);
617
618         rate = s3c2443_roundrate_clksrc16(clk, rate);
619         rate = parent_rate / rate;
620
621         clkdiv1 &= ~S3C2443_CLKDIV1_CAMDIV_MASK;
622         clkdiv1 |= (rate - 1) << S3C2443_CLKDIV1_CAMDIV_SHIFT;
623
624         __raw_writel(clkdiv1, S3C2443_CLKDIV1);
625         return 0;
626 }
627
628 static struct clk clk_cam = {
629         .name           = "camif-upll",         /* same as 2440 name */
630         .id             = -1,
631         .parent         = &clk_esysclk,
632         .ctrlbit        = S3C2443_SCLKCON_CAMCLK,
633         .enable         = s3c2443_clkcon_enable_s,
634         .get_rate       = s3c2443_getrate_cam,
635         .set_rate       = s3c2443_setrate_cam,
636         .round_rate     = s3c2443_roundrate_clksrc16,
637 };
638
639 /* display-if
640  *
641  * display interface clock, divided from esysclk
642 */
643
644 static unsigned long s3c2443_getrate_display(struct clk *clk)
645 {
646         unsigned long parent_rate = clk_get_rate(clk->parent);
647         unsigned long div = __raw_readl(S3C2443_CLKDIV1);
648
649         div &= S3C2443_CLKDIV1_DISPDIV_MASK;
650         div >>= S3C2443_CLKDIV1_DISPDIV_SHIFT;
651
652         return parent_rate / (div + 1);
653 }
654
655 static int s3c2443_setrate_display(struct clk *clk, unsigned long rate)
656 {
657         unsigned long parent_rate = clk_get_rate(clk->parent);
658         unsigned long clkdivn = __raw_readl(S3C2443_CLKDIV1);
659
660         rate = s3c2443_roundrate_clksrc256(clk, rate);
661         rate = parent_rate / rate;
662
663         clkdivn &= ~S3C2443_CLKDIV1_UARTDIV_MASK;
664         clkdivn |= (rate - 1) << S3C2443_CLKDIV1_UARTDIV_SHIFT;
665
666         __raw_writel(clkdivn, S3C2443_CLKDIV1);
667         return 0;
668 }
669
670 static struct clk clk_display = {
671         .name           = "display-if",
672         .id             = -1,
673         .parent         = &clk_esysclk,
674         .ctrlbit        = S3C2443_SCLKCON_DISPCLK,
675         .enable         = s3c2443_clkcon_enable_s,
676         .get_rate       = s3c2443_getrate_display,
677         .set_rate       = s3c2443_setrate_display,
678         .round_rate     = s3c2443_roundrate_clksrc256,
679 };
680
681 /* standard clock definitions */
682
683 static struct clk init_clocks_disable[] = {
684         {
685                 .name           = "nand",
686                 .id             = -1,
687                 .parent         = &clk_h,
688         }, {
689                 .name           = "sdi",
690                 .id             = -1,
691                 .parent         = &clk_p,
692                 .enable         = s3c2443_clkcon_enable_p,
693                 .ctrlbit        = S3C2443_PCLKCON_SDI,
694         }, {
695                 .name           = "adc",
696                 .id             = -1,
697                 .parent         = &clk_p,
698                 .enable         = s3c2443_clkcon_enable_p,
699                 .ctrlbit        = S3C2443_PCLKCON_ADC,
700         }, {
701                 .name           = "i2c",
702                 .id             = -1,
703                 .parent         = &clk_p,
704                 .enable         = s3c2443_clkcon_enable_p,
705                 .ctrlbit        = S3C2443_PCLKCON_IIC,
706         }, {
707                 .name           = "iis",
708                 .id             = -1,
709                 .parent         = &clk_p,
710                 .enable         = s3c2443_clkcon_enable_p,
711                 .ctrlbit        = S3C2443_PCLKCON_IIS,
712         }, {
713                 .name           = "spi",
714                 .id             = 0,
715                 .parent         = &clk_p,
716                 .enable         = s3c2443_clkcon_enable_p,
717                 .ctrlbit        = S3C2443_PCLKCON_SPI0,
718         }, {
719                 .name           = "spi",
720                 .id             = 1,
721                 .parent         = &clk_p,
722                 .enable         = s3c2443_clkcon_enable_p,
723                 .ctrlbit        = S3C2443_PCLKCON_SPI1,
724         }
725 };
726
727 static struct clk init_clocks[] = {
728         {
729                 .name           = "dma",
730                 .id             = 0,
731                 .parent         = &clk_h,
732                 .enable         = s3c2443_clkcon_enable_h,
733                 .ctrlbit        = S3C2443_HCLKCON_DMA0,
734         }, {
735                 .name           = "dma",
736                 .id             = 1,
737                 .parent         = &clk_h,
738                 .enable         = s3c2443_clkcon_enable_h,
739                 .ctrlbit        = S3C2443_HCLKCON_DMA1,
740         }, {
741                 .name           = "dma",
742                 .id             = 2,
743                 .parent         = &clk_h,
744                 .enable         = s3c2443_clkcon_enable_h,
745                 .ctrlbit        = S3C2443_HCLKCON_DMA2,
746         }, {
747                 .name           = "dma",
748                 .id             = 3,
749                 .parent         = &clk_h,
750                 .enable         = s3c2443_clkcon_enable_h,
751                 .ctrlbit        = S3C2443_HCLKCON_DMA3,
752         }, {
753                 .name           = "dma",
754                 .id             = 4,
755                 .parent         = &clk_h,
756                 .enable         = s3c2443_clkcon_enable_h,
757                 .ctrlbit        = S3C2443_HCLKCON_DMA4,
758         }, {
759                 .name           = "dma",
760                 .id             = 5,
761                 .parent         = &clk_h,
762                 .enable         = s3c2443_clkcon_enable_h,
763                 .ctrlbit        = S3C2443_HCLKCON_DMA5,
764         }, {
765                 .name           = "lcd",
766                 .id             = -1,
767                 .parent         = &clk_h,
768                 .enable         = s3c2443_clkcon_enable_h,
769                 .ctrlbit        = S3C2443_HCLKCON_LCDC,
770         }, {
771                 .name           = "gpio",
772                 .id             = -1,
773                 .parent         = &clk_p,
774                 .enable         = s3c2443_clkcon_enable_p,
775                 .ctrlbit        = S3C2443_PCLKCON_GPIO,
776         }, {
777                 .name           = "usb-host",
778                 .id             = -1,
779                 .parent         = &clk_h,
780                 .enable         = s3c2443_clkcon_enable_h,
781                 .ctrlbit        = S3C2443_HCLKCON_USBH,
782         }, {
783                 .name           = "usb-device",
784                 .id             = -1,
785                 .parent         = &clk_h,
786                 .enable         = s3c2443_clkcon_enable_h,
787                 .ctrlbit        = S3C2443_HCLKCON_USBD,
788         }, {
789                 .name           = "hsmmc",
790                 .id             = -1,
791                 .parent         = &clk_h,
792                 .enable         = s3c2443_clkcon_enable_h,
793                 .ctrlbit        = S3C2443_HCLKCON_HSMMC,
794         }, {
795                 .name           = "cfc",
796                 .id             = -1,
797                 .parent         = &clk_h,
798                 .enable         = s3c2443_clkcon_enable_h,
799                 .ctrlbit        = S3C2443_HCLKCON_CFC,
800         }, {
801                 .name           = "ssmc",
802                 .id             = -1,
803                 .parent         = &clk_h,
804                 .enable         = s3c2443_clkcon_enable_h,
805                 .ctrlbit        = S3C2443_HCLKCON_SSMC,
806         }, {
807                 .name           = "timers",
808                 .id             = -1,
809                 .parent         = &clk_p,
810                 .enable         = s3c2443_clkcon_enable_p,
811                 .ctrlbit        = S3C2443_PCLKCON_PWMT,
812         }, {
813                 .name           = "uart",
814                 .id             = 0,
815                 .parent         = &clk_p,
816                 .enable         = s3c2443_clkcon_enable_p,
817                 .ctrlbit        = S3C2443_PCLKCON_UART0,
818         }, {
819                 .name           = "uart",
820                 .id             = 1,
821                 .parent         = &clk_p,
822                 .enable         = s3c2443_clkcon_enable_p,
823                 .ctrlbit        = S3C2443_PCLKCON_UART1,
824         }, {
825                 .name           = "uart",
826                 .id             = 2,
827                 .parent         = &clk_p,
828                 .enable         = s3c2443_clkcon_enable_p,
829                 .ctrlbit        = S3C2443_PCLKCON_UART2,
830         }, {
831                 .name           = "uart",
832                 .id             = 3,
833                 .parent         = &clk_p,
834                 .enable         = s3c2443_clkcon_enable_p,
835                 .ctrlbit        = S3C2443_PCLKCON_UART3,
836         }, {
837                 .name           = "rtc",
838                 .id             = -1,
839                 .parent         = &clk_p,
840                 .enable         = s3c2443_clkcon_enable_p,
841                 .ctrlbit        = S3C2443_PCLKCON_RTC,
842         }, {
843                 .name           = "watchdog",
844                 .id             = -1,
845                 .parent         = &clk_p,
846                 .ctrlbit        = S3C2443_PCLKCON_WDT,
847         }, {
848                 .name           = "usb-bus-host",
849                 .id             = -1,
850                 .parent         = &clk_usb_bus_host,
851         }, {
852                 .name           = "ac97",
853                 .id             = -1,
854                 .parent         = &clk_p,
855                 .ctrlbit        = S3C2443_PCLKCON_AC97,
856         }
857 };
858
859 /* clocks to add where we need to check their parentage */
860
861 /* s3c2443_clk_initparents
862  *
863  * Initialise the parents for the clocks that we get at start-time
864 */
865
866 static int __init clk_init_set_parent(struct clk *clk, struct clk *parent)
867 {
868         printk(KERN_DEBUG "clock %s: parent %s\n", clk->name, parent->name);
869         return clk_set_parent(clk, parent);
870 }
871
872 static void __init s3c2443_clk_initparents(void)
873 {
874         unsigned long clksrc = __raw_readl(S3C2443_CLKSRC);
875         struct clk *parent;
876
877         switch (clksrc & S3C2443_CLKSRC_EPLLREF_MASK) {
878         case S3C2443_CLKSRC_EPLLREF_EXTCLK:
879                 parent = &clk_ext;
880                 break;
881
882         case S3C2443_CLKSRC_EPLLREF_XTAL:
883         default:
884                 parent = &clk_xtal;
885                 break;
886
887         case S3C2443_CLKSRC_EPLLREF_MPLLREF:
888         case S3C2443_CLKSRC_EPLLREF_MPLLREF2:
889                 parent = &clk_mpllref;
890                 break;
891         }
892
893         clk_init_set_parent(&clk_epllref, parent);
894
895         switch (clksrc & S3C2443_CLKSRC_I2S_MASK) {
896         case S3C2443_CLKSRC_I2S_EXT:
897                 parent = &clk_i2s_ext;
898                 break;
899
900         case S3C2443_CLKSRC_I2S_EPLLDIV:
901         default:
902                 parent = &clk_i2s_eplldiv;
903                 break;
904
905         case S3C2443_CLKSRC_I2S_EPLLREF:
906         case S3C2443_CLKSRC_I2S_EPLLREF3:
907                 parent = &clk_epllref;
908         }
909
910         clk_init_set_parent(&clk_i2s, &clk_epllref);
911
912         /* esysclk source */
913
914         parent = (clksrc & S3C2443_CLKSRC_ESYSCLK_EPLL) ?
915                 &clk_epll : &clk_epllref;
916
917         clk_init_set_parent(&clk_esysclk, parent);
918
919         /* msysclk source */
920
921         if (clksrc & S3C2443_CLKSRC_MSYSCLK_MPLL) {
922                 parent = &clk_mpll;
923         } else {
924                 parent = (clksrc & S3C2443_CLKSRC_EXTCLK_DIV) ?
925                         &clk_mdivclk : &clk_mpllref;
926         }
927
928         clk_init_set_parent(&clk_msysclk, parent);
929
930         /* arm */
931
932         if (__raw_readl(S3C2443_CLKDIV0) & S3C2443_CLKDIV0_DVS)
933                 parent = &clk_h;
934         else
935                 parent = &clk_armdiv;
936
937         clk_init_set_parent(&clk_arm, parent);
938 }
939
940 /* armdiv divisor table */
941
942 static unsigned int armdiv[16] = {
943         [S3C2443_CLKDIV0_ARMDIV_1 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]      = 1,
944         [S3C2443_CLKDIV0_ARMDIV_2 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]      = 2,
945         [S3C2443_CLKDIV0_ARMDIV_3 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]      = 3,
946         [S3C2443_CLKDIV0_ARMDIV_4 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]      = 4,
947         [S3C2443_CLKDIV0_ARMDIV_6 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]      = 6,
948         [S3C2443_CLKDIV0_ARMDIV_8 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]      = 8,
949         [S3C2443_CLKDIV0_ARMDIV_12 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]     = 12,
950         [S3C2443_CLKDIV0_ARMDIV_16 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]     = 16,
951 };
952
953 static inline unsigned int s3c2443_fclk_div(unsigned long clkcon0)
954 {
955         clkcon0 &= S3C2443_CLKDIV0_ARMDIV_MASK;
956
957         return armdiv[clkcon0 >> S3C2443_CLKDIV0_ARMDIV_SHIFT];
958 }
959
960 static inline unsigned long s3c2443_get_prediv(unsigned long clkcon0)
961 {
962         clkcon0 &= S3C2443_CLKDIV0_PREDIV_MASK;
963         clkcon0 >>= S3C2443_CLKDIV0_PREDIV_SHIFT;
964
965         return clkcon0 + 1;
966 }
967
968 /* clocks to add straight away */
969
970 static struct clk *clks[] __initdata = {
971         &clk_ext,
972         &clk_epll,
973         &clk_usb_bus_host,
974         &clk_usb_bus,
975         &clk_esysclk,
976         &clk_epllref,
977         &clk_mpllref,
978         &clk_msysclk,
979         &clk_uart,
980         &clk_display,
981         &clk_cam,
982         &clk_i2s_eplldiv,
983         &clk_i2s,
984         &clk_hsspi,
985         &clk_hsmmc_div,
986         &clk_hsmmc,
987         &clk_armdiv,
988         &clk_arm,
989 };
990
991 void __init s3c2443_init_clocks(int xtal)
992 {
993         unsigned long epllcon = __raw_readl(S3C2443_EPLLCON);
994         unsigned long mpllcon = __raw_readl(S3C2443_MPLLCON);
995         unsigned long clkdiv0 = __raw_readl(S3C2443_CLKDIV0);
996         unsigned long pll;
997         unsigned long fclk;
998         unsigned long hclk;
999         unsigned long pclk;
1000         struct clk *clkp;
1001         int ret;
1002         int ptr;
1003
1004         pll = s3c2443_get_mpll(mpllcon, xtal);
1005
1006         fclk = pll / s3c2443_fclk_div(clkdiv0);
1007         hclk = fclk / s3c2443_get_prediv(clkdiv0);
1008         hclk = hclk / ((clkdiv0 & S3C2443_CLKDIV0_HALF_HCLK) ? 2 : 1);
1009         pclk = hclk / ((clkdiv0 & S3C2443_CLKDIV0_HALF_PCLK) ? 2 : 1);
1010
1011         clk_armdiv.rate = fclk;
1012
1013         s3c24xx_setup_clocks(xtal, fclk, hclk, pclk);
1014
1015         printk("S3C2443: mpll %s %ld.%03ld MHz, cpu %ld.%03ld MHz, mem %ld.%03ld MHz, pclk %ld.%03ld MHz\n",
1016                (mpllcon & S3C2443_PLLCON_OFF) ? "off":"on",
1017                print_mhz(pll), print_mhz(fclk),
1018                print_mhz(hclk), print_mhz(pclk));
1019
1020         s3c2443_clk_initparents();
1021
1022         for (ptr = 0; ptr < ARRAY_SIZE(clks); ptr++) {
1023                 clkp = clks[ptr];
1024
1025                 ret = s3c24xx_register_clock(clkp);
1026                 if (ret < 0) {
1027                         printk(KERN_ERR "Failed to register clock %s (%d)\n",
1028                                clkp->name, ret);
1029                 }
1030         }
1031
1032         clk_epll.rate = s3c2443_get_epll(epllcon, xtal);
1033
1034         clk_usb_bus.parent = &clk_usb_bus_host;
1035
1036         /* ensure usb bus clock is within correct rate of 48MHz */
1037
1038         if (clk_get_rate(&clk_usb_bus_host) != (48 * 1000 * 1000)) {
1039                 printk(KERN_INFO "Warning: USB host bus not at 48MHz\n");
1040                 clk_set_rate(&clk_usb_bus_host, 48*1000*1000);
1041         }
1042
1043         printk("S3C2443: epll %s %ld.%03ld MHz, usb-bus %ld.%03ld MHz\n",
1044                (epllcon & S3C2443_PLLCON_OFF) ? "off":"on",
1045                print_mhz(clk_get_rate(&clk_epll)),
1046                print_mhz(clk_get_rate(&clk_usb_bus)));
1047
1048         /* register clocks from clock array */
1049
1050         clkp = init_clocks;
1051         for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) {
1052                 ret = s3c24xx_register_clock(clkp);
1053                 if (ret < 0) {
1054                         printk(KERN_ERR "Failed to register clock %s (%d)\n",
1055                                clkp->name, ret);
1056                 }
1057         }
1058
1059         /* We must be careful disabling the clocks we are not intending to
1060          * be using at boot time, as subsystems such as the LCD which do
1061          * their own DMA requests to the bus can cause the system to lockup
1062          * if they where in the middle of requesting bus access.
1063          *
1064          * Disabling the LCD clock if the LCD is active is very dangerous,
1065          * and therefore the bootloader should be careful to not enable
1066          * the LCD clock if it is not needed.
1067         */
1068
1069         /* install (and disable) the clocks we do not need immediately */
1070
1071         clkp = init_clocks_disable;
1072         for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
1073
1074                 ret = s3c24xx_register_clock(clkp);
1075                 if (ret < 0) {
1076                         printk(KERN_ERR "Failed to register clock %s (%d)\n",
1077                                clkp->name, ret);
1078                 }
1079
1080                 (clkp->enable)(clkp, 0);
1081         }
1082 }