[ARM] 3361/1: S3C24XX - add USB bus clock source

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>
diff --git a/arch/arm/mach-s3c2410/s3c2440-clock.c b/arch/arm/mach-s3c2410/s3c2440-clock.c
index 7bca0be..57a1597 100644
--- a/arch/arm/mach-s3c2410/s3c2440-clock.c
+++ b/arch/arm/mach-s3c2410/s3c2440-clock.c
@@ -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 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;