RE: [PATCHv2 5/6] OMAP: Powerdomains: Add support for checking if pwrdm/clkdm can idle

2010-01-13 Thread Tero.Kristo
 

>-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  writes:
>
>> From: Tero Kristo 
>>
>> 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 
>
>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_ 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,
>> +

Re: [PATCHv2 5/6] OMAP: Powerdomains: Add support for checking if pwrdm/clkdm can idle

2010-01-12 Thread Kevin Hilman
Tero Kristo  writes:

> From: Tero Kristo 
>
> 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 

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_ 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

[PATCHv2 5/6] OMAP: Powerdomains: Add support for checking if pwrdm/clkdm can idle

2009-12-04 Thread Tero Kristo
From: Tero Kristo 

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 
---
 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,
+   .fclk_masks = {
+   [0] = OMAP3430_EN_UART3,
+   },
 };
 
 /*
diff --git a/arch/arm/mach-omap2/powerdomain.c 
b/arch/arm/mach-omap2/powerdomain.c
index 1237717..2bef099 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -1217,6 +1217,31 @@ int pwrdm_wait_transition(struct powerdomain *pwrdm)
return 0;
 }
 
+/**
+ * pwrdm_can_idle - check if the powerdomain can enter idle
+ * @pwrdm: struct powerdomain * the powerdomain to check status o