aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-omap2/pm-debug.c178
-rw-r--r--arch/arm/mach-omap2/pm.h4
-rw-r--r--arch/arm/plat-omap/include/mach/powerdomain.h5
3 files changed, 186 insertions, 1 deletions
diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c
index da3a53f8ccc8..7383e85eac26 100644
--- a/arch/arm/mach-omap2/pm-debug.c
+++ b/arch/arm/mach-omap2/pm-debug.c
@@ -20,13 +20,15 @@
20 */ 20 */
21 21
22#include <linux/kernel.h> 22#include <linux/kernel.h>
23#include <linux/timer.h> 23#include <linux/sched.h>
24#include <linux/clk.h> 24#include <linux/clk.h>
25#include <linux/err.h> 25#include <linux/err.h>
26#include <linux/io.h> 26#include <linux/io.h>
27 27
28#include <mach/clock.h> 28#include <mach/clock.h>
29#include <mach/board.h> 29#include <mach/board.h>
30#include <mach/powerdomain.h>
31#include <mach/clockdomain.h>
30 32
31#include "prm.h" 33#include "prm.h"
32#include "cm.h" 34#include "cm.h"
@@ -150,3 +152,177 @@ void omap2_pm_dump(int mode, int resume, unsigned int us)
150 for (i = 0; i < reg_count; i++) 152 for (i = 0; i < reg_count; i++)
151 printk(KERN_INFO "%-20s: 0x%08x\n", regs[i].name, regs[i].val); 153 printk(KERN_INFO "%-20s: 0x%08x\n", regs[i].name, regs[i].val);
152} 154}
155
156#ifdef CONFIG_DEBUG_FS
157#include <linux/debugfs.h>
158#include <linux/seq_file.h>
159
160struct dentry *pm_dbg_dir;
161
162static int pm_dbg_init_done;
163
164enum {
165 DEBUG_FILE_COUNTERS = 0,
166 DEBUG_FILE_TIMERS,
167};
168
169static const char pwrdm_state_names[][4] = {
170 "OFF",
171 "RET",
172 "INA",
173 "ON"
174};
175
176void pm_dbg_update_time(struct powerdomain *pwrdm, int prev)
177{
178 s64 t;
179
180 if (!pm_dbg_init_done)
181 return ;
182
183 /* Update timer for previous state */
184 t = sched_clock();
185
186 pwrdm->state_timer[prev] += t - pwrdm->timer;
187
188 pwrdm->timer = t;
189}
190
191static int clkdm_dbg_show_counter(struct clockdomain *clkdm, void *user)
192{
193 struct seq_file *s = (struct seq_file *)user;
194
195 if (strcmp(clkdm->name, "emu_clkdm") == 0 ||
196 strcmp(clkdm->name, "wkup_clkdm") == 0 ||
197 strncmp(clkdm->name, "dpll", 4) == 0)
198 return 0;
199
200 seq_printf(s, "%s->%s (%d)", clkdm->name,
201 clkdm->pwrdm.ptr->name,
202 atomic_read(&clkdm->usecount));
203 seq_printf(s, "\n");
204
205 return 0;
206}
207
208static int pwrdm_dbg_show_counter(struct powerdomain *pwrdm, void *user)
209{
210 struct seq_file *s = (struct seq_file *)user;
211 int i;
212
213 if (strcmp(pwrdm->name, "emu_pwrdm") == 0 ||
214 strcmp(pwrdm->name, "wkup_pwrdm") == 0 ||
215 strncmp(pwrdm->name, "dpll", 4) == 0)
216 return 0;
217
218 if (pwrdm->state != pwrdm_read_pwrst(pwrdm))
219 printk(KERN_ERR "pwrdm state mismatch(%s) %d != %d\n",
220 pwrdm->name, pwrdm->state, pwrdm_read_pwrst(pwrdm));
221
222 seq_printf(s, "%s (%s)", pwrdm->name,
223 pwrdm_state_names[pwrdm->state]);
224 for (i = 0; i < 4; i++)
225 seq_printf(s, ",%s:%d", pwrdm_state_names[i],
226 pwrdm->state_counter[i]);
227
228 seq_printf(s, "\n");
229
230 return 0;
231}
232
233static int pwrdm_dbg_show_timer(struct powerdomain *pwrdm, void *user)
234{
235 struct seq_file *s = (struct seq_file *)user;
236 int i;
237
238 if (strcmp(pwrdm->name, "emu_pwrdm") == 0 ||
239 strcmp(pwrdm->name, "wkup_pwrdm") == 0 ||
240 strncmp(pwrdm->name, "dpll", 4) == 0)
241 return 0;
242
243 pwrdm_state_switch(pwrdm);
244
245 seq_printf(s, "%s (%s)", pwrdm->name,
246 pwrdm_state_names[pwrdm->state]);
247
248 for (i = 0; i < 4; i++)
249 seq_printf(s, ",%s:%lld", pwrdm_state_names[i],
250 pwrdm->state_timer[i]);
251
252 seq_printf(s, "\n");
253 return 0;
254}
255
256static int pm_dbg_show_counters(struct seq_file *s, void *unused)
257{
258 pwrdm_for_each(pwrdm_dbg_show_counter, s);
259 clkdm_for_each(clkdm_dbg_show_counter, s);
260
261 return 0;
262}
263
264static int pm_dbg_show_timers(struct seq_file *s, void *unused)
265{
266 pwrdm_for_each(pwrdm_dbg_show_timer, s);
267 return 0;
268}
269
270static int pm_dbg_open(struct inode *inode, struct file *file)
271{
272 switch ((int)inode->i_private) {
273 case DEBUG_FILE_COUNTERS:
274 return single_open(file, pm_dbg_show_counters,
275 &inode->i_private);
276 case DEBUG_FILE_TIMERS:
277 default:
278 return single_open(file, pm_dbg_show_timers,
279 &inode->i_private);
280 };
281}
282
283static const struct file_operations debug_fops = {
284 .open = pm_dbg_open,
285 .read = seq_read,
286 .llseek = seq_lseek,
287 .release = single_release,
288};
289
290static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
291{
292 int i;
293 s64 t;
294
295 t = sched_clock();
296
297 for (i = 0; i < 4; i++)
298 pwrdm->state_timer[i] = 0;
299
300 pwrdm->timer = t;
301
302 return 0;
303}
304
305static int __init pm_dbg_init(void)
306{
307 struct dentry *d;
308
309 d = debugfs_create_dir("pm_debug", NULL);
310 if (IS_ERR(d))
311 return PTR_ERR(d);
312
313 (void) debugfs_create_file("count", S_IRUGO,
314 d, (void *)DEBUG_FILE_COUNTERS, &debug_fops);
315 (void) debugfs_create_file("time", S_IRUGO,
316 d, (void *)DEBUG_FILE_TIMERS, &debug_fops);
317
318 pwrdm_for_each(pwrdms_setup, NULL);
319
320 pm_dbg_init_done = 1;
321
322 return 0;
323}
324late_initcall(pm_dbg_init);
325
326#else
327void pm_dbg_update_time(struct powerdomain *pwrdm, int prev) {}
328#endif
diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
index 21201cd4117b..4589db1c8af8 100644
--- a/arch/arm/mach-omap2/pm.h
+++ b/arch/arm/mach-omap2/pm.h
@@ -11,12 +11,16 @@
11#ifndef __ARCH_ARM_MACH_OMAP2_PM_H 11#ifndef __ARCH_ARM_MACH_OMAP2_PM_H
12#define __ARCH_ARM_MACH_OMAP2_PM_H 12#define __ARCH_ARM_MACH_OMAP2_PM_H
13 13
14#include <mach/powerdomain.h>
15
14#ifdef CONFIG_PM_DEBUG 16#ifdef CONFIG_PM_DEBUG
15extern void omap2_pm_dump(int mode, int resume, unsigned int us); 17extern void omap2_pm_dump(int mode, int resume, unsigned int us);
16extern int omap2_pm_debug; 18extern int omap2_pm_debug;
19extern void pm_dbg_update_time(struct powerdomain *pwrdm, int prev);
17#else 20#else
18#define omap2_pm_dump(mode, resume, us) do {} while (0); 21#define omap2_pm_dump(mode, resume, us) do {} while (0);
19#define omap2_pm_debug 0 22#define omap2_pm_debug 0
23#define pm_dbg_update_time(pwrdm, prev) do {} while (0);
20#endif /* CONFIG_PM_DEBUG */ 24#endif /* CONFIG_PM_DEBUG */
21 25
22extern void omap24xx_idle_loop_suspend(void); 26extern void omap24xx_idle_loop_suspend(void);
diff --git a/arch/arm/plat-omap/include/mach/powerdomain.h b/arch/arm/plat-omap/include/mach/powerdomain.h
index de03f3dbbf3d..6271d8556a40 100644
--- a/arch/arm/plat-omap/include/mach/powerdomain.h
+++ b/arch/arm/plat-omap/include/mach/powerdomain.h
@@ -119,6 +119,11 @@ struct powerdomain {
119 119
120 int state; 120 int state;
121 unsigned state_counter[4]; 121 unsigned state_counter[4];
122
123#ifdef CONFIG_PM_DEBUG
124 s64 timer;
125 s64 state_timer[4];
126#endif
122}; 127};
123 128
124 129