summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJim Wylder <jwylder@motorola.com>2014-06-10 10:11:26 -0500
committerJames Wylder <jwylder@motorola.com>2014-06-12 22:20:59 +0000
commit7ddadb752771a4c6b8f585a7278946d3d664a861 (patch)
tree55520f3cae6654c0ebf2ed574c902bf53373b4b9
parent0ff908aebf6eba804c4bccb830a56d6b04dc7f47 (diff)
downloadolio-linux-3.10-7ddadb752771a4c6b8f585a7278946d3d664a861.tar.xz
olio-linux-3.10-7ddadb752771a4c6b8f585a7278946d3d664a861.zip
IKXCLOCK-2206 arm: omap3: pm-debug cleanup
Save off a golden version if we hit the off state, and then use that as a reference for future debugging messages. Change-Id: Ib08a2c63ab6ca9d0784ffd60e228eafc5d28b01a Signed-off-by: Jim Wylder <jwylder@motorola.com>
-rw-r--r--arch/arm/mach-omap2/pm-debug-regs.c53
-rw-r--r--arch/arm/mach-omap2/pm-debug-regs.h4
-rw-r--r--arch/arm/mach-omap2/pm34xx.c16
3 files changed, 71 insertions, 2 deletions
diff --git a/arch/arm/mach-omap2/pm-debug-regs.c b/arch/arm/mach-omap2/pm-debug-regs.c
index 0997fe8138d..42c40d92427 100644
--- a/arch/arm/mach-omap2/pm-debug-regs.c
+++ b/arch/arm/mach-omap2/pm-debug-regs.c
@@ -134,6 +134,15 @@ static void pm_dbg_regset_store(u32 *ptr)
}
}
+void pm_dbg_regs_copy(int tgt, int src)
+{
+ size_t sz = pm_dbg_get_regset_size();
+
+ pr_debug("saved reference copy %s(%d, %d) size = %u <- %pS\n",
+ __func__, tgt, src, sz, __builtin_return_address(0));
+ memcpy(pm_dbg_reg_set[tgt - 1], pm_dbg_reg_set[src - 1], sz);
+}
+
void pm_dbg_regs_save(int reg_set)
{
if (pm_dbg_reg_set[reg_set - 1] == NULL)
@@ -424,6 +433,50 @@ int pm_dbg_regs_dump(int reg_set)
}
EXPORT_SYMBOL(pm_dbg_regs_dump);
+int pm_dbg_regs_dump_delta(int cur, int ref)
+{
+ int i, j;
+ unsigned long val_cur;
+ u32 *ptr_cur;
+ unsigned long val_ref;
+ u32 *ptr_ref;
+
+ if ((cur <= 0) || (cur > PM_DBG_MAX_REG_SETS) ||
+ (ref <= 0) || (ref > PM_DBG_MAX_REG_SETS)) {
+ return -EINVAL;
+ }
+
+ ptr_cur = pm_dbg_reg_set[cur - 1];
+ ptr_ref = pm_dbg_reg_set[ref - 1];
+
+ i = 0;
+
+ pr_debug(" module ( address) reg %d %d\n",
+ cur, ref);
+ while (pm_dbg_reg_modules[i].name[0] != 0) {
+ bool cm = pm_dbg_reg_modules[i].type == MOD_CM;
+ uint32_t addr = (u32)(OMAP3430_CM_BASE +
+ pm_dbg_reg_modules[i].offset);
+
+ for (j = pm_dbg_reg_modules[i].low;
+ j <= pm_dbg_reg_modules[i].high; j += 4) {
+ val_cur = *(ptr_cur++);
+ val_ref = *(ptr_ref++);
+ if (val_cur != val_ref) {
+ pr_debug("MOD: %s_%-4s %s(%08x) "
+ "%02x => 0x%08lx 0x%08lx\n",
+ cm ? "CM_" : "PRM_",
+ pm_dbg_reg_modules[i].name,
+ cm ? " " : "",
+ addr, j, val_cur, val_ref);
+ }
+ }
+ i++;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(pm_dbg_regs_dump_delta);
+
static void __init pm_dbg_regset_init(void)
{
int i;
diff --git a/arch/arm/mach-omap2/pm-debug-regs.h b/arch/arm/mach-omap2/pm-debug-regs.h
index e403977affa..f70bbe5c6a8 100644
--- a/arch/arm/mach-omap2/pm-debug-regs.h
+++ b/arch/arm/mach-omap2/pm-debug-regs.h
@@ -20,12 +20,16 @@
extern int pm_dbg_regs_init(struct dentry *d);
extern void pm_dbg_regs_save(int reg_set);
extern void pm_dbg_regs_dump(int reg_set);
+extern void pm_dbg_regs_dump_delta(int cur, int rfr);
extern void pm_dbg_show_wakeup_source(void);
+extern void pm_dbg_regs_copy(int tgt, int src);
#else
static inline int pm_dbg_regs_init(struct dentry *d) { return 0; }
static inline void pm_dbg_regs_save(int reg_set) {};
static inline void pm_dbg_regs_dump(int reg_set) {};
+static inline void pm_dbg_regs_dump_delta(int current, int ref) {}
static inline void pm_dbg_show_wakeup_source(void) {};
+static inline void pm_dbg_regs_copy(int tgt, int src) {};
#endif
#endif
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index afe15f00637..6daf94a0223 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -62,6 +62,7 @@
/* pm34xx errata defined in pm.h */
u16 pm34xx_errata;
bool suspend_debug;
+bool suspend_offmode_ref_saved;
struct power_state {
struct powerdomain *pwrdm;
@@ -391,6 +392,12 @@ void omap_sram_idle(bool in_suspend)
omap3_cm_restore_context();
omap3_sram_restore_context();
omap2_sms_restore_context();
+
+ if (unlikely(!suspend_offmode_ref_saved)) {
+ suspend_offmode_ref_saved = true;
+ pm_dbg_regs_copy(3, 1);
+ pm_dbg_regs_copy(4, 2);
+ }
}
if (core_next_state == PWRDM_POWER_OFF) {
omap2_prm_clear_mod_reg_bits(OMAP3430_EN_IO_CHAIN_MASK,
@@ -457,8 +464,13 @@ restore:
}
if (ret) {
pr_err("Could not enter target state in pm_suspend\n");
- pm_dbg_regs_dump(1);
- pm_dbg_regs_dump(2);
+ if (suspend_offmode_ref_saved) {
+ pm_dbg_regs_dump_delta(1, 3);
+ pm_dbg_regs_dump_delta(2, 4);
+ } else {
+ pm_dbg_regs_dump(1);
+ pm_dbg_regs_dump(2);
+ }
} else
pr_info("Successfully put all powerdomains to target state\n");