[ARM] tegra: Add clock support
[linux-2.6.git] / arch / arm / mach-tegra / clock.c
1 /*
2  *
3  * Copyright (C) 2010 Google, Inc.
4  *
5  * Author:
6  *      Colin Cross <ccross@google.com>
7  *
8  * This software is licensed under the terms of the GNU General Public
9  * License version 2, as published by the Free Software Foundation, and
10  * may be copied, distributed, and modified under those terms.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  */
18
19 #include <linux/kernel.h>
20 #include <linux/clk.h>
21 #include <linux/list.h>
22 #include <linux/init.h>
23 #include <linux/module.h>
24 #include <linux/debugfs.h>
25 #include <linux/slab.h>
26 #include <linux/seq_file.h>
27 #include <asm/clkdev.h>
28
29 #include "clock.h"
30
31 static LIST_HEAD(clocks);
32
33 static DEFINE_SPINLOCK(clock_lock);
34
35 struct clk *tegra_get_clock_by_name(const char *name)
36 {
37         struct clk *c;
38         struct clk *ret = NULL;
39         unsigned long flags;
40         spin_lock_irqsave(&clock_lock, flags);
41         list_for_each_entry(c, &clocks, node) {
42                 if (strcmp(c->name, name) == 0) {
43                         ret = c;
44                         break;
45                 }
46         }
47         spin_unlock_irqrestore(&clock_lock, flags);
48         return ret;
49 }
50
51 int clk_reparent(struct clk *c, struct clk *parent)
52 {
53         pr_debug("%s: %s\n", __func__, c->name);
54         if (c->refcnt && c->parent)
55                 clk_disable_locked(c->parent);
56         c->parent = parent;
57         if (c->refcnt && c->parent)
58                 clk_enable_locked(c->parent);
59         list_del(&c->sibling);
60         list_add_tail(&c->sibling, &parent->children);
61         return 0;
62 }
63
64 static void propagate_rate(struct clk *c)
65 {
66         struct clk *clkp;
67         pr_debug("%s: %s\n", __func__, c->name);
68         list_for_each_entry(clkp, &c->children, sibling) {
69                 pr_debug("   %s\n", clkp->name);
70                 if (clkp->ops->recalculate_rate)
71                         clkp->ops->recalculate_rate(clkp);
72                 propagate_rate(clkp);
73         }
74 }
75
76 void clk_init(struct clk *c)
77 {
78         unsigned long flags;
79
80         spin_lock_irqsave(&clock_lock, flags);
81
82         INIT_LIST_HEAD(&c->children);
83         INIT_LIST_HEAD(&c->sibling);
84
85         if (c->ops && c->ops->init)
86                 c->ops->init(c);
87
88         list_add(&c->node, &clocks);
89
90         if (c->parent)
91                 list_add_tail(&c->sibling, &c->parent->children);
92
93         spin_unlock_irqrestore(&clock_lock, flags);
94 }
95
96 int clk_enable_locked(struct clk *c)
97 {
98         int ret;
99         pr_debug("%s: %s\n", __func__, c->name);
100         if (c->refcnt == 0) {
101                 if (c->parent) {
102                         ret = clk_enable_locked(c->parent);
103                         if (ret)
104                                 return ret;
105                 }
106
107                 if (c->ops && c->ops->enable) {
108                         ret = c->ops->enable(c);
109                         if (ret) {
110                                 if (c->parent)
111                                         clk_disable_locked(c->parent);
112                                 return ret;
113                         }
114                         c->state = ON;
115 #ifdef CONFIG_DEBUG_FS
116                         c->set = 1;
117 #endif
118                 }
119         }
120         c->refcnt++;
121
122         return 0;
123 }
124
125 int clk_enable(struct clk *c)
126 {
127         int ret;
128         unsigned long flags;
129         spin_lock_irqsave(&clock_lock, flags);
130         ret = clk_enable_locked(c);
131         spin_unlock_irqrestore(&clock_lock, flags);
132         return ret;
133 }
134 EXPORT_SYMBOL(clk_enable);
135
136 void clk_disable_locked(struct clk *c)
137 {
138         pr_debug("%s: %s\n", __func__, c->name);
139         if (c->refcnt == 0) {
140                 WARN(1, "Attempting to disable clock %s with refcnt 0", c->name);
141                 return;
142         }
143         if (c->refcnt == 1) {
144                 if (c->ops && c->ops->disable)
145                         c->ops->disable(c);
146
147                 if (c->parent)
148                         clk_disable_locked(c->parent);
149
150                 c->state = OFF;
151         }
152         c->refcnt--;
153 }
154
155 void clk_disable(struct clk *c)
156 {
157         unsigned long flags;
158         spin_lock_irqsave(&clock_lock, flags);
159         clk_disable_locked(c);
160         spin_unlock_irqrestore(&clock_lock, flags);
161 }
162 EXPORT_SYMBOL(clk_disable);
163
164 int clk_set_parent_locked(struct clk *c, struct clk *parent)
165 {
166         int ret;
167
168         pr_debug("%s: %s\n", __func__, c->name);
169
170         if (!c->ops || !c->ops->set_parent)
171                 return -ENOSYS;
172
173         ret = c->ops->set_parent(c, parent);
174
175         if (ret)
176                 return ret;
177
178         propagate_rate(c);
179
180         return 0;
181 }
182
183 int clk_set_parent(struct clk *c, struct clk *parent)
184 {
185         int ret;
186         unsigned long flags;
187         spin_lock_irqsave(&clock_lock, flags);
188         ret = clk_set_parent_locked(c, parent);
189         spin_unlock_irqrestore(&clock_lock, flags);
190         return ret;
191 }
192 EXPORT_SYMBOL(clk_set_parent);
193
194 struct clk *clk_get_parent(struct clk *c)
195 {
196         return c->parent;
197 }
198 EXPORT_SYMBOL(clk_get_parent);
199
200 int clk_set_rate(struct clk *c, unsigned long rate)
201 {
202         int ret = 0;
203         unsigned long flags;
204
205         spin_lock_irqsave(&clock_lock, flags);
206
207         pr_debug("%s: %s\n", __func__, c->name);
208
209         if (c->ops && c->ops->set_rate)
210                 ret = c->ops->set_rate(c, rate);
211         else
212                 ret = -ENOSYS;
213
214         propagate_rate(c);
215
216         spin_unlock_irqrestore(&clock_lock, flags);
217
218         return ret;
219 }
220 EXPORT_SYMBOL(clk_set_rate);
221
222 unsigned long clk_get_rate(struct clk *c)
223 {
224         unsigned long flags;
225         unsigned long ret;
226
227         spin_lock_irqsave(&clock_lock, flags);
228
229         pr_debug("%s: %s\n", __func__, c->name);
230
231         ret = c->rate;
232
233         spin_unlock_irqrestore(&clock_lock, flags);
234         return ret;
235 }
236 EXPORT_SYMBOL(clk_get_rate);
237
238 static int tegra_clk_init_one_from_table(struct tegra_clk_init_table *table)
239 {
240         struct clk *c;
241         struct clk *p;
242
243         int ret = 0;
244
245         c = tegra_get_clock_by_name(table->name);
246
247         if (!c) {
248                 pr_warning("Unable to initialize clock %s\n",
249                         table->name);
250                 return -ENODEV;
251         }
252
253         if (table->parent) {
254                 p = tegra_get_clock_by_name(table->parent);
255                 if (!p) {
256                         pr_warning("Unable to find parent %s of clock %s\n",
257                                 table->parent, table->name);
258                         return -ENODEV;
259                 }
260
261                 if (c->parent != p) {
262                         ret = clk_set_parent(c, p);
263                         if (ret) {
264                                 pr_warning("Unable to set parent %s of clock %s: %d\n",
265                                         table->parent, table->name, ret);
266                                 return -EINVAL;
267                         }
268                 }
269         }
270
271         if (table->rate && table->rate != clk_get_rate(c)) {
272                 ret = clk_set_rate(c, table->rate);
273                 if (ret) {
274                         pr_warning("Unable to set clock %s to rate %lu: %d\n",
275                                 table->name, table->rate, ret);
276                         return -EINVAL;
277                 }
278         }
279
280         if (table->enabled) {
281                 ret = clk_enable(c);
282                 if (ret) {
283                         pr_warning("Unable to enable clock %s: %d\n",
284                                 table->name, ret);
285                         return -EINVAL;
286                 }
287         }
288
289         return 0;
290 }
291
292 void tegra_clk_init_from_table(struct tegra_clk_init_table *table)
293 {
294         for (; table->name; table++)
295                 tegra_clk_init_one_from_table(table);
296 }
297 EXPORT_SYMBOL(tegra_clk_init_from_table);
298
299 void tegra_periph_reset_deassert(struct clk *c)
300 {
301         tegra2_periph_reset_deassert(c);
302 }
303 EXPORT_SYMBOL(tegra_periph_reset_deassert);
304
305 void tegra_periph_reset_assert(struct clk *c)
306 {
307         tegra2_periph_reset_assert(c);
308 }
309 EXPORT_SYMBOL(tegra_periph_reset_assert);
310
311 int __init tegra_init_clock(void)
312 {
313         tegra2_init_clocks();
314
315         return 0;
316 }
317
318 #ifdef CONFIG_DEBUG_FS
319 static struct dentry *clk_debugfs_root;
320
321
322 static void clock_tree_show_one(struct seq_file *s, struct clk *c, int level)
323 {
324         struct clk *child;
325         struct clk *safe;
326         const char *state = "uninit";
327         char div[5] = {0};
328
329         if (c->state == ON)
330                 state = "on";
331         else if (c->state == OFF)
332                 state = "off";
333
334         if (c->mul != 0 && c->div != 0) {
335                 BUG_ON(c->mul > 2);
336                 if (c->mul > c->div)
337                         snprintf(div, sizeof(div), "x%d", c->mul / c->div);
338                 else
339                         snprintf(div, sizeof(div), "%d%s", c->div / c->mul,
340                                 (c->div % c->mul) ? ".5" : "");
341         }
342
343         seq_printf(s, "%*s%-*s %-6s %-3d %-5s %-10lu\n",
344                 level * 3 + 1, c->set ? "" : "*",
345                 30 - level * 3, c->name,
346                 state, c->refcnt, div, c->rate);
347         list_for_each_entry_safe(child, safe, &c->children, sibling) {
348                 clock_tree_show_one(s, child, level + 1);
349         }
350 }
351
352 static int clock_tree_show(struct seq_file *s, void *data)
353 {
354         struct clk *c;
355         unsigned long flags;
356         seq_printf(s, " clock                          state  ref div   rate      \n");
357         seq_printf(s, "-----------------------------------------------------------\n");
358         spin_lock_irqsave(&clock_lock, flags);
359         list_for_each_entry(c, &clocks, node)
360                 if (c->parent == NULL)
361                         clock_tree_show_one(s, c, 0);
362         spin_unlock_irqrestore(&clock_lock, flags);
363         return 0;
364 }
365
366 static int clock_tree_open(struct inode *inode, struct file *file)
367 {
368         return single_open(file, clock_tree_show, inode->i_private);
369 }
370
371 static const struct file_operations clock_tree_fops = {
372         .open           = clock_tree_open,
373         .read           = seq_read,
374         .llseek         = seq_lseek,
375         .release        = single_release,
376 };
377
378 static int possible_parents_show(struct seq_file *s, void *data)
379 {
380         struct clk *c = s->private;
381         int i;
382
383         for (i = 0; c->inputs[i].input; i++) {
384                 char *first = (i == 0) ? "" : " ";
385                 seq_printf(s, "%s%s", first, c->inputs[i].input->name);
386         }
387         seq_printf(s, "\n");
388         return 0;
389 }
390
391 static int possible_parents_open(struct inode *inode, struct file *file)
392 {
393         return single_open(file, possible_parents_show, inode->i_private);
394 }
395
396 static const struct file_operations possible_parents_fops = {
397         .open           = possible_parents_open,
398         .read           = seq_read,
399         .llseek         = seq_lseek,
400         .release        = single_release,
401 };
402
403 static int clk_debugfs_register_one(struct clk *c)
404 {
405         struct dentry *d, *child, *child_tmp;
406
407         d = debugfs_create_dir(c->name, clk_debugfs_root);
408         if (!d)
409                 return -ENOMEM;
410         c->dent = d;
411
412         d = debugfs_create_u8("refcnt", S_IRUGO, c->dent, (u8 *)&c->refcnt);
413         if (!d)
414                 goto err_out;
415
416         d = debugfs_create_u32("rate", S_IRUGO, c->dent, (u32 *)&c->rate);
417         if (!d)
418                 goto err_out;
419
420         d = debugfs_create_x32("flags", S_IRUGO, c->dent, (u32 *)&c->flags);
421         if (!d)
422                 goto err_out;
423
424         if (c->inputs) {
425                 d = debugfs_create_file("possible_parents", S_IRUGO, c->dent,
426                         c, &possible_parents_fops);
427                 if (!d)
428                         goto err_out;
429         }
430
431         return 0;
432
433 err_out:
434         d = c->dent;
435         list_for_each_entry_safe(child, child_tmp, &d->d_subdirs, d_u.d_child)
436                 debugfs_remove(child);
437         debugfs_remove(c->dent);
438         return -ENOMEM;
439 }
440
441 static int clk_debugfs_register(struct clk *c)
442 {
443         int err;
444         struct clk *pa = c->parent;
445
446         if (pa && !pa->dent) {
447                 err = clk_debugfs_register(pa);
448                 if (err)
449                         return err;
450         }
451
452         if (!c->dent) {
453                 err = clk_debugfs_register_one(c);
454                 if (err)
455                         return err;
456         }
457         return 0;
458 }
459
460 static int __init clk_debugfs_init(void)
461 {
462         struct clk *c;
463         struct dentry *d;
464         int err = -ENOMEM;
465
466         d = debugfs_create_dir("clock", NULL);
467         if (!d)
468                 return -ENOMEM;
469         clk_debugfs_root = d;
470
471         d = debugfs_create_file("clock_tree", S_IRUGO, clk_debugfs_root, NULL,
472                 &clock_tree_fops);
473         if (!d)
474                 goto err_out;
475
476         list_for_each_entry(c, &clocks, node) {
477                 err = clk_debugfs_register(c);
478                 if (err)
479                         goto err_out;
480         }
481         return 0;
482 err_out:
483         debugfs_remove_recursive(clk_debugfs_root);
484         return err;
485 }
486
487 late_initcall(clk_debugfs_init);
488 #endif