Skip to contentSkip to conversation

ARM: OMAP2+: second set of PM fixes and cleanup for 3.9

PATCH New Paul Walmsley 7 participants 28 messages Dec 9, 2012 – Jan 29, 2013

Subsystems (6)
lore
Share & tools
lore

Paul Walmsley

author maintainer
#0 lore raw

cover ARM: OMAP2+: second set of PM fixes and cleanup for 3.9

Several more OMAP2+ power management fixes, optimizations, and cleanup, intended for 3.9. This series is also a prerequisite for the functional powerdomain conversion series.

I'll plan to bundle these patches together into a pull request with the first set of 3.9 PM patches, sent earlier.

- Paul

---

vmlinux object size
(delta in bytes from TEST_pm_cleanup_fixes_a_3.9 (8f5e20850396fc60fd4ee01f586705033902bb53)):

   text     data      bss    total  kernel
   +460     -368        0      +92  am33xx_only
   +200     -464        0     -264  n800_multi_omap2xxx
   +192     -144        0      +48  n800_only_a
      0        0        0        0  omap1_defconfig
      0        0        0        0  omap1_defconfig_1510innovator_only
      0        0        0        0  omap1_defconfig_5912osk_only
   +296    -1816        0    -1520  omap2plus_defconfig
   +272     -176        0      +96  omap2plus_defconfig_2430sdp_only
   +232    -1816        0    -1584  omap2plus_defconfig_cpupm
   +280    -1520        0    -1240  omap2plus_defconfig_no_pm
  +4388    -1016        0    +3372  omap2plus_defconfig_omap2_4_only
   +468     -952        0     -484  omap2plus_defconfig_omap3_4_only
   +700     -584     -144      -28  rmk_omap3430_ldp_allnoconfig
   +452     -648        0     -196  rmk_omap3430_ldp_oldconfig
   +700     -584     -144      -28  rmk_omap4430_sdp_allnoconfig
   +424     -328        0      +96  rmk_omap4430_sdp_oldconfig

Boot-time memory difference
(delta in bytes from TEST_pm_cleanup_fixes_a_3.9 (8f5e20850396fc60fd4ee01f586705033902bb53))

  avail  rsrvd   high  freed  board          kconfig
     4k    -4k      .      .  2430sdp        omap2plus_defconfig
     4k    -4k      .      .  3517evm        omap2plus_defconfig
     4k    -4k      .      .  3530es3beagle  omap2plus_defconfig
     4k    -4k      .      .  3730beaglexm   omap2plus_defconfig
     4k    -4k      .      .  37xxevm        omap2plus_defconfig
     4k    -4k      .      .  4430es2panda   omap2plus_defconfig
     4k    -4k      .      .  cmt3517        omap2plus_defconfig

Paul Walmsley (10):
ARM: OMAP3/4: cpuidle: fix sparse and checkpatch warnings
ARM: OMAP2+: clockdomain: add pwrdm_state_switch() call to clkdm_sleep()
ARM: OMAP2xxx: PM: clean up some crufty powerstate programming code
ARM: OMAP2: PM/powerdomain: drop unnecessary pwrdm_wait_transition()
ARM: OMAP2+: PM/powerdomain: move omap_set_pwrdm_state() to powerdomain code
ARM: OMAP2+: powerdomain/clockdomain: add a per-powerdomain spinlock
ARM: OMAP2xxx: CM: remove autodep handling
ARM: OMAP2+: clockdomain: work on wkdep/sleepdep functions
ARM: OMAP2+: clockdomain: convert existing atomic usecounts into spinlock-protected shorts/ints
ARM: OMAP2+: powerdomain: fix whitespace, improve flag comments

 arch/arm/mach-omap2/clockdomain-powerdomain.h    |   22 +
 arch/arm/mach-omap2/clockdomain.c                |  550 +++++++++++++++-------
 arch/arm/mach-omap2/clockdomain.h                |   17 -
 arch/arm/mach-omap2/cm2xxx.c                     |   33 -
 arch/arm/mach-omap2/cm3xxx.c                     |   14 -
 arch/arm/mach-omap2/cminst44xx.c                 |    2 
 arch/arm/mach-omap2/cpuidle34xx.c                |   14 -
 arch/arm/mach-omap2/cpuidle44xx.c                |   28 +
 arch/arm/mach-omap2/pm-debug.c                   |    6 
 arch/arm/mach-omap2/pm.c                         |   65 ---
 arch/arm/mach-omap2/pm.h                         |    1 
 arch/arm/mach-omap2/pm24xx.c                     |   30 -
 arch/arm/mach-omap2/powerdomain-clockdomain.h    |   27 +
 arch/arm/mach-omap2/powerdomain.c                |  176 +++++--
 arch/arm/mach-omap2/powerdomain.h                |   42 +-
 arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c |    4 
 arch/arm/mach-omap2/powerdomains2xxx_data.c      |    8 
 arch/arm/mach-omap2/powerdomains3xxx_data.c      |   44 +-
 arch/arm/mach-omap2/prm2xxx_3xxx.c               |    3 
 19 files changed, 661 insertions(+), 425 deletions(-)
 create mode 100644 arch/arm/mach-omap2/clockdomain-powerdomain.h
 create mode 100644 arch/arm/mach-omap2/powerdomain-clockdomain.h
author maintainer
#1 lore raw

PATCH 1/10 ARM: OMAP3/4: cpuidle: fix sparse and checkpatch warnings

Fix the following sparse warnings in the OMAP3/4 CPUIdle code:

arch/arm/mach-omap2/cpuidle34xx.c:272:1: warning: symbol 'omap3_idle_dev' was not declared. Should it be static? arch/arm/mach-omap2/cpuidle34xx.c:274:23: warning: symbol 'omap3_idle_driver' was not declared. Should it be static? arch/arm/mach-omap2/cpuidle44xx.c:164:1: warning: symbol 'omap4_idle_dev' was not declared. Should it be static? arch/arm/mach-omap2/cpuidle44xx.c:166:23: warning: symbol 'omap4_idle_driver' was not declared. Should it be static?

Also fix the following checkpatch warnings:

WARNING: please, no space before tabs
#44: FILE: arch/arm/mach-omap2/cpuidle34xx.c:105:
+^I.name = ^I"omap3_idle",$

WARNING: please, no space before tabs
#45: FILE: arch/arm/mach-omap2/cpuidle34xx.c:106:
+^I.owner = ^ITHIS_MODULE,$

ERROR: code indent should use tabs where possible
#211: FILE: arch/arm/mach-omap2/cpuidle44xx.c:74:
+ /* C2 - CPU0 OFF + CPU1 OFF + MPU CSWR */$

---
 arch/arm/mach-omap2/cpuidle34xx.c |   14 +++++++++-----
 arch/arm/mach-omap2/cpuidle44xx.c |   28 ++++++++++++++++------------
 2 files changed, 25 insertions(+), 17 deletions(-)
arch/arm/mach-omap2/cpuidle34xx.c +9 -5
index ad70220..e6215b5 100644
@@ -53,6 +53,8 @@ struct omap3_idle_statedata {
  */
 #define OMAP_CPUIDLE_CX_NO_CLKDM_IDLE		BIT(0)
 
+static struct powerdomain *mpu_pd, *core_pd, *per_pd, *cam_pd;
+
 /*
  * Prevent PER OFF if CORE is not in RETention or OFF as this would
  * disable PER wakeups completely.
@@ -97,7 +99,7 @@ static struct omap3_idle_statedata omap3_idle_data[] = {
 	},
 };
 
-static struct powerdomain *mpu_pd, *core_pd, *per_pd, *cam_pd;
+/* Private functions */
 
 static int __omap3_enter_idle(struct cpuidle_device *dev,
 				struct cpuidle_driver *drv,
@@ -269,11 +271,11 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
 	return ret;
 }
 
-DEFINE_PER_CPU(struct cpuidle_device, omap3_idle_dev);
+static DEFINE_PER_CPU(struct cpuidle_device, omap3_idle_dev);
 
-struct cpuidle_driver omap3_idle_driver = {
-	.name = 	"omap3_idle",
-	.owner = 	THIS_MODULE,
+static struct cpuidle_driver omap3_idle_driver = {
+	.name =		"omap3_idle",
+	.owner =	THIS_MODULE,
 	.states = {
 		{
 			.enter		  = omap3_enter_idle_bm,
@@ -336,6 +338,8 @@ struct cpuidle_driver omap3_idle_driver = {
 	.safe_state_index = 0,
 };
 
+/* Public functions */
+
 /**
  * omap3_idle_init - Init routine for OMAP3 idle
  *
arch/arm/mach-omap2/cpuidle44xx.c +16 -12
index 288bee6..d639aef 100644
@@ -54,6 +54,8 @@ static struct clockdomain *cpu_clkdm[NR_CPUS];
 static atomic_t abort_barrier;
 static bool cpu_done[NR_CPUS];
 
+/* Private functions */
+
 /**
  * omap4_enter_idle_coupled_[simple/coupled] - OMAP4 cpuidle entry functions
  * @dev: cpuidle device
@@ -161,9 +163,19 @@ fail:
 	return index;
 }
 
-DEFINE_PER_CPU(struct cpuidle_device, omap4_idle_dev);
+/*
+ * For each cpu, setup the broadcast timer because local timers
+ * stops for the states above C1.
+ */
+static void omap_setup_broadcast_timer(void *arg)
+{
+	int cpu = smp_processor_id();
+	clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ON, &cpu);
+}
+
+static DEFINE_PER_CPU(struct cpuidle_device, omap4_idle_dev);
 
-struct cpuidle_driver omap4_idle_driver = {
+static struct cpuidle_driver omap4_idle_driver = {
 	.name				= "omap4_idle",
 	.owner				= THIS_MODULE,
 	.en_core_tk_irqen		= 1,
@@ -178,7 +190,7 @@ struct cpuidle_driver omap4_idle_driver = {
 			.desc = "MPUSS ON"
 		},
 		{
-                        /* C2 - CPU0 OFF + CPU1 OFF + MPU CSWR */
+			/* C2 - CPU0 OFF + CPU1 OFF + MPU CSWR */
 			.exit_latency = 328 + 440,
 			.target_residency = 960,
 			.flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_COUPLED,
@@ -200,15 +212,7 @@ struct cpuidle_driver omap4_idle_driver = {
 	.safe_state_index = 0,
 };
 
-/*
- * For each cpu, setup the broadcast timer because local timers
- * stops for the states above C1.
- */
-static void omap_setup_broadcast_timer(void *arg)
-{
-	int cpu = smp_processor_id();
-	clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ON, &cpu);
-}
+/* Public functions */
 
 /**
  * omap4_idle_init - Init routine for OMAP4 idle
#2 lore raw

PATCH 1/10 ARM: OMAP3/4: cpuidle: fix sparse and checkpatch warnings

Quoted 13 lines · Paul Walmsley

Fix the following sparse warnings in the OMAP3/4 CPUIdle code:

arch/arm/mach-omap2/cpuidle34xx.c:272:1: warning: symbol 'omap3_idle_dev' was not declared. Should it be static? arch/arm/mach-omap2/cpuidle34xx.c:274:23: warning: symbol 'omap3_idle_driver' was not declared. Should it be static? arch/arm/mach-omap2/cpuidle44xx.c:164:1: warning: symbol 'omap4_idle_dev' was not declared. Should it be static? arch/arm/mach-omap2/cpuidle44xx.c:166:23: warning: symbol 'omap4_idle_driver' was not declared. Should it be static?

Also fix the following checkpatch warnings:

WARNING: please, no space before tabs
#44: FILE: arch/arm/mach-omap2/cpuidle34xx.c:105:
+^I.name = ^I"omap3_idle",$

Quoted 9 lines

WARNING: please, no space before tabs
#45: FILE: arch/arm/mach-omap2/cpuidle34xx.c:106:
+^I.owner = ^ITHIS_MODULE,$

ERROR: code indent should use tabs where possible
#211: FILE: arch/arm/mach-omap2/cpuidle44xx.c:74:
+ /* C2 - CPU0 OFF + CPU1 OFF + MPU CSWR */$

Paul,

I am using your "paul-linux-pwrdm_post_fpwrst_devel_a_3.9" branch, where all the patches which you have posted are present (I believe so) and I am getting following sparse warning -

CHECK arch/arm/mach-omap2/powerdomain.c
arch/arm/mach-omap2/powerdomain.c:811:2: warning: context imbalance in 'pwrdm_lock': unexpected unlock
arch/arm/mach-omap2/powerdomain.c:811:2: default context: wanted 1, got 0
include/linux/spinlock.h:340:2: warning: context problem in 'pwrdm_unlock': '_raw_spin_unlock_irqrestore' expected different context
include/linux/spinlock.h:340:2: context 'lock': wanted >= 1, got 0
arch/arm/mach-omap2/powerdomain.c:1130:14: warning: context problem in 'pwrdm_state_switch': 'pwrdm_unlock' expected different context
arch/arm/mach-omap2/powerdomain.c:1130:14: default context: wanted >=
1, got 0
arch/arm/mach-omap2/powerdomain.c:1295:14: warning: context problem in 'pwrdm_set_next_fpwrst': 'pwrdm_unlock' expected different context
arch/arm/mach-omap2/powerdomain.c:1295:14: default context: wanted >=
1, got 0
arch/arm/mach-omap2/powerdomain.c:1317:14: warning: context problem in 'pwrdm_read_next_fpwrst': 'pwrdm_unlock' expected different context
arch/arm/mach-omap2/powerdomain.c:1317:14: default context: wanted >=
1, got 0
arch/arm/mach-omap2/powerdomain.c:1382:14: warning: context problem in 'pwrdm_set_fpwrst': 'pwrdm_unlock' expected different context
arch/arm/mach-omap2/powerdomain.c:1382:14: default context: wanted >=
1, got 0
arch/arm/mach-omap2/powerdomain.c:1407:14: warning: context problem in 'pwrdm_read_fpwrst': 'pwrdm_unlock' expected different context
arch/arm/mach-omap2/powerdomain.c:1407:14: default context: wanted >=
1, got 0
arch/arm/mach-omap2/powerdomain.c:1432:14: warning: context problem in 'pwrdm_read_prev_fpwrst': 'pwrdm_unlock' expected different context
arch/arm/mach-omap2/powerdomain.c:1432:14: default context: wanted >=
1, got 0
arch/arm/mach-omap2/powerdomain.c:1505:14: warning: context problem in 'pwrdm_dbg_show_counter': 'pwrdm_unlock' expected different context
arch/arm/mach-omap2/powerdomain.c:1505:14: default context: wanted >=
1, got 0
arch/arm/mach-omap2/powerdomain.c:1542:14: warning: context problem in 'pwrdm_dbg_show_timer': 'pwrdm_unlock' expected different context
arch/arm/mach-omap2/powerdomain.c:1542:14: default context: wanted >=
1, got 0
CC arch/arm/mach-omap2/powerdomain.o

On the other hand, I have boot tested it on BeagleBone platform.

Thanks,
Vaibhav

author maintainer
#3 lore raw

PATCH 1/10 ARM: OMAP3/4: cpuidle: fix sparse and checkpatch warnings

Quoted 3 lines · Vaibhav Hiremath

I am using your "paul-linux-pwrdm_post_fpwrst_devel_a_3.9" branch, where all the patches which you have posted are present (I believe so) and I am getting following sparse warning -

The branch name to use is:

"TEST_pwrdm_post_fpwrst_devel_a_3.9"

- Paul

#4 lore raw

PATCH 1/10 ARM: OMAP3/4: cpuidle: fix sparse and checkpatch warnings

Quoted 10 lines · Paul Walmsley
Quoted 3 lines · Vaibhav Hiremath

I am using your "paul-linux-pwrdm_post_fpwrst_devel_a_3.9" branch, where all the patches which you have posted are present (I believe so) and I am getting following sparse warning -

The branch name to use is:

"TEST_pwrdm_post_fpwrst_devel_a_3.9"

If I am correct, it only includes one additional patch (merge commit), right???

commit d94831e0005fee743cefd28f4c20b7c435c71236
Merge: 3e885c6 80ab3b2
Author: Paul Walmsley <[email protected]>
Date: Sun Dec 9 13:06:51 2012 -0700

build fixes

Does this also fix sparse warnings?

Thanks,
Vaibhav

Quoted 3 lines

- Paul

author maintainer
#5 lore raw

PATCH 1/10 ARM: OMAP3/4: cpuidle: fix sparse and checkpatch warnings

Quoted 14 lines · Vaibhav
Quoted 4 lines · Paul Walmsley

The branch name to use is:

"TEST_pwrdm_post_fpwrst_devel_a_3.9"

If I am correct, it only includes one additional patch (merge commit), right???

commit d94831e0005fee743cefd28f4c20b7c435c71236
Merge: 3e885c6 80ab3b2
Author: Paul Walmsley <[email protected]>
Date: Sun Dec 9 13:06:51 2012 -0700

Quoted 5 lines

build fixes

Does this also fix sparse warnings?

Just ran a quick sparse check on mach-omap2 at 3e885c6 and d94831e with 'make -j4 C=2 arch/arm/mach-omap2', and no warnings showed up. There were some sparse issues that got fixed at an earlier point, though, so perhaps you have an older copy of the branches somehow?

- Paul

paul at dusk:/kernel/kernel/current$ git log -1
commit d94831e0005fee743cefd28f4c20b7c435c71236
Merge: 3e885c6 80ab3b2
Author: Paul Walmsley <[email protected]>
Date: Sun Dec 9 13:06:51 2012 -0700

build fixes
paul at dusk:/kernel/kernel/current$ make C=2 -j4 arch/arm/mach-omap2/

  CHK     include/generated/uapi/linux/version.h
  CHECK   scripts/mod/empty.c
  CHK     include/generated/utsrelease.h
  UPD     include/generated/utsrelease.h
make[1]: `include/generated/mach-types.h' is up to date.
  CC      kernel/bounds.s
  GEN     include/generated/bounds.h
  CC      arch/arm/kernel/asm-offsets.s
  GEN     include/generated/asm-offsets.h
  CALL    scripts/checksyscalls.sh
  CHECK   arch/arm/mach-omap2/id.c
  CHECK   arch/arm/mach-omap2/io.c
  CHECK   arch/arm/mach-omap2/control.c
  CHECK   arch/arm/mach-omap2/mux.c
  CC      arch/arm/mach-omap2/id.o
  CC      arch/arm/mach-omap2/control.o
  CC      arch/arm/mach-omap2/io.o
  CC      arch/arm/mach-omap2/mux.o
  CHECK   arch/arm/mach-omap2/devices.c
  CHECK   arch/arm/mach-omap2/serial.c
  CHECK   arch/arm/mach-omap2/gpmc.c
  CC      arch/arm/mach-omap2/devices.o
  CC      arch/arm/mach-omap2/serial.o
  CC      arch/arm/mach-omap2/gpmc.o
  CHECK   arch/arm/mach-omap2/timer.c
  CHECK   arch/arm/mach-omap2/pm.c
  CC      arch/arm/mach-omap2/timer.o
  CC      arch/arm/mach-omap2/pm.o
  CHECK   arch/arm/mach-omap2/common.c
  CC      arch/arm/mach-omap2/common.o
  CHECK   arch/arm/mach-omap2/gpio.c
  CC      arch/arm/mach-omap2/gpio.o
  CHECK   arch/arm/mach-omap2/dma.c
  CC      arch/arm/mach-omap2/dma.o
  CHECK   arch/arm/mach-omap2/wd_timer.c
  CHECK   arch/arm/mach-omap2/display.c
  CHECK   arch/arm/mach-omap2/i2c.c
  CC      arch/arm/mach-omap2/wd_timer.o
  CC      arch/arm/mach-omap2/i2c.o
  CC      arch/arm/mach-omap2/display.o
  CHECK   arch/arm/mach-omap2/hdq1w.c
  CC      arch/arm/mach-omap2/hdq1w.o
  CHECK   arch/arm/mach-omap2/omap_hwmod.c
  CHECK   arch/arm/mach-omap2/omap_device.c
  CC      arch/arm/mach-omap2/omap_hwmod.o
  CC      arch/arm/mach-omap2/omap_device.o
  CHECK   arch/arm/mach-omap2/irq.c
  CHECK   arch/arm/mach-omap2/omap_hwmod_common_data.c
  CC      arch/arm/mach-omap2/irq.o
  CC      arch/arm/mach-omap2/omap_hwmod_common_data.o
  CHECK   arch/arm/mach-omap2/omap-secure.c
  CC      arch/arm/mach-omap2/omap-secure.o
  CHECK   arch/arm/mach-omap2/prm44xx.c
  CHECK   arch/arm/mach-omap2/mcbsp.c
  CC      arch/arm/mach-omap2/prm44xx.o
  CC      arch/arm/mach-omap2/mcbsp.o
  CHECK   arch/arm/mach-omap2/omap_twl.c
  CC      arch/arm/mach-omap2/omap_twl.o
  CHECK   arch/arm/mach-omap2/sdrc.c
  CC      arch/arm/mach-omap2/sdrc.o
  CHECK   arch/arm/mach-omap2/omap-smp.c
  CHECK   arch/arm/mach-omap2/omap-hotplug.c
  CC      arch/arm/mach-omap2/omap-smp.o
  CC      arch/arm/mach-omap2/omap-hotplug.o
  CHECK   arch/arm/mach-omap2/omap4-common.c
  CC      arch/arm/mach-omap2/omap4-common.o
  CHECK   arch/arm/mach-omap2/omap-wakeupgen.c
  AS      arch/arm/mach-omap2/sram242x.o
  AS      arch/arm/mach-omap2/sram243x.o
  CC      arch/arm/mach-omap2/omap-wakeupgen.o
  AS      arch/arm/mach-omap2/sram34xx.o
  CHECK   arch/arm/mach-omap2/omap2-restart.c
  CHECK   arch/arm/mach-omap2/omap3-restart.c
  CC      arch/arm/mach-omap2/omap2-restart.o
  CC      arch/arm/mach-omap2/omap3-restart.o
  CHECK   arch/arm/mach-omap2/mux2420.c
  CC      arch/arm/mach-omap2/mux2420.o
  CHECK   arch/arm/mach-omap2/mux2430.c
  CHECK   arch/arm/mach-omap2/mux34xx.c
  CHECK   arch/arm/mach-omap2/mux44xx.c
  CC      arch/arm/mach-omap2/mux2430.o
  CC      arch/arm/mach-omap2/mux34xx.o
  CC      arch/arm/mach-omap2/mux44xx.o
  CHECK   arch/arm/mach-omap2/sdrc2xxx.c
  CHECK   arch/arm/mach-omap2/opp.c
  CC      arch/arm/mach-omap2/sdrc2xxx.o
  CC      arch/arm/mach-omap2/opp.o
  CHECK   arch/arm/mach-omap2/opp3xxx_data.c
  CHECK   arch/arm/mach-omap2/opp4xxx_data.c
  CC      arch/arm/mach-omap2/opp3xxx_data.o
  CC      arch/arm/mach-omap2/opp4xxx_data.o
  CHECK   arch/arm/mach-omap2/pm24xx.c
  AS      arch/arm/mach-omap2/sleep24xx.o
  CHECK   arch/arm/mach-omap2/pm34xx.c
  AS      arch/arm/mach-omap2/sleep34xx.o
  CHECK   arch/arm/mach-omap2/pm44xx.c
  CC      arch/arm/mach-omap2/pm24xx.o
  CHECK   arch/arm/mach-omap2/omap-mpuss-lowpower.c
  CC      arch/arm/mach-omap2/pm34xx.o
  CC      arch/arm/mach-omap2/pm44xx.o
  CC      arch/arm/mach-omap2/omap-mpuss-lowpower.o
  CHECK   arch/arm/mach-omap2/pm-debug.c
  CHECK   arch/arm/mach-omap2/prm_common.c
  CC      arch/arm/mach-omap2/pm-debug.o
  CHECK   arch/arm/mach-omap2/cm_common.c
  CC      arch/arm/mach-omap2/prm_common.o
  CC      arch/arm/mach-omap2/cm_common.o
  CHECK   arch/arm/mach-omap2/prm2xxx_3xxx.c
  CC      arch/arm/mach-omap2/prm2xxx_3xxx.o
  CHECK   arch/arm/mach-omap2/prm2xxx.c
  CHECK   arch/arm/mach-omap2/cm2xxx.c
  CC      arch/arm/mach-omap2/prm2xxx.o
  CC      arch/arm/mach-omap2/cm2xxx.o
  CHECK   arch/arm/mach-omap2/prm3xxx.c
  CC      arch/arm/mach-omap2/prm3xxx.o
  CHECK   arch/arm/mach-omap2/cm3xxx.c
  CC      arch/arm/mach-omap2/cm3xxx.o
  CHECK   arch/arm/mach-omap2/vc3xxx_data.c
  CHECK   arch/arm/mach-omap2/vp3xxx_data.c
  CC      arch/arm/mach-omap2/vc3xxx_data.o
  CC      arch/arm/mach-omap2/vp3xxx_data.o
  CHECK   arch/arm/mach-omap2/prm33xx.c
  CC      arch/arm/mach-omap2/prm33xx.o
  CHECK   arch/arm/mach-omap2/cm33xx.c
  CHECK   arch/arm/mach-omap2/cminst44xx.c
  CC      arch/arm/mach-omap2/cm33xx.o
  CC      arch/arm/mach-omap2/cminst44xx.o
  CHECK   arch/arm/mach-omap2/cm44xx.c
  CC      arch/arm/mach-omap2/cm44xx.o
  CHECK   arch/arm/mach-omap2/prcm_mpu44xx.c
  CC      arch/arm/mach-omap2/prcm_mpu44xx.o
  CHECK   arch/arm/mach-omap2/prminst44xx.c
  CHECK   arch/arm/mach-omap2/vc44xx_data.c
  CC      arch/arm/mach-omap2/prminst44xx.o
  CHECK   arch/arm/mach-omap2/vp44xx_data.c
  CC      arch/arm/mach-omap2/vc44xx_data.o
  CHECK   arch/arm/mach-omap2/voltage.c
  CC      arch/arm/mach-omap2/vp44xx_data.o
  CC      arch/arm/mach-omap2/voltage.o
  CHECK   arch/arm/mach-omap2/vc.c
  CC      arch/arm/mach-omap2/vc.o
  CHECK   arch/arm/mach-omap2/vp.c
  CHECK   arch/arm/mach-omap2/voltagedomains2xxx_data.c
  CC      arch/arm/mach-omap2/voltagedomains2xxx_data.o
  CC      arch/arm/mach-omap2/vp.o
  CHECK   arch/arm/mach-omap2/voltagedomains3xxx_data.c
  CC      arch/arm/mach-omap2/voltagedomains3xxx_data.o
  CHECK   arch/arm/mach-omap2/voltagedomains44xx_data.c
  CHECK   arch/arm/mach-omap2/voltagedomains33xx_data.c
  CC      arch/arm/mach-omap2/voltagedomains33xx_data.o
  CC      arch/arm/mach-omap2/voltagedomains44xx_data.o
  CHECK   arch/arm/mach-omap2/powerdomain.c
  CC      arch/arm/mach-omap2/powerdomain.o
  CHECK   arch/arm/mach-omap2/powerdomain-common.c
  CC      arch/arm/mach-omap2/powerdomain-common.o
  CHECK   arch/arm/mach-omap2/powerdomains2xxx_data.c
  CC      arch/arm/mach-omap2/powerdomains2xxx_data.o
  CHECK   arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c
  CC      arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.o
  CHECK   arch/arm/mach-omap2/powerdomains3xxx_data.c
  CHECK   arch/arm/mach-omap2/powerdomains44xx_data.c
  CC      arch/arm/mach-omap2/powerdomains3xxx_data.o
  CHECK   arch/arm/mach-omap2/powerdomains33xx_data.c
  CC      arch/arm/mach-omap2/powerdomains33xx_data.o
  CC      arch/arm/mach-omap2/powerdomains44xx_data.o
  CHECK   arch/arm/mach-omap2/clockdomain.c
  CC      arch/arm/mach-omap2/clockdomain.o
  CHECK   arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c
  CC      arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.o
  CHECK   arch/arm/mach-omap2/clockdomains2420_data.c
  CHECK   arch/arm/mach-omap2/clockdomains2430_data.c
  CC      arch/arm/mach-omap2/clockdomains2420_data.o
  CC      arch/arm/mach-omap2/clockdomains2430_data.o
  CHECK   arch/arm/mach-omap2/clockdomains3xxx_data.c
  CHECK   arch/arm/mach-omap2/clockdomains44xx_data.c
  CC      arch/arm/mach-omap2/clockdomains3xxx_data.o
  CHECK   arch/arm/mach-omap2/clockdomains33xx_data.c
  CC      arch/arm/mach-omap2/clockdomains44xx_data.o
  CC      arch/arm/mach-omap2/clockdomains33xx_data.o
  CHECK   arch/arm/mach-omap2/clock.c
  CHECK   arch/arm/mach-omap2/clock_common_data.c
  CC      arch/arm/mach-omap2/clock_common_data.o
  CC      arch/arm/mach-omap2/clock.o
  CHECK   arch/arm/mach-omap2/clkt_dpll.c
  CHECK   arch/arm/mach-omap2/clkt_clksel.c
  CC      arch/arm/mach-omap2/clkt_dpll.o
  CHECK   arch/arm/mach-omap2/clock2xxx.c
  CC      arch/arm/mach-omap2/clkt_clksel.o
  CC      arch/arm/mach-omap2/clock2xxx.o
  CHECK   arch/arm/mach-omap2/clkt2xxx_sys.c
  CC      arch/arm/mach-omap2/clkt2xxx_sys.o
  CHECK   arch/arm/mach-omap2/clkt2xxx_dpllcore.c
  CC      arch/arm/mach-omap2/clkt2xxx_dpllcore.o
  CHECK   arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c
  CC      arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.o
  CHECK   arch/arm/mach-omap2/clkt2xxx_apll.c
  CC      arch/arm/mach-omap2/clkt2xxx_apll.o
  CHECK   arch/arm/mach-omap2/clkt2xxx_osc.c
  CC      arch/arm/mach-omap2/clkt2xxx_osc.o
  CHECK   arch/arm/mach-omap2/clkt2xxx_dpll.c
  CC      arch/arm/mach-omap2/clkt2xxx_dpll.o
  CHECK   arch/arm/mach-omap2/clkt_iclk.c
  CC      arch/arm/mach-omap2/clkt_iclk.o
  CHECK   arch/arm/mach-omap2/clock2420_data.c
  CHECK   arch/arm/mach-omap2/clock2430.c
  CHECK   arch/arm/mach-omap2/clock2430_data.c
  CC      arch/arm/mach-omap2/clock2430.o
  CC      arch/arm/mach-omap2/clock2420_data.o
  CC      arch/arm/mach-omap2/clock2430_data.o
  CHECK   arch/arm/mach-omap2/clock3xxx.c
  CC      arch/arm/mach-omap2/clock3xxx.o
  CHECK   arch/arm/mach-omap2/clock34xx.c
  CC      arch/arm/mach-omap2/clock34xx.o
  CHECK   arch/arm/mach-omap2/clkt34xx_dpll3m2.c
  CHECK   arch/arm/mach-omap2/clock3517.c
  CHECK   arch/arm/mach-omap2/clock36xx.c
  CC      arch/arm/mach-omap2/clock3517.o
  CC      arch/arm/mach-omap2/clkt34xx_dpll3m2.o
  CC      arch/arm/mach-omap2/clock36xx.o
  CHECK   arch/arm/mach-omap2/dpll3xxx.c
  CC      arch/arm/mach-omap2/dpll3xxx.o
  CHECK   arch/arm/mach-omap2/clock3xxx_data.c
  CHECK   arch/arm/mach-omap2/clock44xx_data.c
  CHECK   arch/arm/mach-omap2/dpll44xx.c
  CC      arch/arm/mach-omap2/clock3xxx_data.o
  CC      arch/arm/mach-omap2/dpll44xx.o
  CC      arch/arm/mach-omap2/clock44xx_data.o
  CHECK   arch/arm/mach-omap2/clock33xx_data.c
  CHECK   arch/arm/mach-omap2/opp2420_data.c
  CC      arch/arm/mach-omap2/opp2420_data.o
  CHECK   arch/arm/mach-omap2/opp2430_data.c
  CHECK   arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
  CC      arch/arm/mach-omap2/clock33xx_data.o
  CC      arch/arm/mach-omap2/opp2430_data.o
  CHECK   arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c
  CC      arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.o
  CC      arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.o
  CHECK   arch/arm/mach-omap2/omap_hwmod_2xxx_interconnect_data.c
  CC      arch/arm/mach-omap2/omap_hwmod_2xxx_interconnect_data.o
  CHECK   arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_interconnect_data.c
  CHECK   arch/arm/mach-omap2/omap_hwmod_2420_data.c
  CHECK   arch/arm/mach-omap2/omap_hwmod_2430_data.c
  CC      arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_interconnect_data.o
  CC      arch/arm/mach-omap2/omap_hwmod_2420_data.o
  CC      arch/arm/mach-omap2/omap_hwmod_2430_data.o
  CHECK   arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
  CC      arch/arm/mach-omap2/omap_hwmod_3xxx_data.o
  CHECK   arch/arm/mach-omap2/omap_hwmod_33xx_data.c
  CHECK   arch/arm/mach-omap2/omap_hwmod_44xx_data.c
  CHECK   arch/arm/mach-omap2/pmu.c
  CC      arch/arm/mach-omap2/omap_hwmod_33xx_data.o
  CC      arch/arm/mach-omap2/omap_hwmod_44xx_data.o
  CC      arch/arm/mach-omap2/pmu.o
  CHECK   arch/arm/mach-omap2/msdi.c
  CC      arch/arm/mach-omap2/msdi.o
  CHECK   arch/arm/mach-omap2/board-generic.c
  CHECK   arch/arm/mach-omap2/board-h4.c
  CC      arch/arm/mach-omap2/board-generic.o
  CHECK   arch/arm/mach-omap2/board-2430sdp.c
  CC      arch/arm/mach-omap2/board-h4.o
  CC      arch/arm/mach-omap2/board-2430sdp.o
  CHECK   arch/arm/mach-omap2/board-apollon.c
  CHECK   arch/arm/mach-omap2/board-omap3beagle.c
  CC      arch/arm/mach-omap2/board-apollon.o
  CC      arch/arm/mach-omap2/board-omap3beagle.o
  CHECK   arch/arm/mach-omap2/board-devkit8000.c
  CC      arch/arm/mach-omap2/board-devkit8000.o
  CHECK   arch/arm/mach-omap2/board-ldp.c
  CHECK   arch/arm/mach-omap2/board-omap3logic.c
  CC      arch/arm/mach-omap2/board-ldp.o
  CC      arch/arm/mach-omap2/board-omap3logic.o
  CHECK   arch/arm/mach-omap2/board-overo.c
  CC      arch/arm/mach-omap2/board-overo.o
  CHECK   arch/arm/mach-omap2/board-omap3evm.c
  CC      arch/arm/mach-omap2/board-omap3evm.o
  CHECK   arch/arm/mach-omap2/board-omap3pandora.c
  CHECK   arch/arm/mach-omap2/board-3430sdp.c
  CC      arch/arm/mach-omap2/board-omap3pandora.o
  CC      arch/arm/mach-omap2/board-3430sdp.o
  CHECK   arch/arm/mach-omap2/board-n8x0.c
  CC      arch/arm/mach-omap2/board-n8x0.o
  CHECK   arch/arm/mach-omap2/board-rm680.c
  CC      arch/arm/mach-omap2/board-rm680.o
  CHECK   arch/arm/mach-omap2/sdram-nokia.c
  CHECK   arch/arm/mach-omap2/board-rx51.c
  CC      arch/arm/mach-omap2/sdram-nokia.o
  CC      arch/arm/mach-omap2/board-rx51.o
  CHECK   arch/arm/mach-omap2/board-rx51-peripherals.c
  CC      arch/arm/mach-omap2/board-rx51-peripherals.o
  CHECK   arch/arm/mach-omap2/board-rx51-video.c
  CC      arch/arm/mach-omap2/board-rx51-video.o
  CHECK   arch/arm/mach-omap2/board-zoom-peripherals.c
  CHECK   arch/arm/mach-omap2/board-zoom.c
  CC      arch/arm/mach-omap2/board-zoom.o
  CC      arch/arm/mach-omap2/board-zoom-peripherals.o
  CHECK   arch/arm/mach-omap2/board-zoom-display.c
  CHECK   arch/arm/mach-omap2/board-zoom-debugboard.c
  CC      arch/arm/mach-omap2/board-zoom-display.o
  CC      arch/arm/mach-omap2/board-zoom-debugboard.o
  CHECK   arch/arm/mach-omap2/board-3630sdp.c
  CHECK   arch/arm/mach-omap2/board-cm-t35.c
  CC      arch/arm/mach-omap2/board-3630sdp.o
  CHECK   arch/arm/mach-omap2/board-cm-t3517.c
  CC      arch/arm/mach-omap2/board-cm-t35.o
  CC      arch/arm/mach-omap2/board-cm-t3517.o
  CHECK   arch/arm/mach-omap2/board-igep0020.c
  CHECK   arch/arm/mach-omap2/board-omap3touchbook.c
  CC      arch/arm/mach-omap2/board-igep0020.o
  CC      arch/arm/mach-omap2/board-omap3touchbook.o
  CHECK   arch/arm/mach-omap2/board-4430sdp.c
  CHECK   arch/arm/mach-omap2/board-omap4panda.c
  CC      arch/arm/mach-omap2/board-4430sdp.o
  CC      arch/arm/mach-omap2/board-omap4panda.o
  CHECK   arch/arm/mach-omap2/board-am3517evm.c
  CHECK   arch/arm/mach-omap2/board-omap3stalker.c
  CC      arch/arm/mach-omap2/board-am3517evm.o
  CC      arch/arm/mach-omap2/board-omap3stalker.o
  CHECK   arch/arm/mach-omap2/board-ti8168evm.c
  CC      arch/arm/mach-omap2/board-ti8168evm.o
  CHECK   arch/arm/mach-omap2/board-flash.c
  CC      arch/arm/mach-omap2/board-flash.o
  CHECK   arch/arm/mach-omap2/hsmmc.c
  CHECK   arch/arm/mach-omap2/usb-musb.c
  CC      arch/arm/mach-omap2/hsmmc.o
  CHECK   arch/arm/mach-omap2/omap_phy_internal.c
  CC      arch/arm/mach-omap2/usb-musb.o
  CC      arch/arm/mach-omap2/omap_phy_internal.o
  CHECK   arch/arm/mach-omap2/usb-tusb6010.c
  CHECK   arch/arm/mach-omap2/usb-host.c
  CC      arch/arm/mach-omap2/usb-tusb6010.o
  CC      arch/arm/mach-omap2/usb-host.o
  CHECK   arch/arm/mach-omap2/gpmc-onenand.c
  CC      arch/arm/mach-omap2/gpmc-onenand.o
  CHECK   arch/arm/mach-omap2/gpmc-nand.c
  CHECK   arch/arm/mach-omap2/gpmc-smc91x.c
  CC      arch/arm/mach-omap2/gpmc-smc91x.o
  CC      arch/arm/mach-omap2/gpmc-nand.o
  CHECK   arch/arm/mach-omap2/gpmc-smsc911x.c
  CC      arch/arm/mach-omap2/gpmc-smsc911x.o
  CHECK   arch/arm/mach-omap2/common-board-devices.c
  CHECK   arch/arm/mach-omap2/twl-common.c
  CC      arch/arm/mach-omap2/common-board-devices.o
  CC      arch/arm/mach-omap2/twl-common.o
  LD      arch/arm/mach-omap2/built-in.o

paul at dusk:/kernel/kernel/current$

#6 lore raw

PATCH 1/10 ARM: OMAP3/4: cpuidle: fix sparse and checkpatch warnings

Quoted 20 lines · Paul Walmsley
Quoted 18 lines · Vaibhav
Quoted 4 lines · Paul Walmsley

The branch name to use is:

"TEST_pwrdm_post_fpwrst_devel_a_3.9"

If I am correct, it only includes one additional patch (merge commit), right???

commit d94831e0005fee743cefd28f4c20b7c435c71236
Merge: 3e885c6 80ab3b2
Author: Paul Walmsley <[email protected]>
Date: Sun Dec 9 13:06:51 2012 -0700

build fixes

Quoted 7 lines
Quoted 1 line

Does this also fix sparse warnings?

Just ran a quick sparse check on mach-omap2 at 3e885c6 and d94831e with 'make -j4 C=2 arch/arm/mach-omap2', and no warnings showed up. There were some sparse issues that got fixed at an earlier point, though, so perhaps you have an older copy of the branches somehow?

Ignore my earlier comment on sparse warning, it was my wrong sparse tool which was culprit here. I am working on remote server, which has sparse present inside /usr/bin, and somehow my default config using that one instead of what I was building.

I fixed this by changing the PATH, and now I do not see any issues/warnings.

Thanks,
Vaibhav

#7 lore raw

PATCH 1/10 ARM: OMAP3/4: cpuidle: fix sparse and checkpatch warnings

In reply to Paul Walmsley
Quoted 17 lines · Paul Walmsley

Fix the following sparse warnings in the OMAP3/4 CPUIdle code:

arch/arm/mach-omap2/cpuidle34xx.c:272:1: warning: symbol 'omap3_idle_dev' was not declared. Should it be static? arch/arm/mach-omap2/cpuidle34xx.c:274:23: warning: symbol 'omap3_idle_driver' was not declared. Should it be static? arch/arm/mach-omap2/cpuidle44xx.c:164:1: warning: symbol 'omap4_idle_dev' was not declared. Should it be static? arch/arm/mach-omap2/cpuidle44xx.c:166:23: warning: symbol 'omap4_idle_driver' was not declared. Should it be static?

Also fix the following checkpatch warnings:

WARNING: please, no space before tabs
#44: FILE: arch/arm/mach-omap2/cpuidle34xx.c:105:
+^I.name = ^I"omap3_idle",$

WARNING: please, no space before tabs
#45: FILE: arch/arm/mach-omap2/cpuidle34xx.c:106:
+^I.owner = ^ITHIS_MODULE,$

Quoted 8 lines

ERROR: code indent should use tabs where possible
#211: FILE: arch/arm/mach-omap2/cpuidle44xx.c:74:
+ /* C2 - CPU0 OFF + CPU1 OFF + MPU CSWR */$

---

author maintainer
#8 lore raw

PATCH 2/10 ARM: OMAP2+: clockdomain: add pwrdm_state_switch() call to clkdm_sleep()

In reply to Paul Walmsley

In clkdm_sleep(), the powerdomain should be eligible to switch power states right after the call to the low-level clockdomain sleep function. We should have been tracking that with the pwrdm_state_switch() code, but we weren't, for whatever reason. Fix that.

---
 arch/arm/mach-omap2/clockdomain.c |    1 +
 1 file changed, 1 insertion(+)
arch/arm/mach-omap2/clockdomain.c +1 -0
index 64e5046..18f65fd 100644
@@ -763,6 +763,7 @@ int clkdm_sleep(struct clockdomain *clkdm)
 	spin_lock_irqsave(&clkdm->lock, flags);
 	clkdm->_flags &= ~_CLKDM_FLAG_HWSUP_ENABLED;
 	ret = arch_clkdm->clkdm_sleep(clkdm);
+	ret |= pwrdm_state_switch(clkdm->pwrdm.ptr);
 	spin_unlock_irqrestore(&clkdm->lock, flags);
 	return ret;
 }
author maintainer
#9 lore raw

PATCH 3/10 ARM: OMAP2xxx: PM: clean up some crufty powerstate programming code

In reply to Paul Walmsley

Don't attempt to put clockdomains to sleep; this should be handled by the clock framework. It should be enough to program the next-power-state, and then let the code in omap_pm_clkdms_setup() deal with the rest.

Start out by programming the MPU and CORE powerdomains to stay ON. Then control the MPU and CORE powerdomain states directly in omap2_enter_full_retention() and omap2_enter_mpu_retention(). Not the most optimal way to do it, but certainly is the most conservative until OMAP2xxx PM is working again.

Get rid of the open-coded PM_PWSTCTRL_MPU writes in omap2_enter_mpu_retention(); use the powerdomain code instead.

---
 arch/arm/mach-omap2/pm24xx.c |   30 ++++++++++--------------------
 1 file changed, 10 insertions(+), 20 deletions(-)
arch/arm/mach-omap2/pm24xx.c +10 -20
index 83815dd..4c06d8a 100644
@@ -89,11 +89,7 @@ static int omap2_enter_full_retention(void)
 	omap2_prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP24XX_PM_WKST2);
 	omap2_prm_write_mod_reg(0xffffffff, WKUP_MOD, PM_WKST);
 
-	/*
-	 * Set MPU powerdomain's next power state to RETENTION;
-	 * preserve logic state during retention
-	 */
-	pwrdm_set_logic_retst(mpu_pwrdm, PWRDM_POWER_RET);
+	pwrdm_set_next_pwrst(core_pwrdm, PWRDM_POWER_RET);
 	pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_RET);
 
 	/* Workaround to kill USB */
@@ -136,6 +132,9 @@ 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);
+
 	return 0;
 }
 
@@ -185,17 +184,16 @@ static void omap2_enter_mpu_retention(void)
 		omap2_prm_write_mod_reg(0xffffffff, WKUP_MOD, PM_WKST);
 
 		/* Try to enter MPU retention */
-		omap2_prm_write_mod_reg((0x01 << OMAP_POWERSTATE_SHIFT) |
-				  OMAP_LOGICRETSTATE_MASK,
-				  MPU_MOD, OMAP2_PM_PWSTCTRL);
+		pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_RET);
+
 	} else {
 		/* Block MPU retention */
-
-		omap2_prm_write_mod_reg(OMAP_LOGICRETSTATE_MASK, MPU_MOD,
-						 OMAP2_PM_PWSTCTRL);
+		pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_ON);
 	}
 
 	omap2_sram_idle();
+
+	pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_ON);
 }
 
 static int omap2_can_sleep(void)
@@ -250,25 +248,17 @@ 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);
 
-	/* Set CORE powerdomain's next power state to RETENTION */
-	pwrdm_set_next_pwrst(core_pwrdm, PWRDM_POWER_RET);
+	pwrdm_set_logic_retst(core_pwrdm, PWRDM_POWER_RET);
 
-	/*
-	 * Set MPU powerdomain's next power state to RETENTION;
-	 * preserve logic state during retention
-	 */
 	pwrdm_set_logic_retst(mpu_pwrdm, PWRDM_POWER_RET);
-	pwrdm_set_next_pwrst(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);
-	clkdm_sleep(dsp_clkdm);
 
 	pwrdm = clkdm_get_pwrdm(gfx_clkdm);
 	pwrdm_set_next_pwrst(pwrdm, PWRDM_POWER_OFF);
-	clkdm_sleep(gfx_clkdm);
 
 	/* Enable hardware-supervised idle for all clkdms */
 	clkdm_for_each(omap_pm_clkdms_setup, NULL);
author maintainer
#10 lore raw

PATCH 4/10 ARM: OMAP2: PM/powerdomain: drop unnecessary pwrdm_wait_transition()

In reply to Paul Walmsley

Drop an unnecessary pwrdm_wait_transition() from mach-omap2/pm.c - it's called by the subsequent pwrdm_state_switch().

Also get rid of pwrdm_wait_transition() in the powerdomain code - there's no longer any need to export this function.

---
 arch/arm/mach-omap2/pm.c          |    1 -
 arch/arm/mach-omap2/powerdomain.c |   30 +++++-------------------------
 arch/arm/mach-omap2/powerdomain.h |    2 --
 3 files changed, 5 insertions(+), 28 deletions(-)
arch/arm/mach-omap2/pm.c +0 -1
index 331478f..cc8ed0f 100644
@@ -139,7 +139,6 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 pwrst)
 		break;
 	case LOWPOWERSTATE_SWITCH:
 		pwrdm_set_lowpwrstchange(pwrdm);
-		pwrdm_wait_transition(pwrdm);
 		pwrdm_state_switch(pwrdm);
 		break;
 	}
arch/arm/mach-omap2/powerdomain.c +5 -25
index 92388c0..97b3881 100644
@@ -112,7 +112,7 @@ static int _pwrdm_register(struct powerdomain *pwrdm)
 	for (i = 0; i < pwrdm->banks; i++)
 		pwrdm->ret_mem_off_counter[i] = 0;
 
-	pwrdm_wait_transition(pwrdm);
+	arch_pwrdm->pwrdm_wait_transition(pwrdm);
 	pwrdm->state = pwrdm_read_pwrst(pwrdm);
 	pwrdm->state_counter[pwrdm->state] = 1;
 
@@ -950,34 +950,14 @@ int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm)
 	return ret;
 }
 
-/**
- * pwrdm_wait_transition - wait for powerdomain power transition to finish
- * @pwrdm: struct powerdomain * to wait for
- *
- * If the powerdomain @pwrdm is in the process of a state transition,
- * spin until it completes the power transition, or until an iteration
- * bailout value is reached. Returns -EINVAL if the powerdomain
- * pointer is null, -EAGAIN if the bailout value was reached, or
- * returns 0 upon success.
- */
-int pwrdm_wait_transition(struct powerdomain *pwrdm)
-{
-	int ret = -EINVAL;
-
-	if (!pwrdm)
-		return -EINVAL;
-
-	if (arch_pwrdm && arch_pwrdm->pwrdm_wait_transition)
-		ret = arch_pwrdm->pwrdm_wait_transition(pwrdm);
-
-	return ret;
-}
-
 int pwrdm_state_switch(struct powerdomain *pwrdm)
 {
 	int ret;
 
-	ret = pwrdm_wait_transition(pwrdm);
+	if (!pwrdm || !arch_pwrdm)
+		return -EINVAL;
+
+	ret = arch_pwrdm->pwrdm_wait_transition(pwrdm);
 	if (!ret)
 		ret = _pwrdm_state_switch(pwrdm, PWRDM_STATE_NOW);
 
arch/arm/mach-omap2/powerdomain.h +0 -2
index 5277d56eb..7c1534b 100644
@@ -225,8 +225,6 @@ int pwrdm_enable_hdwr_sar(struct powerdomain *pwrdm);
 int pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm);
 bool pwrdm_has_hdwr_sar(struct powerdomain *pwrdm);
 
-int pwrdm_wait_transition(struct powerdomain *pwrdm);
-
 int pwrdm_state_switch(struct powerdomain *pwrdm);
 int pwrdm_pre_transition(struct powerdomain *pwrdm);
 int pwrdm_post_transition(struct powerdomain *pwrdm);
author maintainer
#11 lore raw

PATCH 5/10 ARM: OMAP2+: PM/powerdomain: move omap_set_pwrdm_state() to powerdomain code

In reply to Paul Walmsley

Move omap_set_pwrdm_state() from the PM code to the powerdomain code, and refactor it to split it up into several functions. A subsequent patch will rename it to conform with the existing powerdomain function names.

Cc Jean Pihet <[email protected]>
Cc Kevin Hilman <[email protected]>
---
 arch/arm/mach-omap2/pm.c          |   61 --------------------
 arch/arm/mach-omap2/pm.h          |    1 
 arch/arm/mach-omap2/powerdomain.c |  112 +++++++++++++++++++++++++++----------
 arch/arm/mach-omap2/powerdomain.h |    3 +
 4 files changed, 85 insertions(+), 92 deletions(-)
arch/arm/mach-omap2/pm.c +0 -61
index cc8ed0f..2e2a897 100644
@@ -76,10 +76,6 @@ static void __init omap2_init_processor_devices(void)
 	}
 }
 
-/* Types of sleep_switch used in omap_set_pwrdm_state */
-#define FORCEWAKEUP_SWITCH	0
-#define LOWPOWERSTATE_SWITCH	1
-
 int __init omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused)
 {
 	if ((clkdm->flags & CLKDM_CAN_ENABLE_AUTO) &&
@@ -92,63 +88,6 @@ int __init omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused)
 }
 
 /*
- * This sets pwrdm state (other than mpu & core. Currently only ON &
- * RET are supported.
- */
-int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 pwrst)
-{
-	u8 curr_pwrst, next_pwrst;
-	int sleep_switch = -1, ret = 0, hwsup = 0;
-
-	if (!pwrdm || IS_ERR(pwrdm))
-		return -EINVAL;
-
-	while (!(pwrdm->pwrsts & (1 << pwrst))) {
-		if (pwrst == PWRDM_POWER_OFF)
-			return ret;
-		pwrst--;
-	}
-
-	next_pwrst = pwrdm_read_next_pwrst(pwrdm);
-	if (next_pwrst == pwrst)
-		return ret;
-
-	curr_pwrst = pwrdm_read_pwrst(pwrdm);
-	if (curr_pwrst < PWRDM_POWER_ON) {
-		if ((curr_pwrst > pwrst) &&
-			(pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE)) {
-			sleep_switch = LOWPOWERSTATE_SWITCH;
-		} else {
-			hwsup = clkdm_in_hwsup(pwrdm->pwrdm_clkdms[0]);
-			clkdm_wakeup(pwrdm->pwrdm_clkdms[0]);
-			sleep_switch = FORCEWAKEUP_SWITCH;
-		}
-	}
-
-	ret = pwrdm_set_next_pwrst(pwrdm, pwrst);
-	if (ret)
-		pr_err("%s: unable to set power state of powerdomain: %s\n",
-		       __func__, pwrdm->name);
-
-	switch (sleep_switch) {
-	case FORCEWAKEUP_SWITCH:
-		if (hwsup)
-			clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]);
-		else
-			clkdm_sleep(pwrdm->pwrdm_clkdms[0]);
-		break;
-	case LOWPOWERSTATE_SWITCH:
-		pwrdm_set_lowpwrstchange(pwrdm);
-		pwrdm_state_switch(pwrdm);
-		break;
-	}
-
-	return ret;
-}
-
-
-
-/*
  * This API is to be called during init to set the various voltage
  * domains to the voltage as per the opp table. Typically we boot up
  * at the nominal voltage. So this function finds out the rate of
arch/arm/mach-omap2/pm.h +0 -1
index 686137d..707e9cb 100644
@@ -33,7 +33,6 @@ static inline int omap4_idle_init(void)
 extern void *omap3_secure_ram_storage;
 extern void omap3_pm_off_mode_enable(int);
 extern void omap_sram_idle(void);
-extern int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state);
 extern int omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused);
 extern int (*omap_pm_suspend)(void);
 
arch/arm/mach-omap2/powerdomain.c +83 -29

124 lines not on this page · raw message

arch/arm/mach-omap2/powerdomain.h +2 -1
index 7c1534b..1edb3b7 100644
@@ -228,10 +228,11 @@ bool pwrdm_has_hdwr_sar(struct powerdomain *pwrdm);
 int pwrdm_state_switch(struct powerdomain *pwrdm);
 int pwrdm_pre_transition(struct powerdomain *pwrdm);
 int pwrdm_post_transition(struct powerdomain *pwrdm);
-int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm);
 int pwrdm_get_context_loss_count(struct powerdomain *pwrdm);
 bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm);
 
+extern int omap_set_pwrdm_state(struct powerdomain *pwrdm, u8 state);
+
 extern void omap242x_powerdomains_init(void);
 extern void omap243x_powerdomains_init(void);
 extern void omap3xxx_powerdomains_init(void);
#12 lore raw

PATCH 5/10 ARM: OMAP2+: PM/powerdomain: move omap_set_pwrdm_state() to powerdomain code

Hi Paul,

Quoted 4 lines · Paul Walmsley

Move omap_set_pwrdm_state() from the PM code to the powerdomain code, and refactor it to split it up into several functions. A subsequent patch will rename it to conform with the existing powerdomain function names.

Glad to see this rather cryptic function getting a rewrite. It had never been clear what the function is doing so I think it owes some more comments.

More comments below.

Quoted 115 lines
Cc Jean Pihet <[email protected]>
Cc Kevin Hilman <[email protected]>
---
 arch/arm/mach-omap2/pm.c          |   61 --------------------
 arch/arm/mach-omap2/pm.h          |    1
 arch/arm/mach-omap2/powerdomain.c |  112
+++++++++++++++++++++++++++----------
 arch/arm/mach-omap2/powerdomain.h |    3 +
 4 files changed, 85 insertions(+), 92 deletions(-)
arch/arm/mach-omap2/pm.c +0 -61
index cc8ed0f..2e2a897 100644
@@ -76,10 +76,6 @@ static void __init omap2_init_processor_devices(void)
        }
 }
 
-/* Types of sleep_switch used in omap_set_pwrdm_state */
-#define FORCEWAKEUP_SWITCH     0
-#define LOWPOWERSTATE_SWITCH   1
-
 int __init omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused)
 {
        if ((clkdm->flags & CLKDM_CAN_ENABLE_AUTO) &&
@@ -92,63 +88,6 @@ int __init omap_pm_clkdms_setup(struct clockdomain
 *clkdm, void *unused)
 }
 
 /*
- * This sets pwrdm state (other than mpu & core. Currently only ON &
- * RET are supported.
- */
-int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 pwrst)
-{
-       u8 curr_pwrst, next_pwrst;
-       int sleep_switch = -1, ret = 0, hwsup = 0;
-
-       if (!pwrdm || IS_ERR(pwrdm))
-               return -EINVAL;
-
-       while (!(pwrdm->pwrsts & (1 << pwrst))) {
-               if (pwrst == PWRDM_POWER_OFF)
-                       return ret;
-               pwrst--;
-       }
-
-       next_pwrst = pwrdm_read_next_pwrst(pwrdm);
-       if (next_pwrst == pwrst)
-               return ret;
-
-       curr_pwrst = pwrdm_read_pwrst(pwrdm);
-       if (curr_pwrst < PWRDM_POWER_ON) {
-               if ((curr_pwrst > pwrst) &&
-                       (pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE)) {
-                       sleep_switch = LOWPOWERSTATE_SWITCH;
-               } else {
-                       hwsup = clkdm_in_hwsup(pwrdm->pwrdm_clkdms[0]);
-                       clkdm_wakeup(pwrdm->pwrdm_clkdms[0]);
-                       sleep_switch = FORCEWAKEUP_SWITCH;
-               }
-       }
-
-       ret = pwrdm_set_next_pwrst(pwrdm, pwrst);
-       if (ret)
-               pr_err("%s: unable to set power state of powerdomain:
 %s\n",
-                      __func__, pwrdm->name);
-
-       switch (sleep_switch) {
-       case FORCEWAKEUP_SWITCH:
-               if (hwsup)
-                       clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]);
-               else
-                       clkdm_sleep(pwrdm->pwrdm_clkdms[0]);
-               break;
-       case LOWPOWERSTATE_SWITCH:
-               pwrdm_set_lowpwrstchange(pwrdm);
-               pwrdm_state_switch(pwrdm);
-               break;
-       }
-
-       return ret;
-}
-
-
-
-/*
  * This API is to be called during init to set the various voltage

* domains to the voltage as per the opp table. Typically we boot up
* at the nominal voltage. So this function finds out the rate of

arch/arm/mach-omap2/pm.h +0 -1
index 686137d..707e9cb 100644
@@ -33,7 +33,6 @@ static inline int omap4_idle_init(void)
 extern void *omap3_secure_ram_storage;
 extern void omap3_pm_off_mode_enable(int);
 extern void omap_sram_idle(void);
-extern int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state);
 extern int omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused);
 extern int (*omap_pm_suspend)(void);
 
arch/arm/mach-omap2/powerdomain.c +0 -1
index 97b3881..05f00660 100644
@@ -921,35 +921,6 @@ bool pwrdm_has_hdwr_sar(struct powerdomain *pwrdm)
        return (pwrdm && pwrdm->flags & PWRDM_HAS_HDWR_SAR) ? 1 : 0;
 }
 
-/**

arch/arm/mach-omap2/powerdomain.c bool pwrdm_has_hdwr_sar(struct powerdomain *pwrdm) · line 924

Quoted 10 lines
arch/arm/mach-omap2/powerdomain.c +0 -9
- * pwrdm_set_lowpwrstchange - Request a low power state change
- * @pwrdm: struct powerdomain *
- *
- * Allows a powerdomain to transtion to a lower power sleep state
- * from an existing sleep state without waking up the powerdomain.
- * Returns -EINVAL if the powerdomain pointer is null or if the
- * powerdomain does not support LOWPOWERSTATECHANGE, or returns 0
- * upon success.
- */
 

Can this kerneldoc be reused in the new code?

-int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm)

Quoted 22 lines
arch/arm/mach-omap2/powerdomain.c +0 -18
-{
-       int ret = -EINVAL;
-
-       if (!pwrdm)
-               return -EINVAL;
-
-       if (!(pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE))
-               return -EINVAL;
-
-       pr_debug("powerdomain: %s: setting LOWPOWERSTATECHANGE bit\n",
-                pwrdm->name);
-
-       if (arch_pwrdm && arch_pwrdm->pwrdm_set_lowpwrstchange)
-               ret = arch_pwrdm->pwrdm_set_lowpwrstchange(pwrdm);
-
-       return ret;
-}
-
 int pwrdm_state_switch(struct powerdomain *pwrdm)
 {
        int ret;

arch/arm/mach-omap2/powerdomain.c int pwrdm_post_transition(struct powerdomain *pwrdm) · line 962

Quoted 8 lines
arch/arm/mach-omap2/powerdomain.c +4 -0
@@ -984,6 +955,89 @@ int pwrdm_post_transition(struct powerdomain *pwrdm)
        return 0;
 }
 
+/* Types of sleep_switch used in omap_set_pwrdm_state */
+#define ALREADYACTIVE_SWITCH   0
+#define FORCEWAKEUP_SWITCH     1
+#define LOWPOWERSTATE_SWITCH   2
 

Could you add some more documentation here?
What is the goal of the function, what does it return etc. ?

arch/arm/mach-omap2/powerdomain.c int pwrdm_post_transition(struct powerdomain *pwrdm) · line 964

Quoted 3 lines
arch/arm/mach-omap2/powerdomain.c +3 -0
+
+static u8 _pwrdm_save_clkdm_state_and_activate(struct powerdomain *pwrdm,
+                                              u8 pwrst, bool *hwsup)

+{

Quoted 11 lines
arch/arm/mach-omap2/powerdomain.c +11 -0
+       u8 curr_pwrst, sleep_switch;
+
+       curr_pwrst = pwrdm_read_pwrst(pwrdm);
+       if (curr_pwrst < PWRDM_POWER_ON) {
+               if (curr_pwrst > pwrst &&
+                   pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE &&
+                   arch_pwrdm->pwrdm_set_lowpwrstchange) {
+                       sleep_switch = LOWPOWERSTATE_SWITCH;
+               } else {
+                       *hwsup = clkdm_in_hwsup(pwrdm->pwrdm_clkdms[0]);
+                       clkdm_wakeup(pwrdm->pwrdm_clkdms[0]);

arch/arm/mach-omap2/powerdomain.c int pwrdm_post_transition(struct powerdomain *pwrdm)

Quoted 10 lines
arch/arm/mach-omap2/powerdomain.c +9 -0
+                       sleep_switch = FORCEWAKEUP_SWITCH;
+               }
+       } else {
+               sleep_switch = ALREADYACTIVE_SWITCH;
+       }
+
+       return sleep_switch;
+}
+
 

Same here

Quoted 14 lines
arch/arm/mach-omap2/powerdomain.c +14 -0
+static void _pwrdm_restore_clkdm_state(struct powerdomain *pwrdm,
+                                      u8 sleep_switch, bool hwsup)
+{
+       switch (sleep_switch) {
+       case FORCEWAKEUP_SWITCH:
+               if (hwsup)
+                       clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]);
+               else
+                       clkdm_sleep(pwrdm->pwrdm_clkdms[0]);
+               break;
+       case LOWPOWERSTATE_SWITCH:
+               if (pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE &&
+                   arch_pwrdm->pwrdm_set_lowpwrstchange)
+                       arch_pwrdm->pwrdm_set_lowpwrstchange(pwrdm);

arch/arm/mach-omap2/powerdomain.c int pwrdm_post_transition(struct powerdomain *pwrdm)

Quoted 10 lines
arch/arm/mach-omap2/powerdomain.c +9 -0
+               pwrdm_state_switch(pwrdm);
+               break;
+       }
+}
+
+/*
+ * This sets pwrdm state (other than mpu & core. Currently only ON &
+ * RET are supported.
+ */
 

Same here.
Is this one correct?

Regards,
Jean

Quoted 47 lines
arch/arm/mach-omap2/powerdomain.c +25 -0
+int omap_set_pwrdm_state(struct powerdomain *pwrdm, u8 pwrst)
+{
+       u8 next_pwrst, sleep_switch;
+       int ret = 0;
+       bool hwsup = false;
+
+       if (!pwrdm || IS_ERR(pwrdm))
+               return -EINVAL;
+
+       while (!(pwrdm->pwrsts & (1 << pwrst))) {
+               if (pwrst == PWRDM_POWER_OFF)
+                       return ret;
+               pwrst--;
+       }
+
+       next_pwrst = pwrdm_read_next_pwrst(pwrdm);
+       if (next_pwrst == pwrst)
+               return ret;
+
+       sleep_switch = _pwrdm_save_clkdm_state_and_activate(pwrdm, pwrst,
+                                                           &hwsup);
+
+       ret = pwrdm_set_next_pwrst(pwrdm, pwrst);
+       if (ret)
+               pr_err("%s: unable to set power state of powerdomain:

%s\n",

arch/arm/mach-omap2/powerdomain.c +7 -0
+                      __func__, pwrdm->name);
+
+       _pwrdm_restore_clkdm_state(pwrdm, sleep_switch, hwsup);
+
+       return ret;
+}
+
 /**
  * pwrdm_get_context_loss_count - get powerdomain's context loss count
  * @pwrdm: struct powerdomain * to wait for
arch/arm/mach-omap2/powerdomain.h +0 -0
index 7c1534b..1edb3b7 100644
@@ -228,10 +228,11 @@ bool pwrdm_has_hdwr_sar(struct powerdomain *pwrdm);
 int pwrdm_state_switch(struct powerdomain *pwrdm);
 int pwrdm_pre_transition(struct powerdomain *pwrdm);

arch/arm/mach-omap2/powerdomain.h bool pwrdm_has_hdwr_sar(struct powerdomain *pwrdm); · line 238

Quoted 10 lines
arch/arm/mach-omap2/powerdomain.h +2 -1
 int pwrdm_post_transition(struct powerdomain *pwrdm);
-int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm);
 int pwrdm_get_context_loss_count(struct powerdomain *pwrdm);
 bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm);
 
+extern int omap_set_pwrdm_state(struct powerdomain *pwrdm, u8 state);
+
 extern void omap242x_powerdomains_init(void);
 extern void omap243x_powerdomains_init(void);
 extern void omap3xxx_powerdomains_init(void);

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20121212/3e4e3a15/attachment-0001.html>

author maintainer
#13 lore raw

PATCH 5/10 ARM: OMAP2+: PM/powerdomain: move omap_set_pwrdm_state() to powerdomain code

Hi,

(redacted irrelevant code sections)

Quoted 14 lines · Jean Pihet
Quoted 11 lines · Paul Walmsley

-/**
- * pwrdm_set_lowpwrstchange - Request a low power state change
- * @pwrdm: struct powerdomain *
- *
- * Allows a powerdomain to transtion to a lower power sleep state
- * from an existing sleep state without waking up the powerdomain.
- * Returns -EINVAL if the powerdomain pointer is null or if the
- * powerdomain does not support LOWPOWERSTATECHANGE, or returns 0
- * upon success.
- */

Quoted 1 line

Can this kerneldoc be reused in the new code?

Not directly, since the function is being removed. But I've added some LOWPOWERSTATECHANGE-related documentation in powerdomain.h in the updated patch (below).

Quoted 4 lines
Quoted 4 lines
(quoted diff) +0 -0
@@ -984,6 +955,89 @@ int pwrdm_post_transition(struct powerdomain *pwrdm)
        return 0;
 }
 
Quoted 8 lines

Review int pwrdm_post_transition(struct powerdomain *pwrdm) · line 962

Quoted 5 lines
(quoted diff) +4 -0
+/* Types of sleep_switch used in omap_set_pwrdm_state */
+#define ALREADYACTIVE_SWITCH   0
+#define FORCEWAKEUP_SWITCH     1
+#define LOWPOWERSTATE_SWITCH   2
 

Could you add some more documentation here?
What is the goal of the function, what does it return etc. ?

I've added some related kerneldoc to omap_set_pwrdm_state().

Quoted 10 lines

Review int pwrdm_post_transition(struct powerdomain *pwrdm) · line 965

Quoted 3 lines
(quoted diff) +3 -0
+
+static u8 _pwrdm_save_clkdm_state_and_activate(struct powerdomain *pwrdm,
+                                              u8 pwrst, bool *hwsup)

Same here

Review int pwrdm_post_transition(struct powerdomain *pwrdm) · line 967

Quoted 2 lines
(quoted diff) +2 -0
+static void _pwrdm_restore_clkdm_state(struct powerdomain *pwrdm,
+                                      u8 sleep_switch, bool hwsup)

Same here.

I've added kerneldoc for both of these functions.

Quoted 6 lines

Review int pwrdm_post_transition(struct powerdomain *pwrdm) · line 972

Quoted 5 lines
(quoted diff) +4 -0
+/*
+ * This sets pwrdm state (other than mpu & core. Currently only ON &
+ * RET are supported.
+ */
 

Is this one correct?

This is just a cut and paste from the previous comments in the file. I agree that it is not helpful, so I've added kerneldoc for omap_set_pwrdm_state().

The updated patch follows.

- Paul

From: Paul Walmsley <[email protected]>
Date: Tue, 29 Jan 2013 13:45:09 -0700
Subject: [PATCH] ARM: OMAP2+: PM/powerdomain: move omap_set_pwrdm_state() to
powerdomain code

Move omap_set_pwrdm_state() from the PM code to the powerdomain code, and refactor it to split it up into several functions. A subsequent patch will rename it to conform with the existing powerdomain function names.

This version includes some additional documentation, based on a suggestion from Jean Pihet. It also modifies omap_set_pwrdm_state() to not bail out early unless both the powerdomain current power state and the next power state are equal. (Previously it would terminate early if the next power state was equal to the target power state, which was insufficiently rigorous.)

Cc Jean Pihet <[email protected]>
Cc Kevin Hilman <[email protected]>
Cc Tero Kristo <[email protected]>
---
 arch/arm/mach-omap2/pm.c          |   61 --------------
 arch/arm/mach-omap2/pm.h          |    1 -
 arch/arm/mach-omap2/powerdomain.c |  161 ++++++++++++++++++++++++++++++-------
 arch/arm/mach-omap2/powerdomain.h |   13 ++-
 4 files changed, 144 insertions(+), 92 deletions(-)
arch/arm/mach-omap2/pm.c +0 -61
index f18afc9..48d6d5d 100644
@@ -108,10 +108,6 @@ static void __init omap2_init_processor_devices(void)
 	}
 }
 
-/* Types of sleep_switch used in omap_set_pwrdm_state */
-#define FORCEWAKEUP_SWITCH	0
-#define LOWPOWERSTATE_SWITCH	1
-
 int __init omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused)
 {
 	if ((clkdm->flags & CLKDM_CAN_ENABLE_AUTO) &&
@@ -124,63 +120,6 @@ int __init omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused)
 }
 
 /*
- * This sets pwrdm state (other than mpu & core. Currently only ON &
- * RET are supported.
- */
-int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 pwrst)
-{
-	u8 curr_pwrst, next_pwrst;
-	int sleep_switch = -1, ret = 0, hwsup = 0;
-
-	if (!pwrdm || IS_ERR(pwrdm))
-		return -EINVAL;
-
-	while (!(pwrdm->pwrsts & (1 << pwrst))) {
-		if (pwrst == PWRDM_POWER_OFF)
-			return ret;
-		pwrst--;
-	}
-
-	next_pwrst = pwrdm_read_next_pwrst(pwrdm);
-	if (next_pwrst == pwrst)
-		return ret;
-
-	curr_pwrst = pwrdm_read_pwrst(pwrdm);
-	if (curr_pwrst < PWRDM_POWER_ON) {
-		if ((curr_pwrst > pwrst) &&
-			(pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE)) {
-			sleep_switch = LOWPOWERSTATE_SWITCH;
-		} else {
-			hwsup = clkdm_in_hwsup(pwrdm->pwrdm_clkdms[0]);
-			clkdm_wakeup(pwrdm->pwrdm_clkdms[0]);
-			sleep_switch = FORCEWAKEUP_SWITCH;
-		}
-	}
-
-	ret = pwrdm_set_next_pwrst(pwrdm, pwrst);
-	if (ret)
-		pr_err("%s: unable to set power state of powerdomain: %s\n",
-		       __func__, pwrdm->name);
-
-	switch (sleep_switch) {
-	case FORCEWAKEUP_SWITCH:
-		if (hwsup)
-			clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]);
-		else
-			clkdm_sleep(pwrdm->pwrdm_clkdms[0]);
-		break;
-	case LOWPOWERSTATE_SWITCH:
-		pwrdm_set_lowpwrstchange(pwrdm);
-		pwrdm_state_switch(pwrdm);
-		break;
-	}
-
-	return ret;
-}
-
-
-
-/*
  * This API is to be called during init to set the various voltage
  * domains to the voltage as per the opp table. Typically we boot up
  * at the nominal voltage. So this function finds out the rate of
arch/arm/mach-omap2/pm.h +0 -1
index c22503b..7bdd22a 100644
@@ -33,7 +33,6 @@ static inline int omap4_idle_init(void)
 extern void *omap3_secure_ram_storage;
 extern void omap3_pm_off_mode_enable(int);
 extern void omap_sram_idle(void);
-extern int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state);
 extern int omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused);
 extern int (*omap_pm_suspend)(void);
 
arch/arm/mach-omap2/powerdomain.c +132 -29

185 lines not on this page · raw message

arch/arm/mach-omap2/powerdomain.h +12 -1
index 7c1534b..93e7df8 100644
@@ -162,6 +162,16 @@ struct powerdomain {
  * @pwrdm_disable_hdwr_sar: Disable Hardware Save-Restore feature for a pd
  * @pwrdm_set_lowpwrstchange: Enable pd transitions from a shallow to deep sleep
  * @pwrdm_wait_transition: Wait for a pd state transition to complete
+ *
+ * Regarding @pwrdm_set_lowpwrstchange: On the OMAP2 and 3-family
+ * chips, a powerdomain's power state is not allowed to directly
+ * transition from one low-power state (e.g., CSWR) to another
+ * low-power state (e.g., OFF) without first waking up the
+ * powerdomain.  This wastes energy.  So OMAP4 chips support the
+ * ability to transition a powerdomain power state directly from one
+ * low-power state to another.  The function pointed to by
+ * @pwrdm_set_lowpwrstchange is intended to configure the OMAP4
+ * hardware powerdomain state machine to enable this feature.
  */
 struct pwrdm_ops {
 	int	(*pwrdm_set_next_pwrst)(struct powerdomain *pwrdm, u8 pwrst);
@@ -228,10 +238,11 @@ bool pwrdm_has_hdwr_sar(struct powerdomain *pwrdm);
 int pwrdm_state_switch(struct powerdomain *pwrdm);
 int pwrdm_pre_transition(struct powerdomain *pwrdm);
 int pwrdm_post_transition(struct powerdomain *pwrdm);
-int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm);
 int pwrdm_get_context_loss_count(struct powerdomain *pwrdm);
 bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm);
 
+extern int omap_set_pwrdm_state(struct powerdomain *pwrdm, u8 state);
+
 extern void omap242x_powerdomains_init(void);
 extern void omap243x_powerdomains_init(void);
 extern void omap3xxx_powerdomains_init(void);
Signature · 1 line
1.7.10.4
#14 lore raw

PATCH 5/10 ARM: OMAP2+: PM/powerdomain: move omap_set_pwrdm_state() to powerdomain code

In reply to Paul Walmsley

Minor comment below,

Quoted 32 lines · Paul Walmsley

Move omap_set_pwrdm_state() from the PM code to the powerdomain code, and refactor it to split it up into several functions. A subsequent patch will rename it to conform with the existing powerdomain function names.

Cc Jean Pihet <[email protected]>
Cc Kevin Hilman <[email protected]>
---
 arch/arm/mach-omap2/pm.c          |   61 --------------------
 arch/arm/mach-omap2/pm.h          |    1 
 arch/arm/mach-omap2/powerdomain.c |  112 +++++++++++++++++++++++++++----------
 arch/arm/mach-omap2/powerdomain.h |    3 +
 4 files changed, 85 insertions(+), 92 deletions(-)
arch/arm/mach-omap2/pm.c +0 -4
index cc8ed0f..2e2a897 100644
@@ -76,10 +76,6 @@ static void __init omap2_init_processor_devices(void)
 	}
 }
 
-/* Types of sleep_switch used in omap_set_pwrdm_state */
-#define FORCEWAKEUP_SWITCH	0
-#define LOWPOWERSTATE_SWITCH	1
-
 int __init omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused)
 {
 	if ((clkdm->flags & CLKDM_CAN_ENABLE_AUTO) &&
@@ -92,63 +88,6 @@ int __init omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused)
 }
 

arch/arm/mach-omap2/pm.c int __init omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused) · line 103

Quoted 10 lines
arch/arm/mach-omap2/pm.c +0 -9
 /*
- * This sets pwrdm state (other than mpu & core. Currently only ON &
- * RET are supported.
- */
-int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 pwrst)
-{
-	u8 curr_pwrst, next_pwrst;
-	int sleep_switch = -1, ret = 0, hwsup = 0;
-
-	if (!pwrdm || IS_ERR(pwrdm))

You can use IS_ERR_OR_NULL here.

Thanks,
Vaibhav

Quoted 218 lines
arch/arm/mach-omap2/pm.c +0 -48
-		return -EINVAL;
-
-	while (!(pwrdm->pwrsts & (1 << pwrst))) {
-		if (pwrst == PWRDM_POWER_OFF)
-			return ret;
-		pwrst--;
-	}
-
-	next_pwrst = pwrdm_read_next_pwrst(pwrdm);
-	if (next_pwrst == pwrst)
-		return ret;
-
-	curr_pwrst = pwrdm_read_pwrst(pwrdm);
-	if (curr_pwrst < PWRDM_POWER_ON) {
-		if ((curr_pwrst > pwrst) &&
-			(pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE)) {
-			sleep_switch = LOWPOWERSTATE_SWITCH;
-		} else {
-			hwsup = clkdm_in_hwsup(pwrdm->pwrdm_clkdms[0]);
-			clkdm_wakeup(pwrdm->pwrdm_clkdms[0]);
-			sleep_switch = FORCEWAKEUP_SWITCH;
-		}
-	}
-
-	ret = pwrdm_set_next_pwrst(pwrdm, pwrst);
-	if (ret)
-		pr_err("%s: unable to set power state of powerdomain: %s\n",
-		       __func__, pwrdm->name);
-
-	switch (sleep_switch) {
-	case FORCEWAKEUP_SWITCH:
-		if (hwsup)
-			clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]);
-		else
-			clkdm_sleep(pwrdm->pwrdm_clkdms[0]);
-		break;
-	case LOWPOWERSTATE_SWITCH:
-		pwrdm_set_lowpwrstchange(pwrdm);
-		pwrdm_state_switch(pwrdm);
-		break;
-	}
-
-	return ret;
-}
-
-
-
-/*
  * This API is to be called during init to set the various voltage
  * domains to the voltage as per the opp table. Typically we boot up
  * at the nominal voltage. So this function finds out the rate of
arch/arm/mach-omap2/pm.h +0 -1
index 686137d..707e9cb 100644
@@ -33,7 +33,6 @@ static inline int omap4_idle_init(void)
 extern void *omap3_secure_ram_storage;
 extern void omap3_pm_off_mode_enable(int);
 extern void omap_sram_idle(void);
-extern int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state);
 extern int omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused);
 extern int (*omap_pm_suspend)(void);
 
arch/arm/mach-omap2/powerdomain.c +83 -29
index 97b3881..05f00660 100644
@@ -921,35 +921,6 @@ bool pwrdm_has_hdwr_sar(struct powerdomain *pwrdm)
 	return (pwrdm && pwrdm->flags & PWRDM_HAS_HDWR_SAR) ? 1 : 0;
 }
 
-/**
- * pwrdm_set_lowpwrstchange - Request a low power state change
- * @pwrdm: struct powerdomain *
- *
- * Allows a powerdomain to transtion to a lower power sleep state
- * from an existing sleep state without waking up the powerdomain.
- * Returns -EINVAL if the powerdomain pointer is null or if the
- * powerdomain does not support LOWPOWERSTATECHANGE, or returns 0
- * upon success.
- */
-int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm)
-{
-	int ret = -EINVAL;
-
-	if (!pwrdm)
-		return -EINVAL;
-
-	if (!(pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE))
-		return -EINVAL;
-
-	pr_debug("powerdomain: %s: setting LOWPOWERSTATECHANGE bit\n",
-		 pwrdm->name);
-
-	if (arch_pwrdm && arch_pwrdm->pwrdm_set_lowpwrstchange)
-		ret = arch_pwrdm->pwrdm_set_lowpwrstchange(pwrdm);
-
-	return ret;
-}
-
 int pwrdm_state_switch(struct powerdomain *pwrdm)
 {
 	int ret;
@@ -984,6 +955,89 @@ int pwrdm_post_transition(struct powerdomain *pwrdm)
 	return 0;
 }
 
+/* Types of sleep_switch used in omap_set_pwrdm_state */
+#define ALREADYACTIVE_SWITCH	0
+#define FORCEWAKEUP_SWITCH	1
+#define LOWPOWERSTATE_SWITCH	2
+
+static u8 _pwrdm_save_clkdm_state_and_activate(struct powerdomain *pwrdm,
+					       u8 pwrst, bool *hwsup)
+{
+	u8 curr_pwrst, sleep_switch;
+
+	curr_pwrst = pwrdm_read_pwrst(pwrdm);
+	if (curr_pwrst < PWRDM_POWER_ON) {
+		if (curr_pwrst > pwrst &&
+		    pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE &&
+		    arch_pwrdm->pwrdm_set_lowpwrstchange) {
+			sleep_switch = LOWPOWERSTATE_SWITCH;
+		} else {
+			*hwsup = clkdm_in_hwsup(pwrdm->pwrdm_clkdms[0]);
+			clkdm_wakeup(pwrdm->pwrdm_clkdms[0]);
+			sleep_switch = FORCEWAKEUP_SWITCH;
+		}
+	} else {
+		sleep_switch = ALREADYACTIVE_SWITCH;
+	}
+
+	return sleep_switch;
+}
+
+static void _pwrdm_restore_clkdm_state(struct powerdomain *pwrdm,
+				       u8 sleep_switch, bool hwsup)
+{
+	switch (sleep_switch) {
+	case FORCEWAKEUP_SWITCH:
+		if (hwsup)
+			clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]);
+		else
+			clkdm_sleep(pwrdm->pwrdm_clkdms[0]);
+		break;
+	case LOWPOWERSTATE_SWITCH:
+		if (pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE &&
+		    arch_pwrdm->pwrdm_set_lowpwrstchange)
+			arch_pwrdm->pwrdm_set_lowpwrstchange(pwrdm);
+		pwrdm_state_switch(pwrdm);
+		break;
+	}
+}
+
+/*
+ * This sets pwrdm state (other than mpu & core. Currently only ON &
+ * RET are supported.
+ */
+int omap_set_pwrdm_state(struct powerdomain *pwrdm, u8 pwrst)
+{
+	u8 next_pwrst, sleep_switch;
+	int ret = 0;
+	bool hwsup = false;
+
+	if (!pwrdm || IS_ERR(pwrdm))
+		return -EINVAL;
+
+	while (!(pwrdm->pwrsts & (1 << pwrst))) {
+		if (pwrst == PWRDM_POWER_OFF)
+			return ret;
+		pwrst--;
+	}
+
+	next_pwrst = pwrdm_read_next_pwrst(pwrdm);
+	if (next_pwrst == pwrst)
+		return ret;
+
+	sleep_switch = _pwrdm_save_clkdm_state_and_activate(pwrdm, pwrst,
+							    &hwsup);
+
+	ret = pwrdm_set_next_pwrst(pwrdm, pwrst);
+	if (ret)
+		pr_err("%s: unable to set power state of powerdomain: %s\n",
+		       __func__, pwrdm->name);
+
+	_pwrdm_restore_clkdm_state(pwrdm, sleep_switch, hwsup);
+
+	return ret;
+}
+
 /**
  * pwrdm_get_context_loss_count - get powerdomain's context loss count
  * @pwrdm: struct powerdomain * to wait for
arch/arm/mach-omap2/powerdomain.h +2 -1
index 7c1534b..1edb3b7 100644
@@ -228,10 +228,11 @@ bool pwrdm_has_hdwr_sar(struct powerdomain *pwrdm);
 int pwrdm_state_switch(struct powerdomain *pwrdm);
 int pwrdm_pre_transition(struct powerdomain *pwrdm);
 int pwrdm_post_transition(struct powerdomain *pwrdm);
-int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm);
 int pwrdm_get_context_loss_count(struct powerdomain *pwrdm);
 bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm);
 
+extern int omap_set_pwrdm_state(struct powerdomain *pwrdm, u8 state);
+
 extern void omap242x_powerdomains_init(void);
 extern void omap243x_powerdomains_init(void);
 extern void omap3xxx_powerdomains_init(void);

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

#15 lore raw

PATCH 5/10 ARM: OMAP2+: PM/powerdomain: move omap_set_pwrdm_state() to powerdomain code

Quoted 8 lines · Vaibhav Hiremath

arch/arm/mach-omap2/pm.c int __init omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused) · line 103

Quoted 6 lines
arch/arm/mach-omap2/pm.c +0 -6
-int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 pwrst)
-{
-	u8 curr_pwrst, next_pwrst;
-	int sleep_switch = -1, ret = 0, hwsup = 0;
-
-	if (!pwrdm || IS_ERR(pwrdm))

You can use IS_ERR_OR_NULL here.

As this is removing code...

However, if you pay attention to linux-kernel or linux-arm-kernel, you will notice that I've sent a patch deprecating IS_ERR_OR_NULL() and I'm starting to remove its use. IS_ERR_OR_NULL() creates more problems than it solves because people don't think about what the hell they're doing with it, or even whether it's appropriate to use it.

#16 lore raw

PATCH 5/10 ARM: OMAP2+: PM/powerdomain: move omap_set_pwrdm_state() to powerdomain code

In reply to Paul Walmsley

Hi Paul,

-resending in plain text only, sorry about that-

Quoted 4 lines · Paul Walmsley

Move omap_set_pwrdm_state() from the PM code to the powerdomain code, and refactor it to split it up into several functions. A subsequent patch will rename it to conform with the existing powerdomain function names.

Glad to see this rather cryptic function getting a rewrite. It had never been clear what the function is doing so I think it owes some more comments.

More comments below.

Quoted 111 lines
Cc Jean Pihet <[email protected]>
Cc Kevin Hilman <[email protected]>
---
 arch/arm/mach-omap2/pm.c          |   61 --------------------
 arch/arm/mach-omap2/pm.h          |    1
 arch/arm/mach-omap2/powerdomain.c |  112 +++++++++++++++++++++++++++----------
 arch/arm/mach-omap2/powerdomain.h |    3 +
 4 files changed, 85 insertions(+), 92 deletions(-)
arch/arm/mach-omap2/pm.c +0 -61
index cc8ed0f..2e2a897 100644
@@ -76,10 +76,6 @@ static void __init omap2_init_processor_devices(void)
        }
 }
 
-/* Types of sleep_switch used in omap_set_pwrdm_state */
-#define FORCEWAKEUP_SWITCH     0
-#define LOWPOWERSTATE_SWITCH   1
-
 int __init omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused)
 {
        if ((clkdm->flags & CLKDM_CAN_ENABLE_AUTO) &&
@@ -92,63 +88,6 @@ int __init omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused)
 }
 
 /*
- * This sets pwrdm state (other than mpu & core. Currently only ON &
- * RET are supported.
- */
-int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 pwrst)
-{
-       u8 curr_pwrst, next_pwrst;
-       int sleep_switch = -1, ret = 0, hwsup = 0;
-
-       if (!pwrdm || IS_ERR(pwrdm))
-               return -EINVAL;
-
-       while (!(pwrdm->pwrsts & (1 << pwrst))) {
-               if (pwrst == PWRDM_POWER_OFF)
-                       return ret;
-               pwrst--;
-       }
-
-       next_pwrst = pwrdm_read_next_pwrst(pwrdm);
-       if (next_pwrst == pwrst)
-               return ret;
-
-       curr_pwrst = pwrdm_read_pwrst(pwrdm);
-       if (curr_pwrst < PWRDM_POWER_ON) {
-               if ((curr_pwrst > pwrst) &&
-                       (pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE)) {
-                       sleep_switch = LOWPOWERSTATE_SWITCH;
-               } else {
-                       hwsup = clkdm_in_hwsup(pwrdm->pwrdm_clkdms[0]);
-                       clkdm_wakeup(pwrdm->pwrdm_clkdms[0]);
-                       sleep_switch = FORCEWAKEUP_SWITCH;
-               }
-       }
-
-       ret = pwrdm_set_next_pwrst(pwrdm, pwrst);
-       if (ret)
-               pr_err("%s: unable to set power state of powerdomain: %s\n",
-                      __func__, pwrdm->name);
-
-       switch (sleep_switch) {
-       case FORCEWAKEUP_SWITCH:
-               if (hwsup)
-                       clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]);
-               else
-                       clkdm_sleep(pwrdm->pwrdm_clkdms[0]);
-               break;
-       case LOWPOWERSTATE_SWITCH:
-               pwrdm_set_lowpwrstchange(pwrdm);
-               pwrdm_state_switch(pwrdm);
-               break;
-       }
-
-       return ret;
-}
-
-
-
-/*
  * This API is to be called during init to set the various voltage
  * domains to the voltage as per the opp table. Typically we boot up
  * at the nominal voltage. So this function finds out the rate of
arch/arm/mach-omap2/pm.h +0 -1
index 686137d..707e9cb 100644
@@ -33,7 +33,6 @@ static inline int omap4_idle_init(void)
 extern void *omap3_secure_ram_storage;
 extern void omap3_pm_off_mode_enable(int);
 extern void omap_sram_idle(void);
-extern int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state);
 extern int omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused);
 extern int (*omap_pm_suspend)(void);
 
arch/arm/mach-omap2/powerdomain.c +0 -0
index 97b3881..05f00660 100644
@@ -921,35 +921,6 @@ bool pwrdm_has_hdwr_sar(struct powerdomain *pwrdm)
        return (pwrdm && pwrdm->flags & PWRDM_HAS_HDWR_SAR) ? 1 : 0;
 }
 

arch/arm/mach-omap2/powerdomain.c bool pwrdm_has_hdwr_sar(struct powerdomain *pwrdm) · line 933

Quoted 10 lines
arch/arm/mach-omap2/powerdomain.c +0 -10
-/**
- * pwrdm_set_lowpwrstchange - Request a low power state change
- * @pwrdm: struct powerdomain *
- *
- * Allows a powerdomain to transtion to a lower power sleep state
- * from an existing sleep state without waking up the powerdomain.
- * Returns -EINVAL if the powerdomain pointer is null or if the
- * powerdomain does not support LOWPOWERSTATECHANGE, or returns 0
- * upon success.
- */

Can this kerneldoc be reused in the new code?

Could you add some more documentation here?
What is the goal of the function, what does it return etc. ?

Quoted 16 lines
arch/arm/mach-omap2/powerdomain.c +14 -0
+
+static u8 _pwrdm_save_clkdm_state_and_activate(struct powerdomain *pwrdm,
+                                              u8 pwrst, bool *hwsup)
 
+{
+       u8 curr_pwrst, sleep_switch;
+
+       curr_pwrst = pwrdm_read_pwrst(pwrdm);
+       if (curr_pwrst < PWRDM_POWER_ON) {
+               if (curr_pwrst > pwrst &&
+                   pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE &&
+                   arch_pwrdm->pwrdm_set_lowpwrstchange) {
+                       sleep_switch = LOWPOWERSTATE_SWITCH;
+               } else {
+                       *hwsup = clkdm_in_hwsup(pwrdm->pwrdm_clkdms[0]);

arch/arm/mach-omap2/powerdomain.c int pwrdm_post_transition(struct powerdomain *pwrdm) · line 985

Quoted 10 lines
arch/arm/mach-omap2/powerdomain.c +10 -0
+                       clkdm_wakeup(pwrdm->pwrdm_clkdms[0]);
+                       sleep_switch = FORCEWAKEUP_SWITCH;
+               }
+       } else {
+               sleep_switch = ALREADYACTIVE_SWITCH;
+       }
+
+       return sleep_switch;
+}
+

Same here

Quoted 14 lines
arch/arm/mach-omap2/powerdomain.c +13 -0
+static void _pwrdm_restore_clkdm_state(struct powerdomain *pwrdm,
+                                      u8 sleep_switch, bool hwsup)
+{
+       switch (sleep_switch) {
+       case FORCEWAKEUP_SWITCH:
+               if (hwsup)
+                       clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]);
+               else
+                       clkdm_sleep(pwrdm->pwrdm_clkdms[0]);
+               break;
+       case LOWPOWERSTATE_SWITCH:
+               if (pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE &&
+                   arch_pwrdm->pwrdm_set_lowpwrstchange)

arch/arm/mach-omap2/powerdomain.c int pwrdm_post_transition(struct powerdomain *pwrdm) · line 1008

Quoted 10 lines
arch/arm/mach-omap2/powerdomain.c +10 -0
+                       arch_pwrdm->pwrdm_set_lowpwrstchange(pwrdm);
+               pwrdm_state_switch(pwrdm);
+               break;
+       }
+}
+
+/*
+ * This sets pwrdm state (other than mpu & core. Currently only ON &
+ * RET are supported.
+ */

Same here.
Is this one correct?

Regards,
Jean

+int omap_set_pwrdm_state(struct powerdomain *pwrdm, u8 pwrst) +{

+       u8 next_pwrst, sleep_switch;
+       int ret = 0;
+       bool hwsup = false;

+
+ if (!pwrdm || IS_ERR(pwrdm))
+ return -EINVAL;
+
+ while (!(pwrdm->pwrsts & (1 << pwrst))) {
+ if (pwrst == PWRDM_POWER_OFF)
+ return ret;
+ pwrst--;
+ }
+
+ next_pwrst = pwrdm_read_next_pwrst(pwrdm);
+ if (next_pwrst == pwrst)
+ return ret;
+
+ sleep_switch = _pwrdm_save_clkdm_state_and_

Quoted 34 lines

activate(pwrdm, pwrst,

arch/arm/mach-omap2/powerdomain.c +12 -0
+                                                           &hwsup);
+
+       ret = pwrdm_set_next_pwrst(pwrdm, pwrst);
+       if (ret)
+               pr_err("%s: unable to set power state of powerdomain: %s\n",
+                      __func__, pwrdm->name);
+
+       _pwrdm_restore_clkdm_state(pwrdm, sleep_switch, hwsup);
+
+       return ret;
+}
+
 /**
  * pwrdm_get_context_loss_count - get powerdomain's context loss count
  * @pwrdm: struct powerdomain * to wait for
arch/arm/mach-omap2/powerdomain.h +2 -1
index 7c1534b..1edb3b7 100644
@@ -228,10 +228,11 @@ bool pwrdm_has_hdwr_sar(struct powerdomain *pwrdm);
 int pwrdm_state_switch(struct powerdomain *pwrdm);
 int pwrdm_pre_transition(struct powerdomain *pwrdm);
 int pwrdm_post_transition(struct powerdomain *pwrdm);
-int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm);
 int pwrdm_get_context_loss_count(struct powerdomain *pwrdm);
 bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm);
 
+extern int omap_set_pwrdm_state(struct powerdomain *pwrdm, u8 state);
+
 extern void omap242x_powerdomains_init(void);
 extern void omap243x_powerdomains_init(void);
 extern void omap3xxx_powerdomains_init(void);
author maintainer
#17 lore raw

PATCH 6/10 ARM: OMAP2+: powerdomain/clockdomain: add a per-powerdomain spinlock

In reply to Paul Walmsley

Add a per-powerdomain spinlock. Use that instead of the clockdomain spinlock. Add pwrdm_lock()/pwrdm_unlock() functions to allow other code to acquire or release the powerdomain spinlock without reaching directly into the struct powerdomain.

---
 arch/arm/mach-omap2/clockdomain-powerdomain.h |   22 +++
 arch/arm/mach-omap2/clockdomain.c             |  161 +++++++++++++++++--------
 arch/arm/mach-omap2/clockdomain.h             |    6 +
 arch/arm/mach-omap2/powerdomain-clockdomain.h |   27 ++++
 arch/arm/mach-omap2/powerdomain.c             |   56 ++++++++-
 arch/arm/mach-omap2/powerdomain.h             |   11 +-
 6 files changed, 219 insertions(+), 64 deletions(-)
 create mode 100644 arch/arm/mach-omap2/clockdomain-powerdomain.h
 create mode 100644 arch/arm/mach-omap2/powerdomain-clockdomain.h
arch/arm/mach-omap2/clockdomain-powerdomain.h new file +22 -0
new file mode 100644
index 0000000..8beee2d
@@ -0,0 +1,22 @@
+/*
+ * OMAP clockdomain framework functions for use only by the powerdomain code
+ *
+ * Copyright (C) 2012 Texas Instruments, Inc.
+ * Paul Walmsley
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ARCH_ARM_MACH_OMAP2_CLOCKDOMAIN_POWERDOMAIN_H
+#define __ARCH_ARM_MACH_OMAP2_CLOCKDOMAIN_POWERDOMAIN_H
+
+#include "clockdomain.h"
+
+extern void clkdm_allow_idle_nolock(struct clockdomain *clkdm);
+extern void clkdm_deny_idle_nolock(struct clockdomain *clkdm);
+extern int clkdm_wakeup_nolock(struct clockdomain *clkdm);
+extern int clkdm_sleep_nolock(struct clockdomain *clkdm);
+
+#endif
arch/arm/mach-omap2/clockdomain.c +108 -53

295 lines not on this page · raw message

arch/arm/mach-omap2/clockdomain.h +4 -2
index bc42446..e7f1b4b 100644
@@ -15,7 +15,6 @@
 #define __ARCH_ARM_MACH_OMAP2_CLOCKDOMAIN_H
 
 #include <linux/init.h>
-#include <linux/spinlock.h>
 
 #include "powerdomain.h"
 #include "clock.h"
@@ -139,7 +138,6 @@ struct clockdomain {
 	struct clkdm_dep *sleepdep_srcs;
 	atomic_t usecount;
 	struct list_head node;
-	spinlock_t lock;
 };
 
 /**
@@ -196,12 +194,16 @@ int clkdm_del_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
 int clkdm_read_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
 int clkdm_clear_all_sleepdeps(struct clockdomain *clkdm);
 
+void clkdm_allow_idle_nolock(struct clockdomain *clkdm);
 void clkdm_allow_idle(struct clockdomain *clkdm);
+void clkdm_deny_idle_nolock(struct clockdomain *clkdm);
 void clkdm_deny_idle(struct clockdomain *clkdm);
 bool clkdm_in_hwsup(struct clockdomain *clkdm);
 bool clkdm_missing_idle_reporting(struct clockdomain *clkdm);
 
+int clkdm_wakeup_nolock(struct clockdomain *clkdm);
 int clkdm_wakeup(struct clockdomain *clkdm);
+int clkdm_sleep_nolock(struct clockdomain *clkdm);
 int clkdm_sleep(struct clockdomain *clkdm);
 
 int clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk);
arch/arm/mach-omap2/powerdomain-clockdomain.h new file +27 -0
new file mode 100644
index 0000000..e404eec
@@ -0,0 +1,27 @@
+/*
+ * OMAP powerdomain functions only for use by the OMAP clockdomain code
+ *
+ * Copyright (C) 2012 Texas Instruments, Inc.
+ * Paul Walmsley
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * The point of this file is to try to prevent other code outside of
+ * clockdomain.c from calling the functions listed herein.  Yes, this
+ * means you.
+ */
+
+#ifndef __ARCH_ARM_MACH_OMAP2_POWERDOMAIN_CLOCKDOMAIN_H
+#define __ARCH_ARM_MACH_OMAP2_POWERDOMAIN_CLOCKDOMAIN_H
+
+#include <linux/types.h>
+
+#include "powerdomain.h"
+
+extern void pwrdm_lock(struct powerdomain *pwrdm);
+extern void pwrdm_unlock(struct powerdomain *pwrdm);
+extern int pwrdm_state_switch_nolock(struct powerdomain *pwrdm);
+
+#endif
arch/arm/mach-omap2/powerdomain.c +50 -6

124 lines not on this page · raw message

arch/arm/mach-omap2/powerdomain.h +8 -3
index 1edb3b7..83b4892 100644
@@ -19,8 +19,7 @@
 
 #include <linux/types.h>
 #include <linux/list.h>
-
-#include <linux/atomic.h>
+#include <linux/spinlock.h>
 
 #include "voltage.h"
 
@@ -103,6 +102,8 @@ struct powerdomain;
  * @state_counter:
  * @timer:
  * @state_timer:
+ * @_lock: spinlock used to serialize powerdomain and some clockdomain ops
+ * @_lock_flags: stored flags when @_lock is taken
  *
  * @prcm_partition possible values are defined in mach-omap2/prcm44xx.h.
  */
@@ -127,7 +128,8 @@ struct powerdomain {
 	unsigned state_counter[PWRDM_MAX_PWRSTS];
 	unsigned ret_logic_off_counter;
 	unsigned ret_mem_off_counter[PWRDM_MAX_MEM_BANKS];
-
+	spinlock_t _lock;
+	unsigned long _lock_flags;
 	const u8 pwrstctrl_offs;
 	const u8 pwrstst_offs;
 	const u32 logicretstate_mask;
@@ -225,6 +227,7 @@ int pwrdm_enable_hdwr_sar(struct powerdomain *pwrdm);
 int pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm);
 bool pwrdm_has_hdwr_sar(struct powerdomain *pwrdm);
 
+int pwrdm_state_switch_nolock(struct powerdomain *pwrdm);
 int pwrdm_state_switch(struct powerdomain *pwrdm);
 int pwrdm_pre_transition(struct powerdomain *pwrdm);
 int pwrdm_post_transition(struct powerdomain *pwrdm);
@@ -252,5 +255,7 @@ extern u32 omap2_pwrdm_get_mem_bank_stst_mask(u8 bank);
 extern struct powerdomain wkup_omap2_pwrdm;
 extern struct powerdomain gfx_omap2_pwrdm;
 
+extern void pwrdm_lock(struct powerdomain *pwrdm);
+extern void pwrdm_unlock(struct powerdomain *pwrdm);
 
 #endif
#18 lore raw

PATCH 6/10 ARM: OMAP2+: powerdomain/clockdomain: add a per-powerdomain spinlock

Paul,

Quoted 5 lines · Paul Walmsley

Add a per-powerdomain spinlock. Use that instead of the clockdomain spinlock. Add pwrdm_lock()/pwrdm_unlock() functions to allow other code to acquire or release the powerdomain spinlock without reaching directly into the struct powerdomain.

Since clockdomains are part of powerdomains it seems weird for the clockdomain code to take a powerdoamin lock.
Is there a reason why the powerdomain could not take the lock before calling the clockdomain functions?

Also, are the lock and nolock version the clockdomain function needed?

Regards,
Jean

Quoted 626 lines
---
 arch/arm/mach-omap2/clockdomain-powerdomain.h |   22 +++
 arch/arm/mach-omap2/clockdomain.c             |  161
+++++++++++++++++--------
 arch/arm/mach-omap2/clockdomain.h             |    6 +
 arch/arm/mach-omap2/powerdomain-clockdomain.h |   27 ++++
 arch/arm/mach-omap2/powerdomain.c             |   56 ++++++++-
 arch/arm/mach-omap2/powerdomain.h             |   11 +-
 6 files changed, 219 insertions(+), 64 deletions(-)
 create mode 100644 arch/arm/mach-omap2/clockdomain-powerdomain.h
 create mode 100644 arch/arm/mach-omap2/powerdomain-clockdomain.h
arch/arm/mach-omap2/clockdomain-powerdomain.h new file +2 -0
new file mode 100644
index 0000000..8beee2d
@@ -0,0 +1,22 @@
+/*
+ * OMAP clockdomain framework functions for use only by the powerdomain

code
+ *
+ * Copyright (C) 2012 Texas Instruments, Inc.
+ * Paul Walmsley
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */

arch/arm/mach-omap2/clockdomain-powerdomain.h new file +12 -0
+
+#ifndef __ARCH_ARM_MACH_OMAP2_CLOCKDOMAIN_POWERDOMAIN_H
+#define __ARCH_ARM_MACH_OMAP2_CLOCKDOMAIN_POWERDOMAIN_H
+
+#include "clockdomain.h"
+
+extern void clkdm_allow_idle_nolock(struct clockdomain *clkdm);
+extern void clkdm_deny_idle_nolock(struct clockdomain *clkdm);
+extern int clkdm_wakeup_nolock(struct clockdomain *clkdm);
+extern int clkdm_sleep_nolock(struct clockdomain *clkdm);
+
+#endif
arch/arm/mach-omap2/clockdomain.c +6 -8
index 18f65fd..2142dab 100644
@@ -30,6 +30,7 @@
 #include "soc.h"
 #include "clock.h"
 #include "clockdomain.h"
+#include "powerdomain-clockdomain.h"
 
 /* clkdm_list contains all registered struct clockdomains */
 static LIST_HEAD(clkdm_list);
@@ -91,8 +92,6 @@ static int _clkdm_register(struct clockdomain *clkdm)
 
        pwrdm_add_clkdm(pwrdm, clkdm);
 
-       spin_lock_init(&clkdm->lock);
-
        pr_debug("clockdomain: registered %s\n", clkdm->name);
 
        return 0;
@@ -733,18 +732,17 @@ int clkdm_clear_all_sleepdeps(struct clockdomain
 *clkdm)
 }
 
 /**
- * clkdm_sleep - force clockdomain sleep transition
+ * clkdm_sleep_nolock - force clockdomain sleep transition (lockless)
  * @clkdm: struct clockdomain *
  *
  * Instruct the CM to force a sleep transition on the specified
- * clockdomain @clkdm.  Returns -EINVAL if @clkdm is NULL or if
- * clockdomain does not support software-initiated sleep; 0 upon
- * success.
+ * clockdomain @clkdm.  Only for use by the powerdomain code.  Returns
+ * -EINVAL if @clkdm is NULL or if clockdomain does not support
+ * software-initiated sleep; 0 upon success.
  */
-int clkdm_sleep(struct clockdomain *clkdm)
+int clkdm_sleep_nolock(struct clockdomain *clkdm)
 {
        int ret;
-       unsigned long flags;
 
        if (!clkdm)
                return -EINVAL;
arch/arm/mach-omap2/clockdomain.c +73 -22
@@ -760,27 +758,45 @@ int clkdm_sleep(struct clockdomain *clkdm)
 
        pr_debug("clockdomain: forcing sleep on %s\n", clkdm->name);
 
-       spin_lock_irqsave(&clkdm->lock, flags);
        clkdm->_flags &= ~_CLKDM_FLAG_HWSUP_ENABLED;
        ret = arch_clkdm->clkdm_sleep(clkdm);
-       ret |= pwrdm_state_switch(clkdm->pwrdm.ptr);
-       spin_unlock_irqrestore(&clkdm->lock, flags);
+       ret |= pwrdm_state_switch_nolock(clkdm->pwrdm.ptr);
+
        return ret;
 }
 
 /**
- * clkdm_wakeup - force clockdomain wakeup transition
+ * clkdm_sleep - force clockdomain sleep transition
  * @clkdm: struct clockdomain *
  *
- * Instruct the CM to force a wakeup transition on the specified
- * clockdomain @clkdm.  Returns -EINVAL if @clkdm is NULL or if the
- * clockdomain does not support software-controlled wakeup; 0 upon
+ * Instruct the CM to force a sleep transition on the specified
+ * clockdomain @clkdm.  Returns -EINVAL if @clkdm is NULL or if
+ * clockdomain does not support software-initiated sleep; 0 upon
  * success.
  */
-int clkdm_wakeup(struct clockdomain *clkdm)
+int clkdm_sleep(struct clockdomain *clkdm)
+{
+       int ret;
+
+       pwrdm_lock(clkdm->pwrdm.ptr);
+       ret = clkdm_sleep_nolock(clkdm);
+       pwrdm_unlock(clkdm->pwrdm.ptr);
+
+       return ret;
+}
+
+/**
+ * clkdm_wakeup_nolock - force clockdomain wakeup transition (lockless)
+ * @clkdm: struct clockdomain *
+ *
+ * Instruct the CM to force a wakeup transition on the specified
+ * clockdomain @clkdm.  Only for use by the powerdomain code.  Returns
+ * -EINVAL if @clkdm is NULL or if the clockdomain does not support
+ * software-controlled wakeup; 0 upon success.
+ */
+int clkdm_wakeup_nolock(struct clockdomain *clkdm)
 {
        int ret;
-       unsigned long flags;
 
        if (!clkdm)
                return -EINVAL;
@@ -796,28 +812,46 @@ int clkdm_wakeup(struct clockdomain *clkdm)
 
        pr_debug("clockdomain: forcing wakeup on %s\n", clkdm->name);
 
-       spin_lock_irqsave(&clkdm->lock, flags);
        clkdm->_flags &= ~_CLKDM_FLAG_HWSUP_ENABLED;
        ret = arch_clkdm->clkdm_wakeup(clkdm);
-       ret |= pwrdm_state_switch(clkdm->pwrdm.ptr);
-       spin_unlock_irqrestore(&clkdm->lock, flags);
+       ret |= pwrdm_state_switch_nolock(clkdm->pwrdm.ptr);
+
        return ret;
 }
 
 /**
- * clkdm_allow_idle - enable hwsup idle transitions for clkdm
+ * clkdm_wakeup - force clockdomain wakeup transition
  * @clkdm: struct clockdomain *
  *
- * Allow the hardware to automatically switch the clockdomain @clkdm into
- * active or idle states, as needed by downstream clocks.  If the
+ * Instruct the CM to force a wakeup transition on the specified
+ * clockdomain @clkdm.  Returns -EINVAL if @clkdm is NULL or if the
+ * clockdomain does not support software-controlled wakeup; 0 upon
+ * success.
+ */
+int clkdm_wakeup(struct clockdomain *clkdm)
+{
+       int ret;
+
+       pwrdm_lock(clkdm->pwrdm.ptr);
+       ret = clkdm_wakeup_nolock(clkdm);
+       pwrdm_unlock(clkdm->pwrdm.ptr);
+
+       return ret;
+}
+
+/**
+ * clkdm_allow_idle_nolock - enable hwsup idle transitions for clkdm
+ * @clkdm: struct clockdomain *
+ *
+ * Allow the hardware to automatically switch the clockdomain @clkdm
+ * into active or idle states, as needed by downstream clocks.  If the
  * clockdomain has any downstream clocks enabled in the clock
  * framework, wkdep/sleepdep autodependencies are added; this is so
- * device drivers can read and write to the device.  No return value.
+ * device drivers can read and write to the device.  Only for use by
+ * the powerdomain code.  No return value.
  */
-void clkdm_allow_idle(struct clockdomain *clkdm)
+void clkdm_allow_idle_nolock(struct clockdomain *clkdm)
 {
-       unsigned long flags;
-
        if (!clkdm)
                return;
 
@@ -833,11 +867,26 @@ void clkdm_allow_idle(struct clockdomain *clkdm)
        pr_debug("clockdomain: enabling automatic idle transitions for
 %s\n",
                 clkdm->name);
 
-       spin_lock_irqsave(&clkdm->lock, flags);
        clkdm->_flags |= _CLKDM_FLAG_HWSUP_ENABLED;
        arch_clkdm->clkdm_allow_idle(clkdm);
-       pwrdm_state_switch(clkdm->pwrdm.ptr);
-       spin_unlock_irqrestore(&clkdm->lock, flags);
+       pwrdm_state_switch_nolock(clkdm->pwrdm.ptr);
+}
+
+/**
+ * clkdm_allow_idle - enable hwsup idle transitions for clkdm
+ * @clkdm: struct clockdomain *
+ *
+ * Allow the hardware to automatically switch the clockdomain @clkdm into
+ * active or idle states, as needed by downstream clocks.  If the
+ * clockdomain has any downstream clocks enabled in the clock
+ * framework, wkdep/sleepdep autodependencies are added; this is so
+ * device drivers can read and write to the device.  No return value.
+ */
+void clkdm_allow_idle(struct clockdomain *clkdm)
+{
+       pwrdm_lock(clkdm->pwrdm.ptr);
+       clkdm_allow_idle_nolock(clkdm);
+       pwrdm_unlock(clkdm->pwrdm.ptr);
 }
 

/**

arch/arm/mach-omap2/clockdomain.c +20 -7
@@ -847,12 +896,11 @@ void clkdm_allow_idle(struct clockdomain *clkdm)
  * Prevent the hardware from automatically switching the clockdomain
  * @clkdm into inactive or idle states.  If the clockdomain has
  * downstream clocks enabled in the clock framework, wkdep/sleepdep
- * autodependencies are removed.  No return value.
+ * autodependencies are removed.  Only for use by the powerdomain
+ * code.  No return value.
  */
-void clkdm_deny_idle(struct clockdomain *clkdm)
+void clkdm_deny_idle_nolock(struct clockdomain *clkdm)
 {
-       unsigned long flags;
-
        if (!clkdm)
                return;
 
@@ -868,11 +916,25 @@ void clkdm_deny_idle(struct clockdomain *clkdm)
        pr_debug("clockdomain: disabling automatic idle transitions for
 %s\n",
                 clkdm->name);
 
-       spin_lock_irqsave(&clkdm->lock, flags);
        clkdm->_flags &= ~_CLKDM_FLAG_HWSUP_ENABLED;
        arch_clkdm->clkdm_deny_idle(clkdm);
-       pwrdm_state_switch(clkdm->pwrdm.ptr);
-       spin_unlock_irqrestore(&clkdm->lock, flags);
+       pwrdm_state_switch_nolock(clkdm->pwrdm.ptr);
+}
+
+/**
+ * clkdm_deny_idle - disable hwsup idle transitions for clkdm
+ * @clkdm: struct clockdomain *
+ *
+ * Prevent the hardware from automatically switching the clockdomain
+ * @clkdm into inactive or idle states.  If the clockdomain has
+ * downstream clocks enabled in the clock framework, wkdep/sleepdep
+ * autodependencies are removed.  No return value.
+ */
+void clkdm_deny_idle(struct clockdomain *clkdm)
+{
+       pwrdm_lock(clkdm->pwrdm.ptr);
+       clkdm_deny_idle_nolock(clkdm);
+       pwrdm_unlock(clkdm->pwrdm.ptr);
 }
 

/**

arch/arm/mach-omap2/clockdomain.c +1 -6
@@ -889,14 +951,11 @@ void clkdm_deny_idle(struct clockdomain *clkdm)
 bool clkdm_in_hwsup(struct clockdomain *clkdm)
 {
        bool ret;
-       unsigned long flags;
 
        if (!clkdm)
                return false;
 
-       spin_lock_irqsave(&clkdm->lock, flags);
        ret = (clkdm->_flags & _CLKDM_FLAG_HWSUP_ENABLED) ? true : false;
-       spin_unlock_irqrestore(&clkdm->lock, flags);
 
        return ret;
 }
@@ -922,12 +981,10 @@ bool clkdm_missing_idle_reporting(struct clockdomain
 *clkdm)
 
 static int _clkdm_clk_hwmod_enable(struct clockdomain *clkdm)
 {
-       unsigned long flags;
-
        if (!clkdm || !arch_clkdm || !arch_clkdm->clkdm_clk_enable)
                return -EINVAL;
 
-       spin_lock_irqsave(&clkdm->lock, flags);
+       pwrdm_lock(clkdm->pwrdm.ptr);
 
        /*

* For arch's with no autodeps, clkcm_clk_enable

arch/arm/mach-omap2/clockdomain.c +8 -10
@@ -935,13 +992,13 @@ static int _clkdm_clk_hwmod_enable(struct
 clockdomain *clkdm)
         * enabled, so the clkdm can be force woken up.
         */
        if ((atomic_inc_return(&clkdm->usecount) > 1) && autodeps) {
-               spin_unlock_irqrestore(&clkdm->lock, flags);
+               pwrdm_unlock(clkdm->pwrdm.ptr);
                return 0;
        }
 
        arch_clkdm->clkdm_clk_enable(clkdm);
-       pwrdm_state_switch(clkdm->pwrdm.ptr);
-       spin_unlock_irqrestore(&clkdm->lock, flags);
+       pwrdm_state_switch_nolock(clkdm->pwrdm.ptr);
+       pwrdm_unlock(clkdm->pwrdm.ptr);
 
        pr_debug("clockdomain: %s: enabled\n", clkdm->name);
@@ -950,27 +1007,25 @@ static int _clkdm_clk_hwmod_enable(struct
 clockdomain *clkdm)
 
 static int _clkdm_clk_hwmod_disable(struct clockdomain *clkdm)
 {
-       unsigned long flags;
-
        if (!clkdm || !arch_clkdm || !arch_clkdm->clkdm_clk_disable)
                return -EINVAL;
 
-       spin_lock_irqsave(&clkdm->lock, flags);
+       pwrdm_lock(clkdm->pwrdm.ptr);
 
        if (atomic_read(&clkdm->usecount) == 0) {
-               spin_unlock_irqrestore(&clkdm->lock, flags);
+               pwrdm_unlock(clkdm->pwrdm.ptr);
                WARN_ON(1); /* underflow */
                return -ERANGE;
        }
 
        if (atomic_dec_return(&clkdm->usecount) > 0) {
-               spin_unlock_irqrestore(&clkdm->lock, flags);
+               pwrdm_unlock(clkdm->pwrdm.ptr);
                return 0;
        }
 
        arch_clkdm->clkdm_clk_disable(clkdm);
-       pwrdm_state_switch(clkdm->pwrdm.ptr);
-       spin_unlock_irqrestore(&clkdm->lock, flags);
+       pwrdm_state_switch_nolock(clkdm->pwrdm.ptr);
+       pwrdm_unlock(clkdm->pwrdm.ptr);
 
        pr_debug("clockdomain: %s: disabled\n", clkdm->name);
arch/arm/mach-omap2/clockdomain.h +4 -2
index bc42446..e7f1b4b 100644
@@ -15,7 +15,6 @@
 #define __ARCH_ARM_MACH_OMAP2_CLOCKDOMAIN_H
 
 #include <linux/init.h>
-#include <linux/spinlock.h>
 
 #include "powerdomain.h"
 #include "clock.h"
@@ -139,7 +138,6 @@ struct clockdomain {
        struct clkdm_dep *sleepdep_srcs;
        atomic_t usecount;
        struct list_head node;
-       spinlock_t lock;
 };
 
 /**
@@ -196,12 +194,16 @@ int clkdm_del_sleepdep(struct clockdomain *clkdm1,
 struct clockdomain *clkdm2);
 int clkdm_read_sleepdep(struct clockdomain *clkdm1, struct clockdomain
 *clkdm2);
 int clkdm_clear_all_sleepdeps(struct clockdomain *clkdm);
 
+void clkdm_allow_idle_nolock(struct clockdomain *clkdm);
 void clkdm_allow_idle(struct clockdomain *clkdm);
+void clkdm_deny_idle_nolock(struct clockdomain *clkdm);
 void clkdm_deny_idle(struct clockdomain *clkdm);
 bool clkdm_in_hwsup(struct clockdomain *clkdm);
 bool clkdm_missing_idle_reporting(struct clockdomain *clkdm);
 
+int clkdm_wakeup_nolock(struct clockdomain *clkdm);
 int clkdm_wakeup(struct clockdomain *clkdm);
+int clkdm_sleep_nolock(struct clockdomain *clkdm);
 int clkdm_sleep(struct clockdomain *clkdm);

int clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk);

arch/arm/mach-omap2/powerdomain-clockdomain.h new file +27 -0
new file mode 100644
index 0000000..e404eec
@@ -0,0 +1,27 @@
+/*
+ * OMAP powerdomain functions only for use by the OMAP clockdomain code
+ *
+ * Copyright (C) 2012 Texas Instruments, Inc.
+ * Paul Walmsley
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * The point of this file is to try to prevent other code outside of
+ * clockdomain.c from calling the functions listed herein.  Yes, this
+ * means you.
+ */
+
+#ifndef __ARCH_ARM_MACH_OMAP2_POWERDOMAIN_CLOCKDOMAIN_H
+#define __ARCH_ARM_MACH_OMAP2_POWERDOMAIN_CLOCKDOMAIN_H
+
+#include <linux/types.h>
+
+#include "powerdomain.h"
+
+extern void pwrdm_lock(struct powerdomain *pwrdm);
+extern void pwrdm_unlock(struct powerdomain *pwrdm);
+extern int pwrdm_state_switch_nolock(struct powerdomain *pwrdm);
+
+#endif
arch/arm/mach-omap2/powerdomain.c +40 -2
index 05f00660..2a5f15b 100644
@@ -19,6 +19,7 @@
 #include <linux/list.h>
 #include <linux/errno.h>
 #include <linux/string.h>
+#include <linux/spinlock.h>
 #include <trace/events/power.h>
 
 #include "cm2xxx_3xxx.h"
@@ -31,6 +32,7 @@
 
 #include "powerdomain.h"
 #include "clockdomain.h"
+#include "clockdomain-powerdomain.h"
 
 #include "soc.h"
 #include "pm.h"
@@ -101,6 +103,7 @@ static int _pwrdm_register(struct powerdomain *pwrdm)
        pwrdm->voltdm.ptr = voltdm;
        INIT_LIST_HEAD(&pwrdm->voltdm_node);
        voltdm_add_pwrdm(voltdm, pwrdm);
+       spin_lock_init(&pwrdm->_lock);
 
        list_add(&pwrdm->node, &pwrdm_list);
 
@@ -276,6 +279,30 @@ int pwrdm_complete_init(void)
 }
 
 /**
+ * pwrdm_lock - acquire a Linux spinlock on a powerdomain
+ * @pwrdm: struct powerdomain * to lock
+ *
+ * Acquire the powerdomain spinlock on @pwrdm.  No return value.
+ */
+void pwrdm_lock(struct powerdomain *pwrdm)
+       __acquires(&pwrdm->_lock)
+{
+       spin_lock_irqsave(&pwrdm->_lock, pwrdm->_lock_flags);
+}
+
+/**
+ * pwrdm_unlock - release a Linux spinlock on a powerdomain
+ * @pwrdm: struct powerdomain * to unlock
+ *
+ * Release the powerdomain spinlock on @pwrdm.  No return value.
+ */
+void pwrdm_unlock(struct powerdomain *pwrdm)
+       __releases(&pwrdm->_lock)
+{
+       spin_unlock_irqrestore(&pwrdm->_lock, pwrdm->_lock_flags);
+}
+
+/**
  * pwrdm_lookup - look up a powerdomain by name, return a pointer
  * @name: name of powerdomain
  *
@@ -921,7 +948,7 @@ bool pwrdm_has_hdwr_sar(struct powerdomain *pwrdm)
        return (pwrdm && pwrdm->flags & PWRDM_HAS_HDWR_SAR) ? 1 : 0;
 }
 
-int pwrdm_state_switch(struct powerdomain *pwrdm)
+int pwrdm_state_switch_nolock(struct powerdomain *pwrdm)
 {
        int ret;
 
@@ -935,6 +962,17 @@ int pwrdm_state_switch(struct powerdomain *pwrdm)
        return ret;
 }
 
+int __deprecated pwrdm_state_switch(struct powerdomain *pwrdm)
+{
+       int ret;
+
+       pwrdm_lock(pwrdm);
+       ret = pwrdm_state_switch_nolock(pwrdm);
+       pwrdm_unlock(pwrdm);
+
+       return ret;
+}
+
 int pwrdm_pre_transition(struct powerdomain *pwrdm)
 {
        if (pwrdm)
@@ -973,7 +1011,7 @@ static u8 _pwrdm_save_clkdm_state_and_activate(struct
 powerdomain *pwrdm,
                        sleep_switch = LOWPOWERSTATE_SWITCH;
                } else {
                        *hwsup = clkdm_in_hwsup(pwrdm->pwrdm_clkdms[0]);
-                       clkdm_wakeup(pwrdm->pwrdm_clkdms[0]);
+                       clkdm_wakeup_nolock(pwrdm->pwrdm_clkdms[0]);
                        sleep_switch = FORCEWAKEUP_SWITCH;
                }
        } else {
arch/arm/mach-omap2/powerdomain.c +3 -3
@@ -989,15 +1027,15 @@ static void _pwrdm_restore_clkdm_state(struct
 powerdomain *pwrdm,
        switch (sleep_switch) {
        case FORCEWAKEUP_SWITCH:
                if (hwsup)
-                       clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]);
+                       clkdm_allow_idle_nolock(pwrdm->pwrdm_clkdms[0]);
                else
-                       clkdm_sleep(pwrdm->pwrdm_clkdms[0]);
+                       clkdm_sleep_nolock(pwrdm->pwrdm_clkdms[0]);
                break;
        case LOWPOWERSTATE_SWITCH:
                if (pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE &&
                    arch_pwrdm->pwrdm_set_lowpwrstchange)
                        arch_pwrdm->pwrdm_set_lowpwrstchange(pwrdm);
-               pwrdm_state_switch(pwrdm);
+               pwrdm_state_switch_nolock(pwrdm);
                break;
        }

}

arch/arm/mach-omap2/powerdomain.c +5 -1
@@ -1021,9 +1059,13 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm,
 u8 pwrst)
                pwrst--;
        }
 
+       pwrdm_lock(pwrdm);
+
        next_pwrst = pwrdm_read_next_pwrst(pwrdm);
-       if (next_pwrst == pwrst)
+       if (next_pwrst == pwrst) {
+               pwrdm_unlock(pwrdm);
                return ret;
+       }
 
        sleep_switch = _pwrdm_save_clkdm_state_and_activate(pwrdm, pwrst,
                                                            &hwsup);
arch/arm/mach-omap2/powerdomain.c +2 -0
@@ -1035,6 +1077,8 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm,
 u8 pwrst)
 
        _pwrdm_restore_clkdm_state(pwrdm, sleep_switch, hwsup);
 
+       pwrdm_unlock(pwrdm);
+
        return ret;
 }
arch/arm/mach-omap2/powerdomain.h +6 -3
index 1edb3b7..83b4892 100644
@@ -19,8 +19,7 @@
 
 #include <linux/types.h>
 #include <linux/list.h>
-
-#include <linux/atomic.h>
+#include <linux/spinlock.h>
 
 #include "voltage.h"
 
@@ -103,6 +102,8 @@ struct powerdomain;
  * @state_counter:
  * @timer:
  * @state_timer:
+ * @_lock: spinlock used to serialize powerdomain and some clockdomain ops
+ * @_lock_flags: stored flags when @_lock is taken
  *
  * @prcm_partition possible values are defined in mach-omap2/prcm44xx.h.
  */
@@ -127,7 +128,8 @@ struct powerdomain {
        unsigned state_counter[PWRDM_MAX_PWRSTS];
        unsigned ret_logic_off_counter;
        unsigned ret_mem_off_counter[PWRDM_MAX_MEM_BANKS];
-
+       spinlock_t _lock;
+       unsigned long _lock_flags;
        const u8 pwrstctrl_offs;
        const u8 pwrstst_offs;
        const u32 logicretstate_mask;
@@ -225,6 +227,7 @@ int pwrdm_enable_hdwr_sar(struct powerdomain *pwrdm);
 int pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm);
 bool pwrdm_has_hdwr_sar(struct powerdomain *pwrdm);
 
+int pwrdm_state_switch_nolock(struct powerdomain *pwrdm);
 int pwrdm_state_switch(struct powerdomain *pwrdm);
 int pwrdm_pre_transition(struct powerdomain *pwrdm);
 int pwrdm_post_transition(struct powerdomain *pwrdm);

arch/arm/mach-omap2/powerdomain.h extern u32 omap2_pwrdm_get_mem_bank_stst_mask(u8 bank); · line 261

Quoted 7 lines
arch/arm/mach-omap2/powerdomain.h +2 -0
@@ -252,5 +255,7 @@ extern u32 omap2_pwrdm_get_mem_bank_stst_mask(u8 bank);
 extern struct powerdomain wkup_omap2_pwrdm;
 extern struct powerdomain gfx_omap2_pwrdm;
 
+extern void pwrdm_lock(struct powerdomain *pwrdm);
+extern void pwrdm_unlock(struct powerdomain *pwrdm);
 
 #endif

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20121212/174fb6f6/attachment-0001.html>

author maintainer
#19 lore raw

PATCH 6/10 ARM: OMAP2+: powerdomain/clockdomain: add a per-powerdomain spinlock

Hi

Quoted 9 lines · Jean Pihet
Quoted 5 lines · Paul Walmsley

Add a per-powerdomain spinlock. Use that instead of the clockdomain spinlock. Add pwrdm_lock()/pwrdm_unlock() functions to allow other code to acquire or release the powerdomain spinlock without reaching directly into the struct powerdomain.

Since clockdomains are part of powerdomains it seems weird for the clockdomain code to take a powerdoamin lock.

Why?

Quoted 2 lines

Is there a reason why the powerdomain could not take the lock before calling the clockdomain functions?

Do you mean "is there a reason why the powerdomain _code_ could not take the lock"? If so, the reason is that code other than the powerdomain code calls the clkdm_* functions directly, without calling any powerdomain functions first. So there's really no other place to take the lock unless the callers are updated to take the powerdomain lock themselves. That seems like something to avoid if the caller doesn't have any other relationship to the powerdomain code.

Quoted 1 line

Also, are the lock and nolock version the clockdomain function needed?

Did you have a different solution in mind? The two versions are used for code that needs to be called from two contexts: the first with the powerdomain's lock already held; the second needing to acquire the powerdomain's lock to avoid racing against other PRCM code.

- Paul

#20 lore raw

PATCH 6/10 ARM: OMAP2+: powerdomain/clockdomain: add a per-powerdomain spinlock

In reply to Paul Walmsley

Paul,

-resending in plain text only, sorry about that-

Quoted 5 lines · Paul Walmsley

Add a per-powerdomain spinlock. Use that instead of the clockdomain spinlock. Add pwrdm_lock()/pwrdm_unlock() functions to allow other code to acquire or release the powerdomain spinlock without reaching directly into the struct powerdomain.

Since clockdomains are part of powerdomains it seems weird for the clockdomain code to take a powerdoamin lock.
Is there a reason why the powerdomain could not take the lock before calling the clockdomain functions?

Also, are the lock and nolock version the clockdomain function needed?

Regards,
Jean

author maintainer
#21 lore raw

PATCH 7/10 ARM: OMAP2xxx: CM: remove autodep handling

In reply to Paul Walmsley

There's no need to preserve the autodep handling code in mach-omap2/cm2xxx.c, since no autodeps are defined for these chips. Hopefully they'll never be needed, but if in some future case they are, this code can be added back in.

---
 arch/arm/mach-omap2/cm2xxx.c |   33 ++++-----------------------------
 1 file changed, 4 insertions(+), 29 deletions(-)
arch/arm/mach-omap2/cm2xxx.c +4 -29
index db65069..6774a53 100644
@@ -273,9 +273,6 @@ int omap2xxx_cm_wait_module_ready(s16 prcm_mod, u8 idlest_id, u8 idlest_shift)
 
 static void omap2xxx_clkdm_allow_idle(struct clockdomain *clkdm)
 {
-	if (atomic_read(&clkdm->usecount) > 0)
-		_clkdm_add_autodeps(clkdm);
-
 	omap2xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
 				       clkdm->clktrctrl_mask);
 }
@@ -284,9 +281,6 @@ static void omap2xxx_clkdm_deny_idle(struct clockdomain *clkdm)
 {
 	omap2xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
 					clkdm->clktrctrl_mask);
-
-	if (atomic_read(&clkdm->usecount) > 0)
-		_clkdm_del_autodeps(clkdm);
 }
 
 static int omap2xxx_clkdm_clk_enable(struct clockdomain *clkdm)
@@ -298,18 +292,8 @@ static int omap2xxx_clkdm_clk_enable(struct clockdomain *clkdm)
 
 	hwsup = omap2xxx_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
 					      clkdm->clktrctrl_mask);
-
-	if (hwsup) {
-		/* Disable HW transitions when we are changing deps */
-		omap2xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
-						clkdm->clktrctrl_mask);
-		_clkdm_add_autodeps(clkdm);
-		omap2xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
-					       clkdm->clktrctrl_mask);
-	} else {
-		if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)
-			omap2xxx_clkdm_wakeup(clkdm);
-	}
+	if (!hwsup && clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)
+		omap2xxx_clkdm_wakeup(clkdm);
 
 	return 0;
 }
@@ -324,17 +308,8 @@ static int omap2xxx_clkdm_clk_disable(struct clockdomain *clkdm)
 	hwsup = omap2xxx_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
 					      clkdm->clktrctrl_mask);
 
-	if (hwsup) {
-		/* Disable HW transitions when we are changing deps */
-		omap2xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
-						clkdm->clktrctrl_mask);
-		_clkdm_del_autodeps(clkdm);
-		omap2xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
-					       clkdm->clktrctrl_mask);
-	} else {
-		if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP)
-			omap2xxx_clkdm_sleep(clkdm);
-	}
+	if (!hwsup && clkdm->flags & CLKDM_CAN_FORCE_SLEEP)
+		omap2xxx_clkdm_sleep(clkdm);
 
 	return 0;
 }
author maintainer
#22 lore raw

PATCH 8/10 ARM: OMAP2+: clockdomain: work on wkdep/sleepdep functions

In reply to Paul Walmsley

Split the clkdm_(add|del)_(wk|sleep)dep() functions into lockless and locking versions -- this will be needed in a subsequent patch. Also, while here, remove the leading underscore, since these are not currently static functions. And for functions that have kerneldoc-style comment blocks, but which are missing the initial '/**' tag, fix the tag to indicate that they are kerneldoc.

---
 arch/arm/mach-omap2/clockdomain.c |  394 ++++++++++++++++++++++---------------
 arch/arm/mach-omap2/clockdomain.h |    5 
 arch/arm/mach-omap2/cm3xxx.c      |    8 -
 3 files changed, 240 insertions(+), 167 deletions(-)
arch/arm/mach-omap2/clockdomain.c +233 -161
index 2142dab..9d5b69f 100644
@@ -120,7 +120,7 @@ static struct clkdm_dep *_clkdm_deps_lookup(struct clockdomain *clkdm,
 	return cd;
 }
 
-/*
+/**
  * _autodep_lookup - resolve autodep clkdm names to clkdm pointers; store
  * @autodep: struct clkdm_autodep * to resolve
  *
@@ -152,88 +152,202 @@ static void _autodep_lookup(struct clkdm_autodep *autodep)
 	autodep->clkdm.ptr = clkdm;
 }
 
-/*
- * _clkdm_add_autodeps - add auto sleepdeps/wkdeps to clkdm upon clock enable
- * @clkdm: struct clockdomain *
+/**
+ * _resolve_clkdm_deps() - resolve clkdm_names in @clkdm_deps to clkdms
+ * @clkdm: clockdomain that we are resolving dependencies for
+ * @clkdm_deps: ptr to array of struct clkdm_deps to resolve
  *
- * Add the "autodep" sleep & wakeup dependencies to clockdomain 'clkdm'
- * in hardware-supervised mode.  Meant to be called from clock framework
- * when a clock inside clockdomain 'clkdm' is enabled.	No return value.
+ * Iterates through @clkdm_deps, looking up the struct clockdomain named by
+ * clkdm_name and storing the clockdomain pointer in the struct clkdm_dep.
+ * No return value.
+ */
+static void _resolve_clkdm_deps(struct clockdomain *clkdm,
+				struct clkdm_dep *clkdm_deps)
+{
+	struct clkdm_dep *cd;
+
+	for (cd = clkdm_deps; cd && cd->clkdm_name; cd++) {
+		if (cd->clkdm)
+			continue;
+		cd->clkdm = _clkdm_lookup(cd->clkdm_name);
+
+		WARN(!cd->clkdm, "clockdomain: %s: could not find clkdm %s while resolving dependencies - should never happen",
+		     clkdm->name, cd->clkdm_name);
+	}
+}
+
+/**
+ * _clkdm_add_wkdep - add a wakeup dependency from clkdm2 to clkdm1 (lockless)
+ * @clkdm1: wake this struct clockdomain * up (dependent)
+ * @clkdm2: when this struct clockdomain * wakes up (source)
  *
- * XXX autodeps are deprecated and should be removed at the earliest
- * opportunity
+ * When the clockdomain represented by @clkdm2 wakes up, wake up
+ * @clkdm1. Implemented in hardware on the OMAP, this feature is
+ * designed to reduce wakeup latency of the dependent clockdomain @clkdm1.
+ * Returns -EINVAL if presented with invalid clockdomain pointers,
+ * -ENOENT if @clkdm2 cannot wake up clkdm1 in hardware, or 0 upon
+ * success.
  */
-void _clkdm_add_autodeps(struct clockdomain *clkdm)
+static int _clkdm_add_wkdep(struct clockdomain *clkdm1,
+			    struct clockdomain *clkdm2)
 {
-	struct clkdm_autodep *autodep;
+	struct clkdm_dep *cd;
+	int ret = 0;
 
-	if (!autodeps || clkdm->flags & CLKDM_NO_AUTODEPS)
-		return;
+	if (!clkdm1 || !clkdm2)
+		return -EINVAL;
 
-	for (autodep = autodeps; autodep->clkdm.ptr; autodep++) {
-		if (IS_ERR(autodep->clkdm.ptr))
-			continue;
+	cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs);
+	if (IS_ERR(cd))
+		ret = PTR_ERR(cd);
 
-		pr_debug("clockdomain: %s: adding %s sleepdep/wkdep\n",
-			 clkdm->name, autodep->clkdm.ptr->name);
+	if (!arch_clkdm || !arch_clkdm->clkdm_add_wkdep)
+		ret = -EINVAL;
 
-		clkdm_add_sleepdep(clkdm, autodep->clkdm.ptr);
-		clkdm_add_wkdep(clkdm, autodep->clkdm.ptr);
+	if (ret) {
+		pr_debug("clockdomain: hardware cannot set/clear wake up of %s when %s wakes up\n",
+			 clkdm1->name, clkdm2->name);
+		return ret;
+	}
+
+	if (atomic_inc_return(&cd->wkdep_usecount) == 1) {
+		pr_debug("clockdomain: hardware will wake up %s when %s wakes up\n",
+			 clkdm1->name, clkdm2->name);
+
+		ret = arch_clkdm->clkdm_add_wkdep(clkdm1, clkdm2);
 	}
+
+	return ret;
 }
 
-/*
- * _clkdm_add_autodeps - remove auto sleepdeps/wkdeps from clkdm
- * @clkdm: struct clockdomain *
+/**
+ * _clkdm_del_wkdep - remove a wakeup dep from clkdm2 to clkdm1 (lockless)
+ * @clkdm1: wake this struct clockdomain * up (dependent)
+ * @clkdm2: when this struct clockdomain * wakes up (source)
  *
- * Remove the "autodep" sleep & wakeup dependencies from clockdomain 'clkdm'
- * in hardware-supervised mode.  Meant to be called from clock framework
- * when a clock inside clockdomain 'clkdm' is disabled.  No return value.
+ * Remove a wakeup dependency causing @clkdm1 to wake up when @clkdm2
+ * wakes up.  Returns -EINVAL if presented with invalid clockdomain
+ * pointers, -ENOENT if @clkdm2 cannot wake up clkdm1 in hardware, or
+ * 0 upon success.
+ */
+static int _clkdm_del_wkdep(struct clockdomain *clkdm1,
+			    struct clockdomain *clkdm2)
+{
+	struct clkdm_dep *cd;
+	int ret = 0;
+
+	if (!clkdm1 || !clkdm2)
+		return -EINVAL;
+
+	cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs);
+	if (IS_ERR(cd))
+		ret = PTR_ERR(cd);
+
+	if (!arch_clkdm || !arch_clkdm->clkdm_del_wkdep)
+		ret = -EINVAL;
+
+	if (ret) {
+		pr_debug("clockdomain: hardware cannot set/clear wake up of %s when %s wakes up\n",
+			 clkdm1->name, clkdm2->name);
+		return ret;
+	}
+
+	if (atomic_dec_return(&cd->wkdep_usecount) == 0) {
+		pr_debug("clockdomain: hardware will no longer wake up %s after %s wakes up\n",
+			 clkdm1->name, clkdm2->name);
+
+		ret = arch_clkdm->clkdm_del_wkdep(clkdm1, clkdm2);
+	}
+
+	return ret;
+}
+
+/**
+ * _clkdm_add_sleepdep - add a sleep dependency from clkdm2 to clkdm1 (lockless)
+ * @clkdm1: prevent this struct clockdomain * from sleeping (dependent)
+ * @clkdm2: when this struct clockdomain * is active (source)
  *
- * XXX autodeps are deprecated and should be removed at the earliest
- * opportunity
+ * Prevent @clkdm1 from automatically going inactive (and then to
+ * retention or off) if @clkdm2 is active.  Returns -EINVAL if
+ * presented with invalid clockdomain pointers or called on a machine
+ * that does not support software-configurable hardware sleep
+ * dependencies, -ENOENT if the specified dependency cannot be set in
+ * hardware, or 0 upon success.
  */
-void _clkdm_del_autodeps(struct clockdomain *clkdm)
+static int _clkdm_add_sleepdep(struct clockdomain *clkdm1,
+			       struct clockdomain *clkdm2)
 {
-	struct clkdm_autodep *autodep;
+	struct clkdm_dep *cd;
+	int ret = 0;
 
-	if (!autodeps || clkdm->flags & CLKDM_NO_AUTODEPS)
-		return;
+	if (!clkdm1 || !clkdm2)
+		return -EINVAL;
 
-	for (autodep = autodeps; autodep->clkdm.ptr; autodep++) {
-		if (IS_ERR(autodep->clkdm.ptr))
-			continue;
+	cd = _clkdm_deps_lookup(clkdm2, clkdm1->sleepdep_srcs);
+	if (IS_ERR(cd))
+		ret = PTR_ERR(cd);
 
-		pr_debug("clockdomain: %s: removing %s sleepdep/wkdep\n",
-			 clkdm->name, autodep->clkdm.ptr->name);
+	if (!arch_clkdm || !arch_clkdm->clkdm_add_sleepdep)
+		ret = -EINVAL;
 
-		clkdm_del_sleepdep(clkdm, autodep->clkdm.ptr);
-		clkdm_del_wkdep(clkdm, autodep->clkdm.ptr);
+	if (ret) {
+		pr_debug("clockdomain: hardware cannot set/clear sleep dependency affecting %s from %s\n",
+			 clkdm1->name, clkdm2->name);
+		return ret;
 	}
+
+	if (atomic_inc_return(&cd->sleepdep_usecount) == 1) {
+		pr_debug("clockdomain: will prevent %s from sleeping if %s is active\n",
+			 clkdm1->name, clkdm2->name);
+
+		ret = arch_clkdm->clkdm_add_sleepdep(clkdm1, clkdm2);
+	}
+
+	return ret;
 }
 
 /**
- * _resolve_clkdm_deps() - resolve clkdm_names in @clkdm_deps to clkdms
- * @clkdm: clockdomain that we are resolving dependencies for
- * @clkdm_deps: ptr to array of struct clkdm_deps to resolve
+ * _clkdm_del_sleepdep - remove a sleep dep from clkdm2 to clkdm1 (lockless)
+ * @clkdm1: prevent this struct clockdomain * from sleeping (dependent)
+ * @clkdm2: when this struct clockdomain * is active (source)
  *
- * Iterates through @clkdm_deps, looking up the struct clockdomain named by
- * clkdm_name and storing the clockdomain pointer in the struct clkdm_dep.
- * No return value.
+ * Allow @clkdm1 to automatically go inactive (and then to retention or
+ * off), independent of the activity state of @clkdm2.  Returns -EINVAL
+ * if presented with invalid clockdomain pointers or called on a machine
+ * that does not support software-configurable hardware sleep dependencies,
+ * -ENOENT if the specified dependency cannot be cleared in hardware, or
+ * 0 upon success.
  */
-static void _resolve_clkdm_deps(struct clockdomain *clkdm,
-				struct clkdm_dep *clkdm_deps)
+static int _clkdm_del_sleepdep(struct clockdomain *clkdm1,
+			       struct clockdomain *clkdm2)
 {
 	struct clkdm_dep *cd;
+	int ret = 0;
 
-	for (cd = clkdm_deps; cd && cd->clkdm_name; cd++) {
-		if (cd->clkdm)
-			continue;
-		cd->clkdm = _clkdm_lookup(cd->clkdm_name);
+	if (!clkdm1 || !clkdm2)
+		return -EINVAL;
 
-		WARN(!cd->clkdm, "clockdomain: %s: could not find clkdm %s while resolving dependencies - should never happen",
-		     clkdm->name, cd->clkdm_name);
+	cd = _clkdm_deps_lookup(clkdm2, clkdm1->sleepdep_srcs);
+	if (IS_ERR(cd))
+		ret = PTR_ERR(cd);
+
+	if (!arch_clkdm || !arch_clkdm->clkdm_del_sleepdep)
+		ret = -EINVAL;
+
+	if (ret) {
+		pr_debug("clockdomain: hardware cannot set/clear sleep dependency affecting %s from %s\n",
+			 clkdm1->name, clkdm2->name);
+		return ret;
 	}
+
+	if (atomic_dec_return(&cd->sleepdep_usecount) == 0) {
+		pr_debug("clockdomain: will no longer prevent %s from sleeping if %s is active\n",
+			 clkdm1->name, clkdm2->name);
+
+		ret = arch_clkdm->clkdm_del_sleepdep(clkdm1, clkdm2);
+	}
+
+	return ret;
 }
 
 /* Public functions */
@@ -453,33 +567,7 @@ struct powerdomain *clkdm_get_pwrdm(struct clockdomain *clkdm)
  */
 int clkdm_add_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
 {
-	struct clkdm_dep *cd;
-	int ret = 0;
-
-	if (!clkdm1 || !clkdm2)
-		return -EINVAL;
-
-	cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs);
-	if (IS_ERR(cd))
-		ret = PTR_ERR(cd);
-
-	if (!arch_clkdm || !arch_clkdm->clkdm_add_wkdep)
-		ret = -EINVAL;
-
-	if (ret) {
-		pr_debug("clockdomain: hardware cannot set/clear wake up of %s when %s wakes up\n",
-			 clkdm1->name, clkdm2->name);
-		return ret;
-	}
-
-	if (atomic_inc_return(&cd->wkdep_usecount) == 1) {
-		pr_debug("clockdomain: hardware will wake up %s when %s wakes up\n",
-			 clkdm1->name, clkdm2->name);
-
-		ret = arch_clkdm->clkdm_add_wkdep(clkdm1, clkdm2);
-	}
-
-	return ret;
+	return _clkdm_add_wkdep(clkdm1, clkdm2);
 }
 
 /**
@@ -494,33 +582,7 @@ int clkdm_add_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
  */
 int clkdm_del_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
 {
-	struct clkdm_dep *cd;
-	int ret = 0;
-
-	if (!clkdm1 || !clkdm2)
-		return -EINVAL;
-
-	cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs);
-	if (IS_ERR(cd))
-		ret = PTR_ERR(cd);
-
-	if (!arch_clkdm || !arch_clkdm->clkdm_del_wkdep)
-		ret = -EINVAL;
-
-	if (ret) {
-		pr_debug("clockdomain: hardware cannot set/clear wake up of %s when %s wakes up\n",
-			 clkdm1->name, clkdm2->name);
-		return ret;
-	}
-
-	if (atomic_dec_return(&cd->wkdep_usecount) == 0) {
-		pr_debug("clockdomain: hardware will no longer wake up %s after %s wakes up\n",
-			 clkdm1->name, clkdm2->name);
-
-		ret = arch_clkdm->clkdm_del_wkdep(clkdm1, clkdm2);
-	}
-
-	return ret;
+	return _clkdm_del_wkdep(clkdm1, clkdm2);
 }
 
 /**
@@ -597,33 +659,7 @@ int clkdm_clear_all_wkdeps(struct clockdomain *clkdm)
  */
 int clkdm_add_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
 {
-	struct clkdm_dep *cd;
-	int ret = 0;
-
-	if (!clkdm1 || !clkdm2)
-		return -EINVAL;
-
-	cd = _clkdm_deps_lookup(clkdm2, clkdm1->sleepdep_srcs);
-	if (IS_ERR(cd))
-		ret = PTR_ERR(cd);
-
-	if (!arch_clkdm || !arch_clkdm->clkdm_add_sleepdep)
-		ret = -EINVAL;
-
-	if (ret) {
-		pr_debug("clockdomain: hardware cannot set/clear sleep dependency affecting %s from %s\n",
-			 clkdm1->name, clkdm2->name);
-		return ret;
-	}
-
-	if (atomic_inc_return(&cd->sleepdep_usecount) == 1) {
-		pr_debug("clockdomain: will prevent %s from sleeping if %s is active\n",
-			 clkdm1->name, clkdm2->name);
-
-		ret = arch_clkdm->clkdm_add_sleepdep(clkdm1, clkdm2);
-	}
-
-	return ret;
+	return _clkdm_add_sleepdep(clkdm1, clkdm2);
 }
 
 /**
@@ -640,33 +676,7 @@ int clkdm_add_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
  */
 int clkdm_del_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
 {
-	struct clkdm_dep *cd;
-	int ret = 0;
-
-	if (!clkdm1 || !clkdm2)
-		return -EINVAL;
-
-	cd = _clkdm_deps_lookup(clkdm2, clkdm1->sleepdep_srcs);
-	if (IS_ERR(cd))
-		ret = PTR_ERR(cd);
-
-	if (!arch_clkdm || !arch_clkdm->clkdm_del_sleepdep)
-		ret = -EINVAL;
-
-	if (ret) {
-		pr_debug("clockdomain: hardware cannot set/clear sleep dependency affecting %s from %s\n",
-			 clkdm1->name, clkdm2->name);
-		return ret;
-	}
-
-	if (atomic_dec_return(&cd->sleepdep_usecount) == 0) {
-		pr_debug("clockdomain: will no longer prevent %s from sleeping if %s is active\n",
-			 clkdm1->name, clkdm2->name);
-
-		ret = arch_clkdm->clkdm_del_sleepdep(clkdm1, clkdm2);
-	}
-
-	return ret;
+	return _clkdm_del_sleepdep(clkdm1, clkdm2);
 }
 
 /**
@@ -977,6 +987,68 @@ bool clkdm_missing_idle_reporting(struct clockdomain *clkdm)
 	return (clkdm->flags & CLKDM_MISSING_IDLE_REPORTING) ? true : false;
 }
 
+/* Public autodep handling functions (deprecated) */
+
+/**
+ * clkdm_add_autodeps - add auto sleepdeps/wkdeps to clkdm upon clock enable
+ * @clkdm: struct clockdomain *
+ *
+ * Add the "autodep" sleep & wakeup dependencies to clockdomain 'clkdm'
+ * in hardware-supervised mode.  Meant to be called from clock framework
+ * when a clock inside clockdomain 'clkdm' is enabled.	No return value.
+ *
+ * XXX autodeps are deprecated and should be removed at the earliest
+ * opportunity
+ */
+void clkdm_add_autodeps(struct clockdomain *clkdm)
+{
+	struct clkdm_autodep *autodep;
+
+	if (!autodeps || clkdm->flags & CLKDM_NO_AUTODEPS)
+		return;
+
+	for (autodep = autodeps; autodep->clkdm.ptr; autodep++) {
+		if (IS_ERR(autodep->clkdm.ptr))
+			continue;
+
+		pr_debug("clockdomain: %s: adding %s sleepdep/wkdep\n",
+			 clkdm->name, autodep->clkdm.ptr->name);
+
+		_clkdm_add_sleepdep(clkdm, autodep->clkdm.ptr);
+		_clkdm_add_wkdep(clkdm, autodep->clkdm.ptr);
+	}
+}
+
+/**
+ * clkdm_del_autodeps - remove auto sleepdeps/wkdeps from clkdm
+ * @clkdm: struct clockdomain *
+ *
+ * Remove the "autodep" sleep & wakeup dependencies from clockdomain 'clkdm'
+ * in hardware-supervised mode.  Meant to be called from clock framework
+ * when a clock inside clockdomain 'clkdm' is disabled.  No return value.
+ *
+ * XXX autodeps are deprecated and should be removed at the earliest
+ * opportunity
+ */
+void clkdm_del_autodeps(struct clockdomain *clkdm)
+{
+	struct clkdm_autodep *autodep;
+
+	if (!autodeps || clkdm->flags & CLKDM_NO_AUTODEPS)
+		return;
+
+	for (autodep = autodeps; autodep->clkdm.ptr; autodep++) {
+		if (IS_ERR(autodep->clkdm.ptr))
+			continue;
+
+		pr_debug("clockdomain: %s: removing %s sleepdep/wkdep\n",
+			 clkdm->name, autodep->clkdm.ptr->name);
+
+		_clkdm_del_sleepdep(clkdm, autodep->clkdm.ptr);
+		_clkdm_del_wkdep(clkdm, autodep->clkdm.ptr);
+	}
+}
+
 /* Clockdomain-to-clock/hwmod framework interface code */
 
 static int _clkdm_clk_hwmod_enable(struct clockdomain *clkdm)
arch/arm/mach-omap2/clockdomain.h +3 -2
index e7f1b4b..50c3cd8 100644
@@ -216,8 +216,9 @@ extern void __init omap243x_clockdomains_init(void);
 extern void __init omap3xxx_clockdomains_init(void);
 extern void __init am33xx_clockdomains_init(void);
 extern void __init omap44xx_clockdomains_init(void);
-extern void _clkdm_add_autodeps(struct clockdomain *clkdm);
-extern void _clkdm_del_autodeps(struct clockdomain *clkdm);
+
+extern void clkdm_add_autodeps(struct clockdomain *clkdm);
+extern void clkdm_del_autodeps(struct clockdomain *clkdm);
 
 extern struct clkdm_ops omap2_clkdm_operations;
 extern struct clkdm_ops omap3_clkdm_operations;
arch/arm/mach-omap2/cm3xxx.c +4 -4
index c2086f2..b94af4c 100644
@@ -210,7 +210,7 @@ static int omap3xxx_clkdm_wakeup(struct clockdomain *clkdm)
 static void omap3xxx_clkdm_allow_idle(struct clockdomain *clkdm)
 {
 	if (atomic_read(&clkdm->usecount) > 0)
-		_clkdm_add_autodeps(clkdm);
+		clkdm_add_autodeps(clkdm);
 
 	omap3xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
 				       clkdm->clktrctrl_mask);
@@ -222,7 +222,7 @@ static void omap3xxx_clkdm_deny_idle(struct clockdomain *clkdm)
 					clkdm->clktrctrl_mask);
 
 	if (atomic_read(&clkdm->usecount) > 0)
-		_clkdm_del_autodeps(clkdm);
+		clkdm_del_autodeps(clkdm);
 }
 
 static int omap3xxx_clkdm_clk_enable(struct clockdomain *clkdm)
@@ -250,7 +250,7 @@ static int omap3xxx_clkdm_clk_enable(struct clockdomain *clkdm)
 		/* Disable HW transitions when we are changing deps */
 		omap3xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
 						clkdm->clktrctrl_mask);
-		_clkdm_add_autodeps(clkdm);
+		clkdm_add_autodeps(clkdm);
 		omap3xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
 					       clkdm->clktrctrl_mask);
 	} else {
@@ -287,7 +287,7 @@ static int omap3xxx_clkdm_clk_disable(struct clockdomain *clkdm)
 		/* Disable HW transitions when we are changing deps */
 		omap3xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
 						clkdm->clktrctrl_mask);
-		_clkdm_del_autodeps(clkdm);
+		clkdm_del_autodeps(clkdm);
 		omap3xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
 					       clkdm->clktrctrl_mask);
 	} else {
author maintainer
#23 lore raw

PATCH 9/10 ARM: OMAP2+: clockdomain: convert existing atomic usecounts into spinlock-protected shorts/ints

In reply to Paul Walmsley

The atomic usecounts seem to be confusing, and are no longer needed since the operations that they are attached to really should take place under lock. Replace the atomic counters with simple integers, protected by the enclosing powerdomain spinlock.

---
 arch/arm/mach-omap2/clockdomain.c  |   88 +++++++++++++++++++++++++++++++-----
 arch/arm/mach-omap2/clockdomain.h  |    6 +-
 arch/arm/mach-omap2/cm3xxx.c       |    6 +-
 arch/arm/mach-omap2/cminst44xx.c   |    2 -
 arch/arm/mach-omap2/pm-debug.c     |    6 +-
 arch/arm/mach-omap2/pm.c           |    3 +
 arch/arm/mach-omap2/prm2xxx_3xxx.c |    3 +
 7 files changed, 88 insertions(+), 26 deletions(-)
arch/arm/mach-omap2/clockdomain.c +75 -13
index 9d5b69f..ed8ac2f 100644
@@ -210,7 +210,8 @@ static int _clkdm_add_wkdep(struct clockdomain *clkdm1,
 		return ret;
 	}
 
-	if (atomic_inc_return(&cd->wkdep_usecount) == 1) {
+	cd->wkdep_usecount++;
+	if (cd->wkdep_usecount == 1) {
 		pr_debug("clockdomain: hardware will wake up %s when %s wakes up\n",
 			 clkdm1->name, clkdm2->name);
 
@@ -252,7 +253,8 @@ static int _clkdm_del_wkdep(struct clockdomain *clkdm1,
 		return ret;
 	}
 
-	if (atomic_dec_return(&cd->wkdep_usecount) == 0) {
+	cd->wkdep_usecount--;
+	if (cd->wkdep_usecount == 0) {
 		pr_debug("clockdomain: hardware will no longer wake up %s after %s wakes up\n",
 			 clkdm1->name, clkdm2->name);
 
@@ -296,7 +298,8 @@ static int _clkdm_add_sleepdep(struct clockdomain *clkdm1,
 		return ret;
 	}
 
-	if (atomic_inc_return(&cd->sleepdep_usecount) == 1) {
+	cd->sleepdep_usecount++;
+	if (cd->sleepdep_usecount == 1) {
 		pr_debug("clockdomain: will prevent %s from sleeping if %s is active\n",
 			 clkdm1->name, clkdm2->name);
 
@@ -340,7 +343,8 @@ static int _clkdm_del_sleepdep(struct clockdomain *clkdm1,
 		return ret;
 	}
 
-	if (atomic_dec_return(&cd->sleepdep_usecount) == 0) {
+	cd->sleepdep_usecount--;
+	if (cd->sleepdep_usecount == 0) {
 		pr_debug("clockdomain: will no longer prevent %s from sleeping if %s is active\n",
 			 clkdm1->name, clkdm2->name);
 
@@ -567,7 +571,21 @@ struct powerdomain *clkdm_get_pwrdm(struct clockdomain *clkdm)
  */
 int clkdm_add_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
 {
-	return _clkdm_add_wkdep(clkdm1, clkdm2);
+	struct clkdm_dep *cd;
+	int ret;
+
+	if (!clkdm1 || !clkdm2)
+		return -EINVAL;
+
+	cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs);
+	if (IS_ERR(cd))
+		return PTR_ERR(cd);
+
+	pwrdm_lock(cd->clkdm->pwrdm.ptr);
+	ret = _clkdm_add_wkdep(clkdm1, clkdm2);
+	pwrdm_unlock(cd->clkdm->pwrdm.ptr);
+
+	return ret;
 }
 
 /**
@@ -582,7 +600,21 @@ int clkdm_add_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
  */
 int clkdm_del_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
 {
-	return _clkdm_del_wkdep(clkdm1, clkdm2);
+	struct clkdm_dep *cd;
+	int ret;
+
+	if (!clkdm1 || !clkdm2)
+		return -EINVAL;
+
+	cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs);
+	if (IS_ERR(cd))
+		return PTR_ERR(cd);
+
+	pwrdm_lock(cd->clkdm->pwrdm.ptr);
+	ret = _clkdm_del_wkdep(clkdm1, clkdm2);
+	pwrdm_unlock(cd->clkdm->pwrdm.ptr);
+
+	return ret;
 }
 
 /**
@@ -620,7 +652,7 @@ int clkdm_read_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
 		return ret;
 	}
 
-	/* XXX It's faster to return the atomic wkdep_usecount */
+	/* XXX It's faster to return the wkdep_usecount */
 	return arch_clkdm->clkdm_read_wkdep(clkdm1, clkdm2);
 }
 
@@ -659,7 +691,21 @@ int clkdm_clear_all_wkdeps(struct clockdomain *clkdm)
  */
 int clkdm_add_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
 {
-	return _clkdm_add_sleepdep(clkdm1, clkdm2);
+	struct clkdm_dep *cd;
+	int ret;
+
+	if (!clkdm1 || !clkdm2)
+		return -EINVAL;
+
+	cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs);
+	if (IS_ERR(cd))
+		return PTR_ERR(cd);
+
+	pwrdm_lock(cd->clkdm->pwrdm.ptr);
+	ret = _clkdm_add_sleepdep(clkdm1, clkdm2);
+	pwrdm_unlock(cd->clkdm->pwrdm.ptr);
+
+	return ret;
 }
 
 /**
@@ -676,7 +722,21 @@ int clkdm_add_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
  */
 int clkdm_del_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
 {
-	return _clkdm_del_sleepdep(clkdm1, clkdm2);
+	struct clkdm_dep *cd;
+	int ret;
+
+	if (!clkdm1 || !clkdm2)
+		return -EINVAL;
+
+	cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs);
+	if (IS_ERR(cd))
+		return PTR_ERR(cd);
+
+	pwrdm_lock(cd->clkdm->pwrdm.ptr);
+	ret = _clkdm_del_sleepdep(clkdm1, clkdm2);
+	pwrdm_unlock(cd->clkdm->pwrdm.ptr);
+
+	return ret;
 }
 
 /**
@@ -716,7 +776,7 @@ int clkdm_read_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
 		return ret;
 	}
 
-	/* XXX It's faster to return the atomic sleepdep_usecount */
+	/* XXX It's faster to return the sleepdep_usecount */
 	return arch_clkdm->clkdm_read_sleepdep(clkdm1, clkdm2);
 }
 
@@ -1063,7 +1123,8 @@ static int _clkdm_clk_hwmod_enable(struct clockdomain *clkdm)
 	 * should be called for every clock instance or hwmod that is
 	 * enabled, so the clkdm can be force woken up.
 	 */
-	if ((atomic_inc_return(&clkdm->usecount) > 1) && autodeps) {
+	clkdm->usecount++;
+	if (clkdm->usecount > 1 && autodeps) {
 		pwrdm_unlock(clkdm->pwrdm.ptr);
 		return 0;
 	}
@@ -1084,13 +1145,14 @@ static int _clkdm_clk_hwmod_disable(struct clockdomain *clkdm)
 
 	pwrdm_lock(clkdm->pwrdm.ptr);
 
-	if (atomic_read(&clkdm->usecount) == 0) {
+	if (clkdm->usecount == 0) {
 		pwrdm_unlock(clkdm->pwrdm.ptr);
 		WARN_ON(1); /* underflow */
 		return -ERANGE;
 	}
 
-	if (atomic_dec_return(&clkdm->usecount) > 0) {
+	clkdm->usecount--;
+	if (clkdm->usecount > 0) {
 		pwrdm_unlock(clkdm->pwrdm.ptr);
 		return 0;
 	}
arch/arm/mach-omap2/clockdomain.h +3 -3
index 50c3cd8..2da3765 100644
@@ -91,8 +91,8 @@ struct clkdm_autodep {
 struct clkdm_dep {
 	const char *clkdm_name;
 	struct clockdomain *clkdm;
-	atomic_t wkdep_usecount;
-	atomic_t sleepdep_usecount;
+	s16 wkdep_usecount;
+	s16 sleepdep_usecount;
 };
 
 /* Possible flags for struct clockdomain._flags */
@@ -136,7 +136,7 @@ struct clockdomain {
 	const u16 clkdm_offs;
 	struct clkdm_dep *wkdep_srcs;
 	struct clkdm_dep *sleepdep_srcs;
-	atomic_t usecount;
+	int usecount;
 	struct list_head node;
 };
 
arch/arm/mach-omap2/cm3xxx.c +3 -3
index b94af4c..9061c30 100644
@@ -186,7 +186,7 @@ static int omap3xxx_clkdm_clear_all_sleepdeps(struct clockdomain *clkdm)
 			continue; /* only happens if data is erroneous */
 
 		mask |= 1 << cd->clkdm->dep_bit;
-		atomic_set(&cd->sleepdep_usecount, 0);
+		cd->sleepdep_usecount = 0;
 	}
 	omap2_cm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs,
 				    OMAP3430_CM_SLEEPDEP);
@@ -209,7 +209,7 @@ static int omap3xxx_clkdm_wakeup(struct clockdomain *clkdm)
 
 static void omap3xxx_clkdm_allow_idle(struct clockdomain *clkdm)
 {
-	if (atomic_read(&clkdm->usecount) > 0)
+	if (clkdm->usecount > 0)
 		clkdm_add_autodeps(clkdm);
 
 	omap3xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
@@ -221,7 +221,7 @@ static void omap3xxx_clkdm_deny_idle(struct clockdomain *clkdm)
 	omap3xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
 					clkdm->clktrctrl_mask);
 
-	if (atomic_read(&clkdm->usecount) > 0)
+	if (clkdm->usecount > 0)
 		clkdm_del_autodeps(clkdm);
 }
 
arch/arm/mach-omap2/cminst44xx.c +1 -1
index 7f9a464..f0290f5 100644
@@ -393,7 +393,7 @@ static int omap4_clkdm_clear_all_wkup_sleep_deps(struct clockdomain *clkdm)
 			continue; /* only happens if data is erroneous */
 
 		mask |= 1 << cd->clkdm->dep_bit;
-		atomic_set(&cd->wkdep_usecount, 0);
+		cd->wkdep_usecount = 0;
 	}
 
 	omap4_cminst_clear_inst_reg_bits(mask, clkdm->prcm_partition,
arch/arm/mach-omap2/pm-debug.c +2 -4
index 3cf4fdf..806a06b 100644
@@ -84,10 +84,8 @@ static int clkdm_dbg_show_counter(struct clockdomain *clkdm, void *user)
 		strncmp(clkdm->name, "dpll", 4) == 0)
 		return 0;
 
-	seq_printf(s, "%s->%s (%d)", clkdm->name,
-			clkdm->pwrdm.ptr->name,
-			atomic_read(&clkdm->usecount));
-	seq_printf(s, "\n");
+	seq_printf(s, "%s->%s (%d)\n", clkdm->name, clkdm->pwrdm.ptr->name,
+		   clkdm->usecount);
 
 	return 0;
 }
arch/arm/mach-omap2/pm.c +2 -1
index 2e2a897..6b7cb7c 100644
@@ -78,11 +78,12 @@ static void __init omap2_init_processor_devices(void)
 
 int __init omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused)
 {
+	/* XXX The usecount test is racy */
 	if ((clkdm->flags & CLKDM_CAN_ENABLE_AUTO) &&
 	    !(clkdm->flags & CLKDM_MISSING_IDLE_REPORTING))
 		clkdm_allow_idle(clkdm);
 	else if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP &&
-		 atomic_read(&clkdm->usecount) == 0)
+		 clkdm->usecount == 0)
 		clkdm_sleep(clkdm);
 	return 0;
 }
arch/arm/mach-omap2/prm2xxx_3xxx.c +2 -1
index a3e121f..947f6ad 100644
@@ -210,6 +210,7 @@ int omap2_clkdm_read_wkdep(struct clockdomain *clkdm1,
 					     PM_WKDEP, (1 << clkdm2->dep_bit));
 }
 
+/* XXX Caller must hold the clkdm's powerdomain lock */
 int omap2_clkdm_clear_all_wkdeps(struct clockdomain *clkdm)
 {
 	struct clkdm_dep *cd;
@@ -221,7 +222,7 @@ int omap2_clkdm_clear_all_wkdeps(struct clockdomain *clkdm)
 
 		/* PRM accesses are slow, so minimize them */
 		mask |= 1 << cd->clkdm->dep_bit;
-		atomic_set(&cd->wkdep_usecount, 0);
+		cd->wkdep_usecount = 0;
 	}
 
 	omap2_prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs,
#24 lore raw

PATCH 9/10 ARM: OMAP2+: clockdomain: convert existing atomic usecounts into spinlock-protected shorts/ints

Quoted 306 lines · Paul Walmsley

The atomic usecounts seem to be confusing, and are no longer needed since the operations that they are attached to really should take place under lock. Replace the atomic counters with simple integers, protected by the enclosing powerdomain spinlock.

---
 arch/arm/mach-omap2/clockdomain.c  |   88 +++++++++++++++++++++++++++++++-----
 arch/arm/mach-omap2/clockdomain.h  |    6 +-
 arch/arm/mach-omap2/cm3xxx.c       |    6 +-
 arch/arm/mach-omap2/cminst44xx.c   |    2 -
 arch/arm/mach-omap2/pm-debug.c     |    6 +-
 arch/arm/mach-omap2/pm.c           |    3 +
 arch/arm/mach-omap2/prm2xxx_3xxx.c |    3 +
 7 files changed, 88 insertions(+), 26 deletions(-)
arch/arm/mach-omap2/clockdomain.c +75 -13
index 9d5b69f..ed8ac2f 100644
@@ -210,7 +210,8 @@ static int _clkdm_add_wkdep(struct clockdomain *clkdm1,
 		return ret;
 	}
 
-	if (atomic_inc_return(&cd->wkdep_usecount) == 1) {
+	cd->wkdep_usecount++;
+	if (cd->wkdep_usecount == 1) {
 		pr_debug("clockdomain: hardware will wake up %s when %s wakes up\n",
 			 clkdm1->name, clkdm2->name);
 
@@ -252,7 +253,8 @@ static int _clkdm_del_wkdep(struct clockdomain *clkdm1,
 		return ret;
 	}
 
-	if (atomic_dec_return(&cd->wkdep_usecount) == 0) {
+	cd->wkdep_usecount--;
+	if (cd->wkdep_usecount == 0) {
 		pr_debug("clockdomain: hardware will no longer wake up %s after %s wakes up\n",
 			 clkdm1->name, clkdm2->name);
 
@@ -296,7 +298,8 @@ static int _clkdm_add_sleepdep(struct clockdomain *clkdm1,
 		return ret;
 	}
 
-	if (atomic_inc_return(&cd->sleepdep_usecount) == 1) {
+	cd->sleepdep_usecount++;
+	if (cd->sleepdep_usecount == 1) {
 		pr_debug("clockdomain: will prevent %s from sleeping if %s is active\n",
 			 clkdm1->name, clkdm2->name);
 
@@ -340,7 +343,8 @@ static int _clkdm_del_sleepdep(struct clockdomain *clkdm1,
 		return ret;
 	}
 
-	if (atomic_dec_return(&cd->sleepdep_usecount) == 0) {
+	cd->sleepdep_usecount--;
+	if (cd->sleepdep_usecount == 0) {
 		pr_debug("clockdomain: will no longer prevent %s from sleeping if %s is active\n",
 			 clkdm1->name, clkdm2->name);
 
@@ -567,7 +571,21 @@ struct powerdomain *clkdm_get_pwrdm(struct clockdomain *clkdm)
  */
 int clkdm_add_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
 {
-	return _clkdm_add_wkdep(clkdm1, clkdm2);
+	struct clkdm_dep *cd;
+	int ret;
+
+	if (!clkdm1 || !clkdm2)
+		return -EINVAL;
+
+	cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs);
+	if (IS_ERR(cd))
+		return PTR_ERR(cd);
+
+	pwrdm_lock(cd->clkdm->pwrdm.ptr);
+	ret = _clkdm_add_wkdep(clkdm1, clkdm2);
+	pwrdm_unlock(cd->clkdm->pwrdm.ptr);
+
+	return ret;
 }
 
 /**
@@ -582,7 +600,21 @@ int clkdm_add_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
  */
 int clkdm_del_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
 {
-	return _clkdm_del_wkdep(clkdm1, clkdm2);
+	struct clkdm_dep *cd;
+	int ret;
+
+	if (!clkdm1 || !clkdm2)
+		return -EINVAL;
+
+	cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs);
+	if (IS_ERR(cd))
+		return PTR_ERR(cd);
+
+	pwrdm_lock(cd->clkdm->pwrdm.ptr);
+	ret = _clkdm_del_wkdep(clkdm1, clkdm2);
+	pwrdm_unlock(cd->clkdm->pwrdm.ptr);
+
+	return ret;
 }
 
 /**
@@ -620,7 +652,7 @@ int clkdm_read_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
 		return ret;
 	}
 
-	/* XXX It's faster to return the atomic wkdep_usecount */
+	/* XXX It's faster to return the wkdep_usecount */
 	return arch_clkdm->clkdm_read_wkdep(clkdm1, clkdm2);
 }
 
@@ -659,7 +691,21 @@ int clkdm_clear_all_wkdeps(struct clockdomain *clkdm)
  */
 int clkdm_add_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
 {
-	return _clkdm_add_sleepdep(clkdm1, clkdm2);
+	struct clkdm_dep *cd;
+	int ret;
+
+	if (!clkdm1 || !clkdm2)
+		return -EINVAL;
+
+	cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs);
+	if (IS_ERR(cd))
+		return PTR_ERR(cd);
+
+	pwrdm_lock(cd->clkdm->pwrdm.ptr);
+	ret = _clkdm_add_sleepdep(clkdm1, clkdm2);
+	pwrdm_unlock(cd->clkdm->pwrdm.ptr);
+
+	return ret;
 }
 
 /**
@@ -676,7 +722,21 @@ int clkdm_add_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
  */
 int clkdm_del_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
 {
-	return _clkdm_del_sleepdep(clkdm1, clkdm2);
+	struct clkdm_dep *cd;
+	int ret;
+
+	if (!clkdm1 || !clkdm2)
+		return -EINVAL;
+
+	cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs);
+	if (IS_ERR(cd))
+		return PTR_ERR(cd);
+
+	pwrdm_lock(cd->clkdm->pwrdm.ptr);
+	ret = _clkdm_del_sleepdep(clkdm1, clkdm2);
+	pwrdm_unlock(cd->clkdm->pwrdm.ptr);
+
+	return ret;
 }
 
 /**
@@ -716,7 +776,7 @@ int clkdm_read_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
 		return ret;
 	}
 
-	/* XXX It's faster to return the atomic sleepdep_usecount */
+	/* XXX It's faster to return the sleepdep_usecount */
 	return arch_clkdm->clkdm_read_sleepdep(clkdm1, clkdm2);
 }
 
@@ -1063,7 +1123,8 @@ static int _clkdm_clk_hwmod_enable(struct clockdomain *clkdm)
 	 * should be called for every clock instance or hwmod that is
 	 * enabled, so the clkdm can be force woken up.
 	 */
-	if ((atomic_inc_return(&clkdm->usecount) > 1) && autodeps) {
+	clkdm->usecount++;
+	if (clkdm->usecount > 1 && autodeps) {
 		pwrdm_unlock(clkdm->pwrdm.ptr);
 		return 0;
 	}
@@ -1084,13 +1145,14 @@ static int _clkdm_clk_hwmod_disable(struct clockdomain *clkdm)
 
 	pwrdm_lock(clkdm->pwrdm.ptr);
 
-	if (atomic_read(&clkdm->usecount) == 0) {
+	if (clkdm->usecount == 0) {
 		pwrdm_unlock(clkdm->pwrdm.ptr);
 		WARN_ON(1); /* underflow */
 		return -ERANGE;
 	}
 
-	if (atomic_dec_return(&clkdm->usecount) > 0) {
+	clkdm->usecount--;
+	if (clkdm->usecount > 0) {
 		pwrdm_unlock(clkdm->pwrdm.ptr);
 		return 0;
 	}
arch/arm/mach-omap2/clockdomain.h +3 -3
index 50c3cd8..2da3765 100644
@@ -91,8 +91,8 @@ struct clkdm_autodep {
 struct clkdm_dep {
 	const char *clkdm_name;
 	struct clockdomain *clkdm;
-	atomic_t wkdep_usecount;
-	atomic_t sleepdep_usecount;
+	s16 wkdep_usecount;
+	s16 sleepdep_usecount;
 };
 
 /* Possible flags for struct clockdomain._flags */
@@ -136,7 +136,7 @@ struct clockdomain {
 	const u16 clkdm_offs;
 	struct clkdm_dep *wkdep_srcs;
 	struct clkdm_dep *sleepdep_srcs;
-	atomic_t usecount;
+	int usecount;
 	struct list_head node;
 };
 
arch/arm/mach-omap2/cm3xxx.c +3 -3
index b94af4c..9061c30 100644
@@ -186,7 +186,7 @@ static int omap3xxx_clkdm_clear_all_sleepdeps(struct clockdomain *clkdm)
 			continue; /* only happens if data is erroneous */
 
 		mask |= 1 << cd->clkdm->dep_bit;
-		atomic_set(&cd->sleepdep_usecount, 0);
+		cd->sleepdep_usecount = 0;
 	}
 	omap2_cm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs,
 				    OMAP3430_CM_SLEEPDEP);
@@ -209,7 +209,7 @@ static int omap3xxx_clkdm_wakeup(struct clockdomain *clkdm)
 
 static void omap3xxx_clkdm_allow_idle(struct clockdomain *clkdm)
 {
-	if (atomic_read(&clkdm->usecount) > 0)
+	if (clkdm->usecount > 0)
 		clkdm_add_autodeps(clkdm);
 
 	omap3xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
@@ -221,7 +221,7 @@ static void omap3xxx_clkdm_deny_idle(struct clockdomain *clkdm)
 	omap3xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
 					clkdm->clktrctrl_mask);
 
-	if (atomic_read(&clkdm->usecount) > 0)
+	if (clkdm->usecount > 0)
 		clkdm_del_autodeps(clkdm);
 }
 
arch/arm/mach-omap2/cminst44xx.c +1 -1
index 7f9a464..f0290f5 100644
@@ -393,7 +393,7 @@ static int omap4_clkdm_clear_all_wkup_sleep_deps(struct clockdomain *clkdm)
 			continue; /* only happens if data is erroneous */
 
 		mask |= 1 << cd->clkdm->dep_bit;
-		atomic_set(&cd->wkdep_usecount, 0);
+		cd->wkdep_usecount = 0;
 	}
 
 	omap4_cminst_clear_inst_reg_bits(mask, clkdm->prcm_partition,
arch/arm/mach-omap2/pm-debug.c +2 -4
index 3cf4fdf..806a06b 100644
@@ -84,10 +84,8 @@ static int clkdm_dbg_show_counter(struct clockdomain *clkdm, void *user)
 		strncmp(clkdm->name, "dpll", 4) == 0)
 		return 0;
 
-	seq_printf(s, "%s->%s (%d)", clkdm->name,
-			clkdm->pwrdm.ptr->name,
-			atomic_read(&clkdm->usecount));
-	seq_printf(s, "\n");
+	seq_printf(s, "%s->%s (%d)\n", clkdm->name, clkdm->pwrdm.ptr->name,
+		   clkdm->usecount);
 
 	return 0;
 }
arch/arm/mach-omap2/pm.c +2 -1
index 2e2a897..6b7cb7c 100644
@@ -78,11 +78,12 @@ static void __init omap2_init_processor_devices(void)
 
 int __init omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused)
 {
+	/* XXX The usecount test is racy */
 	if ((clkdm->flags & CLKDM_CAN_ENABLE_AUTO) &&
 	    !(clkdm->flags & CLKDM_MISSING_IDLE_REPORTING))
 		clkdm_allow_idle(clkdm);
 	else if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP &&
-		 atomic_read(&clkdm->usecount) == 0)
+		 clkdm->usecount == 0)
 		clkdm_sleep(clkdm);
 	return 0;
 }
arch/arm/mach-omap2/prm2xxx_3xxx.c +0 -0
index a3e121f..947f6ad 100644

arch/arm/mach-omap2/prm2xxx_3xxx.c int omap2_clkdm_read_wkdep(struct clockdomain *clkdm1, · line 213

Quoted 4 lines
arch/arm/mach-omap2/prm2xxx_3xxx.c +1 -0
@@ -210,6 +210,7 @@ int omap2_clkdm_read_wkdep(struct clockdomain *clkdm1,
 					     PM_WKDEP, (1 << clkdm2->dep_bit));
 }
 
+/* XXX Caller must hold the clkdm's powerdomain lock */

Isn't this comment applicable for all the internal api's

omap2_clkdm_clear_all_wkdeps,
omap3xxx_clkdm_add_sleepdep,
omap3xxx_clkdm_del_sleepdep,
omap3xxx_clkdm_read_sleepdep,
omap3xxx_clkdm_clear_all_sleepdeps,

arch/arm/mach-omap2/prm2xxx_3xxx.c int omap2_clkdm_read_wkdep(struct clockdomain *clkdm1, · line 214

Quoted 1 line
arch/arm/mach-omap2/prm2xxx_3xxx.c +0 -0
 int omap2_clkdm_clear_all_wkdeps(struct clockdomain *clkdm)

Why this function is non-static? typo??? May be I am missing something.

It was static before, but api became public by below commit -

ARM: OMAP2/3: clockdomain/PRM/CM: move the low-level clockdomain functions into PRM/CM

Thanks,
Vaibhav

Quoted 19 lines
arch/arm/mach-omap2/prm2xxx_3xxx.c +1 -1
 {
 	struct clkdm_dep *cd;
@@ -221,7 +222,7 @@ int omap2_clkdm_clear_all_wkdeps(struct clockdomain *clkdm)
 
 		/* PRM accesses are slow, so minimize them */
 		mask |= 1 << cd->clkdm->dep_bit;
-		atomic_set(&cd->wkdep_usecount, 0);
+		cd->wkdep_usecount = 0;
 	}
 
 	omap2_prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs,

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

#25 lore raw

PATCH 9/10 ARM: OMAP2+: clockdomain: convert existing atomic usecounts into spinlock-protected shorts/ints

In reply to Paul Walmsley

Hi Paul,

Quoted 4 lines · Paul Walmsley

The atomic usecounts seem to be confusing, and are no longer needed since the operations that they are attached to really should take place under lock. Replace the atomic counters with simple integers, protected by the enclosing powerdomain spinlock.

[...]

arch/arm/mach-omap2/clockdomain.c static int _clkdm_clk_hwmod_enable(struct clockdomain *clkdm) · line 1130

Quoted 11 lines
arch/arm/mach-omap2/clockdomain.c +2 -1
@@ -1063,7 +1123,8 @@ static int _clkdm_clk_hwmod_enable(struct clockdomain *clkdm)
 	 * should be called for every clock instance or hwmod that is
 	 * enabled, so the clkdm can be force woken up.
 	 */
-	if ((atomic_inc_return(&clkdm->usecount) > 1) && autodeps) {
+	clkdm->usecount++;
+	if (clkdm->usecount > 1 && autodeps) {
 		pwrdm_unlock(clkdm->pwrdm.ptr);
 		return 0;
 	}

This is not directly related to this patch but something I noticed when I enabled the various debug prints.

if the clkdm->usecount is > 1, there is still a call to arch_clkdm->clkdm_clk_enable(). Won't the usecount >1 guarantee that the clkdm is in the right state and the PRCM access can be skipped?

Regards,
Vaibhav

author maintainer
#26 lore raw

PATCH 10/10 ARM: OMAP2+: powerdomain: fix whitespace, improve flag comments

In reply to Paul Walmsley

Fix some whitespace problems introduced by commit da03ce65b5431245b9cd20db3edaaa6b9f5c8dc1 ("OMAP3: powerdomain data:
add voltage domains"). Also, improve the documentation for the struct powerdomain.flags field.

---
 arch/arm/mach-omap2/powerdomain.h                |   26 +++++++------
 arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c |    4 +-
 arch/arm/mach-omap2/powerdomains2xxx_data.c      |    8 ++--
 arch/arm/mach-omap2/powerdomains3xxx_data.c      |   44 +++++++++++-----------
 4 files changed, 42 insertions(+), 40 deletions(-)
arch/arm/mach-omap2/powerdomain.h +14 -12
index 83b4892..842ba46 100644
@@ -43,18 +43,20 @@
 #define PWRSTS_OFF_RET_ON	(PWRSTS_OFF_RET | PWRSTS_ON)
 
 
-/* Powerdomain flags */
-#define PWRDM_HAS_HDWR_SAR	(1 << 0) /* hardware save-and-restore support */
-#define PWRDM_HAS_MPU_QUIRK	(1 << 1) /* MPU pwr domain has MEM bank 0 bits
-					  * in MEM bank 1 position. This is
-					  * true for OMAP3430
-					  */
-#define PWRDM_HAS_LOWPOWERSTATECHANGE	(1 << 2) /*
-						  * support to transition from a
-						  * sleep state to a lower sleep
-						  * state without waking up the
-						  * powerdomain
-						  */
+/*
+ * Powerdomain flags (struct powerdomain.flags)
+ *
+ * PWRDM_HAS_HDWR_SAR - powerdomain has hardware save-and-restore support
+ *
+ * PWRDM_HAS_MPU_QUIRK - MPU pwr domain has MEM bank 0 bits in MEM
+ * bank 1 position. This is true for OMAP3430
+ *
+ * PWRDM_HAS_LOWPOWERSTATECHANGE - can transition from a sleep state
+ * to a lower sleep state without waking up the powerdomain
+ */
+#define PWRDM_HAS_HDWR_SAR		BIT(0)
+#define PWRDM_HAS_MPU_QUIRK		BIT(1)
+#define PWRDM_HAS_LOWPOWERSTATECHANGE	BIT(2)
 
 /*
  * Number of memory banks that are power-controllable.	On OMAP4430, the
arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c +2 -2
index d3a5399..7b946f1 100644
@@ -54,12 +54,12 @@ struct powerdomain gfx_omap2_pwrdm = {
 	.pwrsts_mem_on	  = {
 		[0] = PWRSTS_ON,  /* MEMONSTATE */
 	},
-	.voltdm           = { .name = "core" },
+	.voltdm		  = { .name = "core" },
 };
 
 struct powerdomain wkup_omap2_pwrdm = {
 	.name		= "wkup_pwrdm",
 	.prcm_offs	= WKUP_MOD,
 	.pwrsts		= PWRSTS_ON,
-	.voltdm         = { .name = "wakeup" },
+	.voltdm		= { .name = "wakeup" },
 };
arch/arm/mach-omap2/powerdomains2xxx_data.c +4 -4
index 01abc1e..578eef8 100644
@@ -38,7 +38,7 @@ static struct powerdomain dsp_pwrdm = {
 	.pwrsts_mem_on	  = {
 		[0] = PWRSTS_ON,
 	},
-	.voltdm           = { .name = "core" },
+	.voltdm		  = { .name = "core" },
 };
 
 static struct powerdomain mpu_24xx_pwrdm = {
@@ -53,7 +53,7 @@ static struct powerdomain mpu_24xx_pwrdm = {
 	.pwrsts_mem_on	  = {
 		[0] = PWRSTS_ON,
 	},
-	.voltdm           = { .name = "core" },
+	.voltdm		  = { .name = "core" },
 };
 
 static struct powerdomain core_24xx_pwrdm = {
@@ -72,7 +72,7 @@ static struct powerdomain core_24xx_pwrdm = {
 		[1] = PWRSTS_OFF_RET_ON, /* MEM2ONSTATE */
 		[2] = PWRSTS_OFF_RET_ON, /* MEM3ONSTATE */
 	},
-	.voltdm           = { .name = "core" },
+	.voltdm		  = { .name = "core" },
 };
 
 
@@ -94,7 +94,7 @@ static struct powerdomain mdm_pwrdm = {
 	.pwrsts_mem_on	  = {
 		[0] = PWRSTS_ON,  /* MEMONSTATE */
 	},
-	.voltdm           = { .name = "core" },
+	.voltdm		  = { .name = "core" },
 };
 
 /*
arch/arm/mach-omap2/powerdomains3xxx_data.c +22 -22

170 lines not on this page · raw message

#27 lore raw

cover ARM: OMAP2+: second set of PM fixes and cleanup for 3.9

In reply to Paul Walmsley

Hi Paul,

I just tested this + next two powerdomain series from you on omap3beagle
+ omap4panda boards. This set seems fine, for the code I don't have any major complaints either, thus you can add my ack if you like. I'll send comments for the next two sets soon also.

-Tero

Quoted 83 lines · Paul Walmsley

Several more OMAP2+ power management fixes, optimizations, and cleanup, intended for 3.9. This series is also a prerequisite for the functional powerdomain conversion series.

I'll plan to bundle these patches together into a pull request with the first set of 3.9 PM patches, sent earlier.

- Paul

---

vmlinux object size
(delta in bytes from TEST_pm_cleanup_fixes_a_3.9 (8f5e20850396fc60fd4ee01f586705033902bb53)):

   text     data      bss    total  kernel
   +460     -368        0      +92  am33xx_only
   +200     -464        0     -264  n800_multi_omap2xxx
   +192     -144        0      +48  n800_only_a
      0        0        0        0  omap1_defconfig
      0        0        0        0  omap1_defconfig_1510innovator_only
      0        0        0        0  omap1_defconfig_5912osk_only
   +296    -1816        0    -1520  omap2plus_defconfig
   +272     -176        0      +96  omap2plus_defconfig_2430sdp_only
   +232    -1816        0    -1584  omap2plus_defconfig_cpupm
   +280    -1520        0    -1240  omap2plus_defconfig_no_pm
  +4388    -1016        0    +3372  omap2plus_defconfig_omap2_4_only
   +468     -952        0     -484  omap2plus_defconfig_omap3_4_only
   +700     -584     -144      -28  rmk_omap3430_ldp_allnoconfig
   +452     -648        0     -196  rmk_omap3430_ldp_oldconfig
   +700     -584     -144      -28  rmk_omap4430_sdp_allnoconfig
   +424     -328        0      +96  rmk_omap4430_sdp_oldconfig

Boot-time memory difference
(delta in bytes from TEST_pm_cleanup_fixes_a_3.9 (8f5e20850396fc60fd4ee01f586705033902bb53))

  avail  rsrvd   high  freed  board          kconfig
     4k    -4k      .      .  2430sdp        omap2plus_defconfig
     4k    -4k      .      .  3517evm        omap2plus_defconfig
     4k    -4k      .      .  3530es3beagle  omap2plus_defconfig
     4k    -4k      .      .  3730beaglexm   omap2plus_defconfig
     4k    -4k      .      .  37xxevm        omap2plus_defconfig
     4k    -4k      .      .  4430es2panda   omap2plus_defconfig
     4k    -4k      .      .  cmt3517        omap2plus_defconfig

Paul Walmsley (10):
ARM: OMAP3/4: cpuidle: fix sparse and checkpatch warnings
ARM: OMAP2+: clockdomain: add pwrdm_state_switch() call to clkdm_sleep()
ARM: OMAP2xxx: PM: clean up some crufty powerstate programming code
ARM: OMAP2: PM/powerdomain: drop unnecessary pwrdm_wait_transition()
ARM: OMAP2+: PM/powerdomain: move omap_set_pwrdm_state() to powerdomain code
ARM: OMAP2+: powerdomain/clockdomain: add a per-powerdomain spinlock
ARM: OMAP2xxx: CM: remove autodep handling
ARM: OMAP2+: clockdomain: work on wkdep/sleepdep functions
ARM: OMAP2+: clockdomain: convert existing atomic usecounts into spinlock-protected shorts/ints
ARM: OMAP2+: powerdomain: fix whitespace, improve flag comments

 arch/arm/mach-omap2/clockdomain-powerdomain.h    |   22 +
 arch/arm/mach-omap2/clockdomain.c                |  550 +++++++++++++++-------
 arch/arm/mach-omap2/clockdomain.h                |   17 -
 arch/arm/mach-omap2/cm2xxx.c                     |   33 -
 arch/arm/mach-omap2/cm3xxx.c                     |   14 -
 arch/arm/mach-omap2/cminst44xx.c                 |    2 
 arch/arm/mach-omap2/cpuidle34xx.c                |   14 -
 arch/arm/mach-omap2/cpuidle44xx.c                |   28 +
 arch/arm/mach-omap2/pm-debug.c                   |    6 
 arch/arm/mach-omap2/pm.c                         |   65 ---
 arch/arm/mach-omap2/pm.h                         |    1 
 arch/arm/mach-omap2/pm24xx.c                     |   30 -
 arch/arm/mach-omap2/powerdomain-clockdomain.h    |   27 +
 arch/arm/mach-omap2/powerdomain.c                |  176 +++++--
 arch/arm/mach-omap2/powerdomain.h                |   42 +-
 arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c |    4 
 arch/arm/mach-omap2/powerdomains2xxx_data.c      |    8 
 arch/arm/mach-omap2/powerdomains3xxx_data.c      |   44 +-
 arch/arm/mach-omap2/prm2xxx_3xxx.c               |    3 
 19 files changed, 661 insertions(+), 425 deletions(-)
 create mode 100644 arch/arm/mach-omap2/clockdomain-powerdomain.h
 create mode 100644 arch/arm/mach-omap2/powerdomain-clockdomain.h

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel