1
2
3
4
5
6
7
8
9
10
11
12
13#include <linux/kernel.h>
14#include <linux/init.h>
15#include <linux/module.h>
16#include <linux/list.h>
17#include <linux/errno.h>
18#include <linux/err.h>
19#include <linux/string.h>
20#include <linux/clk.h>
21#include <linux/mutex.h>
22#include <linux/platform_device.h>
23#include <linux/cpufreq.h>
24#include <linux/debugfs.h>
25#include <linux/io.h>
26
27#include <mach/clock.h>
28
29static LIST_HEAD(clocks);
30static DEFINE_MUTEX(clocks_mutex);
31static DEFINE_SPINLOCK(clockfw_lock);
32
33static struct clk_functions *arch_clock;
34
35
36
37
38
39int clk_enable(struct clk *clk)
40{
41 unsigned long flags;
42 int ret = 0;
43
44 if (clk == NULL || IS_ERR(clk))
45 return -EINVAL;
46
47 spin_lock_irqsave(&clockfw_lock, flags);
48 if (arch_clock->clk_enable)
49 ret = arch_clock->clk_enable(clk);
50 spin_unlock_irqrestore(&clockfw_lock, flags);
51
52 return ret;
53}
54EXPORT_SYMBOL(clk_enable);
55
56void clk_disable(struct clk *clk)
57{
58 unsigned long flags;
59
60 if (clk == NULL || IS_ERR(clk))
61 return;
62
63 spin_lock_irqsave(&clockfw_lock, flags);
64 if (clk->usecount == 0) {
65 printk(KERN_ERR "Trying disable clock %s with 0 usecount\n",
66 clk->name);
67 WARN_ON(1);
68 goto out;
69 }
70
71 if (arch_clock->clk_disable)
72 arch_clock->clk_disable(clk);
73
74out:
75 spin_unlock_irqrestore(&clockfw_lock, flags);
76}
77EXPORT_SYMBOL(clk_disable);
78
79unsigned long clk_get_rate(struct clk *clk)
80{
81 unsigned long flags;
82 unsigned long ret = 0;
83
84 if (clk == NULL || IS_ERR(clk))
85 return 0;
86
87 spin_lock_irqsave(&clockfw_lock, flags);
88 ret = clk->rate;
89 spin_unlock_irqrestore(&clockfw_lock, flags);
90
91 return ret;
92}
93EXPORT_SYMBOL(clk_get_rate);
94
95
96
97
98
99long clk_round_rate(struct clk *clk, unsigned long rate)
100{
101 unsigned long flags;
102 long ret = 0;
103
104 if (clk == NULL || IS_ERR(clk))
105 return ret;
106
107 spin_lock_irqsave(&clockfw_lock, flags);
108 if (arch_clock->clk_round_rate)
109 ret = arch_clock->clk_round_rate(clk, rate);
110 spin_unlock_irqrestore(&clockfw_lock, flags);
111
112 return ret;
113}
114EXPORT_SYMBOL(clk_round_rate);
115
116int clk_set_rate(struct clk *clk, unsigned long rate)
117{
118 unsigned long flags;
119 int ret = -EINVAL;
120
121 if (clk == NULL || IS_ERR(clk))
122 return ret;
123
124 spin_lock_irqsave(&clockfw_lock, flags);
125 if (arch_clock->clk_set_rate)
126 ret = arch_clock->clk_set_rate(clk, rate);
127 if (ret == 0) {
128 if (clk->recalc)
129 clk->rate = clk->recalc(clk);
130 propagate_rate(clk);
131 }
132 spin_unlock_irqrestore(&clockfw_lock, flags);
133
134 return ret;
135}
136EXPORT_SYMBOL(clk_set_rate);
137
138int clk_set_parent(struct clk *clk, struct clk *parent)
139{
140 unsigned long flags;
141 int ret = -EINVAL;
142
143 if (clk == NULL || IS_ERR(clk) || parent == NULL || IS_ERR(parent))
144 return ret;
145
146 spin_lock_irqsave(&clockfw_lock, flags);
147 if (clk->usecount == 0) {
148 if (arch_clock->clk_set_parent)
149 ret = arch_clock->clk_set_parent(clk, parent);
150 if (ret == 0) {
151 if (clk->recalc)
152 clk->rate = clk->recalc(clk);
153 propagate_rate(clk);
154 }
155 } else
156 ret = -EBUSY;
157 spin_unlock_irqrestore(&clockfw_lock, flags);
158
159 return ret;
160}
161EXPORT_SYMBOL(clk_set_parent);
162
163struct clk *clk_get_parent(struct clk *clk)
164{
165 return clk->parent;
166}
167EXPORT_SYMBOL(clk_get_parent);
168
169
170
171
172
173unsigned int __initdata mpurate;
174
175
176
177
178
179static int __init omap_clk_setup(char *str)
180{
181 get_option(&str, &mpurate);
182
183 if (!mpurate)
184 return 1;
185
186 if (mpurate < 1000)
187 mpurate *= 1000000;
188
189 return 1;
190}
191__setup("mpurate=", omap_clk_setup);
192
193
194unsigned long followparent_recalc(struct clk *clk)
195{
196 return clk->parent->rate;
197}
198
199void clk_reparent(struct clk *child, struct clk *parent)
200{
201 list_del_init(&child->sibling);
202 if (parent)
203 list_add(&child->sibling, &parent->children);
204 child->parent = parent;
205
206
207
208}
209
210
211void propagate_rate(struct clk * tclk)
212{
213 struct clk *clkp;
214
215 list_for_each_entry(clkp, &tclk->children, sibling) {
216 if (clkp->recalc)
217 clkp->rate = clkp->recalc(clkp);
218 propagate_rate(clkp);
219 }
220}
221
222static LIST_HEAD(root_clks);
223
224
225
226
227
228
229
230
231void recalculate_root_clocks(void)
232{
233 struct clk *clkp;
234
235 list_for_each_entry(clkp, &root_clks, sibling) {
236 if (clkp->recalc)
237 clkp->rate = clkp->recalc(clkp);
238 propagate_rate(clkp);
239 }
240}
241
242
243
244
245
246
247
248
249void clk_init_one(struct clk *clk)
250{
251 INIT_LIST_HEAD(&clk->children);
252}
253
254int clk_register(struct clk *clk)
255{
256 if (clk == NULL || IS_ERR(clk))
257 return -EINVAL;
258
259
260
261
262 if (clk->node.next || clk->node.prev)
263 return 0;
264
265 mutex_lock(&clocks_mutex);
266 if (clk->parent)
267 list_add(&clk->sibling, &clk->parent->children);
268 else
269 list_add(&clk->sibling, &root_clks);
270
271 list_add(&clk->node, &clocks);
272 if (clk->init)
273 clk->init(clk);
274 mutex_unlock(&clocks_mutex);
275
276 return 0;
277}
278EXPORT_SYMBOL(clk_register);
279
280void clk_unregister(struct clk *clk)
281{
282 if (clk == NULL || IS_ERR(clk))
283 return;
284
285 mutex_lock(&clocks_mutex);
286 list_del(&clk->sibling);
287 list_del(&clk->node);
288 mutex_unlock(&clocks_mutex);
289}
290EXPORT_SYMBOL(clk_unregister);
291
292void clk_enable_init_clocks(void)
293{
294 struct clk *clkp;
295
296 list_for_each_entry(clkp, &clocks, node) {
297 if (clkp->flags & ENABLE_ON_INIT)
298 clk_enable(clkp);
299 }
300}
301EXPORT_SYMBOL(clk_enable_init_clocks);
302
303
304
305
306static int clkll_enable_null(struct clk *clk)
307{
308 return 0;
309}
310
311static void clkll_disable_null(struct clk *clk)
312{
313}
314
315const struct clkops clkops_null = {
316 .enable = clkll_enable_null,
317 .disable = clkll_disable_null,
318};
319
320#ifdef CONFIG_CPU_FREQ
321void clk_init_cpufreq_table(struct cpufreq_frequency_table **table)
322{
323 unsigned long flags;
324
325 spin_lock_irqsave(&clockfw_lock, flags);
326 if (arch_clock->clk_init_cpufreq_table)
327 arch_clock->clk_init_cpufreq_table(table);
328 spin_unlock_irqrestore(&clockfw_lock, flags);
329}
330EXPORT_SYMBOL(clk_init_cpufreq_table);
331#endif
332
333
334
335#ifdef CONFIG_OMAP_RESET_CLOCKS
336
337
338
339static int __init clk_disable_unused(void)
340{
341 struct clk *ck;
342 unsigned long flags;
343
344 list_for_each_entry(ck, &clocks, node) {
345 if (ck->ops == &clkops_null)
346 continue;
347
348 if (ck->usecount > 0 || ck->enable_reg == 0)
349 continue;
350
351 spin_lock_irqsave(&clockfw_lock, flags);
352 if (arch_clock->clk_disable_unused)
353 arch_clock->clk_disable_unused(ck);
354 spin_unlock_irqrestore(&clockfw_lock, flags);
355 }
356
357 return 0;
358}
359late_initcall(clk_disable_unused);
360#endif
361
362int __init clk_init(struct clk_functions * custom_clocks)
363{
364 if (!custom_clocks) {
365 printk(KERN_ERR "No custom clock functions registered\n");
366 BUG();
367 }
368
369 arch_clock = custom_clocks;
370
371 return 0;
372}
373
374#if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS)
375
376
377
378static struct dentry *clk_debugfs_root;
379
380static int clk_debugfs_register_one(struct clk *c)
381{
382 int err;
383 struct dentry *d, *child;
384 struct clk *pa = c->parent;
385 char s[255];
386 char *p = s;
387
388 p += sprintf(p, "%s", c->name);
389 if (c->id != 0)
390 sprintf(p, ":%d", c->id);
391 d = debugfs_create_dir(s, pa ? pa->dent : clk_debugfs_root);
392 if (!d)
393 return -ENOMEM;
394 c->dent = d;
395
396 d = debugfs_create_u8("usecount", S_IRUGO, c->dent, (u8 *)&c->usecount);
397 if (!d) {
398 err = -ENOMEM;
399 goto err_out;
400 }
401 d = debugfs_create_u32("rate", S_IRUGO, c->dent, (u32 *)&c->rate);
402 if (!d) {
403 err = -ENOMEM;
404 goto err_out;
405 }
406 d = debugfs_create_x32("flags", S_IRUGO, c->dent, (u32 *)&c->flags);
407 if (!d) {
408 err = -ENOMEM;
409 goto err_out;
410 }
411 return 0;
412
413err_out:
414 d = c->dent;
415 list_for_each_entry(child, &d->d_subdirs, d_u.d_child)
416 debugfs_remove(child);
417 debugfs_remove(c->dent);
418 return err;
419}
420
421static int clk_debugfs_register(struct clk *c)
422{
423 int err;
424 struct clk *pa = c->parent;
425
426 if (pa && !pa->dent) {
427 err = clk_debugfs_register(pa);
428 if (err)
429 return err;
430 }
431
432 if (!c->dent) {
433 err = clk_debugfs_register_one(c);
434 if (err)
435 return err;
436 }
437 return 0;
438}
439
440static int __init clk_debugfs_init(void)
441{
442 struct clk *c;
443 struct dentry *d;
444 int err;
445
446 d = debugfs_create_dir("clock", NULL);
447 if (!d)
448 return -ENOMEM;
449 clk_debugfs_root = d;
450
451 list_for_each_entry(c, &clocks, node) {
452 err = clk_debugfs_register(c);
453 if (err)
454 goto err_out;
455 }
456 return 0;
457err_out:
458 debugfs_remove(clk_debugfs_root);
459 return err;
460}
461late_initcall(clk_debugfs_init);
462
463#endif
464