Merge master.kernel.org:/pub/scm/linux/kernel/git/lethal/genesis-2.6 into devel-stable
[pandora-kernel.git] / arch / arm / mach-omap2 / pm-debug.c
1 /*
2  * OMAP Power Management debug routines
3  *
4  * Copyright (C) 2005 Texas Instruments, Inc.
5  * Copyright (C) 2006-2008 Nokia Corporation
6  *
7  * Written by:
8  * Richard Woodruff <r-woodruff2@ti.com>
9  * Tony Lindgren
10  * Juha Yrjola
11  * Amit Kucheria <amit.kucheria@nokia.com>
12  * Igor Stoppa <igor.stoppa@nokia.com>
13  * Jouni Hogander
14  *
15  * Based on pm.c for omap2
16  *
17  * This program is free software; you can redistribute it and/or modify
18  * it under the terms of the GNU General Public License version 2 as
19  * published by the Free Software Foundation.
20  */
21
22 #include <linux/kernel.h>
23 #include <linux/sched.h>
24 #include <linux/clk.h>
25 #include <linux/err.h>
26 #include <linux/io.h>
27 #include <linux/module.h>
28 #include <linux/slab.h>
29
30 #include <plat/clock.h>
31 #include <plat/board.h>
32 #include <plat/powerdomain.h>
33 #include <plat/clockdomain.h>
34 #include <plat/dmtimer.h>
35
36 #include "prm.h"
37 #include "cm.h"
38 #include "pm.h"
39
40 int omap2_pm_debug;
41 u32 enable_off_mode;
42 u32 sleep_while_idle;
43 u32 wakeup_timer_seconds;
44 u32 wakeup_timer_milliseconds;
45
46 #define DUMP_PRM_MOD_REG(mod, reg)    \
47         regs[reg_count].name = #mod "." #reg; \
48         regs[reg_count++].val = prm_read_mod_reg(mod, reg)
49 #define DUMP_CM_MOD_REG(mod, reg)     \
50         regs[reg_count].name = #mod "." #reg; \
51         regs[reg_count++].val = cm_read_mod_reg(mod, reg)
52 #define DUMP_PRM_REG(reg) \
53         regs[reg_count].name = #reg; \
54         regs[reg_count++].val = __raw_readl(reg)
55 #define DUMP_CM_REG(reg) \
56         regs[reg_count].name = #reg; \
57         regs[reg_count++].val = __raw_readl(reg)
58 #define DUMP_INTC_REG(reg, off) \
59         regs[reg_count].name = #reg; \
60         regs[reg_count++].val = \
61                          __raw_readl(OMAP2_L4_IO_ADDRESS(0x480fe000 + (off)))
62
63 void omap2_pm_dump(int mode, int resume, unsigned int us)
64 {
65         struct reg {
66                 const char *name;
67                 u32 val;
68         } regs[32];
69         int reg_count = 0, i;
70         const char *s1 = NULL, *s2 = NULL;
71
72         if (!resume) {
73 #if 0
74                 /* MPU */
75                 DUMP_PRM_MOD_REG(OCP_MOD, OMAP2_PRM_IRQENABLE_MPU_OFFSET);
76                 DUMP_CM_MOD_REG(MPU_MOD, OMAP2_CM_CLKSTCTRL);
77                 DUMP_PRM_MOD_REG(MPU_MOD, OMAP2_PM_PWSTCTRL);
78                 DUMP_PRM_MOD_REG(MPU_MOD, OMAP2_PM_PWSTST);
79                 DUMP_PRM_MOD_REG(MPU_MOD, PM_WKDEP);
80 #endif
81 #if 0
82                 /* INTC */
83                 DUMP_INTC_REG(INTC_MIR0, 0x0084);
84                 DUMP_INTC_REG(INTC_MIR1, 0x00a4);
85                 DUMP_INTC_REG(INTC_MIR2, 0x00c4);
86 #endif
87 #if 0
88                 DUMP_CM_MOD_REG(CORE_MOD, CM_FCLKEN1);
89                 if (cpu_is_omap24xx()) {
90                         DUMP_CM_MOD_REG(CORE_MOD, OMAP24XX_CM_FCLKEN2);
91                         DUMP_PRM_MOD_REG(OMAP24XX_GR_MOD,
92                                         OMAP2_PRCM_CLKEMUL_CTRL_OFFSET);
93                         DUMP_PRM_MOD_REG(OMAP24XX_GR_MOD,
94                                         OMAP2_PRCM_CLKSRC_CTRL_OFFSET);
95                 }
96                 DUMP_CM_MOD_REG(WKUP_MOD, CM_FCLKEN);
97                 DUMP_CM_MOD_REG(CORE_MOD, CM_ICLKEN1);
98                 DUMP_CM_MOD_REG(CORE_MOD, CM_ICLKEN2);
99                 DUMP_CM_MOD_REG(WKUP_MOD, CM_ICLKEN);
100                 DUMP_CM_MOD_REG(PLL_MOD, CM_CLKEN);
101                 DUMP_CM_MOD_REG(PLL_MOD, CM_AUTOIDLE);
102                 DUMP_PRM_MOD_REG(CORE_MOD, OMAP2_PM_PWSTST);
103 #endif
104 #if 0
105                 /* DSP */
106                 if (cpu_is_omap24xx()) {
107                         DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, CM_FCLKEN);
108                         DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, CM_ICLKEN);
109                         DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, CM_IDLEST);
110                         DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, CM_AUTOIDLE);
111                         DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, CM_CLKSEL);
112                         DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, OMAP2_CM_CLKSTCTRL);
113                         DUMP_PRM_MOD_REG(OMAP24XX_DSP_MOD, OMAP2_RM_RSTCTRL);
114                         DUMP_PRM_MOD_REG(OMAP24XX_DSP_MOD, OMAP2_RM_RSTST);
115                         DUMP_PRM_MOD_REG(OMAP24XX_DSP_MOD, OMAP2_PM_PWSTCTRL);
116                         DUMP_PRM_MOD_REG(OMAP24XX_DSP_MOD, OMAP2_PM_PWSTST);
117                 }
118 #endif
119         } else {
120                 DUMP_PRM_MOD_REG(CORE_MOD, PM_WKST1);
121                 if (cpu_is_omap24xx())
122                         DUMP_PRM_MOD_REG(CORE_MOD, OMAP24XX_PM_WKST2);
123                 DUMP_PRM_MOD_REG(WKUP_MOD, PM_WKST);
124                 DUMP_PRM_MOD_REG(OCP_MOD, OMAP2_PRCM_IRQSTATUS_MPU_OFFSET);
125 #if 1
126                 DUMP_INTC_REG(INTC_PENDING_IRQ0, 0x0098);
127                 DUMP_INTC_REG(INTC_PENDING_IRQ1, 0x00b8);
128                 DUMP_INTC_REG(INTC_PENDING_IRQ2, 0x00d8);
129 #endif
130         }
131
132         switch (mode) {
133         case 0:
134                 s1 = "full";
135                 s2 = "retention";
136                 break;
137         case 1:
138                 s1 = "MPU";
139                 s2 = "retention";
140                 break;
141         case 2:
142                 s1 = "MPU";
143                 s2 = "idle";
144                 break;
145         }
146
147         if (!resume)
148 #ifdef CONFIG_NO_HZ
149                 printk(KERN_INFO
150                        "--- Going to %s %s (next timer after %u ms)\n", s1, s2,
151                        jiffies_to_msecs(get_next_timer_interrupt(jiffies) -
152                                         jiffies));
153 #else
154                 printk(KERN_INFO "--- Going to %s %s\n", s1, s2);
155 #endif
156         else
157                 printk(KERN_INFO "--- Woke up (slept for %u.%03u ms)\n",
158                         us / 1000, us % 1000);
159
160         for (i = 0; i < reg_count; i++)
161                 printk(KERN_INFO "%-20s: 0x%08x\n", regs[i].name, regs[i].val);
162 }
163
164 #ifdef CONFIG_DEBUG_FS
165 #include <linux/debugfs.h>
166 #include <linux/seq_file.h>
167
168 static void pm_dbg_regset_store(u32 *ptr);
169
170 static struct dentry *pm_dbg_dir;
171
172 static int pm_dbg_init_done;
173
174 static int __init pm_dbg_init(void);
175
176 enum {
177         DEBUG_FILE_COUNTERS = 0,
178         DEBUG_FILE_TIMERS,
179 };
180
181 struct pm_module_def {
182         char name[8]; /* Name of the module */
183         short type; /* CM or PRM */
184         unsigned short offset;
185         int low; /* First register address on this module */
186         int high; /* Last register address on this module */
187 };
188
189 #define MOD_CM 0
190 #define MOD_PRM 1
191
192 static const struct pm_module_def *pm_dbg_reg_modules;
193 static const struct pm_module_def omap3_pm_reg_modules[] = {
194         { "IVA2", MOD_CM, OMAP3430_IVA2_MOD, 0, 0x4c },
195         { "OCP", MOD_CM, OCP_MOD, 0, 0x10 },
196         { "MPU", MOD_CM, MPU_MOD, 4, 0x4c },
197         { "CORE", MOD_CM, CORE_MOD, 0, 0x4c },
198         { "SGX", MOD_CM, OMAP3430ES2_SGX_MOD, 0, 0x4c },
199         { "WKUP", MOD_CM, WKUP_MOD, 0, 0x40 },
200         { "CCR", MOD_CM, PLL_MOD, 0, 0x70 },
201         { "DSS", MOD_CM, OMAP3430_DSS_MOD, 0, 0x4c },
202         { "CAM", MOD_CM, OMAP3430_CAM_MOD, 0, 0x4c },
203         { "PER", MOD_CM, OMAP3430_PER_MOD, 0, 0x4c },
204         { "EMU", MOD_CM, OMAP3430_EMU_MOD, 0x40, 0x54 },
205         { "NEON", MOD_CM, OMAP3430_NEON_MOD, 0x20, 0x48 },
206         { "USB", MOD_CM, OMAP3430ES2_USBHOST_MOD, 0, 0x4c },
207
208         { "IVA2", MOD_PRM, OMAP3430_IVA2_MOD, 0x50, 0xfc },
209         { "OCP", MOD_PRM, OCP_MOD, 4, 0x1c },
210         { "MPU", MOD_PRM, MPU_MOD, 0x58, 0xe8 },
211         { "CORE", MOD_PRM, CORE_MOD, 0x58, 0xf8 },
212         { "SGX", MOD_PRM, OMAP3430ES2_SGX_MOD, 0x58, 0xe8 },
213         { "WKUP", MOD_PRM, WKUP_MOD, 0xa0, 0xb0 },
214         { "CCR", MOD_PRM, PLL_MOD, 0x40, 0x70 },
215         { "DSS", MOD_PRM, OMAP3430_DSS_MOD, 0x58, 0xe8 },
216         { "CAM", MOD_PRM, OMAP3430_CAM_MOD, 0x58, 0xe8 },
217         { "PER", MOD_PRM, OMAP3430_PER_MOD, 0x58, 0xe8 },
218         { "EMU", MOD_PRM, OMAP3430_EMU_MOD, 0x58, 0xe4 },
219         { "GLBL", MOD_PRM, OMAP3430_GR_MOD, 0x20, 0xe4 },
220         { "NEON", MOD_PRM, OMAP3430_NEON_MOD, 0x58, 0xe8 },
221         { "USB", MOD_PRM, OMAP3430ES2_USBHOST_MOD, 0x58, 0xe8 },
222         { "", 0, 0, 0, 0 },
223 };
224
225 #define PM_DBG_MAX_REG_SETS 4
226
227 static void *pm_dbg_reg_set[PM_DBG_MAX_REG_SETS];
228
229 static int pm_dbg_get_regset_size(void)
230 {
231         static int regset_size;
232
233         if (regset_size == 0) {
234                 int i = 0;
235
236                 while (pm_dbg_reg_modules[i].name[0] != 0) {
237                         regset_size += pm_dbg_reg_modules[i].high +
238                                 4 - pm_dbg_reg_modules[i].low;
239                         i++;
240                 }
241         }
242         return regset_size;
243 }
244
245 static int pm_dbg_show_regs(struct seq_file *s, void *unused)
246 {
247         int i, j;
248         unsigned long val;
249         int reg_set = (int)s->private;
250         u32 *ptr;
251         void *store = NULL;
252         int regs;
253         int linefeed;
254
255         if (reg_set == 0) {
256                 store = kmalloc(pm_dbg_get_regset_size(), GFP_KERNEL);
257                 ptr = store;
258                 pm_dbg_regset_store(ptr);
259         } else {
260                 ptr = pm_dbg_reg_set[reg_set - 1];
261         }
262
263         i = 0;
264
265         while (pm_dbg_reg_modules[i].name[0] != 0) {
266                 regs = 0;
267                 linefeed = 0;
268                 if (pm_dbg_reg_modules[i].type == MOD_CM)
269                         seq_printf(s, "MOD: CM_%s (%08x)\n",
270                                 pm_dbg_reg_modules[i].name,
271                                 (u32)(OMAP3430_CM_BASE +
272                                 pm_dbg_reg_modules[i].offset));
273                 else
274                         seq_printf(s, "MOD: PRM_%s (%08x)\n",
275                                 pm_dbg_reg_modules[i].name,
276                                 (u32)(OMAP3430_PRM_BASE +
277                                 pm_dbg_reg_modules[i].offset));
278
279                 for (j = pm_dbg_reg_modules[i].low;
280                         j <= pm_dbg_reg_modules[i].high; j += 4) {
281                         val = *(ptr++);
282                         if (val != 0) {
283                                 regs++;
284                                 if (linefeed) {
285                                         seq_printf(s, "\n");
286                                         linefeed = 0;
287                                 }
288                                 seq_printf(s, "  %02x => %08lx", j, val);
289                                 if (regs % 4 == 0)
290                                         linefeed = 1;
291                         }
292                 }
293                 seq_printf(s, "\n");
294                 i++;
295         }
296
297         if (store != NULL)
298                 kfree(store);
299
300         return 0;
301 }
302
303 static void pm_dbg_regset_store(u32 *ptr)
304 {
305         int i, j;
306         u32 val;
307
308         i = 0;
309
310         while (pm_dbg_reg_modules[i].name[0] != 0) {
311                 for (j = pm_dbg_reg_modules[i].low;
312                         j <= pm_dbg_reg_modules[i].high; j += 4) {
313                         if (pm_dbg_reg_modules[i].type == MOD_CM)
314                                 val = cm_read_mod_reg(
315                                         pm_dbg_reg_modules[i].offset, j);
316                         else
317                                 val = prm_read_mod_reg(
318                                         pm_dbg_reg_modules[i].offset, j);
319                         *(ptr++) = val;
320                 }
321                 i++;
322         }
323 }
324
325 int pm_dbg_regset_save(int reg_set)
326 {
327         if (pm_dbg_reg_set[reg_set-1] == NULL)
328                 return -EINVAL;
329
330         pm_dbg_regset_store(pm_dbg_reg_set[reg_set-1]);
331
332         return 0;
333 }
334
335 static const char pwrdm_state_names[][PWRDM_MAX_PWRSTS] = {
336         "OFF",
337         "RET",
338         "INA",
339         "ON"
340 };
341
342 void pm_dbg_update_time(struct powerdomain *pwrdm, int prev)
343 {
344         s64 t;
345
346         if (!pm_dbg_init_done)
347                 return ;
348
349         /* Update timer for previous state */
350         t = sched_clock();
351
352         pwrdm->state_timer[prev] += t - pwrdm->timer;
353
354         pwrdm->timer = t;
355 }
356
357 void omap2_pm_wakeup_on_timer(u32 seconds, u32 milliseconds)
358 {
359         u32 tick_rate, cycles;
360
361         if (!seconds && !milliseconds)
362                 return;
363
364         tick_rate = clk_get_rate(omap_dm_timer_get_fclk(gptimer_wakeup));
365         cycles = tick_rate * seconds + tick_rate * milliseconds / 1000;
366         omap_dm_timer_stop(gptimer_wakeup);
367         omap_dm_timer_set_load_start(gptimer_wakeup, 0, 0xffffffff - cycles);
368
369         pr_info("PM: Resume timer in %u.%03u secs"
370                 " (%d ticks at %d ticks/sec.)\n",
371                 seconds, milliseconds, cycles, tick_rate);
372 }
373
374 static int clkdm_dbg_show_counter(struct clockdomain *clkdm, void *user)
375 {
376         struct seq_file *s = (struct seq_file *)user;
377
378         if (strcmp(clkdm->name, "emu_clkdm") == 0 ||
379                 strcmp(clkdm->name, "wkup_clkdm") == 0 ||
380                 strncmp(clkdm->name, "dpll", 4) == 0)
381                 return 0;
382
383         seq_printf(s, "%s->%s (%d)", clkdm->name,
384                         clkdm->pwrdm.ptr->name,
385                         atomic_read(&clkdm->usecount));
386         seq_printf(s, "\n");
387
388         return 0;
389 }
390
391 static int pwrdm_dbg_show_counter(struct powerdomain *pwrdm, void *user)
392 {
393         struct seq_file *s = (struct seq_file *)user;
394         int i;
395
396         if (strcmp(pwrdm->name, "emu_pwrdm") == 0 ||
397                 strcmp(pwrdm->name, "wkup_pwrdm") == 0 ||
398                 strncmp(pwrdm->name, "dpll", 4) == 0)
399                 return 0;
400
401         if (pwrdm->state != pwrdm_read_pwrst(pwrdm))
402                 printk(KERN_ERR "pwrdm state mismatch(%s) %d != %d\n",
403                         pwrdm->name, pwrdm->state, pwrdm_read_pwrst(pwrdm));
404
405         seq_printf(s, "%s (%s)", pwrdm->name,
406                         pwrdm_state_names[pwrdm->state]);
407         for (i = 0; i < PWRDM_MAX_PWRSTS; i++)
408                 seq_printf(s, ",%s:%d", pwrdm_state_names[i],
409                         pwrdm->state_counter[i]);
410
411         seq_printf(s, ",RET-LOGIC-OFF:%d", pwrdm->ret_logic_off_counter);
412         for (i = 0; i < pwrdm->banks; i++)
413                 seq_printf(s, ",RET-MEMBANK%d-OFF:%d", i + 1,
414                                 pwrdm->ret_mem_off_counter[i]);
415
416         seq_printf(s, "\n");
417
418         return 0;
419 }
420
421 static int pwrdm_dbg_show_timer(struct powerdomain *pwrdm, void *user)
422 {
423         struct seq_file *s = (struct seq_file *)user;
424         int i;
425
426         if (strcmp(pwrdm->name, "emu_pwrdm") == 0 ||
427                 strcmp(pwrdm->name, "wkup_pwrdm") == 0 ||
428                 strncmp(pwrdm->name, "dpll", 4) == 0)
429                 return 0;
430
431         pwrdm_state_switch(pwrdm);
432
433         seq_printf(s, "%s (%s)", pwrdm->name,
434                 pwrdm_state_names[pwrdm->state]);
435
436         for (i = 0; i < 4; i++)
437                 seq_printf(s, ",%s:%lld", pwrdm_state_names[i],
438                         pwrdm->state_timer[i]);
439
440         seq_printf(s, "\n");
441         return 0;
442 }
443
444 static int pm_dbg_show_counters(struct seq_file *s, void *unused)
445 {
446         pwrdm_for_each(pwrdm_dbg_show_counter, s);
447         clkdm_for_each(clkdm_dbg_show_counter, s);
448
449         return 0;
450 }
451
452 static int pm_dbg_show_timers(struct seq_file *s, void *unused)
453 {
454         pwrdm_for_each(pwrdm_dbg_show_timer, s);
455         return 0;
456 }
457
458 static int pm_dbg_open(struct inode *inode, struct file *file)
459 {
460         switch ((int)inode->i_private) {
461         case DEBUG_FILE_COUNTERS:
462                 return single_open(file, pm_dbg_show_counters,
463                         &inode->i_private);
464         case DEBUG_FILE_TIMERS:
465         default:
466                 return single_open(file, pm_dbg_show_timers,
467                         &inode->i_private);
468         };
469 }
470
471 static int pm_dbg_reg_open(struct inode *inode, struct file *file)
472 {
473         return single_open(file, pm_dbg_show_regs, inode->i_private);
474 }
475
476 static const struct file_operations debug_fops = {
477         .open           = pm_dbg_open,
478         .read           = seq_read,
479         .llseek         = seq_lseek,
480         .release        = single_release,
481 };
482
483 static const struct file_operations debug_reg_fops = {
484         .open           = pm_dbg_reg_open,
485         .read           = seq_read,
486         .llseek         = seq_lseek,
487         .release        = single_release,
488 };
489
490 int pm_dbg_regset_init(int reg_set)
491 {
492         char name[2];
493
494         if (!pm_dbg_init_done)
495                 pm_dbg_init();
496
497         if (reg_set < 1 || reg_set > PM_DBG_MAX_REG_SETS ||
498                 pm_dbg_reg_set[reg_set-1] != NULL)
499                 return -EINVAL;
500
501         pm_dbg_reg_set[reg_set-1] =
502                 kmalloc(pm_dbg_get_regset_size(), GFP_KERNEL);
503
504         if (pm_dbg_reg_set[reg_set-1] == NULL)
505                 return -ENOMEM;
506
507         if (pm_dbg_dir != NULL) {
508                 sprintf(name, "%d", reg_set);
509
510                 (void) debugfs_create_file(name, S_IRUGO,
511                         pm_dbg_dir, (void *)reg_set, &debug_reg_fops);
512         }
513
514         return 0;
515 }
516
517 static int pwrdm_suspend_get(void *data, u64 *val)
518 {
519         int ret = -EINVAL;
520
521         if (cpu_is_omap34xx())
522                 ret = omap3_pm_get_suspend_state((struct powerdomain *)data);
523         *val = ret;
524
525         if (ret >= 0)
526                 return 0;
527         return *val;
528 }
529
530 static int pwrdm_suspend_set(void *data, u64 val)
531 {
532         if (cpu_is_omap34xx())
533                 return omap3_pm_set_suspend_state(
534                         (struct powerdomain *)data, (int)val);
535         return -EINVAL;
536 }
537
538 DEFINE_SIMPLE_ATTRIBUTE(pwrdm_suspend_fops, pwrdm_suspend_get,
539                         pwrdm_suspend_set, "%llu\n");
540
541 static int __init pwrdms_setup(struct powerdomain *pwrdm, void *dir)
542 {
543         int i;
544         s64 t;
545         struct dentry *d;
546
547         t = sched_clock();
548
549         for (i = 0; i < 4; i++)
550                 pwrdm->state_timer[i] = 0;
551
552         pwrdm->timer = t;
553
554         if (strncmp(pwrdm->name, "dpll", 4) == 0)
555                 return 0;
556
557         d = debugfs_create_dir(pwrdm->name, (struct dentry *)dir);
558
559         (void) debugfs_create_file("suspend", S_IRUGO|S_IWUSR, d,
560                         (void *)pwrdm, &pwrdm_suspend_fops);
561
562         return 0;
563 }
564
565 static int option_get(void *data, u64 *val)
566 {
567         u32 *option = data;
568
569         *val = *option;
570
571         return 0;
572 }
573
574 static int option_set(void *data, u64 val)
575 {
576         u32 *option = data;
577
578         if (option == &wakeup_timer_milliseconds && val >= 1000)
579                 return -EINVAL;
580
581         *option = val;
582
583         if (option == &enable_off_mode) {
584                 if (cpu_is_omap34xx())
585                         omap3_pm_off_mode_enable(val);
586         }
587
588         return 0;
589 }
590
591 DEFINE_SIMPLE_ATTRIBUTE(pm_dbg_option_fops, option_get, option_set, "%llu\n");
592
593 static int __init pm_dbg_init(void)
594 {
595         int i;
596         struct dentry *d;
597         char name[2];
598
599         if (pm_dbg_init_done)
600                 return 0;
601
602         if (cpu_is_omap34xx())
603                 pm_dbg_reg_modules = omap3_pm_reg_modules;
604         else {
605                 printk(KERN_ERR "%s: only OMAP3 supported\n", __func__);
606                 return -ENODEV;
607         }
608
609         d = debugfs_create_dir("pm_debug", NULL);
610         if (IS_ERR(d))
611                 return PTR_ERR(d);
612
613         (void) debugfs_create_file("count", S_IRUGO,
614                 d, (void *)DEBUG_FILE_COUNTERS, &debug_fops);
615         (void) debugfs_create_file("time", S_IRUGO,
616                 d, (void *)DEBUG_FILE_TIMERS, &debug_fops);
617
618         pwrdm_for_each(pwrdms_setup, (void *)d);
619
620         pm_dbg_dir = debugfs_create_dir("registers", d);
621         if (IS_ERR(pm_dbg_dir))
622                 return PTR_ERR(pm_dbg_dir);
623
624         (void) debugfs_create_file("current", S_IRUGO,
625                 pm_dbg_dir, (void *)0, &debug_reg_fops);
626
627         for (i = 0; i < PM_DBG_MAX_REG_SETS; i++)
628                 if (pm_dbg_reg_set[i] != NULL) {
629                         sprintf(name, "%d", i+1);
630                         (void) debugfs_create_file(name, S_IRUGO,
631                                 pm_dbg_dir, (void *)(i+1), &debug_reg_fops);
632
633                 }
634
635         (void) debugfs_create_file("enable_off_mode", S_IRUGO | S_IWUGO, d,
636                                    &enable_off_mode, &pm_dbg_option_fops);
637         (void) debugfs_create_file("sleep_while_idle", S_IRUGO | S_IWUGO, d,
638                                    &sleep_while_idle, &pm_dbg_option_fops);
639         (void) debugfs_create_file("wakeup_timer_seconds", S_IRUGO | S_IWUGO, d,
640                                    &wakeup_timer_seconds, &pm_dbg_option_fops);
641         (void) debugfs_create_file("wakeup_timer_milliseconds",
642                         S_IRUGO | S_IWUGO, d, &wakeup_timer_milliseconds,
643                         &pm_dbg_option_fops);
644         pm_dbg_init_done = 1;
645
646         return 0;
647 }
648 arch_initcall(pm_dbg_init);
649
650 #endif