Re: PATCH: add small infrastructure and definitions to export debugfs files for OMAP powerdomain attributes

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

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@xxxxxxxxx> 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@xxxxxxxxxxxxxxxx
> http://lists.linaro.org/mailman/listinfo/linaro-kernel
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Linux Arm (vger)]     [ARM Kernel]     [ARM MSM]     [Linux Tegra]     [Maemo Users]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Photo]     [Yosemite News]    [Yosemite Photos]    [Free Online Dating]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux