RE: [PATCHv2 5/6] OMAP: Powerdomains: Add support for checking if pwrdm/clkdm can idle
-Original Message- From: linux-omap-ow...@vger.kernel.org [mailto:linux-omap-ow...@vger.kernel.org] On Behalf Of ext Kevin Hilman Sent: 12 January, 2010 20:57 To: Kristo Tero (Nokia-D/Tampere) Cc: linux-omap@vger.kernel.org Subject: Re: [PATCHv2 5/6] OMAP: Powerdomains: Add support for checking if pwrdm/clkdm can idle Tero Kristo tero.kri...@nokia.com writes: From: Tero Kristo tero.kri...@nokia.com pwrdm_can_idle(pwrdm) will check if the specified powerdomain can enter idle. This is done by checking all clockdomains under the powerdomain if they can idle also. omap2_clkdm_can_idle(clkdm) will check if the specified clockdomain can enter idle. This checks the functional clock status in the clockdomain. These calls can be used e.g. inside cpuidle to decide which power states core and mpu should enter during idle, as there are certain dependencies between wakeup capabilities and reset logic. Signed-off-by: Tero Kristo tero.kri...@nokia.com This looks good by me, but needs a review from Paul to go upstream with the rest of his clockdomain/powerdomain updates for 2.6.34. One question... I'm wondering if it might be good to also check the CM_IDLEST_pwrdm register in the can_idle function. Even if all clocks are disabled, if the idle modes of the module are not set correctly, it may not enter the target state. Hmm I guess you are right here. I think at least one case would be secure devices which do not have FCLK control on the non-secure kernel, but their IDLEST would indeed block state transition. I'll investigate this a bit and update the patch. Kevin --- arch/arm/mach-omap2/clockdomain.c | 24 arch/arm/mach-omap2/clockdomains.h| 14 ++ arch/arm/mach-omap2/powerdomain.c | 25 + arch/arm/plat-omap/include/plat/clockdomain.h | 12 arch/arm/plat-omap/include/plat/powerdomain.h |1 + 5 files changed, 76 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c index fcd8232..9ddeb96 100644 --- a/arch/arm/mach-omap2/clockdomain.c +++ b/arch/arm/mach-omap2/clockdomain.c @@ -474,6 +474,30 @@ int omap2_clkdm_wakeup(struct clockdomain *clkdm) return 0; } + +/** + * omap2_clkdm_can_idle - check if clockdomain has any active clocks or not + * @clkdm: struct clockdomain * + * + * Checks if the clockdomain has any active clock or not, i.e. whether it + * can enter idle. Returns -EINVAL if clkdm is NULL; 0 if unable to idle; + * 1 if can idle. + */ +int omap2_clkdm_can_idle(struct clockdomain *clkdm) +{ +int i; +const int fclk_regs[] = { CM_FCLKEN, OMAP3430ES2_CM_FCLKEN3 }; + +if (!clkdm) +return -EINVAL; + +for (i = 0; i clkdm-fclk_reg_amt; i++) +if (cm_read_mod_reg(clkdm-pwrdm.ptr-prcm_offs, +fclk_regs[i]) ~clkdm-fclk_masks[i]) +return 0; +return 1; +} + /** * omap2_clkdm_allow_idle - enable hwsup idle transitions for clkdm * @clkdm: struct clockdomain * diff --git a/arch/arm/mach-omap2/clockdomains.h b/arch/arm/mach-omap2/clockdomains.h index c4ee076..2cde82a 100644 --- a/arch/arm/mach-omap2/clockdomains.h +++ b/arch/arm/mach-omap2/clockdomains.h @@ -167,6 +167,7 @@ static struct clockdomain iva2_clkdm = { .flags = CLKDM_CAN_HWSUP_SWSUP, .clktrctrl_mask = OMAP3430_CLKTRCTRL_IVA2_MASK, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), +.fclk_reg_amt = 1, }; static struct clockdomain gfx_3430es1_clkdm = { @@ -183,6 +184,7 @@ static struct clockdomain sgx_clkdm = { .flags = CLKDM_CAN_HWSUP_SWSUP, .clktrctrl_mask = OMAP3430ES2_CLKTRCTRL_SGX_MASK, .omap_chip = OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2), +.fclk_reg_amt = 1, }; /* @@ -206,6 +208,11 @@ static struct clockdomain core_l3_34xx_clkdm = { .flags = CLKDM_CAN_HWSUP, .clktrctrl_mask = OMAP3430_CLKTRCTRL_L3_MASK, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), +.fclk_reg_amt = 2, +.fclk_masks = { +[0] = OMAP3430_EN_UART2 | OMAP3430_EN_UART1, +[1] = 0, +}, }; static struct clockdomain core_l4_34xx_clkdm = { @@ -222,6 +229,7 @@ static struct clockdomain dss_34xx_clkdm = { .flags = CLKDM_CAN_HWSUP_SWSUP, .clktrctrl_mask = OMAP3430_CLKTRCTRL_DSS_MASK, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), +.fclk_reg_amt = 1, }; static struct clockdomain cam_clkdm = { @@ -230,6 +238,7 @@ static struct clockdomain cam_clkdm = { .flags = CLKDM_CAN_HWSUP_SWSUP, .clktrctrl_mask = OMAP3430_CLKTRCTRL_CAM_MASK, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), +.fclk_reg_amt = 1, }; static struct clockdomain usbhost_clkdm = { @@ -238,6 +247,7
Re: [PATCHv2 5/6] OMAP: Powerdomains: Add support for checking if pwrdm/clkdm can idle
Tero Kristo tero.kri...@nokia.com writes: From: Tero Kristo tero.kri...@nokia.com pwrdm_can_idle(pwrdm) will check if the specified powerdomain can enter idle. This is done by checking all clockdomains under the powerdomain if they can idle also. omap2_clkdm_can_idle(clkdm) will check if the specified clockdomain can enter idle. This checks the functional clock status in the clockdomain. These calls can be used e.g. inside cpuidle to decide which power states core and mpu should enter during idle, as there are certain dependencies between wakeup capabilities and reset logic. Signed-off-by: Tero Kristo tero.kri...@nokia.com This looks good by me, but needs a review from Paul to go upstream with the rest of his clockdomain/powerdomain updates for 2.6.34. One question... I'm wondering if it might be good to also check the CM_IDLEST_pwrdm register in the can_idle function. Even if all clocks are disabled, if the idle modes of the module are not set correctly, it may not enter the target state. Kevin --- arch/arm/mach-omap2/clockdomain.c | 24 arch/arm/mach-omap2/clockdomains.h| 14 ++ arch/arm/mach-omap2/powerdomain.c | 25 + arch/arm/plat-omap/include/plat/clockdomain.h | 12 arch/arm/plat-omap/include/plat/powerdomain.h |1 + 5 files changed, 76 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c index fcd8232..9ddeb96 100644 --- a/arch/arm/mach-omap2/clockdomain.c +++ b/arch/arm/mach-omap2/clockdomain.c @@ -474,6 +474,30 @@ int omap2_clkdm_wakeup(struct clockdomain *clkdm) return 0; } + +/** + * omap2_clkdm_can_idle - check if clockdomain has any active clocks or not + * @clkdm: struct clockdomain * + * + * Checks if the clockdomain has any active clock or not, i.e. whether it + * can enter idle. Returns -EINVAL if clkdm is NULL; 0 if unable to idle; + * 1 if can idle. + */ +int omap2_clkdm_can_idle(struct clockdomain *clkdm) +{ + int i; + const int fclk_regs[] = { CM_FCLKEN, OMAP3430ES2_CM_FCLKEN3 }; + + if (!clkdm) + return -EINVAL; + + for (i = 0; i clkdm-fclk_reg_amt; i++) + if (cm_read_mod_reg(clkdm-pwrdm.ptr-prcm_offs, + fclk_regs[i]) ~clkdm-fclk_masks[i]) + return 0; + return 1; +} + /** * omap2_clkdm_allow_idle - enable hwsup idle transitions for clkdm * @clkdm: struct clockdomain * diff --git a/arch/arm/mach-omap2/clockdomains.h b/arch/arm/mach-omap2/clockdomains.h index c4ee076..2cde82a 100644 --- a/arch/arm/mach-omap2/clockdomains.h +++ b/arch/arm/mach-omap2/clockdomains.h @@ -167,6 +167,7 @@ static struct clockdomain iva2_clkdm = { .flags = CLKDM_CAN_HWSUP_SWSUP, .clktrctrl_mask = OMAP3430_CLKTRCTRL_IVA2_MASK, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), + .fclk_reg_amt = 1, }; static struct clockdomain gfx_3430es1_clkdm = { @@ -183,6 +184,7 @@ static struct clockdomain sgx_clkdm = { .flags = CLKDM_CAN_HWSUP_SWSUP, .clktrctrl_mask = OMAP3430ES2_CLKTRCTRL_SGX_MASK, .omap_chip = OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2), + .fclk_reg_amt = 1, }; /* @@ -206,6 +208,11 @@ static struct clockdomain core_l3_34xx_clkdm = { .flags = CLKDM_CAN_HWSUP, .clktrctrl_mask = OMAP3430_CLKTRCTRL_L3_MASK, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), + .fclk_reg_amt = 2, + .fclk_masks = { + [0] = OMAP3430_EN_UART2 | OMAP3430_EN_UART1, + [1] = 0, + }, }; static struct clockdomain core_l4_34xx_clkdm = { @@ -222,6 +229,7 @@ static struct clockdomain dss_34xx_clkdm = { .flags = CLKDM_CAN_HWSUP_SWSUP, .clktrctrl_mask = OMAP3430_CLKTRCTRL_DSS_MASK, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), + .fclk_reg_amt = 1, }; static struct clockdomain cam_clkdm = { @@ -230,6 +238,7 @@ static struct clockdomain cam_clkdm = { .flags = CLKDM_CAN_HWSUP_SWSUP, .clktrctrl_mask = OMAP3430_CLKTRCTRL_CAM_MASK, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), + .fclk_reg_amt = 1, }; static struct clockdomain usbhost_clkdm = { @@ -238,6 +247,7 @@ static struct clockdomain usbhost_clkdm = { .flags = CLKDM_CAN_HWSUP_SWSUP, .clktrctrl_mask = OMAP3430ES2_CLKTRCTRL_USBHOST_MASK, .omap_chip = OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2), + .fclk_reg_amt = 1, }; static struct clockdomain per_clkdm = { @@ -246,6 +256,10 @@ static struct clockdomain per_clkdm = { .flags = CLKDM_CAN_HWSUP_SWSUP, .clktrctrl_mask = OMAP3430_CLKTRCTRL_PER_MASK, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), + .fclk_reg_amt = 1, +