[ARM] S3C64XX: Add initial clock framework
authorBen Dooks <ben-linux@fluff.org>
Tue, 21 Oct 2008 13:07:00 +0000 (14:07 +0100)
committerBen Dooks <ben-linux@fluff.org>
Mon, 15 Dec 2008 21:53:58 +0000 (21:53 +0000)
Add the initial clocks definitions for the s3c6400
and s3c6410. Move the epll and ext clock from the
s3c2443 support into the common code.

Signed-off-by: Ben Dooks <ben-linux@fluff.org>
arch/arm/mach-s3c2412/clock.c
arch/arm/mach-s3c2443/clock.c
arch/arm/mach-s3c6410/cpu.c
arch/arm/plat-s3c/clock.c
arch/arm/plat-s3c/include/plat/clock.h
arch/arm/plat-s3c64xx/Makefile
arch/arm/plat-s3c64xx/clock.c [new file with mode: 0644]

index 96d9eb1..3ce15e0 100644 (file)
@@ -93,12 +93,6 @@ static int s3c2412_upll_enable(struct clk *clk, int enable)
 
 /* clock selections */
 
-/* CPU EXTCLK input */
-static struct clk clk_ext = {
-       .name           = "extclk",
-       .id             = -1,
-};
-
 static struct clk clk_erefclk = {
        .name           = "erefclk",
        .id             = -1,
index 1df8429..363f396 100644 (file)
@@ -147,12 +147,6 @@ static unsigned long s3c2443_roundrate_clksrc256(struct clk *clk,
 
 /* clock selections */
 
-/* CPU EXTCLK input */
-static struct clk clk_ext = {
-       .name           = "ext",
-       .id             = -1,
-};
-
 static struct clk clk_mpllref = {
        .name           = "mpllref",
        .parent         = &clk_xtal,
@@ -167,14 +161,6 @@ static struct clk clk_mpll = {
 };
 #endif
 
-static struct clk clk_epllref;
-
-static struct clk clk_epll = {
-       .name           = "epll",
-       .parent         = &clk_epllref,
-       .id             = -1,
-};
-
 static struct clk clk_i2s_ext = {
        .name           = "i2s-ext",
        .id             = -1,
@@ -1072,6 +1058,7 @@ void __init s3c2443_init_clocks(int xtal)
        }
 
        clk_epll.rate = s3c2443_get_epll(epllcon, xtal);
+       clk_epll.parent = &clk_epllref;
        clk_usb_bus.parent = &clk_usb_bus_host;
 
        /* ensure usb bus clock is within correct rate of 48MHz */
index c3e317c..94a6204 100644 (file)
@@ -56,6 +56,7 @@ void __init s3c6410_init_clocks(int xtal)
 {
        printk(KERN_INFO "%s: initialising clocks\n", __func__);
        s3c24xx_register_baseclocks(xtal);
+       s3c64xx_register_clocks();
 }
 
 void __init s3c6410_init_irq(void)
index da7ac07..1054d18 100644 (file)
@@ -239,6 +239,16 @@ struct clk clk_xtal = {
        .ctrlbit        = 0,
 };
 
+struct clk clk_ext = {
+       .name           = "ext",
+       .id             = -1,
+};
+
+struct clk clk_epll = {
+       .name           = "epll",
+       .id             = -1,
+};
+
 struct clk clk_mpll = {
        .name           = "mpll",
        .id             = -1,
index d871609..6a2c5af 100644 (file)
@@ -45,7 +45,13 @@ extern struct clk clk_h;
 extern struct clk clk_p;
 extern struct clk clk_mpll;
 extern struct clk clk_upll;
+extern struct clk clk_epll;
 extern struct clk clk_xtal;
+extern struct clk clk_ext;
+
+/* S3C64XX specific clocks */
+extern struct clk clk_27m;
+extern struct clk clk_48m;
 
 /* exports for arch/arm/mach-s3c2410
  *
@@ -61,6 +67,8 @@ extern int s3c24xx_register_clocks(struct clk **clk, int nr_clks);
 
 extern int s3c24xx_register_baseclocks(unsigned long xtal);
 
+extern void s3c64xx_register_clocks(void);
+
 extern void s3c24xx_setup_clocks(unsigned long fclk,
                                 unsigned long hclk,
                                 unsigned long pclk);
index 26b5714..15f717f 100644 (file)
@@ -15,6 +15,7 @@ obj-                          :=
 obj-y                          += dev-uart.o
 obj-y                          += cpu.o
 obj-y                          += irq.o
+obj-y                          += clock.o
 
 # CPU support
 
diff --git a/arch/arm/plat-s3c64xx/clock.c b/arch/arm/plat-s3c64xx/clock.c
new file mode 100644 (file)
index 0000000..e7c2994
--- /dev/null
@@ -0,0 +1,258 @@
+/* linux/arch/arm/plat-s3c64xx/clock.c
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *     http://armlinux.simtec.co.uk/
+ *
+ * S3C64XX Base clock support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <mach/map.h>
+
+#include <plat/regs-clock.h>
+#include <plat/cpu.h>
+#include <plat/devs.h>
+#include <plat/clock.h>
+
+struct clk clk_27m = {
+       .name           = "clk_27m",
+       .id             = -1,
+       .rate           = 27000000,
+};
+
+struct clk clk_48m = {
+       .name           = "clk_48m",
+       .id             = -1,
+       .rate           = 48000000,
+};
+
+static int inline s3c64xx_gate(void __iomem *reg,
+                               struct clk *clk,
+                               int enable)
+{
+       unsigned int ctrlbit = clk->ctrlbit;
+       u32 con;
+
+       con = __raw_readl(reg);
+
+       if (enable)
+               con |= ctrlbit;
+       else
+               con &= ~ctrlbit;
+
+       __raw_writel(con, reg);
+       return 0;
+}
+
+static int s3c64xx_pclk_ctrl(struct clk *clk, int enable)
+{
+       return s3c64xx_gate(S3C_PCLK_GATE, clk, enable);
+}
+
+static int s3c64xx_hclk_ctrl(struct clk *clk, int enable)
+{
+       return s3c64xx_gate(S3C_HCLK_GATE, clk, enable);
+}
+
+static int s3c6xx_sclk_ctrl(struct clk *clk, int enable)
+{
+       return s3c64xx_gate(S3C_SCLK_GATE, clk, enable);
+}
+
+static struct clk init_clocks_disable[] = {
+       {
+               .name           = "nand",
+               .id             = -1,
+               .parent         = &clk_h,
+       }, {
+               .name           = "adc",
+               .id             = -1,
+               .parent         = &clk_p,
+               .enable         = s3c64xx_pclk_ctrl,
+               .ctrlbit        = S3C_CLKCON_PCLK_TSADC,
+       }, {
+               .name           = "i2c",
+               .id             = -1,
+               .parent         = &clk_p,
+               .enable         = s3c64xx_pclk_ctrl,
+               .ctrlbit        = S3C_CLKCON_PCLK_IIC,
+       }, {
+               .name           = "iis",
+               .id             = 0,
+               .parent         = &clk_p,
+               .enable         = s3c64xx_pclk_ctrl,
+               .ctrlbit        = S3C_CLKCON_PCLK_IIS0,
+       }, {
+               .name           = "iis",
+               .id             = 1,
+               .parent         = &clk_p,
+               .enable         = s3c64xx_pclk_ctrl,
+               .ctrlbit        = S3C_CLKCON_PCLK_IIS1,
+       }, {
+               .name           = "spi",
+               .id             = 0,
+               .parent         = &clk_p,
+               .enable         = s3c64xx_pclk_ctrl,
+               .ctrlbit        = S3C_CLKCON_PCLK_SPI0,
+       }, {
+               .name           = "spi",
+               .id             = 1,
+               .parent         = &clk_p,
+               .enable         = s3c64xx_pclk_ctrl,
+               .ctrlbit        = S3C_CLKCON_PCLK_SPI1,
+       }, {
+               .name           = "48m",
+               .id             = 0,
+               .parent         = &clk_48m,
+               .enable         = s3c64xx_sclk_ctrl,
+               .ctrlbit        = S3C_CLKCON_SCLK_MMC0_48,
+       }, {
+               .name           = "48m",
+               .id             = 1,
+               .parent         = &clk_48m,
+               .enable         = s3c64xx_sclk_ctrl,
+               .ctrlbit        = S3C_CLKCON_SCLK_MMC1_48,
+       }, {
+               .name           = "48m",
+               .id             = 2,
+               .parent         = &clk_48m,
+               .enable         = s3c64xx_sclk_ctrl,
+               .ctrlbit        = S3C_CLKCON_SCLK_MMC2_48,
+       },
+};
+
+static struct clk init_clocks[] = {
+       {
+               .name           = "lcd",
+               .id             = -1,
+               .parent         = &clk_h,
+               .enable         = s3c64xx_hclk_ctrl,
+               .ctrlbit        = S3C_CLKCON_HCLK_LCD,
+       }, {
+               .name           = "gpio",
+               .id             = -1,
+               .parent         = &clk_p,
+               .enable         = s3c64xx_pclk_ctrl,
+               .ctrlbit        = S3C_CLKCON_PCLK_GPIO,
+       }, {
+               .name           = "usb-host",
+               .id             = -1,
+               .parent         = &clk_h,
+               .enable         = s3c64xx_hclk_ctrl,
+               .ctrlbit        = S3C_CLKCON_SCLK_UHOST,
+       }, {
+               .name           = "hsmmc",
+               .id             = 0,
+               .parent         = &clk_h,
+               .enable         = s3c64xx_hclk_ctrl,
+               .ctrlbit        = S3C_CLKCON_HCLK_HSMMC0,
+       }, {
+               .name           = "hsmmc",
+               .id             = 1,
+               .parent         = &clk_h,
+               .enable         = s3c64xx_hclk_ctrl,
+               .ctrlbit        = S3C_CLKCON_HCLK_HSMMC1,
+       }, {
+               .name           = "hsmmc",
+               .id             = 2,
+               .parent         = &clk_h,
+               .enable         = s3c64xx_hclk_ctrl,
+               .ctrlbit        = S3C_CLKCON_HCLK_HSMMC2,
+       }, {
+               .name           = "timers",
+               .id             = -1,
+               .parent         = &clk_p,
+               .enable         = s3c64xx_pclk_ctrl,
+               .ctrlbit        = S3C_CLKCON_PCLK_PWM,
+       }, {
+               .name           = "uart",
+               .id             = 0,
+               .parent         = &clk_p,
+               .enable         = s3c64xx_pclk_ctrl,
+               .ctrlbit        = S3C_CLKCON_PCLK_UART0,
+       }, {
+               .name           = "uart",
+               .id             = 1,
+               .parent         = &clk_p,
+               .enable         = s3c64xx_pclk_ctrl,
+               .ctrlbit        = S3C_CLKCON_PCLK_UART1,
+       }, {
+               .name           = "uart",
+               .id             = 2,
+               .parent         = &clk_p,
+               .enable         = s3c64xx_pclk_ctrl,
+               .ctrlbit        = S3C_CLKCON_PCLK_UART2,
+       }, {
+               .name           = "uart",
+               .id             = 3,
+               .parent         = &clk_p,
+               .enable         = s3c64xx_pclk_ctrl,
+               .ctrlbit        = S3C_CLKCON_PCLK_UART3,
+       }, {
+               .name           = "rtc",
+               .id             = -1,
+               .parent         = &clk_p,
+               .enable         = s3c64xx_pclk_ctrl,
+               .ctrlbit        = S3C_CLKCON_PCLK_RTC,
+       }, {
+               .name           = "watchdog",
+               .id             = -1,
+               .parent         = &clk_p,
+               .ctrlbit        = S3C_CLKCON_PCLK_WDT,
+       }, {
+               .name           = "ac97",
+               .id             = -1,
+               .parent         = &clk_p,
+               .ctrlbit        = S3C_CLKCON_PCLK_AC97,
+       }
+};
+
+static struct clk *clks[] __initdata = {
+       &clk_ext,
+       &clk_epll,
+       &clk_27m,
+       &clk_48m,
+};
+
+void s3c64xx_register_clocks(void)
+{
+       struct clk *clkp;
+       int ret;
+       int ptr;
+
+       s3c24xx_register_clocks(clks, ARRAY_SIZE(clks));
+
+       clkp = init_clocks;
+       for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) {
+               ret = s3c24xx_register_clock(clkp);
+               if (ret < 0) {
+                       printk(KERN_ERR "Failed to register clock %s (%d)\n",
+                              clkp->name, ret);
+               }
+       }
+
+       clkp = init_clocks_disable;
+       for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
+
+               ret = s3c24xx_register_clock(clkp);
+               if (ret < 0) {
+                       printk(KERN_ERR "Failed to register clock %s (%d)\n",
+                              clkp->name, ret);
+               }
+
+               (clkp->enable)(clkp, 0);
+       }
+}