Adding linaro-dev to cc. Kernel consolidation WG might have comments.
On Tue, Oct 12, 2010 at 9:04 AM, Yong Shen yong.shen@linaro.org wrote:
Hi Amit and Jeremy,
This is not a patch review. But patch may better present my idea. Basically, I want to add some code in common clock code to export clock information, so every platform can benefit. This information is present in a tree-like pattern. Currently, each platform uses their own way to show clock info, which is hard to use a common user space tool to collect information. For this purpose, I need do the rest:
- Add a clock name check in the clkdev_add. We don't accept two clocks with
the same name to clkdev_add, do we? otherwise, it is impossible to create a tree-like structure under file system, cause no same names under a directory. 2. Recursive function creates the clock tree in debugfs, which referred omap's clock implementation. 3. Add interface needed to let mach related drivers to report their information. clk_get_rate is already there. Maybe we need clk_get_flags() and clk_get_usecount() and more.
Agreed, this functionality is necessary for common clk infrastructure to be useful.
We've also incorporated this functionality into a tool called powerdebug that'll show runtime state of the clock tree. This is very useful for driver developers.
/Amit
Below is the patch, please share your thoughts.
diff --git a/arch/arm/common/clkdev.c b/arch/arm/common/clkdev.c index e2b2bb6..2ec09ee 100644 --- a/arch/arm/common/clkdev.c +++ b/arch/arm/common/clkdev.c @@ -19,6 +19,7 @@ #include <linux/mutex.h> #include <linux/clk.h> #include <linux/slab.h> +#include <linux/debugfs.h>
#include <asm/clkdev.h> #include <mach/clkdev.h> @@ -95,6 +96,21 @@ EXPORT_SYMBOL(clk_put);
void clkdev_add(struct clk_lookup *cl) { + struct clk_lookup *p; + struct clk *clk = NULL;
+ list_for_each_entry(p, &clocks, node) { + if (p->dev_id) { + if (!cl->dev_id || strcmp(p->dev_id, cl->dev_id)) + continue; + } + if (p->con_id) { + if (!cl->con_id || strcmp(p->con_id, cl->con_id)) + continue; + }
+ return; + } mutex_lock(&clocks_mutex); list_add_tail(&cl->node, &clocks); mutex_unlock(&clocks_mutex); @@ -177,3 +193,131 @@ void clkdev_drop(struct clk_lookup *cl) kfree(cl); } EXPORT_SYMBOL(clkdev_drop);
+#if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS) +/*
- * debugfs support to trace clock tree hierarchy and attributes
- */
+static struct clk_lookup *clk_lookup_get_parent(struct clk *clk) +{ + struct clk_lookup *cl;
+ list_for_each_entry(cl, &clocks, node) { + if (cl->clk == clk_get_parent(clk)) + return cl; + }
+ return NULL; +} +static struct dentry *clk_debugfs_root;
+static int clk_debugfs_register_one(struct clk_lookup *cl) +{ + int err; + struct dentry *d, *child, *child_tmp; + struct clk_lookup *pa = clk_lookup_get_parent(cl->clk); + char s[255]; + char *p = s;
+ if (cl->dev_id && cl->con_id) + p += sprintf(p, "%s-%s", cl->dev_id, cl->con_id); + else if (cl->dev_id) + p += sprintf(p, "%s-NULL", cl->dev_id); + else if (cl->con_id) + p += sprintf(p, "NULL-%s", cl->con_id); + else + p += sprintf(p, "%s", "unknown");
+ printk("create dir %s, %s....\n", s, pa? "nonroot" : "root"); + d = debugfs_create_dir(s, pa ? pa->dent : clk_debugfs_root); + if (!d) { + printk("failed to create dir....\n"); + return -ENOMEM; + }
+ cl->dent = d;
+ if (cl->usecount != NULL) { + d = debugfs_create_u8("usecount", S_IRUGO, cl->dent, (u8 *)&cl->usecount); + if (!d) { + err = -ENOMEM; + goto err_out; + } + } + if (cl->rate) { + d = debugfs_create_u32("rate", S_IRUGO, cl->dent, (u32 *)&cl->rate); + if (!d) { + err = -ENOMEM; + goto err_out; + } + } + if (cl->flags) { + d = debugfs_create_x32("flags", S_IRUGO, cl->dent, (u32 *)&cl->flags); + if (!d) { + err = -ENOMEM; + goto err_out; + } + } + return 0;
+err_out: + printk("err out....\n"); + return -ENOMEM; + d = cl->dent; + list_for_each_entry_safe(child, child_tmp, &d->d_subdirs, d_u.d_child) + debugfs_remove(child); + debugfs_remove(cl->dent); + return err; +}
+static int clk_debugfs_register(struct clk_lookup *cl) +{ + int err; + struct clk_lookup *pa = clk_lookup_get_parent(cl->clk);
+ if (pa && !pa->dent) { + err = clk_debugfs_register(pa); + if (err) + return err; + }
+ if (!cl->dent) { + err = clk_debugfs_register_one(cl); + if (err) + return err; + } + return 0; +}
+static int __init clk_debugfs_init(void) +{ + struct clk_lookup *cl; + struct dentry *d; + int err;
+ d = debugfs_create_dir("clock", NULL); + if (!d) + return -ENOMEM; + clk_debugfs_root = d;
+ list_for_each_entry(cl, &clocks, node) { + //cl->usercount = clk_get_usercount(cl->clk); + //cl->flags = clk_get_flags(cl->clk); + cl->rate = clk_get_rate(cl->clk); + printk("dev name %s, con name %s\n",\ + cl->dev_id ? cl->dev_id : NULL,\ + cl->con_id ? cl->con_id : NULL); + err = clk_debugfs_register(cl); + if (err) + goto err_out; + } + return 0; +err_out: + printk("on my god ........\n"); + debugfs_remove_recursive(clk_debugfs_root); + return err; +} +late_initcall(clk_debugfs_init);
+#endif /* defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS) */ diff --git a/arch/arm/include/asm/clkdev.h b/arch/arm/include/asm/clkdev.h index b56c138..51734ef 100644 --- a/arch/arm/include/asm/clkdev.h +++ b/arch/arm/include/asm/clkdev.h @@ -20,6 +20,13 @@ struct clk_lookup { const char *dev_id; const char *con_id; struct clk *clk;
+#if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS) + short usecount; + unsigned short flags; + unsigned long rate; + struct dentry *dent; +#endif };
struct clk_lookup *clkdev_alloc(struct clk *clk, const char *con_id
This is the information output from powerdebug after I apply the patch to mx51 kernel. / |-- fec.0-NULL <flags=0x0:rate=66500000:usecount=0> |-- NULL-gpt <flags=0x0:rate=8000000:usecount=0> |-- NULL-cko1 <flags=0x0:rate=8000000:usecount=0> |-- mxc_w1.0-NULL <flags=0x0:rate=8000000:usecount=0> |-- pata_fsl-NULL <flags=0x0:rate=66500000:usecount=0> |-- NULL-usb_clk <flags=0x0:rate=60000000:usecount=0> |-- NULL-usb_utmi_clk <flags=0x0:rate=60000000:usecount=0> |-- NULL-usb_ahb_clk <flags=0x0:rate=66500000:usecount=0> |-- NULL-iim_clk <flags=0x0:rate=66500000:usecount=0> |-- mxc_spi.2-NULL <flags=0x0:rate=66500000:usecount=0> |-- mxc_spi.1-NULL <flags=0x0:rate=6000000:usecount=0> |-- mxc_spi.0-NULL <flags=0x0:rate=6000000:usecount=0> |-- mxc_pwm.1-NULL <flags=0x0:rate=8000000:usecount=0> |-- mxc_pwm.0-NULL <flags=0x0:rate=8000000:usecount=0> |-- imx-i2c.1-NULL <flags=0x0:rate=8000000:usecount=0> |-- imx-i2c.0-NULL <flags=0x0:rate=8000000:usecount=0> |-- mxcintuart.2-NULL <flags=0x0:rate=66666666:usecount=0> |-- mxcintuart.1-NULL <flags=0x0:rate=66666666:usecount=0> |-- mxcintuart.0-NULL <flags=0x0:rate=66666666:usecount=0> |-- mxc_sdma-sdma_ipg_clk <flags=0x0:rate=66500000:usecount=0> |-- NULL-gpc_dvfs_clk <flags=0x0:rate=66500000:usecount=0> |-- NULL-ckil <flags=0x0:rate=32768:usecount=0> | |-- mxc_rtc.0-NULL <flags=0x0:rate=32768:usecount=0> | |-- NULL-lpsr_clk <flags=0x0:rate=32768:usecount=0> |-- NULL-ckih2 <flags=0x0:rate=24576000:usecount=0> |-- NULL-ckih <flags=0x0:rate=22579200:usecount=0> |-- NULL-osc <flags=0x0:rate=24000000:usecount=0> | |-- NULL-spdif_xtal_clk <flags=0x0:rate=24000000:usecount=0> | | |-- mxc_alsa_spdif.0-NULL <flags=0x0:rate=24000000:usecount=0> | |-- NULL-usb_phy1_clk <flags=0x0:rate=24000000:usecount=0> | |-- NULL-lp_apm <flags=0x0:rate=24000000:usecount=0> | | |-- NULL-ssi_lp_apm_clk <flags=0x0:rate=24000000:usecount=0> | | | |-- mxc_ssi.1-NULL <flags=0x0:rate=12000000:usecount=0> | | | | |-- NULL-ssi_ext2_clk <flags=0x0:rate=12000000:usecount=0> | | | |-- mxc_ssi.0-NULL <flags=0x0:rate=12000000:usecount=0> | | | | |-- NULL-ssi_ext1_clk <flags=0x0:rate=12000000:usecount=0> | |-- NULL-pll3 <flags=0x0:rate=216000000:usecount=0> | | |-- mxc_sim.0-NULL <flags=0x0:rate=54000000:usecount=0> | | |-- mxc_i2c_hs.3-NULL <flags=0x0:rate=54000000:usecount=0> | | |-- tve.0-NULL <flags=0x0:rate=216000000:usecount=0> | | |-- NULL-csi_mclk2 <flags=0x0:rate=54000000:usecount=0> | | |-- NULL-csi_mclk1 <flags=0x0:rate=54000000:usecount=0> | | |-- NULL-ipu_di1_clk <flags=0x0:rate=27000000:usecount=0> | | |-- NULL-ipu_di0_clk <flags=0x0:rate=27000000:usecount=0> | |-- NULL-pll2 <flags=0x0:rate=665000000:usecount=0> | | |-- mxsdhci.1-NULL <flags=0x0:rate=166250000:usecount=0> | | |-- mxsdhci.0-NULL <flags=0x0:rate=166250000:usecount=0> | | | |-- mxsdhci.3-NULL <flags=0x0:rate=166250000:usecount=0> | | | |-- mxsdhci.2-NULL <flags=0x0:rate=166250000:usecount=0>/q | | |-- NULL-usboh3_clk <flags=0x0:rate=66500000:usecount=0> | | |-- NULL-main_bus_clk <flags=0x0:rate=665000000:usecount=0> | | | |-- NULL-ahb_clk <flags=0x0:rate=133000000:usecount=0> | | | | |-- mxc_scc.0-NULL <flags=0x0:rate=133000000:usecount=0> | | | | |-- NULL-sahara_clk <flags=0x0:rate=133000000:usecount=0> | | | | |-- NULL-emi_intr_clk.1 <flags=0x0:rate=133000000:usecount=0> | | | | |-- NULL-emi_intr_clk.0 <flags=0x0:rate=133000000:usecount=0> | | | | |-- mxc_sdma-sdma_ahb_clk <flags=0x0:rate=133000000:usecount=0> | | | | |-- NULL-emi_slow_clk <flags=0x0:rate=133000000:usecount=0> | | | | | |-- NULL-emi_enfc_clk <flags=0x0:rate=33250000:usecount=0> | | | | | |-- NULL-nfc_clk <flags=0x0:rate=33250000:usecount=0> | | | | |-- NULL-ahb_max_clk <flags=0x0:rate=133000000:usecount=0> | | | |-- NULL-axi_b_clk <flags=0x0:rate=133000000:usecount=0> | | | | |-- mxc_vpu.0-NULL <flags=0x0:rate=133000000:usecount=0> | | | | |-- NULL-ipu_clk <flags=0x0:rate=133000000:usecount=0> | | | | | |-- NULL-mipi_hsp_clk <flags=0x0:rate=133000000:usecount=0> | | | | |-- NULL-vpu_core_clk <flags=0x0:rate=133000000:usecount=0> | | | | |-- NULL-vpu_clk <flags=0x0:rate=133000000:usecount=0> | | | |-- NULL-axi_a_clk <flags=0x0:rate=166250000:usecount=0> | | | | |-- NULL-gpu2d_clk <flags=0x0:rate=166250000:usecount=0> | | | | |-- NULL-garb_clk <flags=0x0:rate=166250000:usecount=0> | | | | |-- NULL-gpu3d_clk <flags=0x0:rate=166250000:usecount=0> | |-- NULL-pll1_main_clk <flags=0x0:rate=800000000:usecount=0> | | |-- NULL-pll1_sw_clk <flags=0x0:rate=800000000:usecount=0> | | | |-- NULL-ddr_hf_clk <flags=0x0:rate=0:usecount=0> | | | | |-- NULL-ddr_clk <flags=0x0:rate=200000000:usecount=0> | | | | | |-- NULL-emi_fast_clk <flags=0x0:rate=200000000:usecount=0> | | | |-- NULL-periph_apm_clk <flags=0x0:rate=800000000:usecount=0> | | | |-- NULL-cpu_clk <flags=0x0:rate=800000000:usecount=0>
Yong