summaryrefslogtreecommitdiff
path: root/arch/arm/mach-tegra
diff options
context:
space:
mode:
authorAlex Frid <afrid@nvidia.com>2011-01-07 19:11:26 -0800
committerDan Willemsen <dwillemsen@nvidia.com>2011-11-30 21:41:56 -0800
commit4499f598e2af7ede7ab81d1a20d9671126e2922d (patch)
treee9a50c7ba251b1f99da0b9fdd609752f8ecfdf72 /arch/arm/mach-tegra
parent159337819fc5ee944c8a75f08dec7ad1ea8ee4b1 (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
Diffstat (limited to 'arch/arm/mach-tegra')
-rw-r--r--arch/arm/mach-tegra/Kconfig5
-rw-r--r--arch/arm/mach-tegra/clock.c93
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;