Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/bp/bp
[sfrench/cifs-2.6.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/cpu.h>
33 #include <plat/pll.h>
34 #include <plat/devs.h>
35 #include <plat/s5pc100.h>
36
37 /* fin_apll, fin_mpll and fin_epll are all the same clock, which we call
38  * ext_xtal_mux for want of an actual name from the manual.
39 */
40
41 static struct clk clk_ext_xtal_mux = {
42         .name           = "ext_xtal",
43         .id             = -1,
44 };
45
46 #define clk_fin_apll clk_ext_xtal_mux
47 #define clk_fin_mpll clk_ext_xtal_mux
48 #define clk_fin_epll clk_ext_xtal_mux
49 #define clk_fin_hpll clk_ext_xtal_mux
50
51 #define clk_fout_mpll   clk_mpll
52 #define clk_vclk_54m    clk_54m
53
54 struct clk_sources {
55         unsigned int    nr_sources;
56         struct clk      **sources;
57 };
58
59 struct clksrc_clk {
60         struct clk              clk;
61         unsigned int            mask;
62         unsigned int            shift;
63
64         struct clk_sources      *sources;
65
66         unsigned int            divider_shift;
67         void __iomem            *reg_divider;
68         void __iomem            *reg_source;
69 };
70
71 /* APLL */
72 static struct clk clk_fout_apll = {
73         .name           = "fout_apll",
74         .id             = -1,
75         .rate           = 27000000,
76 };
77
78 static struct clk *clk_src_apll_list[] = {
79         [0] = &clk_fin_apll,
80         [1] = &clk_fout_apll,
81 };
82
83 static struct clk_sources clk_src_apll = {
84         .sources        = clk_src_apll_list,
85         .nr_sources     = ARRAY_SIZE(clk_src_apll_list),
86 };
87
88 static struct clksrc_clk clk_mout_apll = {
89         .clk    = {
90                 .name           = "mout_apll",
91                 .id             = -1,
92         },
93         .shift          = S5PC100_CLKSRC0_APLL_SHIFT,
94         .mask           = S5PC100_CLKSRC0_APLL_MASK,
95         .sources        = &clk_src_apll,
96         .reg_source     = S5PC100_CLKSRC0,
97 };
98
99 static unsigned long s5pc100_clk_dout_apll_get_rate(struct clk *clk)
100 {
101         unsigned long rate = clk_get_rate(clk->parent);
102         unsigned int ratio;
103
104         ratio = __raw_readl(S5PC100_CLKDIV0) & S5PC100_CLKDIV0_APLL_MASK;
105         ratio >>= S5PC100_CLKDIV0_APLL_SHIFT;
106
107         return rate / (ratio + 1);
108 }
109
110 static struct clk clk_dout_apll = {
111         .name           = "dout_apll",
112         .id             = -1,
113         .parent         = &clk_mout_apll.clk,
114         .get_rate       = s5pc100_clk_dout_apll_get_rate,
115 };
116
117 static unsigned long s5pc100_clk_arm_get_rate(struct clk *clk)
118 {
119         unsigned long rate = clk_get_rate(clk->parent);
120         unsigned int ratio;
121
122         ratio = __raw_readl(S5PC100_CLKDIV0) & S5PC100_CLKDIV0_ARM_MASK;
123         ratio >>= S5PC100_CLKDIV0_ARM_SHIFT;
124
125         return rate / (ratio + 1);
126 }
127
128 static unsigned long s5pc100_clk_arm_round_rate(struct clk *clk,
129                                                 unsigned long rate)
130 {
131         unsigned long parent = clk_get_rate(clk->parent);
132         u32 div;
133
134         if (parent < rate)
135                 return rate;
136
137         div = (parent / rate) - 1;
138         if (div > S5PC100_CLKDIV0_ARM_MASK)
139                 div = S5PC100_CLKDIV0_ARM_MASK;
140
141         return parent / (div + 1);
142 }
143
144 static int s5pc100_clk_arm_set_rate(struct clk *clk, unsigned long rate)
145 {
146         unsigned long parent = clk_get_rate(clk->parent);
147         u32 div;
148         u32 val;
149
150         if (rate < parent / (S5PC100_CLKDIV0_ARM_MASK + 1))
151                 return -EINVAL;
152
153         rate = clk_round_rate(clk, rate);
154         div = clk_get_rate(clk->parent) / rate;
155
156         val = __raw_readl(S5PC100_CLKDIV0);
157         val &= S5PC100_CLKDIV0_ARM_MASK;
158         val |= (div - 1);
159         __raw_writel(val, S5PC100_CLKDIV0);
160
161         return 0;
162 }
163
164 static struct clk clk_arm = {
165         .name           = "armclk",
166         .id             = -1,
167         .parent         = &clk_dout_apll,
168         .get_rate       = s5pc100_clk_arm_get_rate,
169         .set_rate       = s5pc100_clk_arm_set_rate,
170         .round_rate     = s5pc100_clk_arm_round_rate,
171 };
172
173 static unsigned long s5pc100_clk_dout_d0_bus_get_rate(struct clk *clk)
174 {
175         unsigned long rate = clk_get_rate(clk->parent);
176         unsigned int ratio;
177
178         ratio = __raw_readl(S5PC100_CLKDIV0) & S5PC100_CLKDIV0_D0_MASK;
179         ratio >>= S5PC100_CLKDIV0_D0_SHIFT;
180
181         return rate / (ratio + 1);
182 }
183
184 static struct clk clk_dout_d0_bus = {
185         .name           = "dout_d0_bus",
186         .id             = -1,
187         .parent         = &clk_arm,
188         .get_rate       = s5pc100_clk_dout_d0_bus_get_rate,
189 };
190
191 static unsigned long s5pc100_clk_dout_pclkd0_get_rate(struct clk *clk)
192 {
193         unsigned long rate = clk_get_rate(clk->parent);
194         unsigned int ratio;
195
196         ratio = __raw_readl(S5PC100_CLKDIV0) & S5PC100_CLKDIV0_PCLKD0_MASK;
197         ratio >>= S5PC100_CLKDIV0_PCLKD0_SHIFT;
198
199         return rate / (ratio + 1);
200 }
201
202 static struct clk clk_dout_pclkd0 = {
203         .name           = "dout_pclkd0",
204         .id             = -1,
205         .parent         = &clk_dout_d0_bus,
206         .get_rate       = s5pc100_clk_dout_pclkd0_get_rate,
207 };
208
209 static unsigned long s5pc100_clk_dout_apll2_get_rate(struct clk *clk)
210 {
211         unsigned long rate = clk_get_rate(clk->parent);
212         unsigned int ratio;
213
214         ratio = __raw_readl(S5PC100_CLKDIV1) & S5PC100_CLKDIV1_APLL2_MASK;
215         ratio >>= S5PC100_CLKDIV1_APLL2_SHIFT;
216
217         return rate / (ratio + 1);
218 }
219
220 static struct clk clk_dout_apll2 = {
221         .name           = "dout_apll2",
222         .id             = -1,
223         .parent         = &clk_mout_apll.clk,
224         .get_rate       = s5pc100_clk_dout_apll2_get_rate,
225 };
226
227 /* MPLL */
228 static struct clk *clk_src_mpll_list[] = {
229         [0] = &clk_fin_mpll,
230         [1] = &clk_fout_mpll,
231 };
232
233 static struct clk_sources clk_src_mpll = {
234         .sources        = clk_src_mpll_list,
235         .nr_sources     = ARRAY_SIZE(clk_src_mpll_list),
236 };
237
238 static struct clksrc_clk clk_mout_mpll = {
239         .clk = {
240                 .name           = "mout_mpll",
241                 .id             = -1,
242         },
243         .shift          = S5PC100_CLKSRC0_MPLL_SHIFT,
244         .mask           = S5PC100_CLKSRC0_MPLL_MASK,
245         .sources        = &clk_src_mpll,
246         .reg_source     = S5PC100_CLKSRC0,
247 };
248
249 static struct clk *clkset_am_list[] = {
250         [0] = &clk_mout_mpll.clk,
251         [1] = &clk_dout_apll2,
252 };
253
254 static struct clk_sources clk_src_am = {
255         .sources        = clkset_am_list,
256         .nr_sources     = ARRAY_SIZE(clkset_am_list),
257 };
258
259 static struct clksrc_clk clk_mout_am = {
260         .clk = {
261                 .name           = "mout_am",
262                 .id             = -1,
263         },
264         .shift          = S5PC100_CLKSRC0_AMMUX_SHIFT,
265         .mask           = S5PC100_CLKSRC0_AMMUX_MASK,
266         .sources        = &clk_src_am,
267         .reg_source     = S5PC100_CLKSRC0,
268 };
269
270 static unsigned long s5pc100_clk_dout_d1_bus_get_rate(struct clk *clk)
271 {
272         unsigned long rate = clk_get_rate(clk->parent);
273         unsigned int ratio;
274
275         printk(KERN_DEBUG "%s: parent is %ld\n", __func__, rate);
276
277         ratio = __raw_readl(S5PC100_CLKDIV1) & S5PC100_CLKDIV1_D1_MASK;
278         ratio >>= S5PC100_CLKDIV1_D1_SHIFT;
279
280         return rate / (ratio + 1);
281 }
282
283 static struct clk clk_dout_d1_bus = {
284         .name           = "dout_d1_bus",
285         .id             = -1,
286         .parent         = &clk_mout_am.clk,
287         .get_rate       = s5pc100_clk_dout_d1_bus_get_rate,
288 };
289
290 static struct clk *clkset_onenand_list[] = {
291         [0] = &clk_dout_d0_bus,
292         [1] = &clk_dout_d1_bus,
293 };
294
295 static struct clk_sources clk_src_onenand = {
296         .sources        = clkset_onenand_list,
297         .nr_sources     = ARRAY_SIZE(clkset_onenand_list),
298 };
299
300 static struct clksrc_clk clk_mout_onenand = {
301         .clk = {
302                 .name           = "mout_onenand",
303                 .id             = -1,
304         },
305         .shift          = S5PC100_CLKSRC0_ONENAND_SHIFT,
306         .mask           = S5PC100_CLKSRC0_ONENAND_MASK,
307         .sources        = &clk_src_onenand,
308         .reg_source     = S5PC100_CLKSRC0,
309 };
310
311 static unsigned long s5pc100_clk_dout_pclkd1_get_rate(struct clk *clk)
312 {
313         unsigned long rate = clk_get_rate(clk->parent);
314         unsigned int ratio;
315
316         printk(KERN_DEBUG "%s: parent is %ld\n", __func__, rate);
317
318         ratio = __raw_readl(S5PC100_CLKDIV1) & S5PC100_CLKDIV1_PCLKD1_MASK;
319         ratio >>= S5PC100_CLKDIV1_PCLKD1_SHIFT;
320
321         return rate / (ratio + 1);
322 }
323
324 static struct clk clk_dout_pclkd1 = {
325         .name           = "dout_pclkd1",
326         .id             = -1,
327         .parent         = &clk_dout_d1_bus,
328         .get_rate       = s5pc100_clk_dout_pclkd1_get_rate,
329 };
330
331 static unsigned long s5pc100_clk_dout_mpll2_get_rate(struct clk *clk)
332 {
333         unsigned long rate = clk_get_rate(clk->parent);
334         unsigned int ratio;
335
336         printk(KERN_DEBUG "%s: parent is %ld\n", __func__, rate);
337
338         ratio = __raw_readl(S5PC100_CLKDIV1) & S5PC100_CLKDIV1_MPLL2_MASK;
339         ratio >>= S5PC100_CLKDIV1_MPLL2_SHIFT;
340
341         return rate / (ratio + 1);
342 }
343
344 static struct clk clk_dout_mpll2 = {
345         .name           = "dout_mpll2",
346         .id             = -1,
347         .parent         = &clk_mout_am.clk,
348         .get_rate       = s5pc100_clk_dout_mpll2_get_rate,
349 };
350
351 static unsigned long s5pc100_clk_dout_cam_get_rate(struct clk *clk)
352 {
353         unsigned long rate = clk_get_rate(clk->parent);
354         unsigned int ratio;
355
356         printk(KERN_DEBUG "%s: parent is %ld\n", __func__, rate);
357
358         ratio = __raw_readl(S5PC100_CLKDIV1) & S5PC100_CLKDIV1_CAM_MASK;
359         ratio >>= S5PC100_CLKDIV1_CAM_SHIFT;
360
361         return rate / (ratio + 1);
362 }
363
364 static struct clk clk_dout_cam = {
365         .name           = "dout_cam",
366         .id             = -1,
367         .parent         = &clk_dout_mpll2,
368         .get_rate       = s5pc100_clk_dout_cam_get_rate,
369 };
370
371 static unsigned long s5pc100_clk_dout_mpll_get_rate(struct clk *clk)
372 {
373         unsigned long rate = clk_get_rate(clk->parent);
374         unsigned int ratio;
375
376         printk(KERN_DEBUG "%s: parent is %ld\n", __func__, rate);
377
378         ratio = __raw_readl(S5PC100_CLKDIV1) & S5PC100_CLKDIV1_MPLL_MASK;
379         ratio >>= S5PC100_CLKDIV1_MPLL_SHIFT;
380
381         return rate / (ratio + 1);
382 }
383
384 static struct clk clk_dout_mpll = {
385         .name           = "dout_mpll",
386         .id             = -1,
387         .parent         = &clk_mout_am.clk,
388         .get_rate       = s5pc100_clk_dout_mpll_get_rate,
389 };
390
391 /* EPLL */
392 static struct clk clk_fout_epll = {
393         .name           = "fout_epll",
394         .id             = -1,
395 };
396
397 static struct clk *clk_src_epll_list[] = {
398         [0] = &clk_fin_epll,
399         [1] = &clk_fout_epll,
400 };
401
402 static struct clk_sources clk_src_epll = {
403         .sources        = clk_src_epll_list,
404         .nr_sources     = ARRAY_SIZE(clk_src_epll_list),
405 };
406
407 static struct clksrc_clk clk_mout_epll = {
408         .clk    = {
409                 .name           = "mout_epll",
410                 .id             = -1,
411         },
412         .shift          = S5PC100_CLKSRC0_EPLL_SHIFT,
413         .mask           = S5PC100_CLKSRC0_EPLL_MASK,
414         .sources        = &clk_src_epll,
415         .reg_source     = S5PC100_CLKSRC0,
416 };
417
418 /* HPLL */
419 static struct clk clk_fout_hpll = {
420         .name           = "fout_hpll",
421         .id             = -1,
422 };
423
424 static struct clk *clk_src_hpll_list[] = {
425         [0] = &clk_27m,
426         [1] = &clk_fout_hpll,
427 };
428
429 static struct clk_sources clk_src_hpll = {
430         .sources        = clk_src_hpll_list,
431         .nr_sources     = ARRAY_SIZE(clk_src_hpll_list),
432 };
433
434 static struct clksrc_clk clk_mout_hpll = {
435         .clk    = {
436                 .name           = "mout_hpll",
437                 .id             = -1,
438         },
439         .shift          = S5PC100_CLKSRC0_HPLL_SHIFT,
440         .mask           = S5PC100_CLKSRC0_HPLL_MASK,
441         .sources        = &clk_src_hpll,
442         .reg_source     = S5PC100_CLKSRC0,
443 };
444
445 /* Peripherals */
446 /*
447  * The peripheral clocks are all controlled via clocksource followed
448  * by an optional divider and gate stage. We currently roll this into
449  * one clock which hides the intermediate clock from the mux.
450  *
451  * Note, the JPEG clock can only be an even divider...
452  *
453  * The scaler and LCD clocks depend on the S5PC100 version, and also
454  * have a common parent divisor so are not included here.
455  */
456
457 static inline struct clksrc_clk *to_clksrc(struct clk *clk)
458 {
459         return container_of(clk, struct clksrc_clk, clk);
460 }
461
462 static unsigned long s5pc100_getrate_clksrc(struct clk *clk)
463 {
464         struct clksrc_clk *sclk = to_clksrc(clk);
465         unsigned long rate = clk_get_rate(clk->parent);
466         u32 clkdiv = __raw_readl(sclk->reg_divider);
467
468         clkdiv >>= sclk->divider_shift;
469         clkdiv &= 0xf;
470         clkdiv++;
471
472         rate /= clkdiv;
473         return rate;
474 }
475
476 static int s5pc100_setrate_clksrc(struct clk *clk, unsigned long rate)
477 {
478         struct clksrc_clk *sclk = to_clksrc(clk);
479         void __iomem *reg = sclk->reg_divider;
480         unsigned int div;
481         u32 val;
482
483         rate = clk_round_rate(clk, rate);
484         div = clk_get_rate(clk->parent) / rate;
485         if (div > 16)
486                 return -EINVAL;
487
488         val = __raw_readl(reg);
489         val &= ~(0xf << sclk->divider_shift);
490         val |= (div - 1) << sclk->divider_shift;
491         __raw_writel(val, reg);
492
493         return 0;
494 }
495
496 static int s5pc100_setparent_clksrc(struct clk *clk, struct clk *parent)
497 {
498         struct clksrc_clk *sclk = to_clksrc(clk);
499         struct clk_sources *srcs = sclk->sources;
500         u32 clksrc = __raw_readl(sclk->reg_source);
501         int src_nr = -1;
502         int ptr;
503
504         for (ptr = 0; ptr < srcs->nr_sources; ptr++)
505                 if (srcs->sources[ptr] == parent) {
506                         src_nr = ptr;
507                         break;
508                 }
509
510         if (src_nr >= 0) {
511                 clksrc &= ~sclk->mask;
512                 clksrc |= src_nr << sclk->shift;
513
514                 __raw_writel(clksrc, sclk->reg_source);
515                 return 0;
516         }
517
518         return -EINVAL;
519 }
520
521 static unsigned long s5pc100_roundrate_clksrc(struct clk *clk,
522                                               unsigned long rate)
523 {
524         unsigned long parent_rate = clk_get_rate(clk->parent);
525         int div;
526
527         if (rate > parent_rate)
528                 rate = parent_rate;
529         else {
530                 div = rate / parent_rate;
531
532                 if (div == 0)
533                         div = 1;
534                 if (div > 16)
535                         div = 16;
536
537                 rate = parent_rate / div;
538         }
539
540         return rate;
541 }
542
543 static struct clk *clkset_spi_list[] = {
544         &clk_mout_epll.clk,
545         &clk_dout_mpll2,
546         &clk_fin_epll,
547         &clk_mout_hpll.clk,
548 };
549
550 static struct clk_sources clkset_spi = {
551         .sources        = clkset_spi_list,
552         .nr_sources     = ARRAY_SIZE(clkset_spi_list),
553 };
554
555 static struct clksrc_clk clk_spi0 = {
556         .clk    = {
557                 .name           = "spi_bus",
558                 .id             = 0,
559                 .ctrlbit        = S5PC100_CLKGATE_SCLK0_SPI0,
560                 .enable         = s5pc100_sclk0_ctrl,
561                 .set_parent     = s5pc100_setparent_clksrc,
562                 .get_rate       = s5pc100_getrate_clksrc,
563                 .set_rate       = s5pc100_setrate_clksrc,
564                 .round_rate     = s5pc100_roundrate_clksrc,
565         },
566         .shift          = S5PC100_CLKSRC1_SPI0_SHIFT,
567         .mask           = S5PC100_CLKSRC1_SPI0_MASK,
568         .sources        = &clkset_spi,
569         .divider_shift  = S5PC100_CLKDIV2_SPI0_SHIFT,
570         .reg_divider    = S5PC100_CLKDIV2,
571         .reg_source     = S5PC100_CLKSRC1,
572 };
573
574 static struct clksrc_clk clk_spi1 = {
575         .clk    = {
576                 .name           = "spi_bus",
577                 .id             = 1,
578                 .ctrlbit        = S5PC100_CLKGATE_SCLK0_SPI1,
579                 .enable         = s5pc100_sclk0_ctrl,
580                 .set_parent     = s5pc100_setparent_clksrc,
581                 .get_rate       = s5pc100_getrate_clksrc,
582                 .set_rate       = s5pc100_setrate_clksrc,
583                 .round_rate     = s5pc100_roundrate_clksrc,
584         },
585         .shift          = S5PC100_CLKSRC1_SPI1_SHIFT,
586         .mask           = S5PC100_CLKSRC1_SPI1_MASK,
587         .sources        = &clkset_spi,
588         .divider_shift  = S5PC100_CLKDIV2_SPI1_SHIFT,
589         .reg_divider    = S5PC100_CLKDIV2,
590         .reg_source     = S5PC100_CLKSRC1,
591 };
592
593 static struct clksrc_clk clk_spi2 = {
594         .clk    = {
595                 .name           = "spi_bus",
596                 .id             = 2,
597                 .ctrlbit        = S5PC100_CLKGATE_SCLK0_SPI2,
598                 .enable         = s5pc100_sclk0_ctrl,
599                 .set_parent     = s5pc100_setparent_clksrc,
600                 .get_rate       = s5pc100_getrate_clksrc,
601                 .set_rate       = s5pc100_setrate_clksrc,
602                 .round_rate     = s5pc100_roundrate_clksrc,
603         },
604         .shift          = S5PC100_CLKSRC1_SPI2_SHIFT,
605         .mask           = S5PC100_CLKSRC1_SPI2_MASK,
606         .sources        = &clkset_spi,
607         .divider_shift  = S5PC100_CLKDIV2_SPI2_SHIFT,
608         .reg_divider    = S5PC100_CLKDIV2,
609         .reg_source     = S5PC100_CLKSRC1,
610 };
611
612 static struct clk *clkset_uart_list[] = {
613         &clk_mout_epll.clk,
614         &clk_dout_mpll,
615 };
616
617 static struct clk_sources clkset_uart = {
618         .sources        = clkset_uart_list,
619         .nr_sources     = ARRAY_SIZE(clkset_uart_list),
620 };
621
622 static struct clksrc_clk clk_uart_uclk1 = {
623         .clk    = {
624                 .name           = "uclk1",
625                 .id             = -1,
626                 .ctrlbit        = S5PC100_CLKGATE_SCLK0_UART,
627                 .enable         = s5pc100_sclk0_ctrl,
628                 .set_parent     = s5pc100_setparent_clksrc,
629                 .get_rate       = s5pc100_getrate_clksrc,
630                 .set_rate       = s5pc100_setrate_clksrc,
631                 .round_rate     = s5pc100_roundrate_clksrc,
632         },
633         .shift          = S5PC100_CLKSRC1_UART_SHIFT,
634         .mask           = S5PC100_CLKSRC1_UART_MASK,
635         .sources        = &clkset_uart,
636         .divider_shift  = S5PC100_CLKDIV2_UART_SHIFT,
637         .reg_divider    = S5PC100_CLKDIV2,
638         .reg_source     = S5PC100_CLKSRC1,
639 };
640
641 static struct clk clk_iis_cd0 = {
642         .name           = "iis_cdclk0",
643         .id             = -1,
644 };
645
646 static struct clk clk_iis_cd1 = {
647         .name           = "iis_cdclk1",
648         .id             = -1,
649 };
650
651 static struct clk clk_iis_cd2 = {
652         .name           = "iis_cdclk2",
653         .id             = -1,
654 };
655
656 static struct clk clk_pcm_cd0 = {
657         .name           = "pcm_cdclk0",
658         .id             = -1,
659 };
660
661 static struct clk clk_pcm_cd1 = {
662         .name           = "pcm_cdclk1",
663         .id             = -1,
664 };
665
666 static struct clk *clkset_audio0_list[] = {
667         &clk_mout_epll.clk,
668         &clk_dout_mpll,
669         &clk_fin_epll,
670         &clk_iis_cd0,
671         &clk_pcm_cd0,
672         &clk_mout_hpll.clk,
673 };
674
675 static struct clk_sources clkset_audio0 = {
676         .sources        = clkset_audio0_list,
677         .nr_sources     = ARRAY_SIZE(clkset_audio0_list),
678 };
679
680 static struct clksrc_clk clk_audio0 = {
681         .clk    = {
682                 .name           = "audio-bus",
683                 .id             = 0,
684                 .ctrlbit        = S5PC100_CLKGATE_SCLK1_AUDIO0,
685                 .enable         = s5pc100_sclk1_ctrl,
686                 .set_parent     = s5pc100_setparent_clksrc,
687                 .get_rate       = s5pc100_getrate_clksrc,
688                 .set_rate       = s5pc100_setrate_clksrc,
689                 .round_rate     = s5pc100_roundrate_clksrc,
690         },
691         .shift          = S5PC100_CLKSRC3_AUDIO0_SHIFT,
692         .mask           = S5PC100_CLKSRC3_AUDIO0_MASK,
693         .sources        = &clkset_audio0,
694         .divider_shift  = S5PC100_CLKDIV4_AUDIO0_SHIFT,
695         .reg_divider    = S5PC100_CLKDIV4,
696         .reg_source     = S5PC100_CLKSRC3,
697 };
698
699 static struct clk *clkset_audio1_list[] = {
700         &clk_mout_epll.clk,
701         &clk_dout_mpll,
702         &clk_fin_epll,
703         &clk_iis_cd1,
704         &clk_pcm_cd1,
705         &clk_mout_hpll.clk,
706 };
707
708 static struct clk_sources clkset_audio1 = {
709         .sources        = clkset_audio1_list,
710         .nr_sources     = ARRAY_SIZE(clkset_audio1_list),
711 };
712
713 static struct clksrc_clk clk_audio1 = {
714         .clk    = {
715                 .name           = "audio-bus",
716                 .id             = 1,
717                 .ctrlbit        = S5PC100_CLKGATE_SCLK1_AUDIO1,
718                 .enable         = s5pc100_sclk1_ctrl,
719                 .set_parent     = s5pc100_setparent_clksrc,
720                 .get_rate       = s5pc100_getrate_clksrc,
721                 .set_rate       = s5pc100_setrate_clksrc,
722                 .round_rate     = s5pc100_roundrate_clksrc,
723         },
724         .shift          = S5PC100_CLKSRC3_AUDIO1_SHIFT,
725         .mask           = S5PC100_CLKSRC3_AUDIO1_MASK,
726         .sources        = &clkset_audio1,
727         .divider_shift  = S5PC100_CLKDIV4_AUDIO1_SHIFT,
728         .reg_divider    = S5PC100_CLKDIV4,
729         .reg_source     = S5PC100_CLKSRC3,
730 };
731
732 static struct clk *clkset_audio2_list[] = {
733         &clk_mout_epll.clk,
734         &clk_dout_mpll,
735         &clk_fin_epll,
736         &clk_iis_cd2,
737         &clk_mout_hpll.clk,
738 };
739
740 static struct clk_sources clkset_audio2 = {
741         .sources        = clkset_audio2_list,
742         .nr_sources     = ARRAY_SIZE(clkset_audio2_list),
743 };
744
745 static struct clksrc_clk clk_audio2 = {
746         .clk    = {
747                 .name           = "audio-bus",
748                 .id             = 2,
749                 .ctrlbit        = S5PC100_CLKGATE_SCLK1_AUDIO2,
750                 .enable         = s5pc100_sclk1_ctrl,
751                 .set_parent     = s5pc100_setparent_clksrc,
752                 .get_rate       = s5pc100_getrate_clksrc,
753                 .set_rate       = s5pc100_setrate_clksrc,
754                 .round_rate     = s5pc100_roundrate_clksrc,
755         },
756         .shift          = S5PC100_CLKSRC3_AUDIO2_SHIFT,
757         .mask           = S5PC100_CLKSRC3_AUDIO2_MASK,
758         .sources        = &clkset_audio2,
759         .divider_shift  = S5PC100_CLKDIV4_AUDIO2_SHIFT,
760         .reg_divider    = S5PC100_CLKDIV4,
761         .reg_source     = S5PC100_CLKSRC3,
762 };
763
764 static struct clk *clkset_spdif_list[] = {
765         &clk_audio0.clk,
766         &clk_audio1.clk,
767         &clk_audio2.clk,
768 };
769
770 static struct clk_sources clkset_spdif = {
771         .sources        = clkset_spdif_list,
772         .nr_sources     = ARRAY_SIZE(clkset_spdif_list),
773 };
774
775 static struct clksrc_clk clk_spdif = {
776         .clk    = {
777                 .name           = "spdif",
778                 .id             = -1,
779         },
780         .shift          = S5PC100_CLKSRC3_SPDIF_SHIFT,
781         .mask           = S5PC100_CLKSRC3_SPDIF_MASK,
782         .sources        = &clkset_spdif,
783         .reg_source     = S5PC100_CLKSRC3,
784 };
785
786 static struct clk *clkset_lcd_fimc_list[] = {
787         &clk_mout_epll.clk,
788         &clk_dout_mpll,
789         &clk_mout_hpll.clk,
790         &clk_vclk_54m,
791 };
792
793 static struct clk_sources clkset_lcd_fimc = {
794         .sources        = clkset_lcd_fimc_list,
795         .nr_sources     = ARRAY_SIZE(clkset_lcd_fimc_list),
796 };
797
798 static struct clksrc_clk clk_lcd = {
799         .clk    = {
800                 .name           = "lcd",
801                 .id             = -1,
802                 .ctrlbit        = S5PC100_CLKGATE_SCLK1_LCD,
803                 .enable         = s5pc100_sclk1_ctrl,
804                 .set_parent     = s5pc100_setparent_clksrc,
805                 .get_rate       = s5pc100_getrate_clksrc,
806                 .set_rate       = s5pc100_setrate_clksrc,
807                 .round_rate     = s5pc100_roundrate_clksrc,
808         },
809         .shift          = S5PC100_CLKSRC2_LCD_SHIFT,
810         .mask           = S5PC100_CLKSRC2_LCD_MASK,
811         .sources        = &clkset_lcd_fimc,
812         .divider_shift  = S5PC100_CLKDIV3_LCD_SHIFT,
813         .reg_divider    = S5PC100_CLKDIV3,
814         .reg_source     = S5PC100_CLKSRC2,
815 };
816
817 static struct clksrc_clk clk_fimc0 = {
818         .clk    = {
819                 .name           = "fimc",
820                 .id             = 0,
821                 .ctrlbit        = S5PC100_CLKGATE_SCLK1_FIMC0,
822                 .enable         = s5pc100_sclk1_ctrl,
823                 .set_parent     = s5pc100_setparent_clksrc,
824                 .get_rate       = s5pc100_getrate_clksrc,
825                 .set_rate       = s5pc100_setrate_clksrc,
826                 .round_rate     = s5pc100_roundrate_clksrc,
827         },
828         .shift          = S5PC100_CLKSRC2_FIMC0_SHIFT,
829         .mask           = S5PC100_CLKSRC2_FIMC0_MASK,
830         .sources        = &clkset_lcd_fimc,
831         .divider_shift  = S5PC100_CLKDIV3_FIMC0_SHIFT,
832         .reg_divider    = S5PC100_CLKDIV3,
833         .reg_source     = S5PC100_CLKSRC2,
834 };
835
836 static struct clksrc_clk clk_fimc1 = {
837         .clk    = {
838                 .name           = "fimc",
839                 .id             = 1,
840                 .ctrlbit        = S5PC100_CLKGATE_SCLK1_FIMC1,
841                 .enable         = s5pc100_sclk1_ctrl,
842                 .set_parent     = s5pc100_setparent_clksrc,
843                 .get_rate       = s5pc100_getrate_clksrc,
844                 .set_rate       = s5pc100_setrate_clksrc,
845                 .round_rate     = s5pc100_roundrate_clksrc,
846         },
847         .shift          = S5PC100_CLKSRC2_FIMC1_SHIFT,
848         .mask           = S5PC100_CLKSRC2_FIMC1_MASK,
849         .sources        = &clkset_lcd_fimc,
850         .divider_shift  = S5PC100_CLKDIV3_FIMC1_SHIFT,
851         .reg_divider    = S5PC100_CLKDIV3,
852         .reg_source     = S5PC100_CLKSRC2,
853 };
854
855 static struct clksrc_clk clk_fimc2 = {
856         .clk    = {
857                 .name           = "fimc",
858                 .id             = 2,
859                 .ctrlbit        = S5PC100_CLKGATE_SCLK1_FIMC2,
860                 .enable         = s5pc100_sclk1_ctrl,
861                 .set_parent     = s5pc100_setparent_clksrc,
862                 .get_rate       = s5pc100_getrate_clksrc,
863                 .set_rate       = s5pc100_setrate_clksrc,
864                 .round_rate     = s5pc100_roundrate_clksrc,
865         },
866         .shift          = S5PC100_CLKSRC2_FIMC2_SHIFT,
867         .mask           = S5PC100_CLKSRC2_FIMC2_MASK,
868         .sources        = &clkset_lcd_fimc,
869         .divider_shift  = S5PC100_CLKDIV3_FIMC2_SHIFT,
870         .reg_divider    = S5PC100_CLKDIV3,
871         .reg_source     = S5PC100_CLKSRC2,
872 };
873
874 static struct clk *clkset_mmc_list[] = {
875         &clk_mout_epll.clk,
876         &clk_dout_mpll,
877         &clk_fin_epll,
878         &clk_mout_hpll.clk ,
879 };
880
881 static struct clk_sources clkset_mmc = {
882         .sources        = clkset_mmc_list,
883         .nr_sources     = ARRAY_SIZE(clkset_mmc_list),
884 };
885
886 static struct clksrc_clk clk_mmc0 = {
887         .clk    = {
888                 .name           = "mmc_bus",
889                 .id             = 0,
890                 .ctrlbit        = S5PC100_CLKGATE_SCLK0_MMC0,
891                 .enable         = s5pc100_sclk0_ctrl,
892                 .set_parent     = s5pc100_setparent_clksrc,
893                 .get_rate       = s5pc100_getrate_clksrc,
894                 .set_rate       = s5pc100_setrate_clksrc,
895                 .round_rate     = s5pc100_roundrate_clksrc,
896         },
897         .shift          = S5PC100_CLKSRC2_MMC0_SHIFT,
898         .mask           = S5PC100_CLKSRC2_MMC0_MASK,
899         .sources        = &clkset_mmc,
900         .divider_shift  = S5PC100_CLKDIV3_MMC0_SHIFT,
901         .reg_divider    = S5PC100_CLKDIV3,
902         .reg_source     = S5PC100_CLKSRC2,
903 };
904
905 static struct clksrc_clk clk_mmc1 = {
906         .clk    = {
907                 .name           = "mmc_bus",
908                 .id             = 1,
909                 .ctrlbit        = S5PC100_CLKGATE_SCLK0_MMC1,
910                 .enable         = s5pc100_sclk0_ctrl,
911                 .set_parent     = s5pc100_setparent_clksrc,
912                 .get_rate       = s5pc100_getrate_clksrc,
913                 .set_rate       = s5pc100_setrate_clksrc,
914                 .round_rate     = s5pc100_roundrate_clksrc,
915         },
916         .shift          = S5PC100_CLKSRC2_MMC1_SHIFT,
917         .mask           = S5PC100_CLKSRC2_MMC1_MASK,
918         .sources        = &clkset_mmc,
919         .divider_shift  = S5PC100_CLKDIV3_MMC1_SHIFT,
920         .reg_divider    = S5PC100_CLKDIV3,
921         .reg_source     = S5PC100_CLKSRC2,
922 };
923
924 static struct clksrc_clk clk_mmc2 = {
925         .clk    = {
926                 .name           = "mmc_bus",
927                 .id             = 2,
928                 .ctrlbit        = S5PC100_CLKGATE_SCLK0_MMC2,
929                 .enable         = s5pc100_sclk0_ctrl,
930                 .set_parent     = s5pc100_setparent_clksrc,
931                 .get_rate       = s5pc100_getrate_clksrc,
932                 .set_rate       = s5pc100_setrate_clksrc,
933                 .round_rate     = s5pc100_roundrate_clksrc,
934         },
935         .shift          = S5PC100_CLKSRC2_MMC2_SHIFT,
936         .mask           = S5PC100_CLKSRC2_MMC2_MASK,
937         .sources        = &clkset_mmc,
938         .divider_shift  = S5PC100_CLKDIV3_MMC2_SHIFT,
939         .reg_divider    = S5PC100_CLKDIV3,
940         .reg_source     = S5PC100_CLKSRC2,
941 };
942
943
944 static struct clk *clkset_usbhost_list[] = {
945         &clk_mout_epll.clk,
946         &clk_dout_mpll,
947         &clk_mout_hpll.clk,
948         &clk_48m,
949 };
950
951 static struct clk_sources clkset_usbhost = {
952         .sources        = clkset_usbhost_list,
953         .nr_sources     = ARRAY_SIZE(clkset_usbhost_list),
954 };
955
956 static struct clksrc_clk clk_usbhost = {
957         .clk    = {
958                 .name           = "usbhost",
959                 .id             = -1,
960                 .ctrlbit        = S5PC100_CLKGATE_SCLK0_USBHOST,
961                 .enable         = s5pc100_sclk0_ctrl,
962                 .set_parent     = s5pc100_setparent_clksrc,
963                 .get_rate       = s5pc100_getrate_clksrc,
964                 .set_rate       = s5pc100_setrate_clksrc,
965                 .round_rate     = s5pc100_roundrate_clksrc,
966         },
967         .shift          = S5PC100_CLKSRC1_UHOST_SHIFT,
968         .mask           = S5PC100_CLKSRC1_UHOST_MASK,
969         .sources        = &clkset_usbhost,
970         .divider_shift  = S5PC100_CLKDIV2_UHOST_SHIFT,
971         .reg_divider    = S5PC100_CLKDIV2,
972         .reg_source     = S5PC100_CLKSRC1,
973 };
974
975 /* Clock initialisation code */
976
977 static struct clksrc_clk *init_parents[] = {
978         &clk_mout_apll,
979         &clk_mout_mpll,
980         &clk_mout_am,
981         &clk_mout_onenand,
982         &clk_mout_epll,
983         &clk_mout_hpll,
984         &clk_spi0,
985         &clk_spi1,
986         &clk_spi2,
987         &clk_uart_uclk1,
988         &clk_audio0,
989         &clk_audio1,
990         &clk_audio2,
991         &clk_spdif,
992         &clk_lcd,
993         &clk_fimc0,
994         &clk_fimc1,
995         &clk_fimc2,
996         &clk_mmc0,
997         &clk_mmc1,
998         &clk_mmc2,
999         &clk_usbhost,
1000 };
1001
1002 static void __init_or_cpufreq s5pc100_set_clksrc(struct clksrc_clk *clk)
1003 {
1004         struct clk_sources *srcs = clk->sources;
1005         u32 clksrc = __raw_readl(clk->reg_source);
1006
1007         clksrc &= clk->mask;
1008         clksrc >>= clk->shift;
1009
1010         if (clksrc > srcs->nr_sources || !srcs->sources[clksrc]) {
1011                 printk(KERN_ERR "%s: bad source %d\n",
1012                        clk->clk.name, clksrc);
1013                 return;
1014         }
1015
1016         clk->clk.parent = srcs->sources[clksrc];
1017
1018         printk(KERN_INFO "%s: source is %s (%d), rate is %ld.%03ld MHz\n",
1019                 clk->clk.name, clk->clk.parent->name, clksrc,
1020                 print_mhz(clk_get_rate(&clk->clk)));
1021 }
1022
1023 #define GET_DIV(clk, field) ((((clk) & field##_MASK) >> field##_SHIFT) + 1)
1024
1025 void __init_or_cpufreq s5pc100_setup_clocks(void)
1026 {
1027         struct clk *xtal_clk;
1028         unsigned long xtal;
1029         unsigned long armclk;
1030         unsigned long hclkd0;
1031         unsigned long hclk;
1032         unsigned long pclkd0;
1033         unsigned long pclk;
1034         unsigned long apll, mpll, epll, hpll;
1035         unsigned int ptr;
1036         u32 clkdiv0, clkdiv1;
1037
1038         printk(KERN_DEBUG "%s: registering clocks\n", __func__);
1039
1040         clkdiv0 = __raw_readl(S5PC100_CLKDIV0);
1041         clkdiv1 = __raw_readl(S5PC100_CLKDIV1);
1042
1043         printk(KERN_DEBUG "%s: clkdiv0 = %08x, clkdiv1 = %08x\n", __func__, clkdiv0, clkdiv1);
1044
1045         xtal_clk = clk_get(NULL, "xtal");
1046         BUG_ON(IS_ERR(xtal_clk));
1047
1048         xtal = clk_get_rate(xtal_clk);
1049         clk_put(xtal_clk);
1050
1051         printk(KERN_DEBUG "%s: xtal is %ld\n", __func__, xtal);
1052
1053         apll = s5pc1xx_get_pll(xtal, __raw_readl(S5PC100_APLL_CON));
1054         mpll = s5pc1xx_get_pll(xtal, __raw_readl(S5PC100_MPLL_CON));
1055         epll = s5pc1xx_get_pll(xtal, __raw_readl(S5PC100_EPLL_CON));
1056         hpll = s5pc1xx_get_pll(xtal, __raw_readl(S5PC100_HPLL_CON));
1057
1058         printk(KERN_INFO "S5PC100: Apll=%ld.%03ld Mhz, Mpll=%ld.%03ld Mhz"
1059                 ", Epll=%ld.%03ld Mhz, Hpll=%ld.%03ld Mhz\n",
1060                 print_mhz(apll), print_mhz(mpll),
1061                 print_mhz(epll), print_mhz(hpll));
1062
1063         armclk = apll / GET_DIV(clkdiv0, S5PC100_CLKDIV0_APLL);
1064         armclk = armclk / GET_DIV(clkdiv0, S5PC100_CLKDIV0_ARM);
1065         hclkd0 = armclk / GET_DIV(clkdiv0, S5PC100_CLKDIV0_D0);
1066         pclkd0 = hclkd0 / GET_DIV(clkdiv0, S5PC100_CLKDIV0_PCLKD0);
1067         hclk = mpll / GET_DIV(clkdiv1, S5PC100_CLKDIV1_D1);
1068         pclk = hclk / GET_DIV(clkdiv1, S5PC100_CLKDIV1_PCLKD1);
1069
1070         printk(KERN_INFO "S5PC100: ARMCLK=%ld.%03ld MHz, HCLKD0=%ld.%03ld MHz,"
1071                 " PCLKD0=%ld.%03ld MHz\n, HCLK=%ld.%03ld MHz,"
1072                 " PCLK=%ld.%03ld MHz\n",
1073                 print_mhz(armclk), print_mhz(hclkd0),
1074                 print_mhz(pclkd0), print_mhz(hclk), print_mhz(pclk));
1075
1076         clk_fout_apll.rate = apll;
1077         clk_fout_mpll.rate = mpll;
1078         clk_fout_epll.rate = epll;
1079         clk_fout_hpll.rate = hpll;
1080
1081         clk_h.rate = hclk;
1082         clk_p.rate = pclk;
1083         clk_f.rate = armclk;
1084
1085         for (ptr = 0; ptr < ARRAY_SIZE(init_parents); ptr++)
1086                 s5pc100_set_clksrc(init_parents[ptr]);
1087 }
1088
1089 static struct clk *clks[] __initdata = {
1090         &clk_ext_xtal_mux,
1091         &clk_mout_apll.clk,
1092         &clk_dout_apll,
1093         &clk_dout_d0_bus,
1094         &clk_dout_pclkd0,
1095         &clk_dout_apll2,
1096         &clk_mout_mpll.clk,
1097         &clk_mout_am.clk,
1098         &clk_dout_d1_bus,
1099         &clk_mout_onenand.clk,
1100         &clk_dout_pclkd1,
1101         &clk_dout_mpll2,
1102         &clk_dout_cam,
1103         &clk_dout_mpll,
1104         &clk_mout_epll.clk,
1105         &clk_fout_epll,
1106         &clk_iis_cd0,
1107         &clk_iis_cd1,
1108         &clk_iis_cd2,
1109         &clk_pcm_cd0,
1110         &clk_pcm_cd1,
1111         &clk_spi0.clk,
1112         &clk_spi1.clk,
1113         &clk_spi2.clk,
1114         &clk_uart_uclk1.clk,
1115         &clk_audio0.clk,
1116         &clk_audio1.clk,
1117         &clk_audio2.clk,
1118         &clk_spdif.clk,
1119         &clk_lcd.clk,
1120         &clk_fimc0.clk,
1121         &clk_fimc1.clk,
1122         &clk_fimc2.clk,
1123         &clk_mmc0.clk,
1124         &clk_mmc1.clk,
1125         &clk_mmc2.clk,
1126         &clk_usbhost.clk,
1127         &clk_arm,
1128 };
1129
1130 void __init s5pc100_register_clocks(void)
1131 {
1132         struct clk *clkp;
1133         int ret;
1134         int ptr;
1135
1136         for (ptr = 0; ptr < ARRAY_SIZE(clks); ptr++) {
1137                 clkp = clks[ptr];
1138                 ret = s3c24xx_register_clock(clkp);
1139                 if (ret < 0) {
1140                         printk(KERN_ERR "Failed to register clock %s (%d)\n",
1141                                clkp->name, ret);
1142                 }
1143         }
1144 }