Initial Contribution
msm-2.6.38: tag AU_LINUX_ANDROID_GINGERBREAD.02.03.04.00.142
Signed-off-by: Bryan Huntsman <bryanh@codeaurora.org>
diff --git a/arch/arm/mach-msm/clock-debug.c b/arch/arm/mach-msm/clock-debug.c
index 4886404..36bc124 100644
--- a/arch/arm/mach-msm/clock-debug.c
+++ b/arch/arm/mach-msm/clock-debug.c
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2007-2010, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2007-2011, Code Aurora Forum. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -17,7 +17,11 @@
#include <linux/module.h>
#include <linux/ctype.h>
#include <linux/debugfs.h>
+#include <linux/seq_file.h>
#include <linux/clk.h>
+#include <linux/list.h>
+#include <linux/clkdev.h>
+
#include "clock.h"
static int clock_debug_rate_set(void *data, u64 val)
@@ -27,15 +31,15 @@
/* Only increases to max rate will succeed, but that's actually good
* for debugging purposes so we don't check for error. */
- if (clock->flags & CLK_MAX)
+ if (clock->flags & CLKFLAG_MAX)
clk_set_max_rate(clock, val);
- if (clock->flags & CLK_MIN)
+ if (clock->flags & CLKFLAG_MIN)
ret = clk_set_min_rate(clock, val);
else
ret = clk_set_rate(clock, val);
if (ret != 0)
printk(KERN_ERR "clk_set%s_rate failed (%d)\n",
- (clock->flags & CLK_MIN) ? "_min" : "", ret);
+ (clock->flags & CLKFLAG_MIN) ? "_min" : "", ret);
return ret;
}
@@ -49,15 +53,32 @@
DEFINE_SIMPLE_ATTRIBUTE(clock_rate_fops, clock_debug_rate_get,
clock_debug_rate_set, "%llu\n");
+static struct clk *measure;
+
+static int clock_debug_measure_get(void *data, u64 *val)
+{
+ int ret;
+ struct clk *clock = data;
+
+ ret = clk_set_parent(measure, clock);
+ if (!ret)
+ *val = clk_get_rate(measure);
+
+ return ret;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(clock_measure_fops, clock_debug_measure_get,
+ NULL, "%lld\n");
+
static int clock_debug_enable_set(void *data, u64 val)
{
struct clk *clock = data;
int rc = 0;
if (val)
- rc = clock->ops->enable(clock->id);
+ rc = clk_enable(clock);
else
- clock->ops->disable(clock->id);
+ clk_disable(clock);
return rc;
}
@@ -65,20 +86,25 @@
static int clock_debug_enable_get(void *data, u64 *val)
{
struct clk *clock = data;
+ int enabled;
- *val = clock->ops->is_enabled(clock->id);
+ if (clock->ops->is_enabled)
+ enabled = clock->ops->is_enabled(clock);
+ else
+ enabled = !!(clock->count);
+ *val = enabled;
return 0;
}
DEFINE_SIMPLE_ATTRIBUTE(clock_enable_fops, clock_debug_enable_get,
- clock_debug_enable_set, "%llu\n");
+ clock_debug_enable_set, "%lld\n");
static int clock_debug_local_get(void *data, u64 *val)
{
struct clk *clock = data;
- *val = clock->ops->is_local(clock->id);
+ *val = clock->ops->is_local(clock);
return 0;
}
@@ -87,15 +113,83 @@
NULL, "%llu\n");
static struct dentry *debugfs_base;
+static u32 debug_suspend;
+static struct clk_lookup *msm_clocks;
+static unsigned num_msm_clocks;
-int __init clock_debug_init(void)
+int __init clock_debug_init(struct clk_lookup *clocks, unsigned num_clocks)
{
+ int ret = 0;
+
debugfs_base = debugfs_create_dir("clk", NULL);
if (!debugfs_base)
return -ENOMEM;
+ if (!debugfs_create_u32("debug_suspend", S_IRUGO | S_IWUSR,
+ debugfs_base, &debug_suspend)) {
+ debugfs_remove_recursive(debugfs_base);
+ return -ENOMEM;
+ }
+ msm_clocks = clocks;
+ num_msm_clocks = num_clocks;
+
+ measure = clk_get_sys("debug", "measure");
+ if (IS_ERR(measure)) {
+ ret = PTR_ERR(measure);
+ measure = NULL;
+ }
+
+ return ret;
+}
+
+void clock_debug_print_enabled(void)
+{
+ struct clk *clk;
+ unsigned i;
+ int cnt = 0;
+
+ if (likely(!debug_suspend))
+ return;
+
+ pr_info("Enabled clocks:\n");
+ for (i = 0; i < num_msm_clocks; i++) {
+ clk = msm_clocks[i].clk;
+
+ if (clk && clk->ops->is_enabled(clk)) {
+ pr_info("\t%s\n", clk->dbg_name);
+ cnt++;
+ }
+ }
+
+ if (cnt)
+ pr_info("Enabled clock count: %d\n", cnt);
+ else
+ pr_info("No clocks enabled.\n");
+
+}
+
+static int list_rates_show(struct seq_file *m, void *unused)
+{
+ struct clk *clock = m->private;
+ int rate, i = 0;
+
+ while ((rate = clock->ops->list_rate(clock, i++)) >= 0)
+ seq_printf(m, "%d\n", rate);
+
return 0;
}
+static int list_rates_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, list_rates_show, inode->i_private);
+}
+
+static const struct file_operations list_rates_fops = {
+ .open = list_rates_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
int __init clock_debug_add(struct clk *clock)
{
char temp[50], *ptr;
@@ -123,6 +217,18 @@
if (!debugfs_create_file("is_local", S_IRUGO, clk_dir, clock,
&clock_local_fops))
goto error;
+
+ if (measure &&
+ !clk_set_parent(measure, clock) &&
+ !debugfs_create_file("measure", S_IRUGO, clk_dir, clock,
+ &clock_measure_fops))
+ goto error;
+
+ if (clock->ops->list_rate)
+ if (!debugfs_create_file("list_rates",
+ S_IRUGO, clk_dir, clock, &list_rates_fops))
+ goto error;
+
return 0;
error:
debugfs_remove_recursive(clk_dir);