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