aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
authorBen Dooks <ben-linux@fluff.org>2008-10-21 09:06:37 -0400
committerBen Dooks <ben-linux@fluff.org>2008-12-15 16:46:07 -0500
commitc3391e36d697c997b6afeb045071e0be95219a3e (patch)
tree8bd9c12dd364519347473277496da3f3f1a54c9c /arch/arm
parent305554768011707f33f437b96f999f812ba2a7e4 (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')
-rw-r--r--arch/arm/plat-s3c24xx/clock.c32
-rw-r--r--arch/arm/plat-s3c24xx/include/plat/clock.h4
-rw-r--r--arch/arm/plat-s3c24xx/s3c244x-clock.c5
3 files changed, 23 insertions, 18 deletions
diff --git a/arch/arm/plat-s3c24xx/clock.c b/arch/arm/plat-s3c24xx/clock.c
index 1ff1b983604..334e696200b 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
56static LIST_HEAD(clocks); 56static LIST_HEAD(clocks);
57 57
58DEFINE_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 */
62DEFINE_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 235b753cd87..88a00c35b68 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
13struct clk { 15struct 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
54extern struct mutex clocks_mutex; 56extern spinlock_t clocks_lock;
55 57
56extern int s3c2410_clkcon_enable(struct clk *clk, int enable); 58extern 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 7c09773ff9f..dde41f171af 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;