[PATCHv3 03/20] ARM: OMAP4: PM: add support for device off

Jean Pihet jean.pihet at newoldbits.com
Wed Jun 13 11:21:45 EDT 2012


Hi Tero,

I have a few remarks regarding the genericity of this code. I think it
is better if the code in powerdomain.c stays generic and that the
platform specific checks and operations be moved in the specific
functions (via the pwrdm_ops struct).

On Tue, Jun 12, 2012 at 5:31 PM, Tero Kristo <t-kristo at ti.com> wrote:
> On OMAP4+, device wide off-mode has its own enable mechanism in addition
> to powerdomain target states. This patch adds support for this on top
> of functional power states by overloading the OFF state for core pwrdm.
> On pwrdm level, the deepest power state supported by core pwrdm is OSWR.
> When user (e.g. suspend) programs core pwrdm target as OFF, the functional
> power state for the domain will be OSWR with the additional device off
> enabled. Previous power state information will reflect this also.
>
> Signed-off-by: Tero Kristo <t-kristo at ti.com>
> ---
>  arch/arm/mach-omap2/powerdomain.c           |   17 +++++++++
>  arch/arm/mach-omap2/powerdomain.h           |   13 +++++++-
>  arch/arm/mach-omap2/powerdomain44xx.c       |   48 +++++++++++++++++++++++++++
>  arch/arm/mach-omap2/powerdomains44xx_data.c |    3 +-
>  4 files changed, 79 insertions(+), 2 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
> index ac63f86..78a9308 100644
> --- a/arch/arm/mach-omap2/powerdomain.c
> +++ b/arch/arm/mach-omap2/powerdomain.c
> @@ -677,6 +677,8 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 func_pwrst)
>        int sleep_switch = -1, ret = 0, hwsup = 0;
>        int new_func_pwrst, next_func_pwrst, pwrst, logic;
>        u8 curr_pwrst;
> +       bool extra_off_enable = false;
> +       bool has_extra_off = false;
>
>        if (!pwrdm || IS_ERR(pwrdm)) {
>                pr_debug("%s: invalid params: pwrdm=%p\n", __func__, pwrdm);
> @@ -687,6 +689,13 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 func_pwrst)
>
>        mutex_lock(&pwrdm->lock);
>
> +       /* Check if powerdomain has extra off mode handling */
> +       if (pwrdm->flags & PWRDM_HAS_EXTRA_OFF_ENABLE) {
> +               has_extra_off = true;
> +               if (func_pwrst == PWRDM_FUNC_PWRST_OFF)
> +                       extra_off_enable = true;
> +       }
Could those checks be moved in the OMAP4 specific functions, so that
the power domain code stays generic?

> +
>        new_func_pwrst = pwrdm_get_achievable_func_pwrst(pwrdm, func_pwrst);
>        pwrst = pwrdm_func_to_pwrst(pwrdm, new_func_pwrst);
>        logic = pwrdm_func_to_logic_pwrst(pwrdm, new_func_pwrst);
> @@ -741,6 +750,9 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 func_pwrst)
>                break;
>        }
>
> +       if (has_extra_off && arch_pwrdm->pwrdm_enable_off)
> +               arch_pwrdm->pwrdm_enable_off(pwrdm, extra_off_enable);
> +
>  out:
>        mutex_unlock(&pwrdm->lock);
>        return ret;
> @@ -810,6 +822,11 @@ int pwrdm_read_next_func_pwrst(struct powerdomain *pwrdm)
>        int next_pwrst = pwrdm_read_next_pwrst(pwrdm);
>        int next_logic = pwrdm_read_logic_retst(pwrdm);
>
> +       if (pwrdm->flags & PWRDM_HAS_EXTRA_OFF_ENABLE &&
> +           arch_pwrdm->pwrdm_read_next_off &&
> +           arch_pwrdm->pwrdm_read_next_off(pwrdm))
> +               return PWRDM_FUNC_PWRST_OFF;
> +
Same comment here. The OMAP4 specific function for
pwrdm_read_next_pwrst could return PWRDM_FUNC_PWRST_OFF.

>        return pwrdm_pwrst_to_func(pwrdm, next_pwrst, next_logic);
>  }
>
> diff --git a/arch/arm/mach-omap2/powerdomain.h b/arch/arm/mach-omap2/powerdomain.h
> index 0729d91..cc30b94 100644
> --- a/arch/arm/mach-omap2/powerdomain.h
> +++ b/arch/arm/mach-omap2/powerdomain.h
> @@ -75,6 +75,13 @@
>                                                  * state without waking up the
>                                                  * powerdomain
>                                                  */
> +/*
> + * OMAP4+ has device off feature, which must be enabled separately in
> + * addition to power domain next state setup. This feature is overloaded
> + * as EXTRA_OFF_ENABLE for core_pwrdm, and is implemented on top of
> + * functional power state
> + */
> +#define PWRDM_HAS_EXTRA_OFF_ENABLE     (1 << 3)
>
>  /*
>  * Number of memory banks that are power-controllable. On OMAP4430, the
> @@ -173,7 +180,9 @@ struct powerdomain {
>  * @pwrdm_disable_hdwr_sar: Disable Hardware Save-Restore feature for a pd
>  * @pwrdm_set_lowpwrstchange: Enable pd transitions from a shallow to deep sleep
>  * @pwrdm_wait_transition: Wait for a pd state transition to complete
> - * @pwrdm_lost_context_rff: Check if pd has lost RFF context (entered off)
> + * @pwrdm_lost_context_rff: Check if pd has lost RFF context (omap4+ device off)
> + * @pwrdm_enable_off: Extra off mode enable for pd (omap4+ device off)
> + * @pwrdm_read_next_off: Check if pd next state is off (omap4+ device off)
>  */
>  struct pwrdm_ops {
>        int     (*pwrdm_func_to_pwrst)(struct powerdomain *pwrdm, u8 func_pwrst);
> @@ -199,6 +208,8 @@ struct pwrdm_ops {
>        int     (*pwrdm_set_lowpwrstchange)(struct powerdomain *pwrdm);
>        int     (*pwrdm_wait_transition)(struct powerdomain *pwrdm);
>        bool    (*pwrdm_lost_context_rff)(struct powerdomain *pwrdm);
> +       void    (*pwrdm_enable_off)(struct powerdomain *pwrdm, bool enable);
> +       bool    (*pwrdm_read_next_off)(struct powerdomain *pwrdm);
>  };
>
>  int pwrdm_register_platform_funcs(struct pwrdm_ops *custom_funcs);
> diff --git a/arch/arm/mach-omap2/powerdomain44xx.c b/arch/arm/mach-omap2/powerdomain44xx.c
> index 562f78a..b2bdc0f 100644
> --- a/arch/arm/mach-omap2/powerdomain44xx.c
> +++ b/arch/arm/mach-omap2/powerdomain44xx.c
> @@ -358,6 +358,52 @@ bool omap4_pwrdm_lost_context_rff(struct powerdomain *pwrdm)
>        return false;
>  }
>
> +/**
> + * omap4_device_set_next_state_off - setup device off state
> + * @pwrdm: struct powerdomain * to target powerdomain
> + * @enable: true if off-mode should be enabled
> + *
> + * When Device OFF is enabled, Device is allowed to perform
> + * transition to off mode as soon as all power domains in MPU, IVA
> + * and CORE voltage are in OFF or OSWR state (open switch retention)
> + */
> +void omap4_device_set_next_state_off(struct powerdomain *pwrdm, bool enable)
> +{
> +       u8 val = enable ? 0x1 : 0x0;
> +
> +       if (!(pwrdm->flags & PWRDM_HAS_EXTRA_OFF_ENABLE))
> +               return;
> +
> +       omap4_prminst_write_inst_reg(val << OMAP4430_DEVICE_OFF_ENABLE_SHIFT,
> +                                    OMAP4430_PRM_PARTITION,
> +                                    OMAP4430_PRM_DEVICE_INST,
> +                                    OMAP4_PRM_DEVICE_OFF_CTRL_OFFSET);
> +}
> +
> +
> +/**
> + * omap4_device_read_next_state_off - read device off state
> + * @pwrdm: struct powerdomain * to target powerdomain
> + *
> + * Checks if device off is enabled or not.
> + * Returns true if enabled, false otherwise.
> + */
> +bool omap4_device_read_next_state_off(struct powerdomain *pwrdm)
> +{
> +       u32 val;
> +
> +       if (!(pwrdm->flags & PWRDM_HAS_EXTRA_OFF_ENABLE))
> +               return false;
> +
> +       val = omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION,
> +                                         OMAP4430_PRM_DEVICE_INST,
> +                                         OMAP4_PRM_DEVICE_OFF_CTRL_OFFSET);
> +
> +       val &= OMAP4430_DEVICE_OFF_ENABLE_MASK;
> +
> +       return val ? true : false;
> +}
> +
>  struct pwrdm_ops omap4_pwrdm_operations = {
>        .pwrdm_func_to_pwrst    = omap2_pwrdm_func_to_pwrst,
>        .pwrdm_func_to_logic_pwrst      = omap2_pwrdm_func_to_logic_pwrst,
> @@ -381,4 +427,6 @@ struct pwrdm_ops omap4_pwrdm_operations = {
>        .pwrdm_enable_hdwr_sar  = omap4_pwrdm_enable_hdwr_sar,
>        .pwrdm_disable_hdwr_sar = omap4_pwrdm_disable_hdwr_sar,
>        .pwrdm_lost_context_rff = omap4_pwrdm_lost_context_rff,
> +       .pwrdm_enable_off       = omap4_device_set_next_state_off,
> +       .pwrdm_read_next_off    = omap4_device_read_next_state_off,
>  };
> diff --git a/arch/arm/mach-omap2/powerdomains44xx_data.c b/arch/arm/mach-omap2/powerdomains44xx_data.c
> index c4de02f..13db876 100644
> --- a/arch/arm/mach-omap2/powerdomains44xx_data.c
> +++ b/arch/arm/mach-omap2/powerdomains44xx_data.c
> @@ -54,7 +54,8 @@ static struct powerdomain core_44xx_pwrdm = {
>                [3] = PWRSTS_ON,        /* ducati_l2ram */
>                [4] = PWRSTS_ON,        /* ducati_unicache */
>        },
> -       .flags            = PWRDM_HAS_LOWPOWERSTATECHANGE,
> +       .flags            = PWRDM_HAS_LOWPOWERSTATECHANGE |
> +                           PWRDM_HAS_EXTRA_OFF_ENABLE,
>  };
>
>  /* gfx_44xx_pwrdm: 3D accelerator power domain */

Regards,
Jean

> --
> 1.7.4.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html



More information about the linux-arm-kernel mailing list