- These changes make OMAP power state register fields available as attributes per field in debugfs decoded as text with the hex value - pwrdm_read_reg_field() might replace a lot of the explicit functions for reading register fields and clean up the existing OMAP code a bit. - the changes are usable via debugfs standalone or with the patch coming for powerdebug - I've only implemented the support for the MPU PD - to support additional the other powerdomains all that's needed is to add the register_def_t's and field_def_t's
here's a screenshot: ./powerdebug -P -d failed to initialize sensors
Power Domain Information: *******************
mpu_pwrdm context lostcontext_dff 0:false lostmem_l1 0:false lostmem_l2 0:false lostmem_ram 0:false rstst emulation_rst 0:false pwrstctl powerstate 3:on-active logicretstate 1:whole lowpowerstatechange 0:false l1_retstate 1:retention l2_retstate 1:retention ram_retstate 1:retention l1_onstate 3:on-active l2_onstate 3:on-active ram_onstate 3:on-active pwrst powerstatest 3:on-active logicstatest 1:on l1_statest 3:on-active l2_statest 3:on-active ram_statest 3:on-active intransition 0:false lastpowerstateentered 3:on-active
and the patch against Linaro 12.04 kernel is:
From 4b762379805848eebd3454d6bb344a50012069d4 Mon Sep 17 00:00:00 2001
From: Eric van Tassell <evt@evtM17x.(none)> Date: Sat, 5 May 2012 15:05:48 -0500 Subject: [PATCH] + basic infrastructure for creating powerdomain attribute files in debugfs + definitions to create the attributes for mpu power domain
--- arch/arm/mach-omap2/pm-debug.c | 4 ++ arch/arm/mach-omap2/pm44xx.c | 3 +- arch/arm/mach-omap2/powerdomain.c | 89 +++++++++++++++++++++++++++ arch/arm/mach-omap2/powerdomain.h | 46 +++++++++++++- arch/arm/mach-omap2/powerdomain44xx.c | 23 +++++++ arch/arm/mach-omap2/powerdomains44xx_data.c | 85 +++++++++++++++++++++++++ arch/arm/mach-omap2/prm44xx.h | 1 + 8 files changed, 254 insertions(+), 2 deletions(-)
diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c index 4411163..2e365e3 100644 --- a/arch/arm/mach-omap2/pm-debug.c +++ b/arch/arm/mach-omap2/pm-debug.c @@ -224,6 +224,10 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *dir) (void) debugfs_create_file("suspend", S_IRUGO|S_IWUSR, d, (void *)pwrdm, &pwrdm_suspend_fops);
+#ifdef CONFIG_PM_DEBUG + if (d) + pwrdm_create_register_dirs(pwrdm, d); +#endif // CONFIG_PM_DEBUG return 0; }
diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c index 4ab9b9d..f5c189e 100644 --- a/arch/arm/mach-omap2/pm44xx.c +++ b/arch/arm/mach-omap2/pm44xx.c @@ -155,7 +155,7 @@ static int __init clkdms_setup(struct clockdomain *clkdm, void *unused) }
-static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused) +static int __init pwrdms_setup(struct powerdomain *pwrdm, void *arg) { struct power_state *pwrst;
@@ -365,6 +365,7 @@ static int __init omap4_pm_init(void) OMAP44XX_IRQ_PRCM); goto err2; } + ret = pwrdm_for_each(pwrdms_setup, NULL); if (ret) { pr_err("Failed to setup powerdomains\n"); diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c index 8a18d1b..b392760 100644 --- a/arch/arm/mach-omap2/powerdomain.c +++ b/arch/arm/mach-omap2/powerdomain.c @@ -37,6 +37,11 @@
#define PWRDM_TRACE_STATES_FLAG (1<<31)
+#ifdef CONFIG_PM_DEBUG +#include "prm-regbits-44xx.h" +#include <linux/debugfs.h> +#endif // CONFIG_PM_DEBUG + enum { PWRDM_STATE_NOW = 0, PWRDM_STATE_PREV, @@ -201,6 +206,90 @@ static int _pwrdm_post_transition_cb(struct powerdomain *pwrdm, void *unused)
/* Public functions */
+#ifdef CONFIG_PM_DEBUG +///////////////////////////////////////////////////////////////////////////// +int pwrdm_read_reg_field(field_def_t *f) +{ + int ret = -EINVAL; + + + if (!f ) + return -EINVAL; + + if (!(f->reg)) + return -EINVAL; + + if (!f->reg->pwrdm) + return -EINVAL; + + if (arch_pwrdm && arch_pwrdm->pwrdm_read_reg_field) + ret = arch_pwrdm->pwrdm_read_reg_field(f); + return ret; +} + +#define BUFMAX 4096 +static char scratch[BUFMAX]; + + +static ssize_t pwrdm_dbg_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + field_def_t *f = (field_def_t *)file->private_data; + int n; + int val; + + val = pwrdm_read_reg_field(f); + memset(scratch, 0, BUFMAX); + n = sprintf(scratch, "%d:%s", val, f->decoder(val)); + return simple_read_from_buffer(buf, count, ppos, scratch, n + 1); +} + +static int pwrdm_dbg_open(struct inode *inode, struct file *file) +{ + file->private_data = inode->i_private; + return 0; +} + +static const struct file_operations pwrdm_dbg_ops = { + .read = pwrdm_dbg_read, + .open = pwrdm_dbg_open, +}; +/////////////////////////////////////////////////////////////////////////////debug + +static void pwrdm_create_1register_dir(register_def_t *r, struct dentry *pd_dentry) +{ + struct dentry *reg_dentry; + int i; + + reg_dentry = debugfs_create_dir(r->name, pd_dentry); + for (i = 0; i < r->num_fields; i++) { + field_def_t *f = &(r->fields[i]); + + f->reg = r; // link field to register + + debugfs_create_file(f->name, + S_IRUGO, + reg_dentry, + (void *)&(r->fields[i]), + &pwrdm_dbg_ops); + } +} + +void pwrdm_create_register_dirs(struct powerdomain *p, struct dentry *pd_dentry) +{ + int i; + + if ((p == (struct powerdomain *)NULL) || (pd_dentry == (struct dentry *)NULL)) + return; + + for (i = 0; i < p->num_reg_defs; i++) { + p->register_defs[i]->pwrdm = p; + pwrdm_create_1register_dir(p->register_defs[i], pd_dentry); + } +} + +#endif // CONFIG_PM_DEBUG + /** * pwrdm_register_platform_funcs - register powerdomain implementation fns * @po: func pointers for arch specific implementations diff --git a/arch/arm/mach-omap2/powerdomain.h b/arch/arm/mach-omap2/powerdomain.h index 0d72a8a..5eaf08c 100644 --- a/arch/arm/mach-omap2/powerdomain.h +++ b/arch/arm/mach-omap2/powerdomain.h @@ -76,6 +76,47 @@
struct clockdomain; struct powerdomain; +#ifdef CONFIG_PM_DEBUG +/* general PD decoder definitions */ + +/* field definitions for PD_MPU */ + +typedef struct { + char *name; + u32 shift; + u32 mask; + char * (*decoder)(u8); // note: decoder may be NULL + struct _register_def_t_ *reg; +} field_def_t; + +typedef struct _register_def_t_ { + u32 ix; + char *name; + field_def_t *fields; + u8 num_fields; + struct powerdomain *pwrdm; +} register_def_t; + +#define NUM_ELTS(whole, part) (sizeof(whole)/sizeof(part)) +#define NUM_FIELDS(whole) (sizeof(whole)/sizeof(field_def_t)) + +#define DECODER(name) \ + char *decode_##name(u8 ix) { \ + if (ix > sizeof(name)/sizeof(char *)) \ + return "*invalid*"; \ + else \ + return name[ix]; \ +} + +#define FIELD_ATTR(name_str, base_name, funcp) \ + { \ + .name = name_str, \ + .shift = base_name ## _SHIFT , \ + .mask = base_name ## _MASK , \ + .decoder = funcp \ + } + +#endif //CONFIG_PM_DEBUG
/** * struct powerdomain - OMAP powerdomain @@ -124,6 +165,8 @@ struct powerdomain { #ifdef CONFIG_PM_DEBUG s64 timer; s64 state_timer[PWRDM_MAX_PWRSTS]; + register_def_t **register_defs; + int num_reg_defs; #endif };
@@ -149,6 +192,7 @@ struct powerdomain { * @pwrdm_wait_transition: Wait for a pd state transition to complete */ struct pwrdm_ops { + int (*pwrdm_read_reg_field)(field_def_t *f); int (*pwrdm_set_next_pwrst)(struct powerdomain *pwrdm, u8 pwrst); int (*pwrdm_read_next_pwrst)(struct powerdomain *pwrdm); int (*pwrdm_read_pwrst)(struct powerdomain *pwrdm); @@ -173,6 +217,7 @@ int pwrdm_register_platform_funcs(struct pwrdm_ops *custom_funcs); int pwrdm_register_pwrdms(struct powerdomain **pwrdm_list); int pwrdm_complete_init(void);
+void pwrdm_create_register_dirs(struct powerdomain *p, struct dentry *pd_dentry); struct powerdomain *pwrdm_lookup(const char *name);
int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm, void *user), @@ -237,5 +282,4 @@ extern u32 omap2_pwrdm_get_mem_bank_stst_mask(u8 bank); extern struct powerdomain wkup_omap2_pwrdm; extern struct powerdomain gfx_omap2_pwrdm;
- #endif diff --git a/arch/arm/mach-omap2/powerdomain44xx.c b/arch/arm/mach-omap2/powerdomain44xx.c index a7880af..3d6d026 100644 --- a/arch/arm/mach-omap2/powerdomain44xx.c +++ b/arch/arm/mach-omap2/powerdomain44xx.c @@ -44,6 +44,28 @@ static int omap4_pwrdm_read_next_pwrst(struct powerdomain *pwrdm) return v; }
+static int omap4_pwrdm_read_reg_field(field_def_t *f) +{ + u32 v; + struct powerdomain *pwrdm; + register_def_t *reg; + + if ((reg = f->reg) == (register_def_t *)NULL) + return(0xdeadbeee); + + if ((pwrdm = reg->pwrdm) == (struct powerdomain *)NULL) + return(0xdeadbeef); + + v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, + pwrdm->prcm_offs, + reg->ix); + v &= f->mask; + v >>= f->shift; + return v; + + +} + static int omap4_pwrdm_read_pwrst(struct powerdomain *pwrdm) { u32 v; @@ -210,6 +232,7 @@ static int omap4_pwrdm_wait_transition(struct powerdomain *pwrdm) struct pwrdm_ops omap4_pwrdm_operations = { .pwrdm_set_next_pwrst = omap4_pwrdm_set_next_pwrst, .pwrdm_read_next_pwrst = omap4_pwrdm_read_next_pwrst, + .pwrdm_read_reg_field = omap4_pwrdm_read_reg_field, .pwrdm_read_pwrst = omap4_pwrdm_read_pwrst, .pwrdm_read_prev_pwrst = omap4_pwrdm_read_prev_pwrst, .pwrdm_set_lowpwrstchange = omap4_pwrdm_set_lowpwrstchange, diff --git a/arch/arm/mach-omap2/powerdomains44xx_data.c b/arch/arm/mach-omap2/powerdomains44xx_data.c index fbd4c5f..45d4a03 100644 --- a/arch/arm/mach-omap2/powerdomains44xx_data.c +++ b/arch/arm/mach-omap2/powerdomains44xx_data.c @@ -30,6 +30,83 @@ #include "prm44xx.h" #include "prcm_mpu44xx.h"
+#if CONFIG_PM_DEBUG + +char *pwrst_vals[] = {"off", "retention", "on-inactive", "on-active"}; +char *boolean_vals[] = {"false", "true"}; +char *statest_vals[] = {"off", "retention", "on-inactive", "on-active"}; +char *logicst_vals[] = {"off", "on"}; +char *logic_retst_vals[] = {"retention regigsters", "whole logic"}; + +DECODER(pwrst_vals); +DECODER(boolean_vals); +DECODER(statest_vals); +DECODER(logicst_vals); +DECODER(logic_retst_vals); + +field_def_t pwrst_fields[] = { + FIELD_ATTR("lastpowerstateentered", OMAP4430_LASTPOWERSTATEENTERED, decode_pwrst_vals), + FIELD_ATTR("intransition", OMAP4430_INTRANSITION, decode_boolean_vals), + FIELD_ATTR("ram_statest", OMAP4430_MPU_RAM_STATEST, decode_statest_vals), + FIELD_ATTR("l2_statest", OMAP4430_MPU_L2_STATEST, decode_statest_vals), + FIELD_ATTR("l1_statest", OMAP4430_MPU_L1_STATEST, decode_statest_vals), + FIELD_ATTR("logicstatest", OMAP4430_LOGICSTATEST, decode_logicst_vals), + FIELD_ATTR("powerstatest", OMAP_POWERSTATEST, decode_pwrst_vals), +}; + +field_def_t pwrstctl_fields[] = { + FIELD_ATTR("ram_onstate", OMAP4430_MPU_RAM_ONSTATE, decode_statest_vals), + FIELD_ATTR("l2_onstate", OMAP4430_MPU_L2_ONSTATE, decode_statest_vals), + FIELD_ATTR("l1_onstate", OMAP4430_MPU_L1_ONSTATE, decode_statest_vals), + FIELD_ATTR("ram_retstate", OMAP4430_MPU_RAM_RETSTATE, decode_statest_vals), + FIELD_ATTR("l2_retstate", OMAP4430_MPU_L2_RETSTATE, decode_statest_vals), + FIELD_ATTR("l1_retstate", OMAP4430_MPU_L1_RETSTATE, decode_statest_vals), + FIELD_ATTR("lowpowerstatechange", OMAP4430_LOWPOWERSTATECHANGE, decode_boolean_vals), + FIELD_ATTR("logicretstate", OMAP4430_LOGICRETSTATE, decode_logic_retst_vals), + FIELD_ATTR("powerstate", OMAP_POWERSTATE, decode_pwrst_vals), +}; + +field_def_t rstst_fields[] = { + + FIELD_ATTR("emulation_rst", OMAP4430_EMULATION_RST, decode_boolean_vals), +}; + +field_def_t ctx_fields[] = { + FIELD_ATTR("lostmem_ram", OMAP4430_LOSTMEM_MPU_RAM, decode_boolean_vals), + FIELD_ATTR("lostmem_l2", OMAP4430_LOSTMEM_MPU_L2, decode_boolean_vals), + FIELD_ATTR("lostmem_l1", OMAP4430_LOSTMEM_MPU_L1, decode_boolean_vals), + FIELD_ATTR("lostcontext_dff", OMAP4430_LOSTCONTEXT_DFF, decode_boolean_vals), +}; + + +register_def_t omap4_mpu_pwrst = {OMAP4_PM_PWSTST, + "pwrst", + pwrst_fields, + NUM_FIELDS(pwrst_fields)}; +register_def_t omap4_mpu_pwrstctl = {OMAP4_PM_PWSTCTRL, + "pwrstctl", + pwrstctl_fields, + NUM_FIELDS(pwrstctl_fields)}; +register_def_t omap4_mpu_rstst = {OMAP4_RM_RSTST, + "rstst", + rstst_fields, + NUM_FIELDS(rstst_fields)}; +register_def_t omap4_mpu_ctx = {OMAP4_RM_MPU_CONTEXT, + "context", + ctx_fields, + NUM_FIELDS(ctx_fields)}; + +register_def_t *omap4_mpu_regs[] = { + &omap4_mpu_pwrst, + &omap4_mpu_pwrstctl, + &omap4_mpu_rstst, + &omap4_mpu_ctx +}; + + +#endif // CONFIG_PM_DEBUG + + /* core_44xx_pwrdm: CORE power domain */ static struct powerdomain core_44xx_pwrdm = { .name = "core_pwrdm", @@ -218,6 +295,10 @@ static struct powerdomain mpu_443x_pwrdm = { [1] = PWRSTS_ON, /* mpu_l2 */ [2] = PWRSTS_ON, /* mpu_ram */ }, +#ifdef CONFIG_PM_DEBUG + .register_defs = omap4_mpu_regs, + .num_reg_defs = NUM_ELTS(omap4_mpu_regs,register_def_t *), +#endif };
static struct powerdomain mpu_446x_pwrdm = { @@ -236,6 +317,10 @@ static struct powerdomain mpu_446x_pwrdm = { [0] = PWRSTS_ON, /* mpu_l2 */ [1] = PWRSTS_ON, /* mpu_ram */ }, +#ifdef CONFIG_PM_DEBUG + .register_defs = omap4_mpu_regs, + .num_reg_defs = NUM_ELTS(omap4_mpu_regs,register_def_t *), +#endif };
/* ivahd_44xx_pwrdm: IVA-HD power domain */ diff --git a/arch/arm/mach-omap2/prm44xx.h b/arch/arm/mach-omap2/prm44xx.h index 3d66ccd..926257f 100644 --- a/arch/arm/mach-omap2/prm44xx.h +++ b/arch/arm/mach-omap2/prm44xx.h @@ -66,6 +66,7 @@ #define OMAP4_RM_RSTST 0x0008 #define OMAP4_PM_PWSTCTRL 0x0000 #define OMAP4_PM_PWSTST 0x0004 +#define OMAP4_RM_MPU_CONTEXT 0x0024
/* PRM */
Eric,
This looks interesting, but I'll add the linux-omap list to CC so someone can verify if there isn't already a patch to export this.
On Tue, May 15, 2012 at 2:57 AM, eric van tassell evttxl@gmail.com wrote:
- These changes make OMAP power state register fields available as
attributes per field in debugfs decoded as text with the hex value
- pwrdm_read_reg_field() might replace a lot of the explicit functions
for reading register fields and clean up the existing OMAP code a bit.
- the changes are usable via debugfs standalone or with the patch
coming for powerdebug
- I've only implemented the support for the MPU PD
- to support additional the other powerdomains all that's needed is to
add the register_def_t's and field_def_t's
Have you looked at other ARM platforms to see if they have similar information that could be exported using in the same way? It would be useful to export this information through a single interface to powerdebug like in the case of regulators and clocks.
here's a screenshot: ./powerdebug -P -d failed to initialize sensors
Power Domain Information:
mpu_pwrdm context lostcontext_dff 0:false lostmem_l1 0:false lostmem_l2 0:false lostmem_ram 0:false rstst emulation_rst 0:false pwrstctl powerstate 3:on-active logicretstate 1:whole lowpowerstatechange 0:false l1_retstate 1:retention l2_retstate 1:retention ram_retstate 1:retention l1_onstate 3:on-active l2_onstate 3:on-active ram_onstate 3:on-active pwrst powerstatest 3:on-active logicstatest 1:on l1_statest 3:on-active l2_statest 3:on-active ram_statest 3:on-active intransition 0:false lastpowerstateentered 3:on-active
and the patch against Linaro 12.04 kernel is:
From 4b762379805848eebd3454d6bb344a50012069d4 Mon Sep 17 00:00:00 2001 From: Eric van Tassell <evt@evtM17x.(none)> Date: Sat, 5 May 2012 15:05:48 -0500 Subject: [PATCH] + basic infrastructure for creating powerdomain attribute files in debugfs + definitions to create the attributes for mpu power domain
arch/arm/mach-omap2/pm-debug.c | 4 ++ arch/arm/mach-omap2/pm44xx.c | 3 +- arch/arm/mach-omap2/powerdomain.c | 89 +++++++++++++++++++++++++++ arch/arm/mach-omap2/powerdomain.h | 46 +++++++++++++- arch/arm/mach-omap2/powerdomain44xx.c | 23 +++++++ arch/arm/mach-omap2/powerdomains44xx_data.c | 85 +++++++++++++++++++++++++ arch/arm/mach-omap2/prm44xx.h | 1 + 8 files changed, 254 insertions(+), 2 deletions(-)
diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c index 4411163..2e365e3 100644 --- a/arch/arm/mach-omap2/pm-debug.c +++ b/arch/arm/mach-omap2/pm-debug.c @@ -224,6 +224,10 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *dir) (void) debugfs_create_file("suspend", S_IRUGO|S_IWUSR, d, (void *)pwrdm, &pwrdm_suspend_fops);
+#ifdef CONFIG_PM_DEBUG
- if (d)
- pwrdm_create_register_dirs(pwrdm, d);
+#endif // CONFIG_PM_DEBUG return 0; }
diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c index 4ab9b9d..f5c189e 100644 --- a/arch/arm/mach-omap2/pm44xx.c +++ b/arch/arm/mach-omap2/pm44xx.c @@ -155,7 +155,7 @@ static int __init clkdms_setup(struct clockdomain *clkdm, void *unused) }
-static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused) +static int __init pwrdms_setup(struct powerdomain *pwrdm, void *arg) { struct power_state *pwrst;
@@ -365,6 +365,7 @@ static int __init omap4_pm_init(void) OMAP44XX_IRQ_PRCM); goto err2; }
ret = pwrdm_for_each(pwrdms_setup, NULL); if (ret) { pr_err("Failed to setup powerdomains\n"); diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c index 8a18d1b..b392760 100644 --- a/arch/arm/mach-omap2/powerdomain.c +++ b/arch/arm/mach-omap2/powerdomain.c @@ -37,6 +37,11 @@
#define PWRDM_TRACE_STATES_FLAG (1<<31)
+#ifdef CONFIG_PM_DEBUG +#include "prm-regbits-44xx.h" +#include <linux/debugfs.h> +#endif // CONFIG_PM_DEBUG
enum { PWRDM_STATE_NOW = 0, PWRDM_STATE_PREV, @@ -201,6 +206,90 @@ static int _pwrdm_post_transition_cb(struct powerdomain *pwrdm, void *unused)
/* Public functions */
+#ifdef CONFIG_PM_DEBUG +///////////////////////////////////////////////////////////////////////////// +int pwrdm_read_reg_field(field_def_t *f) +{
- int ret = -EINVAL;
- if (!f )
- return -EINVAL;
- if (!(f->reg))
- return -EINVAL;
- if (!f->reg->pwrdm)
- return -EINVAL;
- if (arch_pwrdm && arch_pwrdm->pwrdm_read_reg_field)
- ret = arch_pwrdm->pwrdm_read_reg_field(f);
- return ret;
+}
+#define BUFMAX 4096 +static char scratch[BUFMAX];
+static ssize_t pwrdm_dbg_read(struct file *file, char __user *buf,
- size_t count, loff_t *ppos)
+{
- field_def_t *f = (field_def_t *)file->private_data;
- int n;
- int val;
- val = pwrdm_read_reg_field(f);
- memset(scratch, 0, BUFMAX);
- n = sprintf(scratch, "%d:%s", val, f->decoder(val));
- return simple_read_from_buffer(buf, count, ppos, scratch, n + 1);
+}
+static int pwrdm_dbg_open(struct inode *inode, struct file *file) +{
- file->private_data = inode->i_private;
- return 0;
+}
+static const struct file_operations pwrdm_dbg_ops = {
- .read = pwrdm_dbg_read,
- .open = pwrdm_dbg_open,
+}; +/////////////////////////////////////////////////////////////////////////////debug
+static void pwrdm_create_1register_dir(register_def_t *r, struct dentry *pd_dentry) +{
- struct dentry *reg_dentry;
- int i;
- reg_dentry = debugfs_create_dir(r->name, pd_dentry);
- for (i = 0; i < r->num_fields; i++) {
- field_def_t *f = &(r->fields[i]);
- f->reg = r; // link field to register
- debugfs_create_file(f->name,
- S_IRUGO,
- reg_dentry,
- (void *)&(r->fields[i]),
- &pwrdm_dbg_ops);
- }
+}
+void pwrdm_create_register_dirs(struct powerdomain *p, struct dentry *pd_dentry) +{
- int i;
- if ((p == (struct powerdomain *)NULL) || (pd_dentry == (struct dentry *)NULL))
- return;
- for (i = 0; i < p->num_reg_defs; i++) {
- p->register_defs[i]->pwrdm = p;
- pwrdm_create_1register_dir(p->register_defs[i], pd_dentry);
- }
+}
+#endif // CONFIG_PM_DEBUG
/** * pwrdm_register_platform_funcs - register powerdomain implementation fns * @po: func pointers for arch specific implementations diff --git a/arch/arm/mach-omap2/powerdomain.h b/arch/arm/mach-omap2/powerdomain.h index 0d72a8a..5eaf08c 100644 --- a/arch/arm/mach-omap2/powerdomain.h +++ b/arch/arm/mach-omap2/powerdomain.h @@ -76,6 +76,47 @@
struct clockdomain; struct powerdomain; +#ifdef CONFIG_PM_DEBUG +/* general PD decoder definitions */
+/* field definitions for PD_MPU */
+typedef struct {
- char *name;
- u32 shift;
- u32 mask;
- char * (*decoder)(u8); // note: decoder may be NULL
- struct _register_def_t_ *reg;
+} field_def_t;
+typedef struct _register_def_t_ {
- u32 ix;
- char *name;
- field_def_t *fields;
- u8 num_fields;
- struct powerdomain *pwrdm;
+} register_def_t;
+#define NUM_ELTS(whole, part) (sizeof(whole)/sizeof(part)) +#define NUM_FIELDS(whole) (sizeof(whole)/sizeof(field_def_t))
+#define DECODER(name) \
- char *decode_##name(u8 ix) { \
- if (ix > sizeof(name)/sizeof(char *)) \
- return "*invalid*"; \
- else \
- return name[ix]; \
+}
+#define FIELD_ATTR(name_str, base_name, funcp) \
- { \
- .name = name_str, \
- .shift = base_name ## _SHIFT , \
- .mask = base_name ## _MASK , \
- .decoder = funcp \
- }
+#endif //CONFIG_PM_DEBUG
/** * struct powerdomain - OMAP powerdomain @@ -124,6 +165,8 @@ struct powerdomain { #ifdef CONFIG_PM_DEBUG s64 timer; s64 state_timer[PWRDM_MAX_PWRSTS];
- register_def_t **register_defs;
- int num_reg_defs;
#endif };
@@ -149,6 +192,7 @@ struct powerdomain { * @pwrdm_wait_transition: Wait for a pd state transition to complete */ struct pwrdm_ops {
- int (*pwrdm_read_reg_field)(field_def_t *f);
int (*pwrdm_set_next_pwrst)(struct powerdomain *pwrdm, u8 pwrst); int (*pwrdm_read_next_pwrst)(struct powerdomain *pwrdm); int (*pwrdm_read_pwrst)(struct powerdomain *pwrdm); @@ -173,6 +217,7 @@ int pwrdm_register_platform_funcs(struct pwrdm_ops *custom_funcs); int pwrdm_register_pwrdms(struct powerdomain **pwrdm_list); int pwrdm_complete_init(void);
+void pwrdm_create_register_dirs(struct powerdomain *p, struct dentry *pd_dentry); struct powerdomain *pwrdm_lookup(const char *name);
int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm, void *user), @@ -237,5 +282,4 @@ extern u32 omap2_pwrdm_get_mem_bank_stst_mask(u8 bank); extern struct powerdomain wkup_omap2_pwrdm; extern struct powerdomain gfx_omap2_pwrdm;
#endif diff --git a/arch/arm/mach-omap2/powerdomain44xx.c b/arch/arm/mach-omap2/powerdomain44xx.c index a7880af..3d6d026 100644 --- a/arch/arm/mach-omap2/powerdomain44xx.c +++ b/arch/arm/mach-omap2/powerdomain44xx.c @@ -44,6 +44,28 @@ static int omap4_pwrdm_read_next_pwrst(struct powerdomain *pwrdm) return v; }
+static int omap4_pwrdm_read_reg_field(field_def_t *f) +{
- u32 v;
- struct powerdomain *pwrdm;
- register_def_t *reg;
- if ((reg = f->reg) == (register_def_t *)NULL)
- return(0xdeadbeee);
- if ((pwrdm = reg->pwrdm) == (struct powerdomain *)NULL)
- return(0xdeadbeef);
- v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition,
- pwrdm->prcm_offs,
- reg->ix);
- v &= f->mask;
- v >>= f->shift;
- return v;
+}
static int omap4_pwrdm_read_pwrst(struct powerdomain *pwrdm) { u32 v; @@ -210,6 +232,7 @@ static int omap4_pwrdm_wait_transition(struct powerdomain *pwrdm) struct pwrdm_ops omap4_pwrdm_operations = { .pwrdm_set_next_pwrst = omap4_pwrdm_set_next_pwrst, .pwrdm_read_next_pwrst = omap4_pwrdm_read_next_pwrst,
- .pwrdm_read_reg_field = omap4_pwrdm_read_reg_field,
.pwrdm_read_pwrst = omap4_pwrdm_read_pwrst, .pwrdm_read_prev_pwrst = omap4_pwrdm_read_prev_pwrst, .pwrdm_set_lowpwrstchange = omap4_pwrdm_set_lowpwrstchange, diff --git a/arch/arm/mach-omap2/powerdomains44xx_data.c b/arch/arm/mach-omap2/powerdomains44xx_data.c index fbd4c5f..45d4a03 100644 --- a/arch/arm/mach-omap2/powerdomains44xx_data.c +++ b/arch/arm/mach-omap2/powerdomains44xx_data.c @@ -30,6 +30,83 @@ #include "prm44xx.h" #include "prcm_mpu44xx.h"
+#if CONFIG_PM_DEBUG
+char *pwrst_vals[] = {"off", "retention", "on-inactive", "on-active"}; +char *boolean_vals[] = {"false", "true"}; +char *statest_vals[] = {"off", "retention", "on-inactive", "on-active"}; +char *logicst_vals[] = {"off", "on"}; +char *logic_retst_vals[] = {"retention regigsters", "whole logic"};
+DECODER(pwrst_vals); +DECODER(boolean_vals); +DECODER(statest_vals); +DECODER(logicst_vals); +DECODER(logic_retst_vals);
+field_def_t pwrst_fields[] = {
- FIELD_ATTR("lastpowerstateentered",
OMAP4430_LASTPOWERSTATEENTERED, decode_pwrst_vals),
- FIELD_ATTR("intransition", OMAP4430_INTRANSITION, decode_boolean_vals),
- FIELD_ATTR("ram_statest", OMAP4430_MPU_RAM_STATEST, decode_statest_vals),
- FIELD_ATTR("l2_statest", OMAP4430_MPU_L2_STATEST, decode_statest_vals),
- FIELD_ATTR("l1_statest", OMAP4430_MPU_L1_STATEST, decode_statest_vals),
- FIELD_ATTR("logicstatest", OMAP4430_LOGICSTATEST, decode_logicst_vals),
- FIELD_ATTR("powerstatest", OMAP_POWERSTATEST, decode_pwrst_vals),
+};
+field_def_t pwrstctl_fields[] = {
- FIELD_ATTR("ram_onstate", OMAP4430_MPU_RAM_ONSTATE,
decode_statest_vals),
- FIELD_ATTR("l2_onstate", OMAP4430_MPU_L2_ONSTATE,
decode_statest_vals),
- FIELD_ATTR("l1_onstate", OMAP4430_MPU_L1_ONSTATE,
decode_statest_vals),
- FIELD_ATTR("ram_retstate", OMAP4430_MPU_RAM_RETSTATE,
decode_statest_vals),
- FIELD_ATTR("l2_retstate", OMAP4430_MPU_L2_RETSTATE,
decode_statest_vals),
- FIELD_ATTR("l1_retstate", OMAP4430_MPU_L1_RETSTATE,
decode_statest_vals),
- FIELD_ATTR("lowpowerstatechange",
OMAP4430_LOWPOWERSTATECHANGE, decode_boolean_vals),
- FIELD_ATTR("logicretstate", OMAP4430_LOGICRETSTATE,
decode_logic_retst_vals),
- FIELD_ATTR("powerstate", OMAP_POWERSTATE, decode_pwrst_vals),
+};
+field_def_t rstst_fields[] = {
- FIELD_ATTR("emulation_rst", OMAP4430_EMULATION_RST,
decode_boolean_vals), +};
+field_def_t ctx_fields[] = {
- FIELD_ATTR("lostmem_ram", OMAP4430_LOSTMEM_MPU_RAM,
decode_boolean_vals),
- FIELD_ATTR("lostmem_l2", OMAP4430_LOSTMEM_MPU_L2,
decode_boolean_vals),
- FIELD_ATTR("lostmem_l1", OMAP4430_LOSTMEM_MPU_L1,
decode_boolean_vals),
- FIELD_ATTR("lostcontext_dff", OMAP4430_LOSTCONTEXT_DFF,
decode_boolean_vals), +};
+register_def_t omap4_mpu_pwrst = {OMAP4_PM_PWSTST,
- "pwrst",
- pwrst_fields,
- NUM_FIELDS(pwrst_fields)};
+register_def_t omap4_mpu_pwrstctl = {OMAP4_PM_PWSTCTRL,
- "pwrstctl",
- pwrstctl_fields,
- NUM_FIELDS(pwrstctl_fields)};
+register_def_t omap4_mpu_rstst = {OMAP4_RM_RSTST,
- "rstst",
- rstst_fields,
- NUM_FIELDS(rstst_fields)};
+register_def_t omap4_mpu_ctx = {OMAP4_RM_MPU_CONTEXT,
- "context",
- ctx_fields,
- NUM_FIELDS(ctx_fields)};
+register_def_t *omap4_mpu_regs[] = {
- &omap4_mpu_pwrst,
- &omap4_mpu_pwrstctl,
- &omap4_mpu_rstst,
- &omap4_mpu_ctx
+};
+#endif // CONFIG_PM_DEBUG
/* core_44xx_pwrdm: CORE power domain */ static struct powerdomain core_44xx_pwrdm = { .name = "core_pwrdm", @@ -218,6 +295,10 @@ static struct powerdomain mpu_443x_pwrdm = { [1] = PWRSTS_ON, /* mpu_l2 */ [2] = PWRSTS_ON, /* mpu_ram */ }, +#ifdef CONFIG_PM_DEBUG
- .register_defs = omap4_mpu_regs,
- .num_reg_defs = NUM_ELTS(omap4_mpu_regs,register_def_t *),
+#endif };
static struct powerdomain mpu_446x_pwrdm = { @@ -236,6 +317,10 @@ static struct powerdomain mpu_446x_pwrdm = { [0] = PWRSTS_ON, /* mpu_l2 */ [1] = PWRSTS_ON, /* mpu_ram */ }, +#ifdef CONFIG_PM_DEBUG
- .register_defs = omap4_mpu_regs,
- .num_reg_defs = NUM_ELTS(omap4_mpu_regs,register_def_t *),
+#endif };
/* ivahd_44xx_pwrdm: IVA-HD power domain */ diff --git a/arch/arm/mach-omap2/prm44xx.h b/arch/arm/mach-omap2/prm44xx.h index 3d66ccd..926257f 100644 --- a/arch/arm/mach-omap2/prm44xx.h +++ b/arch/arm/mach-omap2/prm44xx.h @@ -66,6 +66,7 @@ #define OMAP4_RM_RSTST 0x0008 #define OMAP4_PM_PWSTCTRL 0x0000 #define OMAP4_PM_PWSTST 0x0004 +#define OMAP4_RM_MPU_CONTEXT 0x0024
/* PRM */
1.7.9.5
--
- evt
(Eric van Tassell) twitter: evt_texelsoft linked-in: linkedin.com/in/evttxl
linaro-kernel mailing list linaro-kernel@lists.linaro.org http://lists.linaro.org/mailman/listinfo/linaro-kernel
Hi Amit, Eric,
Amit Kucheria amit.kucheria@linaro.org writes:
Eric,
This looks interesting, but I'll add the linux-omap list to CC so someone can verify if there isn't already a patch to export this.
We used to have similar PM debug code in the kernel, but as the one who maintained it, I decided to remove it. This kind of thing is obviously very SoC specific, and therefore a major pain to maintain in the kernel for all the SoCs we support in linux-omap.
In my view, this kind of raw register dump/analysis does not belong in the kernel, but rather in userspace tools.
What we have been moving towards is using tracepoints in the clock/clockdomain/powerdomain layers to track state transitions in all of these layers. By analyzing the trace you can similarily see the state of each of the clocks and powerdomains. We currently don't have all of the low-level details (like context loss, logic & mem state, etc.) but that is not difficult to add with some new tracepoints.
I removed the in-kernel register dumping in the hope that folks would start using userspace tools perf/ftrace to do the same.
Kevin
linaro-kernel@lists.linaro.org