From 302f70450dd87df2d7daef1a37f38ff413c6593e Mon Sep 17 00:00:00 2001 From: Jim Wylder Date: Tue, 15 Apr 2014 12:08:38 -0500 Subject: IKXCLOCK-938 arm: omap2: pm debug register dump Reworking of earlier data reporting module. Register values can be read from /pm_debug/registers/current,1,2,3,4 Currently 1 is recorded before the last suspend and 2 is recorded after the last suspend. Change-Id: I061ec369a59c647c662879f30f4830f8d47e8996 Signed-off-by: Jim Wylder --- arch/arm/mach-omap2/Makefile | 2 +- arch/arm/mach-omap2/pm-debug-regs.c | 478 ++++++++++++++++++++++++++++++++++++ arch/arm/mach-omap2/pm-debug-regs.h | 31 +++ arch/arm/mach-omap2/pm-debug.c | 4 + arch/arm/mach-omap2/pm34xx.c | 19 +- arch/arm/mach-omap2/prm2xxx.h | 3 + 6 files changed, 533 insertions(+), 4 deletions(-) create mode 100644 arch/arm/mach-omap2/pm-debug-regs.c create mode 100644 arch/arm/mach-omap2/pm-debug-regs.h diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index 50daf4181a7..731e039bef0 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -85,7 +85,7 @@ obj-$(CONFIG_ARCH_OMAP2) += sleep24xx.o obj-$(CONFIG_ARCH_OMAP3) += pm34xx.o sleep34xx.o obj-$(CONFIG_ARCH_OMAP4) += pm44xx.o omap-mpuss-lowpower.o obj-$(CONFIG_SOC_OMAP5) += omap-mpuss-lowpower.o -obj-$(CONFIG_PM_DEBUG) += pm-debug.o +obj-$(CONFIG_PM_DEBUG) += pm-debug.o pm-debug-regs.o obj-$(CONFIG_POWER_AVS_OMAP) += sr_device.o obj-$(CONFIG_POWER_AVS_OMAP_CLASS3) += smartreflex-class3.o diff --git a/arch/arm/mach-omap2/pm-debug-regs.c b/arch/arm/mach-omap2/pm-debug-regs.c new file mode 100644 index 00000000000..0997fe8138d --- /dev/null +++ b/arch/arm/mach-omap2/pm-debug-regs.c @@ -0,0 +1,478 @@ +/* + * Copyright (C) 2014 Motorola Mobility LLC + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Work based on OMAP Power Management debug routines + * Copyright (C) 2005 Texas Instruments, Inc. + * Copyright (C) 2006-2008 Nokia Corporation + * + * Written by: + * Richard Woodruff + * Tony Lindgren + * Juha Yrjola + * Amit Kucheria + * Igor Stoppa + * Jouni Hogander + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "iomap.h" +#include "clock.h" +#include "powerdomain.h" +#include "clockdomain.h" +#include "omap-pm.h" + +#include "soc.h" +#include "cm2xxx_3xxx.h" +#include "prm3xxx.h" +#include "prm2xxx_3xxx.h" +#include "pm.h" + +#ifdef CONFIG_DEBUG_FS +#include +#include + +static struct dentry *pm_dbg_dir; +#endif + +struct pm_module_def { + char name[8]; /* Name of the module */ + short type; /* CM or PRM */ + unsigned short offset; + int low; /* First register address on this module */ + int high; /* Last register address on this module */ +}; + +#define MOD_CM 0 +#define MOD_PRM 1 + + +static const struct pm_module_def pm_dbg_reg_modules[] = { + { "IVA2", MOD_CM, OMAP3430_IVA2_MOD, 0, 0x4c }, + { "OCP", MOD_CM, OCP_MOD, 0, 0x10 }, + { "MPU", MOD_CM, MPU_MOD, 4, 0x4c }, + { "CORE", MOD_CM, CORE_MOD, 0, 0x4c }, + { "SGX", MOD_CM, OMAP3430ES2_SGX_MOD, 0, 0x4c }, + { "WKUP", MOD_CM, WKUP_MOD, 0, 0x40 }, + { "CCR", MOD_CM, PLL_MOD, 0, 0x70 }, + { "DSS", MOD_CM, OMAP3430_DSS_MOD, 0, 0x4c }, + { "CAM", MOD_CM, OMAP3430_CAM_MOD, 0, 0x4c }, + { "PER", MOD_CM, OMAP3430_PER_MOD, 0, 0x4c }, + { "EMU", MOD_CM, OMAP3430_EMU_MOD, 0x40, 0x54 }, + { "NEON", MOD_CM, OMAP3430_NEON_MOD, 0x20, 0x48 }, + { "USB", MOD_CM, OMAP3430ES2_USBHOST_MOD, 0, 0x4c }, + + { "IVA2", MOD_PRM, OMAP3430_IVA2_MOD, 0x50, 0xfc }, + { "OCP", MOD_PRM, OCP_MOD, 4, 0x1c }, + { "MPU", MOD_PRM, MPU_MOD, 0x58, 0xe8 }, + { "CORE", MOD_PRM, CORE_MOD, 0x58, 0xf8 }, + { "SGX", MOD_PRM, OMAP3430ES2_SGX_MOD, 0x58, 0xe8 }, + { "WKUP", MOD_PRM, WKUP_MOD, 0xa0, 0xb0 }, + { "CCR", MOD_PRM, PLL_MOD, 0x40, 0x70 }, + { "DSS", MOD_PRM, OMAP3430_DSS_MOD, 0x58, 0xe8 }, + { "CAM", MOD_PRM, OMAP3430_CAM_MOD, 0x58, 0xe8 }, + { "PER", MOD_PRM, OMAP3430_PER_MOD, 0x58, 0xe8 }, + { "EMU", MOD_PRM, OMAP3430_EMU_MOD, 0x58, 0xe4 }, + { "GLBL", MOD_PRM, OMAP3430_GR_MOD, 0x20, 0xe4 }, + { "NEON", MOD_PRM, OMAP3430_NEON_MOD, 0x58, 0xe8 }, + { "USB", MOD_PRM, OMAP3430ES2_USBHOST_MOD, 0x58, 0xe8 }, + { "", 0, 0, 0, 0 }, +}; + +#define PM_DBG_MAX_REG_SETS 4 + +static void *pm_dbg_reg_set[PM_DBG_MAX_REG_SETS] = {0}; + +static int pm_dbg_get_regset_size(void) +{ + static int regset_size = 0; + + if (regset_size == 0) { + int i = 0; + while (pm_dbg_reg_modules[i].name[0] != 0) { + regset_size += pm_dbg_reg_modules[i].high + + 4 - pm_dbg_reg_modules[i].low; + i++; + } + } + return regset_size; +} + +static void pm_dbg_regset_store(u32 *ptr) +{ + int i = 0; + int j; + u32 val; + + while (pm_dbg_reg_modules[i].name[0] != 0) { + for (j = pm_dbg_reg_modules[i].low; + j <= pm_dbg_reg_modules[i].high; j += 4) { + if (pm_dbg_reg_modules[i].type == MOD_CM) + val = omap2_cm_read_mod_reg( + pm_dbg_reg_modules[i].offset, j); + else + val = omap2_prm_read_mod_reg( + pm_dbg_reg_modules[i].offset, j); + *(ptr++) = val; + } + i++; + } +} + +void pm_dbg_regs_save(int reg_set) +{ + if (pm_dbg_reg_set[reg_set - 1] == NULL) + return; + + pm_dbg_regset_store(pm_dbg_reg_set[reg_set - 1]); +} + +#ifdef CONFIG_DEBUG_FS +static int pm_dbg_show_regs(struct seq_file *s, void *unused) +{ + int i, j; + unsigned long val; + int reg_set = (int)s->private; + u32 *ptr; + void *store = NULL; + int regs; + int linefeed; + + if (!cpu_is_omap34xx()) + return -EINVAL; + + if (reg_set == 0) { + store = kmalloc(pm_dbg_get_regset_size(), GFP_KERNEL); + if (store == NULL) + return -ENOMEM; + ptr = store; + pm_dbg_regset_store(ptr); + } else { + ptr = pm_dbg_reg_set[reg_set - 1]; + } + + i = 0; + + while (pm_dbg_reg_modules[i].name[0] != 0) { + regs = 0; + linefeed = 0; + if (pm_dbg_reg_modules[i].type == MOD_CM) + seq_printf(s, "MOD: CM_%s (%08x)\n", + pm_dbg_reg_modules[i].name, + (u32)(OMAP3430_CM_BASE + + pm_dbg_reg_modules[i].offset)); + else + seq_printf(s, "MOD: PRM_%s (%08x)\n", + pm_dbg_reg_modules[i].name, + (u32)(OMAP3430_PRM_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 = *(ptr++); + if (val != 0) { + regs++; + if (linefeed) { + seq_printf(s, "\n"); + linefeed = 0; + } + seq_printf(s, " %02x => %08lx", j, val); + if (regs % 4 == 0) + linefeed = 1; + } + } + seq_printf(s, "\n"); + i++; + } + + if (store != NULL) + kfree(store); + + return 0; +} + +#define WAKEUP_SOURCE_LEN 512 +void pm_dbg_show_wakeup_source(void) +{ + u32 val = 0; + int len = 0; + static char buf[WAKEUP_SOURCE_LEN]; + char *pbuf; + u32 gpio_bit = 0; + + /* print the real wkup sources */ + memset(buf, 0, WAKEUP_SOURCE_LEN); + pbuf = buf; + len = WAKEUP_SOURCE_LEN - (pbuf - buf); + if (len > 16) + pbuf += snprintf(pbuf, len, "WAKEDUP BY: "); + + val = omap2_prm_read_mod_reg(WKUP_MOD, PM_WKST); + val &= omap2_prm_read_mod_reg(WKUP_MOD, PM_WKEN); + len = WAKEUP_SOURCE_LEN - (pbuf - buf); + if (val && len > 30) + pbuf += snprintf(pbuf, len, "WKUP_MOD(0x%x), ", val); + + val = omap2_prm_read_mod_reg(CORE_MOD, PM_WKST1); + val &= omap2_prm_read_mod_reg(CORE_MOD, PM_WKEN1); + len = WAKEUP_SOURCE_LEN - (pbuf - buf); + if (val && len > 30) + pbuf += snprintf(pbuf, len, "CORE_MOD(0x%x), ", val); + + val = omap2_prm_read_mod_reg(CORE_MOD, OMAP3430ES2_PM_WKST3); + val &= omap2_prm_read_mod_reg(CORE_MOD, OMAP3430ES2_PM_WKEN3); + len = WAKEUP_SOURCE_LEN - (pbuf - buf); + if (val && len > 30) + pbuf += snprintf(pbuf, len, "CORE3_MOD(0x%x), ", val); + + val = omap2_prm_read_mod_reg(OMAP3430_PER_MOD, PM_WKST); + val &= omap2_prm_read_mod_reg(OMAP3430_PER_MOD, PM_WKEN); + len = WAKEUP_SOURCE_LEN - (pbuf - buf); + if (val && len > 30) + pbuf += snprintf(pbuf, len, "PER_MOD(0x%x), ", val); + + val = omap2_prm_read_mod_reg(OMAP3430ES2_USBHOST_MOD, PM_WKST); + val &= omap2_prm_read_mod_reg(OMAP3430ES2_USBHOST_MOD, PM_WKEN); + len = WAKEUP_SOURCE_LEN - (pbuf - buf); + if (val && len > 30) + pbuf += snprintf(pbuf, len, "USBHOST(0x%x), ", val); + + val = omap2_prm_read_mod_reg(OMAP3430_DSS_MOD, PM_WKST); + val &= omap2_prm_read_mod_reg(OMAP3430_DSS_MOD, PM_WKEN); + len = WAKEUP_SOURCE_LEN - (pbuf - buf); + if (val && len > 30) + pbuf += snprintf(pbuf, len, "DSS(0x%x), ", val); + + val = omap2_prm_read_mod_reg(OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET); + val &= omap2_prm_read_mod_reg(OCP_MOD, OMAP3_PRM_IRQENABLE_MPU_OFFSET); + len = WAKEUP_SOURCE_LEN - (pbuf - buf); + if (val && len > 30) + pbuf += snprintf(pbuf, len, "MPU_IRQSTATUS(0x%x), ", val); + + val = omap2_prm_read_mod_reg(OMAP3430_IVA2_MOD, OMAP3430_PRM_IRQSTATUS_IVA2); + val &= omap2_prm_read_mod_reg(OMAP3430_IVA2_MOD, OMAP3430_PRM_IRQENABLE_IVA2); + len = WAKEUP_SOURCE_LEN - (pbuf - buf); + if (val && len > 30) + pbuf += snprintf(pbuf, len, "IVA2_IRQSTATUS(0x%x), ", val); + + val = __raw_readl(OMAP2_L4_IO_ADDRESS(OMAP34XX_IC_BASE + (0x009C))); + len = WAKEUP_SOURCE_LEN - (pbuf - buf); + if (val && len > 30) + pbuf += snprintf(pbuf, len, "INTC_FIQ0(0x%x), ", val); + + val = __raw_readl(OMAP2_L4_IO_ADDRESS(OMAP34XX_IC_BASE + (0x00bC))); + len = WAKEUP_SOURCE_LEN - (pbuf - buf); + if (val && len > 30) + pbuf += snprintf(pbuf, len, "INTC_FIQ1(0x%x), ", val); + + val = __raw_readl(OMAP2_L4_IO_ADDRESS(OMAP34XX_IC_BASE + (0x00dC))); + len = WAKEUP_SOURCE_LEN - (pbuf - buf); + if (val && len > 30) + pbuf += snprintf(pbuf, len, "INTC_FIQ2(0x%x), ", val); + + + val = __raw_readl(OMAP2_L4_IO_ADDRESS(OMAP34XX_IC_BASE + (0x0098))); + len = WAKEUP_SOURCE_LEN - (pbuf - buf); + if (val && len > 30) + pbuf += snprintf(pbuf, len, "INTC_IRQ0(0x%x), ", val); + + val = __raw_readl(OMAP2_L4_IO_ADDRESS(OMAP34XX_IC_BASE + (0x00B8))); + len = WAKEUP_SOURCE_LEN - (pbuf - buf); + if (val && len > 30) + pbuf += snprintf(pbuf, len, "INTC_IRQ1(0x%x), ", val); + + val = __raw_readl(OMAP2_L4_IO_ADDRESS(OMAP34XX_IC_BASE + (0x00D8))); + len = WAKEUP_SOURCE_LEN - (pbuf - buf); + if (val && len > 30) + pbuf += snprintf(pbuf, len, "INTC_IRQ2(0x%x), ", val); + + val = __raw_readl(OMAP2_L4_IO_ADDRESS(OMAP34XX_IC_BASE + (0x009C))); + len = WAKEUP_SOURCE_LEN - (pbuf - buf); + if (val && len > 30) + pbuf += snprintf(pbuf, len, "INTC_FIQ0(0x%x), ", val); + + val = __raw_readl(OMAP2_L4_IO_ADDRESS(OMAP34XX_IC_BASE + (0x00BC))); + len = WAKEUP_SOURCE_LEN - (pbuf - buf); + if (val && len > 30) + pbuf += snprintf(pbuf, len, "INTC_FIQ1(0x%x), ", val); + + val = __raw_readl(OMAP2_L4_IO_ADDRESS(OMAP34XX_IC_BASE + (0x00DC))); + len = WAKEUP_SOURCE_LEN - (pbuf - buf); + if (val && len > 30) + pbuf += snprintf(pbuf, len, "INTC_FIQ2(0x%x), ", val); + + len = WAKEUP_SOURCE_LEN - (pbuf - buf); + if ((val & (1<<29)) && len > 20) { + gpio_bit = __raw_readl(OMAP2_L4_IO_ADDRESS(0x48310018)) & + __raw_readl(OMAP2_L4_IO_ADDRESS(0x4831001C)); + pbuf += snprintf(pbuf, len, "GPIO1(0x%x), ", gpio_bit); + } + len = WAKEUP_SOURCE_LEN - (pbuf - buf); + if ((val & (1<<30)) && len > 20) { + gpio_bit = __raw_readl(OMAP2_L4_IO_ADDRESS(0x49050018)) & + __raw_readl(OMAP2_L4_IO_ADDRESS(0x4905001C)); + pbuf += snprintf(pbuf, len, "GPIO2(0x%x), ", gpio_bit); + } + len = WAKEUP_SOURCE_LEN - (pbuf - buf); + if ((val & (1<<31)) && len > 20) { + gpio_bit = __raw_readl(OMAP2_L4_IO_ADDRESS(0x49052018)) & + __raw_readl(OMAP2_L4_IO_ADDRESS(0x4905201C)); + pbuf += snprintf(pbuf, len, "GPIO3(0x%x), ", gpio_bit); + } + + val = __raw_readl(OMAP2_L4_IO_ADDRESS(OMAP34XX_IC_BASE + (0x00b8))); + len = WAKEUP_SOURCE_LEN - (pbuf - buf); + if (val && len > 30) + pbuf += snprintf(pbuf, len, "INTC_IRQ1(0x%x), ", val); + + len = WAKEUP_SOURCE_LEN - (pbuf - buf); + if ((val & (1<<0)) && len > 20) { + gpio_bit = __raw_readl(OMAP2_L4_IO_ADDRESS(0x49054018)) & + __raw_readl(OMAP2_L4_IO_ADDRESS(0x4905401C)); + pbuf += snprintf(pbuf, len, "GPIO4(0x%x), ", gpio_bit); + } + len = WAKEUP_SOURCE_LEN - (pbuf - buf); + if ((val & (1<<1)) && len > 20) { + gpio_bit = __raw_readl(OMAP2_L4_IO_ADDRESS(0x49056018)) & + __raw_readl(OMAP2_L4_IO_ADDRESS(0x4905601C)); + pbuf += snprintf(pbuf, len, "GPIO5(0x%x), ", gpio_bit); + } + len = WAKEUP_SOURCE_LEN - (pbuf - buf); + if ((val & (1<<2)) && len > 20) { + gpio_bit = __raw_readl(OMAP2_L4_IO_ADDRESS(0x49058018)) & + __raw_readl(OMAP2_L4_IO_ADDRESS(0x4905801C)); + pbuf += snprintf(pbuf, len, "GPIO6(0x%x), ", gpio_bit); + } + + val = __raw_readl(OMAP2_L4_IO_ADDRESS(OMAP34XX_IC_BASE + (0x00d8))); + len = WAKEUP_SOURCE_LEN - (pbuf - buf); + if (val && len > 30) + pbuf += snprintf(pbuf, len, "INTC_IRQ2(0x%x)", val); + + pr_debug("%s\n", buf); + +} +EXPORT_SYMBOL(pm_dbg_show_wakeup_source); + +static int pm_dbg_reg_open(struct inode *inode, struct file *file) +{ + return single_open(file, pm_dbg_show_regs, inode->i_private); +} + +static const struct file_operations debug_reg_fops = { + .open = pm_dbg_reg_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; +#endif + +int pm_dbg_regs_dump(int reg_set) +{ + int i, j; + unsigned long val; + u32 *ptr; + int regs; + + if ((reg_set <= 0) || (reg_set > PM_DBG_MAX_REG_SETS)) + return -EINVAL; + + ptr = pm_dbg_reg_set[reg_set - 1]; + + i = 0; + + while (pm_dbg_reg_modules[i].name[0] != 0) { + regs = 0; + if (pm_dbg_reg_modules[i].type == MOD_CM) + pr_debug("MOD: CM_%s (%08x)\n", + pm_dbg_reg_modules[i].name, + (u32)(OMAP3430_CM_BASE + + pm_dbg_reg_modules[i].offset)); + else + pr_debug("MOD: PRM_%s (%08x)\n", + pm_dbg_reg_modules[i].name, + (u32)(OMAP3430_PRM_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 = *(ptr++); + if (val != 0) { + regs++; + pr_debug(" %02x => %08lx\n", j, val); + } + } + i++; + } + + return 0; +} +EXPORT_SYMBOL(pm_dbg_regs_dump); + +static void __init pm_dbg_regset_init(void) +{ + int i; + + for (i = 0; i < PM_DBG_MAX_REG_SETS; i++) { + pm_dbg_reg_set[i] = + kmalloc(pm_dbg_get_regset_size(), GFP_KERNEL); + } +} + +#ifdef CONFIG_DEBUG_FS +int __init pm_dbg_regs_init(struct dentry *d) +{ + int i; + char name[2]; + + if (!cpu_is_omap34xx()) { + pr_err("%s: only OMAP3 supported\n", __func__); + return -ENODEV; + } + + pm_dbg_dir = debugfs_create_dir("registers", d); + if (IS_ERR(pm_dbg_dir)) + return PTR_ERR(pm_dbg_dir); + + (void) debugfs_create_file("current", S_IRUGO, + pm_dbg_dir, (void *)0, &debug_reg_fops); + + pm_dbg_regset_init(); + for (i = 0; i < PM_DBG_MAX_REG_SETS; i++) { + if (pm_dbg_reg_set[i] != NULL) { + sprintf(name, "%d", i + 1); + (void) debugfs_create_file(name, S_IRUGO, + pm_dbg_dir, (void *)(i+1), &debug_reg_fops); + } + } + + return 0; +} +#else +static int __init pm_dbg_regs_init(void) +{ + if (!cpu_is_omap34xx()) { + pr_err("%s: only OMAP3 supported\n", __func__); + return -ENODEV; + } + + pm_dbg_regset_init(); + return 0; +} +omap_arch_initcall(pm_dbg_regs_init); +#endif diff --git a/arch/arm/mach-omap2/pm-debug-regs.h b/arch/arm/mach-omap2/pm-debug-regs.h new file mode 100644 index 00000000000..e403977affa --- /dev/null +++ b/arch/arm/mach-omap2/pm-debug-regs.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2013 Motorola Mobility LLC + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __PM_DEBUG_REGS_H__ +#define __PM_DEBUG_REGS_H__ + +#include + +#ifdef CONFIG_PM_DEBUG +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_show_wakeup_source(void); +#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_show_wakeup_source(void) {}; +#endif + +#endif diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c index 0b339861d75..cc38db9edf0 100644 --- a/arch/arm/mach-omap2/pm-debug.c +++ b/arch/arm/mach-omap2/pm-debug.c @@ -36,6 +36,7 @@ #include "cm2xxx_3xxx.h" #include "prm2xxx_3xxx.h" #include "pm.h" +#include "pm-debug-regs.h" u32 enable_off_mode; @@ -273,6 +274,9 @@ static int __init pm_dbg_init(void) (void) debugfs_create_file("enable_off_mode", S_IRUGO | S_IWUSR, d, &enable_off_mode, &pm_dbg_option_fops); + + pm_dbg_regs_init(d); + pm_dbg_init_done = 1; return 0; diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c index a52cfb7fb48..54cd309e790 100644 --- a/arch/arm/mach-omap2/pm34xx.c +++ b/arch/arm/mach-omap2/pm34xx.c @@ -50,6 +50,7 @@ #include "sdrc.h" #include "sram.h" #include "control.h" +#include "pm-debug-regs.h" /* pm34xx errata defined in pm.h */ u16 pm34xx_errata; @@ -71,6 +72,7 @@ void (*omap3_do_wfi_sram)(void); static struct powerdomain *mpu_pwrdm, *neon_pwrdm; static struct powerdomain *core_pwrdm, *per_pwrdm; +static struct powerdomain *dss_pwrdm; static void omap3_core_save_context(void) { @@ -295,7 +297,6 @@ void omap_sram_idle(void) } omap3_intc_prepare_idle(); - /* * On EMU/HS devices ROM code restores a SRDC value * from scratchpad which has automatic self refresh on timeout @@ -308,6 +309,9 @@ void omap_sram_idle(void) core_next_state == PWRDM_POWER_OFF) sdrc_pwr = sdrc_read_reg(SDRC_POWER); + if (suspend_debug) + pm_dbg_regs_save(1); + /* * omap3_arm_context is the location where some ARM context * get saved. The rest is placed on the stack, and restored @@ -320,6 +324,9 @@ void omap_sram_idle(void) else omap34xx_do_sram_idle(save_state); + if (suspend_debug) + pm_dbg_regs_save(2); + /* Restore normal SDRC POWER settings */ if (cpu_is_omap3430() && omap_rev() >= OMAP3430_REV_ES3_0 && (omap_type() == OMAP2_DEVICE_TYPE_EMU || @@ -396,11 +403,15 @@ restore: } omap_set_pwrdm_state(pwrst->pwrdm, pwrst->saved_state); } - if (ret) + if (ret) { pr_err("Could not enter target state in pm_suspend\n"); - else + pm_dbg_regs_dump(1); + pm_dbg_regs_dump(2); + } else pr_info("Successfully put all powerdomains to target state\n"); + pm_dbg_show_wakeup_source(); + suspend_debug = false; return ret; } @@ -653,6 +664,7 @@ static void __init pm_errata_configure(void) pm34xx_errata |= PM_RTA_ERRATUM_i608; /* Enable the l2 cache toggling in sleep logic */ enable_omap3630_toggle_l2_on_restore(); + if (omap_rev() < OMAP3630_REV_ES1_2) pm34xx_errata |= (PM_SDRC_WAKEUP_ERRATUM_i583 | PM_PER_MEMORIES_ERRATUM_i582); @@ -713,6 +725,7 @@ int __init omap3_pm_init(void) neon_pwrdm = pwrdm_lookup("neon_pwrdm"); per_pwrdm = pwrdm_lookup("per_pwrdm"); core_pwrdm = pwrdm_lookup("core_pwrdm"); + dss_pwrdm = pwrdm_lookup("dss_pwrdm"); neon_clkdm = clkdm_lookup("neon_clkdm"); mpu_clkdm = clkdm_lookup("mpu_clkdm"); diff --git a/arch/arm/mach-omap2/prm2xxx.h b/arch/arm/mach-omap2/prm2xxx.h index 3194dd87e0e..8f16aecf92f 100644 --- a/arch/arm/mach-omap2/prm2xxx.h +++ b/arch/arm/mach-omap2/prm2xxx.h @@ -94,6 +94,9 @@ */ /* Register offsets appearing on both OMAP2 and OMAP3 */ +#define INTC_PENDING_IRQ0 0x0098 +#define INTC_PENDING_IRQ1 0x00b8 +#define INTC_PENDING_IRQ2 0x00d8 #define OMAP2_RM_RSTCTRL 0x0050 #define OMAP2_RM_RSTTIME 0x0054 -- cgit v1.2.3-70-g09d2