diff options
Diffstat (limited to 'arch/arm/mach-tegra/clock.c')
-rw-r--r-- | arch/arm/mach-tegra/clock.c | 883 |
1 files changed, 804 insertions, 79 deletions
diff --git a/arch/arm/mach-tegra/clock.c b/arch/arm/mach-tegra/clock.c index e028320ab42..f31da0bf149 100644 --- a/arch/arm/mach-tegra/clock.c +++ b/arch/arm/mach-tegra/clock.c | |||
@@ -5,6 +5,8 @@ | |||
5 | * Author: | 5 | * Author: |
6 | * Colin Cross <ccross@google.com> | 6 | * Colin Cross <ccross@google.com> |
7 | * | 7 | * |
8 | * Copyright (C) 2010-2011 NVIDIA Corporation | ||
9 | * | ||
8 | * This software is licensed under the terms of the GNU General Public | 10 | * This software is licensed under the terms of the GNU General Public |
9 | * License version 2, as published by the Free Software Foundation, and | 11 | * License version 2, as published by the Free Software Foundation, and |
10 | * may be copied, distributed, and modified under those terms. | 12 | * may be copied, distributed, and modified under those terms. |
@@ -24,34 +26,52 @@ | |||
24 | #include <linux/init.h> | 26 | #include <linux/init.h> |
25 | #include <linux/list.h> | 27 | #include <linux/list.h> |
26 | #include <linux/module.h> | 28 | #include <linux/module.h> |
27 | #include <linux/sched.h> | ||
28 | #include <linux/seq_file.h> | 29 | #include <linux/seq_file.h> |
29 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
31 | #include <linux/uaccess.h> | ||
32 | #include <trace/events/power.h> | ||
30 | 33 | ||
31 | #include <mach/clk.h> | 34 | #include <mach/clk.h> |
32 | 35 | ||
33 | #include "board.h" | 36 | #include "board.h" |
34 | #include "clock.h" | 37 | #include "clock.h" |
38 | #include "dvfs.h" | ||
39 | |||
40 | #define DISABLE_BOOT_CLOCKS 1 | ||
35 | 41 | ||
36 | /* | 42 | /* |
37 | * Locking: | 43 | * Locking: |
38 | * | 44 | * |
39 | * Each struct clk has a spinlock. | 45 | * Each struct clk has a lock. Depending on the cansleep flag, that lock |
46 | * may be a spinlock or a mutex. For most clocks, the spinlock is sufficient, | ||
47 | * and using the spinlock allows the clock to be manipulated from an interrupt | ||
48 | * or while holding a spinlock. Some clocks may need to adjust a regulator | ||
49 | * in order to maintain the required voltage for a new frequency. Those | ||
50 | * clocks set the cansleep flag, and take a mutex so that the regulator api | ||
51 | * can be used while holding the lock. | ||
40 | * | 52 | * |
41 | * To avoid AB-BA locking problems, locks must always be traversed from child | 53 | * 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 | 54 | * 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 | 55 | * 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 | 56 | * parent clock's lock. There are two exceptions to this ordering: |
45 | * the clock tree through debugfs. In this case, clk_lock_all is called, | 57 | * 1. When setting a clock as cansleep, in which case the entire list of clocks |
46 | * which attemps to iterate through the entire list of clocks and take every | 58 | * is traversed to set the children as cansleep as well. This must occur |
47 | * clock lock. If any call to spin_trylock fails, all locked clocks are | 59 | * during init, before any calls to clk_get, so no other clock locks can |
48 | * unlocked, and the process is retried. When all the locks are held, | 60 | * get taken. |
49 | * the only clock operation that can be called is clk_get_rate_all_locked. | 61 | * 2. When dumping the clock tree through debugfs. In this case, clk_lock_all |
62 | * is called, which attemps to iterate through the entire list of clocks | ||
63 | * and take every clock lock. If any call to clk_trylock fails, a locked | ||
64 | * clocks are unlocked, and the process is retried. When all the locks | ||
65 | * are held, the only clock operation that can be called is | ||
66 | * clk_get_rate_all_locked. | ||
50 | * | 67 | * |
51 | * Within a single clock, no clock operation can call another clock operation | 68 | * 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 | 69 | * on itself, except for clk_xxx_locked. Any clock operation can call any other |
53 | * clock operation can call any other clock operation on any of it's possible | 70 | * clock operation on any of it's possible parents. |
54 | * parents. | 71 | * |
72 | * clk_set_cansleep is used to mark a clock as sleeping. It is called during | ||
73 | * dvfs (Dynamic Voltage and Frequency Scaling) init on any clock that has a | ||
74 | * dvfs requirement, and propagated to all possible children of sleeping clock. | ||
55 | * | 75 | * |
56 | * An additional mutex, clock_list_lock, is used to protect the list of all | 76 | * An additional mutex, clock_list_lock, is used to protect the list of all |
57 | * clocks. | 77 | * clocks. |
@@ -59,6 +79,10 @@ | |||
59 | * The clock operations must lock internally to protect against | 79 | * The clock operations must lock internally to protect against |
60 | * read-modify-write on registers that are shared by multiple clocks | 80 | * read-modify-write on registers that are shared by multiple clocks |
61 | */ | 81 | */ |
82 | |||
83 | /* FIXME: remove and never ignore overclock */ | ||
84 | #define IGNORE_PARENT_OVERCLOCK 0 | ||
85 | |||
62 | static DEFINE_MUTEX(clock_list_lock); | 86 | static DEFINE_MUTEX(clock_list_lock); |
63 | static LIST_HEAD(clocks); | 87 | static LIST_HEAD(clocks); |
64 | 88 | ||
@@ -76,8 +100,21 @@ struct clk *tegra_get_clock_by_name(const char *name) | |||
76 | mutex_unlock(&clock_list_lock); | 100 | mutex_unlock(&clock_list_lock); |
77 | return ret; | 101 | return ret; |
78 | } | 102 | } |
103 | EXPORT_SYMBOL(tegra_get_clock_by_name); | ||
104 | |||
105 | static void clk_stats_update(struct clk *c) | ||
106 | { | ||
107 | u64 cur_jiffies = get_jiffies_64(); | ||
108 | |||
109 | if (c->refcnt) { | ||
110 | c->stats.time_on = cputime64_add(c->stats.time_on, | ||
111 | cputime64_sub(cur_jiffies, c->stats.last_update)); | ||
112 | } | ||
113 | |||
114 | c->stats.last_update = cur_jiffies; | ||
115 | } | ||
79 | 116 | ||
80 | /* Must be called with c->spinlock held */ | 117 | /* Must be called with clk_lock(c) held */ |
81 | static unsigned long clk_predict_rate_from_parent(struct clk *c, struct clk *p) | 118 | static unsigned long clk_predict_rate_from_parent(struct clk *c, struct clk *p) |
82 | { | 119 | { |
83 | u64 rate; | 120 | u64 rate; |
@@ -93,7 +130,17 @@ static unsigned long clk_predict_rate_from_parent(struct clk *c, struct clk *p) | |||
93 | return rate; | 130 | return rate; |
94 | } | 131 | } |
95 | 132 | ||
96 | /* Must be called with c->spinlock held */ | 133 | unsigned long clk_get_max_rate(struct clk *c) |
134 | { | ||
135 | return c->max_rate; | ||
136 | } | ||
137 | |||
138 | unsigned long clk_get_min_rate(struct clk *c) | ||
139 | { | ||
140 | return c->min_rate; | ||
141 | } | ||
142 | |||
143 | /* Must be called with clk_lock(c) held */ | ||
97 | unsigned long clk_get_rate_locked(struct clk *c) | 144 | unsigned long clk_get_rate_locked(struct clk *c) |
98 | { | 145 | { |
99 | unsigned long rate; | 146 | unsigned long rate; |
@@ -111,16 +158,55 @@ unsigned long clk_get_rate(struct clk *c) | |||
111 | unsigned long flags; | 158 | unsigned long flags; |
112 | unsigned long rate; | 159 | unsigned long rate; |
113 | 160 | ||
114 | spin_lock_irqsave(&c->spinlock, flags); | 161 | clk_lock_save(c, &flags); |
115 | 162 | ||
116 | rate = clk_get_rate_locked(c); | 163 | rate = clk_get_rate_locked(c); |
117 | 164 | ||
118 | spin_unlock_irqrestore(&c->spinlock, flags); | 165 | clk_unlock_restore(c, &flags); |
119 | 166 | ||
120 | return rate; | 167 | return rate; |
121 | } | 168 | } |
122 | EXPORT_SYMBOL(clk_get_rate); | 169 | EXPORT_SYMBOL(clk_get_rate); |
123 | 170 | ||
171 | static void __clk_set_cansleep(struct clk *c) | ||
172 | { | ||
173 | struct clk *child; | ||
174 | int i; | ||
175 | BUG_ON(mutex_is_locked(&c->mutex)); | ||
176 | BUG_ON(spin_is_locked(&c->spinlock)); | ||
177 | |||
178 | /* Make sure that all possible descendants of sleeping clock are | ||
179 | marked as sleeping (to eliminate "sleeping parent - non-sleeping | ||
180 | child" relationship */ | ||
181 | list_for_each_entry(child, &clocks, node) { | ||
182 | bool possible_parent = (child->parent == c); | ||
183 | |||
184 | if (!possible_parent && child->inputs) { | ||
185 | for (i = 0; child->inputs[i].input; i++) { | ||
186 | if ((child->inputs[i].input == c) && | ||
187 | tegra_clk_is_parent_allowed(child, c)) { | ||
188 | possible_parent = true; | ||
189 | break; | ||
190 | } | ||
191 | } | ||
192 | } | ||
193 | |||
194 | if (possible_parent) | ||
195 | __clk_set_cansleep(child); | ||
196 | } | ||
197 | |||
198 | c->cansleep = true; | ||
199 | } | ||
200 | |||
201 | /* Must be called before any clk_get calls */ | ||
202 | void clk_set_cansleep(struct clk *c) | ||
203 | { | ||
204 | |||
205 | mutex_lock(&clock_list_lock); | ||
206 | __clk_set_cansleep(c); | ||
207 | mutex_unlock(&clock_list_lock); | ||
208 | } | ||
209 | |||
124 | int clk_reparent(struct clk *c, struct clk *parent) | 210 | int clk_reparent(struct clk *c, struct clk *parent) |
125 | { | 211 | { |
126 | c->parent = parent; | 212 | c->parent = parent; |
@@ -129,7 +215,7 @@ int clk_reparent(struct clk *c, struct clk *parent) | |||
129 | 215 | ||
130 | void clk_init(struct clk *c) | 216 | void clk_init(struct clk *c) |
131 | { | 217 | { |
132 | spin_lock_init(&c->spinlock); | 218 | clk_lock_init(c); |
133 | 219 | ||
134 | if (c->ops && c->ops->init) | 220 | if (c->ops && c->ops->init) |
135 | c->ops->init(c); | 221 | c->ops->init(c); |
@@ -142,93 +228,189 @@ void clk_init(struct clk *c) | |||
142 | else | 228 | else |
143 | c->state = ON; | 229 | c->state = ON; |
144 | } | 230 | } |
231 | c->stats.last_update = get_jiffies_64(); | ||
145 | 232 | ||
146 | mutex_lock(&clock_list_lock); | 233 | mutex_lock(&clock_list_lock); |
147 | list_add(&c->node, &clocks); | 234 | list_add(&c->node, &clocks); |
148 | mutex_unlock(&clock_list_lock); | 235 | mutex_unlock(&clock_list_lock); |
149 | } | 236 | } |
150 | 237 | ||
151 | int clk_enable(struct clk *c) | 238 | static int clk_enable_locked(struct clk *c) |
152 | { | 239 | { |
153 | int ret = 0; | 240 | int ret = 0; |
154 | unsigned long flags; | 241 | int rate = clk_get_rate_locked(c); |
242 | bool set_rate = false; | ||
243 | |||
244 | if (rate > c->max_rate) { | ||
245 | rate = c->max_rate; | ||
246 | set_rate = true; | ||
247 | } | ||
155 | 248 | ||
156 | spin_lock_irqsave(&c->spinlock, flags); | 249 | if (clk_is_auto_dvfs(c)) { |
250 | ret = tegra_dvfs_set_rate(c, rate); | ||
251 | if (ret) | ||
252 | return ret; | ||
253 | } | ||
157 | 254 | ||
158 | if (c->refcnt == 0) { | 255 | if (c->refcnt == 0) { |
159 | if (c->parent) { | 256 | if (c->parent) { |
160 | ret = clk_enable(c->parent); | 257 | ret = clk_enable(c->parent); |
161 | if (ret) | 258 | if (ret) |
162 | goto out; | 259 | return ret; |
163 | } | 260 | } |
164 | 261 | ||
262 | if (set_rate) | ||
263 | clk_set_rate_locked(c, rate); | ||
264 | |||
165 | if (c->ops && c->ops->enable) { | 265 | if (c->ops && c->ops->enable) { |
166 | ret = c->ops->enable(c); | 266 | ret = c->ops->enable(c); |
267 | trace_clock_enable(c->name, 1, 0); | ||
167 | if (ret) { | 268 | if (ret) { |
168 | if (c->parent) | 269 | if (c->parent) |
169 | clk_disable(c->parent); | 270 | clk_disable(c->parent); |
170 | goto out; | 271 | return ret; |
171 | } | 272 | } |
172 | c->state = ON; | 273 | c->state = ON; |
173 | c->set = true; | 274 | c->set = true; |
174 | } | 275 | } |
276 | clk_stats_update(c); | ||
175 | } | 277 | } |
176 | c->refcnt++; | 278 | c->refcnt++; |
177 | out: | 279 | |
178 | spin_unlock_irqrestore(&c->spinlock, flags); | ||
179 | return ret; | 280 | return ret; |
180 | } | 281 | } |
181 | EXPORT_SYMBOL(clk_enable); | ||
182 | 282 | ||
183 | void clk_disable(struct clk *c) | 283 | |
284 | int clk_enable(struct clk *c) | ||
184 | { | 285 | { |
286 | int ret = 0; | ||
185 | unsigned long flags; | 287 | unsigned long flags; |
186 | 288 | ||
187 | spin_lock_irqsave(&c->spinlock, flags); | 289 | clk_lock_save(c, &flags); |
290 | ret = clk_enable_locked(c); | ||
291 | clk_unlock_restore(c, &flags); | ||
292 | return ret; | ||
293 | } | ||
294 | EXPORT_SYMBOL(clk_enable); | ||
188 | 295 | ||
296 | static void clk_disable_locked(struct clk *c) | ||
297 | { | ||
189 | if (c->refcnt == 0) { | 298 | if (c->refcnt == 0) { |
190 | WARN(1, "Attempting to disable clock %s with refcnt 0", c->name); | 299 | WARN(1, "Attempting to disable clock %s with refcnt 0", c->name); |
191 | spin_unlock_irqrestore(&c->spinlock, flags); | ||
192 | return; | 300 | return; |
193 | } | 301 | } |
194 | if (c->refcnt == 1) { | 302 | if (c->refcnt == 1) { |
195 | if (c->ops && c->ops->disable) | 303 | if (c->ops && c->ops->disable) { |
304 | trace_clock_disable(c->name, 0, 0); | ||
196 | c->ops->disable(c); | 305 | c->ops->disable(c); |
197 | 306 | } | |
198 | if (c->parent) | 307 | if (c->parent) |
199 | clk_disable(c->parent); | 308 | clk_disable(c->parent); |
200 | 309 | ||
201 | c->state = OFF; | 310 | c->state = OFF; |
311 | clk_stats_update(c); | ||
202 | } | 312 | } |
203 | c->refcnt--; | 313 | c->refcnt--; |
204 | 314 | ||
205 | spin_unlock_irqrestore(&c->spinlock, flags); | 315 | if (clk_is_auto_dvfs(c) && c->refcnt == 0) |
316 | tegra_dvfs_set_rate(c, 0); | ||
206 | } | 317 | } |
207 | EXPORT_SYMBOL(clk_disable); | ||
208 | 318 | ||
209 | int clk_set_parent(struct clk *c, struct clk *parent) | 319 | void clk_disable(struct clk *c) |
210 | { | 320 | { |
211 | int ret; | ||
212 | unsigned long flags; | 321 | unsigned long flags; |
322 | |||
323 | clk_lock_save(c, &flags); | ||
324 | clk_disable_locked(c); | ||
325 | clk_unlock_restore(c, &flags); | ||
326 | } | ||
327 | EXPORT_SYMBOL(clk_disable); | ||
328 | |||
329 | static int clk_rate_change_notify(struct clk *c, unsigned long rate) | ||
330 | { | ||
331 | if (!c->rate_change_nh) | ||
332 | return -ENOSYS; | ||
333 | return raw_notifier_call_chain(c->rate_change_nh, rate, NULL); | ||
334 | } | ||
335 | |||
336 | int clk_set_parent_locked(struct clk *c, struct clk *parent) | ||
337 | { | ||
338 | int ret = 0; | ||
213 | unsigned long new_rate; | 339 | unsigned long new_rate; |
214 | unsigned long old_rate; | 340 | unsigned long old_rate; |
215 | 341 | bool disable = false; | |
216 | spin_lock_irqsave(&c->spinlock, flags); | ||
217 | 342 | ||
218 | if (!c->ops || !c->ops->set_parent) { | 343 | if (!c->ops || !c->ops->set_parent) { |
219 | ret = -ENOSYS; | 344 | ret = -ENOSYS; |
220 | goto out; | 345 | goto out; |
221 | } | 346 | } |
222 | 347 | ||
348 | if (!tegra_clk_is_parent_allowed(c, parent)) { | ||
349 | ret = -EINVAL; | ||
350 | goto out; | ||
351 | } | ||
352 | |||
223 | new_rate = clk_predict_rate_from_parent(c, parent); | 353 | new_rate = clk_predict_rate_from_parent(c, parent); |
224 | old_rate = clk_get_rate_locked(c); | 354 | old_rate = clk_get_rate_locked(c); |
225 | 355 | ||
356 | if (new_rate > clk_get_max_rate(c)) { | ||
357 | |||
358 | pr_err("Failed to set parent %s for %s (violates clock limit" | ||
359 | " %lu)\n", parent->name, c->name, clk_get_max_rate(c)); | ||
360 | #if !IGNORE_PARENT_OVERCLOCK | ||
361 | ret = -EINVAL; | ||
362 | goto out; | ||
363 | #endif | ||
364 | } | ||
365 | |||
366 | /* The new clock control register setting does not take effect if | ||
367 | * clock is disabled. Later, when the clock is enabled it would run | ||
368 | * for several cycles on the old parent, which may hang h/w if the | ||
369 | * parent is already disabled. To guarantee h/w switch to the new | ||
370 | * setting enable clock while setting parent. | ||
371 | */ | ||
372 | if ((c->refcnt == 0) && (c->flags & MUX)) { | ||
373 | pr_debug("Setting parent of clock %s with refcnt 0\n", c->name); | ||
374 | ret = clk_enable_locked(c); | ||
375 | if (ret) | ||
376 | goto out; | ||
377 | disable = true; | ||
378 | } | ||
379 | |||
380 | if (clk_is_auto_dvfs(c) && c->refcnt > 0 && | ||
381 | (!c->parent || new_rate > old_rate)) { | ||
382 | ret = tegra_dvfs_set_rate(c, new_rate); | ||
383 | if (ret) | ||
384 | goto out; | ||
385 | } | ||
386 | |||
226 | ret = c->ops->set_parent(c, parent); | 387 | ret = c->ops->set_parent(c, parent); |
227 | if (ret) | 388 | if (ret) |
228 | goto out; | 389 | goto out; |
229 | 390 | ||
391 | if (clk_is_auto_dvfs(c) && c->refcnt > 0 && | ||
392 | new_rate < old_rate) | ||
393 | ret = tegra_dvfs_set_rate(c, new_rate); | ||
394 | |||
395 | if (new_rate != old_rate) | ||
396 | clk_rate_change_notify(c, new_rate); | ||
397 | |||
230 | out: | 398 | out: |
231 | spin_unlock_irqrestore(&c->spinlock, flags); | 399 | if (disable) |
400 | clk_disable_locked(c); | ||
401 | return ret; | ||
402 | } | ||
403 | |||
404 | |||
405 | int clk_set_parent(struct clk *c, struct clk *parent) | ||
406 | { | ||
407 | int ret = 0; | ||
408 | unsigned long flags; | ||
409 | |||
410 | clk_lock_save(c, &flags); | ||
411 | ret = clk_set_parent_locked(c, parent); | ||
412 | clk_unlock_restore(c, &flags); | ||
413 | |||
232 | return ret; | 414 | return ret; |
233 | } | 415 | } |
234 | EXPORT_SYMBOL(clk_set_parent); | 416 | EXPORT_SYMBOL(clk_set_parent); |
@@ -241,42 +423,84 @@ EXPORT_SYMBOL(clk_get_parent); | |||
241 | 423 | ||
242 | int clk_set_rate_locked(struct clk *c, unsigned long rate) | 424 | int clk_set_rate_locked(struct clk *c, unsigned long rate) |
243 | { | 425 | { |
426 | int ret = 0; | ||
427 | unsigned long old_rate, max_rate; | ||
244 | long new_rate; | 428 | long new_rate; |
429 | bool disable = false; | ||
245 | 430 | ||
246 | if (!c->ops || !c->ops->set_rate) | 431 | old_rate = clk_get_rate_locked(c); |
247 | return -ENOSYS; | ||
248 | 432 | ||
249 | if (rate > c->max_rate) | 433 | max_rate = clk_get_max_rate(c); |
250 | rate = c->max_rate; | 434 | if (rate > max_rate) |
435 | rate = max_rate; | ||
251 | 436 | ||
252 | if (c->ops && c->ops->round_rate) { | 437 | if (c->ops && c->ops->round_rate) { |
253 | new_rate = c->ops->round_rate(c, rate); | 438 | new_rate = c->ops->round_rate(c, rate); |
254 | 439 | ||
255 | if (new_rate < 0) | 440 | if (new_rate < 0) { |
256 | return new_rate; | 441 | ret = new_rate; |
442 | return ret; | ||
443 | } | ||
257 | 444 | ||
258 | rate = new_rate; | 445 | rate = new_rate; |
259 | } | 446 | } |
260 | 447 | ||
261 | return c->ops->set_rate(c, rate); | 448 | /* The new clock control register setting does not take effect if |
449 | * clock is disabled. Later, when the clock is enabled it would run | ||
450 | * for several cycles on the old rate, which may over-clock module | ||
451 | * at given voltage. To guarantee h/w switch to the new setting | ||
452 | * enable clock while setting rate. | ||
453 | */ | ||
454 | if ((c->refcnt == 0) && (c->flags & (DIV_U71 | DIV_U16)) && | ||
455 | clk_is_auto_dvfs(c)) { | ||
456 | pr_debug("Setting rate of clock %s with refcnt 0\n", c->name); | ||
457 | ret = clk_enable_locked(c); | ||
458 | if (ret) | ||
459 | goto out; | ||
460 | disable = true; | ||
461 | } | ||
462 | |||
463 | if (clk_is_auto_dvfs(c) && rate > old_rate && c->refcnt > 0) { | ||
464 | ret = tegra_dvfs_set_rate(c, rate); | ||
465 | if (ret) | ||
466 | goto out; | ||
467 | } | ||
468 | |||
469 | trace_clock_set_rate(c->name, rate, 0); | ||
470 | ret = c->ops->set_rate(c, rate); | ||
471 | if (ret) | ||
472 | goto out; | ||
473 | |||
474 | if (clk_is_auto_dvfs(c) && rate < old_rate && c->refcnt > 0) | ||
475 | ret = tegra_dvfs_set_rate(c, rate); | ||
476 | |||
477 | if (rate != old_rate) | ||
478 | clk_rate_change_notify(c, rate); | ||
479 | |||
480 | out: | ||
481 | if (disable) | ||
482 | clk_disable_locked(c); | ||
483 | return ret; | ||
262 | } | 484 | } |
263 | 485 | ||
264 | int clk_set_rate(struct clk *c, unsigned long rate) | 486 | int clk_set_rate(struct clk *c, unsigned long rate) |
265 | { | 487 | { |
266 | int ret; | ||
267 | unsigned long flags; | 488 | unsigned long flags; |
489 | int ret; | ||
490 | |||
491 | if (!c->ops || !c->ops->set_rate) | ||
492 | return -ENOSYS; | ||
268 | 493 | ||
269 | spin_lock_irqsave(&c->spinlock, flags); | 494 | clk_lock_save(c, &flags); |
270 | 495 | ||
271 | ret = clk_set_rate_locked(c, rate); | 496 | ret = clk_set_rate_locked(c, rate); |
272 | 497 | ||
273 | spin_unlock_irqrestore(&c->spinlock, flags); | 498 | clk_unlock_restore(c, &flags); |
274 | 499 | ||
275 | return ret; | 500 | return ret; |
276 | } | 501 | } |
277 | EXPORT_SYMBOL(clk_set_rate); | 502 | EXPORT_SYMBOL(clk_set_rate); |
278 | 503 | ||
279 | |||
280 | /* Must be called with clocks lock and all indvidual clock locks held */ | 504 | /* Must be called with clocks lock and all indvidual clock locks held */ |
281 | unsigned long clk_get_rate_all_locked(struct clk *c) | 505 | unsigned long clk_get_rate_all_locked(struct clk *c) |
282 | { | 506 | { |
@@ -303,27 +527,50 @@ unsigned long clk_get_rate_all_locked(struct clk *c) | |||
303 | 527 | ||
304 | long clk_round_rate(struct clk *c, unsigned long rate) | 528 | long clk_round_rate(struct clk *c, unsigned long rate) |
305 | { | 529 | { |
306 | unsigned long flags; | 530 | unsigned long flags, max_rate; |
307 | long ret; | 531 | long ret; |
308 | 532 | ||
309 | spin_lock_irqsave(&c->spinlock, flags); | 533 | clk_lock_save(c, &flags); |
310 | 534 | ||
311 | if (!c->ops || !c->ops->round_rate) { | 535 | if (!c->ops || !c->ops->round_rate) { |
312 | ret = -ENOSYS; | 536 | ret = -ENOSYS; |
313 | goto out; | 537 | goto out; |
314 | } | 538 | } |
315 | 539 | ||
316 | if (rate > c->max_rate) | 540 | max_rate = clk_get_max_rate(c); |
317 | rate = c->max_rate; | 541 | if (rate > max_rate) |
542 | rate = max_rate; | ||
318 | 543 | ||
319 | ret = c->ops->round_rate(c, rate); | 544 | ret = c->ops->round_rate(c, rate); |
320 | 545 | ||
321 | out: | 546 | out: |
322 | spin_unlock_irqrestore(&c->spinlock, flags); | 547 | clk_unlock_restore(c, &flags); |
323 | return ret; | 548 | return ret; |
324 | } | 549 | } |
325 | EXPORT_SYMBOL(clk_round_rate); | 550 | EXPORT_SYMBOL(clk_round_rate); |
326 | 551 | ||
552 | static int tegra_clk_clip_rate_for_parent(struct clk *c, struct clk *p) | ||
553 | { | ||
554 | unsigned long flags, max_rate, old_rate, new_rate; | ||
555 | |||
556 | clk_lock_save(c, &flags); | ||
557 | |||
558 | max_rate = clk_get_max_rate(c); | ||
559 | new_rate = clk_predict_rate_from_parent(c, p); | ||
560 | old_rate = clk_get_rate_locked(c); | ||
561 | |||
562 | clk_unlock_restore(c, &flags); | ||
563 | |||
564 | if (new_rate > max_rate) { | ||
565 | u64 rate = max_rate; | ||
566 | rate *= old_rate; | ||
567 | do_div(rate, new_rate); | ||
568 | |||
569 | return clk_set_rate(c, (unsigned long)rate); | ||
570 | } | ||
571 | return 0; | ||
572 | } | ||
573 | |||
327 | static int tegra_clk_init_one_from_table(struct tegra_clk_init_table *table) | 574 | static int tegra_clk_init_one_from_table(struct tegra_clk_init_table *table) |
328 | { | 575 | { |
329 | struct clk *c; | 576 | struct clk *c; |
@@ -348,6 +595,14 @@ static int tegra_clk_init_one_from_table(struct tegra_clk_init_table *table) | |||
348 | } | 595 | } |
349 | 596 | ||
350 | if (c->parent != p) { | 597 | if (c->parent != p) { |
598 | ret = tegra_clk_clip_rate_for_parent(c, p); | ||
599 | if (ret) { | ||
600 | pr_warning("Unable to clip rate for parent %s" | ||
601 | " of clock %s: %d\n", | ||
602 | table->parent, table->name, ret); | ||
603 | return -EINVAL; | ||
604 | } | ||
605 | |||
351 | ret = clk_set_parent(c, p); | 606 | ret = clk_set_parent(c, p); |
352 | if (ret) { | 607 | if (ret) { |
353 | pr_warning("Unable to set parent %s of clock %s: %d\n", | 608 | pr_warning("Unable to set parent %s of clock %s: %d\n", |
@@ -387,60 +642,272 @@ EXPORT_SYMBOL(tegra_clk_init_from_table); | |||
387 | 642 | ||
388 | void tegra_periph_reset_deassert(struct clk *c) | 643 | void tegra_periph_reset_deassert(struct clk *c) |
389 | { | 644 | { |
390 | tegra2_periph_reset_deassert(c); | 645 | BUG_ON(!c->ops->reset); |
646 | c->ops->reset(c, false); | ||
391 | } | 647 | } |
392 | EXPORT_SYMBOL(tegra_periph_reset_deassert); | 648 | EXPORT_SYMBOL(tegra_periph_reset_deassert); |
393 | 649 | ||
394 | void tegra_periph_reset_assert(struct clk *c) | 650 | void tegra_periph_reset_assert(struct clk *c) |
395 | { | 651 | { |
396 | tegra2_periph_reset_assert(c); | 652 | BUG_ON(!c->ops->reset); |
653 | c->ops->reset(c, true); | ||
397 | } | 654 | } |
398 | EXPORT_SYMBOL(tegra_periph_reset_assert); | 655 | EXPORT_SYMBOL(tegra_periph_reset_assert); |
399 | 656 | ||
657 | int tegra_is_clk_enabled(struct clk *c) | ||
658 | { | ||
659 | return c->refcnt; | ||
660 | } | ||
661 | EXPORT_SYMBOL(tegra_is_clk_enabled); | ||
662 | |||
663 | int tegra_clk_shared_bus_update(struct clk *c) | ||
664 | { | ||
665 | int ret = 0; | ||
666 | unsigned long flags; | ||
667 | |||
668 | clk_lock_save(c, &flags); | ||
669 | |||
670 | if (c->ops && c->ops->shared_bus_update) | ||
671 | ret = c->ops->shared_bus_update(c); | ||
672 | |||
673 | clk_unlock_restore(c, &flags); | ||
674 | return ret; | ||
675 | } | ||
676 | |||
677 | /* dvfs initialization may lower default maximum rate */ | ||
678 | void __init tegra_init_max_rate(struct clk *c, unsigned long max_rate) | ||
679 | { | ||
680 | struct clk *shared_bus_user; | ||
681 | |||
682 | if (c->max_rate <= max_rate) | ||
683 | return; | ||
684 | |||
685 | pr_warning("Lowering %s maximum rate from %lu to %lu\n", | ||
686 | c->name, c->max_rate, max_rate); | ||
687 | |||
688 | c->max_rate = max_rate; | ||
689 | list_for_each_entry(shared_bus_user, | ||
690 | &c->shared_bus_list, u.shared_bus_user.node) { | ||
691 | shared_bus_user->u.shared_bus_user.rate = max_rate; | ||
692 | shared_bus_user->max_rate = max_rate; | ||
693 | } | ||
694 | } | ||
695 | |||
400 | void __init tegra_init_clock(void) | 696 | void __init tegra_init_clock(void) |
401 | { | 697 | { |
402 | tegra2_init_clocks(); | 698 | int ret; |
699 | struct clk *cpu; | ||
700 | struct clk *twd; | ||
701 | |||
702 | tegra_soc_init_clocks(); | ||
703 | tegra_soc_init_dvfs(); | ||
704 | |||
705 | /* The twd clock is a detached child of the CPU complex clock. | ||
706 | Force an update of the twd clock after DVFS as updated the | ||
707 | CPU clock rate. */ | ||
708 | cpu = tegra_get_clock_by_name("cpu"); | ||
709 | twd = tegra_get_clock_by_name("twd"); | ||
710 | ret = clk_set_rate(twd, clk_get_rate(cpu)); | ||
711 | if (ret) | ||
712 | pr_err("Failed to set twd clock rate: %d\n", ret); | ||
713 | else | ||
714 | pr_debug("TWD clock rate: %ld\n", clk_get_rate(twd)); | ||
715 | } | ||
716 | |||
717 | #ifdef CONFIG_ARCH_TEGRA_2x_SOC | ||
718 | /* On tegra 2 SoC the SDMMC clock source register have extra bits that | ||
719 | * adjust the SDMMC controller delay between the clock and data to | ||
720 | * compenstate for delays on the PCB. */ | ||
721 | void tegra_sdmmc_tap_delay(struct clk *c, int delay) { | ||
722 | unsigned long flags; | ||
723 | |||
724 | clk_lock_save(c, &flags); | ||
725 | tegra2_sdmmc_tap_delay(c, delay); | ||
726 | |||
727 | clk_unlock_restore(c, &flags); | ||
403 | } | 728 | } |
729 | #endif | ||
730 | |||
731 | static bool tegra_keep_boot_clocks = false; | ||
732 | static int __init tegra_keep_boot_clocks_setup(char *__unused) | ||
733 | { | ||
734 | tegra_keep_boot_clocks = true; | ||
735 | return 1; | ||
736 | } | ||
737 | __setup("tegra_keep_boot_clocks", tegra_keep_boot_clocks_setup); | ||
404 | 738 | ||
405 | /* | 739 | /* |
406 | * The SDMMC controllers have extra bits in the clock source register that | 740 | * Bootloader may not match kernel restrictions on CPU clock sources. |
407 | * adjust the delay between the clock and data to compenstate for delays | 741 | * Make sure CPU clock is sourced from either main or backup parent. |
408 | * on the PCB. | ||
409 | */ | 742 | */ |
410 | void tegra_sdmmc_tap_delay(struct clk *c, int delay) | 743 | static int tegra_sync_cpu_clock(void) |
411 | { | 744 | { |
745 | int ret; | ||
746 | unsigned long rate; | ||
747 | struct clk *c = tegra_get_clock_by_name("cpu"); | ||
748 | |||
749 | BUG_ON(!c); | ||
750 | rate = clk_get_rate(c); | ||
751 | ret = clk_set_rate(c, rate); | ||
752 | if (ret) | ||
753 | pr_err("%s: Failed to sync CPU at rate %lu\n", __func__, rate); | ||
754 | else | ||
755 | pr_info("CPU rate: %lu MHz\n", clk_get_rate(c) / 1000000); | ||
756 | return ret; | ||
757 | } | ||
758 | late_initcall(tegra_sync_cpu_clock); | ||
759 | |||
760 | /* | ||
761 | * Iterate through all clocks, disabling any for which the refcount is 0 | ||
762 | * but the clock init detected the bootloader left the clock on. | ||
763 | */ | ||
764 | static int __init tegra_init_disable_boot_clocks(void) | ||
765 | { | ||
766 | #if DISABLE_BOOT_CLOCKS | ||
412 | unsigned long flags; | 767 | unsigned long flags; |
768 | struct clk *c; | ||
413 | 769 | ||
414 | spin_lock_irqsave(&c->spinlock, flags); | 770 | mutex_lock(&clock_list_lock); |
415 | tegra2_sdmmc_tap_delay(c, delay); | 771 | |
416 | spin_unlock_irqrestore(&c->spinlock, flags); | 772 | list_for_each_entry(c, &clocks, node) { |
773 | clk_lock_save(c, &flags); | ||
774 | if (c->refcnt == 0 && c->state == ON && | ||
775 | c->ops && c->ops->disable) { | ||
776 | pr_warn_once("%s clocks left on by bootloader:\n", | ||
777 | tegra_keep_boot_clocks ? | ||
778 | "Prevented disabling" : | ||
779 | "Disabling"); | ||
780 | |||
781 | pr_warn(" %s\n", c->name); | ||
782 | |||
783 | if (!tegra_keep_boot_clocks) { | ||
784 | c->ops->disable(c); | ||
785 | c->state = OFF; | ||
786 | } | ||
787 | } | ||
788 | clk_unlock_restore(c, &flags); | ||
789 | } | ||
790 | |||
791 | mutex_unlock(&clock_list_lock); | ||
792 | #endif | ||
793 | return 0; | ||
794 | } | ||
795 | late_initcall(tegra_init_disable_boot_clocks); | ||
796 | |||
797 | /* Several extended clock configuration bits (e.g., clock routing, clock | ||
798 | * phase control) are included in PLL and peripheral clock source | ||
799 | * registers. */ | ||
800 | int tegra_clk_cfg_ex(struct clk *c, enum tegra_clk_ex_param p, u32 setting) | ||
801 | { | ||
802 | int ret = 0; | ||
803 | unsigned long flags; | ||
804 | |||
805 | clk_lock_save(c, &flags); | ||
806 | |||
807 | if (!c->ops || !c->ops->clk_cfg_ex) { | ||
808 | ret = -ENOSYS; | ||
809 | goto out; | ||
810 | } | ||
811 | ret = c->ops->clk_cfg_ex(c, p, setting); | ||
812 | |||
813 | out: | ||
814 | clk_unlock_restore(c, &flags); | ||
815 | return ret; | ||
816 | } | ||
817 | |||
818 | int tegra_register_clk_rate_notifier(struct clk *c, struct notifier_block *nb) | ||
819 | { | ||
820 | int ret; | ||
821 | unsigned long flags; | ||
822 | |||
823 | if (!c->rate_change_nh) | ||
824 | return -ENOSYS; | ||
825 | |||
826 | clk_lock_save(c, &flags); | ||
827 | ret = raw_notifier_chain_register(c->rate_change_nh, nb); | ||
828 | clk_unlock_restore(c, &flags); | ||
829 | return ret; | ||
830 | } | ||
831 | |||
832 | void tegra_unregister_clk_rate_notifier( | ||
833 | struct clk *c, struct notifier_block *nb) | ||
834 | { | ||
835 | unsigned long flags; | ||
836 | |||
837 | if (!c->rate_change_nh) | ||
838 | return; | ||
839 | |||
840 | clk_lock_save(c, &flags); | ||
841 | raw_notifier_chain_unregister(c->rate_change_nh, nb); | ||
842 | clk_unlock_restore(c, &flags); | ||
417 | } | 843 | } |
418 | 844 | ||
419 | #ifdef CONFIG_DEBUG_FS | 845 | #ifdef CONFIG_DEBUG_FS |
420 | 846 | ||
847 | /* | ||
848 | * Attempt to lock all the clocks that are marked cansleep | ||
849 | * Must be called with irqs enabled | ||
850 | */ | ||
851 | static int __clk_lock_all_mutexes(void) | ||
852 | { | ||
853 | struct clk *c; | ||
854 | |||
855 | might_sleep(); | ||
856 | |||
857 | list_for_each_entry(c, &clocks, node) | ||
858 | if (clk_cansleep(c)) | ||
859 | if (!mutex_trylock(&c->mutex)) | ||
860 | goto unlock_mutexes; | ||
861 | |||
862 | return 0; | ||
863 | |||
864 | unlock_mutexes: | ||
865 | list_for_each_entry_continue_reverse(c, &clocks, node) | ||
866 | if (clk_cansleep(c)) | ||
867 | mutex_unlock(&c->mutex); | ||
868 | |||
869 | return -EAGAIN; | ||
870 | } | ||
871 | |||
872 | /* | ||
873 | * Attempt to lock all the clocks that are not marked cansleep | ||
874 | * Must be called with irqs disabled | ||
875 | */ | ||
421 | static int __clk_lock_all_spinlocks(void) | 876 | static int __clk_lock_all_spinlocks(void) |
422 | { | 877 | { |
423 | struct clk *c; | 878 | struct clk *c; |
424 | 879 | ||
425 | list_for_each_entry(c, &clocks, node) | 880 | list_for_each_entry(c, &clocks, node) |
426 | if (!spin_trylock(&c->spinlock)) | 881 | if (!clk_cansleep(c)) |
427 | goto unlock_spinlocks; | 882 | if (!spin_trylock(&c->spinlock)) |
883 | goto unlock_spinlocks; | ||
428 | 884 | ||
429 | return 0; | 885 | return 0; |
430 | 886 | ||
431 | unlock_spinlocks: | 887 | unlock_spinlocks: |
432 | list_for_each_entry_continue_reverse(c, &clocks, node) | 888 | list_for_each_entry_continue_reverse(c, &clocks, node) |
433 | spin_unlock(&c->spinlock); | 889 | if (!clk_cansleep(c)) |
890 | spin_unlock(&c->spinlock); | ||
434 | 891 | ||
435 | return -EAGAIN; | 892 | return -EAGAIN; |
436 | } | 893 | } |
437 | 894 | ||
895 | static void __clk_unlock_all_mutexes(void) | ||
896 | { | ||
897 | struct clk *c; | ||
898 | |||
899 | list_for_each_entry_reverse(c, &clocks, node) | ||
900 | if (clk_cansleep(c)) | ||
901 | mutex_unlock(&c->mutex); | ||
902 | } | ||
903 | |||
438 | static void __clk_unlock_all_spinlocks(void) | 904 | static void __clk_unlock_all_spinlocks(void) |
439 | { | 905 | { |
440 | struct clk *c; | 906 | struct clk *c; |
441 | 907 | ||
442 | list_for_each_entry_reverse(c, &clocks, node) | 908 | list_for_each_entry_reverse(c, &clocks, node) |
443 | spin_unlock(&c->spinlock); | 909 | if (!clk_cansleep(c)) |
910 | spin_unlock(&c->spinlock); | ||
444 | } | 911 | } |
445 | 912 | ||
446 | /* | 913 | /* |
@@ -453,6 +920,10 @@ static void clk_lock_all(void) | |||
453 | { | 920 | { |
454 | int ret; | 921 | int ret; |
455 | retry: | 922 | retry: |
923 | ret = __clk_lock_all_mutexes(); | ||
924 | if (ret) | ||
925 | goto failed_mutexes; | ||
926 | |||
456 | local_irq_disable(); | 927 | local_irq_disable(); |
457 | 928 | ||
458 | ret = __clk_lock_all_spinlocks(); | 929 | ret = __clk_lock_all_spinlocks(); |
@@ -464,7 +935,9 @@ retry: | |||
464 | 935 | ||
465 | failed_spinlocks: | 936 | failed_spinlocks: |
466 | local_irq_enable(); | 937 | local_irq_enable(); |
467 | yield(); | 938 | __clk_unlock_all_mutexes(); |
939 | failed_mutexes: | ||
940 | msleep(1); | ||
468 | goto retry; | 941 | goto retry; |
469 | } | 942 | } |
470 | 943 | ||
@@ -478,16 +951,28 @@ static void clk_unlock_all(void) | |||
478 | __clk_unlock_all_spinlocks(); | 951 | __clk_unlock_all_spinlocks(); |
479 | 952 | ||
480 | local_irq_enable(); | 953 | local_irq_enable(); |
954 | |||
955 | __clk_unlock_all_mutexes(); | ||
481 | } | 956 | } |
482 | 957 | ||
483 | static struct dentry *clk_debugfs_root; | 958 | static struct dentry *clk_debugfs_root; |
484 | 959 | ||
960 | static void dvfs_show_one(struct seq_file *s, struct dvfs *d, int level) | ||
961 | { | ||
962 | seq_printf(s, "%*s %-*s%21s%d mV\n", | ||
963 | level * 3 + 1, "", | ||
964 | 30 - level * 3, d->dvfs_rail->reg_id, | ||
965 | "", | ||
966 | d->cur_millivolts); | ||
967 | } | ||
485 | 968 | ||
486 | static void clock_tree_show_one(struct seq_file *s, struct clk *c, int level) | 969 | static void clock_tree_show_one(struct seq_file *s, struct clk *c, int level) |
487 | { | 970 | { |
488 | struct clk *child; | 971 | struct clk *child; |
489 | const char *state = "uninit"; | 972 | const char *state = "uninit"; |
490 | char div[8] = {0}; | 973 | char div[8] = {0}; |
974 | unsigned long rate = clk_get_rate_all_locked(c); | ||
975 | unsigned long max_rate = clk_get_max_rate(c);; | ||
491 | 976 | ||
492 | if (c->state == ON) | 977 | if (c->state == ON) |
493 | state = "on"; | 978 | state = "on"; |
@@ -511,12 +996,19 @@ static void clock_tree_show_one(struct seq_file *s, struct clk *c, int level) | |||
511 | } | 996 | } |
512 | } | 997 | } |
513 | 998 | ||
514 | seq_printf(s, "%*s%c%c%-*s %-6s %-3d %-8s %-10lu\n", | 999 | seq_printf(s, "%*s%c%c%-*s%c %-6s %-3d %-8s %-10lu", |
515 | level * 3 + 1, "", | 1000 | level * 3 + 1, "", |
516 | c->rate > c->max_rate ? '!' : ' ', | 1001 | rate > max_rate ? '!' : ' ', |
517 | !c->set ? '*' : ' ', | 1002 | !c->set ? '*' : ' ', |
518 | 30 - level * 3, c->name, | 1003 | 30 - level * 3, c->name, |
519 | state, c->refcnt, div, clk_get_rate_all_locked(c)); | 1004 | c->cansleep ? '$' : ' ', |
1005 | state, c->refcnt, div, rate); | ||
1006 | if (c->parent && !list_empty(&c->parent->shared_bus_list)) | ||
1007 | seq_printf(s, " (%lu)", c->u.shared_bus_user.rate); | ||
1008 | seq_printf(s, "\n"); | ||
1009 | |||
1010 | if (c->dvfs) | ||
1011 | dvfs_show_one(s, c->dvfs, level + 1); | ||
520 | 1012 | ||
521 | list_for_each_entry(child, &clocks, node) { | 1013 | list_for_each_entry(child, &clocks, node) { |
522 | if (child->parent != c) | 1014 | if (child->parent != c) |
@@ -529,8 +1021,8 @@ static void clock_tree_show_one(struct seq_file *s, struct clk *c, int level) | |||
529 | static int clock_tree_show(struct seq_file *s, void *data) | 1021 | static int clock_tree_show(struct seq_file *s, void *data) |
530 | { | 1022 | { |
531 | struct clk *c; | 1023 | struct clk *c; |
532 | seq_printf(s, " clock state ref div rate\n"); | 1024 | seq_printf(s, " clock state ref div rate (shared rate)\n"); |
533 | seq_printf(s, "--------------------------------------------------------------\n"); | 1025 | seq_printf(s, "------------------------------------------------------------------------------\n"); |
534 | 1026 | ||
535 | mutex_lock(&clock_list_lock); | 1027 | mutex_lock(&clock_list_lock); |
536 | 1028 | ||
@@ -558,6 +1050,61 @@ static const struct file_operations clock_tree_fops = { | |||
558 | .release = single_release, | 1050 | .release = single_release, |
559 | }; | 1051 | }; |
560 | 1052 | ||
1053 | static void syncevent_one(struct clk *c) | ||
1054 | { | ||
1055 | struct clk *child; | ||
1056 | |||
1057 | if (c->state == ON) | ||
1058 | trace_clock_enable(c->name, 1, smp_processor_id()); | ||
1059 | else | ||
1060 | trace_clock_disable(c->name, 0, smp_processor_id()); | ||
1061 | |||
1062 | trace_clock_set_rate(c->name, clk_get_rate_all_locked(c), | ||
1063 | smp_processor_id()); | ||
1064 | |||
1065 | list_for_each_entry(child, &clocks, node) { | ||
1066 | if (child->parent != c) | ||
1067 | continue; | ||
1068 | |||
1069 | syncevent_one(child); | ||
1070 | } | ||
1071 | } | ||
1072 | |||
1073 | static int syncevent_write(struct file *file, const char __user *user_buf, | ||
1074 | size_t count, loff_t *ppos) | ||
1075 | { | ||
1076 | struct clk *c; | ||
1077 | char buffer[40]; | ||
1078 | int buf_size; | ||
1079 | |||
1080 | memset(buffer, 0, sizeof(buffer)); | ||
1081 | buf_size = min(count, (sizeof(buffer)-1)); | ||
1082 | |||
1083 | if (copy_from_user(buffer, user_buf, buf_size)) | ||
1084 | return -EFAULT; | ||
1085 | |||
1086 | if (!strnicmp("all", buffer, 3)) { | ||
1087 | mutex_lock(&clock_list_lock); | ||
1088 | |||
1089 | clk_lock_all(); | ||
1090 | |||
1091 | list_for_each_entry(c, &clocks, node) { | ||
1092 | if (c->parent == NULL) | ||
1093 | syncevent_one(c); | ||
1094 | } | ||
1095 | |||
1096 | clk_unlock_all(); | ||
1097 | |||
1098 | mutex_unlock(&clock_list_lock); | ||
1099 | } | ||
1100 | |||
1101 | return count; | ||
1102 | } | ||
1103 | |||
1104 | static const struct file_operations syncevent_fops = { | ||
1105 | .write = syncevent_write, | ||
1106 | }; | ||
1107 | |||
561 | static int possible_parents_show(struct seq_file *s, void *data) | 1108 | static int possible_parents_show(struct seq_file *s, void *data) |
562 | { | 1109 | { |
563 | struct clk *c = s->private; | 1110 | struct clk *c = s->private; |
@@ -583,9 +1130,157 @@ static const struct file_operations possible_parents_fops = { | |||
583 | .release = single_release, | 1130 | .release = single_release, |
584 | }; | 1131 | }; |
585 | 1132 | ||
1133 | static int parent_show(struct seq_file *s, void *data) | ||
1134 | { | ||
1135 | struct clk *c = s->private; | ||
1136 | struct clk *p = clk_get_parent(c); | ||
1137 | |||
1138 | seq_printf(s, "%s\n", p ? p->name : "clk_root"); | ||
1139 | return 0; | ||
1140 | } | ||
1141 | |||
1142 | static int parent_open(struct inode *inode, struct file *file) | ||
1143 | { | ||
1144 | return single_open(file, parent_show, inode->i_private); | ||
1145 | } | ||
1146 | |||
1147 | static int rate_get(void *data, u64 *val) | ||
1148 | { | ||
1149 | struct clk *c = (struct clk *)data; | ||
1150 | *val = (u64)clk_get_rate(c); | ||
1151 | return 0; | ||
1152 | } | ||
1153 | |||
1154 | static int state_get(void *data, u64 *val) | ||
1155 | { | ||
1156 | struct clk *c = (struct clk *)data; | ||
1157 | *val = (u64)((c->state == ON) ? 1 : 0); | ||
1158 | return 0; | ||
1159 | } | ||
1160 | |||
1161 | #ifdef CONFIG_TEGRA_CLOCK_DEBUG_WRITE | ||
1162 | |||
1163 | static const mode_t parent_rate_mode = S_IRUGO | S_IWUSR; | ||
1164 | |||
1165 | static ssize_t parent_write(struct file *file, | ||
1166 | const char __user *userbuf, size_t count, loff_t *ppos) | ||
1167 | { | ||
1168 | struct seq_file *s = file->private_data; | ||
1169 | struct clk *c = s->private; | ||
1170 | struct clk *p = NULL; | ||
1171 | char buf[32]; | ||
1172 | |||
1173 | if (sizeof(buf) <= count) | ||
1174 | return -EINVAL; | ||
1175 | |||
1176 | if (copy_from_user(buf, userbuf, count)) | ||
1177 | return -EFAULT; | ||
1178 | |||
1179 | /* terminate buffer and trim - white spaces may be appended | ||
1180 | * at the end when invoked from shell command line */ | ||
1181 | buf[count]='\0'; | ||
1182 | strim(buf); | ||
1183 | |||
1184 | p = tegra_get_clock_by_name(buf); | ||
1185 | if (!p) | ||
1186 | return -EINVAL; | ||
1187 | |||
1188 | if (clk_set_parent(c, p)) | ||
1189 | return -EINVAL; | ||
1190 | |||
1191 | return count; | ||
1192 | } | ||
1193 | |||
1194 | static const struct file_operations parent_fops = { | ||
1195 | .open = parent_open, | ||
1196 | .read = seq_read, | ||
1197 | .write = parent_write, | ||
1198 | .llseek = seq_lseek, | ||
1199 | .release = single_release, | ||
1200 | }; | ||
1201 | |||
1202 | static int rate_set(void *data, u64 val) | ||
1203 | { | ||
1204 | struct clk *c = (struct clk *)data; | ||
1205 | return clk_set_rate(c, (unsigned long)val); | ||
1206 | } | ||
1207 | DEFINE_SIMPLE_ATTRIBUTE(rate_fops, rate_get, rate_set, "%llu\n"); | ||
1208 | |||
1209 | static int state_set(void *data, u64 val) | ||
1210 | { | ||
1211 | struct clk *c = (struct clk *)data; | ||
1212 | |||
1213 | if (val) | ||
1214 | return clk_enable(c); | ||
1215 | else { | ||
1216 | clk_disable(c); | ||
1217 | return 0; | ||
1218 | } | ||
1219 | } | ||
1220 | DEFINE_SIMPLE_ATTRIBUTE(state_fops, state_get, state_set, "%llu\n"); | ||
1221 | |||
1222 | #else | ||
1223 | |||
1224 | static const mode_t parent_rate_mode = S_IRUGO; | ||
1225 | |||
1226 | static const struct file_operations parent_fops = { | ||
1227 | .open = parent_open, | ||
1228 | .read = seq_read, | ||
1229 | .llseek = seq_lseek, | ||
1230 | .release = single_release, | ||
1231 | }; | ||
1232 | |||
1233 | DEFINE_SIMPLE_ATTRIBUTE(rate_fops, rate_get, NULL, "%llu\n"); | ||
1234 | DEFINE_SIMPLE_ATTRIBUTE(state_fops, state_get, NULL, "%llu\n"); | ||
1235 | #endif | ||
1236 | |||
1237 | static int time_on_get(void *data, u64 *val) | ||
1238 | { | ||
1239 | unsigned long flags; | ||
1240 | struct clk *c = (struct clk *)data; | ||
1241 | |||
1242 | clk_lock_save(c, &flags); | ||
1243 | clk_stats_update(c); | ||
1244 | *val = cputime64_to_clock_t(c->stats.time_on); | ||
1245 | clk_unlock_restore(c, &flags); | ||
1246 | |||
1247 | return 0; | ||
1248 | } | ||
1249 | DEFINE_SIMPLE_ATTRIBUTE(time_on_fops, time_on_get, NULL, "%llu\n"); | ||
1250 | |||
1251 | static int possible_rates_show(struct seq_file *s, void *data) | ||
1252 | { | ||
1253 | struct clk *c = s->private; | ||
1254 | long rate = 0; | ||
1255 | |||
1256 | /* shared bus clock must round up, unless top of range reached */ | ||
1257 | while (rate <= c->max_rate) { | ||
1258 | long rounded_rate = c->ops->round_rate(c, rate); | ||
1259 | if (IS_ERR_VALUE(rounded_rate) || (rounded_rate <= rate)) | ||
1260 | break; | ||
1261 | |||
1262 | rate = rounded_rate + 2000; /* 2kHz resolution */ | ||
1263 | seq_printf(s, "%ld ", rounded_rate / 1000); | ||
1264 | } | ||
1265 | seq_printf(s, "(kHz)\n"); | ||
1266 | return 0; | ||
1267 | } | ||
1268 | |||
1269 | static int possible_rates_open(struct inode *inode, struct file *file) | ||
1270 | { | ||
1271 | return single_open(file, possible_rates_show, inode->i_private); | ||
1272 | } | ||
1273 | |||
1274 | static const struct file_operations possible_rates_fops = { | ||
1275 | .open = possible_rates_open, | ||
1276 | .read = seq_read, | ||
1277 | .llseek = seq_lseek, | ||
1278 | .release = single_release, | ||
1279 | }; | ||
1280 | |||
586 | static int clk_debugfs_register_one(struct clk *c) | 1281 | static int clk_debugfs_register_one(struct clk *c) |
587 | { | 1282 | { |
588 | struct dentry *d, *child, *child_tmp; | 1283 | struct dentry *d; |
589 | 1284 | ||
590 | d = debugfs_create_dir(c->name, clk_debugfs_root); | 1285 | d = debugfs_create_dir(c->name, clk_debugfs_root); |
591 | if (!d) | 1286 | if (!d) |
@@ -596,11 +1291,31 @@ static int clk_debugfs_register_one(struct clk *c) | |||
596 | if (!d) | 1291 | if (!d) |
597 | goto err_out; | 1292 | goto err_out; |
598 | 1293 | ||
599 | d = debugfs_create_u32("rate", S_IRUGO, c->dent, (u32 *)&c->rate); | 1294 | d = debugfs_create_x32("flags", S_IRUGO, c->dent, (u32 *)&c->flags); |
600 | if (!d) | 1295 | if (!d) |
601 | goto err_out; | 1296 | goto err_out; |
602 | 1297 | ||
603 | d = debugfs_create_x32("flags", S_IRUGO, c->dent, (u32 *)&c->flags); | 1298 | d = debugfs_create_u32("max", S_IRUGO, c->dent, (u32 *)&c->max_rate); |
1299 | if (!d) | ||
1300 | goto err_out; | ||
1301 | |||
1302 | d = debugfs_create_file( | ||
1303 | "parent", parent_rate_mode, c->dent, c, &parent_fops); | ||
1304 | if (!d) | ||
1305 | goto err_out; | ||
1306 | |||
1307 | d = debugfs_create_file( | ||
1308 | "rate", parent_rate_mode, c->dent, c, &rate_fops); | ||
1309 | if (!d) | ||
1310 | goto err_out; | ||
1311 | |||
1312 | d = debugfs_create_file( | ||
1313 | "state", parent_rate_mode, c->dent, c, &state_fops); | ||
1314 | if (!d) | ||
1315 | goto err_out; | ||
1316 | |||
1317 | d = debugfs_create_file( | ||
1318 | "time_on", S_IRUGO, c->dent, c, &time_on_fops); | ||
604 | if (!d) | 1319 | if (!d) |
605 | goto err_out; | 1320 | goto err_out; |
606 | 1321 | ||
@@ -611,13 +1326,17 @@ static int clk_debugfs_register_one(struct clk *c) | |||
611 | goto err_out; | 1326 | goto err_out; |
612 | } | 1327 | } |
613 | 1328 | ||
1329 | if (c->ops && c->ops->round_rate && c->ops->shared_bus_update) { | ||
1330 | d = debugfs_create_file("possible_rates", S_IRUGO, c->dent, | ||
1331 | c, &possible_rates_fops); | ||
1332 | if (!d) | ||
1333 | goto err_out; | ||
1334 | } | ||
1335 | |||
614 | return 0; | 1336 | return 0; |
615 | 1337 | ||
616 | err_out: | 1338 | err_out: |
617 | d = c->dent; | 1339 | debugfs_remove_recursive(c->dent); |
618 | list_for_each_entry_safe(child, child_tmp, &d->d_subdirs, d_u.d_child) | ||
619 | debugfs_remove(child); | ||
620 | debugfs_remove(c->dent); | ||
621 | return -ENOMEM; | 1340 | return -ENOMEM; |
622 | } | 1341 | } |
623 | 1342 | ||
@@ -656,6 +1375,12 @@ static int __init clk_debugfs_init(void) | |||
656 | if (!d) | 1375 | if (!d) |
657 | goto err_out; | 1376 | goto err_out; |
658 | 1377 | ||
1378 | d = debugfs_create_file("syncevents", S_IRUGO|S_IWUSR, clk_debugfs_root, NULL, | ||
1379 | &syncevent_fops); | ||
1380 | |||
1381 | if (dvfs_debugfs_init(clk_debugfs_root)) | ||
1382 | goto err_out; | ||
1383 | |||
659 | list_for_each_entry(c, &clocks, node) { | 1384 | list_for_each_entry(c, &clocks, node) { |
660 | err = clk_debugfs_register(c); | 1385 | err = clk_debugfs_register(c); |
661 | if (err) | 1386 | if (err) |