Re: [PATCHv4 4/8] ARM: OMAP3: add manual control for mpu / core pwrdm usecounting

2012-08-06 Thread Jean Pihet
Hi Tero,

On Mon, Jul 30, 2012 at 10:40 AM, Tero Kristo t-kri...@ti.com wrote:
 On Fri, 2012-07-27 at 12:36 -0700, Kevin Hilman wrote:
 Tero Kristo t-kri...@ti.com writes:

  mpu / core powerdomain usecounts are now statically increased
  by 1 during MPU activity. This allows the domains to reflect
  actual usage, and will allow the usecount to reach 0 just before
  all CPUs are ready to idle. Proper powerdomain usecounts are
  propageted to voltagedomain level also, and will allow vc
  callbacks to be triggered at right point of time.
 
  Signed-off-by: Tero Kristo t-kri...@ti.com
  Cc: Paul Walmsley p...@pwsan.com
  Cc: Kevin Hilman khil...@ti.com

 IMO, the idea is fine, but I'm not crazy about the implementation in
 powerdomain.c, which is meant for pwrdm generic code.   In particular,
 I'm not crazy about the pwrdm lookups in powerdomain.c.

 Since pmsoc.c already has references to mpu_pwrdm and core_pwrdm, why
 not just add the pwrdm_clkdm_enable/disable calls directly in pmsoc.c

 I think this was how the patch was in some earlier rev but I thought I'd
 try to be more clever with this. :) I can revert the implementation back
 to this.
Furthermore after the changes in pre/post transitions [1], some more
checks will be needed to identify the transitions on the mpu and core
power domains.

[1] 
http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=commitdiff;h=e055548953355b6e69c56f9e54388845b29b4e97

Regards,
Jean


 Also, the changelog should be a bit more specific about why CORE
 powerdomain is also handled here when most of the code only talks about
 the CPU.

 Yea, I'll add some beef to this also.

 -Tero

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


Re: [PATCHv7 06/12] ARM: OMAP4: suspend: Program all domains to retention

2012-08-06 Thread Jean Pihet
Hi!

On Thu, Jul 19, 2012 at 4:16 PM, Sergei Shtylyov sshtyl...@mvista.com wrote:
 Hello.

 On 07/19/2012 05:26 PM, Tero Kristo wrote:

 From: Rajendra Nayak rna...@ti.com

 Remove the FIXME's in the suspend sequence since
 we now intend to support system level RET support.

 Signed-off-by: Rajendra Nayak rna...@ti.com
 Signed-off-by: Tero Kristo t-kri...@ti.com
 [Jean Pihet j-pi...@ti.com: ported on top of the functional power
 states]

   Shouldn't Jean also have signed off?
Sure! I am OK with this change, feel free to add:
Acked-by: Jean Pihet j-pi...@ti.com

Regards,
Jean


 Reviewed-by: Santosh Shilimkar santosh.shilim...@ti.com

 WBR, Sergei
 --
 To unsubscribe from this list: send the line unsubscribe linux-omap in
 the body of a message to majord...@vger.kernel.org
 More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 2/8] ARM: OMAP2+: PM: introduce power domains functional states

2012-07-13 Thread Jean Pihet
Hi Nishant,

On Fri, Jul 13, 2012 at 5:01 AM, Menon, Nishanth n...@ti.com wrote:
 On Thu, Jun 14, 2012 at 9:53 AM, Jean Pihet jean.pi...@newoldbits.com wrote:
 [..]
 --- a/arch/arm/mach-omap2/powerdomain-common.c
 +++ b/arch/arm/mach-omap2/powerdomain-common.c
 @@ -108,3 +108,74 @@ u32 omap2_pwrdm_get_mem_bank_stst_mask(u8 bank)
 return 0;
  }

 +/**
 + * omap2_pwrdm_func_to_pwrst - Convert functional (i.e. logical) to
 + * internal (i.e. registers) values for the power domains states.
 + * @struct powerdomain * to convert the values for
 + * @func_pwrst: functional power state
 + *
 + * Returns the internal power state value for the power domain, or
 + * -EINVAL in case of invalid parameters passed in.
 + */
 +int omap2_pwrdm_func_to_pwrst(struct powerdomain *pwrdm, u8 func_pwrst)

 Unless we handle logicpwst and pwst here, it makes it hard for non
 arch/arm/mach-omap2/powerdomain* files to use this properly.
The logic and mem states support is coming in another patch in the
series. I think I should merge the patches together since I got the
same remarks a few times already


 +{
 +   int ret;
 +
 +   switch (func_pwrst) {
 +   case PWRDM_FUNC_PWRST_ON:
 +   ret = PWRDM_POWER_ON;
 +   break;
 +   case PWRDM_FUNC_PWRST_INACTIVE:
 +   ret = PWRDM_POWER_INACTIVE;
 +   break;
 +   case PWRDM_FUNC_PWRST_CSWR:
 +   case PWRDM_FUNC_PWRST_OSWR:
 +   ret = PWRDM_POWER_RET;

 logic power state?

 +   break;
 +   case PWRDM_FUNC_PWRST_OFF:
 +   ret = PWRDM_POWER_OFF;
 +   break;
 +   default:
 +   ret = -EINVAL;
 +   }
 +
 +   return ret;
 +}
 +
 +/**
 + * omap2_pwrdm_pwrst_to_func - Convert internal (i.e. registers) to
 + * functional (i.e. logical) values for the power domains states.
 + * @struct powerdomain * to convert the values for
 + * @pwrst: internal power state
 + *
 + * Returns the functional power state value for the power domain, or
 + * -EINVAL in case of invalid parameters passed in.
 + */
 +int omap2_pwrdm_pwrst_to_func(struct powerdomain *pwrdm, u8 pwrst)
 Same here as well..
 +{
 +   int ret;
 +
 +   switch (pwrst) {
 +   case PWRDM_POWER_ON:
 +   ret = PWRDM_FUNC_PWRST_ON;
 +   break;
 +   case PWRDM_POWER_INACTIVE:
 +   ret = PWRDM_FUNC_PWRST_INACTIVE;
 +   break;
 +   case PWRDM_POWER_RET:
 +   /*
 +* XXX warning: return OSWR in case of pd in RET and
 +* logic in OFF
 +*/
 We need to be able to pass in logic pwst to be able to make that 
 determination.

 +   ret = PWRDM_FUNC_PWRST_CSWR;
 +   break;
 +   case PWRDM_POWER_OFF:
 +   ret = PWRDM_FUNC_PWRST_OFF;
 +   break;
 +   default:
 +   ret = -EINVAL;
 +   }
 +
 +   return ret;
 +}
 +
 diff --git a/arch/arm/mach-omap2/powerdomain.c 
 b/arch/arm/mach-omap2/powerdomain.c
 index 1641e72..e79b5ae 100644
 --- a/arch/arm/mach-omap2/powerdomain.c
 +++ b/arch/arm/mach-omap2/powerdomain.c
 @@ -466,6 +466,135 @@ int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm)
  }

  /**
 + * pwrdm_func_to_pwrst - get the internal (i.e. registers) value mapped
 + * to the functional state
 + * @pwrdm: struct powerdomain * to query
 + * @func_pwrst: functional power state
 + *
 + * Convert the functional power state to the platform specific power
 + * domain state value.
 + * Returns the internal power domain state value or -EINVAL in case
 + * of invalid parameters passed in.
 + */
 +int pwrdm_func_to_pwrst(struct powerdomain *pwrdm, u8 func_pwrst)
 should take enum pwrdm_func_state func_pwrst
Ok


 +{
 +   int ret = func_pwrst;
 +
 +   if ((!pwrdm) || (func_pwrst = PWRDM_MAX_FUNC_PWRSTS))
 +   return -EINVAL;
 +
 +   if (arch_pwrdm  arch_pwrdm-pwrdm_func_to_pwrst)
 +   ret = arch_pwrdm-pwrdm_func_to_pwrst(pwrdm, func_pwrst);

 Should we not return an error if the function pointer is not available
 for the arch?
 on platforms without func_pwrst pointer converter routing hooked on,
 we return func_pwrst back to caller, which expects pwrst!
This is what the code does, cf. the first line of the function 'int
ret = func_pwrst;'. Is that what you mean?


 +
 +   pr_debug(powerdomain: convert func %0x to pwrst %0x for %s\n,
 +func_pwrst, ret, pwrdm-name);
 +
 +   return ret;
 +}
 +
 +/**
 + * pwrdm_pwrst_to_func - get the functional (i.e. logical) value mapped
 + * to the internal state
 + * @pwrdm: struct powerdomain * to query
 + * @pwrst: internal power state
 + *
 + * Convert the internal power state to the power domain functional value.
 + * Returns the functional power domain state value or -EINVAL in case
 + * of invalid parameters passed in.
 + */
 +int pwrdm_pwrst_to_func(struct powerdomain *pwrdm, u8 pwrst)
 should return enum pwrdm_func_state

Re: [PATCH 2/8] ARM: OMAP2+: PM: introduce power domains functional states

2012-07-13 Thread Jean Pihet
Hi!

On Fri, Jul 13, 2012 at 7:29 AM, Menon, Nishanth n...@ti.com wrote:
 On Fri, Jul 13, 2012 at 12:26 AM, Rajendra Nayak rna...@ti.com wrote:
 On Friday 13 July 2012 08:31 AM, Menon, Nishanth wrote:

 my Crib about the above apis are lack of logic power state handling:(
 which forces code like cpuidle to use different apis for logic
 power state and force them to use these apis just for pwrst.


 Have you looked at an alternate approach that was proposed here..
 https://patchwork.kernel.org/patch/1160431/

 Santosh pointed me to the thread offline. This is indeed a much better
 approach IMHO than having 3 conflicting options inside powerdomain
 framework.
After looking at the code and having sent my comments, I like it ...
mainly because it is really similar to my proposal ;-p
Can you elaborate more on 'having 3 conflicting options inside
powerdomain framework'?

Here are the main differences in the implementation:
- the RFC code provides a _private header file, which forces the
external users (cpuidle, pm.c etc.),
- the RFC code still uses the same function names while my code
renames them to '*_func_*'. This makes the code look more complicated
than it really is.

 Regards,
 Nishanth Menon

We are having a discussion on the best way to have the feature in. More to come!

Thanks!
Jean
--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v4 0/8] ARM: OMAP2+: PM: introduce the power domains functional states

2012-07-13 Thread Jean Pihet
Hi!

On Thu, Jun 14, 2012 at 4:53 PM, Jean Pihet jean.pi...@newoldbits.com wrote:
 Here is a re-spin after some comments after an internal review and some 
 testing on
 OMAP4 with device OFF support.

 Implement the functional states for the power domains:
 - unify the API to use the functional states,
 - protect the power domain state change by a mutex in
   omap_set_pwrdm_state,
 - introduce the functional states for power domains power states and
   logic power states, and the conversion functions between the
   functional and internal states,
 - program the logic power state of power domains from the functional
   states, in omap_set_pwrdm_state
 - convert the OMAP2/3/4 PM code to use the updated API,
 - provide the power domains statistics by functional states,
 - provide ftrace tracepoints with the functional state.

 Based on mainline kernel 3.5.0-rc2.

 Tested on OMAP3 Beagleboard, with suspend and cpuidle in RET and
 OFF modes.

Here is the latest version for anyone willing to look at it, or even
better review and test it.

The latest code can be fetched from https://gitorious.org/jpihet/linux.
Please note that the tree also contains branches for the per-device PM
QoS, OMAP4 device OFF and the misc fixes needed to allow OMAP4 to
enter the low power modes.

Based on 3.5.0-rc6; tested with OMAP34 suspend/resume and OMAP3
cpuidle, using CSWR and OFF modes.

Here are the changes since the last version:
- changed the locking to a spinlock. Thanks to Ambresh K for reporting
the issue,
- extended the locking to the next power state read
(pwrdm_read_next_func_pwrst) and write (omap_set_pwrdm_state).

Regards,
Jean



 History:
  v4:
  - reworked the code after internal review and testing with OMAP34 device
OFF,
  - fixed the tracepoints generation code,
  - introduce a function that returns power domains achievable functional
states, in order to return a valid state for power domains that only
support some of the power states. Although it has been tested OK the
code is in RFC state.

  v3:
  - fix a bug in OMAP3 cpuidle which prevented the IO wake-ups in PER

  v2:
  - add the logic power states,
  - provide the power domains statistics by functional states

  v1:
  - initial implementation, in RFC state


 Jean Pihet (8):
   ARM: OMAP2+: PM: protect the power domain state change by a mutex
   ARM: OMAP2+: PM: introduce power domains functional states
   ARM: OMAP2+: PM: use the functional power states API
   ARM: OMAP2+: PM: introduce power domains logic and memory functional
 states
   ARM: OMAP2+: PM: introduce power domains achievable functional states
   ARM: OMAP2+: PM: use the functional power states API for logic and
 memory
   ARM: OMAP2+: PM: use power domain functional state in stats counters
   ARM: OMAP2+: PM debug: trace the functional power domains states

  arch/arm/mach-omap2/cpuidle34xx.c  |   61 +++---
  arch/arm/mach-omap2/cpuidle44xx.c  |   28 +--
  arch/arm/mach-omap2/omap-hotplug.c |2 +-
  arch/arm/mach-omap2/omap-mpuss-lowpower.c  |   39 ++--
  arch/arm/mach-omap2/pm-debug.c |   15 +-
  arch/arm/mach-omap2/pm.c   |   62 -
  arch/arm/mach-omap2/pm.h   |1 -
  arch/arm/mach-omap2/pm24xx.c   |   15 +-
  arch/arm/mach-omap2/pm34xx.c   |   78 +++---
  arch/arm/mach-omap2/pm44xx.c   |   18 +-
  arch/arm/mach-omap2/powerdomain-common.c   |  100 
  arch/arm/mach-omap2/powerdomain.c  |  367 
 ++--
  arch/arm/mach-omap2/powerdomain.h  |  101 ++--
  arch/arm/mach-omap2/powerdomain2xxx_3xxx.c |7 +
  arch/arm/mach-omap2/powerdomain44xx.c  |3 +
  15 files changed, 653 insertions(+), 244 deletions(-)

 --
 1.7.7.6

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


Re: RFC: Simplification of Power Domain Control

2012-07-13 Thread Jean Pihet
Hi Nishant, Rajendra,

On Fri, Jul 13, 2012 at 1:03 PM, Rajendra Nayak rna...@ti.com wrote:
 Hi Nishanth,


 On Friday 13 July 2012 03:21 PM, Menon, Nishanth wrote:

 On Thursday 05 July 2012, Rajendra Nayak wrote:
 [..]

  From 5f5e4eb342110286bf719c7d9d7c1959f53e34f9 Mon Sep 17 00:00:00 2001
 From: Rajendra Nayakrna...@ti.com
 Date: Thu, 5 Jul 2012 17:33:28 +0530
 Subject: [RFC] ARM: OMAP: Powerdomain: control memory and logic bits
 internally

 Powerdomain framework exposes various apis for memory and logic
 control for powerdomains, for its users to program OSWR: Open SWitch
 Retention state. While in theory, there are various combinations of
 memory and logic states possible which can be configured as OSWR,
 in practice all OMAPs use just one combination. Logic lost, memory
 retained.

 This can very easily be handled within the powerdomain framework itself,
 without exposing all complex memory/logic control apis to upper layer
 drivers like cpuidle and suspend.

 To do this, introduce 2 new power domain states PWRDM_POWER_CSWR and
 PWRDM_POWER_OSWR usable by the users of powerdomain framework and
 make all memory/logic control apis internal to powerdomain framework.
 Change all users of powerdomain framework to get rid of all usage
 of memory/logic control apis and use the newly defined states for
 CSWR and OSWR with the already used powerstate control apis.

 Some functions (which are now made internal) are forward declared
 to avoid moving functions around in the file (which can be done in a
 later patch) to help keep the patch reviewable.

 Signed-off-by: Rajendra Nayakrna...@ti.com



 Ref: http://marc.info/?t=13396858684r=1w=2

 Apologies, but i've had to copypaste the original message, so inline
 response
 might be a bit messed up.

  From an initial port to get cpuidle working on OMAP5, my experiences
 follow:


 Thanks for the tests and the review.


 a) counter handling (pm-debug.c) - we can now do better than give our
 arcane RET:5
 LOGIC-POWER-OFF:4 , instead we can clearly indicate OSWR, CSWR in
 counter
 Part of the issue also now becomes that count and time arrays are in
 the range of
 PWRDM_POWER_ON. They break when CSWR/OSWR is in pwrdm-state
Cf. http://marc.info/?l=linux-omapm=133968582005062w=2 for an
implementation of the power domains statistics using the func power
states. Of course the string format can be updated.


 b) pwrst handling this becomes a hard one to handle (as usual) when
 comparisons of
 while (!(pwrdm-pwrsts  (1  pwrst))) {

  if (pwrst == PWRDM_POWER_OFF)
  goto out;
  pwrst--;
 }

 with value 4, 5 -  pwrsts should either now use OSWR, CSWR definitions
 OR we will need translate back before checks
That is correct. The proposed implementation introduces a new function
pwrdm_get_achievable_func_pwrst that walks through the _internal_
(i.e. registers) states for both the power state and the logic state.
Cf. http://marc.info/?l=linux-omapm=133968582005061w=2. The patch is
in RFC state and so it would be ideal to get some comments from the
knowledgeable persons.


 c) in few critical places, these mentioned error checks do silent
 error returns - example:
   if (!(pwrdm-pwrsts_logic_ret  (1  pwrst)))

   return -EINVAL;
   this bit me more than once while i tried to bring up the patch
 we should be doing a patch which introduces a ratelimited WARN to kill the
 bad callers.
Right!


 d) we have been lazy in programming and have been using cur_pwrst
 PWRDM_POWER_ON or INACTIVE etc.. and do a set of operations based off
 that. this wont work as CSWR, OSWR  POWER_INACTIVE. (e.g. pm3 code)
That is one of the concerns with the current code. Any suggestion on that?



 All are valid issues. Some I overlooked, some like the array index
 issues due to CSWR/OSWR being defined post OFF, I knew but did not
 handle well because it was  a hastily cooked up RFC to clarify our
 thoughts.
Correct. That is the problem with the RFC, which is trying to retain
most of the original code for the states handling.


 now that I have more feedback I will certainly wort on improving it.



 e) similar to what Jean did, omap_set_pwrdm_state will need to move
 over from pm.c to powerdomain.c
Correct! The function could even be renamed to pwrdm_... Also the
private header file is a good concept.


 f) We probably should also will need an updated patch for
 http://marc.info/?l=linux-omapm=133968581105049w=2


 Yes, certainly, they would be needed as well.
I have a new version of the patch. Cf. the tree at
https://gitorious.org/jpihet/linux (functional-pwrst branch).


 regards,
 Rajendra

Thanks and regards,
Jean



 Regards,
 Nishanth Menon


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

Re: RFC: Simplification of Power Domain Control

2012-07-05 Thread Jean Pihet
On Thu, Jul 5, 2012 at 3:03 PM, Rajendra Nayak rna...@ti.com wrote:
 Just to give more context, the though of doing something like
 what the below RFC does came up as part of the patch review of
 Jean's Functional power state series.
My reply crossed yours...

 There was also some
 offline discussion about this between me, Santosh Shilimkar and
 Paul Walmsley.
Good to know!
And... ?

Jean.



 On Thursday 05 July 2012 06:17 PM, Rajendra Nayak wrote:

 Hi,

 This RFC is aimed at simplifying the powerdomain control
 (in software) for OMAP. Powerdomains on OMAP have been
 fairly complex to program (as compared to other SoCs)
 mainly due to the multiple memory/logic control exposed
 to software. These controls are limited to achieving
 whats know as 'OSWR: Open Switch Retention' state in OMAP.
 Rest of the states supported (ON, INACTIVE, CSWR, OFF) are
 fairly easy to program needing just a target power state
 to be configured.

 While in theory, the hardware does expose multiple ways/
 combinations in which OSWR can be achieved, we in software
 have always been  using just *one* combination all along.
 OSWR has always been configured as *logic lost, all memory
 retained* for all current OMAPs supported.

 With future OMAPs planning to get rid of all the memory/logic
 control altogether it makes sense to look at the apis exposed
 through the current powerdomain framework to its users (like
 cpuilde, suspend etc) and see if those could also be simplified.

 The RFC is suspend tested on OMAP4430sdp and
 OMAP3630Beagle-Xm.

 regards,
 Rajendra

 
  From 5f5e4eb342110286bf719c7d9d7c1959f53e34f9 Mon Sep 17 00:00:00 2001
 From: Rajendra Nayakrna...@ti.com
 Date: Thu, 5 Jul 2012 17:33:28 +0530
 Subject: [RFC] ARM: OMAP: Powerdomain: control memory and logic bits
 internally

 Powerdomain framework exposes various apis for memory and logic
 control for powerdomains, for its users to program OSWR: Open SWitch
 Retention state. While in theory, there are various combinations of
 memory and logic states possible which can be configured as OSWR,
 in practice all OMAPs use just one combination. Logic lost, memory
 retained.

 This can very easily be handled within the powerdomain framework itself,
 without exposing all complex memory/logic control apis to upper layer
 drivers like cpuidle and suspend.

 To do this, introduce 2 new power domain states PWRDM_POWER_CSWR and
 PWRDM_POWER_OSWR usable by the users of powerdomain framework and
 make all memory/logic control apis internal to powerdomain framework.
 Change all users of powerdomain framework to get rid of all usage
 of memory/logic control apis and use the newly defined states for
 CSWR and OSWR with the already used powerstate control apis.

 Some functions (which are now made internal) are forward declared
 to avoid moving functions around in the file (which can be done in a
 later patch) to help keep the patch reviewable.

 Signed-off-by: Rajendra Nayakrna...@ti.com
 ---
   arch/arm/mach-omap2/cpuidle44xx.c|9 +---
   arch/arm/mach-omap2/omap-mpuss-lowpower.c|7 +--
   arch/arm/mach-omap2/pm24xx.c |   17 +--
   arch/arm/mach-omap2/pm34xx.c |8 ++--
   arch/arm/mach-omap2/pm44xx.c |   11 +---
   arch/arm/mach-omap2/powerdomain-private.h|   17 +++
   arch/arm/mach-omap2/powerdomain.c|   54
 +++---
   arch/arm/mach-omap2/powerdomain.h|   14 +-
   arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c |1 +
   arch/arm/mach-omap2/powerdomains2xxx_data.c  |1 +
   arch/arm/mach-omap2/powerdomains3xxx_data.c  |1 +
   arch/arm/mach-omap2/powerdomains44xx_data.c  |1 +
   12 files changed, 85 insertions(+), 56 deletions(-)
   create mode 100644 arch/arm/mach-omap2/powerdomain-private.h

 diff --git a/arch/arm/mach-omap2/cpuidle44xx.c
 b/arch/arm/mach-omap2/cpuidle44xx.c
 index be1617c..d40fe90 100644
 --- a/arch/arm/mach-omap2/cpuidle44xx.c
 +++ b/arch/arm/mach-omap2/cpuidle44xx.c
 @@ -27,7 +27,6 @@
   /* Machine specific information */
   struct omap4_idle_statedata {
 u32 cpu_state;
 -   u32 mpu_logic_state;
 u32 mpu_state;
   };

 @@ -35,17 +34,14 @@ static struct omap4_idle_statedata omap4_idle_data[] =
 {
 {
 .cpu_state = PWRDM_POWER_ON,
 .mpu_state = PWRDM_POWER_ON,
 -   .mpu_logic_state = PWRDM_POWER_RET,
 },
 {
 .cpu_state = PWRDM_POWER_OFF,
 -   .mpu_state = PWRDM_POWER_RET,
 -   .mpu_logic_state = PWRDM_POWER_RET,
 +   .mpu_state = PWRDM_POWER_CSWR,
 },
 {
 .cpu_state = PWRDM_POWER_OFF,
 -   .mpu_state = PWRDM_POWER_RET,
 -   .mpu_logic_state = PWRDM_POWER_OFF,
 +   .mpu_state = PWRDM_POWER_OSWR,
 },
   };

 @@ -95,7 +91,6 @@ static int omap4_enter_idle(struct 

Re: [PATCH 3/3] ARM: OMAP3: PM: cpuidle: optimize the clkdm idle latency in C1 state

2012-06-20 Thread Jean Pihet
Hi Rajendra,

On Wed, Jun 20, 2012 at 10:19 AM, Rajendra Nayak rna...@ti.com wrote:
 Hi Jean,


 On Friday 01 June 2012 08:41 PM, Jean Pihet wrote:

 For a power domain to idle all the clock domains in it must idle.
 This patch implements an optimization of the cpuidle code by
 denying and later allowing only the first registered clock domain
 of a power domain, and so optimizes the latency of the low power code.


 How much do we really save doing this? I understand what you are doing
 by looking at the patch but the changelog seems very confusing.
The gain is on the registers accesses and the internal PRCM state machine.
If needed the changelog can be updated.

 What the patch does is get rid of a few function indirection
 and assumes there is only *one* clkdm for mpu and core. Is that right?
Not exactly. The patch does not assume that there is only one clkdm
per power domain. It just allows or denies only one clkdm to idle,
which has the same effect at the power domain level.

Thanks for reviewing,
Jean


 regards,
 Rajendra



 The functions _cpuidle_allow_idle and _cpuidle_deny_idle are
 not used anymore and so are removed.

 Signed-off-by: Jean Pihetj-pi...@ti.com
 ---
  arch/arm/mach-omap2/cpuidle34xx.c |   22 --
  1 files changed, 4 insertions(+), 18 deletions(-)

 diff --git a/arch/arm/mach-omap2/cpuidle34xx.c
 b/arch/arm/mach-omap2/cpuidle34xx.c
 index 2e2f1c6..e6ae3fe 100644
 --- a/arch/arm/mach-omap2/cpuidle34xx.c
 +++ b/arch/arm/mach-omap2/cpuidle34xx.c
 @@ -77,20 +77,6 @@ static struct omap3_idle_statedata omap3_idle_data[] =
 {

  static struct powerdomain *mpu_pd, *core_pd, *per_pd, *cam_pd;

 -static int _cpuidle_allow_idle(struct powerdomain *pwrdm,
 -                               struct clockdomain *clkdm)
 -{
 -       clkdm_allow_idle(clkdm);
 -       return 0;
 -}
 -
 -static int _cpuidle_deny_idle(struct powerdomain *pwrdm,
 -                               struct clockdomain *clkdm)
 -{
 -       clkdm_deny_idle(clkdm);
 -       return 0;
 -}
 -
  static int __omap3_enter_idle(struct cpuidle_device *dev,
                                struct cpuidle_driver *drv,
                                int index)
 @@ -108,8 +94,8 @@ static int __omap3_enter_idle(struct cpuidle_device
 *dev,

        /* Deny idle for C1 */
        if (index == 0) {
 -               pwrdm_for_each_clkdm(mpu_pd, _cpuidle_deny_idle);
 -               pwrdm_for_each_clkdm(core_pd, _cpuidle_deny_idle);
 +               clkdm_deny_idle(mpu_pd-pwrdm_clkdms[0]);
 +               clkdm_deny_idle(core_pd-pwrdm_clkdms[0]);
        }

        /*
 @@ -131,8 +117,8 @@ static int __omap3_enter_idle(struct cpuidle_device
 *dev,

        /* Re-allow idle for C1 */
        if (index == 0) {
 -               pwrdm_for_each_clkdm(mpu_pd, _cpuidle_allow_idle);
 -               pwrdm_for_each_clkdm(core_pd, _cpuidle_allow_idle);
 +               clkdm_allow_idle(mpu_pd-pwrdm_clkdms[0]);
 +               clkdm_allow_idle(core_pd-pwrdm_clkdms[0]);
        }

  return_sleep_time:


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


Re: [PATCH 3/3] ARM: OMAP3: PM: cpuidle: optimize the clkdm idle latency in C1 state

2012-06-20 Thread Jean Pihet
Hi Rajendra,

On Wed, Jun 20, 2012 at 10:57 AM, Rajendra Nayak rna...@ti.com wrote:
 Jean,


 On Wednesday 20 June 2012 02:22 PM, Rajendra Nayak wrote:

 Hi Jean,

 On Wednesday 20 June 2012 02:16 PM, Rajendra Nayak wrote:

 On Wednesday 20 June 2012 02:01 PM, Jean Pihet wrote:

 Hi Rajendra,

 On Wed, Jun 20, 2012 at 10:19 AM, Rajendra Nayakrna...@ti.com wrote:

 Hi Jean,


 On Friday 01 June 2012 08:41 PM, Jean Pihet wrote:


 For a power domain to idle all the clock domains in it must idle.
 This patch implements an optimization of the cpuidle code by
 denying and later allowing only the first registered clock domain
 of a power domain, and so optimizes the latency of the low power code.



 How much do we really save doing this? I understand what you are doing
 by looking at the patch but the changelog seems very confusing.

 The gain is on the registers accesses and the internal PRCM state
 machine.
 If needed the changelog can be updated.


 Can you explain a bit more on which register accesses are you talking
 about? and some more on the PRCM state machine.


 never mind, I looked at the patch again and then the cpuidle code and
 figured what you are doing. Makes sense to me now :-)
Ok!



 How do you like this updated changelog, I just added one more line.


 
 For a power domain to idle all the clock domains in it must idle.
 Denying just *one* clkdm in a pwrdm from idling should have the
 same effect as denying *all*.

 This patch implements an optimization of the cpuidle code by
 denying and later allowing only the first registered clock domain
 of a power domain, and so optimizes the latency of the low power code.
 
That looks great!

Kevin,
Can you take this change still in your for_3.6/pm/performance branch?

Thanks  regards,
Jean


 regards,
 Rajendra
 --
 To unsubscribe from this list: send the line unsubscribe linux-omap in
 the body of a message to majord...@vger.kernel.org
 More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 03/10] ARM: OMAP2+: PM QoS: manage the per-device latency constraints in hwmod

2012-06-20 Thread Jean Pihet
Rajendra,

On Wed, Jun 20, 2012 at 12:29 PM, Rajendra Nayak rna...@ti.com wrote:
 On Thursday 14 June 2012 08:35 PM, Jean Pihet wrote:

 Call the per-device PM QoS functions of the power domain code from the
 hwmod layer, in order to apply the constraints requested to a device.

 While at it, correct the functions kerneldoc.


 Shouldn't this patch be just merged with PATCH 02/10?
Ideally yes!

Paul,
Is this possiblr or is the patch 02/10 already scheduled for inclusion
in l-o or mainline?

Regards,
Jean




 Signed-off-by: Jean Pihetj-pi...@ti.com
 ---
  arch/arm/mach-omap2/omap_hwmod.c |   22 ++
  1 files changed, 6 insertions(+), 16 deletions(-)

 diff --git a/arch/arm/mach-omap2/omap_hwmod.c
 b/arch/arm/mach-omap2/omap_hwmod.c
 index cc173d9..4f43e0c 100644
 --- a/arch/arm/mach-omap2/omap_hwmod.c
 +++ b/arch/arm/mach-omap2/omap_hwmod.c
 @@ -3302,15 +3302,13 @@ ohsps_unlock:
  }

  /**
 - * omap_hwmod_set_wakeuplat_constraint - set/release a wake-up latency
 + * omap_hwmod_set_wakeuplat_constraint - Set or update a wake-up latency
   * constraint
   * @oh: struct omap_hwmod* to which the target device belongs to.
   * @cookie: identifier of the constraints list for @oh.
   * @min_latency: the minimum allowed wake-up latency for @oh.
   *
 - * Sets a wakeup latency contraint.  (To remove a wakeup latency
 - * constraint, call omap_hwmod_remove_wakeuplat_constraint()).
 - * Returns the return value from pwrdm_wakeuplat_remove_constraint(),
 + * Returns the return value from pwrdm_wakeuplat_update_constraint(),
   * or -EINVAL in case of invalid parameters.
   */
  int omap_hwmod_set_wakeuplat_constraint(struct omap_hwmod *oh, void
 *cookie,
 @@ -3321,21 +3319,17 @@ int omap_hwmod_set_wakeuplat_constraint(struct
 omap_hwmod *oh, void *cookie,
        if (!pwrdm)
                return -EINVAL;

 -       /*
 -        * XXX Update to use pwrdm_wakeuplat_update_constraint() when
 -        * that code is ready
 -        */
 -       return -EINVAL;
 +       return pwrdm_wakeuplat_update_constraint(pwrdm, cookie,
 min_latency);
  }

  /**
 - * omap_hwmod_remove_wakeuplat_constraint - release a wake-up latency
 + * omap_hwmod_remove_wakeuplat_constraint - Release a wake-up latency
   * constraint
   * @oh: struct omap_hwmod* to which the target device belongs to.
   * @cookie: identifier of the constraints list for @oh.
   *
   * Removes a wakeup latency contraint.  Returns the return value from
 - * pwrdm_wakeuplat_update_constraint(), or -EINVAL in case of invalid
 + * pwrdm_wakeuplat_remove_constraint(), or -EINVAL in case of invalid
   * parameters.
   */
  int omap_hwmod_remove_wakeuplat_constraint(struct omap_hwmod *oh, void
 *cookie)
 @@ -3345,11 +3339,7 @@ int omap_hwmod_remove_wakeuplat_constraint(struct
 omap_hwmod *oh, void *cookie)
        if (!pwrdm)
                return -EINVAL;

 -       /*
 -        * XXX Update to use pwrdm_wakeuplat_remove_constraint() when
 -        * that code is ready
 -        */
 -       return -EINVAL;
 +       return pwrdm_wakeuplat_remove_constraint(pwrdm, cookie);
  }

  /**


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


Re: [PATCH 07/10] ARM: OMAP3: update cpuidle latency and threshold figures

2012-06-20 Thread Jean Pihet
On Wed, Jun 20, 2012 at 1:01 PM, Rajendra Nayak rna...@ti.com wrote:
 On Thursday 14 June 2012 08:35 PM, Jean Pihet wrote:

                {
                        .enter            = omap3_enter_idle_bm,
 -                       .exit_latency     = 3000 + 8500,
 -                       .target_residency = 15000,
 +                       .exit_latency     = 4080 + 801,
 +                       .target_residency = 215000,
                        .flags            = CPUIDLE_FLAG_TIME_VALID,
                        .name             = C6,
                        .desc             = MPU OFF + CORE RET,
                },
                {
                        .enter            = omap3_enter_idle_bm,
 -                       .exit_latency     = 1 + 3,
 -                       .target_residency = 3,
 +                       .exit_latency     = 4300 + 13000,
 +                       .target_residency = 215000,


 Is the target_residency same for both these states?
Yes it is. The details are found in the omappedia wiki page.

Thanks,
Jean



                        .flags            = CPUIDLE_FLAG_TIME_VALID,
                        .name             = C7,
                        .desc             = MPU OFF + CORE OFF,


N‹§²æìr¸›yúèšØb²X¬¶Ç§vØ^–)Þº{.nÇ+‰·¥Š{±¢f©Š{ayºʇڙë,j­¢f£¢·hš‹àz¹®w¥¢¸
¢·¦j:+v‰¨ŠwèjØm¶Ÿÿ¾«‘êçzZ+ƒùšŽŠÝ¢jú!¶i

Re: usage of sparse or other trick for improved type safety

2012-06-15 Thread Jean Pihet
Hi!

Added Paul in Cc:.

On Thu, Jun 14, 2012 at 10:05 AM, Jean Pihet jean.pi...@newoldbits.com wrote:
 Hi Richard, all,

 On Tue, Jun 12, 2012 at 6:34 PM, Woodruff, Richard r-woodru...@ti.com wrote:
 Hi Tony,

 From: Tony Lindgren [mailto:t...@atomide.com]
 Sent: Friday, May 25, 2012 2:53 AM

 Thanks for quick input.  Apologies on slow ack of it.

 Before we had these frameworks in place it was often hard to debug when
 something
 did not work for some omaps. Things would just not work or would stop
 working
 for some drivers with no ideas what was going on. So yeah, having these
 kind of
 frameworks in place has helped a lot to avoid breakage like you're
 describing
 above.

 Trees which had to hit the lowest power states for full customer boards all 
 employed some form of abstraction of clock, power, voltage. The one today in 
 mainline today is the most clean. Aspects around auto-generation are very 
 good even if a bit big in size.

 Perhaps main grump I hear is the number of abstraction layers sometimes 
 makes debugging difficult. It would be nice to find smart tricks for compile 
 to prune away some.

 Still one can experience some of the mystery issues, as the PRCM connection 
 to IP-device utilizes a protocol which the device side can mess up. If the 
 device does not shut down its local function and associated clocks cleanly 
 it will show 'stuck in transition' and this gates final global changes. In 
 one of the closed implementation we would bug() drivers who did not shut 
 down their internal clocks properly before allowing global clock release.  
 Most of the issues seen in field are at drivers/peripheral-ip.


 For some external subsystems it might be possible to let the omap kernel
 manage
 powerdomains and other resource via remote proc interface, assuming these
 registers are ioremapped in the omap kernel side and not owned by the
 external
 subsystem. The messaging to do this would add some undesired latencies
 though,
 but maybe those would not be so critical for the external subsystems as
 they
 tend to be full on or completely off type accelerators.

 Humm. Maybe for some. Guess walking what is used and sorting might tell.

 The way some subsystems 'ideal' operation is described from designers 
 implies tight control of timing and sequence for things like power state. A 
 RPC doesn't feel like it fits with intent. However... practically speaking 
 from 'full system view' RPC may fit sometimes. A subsystem exporting hooks 
 to save 100uW using its optimal state set against other components running 
 in 500mW range minimizes usefulness.

 The other alternative of course is to implement similar frameworks for the
 external subsystems. Some of this might be possible to implement as simple
 macros with some type checks if it's subsystem specific. For doing it for
 all omap devices, macros were soon found not to be enough as the various
 bits all over need to be linked together for managing various resources.

 Agree.

 I don't know insides of all subsystems.  Though what I know or hear is kind 
 of a mixed picture.

 OMAP has an ultra high level of integration. As such you might find 
 something like DSP-Bios may provide a good hook but quick integration of a 
 previously standalone single purpose piece does not have time to be 
 readapted.

 The type checking question kind of grows out of this.  Linux might today 
 offer a clean run-time api which is place where high wall should be built 
 with type check.  But... the driver might not be able to function yet with 
 the API alone given state of evolution of both ends.

 Regarding the API and type checking I think the following must be enforced:
 1. proper type checking in the API, possibly by the compiler,
 2. clean separation of an API into an internal part (used only by the
 framework implementation) and an external part (used by the callers of
 the API).

 About 1: using enum for the parameters did not help much AFACIT. The
 compiler cannot tell if the parameter from a variable is in the
 allowed range.
 Any thought?

 About 2: while introducing the functional power states I came across
 this problem. Ideally the current states macros (PWRDM_POWER_* and
 PWRSTS_*) shall be used by the internal code only in powerdomain*.[ch]
 while the callers (pm.c etc) shall use the new macros
 (PWRDM_FUNC_PWRST_*) and API (mainly pwrdm_*_func_* and
 omap_set_pwrdm_state).

 Here below is a patch extract (trimmed for brevity) to illustrate the problem.
FYI the full patch is at http://marc.info/?l=linux-omapm=133968581305050w=2


 From here is see a few possible options:
 1. clearly separate the internal and external parts of the API in the
 header file using comments (as done in the patch below) or with a new
 #ifdef POWERDOMAIN_INTERNAL_API (ugly I know),
Some more details about that option: the internal values could be
prefixed by '__' or similar which kinds of highlights a bad API usage.

 2. create a new internal only header file

Re: [PATCH 2/8] ARM: OMAP2+: PM: introduce power domains functional states

2012-06-15 Thread Jean Pihet
Hi,

Here are some remarks I got after an internal review. I think those
points need to be discussed with a broader audience.

On Thu, Jun 14, 2012 at 4:53 PM, Jean Pihet jean.pi...@newoldbits.com wrote:
 Introduce functional (or logical) states for power domains and the
 API functions to read the power domains settings and to convert
 between the functional (i.e. logical) and the internal (or registers)
 values.

 OMAP2, OMAP3 and OMAP4 platforms are defining a conversion routine.

 In the new API only the function omap_set_pwrdm_state shall be used
 to change a power domain target state, along with the associated
 PWRDM_FUNC_* macros as the state parameters.
 While at it the function is moved to the power domains code.

 The power domain API in powerdomain.h is split in the external and the
 internal parts; only the external API functions and defines shall be used
 by external code, the internal API is only to be used in powerdomain*.[ch]
 files.

 The memory and logic states are not using the functional states, this
 comes as a subsequent patch.

 Signed-off-by: Jean Pihet j-pi...@ti.com
 ---
  arch/arm/mach-omap2/pm.c                   |   66 ---
  arch/arm/mach-omap2/pm.h                   |    1 -
  arch/arm/mach-omap2/powerdomain-common.c   |   71 +++
  arch/arm/mach-omap2/powerdomain.c          |  174 
 
  arch/arm/mach-omap2/powerdomain.h          |   77 +
  arch/arm/mach-omap2/powerdomain2xxx_3xxx.c |    5 +
  arch/arm/mach-omap2/powerdomain44xx.c      |    2 +
  7 files changed, 306 insertions(+), 90 deletions(-)

 diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
 index a05f00c..dfe702b 100644
 --- a/arch/arm/mach-omap2/pm.c
 +++ b/arch/arm/mach-omap2/pm.c
 @@ -74,10 +74,6 @@ static void __init omap2_init_processor_devices(void)
        }
  }

 -/* Types of sleep_switch used in omap_set_pwrdm_state */
 -#define FORCEWAKEUP_SWITCH     0
 -#define LOWPOWERSTATE_SWITCH   1
 -
  int __init omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused)
  {
        if (clkdm-flags  CLKDM_CAN_ENABLE_AUTO)
 @@ -89,68 +85,6 @@ int __init omap_pm_clkdms_setup(struct clockdomain *clkdm, 
 void *unused)
  }

  /*
 - * This sets pwrdm state (other than mpu  core. Currently only ON 
 - * RET are supported.
 - */
 -int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 pwrst)
 -{
 -       u8 curr_pwrst, next_pwrst;
 -       int sleep_switch = -1, ret = 0, hwsup = 0;
 -
 -       if (!pwrdm || IS_ERR(pwrdm))
 -               return -EINVAL;
 -
 -       mutex_lock(pwrdm-lock);
 -
 -       while (!(pwrdm-pwrsts  (1  pwrst))) {
 -               if (pwrst == PWRDM_POWER_OFF)
 -                       goto out;
 -               pwrst--;
 -       }
 -
 -       next_pwrst = pwrdm_read_next_pwrst(pwrdm);
 -       if (next_pwrst == pwrst)
 -               goto out;
 -
 -       curr_pwrst = pwrdm_read_pwrst(pwrdm);
 -       if (curr_pwrst  PWRDM_POWER_ON) {
 -               if ((curr_pwrst  pwrst) 
 -                       (pwrdm-flags  PWRDM_HAS_LOWPOWERSTATECHANGE)) {
 -                       sleep_switch = LOWPOWERSTATE_SWITCH;
 -               } else {
 -                       hwsup = clkdm_in_hwsup(pwrdm-pwrdm_clkdms[0]);
 -                       clkdm_wakeup(pwrdm-pwrdm_clkdms[0]);
 -                       sleep_switch = FORCEWAKEUP_SWITCH;
 -               }
 -       }
 -
 -       ret = pwrdm_set_next_pwrst(pwrdm, pwrst);
 -       if (ret)
 -               pr_err(%s: unable to set power state of powerdomain: %s\n,
 -                      __func__, pwrdm-name);
 -
 -       switch (sleep_switch) {
 -       case FORCEWAKEUP_SWITCH:
 -               if (hwsup)
 -                       clkdm_allow_idle(pwrdm-pwrdm_clkdms[0]);
 -               else
 -                       clkdm_sleep(pwrdm-pwrdm_clkdms[0]);
 -               break;
 -       case LOWPOWERSTATE_SWITCH:
 -               pwrdm_set_lowpwrstchange(pwrdm);
 -               pwrdm_wait_transition(pwrdm);
 -               pwrdm_state_switch(pwrdm);
 -               break;
 -       }
 -
 -out:
 -       mutex_unlock(pwrdm-lock);
 -       return ret;
 -}
 -
 -
 -
 -/*
  * This API is to be called during init to set the various voltage
  * domains to the voltage as per the opp table. Typically we boot up
  * at the nominal voltage. So this function finds out the rate of
 diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
 index 7856489..5bc0848 100644
 --- a/arch/arm/mach-omap2/pm.h
 +++ b/arch/arm/mach-omap2/pm.h
 @@ -18,7 +18,6 @@
  extern void *omap3_secure_ram_storage;
  extern void omap3_pm_off_mode_enable(int);
  extern void omap_sram_idle(void);
 -extern int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state);
  extern int omap3_idle_init(void);
  extern int omap4_idle_init(void);
  extern int omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused);
 diff --git a/arch/arm/mach-omap2/powerdomain-common.c 
 b/arch/arm/mach-omap2/powerdomain-common.c
 index c0aeabf

Re: [PATCH 5/8] ARM: OMAP2+: PM: introduce power domains achievable functional states

2012-06-15 Thread Jean Pihet
Hi,

Here are some remarks I got after an internal review. I think those
points need to be discussed with a broader audience.

On Thu, Jun 14, 2012 at 4:53 PM, Jean Pihet jean.pi...@newoldbits.com wrote:
 Note: the patch is in RFC state because the state machine for setting
 the next power domain states needs more discussion. Validated on OMAP34
 with cpuidle and suspend/resume, though.

 Power domains have varied capabilities. When attempting a low power
 state such as OFF/RET, a specific min requested state may not be
 supported on the power domain. This is because a combination
 of system power states where the parent PD's state is not in line
 with expectation can result in system instabilities.

 This patch provides a function that returns the achievable functional
 power state for a power domain and its use by omap_set_pwrdm_state.
 The achievable power state is first looked for in the lower power
 states in order to maximize the power savings, then if not found
 in the higher power states.

 Inspired from Tero's work on OMAP4 device OFF support and generalized
 to the functional power states.

 Signed-off-by: Jean Pihet j-pi...@ti.com
 Cc: Tero Kristo t-kri...@ti.com
 ---
  arch/arm/mach-omap2/powerdomain.c |  156 
 +++--
  arch/arm/mach-omap2/powerdomain.h |    1 +
  2 files changed, 134 insertions(+), 23 deletions(-)

 diff --git a/arch/arm/mach-omap2/powerdomain.c 
 b/arch/arm/mach-omap2/powerdomain.c
 index ce2685a..f94174b 100644
 --- a/arch/arm/mach-omap2/powerdomain.c
 +++ b/arch/arm/mach-omap2/powerdomain.c
 @@ -554,6 +554,108 @@ int pwrdm_pwrst_to_func(struct powerdomain *pwrdm, u8 
 pwrst, u8 logic)
        return ret;
  }

 +/**
 + * pwrdm_get_achievable_func_pwrst() - Provide achievable functional state
 + * @pwrdm: struct powerdomain * to set
 + * @func_pwrst: minimum functional state we would like to hit
 + * (one of the PWRDM_FUNC_* macros)
 + *
 + * Power domains have varied capabilities. When attempting a low power
 + * state such as OFF/RET, a specific min requested state may not be
 + * supported on the power domain. This is because a combination
 + * of system power states where the parent PD's state is not in line
 + * with expectation can result in system instabilities.
 + *
 + * The achievable power state is first looked for in the lower power
 + * states in order to maximize the power savings, then if not found
 + * in the higher power states.
 + *
 + * Returns the achievable functional power state, or -EINVAL in case of
 + * invalid parameters.
 + */
 +int pwrdm_get_achievable_func_pwrst(struct powerdomain *pwrdm, u8 func_pwrst)
 +{
 +       int pwrst = pwrdm_func_to_pwrst(pwrdm, func_pwrst);
 +       int logic = pwrdm_func_to_logic_pwrst(pwrdm, func_pwrst);
 +       int new_func_pwrst, new_pwrst, new_logic;
 +       int found;
 +
 +       if (!pwrdm || IS_ERR(pwrdm)) {
 +               pr_debug(%s: invalid params: pwrdm=%p, func_pwrst=%0x\n,
 +                        __func__, pwrdm, func_pwrst);
 +               return -EINVAL;
 +       }
 +
 +       if ((pwrst  0) || (logic  0)) {
 +               pr_debug(%s: invalid params for pwrdm %s, func_pwrst=%0x\n,
 +                        __func__, pwrdm-name, func_pwrst);
 +               return PWRDM_FUNC_PWRST_ON;
 +       }
 +
 +       /*
 +        * Power state: if the requested state is not supported,
 +        * try the lower power states.
 +        */
 +       found = 1;
 +       new_pwrst = pwrst;
 +       while (!(pwrdm-pwrsts  (1  new_pwrst))) {
 +               if (new_pwrst == PWRDM_POWER_OFF) {
 +                       found = 0;
 +                       break;
 +               }
 +               new_pwrst--;
 +       }
 +
 +       /*
 +        * If no lower power state found, fallback to the higher
 +        * power states.
 +        * PWRDM_POWER_ON is always valid.
 +        */
 +       if (!found) {
 +               new_pwrst = pwrst;
 +               while (!(pwrdm-pwrsts  (1  new_pwrst))) {
 +                       if (new_pwrst == PWRDM_POWER_ON)
 +                               break;
 +                       new_pwrst++;
 +               }
 +       }
 +
 +       /*
 +        * Logic RET state: if the requested state is not supported,
 +        * try the lower logic states.
 +        */
 +       found = 1;
 +       new_logic = logic;
 +       while (!(pwrdm-pwrsts_logic_ret  (1  new_logic))) {
 +               if (new_logic == PWRDM_LOGIC_MEM_PWRST_OFF) {
 +                       found = 0;
 +                       break;
 +               }
 +               new_logic--;
 +       }
 +
 +       /*
 +        * If no lower logic state found, fallback to the higher
 +        * logic states.
 +        * PWRDM_LOGIC_MEM_PWRST_RET is always valid.
 +        */
 +       if (!found) {
 +               new_logic = logic;
 +               while (!(pwrdm-pwrsts_logic_ret  (1  new_logic))) {
 +                       if (new_logic == PWRDM_LOGIC_MEM_PWRST_RET

Re: [PATCH 01/10] ARM: OMAP2+: PM QoS: control the power domains next state from the constraints

2012-06-15 Thread Jean Pihet
Hi,

Here are some remarks I got after an internal review. I think those
points need to be discussed with a broader audience.

On Thu, Jun 14, 2012 at 5:05 PM, Jean Pihet jean.pi...@newoldbits.com wrote:
 When a PM QoS device latency constraint is requested or removed the
 constraint is stored in the constraints list of the corresponding power
 domain, then the aggregated constraint value is applied by programming
 the next functional power state using omap_set_pwrdm_state.

 Tested on OMAP3 Beagleboard and OMAP4 Pandaboard in RET/OFF using
 wake-up latency constraints on MPU, CORE and PER.

 Signed-off-by: Jean Pihet j-pi...@ti.com
 ---
  arch/arm/mach-omap2/powerdomain.c |  215 
 +
  arch/arm/mach-omap2/powerdomain.h |   18 +++
  2 files changed, 233 insertions(+), 0 deletions(-)

 diff --git a/arch/arm/mach-omap2/powerdomain.c 
 b/arch/arm/mach-omap2/powerdomain.c
 index f6885f9..82797c2 100644
 --- a/arch/arm/mach-omap2/powerdomain.c
 +++ b/arch/arm/mach-omap2/powerdomain.c
 @@ -17,8 +17,10 @@
  #include linux/kernel.h
  #include linux/types.h
  #include linux/list.h
 +#include linux/slab.h
  #include linux/errno.h
  #include linux/string.h
 +#include linux/pm_qos.h
  #include trace/events/power.h

  #include cm2xxx_3xxx.h
 @@ -113,6 +115,12 @@ static int _pwrdm_register(struct powerdomain *pwrdm)
        for (i = 0; i  pwrdm-banks; i++)
                pwrdm-ret_mem_off_counter[i] = 0;

 +       /* Initialize the per-device wake-up constraints framework data */
 +       mutex_init(pwrdm-wkup_lat_plist_lock);
 +       plist_head_init(pwrdm-wkup_lat_plist_head);
 +       pwrdm-wkup_lat_next_state = PWRDM_FUNC_PWRST_OFF;
 +
 +       /* Initialize the pwrdm state */
        pwrdm_wait_transition(pwrdm);
        pwrdm-state = pwrdm_read_func_pwrst(pwrdm);
        pwrdm-state_counter[pwrdm-state] = 1;
 @@ -200,6 +208,58 @@ static int _pwrdm_post_transition_cb(struct powerdomain 
 *pwrdm, void *unused)
        return 0;
  }

 +/**
 + * _pwrdm_wakeuplat_update_pwrst - Update power domain power state if needed
 + * @pwrdm: struct powerdomain * to which requesting device belongs to.
 + * @min_latency: the allowed wake-up latency for the given power domain. A
 + *  value of PM_QOS_DEV_LAT_DEFAULT_VALUE means 'no constraint' on the pwrdm.
 + *
 + * Finds the power domain next power state that fulfills the constraint.
 + * Programs a new target state if it is different from current power state.
 + * The power domains get the next power state programmed directly in the
 + * registers.
 + *
 + * Returns 0 in case of success, -EINVAL in case of invalid parameters,
 + * or the return value from omap_set_pwrdm_state.
 + */
 +static int _pwrdm_wakeuplat_update_pwrst(struct powerdomain *pwrdm,
 +                                        long min_latency)
 +{
 +       int ret = 0, state, new_state = PWRDM_FUNC_PWRST_ON;
 +
 +       if (!pwrdm) {
 +               WARN(1, powerdomain: %s: invalid parameter(s), __func__);
 +               return -EINVAL;
 +       }
 +
 +       /*
 +        * Find the next supported power state with
 +        *  wakeup latency = min_latency.
 +        * Pick the lower state if no constraint on the pwrdm
 +        *  (min_latency == PM_QOS_DEV_LAT_DEFAULT_VALUE).
 +        * Skip the states marked as unsupported (UNSUP_STATE).
 +        * If no power state found, fall back to PWRDM_FUNC_PWRST_ON.
 +        */
 +       for (state = 0x0; state  PWRDM_MAX_FUNC_PWRSTS; state++) {
 +               if ((min_latency == PM_QOS_DEV_LAT_DEFAULT_VALUE) ||
 +                   ((pwrdm-wakeup_lat[state] != UNSUP_STATE) 
 +                    (pwrdm-wakeup_lat[state] = min_latency))) {
 +                       new_state = state;
 +                       break;
 +               }
 +       }
 +
 +       pwrdm-wkup_lat_next_state = new_state;
 +       ret = omap_set_pwrdm_state(pwrdm, new_state);
 +
 +       pr_debug(%s: func pwrst for %s: curr=%d, next=%d, min_latency=%ld, 
 new_state=%d\n,
 +                __func__, pwrdm-name, pwrdm_read_func_pwrst(pwrdm),
 +                pwrdm_read_next_func_pwrst(pwrdm), min_latency, new_state);
 +
 +       return ret;
 +}
 +
 +
  /* Public functions */

  /**
 @@ -1317,6 +1377,161 @@ int pwrdm_post_transition(void)
  }

  /**
 + * pwrdm_wakeuplat_update_constraint - Set or update a powerdomain wakeup
 + *  latency constraint and apply it
 + * @pwrdm: struct powerdomain * which the constraint applies to
 + * @cookie: constraint identifier, used for tracking
 + * @min_latency: minimum wakeup latency constraint (in microseconds) for
 + *  the given pwrdm
 + *
 + * Tracks the constraints by @cookie.
 + * Constraint set/update: Adds a new entry to powerdomain's wake-up latency
 + * constraint list. If the constraint identifier already exists in the list,
 + * the old value is overwritten.
 + *
 + * Applies the aggregated constraint value for the given pwrdm by calling
 + * _pwrdm_wakeuplat_update_pwrst.
 + *
 + * Returns 0 upon success

Re: MFD USB host: prevents CORE retention in idle

2012-06-15 Thread Jean Pihet
Hi Keshava,

On Fri, Jun 15, 2012 at 2:04 PM, Munegowda, Keshava
keshava_mgo...@ti.com wrote:
 On Tue, Jun 12, 2012 at 6:28 PM, Munegowda, Keshava
 keshava_mgo...@ti.com wrote:
 hi kevin
     now I am using initramfs with kernel linux3.5.rc1,
 but the retention is not working in 3430 sdp.  I am seeing the following
 error followed by a crash


 echo mem  /sys/power/state
 [   35.609252] PM: Syncing filesystems ... done.
 [   35.614654] PM: Preparing system for mem sleep
 [   35.658630] Freezing user space processes ... (elapsed 0.01 seconds)
 done.
 [   35.689727] Freezing remaining freezable tasks ... (elapsed 0.02 seconds)
 done.
 [   35.697692] PM: Entering mem sleep
 [   35.722442] usb usb1: usb auto-resume
 [   35.726409] ehci-omap ehci-omap.0: resume root hub
 [   35.775451] hub 1-0:1.0: hub_resume
 [   35.779846] hub 1-0:1.0: hub_suspend
 [   35.784240] usb usb1: bus suspend, wakeup 0
 [   35.788665] ehci-omap ehci-omap.0: suspend root hub
 [   35.805786] PM: suspend of devices complete after 99.304 msecs
 [   35.816497] PM: late suspend of devices complete after 4.364 msecs
 [   35.831573] PM: noirq suspend of devices complete after 8.331 msecs
 [   35.838500] Disabling non-boot CPUs ...
 [   36.312164] Powerdomain (core_pwrdm) didn't enter target state 1
 [   36.318481] Could not enter target state in pm_suspend
 [   36.324859] Unable to handle kernel NULL pointer dereference at virtual
 address 0018
 [   36.333557] pgd = c628
 [   36.336639] [0018] *pgd=85c8f831, *pte=, *ppte=
 [   36.343414] Internal error: Oops: 17 [#1] SMP ARM
 [   36.348388] Modules linked in:
 [   36.351623] CPU: 0    Tainted: G    W (3.5.0-rc1 #1)
 [   36.357574] PC is at _od_resume_noirq+0x14/0x58
 [   36.362365] LR is at dpm_run_callback+0x2c/0x74

You need the fix from
https://gitorious.org/linux-omap-dss2/linux/commit/9e0ca55fa5d9ff012964a7c7cef8af1b814b2fdb

Hope this helps!

Regards,
Jean
--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: usage of sparse or other trick for improved type safety

2012-06-14 Thread Jean Pihet
Hi Richard, all,

On Tue, Jun 12, 2012 at 6:34 PM, Woodruff, Richard r-woodru...@ti.com wrote:
 Hi Tony,

 From: Tony Lindgren [mailto:t...@atomide.com]
 Sent: Friday, May 25, 2012 2:53 AM

 Thanks for quick input.  Apologies on slow ack of it.

 Before we had these frameworks in place it was often hard to debug when
 something
 did not work for some omaps. Things would just not work or would stop
 working
 for some drivers with no ideas what was going on. So yeah, having these
 kind of
 frameworks in place has helped a lot to avoid breakage like you're
 describing
 above.

 Trees which had to hit the lowest power states for full customer boards all 
 employed some form of abstraction of clock, power, voltage. The one today in 
 mainline today is the most clean. Aspects around auto-generation are very 
 good even if a bit big in size.

 Perhaps main grump I hear is the number of abstraction layers sometimes makes 
 debugging difficult. It would be nice to find smart tricks for compile to 
 prune away some.

 Still one can experience some of the mystery issues, as the PRCM connection 
 to IP-device utilizes a protocol which the device side can mess up. If the 
 device does not shut down its local function and associated clocks cleanly it 
 will show 'stuck in transition' and this gates final global changes. In one 
 of the closed implementation we would bug() drivers who did not shut down 
 their internal clocks properly before allowing global clock release.  Most of 
 the issues seen in field are at drivers/peripheral-ip.


 For some external subsystems it might be possible to let the omap kernel
 manage
 powerdomains and other resource via remote proc interface, assuming these
 registers are ioremapped in the omap kernel side and not owned by the
 external
 subsystem. The messaging to do this would add some undesired latencies
 though,
 but maybe those would not be so critical for the external subsystems as
 they
 tend to be full on or completely off type accelerators.

 Humm. Maybe for some. Guess walking what is used and sorting might tell.

 The way some subsystems 'ideal' operation is described from designers implies 
 tight control of timing and sequence for things like power state. A RPC 
 doesn't feel like it fits with intent. However... practically speaking from 
 'full system view' RPC may fit sometimes. A subsystem exporting hooks to save 
 100uW using its optimal state set against other components running in 500mW 
 range minimizes usefulness.

 The other alternative of course is to implement similar frameworks for the
 external subsystems. Some of this might be possible to implement as simple
 macros with some type checks if it's subsystem specific. For doing it for
 all omap devices, macros were soon found not to be enough as the various
 bits all over need to be linked together for managing various resources.

 Agree.

 I don't know insides of all subsystems.  Though what I know or hear is kind 
 of a mixed picture.

 OMAP has an ultra high level of integration. As such you might find something 
 like DSP-Bios may provide a good hook but quick integration of a previously 
 standalone single purpose piece does not have time to be readapted.

 The type checking question kind of grows out of this.  Linux might today 
 offer a clean run-time api which is place where high wall should be built 
 with type check.  But... the driver might not be able to function yet with 
 the API alone given state of evolution of both ends.

Regarding the API and type checking I think the following must be enforced:
1. proper type checking in the API, possibly by the compiler,
2. clean separation of an API into an internal part (used only by the
framework implementation) and an external part (used by the callers of
the API).

About 1: using enum for the parameters did not help much AFACIT. The
compiler cannot tell if the parameter from a variable is in the
allowed range.
Any thought?

About 2: while introducing the functional power states I came across
this problem. Ideally the current states macros (PWRDM_POWER_* and
PWRSTS_*) shall be used by the internal code only in powerdomain*.[ch]
while the callers (pm.c etc) shall use the new macros
(PWRDM_FUNC_PWRST_*) and API (mainly pwrdm_*_func_* and
omap_set_pwrdm_state).

Here below is a patch extract (trimmed for brevity) to illustrate the problem.

From here is see a few possible options:
1. clearly separate the internal and external parts of the API in the
header file using comments (as done in the patch below) or with a new
#ifdef POWERDOMAIN_INTERNAL_API (ugly I know),
2. create a new internal only header file (powerdomain_internal.h) and
include it only from powerdomain*.[ch],
3. move the external API to pm.h and keep the internal API in powerdomain.h

Although I am using the func power states as an example I think this
is a applicable to all PM frameworks APIs.

What do you think?


diff --git a/arch/arm/mach-omap2/powerdomain.h

[PATCH v4 0/8] ARM: OMAP2+: PM: introduce the power domains functional states

2012-06-14 Thread Jean Pihet
Here is a re-spin after some comments after an internal review and some testing 
on
OMAP4 with device OFF support.

Implement the functional states for the power domains:
- unify the API to use the functional states,
- protect the power domain state change by a mutex in
  omap_set_pwrdm_state,
- introduce the functional states for power domains power states and
  logic power states, and the conversion functions between the
  functional and internal states,
- program the logic power state of power domains from the functional
  states, in omap_set_pwrdm_state
- convert the OMAP2/3/4 PM code to use the updated API,
- provide the power domains statistics by functional states,
- provide ftrace tracepoints with the functional state.

Based on mainline kernel 3.5.0-rc2.

Tested on OMAP3 Beagleboard, with suspend and cpuidle in RET and
OFF modes.


History:
 v4:
 - reworked the code after internal review and testing with OMAP34 device
   OFF,
 - fixed the tracepoints generation code,
 - introduce a function that returns power domains achievable functional
   states, in order to return a valid state for power domains that only
   support some of the power states. Although it has been tested OK the
   code is in RFC state.

 v3:
 - fix a bug in OMAP3 cpuidle which prevented the IO wake-ups in PER

 v2:
 - add the logic power states,
 - provide the power domains statistics by functional states

 v1:
 - initial implementation, in RFC state
 

Jean Pihet (8):
  ARM: OMAP2+: PM: protect the power domain state change by a mutex
  ARM: OMAP2+: PM: introduce power domains functional states
  ARM: OMAP2+: PM: use the functional power states API
  ARM: OMAP2+: PM: introduce power domains logic and memory functional
states
  ARM: OMAP2+: PM: introduce power domains achievable functional states
  ARM: OMAP2+: PM: use the functional power states API for logic and
memory
  ARM: OMAP2+: PM: use power domain functional state in stats counters
  ARM: OMAP2+: PM debug: trace the functional power domains states

 arch/arm/mach-omap2/cpuidle34xx.c  |   61 +++---
 arch/arm/mach-omap2/cpuidle44xx.c  |   28 +--
 arch/arm/mach-omap2/omap-hotplug.c |2 +-
 arch/arm/mach-omap2/omap-mpuss-lowpower.c  |   39 ++--
 arch/arm/mach-omap2/pm-debug.c |   15 +-
 arch/arm/mach-omap2/pm.c   |   62 -
 arch/arm/mach-omap2/pm.h   |1 -
 arch/arm/mach-omap2/pm24xx.c   |   15 +-
 arch/arm/mach-omap2/pm34xx.c   |   78 +++---
 arch/arm/mach-omap2/pm44xx.c   |   18 +-
 arch/arm/mach-omap2/powerdomain-common.c   |  100 
 arch/arm/mach-omap2/powerdomain.c  |  367 ++--
 arch/arm/mach-omap2/powerdomain.h  |  101 ++--
 arch/arm/mach-omap2/powerdomain2xxx_3xxx.c |7 +
 arch/arm/mach-omap2/powerdomain44xx.c  |3 +
 15 files changed, 653 insertions(+), 244 deletions(-)

-- 
1.7.7.6

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


[PATCH 1/8] ARM: OMAP2+: PM: protect the power domain state change by a mutex

2012-06-14 Thread Jean Pihet
omap_set_pwrdm_state is intented to be the only API for changing
a power domain state.
This patch protects the power domains settings and structs from
concurrent accesses to the function by using a mutex.

Signed-off-by: Jean Pihet j-pi...@ti.com
---
 arch/arm/mach-omap2/pm.c  |8 ++--
 arch/arm/mach-omap2/powerdomain.c |1 +
 arch/arm/mach-omap2/powerdomain.h |3 ++-
 3 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
index 9cb5ced..a05f00c 100644
--- a/arch/arm/mach-omap2/pm.c
+++ b/arch/arm/mach-omap2/pm.c
@@ -100,15 +100,17 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 
pwrst)
if (!pwrdm || IS_ERR(pwrdm))
return -EINVAL;
 
+   mutex_lock(pwrdm-lock);
+
while (!(pwrdm-pwrsts  (1  pwrst))) {
if (pwrst == PWRDM_POWER_OFF)
-   return ret;
+   goto out;
pwrst--;
}
 
next_pwrst = pwrdm_read_next_pwrst(pwrdm);
if (next_pwrst == pwrst)
-   return ret;
+   goto out;
 
curr_pwrst = pwrdm_read_pwrst(pwrdm);
if (curr_pwrst  PWRDM_POWER_ON) {
@@ -141,6 +143,8 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 
pwrst)
break;
}
 
+out:
+   mutex_unlock(pwrdm-lock);
return ret;
 }
 
diff --git a/arch/arm/mach-omap2/powerdomain.c 
b/arch/arm/mach-omap2/powerdomain.c
index 9611490..1641e72 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -102,6 +102,7 @@ static int _pwrdm_register(struct powerdomain *pwrdm)
INIT_LIST_HEAD(pwrdm-voltdm_node);
voltdm_add_pwrdm(voltdm, pwrdm);
 
+   mutex_init(pwrdm-lock);
list_add(pwrdm-node, pwrdm_list);
 
/* Initialize the powerdomain's state counter */
diff --git a/arch/arm/mach-omap2/powerdomain.h 
b/arch/arm/mach-omap2/powerdomain.h
index 8f88d65..bab84fc 100644
--- a/arch/arm/mach-omap2/powerdomain.h
+++ b/arch/arm/mach-omap2/powerdomain.h
@@ -19,7 +19,7 @@
 
 #include linux/types.h
 #include linux/list.h
-
+#include linux/mutex.h
 #include linux/atomic.h
 
 #include plat/cpu.h
@@ -116,6 +116,7 @@ struct powerdomain {
struct clockdomain *pwrdm_clkdms[PWRDM_MAX_CLKDMS];
struct list_head node;
struct list_head voltdm_node;
+   struct mutex lock;
int state;
unsigned state_counter[PWRDM_MAX_PWRSTS];
unsigned ret_logic_off_counter;
-- 
1.7.7.6

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


[PATCH 2/8] ARM: OMAP2+: PM: introduce power domains functional states

2012-06-14 Thread Jean Pihet
Introduce functional (or logical) states for power domains and the
API functions to read the power domains settings and to convert
between the functional (i.e. logical) and the internal (or registers)
values.

OMAP2, OMAP3 and OMAP4 platforms are defining a conversion routine.

In the new API only the function omap_set_pwrdm_state shall be used
to change a power domain target state, along with the associated
PWRDM_FUNC_* macros as the state parameters.
While at it the function is moved to the power domains code.

The power domain API in powerdomain.h is split in the external and the
internal parts; only the external API functions and defines shall be used
by external code, the internal API is only to be used in powerdomain*.[ch]
files.

The memory and logic states are not using the functional states, this
comes as a subsequent patch.

Signed-off-by: Jean Pihet j-pi...@ti.com
---
 arch/arm/mach-omap2/pm.c   |   66 ---
 arch/arm/mach-omap2/pm.h   |1 -
 arch/arm/mach-omap2/powerdomain-common.c   |   71 +++
 arch/arm/mach-omap2/powerdomain.c  |  174 
 arch/arm/mach-omap2/powerdomain.h  |   77 +
 arch/arm/mach-omap2/powerdomain2xxx_3xxx.c |5 +
 arch/arm/mach-omap2/powerdomain44xx.c  |2 +
 7 files changed, 306 insertions(+), 90 deletions(-)

diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
index a05f00c..dfe702b 100644
--- a/arch/arm/mach-omap2/pm.c
+++ b/arch/arm/mach-omap2/pm.c
@@ -74,10 +74,6 @@ static void __init omap2_init_processor_devices(void)
}
 }
 
-/* Types of sleep_switch used in omap_set_pwrdm_state */
-#define FORCEWAKEUP_SWITCH 0
-#define LOWPOWERSTATE_SWITCH   1
-
 int __init omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused)
 {
if (clkdm-flags  CLKDM_CAN_ENABLE_AUTO)
@@ -89,68 +85,6 @@ int __init omap_pm_clkdms_setup(struct clockdomain *clkdm, 
void *unused)
 }
 
 /*
- * This sets pwrdm state (other than mpu  core. Currently only ON 
- * RET are supported.
- */
-int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 pwrst)
-{
-   u8 curr_pwrst, next_pwrst;
-   int sleep_switch = -1, ret = 0, hwsup = 0;
-
-   if (!pwrdm || IS_ERR(pwrdm))
-   return -EINVAL;
-
-   mutex_lock(pwrdm-lock);
-
-   while (!(pwrdm-pwrsts  (1  pwrst))) {
-   if (pwrst == PWRDM_POWER_OFF)
-   goto out;
-   pwrst--;
-   }
-
-   next_pwrst = pwrdm_read_next_pwrst(pwrdm);
-   if (next_pwrst == pwrst)
-   goto out;
-
-   curr_pwrst = pwrdm_read_pwrst(pwrdm);
-   if (curr_pwrst  PWRDM_POWER_ON) {
-   if ((curr_pwrst  pwrst) 
-   (pwrdm-flags  PWRDM_HAS_LOWPOWERSTATECHANGE)) {
-   sleep_switch = LOWPOWERSTATE_SWITCH;
-   } else {
-   hwsup = clkdm_in_hwsup(pwrdm-pwrdm_clkdms[0]);
-   clkdm_wakeup(pwrdm-pwrdm_clkdms[0]);
-   sleep_switch = FORCEWAKEUP_SWITCH;
-   }
-   }
-
-   ret = pwrdm_set_next_pwrst(pwrdm, pwrst);
-   if (ret)
-   pr_err(%s: unable to set power state of powerdomain: %s\n,
-  __func__, pwrdm-name);
-
-   switch (sleep_switch) {
-   case FORCEWAKEUP_SWITCH:
-   if (hwsup)
-   clkdm_allow_idle(pwrdm-pwrdm_clkdms[0]);
-   else
-   clkdm_sleep(pwrdm-pwrdm_clkdms[0]);
-   break;
-   case LOWPOWERSTATE_SWITCH:
-   pwrdm_set_lowpwrstchange(pwrdm);
-   pwrdm_wait_transition(pwrdm);
-   pwrdm_state_switch(pwrdm);
-   break;
-   }
-
-out:
-   mutex_unlock(pwrdm-lock);
-   return ret;
-}
-
-
-
-/*
  * This API is to be called during init to set the various voltage
  * domains to the voltage as per the opp table. Typically we boot up
  * at the nominal voltage. So this function finds out the rate of
diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
index 7856489..5bc0848 100644
--- a/arch/arm/mach-omap2/pm.h
+++ b/arch/arm/mach-omap2/pm.h
@@ -18,7 +18,6 @@
 extern void *omap3_secure_ram_storage;
 extern void omap3_pm_off_mode_enable(int);
 extern void omap_sram_idle(void);
-extern int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state);
 extern int omap3_idle_init(void);
 extern int omap4_idle_init(void);
 extern int omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused);
diff --git a/arch/arm/mach-omap2/powerdomain-common.c 
b/arch/arm/mach-omap2/powerdomain-common.c
index c0aeabf..2973be7 100644
--- a/arch/arm/mach-omap2/powerdomain-common.c
+++ b/arch/arm/mach-omap2/powerdomain-common.c
@@ -108,3 +108,74 @@ u32 omap2_pwrdm_get_mem_bank_stst_mask(u8 bank)
return 0;
 }
 
+/**
+ * omap2_pwrdm_func_to_pwrst - Convert functional (i.e. logical) to
+ * internal (i.e. registers) values

[PATCH 3/8] ARM: OMAP2+: PM: use the functional power states API

2012-06-14 Thread Jean Pihet
Use the functional power states as the API to control power domains.
The omap_set_pwrdm_state function shall be used instead of
pwrdm_set_next_pwrst to control the power domains next states.

Note: the internal code for power domains state management still
uses the internal power states.

Signed-off-by: Jean Pihet j-pi...@ti.com
---
 arch/arm/mach-omap2/cpuidle34xx.c |   61 +++---
 arch/arm/mach-omap2/cpuidle44xx.c |   25 +-
 arch/arm/mach-omap2/omap-hotplug.c|2 +-
 arch/arm/mach-omap2/omap-mpuss-lowpower.c |   43 +---
 arch/arm/mach-omap2/pm24xx.c  |   10 ++--
 arch/arm/mach-omap2/pm34xx.c  |   78 +++--
 arch/arm/mach-omap2/pm44xx.c  |8 ++--
 arch/arm/mach-omap2/powerdomain.c |2 +-
 8 files changed, 119 insertions(+), 110 deletions(-)

diff --git a/arch/arm/mach-omap2/cpuidle34xx.c 
b/arch/arm/mach-omap2/cpuidle34xx.c
index 207bc1c..ef8d7d4 100644
--- a/arch/arm/mach-omap2/cpuidle34xx.c
+++ b/arch/arm/mach-omap2/cpuidle34xx.c
@@ -46,32 +46,32 @@ struct omap3_idle_statedata {
 
 static struct omap3_idle_statedata omap3_idle_data[] = {
{
-   .mpu_state = PWRDM_POWER_ON,
-   .core_state = PWRDM_POWER_ON,
+   .mpu_state = PWRDM_FUNC_PWRST_ON,
+   .core_state = PWRDM_FUNC_PWRST_ON,
},
{
-   .mpu_state = PWRDM_POWER_ON,
-   .core_state = PWRDM_POWER_ON,
+   .mpu_state = PWRDM_FUNC_PWRST_ON,
+   .core_state = PWRDM_FUNC_PWRST_ON,
},
{
-   .mpu_state = PWRDM_POWER_RET,
-   .core_state = PWRDM_POWER_ON,
+   .mpu_state = PWRDM_FUNC_PWRST_CSWR,
+   .core_state = PWRDM_FUNC_PWRST_ON,
},
{
-   .mpu_state = PWRDM_POWER_OFF,
-   .core_state = PWRDM_POWER_ON,
+   .mpu_state = PWRDM_FUNC_PWRST_OFF,
+   .core_state = PWRDM_FUNC_PWRST_ON,
},
{
-   .mpu_state = PWRDM_POWER_RET,
-   .core_state = PWRDM_POWER_RET,
+   .mpu_state = PWRDM_FUNC_PWRST_CSWR,
+   .core_state = PWRDM_FUNC_PWRST_CSWR,
},
{
-   .mpu_state = PWRDM_POWER_OFF,
-   .core_state = PWRDM_POWER_RET,
+   .mpu_state = PWRDM_FUNC_PWRST_OFF,
+   .core_state = PWRDM_FUNC_PWRST_CSWR,
},
{
-   .mpu_state = PWRDM_POWER_OFF,
-   .core_state = PWRDM_POWER_OFF,
+   .mpu_state = PWRDM_FUNC_PWRST_OFF,
+   .core_state = PWRDM_FUNC_PWRST_OFF,
},
 };
 
@@ -100,8 +100,8 @@ static int __omap3_enter_idle(struct cpuidle_device *dev,
 
local_fiq_disable();
 
-   pwrdm_set_next_pwrst(mpu_pd, mpu_state);
-   pwrdm_set_next_pwrst(core_pd, core_state);
+   omap_set_pwrdm_state(mpu_pd, mpu_state);
+   omap_set_pwrdm_state(core_pd, core_state);
 
if (omap_irq_pending() || need_resched())
goto return_sleep_time;
@@ -116,7 +116,7 @@ static int __omap3_enter_idle(struct cpuidle_device *dev,
 * Call idle CPU PM enter notifier chain so that
 * VFP context is saved.
 */
-   if (mpu_state == PWRDM_POWER_OFF)
+   if (mpu_state == PWRDM_FUNC_PWRST_OFF)
cpu_pm_enter();
 
/* Execute ARM wfi */
@@ -126,7 +126,7 @@ static int __omap3_enter_idle(struct cpuidle_device *dev,
 * Call idle CPU PM enter notifier chain to restore
 * VFP context.
 */
-   if (pwrdm_read_prev_pwrst(mpu_pd) == PWRDM_POWER_OFF)
+   if (pwrdm_read_prev_func_pwrst(mpu_pd) == PWRDM_FUNC_PWRST_OFF)
cpu_pm_exit();
 
/* Re-allow idle for C1 */
@@ -175,20 +175,20 @@ static int next_valid_state(struct cpuidle_device *dev,
struct cpuidle_driver *drv, int index)
 {
struct omap3_idle_statedata *cx = omap3_idle_data[index];
-   u32 mpu_deepest_state = PWRDM_POWER_RET;
-   u32 core_deepest_state = PWRDM_POWER_RET;
+   u32 mpu_deepest_state = PWRDM_FUNC_PWRST_CSWR;
+   u32 core_deepest_state = PWRDM_FUNC_PWRST_CSWR;
int idx;
int next_index = -1;
 
if (enable_off_mode) {
-   mpu_deepest_state = PWRDM_POWER_OFF;
+   mpu_deepest_state = PWRDM_FUNC_PWRST_OFF;
/*
 * Erratum i583: valable for ES rev  Es1.2 on 3630.
 * CORE OFF mode is not supported in a stable form, restrict
 * instead the CORE state to RET.
 */
if (!IS_PM34XX_ERRATUM(PM_SDRC_WAKEUP_ERRATUM_i583))
-   core_deepest_state = PWRDM_POWER_OFF;
+   core_deepest_state = PWRDM_FUNC_PWRST_OFF;
}
 
/* Check if current state is valid */
@@ -232,7 +232,7 @@ static int omap3_enter_idle_bm(struct cpuidle_device

[PATCH 5/8] ARM: OMAP2+: PM: introduce power domains achievable functional states

2012-06-14 Thread Jean Pihet
Note: the patch is in RFC state because the state machine for setting
the next power domain states needs more discussion. Validated on OMAP34
with cpuidle and suspend/resume, though.

Power domains have varied capabilities. When attempting a low power
state such as OFF/RET, a specific min requested state may not be
supported on the power domain. This is because a combination
of system power states where the parent PD's state is not in line
with expectation can result in system instabilities.

This patch provides a function that returns the achievable functional
power state for a power domain and its use by omap_set_pwrdm_state.
The achievable power state is first looked for in the lower power
states in order to maximize the power savings, then if not found
in the higher power states.

Inspired from Tero's work on OMAP4 device OFF support and generalized
to the functional power states.

Signed-off-by: Jean Pihet j-pi...@ti.com
Cc: Tero Kristo t-kri...@ti.com
---
 arch/arm/mach-omap2/powerdomain.c |  156 +++--
 arch/arm/mach-omap2/powerdomain.h |1 +
 2 files changed, 134 insertions(+), 23 deletions(-)

diff --git a/arch/arm/mach-omap2/powerdomain.c 
b/arch/arm/mach-omap2/powerdomain.c
index ce2685a..f94174b 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -554,6 +554,108 @@ int pwrdm_pwrst_to_func(struct powerdomain *pwrdm, u8 
pwrst, u8 logic)
return ret;
 }
 
+/**
+ * pwrdm_get_achievable_func_pwrst() - Provide achievable functional state
+ * @pwrdm: struct powerdomain * to set
+ * @func_pwrst: minimum functional state we would like to hit
+ * (one of the PWRDM_FUNC_* macros)
+ *
+ * Power domains have varied capabilities. When attempting a low power
+ * state such as OFF/RET, a specific min requested state may not be
+ * supported on the power domain. This is because a combination
+ * of system power states where the parent PD's state is not in line
+ * with expectation can result in system instabilities.
+ *
+ * The achievable power state is first looked for in the lower power
+ * states in order to maximize the power savings, then if not found
+ * in the higher power states.
+ *
+ * Returns the achievable functional power state, or -EINVAL in case of
+ * invalid parameters.
+ */
+int pwrdm_get_achievable_func_pwrst(struct powerdomain *pwrdm, u8 func_pwrst)
+{
+   int pwrst = pwrdm_func_to_pwrst(pwrdm, func_pwrst);
+   int logic = pwrdm_func_to_logic_pwrst(pwrdm, func_pwrst);
+   int new_func_pwrst, new_pwrst, new_logic;
+   int found;
+
+   if (!pwrdm || IS_ERR(pwrdm)) {
+   pr_debug(%s: invalid params: pwrdm=%p, func_pwrst=%0x\n,
+__func__, pwrdm, func_pwrst);
+   return -EINVAL;
+   }
+
+   if ((pwrst  0) || (logic  0)) {
+   pr_debug(%s: invalid params for pwrdm %s, func_pwrst=%0x\n,
+__func__, pwrdm-name, func_pwrst);
+   return PWRDM_FUNC_PWRST_ON;
+   }
+
+   /*
+* Power state: if the requested state is not supported,
+* try the lower power states.
+*/
+   found = 1;
+   new_pwrst = pwrst;
+   while (!(pwrdm-pwrsts  (1  new_pwrst))) {
+   if (new_pwrst == PWRDM_POWER_OFF) {
+   found = 0;
+   break;
+   }
+   new_pwrst--;
+   }
+
+   /*
+* If no lower power state found, fallback to the higher
+* power states.
+* PWRDM_POWER_ON is always valid.
+*/
+   if (!found) {
+   new_pwrst = pwrst;
+   while (!(pwrdm-pwrsts  (1  new_pwrst))) {
+   if (new_pwrst == PWRDM_POWER_ON)
+   break;
+   new_pwrst++;
+   }
+   }
+
+   /*
+* Logic RET state: if the requested state is not supported,
+* try the lower logic states.
+*/
+   found = 1;
+   new_logic = logic;
+   while (!(pwrdm-pwrsts_logic_ret  (1  new_logic))) {
+   if (new_logic == PWRDM_LOGIC_MEM_PWRST_OFF) {
+   found = 0;
+   break;
+   }
+   new_logic--;
+   }
+
+   /*
+* If no lower logic state found, fallback to the higher
+* logic states.
+* PWRDM_LOGIC_MEM_PWRST_RET is always valid.
+*/
+   if (!found) {
+   new_logic = logic;
+   while (!(pwrdm-pwrsts_logic_ret  (1  new_logic))) {
+   if (new_logic == PWRDM_LOGIC_MEM_PWRST_RET)
+   break;
+   new_logic++;
+   }
+   }
+
+   new_func_pwrst = pwrdm_pwrst_to_func(pwrdm, new_pwrst, new_logic);
+
+   pr_debug(%s(%s, func_pwrst=%0x) returns %0x\n, __func__,
+pwrdm-name, func_pwrst, new_func_pwrst);
+
+   return new_func_pwrst

[PATCH 6/8] ARM: OMAP2+: PM: use the functional power states API for logic and memory

2012-06-14 Thread Jean Pihet
Since the power domains logic state is derived from the power domain
functional state and is now programmed from omap_set_pwrdm_state,
the calls to pwrdm_set_logic_retst are removed and the mpu_logic_state
field is removed from the private data of the cpuidle and suspend code.

Signed-off-by: Jean Pihet j-pi...@ti.com
---
 arch/arm/mach-omap2/cpuidle44xx.c |   11 ++-
 arch/arm/mach-omap2/omap-mpuss-lowpower.c |6 +-
 arch/arm/mach-omap2/pm24xx.c  |5 +
 arch/arm/mach-omap2/pm44xx.c  |   10 ++
 4 files changed, 6 insertions(+), 26 deletions(-)

diff --git a/arch/arm/mach-omap2/cpuidle44xx.c 
b/arch/arm/mach-omap2/cpuidle44xx.c
index 50c9082..221039a 100644
--- a/arch/arm/mach-omap2/cpuidle44xx.c
+++ b/arch/arm/mach-omap2/cpuidle44xx.c
@@ -27,7 +27,6 @@
 /* Machine specific information */
 struct omap4_idle_statedata {
u32 cpu_state;
-   u32 mpu_logic_state;
u32 mpu_state;
 };
 
@@ -35,17 +34,14 @@ static struct omap4_idle_statedata omap4_idle_data[] = {
{
.cpu_state = PWRDM_FUNC_PWRST_ON,
.mpu_state = PWRDM_FUNC_PWRST_ON,
-   .mpu_logic_state = PWRDM_POWER_RET,
},
{
.cpu_state = PWRDM_FUNC_PWRST_OFF,
.mpu_state = PWRDM_FUNC_PWRST_CSWR,
-   .mpu_logic_state = PWRDM_POWER_RET,
},
{
.cpu_state = PWRDM_FUNC_PWRST_OFF,
-   .mpu_state = PWRDM_FUNC_PWRST_CSWR,
-   .mpu_logic_state = PWRDM_POWER_OFF,
+   .mpu_state = PWRDM_FUNC_PWRST_OSWR,
},
 };
 
@@ -95,16 +91,13 @@ static int omap4_enter_idle(struct cpuidle_device *dev,
if (cx-cpu_state == PWRDM_FUNC_PWRST_OFF)
cpu_pm_enter();
 
-   pwrdm_set_logic_retst(mpu_pd, cx-mpu_logic_state);
omap_set_pwrdm_state(mpu_pd, cx-mpu_state);
 
/*
 * Call idle CPU cluster PM enter notifier chain
 * to save GIC and wakeupgen context.
 */
-   if (((cx-mpu_state == PWRDM_FUNC_PWRST_CSWR) ||
-(cx-mpu_state == PWRDM_FUNC_PWRST_OSWR)) 
-   (cx-mpu_logic_state == PWRDM_POWER_OFF))
+   if (cx-mpu_state == PWRDM_FUNC_PWRST_OSWR)
cpu_cluster_pm_enter();
 
omap4_enter_lowpower(dev-cpu, cx-cpu_state);
diff --git a/arch/arm/mach-omap2/omap-mpuss-lowpower.c 
b/arch/arm/mach-omap2/omap-mpuss-lowpower.c
index dd94a0e..c79cc0f 100644
--- a/arch/arm/mach-omap2/omap-mpuss-lowpower.c
+++ b/arch/arm/mach-omap2/omap-mpuss-lowpower.c
@@ -232,7 +232,6 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int 
power_state)
 {
unsigned int save_state = 0;
unsigned int wakeup_cpu;
-   int mpuss_state;
 
if (omap_rev() == OMAP4430_REV_ES1_0)
return -ENXIO;
@@ -265,10 +264,7 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int 
power_state)
 * In MPUSS OSWR or device OFF, interrupt controller context is lost.
 */
mpuss_clear_prev_logic_pwrst();
-   mpuss_state = pwrdm_read_next_func_pwrst(mpuss_pd);
-   if (((mpuss_state == PWRDM_FUNC_PWRST_CSWR) ||
-(mpuss_state == PWRDM_FUNC_PWRST_OSWR)) 
-   (pwrdm_read_logic_retst(mpuss_pd) == PWRDM_POWER_OFF))
+   if (pwrdm_read_next_func_pwrst(mpuss_pd) == PWRDM_FUNC_PWRST_OSWR)
save_state = 2;
 
cpu_clear_prev_logic_pwrst(cpu);
diff --git a/arch/arm/mach-omap2/pm24xx.c b/arch/arm/mach-omap2/pm24xx.c
index 0bed51e..fdb0767 100644
--- a/arch/arm/mach-omap2/pm24xx.c
+++ b/arch/arm/mach-omap2/pm24xx.c
@@ -93,7 +93,6 @@ static int omap2_enter_full_retention(void)
 * Set MPU powerdomain's next power state to RETENTION;
 * preserve logic state during retention
 */
-   pwrdm_set_logic_retst(mpu_pwrdm, PWRDM_POWER_RET);
omap_set_pwrdm_state(mpu_pwrdm, PWRDM_FUNC_PWRST_CSWR);
 
/* Workaround to kill USB */
@@ -248,7 +247,7 @@ static void __init prcm_setup_regs(void)
 */
num_mem_banks = pwrdm_get_mem_bank_count(core_pwrdm);
for (i = 0; i  num_mem_banks; i++)
-   pwrdm_set_mem_retst(core_pwrdm, i, PWRDM_POWER_RET);
+   pwrdm_set_mem_retst(core_pwrdm, i, PWRDM_LOGIC_MEM_PWRST_RET);
 
/* Set CORE powerdomain's next power state to RETENTION */
omap_set_pwrdm_state(core_pwrdm, PWRDM_FUNC_PWRST_CSWR);
@@ -257,11 +256,9 @@ static void __init prcm_setup_regs(void)
 * Set MPU powerdomain's next power state to RETENTION;
 * preserve logic state during retention
 */
-   pwrdm_set_logic_retst(mpu_pwrdm, PWRDM_POWER_RET);
omap_set_pwrdm_state(mpu_pwrdm, PWRDM_FUNC_PWRST_CSWR);
 
/* Force-power down DSP, GFX powerdomains */
-
pwrdm = clkdm_get_pwrdm(dsp_clkdm);
omap_set_pwrdm_state(pwrdm, PWRDM_FUNC_PWRST_OFF);
clkdm_sleep(dsp_clkdm);
diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2

[PATCH 4/8] ARM: OMAP2+: PM: introduce power domains logic and memory functional states

2012-06-14 Thread Jean Pihet
In the new API the functions pwrdm_*_logic_* and pwrdm_*_mem_* take the
functional states as parameter.

OMAP2, OMAP3 and OMAP4 platforms are defining a conversion routine
between the functional state and the logic power state.

The power domains logic state is now derived from the functional
state and the logic state is programmed from omap_set_pwrdm_state.

Signed-off-by: Jean Pihet j-pi...@ti.com
---
 arch/arm/mach-omap2/powerdomain-common.c   |   41 --
 arch/arm/mach-omap2/powerdomain.c  |   79 +--
 arch/arm/mach-omap2/powerdomain.h  |   22 +++-
 arch/arm/mach-omap2/powerdomain2xxx_3xxx.c |2 +
 arch/arm/mach-omap2/powerdomain44xx.c  |1 +
 5 files changed, 118 insertions(+), 27 deletions(-)

diff --git a/arch/arm/mach-omap2/powerdomain-common.c 
b/arch/arm/mach-omap2/powerdomain-common.c
index 2973be7..1ae3659 100644
--- a/arch/arm/mach-omap2/powerdomain-common.c
+++ b/arch/arm/mach-omap2/powerdomain-common.c
@@ -143,6 +143,36 @@ int omap2_pwrdm_func_to_pwrst(struct powerdomain *pwrdm, 
u8 func_pwrst)
 }
 
 /**
+ * omap2_pwrdm_func_to_logic_pwrst - Convert functional (i.e. logical) to
+ * internal (i.e. registers) values for the power domains logic states.
+ * @struct powerdomain * to convert the values for
+ * @func_pwrst: functional power state
+ *
+ * Returns the internal logic state value for the power domain, or
+ * -EINVAL in case of invalid parameters passed in.
+ */
+int omap2_pwrdm_func_to_logic_pwrst(struct powerdomain *pwrdm, u8 func_pwrst)
+{
+   int ret;
+
+   switch (func_pwrst) {
+   case PWRDM_FUNC_PWRST_ON:
+   case PWRDM_FUNC_PWRST_INACTIVE:
+   case PWRDM_FUNC_PWRST_CSWR:
+   ret = PWRDM_LOGIC_MEM_PWRST_RET;
+   break;
+   case PWRDM_FUNC_PWRST_OSWR:
+   case PWRDM_FUNC_PWRST_OFF:
+   ret = PWRDM_LOGIC_MEM_PWRST_OFF;
+   break;
+   default:
+   ret = -EINVAL;
+   }
+
+   return ret;
+}
+
+/**
  * omap2_pwrdm_pwrst_to_func - Convert internal (i.e. registers) to
  * functional (i.e. logical) values for the power domains states.
  * @struct powerdomain * to convert the values for
@@ -151,7 +181,7 @@ int omap2_pwrdm_func_to_pwrst(struct powerdomain *pwrdm, u8 
func_pwrst)
  * Returns the functional power state value for the power domain, or
  * -EINVAL in case of invalid parameters passed in.
  */
-int omap2_pwrdm_pwrst_to_func(struct powerdomain *pwrdm, u8 pwrst)
+int omap2_pwrdm_pwrst_to_func(struct powerdomain *pwrdm, u8 pwrst, u8 logic)
 {
int ret;
 
@@ -163,11 +193,10 @@ int omap2_pwrdm_pwrst_to_func(struct powerdomain *pwrdm, 
u8 pwrst)
ret = PWRDM_FUNC_PWRST_INACTIVE;
break;
case PWRDM_POWER_RET:
-   /*
-* XXX warning: return OSWR in case of pd in RET and
-* logic in OFF
-*/
-   ret = PWRDM_FUNC_PWRST_CSWR;
+   if (logic == PWRDM_LOGIC_MEM_PWRST_RET)
+   ret = PWRDM_FUNC_PWRST_CSWR;
+   else
+   ret = PWRDM_FUNC_PWRST_OSWR;
break;
case PWRDM_POWER_OFF:
ret = PWRDM_FUNC_PWRST_OFF;
diff --git a/arch/arm/mach-omap2/powerdomain.c 
b/arch/arm/mach-omap2/powerdomain.c
index ec2b21c..ce2685a 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -129,14 +129,14 @@ static void _update_logic_membank_counters(struct 
powerdomain *pwrdm)
 
prev_logic_pwrst = pwrdm_read_prev_logic_pwrst(pwrdm);
if ((pwrdm-pwrsts_logic_ret == PWRSTS_OFF_RET) 
-   (prev_logic_pwrst == PWRDM_POWER_OFF))
+   (prev_logic_pwrst == PWRDM_LOGIC_MEM_PWRST_OFF))
pwrdm-ret_logic_off_counter++;
 
for (i = 0; i  pwrdm-banks; i++) {
prev_mem_pwrst = pwrdm_read_prev_mem_pwrst(pwrdm, i);
 
if ((pwrdm-pwrsts_mem_ret[i] == PWRSTS_OFF_RET) 
-   (prev_mem_pwrst == PWRDM_POWER_OFF))
+   (prev_mem_pwrst == PWRDM_LOGIC_MEM_PWRST_OFF))
pwrdm-ret_mem_off_counter[i]++;
}
 }
@@ -493,27 +493,63 @@ int pwrdm_func_to_pwrst(struct powerdomain *pwrdm, u8 
func_pwrst)
 }
 
 /**
+ * pwrdm_func_to_logic_pwrst - get the internal (i.e. registers) value
+ * of the logic state mapped to the functional state
+ * @pwrdm: struct powerdomain * to query
+ * @func_pwrst: functional power state
+ *
+ * Convert the functional power state to the platform specific power
+ * domain logic state value.
+ * Returns the internal power domain logic state value or -EINVAL in
+ * case of invalid parameters passed in.
+ */
+int pwrdm_func_to_logic_pwrst(struct powerdomain *pwrdm, u8 func_pwrst)
+{
+   int ret = func_pwrst;
+
+   if ((!pwrdm) || (func_pwrst = PWRDM_MAX_FUNC_PWRSTS))
+   return -EINVAL;
+
+   if (arch_pwrdm  arch_pwrdm-pwrdm_func_to_logic_pwrst

[PATCH 8/8] ARM: OMAP2+: PM debug: trace the functional power domains states

2012-06-14 Thread Jean Pihet
Trace the power domain transitions using the functional power states,
which include the power and logic states.

While at it, fix the trace in the case a power domain did not hit
the desired state, as reported by Paul Walmsley.

Reported-by: Paul Walmsley p...@pwsan.com
Signed-off-by: Jean Pihet j-pi...@ti.com
---
 arch/arm/mach-omap2/powerdomain.c |   15 +--
 1 files changed, 5 insertions(+), 10 deletions(-)

diff --git a/arch/arm/mach-omap2/powerdomain.c 
b/arch/arm/mach-omap2/powerdomain.c
index 875c6c4..f6885f9 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -144,7 +144,7 @@ static void _update_logic_membank_counters(struct 
powerdomain *pwrdm)
 static int _pwrdm_state_switch(struct powerdomain *pwrdm, int flag)
 {
 
-   int prev, state, trace_state = 0;
+   int prev, next, state, trace_state;
 
if (pwrdm == NULL)
return -EINVAL;
@@ -165,10 +165,10 @@ static int _pwrdm_state_switch(struct powerdomain *pwrdm, 
int flag)
 * If the power domain did not hit the desired state,
 * generate a trace event with both the desired and hit states
 */
-   if (state != prev) {
+   next = pwrdm_read_next_func_pwrst(pwrdm);
+   if (next != prev) {
trace_state = (PWRDM_TRACE_STATES_FLAG |
-  ((state  OMAP_POWERSTATE_MASK)  8) |
-  ((prev  OMAP_POWERSTATE_MASK)  0));
+  (next  8) | (prev  0));
trace_power_domain_target(pwrdm-name, trace_state,
  smp_processor_id());
}
@@ -768,13 +768,8 @@ int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 
pwrst)
pr_debug(powerdomain: setting next powerstate for %s to %0x\n,
 pwrdm-name, pwrst);
 
-   if (arch_pwrdm  arch_pwrdm-pwrdm_set_next_pwrst) {
-   /* Trace the pwrdm desired target state */
-   trace_power_domain_target(pwrdm-name, pwrst,
- smp_processor_id());
-   /* Program the pwrdm desired target state */
+   if (arch_pwrdm  arch_pwrdm-pwrdm_set_next_pwrst)
ret = arch_pwrdm-pwrdm_set_next_pwrst(pwrdm, pwrst);
-   }
 
return ret;
 }
-- 
1.7.7.6

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


[PATCH 7/8] ARM: OMAP2+: PM: use power domain functional state in stats counters

2012-06-14 Thread Jean Pihet
The PM code uses some counters to keep track of the power domains
transitions, in order to provide the information to drivers (in
pwrdm_get_context_loss_count) and to expose the information to
sysfs for debug purpose.

This patch provides the information for each functional state.

Signed-off-by: Jean Pihet j-pi...@ti.com
---
 arch/arm/mach-omap2/pm-debug.c|   15 ---
 arch/arm/mach-omap2/powerdomain.c |   12 ++--
 arch/arm/mach-omap2/powerdomain.h |4 ++--
 3 files changed, 16 insertions(+), 15 deletions(-)

diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c
index 814bcd9..13c00fb 100644
--- a/arch/arm/mach-omap2/pm-debug.c
+++ b/arch/arm/mach-omap2/pm-debug.c
@@ -53,9 +53,10 @@ enum {
DEBUG_FILE_TIMERS,
 };
 
-static const char pwrdm_state_names[][PWRDM_MAX_PWRSTS] = {
+static const char pwrdm_state_names[][PWRDM_MAX_FUNC_PWRSTS] = {
OFF,
-   RET,
+   OSWR,
+   CSWR,
INA,
ON
 };
@@ -102,13 +103,13 @@ static int pwrdm_dbg_show_counter(struct powerdomain 
*pwrdm, void *user)
strncmp(pwrdm-name, dpll, 4) == 0)
return 0;
 
-   if (pwrdm-state != pwrdm_read_pwrst(pwrdm))
+   if (pwrdm-state != pwrdm_read_func_pwrst(pwrdm))
printk(KERN_ERR pwrdm state mismatch(%s) %d != %d\n,
-   pwrdm-name, pwrdm-state, pwrdm_read_pwrst(pwrdm));
+  pwrdm-name, pwrdm-state, pwrdm_read_func_pwrst(pwrdm));
 
seq_printf(s, %s (%s), pwrdm-name,
pwrdm_state_names[pwrdm-state]);
-   for (i = 0; i  PWRDM_MAX_PWRSTS; i++)
+   for (i = 0; i  PWRDM_MAX_FUNC_PWRSTS; i++)
seq_printf(s, ,%s:%d, pwrdm_state_names[i],
pwrdm-state_counter[i]);
 
@@ -137,7 +138,7 @@ static int pwrdm_dbg_show_timer(struct powerdomain *pwrdm, 
void *user)
seq_printf(s, %s (%s), pwrdm-name,
pwrdm_state_names[pwrdm-state]);
 
-   for (i = 0; i  4; i++)
+   for (i = 0; i  PWRDM_MAX_FUNC_PWRSTS; i++)
seq_printf(s, ,%s:%lld, pwrdm_state_names[i],
pwrdm-state_timer[i]);
 
@@ -211,7 +212,7 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, 
void *dir)
 
t = sched_clock();
 
-   for (i = 0; i  4; i++)
+   for (i = 0; i  PWRDM_MAX_FUNC_PWRSTS; i++)
pwrdm-state_timer[i] = 0;
 
pwrdm-timer = t;
diff --git a/arch/arm/mach-omap2/powerdomain.c 
b/arch/arm/mach-omap2/powerdomain.c
index f94174b..875c6c4 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -106,7 +106,7 @@ static int _pwrdm_register(struct powerdomain *pwrdm)
list_add(pwrdm-node, pwrdm_list);
 
/* Initialize the powerdomain's state counter */
-   for (i = 0; i  PWRDM_MAX_PWRSTS; i++)
+   for (i = 0; i  PWRDM_MAX_FUNC_PWRSTS; i++)
pwrdm-state_counter[i] = 0;
 
pwrdm-ret_logic_off_counter = 0;
@@ -114,7 +114,7 @@ static int _pwrdm_register(struct powerdomain *pwrdm)
pwrdm-ret_mem_off_counter[i] = 0;
 
pwrdm_wait_transition(pwrdm);
-   pwrdm-state = pwrdm_read_pwrst(pwrdm);
+   pwrdm-state = pwrdm_read_func_pwrst(pwrdm);
pwrdm-state_counter[pwrdm-state] = 1;
 
pr_debug(powerdomain: registered %s\n, pwrdm-name);
@@ -149,17 +149,17 @@ static int _pwrdm_state_switch(struct powerdomain *pwrdm, 
int flag)
if (pwrdm == NULL)
return -EINVAL;
 
-   state = pwrdm_read_pwrst(pwrdm);
+   state = pwrdm_read_func_pwrst(pwrdm);
 
switch (flag) {
case PWRDM_STATE_NOW:
prev = pwrdm-state;
break;
case PWRDM_STATE_PREV:
-   prev = pwrdm_read_prev_pwrst(pwrdm);
+   prev = pwrdm_read_prev_func_pwrst(pwrdm);
if (pwrdm-state != prev)
pwrdm-state_counter[prev]++;
-   if (prev == PWRDM_POWER_RET)
+   if (prev == PWRDM_FUNC_PWRST_OSWR)
_update_logic_membank_counters(pwrdm);
/*
 * If the power domain did not hit the desired state,
@@ -1338,7 +1338,7 @@ int pwrdm_get_context_loss_count(struct powerdomain 
*pwrdm)
return -ENODEV;
}
 
-   count = pwrdm-state_counter[PWRDM_POWER_OFF];
+   count = pwrdm-state_counter[PWRDM_FUNC_PWRST_OFF];
count += pwrdm-ret_logic_off_counter;
 
for (i = 0; i  pwrdm-banks; i++)
diff --git a/arch/arm/mach-omap2/powerdomain.h 
b/arch/arm/mach-omap2/powerdomain.h
index 9dd68ab..06fb396 100644
--- a/arch/arm/mach-omap2/powerdomain.h
+++ b/arch/arm/mach-omap2/powerdomain.h
@@ -165,13 +165,13 @@ struct powerdomain {
struct list_head voltdm_node;
struct mutex lock;
int state;
-   unsigned state_counter[PWRDM_MAX_PWRSTS];
+   unsigned state_counter[PWRDM_MAX_FUNC_PWRSTS];
unsigned

[PATCH v8 00/10] PM QoS: implement the OMAP low level constraints management code

2012-06-14 Thread Jean Pihet
. Implement the devices wake-up latency constraints using the global
  device PM QoS notification handler which applies the constraints to the
  underlying layer,
. Implement the low level code which controls the power domains next
  functional power states, through the hwmod and pwrdm layers,
. Include a fix for the cpuidle code to always return a valid C-state,
. Add cpuidle and power domains wake-up latency figures for OMAP3, cf. 
  comments in the code and [1] for the details on where the numbers
  are magically coming from,
. Implement the relation between the cpuidle and per-device PM QoS frameworks
  in the OMAP3 specific idle callbacks.
  The chosen C-state shall satisfy the following conditions:
   . it satisfies the enable_off_mode flag,
   . the next state for MPU and CORE power domains is not lower than the
 state programmed by the per-device PM QoS.
. convert I2C driver to PM QoS for latency constraints,
. remove the latency related functions from the API (omap_pm_set_*) and
  update the kernel Documentation accordingly.


ToDo:
1. Re-visit the OMAP power domains states initialization procedure. Currently
   the power states that have been changed from the constraints API which were
   applied before the initialization of the power domains are lost
2. Further clean-up the OMAP PM layer, use the generic frameworks instead (OPP,
   PM QoS for throughput constraints ...)

Note: the following commits are required and so are included in this series,
 although they are planned for inclusion into mainline via the linux-omap tree:
  . ARM: OMAP2+: hwmod: manage the wake-up latency constraints
  . ARM: OMAP3: PM: cpuidle: default to C1 in next_valid_state


Based on mainline kernel 3.5.0-rc2 with the functional power states changes
applied.

Tested cpuidle and suspend on OMAP3 Beagleboard (ES2.x) with constraints
on MPU, CORE, PER in RETention and OFF modes.

[1] http://www.omappedia.org/wiki/Power_Management_Device_Latencies_Measurement


History:
v8:
. reworked the code after internal review and testing with OMAP34 device
   OFF

v7:
. rebased on top of the functional power state changes

v6:
. minor change in the commits description after Kevin's review
. added Kevin's Reviewed-by

v5:
. rebased on latest linux-omap
. rework after Kevin's comments on the MLs

v4:
. split up the patches which remove the omap_pm_ code from the patch set.
  Those patches are to be submitted later, on top of this patch set.
. latency numbers: provide the measurements setup and conditions in the code
  comments, added the link to the details on wiki [1].
. improved kerneldoc
. split big functions into smaller ones, in order to improve the readability

v3: reworked the error return path and improved the kerneldoc

v2: reworked the OMAP specific cpuidle code to demote the initial C-state to
 a valid C-state which fulfills the per-device constraints

v1: initial version


Jean Pihet (10):
  ARM: OMAP2+: PM QoS: control the power domains next state from the
constraints
  ARM: OMAP2+: hwmod: manage the wake-up latency constraints
  ARM: OMAP2+: PM QoS: manage the per-device latency constraints in
hwmod
  ARM: OMAP: omap_device: register to the per-device PM QoS framework
  ARM: OMAP3: cpuidle: next C-state decision depends on the PM QoS MPU
and CORE constraints
  ARM: OMAP3: PM: cpuidle: default to C1 in next_valid_state
  ARM: OMAP3: update cpuidle latency and threshold figures
  ARM: OMAP3: powerdomain data: add wake-up latency figures
  ARM: OMAP: convert I2C driver to PM QoS for latency constraints
  ARM: OMAP: PM: remove the latency related functions from the API

 Documentation/arm/OMAP/omap_pm   |   68 +++--
 arch/arm/mach-omap2/cpuidle34xx.c|  124 ++-
 arch/arm/mach-omap2/omap_hwmod.c |   44 +-
 arch/arm/mach-omap2/powerdomain.c|  215 ++
 arch/arm/mach-omap2/powerdomain.h|   18 ++
 arch/arm/mach-omap2/powerdomains3xxx_data.c  |   83 ++
 arch/arm/plat-omap/i2c.c |   21 ---
 arch/arm/plat-omap/include/plat/omap-pm.h|   99 
 arch/arm/plat-omap/include/plat/omap_hwmod.h |5 +
 arch/arm/plat-omap/omap-pm-noop.c|   88 ---
 arch/arm/plat-omap/omap_device.c |   81 ++-
 drivers/i2c/busses/i2c-omap.c|   28 ++--
 include/linux/i2c-omap.h |1 -
 13 files changed, 563 insertions(+), 312 deletions(-)

-- 
1.7.7.6

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


[PATCH 02/10] ARM: OMAP2+: hwmod: manage the wake-up latency constraints

2012-06-14 Thread Jean Pihet
The OMAP PM code implements a handler for the per-device PM QoS framework.
The handler queries the omap_hwmod layer in order to manage the power domains
wake-up latency constraints. Hwmod retrieves the correct power domain
and if it exists it calls the corresponding power domain function.

Tested on OMAP3 Beagleboard and OMAP4 Pandaboard in RET/OFF using wake-up
latency constraints on MPU, CORE and PER.

Signed-off-by: Jean Pihet j-pi...@ti.com
Reviewed-by: Kevin Hilman khil...@ti.com
[p...@pwsan.com: cleaned some documentation; split set/remove constraint
 functions; modified to return -EINVAL until underlying code is ready]
Signed-off-by: Paul Walmsley p...@pwsan.com
---
 arch/arm/mach-omap2/omap_hwmod.c |   54 +-
 arch/arm/plat-omap/include/plat/omap_hwmod.h |5 ++
 2 files changed, 58 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index bf86f7e..cc173d9 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -145,6 +145,7 @@
 #include powerdomain.h
 #include plat/clock.h
 #include plat/omap_hwmod.h
+#include plat/omap_device.h
 #include plat/prcm.h
 
 #include cm2xxx_3xxx.h
@@ -3301,10 +3302,61 @@ ohsps_unlock:
 }
 
 /**
+ * omap_hwmod_set_wakeuplat_constraint - set/release a wake-up latency
+ * constraint
+ * @oh: struct omap_hwmod* to which the target device belongs to.
+ * @cookie: identifier of the constraints list for @oh.
+ * @min_latency: the minimum allowed wake-up latency for @oh.
+ *
+ * Sets a wakeup latency contraint.  (To remove a wakeup latency
+ * constraint, call omap_hwmod_remove_wakeuplat_constraint()).
+ * Returns the return value from pwrdm_wakeuplat_remove_constraint(),
+ * or -EINVAL in case of invalid parameters.
+ */
+int omap_hwmod_set_wakeuplat_constraint(struct omap_hwmod *oh, void *cookie,
+   long min_latency)
+{
+   struct powerdomain *pwrdm = omap_hwmod_get_pwrdm(oh);
+
+   if (!pwrdm)
+   return -EINVAL;
+
+   /*
+* XXX Update to use pwrdm_wakeuplat_update_constraint() when
+* that code is ready
+*/
+   return -EINVAL;
+}
+
+/**
+ * omap_hwmod_remove_wakeuplat_constraint - release a wake-up latency
+ * constraint
+ * @oh: struct omap_hwmod* to which the target device belongs to.
+ * @cookie: identifier of the constraints list for @oh.
+ *
+ * Removes a wakeup latency contraint.  Returns the return value from
+ * pwrdm_wakeuplat_update_constraint(), or -EINVAL in case of invalid
+ * parameters.
+ */
+int omap_hwmod_remove_wakeuplat_constraint(struct omap_hwmod *oh, void *cookie)
+{
+   struct powerdomain *pwrdm = omap_hwmod_get_pwrdm(oh);
+
+   if (!pwrdm)
+   return -EINVAL;
+
+   /*
+* XXX Update to use pwrdm_wakeuplat_remove_constraint() when
+* that code is ready
+*/
+   return -EINVAL;
+}
+
+/**
  * omap_hwmod_get_context_loss_count - get lost context count
  * @oh: struct omap_hwmod *
  *
- * Query the powerdomain of of @oh to get the context loss
+ * Query the powerdomain of @oh to get the context loss
  * count for this device.
  *
  * Returns the context loss count of the powerdomain assocated with @oh
diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h 
b/arch/arm/plat-omap/include/plat/omap_hwmod.h
index c835b71..3aa10df 100644
--- a/arch/arm/plat-omap/include/plat/omap_hwmod.h
+++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h
@@ -623,6 +623,11 @@ int omap_hwmod_for_each_by_class(const char *classname,
 void *user);
 
 int omap_hwmod_set_postsetup_state(struct omap_hwmod *oh, u8 state);
+
+int omap_hwmod_set_wakeuplat_constraint(struct omap_hwmod *oh, void *cookie,
+   long min_latency);
+int omap_hwmod_remove_wakeuplat_constraint(struct omap_hwmod *oh, void 
*cookie);
+
 int omap_hwmod_get_context_loss_count(struct omap_hwmod *oh);
 
 int omap_hwmod_no_setup_reset(struct omap_hwmod *oh);
-- 
1.7.7.6

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


[PATCH 04/10] ARM: OMAP: omap_device: register to the per-device PM QoS framework

2012-06-14 Thread Jean Pihet
Implement the devices wake-up latency constraints using the global
device PM QoS notification handler which applies the constraints to the
underlying layer by calling the corresponding function at hwmod level.

Tested on OMAP3 Beagleboard and OMAP4 Pandaboard in RET/OFF using wake-up
latency constraints on MPU, CORE and PER.

Signed-off-by: Jean Pihet j-pi...@ti.com
Reviewed-by: Kevin Hilman khil...@ti.com
[p...@pwsan.com: modified to work with omap_devices with large numbers of
 hwmods; moved code to mach-omap2/omap_device.c; added documentation; use
 notifier return codes]
Signed-off-by: Paul Walmsley p...@pwsan.com
---
 arch/arm/plat-omap/omap_device.c |   81 +-
 1 files changed, 80 insertions(+), 1 deletions(-)

diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c
index c490240..241705b 100644
--- a/arch/arm/plat-omap/omap_device.c
+++ b/arch/arm/plat-omap/omap_device.c
@@ -3,6 +3,7 @@
  * omap_device implementation
  *
  * Copyright (C) 2009-2010 Nokia Corporation
+ * Copyright (C) 2011 Texas Instruments, Inc.
  * Paul Walmsley, Kevin Hilman
  *
  * Developed in collaboration with (alphabetical order): Benoit
@@ -89,6 +90,7 @@
 #include linux/pm_runtime.h
 #include linux/of.h
 #include linux/notifier.h
+#include linux/pm_qos.h
 
 #include plat/omap_device.h
 #include plat/omap_hwmod.h
@@ -401,6 +403,72 @@ static int _omap_device_notifier_call(struct 
notifier_block *nb,
return NOTIFY_DONE;
 }
 
+/**
+ * _omap_device_pm_qos_handler - interface to the per-device PM QoS framework
+ * @nb: pointer to omap_device_pm_qos_nb (not used)
+ * @new_value: new maximum wakeup latency constraint for @req-dev (in us)
+ * @req: struct dev_pm_qos_request * passed by the Linux PM QoS code
+ *
+ * Called by the Linux core device PM QoS code to alter the maximum
+ * wakeup latency constraint on a device.  If the underlying device is
+ * an omap_device, then this code will pass the constraint on to the
+ * underlying hwmods.  Returns -EINVAL if this code can't handle the
+ * constraint for some reason, or passes along the return code from the
+ * hwmod wakeup latency constraint functions.
+ */
+static int _omap_device_pm_qos_handler(struct notifier_block *nb,
+  unsigned long new_value,
+  void *req)
+{
+   struct omap_device *od;
+   struct omap_hwmod *oh;
+   struct platform_device *pdev;
+   struct dev_pm_qos_request *dev_pm_qos_req = req;
+   int ret = NOTIFY_OK;
+   int r, i;
+
+   pr_debug(OMAP PM constraints: req@0x%p, new_value=%lu\n,
+req, new_value);
+
+   /* Look for the platform device for the constraint target device */
+   pdev = to_platform_device(dev_pm_qos_req-dev);
+
+   /* Try to catch non platform devices */
+   if (pdev-name == NULL) {
+   pr_err(%s: Error: platform device for device %s not valid\n,
+  __func__, dev_name(dev_pm_qos_req-dev));
+   return NOTIFY_DONE;
+   }
+
+   /* Find the associated omap_device for dev */
+   od = to_omap_device(pdev);
+   if (od == NULL) {
+   pr_err(%s: Error: no omap_device for device %s\n,
+  __func__, dev_name(dev_pm_qos_req-dev));
+   return NOTIFY_DONE;
+   }
+
+   pr_debug(OMAP PM constraints: req@0x%p, dev=0x%p, new_value=%lu\n,
+req, dev_pm_qos_req-dev, new_value);
+
+   for (i = 0; i  od-hwmods_cnt; i++) {
+   oh = od-hwmods[i];
+   if (new_value == PM_QOS_DEV_LAT_DEFAULT_VALUE)
+   r = omap_hwmod_remove_wakeuplat_constraint(
+   oh,
+   dev_pm_qos_req);
+   else
+   r = omap_hwmod_set_wakeuplat_constraint(
+   oh,
+   dev_pm_qos_req,
+   new_value);
+
+   if (!r)
+   ret = NOTIFY_BAD;
+   }
+
+   return ret;
+}
 
 /* Public functions for use by core code */
 
@@ -1115,13 +1183,24 @@ int omap_device_enable_clocks(struct omap_device *od)
return 0;
 }
 
+static struct notifier_block omap_device_pm_qos_nb = {
+   .notifier_call = _omap_device_pm_qos_handler,
+};
+
 static struct notifier_block platform_nb = {
.notifier_call = _omap_device_notifier_call,
 };
 
 static int __init omap_device_init(void)
 {
+   int ret;
+
bus_register_notifier(platform_bus_type, platform_nb);
-   return 0;
+
+   ret = dev_pm_qos_add_global_notifier(omap_device_pm_qos_nb);
+   if (ret)
+   pr_err(omap_device: cannot add global notifier for dev PM 
QoS\n);
+
+   return ret;
 }
 core_initcall(omap_device_init);
-- 
1.7.7.6

[PATCH 03/10] ARM: OMAP2+: PM QoS: manage the per-device latency constraints in hwmod

2012-06-14 Thread Jean Pihet
Call the per-device PM QoS functions of the power domain code from the
hwmod layer, in order to apply the constraints requested to a device.

While at it, correct the functions kerneldoc.

Signed-off-by: Jean Pihet j-pi...@ti.com
---
 arch/arm/mach-omap2/omap_hwmod.c |   22 ++
 1 files changed, 6 insertions(+), 16 deletions(-)

diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index cc173d9..4f43e0c 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -3302,15 +3302,13 @@ ohsps_unlock:
 }
 
 /**
- * omap_hwmod_set_wakeuplat_constraint - set/release a wake-up latency
+ * omap_hwmod_set_wakeuplat_constraint - Set or update a wake-up latency
  * constraint
  * @oh: struct omap_hwmod* to which the target device belongs to.
  * @cookie: identifier of the constraints list for @oh.
  * @min_latency: the minimum allowed wake-up latency for @oh.
  *
- * Sets a wakeup latency contraint.  (To remove a wakeup latency
- * constraint, call omap_hwmod_remove_wakeuplat_constraint()).
- * Returns the return value from pwrdm_wakeuplat_remove_constraint(),
+ * Returns the return value from pwrdm_wakeuplat_update_constraint(),
  * or -EINVAL in case of invalid parameters.
  */
 int omap_hwmod_set_wakeuplat_constraint(struct omap_hwmod *oh, void *cookie,
@@ -3321,21 +3319,17 @@ int omap_hwmod_set_wakeuplat_constraint(struct 
omap_hwmod *oh, void *cookie,
if (!pwrdm)
return -EINVAL;
 
-   /*
-* XXX Update to use pwrdm_wakeuplat_update_constraint() when
-* that code is ready
-*/
-   return -EINVAL;
+   return pwrdm_wakeuplat_update_constraint(pwrdm, cookie, min_latency);
 }
 
 /**
- * omap_hwmod_remove_wakeuplat_constraint - release a wake-up latency
+ * omap_hwmod_remove_wakeuplat_constraint - Release a wake-up latency
  * constraint
  * @oh: struct omap_hwmod* to which the target device belongs to.
  * @cookie: identifier of the constraints list for @oh.
  *
  * Removes a wakeup latency contraint.  Returns the return value from
- * pwrdm_wakeuplat_update_constraint(), or -EINVAL in case of invalid
+ * pwrdm_wakeuplat_remove_constraint(), or -EINVAL in case of invalid
  * parameters.
  */
 int omap_hwmod_remove_wakeuplat_constraint(struct omap_hwmod *oh, void *cookie)
@@ -3345,11 +3339,7 @@ int omap_hwmod_remove_wakeuplat_constraint(struct 
omap_hwmod *oh, void *cookie)
if (!pwrdm)
return -EINVAL;
 
-   /*
-* XXX Update to use pwrdm_wakeuplat_remove_constraint() when
-* that code is ready
-*/
-   return -EINVAL;
+   return pwrdm_wakeuplat_remove_constraint(pwrdm, cookie);
 }
 
 /**
-- 
1.7.7.6

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


[PATCH 01/10] ARM: OMAP2+: PM QoS: control the power domains next state from the constraints

2012-06-14 Thread Jean Pihet
When a PM QoS device latency constraint is requested or removed the
constraint is stored in the constraints list of the corresponding power
domain, then the aggregated constraint value is applied by programming
the next functional power state using omap_set_pwrdm_state.

Tested on OMAP3 Beagleboard and OMAP4 Pandaboard in RET/OFF using
wake-up latency constraints on MPU, CORE and PER.

Signed-off-by: Jean Pihet j-pi...@ti.com
---
 arch/arm/mach-omap2/powerdomain.c |  215 +
 arch/arm/mach-omap2/powerdomain.h |   18 +++
 2 files changed, 233 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/powerdomain.c 
b/arch/arm/mach-omap2/powerdomain.c
index f6885f9..82797c2 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -17,8 +17,10 @@
 #include linux/kernel.h
 #include linux/types.h
 #include linux/list.h
+#include linux/slab.h
 #include linux/errno.h
 #include linux/string.h
+#include linux/pm_qos.h
 #include trace/events/power.h
 
 #include cm2xxx_3xxx.h
@@ -113,6 +115,12 @@ static int _pwrdm_register(struct powerdomain *pwrdm)
for (i = 0; i  pwrdm-banks; i++)
pwrdm-ret_mem_off_counter[i] = 0;
 
+   /* Initialize the per-device wake-up constraints framework data */
+   mutex_init(pwrdm-wkup_lat_plist_lock);
+   plist_head_init(pwrdm-wkup_lat_plist_head);
+   pwrdm-wkup_lat_next_state = PWRDM_FUNC_PWRST_OFF;
+
+   /* Initialize the pwrdm state */
pwrdm_wait_transition(pwrdm);
pwrdm-state = pwrdm_read_func_pwrst(pwrdm);
pwrdm-state_counter[pwrdm-state] = 1;
@@ -200,6 +208,58 @@ static int _pwrdm_post_transition_cb(struct powerdomain 
*pwrdm, void *unused)
return 0;
 }
 
+/**
+ * _pwrdm_wakeuplat_update_pwrst - Update power domain power state if needed
+ * @pwrdm: struct powerdomain * to which requesting device belongs to.
+ * @min_latency: the allowed wake-up latency for the given power domain. A
+ *  value of PM_QOS_DEV_LAT_DEFAULT_VALUE means 'no constraint' on the pwrdm.
+ *
+ * Finds the power domain next power state that fulfills the constraint.
+ * Programs a new target state if it is different from current power state.
+ * The power domains get the next power state programmed directly in the
+ * registers.
+ *
+ * Returns 0 in case of success, -EINVAL in case of invalid parameters,
+ * or the return value from omap_set_pwrdm_state.
+ */
+static int _pwrdm_wakeuplat_update_pwrst(struct powerdomain *pwrdm,
+long min_latency)
+{
+   int ret = 0, state, new_state = PWRDM_FUNC_PWRST_ON;
+
+   if (!pwrdm) {
+   WARN(1, powerdomain: %s: invalid parameter(s), __func__);
+   return -EINVAL;
+   }
+
+   /*
+* Find the next supported power state with
+*  wakeup latency = min_latency.
+* Pick the lower state if no constraint on the pwrdm
+*  (min_latency == PM_QOS_DEV_LAT_DEFAULT_VALUE).
+* Skip the states marked as unsupported (UNSUP_STATE).
+* If no power state found, fall back to PWRDM_FUNC_PWRST_ON.
+*/
+   for (state = 0x0; state  PWRDM_MAX_FUNC_PWRSTS; state++) {
+   if ((min_latency == PM_QOS_DEV_LAT_DEFAULT_VALUE) ||
+   ((pwrdm-wakeup_lat[state] != UNSUP_STATE) 
+(pwrdm-wakeup_lat[state] = min_latency))) {
+   new_state = state;
+   break;
+   }
+   }
+
+   pwrdm-wkup_lat_next_state = new_state;
+   ret = omap_set_pwrdm_state(pwrdm, new_state);
+
+   pr_debug(%s: func pwrst for %s: curr=%d, next=%d, min_latency=%ld, 
new_state=%d\n,
+__func__, pwrdm-name, pwrdm_read_func_pwrst(pwrdm),
+pwrdm_read_next_func_pwrst(pwrdm), min_latency, new_state);
+
+   return ret;
+}
+
+
 /* Public functions */
 
 /**
@@ -1317,6 +1377,161 @@ int pwrdm_post_transition(void)
 }
 
 /**
+ * pwrdm_wakeuplat_update_constraint - Set or update a powerdomain wakeup
+ *  latency constraint and apply it
+ * @pwrdm: struct powerdomain * which the constraint applies to
+ * @cookie: constraint identifier, used for tracking
+ * @min_latency: minimum wakeup latency constraint (in microseconds) for
+ *  the given pwrdm
+ *
+ * Tracks the constraints by @cookie.
+ * Constraint set/update: Adds a new entry to powerdomain's wake-up latency
+ * constraint list. If the constraint identifier already exists in the list,
+ * the old value is overwritten.
+ *
+ * Applies the aggregated constraint value for the given pwrdm by calling
+ * _pwrdm_wakeuplat_update_pwrst.
+ *
+ * Returns 0 upon success, -ENOMEM in case of memory shortage, -EINVAL in
+ * case of invalid latency value, or the return value from
+ * _pwrdm_wakeuplat_update_pwrst.
+ *
+ * The caller must check the validity of the parameters.
+ */
+int pwrdm_wakeuplat_update_constraint(struct powerdomain *pwrdm, void *cookie

[PATCH 06/10] ARM: OMAP3: PM: cpuidle: default to C1 in next_valid_state

2012-06-14 Thread Jean Pihet
If the next state is no found in the next_valid_state function,
fallback to the default value of C1 (which is state 0).
This prevents the use of a bogus state -1 in the rest of the cpuidle
code.

Signed-off-by: Jean Pihet j-pi...@ti.com
---
 arch/arm/mach-omap2/cpuidle34xx.c |8 +---
 1 files changed, 1 insertions(+), 7 deletions(-)

diff --git a/arch/arm/mach-omap2/cpuidle34xx.c 
b/arch/arm/mach-omap2/cpuidle34xx.c
index 1f33b8e..9319f94 100644
--- a/arch/arm/mach-omap2/cpuidle34xx.c
+++ b/arch/arm/mach-omap2/cpuidle34xx.c
@@ -186,7 +186,7 @@ static int next_valid_state(struct cpuidle_device *dev,
u32 mpu_pm_qos_next_state = mpu_pd-wkup_lat_next_state;
u32 core_pm_qos_next_state = core_pd-wkup_lat_next_state;
int idx;
-   int next_index = -1;
+   int next_index = 0; /* C1 is the default value */
 
if (enable_off_mode) {
mpu_deepest_state = PWRDM_FUNC_PWRST_OFF;
@@ -221,12 +221,6 @@ static int next_valid_state(struct cpuidle_device *dev,
}
}
 
-   /*
-* C1 is always valid.
-* So, no need to check for 'next_index == -1' outside
-* this loop.
-*/
-
return next_index;
 }
 
-- 
1.7.7.6

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


[PATCH 07/10] ARM: OMAP3: update cpuidle latency and threshold figures

2012-06-14 Thread Jean Pihet
Update the data from the measurements performed at HW and SW levels.

Cf. http://www.omappedia.org/wiki/Power_Management_Device_Latencies_Measurement
for a detailed explanation on where are the numbers coming from.

ToDo:
- Measure the wake-up latencies for all power domains for OMAP3
- Correct some numbers when sys_clkreq and sys_offmode are supported

Signed-off-by: Jean Pihet j-pi...@ti.com
Reviewed-by: Kevin Hilman khil...@ti.com
---
 arch/arm/mach-omap2/cpuidle34xx.c |   52 +++--
 1 files changed, 38 insertions(+), 14 deletions(-)

diff --git a/arch/arm/mach-omap2/cpuidle34xx.c 
b/arch/arm/mach-omap2/cpuidle34xx.c
index 9319f94..9438385 100644
--- a/arch/arm/mach-omap2/cpuidle34xx.c
+++ b/arch/arm/mach-omap2/cpuidle34xx.c
@@ -295,6 +295,30 @@ DEFINE_PER_CPU(struct cpuidle_device, omap3_idle_dev);
  *
  * - target_residency: required amount of time in the C state
  *  to break even on energy cost
+ *
+ * The MPU latency and threshold values for the C-states are the worst case
+ * values from the HW and SW, as described in details at
+ * 
http://www.omappedia.org/wiki/Power_Management_Device_Latencies_Measurement#cpuidle_results
+ *
+ * Measurements conditions and remarks:
+ *  . the measurements have been performed at OPP50
+ *  . the sys_offmode signal is not supported and so not used for the
+ *measurements. Instead the latency and threshold values for C9 are
+ *corrected with the value for Triton 2, which is 11.5ms
+ *  . the sys_clkreq signal is not used and so a correction is needed - TBD
+ *  . the sys_clkoff signal is supported, this value need to be corrected with
+ *the correct value of SYSCLK on/off timings (1ms for sysclk on, 2.5ms
+ *for sysclk off)
+ *  . the setup time of DPLLs is included in the measured values. However
+ *this is only valid for DPLLs that are enabled to auto-idle at
+ *measurement time. There currently is no provision for the dynamic
+ *nature of the auto-idle setting
+ *  . in order to force the cpuidle algorithm to chose the power efficient
+ *C-states (C1, C3, C5, C7) in preference, the other C-states have a
+ *threshold value equal to the next power efficient C-state
+ *
+ * The latency and threshold values can be overriden by data from the board
+ * files, using omap3_pm_init_cpuidle.
  */
 struct cpuidle_driver omap3_idle_driver = {
.name = omap3_idle,
@@ -302,56 +326,56 @@ struct cpuidle_driver omap3_idle_driver = {
.states = {
{
.enter= omap3_enter_idle,
-   .exit_latency = 2 + 2,
-   .target_residency = 5,
+   .exit_latency = 73 + 78,
+   .target_residency = 152,
.flags= CPUIDLE_FLAG_TIME_VALID,
.name = C1,
.desc = MPU ON + CORE ON,
},
{
.enter= omap3_enter_idle_bm,
-   .exit_latency = 10 + 10,
-   .target_residency = 30,
+   .exit_latency = 165 + 88,
+   .target_residency = 345,
.flags= CPUIDLE_FLAG_TIME_VALID,
.name = C2,
.desc = MPU ON + CORE ON,
},
{
.enter= omap3_enter_idle_bm,
-   .exit_latency = 50 + 50,
-   .target_residency = 300,
+   .exit_latency = 163 + 182,
+   .target_residency = 345,
.flags= CPUIDLE_FLAG_TIME_VALID,
.name = C3,
.desc = MPU RET + CORE ON,
},
{
.enter= omap3_enter_idle_bm,
-   .exit_latency = 1500 + 1800,
-   .target_residency = 4000,
+   .exit_latency = 2852 + 605,
+   .target_residency = 15,
.flags= CPUIDLE_FLAG_TIME_VALID,
.name = C4,
.desc = MPU OFF + CORE ON,
},
{
.enter= omap3_enter_idle_bm,
-   .exit_latency = 2500 + 7500,
-   .target_residency = 12000,
+   .exit_latency = 800 + 366,
+   .target_residency = 2120,
.flags= CPUIDLE_FLAG_TIME_VALID,
.name = C5,
.desc = MPU RET + CORE RET,
},
{
.enter

[PATCH 09/10] ARM: OMAP: convert I2C driver to PM QoS for latency constraints

2012-06-14 Thread Jean Pihet
Convert the driver from the outdated omap_pm_set_max_mpu_wakeup_lat
API to the new PM QoS API.
Since the constraint is on the MPU subsystem, use the PM_QOS_CPU_DMA_LATENCY
class of PM QoS. The resulting MPU constraints are used by cpuidle to
decide the next power state of the MPU subsystem.

The I2C device latency timing is derived from the FIFO size and the
clock speed and so is applicable to all OMAP SoCs.

Signed-off-by: Jean Pihet j-pi...@ti.com
---
 arch/arm/plat-omap/i2c.c  |   21 -
 drivers/i2c/busses/i2c-omap.c |   28 +---
 include/linux/i2c-omap.h  |1 -
 3 files changed, 17 insertions(+), 33 deletions(-)

diff --git a/arch/arm/plat-omap/i2c.c b/arch/arm/plat-omap/i2c.c
index db071bc..dba8338 100644
--- a/arch/arm/plat-omap/i2c.c
+++ b/arch/arm/plat-omap/i2c.c
@@ -26,7 +26,6 @@
 #include linux/kernel.h
 #include linux/platform_device.h
 #include linux/i2c.h
-#include linux/i2c-omap.h
 #include linux/slab.h
 #include linux/err.h
 #include linux/clk.h
@@ -34,7 +33,6 @@
 #include mach/irqs.h
 #include plat/mux.h
 #include plat/i2c.h
-#include plat/omap-pm.h
 #include plat/omap_device.h
 
 #define OMAP_I2C_SIZE  0x3f
@@ -129,16 +127,6 @@ static inline int omap1_i2c_add_bus(int bus_id)
 
 
 #ifdef CONFIG_ARCH_OMAP2PLUS
-/*
- * XXX This function is a temporary compatibility wrapper - only
- * needed until the I2C driver can be converted to call
- * omap_pm_set_max_dev_wakeup_lat() and handle a return code.
- */
-static void omap_pm_set_max_mpu_wakeup_lat_compat(struct device *dev, long t)
-{
-   omap_pm_set_max_mpu_wakeup_lat(dev, t);
-}
-
 static inline int omap2_i2c_add_bus(int bus_id)
 {
int l;
@@ -170,15 +158,6 @@ static inline int omap2_i2c_add_bus(int bus_id)
dev_attr = (struct omap_i2c_dev_attr *)oh-dev_attr;
pdata-flags = dev_attr-flags;
 
-   /*
-* When waiting for completion of a i2c transfer, we need to
-* set a wake up latency constraint for the MPU. This is to
-* ensure quick enough wakeup from idle, when transfer
-* completes.
-* Only omap3 has support for constraints
-*/
-   if (cpu_is_omap34xx())
-   pdata-set_mpu_wkup_lat = omap_pm_set_max_mpu_wakeup_lat_compat;
pdev = omap_device_build(name, bus_id, oh, pdata,
sizeof(struct omap_i2c_bus_platform_data),
NULL, 0, 0);
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index 801df60..72d7076 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -43,6 +43,7 @@
 #include linux/slab.h
 #include linux/i2c-omap.h
 #include linux/pm_runtime.h
+#include linux/pm_qos.h
 
 /* I2C controller revisions */
 #define OMAP_I2C_OMAP1_REV_2   0x20
@@ -183,8 +184,7 @@ struct omap_i2c_dev {
struct completion   cmd_complete;
struct resource *ioarea;
u32 latency;/* maximum mpu wkup latency */
-   void(*set_mpu_wkup_lat)(struct device *dev,
-   long latency);
+   struct pm_qos_request   pm_qos_request;
u32 speed;  /* Speed of bus in kHz */
u32 dtrev;  /* extra revision from DT */
u32 flags;
@@ -634,8 +634,16 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg 
msgs[], int num)
if (r  0)
goto out;
 
-   if (dev-set_mpu_wkup_lat != NULL)
-   dev-set_mpu_wkup_lat(dev-dev, dev-latency);
+   /*
+* When waiting for completion of a i2c transfer, we need to
+* set a wake up latency constraint for the MPU. This is to
+* ensure quick enough wakeup from idle, when transfer
+* completes.
+*/
+   if (dev-latency)
+   pm_qos_add_request(dev-pm_qos_request,
+  PM_QOS_CPU_DMA_LATENCY,
+  dev-latency);
 
for (i = 0; i  num; i++) {
r = omap_i2c_xfer_msg(adap, msgs[i], (i == (num - 1)));
@@ -643,8 +651,8 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg 
msgs[], int num)
break;
}
 
-   if (dev-set_mpu_wkup_lat != NULL)
-   dev-set_mpu_wkup_lat(dev-dev, -1);
+   if (dev-latency)
+   pm_qos_remove_request(dev-pm_qos_request);
 
if (r == 0)
r = num;
@@ -1032,7 +1040,6 @@ omap_i2c_probe(struct platform_device *pdev)
} else if (pdata != NULL) {
dev-speed = pdata-clkrate;
dev-flags = pdata-flags;
-   dev-set_mpu_wkup_lat = pdata-set_mpu_wkup_lat;
dev-dtrev = pdata-rev;
}
 
@@ -1081,10 +1088,9 @@ omap_i2c_probe(struct platform_device *pdev)
else
dev-b_hw = 1; /* Enable hardware

[PATCH 10/10] ARM: OMAP: PM: remove the latency related functions from the API

2012-06-14 Thread Jean Pihet
Remove the following functions from the OMAP PM API:
 omap_pm_set_max_mpu_wakeup_lat
 omap_pm_set_max_dev_wakeup_lat
 omap_pm_set_max_sdma_lat
and updated the kernel Documentation accordingly.

The generic per-device PM QoS functions shall be used instead of the
OMAP PM API, cf. include/linux/pm_qos.h and
Documentation/power/pm_qos_interface.txt.

Signed-off-by: Jean Pihet j-pi...@ti.com
---
 Documentation/arm/OMAP/omap_pm|   68 ++--
 arch/arm/plat-omap/include/plat/omap-pm.h |   99 -
 arch/arm/plat-omap/omap-pm-noop.c |   88 -
 3 files changed, 21 insertions(+), 234 deletions(-)

diff --git a/Documentation/arm/OMAP/omap_pm b/Documentation/arm/OMAP/omap_pm
index 9012bb0..90f67a3 100644
--- a/Documentation/arm/OMAP/omap_pm
+++ b/Documentation/arm/OMAP/omap_pm
@@ -5,8 +5,19 @@ The OMAP PM interface
 This document describes the temporary OMAP PM interface.  Driver
 authors use these functions to communicate minimum latency or
 throughput constraints to the kernel power management code.
+
 Over time, the intention is to merge features from the OMAP PM
 interface into the Linux PM QoS code.
+The following PM QoS features already migrated to the PM QoS framework:
+- PM QoS CPU and DMA latency: used to specify the maximum allowed wake-up
+  latency for the CPU,
+- per device PM QoS latency: used to specifiy the maximum allowed wake-up
+  latency for a given device.
+
+Please refer to the corresponding header file and kernel documentation
+for the PM QoS framework, respectively at include/linux/pm_qos.h and
+Documentation/power/pm_qos_interface.txt.
+
 
 Drivers need to express PM parameters which:
 
@@ -29,21 +40,12 @@ Drivers need to express PM parameters which:
 
 
 This document proposes the OMAP PM interface, including the following
-five power management functions for driver code:
-
-1. Set the maximum MPU wakeup latency:
-   (*pdata-set_max_mpu_wakeup_lat)(struct device *dev, unsigned long t)
+power management functions for driver code:
 
-2. Set the maximum device wakeup latency:
-   (*pdata-set_max_dev_wakeup_lat)(struct device *dev, unsigned long t)
-
-3. Set the maximum system DMA transfer start latency (CORE pwrdm):
-   (*pdata-set_max_sdma_lat)(struct device *dev, long t)
-
-4. Set the minimum bus throughput needed by a device:
+1. Set the minimum bus throughput needed by a device:
(*pdata-set_min_bus_tput)(struct device *dev, u8 agent_id, unsigned long r)
 
-5. Return the number of times the device has lost context
+2. Return the number of times the device has lost context
(*pdata-get_dev_context_loss_count)(struct device *dev)
 
 
@@ -55,10 +57,12 @@ The OMAP PM layer is intended to be temporary
 -
 
 The intention is that eventually the Linux PM QoS layer should support
-the range of power management features present in OMAP3.  As this
-happens, existing drivers using the OMAP PM interface can be modified
+the range of power management features present in OMAP3. As this
+happens, existing drivers using the OMAP PM interface shall be modified
 to use the Linux PM QoS code; and the OMAP PM interface can disappear.
 
+The set_min_bus_tput function shall be converted to a throughput PM QoS
+framework.
 
 Driver usage of the OMAP PM functions
 -
@@ -66,39 +70,9 @@ Driver usage of the OMAP PM functions
 As the 'pdata' in the above examples indicates, these functions are
 exposed to drivers through function pointers in driver .platform_data
 structures.  The function pointers are initialized by the board-*.c
-files to point to the corresponding OMAP PM functions:
-.set_max_dev_wakeup_lat will point to
-omap_pm_set_max_dev_wakeup_lat(), etc.  Other architectures which do
-not support these functions should leave these function pointers set
-to NULL.  Drivers should use the following idiom:
-
-if (pdata-set_max_dev_wakeup_lat)
-(*pdata-set_max_dev_wakeup_lat)(dev, t);
-
-The most common usage of these functions will probably be to specify
-the maximum time from when an interrupt occurs, to when the device
-becomes accessible.  To accomplish this, driver writers should use the
-set_max_mpu_wakeup_lat() function to to constrain the MPU wakeup
-latency, and the set_max_dev_wakeup_lat() function to constrain the
-device wakeup latency (from clk_enable() to accessibility).  For
-example,
-
-/* Limit MPU wakeup latency */
-if (pdata-set_max_mpu_wakeup_lat)
-(*pdata-set_max_mpu_wakeup_lat)(dev, tc);
-
-/* Limit device powerdomain wakeup latency */
-if (pdata-set_max_dev_wakeup_lat)
-(*pdata-set_max_dev_wakeup_lat)(dev, td);
-
-/* total wakeup latency in this example: (tc + td) */
-
-The PM parameters can be overwritten by calling the function again
-with the new value.  The settings can be removed by calling the
-function with a t argument of -1 (except

[PATCH 05/10] ARM: OMAP3: cpuidle: next C-state decision depends on the PM QoS MPU and CORE constraints

2012-06-14 Thread Jean Pihet
The MPU latency figures for cpuidle include the MPU itself and also
the peripherals needed for the MPU to execute instructions (e.g.
main memory, caches, IRQ controller, MMU etc). On OMAP3 those
peripherals belong to the MPU and CORE power domains and so the
cpuidle C-states are a combination of MPU and CORE states.

This patch implements the relation between the cpuidle and per-
device PM QoS frameworks in the OMAP3 specific idle callbacks.

The chosen C-state shall satisfy the following conditions:
 . the 'valid' field is enabled,
 . it satisfies the enable_off_mode flag,
 . the next state for MPU and CORE power domains is not lower than the
   next state calculated by the per-device PM QoS.

Tested on OMAP3 Beagleboard in RET/OFF using wake-up latency constraints
on MPU, CORE and PER.

Signed-off-by: Jean Pihet j-pi...@ti.com
Reviewed-by: Kevin Hilman khil...@ti.com
---
 arch/arm/mach-omap2/cpuidle34xx.c |   64 -
 1 files changed, 42 insertions(+), 22 deletions(-)

diff --git a/arch/arm/mach-omap2/cpuidle34xx.c 
b/arch/arm/mach-omap2/cpuidle34xx.c
index ef8d7d4..1f33b8e 100644
--- a/arch/arm/mach-omap2/cpuidle34xx.c
+++ b/arch/arm/mach-omap2/cpuidle34xx.c
@@ -92,8 +92,8 @@ static int _cpuidle_deny_idle(struct powerdomain *pwrdm,
 }
 
 static int __omap3_enter_idle(struct cpuidle_device *dev,
-   struct cpuidle_driver *drv,
-   int index)
+ struct cpuidle_driver *drv,
+ int index)
 {
struct omap3_idle_statedata *cx = omap3_idle_data[index];
u32 mpu_state = cx-mpu_state, core_state = cx-core_state;
@@ -150,10 +150,14 @@ return_sleep_time:
  *
  * Called from the CPUidle framework to program the device to the
  * specified target state selected by the governor.
+ *
+ * Note: this function does not check for any pending activity or dependency
+ * between power domains states, so the caller shall check the parameters
+ * correctness.
  */
 static inline int omap3_enter_idle(struct cpuidle_device *dev,
-   struct cpuidle_driver *drv,
-   int index)
+  struct cpuidle_driver *drv,
+  int index)
 {
return cpuidle_wrap_enter(dev, drv, index, __omap3_enter_idle);
 }
@@ -168,8 +172,10 @@ static inline int omap3_enter_idle(struct cpuidle_device 
*dev,
  * to the caller. Else, this function searches for a lower c-state which is
  * still valid (as defined in omap3_power_states[]) and returns its index.
  *
- * A state is valid if the 'valid' field is enabled and
- * if it satisfies the enable_off_mode condition.
+ * A state is valid if:
+ * . it satisfies the enable_off_mode flag,
+ * . the next state for MPU and CORE power domains is not lower than the
+ *   state programmed by the per-device PM QoS.
  */
 static int next_valid_state(struct cpuidle_device *dev,
struct cpuidle_driver *drv, int index)
@@ -177,6 +183,8 @@ static int next_valid_state(struct cpuidle_device *dev,
struct omap3_idle_statedata *cx = omap3_idle_data[index];
u32 mpu_deepest_state = PWRDM_FUNC_PWRST_CSWR;
u32 core_deepest_state = PWRDM_FUNC_PWRST_CSWR;
+   u32 mpu_pm_qos_next_state = mpu_pd-wkup_lat_next_state;
+   u32 core_pm_qos_next_state = core_pd-wkup_lat_next_state;
int idx;
int next_index = -1;
 
@@ -193,7 +201,9 @@ static int next_valid_state(struct cpuidle_device *dev,
 
/* Check if current state is valid */
if ((cx-mpu_state = mpu_deepest_state) 
-   (cx-core_state = core_deepest_state))
+   (cx-core_state = core_deepest_state) 
+   (cx-mpu_state = mpu_pm_qos_next_state) 
+   (cx-core_state = core_pm_qos_next_state))
return index;
 
/*
@@ -203,7 +213,9 @@ static int next_valid_state(struct cpuidle_device *dev,
for (idx = index - 1; idx = 0; idx--) {
cx =  omap3_idle_data[idx];
if ((cx-mpu_state = mpu_deepest_state) 
-   (cx-core_state = core_deepest_state)) {
+   (cx-core_state = core_deepest_state) 
+   (cx-mpu_state = mpu_pm_qos_next_state) 
+   (cx-core_state = core_pm_qos_next_state)) {
next_index = idx;
break;
}
@@ -224,12 +236,15 @@ static int next_valid_state(struct cpuidle_device *dev,
  * @drv: cpuidle driver
  * @index: array index of target state to be programmed
  *
- * This function checks for any pending activity and then programs
- * the device to the specified or a safer state.
+ * Called from the CPUidle framework to program the device to the
+ * specified target state selected by the governor.
+ *
+ * This function checks for any pending activity or dependency between
+ * power domains states and then programs

[PATCH 08/10] ARM: OMAP3: powerdomain data: add wake-up latency figures

2012-06-14 Thread Jean Pihet
Figures are added to the power domains structs for RET and OFF modes.

Note: the latency figures for MPU, PER, CORE, NEON have been obtained
from actual measurements.
The latency figures for the other power domains are preliminary and
shall be added.

Cf. http://www.omappedia.org/wiki/Power_Management_Device_Latencies_Measurement
for a detailed explanation on where are the numbers coming from.

Tested on OMAP3 Beagleboard in RET/OFF using wake-up latency constraints
on MPU, CORE and PER.

Signed-off-by: Jean Pihet j-pi...@ti.com
Reviewed-by: Kevin Hilman khil...@ti.com
---
 arch/arm/mach-omap2/powerdomains3xxx_data.c |   83 +++
 1 files changed, 83 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/powerdomains3xxx_data.c 
b/arch/arm/mach-omap2/powerdomains3xxx_data.c
index fb0a0a6..edc4199 100644
--- a/arch/arm/mach-omap2/powerdomains3xxx_data.c
+++ b/arch/arm/mach-omap2/powerdomains3xxx_data.c
@@ -32,6 +32,19 @@
 
 /*
  * Powerdomains
+ *
+ * The wakeup_lat values are derived from HW and SW measurements on
+ * the actual target. For more details cf.
+ * 
http://www.omappedia.org/wiki/Power_Management_Device_Latencies_Measurement#Results_for_individual_power_domains
+ *
+ * Note: the latency figures for MPU, PER, CORE, NEON have been obtained
+ * from actual measurements.
+ * The latency figures for the other power domains are preliminary and
+ * shall be added.
+ *
+ * Note: only the SW restore timing values are taken into account.
+ * The HW impact of the sys_clkreq and sys_offmode signals is not taken
+ * into account - TDB
  */
 
 static struct powerdomain iva2_pwrdm = {
@@ -52,6 +65,13 @@ static struct powerdomain iva2_pwrdm = {
[2] = PWRSTS_OFF_ON,
[3] = PWRSTS_ON,
},
+   .wakeup_lat = {
+   [PWRDM_FUNC_PWRST_OFF] = 1100,
+   [PWRDM_FUNC_PWRST_OSWR] = UNSUP_STATE,
+   [PWRDM_FUNC_PWRST_CSWR] = 350,
+   [PWRDM_FUNC_PWRST_INACTIVE] = UNSUP_STATE,
+   [PWRDM_FUNC_PWRST_ON] = 0,
+   },
.voltdm   = { .name = mpu_iva },
 };
 
@@ -68,6 +88,13 @@ static struct powerdomain mpu_3xxx_pwrdm = {
.pwrsts_mem_on= {
[0] = PWRSTS_OFF_ON,
},
+   .wakeup_lat = {
+   [PWRDM_FUNC_PWRST_OFF] = 1830,
+   [PWRDM_FUNC_PWRST_OSWR] = UNSUP_STATE,
+   [PWRDM_FUNC_PWRST_CSWR] = 121,
+   [PWRDM_FUNC_PWRST_INACTIVE] = UNSUP_STATE,
+   [PWRDM_FUNC_PWRST_ON] = 0,
+   },
.voltdm   = { .name = mpu_iva },
 };
 
@@ -95,6 +122,13 @@ static struct powerdomain core_3xxx_pre_es3_1_pwrdm = {
[0] = PWRSTS_OFF_RET_ON, /* MEM1ONSTATE */
[1] = PWRSTS_OFF_RET_ON, /* MEM2ONSTATE */
},
+   .wakeup_lat = {
+   [PWRDM_FUNC_PWRST_OFF] = 3082,
+   [PWRDM_FUNC_PWRST_OSWR] = UNSUP_STATE,
+   [PWRDM_FUNC_PWRST_CSWR] = 153,
+   [PWRDM_FUNC_PWRST_INACTIVE] = UNSUP_STATE,
+   [PWRDM_FUNC_PWRST_ON] = 0,
+   },
.voltdm   = { .name = core },
 };
 
@@ -117,6 +151,13 @@ static struct powerdomain core_3xxx_es3_1_pwrdm = {
[0] = PWRSTS_OFF_RET_ON, /* MEM1ONSTATE */
[1] = PWRSTS_OFF_RET_ON, /* MEM2ONSTATE */
},
+   .wakeup_lat = {
+   [PWRDM_FUNC_PWRST_OFF] = 3082,
+   [PWRDM_FUNC_PWRST_OSWR] = UNSUP_STATE,
+   [PWRDM_FUNC_PWRST_CSWR] = 153,
+   [PWRDM_FUNC_PWRST_INACTIVE] = UNSUP_STATE,
+   [PWRDM_FUNC_PWRST_ON] = 0,
+   },
.voltdm   = { .name = core },
 };
 
@@ -132,6 +173,13 @@ static struct powerdomain dss_pwrdm = {
.pwrsts_mem_on= {
[0] = PWRSTS_ON,  /* MEMONSTATE */
},
+   .wakeup_lat = {
+   [PWRDM_FUNC_PWRST_OFF] = 70,
+   [PWRDM_FUNC_PWRST_OSWR] = UNSUP_STATE,
+   [PWRDM_FUNC_PWRST_CSWR] = 20,
+   [PWRDM_FUNC_PWRST_INACTIVE] = UNSUP_STATE,
+   [PWRDM_FUNC_PWRST_ON] = 0,
+   },
.voltdm   = { .name = core },
 };
 
@@ -153,6 +201,13 @@ static struct powerdomain sgx_pwrdm = {
.pwrsts_mem_on= {
[0] = PWRSTS_ON,  /* MEMONSTATE */
},
+   .wakeup_lat = {
+   [PWRDM_FUNC_PWRST_OFF] = 1000,
+   [PWRDM_FUNC_PWRST_OSWR] = UNSUP_STATE,
+   [PWRDM_FUNC_PWRST_CSWR] = UNSUP_STATE,
+   [PWRDM_FUNC_PWRST_INACTIVE] = UNSUP_STATE,
+   [PWRDM_FUNC_PWRST_ON] = 0,
+   },
.voltdm   = { .name = core },
 };
 
@@ -168,6 +223,13 @@ static struct powerdomain cam_pwrdm = {
.pwrsts_mem_on= {
[0] = PWRSTS_ON,  /* MEMONSTATE */
},
+   .wakeup_lat = {
+   [PWRDM_FUNC_PWRST_OFF] = 850,
+   [PWRDM_FUNC_PWRST_OSWR] = UNSUP_STATE,
+   [PWRDM_FUNC_PWRST_CSWR] = 35

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

2012-06-13 Thread Jean Pihet
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-kri...@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-kri...@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 

Re: [GIT PULL] OMAP DSS for v3.5

2012-06-05 Thread Jean Pihet
Hi Tomi,

On Tue, May 22, 2012 at 12:09 PM, Tomi Valkeinen tomi.valkei...@ti.com wrote:
 Hi Florian,

 Here are the OMAP DSS changes for 3.5.

 I really tried this time to send the pull request early, but here I am
 again, sending it when the merge window has already opened... A few
 late-found bugs caused some unnecessary delays.

 I'm using github this time instead of gitorious, as gitorious seems to
 be down. This is my first pull request with a signed tag, I hope
 everything is correct.

 Note that there's a merge for small branch with omap board file changes
 (e4a9e94cc58ed6e4efb02b80be3a9bf57f448d07) that is also pulled by Tony
 for the linux-omap tree. This is meant to help avoid conflicts in the
 board files.

  Tomi


 The following changes since commit 66f75a5d028beaf67c931435fdc3e7823125730c:

  Linux 3.4-rc4 (2012-04-21 14:47:52 -0700)

 are available in the git repository at:

  git://github.com/tomba/linux.git tags/omapdss-for-3.5

 for you to fetch changes up to e92a5b28f71aea01b281f9c89d97a4bc5b24748f:

  OMAPDSS: HDMI: OMAP4: Update IRQ flags for the HPD IRQ request (2012-05-22 
 11:00:09 +0300)

 
 Omapdss driver changes for 3.5 merge window.

 Lots of normal development commits, but perhaps most notable changes are:

 * HDMI rework to properly decouple the HDMI audio part from the HDMI video 
 part.
 * Restructure omapdss core driver so that it's possible to implement device
  tree support. This included changing how platform data is passed to the
  drivers, changing display device registration and improving the panel 
 driver's
  ability to configure the underlying video output interface.
 * Basic support for DSI packet interleaving


I am using a mainline kernel (3.5.0-rc1) with the patches below integrated.
I have an issue with suspend/resume on OMAP3 Beagleboard, where the
system hangs at resume time.

Here below is a log with the option no_console_suspend set and a few
added messages in case of null pointer in _od_resume_noirq.
It looks like there is no omap_device associated to the omapdss_dpi pdev.

What do you think? How to fix this?
Sorry I know there have been some discussions on the lists but I am
not aware of all the details in the devices creation for DSS.

/ # echo mem  /sys/power/state
[   23.262298] PM: Syncing filesystems ... done.
[   23.295501] Freezing user space processes ... (elapsed 0.02 seconds) done.
[   23.326507] Freezing remaining freezable tasks ... (elapsed 0.02 seconds) don
e.
[   23.502197] PM: suspend of devices complete after 163.766 msecs
[   23.511932] PM: late suspend of devices complete after 3.418 msecs
[   23.52] PM: noirq suspend of devices complete after 5.860 msecs
[   23.531249] Disabling non-boot CPUs ...
[   24.476562] Powerdomain (per_pwrdm) didn't enter target state 1
[   24.482818] Powerdomain (core_pwrdm) didn't enter target state 1
[   24.489166] Could not enter target state in pm_suspend
[   24.495147] *** _od_resume_noirq: od=NULL, dev=0xc78bcc08
[   24.500915] *** _od_resume_noirq: od=NULL, pdev=0xc78bcc00
[   24.506805] *** _od_resume_noirq: od=NULL, pdev-name:omapdss_dpi
[   24.513336] Unable to handle kernel NULL pointer dereference at virtual addre
ss 0018
[   24.521942] pgd = c62f
[   24.524841] [0018] *pgd=862c1831, *pte=, *ppte=
[   24.531524] Internal error: Oops: 17 [#1] SMP ARM
[   24.536529] Modules linked in:
[   24.539764] CPU: 0Not tainted  (3.5.0-rc1-00010-g5041caa-dirty #131)
[   24.546844] PC is at _od_resume_noirq+0x1c/0xac
[   24.551635] LR is at _od_resume_noirq+0x94/0xac
...

Regards,
Jean

 
 Archit Taneja (19):
      OMAPDSS: DISPC/RFBI: Use dispc_mgr_set_lcd_timings() for setting lcd size
      OMAPDSS: DISPC: Use a common function to set manager timings
      OMAPDSS: DISPC: Clean up manager timing/size functions
      OMAPDSS: HDMI: Fix ti_hdmi_4xxx_core_dump
      OMAPDSS: HDMI: define and dump CORE registers in correct order
      OMAPDSS: Fix DSI_FCLK clock source selection
      OMAPDSS: DISPC: Remove Fake VSYNC support
      OMAPDSS: APPLY: Add manager timings as extra_info in private data
      OMAPDSS: Apply manager timings instead of direct DISPC writes
      OMAPDSS: MANAGER: Create a function to check manager timings
      OMAPDSS: APPLY: Don't check manager settings if it is disabled
      OMAPDSS: APPLY: Remove display dependency from overlay and manager checks
      OMAPDSS: DPI/HDMI: Apply manager timings even if panel is disabled
      OMAPDSS: APPLY: Remove an unnecessary omap_dss_device pointer
      OMAPDSS: DISPC: Remove omap_dss_device pointer usage from 
 dispc_mgr_pclk_rate()
      OMAPDSS: DISPC: Remove usage of dispc_mgr_get_device()
      OMAPDSS: DSI: Support command mode interleaving during video mode 
 blanking periods
      OMAPDSS: VENC/DISPC: Delay dividing Y resolution for managers connected 
 to VENC
      OMAPDSS: 

Re: [GIT PULL] OMAP DSS for v3.5

2012-06-05 Thread Jean Pihet
Hi Tomi,

On Tue, Jun 5, 2012 at 2:33 PM, Tomi Valkeinen tomi.valkei...@ti.com wrote:
 Hi Jean,

 On Tue, 2012-06-05 at 14:17 +0200, Jean Pihet wrote:
 Hi Tomi,

 I am using a mainline kernel (3.5.0-rc1) with the patches below integrated.
 I have an issue with suspend/resume on OMAP3 Beagleboard, where the
 system hangs at resume time.

 Here below is a log with the option no_console_suspend set and a few
 added messages in case of null pointer in _od_resume_noirq.
 It looks like there is no omap_device associated to the omapdss_dpi pdev.

 What do you think? How to fix this?
 Sorry I know there have been some discussions on the lists but I am
 not aware of all the details in the devices creation for DSS.

 / # echo mem  /sys/power/state
 [   23.262298] PM: Syncing filesystems ... done.
 [   23.295501] Freezing user space processes ... (elapsed 0.02 seconds) done.
 [   23.326507] Freezing remaining freezable tasks ... (elapsed 0.02 seconds) 
 don
 e.
 [   23.502197] PM: suspend of devices complete after 163.766 msecs
 [   23.511932] PM: late suspend of devices complete after 3.418 msecs
 [   23.52] PM: noirq suspend of devices complete after 5.860 msecs
 [   23.531249] Disabling non-boot CPUs ...
 [   24.476562] Powerdomain (per_pwrdm) didn't enter target state 1
 [   24.482818] Powerdomain (core_pwrdm) didn't enter target state 1
 [   24.489166] Could not enter target state in pm_suspend
 [   24.495147] *** _od_resume_noirq: od=NULL, dev=0xc78bcc08
 [   24.500915] *** _od_resume_noirq: od=NULL, pdev=0xc78bcc00
 [   24.506805] *** _od_resume_noirq: od=NULL, pdev-name:omapdss_dpi
 [   24.513336] Unable to handle kernel NULL pointer dereference at virtual 
 addre
 ss 0018
 [   24.521942] pgd = c62f
 [   24.524841] [0018] *pgd=862c1831, *pte=, *ppte=
 [   24.531524] Internal error: Oops: 17 [#1] SMP ARM
 [   24.536529] Modules linked in:
 [   24.539764] CPU: 0    Not tainted  (3.5.0-rc1-00010-g5041caa-dirty #131)
 [   24.546844] PC is at _od_resume_noirq+0x1c/0xac
 [   24.551635] LR is at _od_resume_noirq+0x94/0xac
 ...

 I'm on leave currently, so I can't test it right now. But can you try
Oh sorry about that!

 the attached patch? Or even better, try merging the tag:
That fixes it! I am able to suspend/resume correctly now.


 git://gitorious.org/linux-omap-dss2/linux.git tags/omapdss-for-3.5-rc2

 which contains the included patch plus a couple other fixes.
Thanks for the link, that is certainly useful!

Have a nice time on leave ;-p


  Tomi


Regards,
Jean
--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 0/3] ARM: OMAP3: PM: optimize cpuidle C1 state latency

2012-06-01 Thread Jean Pihet
The C1 state latency can be improved by optimizing the cpuidle low
level code.

The first patch is a precaution fix for patch 2.
Patches 2  3 are optimization changes.

Rebased on top of the for_3.6/pm/performance branch of
khilman's tree [1].

Tested on Beagleboard using a DMA-enabled copy from NAND flash
to /dev/null.

[1] git://git.kernel.org/pub/scm/linux/kernel/git/khilman/linux-omap-pm.git

Jean Pihet (3):
  ARM: OMAP3: PM: cpuidle: default to C1 in next_valid_state
  ARM: OMAP3: PM: cpuidle: optimize the PER latency in C1 state
  ARM: OMAP3: PM: cpuidle: optimize the clkdm idle latency in C1 state

 arch/arm/mach-omap2/cpuidle34xx.c |   71 ++---
 1 files changed, 27 insertions(+), 44 deletions(-)

-- 
1.7.7.6

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


[PATCH 1/3] ARM: OMAP3: PM: cpuidle: default to C1 in next_valid_state

2012-06-01 Thread Jean Pihet
If the next state is no found in the next_valid_state function,
fallback to the default value of C1 (which is state 0).
This prevents the use of a bogus state -1 in the rest of the cpuidle
code.

Signed-off-by: Jean Pihet j-pi...@ti.com
---
 arch/arm/mach-omap2/cpuidle34xx.c |8 +---
 1 files changed, 1 insertions(+), 7 deletions(-)

diff --git a/arch/arm/mach-omap2/cpuidle34xx.c 
b/arch/arm/mach-omap2/cpuidle34xx.c
index 207bc1c..f619a92 100644
--- a/arch/arm/mach-omap2/cpuidle34xx.c
+++ b/arch/arm/mach-omap2/cpuidle34xx.c
@@ -178,7 +178,7 @@ static int next_valid_state(struct cpuidle_device *dev,
u32 mpu_deepest_state = PWRDM_POWER_RET;
u32 core_deepest_state = PWRDM_POWER_RET;
int idx;
-   int next_index = -1;
+   int next_index = 0; /* C1 is the default value */
 
if (enable_off_mode) {
mpu_deepest_state = PWRDM_POWER_OFF;
@@ -209,12 +209,6 @@ static int next_valid_state(struct cpuidle_device *dev,
}
}
 
-   /*
-* C1 is always valid.
-* So, no need to check for 'next_index == -1' outside
-* this loop.
-*/
-
return next_index;
 }
 
-- 
1.7.7.6

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


[PATCH 2/3] ARM: OMAP3: PM: cpuidle: optimize the PER latency in C1 state

2012-06-01 Thread Jean Pihet
One of the main contributors of the low power code latency is
the PER power domain. To optimize the high-performance and
low-latency C1 state, prevent any PER state which is lower
than the CORE state in C1.

Reported and suggested by Kevin Hilman.

Reported-by: Kevin Hilman khil...@ti.com
Signed-off-by: Jean Pihet j-pi...@ti.com
---
 arch/arm/mach-omap2/cpuidle34xx.c |   41 +++-
 1 files changed, 22 insertions(+), 19 deletions(-)

diff --git a/arch/arm/mach-omap2/cpuidle34xx.c 
b/arch/arm/mach-omap2/cpuidle34xx.c
index f619a92..2e2f1c6 100644
--- a/arch/arm/mach-omap2/cpuidle34xx.c
+++ b/arch/arm/mach-omap2/cpuidle34xx.c
@@ -222,23 +222,22 @@ static int next_valid_state(struct cpuidle_device *dev,
  * the device to the specified or a safer state.
  */
 static int omap3_enter_idle_bm(struct cpuidle_device *dev,
-   struct cpuidle_driver *drv,
+  struct cpuidle_driver *drv,
   int index)
 {
int new_state_idx;
-   u32 core_next_state, per_next_state = 0, per_saved_state = 0, cam_state;
+   u32 core_next_state, per_next_state = 0, per_saved_state = 0;
struct omap3_idle_statedata *cx;
int ret;
 
/*
-* Prevent idle completely if CAM is active.
+* Use only C1 if CAM is active.
 * CAM does not have wakeup capability in OMAP3.
 */
-   cam_state = pwrdm_read_pwrst(cam_pd);
-   if (cam_state == PWRDM_POWER_ON) {
+   if (pwrdm_read_pwrst(cam_pd) == PWRDM_POWER_ON)
new_state_idx = drv-safe_state_index;
-   goto select_state;
-   }
+   else
+   new_state_idx = next_valid_state(dev, drv, index);
 
/*
 * FIXME: we currently manage device-specific idle states
@@ -248,24 +247,28 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
 *its own code.
 */
 
-   /*
-* Prevent PER off if CORE is not in retention or off as this
-* would disable PER wakeups completely.
-*/
-   cx = omap3_idle_data[index];
+   /* Program PER state */
+   cx = omap3_idle_data[new_state_idx];
core_next_state = cx-core_state;
per_next_state = per_saved_state = pwrdm_read_next_pwrst(per_pd);
-   if ((per_next_state == PWRDM_POWER_OFF) 
-   (core_next_state  PWRDM_POWER_RET))
-   per_next_state = PWRDM_POWER_RET;
+   if (new_state_idx == 0) {
+   /* In C1 do not allow PER state lower than CORE state */
+   if (per_next_state  core_next_state)
+   per_next_state = core_next_state;
+   } else {
+   /*
+* Prevent PER OFF if CORE is not in RETention or OFF as this
+* would disable PER wakeups completely.
+*/
+   if ((per_next_state == PWRDM_POWER_OFF) 
+   (core_next_state  PWRDM_POWER_RET))
+   per_next_state = PWRDM_POWER_RET;
+   }
 
/* Are we changing PER target state? */
if (per_next_state != per_saved_state)
pwrdm_set_next_pwrst(per_pd, per_next_state);
 
-   new_state_idx = next_valid_state(dev, drv, index);
-
-select_state:
ret = omap3_enter_idle(dev, drv, new_state_idx);
 
/* Restore original PER state if it was modified */
@@ -282,7 +285,7 @@ struct cpuidle_driver omap3_idle_driver = {
.owner =THIS_MODULE,
.states = {
{
-   .enter= omap3_enter_idle,
+   .enter= omap3_enter_idle_bm,
.exit_latency = 2 + 2,
.target_residency = 5,
.flags= CPUIDLE_FLAG_TIME_VALID,
-- 
1.7.7.6

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


[PATCH 3/3] ARM: OMAP3: PM: cpuidle: optimize the clkdm idle latency in C1 state

2012-06-01 Thread Jean Pihet
For a power domain to idle all the clock domains in it must idle.
This patch implements an optimization of the cpuidle code by
denying and later allowing only the first registered clock domain
of a power domain, and so optimizes the latency of the low power code.

The functions _cpuidle_allow_idle and _cpuidle_deny_idle are
not used anymore and so are removed.

Signed-off-by: Jean Pihet j-pi...@ti.com
---
 arch/arm/mach-omap2/cpuidle34xx.c |   22 --
 1 files changed, 4 insertions(+), 18 deletions(-)

diff --git a/arch/arm/mach-omap2/cpuidle34xx.c 
b/arch/arm/mach-omap2/cpuidle34xx.c
index 2e2f1c6..e6ae3fe 100644
--- a/arch/arm/mach-omap2/cpuidle34xx.c
+++ b/arch/arm/mach-omap2/cpuidle34xx.c
@@ -77,20 +77,6 @@ static struct omap3_idle_statedata omap3_idle_data[] = {
 
 static struct powerdomain *mpu_pd, *core_pd, *per_pd, *cam_pd;
 
-static int _cpuidle_allow_idle(struct powerdomain *pwrdm,
-   struct clockdomain *clkdm)
-{
-   clkdm_allow_idle(clkdm);
-   return 0;
-}
-
-static int _cpuidle_deny_idle(struct powerdomain *pwrdm,
-   struct clockdomain *clkdm)
-{
-   clkdm_deny_idle(clkdm);
-   return 0;
-}
-
 static int __omap3_enter_idle(struct cpuidle_device *dev,
struct cpuidle_driver *drv,
int index)
@@ -108,8 +94,8 @@ static int __omap3_enter_idle(struct cpuidle_device *dev,
 
/* Deny idle for C1 */
if (index == 0) {
-   pwrdm_for_each_clkdm(mpu_pd, _cpuidle_deny_idle);
-   pwrdm_for_each_clkdm(core_pd, _cpuidle_deny_idle);
+   clkdm_deny_idle(mpu_pd-pwrdm_clkdms[0]);
+   clkdm_deny_idle(core_pd-pwrdm_clkdms[0]);
}
 
/*
@@ -131,8 +117,8 @@ static int __omap3_enter_idle(struct cpuidle_device *dev,
 
/* Re-allow idle for C1 */
if (index == 0) {
-   pwrdm_for_each_clkdm(mpu_pd, _cpuidle_allow_idle);
-   pwrdm_for_each_clkdm(core_pd, _cpuidle_allow_idle);
+   clkdm_allow_idle(mpu_pd-pwrdm_clkdms[0]);
+   clkdm_allow_idle(core_pd-pwrdm_clkdms[0]);
}
 
 return_sleep_time:
-- 
1.7.7.6

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


Re: [PATCH 2/2] ARM: OMAP3: PM: cpuidle: optimize the clkdm idle latency in C1 state

2012-06-01 Thread Jean Pihet
Hi Kevin,

On Thu, May 31, 2012 at 6:29 PM, Kevin Hilman khil...@ti.com wrote:
 jean.pi...@newoldbits.com writes:

 From: Jean Pihet j-pi...@ti.com

 It is not needed to iterate through all the clock domains of a
 power domain in order to allow or deny it to idle.

 Why?  (I know the answer, but would like it answered here.)

 This patch allows or denies only the first registered clock domain
 of a power domain, and so optimizes the latency of the low power
 code. The functions _cpuidle_allow_idle and _cpuidle_deny_idle are
 not used anymore and so are removed.

 Signed-off-by: Jean Pihet j-pi...@ti.com

 Other than the changelog update, it looks good but also needs a rebase
 like the previous patch.

 After that, I'll add them to my for_3.6/pm/performance branch and queue
 for v3.6.
The new series has been sent as '[PATCH 0/3] ARM: OMAP3: PM: optimize
cpuidle C1 state latency' with the suggested changes (changelog
updated, rebased on for_3.6/pm/performance).

Note: with the code from the branch the CORE does not idle. The
optimization changes have been tested OK though.


 Thanks!

 Kevin


Regards,
Jean


 ---
  arch/arm/mach-omap2/cpuidle34xx.c |   22 --
  1 files changed, 4 insertions(+), 18 deletions(-)

 diff --git a/arch/arm/mach-omap2/cpuidle34xx.c 
 b/arch/arm/mach-omap2/cpuidle34xx.c
 index 353dd8d..d44b68a 100644
 --- a/arch/arm/mach-omap2/cpuidle34xx.c
 +++ b/arch/arm/mach-omap2/cpuidle34xx.c
 @@ -73,20 +73,6 @@ struct omap3_idle_statedata 
 omap3_idle_data[OMAP3_NUM_STATES];

  struct powerdomain *mpu_pd, *core_pd, *per_pd, *cam_pd;

 -static int _cpuidle_allow_idle(struct powerdomain *pwrdm,
 -                             struct clockdomain *clkdm)
 -{
 -     clkdm_allow_idle(clkdm);
 -     return 0;
 -}
 -
 -static int _cpuidle_deny_idle(struct powerdomain *pwrdm,
 -                             struct clockdomain *clkdm)
 -{
 -     clkdm_deny_idle(clkdm);
 -     return 0;
 -}
 -
  static int __omap3_enter_idle(struct cpuidle_device *dev,
                               struct cpuidle_driver *drv,
                               int index)
 @@ -105,8 +91,8 @@ static int __omap3_enter_idle(struct cpuidle_device *dev,

       /* Deny idle for C1 */
       if (index == 0) {
 -             pwrdm_for_each_clkdm(mpu_pd, _cpuidle_deny_idle);
 -             pwrdm_for_each_clkdm(core_pd, _cpuidle_deny_idle);
 +             clkdm_deny_idle(mpu_pd-pwrdm_clkdms[0]);
 +             clkdm_deny_idle(core_pd-pwrdm_clkdms[0]);
       }

       /*
 @@ -128,8 +114,8 @@ static int __omap3_enter_idle(struct cpuidle_device *dev,

       /* Re-allow idle for C1 */
       if (index == 0) {
 -             pwrdm_for_each_clkdm(mpu_pd, _cpuidle_allow_idle);
 -             pwrdm_for_each_clkdm(core_pd, _cpuidle_allow_idle);
 +             clkdm_allow_idle(mpu_pd-pwrdm_clkdms[0]);
 +             clkdm_allow_idle(core_pd-pwrdm_clkdms[0]);
       }

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


Re: [PATCH 0/3] ARM: OMAP3: PM: optimize cpuidle C1 state latency

2012-06-01 Thread Jean Pihet
On Fri, Jun 1, 2012 at 6:26 PM, Kevin Hilman khil...@ti.com wrote:
 Hi Jean,

 Jean Pihet jean.pi...@newoldbits.com writes:

 The C1 state latency can be improved by optimizing the cpuidle low
 level code.

 The first patch is a precaution fix for patch 2.
 Patches 2  3 are optimization changes.

 Rebased on top of the for_3.6/pm/performance branch of
 khilman's tree [1].

 Tested on Beagleboard using a DMA-enabled copy from NAND flash
 to /dev/null.

 Thanks for following this through.

 Adding this series to my for_3.6/pm/performance branch.
Great!


 Also FYI, combining your series with the various fixes for CORE
 retention, I'm seeing CORE hit retention in idle just fine on 3430/n900
 and 3530/Overo.
Nice, thx for testing!


 Thanks!

 Kevin

Regards,
Jean
--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: v3.4-rc4 DSS PM problem (Was: Re: Problems with 3.4-rc5)

2012-05-25 Thread Jean Pihet
Hi Tomi, Paul!

On Fri, May 25, 2012 at 10:24 AM, Tomi Valkeinen tomi.valkei...@ti.com wrote:
 On Thu, 2012-05-24 at 18:39 -0600, Paul Walmsley wrote:
 cc Jean

 Hello Tomi,

 On Wed, 16 May 2012, Tomi Valkeinen wrote:

  I also suspect that this could be just a plain DSS bug. The default FIFO
  low/high thresholds are 960/1023 bytes (i.e. DSS starts refilling the
  FIFO when there are 960 or less bytes in the fifo, and stops at 1023.
  The fifo is 1024 bytes). The values are calculated with fifo_size -
  burst_size and fifo_size - 1.
 
  We are now using FIFO merge features, which combines multiple fifos into
  one when possible, making the fifo size 1024*3 = 3072. Using the same
  low threshold and increasing the high threshold to 960/3071 works fine.
  Changing the high threshold to 3008 causes underflows. Increasing the
  low threshold to ~1600 makes DSS work again.

 Just a few thoughts.

 In terms of the high threshold, it seems really strange to me that
 changing the high threshold would make such a difference.  Naïvely, I'd
 assume that you'd want to set it as high as possible?  I suppose in cases
 where the interconnect is congested, setting it lower might allow lower
 latency for other interconnect users, but I'd hope we don't have to worry
 much about that.  So it doesn't seem to me that there would be any
 advantage to setting it lower than the maximum.

 It's true that the high threshold should be set as high as possible, and
 this is what we do. Except for DSI command mode output on OMAP3, where,
 for unknown reason, the highest value (fifosize - 1) doesn't work and we
 need to program it to fifosize - burstsize. And this was causing the
 original problem, fifosize - burstsize was not working for other outputs
 properly.

 I guess this also hints that there's something wrong with omap3 and the
 dss fifo thresholds.

 Probably the low threshold is the more important parameter, from a PM
 perspective.  If you know the FIFO's drain rate and the low threshold, it
 should be possible to calculate the maximum latency that the FIFO can
 tolerate to avoid an underflow.  This could be used to specify a device PM
 QoS constraint to prevent the interconnect latency from exceeding that
 value.

 Yes, this is how the low threshold should be adjusted. I have never
 tried to calculate the threshold need, though, as I haven't had all the
 information and understanding to properly calculate it.

 I'd guess the calculations would be something like this -- (I hope you can
 correct my relative ignorance of the DSS in the following estimates):

 Looking at mach-omap2/board-rx51-video.c, let's suppose that the FIFO
 drain rate would be 864 x 480 x 32 bits/second.  Since the FIFO width is
 32 bits, that's

 I think the DSS fifo entries are 8 bit on omap2/3, 128bits on omap4. At
 least those are the units used with fifo size, threshold sizes, burst
 size, etc.

    864 x 480 = 414 780 FIFO entries/second, or

    (1 000 000 µs/s / 414 780 FIFO entries/s) = ~2.411 µs/FIFO entry.

 So if you need a low FIFO threshold at 960 entries, you could call the
 device PM QoS functions to set a wakeup latency constraint for the
 interconnect would be nothing greater than this:

    (2.411 µs/FIFO entry * 960 FIFO entries) = 2 314.96 µs

 (The reality is that it would need to be something less than this, to
 account for the time needed for the GFX DMA transfer to start supplying
 data, etc.)

 Makes sense.

 Another reason for underflows we have is the different rotation engines.
 VRFB on omap2/3, and TILER on omap4. Both increase the work needed to
 get pixels, although I'm not sure what the actual causes for the
 increased work are.

 The ultimate goal, with Jean's device PM QoS patches, is that these
 constraints could change the DPLL autoidle settings or powerdomain states
 to ensure the constraint was met.  He's got a page here:
Indeed! The core code is ready and the OMAP power domains code is
under review for the moment. The ultimate goal is to split the overall
latency of a device into the contributors (SW, HW SoC, HW external
etc.), so the DPLL relock time would be taken into account. However
without the submitted code in place there is no way to build the
feature in incremental steps.


   http://omappedia.org/wiki/Power_Management_Device_Latencies_Measurement
In the wiki page there is a link to the ELC/Fosdem presentation [1]
about the new model for the latency.
[1] http://omappedia.org/wiki/File:ELC-2012-jpihet-DeviceLatencyModel.pdf


 (Unfortunately it's not clear what the DPLL autoidle modes and voltage
 scaling bits are set to for many of the estimates, and we also know that
The code is from an l-o tree + the measurement code in, so the DPLL
are allowed to auto-idle. In the new model the DPLL relock latency
contribution should be split from the power domains latency.

 there are many software optimizations possible for our idle path.)
Sure! Recently we have had the case with the C1 cpuidle state.
Hopefully some 

Re: [PATCH 2/6] ARM: OMAP2+: PM: introduce power domains functional states

2012-05-21 Thread Jean Pihet
Hi Santosh,

On Thu, May 17, 2012 at 12:04 PM, Santosh Shilimkar
santosh.shilim...@ti.com wrote:
 Jean,
 On Tuesday 08 May 2012 02:10 PM, Jean Pihet wrote:
 Paul,

 On Mon, May 7, 2012 at 11:28 AM, Paul Walmsley p...@pwsan.com wrote:
 Hi

 On Wed, 18 Apr 2012, jean.pi...@newoldbits.com wrote:

 From: Jean Pihet j-pi...@ti.com

 Introduce functional (or logical) states for power domains and the
 API functions to read the power domains settings and to convert
 between the functional (i.e. logical) and the internal (or registers)
 values.

 OMAP2, OMAP3 and OMAP4 platforms are defining a conversion routine.

 In the new API the function omap_set_pwrdm_state takes the functional
 states as parameter; while at it the function is moved to the power
 domains code.

 The memory and logic states are not using the functional states, this
 comes as a subsequent patch.

 Signed-off-by: Jean Pihet j-pi...@ti.com

 This patch results in several checkpatch warnings; please resolve them.
 Oops. Will check and update.


 ---
  arch/arm/mach-omap2/pm.c                   |   66 ---
  arch/arm/mach-omap2/powerdomain-common.c   |   61 ++
  arch/arm/mach-omap2/powerdomain.c          |  175 
 
  arch/arm/mach-omap2/powerdomain.h          |   21 
  arch/arm/mach-omap2/powerdomain2xxx_3xxx.c |    5 +
  arch/arm/mach-omap2/powerdomain44xx.c      |    2 +
  6 files changed, 264 insertions(+), 66 deletions(-)

 ...

 +/*
 + * Functional (i.e. logical) to internal (i.e. registers)
 + * values for the power domains states
 + */

 Please use kerneldoc-style function comments.
 Ok


 +int omap2_pwrdm_func_to_pwrst(struct powerdomain *pwrdm, u8 func_pwrst)
 +{
 +     int ret;
 +
 +     switch (func_pwrst) {
 +     case PWRDM_FUNC_PWRST_ON:
 +             ret = PWRDM_POWER_ON;
 +             break;
 +     case PWRDM_FUNC_PWRST_INACTIVE:
 +             ret = PWRDM_POWER_INACTIVE;
 +             break;
 +     case PWRDM_FUNC_PWRST_CSWR:
 +     case PWRDM_FUNC_PWRST_OSWR:
 +             ret = PWRDM_POWER_RET;
 +             break;
 +     case PWRDM_FUNC_PWRST_OFF:
 +             ret = PWRDM_POWER_OFF;
 +             break;
 +     default:
 +             ret = -1;
 +     }
 +
 +     return ret;
 +}

 At a quick glance, I don't think that this function is appropriate for all
 OMAP2+ chips.  For example, off-mode is not supported in our OMAP2xxx
 kernels.  And OMAP2xxx/3xxx do not support the INACTIVE powerstate.  So
 probably this function should differ by chip, and be located in the
 powerdomain[2-4]*xx*.c files.
 I hope to make this function as generic as possible, hence the
 location (powerdomain-common.c). Some states are not programmed by the
 pwrdm_* functions since there forbidden by the contents of the
 pwrdm-pwrst field.
 Now if the need arises some platform specific function can be defined
 for conversion functions since the pwrdm-ops function pointers are
 used. I do not think it is needed now but it can easily be changed.

 Also, what about the logic and memory bank power states?  Shouldn't this
 function pass those back as well?
 Cf. in the description The memory and logic states are not using the
 functional states, this comes as a subsequent patch.

 I don't see much difference between the functional power states to
 actual power states with some cases here and there.

 +     case PWRDM_FUNC_PWRST_CSWR:
 +     case PWRDM_FUNC_PWRST_OSWR:
 +             ret = PWRDM_POWER_RET;
The whole patch series takes the logic state into account in the
functional power state.
Cf. in the description The memory and logic states are not using the
functional states, this comes as a subsequent patch.

 This is not true and even if you add logic/memmort etc support,
 I still think, we are just duplicating stuff between functional
 vs actual power state.
The idea is to provide a single function to program the power domains
state, including the logic state.
There is no duplication of code, just a simplification in the API. IMO
there are too much calls to set and get the power domain states (power
state, logical etc.) and most of the calls do not take the logical
state into account.
If you look the the code in pm.c and cpuidle.c you will notice
that the code is simplified.

 If the idea is to have one single interface to program the power
 domain states, so that Generic frameworks, or PM code movement to
 driver/* directories is easier, we may want think about alternative
 which is scalable.

 Just a wild thought...

 May be we can abstract all the necessary/used power domain programming
 entities inside a structure and export that. That should contain, power
 state, logic state, mem state, special quirk flags like SAR etc.
 being structure is always expandable and an API taking structure as
 a parameter need not change.
That is the goal. This patch series uses the date from the platform
specific power domain structs and abstracts those in the API.

So in summary I would say that the power domain

Re: [PATCHv2 03/19] ARM: OMAP4: PM: Add device-off support

2012-05-21 Thread Jean Pihet
Hi Tero, Kevin, Santosh,

On Mon, May 21, 2012 at 10:48 AM, Tero Kristo t-kri...@ti.com wrote:
 On Wed, 2012-05-16 at 15:36 -0700, Kevin Hilman wrote:
 +Jean for functional power states

 Tero Kristo t-kri...@ti.com writes:

  This patch adds device off support to OMAP4 device type.

 Description is rather thin for a patch that is doing so much.

  OFF mode is disabled by default,

 why?

 Good question. For historical reference I guess. The device off works
 pretty nicely with the current kernel already, so it should be possible
 to enable it by default and blame the people who break it.
Agree. The next problem is 'who will fix the breakage?'.

  however, there are two ways to enable OFF mode:
  a) In the board file, call omap4_pm_off_mode_enable(1)
  b) Enable OFF mode using the debugfs entry
  echo 1/sys/kernel/debug/pm_debug/enable_off_mode
  (conversely echo '0' will disable it as well).

 This part needs to be a separate patch.

 But, as stated in the core retention series, I'd like to move away from
 these global flags all together.

 The way we manage the disabling of certain states (like off) is already
 clumsy for OMAP3, and it's getting worse with OMAP4.  Basically, I think
 this feature needs to be supported by using constraints on functional
 power states.   Having checks all over the place is getting unwieldy and
 not attractive to maintain.

 The combination of constraints and functional power states should make
 this much more manageable.   Until we have that, I'd prefer to keep
 the debugfs enable/disable stuff as separate patches at the end of the
 series used only for testing.

 Okay, this sounds like a good plan.


  Signed-off-by: Santosh Shilimkar santosh.shilim...@ti.com
  [t-kri...@ti.com: largely re-structured the code]

 then the sign-off above from Santosh probably doesn't apply anymore.
 You should change that to a Cc and just mention tht this is based upon
 some original work from Santosh.

 Yeah... I am not quite sure where the line goes here as I am modifying
 the patches quite heavily but try to keep credits to the original
 authors... will change this like so.


 First,  some general comments:

 There is a lot going on in this patch, so it is hard to follow what all
 is related, and why.  Just a quick glance suggests it needs to be broken
 up into at least a few parts:

 What is the merge plan for the func power state stuff? I don't want to
 create new dependencies if unnecessary. Otherwise the split should be
 okay.
That is something I am interested in too ;p
I did port and test Tero's patches on top of the functional power
states, which is the logical approach to me. Now given the reviews
status on both this patch series and the func power states series I am
not sure which one needs to be ported on top of the other ;-|
[1] https://gitorious.org/jpihet/linux-omap/commits/omap4_dev_off

Using the functional power states for the OMAP4 core and device off
has some advantages in simplifying the code, especially in the
previous/current/next states checking and programming.



 - low-level PRM support: new APIs for various off-mode features)
   (should probably be done on top of functional power states)
 - powerdomain core support or achievable states
   (should probably be done on top of functional power states)
 - IRQ/GIC context save/restore
 - secure RAM save/restore (this has been tightly coupled to the GIC
   but it's not obvious why)

 This is tightly coupled to GIC because the ROM code has following API
 calls:

 - save gic
 - save secure RAM
 - save secure all (gic + RAM + some other mysterious stuff)

 It is difficult/impossible to separate these without adding redundant
 code execution (e.g. doing a GIC save from the GIC code + then doing a
 second GIC save with save secure all from core PM code.)

 - PM debug support to enable/disable off-mode
   (for testing only, not for merge)

  Signed-off-by: Tero Kristo t-kri...@ti.com
  ---
   arch/arm/mach-omap2/omap-mpuss-lowpower.c |   10 -
   arch/arm/mach-omap2/omap-wakeupgen.c      |   47 +++-
   arch/arm/mach-omap2/pm-debug.c            |   17 +--
   arch/arm/mach-omap2/pm.h                  |   20 +
   arch/arm/mach-omap2/pm44xx.c              |   45 +++
   arch/arm/mach-omap2/prm44xx.c             |   66 
  +
   6 files changed, 197 insertions(+), 8 deletions(-)
 
  diff --git a/arch/arm/mach-omap2/omap-mpuss-lowpower.c 
  b/arch/arm/mach-omap2/omap-mpuss-lowpower.c
  index e02c082..7418e7c 100644
  --- a/arch/arm/mach-omap2/omap-mpuss-lowpower.c
  +++ b/arch/arm/mach-omap2/omap-mpuss-lowpower.c
  @@ -60,6 +60,7 @@
   #include prcm44xx.h
   #include prm44xx.h
   #include prm-regbits-44xx.h
  +#include cm44xx.h
 
   #ifdef CONFIG_SMP
 
  @@ -263,9 +264,13 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned 
  int power_state)
       * In MPUSS OSWR or device OFF, interrupt controller  contest is lost.
       */
      

Re: [PATCH] arm: omap3: am35x: Set proper powerdomain states

2012-05-15 Thread Jean Pihet
Hi Mark,

On Mon, Apr 30, 2012 at 11:26 PM, Mark A. Greer mgr...@animalcreek.com wrote:
 From: Mark A. Greer mgr...@animalcreek.com

 The am35x family of SoCs only support the PWRSTS_ON
 state so create a new set of powerdomain structures
 that ensure that only the ON state is entered.

 Signed-off-by: Mark A. Greer mgr...@animalcreek.com
 ---

 These patches apply on top of Kevin's patch series,
    [PATCH/RFT 0/8] ARM: OMAP: remove IP checks from SoC family detection

 Tested on an am3517 evm and am37x evm.

  arch/arm/mach-omap2/powerdomains3xxx_data.c |  136 
 ---
  1 file changed, 124 insertions(+), 12 deletions(-)

 diff --git a/arch/arm/mach-omap2/powerdomains3xxx_data.c 
 b/arch/arm/mach-omap2/powerdomains3xxx_data.c
 index fb0a0a6..6ec06ad 100644
 --- a/arch/arm/mach-omap2/powerdomains3xxx_data.c
 +++ b/arch/arm/mach-omap2/powerdomains3xxx_data.c
 @@ -71,6 +71,22 @@ static struct powerdomain mpu_3xxx_pwrdm = {
        .voltdm           = { .name = mpu_iva },
  };

 +static struct powerdomain mpu_am35x_pwrdm = {
 +       .name             = mpu_pwrdm,
 +       .prcm_offs        = MPU_MOD,
 +       .pwrsts           = PWRSTS_ON,
 +       .pwrsts_logic_ret = PWRSTS_ON,
 +       .flags            = PWRDM_HAS_MPU_QUIRK,
 +       .banks            = 1,
 +       .pwrsts_mem_ret   = {
 +               [0] = PWRSTS_ON,
 +       },
 +       .pwrsts_mem_on    = {
 +               [0] = PWRSTS_ON,
 +       },
 +       .voltdm           = { .name = mpu_iva },
 +};
 +
  /*
  * The USBTLL Save-and-Restore mechanism is broken on
  * 3430s up to ES3.0 and 3630ES1.0. Hence this feature
 @@ -120,6 +136,23 @@ static struct powerdomain core_3xxx_es3_1_pwrdm = {
        .voltdm           = { .name = core },
  };

 +static struct powerdomain core_am35x_pwrdm = {
 +       .name             = core_pwrdm,
 +       .prcm_offs        = CORE_MOD,
 +       .pwrsts           = PWRSTS_ON,
 +       .pwrsts_logic_ret = PWRSTS_ON,
 +       .banks            = 2,
 +       .pwrsts_mem_ret   = {
 +               [0] = PWRSTS_ON,         /* MEM1RETSTATE */
 +               [1] = PWRSTS_ON,         /* MEM2RETSTATE */
 +       },
 +       .pwrsts_mem_on    = {
 +               [0] = PWRSTS_ON, /* MEM1ONSTATE */
 +               [1] = PWRSTS_ON, /* MEM2ONSTATE */
 +       },
 +       .voltdm           = { .name = core },
 +};
 +
  static struct powerdomain dss_pwrdm = {
        .name             = dss_pwrdm,
        .prcm_offs        = OMAP3430_DSS_MOD,
 @@ -135,6 +168,21 @@ static struct powerdomain dss_pwrdm = {
        .voltdm           = { .name = core },
  };

 +static struct powerdomain dss_am35x_pwrdm = {
 +       .name             = dss_pwrdm,
 +       .prcm_offs        = OMAP3430_DSS_MOD,
 +       .pwrsts           = PWRSTS_ON,
 +       .pwrsts_logic_ret = PWRSTS_ON,
 +       .banks            = 1,
 +       .pwrsts_mem_ret   = {
 +               [0] = PWRSTS_ON, /* MEMRETSTATE */
 +       },
 +       .pwrsts_mem_on    = {
 +               [0] = PWRSTS_ON,  /* MEMONSTATE */
 +       },
 +       .voltdm           = { .name = core },
 +};
 +
  /*
  * Although the 34XX TRM Rev K Table 4-371 notes that retention is a
  * possible SGX powerstate, the SGX device itself does not support
 @@ -156,6 +204,21 @@ static struct powerdomain sgx_pwrdm = {
        .voltdm           = { .name = core },
  };

 +static struct powerdomain sgx_am35x_pwrdm = {
 +       .name             = sgx_pwrdm,
 +       .prcm_offs        = OMAP3430ES2_SGX_MOD,
 +       .pwrsts           = PWRSTS_ON,
 +       .pwrsts_logic_ret = PWRSTS_ON,
 +       .banks            = 1,
 +       .pwrsts_mem_ret   = {
 +               [0] = PWRSTS_ON, /* MEMRETSTATE */
 +       },
 +       .pwrsts_mem_on    = {
 +               [0] = PWRSTS_ON,  /* MEMONSTATE */
 +       },
 +       .voltdm           = { .name = core },
 +};
 +
  static struct powerdomain cam_pwrdm = {
        .name             = cam_pwrdm,
        .prcm_offs        = OMAP3430_CAM_MOD,
 @@ -186,6 +249,21 @@ static struct powerdomain per_pwrdm = {
        .voltdm           = { .name = core },
  };

 +static struct powerdomain per_am35x_pwrdm = {
 +       .name             = per_pwrdm,
 +       .prcm_offs        = OMAP3430_PER_MOD,
 +       .pwrsts           = PWRSTS_ON,
 +       .pwrsts_logic_ret = PWRSTS_ON,
 +       .banks            = 1,
 +       .pwrsts_mem_ret   = {
 +               [0] = PWRSTS_ON, /* MEMRETSTATE */
 +       },
 +       .pwrsts_mem_on    = {
 +               [0] = PWRSTS_ON,  /* MEMONSTATE */
 +       },
 +       .voltdm           = { .name = core },
 +};
 +
  static struct powerdomain emu_pwrdm = {
        .name           = emu_pwrdm,
        .prcm_offs      = OMAP3430_EMU_MOD,
 @@ -200,6 +278,14 @@ static struct powerdomain neon_pwrdm = {
        .voltdm           = { .name = mpu_iva },
  };

 +static struct powerdomain neon_am35x_pwrdm = {
 +       .name             = neon_pwrdm,
 +       .prcm_offs        = OMAP3430_NEON_MOD,
 +       .pwrsts           = PWRSTS_ON,

[PATCH 1/2] ARM: OMAP3: PM: cpuidle: optimize the PER latency in C1 state

2012-05-09 Thread jean . pihet
From: Jean Pihet j-pi...@ti.com

One of the main contributors of the low power code latency is
the PER power domain. To optimize the high-performance and
low-latency C1 state, prevent any PER state which is lower
than the CORE state in C1.

Reported and suggested by Kevin Hilman.

Reported-by: Kevin Hilman khil...@ti.com
Signed-off-by: Jean Pihet j-pi...@ti.com
---
 arch/arm/mach-omap2/cpuidle34xx.c |   38 +++-
 1 files changed, 20 insertions(+), 18 deletions(-)

diff --git a/arch/arm/mach-omap2/cpuidle34xx.c 
b/arch/arm/mach-omap2/cpuidle34xx.c
index 5358664..353dd8d 100644
--- a/arch/arm/mach-omap2/cpuidle34xx.c
+++ b/arch/arm/mach-omap2/cpuidle34xx.c
@@ -247,19 +247,18 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
   int index)
 {
int new_state_idx;
-   u32 core_next_state, per_next_state = 0, per_saved_state = 0, cam_state;
+   u32 core_next_state, per_next_state = 0, per_saved_state = 0;
struct omap3_idle_statedata *cx;
int ret;
 
/*
-* Prevent idle completely if CAM is active.
+* Use only C1 if CAM is active.
 * CAM does not have wakeup capability in OMAP3.
 */
-   cam_state = pwrdm_read_pwrst(cam_pd);
-   if (cam_state == PWRDM_POWER_ON) {
+   if (pwrdm_read_pwrst(cam_pd) == PWRDM_POWER_ON)
new_state_idx = drv-safe_state_index;
-   goto select_state;
-   }
+   else
+   new_state_idx = next_valid_state(dev, drv, index);
 
/*
 * FIXME: we currently manage device-specific idle states
@@ -269,24 +268,28 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
 *its own code.
 */
 
-   /*
-* Prevent PER off if CORE is not in retention or off as this
-* would disable PER wakeups completely.
-*/
-   cx = cpuidle_get_statedata(dev-states_usage[index]);
+   /* Program PER state */
+   cx = cpuidle_get_statedata(dev-states_usage[new_state_idx]);
core_next_state = cx-core_state;
per_next_state = per_saved_state = pwrdm_read_next_pwrst(per_pd);
-   if ((per_next_state == PWRDM_POWER_OFF) 
-   (core_next_state  PWRDM_POWER_RET))
-   per_next_state = PWRDM_POWER_RET;
+   if (new_state_idx == 0) {
+   /* In C1 do not allow PER state lower than CORE state */
+   if (per_next_state  core_next_state)
+   per_next_state = core_next_state;
+   } else {
+   /*
+* Prevent PER OFF if CORE is not in RETention or OFF as this
+* would disable PER wakeups completely.
+*/
+   if ((per_next_state == PWRDM_POWER_OFF) 
+   (core_next_state  PWRDM_POWER_RET))
+   per_next_state = PWRDM_POWER_RET;
+   }
 
/* Are we changing PER target state? */
if (per_next_state != per_saved_state)
pwrdm_set_next_pwrst(per_pd, per_next_state);
 
-   new_state_idx = next_valid_state(dev, drv, index);
-
-select_state:
ret = omap3_enter_idle(dev, drv, new_state_idx);
 
/* Restore original PER state if it was modified */
@@ -372,7 +375,6 @@ int __init omap3_idle_init(void)
 
/* C1 . MPU WFI + Core active */
_fill_cstate(drv, 0, MPU ON + CORE ON);
-   (drv-states[0])-enter = omap3_enter_idle;
drv-safe_state_index = 0;
cx = _fill_cstate_usage(dev, 0);
cx-valid = 1;  /* C1 is always valid */
-- 
1.7.7.6

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


[PATCH 2/2] ARM: OMAP3: PM: cpuidle: optimize the clkdm idle latency in C1 state

2012-05-09 Thread jean . pihet
From: Jean Pihet j-pi...@ti.com

It is not needed to iterate through all the clock domains of a
power domain in order to allow or deny it to idle.
This patch allows or denies only the first registered clock domain
of a power domain, and so optimizes the latency of the low power
code. The functions _cpuidle_allow_idle and _cpuidle_deny_idle are
not used anymore and so are removed.

Signed-off-by: Jean Pihet j-pi...@ti.com
---
 arch/arm/mach-omap2/cpuidle34xx.c |   22 --
 1 files changed, 4 insertions(+), 18 deletions(-)

diff --git a/arch/arm/mach-omap2/cpuidle34xx.c 
b/arch/arm/mach-omap2/cpuidle34xx.c
index 353dd8d..d44b68a 100644
--- a/arch/arm/mach-omap2/cpuidle34xx.c
+++ b/arch/arm/mach-omap2/cpuidle34xx.c
@@ -73,20 +73,6 @@ struct omap3_idle_statedata 
omap3_idle_data[OMAP3_NUM_STATES];
 
 struct powerdomain *mpu_pd, *core_pd, *per_pd, *cam_pd;
 
-static int _cpuidle_allow_idle(struct powerdomain *pwrdm,
-   struct clockdomain *clkdm)
-{
-   clkdm_allow_idle(clkdm);
-   return 0;
-}
-
-static int _cpuidle_deny_idle(struct powerdomain *pwrdm,
-   struct clockdomain *clkdm)
-{
-   clkdm_deny_idle(clkdm);
-   return 0;
-}
-
 static int __omap3_enter_idle(struct cpuidle_device *dev,
struct cpuidle_driver *drv,
int index)
@@ -105,8 +91,8 @@ static int __omap3_enter_idle(struct cpuidle_device *dev,
 
/* Deny idle for C1 */
if (index == 0) {
-   pwrdm_for_each_clkdm(mpu_pd, _cpuidle_deny_idle);
-   pwrdm_for_each_clkdm(core_pd, _cpuidle_deny_idle);
+   clkdm_deny_idle(mpu_pd-pwrdm_clkdms[0]);
+   clkdm_deny_idle(core_pd-pwrdm_clkdms[0]);
}
 
/*
@@ -128,8 +114,8 @@ static int __omap3_enter_idle(struct cpuidle_device *dev,
 
/* Re-allow idle for C1 */
if (index == 0) {
-   pwrdm_for_each_clkdm(mpu_pd, _cpuidle_allow_idle);
-   pwrdm_for_each_clkdm(core_pd, _cpuidle_allow_idle);
+   clkdm_allow_idle(mpu_pd-pwrdm_clkdms[0]);
+   clkdm_allow_idle(core_pd-pwrdm_clkdms[0]);
}
 
 return_sleep_time:
-- 
1.7.7.6

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


Re: PM related performance degradation on OMAP3

2012-05-09 Thread Jean Pihet
Hi Kevin,

On Mon, May 7, 2012 at 7:31 PM, Kevin Hilman khil...@ti.com wrote:
 Jean Pihet jean.pi...@newoldbits.com writes:

 On Tue, May 1, 2012 at 7:27 PM, Kevin Hilman khil...@ti.com wrote:
 Jean Pihet jean.pi...@newoldbits.com writes:

 HI Kevin, Grazvydas,

 On Tue, Apr 24, 2012 at 4:29 PM, Kevin Hilman khil...@ti.com wrote:
 Jean Pihet jean.pi...@newoldbits.com writes:

 Hi Grazvydas, Kevin,

 I did some gather some performance measurements and statistics using
 custom tracepoints in __omap3_enter_idle.
 I posted the patches for the power domains registers cache, cf.
 http://marc.info/?l=linux-omapm=133587781712039w=2.

 All the details are at
 http://www.omappedia.org/wiki/Power_Management_Device_Latencies_Measurement#C1_performance_problem:_analysis
 I updated the page with the measurements results with Kevin's patches
 and the registers cache patches.

 The results are showing that:
 - the registers cache optimizes the low power mode transitions, but is
 not sufficient to obtain a big gain. A few unused domains are
 transitioning, which causes a big penalty in the idle path.

 PER is the one that seems to be causing the most latency.

 Can you try do your measurements using hack below which makes sure that
 PER isn't any deeper than CORE?

 Indeed your patch brings significant improvements, cf. wiki page at
 http://www.omappedia.org/wiki/Power_Management_Device_Latencies_Measurement#C1_performance_problem:_analysis
 for detailed information.
 Here below is the reworked patch, more suited for inclusion in mainline [1]

 I have another optimisation -in proof of concept state- that brings
 another significant improvement. It is about allowing/disabling idle
 for only 1 clkdm in a pwrdm and not iterate through all the clkdms.
 This still needs some rework though. Cf. patch [2]

 That should work since disabling idle for any clkdm will have the same
 effect.  Can you send this as a separate patch with a descriptive
 changelog.
I just sent 2 patches which optimize the C1 state latency:
 . [PATCH 1/2] ARM: OMAP3: PM: cpuidle: optimize the PER latency in C1 state
 . [PATCH 2/2] ARM: OMAP3: PM: cpuidle: optimize the clkdm idle
latency in C1 state

Note: those patches apply on top of your pre/post_transition
optimization patches.

The performance results are close to the !PM case (No IDLE, no
omap_sram_idle, all pwrdms to ON), i.e. 3.1MB/s on Beagleboard.
The wiki page update comes asap.

Regards,
Jean


 Kevin


 Patches [1] and [2] on top of the registers cache and the
 optimisations in pre/post_transition bring the performance close to
 the performance for the non cpuidle case (3.0MB/s compared to 3.1MB/s
 on Beagleboard).

 What do you think?

 Regards,
 Jean

 ---
 [1]
 diff --git a/arch/arm/mach-omap2/cpuidle34xx.c
 b/arch/arm/mach-omap2/cpuidle34xx.c
 index e406d7b..572b605 100644
 +++ b/arch/arm/mach-omap2/cpuidle34xx.c
 @@ -279,32 +279,36 @@ static int omap3_enter_idle_bm(struct cpuidle_device 
 *dev,
       int ret;

       /*
 -      * Prevent idle completely if CAM is active.
 +      * Use only C1 if CAM is active.
        * CAM does not have wakeup capability in OMAP3.
        */
 -     if (pwrdm_read_func_pwrst(cam_pd) == PWRDM_FUNC_PWRST_ON) {
 +     if (pwrdm_read_func_pwrst(cam_pd) == PWRDM_FUNC_PWRST_ON)
               new_state_idx = drv-safe_state_index;
 -             goto select_state;
 -     }
 -
 -     new_state_idx = next_valid_state(dev, drv, index);
 +     else
 +             new_state_idx = next_valid_state(dev, drv, index);

 -     /*
 -      * Prevent PER off if CORE is not in retention or off as this
 -      * would disable PER wakeups completely.
 -      */
 +     /* Program PER state */
       cx = cpuidle_get_statedata(dev-states_usage[new_state_idx]);
       core_next_state = cx-core_state;
 -     per_next_state = per_saved_state = pwrdm_read_next_func_pwrst(per_pd);
 -     if ((per_next_state == PWRDM_FUNC_PWRST_OFF) 
 -         (core_next_state  PWRDM_FUNC_PWRST_CSWR))
 -             per_next_state = PWRDM_FUNC_PWRST_CSWR;
 +     if (new_state_idx == 0) {
 +             /* In C1 do not allow PER state lower than CORE state */
 +             per_next_state = core_next_state;
 +     } else {
 +             /*
 +              * Prevent PER off if CORE is not in RETention or OFF as this
 +              * would disable PER wakeups completely.
 +              */
 +             per_next_state = per_saved_state =
 +                             pwrdm_read_next_func_pwrst(per_pd);
 +             if ((per_next_state == PWRDM_FUNC_PWRST_OFF) 
 +                 (core_next_state  PWRDM_FUNC_PWRST_CSWR))
 +                     per_next_state = PWRDM_FUNC_PWRST_CSWR;
 +     }

       /* Are we changing PER target state? */
       if (per_next_state != per_saved_state)
               omap_set_pwrdm_state(per_pd, per_next_state);

 -select_state:
       ret = omap3_enter_idle(dev, drv, new_state_idx);

       /* Restore original PER state if it was modified */
 @@ -390,7 +394,6 @@ int

Re: [PATCH 1/6] ARM: OMAP2+: PM: protect the power domain state change by a mutex

2012-05-08 Thread Jean Pihet
Hi Paul,

Thanks for the review. Do you plan to review the full set before I
start to address the comments.

On Mon, May 7, 2012 at 8:41 AM, Paul Walmsley p...@pwsan.com wrote:
 Hi

 On Wed, 18 Apr 2012, jean.pi...@newoldbits.com wrote:

 From: Jean Pihet j-pi...@ti.com

 Signed-off-by: Jean Pihet j-pi...@ti.com

 This patch is missing a description, which would describe why this lock is
 needed and what it protects against.  Please add this.
Ok


 ---
  arch/arm/mach-omap2/pm.c          |    8 ++--
  arch/arm/mach-omap2/powerdomain.c |    1 +
  arch/arm/mach-omap2/powerdomain.h |    3 ++-
  3 files changed, 9 insertions(+), 3 deletions(-)

 diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
 index d0c1c96..6918a13 100644
 --- a/arch/arm/mach-omap2/pm.c
 +++ b/arch/arm/mach-omap2/pm.c
 @@ -100,15 +100,17 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm, 
 u32 pwrst)
       if (!pwrdm || IS_ERR(pwrdm))
               return -EINVAL;

 +     mutex_lock(pwrdm-lock);
 +
       while (!(pwrdm-pwrsts  (1  pwrst))) {
               if (pwrst == PWRDM_POWER_OFF)
 -                     return ret;
 +                     goto out;
               pwrst--;
       }

       next_pwrst = pwrdm_read_next_pwrst(pwrdm);
       if (next_pwrst == pwrst)
 -             return ret;
 +             goto out;

       curr_pwrst = pwrdm_read_pwrst(pwrdm);
       if (curr_pwrst  PWRDM_POWER_ON) {
 @@ -141,6 +143,8 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 
 pwrst)
               break;
       }

 +out:
 +     mutex_unlock(pwrdm-lock);
       return ret;
  }


 So this mutex would protect against simultaneous calls to
 omap_set_pwrdm_state(), but shouldn't this protection be extended to
 anything that would change the powerdomain's state?  For example, couldn't
 other calls to pwrdm_set_next_pwrst() race against this function?
The intention behind this patch set is to change the API to only use
omap_set_pwrdm_state to change the power domains states. Probably I
should emphasize more on that in the cover letter and commits
description.


 diff --git a/arch/arm/mach-omap2/powerdomain.c 
 b/arch/arm/mach-omap2/powerdomain.c
 index 96ad3dbe..319b277 100644
 --- a/arch/arm/mach-omap2/powerdomain.c
 +++ b/arch/arm/mach-omap2/powerdomain.c
 @@ -102,6 +102,7 @@ static int _pwrdm_register(struct powerdomain *pwrdm)
       INIT_LIST_HEAD(pwrdm-voltdm_node);
       voltdm_add_pwrdm(voltdm, pwrdm);

 +     mutex_init(pwrdm-lock);
       list_add(pwrdm-node, pwrdm_list);

       /* Initialize the powerdomain's state counter */
 diff --git a/arch/arm/mach-omap2/powerdomain.h 
 b/arch/arm/mach-omap2/powerdomain.h
 index 0d72a8a..6c6567d 100644
 --- a/arch/arm/mach-omap2/powerdomain.h
 +++ b/arch/arm/mach-omap2/powerdomain.h
 @@ -19,7 +19,7 @@

  #include linux/types.h
  #include linux/list.h
 -
 +#include linux/mutex.h
  #include linux/atomic.h

  #include plat/cpu.h
 @@ -116,6 +116,7 @@ struct powerdomain {
       struct clockdomain *pwrdm_clkdms[PWRDM_MAX_CLKDMS];
       struct list_head node;
       struct list_head voltdm_node;
 +     struct mutex lock;
       int state;
       unsigned state_counter[PWRDM_MAX_PWRSTS];
       unsigned ret_logic_off_counter;

 Please add a kerneldoc entry in the struct powerdomain documentation for
 this field.
Ok



 - Paul

Thanks,
Jean
--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 2/6] ARM: OMAP2+: PM: introduce power domains functional states

2012-05-08 Thread Jean Pihet
Paul,

On Mon, May 7, 2012 at 11:28 AM, Paul Walmsley p...@pwsan.com wrote:
 Hi

 On Wed, 18 Apr 2012, jean.pi...@newoldbits.com wrote:

 From: Jean Pihet j-pi...@ti.com

 Introduce functional (or logical) states for power domains and the
 API functions to read the power domains settings and to convert
 between the functional (i.e. logical) and the internal (or registers)
 values.

 OMAP2, OMAP3 and OMAP4 platforms are defining a conversion routine.

 In the new API the function omap_set_pwrdm_state takes the functional
 states as parameter; while at it the function is moved to the power
 domains code.

 The memory and logic states are not using the functional states, this
 comes as a subsequent patch.

 Signed-off-by: Jean Pihet j-pi...@ti.com

 This patch results in several checkpatch warnings; please resolve them.
Oops. Will check and update.


 ---
  arch/arm/mach-omap2/pm.c                   |   66 ---
  arch/arm/mach-omap2/powerdomain-common.c   |   61 ++
  arch/arm/mach-omap2/powerdomain.c          |  175 
 
  arch/arm/mach-omap2/powerdomain.h          |   21 
  arch/arm/mach-omap2/powerdomain2xxx_3xxx.c |    5 +
  arch/arm/mach-omap2/powerdomain44xx.c      |    2 +
  6 files changed, 264 insertions(+), 66 deletions(-)

...

 +/*
 + * Functional (i.e. logical) to internal (i.e. registers)
 + * values for the power domains states
 + */

 Please use kerneldoc-style function comments.
Ok


 +int omap2_pwrdm_func_to_pwrst(struct powerdomain *pwrdm, u8 func_pwrst)
 +{
 +     int ret;
 +
 +     switch (func_pwrst) {
 +     case PWRDM_FUNC_PWRST_ON:
 +             ret = PWRDM_POWER_ON;
 +             break;
 +     case PWRDM_FUNC_PWRST_INACTIVE:
 +             ret = PWRDM_POWER_INACTIVE;
 +             break;
 +     case PWRDM_FUNC_PWRST_CSWR:
 +     case PWRDM_FUNC_PWRST_OSWR:
 +             ret = PWRDM_POWER_RET;
 +             break;
 +     case PWRDM_FUNC_PWRST_OFF:
 +             ret = PWRDM_POWER_OFF;
 +             break;
 +     default:
 +             ret = -1;
 +     }
 +
 +     return ret;
 +}

 At a quick glance, I don't think that this function is appropriate for all
 OMAP2+ chips.  For example, off-mode is not supported in our OMAP2xxx
 kernels.  And OMAP2xxx/3xxx do not support the INACTIVE powerstate.  So
 probably this function should differ by chip, and be located in the
 powerdomain[2-4]*xx*.c files.
I hope to make this function as generic as possible, hence the
location (powerdomain-common.c). Some states are not programmed by the
pwrdm_* functions since there forbidden by the contents of the
pwrdm-pwrst field.
Now if the need arises some platform specific function can be defined
for conversion functions since the pwrdm-ops function pointers are
used. I do not think it is needed now but it can easily be changed.

 Also, what about the logic and memory bank power states?  Shouldn't this
 function pass those back as well?
Cf. in the description The memory and logic states are not using the
functional states, this comes as a subsequent patch.


 +
 +/*
 + * Internal (i.e. registers) to functional (i.e. logical) values
 + * for the power domains states
 + */

 Please use kerneldoc-style function documentation.
Ok


 +int omap2_pwrdm_pwrst_to_func(struct powerdomain *pwrdm, u8 pwrst)

 Probably best to use func_pwrst or fpwrst rather than simply func
 here.
Ok. I am for 'omap2_pwrdm_pwrst_to_fpwrst(...)'.


 +{
 +     int ret;
 +
 +     switch (pwrst) {
 +     case PWRDM_POWER_ON:
 +             ret = PWRDM_FUNC_PWRST_ON;
 +             break;
 +     case PWRDM_POWER_INACTIVE:
 +             ret = PWRDM_FUNC_PWRST_INACTIVE;
 +             break;
 +     case PWRDM_POWER_RET:
 +             /*
 +              * XXX warning: return OSWR in case of pd in RET and
 +              * logic in OFF
 +              */
 +             ret = PWRDM_FUNC_PWRST_CSWR;
 +             break;
 +     case PWRDM_POWER_OFF:
 +             ret = PWRDM_FUNC_PWRST_OFF;
 +             break;
 +     default:
 +             ret = -1;
 +     }
 +
 +     return ret;
 +}

 This function also needs to check the bank power states and logic power
 states to determine what the actual functional powerstate is.
Same remark as above + there is a comment about it in the code (XXX warning).

 +
 diff --git a/arch/arm/mach-omap2/powerdomain.c 
 b/arch/arm/mach-omap2/powerdomain.c
 index 319b277..718fa43 100644
 --- a/arch/arm/mach-omap2/powerdomain.c
 +++ b/arch/arm/mach-omap2/powerdomain.c
 @@ -466,6 +466,136 @@ int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm)
  }

  /**
 + * pwrdm_func_to_pwrst - get the internal (i.e. registers) value mapped
 + * to the functional state

 Probably best to use func_pwrst or fpwrst rather than simply func
 here.
Ok


 + * @pwrdm: struct powerdomain * to query
 + * @func_pwrst: functional power state
 + *
 + * Convert the functional power state to the platform specific power
 + * domain state value.
 + * Returns the internal power domain state

Re: oprofile and ARM A9 hardware counter

2012-05-08 Thread Jean Pihet
Hi Benoit,

On Tue, May 8, 2012 at 1:01 PM, Cousson, Benoit b-cous...@ti.com wrote:
 Hi Kevin  Jon,


 On 5/8/2012 1:28 AM, Kevin Hilman wrote:

 Jon Hunterjon-hun...@ti.com  writes:

 Hi Kevin,

 On 05/07/2012 12:15 PM, Kevin Hilman wrote:

 Jon Hunterjon-hun...@ti.com  writes:

 Hi Will,

 On 04/26/2012 01:07 PM, Will Deacon wrote:

 On Wed, Apr 04, 2012 at 12:15:24PM +0100, Will Deacon wrote:

 On Wed, Apr 04, 2012 at 12:29:49AM +0100, Paul Walmsley wrote:


 Part of the problem is that the clockdomain data for the emu_sys
 clockdomain is wrong.  Here's something to try to fix it.  It might
 just
 be enough to get it to work.


 Hmm, doesn't seem to work but I do see the following in dmesg when I
 try to
 use perf:

  powerdomain: waited too long for powerdomain emu_pwrdm to complete
 transition

 which is new with your patch.


 Sorry to nag, but does anybody have a clue where to go from here? I
 can
 start digging in the OMAP PM code, but it's all new territory for me.


 I did a little playing around with this today and I think that I have
 figured out why this was not working (see below). Please can you try the
 following patch? I tried this on top of your series for perf/omap4.

 Paul, FYI. If this works for Will then I can re-base on top of the
 latest linux-omap and submit to the mailing list.

 Also, the above error about the emu_pwrdm is odd too. I noticed that
 the emu_pwrdm is always in the transitioning state. And when I say 
 always, I
 mean that even if I check the power domain state while u-boot is running 
 it
 is in the transitioning state. So even before the kernel starts.

 Cheers
 Jon

  From 9137ff9c1b382232de7443db0b51b7555846fb62 Mon Sep 17 00:00:00 2001
 From: Jon Hunterjon-hun...@ti.com
 Date: Fri, 4 May 2012 16:48:45 -0500
 Subject: [PATCH] ARM: OMAP4: Disable auto enable for EMU CLKDM

 The flag CLKDM_CAN_HWSUP allows the clock-domain to automatically
 transition
 to the enabled and disabled state. This means that as soon as we force
 a
 software wake-up on the clock domain, the clock domain will be allowed
 to idle
 and put back into the hardware auto state. For the EMU clock domain
 this is not
 what we want. We want to keep the clock domain in the software wakeup
 state
 while the clock domain is being used and put it back in to the hardware
 auto
 state when we have finished using the clock domain.

 Signed-off-by: Jon Hunterjon-hun...@ti.com


 With this patch, how is the clkdm ever idled?


 It does not! Sorry, I was so engrossed with figuring out why the EMU
 clkdm was being idled as soon as it was enabled, I forgot to check if is
 ever disabled once we terminated perf :-(

 IIUC, your patch will get PMU interrupts working, but similarily to
 previous patches in this thread, it works because it *never* allows the
 EMU clkdm to idle.  This is not a mergeable solution because it will not
 allow CORE retention (and thus full-chip retention.)


 Right!

 What we need is a solution that allows the clkdm to idle, and then to be
 reinitialzed when it wakes up.  Due to the way (I understand) resets in
 the debugss, allowing the clkdm to idle will cause a reset, so the
 PMU/CTI interrupts need to be reinitialzied after wakeup.


 Yes exactly I see that now. I have prototyped the 3 patches and this is
 working AND the EMU clkdm does go back to idle. I can send out to the
 list for review.


 Perfect, thanks.

 Kevin

 P.S. Please note there is also already a different fix in mainline for
 the EMU clkdm data from Paul which adds the force wakeup flag and
 removes the DISABLE_AUTO flag[1] (but leaves the ENABLE_AUTO flag,
 because the hardware is capable.)


 Hmmm ... yes saw this, and you will have to excuse me as I don't fully
 follow the logic here. In fact, I am thinking we want the opposite ;-)

  From looking, into this it seems to me that when PMU is running we want
 the EMU clock domain in software-wakeup state and when PMU is not
 running we want in the hardware auto state.


 So far, I'm with you.

 By keeping the ENABLE_AUTO flag set, as soon as we enable the clock
 domain it is put right back into the HW_AUTO state


 This is only because it was in the HWSUP state when _enable was called.
 If clkdm_deny_idle() is used, that behavior will change.

 and hence PMU is
 not working (see _enable() function in
 arch/arm/mach-omap2/omap_hwmod.c)

 So really what I think we want is to remove the ENABLE_AUTO flag to keep
 the clock domain in software wake-up and use the DISABLE_AUTO flag to
 put the clock domain back in HW_AUTO (note this requires a patch to
 perform this 2nd part).


 Well, Paul will have to comment here for the final word, but IIUC, the
 hwmod flags are supposed to indicate only what the HW is capable of.  If
 we want to change the runtime behavior, we nee to use (or add) APIs to
 change the beahvior.  In this case, clkdm_allow_idle(),
 clkdm_deny_idle() are probably what is needed here.


 Yes, indeed, we should not hack the flags to fix that kind of issue. 

Re: oprofile and ARM A9 hardware counter

2012-05-08 Thread Jean Pihet
On Tue, May 8, 2012 at 2:37 PM, Cousson, Benoit b-cous...@ti.com wrote:
 Salut Jean,


 On 5/8/2012 1:23 PM, Jean Pihet wrote:

 Hi Benoit,

 On Tue, May 8, 2012 at 1:01 PM, Cousson, Benoitb-cous...@ti.com  wrote:

 Hi Kevin  Jon,



 On 5/8/2012 1:28 AM, Kevin Hilman wrote:


 Jon Hunterjon-hun...@ti.com    writes:

 Hi Kevin,

 On 05/07/2012 12:15 PM, Kevin Hilman wrote:


 Jon Hunterjon-hun...@ti.com    writes:

 Hi Will,

 On 04/26/2012 01:07 PM, Will Deacon wrote:


 On Wed, Apr 04, 2012 at 12:15:24PM +0100, Will Deacon wrote:


 On Wed, Apr 04, 2012 at 12:29:49AM +0100, Paul Walmsley wrote:



 Part of the problem is that the clockdomain data for the emu_sys
 clockdomain is wrong.  Here's something to try to fix it.  It
 might
 just
 be enough to get it to work.



 Hmm, doesn't seem to work but I do see the following in dmesg when
 I
 try to
 use perf:

  powerdomain: waited too long for powerdomain emu_pwrdm to complete
 transition

 which is new with your patch.



 Sorry to nag, but does anybody have a clue where to go from here? I
 can
 start digging in the OMAP PM code, but it's all new territory for
 me.



 I did a little playing around with this today and I think that I have
 figured out why this was not working (see below). Please can you try
 the
 following patch? I tried this on top of your series for perf/omap4.

 Paul, FYI. If this works for Will then I can re-base on top of the
 latest linux-omap and submit to the mailing list.

 Also, the above error about the emu_pwrdm is odd too. I noticed that
 the emu_pwrdm is always in the transitioning state. And when I say
 always, I
 mean that even if I check the power domain state while u-boot is
 running it
 is in the transitioning state. So even before the kernel starts.

 Cheers
 Jon

  From 9137ff9c1b382232de7443db0b51b7555846fb62 Mon Sep 17 00:00:00
 2001
 From: Jon Hunterjon-hun...@ti.com
 Date: Fri, 4 May 2012 16:48:45 -0500
 Subject: [PATCH] ARM: OMAP4: Disable auto enable for EMU CLKDM

 The flag CLKDM_CAN_HWSUP allows the clock-domain to automatically
 transition
 to the enabled and disabled state. This means that as soon as we
 force
 a
 software wake-up on the clock domain, the clock domain will be
 allowed
 to idle
 and put back into the hardware auto state. For the EMU clock domain
 this is not
 what we want. We want to keep the clock domain in the software wakeup
 state
 while the clock domain is being used and put it back in to the
 hardware
 auto
 state when we have finished using the clock domain.

 Signed-off-by: Jon Hunterjon-hun...@ti.com



 With this patch, how is the clkdm ever idled?



 It does not! Sorry, I was so engrossed with figuring out why the EMU
 clkdm was being idled as soon as it was enabled, I forgot to check if
 is
 ever disabled once we terminated perf :-(

 IIUC, your patch will get PMU interrupts working, but similarily to
 previous patches in this thread, it works because it *never* allows
 the
 EMU clkdm to idle.  This is not a mergeable solution because it will
 not
 allow CORE retention (and thus full-chip retention.)



 Right!

 What we need is a solution that allows the clkdm to idle, and then to
 be
 reinitialzed when it wakes up.  Due to the way (I understand) resets
 in
 the debugss, allowing the clkdm to idle will cause a reset, so the
 PMU/CTI interrupts need to be reinitialzied after wakeup.



 Yes exactly I see that now. I have prototyped the 3 patches and this is
 working AND the EMU clkdm does go back to idle. I can send out to the
 list for review.



 Perfect, thanks.

 Kevin

 P.S. Please note there is also already a different fix in mainline for
 the EMU clkdm data from Paul which adds the force wakeup flag and
 removes the DISABLE_AUTO flag[1] (but leaves the ENABLE_AUTO flag,
 because the hardware is capable.)



 Hmmm ... yes saw this, and you will have to excuse me as I don't fully
 follow the logic here. In fact, I am thinking we want the opposite ;-)

  From looking, into this it seems to me that when PMU is running we
 want
 the EMU clock domain in software-wakeup state and when PMU is not
 running we want in the hardware auto state.



 So far, I'm with you.

 By keeping the ENABLE_AUTO flag set, as soon as we enable the clock
 domain it is put right back into the HW_AUTO state



 This is only because it was in the HWSUP state when _enable was called.
 If clkdm_deny_idle() is used, that behavior will change.

 and hence PMU is
 not working (see _enable() function in
 arch/arm/mach-omap2/omap_hwmod.c)

 So really what I think we want is to remove the ENABLE_AUTO flag to
 keep
 the clock domain in software wake-up and use the DISABLE_AUTO flag to
 put the clock domain back in HW_AUTO (note this requires a patch to
 perform this 2nd part).



 Well, Paul will have to comment here for the final word, but IIUC, the
 hwmod flags are supposed to indicate only what the HW is capable of.  If
 we want to change the runtime behavior, we nee to use (or add) APIs to
 change

Re: [PATCH] arm: omap: Use only valid power domain states

2012-05-03 Thread Jean Pihet
Hi Mark,

On Thu, May 3, 2012 at 12:04 AM, Mark A. Greer mgr...@animalcreek.com wrote:
 On Tue, May 01, 2012 at 10:47:35AM +0200, Jean Pihet wrote:
 Hi Mark,

 Hi Jean.  Thanks for the review.

 On Mon, Apr 30, 2012 at 11:25 PM, Mark A. Greer mgr...@animalcreek.com 
 wrote:
  From: Mark A. Greer mgr...@animalcreek.com

  diff --git a/arch/arm/mach-omap2/cpuidle34xx.c 
  b/arch/arm/mach-omap2/cpuidle34xx.c
  index 5358664..2c91711 100644
  --- a/arch/arm/mach-omap2/cpuidle34xx.c
  +++ b/arch/arm/mach-omap2/cpuidle34xx.c
  @@ -175,19 +175,25 @@ static int next_valid_state(struct cpuidle_device 
  *dev,
         struct cpuidle_state_usage *curr_usage = dev-states_usage[index];
         struct cpuidle_state *curr = drv-states[index];
         struct omap3_idle_statedata *cx = cpuidle_get_statedata(curr_usage);
  -       u32 mpu_deepest_state = PWRDM_POWER_RET;
  -       u32 core_deepest_state = PWRDM_POWER_RET;
  +       u32 mpu_deepest_state, mpu_deepest_possible;
  +       u32 core_deepest_state, core_deepest_possible;
         int next_index = -1;
 
  +       mpu_deepest_possible = pwrdm_get_deepest_state(mpu_pd);
  +       mpu_deepest_state = max_t(u32, mpu_deepest_possible, 
  PWRDM_POWER_RET);
 I do not think you need to change the pwrdm API and the cpuidle code for 
 that.
 Instead you should use the pwrst* fields in the power domains data
 files, which allow to specify the allowed states.
 After reading the rest of your patches it seems you are addressing the
 issue in a subsequent patch 'arm: omap3: am35x: Set proper powerdomain
 states'.

 That patch sets the allowable power domain states for the am35x; the intent
 of this patch was to make the code respect what is set in the pwrst* fields.

  diff --git a/arch/arm/mach-omap2/powerdomain.c 
  b/arch/arm/mach-omap2/powerdomain.c
  index 96ad3dbe..9c80c19 100644
  --- a/arch/arm/mach-omap2/powerdomain.c
  +++ b/arch/arm/mach-omap2/powerdomain.c
  @@ -1078,3 +1078,28 @@ bool pwrdm_can_ever_lose_context(struct powerdomain 
  *pwrdm)
 
         return 0;
   }
  +
  +/**
  + * pwrdm_get_deepest_state - Get deepest valid state domain can enter
  + * @pwrdm: struct powerdomain *
  + *
  + * Find and return the deepest valid state a power domain can be in.
  + * Returns the deepest state that @pwrdm can enter.
  + */
  +u32 pwrdm_get_deepest_state(struct powerdomain *pwrdm)
  +{
  +       u32 valid_states, deepest_state;
  +
  +       valid_states = pwrdm-pwrsts;
  +
  +       if (valid_states  PWRSTS_OFF)
  +               deepest_state = PWRDM_POWER_OFF;
  +       else if (valid_states  PWRSTS_RET)
  +               deepest_state = PWRDM_POWER_RET;
  +       else if (valid_states  PWRSTS_INACTIVE)
  +               deepest_state = PWRDM_POWER_INACTIVE;
  +       else
  +               deepest_state = PWRDM_POWER_ON;
  +
  +       return deepest_state;
  +}

 The pwrdm API already performs those checks on pwrst*, cf.
 pwrdm_set_next_pwrst for example.

 Well, sort of.  pwrdm_set_next_pwrst() fails if its an invalid state
 returning -EINVAL.  Very few of the callers actually check to see if
 it failed so they don't try the next-one-up power state.  The net
 result is that the next state doesn't change even though it could
 move to a lower state (just not the one that was asked for).

 Is that acceptable?
No that is not acceptable. In fact the next power state should only be
set using omap_set_pwrdm_state, which falls back to the next valid
power state. Note: my latest patches about the functional power states
is using omap_set_pwrdm_state as the only function to set the power,
logic states.

 Another sort of strange one is omap3_pm_off_mode_enable().  If its
 called with 'enable' set and PWRDM_POWER_OFF isn't a valid state,
 omap_set_pwrdm_state() will return 0 and leave the next state alone.
 When omap3_pm_off_mode_enable() is called again with 'enable' set,
 omap_set_pwrdm_state() will find the lowest valid state = RET.
 So, if you had a device where OFF wasn't valid but RET was and
 its currently ON, when the user enables OFF mode, it stays ON
 and when they disable OFF mode, it moves to RET.

 Is that acceptable?
No. omap_set_pwrdm_state should be fixed in that case.
In fact the enable_off_mode flag is scheduled for removal in favor of
the PM QoS constraints.

 If the things above are acceptable, then I think you're right, we can
 forget this patch.  FYI, the am35x appears to work okay and no invalid
 states are entered (according to /sys/kernel/debug/pm_debug/count)
 without this patch.
I think we should fix the existing code if it has problems, not add
more specific code.

Kevin, what is your take on this?

 Mark

Regards,
Jean
--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 2/5] ARM: OMAP2+: PM: use the power domains registers cache for the power states

2012-05-03 Thread Jean Pihet
Hi Jon, Vaibhav,

On Thu, May 3, 2012 at 8:38 AM, Bedia, Vaibhav vaibhav.be...@ti.com wrote:
 On Tue, May 01, 2012 at 21:07:39, Hunter, Jon wrote:
 [...]
   int pwrdm_read_pwrst(struct powerdomain *pwrdm)
   {
  -   int ret = -EINVAL;
  +   int pwrst, ret = -EINVAL;
 
      if (!pwrdm)
              return -EINVAL;
 
  -   if (arch_pwrdm  arch_pwrdm-pwrdm_read_pwrst)
  +   if (!pwrdm_cache_read(pwrdm, PWRDM_CACHE_PWRST, pwrst))
  +           return pwrst;
  +
  +   if (arch_pwrdm  arch_pwrdm-pwrdm_read_pwrst) {
              ret = arch_pwrdm-pwrdm_read_pwrst(pwrdm);
  +           if (ret = 0)
  +                   pwrdm_cache_write(pwrdm, PWRDM_CACHE_PWRST, ret);
  +   }

 Do we really want to use the cache for the current state? This is
 updated by hardware. In the above it appears that once we have read it
 once we will just return this value until the cache is invalidated.
 Makes me a little nervous.
I agree with your concerns. The HW can update things in our back and
so there is a risk of having the wrong state reported by the API.
Ideally the registers accesses shall be optimized in the HW itself
(hint for next gen chipsets ;-).

IMO a generic approach on caching is preferred on a hack on the low power code.

The cache implementation is based on the following principles:
1. the registers value are read from the cache if it is 'hot', the
values are read from the registers if the cache has been invalidated
2. the coherency of the cache fields relies on the invalidate of the
fields at the right time during the low power transitions
3. the previous states fields of the cache are invalidated when
clearing the previous power states
4. the current states fields of the cache are invalidated after coming
back from the low power mode, i.e. after the return from the low level
WFI instruction
5. the pwrdm_state_switch function detects the states changes, updates
the last internal state (pwrdm-state) and the states statistics
6. in PM debug any discrepancy between pwrdm-state and the current
state from the API is reported. More checking could be added in PM
debug

So there must be a compromise on which fields are invalidated and
when. I first tried to invalidate the whole cache after every low
power transition, which works fine but does not gain much in
performance. The current invalidate scheme (points 3, 4) is optimized
for performance and has been tested succesfully on OMAP3 (using
cpuidle in RET and OFF).

In any case if the HW asynchronously changes the registers states it
will not always be detected, with or without the cache implementation.
For example if a power domain transitions more than once, only the
last transition -to a different state than pwrdm-state- will be
detected the next time pwrdm_state_switch runs.


 I echo the concern here. If a powerdomain transition occurs when h/w 
 conditions
 are met, the cached values will go out of sync and this may lead to unexpected
 behavior wherever this API is being used.

 As Jon pointed out in another patch, the registers which can be updated by 
 h/w should
 be handled differently.
Agree but if you do not cache the previous and current registers there
is no point in having the cache in place.


 Just a wild thought, can PRCM_MPU_IRQ ([4]TRANSITION_EN) be used as a trigger 
 to update
 the cache if the transition happened under s/w control?
That is a nice suggestion. We need to explore the ways to detect transitions.


 Regards,
 Vaibhav

Thanks for your comments!

Regards,
Jean
--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCHv4 8/8] ARM: OMAP4: PM: Added option for enabling OSWR

2012-05-03 Thread Jean Pihet
Hi Tero,

On Fri, Apr 20, 2012 at 11:19 AM, Tero Kristo t-kri...@ti.com wrote:
 PM debug now contains a file that can be used to control OSWR support
 enable / disable on OMAP4. Also removed the off_mode_enable file for
 the same platform as it is unsupported.

 Signed-off-by: Tero Kristo t-kri...@ti.com
 ---
  arch/arm/mach-omap2/pm-debug.c |   20 
  arch/arm/mach-omap2/pm.h       |    1 +
  arch/arm/mach-omap2/pm44xx.c   |   16 
  3 files changed, 33 insertions(+), 4 deletions(-)

 diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c
 index 814bcd9..d9a8e42 100644
 --- a/arch/arm/mach-omap2/pm-debug.c
 +++ b/arch/arm/mach-omap2/pm-debug.c
 @@ -39,6 +39,7 @@
  #include pm.h

  u32 enable_off_mode;
 +static u32 enable_oswr_mode;

  #ifdef CONFIG_DEBUG_FS
  #include linux/debugfs.h
 @@ -247,10 +248,13 @@ static int option_set(void *data, u64 val)
                        omap_pm_enable_off_mode();
                else
                        omap_pm_disable_off_mode();
 -               if (cpu_is_omap34xx())
 -                       omap3_pm_off_mode_enable(val);
 +
 +               omap3_pm_off_mode_enable(val);
Great since this change removes a non-init cpu_is_xxx check.

        }

 +       if (option == enable_oswr_mode)
 +               omap4_pm_oswr_mode_enable(val);
 +
        return 0;
  }

 @@ -274,8 +278,16 @@ static int __init pm_dbg_init(void)

        pwrdm_for_each(pwrdms_setup, (void *)d);

 -       (void) debugfs_create_file(enable_off_mode, S_IRUGO | S_IWUSR, d,
 -                                  enable_off_mode, pm_dbg_option_fops);
 +       if (cpu_is_omap34xx())
 +               (void) debugfs_create_file(enable_off_mode,
 +                       S_IRUGO | S_IWUSR, d, enable_off_mode,
 +                       pm_dbg_option_fops);
Is the enable_off_mode entry needed on other OMAP platorms (OMAP3)?

 +
 +       if (cpu_is_omap44xx())
 +               (void) debugfs_create_file(enable_oswr_mode,
 +                       S_IRUGO | S_IWUSR, d, enable_oswr_mode,
 +                       pm_dbg_option_fops);
 +
        pm_dbg_init_done = 1;

Regards,
Jean
--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: PM related performance degradation on OMAP3

2012-05-02 Thread Jean Pihet
On Tue, May 1, 2012 at 7:27 PM, Kevin Hilman khil...@ti.com wrote:
 Jean Pihet jean.pi...@newoldbits.com writes:

 HI Kevin, Grazvydas,

 On Tue, Apr 24, 2012 at 4:29 PM, Kevin Hilman khil...@ti.com wrote:
 Jean Pihet jean.pi...@newoldbits.com writes:

 Hi Grazvydas, Kevin,

 I did some gather some performance measurements and statistics using
 custom tracepoints in __omap3_enter_idle.
 I posted the patches for the power domains registers cache, cf.
 http://marc.info/?l=linux-omapm=133587781712039w=2.

 All the details are at
 http://www.omappedia.org/wiki/Power_Management_Device_Latencies_Measurement#C1_performance_problem:_analysis
 I updated the page with the measurements results with Kevin's patches
 and the registers cache patches.

 The results are showing that:
 - the registers cache optimizes the low power mode transitions, but is
 not sufficient to obtain a big gain. A few unused domains are
 transitioning, which causes a big penalty in the idle path.

 PER is the one that seems to be causing the most latency.

 Can you try do your measurements using hack below which makes sure that
 PER isn't any deeper than CORE?

Indeed your patch brings significant improvements, cf. wiki page at
http://www.omappedia.org/wiki/Power_Management_Device_Latencies_Measurement#C1_performance_problem:_analysis
for detailed information.
Here below is the reworked patch, more suited for inclusion in mainline [1]

I have another optimisation -in proof of concept state- that brings
another significant improvement. It is about allowing/disabling idle
for only 1 clkdm in a pwrdm and not iterate through all the clkdms.
This still needs some rework though. Cf. patch [2]

Patches [1] and [2] on top of the registers cache and the
optimisations in pre/post_transition bring the performance close to
the performance for the non cpuidle case (3.0MB/s compared to 3.1MB/s
on Beagleboard).

What do you think?

Regards,
Jean

---
[1]
diff --git a/arch/arm/mach-omap2/cpuidle34xx.c
b/arch/arm/mach-omap2/cpuidle34xx.c
index e406d7b..572b605 100644
+++ b/arch/arm/mach-omap2/cpuidle34xx.c
@@ -279,32 +279,36 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
int ret;

/*
-* Prevent idle completely if CAM is active.
+* Use only C1 if CAM is active.
 * CAM does not have wakeup capability in OMAP3.
 */
-   if (pwrdm_read_func_pwrst(cam_pd) == PWRDM_FUNC_PWRST_ON) {
+   if (pwrdm_read_func_pwrst(cam_pd) == PWRDM_FUNC_PWRST_ON)
new_state_idx = drv-safe_state_index;
-   goto select_state;
-   }
-
-   new_state_idx = next_valid_state(dev, drv, index);
+   else
+   new_state_idx = next_valid_state(dev, drv, index);

-   /*
-* Prevent PER off if CORE is not in retention or off as this
-* would disable PER wakeups completely.
-*/
+   /* Program PER state */
cx = cpuidle_get_statedata(dev-states_usage[new_state_idx]);
core_next_state = cx-core_state;
-   per_next_state = per_saved_state = pwrdm_read_next_func_pwrst(per_pd);
-   if ((per_next_state == PWRDM_FUNC_PWRST_OFF) 
-   (core_next_state  PWRDM_FUNC_PWRST_CSWR))
-   per_next_state = PWRDM_FUNC_PWRST_CSWR;
+   if (new_state_idx == 0) {
+   /* In C1 do not allow PER state lower than CORE state */
+   per_next_state = core_next_state;
+   } else {
+   /*
+* Prevent PER off if CORE is not in RETention or OFF as this
+* would disable PER wakeups completely.
+*/
+   per_next_state = per_saved_state =
+   pwrdm_read_next_func_pwrst(per_pd);
+   if ((per_next_state == PWRDM_FUNC_PWRST_OFF) 
+   (core_next_state  PWRDM_FUNC_PWRST_CSWR))
+   per_next_state = PWRDM_FUNC_PWRST_CSWR;
+   }

/* Are we changing PER target state? */
if (per_next_state != per_saved_state)
omap_set_pwrdm_state(per_pd, per_next_state);

-select_state:
ret = omap3_enter_idle(dev, drv, new_state_idx);

/* Restore original PER state if it was modified */
@@ -390,7 +394,6 @@ int __init omap3_idle_init(void)

/* C1 . MPU WFI + Core active */
_fill_cstate(drv, 0, MPU ON + CORE ON);
-   (drv-states[0])-enter = omap3_enter_idle;
drv-safe_state_index = 0;
cx = _fill_cstate_usage(dev, 0);
cx-valid = 1;  /* C1 is always valid */

[2]
diff --git a/arch/arm/mach-omap2/cpuidle34xx.c
b/arch/arm/mach-omap2/cpuidle34xx.c
index e406d7b..6aa3c75 100644
--- a/arch/arm/mach-omap2/cpuidle34xx.c
+++ b/arch/arm/mach-omap2/cpuidle34xx.c
@@ -118,8 +118,10 @@ static int __omap3_enter_idle(struct cpuidle_device *dev,

/* Deny idle for C1 */
if (index == 0) {
-   pwrdm_for_each_clkdm(mpu_pd, _cpuidle_deny_idle);
-   pwrdm_for_each_clkdm(core_pd

Re: [PATCH v7 0/6] PM QoS: implement the OMAP low level constraints management code

2012-05-01 Thread Jean Pihet
Hi Kevin,

On Tue, May 1, 2012 at 1:15 AM, Kevin Hilman khil...@ti.com wrote:
 Hi Jean,

 jean.pi...@newoldbits.com writes:

 From: Jean Pihet j-pi...@ti.com

 . Implement the devices wake-up latency constraints using the global
   device PM QoS notification handler which applies the constraints to the
   underlying layer,
 . Implement the low level code which controls the power domains next
   functional power states [3], through the hwmod and pwrdm layers,
 . Add cpuidle and power domains wake-up latency figures for OMAP3, cf.
   comments in the code and [1] for the details on where the numbers
   are magically coming from,
 . Implement the relation between the cpuidle and per-device PM QoS frameworks
   in the OMAP3 specific idle callbacks.
   The chosen C-state shall satisfy the following conditions:
    . the 'valid' field is enabled,
    . it satisfies the enable_off_mode flag,
    . the next state for MPU and CORE power domains is not lower than the
      state programmed by the per-device PM QoS.

 I've just been through this series and it looks good to me.

 Reviewed-by: Kevin Hilman khil...@ti.com
Thx for reviewing!

 ToDo:
 1. support OMAP4 chipset when the low power modes will be supported

 Have you been able to do this with Tero's latest CORE RET and device off
 series?
No I still have to port Tero's latest patch set on top of the
functional power states and the constraints code. This is on my
ToDoNext list ;p


 Kevin


Thanks,
Jean
--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] arm: omap: Use only valid power domain states

2012-05-01 Thread Jean Pihet
Hi Mark,

On Mon, Apr 30, 2012 at 11:25 PM, Mark A. Greer mgr...@animalcreek.com wrote:
 From: Mark A. Greer mgr...@animalcreek.com

 Some parts of the OMAP code assume that all power
 domains support certain states (e.g., RET  OFF).
 This isn't always true (e.g., the am35x family of
 SoC's) so those assumptions need to be removed.

 Remove those assumptions by looking up the deepest
 state that a power domain can be in whereever its
 being blindly set.  The 'max()' of the deepest
 state and what the code formerly wanted to set it
 to, is the correct state.  If the code formerly
 wanted to set it to PWRDM_POWER_OFF, then the
 deepest possible state will be used (i.e., no
 need to perform the 'max()').

 The code still assumes that ON is a valid state.

 Signed-off-by: Mark A. Greer mgr...@animalcreek.com
 ---

 These patches apply on top of Kevin's patch series,
      [PATCH/RFT 0/8] ARM: OMAP: remove IP checks from SoC family detection

 Tested on an am3517 evm and am37x evm.

  arch/arm/mach-omap2/cpuidle34xx.c |   19 +--
  arch/arm/mach-omap2/pm34xx.c      |   15 +--
  arch/arm/mach-omap2/powerdomain.c |   25 +
  arch/arm/mach-omap2/powerdomain.h |    2 ++
  4 files changed, 49 insertions(+), 12 deletions(-)

 diff --git a/arch/arm/mach-omap2/cpuidle34xx.c 
 b/arch/arm/mach-omap2/cpuidle34xx.c
 index 5358664..2c91711 100644
 --- a/arch/arm/mach-omap2/cpuidle34xx.c
 +++ b/arch/arm/mach-omap2/cpuidle34xx.c
 @@ -175,19 +175,25 @@ static int next_valid_state(struct cpuidle_device *dev,
        struct cpuidle_state_usage *curr_usage = dev-states_usage[index];
        struct cpuidle_state *curr = drv-states[index];
        struct omap3_idle_statedata *cx = cpuidle_get_statedata(curr_usage);
 -       u32 mpu_deepest_state = PWRDM_POWER_RET;
 -       u32 core_deepest_state = PWRDM_POWER_RET;
 +       u32 mpu_deepest_state, mpu_deepest_possible;
 +       u32 core_deepest_state, core_deepest_possible;
        int next_index = -1;

 +       mpu_deepest_possible = pwrdm_get_deepest_state(mpu_pd);
 +       mpu_deepest_state = max_t(u32, mpu_deepest_possible, PWRDM_POWER_RET);
I do not think you need to change the pwrdm API and the cpuidle code for that.

Instead you should use the pwrst* fields in the power domains data
files, which allow to specify the allowed states.
After reading the rest of your patches it seems you are addressing the
issue in a subsequent patch 'arm: omap3: am35x: Set proper powerdomain
states'.

 +
 +       core_deepest_possible = pwrdm_get_deepest_state(core_pd);
 +       core_deepest_state = max_t(u32, core_deepest_possible, 
 PWRDM_POWER_RET);
 +
        if (enable_off_mode) {
 -               mpu_deepest_state = PWRDM_POWER_OFF;
 +               mpu_deepest_state = mpu_deepest_possible;
                /*
                 * Erratum i583: valable for ES rev  Es1.2 on 3630.
                 * CORE OFF mode is not supported in a stable form, restrict
                 * instead the CORE state to RET.
                 */
                if (!IS_PM34XX_ERRATUM(PM_SDRC_WAKEUP_ERRATUM_i583))
 -                       core_deepest_state = PWRDM_POWER_OFF;
 +                       core_deepest_state = core_deepest_possible;
        }

        /* Check if current state is valid */
 @@ -422,8 +428,9 @@ int __init omap3_idle_init(void)
                pr_warn(%s: core off state C7 disabled due to i583\n,
                        __func__);
        }
 -       cx-mpu_state = PWRDM_POWER_OFF;
 -       cx-core_state = PWRDM_POWER_OFF;
 +
 +       cx-mpu_state = pwrdm_get_deepest_state(mpu_pd);
 +       cx-core_state = pwrdm_get_deepest_state(core_pd);

        drv-state_count = OMAP3_NUM_STATES;
        cpuidle_register_driver(omap3_idle_driver);
 diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
 index ec92676..40d8d07 100644
 --- a/arch/arm/mach-omap2/pm34xx.c
 +++ b/arch/arm/mach-omap2/pm34xx.c
 @@ -614,12 +614,11 @@ void omap3_pm_off_mode_enable(int enable)
        struct power_state *pwrst;
        u32 state;

 -       if (enable)
 -               state = PWRDM_POWER_OFF;
 -       else
 -               state = PWRDM_POWER_RET;
 -
        list_for_each_entry(pwrst, pwrst_list, node) {
 +               state = pwrdm_get_deepest_state(pwrst-pwrdm);
 +               if (!enable)
 +                       state = max_t(u32, state, PWRDM_POWER_RET);
 +
                if (IS_PM34XX_ERRATUM(PM_SDRC_WAKEUP_ERRATUM_i583) 
                                pwrst-pwrdm == core_pwrdm 
                                state == PWRDM_POWER_OFF) {
 @@ -660,6 +659,7 @@ int omap3_pm_set_suspend_state(struct powerdomain *pwrdm, 
 int state)
  static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
  {
        struct power_state *pwrst;
 +       u32 state;

        if (!pwrdm-pwrsts)
                return 0;
 @@ -668,7 +668,10 @@ static int __init pwrdms_setup(struct powerdomain 
 *pwrdm, void *unused)
        if (!pwrst)
             

[PATCH 0/5] ARM: OMAP2+: PM: implement a caching mechanism on the power domains state registers

2012-05-01 Thread jean . pihet
From: Jean Pihet j-pi...@ti.com

The OMAP3 PRCM registers accesses are known to be slow, with a PRCM register
read taking up to 12-14us depending on the OPP.

This patch adds a caching mechanism on the power domains state registers.
When the cache is cold or has been invalidated a register access is
performed, otherwise the register value is retrieved from the registers
cache.
The API is made of read and write functions for fields in the cache, as well
as an invalidate and helper functions to invalidate parts of the cache
contents (i.e. previous, current power states and all fields in the cache).
The power domain code is converted to use the API to read and write the
previous, current and next states for the power domains states, logical
and memory states.
The PM debug code also uses the caching API instead of the internal
pwrdm-state variable.

Using the caching mechanism optimizes the performance of the system in the
transitions to and from the low power states.

Tested on Beagleboard using cpuidle in RET and OFF modes.

Based on the linux-omap git tree (3.4.0-rc2) [1] with the changes for the
functional power states [2] and the per-device PM QoS support for OMAP [3].

[1] git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap.git
[2] http://marc.info/?l=linux-omapm=133475291911194w=2
[3] http://marc.info/?l=linux-omapm=133475685213067w=2


Jean Pihet (5):
  ARM: OMAP2+: PM: implement a caching mechanism on the power domains
state registers
  ARM: OMAP2+: PM: use the power domains registers cache for the power
states
  ARM: OMAP2+: PM: use the power domains registers cache for the logic
and mem states
  ARM: OMAP2+: PM: use the power domains registers cache invalidate API
  ARM: OMAP2+: PM debug: use the power domains registers caching API

 arch/arm/mach-omap2/pm-debug.c|   16 ++-
 arch/arm/mach-omap2/pm34xx.c  |6 +
 arch/arm/mach-omap2/powerdomain.c |  272 -
 arch/arm/mach-omap2/powerdomain.h |   45 ++-
 4 files changed, 297 insertions(+), 42 deletions(-)

-- 
1.7.7.6

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


[PATCH 1/5] ARM: OMAP2+: PM: implement a caching mechanism on the power domains state registers

2012-05-01 Thread jean . pihet
From: Jean Pihet j-pi...@ti.com

The OMAP3 PRCM registers accesses are known to be slow. A PRCM read
can take up to 12-14us depending on the OPP.

This patch adds a caching mechanism on the power domains state registers.
When the cache is cold or has been invalidated a register access is
performed, otherwise the register value is retrieved from the registers
cache.
The API is made of read and write functions for fields in the cache, as well
as an invalidate function and helper functions to invalidate parts of the
cache contents (i.e. previous, current power states and all fields in the
cache).

Signed-off-by: Jean Pihet j-pi...@ti.com
---
 arch/arm/mach-omap2/powerdomain.c |  128 +
 arch/arm/mach-omap2/powerdomain.h |   45 -
 2 files changed, 171 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-omap2/powerdomain.c 
b/arch/arm/mach-omap2/powerdomain.c
index 100c422..18e1ffc 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -697,6 +697,134 @@ out:
 }
 
 /**
+ * pwrdm_cache_read - read from the registers cache
+ * @pwrdm: struct powerdomain *
+ * @index: index of the data to be read from the cache
+ * @value: data value to be returned
+ *
+ * Returns 0 if the data is read from the cache.
+ * Returns -ENODATA if the data is not present, -EINVAL if the data is
+ * to be read past the end of the cache.
+ */
+static int pwrdm_cache_read(struct powerdomain *pwrdm, int index, int *value)
+{
+   if (index = PWRDM_CACHE_SIZE)
+   return -EINVAL;
+
+   if (!(pwrdm-cache_state  (1  index)))
+   return -ENODATA;
+
+   *value = pwrdm-cache[index];
+   return 0;
+}
+
+/**
+ * pwrdm_cache_write - store data to the registers cache
+ * @pwrdm: struct powerdomain *
+ * @index: index of the data to write to the cache
+ * @value: data value to be stored
+ *
+ * Stores the data in the cache and maintains the internal cache state.
+ *
+ * Returns -EINVAL if the data is to be written past the end of the cache,
+ * 0 otherwise.
+ */
+static int pwrdm_cache_write(struct powerdomain *pwrdm, int index, int value)
+{
+   if (index = PWRDM_CACHE_SIZE)
+   return -EINVAL;
+
+   pwrdm-cache[index] = value;
+   pwrdm-cache_state |= (1  index);
+
+   return 0;
+}
+
+/**
+ * pwrdm_invalidate_regs_cache_fields - invalidate fields in the
+ * power domain registers cache
+ * @pwrdm: struct powerdomain *
+ * @mask: cache fields to invalidate, made by OR'ing the
+ * PWRDM_CACHE_* values
+ *
+ * If pwrdm is NULL, invalidate the fields for all power domains,
+ * otherwise invalidate them for the given pwrdm only.
+ *
+ * Invalidates some of the power domain cache fields, thus imposing
+ * an effective re-read from the HW register at the next access.
+ */
+void pwrdm_invalidate_regs_cache_fields(struct powerdomain *pwrdm, int mask)
+{
+   struct powerdomain *temp_pwrdm;
+
+   if (pwrdm) {
+   pwrdm-cache_state = ~mask;
+   } else {
+   list_for_each_entry(temp_pwrdm, pwrdm_list, node)
+   temp_pwrdm-cache_state = ~mask;
+   }
+}
+
+/**
+ * pwrdm_invalidate_regs_cache_fields_prev - invalidate the previous states
+ * in the power domain registers cache
+ * @pwrdm: struct powerdomain *
+ *
+ * If pwrdm is NULL, invalidate the previous states for all power domains,
+ * otherwise invalidate them for the given pwrdm only.
+ *
+ * Invalidates only the previous states of the power domain cache fields,
+ * thus imposing an effective re-read from the HW register at the next access.
+ */
+void pwrdm_invalidate_regs_cache_fields_prev(struct powerdomain *pwrdm)
+{
+   int i;
+
+   pwrdm_invalidate_regs_cache_fields(pwrdm,
+   PWRDM_CACHE_PREV_PWRST |
+   PWRDM_CACHE_PREV_LOGIC_PWRST);
+   for (i = 0; i  PWRDM_MAX_MEM_BANKS; i++)
+   pwrdm_invalidate_regs_cache_fields(pwrdm,
+   PWRDM_CACHE_PREV_MEM_PWRST + i);
+}
+
+/**
+ * pwrdm_invalidate_regs_cache_fields_current - invalidate the current
+ * states in the power domains' registers cache
+ *
+ * If pwrdm is NULL, invalidate the current states for all power domains,
+ * otherwise invalidate them for the given pwrdm only.
+ *
+ * Invalidates only the current states of the power domains cache fields,
+ * thus imposing an effective re-read from the HW register at the next access.
+ */
+void pwrdm_invalidate_regs_cache_fields_current(struct powerdomain *pwrdm)
+{
+   int i;
+
+   pwrdm_invalidate_regs_cache_fields(pwrdm, PWRDM_CACHE_PWRST |
+  PWRDM_CACHE_LOGIC_RETST);
+   for (i = 0; i  PWRDM_MAX_MEM_BANKS; i++) {
+   pwrdm_invalidate_regs_cache_fields(pwrdm,
+   PWRDM_CACHE_MEM_PWRST + i);
+   pwrdm_invalidate_regs_cache_fields(pwrdm

[PATCH 2/5] ARM: OMAP2+: PM: use the power domains registers cache for the power states

2012-05-01 Thread jean . pihet
From: Jean Pihet j-pi...@ti.com

Use the caching API for the previous, current and next power domains states.

Signed-off-by: Jean Pihet j-pi...@ti.com
---
 arch/arm/mach-omap2/powerdomain.c |   32 ++--
 1 files changed, 26 insertions(+), 6 deletions(-)

diff --git a/arch/arm/mach-omap2/powerdomain.c 
b/arch/arm/mach-omap2/powerdomain.c
index 18e1ffc..2058e27 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -854,6 +854,8 @@ int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 
pwrst)
  smp_processor_id());
/* Program the pwrdm desired target state */
ret = arch_pwrdm-pwrdm_set_next_pwrst(pwrdm, pwrst);
+   if (!ret)
+   pwrdm_cache_write(pwrdm, PWRDM_CACHE_NEXT_PWRST, pwrst);
}
 
return ret;
@@ -869,13 +871,19 @@ int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 
pwrst)
  */
 int pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
 {
-   int ret = -EINVAL;
+   int pwrst, ret = -EINVAL;
 
if (!pwrdm)
return -EINVAL;
 
-   if (arch_pwrdm  arch_pwrdm-pwrdm_read_next_pwrst)
+   if (!pwrdm_cache_read(pwrdm, PWRDM_CACHE_NEXT_PWRST, pwrst))
+   return pwrst;
+
+   if (arch_pwrdm  arch_pwrdm-pwrdm_read_next_pwrst) {
ret = arch_pwrdm-pwrdm_read_next_pwrst(pwrdm);
+   if (ret = 0)
+   pwrdm_cache_write(pwrdm, PWRDM_CACHE_NEXT_PWRST, ret);
+   }
 
return ret;
 }
@@ -906,13 +914,19 @@ int pwrdm_read_next_func_pwrst(struct powerdomain *pwrdm)
  */
 int pwrdm_read_pwrst(struct powerdomain *pwrdm)
 {
-   int ret = -EINVAL;
+   int pwrst, ret = -EINVAL;
 
if (!pwrdm)
return -EINVAL;
 
-   if (arch_pwrdm  arch_pwrdm-pwrdm_read_pwrst)
+   if (!pwrdm_cache_read(pwrdm, PWRDM_CACHE_PWRST, pwrst))
+   return pwrst;
+
+   if (arch_pwrdm  arch_pwrdm-pwrdm_read_pwrst) {
ret = arch_pwrdm-pwrdm_read_pwrst(pwrdm);
+   if (ret = 0)
+   pwrdm_cache_write(pwrdm, PWRDM_CACHE_PWRST, ret);
+   }
 
return ret;
 }
@@ -943,13 +957,19 @@ int pwrdm_read_func_pwrst(struct powerdomain *pwrdm)
  */
 int pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
 {
-   int ret = -EINVAL;
+   int pwrst, ret = -EINVAL;
 
if (!pwrdm)
return -EINVAL;
 
-   if (arch_pwrdm  arch_pwrdm-pwrdm_read_prev_pwrst)
+   if (!pwrdm_cache_read(pwrdm, PWRDM_CACHE_PREV_PWRST, pwrst))
+   return pwrst;
+
+   if (arch_pwrdm  arch_pwrdm-pwrdm_read_prev_pwrst) {
ret = arch_pwrdm-pwrdm_read_prev_pwrst(pwrdm);
+   if (ret = 0)
+   pwrdm_cache_write(pwrdm, PWRDM_CACHE_PREV_PWRST, ret);
+   }
 
return ret;
 }
-- 
1.7.7.6

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


[PATCH 3/5] ARM: OMAP2+: PM: use the power domains registers cache for the logic and mem states

2012-05-01 Thread jean . pihet
From: Jean Pihet j-pi...@ti.com

Use the caching API for the previous, current and next
power domains logical and memory states.

Signed-off-by: Jean Pihet j-pi...@ti.com
---
 arch/arm/mach-omap2/powerdomain.c |  108 -
 1 files changed, 82 insertions(+), 26 deletions(-)

diff --git a/arch/arm/mach-omap2/powerdomain.c 
b/arch/arm/mach-omap2/powerdomain.c
index 2058e27..9800b2b 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -1011,11 +1011,15 @@ int pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 
pwrst)
if (!(pwrdm-pwrsts_logic_ret  (1  pwrst)))
return -EINVAL;
 
-   pr_debug(powerdomain: setting next logic powerstate for %s to %0x\n,
+   pr_debug(powerdomain: setting next logic RET state for %s to %0x\n,
 pwrdm-name, pwrst);
 
-   if (arch_pwrdm  arch_pwrdm-pwrdm_set_logic_retst)
+   if (arch_pwrdm  arch_pwrdm-pwrdm_set_logic_retst) {
ret = arch_pwrdm-pwrdm_set_logic_retst(pwrdm, pwrst);
+   if (!ret)
+   pwrdm_cache_write(pwrdm, PWRDM_CACHE_NEXT_LOGIC_RETST,
+ pwrst);
+   }
 
return ret;
 }
@@ -1023,13 +1027,13 @@ int pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 
pwrst)
 /**
  * pwrdm_set_mem_onst - set memory power state while powerdomain ON
  * @pwrdm: struct powerdomain * to set
- * @bank: memory bank number to set (0-3)
+ * @bank: memory bank number to set (0-PWRDM_MAX_MEM_BANKS)
  * @pwrst: one of the PWRDM_LOGIC_MEM_PWRST_* macros
  *
  * Set the next power state @pwrst that memory bank @bank of the
  * powerdomain @pwrdm will enter when the powerdomain enters the ON
- * state.  @bank will be a number from 0 to 3, and represents different
- * types of memory, depending on the powerdomain.  Returns -EINVAL if
+ * state.  @bank represents different types of memory, depending on
+ * the powerdomain.  Returns -EINVAL if
  * the powerdomain pointer is null or the target power state is not
  * not supported for this memory bank, -EEXIST if the target memory
  * bank does not exist or is not controllable, or returns 0 upon
@@ -1051,8 +1055,12 @@ int pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 
bank, u8 pwrst)
pr_debug(powerdomain: setting next memory powerstate for domain %s 
 bank %0x while pwrdm-ON to %0x\n, pwrdm-name, bank, pwrst);
 
-   if (arch_pwrdm  arch_pwrdm-pwrdm_set_mem_onst)
+   if (arch_pwrdm  arch_pwrdm-pwrdm_set_mem_onst) {
ret = arch_pwrdm-pwrdm_set_mem_onst(pwrdm, bank, pwrst);
+   if (!ret)
+   pwrdm_cache_write(pwrdm, PWRDM_CACHE_MEM_ONST + bank,
+ pwrst);
+   }
 
return ret;
 }
@@ -1060,13 +1068,13 @@ int pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 
bank, u8 pwrst)
 /**
  * pwrdm_set_mem_retst - set memory power state while powerdomain in RET
  * @pwrdm: struct powerdomain * to set
- * @bank: memory bank number to set (0-3)
+ * @bank: memory bank number to set (0-PWRDM_MAX_MEM_BANKS)
  * @pwrst: one of the PWRDM_LOGIC_MEM_PWRST_* macros
  *
  * Set the next power state @pwrst that memory bank @bank of the
  * powerdomain @pwrdm will enter when the powerdomain enters the
- * RETENTION state.  Bank will be a number from 0 to 3, and represents
- * different types of memory, depending on the powerdomain.  @pwrst
+ * RETENTION state.  Bank represents different types of memory,
+ * depending on the powerdomain.  @pwrst
  * will be either RETENTION or OFF, if supported.  Returns -EINVAL if
  * the powerdomain pointer is null or the target power state is not
  * not supported for this memory bank, -EEXIST if the target memory
@@ -1089,8 +1097,13 @@ int pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 
bank, u8 pwrst)
pr_debug(powerdomain: setting next memory powerstate for domain %s 
 bank %0x while pwrdm-RET to %0x\n, pwrdm-name, bank, pwrst);
 
-   if (arch_pwrdm  arch_pwrdm-pwrdm_set_mem_retst)
+   if (arch_pwrdm  arch_pwrdm-pwrdm_set_mem_retst) {
ret = arch_pwrdm-pwrdm_set_mem_retst(pwrdm, bank, pwrst);
+   if (!ret)
+   pwrdm_cache_write(pwrdm,
+ PWRDM_CACHE_NEXT_MEM_RETST + bank,
+ pwrst);
+   }
 
return ret;
 }
@@ -1106,13 +1119,19 @@ int pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 
bank, u8 pwrst)
  */
 int pwrdm_read_logic_pwrst(struct powerdomain *pwrdm)
 {
-   int ret = -EINVAL;
+   int retst, ret = -EINVAL;
 
if (!pwrdm)
return -EINVAL;
 
-   if (arch_pwrdm  arch_pwrdm-pwrdm_read_logic_pwrst)
+   if (!pwrdm_cache_read(pwrdm, PWRDM_CACHE_LOGIC_RETST, retst))
+   return retst;
+
+   if (arch_pwrdm  arch_pwrdm-pwrdm_read_logic_pwrst) {
ret = arch_pwrdm

[PATCH 4/5] ARM: OMAP2+: PM: use the power domains registers cache invalidate API

2012-05-01 Thread jean . pihet
From: Jean Pihet j-pi...@ti.com

The power domains registers cache is partially invalidated when clearing
the previous power states and after coming back from the low power mode,
i.e. after the return from the low level WFI instruction.

Note: this invalidate use scheme is optimized for performance, the states
returned by the state read functions might not reflect the real state if
the power domains registers have not been changed using the API or have
not been changed by the operating system (e.g. the ROM code in case of
secure code execution).

Signed-off-by: Jean Pihet j-pi...@ti.com
---
 arch/arm/mach-omap2/pm34xx.c  |6 ++
 arch/arm/mach-omap2/powerdomain.c |4 +++-
 2 files changed, 9 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index ed73ffc..a222f517 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -353,6 +353,12 @@ void omap_sram_idle(void)
else
omap34xx_do_sram_idle(save_state);
 
+   /*
+* Invalidate the current states from the regs cache
+* for all power domains
+*/
+   pwrdm_invalidate_regs_cache_fields_current(NULL);
+
/* Restore normal SDRC POWER settings */
if (cpu_is_omap3430()  omap_rev() = OMAP3430_REV_ES3_0 
(omap_type() == OMAP2_DEVICE_TYPE_EMU ||
diff --git a/arch/arm/mach-omap2/powerdomain.c 
b/arch/arm/mach-omap2/powerdomain.c
index 9800b2b..0b9259b 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -1324,8 +1324,10 @@ int pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm)
pr_debug(powerdomain: clearing previous power state reg for %s\n,
 pwrdm-name);
 
-   if (arch_pwrdm  arch_pwrdm-pwrdm_clear_all_prev_pwrst)
+   if (arch_pwrdm  arch_pwrdm-pwrdm_clear_all_prev_pwrst) {
ret = arch_pwrdm-pwrdm_clear_all_prev_pwrst(pwrdm);
+   pwrdm_invalidate_regs_cache_fields_prev(pwrdm);
+   }
 
return ret;
 }
-- 
1.7.7.6

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


[PATCH 5/5] ARM: OMAP2+: PM debug: use the power domains registers caching API

2012-05-01 Thread jean . pihet
From: Jean Pihet j-pi...@ti.com

Use the caching API instead of using the internal pwrdm-state field
for PM debug statistics display.

Note: some power domains states mismatch messages can be printed out with
the power domains states statstics, indicating that the power domains are
not controlled by any driver or that the invalidate API is not correctly
used.

Signed-off-by: Jean Pihet j-pi...@ti.com
---
 arch/arm/mach-omap2/pm-debug.c |   16 +---
 1 files changed, 9 insertions(+), 7 deletions(-)

diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c
index 13c00fb..ed9846e 100644
--- a/arch/arm/mach-omap2/pm-debug.c
+++ b/arch/arm/mach-omap2/pm-debug.c
@@ -96,19 +96,20 @@ static int clkdm_dbg_show_counter(struct clockdomain 
*clkdm, void *user)
 static int pwrdm_dbg_show_counter(struct powerdomain *pwrdm, void *user)
 {
struct seq_file *s = (struct seq_file *)user;
-   int i;
+   int i, pwrst;
 
if (strcmp(pwrdm-name, emu_pwrdm) == 0 ||
strcmp(pwrdm-name, wkup_pwrdm) == 0 ||
strncmp(pwrdm-name, dpll, 4) == 0)
return 0;
 
-   if (pwrdm-state != pwrdm_read_func_pwrst(pwrdm))
-   printk(KERN_ERR pwrdm state mismatch(%s) %d != %d\n,
-  pwrdm-name, pwrdm-state, pwrdm_read_func_pwrst(pwrdm));
+   pwrst = pwrdm_read_func_pwrst(pwrdm);
+   if (pwrdm-state != pwrst)
+   printk(KERN_ERR pwrdm state mismatch(%s): last saved %d != 
current %d\n,
+  pwrdm-name, pwrdm-state, pwrst);
 
seq_printf(s, %s (%s), pwrdm-name,
-   pwrdm_state_names[pwrdm-state]);
+   pwrdm_state_names[pwrst]);
for (i = 0; i  PWRDM_MAX_FUNC_PWRSTS; i++)
seq_printf(s, ,%s:%d, pwrdm_state_names[i],
pwrdm-state_counter[i]);
@@ -126,7 +127,7 @@ static int pwrdm_dbg_show_counter(struct powerdomain 
*pwrdm, void *user)
 static int pwrdm_dbg_show_timer(struct powerdomain *pwrdm, void *user)
 {
struct seq_file *s = (struct seq_file *)user;
-   int i;
+   int i, pwrst;
 
if (strcmp(pwrdm-name, emu_pwrdm) == 0 ||
strcmp(pwrdm-name, wkup_pwrdm) == 0 ||
@@ -134,9 +135,10 @@ static int pwrdm_dbg_show_timer(struct powerdomain *pwrdm, 
void *user)
return 0;
 
pwrdm_state_switch(pwrdm);
+   pwrst = pwrdm_read_func_pwrst(pwrdm);
 
seq_printf(s, %s (%s), pwrdm-name,
-   pwrdm_state_names[pwrdm-state]);
+   pwrdm_state_names[pwrst]);
 
for (i = 0; i  PWRDM_MAX_FUNC_PWRSTS; i++)
seq_printf(s, ,%s:%lld, pwrdm_state_names[i],
-- 
1.7.7.6

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


Re: PM related performance degradation on OMAP3

2012-05-01 Thread Jean Pihet
HI Kevin, Grazvydas,

On Tue, Apr 24, 2012 at 4:29 PM, Kevin Hilman khil...@ti.com wrote:
 Jean Pihet jean.pi...@newoldbits.com writes:

 Hi Grazvydas, Kevin,

 I did some gather some performance measurements and statistics using
 custom tracepoints in __omap3_enter_idle.
I posted the patches for the power domains registers cache, cf.
http://marc.info/?l=linux-omapm=133587781712039w=2.

 All the details are at
 http://www.omappedia.org/wiki/Power_Management_Device_Latencies_Measurement#C1_performance_problem:_analysis
I updated the page with the measurements results with Kevin's patches
and the registers cache patches.

The results are showing that:
- the registers cache optimizes the low power mode transitions, but is
not sufficient to obtain a big gain. A few unused domains are
transitioning, which causes a big penalty in the idle path.
- khilman's optimizations are really helpful. Furthermore it optimizes
farther the registers cache statistics accesses.
- the average time in idle now drops to 246us, which is still very
large for a cpu intensive C-state. For information with PM disabled
the average time in idle is 113us.

Regards,
Jean

 .

 This is great, thanks.

 [...]

 Here are the results (BW in MB/s) on Beagleboard:
 - 4.7: without using DMA,

 - Using DMA
   2.1: [0]
   2.1: [1] only C1
   2.6: [1]+[2] no pre_ post_
   2.3: [1]+[5] no pwrdm_for_each_clkdm
   2.8: [1]+[5]+[2]
   3.1: [1]+[5]+[6] no omap_sram_idle
   3.1: No IDLE, no omap_sram_idle, all pwrdms to ON

 So indeed this shows there is some serious performance issue with the
 C1 C-state.

 Yes, this confirms what both Grazvytas and I are seeing as well.

 [...]

 From the list of contributors, the main ones are:
     (140us) pwrdm_pre_transition and pwrdm_post_transition,

 See the series I just posted to address this one:
 [PATCH/RFT 0/3] ARM: OMAP: PM: reduce overhead of pwrdm pre/post transitions

     (105us) omap2_gpio_prepare_for_idle and
 omap2_gpio_resume_after_idle. This could be avoided if PER stays ON in
 the latency-critical C-states,
     (78us) pwrdm_for_each_clkdm(mpu, core, deny_idle/allow_idle),
     (33us estimated) omap_set_pwrdm_state(mpu, core, neon),
     (11 us) clkdm_allow_idle(mpu). Is this needed?

 In that same series, I removed this as it appears to be a remnant of a
 code move (c.f. patch 3 in above series.)

 Here are a few questions and suggestions:
 - In case of latency critical C-states could the high-latency code be
 bypassed in favor of a much simpler version? Pushing the concept a bit
 farther one could have a C1 state that just relaxes the cpu (no WFI),
 a C2 state which bypasses a lot of code in __omap3_enter_idle, and the
 rest of the C-states as we have today,

 I was thinking a WFI only state, with *all* powerdomains staying on is
 probably sufficient for C1.  Do you see the enter/exit latency from that
 as even being too hight?

 - Is it needed to iterate through all the power and clock domains in
 order to keep them active?

 No.  My series above starts to addresses this, but I think Tero's
 use-counting series is the final solution since this should really be
 done when we know the powerdomains are transitioning.

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


Re: [PATCH/RFT 5/8] ARM: OMAP: clock: remove unused CK_3505 flag

2012-04-30 Thread Jean Pihet
Hi Kevin,

On Fri, Apr 27, 2012 at 1:29 AM, Kevin Hilman khil...@ti.com wrote:
 This flag is no longer used since clock init all AM35x devices
 is now the same.

 Acked-by: Vaibhav Hiremath hvaib...@ti.com
 Tested-by: Vaibhav Hiremath hvaib...@ti.com
 Signed-off-by: Kevin Hilman khil...@ti.com
 ---
  arch/arm/plat-omap/include/plat/clkdev_omap.h |    3 +--
  1 file changed, 1 insertion(+), 2 deletions(-)

 diff --git a/arch/arm/plat-omap/include/plat/clkdev_omap.h 
 b/arch/arm/plat-omap/include/plat/clkdev_omap.h
 index b299b8d..45afa4d 100644
 --- a/arch/arm/plat-omap/include/plat/clkdev_omap.h
 +++ b/arch/arm/plat-omap/include/plat/clkdev_omap.h
 @@ -34,7 +34,6 @@ struct omap_clk {
  #define CK_243X                (1  5)        /* 243x, 253x */
  #define CK_3430ES1     (1  6)        /* 34xxES1 only */
  #define CK_3430ES2PLUS (1  7)        /* 34xxES2, ES3, non-Sitara 35xx only 
 */
 -#define CK_3505                (1  8)
  #define CK_3517                (1  9)
If this is the only flag remaining, should it better be renamed to CK_35XX?

  #define CK_36XX                (1  10)       /* 36xx/37xx-specific clocks 
 */
  #define CK_443X                (1  11)
 @@ -44,7 +43,7 @@ struct omap_clk {


  #define CK_34XX                (CK_3430ES1 | CK_3430ES2PLUS)
 -#define CK_AM35XX      (CK_3505 | CK_3517)     /* all Sitara AM35xx */
 +#define CK_AM35XX      CK_3517         /* all Sitara AM35xx */
  #define CK_3XXX                (CK_34XX | CK_AM35XX | CK_36XX)


Regards,
Jean


 --
 1.7.9.2

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


Re: [PATCH/RFT 6/8] ARM: OMAP: remove unused cpu_is_omap3505()

2012-04-30 Thread Jean Pihet
Kevin,

On Fri, Apr 27, 2012 at 1:29 AM, Kevin Hilman khil...@ti.com wrote:
 The 3505 check is now unused and can be removed.

 There are no longer any cpu_is_* checks that depend on specific IP
 detection.

 Acked-by: Vaibhav Hiremath hvaib...@ti.com
 Tested-by: Vaibhav Hiremath hvaib...@ti.com
 Signed-off-by: Kevin Hilman khil...@ti.com
 ---
  arch/arm/plat-omap/include/plat/cpu.h |    8 +---
  1 file changed, 1 insertion(+), 7 deletions(-)

 diff --git a/arch/arm/plat-omap/include/plat/cpu.h 
 b/arch/arm/plat-omap/include/plat/cpu.h
 index 41f3e5a..b34bf6c 100644
 --- a/arch/arm/plat-omap/include/plat/cpu.h
 +++ b/arch/arm/plat-omap/include/plat/cpu.h
 @@ -250,8 +250,7 @@ IS_AM_SUBCLASS(335x, 0x335)
  * cpu_is_omap2423():  True for OMAP2423
  * cpu_is_omap2430():  True for OMAP2430
  * cpu_is_omap3430():  True for OMAP3430
 - * cpu_is_omap3505():  True for OMAP3505
 - * cpu_is_omap3517():  True for OMAP3517
 + * cpu_is_omap3517():  True for AM35x: OMAP3517, OMAP3505
Is cpu_is_omap35xx() a better name for it?

Regards,
Jean

  */
  #define GET_OMAP_TYPE  ((omap_rev()  16)  0x)

 @@ -275,7 +274,6 @@ IS_OMAP_TYPE(2422, 0x2422)
  IS_OMAP_TYPE(2423, 0x2423)
  IS_OMAP_TYPE(2430, 0x2430)
  IS_OMAP_TYPE(3430, 0x3430)
 -IS_OMAP_TYPE(3505, 0x3517)
  IS_OMAP_TYPE(3517, 0x3517)

  #define cpu_is_omap310()               0
 @@ -292,7 +290,6 @@ IS_OMAP_TYPE(3517, 0x3517)
  #define cpu_is_omap2423()              0
  #define cpu_is_omap2430()              0
  #define cpu_is_omap3530()              0
 -#define cpu_is_omap3505()              0
  #define cpu_is_omap3517()              0
  #define cpu_is_omap3430()              0
  #define cpu_is_omap3630()              0
 @@ -346,7 +343,6 @@ IS_OMAP_TYPE(3517, 0x3517)
  #if defined(CONFIG_ARCH_OMAP3)
  # undef cpu_is_omap3430
  # undef cpu_is_omap3530
 -# undef cpu_is_omap3505
  # undef cpu_is_omap3517
  # undef cpu_is_ti81xx
  # undef cpu_is_ti816x
 @@ -356,8 +352,6 @@ IS_OMAP_TYPE(3517, 0x3517)
  # define cpu_is_omap3430()             is_omap3430()
  # define cpu_is_omap3530()             (cpu_is_omap3430())
  # define cpu_is_omap3517()             is_omap3517()
 -# define cpu_is_omap3505()             (cpu_is_omap3517()            \
 -                                               !omap3_has_sgx())
  # undef cpu_is_omap3630
  # define cpu_is_omap3630()             is_omap363x()
  # define cpu_is_ti81xx()               is_ti81xx()
 --
 1.7.9.2

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


Re: PM related performance degradation on OMAP3

2012-04-24 Thread Jean Pihet
Hi Grazvydas, Kevin,

I did some gather some performance measurements and statistics using
custom tracepoints in __omap3_enter_idle.
All the details are at
http://www.omappedia.org/wiki/Power_Management_Device_Latencies_Measurement#C1_performance_problem:_analysis
.

The setup is:
- Beagleboard (OMAP3530) at 500MHz,
- l-o master kernel + functional power states + per-device PM QoS. It
has been checked that the changes from l-o master do not have an
impact on the performance.
- The data transfer is performed using dd from a file in JFFS2 to
/dev/null: 'dd if=/tmp/mnt/a of=/dev/null bs=1M count=32'.

On Tue, Apr 17, 2012 at 4:30 PM, Kevin Hilman khil...@ti.com wrote:
 Grazvydas Ignotas nota...@gmail.com writes:

 On Thu, Apr 12, 2012 at 3:19 AM, Kevin Hilman khil...@ti.com wrote:
 It would be helpful now to narrow down what are the big contributors to
 the overhead in omap_sram_idle().  Most of the code there is skipped for
 C1 because the next states for MPU and CORE are both ON.

 Ok I did some tests, all in mostly idle system with just init, busybox
 shell and dd doing a NAND read to /dev/null .

...

 MB/s is throughput that
 dd reports, mA and approx. current draw during the transfer, read from
 fuel gauge that's onboard.

 MB/s| mA|comment
  3.7|218|mainline f549e088b80
  3.8|224|nand qos PM_QOS_CPU_DMA_LATENCY 0 [1]
  4.4|220|[1] + pwrdm_p*_transition commented [2]
  3.8|225|[1] + omap34xx_do_sram_idle-cpu_do_idle [3]
  4.2|210|[1] + pwrdm_set_next_pwrst(per_pd, PWRDM_POWER_ON) [4]
  4.0|224|[1] + 'Deny idle' [5]
  5.1|210|[2] + [4] + [5]
  5.2|202|[5] + omap_sram_idle-cpu_do_idle [6]
  5.5|243|!CONFIG_PM
  6.1|282|busywait DMA end (for reference)

Here are the results (BW in MB/s) on Beagleboard:
- 4.7: without using DMA,

- Using DMA
  2.1: [0]
  2.1: [1] only C1
  2.6: [1]+[2] no pre_ post_
  2.3: [1]+[5] no pwrdm_for_each_clkdm
  2.8: [1]+[5]+[2]
  3.1: [1]+[5]+[6] no omap_sram_idle
  3.1: No IDLE, no omap_sram_idle, all pwrdms to ON

So indeed this shows there is some serious performance issue with the
C1 C-state.

 Thanks for the detailed experiments.  This definitely confirms we have
 some serious unwanted overhead for C1, and our C-state latency values
 are clearly way off base, since they only account HW latency and not any
 of the SW latency introduced in omap_sram_idle().

 There are 2 primary differences that I see as possible causes.  I list
 them here with a couple more experiments for you to try to help us
 narrow this down.

 1) powerdomain accounting: pwrdm_pre_transition(), pwrdm_post_transition()

 Could you try using omap_sram_idle() and just commenting out those
 calls?  Does that help performance?  Those iterate over all the
 powerdomains, so defintely add some overhead, but I don't think it
 would be as significant as what you're seeing.

 Seems to be taking good part of it.

    Much more likely is...

 2) jump to SRAM, SDRC self-refresh, SDRC errata workarounds

 Could not notice any difference.

 To me it looks like this results from many small things adding up..
 Idle is called so often that pwrdm_p*_transition() and those
 pwrdm_for_each_clkdm() walks start slowing everything down, perhaps
 because they access lots of registers on slow buses?

From the list of contributors, the main ones are:
(140us) pwrdm_pre_transition and pwrdm_post_transition,
(105us) omap2_gpio_prepare_for_idle and
omap2_gpio_resume_after_idle. This could be avoided if PER stays ON in
the latency-critical C-states,
(78us) pwrdm_for_each_clkdm(mpu, core, deny_idle/allow_idle),
(33us estimated) omap_set_pwrdm_state(mpu, core, neon),
(11 us) clkdm_allow_idle(mpu). Is this needed?

Here are a few questions and suggestions:
- In case of latency critical C-states could the high-latency code be
bypassed in favor of a much simpler version? Pushing the concept a bit
farther one could have a C1 state that just relaxes the cpu (no WFI),
a C2 state which bypasses a lot of code in __omap3_enter_idle, and the
rest of the C-states as we have today,
- Is it needed to iterate through all the power and clock domains in
order to keep them active?
- Trying to idle some non related power domains (e.g. PER) causes a
performance hit. How to link all the power domains states to the
cpuidle C-state? The per-device PM QoS framework could be used to
constraint some power domains, but this is highly dependent on the use
case.

 Yes PRCM register accesses are unfortunately rather slow, and we've
 known that for some time, but haven't done any detailed analysis of the
 overhead.
That would be worth doing the analysis. A lot of read accesses to the
current, next and previous power states are performed in the idle
code.

 Using the function_graph tracer, I was able to see that the pre/post
 transition are taking an enormous amount of time:

  - pwrdm pre-transition: 1400+ us at 600MHz (4000+ us at 125MHz)
  - pwrdm post-transtion: 1600+ us at 600MHz (6000+ us at 125MHz)

 Notice the big difference between 600MHz 

Re: PM related performance degradation on OMAP3

2012-04-24 Thread Jean Pihet
Hi Tero,

On Tue, Apr 24, 2012 at 2:21 PM, Tero Kristo t-kri...@ti.com wrote:
 On Tue, 2012-04-24 at 16:08 +0530, Santosh Shilimkar wrote:
 + Tero

 On Tuesday 24 April 2012 03:20 PM, Jean Pihet wrote:
  Hi Grazvydas, Kevin,
 
  I did some gather some performance measurements and statistics using
  custom tracepoints in __omap3_enter_idle.
  All the details are at
  http://www.omappedia.org/wiki/Power_Management_Device_Latencies_Measurement#C1_performance_problem:_analysis
  .
 
 Nice data.

  The setup is:
  - Beagleboard (OMAP3530) at 500MHz,
  - l-o master kernel + functional power states + per-device PM QoS. It
  has been checked that the changes from l-o master do not have an
  impact on the performance.
  - The data transfer is performed using dd from a file in JFFS2 to
  /dev/null: 'dd if=/tmp/mnt/a of=/dev/null bs=1M count=32'.

 Question: what is used for gathering the latency values?
I used ftrace tracepoints which are supposed to be low overhead. I
checked that the overhead cannot be measured on the measurement
interval (400us), given the fact that the time base is 31us (32 KHz
clock).

 
  On Tue, Apr 17, 2012 at 4:30 PM, Kevin Hilman khil...@ti.com wrote:
  Grazvydas Ignotas nota...@gmail.com writes:
 
  On Thu, Apr 12, 2012 at 3:19 AM, Kevin Hilman khil...@ti.com wrote:
  It would be helpful now to narrow down what are the big contributors to
  the overhead in omap_sram_idle().  Most of the code there is skipped for
  C1 because the next states for MPU and CORE are both ON.
 
  Ok I did some tests, all in mostly idle system with just init, busybox
  shell and dd doing a NAND read to /dev/null .
 
  ...
 
  MB/s is throughput that
  dd reports, mA and approx. current draw during the transfer, read from
  fuel gauge that's onboard.
 
  MB/s| mA|comment
   3.7|218|mainline f549e088b80
   3.8|224|nand qos PM_QOS_CPU_DMA_LATENCY 0 [1]
   4.4|220|[1] + pwrdm_p*_transition commented [2]
   3.8|225|[1] + omap34xx_do_sram_idle-cpu_do_idle [3]
   4.2|210|[1] + pwrdm_set_next_pwrst(per_pd, PWRDM_POWER_ON) [4]
   4.0|224|[1] + 'Deny idle' [5]
   5.1|210|[2] + [4] + [5]
   5.2|202|[5] + omap_sram_idle-cpu_do_idle [6]
   5.5|243|!CONFIG_PM
   6.1|282|busywait DMA end (for reference)
 
  Here are the results (BW in MB/s) on Beagleboard:
  - 4.7: without using DMA,
 
  - Using DMA
    2.1: [0]
    2.1: [1] only C1
    2.6: [1]+[2] no pre_ post_
    2.3: [1]+[5] no pwrdm_for_each_clkdm
    2.8: [1]+[5]+[2]
    3.1: [1]+[5]+[6] no omap_sram_idle
    3.1: No IDLE, no omap_sram_idle, all pwrdms to ON
 
  So indeed this shows there is some serious performance issue with the
  C1 C-state.
 
 Looks like other clock-domain (notably l4, per, AON) should be denied
 idle in C1 to avoid the huge penalties. It might just do the trick.


  Thanks for the detailed experiments.  This definitely confirms we have
  some serious unwanted overhead for C1, and our C-state latency values
  are clearly way off base, since they only account HW latency and not any
  of the SW latency introduced in omap_sram_idle().
 
  There are 2 primary differences that I see as possible causes.  I list
  them here with a couple more experiments for you to try to help us
  narrow this down.
 
  1) powerdomain accounting: pwrdm_pre_transition(), 
  pwrdm_post_transition()
 
  Could you try using omap_sram_idle() and just commenting out those
  calls?  Does that help performance?  Those iterate over all the
  powerdomains, so defintely add some overhead, but I don't think it
  would be as significant as what you're seeing.
 
  Seems to be taking good part of it.
 
     Much more likely is...
 
  2) jump to SRAM, SDRC self-refresh, SDRC errata workarounds
 
  Could not notice any difference.
 
  To me it looks like this results from many small things adding up..
  Idle is called so often that pwrdm_p*_transition() and those
  pwrdm_for_each_clkdm() walks start slowing everything down, perhaps
  because they access lots of registers on slow buses?
 
  From the list of contributors, the main ones are:
      (140us) pwrdm_pre_transition and pwrdm_post_transition,

 I have observed this one on OMAP4 too. There was a plan to remove
 this as part of Tero's PD/CD use-counting series.

 pwrdm_pre / post transitions could be optimized a bit already now. They
 only should need to be called for mpu / core and per domains, but
 currently they scan through everything.


      (105us) omap2_gpio_prepare_for_idle and
  omap2_gpio_resume_after_idle. This could be avoided if PER stays ON in
  the latency-critical C-states,
 Yes. In C1 when you deny idle for per, there should be no need to
 call this. But even in the case when it is called, why is it taking
 105 uS. Needs to dig further.

      (78us) pwrdm_for_each_clkdm(mpu, core, deny_idle/allow_idle),
 Depending on OPP, a PRCM read can take upto ~12-14 uS, so above
 shouldn't be surprising.

      (33us estimated) omap_set_pwrdm_state(mpu, core, neon),
 This is again dominated by PRCM read

      (11 us

Re: [PATCH 2/9] ARM: OMAP2+: SmartReflex: move the driver specific macros in include/linux/power

2012-04-19 Thread Jean Pihet
Hi Arnd,

On Thu, Apr 19, 2012 at 3:54 PM, Arnd Bergmann a...@arndb.de wrote:
 On Thursday 05 April 2012, Trilok Soni wrote:
  Couple of suggestions:
 
  drivers/platform/omap/avs?
  drivers/misc/omap/avs?
 

 I would definitely prefer something under drivers/power,
 drivers/regulators or a new top-level directory under
 drivers.
Can I take this as an OK for drivers/power/avs as suggested?


  IIRC, David Brownell was referring to the rule of three for such case.
  Meaning that it worth having a generic fmwk when at least three
  different drivers are doing the same kind of things.
 
  Do OMAP v1 and OMAP v2 implementations count as 2 drivers? ;-)
  More seriously, the OMAP code for SmartReflex is far from complete in
  mainline. There is a plan to provide the following features:
  - OMAP v1 IP,
  - OMAP v2 IP,
  - class 1.5,
  - class 3,
  - class 3.5,
  - and more support for the upcoming chipsets.

 I don't understand much of these versions right now, but hopefully after
 going through all these docs. My only contention point is to not create
 any directory into the drivers/power, unless it is generic fwk and then
 build up client drivers on top of it. Meanwhile we could move this
 driver into above options as I have suggested.

 I think creating the directory in the place where we want the files
 to stay in the long run is ok, if the plan is to add more drivers and
 make the base code more generic. We don't have to wait until it's too
 late and we absolutely need a framework ;-)
Agree! That is the intention to provide a fwk.

 The part I don't understand is how this relates to the regulator framework.
 Is there any overlap between the functionality provided by the
 smartreflex framework and the regulator framework? If so, would it be
 better to extend the existing framework so it can do smartreflex as well?
The link with regulator has indeed an impact on the target dir, this
is still unknown and discussed internally.


        Arnd

Thanks,
Jean
--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 0/9] PM: Create the AVS class of drivers

2012-04-18 Thread Jean Pihet
Hi Andrew, Greg,

Can you please look at this patch set?
The idea is to create a framework and drivers for the AVS class of
devices. This patch set implements the first step by moving the
existing code to drivers/power/avs. Next steps will be to implement
class support and notifications, add more classes of operations for
OMAP chips, etc.

Keerthy J is taking over the ownership of this code and will continue
the development further.

What do you think?

Regards,
Jean

On Mon, Mar 19, 2012 at 5:12 PM,  jean.pi...@newoldbits.com wrote:
 From: Jean Pihet j-pi...@ti.com

 AVS is a power management technique which controls the operating
 voltage of a device in order to optimize (i.e. reduce) its power
 consumption. The voltage is adapted depending on static factors
 (chip manufacturing process) and dynamic factors (temperature
 depending performance).
 AVS is also called SmartReflex on OMAP devices.

 To that end, create the AVS framework in drivers/power/avs and
 move the OMAP SmartReflex code to the new directory.

 In preparation to the move of the OMAP code the following changes have been
 made:
 - split the include files into generic and platform specific code,
 - fill in platform data from the device initialization code and pass
  it to the driver,
 - create CONFIG_AVS* config options accordingly.

 The platform integration data for SmartReflex is passed from hwmod
 and the voltage layer to the driver using pdata.


 Tested on OMAP3 Beagleboard using omap2plus_defconfig with the
 CONFIG_POWER_AVS* options set.
 Based on master branch of the l-o git tree (3.3.0-rc6) [1], commit
 85244e0edd240da2004bb2ab7cbcbc67a336f20d.

 [1] git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap.git


 History:
 v2: rework after the comments on MLs
  . Keep the OMAP Kconfig options in the arch dir (Rafael),
  . Move the shared header file from plat-omap to
    include/linux/power/ (Tony)

 v1: initial revision


 Jean Pihet (9):
  ARM: OMAP3+: voltage: export functions to plat/voltage.h
  ARM: OMAP2+: SmartReflex: move the driver specific macros in
    include/linux/power
  ARM: OMAP3+: SmartReflex: class drivers should use struct omap_sr *
  ARM: OMAP2+: smartreflex: Use the names from hwmod data instead of
    voltage domains.
  ARM: OMAP3: hwmod: rename the smartreflex entries
  ARM: OMAP2+: SmartReflex: introduce a busy loop condition test macro
  ARM: OMAP2+: SmartReflex: Use per-OPP data structure
  ARM: OMAP2+: SmartReflex: add POWER_AVS Kconfig options
  ARM: OMAP: SmartReflex: Move smartreflex driver to drivers/

  arch/arm/mach-omap2/Makefile               |    4 +-
  arch/arm/mach-omap2/omap_hwmod_3xxx_data.c |   12 +-
  arch/arm/mach-omap2/omap_hwmod_44xx_data.c |    3 +-
  arch/arm/mach-omap2/pm.h                   |    2 +-
  arch/arm/mach-omap2/smartreflex-class3.c   |   60 --
  arch/arm/mach-omap2/smartreflex.c          | 1165 
 
  arch/arm/mach-omap2/smartreflex.h          |  256 --
  arch/arm/mach-omap2/sr_device.c            |   38 +-
  arch/arm/mach-omap2/voltage.h              |    1 -
  arch/arm/mach-omap2/vp.h                   |    2 -
  arch/arm/plat-omap/Kconfig                 |   30 +-
  arch/arm/plat-omap/include/plat/voltage.h  |    3 +
  drivers/power/Kconfig                      |    2 +
  drivers/power/Makefile                     |    2 +
  drivers/power/avs/Kconfig                  |   12 +
  drivers/power/avs/Makefile                 |    2 +
  drivers/power/avs/smartreflex-class3.c     |   61 ++
  drivers/power/avs/smartreflex.c            | 1118 ++
  drivers/power/avs/smartreflex.h            |  238 ++
  include/linux/power/smartreflex.h          |   97 +++
  20 files changed, 1590 insertions(+), 1518 deletions(-)
  delete mode 100644 arch/arm/mach-omap2/smartreflex-class3.c
  delete mode 100644 arch/arm/mach-omap2/smartreflex.c
  delete mode 100644 arch/arm/mach-omap2/smartreflex.h
  create mode 100644 drivers/power/avs/Kconfig
  create mode 100644 drivers/power/avs/Makefile
  create mode 100644 drivers/power/avs/smartreflex-class3.c
  create mode 100644 drivers/power/avs/smartreflex.c
  create mode 100644 drivers/power/avs/smartreflex.h
  create mode 100644 include/linux/power/smartreflex.h

 --
 1.7.5.4

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


[PATCH v3 0/6] ARM: OMAP2+: PM: introduce the power domains functional states

2012-04-18 Thread jean . pihet
From: Jean Pihet j-pi...@ti.com

Implement the functional states for the power domains:
- protect the power domain state change by a mutex in
  omap_set_pwrdm_state,
- introduce the functional states for power domains power states and
  logic power states, and the conversion functions between the
  functional and internal states,
- unify the API to use the functional states,
- program the logic power state of power domains from the functional
  states, in omap_set_pwrdm_state
- convert the OMAP2/3/4 PM code to use the updated API,
- provide the power domains statistics by functional states.

Tested on OMAP3 Beagleboard, with suspend and cpuidle in RET and
OFF modes.


History:
 v3:
 - fix a bug in OMAP3 cpuidle which prevented the IO wake-ups in PER

 v2:
 - add the logic power states,
 - provide the power domains statistics by functional states

 v1:
 - initial implementation, in RFC state
 

Jean Pihet (6):
  ARM: OMAP2+: PM: protect the power domain state change by a mutex
  ARM: OMAP2+: PM: introduce power domains functional states
  ARM: OMAP2+: PM: use the functional power states API
  ARM: OMAP2+: PM: introduce power domains logic and memory functional
states
  ARM: OMAP2+: PM: use the functional power states API for logic and
memory
  ARM: OMAP2+: PM: use power domain functional state in stats counters

 arch/arm/mach-omap2/cpuidle34xx.c  |   61 
 arch/arm/mach-omap2/cpuidle44xx.c  |   28 ++--
 arch/arm/mach-omap2/omap-hotplug.c |2 +-
 arch/arm/mach-omap2/omap-mpuss-lowpower.c  |   39 +++---
 arch/arm/mach-omap2/pm-debug.c |   15 +-
 arch/arm/mach-omap2/pm.c   |   62 ---
 arch/arm/mach-omap2/pm24xx.c   |   14 +-
 arch/arm/mach-omap2/pm34xx.c   |   80 +-
 arch/arm/mach-omap2/pm44xx.c   |   15 +--
 arch/arm/mach-omap2/powerdomain-common.c   |   85 ++
 arch/arm/mach-omap2/powerdomain.c  |  244 ++--
 arch/arm/mach-omap2/powerdomain.h  |   42 +-
 arch/arm/mach-omap2/powerdomain2xxx_3xxx.c |7 +
 arch/arm/mach-omap2/powerdomain44xx.c  |3 +
 14 files changed, 489 insertions(+), 208 deletions(-)

-- 
1.7.7.6

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


[PATCH 1/6] ARM: OMAP2+: PM: protect the power domain state change by a mutex

2012-04-18 Thread jean . pihet
From: Jean Pihet j-pi...@ti.com

Signed-off-by: Jean Pihet j-pi...@ti.com
---
 arch/arm/mach-omap2/pm.c  |8 ++--
 arch/arm/mach-omap2/powerdomain.c |1 +
 arch/arm/mach-omap2/powerdomain.h |3 ++-
 3 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
index d0c1c96..6918a13 100644
--- a/arch/arm/mach-omap2/pm.c
+++ b/arch/arm/mach-omap2/pm.c
@@ -100,15 +100,17 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 
pwrst)
if (!pwrdm || IS_ERR(pwrdm))
return -EINVAL;
 
+   mutex_lock(pwrdm-lock);
+
while (!(pwrdm-pwrsts  (1  pwrst))) {
if (pwrst == PWRDM_POWER_OFF)
-   return ret;
+   goto out;
pwrst--;
}
 
next_pwrst = pwrdm_read_next_pwrst(pwrdm);
if (next_pwrst == pwrst)
-   return ret;
+   goto out;
 
curr_pwrst = pwrdm_read_pwrst(pwrdm);
if (curr_pwrst  PWRDM_POWER_ON) {
@@ -141,6 +143,8 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 
pwrst)
break;
}
 
+out:
+   mutex_unlock(pwrdm-lock);
return ret;
 }
 
diff --git a/arch/arm/mach-omap2/powerdomain.c 
b/arch/arm/mach-omap2/powerdomain.c
index 96ad3dbe..319b277 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -102,6 +102,7 @@ static int _pwrdm_register(struct powerdomain *pwrdm)
INIT_LIST_HEAD(pwrdm-voltdm_node);
voltdm_add_pwrdm(voltdm, pwrdm);
 
+   mutex_init(pwrdm-lock);
list_add(pwrdm-node, pwrdm_list);
 
/* Initialize the powerdomain's state counter */
diff --git a/arch/arm/mach-omap2/powerdomain.h 
b/arch/arm/mach-omap2/powerdomain.h
index 0d72a8a..6c6567d 100644
--- a/arch/arm/mach-omap2/powerdomain.h
+++ b/arch/arm/mach-omap2/powerdomain.h
@@ -19,7 +19,7 @@
 
 #include linux/types.h
 #include linux/list.h
-
+#include linux/mutex.h
 #include linux/atomic.h
 
 #include plat/cpu.h
@@ -116,6 +116,7 @@ struct powerdomain {
struct clockdomain *pwrdm_clkdms[PWRDM_MAX_CLKDMS];
struct list_head node;
struct list_head voltdm_node;
+   struct mutex lock;
int state;
unsigned state_counter[PWRDM_MAX_PWRSTS];
unsigned ret_logic_off_counter;
-- 
1.7.7.6

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


[PATCH 2/6] ARM: OMAP2+: PM: introduce power domains functional states

2012-04-18 Thread jean . pihet
From: Jean Pihet j-pi...@ti.com

Introduce functional (or logical) states for power domains and the
API functions to read the power domains settings and to convert
between the functional (i.e. logical) and the internal (or registers)
values.

OMAP2, OMAP3 and OMAP4 platforms are defining a conversion routine.

In the new API the function omap_set_pwrdm_state takes the functional
states as parameter; while at it the function is moved to the power
domains code.

The memory and logic states are not using the functional states, this
comes as a subsequent patch.

Signed-off-by: Jean Pihet j-pi...@ti.com
---
 arch/arm/mach-omap2/pm.c   |   66 ---
 arch/arm/mach-omap2/powerdomain-common.c   |   61 ++
 arch/arm/mach-omap2/powerdomain.c  |  175 
 arch/arm/mach-omap2/powerdomain.h  |   21 
 arch/arm/mach-omap2/powerdomain2xxx_3xxx.c |5 +
 arch/arm/mach-omap2/powerdomain44xx.c  |2 +
 6 files changed, 264 insertions(+), 66 deletions(-)

diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
index 6918a13..8670c4b 100644
--- a/arch/arm/mach-omap2/pm.c
+++ b/arch/arm/mach-omap2/pm.c
@@ -74,10 +74,6 @@ static void __init omap2_init_processor_devices(void)
}
 }
 
-/* Types of sleep_switch used in omap_set_pwrdm_state */
-#define FORCEWAKEUP_SWITCH 0
-#define LOWPOWERSTATE_SWITCH   1
-
 int __init omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused)
 {
if (clkdm-flags  CLKDM_CAN_ENABLE_AUTO)
@@ -89,68 +85,6 @@ int __init omap_pm_clkdms_setup(struct clockdomain *clkdm, 
void *unused)
 }
 
 /*
- * This sets pwrdm state (other than mpu  core. Currently only ON 
- * RET are supported.
- */
-int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 pwrst)
-{
-   u8 curr_pwrst, next_pwrst;
-   int sleep_switch = -1, ret = 0, hwsup = 0;
-
-   if (!pwrdm || IS_ERR(pwrdm))
-   return -EINVAL;
-
-   mutex_lock(pwrdm-lock);
-
-   while (!(pwrdm-pwrsts  (1  pwrst))) {
-   if (pwrst == PWRDM_POWER_OFF)
-   goto out;
-   pwrst--;
-   }
-
-   next_pwrst = pwrdm_read_next_pwrst(pwrdm);
-   if (next_pwrst == pwrst)
-   goto out;
-
-   curr_pwrst = pwrdm_read_pwrst(pwrdm);
-   if (curr_pwrst  PWRDM_POWER_ON) {
-   if ((curr_pwrst  pwrst) 
-   (pwrdm-flags  PWRDM_HAS_LOWPOWERSTATECHANGE)) {
-   sleep_switch = LOWPOWERSTATE_SWITCH;
-   } else {
-   hwsup = clkdm_in_hwsup(pwrdm-pwrdm_clkdms[0]);
-   clkdm_wakeup(pwrdm-pwrdm_clkdms[0]);
-   sleep_switch = FORCEWAKEUP_SWITCH;
-   }
-   }
-
-   ret = pwrdm_set_next_pwrst(pwrdm, pwrst);
-   if (ret)
-   pr_err(%s: unable to set power state of powerdomain: %s\n,
-  __func__, pwrdm-name);
-
-   switch (sleep_switch) {
-   case FORCEWAKEUP_SWITCH:
-   if (hwsup)
-   clkdm_allow_idle(pwrdm-pwrdm_clkdms[0]);
-   else
-   clkdm_sleep(pwrdm-pwrdm_clkdms[0]);
-   break;
-   case LOWPOWERSTATE_SWITCH:
-   pwrdm_set_lowpwrstchange(pwrdm);
-   pwrdm_wait_transition(pwrdm);
-   pwrdm_state_switch(pwrdm);
-   break;
-   }
-
-out:
-   mutex_unlock(pwrdm-lock);
-   return ret;
-}
-
-
-
-/*
  * This API is to be called during init to set the various voltage
  * domains to the voltage as per the opp table. Typically we boot up
  * at the nominal voltage. So this function finds out the rate of
diff --git a/arch/arm/mach-omap2/powerdomain-common.c 
b/arch/arm/mach-omap2/powerdomain-common.c
index c0aeabf..098dc42 100644
--- a/arch/arm/mach-omap2/powerdomain-common.c
+++ b/arch/arm/mach-omap2/powerdomain-common.c
@@ -108,3 +108,64 @@ u32 omap2_pwrdm_get_mem_bank_stst_mask(u8 bank)
return 0;
 }
 
+/*
+ * Functional (i.e. logical) to internal (i.e. registers)
+ * values for the power domains states
+ */
+int omap2_pwrdm_func_to_pwrst(struct powerdomain *pwrdm, u8 func_pwrst)
+{
+   int ret;
+
+   switch (func_pwrst) {
+   case PWRDM_FUNC_PWRST_ON:
+   ret = PWRDM_POWER_ON;
+   break;
+   case PWRDM_FUNC_PWRST_INACTIVE:
+   ret = PWRDM_POWER_INACTIVE;
+   break;
+   case PWRDM_FUNC_PWRST_CSWR:
+   case PWRDM_FUNC_PWRST_OSWR:
+   ret = PWRDM_POWER_RET;
+   break;
+   case PWRDM_FUNC_PWRST_OFF:
+   ret = PWRDM_POWER_OFF;
+   break;
+   default:
+   ret = -1;
+   }
+
+   return ret;
+}
+
+/*
+ * Internal (i.e. registers) to functional (i.e. logical) values
+ * for the power domains states
+ */
+int omap2_pwrdm_pwrst_to_func(struct powerdomain *pwrdm, u8 pwrst)
+{
+   int ret;
+
+   switch (pwrst

[PATCH 4/6] ARM: OMAP2+: PM: introduce power domains logic and memory functional states

2012-04-18 Thread jean . pihet
From: Jean Pihet j-pi...@ti.com

In the new API the functions pwrdm_*_logic_* and pwrdm_*_mem_* take the
functional states as parameter.

OMAP2, OMAP3 and OMAP4 platforms are defining a conversion routine
between the functional state and the logic power state.

The power domains logic state is now derived from the functional
state and the logic state is programmed from omap_set_pwrdm_state.

Signed-off-by: Jean Pihet j-pi...@ti.com
---
 arch/arm/mach-omap2/powerdomain-common.c   |   36 ++--
 arch/arm/mach-omap2/powerdomain.c  |   80 +--
 arch/arm/mach-omap2/powerdomain.h  |   20 ++-
 arch/arm/mach-omap2/powerdomain2xxx_3xxx.c |2 +
 arch/arm/mach-omap2/powerdomain44xx.c  |1 +
 5 files changed, 112 insertions(+), 27 deletions(-)

diff --git a/arch/arm/mach-omap2/powerdomain-common.c 
b/arch/arm/mach-omap2/powerdomain-common.c
index 098dc42..ecaf405 100644
--- a/arch/arm/mach-omap2/powerdomain-common.c
+++ b/arch/arm/mach-omap2/powerdomain-common.c
@@ -138,10 +138,35 @@ int omap2_pwrdm_func_to_pwrst(struct powerdomain *pwrdm, 
u8 func_pwrst)
 }
 
 /*
+ * Functional (i.e. logical) to internal (i.e. registers)
+ * values for the power domains logic states
+ */
+int omap2_pwrdm_func_to_logic_pwrst(struct powerdomain *pwrdm, u8 func_pwrst)
+{
+   int ret;
+
+   switch (func_pwrst) {
+   case PWRDM_FUNC_PWRST_ON:
+   case PWRDM_FUNC_PWRST_INACTIVE:
+   case PWRDM_FUNC_PWRST_CSWR:
+   ret = PWRDM_LOGIC_MEM_PWRST_RET;
+   break;
+   case PWRDM_FUNC_PWRST_OSWR:
+   case PWRDM_FUNC_PWRST_OFF:
+   ret = PWRDM_LOGIC_MEM_PWRST_OFF;
+   break;
+   default:
+   ret = -1;
+   }
+
+   return ret;
+ }
+
+/*
  * Internal (i.e. registers) to functional (i.e. logical) values
  * for the power domains states
  */
-int omap2_pwrdm_pwrst_to_func(struct powerdomain *pwrdm, u8 pwrst)
+int omap2_pwrdm_pwrst_to_func(struct powerdomain *pwrdm, u8 pwrst, u8 logic)
 {
int ret;
 
@@ -153,11 +178,10 @@ int omap2_pwrdm_pwrst_to_func(struct powerdomain *pwrdm, 
u8 pwrst)
ret = PWRDM_FUNC_PWRST_INACTIVE;
break;
case PWRDM_POWER_RET:
-   /*
-* XXX warning: return OSWR in case of pd in RET and
-* logic in OFF
-*/
-   ret = PWRDM_FUNC_PWRST_CSWR;
+   if (logic == PWRDM_LOGIC_MEM_PWRST_RET)
+   ret = PWRDM_FUNC_PWRST_CSWR;
+   else
+   ret = PWRDM_FUNC_PWRST_OSWR;
break;
case PWRDM_POWER_OFF:
ret = PWRDM_FUNC_PWRST_OFF;
diff --git a/arch/arm/mach-omap2/powerdomain.c 
b/arch/arm/mach-omap2/powerdomain.c
index 28d5599..3faac62 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -129,14 +129,14 @@ static void _update_logic_membank_counters(struct 
powerdomain *pwrdm)
 
prev_logic_pwrst = pwrdm_read_prev_logic_pwrst(pwrdm);
if ((pwrdm-pwrsts_logic_ret == PWRSTS_OFF_RET) 
-   (prev_logic_pwrst == PWRDM_POWER_OFF))
+   (prev_logic_pwrst == PWRDM_LOGIC_MEM_PWRST_OFF))
pwrdm-ret_logic_off_counter++;
 
for (i = 0; i  pwrdm-banks; i++) {
prev_mem_pwrst = pwrdm_read_prev_mem_pwrst(pwrdm, i);
 
if ((pwrdm-pwrsts_mem_ret[i] == PWRSTS_OFF_RET) 
-   (prev_mem_pwrst == PWRDM_POWER_OFF))
+   (prev_mem_pwrst == PWRDM_LOGIC_MEM_PWRST_OFF))
pwrdm-ret_mem_off_counter[i]++;
}
 }
@@ -494,27 +494,64 @@ int pwrdm_func_to_pwrst(struct powerdomain *pwrdm, u8 
func_pwrst)
 }
 
 /**
+ * pwrdm_func_to_logic_pwrst - get the internal (i.e. registers) value
+ * of the logic state mapped to the functional state
+ * @pwrdm: struct powerdomain * to query
+ * @func_pwrst: functional power state
+ *
+ * Convert the functional power state to the platform specific power
+ * domain logic state value.
+ * Returns the internal power domain logic state value or -EINVAL in
+ * case of invalid parameters passed in.
+ */
+int pwrdm_func_to_logic_pwrst(struct powerdomain *pwrdm, u8 func_pwrst)
+{
+   int ret = func_pwrst;
+
+   if ((!pwrdm)|| (func_pwrst = PWRDM_MAX_FUNC_PWRSTS))
+   return -EINVAL;
+
+   pr_debug(powerdomain: convert %0x func to logic pwrst for %s\n,
+func_pwrst, pwrdm-name);
+
+   if (arch_pwrdm  arch_pwrdm-pwrdm_func_to_logic_pwrst) {
+   ret = arch_pwrdm-pwrdm_func_to_logic_pwrst(pwrdm, func_pwrst);
+   }
+
+   return ret;
+}
+
+/**
  * pwrdm_pwrst_to_func - get the functional (i.e. logical) value mapped
  * to the internal state
  * @pwrdm: struct powerdomain * to query
  * @pwrst: internal power state
+ * @logic: internal logic state
  *
- * Convert the internal power state to the power domain functional value.
+ * Convert the internal power

[PATCH 3/6] ARM: OMAP2+: PM: use the functional power states API

2012-04-18 Thread jean . pihet
From: Jean Pihet j-pi...@ti.com

Use the functional power states as the API to control power domains.
The omap_set_pwrdm_state function shall be used instead of
pwrdm_set_next_pwrst to control the power domains next states.

Note: the internal code for power domains state management still
uses the internal power states.

Signed-off-by: Jean Pihet j-pi...@ti.com
---
 arch/arm/mach-omap2/cpuidle34xx.c |   61 +++---
 arch/arm/mach-omap2/cpuidle44xx.c |   25 +
 arch/arm/mach-omap2/omap-hotplug.c|2 +-
 arch/arm/mach-omap2/omap-mpuss-lowpower.c |   43 +---
 arch/arm/mach-omap2/pm24xx.c  |   10 ++--
 arch/arm/mach-omap2/pm34xx.c  |   80 +++--
 arch/arm/mach-omap2/pm44xx.c  |8 ++--
 arch/arm/mach-omap2/powerdomain.c |2 +-
 8 files changed, 120 insertions(+), 111 deletions(-)

diff --git a/arch/arm/mach-omap2/cpuidle34xx.c 
b/arch/arm/mach-omap2/cpuidle34xx.c
index 5358664..ff2dea3 100644
--- a/arch/arm/mach-omap2/cpuidle34xx.c
+++ b/arch/arm/mach-omap2/cpuidle34xx.c
@@ -97,8 +97,8 @@ static int __omap3_enter_idle(struct cpuidle_device *dev,
 
local_fiq_disable();
 
-   pwrdm_set_next_pwrst(mpu_pd, mpu_state);
-   pwrdm_set_next_pwrst(core_pd, core_state);
+   omap_set_pwrdm_state(mpu_pd, mpu_state);
+   omap_set_pwrdm_state(core_pd, core_state);
 
if (omap_irq_pending() || need_resched())
goto return_sleep_time;
@@ -113,7 +113,7 @@ static int __omap3_enter_idle(struct cpuidle_device *dev,
 * Call idle CPU PM enter notifier chain so that
 * VFP context is saved.
 */
-   if (mpu_state == PWRDM_POWER_OFF)
+   if (mpu_state == PWRDM_FUNC_PWRST_OFF)
cpu_pm_enter();
 
/* Execute ARM wfi */
@@ -123,7 +123,7 @@ static int __omap3_enter_idle(struct cpuidle_device *dev,
 * Call idle CPU PM enter notifier chain to restore
 * VFP context.
 */
-   if (pwrdm_read_prev_pwrst(mpu_pd) == PWRDM_POWER_OFF)
+   if (pwrdm_read_prev_func_pwrst(mpu_pd) == PWRDM_FUNC_PWRST_OFF)
cpu_pm_exit();
 
/* Re-allow idle for C1 */
@@ -175,19 +175,19 @@ static int next_valid_state(struct cpuidle_device *dev,
struct cpuidle_state_usage *curr_usage = dev-states_usage[index];
struct cpuidle_state *curr = drv-states[index];
struct omap3_idle_statedata *cx = cpuidle_get_statedata(curr_usage);
-   u32 mpu_deepest_state = PWRDM_POWER_RET;
-   u32 core_deepest_state = PWRDM_POWER_RET;
+   u32 mpu_deepest_state = PWRDM_FUNC_PWRST_CSWR;
+   u32 core_deepest_state = PWRDM_FUNC_PWRST_CSWR;
int next_index = -1;
 
if (enable_off_mode) {
-   mpu_deepest_state = PWRDM_POWER_OFF;
+   mpu_deepest_state = PWRDM_FUNC_PWRST_OFF;
/*
 * Erratum i583: valable for ES rev  Es1.2 on 3630.
 * CORE OFF mode is not supported in a stable form, restrict
 * instead the CORE state to RET.
 */
if (!IS_PM34XX_ERRATUM(PM_SDRC_WAKEUP_ERRATUM_i583))
-   core_deepest_state = PWRDM_POWER_OFF;
+   core_deepest_state = PWRDM_FUNC_PWRST_OFF;
}
 
/* Check if current state is valid */
@@ -247,7 +247,7 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
   int index)
 {
int new_state_idx;
-   u32 core_next_state, per_next_state = 0, per_saved_state = 0, cam_state;
+   u32 core_next_state, per_next_state = 0, per_saved_state = 0;
struct omap3_idle_statedata *cx;
int ret;
 
@@ -255,8 +255,7 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
 * Prevent idle completely if CAM is active.
 * CAM does not have wakeup capability in OMAP3.
 */
-   cam_state = pwrdm_read_pwrst(cam_pd);
-   if (cam_state == PWRDM_POWER_ON) {
+   if (pwrdm_read_func_pwrst(cam_pd) == PWRDM_FUNC_PWRST_ON) {
new_state_idx = drv-safe_state_index;
goto select_state;
}
@@ -275,14 +274,14 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
 */
cx = cpuidle_get_statedata(dev-states_usage[index]);
core_next_state = cx-core_state;
-   per_next_state = per_saved_state = pwrdm_read_next_pwrst(per_pd);
-   if ((per_next_state == PWRDM_POWER_OFF) 
-   (core_next_state  PWRDM_POWER_RET))
-   per_next_state = PWRDM_POWER_RET;
+   per_next_state = per_saved_state = pwrdm_read_next_func_pwrst(per_pd);
+   if ((per_next_state == PWRDM_FUNC_PWRST_OFF) 
+   (core_next_state  PWRDM_FUNC_PWRST_CSWR))
+   per_next_state = PWRDM_FUNC_PWRST_CSWR;
 
/* Are we changing PER target state? */
if (per_next_state != per_saved_state)
-   pwrdm_set_next_pwrst

[PATCH 5/6] ARM: OMAP2+: PM: use the functional power states API for logic and memory

2012-04-18 Thread jean . pihet
From: Jean Pihet j-pi...@ti.com

Since the power domains logic state is derived from the power domain
functional state and is now programmed from omap_set_pwrdm_state,
the calls to pwrdm_set_logic_retst are removed and the mpu_logic_state
field is removed from the private data of the cpuidle and suspend code.

Signed-off-by: Jean Pihet j-pi...@ti.com
---
 arch/arm/mach-omap2/cpuidle44xx.c |9 +
 arch/arm/mach-omap2/omap-mpuss-lowpower.c |6 +-
 arch/arm/mach-omap2/pm24xx.c  |4 +---
 arch/arm/mach-omap2/pm44xx.c  |7 +--
 4 files changed, 4 insertions(+), 22 deletions(-)

diff --git a/arch/arm/mach-omap2/cpuidle44xx.c 
b/arch/arm/mach-omap2/cpuidle44xx.c
index 1daa0c1..9d99696 100644
--- a/arch/arm/mach-omap2/cpuidle44xx.c
+++ b/arch/arm/mach-omap2/cpuidle44xx.c
@@ -27,7 +27,6 @@
 /* Machine specific information to be recorded in the C-state driver_data */
 struct omap4_idle_statedata {
u32 cpu_state;
-   u32 mpu_logic_state;
u32 mpu_state;
u8 valid;
 };
@@ -91,16 +90,13 @@ static int omap4_enter_idle(struct cpuidle_device *dev,
if (cx-cpu_state == PWRDM_FUNC_PWRST_OFF)
cpu_pm_enter();
 
-   pwrdm_set_logic_retst(mpu_pd, cx-mpu_logic_state);
omap_set_pwrdm_state(mpu_pd, cx-mpu_state);
 
/*
 * Call idle CPU cluster PM enter notifier chain
 * to save GIC and wakeupgen context.
 */
-   if (((cx-mpu_state == PWRDM_FUNC_PWRST_CSWR) ||
-(cx-mpu_state == PWRDM_FUNC_PWRST_OSWR)) 
-   (cx-mpu_logic_state == PWRDM_POWER_OFF))
+   if (cx-mpu_state == PWRDM_FUNC_PWRST_OSWR)
cpu_cluster_pm_enter();
 
omap4_enter_lowpower(dev-cpu, cx-cpu_state);
@@ -195,21 +191,18 @@ int __init omap4_idle_init(void)
cx-valid = 1;  /* C1 is always valid */
cx-cpu_state = PWRDM_FUNC_PWRST_ON;
cx-mpu_state = PWRDM_FUNC_PWRST_ON;
-   cx-mpu_logic_state = PWRDM_POWER_RET;
 
/* C2 - CPU0 OFF + CPU1 OFF + MPU CSWR */
_fill_cstate(drv, 1, MPUSS CSWR);
cx = _fill_cstate_usage(dev, 1);
cx-cpu_state = PWRDM_FUNC_PWRST_OFF;
cx-mpu_state = PWRDM_FUNC_PWRST_CSWR;
-   cx-mpu_logic_state = PWRDM_POWER_RET;
 
/* C3 - CPU0 OFF + CPU1 OFF + MPU OSWR */
_fill_cstate(drv, 2, MPUSS OSWR);
cx = _fill_cstate_usage(dev, 2);
cx-cpu_state = PWRDM_FUNC_PWRST_OFF;
cx-mpu_state = PWRDM_FUNC_PWRST_OSWR;
-   cx-mpu_logic_state = PWRDM_POWER_OFF;
 
drv-state_count = OMAP4_NUM_STATES;
cpuidle_register_driver(omap4_idle_driver);
diff --git a/arch/arm/mach-omap2/omap-mpuss-lowpower.c 
b/arch/arm/mach-omap2/omap-mpuss-lowpower.c
index dd94a0e..c79cc0f 100644
--- a/arch/arm/mach-omap2/omap-mpuss-lowpower.c
+++ b/arch/arm/mach-omap2/omap-mpuss-lowpower.c
@@ -232,7 +232,6 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int 
power_state)
 {
unsigned int save_state = 0;
unsigned int wakeup_cpu;
-   int mpuss_state;
 
if (omap_rev() == OMAP4430_REV_ES1_0)
return -ENXIO;
@@ -265,10 +264,7 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int 
power_state)
 * In MPUSS OSWR or device OFF, interrupt controller context is lost.
 */
mpuss_clear_prev_logic_pwrst();
-   mpuss_state = pwrdm_read_next_func_pwrst(mpuss_pd);
-   if (((mpuss_state == PWRDM_FUNC_PWRST_CSWR) ||
-(mpuss_state == PWRDM_FUNC_PWRST_OSWR)) 
-   (pwrdm_read_logic_retst(mpuss_pd) == PWRDM_POWER_OFF))
+   if (pwrdm_read_next_func_pwrst(mpuss_pd) == PWRDM_FUNC_PWRST_OSWR)
save_state = 2;
 
cpu_clear_prev_logic_pwrst(cpu);
diff --git a/arch/arm/mach-omap2/pm24xx.c b/arch/arm/mach-omap2/pm24xx.c
index bb84348..fbadc37 100644
--- a/arch/arm/mach-omap2/pm24xx.c
+++ b/arch/arm/mach-omap2/pm24xx.c
@@ -93,7 +93,6 @@ static int omap2_enter_full_retention(void)
 * Set MPU powerdomain's next power state to RETENTION;
 * preserve logic state during retention
 */
-   pwrdm_set_logic_retst(mpu_pwrdm, PWRDM_POWER_RET);
omap_set_pwrdm_state(mpu_pwrdm, PWRDM_FUNC_PWRST_CSWR);
 
/* Workaround to kill USB */
@@ -251,7 +250,7 @@ static void __init prcm_setup_regs(void)
 */
num_mem_banks = pwrdm_get_mem_bank_count(core_pwrdm);
for (i = 0; i  num_mem_banks; i++)
-   pwrdm_set_mem_retst(core_pwrdm, i, PWRDM_POWER_RET);
+   pwrdm_set_mem_retst(core_pwrdm, i, PWRDM_LOGIC_MEM_PWRST_RET);
 
/* Set CORE powerdomain's next power state to RETENTION */
omap_set_pwrdm_state(core_pwrdm, PWRDM_FUNC_PWRST_CSWR);
@@ -260,7 +259,6 @@ static void __init prcm_setup_regs(void)
 * Set MPU powerdomain's next power state to RETENTION;
 * preserve logic state during retention
 */
-   pwrdm_set_logic_retst(mpu_pwrdm, PWRDM_POWER_RET

[PATCH 6/6] ARM: OMAP2+: PM: use power domain functional state in stats counters

2012-04-18 Thread jean . pihet
From: Jean Pihet j-pi...@ti.com

The PM code uses some counters to keep track of the power domains
transitions, in order to provide the information to drivers (in
pwrdm_get_context_loss_count) and to expose the information to
sysfs for debug purpose.

This patch provides the information for each functional state.

Signed-off-by: Jean Pihet j-pi...@ti.com
---
 arch/arm/mach-omap2/pm-debug.c|   15 ---
 arch/arm/mach-omap2/powerdomain.c |   12 ++--
 arch/arm/mach-omap2/powerdomain.h |4 ++--
 3 files changed, 16 insertions(+), 15 deletions(-)

diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c
index 814bcd9..13c00fb 100644
--- a/arch/arm/mach-omap2/pm-debug.c
+++ b/arch/arm/mach-omap2/pm-debug.c
@@ -53,9 +53,10 @@ enum {
DEBUG_FILE_TIMERS,
 };
 
-static const char pwrdm_state_names[][PWRDM_MAX_PWRSTS] = {
+static const char pwrdm_state_names[][PWRDM_MAX_FUNC_PWRSTS] = {
OFF,
-   RET,
+   OSWR,
+   CSWR,
INA,
ON
 };
@@ -102,13 +103,13 @@ static int pwrdm_dbg_show_counter(struct powerdomain 
*pwrdm, void *user)
strncmp(pwrdm-name, dpll, 4) == 0)
return 0;
 
-   if (pwrdm-state != pwrdm_read_pwrst(pwrdm))
+   if (pwrdm-state != pwrdm_read_func_pwrst(pwrdm))
printk(KERN_ERR pwrdm state mismatch(%s) %d != %d\n,
-   pwrdm-name, pwrdm-state, pwrdm_read_pwrst(pwrdm));
+  pwrdm-name, pwrdm-state, pwrdm_read_func_pwrst(pwrdm));
 
seq_printf(s, %s (%s), pwrdm-name,
pwrdm_state_names[pwrdm-state]);
-   for (i = 0; i  PWRDM_MAX_PWRSTS; i++)
+   for (i = 0; i  PWRDM_MAX_FUNC_PWRSTS; i++)
seq_printf(s, ,%s:%d, pwrdm_state_names[i],
pwrdm-state_counter[i]);
 
@@ -137,7 +138,7 @@ static int pwrdm_dbg_show_timer(struct powerdomain *pwrdm, 
void *user)
seq_printf(s, %s (%s), pwrdm-name,
pwrdm_state_names[pwrdm-state]);
 
-   for (i = 0; i  4; i++)
+   for (i = 0; i  PWRDM_MAX_FUNC_PWRSTS; i++)
seq_printf(s, ,%s:%lld, pwrdm_state_names[i],
pwrdm-state_timer[i]);
 
@@ -211,7 +212,7 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, 
void *dir)
 
t = sched_clock();
 
-   for (i = 0; i  4; i++)
+   for (i = 0; i  PWRDM_MAX_FUNC_PWRSTS; i++)
pwrdm-state_timer[i] = 0;
 
pwrdm-timer = t;
diff --git a/arch/arm/mach-omap2/powerdomain.c 
b/arch/arm/mach-omap2/powerdomain.c
index 3faac62..3f78f16 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -106,7 +106,7 @@ static int _pwrdm_register(struct powerdomain *pwrdm)
list_add(pwrdm-node, pwrdm_list);
 
/* Initialize the powerdomain's state counter */
-   for (i = 0; i  PWRDM_MAX_PWRSTS; i++)
+   for (i = 0; i  PWRDM_MAX_FUNC_PWRSTS; i++)
pwrdm-state_counter[i] = 0;
 
pwrdm-ret_logic_off_counter = 0;
@@ -114,7 +114,7 @@ static int _pwrdm_register(struct powerdomain *pwrdm)
pwrdm-ret_mem_off_counter[i] = 0;
 
pwrdm_wait_transition(pwrdm);
-   pwrdm-state = pwrdm_read_pwrst(pwrdm);
+   pwrdm-state = pwrdm_read_func_pwrst(pwrdm);
pwrdm-state_counter[pwrdm-state] = 1;
 
pr_debug(powerdomain: registered %s\n, pwrdm-name);
@@ -149,17 +149,17 @@ static int _pwrdm_state_switch(struct powerdomain *pwrdm, 
int flag)
if (pwrdm == NULL)
return -EINVAL;
 
-   state = pwrdm_read_pwrst(pwrdm);
+   state = pwrdm_read_func_pwrst(pwrdm);
 
switch (flag) {
case PWRDM_STATE_NOW:
prev = pwrdm-state;
break;
case PWRDM_STATE_PREV:
-   prev = pwrdm_read_prev_pwrst(pwrdm);
+   prev = pwrdm_read_prev_func_pwrst(pwrdm);
if (pwrdm-state != prev)
pwrdm-state_counter[prev]++;
-   if (prev == PWRDM_POWER_RET)
+   if (prev == PWRDM_FUNC_PWRST_OSWR)
_update_logic_membank_counters(pwrdm);
/*
 * If the power domain did not hit the desired state,
@@ -1240,7 +1240,7 @@ int pwrdm_get_context_loss_count(struct powerdomain 
*pwrdm)
return -ENODEV;
}
 
-   count = pwrdm-state_counter[PWRDM_POWER_OFF];
+   count = pwrdm-state_counter[PWRDM_FUNC_PWRST_OFF];
count += pwrdm-ret_logic_off_counter;
 
for (i = 0; i  pwrdm-banks; i++)
diff --git a/arch/arm/mach-omap2/powerdomain.h 
b/arch/arm/mach-omap2/powerdomain.h
index 4e5ce15..9249d42 100644
--- a/arch/arm/mach-omap2/powerdomain.h
+++ b/arch/arm/mach-omap2/powerdomain.h
@@ -135,13 +135,13 @@ struct powerdomain {
struct list_head voltdm_node;
struct mutex lock;
int state;
-   unsigned state_counter[PWRDM_MAX_PWRSTS];
+   unsigned state_counter

[PATCH v7 0/6] PM QoS: implement the OMAP low level constraints management code

2012-04-18 Thread jean . pihet
From: Jean Pihet j-pi...@ti.com

. Implement the devices wake-up latency constraints using the global
  device PM QoS notification handler which applies the constraints to the
  underlying layer,
. Implement the low level code which controls the power domains next
  functional power states [3], through the hwmod and pwrdm layers,
. Add cpuidle and power domains wake-up latency figures for OMAP3, cf. 
  comments in the code and [1] for the details on where the numbers
  are magically coming from,
. Implement the relation between the cpuidle and per-device PM QoS frameworks
  in the OMAP3 specific idle callbacks.
  The chosen C-state shall satisfy the following conditions:
   . the 'valid' field is enabled,
   . it satisfies the enable_off_mode flag,
   . the next state for MPU and CORE power domains is not lower than the
 state programmed by the per-device PM QoS.


ToDo:
1. support OMAP4 chipset when the low power modes will be supported
2. validate the constraints framework on OMAP4 HW (done on OMAP3)
3. Re-visit the OMAP power domains states initialization procedure. Currently
   the power states that have been changed from the constraints API which were
   applied before the initialization of the power domains are lost
4. Further clean-up the OMAP PM layer, use the generic frameworks instead (OPP,
   PM QoS for throughput constraints ...)


Based on the pm-qos branch of the linux-omap git tree (3.4.0-rc2) [2] with
the functional power states changes applied [3].

Tested cpuidle and suspend on OMAP3 Beagleboard (ES2.x) with constraints
on MPU, CORE, PER in RETention and OFF modes.

[1] http://www.omappedia.org/wiki/Power_Management_Device_Latencies_Measurement
[2] git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap.git
[3] http://marc.info/?l=linux-omapm=133475291911194w=2


History:

v7:
. rebased on top of the functional power state changes [3]

v6:
. minor change in the commits description after Kevin's review
. added Kevin's Reviewed-by

v5:
. rebased on latest linux-omap [2]
. rework after Kevin's comments on the MLs

v4:
. split up the patches which remove the omap_pm_ code from the patch set.
  Those patches are to be submitted later, on top of this patch set.
. latency numbers: provide the measurements setup and conditions in the code
  comments, added the link to the details on wiki [1].
. improved kerneldoc
. split big functions into smaller ones, in order to improve the readability

v3: reworked the error return path and improved the kerneldoc

v2: reworked the OMAP specific cpuidle code to demote the initial C-state to
 a valid C-state which fulfills the per-device constraints

v1: initial version


Jean Pihet (6):
  ARM: OMAP2+: PM QoS: control the power domains next state from the
constraints
  ARM: OMAP2+: PM QoS: manage the per-device latency constraints in
hwmod
  ARM: OMAP: omap_device: register to the per-device PM QoS framework
  ARM: OMAP3: cpuidle: next C-state decision depends on the PM QoS MPU
and CORE constraints
  ARM: OMAP3: update cpuidle latency and threshold figures
  ARM: OMAP3: powerdomain data: add wake-up latency figures

 arch/arm/mach-omap2/cpuidle34xx.c   |  109 --
 arch/arm/mach-omap2/omap_hwmod.c|   22 +--
 arch/arm/mach-omap2/pm.h|   17 ++-
 arch/arm/mach-omap2/powerdomain.c   |  216 +++
 arch/arm/mach-omap2/powerdomain.h   |   17 ++
 arch/arm/mach-omap2/powerdomains3xxx_data.c |   83 ++
 arch/arm/plat-omap/omap_device.c|   81 ++-
 7 files changed, 481 insertions(+), 64 deletions(-)

-- 
1.7.7.6

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


[PATCH 2/6] ARM: OMAP2+: PM QoS: manage the per-device latency constraints in hwmod

2012-04-18 Thread jean . pihet
From: Jean Pihet j-pi...@ti.com

Call the per-device PM QoS functions of the power domain code from the
hwmod layer, in order to apply the constraints requested to a device.

While at it, correct the functions kerneldoc.

Signed-off-by: Jean Pihet j-pi...@ti.com
---
 arch/arm/mach-omap2/omap_hwmod.c |   22 ++
 1 files changed, 6 insertions(+), 16 deletions(-)

diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index aefd2ee..9485eb1 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -3020,15 +3020,13 @@ ohsps_unlock:
 }
 
 /**
- * omap_hwmod_set_wakeuplat_constraint - set/release a wake-up latency
+ * omap_hwmod_set_wakeuplat_constraint - Set or update a wake-up latency
  * constraint
  * @oh: struct omap_hwmod* to which the target device belongs to.
  * @cookie: identifier of the constraints list for @oh.
  * @min_latency: the minimum allowed wake-up latency for @oh.
  *
- * Sets a wakeup latency contraint.  (To remove a wakeup latency
- * constraint, call omap_hwmod_remove_wakeuplat_constraint()).
- * Returns the return value from pwrdm_wakeuplat_remove_constraint(),
+ * Returns the return value from pwrdm_wakeuplat_update_constraint(),
  * or -EINVAL in case of invalid parameters.
  */
 int omap_hwmod_set_wakeuplat_constraint(struct omap_hwmod *oh, void *cookie,
@@ -3039,21 +3037,17 @@ int omap_hwmod_set_wakeuplat_constraint(struct 
omap_hwmod *oh, void *cookie,
if (!pwrdm)
return -EINVAL;
 
-   /*
-* XXX Update to use pwrdm_wakeuplat_update_constraint() when
-* that code is ready
-*/
-   return -EINVAL;
+   return pwrdm_wakeuplat_update_constraint(pwrdm, cookie, min_latency);
 }
 
 /**
- * omap_hwmod_remove_wakeuplat_constraint - release a wake-up latency
+ * omap_hwmod_remove_wakeuplat_constraint - Release a wake-up latency
  * constraint
  * @oh: struct omap_hwmod* to which the target device belongs to.
  * @cookie: identifier of the constraints list for @oh.
  *
  * Removes a wakeup latency contraint.  Returns the return value from
- * pwrdm_wakeuplat_update_constraint(), or -EINVAL in case of invalid
+ * pwrdm_wakeuplat_remove_constraint(), or -EINVAL in case of invalid
  * parameters.
  */
 int omap_hwmod_remove_wakeuplat_constraint(struct omap_hwmod *oh, void *cookie)
@@ -3063,11 +3057,7 @@ int omap_hwmod_remove_wakeuplat_constraint(struct 
omap_hwmod *oh, void *cookie)
if (!pwrdm)
return -EINVAL;
 
-   /*
-* XXX Update to use pwrdm_wakeuplat_remove_constraint() when
-* that code is ready
-*/
-   return -EINVAL;
+   return pwrdm_wakeuplat_remove_constraint(pwrdm, cookie);
 }
 
 /**
-- 
1.7.7.6

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


[PATCH 1/6] ARM: OMAP2+: PM QoS: control the power domains next state from the constraints

2012-04-18 Thread jean . pihet
From: Jean Pihet j-pi...@ti.com

When a PM QoS device latency constraint is requested or removed the
constraint is stored in the constraints list of the corresponding power
domain, then the aggregated constraint value is applied by programming
the next functional power state using omap_set_pwrdm_state.

Tested on OMAP3 Beagleboard and OMAP4 Pandaboard in RET/OFF using
wake-up latency constraints on MPU, CORE and PER.

Signed-off-by: Jean Pihet j-pi...@ti.com
---
 arch/arm/mach-omap2/powerdomain.c |  216 +
 arch/arm/mach-omap2/powerdomain.h |   17 +++
 2 files changed, 233 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/powerdomain.c 
b/arch/arm/mach-omap2/powerdomain.c
index 3f78f16..100c422 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -17,8 +17,10 @@
 #include linux/kernel.h
 #include linux/types.h
 #include linux/list.h
+#include linux/slab.h
 #include linux/errno.h
 #include linux/string.h
+#include linux/pm_qos.h
 #include trace/events/power.h
 
 #include cm2xxx_3xxx.h
@@ -113,6 +115,12 @@ static int _pwrdm_register(struct powerdomain *pwrdm)
for (i = 0; i  pwrdm-banks; i++)
pwrdm-ret_mem_off_counter[i] = 0;
 
+   /* Initialize the per-device wake-up constraints framework data */
+   mutex_init(pwrdm-wkup_lat_plist_lock);
+   plist_head_init(pwrdm-wkup_lat_plist_head);
+   pwrdm-wkup_lat_next_state = PWRDM_FUNC_PWRST_OFF;
+
+   /* Initialize the pwrdm state */
pwrdm_wait_transition(pwrdm);
pwrdm-state = pwrdm_read_func_pwrst(pwrdm);
pwrdm-state_counter[pwrdm-state] = 1;
@@ -200,6 +208,58 @@ static int _pwrdm_post_transition_cb(struct powerdomain 
*pwrdm, void *unused)
return 0;
 }
 
+/**
+ * _pwrdm_wakeuplat_update_pwrst - Update power domain power state if needed
+ * @pwrdm: struct powerdomain * to which requesting device belongs to.
+ * @min_latency: the allowed wake-up latency for the given power domain. A
+ *  value of PM_QOS_DEV_LAT_DEFAULT_VALUE means 'no constraint' on the pwrdm.
+ *
+ * Finds the power domain next power state that fulfills the constraint.
+ * Programs a new target state if it is different from current power state.
+ * The power domains get the next power state programmed directly in the
+ * registers.
+ *
+ * Returns 0 in case of success, -EINVAL in case of invalid parameters,
+ * or the return value from omap_set_pwrdm_state.
+ */
+static int _pwrdm_wakeuplat_update_pwrst(struct powerdomain *pwrdm,
+long min_latency)
+{
+   int ret = 0, state, new_state = PWRDM_FUNC_PWRST_ON;
+
+   if (!pwrdm) {
+   WARN(1, powerdomain: %s: invalid parameter(s), __func__);
+   return -EINVAL;
+   }
+
+   /*
+* Find the next supported power state with
+*  wakeup latency = min_latency.
+* Pick the lower state if no constraint on the pwrdm
+*  (min_latency == PM_QOS_DEV_LAT_DEFAULT_VALUE).
+* Skip the states marked as unsupported (UNSUP_STATE).
+* If no power state found, fall back to PWRDM_FUNC_PWRST_ON.
+*/
+for (state = 0x0; state  PWRDM_MAX_FUNC_PWRSTS; state++) {
+if ((min_latency == PM_QOS_DEV_LAT_DEFAULT_VALUE) ||
+((pwrdm-wakeup_lat[state] != UNSUP_STATE) 
+ (pwrdm-wakeup_lat[state] = min_latency))) {
+new_state = state;
+break;
+}
+}
+
+   pwrdm-wkup_lat_next_state = new_state;
+   ret = omap_set_pwrdm_state(pwrdm, new_state);
+
+   pr_debug(%s: func pwrst for %s: curr=%d, next=%d, min_latency=%ld, 
new_state=%d\n,
+__func__, pwrdm-name, pwrdm_read_func_pwrst(pwrdm),
+pwrdm_read_next_func_pwrst(pwrdm), min_latency, new_state);
+
+   return ret;
+}
+
+
 /* Public functions */
 
 /**
@@ -1224,6 +1284,162 @@ int pwrdm_post_transition(void)
 }
 
 /**
+ * pwrdm_wakeuplat_update_constraint - Set or update a powerdomain wakeup
+ *  latency constraint and apply it
+ * @pwrdm: struct powerdomain * which the constraint applies to
+ * @cookie: constraint identifier, used for tracking
+ * @min_latency: minimum wakeup latency constraint (in microseconds) for
+ *  the given pwrdm
+ *
+ * Tracks the constraints by @cookie.
+ * Constraint set/update: Adds a new entry to powerdomain's wake-up latency
+ * constraint list. If the constraint identifier already exists in the list,
+ * the old value is overwritten.
+ *
+ * Applies the aggregated constraint value for the given pwrdm by calling
+ * _pwrdm_wakeuplat_update_pwrst.
+ *
+ * Returns 0 upon success, -ENOMEM in case of memory shortage, -EINVAL in
+ * case of invalid latency value, or the return value from
+ * _pwrdm_wakeuplat_update_pwrst.
+ *
+ * The caller must check the validity of the parameters.
+ */
+int pwrdm_wakeuplat_update_constraint(struct powerdomain

[PATCH 3/6] ARM: OMAP: omap_device: register to the per-device PM QoS framework

2012-04-18 Thread jean . pihet
From: Jean Pihet j-pi...@ti.com

Implement the devices wake-up latency constraints using the global
device PM QoS notification handler which applies the constraints to the
underlying layer by calling the corresponding function at hwmod level.

Tested on OMAP3 Beagleboard and OMAP4 Pandaboard in RET/OFF using wake-up
latency constraints on MPU, CORE and PER.

Signed-off-by: Jean Pihet j-pi...@ti.com
Reviewed-by: Kevin Hilman khil...@ti.com
[p...@pwsan.com: modified to work with omap_devices with large numbers of
 hwmods; moved code to mach-omap2/omap_device.c; added documentation; use
 notifier return codes]
Signed-off-by: Paul Walmsley p...@pwsan.com
---
 arch/arm/plat-omap/omap_device.c |   81 +-
 1 files changed, 80 insertions(+), 1 deletions(-)

diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c
index d50cbc6..fb66879 100644
--- a/arch/arm/plat-omap/omap_device.c
+++ b/arch/arm/plat-omap/omap_device.c
@@ -3,6 +3,7 @@
  * omap_device implementation
  *
  * Copyright (C) 2009-2010 Nokia Corporation
+ * Copyright (C) 2011 Texas Instruments, Inc.
  * Paul Walmsley, Kevin Hilman
  *
  * Developed in collaboration with (alphabetical order): Benoit
@@ -89,6 +90,7 @@
 #include linux/pm_runtime.h
 #include linux/of.h
 #include linux/notifier.h
+#include linux/pm_qos.h
 
 #include plat/omap_device.h
 #include plat/omap_hwmod.h
@@ -401,6 +403,72 @@ static int _omap_device_notifier_call(struct 
notifier_block *nb,
return NOTIFY_DONE;
 }
 
+/**
+ * _omap_device_pm_qos_handler - interface to the per-device PM QoS framework
+ * @nb: pointer to omap_device_pm_qos_nb (not used)
+ * @new_value: new maximum wakeup latency constraint for @req-dev (in µs)
+ * @req: struct dev_pm_qos_request * passed by the Linux PM QoS code
+ *
+ * Called by the Linux core device PM QoS code to alter the maximum
+ * wakeup latency constraint on a device.  If the underlying device is
+ * an omap_device, then this code will pass the constraint on to the
+ * underlying hwmods.  Returns -EINVAL if this code can't handle the
+ * constraint for some reason, or passes along the return code from the
+ * hwmod wakeup latency constraint functions.
+ */
+static int _omap_device_pm_qos_handler(struct notifier_block *nb,
+  unsigned long new_value,
+  void *req)
+{
+   struct omap_device *od;
+   struct omap_hwmod *oh;
+   struct platform_device *pdev;
+   struct dev_pm_qos_request *dev_pm_qos_req = req;
+   int ret = NOTIFY_OK;
+   int r, i;
+
+   pr_debug(OMAP PM constraints: req@0x%p, new_value=%lu\n,
+req, new_value);
+
+   /* Look for the platform device for the constraint target device */
+   pdev = to_platform_device(dev_pm_qos_req-dev);
+
+   /* Try to catch non platform devices */
+   if (pdev-name == NULL) {
+   pr_err(%s: Error: platform device for device %s not valid\n,
+  __func__, dev_name(dev_pm_qos_req-dev));
+   return NOTIFY_DONE;
+   }
+
+   /* Find the associated omap_device for dev */
+   od = to_omap_device(pdev);
+   if (od == NULL) {
+   pr_err(%s: Error: no omap_device for device %s\n,
+  __func__, dev_name(dev_pm_qos_req-dev));
+   return NOTIFY_DONE;
+   }
+
+   pr_debug(OMAP PM constraints: req@0x%p, dev=0x%p, new_value=%lu\n,
+req, dev_pm_qos_req-dev, new_value);
+
+   for (i = 0; i  od-hwmods_cnt; i++) {
+   oh = od-hwmods[i];
+   if (new_value == PM_QOS_DEV_LAT_DEFAULT_VALUE)
+   r = omap_hwmod_remove_wakeuplat_constraint(
+   oh,
+   dev_pm_qos_req);
+   else
+   r = omap_hwmod_set_wakeuplat_constraint(
+   oh,
+   dev_pm_qos_req,
+   new_value);
+
+   if (!r)
+   ret = NOTIFY_BAD;
+   }
+
+   return ret;
+}
 
 /* Public functions for use by core code */
 
@@ -1117,13 +1185,24 @@ int omap_device_enable_clocks(struct omap_device *od)
return 0;
 }
 
+static struct notifier_block omap_device_pm_qos_nb = {
+   .notifier_call = _omap_device_pm_qos_handler,
+};
+
 static struct notifier_block platform_nb = {
.notifier_call = _omap_device_notifier_call,
 };
 
 static int __init omap_device_init(void)
 {
+   int ret;
+
bus_register_notifier(platform_bus_type, platform_nb);
-   return 0;
+
+   ret = dev_pm_qos_add_global_notifier(omap_device_pm_qos_nb);
+   if (!ret)
+   pr_err(omap_device: cannot add global notifier for dev PM 
QoS\n);
+
+   return ret

[PATCH 4/6] ARM: OMAP3: cpuidle: next C-state decision depends on the PM QoS MPU and CORE constraints

2012-04-18 Thread jean . pihet
From: Jean Pihet j-pi...@ti.com

The MPU latency figures for cpuidle include the MPU itself and also
the peripherals needed for the MPU to execute instructions (e.g.
main memory, caches, IRQ controller, MMU etc). On OMAP3 those
peripherals belong to the MPU and CORE power domains and so the
cpuidle C-states are a combination of MPU and CORE states.

This patch implements the relation between the cpuidle and per-
device PM QoS frameworks in the OMAP3 specific idle callbacks.

The chosen C-state shall satisfy the following conditions:
 . the 'valid' field is enabled,
 . it satisfies the enable_off_mode flag,
 . the next state for MPU and CORE power domains is not lower than the
   next state calculated by the per-device PM QoS.

Tested on OMAP3 Beagleboard in RET/OFF using wake-up latency constraints
on MPU, CORE and PER.

Signed-off-by: Jean Pihet j-pi...@ti.com
Reviewed-by: Kevin Hilman khil...@ti.com
---
 arch/arm/mach-omap2/cpuidle34xx.c |   59 -
 arch/arm/mach-omap2/pm.h  |   17 +-
 2 files changed, 47 insertions(+), 29 deletions(-)

diff --git a/arch/arm/mach-omap2/cpuidle34xx.c 
b/arch/arm/mach-omap2/cpuidle34xx.c
index ff2dea3..2f95cfc 100644
--- a/arch/arm/mach-omap2/cpuidle34xx.c
+++ b/arch/arm/mach-omap2/cpuidle34xx.c
@@ -39,7 +39,7 @@
 #ifdef CONFIG_CPU_IDLE
 
 /*
- * The latencies/thresholds for various C states have
+ * The MPU latencies/thresholds for various C states have
  * to be configured from the respective board files.
  * These are some default values (which might not provide
  * the best power savings) used on boards which do not
@@ -74,22 +74,21 @@ struct omap3_idle_statedata 
omap3_idle_data[OMAP3_NUM_STATES];
 struct powerdomain *mpu_pd, *core_pd, *per_pd, *cam_pd;
 
 static int _cpuidle_allow_idle(struct powerdomain *pwrdm,
-   struct clockdomain *clkdm)
+  struct clockdomain *clkdm)
 {
clkdm_allow_idle(clkdm);
return 0;
 }
 
 static int _cpuidle_deny_idle(struct powerdomain *pwrdm,
-   struct clockdomain *clkdm)
+ struct clockdomain *clkdm)
 {
clkdm_deny_idle(clkdm);
return 0;
 }
 
 static int __omap3_enter_idle(struct cpuidle_device *dev,
-   struct cpuidle_driver *drv,
-   int index)
+ struct cpuidle_driver *drv, int index)
 {
struct omap3_idle_statedata *cx =
cpuidle_get_statedata(dev-states_usage[index]);
@@ -147,10 +146,13 @@ return_sleep_time:
  *
  * Called from the CPUidle framework to program the device to the
  * specified target state selected by the governor.
+ *
+ * Note: this function does not check for any pending activity or dependency
+ * between power domains states, so the caller shall check the parameters
+ * correctness.
  */
 static inline int omap3_enter_idle(struct cpuidle_device *dev,
-   struct cpuidle_driver *drv,
-   int index)
+  struct cpuidle_driver *drv, int index)
 {
return cpuidle_wrap_enter(dev, drv, index, __omap3_enter_idle);
 }
@@ -165,18 +167,22 @@ static inline int omap3_enter_idle(struct cpuidle_device 
*dev,
  * to the caller. Else, this function searches for a lower c-state which is
  * still valid (as defined in omap3_power_states[]) and returns its index.
  *
- * A state is valid if the 'valid' field is enabled and
- * if it satisfies the enable_off_mode condition.
+ * A state is valid if:
+ * . the 'valid' field is enabled,
+ * . it satisfies the enable_off_mode flag,
+ * . the next state for MPU and CORE power domains is not lower than the
+ *   state programmed by the per-device PM QoS.
  */
 static int next_valid_state(struct cpuidle_device *dev,
-   struct cpuidle_driver *drv,
-   int index)
+   struct cpuidle_driver *drv, int index)
 {
struct cpuidle_state_usage *curr_usage = dev-states_usage[index];
struct cpuidle_state *curr = drv-states[index];
struct omap3_idle_statedata *cx = cpuidle_get_statedata(curr_usage);
u32 mpu_deepest_state = PWRDM_FUNC_PWRST_CSWR;
u32 core_deepest_state = PWRDM_FUNC_PWRST_CSWR;
+   u32 mpu_pm_qos_next_state = mpu_pd-wkup_lat_next_state;
+   u32 core_pm_qos_next_state = core_pd-wkup_lat_next_state;
int next_index = -1;
 
if (enable_off_mode) {
@@ -193,7 +199,9 @@ static int next_valid_state(struct cpuidle_device *dev,
/* Check if current state is valid */
if ((cx-valid) 
(cx-mpu_state = mpu_deepest_state) 
-   (cx-core_state = core_deepest_state)) {
+   (cx-core_state = core_deepest_state) 
+   (cx-mpu_state = mpu_pm_qos_next_state) 
+   (cx-core_state = core_pm_qos_next_state)) {
return

[PATCH 6/6] ARM: OMAP3: powerdomain data: add wake-up latency figures

2012-04-18 Thread jean . pihet
From: Jean Pihet j-pi...@ti.com

Figures are added to the power domains structs for RET and OFF modes.

Note: the latency figures for MPU, PER, CORE, NEON have been obtained
from actual measurements.
The latency figures for the other power domains are preliminary and
shall be added.

Cf. http://www.omappedia.org/wiki/Power_Management_Device_Latencies_Measurement
for a detailed explanation on where are the numbers coming from.

Tested on OMAP3 Beagleboard in RET/OFF using wake-up latency constraints
on MPU, CORE and PER.

Signed-off-by: Jean Pihet j-pi...@ti.com
Reviewed-by: Kevin Hilman khil...@ti.com
---
 arch/arm/mach-omap2/powerdomains3xxx_data.c |   83 +++
 1 files changed, 83 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/powerdomains3xxx_data.c 
b/arch/arm/mach-omap2/powerdomains3xxx_data.c
index b7ea468..34103f81 100644
--- a/arch/arm/mach-omap2/powerdomains3xxx_data.c
+++ b/arch/arm/mach-omap2/powerdomains3xxx_data.c
@@ -32,6 +32,19 @@
 
 /*
  * Powerdomains
+ *
+ * The wakeup_lat values are derived from HW and SW measurements on
+ * the actual target. For more details cf.
+ * 
http://www.omappedia.org/wiki/Power_Management_Device_Latencies_Measurement#Results_for_individual_power_domains
+ *
+ * Note: the latency figures for MPU, PER, CORE, NEON have been obtained
+ * from actual measurements.
+ * The latency figures for the other power domains are preliminary and
+ * shall be added.
+ *
+ * Note: only the SW restore timing values are taken into account.
+ * The HW impact of the sys_clkreq and sys_offmode signals is not taken
+ * into account - TDB
  */
 
 static struct powerdomain iva2_pwrdm = {
@@ -52,6 +65,13 @@ static struct powerdomain iva2_pwrdm = {
[2] = PWRSTS_OFF_ON,
[3] = PWRSTS_ON,
},
+   .wakeup_lat = {
+   [PWRDM_FUNC_PWRST_OFF] = 1100,
+   [PWRDM_FUNC_PWRST_OSWR] = UNSUP_STATE,
+   [PWRDM_FUNC_PWRST_CSWR] = 350,
+   [PWRDM_FUNC_PWRST_INACTIVE] = UNSUP_STATE,
+   [PWRDM_FUNC_PWRST_ON] = 0,
+   },
.voltdm   = { .name = mpu_iva },
 };
 
@@ -68,6 +88,13 @@ static struct powerdomain mpu_3xxx_pwrdm = {
.pwrsts_mem_on= {
[0] = PWRSTS_OFF_ON,
},
+   .wakeup_lat = {
+   [PWRDM_FUNC_PWRST_OFF] = 1830,
+   [PWRDM_FUNC_PWRST_OSWR] = UNSUP_STATE,
+   [PWRDM_FUNC_PWRST_CSWR] = 121,
+   [PWRDM_FUNC_PWRST_INACTIVE] = UNSUP_STATE,
+   [PWRDM_FUNC_PWRST_ON] = 0,
+   },
.voltdm   = { .name = mpu_iva },
 };
 
@@ -95,6 +122,13 @@ static struct powerdomain core_3xxx_pre_es3_1_pwrdm = {
[0] = PWRSTS_OFF_RET_ON, /* MEM1ONSTATE */
[1] = PWRSTS_OFF_RET_ON, /* MEM2ONSTATE */
},
+   .wakeup_lat = {
+   [PWRDM_FUNC_PWRST_OFF] = 3082,
+   [PWRDM_FUNC_PWRST_OSWR] = UNSUP_STATE,
+   [PWRDM_FUNC_PWRST_CSWR] = 153,
+   [PWRDM_FUNC_PWRST_INACTIVE] = UNSUP_STATE,
+   [PWRDM_FUNC_PWRST_ON] = 0,
+   },
.voltdm   = { .name = core },
 };
 
@@ -117,6 +151,13 @@ static struct powerdomain core_3xxx_es3_1_pwrdm = {
[0] = PWRSTS_OFF_RET_ON, /* MEM1ONSTATE */
[1] = PWRSTS_OFF_RET_ON, /* MEM2ONSTATE */
},
+   .wakeup_lat = {
+   [PWRDM_FUNC_PWRST_OFF] = 3082,
+   [PWRDM_FUNC_PWRST_OSWR] = UNSUP_STATE,
+   [PWRDM_FUNC_PWRST_CSWR] = 153,
+   [PWRDM_FUNC_PWRST_INACTIVE] = UNSUP_STATE,
+   [PWRDM_FUNC_PWRST_ON] = 0,
+   },
.voltdm   = { .name = core },
 };
 
@@ -132,6 +173,13 @@ static struct powerdomain dss_pwrdm = {
.pwrsts_mem_on= {
[0] = PWRSTS_ON,  /* MEMONSTATE */
},
+   .wakeup_lat = {
+   [PWRDM_FUNC_PWRST_OFF] = 70,
+   [PWRDM_FUNC_PWRST_OSWR] = UNSUP_STATE,
+   [PWRDM_FUNC_PWRST_CSWR] = 20,
+   [PWRDM_FUNC_PWRST_INACTIVE] = UNSUP_STATE,
+   [PWRDM_FUNC_PWRST_ON] = 0,
+   },
.voltdm   = { .name = core },
 };
 
@@ -153,6 +201,13 @@ static struct powerdomain sgx_pwrdm = {
.pwrsts_mem_on= {
[0] = PWRSTS_ON,  /* MEMONSTATE */
},
+   .wakeup_lat = {
+   [PWRDM_FUNC_PWRST_OFF] = 1000,
+   [PWRDM_FUNC_PWRST_OSWR] = UNSUP_STATE,
+   [PWRDM_FUNC_PWRST_CSWR] = UNSUP_STATE,
+   [PWRDM_FUNC_PWRST_INACTIVE] = UNSUP_STATE,
+   [PWRDM_FUNC_PWRST_ON] = 0,
+   },
.voltdm   = { .name = core },
 };
 
@@ -168,6 +223,13 @@ static struct powerdomain cam_pwrdm = {
.pwrsts_mem_on= {
[0] = PWRSTS_ON,  /* MEMONSTATE */
},
+   .wakeup_lat = {
+   [PWRDM_FUNC_PWRST_OFF] = 850,
+   [PWRDM_FUNC_PWRST_OSWR] = UNSUP_STATE

[PATCH 5/6] ARM: OMAP3: update cpuidle latency and threshold figures

2012-04-18 Thread jean . pihet
From: Jean Pihet j-pi...@ti.com

Update the data from the measurements performed at HW and SW levels.

Cf. http://www.omappedia.org/wiki/Power_Management_Device_Latencies_Measurement
for a detailed explanation on where are the numbers coming from.

ToDo:
- Measure the wake-up latencies for all power domains for OMAP3
- Correct some numbers when sys_clkreq and sys_offmode are supported

Signed-off-by: Jean Pihet j-pi...@ti.com
Reviewed-by: Kevin Hilman khil...@ti.com
---
 arch/arm/mach-omap2/cpuidle34xx.c |   52 +++-
 1 files changed, 33 insertions(+), 19 deletions(-)

diff --git a/arch/arm/mach-omap2/cpuidle34xx.c 
b/arch/arm/mach-omap2/cpuidle34xx.c
index 2f95cfc..e406d7b 100644
--- a/arch/arm/mach-omap2/cpuidle34xx.c
+++ b/arch/arm/mach-omap2/cpuidle34xx.c
@@ -39,27 +39,41 @@
 #ifdef CONFIG_CPU_IDLE
 
 /*
- * The MPU latencies/thresholds for various C states have
- * to be configured from the respective board files.
- * These are some default values (which might not provide
- * the best power savings) used on boards which do not
- * pass these details from the board file.
+ * The MPU latency and threshold values for the C-states are the worst case
+ * values from the HW and SW, as described in details at
+ * 
http://www.omappedia.org/wiki/Power_Management_Device_Latencies_Measurement#cpuidle_results
+ *
+ * Measurements conditions and remarks:
+ *  . the measurements have been performed at OPP50
+ *  . the sys_offmode signal is not supported and so not used for the
+ *measurements. Instead the latency and threshold values for C9 are
+ *corrected with the value for Triton 2, which is 11.5ms
+ *  . the sys_clkreq signal is not used and so a correction is needed - TBD
+ *  . the sys_clkoff signal is supported, this value need to be corrected with
+ *the correct value of SYSCLK on/off timings (1ms for sysclk on, 2.5ms
+ *for sysclk off)
+ *  . in order to force the cpuidle algorithm to chose the power efficient
+ *C-states (C1, C3, C5, C7) in preference, the other C-states have a
+ *threshold value equal to the next power efficient C-state
+ * 
+ * The latency and threshold values can be overriden by data from the board
+ * files, using omap3_pm_init_cpuidle.
  */
 static struct cpuidle_params cpuidle_params_table[] = {
-   /* C1 */
-   {2 + 2, 5, 1},
-   /* C2 */
-   {10 + 10, 30, 1},
-   /* C3 */
-   {50 + 50, 300, 1},
-   /* C4 */
-   {1500 + 1800, 4000, 1},
-   /* C5 */
-   {2500 + 7500, 12000, 1},
-   /* C6 */
-   {3000 + 8500, 15000, 1},
-   /* C7 */
-   {1 + 3, 30, 1},
+   /* C1 . MPU WFI + Core active */
+   {73 + 78, 152, 1},
+   /* C2 . MPU WFI + Core inactive */
+   {165 + 88, 345, 1},
+   /* C3 . MPU CSWR + Core inactive */
+   {163 + 182, 345, 1},
+   /* C4 . MPU OFF + Core inactive */
+   {2852 + 605, 15, 1},
+   /* C5 . MPU RET + Core RET */
+   {800 + 366, 2120, 1},
+   /* C6 . MPU OFF + Core RET */
+   {4080 + 801, 215000, 1},
+   /* C7 . MPU OFF + Core OFF */
+   {4300 + 13000, 215000, 1},
 };
 #define OMAP3_NUM_STATES ARRAY_SIZE(cpuidle_params_table)
 
-- 
1.7.7.6

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


[PATCH 0/2] ARM: OMAP: PM: remove the latency related functions from the API

2012-04-18 Thread jean . pihet
From: Jean Pihet j-pi...@ti.com

Remove the following functions from the OMAP PM API and the callers
(currently only I2C driver):
 omap_pm_set_max_mpu_wakeup_lat
 omap_pm_set_max_dev_wakeup_lat
 omap_pm_set_max_sdma_lat
and updated the kernel Documentation accordingly.

The generic per-device PM QoS functions shall be used instead of the
OMAP PM API, cf. include/linux/pm_qos.h and
Documentation/power/pm_qos_interface.txt.

Based on the pm-qos branch of the linux-omap git tree (3.4.0-rc2) [1] with
the changes for the functional power states [2] and the per-device PM
QoS support for OMAP [3].

Tested cpuidle and suspend on OMAP3 Beagleboard (ES2.x) with constraints
on MPU, CORE, PER in RETention and OFF modes.

[1] git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap.git
[2] http://marc.info/?l=linux-omapm=133475291911194w=2
[3] http://marc.info/?l=linux-omapm=133475685213067w=2


Jean Pihet (2):
  ARM: OMAP: convert I2C driver to PM QoS for latency constraints
  ARM: OMAP: PM: remove the latency related functions from the API

 Documentation/arm/OMAP/omap_pm|   68 ++--
 arch/arm/plat-omap/i2c.c  |   21 --
 arch/arm/plat-omap/include/plat/omap-pm.h |   99 -
 arch/arm/plat-omap/omap-pm-noop.c |   88 -
 drivers/i2c/busses/i2c-omap.c |   28 +---
 include/linux/i2c-omap.h  |1 -
 6 files changed, 38 insertions(+), 267 deletions(-)

-- 
1.7.7.6

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


[PATCH 2/2] ARM: OMAP: PM: remove the latency related functions from the API

2012-04-18 Thread jean . pihet
From: Jean Pihet j-pi...@ti.com

Remove the following functions from the OMAP PM API:
 omap_pm_set_max_mpu_wakeup_lat
 omap_pm_set_max_dev_wakeup_lat
 omap_pm_set_max_sdma_lat
and updated the kernel Documentation accordingly.

The generic per-device PM QoS functions shall be used instead of the
OMAP PM API, cf. include/linux/pm_qos.h and
Documentation/power/pm_qos_interface.txt.

Signed-off-by: Jean Pihet j-pi...@ti.com
---
 Documentation/arm/OMAP/omap_pm|   68 ++--
 arch/arm/plat-omap/include/plat/omap-pm.h |   99 -
 arch/arm/plat-omap/omap-pm-noop.c |   88 -
 3 files changed, 21 insertions(+), 234 deletions(-)

diff --git a/Documentation/arm/OMAP/omap_pm b/Documentation/arm/OMAP/omap_pm
index 9012bb0..90f67a3 100644
--- a/Documentation/arm/OMAP/omap_pm
+++ b/Documentation/arm/OMAP/omap_pm
@@ -5,8 +5,19 @@ The OMAP PM interface
 This document describes the temporary OMAP PM interface.  Driver
 authors use these functions to communicate minimum latency or
 throughput constraints to the kernel power management code.
+
 Over time, the intention is to merge features from the OMAP PM
 interface into the Linux PM QoS code.
+The following PM QoS features already migrated to the PM QoS framework:
+- PM QoS CPU and DMA latency: used to specify the maximum allowed wake-up
+  latency for the CPU,
+- per device PM QoS latency: used to specifiy the maximum allowed wake-up
+  latency for a given device.
+
+Please refer to the corresponding header file and kernel documentation
+for the PM QoS framework, respectively at include/linux/pm_qos.h and
+Documentation/power/pm_qos_interface.txt.
+
 
 Drivers need to express PM parameters which:
 
@@ -29,21 +40,12 @@ Drivers need to express PM parameters which:
 
 
 This document proposes the OMAP PM interface, including the following
-five power management functions for driver code:
-
-1. Set the maximum MPU wakeup latency:
-   (*pdata-set_max_mpu_wakeup_lat)(struct device *dev, unsigned long t)
+power management functions for driver code:
 
-2. Set the maximum device wakeup latency:
-   (*pdata-set_max_dev_wakeup_lat)(struct device *dev, unsigned long t)
-
-3. Set the maximum system DMA transfer start latency (CORE pwrdm):
-   (*pdata-set_max_sdma_lat)(struct device *dev, long t)
-
-4. Set the minimum bus throughput needed by a device:
+1. Set the minimum bus throughput needed by a device:
(*pdata-set_min_bus_tput)(struct device *dev, u8 agent_id, unsigned long r)
 
-5. Return the number of times the device has lost context
+2. Return the number of times the device has lost context
(*pdata-get_dev_context_loss_count)(struct device *dev)
 
 
@@ -55,10 +57,12 @@ The OMAP PM layer is intended to be temporary
 -
 
 The intention is that eventually the Linux PM QoS layer should support
-the range of power management features present in OMAP3.  As this
-happens, existing drivers using the OMAP PM interface can be modified
+the range of power management features present in OMAP3. As this
+happens, existing drivers using the OMAP PM interface shall be modified
 to use the Linux PM QoS code; and the OMAP PM interface can disappear.
 
+The set_min_bus_tput function shall be converted to a throughput PM QoS
+framework.
 
 Driver usage of the OMAP PM functions
 -
@@ -66,39 +70,9 @@ Driver usage of the OMAP PM functions
 As the 'pdata' in the above examples indicates, these functions are
 exposed to drivers through function pointers in driver .platform_data
 structures.  The function pointers are initialized by the board-*.c
-files to point to the corresponding OMAP PM functions:
-.set_max_dev_wakeup_lat will point to
-omap_pm_set_max_dev_wakeup_lat(), etc.  Other architectures which do
-not support these functions should leave these function pointers set
-to NULL.  Drivers should use the following idiom:
-
-if (pdata-set_max_dev_wakeup_lat)
-(*pdata-set_max_dev_wakeup_lat)(dev, t);
-
-The most common usage of these functions will probably be to specify
-the maximum time from when an interrupt occurs, to when the device
-becomes accessible.  To accomplish this, driver writers should use the
-set_max_mpu_wakeup_lat() function to to constrain the MPU wakeup
-latency, and the set_max_dev_wakeup_lat() function to constrain the
-device wakeup latency (from clk_enable() to accessibility).  For
-example,
-
-/* Limit MPU wakeup latency */
-if (pdata-set_max_mpu_wakeup_lat)
-(*pdata-set_max_mpu_wakeup_lat)(dev, tc);
-
-/* Limit device powerdomain wakeup latency */
-if (pdata-set_max_dev_wakeup_lat)
-(*pdata-set_max_dev_wakeup_lat)(dev, td);
-
-/* total wakeup latency in this example: (tc + td) */
-
-The PM parameters can be overwritten by calling the function again
-with the new value.  The settings can be removed by calling the
-function

Re: [PATCH 5/6] ARM: OMAP3: update cpuidle latency and threshold figures

2012-04-18 Thread Jean Pihet
On Wed, Apr 18, 2012 at 5:18 PM, Grazvydas Ignotas nota...@gmail.com wrote:
 On Wed, Apr 18, 2012 at 4:45 PM,  jean.pi...@newoldbits.com wrote:
 From: Jean Pihet j-pi...@ti.com

 Update the data from the measurements performed at HW and SW levels.

 Cf. 
 http://www.omappedia.org/wiki/Power_Management_Device_Latencies_Measurement
 for a detailed explanation on where are the numbers coming from.

 ...
 ToDo:
 - Measure the wake-up latencies for all power domains for OMAP3
 - Correct some numbers when sys_clkreq and sys_offmode are supported

 Signed-off-by: Jean Pihet j-pi...@ti.com
 Reviewed-by: Kevin Hilman khil...@ti.com
 ---
  arch/arm/mach-omap2/cpuidle34xx.c |   52 
 +++-
  1 files changed, 33 insertions(+), 19 deletions(-)

 diff --git a/arch/arm/mach-omap2/cpuidle34xx.c 
 b/arch/arm/mach-omap2/cpuidle34xx.c
 index 2f95cfc..e406d7b 100644
 --- a/arch/arm/mach-omap2/cpuidle34xx.c
 +++ b/arch/arm/mach-omap2/cpuidle34xx.c
 @@ -39,27 +39,41 @@
 snip
  static struct cpuidle_params cpuidle_params_table[] = {
 -       /* C1 */
 -       {2 + 2, 5, 1},
 -       /* C2 */
 -       {10 + 10, 30, 1},
 -       /* C3 */
 -       {50 + 50, 300, 1},
 -       /* C4 */
 -       {1500 + 1800, 4000, 1},
 -       /* C5 */
 -       {2500 + 7500, 12000, 1},
 -       /* C6 */
 -       {3000 + 8500, 15000, 1},
 -       /* C7 */
 -       {1 + 3, 30, 1},
 +       /* C1 . MPU WFI + Core active */
 +       {73 + 78, 152, 1},
 +       /* C2 . MPU WFI + Core inactive */
 +       {165 + 88, 345, 1},
 +       /* C3 . MPU CSWR + Core inactive */
 +       {163 + 182, 345, 1},
 +       /* C4 . MPU OFF + Core inactive */
 +       {2852 + 605, 15, 1},
 +       /* C5 . MPU RET + Core RET */
 +       {800 + 366, 2120, 1},
 +       /* C6 . MPU OFF + Core RET */
 +       {4080 + 801, 215000, 1},
 +       /* C7 . MPU OFF + Core OFF */
 +       {4300 + 13000, 215000, 1},
  };

 These (C1 at least) seem to look quite a bit better than what we see here:
 http://marc.info/?t=13337528274r=1w=2
 according to that wiki log, some of those measurements are from 2010,
 I wonder if that still matches today's code well.
Those figures are for the HW part of the low power transitions
assuming that the SW overhead (in omap_sram_idle) is minimal, which
seems to not be true anymore.
I need to measure the latencies again on the latest SW.

Thanks,
Jean



 --
 Gražvydas
--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 1/9] ARM: OMAP3+: voltage: export functions to plat/voltage.h

2012-04-18 Thread Jean Pihet
Hi Kevin,

Adding Keerthy J

On Wed, Apr 18, 2012 at 7:27 PM, Kevin Hilman khil...@ti.com wrote:
 Hi Jean,

 jean.pi...@newoldbits.com writes:

 From: Jean Pihet j-pi...@ti.com

 Move some functions from mach-omap2/ dir to the plat/ dir.
 The SmartReflex class driver is a user of the basic voltage domains
 functions (enable, disable, reset).

 Signed-off-by: Jean Pihet j-pi...@ti.com
 Cc: Kevin Hilman khil...@ti.com

 Rather than expose the VP functions directly, how about adding a new API
 at the voltdm layer to start/stop AVS.  Maybe something like:

  voltdm_avs_start(struct voltagedomain *voltdm)
  voltdm_avs_stop(struct voltagedomain *voltdm)

 These will internally just call VP enable/disable for now, but we may
 have more to add to these in the future to support other SR classes.
Agree.
That would be a first step in the definition of the API between SR and
VP. Implementing other SR classes might require more than that, this
is still under investigation for now.


 Kevin


Thanks for reviewing,
Jean
--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 5/9] ARM: OMAP3: hwmod: rename the smartreflex entries

2012-04-18 Thread Jean Pihet
Kevin,

On Wed, Apr 18, 2012 at 7:33 PM, Kevin Hilman khil...@ti.com wrote:
 +Benoit

 jean.pi...@newoldbits.com writes:

 From: Jean Pihet j-pi...@ti.com

 Change the name field value to better reflect the smartreflex
 integration in the system

 Signed-off-by: Jean Pihet j-pi...@ti.com
 ---
  arch/arm/mach-omap2/omap_hwmod_3xxx_data.c |    8 
  arch/arm/mach-omap2/smartreflex.c          |    2 +-
  2 files changed, 5 insertions(+), 5 deletions(-)

 diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c 
 b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
 index d7d4c70..40f57c4 100644
 --- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
 +++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
 @@ -2751,7 +2751,7 @@ static struct omap_hwmod_ocp_if *omap34xx_sr1_slaves[] 
 = {
  };

  static struct omap_hwmod omap34xx_sr1_hwmod = {
 -     .name           = sr1,
 +     .name           = mpu_iva,

 Should this be smartreflex_mpu_iva?

 The OMAP4 SR hwmods have a 'smartreflex_' prefix which seems better.

       .class          = omap34xx_smartreflex_hwmod_class,
       .main_clk       = sr1_fck,
       .prcm           = {
 @@ -2775,7 +2775,7 @@ static struct omap_hwmod_ocp_if *omap36xx_sr1_slaves[] 
 = {
  };

  static struct omap_hwmod omap36xx_sr1_hwmod = {
 -     .name           = sr1,
 +     .name           = mpu_iva,
       .class          = omap36xx_smartreflex_hwmod_class,
       .main_clk       = sr1_fck,
       .prcm           = {
 @@ -2803,7 +2803,7 @@ static struct omap_hwmod_ocp_if *omap34xx_sr2_slaves[] 
 = {
  };

  static struct omap_hwmod omap34xx_sr2_hwmod = {
 -     .name           = sr2,
 +     .name           = core,
       .class          = omap34xx_smartreflex_hwmod_class,
       .main_clk       = sr2_fck,
       .prcm           = {
 @@ -2827,7 +2827,7 @@ static struct omap_hwmod_ocp_if *omap36xx_sr2_slaves[] 
 = {
  };

  static struct omap_hwmod omap36xx_sr2_hwmod = {
 -     .name           = sr2,
 +     .name           = core,
       .class          = omap36xx_smartreflex_hwmod_class,
       .main_clk       = sr2_fck,
       .prcm           = {
 diff --git a/arch/arm/mach-omap2/smartreflex.c 
 b/arch/arm/mach-omap2/smartreflex.c
 index c18d47d..b2728a5 100644
 --- a/arch/arm/mach-omap2/smartreflex.c
 +++ b/arch/arm/mach-omap2/smartreflex.c
 @@ -184,7 +184,7 @@ static void sr_set_regfields(struct omap_sr *sr)
               sr-err_weight = OMAP3430_SR_ERRWEIGHT;
               sr-err_maxlimit = OMAP3430_SR_ERRMAXLIMIT;
               sr-accum_data = OMAP3430_SR_ACCUMDATA;
 -             if (!(strcmp(sr-name, sr1))) {
 +             if (!(strcmp(sr-name, sr_mpu_iva))) {

 Why the 'sr_' prefix?
Historically the sr instance name is generated from hwmod name
prepended with sr_.
I agree it is better to change the hwmod name and remove the sr_
prefix from the sr init code.


                       sr-senn_avgweight = OMAP3430_SR1_SENNAVGWEIGHT;
                       sr-senp_avgweight = OMAP3430_SR1_SENPAVGWEIGHT;
               } else {

 Kevin

Thanks,
Jean
--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 7/9] ARM: OMAP2+: SmartReflex: Use per-OPP data structure

2012-04-18 Thread Jean Pihet
On Wed, Apr 18, 2012 at 8:21 PM, Kevin Hilman khil...@ti.com wrote:
 jean.pi...@newoldbits.com writes:

 From: Jean Pihet j-pi...@ti.com

 The SmartReflex driver incorrectly treats some per-OPP data as data
 common to all OPPs (e.g., ERRMINLIMIT).  Move this data into a per-OPP
 data structure.

 OK

 The SmartReflex driver should not be dependent on whether the host SoC
 uses eFuses to store SmartReflex parameters or not.  (Even SoCs that
 do store SR data in eFuses often need to override that data with
 software-defined values.)  So, convert sr_retrieve_nvalue() to look up
 per-OPP data by the OPP's nominal voltage, rather than by the eFuse
 offset.

 Right.

 While at it:
  . tidy up the code wrt default values in the data tables,
  . remove the global errminlimit debugfs entry and create per-voltage
    entries from the data tables.

 OK

 Furthermore, in order to make the SmartReflex implementation ready for
 the move to drivers/, remove the dependency from the SR driver code
 to the voltage layer by querying the data tables only from the SR device
 init code.

 So that's 4 relatively independent things going on in this patch which
 makes it somewhat difficult to review and understand.

 I'd suggest breaking it up into smaller parts if possible.  If not, fix
 up the changelog to describe why all of these need to go together, and
 why it's necessary to do them before the move.
Those changes are not independent from each other.
However for improved readability the patch can be split up (e.g.
efuse-opp, debugfs ...) and the changelog updated accordingly.


 Thanks,

 Kevin


Thanks,
Jean
--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[RFC/PATCH v2 0/6] ARM: OMAP2+: PM: introduce the power domains functional states

2012-04-11 Thread jean . pihet
From: Jean Pihet j-pi...@ti.com

Implement the functional states for the power domains:
- protect the power domain state change by a mutex in
  omap_set_pwrdm_state,
- introduce the functional states for power domains power states and
  logic power states, and the conversion functions between the
  functional and internal states,
- unify the API to use the functional states,
- program the logic power state of power domains from the functional
  states, in omap_set_pwrdm_state
- convert the OMAP2/3/4 PM code to use the updated API,
- provide the power domains statistics by functional states.

Tested on OMAP3 Beagleboard, with suspend and cpuidle in RET and
OFF modes.


Jean Pihet (6):
  ARM: OMAP2+: PM: protect the power domain state change by a mutex
  ARM: OMAP2+: PM: introduce power domains functional states
  ARM: OMAP2+: PM: use the functional power states API
  ARM: OMAP2+: PM: introduce power domains logic and memory functional
states
  ARM: OMAP2+: PM: use the functional power states API for logic and
memory
  ARM: OMAP2+: PM: use power domain functional state in stats counters

 arch/arm/mach-omap2/cpuidle34xx.c  |   61 
 arch/arm/mach-omap2/cpuidle44xx.c  |   28 ++--
 arch/arm/mach-omap2/omap-hotplug.c |2 +-
 arch/arm/mach-omap2/omap-mpuss-lowpower.c  |   39 +++---
 arch/arm/mach-omap2/pm-debug.c |   15 +-
 arch/arm/mach-omap2/pm.c   |   62 ---
 arch/arm/mach-omap2/pm24xx.c   |   14 +-
 arch/arm/mach-omap2/pm34xx.c   |   80 +-
 arch/arm/mach-omap2/pm44xx.c   |   15 +--
 arch/arm/mach-omap2/powerdomain-common.c   |   85 ++
 arch/arm/mach-omap2/powerdomain.c  |  244 ++--
 arch/arm/mach-omap2/powerdomain.h  |   42 +-
 arch/arm/mach-omap2/powerdomain2xxx_3xxx.c |7 +
 arch/arm/mach-omap2/powerdomain44xx.c  |3 +
 14 files changed, 489 insertions(+), 208 deletions(-)

-- 
1.7.7.6

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


[PATCH 1/6] ARM: OMAP2+: PM: protect the power domain state change by a mutex

2012-04-11 Thread jean . pihet
From: Jean Pihet j-pi...@ti.com

Signed-off-by: Jean Pihet j-pi...@ti.com
---
 arch/arm/mach-omap2/pm.c  |8 ++--
 arch/arm/mach-omap2/powerdomain.c |1 +
 arch/arm/mach-omap2/powerdomain.h |3 ++-
 3 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
index d0c1c96..6918a13 100644
--- a/arch/arm/mach-omap2/pm.c
+++ b/arch/arm/mach-omap2/pm.c
@@ -100,15 +100,17 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 
pwrst)
if (!pwrdm || IS_ERR(pwrdm))
return -EINVAL;
 
+   mutex_lock(pwrdm-lock);
+
while (!(pwrdm-pwrsts  (1  pwrst))) {
if (pwrst == PWRDM_POWER_OFF)
-   return ret;
+   goto out;
pwrst--;
}
 
next_pwrst = pwrdm_read_next_pwrst(pwrdm);
if (next_pwrst == pwrst)
-   return ret;
+   goto out;
 
curr_pwrst = pwrdm_read_pwrst(pwrdm);
if (curr_pwrst  PWRDM_POWER_ON) {
@@ -141,6 +143,8 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 
pwrst)
break;
}
 
+out:
+   mutex_unlock(pwrdm-lock);
return ret;
 }
 
diff --git a/arch/arm/mach-omap2/powerdomain.c 
b/arch/arm/mach-omap2/powerdomain.c
index 96ad3dbe..319b277 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -102,6 +102,7 @@ static int _pwrdm_register(struct powerdomain *pwrdm)
INIT_LIST_HEAD(pwrdm-voltdm_node);
voltdm_add_pwrdm(voltdm, pwrdm);
 
+   mutex_init(pwrdm-lock);
list_add(pwrdm-node, pwrdm_list);
 
/* Initialize the powerdomain's state counter */
diff --git a/arch/arm/mach-omap2/powerdomain.h 
b/arch/arm/mach-omap2/powerdomain.h
index 0d72a8a..6c6567d 100644
--- a/arch/arm/mach-omap2/powerdomain.h
+++ b/arch/arm/mach-omap2/powerdomain.h
@@ -19,7 +19,7 @@
 
 #include linux/types.h
 #include linux/list.h
-
+#include linux/mutex.h
 #include linux/atomic.h
 
 #include plat/cpu.h
@@ -116,6 +116,7 @@ struct powerdomain {
struct clockdomain *pwrdm_clkdms[PWRDM_MAX_CLKDMS];
struct list_head node;
struct list_head voltdm_node;
+   struct mutex lock;
int state;
unsigned state_counter[PWRDM_MAX_PWRSTS];
unsigned ret_logic_off_counter;
-- 
1.7.7.6

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


[PATCH 2/6] ARM: OMAP2+: PM: introduce power domains functional states

2012-04-11 Thread jean . pihet
From: Jean Pihet j-pi...@ti.com

Introduce functional (or logical) states for power domains and the
API functions to read the power domains settings and to convert
between the functional (i.e. logical) and the internal (or registers)
values.

OMAP2, OMAP3 and OMAP4 platforms are defining a conversion routine.

In the new API the function omap_set_pwrdm_state takes the functional
states as parameter; while at it the function is moved to the power
domains code.

The memory and logic states are not using the functional states, this
comes as a subsequent patch.

Signed-off-by: Jean Pihet j-pi...@ti.com
---
 arch/arm/mach-omap2/pm.c   |   66 ---
 arch/arm/mach-omap2/powerdomain-common.c   |   61 ++
 arch/arm/mach-omap2/powerdomain.c  |  175 
 arch/arm/mach-omap2/powerdomain.h  |   21 
 arch/arm/mach-omap2/powerdomain2xxx_3xxx.c |5 +
 arch/arm/mach-omap2/powerdomain44xx.c  |2 +
 6 files changed, 264 insertions(+), 66 deletions(-)

diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
index 6918a13..8670c4b 100644
--- a/arch/arm/mach-omap2/pm.c
+++ b/arch/arm/mach-omap2/pm.c
@@ -74,10 +74,6 @@ static void __init omap2_init_processor_devices(void)
}
 }
 
-/* Types of sleep_switch used in omap_set_pwrdm_state */
-#define FORCEWAKEUP_SWITCH 0
-#define LOWPOWERSTATE_SWITCH   1
-
 int __init omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused)
 {
if (clkdm-flags  CLKDM_CAN_ENABLE_AUTO)
@@ -89,68 +85,6 @@ int __init omap_pm_clkdms_setup(struct clockdomain *clkdm, 
void *unused)
 }
 
 /*
- * This sets pwrdm state (other than mpu  core. Currently only ON 
- * RET are supported.
- */
-int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 pwrst)
-{
-   u8 curr_pwrst, next_pwrst;
-   int sleep_switch = -1, ret = 0, hwsup = 0;
-
-   if (!pwrdm || IS_ERR(pwrdm))
-   return -EINVAL;
-
-   mutex_lock(pwrdm-lock);
-
-   while (!(pwrdm-pwrsts  (1  pwrst))) {
-   if (pwrst == PWRDM_POWER_OFF)
-   goto out;
-   pwrst--;
-   }
-
-   next_pwrst = pwrdm_read_next_pwrst(pwrdm);
-   if (next_pwrst == pwrst)
-   goto out;
-
-   curr_pwrst = pwrdm_read_pwrst(pwrdm);
-   if (curr_pwrst  PWRDM_POWER_ON) {
-   if ((curr_pwrst  pwrst) 
-   (pwrdm-flags  PWRDM_HAS_LOWPOWERSTATECHANGE)) {
-   sleep_switch = LOWPOWERSTATE_SWITCH;
-   } else {
-   hwsup = clkdm_in_hwsup(pwrdm-pwrdm_clkdms[0]);
-   clkdm_wakeup(pwrdm-pwrdm_clkdms[0]);
-   sleep_switch = FORCEWAKEUP_SWITCH;
-   }
-   }
-
-   ret = pwrdm_set_next_pwrst(pwrdm, pwrst);
-   if (ret)
-   pr_err(%s: unable to set power state of powerdomain: %s\n,
-  __func__, pwrdm-name);
-
-   switch (sleep_switch) {
-   case FORCEWAKEUP_SWITCH:
-   if (hwsup)
-   clkdm_allow_idle(pwrdm-pwrdm_clkdms[0]);
-   else
-   clkdm_sleep(pwrdm-pwrdm_clkdms[0]);
-   break;
-   case LOWPOWERSTATE_SWITCH:
-   pwrdm_set_lowpwrstchange(pwrdm);
-   pwrdm_wait_transition(pwrdm);
-   pwrdm_state_switch(pwrdm);
-   break;
-   }
-
-out:
-   mutex_unlock(pwrdm-lock);
-   return ret;
-}
-
-
-
-/*
  * This API is to be called during init to set the various voltage
  * domains to the voltage as per the opp table. Typically we boot up
  * at the nominal voltage. So this function finds out the rate of
diff --git a/arch/arm/mach-omap2/powerdomain-common.c 
b/arch/arm/mach-omap2/powerdomain-common.c
index c0aeabf..098dc42 100644
--- a/arch/arm/mach-omap2/powerdomain-common.c
+++ b/arch/arm/mach-omap2/powerdomain-common.c
@@ -108,3 +108,64 @@ u32 omap2_pwrdm_get_mem_bank_stst_mask(u8 bank)
return 0;
 }
 
+/*
+ * Functional (i.e. logical) to internal (i.e. registers)
+ * values for the power domains states
+ */
+int omap2_pwrdm_func_to_pwrst(struct powerdomain *pwrdm, u8 func_pwrst)
+{
+   int ret;
+
+   switch (func_pwrst) {
+   case PWRDM_FUNC_PWRST_ON:
+   ret = PWRDM_POWER_ON;
+   break;
+   case PWRDM_FUNC_PWRST_INACTIVE:
+   ret = PWRDM_POWER_INACTIVE;
+   break;
+   case PWRDM_FUNC_PWRST_CSWR:
+   case PWRDM_FUNC_PWRST_OSWR:
+   ret = PWRDM_POWER_RET;
+   break;
+   case PWRDM_FUNC_PWRST_OFF:
+   ret = PWRDM_POWER_OFF;
+   break;
+   default:
+   ret = -1;
+   }
+
+   return ret;
+}
+
+/*
+ * Internal (i.e. registers) to functional (i.e. logical) values
+ * for the power domains states
+ */
+int omap2_pwrdm_pwrst_to_func(struct powerdomain *pwrdm, u8 pwrst)
+{
+   int ret;
+
+   switch (pwrst

[PATCH 3/6] ARM: OMAP2+: PM: use the functional power states API

2012-04-11 Thread jean . pihet
From: Jean Pihet j-pi...@ti.com

Use the functional power states as the API to control power domains.
The omap_set_pwrdm_state function shall be used instead of
pwrdm_set_next_pwrst to control the power domains next states.

Note: the internal code for power domains state management still
uses the internal power states.

Signed-off-by: Jean Pihet j-pi...@ti.com
---
 arch/arm/mach-omap2/cpuidle34xx.c |   61 +++---
 arch/arm/mach-omap2/cpuidle44xx.c |   25 +
 arch/arm/mach-omap2/omap-hotplug.c|2 +-
 arch/arm/mach-omap2/omap-mpuss-lowpower.c |   43 +---
 arch/arm/mach-omap2/pm24xx.c  |   10 ++--
 arch/arm/mach-omap2/pm34xx.c  |   80 +++--
 arch/arm/mach-omap2/pm44xx.c  |8 ++--
 arch/arm/mach-omap2/powerdomain.c |2 +-
 8 files changed, 120 insertions(+), 111 deletions(-)

diff --git a/arch/arm/mach-omap2/cpuidle34xx.c 
b/arch/arm/mach-omap2/cpuidle34xx.c
index 5358664..538aea5 100644
--- a/arch/arm/mach-omap2/cpuidle34xx.c
+++ b/arch/arm/mach-omap2/cpuidle34xx.c
@@ -97,8 +97,8 @@ static int __omap3_enter_idle(struct cpuidle_device *dev,
 
local_fiq_disable();
 
-   pwrdm_set_next_pwrst(mpu_pd, mpu_state);
-   pwrdm_set_next_pwrst(core_pd, core_state);
+   omap_set_pwrdm_state(mpu_pd, mpu_state);
+   omap_set_pwrdm_state(core_pd, core_state);
 
if (omap_irq_pending() || need_resched())
goto return_sleep_time;
@@ -113,7 +113,7 @@ static int __omap3_enter_idle(struct cpuidle_device *dev,
 * Call idle CPU PM enter notifier chain so that
 * VFP context is saved.
 */
-   if (mpu_state == PWRDM_POWER_OFF)
+   if (mpu_state == PWRDM_FUNC_PWRST_OFF)
cpu_pm_enter();
 
/* Execute ARM wfi */
@@ -123,7 +123,7 @@ static int __omap3_enter_idle(struct cpuidle_device *dev,
 * Call idle CPU PM enter notifier chain to restore
 * VFP context.
 */
-   if (pwrdm_read_prev_pwrst(mpu_pd) == PWRDM_POWER_OFF)
+   if (pwrdm_read_prev_func_pwrst(mpu_pd) == PWRDM_FUNC_PWRST_OFF)
cpu_pm_exit();
 
/* Re-allow idle for C1 */
@@ -175,19 +175,19 @@ static int next_valid_state(struct cpuidle_device *dev,
struct cpuidle_state_usage *curr_usage = dev-states_usage[index];
struct cpuidle_state *curr = drv-states[index];
struct omap3_idle_statedata *cx = cpuidle_get_statedata(curr_usage);
-   u32 mpu_deepest_state = PWRDM_POWER_RET;
-   u32 core_deepest_state = PWRDM_POWER_RET;
+   u32 mpu_deepest_state = PWRDM_FUNC_PWRST_CSWR;
+   u32 core_deepest_state = PWRDM_FUNC_PWRST_CSWR;
int next_index = -1;
 
if (enable_off_mode) {
-   mpu_deepest_state = PWRDM_POWER_OFF;
+   mpu_deepest_state = PWRDM_FUNC_PWRST_OFF;
/*
 * Erratum i583: valable for ES rev  Es1.2 on 3630.
 * CORE OFF mode is not supported in a stable form, restrict
 * instead the CORE state to RET.
 */
if (!IS_PM34XX_ERRATUM(PM_SDRC_WAKEUP_ERRATUM_i583))
-   core_deepest_state = PWRDM_POWER_OFF;
+   core_deepest_state = PWRDM_FUNC_PWRST_OFF;
}
 
/* Check if current state is valid */
@@ -247,7 +247,7 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
   int index)
 {
int new_state_idx;
-   u32 core_next_state, per_next_state = 0, per_saved_state = 0, cam_state;
+   u32 core_next_state, per_next_state = 0, per_saved_state = 0;
struct omap3_idle_statedata *cx;
int ret;
 
@@ -255,8 +255,7 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
 * Prevent idle completely if CAM is active.
 * CAM does not have wakeup capability in OMAP3.
 */
-   cam_state = pwrdm_read_pwrst(cam_pd);
-   if (cam_state == PWRDM_POWER_ON) {
+   if (pwrdm_read_func_pwrst(cam_pd) == PWRDM_FUNC_PWRST_ON) {
new_state_idx = drv-safe_state_index;
goto select_state;
}
@@ -275,14 +274,14 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
 */
cx = cpuidle_get_statedata(dev-states_usage[index]);
core_next_state = cx-core_state;
-   per_next_state = per_saved_state = pwrdm_read_next_pwrst(per_pd);
-   if ((per_next_state == PWRDM_POWER_OFF) 
-   (core_next_state  PWRDM_POWER_RET))
-   per_next_state = PWRDM_POWER_RET;
+   per_next_state = per_saved_state = pwrdm_read_next_func_pwrst(per_pd);
+   if (per_next_state == PWRDM_FUNC_PWRST_OFF ||
+   core_next_state  PWRDM_FUNC_PWRST_CSWR)
+   per_next_state = PWRDM_FUNC_PWRST_CSWR;
 
/* Are we changing PER target state? */
if (per_next_state != per_saved_state)
-   pwrdm_set_next_pwrst(per_pd

<    1   2   3   4   5   6   7   8   9   10   >