blob: 92bcc20723023b05a710bc3782950f938065626c [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 Crossf0355302010-10-13 19:16:02 -0700169 if (!c->ops || !c->ops->enable) {
170 c->refcnt++;
171 c->set = 1;
172 if (c->parent)
173 c->state = c->parent->state;
174 else
175 c->state = ON;
176 }
177
Colin Cross71fc84c2010-06-07 20:49:46 -0700178 clk_recalculate_rate(c);
179
Colin Crossd8611962010-01-28 16:40:29 -0800180 list_add(&c->node, &clocks);
181
182 if (c->parent)
183 list_add_tail(&c->sibling, &c->parent->children);
184
185 spin_unlock_irqrestore(&clock_lock, flags);
186}
187
188int clk_enable_locked(struct clk *c)
189{
190 int ret;
Colin Crossbd41ef52010-09-08 20:01:04 -0700191
Colin Crossd8611962010-01-28 16:40:29 -0800192 if (c->refcnt == 0) {
193 if (c->parent) {
194 ret = clk_enable_locked(c->parent);
195 if (ret)
196 return ret;
197 }
198
199 if (c->ops && c->ops->enable) {
200 ret = c->ops->enable(c);
201 if (ret) {
202 if (c->parent)
203 clk_disable_locked(c->parent);
204 return ret;
205 }
206 c->state = ON;
207#ifdef CONFIG_DEBUG_FS
208 c->set = 1;
209#endif
210 }
211 }
212 c->refcnt++;
213
214 return 0;
215}
216
Colin Cross71fc84c2010-06-07 20:49:46 -0700217int clk_enable_cansleep(struct clk *c)
218{
219 int ret;
220 unsigned long flags;
221
222 mutex_lock(&dvfs_lock);
223
224 if (clk_is_dvfs(c) && c->refcnt > 0)
225 dvfs_set_rate(c->dvfs, c->rate);
226
227 spin_lock_irqsave(&clock_lock, flags);
228 ret = clk_enable_locked(c);
229 spin_unlock_irqrestore(&clock_lock, flags);
230
231 mutex_unlock(&dvfs_lock);
232
233 return ret;
234}
235EXPORT_SYMBOL(clk_enable_cansleep);
236
Colin Crossd8611962010-01-28 16:40:29 -0800237int clk_enable(struct clk *c)
238{
239 int ret;
240 unsigned long flags;
Colin Cross71fc84c2010-06-07 20:49:46 -0700241
242 if (clk_is_dvfs(c))
243 BUG();
244
Colin Crossd8611962010-01-28 16:40:29 -0800245 spin_lock_irqsave(&clock_lock, flags);
246 ret = clk_enable_locked(c);
247 spin_unlock_irqrestore(&clock_lock, flags);
Colin Cross71fc84c2010-06-07 20:49:46 -0700248
Colin Crossd8611962010-01-28 16:40:29 -0800249 return ret;
250}
251EXPORT_SYMBOL(clk_enable);
252
253void clk_disable_locked(struct clk *c)
254{
Colin Crossd8611962010-01-28 16:40:29 -0800255 if (c->refcnt == 0) {
256 WARN(1, "Attempting to disable clock %s with refcnt 0", c->name);
257 return;
258 }
259 if (c->refcnt == 1) {
260 if (c->ops && c->ops->disable)
261 c->ops->disable(c);
262
263 if (c->parent)
264 clk_disable_locked(c->parent);
265
266 c->state = OFF;
267 }
268 c->refcnt--;
269}
270
Colin Cross71fc84c2010-06-07 20:49:46 -0700271void clk_disable_cansleep(struct clk *c)
272{
273 unsigned long flags;
274
275 mutex_lock(&dvfs_lock);
276
277 spin_lock_irqsave(&clock_lock, flags);
278 clk_disable_locked(c);
279 spin_unlock_irqrestore(&clock_lock, flags);
280
281 if (clk_is_dvfs(c) && c->refcnt == 0)
282 dvfs_set_rate(c->dvfs, c->rate);
283
284 mutex_unlock(&dvfs_lock);
285}
286EXPORT_SYMBOL(clk_disable_cansleep);
287
Colin Crossd8611962010-01-28 16:40:29 -0800288void clk_disable(struct clk *c)
289{
290 unsigned long flags;
Colin Cross71fc84c2010-06-07 20:49:46 -0700291
292 if (clk_is_dvfs(c))
293 BUG();
294
Colin Crossd8611962010-01-28 16:40:29 -0800295 spin_lock_irqsave(&clock_lock, flags);
296 clk_disable_locked(c);
297 spin_unlock_irqrestore(&clock_lock, flags);
298}
299EXPORT_SYMBOL(clk_disable);
300
301int clk_set_parent_locked(struct clk *c, struct clk *parent)
302{
303 int ret;
304
Colin Crossd8611962010-01-28 16:40:29 -0800305 if (!c->ops || !c->ops->set_parent)
306 return -ENOSYS;
307
308 ret = c->ops->set_parent(c, parent);
309
310 if (ret)
311 return ret;
312
Colin Cross71fc84c2010-06-07 20:49:46 -0700313 clk_recalculate_rate(c);
314
Colin Crossd8611962010-01-28 16:40:29 -0800315 propagate_rate(c);
316
317 return 0;
318}
319
320int clk_set_parent(struct clk *c, struct clk *parent)
321{
322 int ret;
323 unsigned long flags;
324 spin_lock_irqsave(&clock_lock, flags);
325 ret = clk_set_parent_locked(c, parent);
326 spin_unlock_irqrestore(&clock_lock, flags);
327 return ret;
328}
329EXPORT_SYMBOL(clk_set_parent);
330
331struct clk *clk_get_parent(struct clk *c)
332{
333 return c->parent;
334}
335EXPORT_SYMBOL(clk_get_parent);
336
Colin Cross71fc84c2010-06-07 20:49:46 -0700337int clk_set_rate_locked(struct clk *c, unsigned long rate)
338{
339 int ret;
340
341 if (rate > c->max_rate)
342 rate = c->max_rate;
343
344 if (!c->ops || !c->ops->set_rate)
345 return -ENOSYS;
346
347 ret = c->ops->set_rate(c, rate);
348
349 if (ret)
350 return ret;
351
352 clk_recalculate_rate(c);
353
354 propagate_rate(c);
355
356 return 0;
357}
358
359int clk_set_rate_cansleep(struct clk *c, unsigned long rate)
360{
361 int ret = 0;
362 unsigned long flags;
363
Colin Cross71fc84c2010-06-07 20:49:46 -0700364 mutex_lock(&dvfs_lock);
365
366 if (rate > c->rate)
367 ret = dvfs_set_rate(c->dvfs, rate);
368 if (ret)
369 goto out;
370
371 spin_lock_irqsave(&clock_lock, flags);
372 ret = clk_set_rate_locked(c, rate);
373 spin_unlock_irqrestore(&clock_lock, flags);
374
375 if (ret)
376 goto out;
377
378 ret = dvfs_set_rate(c->dvfs, rate);
379
380out:
381 mutex_unlock(&dvfs_lock);
382 return ret;
383}
384EXPORT_SYMBOL(clk_set_rate_cansleep);
385
Colin Crossd8611962010-01-28 16:40:29 -0800386int clk_set_rate(struct clk *c, unsigned long rate)
387{
388 int ret = 0;
389 unsigned long flags;
390
Colin Cross71fc84c2010-06-07 20:49:46 -0700391 if (clk_is_dvfs(c))
392 BUG();
Colin Crossd8611962010-01-28 16:40:29 -0800393
Colin Cross71fc84c2010-06-07 20:49:46 -0700394 spin_lock_irqsave(&clock_lock, flags);
395 ret = clk_set_rate_locked(c, rate);
Colin Crossd8611962010-01-28 16:40:29 -0800396 spin_unlock_irqrestore(&clock_lock, flags);
397
398 return ret;
399}
400EXPORT_SYMBOL(clk_set_rate);
401
402unsigned long clk_get_rate(struct clk *c)
403{
404 unsigned long flags;
405 unsigned long ret;
406
407 spin_lock_irqsave(&clock_lock, flags);
408
Colin Crossd8611962010-01-28 16:40:29 -0800409 ret = c->rate;
410
411 spin_unlock_irqrestore(&clock_lock, flags);
412 return ret;
413}
414EXPORT_SYMBOL(clk_get_rate);
415
Colin Cross71fc84c2010-06-07 20:49:46 -0700416long clk_round_rate(struct clk *c, unsigned long rate)
417{
Colin Cross71fc84c2010-06-07 20:49:46 -0700418 if (!c->ops || !c->ops->round_rate)
419 return -ENOSYS;
420
421 if (rate > c->max_rate)
422 rate = c->max_rate;
423
424 return c->ops->round_rate(c, rate);
425}
426EXPORT_SYMBOL(clk_round_rate);
427
Colin Crossd8611962010-01-28 16:40:29 -0800428static int tegra_clk_init_one_from_table(struct tegra_clk_init_table *table)
429{
430 struct clk *c;
431 struct clk *p;
432
433 int ret = 0;
434
435 c = tegra_get_clock_by_name(table->name);
436
437 if (!c) {
438 pr_warning("Unable to initialize clock %s\n",
439 table->name);
440 return -ENODEV;
441 }
442
443 if (table->parent) {
444 p = tegra_get_clock_by_name(table->parent);
445 if (!p) {
446 pr_warning("Unable to find parent %s of clock %s\n",
447 table->parent, table->name);
448 return -ENODEV;
449 }
450
451 if (c->parent != p) {
452 ret = clk_set_parent(c, p);
453 if (ret) {
454 pr_warning("Unable to set parent %s of clock %s: %d\n",
455 table->parent, table->name, ret);
456 return -EINVAL;
457 }
458 }
459 }
460
461 if (table->rate && table->rate != clk_get_rate(c)) {
462 ret = clk_set_rate(c, table->rate);
463 if (ret) {
464 pr_warning("Unable to set clock %s to rate %lu: %d\n",
465 table->name, table->rate, ret);
466 return -EINVAL;
467 }
468 }
469
470 if (table->enabled) {
471 ret = clk_enable(c);
472 if (ret) {
473 pr_warning("Unable to enable clock %s: %d\n",
474 table->name, ret);
475 return -EINVAL;
476 }
477 }
478
479 return 0;
480}
481
482void tegra_clk_init_from_table(struct tegra_clk_init_table *table)
483{
484 for (; table->name; table++)
485 tegra_clk_init_one_from_table(table);
486}
487EXPORT_SYMBOL(tegra_clk_init_from_table);
488
489void tegra_periph_reset_deassert(struct clk *c)
490{
491 tegra2_periph_reset_deassert(c);
492}
493EXPORT_SYMBOL(tegra_periph_reset_deassert);
494
495void tegra_periph_reset_assert(struct clk *c)
496{
497 tegra2_periph_reset_assert(c);
498}
499EXPORT_SYMBOL(tegra_periph_reset_assert);
500
Colin Cross71fc84c2010-06-07 20:49:46 -0700501void __init tegra_init_clock(void)
Colin Crossd8611962010-01-28 16:40:29 -0800502{
503 tegra2_init_clocks();
Colin Cross71fc84c2010-06-07 20:49:46 -0700504}
505
506int __init tegra_init_dvfs(void)
507{
508 struct clk *c, *safe;
509
510 mutex_lock(&dvfs_lock);
511
512 list_for_each_entry_safe(c, safe, &clocks, node)
513 if (c->dvfs)
514 dvfs_init(c);
515
516 mutex_unlock(&dvfs_lock);
Colin Crossd8611962010-01-28 16:40:29 -0800517
518 return 0;
519}
520
Colin Cross71fc84c2010-06-07 20:49:46 -0700521late_initcall(tegra_init_dvfs);
522
Colin Crossd8611962010-01-28 16:40:29 -0800523#ifdef CONFIG_DEBUG_FS
524static struct dentry *clk_debugfs_root;
525
526
527static void clock_tree_show_one(struct seq_file *s, struct clk *c, int level)
528{
529 struct clk *child;
530 struct clk *safe;
531 const char *state = "uninit";
Colin Cross71fc84c2010-06-07 20:49:46 -0700532 char div[8] = {0};
Colin Crossd8611962010-01-28 16:40:29 -0800533
534 if (c->state == ON)
535 state = "on";
536 else if (c->state == OFF)
537 state = "off";
538
539 if (c->mul != 0 && c->div != 0) {
Colin Cross71fc84c2010-06-07 20:49:46 -0700540 if (c->mul > c->div) {
541 int mul = c->mul / c->div;
542 int mul2 = (c->mul * 10 / c->div) % 10;
543 int mul3 = (c->mul * 10) % c->div;
544 if (mul2 == 0 && mul3 == 0)
545 snprintf(div, sizeof(div), "x%d", mul);
546 else if (mul3 == 0)
547 snprintf(div, sizeof(div), "x%d.%d", mul, mul2);
548 else
549 snprintf(div, sizeof(div), "x%d.%d..", mul, mul2);
550 } else {
Colin Crossd8611962010-01-28 16:40:29 -0800551 snprintf(div, sizeof(div), "%d%s", c->div / c->mul,
552 (c->div % c->mul) ? ".5" : "");
Colin Cross71fc84c2010-06-07 20:49:46 -0700553 }
Colin Crossd8611962010-01-28 16:40:29 -0800554 }
555
Colin Cross71fc84c2010-06-07 20:49:46 -0700556 seq_printf(s, "%*s%c%c%-*s %-6s %-3d %-8s %-10lu\n",
557 level * 3 + 1, "",
558 c->rate > c->max_rate ? '!' : ' ',
559 !c->set ? '*' : ' ',
Colin Crossd8611962010-01-28 16:40:29 -0800560 30 - level * 3, c->name,
561 state, c->refcnt, div, c->rate);
562 list_for_each_entry_safe(child, safe, &c->children, sibling) {
563 clock_tree_show_one(s, child, level + 1);
564 }
565}
566
567static int clock_tree_show(struct seq_file *s, void *data)
568{
569 struct clk *c;
570 unsigned long flags;
Colin Cross71fc84c2010-06-07 20:49:46 -0700571 seq_printf(s, " clock state ref div rate\n");
572 seq_printf(s, "--------------------------------------------------------------\n");
Colin Crossd8611962010-01-28 16:40:29 -0800573 spin_lock_irqsave(&clock_lock, flags);
574 list_for_each_entry(c, &clocks, node)
575 if (c->parent == NULL)
576 clock_tree_show_one(s, c, 0);
577 spin_unlock_irqrestore(&clock_lock, flags);
578 return 0;
579}
580
581static int clock_tree_open(struct inode *inode, struct file *file)
582{
583 return single_open(file, clock_tree_show, inode->i_private);
584}
585
586static const struct file_operations clock_tree_fops = {
587 .open = clock_tree_open,
588 .read = seq_read,
589 .llseek = seq_lseek,
590 .release = single_release,
591};
592
593static int possible_parents_show(struct seq_file *s, void *data)
594{
595 struct clk *c = s->private;
596 int i;
597
598 for (i = 0; c->inputs[i].input; i++) {
599 char *first = (i == 0) ? "" : " ";
600 seq_printf(s, "%s%s", first, c->inputs[i].input->name);
601 }
602 seq_printf(s, "\n");
603 return 0;
604}
605
606static int possible_parents_open(struct inode *inode, struct file *file)
607{
608 return single_open(file, possible_parents_show, inode->i_private);
609}
610
611static const struct file_operations possible_parents_fops = {
612 .open = possible_parents_open,
613 .read = seq_read,
614 .llseek = seq_lseek,
615 .release = single_release,
616};
617
618static int clk_debugfs_register_one(struct clk *c)
619{
620 struct dentry *d, *child, *child_tmp;
621
622 d = debugfs_create_dir(c->name, clk_debugfs_root);
623 if (!d)
624 return -ENOMEM;
625 c->dent = d;
626
627 d = debugfs_create_u8("refcnt", S_IRUGO, c->dent, (u8 *)&c->refcnt);
628 if (!d)
629 goto err_out;
630
631 d = debugfs_create_u32("rate", S_IRUGO, c->dent, (u32 *)&c->rate);
632 if (!d)
633 goto err_out;
634
635 d = debugfs_create_x32("flags", S_IRUGO, c->dent, (u32 *)&c->flags);
636 if (!d)
637 goto err_out;
638
639 if (c->inputs) {
640 d = debugfs_create_file("possible_parents", S_IRUGO, c->dent,
641 c, &possible_parents_fops);
642 if (!d)
643 goto err_out;
644 }
645
646 return 0;
647
648err_out:
649 d = c->dent;
650 list_for_each_entry_safe(child, child_tmp, &d->d_subdirs, d_u.d_child)
651 debugfs_remove(child);
652 debugfs_remove(c->dent);
653 return -ENOMEM;
654}
655
656static int clk_debugfs_register(struct clk *c)
657{
658 int err;
659 struct clk *pa = c->parent;
660
661 if (pa && !pa->dent) {
662 err = clk_debugfs_register(pa);
663 if (err)
664 return err;
665 }
666
667 if (!c->dent) {
668 err = clk_debugfs_register_one(c);
669 if (err)
670 return err;
671 }
672 return 0;
673}
674
675static int __init clk_debugfs_init(void)
676{
677 struct clk *c;
678 struct dentry *d;
679 int err = -ENOMEM;
680
681 d = debugfs_create_dir("clock", NULL);
682 if (!d)
683 return -ENOMEM;
684 clk_debugfs_root = d;
685
686 d = debugfs_create_file("clock_tree", S_IRUGO, clk_debugfs_root, NULL,
687 &clock_tree_fops);
688 if (!d)
689 goto err_out;
690
691 list_for_each_entry(c, &clocks, node) {
692 err = clk_debugfs_register(c);
693 if (err)
694 goto err_out;
695 }
696 return 0;
697err_out:
698 debugfs_remove_recursive(clk_debugfs_root);
699 return err;
700}
701
702late_initcall(clk_debugfs_init);
703#endif