2 * OMAP Power Management debug routines
4 * Copyright (C) 2005 Texas Instruments, Inc.
5 * Copyright (C) 2006-2008 Nokia Corporation
8 * Richard Woodruff <r-woodruff2@ti.com>
11 * Amit Kucheria <amit.kucheria@nokia.com>
12 * Igor Stoppa <igor.stoppa@nokia.com>
15 * Based on pm.c for omap2
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.
22 #include <linux/kernel.h>
23 #include <linux/sched.h>
24 #include <linux/clk.h>
25 #include <linux/err.h>
27 #include <linux/module.h>
28 #include <linux/slab.h>
30 #include <plat/clock.h>
31 #include <plat/board.h>
32 #include "powerdomain.h"
33 #include "clockdomain.h"
34 #include <plat/dmtimer.h>
35 #include <plat/omap-pm.h>
37 #include "cm2xxx_3xxx.h"
38 #include "prm2xxx_3xxx.h"
41 #define PM_DEBUG_MAX_SAVED_REGS 64
42 #define PM_DEBUG_PRM_MIN 0x4A306000
43 #define PM_DEBUG_PRM_MAX (0x4A307F00 + (PM_DEBUG_MAX_SAVED_REGS * 4) - 1)
44 #define PM_DEBUG_CM1_MIN 0x4A004000
45 #define PM_DEBUG_CM1_MAX (0x4A004F00 + (PM_DEBUG_MAX_SAVED_REGS * 4) - 1)
46 #define PM_DEBUG_CM2_MIN 0x4A008000
47 #define PM_DEBUG_CM2_MAX (0x4A009F00 + (PM_DEBUG_MAX_SAVED_REGS * 4) - 1)
52 u32 wakeup_timer_seconds
;
53 u32 wakeup_timer_milliseconds
;
54 u32 omap4_device_off_counter
= 0;
56 #ifdef CONFIG_PM_ADVANCED_DEBUG
57 static u32 saved_reg_num
;
58 static u32 saved_reg_num_used
;
59 static u32 saved_reg_addr
;
60 static u32 saved_reg_buff
[2][PM_DEBUG_MAX_SAVED_REGS
];
63 #define DUMP_PRM_MOD_REG(mod, reg) \
64 regs[reg_count].name = #mod "." #reg; \
65 regs[reg_count++].val = omap2_prm_read_mod_reg(mod, reg)
66 #define DUMP_CM_MOD_REG(mod, reg) \
67 regs[reg_count].name = #mod "." #reg; \
68 regs[reg_count++].val = omap2_cm_read_mod_reg(mod, reg)
69 #define DUMP_PRM_REG(reg) \
70 regs[reg_count].name = #reg; \
71 regs[reg_count++].val = __raw_readl(reg)
72 #define DUMP_CM_REG(reg) \
73 regs[reg_count].name = #reg; \
74 regs[reg_count++].val = __raw_readl(reg)
75 #define DUMP_INTC_REG(reg, off) \
76 regs[reg_count].name = #reg; \
77 regs[reg_count++].val = \
78 __raw_readl(OMAP2_L4_IO_ADDRESS(0x480fe000 + (off)))
80 void omap2_pm_dump(int mode
, int resume
, unsigned int us
)
87 const char *s1
= NULL
, *s2
= NULL
;
92 DUMP_PRM_MOD_REG(OCP_MOD
, OMAP2_PRM_IRQENABLE_MPU_OFFSET
);
93 DUMP_CM_MOD_REG(MPU_MOD
, OMAP2_CM_CLKSTCTRL
);
94 DUMP_PRM_MOD_REG(MPU_MOD
, OMAP2_PM_PWSTCTRL
);
95 DUMP_PRM_MOD_REG(MPU_MOD
, OMAP2_PM_PWSTST
);
96 DUMP_PRM_MOD_REG(MPU_MOD
, PM_WKDEP
);
100 DUMP_INTC_REG(INTC_MIR0
, 0x0084);
101 DUMP_INTC_REG(INTC_MIR1
, 0x00a4);
102 DUMP_INTC_REG(INTC_MIR2
, 0x00c4);
105 DUMP_CM_MOD_REG(CORE_MOD
, CM_FCLKEN1
);
106 if (cpu_is_omap24xx()) {
107 DUMP_CM_MOD_REG(CORE_MOD
, OMAP24XX_CM_FCLKEN2
);
108 DUMP_PRM_MOD_REG(OMAP24XX_GR_MOD
,
109 OMAP2_PRCM_CLKEMUL_CTRL_OFFSET
);
110 DUMP_PRM_MOD_REG(OMAP24XX_GR_MOD
,
111 OMAP2_PRCM_CLKSRC_CTRL_OFFSET
);
113 DUMP_CM_MOD_REG(WKUP_MOD
, CM_FCLKEN
);
114 DUMP_CM_MOD_REG(CORE_MOD
, CM_ICLKEN1
);
115 DUMP_CM_MOD_REG(CORE_MOD
, CM_ICLKEN2
);
116 DUMP_CM_MOD_REG(WKUP_MOD
, CM_ICLKEN
);
117 DUMP_CM_MOD_REG(PLL_MOD
, CM_CLKEN
);
118 DUMP_CM_MOD_REG(PLL_MOD
, CM_AUTOIDLE
);
119 DUMP_PRM_MOD_REG(CORE_MOD
, OMAP2_PM_PWSTST
);
123 if (cpu_is_omap24xx()) {
124 DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD
, CM_FCLKEN
);
125 DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD
, CM_ICLKEN
);
126 DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD
, CM_IDLEST
);
127 DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD
, CM_AUTOIDLE
);
128 DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD
, CM_CLKSEL
);
129 DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD
, OMAP2_CM_CLKSTCTRL
);
130 DUMP_PRM_MOD_REG(OMAP24XX_DSP_MOD
, OMAP2_RM_RSTCTRL
);
131 DUMP_PRM_MOD_REG(OMAP24XX_DSP_MOD
, OMAP2_RM_RSTST
);
132 DUMP_PRM_MOD_REG(OMAP24XX_DSP_MOD
, OMAP2_PM_PWSTCTRL
);
133 DUMP_PRM_MOD_REG(OMAP24XX_DSP_MOD
, OMAP2_PM_PWSTST
);
137 DUMP_PRM_MOD_REG(CORE_MOD
, PM_WKST1
);
138 if (cpu_is_omap24xx())
139 DUMP_PRM_MOD_REG(CORE_MOD
, OMAP24XX_PM_WKST2
);
140 DUMP_PRM_MOD_REG(WKUP_MOD
, PM_WKST
);
141 DUMP_PRM_MOD_REG(OCP_MOD
, OMAP2_PRCM_IRQSTATUS_MPU_OFFSET
);
143 DUMP_INTC_REG(INTC_PENDING_IRQ0
, 0x0098);
144 DUMP_INTC_REG(INTC_PENDING_IRQ1
, 0x00b8);
145 DUMP_INTC_REG(INTC_PENDING_IRQ2
, 0x00d8);
167 "--- Going to %s %s (next timer after %u ms)\n", s1
, s2
,
168 jiffies_to_msecs(get_next_timer_interrupt(jiffies
) -
171 printk(KERN_INFO
"--- Going to %s %s\n", s1
, s2
);
174 printk(KERN_INFO
"--- Woke up (slept for %u.%03u ms)\n",
175 us
/ 1000, us
% 1000);
177 for (i
= 0; i
< reg_count
; i
++)
178 printk(KERN_INFO
"%-20s: 0x%08x\n", regs
[i
].name
, regs
[i
].val
);
181 void omap2_pm_wakeup_on_timer(u32 seconds
, u32 milliseconds
)
183 u32 tick_rate
, cycles
;
185 if (!seconds
&& !milliseconds
)
188 tick_rate
= clk_get_rate(omap_dm_timer_get_fclk(gptimer_wakeup
));
189 cycles
= tick_rate
* seconds
+ tick_rate
* milliseconds
/ 1000;
190 omap_dm_timer_stop(gptimer_wakeup
);
191 omap_dm_timer_set_load_start(gptimer_wakeup
, 0, 0xffffffff - cycles
);
193 pr_info("PM: Resume timer in %u.%03u secs"
194 " (%d ticks at %d ticks/sec.)\n",
195 seconds
, milliseconds
, cycles
, tick_rate
);
198 #ifdef CONFIG_DEBUG_FS
199 #include <linux/debugfs.h>
200 #include <linux/seq_file.h>
202 static void pm_dbg_regset_store(u32
*ptr
);
204 static struct dentry
*pm_dbg_dir
;
206 static int pm_dbg_init_done
;
208 static int pm_dbg_init(void);
211 DEBUG_FILE_COUNTERS
= 0,
213 DEBUG_FILE_LAST_COUNTERS
,
214 DEBUG_FILE_LAST_TIMERS
,
217 struct pm_module_def
{
218 char name
[8]; /* Name of the module */
219 short type
; /* CM or PRM */
220 unsigned short offset
;
221 int low
; /* First register address on this module */
222 int high
; /* Last register address on this module */
228 static const struct pm_module_def
*pm_dbg_reg_modules
;
229 static const struct pm_module_def omap3_pm_reg_modules
[] = {
230 { "IVA2", MOD_CM
, OMAP3430_IVA2_MOD
, 0, 0x4c },
231 { "OCP", MOD_CM
, OCP_MOD
, 0, 0x10 },
232 { "MPU", MOD_CM
, MPU_MOD
, 4, 0x4c },
233 { "CORE", MOD_CM
, CORE_MOD
, 0, 0x4c },
234 { "SGX", MOD_CM
, OMAP3430ES2_SGX_MOD
, 0, 0x4c },
235 { "WKUP", MOD_CM
, WKUP_MOD
, 0, 0x40 },
236 { "CCR", MOD_CM
, PLL_MOD
, 0, 0x70 },
237 { "DSS", MOD_CM
, OMAP3430_DSS_MOD
, 0, 0x4c },
238 { "CAM", MOD_CM
, OMAP3430_CAM_MOD
, 0, 0x4c },
239 { "PER", MOD_CM
, OMAP3430_PER_MOD
, 0, 0x4c },
240 { "EMU", MOD_CM
, OMAP3430_EMU_MOD
, 0x40, 0x54 },
241 { "NEON", MOD_CM
, OMAP3430_NEON_MOD
, 0x20, 0x48 },
242 { "USB", MOD_CM
, OMAP3430ES2_USBHOST_MOD
, 0, 0x4c },
244 { "IVA2", MOD_PRM
, OMAP3430_IVA2_MOD
, 0x50, 0xfc },
245 { "OCP", MOD_PRM
, OCP_MOD
, 4, 0x1c },
246 { "MPU", MOD_PRM
, MPU_MOD
, 0x58, 0xe8 },
247 { "CORE", MOD_PRM
, CORE_MOD
, 0x58, 0xf8 },
248 { "SGX", MOD_PRM
, OMAP3430ES2_SGX_MOD
, 0x58, 0xe8 },
249 { "WKUP", MOD_PRM
, WKUP_MOD
, 0xa0, 0xb0 },
250 { "CCR", MOD_PRM
, PLL_MOD
, 0x40, 0x70 },
251 { "DSS", MOD_PRM
, OMAP3430_DSS_MOD
, 0x58, 0xe8 },
252 { "CAM", MOD_PRM
, OMAP3430_CAM_MOD
, 0x58, 0xe8 },
253 { "PER", MOD_PRM
, OMAP3430_PER_MOD
, 0x58, 0xe8 },
254 { "EMU", MOD_PRM
, OMAP3430_EMU_MOD
, 0x58, 0xe4 },
255 { "GLBL", MOD_PRM
, OMAP3430_GR_MOD
, 0x20, 0xe4 },
256 { "NEON", MOD_PRM
, OMAP3430_NEON_MOD
, 0x58, 0xe8 },
257 { "USB", MOD_PRM
, OMAP3430ES2_USBHOST_MOD
, 0x58, 0xe8 },
261 #define PM_DBG_MAX_REG_SETS 4
263 static void *pm_dbg_reg_set
[PM_DBG_MAX_REG_SETS
];
265 static int pm_dbg_get_regset_size(void)
267 static int regset_size
;
269 if (regset_size
== 0) {
272 while (pm_dbg_reg_modules
[i
].name
[0] != 0) {
273 regset_size
+= pm_dbg_reg_modules
[i
].high
+
274 4 - pm_dbg_reg_modules
[i
].low
;
281 static int pm_dbg_show_regs(struct seq_file
*s
, void *unused
)
285 int reg_set
= (int)s
->private;
292 store
= kmalloc(pm_dbg_get_regset_size(), GFP_KERNEL
);
294 pm_dbg_regset_store(ptr
);
296 ptr
= pm_dbg_reg_set
[reg_set
- 1];
301 while (pm_dbg_reg_modules
[i
].name
[0] != 0) {
304 if (pm_dbg_reg_modules
[i
].type
== MOD_CM
)
305 seq_printf(s
, "MOD: CM_%s (%08x)\n",
306 pm_dbg_reg_modules
[i
].name
,
307 (u32
)(OMAP3430_CM_BASE
+
308 pm_dbg_reg_modules
[i
].offset
));
310 seq_printf(s
, "MOD: PRM_%s (%08x)\n",
311 pm_dbg_reg_modules
[i
].name
,
312 (u32
)(OMAP3430_PRM_BASE
+
313 pm_dbg_reg_modules
[i
].offset
));
315 for (j
= pm_dbg_reg_modules
[i
].low
;
316 j
<= pm_dbg_reg_modules
[i
].high
; j
+= 4) {
324 seq_printf(s
, " %02x => %08lx", j
, val
);
339 static void pm_dbg_regset_store(u32
*ptr
)
346 while (pm_dbg_reg_modules
[i
].name
[0] != 0) {
347 for (j
= pm_dbg_reg_modules
[i
].low
;
348 j
<= pm_dbg_reg_modules
[i
].high
; j
+= 4) {
349 if (pm_dbg_reg_modules
[i
].type
== MOD_CM
)
350 val
= omap2_cm_read_mod_reg(
351 pm_dbg_reg_modules
[i
].offset
, j
);
353 val
= omap2_prm_read_mod_reg(
354 pm_dbg_reg_modules
[i
].offset
, j
);
361 int pm_dbg_regset_save(int reg_set
)
363 if (pm_dbg_reg_set
[reg_set
-1] == NULL
)
366 pm_dbg_regset_store(pm_dbg_reg_set
[reg_set
-1]);
371 static const char pwrdm_state_names
[][PWRDM_MAX_PWRSTS
] = {
378 void pm_dbg_update_time(struct powerdomain
*pwrdm
, int prev
)
382 if (!pm_dbg_init_done
)
385 /* Update timer for previous state */
388 pwrdm
->time
.state
[prev
] += t
- pwrdm
->timer
;
393 static int clkdm_dbg_show_counter(struct clockdomain
*clkdm
, void *user
)
395 struct seq_file
*s
= (struct seq_file
*)user
;
397 if (strcmp(clkdm
->name
, "emu_clkdm") == 0 ||
398 strcmp(clkdm
->name
, "wkup_clkdm") == 0 ||
399 strncmp(clkdm
->name
, "dpll", 4) == 0)
402 seq_printf(s
, "%s->%s (%d)", clkdm
->name
,
403 clkdm
->pwrdm
.ptr
->name
,
404 atomic_read(&clkdm
->usecount
));
410 static int pwrdm_dbg_show_count_stats(struct powerdomain
*pwrdm
,
411 struct powerdomain_count_stats
*stats
, struct seq_file
*s
)
415 seq_printf(s
, "%s (%s)", pwrdm
->name
,
416 pwrdm_state_names
[pwrdm
->state
]);
418 for (i
= 0; i
< PWRDM_MAX_PWRSTS
; i
++)
419 seq_printf(s
, ",%s:%d", pwrdm_state_names
[i
],
422 seq_printf(s
, ",RET-LOGIC-OFF:%d", stats
->ret_logic_off
);
423 for (i
= 0; i
< pwrdm
->banks
; i
++)
424 seq_printf(s
, ",RET-MEMBANK%d-OFF:%d", i
+ 1,
425 stats
->ret_mem_off
[i
]);
432 static int pwrdm_dbg_show_time_stats(struct powerdomain
*pwrdm
,
433 struct powerdomain_time_stats
*stats
, struct seq_file
*s
)
438 seq_printf(s
, "%s (%s)", pwrdm
->name
,
439 pwrdm_state_names
[pwrdm
->state
]);
441 for (i
= 0; i
< 4; i
++)
442 total
+= stats
->state
[i
];
444 for (i
= 0; i
< 4; i
++)
445 seq_printf(s
, ",%s:%lld (%lld%%)", pwrdm_state_names
[i
],
447 total
? div64_u64(stats
->state
[i
] * 100, total
) : 0);
454 static int pwrdm_dbg_show_counter(struct powerdomain
*pwrdm
, void *user
)
456 struct seq_file
*s
= (struct seq_file
*)user
;
458 if (strcmp(pwrdm
->name
, "emu_pwrdm") == 0 ||
459 strcmp(pwrdm
->name
, "wkup_pwrdm") == 0 ||
460 strncmp(pwrdm
->name
, "dpll", 4) == 0)
463 if (pwrdm
->state
!= pwrdm_read_pwrst(pwrdm
))
464 printk(KERN_ERR
"pwrdm state mismatch(%s) %d != %d\n",
465 pwrdm
->name
, pwrdm
->state
, pwrdm_read_pwrst(pwrdm
));
467 pwrdm_dbg_show_count_stats(pwrdm
, &pwrdm
->count
, s
);
472 static int pwrdm_dbg_show_timer(struct powerdomain
*pwrdm
, void *user
)
474 struct seq_file
*s
= (struct seq_file
*)user
;
476 if (strcmp(pwrdm
->name
, "emu_pwrdm") == 0 ||
477 strcmp(pwrdm
->name
, "wkup_pwrdm") == 0 ||
478 strncmp(pwrdm
->name
, "dpll", 4) == 0)
481 pwrdm_state_switch(pwrdm
);
483 pwrdm_dbg_show_time_stats(pwrdm
, &pwrdm
->time
, s
);
488 static int pwrdm_dbg_show_last_counter(struct powerdomain
*pwrdm
, void *user
)
490 struct seq_file
*s
= (struct seq_file
*)user
;
491 struct powerdomain_count_stats stats
;
494 if (strcmp(pwrdm
->name
, "emu_pwrdm") == 0 ||
495 strcmp(pwrdm
->name
, "wkup_pwrdm") == 0 ||
496 strncmp(pwrdm
->name
, "dpll", 4) == 0)
499 stats
= pwrdm
->count
;
500 for (i
= 0; i
< PWRDM_MAX_PWRSTS
; i
++)
501 stats
.state
[i
] -= pwrdm
->last_count
.state
[i
];
502 for (i
= 0; i
< PWRDM_MAX_MEM_BANKS
; i
++)
503 stats
.ret_mem_off
[i
] -= pwrdm
->last_count
.ret_mem_off
[i
];
504 stats
.ret_logic_off
-= pwrdm
->last_count
.ret_logic_off
;
506 pwrdm
->last_count
= pwrdm
->count
;
508 pwrdm_dbg_show_count_stats(pwrdm
, &stats
, s
);
513 static int pwrdm_dbg_show_last_timer(struct powerdomain
*pwrdm
, void *user
)
515 struct seq_file
*s
= (struct seq_file
*)user
;
516 struct powerdomain_time_stats stats
;
520 for (i
= 0; i
< PWRDM_MAX_PWRSTS
; i
++)
521 stats
.state
[i
] -= pwrdm
->last_time
.state
[i
];
523 pwrdm
->last_time
= pwrdm
->time
;
525 pwrdm_dbg_show_time_stats(pwrdm
, &stats
, s
);
530 static int pm_dbg_show_counters(struct seq_file
*s
, void *unused
)
532 pwrdm_for_each(pwrdm_dbg_show_counter
, s
);
533 if (cpu_is_omap44xx())
534 seq_printf(s
, "DEVICE-OFF:%d\n", omap4_device_off_counter
);
535 clkdm_for_each(clkdm_dbg_show_counter
, s
);
540 static int pm_dbg_show_timers(struct seq_file
*s
, void *unused
)
542 pwrdm_for_each(pwrdm_dbg_show_timer
, s
);
546 static int pm_dbg_show_last_counters(struct seq_file
*s
, void *unused
)
548 pwrdm_for_each(pwrdm_dbg_show_last_counter
, s
);
552 static int pm_dbg_show_last_timers(struct seq_file
*s
, void *unused
)
554 pwrdm_for_each(pwrdm_dbg_show_last_timer
, s
);
558 static int pm_dbg_open(struct inode
*inode
, struct file
*file
)
560 switch ((int)inode
->i_private
) {
561 case DEBUG_FILE_COUNTERS
:
562 return single_open(file
, pm_dbg_show_counters
,
564 case DEBUG_FILE_TIMERS
:
565 return single_open(file
, pm_dbg_show_timers
,
567 case DEBUG_FILE_LAST_COUNTERS
:
568 return single_open(file
, pm_dbg_show_last_counters
,
570 case DEBUG_FILE_LAST_TIMERS
:
572 return single_open(file
, pm_dbg_show_last_timers
,
577 static int pm_dbg_reg_open(struct inode
*inode
, struct file
*file
)
579 return single_open(file
, pm_dbg_show_regs
, inode
->i_private
);
582 static const struct file_operations debug_fops
= {
586 .release
= single_release
,
589 static const struct file_operations debug_reg_fops
= {
590 .open
= pm_dbg_reg_open
,
593 .release
= single_release
,
596 int __init
pm_dbg_regset_init(int reg_set
)
600 if (!pm_dbg_init_done
)
603 if (reg_set
< 1 || reg_set
> PM_DBG_MAX_REG_SETS
||
604 pm_dbg_reg_set
[reg_set
-1] != NULL
)
607 pm_dbg_reg_set
[reg_set
-1] =
608 kmalloc(pm_dbg_get_regset_size(), GFP_KERNEL
);
610 if (pm_dbg_reg_set
[reg_set
-1] == NULL
)
613 if (pm_dbg_dir
!= NULL
) {
614 sprintf(name
, "%d", reg_set
);
616 (void) debugfs_create_file(name
, S_IRUGO
,
617 pm_dbg_dir
, (void *)reg_set
, &debug_reg_fops
);
623 static int pwrdm_suspend_get(void *data
, u64
*val
)
627 if (cpu_is_omap34xx())
628 ret
= omap3_pm_get_suspend_state((struct powerdomain
*)data
);
636 static int pwrdm_suspend_set(void *data
, u64 val
)
638 if (cpu_is_omap34xx())
639 return omap3_pm_set_suspend_state(
640 (struct powerdomain
*)data
, (int)val
);
644 DEFINE_SIMPLE_ATTRIBUTE(pwrdm_suspend_fops
, pwrdm_suspend_get
,
645 pwrdm_suspend_set
, "%llu\n");
647 #ifdef CONFIG_PM_ADVANCED_DEBUG
648 static bool is_addr_valid()
650 int saved_reg_addr_max
= 0;
651 /* Only for OMAP4 for the timebeing */
652 if (!cpu_is_omap44xx())
655 saved_reg_num
= (saved_reg_num
> PM_DEBUG_MAX_SAVED_REGS
) ?
656 PM_DEBUG_MAX_SAVED_REGS
: saved_reg_num
;
658 saved_reg_addr_max
= saved_reg_addr
+ (saved_reg_num
* 4) - 1;
660 if (saved_reg_addr
>= PM_DEBUG_PRM_MIN
&&
661 saved_reg_addr_max
<= PM_DEBUG_PRM_MAX
)
663 if (saved_reg_addr
>= PM_DEBUG_CM1_MIN
&&
664 saved_reg_addr_max
<= PM_DEBUG_CM1_MAX
)
666 if (saved_reg_addr
>= PM_DEBUG_CM2_MIN
&&
667 saved_reg_addr_max
<= PM_DEBUG_CM2_MAX
)
672 void omap4_pm_suspend_save_regs()
675 if (!saved_reg_num
|| !is_addr_valid())
678 saved_reg_num_used
= saved_reg_num
;
680 for (i
= 0; i
< saved_reg_num
; i
++) {
681 saved_reg_buff
[1][i
] = omap_readl(saved_reg_addr
+ (i
*4));
682 saved_reg_buff
[0][i
] = saved_reg_addr
+ (i
*4);
688 static int __init
pwrdms_setup(struct powerdomain
*pwrdm
, void *dir
)
696 for (i
= 0; i
< 4; i
++)
697 pwrdm
->time
.state
[i
] = 0;
701 if (strncmp(pwrdm
->name
, "dpll", 4) == 0)
704 d
= debugfs_create_dir(pwrdm
->name
, (struct dentry
*)dir
);
706 (void) debugfs_create_file("suspend", S_IRUGO
|S_IWUSR
, d
,
707 (void *)pwrdm
, &pwrdm_suspend_fops
);
712 static int option_get(void *data
, u64
*val
)
716 if (option
== &enable_off_mode
) {
717 enable_off_mode
= off_mode_enabled
;
721 #ifdef CONFIG_PM_ADVANCED_DEBUG
722 if (option
== &saved_reg_addr
) {
724 for (i
= 0; i
< saved_reg_num_used
; i
++)
725 pr_info(" %x = %x\n", saved_reg_buff
[0][i
],
726 saved_reg_buff
[1][i
]);
733 static int option_set(void *data
, u64 val
)
737 if (option
== &wakeup_timer_milliseconds
&& val
>= 1000)
740 if (cpu_is_omap443x() && omap_type() == OMAP2_DEVICE_TYPE_GP
)
745 if (option
== &enable_off_mode
) {
747 omap_pm_enable_off_mode();
749 omap_pm_disable_off_mode();
750 if (cpu_is_omap34xx())
751 omap3_pm_off_mode_enable(val
);
757 DEFINE_SIMPLE_ATTRIBUTE(pm_dbg_option_fops
, option_get
, option_set
, "%llu\n");
759 static int __init
pm_dbg_init(void)
765 if (pm_dbg_init_done
)
768 if (cpu_is_omap34xx()) {
769 pm_dbg_reg_modules
= omap3_pm_reg_modules
;
770 } else if (cpu_is_omap44xx()) {
771 /* Allow pm_dbg_init on OMAP4. */
773 printk(KERN_ERR
"%s: only OMAP3 supported\n", __func__
);
777 d
= debugfs_create_dir("pm_debug", NULL
);
781 (void) debugfs_create_file("count", S_IRUGO
,
782 d
, (void *)DEBUG_FILE_COUNTERS
, &debug_fops
);
783 (void) debugfs_create_file("time", S_IRUGO
,
784 d
, (void *)DEBUG_FILE_TIMERS
, &debug_fops
);
785 (void) debugfs_create_file("last_count", S_IRUGO
,
786 d
, (void *)DEBUG_FILE_LAST_COUNTERS
, &debug_fops
);
787 (void) debugfs_create_file("last_time", S_IRUGO
,
788 d
, (void *)DEBUG_FILE_LAST_TIMERS
, &debug_fops
);
790 pwrdm_for_each(pwrdms_setup
, (void *)d
);
792 if (cpu_is_omap44xx())
793 goto skip_reg_debufs
;
795 pm_dbg_dir
= debugfs_create_dir("registers", d
);
796 if (IS_ERR(pm_dbg_dir
))
797 return PTR_ERR(pm_dbg_dir
);
799 (void) debugfs_create_file("current", S_IRUGO
,
800 pm_dbg_dir
, (void *)0, &debug_reg_fops
);
802 for (i
= 0; i
< PM_DBG_MAX_REG_SETS
; i
++)
803 if (pm_dbg_reg_set
[i
] != NULL
) {
804 sprintf(name
, "%d", i
+1);
805 (void) debugfs_create_file(name
, S_IRUGO
,
806 pm_dbg_dir
, (void *)(i
+1), &debug_reg_fops
);
810 (void) debugfs_create_file("sleep_while_idle", S_IRUGO
| S_IWUSR
, d
,
811 &sleep_while_idle
, &pm_dbg_option_fops
);
814 #ifdef CONFIG_OMAP_ALLOW_OSWR
815 (void) debugfs_create_file("enable_off_mode", S_IRUGO
| S_IWUSR
, d
,
816 &enable_off_mode
, &pm_dbg_option_fops
);
818 (void) debugfs_create_file("wakeup_timer_seconds", S_IRUGO
| S_IWUSR
, d
,
819 &wakeup_timer_seconds
, &pm_dbg_option_fops
);
820 (void) debugfs_create_file("wakeup_timer_milliseconds",
821 S_IRUGO
| S_IWUSR
, d
, &wakeup_timer_milliseconds
,
822 &pm_dbg_option_fops
);
824 #ifdef CONFIG_PM_ADVANCED_DEBUG
825 (void) debugfs_create_file("saved_reg_show",
826 S_IRUGO
| S_IWUSR
, d
, &saved_reg_addr
,
827 &pm_dbg_option_fops
);
828 debugfs_create_u32("saved_reg_addr", S_IRUGO
| S_IWUGO
, d
,
830 debugfs_create_u32("saved_reg_num", S_IRUGO
| S_IWUGO
, d
,
833 pm_dbg_init_done
= 1;
837 arch_initcall(pm_dbg_init
);