* [PATCH 1/1] ARM: OMAP: CLKFW: Initial sysfs support for omap clock framework
@ 2008-04-16 8:44 Hiroshi DOYU
2008-04-16 8:57 ` Hiroshi DOYU
2008-04-16 16:58 ` David Brownell
0 siblings, 2 replies; 21+ messages in thread
From: Hiroshi DOYU @ 2008-04-16 8:44 UTC (permalink / raw)
To: linux-omap; +Cc: Hiroshi DOYU
Sysfs 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 /sys/kernel/clock/omap_32k_fck/
/sys/kernel/clock/omap_32k_fck/
|-- gpt10_fck
|-- gpt11_fck
|-- gpt1_fck
|-- per_32k_alwon_fck
| |-- gpio3_fck
| |-- gpio4_fck
| |-- gpio5_fck
| `-- gpio6_fck
|-- ts_fck
`-- wkup_32k_fck
`-- gpio1_fck
11 directories
omap:~# tree /sys/kernel/clock/omap_32k_fck/gpt10_fck
/sys/kernel/clock/omap_32k_fck/gpt10_fck
|-- flags
|-- rate
`-- usecount
0 directories, 3 files
Signed-off-by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
---
arch/arm/plat-omap/clock.c | 153 +++++++++++++++++++++++++++++++++++++
include/asm-arm/arch-omap/clock.h | 2 +
2 files changed, 155 insertions(+), 0 deletions(-)
diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c
index 1bd8781..56c7dd2 100644
--- a/arch/arm/plat-omap/clock.c
+++ b/arch/arm/plat-omap/clock.c
@@ -33,6 +33,159 @@ static DEFINE_SPINLOCK(clockfw_lock);
static struct clk_functions *arch_clock;
+/*
+ * Sysfs support to trace clk tree hierarchy
+ */
+static struct kset *clock_kset;
+
+struct clk_attr {
+ struct attribute attr;
+ ssize_t (*show)(struct clk *clk, struct clk_attr *attr, char *buf);
+ ssize_t (*store)(struct clk *clk, struct clk_attr *attr,
+ const char *buf, size_t count);
+};
+#define to_clk_attr(x) container_of(x, struct clk_attr, attr)
+
+static ssize_t clk_attr_store(struct kobject *kobj, struct attribute *attr,
+ const char *buf, size_t count)
+{
+ struct clk_attr *ca;
+ struct clk *clk;
+
+ ca = to_clk_attr(attr);
+ clk = to_clk(kobj);
+
+ if (!ca->store)
+ return -EIO;
+ return ca->store(clk, ca, buf, count);
+}
+
+static ssize_t clk_attr_show(struct kobject *kobj, struct attribute *attr,
+ char *buf)
+{
+ struct clk_attr *ca;
+ struct clk *clk;
+
+ ca = to_clk_attr(attr);
+ clk = to_clk(kobj);
+
+ if (!ca->show)
+ return -EIO;
+ return ca->show(clk, ca, buf);
+}
+
+static struct sysfs_ops clk_sysfs_ops = {
+ .show = clk_attr_show,
+ .store = clk_attr_store,
+};
+
+static ssize_t attr_store(struct clk *clk, struct clk_attr *attr,
+ const char *buf, size_t count)
+{
+ unsigned long flags;
+ unsigned long val;
+ int err;
+
+ spin_lock_irqsave(&clockfw_lock, flags);
+ sscanf(buf, "%lx", &val);
+
+ if (strcmp(attr->attr.name, "rate") == 0) {
+ err = clk_set_rate(clk, val);
+ if (err)
+ count = -EIO;
+ }
+ spin_unlock_irqrestore(&clockfw_lock, flags);
+ return count;
+}
+
+static ssize_t attr_show(struct clk *clk, struct clk_attr *attr, char *buf)
+{
+ int n = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&clockfw_lock, flags);
+
+ if (strcmp(attr->attr.name, "rate") == 0)
+ n = sprintf(buf, "%lu\n", clk->rate);
+ else if (strcmp(attr->attr.name, "flags") == 0)
+ n = sprintf(buf, "0x%08x\n", clk->flags);
+ else if (strcmp(attr->attr.name, "usecount") == 0)
+ n = sprintf(buf, "%d\n", clk->usecount);
+
+ spin_unlock_irqrestore(&clockfw_lock, flags);
+ return n;
+}
+static struct clk_attr rate = __ATTR(rate, 0444, attr_show, attr_store);
+static struct clk_attr flags = __ATTR(flags, 0444, attr_show, NULL);
+static struct clk_attr usecount = __ATTR(usecount, 0444, attr_show, NULL);
+
+static struct attribute *clk_default_attrs[] = {
+ &rate.attr,
+ &flags.attr,
+ &usecount.attr,
+ NULL,
+};
+
+static void clk_release(struct kobject *kobj)
+{
+ /* REVISIT: Dynamic registration */
+}
+
+static struct kobj_type clk_ktype = {
+ .sysfs_ops = &clk_sysfs_ops,
+ .release = clk_release,
+ .default_attrs = clk_default_attrs,
+};
+
+static int clk_sysfs_register(struct clk *clk)
+{
+ struct clk *pa = clk->parent;
+
+ if (pa && !pa->kobj.state_initialized)
+ return clk_sysfs_register(pa);
+ else if (!clk->kobj.state_initialized) {
+ int err;
+ char name[KOBJ_NAME_LEN];
+ char *p = name;
+
+ clk->kobj.kset = clock_kset;
+ p += sprintf(name, "%s", clk->name);
+ if (clk->id != 0)
+ sprintf(p, "%d", clk->id);
+ err = kobject_init_and_add(&clk->kobj, &clk_ktype,
+ pa ? &pa->kobj : NULL, "%s", name);
+ return err;
+ }
+ return 0;
+}
+
+static int __init clk_sysfs_init(void)
+{
+ struct clk *clk;
+ int err;
+ struct list_head *entry;
+
+ clock_kset = kset_create_and_add("clock", NULL, kernel_kobj);
+ if (!clock_kset)
+ return -ENOMEM;
+
+ list_for_each_entry(clk, &clocks, node) {
+ err = clk_sysfs_register(clk);
+ if (err)
+ goto err_out;
+ }
+ return 0;
+
+err_out:
+ list_for_each(entry, &clock_kset->list) {
+ struct kobject *k = container_of(entry, struct kobject, entry);
+ kobject_del(k);
+ }
+ kset_unregister(clock_kset);
+ return err;
+}
+late_initcall(clk_sysfs_init);
+
#ifdef CONFIG_PM_DEBUG
static void print_parents(struct clk *clk)
diff --git a/include/asm-arm/arch-omap/clock.h b/include/asm-arm/arch-omap/clock.h
index cce55ba..a806f9f 100644
--- a/include/asm-arm/arch-omap/clock.h
+++ b/include/asm-arm/arch-omap/clock.h
@@ -61,6 +61,7 @@ struct dpll_data {
struct clk {
struct list_head node;
+ struct kobject kobj;
struct module *owner;
const char *name;
int id;
@@ -87,6 +88,7 @@ struct clk {
__u8 src_offset;
#endif
};
+#define to_clk(x) container_of(x, struct clk, kobj)
struct clk_functions {
int (*clk_enable)(struct clk *clk);
--
1.5.5.rc2.6.gf58d
^ permalink raw reply related [flat|nested] 21+ messages in thread* Re: [PATCH 1/1] ARM: OMAP: CLKFW: Initial sysfs support for omap clock framework 2008-04-16 8:44 [PATCH 1/1] ARM: OMAP: CLKFW: Initial sysfs support for omap clock framework Hiroshi DOYU @ 2008-04-16 8:57 ` Hiroshi DOYU 2008-04-16 13:20 ` Hiroshi DOYU 2008-04-16 16:58 ` David Brownell 1 sibling, 1 reply; 21+ messages in thread From: Hiroshi DOYU @ 2008-04-16 8:57 UTC (permalink / raw) To: linux-omap; +Cc: Hiroshi.DOYU Hi, Please ignore the previous one. The correct one is here;) Hiroshi DOYU >From 0ccce1d2d3f2760af8ad7b1b390429226042ef71 Mon Sep 17 00:00:00 2001 From: Hiroshi DOYU <Hiroshi.DOYU@nokia.com> Date: Wed, 16 Apr 2008 11:29:07 +0300 Subject: [PATCH 1/1] ARM: OMAP: CLKFW: Initial sysfs support for omap clock framework Sysfs 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 /sys/kernel/clock/omap_32k_fck/ /sys/kernel/clock/omap_32k_fck/ |-- gpt10_fck |-- gpt11_fck |-- gpt1_fck |-- per_32k_alwon_fck | |-- gpio3_fck | |-- gpio4_fck | |-- gpio5_fck | `-- gpio6_fck |-- ts_fck `-- wkup_32k_fck `-- gpio1_fck 11 directories omap:~# tree /sys/kernel/clock/omap_32k_fck/gpt10_fck /sys/kernel/clock/omap_32k_fck/gpt10_fck |-- flags |-- rate `-- usecount 0 directories, 3 files Signed-off-by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com> --- arch/arm/plat-omap/clock.c | 151 +++++++++++++++++++++++++++++++++++++ include/asm-arm/arch-omap/clock.h | 2 + 2 files changed, 153 insertions(+), 0 deletions(-) diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c index 1bd8781..c794b70 100644 --- a/arch/arm/plat-omap/clock.c +++ b/arch/arm/plat-omap/clock.c @@ -33,6 +33,157 @@ static DEFINE_SPINLOCK(clockfw_lock); static struct clk_functions *arch_clock; +/* + * Sysfs support to trace clk tree hierarchy + */ +static struct kset *clock_kset; + +struct clk_attr { + struct attribute attr; + ssize_t (*show)(struct clk *clk, struct clk_attr *attr, char *buf); + ssize_t (*store)(struct clk *clk, struct clk_attr *attr, + const char *buf, size_t count); +}; +#define to_clk_attr(x) container_of(x, struct clk_attr, attr) + +static ssize_t clk_attr_store(struct kobject *kobj, struct attribute *attr, + const char *buf, size_t count) +{ + struct clk_attr *ca; + struct clk *clk; + + ca = to_clk_attr(attr); + clk = to_clk(kobj); + + if (!ca->store) + return -EIO; + return ca->store(clk, ca, buf, count); +} + +static ssize_t clk_attr_show(struct kobject *kobj, struct attribute *attr, + char *buf) +{ + struct clk_attr *ca; + struct clk *clk; + + ca = to_clk_attr(attr); + clk = to_clk(kobj); + + if (!ca->show) + return -EIO; + return ca->show(clk, ca, buf); +} + +static struct sysfs_ops clk_sysfs_ops = { + .show = clk_attr_show, + .store = clk_attr_store, +}; + +static ssize_t attr_store(struct clk *clk, struct clk_attr *attr, + const char *buf, size_t count) +{ + unsigned long flags; + unsigned long val; + int err; + + sscanf(buf, "%lx", &val); + + if (strcmp(attr->attr.name, "rate") == 0) { + err = clk_set_rate(clk, val); + if (err) + count = -EIO; + } + return count; +} + +static ssize_t attr_show(struct clk *clk, struct clk_attr *attr, char *buf) +{ + int n = 0; + unsigned long flags; + + spin_lock_irqsave(&clockfw_lock, flags); + + if (strcmp(attr->attr.name, "rate") == 0) + n = sprintf(buf, "%lu\n", clk->rate); + else if (strcmp(attr->attr.name, "flags") == 0) + n = sprintf(buf, "0x%08x\n", clk->flags); + else if (strcmp(attr->attr.name, "usecount") == 0) + n = sprintf(buf, "%d\n", clk->usecount); + + spin_unlock_irqrestore(&clockfw_lock, flags); + return n; +} +static struct clk_attr rate = __ATTR(rate, 0444, attr_show, attr_store); +static struct clk_attr flags = __ATTR(flags, 0444, attr_show, NULL); +static struct clk_attr usecount = __ATTR(usecount, 0444, attr_show, NULL); + +static struct attribute *clk_default_attrs[] = { + &rate.attr, + &flags.attr, + &usecount.attr, + NULL, +}; + +static void clk_release(struct kobject *kobj) +{ + /* REVISIT: Dynamic registration */ +} + +static struct kobj_type clk_ktype = { + .sysfs_ops = &clk_sysfs_ops, + .release = clk_release, + .default_attrs = clk_default_attrs, +}; + +static int clk_sysfs_register(struct clk *clk) +{ + struct clk *pa = clk->parent; + + if (pa && !pa->kobj.state_initialized) + return clk_sysfs_register(pa); + else if (!clk->kobj.state_initialized) { + int err; + char name[KOBJ_NAME_LEN]; + char *p = name; + + clk->kobj.kset = clock_kset; + p += sprintf(name, "%s", clk->name); + if (clk->id != 0) + sprintf(p, "%d", clk->id); + err = kobject_init_and_add(&clk->kobj, &clk_ktype, + pa ? &pa->kobj : NULL, "%s", name); + return err; + } + return 0; +} + +static int __init clk_sysfs_init(void) +{ + struct clk *clk; + int err; + struct list_head *entry; + + clock_kset = kset_create_and_add("clock", NULL, kernel_kobj); + if (!clock_kset) + return -ENOMEM; + + list_for_each_entry(clk, &clocks, node) { + err = clk_sysfs_register(clk); + if (err) + goto err_out; + } + return 0; + +err_out: + list_for_each(entry, &clock_kset->list) { + struct kobject *k = container_of(entry, struct kobject, entry); + kobject_del(k); + } + kset_unregister(clock_kset); + return err; +} +late_initcall(clk_sysfs_init); + #ifdef CONFIG_PM_DEBUG static void print_parents(struct clk *clk) diff --git a/include/asm-arm/arch-omap/clock.h b/include/asm-arm/arch-omap/clock.h index cce55ba..a806f9f 100644 --- a/include/asm-arm/arch-omap/clock.h +++ b/include/asm-arm/arch-omap/clock.h @@ -61,6 +61,7 @@ struct dpll_data { struct clk { struct list_head node; + struct kobject kobj; struct module *owner; const char *name; int id; @@ -87,6 +88,7 @@ struct clk { __u8 src_offset; #endif }; +#define to_clk(x) container_of(x, struct clk, kobj) struct clk_functions { int (*clk_enable)(struct clk *clk); -- 1.5.5.rc2.6.gf58d ^ permalink raw reply related [flat|nested] 21+ messages in thread
* Re: [PATCH 1/1] ARM: OMAP: CLKFW: Initial sysfs support for omap clock framework 2008-04-16 8:57 ` Hiroshi DOYU @ 2008-04-16 13:20 ` Hiroshi DOYU 0 siblings, 0 replies; 21+ messages in thread From: Hiroshi DOYU @ 2008-04-16 13:20 UTC (permalink / raw) To: linux-omap; +Cc: Hiroshi.DOYU [-- Attachment #1: Type: Text/Plain, Size: 7813 bytes --] Hi, There is still problem with following tree recursively. Fix the problem as below and attached the new one. Now all clocks should be there. diff -u b/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c --- b/arch/arm/plat-omap/clock.c +++ b/arch/arm/plat-omap/clock.c @@ -82,7 +82,6 @@ static ssize_t attr_store(struct clk *clk, struct clk_attr *attr, const char *buf, size_t count) { - unsigned long flags; unsigned long val; int err; @@ -137,17 +136,21 @@ static int clk_sysfs_register(struct clk *clk) { + int err; struct clk *pa = clk->parent; - if (pa && !pa->kobj.state_initialized) - return clk_sysfs_register(pa); - else if (!clk->kobj.state_initialized) { - int err; + if (pa && !pa->kobj.state_initialized) { + err = clk_sysfs_register(pa); + if (err) + return err; + } + + if (!clk->kobj.state_initialized) { char name[KOBJ_NAME_LEN]; char *p = name; clk->kobj.kset = clock_kset; - p += sprintf(name, "%s", clk->name); + p += sprintf(p, "%s", clk->name); if (clk->id != 0) sprintf(p, "%d", clk->id); err = kobject_init_and_add(&clk->kobj, &clk_ktype, From: Hiroshi DOYU <Hiroshi.DOYU@nokia.com> Subject: Re: [PATCH 1/1] ARM: OMAP: CLKFW: Initial sysfs support for omap clock framework Date: Wed, 16 Apr 2008 11:57:49 +0300 (EEST) > Hi, > > Please ignore the previous one. The correct one is here;) > > Hiroshi DOYU > > From 0ccce1d2d3f2760af8ad7b1b390429226042ef71 Mon Sep 17 00:00:00 2001 > From: Hiroshi DOYU <Hiroshi.DOYU@nokia.com> > Date: Wed, 16 Apr 2008 11:29:07 +0300 > Subject: [PATCH 1/1] ARM: OMAP: CLKFW: Initial sysfs support for omap clock framework > > Sysfs 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 /sys/kernel/clock/omap_32k_fck/ > /sys/kernel/clock/omap_32k_fck/ > |-- gpt10_fck > |-- gpt11_fck > |-- gpt1_fck > |-- per_32k_alwon_fck > | |-- gpio3_fck > | |-- gpio4_fck > | |-- gpio5_fck > | `-- gpio6_fck > |-- ts_fck > `-- wkup_32k_fck > `-- gpio1_fck > > 11 directories > > omap:~# tree /sys/kernel/clock/omap_32k_fck/gpt10_fck > /sys/kernel/clock/omap_32k_fck/gpt10_fck > |-- flags > |-- rate > `-- usecount > > 0 directories, 3 files > > Signed-off-by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com> > --- > arch/arm/plat-omap/clock.c | 151 +++++++++++++++++++++++++++++++++++++ > include/asm-arm/arch-omap/clock.h | 2 + > 2 files changed, 153 insertions(+), 0 deletions(-) > > diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c > index 1bd8781..c794b70 100644 > --- a/arch/arm/plat-omap/clock.c > +++ b/arch/arm/plat-omap/clock.c > @@ -33,6 +33,157 @@ static DEFINE_SPINLOCK(clockfw_lock); > > static struct clk_functions *arch_clock; > > +/* > + * Sysfs support to trace clk tree hierarchy > + */ > +static struct kset *clock_kset; > + > +struct clk_attr { > + struct attribute attr; > + ssize_t (*show)(struct clk *clk, struct clk_attr *attr, char *buf); > + ssize_t (*store)(struct clk *clk, struct clk_attr *attr, > + const char *buf, size_t count); > +}; > +#define to_clk_attr(x) container_of(x, struct clk_attr, attr) > + > +static ssize_t clk_attr_store(struct kobject *kobj, struct attribute *attr, > + const char *buf, size_t count) > +{ > + struct clk_attr *ca; > + struct clk *clk; > + > + ca = to_clk_attr(attr); > + clk = to_clk(kobj); > + > + if (!ca->store) > + return -EIO; > + return ca->store(clk, ca, buf, count); > +} > + > +static ssize_t clk_attr_show(struct kobject *kobj, struct attribute *attr, > + char *buf) > +{ > + struct clk_attr *ca; > + struct clk *clk; > + > + ca = to_clk_attr(attr); > + clk = to_clk(kobj); > + > + if (!ca->show) > + return -EIO; > + return ca->show(clk, ca, buf); > +} > + > +static struct sysfs_ops clk_sysfs_ops = { > + .show = clk_attr_show, > + .store = clk_attr_store, > +}; > + > +static ssize_t attr_store(struct clk *clk, struct clk_attr *attr, > + const char *buf, size_t count) > +{ > + unsigned long flags; > + unsigned long val; > + int err; > + > + sscanf(buf, "%lx", &val); > + > + if (strcmp(attr->attr.name, "rate") == 0) { > + err = clk_set_rate(clk, val); > + if (err) > + count = -EIO; > + } > + return count; > +} > + > +static ssize_t attr_show(struct clk *clk, struct clk_attr *attr, char *buf) > +{ > + int n = 0; > + unsigned long flags; > + > + spin_lock_irqsave(&clockfw_lock, flags); > + > + if (strcmp(attr->attr.name, "rate") == 0) > + n = sprintf(buf, "%lu\n", clk->rate); > + else if (strcmp(attr->attr.name, "flags") == 0) > + n = sprintf(buf, "0x%08x\n", clk->flags); > + else if (strcmp(attr->attr.name, "usecount") == 0) > + n = sprintf(buf, "%d\n", clk->usecount); > + > + spin_unlock_irqrestore(&clockfw_lock, flags); > + return n; > +} > +static struct clk_attr rate = __ATTR(rate, 0444, attr_show, attr_store); > +static struct clk_attr flags = __ATTR(flags, 0444, attr_show, NULL); > +static struct clk_attr usecount = __ATTR(usecount, 0444, attr_show, NULL); > + > +static struct attribute *clk_default_attrs[] = { > + &rate.attr, > + &flags.attr, > + &usecount.attr, > + NULL, > +}; > + > +static void clk_release(struct kobject *kobj) > +{ > + /* REVISIT: Dynamic registration */ > +} > + > +static struct kobj_type clk_ktype = { > + .sysfs_ops = &clk_sysfs_ops, > + .release = clk_release, > + .default_attrs = clk_default_attrs, > +}; > + > +static int clk_sysfs_register(struct clk *clk) > +{ > + struct clk *pa = clk->parent; > + > + if (pa && !pa->kobj.state_initialized) > + return clk_sysfs_register(pa); > + else if (!clk->kobj.state_initialized) { > + int err; > + char name[KOBJ_NAME_LEN]; > + char *p = name; > + > + clk->kobj.kset = clock_kset; > + p += sprintf(name, "%s", clk->name); > + if (clk->id != 0) > + sprintf(p, "%d", clk->id); > + err = kobject_init_and_add(&clk->kobj, &clk_ktype, > + pa ? &pa->kobj : NULL, "%s", name); > + return err; > + } > + return 0; > +} > + > +static int __init clk_sysfs_init(void) > +{ > + struct clk *clk; > + int err; > + struct list_head *entry; > + > + clock_kset = kset_create_and_add("clock", NULL, kernel_kobj); > + if (!clock_kset) > + return -ENOMEM; > + > + list_for_each_entry(clk, &clocks, node) { > + err = clk_sysfs_register(clk); > + if (err) > + goto err_out; > + } > + return 0; > + > +err_out: > + list_for_each(entry, &clock_kset->list) { > + struct kobject *k = container_of(entry, struct kobject, entry); > + kobject_del(k); > + } > + kset_unregister(clock_kset); > + return err; > +} > +late_initcall(clk_sysfs_init); > + > #ifdef CONFIG_PM_DEBUG > > static void print_parents(struct clk *clk) > diff --git a/include/asm-arm/arch-omap/clock.h b/include/asm-arm/arch-omap/clock.h > index cce55ba..a806f9f 100644 > --- a/include/asm-arm/arch-omap/clock.h > +++ b/include/asm-arm/arch-omap/clock.h > @@ -61,6 +61,7 @@ struct dpll_data { > > struct clk { > struct list_head node; > + struct kobject kobj; > struct module *owner; > const char *name; > int id; > @@ -87,6 +88,7 @@ struct clk { > __u8 src_offset; > #endif > }; > +#define to_clk(x) container_of(x, struct clk, kobj) > > struct clk_functions { > int (*clk_enable)(struct clk *clk); > -- > 1.5.5.rc2.6.gf58d > > [-- Attachment #2: 0001-ARM-OMAP-CLKFW-Initial-sysfs-support-for-omap-clo.patch --] [-- Type: Text/Plain, Size: 5699 bytes --] >From 5711ee744835d15f017d010cead105a0eb288801 Mon Sep 17 00:00:00 2001 From: Hiroshi DOYU <Hiroshi.DOYU@nokia.com> Date: Wed, 16 Apr 2008 11:29:07 +0300 Subject: [PATCH 1/1] ARM: OMAP: CLKFW: Initial sysfs support for omap clock framework Sysfs 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 /sys/kernel/clock/omap_32k_fck/ /sys/kernel/clock/omap_32k_fck/ |-- gpt10_fck |-- gpt11_fck |-- gpt1_fck |-- per_32k_alwon_fck | |-- gpio3_fck | |-- gpio4_fck | |-- gpio5_fck | `-- gpio6_fck |-- ts_fck `-- wkup_32k_fck `-- gpio1_fck 11 directories omap:~# tree /sys/kernel/clock/omap_32k_fck/gpt10_fck /sys/kernel/clock/omap_32k_fck/gpt10_fck |-- flags |-- rate `-- usecount 0 directories, 3 files Signed-off-by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com> --- arch/arm/plat-omap/clock.c | 154 +++++++++++++++++++++++++++++++++++++ include/asm-arm/arch-omap/clock.h | 2 + 2 files changed, 156 insertions(+), 0 deletions(-) diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c index 1bd8781..5e45e62 100644 --- a/arch/arm/plat-omap/clock.c +++ b/arch/arm/plat-omap/clock.c @@ -33,6 +33,160 @@ static DEFINE_SPINLOCK(clockfw_lock); static struct clk_functions *arch_clock; +/* + * Sysfs support to trace clk tree hierarchy + */ +static struct kset *clock_kset; + +struct clk_attr { + struct attribute attr; + ssize_t (*show)(struct clk *clk, struct clk_attr *attr, char *buf); + ssize_t (*store)(struct clk *clk, struct clk_attr *attr, + const char *buf, size_t count); +}; +#define to_clk_attr(x) container_of(x, struct clk_attr, attr) + +static ssize_t clk_attr_store(struct kobject *kobj, struct attribute *attr, + const char *buf, size_t count) +{ + struct clk_attr *ca; + struct clk *clk; + + ca = to_clk_attr(attr); + clk = to_clk(kobj); + + if (!ca->store) + return -EIO; + return ca->store(clk, ca, buf, count); +} + +static ssize_t clk_attr_show(struct kobject *kobj, struct attribute *attr, + char *buf) +{ + struct clk_attr *ca; + struct clk *clk; + + ca = to_clk_attr(attr); + clk = to_clk(kobj); + + if (!ca->show) + return -EIO; + return ca->show(clk, ca, buf); +} + +static struct sysfs_ops clk_sysfs_ops = { + .show = clk_attr_show, + .store = clk_attr_store, +}; + +static ssize_t attr_store(struct clk *clk, struct clk_attr *attr, + const char *buf, size_t count) +{ + unsigned long val; + int err; + + sscanf(buf, "%lx", &val); + + if (strcmp(attr->attr.name, "rate") == 0) { + err = clk_set_rate(clk, val); + if (err) + count = -EIO; + } + return count; +} + +static ssize_t attr_show(struct clk *clk, struct clk_attr *attr, char *buf) +{ + int n = 0; + unsigned long flags; + + spin_lock_irqsave(&clockfw_lock, flags); + + if (strcmp(attr->attr.name, "rate") == 0) + n = sprintf(buf, "%lu\n", clk->rate); + else if (strcmp(attr->attr.name, "flags") == 0) + n = sprintf(buf, "0x%08x\n", clk->flags); + else if (strcmp(attr->attr.name, "usecount") == 0) + n = sprintf(buf, "%d\n", clk->usecount); + + spin_unlock_irqrestore(&clockfw_lock, flags); + return n; +} +static struct clk_attr rate = __ATTR(rate, 0444, attr_show, attr_store); +static struct clk_attr flags = __ATTR(flags, 0444, attr_show, NULL); +static struct clk_attr usecount = __ATTR(usecount, 0444, attr_show, NULL); + +static struct attribute *clk_default_attrs[] = { + &rate.attr, + &flags.attr, + &usecount.attr, + NULL, +}; + +static void clk_release(struct kobject *kobj) +{ + /* REVISIT: Dynamic registration */ +} + +static struct kobj_type clk_ktype = { + .sysfs_ops = &clk_sysfs_ops, + .release = clk_release, + .default_attrs = clk_default_attrs, +}; + +static int clk_sysfs_register(struct clk *clk) +{ + int err; + struct clk *pa = clk->parent; + + if (pa && !pa->kobj.state_initialized) { + err = clk_sysfs_register(pa); + if (err) + return err; + } + + if (!clk->kobj.state_initialized) { + char name[KOBJ_NAME_LEN]; + char *p = name; + + clk->kobj.kset = clock_kset; + p += sprintf(p, "%s", clk->name); + if (clk->id != 0) + sprintf(p, "%d", clk->id); + err = kobject_init_and_add(&clk->kobj, &clk_ktype, + pa ? &pa->kobj : NULL, "%s", name); + return err; + } + return 0; +} + +static int __init clk_sysfs_init(void) +{ + struct clk *clk; + int err; + struct list_head *entry; + + clock_kset = kset_create_and_add("clock", NULL, kernel_kobj); + if (!clock_kset) + return -ENOMEM; + + list_for_each_entry(clk, &clocks, node) { + err = clk_sysfs_register(clk); + if (err) + goto err_out; + } + return 0; + +err_out: + list_for_each(entry, &clock_kset->list) { + struct kobject *k = container_of(entry, struct kobject, entry); + kobject_del(k); + } + kset_unregister(clock_kset); + return err; +} +late_initcall(clk_sysfs_init); + #ifdef CONFIG_PM_DEBUG static void print_parents(struct clk *clk) diff --git a/include/asm-arm/arch-omap/clock.h b/include/asm-arm/arch-omap/clock.h index cce55ba..a806f9f 100644 --- a/include/asm-arm/arch-omap/clock.h +++ b/include/asm-arm/arch-omap/clock.h @@ -61,6 +61,7 @@ struct dpll_data { struct clk { struct list_head node; + struct kobject kobj; struct module *owner; const char *name; int id; @@ -87,6 +88,7 @@ struct clk { __u8 src_offset; #endif }; +#define to_clk(x) container_of(x, struct clk, kobj) struct clk_functions { int (*clk_enable)(struct clk *clk); -- 1.5.5.rc2.6.gf58d ^ permalink raw reply related [flat|nested] 21+ messages in thread
* Re: [PATCH 1/1] ARM: OMAP: CLKFW: Initial sysfs support for omap clock framework 2008-04-16 8:44 [PATCH 1/1] ARM: OMAP: CLKFW: Initial sysfs support for omap clock framework Hiroshi DOYU 2008-04-16 8:57 ` Hiroshi DOYU @ 2008-04-16 16:58 ` David Brownell 2008-04-16 20:51 ` Tony Lindgren 1 sibling, 1 reply; 21+ messages in thread From: David Brownell @ 2008-04-16 16:58 UTC (permalink / raw) To: Hiroshi DOYU; +Cc: linux-omap On Wednesday 16 April 2008, Hiroshi DOYU wrote: > omap:~# tree -d /sys/kernel/clock/omap_32k_fck/ > /sys/kernel/clock/omap_32k_fck/ > |-- gpt10_fck > |-- gpt11_fck > |-- gpt1_fck > |-- per_32k_alwon_fck > | |-- gpio3_fck > | |-- gpio4_fck > | |-- gpio5_fck > | `-- gpio6_fck > |-- ts_fck > `-- wkup_32k_fck > `-- gpio1_fck > > 11 directories > > omap:~# tree /sys/kernel/clock/omap_32k_fck/gpt10_fck > /sys/kernel/clock/omap_32k_fck/gpt10_fck > |-- flags > |-- rate > `-- usecount Does this need to be in sysfs? I'd think debugfs would be more appropriate ... that information isn't needed for normal operation. Appended is a small patch I've been carrying around. This doesn't move the clocks info from procfs to debugfs, but that'd be an easy patch. (Probably needs minor updates given the recent clocktree changes, but it still applies. The coupling to the device tree is a bit weak, and I'd think displaying power domains would be useful too.) - Dave ============ CUT HERE Make /proc/omap_clocks show the clock hierarchy through indentation, and the ids for devices (like i2c and spi; but oddly not uart, gpt, mcbsp, or wdt) with multiple instances. Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> --- arch/arm/plat-omap/clock.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) --- a/arch/arm/plat-omap/clock.c 2007-11-23 18:29:46.000000000 -0800 +++ b/arch/arm/plat-omap/clock.c 2007-11-23 18:45:44.000000000 -0800 @@ -465,13 +465,30 @@ static void omap_ck_stop(struct seq_file { } -int omap_ck_show(struct seq_file *m, void *v) +/* show clock hierarchy */ +static void omap_cktree_show(struct seq_file *m, unsigned n, struct clk *p) { struct clk *cp; - list_for_each_entry(cp, &clocks, node) - seq_printf(m,"%s %ld %d\n", cp->name, cp->rate, cp->usecount); + if (p) { + seq_printf(m, "%*s%-*s %9ld Hz, use %2d", + n, "", 30 - n, p->name, + p->rate, p->usecount); + if (p->id) + seq_printf(m, " (id %d)", p->id); + seq_printf(m, "\n"); + n += 2; + } + list_for_each_entry(cp, &clocks, node) { + if (cp->parent == p) + omap_cktree_show(m, n, cp); + } +} + +static int omap_ck_show(struct seq_file *m, void *v) +{ + omap_cktree_show(m, 0, NULL); return 0; } -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 1/1] ARM: OMAP: CLKFW: Initial sysfs support for omap clock framework 2008-04-16 16:58 ` David Brownell @ 2008-04-16 20:51 ` Tony Lindgren 2008-04-17 14:09 ` [PATCH 1/2] ARM: OMAP: CLKFW: Initial debugfs " Hiroshi DOYU 0 siblings, 1 reply; 21+ messages in thread From: Tony Lindgren @ 2008-04-16 20:51 UTC (permalink / raw) To: David Brownell; +Cc: Hiroshi DOYU, linux-omap * David Brownell <david-b@pacbell.net> [080416 09:58]: > On Wednesday 16 April 2008, Hiroshi DOYU wrote: > > omap:~# tree -d /sys/kernel/clock/omap_32k_fck/ > > /sys/kernel/clock/omap_32k_fck/ > > |-- gpt10_fck > > |-- gpt11_fck > > |-- gpt1_fck > > |-- per_32k_alwon_fck > > | |-- gpio3_fck > > | |-- gpio4_fck > > | |-- gpio5_fck > > | `-- gpio6_fck > > |-- ts_fck > > `-- wkup_32k_fck > > `-- gpio1_fck > > > > 11 directories > > > > omap:~# tree /sys/kernel/clock/omap_32k_fck/gpt10_fck > > /sys/kernel/clock/omap_32k_fck/gpt10_fck > > |-- flags > > |-- rate > > `-- usecount > > Does this need to be in sysfs? I'd think debugfs would be > more appropriate ... that information isn't needed for normal > operation. > > Appended is a small patch I've been carrying around. This > doesn't move the clocks info from procfs to debugfs, but > that'd be an easy patch. (Probably needs minor updates given > the recent clocktree changes, but it still applies. The > coupling to the device tree is a bit weak, and I'd think > displaying power domains would be useful too.) Yeah, debugfs would be best. And that /proc/clocks entry will disappear once that's available (it's currently only in l-o tree). Tony > - Dave > > ============ CUT HERE > Make /proc/omap_clocks show the clock hierarchy through indentation, > and the ids for devices (like i2c and spi; but oddly not uart, gpt, > mcbsp, or wdt) with multiple instances. > > Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> > --- > arch/arm/plat-omap/clock.c | 23 ++++++++++++++++++++--- > 1 file changed, 20 insertions(+), 3 deletions(-) > > --- a/arch/arm/plat-omap/clock.c 2007-11-23 18:29:46.000000000 -0800 > +++ b/arch/arm/plat-omap/clock.c 2007-11-23 18:45:44.000000000 -0800 > @@ -465,13 +465,30 @@ static void omap_ck_stop(struct seq_file > { > } > > -int omap_ck_show(struct seq_file *m, void *v) > +/* show clock hierarchy */ > +static void omap_cktree_show(struct seq_file *m, unsigned n, struct clk *p) > { > struct clk *cp; > > - list_for_each_entry(cp, &clocks, node) > - seq_printf(m,"%s %ld %d\n", cp->name, cp->rate, cp->usecount); > + if (p) { > + seq_printf(m, "%*s%-*s %9ld Hz, use %2d", > + n, "", 30 - n, p->name, > + p->rate, p->usecount); > + if (p->id) > + seq_printf(m, " (id %d)", p->id); > + seq_printf(m, "\n"); > + n += 2; > + } > > + list_for_each_entry(cp, &clocks, node) { > + if (cp->parent == p) > + omap_cktree_show(m, n, cp); > + } > +} > + > +static int omap_ck_show(struct seq_file *m, void *v) > +{ > + omap_cktree_show(m, 0, NULL); > return 0; > } > > -- > To unsubscribe from this list: send the line "unsubscribe linux-omap" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 1/2] ARM: OMAP: CLKFW: Initial debugfs support for omap clock framework 2008-04-16 20:51 ` Tony Lindgren @ 2008-04-17 14:09 ` Hiroshi DOYU 2008-04-17 14:09 ` [PATCH 2/2] ARM: OMAP: CLKFW: Remove procfs entry for debugging " Hiroshi DOYU 2008-04-17 16:23 ` [PATCH 1/2] ARM: OMAP: CLKFW: Initial debugfs support for omap " Paul Walmsley 0 siblings, 2 replies; 21+ messages in thread From: Hiroshi DOYU @ 2008-04-17 14:09 UTC (permalink / raw) To: linux-omap; +Cc: Hiroshi DOYU 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> --- arch/arm/plat-omap/clock.c | 94 ++++++++++++++++++++++++++++++++++++- include/asm-arm/arch-omap/clock.h | 3 + 2 files changed, 96 insertions(+), 1 deletions(-) diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c index 1bd8781..fa5c965 100644 --- a/arch/arm/plat-omap/clock.c +++ b/arch/arm/plat-omap/clock.c @@ -1,7 +1,7 @@ /* * linux/arch/arm/plat-omap/clock.c * - * Copyright (C) 2004 - 2005 Nokia corporation + * Copyright (C) 2004 - 2008 Nokia corporation * Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com> * * Modified for omap shared clock framework by Tony Lindgren <tony@atomide.com> @@ -21,6 +21,7 @@ #include <linux/clk.h> #include <linux/mutex.h> #include <linux/platform_device.h> +#include <linux/debugfs.h> #include <asm/io.h> #include <asm/semaphore.h> @@ -506,3 +507,94 @@ int __init omap_ck_init(void) } __initcall(omap_ck_init); #endif + +#if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS) +/* + * debugfs support to trace clock tree hierarchy and attributes + */ +static struct dentry *clk_debugfs_root; + +static int clk_debugfs_register_one(struct clk *c) +{ + int err; + struct dentry *d, *child; + struct clk *pa = c->parent; + char s[255]; + char *p = s; + + p += sprintf(p, "%s", c->name); + if (c->id != 0) + sprintf(p, "%d", c->id); + d = debugfs_create_dir(s, pa ? pa->dent : clk_debugfs_root); + if (IS_ERR(d)) + return PTR_ERR(d); + c->dent = d; + + d = debugfs_create_u8("usecount", S_IRUGO, c->dent, (u8 *)&c->usecount); + if (IS_ERR(d)) { + err = PTR_ERR(d); + goto err_out; + } + d = debugfs_create_u32("rate", S_IRUGO, c->dent, (u32 *)&c->rate); + if (IS_ERR(d)) { + err = PTR_ERR(d); + goto err_out; + } + d = debugfs_create_x32("flags", S_IRUGO, c->dent, (u32 *)&c->flags); + if (IS_ERR(d)) { + err = PTR_ERR(d); + goto err_out; + } + return 0; + +err_out: + d = c->dent; + list_for_each_entry(child, &d->d_subdirs, d_u.d_child) + debugfs_remove(child); + debugfs_remove(c->dent); + return err; +} + +static int clk_debugfs_register(struct clk *c) +{ + int err; + struct clk *pa = c->parent; + + if (pa && !pa->dent) { + err = clk_debugfs_register(pa); + if (err) + return err; + } + + if (!c->dent) { + err = clk_debugfs_register_one(c); + if (err) + return err; + } + return 0; +} + +static int __init clk_debugfs_init(void) +{ + struct clk *c; + struct dentry *d; + int err; + + d = debugfs_create_dir("clock", NULL); + if (IS_ERR(d)) + return PTR_ERR(d); + clk_debugfs_root = d; + + list_for_each_entry(c, &clocks, node) { + err = clk_debugfs_register(c); + if (err) + goto err_out; + } + return 0; +err_out: + debugfs_remove(clk_debugfs_root); /* REVISIT: Cleanup correctly */ + return err; +} +late_initcall(clk_debugfs_init); + +#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 cce55ba..0d75724 100644 --- a/include/asm-arm/arch-omap/clock.h +++ b/include/asm-arm/arch-omap/clock.h @@ -86,6 +86,9 @@ struct clk { __u8 rate_offset; __u8 src_offset; #endif +#ifdef CONFIG_DEBUG_FS + struct dentry *dent; /* For visible tree hierarchy */ +#endif }; struct clk_functions { -- 1.5.5.rc2.6.gf58d ^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 2/2] ARM: OMAP: CLKFW: Remove procfs entry for debugging clock framework 2008-04-17 14:09 ` [PATCH 1/2] ARM: OMAP: CLKFW: Initial debugfs " Hiroshi DOYU @ 2008-04-17 14:09 ` Hiroshi DOYU 2008-04-17 16:23 ` [PATCH 1/2] ARM: OMAP: CLKFW: Initial debugfs support for omap " Paul Walmsley 1 sibling, 0 replies; 21+ messages in thread From: Hiroshi DOYU @ 2008-04-17 14:09 UTC (permalink / raw) To: linux-omap; +Cc: Hiroshi DOYU This feature can be covered by debugfs for omap clock framework. Signed-off-by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com> --- arch/arm/plat-omap/clock.c | 96 -------------------------------------------- 1 files changed, 0 insertions(+), 96 deletions(-) diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c index fa5c965..3fd28d1 100644 --- a/arch/arm/plat-omap/clock.c +++ b/arch/arm/plat-omap/clock.c @@ -34,41 +34,6 @@ static DEFINE_SPINLOCK(clockfw_lock); static struct clk_functions *arch_clock; -#ifdef CONFIG_PM_DEBUG - -static void print_parents(struct clk *clk) -{ - struct clk *p; - int printed = 0; - - list_for_each_entry(p, &clocks, node) { - if (p->parent == clk && p->usecount) { - if (!clk->usecount && !printed) { - printk("MISMATCH: %s\n", clk->name); - printed = 1; - } - printk("\t%-15s\n", p->name); - } - } -} - -void clk_print_usecounts(void) -{ - unsigned long flags; - struct clk *p; - - spin_lock_irqsave(&clockfw_lock, flags); - list_for_each_entry(p, &clocks, node) { - if (p->usecount) - printk("%-15s: %d\n", p->name, p->usecount); - print_parents(p); - - } - spin_unlock_irqrestore(&clockfw_lock, flags); -} - -#endif - /*------------------------------------------------------------------------- * Standard clock functions defined in include/linux/clk.h *-------------------------------------------------------------------------*/ @@ -447,67 +412,6 @@ int __init clk_init(struct clk_functions * custom_clocks) return 0; } -#if defined(CONFIG_PM_DEBUG) && defined(CONFIG_PROC_FS) -#include <linux/proc_fs.h> -#include <linux/seq_file.h> - -static void *omap_ck_start(struct seq_file *m, loff_t *pos) -{ - return *pos < 1 ? (void *)1 : NULL; -} - -static void *omap_ck_next(struct seq_file *m, void *v, loff_t *pos) -{ - ++*pos; - return NULL; -} - -static void omap_ck_stop(struct seq_file *m, void *v) -{ -} - -int omap_ck_show(struct seq_file *m, void *v) -{ - struct clk *cp; - - list_for_each_entry(cp, &clocks, node) - seq_printf(m,"%s %ld %d\n", cp->name, cp->rate, cp->usecount); - - return 0; -} - -static struct seq_operations omap_ck_op = { - .start = omap_ck_start, - .next = omap_ck_next, - .stop = omap_ck_stop, - .show = omap_ck_show -}; - -static int omap_ck_open(struct inode *inode, struct file *file) -{ - return seq_open(file, &omap_ck_op); -} - -static struct file_operations proc_omap_ck_operations = { - .open = omap_ck_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, -}; - -int __init omap_ck_init(void) -{ - struct proc_dir_entry *entry; - - entry = create_proc_entry("omap_clocks", 0, NULL); - if (entry) - entry->proc_fops = &proc_omap_ck_operations; - return 0; - -} -__initcall(omap_ck_init); -#endif - #if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS) /* * debugfs support to trace clock tree hierarchy and attributes -- 1.5.5.rc2.6.gf58d ^ permalink raw reply related [flat|nested] 21+ messages in thread
* Re: [PATCH 1/2] ARM: OMAP: CLKFW: Initial debugfs support for omap clock framework 2008-04-17 14:09 ` [PATCH 1/2] ARM: OMAP: CLKFW: Initial debugfs " Hiroshi DOYU 2008-04-17 14:09 ` [PATCH 2/2] ARM: OMAP: CLKFW: Remove procfs entry for debugging " Hiroshi DOYU @ 2008-04-17 16:23 ` Paul Walmsley 2008-04-17 18:40 ` David Brownell 1 sibling, 1 reply; 21+ messages in thread From: Paul Walmsley @ 2008-04-17 16:23 UTC (permalink / raw) To: Hiroshi DOYU; +Cc: linux-omap Hello Hiroshi, On Thu, 17 Apr 2008, Hiroshi DOYU wrote: > 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: As a replacement for print_parents, which was read-only, it seems good to me. But it would be nice to be able to call into clock functions like round_rate, set_rate, and set_parent via filesystem writes for debugging purposes, and I don't think that debugfs supports this. I have a patch here that I use for internal testing that builds the clock tree in sysfs, and allows for round_rate/set_rate calls, along with enable/disable testing. But sysfs may not be the right place. It doesn't seem like there's any logical place to put it that would not involve major upstream arm-wrestling. Maybe /sys/devices/platform? There are also procfs and configfs, I suppose. Obviously, I could continue to carry my debugging patch in my local tree here. But you mention powerdomain links. I suspect that we will want to have a standard place for all of these filesystem entities, particularly since one could conceive of a completely userspace power management policy that would control powerdomains and clockdomains via the filesystem. So it probably makes sense to discuss this now. A quick comment on the patch itself, inlined below. > +static int clk_debugfs_register_one(struct clk *c) > +{ > + int err; > + struct dentry *d, *child; > + struct clk *pa = c->parent; > + char s[255]; > + char *p = s; > + > + p += sprintf(p, "%s", c->name); > + if (c->id != 0) > + sprintf(p, "%d", c->id); perhaps separate the ID and the clock name with a colon, if the ID exists? - Paul ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 1/2] ARM: OMAP: CLKFW: Initial debugfs support for omap clock framework 2008-04-17 16:23 ` [PATCH 1/2] ARM: OMAP: CLKFW: Initial debugfs support for omap " Paul Walmsley @ 2008-04-17 18:40 ` David Brownell 2008-04-17 18:45 ` Paul Walmsley 0 siblings, 1 reply; 21+ messages in thread From: David Brownell @ 2008-04-17 18:40 UTC (permalink / raw) To: Paul Walmsley; +Cc: Hiroshi DOYU, linux-omap On Thursday 17 April 2008, Paul Walmsley wrote: > But it would be nice to be able to call into clock functions like > round_rate, set_rate, and set_parent via filesystem writes for debugging > purposes, and I don't think that debugfs supports this. It does, if you set up the files properly ... except maybe the set_parent stuff. - Dave ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 1/2] ARM: OMAP: CLKFW: Initial debugfs support for omap clock framework 2008-04-17 18:40 ` David Brownell @ 2008-04-17 18:45 ` Paul Walmsley 2008-04-17 18:54 ` David Brownell 2008-04-17 18:57 ` Hiroshi DOYU 0 siblings, 2 replies; 21+ messages in thread From: Paul Walmsley @ 2008-04-17 18:45 UTC (permalink / raw) To: David Brownell; +Cc: Hiroshi DOYU, linux-omap Hello David, On Thu, 17 Apr 2008, David Brownell wrote: > On Thursday 17 April 2008, Paul Walmsley wrote: > > But it would be nice to be able to call into clock functions like > > round_rate, set_rate, and set_parent via filesystem writes for debugging > > purposes, and I don't think that debugfs supports this. > > It does, if you set up the files properly ... except > maybe the set_parent stuff. Could you be more specific? The only write support that I see in the debugfs API is to store bytes into memory locations. We'd need to call functions also upon writes. - Paul ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 1/2] ARM: OMAP: CLKFW: Initial debugfs support for omap clock framework 2008-04-17 18:45 ` Paul Walmsley @ 2008-04-17 18:54 ` David Brownell 2008-04-17 19:17 ` Paul Walmsley 2008-04-17 18:57 ` Hiroshi DOYU 1 sibling, 1 reply; 21+ messages in thread From: David Brownell @ 2008-04-17 18:54 UTC (permalink / raw) To: Paul Walmsley; +Cc: Hiroshi DOYU, linux-omap On Thursday 17 April 2008, Paul Walmsley wrote: > Hello David, > > On Thu, 17 Apr 2008, David Brownell wrote: > > > On Thursday 17 April 2008, Paul Walmsley wrote: > > > But it would be nice to be able to call into clock functions like > > > round_rate, set_rate, and set_parent via filesystem writes for debugging > > > purposes, and I don't think that debugfs supports this. > > > > It does, if you set up the files properly ... except > > maybe the set_parent stuff. > > Could you be more specific? The only write support that I see in the > debugfs API is to store bytes into memory locations. We'd need to call > functions also upon writes. struct dentry *debugfs_create_file(const char *name, mode_t mode, struct dentry *parent, void *data, const struct file_operations *fops); ... provide a file_operations vector supporting writes. Or building more complex values with seq_file, etc. There are indeed lots of functions letting you create single-valued attributes. I happen to find that model uselessly constraining, and can't really imagine using it. - Dave ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 1/2] ARM: OMAP: CLKFW: Initial debugfs support for omap clock framework 2008-04-17 18:54 ` David Brownell @ 2008-04-17 19:17 ` Paul Walmsley 0 siblings, 0 replies; 21+ messages in thread From: Paul Walmsley @ 2008-04-17 19:17 UTC (permalink / raw) To: David Brownell; +Cc: Hiroshi DOYU, linux-omap Hello David, On Thu, 17 Apr 2008, David Brownell wrote: > struct dentry *debugfs_create_file(const char *name, mode_t mode, > struct dentry *parent, void *data, > const struct file_operations *fops); > > ... provide a file_operations vector supporting writes. Or building > more complex values with seq_file, etc. thanks, missed that. That would indeed work. - Paul ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 1/2] ARM: OMAP: CLKFW: Initial debugfs support for omap clock framework 2008-04-17 18:45 ` Paul Walmsley 2008-04-17 18:54 ` David Brownell @ 2008-04-17 18:57 ` Hiroshi DOYU 2008-04-17 19:14 ` David Brownell 1 sibling, 1 reply; 21+ messages in thread From: Hiroshi DOYU @ 2008-04-17 18:57 UTC (permalink / raw) To: paul; +Cc: david-b, linux-omap Hi, From: "ext Paul Walmsley" <paul@pwsan.com> Subject: Re: [PATCH 1/2] ARM: OMAP: CLKFW: Initial debugfs support for omap clock framework Date: Thu, 17 Apr 2008 12:45:02 -0600 (MDT) > Hello David, > > On Thu, 17 Apr 2008, David Brownell wrote: > > > On Thursday 17 April 2008, Paul Walmsley wrote: > > > But it would be nice to be able to call into clock functions like > > > round_rate, set_rate, and set_parent via filesystem writes for debugging > > > purposes, and I don't think that debugfs supports this. > > > > It does, if you set up the files properly ... except > > maybe the set_parent stuff. > > Could you be more specific? The only write support that I see in the > debugfs API is to store bytes into memory locations. We'd need to call > functions also upon writes. "debugfs_create_file(...fops)" has take "fops" as its argument. I guess that this can deal with the above. For "set_parent", would it be possible to do that by using "debugfs_rename()"? And if there will be a little possibility that sysfs attribute can be used by userland in the future, keeping sysfs instead of debugfs doesn't seem not so illegal, does it? Hiroshi DOYU ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 1/2] ARM: OMAP: CLKFW: Initial debugfs support for omap clock framework 2008-04-17 18:57 ` Hiroshi DOYU @ 2008-04-17 19:14 ` David Brownell 2008-04-17 19:44 ` Paul Walmsley 0 siblings, 1 reply; 21+ messages in thread From: David Brownell @ 2008-04-17 19:14 UTC (permalink / raw) To: Hiroshi DOYU; +Cc: paul, linux-omap On Thursday 17 April 2008, Hiroshi DOYU wrote: > For "set_parent", would it be possible to do that by using > "debugfs_rename()"? Could be. What happens if you try it? > And if there will be a little possibility that sysfs attribute can be > used by userland in the future, keeping sysfs instead of debugfs > doesn't seem not so illegal, does it? I'm unaware of any laws passed in any country on that topic. ;) I happen to think that the clock tree is sensitive enough that it should not be managed from userspace in production systems. (Except possibly through driver-specific APIs which ensure the right rules are followed.) Too easy to break things otherwise. - Dave ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 1/2] ARM: OMAP: CLKFW: Initial debugfs support for omap clock framework 2008-04-17 19:14 ` David Brownell @ 2008-04-17 19:44 ` Paul Walmsley 2008-04-17 19:49 ` Igor Stoppa 2008-04-17 19:58 ` Hiroshi DOYU 0 siblings, 2 replies; 21+ messages in thread From: Paul Walmsley @ 2008-04-17 19:44 UTC (permalink / raw) To: David Brownell; +Cc: Hiroshi DOYU, linux-omap Hello Hiroshi, David, On Thu, 17 Apr 2008, David Brownell wrote: > On Thursday 17 April 2008, Hiroshi DOYU wrote: > > > And if there will be a little possibility that sysfs attribute can be > > used by userland in the future, keeping sysfs instead of debugfs > > doesn't seem not so illegal, does it? True, but if we can do a debugfs implementation first, then that seems like a good way to start, no? Userspace PM implementations are probably some months in the future, and we can mandate that debugfs be mounted for those. > I happen to think that the clock tree is sensitive enough > that it should not be managed from userspace in production > systems. (Except possibly through driver-specific APIs which > ensure the right rules are followed.) Too easy to break things > otherwise. In terms of the clock tree, it would be good to allow userspace-driven OPP changes, analogous to CPUFreq's userspace governor. [ In general, I agree that userspace should not be changing driver clocks directly, just like userspace should not be mucking around in /dev/mem directly :-) ] Clock tree changes (like OPP changes) which are not initiated by drivers do create some additional complexity. Drivers will need to be notified before and after these changes. It turns out that DSP Bridge already needs post-frequency-change notification for the DSP clock - there is a patch here which will soon be posted to add those. Pre-change notifiers are also needed to quiesce DMA, etc.; those are somewhat more difficult, but also in the works. - Paul ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 1/2] ARM: OMAP: CLKFW: Initial debugfs support for omap clock framework 2008-04-17 19:44 ` Paul Walmsley @ 2008-04-17 19:49 ` Igor Stoppa 2008-04-17 20:47 ` Paul Walmsley 2008-04-17 19:58 ` Hiroshi DOYU 1 sibling, 1 reply; 21+ messages in thread From: Igor Stoppa @ 2008-04-17 19:49 UTC (permalink / raw) To: ext Paul Walmsley; +Cc: David Brownell, Hiroshi DOYU, linux-omap Hi all, On Thu, 2008-04-17 at 13:44 -0600, ext Paul Walmsley wrote: > Hello Hiroshi, David, > > On Thu, 17 Apr 2008, David Brownell wrote: > > > On Thursday 17 April 2008, Hiroshi DOYU wrote: > > > > > And if there will be a little possibility that sysfs attribute can be > > > used by userland in the future, keeping sysfs instead of debugfs > > > doesn't seem not so illegal, does it? > > True, but if we can do a debugfs implementation first, then that seems > like a good way to start, no? Userspace PM implementations are probably > some months in the future, and we can mandate that debugfs be mounted for > those. I can hardly see the benefit of a userspace implementation, considering the extra context switch required and the fact the in many cases clocks get enabled in response to irqs. > > I happen to think that the clock tree is sensitive enough > > that it should not be managed from userspace in production > > systems. (Except possibly through driver-specific APIs which > > ensure the right rules are followed.) Too easy to break things > > otherwise. > > In terms of the clock tree, it would be good to allow userspace-driven OPP > changes, analogous to CPUFreq's userspace governor. [ In general, I agree > that userspace should not be changing driver clocks directly, just like > userspace should not be mucking around in /dev/mem directly :-) ] That also sounds akward at best: cpufreq (or similar) is much better suited for this sort of activity; userspace governor would be the userspace controller you refer to, but it is far from being optimal. Userspace should limit itself to changing policies. -- Cheers, Igor --- Igor Stoppa Next Generation Software Nokia Devices R&D - Helsinki ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 1/2] ARM: OMAP: CLKFW: Initial debugfs support for omap clock framework 2008-04-17 19:49 ` Igor Stoppa @ 2008-04-17 20:47 ` Paul Walmsley 2008-04-17 21:22 ` David Brownell 2008-04-18 7:08 ` Igor Stoppa 0 siblings, 2 replies; 21+ messages in thread From: Paul Walmsley @ 2008-04-17 20:47 UTC (permalink / raw) To: Igor Stoppa; +Cc: David Brownell, Hiroshi DOYU, linux-omap Hello Igor, On Thu, 17 Apr 2008, Igor Stoppa wrote: > On Thu, 2008-04-17 at 13:44 -0600, ext Paul Walmsley wrote: > > > True, but if we can do a debugfs implementation first, then that seems > > like a good way to start, no? Userspace PM implementations are probably > > some months in the future, and we can mandate that debugfs be mounted for > > those. > > I can hardly see the benefit of a userspace implementation, considering > the extra context switch required and the fact the in many cases clocks > get enabled in response to irqs. I agree that we shouldn't try to move the clock framework to userspace. But, determining what OPP to switch to next, based on system load or other requirements published by drivers or userspace processes; or determining what power state to put powerdomains to -- it would be nice to experiment with a userspace governor for those tasks. It would certainly make development and testing easier. > > In terms of the clock tree, it would be good to allow userspace-driven OPP > > changes, analogous to CPUFreq's userspace governor. [ In general, I agree > > that userspace should not be changing driver clocks directly, just like > > userspace should not be mucking around in /dev/mem directly :-) ] > > That also sounds akward at best: cpufreq (or similar) is much better > suited for this sort of activity; userspace governor would be the > userspace controller you refer to, but it is far from being optimal. > > Userspace should limit itself to changing policies. CPUFreq is good, but it does not manage non-CPU-frequency knobs very well, and there are plenty of those on OMAP3. Is there any reason why we should not allow the option of userspace OPP selection/powerdomain control for OMAP? If people don't want to use it, they don't have to :-) - Paul ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 1/2] ARM: OMAP: CLKFW: Initial debugfs support for omap clock framework 2008-04-17 20:47 ` Paul Walmsley @ 2008-04-17 21:22 ` David Brownell 2008-04-18 7:08 ` Igor Stoppa 1 sibling, 0 replies; 21+ messages in thread From: David Brownell @ 2008-04-17 21:22 UTC (permalink / raw) To: Paul Walmsley; +Cc: Igor Stoppa, Hiroshi DOYU, linux-omap On Thursday 17 April 2008, Paul Walmsley wrote: > > > > Userspace should limit itself to changing policies. > > CPUFreq is good, but it does not manage non-CPU-frequency knobs very well, > and there are plenty of those on OMAP3. Similar issues are widely acknowledged. > Is there any reason why we should not allow the option of userspace OPP > selection/powerdomain control for OMAP? If people don't want to use it, > they don't have to :-) Sure, allow userspace controls. Even use debugs to prototype them. Just don't build fragile interfaces ... don't expect userspace code to do the equivalent of open heart surgery. - Dave -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 1/2] ARM: OMAP: CLKFW: Initial debugfs support for omap clock framework 2008-04-17 20:47 ` Paul Walmsley 2008-04-17 21:22 ` David Brownell @ 2008-04-18 7:08 ` Igor Stoppa 1 sibling, 0 replies; 21+ messages in thread From: Igor Stoppa @ 2008-04-18 7:08 UTC (permalink / raw) To: ext Paul Walmsley; +Cc: David Brownell, Hiroshi DOYU, linux-omap Hi Paul, On Thu, 2008-04-17 at 14:47 -0600, ext Paul Walmsley wrote: > Hello Igor, > > On Thu, 17 Apr 2008, Igor Stoppa wrote: > > > On Thu, 2008-04-17 at 13:44 -0600, ext Paul Walmsley wrote: > > > > > True, but if we can do a debugfs implementation first, then that seems > > > like a good way to start, no? Userspace PM implementations are probably > > > some months in the future, and we can mandate that debugfs be mounted for > > > those. > > > > I can hardly see the benefit of a userspace implementation, considering > > the extra context switch required and the fact the in many cases clocks > > get enabled in response to irqs. > > I agree that we shouldn't try to move the clock framework to userspace. > > But, determining what OPP to switch to next, based on system load or other > requirements published by drivers or userspace processes; or determining > what power state to put powerdomains to -- it would be nice to experiment > with a userspace governor for those tasks. It would certainly make > development and testing easier. yes, it can be used to play with it in its infancy state, when one is still not looking for performance/stability stress testing. Afterward it simply doesn't fit the bill of leveraging the HW response time. Notice also that with QoS information coming from different sources, mostly low level ones, this will generate lots of cache trashing. > > > In terms of the clock tree, it would be good to allow userspace-driven OPP > > > changes, analogous to CPUFreq's userspace governor. [ In general, I agree > > > that userspace should not be changing driver clocks directly, just like > > > userspace should not be mucking around in /dev/mem directly :-) ] > > > > That also sounds akward at best: cpufreq (or similar) is much better > > suited for this sort of activity; userspace governor would be the > > userspace controller you refer to, but it is far from being optimal. > > > > Userspace should limit itself to changing policies. > > CPUFreq is good, but it does not manage non-CPU-frequency knobs very well, > and there are plenty of those on OMAP3. But CPUFreq can be expanded. Call it systemfreq or whatever can be more appealing from an advertising point of view. For omap HW anything different from ondemand doesn't make much sense. Maybe performance, would be another viable option, in certain cases. > Is there any reason why we should not allow the option of userspace OPP > selection/powerdomain control for OMAP? If people don't want to use it, > they don't have to :-) No, of course freedom is good. But it shouldn't be freedom of knowingly adopt suboptimal solutions just for the sake of diversity. An approach that doesn't involve requiring userspace components can be used also for more "embedded" systems where there might be no traditional userspace. A similar case would be in replacing CPUIdle with user space based decision, which is likely far from being optimal. -- Cheers, Igor --- Igor Stoppa Next Generation Software Nokia Devices R&D - Helsinki ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 1/2] ARM: OMAP: CLKFW: Initial debugfs support for omap clock framework 2008-04-17 19:44 ` Paul Walmsley 2008-04-17 19:49 ` Igor Stoppa @ 2008-04-17 19:58 ` Hiroshi DOYU 2008-04-21 18:40 ` Tony Lindgren 1 sibling, 1 reply; 21+ messages in thread From: Hiroshi DOYU @ 2008-04-17 19:58 UTC (permalink / raw) To: paul; +Cc: david-b, linux-omap [-- Attachment #1: Type: Text/Plain, Size: 1570 bytes --] From: "ext Paul Walmsley" <paul@pwsan.com> Subject: Re: [PATCH 1/2] ARM: OMAP: CLKFW: Initial debugfs support for omap clock framework Date: Thu, 17 Apr 2008 13:44:04 -0600 (MDT) > Hello Hiroshi, David, > > On Thu, 17 Apr 2008, David Brownell wrote: > > > On Thursday 17 April 2008, Hiroshi DOYU wrote: > > > > > And if there will be a little possibility that sysfs attribute can be > > > used by userland in the future, keeping sysfs instead of debugfs > > > doesn't seem not so illegal, does it? > > True, but if we can do a debugfs implementation first, then that seems > like a good way to start, no? Userspace PM implementations are probably > some months in the future, and we can mandate that debugfs be mounted for > those. Agreed. Update ones attached. The diffs against the previous are: diff -u b/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c --- b/arch/arm/plat-omap/clock.c +++ b/arch/arm/plat-omap/clock.c @@ -524,7 +524,7 @@ p += sprintf(p, "%s", c->name); if (c->id != 0) - sprintf(p, "%d", c->id); + sprintf(p, ":%d", c->id); d = debugfs_create_dir(s, pa ? pa->dent : clk_debugfs_root); if (IS_ERR(d)) return PTR_ERR(d); diff -u b/include/asm-arm/arch-omap/clock.h b/include/asm-arm/arch-omap/clock.h --- b/include/asm-arm/arch-omap/clock.h +++ b/include/asm-arm/arch-omap/clock.h @@ -86,7 +86,7 @@ __u8 rate_offset; __u8 src_offset; #endif -#ifdef CONFIG_DEBUG_FS +#if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS) struct dentry *dent; /* For visible tree hierarchy */ #endif }; Hiroshi DOYU [-- Attachment #2: 0002-ARM-OMAP-CLKFW-Remove-procfs-entry-for-debugging.patch --] [-- Type: Text/Plain, Size: 3140 bytes --] >From fa06e7a21c08299eaa61e6c367ec8e737a8ff13b Mon Sep 17 00:00:00 2001 From: Hiroshi DOYU <Hiroshi.DOYU@nokia.com> Date: Thu, 17 Apr 2008 16:51:41 +0300 Subject: [PATCH 2/2] ARM: OMAP: CLKFW: Remove procfs entry for debugging clock framework This feature can be covered by debugfs for omap clock framework. Signed-off-by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com> --- arch/arm/plat-omap/clock.c | 96 -------------------------------------------- 1 files changed, 0 insertions(+), 96 deletions(-) diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c index 2ae87bf..714dbbf 100644 --- a/arch/arm/plat-omap/clock.c +++ b/arch/arm/plat-omap/clock.c @@ -34,41 +34,6 @@ static DEFINE_SPINLOCK(clockfw_lock); static struct clk_functions *arch_clock; -#ifdef CONFIG_PM_DEBUG - -static void print_parents(struct clk *clk) -{ - struct clk *p; - int printed = 0; - - list_for_each_entry(p, &clocks, node) { - if (p->parent == clk && p->usecount) { - if (!clk->usecount && !printed) { - printk("MISMATCH: %s\n", clk->name); - printed = 1; - } - printk("\t%-15s\n", p->name); - } - } -} - -void clk_print_usecounts(void) -{ - unsigned long flags; - struct clk *p; - - spin_lock_irqsave(&clockfw_lock, flags); - list_for_each_entry(p, &clocks, node) { - if (p->usecount) - printk("%-15s: %d\n", p->name, p->usecount); - print_parents(p); - - } - spin_unlock_irqrestore(&clockfw_lock, flags); -} - -#endif - /*------------------------------------------------------------------------- * Standard clock functions defined in include/linux/clk.h *-------------------------------------------------------------------------*/ @@ -447,67 +412,6 @@ int __init clk_init(struct clk_functions * custom_clocks) return 0; } -#if defined(CONFIG_PM_DEBUG) && defined(CONFIG_PROC_FS) -#include <linux/proc_fs.h> -#include <linux/seq_file.h> - -static void *omap_ck_start(struct seq_file *m, loff_t *pos) -{ - return *pos < 1 ? (void *)1 : NULL; -} - -static void *omap_ck_next(struct seq_file *m, void *v, loff_t *pos) -{ - ++*pos; - return NULL; -} - -static void omap_ck_stop(struct seq_file *m, void *v) -{ -} - -int omap_ck_show(struct seq_file *m, void *v) -{ - struct clk *cp; - - list_for_each_entry(cp, &clocks, node) - seq_printf(m,"%s %ld %d\n", cp->name, cp->rate, cp->usecount); - - return 0; -} - -static struct seq_operations omap_ck_op = { - .start = omap_ck_start, - .next = omap_ck_next, - .stop = omap_ck_stop, - .show = omap_ck_show -}; - -static int omap_ck_open(struct inode *inode, struct file *file) -{ - return seq_open(file, &omap_ck_op); -} - -static struct file_operations proc_omap_ck_operations = { - .open = omap_ck_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, -}; - -int __init omap_ck_init(void) -{ - struct proc_dir_entry *entry; - - entry = create_proc_entry("omap_clocks", 0, NULL); - if (entry) - entry->proc_fops = &proc_omap_ck_operations; - return 0; - -} -__initcall(omap_ck_init); -#endif - #if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS) /* * debugfs support to trace clock tree hierarchy and attributes -- 1.5.5.rc2.6.gf58d [-- Attachment #3: 0001-ARM-OMAP-CLKFW-Initial-debugfs-support-for-omap-c.patch --] [-- Type: Text/Plain, Size: 4611 bytes --] >From d0c2ffa4d45ea686020959c9d7a68f1669806d22 Mon Sep 17 00:00:00 2001 From: Hiroshi DOYU <Hiroshi.DOYU@nokia.com> Date: Thu, 17 Apr 2008 13:51:34 +0300 Subject: [PATCH 1/2] 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> --- arch/arm/plat-omap/clock.c | 94 ++++++++++++++++++++++++++++++++++++- include/asm-arm/arch-omap/clock.h | 3 + 2 files changed, 96 insertions(+), 1 deletions(-) diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c index 1bd8781..2ae87bf 100644 --- a/arch/arm/plat-omap/clock.c +++ b/arch/arm/plat-omap/clock.c @@ -1,7 +1,7 @@ /* * linux/arch/arm/plat-omap/clock.c * - * Copyright (C) 2004 - 2005 Nokia corporation + * Copyright (C) 2004 - 2008 Nokia corporation * Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com> * * Modified for omap shared clock framework by Tony Lindgren <tony@atomide.com> @@ -21,6 +21,7 @@ #include <linux/clk.h> #include <linux/mutex.h> #include <linux/platform_device.h> +#include <linux/debugfs.h> #include <asm/io.h> #include <asm/semaphore.h> @@ -506,3 +507,94 @@ int __init omap_ck_init(void) } __initcall(omap_ck_init); #endif + +#if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS) +/* + * debugfs support to trace clock tree hierarchy and attributes + */ +static struct dentry *clk_debugfs_root; + +static int clk_debugfs_register_one(struct clk *c) +{ + int err; + struct dentry *d, *child; + struct clk *pa = c->parent; + char s[255]; + char *p = s; + + p += sprintf(p, "%s", c->name); + if (c->id != 0) + sprintf(p, ":%d", c->id); + d = debugfs_create_dir(s, pa ? pa->dent : clk_debugfs_root); + if (IS_ERR(d)) + return PTR_ERR(d); + c->dent = d; + + d = debugfs_create_u8("usecount", S_IRUGO, c->dent, (u8 *)&c->usecount); + if (IS_ERR(d)) { + err = PTR_ERR(d); + goto err_out; + } + d = debugfs_create_u32("rate", S_IRUGO, c->dent, (u32 *)&c->rate); + if (IS_ERR(d)) { + err = PTR_ERR(d); + goto err_out; + } + d = debugfs_create_x32("flags", S_IRUGO, c->dent, (u32 *)&c->flags); + if (IS_ERR(d)) { + err = PTR_ERR(d); + goto err_out; + } + return 0; + +err_out: + d = c->dent; + list_for_each_entry(child, &d->d_subdirs, d_u.d_child) + debugfs_remove(child); + debugfs_remove(c->dent); + return err; +} + +static int clk_debugfs_register(struct clk *c) +{ + int err; + struct clk *pa = c->parent; + + if (pa && !pa->dent) { + err = clk_debugfs_register(pa); + if (err) + return err; + } + + if (!c->dent) { + err = clk_debugfs_register_one(c); + if (err) + return err; + } + return 0; +} + +static int __init clk_debugfs_init(void) +{ + struct clk *c; + struct dentry *d; + int err; + + d = debugfs_create_dir("clock", NULL); + if (IS_ERR(d)) + return PTR_ERR(d); + clk_debugfs_root = d; + + list_for_each_entry(c, &clocks, node) { + err = clk_debugfs_register(c); + if (err) + goto err_out; + } + return 0; +err_out: + debugfs_remove(clk_debugfs_root); /* REVISIT: Cleanup correctly */ + return err; +} +late_initcall(clk_debugfs_init); + +#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 cce55ba..811af84 100644 --- a/include/asm-arm/arch-omap/clock.h +++ b/include/asm-arm/arch-omap/clock.h @@ -86,6 +86,9 @@ struct clk { __u8 rate_offset; __u8 src_offset; #endif +#if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS) + struct dentry *dent; /* For visible tree hierarchy */ +#endif }; struct clk_functions { -- 1.5.5.rc2.6.gf58d ^ permalink raw reply related [flat|nested] 21+ messages in thread
* Re: [PATCH 1/2] ARM: OMAP: CLKFW: Initial debugfs support for omap clock framework 2008-04-17 19:58 ` Hiroshi DOYU @ 2008-04-21 18:40 ` Tony Lindgren 0 siblings, 0 replies; 21+ messages in thread From: Tony Lindgren @ 2008-04-21 18:40 UTC (permalink / raw) To: Hiroshi DOYU; +Cc: paul, david-b, linux-omap * Hiroshi DOYU <Hiroshi.DOYU@nokia.com> [080417 13:02]: > From: "ext Paul Walmsley" <paul@pwsan.com> > Subject: Re: [PATCH 1/2] ARM: OMAP: CLKFW: Initial debugfs support for omap clock framework > Date: Thu, 17 Apr 2008 13:44:04 -0600 (MDT) > > > Hello Hiroshi, David, > > > > On Thu, 17 Apr 2008, David Brownell wrote: > > > > > On Thursday 17 April 2008, Hiroshi DOYU wrote: > > > > > > > And if there will be a little possibility that sysfs attribute can be > > > > used by userland in the future, keeping sysfs instead of debugfs > > > > doesn't seem not so illegal, does it? > > > > True, but if we can do a debugfs implementation first, then that seems > > like a good way to start, no? Userspace PM implementations are probably > > some months in the future, and we can mandate that debugfs be mounted for > > those. > > Agreed. Update ones attached. The diffs against the previous are: > > diff -u b/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c > --- b/arch/arm/plat-omap/clock.c > +++ b/arch/arm/plat-omap/clock.c > @@ -524,7 +524,7 @@ > > p += sprintf(p, "%s", c->name); > if (c->id != 0) > - sprintf(p, "%d", c->id); > + sprintf(p, ":%d", c->id); > d = debugfs_create_dir(s, pa ? pa->dent : clk_debugfs_root); > if (IS_ERR(d)) > return PTR_ERR(d); > diff -u b/include/asm-arm/arch-omap/clock.h b/include/asm-arm/arch-omap/clock.h > --- b/include/asm-arm/arch-omap/clock.h > +++ b/include/asm-arm/arch-omap/clock.h > @@ -86,7 +86,7 @@ > __u8 rate_offset; > __u8 src_offset; > #endif > -#ifdef CONFIG_DEBUG_FS > +#if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS) > struct dentry *dent; /* For visible tree hierarchy */ > #endif > }; Pushing today. Tony > > Hiroshi DOYU > From fa06e7a21c08299eaa61e6c367ec8e737a8ff13b Mon Sep 17 00:00:00 2001 > From: Hiroshi DOYU <Hiroshi.DOYU@nokia.com> > Date: Thu, 17 Apr 2008 16:51:41 +0300 > Subject: [PATCH 2/2] ARM: OMAP: CLKFW: Remove procfs entry for debugging clock framework > > This feature can be covered by debugfs for omap clock framework. > > Signed-off-by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com> > --- > arch/arm/plat-omap/clock.c | 96 -------------------------------------------- > 1 files changed, 0 insertions(+), 96 deletions(-) > > diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c > index 2ae87bf..714dbbf 100644 > --- a/arch/arm/plat-omap/clock.c > +++ b/arch/arm/plat-omap/clock.c > @@ -34,41 +34,6 @@ static DEFINE_SPINLOCK(clockfw_lock); > > static struct clk_functions *arch_clock; > > -#ifdef CONFIG_PM_DEBUG > - > -static void print_parents(struct clk *clk) > -{ > - struct clk *p; > - int printed = 0; > - > - list_for_each_entry(p, &clocks, node) { > - if (p->parent == clk && p->usecount) { > - if (!clk->usecount && !printed) { > - printk("MISMATCH: %s\n", clk->name); > - printed = 1; > - } > - printk("\t%-15s\n", p->name); > - } > - } > -} > - > -void clk_print_usecounts(void) > -{ > - unsigned long flags; > - struct clk *p; > - > - spin_lock_irqsave(&clockfw_lock, flags); > - list_for_each_entry(p, &clocks, node) { > - if (p->usecount) > - printk("%-15s: %d\n", p->name, p->usecount); > - print_parents(p); > - > - } > - spin_unlock_irqrestore(&clockfw_lock, flags); > -} > - > -#endif > - > /*------------------------------------------------------------------------- > * Standard clock functions defined in include/linux/clk.h > *-------------------------------------------------------------------------*/ > @@ -447,67 +412,6 @@ int __init clk_init(struct clk_functions * custom_clocks) > return 0; > } > > -#if defined(CONFIG_PM_DEBUG) && defined(CONFIG_PROC_FS) > -#include <linux/proc_fs.h> > -#include <linux/seq_file.h> > - > -static void *omap_ck_start(struct seq_file *m, loff_t *pos) > -{ > - return *pos < 1 ? (void *)1 : NULL; > -} > - > -static void *omap_ck_next(struct seq_file *m, void *v, loff_t *pos) > -{ > - ++*pos; > - return NULL; > -} > - > -static void omap_ck_stop(struct seq_file *m, void *v) > -{ > -} > - > -int omap_ck_show(struct seq_file *m, void *v) > -{ > - struct clk *cp; > - > - list_for_each_entry(cp, &clocks, node) > - seq_printf(m,"%s %ld %d\n", cp->name, cp->rate, cp->usecount); > - > - return 0; > -} > - > -static struct seq_operations omap_ck_op = { > - .start = omap_ck_start, > - .next = omap_ck_next, > - .stop = omap_ck_stop, > - .show = omap_ck_show > -}; > - > -static int omap_ck_open(struct inode *inode, struct file *file) > -{ > - return seq_open(file, &omap_ck_op); > -} > - > -static struct file_operations proc_omap_ck_operations = { > - .open = omap_ck_open, > - .read = seq_read, > - .llseek = seq_lseek, > - .release = seq_release, > -}; > - > -int __init omap_ck_init(void) > -{ > - struct proc_dir_entry *entry; > - > - entry = create_proc_entry("omap_clocks", 0, NULL); > - if (entry) > - entry->proc_fops = &proc_omap_ck_operations; > - return 0; > - > -} > -__initcall(omap_ck_init); > -#endif > - > #if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS) > /* > * debugfs support to trace clock tree hierarchy and attributes > -- > 1.5.5.rc2.6.gf58d > > From d0c2ffa4d45ea686020959c9d7a68f1669806d22 Mon Sep 17 00:00:00 2001 > From: Hiroshi DOYU <Hiroshi.DOYU@nokia.com> > Date: Thu, 17 Apr 2008 13:51:34 +0300 > Subject: [PATCH 1/2] 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> > --- > arch/arm/plat-omap/clock.c | 94 ++++++++++++++++++++++++++++++++++++- > include/asm-arm/arch-omap/clock.h | 3 + > 2 files changed, 96 insertions(+), 1 deletions(-) > > diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c > index 1bd8781..2ae87bf 100644 > --- a/arch/arm/plat-omap/clock.c > +++ b/arch/arm/plat-omap/clock.c > @@ -1,7 +1,7 @@ > /* > * linux/arch/arm/plat-omap/clock.c > * > - * Copyright (C) 2004 - 2005 Nokia corporation > + * Copyright (C) 2004 - 2008 Nokia corporation > * Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com> > * > * Modified for omap shared clock framework by Tony Lindgren <tony@atomide.com> > @@ -21,6 +21,7 @@ > #include <linux/clk.h> > #include <linux/mutex.h> > #include <linux/platform_device.h> > +#include <linux/debugfs.h> > > #include <asm/io.h> > #include <asm/semaphore.h> > @@ -506,3 +507,94 @@ int __init omap_ck_init(void) > } > __initcall(omap_ck_init); > #endif > + > +#if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS) > +/* > + * debugfs support to trace clock tree hierarchy and attributes > + */ > +static struct dentry *clk_debugfs_root; > + > +static int clk_debugfs_register_one(struct clk *c) > +{ > + int err; > + struct dentry *d, *child; > + struct clk *pa = c->parent; > + char s[255]; > + char *p = s; > + > + p += sprintf(p, "%s", c->name); > + if (c->id != 0) > + sprintf(p, ":%d", c->id); > + d = debugfs_create_dir(s, pa ? pa->dent : clk_debugfs_root); > + if (IS_ERR(d)) > + return PTR_ERR(d); > + c->dent = d; > + > + d = debugfs_create_u8("usecount", S_IRUGO, c->dent, (u8 *)&c->usecount); > + if (IS_ERR(d)) { > + err = PTR_ERR(d); > + goto err_out; > + } > + d = debugfs_create_u32("rate", S_IRUGO, c->dent, (u32 *)&c->rate); > + if (IS_ERR(d)) { > + err = PTR_ERR(d); > + goto err_out; > + } > + d = debugfs_create_x32("flags", S_IRUGO, c->dent, (u32 *)&c->flags); > + if (IS_ERR(d)) { > + err = PTR_ERR(d); > + goto err_out; > + } > + return 0; > + > +err_out: > + d = c->dent; > + list_for_each_entry(child, &d->d_subdirs, d_u.d_child) > + debugfs_remove(child); > + debugfs_remove(c->dent); > + return err; > +} > + > +static int clk_debugfs_register(struct clk *c) > +{ > + int err; > + struct clk *pa = c->parent; > + > + if (pa && !pa->dent) { > + err = clk_debugfs_register(pa); > + if (err) > + return err; > + } > + > + if (!c->dent) { > + err = clk_debugfs_register_one(c); > + if (err) > + return err; > + } > + return 0; > +} > + > +static int __init clk_debugfs_init(void) > +{ > + struct clk *c; > + struct dentry *d; > + int err; > + > + d = debugfs_create_dir("clock", NULL); > + if (IS_ERR(d)) > + return PTR_ERR(d); > + clk_debugfs_root = d; > + > + list_for_each_entry(c, &clocks, node) { > + err = clk_debugfs_register(c); > + if (err) > + goto err_out; > + } > + return 0; > +err_out: > + debugfs_remove(clk_debugfs_root); /* REVISIT: Cleanup correctly */ > + return err; > +} > +late_initcall(clk_debugfs_init); > + > +#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 cce55ba..811af84 100644 > --- a/include/asm-arm/arch-omap/clock.h > +++ b/include/asm-arm/arch-omap/clock.h > @@ -86,6 +86,9 @@ struct clk { > __u8 rate_offset; > __u8 src_offset; > #endif > +#if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS) > + struct dentry *dent; /* For visible tree hierarchy */ > +#endif > }; > > struct clk_functions { > -- > 1.5.5.rc2.6.gf58d > ^ permalink raw reply [flat|nested] 21+ messages in thread
end of thread, other threads:[~2008-04-21 18:40 UTC | newest] Thread overview: 21+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2008-04-16 8:44 [PATCH 1/1] ARM: OMAP: CLKFW: Initial sysfs support for omap clock framework Hiroshi DOYU 2008-04-16 8:57 ` Hiroshi DOYU 2008-04-16 13:20 ` Hiroshi DOYU 2008-04-16 16:58 ` David Brownell 2008-04-16 20:51 ` Tony Lindgren 2008-04-17 14:09 ` [PATCH 1/2] ARM: OMAP: CLKFW: Initial debugfs " Hiroshi DOYU 2008-04-17 14:09 ` [PATCH 2/2] ARM: OMAP: CLKFW: Remove procfs entry for debugging " Hiroshi DOYU 2008-04-17 16:23 ` [PATCH 1/2] ARM: OMAP: CLKFW: Initial debugfs support for omap " Paul Walmsley 2008-04-17 18:40 ` David Brownell 2008-04-17 18:45 ` Paul Walmsley 2008-04-17 18:54 ` David Brownell 2008-04-17 19:17 ` Paul Walmsley 2008-04-17 18:57 ` Hiroshi DOYU 2008-04-17 19:14 ` David Brownell 2008-04-17 19:44 ` Paul Walmsley 2008-04-17 19:49 ` Igor Stoppa 2008-04-17 20:47 ` Paul Walmsley 2008-04-17 21:22 ` David Brownell 2008-04-18 7:08 ` Igor Stoppa 2008-04-17 19:58 ` Hiroshi DOYU 2008-04-21 18:40 ` Tony Lindgren
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox