On 10 Nov 17, Yong Shen wrote: > Hi Jeremy, > > Great ideal to make it beyond ARM specific. > Below is the updated patch as per your comments. > > From 5a3e2d3bf577e3059c9254a61d671910ab170623 Mon Sep 17 00:00:00 2001 > From: Yong Shen <yong.s...@linaro.org> > Date: Tue, 16 Nov 2010 15:00:28 +0800 > Subject: [PATCH] export clock debug information to user space > > create a tree-like directory structure in debugfs so user space tools like > powerdebug can generate readable clock information. > more functions tend to be add in, like individual clock enable/disable by > writing to this debugfs. > > Signed-off-by: Yong Shen <yong.s...@linaro.org> > --- > arch/arm/common/Kconfig | 7 +++ > arch/arm/common/clkdev.c | 28 +++++++++++++ > arch/arm/plat-mxc/clock-common.c | 5 ++- > include/linux/clk.h | 19 ++++++++- > kernel/clk.c | 83 > ++++++++++++++++++++++++++++++++++++++ > 5 files changed, 139 insertions(+), 3 deletions(-) > > diff --git a/arch/arm/common/Kconfig b/arch/arm/common/Kconfig > index 0a34c81..0300c95 100644 > --- a/arch/arm/common/Kconfig > +++ b/arch/arm/common/Kconfig > @@ -41,3 +41,10 @@ config SHARP_SCOOP > config COMMON_CLKDEV > bool > select HAVE_CLK > + > +config CLK_DEBUG > + bool "clock debug information export to user space" > + depends on COMMON_CLKDEV && PM_DEBUG && DEBUG_FS > + default n > + help > + export clk debug information to user space > diff --git a/arch/arm/common/clkdev.c b/arch/arm/common/clkdev.c > index 9e4c4d9..5f4a309 100644 > --- a/arch/arm/common/clkdev.c > +++ b/arch/arm/common/clkdev.c > @@ -19,6 +19,9 @@ > #include <linux/mutex.h> > #include <linux/clk.h> > #include <linux/slab.h> > +#ifdef CONFIG_CLK_DEBUG > +#include <linux/debugfs.h> > +#endif > > #include <asm/clkdev.h> > > @@ -186,3 +189,28 @@ void clkdev_drop(struct clk_lookup *cl) > kfree(cl); > } > EXPORT_SYMBOL(clkdev_drop); > + > +#ifdef CONFIG_CLK_DEBUG > +static int __init clk_debugfs_init(void) > +{ > + struct clk_lookup *cl; > + struct dentry *d; > + int err; > + > + d = debugfs_create_dir("clocks", NULL); > + if (!d) > + return -ENOMEM; > +
Is mutt going crazy or is the indentation here completely off? The same thing throughout the patch. > + list_for_each_entry(cl, &clocks, node) { > + err = clk_debugfs_register(cl->clk, d); > + if (err) > + goto err_out; > + } > + return 0; > +err_out: > + debugfs_remove_recursive(d); > + return err; > +} > +late_initcall(clk_debugfs_init); > + > +#endif > diff --git a/arch/arm/plat-mxc/clock-common.c > b/arch/arm/plat-mxc/clock-common.c > index 8911813..20d38a8 100644 > --- a/arch/arm/plat-mxc/clock-common.c > +++ b/arch/arm/plat-mxc/clock-common.c > @@ -97,7 +97,10 @@ unsigned long clk_mxc_get_rate(struct clk *_clk) > if (clk->get_rate) > return clk->get_rate(clk); > > - return clk_get_rate(clk->parent); > + if (clk->parent) > + return clk_get_rate(clk->parent); > + > + return 0; > } > > /* Round the requested clock rate to the nearest supported > diff --git a/include/linux/clk.h b/include/linux/clk.h > index 56416b7..751c086 100644 > --- a/include/linux/clk.h > +++ b/include/linux/clk.h > @@ -44,16 +44,28 @@ struct device; > * registered with the arch-specific clock management code; the clock > driver > * code does not need to handle these. > */ > +#define CLK_NAME_LEN 32 > struct clk { > const struct clk_ops *ops; > unsigned int enable_count; > struct mutex mutex; > +#ifdef CONFIG_CLK_DEBUG > + char name[CLK_NAME_LEN]; > + struct dentry *dentry; > +#endif > }; > > -#define INIT_CLK(name, o) { \ > +#ifdef CONFIG_CLK_DEBUG > +#define __INIT_CLK_DEBUG(n) .name = #n, > +#else > +#define __INIT_CLK_DEBUG(n) > +#endif > + > +#define INIT_CLK(clk_name, o) { \ > .ops = &o, \ > .enable_count = 0, \ > - .mutex = __MUTEX_INITIALIZER(name.mutex), \ > + .mutex = __MUTEX_INITIALIZER(clk_name.mutex), \ > + __INIT_CLK_DEBUG(clk_name) \ > } > > struct clk_ops { > @@ -245,4 +257,7 @@ struct clk *clk_get_sys(const char *dev_id, const char > *con_id); > int clk_add_alias(const char *alias, const char *alias_dev_name, char *id, > struct device *dev); > > +#ifdef CONFIG_CLK_DEBUG > +int clk_debugfs_register(struct clk *clk, struct dentry *root); > +#endif > #endif > diff --git a/kernel/clk.c b/kernel/clk.c > index 32f25ef..97e5e66 100644 > --- a/kernel/clk.c > +++ b/kernel/clk.c > @@ -12,6 +12,10 @@ > #include <linux/mutex.h> > #include <linux/module.h> > > +#ifdef CONFIG_CLK_DEBUG > +#include <linux/debugfs.h> > +#endif > + > int clk_enable(struct clk *clk) > { > int ret = 0; > @@ -113,3 +117,82 @@ struct clk_ops clk_fixed_ops = { > .get_rate = clk_fixed_get_rate, > }; > EXPORT_SYMBOL_GPL(clk_fixed_ops); > + > +#ifdef CONFIG_CLK_DEBUG > +/* > + * debugfs support to trace clock tree hierarchy and attributes > + */ > +static int clk_debug_rate_get(void *data, u64 *val) > +{ > + struct clk *clk = data; > + > + *val = (u64)clk_get_rate(clk); > + return 0; > +} > +DEFINE_SIMPLE_ATTRIBUTE(clk_debug_rate_fops, clk_debug_rate_get, NULL, > + "%llu\n"); > + > + > +static int clk_debugfs_register_one(struct clk *clk, struct dentry *root) > +{ > + int err; > + struct dentry *d, *child, *child_tmp; > + struct clk *pa = clk_get_parent(clk); > + > + if (pa && !IS_ERR(pa)) > + d = debugfs_create_dir(clk->name, pa->dentry); > + else > + d = debugfs_create_dir(clk->name, root); > + > + if (!d) > + return -ENOMEM; > + > + clk->dentry = d; > + > + d = debugfs_create_u32("enable_count", S_IRUGO, clk->dentry, > + (u32 *)&clk->enable_count); > + if (!d) { > + err = -ENOMEM; > + goto err_out; > + } > + > + d = debugfs_create_file("rate", S_IRUGO, clk->dentry, (void *)clk, > + &clk_debug_rate_fops); > + if (!d) { > + err = -ENOMEM; > + goto err_out; > + } > + > + return 0; > + > +err_out: > + d = clk->dentry; > + list_for_each_entry_safe(child, child_tmp, &d->d_subdirs, d_u.d_child) > + debugfs_remove(child); > + debugfs_remove(clk->dentry); > + return err; > +} > + > +int clk_debugfs_register(struct clk *clk, struct dentry *root) > +{ > + int err; > + struct clk *pa; > + > + pa = clk_get_parent(clk); > + > + if (pa && !IS_ERR(pa) && !pa->dentry) { > + err = clk_debugfs_register(pa, root); > + if (err) > + return err; > + } > + > + if (!clk->dentry) { > + err = clk_debugfs_register_one(clk, root); > + if (err) > + return err; > + } > + return 0; > +} > +EXPORT_SYMBOL_GPL(clk_debugfs_register); > + > +#endif /* defined CONFIG_CLK_DEBUG */ > -- > 1.7.0.4 > > Cheers > Yong > > On Tue, Nov 16, 2010 at 5:16 PM, Jeremy Kerr <jeremy.k...@canonical.com>wrote: > > > Hi Yong, > > > > Looks good, just a couple of things: > > > > > diff --git a/arch/arm/common/clkdev.c b/arch/arm/common/clkdev.c > > > index 9e4c4d9..cf81e70 100644 > > > --- a/arch/arm/common/clkdev.c > > > +++ b/arch/arm/common/clkdev.c > > > > Why not do this in the core clock code (kernel/clk.c) instead? No need to > > make > > it ARM-specific. > > > > > diff --git a/arch/arm/plat-mxc/clock-common.c > > > b/arch/arm/plat-mxc/clock-common.c > > > index 8911813..20d38a8 100644 > > > --- a/arch/arm/plat-mxc/clock-common.c > > > +++ b/arch/arm/plat-mxc/clock-common.c > > > @@ -97,7 +97,10 @@ unsigned long clk_mxc_get_rate(struct clk *_clk) > > > if (clk->get_rate) > > > return clk->get_rate(clk); > > > > > > - return clk_get_rate(clk->parent); > > > + if (clk->parent) > > > + return clk_get_rate(clk->parent); > > > + > > > + return 0; > > > } > > > > > > /* Round the requested clock rate to the nearest supported > > > diff --git a/include/linux/clk.h b/include/linux/clk.h > > > index 56416b7..1102c2c 100644 > > > --- a/include/linux/clk.h > > > +++ b/include/linux/clk.h > > > @@ -44,17 +44,31 @@ struct device; > > > * registered with the arch-specific clock management code; the clock > > > driver > > > * code does not need to handle these. > > > */ > > > +#define CLK_NAME_LEN 16 > > > > We might need more than 16 bytes here; 32 should be fine. > > > > > struct clk { > > > const struct clk_ops *ops; > > > unsigned int enable_count; > > > struct mutex mutex; > > > +#ifdef CONFIG_CLK_DEBUG > > > + char name[CLK_NAME_LEN]; > > > + struct dentry *dentry; > > > +#endif > > > }; > > > > > > -#define INIT_CLK(name, o) { \ > > > +#ifndef CONFIG_CLK_DEBUG > > > +#define INIT_CLK(clk_name, o) { \ > > > .ops = &o, \ > > > .enable_count = 0, \ > > > - .mutex = __MUTEX_INITIALIZER(name.mutex), \ > > > + .mutex = __MUTEX_INITIALIZER(clk_name.mutex), \ > > > } > > > +#else > > > +#define INIT_CLK(clk_name, o) { \ > > > + .ops = &o, \ > > > + .enable_count = 0, \ > > > + .mutex = __MUTEX_INITIALIZER(clk_name.mutex), \ > > > + .name = #clk_name, \ > > > +} > > > +#endif > > > > How about this instead: > > > > +#ifdef CONFIG_CLK_DEBUG > > +#define __INIT_CLK_DEBUG(n) .name = #n, > > +#else > > +#define __INIT_CLK_DEBUG(n) > > +#endif > > + > > /* static initialiser for non-atomic clocks */ > > #define INIT_CLK(name, o) { \ > > .ops = &o, \ > > .enable_count = 0, \ > > .flags = 0, \ > > .lock.mutex = __MUTEX_INITIALIZER(name.lock.mutex), \ > > + __INIT_CLK_DEBUG(name) \ > > } > > > > /* static initialiser for atomic clocks */ > > > > - otherwise, you're going to need to add another definition of > > INIT_CLK_ATOMIC > > too, giving four in total. > > > > Cheers, > > > > > > Jeremy > > > _______________________________________________ > linaro-dev mailing list > linaro-dev@lists.linaro.org > http://lists.linaro.org/mailman/listinfo/linaro-dev _______________________________________________ linaro-dev mailing list linaro-dev@lists.linaro.org http://lists.linaro.org/mailman/listinfo/linaro-dev