aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-s3c2410/clock.c14
-rw-r--r--arch/arm/mach-s3c2410/clock.h4
-rw-r--r--arch/arm/mach-s3c2410/s3c2440-clock.c21
3 files changed, 37 insertions, 2 deletions
diff --git a/arch/arm/mach-s3c2410/clock.c b/arch/arm/mach-s3c2410/clock.c
index 95c6d46c3dd6..fec02c92f95f 100644
--- a/arch/arm/mach-s3c2410/clock.c
+++ b/arch/arm/mach-s3c2410/clock.c
@@ -53,7 +53,8 @@
53/* clock information */ 53/* clock information */
54 54
55static LIST_HEAD(clocks); 55static LIST_HEAD(clocks);
56static DEFINE_MUTEX(clocks_mutex); 56
57DEFINE_MUTEX(clocks_mutex);
57 58
58/* old functions */ 59/* old functions */
59 60
@@ -296,6 +297,13 @@ static struct clk clk_p = {
296 .ctrlbit = 0, 297 .ctrlbit = 0,
297}; 298};
298 299
300struct clk clk_usb_bus = {
301 .name = "usb-bus",
302 .id = -1,
303 .rate = 0,
304 .parent = &clk_upll,
305};
306
299/* clocks that could be registered by external code */ 307/* clocks that could be registered by external code */
300 308
301static int s3c24xx_dclk_enable(struct clk *clk, int enable) 309static int s3c24xx_dclk_enable(struct clk *clk, int enable)
@@ -606,6 +614,10 @@ int __init s3c24xx_setup_clocks(unsigned long xtal,
606 if (s3c24xx_register_clock(&clk_p) < 0) 614 if (s3c24xx_register_clock(&clk_p) < 0)
607 printk(KERN_ERR "failed to register cpu pclk\n"); 615 printk(KERN_ERR "failed to register cpu pclk\n");
608 616
617
618 if (s3c24xx_register_clock(&clk_usb_bus) < 0)
619 printk(KERN_ERR "failed to register usb bus clock\n");
620
609 /* register clocks from clock array */ 621 /* register clocks from clock array */
610 622
611 for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) { 623 for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) {
diff --git a/arch/arm/mach-s3c2410/clock.h b/arch/arm/mach-s3c2410/clock.h
index 32864b30c1e0..01bb458bf8eb 100644
--- a/arch/arm/mach-s3c2410/clock.h
+++ b/arch/arm/mach-s3c2410/clock.h
@@ -34,11 +34,15 @@ extern struct clk s3c24xx_clkout0;
34extern struct clk s3c24xx_clkout1; 34extern struct clk s3c24xx_clkout1;
35extern struct clk s3c24xx_uclk; 35extern struct clk s3c24xx_uclk;
36 36
37extern struct clk clk_usb_bus;
38
37/* exports for arch/arm/mach-s3c2410 39/* exports for arch/arm/mach-s3c2410
38 * 40 *
39 * Please DO NOT use these outside of arch/arm/mach-s3c2410 41 * Please DO NOT use these outside of arch/arm/mach-s3c2410
40*/ 42*/
41 43
44extern struct mutex clocks_mutex;
45
42extern int s3c24xx_clkcon_enable(struct clk *clk, int enable); 46extern int s3c24xx_clkcon_enable(struct clk *clk, int enable);
43extern int s3c24xx_register_clock(struct clk *clk); 47extern int s3c24xx_register_clock(struct clk *clk);
44 48
diff --git a/arch/arm/mach-s3c2410/s3c2440-clock.c b/arch/arm/mach-s3c2410/s3c2440-clock.c
index 7bca0be87384..57a15974d4b5 100644
--- a/arch/arm/mach-s3c2410/s3c2440-clock.c
+++ b/arch/arm/mach-s3c2410/s3c2440-clock.c
@@ -31,6 +31,7 @@
31#include <linux/sysdev.h> 31#include <linux/sysdev.h>
32#include <linux/interrupt.h> 32#include <linux/interrupt.h>
33#include <linux/ioport.h> 33#include <linux/ioport.h>
34#include <linux/mutex.h>
34#include <linux/clk.h> 35#include <linux/clk.h>
35 36
36#include <asm/hardware.h> 37#include <asm/hardware.h>
@@ -111,20 +112,38 @@ static struct clk s3c2440_clk_ac97 = {
111static int s3c2440_clk_add(struct sys_device *sysdev) 112static int s3c2440_clk_add(struct sys_device *sysdev)
112{ 113{
113 unsigned long camdivn = __raw_readl(S3C2440_CAMDIVN); 114 unsigned long camdivn = __raw_readl(S3C2440_CAMDIVN);
115 unsigned long clkdivn;
114 struct clk *clk_h; 116 struct clk *clk_h;
115 struct clk *clk_p; 117 struct clk *clk_p;
118 struct clk *clk_upll;
116 119
117 printk("S3C2440: Clock Support, DVS %s\n", 120 printk("S3C2440: Clock Support, DVS %s\n",
118 (camdivn & S3C2440_CAMDIVN_DVSEN) ? "on" : "off"); 121 (camdivn & S3C2440_CAMDIVN_DVSEN) ? "on" : "off");
119 122
120 clk_p = clk_get(NULL, "pclk"); 123 clk_p = clk_get(NULL, "pclk");
121 clk_h = clk_get(NULL, "hclk"); 124 clk_h = clk_get(NULL, "hclk");
125 clk_upll = clk_get(NULL, "upll");
122 126
123 if (IS_ERR(clk_p) || IS_ERR(clk_h)) { 127 if (IS_ERR(clk_p) || IS_ERR(clk_h) || IS_ERR(clk_upll)) {
124 printk(KERN_ERR "S3C2440: Failed to get parent clocks\n"); 128 printk(KERN_ERR "S3C2440: Failed to get parent clocks\n");
125 return -EINVAL; 129 return -EINVAL;
126 } 130 }
127 131
132 /* check rate of UPLL, and if it is near 96MHz, then change
133 * to using half the UPLL rate for the system */
134
135 if (clk_get_rate(clk_upll) > (94 * MHZ)) {
136 clk_usb_bus.rate = clk_get_rate(clk_upll) / 2;
137
138 mutex_lock(&clocks_mutex);
139
140 clkdivn = __raw_readl(S3C2410_CLKDIVN);
141 clkdivn |= S3C2440_CLKDIVN_UCLK;
142 __raw_writel(camdivn, S3C2410_CLKDIVN);
143
144 mutex_unlock(&clocks_mutex);
145 }
146
128 s3c2440_clk_cam.parent = clk_h; 147 s3c2440_clk_cam.parent = clk_h;
129 s3c2440_clk_ac97.parent = clk_p; 148 s3c2440_clk_ac97.parent = clk_p;
130 s3c2440_clk_cam_upll.parent = clk_upll; 149 s3c2440_clk_cam_upll.parent = clk_upll;