]> git.karo-electronics.de Git - karo-tx-linux.git/blob - arch/arm/mach-s3c64xx/clock.c
ARM: S3C64XX: Remove duplicated camera clock
[karo-tx-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 clk *clkset_camif_list[] = {
677         &clk_h2,
678 };
679
680 static struct clksrc_sources clkset_camif = {
681         .sources        = clkset_camif_list,
682         .nr_sources     = ARRAY_SIZE(clkset_camif_list),
683 };
684
685 static struct clksrc_clk clksrcs[] = {
686         {
687                 .clk    = {
688                         .name           = "usb-bus-host",
689                         .ctrlbit        = S3C_CLKCON_SCLK_UHOST,
690                         .enable         = s3c64xx_sclk_ctrl,
691                 },
692                 .reg_src        = { .reg = S3C_CLK_SRC, .shift = 5, .size = 2  },
693                 .reg_div        = { .reg = S3C_CLK_DIV1, .shift = 20, .size = 4  },
694                 .sources        = &clkset_uhost,
695         }, {
696                 .clk    = {
697                         .name           = "audio-bus",
698                         .devname        = "samsung-i2s.0",
699                         .ctrlbit        = S3C_CLKCON_SCLK_AUDIO0,
700                         .enable         = s3c64xx_sclk_ctrl,
701                 },
702                 .reg_src        = { .reg = S3C_CLK_SRC, .shift = 7, .size = 3  },
703                 .reg_div        = { .reg = S3C_CLK_DIV2, .shift = 8, .size = 4  },
704                 .sources        = &clkset_audio0,
705         }, {
706                 .clk    = {
707                         .name           = "audio-bus",
708                         .devname        = "samsung-i2s.1",
709                         .ctrlbit        = S3C_CLKCON_SCLK_AUDIO1,
710                         .enable         = s3c64xx_sclk_ctrl,
711                 },
712                 .reg_src        = { .reg = S3C_CLK_SRC, .shift = 10, .size = 3  },
713                 .reg_div        = { .reg = S3C_CLK_DIV2, .shift = 12, .size = 4  },
714                 .sources        = &clkset_audio1,
715         }, {
716                 .clk    = {
717                         .name           = "audio-bus",
718                         .devname        = "samsung-i2s.2",
719                         .ctrlbit        = S3C6410_CLKCON_SCLK_AUDIO2,
720                         .enable         = s3c64xx_sclk_ctrl,
721                 },
722                 .reg_src        = { .reg = S3C6410_CLK_SRC2, .shift = 0, .size = 3  },
723                 .reg_div        = { .reg = S3C_CLK_DIV2, .shift = 24, .size = 4  },
724                 .sources        = &clkset_audio2,
725         }, {
726                 .clk    = {
727                         .name           = "irda-bus",
728                         .ctrlbit        = S3C_CLKCON_SCLK_IRDA,
729                         .enable         = s3c64xx_sclk_ctrl,
730                 },
731                 .reg_src        = { .reg = S3C_CLK_SRC, .shift = 24, .size = 2  },
732                 .reg_div        = { .reg = S3C_CLK_DIV2, .shift = 20, .size = 4  },
733                 .sources        = &clkset_irda,
734         }, {
735                 .clk    = {
736                         .name           = "camera",
737                         .ctrlbit        = S3C_CLKCON_SCLK_CAM,
738                         .enable         = s3c64xx_sclk_ctrl,
739                 },
740                 .reg_div        = { .reg = S3C_CLK_DIV0, .shift = 20, .size = 4  },
741                 .reg_src        = { .reg = NULL, .shift = 0, .size = 0  },
742                 .sources        = &clkset_camif,
743         },
744 };
745
746 /* Where does UCLK0 come from? */
747 static struct clksrc_clk clk_sclk_uclk = {
748         .clk    = {
749                 .name           = "uclk1",
750                 .ctrlbit        = S3C_CLKCON_SCLK_UART,
751                 .enable         = s3c64xx_sclk_ctrl,
752         },
753         .reg_src        = { .reg = S3C_CLK_SRC, .shift = 13, .size = 1  },
754         .reg_div        = { .reg = S3C_CLK_DIV2, .shift = 16, .size = 4  },
755         .sources        = &clkset_uart,
756 };
757
758 static struct clksrc_clk clk_sclk_mmc0 = {
759         .clk    = {
760                 .name           = "mmc_bus",
761                 .devname        = "s3c-sdhci.0",
762                 .ctrlbit        = S3C_CLKCON_SCLK_MMC0,
763                 .enable         = s3c64xx_sclk_ctrl,
764         },
765         .reg_src        = { .reg = S3C_CLK_SRC, .shift = 18, .size = 2  },
766         .reg_div        = { .reg = S3C_CLK_DIV1, .shift = 0, .size = 4  },
767         .sources        = &clkset_spi_mmc,
768 };
769
770 static struct clksrc_clk clk_sclk_mmc1 = {
771         .clk    = {
772                 .name           = "mmc_bus",
773                 .devname        = "s3c-sdhci.1",
774                 .ctrlbit        = S3C_CLKCON_SCLK_MMC1,
775                 .enable         = s3c64xx_sclk_ctrl,
776         },
777         .reg_src        = { .reg = S3C_CLK_SRC, .shift = 20, .size = 2  },
778         .reg_div        = { .reg = S3C_CLK_DIV1, .shift = 4, .size = 4  },
779         .sources        = &clkset_spi_mmc,
780 };
781
782 static struct clksrc_clk clk_sclk_mmc2 = {
783         .clk    = {
784                 .name           = "mmc_bus",
785                 .devname        = "s3c-sdhci.2",
786                 .ctrlbit        = S3C_CLKCON_SCLK_MMC2,
787                 .enable         = s3c64xx_sclk_ctrl,
788         },
789         .reg_src        = { .reg = S3C_CLK_SRC, .shift = 22, .size = 2  },
790         .reg_div        = { .reg = S3C_CLK_DIV1, .shift = 8, .size = 4  },
791         .sources        = &clkset_spi_mmc,
792 };
793
794 static struct clksrc_clk clk_sclk_spi0 = {
795         .clk    = {
796                 .name           = "spi-bus",
797                 .devname        = "s3c6410-spi.0",
798                 .ctrlbit        = S3C_CLKCON_SCLK_SPI0,
799                 .enable         = s3c64xx_sclk_ctrl,
800         },
801         .reg_src = { .reg = S3C_CLK_SRC, .shift = 14, .size = 2 },
802         .reg_div = { .reg = S3C_CLK_DIV2, .shift = 0, .size = 4 },
803         .sources = &clkset_spi_mmc,
804 };
805
806 static struct clksrc_clk clk_sclk_spi1 = {
807         .clk    = {
808                 .name           = "spi-bus",
809                 .devname        = "s3c6410-spi.1",
810                 .ctrlbit        = S3C_CLKCON_SCLK_SPI1,
811                 .enable         = s3c64xx_sclk_ctrl,
812         },
813         .reg_src = { .reg = S3C_CLK_SRC, .shift = 16, .size = 2 },
814         .reg_div = { .reg = S3C_CLK_DIV2, .shift = 4, .size = 4 },
815         .sources = &clkset_spi_mmc,
816 };
817
818 /* Clock initialisation code */
819
820 static struct clksrc_clk *init_parents[] = {
821         &clk_mout_apll,
822         &clk_mout_epll,
823         &clk_mout_mpll,
824 };
825
826 static struct clksrc_clk *clksrc_cdev[] = {
827         &clk_sclk_uclk,
828         &clk_sclk_mmc0,
829         &clk_sclk_mmc1,
830         &clk_sclk_mmc2,
831         &clk_sclk_spi0,
832         &clk_sclk_spi1,
833 };
834
835 static struct clk *clk_cdev[] = {
836         &clk_hsmmc0,
837         &clk_hsmmc1,
838         &clk_hsmmc2,
839         &clk_48m_spi0,
840         &clk_48m_spi1,
841 };
842
843 static struct clk_lookup s3c64xx_clk_lookup[] = {
844         CLKDEV_INIT(NULL, "clk_uart_baud2", &clk_p),
845         CLKDEV_INIT(NULL, "clk_uart_baud3", &clk_sclk_uclk.clk),
846         CLKDEV_INIT("s3c-sdhci.0", "mmc_busclk.0", &clk_hsmmc0),
847         CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.0", &clk_hsmmc1),
848         CLKDEV_INIT("s3c-sdhci.2", "mmc_busclk.0", &clk_hsmmc2),
849         CLKDEV_INIT("s3c-sdhci.0", "mmc_busclk.2", &clk_sclk_mmc0.clk),
850         CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.2", &clk_sclk_mmc1.clk),
851         CLKDEV_INIT("s3c-sdhci.2", "mmc_busclk.2", &clk_sclk_mmc2.clk),
852         CLKDEV_INIT(NULL, "spi_busclk0", &clk_p),
853         CLKDEV_INIT("s3c6410-spi.0", "spi_busclk1", &clk_sclk_spi0.clk),
854         CLKDEV_INIT("s3c6410-spi.0", "spi_busclk2", &clk_48m_spi0),
855         CLKDEV_INIT("s3c6410-spi.1", "spi_busclk1", &clk_sclk_spi1.clk),
856         CLKDEV_INIT("s3c6410-spi.1", "spi_busclk2", &clk_48m_spi1),
857 };
858
859 #define GET_DIV(clk, field) ((((clk) & field##_MASK) >> field##_SHIFT) + 1)
860
861 void __init_or_cpufreq s3c64xx_setup_clocks(void)
862 {
863         struct clk *xtal_clk;
864         unsigned long xtal;
865         unsigned long fclk;
866         unsigned long hclk;
867         unsigned long hclk2;
868         unsigned long pclk;
869         unsigned long epll;
870         unsigned long apll;
871         unsigned long mpll;
872         unsigned int ptr;
873         u32 clkdiv0;
874
875         printk(KERN_DEBUG "%s: registering clocks\n", __func__);
876
877         clkdiv0 = __raw_readl(S3C_CLK_DIV0);
878         printk(KERN_DEBUG "%s: clkdiv0 = %08x\n", __func__, clkdiv0);
879
880         xtal_clk = clk_get(NULL, "xtal");
881         BUG_ON(IS_ERR(xtal_clk));
882
883         xtal = clk_get_rate(xtal_clk);
884         clk_put(xtal_clk);
885
886         printk(KERN_DEBUG "%s: xtal is %ld\n", __func__, xtal);
887
888         /* For now assume the mux always selects the crystal */
889         clk_ext_xtal_mux.parent = xtal_clk;
890
891         epll = s3c_get_pll6553x(xtal, __raw_readl(S3C_EPLL_CON0),
892                                 __raw_readl(S3C_EPLL_CON1));
893         mpll = s3c6400_get_pll(xtal, __raw_readl(S3C_MPLL_CON));
894         apll = s3c6400_get_pll(xtal, __raw_readl(S3C_APLL_CON));
895
896         fclk = mpll;
897
898         printk(KERN_INFO "S3C64XX: PLL settings, A=%ld, M=%ld, E=%ld\n",
899                apll, mpll, epll);
900
901         if(__raw_readl(S3C64XX_OTHERS) & S3C64XX_OTHERS_SYNCMUXSEL)
902                 /* Synchronous mode */
903                 hclk2 = apll / GET_DIV(clkdiv0, S3C6400_CLKDIV0_HCLK2);
904         else
905                 /* Asynchronous mode */
906                 hclk2 = mpll / GET_DIV(clkdiv0, S3C6400_CLKDIV0_HCLK2);
907
908         hclk = hclk2 / GET_DIV(clkdiv0, S3C6400_CLKDIV0_HCLK);
909         pclk = hclk2 / GET_DIV(clkdiv0, S3C6400_CLKDIV0_PCLK);
910
911         printk(KERN_INFO "S3C64XX: HCLK2=%ld, HCLK=%ld, PCLK=%ld\n",
912                hclk2, hclk, pclk);
913
914         clk_fout_mpll.rate = mpll;
915         clk_fout_epll.rate = epll;
916         clk_fout_apll.rate = apll;
917
918         clk_h2.rate = hclk2;
919         clk_h.rate = hclk;
920         clk_p.rate = pclk;
921         clk_f.rate = fclk;
922
923         for (ptr = 0; ptr < ARRAY_SIZE(init_parents); ptr++)
924                 s3c_set_clksrc(init_parents[ptr], true);
925
926         for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
927                 s3c_set_clksrc(&clksrcs[ptr], true);
928 }
929
930 static struct clk *clks1[] __initdata = {
931         &clk_ext_xtal_mux,
932         &clk_iis_cd0,
933         &clk_iis_cd1,
934         &clk_iisv4_cd,
935         &clk_pcm_cd,
936         &clk_mout_epll.clk,
937         &clk_mout_mpll.clk,
938         &clk_dout_mpll,
939         &clk_arm,
940 };
941
942 static struct clk *clks[] __initdata = {
943         &clk_ext,
944         &clk_epll,
945         &clk_27m,
946         &clk_48m,
947         &clk_h2,
948         &clk_xusbxti,
949 };
950
951 /**
952  * s3c64xx_register_clocks - register clocks for s3c6400 and s3c6410
953  * @xtal: The rate for the clock crystal feeding the PLLs.
954  * @armclk_divlimit: Divisor mask for ARMCLK.
955  *
956  * Register the clocks for the S3C6400 and S3C6410 SoC range, such
957  * as ARMCLK as well as the necessary parent clocks.
958  *
959  * This call does not setup the clocks, which is left to the
960  * s3c64xx_setup_clocks() call which may be needed by the cpufreq
961  * or resume code to re-set the clocks if the bootloader has changed
962  * them.
963  */
964 void __init s3c64xx_register_clocks(unsigned long xtal, 
965                                     unsigned armclk_divlimit)
966 {
967         unsigned int cnt;
968
969         armclk_mask = armclk_divlimit;
970
971         s3c24xx_register_baseclocks(xtal);
972         s3c24xx_register_clocks(clks, ARRAY_SIZE(clks));
973
974         s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
975
976         s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
977         s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
978
979         s3c24xx_register_clocks(clk_cdev, ARRAY_SIZE(clk_cdev));
980         for (cnt = 0; cnt < ARRAY_SIZE(clk_cdev); cnt++)
981                 s3c_disable_clocks(clk_cdev[cnt], 1);
982
983         s3c24xx_register_clocks(clks1, ARRAY_SIZE(clks1));
984         s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
985         for (cnt = 0; cnt < ARRAY_SIZE(clksrc_cdev); cnt++)
986                 s3c_register_clksrc(clksrc_cdev[cnt], 1);
987         clkdev_add_table(s3c64xx_clk_lookup, ARRAY_SIZE(s3c64xx_clk_lookup));
988
989         s3c_pwmclk_init();
990 }