diff options
Diffstat (limited to 'arch/arm/plat-omap/clock.c')
-rw-r--r-- | arch/arm/plat-omap/clock.c | 128 |
1 files changed, 92 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) */ | ||