[ARM] 3361/1: S3C24XX - add USB bus clock source
authorBen Dooks <ben@trinity.fluff.org>
Mon, 20 Mar 2006 21:00:48 +0000 (21:00 +0000)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Tue, 21 Mar 2006 22:06:20 +0000 (22:06 +0000)
Patch from Ben Dooks

Add USB bus clock definition for 48MHz fed to OHCI and gadget cores

Signed-off-by: Ben Dooks <ben-linux@fluff.org>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
arch/arm/mach-s3c2410/clock.c
arch/arm/mach-s3c2410/clock.h
arch/arm/mach-s3c2410/s3c2440-clock.c

index 95c6d46c3dd64b0d9ba8208071097a72899431db..fec02c92f95f4406da0dc2a1e2ca4a9e933c4159 100644 (file)
@@ -53,7 +53,8 @@
 /* clock information */
 
 static LIST_HEAD(clocks);
-static DEFINE_MUTEX(clocks_mutex);
+
+DEFINE_MUTEX(clocks_mutex);
 
 /* old functions */
 
@@ -296,6 +297,13 @@ static struct clk clk_p = {
        .ctrlbit        = 0,
 };
 
+struct clk clk_usb_bus = {
+       .name           = "usb-bus",
+       .id             = -1,
+       .rate           = 0,
+       .parent         = &clk_upll,
+};
+
 /* clocks that could be registered by external code */
 
 static int s3c24xx_dclk_enable(struct clk *clk, int enable)
@@ -606,6 +614,10 @@ int __init s3c24xx_setup_clocks(unsigned long xtal,
        if (s3c24xx_register_clock(&clk_p) < 0)
                printk(KERN_ERR "failed to register cpu pclk\n");
 
+
+       if (s3c24xx_register_clock(&clk_usb_bus) < 0)
+               printk(KERN_ERR "failed to register usb bus clock\n");
+
        /* register clocks from clock array */
 
        for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) {
index 32864b30c1e0965488b0a1c9ec9fb463be8f168a..01bb458bf8eb9482d23d6d408e08bbba4fb0c228 100644 (file)
@@ -34,11 +34,15 @@ extern struct clk s3c24xx_clkout0;
 extern struct clk s3c24xx_clkout1;
 extern struct clk s3c24xx_uclk;
 
+extern struct clk clk_usb_bus;
+
 /* exports for arch/arm/mach-s3c2410
  *
  * Please DO NOT use these outside of arch/arm/mach-s3c2410
 */
 
+extern struct mutex clocks_mutex;
+
 extern int s3c24xx_clkcon_enable(struct clk *clk, int enable);
 extern int s3c24xx_register_clock(struct clk *clk);
 
index 7bca0be873848c728968a5c7d0aa8570ee083581..57a15974d4b50aaded6667882e4004b459cca878 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/sysdev.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
+#include <linux/mutex.h>
 #include <linux/clk.h>
 
 #include <asm/hardware.h>
@@ -111,20 +112,38 @@ static struct clk s3c2440_clk_ac97 = {
 static int s3c2440_clk_add(struct sys_device *sysdev)
 {
        unsigned long camdivn = __raw_readl(S3C2440_CAMDIVN);
+       unsigned long clkdivn;
        struct clk *clk_h;
        struct clk *clk_p;
+       struct clk *clk_upll;
 
        printk("S3C2440: Clock Support, DVS %s\n",
               (camdivn & S3C2440_CAMDIVN_DVSEN) ? "on" : "off");
 
        clk_p = clk_get(NULL, "pclk");
        clk_h = clk_get(NULL, "hclk");
+       clk_upll = clk_get(NULL, "upll");
 
-       if (IS_ERR(clk_p) || IS_ERR(clk_h)) {
+       if (IS_ERR(clk_p) || IS_ERR(clk_h) || IS_ERR(clk_upll)) {
                printk(KERN_ERR "S3C2440: Failed to get parent clocks\n");
                return -EINVAL;
        }
 
+       /* check rate of UPLL, and if it is near 96MHz, then change
+        * to using half the UPLL rate for the system */
+
+       if (clk_get_rate(clk_upll) > (94 * MHZ)) {
+               clk_usb_bus.rate = clk_get_rate(clk_upll) / 2;
+
+               mutex_lock(&clocks_mutex);
+
+               clkdivn = __raw_readl(S3C2410_CLKDIVN);
+               clkdivn |= S3C2440_CLKDIVN_UCLK;
+               __raw_writel(camdivn, S3C2410_CLKDIVN);
+
+               mutex_unlock(&clocks_mutex);
+       }
+
        s3c2440_clk_cam.parent = clk_h;
        s3c2440_clk_ac97.parent = clk_p;
        s3c2440_clk_cam_upll.parent = clk_upll;