aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-tegra
diff options
context:
space:
mode:
authorColin Cross <ccross@android.com>2011-02-12 19:43:05 -0500
committerColin Cross <ccross@android.com>2011-02-21 03:10:43 -0500
commit4729fd7a7dfe7847b4870801ad12222adaeb016c (patch)
tree4e91328db46cc6c5ddd91d6e75323020c4623c42 /arch/arm/mach-tegra
parentf151961173bf28047d01b410969f05e485f56d7e (diff)
ARM: tegra: clock: Convert global lock to a lock per clock
Give each clock its own lock, and remove all lock traversals from parent to child clocks to prevent AB-BA deadlocks. This brings the locking in line with the common struct clk patches and should make conversion simple. Acked-by: Olof Johansson <olof@lixom.net> Signed-off-by: Colin Cross <ccross@android.com>
Diffstat (limited to 'arch/arm/mach-tegra')
-rw-r--r--arch/arm/mach-tegra/clock.c351
-rw-r--r--arch/arm/mach-tegra/clock.h14
-rw-r--r--arch/arm/mach-tegra/include/mach/clk.h1
-rw-r--r--arch/arm/mach-tegra/tegra2_clocks.c119
4 files changed, 318 insertions, 167 deletions
diff --git a/arch/arm/mach-tegra/clock.c b/arch/arm/mach-tegra/clock.c
index 8fd96bfb0cde..aff4c5b8c378 100644
--- a/arch/arm/mach-tegra/clock.c
+++ b/arch/arm/mach-tegra/clock.c
@@ -18,83 +18,117 @@
18 18
19#include <linux/kernel.h> 19#include <linux/kernel.h>
20#include <linux/clk.h> 20#include <linux/clk.h>
21#include <linux/list.h> 21#include <linux/clkdev.h>
22#include <linux/debugfs.h>
23#include <linux/delay.h>
22#include <linux/init.h> 24#include <linux/init.h>
25#include <linux/list.h>
23#include <linux/module.h> 26#include <linux/module.h>
24#include <linux/debugfs.h> 27#include <linux/sched.h>
25#include <linux/slab.h>
26#include <linux/seq_file.h> 28#include <linux/seq_file.h>
27#include <linux/clkdev.h> 29#include <linux/slab.h>
30
31#include <mach/clk.h>
28 32
29#include "board.h" 33#include "board.h"
30#include "clock.h" 34#include "clock.h"
31 35
36/*
37 * Locking:
38 *
39 * Each struct clk has a spinlock.
40 *
41 * To avoid AB-BA locking problems, locks must always be traversed from child
42 * clock to parent clock. For example, when enabling a clock, the clock's lock
43 * is taken, and then clk_enable is called on the parent, which take's the
44 * parent clock's lock. There is one exceptions to this ordering: When dumping
45 * the clock tree through debugfs. In this case, clk_lock_all is called,
46 * which attemps to iterate through the entire list of clocks and take every
47 * clock lock. If any call to spin_trylock fails, all locked clocks are
48 * unlocked, and the process is retried. When all the locks are held,
49 * the only clock operation that can be called is clk_get_rate_all_locked.
50 *
51 * Within a single clock, no clock operation can call another clock operation
52 * on itself, except for clk_get_rate_locked and clk_set_rate_locked. Any
53 * clock operation can call any other clock operation on any of it's possible
54 * parents.
55 *
56 * An additional mutex, clock_list_lock, is used to protect the list of all
57 * clocks.
58 *
59 * The clock operations must lock internally to protect against
60 * read-modify-write on registers that are shared by multiple clocks
61 */
62static DEFINE_MUTEX(clock_list_lock);
32static LIST_HEAD(clocks); 63static LIST_HEAD(clocks);
33 64
34static DEFINE_SPINLOCK(clock_lock);
35struct clk *tegra_get_clock_by_name(const char *name) 65struct clk *tegra_get_clock_by_name(const char *name)
36{ 66{
37 struct clk *c; 67 struct clk *c;
38 struct clk *ret = NULL; 68 struct clk *ret = NULL;
39 unsigned long flags; 69 mutex_lock(&clock_list_lock);
40 spin_lock_irqsave(&clock_lock, flags);
41 list_for_each_entry(c, &clocks, node) { 70 list_for_each_entry(c, &clocks, node) {
42 if (strcmp(c->name, name) == 0) { 71 if (strcmp(c->name, name) == 0) {
43 ret = c; 72 ret = c;
44 break; 73 break;
45 } 74 }
46 } 75 }
47 spin_unlock_irqrestore(&clock_lock, flags); 76 mutex_unlock(&clock_list_lock);
48 return ret; 77 return ret;
49} 78}
50 79
51static void clk_recalculate_rate(struct clk *c) 80/* Must be called with c->spinlock held */
81static unsigned long clk_predict_rate_from_parent(struct clk *c, struct clk *p)
52{ 82{
53 u64 rate; 83 u64 rate;
54 84
55 if (!c->parent) 85 rate = clk_get_rate(p);
56 return;
57
58 rate = c->parent->rate;
59 86
60 if (c->mul != 0 && c->div != 0) { 87 if (c->mul != 0 && c->div != 0) {
61 rate = rate * c->mul; 88 rate *= c->mul;
62 do_div(rate, c->div); 89 do_div(rate, c->div);
63 } 90 }
64 91
65 if (rate > c->max_rate) 92 return rate;
66 pr_warn("clocks: Set clock %s to rate %llu, max is %lu\n",
67 c->name, rate, c->max_rate);
68
69 c->rate = rate;
70} 93}
71 94
72int clk_reparent(struct clk *c, struct clk *parent) 95/* Must be called with c->spinlock held */
96unsigned long clk_get_rate_locked(struct clk *c)
73{ 97{
74 c->parent = parent; 98 unsigned long rate;
75 list_del(&c->sibling);
76 list_add_tail(&c->sibling, &parent->children);
77 return 0;
78}
79 99
80static void propagate_rate(struct clk *c) 100 if (c->parent)
81{ 101 rate = clk_predict_rate_from_parent(c, c->parent);
82 struct clk *clkp; 102 else
103 rate = c->rate;
83 104
84 list_for_each_entry(clkp, &c->children, sibling) { 105 return rate;
85 clk_recalculate_rate(clkp);
86 propagate_rate(clkp);
87 }
88} 106}
89 107
90void clk_init(struct clk *c) 108unsigned long clk_get_rate(struct clk *c)
91{ 109{
92 unsigned long flags; 110 unsigned long flags;
111 unsigned long rate;
93 112
94 spin_lock_irqsave(&clock_lock, flags); 113 spin_lock_irqsave(&c->spinlock, flags);
95 114
96 INIT_LIST_HEAD(&c->children); 115 rate = clk_get_rate_locked(c);
97 INIT_LIST_HEAD(&c->sibling); 116
117 spin_unlock_irqrestore(&c->spinlock, flags);
118
119 return rate;
120}
121EXPORT_SYMBOL(clk_get_rate);
122
123int clk_reparent(struct clk *c, struct clk *parent)
124{
125 c->parent = parent;
126 return 0;
127}
128
129void clk_init(struct clk *c)
130{
131 spin_lock_init(&c->spinlock);
98 132
99 if (c->ops && c->ops->init) 133 if (c->ops && c->ops->init)
100 c->ops->init(c); 134 c->ops->init(c);
@@ -108,33 +142,31 @@ void clk_init(struct clk *c)
108 c->state = ON; 142 c->state = ON;
109 } 143 }
110 144
111 clk_recalculate_rate(c); 145 mutex_lock(&clock_list_lock);
112
113 list_add(&c->node, &clocks); 146 list_add(&c->node, &clocks);
114 147 mutex_unlock(&clock_list_lock);
115 if (c->parent)
116 list_add_tail(&c->sibling, &c->parent->children);
117
118 spin_unlock_irqrestore(&clock_lock, flags);
119} 148}
120 149
121int clk_enable_locked(struct clk *c) 150int clk_enable(struct clk *c)
122{ 151{
123 int ret; 152 int ret = 0;
153 unsigned long flags;
154
155 spin_lock_irqsave(&c->spinlock, flags);
124 156
125 if (c->refcnt == 0) { 157 if (c->refcnt == 0) {
126 if (c->parent) { 158 if (c->parent) {
127 ret = clk_enable_locked(c->parent); 159 ret = clk_enable(c->parent);
128 if (ret) 160 if (ret)
129 return ret; 161 goto out;
130 } 162 }
131 163
132 if (c->ops && c->ops->enable) { 164 if (c->ops && c->ops->enable) {
133 ret = c->ops->enable(c); 165 ret = c->ops->enable(c);
134 if (ret) { 166 if (ret) {
135 if (c->parent) 167 if (c->parent)
136 clk_disable_locked(c->parent); 168 clk_disable(c->parent);
137 return ret; 169 goto out;
138 } 170 }
139 c->state = ON; 171 c->state = ON;
140#ifdef CONFIG_DEBUG_FS 172#ifdef CONFIG_DEBUG_FS
@@ -143,27 +175,21 @@ int clk_enable_locked(struct clk *c)
143 } 175 }
144 } 176 }
145 c->refcnt++; 177 c->refcnt++;
146 178out:
147 return 0; 179 spin_unlock_irqrestore(&c->spinlock, flags);
180 return ret;
148} 181}
182EXPORT_SYMBOL(clk_enable);
149 183
150int clk_enable(struct clk *c) 184void clk_disable(struct clk *c)
151{ 185{
152 int ret;
153 unsigned long flags; 186 unsigned long flags;
154 187
155 spin_lock_irqsave(&clock_lock, flags); 188 spin_lock_irqsave(&c->spinlock, flags);
156 ret = clk_enable_locked(c);
157 spin_unlock_irqrestore(&clock_lock, flags);
158 189
159 return ret;
160}
161EXPORT_SYMBOL(clk_enable);
162
163void clk_disable_locked(struct clk *c)
164{
165 if (c->refcnt == 0) { 190 if (c->refcnt == 0) {
166 WARN(1, "Attempting to disable clock %s with refcnt 0", c->name); 191 WARN(1, "Attempting to disable clock %s with refcnt 0", c->name);
192 spin_unlock_irqrestore(&c->spinlock, flags);
167 return; 193 return;
168 } 194 }
169 if (c->refcnt == 1) { 195 if (c->refcnt == 1) {
@@ -171,49 +197,39 @@ void clk_disable_locked(struct clk *c)
171 c->ops->disable(c); 197 c->ops->disable(c);
172 198
173 if (c->parent) 199 if (c->parent)
174 clk_disable_locked(c->parent); 200 clk_disable(c->parent);
175 201
176 c->state = OFF; 202 c->state = OFF;
177 } 203 }
178 c->refcnt--; 204 c->refcnt--;
179}
180 205
181void clk_disable(struct clk *c) 206 spin_unlock_irqrestore(&c->spinlock, flags);
182{
183 unsigned long flags;
184
185 spin_lock_irqsave(&clock_lock, flags);
186 clk_disable_locked(c);
187 spin_unlock_irqrestore(&clock_lock, flags);
188} 207}
189EXPORT_SYMBOL(clk_disable); 208EXPORT_SYMBOL(clk_disable);
190 209
191int clk_set_parent_locked(struct clk *c, struct clk *parent) 210int clk_set_parent(struct clk *c, struct clk *parent)
192{ 211{
193 int ret; 212 int ret;
213 unsigned long flags;
214 unsigned long new_rate;
215 unsigned long old_rate;
194 216
195 if (!c->ops || !c->ops->set_parent) 217 spin_lock_irqsave(&c->spinlock, flags);
196 return -ENOSYS;
197 218
198 ret = c->ops->set_parent(c, parent); 219 if (!c->ops || !c->ops->set_parent) {
199 220 ret = -ENOSYS;
200 if (ret) 221 goto out;
201 return ret; 222 }
202
203 clk_recalculate_rate(c);
204 223
205 propagate_rate(c); 224 new_rate = clk_predict_rate_from_parent(c, parent);
225 old_rate = clk_get_rate_locked(c);
206 226
207 return 0; 227 ret = c->ops->set_parent(c, parent);
208} 228 if (ret)
229 goto out;
209 230
210int clk_set_parent(struct clk *c, struct clk *parent) 231out:
211{ 232 spin_unlock_irqrestore(&c->spinlock, flags);
212 int ret;
213 unsigned long flags;
214 spin_lock_irqsave(&clock_lock, flags);
215 ret = clk_set_parent_locked(c, parent);
216 spin_unlock_irqrestore(&clock_lock, flags);
217 return ret; 233 return ret;
218} 234}
219EXPORT_SYMBOL(clk_set_parent); 235EXPORT_SYMBOL(clk_set_parent);
@@ -226,62 +242,75 @@ EXPORT_SYMBOL(clk_get_parent);
226 242
227int clk_set_rate_locked(struct clk *c, unsigned long rate) 243int clk_set_rate_locked(struct clk *c, unsigned long rate)
228{ 244{
229 int ret;
230
231 if (rate > c->max_rate)
232 rate = c->max_rate;
233
234 if (!c->ops || !c->ops->set_rate) 245 if (!c->ops || !c->ops->set_rate)
235 return -ENOSYS; 246 return -ENOSYS;
236 247
237 ret = c->ops->set_rate(c, rate); 248 if (rate > c->max_rate)
238 249 rate = c->max_rate;
239 if (ret)
240 return ret;
241
242 clk_recalculate_rate(c);
243
244 propagate_rate(c);
245 250
246 return 0; 251 return c->ops->set_rate(c, rate);
247} 252}
248 253
249int clk_set_rate(struct clk *c, unsigned long rate) 254int clk_set_rate(struct clk *c, unsigned long rate)
250{ 255{
251 int ret = 0; 256 int ret;
252 unsigned long flags; 257 unsigned long flags;
253 258
254 spin_lock_irqsave(&clock_lock, flags); 259 spin_lock_irqsave(&c->spinlock, flags);
260
255 ret = clk_set_rate_locked(c, rate); 261 ret = clk_set_rate_locked(c, rate);
256 spin_unlock_irqrestore(&clock_lock, flags); 262
263 spin_unlock_irqrestore(&c->spinlock, flags);
257 264
258 return ret; 265 return ret;
259} 266}
260EXPORT_SYMBOL(clk_set_rate); 267EXPORT_SYMBOL(clk_set_rate);
261 268
262unsigned long clk_get_rate(struct clk *c)
263{
264 unsigned long flags;
265 unsigned long ret;
266 269
267 spin_lock_irqsave(&clock_lock, flags); 270/* Must be called with clocks lock and all indvidual clock locks held */
271unsigned long clk_get_rate_all_locked(struct clk *c)
272{
273 u64 rate;
274 int mul = 1;
275 int div = 1;
276 struct clk *p = c;
277
278 while (p) {
279 c = p;
280 if (c->mul != 0 && c->div != 0) {
281 mul *= c->mul;
282 div *= c->div;
283 }
284 p = c->parent;
285 }
268 286
269 ret = c->rate; 287 rate = c->rate;
288 rate *= mul;
289 do_div(rate, div);
270 290
271 spin_unlock_irqrestore(&clock_lock, flags); 291 return rate;
272 return ret;
273} 292}
274EXPORT_SYMBOL(clk_get_rate);
275 293
276long clk_round_rate(struct clk *c, unsigned long rate) 294long clk_round_rate(struct clk *c, unsigned long rate)
277{ 295{
278 if (!c->ops || !c->ops->round_rate) 296 unsigned long flags;
279 return -ENOSYS; 297 long ret;
298
299 spin_lock_irqsave(&c->spinlock, flags);
300
301 if (!c->ops || !c->ops->round_rate) {
302 ret = -ENOSYS;
303 goto out;
304 }
280 305
281 if (rate > c->max_rate) 306 if (rate > c->max_rate)
282 rate = c->max_rate; 307 rate = c->max_rate;
283 308
284 return c->ops->round_rate(c, rate); 309 ret = c->ops->round_rate(c, rate);
310
311out:
312 spin_unlock_irqrestore(&c->spinlock, flags);
313 return ret;
285} 314}
286EXPORT_SYMBOL(clk_round_rate); 315EXPORT_SYMBOL(clk_round_rate);
287 316
@@ -364,13 +393,75 @@ void __init tegra_init_clock(void)
364} 393}
365 394
366#ifdef CONFIG_DEBUG_FS 395#ifdef CONFIG_DEBUG_FS
396
397static int __clk_lock_all_spinlocks(void)
398{
399 struct clk *c;
400
401 list_for_each_entry(c, &clocks, node)
402 if (!spin_trylock(&c->spinlock))
403 goto unlock_spinlocks;
404
405 return 0;
406
407unlock_spinlocks:
408 list_for_each_entry_continue_reverse(c, &clocks, node)
409 spin_unlock(&c->spinlock);
410
411 return -EAGAIN;
412}
413
414static void __clk_unlock_all_spinlocks(void)
415{
416 struct clk *c;
417
418 list_for_each_entry_reverse(c, &clocks, node)
419 spin_unlock(&c->spinlock);
420}
421
422/*
423 * This function retries until it can take all locks, and may take
424 * an arbitrarily long time to complete.
425 * Must be called with irqs enabled, returns with irqs disabled
426 * Must be called with clock_list_lock held
427 */
428static void clk_lock_all(void)
429{
430 int ret;
431retry:
432 local_irq_disable();
433
434 ret = __clk_lock_all_spinlocks();
435 if (ret)
436 goto failed_spinlocks;
437
438 /* All locks taken successfully, return */
439 return;
440
441failed_spinlocks:
442 local_irq_enable();
443 yield();
444 goto retry;
445}
446
447/*
448 * Unlocks all clocks after a clk_lock_all
449 * Must be called with irqs disabled, returns with irqs enabled
450 * Must be called with clock_list_lock held
451 */
452static void clk_unlock_all(void)
453{
454 __clk_unlock_all_spinlocks();
455
456 local_irq_enable();
457}
458
367static struct dentry *clk_debugfs_root; 459static struct dentry *clk_debugfs_root;
368 460
369 461
370static void clock_tree_show_one(struct seq_file *s, struct clk *c, int level) 462static void clock_tree_show_one(struct seq_file *s, struct clk *c, int level)
371{ 463{
372 struct clk *child; 464 struct clk *child;
373 struct clk *safe;
374 const char *state = "uninit"; 465 const char *state = "uninit";
375 char div[8] = {0}; 466 char div[8] = {0};
376 467
@@ -401,8 +492,12 @@ static void clock_tree_show_one(struct seq_file *s, struct clk *c, int level)
401 c->rate > c->max_rate ? '!' : ' ', 492 c->rate > c->max_rate ? '!' : ' ',
402 !c->set ? '*' : ' ', 493 !c->set ? '*' : ' ',
403 30 - level * 3, c->name, 494 30 - level * 3, c->name,
404 state, c->refcnt, div, c->rate); 495 state, c->refcnt, div, clk_get_rate_all_locked(c));
405 list_for_each_entry_safe(child, safe, &c->children, sibling) { 496
497 list_for_each_entry(child, &clocks, node) {
498 if (child->parent != c)
499 continue;
500
406 clock_tree_show_one(s, child, level + 1); 501 clock_tree_show_one(s, child, level + 1);
407 } 502 }
408} 503}
@@ -410,14 +505,20 @@ static void clock_tree_show_one(struct seq_file *s, struct clk *c, int level)
410static int clock_tree_show(struct seq_file *s, void *data) 505static int clock_tree_show(struct seq_file *s, void *data)
411{ 506{
412 struct clk *c; 507 struct clk *c;
413 unsigned long flags;
414 seq_printf(s, " clock state ref div rate\n"); 508 seq_printf(s, " clock state ref div rate\n");
415 seq_printf(s, "--------------------------------------------------------------\n"); 509 seq_printf(s, "--------------------------------------------------------------\n");
416 spin_lock_irqsave(&clock_lock, flags); 510
511 mutex_lock(&clock_list_lock);
512
513 clk_lock_all();
514
417 list_for_each_entry(c, &clocks, node) 515 list_for_each_entry(c, &clocks, node)
418 if (c->parent == NULL) 516 if (c->parent == NULL)
419 clock_tree_show_one(s, c, 0); 517 clock_tree_show_one(s, c, 0);
420 spin_unlock_irqrestore(&clock_lock, flags); 518
519 clk_unlock_all();
520
521 mutex_unlock(&clock_list_lock);
421 return 0; 522 return 0;
422} 523}
423 524
diff --git a/arch/arm/mach-tegra/clock.h b/arch/arm/mach-tegra/clock.h
index 20f0ce69bbaf..a63dbf93d9b0 100644
--- a/arch/arm/mach-tegra/clock.h
+++ b/arch/arm/mach-tegra/clock.h
@@ -20,8 +20,9 @@
20#ifndef __MACH_TEGRA_CLOCK_H 20#ifndef __MACH_TEGRA_CLOCK_H
21#define __MACH_TEGRA_CLOCK_H 21#define __MACH_TEGRA_CLOCK_H
22 22
23#include <linux/list.h>
24#include <linux/clkdev.h> 23#include <linux/clkdev.h>
24#include <linux/list.h>
25#include <linux/spinlock.h>
25 26
26#define DIV_BUS (1 << 0) 27#define DIV_BUS (1 << 0)
27#define DIV_U71 (1 << 1) 28#define DIV_U71 (1 << 1)
@@ -75,8 +76,6 @@ enum clk_state {
75struct clk { 76struct clk {
76 /* node for master clocks list */ 77 /* node for master clocks list */
77 struct list_head node; /* node for list of all clocks */ 78 struct list_head node; /* node for list of all clocks */
78 struct list_head children; /* list of children */
79 struct list_head sibling; /* node for children */
80 struct clk_lookup lookup; 79 struct clk_lookup lookup;
81 80
82#ifdef CONFIG_DEBUG_FS 81#ifdef CONFIG_DEBUG_FS
@@ -122,8 +121,9 @@ struct clk {
122 struct clk *backup; 121 struct clk *backup;
123 } cpu; 122 } cpu;
124 } u; 123 } u;
125};
126 124
125 spinlock_t spinlock;
126};
127 127
128struct clk_duplicate { 128struct clk_duplicate {
129 const char *name; 129 const char *name;
@@ -143,11 +143,9 @@ void tegra2_periph_reset_assert(struct clk *c);
143void clk_init(struct clk *clk); 143void clk_init(struct clk *clk);
144struct clk *tegra_get_clock_by_name(const char *name); 144struct clk *tegra_get_clock_by_name(const char *name);
145unsigned long clk_measure_input_freq(void); 145unsigned long clk_measure_input_freq(void);
146void clk_disable_locked(struct clk *c);
147int clk_enable_locked(struct clk *c);
148int clk_set_parent_locked(struct clk *c, struct clk *parent);
149int clk_set_rate_locked(struct clk *c, unsigned long rate);
150int clk_reparent(struct clk *c, struct clk *parent); 146int clk_reparent(struct clk *c, struct clk *parent);
151void tegra_clk_init_from_table(struct tegra_clk_init_table *table); 147void tegra_clk_init_from_table(struct tegra_clk_init_table *table);
148unsigned long clk_get_rate_locked(struct clk *c);
149int clk_set_rate_locked(struct clk *c, unsigned long rate);
152 150
153#endif 151#endif
diff --git a/arch/arm/mach-tegra/include/mach/clk.h b/arch/arm/mach-tegra/include/mach/clk.h
index 633865298ae4..fa7f9ca1fdbd 100644
--- a/arch/arm/mach-tegra/include/mach/clk.h
+++ b/arch/arm/mach-tegra/include/mach/clk.h
@@ -25,4 +25,5 @@ struct clk;
25void tegra_periph_reset_deassert(struct clk *c); 25void tegra_periph_reset_deassert(struct clk *c);
26void tegra_periph_reset_assert(struct clk *c); 26void tegra_periph_reset_assert(struct clk *c);
27 27
28unsigned long clk_get_rate_all_locked(struct clk *c);
28#endif 29#endif
diff --git a/arch/arm/mach-tegra/tegra2_clocks.c b/arch/arm/mach-tegra/tegra2_clocks.c
index 324c4d33ad16..ea07f513e90c 100644
--- a/arch/arm/mach-tegra/tegra2_clocks.c
+++ b/arch/arm/mach-tegra/tegra2_clocks.c
@@ -23,8 +23,8 @@
23#include <linux/spinlock.h> 23#include <linux/spinlock.h>
24#include <linux/delay.h> 24#include <linux/delay.h>
25#include <linux/io.h> 25#include <linux/io.h>
26#include <linux/hrtimer.h>
27#include <linux/clkdev.h> 26#include <linux/clkdev.h>
27#include <linux/clk.h>
28 28
29#include <mach/iomap.h> 29#include <mach/iomap.h>
30#include <mach/suspend.h> 30#include <mach/suspend.h>
@@ -147,6 +147,13 @@
147static void __iomem *reg_clk_base = IO_ADDRESS(TEGRA_CLK_RESET_BASE); 147static void __iomem *reg_clk_base = IO_ADDRESS(TEGRA_CLK_RESET_BASE);
148static void __iomem *reg_pmc_base = IO_ADDRESS(TEGRA_PMC_BASE); 148static void __iomem *reg_pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
149 149
150/*
151 * Some clocks share a register with other clocks. Any clock op that
152 * non-atomically modifies a register used by another clock must lock
153 * clock_register_lock first.
154 */
155static DEFINE_SPINLOCK(clock_register_lock);
156
150#define clk_writel(value, reg) \ 157#define clk_writel(value, reg) \
151 __raw_writel(value, (u32)reg_clk_base + (reg)) 158 __raw_writel(value, (u32)reg_clk_base + (reg))
152#define clk_readl(reg) \ 159#define clk_readl(reg) \
@@ -330,12 +337,12 @@ static int tegra2_super_clk_set_parent(struct clk *c, struct clk *p)
330 val |= sel->value << shift; 337 val |= sel->value << shift;
331 338
332 if (c->refcnt) 339 if (c->refcnt)
333 clk_enable_locked(p); 340 clk_enable(p);
334 341
335 clk_writel(val, c->reg); 342 clk_writel(val, c->reg);
336 343
337 if (c->refcnt && c->parent) 344 if (c->refcnt && c->parent)
338 clk_disable_locked(c->parent); 345 clk_disable(c->parent);
339 346
340 clk_reparent(c, p); 347 clk_reparent(c, p);
341 return 0; 348 return 0;
@@ -378,22 +385,22 @@ static void tegra2_cpu_clk_disable(struct clk *c)
378static int tegra2_cpu_clk_set_rate(struct clk *c, unsigned long rate) 385static int tegra2_cpu_clk_set_rate(struct clk *c, unsigned long rate)
379{ 386{
380 int ret; 387 int ret;
381 ret = clk_set_parent_locked(c->parent, c->u.cpu.backup); 388 ret = clk_set_parent(c->parent, c->u.cpu.backup);
382 if (ret) { 389 if (ret) {
383 pr_err("Failed to switch cpu to clock %s\n", c->u.cpu.backup->name); 390 pr_err("Failed to switch cpu to clock %s\n", c->u.cpu.backup->name);
384 return ret; 391 return ret;
385 } 392 }
386 393
387 if (rate == c->u.cpu.backup->rate) 394 if (rate == clk_get_rate(c->u.cpu.backup))
388 goto out; 395 goto out;
389 396
390 ret = clk_set_rate_locked(c->u.cpu.main, rate); 397 ret = clk_set_rate(c->u.cpu.main, rate);
391 if (ret) { 398 if (ret) {
392 pr_err("Failed to change cpu pll to %lu\n", rate); 399 pr_err("Failed to change cpu pll to %lu\n", rate);
393 return ret; 400 return ret;
394 } 401 }
395 402
396 ret = clk_set_parent_locked(c->parent, c->u.cpu.main); 403 ret = clk_set_parent(c->parent, c->u.cpu.main);
397 if (ret) { 404 if (ret) {
398 pr_err("Failed to switch cpu to clock %s\n", c->u.cpu.main->name); 405 pr_err("Failed to switch cpu to clock %s\n", c->u.cpu.main->name);
399 return ret; 406 return ret;
@@ -421,24 +428,45 @@ static void tegra2_bus_clk_init(struct clk *c)
421 428
422static int tegra2_bus_clk_enable(struct clk *c) 429static int tegra2_bus_clk_enable(struct clk *c)
423{ 430{
424 u32 val = clk_readl(c->reg); 431 u32 val;
432 unsigned long flags;
433
434 spin_lock_irqsave(&clock_register_lock, flags);
435
436 val = clk_readl(c->reg);
425 val &= ~(BUS_CLK_DISABLE << c->reg_shift); 437 val &= ~(BUS_CLK_DISABLE << c->reg_shift);
426 clk_writel(val, c->reg); 438 clk_writel(val, c->reg);
439
440 spin_unlock_irqrestore(&clock_register_lock, flags);
441
427 return 0; 442 return 0;
428} 443}
429 444
430static void tegra2_bus_clk_disable(struct clk *c) 445static void tegra2_bus_clk_disable(struct clk *c)
431{ 446{
432 u32 val = clk_readl(c->reg); 447 u32 val;
448 unsigned long flags;
449
450 spin_lock_irqsave(&clock_register_lock, flags);
451
452 val = clk_readl(c->reg);
433 val |= BUS_CLK_DISABLE << c->reg_shift; 453 val |= BUS_CLK_DISABLE << c->reg_shift;
434 clk_writel(val, c->reg); 454 clk_writel(val, c->reg);
455
456 spin_unlock_irqrestore(&clock_register_lock, flags);
435} 457}
436 458
437static int tegra2_bus_clk_set_rate(struct clk *c, unsigned long rate) 459static int tegra2_bus_clk_set_rate(struct clk *c, unsigned long rate)
438{ 460{
439 u32 val = clk_readl(c->reg); 461 u32 val;
440 unsigned long parent_rate = c->parent->rate; 462 unsigned long parent_rate = clk_get_rate(c->parent);
463 unsigned long flags;
464 int ret = -EINVAL;
441 int i; 465 int i;
466
467 spin_lock_irqsave(&clock_register_lock, flags);
468
469 val = clk_readl(c->reg);
442 for (i = 1; i <= 4; i++) { 470 for (i = 1; i <= 4; i++) {
443 if (rate == parent_rate / i) { 471 if (rate == parent_rate / i) {
444 val &= ~(BUS_CLK_DIV_MASK << c->reg_shift); 472 val &= ~(BUS_CLK_DIV_MASK << c->reg_shift);
@@ -446,10 +474,14 @@ static int tegra2_bus_clk_set_rate(struct clk *c, unsigned long rate)
446 clk_writel(val, c->reg); 474 clk_writel(val, c->reg);
447 c->div = i; 475 c->div = i;
448 c->mul = 1; 476 c->mul = 1;
449 return 0; 477 ret = 0;
478 break;
450 } 479 }
451 } 480 }
452 return -EINVAL; 481
482 spin_unlock_irqrestore(&clock_register_lock, flags);
483
484 return ret;
453} 485}
454 486
455static struct clk_ops tegra_bus_ops = { 487static struct clk_ops tegra_bus_ops = {
@@ -511,14 +543,15 @@ static void tegra2_blink_clk_disable(struct clk *c)
511 543
512static int tegra2_blink_clk_set_rate(struct clk *c, unsigned long rate) 544static int tegra2_blink_clk_set_rate(struct clk *c, unsigned long rate)
513{ 545{
514 if (rate >= c->parent->rate) { 546 unsigned long parent_rate = clk_get_rate(c->parent);
547 if (rate >= parent_rate) {
515 c->div = 1; 548 c->div = 1;
516 pmc_writel(0, c->reg); 549 pmc_writel(0, c->reg);
517 } else { 550 } else {
518 unsigned int on_off; 551 unsigned int on_off;
519 u32 val; 552 u32 val;
520 553
521 on_off = DIV_ROUND_UP(c->parent->rate / 8, rate); 554 on_off = DIV_ROUND_UP(parent_rate / 8, rate);
522 c->div = on_off * 8; 555 c->div = on_off * 8;
523 556
524 val = (on_off & PMC_BLINK_TIMER_DATA_ON_MASK) << 557 val = (on_off & PMC_BLINK_TIMER_DATA_ON_MASK) <<
@@ -604,7 +637,7 @@ static int tegra2_pll_clk_set_rate(struct clk *c, unsigned long rate)
604 637
605 pr_debug("%s: %s %lu\n", __func__, c->name, rate); 638 pr_debug("%s: %s %lu\n", __func__, c->name, rate);
606 639
607 input_rate = c->parent->rate; 640 input_rate = clk_get_rate(c->parent);
608 for (sel = c->u.pll.freq_table; sel->input_rate != 0; sel++) { 641 for (sel = c->u.pll.freq_table; sel->input_rate != 0; sel++) {
609 if (sel->input_rate == input_rate && sel->output_rate == rate) { 642 if (sel->input_rate == input_rate && sel->output_rate == rate) {
610 c->mul = sel->n; 643 c->mul = sel->n;
@@ -717,9 +750,11 @@ static int tegra2_pll_div_clk_enable(struct clk *c)
717{ 750{
718 u32 val; 751 u32 val;
719 u32 new_val; 752 u32 new_val;
753 unsigned long flags;
720 754
721 pr_debug("%s: %s\n", __func__, c->name); 755 pr_debug("%s: %s\n", __func__, c->name);
722 if (c->flags & DIV_U71) { 756 if (c->flags & DIV_U71) {
757 spin_lock_irqsave(&clock_register_lock, flags);
723 val = clk_readl(c->reg); 758 val = clk_readl(c->reg);
724 new_val = val >> c->reg_shift; 759 new_val = val >> c->reg_shift;
725 new_val &= 0xFFFF; 760 new_val &= 0xFFFF;
@@ -729,12 +764,15 @@ static int tegra2_pll_div_clk_enable(struct clk *c)
729 val &= ~(0xFFFF << c->reg_shift); 764 val &= ~(0xFFFF << c->reg_shift);
730 val |= new_val << c->reg_shift; 765 val |= new_val << c->reg_shift;
731 clk_writel(val, c->reg); 766 clk_writel(val, c->reg);
767 spin_unlock_irqrestore(&clock_register_lock, flags);
732 return 0; 768 return 0;
733 } else if (c->flags & DIV_2) { 769 } else if (c->flags & DIV_2) {
734 BUG_ON(!(c->flags & PLLD)); 770 BUG_ON(!(c->flags & PLLD));
771 spin_lock_irqsave(&clock_register_lock, flags);
735 val = clk_readl(c->reg); 772 val = clk_readl(c->reg);
736 val &= ~PLLD_MISC_DIV_RST; 773 val &= ~PLLD_MISC_DIV_RST;
737 clk_writel(val, c->reg); 774 clk_writel(val, c->reg);
775 spin_unlock_irqrestore(&clock_register_lock, flags);
738 return 0; 776 return 0;
739 } 777 }
740 return -EINVAL; 778 return -EINVAL;
@@ -744,9 +782,11 @@ static void tegra2_pll_div_clk_disable(struct clk *c)
744{ 782{
745 u32 val; 783 u32 val;
746 u32 new_val; 784 u32 new_val;
785 unsigned long flags;
747 786
748 pr_debug("%s: %s\n", __func__, c->name); 787 pr_debug("%s: %s\n", __func__, c->name);
749 if (c->flags & DIV_U71) { 788 if (c->flags & DIV_U71) {
789 spin_lock_irqsave(&clock_register_lock, flags);
750 val = clk_readl(c->reg); 790 val = clk_readl(c->reg);
751 new_val = val >> c->reg_shift; 791 new_val = val >> c->reg_shift;
752 new_val &= 0xFFFF; 792 new_val &= 0xFFFF;
@@ -756,11 +796,14 @@ static void tegra2_pll_div_clk_disable(struct clk *c)
756 val &= ~(0xFFFF << c->reg_shift); 796 val &= ~(0xFFFF << c->reg_shift);
757 val |= new_val << c->reg_shift; 797 val |= new_val << c->reg_shift;
758 clk_writel(val, c->reg); 798 clk_writel(val, c->reg);
799 spin_unlock_irqrestore(&clock_register_lock, flags);
759 } else if (c->flags & DIV_2) { 800 } else if (c->flags & DIV_2) {
760 BUG_ON(!(c->flags & PLLD)); 801 BUG_ON(!(c->flags & PLLD));
802 spin_lock_irqsave(&clock_register_lock, flags);
761 val = clk_readl(c->reg); 803 val = clk_readl(c->reg);
762 val |= PLLD_MISC_DIV_RST; 804 val |= PLLD_MISC_DIV_RST;
763 clk_writel(val, c->reg); 805 clk_writel(val, c->reg);
806 spin_unlock_irqrestore(&clock_register_lock, flags);
764 } 807 }
765} 808}
766 809
@@ -769,10 +812,14 @@ static int tegra2_pll_div_clk_set_rate(struct clk *c, unsigned long rate)
769 u32 val; 812 u32 val;
770 u32 new_val; 813 u32 new_val;
771 int divider_u71; 814 int divider_u71;
815 unsigned long parent_rate = clk_get_rate(c->parent);
816 unsigned long flags;
817
772 pr_debug("%s: %s %lu\n", __func__, c->name, rate); 818 pr_debug("%s: %s %lu\n", __func__, c->name, rate);
773 if (c->flags & DIV_U71) { 819 if (c->flags & DIV_U71) {
774 divider_u71 = clk_div71_get_divider(c->parent->rate, rate); 820 divider_u71 = clk_div71_get_divider(parent_rate, rate);
775 if (divider_u71 >= 0) { 821 if (divider_u71 >= 0) {
822 spin_lock_irqsave(&clock_register_lock, flags);
776 val = clk_readl(c->reg); 823 val = clk_readl(c->reg);
777 new_val = val >> c->reg_shift; 824 new_val = val >> c->reg_shift;
778 new_val &= 0xFFFF; 825 new_val &= 0xFFFF;
@@ -786,10 +833,11 @@ static int tegra2_pll_div_clk_set_rate(struct clk *c, unsigned long rate)
786 clk_writel(val, c->reg); 833 clk_writel(val, c->reg);
787 c->div = divider_u71 + 2; 834 c->div = divider_u71 + 2;
788 c->mul = 2; 835 c->mul = 2;
836 spin_unlock_irqrestore(&clock_register_lock, flags);
789 return 0; 837 return 0;
790 } 838 }
791 } else if (c->flags & DIV_2) { 839 } else if (c->flags & DIV_2) {
792 if (c->parent->rate == rate * 2) 840 if (parent_rate == rate * 2)
793 return 0; 841 return 0;
794 } 842 }
795 return -EINVAL; 843 return -EINVAL;
@@ -798,15 +846,16 @@ static int tegra2_pll_div_clk_set_rate(struct clk *c, unsigned long rate)
798static long tegra2_pll_div_clk_round_rate(struct clk *c, unsigned long rate) 846static long tegra2_pll_div_clk_round_rate(struct clk *c, unsigned long rate)
799{ 847{
800 int divider; 848 int divider;
849 unsigned long parent_rate = clk_get_rate(c->parent);
801 pr_debug("%s: %s %lu\n", __func__, c->name, rate); 850 pr_debug("%s: %s %lu\n", __func__, c->name, rate);
802 851
803 if (c->flags & DIV_U71) { 852 if (c->flags & DIV_U71) {
804 divider = clk_div71_get_divider(c->parent->rate, rate); 853 divider = clk_div71_get_divider(parent_rate, rate);
805 if (divider < 0) 854 if (divider < 0)
806 return divider; 855 return divider;
807 return c->parent->rate * 2 / (divider + 2); 856 return parent_rate * 2 / (divider + 2);
808 } else if (c->flags & DIV_2) { 857 } else if (c->flags & DIV_2) {
809 return c->parent->rate / 2; 858 return parent_rate / 2;
810 } 859 }
811 return -EINVAL; 860 return -EINVAL;
812} 861}
@@ -912,12 +961,12 @@ static int tegra2_periph_clk_set_parent(struct clk *c, struct clk *p)
912 val |= (sel->value) << PERIPH_CLK_SOURCE_SHIFT; 961 val |= (sel->value) << PERIPH_CLK_SOURCE_SHIFT;
913 962
914 if (c->refcnt) 963 if (c->refcnt)
915 clk_enable_locked(p); 964 clk_enable(p);
916 965
917 clk_writel(val, c->reg); 966 clk_writel(val, c->reg);
918 967
919 if (c->refcnt && c->parent) 968 if (c->refcnt && c->parent)
920 clk_disable_locked(c->parent); 969 clk_disable(c->parent);
921 970
922 clk_reparent(c, p); 971 clk_reparent(c, p);
923 return 0; 972 return 0;
@@ -931,9 +980,10 @@ static int tegra2_periph_clk_set_rate(struct clk *c, unsigned long rate)
931{ 980{
932 u32 val; 981 u32 val;
933 int divider; 982 int divider;
934 pr_debug("%s: %lu\n", __func__, rate); 983 unsigned long parent_rate = clk_get_rate(c->parent);
984
935 if (c->flags & DIV_U71) { 985 if (c->flags & DIV_U71) {
936 divider = clk_div71_get_divider(c->parent->rate, rate); 986 divider = clk_div71_get_divider(parent_rate, rate);
937 if (divider >= 0) { 987 if (divider >= 0) {
938 val = clk_readl(c->reg); 988 val = clk_readl(c->reg);
939 val &= ~PERIPH_CLK_SOURCE_DIVU71_MASK; 989 val &= ~PERIPH_CLK_SOURCE_DIVU71_MASK;
@@ -944,7 +994,7 @@ static int tegra2_periph_clk_set_rate(struct clk *c, unsigned long rate)
944 return 0; 994 return 0;
945 } 995 }
946 } else if (c->flags & DIV_U16) { 996 } else if (c->flags & DIV_U16) {
947 divider = clk_div16_get_divider(c->parent->rate, rate); 997 divider = clk_div16_get_divider(parent_rate, rate);
948 if (divider >= 0) { 998 if (divider >= 0) {
949 val = clk_readl(c->reg); 999 val = clk_readl(c->reg);
950 val &= ~PERIPH_CLK_SOURCE_DIVU16_MASK; 1000 val &= ~PERIPH_CLK_SOURCE_DIVU16_MASK;
@@ -954,7 +1004,7 @@ static int tegra2_periph_clk_set_rate(struct clk *c, unsigned long rate)
954 c->mul = 1; 1004 c->mul = 1;
955 return 0; 1005 return 0;
956 } 1006 }
957 } else if (c->parent->rate <= rate) { 1007 } else if (parent_rate <= rate) {
958 c->div = 1; 1008 c->div = 1;
959 c->mul = 1; 1009 c->mul = 1;
960 return 0; 1010 return 0;
@@ -966,19 +1016,20 @@ static long tegra2_periph_clk_round_rate(struct clk *c,
966 unsigned long rate) 1016 unsigned long rate)
967{ 1017{
968 int divider; 1018 int divider;
1019 unsigned long parent_rate = clk_get_rate(c->parent);
969 pr_debug("%s: %s %lu\n", __func__, c->name, rate); 1020 pr_debug("%s: %s %lu\n", __func__, c->name, rate);
970 1021
971 if (c->flags & DIV_U71) { 1022 if (c->flags & DIV_U71) {
972 divider = clk_div71_get_divider(c->parent->rate, rate); 1023 divider = clk_div71_get_divider(parent_rate, rate);
973 if (divider < 0) 1024 if (divider < 0)
974 return divider; 1025 return divider;
975 1026
976 return c->parent->rate * 2 / (divider + 2); 1027 return parent_rate * 2 / (divider + 2);
977 } else if (c->flags & DIV_U16) { 1028 } else if (c->flags & DIV_U16) {
978 divider = clk_div16_get_divider(c->parent->rate, rate); 1029 divider = clk_div16_get_divider(parent_rate, rate);
979 if (divider < 0) 1030 if (divider < 0)
980 return divider; 1031 return divider;
981 return c->parent->rate / (divider + 1); 1032 return parent_rate / (divider + 1);
982 } 1033 }
983 return -EINVAL; 1034 return -EINVAL;
984} 1035}
@@ -1006,7 +1057,7 @@ static void tegra2_clk_double_init(struct clk *c)
1006 1057
1007static int tegra2_clk_double_set_rate(struct clk *c, unsigned long rate) 1058static int tegra2_clk_double_set_rate(struct clk *c, unsigned long rate)
1008{ 1059{
1009 if (rate != 2 * c->parent->rate) 1060 if (rate != 2 * clk_get_rate(c->parent))
1010 return -EINVAL; 1061 return -EINVAL;
1011 c->mul = 2; 1062 c->mul = 2;
1012 c->div = 1; 1063 c->div = 1;
@@ -1057,12 +1108,12 @@ static int tegra2_audio_sync_clk_set_parent(struct clk *c, struct clk *p)
1057 val |= sel->value; 1108 val |= sel->value;
1058 1109
1059 if (c->refcnt) 1110 if (c->refcnt)
1060 clk_enable_locked(p); 1111 clk_enable(p);
1061 1112
1062 clk_writel(val, c->reg); 1113 clk_writel(val, c->reg);
1063 1114
1064 if (c->refcnt && c->parent) 1115 if (c->refcnt && c->parent)
1065 clk_disable_locked(c->parent); 1116 clk_disable(c->parent);
1066 1117
1067 clk_reparent(c, p); 1118 clk_reparent(c, p);
1068 return 0; 1119 return 0;