diff options
author | Alex Frid <afrid@nvidia.com> | 2011-01-07 19:11:26 -0800 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2011-11-30 21:41:56 -0800 |
commit | 4499f598e2af7ede7ab81d1a20d9671126e2922d (patch) | |
tree | e9a50c7ba251b1f99da0b9fdd609752f8ecfdf72 | |
parent | 159337819fc5ee944c8a75f08dec7ad1ea8ee4b1 (diff) |
ARM: tegra: clock: Add debugfs clock set methods
Implemented debugfs clock write mechanism (disabled by default).
Expanded and fixed debugfs clock nodes to properly read clock
parent and rate.
Original-Change-Id: I9f20994d0829634e09f4bccd6fce6c7c8b5bf844
Reviewed-on: http://git-master/r/15315
Tested-by: Amit Kamath <akamath@nvidia.com>
Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>
Rebase-Id: Ra802d13d77e74c6e8def92a93c08157f8eb888fe
-rw-r--r-- | arch/arm/mach-tegra/Kconfig | 5 | ||||
-rw-r--r-- | arch/arm/mach-tegra/clock.c | 93 |
2 files changed, 96 insertions, 2 deletions
diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig index d20ab5b559ff..87b0f8a69fe3 100644 --- a/arch/arm/mach-tegra/Kconfig +++ b/arch/arm/mach-tegra/Kconfig @@ -163,4 +163,9 @@ config WIFI_CONTROL_FUNC help Enables Power/Reset/Carddetect function abstraction +config TEGRA_CLOCK_DEBUG_WRITE + bool "Enable debugfs write access to clock tree" + depends on DEBUG_FS + default n + endif diff --git a/arch/arm/mach-tegra/clock.c b/arch/arm/mach-tegra/clock.c index 1f68b97a584c..889c032767f4 100644 --- a/arch/arm/mach-tegra/clock.c +++ b/arch/arm/mach-tegra/clock.c @@ -26,6 +26,7 @@ #include <linux/module.h> #include <linux/seq_file.h> #include <linux/slab.h> +#include <linux/uaccess.h> #include <mach/clk.h> @@ -773,6 +774,88 @@ static const struct file_operations possible_parents_fops = { .release = single_release, }; +static int parent_show(struct seq_file *s, void *data) +{ + struct clk *c = s->private; + struct clk *p = clk_get_parent(c); + + seq_printf(s, "%s\n", p ? p->name : "clk_root"); + return 0; +} + +static int parent_open(struct inode *inode, struct file *file) +{ + return single_open(file, parent_show, inode->i_private); +} + +static int rate_get(void *data, u64 *val) +{ + struct clk *c = (struct clk *)data; + *val = (u64)clk_get_rate(c); + return 0; +} + +#ifdef CONFIG_TEGRA_CLOCK_DEBUG_WRITE + +static const mode_t parent_rate_mode = S_IRUGO | S_IWUGO; + +static ssize_t parent_write(struct file *file, + const char __user *userbuf, size_t count, loff_t *ppos) +{ + struct seq_file *s = file->private_data; + struct clk *c = s->private; + struct clk *p = NULL; + char buf[32]; + + if (sizeof(buf) <= count) + return -EINVAL; + + if (copy_from_user(buf, userbuf, count)) + return -EFAULT; + + /* terminate buffer and trim - white spaces may be appended + * at the end when invoked from shell command line */ + buf[count]='\0'; + strim(buf); + + p = tegra_get_clock_by_name(buf); + if (!p) + return -EINVAL; + + clk_set_parent(c, p); + return count; +} + +static const struct file_operations parent_fops = { + .open = parent_open, + .read = seq_read, + .write = parent_write, + .llseek = seq_lseek, + .release = single_release, +}; + +static int rate_set(void *data, u64 val) +{ + struct clk *c = (struct clk *)data; + clk_set_rate(c, (unsigned long)val); + return 0; +} +DEFINE_SIMPLE_ATTRIBUTE(rate_fops, rate_get, rate_set, "%llu\n"); + +#else + +static const mode_t parent_rate_mode = S_IRUGO; + +static const struct file_operations parent_fops = { + .open = parent_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +DEFINE_SIMPLE_ATTRIBUTE(rate_fops, rate_get, NULL, "%llu\n"); +#endif + static int clk_debugfs_register_one(struct clk *c) { struct dentry *d; @@ -786,11 +869,17 @@ static int clk_debugfs_register_one(struct clk *c) if (!d) goto err_out; - d = debugfs_create_u32("rate", S_IRUGO, c->dent, (u32 *)&c->rate); + d = debugfs_create_x32("flags", S_IRUGO, c->dent, (u32 *)&c->flags); if (!d) goto err_out; - d = debugfs_create_x32("flags", S_IRUGO, c->dent, (u32 *)&c->flags); + d = debugfs_create_file( + "parent", parent_rate_mode, c->dent, c, &parent_fops); + if (!d) + goto err_out; + + d = debugfs_create_file( + "rate", parent_rate_mode, c->dent, c, &rate_fops); if (!d) goto err_out; |