RE: [PATCHv3 1/6] OMAP: Powerdomains: Add support for INACTIVE state on pwrdm level
Hi Paul, Thanks for comments, my responses inline below. >-Original Message- >From: ext Paul Walmsley [mailto:p...@pwsan.com] >Sent: 21 January, 2010 06:35 >To: Kristo Tero (Nokia-D/Tampere) >Cc: linux-omap@vger.kernel.org; khil...@deeprootsystems.com >Subject: Re: [PATCHv3 1/6] OMAP: Powerdomains: Add support for >INACTIVE state on pwrdm level > >Hi Tero, > >I regret the delay in reviewing. I haven't kept up on the comments on >this thread, so if I've asked a question that you've already answered, >please feel free to point me to the response. > >A few comments/questions: > >On Fri, 15 Jan 2010, Tero Kristo wrote: > >> From: Tero Kristo >> >> Currently only ON, RET and OFF are supported, and ON is >arguably broken as it >> allows the powerdomain to enter INACTIVE state unless idle >is prevented. >> Now, pwrdm code prevents idle if ON is selected, and also >adds support for >> INACTIVE. This simplifies the control needed inside sleep code. >> >> This patch also requires caching of next power state inside >powerdomain code, >> as INACTIVE is not directly supported by hardware. > >The idea seems like a good one, and a simplification for the >PM code. I'm >a little worried that this patch mixes hardware-programmable >powerdomain >states with logical powerdomain states. I wonder if we would >be better >off separating, for example, the logic of putting a powerdomain into >INACTIVE state and any other logical powerdomain management, from the >physical details of how the chip is programmed. Just looking for your >comments on this, not necessarily any changes in your patches in this >regard. > >> Next powerstate is thus now stored for each powerdomain in >next_state. >> >> Signed-off-by: Tero Kristo >> --- >> arch/arm/mach-omap2/powerdomain.c | 32 > >> arch/arm/mach-omap2/powerdomains34xx.h| 26 >++-- >> arch/arm/plat-omap/include/plat/powerdomain.h |4 +++ >> 3 files changed, 43 insertions(+), 19 deletions(-) >> >> diff --git a/arch/arm/mach-omap2/powerdomain.c >b/arch/arm/mach-omap2/powerdomain.c >> index 26b3f3e..a08d596 100644 >> --- a/arch/arm/mach-omap2/powerdomain.c >> +++ b/arch/arm/mach-omap2/powerdomain.c >> @@ -110,8 +110,8 @@ static struct powerdomain >*_pwrdm_deps_lookup(struct powerdomain *pwrdm, >> static int _pwrdm_state_switch(struct powerdomain *pwrdm, int flag) >> { >> >> -int prev; >> -int state; >> +u8 prev; >> +u8 state; >> >> if (pwrdm == NULL) >> return -EINVAL; >> @@ -218,7 +218,9 @@ int pwrdm_register(struct powerdomain *pwrdm) >> >> pr_debug("powerdomain: registered %s\n", pwrdm->name); >> ret = 0; >> - >> +pwrdm->next_state = >> +prm_read_mod_bits_shift(pwrdm->prcm_offs, PM_PWSTCTRL, >> +OMAP_POWERSTATE_MASK); >> pr_unlock: >> write_unlock_irqrestore(&pwrdm_rwlock, flags); >> >> @@ -699,19 +701,38 @@ int pwrdm_get_mem_bank_count(struct >powerdomain *pwrdm) >> */ >> int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst) >> { >> +u8 prg_pwrst; >> + >> if (!pwrdm) >> return -EINVAL; >> >> +if (pwrdm->next_state == pwrst) >> +return 0; >> + >> if (!(pwrdm->pwrsts & (1 << pwrst))) >> return -EINVAL; >> >> pr_debug("powerdomain: setting next powerstate for %s to %0x\n", >> pwrdm->name, pwrst); >> >> +/* INACTIVE is reserved, so we program pwrdm as ON */ >> +if (pwrst == PWRDM_POWER_INACTIVE) >> +prg_pwrst = PWRDM_POWER_ON; >> +else >> +prg_pwrst = pwrst; >> + >> prm_rmw_mod_reg_bits(OMAP_POWERSTATE_MASK, >> - (pwrst << OMAP_POWERSTATE_SHIFT), >> + (prg_pwrst << OMAP_POWERSTATE_SHIFT), >> pwrdm->prcm_offs, PM_PWSTCTRL); >> >> +/* If next state is ON, prevent idle */ >> +if (pwrst == PWRDM_POWER_ON) >> +omap2_clkdm_deny_idle(pwrdm->pwrdm_clkdms[0]); >> +else >> +omap2_clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]); > >Looks like this will force clockdomains into hardware-supervised mode, >even if they were originally programmed into software-supervised mode. >Please f
Re: [PATCHv3 1/6] OMAP: Powerdomains: Add support for INACTIVE state on pwrdm level
Hi Tero, I regret the delay in reviewing. I haven't kept up on the comments on this thread, so if I've asked a question that you've already answered, please feel free to point me to the response. A few comments/questions: On Fri, 15 Jan 2010, Tero Kristo wrote: > From: Tero Kristo > > Currently only ON, RET and OFF are supported, and ON is arguably broken as it > allows the powerdomain to enter INACTIVE state unless idle is prevented. > Now, pwrdm code prevents idle if ON is selected, and also adds support for > INACTIVE. This simplifies the control needed inside sleep code. > > This patch also requires caching of next power state inside powerdomain code, > as INACTIVE is not directly supported by hardware. The idea seems like a good one, and a simplification for the PM code. I'm a little worried that this patch mixes hardware-programmable powerdomain states with logical powerdomain states. I wonder if we would be better off separating, for example, the logic of putting a powerdomain into INACTIVE state and any other logical powerdomain management, from the physical details of how the chip is programmed. Just looking for your comments on this, not necessarily any changes in your patches in this regard. > Next powerstate is thus now stored for each powerdomain in next_state. > > Signed-off-by: Tero Kristo > --- > arch/arm/mach-omap2/powerdomain.c | 32 > arch/arm/mach-omap2/powerdomains34xx.h| 26 ++-- > arch/arm/plat-omap/include/plat/powerdomain.h |4 +++ > 3 files changed, 43 insertions(+), 19 deletions(-) > > diff --git a/arch/arm/mach-omap2/powerdomain.c > b/arch/arm/mach-omap2/powerdomain.c > index 26b3f3e..a08d596 100644 > --- a/arch/arm/mach-omap2/powerdomain.c > +++ b/arch/arm/mach-omap2/powerdomain.c > @@ -110,8 +110,8 @@ static struct powerdomain *_pwrdm_deps_lookup(struct > powerdomain *pwrdm, > static int _pwrdm_state_switch(struct powerdomain *pwrdm, int flag) > { > > - int prev; > - int state; > + u8 prev; > + u8 state; > > if (pwrdm == NULL) > return -EINVAL; > @@ -218,7 +218,9 @@ int pwrdm_register(struct powerdomain *pwrdm) > > pr_debug("powerdomain: registered %s\n", pwrdm->name); > ret = 0; > - > + pwrdm->next_state = > + prm_read_mod_bits_shift(pwrdm->prcm_offs, PM_PWSTCTRL, > + OMAP_POWERSTATE_MASK); > pr_unlock: > write_unlock_irqrestore(&pwrdm_rwlock, flags); > > @@ -699,19 +701,38 @@ int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm) > */ > int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst) > { > + u8 prg_pwrst; > + > if (!pwrdm) > return -EINVAL; > > + if (pwrdm->next_state == pwrst) > + return 0; > + > if (!(pwrdm->pwrsts & (1 << pwrst))) > return -EINVAL; > > pr_debug("powerdomain: setting next powerstate for %s to %0x\n", >pwrdm->name, pwrst); > > + /* INACTIVE is reserved, so we program pwrdm as ON */ > + if (pwrst == PWRDM_POWER_INACTIVE) > + prg_pwrst = PWRDM_POWER_ON; > + else > + prg_pwrst = pwrst; > + > prm_rmw_mod_reg_bits(OMAP_POWERSTATE_MASK, > - (pwrst << OMAP_POWERSTATE_SHIFT), > + (prg_pwrst << OMAP_POWERSTATE_SHIFT), >pwrdm->prcm_offs, PM_PWSTCTRL); > > + /* If next state is ON, prevent idle */ > + if (pwrst == PWRDM_POWER_ON) > + omap2_clkdm_deny_idle(pwrdm->pwrdm_clkdms[0]); > + else > + omap2_clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]); Looks like this will force clockdomains into hardware-supervised mode, even if they were originally programmed into software-supervised mode. Please fix this so clockdomains that were originally programmed into software-supervised mode aren't inadvertently switched. > + > + pwrdm->next_state = pwrst; > + > return 0; > } > > @@ -728,8 +749,7 @@ int pwrdm_read_next_pwrst(struct powerdomain *pwrdm) > if (!pwrdm) > return -EINVAL; > > - return prm_read_mod_bits_shift(pwrdm->prcm_offs, PM_PWSTCTRL, > - OMAP_POWERSTATE_MASK); > + return pwrdm->next_state; > } > > /** > diff --git a/arch/arm/mach-omap2/powerdomains34xx.h > b/arch/arm/mach-omap2/powerdomains34xx.h > index 588f7e0..f50a3f2 100644 > --- a/arch/arm/mach-omap2/powerdomains34xx.h > +++ b/arch/arm/mach-omap2/powerdomains34xx.h > @@ -165,7 +165,7 @@ static struct powerdomain iva2_pwrdm = { > .omap_chip= OMAP_CHIP_INIT(CHIP_IS_OMAP3430), > .dep_bit = OMAP3430_PM_WKDEP_MPU_EN_IVA2_SHIFT, > .wkdep_srcs = iva2_wkdeps, > - .pwrsts = PWRSTS_OFF_RET_ON, > + .pwrsts = PWRSTS_OFF_RET_INA_ON, > .pwrsts_logic_ret = PWRSTS_OFF_RET, > .banks= 4, > .pwrsts_
[PATCHv3 1/6] OMAP: Powerdomains: Add support for INACTIVE state on pwrdm level
From: Tero Kristo Currently only ON, RET and OFF are supported, and ON is arguably broken as it allows the powerdomain to enter INACTIVE state unless idle is prevented. Now, pwrdm code prevents idle if ON is selected, and also adds support for INACTIVE. This simplifies the control needed inside sleep code. This patch also requires caching of next power state inside powerdomain code, as INACTIVE is not directly supported by hardware. Next powerstate is thus now stored for each powerdomain in next_state. Signed-off-by: Tero Kristo --- arch/arm/mach-omap2/powerdomain.c | 32 arch/arm/mach-omap2/powerdomains34xx.h| 26 ++-- arch/arm/plat-omap/include/plat/powerdomain.h |4 +++ 3 files changed, 43 insertions(+), 19 deletions(-) diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c index 26b3f3e..a08d596 100644 --- a/arch/arm/mach-omap2/powerdomain.c +++ b/arch/arm/mach-omap2/powerdomain.c @@ -110,8 +110,8 @@ static struct powerdomain *_pwrdm_deps_lookup(struct powerdomain *pwrdm, static int _pwrdm_state_switch(struct powerdomain *pwrdm, int flag) { - int prev; - int state; + u8 prev; + u8 state; if (pwrdm == NULL) return -EINVAL; @@ -218,7 +218,9 @@ int pwrdm_register(struct powerdomain *pwrdm) pr_debug("powerdomain: registered %s\n", pwrdm->name); ret = 0; - + pwrdm->next_state = + prm_read_mod_bits_shift(pwrdm->prcm_offs, PM_PWSTCTRL, + OMAP_POWERSTATE_MASK); pr_unlock: write_unlock_irqrestore(&pwrdm_rwlock, flags); @@ -699,19 +701,38 @@ int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm) */ int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst) { + u8 prg_pwrst; + if (!pwrdm) return -EINVAL; + if (pwrdm->next_state == pwrst) + return 0; + if (!(pwrdm->pwrsts & (1 << pwrst))) return -EINVAL; pr_debug("powerdomain: setting next powerstate for %s to %0x\n", pwrdm->name, pwrst); + /* INACTIVE is reserved, so we program pwrdm as ON */ + if (pwrst == PWRDM_POWER_INACTIVE) + prg_pwrst = PWRDM_POWER_ON; + else + prg_pwrst = pwrst; + prm_rmw_mod_reg_bits(OMAP_POWERSTATE_MASK, -(pwrst << OMAP_POWERSTATE_SHIFT), +(prg_pwrst << OMAP_POWERSTATE_SHIFT), pwrdm->prcm_offs, PM_PWSTCTRL); + /* If next state is ON, prevent idle */ + if (pwrst == PWRDM_POWER_ON) + omap2_clkdm_deny_idle(pwrdm->pwrdm_clkdms[0]); + else + omap2_clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]); + + pwrdm->next_state = pwrst; + return 0; } @@ -728,8 +749,7 @@ int pwrdm_read_next_pwrst(struct powerdomain *pwrdm) if (!pwrdm) return -EINVAL; - return prm_read_mod_bits_shift(pwrdm->prcm_offs, PM_PWSTCTRL, - OMAP_POWERSTATE_MASK); + return pwrdm->next_state; } /** diff --git a/arch/arm/mach-omap2/powerdomains34xx.h b/arch/arm/mach-omap2/powerdomains34xx.h index 588f7e0..f50a3f2 100644 --- a/arch/arm/mach-omap2/powerdomains34xx.h +++ b/arch/arm/mach-omap2/powerdomains34xx.h @@ -165,7 +165,7 @@ static struct powerdomain iva2_pwrdm = { .omap_chip= OMAP_CHIP_INIT(CHIP_IS_OMAP3430), .dep_bit = OMAP3430_PM_WKDEP_MPU_EN_IVA2_SHIFT, .wkdep_srcs = iva2_wkdeps, - .pwrsts = PWRSTS_OFF_RET_ON, + .pwrsts = PWRSTS_OFF_RET_INA_ON, .pwrsts_logic_ret = PWRSTS_OFF_RET, .banks= 4, .pwrsts_mem_ret = { @@ -188,7 +188,7 @@ static struct powerdomain mpu_34xx_pwrdm = { .omap_chip= OMAP_CHIP_INIT(CHIP_IS_OMAP3430), .dep_bit = OMAP3430_EN_MPU_SHIFT, .wkdep_srcs = mpu_34xx_wkdeps, - .pwrsts = PWRSTS_OFF_RET_ON, + .pwrsts = PWRSTS_OFF_RET_INA_ON, .pwrsts_logic_ret = PWRSTS_OFF_RET, .flags= PWRDM_HAS_MPU_QUIRK, .banks= 1, @@ -207,7 +207,7 @@ static struct powerdomain core_34xx_pre_es3_1_pwrdm = { .omap_chip= OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1 | CHIP_IS_OMAP3430ES2 | CHIP_IS_OMAP3430ES3_0), - .pwrsts = PWRSTS_OFF_RET_ON, + .pwrsts = PWRSTS_OFF_RET_INA_ON, .dep_bit = OMAP3430_EN_CORE_SHIFT, .banks= 2, .pwrsts_mem_ret = { @@ -215,8 +215,8 @@ static struct powerdomain core_34xx_pre_es3_1_pwrdm = { [1] = PWRSTS_OFF_RET,/* MEM2RETSTATE */ }, .pwrsts_mem_on= { - [0] = PWRSTS_OFF_RET_ON, /* MEM1ONSTATE *