blob: 6f603edbb4d0ba7e7802ce3e72c166284d59bb33 [file] [log] [blame]
Matt Wagantalld64560fe2011-01-26 16:20:54 -08001/*
2 * Copyright (C) 2007 Google, Inc.
3 * Copyright (c) 2007-2010, Code Aurora Forum. All rights reserved.
4 *
5 * This software is licensed under the terms of the GNU General Public
6 * License version 2, as published by the Free Software Foundation, and
7 * may be copied, distributed, and modified under those terms.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 */
15
16#include <linux/kernel.h>
17#include <linux/module.h>
18#include <linux/ctype.h>
19#include <linux/debugfs.h>
20#include <linux/clk.h>
21#include "clock.h"
22#include "clock-pcom.h"
23
24static int clock_debug_rate_set(void *data, u64 val)
25{
26 struct clk *clock = data;
27 int ret;
28
29 /* Only increases to max rate will succeed, but that's actually good
30 * for debugging purposes so we don't check for error. */
31 if (clock->flags & CLK_MAX)
32 clk_set_max_rate(clock, val);
33 if (clock->flags & CLK_MIN)
34 ret = clk_set_min_rate(clock, val);
35 else
36 ret = clk_set_rate(clock, val);
37 if (ret != 0)
38 printk(KERN_ERR "clk_set%s_rate failed (%d)\n",
39 (clock->flags & CLK_MIN) ? "_min" : "", ret);
40 return ret;
41}
42
43static int clock_debug_rate_get(void *data, u64 *val)
44{
45 struct clk *clock = data;
46 *val = clk_get_rate(clock);
47 return 0;
48}
49
50DEFINE_SIMPLE_ATTRIBUTE(clock_rate_fops, clock_debug_rate_get,
51 clock_debug_rate_set, "%llu\n");
52
53static int clock_debug_enable_set(void *data, u64 val)
54{
55 struct clk *clock = data;
56 int rc = 0;
57
58 if (val)
59 rc = clock->ops->enable(clock->id);
60 else
61 clock->ops->disable(clock->id);
62
63 return rc;
64}
65
66static int clock_debug_enable_get(void *data, u64 *val)
67{
68 struct clk *clock = data;
69
70 *val = clock->ops->is_enabled(clock->id);
71
72 return 0;
73}
74
75DEFINE_SIMPLE_ATTRIBUTE(clock_enable_fops, clock_debug_enable_get,
76 clock_debug_enable_set, "%llu\n");
77
78static int clock_debug_local_get(void *data, u64 *val)
79{
80 struct clk *clock = data;
81
82 *val = clock->ops != &clk_ops_pcom;
83
84 return 0;
85}
86
87DEFINE_SIMPLE_ATTRIBUTE(clock_local_fops, clock_debug_local_get,
88 NULL, "%llu\n");
89
90static struct dentry *dent_rate, *dent_enable, *dent_local;
91
92int __init clock_debug_init(void)
93{
94 dent_rate = debugfs_create_dir("clk_rate", 0);
95 if (!dent_rate)
96 goto err;
97
98 dent_enable = debugfs_create_dir("clk_enable", 0);
99 if (!dent_enable)
100 goto err;
101
102 dent_local = debugfs_create_dir("clk_local", NULL);
103 if (!dent_local)
104 goto err;
105
106 return 0;
107err:
108 debugfs_remove(dent_local);
109 debugfs_remove(dent_enable);
110 debugfs_remove(dent_rate);
111 return -ENOMEM;
112}
113
114int __init clock_debug_add(struct clk *clock)
115{
116 char temp[50], *ptr;
117
118 if (!dent_rate || !dent_enable || !dent_local)
119 return -ENOMEM;
120
121 strncpy(temp, clock->dbg_name, ARRAY_SIZE(temp)-1);
122 for (ptr = temp; *ptr; ptr++)
123 *ptr = tolower(*ptr);
124
125 debugfs_create_file(temp, S_IRUGO | S_IWUSR, dent_rate,
126 clock, &clock_rate_fops);
127 debugfs_create_file(temp, S_IRUGO | S_IWUSR, dent_enable,
128 clock, &clock_enable_fops);
129 debugfs_create_file(temp, S_IRUGO, dent_local,
130 clock, &clock_local_fops);
131
132 return 0;
133}