ARM: arm-soc: Merge branch 'next/pm2' into next/pm
[cascardo/linux.git] / arch / arm / mach-s3c64xx / clock.c
1 /* linux/arch/arm/plat-s3c64xx/clock.c
2  *
3  * Copyright 2008 Openmoko, Inc.
4  * Copyright 2008 Simtec Electronics
5  *      Ben Dooks <ben@simtec.co.uk>
6  *      http://armlinux.simtec.co.uk/
7  *
8  * S3C64XX Base clock support
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/interrupt.h>
18 #include <linux/ioport.h>
19 #include <linux/clk.h>
20 #include <linux/err.h>
21 #include <linux/io.h>
22
23 #include <mach/hardware.h>
24 #include <mach/map.h>
25
26 #include <mach/regs-sys.h>
27 #include <mach/regs-clock.h>
28
29 #include <plat/cpu.h>
30 #include <plat/devs.h>
31 #include <plat/cpu-freq.h>
32 #include <plat/clock.h>
33 #include <plat/clock-clksrc.h>
34 #include <plat/pll.h>
35
36 /* fin_apll, fin_mpll and fin_epll are all the same clock, which we call
37  * ext_xtal_mux for want of an actual name from the manual.
38 */
39
40 static struct clk clk_ext_xtal_mux = {
41         .name           = "ext_xtal",
42 };
43
44 #define clk_fin_apll clk_ext_xtal_mux
45 #define clk_fin_mpll clk_ext_xtal_mux
46 #define clk_fin_epll clk_ext_xtal_mux
47
48 #define clk_fout_mpll   clk_mpll
49 #define clk_fout_epll   clk_epll
50
51 struct clk clk_h2 = {
52         .name           = "hclk2",
53         .rate           = 0,
54 };
55
56 struct clk clk_27m = {
57         .name           = "clk_27m",
58         .rate           = 27000000,
59 };
60
61 static int clk_48m_ctrl(struct clk *clk, int enable)
62 {
63         unsigned long flags;
64         u32 val;
65
66         /* can't rely on clock lock, this register has other usages */
67         local_irq_save(flags);
68
69         val = __raw_readl(S3C64XX_OTHERS);
70         if (enable)
71                 val |= S3C64XX_OTHERS_USBMASK;
72         else
73                 val &= ~S3C64XX_OTHERS_USBMASK;
74
75         __raw_writel(val, S3C64XX_OTHERS);
76         local_irq_restore(flags);
77
78         return 0;
79 }
80
81 struct clk clk_48m = {
82         .name           = "clk_48m",
83         .rate           = 48000000,
84         .enable         = clk_48m_ctrl,
85 };
86
87 struct clk clk_xusbxti = {
88         .name           = "xusbxti",
89         .rate           = 48000000,
90 };
91
92 static int inline s3c64xx_gate(void __iomem *reg,
93                                 struct clk *clk,
94                                 int enable)
95 {
96         unsigned int ctrlbit = clk->ctrlbit;
97         u32 con;
98
99         con = __raw_readl(reg);
100
101         if (enable)
102                 con |= ctrlbit;
103         else
104                 con &= ~ctrlbit;
105
106         __raw_writel(con, reg);
107         return 0;
108 }
109
110 static int s3c64xx_pclk_ctrl(struct clk *clk, int enable)
111 {
112         return s3c64xx_gate(S3C_PCLK_GATE, clk, enable);
113 }
114
115 static int s3c64xx_hclk_ctrl(struct clk *clk, int enable)
116 {
117         return s3c64xx_gate(S3C_HCLK_GATE, clk, enable);
118 }
119
120 int s3c64xx_sclk_ctrl(struct clk *clk, int enable)
121 {
122         return s3c64xx_gate(S3C_SCLK_GATE, clk, enable);
123 }
124
125 static struct clk init_clocks_off[] = {
126         {
127                 .name           = "nand",
128                 .parent         = &clk_h,
129         }, {
130                 .name           = "rtc",
131                 .parent         = &clk_p,
132                 .enable         = s3c64xx_pclk_ctrl,
133                 .ctrlbit        = S3C_CLKCON_PCLK_RTC,
134         }, {
135                 .name           = "adc",
136                 .parent         = &clk_p,
137                 .enable         = s3c64xx_pclk_ctrl,
138                 .ctrlbit        = S3C_CLKCON_PCLK_TSADC,
139         }, {
140                 .name           = "i2c",
141                 .devname        = "s3c2440-i2c.0",
142                 .parent         = &clk_p,
143                 .enable         = s3c64xx_pclk_ctrl,
144                 .ctrlbit        = S3C_CLKCON_PCLK_IIC,
145         }, {
146                 .name           = "i2c",
147                 .devname        = "s3c2440-i2c.1",
148                 .parent         = &clk_p,
149                 .enable         = s3c64xx_pclk_ctrl,
150                 .ctrlbit        = S3C6410_CLKCON_PCLK_I2C1,
151         }, {
152                 .name           = "iis",
153                 .devname        = "samsung-i2s.0",
154                 .parent         = &clk_p,
155                 .enable         = s3c64xx_pclk_ctrl,
156                 .ctrlbit        = S3C_CLKCON_PCLK_IIS0,
157         }, {
158                 .name           = "iis",
159                 .devname        = "samsung-i2s.1",
160                 .parent         = &clk_p,
161                 .enable         = s3c64xx_pclk_ctrl,
162                 .ctrlbit        = S3C_CLKCON_PCLK_IIS1,
163         }, {
164 #ifdef CONFIG_CPU_S3C6410
165                 .name           = "iis",
166                 .parent         = &clk_p,
167                 .enable         = s3c64xx_pclk_ctrl,
168                 .ctrlbit        = S3C6410_CLKCON_PCLK_IIS2,
169         }, {
170 #endif
171                 .name           = "keypad",
172                 .parent         = &clk_p,
173                 .enable         = s3c64xx_pclk_ctrl,
174                 .ctrlbit        = S3C_CLKCON_PCLK_KEYPAD,
175         }, {
176                 .name           = "spi",
177                 .devname        = "s3c6410-spi.0",
178                 .parent         = &clk_p,
179                 .enable         = s3c64xx_pclk_ctrl,
180                 .ctrlbit        = S3C_CLKCON_PCLK_SPI0,
181         }, {
182                 .name           = "spi",
183                 .devname        = "s3c6410-spi.1",
184                 .parent         = &clk_p,
185                 .enable         = s3c64xx_pclk_ctrl,
186                 .ctrlbit        = S3C_CLKCON_PCLK_SPI1,
187         }, {
188                 .name           = "48m",
189                 .devname        = "s3c-sdhci.0",
190                 .parent         = &clk_48m,
191                 .enable         = s3c64xx_sclk_ctrl,
192                 .ctrlbit        = S3C_CLKCON_SCLK_MMC0_48,
193         }, {
194                 .name           = "48m",
195                 .devname        = "s3c-sdhci.1",
196                 .parent         = &clk_48m,
197                 .enable         = s3c64xx_sclk_ctrl,
198                 .ctrlbit        = S3C_CLKCON_SCLK_MMC1_48,
199         }, {
200                 .name           = "48m",
201                 .devname        = "s3c-sdhci.2",
202                 .parent         = &clk_48m,
203                 .enable         = s3c64xx_sclk_ctrl,
204                 .ctrlbit        = S3C_CLKCON_SCLK_MMC2_48,
205         }, {
206                 .name           = "ac97",
207                 .parent         = &clk_p,
208                 .ctrlbit        = S3C_CLKCON_PCLK_AC97,
209         }, {
210                 .name           = "cfcon",
211                 .parent         = &clk_h,
212                 .enable         = s3c64xx_hclk_ctrl,
213                 .ctrlbit        = S3C_CLKCON_HCLK_IHOST,
214         }, {
215                 .name           = "dma0",
216                 .parent         = &clk_h,
217                 .enable         = s3c64xx_hclk_ctrl,
218                 .ctrlbit        = S3C_CLKCON_HCLK_DMA0,
219         }, {
220                 .name           = "dma1",
221                 .parent         = &clk_h,
222                 .enable         = s3c64xx_hclk_ctrl,
223                 .ctrlbit        = S3C_CLKCON_HCLK_DMA1,
224         }, {
225                 .name           = "3dse",
226                 .parent         = &clk_h,
227                 .enable         = s3c64xx_hclk_ctrl,
228                 .ctrlbit        = S3C_CLKCON_HCLK_3DSE,
229         }, {
230                 .name           = "hclk_secur",
231                 .parent         = &clk_h,
232                 .enable         = s3c64xx_hclk_ctrl,
233                 .ctrlbit        = S3C_CLKCON_HCLK_SECUR,
234         }, {
235                 .name           = "sdma1",
236                 .parent         = &clk_h,
237                 .enable         = s3c64xx_hclk_ctrl,
238                 .ctrlbit        = S3C_CLKCON_HCLK_SDMA1,
239         }, {
240                 .name           = "sdma0",
241                 .parent         = &clk_h,
242                 .enable         = s3c64xx_hclk_ctrl,
243                 .ctrlbit        = S3C_CLKCON_HCLK_SDMA0,
244         }, {
245                 .name           = "hclk_jpeg",
246                 .parent         = &clk_h,
247                 .enable         = s3c64xx_hclk_ctrl,
248                 .ctrlbit        = S3C_CLKCON_HCLK_JPEG,
249         }, {
250                 .name           = "camif",
251                 .parent         = &clk_h,
252                 .enable         = s3c64xx_hclk_ctrl,
253                 .ctrlbit        = S3C_CLKCON_HCLK_CAMIF,
254         }, {
255                 .name           = "hclk_scaler",
256                 .parent         = &clk_h,
257                 .enable         = s3c64xx_hclk_ctrl,
258                 .ctrlbit        = S3C_CLKCON_HCLK_SCALER,
259         }, {
260                 .name           = "2d",
261                 .parent         = &clk_h,
262                 .enable         = s3c64xx_hclk_ctrl,
263                 .ctrlbit        = S3C_CLKCON_HCLK_2D,
264         }, {
265                 .name           = "tv",
266                 .parent         = &clk_h,
267                 .enable         = s3c64xx_hclk_ctrl,
268                 .ctrlbit        = S3C_CLKCON_HCLK_TV,
269         }, {
270                 .name           = "post0",
271                 .parent         = &clk_h,
272                 .enable         = s3c64xx_hclk_ctrl,
273                 .ctrlbit        = S3C_CLKCON_HCLK_POST0,
274         }, {
275                 .name           = "rot",
276                 .parent         = &clk_h,
277                 .enable         = s3c64xx_hclk_ctrl,
278                 .ctrlbit        = S3C_CLKCON_HCLK_ROT,
279         }, {
280                 .name           = "hclk_mfc",
281                 .parent         = &clk_h,
282                 .enable         = s3c64xx_hclk_ctrl,
283                 .ctrlbit        = S3C_CLKCON_HCLK_MFC,
284         }, {
285                 .name           = "pclk_mfc",
286                 .parent         = &clk_p,
287                 .enable         = s3c64xx_pclk_ctrl,
288                 .ctrlbit        = S3C_CLKCON_PCLK_MFC,
289         }, {
290                 .name           = "dac27",
291                 .enable         = s3c64xx_sclk_ctrl,
292                 .ctrlbit        = S3C_CLKCON_SCLK_DAC27,
293         }, {
294                 .name           = "tv27",
295                 .enable         = s3c64xx_sclk_ctrl,
296                 .ctrlbit        = S3C_CLKCON_SCLK_TV27,
297         }, {
298                 .name           = "scaler27",
299                 .enable         = s3c64xx_sclk_ctrl,
300                 .ctrlbit        = S3C_CLKCON_SCLK_SCALER27,
301         }, {
302                 .name           = "sclk_scaler",
303                 .enable         = s3c64xx_sclk_ctrl,
304                 .ctrlbit        = S3C_CLKCON_SCLK_SCALER,
305         }, {
306                 .name           = "post0_27",
307                 .enable         = s3c64xx_sclk_ctrl,
308                 .ctrlbit        = S3C_CLKCON_SCLK_POST0_27,
309         }, {
310                 .name           = "secur",
311                 .enable         = s3c64xx_sclk_ctrl,
312                 .ctrlbit        = S3C_CLKCON_SCLK_SECUR,
313         }, {
314                 .name           = "sclk_mfc",
315                 .enable         = s3c64xx_sclk_ctrl,
316                 .ctrlbit        = S3C_CLKCON_SCLK_MFC,
317         }, {
318                 .name           = "sclk_jpeg",
319                 .enable         = s3c64xx_sclk_ctrl,
320                 .ctrlbit        = S3C_CLKCON_SCLK_JPEG,
321         },
322 };
323
324 static struct clk clk_48m_spi0 = {
325         .name           = "spi_48m",
326         .devname        = "s3c6410-spi.0",
327         .parent         = &clk_48m,
328         .enable         = s3c64xx_sclk_ctrl,
329         .ctrlbit        = S3C_CLKCON_SCLK_SPI0_48,
330 };
331
332 static struct clk clk_48m_spi1 = {
333         .name           = "spi_48m",
334         .devname        = "s3c6410-spi.1",
335         .parent         = &clk_48m,
336         .enable         = s3c64xx_sclk_ctrl,
337         .ctrlbit        = S3C_CLKCON_SCLK_SPI1_48,
338 };
339
340 static struct clk init_clocks[] = {
341         {
342                 .name           = "lcd",
343                 .parent         = &clk_h,
344                 .enable         = s3c64xx_hclk_ctrl,
345                 .ctrlbit        = S3C_CLKCON_HCLK_LCD,
346         }, {
347                 .name           = "gpio",
348                 .parent         = &clk_p,
349                 .enable         = s3c64xx_pclk_ctrl,
350                 .ctrlbit        = S3C_CLKCON_PCLK_GPIO,
351         }, {
352                 .name           = "usb-host",
353                 .parent         = &clk_h,
354                 .enable         = s3c64xx_hclk_ctrl,
355                 .ctrlbit        = S3C_CLKCON_HCLK_UHOST,
356         }, {
357                 .name           = "otg",
358                 .parent         = &clk_h,
359                 .enable         = s3c64xx_hclk_ctrl,
360                 .ctrlbit        = S3C_CLKCON_HCLK_USB,
361         }, {
362                 .name           = "timers",
363                 .parent         = &clk_p,
364                 .enable         = s3c64xx_pclk_ctrl,
365                 .ctrlbit        = S3C_CLKCON_PCLK_PWM,
366         }, {
367                 .name           = "uart",
368                 .devname        = "s3c6400-uart.0",
369                 .parent         = &clk_p,
370                 .enable         = s3c64xx_pclk_ctrl,
371                 .ctrlbit        = S3C_CLKCON_PCLK_UART0,
372         }, {
373                 .name           = "uart",
374                 .devname        = "s3c6400-uart.1",
375                 .parent         = &clk_p,
376                 .enable         = s3c64xx_pclk_ctrl,
377                 .ctrlbit        = S3C_CLKCON_PCLK_UART1,
378         }, {
379                 .name           = "uart",
380                 .devname        = "s3c6400-uart.2",
381                 .parent         = &clk_p,
382                 .enable         = s3c64xx_pclk_ctrl,
383                 .ctrlbit        = S3C_CLKCON_PCLK_UART2,
384         }, {
385                 .name           = "uart",
386                 .devname        = "s3c6400-uart.3",
387                 .parent         = &clk_p,
388                 .enable         = s3c64xx_pclk_ctrl,
389                 .ctrlbit        = S3C_CLKCON_PCLK_UART3,
390         }, {
391                 .name           = "watchdog",
392                 .parent         = &clk_p,
393                 .ctrlbit        = S3C_CLKCON_PCLK_WDT,
394         },
395 };
396
397 static struct clk clk_hsmmc0 = {
398         .name           = "hsmmc",
399         .devname        = "s3c-sdhci.0",
400         .parent         = &clk_h,
401         .enable         = s3c64xx_hclk_ctrl,
402         .ctrlbit        = S3C_CLKCON_HCLK_HSMMC0,
403 };
404
405 static struct clk clk_hsmmc1 = {
406         .name           = "hsmmc",
407         .devname        = "s3c-sdhci.1",
408         .parent         = &clk_h,
409         .enable         = s3c64xx_hclk_ctrl,
410         .ctrlbit        = S3C_CLKCON_HCLK_HSMMC1,
411 };
412
413 static struct clk clk_hsmmc2 = {
414         .name           = "hsmmc",
415         .devname        = "s3c-sdhci.2",
416         .parent         = &clk_h,
417         .enable         = s3c64xx_hclk_ctrl,
418         .ctrlbit        = S3C_CLKCON_HCLK_HSMMC2,
419 };
420
421 static struct clk clk_fout_apll = {
422         .name           = "fout_apll",
423 };
424
425 static struct clk *clk_src_apll_list[] = {
426         [0] = &clk_fin_apll,
427         [1] = &clk_fout_apll,
428 };
429
430 static struct clksrc_sources clk_src_apll = {
431         .sources        = clk_src_apll_list,
432         .nr_sources     = ARRAY_SIZE(clk_src_apll_list),
433 };
434
435 static struct clksrc_clk clk_mout_apll = {
436         .clk    = {
437                 .name           = "mout_apll",
438         },
439         .reg_src        = { .reg = S3C_CLK_SRC, .shift = 0, .size = 1  },
440         .sources        = &clk_src_apll,
441 };
442
443 static struct clk *clk_src_epll_list[] = {
444         [0] = &clk_fin_epll,
445         [1] = &clk_fout_epll,
446 };
447
448 static struct clksrc_sources clk_src_epll = {
449         .sources        = clk_src_epll_list,
450         .nr_sources     = ARRAY_SIZE(clk_src_epll_list),
451 };
452
453 static struct clksrc_clk clk_mout_epll = {
454         .clk    = {
455                 .name           = "mout_epll",
456         },
457         .reg_src        = { .reg = S3C_CLK_SRC, .shift = 2, .size = 1  },
458         .sources        = &clk_src_epll,
459 };
460
461 static struct clk *clk_src_mpll_list[] = {
462         [0] = &clk_fin_mpll,
463         [1] = &clk_fout_mpll,
464 };
465
466 static struct clksrc_sources clk_src_mpll = {
467         .sources        = clk_src_mpll_list,
468         .nr_sources     = ARRAY_SIZE(clk_src_mpll_list),
469 };
470
471 static struct clksrc_clk clk_mout_mpll = {
472         .clk = {
473                 .name           = "mout_mpll",
474         },
475         .reg_src        = { .reg = S3C_CLK_SRC, .shift = 1, .size = 1  },
476         .sources        = &clk_src_mpll,
477 };
478
479 static unsigned int armclk_mask;
480
481 static unsigned long s3c64xx_clk_arm_get_rate(struct clk *clk)
482 {
483         unsigned long rate = clk_get_rate(clk->parent);
484         u32 clkdiv;
485
486         /* divisor mask starts at bit0, so no need to shift */
487         clkdiv = __raw_readl(S3C_CLK_DIV0) & armclk_mask;
488
489         return rate / (clkdiv + 1);
490 }
491
492 static unsigned long s3c64xx_clk_arm_round_rate(struct clk *clk,
493                                                 unsigned long rate)
494 {
495         unsigned long parent = clk_get_rate(clk->parent);
496         u32 div;
497
498         if (parent < rate)
499                 return parent;
500
501         div = (parent / rate) - 1;
502         if (div > armclk_mask)
503                 div = armclk_mask;
504
505         return parent / (div + 1);
506 }
507
508 static int s3c64xx_clk_arm_set_rate(struct clk *clk, unsigned long rate)
509 {
510         unsigned long parent = clk_get_rate(clk->parent);
511         u32 div;
512         u32 val;
513
514         if (rate < parent / (armclk_mask + 1))
515                 return -EINVAL;
516
517         rate = clk_round_rate(clk, rate);
518         div = clk_get_rate(clk->parent) / rate;
519
520         val = __raw_readl(S3C_CLK_DIV0);
521         val &= ~armclk_mask;
522         val |= (div - 1);
523         __raw_writel(val, S3C_CLK_DIV0);
524
525         return 0;
526
527 }
528
529 static struct clk clk_arm = {
530         .name           = "armclk",
531         .parent         = &clk_mout_apll.clk,
532         .ops            = &(struct clk_ops) {
533                 .get_rate       = s3c64xx_clk_arm_get_rate,
534                 .set_rate       = s3c64xx_clk_arm_set_rate,
535                 .round_rate     = s3c64xx_clk_arm_round_rate,
536         },
537 };
538
539 static unsigned long s3c64xx_clk_doutmpll_get_rate(struct clk *clk)
540 {
541         unsigned long rate = clk_get_rate(clk->parent);
542
543         printk(KERN_DEBUG "%s: parent is %ld\n", __func__, rate);
544
545         if (__raw_readl(S3C_CLK_DIV0) & S3C6400_CLKDIV0_MPLL_MASK)
546                 rate /= 2;
547
548         return rate;
549 }
550
551 static struct clk_ops clk_dout_ops = {
552         .get_rate       = s3c64xx_clk_doutmpll_get_rate,
553 };
554
555 static struct clk clk_dout_mpll = {
556         .name           = "dout_mpll",
557         .parent         = &clk_mout_mpll.clk,
558         .ops            = &clk_dout_ops,
559 };
560
561 static struct clk *clkset_spi_mmc_list[] = {
562         &clk_mout_epll.clk,
563         &clk_dout_mpll,
564         &clk_fin_epll,
565         &clk_27m,
566 };
567
568 static struct clksrc_sources clkset_spi_mmc = {
569         .sources        = clkset_spi_mmc_list,
570         .nr_sources     = ARRAY_SIZE(clkset_spi_mmc_list),
571 };
572
573 static struct clk *clkset_irda_list[] = {
574         &clk_mout_epll.clk,
575         &clk_dout_mpll,
576         NULL,
577         &clk_27m,
578 };
579
580 static struct clksrc_sources clkset_irda = {
581         .sources        = clkset_irda_list,
582         .nr_sources     = ARRAY_SIZE(clkset_irda_list),
583 };
584
585 static struct clk *clkset_uart_list[] = {
586         &clk_mout_epll.clk,
587         &clk_dout_mpll,
588         NULL,
589         NULL
590 };
591
592 static struct clksrc_sources clkset_uart = {
593         .sources        = clkset_uart_list,
594         .nr_sources     = ARRAY_SIZE(clkset_uart_list),
595 };
596
597 static struct clk *clkset_uhost_list[] = {
598         &clk_48m,
599         &clk_mout_epll.clk,
600         &clk_dout_mpll,
601         &clk_fin_epll,
602 };
603
604 static struct clksrc_sources clkset_uhost = {
605         .sources        = clkset_uhost_list,
606         .nr_sources     = ARRAY_SIZE(clkset_uhost_list),
607 };
608
609 /* The peripheral clocks are all controlled via clocksource followed
610  * by an optional divider and gate stage. We currently roll this into
611  * one clock which hides the intermediate clock from the mux.
612  *
613  * Note, the JPEG clock can only be an even divider...
614  *
615  * The scaler and LCD clocks depend on the S3C64XX version, and also
616  * have a common parent divisor so are not included here.
617  */
618
619 /* clocks that feed other parts of the clock source tree */
620
621 static struct clk clk_iis_cd0 = {
622         .name           = "iis_cdclk0",
623 };
624
625 static struct clk clk_iis_cd1 = {
626         .name           = "iis_cdclk1",
627 };
628
629 static struct clk clk_iisv4_cd = {
630         .name           = "iis_cdclk_v4",
631 };
632
633 static struct clk clk_pcm_cd = {
634         .name           = "pcm_cdclk",
635 };
636
637 static struct clk *clkset_audio0_list[] = {
638         [0] = &clk_mout_epll.clk,
639         [1] = &clk_dout_mpll,
640         [2] = &clk_fin_epll,
641         [3] = &clk_iis_cd0,
642         [4] = &clk_pcm_cd,
643 };
644
645 static struct clksrc_sources clkset_audio0 = {
646         .sources        = clkset_audio0_list,
647         .nr_sources     = ARRAY_SIZE(clkset_audio0_list),
648 };
649
650 static struct clk *clkset_audio1_list[] = {
651         [0] = &clk_mout_epll.clk,
652         [1] = &clk_dout_mpll,
653         [2] = &clk_fin_epll,
654         [3] = &clk_iis_cd1,
655         [4] = &clk_pcm_cd,
656 };
657
658 static struct clksrc_sources clkset_audio1 = {
659         .sources        = clkset_audio1_list,
660         .nr_sources     = ARRAY_SIZE(clkset_audio1_list),
661 };
662
663 static struct clk *clkset_audio2_list[] = {
664         [0] = &clk_mout_epll.clk,
665         [1] = &clk_dout_mpll,
666         [2] = &clk_fin_epll,
667         [3] = &clk_iisv4_cd,
668         [4] = &clk_pcm_cd,
669 };
670
671 static struct clksrc_sources clkset_audio2 = {
672         .sources        = clkset_audio2_list,
673         .nr_sources     = ARRAY_SIZE(clkset_audio2_list),
674 };
675
676 static struct clksrc_clk clksrcs[] = {
677         {
678                 .clk    = {
679                         .name           = "usb-bus-host",
680                         .ctrlbit        = S3C_CLKCON_SCLK_UHOST,
681                         .enable         = s3c64xx_sclk_ctrl,
682                 },
683                 .reg_src        = { .reg = S3C_CLK_SRC, .shift = 5, .size = 2  },
684                 .reg_div        = { .reg = S3C_CLK_DIV1, .shift = 20, .size = 4  },
685                 .sources        = &clkset_uhost,
686         }, {
687                 .clk    = {
688                         .name           = "audio-bus",
689                         .devname        = "samsung-i2s.0",
690                         .ctrlbit        = S3C_CLKCON_SCLK_AUDIO0,
691                         .enable         = s3c64xx_sclk_ctrl,
692                 },
693                 .reg_src        = { .reg = S3C_CLK_SRC, .shift = 7, .size = 3  },
694                 .reg_div        = { .reg = S3C_CLK_DIV2, .shift = 8, .size = 4  },
695                 .sources        = &clkset_audio0,
696         }, {
697                 .clk    = {
698                         .name           = "audio-bus",
699                         .devname        = "samsung-i2s.1",
700                         .ctrlbit        = S3C_CLKCON_SCLK_AUDIO1,
701                         .enable         = s3c64xx_sclk_ctrl,
702                 },
703                 .reg_src        = { .reg = S3C_CLK_SRC, .shift = 10, .size = 3  },
704                 .reg_div        = { .reg = S3C_CLK_DIV2, .shift = 12, .size = 4  },
705                 .sources        = &clkset_audio1,
706         }, {
707                 .clk    = {
708                         .name           = "audio-bus",
709                         .devname        = "samsung-i2s.2",
710                         .ctrlbit        = S3C6410_CLKCON_SCLK_AUDIO2,
711                         .enable         = s3c64xx_sclk_ctrl,
712                 },
713                 .reg_src        = { .reg = S3C6410_CLK_SRC2, .shift = 0, .size = 3  },
714                 .reg_div        = { .reg = S3C_CLK_DIV2, .shift = 24, .size = 4  },
715                 .sources        = &clkset_audio2,
716         }, {
717                 .clk    = {
718                         .name           = "irda-bus",
719                         .ctrlbit        = S3C_CLKCON_SCLK_IRDA,
720                         .enable         = s3c64xx_sclk_ctrl,
721                 },
722                 .reg_src        = { .reg = S3C_CLK_SRC, .shift = 24, .size = 2  },
723                 .reg_div        = { .reg = S3C_CLK_DIV2, .shift = 20, .size = 4  },
724                 .sources        = &clkset_irda,
725         }, {
726                 .clk    = {
727                         .name           = "camera",
728                         .ctrlbit        = S3C_CLKCON_SCLK_CAM,
729                         .enable         = s3c64xx_sclk_ctrl,
730                         .parent         = &clk_h2,
731                 },
732                 .reg_div        = { .reg = S3C_CLK_DIV0, .shift = 20, .size = 4  },
733         },
734 };
735
736 /* Where does UCLK0 come from? */
737 static struct clksrc_clk clk_sclk_uclk = {
738         .clk    = {
739                 .name           = "uclk1",
740                 .ctrlbit        = S3C_CLKCON_SCLK_UART,
741                 .enable         = s3c64xx_sclk_ctrl,
742         },
743         .reg_src        = { .reg = S3C_CLK_SRC, .shift = 13, .size = 1  },
744         .reg_div        = { .reg = S3C_CLK_DIV2, .shift = 16, .size = 4  },
745         .sources        = &clkset_uart,
746 };
747
748 static struct clksrc_clk clk_sclk_mmc0 = {
749         .clk    = {
750                 .name           = "mmc_bus",
751                 .devname        = "s3c-sdhci.0",
752                 .ctrlbit        = S3C_CLKCON_SCLK_MMC0,
753                 .enable         = s3c64xx_sclk_ctrl,
754         },
755         .reg_src        = { .reg = S3C_CLK_SRC, .shift = 18, .size = 2  },
756         .reg_div        = { .reg = S3C_CLK_DIV1, .shift = 0, .size = 4  },
757         .sources        = &clkset_spi_mmc,
758 };
759
760 static struct clksrc_clk clk_sclk_mmc1 = {
761         .clk    = {
762                 .name           = "mmc_bus",
763                 .devname        = "s3c-sdhci.1",
764                 .ctrlbit        = S3C_CLKCON_SCLK_MMC1,
765                 .enable         = s3c64xx_sclk_ctrl,
766         },
767         .reg_src        = { .reg = S3C_CLK_SRC, .shift = 20, .size = 2  },
768         .reg_div        = { .reg = S3C_CLK_DIV1, .shift = 4, .size = 4  },
769         .sources        = &clkset_spi_mmc,
770 };
771
772 static struct clksrc_clk clk_sclk_mmc2 = {
773         .clk    = {
774                 .name           = "mmc_bus",
775                 .devname        = "s3c-sdhci.2",
776                 .ctrlbit        = S3C_CLKCON_SCLK_MMC2,
777                 .enable         = s3c64xx_sclk_ctrl,
778         },
779         .reg_src        = { .reg = S3C_CLK_SRC, .shift = 22, .size = 2  },
780         .reg_div        = { .reg = S3C_CLK_DIV1, .shift = 8, .size = 4  },
781         .sources        = &clkset_spi_mmc,
782 };
783
784 static struct clksrc_clk clk_sclk_spi0 = {
785         .clk    = {
786                 .name           = "spi-bus",
787                 .devname        = "s3c6410-spi.0",
788                 .ctrlbit        = S3C_CLKCON_SCLK_SPI0,
789                 .enable         = s3c64xx_sclk_ctrl,
790         },
791         .reg_src = { .reg = S3C_CLK_SRC, .shift = 14, .size = 2 },
792         .reg_div = { .reg = S3C_CLK_DIV2, .shift = 0, .size = 4 },
793         .sources = &clkset_spi_mmc,
794 };
795
796 static struct clksrc_clk clk_sclk_spi1 = {
797         .clk    = {
798                 .name           = "spi-bus",
799                 .devname        = "s3c6410-spi.1",
800                 .ctrlbit        = S3C_CLKCON_SCLK_SPI1,
801                 .enable         = s3c64xx_sclk_ctrl,
802         },
803         .reg_src = { .reg = S3C_CLK_SRC, .shift = 16, .size = 2 },
804         .reg_div = { .reg = S3C_CLK_DIV2, .shift = 4, .size = 4 },
805         .sources = &clkset_spi_mmc,
806 };
807
808 /* Clock initialisation code */
809
810 static struct clksrc_clk *init_parents[] = {
811         &clk_mout_apll,
812         &clk_mout_epll,
813         &clk_mout_mpll,
814 };
815
816 static struct clksrc_clk *clksrc_cdev[] = {
817         &clk_sclk_uclk,
818         &clk_sclk_mmc0,
819         &clk_sclk_mmc1,
820         &clk_sclk_mmc2,
821         &clk_sclk_spi0,
822         &clk_sclk_spi1,
823 };
824
825 static struct clk *clk_cdev[] = {
826         &clk_hsmmc0,
827         &clk_hsmmc1,
828         &clk_hsmmc2,
829         &clk_48m_spi0,
830         &clk_48m_spi1,
831 };
832
833 static struct clk_lookup s3c64xx_clk_lookup[] = {
834         CLKDEV_INIT(NULL, "clk_uart_baud2", &clk_p),
835         CLKDEV_INIT(NULL, "clk_uart_baud3", &clk_sclk_uclk.clk),
836         CLKDEV_INIT("s3c-sdhci.0", "mmc_busclk.0", &clk_hsmmc0),
837         CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.0", &clk_hsmmc1),
838         CLKDEV_INIT("s3c-sdhci.2", "mmc_busclk.0", &clk_hsmmc2),
839         CLKDEV_INIT("s3c-sdhci.0", "mmc_busclk.2", &clk_sclk_mmc0.clk),
840         CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.2", &clk_sclk_mmc1.clk),
841         CLKDEV_INIT("s3c-sdhci.2", "mmc_busclk.2", &clk_sclk_mmc2.clk),
842         CLKDEV_INIT(NULL, "spi_busclk0", &clk_p),
843         CLKDEV_INIT("s3c6410-spi.0", "spi_busclk1", &clk_sclk_spi0.clk),
844         CLKDEV_INIT("s3c6410-spi.0", "spi_busclk2", &clk_48m_spi0),
845         CLKDEV_INIT("s3c6410-spi.1", "spi_busclk1", &clk_sclk_spi1.clk),
846         CLKDEV_INIT("s3c6410-spi.1", "spi_busclk2", &clk_48m_spi1),
847 };
848
849 #define GET_DIV(clk, field) ((((clk) & field##_MASK) >> field##_SHIFT) + 1)
850
851 void __init_or_cpufreq s3c64xx_setup_clocks(void)
852 {
853         struct clk *xtal_clk;
854         unsigned long xtal;
855         unsigned long fclk;
856         unsigned long hclk;
857         unsigned long hclk2;
858         unsigned long pclk;
859         unsigned long epll;
860         unsigned long apll;
861         unsigned long mpll;
862         unsigned int ptr;
863         u32 clkdiv0;
864
865         printk(KERN_DEBUG "%s: registering clocks\n", __func__);
866
867         clkdiv0 = __raw_readl(S3C_CLK_DIV0);
868         printk(KERN_DEBUG "%s: clkdiv0 = %08x\n", __func__, clkdiv0);
869
870         xtal_clk = clk_get(NULL, "xtal");
871         BUG_ON(IS_ERR(xtal_clk));
872
873         xtal = clk_get_rate(xtal_clk);
874         clk_put(xtal_clk);
875
876         printk(KERN_DEBUG "%s: xtal is %ld\n", __func__, xtal);
877
878         /* For now assume the mux always selects the crystal */
879         clk_ext_xtal_mux.parent = xtal_clk;
880
881         epll = s3c_get_pll6553x(xtal, __raw_readl(S3C_EPLL_CON0),
882                                 __raw_readl(S3C_EPLL_CON1));
883         mpll = s3c6400_get_pll(xtal, __raw_readl(S3C_MPLL_CON));
884         apll = s3c6400_get_pll(xtal, __raw_readl(S3C_APLL_CON));
885
886         fclk = mpll;
887
888         printk(KERN_INFO "S3C64XX: PLL settings, A=%ld, M=%ld, E=%ld\n",
889                apll, mpll, epll);
890
891         if(__raw_readl(S3C64XX_OTHERS) & S3C64XX_OTHERS_SYNCMUXSEL)
892                 /* Synchronous mode */
893                 hclk2 = apll / GET_DIV(clkdiv0, S3C6400_CLKDIV0_HCLK2);
894         else
895                 /* Asynchronous mode */
896                 hclk2 = mpll / GET_DIV(clkdiv0, S3C6400_CLKDIV0_HCLK2);
897
898         hclk = hclk2 / GET_DIV(clkdiv0, S3C6400_CLKDIV0_HCLK);
899         pclk = hclk2 / GET_DIV(clkdiv0, S3C6400_CLKDIV0_PCLK);
900
901         printk(KERN_INFO "S3C64XX: HCLK2=%ld, HCLK=%ld, PCLK=%ld\n",
902                hclk2, hclk, pclk);
903
904         clk_fout_mpll.rate = mpll;
905         clk_fout_epll.rate = epll;
906         clk_fout_apll.rate = apll;
907
908         clk_h2.rate = hclk2;
909         clk_h.rate = hclk;
910         clk_p.rate = pclk;
911         clk_f.rate = fclk;
912
913         for (ptr = 0; ptr < ARRAY_SIZE(init_parents); ptr++)
914                 s3c_set_clksrc(init_parents[ptr], true);
915
916         for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
917                 s3c_set_clksrc(&clksrcs[ptr], true);
918 }
919
920 static struct clk *clks1[] __initdata = {
921         &clk_ext_xtal_mux,
922         &clk_iis_cd0,
923         &clk_iis_cd1,
924         &clk_iisv4_cd,
925         &clk_pcm_cd,
926         &clk_mout_epll.clk,
927         &clk_mout_mpll.clk,
928         &clk_dout_mpll,
929         &clk_arm,
930 };
931
932 static struct clk *clks[] __initdata = {
933         &clk_ext,
934         &clk_epll,
935         &clk_27m,
936         &clk_48m,
937         &clk_h2,
938         &clk_xusbxti,
939 };
940
941 /**
942  * s3c64xx_register_clocks - register clocks for s3c6400 and s3c6410
943  * @xtal: The rate for the clock crystal feeding the PLLs.
944  * @armclk_divlimit: Divisor mask for ARMCLK.
945  *
946  * Register the clocks for the S3C6400 and S3C6410 SoC range, such
947  * as ARMCLK as well as the necessary parent clocks.
948  *
949  * This call does not setup the clocks, which is left to the
950  * s3c64xx_setup_clocks() call which may be needed by the cpufreq
951  * or resume code to re-set the clocks if the bootloader has changed
952  * them.
953  */
954 void __init s3c64xx_register_clocks(unsigned long xtal, 
955                                     unsigned armclk_divlimit)
956 {
957         unsigned int cnt;
958
959         armclk_mask = armclk_divlimit;
960
961         s3c24xx_register_baseclocks(xtal);
962         s3c24xx_register_clocks(clks, ARRAY_SIZE(clks));
963
964         s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
965
966         s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
967         s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
968
969         s3c24xx_register_clocks(clk_cdev, ARRAY_SIZE(clk_cdev));
970         for (cnt = 0; cnt < ARRAY_SIZE(clk_cdev); cnt++)
971                 s3c_disable_clocks(clk_cdev[cnt], 1);
972
973         s3c24xx_register_clocks(clks1, ARRAY_SIZE(clks1));
974         s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
975         for (cnt = 0; cnt < ARRAY_SIZE(clksrc_cdev); cnt++)
976                 s3c_register_clksrc(clksrc_cdev[cnt], 1);
977         clkdev_add_table(s3c64xx_clk_lookup, ARRAY_SIZE(s3c64xx_clk_lookup));
978
979         s3c_pwmclk_init();
980 }