1 /* linux/arch/arm/plat-s3c64xx/clock.c
3 * Copyright 2008 Openmoko, Inc.
4 * Copyright 2008 Simtec Electronics
5 * Ben Dooks <ben@simtec.co.uk>
6 * http://armlinux.simtec.co.uk/
8 * S3C64XX Base clock support
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.
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>
23 #include <mach/hardware.h>
26 #include <mach/regs-sys.h>
27 #include <mach/regs-clock.h>
31 #include <plat/devs.h>
32 #include <plat/cpu-freq.h>
33 #include <plat/clock.h>
34 #include <plat/clock-clksrc.h>
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.
40 static struct clk clk_ext_xtal_mux = {
45 #define clk_fin_apll clk_ext_xtal_mux
46 #define clk_fin_mpll clk_ext_xtal_mux
47 #define clk_fin_epll clk_ext_xtal_mux
49 #define clk_fout_mpll clk_mpll
50 #define clk_fout_epll clk_epll
58 struct clk clk_27m = {
64 static int clk_48m_ctrl(struct clk *clk, int enable)
69 /* can't rely on clock lock, this register has other usages */
70 local_irq_save(flags);
72 val = __raw_readl(S3C64XX_OTHERS);
74 val |= S3C64XX_OTHERS_USBMASK;
76 val &= ~S3C64XX_OTHERS_USBMASK;
78 __raw_writel(val, S3C64XX_OTHERS);
79 local_irq_restore(flags);
84 struct clk clk_48m = {
88 .enable = clk_48m_ctrl,
91 static int inline s3c64xx_gate(void __iomem *reg,
95 unsigned int ctrlbit = clk->ctrlbit;
98 con = __raw_readl(reg);
105 __raw_writel(con, reg);
109 static int s3c64xx_pclk_ctrl(struct clk *clk, int enable)
111 return s3c64xx_gate(S3C_PCLK_GATE, clk, enable);
114 static int s3c64xx_hclk_ctrl(struct clk *clk, int enable)
116 return s3c64xx_gate(S3C_HCLK_GATE, clk, enable);
119 int s3c64xx_sclk_ctrl(struct clk *clk, int enable)
121 return s3c64xx_gate(S3C_SCLK_GATE, clk, enable);
124 static struct clk init_clocks_disable[] = {
133 .enable = s3c64xx_pclk_ctrl,
134 .ctrlbit = S3C_CLKCON_PCLK_TSADC,
139 .enable = s3c64xx_pclk_ctrl,
140 .ctrlbit = S3C_CLKCON_PCLK_IIC,
145 .enable = s3c64xx_pclk_ctrl,
146 .ctrlbit = S3C_CLKCON_PCLK_IIS0,
151 .enable = s3c64xx_pclk_ctrl,
152 .ctrlbit = S3C_CLKCON_PCLK_IIS1,
157 .enable = s3c64xx_pclk_ctrl,
158 .ctrlbit = S3C_CLKCON_PCLK_SPI0,
163 .enable = s3c64xx_pclk_ctrl,
164 .ctrlbit = S3C_CLKCON_PCLK_SPI1,
169 .enable = s3c64xx_sclk_ctrl,
170 .ctrlbit = S3C_CLKCON_SCLK_SPI0_48,
175 .enable = s3c64xx_sclk_ctrl,
176 .ctrlbit = S3C_CLKCON_SCLK_SPI1_48,
181 .enable = s3c64xx_sclk_ctrl,
182 .ctrlbit = S3C_CLKCON_SCLK_MMC0_48,
187 .enable = s3c64xx_sclk_ctrl,
188 .ctrlbit = S3C_CLKCON_SCLK_MMC1_48,
193 .enable = s3c64xx_sclk_ctrl,
194 .ctrlbit = S3C_CLKCON_SCLK_MMC2_48,
199 .enable = s3c64xx_hclk_ctrl,
200 .ctrlbit = S3C_CLKCON_HCLK_DMA0,
205 .enable = s3c64xx_hclk_ctrl,
206 .ctrlbit = S3C_CLKCON_HCLK_DMA1,
210 static struct clk init_clocks[] = {
215 .enable = s3c64xx_hclk_ctrl,
216 .ctrlbit = S3C_CLKCON_HCLK_LCD,
221 .enable = s3c64xx_pclk_ctrl,
222 .ctrlbit = S3C_CLKCON_PCLK_GPIO,
227 .enable = s3c64xx_hclk_ctrl,
228 .ctrlbit = S3C_CLKCON_HCLK_UHOST,
233 .enable = s3c64xx_hclk_ctrl,
234 .ctrlbit = S3C_CLKCON_HCLK_HSMMC0,
239 .enable = s3c64xx_hclk_ctrl,
240 .ctrlbit = S3C_CLKCON_HCLK_HSMMC1,
245 .enable = s3c64xx_hclk_ctrl,
246 .ctrlbit = S3C_CLKCON_HCLK_HSMMC2,
251 .enable = s3c64xx_pclk_ctrl,
252 .ctrlbit = S3C_CLKCON_PCLK_PWM,
257 .enable = s3c64xx_pclk_ctrl,
258 .ctrlbit = S3C_CLKCON_PCLK_UART0,
263 .enable = s3c64xx_pclk_ctrl,
264 .ctrlbit = S3C_CLKCON_PCLK_UART1,
269 .enable = s3c64xx_pclk_ctrl,
270 .ctrlbit = S3C_CLKCON_PCLK_UART2,
275 .enable = s3c64xx_pclk_ctrl,
276 .ctrlbit = S3C_CLKCON_PCLK_UART3,
281 .enable = s3c64xx_pclk_ctrl,
282 .ctrlbit = S3C_CLKCON_PCLK_RTC,
287 .ctrlbit = S3C_CLKCON_PCLK_WDT,
292 .ctrlbit = S3C_CLKCON_PCLK_AC97,
297 static struct clk clk_fout_apll = {
302 static struct clk *clk_src_apll_list[] = {
304 [1] = &clk_fout_apll,
307 static struct clksrc_sources clk_src_apll = {
308 .sources = clk_src_apll_list,
309 .nr_sources = ARRAY_SIZE(clk_src_apll_list),
312 static struct clksrc_clk clk_mout_apll = {
317 .reg_src = { .reg = S3C_CLK_SRC, .shift = 0, .size = 1 },
318 .sources = &clk_src_apll,
321 static struct clk *clk_src_epll_list[] = {
323 [1] = &clk_fout_epll,
326 static struct clksrc_sources clk_src_epll = {
327 .sources = clk_src_epll_list,
328 .nr_sources = ARRAY_SIZE(clk_src_epll_list),
331 static struct clksrc_clk clk_mout_epll = {
336 .reg_src = { .reg = S3C_CLK_SRC, .shift = 2, .size = 1 },
337 .sources = &clk_src_epll,
340 static struct clk *clk_src_mpll_list[] = {
342 [1] = &clk_fout_mpll,
345 static struct clksrc_sources clk_src_mpll = {
346 .sources = clk_src_mpll_list,
347 .nr_sources = ARRAY_SIZE(clk_src_mpll_list),
350 static struct clksrc_clk clk_mout_mpll = {
355 .reg_src = { .reg = S3C_CLK_SRC, .shift = 1, .size = 1 },
356 .sources = &clk_src_mpll,
359 static unsigned int armclk_mask;
361 static unsigned long s3c64xx_clk_arm_get_rate(struct clk *clk)
363 unsigned long rate = clk_get_rate(clk->parent);
366 /* divisor mask starts at bit0, so no need to shift */
367 clkdiv = __raw_readl(S3C_CLK_DIV0) & armclk_mask;
369 return rate / (clkdiv + 1);
372 static unsigned long s3c64xx_clk_arm_round_rate(struct clk *clk,
375 unsigned long parent = clk_get_rate(clk->parent);
381 div = (parent / rate) - 1;
382 if (div > armclk_mask)
385 return parent / (div + 1);
388 static int s3c64xx_clk_arm_set_rate(struct clk *clk, unsigned long rate)
390 unsigned long parent = clk_get_rate(clk->parent);
394 if (rate < parent / (armclk_mask + 1))
397 rate = clk_round_rate(clk, rate);
398 div = clk_get_rate(clk->parent) / rate;
400 val = __raw_readl(S3C_CLK_DIV0);
403 __raw_writel(val, S3C_CLK_DIV0);
409 static struct clk clk_arm = {
412 .parent = &clk_mout_apll.clk,
413 .ops = &(struct clk_ops) {
414 .get_rate = s3c64xx_clk_arm_get_rate,
415 .set_rate = s3c64xx_clk_arm_set_rate,
416 .round_rate = s3c64xx_clk_arm_round_rate,
420 static unsigned long s3c64xx_clk_doutmpll_get_rate(struct clk *clk)
422 unsigned long rate = clk_get_rate(clk->parent);
424 printk(KERN_DEBUG "%s: parent is %ld\n", __func__, rate);
426 if (__raw_readl(S3C_CLK_DIV0) & S3C6400_CLKDIV0_MPLL_MASK)
432 static struct clk_ops clk_dout_ops = {
433 .get_rate = s3c64xx_clk_doutmpll_get_rate,
436 static struct clk clk_dout_mpll = {
439 .parent = &clk_mout_mpll.clk,
440 .ops = &clk_dout_ops,
443 static struct clk *clkset_spi_mmc_list[] = {
450 static struct clksrc_sources clkset_spi_mmc = {
451 .sources = clkset_spi_mmc_list,
452 .nr_sources = ARRAY_SIZE(clkset_spi_mmc_list),
455 static struct clk *clkset_irda_list[] = {
462 static struct clksrc_sources clkset_irda = {
463 .sources = clkset_irda_list,
464 .nr_sources = ARRAY_SIZE(clkset_irda_list),
467 static struct clk *clkset_uart_list[] = {
474 static struct clksrc_sources clkset_uart = {
475 .sources = clkset_uart_list,
476 .nr_sources = ARRAY_SIZE(clkset_uart_list),
479 static struct clk *clkset_uhost_list[] = {
486 static struct clksrc_sources clkset_uhost = {
487 .sources = clkset_uhost_list,
488 .nr_sources = ARRAY_SIZE(clkset_uhost_list),
491 /* The peripheral clocks are all controlled via clocksource followed
492 * by an optional divider and gate stage. We currently roll this into
493 * one clock which hides the intermediate clock from the mux.
495 * Note, the JPEG clock can only be an even divider...
497 * The scaler and LCD clocks depend on the S3C64XX version, and also
498 * have a common parent divisor so are not included here.
501 /* clocks that feed other parts of the clock source tree */
503 static struct clk clk_iis_cd0 = {
504 .name = "iis_cdclk0",
508 static struct clk clk_iis_cd1 = {
509 .name = "iis_cdclk1",
513 static struct clk clk_pcm_cd = {
518 static struct clk *clkset_audio0_list[] = {
519 [0] = &clk_mout_epll.clk,
520 [1] = &clk_dout_mpll,
526 static struct clksrc_sources clkset_audio0 = {
527 .sources = clkset_audio0_list,
528 .nr_sources = ARRAY_SIZE(clkset_audio0_list),
531 static struct clk *clkset_audio1_list[] = {
532 [0] = &clk_mout_epll.clk,
533 [1] = &clk_dout_mpll,
539 static struct clksrc_sources clkset_audio1 = {
540 .sources = clkset_audio1_list,
541 .nr_sources = ARRAY_SIZE(clkset_audio1_list),
544 static struct clk *clkset_camif_list[] = {
548 static struct clksrc_sources clkset_camif = {
549 .sources = clkset_camif_list,
550 .nr_sources = ARRAY_SIZE(clkset_camif_list),
553 static struct clksrc_clk clksrcs[] = {
558 .ctrlbit = S3C_CLKCON_SCLK_MMC0,
559 .enable = s3c64xx_sclk_ctrl,
561 .reg_src = { .reg = S3C_CLK_SRC, .shift = 18, .size = 2 },
562 .reg_div = { .reg = S3C_CLK_DIV1, .shift = 0, .size = 4 },
563 .sources = &clkset_spi_mmc,
568 .ctrlbit = S3C_CLKCON_SCLK_MMC1,
569 .enable = s3c64xx_sclk_ctrl,
571 .reg_src = { .reg = S3C_CLK_SRC, .shift = 20, .size = 2 },
572 .reg_div = { .reg = S3C_CLK_DIV1, .shift = 4, .size = 4 },
573 .sources = &clkset_spi_mmc,
578 .ctrlbit = S3C_CLKCON_SCLK_MMC2,
579 .enable = s3c64xx_sclk_ctrl,
581 .reg_src = { .reg = S3C_CLK_SRC, .shift = 22, .size = 2 },
582 .reg_div = { .reg = S3C_CLK_DIV1, .shift = 8, .size = 4 },
583 .sources = &clkset_spi_mmc,
586 .name = "usb-bus-host",
588 .ctrlbit = S3C_CLKCON_SCLK_UHOST,
589 .enable = s3c64xx_sclk_ctrl,
591 .reg_src = { .reg = S3C_CLK_SRC, .shift = 5, .size = 2 },
592 .reg_div = { .reg = S3C_CLK_DIV1, .shift = 20, .size = 4 },
593 .sources = &clkset_uhost,
598 .ctrlbit = S3C_CLKCON_SCLK_UART,
599 .enable = s3c64xx_sclk_ctrl,
601 .reg_src = { .reg = S3C_CLK_SRC, .shift = 13, .size = 1 },
602 .reg_div = { .reg = S3C_CLK_DIV2, .shift = 16, .size = 4 },
603 .sources = &clkset_uart,
605 /* Where does UCLK0 come from? */
609 .ctrlbit = S3C_CLKCON_SCLK_SPI0,
610 .enable = s3c64xx_sclk_ctrl,
612 .reg_src = { .reg = S3C_CLK_SRC, .shift = 14, .size = 2 },
613 .reg_div = { .reg = S3C_CLK_DIV2, .shift = 0, .size = 4 },
614 .sources = &clkset_spi_mmc,
619 .ctrlbit = S3C_CLKCON_SCLK_SPI1,
620 .enable = s3c64xx_sclk_ctrl,
622 .reg_src = { .reg = S3C_CLK_SRC, .shift = 16, .size = 2 },
623 .reg_div = { .reg = S3C_CLK_DIV2, .shift = 4, .size = 4 },
624 .sources = &clkset_spi_mmc,
629 .ctrlbit = S3C_CLKCON_SCLK_AUDIO0,
630 .enable = s3c64xx_sclk_ctrl,
632 .reg_src = { .reg = S3C_CLK_SRC, .shift = 7, .size = 3 },
633 .reg_div = { .reg = S3C_CLK_DIV2, .shift = 8, .size = 4 },
634 .sources = &clkset_audio0,
639 .ctrlbit = S3C_CLKCON_SCLK_AUDIO1,
640 .enable = s3c64xx_sclk_ctrl,
642 .reg_src = { .reg = S3C_CLK_SRC, .shift = 10, .size = 3 },
643 .reg_div = { .reg = S3C_CLK_DIV2, .shift = 12, .size = 4 },
644 .sources = &clkset_audio1,
649 .ctrlbit = S3C_CLKCON_SCLK_IRDA,
650 .enable = s3c64xx_sclk_ctrl,
652 .reg_src = { .reg = S3C_CLK_SRC, .shift = 24, .size = 2 },
653 .reg_div = { .reg = S3C_CLK_DIV2, .shift = 20, .size = 4 },
654 .sources = &clkset_irda,
659 .ctrlbit = S3C_CLKCON_SCLK_CAM,
660 .enable = s3c64xx_sclk_ctrl,
662 .reg_div = { .reg = S3C_CLK_DIV0, .shift = 20, .size = 4 },
663 .reg_src = { .reg = NULL, .shift = 0, .size = 0 },
664 .sources = &clkset_camif,
668 /* Clock initialisation code */
670 static struct clksrc_clk *init_parents[] = {
676 #define GET_DIV(clk, field) ((((clk) & field##_MASK) >> field##_SHIFT) + 1)
678 void __init_or_cpufreq s3c6400_setup_clocks(void)
680 struct clk *xtal_clk;
692 printk(KERN_DEBUG "%s: registering clocks\n", __func__);
694 clkdiv0 = __raw_readl(S3C_CLK_DIV0);
695 printk(KERN_DEBUG "%s: clkdiv0 = %08x\n", __func__, clkdiv0);
697 xtal_clk = clk_get(NULL, "xtal");
698 BUG_ON(IS_ERR(xtal_clk));
700 xtal = clk_get_rate(xtal_clk);
703 printk(KERN_DEBUG "%s: xtal is %ld\n", __func__, xtal);
705 /* For now assume the mux always selects the crystal */
706 clk_ext_xtal_mux.parent = xtal_clk;
708 epll = s3c6400_get_epll(xtal);
709 mpll = s3c6400_get_pll(xtal, __raw_readl(S3C_MPLL_CON));
710 apll = s3c6400_get_pll(xtal, __raw_readl(S3C_APLL_CON));
714 printk(KERN_INFO "S3C64XX: PLL settings, A=%ld, M=%ld, E=%ld\n",
717 hclk2 = mpll / GET_DIV(clkdiv0, S3C6400_CLKDIV0_HCLK2);
718 hclk = hclk2 / GET_DIV(clkdiv0, S3C6400_CLKDIV0_HCLK);
719 pclk = hclk2 / GET_DIV(clkdiv0, S3C6400_CLKDIV0_PCLK);
721 printk(KERN_INFO "S3C64XX: HCLK2=%ld, HCLK=%ld, PCLK=%ld\n",
724 clk_fout_mpll.rate = mpll;
725 clk_fout_epll.rate = epll;
726 clk_fout_apll.rate = apll;
733 for (ptr = 0; ptr < ARRAY_SIZE(init_parents); ptr++)
734 s3c_set_clksrc(init_parents[ptr], true);
736 for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
737 s3c_set_clksrc(&clksrcs[ptr], true);
740 static struct clk *clks1[] __initdata = {
752 * s3c6400_register_clocks - register clocks for s3c6400 and above
753 * @armclk_divlimit: Divisor mask for ARMCLK
755 * Register the clocks for the S3C6400 and above SoC range, such
756 * as ARMCLK and the clocks which have divider chains attached.
758 * This call does not setup the clocks, which is left to the
759 * s3c6400_setup_clocks() call which may be needed by the cpufreq
760 * or resume code to re-set the clocks if the bootloader has changed
763 void __init s3c6400_register_clocks(unsigned armclk_divlimit)
769 armclk_mask = armclk_divlimit;
771 for (ptr = 0; ptr < ARRAY_SIZE(clks1); ptr++) {
773 ret = s3c24xx_register_clock(clkp);
775 printk(KERN_ERR "Failed to register clock %s (%d)\n",
780 s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
783 static struct clk *clks[] __initdata = {
791 void __init s3c64xx_register_clocks(void)
797 s3c24xx_register_clocks(clks, ARRAY_SIZE(clks));
798 s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
800 clkp = init_clocks_disable;
801 for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
803 ret = s3c24xx_register_clock(clkp);
805 printk(KERN_ERR "Failed to register clock %s (%d)\n",
809 (clkp->enable)(clkp, 0);