aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Brownell <david-b@pacbell.net>2007-08-09 23:56:07 -0400
committerHaavard Skinnemoen <hskinnemoen@atmel.com>2007-10-11 05:38:41 -0400
commitd938b89392bd3ff64e0610d8c4e0d3f7091d98db (patch)
treeba1b94b3387e031506fbac50f398afc1cff949fb
parent2417a130bd4013f804983c62cb116bc9ec7f8e2d (diff)
[AVR32] /sys/kernel/debug/at32ap_clk
When debugfs is available, /sys/kernel/debug/at32ap_clk will provide a dump of the power manager registers and of the current clock tree. This can help sorting out various surprises, and when making runtime PM work. Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Signed-off-by: Haavard Skinnemoen <hskinnemoen@atmel.com>
-rw-r--r--arch/avr32/mach-at32ap/clock.c116
1 files changed, 116 insertions, 0 deletions
diff --git a/arch/avr32/mach-at32ap/clock.c b/arch/avr32/mach-at32ap/clock.c
index 0f8c89c9f832..4642117cc9ab 100644
--- a/arch/avr32/mach-at32ap/clock.c
+++ b/arch/avr32/mach-at32ap/clock.c
@@ -150,3 +150,119 @@ struct clk *clk_get_parent(struct clk *clk)
150 return clk->parent; 150 return clk->parent;
151} 151}
152EXPORT_SYMBOL(clk_get_parent); 152EXPORT_SYMBOL(clk_get_parent);
153
154
155
156#ifdef CONFIG_DEBUG_FS
157
158/* /sys/kernel/debug/at32ap_clk */
159
160#include <linux/io.h>
161#include <linux/debugfs.h>
162#include <linux/seq_file.h>
163#include "pm.h"
164
165
166#define NEST_DELTA 2
167#define NEST_MAX 6
168
169struct clkinf {
170 struct seq_file *s;
171 unsigned nest;
172};
173
174static void
175dump_clock(struct clk *parent, struct clkinf *r)
176{
177 unsigned nest = r->nest;
178 char buf[16 + NEST_MAX];
179 struct clk *clk;
180 unsigned i;
181
182 /* skip clocks coupled to devices that aren't registered */
183 if (parent->dev && !parent->dev->bus_id[0] && !parent->users)
184 return;
185
186 /* <nest spaces> name <pad to end> */
187 memset(buf, ' ', sizeof(buf) - 1);
188 buf[sizeof(buf) - 1] = 0;
189 i = strlen(parent->name);
190 memcpy(buf + nest, parent->name,
191 min(i, (unsigned)(sizeof(buf) - 1 - nest)));
192
193 seq_printf(r->s, "%s%c users=%2d %-3s %9ld Hz",
194 buf, parent->set_parent ? '*' : ' ',
195 parent->users,
196 parent->users ? "on" : "off", /* NOTE: not-paranoid!! */
197 clk_get_rate(parent));
198 if (parent->dev)
199 seq_printf(r->s, ", for %s", parent->dev->bus_id);
200 seq_printf(r->s, "\n");
201
202 /* cost of this scan is small, but not linear... */
203 r->nest = nest + NEST_DELTA;
204 for (i = 3; i < at32_nr_clocks; i++) {
205 clk = at32_clock_list[i];
206 if (clk->parent == parent)
207 dump_clock(clk, r);
208 }
209 r->nest = nest;
210}
211
212static int clk_show(struct seq_file *s, void *unused)
213{
214 struct clkinf r;
215 int i;
216
217 /* show all the power manager registers */
218 seq_printf(s, "MCCTRL = %8x\n", pm_readl(MCCTRL));
219 seq_printf(s, "CKSEL = %8x\n", pm_readl(CKSEL));
220 seq_printf(s, "CPUMASK = %8x\n", pm_readl(CPU_MASK));
221 seq_printf(s, "HSBMASK = %8x\n", pm_readl(HSB_MASK));
222 seq_printf(s, "PBAMASK = %8x\n", pm_readl(PBA_MASK));
223 seq_printf(s, "PBBMASK = %8x\n", pm_readl(PBB_MASK));
224 seq_printf(s, "PLL0 = %8x\n", pm_readl(PLL0));
225 seq_printf(s, "PLL1 = %8x\n", pm_readl(PLL1));
226 seq_printf(s, "IMR = %8x\n", pm_readl(IMR));
227 for (i = 0; i < 8; i++) {
228 if (i == 5)
229 continue;
230 seq_printf(s, "GCCTRL%d = %8x\n", i, pm_readl(GCCTRL(i)));
231 }
232
233 seq_printf(s, "\n");
234
235 /* show clock tree as derived from the three oscillators
236 * we "know" are at the head of the list
237 */
238 r.s = s;
239 r.nest = 0;
240 dump_clock(at32_clock_list[0], &r);
241 dump_clock(at32_clock_list[1], &r);
242 dump_clock(at32_clock_list[2], &r);
243
244 return 0;
245}
246
247static int clk_open(struct inode *inode, struct file *file)
248{
249 return single_open(file, clk_show, NULL);
250}
251
252static const struct file_operations clk_operations = {
253 .open = clk_open,
254 .read = seq_read,
255 .llseek = seq_lseek,
256 .release = single_release,
257};
258
259static int __init clk_debugfs_init(void)
260{
261 (void) debugfs_create_file("at32ap_clk", S_IFREG | S_IRUGO,
262 NULL, NULL, &clk_operations);
263
264 return 0;
265}
266postcore_initcall(clk_debugfs_init);
267
268#endif