public inbox for linux-omap@vger.kernel.org
 help / color / mirror / Atom feed
* [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

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