3 * Copyright (C) 2010 Google, Inc.
6 * Colin Cross <ccross@google.com>
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.
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.
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>
31 static LIST_HEAD(clocks
);
33 static DEFINE_SPINLOCK(clock_lock
);
35 struct clk
*tegra_get_clock_by_name(const char *name
)
38 struct clk
*ret
= NULL
;
40 spin_lock_irqsave(&clock_lock
, flags
);
41 list_for_each_entry(c
, &clocks
, node
) {
42 if (strcmp(c
->name
, name
) == 0) {
47 spin_unlock_irqrestore(&clock_lock
, flags
);
51 int clk_reparent(struct clk
*c
, struct clk
*parent
)
53 pr_debug("%s: %s\n", __func__
, c
->name
);
54 if (c
->refcnt
&& c
->parent
)
55 clk_disable_locked(c
->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
);
64 static void propagate_rate(struct clk
*c
)
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
);
76 void clk_init(struct clk
*c
)
80 spin_lock_irqsave(&clock_lock
, flags
);
82 INIT_LIST_HEAD(&c
->children
);
83 INIT_LIST_HEAD(&c
->sibling
);
85 if (c
->ops
&& c
->ops
->init
)
88 list_add(&c
->node
, &clocks
);
91 list_add_tail(&c
->sibling
, &c
->parent
->children
);
93 spin_unlock_irqrestore(&clock_lock
, flags
);
96 int clk_enable_locked(struct clk
*c
)
99 pr_debug("%s: %s\n", __func__
, c
->name
);
100 if (c
->refcnt
== 0) {
102 ret
= clk_enable_locked(c
->parent
);
107 if (c
->ops
&& c
->ops
->enable
) {
108 ret
= c
->ops
->enable(c
);
111 clk_disable_locked(c
->parent
);
115 #ifdef CONFIG_DEBUG_FS
125 int clk_enable(struct clk
*c
)
129 spin_lock_irqsave(&clock_lock
, flags
);
130 ret
= clk_enable_locked(c
);
131 spin_unlock_irqrestore(&clock_lock
, flags
);
134 EXPORT_SYMBOL(clk_enable
);
136 void clk_disable_locked(struct clk
*c
)
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
);
143 if (c
->refcnt
== 1) {
144 if (c
->ops
&& c
->ops
->disable
)
148 clk_disable_locked(c
->parent
);
155 void clk_disable(struct clk
*c
)
158 spin_lock_irqsave(&clock_lock
, flags
);
159 clk_disable_locked(c
);
160 spin_unlock_irqrestore(&clock_lock
, flags
);
162 EXPORT_SYMBOL(clk_disable
);
164 int clk_set_parent_locked(struct clk
*c
, struct clk
*parent
)
168 pr_debug("%s: %s\n", __func__
, c
->name
);
170 if (!c
->ops
|| !c
->ops
->set_parent
)
173 ret
= c
->ops
->set_parent(c
, parent
);
183 int clk_set_parent(struct clk
*c
, struct clk
*parent
)
187 spin_lock_irqsave(&clock_lock
, flags
);
188 ret
= clk_set_parent_locked(c
, parent
);
189 spin_unlock_irqrestore(&clock_lock
, flags
);
192 EXPORT_SYMBOL(clk_set_parent
);
194 struct clk
*clk_get_parent(struct clk
*c
)
198 EXPORT_SYMBOL(clk_get_parent
);
200 int clk_set_rate(struct clk
*c
, unsigned long rate
)
205 spin_lock_irqsave(&clock_lock
, flags
);
207 pr_debug("%s: %s\n", __func__
, c
->name
);
209 if (c
->ops
&& c
->ops
->set_rate
)
210 ret
= c
->ops
->set_rate(c
, rate
);
216 spin_unlock_irqrestore(&clock_lock
, flags
);
220 EXPORT_SYMBOL(clk_set_rate
);
222 unsigned long clk_get_rate(struct clk
*c
)
227 spin_lock_irqsave(&clock_lock
, flags
);
229 pr_debug("%s: %s\n", __func__
, c
->name
);
233 spin_unlock_irqrestore(&clock_lock
, flags
);
236 EXPORT_SYMBOL(clk_get_rate
);
238 static int tegra_clk_init_one_from_table(struct tegra_clk_init_table
*table
)
245 c
= tegra_get_clock_by_name(table
->name
);
248 pr_warning("Unable to initialize clock %s\n",
254 p
= tegra_get_clock_by_name(table
->parent
);
256 pr_warning("Unable to find parent %s of clock %s\n",
257 table
->parent
, table
->name
);
261 if (c
->parent
!= p
) {
262 ret
= clk_set_parent(c
, p
);
264 pr_warning("Unable to set parent %s of clock %s: %d\n",
265 table
->parent
, table
->name
, ret
);
271 if (table
->rate
&& table
->rate
!= clk_get_rate(c
)) {
272 ret
= clk_set_rate(c
, table
->rate
);
274 pr_warning("Unable to set clock %s to rate %lu: %d\n",
275 table
->name
, table
->rate
, ret
);
280 if (table
->enabled
) {
283 pr_warning("Unable to enable clock %s: %d\n",
292 void tegra_clk_init_from_table(struct tegra_clk_init_table
*table
)
294 for (; table
->name
; table
++)
295 tegra_clk_init_one_from_table(table
);
297 EXPORT_SYMBOL(tegra_clk_init_from_table
);
299 void tegra_periph_reset_deassert(struct clk
*c
)
301 tegra2_periph_reset_deassert(c
);
303 EXPORT_SYMBOL(tegra_periph_reset_deassert
);
305 void tegra_periph_reset_assert(struct clk
*c
)
307 tegra2_periph_reset_assert(c
);
309 EXPORT_SYMBOL(tegra_periph_reset_assert
);
311 int __init
tegra_init_clock(void)
313 tegra2_init_clocks();
318 #ifdef CONFIG_DEBUG_FS
319 static struct dentry
*clk_debugfs_root
;
322 static void clock_tree_show_one(struct seq_file
*s
, struct clk
*c
, int level
)
326 const char *state
= "uninit";
331 else if (c
->state
== OFF
)
334 if (c
->mul
!= 0 && c
->div
!= 0) {
337 snprintf(div
, sizeof(div
), "x%d", c
->mul
/ c
->div
);
339 snprintf(div
, sizeof(div
), "%d%s", c
->div
/ c
->mul
,
340 (c
->div
% c
->mul
) ? ".5" : "");
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);
352 static int clock_tree_show(struct seq_file
*s
, void *data
)
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
);
366 static int clock_tree_open(struct inode
*inode
, struct file
*file
)
368 return single_open(file
, clock_tree_show
, inode
->i_private
);
371 static const struct file_operations clock_tree_fops
= {
372 .open
= clock_tree_open
,
375 .release
= single_release
,
378 static int possible_parents_show(struct seq_file
*s
, void *data
)
380 struct clk
*c
= s
->private;
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
);
391 static int possible_parents_open(struct inode
*inode
, struct file
*file
)
393 return single_open(file
, possible_parents_show
, inode
->i_private
);
396 static const struct file_operations possible_parents_fops
= {
397 .open
= possible_parents_open
,
400 .release
= single_release
,
403 static int clk_debugfs_register_one(struct clk
*c
)
405 struct dentry
*d
, *child
, *child_tmp
;
407 d
= debugfs_create_dir(c
->name
, clk_debugfs_root
);
412 d
= debugfs_create_u8("refcnt", S_IRUGO
, c
->dent
, (u8
*)&c
->refcnt
);
416 d
= debugfs_create_u32("rate", S_IRUGO
, c
->dent
, (u32
*)&c
->rate
);
420 d
= debugfs_create_x32("flags", S_IRUGO
, c
->dent
, (u32
*)&c
->flags
);
425 d
= debugfs_create_file("possible_parents", S_IRUGO
, c
->dent
,
426 c
, &possible_parents_fops
);
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
);
441 static int clk_debugfs_register(struct clk
*c
)
444 struct clk
*pa
= c
->parent
;
446 if (pa
&& !pa
->dent
) {
447 err
= clk_debugfs_register(pa
);
453 err
= clk_debugfs_register_one(c
);
460 static int __init
clk_debugfs_init(void)
466 d
= debugfs_create_dir("clock", NULL
);
469 clk_debugfs_root
= d
;
471 d
= debugfs_create_file("clock_tree", S_IRUGO
, clk_debugfs_root
, NULL
,
476 list_for_each_entry(c
, &clocks
, node
) {
477 err
= clk_debugfs_register(c
);
483 debugfs_remove_recursive(clk_debugfs_root
);
487 late_initcall(clk_debugfs_init
);