[PATCH 00/12] ARM: OMAP2+: powerdomain/PM: convert to functional power states

2012-12-09 Thread Paul Walmsley
Hi

This series converts the OMAP2+ powerdomain and PM code to use
"functional power states" - high-level power states such as "OSWR",
which reflect changes in multiple underlying registers, rather than
expecting high-level PM code to program the registers directly.  This
is intended to reduce the complexity of the high-level PM code and to
make it easier to implement register caching of the various
powerdomain registers, some of which are quite slow to access.


- Paul

---

vmlinux object size
(delta in bytes from TEST_pm_cleanup_fixes_b_3.9 
(2f8d7b1f0048df431ca226d81c5c27c4dd21953b)):
   text data  bsstotal  kernel
   +456  -560 +400  am33xx_only
   +448  -960 +352  n800_multi_omap2xxx
   +448  -960 +352  n800_only_a
  0000  omap1_defconfig
  0000  omap1_defconfig_1510innovator_only
  0000  omap1_defconfig_5912osk_only
  +1180 -7440 +436  omap2plus_defconfig
   +584  -720 +512  omap2plus_defconfig_2430sdp_only
  +1244 -8080 +436  omap2plus_defconfig_cpupm
   +976-12240 -248  omap2plus_defconfig_no_pm
   +844 -4080 +436  omap2plus_defconfig_omap2_4_only
  +1088 -6240 +464  omap2plus_defconfig_omap3_4_only
  +1292-1232 -352 -292  rmk_omap3430_ldp_allnoconfig
   +916 -7200 +196  rmk_omap3430_ldp_oldconfig
  +1292-1232 -352 -292  rmk_omap4430_sdp_allnoconfig
   +840 -3920 +448  rmk_omap4430_sdp_oldconfig

Boot-time memory difference
(delta in bytes from TEST_pm_cleanup_fixes_b_3.9 
(2f8d7b1f0048df431ca226d81c5c27c4dd21953b))
  avail  rsrvd   high  freed  board  kconfig
-8k 8k  .  .  2430sdpomap2plus_defconfig
-8k 8k  .  .  3517evmomap2plus_defconfig
-8k 8k  .  .  3530es3beagle  omap2plus_defconfig
-8k 8k  .  .  3730beaglexm   omap2plus_defconfig
-8k 8k  .  .  37xxevmomap2plus_defconfig
-8k 8k  .  .  4430es2panda   omap2plus_defconfig
-8k 8k  .  .  4460pandaesomap2plus_defconfig
-8k 8k  .  .  cmt3517omap2plus_defconfig

Jean Pihet (6):
  ARM: OMAP2+: PM: introduce power domains functional states
  ARM: OMAP2+: PM debug: trace the functional power domains states
  ARM: OMAP2xxx: PM: convert to use the functional power states API
  ARM: OMAP3xxx: PM: convert to use the functional power states API
  ARM: OMAP44xx: PM: convert to use the functional power states API
  ARM: OMAP2+: PM: use power domain functional state in stats counters

Paul Walmsley (6):
  ARM: OMAP2+: powerdomain: add functions that report on powerdomain 
capabilities
  ARM: OMAP2+: powerdomain: drop many low-level powerdomain funcs
  ARM: OMAP2+: powerdomain: add ability to test for supported power states
  ARM: OMAP2+: powerdomain/PM: only program supported power states
  ARM: OMAP2+: powerdomain: program memory bank next-power-state upon init
  ARM: OMAP2+: powerdomain: assume memory bank power states follow 
powerdomain


 arch/arm/mach-omap2/common.h  |7 
 arch/arm/mach-omap2/cpuidle34xx.c |   95 +-
 arch/arm/mach-omap2/cpuidle44xx.c |   32 -
 arch/arm/mach-omap2/omap-hotplug.c|2 
 arch/arm/mach-omap2/omap-mpuss-lowpower.c |   69 +-
 arch/arm/mach-omap2/pm-debug.c|   46 -
 arch/arm/mach-omap2/pm.h  |2 
 arch/arm/mach-omap2/pm24xx.c  |   33 -
 arch/arm/mach-omap2/pm34xx.c  |  188 +++-
 arch/arm/mach-omap2/pm44xx.c  |   47 +
 arch/arm/mach-omap2/powerdomain.c | 1235 +
 arch/arm/mach-omap2/powerdomain.h |   69 +-
 12 files changed, 1040 insertions(+), 785 deletions(-)

--
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/12] ARM: OMAP2+: powerdomain: add functions that report on powerdomain capabilities

2012-12-09 Thread Paul Walmsley
Add several functions to report on whether powerdomains can change their
power state or logic retention power state, and whether those abilities
can be controlled by the kernel.  This code is used in subsequent patches
that add the functional power state code.

Signed-off-by: Paul Walmsley 
---
 arch/arm/mach-omap2/powerdomain.c |   56 +
 1 file changed, 56 insertions(+)

diff --git a/arch/arm/mach-omap2/powerdomain.c 
b/arch/arm/mach-omap2/powerdomain.c
index 2a5f15b..94b89a25 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -203,6 +203,62 @@ static int _pwrdm_post_transition_cb(struct powerdomain 
*pwrdm, void *unused)
return 0;
 }
 
+/**
+ * _pwrdm_pwrst_is_controllable - can software change the powerdomain pwrst?
+ * @pwrdm: struct powerdomain * to test
+ *
+ * If the kernel can program the power state that the powerdomain
+ * @pwrdm should enter next, return 1; otherwise, return 0.
+ */
+static bool _pwrdm_pwrst_is_controllable(struct powerdomain *pwrdm)
+{
+   return (!pwrdm->pwrsts || pwrdm->pwrsts == PWRSTS_ON) ? 0 : 1;
+}
+
+/**
+ * _pwrdm_pwrst_can_change - can the power state of @pwrdm change?
+ * @pwrdm: struct powerdomain * to test
+ *
+ * If the power state of the powerdomain represented by @pwrdm can
+ * change (i.e., is not always on), and the kernel has some way to
+ * detect this, return 1; otherwise, return 0.  XXX The current
+ * implementation of this is based on an assumption and has not been
+ * verified against all OMAPs.
+ */
+static bool _pwrdm_pwrst_can_change(struct powerdomain *pwrdm)
+{
+   return _pwrdm_pwrst_is_controllable(pwrdm);
+}
+
+/**
+ * _pwrdm_logic_retst_is_controllable - can software change the logic retst?
+ * @pwrdm: struct powerdomain * to test
+ *
+ * If the kernel can program the power state that the powerdomain
+ * @pwrdm logic should enter when the @pwrdm enters the RETENTION
+ * power state, return 1; otherwise, return 0.
+ */
+static bool _pwrdm_logic_retst_is_controllable(struct powerdomain *pwrdm)
+{
+   return (!pwrdm->pwrsts_logic_ret ||
+   pwrdm->pwrsts_logic_ret == PWRSTS_RET) ? 0 : 1;
+}
+
+/**
+ * _pwrdm_logic_retst_can_change - can the logic retst change on @pwrdm?
+ * @pwrdm: struct powerdomain * to test
+ *
+ * If the logic powerstate for the powerdomain represented by @pwrdm
+ * can ever be something other than the powerdomain's powerstate, and
+ * the kernel has some way to detect this, return 1; otherwise, return
+ * 0.  XXX The current implementation of this is based on an
+ * assumption and has not been verified against all OMAPs.
+ */
+static bool _pwrdm_logic_retst_can_change(struct powerdomain *pwrdm)
+{
+   return _pwrdm_logic_retst_is_controllable(pwrdm);
+}
+
 /* Public functions */
 
 /**


--
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 03/12] ARM: OMAP2+: PM debug: trace the functional power domains states

2012-12-09 Thread Paul Walmsley
From: Jean Pihet 

Trace the power domain transitions using the functional power states,
which include the power and logic states.

Signed-off-by: Jean Pihet 
[p...@pwsan.com: split the fix that was originally part of this patch into a
 separate patch]
Signed-off-by: Paul Walmsley 
---
 arch/arm/mach-omap2/powerdomain.c |   14 --
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/arch/arm/mach-omap2/powerdomain.c 
b/arch/arm/mach-omap2/powerdomain.c
index 18f33de..2c732b6 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -881,13 +881,8 @@ int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 
pwrst)
pr_debug("powerdomain: %s: setting next powerstate 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;
 }
@@ -1571,6 +1566,9 @@ int pwrdm_set_next_fpwrst(struct powerdomain *pwrdm, u8 
fpwrst)
pr_debug("%s: set fpwrst %0x to pwrdm %s\n", __func__, fpwrst,
 pwrdm->name);
 
+   /* Trace the pwrdm desired target state */
+   trace_power_domain_target(pwrdm->name, fpwrst, smp_processor_id());
+
pwrdm_lock(pwrdm);
ret = _set_logic_retst_and_pwrdm_pwrst(pwrdm, logic, pwrst);
pwrdm_unlock(pwrdm);
@@ -1658,6 +1656,10 @@ int pwrdm_set_fpwrst(struct powerdomain *pwrdm, enum 
pwrdm_func_state fpwrst)
if (next_fpwrst == fpwrst)
goto psf_out;
 
+   /* Trace the pwrdm desired target state */
+   trace_power_domain_target(pwrdm->name, next_fpwrst,
+ smp_processor_id());
+
sleep_switch = _pwrdm_save_clkdm_state_and_activate(pwrdm, pwrst,
&hwsup);
 


--
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 05/12] ARM: OMAP3xxx: PM: convert to use the functional power states API

2012-12-09 Thread Paul Walmsley
From: Jean Pihet 

Use the functional power states as the API to control power domains:

- use the PWRDM_FUNC_PWRST_* macros for the power states and logic
  settings,

- the function pwrdm_set_next_fpwrst(), which controls the power domains
  next power and logic settings, shall be used instead of
  pwrdm_set_next_pwrst() to program the power domains next states,

- the function pwrdm_set_fpwrst(), which programs the power domains
  power and logic settings, shall be used instead of
  omap_set_pwrdm_state().

Signed-off-by: Jean Pihet 
[p...@pwsan.com: split the original patch into OMAP2/3/4 variants;
 clean up omap3_save_secure_ram_context(); fix commit message;
 warn if sets fail; various other changes]
Signed-off-by: Paul Walmsley 
---
 arch/arm/mach-omap2/cpuidle34xx.c |   95 ---
 arch/arm/mach-omap2/pm.h  |2 
 arch/arm/mach-omap2/pm34xx.c  |  156 +++--
 3 files changed, 130 insertions(+), 123 deletions(-)

diff --git a/arch/arm/mach-omap2/cpuidle34xx.c 
b/arch/arm/mach-omap2/cpuidle34xx.c
index e6215b5..a8e6263 100644
--- a/arch/arm/mach-omap2/cpuidle34xx.c
+++ b/arch/arm/mach-omap2/cpuidle34xx.c
@@ -36,9 +36,9 @@
 
 /* Mach specific information to be recorded in the C-state driver_data */
 struct omap3_idle_statedata {
-   u8 mpu_state;
-   u8 core_state;
-   u8 per_min_state;
+   u8 mpu_fpwrst;
+   u8 core_fpwrst;
+   u8 per_min_fpwrst;
u8 flags;
 };
 
@@ -61,41 +61,41 @@ static struct powerdomain *mpu_pd, *core_pd, *per_pd, 
*cam_pd;
  */
 static struct omap3_idle_statedata omap3_idle_data[] = {
{
-   .mpu_state = PWRDM_POWER_ON,
-   .core_state = PWRDM_POWER_ON,
+   .mpu_fpwrst = PWRDM_FUNC_PWRST_ON,
+   .core_fpwrst = PWRDM_FUNC_PWRST_ON,
/* In C1 do not allow PER state lower than CORE state */
-   .per_min_state = PWRDM_POWER_ON,
+   .per_min_fpwrst = PWRDM_FUNC_PWRST_ON,
.flags = OMAP_CPUIDLE_CX_NO_CLKDM_IDLE,
},
{
-   .mpu_state = PWRDM_POWER_ON,
-   .core_state = PWRDM_POWER_ON,
-   .per_min_state = PWRDM_POWER_RET,
+   .mpu_fpwrst = PWRDM_FUNC_PWRST_ON,
+   .core_fpwrst = PWRDM_FUNC_PWRST_ON,
+   .per_min_fpwrst = PWRDM_FUNC_PWRST_CSWR,
},
{
-   .mpu_state = PWRDM_POWER_RET,
-   .core_state = PWRDM_POWER_ON,
-   .per_min_state = PWRDM_POWER_RET,
+   .mpu_fpwrst = PWRDM_FUNC_PWRST_CSWR,
+   .core_fpwrst = PWRDM_FUNC_PWRST_ON,
+   .per_min_fpwrst = PWRDM_FUNC_PWRST_CSWR,
},
{
-   .mpu_state = PWRDM_POWER_OFF,
-   .core_state = PWRDM_POWER_ON,
-   .per_min_state = PWRDM_POWER_RET,
+   .mpu_fpwrst = PWRDM_FUNC_PWRST_OFF,
+   .core_fpwrst = PWRDM_FUNC_PWRST_ON,
+   .per_min_fpwrst = PWRDM_FUNC_PWRST_CSWR,
},
{
-   .mpu_state = PWRDM_POWER_RET,
-   .core_state = PWRDM_POWER_RET,
-   .per_min_state = PWRDM_POWER_OFF,
+   .mpu_fpwrst = PWRDM_FUNC_PWRST_CSWR,
+   .core_fpwrst = PWRDM_FUNC_PWRST_CSWR,
+   .per_min_fpwrst = PWRDM_FUNC_PWRST_OFF,
},
{
-   .mpu_state = PWRDM_POWER_OFF,
-   .core_state = PWRDM_POWER_RET,
-   .per_min_state = PWRDM_POWER_OFF,
+   .mpu_fpwrst = PWRDM_FUNC_PWRST_OFF,
+   .core_fpwrst = PWRDM_FUNC_PWRST_CSWR,
+   .per_min_fpwrst = PWRDM_FUNC_PWRST_OFF,
},
{
-   .mpu_state = PWRDM_POWER_OFF,
-   .core_state = PWRDM_POWER_OFF,
-   .per_min_state = PWRDM_POWER_OFF,
+   .mpu_fpwrst = PWRDM_FUNC_PWRST_OFF,
+   .core_fpwrst = PWRDM_FUNC_PWRST_OFF,
+   .per_min_fpwrst = PWRDM_FUNC_PWRST_OFF,
},
 };
 
@@ -116,15 +116,15 @@ static int __omap3_enter_idle(struct cpuidle_device *dev,
if (cx->flags & OMAP_CPUIDLE_CX_NO_CLKDM_IDLE) {
clkdm_deny_idle(mpu_pd->pwrdm_clkdms[0]);
} else {
-   pwrdm_set_next_pwrst(mpu_pd, cx->mpu_state);
-   pwrdm_set_next_pwrst(core_pd, cx->core_state);
+   pwrdm_set_next_fpwrst(mpu_pd, cx->mpu_fpwrst);
+   pwrdm_set_next_fpwrst(core_pd, cx->core_fpwrst);
}
 
/*
 * Call idle CPU PM enter notifier chain so that
 * VFP context is saved.
 */
-   if (cx->mpu_state == PWRDM_POWER_OFF)
+   if (cx->mpu_fpwrst == PWRDM_FUNC_PWRST_OFF)
cpu_pm_enter();
 
/* Execute ARM wfi */
@@ -134,8 +134,8 @@ static int __omap3_enter_idle(struct cpuidle_device *dev,
 * Call idle CPU PM enter notifier chain to restore
 * VFP context.
 */
-   if (cx->mpu_state == PWRDM_POWER_

[PATCH 06/12] ARM: OMAP44xx: PM: convert to use the functional power states API

2012-12-09 Thread Paul Walmsley
From: Jean Pihet 

Use the functional power states as the API to control power
domains:
- use the PWRDM_FUNC_PWRST_* and PWRDM_LOGIC_MEM_PWRST_*
  macros for the power states and logic settings,
- the function pwrdm_set_next_fpwrst, which controls
  the power domains next power and logic settings, shall
  be used instead of pwrdm_set_next_pwrst to program the
  power domains next states,
- the function pwrdm_set_fpwrst, which programs the power
  domains power and logic settings, shall be used instead
  of omap_set_pwrdm_state.

Signed-off-by: Jean Pihet 
[p...@pwsan.com: split the original patch into OMAP2/3/4 variants;
 warn if sets fail; various other changes]
Signed-off-by: Paul Walmsley 
---
 arch/arm/mach-omap2/common.h  |7 +--
 arch/arm/mach-omap2/cpuidle44xx.c |   32 +
 arch/arm/mach-omap2/omap-hotplug.c|2 -
 arch/arm/mach-omap2/omap-mpuss-lowpower.c |   69 +
 arch/arm/mach-omap2/pm44xx.c  |   42 +-
 5 files changed, 79 insertions(+), 73 deletions(-)

diff --git a/arch/arm/mach-omap2/common.h b/arch/arm/mach-omap2/common.h
index c57eeea..5ad846a 100644
--- a/arch/arm/mach-omap2/common.h
+++ b/arch/arm/mach-omap2/common.h
@@ -235,14 +235,13 @@ extern void omap5_secondary_startup(void);
 
 #if defined(CONFIG_SMP) && defined(CONFIG_PM)
 extern int omap4_mpuss_init(void);
-extern int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state);
+extern int omap4_mpuss_enter_lowpower(unsigned int cpu, u8 fpwrst);
 extern int omap4_finish_suspend(unsigned long cpu_state);
 extern void omap4_cpu_resume(void);
-extern int omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state);
+extern int omap4_mpuss_hotplug_cpu(unsigned int cpu, u8 fpwrst);
 extern u32 omap4_mpuss_read_prev_context_state(void);
 #else
-static inline int omap4_enter_lowpower(unsigned int cpu,
-   unsigned int power_state)
+static inline int omap4_mpuss_enter_lowpower(unsigned int cpu, u8 fpwrst)
 {
cpu_do_idle();
return 0;
diff --git a/arch/arm/mach-omap2/cpuidle44xx.c 
b/arch/arm/mach-omap2/cpuidle44xx.c
index d639aef..2cb5332 100644
--- a/arch/arm/mach-omap2/cpuidle44xx.c
+++ b/arch/arm/mach-omap2/cpuidle44xx.c
@@ -25,26 +25,22 @@
 
 /* Machine specific information */
 struct omap4_idle_statedata {
-   u32 cpu_state;
-   u32 mpu_logic_state;
-   u32 mpu_state;
+   u8 cpu_pwrst;
+   u8 mpu_pwrst;
 };
 
 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_pwrst = PWRDM_FUNC_PWRST_ON,
+   .mpu_pwrst = PWRDM_FUNC_PWRST_ON,
},
{
-   .cpu_state = PWRDM_POWER_OFF,
-   .mpu_state = PWRDM_POWER_RET,
-   .mpu_logic_state = PWRDM_POWER_RET,
+   .cpu_pwrst = PWRDM_FUNC_PWRST_OFF,
+   .mpu_pwrst = PWRDM_FUNC_PWRST_CSWR,
},
{
-   .cpu_state = PWRDM_POWER_OFF,
-   .mpu_state = PWRDM_POWER_RET,
-   .mpu_logic_state = PWRDM_POWER_OFF,
+   .cpu_pwrst = PWRDM_FUNC_PWRST_OFF,
+   .mpu_pwrst = PWRDM_FUNC_PWRST_OSWR,
},
 };
 
@@ -93,7 +89,7 @@ static int omap4_enter_idle_coupled(struct cpuidle_device 
*dev,
 * out of coherency and in OFF mode.
 */
if (dev->cpu == 0 && cpumask_test_cpu(1, cpu_online_mask)) {
-   while (pwrdm_read_pwrst(cpu_pd[1]) != PWRDM_POWER_OFF) {
+   while (pwrdm_read_fpwrst(cpu_pd[1]) != PWRDM_FUNC_PWRST_OFF) {
cpu_relax();
 
/*
@@ -118,19 +114,17 @@ static int omap4_enter_idle_coupled(struct cpuidle_device 
*dev,
cpu_pm_enter();
 
if (dev->cpu == 0) {
-   pwrdm_set_logic_retst(mpu_pd, cx->mpu_logic_state);
-   omap_set_pwrdm_state(mpu_pd, cx->mpu_state);
+   WARN_ON(pwrdm_set_fpwrst(mpu_pd, cx->mpu_pwrst));
 
/*
 * Call idle CPU cluster PM enter notifier chain
 * to save GIC and wakeupgen context.
 */
-   if ((cx->mpu_state == PWRDM_POWER_RET) &&
-   (cx->mpu_logic_state == PWRDM_POWER_OFF))
-   cpu_cluster_pm_enter();
+   if (cx->mpu_pwrst == PWRDM_FUNC_PWRST_OSWR)
+   cpu_cluster_pm_enter();
}
 
-   omap4_enter_lowpower(dev->cpu, cx->cpu_state);
+   omap4_mpuss_enter_lowpower(dev->cpu, cx->cpu_pwrst);
cpu_done[dev->cpu] = true;
 
/* Wakeup CPU1 only if it is not offlined */
diff --git a/arch/arm/mach-omap2/omap-hotplug.c 
b/arch/arm/mach-omap2/omap-hotplug.c
index e712d17..d38b12d 100644
--- a/arch/arm/mach-omap2/omap-hotplug.c
+++ b/arch/arm/mach-omap2/omap-hotplug.c
@@ -53,7 +

[PATCH 12/12] ARM: OMAP2+: powerdomain: assume memory bank power states follow powerdomain

2012-12-09 Thread Paul Walmsley
Assume that the memory bank power states follow the powerdomain power
states.  The motivations are to reduce the amount of powerdomain code,
decrease the execution time of the powerdomain state switch code, and
simplify the power state debug.

This assumption is true for the currently-implemented functional power
states.  If it ceases to be true, the memory bank power states should
be controlled via the functional power states, rather than controlled
via low-level functions.

For the moment, the underlying implementation code in
mach-omap2/prm*.c has been preserved, although some of that code may
be removable too.

Signed-off-by: Paul Walmsley 
Cc: Tero Kristo 
Cc: Rajendra Nayak 
Cc: Kevin Hilman 
---
 arch/arm/mach-omap2/pm-debug.c|4 -
 arch/arm/mach-omap2/pm24xx.c  |9 -
 arch/arm/mach-omap2/powerdomain.c |  277 +++--
 arch/arm/mach-omap2/powerdomain.h |9 -
 4 files changed, 79 insertions(+), 220 deletions(-)

diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c
index 72cf9e0..03da2e3 100644
--- a/arch/arm/mach-omap2/pm-debug.c
+++ b/arch/arm/mach-omap2/pm-debug.c
@@ -108,10 +108,6 @@ static int pwrdm_dbg_show_counter(struct powerdomain 
*pwrdm, void *user)
seq_printf(s, ",%s:%d", pwrdm_convert_fpwrst_to_name(i),
   pwrdm->fpwrst_counter[i - PWRDM_FPWRST_OFFSET]);
 
-   for (i = 0; i < pwrdm->banks; i++)
-   seq_printf(s, ",RET-MEMBANK%d-OFF:%d", i + 1,
-   pwrdm->ret_mem_off_counter[i]);
-
seq_printf(s, "\n");
 
return 0;
diff --git a/arch/arm/mach-omap2/pm24xx.c b/arch/arm/mach-omap2/pm24xx.c
index 29abb63..99c16c2 100644
--- a/arch/arm/mach-omap2/pm24xx.c
+++ b/arch/arm/mach-omap2/pm24xx.c
@@ -230,7 +230,6 @@ out:
 
 static void __init prcm_setup_regs(void)
 {
-   int i, num_mem_banks;
struct powerdomain *pwrdm;
 
/*
@@ -240,14 +239,6 @@ static void __init prcm_setup_regs(void)
omap2_prm_write_mod_reg(OMAP24XX_AUTOIDLE_MASK, OCP_MOD,
  OMAP2_PRCM_SYSCONFIG_OFFSET);
 
-   /*
-* Set CORE powerdomain memory banks to retain their contents
-* during RETENTION
-*/
-   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);
-
/* Force-power down DSP, GFX powerdomains */
 
pwrdm = clkdm_get_pwrdm(dsp_clkdm);
diff --git a/arch/arm/mach-omap2/powerdomain.c 
b/arch/arm/mach-omap2/powerdomain.c
index a70e3f6..7a32fcc 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -118,9 +118,6 @@ static int _pwrdm_register(struct powerdomain *pwrdm)
for (i = 0; i < PWRDM_FPWRSTS_COUNT; i++)
pwrdm->fpwrst_counter[i] = 0;
 
-   for (i = 0; i < pwrdm->banks; i++)
-   pwrdm->ret_mem_off_counter[i] = 0;
-
arch_pwrdm->pwrdm_wait_transition(pwrdm);
pwrdm->fpwrst = pwrdm_read_fpwrst(pwrdm);
pwrdm->fpwrst_counter[pwrdm->fpwrst - PWRDM_FPWRST_OFFSET] = 1;
@@ -364,7 +361,6 @@ static int _pwrdm_read_next_fpwrst(struct powerdomain 
*pwrdm)
if (next_logic < 0)
return next_logic;
}
-
ret = _pwrdm_pwrst_to_fpwrst(pwrdm, next_pwrst, next_logic, &fpwrst);
 
return (ret) ? ret : fpwrst;
@@ -437,12 +433,86 @@ static int _pwrdm_read_prev_fpwrst(struct powerdomain 
*pwrdm)
return (ret) ? ret : fpwrst;
 }
 
+/**
+ * _pwrdm_set_mem_onst - set memory power state while powerdomain ON
+ * @pwrdm: struct powerdomain * to set
+ * @bank: memory bank number to set (0-3)
+ * @pwrst: one of the PWRDM_POWER_* 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
+ * 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
+ * success.
+ */
+static int _pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, u8 pwrst)
+{
+   int ret = -EINVAL;
+
+   if (!pwrdm)
+   return -EINVAL;
+
+   if (pwrdm->banks < (bank + 1))
+   return -EEXIST;
+
+   if (!(pwrdm->pwrsts_mem_on[bank] & (1 << pwrst)))
+   return -EINVAL;
+
+   pr_debug("powerdomain: %s: setting next memory powerstate for bank %0x 
while pwrdm-ON to %0x\n",
+pwrdm->name, bank, pwrst);
+
+   if (arch_pwrdm && arch_pwrdm->pwrdm_set_mem_onst)
+   ret = arch_pwrdm->pwrdm_set_mem_onst(pwrdm, bank, pwrst);
+
+   return ret;
+}
+
+/**
+ * _pwrdm_set_mem_retst - set memory power state while powerdoma

[PATCH 09/12] ARM: OMAP2+: powerdomain: add ability to test for supported power states

2012-12-09 Thread Paul Walmsley
Add pwrdm_supports_fpwrst(), intended for use by the PM code to avoid
attempting to program a powerdomain to a power state that it doesn't
support.

Signed-off-by: Paul Walmsley 
---
 arch/arm/mach-omap2/powerdomain.c |   33 +
 arch/arm/mach-omap2/powerdomain.h |1 +
 2 files changed, 34 insertions(+)

diff --git a/arch/arm/mach-omap2/powerdomain.c 
b/arch/arm/mach-omap2/powerdomain.c
index 86fe84c..6ba79df 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -1495,3 +1495,36 @@ int pwrdm_read_prev_fpwrst(struct powerdomain *pwrdm)
return ret;
 }
 
+/**
+ * pwrdm_supports_fpwrst - does the powerdomain @pwrdm support the @fpwrst 
power
+ * state?
+ * @pwrdm: struct powerdomain * pointing to a powerdomain to test
+ * @fpwrst: functional power state
+ *
+ * Returns true if the powerdomain pointed to by @pwrdm can enter the
+ * functional power state @fpwrst, or false if not.
+ */
+bool pwrdm_supports_fpwrst(struct powerdomain *pwrdm, u8 fpwrst)
+{
+   u8 pwrst, logic;
+   int ret;
+
+   if (!pwrdm || IS_ERR(pwrdm))
+   return false;
+
+   ret = _pwrdm_fpwrst_to_pwrst(pwrdm, fpwrst, &pwrst, &logic);
+   if (ret)
+   return false;
+
+   pr_debug("%s: pwrdm %s: set fpwrst %0x\n", __func__, pwrdm->name,
+fpwrst);
+
+   if (pwrdm->pwrsts_logic_ret && pwrst == PWRDM_POWER_RET &&
+   !(pwrdm->pwrsts_logic_ret & (1 << logic)))
+   return false;
+
+   if (!(pwrdm->pwrsts & (1 << pwrst)))
+   return false;
+
+   return true;
+}
diff --git a/arch/arm/mach-omap2/powerdomain.h 
b/arch/arm/mach-omap2/powerdomain.h
index aa1c9ae..52be8cd 100644
--- a/arch/arm/mach-omap2/powerdomain.h
+++ b/arch/arm/mach-omap2/powerdomain.h
@@ -260,6 +260,7 @@ extern int pwrdm_set_fpwrst(struct powerdomain *pwrdm,
enum pwrdm_func_state fpwrst);
 extern int pwrdm_read_fpwrst(struct powerdomain *pwrdm);
 extern int pwrdm_read_prev_fpwrst(struct powerdomain *pwrdm);
+extern bool pwrdm_supports_fpwrst(struct powerdomain *pwrdm, u8 fpwrst);
 
 extern void omap242x_powerdomains_init(void);
 extern void omap243x_powerdomains_init(void);


--
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 11/12] ARM: OMAP2+: powerdomain: program memory bank next-power-state upon init

2012-12-09 Thread Paul Walmsley
During powerdomain init, we were previously programming a reasonable
default for the powerdomain and logic next-power-state fields, but not
touching the memory bank next-power-state fields.  To ensure that the
previous OS or bootloader didn't leave the system in a bad state, program
the memory bank next-power-state bitfields to reasonable defaults.

Signed-off-by: Paul Walmsley 
---
 arch/arm/mach-omap2/powerdomain.c |   21 ++---
 1 file changed, 14 insertions(+), 7 deletions(-)

diff --git a/arch/arm/mach-omap2/powerdomain.c 
b/arch/arm/mach-omap2/powerdomain.c
index fdeabbf..a70e3f6 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -563,21 +563,28 @@ int pwrdm_register_pwrdms(struct powerdomain **ps)
  *
  * Do whatever is necessary to initialize registered powerdomains and
  * powerdomain code.  Currently, this programs the next power state
- * for each powerdomain to ON.  This prevents powerdomains from
- * unexpectedly losing context or entering high wakeup latency modes
- * with non-power-management-enabled kernels.  Must be called after
- * pwrdm_register_pwrdms().  Returns -EACCES if called before
- * pwrdm_register_pwrdms(), or 0 upon success.
+ * for each powerdomain to ON, and programs the memory bank power
+ * states to follow the powerdomain power states.  This prevents
+ * powerdomains from unexpectedly losing context or entering high
+ * wakeup latency modes with non-power-management-enabled kernels.
+ * Must be called after pwrdm_register_pwrdms().  Returns -EACCES if
+ * called before pwrdm_register_pwrdms(), or 0 upon success.
  */
 int pwrdm_complete_init(void)
 {
struct powerdomain *temp_p;
+   int i;
 
if (list_empty(&pwrdm_list))
return -EACCES;
 
-   list_for_each_entry(temp_p, &pwrdm_list, node)
-   pwrdm_set_next_fpwrst(temp_p, PWRDM_FUNC_PWRST_ON);
+   list_for_each_entry(temp_p, &pwrdm_list, node) {
+   for (i = 0; i < temp_p->banks; i++) {
+   pwrdm_set_mem_onst(temp_p, i, PWRDM_POWER_ON);
+   pwrdm_set_mem_retst(temp_p, i, PWRDM_POWER_RET);
+   }
+   WARN_ON(pwrdm_set_next_fpwrst(temp_p, PWRDM_FUNC_PWRST_ON));
+   }
 
return 0;
 }


--
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 10/12] ARM: OMAP2+: powerdomain/PM: only program supported power states

2012-12-09 Thread Paul Walmsley
Previously the PM code attempted to program power states that the
underlying powerdomain didn't support.  Change this to only program
power states that are supported by the hardware.

In the future, the PM code should be changed further to program
explicit lists of powerdomain power states that are valid for each
chip (and supported by the underlying software).  Also the powerdomain
code should return errors when PM code tries to program an unsupported
power state, rather than simply ignoring the requrest.

Signed-off-by: Paul Walmsley 
Cc: Kevin Hilman 
---
 arch/arm/mach-omap2/pm34xx.c  |   34 +
 arch/arm/mach-omap2/pm44xx.c  |9 -
 arch/arm/mach-omap2/powerdomain.c |   74 ++---
 3 files changed, 52 insertions(+), 65 deletions(-)

diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 8aac26e..c4d4154 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -395,7 +395,14 @@ restore:
/* Restore next_pwrsts */
list_for_each_entry(pwrst, &pwrst_list, node) {
prev_fpwrst = pwrdm_read_prev_fpwrst(pwrst->pwrdm);
-   if (prev_fpwrst > pwrst->next_fpwrst) {
+   /*
+* The SGX powerdomain will report its previous state as
+* INACTIVE when it's been programmed to ON.  This seems to
+* be the only OMAP3 powerdomain that does this.
+*/
+   if (prev_fpwrst == PWRDM_FUNC_PWRST_INACTIVE)
+   prev_fpwrst = PWRDM_FUNC_PWRST_ON;
+   if (prev_fpwrst != pwrst->next_fpwrst) {
pr_info("Powerdomain %s didn't enter target state %s - 
entered state %s instead\n",
pwrst->pwrdm->name,

pwrdm_convert_fpwrst_to_name(pwrst->next_fpwrst),
@@ -575,6 +582,10 @@ void omap3_pm_off_mode_enable(int enable)
 
fpwrst = (enable) ? PWRDM_FUNC_PWRST_OFF : PWRDM_FUNC_PWRST_CSWR;
 
+   /*
+* XXX This should be replaced by explicit lists of
+* powerdomains with specific powerstates to set
+*/
list_for_each_entry(pwrst, &pwrst_list, node) {
if (IS_PM34XX_ERRATUM(PM_SDRC_WAKEUP_ERRATUM_i583) &&
pwrst->pwrdm == core_pwrdm &&
@@ -584,6 +595,12 @@ void omap3_pm_off_mode_enable(int enable)
__func__);
} else {
pwrst->next_fpwrst = fpwrst;
+   if (!pwrdm_supports_fpwrst(pwrst->pwrdm,
+  pwrst->next_fpwrst))
+   pwrst->next_fpwrst = PWRDM_FUNC_PWRST_CSWR;
+   if (!pwrdm_supports_fpwrst(pwrst->pwrdm,
+  pwrst->next_fpwrst))
+   pwrst->next_fpwrst = PWRDM_FUNC_PWRST_ON;
}
WARN_ON(pwrdm_set_fpwrst(pwrst->pwrdm, pwrst->next_fpwrst));
}
@@ -603,9 +620,17 @@ int omap3_pm_set_suspend_state(struct powerdomain *pwrdm, 
u8 fpwrst)
 {
struct power_state *pwrst;
 
+   /*
+* XXX This should be replaced by per-powerdomain suspend
+* power state files
+*/
list_for_each_entry(pwrst, &pwrst_list, node) {
if (pwrst->pwrdm == pwrdm) {
pwrst->next_fpwrst = fpwrst;
+   if (!pwrdm_supports_fpwrst(pwrdm, pwrst->next_fpwrst))
+   pwrst->next_fpwrst = PWRDM_FUNC_PWRST_CSWR;
+   if (!pwrdm_supports_fpwrst(pwrdm, pwrst->next_fpwrst))
+   pwrst->next_fpwrst = PWRDM_FUNC_PWRST_ON;
return 0;
}
}
@@ -623,7 +648,14 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, 
void *unused)
if (!pwrst)
return -ENOMEM;
pwrst->pwrdm = pwrdm;
+
+   /*
+* XXX This should be replaced by explicit lists of
+* powerdomains with specific powerstates to set
+*/
pwrst->next_fpwrst = PWRDM_FUNC_PWRST_CSWR;
+   if (!pwrdm_supports_fpwrst(pwrdm, pwrst->next_fpwrst))
+   pwrst->next_fpwrst = PWRDM_FUNC_PWRST_ON;
list_add(&pwrst->node, &pwrst_list);
 
if (pwrdm_has_hdwr_sar(pwrdm))
diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c
index 595f84e..5db9a91 100644
--- a/arch/arm/mach-omap2/pm44xx.c
+++ b/arch/arm/mach-omap2/pm44xx.c
@@ -67,8 +67,7 @@ static int omap4_pm_suspend(void)
/* Restore next powerdomain state */
list_for_each_entry(pwrst, &pwrst_list, node) {
prev_fpwrst = pwrdm_read_prev_fpwrst(pwrst->pwrdm);
-   /* XXX test below should be != */
-   if (prev_fpwrst > pwrst->next_fpwrst) {
+   if (prev_fpwrst != pwrst->next_fpwrst) {

[PATCH 08/12] ARM: OMAP2+: powerdomain: drop many low-level powerdomain funcs

2012-12-09 Thread Paul Walmsley
The powerdomain code that exported the ability to read or change the
previous, current, or next powerdomain or logic power states can now
be removed.  All this is controlled via the powerdomain functional
power state interface now.

Signed-off-by: Paul Walmsley 
---
 arch/arm/mach-omap2/powerdomain.c |  270 +++--
 arch/arm/mach-omap2/powerdomain.h |9 -
 2 files changed, 21 insertions(+), 258 deletions(-)

diff --git a/arch/arm/mach-omap2/powerdomain.c 
b/arch/arm/mach-omap2/powerdomain.c
index 3e2e263..86fe84c 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -253,9 +253,6 @@ static int _match_pwrst(u32 pwrsts, int pwrst, int min, int 
max)
 static int _pwrdm_fpwrst_to_pwrst(struct powerdomain *pwrdm, u8 fpwrst,
  u8 *pwrdm_pwrst, u8 *logic_retst)
 {
-   if (!pwrdm || !pwrdm_pwrst || !logic_retst)
-   return -EINVAL;
-
switch (fpwrst) {
case PWRDM_FUNC_PWRST_ON:
*pwrdm_pwrst = PWRDM_POWER_ON;
@@ -317,9 +314,6 @@ static int _pwrdm_fpwrst_to_pwrst(struct powerdomain 
*pwrdm, u8 fpwrst,
 static int _pwrdm_pwrst_to_fpwrst(struct powerdomain *pwrdm, u8 pwrst, u8 
logic,
  u8 *fpwrst)
 {
-   if (!pwrdm || !fpwrst)
-   return -EINVAL;
-
switch (pwrst) {
case PWRDM_POWER_ON:
*fpwrst = PWRDM_FUNC_PWRST_ON;
@@ -370,16 +364,27 @@ static int _set_logic_retst_and_pwrdm_pwrst(struct 
powerdomain *pwrdm,
if (!_pwrdm_pwrst_is_controllable(pwrdm))
return 0;
 
+   if (!arch_pwrdm || !arch_pwrdm->pwrdm_set_next_pwrst)
+   return -EINVAL;
+
+   if (!(pwrdm->pwrsts & (1 << pwrst)))
+   return -EINVAL;
+
if (pwrdm->pwrsts_logic_ret && pwrst == PWRDM_POWER_RET) {
-   ret = pwrdm_set_logic_retst(pwrdm, logic);
-   if (ret) {
-   pr_err("%s: unable to set logic state %0x of 
powerdomain: %s\n",
-  __func__, logic, pwrdm->name);
-   return ret;
+   if (!(pwrdm->pwrsts_logic_ret & (1 << logic)))
+   return -EINVAL;
+
+   if (arch_pwrdm->pwrdm_set_logic_retst) {
+   ret = arch_pwrdm->pwrdm_set_logic_retst(pwrdm, logic);
+   if (ret) {
+   pr_err("%s: unable to set logic state %0x of 
powerdomain: %s\n",
+  __func__, logic, pwrdm->name);
+   return ret;
+   }
}
}
 
-   ret = pwrdm_set_next_pwrst(pwrdm, pwrst);
+   ret = arch_pwrdm->pwrdm_set_next_pwrst(pwrdm, pwrst);
if (ret)
pr_err("%s: unable to set power state %0x of powerdomain: %s\n",
   __func__, pwrst, pwrdm->name);
@@ -847,133 +852,6 @@ int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm)
 }
 
 /**
- * pwrdm_set_next_pwrst - set next powerdomain power state
- * @pwrdm: struct powerdomain * to set
- * @pwrst: one of the PWRDM_POWER_* macros
- *
- * Set the powerdomain @pwrdm's next power state to @pwrst.  The powerdomain
- * may not enter this state immediately if the preconditions for this state
- * have not been satisfied.  Returns -EINVAL if the powerdomain pointer is
- * null or if the power state is invalid for the powerdomin, or returns 0
- * upon success.
- */
-int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
-{
-   int ret = -EINVAL;
-
-   if (!pwrdm)
-   return -EINVAL;
-
-   if (!(pwrdm->pwrsts & (1 << pwrst)))
-   return -EINVAL;
-
-   pr_debug("powerdomain: %s: setting next powerstate to %0x\n",
-pwrdm->name, pwrst);
-
-   if (arch_pwrdm && arch_pwrdm->pwrdm_set_next_pwrst)
-   ret = arch_pwrdm->pwrdm_set_next_pwrst(pwrdm, pwrst);
-
-   return ret;
-}
-
-/**
- * pwrdm_read_next_pwrst - get next powerdomain power state
- * @pwrdm: struct powerdomain * to get power state
- *
- * Return the powerdomain @pwrdm's next power state.  Returns -EINVAL
- * if the powerdomain pointer is null or returns the next power state
- * upon success.
- */
-int pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
-{
-   int ret = -EINVAL;
-
-   if (!pwrdm)
-   return -EINVAL;
-
-   if (arch_pwrdm && arch_pwrdm->pwrdm_read_next_pwrst)
-   ret = arch_pwrdm->pwrdm_read_next_pwrst(pwrdm);
-
-   return ret;
-}
-
-/**
- * pwrdm_read_pwrst - get current powerdomain power state
- * @pwrdm: struct powerdomain * to get power state
- *
- * Return the powerdomain @pwrdm's current power state.Returns -EINVAL
- * if the powerdomain pointer is null or returns the current power state
- * upon success. Note that if the power domain only supports the ON state
- * then just return ON as the current state.
- */
-int pwrdm_

[PATCH 04/12] ARM: OMAP2xxx: PM: convert to use the functional power states API

2012-12-09 Thread Paul Walmsley
From: Jean Pihet 

Use the functional power states as the API to control power domains:

- use the PWRDM_FUNC_PWRST_* macros for the power states and logic
  settings,

- the function pwrdm_set_next_fpwrst(), which controls the power domains
  next power and logic settings, shall be used instead of
  pwrdm_set_next_pwrst() to program the power domains next states,

- the function pwrdm_set_fpwrst(), which programs the power domains
  power and logic settings, shall be used instead of
  omap_set_pwrdm_state().

Signed-off-by: Jean Pihet 
[p...@pwsan.com: split the original patch into OMAP2/3/4 variants; fix
 commit message; update the power state programming to make sense;
 warn if sets fail]
Signed-off-by: Paul Walmsley 
---
 arch/arm/mach-omap2/pm24xx.c |   24 ++--
 1 file changed, 10 insertions(+), 14 deletions(-)

diff --git a/arch/arm/mach-omap2/pm24xx.c b/arch/arm/mach-omap2/pm24xx.c
index 4c06d8a..29abb63 100644
--- a/arch/arm/mach-omap2/pm24xx.c
+++ b/arch/arm/mach-omap2/pm24xx.c
@@ -89,8 +89,8 @@ static int omap2_enter_full_retention(void)
omap2_prm_write_mod_reg(0x, CORE_MOD, OMAP24XX_PM_WKST2);
omap2_prm_write_mod_reg(0x, WKUP_MOD, PM_WKST);
 
-   pwrdm_set_next_pwrst(core_pwrdm, PWRDM_POWER_RET);
-   pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_RET);
+   WARN_ON(pwrdm_set_next_fpwrst(core_pwrdm, PWRDM_FUNC_PWRST_CSWR));
+   WARN_ON(pwrdm_set_next_fpwrst(mpu_pwrdm, PWRDM_FUNC_PWRST_CSWR));
 
/* Workaround to kill USB */
l = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0) | OMAP24XX_USBSTANDBYCTRL;
@@ -132,8 +132,8 @@ no_sleep:
/* Mask future PRCM-to-MPU interrupts */
omap2_prm_write_mod_reg(0x0, OCP_MOD, OMAP2_PRCM_IRQSTATUS_MPU_OFFSET);
 
-   pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_ON);
-   pwrdm_set_next_pwrst(core_pwrdm, PWRDM_POWER_ON);
+   WARN_ON(pwrdm_set_next_fpwrst(mpu_pwrdm, PWRDM_FUNC_PWRST_ON));
+   WARN_ON(pwrdm_set_next_fpwrst(core_pwrdm, PWRDM_FUNC_PWRST_ON));
 
return 0;
 }
@@ -184,16 +184,16 @@ static void omap2_enter_mpu_retention(void)
omap2_prm_write_mod_reg(0x, WKUP_MOD, PM_WKST);
 
/* Try to enter MPU retention */
-   pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_RET);
-
+   WARN_ON(pwrdm_set_next_fpwrst(mpu_pwrdm,
+ PWRDM_FUNC_PWRST_CSWR));
} else {
/* Block MPU retention */
-   pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_ON);
+   WARN_ON(pwrdm_set_next_fpwrst(mpu_pwrdm, PWRDM_FUNC_PWRST_ON));
}
 
omap2_sram_idle();
 
-   pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_ON);
+   WARN_ON(pwrdm_set_next_fpwrst(mpu_pwrdm, PWRDM_FUNC_PWRST_ON));
 }
 
 static int omap2_can_sleep(void)
@@ -248,17 +248,13 @@ static void __init prcm_setup_regs(void)
for (i = 0; i < num_mem_banks; i++)
pwrdm_set_mem_retst(core_pwrdm, i, PWRDM_POWER_RET);
 
-   pwrdm_set_logic_retst(core_pwrdm, PWRDM_POWER_RET);
-
-   pwrdm_set_logic_retst(mpu_pwrdm, PWRDM_POWER_RET);
-
/* Force-power down DSP, GFX powerdomains */
 
pwrdm = clkdm_get_pwrdm(dsp_clkdm);
-   pwrdm_set_next_pwrst(pwrdm, PWRDM_POWER_OFF);
+   WARN_ON(pwrdm_set_next_fpwrst(pwrdm, PWRDM_FUNC_PWRST_OFF));
 
pwrdm = clkdm_get_pwrdm(gfx_clkdm);
-   pwrdm_set_next_pwrst(pwrdm, PWRDM_POWER_OFF);
+   WARN_ON(pwrdm_set_next_fpwrst(pwrdm, PWRDM_FUNC_PWRST_OFF));
 
/* Enable hardware-supervised idle for all clkdms */
clkdm_for_each(omap_pm_clkdms_setup, NULL);


--
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/12] ARM: OMAP2+: PM: use power domain functional state in stats counters

2012-12-09 Thread Paul Walmsley
From: 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 
[p...@pwsan.com: use PWRDM_FPWRSTS_COUNT due to functional power state offset;
 use powerdomain.c fn to convert func pwrsts to names; rename 'state' to
 'fpwrst' to indicate use of func pwrsts; convert remaining users of the
 non-func pwrst API; add some kerneldoc]
Signed-off-by: Paul Walmsley 
---
 arch/arm/mach-omap2/pm-debug.c|   42 -
 arch/arm/mach-omap2/powerdomain.c |  167 ++---
 arch/arm/mach-omap2/powerdomain.h |   17 ++--
 3 files changed, 108 insertions(+), 118 deletions(-)

diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c
index 806a06b..72cf9e0 100644
--- a/arch/arm/mach-omap2/pm-debug.c
+++ b/arch/arm/mach-omap2/pm-debug.c
@@ -53,13 +53,6 @@ enum {
DEBUG_FILE_TIMERS,
 };
 
-static const char pwrdm_state_names[][PWRDM_MAX_PWRSTS] = {
-   "OFF",
-   "RET",
-   "INA",
-   "ON"
-};
-
 void pm_dbg_update_time(struct powerdomain *pwrdm, int prev)
 {
s64 t;
@@ -70,7 +63,7 @@ void pm_dbg_update_time(struct powerdomain *pwrdm, int prev)
/* Update timer for previous state */
t = sched_clock();
 
-   pwrdm->state_timer[prev] += t - pwrdm->timer;
+   pwrdm->fpwrst_timer[prev - PWRDM_FPWRST_OFFSET] += t - pwrdm->timer;
 
pwrdm->timer = t;
 }
@@ -79,6 +72,7 @@ static int clkdm_dbg_show_counter(struct clockdomain *clkdm, 
void *user)
 {
struct seq_file *s = (struct seq_file *)user;
 
+   /* XXX This needs to be implemented in a better way */
if (strcmp(clkdm->name, "emu_clkdm") == 0 ||
strcmp(clkdm->name, "wkup_clkdm") == 0 ||
strncmp(clkdm->name, "dpll", 4) == 0)
@@ -94,23 +88,26 @@ static int pwrdm_dbg_show_counter(struct powerdomain 
*pwrdm, void *user)
 {
struct seq_file *s = (struct seq_file *)user;
int i;
+   int curr_fpwrst;
 
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_pwrst(pwrdm))
-   printk(KERN_ERR "pwrdm state mismatch(%s) %d != %d\n",
-   pwrdm->name, pwrdm->state, pwrdm_read_pwrst(pwrdm));
+   curr_fpwrst = pwrdm_read_fpwrst(pwrdm);
+   if (pwrdm->fpwrst != curr_fpwrst)
+   pr_err("pwrdm state mismatch(%s) %s != %s\n",
+  pwrdm->name,
+  pwrdm_convert_fpwrst_to_name(pwrdm->fpwrst),
+  pwrdm_convert_fpwrst_to_name(curr_fpwrst));
 
seq_printf(s, "%s (%s)", pwrdm->name,
-   pwrdm_state_names[pwrdm->state]);
-   for (i = 0; i < PWRDM_MAX_PWRSTS; i++)
-   seq_printf(s, ",%s:%d", pwrdm_state_names[i],
-   pwrdm->state_counter[i]);
+  pwrdm_convert_fpwrst_to_name(pwrdm->fpwrst));
+   for (i = PWRDM_FPWRST_OFFSET; i < PWRDM_MAX_FUNC_PWRSTS; i++)
+   seq_printf(s, ",%s:%d", pwrdm_convert_fpwrst_to_name(i),
+  pwrdm->fpwrst_counter[i - PWRDM_FPWRST_OFFSET]);
 
-   seq_printf(s, ",RET-LOGIC-OFF:%d", pwrdm->ret_logic_off_counter);
for (i = 0; i < pwrdm->banks; i++)
seq_printf(s, ",RET-MEMBANK%d-OFF:%d", i + 1,
pwrdm->ret_mem_off_counter[i]);
@@ -133,11 +130,12 @@ static int pwrdm_dbg_show_timer(struct powerdomain 
*pwrdm, void *user)
pwrdm_state_switch(pwrdm);
 
seq_printf(s, "%s (%s)", pwrdm->name,
-   pwrdm_state_names[pwrdm->state]);
+  pwrdm_convert_fpwrst_to_name(pwrdm->fpwrst));
 
-   for (i = 0; i < 4; i++)
-   seq_printf(s, ",%s:%lld", pwrdm_state_names[i],
-   pwrdm->state_timer[i]);
+   for (i = 0; i < PWRDM_FPWRSTS_COUNT; i++)
+   seq_printf(s, ",%s:%lld",
+  pwrdm_convert_fpwrst_to_name(i + 
PWRDM_FPWRST_OFFSET),
+  pwrdm->fpwrst_timer[i]);
 
seq_printf(s, "\n");
return 0;
@@ -209,8 +207,8 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, 
void *dir)
 
t = sched_clock();
 
-   for (i = 0; i < 4; i++)
-   pwrdm->state_timer[i] = 0;
+   for (i = 0; i < PWRDM_FPWRSTS_COUNT; i++)
+   pwrdm->fpwrst_timer[i] = 0;
 
pwrdm->timer = t;
 
diff --git a/arch/arm/mach-omap2/powerdomain.c 
b/arch/arm/mach-omap2/powerdomain.c
index 2c732b6..3e2e263 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -115,97 +115,16 @@ static int _pwrdm_register(struct powerdom

[PATCH 02/12] ARM: OMAP2+: PM: introduce power domains functional states

2012-12-09 Thread Paul Walmsley
From: Jean Pihet 

Introduce the functional states for power domains, which include
the power states and the logic states.
This patch provides the API functions to set and read the power
domains functional state and internal functions to convert between
the functional (i.e. logical) and the internal (or registers) values.

In the new API only the functions pwrdm_set_next_fpwrst() and
pwrdm_set_fpwrst() shall be used to change a power domain target
state, along with the associated PWRDM_FUNC_* macros as the state
parameters.

Note about the power domains allowed states:
Power domains have varied capabilities, as defined by the value of
the pwrsts and pwrsts_logic_ret fields of the powerdomain struct.
When reading or setting a low power state such as OFF/RET, a specific
requested state may not be supported on the given power domain.
In the states conversion functions a power or logic 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. An iteration
function is used, as suggested by Rajendra Nayak 
This function is temporary and will be removed later in the series.

This functionality brings consistency in the functional power states
core code and acts as a guard against hardware implementations
discrepancies, e.g. some power domains only support the RET logic
state although reading the logic state registers (previous, current
and next) always returns OFF. The DSS power domain on OMAP3 is an
example.

Signed-off-by: Jean Pihet 
Cc: Tero Kristo 
Cc: Rajendra Nayak 
Cc: Nishanth Menon 
[p...@pwsan.com: add offset for functional powerstates so it's not
 possible to confuse them with the old API; use one fn to convert func
 pwrsts to low-level hardware bits; skip hardware reads when hardware
 logic retst and logic pwrst bits are missing; fix kerneldoc and
 commit message; remove unnecessary PWRDM_LOGIC_MEM_PWRST_* macros;
 combine spinlock patch into this patch; expand the number of operations
 which take the spinlock]
Signed-off-by: Paul Walmsley 
---
 arch/arm/mach-omap2/powerdomain.c |  525 +
 arch/arm/mach-omap2/powerdomain.h |   33 ++
 2 files changed, 553 insertions(+), 5 deletions(-)

diff --git a/arch/arm/mach-omap2/powerdomain.c 
b/arch/arm/mach-omap2/powerdomain.c
index 94b89a25..18f33de 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -1,7 +1,7 @@
 /*
  * OMAP powerdomain control
  *
- * Copyright (C) 2007-2008, 2011 Texas Instruments, Inc.
+ * Copyright (C) 2007-2008, 2011-2012 Texas Instruments, Inc.
  * Copyright (C) 2007-2011 Nokia Corporation
  *
  * Written by Paul Walmsley
@@ -44,12 +44,19 @@ enum {
PWRDM_STATE_PREV,
 };
 
-
 /* pwrdm_list contains all registered struct powerdomains */
 static LIST_HEAD(pwrdm_list);
 
 static struct pwrdm_ops *arch_pwrdm;
 
+/*
+ * _fpwrst_names: human-readable functional powerstate names - should match
+ *the enum pwrdm_func_state order and names
+ */
+static const char * const _fpwrst_names[] = {
+   "OFF", "OSWR", "CSWR", "INACTIVE", "ON"
+};
+
 /* Private functions */
 
 static struct powerdomain *_pwrdm_lookup(const char *name)
@@ -145,7 +152,6 @@ static void _update_logic_membank_counters(struct 
powerdomain *pwrdm)
 
 static int _pwrdm_state_switch(struct powerdomain *pwrdm, int flag)
 {
-
int prev, next, state, trace_state = 0;
 
if (pwrdm == NULL)
@@ -259,6 +265,309 @@ static bool _pwrdm_logic_retst_can_change(struct 
powerdomain *pwrdm)
return _pwrdm_logic_retst_is_controllable(pwrdm);
 }
 
+/**
+ * _match_pwrst: determine the closest supported power state
+ * @pwrsts: list of allowed states, defined as a bitmask
+ * @pwrst: initial state to be used as a starting point
+ * @min: minimum (i.e. lowest consumption) allowed state
+ * @max: maximum (i.e. highest consumption) allowed state
+ *
+ * Search down then up for a valid state from a list of allowed
+ * states.  Used by states conversion functions (_pwrdm_fpwrst_to_*)
+ * to look for allowed power and logic states for a powerdomain.
+ * Returns the matching allowed state.  XXX Deprecated.  The software
+ * should not try to program unsupported powerstates.
+ */
+static int _match_pwrst(u32 pwrsts, int pwrst, int min, int max)
+{
+   int found = 1, new_pwrst = pwrst;
+
+   /*
+* If the power domain does not allow any state programmation
+* return the max state which is always allowed
+*/
+   if (!pwrsts)
+   return max;
+
+   /*
+* Search lower: if the requested state is not supported
+* try the lower states, stopping at the minimum allowed
+* state
+*/
+   while (!(pwrsts & (1 << new_pwrst))) {
+   if (new_pwrst <= min) {
+   found = 0;
+   break;
+   }
+   new_pwrst--;
+   }
+
+   /*
+* Search higher: if no lower state found

[PATCH 00/12] ARM: OMAP2+: powerdomain updates after the functional power state conversion

2012-12-09 Thread Paul Walmsley
OMAP powerdomain code updates, implemented on top of the
functional power state conversion series.  This series fixes the powerdomain
handling for OMAP2xxx, adds caching for the powerdomain next-power-state
and previous-power-state register bitfields, and some cleanup that's
intended to make it easier to move the powerdomain code out to drivers/.

- Paul

---

vmlinux object size
(delta in bytes from TEST_func_powerstates_devel_3.9 
(6d8345f4177c976eca1a1368cdd68e95f80c3f27)):
   text data  bsstotal  kernel
-68  +480  -20  am33xx_only
   -136  +480  -88  n800_multi_omap2xxx
   -128  +480  -80  n800_only_a
  0000  omap1_defconfig
  0000  omap1_defconfig_1510innovator_only
  0000  omap1_defconfig_5912osk_only
-32 +3680 +336  omap2plus_defconfig
+20  +160  +36  omap2plus_defconfig_2430sdp_only
-32 +4320 +400  omap2plus_defconfig_cpupm
   +572 +1920 +764  omap2plus_defconfig_no_pm
-20 +2080 +188  omap2plus_defconfig_omap2_4_only
-84 +3040 +220  omap2plus_defconfig_omap3_4_only
   +708 +200 -104 +804  rmk_omap3430_ldp_allnoconfig
   +352 +1280 +480  rmk_omap3430_ldp_oldconfig
   +708 +200 -104 +804  rmk_omap4430_sdp_allnoconfig
   -164   +80 -156  rmk_omap4430_sdp_oldconfig

Paul Walmsley (12):
  ARM: OMAP2+: powerdomain: consolidate arch_pwrdm check code
  ARM: OMAP2+: PM/powerdomain: move the power state time tracking into the 
powerdomain code
  ARM: OMAP2+: powerdomain: split pwrdm_state_switch()
  ARM: OMAP2+: PM: clean up some debugfs functions
  ARM: OMAP2+: powerdomain: remove some redundant checks; add some notes
  ARM: OMAP2+: CM: use the cached copy of the clockdomain's hwsup state
  ARM: OMAP2+: powerdomain: cache the powerdomain next power state
  ARM: OMAP2+: powerdomain: cache the powerdomain's previous power state
  ARM: OMAP2+: powerdomain: skip register reads for powerdomains known to 
be on
  ARM: OMAP2+: powerdomain: skip previous-power-state read if next_pwrst is 
ON
  ARM: OMAP2xxx: powerdomain: add previous power state tracking
  ARM: OMAP2xxx: PM: add pwrdm_(pre|post)_transition() calls to the 2xxx PM 
code


 arch/arm/mach-omap2/clockdomain.c   |   18 +
 arch/arm/mach-omap2/clockdomain.h   |2 
 arch/arm/mach-omap2/cm2xxx.c|   19 -
 arch/arm/mach-omap2/cm3xxx.c|   14 -
 arch/arm/mach-omap2/pm-debug.c  |  101 
 arch/arm/mach-omap2/pm.h|6 
 arch/arm/mach-omap2/pm24xx.c|8 +
 arch/arm/mach-omap2/powerdomain.c   |  352 +++
 arch/arm/mach-omap2/powerdomain.h   |   40 +++
 arch/arm/mach-omap2/powerdomains2xxx_data.c |2 
 arch/arm/mach-omap2/powerdomains33xx_data.c |3 
 arch/arm/mach-omap2/powerdomains3xxx_data.c |9 -
 arch/arm/mach-omap2/powerdomains44xx_data.c |5 
 arch/arm/mach-omap2/prm2xxx.c   |   12 +
 14 files changed, 347 insertions(+), 244 deletions(-)

--
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/12] ARM: OMAP2+: powerdomain: consolidate arch_pwrdm check code

2012-12-09 Thread Paul Walmsley
Check for the presence of some of the arch_pwrdm function pointers
during powerdomain setup, rather than in the individual functions.
The primary motivation is to make the code slightly easier to read, but it
also should avoid a few instructions in some hot paths.

Signed-off-by: Paul Walmsley 
---
 arch/arm/mach-omap2/powerdomain.c |   43 +++--
 1 file changed, 18 insertions(+), 25 deletions(-)

diff --git a/arch/arm/mach-omap2/powerdomain.c 
b/arch/arm/mach-omap2/powerdomain.c
index f81aee1..b67d721 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -385,9 +385,6 @@ static int _set_logic_retst_and_pwrdm_pwrst(struct 
powerdomain *pwrdm,
if (!_pwrdm_pwrst_is_controllable(pwrdm))
return 0;
 
-   if (!arch_pwrdm || !arch_pwrdm->pwrdm_set_next_pwrst)
-   return -EINVAL;
-
if (!(pwrdm->pwrsts & (1 << pwrst)))
return -EINVAL;
 
@@ -395,13 +392,11 @@ static int _set_logic_retst_and_pwrdm_pwrst(struct 
powerdomain *pwrdm,
if (!(pwrdm->pwrsts_logic_ret & (1 << logic)))
return -EINVAL;
 
-   if (arch_pwrdm->pwrdm_set_logic_retst) {
-   ret = arch_pwrdm->pwrdm_set_logic_retst(pwrdm, logic);
-   if (ret) {
-   pr_err("%s: unable to set logic state %0x of 
powerdomain: %s\n",
-  __func__, logic, pwrdm->name);
-   return ret;
-   }
+   ret = arch_pwrdm->pwrdm_set_logic_retst(pwrdm, logic);
+   if (ret) {
+   pr_err("%s: unable to set logic state %0x of 
powerdomain: %s\n",
+  __func__, logic, pwrdm->name);
+   return ret;
}
}
 
@@ -426,9 +421,6 @@ static int _pwrdm_read_next_fpwrst(struct powerdomain 
*pwrdm)
int next_pwrst, next_logic, ret;
u8 fpwrst;
 
-   if (!arch_pwrdm || !arch_pwrdm->pwrdm_read_next_pwrst)
-   return -EINVAL;
-
next_pwrst = arch_pwrdm->pwrdm_read_next_pwrst(pwrdm);
if (next_pwrst < 0)
return next_pwrst;
@@ -653,9 +645,12 @@ static int _pwrdm_post_transition_cb(struct powerdomain 
*pwrdm, void *unused)
  *
  * Register the list of function pointers used to implement the
  * powerdomain functions on different OMAP SoCs.  Should be called
- * before any other pwrdm_register*() function.  Returns -EINVAL if
- * @po is null, -EEXIST if platform functions have already been
- * registered, or 0 upon success.
+ * before any other pwrdm_register*() function.  Several function
+ * pointers in @po are required to be non-null for the powerdomain
+ * code to function: pwrdm_wait_transition, pwrdm_read_next_pwrst,
+ * pwrdm_read_pwrst, pwrdm_set_next_pwrst, pwrdm_set_logic_retst, and
+ * pwrdm_read_prev_pwrst.  Returns -EINVAL if @po is null, -EEXIST if
+ * platform functions have already been registered, or 0 upon success.
  */
 int pwrdm_register_platform_funcs(struct pwrdm_ops *po)
 {
@@ -665,6 +660,11 @@ int pwrdm_register_platform_funcs(struct pwrdm_ops *po)
if (arch_pwrdm)
return -EEXIST;
 
+   if (!po->pwrdm_wait_transition || !po->pwrdm_read_next_pwrst ||
+   !po->pwrdm_read_pwrst || !po->pwrdm_set_next_pwrst ||
+   !po->pwrdm_set_logic_retst || !po->pwrdm_read_prev_pwrst)
+   return -ENOENT;
+
arch_pwrdm = po;
 
return 0;
@@ -1221,7 +1221,7 @@ int pwrdm_read_next_fpwrst(struct powerdomain *pwrdm)
int next_pwrst, next_logic, ret;
u8 fpwrst;
 
-   if (!arch_pwrdm || !arch_pwrdm->pwrdm_read_next_pwrst)
+   if (!arch_pwrdm)
return -EINVAL;
 
pwrdm_lock(pwrdm);
@@ -1264,8 +1264,7 @@ int pwrdm_set_fpwrst(struct powerdomain *pwrdm, enum 
pwrdm_func_state fpwrst)
int ret = 0;
bool hwsup = false;
 
-   if (!pwrdm || IS_ERR(pwrdm) || !arch_pwrdm ||
-   !arch_pwrdm->pwrdm_read_pwrst)
+   if (!pwrdm || IS_ERR(pwrdm) || !arch_pwrdm)
return -EINVAL;
 
/*
@@ -1334,9 +1333,6 @@ int pwrdm_read_fpwrst(struct powerdomain *pwrdm)
if (!_pwrdm_pwrst_can_change(pwrdm))
return PWRDM_FUNC_PWRST_ON;
 
-   if (!arch_pwrdm->pwrdm_read_pwrst)
-   return -EINVAL;
-
pwrdm_lock(pwrdm);
ret = _pwrdm_read_fpwrst(pwrdm);
pwrdm_unlock(pwrdm);
@@ -1362,9 +1358,6 @@ int pwrdm_read_prev_fpwrst(struct powerdomain *pwrdm)
if (!_pwrdm_pwrst_can_change(pwrdm))
return PWRDM_FUNC_PWRST_ON;
 
-   if (!arch_pwrdm->pwrdm_read_prev_pwrst)
-   return -EINVAL;
-
pwrdm_lock(pwrdm);
ret = _pwrdm_read_prev_fpwrst(pwrdm);
pwrdm_unlock(pwrdm);


--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to maj

[PATCH 02/12] ARM: OMAP2+: PM/powerdomain: move the power state time tracking into the powerdomain code

2012-12-09 Thread Paul Walmsley
Move the power state time tracking code into the powerdomain code.
This code accesses internal powerdomain state, so this change will
allow us to reduce what is exported from the powerdomain code.

Signed-off-by: Paul Walmsley 
Cc: Tero Kristo 
Cc: Kevin Hilman 
---
 arch/arm/mach-omap2/pm-debug.c|   24 
 arch/arm/mach-omap2/pm.h  |6 --
 arch/arm/mach-omap2/powerdomain.c |   22 +-
 3 files changed, 21 insertions(+), 31 deletions(-)

diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c
index 03da2e3..80c001a 100644
--- a/arch/arm/mach-omap2/pm-debug.c
+++ b/arch/arm/mach-omap2/pm-debug.c
@@ -53,21 +53,6 @@ enum {
DEBUG_FILE_TIMERS,
 };
 
-void pm_dbg_update_time(struct powerdomain *pwrdm, int prev)
-{
-   s64 t;
-
-   if (!pm_dbg_init_done)
-   return ;
-
-   /* Update timer for previous state */
-   t = sched_clock();
-
-   pwrdm->fpwrst_timer[prev - PWRDM_FPWRST_OFFSET] += t - pwrdm->timer;
-
-   pwrdm->timer = t;
-}
-
 static int clkdm_dbg_show_counter(struct clockdomain *clkdm, void *user)
 {
struct seq_file *s = (struct seq_file *)user;
@@ -197,17 +182,8 @@ DEFINE_SIMPLE_ATTRIBUTE(pwrdm_suspend_fops, 
pwrdm_suspend_get,
 
 static int __init pwrdms_setup(struct powerdomain *pwrdm, void *dir)
 {
-   int i;
-   s64 t;
struct dentry *d;
 
-   t = sched_clock();
-
-   for (i = 0; i < PWRDM_FPWRSTS_COUNT; i++)
-   pwrdm->fpwrst_timer[i] = 0;
-
-   pwrdm->timer = t;
-
if (strncmp(pwrdm->name, "dpll", 4) == 0)
return 0;
 
diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
index 19ef376..c496f27 100644
--- a/arch/arm/mach-omap2/pm.h
+++ b/arch/arm/mach-omap2/pm.h
@@ -59,12 +59,6 @@ extern u32 enable_off_mode;
 #define enable_off_mode 0
 #endif
 
-#if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS)
-extern void pm_dbg_update_time(struct powerdomain *pwrdm, int prev);
-#else
-#define pm_dbg_update_time(pwrdm, prev) do {} while (0);
-#endif /* CONFIG_PM_DEBUG */
-
 /* 24xx */
 extern void omap24xx_idle_loop_suspend(void);
 extern unsigned int omap24xx_idle_loop_suspend_sz;
diff --git a/arch/arm/mach-omap2/powerdomain.c 
b/arch/arm/mach-omap2/powerdomain.c
index b67d721..53bc852 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -20,6 +20,8 @@
 #include 
 #include 
 #include 
+#include 
+
 #include 
 
 #include "cm2xxx_3xxx.h"
@@ -126,6 +128,9 @@ static int _pwrdm_register(struct powerdomain *pwrdm)
arch_pwrdm->pwrdm_wait_transition(pwrdm);
pwrdm->fpwrst = pwrdm_read_fpwrst(pwrdm);
pwrdm->fpwrst_counter[pwrdm->fpwrst - PWRDM_FPWRST_OFFSET] = 1;
+#ifdef CONFIG_PM_DEBUG
+   pwrdm->timer = sched_clock();
+#endif
 
return 0;
 }
@@ -579,6 +584,21 @@ static int _pwrdm_set_mem_retst(struct powerdomain *pwrdm, 
u8 bank, u8 pwrst)
return ret;
 }
 
+/* XXX prev is wrong type */
+/* XXX is sched_clock() correct to use here? */
+/* Update timer for previous state */
+static void _pwrdm_update_pwrst_time(struct powerdomain *pwrdm, int prev)
+{
+#ifdef CONFIG_PM_DEBUG
+   s64 t;
+
+   t = sched_clock();
+
+   pwrdm->fpwrst_timer[prev - PWRDM_FPWRST_OFFSET] += t - pwrdm->timer;
+
+   pwrdm->timer = t;
+#endif
+}
 
 /* XXX Caller must hold pwrdm->_lock */
 static int _pwrdm_state_switch(struct powerdomain *pwrdm, int flag)
@@ -617,7 +637,7 @@ static int _pwrdm_state_switch(struct powerdomain *pwrdm, 
int flag)
if (fpwrst != prev)
pwrdm->fpwrst_counter[fpwrst - PWRDM_FPWRST_OFFSET]++;
 
-   pm_dbg_update_time(pwrdm, prev);
+   _pwrdm_update_pwrst_time(pwrdm, prev);
 
pwrdm->fpwrst = fpwrst;
 


--
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 05/12] ARM: OMAP2+: powerdomain: remove some redundant checks; add some notes

2012-12-09 Thread Paul Walmsley
Remove some redundant tests in static functions, and add some comments
to some code that should have future attention.

Signed-off-by: Paul Walmsley 
---
 arch/arm/mach-omap2/powerdomain.c |   18 +++---
 1 file changed, 11 insertions(+), 7 deletions(-)

diff --git a/arch/arm/mach-omap2/powerdomain.c 
b/arch/arm/mach-omap2/powerdomain.c
index 658f4ed..62e2f75 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -95,7 +95,7 @@ static int _pwrdm_register(struct powerdomain *pwrdm)
int i;
struct voltagedomain *voltdm;
 
-   if (!pwrdm || !pwrdm->name)
+   if (!pwrdm->name)
return -EINVAL;
 
if (cpu_is_omap44xx() &&
@@ -528,9 +528,6 @@ static int _pwrdm_set_mem_onst(struct powerdomain *pwrdm, 
u8 bank, u8 pwrst)
 {
int ret = -EINVAL;
 
-   if (!pwrdm)
-   return -EINVAL;
-
if (pwrdm->banks < (bank + 1))
return -EEXIST;
 
@@ -566,9 +563,6 @@ static int _pwrdm_set_mem_retst(struct powerdomain *pwrdm, 
u8 bank, u8 pwrst)
 {
int ret = -EINVAL;
 
-   if (!pwrdm)
-   return -EINVAL;
-
if (pwrdm->banks < (bank + 1))
return -EEXIST;
 
@@ -635,6 +629,11 @@ static void _pwrdm_state_switch(struct powerdomain *pwrdm)
 
 static int _pwrdm_pre_transition_cb(struct powerdomain *pwrdm, void *unused)
 {
+   /*
+* XXX It should be possible to avoid the clear_all_prev_pwrst
+* call for powerdomains if we are programming them to stay on,
+* for example.
+*/
pwrdm_clear_all_prev_pwrst(pwrdm);
_pwrdm_state_switch(pwrdm);
return 0;
@@ -1000,6 +999,11 @@ int pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm)
return ret;
 
/*
+* XXX Is there some way for us to skip powerdomains that
+* don't have a prev pwrst register?
+*/
+
+   /*
 * XXX should get the powerdomain's current state here;
 * warn & fail if it is not ON.
 */


--
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 03/12] ARM: OMAP2+: powerdomain: split pwrdm_state_switch()

2012-12-09 Thread Paul Walmsley
Move the pwrdm_state_switch() code that deals with previous power
states into the post-transition callback.  This improves the clarity
of pwrdm_state_switch() considerably.  Add some sorely-needed
kerneldoc for these functions.

It should be possible to drop pwrdm_state_switch() completely during
3.9.

Signed-off-by: Paul Walmsley 
Cc: Tero Kristo 
---
 arch/arm/mach-omap2/powerdomain.c |  118 -
 arch/arm/mach-omap2/powerdomain.h |1 
 2 files changed, 76 insertions(+), 43 deletions(-)

diff --git a/arch/arm/mach-omap2/powerdomain.c 
b/arch/arm/mach-omap2/powerdomain.c
index 53bc852..d38f493 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -40,11 +40,6 @@
 
 #define PWRDM_TRACE_STATES_FLAG(1<<31)
 
-enum {
-   PWRDM_STATE_NOW = 0,
-   PWRDM_STATE_PREV,
-};
-
 /* Types of sleep_switch used in pwrdm_set_fpwrst() */
 #define ALREADYACTIVE_SWITCH   0
 #define FORCEWAKEUP_SWITCH 1
@@ -600,60 +595,97 @@ static void _pwrdm_update_pwrst_time(struct powerdomain 
*pwrdm, int prev)
 #endif
 }
 
-/* XXX Caller must hold pwrdm->_lock */
-static int _pwrdm_state_switch(struct powerdomain *pwrdm, int flag)
+/**
+ * _pwrdm_state_switch - record powerdomain usage data; track power state
+ * (before powerdomain state transition)
+ * @pwrdm: struct powerdomain * to observe
+ *
+ * If the powerdomain @pwrdm's current power state is not what we last
+ * observed it to be, then increment the counter for that power state.
+ * This is used to track context loss events, and for debugging.  Also
+ * if CONFIG_PM_DEBUG=y, track the amount of time the powerdomain has
+ * spent in the current power state.  Caller must hold pwrdm->_lock.
+ * Intended to be called immediately before the powerdomain's power
+ * state is likely to change.  XXX Note that the counts and durations
+ * observed by this function may be inaccurate.  Powerdomains can
+ * transition power states automatically, without the kernel being
+ * involved -- for example, a device can DMA data from memory while
+ * the MPU is asleep.  This function does not attempt to account for
+ * that.  XXX It may be possible to skip this function completely if
+ * PM debugging is not needed and off-mode and OSWR is disabled (e.g.,
+ * no context loss events).  No return value.
+ */
+static void _pwrdm_state_switch(struct powerdomain *pwrdm)
 {
-   int prev, next, fpwrst, trace_state = 0;
-
-   if (pwrdm == NULL)
-   return -EINVAL;
+   int fpwrst;
 
fpwrst = _pwrdm_read_fpwrst(pwrdm);
-
-   switch (flag) {
-   case PWRDM_STATE_NOW:
-   prev = pwrdm->fpwrst;
-   break;
-   case PWRDM_STATE_PREV:
-   prev = _pwrdm_read_prev_fpwrst(pwrdm);
-   if (pwrdm->fpwrst != prev)
-   pwrdm->fpwrst_counter[prev - PWRDM_FPWRST_OFFSET]++;
-   /*
-* If the power domain did not hit the desired state,
-* generate a trace event with both the desired and hit states
-*/
-   next = _pwrdm_read_next_fpwrst(pwrdm);
-   if (next != prev) {
-   trace_state = (PWRDM_TRACE_STATES_FLAG | next << 8 |
-  prev);
-   trace_power_domain_target(pwrdm->name, trace_state,
- smp_processor_id());
-   }
-   break;
-   default:
-   return -EINVAL;
-   }
-
-   if (fpwrst != prev)
+   if (fpwrst != pwrdm->fpwrst)
pwrdm->fpwrst_counter[fpwrst - PWRDM_FPWRST_OFFSET]++;
 
-   _pwrdm_update_pwrst_time(pwrdm, prev);
+   _pwrdm_update_pwrst_time(pwrdm, pwrdm->fpwrst);
 
pwrdm->fpwrst = fpwrst;
-
-   return 0;
 }
 
 static int _pwrdm_pre_transition_cb(struct powerdomain *pwrdm, void *unused)
 {
pwrdm_clear_all_prev_pwrst(pwrdm);
-   _pwrdm_state_switch(pwrdm, PWRDM_STATE_NOW);
+   _pwrdm_state_switch(pwrdm);
return 0;
 }
 
+/**
+ * _pwrdm_post_transition_cb - record powerdomain usage data; track power state
+ * (after powerdomain power state transition)
+ * @pwrdm: struct powerdomain * to observe
+ *
+ * If the powerdomain @pwrdm's previous power state doesn't match our
+ * recollection of the powerdomain's current power state, then
+ * increment the counter for the previous power state.  And if the
+ * powerdomain's previous power state doesn't match the current power
+ * state, increment the counter for the current power state.  This
+ * function is used to track context loss events, and for debugging.
+ * Also if CONFIG_PM_DEBUG=y, track the approximate amount of time the
+ * powerdomain has spent in the previous power state.  Caller must
+ * hold pwrdm->_lock.  XXX Note that the counts and durations observed
+ * by this function may be inaccurate.  Powerdomains can transition
+ * power states

[PATCH 04/12] ARM: OMAP2+: PM: clean up some debugfs functions

2012-12-09 Thread Paul Walmsley
Move some debugfs functions into the powerdomain and clockdomain code;
the ultimate goal is to stop exporting some of the
powerdomain/clockdomain functions.  Get rid of the nasty hacks that
avoid executing some of the debug functions based on string
comparisons on powerdomain and clockdomain names.  Lock the
powerdomain for the duration of these functions so that the debug
information doesn't change during execution.  Also, while here, fix a
whitespace issue in mach-omap2/pm-debug.c.

Signed-off-by: Paul Walmsley 
Cc: Tero Kristo 
Cc: Kevin Hilman 
---
 arch/arm/mach-omap2/clockdomain.c |   18 +++-
 arch/arm/mach-omap2/clockdomain.h |2 +
 arch/arm/mach-omap2/pm-debug.c|   77 ++
 arch/arm/mach-omap2/powerdomain.c |   85 +
 arch/arm/mach-omap2/powerdomain.h |4 ++
 5 files changed, 111 insertions(+), 75 deletions(-)

diff --git a/arch/arm/mach-omap2/clockdomain.c 
b/arch/arm/mach-omap2/clockdomain.c
index a90c0c8..bc9b79e 100644
--- a/arch/arm/mach-omap2/clockdomain.c
+++ b/arch/arm/mach-omap2/clockdomain.c
@@ -22,9 +22,8 @@
 #include 
 #include 
 #include 
-
+#include 
 #include 
-
 #include 
 
 #include "soc.h"
@@ -1281,3 +1280,18 @@ int clkdm_hwmod_disable(struct clockdomain *clkdm, 
struct omap_hwmod *oh)
return _clkdm_clk_hwmod_disable(clkdm);
 }
 
+/* Clockdomain debugfs functions */
+
+int clkdm_dbg_show_counter(struct clockdomain *clkdm, void *seq_file)
+{
+   struct seq_file *s = (struct seq_file *)seq_file;
+
+   if (!clkdm->flags)
+   return 0;
+
+   seq_printf(s, "%s->%s (%d)\n", clkdm->name, clkdm->pwrdm.ptr->name,
+  clkdm->usecount);
+
+   return 0;
+}
+
diff --git a/arch/arm/mach-omap2/clockdomain.h 
b/arch/arm/mach-omap2/clockdomain.h
index 2da3765..95e473b 100644
--- a/arch/arm/mach-omap2/clockdomain.h
+++ b/arch/arm/mach-omap2/clockdomain.h
@@ -229,4 +229,6 @@ extern struct clkdm_dep gfx_24xx_wkdeps[];
 extern struct clkdm_dep dsp_24xx_wkdeps[];
 extern struct clockdomain wkup_common_clkdm;
 
+extern int clkdm_dbg_show_counter(struct clockdomain *clkdm, void *seq_file);
+
 #endif
diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c
index 80c001a..9861069 100644
--- a/arch/arm/mach-omap2/pm-debug.c
+++ b/arch/arm/mach-omap2/pm-debug.c
@@ -53,75 +53,6 @@ enum {
DEBUG_FILE_TIMERS,
 };
 
-static int clkdm_dbg_show_counter(struct clockdomain *clkdm, void *user)
-{
-   struct seq_file *s = (struct seq_file *)user;
-
-   /* XXX This needs to be implemented in a better way */
-   if (strcmp(clkdm->name, "emu_clkdm") == 0 ||
-   strcmp(clkdm->name, "wkup_clkdm") == 0 ||
-   strncmp(clkdm->name, "dpll", 4) == 0)
-   return 0;
-
-   seq_printf(s, "%s->%s (%d)\n", clkdm->name, clkdm->pwrdm.ptr->name,
-  clkdm->usecount);
-
-   return 0;
-}
-
-static int pwrdm_dbg_show_counter(struct powerdomain *pwrdm, void *user)
-{
-   struct seq_file *s = (struct seq_file *)user;
-   int i;
-   int curr_fpwrst;
-
-   if (strcmp(pwrdm->name, "emu_pwrdm") == 0 ||
-   strcmp(pwrdm->name, "wkup_pwrdm") == 0 ||
-   strncmp(pwrdm->name, "dpll", 4) == 0)
-   return 0;
-
-   curr_fpwrst = pwrdm_read_fpwrst(pwrdm);
-   if (pwrdm->fpwrst != curr_fpwrst)
-   pr_err("pwrdm state mismatch(%s) %s != %s\n",
-  pwrdm->name,
-  pwrdm_convert_fpwrst_to_name(pwrdm->fpwrst),
-  pwrdm_convert_fpwrst_to_name(curr_fpwrst));
-
-   seq_printf(s, "%s (%s)", pwrdm->name,
-  pwrdm_convert_fpwrst_to_name(pwrdm->fpwrst));
-   for (i = PWRDM_FPWRST_OFFSET; i < PWRDM_MAX_FUNC_PWRSTS; i++)
-   seq_printf(s, ",%s:%d", pwrdm_convert_fpwrst_to_name(i),
-  pwrdm->fpwrst_counter[i - PWRDM_FPWRST_OFFSET]);
-
-   seq_printf(s, "\n");
-
-   return 0;
-}
-
-static int pwrdm_dbg_show_timer(struct powerdomain *pwrdm, void *user)
-{
-   struct seq_file *s = (struct seq_file *)user;
-   int i;
-
-   if (strcmp(pwrdm->name, "emu_pwrdm") == 0 ||
-   strcmp(pwrdm->name, "wkup_pwrdm") == 0 ||
-   strncmp(pwrdm->name, "dpll", 4) == 0)
-   return 0;
-
-   pwrdm_state_switch(pwrdm);
-
-   seq_printf(s, "%s (%s)", pwrdm->name,
-  pwrdm_convert_fpwrst_to_name(pwrdm->fpwrst));
-
-   for (i = 0; i < PWRDM_FPWRSTS_COUNT; i++)
-   seq_printf(s, ",%s:%lld",
-  pwrdm_convert_fpwrst_to_name(i + 
PWRDM_FPWRST_OFFSET),
-  pwrdm->fpwrst_timer[i]);
-
-   seq_printf(s, "\n");
-   return 0;
-}
-
 static int pm_dbg_show_counters(struct seq_file *s, void *unused)
 {
pwrdm_for_each(pwrdm_dbg_show_counter, s);
@@ -150,10 +81,10 @@ static int pm_dbg_open(struct inode *inode, struct file 
*file)
 }
 
 static

[PATCH 06/12] ARM: OMAP2+: CM: use the cached copy of the clockdomain's hwsup state

2012-12-09 Thread Paul Walmsley
Avoid some unnecessary CM IP block reads by using the cached copy of
the clockdomain's hardware-supervised idle state.  This should
simplify the code slightly and save a few hundred nanoseconds in these
paths.

Signed-off-by: Paul Walmsley 
---
 arch/arm/mach-omap2/cm2xxx.c |   19 ++-
 arch/arm/mach-omap2/cm3xxx.c |   14 ++
 2 files changed, 4 insertions(+), 29 deletions(-)

diff --git a/arch/arm/mach-omap2/cm2xxx.c b/arch/arm/mach-omap2/cm2xxx.c
index 6774a53..8ca13cd 100644
--- a/arch/arm/mach-omap2/cm2xxx.c
+++ b/arch/arm/mach-omap2/cm2xxx.c
@@ -285,14 +285,7 @@ static void omap2xxx_clkdm_deny_idle(struct clockdomain 
*clkdm)
 
 static int omap2xxx_clkdm_clk_enable(struct clockdomain *clkdm)
 {
-   bool hwsup = false;
-
-   if (!clkdm->clktrctrl_mask)
-   return 0;
-
-   hwsup = omap2xxx_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
- clkdm->clktrctrl_mask);
-   if (!hwsup && clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)
+   if (!clkdm_in_hwsup(clkdm) && clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)
omap2xxx_clkdm_wakeup(clkdm);
 
return 0;
@@ -300,15 +293,7 @@ static int omap2xxx_clkdm_clk_enable(struct clockdomain 
*clkdm)
 
 static int omap2xxx_clkdm_clk_disable(struct clockdomain *clkdm)
 {
-   bool hwsup = false;
-
-   if (!clkdm->clktrctrl_mask)
-   return 0;
-
-   hwsup = omap2xxx_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
- clkdm->clktrctrl_mask);
-
-   if (!hwsup && clkdm->flags & CLKDM_CAN_FORCE_SLEEP)
+   if (!clkdm_in_hwsup(clkdm) && clkdm->flags & CLKDM_CAN_FORCE_SLEEP)
omap2xxx_clkdm_sleep(clkdm);
 
return 0;
diff --git a/arch/arm/mach-omap2/cm3xxx.c b/arch/arm/mach-omap2/cm3xxx.c
index 9061c30..75872134 100644
--- a/arch/arm/mach-omap2/cm3xxx.c
+++ b/arch/arm/mach-omap2/cm3xxx.c
@@ -227,8 +227,6 @@ static void omap3xxx_clkdm_deny_idle(struct clockdomain 
*clkdm)
 
 static int omap3xxx_clkdm_clk_enable(struct clockdomain *clkdm)
 {
-   bool hwsup = false;
-
if (!clkdm->clktrctrl_mask)
return 0;
 
@@ -243,10 +241,7 @@ static int omap3xxx_clkdm_clk_enable(struct clockdomain 
*clkdm)
return 0;
}
 
-   hwsup = omap3xxx_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
- clkdm->clktrctrl_mask);
-
-   if (hwsup) {
+   if (clkdm_in_hwsup(clkdm)) {
/* Disable HW transitions when we are changing deps */
omap3xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
clkdm->clktrctrl_mask);
@@ -263,8 +258,6 @@ static int omap3xxx_clkdm_clk_enable(struct clockdomain 
*clkdm)
 
 static int omap3xxx_clkdm_clk_disable(struct clockdomain *clkdm)
 {
-   bool hwsup = false;
-
if (!clkdm->clktrctrl_mask)
return 0;
 
@@ -280,10 +273,7 @@ static int omap3xxx_clkdm_clk_disable(struct clockdomain 
*clkdm)
return 0;
}
 
-   hwsup = omap3xxx_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
- clkdm->clktrctrl_mask);
-
-   if (hwsup) {
+   if (clkdm_in_hwsup(clkdm)) {
/* Disable HW transitions when we are changing deps */
omap3xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
clkdm->clktrctrl_mask);


--
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 12/12] ARM: OMAP2xxx: PM: add pwrdm_(pre|post)_transition() calls to the 2xxx PM code

2012-12-09 Thread Paul Walmsley
The OMAP2xxx PM code was missing calls to pwrdm_pre_transition() and
pwrdm_post_transition().  This prevented the power state debugging
from working correctly, and also violated some assumptions that are
used in future power state caching patches.

Signed-off-by: Paul Walmsley 
Cc: Kevin Hilman 
---
 arch/arm/mach-omap2/pm24xx.c |8 
 1 file changed, 8 insertions(+)

diff --git a/arch/arm/mach-omap2/pm24xx.c b/arch/arm/mach-omap2/pm24xx.c
index 99c16c2..896727c 100644
--- a/arch/arm/mach-omap2/pm24xx.c
+++ b/arch/arm/mach-omap2/pm24xx.c
@@ -98,6 +98,8 @@ static int omap2_enter_full_retention(void)
 
omap2_gpio_prepare_for_idle(0);
 
+   pwrdm_pre_transition(NULL);
+
/* One last check for pending IRQs to avoid extra latency due
 * to sleeping unnecessarily. */
if (omap_irq_pending())
@@ -109,6 +111,8 @@ static int omap2_enter_full_retention(void)
   OMAP_SDRC_REGADDR(SDRC_POWER));
 
 no_sleep:
+   pwrdm_post_transition(NULL);
+
omap2_gpio_resume_after_idle();
 
clk_enable(osc_ck);
@@ -191,8 +195,12 @@ static void omap2_enter_mpu_retention(void)
WARN_ON(pwrdm_set_next_fpwrst(mpu_pwrdm, PWRDM_FUNC_PWRST_ON));
}
 
+   pwrdm_pre_transition(mpu_pwrdm);
+
omap2_sram_idle();
 
+   pwrdm_post_transition(mpu_pwrdm);
+
WARN_ON(pwrdm_set_next_fpwrst(mpu_pwrdm, PWRDM_FUNC_PWRST_ON));
 }
 


--
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 10/12] ARM: OMAP2+: powerdomain: skip previous-power-state read if next_pwrst is ON

2012-12-09 Thread Paul Walmsley
If the powerdomain's next-power-state is set to ON, then we can skip
the powerdomain previous-power-state read during
pwrdm_post_transition().  This is both an optimization (for all OMAPs)
and a fix (for OMAP2xxx).  It turns out the OMAP2xxx previous power
state mechanism is slightly different than the OMAP3+ mechanism. The
bitfield can't be cleared, and it's only updated after a powerdomain
power state transition.  So reading this value before any powerdomain
power state transition occurred will always return OFF (the reset
value).  After this patch, if the power domain was programmed to stay
ON before pwrdm_pre_transition() is called, the previous power state
code will return ON during pwrdm_post_transition().

Signed-off-by: Paul Walmsley 
---
 arch/arm/mach-omap2/powerdomain.c |4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-omap2/powerdomain.c 
b/arch/arm/mach-omap2/powerdomain.c
index a4bb0bb..72d6ce0 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -681,7 +681,9 @@ static int _pwrdm_post_transition_cb(struct powerdomain 
*pwrdm, void *unused)
int prev, fpwrst;
int trace_state = 0;
 
-   prev = _pwrdm_read_prev_fpwrst(pwrdm);
+   prev = (pwrdm->next_fpwrst == PWRDM_FUNC_PWRST_ON) ?
+   PWRDM_FUNC_PWRST_ON : _pwrdm_read_prev_fpwrst(pwrdm);
+
if (pwrdm->fpwrst != prev)
pwrdm->fpwrst_counter[prev - PWRDM_FPWRST_OFFSET]++;
 


--
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 09/12] ARM: OMAP2+: powerdomain: skip register reads for powerdomains known to be on

2012-12-09 Thread Paul Walmsley
There's no need to determine the current power state for powerdomains
that must be on while the kernel is running.  We mark these
powerdomains with a new flag, PWRDM_ACTIVE_WITH_KERNEL.  Any
powerdomain marked with that flag is reported as being in the ON power
state while the kernel is running.

Signed-off-by: Paul Walmsley 
Cc: Benoît Cousson 
---
 arch/arm/mach-omap2/powerdomain.c   |9 ++---
 arch/arm/mach-omap2/powerdomain.h   |4 
 arch/arm/mach-omap2/powerdomains2xxx_data.c |2 ++
 arch/arm/mach-omap2/powerdomains33xx_data.c |3 ++-
 arch/arm/mach-omap2/powerdomains3xxx_data.c |9 ++---
 arch/arm/mach-omap2/powerdomains44xx_data.c |5 -
 6 files changed, 24 insertions(+), 8 deletions(-)

diff --git a/arch/arm/mach-omap2/powerdomain.c 
b/arch/arm/mach-omap2/powerdomain.c
index f5e2727..a4bb0bb 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -462,7 +462,8 @@ static int _pwrdm_read_fpwrst(struct powerdomain *pwrdm)
int pwrst, logic_pwrst, ret;
u8 fpwrst;
 
-   if (!_pwrdm_pwrst_can_change(pwrdm))
+   if (!_pwrdm_pwrst_can_change(pwrdm) ||
+   pwrdm->flags & PWRDM_ACTIVE_WITH_KERNEL)
return PWRDM_FUNC_PWRST_ON;
 
pwrst = arch_pwrdm->pwrdm_read_pwrst(pwrdm);
@@ -1104,12 +1105,14 @@ bool pwrdm_has_hdwr_sar(struct powerdomain *pwrdm)
 
 int pwrdm_state_switch_nolock(struct powerdomain *pwrdm)
 {
-   int ret;
+   int ret = 0;
 
if (!pwrdm || !arch_pwrdm)
return -EINVAL;
 
-   ret = arch_pwrdm->pwrdm_wait_transition(pwrdm);
+   if (!(pwrdm->flags & PWRDM_ACTIVE_WITH_KERNEL))
+   ret = arch_pwrdm->pwrdm_wait_transition(pwrdm);
+
if (!ret)
_pwrdm_state_switch(pwrdm);
 
diff --git a/arch/arm/mach-omap2/powerdomain.h 
b/arch/arm/mach-omap2/powerdomain.h
index f4a189a..10941fd 100644
--- a/arch/arm/mach-omap2/powerdomain.h
+++ b/arch/arm/mach-omap2/powerdomain.h
@@ -78,10 +78,14 @@ enum pwrdm_func_state {
  *
  * PWRDM_HAS_LOWPOWERSTATECHANGE - can transition from a sleep state
  * to a lower sleep state without waking up the powerdomain
+ *
+ * PWRDM_ACTIVE_WITH_KERNEL - this powerdomain's current power state is
+ * guaranteed to be ON whenever the kernel is running
  */
 #define PWRDM_HAS_HDWR_SAR BIT(0)
 #define PWRDM_HAS_MPU_QUIRKBIT(1)
 #define PWRDM_HAS_LOWPOWERSTATECHANGE  BIT(2)
+#define PWRDM_ACTIVE_WITH_KERNEL   BIT(3)
 
 /*
  * Powerdomain internal flags (struct powerdomain._flags)
diff --git a/arch/arm/mach-omap2/powerdomains2xxx_data.c 
b/arch/arm/mach-omap2/powerdomains2xxx_data.c
index 578eef8..112927f 100644
--- a/arch/arm/mach-omap2/powerdomains2xxx_data.c
+++ b/arch/arm/mach-omap2/powerdomains2xxx_data.c
@@ -54,6 +54,7 @@ static struct powerdomain mpu_24xx_pwrdm = {
[0] = PWRSTS_ON,
},
.voltdm   = { .name = "core" },
+   .flags= PWRDM_ACTIVE_WITH_KERNEL,
 };
 
 static struct powerdomain core_24xx_pwrdm = {
@@ -73,6 +74,7 @@ static struct powerdomain core_24xx_pwrdm = {
[2] = PWRSTS_OFF_RET_ON, /* MEM3ONSTATE */
},
.voltdm   = { .name = "core" },
+   .flags= PWRDM_ACTIVE_WITH_KERNEL,
 };
 
 
diff --git a/arch/arm/mach-omap2/powerdomains33xx_data.c 
b/arch/arm/mach-omap2/powerdomains33xx_data.c
index 869adb8..acb148a 100644
--- a/arch/arm/mach-omap2/powerdomains33xx_data.c
+++ b/arch/arm/mach-omap2/powerdomains33xx_data.c
@@ -123,7 +123,8 @@ static struct powerdomain mpu_33xx_pwrdm = {
.pwrstst_offs   = AM33XX_PM_MPU_PWRSTST_OFFSET,
.pwrsts = PWRSTS_OFF_RET_ON,
.pwrsts_logic_ret   = PWRSTS_OFF_RET,
-   .flags  = PWRDM_HAS_LOWPOWERSTATECHANGE,
+   .flags  = (PWRDM_HAS_LOWPOWERSTATECHANGE |
+  PWRDM_ACTIVE_WITH_KERNEL),
.banks  = 3,
.logicretstate_mask = AM33XX_LOGICRETSTATE_MASK,
.mem_on_mask= {
diff --git a/arch/arm/mach-omap2/powerdomains3xxx_data.c 
b/arch/arm/mach-omap2/powerdomains3xxx_data.c
index f0e14e9ef..ade93d3 100644
--- a/arch/arm/mach-omap2/powerdomains3xxx_data.c
+++ b/arch/arm/mach-omap2/powerdomains3xxx_data.c
@@ -58,7 +58,7 @@ static struct powerdomain mpu_3xxx_pwrdm = {
.prcm_offs= MPU_MOD,
.pwrsts   = PWRSTS_OFF_RET_ON,
.pwrsts_logic_ret = PWRSTS_OFF_RET,
-   .flags= PWRDM_HAS_MPU_QUIRK,
+   .flags= (PWRDM_HAS_MPU_QUIRK | PWRDM_ACTIVE_WITH_KERNEL),
.banks= 1,
.pwrsts_mem_ret   = {
[0] = PWRSTS_OFF_RET,
@@ -74,7 +74,7 @@ static struct powerdomain mpu_am35x_pwrdm = {
.prcm_offs= MPU_MOD,
.pwrsts   = PWRSTS_ON,
.pwrsts_logic_ret = PWRSTS_ON,
-   .flags= PWRDM_HAS_MPU_QUIRK,
+

[PATCH 11/12] ARM: OMAP2xxx: powerdomain: add previous power state tracking

2012-12-09 Thread Paul Walmsley
The OMAP2xxx PRM does support a form of powerdomain previous-power-state
tracking; so add it.  This allows the power state tracking and debugging
code to do something useful on this platform.

Signed-off-by: Paul Walmsley 
---
 arch/arm/mach-omap2/prm2xxx.c |   12 
 1 file changed, 12 insertions(+)

diff --git a/arch/arm/mach-omap2/prm2xxx.c b/arch/arm/mach-omap2/prm2xxx.c
index e4cdb69..2d3c905 100644
--- a/arch/arm/mach-omap2/prm2xxx.c
+++ b/arch/arm/mach-omap2/prm2xxx.c
@@ -180,10 +180,22 @@ static int omap2xxx_pwrdm_read_pwrst(struct powerdomain 
*pwrdm)
return omap2xxx_pwrst_to_common_pwrst(omap2xxx_pwrst);
 }
 
+static int omap2xxx_pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
+{
+   u8 omap2xxx_pwrst;
+
+   omap2xxx_pwrst = omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
+  OMAP2_PM_PWSTST,
+  
OMAP24XX_LASTSTATEENTERED_MASK);
+
+   return omap2xxx_pwrst_to_common_pwrst(omap2xxx_pwrst);
+}
+
 struct pwrdm_ops omap2_pwrdm_operations = {
.pwrdm_set_next_pwrst   = omap2xxx_pwrdm_set_next_pwrst,
.pwrdm_read_next_pwrst  = omap2xxx_pwrdm_read_next_pwrst,
.pwrdm_read_pwrst   = omap2xxx_pwrdm_read_pwrst,
+   .pwrdm_read_prev_pwrst  = omap2xxx_pwrdm_read_prev_pwrst,
.pwrdm_set_logic_retst  = omap2_pwrdm_set_logic_retst,
.pwrdm_set_mem_onst = omap2_pwrdm_set_mem_onst,
.pwrdm_set_mem_retst= omap2_pwrdm_set_mem_retst,


--
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 08/12] ARM: OMAP2+: powerdomain: cache the powerdomain's previous power state

2012-12-09 Thread Paul Walmsley
Cache the powerdomain previous power state registers.  The objective
here is to avoid unneeded reads from the previous power state
registers.  Reads from these registers can be extremely slow, even by
I/O device standards.  I no longer recall the exact measurements, but
my recollection was that they cost several microseconds.

The cache is invalidated as part of the powerdomain pre-transition
code, which runs shortly before WFI/WFE.

Signed-off-by: Paul Walmsley 
Cc: Kevin Hilman 
---
 arch/arm/mach-omap2/powerdomain.c |9 +
 arch/arm/mach-omap2/powerdomain.h |   14 ++
 2 files changed, 23 insertions(+)

diff --git a/arch/arm/mach-omap2/powerdomain.c 
b/arch/arm/mach-omap2/powerdomain.c
index 425c868..f5e2727 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -499,6 +499,9 @@ static int _pwrdm_read_prev_fpwrst(struct powerdomain 
*pwrdm)
if (!_pwrdm_pwrst_can_change(pwrdm))
return PWRDM_FUNC_PWRST_ON;
 
+   if (pwrdm->_flags & _PWRDM_PREV_FPWRST_IS_VALID)
+   return pwrdm->prev_fpwrst;
+
pwrst = arch_pwrdm->pwrdm_read_prev_pwrst(pwrdm);
if (pwrst < 0)
return pwrst;
@@ -512,6 +515,10 @@ static int _pwrdm_read_prev_fpwrst(struct powerdomain 
*pwrdm)
}
 
ret = _pwrdm_pwrst_to_fpwrst(pwrdm, pwrst, logic_pwrst, &fpwrst);
+   if (!ret) {
+   pwrdm->prev_fpwrst = fpwrst;
+   pwrdm->_flags |= _PWRDM_PREV_FPWRST_IS_VALID;
+   }
 
return (ret) ? ret : fpwrst;
 }
@@ -1017,6 +1024,8 @@ int pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm)
pr_debug("powerdomain: %s: clearing previous power state reg\n",
 pwrdm->name);
 
+   pwrdm->_flags &= ~_PWRDM_PREV_FPWRST_IS_VALID;
+
if (arch_pwrdm && arch_pwrdm->pwrdm_clear_all_prev_pwrst)
ret = arch_pwrdm->pwrdm_clear_all_prev_pwrst(pwrdm);
 
diff --git a/arch/arm/mach-omap2/powerdomain.h 
b/arch/arm/mach-omap2/powerdomain.h
index 1fb21f5..f4a189a 100644
--- a/arch/arm/mach-omap2/powerdomain.h
+++ b/arch/arm/mach-omap2/powerdomain.h
@@ -90,8 +90,17 @@ enum pwrdm_func_state {
  *powerdomain's next-functional-power-state -- struct
  *powerdomain.next_fpwrst -- is valid.  If this bit is not set,
  *the code needs to load the current value from the hardware.
+ *
+ * _PWRDM_PREV_FPWRST_IS_VALID: the locally-cached copy of the
+ *powerdomain's previous-functional-power-state -- struct
+ *powerdomain.prev_fpwrst -- is valid.  If this bit is not set,
+ *the code needs to load the current value from the hardware.  The
+ *previous-functional-power-state cache for the CORE and MPU needs
+ *to be invalidated right before WFI, unless they were not programmed
+ *to change power states.
  */
 #define _PWRDM_NEXT_FPWRST_IS_VALIDBIT(0)
+#define _PWRDM_PREV_FPWRST_IS_VALIDBIT(1)
 
 /*
  * Number of memory banks that are power-controllable. On OMAP4430, the
@@ -138,6 +147,7 @@ struct powerdomain;
  * @fpwrst: current func power state (set in pwrdm_state_switch() or 
post_trans)
  * @fpwrst_counter: estimated number of times the pwrdm entered the power 
states
  * @next_fpwrst: cache of the powerdomain's next-power-state
+ * @prev_fpwrst: cache of the powerdomain's previous-power-state bitfield
  * @timer: sched_clock() timestamp of last pwrdm_state_switch()
  * @fpwrst_timer: estimated nanoseconds of residency in the various power 
states
  * @_lock: spinlock used to serialize powerdomain and some clockdomain ops
@@ -146,6 +156,9 @@ struct powerdomain;
  *
  * @prcm_partition possible values are defined in mach-omap2/prcm44xx.h.
  *
+ * @prev_fpwrst is updated during pwrdm_pre_transition(), but presumably
+ * should also be updated upon clock/IP block idle transitions.
+ *
  * Possible values for @_flags are documented above in the
  * "Powerdomain internal flags (struct powerdomain._flags)" comments.
  */
@@ -165,6 +178,7 @@ struct powerdomain {
const u8 prcm_partition;
u8 fpwrst;
u8 next_fpwrst;
+   u8 prev_fpwrst;
u8 _flags;
struct clockdomain *pwrdm_clkdms[PWRDM_MAX_CLKDMS];
struct list_head node;


--
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/12] ARM: OMAP2+: powerdomain: cache the powerdomain next power state

2012-12-09 Thread Paul Walmsley
Cache the powerdomain next power state registers.  The objective here
is to avoid unneeded reads and writes to the next power state
registers, which are slow compared to RAM & CPU cache.

Signed-off-by: Paul Walmsley 
Cc: Kevin Hilman 
---
 arch/arm/mach-omap2/powerdomain.c |   64 +
 arch/arm/mach-omap2/powerdomain.h |   17 ++
 2 files changed, 46 insertions(+), 35 deletions(-)

diff --git a/arch/arm/mach-omap2/powerdomain.c 
b/arch/arm/mach-omap2/powerdomain.c
index 62e2f75..425c868 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -376,7 +376,7 @@ static int _pwrdm_pwrst_to_fpwrst(struct powerdomain 
*pwrdm, u8 pwrst, u8 logic,
  * software-controllable, returns 0; otherwise, passes along the
  * return value from pwrdm_set_logic_retst() if there is an error
  * returned by that function, otherwise, passes along the return value
- * from pwrdm_set_next_pwrst()
+ * from pwrdm_set_next_fpwrst()
  */
 static int _set_logic_retst_and_pwrdm_pwrst(struct powerdomain *pwrdm,
u8 logic, u8 pwrst)
@@ -426,6 +426,9 @@ static int _pwrdm_read_next_fpwrst(struct powerdomain 
*pwrdm)
int next_pwrst, next_logic, ret;
u8 fpwrst;
 
+   if (pwrdm->_flags & _PWRDM_NEXT_FPWRST_IS_VALID)
+   return pwrdm->next_fpwrst;
+
next_pwrst = arch_pwrdm->pwrdm_read_next_pwrst(pwrdm);
if (next_pwrst < 0)
return next_pwrst;
@@ -438,6 +441,10 @@ static int _pwrdm_read_next_fpwrst(struct powerdomain 
*pwrdm)
return next_logic;
}
ret = _pwrdm_pwrst_to_fpwrst(pwrdm, next_pwrst, next_logic, &fpwrst);
+   if (!ret) {
+   pwrdm->next_fpwrst = fpwrst;
+   pwrdm->_flags |= _PWRDM_NEXT_FPWRST_IS_VALID;
+   }
 
return (ret) ? ret : fpwrst;
 }
@@ -663,7 +670,7 @@ static int _pwrdm_pre_transition_cb(struct powerdomain 
*pwrdm, void *unused)
  */
 static int _pwrdm_post_transition_cb(struct powerdomain *pwrdm, void *unused)
 {
-   int prev, next, fpwrst;
+   int prev, fpwrst;
int trace_state = 0;
 
prev = _pwrdm_read_prev_fpwrst(pwrdm);
@@ -676,10 +683,9 @@ static int _pwrdm_post_transition_cb(struct powerdomain 
*pwrdm, void *unused)
 * If the power domain did not hit the desired state,
 * generate a trace event with both the desired and hit states
 */
-   next = _pwrdm_read_next_fpwrst(pwrdm);
-   if (next != prev) {
-   trace_state = (PWRDM_TRACE_STATES_FLAG | next << 8 |
-  prev);
+   if (pwrdm->next_fpwrst != prev) {
+   trace_state = (PWRDM_TRACE_STATES_FLAG |
+  pwrdm->next_fpwrst << 8 | prev);
trace_power_domain_target(pwrdm->name, trace_state,
  smp_processor_id());
}
@@ -1256,6 +1262,10 @@ int pwrdm_set_next_fpwrst(struct powerdomain *pwrdm, u8 
fpwrst)
if (ret)
return ret;
 
+   if (pwrdm->_flags & _PWRDM_NEXT_FPWRST_IS_VALID &&
+   pwrdm->next_fpwrst == fpwrst)
+   return 0;
+
pr_debug("%s: set fpwrst %0x to pwrdm %s\n", __func__, fpwrst,
 pwrdm->name);
 
@@ -1264,6 +1274,10 @@ int pwrdm_set_next_fpwrst(struct powerdomain *pwrdm, u8 
fpwrst)
 
pwrdm_lock(pwrdm);
ret = _set_logic_retst_and_pwrdm_pwrst(pwrdm, logic, pwrst);
+   if (!ret) {
+   pwrdm->next_fpwrst = fpwrst;
+   pwrdm->_flags |= _PWRDM_NEXT_FPWRST_IS_VALID;
+   }
pwrdm_unlock(pwrdm);
 
return ret;
@@ -1279,36 +1293,16 @@ int pwrdm_set_next_fpwrst(struct powerdomain *pwrdm, u8 
fpwrst)
  */
 int pwrdm_read_next_fpwrst(struct powerdomain *pwrdm)
 {
-   int next_pwrst, next_logic, ret;
-   u8 fpwrst;
+   int ret;
 
-   if (!arch_pwrdm)
+   if (!pwrdm)
return -EINVAL;
 
pwrdm_lock(pwrdm);
-
-   next_pwrst = arch_pwrdm->pwrdm_read_next_pwrst(pwrdm);
-   if (next_pwrst < 0) {
-   ret = next_pwrst;
-   goto prnf_out;
-   }
-
-   next_logic = next_pwrst;
-   if (_pwrdm_logic_retst_can_change(pwrdm) &&
-   arch_pwrdm->pwrdm_read_logic_pwrst) {
-   next_logic = arch_pwrdm->pwrdm_read_logic_pwrst(pwrdm);
-   if (next_logic < 0) {
-   ret = next_logic;
-   goto prnf_out;
-   }
-   }
-
-   ret = _pwrdm_pwrst_to_fpwrst(pwrdm, next_pwrst, next_logic, &fpwrst);
-
-prnf_out:
+   ret = _pwrdm_read_next_fpwrst(pwrdm);
pwrdm_unlock(pwrdm);
 
-   return (ret) ? ret : fpwrst;
+   return ret;
 }
 
 /**
@@ -1344,10 +1338,6 @@ int pwrdm_set_fpwrst(struct powerdomain *pwrdm, enum 
pwrdm_func_state fpwrst)
 
pwrdm_lock(pwrdm);
 
-   /*
-* XXX quite heavyweight for what this is intended to

Re: [PATCH] ARM: OMAP4: Fix EMU clock domain always on

2012-12-09 Thread Paul Walmsley
Hi Jon,

On Fri, 7 Dec 2012, Jon Hunter wrote:

> Commit d043d87 (ARM: OMAP2+: clockdomain: bypass clockdomain handling
> when disabling unused clks) skips the decrementing of a clock-domains
> use count if the clocks use count is zero. However, for OMAP4 devices
> this is causing the EMU clock-domain to be stuck ON as the use count is
> not getting decremented correctly.

Thanks for the fix and the great patch description; queued for v3.8-rc.


- Paul
--
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/4] ARM: OMAP4: Clock fixes

2012-12-09 Thread Paul Walmsley
On Mon, 3 Dec 2012, Jon Hunter wrote:

> Fixes included, fixing up timer clock aliases for v3.8 and working
> around ABE DPLL issue seen with latest u-boot bootloader (v2012.10).
> 
> Testing includes:
> - Boot testing on OMAP4460 Panda and verifying that all dmtimers are
>   working.
> 
> V2 changes:
> - Updated series to latest ARM-SoC for-next branch that includes common
>   clock updates for OMAP4.
> - Added new function table for non-M4X DPLLs which is now required after
>   enhancing support for OMAP4 DPLLs for 4X multiplier.

Thanks, queued for 3.8-rc.


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


Testing the powerdomain changes

2012-12-09 Thread Paul Walmsley

Hi,

in case anyone is interested in trying out the recent powerdomain & PM 
changes, posted for 3.9, there's a temporary branch 
"TEST_pwrdm_post_fpwrst_devel_a_3.9" in the git tree 
git://git.pwsan.com/linux-2.6.  It's based on the PRCM cleanup branches 
for v3.7, plus some old regression workarounds needed since the base is 
v3.7-rc2.  Once 3.8 comes out, this branch will be rebased there ASAP, 
assuming we don't have another huge set of regressions...


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


About 1-Wire driver of OMAP4

2012-12-09 Thread herman516
Hi,

I implemented gas gauge driver by 1-Wire interface in OMAP4 CPU, the
driver we used is a GPIO pin to simulate 1-Wire bus but it sometimes can't
work well of timing issue. So we want to use HDQ/1Wire controller in OMAP4,
does anyone have experience of OMAP4 1-Wire driver of using its controller?
Our gas gauge is DS2780 and we use "android-omap-3.0" kernel branch. I
tried to do below steps but it still can't work. Or do you have any
suggestion? Thanks.

1. Add hwmod of hdq1w in omap_hwmod_44xx_data.c file
2. Use omap_hdq.c file
3. Select "CONFIG_HDQ_MASTER_OMAP", "CONFIG_W1", "CONFIG_HDQ_MASTER_OMAP"
and "CONFIG_BATTERY_DS2780" in menuconfig.


Regards,
Herman
--
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 v3 2/3] mtd: devices: elm: Add support for ELM error correction

2012-12-09 Thread Philip, Avinash
On Fri, Dec 07, 2012 at 16:07:23, Nori, Sekhar wrote:
> On 11/29/2012 5:16 PM, Philip, Avinash wrote:
> > The ELM hardware module can be used to speedup BCH 4/8/16 ECC scheme
> > error correction.
> > For now only 4 & 8 bit support is added
> > 
> > Signed-off-by: Philip, Avinash 
> > Cc: Grant Likely 
> > Cc: Rob Herring 
> > Cc: Rob Landley 

[...]
/**
> > + * elm_config - Configure ELM module
> > + * @info:  elm info
> > + */
> > +static void elm_config(struct elm_info *info)
> 
> This is called "config", but there is no configuration information
> passed which looks odd..

The config information is bch_type, encapsulated in struct elm_info.

> 
> > +{
> > +   u32 reg_val;
> > +
> > +   reg_val = (info->bch_type & ECC_BCH_LEVEL_MASK) | (ELM_ECC_SIZE << 16);
> > +   elm_write_reg(info, ELM_LOCATION_CONFIG, reg_val);
> > +}
> 
> Is there a use case where BCH type needs to be changed after NAND has
> been probed?

No, I think kernel handles the entire NAND part with a single ecc layout.
Hence there is no run time BCH switching. But ELM driver should support BCH
4 & 8. Selection of BCH information comes from DT of NAND driver.

As NAND driver supporting BCH4 & 8 ecc scheme ELM module support
configuration of both.  Configuration of ELM module should done as part
of NAND driver probing.


> You will have to erase any existing data written to NAND if
> you change the ECC type. That sounds destructive enough to avoid such a
> thing.

There is no support for BCH switching after NAND driver probing.

[...]
> > +struct device *elm_request(enum bch_ecc bch_type)
> > +{
> > +   struct elm_info *info;
> > +
> > +   list_for_each_entry(info, &elm_devices, list) {
> > +   if (info && info->dev) {
> > +   info->bch_type = bch_type;
> > +   elm_config(info);
> > +   return info->dev;
> > +   }
> > +   }
> 
> This will always return the first ELM device probed since you never
> remove the allocated device from the list.

But now I realized that, there is no mechanism of freeing the requested
resource.

So I will add mechanism to request ELM module successfully only if ELM
module is not requested already and add mechanism to free it, on NAND
driver module unload (loadable module support). This way ELM driver
can achieve multi instance support.

> I wonder why you really need a list?

The prime motivation for the list is the driver should support multi
instances of ELM by removing global symbols.

Thanks
Avinash

> 
> Thanks,
> Sekhar
> 

N�r��yb�X��ǧv�^�)޺{.n�+{��f��{ay�ʇڙ�,j��f���h���z��w���
���j:+v���w�j�mzZ+�ݢj"��!�i

RE: [PATCH v3 1/3] mtd: nand: omap2: Update nerrors using ecc.strength

2012-12-09 Thread Philip, Avinash
On Fri, Dec 07, 2012 at 16:10:04, Nori, Sekhar wrote:
> On 12/5/2012 6:13 PM, Philip, Avinash wrote:
> > On Wed, Dec 05, 2012 at 17:33:37, Nori, Sekhar wrote:
> >> Hi Avinash,
> >>
> >> On 11/29/2012 5:16 PM, Philip, Avinash wrote:
> >>> Update number of errors using nand ecc strength.
> >>> Also add macro definitions BCH8_ERROR_MAX & BCH4_ERROR_MAX
> >>
> >> Can you please describe why the original method of setting nerrors was
> >> incorrect? Was it causing any issues in any particular configuration?
> > 
> > It affects the reusability of the code. For example BCH8 with AM335x RBL 
> > compatibility requires  14 bytes instead of 13 byte. So setting nerrors
> > with
> > nerrors = (info->nand.ecc.bytes == 13) ? 8 : 4;
> > will break am335x RBL compatibility.
> 
> This should be summarized in the patch description so the motivation is
> clear to those who read the history later.

Ok I will add the details in patch description in next version.

Thanks
Avinash

> 
> Thanks,
> Sekhar
> 



RE: [rtc-linux] [PATCH v3 1/5] rtc: OMAP: Add system pm_power_off to rtc driver

2012-12-09 Thread AnilKumar, Chimata
On Wed, Nov 28, 2012 at 16:42:26, Russell King - ARM Linux wrote:
> On Tue, Nov 27, 2012 at 03:42:39PM -0800, Andrew Morton wrote:
> > > + /* Do not allow to execute any other task */
> > > + spin_lock_irqsave(&lock, flags);
> > > + while (1);
> > 
> > I suspect this doesn't do what you want it to do.
> > 
> > Firstly, please provide adequate code comments here so that code
> > readers do not also need to be mind readers.
> > 
> > If you want to stop this CPU dead in its tracks (why?) then
> > 
> > local_irq_disable();
> > while (1)
> > ;   /* Note correct code layout */
> > 
> > will do it.  But it means that the NMI watchdog (if present) will come
> > along and whack the machine in the head a few seconds later.  And this
> > does nothing to stop other CPUs.
> > 
> > But not being a mind reader, I'm really at a loss to suggest what
> > should be done here.  

Here intention is to disable all interrupts between rtc power_off request
till system actually went to power off mode, max 2 seconds based on when
the AM335x RTC alarm2 expires. The idea was that since the system is
going to shutdown, it is better to not process any more interrupts.

> It's hooking into the pm_power_off hook, which is called from kernel/sys.c
> via arch code.  We will have already stopped all other CPUs at this point.
> 
> Why there's that while (1) there I don't know; when pm_power_off is not
> hooked, we don't do anything like that - and what will happen in that
> case is we'll return all the way back to sys_reboot(), which will call
> do_exit(0) on us.

When testing with v3.7-rc7, I saw the following BUG() triggered when I did
not use a while(1). Logs below.

Before calling do_exit(0), there is a reboot_mutex lock that is taken in
reboot syscall. do_exit() function is , checking for any locks held by the
processor and if yes then it is printing a BUG_ON from print_held_locks_bug() 
function along with the locks held information.
Even though the BUG triggers, the system is going to power off because
The hardware has been triggered.

 (log)
[root@arago /]# poweroff
The system is going down NOW!
Sent SIGTERM to all processes
Sent SIGKILL to all processes
Requesting system poweroff
[   32.125900] Disabling non-boot CPUs ...
[   32.130155] Power down.
[   32.132741] System will go to power_off state in approx. 2 secs
[   32.139994]
[   32.141575] =
[   32.146564] [ BUG: lock held at task exit time! ]
[   32.151522] 3.7.0-rc7-00015-g3f8bbe0 #32 Not tainted
[   32.156721] -
[   32.161676] init/622 is exiting with locks still held!
[   32.167085] 1 lock held by init/622:
[   32.170831]  #0:  (reboot_mutex){+.+...}, at: [] 
sys_reboot+0xf4/0x1e8
[   32.178679]
[   32.178679] stack backtrace:
[   32.183305] [] (unwind_backtrace+0x0/0xf0) from [] 
(do_exit+0x488/0x7e8)
[   32.192183] [] (do_exit+0x488/0x7e8) from [] 
(sys_reboot+0x100/0x1e8)
[   32.200797] [] (sys_reboot+0x100/0x1e8) from [] 
(ret_fast_syscall+0x0/0x3c)
=

It is not clear to me where reboot_mutex should have been unlocked before
debug_check_no_locks_held() is called in do_exit()?

Note: In latest linux-next tip I am *not* seeing this error. I have not
bisected yet to see what fixed this. Since with latest linux-next I am
not seeing an issue, I will remove spinlock and the while(1). Hope that
will make the patch more acceptable.

> I don't see a problem with that, and I don't see why we need to spin
> (without any power saving too) waiting for some event.  If we've called
> sys_reboot with LINUX_REBOOT_CMD_POWER_OFF, we'd better have already
> killed most of userspace off by that time anyway.
> 

I did a search of various power-off implementations in *arch/arm*.

Those that use a while(1):
=
arch/arm/mach-at91/board-gsia18s.c
arch/arm/mach-at91/setup.c doesn't
arch/arm/mach-cns3xxx/cns3420vb.c
arch/arm/mach-iop32x/glantank.c
arch/arm/mach-iop32x/iq31244.c
arch/arm/mach-iop32x/n2100.c local_irq_disable() and then a while(1)
arch/arm/mach-kirkwood/board-lsxl.c

arch/arm/mach-highbank/highbank.c does while(1) cpu_do_idle()

Those that don't have a while(1):

arch/arm/mach-imx/mach-mx31moboard.c
arch/arm/mach-iop32x/em7210.c

Doesn't have a while(1) but setting a gpio so presumably kills the system 
immediately:
===
arch/arm/mach-ixp4xx/dsmg600-setup.c  
arch/arm/mach-ixp4xx/nas100d-setup.c
arch/arm/mach-ixp4xx/nslu2-setup.c
arch/arm/mach-kirkwood/board-dnskw.c
arch/arm/mach-kirkwood/board-ib62x0.c
arch/arm/mach-kirkwood/board-dnskw.c
arch/arm/mach-kirkwood/board-ib62x0.c
arch/arm/mach-kirkwood/d2net_v2-setup.c
arch/arm/mach-kirkwood/netspace_v2-setup.c
arch/arm/mach-kirkwood/netxbig_v2-setup.c
arch/arm/mach-kirkwood/t5325-setup.c
arch/arm/mach-orion5x/dns323-setup.c

arch/arm/mach-vexpress/v2m.c take a spinlock, not sure when it will shut down

arch/arm/mach-kirkwood/board-ts219.c sends a character to PIC 

[PATCH 0/9] memory: emif: miscellaneous bug fixes for EMIF driver

2012-12-09 Thread Lokesh Vutla
This series resolves a few minor issues for EMIF driver.

Tested all the patches on OMAP4-sdp, OMAP5-sevm.
Patch : "memory: emif: setup LP settings on freq update"
is tested on a local tree, since freq update cannot be
tested on mainline.

Ambresh K (1):
  memory: emif: use default custom config parameter.

Lokesh Vutla (1):
  memory: emif: Correct the lpmode timeout calculation

Nishanth Menon (5):
  memory: emif: setup LP settings on freq update
  memory: emif: handle overflow for timing for LP mode
  memory: emif: Handle devices which are not rated for >85C
  memory: emif: use restart if power_off not present when out of spec
  memory: emif: disable phy_fast_dll_lock

Oleksandr Dmytryshyn (1):
  memory: emif: fix timings initialization issue

Severine Glock (1):
  memory: emif: debugfs: Remove MR4= string print

 drivers/memory/emif.c   |   92 +--
 drivers/memory/emif.h   |2 +-
 include/linux/platform_data/emif_plat.h |1 +
 3 files changed, 78 insertions(+), 17 deletions(-)

-- 
1.7.9.5

--
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/9] memory: emif: setup LP settings on freq update

2012-12-09 Thread Lokesh Vutla
From: Nishanth Menon 

Program the power management shadow register on freq update
else the concept of threshold frequencies dont really matter
as the system always uses the performance mode timing for LP
which is programmed in at init time.

Signed-off-by: Nishanth Menon 
---
 drivers/memory/emif.c |5 +
 1 file changed, 5 insertions(+)

diff --git a/drivers/memory/emif.c b/drivers/memory/emif.c
index 8589aba..69a480d 100644
--- a/drivers/memory/emif.c
+++ b/drivers/memory/emif.c
@@ -815,6 +815,11 @@ static void setup_registers(struct emif_data *emif, struct 
emif_regs *regs)
writel(regs->sdram_tim2_shdw, base + EMIF_SDRAM_TIMING_2_SHDW);
writel(regs->phy_ctrl_1_shdw, base + EMIF_DDR_PHY_CTRL_1_SHDW);
 
+   if (emif->lpmode != EMIF_LP_MODE_DISABLE) {
+   writel(regs->pwr_mgmt_ctrl_shdw,
+  base + EMIF_POWER_MANAGEMENT_CTRL_SHDW);
+   }
+
/* Settings specific for EMIF4D5 */
if (emif->plat_data->ip_rev != EMIF_4D5)
return;
-- 
1.7.9.5

--
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 6/9] memory: emif: debugfs: Remove MR4= string print

2012-12-09 Thread Lokesh Vutla
From: Severine Glock 

MR4 is reported under debugfs with following format MR4=%d.
Remove MR4= string for better convenience.

Signed-off-by: Severine Glock 
---
 drivers/memory/emif.c |2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/memory/emif.c b/drivers/memory/emif.c
index 625732d..32ce601 100644
--- a/drivers/memory/emif.c
+++ b/drivers/memory/emif.c
@@ -147,7 +147,7 @@ static int emif_mr4_show(struct seq_file *s, void *unused)
 {
struct emif_data *emif = s->private;
 
-   seq_printf(s, "MR4=%d\n", emif->temperature_level);
+   seq_printf(s, "%d\n", emif->temperature_level);
return 0;
 }
 
-- 
1.7.9.5

--
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 8/9] memory: emif: fix timings initialization issue

2012-12-09 Thread Lokesh Vutla
From: Oleksandr Dmytryshyn 

The issue was that only the first timings table was added to the
emif platform data at the emif driver registration. All other
timings tables was filled with zeros. Now all emif timings table
are added to the platform data.

Signed-off-by: Oleksandr Dmytryshyn 
---
 drivers/memory/emif.c |2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/memory/emif.c b/drivers/memory/emif.c
index 32ce601..70f6e0f 100644
--- a/drivers/memory/emif.c
+++ b/drivers/memory/emif.c
@@ -1462,7 +1462,7 @@ static struct emif_data *__init_or_module 
get_device_details(
if (pd->timings) {
temp = devm_kzalloc(dev, size, GFP_KERNEL);
if (temp) {
-   memcpy(temp, pd->timings, sizeof(*pd->timings));
+   memcpy(temp, pd->timings, size);
pd->timings = temp;
} else {
dev_warn(dev, "%s:%d: allocation error\n", __func__,
-- 
1.7.9.5

--
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/9] memory: emif: Correct the lpmode timeout calculation

2012-12-09 Thread Lokesh Vutla
The driver tries to round up the specified timeout cycles to
next power of 2 value. But this is done wrongly.
Correcting this here.

Signed-off-by: Lokesh Vutla 
---
 drivers/memory/emif.c |4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/memory/emif.c b/drivers/memory/emif.c
index 06d31c9..8589aba 100644
--- a/drivers/memory/emif.c
+++ b/drivers/memory/emif.c
@@ -731,9 +731,9 @@ static u32 get_pwr_mgmt_ctrl(u32 freq, struct emif_data 
*emif, u32 ip_rev)
if (timeout < 16) {
timeout = 0;
} else {
-   timeout = __fls(timeout) - 3;
if (timeout & (timeout - 1))
-   timeout++;
+   timeout <<= 1;
+   timeout = __fls(timeout) - 3;
}
 
switch (lpmode) {
-- 
1.7.9.5

--
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/9] memory: emif: disable phy_fast_dll_lock

2012-12-09 Thread Lokesh Vutla
From: Nishanth Menon 

As per OMAP5 TRM, phy_fast_dll_lock is meant for simulations only.
'0' is supposed to be used for normal operations. So, use 0.

Signed-off-by: Nishanth Menon 
---
 drivers/memory/emif.h |2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/memory/emif.h b/drivers/memory/emif.h
index bfe08ba..574fdfb 100644
--- a/drivers/memory/emif.h
+++ b/drivers/memory/emif.h
@@ -82,7 +82,7 @@
 #define EMIF_DLL_SLAVE_DLY_CTRL_100_MHZ_AND_LESS_ATTILAPHY 0xFF
 
 /* DDR_PHY_CTRL_1 values for EMIF4D5 INTELLIPHY combination */
-#define EMIF_DDR_PHY_CTRL_1_BASE_VAL_INTELLIPHY0x0E084200
+#define EMIF_DDR_PHY_CTRL_1_BASE_VAL_INTELLIPHY0x0E084000
 #define EMIF_PHY_TOTAL_READ_LATENCY_INTELLIPHY_PS  1
 
 /* TEMP_ALERT_CONFIG - corresponding to temp gradient 5 C/s */
-- 
1.7.9.5

--
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/9] memory: emif: handle overflow for timing for LP mode

2012-12-09 Thread Lokesh Vutla
From: Nishanth Menon 

In case the custom timings provide values which overflow
the maximum possible field value, warn and use maximum
permissible value.

Signed-off-by: Nishanth Menon 
---
 drivers/memory/emif.c |   36 
 1 file changed, 28 insertions(+), 8 deletions(-)

diff --git a/drivers/memory/emif.c b/drivers/memory/emif.c
index 69a480d..27a3ce1 100644
--- a/drivers/memory/emif.c
+++ b/drivers/memory/emif.c
@@ -714,6 +714,8 @@ static u32 get_pwr_mgmt_ctrl(u32 freq, struct emif_data 
*emif, u32 ip_rev)
u32 timeout_perf= EMIF_LP_MODE_TIMEOUT_PERFORMANCE;
u32 timeout_pwr = EMIF_LP_MODE_TIMEOUT_POWER;
u32 freq_threshold  = EMIF_LP_MODE_FREQ_THRESHOLD;
+   u32 mask;
+   u8 shift;
 
struct emif_custom_configs *cust_cfgs = emif->plat_data->custom_configs;
 
@@ -738,27 +740,45 @@ static u32 get_pwr_mgmt_ctrl(u32 freq, struct emif_data 
*emif, u32 ip_rev)
 
switch (lpmode) {
case EMIF_LP_MODE_CLOCK_STOP:
-   pwr_mgmt_ctrl = (timeout << CS_TIM_SHIFT) |
-   SR_TIM_MASK | PD_TIM_MASK;
+   shift = CS_TIM_SHIFT;
+   mask = CS_TIM_MASK;
break;
case EMIF_LP_MODE_SELF_REFRESH:
/* Workaround for errata i735 */
if (timeout < 6)
timeout = 6;
 
-   pwr_mgmt_ctrl = (timeout << SR_TIM_SHIFT) |
-   CS_TIM_MASK | PD_TIM_MASK;
+   shift = SR_TIM_SHIFT;
+   mask = SR_TIM_MASK;
break;
case EMIF_LP_MODE_PWR_DN:
-   pwr_mgmt_ctrl = (timeout << PD_TIM_SHIFT) |
-   CS_TIM_MASK | SR_TIM_MASK;
+   shift = PD_TIM_SHIFT;
+   mask = PD_TIM_MASK;
break;
case EMIF_LP_MODE_DISABLE:
default:
-   pwr_mgmt_ctrl = CS_TIM_MASK |
-   PD_TIM_MASK | SR_TIM_MASK;
+   mask = 0;
+   shift = 0;
+   break;
+   }
+   /* Round to maximum in case of overflow, BUT warn! */
+   if (lpmode != EMIF_LP_MODE_DISABLE && timeout > mask >> shift) {
+   pr_err("TIMEOUT Overflow - lpmode=%d perf=%d pwr=%d freq=%d\n",
+  lpmode,
+  timeout_perf,
+  timeout_pwr,
+  freq_threshold);
+   WARN(1, "timeout=0x%02x greater than 0x%02x. Using max\n",
+timeout, mask >> shift);
+   timeout = mask >> shift;
}
 
+   /* Setup required timing */
+   pwr_mgmt_ctrl = (timeout << shift) & mask;
+   /* setup a default mask for rest of the modes */
+   pwr_mgmt_ctrl |= (SR_TIM_MASK | CS_TIM_MASK | PD_TIM_MASK) &
+ ~mask;
+
/* No CS_TIM in EMIF_4D5 */
if (ip_rev == EMIF_4D5)
pwr_mgmt_ctrl &= ~CS_TIM_MASK;
-- 
1.7.9.5

--
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 4/9] memory: emif: Handle devices which are not rated for >85C

2012-12-09 Thread Lokesh Vutla
From: Nishanth Menon 

As per JESD209-2E specification for LPDDR2,
  http://www.jedec.org/standards-documents/results/jesd209-2E
Table 73, LPDDR2 memories come in two flavors - Standard and
Extended. The Standard types can operate from -25C to +85C
However, beyond that and upto +105C can only be supported by
Extended types.

Unfortunately, it seems there is no info in MR0(device info) or
MR[1,2](device feature) for run time detection of this capability
as far as seen on the spec. Hence, we provide a custom_config
flag to be populated by platforms which have these "extended"
type memories.

For the "Standard" memories, we need to consider MR4 notifications
of temperature triggers >85C as equivalent to thermal shutdown
events (equivalent to Spec specified thermal shutdown events for
"extended" parts).

Reported-by: Richard Woodruff 
Signed-off-by: Nishanth Menon 
---
 drivers/memory/emif.c   |   24 
 include/linux/platform_data/emif_plat.h |1 +
 2 files changed, 25 insertions(+)

diff --git a/drivers/memory/emif.c b/drivers/memory/emif.c
index 27a3ce1..ffbdf9e 100644
--- a/drivers/memory/emif.c
+++ b/drivers/memory/emif.c
@@ -916,6 +916,7 @@ static irqreturn_t handle_temp_alert(void __iomem *base, 
struct emif_data *emif)
 {
u32 old_temp_level;
irqreturn_t ret = IRQ_HANDLED;
+   struct emif_custom_configs *custom_configs;
 
spin_lock_irqsave(&emif_lock, irq_state);
old_temp_level = emif->temperature_level;
@@ -928,6 +929,29 @@ static irqreturn_t handle_temp_alert(void __iomem *base, 
struct emif_data *emif)
goto out;
}
 
+   custom_configs = emif->plat_data->custom_configs;
+
+   /*
+* IF we detect higher than "nominal rating" from DDR sensor
+* on an unsupported DDR part, shutdown system
+*/
+   if (custom_configs && !(custom_configs->mask &
+   EMIF_CUSTOM_CONFIG_EXTENDED_TEMP_PART)) {
+   if (emif->temperature_level >= SDRAM_TEMP_HIGH_DERATE_REFRESH) {
+   dev_err(emif->dev,
+   "%s:NOT Extended temperature capable memory."
+   "Converting MR4=0x%02x as shutdown event\n",
+   __func__, emif->temperature_level);
+   /*
+* Temperature far too high - do kernel_power_off()
+* from thread context
+*/
+   emif->temperature_level = SDRAM_TEMP_VERY_HIGH_SHUTDOWN;
+   ret = IRQ_WAKE_THREAD;
+   goto out;
+   }
+   }
+
if (emif->temperature_level < old_temp_level ||
emif->temperature_level == SDRAM_TEMP_VERY_HIGH_SHUTDOWN) {
/*
diff --git a/include/linux/platform_data/emif_plat.h 
b/include/linux/platform_data/emif_plat.h
index 03378ca..5c19a2a 100644
--- a/include/linux/platform_data/emif_plat.h
+++ b/include/linux/platform_data/emif_plat.h
@@ -40,6 +40,7 @@
 /* Custom config requests */
 #define EMIF_CUSTOM_CONFIG_LPMODE  0x0001
 #define EMIF_CUSTOM_CONFIG_TEMP_ALERT_POLL_INTERVAL0x0002
+#define EMIF_CUSTOM_CONFIG_EXTENDED_TEMP_PART  0x0004
 
 #ifndef __ASSEMBLY__
 /**
-- 
1.7.9.5

--
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/9] memory: emif: use restart if power_off not present when out of spec

2012-12-09 Thread Lokesh Vutla
From: Nishanth Menon 

Some machine or kernel variants might have missed implementation
of power off handlers. We DONOT want to let the system be in
"out of spec" state in this condition. So, WARN and attempt
a machine restart in the hopes of clearing the out-of-spec
temperature condition.

NOTE: This is not the safest option, but safer than leaving the
system in unstable conditions.

Signed-off-by: Nishanth Menon 
---
 drivers/memory/emif.c |9 -
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/memory/emif.c b/drivers/memory/emif.c
index ffbdf9e..625732d 100644
--- a/drivers/memory/emif.c
+++ b/drivers/memory/emif.c
@@ -24,6 +24,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include "emif.h"
 #include "of_memory.h"
@@ -1013,7 +1014,13 @@ static irqreturn_t emif_threaded_isr(int irq, void 
*dev_id)
 
if (emif->temperature_level == SDRAM_TEMP_VERY_HIGH_SHUTDOWN) {
dev_emerg(emif->dev, "SDRAM temperature exceeds operating 
limit.. Needs shut down!!!\n");
-   kernel_power_off();
+   /* If we have Power OFF ability, use it, else try restarting */
+   if (pm_power_off) {
+   kernel_power_off();
+   } else {
+   WARN(1, "FIXME: NO pm_power_off!!! trying restart\n");
+   kernel_restart("SDRAM Over-temp Emergency restart");
+   }
return IRQ_HANDLED;
}
 
-- 
1.7.9.5

--
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 9/9] memory: emif: use default custom config parameter.

2012-12-09 Thread Lokesh Vutla
From: Ambresh K 

In-case of low power mode selected and custom parameters
are not configured, then use default configuration.

Signed-off-by: Ambresh K 
---
 drivers/memory/emif.c |   10 +++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/drivers/memory/emif.c b/drivers/memory/emif.c
index 70f6e0f..e58fde4 100644
--- a/drivers/memory/emif.c
+++ b/drivers/memory/emif.c
@@ -722,9 +722,13 @@ static u32 get_pwr_mgmt_ctrl(u32 freq, struct emif_data 
*emif, u32 ip_rev)
 
if (cust_cfgs && (cust_cfgs->mask & EMIF_CUSTOM_CONFIG_LPMODE)) {
lpmode  = cust_cfgs->lpmode;
-   timeout_perf= cust_cfgs->lpmode_timeout_performance;
-   timeout_pwr = cust_cfgs->lpmode_timeout_power;
-   freq_threshold  = cust_cfgs->lpmode_freq_threshold;
+
+   if (cust_cfgs->lpmode_timeout_performance)
+   timeout_perf= cust_cfgs->lpmode_timeout_performance;
+   if (cust_cfgs->lpmode_timeout_power)
+   timeout_pwr = cust_cfgs->lpmode_timeout_power;
+   if (cust_cfgs->lpmode_freq_threshold)
+   freq_threshold  = cust_cfgs->lpmode_freq_threshold;
}
 
/* Timeout based on DDR frequency */
-- 
1.7.9.5

--
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/9] memory: emif: miscellaneous bug fixes for EMIF driver

2012-12-09 Thread Lokesh Vutla

Sorry to Spam you in-box.
Please discard this message...

Thanks
Lokesh

On Monday 10 December 2012 12:38 PM, a...@dbdp33.itg.ti.com wrote:

From: Lokesh Vutla 

This series resolves a few minor issues for EMIF driver.

Tested all the patches on OMAP4-sdp, OMAP5-sevm.
Patch : "memory: emif: setup LP settings on freq update"
is tested on a local tree, since freq update cannot be
tested on mainline.

Ambresh K (1):
   memory: emif: use default custom config parameter.

Lokesh Vutla (1):
   memory: emif: Correct the lpmode timeout calculation

Nishanth Menon (5):
   memory: emif: setup LP settings on freq update
   memory: emif: handle overflow for timing for LP mode
   memory: emif: Handle devices which are not rated for >85C
   memory: emif: use restart if power_off not present when out of spec
   memory: emif: disable phy_fast_dll_lock

Oleksandr Dmytryshyn (1):
   memory: emif: fix timings initialization issue

Severine Glock (1):
   memory: emif: debugfs: Remove MR4= string print

  drivers/memory/emif.c   |   92 +--
  drivers/memory/emif.h   |2 +-
  include/linux/platform_data/emif_plat.h |1 +
  3 files changed, 78 insertions(+), 17 deletions(-)



--
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/5] OMAPFB: connect ovl managers to all dssdevs

2012-12-09 Thread Archit Taneja

Hi,

On Friday 07 December 2012 05:25 PM, Tomi Valkeinen wrote:

Commit 5d89bcc341771d95e3a2996218e5949a6627f59e (OMAPDSS: remove initial
display code from omapdss) moved setting up the initial overlay, overlay
manager, output and display connections from omapdss to omapfb.

However, currently omapfb only handles the connection related to the
default display, which means that no overlay managers are connected to
other displays.

This patch changes omapfb to go through all dssdevs, and connect an
overlay manager to them.

Signed-off-by: Tomi Valkeinen 
---
  drivers/video/omap2/omapfb/omapfb-main.c |   38 +++---
  1 file changed, 24 insertions(+), 14 deletions(-)

diff --git a/drivers/video/omap2/omapfb/omapfb-main.c 
b/drivers/video/omap2/omapfb/omapfb-main.c
index 1df973e..24739fc 100644
--- a/drivers/video/omap2/omapfb/omapfb-main.c
+++ b/drivers/video/omap2/omapfb/omapfb-main.c
@@ -2353,27 +2353,37 @@ static int omapfb_init_display(struct omapfb2_device 
*fbdev,
  }

  static int omapfb_init_connections(struct omapfb2_device *fbdev,
-   struct omap_dss_device *dssdev)
+   struct omap_dss_device *def_dssdev)
  {
int i, r;
-   struct omap_overlay_manager *mgr = NULL;
+   struct omap_overlay_manager *mgr;

-   for (i = 0; i < fbdev->num_managers; i++) {
-   mgr = fbdev->managers[i];
-
-   if (dssdev->channel == mgr->id)
-   break;
+   if (!def_dssdev->output) {
+   dev_err(fbdev->dev, "no output for the default display\n");
+   return -EINVAL;
}

-   if (i == fbdev->num_managers)
-   return -ENODEV;
+   for (i = 0; i < fbdev->num_displays; ++i) {
+   struct omap_dss_device *dssdev = fbdev->displays[i].dssdev;
+   struct omap_dss_output *out = dssdev->output;

-   if (mgr->output)
-   mgr->unset_output(mgr);
+   mgr = omap_dss_get_overlay_manager(dssdev->channel);


This dssdev->channel reference is something we would want to get rid of 
eventually, right?


At the point omapfb_init_connections() is called, we would have all the 
omap_dss_devices registered, right? So at this point, omapfb will have 
an overall view of how the panels need to be connected to DSS.


I think we can try to find a manager here for dssdev rather than using 
dssdev->channel directly. The dssdev's output could connect to a few 
managers. We would want to chose managers for each dssdev output in such 
a way that all outputs have a manager. I guess there would be multiple 
combinations for this, but it would be okay to pick any one of them.


I think we would need some recursive or backtracking sort of approach to 
get a desired combination. We can figure about how to make it work 
later, but do you agree if this is a right way to get rid of 
dssdev->channel?


Also, we would need to do this for omapdrm separately using it's own 
encoder/connector entities.


Archit



-   r = mgr->set_output(mgr, dssdev->output);
-   if (r)
-   return r;
+   if (!mgr || !out)
+   continue;
+
+   if (mgr->output)
+   mgr->unset_output(mgr);
+
+   mgr->set_output(mgr, out);
+   }
+
+   mgr = def_dssdev->output->manager;
+
+   if (!mgr) {
+   dev_err(fbdev->dev, "no ovl manager for the default display\n");
+   return -EINVAL;
+   }

for (i = 0; i < fbdev->num_overlays; i++) {
struct omap_overlay *ovl = fbdev->overlays[i];



--
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/1] net: ethernet: davinci_cpdma: Add boundary for rx and tx descriptors

2012-12-09 Thread Mugunthan V N
When there is heavy transmission traffic in the CPDMA, then Rx descriptors
memory is also utilized as tx desc memory this leads to reduced rx desc memory
which leads to poor performance.

This patch adds boundary for tx and rx descriptors in bd ram dividing the
descriptor memory to ensure that during heavy transmission tx doesn't use
rx descriptors.

This patch is already applied to davinci_emac driver, since CPSW and
davici_dmac uses the same CPDMA, moving the boundry seperation from
Davinci EMAC driver to CPDMA driver which was done in the following
commit

commit 86d8c07ff2448eb4e860e50f34ef6ee78e45c40c
Author: Sascha Hauer 
Date:   Tue Jan 3 05:27:47 2012 +

net/davinci: do not use all descriptors for tx packets

The driver uses a shared pool for both rx and tx descriptors.
During open it queues fixed number of 128 descriptors for receive
packets. For each received packet it tries to queue another
descriptor. If this fails the descriptor is lost for rx.
The driver has no limitation on tx descriptors to use, so it
can happen during a nmap / ping -f attack that the driver
allocates all descriptors for tx and looses all rx descriptors.
The driver stops working then.
To fix this limit the number of tx descriptors used to half of
the descriptors available, the rx path uses the other half.

Tested on a custom board using nmap / ping -f to the board from
two different hosts.

Signed-off-by: Mugunthan V N 
---
 drivers/net/ethernet/ti/davinci_cpdma.c |   20 ++--
 drivers/net/ethernet/ti/davinci_emac.c  |8 
 2 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/drivers/net/ethernet/ti/davinci_cpdma.c 
b/drivers/net/ethernet/ti/davinci_cpdma.c
index 4995673..d37f546 100644
--- a/drivers/net/ethernet/ti/davinci_cpdma.c
+++ b/drivers/net/ethernet/ti/davinci_cpdma.c
@@ -105,13 +105,13 @@ struct cpdma_ctlr {
 };
 
 struct cpdma_chan {
+   struct cpdma_desc __iomem   *head, *tail;
+   void __iomem*hdp, *cp, *rxfree;
enum cpdma_statestate;
struct cpdma_ctlr   *ctlr;
int chan_num;
spinlock_t  lock;
-   struct cpdma_desc __iomem   *head, *tail;
int count;
-   void __iomem*hdp, *cp, *rxfree;
u32 mask;
cpdma_handler_fnhandler;
enum dma_data_direction dir;
@@ -217,7 +217,7 @@ desc_from_phys(struct cpdma_desc_pool *pool, dma_addr_t dma)
 }
 
 static struct cpdma_desc __iomem *
-cpdma_desc_alloc(struct cpdma_desc_pool *pool, int num_desc)
+cpdma_desc_alloc(struct cpdma_desc_pool *pool, int num_desc, bool is_rx)
 {
unsigned long flags;
int index;
@@ -225,8 +225,14 @@ cpdma_desc_alloc(struct cpdma_desc_pool *pool, int 
num_desc)
 
spin_lock_irqsave(&pool->lock, flags);
 
-   index = bitmap_find_next_zero_area(pool->bitmap, pool->num_desc, 0,
-  num_desc, 0);
+   if (is_rx) {
+   index = bitmap_find_next_zero_area(pool->bitmap,
+   pool->num_desc/2, 0, num_desc, 0);
+} else {
+   index = bitmap_find_next_zero_area(pool->bitmap,
+   pool->num_desc, pool->num_desc/2, num_desc, 0);
+   }
+
if (index < pool->num_desc) {
bitmap_set(pool->bitmap, index, num_desc);
desc = pool->iomap + pool->desc_size * index;
@@ -660,6 +666,7 @@ int cpdma_chan_submit(struct cpdma_chan *chan, void *token, 
void *data,
unsigned long   flags;
u32 mode;
int ret = 0;
+   boolis_rx;
 
spin_lock_irqsave(&chan->lock, flags);
 
@@ -668,7 +675,8 @@ int cpdma_chan_submit(struct cpdma_chan *chan, void *token, 
void *data,
goto unlock_ret;
}
 
-   desc = cpdma_desc_alloc(ctlr->pool, 1);
+   is_rx = (chan->rxfree != 0);
+   desc = cpdma_desc_alloc(ctlr->pool, 1, is_rx);
if (!desc) {
chan->stats.desc_alloc_fail++;
ret = -ENOMEM;
diff --git a/drivers/net/ethernet/ti/davinci_emac.c 
b/drivers/net/ethernet/ti/davinci_emac.c
index fce89a0..f349273 100644
--- a/drivers/net/ethernet/ti/davinci_emac.c
+++ b/drivers/net/ethernet/ti/davinci_emac.c
@@ -120,7 +120,6 @@ static const char emac_version_string[] = "TI DaVinci EMAC 
Linux v6.1";
 #define EMAC_DEF_TX_CH (0) /* Default 0th channel */
 #define EMAC_DEF_RX_CH (0) /* Default 0th channel */
 #define EMAC_DEF_RX_NUM_DESC   (128)
-#define EMAC_DEF_TX_NUM_DESC   (128)
 #define EMAC_DEF_MAX_TX_CH (1) /* Max TX channels configured */
 #define EMAC_DEF_MAX_RX_CH (1) /* Max RX