diff options
author | Hiroshi DOYU <Hiroshi.DOYU@nokia.com> | 2008-07-03 05:24:41 -0400 |
---|---|---|
committer | Tony Lindgren <tony@atomide.com> | 2008-07-03 05:24:41 -0400 |
commit | 137b3ee27ab1b27dba081542476054836978ca45 (patch) | |
tree | 53857cbfa413b112a1fc60d364e9f1d3b2e8591f | |
parent | 44f78f43b349d19d378a996c4a2d9fcdff771b1e (diff) |
ARM: OMAP: CLKFW: Initial debugfs support for omap clock framework
debugfs can provide the infrastructure to trace the dependencies of
clock tree hierarchy quite visibly. This patch enables to keep track
of clock tree hierarchy and expose their attributes under each clock
directry as below:
omap:~# tree -d -L 2 /debug/clock/omap_32k_fck/
/debug/clock/omap_32k_fck/
|-- gpt10_fck
|-- gpt11_fck
|-- gpt1_fck
|-- per_32k_alwon_fck
| |-- gpio2_fck
| |-- gpio3_fck
| |-- gpio4_fck
| |-- gpio5_fck
| |-- gpio6_fck
| `-- wdt3_fck
|-- ts_fck
`-- wkup_32k_fck
|-- gpio1_fck
`-- wdt2_fck
14 directories
omap:~# tree /debug/clock/omap_32k_fck/gpt10_fck/
/debug/clock/omap_32k_fck/gpt10_fck/
|-- flags
|-- rate
`-- usecount
0 directories, 3 files
Although, compared with David Brownell's small patch, this may look
bit overkilling, I expect that this debugfs can deal with other PRCM
complexities at the same time. For example, powerdomain dependencies
can be expressed by using symbolic links of these clocks if
powerdomain supports dubgfs as well.
Signed-off-by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
-rw-r--r-- | arch/arm/plat-omap/clock.c | 128 | ||||
-rw-r--r-- | include/asm-arm/arch-omap/clock.h | 3 |
2 files changed, 95 insertions, 36 deletions
diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c index 2db5580048d8..c2e741de0203 100644 --- a/arch/arm/plat-omap/clock.c +++ b/arch/arm/plat-omap/clock.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/arm/plat-omap/clock.c | 2 | * linux/arch/arm/plat-omap/clock.c |
3 | * | 3 | * |
4 | * Copyright (C) 2004 - 2005 Nokia corporation | 4 | * Copyright (C) 2004 - 2008 Nokia corporation |
5 | * Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com> | 5 | * Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com> |
6 | * | 6 | * |
7 | * Modified for omap shared clock framework by Tony Lindgren <tony@atomide.com> | 7 | * Modified for omap shared clock framework by Tony Lindgren <tony@atomide.com> |
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/mutex.h> | 22 | #include <linux/mutex.h> |
23 | #include <linux/platform_device.h> | 23 | #include <linux/platform_device.h> |
24 | #include <linux/cpufreq.h> | 24 | #include <linux/cpufreq.h> |
25 | #include <linux/debugfs.h> | ||
25 | 26 | ||
26 | #include <asm/io.h> | 27 | #include <asm/io.h> |
27 | 28 | ||
@@ -33,41 +34,6 @@ static DEFINE_SPINLOCK(clockfw_lock); | |||
33 | 34 | ||
34 | static struct clk_functions *arch_clock; | 35 | static struct clk_functions *arch_clock; |
35 | 36 | ||
36 | #ifdef CONFIG_PM_DEBUG | ||
37 | |||
38 | static void print_parents(struct clk *clk) | ||
39 | { | ||
40 | struct clk *p; | ||
41 | int printed = 0; | ||
42 | |||
43 | list_for_each_entry(p, &clocks, node) { | ||
44 | if (p->parent == clk && p->usecount) { | ||
45 | if (!clk->usecount && !printed) { | ||
46 | printk("MISMATCH: %s\n", clk->name); | ||
47 | printed = 1; | ||
48 | } | ||
49 | printk("\t%-15s\n", p->name); | ||
50 | } | ||
51 | } | ||
52 | } | ||
53 | |||
54 | void clk_print_usecounts(void) | ||
55 | { | ||
56 | unsigned long flags; | ||
57 | struct clk *p; | ||
58 | |||
59 | spin_lock_irqsave(&clockfw_lock, flags); | ||
60 | list_for_each_entry(p, &clocks, node) { | ||
61 | if (p->usecount) | ||
62 | printk("%-15s: %d\n", p->name, p->usecount); | ||
63 | print_parents(p); | ||
64 | |||
65 | } | ||
66 | spin_unlock_irqrestore(&clockfw_lock, flags); | ||
67 | } | ||
68 | |||
69 | #endif | ||
70 | |||
71 | /*------------------------------------------------------------------------- | 37 | /*------------------------------------------------------------------------- |
72 | * Standard clock functions defined in include/linux/clk.h | 38 | * Standard clock functions defined in include/linux/clk.h |
73 | *-------------------------------------------------------------------------*/ | 39 | *-------------------------------------------------------------------------*/ |
@@ -446,3 +412,93 @@ int __init clk_init(struct clk_functions * custom_clocks) | |||
446 | return 0; | 412 | return 0; |
447 | } | 413 | } |
448 | 414 | ||
415 | #if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS) | ||
416 | /* | ||
417 | * debugfs support to trace clock tree hierarchy and attributes | ||
418 | */ | ||
419 | static struct dentry *clk_debugfs_root; | ||
420 | |||
421 | static int clk_debugfs_register_one(struct clk *c) | ||
422 | { | ||
423 | int err; | ||
424 | struct dentry *d, *child; | ||
425 | struct clk *pa = c->parent; | ||
426 | char s[255]; | ||
427 | char *p = s; | ||
428 | |||
429 | p += sprintf(p, "%s", c->name); | ||
430 | if (c->id != 0) | ||
431 | sprintf(p, ":%d", c->id); | ||
432 | d = debugfs_create_dir(s, pa ? pa->dent : clk_debugfs_root); | ||
433 | if (IS_ERR(d)) | ||
434 | return PTR_ERR(d); | ||
435 | c->dent = d; | ||
436 | |||
437 | d = debugfs_create_u8("usecount", S_IRUGO, c->dent, (u8 *)&c->usecount); | ||
438 | if (IS_ERR(d)) { | ||
439 | err = PTR_ERR(d); | ||
440 | goto err_out; | ||
441 | } | ||
442 | d = debugfs_create_u32("rate", S_IRUGO, c->dent, (u32 *)&c->rate); | ||
443 | if (IS_ERR(d)) { | ||
444 | err = PTR_ERR(d); | ||
445 | goto err_out; | ||
446 | } | ||
447 | d = debugfs_create_x32("flags", S_IRUGO, c->dent, (u32 *)&c->flags); | ||
448 | if (IS_ERR(d)) { | ||
449 | err = PTR_ERR(d); | ||
450 | goto err_out; | ||
451 | } | ||
452 | return 0; | ||
453 | |||
454 | err_out: | ||
455 | d = c->dent; | ||
456 | list_for_each_entry(child, &d->d_subdirs, d_u.d_child) | ||
457 | debugfs_remove(child); | ||
458 | debugfs_remove(c->dent); | ||
459 | return err; | ||
460 | } | ||
461 | |||
462 | static int clk_debugfs_register(struct clk *c) | ||
463 | { | ||
464 | int err; | ||
465 | struct clk *pa = c->parent; | ||
466 | |||
467 | if (pa && !pa->dent) { | ||
468 | err = clk_debugfs_register(pa); | ||
469 | if (err) | ||
470 | return err; | ||
471 | } | ||
472 | |||
473 | if (!c->dent) { | ||
474 | err = clk_debugfs_register_one(c); | ||
475 | if (err) | ||
476 | return err; | ||
477 | } | ||
478 | return 0; | ||
479 | } | ||
480 | |||
481 | static int __init clk_debugfs_init(void) | ||
482 | { | ||
483 | struct clk *c; | ||
484 | struct dentry *d; | ||
485 | int err; | ||
486 | |||
487 | d = debugfs_create_dir("clock", NULL); | ||
488 | if (IS_ERR(d)) | ||
489 | return PTR_ERR(d); | ||
490 | clk_debugfs_root = d; | ||
491 | |||
492 | list_for_each_entry(c, &clocks, node) { | ||
493 | err = clk_debugfs_register(c); | ||
494 | if (err) | ||
495 | goto err_out; | ||
496 | } | ||
497 | return 0; | ||
498 | err_out: | ||
499 | debugfs_remove(clk_debugfs_root); /* REVISIT: Cleanup correctly */ | ||
500 | return err; | ||
501 | } | ||
502 | late_initcall(clk_debugfs_init); | ||
503 | |||
504 | #endif /* defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS) */ | ||
diff --git a/include/asm-arm/arch-omap/clock.h b/include/asm-arm/arch-omap/clock.h index 12a5e4de9518..8490fbba39d1 100644 --- a/include/asm-arm/arch-omap/clock.h +++ b/include/asm-arm/arch-omap/clock.h | |||
@@ -71,6 +71,9 @@ struct clk { | |||
71 | __u8 rate_offset; | 71 | __u8 rate_offset; |
72 | __u8 src_offset; | 72 | __u8 src_offset; |
73 | #endif | 73 | #endif |
74 | #if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS) | ||
75 | struct dentry *dent; /* For visible tree hierarchy */ | ||
76 | #endif | ||
74 | }; | 77 | }; |
75 | 78 | ||
76 | struct cpufreq_frequency_table; | 79 | struct cpufreq_frequency_table; |