DMAENGINE: DMA40 U8500 platform configuration
[pandora-kernel.git] / arch / arm / plat-s5pc1xx / s5pc100-clock.c
1 /* linux/arch/arm/plat-s5pc1xx/s5pc100-clock.c
2  *
3  * Copyright 2009 Samsung Electronics, Co.
4  *      Byungho Min <bhmin@samsung.com>
5  *
6  * S5PC100 based common clock support
7  *
8  * Based on plat-s3c64xx/s3c6400-clock.c
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License version 2 as
12  * published by the Free Software Foundation.
13 */
14
15 #include <linux/init.h>
16 #include <linux/module.h>
17 #include <linux/kernel.h>
18 #include <linux/list.h>
19 #include <linux/errno.h>
20 #include <linux/err.h>
21 #include <linux/clk.h>
22 #include <linux/sysdev.h>
23 #include <linux/io.h>
24
25 #include <mach/hardware.h>
26 #include <mach/map.h>
27
28 #include <plat/cpu-freq.h>
29
30 #include <plat/regs-clock.h>
31 #include <plat/clock.h>
32 #include <plat/clock-clksrc.h>
33 #include <plat/cpu.h>
34 #include <plat/pll.h>
35 #include <plat/devs.h>
36 #include <plat/s5pc100.h>
37
38 /* fin_apll, fin_mpll and fin_epll are all the same clock, which we call
39  * ext_xtal_mux for want of an actual name from the manual.
40 */
41
42 static struct clk clk_ext_xtal_mux = {
43         .name           = "ext_xtal",
44         .id             = -1,
45 };
46
47 #define clk_fin_apll clk_ext_xtal_mux
48 #define clk_fin_mpll clk_ext_xtal_mux
49 #define clk_fin_epll clk_ext_xtal_mux
50 #define clk_fin_hpll clk_ext_xtal_mux
51
52 #define clk_fout_mpll   clk_mpll
53 #define clk_vclk_54m    clk_54m
54
55 /* APLL */
56 static struct clk clk_fout_apll = {
57         .name           = "fout_apll",
58         .id             = -1,
59         .rate           = 27000000,
60 };
61
62 static struct clk *clk_src_apll_list[] = {
63         [0] = &clk_fin_apll,
64         [1] = &clk_fout_apll,
65 };
66
67 static struct clksrc_sources clk_src_apll = {
68         .sources        = clk_src_apll_list,
69         .nr_sources     = ARRAY_SIZE(clk_src_apll_list),
70 };
71
72 static struct clksrc_clk clk_mout_apll = {
73         .clk    = {
74                 .name           = "mout_apll",
75                 .id             = -1,
76         },
77         .sources        = &clk_src_apll,
78         .reg_src = { .reg = S5PC100_CLKSRC0, .shift = 0, .size = 1, },
79 };
80
81 static unsigned long s5pc100_clk_dout_apll_get_rate(struct clk *clk)
82 {
83         unsigned long rate = clk_get_rate(clk->parent);
84         unsigned int ratio;
85
86         ratio = __raw_readl(S5PC100_CLKDIV0) & S5PC100_CLKDIV0_APLL_MASK;
87         ratio >>= S5PC100_CLKDIV0_APLL_SHIFT;
88
89         return rate / (ratio + 1);
90 }
91
92 static struct clk clk_dout_apll = {
93         .name           = "dout_apll",
94         .id             = -1,
95         .parent         = &clk_mout_apll.clk,
96         .ops            = &(struct clk_ops) {
97                 .get_rate       = s5pc100_clk_dout_apll_get_rate,
98         },
99 };
100
101 static unsigned long s5pc100_clk_arm_get_rate(struct clk *clk)
102 {
103         unsigned long rate = clk_get_rate(clk->parent);
104         unsigned int ratio;
105
106         ratio = __raw_readl(S5PC100_CLKDIV0) & S5PC100_CLKDIV0_ARM_MASK;
107         ratio >>= S5PC100_CLKDIV0_ARM_SHIFT;
108
109         return rate / (ratio + 1);
110 }
111
112 static unsigned long s5pc100_clk_arm_round_rate(struct clk *clk,
113                                                 unsigned long rate)
114 {
115         unsigned long parent = clk_get_rate(clk->parent);
116         u32 div;
117
118         if (parent < rate)
119                 return rate;
120
121         div = (parent / rate) - 1;
122         if (div > S5PC100_CLKDIV0_ARM_MASK)
123                 div = S5PC100_CLKDIV0_ARM_MASK;
124
125         return parent / (div + 1);
126 }
127
128 static int s5pc100_clk_arm_set_rate(struct clk *clk, unsigned long rate)
129 {
130         unsigned long parent = clk_get_rate(clk->parent);
131         u32 div;
132         u32 val;
133
134         if (rate < parent / (S5PC100_CLKDIV0_ARM_MASK + 1))
135                 return -EINVAL;
136
137         rate = clk_round_rate(clk, rate);
138         div = clk_get_rate(clk->parent) / rate;
139
140         val = __raw_readl(S5PC100_CLKDIV0);
141         val &= S5PC100_CLKDIV0_ARM_MASK;
142         val |= (div - 1);
143         __raw_writel(val, S5PC100_CLKDIV0);
144
145         return 0;
146 }
147
148 static struct clk clk_arm = {
149         .name           = "armclk",
150         .id             = -1,
151         .parent         = &clk_dout_apll,
152         .ops            = &(struct clk_ops) {
153                 .get_rate       = s5pc100_clk_arm_get_rate,
154                 .set_rate       = s5pc100_clk_arm_set_rate,
155                 .round_rate     = s5pc100_clk_arm_round_rate,
156         },
157 };
158
159 static unsigned long s5pc100_clk_dout_d0_bus_get_rate(struct clk *clk)
160 {
161         unsigned long rate = clk_get_rate(clk->parent);
162         unsigned int ratio;
163
164         ratio = __raw_readl(S5PC100_CLKDIV0) & S5PC100_CLKDIV0_D0_MASK;
165         ratio >>= S5PC100_CLKDIV0_D0_SHIFT;
166
167         return rate / (ratio + 1);
168 }
169
170 static struct clk clk_dout_d0_bus = {
171         .name           = "dout_d0_bus",
172         .id             = -1,
173         .parent         = &clk_arm,
174         .ops            = &(struct clk_ops) {
175                 .get_rate       = s5pc100_clk_dout_d0_bus_get_rate,
176         },
177 };
178
179 static unsigned long s5pc100_clk_dout_pclkd0_get_rate(struct clk *clk)
180 {
181         unsigned long rate = clk_get_rate(clk->parent);
182         unsigned int ratio;
183
184         ratio = __raw_readl(S5PC100_CLKDIV0) & S5PC100_CLKDIV0_PCLKD0_MASK;
185         ratio >>= S5PC100_CLKDIV0_PCLKD0_SHIFT;
186
187         return rate / (ratio + 1);
188 }
189
190 static struct clk clk_dout_pclkd0 = {
191         .name           = "dout_pclkd0",
192         .id             = -1,
193         .parent         = &clk_dout_d0_bus,
194         .ops            = &(struct clk_ops) {
195                 .get_rate       = s5pc100_clk_dout_pclkd0_get_rate,
196         },
197 };
198
199 static unsigned long s5pc100_clk_dout_apll2_get_rate(struct clk *clk)
200 {
201         unsigned long rate = clk_get_rate(clk->parent);
202         unsigned int ratio;
203
204         ratio = __raw_readl(S5PC100_CLKDIV1) & S5PC100_CLKDIV1_APLL2_MASK;
205         ratio >>= S5PC100_CLKDIV1_APLL2_SHIFT;
206
207         return rate / (ratio + 1);
208 }
209
210 static struct clk clk_dout_apll2 = {
211         .name           = "dout_apll2",
212         .id             = -1,
213         .parent         = &clk_mout_apll.clk,
214         .ops            = &(struct clk_ops) {
215                 .get_rate       = s5pc100_clk_dout_apll2_get_rate,
216         },
217 };
218
219 /* MPLL */
220 static struct clk *clk_src_mpll_list[] = {
221         [0] = &clk_fin_mpll,
222         [1] = &clk_fout_mpll,
223 };
224
225 static struct clksrc_sources clk_src_mpll = {
226         .sources        = clk_src_mpll_list,
227         .nr_sources     = ARRAY_SIZE(clk_src_mpll_list),
228 };
229
230 static struct clksrc_clk clk_mout_mpll = {
231         .clk = {
232                 .name           = "mout_mpll",
233                 .id             = -1,
234         },
235         .sources        = &clk_src_mpll,
236         .reg_src = { .reg = S5PC100_CLKSRC0, .shift = 4, .size = 1, },
237 };
238
239 static struct clk *clkset_am_list[] = {
240         [0] = &clk_mout_mpll.clk,
241         [1] = &clk_dout_apll2,
242 };
243
244 static struct clksrc_sources clk_src_am = {
245         .sources        = clkset_am_list,
246         .nr_sources     = ARRAY_SIZE(clkset_am_list),
247 };
248
249 static struct clksrc_clk clk_mout_am = {
250         .clk = {
251                 .name           = "mout_am",
252                 .id             = -1,
253         },
254         .sources        = &clk_src_am,
255         .reg_src = { .reg = S5PC100_CLKSRC0, .shift = 16, .size = 1, },
256 };
257
258 static unsigned long s5pc100_clk_dout_d1_bus_get_rate(struct clk *clk)
259 {
260         unsigned long rate = clk_get_rate(clk->parent);
261         unsigned int ratio;
262
263         printk(KERN_DEBUG "%s: parent is %ld\n", __func__, rate);
264
265         ratio = __raw_readl(S5PC100_CLKDIV1) & S5PC100_CLKDIV1_D1_MASK;
266         ratio >>= S5PC100_CLKDIV1_D1_SHIFT;
267
268         return rate / (ratio + 1);
269 }
270
271 static struct clk clk_dout_d1_bus = {
272         .name           = "dout_d1_bus",
273         .id             = -1,
274         .parent         = &clk_mout_am.clk,
275         .ops            = &(struct clk_ops) {
276                 .get_rate       = s5pc100_clk_dout_d1_bus_get_rate,
277         },
278 };
279
280 static struct clk *clkset_onenand_list[] = {
281         [0] = &clk_dout_d0_bus,
282         [1] = &clk_dout_d1_bus,
283 };
284
285 static struct clksrc_sources clk_src_onenand = {
286         .sources        = clkset_onenand_list,
287         .nr_sources     = ARRAY_SIZE(clkset_onenand_list),
288 };
289
290 static struct clksrc_clk clk_mout_onenand = {
291         .clk = {
292                 .name           = "mout_onenand",
293                 .id             = -1,
294         },
295         .sources        = &clk_src_onenand,
296         .reg_src = { .reg = S5PC100_CLKSRC0, .shift = 24, .size = 1, },
297 };
298
299 static unsigned long s5pc100_clk_dout_pclkd1_get_rate(struct clk *clk)
300 {
301         unsigned long rate = clk_get_rate(clk->parent);
302         unsigned int ratio;
303
304         printk(KERN_DEBUG "%s: parent is %ld\n", __func__, rate);
305
306         ratio = __raw_readl(S5PC100_CLKDIV1) & S5PC100_CLKDIV1_PCLKD1_MASK;
307         ratio >>= S5PC100_CLKDIV1_PCLKD1_SHIFT;
308
309         return rate / (ratio + 1);
310 }
311
312 static struct clk clk_dout_pclkd1 = {
313         .name           = "dout_pclkd1",
314         .id             = -1,
315         .parent         = &clk_dout_d1_bus,
316         .ops            = &(struct clk_ops) {
317                 .get_rate       = s5pc100_clk_dout_pclkd1_get_rate,
318         },
319 };
320
321 static unsigned long s5pc100_clk_dout_mpll2_get_rate(struct clk *clk)
322 {
323         unsigned long rate = clk_get_rate(clk->parent);
324         unsigned int ratio;
325
326         printk(KERN_DEBUG "%s: parent is %ld\n", __func__, rate);
327
328         ratio = __raw_readl(S5PC100_CLKDIV1) & S5PC100_CLKDIV1_MPLL2_MASK;
329         ratio >>= S5PC100_CLKDIV1_MPLL2_SHIFT;
330
331         return rate / (ratio + 1);
332 }
333
334 static struct clk clk_dout_mpll2 = {
335         .name           = "dout_mpll2",
336         .id             = -1,
337         .parent         = &clk_mout_am.clk,
338         .ops            = &(struct clk_ops) {
339                 .get_rate       = s5pc100_clk_dout_mpll2_get_rate,
340         },
341 };
342
343 static unsigned long s5pc100_clk_dout_cam_get_rate(struct clk *clk)
344 {
345         unsigned long rate = clk_get_rate(clk->parent);
346         unsigned int ratio;
347
348         printk(KERN_DEBUG "%s: parent is %ld\n", __func__, rate);
349
350         ratio = __raw_readl(S5PC100_CLKDIV1) & S5PC100_CLKDIV1_CAM_MASK;
351         ratio >>= S5PC100_CLKDIV1_CAM_SHIFT;
352
353         return rate / (ratio + 1);
354 }
355
356 static struct clk clk_dout_cam = {
357         .name           = "dout_cam",
358         .id             = -1,
359         .parent         = &clk_dout_mpll2,
360         .ops            = &(struct clk_ops) {
361                 .get_rate       = s5pc100_clk_dout_cam_get_rate,
362         },
363 };
364
365 static unsigned long s5pc100_clk_dout_mpll_get_rate(struct clk *clk)
366 {
367         unsigned long rate = clk_get_rate(clk->parent);
368         unsigned int ratio;
369
370         printk(KERN_DEBUG "%s: parent is %ld\n", __func__, rate);
371
372         ratio = __raw_readl(S5PC100_CLKDIV1) & S5PC100_CLKDIV1_MPLL_MASK;
373         ratio >>= S5PC100_CLKDIV1_MPLL_SHIFT;
374
375         return rate / (ratio + 1);
376 }
377
378 static struct clk clk_dout_mpll = {
379         .name           = "dout_mpll",
380         .id             = -1,
381         .parent         = &clk_mout_am.clk,
382         .ops            = &(struct clk_ops) {
383                 .get_rate       = s5pc100_clk_dout_mpll_get_rate,
384         },
385 };
386
387 /* EPLL */
388 static struct clk clk_fout_epll = {
389         .name           = "fout_epll",
390         .id             = -1,
391 };
392
393 static struct clk *clk_src_epll_list[] = {
394         [0] = &clk_fin_epll,
395         [1] = &clk_fout_epll,
396 };
397
398 static struct clksrc_sources clk_src_epll = {
399         .sources        = clk_src_epll_list,
400         .nr_sources     = ARRAY_SIZE(clk_src_epll_list),
401 };
402
403 static struct clksrc_clk clk_mout_epll = {
404         .clk    = {
405                 .name           = "mout_epll",
406                 .id             = -1,
407         },
408         .sources = &clk_src_epll,
409         .reg_src = { .reg = S5PC100_CLKSRC0, .shift = 8, .size = 1, },
410 };
411
412 /* HPLL */
413 static struct clk clk_fout_hpll = {
414         .name           = "fout_hpll",
415         .id             = -1,
416 };
417
418 static struct clk *clk_src_hpll_list[] = {
419         [0] = &clk_27m,
420         [1] = &clk_fout_hpll,
421 };
422
423 static struct clksrc_sources clk_src_hpll = {
424         .sources        = clk_src_hpll_list,
425         .nr_sources     = ARRAY_SIZE(clk_src_hpll_list),
426 };
427
428 static struct clksrc_clk clk_mout_hpll = {
429         .clk    = {
430                 .name           = "mout_hpll",
431                 .id             = -1,
432         },
433         .sources = &clk_src_hpll,
434         .reg_src = { .reg = S5PC100_CLKSRC0, .shift = 12, .size = 1, },
435 };
436
437 /* Peripherals */
438 /*
439  * The peripheral clocks are all controlled via clocksource followed
440  * by an optional divider and gate stage. We currently roll this into
441  * one clock which hides the intermediate clock from the mux.
442  *
443  * Note, the JPEG clock can only be an even divider...
444  *
445  * The scaler and LCD clocks depend on the S5PC100 version, and also
446  * have a common parent divisor so are not included here.
447  */
448
449 static struct clk clk_iis_cd0 = {
450         .name           = "iis_cdclk0",
451         .id             = -1,
452 };
453
454 static struct clk clk_iis_cd1 = {
455         .name           = "iis_cdclk1",
456         .id             = -1,
457 };
458
459 static struct clk clk_iis_cd2 = {
460         .name           = "iis_cdclk2",
461         .id             = -1,
462 };
463
464 static struct clk clk_pcm_cd0 = {
465         .name           = "pcm_cdclk0",
466         .id             = -1,
467 };
468
469 static struct clk clk_pcm_cd1 = {
470         .name           = "pcm_cdclk1",
471         .id             = -1,
472 };
473
474 static struct clk *clkset_audio0_list[] = {
475         &clk_mout_epll.clk,
476         &clk_dout_mpll,
477         &clk_fin_epll,
478         &clk_iis_cd0,
479         &clk_pcm_cd0,
480         &clk_mout_hpll.clk,
481 };
482
483 static struct clksrc_sources clkset_audio0 = {
484         .sources        = clkset_audio0_list,
485         .nr_sources     = ARRAY_SIZE(clkset_audio0_list),
486 };
487
488 static struct clk *clkset_spi_list[] = {
489         &clk_mout_epll.clk,
490         &clk_dout_mpll2,
491         &clk_fin_epll,
492         &clk_mout_hpll.clk,
493 };
494
495 static struct clksrc_sources clkset_spi = {
496         .sources        = clkset_spi_list,
497         .nr_sources     = ARRAY_SIZE(clkset_spi_list),
498 };
499
500 static struct clk *clkset_uart_list[] = {
501         &clk_mout_epll.clk,
502         &clk_dout_mpll,
503 };
504
505 static struct clksrc_sources clkset_uart = {
506         .sources        = clkset_uart_list,
507         .nr_sources     = ARRAY_SIZE(clkset_uart_list),
508 };
509
510 static struct clk *clkset_audio1_list[] = {
511         &clk_mout_epll.clk,
512         &clk_dout_mpll,
513         &clk_fin_epll,
514         &clk_iis_cd1,
515         &clk_pcm_cd1,
516         &clk_mout_hpll.clk,
517 };
518
519 static struct clksrc_sources clkset_audio1 = {
520         .sources        = clkset_audio1_list,
521         .nr_sources     = ARRAY_SIZE(clkset_audio1_list),
522 };
523
524 static struct clk *clkset_audio2_list[] = {
525         &clk_mout_epll.clk,
526         &clk_dout_mpll,
527         &clk_fin_epll,
528         &clk_iis_cd2,
529         &clk_mout_hpll.clk,
530 };
531
532 static struct clksrc_sources clkset_audio2 = {
533         .sources        = clkset_audio2_list,
534         .nr_sources     = ARRAY_SIZE(clkset_audio2_list),
535 };
536
537 static struct clksrc_clk clksrc_audio[] = {
538         {
539                 .clk    = {
540                         .name           = "audio-bus",
541                         .id             = 0,
542                         .ctrlbit        = S5PC100_CLKGATE_SCLK1_AUDIO0,
543                         .enable         = s5pc100_sclk1_ctrl,
544                 },
545                 .sources = &clkset_audio0,
546                 .reg_div = { .reg = S5PC100_CLKDIV4, .shift = 12, .size = 4, },
547                 .reg_src = { .reg = S5PC100_CLKSRC3, .shift = 12, .size = 3, },
548         }, {
549                 .clk    = {
550                         .name           = "audio-bus",
551                         .id             = 1,
552                         .ctrlbit        = S5PC100_CLKGATE_SCLK1_AUDIO1,
553                         .enable         = s5pc100_sclk1_ctrl,
554                 },
555                 .sources = &clkset_audio1,
556                 .reg_div = { .reg = S5PC100_CLKDIV4, .shift = 16, .size = 4, },
557                 .reg_src = { .reg = S5PC100_CLKSRC3, .shift = 16, .size = 3, },
558         }, {
559                 .clk    = {
560                         .name           = "audio-bus",
561                         .id             = 2,
562                         .ctrlbit        = S5PC100_CLKGATE_SCLK1_AUDIO2,
563                         .enable         = s5pc100_sclk1_ctrl,
564                 },
565                 .sources = &clkset_audio2,
566                 .reg_div = { .reg = S5PC100_CLKDIV4, .shift = 20, .size = 4, },
567                 .reg_src = { .reg = S5PC100_CLKSRC3, .shift = 20, .size = 3, },
568         },
569 };
570
571 static struct clk *clkset_spdif_list[] = {
572         &clksrc_audio[0].clk,
573         &clksrc_audio[1].clk,
574         &clksrc_audio[2].clk,
575 };
576
577 static struct clksrc_sources clkset_spdif = {
578         .sources        = clkset_spdif_list,
579         .nr_sources     = ARRAY_SIZE(clkset_spdif_list),
580 };
581
582 static struct clk *clkset_lcd_fimc_list[] = {
583         &clk_mout_epll.clk,
584         &clk_dout_mpll,
585         &clk_mout_hpll.clk,
586         &clk_vclk_54m,
587 };
588
589 static struct clksrc_sources clkset_lcd_fimc = {
590         .sources        = clkset_lcd_fimc_list,
591         .nr_sources     = ARRAY_SIZE(clkset_lcd_fimc_list),
592 };
593
594 static struct clk *clkset_mmc_list[] = {
595         &clk_mout_epll.clk,
596         &clk_dout_mpll,
597         &clk_fin_epll,
598         &clk_mout_hpll.clk ,
599 };
600
601 static struct clksrc_sources clkset_mmc = {
602         .sources        = clkset_mmc_list,
603         .nr_sources     = ARRAY_SIZE(clkset_mmc_list),
604 };
605
606 static struct clk *clkset_usbhost_list[] = {
607         &clk_mout_epll.clk,
608         &clk_dout_mpll,
609         &clk_mout_hpll.clk,
610         &clk_48m,
611 };
612
613 static struct clksrc_sources clkset_usbhost = {
614         .sources        = clkset_usbhost_list,
615         .nr_sources     = ARRAY_SIZE(clkset_usbhost_list),
616 };
617
618 static struct clksrc_clk clksrc_clks[] = {
619         {
620                 .clk    = {
621                         .name           = "spi_bus",
622                         .id             = 0,
623                         .ctrlbit        = S5PC100_CLKGATE_SCLK0_SPI0,
624                         .enable         = s5pc100_sclk0_ctrl,
625
626                 },
627                 .sources = &clkset_spi,
628                 .reg_div = { .reg = S5PC100_CLKDIV2, .shift = 4, .size = 4, },
629                 .reg_src = { .reg = S5PC100_CLKSRC1, .shift = 4, .size = 2, },
630         }, {
631                 .clk    = {
632                         .name           = "spi_bus",
633                         .id             = 1,
634                         .ctrlbit        = S5PC100_CLKGATE_SCLK0_SPI1,
635                         .enable         = s5pc100_sclk0_ctrl,
636                 },
637                 .sources = &clkset_spi,
638                 .reg_div = { .reg = S5PC100_CLKDIV2, .shift = 8, .size = 4, },
639                 .reg_src = { .reg = S5PC100_CLKSRC1, .shift = 8, .size = 2, },
640         }, {
641                 .clk    = {
642                         .name           = "spi_bus",
643                         .id             = 2,
644                         .ctrlbit        = S5PC100_CLKGATE_SCLK0_SPI2,
645                         .enable         = s5pc100_sclk0_ctrl,
646                 },
647                 .sources = &clkset_spi,
648                 .reg_div = { .reg = S5PC100_CLKDIV2, .shift = 12, .size = 4, },
649                 .reg_src = { .reg = S5PC100_CLKSRC1, .shift = 12, .size = 2, },
650         }, {
651                 .clk    = {
652                         .name           = "uclk1",
653                         .id             = -1,
654                         .ctrlbit        = S5PC100_CLKGATE_SCLK0_UART,
655                         .enable         = s5pc100_sclk0_ctrl,
656                 },
657                 .sources = &clkset_uart,
658                 .reg_div = { .reg = S5PC100_CLKDIV2, .shift = 0, .size = 3, },
659                 .reg_src = { .reg = S5PC100_CLKSRC1, .shift = 0, .size = 1, },
660         }, {
661                 .clk    = {
662                         .name           = "spdif",
663                         .id             = -1,
664                 },
665                 .sources        = &clkset_spdif,
666                 .reg_src = { .reg = S5PC100_CLKSRC3, .shift = 24, .size = 2, },
667         }, {
668                 .clk    = {
669                         .name           = "lcd",
670                         .id             = -1,
671                         .ctrlbit        = S5PC100_CLKGATE_SCLK1_LCD,
672                         .enable         = s5pc100_sclk1_ctrl,
673                 },
674                 .sources = &clkset_lcd_fimc,
675                 .reg_div = { .reg = S5PC100_CLKDIV3, .shift = 12, .size = 4, },
676                 .reg_src = { .reg = S5PC100_CLKSRC2, .shift = 12, .size = 2, },
677         }, {
678                 .clk    = {
679                         .name           = "fimc",
680                         .id             = 0,
681                         .ctrlbit        = S5PC100_CLKGATE_SCLK1_FIMC0,
682                         .enable         = s5pc100_sclk1_ctrl,
683                 },
684                 .sources = &clkset_lcd_fimc,
685                 .reg_div = { .reg = S5PC100_CLKDIV3, .shift = 16, .size = 4, },
686                 .reg_src = { .reg = S5PC100_CLKSRC2, .shift = 16, .size = 2, },
687         }, {
688                 .clk    = {
689                         .name           = "fimc",
690                         .id             = 1,
691                         .ctrlbit        = S5PC100_CLKGATE_SCLK1_FIMC1,
692                         .enable         = s5pc100_sclk1_ctrl,
693                 },
694                 .sources        = &clkset_lcd_fimc,
695                 .reg_div = { .reg = S5PC100_CLKDIV3, .shift = 20, .size = 4, },
696                 .reg_src = { .reg = S5PC100_CLKSRC2, .shift = 20, .size = 2, },
697         }, {
698                 .clk    = {
699                         .name           = "fimc",
700                         .id             = 2,
701                         .ctrlbit        = S5PC100_CLKGATE_SCLK1_FIMC2,
702                         .enable         = s5pc100_sclk1_ctrl,
703                 },
704                 .sources = &clkset_lcd_fimc,
705                 .reg_div = { .reg = S5PC100_CLKDIV3, .shift = 24, .size = 4, },
706                 .reg_src = { .reg = S5PC100_CLKSRC2, .shift = 24, .size = 2, },
707         }, {
708                 .clk    = {
709                         .name           = "mmc_bus",
710                         .id             = 0,
711                         .ctrlbit        = S5PC100_CLKGATE_SCLK0_MMC0,
712                         .enable         = s5pc100_sclk0_ctrl,
713                 },
714                 .sources = &clkset_mmc,
715                 .reg_div = { .reg = S5PC100_CLKDIV3, .shift = 0, .size = 4, },
716                 .reg_src = { .reg = S5PC100_CLKSRC2, .shift = 0, .size = 2, },
717         }, {
718                 .clk    = {
719                         .name           = "mmc_bus",
720                         .id             = 1,
721                         .ctrlbit        = S5PC100_CLKGATE_SCLK0_MMC1,
722                         .enable         = s5pc100_sclk0_ctrl,
723                 },
724                 .sources = &clkset_mmc,
725                 .reg_div = { .reg = S5PC100_CLKDIV3, .shift = 4, .size = 4, },
726                 .reg_src = { .reg = S5PC100_CLKSRC2, .shift = 4, .size = 2, },
727         }, {
728                 .clk    = {
729                         .name           = "mmc_bus",
730                         .id             = 2,
731                         .ctrlbit        = S5PC100_CLKGATE_SCLK0_MMC2,
732                         .enable         = s5pc100_sclk0_ctrl,
733                 },
734                 .sources        = &clkset_mmc,
735                 .reg_div = { .reg = S5PC100_CLKDIV3, .shift = 8, .size = 4, },
736                 .reg_src = { .reg = S5PC100_CLKSRC2, .shift = 8, .size = 2, },
737         }, {
738                 .clk    = {
739                         .name           = "usbhost",
740                         .id             = -1,
741                         .ctrlbit        = S5PC100_CLKGATE_SCLK0_USBHOST,
742                         .enable         = s5pc100_sclk0_ctrl,
743                 },
744                 .sources = &clkset_usbhost,
745                 .reg_div = { .reg = S5PC100_CLKDIV2, .shift = 20, .size = 4, },
746                 .reg_src = { .reg = S5PC100_CLKSRC1, .shift = 20, .size = 2, },
747         }
748 };
749
750 /* Clock initialisation code */
751
752 static struct clksrc_clk *init_parents[] = {
753         &clk_mout_apll,
754         &clk_mout_mpll,
755         &clk_mout_am,
756         &clk_mout_onenand,
757         &clk_mout_epll,
758         &clk_mout_hpll,
759 };
760
761 #define GET_DIV(clk, field) ((((clk) & field##_MASK) >> field##_SHIFT) + 1)
762
763 void __init_or_cpufreq s5pc100_setup_clocks(void)
764 {
765         struct clk *xtal_clk;
766         unsigned long xtal;
767         unsigned long armclk;
768         unsigned long hclkd0;
769         unsigned long hclk;
770         unsigned long pclkd0;
771         unsigned long pclk;
772         unsigned long apll, mpll, epll, hpll;
773         unsigned int ptr;
774         u32 clkdiv0, clkdiv1;
775
776         printk(KERN_DEBUG "%s: registering clocks\n", __func__);
777
778         clkdiv0 = __raw_readl(S5PC100_CLKDIV0);
779         clkdiv1 = __raw_readl(S5PC100_CLKDIV1);
780
781         printk(KERN_DEBUG "%s: clkdiv0 = %08x, clkdiv1 = %08x\n", __func__, clkdiv0, clkdiv1);
782
783         xtal_clk = clk_get(NULL, "xtal");
784         BUG_ON(IS_ERR(xtal_clk));
785
786         xtal = clk_get_rate(xtal_clk);
787         clk_put(xtal_clk);
788
789         printk(KERN_DEBUG "%s: xtal is %ld\n", __func__, xtal);
790
791         apll = s5pc1xx_get_pll(xtal, __raw_readl(S5PC100_APLL_CON));
792         mpll = s5pc1xx_get_pll(xtal, __raw_readl(S5PC100_MPLL_CON));
793         epll = s5pc1xx_get_pll(xtal, __raw_readl(S5PC100_EPLL_CON));
794         hpll = s5pc1xx_get_pll(xtal, __raw_readl(S5PC100_HPLL_CON));
795
796         printk(KERN_INFO "S5PC100: Apll=%ld.%03ld Mhz, Mpll=%ld.%03ld Mhz"
797                 ", Epll=%ld.%03ld Mhz, Hpll=%ld.%03ld Mhz\n",
798                 print_mhz(apll), print_mhz(mpll),
799                 print_mhz(epll), print_mhz(hpll));
800
801         armclk = apll / GET_DIV(clkdiv0, S5PC100_CLKDIV0_APLL);
802         armclk = armclk / GET_DIV(clkdiv0, S5PC100_CLKDIV0_ARM);
803         hclkd0 = armclk / GET_DIV(clkdiv0, S5PC100_CLKDIV0_D0);
804         pclkd0 = hclkd0 / GET_DIV(clkdiv0, S5PC100_CLKDIV0_PCLKD0);
805         hclk = mpll / GET_DIV(clkdiv1, S5PC100_CLKDIV1_D1);
806         pclk = hclk / GET_DIV(clkdiv1, S5PC100_CLKDIV1_PCLKD1);
807
808         printk(KERN_INFO "S5PC100: ARMCLK=%ld.%03ld MHz, HCLKD0=%ld.%03ld MHz,"
809                 " PCLKD0=%ld.%03ld MHz\n, HCLK=%ld.%03ld MHz,"
810                 " PCLK=%ld.%03ld MHz\n",
811                 print_mhz(armclk), print_mhz(hclkd0),
812                 print_mhz(pclkd0), print_mhz(hclk), print_mhz(pclk));
813
814         clk_fout_apll.rate = apll;
815         clk_fout_mpll.rate = mpll;
816         clk_fout_epll.rate = epll;
817         clk_fout_hpll.rate = hpll;
818
819         clk_h.rate = hclk;
820         clk_p.rate = pclk;
821         clk_f.rate = armclk;
822
823         for (ptr = 0; ptr < ARRAY_SIZE(init_parents); ptr++)
824                 s3c_set_clksrc(init_parents[ptr], true);
825
826         for (ptr = 0; ptr < ARRAY_SIZE(clksrc_audio); ptr++)
827                 s3c_set_clksrc(clksrc_audio + ptr, true);
828
829         for (ptr = 0; ptr < ARRAY_SIZE(clksrc_clks); ptr++)
830                 s3c_set_clksrc(clksrc_clks + ptr, true);
831 }
832
833 static struct clk *clks[] __initdata = {
834         &clk_ext_xtal_mux,
835         &clk_dout_apll,
836         &clk_dout_d0_bus,
837         &clk_dout_pclkd0,
838         &clk_dout_apll2,
839         &clk_mout_apll.clk,
840         &clk_mout_mpll.clk,
841         &clk_mout_epll.clk,
842         &clk_mout_hpll.clk,
843         &clk_mout_am.clk,
844         &clk_dout_d1_bus,
845         &clk_mout_onenand.clk,
846         &clk_dout_pclkd1,
847         &clk_dout_mpll2,
848         &clk_dout_cam,
849         &clk_dout_mpll,
850         &clk_fout_epll,
851         &clk_iis_cd0,
852         &clk_iis_cd1,
853         &clk_iis_cd2,
854         &clk_pcm_cd0,
855         &clk_pcm_cd1,
856         &clk_arm,
857 };
858
859 void __init s5pc100_register_clocks(void)
860 {
861         struct clk *clkp;
862         int ret;
863         int ptr;
864
865         for (ptr = 0; ptr < ARRAY_SIZE(clks); ptr++) {
866                 clkp = clks[ptr];
867                 ret = s3c24xx_register_clock(clkp);
868                 if (ret < 0) {
869                         printk(KERN_ERR "Failed to register clock %s (%d)\n",
870                                clkp->name, ret);
871                 }
872         }
873
874         s3c_register_clksrc(clksrc_audio, ARRAY_SIZE(clksrc_audio));
875         s3c_register_clksrc(clksrc_clks, ARRAY_SIZE(clksrc_clks));
876 }