blob: f55bb83fb2d37049ee0901a4e11db4a72613cfde [file] [log] [blame]
Colin Crossd8611962010-01-28 16:40:29 -08001/*
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>
Colin Cross71fc84c2010-06-07 20:49:46 -070027#include <linux/regulator/consumer.h>
Jean-Christop PLAGNIOL-VILLARD6d803ba2010-11-17 10:04:33 +010028#include <linux/clkdev.h>
Colin Crossd8611962010-01-28 16:40:29 -080029
30#include "clock.h"
Colin Cross71fc84c2010-06-07 20:49:46 -070031#include "board.h"
32#include "fuse.h"
Colin Crossd8611962010-01-28 16:40:29 -080033
34static LIST_HEAD(clocks);
35
36static DEFINE_SPINLOCK(clock_lock);
Colin Cross71fc84c2010-06-07 20:49:46 -070037static DEFINE_MUTEX(dvfs_lock);
38
39static int clk_is_dvfs(struct clk *c)
40{
41 return (c->dvfs != NULL);
42};
43
44static int dvfs_set_rate(struct dvfs *d, unsigned long rate)
45{
46 struct dvfs_table *t;
47
48 if (d->table == NULL)
49 return -ENODEV;
50
51 for (t = d->table; t->rate != 0; t++) {
52 if (rate <= t->rate) {
53 if (!d->reg)
54 return 0;
55
56 return regulator_set_voltage(d->reg,
57 t->millivolts * 1000,
58 d->max_millivolts * 1000);
59 }
60 }
61
62 return -EINVAL;
63}
64
65static void dvfs_init(struct clk *c)
66{
67 int process_id;
68 int i;
69 struct dvfs_table *table;
70
71 process_id = c->dvfs->cpu ? tegra_core_process_id() :
72 tegra_cpu_process_id();
73
74 for (i = 0; i < c->dvfs->process_id_table_length; i++)
75 if (process_id == c->dvfs->process_id_table[i].process_id)
76 c->dvfs->table = c->dvfs->process_id_table[i].table;
77
78 if (c->dvfs->table == NULL) {
79 pr_err("Failed to find dvfs table for clock %s process %d\n",
80 c->name, process_id);
81 return;
82 }
83
84 c->dvfs->max_millivolts = 0;
85 for (table = c->dvfs->table; table->rate != 0; table++)
86 if (c->dvfs->max_millivolts < table->millivolts)
87 c->dvfs->max_millivolts = table->millivolts;
88
89 c->dvfs->reg = regulator_get(NULL, c->dvfs->reg_id);
90
91 if (IS_ERR(c->dvfs->reg)) {
92 pr_err("Failed to get regulator %s for clock %s\n",
93 c->dvfs->reg_id, c->name);
94 c->dvfs->reg = NULL;
95 return;
96 }
97
98 if (c->refcnt > 0)
99 dvfs_set_rate(c->dvfs, c->rate);
100}
Colin Crossd8611962010-01-28 16:40:29 -0800101
102struct clk *tegra_get_clock_by_name(const char *name)
103{
104 struct clk *c;
105 struct clk *ret = NULL;
106 unsigned long flags;
107 spin_lock_irqsave(&clock_lock, flags);
108 list_for_each_entry(c, &clocks, node) {
109 if (strcmp(c->name, name) == 0) {
110 ret = c;
111 break;
112 }
113 }
114 spin_unlock_irqrestore(&clock_lock, flags);
115 return ret;
116}
117
Colin Cross71fc84c2010-06-07 20:49:46 -0700118static void clk_recalculate_rate(struct clk *c)
119{
120 u64 rate;
121
122 if (!c->parent)
123 return;
124
125 rate = c->parent->rate;
126
127 if (c->mul != 0 && c->div != 0) {
128 rate = rate * c->mul;
129 do_div(rate, c->div);
130 }
131
132 if (rate > c->max_rate)
133 pr_warn("clocks: Set clock %s to rate %llu, max is %lu\n",
134 c->name, rate, c->max_rate);
135
136 c->rate = rate;
137}
138
Colin Crossd8611962010-01-28 16:40:29 -0800139int clk_reparent(struct clk *c, struct clk *parent)
140{
Colin Crossd8611962010-01-28 16:40:29 -0800141 c->parent = parent;
Colin Crossd8611962010-01-28 16:40:29 -0800142 list_del(&c->sibling);
143 list_add_tail(&c->sibling, &parent->children);
144 return 0;
145}
146
147static void propagate_rate(struct clk *c)
148{
149 struct clk *clkp;
Colin Crossbd41ef52010-09-08 20:01:04 -0700150
Colin Crossd8611962010-01-28 16:40:29 -0800151 list_for_each_entry(clkp, &c->children, sibling) {
Colin Cross71fc84c2010-06-07 20:49:46 -0700152 clk_recalculate_rate(clkp);
Colin Crossd8611962010-01-28 16:40:29 -0800153 propagate_rate(clkp);
154 }
155}
156
157void clk_init(struct clk *c)
158{
159 unsigned long flags;
160
161 spin_lock_irqsave(&clock_lock, flags);
162
163 INIT_LIST_HEAD(&c->children);
164 INIT_LIST_HEAD(&c->sibling);
165
166 if (c->ops && c->ops->init)
167 c->ops->init(c);
168
Colin Cross71fc84c2010-06-07 20:49:46 -0700169 clk_recalculate_rate(c);
170
Colin Crossd8611962010-01-28 16:40:29 -0800171 list_add(&c->node, &clocks);
172
173 if (c->parent)
174 list_add_tail(&c->sibling, &c->parent->children);
175
176 spin_unlock_irqrestore(&clock_lock, flags);
177}
178
179int clk_enable_locked(struct clk *c)
180{
181 int ret;
Colin Crossbd41ef52010-09-08 20:01:04 -0700182
Colin Crossd8611962010-01-28 16:40:29 -0800183 if (c->refcnt == 0) {
184 if (c->parent) {
185 ret = clk_enable_locked(c->parent);
186 if (ret)
187 return ret;
188 }
189
190 if (c->ops && c->ops->enable) {
191 ret = c->ops->enable(c);
192 if (ret) {
193 if (c->parent)
194 clk_disable_locked(c->parent);
195 return ret;
196 }
197 c->state = ON;
198#ifdef CONFIG_DEBUG_FS
199 c->set = 1;
200#endif
201 }
202 }
203 c->refcnt++;
204
205 return 0;
206}
207
Colin Cross71fc84c2010-06-07 20:49:46 -0700208int clk_enable_cansleep(struct clk *c)
209{
210 int ret;
211 unsigned long flags;
212
213 mutex_lock(&dvfs_lock);
214
215 if (clk_is_dvfs(c) && c->refcnt > 0)
216 dvfs_set_rate(c->dvfs, c->rate);
217
218 spin_lock_irqsave(&clock_lock, flags);
219 ret = clk_enable_locked(c);
220 spin_unlock_irqrestore(&clock_lock, flags);
221
222 mutex_unlock(&dvfs_lock);
223
224 return ret;
225}
226EXPORT_SYMBOL(clk_enable_cansleep);
227
Colin Crossd8611962010-01-28 16:40:29 -0800228int clk_enable(struct clk *c)
229{
230 int ret;
231 unsigned long flags;
Colin Cross71fc84c2010-06-07 20:49:46 -0700232
233 if (clk_is_dvfs(c))
234 BUG();
235
Colin Crossd8611962010-01-28 16:40:29 -0800236 spin_lock_irqsave(&clock_lock, flags);
237 ret = clk_enable_locked(c);
238 spin_unlock_irqrestore(&clock_lock, flags);
Colin Cross71fc84c2010-06-07 20:49:46 -0700239
Colin Crossd8611962010-01-28 16:40:29 -0800240 return ret;
241}
242EXPORT_SYMBOL(clk_enable);
243
244void clk_disable_locked(struct clk *c)
245{
Colin Crossd8611962010-01-28 16:40:29 -0800246 if (c->refcnt == 0) {
247 WARN(1, "Attempting to disable clock %s with refcnt 0", c->name);
248 return;
249 }
250 if (c->refcnt == 1) {
251 if (c->ops && c->ops->disable)
252 c->ops->disable(c);
253
254 if (c->parent)
255 clk_disable_locked(c->parent);
256
257 c->state = OFF;
258 }
259 c->refcnt--;
260}
261
Colin Cross71fc84c2010-06-07 20:49:46 -0700262void clk_disable_cansleep(struct clk *c)
263{
264 unsigned long flags;
265
266 mutex_lock(&dvfs_lock);
267
268 spin_lock_irqsave(&clock_lock, flags);
269 clk_disable_locked(c);
270 spin_unlock_irqrestore(&clock_lock, flags);
271
272 if (clk_is_dvfs(c) && c->refcnt == 0)
273 dvfs_set_rate(c->dvfs, c->rate);
274
275 mutex_unlock(&dvfs_lock);
276}
277EXPORT_SYMBOL(clk_disable_cansleep);
278
Colin Crossd8611962010-01-28 16:40:29 -0800279void clk_disable(struct clk *c)
280{
281 unsigned long flags;
Colin Cross71fc84c2010-06-07 20:49:46 -0700282
283 if (clk_is_dvfs(c))
284 BUG();
285
Colin Crossd8611962010-01-28 16:40:29 -0800286 spin_lock_irqsave(&clock_lock, flags);
287 clk_disable_locked(c);
288 spin_unlock_irqrestore(&clock_lock, flags);
289}
290EXPORT_SYMBOL(clk_disable);
291
292int clk_set_parent_locked(struct clk *c, struct clk *parent)
293{
294 int ret;
295
Colin Crossd8611962010-01-28 16:40:29 -0800296 if (!c->ops || !c->ops->set_parent)
297 return -ENOSYS;
298
299 ret = c->ops->set_parent(c, parent);
300
301 if (ret)
302 return ret;
303
Colin Cross71fc84c2010-06-07 20:49:46 -0700304 clk_recalculate_rate(c);
305
Colin Crossd8611962010-01-28 16:40:29 -0800306 propagate_rate(c);
307
308 return 0;
309}
310
311int clk_set_parent(struct clk *c, struct clk *parent)
312{
313 int ret;
314 unsigned long flags;
315 spin_lock_irqsave(&clock_lock, flags);
316 ret = clk_set_parent_locked(c, parent);
317 spin_unlock_irqrestore(&clock_lock, flags);
318 return ret;
319}
320EXPORT_SYMBOL(clk_set_parent);
321
322struct clk *clk_get_parent(struct clk *c)
323{
324 return c->parent;
325}
326EXPORT_SYMBOL(clk_get_parent);
327
Colin Cross71fc84c2010-06-07 20:49:46 -0700328int clk_set_rate_locked(struct clk *c, unsigned long rate)
329{
330 int ret;
331
332 if (rate > c->max_rate)
333 rate = c->max_rate;
334
335 if (!c->ops || !c->ops->set_rate)
336 return -ENOSYS;
337
338 ret = c->ops->set_rate(c, rate);
339
340 if (ret)
341 return ret;
342
343 clk_recalculate_rate(c);
344
345 propagate_rate(c);
346
347 return 0;
348}
349
350int clk_set_rate_cansleep(struct clk *c, unsigned long rate)
351{
352 int ret = 0;
353 unsigned long flags;
354
Colin Cross71fc84c2010-06-07 20:49:46 -0700355 mutex_lock(&dvfs_lock);
356
357 if (rate > c->rate)
358 ret = dvfs_set_rate(c->dvfs, rate);
359 if (ret)
360 goto out;
361
362 spin_lock_irqsave(&clock_lock, flags);
363 ret = clk_set_rate_locked(c, rate);
364 spin_unlock_irqrestore(&clock_lock, flags);
365
366 if (ret)
367 goto out;
368
369 ret = dvfs_set_rate(c->dvfs, rate);
370
371out:
372 mutex_unlock(&dvfs_lock);
373 return ret;
374}
375EXPORT_SYMBOL(clk_set_rate_cansleep);
376
Colin Crossd8611962010-01-28 16:40:29 -0800377int clk_set_rate(struct clk *c, unsigned long rate)
378{
379 int ret = 0;
380 unsigned long flags;
381
Colin Cross71fc84c2010-06-07 20:49:46 -0700382 if (clk_is_dvfs(c))
383 BUG();
Colin Crossd8611962010-01-28 16:40:29 -0800384
Colin Cross71fc84c2010-06-07 20:49:46 -0700385 spin_lock_irqsave(&clock_lock, flags);
386 ret = clk_set_rate_locked(c, rate);
Colin Crossd8611962010-01-28 16:40:29 -0800387 spin_unlock_irqrestore(&clock_lock, flags);
388
389 return ret;
390}
391EXPORT_SYMBOL(clk_set_rate);
392
393unsigned long clk_get_rate(struct clk *c)
394{
395 unsigned long flags;
396 unsigned long ret;
397
398 spin_lock_irqsave(&clock_lock, flags);
399
Colin Crossd8611962010-01-28 16:40:29 -0800400 ret = c->rate;
401
402 spin_unlock_irqrestore(&clock_lock, flags);
403 return ret;
404}
405EXPORT_SYMBOL(clk_get_rate);
406
Colin Cross71fc84c2010-06-07 20:49:46 -0700407long clk_round_rate(struct clk *c, unsigned long rate)
408{
Colin Cross71fc84c2010-06-07 20:49:46 -0700409 if (!c->ops || !c->ops->round_rate)
410 return -ENOSYS;
411
412 if (rate > c->max_rate)
413 rate = c->max_rate;
414
415 return c->ops->round_rate(c, rate);
416}
417EXPORT_SYMBOL(clk_round_rate);
418
Colin Crossd8611962010-01-28 16:40:29 -0800419static int tegra_clk_init_one_from_table(struct tegra_clk_init_table *table)
420{
421 struct clk *c;
422 struct clk *p;
423
424 int ret = 0;
425
426 c = tegra_get_clock_by_name(table->name);
427
428 if (!c) {
429 pr_warning("Unable to initialize clock %s\n",
430 table->name);
431 return -ENODEV;
432 }
433
434 if (table->parent) {
435 p = tegra_get_clock_by_name(table->parent);
436 if (!p) {
437 pr_warning("Unable to find parent %s of clock %s\n",
438 table->parent, table->name);
439 return -ENODEV;
440 }
441
442 if (c->parent != p) {
443 ret = clk_set_parent(c, p);
444 if (ret) {
445 pr_warning("Unable to set parent %s of clock %s: %d\n",
446 table->parent, table->name, ret);
447 return -EINVAL;
448 }
449 }
450 }
451
452 if (table->rate && table->rate != clk_get_rate(c)) {
453 ret = clk_set_rate(c, table->rate);
454 if (ret) {
455 pr_warning("Unable to set clock %s to rate %lu: %d\n",
456 table->name, table->rate, ret);
457 return -EINVAL;
458 }
459 }
460
461 if (table->enabled) {
462 ret = clk_enable(c);
463 if (ret) {
464 pr_warning("Unable to enable clock %s: %d\n",
465 table->name, ret);
466 return -EINVAL;
467 }
468 }
469
470 return 0;
471}
472
473void tegra_clk_init_from_table(struct tegra_clk_init_table *table)
474{
475 for (; table->name; table++)
476 tegra_clk_init_one_from_table(table);
477}
478EXPORT_SYMBOL(tegra_clk_init_from_table);
479
480void tegra_periph_reset_deassert(struct clk *c)
481{
482 tegra2_periph_reset_deassert(c);
483}
484EXPORT_SYMBOL(tegra_periph_reset_deassert);
485
486void tegra_periph_reset_assert(struct clk *c)
487{
488 tegra2_periph_reset_assert(c);
489}
490EXPORT_SYMBOL(tegra_periph_reset_assert);
491
Colin Cross71fc84c2010-06-07 20:49:46 -0700492void __init tegra_init_clock(void)
Colin Crossd8611962010-01-28 16:40:29 -0800493{
494 tegra2_init_clocks();
Colin Cross71fc84c2010-06-07 20:49:46 -0700495}
496
497int __init tegra_init_dvfs(void)
498{
499 struct clk *c, *safe;
500
501 mutex_lock(&dvfs_lock);
502
503 list_for_each_entry_safe(c, safe, &clocks, node)
504 if (c->dvfs)
505 dvfs_init(c);
506
507 mutex_unlock(&dvfs_lock);
Colin Crossd8611962010-01-28 16:40:29 -0800508
509 return 0;
510}
511
Colin Cross71fc84c2010-06-07 20:49:46 -0700512late_initcall(tegra_init_dvfs);
513
Colin Crossd8611962010-01-28 16:40:29 -0800514#ifdef CONFIG_DEBUG_FS
515static struct dentry *clk_debugfs_root;
516
517
518static void clock_tree_show_one(struct seq_file *s, struct clk *c, int level)
519{
520 struct clk *child;
521 struct clk *safe;
522 const char *state = "uninit";
Colin Cross71fc84c2010-06-07 20:49:46 -0700523 char div[8] = {0};
Colin Crossd8611962010-01-28 16:40:29 -0800524
525 if (c->state == ON)
526 state = "on";
527 else if (c->state == OFF)
528 state = "off";
529
530 if (c->mul != 0 && c->div != 0) {
Colin Cross71fc84c2010-06-07 20:49:46 -0700531 if (c->mul > c->div) {
532 int mul = c->mul / c->div;
533 int mul2 = (c->mul * 10 / c->div) % 10;
534 int mul3 = (c->mul * 10) % c->div;
535 if (mul2 == 0 && mul3 == 0)
536 snprintf(div, sizeof(div), "x%d", mul);
537 else if (mul3 == 0)
538 snprintf(div, sizeof(div), "x%d.%d", mul, mul2);
539 else
540 snprintf(div, sizeof(div), "x%d.%d..", mul, mul2);
541 } else {
Colin Crossd8611962010-01-28 16:40:29 -0800542 snprintf(div, sizeof(div), "%d%s", c->div / c->mul,
543 (c->div % c->mul) ? ".5" : "");
Colin Cross71fc84c2010-06-07 20:49:46 -0700544 }
Colin Crossd8611962010-01-28 16:40:29 -0800545 }
546
Colin Cross71fc84c2010-06-07 20:49:46 -0700547 seq_printf(s, "%*s%c%c%-*s %-6s %-3d %-8s %-10lu\n",
548 level * 3 + 1, "",
549 c->rate > c->max_rate ? '!' : ' ',
550 !c->set ? '*' : ' ',
Colin Crossd8611962010-01-28 16:40:29 -0800551 30 - level * 3, c->name,
552 state, c->refcnt, div, c->rate);
553 list_for_each_entry_safe(child, safe, &c->children, sibling) {
554 clock_tree_show_one(s, child, level + 1);
555 }
556}
557
558static int clock_tree_show(struct seq_file *s, void *data)
559{
560 struct clk *c;
561 unsigned long flags;
Colin Cross71fc84c2010-06-07 20:49:46 -0700562 seq_printf(s, " clock state ref div rate\n");
563 seq_printf(s, "--------------------------------------------------------------\n");
Colin Crossd8611962010-01-28 16:40:29 -0800564 spin_lock_irqsave(&clock_lock, flags);
565 list_for_each_entry(c, &clocks, node)
566 if (c->parent == NULL)
567 clock_tree_show_one(s, c, 0);
568 spin_unlock_irqrestore(&clock_lock, flags);
569 return 0;
570}
571
572static int clock_tree_open(struct inode *inode, struct file *file)
573{
574 return single_open(file, clock_tree_show, inode->i_private);
575}
576
577static const struct file_operations clock_tree_fops = {
578 .open = clock_tree_open,
579 .read = seq_read,
580 .llseek = seq_lseek,
581 .release = single_release,
582};
583
584static int possible_parents_show(struct seq_file *s, void *data)
585{
586 struct clk *c = s->private;
587 int i;
588
589 for (i = 0; c->inputs[i].input; i++) {
590 char *first = (i == 0) ? "" : " ";
591 seq_printf(s, "%s%s", first, c->inputs[i].input->name);
592 }
593 seq_printf(s, "\n");
594 return 0;
595}
596
597static int possible_parents_open(struct inode *inode, struct file *file)
598{
599 return single_open(file, possible_parents_show, inode->i_private);
600}
601
602static const struct file_operations possible_parents_fops = {
603 .open = possible_parents_open,
604 .read = seq_read,
605 .llseek = seq_lseek,
606 .release = single_release,
607};
608
609static int clk_debugfs_register_one(struct clk *c)
610{
611 struct dentry *d, *child, *child_tmp;
612
613 d = debugfs_create_dir(c->name, clk_debugfs_root);
614 if (!d)
615 return -ENOMEM;
616 c->dent = d;
617
618 d = debugfs_create_u8("refcnt", S_IRUGO, c->dent, (u8 *)&c->refcnt);
619 if (!d)
620 goto err_out;
621
622 d = debugfs_create_u32("rate", S_IRUGO, c->dent, (u32 *)&c->rate);
623 if (!d)
624 goto err_out;
625
626 d = debugfs_create_x32("flags", S_IRUGO, c->dent, (u32 *)&c->flags);
627 if (!d)
628 goto err_out;
629
630 if (c->inputs) {
631 d = debugfs_create_file("possible_parents", S_IRUGO, c->dent,
632 c, &possible_parents_fops);
633 if (!d)
634 goto err_out;
635 }
636
637 return 0;
638
639err_out:
640 d = c->dent;
641 list_for_each_entry_safe(child, child_tmp, &d->d_subdirs, d_u.d_child)
642 debugfs_remove(child);
643 debugfs_remove(c->dent);
644 return -ENOMEM;
645}
646
647static int clk_debugfs_register(struct clk *c)
648{
649 int err;
650 struct clk *pa = c->parent;
651
652 if (pa && !pa->dent) {
653 err = clk_debugfs_register(pa);
654 if (err)
655 return err;
656 }
657
658 if (!c->dent) {
659 err = clk_debugfs_register_one(c);
660 if (err)
661 return err;
662 }
663 return 0;
664}
665
666static int __init clk_debugfs_init(void)
667{
668 struct clk *c;
669 struct dentry *d;
670 int err = -ENOMEM;
671
672 d = debugfs_create_dir("clock", NULL);
673 if (!d)
674 return -ENOMEM;
675 clk_debugfs_root = d;
676
677 d = debugfs_create_file("clock_tree", S_IRUGO, clk_debugfs_root, NULL,
678 &clock_tree_fops);
679 if (!d)
680 goto err_out;
681
682 list_for_each_entry(c, &clocks, node) {
683 err = clk_debugfs_register(c);
684 if (err)
685 goto err_out;
686 }
687 return 0;
688err_out:
689 debugfs_remove_recursive(clk_debugfs_root);
690 return err;
691}
692
693late_initcall(clk_debugfs_init);
694#endif