Adding linaro-dev to cc. Kernel consolidation WG might have comments.
On Tue, Oct 12, 2010 at 9:04 AM, Yong Shen <[email protected]> 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:
> 1. 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
>
_______________________________________________
linaro-dev mailing list
[email protected]
http://lists.linaro.org/mailman/listinfo/linaro-dev