diff options
author | Ben Dooks <ben-linux@fluff.org> | 2008-10-21 09:06:37 -0400 |
---|---|---|
committer | Ben Dooks <ben-linux@fluff.org> | 2008-12-15 16:46:07 -0500 |
commit | c3391e36d697c997b6afeb045071e0be95219a3e (patch) | |
tree | 8bd9c12dd364519347473277496da3f3f1a54c9c /arch/arm/plat-s3c24xx | |
parent | 305554768011707f33f437b96f999f812ba2a7e4 (diff) |
[ARM] S3C24XX: Change clock locking to use spinlocks.
We cannot sleep if we have cpufreq pm enabled during some
of the clock operations, so change to use a spinlock to
protect the clock system.
Signed-off-by: Ben Dooks <ben-linux@fluff.org>
Diffstat (limited to 'arch/arm/plat-s3c24xx')
-rw-r--r-- | arch/arm/plat-s3c24xx/clock.c | 32 | ||||
-rw-r--r-- | arch/arm/plat-s3c24xx/include/plat/clock.h | 4 | ||||
-rw-r--r-- | arch/arm/plat-s3c24xx/s3c244x-clock.c | 5 |
3 files changed, 23 insertions, 18 deletions
diff --git a/arch/arm/plat-s3c24xx/clock.c b/arch/arm/plat-s3c24xx/clock.c index 1ff1b9836042..334e696200be 100644 --- a/arch/arm/plat-s3c24xx/clock.c +++ b/arch/arm/plat-s3c24xx/clock.c | |||
@@ -37,7 +37,7 @@ | |||
37 | #include <linux/interrupt.h> | 37 | #include <linux/interrupt.h> |
38 | #include <linux/ioport.h> | 38 | #include <linux/ioport.h> |
39 | #include <linux/clk.h> | 39 | #include <linux/clk.h> |
40 | #include <linux/mutex.h> | 40 | #include <linux/spinlock.h> |
41 | #include <linux/delay.h> | 41 | #include <linux/delay.h> |
42 | #include <linux/io.h> | 42 | #include <linux/io.h> |
43 | 43 | ||
@@ -55,7 +55,11 @@ | |||
55 | 55 | ||
56 | static LIST_HEAD(clocks); | 56 | static LIST_HEAD(clocks); |
57 | 57 | ||
58 | DEFINE_MUTEX(clocks_mutex); | 58 | /* We originally used an mutex here, but some contexts (see resume) |
59 | * are calling functions such as clk_set_parent() with IRQs disabled | ||
60 | * causing an BUG to be triggered. | ||
61 | */ | ||
62 | DEFINE_SPINLOCK(clocks_lock); | ||
59 | 63 | ||
60 | /* enable and disable calls for use with the clk struct */ | 64 | /* enable and disable calls for use with the clk struct */ |
61 | 65 | ||
@@ -77,7 +81,7 @@ struct clk *clk_get(struct device *dev, const char *id) | |||
77 | else | 81 | else |
78 | idno = to_platform_device(dev)->id; | 82 | idno = to_platform_device(dev)->id; |
79 | 83 | ||
80 | mutex_lock(&clocks_mutex); | 84 | spin_lock(&clocks_lock); |
81 | 85 | ||
82 | list_for_each_entry(p, &clocks, list) { | 86 | list_for_each_entry(p, &clocks, list) { |
83 | if (p->id == idno && | 87 | if (p->id == idno && |
@@ -101,7 +105,7 @@ struct clk *clk_get(struct device *dev, const char *id) | |||
101 | } | 105 | } |
102 | } | 106 | } |
103 | 107 | ||
104 | mutex_unlock(&clocks_mutex); | 108 | spin_unlock(&clocks_lock); |
105 | return clk; | 109 | return clk; |
106 | } | 110 | } |
107 | 111 | ||
@@ -117,12 +121,12 @@ int clk_enable(struct clk *clk) | |||
117 | 121 | ||
118 | clk_enable(clk->parent); | 122 | clk_enable(clk->parent); |
119 | 123 | ||
120 | mutex_lock(&clocks_mutex); | 124 | spin_lock(&clocks_lock); |
121 | 125 | ||
122 | if ((clk->usage++) == 0) | 126 | if ((clk->usage++) == 0) |
123 | (clk->enable)(clk, 1); | 127 | (clk->enable)(clk, 1); |
124 | 128 | ||
125 | mutex_unlock(&clocks_mutex); | 129 | spin_unlock(&clocks_lock); |
126 | return 0; | 130 | return 0; |
127 | } | 131 | } |
128 | 132 | ||
@@ -131,12 +135,12 @@ void clk_disable(struct clk *clk) | |||
131 | if (IS_ERR(clk) || clk == NULL) | 135 | if (IS_ERR(clk) || clk == NULL) |
132 | return; | 136 | return; |
133 | 137 | ||
134 | mutex_lock(&clocks_mutex); | 138 | spin_lock(&clocks_lock); |
135 | 139 | ||
136 | if ((--clk->usage) == 0) | 140 | if ((--clk->usage) == 0) |
137 | (clk->enable)(clk, 0); | 141 | (clk->enable)(clk, 0); |
138 | 142 | ||
139 | mutex_unlock(&clocks_mutex); | 143 | spin_unlock(&clocks_lock); |
140 | clk_disable(clk->parent); | 144 | clk_disable(clk->parent); |
141 | } | 145 | } |
142 | 146 | ||
@@ -182,9 +186,9 @@ int clk_set_rate(struct clk *clk, unsigned long rate) | |||
182 | if (clk->set_rate == NULL) | 186 | if (clk->set_rate == NULL) |
183 | return -EINVAL; | 187 | return -EINVAL; |
184 | 188 | ||
185 | mutex_lock(&clocks_mutex); | 189 | spin_lock(&clocks_lock); |
186 | ret = (clk->set_rate)(clk, rate); | 190 | ret = (clk->set_rate)(clk, rate); |
187 | mutex_unlock(&clocks_mutex); | 191 | spin_unlock(&clocks_lock); |
188 | 192 | ||
189 | return ret; | 193 | return ret; |
190 | } | 194 | } |
@@ -201,12 +205,12 @@ int clk_set_parent(struct clk *clk, struct clk *parent) | |||
201 | if (IS_ERR(clk)) | 205 | if (IS_ERR(clk)) |
202 | return -EINVAL; | 206 | return -EINVAL; |
203 | 207 | ||
204 | mutex_lock(&clocks_mutex); | 208 | spin_lock(&clocks_lock); |
205 | 209 | ||
206 | if (clk->set_parent) | 210 | if (clk->set_parent) |
207 | ret = (clk->set_parent)(clk, parent); | 211 | ret = (clk->set_parent)(clk, parent); |
208 | 212 | ||
209 | mutex_unlock(&clocks_mutex); | 213 | spin_unlock(&clocks_lock); |
210 | 214 | ||
211 | return ret; | 215 | return ret; |
212 | } | 216 | } |
@@ -302,9 +306,9 @@ int s3c24xx_register_clock(struct clk *clk) | |||
302 | 306 | ||
303 | /* add to the list of available clocks */ | 307 | /* add to the list of available clocks */ |
304 | 308 | ||
305 | mutex_lock(&clocks_mutex); | 309 | spin_lock(&clocks_lock); |
306 | list_add(&clk->list, &clocks); | 310 | list_add(&clk->list, &clocks); |
307 | mutex_unlock(&clocks_mutex); | 311 | spin_unlock(&clocks_lock); |
308 | 312 | ||
309 | return 0; | 313 | return 0; |
310 | } | 314 | } |
diff --git a/arch/arm/plat-s3c24xx/include/plat/clock.h b/arch/arm/plat-s3c24xx/include/plat/clock.h index 235b753cd877..88a00c35b685 100644 --- a/arch/arm/plat-s3c24xx/include/plat/clock.h +++ b/arch/arm/plat-s3c24xx/include/plat/clock.h | |||
@@ -10,6 +10,8 @@ | |||
10 | * published by the Free Software Foundation. | 10 | * published by the Free Software Foundation. |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/spinlock.h> | ||
14 | |||
13 | struct clk { | 15 | struct clk { |
14 | struct list_head list; | 16 | struct list_head list; |
15 | struct module *owner; | 17 | struct module *owner; |
@@ -51,7 +53,7 @@ extern struct clk clk_xtal; | |||
51 | * Please DO NOT use these outside of arch/arm/mach-s3c2410 | 53 | * Please DO NOT use these outside of arch/arm/mach-s3c2410 |
52 | */ | 54 | */ |
53 | 55 | ||
54 | extern struct mutex clocks_mutex; | 56 | extern spinlock_t clocks_lock; |
55 | 57 | ||
56 | extern int s3c2410_clkcon_enable(struct clk *clk, int enable); | 58 | extern int s3c2410_clkcon_enable(struct clk *clk, int enable); |
57 | 59 | ||
diff --git a/arch/arm/plat-s3c24xx/s3c244x-clock.c b/arch/arm/plat-s3c24xx/s3c244x-clock.c index 7c09773ff9fc..dde41f171aff 100644 --- a/arch/arm/plat-s3c24xx/s3c244x-clock.c +++ b/arch/arm/plat-s3c24xx/s3c244x-clock.c | |||
@@ -31,7 +31,6 @@ | |||
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> | ||
35 | #include <linux/clk.h> | 34 | #include <linux/clk.h> |
36 | #include <linux/io.h> | 35 | #include <linux/io.h> |
37 | 36 | ||
@@ -102,13 +101,13 @@ static int s3c244x_clk_add(struct sys_device *sysdev) | |||
102 | if (clk_get_rate(clock_upll) > (94 * MHZ)) { | 101 | if (clk_get_rate(clock_upll) > (94 * MHZ)) { |
103 | clk_usb_bus.rate = clk_get_rate(clock_upll) / 2; | 102 | clk_usb_bus.rate = clk_get_rate(clock_upll) / 2; |
104 | 103 | ||
105 | mutex_lock(&clocks_mutex); | 104 | spin_lock(&clocks_lock); |
106 | 105 | ||
107 | clkdivn = __raw_readl(S3C2410_CLKDIVN); | 106 | clkdivn = __raw_readl(S3C2410_CLKDIVN); |
108 | clkdivn |= S3C2440_CLKDIVN_UCLK; | 107 | clkdivn |= S3C2440_CLKDIVN_UCLK; |
109 | __raw_writel(clkdivn, S3C2410_CLKDIVN); | 108 | __raw_writel(clkdivn, S3C2410_CLKDIVN); |
110 | 109 | ||
111 | mutex_unlock(&clocks_mutex); | 110 | spin_unlock(&clocks_lock); |
112 | } | 111 | } |
113 | 112 | ||
114 | return 0; | 113 | return 0; |