public inbox for linux-omap@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/04] PM OMAP3: Misc patches
@ 2008-10-29 11:31 Tero Kristo
  2008-10-29 11:31 ` [PATCH 01/04] Fix cpuidle off-modes to be controlled via sysfs Tero Kristo
  0 siblings, 1 reply; 9+ messages in thread
From: Tero Kristo @ 2008-10-29 11:31 UTC (permalink / raw)
  To: linux-omap

Some misc PM related patches here. #1 and #3 are more important than others,
#4 introduces the PRCM register dump capability to PM debug, #2 is a sort
of cosmetic change.

--Tero



^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 01/04] Fix cpuidle off-modes to be controlled via sysfs
  2008-10-29 11:31 [PATCH 00/04] PM OMAP3: Misc patches Tero Kristo
@ 2008-10-29 11:31 ` Tero Kristo
  2008-10-29 11:31   ` [PATCH 02/04] PM debug: do not print out status for meta powerdomains (dpll*) Tero Kristo
  2008-10-29 18:13   ` [PATCH 01/04] Fix cpuidle off-modes to be controlled via sysfs Kevin Hilman
  0 siblings, 2 replies; 9+ messages in thread
From: Tero Kristo @ 2008-10-29 11:31 UTC (permalink / raw)
  To: linux-omap

Signed-off-by: Tero Kristo <tero.kristo@nokia.com>
---
 arch/arm/mach-omap2/cpuidle34xx.c |   21 ++++++++++++++++++---
 arch/arm/mach-omap2/pm.c          |    4 ++--
 2 files changed, 20 insertions(+), 5 deletions(-)

diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c
index 235976e..f97c4d8 100644
--- a/arch/arm/mach-omap2/cpuidle34xx.c
+++ b/arch/arm/mach-omap2/cpuidle34xx.c
@@ -29,6 +29,8 @@
 #include <mach/control.h>
 #include <mach/common.h>
 
+#include "pm.h"
+
 #ifdef CONFIG_CPU_IDLE
 
 #define OMAP3_MAX_STATES 7
@@ -77,6 +79,8 @@ static int omap3_enter_idle(struct cpuidle_device *dev,
 {
 	struct omap3_processor_cx *cx = cpuidle_get_statedata(state);
 	struct timespec ts_preidle, ts_postidle, ts_idle;
+	int mpu_next_state;
+	int core_next_state;
 
 	current_cx_state = *cx;
 
@@ -89,8 +93,19 @@ static int omap3_enter_idle(struct cpuidle_device *dev,
 	local_irq_disable();
 	local_fiq_disable();
 
-	set_pwrdm_state(mpu_pd, cx->mpu_state);
-	set_pwrdm_state(core_pd, cx->core_state);
+	/* Dirty hack to enable / disable off-mode dynamically */
+	mpu_next_state = cx->mpu_state;
+	core_next_state = cx->core_state;
+
+	if (!enable_off_mode) {
+		if (mpu_next_state == PWRDM_POWER_OFF)
+			mpu_next_state = PWRDM_POWER_RET;
+		if (core_next_state == PWRDM_POWER_OFF)
+			core_next_state = PWRDM_POWER_RET;
+	}
+
+	set_pwrdm_state(mpu_pd, mpu_next_state);
+	set_pwrdm_state(core_pd, core_next_state);
 
 	if (omap_irq_pending())
 		goto return_sleep_time;
@@ -195,7 +210,7 @@ void omap_init_power_states(void)
 				CPUIDLE_FLAG_CHECK_BM;
 
 	/* C6 . MPU OFF + Core OFF */
-	omap3_power_states[OMAP3_STATE_C6].valid = 0;
+	omap3_power_states[OMAP3_STATE_C6].valid = 1;
 	omap3_power_states[OMAP3_STATE_C6].type = OMAP3_STATE_C6;
 	omap3_power_states[OMAP3_STATE_C6].sleep_latency = 10000;
 	omap3_power_states[OMAP3_STATE_C6].wakeup_latency = 30000;
diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
index 136683b..9dbe7e2 100644
--- a/arch/arm/mach-omap2/pm.c
+++ b/arch/arm/mach-omap2/pm.c
@@ -87,9 +87,9 @@ static ssize_t idle_store(struct kobject *kobj, struct kobj_attribute *attr,
 	} else if (attr == &clocks_off_while_idle_attr) {
 		clocks_off_while_idle = value;
 	} else if (attr == &enable_off_mode_attr) {
-		int enable = (value > 0) ? 1 : 0;
+		enable_off_mode = (value > 0) ? 1 : 0;
 
-		omap3_pm_off_mode_enable(enable);
+		omap3_pm_off_mode_enable(enable_off_mode);
 	} else if (attr == &voltage_off_while_idle_attr) {
 		voltage_off_while_idle = value;
 		if (voltage_off_while_idle)
-- 
1.5.4.3


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 02/04] PM debug: do not print out status for meta powerdomains (dpll*)
  2008-10-29 11:31 ` [PATCH 01/04] Fix cpuidle off-modes to be controlled via sysfs Tero Kristo
@ 2008-10-29 11:31   ` Tero Kristo
  2008-10-29 11:31     ` [PATCH 03/04] PM counters: fix initialization race condition Tero Kristo
  2008-10-29 18:15     ` [PATCH 02/04] PM debug: do not print out status for meta powerdomains (dpll*) Kevin Hilman
  2008-10-29 18:13   ` [PATCH 01/04] Fix cpuidle off-modes to be controlled via sysfs Kevin Hilman
  1 sibling, 2 replies; 9+ messages in thread
From: Tero Kristo @ 2008-10-29 11:31 UTC (permalink / raw)
  To: linux-omap

Signed-off-by: Tero Kristo <tero.kristo@nokia.com>
---
 arch/arm/mach-omap2/pm-debug.c |    6 ++++--
 1 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c
index c903c55..d21af83 100644
--- a/arch/arm/mach-omap2/pm-debug.c
+++ b/arch/arm/mach-omap2/pm-debug.c
@@ -197,7 +197,8 @@ static int clkdm_dbg_show_counter(struct clockdomain *clkdm, void *user)
 	struct seq_file *s = (struct seq_file *)user;
 
 	if (strcmp(clkdm->name, "emu_clkdm") == 0 ||
-		strcmp(clkdm->name, "wkup_clkdm") == 0)
+		strcmp(clkdm->name, "wkup_clkdm") == 0 ||
+		strncmp(clkdm->name, "dpll", 4) == 0)
 		return 0;
 
 	seq_printf(s, "%s->%s (%d)", clkdm->name,
@@ -214,7 +215,8 @@ static int pwrdm_dbg_show_counter(struct powerdomain *pwrdm, void *user)
 	int i;
 
 	if (strcmp(pwrdm->name, "emu_pwrdm") == 0 ||
-		strcmp(pwrdm->name, "wkup_pwrdm") == 0)
+		strcmp(pwrdm->name, "wkup_pwrdm") == 0 ||
+		strncmp(pwrdm->name, "dpll", 4) == 0)
 		return 0;
 
 	if (pwrdm->state != pwrdm_read_pwrst(pwrdm))
-- 
1.5.4.3


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 03/04] PM counters: fix initialization race condition
  2008-10-29 11:31   ` [PATCH 02/04] PM debug: do not print out status for meta powerdomains (dpll*) Tero Kristo
@ 2008-10-29 11:31     ` Tero Kristo
  2008-10-29 11:31       ` [PATCH 04/04] PM debug: Add PRCM register dump support Tero Kristo
  2008-10-29 18:16       ` [PATCH 03/04] PM counters: fix initialization race condition Kevin Hilman
  2008-10-29 18:15     ` [PATCH 02/04] PM debug: do not print out status for meta powerdomains (dpll*) Kevin Hilman
  1 sibling, 2 replies; 9+ messages in thread
From: Tero Kristo @ 2008-10-29 11:31 UTC (permalink / raw)
  To: linux-omap

Signed-off-by: Tero Kristo <tero.kristo@nokia.com>
---
 arch/arm/mach-omap2/clockdomain.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c
index b0b5885..b27afc0 100644
--- a/arch/arm/mach-omap2/clockdomain.c
+++ b/arch/arm/mach-omap2/clockdomain.c
@@ -481,6 +481,8 @@ void omap2_clkdm_allow_idle(struct clockdomain *clkdm)
 			    v << __ffs(clkdm->clktrctrl_mask),
 			    clkdm->pwrdm.ptr->prcm_offs,
 			    CM_CLKSTCTRL);
+
+	pwrdm_clkdm_state_switch(clkdm);
 }
 
 /**
-- 
1.5.4.3


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 04/04] PM debug: Add PRCM register dump support
  2008-10-29 11:31     ` [PATCH 03/04] PM counters: fix initialization race condition Tero Kristo
@ 2008-10-29 11:31       ` Tero Kristo
  2008-10-29 18:18         ` Kevin Hilman
  2008-10-29 18:16       ` [PATCH 03/04] PM counters: fix initialization race condition Kevin Hilman
  1 sibling, 1 reply; 9+ messages in thread
From: Tero Kristo @ 2008-10-29 11:31 UTC (permalink / raw)
  To: linux-omap

Allows dumping out current register contents from the debug filesystem, and
also allows user to add arbitrary register save points into code. Current
register contents are available under debugfs at:

[debugfs]/pm_debug/registers/current

To add a save point, do following:

>From module init (or somewhere before the save call, called only once):
  pm_dbg_init_regset(n); // n=1..4, allocates memory for dump area #n

>From arbitrary code location:
  pm_dbg_regset_save(n); // n=1..4, saves registers to dump area #n

After this, the register dump can be seen under [debugfs]/pm_debug/registers/n

Signed-off-by: Tero Kristo <tero.kristo@nokia.com>
---
 arch/arm/mach-omap2/pm-debug.c |  208 ++++++++++++++++++++++++++++++++++++++++
 arch/arm/mach-omap2/pm.h       |    4 +
 2 files changed, 212 insertions(+), 0 deletions(-)
 mode change 100644 => 100755 arch/arm/mach-omap2/pm-debug.c
 mode change 100644 => 100755 arch/arm/mach-omap2/pm.h

diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c
old mode 100644
new mode 100755
index d21af83..05f3914
--- a/arch/arm/mach-omap2/pm-debug.c
+++ b/arch/arm/mach-omap2/pm-debug.c
@@ -159,6 +159,8 @@ void omap2_pm_dump(int mode, int resume, unsigned int us)
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
 
+static void pm_dbg_regset_store(u32 *ptr);
+
 struct dentry *pm_dbg_dir;
 
 static int pm_dbg_init_done;
@@ -168,6 +170,159 @@ enum {
 	DEBUG_FILE_TIMERS,
 };
 
+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];
+
+static int pm_dbg_get_regset_size(void)
+{
+	static int regset_size;
+
+	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 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 (reg_set == 0) {
+		store = kmalloc(pm_dbg_get_regset_size(), GFP_KERNEL);
+		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)(OMAP2_CM_BASE +
+				pm_dbg_reg_modules[i].offset));
+		else
+			seq_printf(s, "MOD: PRM_%s (%08x)\n",
+				pm_dbg_reg_modules[i].name,
+				(u32)(OMAP2_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;
+}
+
+static void pm_dbg_regset_store(u32 *ptr)
+{
+	int i, j;
+	u32 val;
+
+	i = 0;
+
+	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 = cm_read_mod_reg(
+					pm_dbg_reg_modules[i].offset, j);
+			else
+				val = prm_read_mod_reg(
+					pm_dbg_reg_modules[i].offset, j);
+			*(ptr++) = val;
+		}
+		i++;
+	}
+}
+
+int pm_dbg_regset_save(int reg_set)
+{
+	if (pm_dbg_reg_set[reg_set-1] == NULL)
+		return -EINVAL;
+
+	pm_dbg_regset_store(pm_dbg_reg_set[reg_set-1]);
+
+	return 0;
+}
+
 static const char pwrdm_state_names[][4] = {
 	"OFF",
 	"RET",
@@ -281,6 +436,11 @@ static int pm_dbg_open(struct inode *inode, struct file *file)
 	};
 }
 
+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_fops = {
 	.open           = pm_dbg_open,
 	.read           = seq_read,
@@ -288,6 +448,37 @@ static const struct file_operations debug_fops = {
 	.release        = single_release,
 };
 
+static const struct file_operations debug_reg_fops = {
+	.open           = pm_dbg_reg_open,
+	.read           = seq_read,
+	.llseek         = seq_lseek,
+	.release        = single_release,
+};
+
+int pm_dbg_regset_init(int reg_set)
+{
+	char name[2];
+
+	if (reg_set < 1 || reg_set > PM_DBG_MAX_REG_SETS ||
+		pm_dbg_reg_set[reg_set-1] != NULL)
+		return -EINVAL;
+
+	pm_dbg_reg_set[reg_set-1] =
+		kmalloc(pm_dbg_get_regset_size(), GFP_KERNEL);
+
+	if (pm_dbg_reg_set[reg_set-1] == NULL)
+		return -ENOMEM;
+
+	if (pm_dbg_dir != NULL) {
+		sprintf(name, "%d", reg_set);
+
+		(void) debugfs_create_file(name, S_IRUGO,
+			pm_dbg_dir, (void *)reg_set, &debug_reg_fops);
+	}
+
+	return 0;
+}
+
 static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
 {
 	int i;
@@ -307,7 +498,9 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
 
 static int __init pm_dbg_init(void)
 {
+	int i;
 	struct dentry *d;
+	char name[2];
 
 	printk(KERN_INFO "pm_dbg_init()\n");
 
@@ -322,6 +515,21 @@ static int __init pm_dbg_init(void)
 
 	pwrdm_for_each(pwrdms_setup, NULL);
 
+	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);
+
+	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);
+
+		}
+
 	pm_dbg_init_done = 1;
 
 	return 0;
diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
old mode 100644
new mode 100755
index b7d66be..8f1ebea
--- a/arch/arm/mach-omap2/pm.h
+++ b/arch/arm/mach-omap2/pm.h
@@ -34,9 +34,13 @@ extern void omap3_pm_off_mode_enable(int);
 extern void omap2_pm_dump(int mode, int resume, unsigned int us);
 extern int omap2_pm_debug;
 extern void pm_dbg_update_time(struct powerdomain *pwrdm, int prev);
+extern int pm_dbg_regset_save(int reg_set);
+extern int pm_dbg_regset_init(int reg_set);
 #else
 #define omap2_pm_dump(mode, resume, us)		do {} while (0);
 #define omap2_pm_debug				0
 #define pm_dbg_update_time(pwrdm, prev) do {} while (0);
+#define pm_dbg_regset_save(reg_set) do {} while (0);
+#define pm_dbg_regset_init(reg_set) do {} while (0);
 #endif /* CONFIG_PM_DEBUG */
 #endif
-- 
1.5.4.3


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH 01/04] Fix cpuidle off-modes to be controlled via sysfs
  2008-10-29 11:31 ` [PATCH 01/04] Fix cpuidle off-modes to be controlled via sysfs Tero Kristo
  2008-10-29 11:31   ` [PATCH 02/04] PM debug: do not print out status for meta powerdomains (dpll*) Tero Kristo
@ 2008-10-29 18:13   ` Kevin Hilman
  1 sibling, 0 replies; 9+ messages in thread
From: Kevin Hilman @ 2008-10-29 18:13 UTC (permalink / raw)
  To: Tero Kristo; +Cc: linux-omap

Tero Kristo <tero.kristo@nokia.com> writes:

> Signed-off-by: Tero Kristo <tero.kristo@nokia.com>
> ---
>  arch/arm/mach-omap2/cpuidle34xx.c |   21 ++++++++++++++++++---
>  arch/arm/mach-omap2/pm.c          |    4 ++--
>  2 files changed, 20 insertions(+), 5 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c
> index 235976e..f97c4d8 100644
> --- a/arch/arm/mach-omap2/cpuidle34xx.c
> +++ b/arch/arm/mach-omap2/cpuidle34xx.c
> @@ -29,6 +29,8 @@
>  #include <mach/control.h>
>  #include <mach/common.h>
>  
> +#include "pm.h"
> +
>  #ifdef CONFIG_CPU_IDLE
>  
>  #define OMAP3_MAX_STATES 7
> @@ -77,6 +79,8 @@ static int omap3_enter_idle(struct cpuidle_device *dev,
>  {
>  	struct omap3_processor_cx *cx = cpuidle_get_statedata(state);
>  	struct timespec ts_preidle, ts_postidle, ts_idle;
> +	int mpu_next_state;
> +	int core_next_state;
>  
>  	current_cx_state = *cx;
>  
> @@ -89,8 +93,19 @@ static int omap3_enter_idle(struct cpuidle_device *dev,
>  	local_irq_disable();
>  	local_fiq_disable();
>  
> -	set_pwrdm_state(mpu_pd, cx->mpu_state);
> -	set_pwrdm_state(core_pd, cx->core_state);
> +	/* Dirty hack to enable / disable off-mode dynamically */
> +	mpu_next_state = cx->mpu_state;
> +	core_next_state = cx->core_state;
> +
> +	if (!enable_off_mode) {
> +		if (mpu_next_state == PWRDM_POWER_OFF)
> +			mpu_next_state = PWRDM_POWER_RET;
> +		if (core_next_state == PWRDM_POWER_OFF)
> +			core_next_state = PWRDM_POWER_RET;
> +	}
> +
> +	set_pwrdm_state(mpu_pd, mpu_next_state);
> +	set_pwrdm_state(core_pd, core_next_state);
>  
>  	if (omap_irq_pending())
>  		goto return_sleep_time;
> @@ -195,7 +210,7 @@ void omap_init_power_states(void)
>  				CPUIDLE_FLAG_CHECK_BM;
>  
>  	/* C6 . MPU OFF + Core OFF */
> -	omap3_power_states[OMAP3_STATE_C6].valid = 0;
> +	omap3_power_states[OMAP3_STATE_C6].valid = 1;
>  	omap3_power_states[OMAP3_STATE_C6].type = OMAP3_STATE_C6;
>  	omap3_power_states[OMAP3_STATE_C6].sleep_latency = 10000;
>  	omap3_power_states[OMAP3_STATE_C6].wakeup_latency = 30000;
> diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
> index 136683b..9dbe7e2 100644
> --- a/arch/arm/mach-omap2/pm.c
> +++ b/arch/arm/mach-omap2/pm.c
> @@ -87,9 +87,9 @@ static ssize_t idle_store(struct kobject *kobj, struct kobj_attribute *attr,
>  	} else if (attr == &clocks_off_while_idle_attr) {
>  		clocks_off_while_idle = value;
>  	} else if (attr == &enable_off_mode_attr) {
> -		int enable = (value > 0) ? 1 : 0;
> +		enable_off_mode = (value > 0) ? 1 : 0;
>  
> -		omap3_pm_off_mode_enable(enable);
> +		omap3_pm_off_mode_enable(enable_off_mode);
>  	} else if (attr == &voltage_off_while_idle_attr) {
>  		voltage_off_while_idle = value;
>  		if (voltage_off_while_idle)

I already have similar version to this in the staging area for the
next PM branch[1] (which is not quite ready.)

Kevin

[1] http://git.kernel.org/?p=linux/kernel/git/khilman/linux-omap-pm.git;a=shortlog;h=tmp/pm-next


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 02/04] PM debug: do not print out status for meta powerdomains (dpll*)
  2008-10-29 11:31   ` [PATCH 02/04] PM debug: do not print out status for meta powerdomains (dpll*) Tero Kristo
  2008-10-29 11:31     ` [PATCH 03/04] PM counters: fix initialization race condition Tero Kristo
@ 2008-10-29 18:15     ` Kevin Hilman
  1 sibling, 0 replies; 9+ messages in thread
From: Kevin Hilman @ 2008-10-29 18:15 UTC (permalink / raw)
  To: Tero Kristo; +Cc: linux-omap

Tero Kristo <tero.kristo@nokia.com> writes:

> Signed-off-by: Tero Kristo <tero.kristo@nokia.com>
> ---
>  arch/arm/mach-omap2/pm-debug.c |    6 ++++--
>  1 files changed, 4 insertions(+), 2 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c
> index c903c55..d21af83 100644
> --- a/arch/arm/mach-omap2/pm-debug.c
> +++ b/arch/arm/mach-omap2/pm-debug.c
> @@ -197,7 +197,8 @@ static int clkdm_dbg_show_counter(struct clockdomain *clkdm, void *user)
>  	struct seq_file *s = (struct seq_file *)user;
>  
>  	if (strcmp(clkdm->name, "emu_clkdm") == 0 ||
> -		strcmp(clkdm->name, "wkup_clkdm") == 0)
> +		strcmp(clkdm->name, "wkup_clkdm") == 0 ||
> +		strncmp(clkdm->name, "dpll", 4) == 0)
>  		return 0;
>  
>  	seq_printf(s, "%s->%s (%d)", clkdm->name,
> @@ -214,7 +215,8 @@ static int pwrdm_dbg_show_counter(struct powerdomain *pwrdm, void *user)
>  	int i;
>  
>  	if (strcmp(pwrdm->name, "emu_pwrdm") == 0 ||
> -		strcmp(pwrdm->name, "wkup_pwrdm") == 0)
> +		strcmp(pwrdm->name, "wkup_pwrdm") == 0 ||
> +		strncmp(pwrdm->name, "dpll", 4) == 0)
>  		return 0;
>  
>  	if (pwrdm->state != pwrdm_read_pwrst(pwrdm))
> -- 
> 1.5.4.3
>

Thanks, pulling into next PM branch.

Kevin

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 03/04] PM counters: fix initialization race condition
  2008-10-29 11:31     ` [PATCH 03/04] PM counters: fix initialization race condition Tero Kristo
  2008-10-29 11:31       ` [PATCH 04/04] PM debug: Add PRCM register dump support Tero Kristo
@ 2008-10-29 18:16       ` Kevin Hilman
  1 sibling, 0 replies; 9+ messages in thread
From: Kevin Hilman @ 2008-10-29 18:16 UTC (permalink / raw)
  To: Tero Kristo; +Cc: linux-omap

Tero Kristo <tero.kristo@nokia.com> writes:

> Signed-off-by: Tero Kristo <tero.kristo@nokia.com>
> ---
>  arch/arm/mach-omap2/clockdomain.c |    2 ++
>  1 files changed, 2 insertions(+), 0 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c
> index b0b5885..b27afc0 100644
> --- a/arch/arm/mach-omap2/clockdomain.c
> +++ b/arch/arm/mach-omap2/clockdomain.c
> @@ -481,6 +481,8 @@ void omap2_clkdm_allow_idle(struct clockdomain *clkdm)
>  			    v << __ffs(clkdm->clktrctrl_mask),
>  			    clkdm->pwrdm.ptr->prcm_offs,
>  			    CM_CLKSTCTRL);
> +
> +	pwrdm_clkdm_state_switch(clkdm);
>  }
>  
>  /**

Thanks, pulling into next PM branch.

Kevin

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 04/04] PM debug: Add PRCM register dump support
  2008-10-29 11:31       ` [PATCH 04/04] PM debug: Add PRCM register dump support Tero Kristo
@ 2008-10-29 18:18         ` Kevin Hilman
  0 siblings, 0 replies; 9+ messages in thread
From: Kevin Hilman @ 2008-10-29 18:18 UTC (permalink / raw)
  To: Tero Kristo; +Cc: linux-omap

Tero Kristo <tero.kristo@nokia.com> writes:

> Allows dumping out current register contents from the debug filesystem, and
> also allows user to add arbitrary register save points into code. Current
> register contents are available under debugfs at:
>
> [debugfs]/pm_debug/registers/current
>
> To add a save point, do following:
>
> From module init (or somewhere before the save call, called only once):
>   pm_dbg_init_regset(n); // n=1..4, allocates memory for dump area #n
>
> From arbitrary code location:
>   pm_dbg_regset_save(n); // n=1..4, saves registers to dump area #n
>
> After this, the register dump can be seen under [debugfs]/pm_debug/registers/n
>
> Signed-off-by: Tero Kristo <tero.kristo@nokia.com>


Excellent, I was hoping this feature would be coming along.

Pulling into next PM branch.

Kevin

> ---
>  arch/arm/mach-omap2/pm-debug.c |  208 ++++++++++++++++++++++++++++++++++++++++
>  arch/arm/mach-omap2/pm.h       |    4 +
>  2 files changed, 212 insertions(+), 0 deletions(-)
>  mode change 100644 => 100755 arch/arm/mach-omap2/pm-debug.c
>  mode change 100644 => 100755 arch/arm/mach-omap2/pm.h
>
> diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c
> old mode 100644
> new mode 100755
> index d21af83..05f3914
> --- a/arch/arm/mach-omap2/pm-debug.c
> +++ b/arch/arm/mach-omap2/pm-debug.c
> @@ -159,6 +159,8 @@ void omap2_pm_dump(int mode, int resume, unsigned int us)
>  #include <linux/debugfs.h>
>  #include <linux/seq_file.h>
>  
> +static void pm_dbg_regset_store(u32 *ptr);
> +
>  struct dentry *pm_dbg_dir;
>  
>  static int pm_dbg_init_done;
> @@ -168,6 +170,159 @@ enum {
>  	DEBUG_FILE_TIMERS,
>  };
>  
> +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];
> +
> +static int pm_dbg_get_regset_size(void)
> +{
> +	static int regset_size;
> +
> +	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 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 (reg_set == 0) {
> +		store = kmalloc(pm_dbg_get_regset_size(), GFP_KERNEL);
> +		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)(OMAP2_CM_BASE +
> +				pm_dbg_reg_modules[i].offset));
> +		else
> +			seq_printf(s, "MOD: PRM_%s (%08x)\n",
> +				pm_dbg_reg_modules[i].name,
> +				(u32)(OMAP2_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;
> +}
> +
> +static void pm_dbg_regset_store(u32 *ptr)
> +{
> +	int i, j;
> +	u32 val;
> +
> +	i = 0;
> +
> +	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 = cm_read_mod_reg(
> +					pm_dbg_reg_modules[i].offset, j);
> +			else
> +				val = prm_read_mod_reg(
> +					pm_dbg_reg_modules[i].offset, j);
> +			*(ptr++) = val;
> +		}
> +		i++;
> +	}
> +}
> +
> +int pm_dbg_regset_save(int reg_set)
> +{
> +	if (pm_dbg_reg_set[reg_set-1] == NULL)
> +		return -EINVAL;
> +
> +	pm_dbg_regset_store(pm_dbg_reg_set[reg_set-1]);
> +
> +	return 0;
> +}
> +
>  static const char pwrdm_state_names[][4] = {
>  	"OFF",
>  	"RET",
> @@ -281,6 +436,11 @@ static int pm_dbg_open(struct inode *inode, struct file *file)
>  	};
>  }
>  
> +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_fops = {
>  	.open           = pm_dbg_open,
>  	.read           = seq_read,
> @@ -288,6 +448,37 @@ static const struct file_operations debug_fops = {
>  	.release        = single_release,
>  };
>  
> +static const struct file_operations debug_reg_fops = {
> +	.open           = pm_dbg_reg_open,
> +	.read           = seq_read,
> +	.llseek         = seq_lseek,
> +	.release        = single_release,
> +};
> +
> +int pm_dbg_regset_init(int reg_set)
> +{
> +	char name[2];
> +
> +	if (reg_set < 1 || reg_set > PM_DBG_MAX_REG_SETS ||
> +		pm_dbg_reg_set[reg_set-1] != NULL)
> +		return -EINVAL;
> +
> +	pm_dbg_reg_set[reg_set-1] =
> +		kmalloc(pm_dbg_get_regset_size(), GFP_KERNEL);
> +
> +	if (pm_dbg_reg_set[reg_set-1] == NULL)
> +		return -ENOMEM;
> +
> +	if (pm_dbg_dir != NULL) {
> +		sprintf(name, "%d", reg_set);
> +
> +		(void) debugfs_create_file(name, S_IRUGO,
> +			pm_dbg_dir, (void *)reg_set, &debug_reg_fops);
> +	}
> +
> +	return 0;
> +}
> +
>  static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
>  {
>  	int i;
> @@ -307,7 +498,9 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
>  
>  static int __init pm_dbg_init(void)
>  {
> +	int i;
>  	struct dentry *d;
> +	char name[2];
>  
>  	printk(KERN_INFO "pm_dbg_init()\n");
>  
> @@ -322,6 +515,21 @@ static int __init pm_dbg_init(void)
>  
>  	pwrdm_for_each(pwrdms_setup, NULL);
>  
> +	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);
> +
> +	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);
> +
> +		}
> +
>  	pm_dbg_init_done = 1;
>  
>  	return 0;
> diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
> old mode 100644
> new mode 100755
> index b7d66be..8f1ebea
> --- a/arch/arm/mach-omap2/pm.h
> +++ b/arch/arm/mach-omap2/pm.h
> @@ -34,9 +34,13 @@ extern void omap3_pm_off_mode_enable(int);
>  extern void omap2_pm_dump(int mode, int resume, unsigned int us);
>  extern int omap2_pm_debug;
>  extern void pm_dbg_update_time(struct powerdomain *pwrdm, int prev);
> +extern int pm_dbg_regset_save(int reg_set);
> +extern int pm_dbg_regset_init(int reg_set);
>  #else
>  #define omap2_pm_dump(mode, resume, us)		do {} while (0);
>  #define omap2_pm_debug				0
>  #define pm_dbg_update_time(pwrdm, prev) do {} while (0);
> +#define pm_dbg_regset_save(reg_set) do {} while (0);
> +#define pm_dbg_regset_init(reg_set) do {} while (0);
>  #endif /* CONFIG_PM_DEBUG */
>  #endif
> -- 
> 1.5.4.3
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2008-10-29 18:19 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-10-29 11:31 [PATCH 00/04] PM OMAP3: Misc patches Tero Kristo
2008-10-29 11:31 ` [PATCH 01/04] Fix cpuidle off-modes to be controlled via sysfs Tero Kristo
2008-10-29 11:31   ` [PATCH 02/04] PM debug: do not print out status for meta powerdomains (dpll*) Tero Kristo
2008-10-29 11:31     ` [PATCH 03/04] PM counters: fix initialization race condition Tero Kristo
2008-10-29 11:31       ` [PATCH 04/04] PM debug: Add PRCM register dump support Tero Kristo
2008-10-29 18:18         ` Kevin Hilman
2008-10-29 18:16       ` [PATCH 03/04] PM counters: fix initialization race condition Kevin Hilman
2008-10-29 18:15     ` [PATCH 02/04] PM debug: do not print out status for meta powerdomains (dpll*) Kevin Hilman
2008-10-29 18:13   ` [PATCH 01/04] Fix cpuidle off-modes to be controlled via sysfs Kevin Hilman

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox