linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/10] OMAP2/3/4 clockdomains/powerdomains: split shared dependencies and clean up - for 2.6.34
@ 2010-01-12  1:05 Paul Walmsley
  2010-01-12  1:05 ` [PATCH 01/10] OMAP2/3 clkdm/pwrdm: move wkdep/sleepdep handling from pwrdm to clkdm Paul Walmsley
                   ` (9 more replies)
  0 siblings, 10 replies; 14+ messages in thread
From: Paul Walmsley @ 2010-01-12  1:05 UTC (permalink / raw)
  To: linux-arm-kernel

Hello,

this series has already been posted on linux-omap, but is being
reposted here on linux-arm-kernel in case others wish to comment
before sending upstream to the for-next tree for 2.6.34 merging.

- Paul

---

Hi,

This series moves wakeup and sleep dependencies on the OMAP2/3 chips from
the powerdomain layer to the clockdomain layer, where they belong.  It also
adds usecounting for clockdomain dependency usecounting, which fixes the
obvious problem that occurs when several different pieces of code need
to add clockdomain dependencies, and then one removes the dependency.
(To add usecounting, the dependencies that were shared between
clockdomains have been split into separate records.)  These changes should
prepare the clockdomain code for OMAP4 clockdomain dependencies.

The series also does some cleanup.  struct powerdomain is packed, the
dead function pwrdm_clk_state_switch() is removed, documentation is improved,
the nonexistent MDM clockdomain is removed from OMAP2420.

Boot-tested on N800, 2430SDP, and OMAP3 Beagle.  Compile-tested with
omap_osk_5912_defconfig.

Applies on the 'for_2.6.34' branch of git://git.pwsan.com/linux-2.6


- Paul

---

   text    data     bss     dec     hex filename
3622921  198528  102984 3924433  3be1d1 vmlinux.beagle.orig
3623325  199168  102984 3925477  3be5e5 vmlinux.beagle

Paul Walmsley (10):
      OMAP2/3 clkdm/pwrdm: move wkdep/sleepdep handling from pwrdm to clkdm
      OMAP2/3 clockdomains: split shared structures so usecounting works
      OMAP2 clockdomain: modem clockdomain is only present on OMAP2430
      OMAP clockdomain/powerdomain: remove runtime register/unregister
      OMAP clockdomains: add usecounting for wakeup and sleep dependencies
      OMAP2/3/4 clockdomain: add clkdm_clear_all_{wkdep,sleepdep}s()
      OMAP powerdomain/PM: use symbolic constants for the max number of power states
      OMAP powerdomain: rearrange struct powerdomain to save some memory
      OMAP powerdomain: remove pwrdm_clk_state_switch
      OMAP clockdomain/powerdomain: improve documentation


 arch/arm/mach-omap2/clockdomain.c             |  691 +++++++++++++++++++------
 arch/arm/mach-omap2/clockdomains.h            |  474 +++++++++++++++++
 arch/arm/mach-omap2/io.c                      |    2 
 arch/arm/mach-omap2/omap_hwmod.c              |   10 
 arch/arm/mach-omap2/pm34xx.c                  |   10 
 arch/arm/mach-omap2/powerdomain.c             |  570 ++++-----------------
 arch/arm/mach-omap2/powerdomains.h            |   88 ---
 arch/arm/mach-omap2/powerdomains24xx.h        |   87 ---
 arch/arm/mach-omap2/powerdomains34xx.h        |  145 -----
 arch/arm/mach-omap2/prcm.c                    |   12 
 arch/arm/plat-omap/include/plat/clockdomain.h |   99 ++--
 arch/arm/plat-omap/include/plat/powerdomain.h |   78 +--
 arch/arm/plat-omap/include/plat/prcm.h        |    8 
 13 files changed, 1241 insertions(+), 1033 deletions(-)

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 01/10] OMAP2/3 clkdm/pwrdm: move wkdep/sleepdep handling from pwrdm to clkdm
  2010-01-12  1:05 [PATCH 00/10] OMAP2/3/4 clockdomains/powerdomains: split shared dependencies and clean up - for 2.6.34 Paul Walmsley
@ 2010-01-12  1:05 ` Paul Walmsley
  2010-01-12  1:05 ` [PATCH 02/10] OMAP2/3 clockdomains: split shared structures so usecounting works Paul Walmsley
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 14+ messages in thread
From: Paul Walmsley @ 2010-01-12  1:05 UTC (permalink / raw)
  To: linux-arm-kernel

Move clockdomain wakeup dependency and sleep dependency data
structures from the powerdomain layer to the clockdomain layer, where
they belong.  These dependencies were originally placed in the
powerdomain layer due to unclear documentation; however, it is clear
now that these dependencies are between clockdomains.  For OMAP2/3,
this is not such a big problem, but for OMAP4 this needs to be fixed.

Thanks to Beno?t Cousson <b-cousson@ti.com> for his advice on this
patch.

Signed-off-by: Paul Walmsley <paul@pwsan.com>
Cc: Beno?t Cousson <b-cousson@ti.com>
---
 arch/arm/mach-omap2/clockdomain.c             |  368 ++++++++++++++++++++----
 arch/arm/mach-omap2/clockdomains.h            |  378 ++++++++++++++++++++++++-
 arch/arm/mach-omap2/io.c                      |    2 
 arch/arm/mach-omap2/omap_hwmod.c              |   10 -
 arch/arm/mach-omap2/pm34xx.c                  |   10 +
 arch/arm/mach-omap2/powerdomain.c             |  259 -----------------
 arch/arm/mach-omap2/powerdomains.h            |   88 +-----
 arch/arm/mach-omap2/powerdomains24xx.h        |   87 ------
 arch/arm/mach-omap2/powerdomains34xx.h        |  145 ----------
 arch/arm/mach-omap2/prcm.c                    |   12 +
 arch/arm/plat-omap/include/plat/clockdomain.h |   50 +++
 arch/arm/plat-omap/include/plat/powerdomain.h |   34 --
 arch/arm/plat-omap/include/plat/prcm.h        |    8 +
 13 files changed, 761 insertions(+), 690 deletions(-)

diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c
index 8c9e78c..a70ba29 100644
--- a/arch/arm/mach-omap2/clockdomain.c
+++ b/arch/arm/mach-omap2/clockdomain.c
@@ -27,14 +27,14 @@
 
 #include <linux/bitops.h>
 
-#include <plat/clock.h>
-
 #include "prm.h"
 #include "prm-regbits-24xx.h"
 #include "cm.h"
 
+#include <plat/clock.h>
 #include <plat/powerdomain.h>
 #include <plat/clockdomain.h>
+#include <plat/prcm.h>
 
 /* clkdm_list contains all registered struct clockdomains */
 static LIST_HEAD(clkdm_list);
@@ -42,28 +42,75 @@ static LIST_HEAD(clkdm_list);
 /* clkdm_mutex protects clkdm_list add and del ops */
 static DEFINE_MUTEX(clkdm_mutex);
 
-/* array of powerdomain deps to be added/removed when clkdm in hwsup mode */
-static struct clkdm_pwrdm_autodep *autodeps;
+/* array of clockdomain deps to be added/removed when clkdm in hwsup mode */
+static struct clkdm_autodep *autodeps;
 
 
 /* Private functions */
 
+static struct clockdomain *_clkdm_lookup(const char *name)
+{
+	struct clockdomain *clkdm, *temp_clkdm;
+
+	if (!name)
+		return NULL;
+
+	clkdm = NULL;
+
+	list_for_each_entry(temp_clkdm, &clkdm_list, node) {
+		if (!strcmp(name, temp_clkdm->name)) {
+			clkdm = temp_clkdm;
+			break;
+		}
+	}
+
+	return clkdm;
+}
+
+/* _clkdm_deps_lookup - look up the specified clockdomain in a clkdm list */
+static struct clkdm_dep *_clkdm_deps_lookup(struct clockdomain *clkdm,
+					    struct clkdm_dep *deps)
+{
+	struct clkdm_dep *cd;
+
+	if (!clkdm || !deps || !omap_chip_is(clkdm->omap_chip))
+		return ERR_PTR(-EINVAL);
+
+	for (cd = deps; cd->clkdm_name; cd++) {
+
+		if (!omap_chip_is(cd->omap_chip))
+			continue;
+
+		if (!cd->clkdm && cd->clkdm_name)
+			cd->clkdm = _clkdm_lookup(cd->clkdm_name);
+
+		if (cd->clkdm == clkdm)
+			break;
+
+	}
+
+	if (!cd->clkdm_name)
+		return ERR_PTR(-ENOENT);
+
+	return cd;
+}
+
 /*
- * _autodep_lookup - resolve autodep pwrdm names to pwrdm pointers; store
- * @autodep: struct clkdm_pwrdm_autodep * to resolve
+ * _autodep_lookup - resolve autodep clkdm names to clkdm pointers; store
+ * @autodep: struct clkdm_autodep * to resolve
  *
- * Resolve autodep powerdomain names to powerdomain pointers via
- * pwrdm_lookup() and store the pointers in the autodep structure.  An
- * "autodep" is a powerdomain sleep/wakeup dependency that is
+ * Resolve autodep clockdomain names to clockdomain pointers via
+ * clkdm_lookup() and store the pointers in the autodep structure.  An
+ * "autodep" is a clockdomain sleep/wakeup dependency that is
  * automatically added and removed whenever clocks in the associated
  * clockdomain are enabled or disabled (respectively) when the
  * clockdomain is in hardware-supervised mode.	Meant to be called
  * once at clockdomain layer initialization, since these should remain
  * fixed for a particular architecture.  No return value.
  */
-static void _autodep_lookup(struct clkdm_pwrdm_autodep *autodep)
+static void _autodep_lookup(struct clkdm_autodep *autodep)
 {
-	struct powerdomain *pwrdm;
+	struct clockdomain *clkdm;
 
 	if (!autodep)
 		return;
@@ -71,13 +118,13 @@ static void _autodep_lookup(struct clkdm_pwrdm_autodep *autodep)
 	if (!omap_chip_is(autodep->omap_chip))
 		return;
 
-	pwrdm = pwrdm_lookup(autodep->pwrdm.name);
-	if (!pwrdm) {
-		pr_err("clockdomain: autodeps: powerdomain %s does not exist\n",
-			 autodep->pwrdm.name);
-		pwrdm = ERR_PTR(-ENOENT);
+	clkdm = clkdm_lookup(autodep->clkdm.name);
+	if (!clkdm) {
+		pr_err("clockdomain: autodeps: clockdomain %s does not exist\n",
+			 autodep->clkdm.name);
+		clkdm = ERR_PTR(-ENOENT);
 	}
-	autodep->pwrdm.ptr = pwrdm;
+	autodep->clkdm.ptr = clkdm;
 }
 
 /*
@@ -90,21 +137,21 @@ static void _autodep_lookup(struct clkdm_pwrdm_autodep *autodep)
  */
 static void _clkdm_add_autodeps(struct clockdomain *clkdm)
 {
-	struct clkdm_pwrdm_autodep *autodep;
+	struct clkdm_autodep *autodep;
 
-	for (autodep = autodeps; autodep->pwrdm.ptr; autodep++) {
-		if (IS_ERR(autodep->pwrdm.ptr))
+	for (autodep = autodeps; autodep->clkdm.ptr; autodep++) {
+		if (IS_ERR(autodep->clkdm.ptr))
 			continue;
 
 		if (!omap_chip_is(autodep->omap_chip))
 			continue;
 
 		pr_debug("clockdomain: adding %s sleepdep/wkdep for "
-			 "pwrdm %s\n", autodep->pwrdm.ptr->name,
-			 clkdm->pwrdm.ptr->name);
+			 "clkdm %s\n", autodep->clkdm.ptr->name,
+			 clkdm->name);
 
-		pwrdm_add_sleepdep(clkdm->pwrdm.ptr, autodep->pwrdm.ptr);
-		pwrdm_add_wkdep(clkdm->pwrdm.ptr, autodep->pwrdm.ptr);
+		clkdm_add_sleepdep(clkdm, autodep->clkdm.ptr);
+		clkdm_add_wkdep(clkdm, autodep->clkdm.ptr);
 	}
 }
 
@@ -118,21 +165,21 @@ static void _clkdm_add_autodeps(struct clockdomain *clkdm)
  */
 static void _clkdm_del_autodeps(struct clockdomain *clkdm)
 {
-	struct clkdm_pwrdm_autodep *autodep;
+	struct clkdm_autodep *autodep;
 
-	for (autodep = autodeps; autodep->pwrdm.ptr; autodep++) {
-		if (IS_ERR(autodep->pwrdm.ptr))
+	for (autodep = autodeps; autodep->clkdm.ptr; autodep++) {
+		if (IS_ERR(autodep->clkdm.ptr))
 			continue;
 
 		if (!omap_chip_is(autodep->omap_chip))
 			continue;
 
 		pr_debug("clockdomain: removing %s sleepdep/wkdep for "
-			 "pwrdm %s\n", autodep->pwrdm.ptr->name,
-			 clkdm->pwrdm.ptr->name);
+			 "clkdm %s\n", autodep->clkdm.ptr->name,
+			 clkdm->name);
 
-		pwrdm_del_sleepdep(clkdm->pwrdm.ptr, autodep->pwrdm.ptr);
-		pwrdm_del_wkdep(clkdm->pwrdm.ptr, autodep->pwrdm.ptr);
+		clkdm_del_sleepdep(clkdm, autodep->clkdm.ptr);
+		clkdm_del_wkdep(clkdm, autodep->clkdm.ptr);
 	}
 }
 
@@ -171,25 +218,6 @@ static void _omap2_clkdm_set_hwsup(struct clockdomain *clkdm, int enable)
 
 }
 
-static struct clockdomain *_clkdm_lookup(const char *name)
-{
-	struct clockdomain *clkdm, *temp_clkdm;
-
-	if (!name)
-		return NULL;
-
-	clkdm = NULL;
-
-	list_for_each_entry(temp_clkdm, &clkdm_list, node) {
-		if (!strcmp(name, temp_clkdm->name)) {
-			clkdm = temp_clkdm;
-			break;
-		}
-	}
-
-	return clkdm;
-}
-
 
 /* Public functions */
 
@@ -200,26 +228,24 @@ static struct clockdomain *_clkdm_lookup(const char *name)
  *
  * Set up internal state.  If a pointer to an array of clockdomains
  * was supplied, loop through the list of clockdomains, register all
- * that are available on the current platform.	Similarly, if a
- * pointer to an array of clockdomain-powerdomain autodependencies was
- * provided, register those.  No return value.
+ * that are available on the current platform. Similarly, if a pointer
+ * to an array of clockdomain autodependencies was provided, register
+ * those.  No return value.
  */
 void clkdm_init(struct clockdomain **clkdms,
-		struct clkdm_pwrdm_autodep *init_autodeps)
+		struct clkdm_autodep *init_autodeps)
 {
 	struct clockdomain **c = NULL;
-	struct clkdm_pwrdm_autodep *autodep = NULL;
+	struct clkdm_autodep *autodep = NULL;
 
 	if (clkdms)
 		for (c = clkdms; *c; c++)
 			clkdm_register(*c);
 
-	if (!cpu_is_omap44xx()) {
-		autodeps = init_autodeps;
-		if (autodeps)
-			for (autodep = autodeps; autodep->pwrdm.ptr; autodep++)
-				_autodep_lookup(autodep);
-	}
+	autodeps = init_autodeps;
+	if (autodeps)
+		for (autodep = autodeps; autodep->clkdm.ptr; autodep++)
+			_autodep_lookup(autodep);
 }
 
 /**
@@ -374,6 +400,226 @@ struct powerdomain *clkdm_get_pwrdm(struct clockdomain *clkdm)
 /* Hardware clockdomain control */
 
 /**
+ * clkdm_add_wkdep - add a wakeup dependency from clkdm2 to clkdm1
+ * @clkdm1: wake this struct clockdomain * up (dependent)
+ * @clkdm2: when this struct clockdomain * wakes up (source)
+ *
+ * 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.
+ */
+int clkdm_add_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
+{
+	struct clkdm_dep *cd;
+
+	if (!clkdm1 || !clkdm2)
+		return -EINVAL;
+
+	cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs);
+	if (IS_ERR(cd)) {
+		pr_debug("clockdomain: hardware cannot set/clear wake up of "
+			 "%s when %s wakes up\n", clkdm1->name, clkdm2->name);
+		return PTR_ERR(cd);
+	}
+
+	pr_debug("clockdomain: hardware will wake up %s when %s wakes up\n",
+		 clkdm1->name, clkdm2->name);
+
+	prm_set_mod_reg_bits((1 << clkdm2->dep_bit),
+			     clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP);
+
+	return 0;
+}
+
+/**
+ * clkdm_del_wkdep - remove a wakeup dependency from clkdm2 to clkdm1
+ * @clkdm1: wake this struct clockdomain * up (dependent)
+ * @clkdm2: when this struct clockdomain * wakes up (source)
+ *
+ * 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.
+ */
+int clkdm_del_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
+{
+	struct clkdm_dep *cd;
+
+	if (!clkdm1 || !clkdm2)
+		return -EINVAL;
+
+	cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs);
+	if (IS_ERR(cd)) {
+		pr_debug("clockdomain: hardware cannot set/clear wake up of "
+			 "%s when %s wakes up\n", clkdm1->name, clkdm2->name);
+		return PTR_ERR(cd);
+	}
+
+	pr_debug("clockdomain: hardware will no longer wake up %s after %s "
+		 "wakes up\n", clkdm1->name, clkdm2->name);
+
+	prm_clear_mod_reg_bits((1 << clkdm2->dep_bit),
+			       clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP);
+
+	return 0;
+}
+
+/**
+ * clkdm_read_wkdep - read wakeup dependency state from clkdm2 to clkdm1
+ * @clkdm1: wake this struct clockdomain * up (dependent)
+ * @clkdm2: when this struct clockdomain * wakes up (source)
+ *
+ * Return 1 if a hardware wakeup dependency exists wherein @clkdm1 will be
+ * awoken when @clkdm2 wakes up; 0 if dependency is not set; -EINVAL
+ * if either clockdomain pointer is invalid; or -ENOENT if the hardware
+ * is incapable.
+ *
+ * REVISIT: Currently this function only represents software-controllable
+ * wakeup dependencies.  Wakeup dependencies fixed in hardware are not
+ * yet handled here.
+ */
+int clkdm_read_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
+{
+	struct clkdm_dep *cd;
+
+	if (!clkdm1 || !clkdm2)
+		return -EINVAL;
+
+	cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs);
+	if (IS_ERR(cd)) {
+		pr_debug("clockdomain: hardware cannot set/clear wake up of "
+			 "%s when %s wakes up\n", clkdm1->name, clkdm2->name);
+		return PTR_ERR(cd);
+	}
+
+	return prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP,
+				       (1 << clkdm2->dep_bit));
+}
+
+/**
+ * clkdm_add_sleepdep - add a sleep dependency from clkdm2 to clkdm1
+ * @clkdm1: prevent this struct clockdomain * from sleeping (dependent)
+ * @clkdm2: when this struct clockdomain * is active (source)
+ *
+ * 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.
+ */
+int clkdm_add_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
+{
+	struct clkdm_dep *cd;
+
+	if (!cpu_is_omap34xx())
+		return -EINVAL;
+
+	if (!clkdm1 || !clkdm2)
+		return -EINVAL;
+
+	cd = _clkdm_deps_lookup(clkdm2, clkdm1->sleepdep_srcs);
+	if (IS_ERR(cd)) {
+		pr_debug("clockdomain: hardware cannot set/clear sleep "
+			 "dependency affecting %s from %s\n", clkdm1->name,
+			 clkdm2->name);
+		return PTR_ERR(cd);
+	}
+
+	pr_debug("clockdomain: will prevent %s from sleeping if %s is active\n",
+		 clkdm1->name, clkdm2->name);
+
+	cm_set_mod_reg_bits((1 << clkdm2->dep_bit),
+			    clkdm1->pwrdm.ptr->prcm_offs,
+			    OMAP3430_CM_SLEEPDEP);
+
+	return 0;
+}
+
+/**
+ * clkdm_del_sleepdep - remove a sleep dependency from clkdm2 to clkdm1
+ * @clkdm1: prevent this struct clockdomain * from sleeping (dependent)
+ * @clkdm2: when this struct clockdomain * is active (source)
+ *
+ * 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.
+ */
+int clkdm_del_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
+{
+	struct clkdm_dep *cd;
+
+	if (!cpu_is_omap34xx())
+		return -EINVAL;
+
+	if (!clkdm1 || !clkdm2)
+		return -EINVAL;
+
+	cd = _clkdm_deps_lookup(clkdm2, clkdm1->sleepdep_srcs);
+	if (IS_ERR(cd)) {
+		pr_debug("clockdomain: hardware cannot set/clear sleep "
+			 "dependency affecting %s from %s\n", clkdm1->name,
+			 clkdm2->name);
+		return PTR_ERR(cd);
+	}
+
+	pr_debug("clockdomain: will no longer prevent %s from sleeping if "
+		 "%s is active\n", clkdm1->name, clkdm2->name);
+
+	cm_clear_mod_reg_bits((1 << clkdm2->dep_bit),
+			      clkdm1->pwrdm.ptr->prcm_offs,
+			      OMAP3430_CM_SLEEPDEP);
+
+	return 0;
+}
+
+/**
+ * clkdm_read_sleepdep - read sleep dependency state from clkdm2 to clkdm1
+ * @clkdm1: prevent this struct clockdomain * from sleeping (dependent)
+ * @clkdm2: when this struct clockdomain * is active (source)
+ *
+ * Return 1 if a hardware sleep dependency exists wherein @clkdm1 will
+ * not be allowed to automatically go inactive if @clkdm2 is active;
+ * 0 if @clkdm1's automatic power state inactivity transition is independent
+ * of @clkdm2's; -EINVAL if either clockdomain pointer is invalid or called
+ * on a machine that does not support software-configurable hardware sleep
+ * dependencies; or -ENOENT if the hardware is incapable.
+ *
+ * REVISIT: Currently this function only represents software-controllable
+ * sleep dependencies.	Sleep dependencies fixed in hardware are not
+ * yet handled here.
+ */
+int clkdm_read_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
+{
+	struct clkdm_dep *cd;
+
+	if (!cpu_is_omap34xx())
+		return -EINVAL;
+
+	if (!clkdm1 || !clkdm2)
+		return -EINVAL;
+
+	cd = _clkdm_deps_lookup(clkdm2, clkdm1->sleepdep_srcs);
+	if (IS_ERR(cd)) {
+		pr_debug("clockdomain: hardware cannot set/clear sleep "
+			 "dependency affecting %s from %s\n", clkdm1->name,
+			 clkdm2->name);
+		return PTR_ERR(cd);
+	}
+
+	return prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs,
+				       OMAP3430_CM_SLEEPDEP,
+				       (1 << clkdm2->dep_bit));
+}
+
+
+/**
  * omap2_clkdm_clktrctrl_read - read the clkdm's current state transition mode
  * @clk: struct clk * of a clockdomain
  *
diff --git a/arch/arm/mach-omap2/clockdomains.h b/arch/arm/mach-omap2/clockdomains.h
index 6dc5ddc..ff216f2 100644
--- a/arch/arm/mach-omap2/clockdomains.h
+++ b/arch/arm/mach-omap2/clockdomains.h
@@ -2,9 +2,28 @@
  * OMAP2/3 clockdomains
  *
  * Copyright (C) 2008 Texas Instruments, Inc.
- * Copyright (C) 2008 Nokia Corporation
+ * Copyright (C) 2008-2009 Nokia Corporation
  *
- * Written by Paul Walmsley
+ * Written by Paul Walmsley and Jouni H?gander
+ *
+ * This file contains clockdomains and clockdomain wakeup/sleep
+ * dependencies for the OMAP2/3 chips.  Some notes:
+ *
+ * A useful validation rule for struct clockdomain: Any clockdomain
+ * referenced by a wkdep_srcs or sleepdep_srcs array must have a
+ * dep_bit assigned.  So wkdep_srcs/sleepdep_srcs are really just
+ * software-controllable dependencies.  Non-software-controllable
+ * dependencies do exist, but they are not encoded below (yet).
+ *
+ * 24xx does not support programmable sleep dependencies (SLEEPDEP)
+ *
+ * The overly-specific dep_bit names are due to a bit name collision
+ * with CM_FCLKEN_{DSP,IVA2}.  The DSP/IVA2 PM_WKDEP and CM_SLEEPDEP shift
+ * value are the same for all powerdomains: 2
+ *
+ * XXX should dep_bit be a mask, so we can test to see if it is 0 as a
+ * sanity check?
+ * XXX encode hardware fixed wakeup dependencies -- esp. for 3430 CORE
  */
 
 /*
@@ -21,6 +40,287 @@
 #include "prm.h"
 
 /*
+ * Clockdomain dependencies for wkdeps/sleepdeps
+ *
+ * XXX Hardware dependencies (e.g., dependencies that cannot be
+ * changed in software) are not included here yet, but should be.
+ */
+
+/* OMAP2/3-common wakeup dependencies */
+
+/*
+ * 2420/2430 PM_WKDEP_GFX: CORE, MPU, WKUP
+ * 3430ES1 PM_WKDEP_GFX: adds IVA2, removes CORE
+ * 3430ES2 PM_WKDEP_SGX: adds IVA2, removes CORE
+ */
+static struct clkdm_dep gfx_sgx_wkdeps[] = {
+	{
+		.clkdm_name = "core_l3_clkdm",
+		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
+	},
+	{
+		.clkdm_name = "core_l4_clkdm",
+		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
+	},
+	{
+		.clkdm_name = "iva2_clkdm",
+		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+	},
+	{
+		.clkdm_name = "mpu_clkdm",
+		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX |
+					    CHIP_IS_OMAP3430)
+	},
+	{
+		.clkdm_name = "wkup_clkdm",
+		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX |
+					    CHIP_IS_OMAP3430)
+	},
+	{ NULL },
+};
+
+
+/* 24XX-specific possible dependencies */
+
+#ifdef CONFIG_ARCH_OMAP24XX
+
+/* Wakeup dependency source arrays */
+
+/*
+ * 2420/2430 PM_WKDEP_DSP: CORE, MPU, WKUP
+ * 2420/2430 PM_WKDEP_MDM: same as DSP
+ */
+static struct clkdm_dep dsp_mdm_24xx_wkdeps[] = {
+	{
+		.clkdm_name = "core_l3_clkdm",
+		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
+	},
+	{
+		.clkdm_name = "core_l4_clkdm",
+		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
+	},
+	{
+		.clkdm_name = "mpu_clkdm",
+		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
+	},
+	{
+		.clkdm_name = "wkup_clkdm",
+		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
+	},
+	{ NULL },
+};
+
+/*
+ * 2420 PM_WKDEP_MPU: CORE, DSP, WKUP
+ * 2430 adds MDM
+ */
+static struct clkdm_dep mpu_24xx_wkdeps[] = {
+	{
+		.clkdm_name = "core_l3_clkdm",
+		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
+	},
+	{
+		.clkdm_name = "core_l4_clkdm",
+		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
+	},
+	{
+		.clkdm_name = "dsp_clkdm",
+		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
+	},
+	{
+		.clkdm_name = "wkup_clkdm",
+		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
+	},
+	{
+		.clkdm_name = "mdm_clkdm",
+		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
+	},
+	{ NULL },
+};
+
+/*
+ * 2420 PM_WKDEP_CORE: DSP, GFX, MPU, WKUP
+ * 2430 adds MDM
+ */
+static struct clkdm_dep core_24xx_wkdeps[] = {
+	{
+		.clkdm_name = "dsp_clkdm",
+		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
+	},
+	{
+		.clkdm_name = "gfx_clkdm",
+		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
+	},
+	{
+		.clkdm_name = "mpu_clkdm",
+		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
+	},
+	{
+		.clkdm_name = "wkup_clkdm",
+		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
+	},
+	{
+		.clkdm_name = "mdm_clkdm",
+		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
+	},
+	{ NULL },
+};
+
+#endif
+
+/* 34XX-specific possible dependencies */
+
+#ifdef CONFIG_ARCH_OMAP34XX
+
+/*
+ * 3430: PM_WKDEP_{PER,USBHOST}: CORE, IVA2, MPU, WKUP
+ * (USBHOST is ES2 only)
+ */
+static struct clkdm_dep per_usbhost_wkdeps[] = {
+	{
+		.clkdm_name = "core_l3_clkdm",
+		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+	},
+	{
+		.clkdm_name = "core_l4_clkdm",
+		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+	},
+	{
+		.clkdm_name = "iva2_clkdm",
+		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+	},
+	{
+		.clkdm_name = "mpu_clkdm",
+		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+	},
+	{
+		.clkdm_name = "wkup_clkdm",
+		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+	},
+	{ NULL },
+};
+
+/*
+ * 3430 PM_WKDEP_MPU: CORE, IVA2, DSS, PER
+ */
+static struct clkdm_dep mpu_34xx_wkdeps[] = {
+	{
+		.clkdm_name = "core_l3_clkdm",
+		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+	},
+	{
+		.clkdm_name = "core_l4_clkdm",
+		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+	},
+	{
+		.clkdm_name = "iva2_clkdm",
+		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+	},
+	{
+		.clkdm_name = "dss_clkdm",
+		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+	},
+	{
+		.clkdm_name = "per_clkdm",
+		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+	},
+	{ NULL },
+};
+
+/*
+ * 3430 PM_WKDEP_IVA2: CORE, MPU, WKUP, DSS, PER
+ */
+static struct clkdm_dep iva2_wkdeps[] = {
+	{
+		.clkdm_name = "core_l3_clkdm",
+		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+	},
+	{
+		.clkdm_name = "core_l4_clkdm",
+		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+	},
+	{
+		.clkdm_name = "mpu_clkdm",
+		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+	},
+	{
+		.clkdm_name = "wkup_clkdm",
+		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+	},
+	{
+		.clkdm_name = "dss_clkdm",
+		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+	},
+	{
+		.clkdm_name = "per_clkdm",
+		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+	},
+	{ NULL },
+};
+
+
+/* 3430 PM_WKDEP_{CAM,DSS}: IVA2, MPU, WKUP */
+static struct clkdm_dep cam_dss_wkdeps[] = {
+	{
+		.clkdm_name = "iva2_clkdm",
+		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+	},
+	{
+		.clkdm_name = "mpu_clkdm",
+		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+	},
+	{
+		.clkdm_name = "wkup_clkdm",
+		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+	},
+	{ NULL },
+};
+
+/* 3430: PM_WKDEP_NEON: MPU */
+static struct clkdm_dep neon_wkdeps[] = {
+	{
+		.clkdm_name = "mpu_clkdm",
+		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+	},
+	{ NULL },
+};
+
+
+/* Sleep dependency source arrays for 34xx-specific clkdms - 34XX only */
+
+/*
+ * 3430: CM_SLEEPDEP_{DSS,PER}: MPU, IVA
+ * 3430ES2: CM_SLEEPDEP_USBHOST: MPU, IVA
+ */
+static struct clkdm_dep dss_per_usbhost_sleepdeps[] = {
+	{
+		.clkdm_name = "mpu_clkdm",
+		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+	},
+	{
+		.clkdm_name = "iva2_clkdm",
+		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+	},
+	{ NULL },
+};
+
+/*
+ * 3430: CM_SLEEPDEP_CAM: MPU
+ * 3430ES1: CM_SLEEPDEP_GFX: MPU
+ * 3430ES2: CM_SLEEPDEP_SGX: MPU
+ */
+static struct clkdm_dep cam_gfx_sleepdeps[] = {
+	{
+		.clkdm_name = "mpu_clkdm",
+		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+	},
+	{ NULL },
+};
+
+#endif /* CONFIG_ARCH_OMAP34XX */
+
+
+/*
  * OMAP2/3-common clockdomains
  *
  * Even though the 2420 has a single PRCM module from the
@@ -35,6 +335,7 @@
 static struct clockdomain wkup_clkdm = {
 	.name		= "wkup_clkdm",
 	.pwrdm		= { .name = "wkup_pwrdm" },
+	.dep_bit	= OMAP_EN_WKUP_SHIFT,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP24XX | CHIP_IS_OMAP3430),
 };
 
@@ -63,6 +364,7 @@ static struct clockdomain mpu_2420_clkdm = {
 	.pwrdm		= { .name = "mpu_pwrdm" },
 	.flags		= CLKDM_CAN_HWSUP,
 	.clkstctrl_reg  = OMAP2420_CM_REGADDR(MPU_MOD, OMAP2_CM_CLKSTCTRL),
+	.wkdep_srcs	= mpu_24xx_wkdeps,
 	.clktrctrl_mask = OMAP24XX_AUTOSTATE_MPU_MASK,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 };
@@ -73,6 +375,8 @@ static struct clockdomain iva1_2420_clkdm = {
 	.flags		= CLKDM_CAN_HWSUP_SWSUP,
 	.clkstctrl_reg  = OMAP2420_CM_REGADDR(OMAP24XX_DSP_MOD,
 						 OMAP2_CM_CLKSTCTRL),
+	.dep_bit	= OMAP24XX_PM_WKDEP_MPU_EN_DSP_SHIFT,
+	.wkdep_srcs	= dsp_mdm_24xx_wkdeps,
 	.clktrctrl_mask = OMAP2420_AUTOSTATE_IVA_MASK,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 };
@@ -92,6 +396,7 @@ static struct clockdomain gfx_2420_clkdm = {
 	.pwrdm		= { .name = "gfx_pwrdm" },
 	.flags		= CLKDM_CAN_HWSUP_SWSUP,
 	.clkstctrl_reg  = OMAP2420_CM_REGADDR(GFX_MOD, OMAP2_CM_CLKSTCTRL),
+	.wkdep_srcs	= gfx_sgx_wkdeps,
 	.clktrctrl_mask = OMAP24XX_AUTOSTATE_GFX_MASK,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 };
@@ -101,6 +406,7 @@ static struct clockdomain core_l3_2420_clkdm = {
 	.pwrdm		= { .name = "core_pwrdm" },
 	.flags		= CLKDM_CAN_HWSUP,
 	.clkstctrl_reg  = OMAP2420_CM_REGADDR(CORE_MOD, OMAP2_CM_CLKSTCTRL),
+	.wkdep_srcs	= core_24xx_wkdeps,
 	.clktrctrl_mask = OMAP24XX_AUTOSTATE_L3_MASK,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 };
@@ -110,6 +416,7 @@ static struct clockdomain core_l4_2420_clkdm = {
 	.pwrdm		= { .name = "core_pwrdm" },
 	.flags		= CLKDM_CAN_HWSUP,
 	.clkstctrl_reg  = OMAP2420_CM_REGADDR(CORE_MOD, OMAP2_CM_CLKSTCTRL),
+	.wkdep_srcs	= core_24xx_wkdeps,
 	.clktrctrl_mask = OMAP24XX_AUTOSTATE_L4_MASK,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 };
@@ -138,16 +445,20 @@ static struct clockdomain mpu_2430_clkdm = {
 	.flags		= CLKDM_CAN_HWSUP_SWSUP,
 	.clkstctrl_reg  = OMAP2430_CM_REGADDR(MPU_MOD,
 						 OMAP2_CM_CLKSTCTRL),
+	.wkdep_srcs	= mpu_24xx_wkdeps,
 	.clktrctrl_mask = OMAP24XX_AUTOSTATE_MPU_MASK,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
+/* Another case of bit name collisions between several registers: EN_MDM */
 static struct clockdomain mdm_clkdm = {
 	.name		= "mdm_clkdm",
 	.pwrdm		= { .name = "mdm_pwrdm" },
 	.flags		= CLKDM_CAN_HWSUP_SWSUP,
 	.clkstctrl_reg  = OMAP2430_CM_REGADDR(OMAP2430_MDM_MOD,
 						 OMAP2_CM_CLKSTCTRL),
+	.dep_bit	= OMAP2430_PM_WKDEP_MPU_EN_MDM_SHIFT,
+	.wkdep_srcs	= dsp_mdm_24xx_wkdeps,
 	.clktrctrl_mask = OMAP2430_AUTOSTATE_MDM_MASK,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
@@ -158,6 +469,8 @@ static struct clockdomain dsp_2430_clkdm = {
 	.flags		= CLKDM_CAN_HWSUP_SWSUP,
 	.clkstctrl_reg  = OMAP2430_CM_REGADDR(OMAP24XX_DSP_MOD,
 						 OMAP2_CM_CLKSTCTRL),
+	.dep_bit	= OMAP24XX_PM_WKDEP_MPU_EN_DSP_SHIFT,
+	.wkdep_srcs	= dsp_mdm_24xx_wkdeps,
 	.clktrctrl_mask = OMAP24XX_AUTOSTATE_DSP_MASK,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
@@ -167,24 +480,39 @@ static struct clockdomain gfx_2430_clkdm = {
 	.pwrdm		= { .name = "gfx_pwrdm" },
 	.flags		= CLKDM_CAN_HWSUP_SWSUP,
 	.clkstctrl_reg  = OMAP2430_CM_REGADDR(GFX_MOD, OMAP2_CM_CLKSTCTRL),
+	.wkdep_srcs	= gfx_sgx_wkdeps,
 	.clktrctrl_mask = OMAP24XX_AUTOSTATE_GFX_MASK,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
+/*
+ * XXX add usecounting for clkdm dependencies, otherwise the presence
+ * of a single dep bit for core_l3_24xx_clkdm and core_l4_24xx_clkdm
+ * could cause trouble
+ */
 static struct clockdomain core_l3_2430_clkdm = {
 	.name		= "core_l3_clkdm",
 	.pwrdm		= { .name = "core_pwrdm" },
 	.flags		= CLKDM_CAN_HWSUP,
 	.clkstctrl_reg  = OMAP2430_CM_REGADDR(CORE_MOD, OMAP2_CM_CLKSTCTRL),
+	.dep_bit	= OMAP24XX_EN_CORE_SHIFT,
+	.wkdep_srcs	= core_24xx_wkdeps,
 	.clktrctrl_mask = OMAP24XX_AUTOSTATE_L3_MASK,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
+/*
+ * XXX add usecounting for clkdm dependencies, otherwise the presence
+ * of a single dep bit for core_l3_24xx_clkdm and core_l4_24xx_clkdm
+ * could cause trouble
+ */
 static struct clockdomain core_l4_2430_clkdm = {
 	.name		= "core_l4_clkdm",
 	.pwrdm		= { .name = "core_pwrdm" },
 	.flags		= CLKDM_CAN_HWSUP,
 	.clkstctrl_reg  = OMAP2430_CM_REGADDR(CORE_MOD, OMAP2_CM_CLKSTCTRL),
+	.dep_bit	= OMAP24XX_EN_CORE_SHIFT,
+	.wkdep_srcs	= core_24xx_wkdeps,
 	.clktrctrl_mask = OMAP24XX_AUTOSTATE_L4_MASK,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
@@ -212,6 +540,8 @@ static struct clockdomain mpu_34xx_clkdm = {
 	.pwrdm		= { .name = "mpu_pwrdm" },
 	.flags		= CLKDM_CAN_HWSUP | CLKDM_CAN_FORCE_WAKEUP,
 	.clkstctrl_reg	= OMAP34XX_CM_REGADDR(MPU_MOD, OMAP2_CM_CLKSTCTRL),
+	.dep_bit	= OMAP3430_EN_MPU_SHIFT,
+	.wkdep_srcs	= mpu_34xx_wkdeps,
 	.clktrctrl_mask = OMAP3430_CLKTRCTRL_MPU_MASK,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
@@ -222,6 +552,7 @@ static struct clockdomain neon_clkdm = {
 	.flags		= CLKDM_CAN_HWSUP_SWSUP,
 	.clkstctrl_reg	= OMAP34XX_CM_REGADDR(OMAP3430_NEON_MOD,
 						 OMAP2_CM_CLKSTCTRL),
+	.wkdep_srcs	= neon_wkdeps,
 	.clktrctrl_mask = OMAP3430_CLKTRCTRL_NEON_MASK,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
@@ -232,6 +563,8 @@ static struct clockdomain iva2_clkdm = {
 	.flags		= CLKDM_CAN_HWSUP_SWSUP,
 	.clkstctrl_reg	= OMAP34XX_CM_REGADDR(OMAP3430_IVA2_MOD,
 						 OMAP2_CM_CLKSTCTRL),
+	.dep_bit	= OMAP3430_PM_WKDEP_MPU_EN_IVA2_SHIFT,
+	.wkdep_srcs	= iva2_wkdeps,
 	.clktrctrl_mask = OMAP3430_CLKTRCTRL_IVA2_MASK,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
@@ -241,6 +574,8 @@ static struct clockdomain gfx_3430es1_clkdm = {
 	.pwrdm		= { .name = "gfx_pwrdm" },
 	.flags		= CLKDM_CAN_HWSUP_SWSUP,
 	.clkstctrl_reg	= OMAP34XX_CM_REGADDR(GFX_MOD, OMAP2_CM_CLKSTCTRL),
+	.wkdep_srcs	= gfx_sgx_wkdeps,
+	.sleepdep_srcs	= cam_gfx_sleepdeps,
 	.clktrctrl_mask = OMAP3430ES1_CLKTRCTRL_GFX_MASK,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1),
 };
@@ -251,6 +586,8 @@ static struct clockdomain sgx_clkdm = {
 	.flags		= CLKDM_CAN_HWSUP_SWSUP,
 	.clkstctrl_reg	= OMAP34XX_CM_REGADDR(OMAP3430ES2_SGX_MOD,
 						 OMAP2_CM_CLKSTCTRL),
+	.wkdep_srcs	= gfx_sgx_wkdeps,
+	.sleepdep_srcs	= cam_gfx_sleepdeps,
 	.clktrctrl_mask = OMAP3430ES2_CLKTRCTRL_SGX_MASK,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2),
 };
@@ -271,30 +608,46 @@ static struct clockdomain d2d_clkdm = {
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
+/*
+ * XXX add usecounting for clkdm dependencies, otherwise the presence
+ * of a single dep bit for core_l3_34xx_clkdm and core_l4_34xx_clkdm
+ * could cause trouble
+ */
 static struct clockdomain core_l3_34xx_clkdm = {
 	.name		= "core_l3_clkdm",
 	.pwrdm		= { .name = "core_pwrdm" },
 	.flags		= CLKDM_CAN_HWSUP,
 	.clkstctrl_reg	= OMAP34XX_CM_REGADDR(CORE_MOD, OMAP2_CM_CLKSTCTRL),
+	.dep_bit	= OMAP3430_EN_CORE_SHIFT,
 	.clktrctrl_mask = OMAP3430_CLKTRCTRL_L3_MASK,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
+/*
+ * XXX add usecounting for clkdm dependencies, otherwise the presence
+ * of a single dep bit for core_l3_34xx_clkdm and core_l4_34xx_clkdm
+ * could cause trouble
+ */
 static struct clockdomain core_l4_34xx_clkdm = {
 	.name		= "core_l4_clkdm",
 	.pwrdm		= { .name = "core_pwrdm" },
 	.flags		= CLKDM_CAN_HWSUP,
 	.clkstctrl_reg	= OMAP34XX_CM_REGADDR(CORE_MOD, OMAP2_CM_CLKSTCTRL),
+	.dep_bit	= OMAP3430_EN_CORE_SHIFT,
 	.clktrctrl_mask = OMAP3430_CLKTRCTRL_L4_MASK,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
+/* Another case of bit name collisions between several registers: EN_DSS */
 static struct clockdomain dss_34xx_clkdm = {
 	.name		= "dss_clkdm",
 	.pwrdm		= { .name = "dss_pwrdm" },
 	.flags		= CLKDM_CAN_HWSUP_SWSUP,
 	.clkstctrl_reg	= OMAP34XX_CM_REGADDR(OMAP3430_DSS_MOD,
 						 OMAP2_CM_CLKSTCTRL),
+	.dep_bit	= OMAP3430_PM_WKDEP_MPU_EN_DSS_SHIFT,
+	.wkdep_srcs	= cam_dss_wkdeps,
+	.sleepdep_srcs	= dss_per_usbhost_sleepdeps,
 	.clktrctrl_mask = OMAP3430_CLKTRCTRL_DSS_MASK,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
@@ -305,6 +658,8 @@ static struct clockdomain cam_clkdm = {
 	.flags		= CLKDM_CAN_HWSUP_SWSUP,
 	.clkstctrl_reg	= OMAP34XX_CM_REGADDR(OMAP3430_CAM_MOD,
 						 OMAP2_CM_CLKSTCTRL),
+	.wkdep_srcs	= cam_dss_wkdeps,
+	.sleepdep_srcs	= cam_gfx_sleepdeps,
 	.clktrctrl_mask = OMAP3430_CLKTRCTRL_CAM_MASK,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
@@ -315,6 +670,8 @@ static struct clockdomain usbhost_clkdm = {
 	.flags		= CLKDM_CAN_HWSUP_SWSUP,
 	.clkstctrl_reg	= OMAP34XX_CM_REGADDR(OMAP3430ES2_USBHOST_MOD,
 						 OMAP2_CM_CLKSTCTRL),
+	.wkdep_srcs	= per_usbhost_wkdeps,
+	.sleepdep_srcs	= dss_per_usbhost_sleepdeps,
 	.clktrctrl_mask = OMAP3430ES2_CLKTRCTRL_USBHOST_MASK,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2),
 };
@@ -325,6 +682,9 @@ static struct clockdomain per_clkdm = {
 	.flags		= CLKDM_CAN_HWSUP_SWSUP,
 	.clkstctrl_reg	= OMAP34XX_CM_REGADDR(OMAP3430_PER_MOD,
 						 OMAP2_CM_CLKSTCTRL),
+	.dep_bit	= OMAP3430_EN_PER_SHIFT,
+	.wkdep_srcs	= per_usbhost_wkdeps,
+	.sleepdep_srcs	= dss_per_usbhost_sleepdeps,
 	.clktrctrl_mask = OMAP3430_CLKTRCTRL_PER_MASK,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
@@ -378,25 +738,21 @@ static struct clockdomain dpll5_clkdm = {
 #include "clockdomains44xx.h"
 
 /*
- * Clockdomain-powerdomain hwsup dependencies (34XX only)
+ * Clockdomain hwsup dependencies (34XX only)
  */
 
-static struct clkdm_pwrdm_autodep clkdm_pwrdm_autodeps[] = {
-
-#ifdef CONFIG_ARCH_OMAP34XX
+static struct clkdm_autodep clkdm_autodeps[] = {
 	{
-		.pwrdm	   = { .name = "mpu_pwrdm" },
+		.clkdm	   = { .name = "mpu_clkdm" },
 		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 	},
 	{
-		.pwrdm	   = { .name = "iva2_pwrdm" },
+		.clkdm	   = { .name = "iva2_clkdm" },
 		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 	},
 	{
-		.pwrdm	   = { .name = NULL },
+		.clkdm	   = { .name = NULL },
 	}
-#endif
-
 };
 
 /*
diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
index 51d7453..8c58699 100644
--- a/arch/arm/mach-omap2/io.c
+++ b/arch/arm/mach-omap2/io.c
@@ -313,7 +313,7 @@ void __init omap2_init_common_hw(struct omap_sdrc_params *sdrc_cs0,
 		hwmods = omap34xx_hwmods;
 
 	pwrdm_init(powerdomains_omap);
-	clkdm_init(clockdomains_omap, clkdm_pwrdm_autodeps);
+	clkdm_init(clockdomains_omap, clkdm_autodeps);
 #ifndef CONFIG_ARCH_OMAP4 /* FIXME: Remove this once the clkdev is ready */
 	/* The OPP tables have to be registered before a clk init */
 	omap_hwmod_init(hwmods);
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index d8c8545..88d91de 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -298,15 +298,14 @@ static int _disable_wakeup(struct omap_hwmod *oh)
  * be accessed by the IVA, there should be a sleepdep between the IVA
  * initiator and the module).  Only applies to modules in smart-idle
  * mode.  Returns -EINVAL upon error or passes along
- * pwrdm_add_sleepdep() value upon success.
+ * clkdm_add_sleepdep() value upon success.
  */
 static int _add_initiator_dep(struct omap_hwmod *oh, struct omap_hwmod *init_oh)
 {
 	if (!oh->_clk)
 		return -EINVAL;
 
-	return pwrdm_add_sleepdep(oh->_clk->clkdm->pwrdm.ptr,
-				  init_oh->_clk->clkdm->pwrdm.ptr);
+	return clkdm_add_sleepdep(oh->_clk->clkdm, init_oh->_clk->clkdm);
 }
 
 /**
@@ -319,15 +318,14 @@ static int _add_initiator_dep(struct omap_hwmod *oh, struct omap_hwmod *init_oh)
  * be accessed by the IVA, there should be no sleepdep between the IVA
  * initiator and the module).  Only applies to modules in smart-idle
  * mode.  Returns -EINVAL upon error or passes along
- * pwrdm_add_sleepdep() value upon success.
+ * clkdm_del_sleepdep() value upon success.
  */
 static int _del_initiator_dep(struct omap_hwmod *oh, struct omap_hwmod *init_oh)
 {
 	if (!oh->_clk)
 		return -EINVAL;
 
-	return pwrdm_del_sleepdep(oh->_clk->clkdm->pwrdm.ptr,
-				  init_oh->_clk->clkdm->pwrdm.ptr);
+	return clkdm_del_sleepdep(oh->_clk->clkdm, init_oh->_clk->clkdm);
 }
 
 /**
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 3189acc..ab110b4 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -1013,6 +1013,7 @@ void omap_push_sram_idle(void)
 static int __init omap3_pm_init(void)
 {
 	struct power_state *pwrst, *tmp;
+	struct clockdomain *neon_clkdm, *per_clkdm, *mpu_clkdm, *core_clkdm;
 	int ret;
 
 	if (!cpu_is_omap34xx())
@@ -1052,6 +1053,11 @@ static int __init omap3_pm_init(void)
 	core_pwrdm = pwrdm_lookup("core_pwrdm");
 	cam_pwrdm = pwrdm_lookup("cam_pwrdm");
 
+	neon_clkdm = clkdm_lookup("neon_clkdm");
+	mpu_clkdm = clkdm_lookup("mpu_clkdm");
+	per_clkdm = clkdm_lookup("per_clkdm");
+	core_clkdm = clkdm_lookup("core_clkdm");
+
 	omap_push_sram_idle();
 #ifdef CONFIG_SUSPEND
 	suspend_set_ops(&omap_pm_ops);
@@ -1060,14 +1066,14 @@ static int __init omap3_pm_init(void)
 	pm_idle = omap3_pm_idle;
 	omap3_idle_init();
 
-	pwrdm_add_wkdep(neon_pwrdm, mpu_pwrdm);
+	clkdm_add_wkdep(neon_clkdm, mpu_clkdm);
 	/*
 	 * REVISIT: This wkdep is only necessary when GPIO2-6 are enabled for
 	 * IO-pad wakeup.  Otherwise it will unnecessarily waste power
 	 * waking up PER with every CORE wakeup - see
 	 * http://marc.info/?l=linux-omap&m=121852150710062&w=2
 	*/
-	pwrdm_add_wkdep(per_pwrdm, core_pwrdm);
+	clkdm_add_wkdep(per_clkdm, core_clkdm);
 
 	if (omap_type() != OMAP2_DEVICE_TYPE_GP) {
 		omap3_secure_ram_storage =
diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
index c0de050..e8e8d88 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -2,7 +2,7 @@
  * OMAP powerdomain control
  *
  * Copyright (C) 2007-2008 Texas Instruments, Inc.
- * Copyright (C) 2007-2008 Nokia Corporation
+ * Copyright (C) 2007-2009 Nokia Corporation
  *
  * Written by Paul Walmsley
  *
@@ -36,6 +36,7 @@
 #include <plat/cpu.h>
 #include <plat/powerdomain.h>
 #include <plat/clockdomain.h>
+#include <plat/prcm.h>
 
 #include "pm.h"
 
@@ -88,17 +89,6 @@ static DEFINE_RWLOCK(pwrdm_rwlock);
 
 /* Private functions */
 
-static u32 prm_read_mod_bits_shift(s16 domain, s16 idx, u32 mask)
-{
-	u32 v;
-
-	v = prm_read_mod_reg(domain, idx);
-	v &= mask;
-	v >>= __ffs(mask);
-
-	return v;
-}
-
 static struct powerdomain *_pwrdm_lookup(const char *name)
 {
 	struct powerdomain *pwrdm, *temp_pwrdm;
@@ -115,34 +105,6 @@ static struct powerdomain *_pwrdm_lookup(const char *name)
 	return pwrdm;
 }
 
-/* _pwrdm_deps_lookup - look up the specified powerdomain in a pwrdm list */
-static struct powerdomain *_pwrdm_deps_lookup(struct powerdomain *pwrdm,
-					      struct pwrdm_dep *deps)
-{
-	struct pwrdm_dep *pd;
-
-	if (!pwrdm || !deps || !omap_chip_is(pwrdm->omap_chip))
-		return ERR_PTR(-EINVAL);
-
-	for (pd = deps; pd->pwrdm_name; pd++) {
-
-		if (!omap_chip_is(pd->omap_chip))
-			continue;
-
-		if (!pd->pwrdm && pd->pwrdm_name)
-			pd->pwrdm = pwrdm_lookup(pd->pwrdm_name);
-
-		if (pd->pwrdm == pwrdm)
-			break;
-
-	}
-
-	if (!pd->pwrdm_name)
-		return ERR_PTR(-ENOENT);
-
-	return pd->pwrdm;
-}
-
 static int _pwrdm_state_switch(struct powerdomain *pwrdm, int flag)
 {
 
@@ -502,223 +464,6 @@ int pwrdm_for_each_clkdm(struct powerdomain *pwrdm,
 	return ret;
 }
 
-
-/**
- * pwrdm_add_wkdep - add a wakeup dependency from pwrdm2 to pwrdm1
- * @pwrdm1: wake this struct powerdomain * up (dependent)
- * @pwrdm2: when this struct powerdomain * wakes up (source)
- *
- * When the powerdomain represented by pwrdm2 wakes up (due to an
- * interrupt), wake up pwrdm1.	Implemented in hardware on the OMAP,
- * this feature is designed to reduce wakeup latency of the dependent
- * powerdomain.  Returns -EINVAL if presented with invalid powerdomain
- * pointers, -ENOENT if pwrdm2 cannot wake up pwrdm1 in hardware, or
- * 0 upon success.
- */
-int pwrdm_add_wkdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2)
-{
-	struct powerdomain *p;
-
-	if (!pwrdm1)
-		return -EINVAL;
-
-	p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->wkdep_srcs);
-	if (IS_ERR(p)) {
-		pr_debug("powerdomain: hardware cannot set/clear wake up of "
-			 "%s when %s wakes up\n", pwrdm1->name, pwrdm2->name);
-		return PTR_ERR(p);
-	}
-
-	pr_debug("powerdomain: hardware will wake up %s when %s wakes up\n",
-		 pwrdm1->name, pwrdm2->name);
-
-	prm_set_mod_reg_bits((1 << pwrdm2->dep_bit),
-			     pwrdm1->prcm_offs, PM_WKDEP);
-
-	return 0;
-}
-
-/**
- * pwrdm_del_wkdep - remove a wakeup dependency from pwrdm2 to pwrdm1
- * @pwrdm1: wake this struct powerdomain * up (dependent)
- * @pwrdm2: when this struct powerdomain * wakes up (source)
- *
- * Remove a wakeup dependency that causes pwrdm1 to wake up when pwrdm2
- * wakes up.  Returns -EINVAL if presented with invalid powerdomain
- * pointers, -ENOENT if pwrdm2 cannot wake up pwrdm1 in hardware, or
- * 0 upon success.
- */
-int pwrdm_del_wkdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2)
-{
-	struct powerdomain *p;
-
-	if (!pwrdm1)
-		return -EINVAL;
-
-	p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->wkdep_srcs);
-	if (IS_ERR(p)) {
-		pr_debug("powerdomain: hardware cannot set/clear wake up of "
-			 "%s when %s wakes up\n", pwrdm1->name, pwrdm2->name);
-		return PTR_ERR(p);
-	}
-
-	pr_debug("powerdomain: hardware will no longer wake up %s after %s "
-		 "wakes up\n", pwrdm1->name, pwrdm2->name);
-
-	prm_clear_mod_reg_bits((1 << pwrdm2->dep_bit),
-			       pwrdm1->prcm_offs, PM_WKDEP);
-
-	return 0;
-}
-
-/**
- * pwrdm_read_wkdep - read wakeup dependency state from pwrdm2 to pwrdm1
- * @pwrdm1: wake this struct powerdomain * up (dependent)
- * @pwrdm2: when this struct powerdomain * wakes up (source)
- *
- * Return 1 if a hardware wakeup dependency exists wherein pwrdm1 will be
- * awoken when pwrdm2 wakes up; 0 if dependency is not set; -EINVAL
- * if either powerdomain pointer is invalid; or -ENOENT if the hardware
- * is incapable.
- *
- * REVISIT: Currently this function only represents software-controllable
- * wakeup dependencies.  Wakeup dependencies fixed in hardware are not
- * yet handled here.
- */
-int pwrdm_read_wkdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2)
-{
-	struct powerdomain *p;
-
-	if (!pwrdm1)
-		return -EINVAL;
-
-	p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->wkdep_srcs);
-	if (IS_ERR(p)) {
-		pr_debug("powerdomain: hardware cannot set/clear wake up of "
-			 "%s when %s wakes up\n", pwrdm1->name, pwrdm2->name);
-		return PTR_ERR(p);
-	}
-
-	return prm_read_mod_bits_shift(pwrdm1->prcm_offs, PM_WKDEP,
-					(1 << pwrdm2->dep_bit));
-}
-
-/**
- * pwrdm_add_sleepdep - add a sleep dependency from pwrdm2 to pwrdm1
- * @pwrdm1: prevent this struct powerdomain * from sleeping (dependent)
- * @pwrdm2: when this struct powerdomain * is active (source)
- *
- * Prevent pwrdm1 from automatically going inactive (and then to
- * retention or off) if pwrdm2 is still active.	 Returns -EINVAL if
- * presented with invalid powerdomain 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.
- */
-int pwrdm_add_sleepdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2)
-{
-	struct powerdomain *p;
-
-	if (!cpu_is_omap34xx())
-		return -EINVAL;
-
-	if (!pwrdm1)
-		return -EINVAL;
-
-	p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->sleepdep_srcs);
-	if (IS_ERR(p)) {
-		pr_debug("powerdomain: hardware cannot set/clear sleep "
-			 "dependency affecting %s from %s\n", pwrdm1->name,
-			 pwrdm2->name);
-		return PTR_ERR(p);
-	}
-
-	pr_debug("powerdomain: will prevent %s from sleeping if %s is active\n",
-		 pwrdm1->name, pwrdm2->name);
-
-	cm_set_mod_reg_bits((1 << pwrdm2->dep_bit),
-			    pwrdm1->prcm_offs, OMAP3430_CM_SLEEPDEP);
-
-	return 0;
-}
-
-/**
- * pwrdm_del_sleepdep - remove a sleep dependency from pwrdm2 to pwrdm1
- * @pwrdm1: prevent this struct powerdomain * from sleeping (dependent)
- * @pwrdm2: when this struct powerdomain * is active (source)
- *
- * Allow pwrdm1 to automatically go inactive (and then to retention or
- * off), independent of the activity state of pwrdm2.  Returns -EINVAL
- * if presented with invalid powerdomain 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.
- */
-int pwrdm_del_sleepdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2)
-{
-	struct powerdomain *p;
-
-	if (!cpu_is_omap34xx())
-		return -EINVAL;
-
-	if (!pwrdm1)
-		return -EINVAL;
-
-	p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->sleepdep_srcs);
-	if (IS_ERR(p)) {
-		pr_debug("powerdomain: hardware cannot set/clear sleep "
-			 "dependency affecting %s from %s\n", pwrdm1->name,
-			 pwrdm2->name);
-		return PTR_ERR(p);
-	}
-
-	pr_debug("powerdomain: will no longer prevent %s from sleeping if "
-		 "%s is active\n", pwrdm1->name, pwrdm2->name);
-
-	cm_clear_mod_reg_bits((1 << pwrdm2->dep_bit),
-			      pwrdm1->prcm_offs, OMAP3430_CM_SLEEPDEP);
-
-	return 0;
-}
-
-/**
- * pwrdm_read_sleepdep - read sleep dependency state from pwrdm2 to pwrdm1
- * @pwrdm1: prevent this struct powerdomain * from sleeping (dependent)
- * @pwrdm2: when this struct powerdomain * is active (source)
- *
- * Return 1 if a hardware sleep dependency exists wherein pwrdm1 will
- * not be allowed to automatically go inactive if pwrdm2 is active;
- * 0 if pwrdm1's automatic power state inactivity transition is independent
- * of pwrdm2's; -EINVAL if either powerdomain pointer is invalid or called
- * on a machine that does not support software-configurable hardware sleep
- * dependencies; or -ENOENT if the hardware is incapable.
- *
- * REVISIT: Currently this function only represents software-controllable
- * sleep dependencies.	Sleep dependencies fixed in hardware are not
- * yet handled here.
- */
-int pwrdm_read_sleepdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2)
-{
-	struct powerdomain *p;
-
-	if (!cpu_is_omap34xx())
-		return -EINVAL;
-
-	if (!pwrdm1)
-		return -EINVAL;
-
-	p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->sleepdep_srcs);
-	if (IS_ERR(p)) {
-		pr_debug("powerdomain: hardware cannot set/clear sleep "
-			 "dependency affecting %s from %s\n", pwrdm1->name,
-			 pwrdm2->name);
-		return PTR_ERR(p);
-	}
-
-	return prm_read_mod_bits_shift(pwrdm1->prcm_offs, OMAP3430_CM_SLEEPDEP,
-					(1 << pwrdm2->dep_bit));
-}
-
 /**
  * pwrdm_get_mem_bank_count - get number of memory banks in this powerdomain
  * @pwrdm: struct powerdomain *
diff --git a/arch/arm/mach-omap2/powerdomains.h b/arch/arm/mach-omap2/powerdomains.h
index d646c99..faa8fc9 100644
--- a/arch/arm/mach-omap2/powerdomains.h
+++ b/arch/arm/mach-omap2/powerdomains.h
@@ -1,8 +1,8 @@
 /*
  * OMAP2/3 common powerdomain definitions
  *
- * Copyright (C) 2007-8 Texas Instruments, Inc.
- * Copyright (C) 2007-8 Nokia Corporation
+ * Copyright (C) 2007-2008 Texas Instruments, Inc.
+ * Copyright (C) 2007-2009 Nokia Corporation
  *
  * Written by Paul Walmsley
  * Debugging and integration fixes by Jouni H?gander
@@ -25,19 +25,8 @@
  * This file contains all of the powerdomains that have some element
  * of software control for the OMAP24xx and OMAP34XX chips.
  *
- * A few notes:
- *
  * This is not an exhaustive listing of powerdomains on the chips; only
  * powerdomains that can be controlled in software.
- *
- * A useful validation rule for struct powerdomain:
- * Any powerdomain referenced by a wkdep_srcs or sleepdep_srcs array
- * must have a dep_bit assigned.  So wkdep_srcs/sleepdep_srcs are really
- * just software-controllable dependencies.  Non-software-controllable
- * dependencies do exist, but they are not encoded below (yet).
- *
- * 24xx does not support programmable sleep dependencies (SLEEPDEP)
- *
  */
 
 /*
@@ -47,26 +36,17 @@
  *
  * On the 2420, this is a 'C55 DSP called, simply, the DSP.  Its
  * powerdomain is called the "DSP power domain."  On the 2430, the
- * on-board DSP is a 'C64 DSP, now called the IVA2 or IVA2.1.  Its
- * powerdomain is still called the "DSP power domain."	On the 3430,
- * the DSP is a 'C64 DSP like the 2430, also known as the IVA2; but
- * its powerdomain is now called the "IVA2 power domain."
+ * on-board DSP is a 'C64 DSP, now called (along with its hardware
+ * accelerators) the IVA2 or IVA2.1.  Its powerdomain is still called
+ * the "DSP power domain." On the 3430, the DSP is a 'C64 DSP like the
+ * 2430, also known as the IVA2; but its powerdomain is now called the
+ * "IVA2 power domain."
  *
  * The 2420 also has something called the IVA, which is a separate ARM
  * core, and has nothing to do with the DSP/IVA2.
  *
  * Ideally the DSP/IVA2 could just be the same powerdomain, but the PRCM
  * address offset is different between the C55 and C64 DSPs.
- *
- * The overly-specific dep_bit names are due to a bit name collision
- * with CM_FCLKEN_{DSP,IVA2}.  The DSP/IVA2 PM_WKDEP and CM_SLEEPDEP shift
- * value are the same for all powerdomains: 2
- */
-
-/*
- * XXX should dep_bit be a mask, so we can test to see if it is 0 as a
- * sanity check?
- * XXX encode hardware fixed wakeup dependencies -- esp. for 3430 CORE
  */
 
 #include <plat/powerdomain.h>
@@ -74,60 +54,11 @@
 #include "prcm-common.h"
 #include "prm.h"
 #include "cm.h"
-
-/* OMAP2/3-common powerdomains and wakeup dependencies */
-
-#ifndef CONFIG_ARCH_OMAP4
-/*
- * 2420/2430 PM_WKDEP_GFX: CORE, MPU, WKUP
- * 3430ES1 PM_WKDEP_GFX: adds IVA2, removes CORE
- * 3430ES2 PM_WKDEP_SGX: adds IVA2, removes CORE
- */
-static struct pwrdm_dep gfx_sgx_wkdeps[] = {
-	{
-		.pwrdm_name = "core_pwrdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
-	},
-	{
-		.pwrdm_name = "iva2_pwrdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.pwrdm_name = "mpu_pwrdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX |
-					    CHIP_IS_OMAP3430)
-	},
-	{
-		.pwrdm_name = "wkup_pwrdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX |
-					    CHIP_IS_OMAP3430)
-	},
-	{ NULL },
-};
-
-/*
- * 3430: CM_SLEEPDEP_CAM: MPU
- * 3430ES1: CM_SLEEPDEP_GFX: MPU
- * 3430ES2: CM_SLEEPDEP_SGX: MPU
- */
-static struct pwrdm_dep cam_gfx_sleepdeps[] = {
-	{
-		.pwrdm_name = "mpu_pwrdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{ NULL },
-};
-#endif
-
-
 #include "powerdomains24xx.h"
 #include "powerdomains34xx.h"
 #include "powerdomains44xx.h"
 
-
-/*
- * OMAP2/3 common powerdomains
- */
+/* OMAP2/3-common powerdomains */
 
 #if defined(CONFIG_ARCH_OMAP24XX) | defined(CONFIG_ARCH_OMAP34XX)
 
@@ -140,8 +71,6 @@ static struct powerdomain gfx_omap2_pwrdm = {
 	.prcm_offs	  = GFX_MOD,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX |
 					   CHIP_IS_OMAP3430ES1),
-	.wkdep_srcs	  = gfx_sgx_wkdeps,
-	.sleepdep_srcs	  = cam_gfx_sleepdeps,
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRDM_POWER_RET,
 	.banks		  = 1,
@@ -157,7 +86,6 @@ static struct powerdomain wkup_omap2_pwrdm = {
 	.name		= "wkup_pwrdm",
 	.prcm_offs	= WKUP_MOD,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP24XX | CHIP_IS_OMAP3430),
-	.dep_bit	= OMAP_EN_WKUP_SHIFT,
 };
 
 #endif
diff --git a/arch/arm/mach-omap2/powerdomains24xx.h b/arch/arm/mach-omap2/powerdomains24xx.h
index bd249a4..652a01b 100644
--- a/arch/arm/mach-omap2/powerdomains24xx.h
+++ b/arch/arm/mach-omap2/powerdomains24xx.h
@@ -2,7 +2,7 @@
  * OMAP24XX powerdomain definitions
  *
  * Copyright (C) 2007-2008 Texas Instruments, Inc.
- * Copyright (C) 2007-2008 Nokia Corporation
+ * Copyright (C) 2007-2009 Nokia Corporation
  *
  * Written by Paul Walmsley
  * Debugging and integration fixes by Jouni H?gander
@@ -32,90 +32,12 @@
 
 #ifdef CONFIG_ARCH_OMAP24XX
 
-
-/* Wakeup dependency source arrays */
-
-/*
- * 2420/2430 PM_WKDEP_DSP: CORE, MPU, WKUP
- * 2430 PM_WKDEP_MDM: same as above
- */
-static struct pwrdm_dep dsp_mdm_24xx_wkdeps[] = {
-	{
-		.pwrdm_name = "core_pwrdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
-	},
-	{
-		.pwrdm_name = "mpu_pwrdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
-	},
-	{
-		.pwrdm_name = "wkup_pwrdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
-	},
-	{ NULL },
-};
-
-/*
- * 2420 PM_WKDEP_MPU: CORE, DSP, WKUP
- * 2430 adds MDM
- */
-static struct pwrdm_dep mpu_24xx_wkdeps[] = {
-	{
-		.pwrdm_name = "core_pwrdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
-	},
-	{
-		.pwrdm_name = "dsp_pwrdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
-	},
-	{
-		.pwrdm_name = "wkup_pwrdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
-	},
-	{
-		.pwrdm_name = "mdm_pwrdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
-	},
-	{ NULL },
-};
-
-/*
- * 2420 PM_WKDEP_CORE: DSP, GFX, MPU, WKUP
- * 2430 adds MDM
- */
-static struct pwrdm_dep core_24xx_wkdeps[] = {
-	{
-		.pwrdm_name = "dsp_pwrdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
-	},
-	{
-		.pwrdm_name = "gfx_pwrdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
-	},
-	{
-		.pwrdm_name = "mpu_pwrdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
-	},
-	{
-		.pwrdm_name = "wkup_pwrdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
-	},
-	{
-		.pwrdm_name = "mdm_pwrdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
-	},
-	{ NULL },
-};
-
-
 /* Powerdomains */
 
 static struct powerdomain dsp_pwrdm = {
 	.name		  = "dsp_pwrdm",
 	.prcm_offs	  = OMAP24XX_DSP_MOD,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX),
-	.dep_bit	  = OMAP24XX_PM_WKDEP_MPU_EN_DSP_SHIFT,
-	.wkdep_srcs	  = dsp_mdm_24xx_wkdeps,
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRDM_POWER_RET,
 	.banks		  = 1,
@@ -131,8 +53,6 @@ static struct powerdomain mpu_24xx_pwrdm = {
 	.name		  = "mpu_pwrdm",
 	.prcm_offs	  = MPU_MOD,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX),
-	.dep_bit	  = OMAP24XX_EN_MPU_SHIFT,
-	.wkdep_srcs	  = mpu_24xx_wkdeps,
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_OFF_RET,
 	.banks		  = 1,
@@ -148,9 +68,7 @@ static struct powerdomain core_24xx_pwrdm = {
 	.name		  = "core_pwrdm",
 	.prcm_offs	  = CORE_MOD,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX),
-	.wkdep_srcs	  = core_24xx_wkdeps,
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
-	.dep_bit	  = OMAP24XX_EN_CORE_SHIFT,
 	.banks		  = 3,
 	.pwrsts_mem_ret	  = {
 		[0] = PWRSTS_OFF_RET,	 /* MEM1RETSTATE */
@@ -176,13 +94,10 @@ static struct powerdomain core_24xx_pwrdm = {
 
 /* XXX 2430 KILLDOMAINWKUP bit?  No current users apparently */
 
-/* Another case of bit name collisions between several registers: EN_MDM */
 static struct powerdomain mdm_pwrdm = {
 	.name		  = "mdm_pwrdm",
 	.prcm_offs	  = OMAP2430_MDM_MOD,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
-	.dep_bit	  = OMAP2430_PM_WKDEP_MPU_EN_MDM_SHIFT,
-	.wkdep_srcs	  = dsp_mdm_24xx_wkdeps,
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRDM_POWER_RET,
 	.banks		  = 1,
diff --git a/arch/arm/mach-omap2/powerdomains34xx.h b/arch/arm/mach-omap2/powerdomains34xx.h
index 588f7e0..28228ef 100644
--- a/arch/arm/mach-omap2/powerdomains34xx.h
+++ b/arch/arm/mach-omap2/powerdomains34xx.h
@@ -2,7 +2,7 @@
  * OMAP34XX powerdomain definitions
  *
  * Copyright (C) 2007-2008 Texas Instruments, Inc.
- * Copyright (C) 2007-2008 Nokia Corporation
+ * Copyright (C) 2007-2009 Nokia Corporation
  *
  * Written by Paul Walmsley
  * Debugging and integration fixes by Jouni H?gander
@@ -35,127 +35,6 @@
 #ifdef CONFIG_ARCH_OMAP34XX
 
 /*
- * 3430: PM_WKDEP_{PER,USBHOST}: CORE, IVA2, MPU, WKUP
- * (USBHOST is ES2 only)
- */
-static struct pwrdm_dep per_usbhost_wkdeps[] = {
-	{
-		.pwrdm_name = "core_pwrdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.pwrdm_name = "iva2_pwrdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.pwrdm_name = "mpu_pwrdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.pwrdm_name = "wkup_pwrdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{ NULL },
-};
-
-/*
- * 3430 PM_WKDEP_MPU: CORE, IVA2, DSS, PER
- */
-static struct pwrdm_dep mpu_34xx_wkdeps[] = {
-	{
-		.pwrdm_name = "core_pwrdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.pwrdm_name = "iva2_pwrdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.pwrdm_name = "dss_pwrdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.pwrdm_name = "per_pwrdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{ NULL },
-};
-
-/*
- * 3430 PM_WKDEP_IVA2: CORE, MPU, WKUP, DSS, PER
- */
-static struct pwrdm_dep iva2_wkdeps[] = {
-	{
-		.pwrdm_name = "core_pwrdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.pwrdm_name = "mpu_pwrdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.pwrdm_name = "wkup_pwrdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.pwrdm_name = "dss_pwrdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.pwrdm_name = "per_pwrdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{ NULL },
-};
-
-
-/* 3430 PM_WKDEP_{CAM,DSS}: IVA2, MPU, WKUP */
-static struct pwrdm_dep cam_dss_wkdeps[] = {
-	{
-		.pwrdm_name = "iva2_pwrdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.pwrdm_name = "mpu_pwrdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.pwrdm_name = "wkup_pwrdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{ NULL },
-};
-
-/* 3430: PM_WKDEP_NEON: MPU */
-static struct pwrdm_dep neon_wkdeps[] = {
-	{
-		.pwrdm_name = "mpu_pwrdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{ NULL },
-};
-
-
-/* Sleep dependency source arrays for 34xx-specific pwrdms - 34XX only */
-
-/*
- * 3430: CM_SLEEPDEP_{DSS,PER}: MPU, IVA
- * 3430ES2: CM_SLEEPDEP_USBHOST: MPU, IVA
- */
-static struct pwrdm_dep dss_per_usbhost_sleepdeps[] = {
-	{
-		.pwrdm_name = "mpu_pwrdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{
-		.pwrdm_name = "iva2_pwrdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
-	},
-	{ NULL },
-};
-
-
-/*
  * Powerdomains
  */
 
@@ -163,8 +42,6 @@ static struct powerdomain iva2_pwrdm = {
 	.name		  = "iva2_pwrdm",
 	.prcm_offs	  = OMAP3430_IVA2_MOD,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-	.dep_bit	  = OMAP3430_PM_WKDEP_MPU_EN_IVA2_SHIFT,
-	.wkdep_srcs	  = iva2_wkdeps,
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_OFF_RET,
 	.banks		  = 4,
@@ -186,8 +63,6 @@ static struct powerdomain mpu_34xx_pwrdm = {
 	.name		  = "mpu_pwrdm",
 	.prcm_offs	  = MPU_MOD,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-	.dep_bit	  = OMAP3430_EN_MPU_SHIFT,
-	.wkdep_srcs	  = mpu_34xx_wkdeps,
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_OFF_RET,
 	.flags		  = PWRDM_HAS_MPU_QUIRK,
@@ -200,7 +75,6 @@ static struct powerdomain mpu_34xx_pwrdm = {
 	},
 };
 
-/* No wkdeps or sleepdeps for 34xx core apparently */
 static struct powerdomain core_34xx_pre_es3_1_pwrdm = {
 	.name		  = "core_pwrdm",
 	.prcm_offs	  = CORE_MOD,
@@ -208,7 +82,6 @@ static struct powerdomain core_34xx_pre_es3_1_pwrdm = {
 					   CHIP_IS_OMAP3430ES2 |
 					   CHIP_IS_OMAP3430ES3_0),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
-	.dep_bit	  = OMAP3430_EN_CORE_SHIFT,
 	.banks		  = 2,
 	.pwrsts_mem_ret	  = {
 		[0] = PWRSTS_OFF_RET,	 /* MEM1RETSTATE */
@@ -220,13 +93,11 @@ static struct powerdomain core_34xx_pre_es3_1_pwrdm = {
 	},
 };
 
-/* No wkdeps or sleepdeps for 34xx core apparently */
 static struct powerdomain core_34xx_es3_1_pwrdm = {
 	.name		  = "core_pwrdm",
 	.prcm_offs	  = CORE_MOD,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES3_1),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
-	.dep_bit	  = OMAP3430_EN_CORE_SHIFT,
 	.flags		  = PWRDM_HAS_HDWR_SAR, /* for USBTLL only */
 	.banks		  = 2,
 	.pwrsts_mem_ret	  = {
@@ -239,14 +110,10 @@ static struct powerdomain core_34xx_es3_1_pwrdm = {
 	},
 };
 
-/* Another case of bit name collisions between several registers: EN_DSS */
 static struct powerdomain dss_pwrdm = {
 	.name		  = "dss_pwrdm",
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 	.prcm_offs	  = OMAP3430_DSS_MOD,
-	.dep_bit	  = OMAP3430_PM_WKDEP_MPU_EN_DSS_SHIFT,
-	.wkdep_srcs	  = cam_dss_wkdeps,
-	.sleepdep_srcs	  = dss_per_usbhost_sleepdeps,
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRDM_POWER_RET,
 	.banks		  = 1,
@@ -267,8 +134,6 @@ static struct powerdomain sgx_pwrdm = {
 	.name		  = "sgx_pwrdm",
 	.prcm_offs	  = OMAP3430ES2_SGX_MOD,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2),
-	.wkdep_srcs	  = gfx_sgx_wkdeps,
-	.sleepdep_srcs	  = cam_gfx_sleepdeps,
 	/* XXX This is accurate for 3430 SGX, but what about GFX? */
 	.pwrsts		  = PWRSTS_OFF_ON,
 	.pwrsts_logic_ret = PWRDM_POWER_RET,
@@ -285,8 +150,6 @@ static struct powerdomain cam_pwrdm = {
 	.name		  = "cam_pwrdm",
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 	.prcm_offs	  = OMAP3430_CAM_MOD,
-	.wkdep_srcs	  = cam_dss_wkdeps,
-	.sleepdep_srcs	  = cam_gfx_sleepdeps,
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRDM_POWER_RET,
 	.banks		  = 1,
@@ -302,9 +165,6 @@ static struct powerdomain per_pwrdm = {
 	.name		  = "per_pwrdm",
 	.prcm_offs	  = OMAP3430_PER_MOD,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-	.dep_bit	  = OMAP3430_EN_PER_SHIFT,
-	.wkdep_srcs	  = per_usbhost_wkdeps,
-	.sleepdep_srcs	  = dss_per_usbhost_sleepdeps,
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_OFF_RET,
 	.banks		  = 1,
@@ -326,7 +186,6 @@ static struct powerdomain neon_pwrdm = {
 	.name		  = "neon_pwrdm",
 	.prcm_offs	  = OMAP3430_NEON_MOD,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-	.wkdep_srcs	  = neon_wkdeps,
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRDM_POWER_RET,
 };
@@ -335,8 +194,6 @@ static struct powerdomain usbhost_pwrdm = {
 	.name		  = "usbhost_pwrdm",
 	.prcm_offs	  = OMAP3430ES2_USBHOST_MOD,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2),
-	.wkdep_srcs	  = per_usbhost_wkdeps,
-	.sleepdep_srcs	  = dss_per_usbhost_sleepdeps,
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRDM_POWER_RET,
 	/*
diff --git a/arch/arm/mach-omap2/prcm.c b/arch/arm/mach-omap2/prcm.c
index cc621e2..63330d2 100644
--- a/arch/arm/mach-omap2/prcm.c
+++ b/arch/arm/mach-omap2/prcm.c
@@ -202,6 +202,18 @@ u32 prm_rmw_mod_reg_bits(u32 mask, u32 bits, s16 module, s16 idx)
 	return v;
 }
 
+/* Read a PRM register, AND it, and shift the result down to bit 0 */
+u32 prm_read_mod_bits_shift(s16 domain, s16 idx, u32 mask)
+{
+	u32 v;
+
+	v = prm_read_mod_reg(domain, idx);
+	v &= mask;
+	v >>= __ffs(mask);
+
+	return v;
+}
+
 /* Read a register in a CM module */
 u32 cm_read_mod_reg(s16 module, u16 idx)
 {
diff --git a/arch/arm/plat-omap/include/plat/clockdomain.h b/arch/arm/plat-omap/include/plat/clockdomain.h
index 4806e2c..f77ca72 100644
--- a/arch/arm/plat-omap/include/plat/clockdomain.h
+++ b/arch/arm/plat-omap/include/plat/clockdomain.h
@@ -4,7 +4,7 @@
  * OMAP2/3 clockdomain framework functions
  *
  * Copyright (C) 2008 Texas Instruments, Inc.
- * Copyright (C) 2008 Nokia Corporation
+ * Copyright (C) 2008-2009 Nokia Corporation
  *
  * Written by Paul Walmsley
  *
@@ -41,26 +41,40 @@
 #define OMAP34XX_CLKSTCTRL_ENABLE_AUTO		0x3
 
 /*
- * struct clkdm_pwrdm_autodep - a powerdomain that should have wkdeps
- * and sleepdeps added when a powerdomain should stay active in hwsup mode;
- * and conversely, removed when the powerdomain should be allowed to go
+ * struct clkdm_autodep - a clockdomain that should have wkdeps
+ * and sleepdeps added when a clockdomain should stay active in hwsup mode;
+ * and conversely, removed when the clockdomain should be allowed to go
  * inactive in hwsup mode.
  */
-struct clkdm_pwrdm_autodep {
+struct clkdm_autodep {
 
 	union {
-		/* Name of the powerdomain to add a wkdep/sleepdep on */
+		/* Name of the clockdomain to add a wkdep/sleepdep on */
 		const char *name;
 
-		/* Powerdomain pointer (looked up at clkdm_init() time) */
-		struct powerdomain *ptr;
-	} pwrdm;
+		/* Clockdomain pointer (looked up at clkdm_init() time) */
+		struct clockdomain *ptr;
+	} clkdm;
 
 	/* OMAP chip types that this clockdomain dep is valid on */
 	const struct omap_chip_id omap_chip;
 
 };
 
+/* Encodes dependencies between clockdomains - statically defined */
+struct clkdm_dep {
+
+	/* Clockdomain name */
+	const char *clkdm_name;
+
+	/* Clockdomain pointer - resolved by the clockdomain code */
+	struct clockdomain *clkdm;
+
+	/* Flags to mark OMAP chip restrictions, etc. */
+	const struct omap_chip_id omap_chip;
+
+};
+
 struct clockdomain {
 
 	/* Clockdomain name */
@@ -83,6 +97,15 @@ struct clockdomain {
 	/* Clockdomain capability flags */
 	const u8 flags;
 
+	/* Bit shift of this clockdomain's PM_WKDEP/CM_SLEEPDEP bit */
+	const u8 dep_bit;
+
+	/* Clockdomains that can be told to wake this powerdomain up */
+	struct clkdm_dep *wkdep_srcs;
+
+	/* Clockdomains that can be told to keep this clkdm from inactivity */
+	struct clkdm_dep *sleepdep_srcs;
+
 	/* OMAP chip types that this clockdomain is valid on */
 	const struct omap_chip_id omap_chip;
 
@@ -93,7 +116,7 @@ struct clockdomain {
 
 };
 
-void clkdm_init(struct clockdomain **clkdms, struct clkdm_pwrdm_autodep *autodeps);
+void clkdm_init(struct clockdomain **clkdms, struct clkdm_autodep *autodeps);
 int clkdm_register(struct clockdomain *clkdm);
 int clkdm_unregister(struct clockdomain *clkdm);
 struct clockdomain *clkdm_lookup(const char *name);
@@ -102,6 +125,13 @@ int clkdm_for_each(int (*fn)(struct clockdomain *clkdm, void *user),
 			void *user);
 struct powerdomain *clkdm_get_pwrdm(struct clockdomain *clkdm);
 
+int clkdm_add_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
+int clkdm_del_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
+int clkdm_read_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
+int clkdm_add_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
+int clkdm_del_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
+int clkdm_read_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
+
 void omap2_clkdm_allow_idle(struct clockdomain *clkdm);
 void omap2_clkdm_deny_idle(struct clockdomain *clkdm);
 
diff --git a/arch/arm/plat-omap/include/plat/powerdomain.h b/arch/arm/plat-omap/include/plat/powerdomain.h
index bac378e..dd5f79d 100644
--- a/arch/arm/plat-omap/include/plat/powerdomain.h
+++ b/arch/arm/plat-omap/include/plat/powerdomain.h
@@ -1,8 +1,8 @@
 /*
  * OMAP2/3 powerdomain control
  *
- * Copyright (C) 2007-8 Texas Instruments, Inc.
- * Copyright (C) 2007-8 Nokia Corporation
+ * Copyright (C) 2007-2008 Texas Instruments, Inc.
+ * Copyright (C) 2007-2009 Nokia Corporation
  *
  * Written by Paul Walmsley
  *
@@ -68,20 +68,6 @@
 struct clockdomain;
 struct powerdomain;
 
-/* Encodes dependencies between powerdomains - statically defined */
-struct pwrdm_dep {
-
-	/* Powerdomain name */
-	const char *pwrdm_name;
-
-	/* Powerdomain pointer - resolved by the powerdomain code */
-	struct powerdomain *pwrdm;
-
-	/* Flags to mark OMAP chip restrictions, etc. */
-	const struct omap_chip_id omap_chip;
-
-};
-
 struct powerdomain {
 
 	/* Powerdomain name */
@@ -93,15 +79,6 @@ struct powerdomain {
 	/* Used to represent the OMAP chip types containing this pwrdm */
 	const struct omap_chip_id omap_chip;
 
-	/* Powerdomains that can be told to wake this powerdomain up */
-	struct pwrdm_dep *wkdep_srcs;
-
-	/* Powerdomains that can be told to keep this pwrdm from inactivity */
-	struct pwrdm_dep *sleepdep_srcs;
-
-	/* Bit shift of this powerdomain's PM_WKDEP/CM_SLEEPDEP bit */
-	const u8 dep_bit;
-
 	/* Possible powerdomain power states */
 	const u8 pwrsts;
 
@@ -152,13 +129,6 @@ int pwrdm_for_each_clkdm(struct powerdomain *pwrdm,
 			 int (*fn)(struct powerdomain *pwrdm,
 				   struct clockdomain *clkdm));
 
-int pwrdm_add_wkdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2);
-int pwrdm_del_wkdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2);
-int pwrdm_read_wkdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2);
-int pwrdm_add_sleepdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2);
-int pwrdm_del_sleepdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2);
-int pwrdm_read_sleepdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2);
-
 int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm);
 
 int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst);
diff --git a/arch/arm/plat-omap/include/plat/prcm.h b/arch/arm/plat-omap/include/plat/prcm.h
index e63e94e..66938a9 100644
--- a/arch/arm/plat-omap/include/plat/prcm.h
+++ b/arch/arm/plat-omap/include/plat/prcm.h
@@ -33,6 +33,14 @@ int omap2_cm_wait_idlest(void __iomem *reg, u32 mask, const char *name);
 void omap3_prcm_save_context(void);
 void omap3_prcm_restore_context(void);
 
+u32 prm_read_mod_reg(s16 module, u16 idx);
+void prm_write_mod_reg(u32 val, s16 module, u16 idx);
+u32 prm_rmw_mod_reg_bits(u32 mask, u32 bits, s16 module, s16 idx);
+u32 prm_read_mod_bits_shift(s16 domain, s16 idx, u32 mask);
+u32 cm_read_mod_reg(s16 module, u16 idx);
+void cm_write_mod_reg(u32 val, s16 module, u16 idx);
+u32 cm_rmw_mod_reg_bits(u32 mask, u32 bits, s16 module, s16 idx);
+
 #endif
 
 

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 02/10] OMAP2/3 clockdomains: split shared structures so usecounting works
  2010-01-12  1:05 [PATCH 00/10] OMAP2/3/4 clockdomains/powerdomains: split shared dependencies and clean up - for 2.6.34 Paul Walmsley
  2010-01-12  1:05 ` [PATCH 01/10] OMAP2/3 clkdm/pwrdm: move wkdep/sleepdep handling from pwrdm to clkdm Paul Walmsley
@ 2010-01-12  1:05 ` Paul Walmsley
  2010-01-12  1:05 ` [PATCH 03/10] OMAP2 clockdomain: modem clockdomain is only present on OMAP2430 Paul Walmsley
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 14+ messages in thread
From: Paul Walmsley @ 2010-01-12  1:05 UTC (permalink / raw)
  To: linux-arm-kernel

Previously some of the clockdomain wakeup/sleep dependency structures
were shared between several domains.  For the subsequent wakeup and sleep
dependency usecounting patch to work, these can no longer be
shared.  This patch splits the shared structures apart.

Signed-off-by: Paul Walmsley <paul@pwsan.com>
---
 arch/arm/mach-omap2/clockdomains.h |  163 ++++++++++++++++++++++++++++--------
 1 files changed, 127 insertions(+), 36 deletions(-)

diff --git a/arch/arm/mach-omap2/clockdomains.h b/arch/arm/mach-omap2/clockdomains.h
index ff216f2..9629ef1 100644
--- a/arch/arm/mach-omap2/clockdomains.h
+++ b/arch/arm/mach-omap2/clockdomains.h
@@ -52,6 +52,8 @@
  * 2420/2430 PM_WKDEP_GFX: CORE, MPU, WKUP
  * 3430ES1 PM_WKDEP_GFX: adds IVA2, removes CORE
  * 3430ES2 PM_WKDEP_SGX: adds IVA2, removes CORE
+ * These can share data since they will never be present simultaneously
+ * on the same device.
  */
 static struct clkdm_dep gfx_sgx_wkdeps[] = {
 	{
@@ -86,11 +88,32 @@ static struct clkdm_dep gfx_sgx_wkdeps[] = {
 
 /* Wakeup dependency source arrays */
 
+/* 2420/2430 PM_WKDEP_DSP: CORE, MPU, WKUP */
+static struct clkdm_dep dsp_24xx_wkdeps[] = {
+	{
+		.clkdm_name = "core_l3_clkdm",
+		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
+	},
+	{
+		.clkdm_name = "core_l4_clkdm",
+		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
+	},
+	{
+		.clkdm_name = "mpu_clkdm",
+		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
+	},
+	{
+		.clkdm_name = "wkup_clkdm",
+		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
+	},
+	{ NULL },
+};
+
 /*
- * 2420/2430 PM_WKDEP_DSP: CORE, MPU, WKUP
- * 2420/2430 PM_WKDEP_MDM: same as DSP
+ * 2420/2430 PM_WKDEP_MDM: CORE, MPU, WKUP
+ * XXX This is probably 2430-only; 2420 did not have a stacked modem config.
  */
-static struct clkdm_dep dsp_mdm_24xx_wkdeps[] = {
+static struct clkdm_dep mdm_24xx_wkdeps[] = {
 	{
 		.clkdm_name = "core_l3_clkdm",
 		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
@@ -172,11 +195,8 @@ static struct clkdm_dep core_24xx_wkdeps[] = {
 
 #ifdef CONFIG_ARCH_OMAP34XX
 
-/*
- * 3430: PM_WKDEP_{PER,USBHOST}: CORE, IVA2, MPU, WKUP
- * (USBHOST is ES2 only)
- */
-static struct clkdm_dep per_usbhost_wkdeps[] = {
+/* 3430: PM_WKDEP_PER: CORE, IVA2, MPU, WKUP */
+static struct clkdm_dep per_wkdeps[] = {
 	{
 		.clkdm_name = "core_l3_clkdm",
 		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
@@ -200,9 +220,32 @@ static struct clkdm_dep per_usbhost_wkdeps[] = {
 	{ NULL },
 };
 
-/*
- * 3430 PM_WKDEP_MPU: CORE, IVA2, DSS, PER
- */
+/* 3430ES2: PM_WKDEP_USBHOST: CORE, IVA2, MPU, WKUP */
+static struct clkdm_dep usbhost_wkdeps[] = {
+	{
+		.clkdm_name = "core_l3_clkdm",
+		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+	},
+	{
+		.clkdm_name = "core_l4_clkdm",
+		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+	},
+	{
+		.clkdm_name = "iva2_clkdm",
+		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+	},
+	{
+		.clkdm_name = "mpu_clkdm",
+		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+	},
+	{
+		.clkdm_name = "wkup_clkdm",
+		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+	},
+	{ NULL },
+};
+
+/* 3430 PM_WKDEP_MPU: CORE, IVA2, DSS, PER */
 static struct clkdm_dep mpu_34xx_wkdeps[] = {
 	{
 		.clkdm_name = "core_l3_clkdm",
@@ -227,9 +270,7 @@ static struct clkdm_dep mpu_34xx_wkdeps[] = {
 	{ NULL },
 };
 
-/*
- * 3430 PM_WKDEP_IVA2: CORE, MPU, WKUP, DSS, PER
- */
+/* 3430 PM_WKDEP_IVA2: CORE, MPU, WKUP, DSS, PER */
 static struct clkdm_dep iva2_wkdeps[] = {
 	{
 		.clkdm_name = "core_l3_clkdm",
@@ -259,8 +300,25 @@ static struct clkdm_dep iva2_wkdeps[] = {
 };
 
 
-/* 3430 PM_WKDEP_{CAM,DSS}: IVA2, MPU, WKUP */
-static struct clkdm_dep cam_dss_wkdeps[] = {
+/* 3430 PM_WKDEP_CAM: IVA2, MPU, WKUP */
+static struct clkdm_dep cam_wkdeps[] = {
+	{
+		.clkdm_name = "iva2_clkdm",
+		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+	},
+	{
+		.clkdm_name = "mpu_clkdm",
+		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+	},
+	{
+		.clkdm_name = "wkup_clkdm",
+		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+	},
+	{ NULL },
+};
+
+/* 3430 PM_WKDEP_DSS: IVA2, MPU, WKUP */
+static struct clkdm_dep dss_wkdeps[] = {
 	{
 		.clkdm_name = "iva2_clkdm",
 		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
@@ -288,11 +346,8 @@ static struct clkdm_dep neon_wkdeps[] = {
 
 /* Sleep dependency source arrays for 34xx-specific clkdms - 34XX only */
 
-/*
- * 3430: CM_SLEEPDEP_{DSS,PER}: MPU, IVA
- * 3430ES2: CM_SLEEPDEP_USBHOST: MPU, IVA
- */
-static struct clkdm_dep dss_per_usbhost_sleepdeps[] = {
+/* 3430: CM_SLEEPDEP_DSS: MPU, IVA */
+static struct clkdm_dep dss_sleepdeps[] = {
 	{
 		.clkdm_name = "mpu_clkdm",
 		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
@@ -304,12 +359,48 @@ static struct clkdm_dep dss_per_usbhost_sleepdeps[] = {
 	{ NULL },
 };
 
+/* 3430: CM_SLEEPDEP_PER: MPU, IVA */
+static struct clkdm_dep per_sleepdeps[] = {
+	{
+		.clkdm_name = "mpu_clkdm",
+		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+	},
+	{
+		.clkdm_name = "iva2_clkdm",
+		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+	},
+	{ NULL },
+};
+
+/* 3430ES2: CM_SLEEPDEP_USBHOST: MPU, IVA */
+static struct clkdm_dep usbhost_sleepdeps[] = {
+	{
+		.clkdm_name = "mpu_clkdm",
+		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+	},
+	{
+		.clkdm_name = "iva2_clkdm",
+		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+	},
+	{ NULL },
+};
+
+/* 3430: CM_SLEEPDEP_CAM: MPU */
+static struct clkdm_dep cam_sleepdeps[] = {
+	{
+		.clkdm_name = "mpu_clkdm",
+		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+	},
+	{ NULL },
+};
+
 /*
- * 3430: CM_SLEEPDEP_CAM: MPU
  * 3430ES1: CM_SLEEPDEP_GFX: MPU
  * 3430ES2: CM_SLEEPDEP_SGX: MPU
+ * These can share data since they will never be present simultaneously
+ * on the same device.
  */
-static struct clkdm_dep cam_gfx_sleepdeps[] = {
+static struct clkdm_dep gfx_sgx_sleepdeps[] = {
 	{
 		.clkdm_name = "mpu_clkdm",
 		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
@@ -376,7 +467,7 @@ static struct clockdomain iva1_2420_clkdm = {
 	.clkstctrl_reg  = OMAP2420_CM_REGADDR(OMAP24XX_DSP_MOD,
 						 OMAP2_CM_CLKSTCTRL),
 	.dep_bit	= OMAP24XX_PM_WKDEP_MPU_EN_DSP_SHIFT,
-	.wkdep_srcs	= dsp_mdm_24xx_wkdeps,
+	.wkdep_srcs	= dsp_24xx_wkdeps,
 	.clktrctrl_mask = OMAP2420_AUTOSTATE_IVA_MASK,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 };
@@ -458,7 +549,7 @@ static struct clockdomain mdm_clkdm = {
 	.clkstctrl_reg  = OMAP2430_CM_REGADDR(OMAP2430_MDM_MOD,
 						 OMAP2_CM_CLKSTCTRL),
 	.dep_bit	= OMAP2430_PM_WKDEP_MPU_EN_MDM_SHIFT,
-	.wkdep_srcs	= dsp_mdm_24xx_wkdeps,
+	.wkdep_srcs	= mdm_24xx_wkdeps,
 	.clktrctrl_mask = OMAP2430_AUTOSTATE_MDM_MASK,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
@@ -470,7 +561,7 @@ static struct clockdomain dsp_2430_clkdm = {
 	.clkstctrl_reg  = OMAP2430_CM_REGADDR(OMAP24XX_DSP_MOD,
 						 OMAP2_CM_CLKSTCTRL),
 	.dep_bit	= OMAP24XX_PM_WKDEP_MPU_EN_DSP_SHIFT,
-	.wkdep_srcs	= dsp_mdm_24xx_wkdeps,
+	.wkdep_srcs	= dsp_24xx_wkdeps,
 	.clktrctrl_mask = OMAP24XX_AUTOSTATE_DSP_MASK,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
@@ -575,7 +666,7 @@ static struct clockdomain gfx_3430es1_clkdm = {
 	.flags		= CLKDM_CAN_HWSUP_SWSUP,
 	.clkstctrl_reg	= OMAP34XX_CM_REGADDR(GFX_MOD, OMAP2_CM_CLKSTCTRL),
 	.wkdep_srcs	= gfx_sgx_wkdeps,
-	.sleepdep_srcs	= cam_gfx_sleepdeps,
+	.sleepdep_srcs	= gfx_sgx_sleepdeps,
 	.clktrctrl_mask = OMAP3430ES1_CLKTRCTRL_GFX_MASK,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1),
 };
@@ -587,7 +678,7 @@ static struct clockdomain sgx_clkdm = {
 	.clkstctrl_reg	= OMAP34XX_CM_REGADDR(OMAP3430ES2_SGX_MOD,
 						 OMAP2_CM_CLKSTCTRL),
 	.wkdep_srcs	= gfx_sgx_wkdeps,
-	.sleepdep_srcs	= cam_gfx_sleepdeps,
+	.sleepdep_srcs	= gfx_sgx_sleepdeps,
 	.clktrctrl_mask = OMAP3430ES2_CLKTRCTRL_SGX_MASK,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2),
 };
@@ -646,8 +737,8 @@ static struct clockdomain dss_34xx_clkdm = {
 	.clkstctrl_reg	= OMAP34XX_CM_REGADDR(OMAP3430_DSS_MOD,
 						 OMAP2_CM_CLKSTCTRL),
 	.dep_bit	= OMAP3430_PM_WKDEP_MPU_EN_DSS_SHIFT,
-	.wkdep_srcs	= cam_dss_wkdeps,
-	.sleepdep_srcs	= dss_per_usbhost_sleepdeps,
+	.wkdep_srcs	= dss_wkdeps,
+	.sleepdep_srcs	= dss_sleepdeps,
 	.clktrctrl_mask = OMAP3430_CLKTRCTRL_DSS_MASK,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
@@ -658,8 +749,8 @@ static struct clockdomain cam_clkdm = {
 	.flags		= CLKDM_CAN_HWSUP_SWSUP,
 	.clkstctrl_reg	= OMAP34XX_CM_REGADDR(OMAP3430_CAM_MOD,
 						 OMAP2_CM_CLKSTCTRL),
-	.wkdep_srcs	= cam_dss_wkdeps,
-	.sleepdep_srcs	= cam_gfx_sleepdeps,
+	.wkdep_srcs	= cam_wkdeps,
+	.sleepdep_srcs	= cam_sleepdeps,
 	.clktrctrl_mask = OMAP3430_CLKTRCTRL_CAM_MASK,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
@@ -670,8 +761,8 @@ static struct clockdomain usbhost_clkdm = {
 	.flags		= CLKDM_CAN_HWSUP_SWSUP,
 	.clkstctrl_reg	= OMAP34XX_CM_REGADDR(OMAP3430ES2_USBHOST_MOD,
 						 OMAP2_CM_CLKSTCTRL),
-	.wkdep_srcs	= per_usbhost_wkdeps,
-	.sleepdep_srcs	= dss_per_usbhost_sleepdeps,
+	.wkdep_srcs	= usbhost_wkdeps,
+	.sleepdep_srcs	= usbhost_sleepdeps,
 	.clktrctrl_mask = OMAP3430ES2_CLKTRCTRL_USBHOST_MASK,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2),
 };
@@ -683,8 +774,8 @@ static struct clockdomain per_clkdm = {
 	.clkstctrl_reg	= OMAP34XX_CM_REGADDR(OMAP3430_PER_MOD,
 						 OMAP2_CM_CLKSTCTRL),
 	.dep_bit	= OMAP3430_EN_PER_SHIFT,
-	.wkdep_srcs	= per_usbhost_wkdeps,
-	.sleepdep_srcs	= dss_per_usbhost_sleepdeps,
+	.wkdep_srcs	= per_wkdeps,
+	.sleepdep_srcs	= per_sleepdeps,
 	.clktrctrl_mask = OMAP3430_CLKTRCTRL_PER_MASK,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 03/10] OMAP2 clockdomain: modem clockdomain is only present on OMAP2430
  2010-01-12  1:05 [PATCH 00/10] OMAP2/3/4 clockdomains/powerdomains: split shared dependencies and clean up - for 2.6.34 Paul Walmsley
  2010-01-12  1:05 ` [PATCH 01/10] OMAP2/3 clkdm/pwrdm: move wkdep/sleepdep handling from pwrdm to clkdm Paul Walmsley
  2010-01-12  1:05 ` [PATCH 02/10] OMAP2/3 clockdomains: split shared structures so usecounting works Paul Walmsley
@ 2010-01-12  1:05 ` Paul Walmsley
  2010-01-12  1:05 ` [PATCH 04/10] OMAP clockdomain/powerdomain: remove runtime register/unregister Paul Walmsley
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 14+ messages in thread
From: Paul Walmsley @ 2010-01-12  1:05 UTC (permalink / raw)
  To: linux-arm-kernel

For some reason, previously, we included the MDM clockdomain on all 24xx,
but the stacked die-on-die modem configuration (chassis mode) is only
available on OMAP2430.

Signed-off-by: Paul Walmsley <paul@pwsan.com>
---
 arch/arm/mach-omap2/clockdomains.h |   49 ++++++++++++++++++++----------------
 1 files changed, 27 insertions(+), 22 deletions(-)

diff --git a/arch/arm/mach-omap2/clockdomains.h b/arch/arm/mach-omap2/clockdomains.h
index 9629ef1..fb026da 100644
--- a/arch/arm/mach-omap2/clockdomains.h
+++ b/arch/arm/mach-omap2/clockdomains.h
@@ -110,10 +110,10 @@ static struct clkdm_dep dsp_24xx_wkdeps[] = {
 };
 
 /*
- * 2420/2430 PM_WKDEP_MDM: CORE, MPU, WKUP
- * XXX This is probably 2430-only; 2420 did not have a stacked modem config.
+ * 2420 PM_WKDEP_MPU: CORE, DSP, WKUP
+ * 2430 adds MDM
  */
-static struct clkdm_dep mdm_24xx_wkdeps[] = {
+static struct clkdm_dep mpu_24xx_wkdeps[] = {
 	{
 		.clkdm_name = "core_l3_clkdm",
 		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
@@ -123,31 +123,35 @@ static struct clkdm_dep mdm_24xx_wkdeps[] = {
 		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
 	},
 	{
-		.clkdm_name = "mpu_clkdm",
+		.clkdm_name = "dsp_clkdm",
 		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
 	},
 	{
 		.clkdm_name = "wkup_clkdm",
 		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
 	},
+	{
+		.clkdm_name = "mdm_clkdm",
+		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
+	},
 	{ NULL },
 };
 
 /*
- * 2420 PM_WKDEP_MPU: CORE, DSP, WKUP
+ * 2420 PM_WKDEP_CORE: DSP, GFX, MPU, WKUP
  * 2430 adds MDM
  */
-static struct clkdm_dep mpu_24xx_wkdeps[] = {
+static struct clkdm_dep core_24xx_wkdeps[] = {
 	{
-		.clkdm_name = "core_l3_clkdm",
+		.clkdm_name = "dsp_clkdm",
 		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
 	},
 	{
-		.clkdm_name = "core_l4_clkdm",
+		.clkdm_name = "gfx_clkdm",
 		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
 	},
 	{
-		.clkdm_name = "dsp_clkdm",
+		.clkdm_name = "mpu_clkdm",
 		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
 	},
 	{
@@ -161,17 +165,21 @@ static struct clkdm_dep mpu_24xx_wkdeps[] = {
 	{ NULL },
 };
 
-/*
- * 2420 PM_WKDEP_CORE: DSP, GFX, MPU, WKUP
- * 2430 adds MDM
- */
-static struct clkdm_dep core_24xx_wkdeps[] = {
+#endif
+
+
+/* 2430-specific possible wakeup dependencies */
+
+#ifdef CONFIG_ARCH_OMAP2430
+
+/* 2430 PM_WKDEP_MDM: CORE, MPU, WKUP */
+static struct clkdm_dep mdm_2430_wkdeps[] = {
 	{
-		.clkdm_name = "dsp_clkdm",
+		.clkdm_name = "core_l3_clkdm",
 		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
 	},
 	{
-		.clkdm_name = "gfx_clkdm",
+		.clkdm_name = "core_l4_clkdm",
 		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
 	},
 	{
@@ -182,14 +190,11 @@ static struct clkdm_dep core_24xx_wkdeps[] = {
 		.clkdm_name = "wkup_clkdm",
 		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
 	},
-	{
-		.clkdm_name = "mdm_clkdm",
-		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
-	},
 	{ NULL },
 };
 
-#endif
+#endif /* CONFIG_ARCH_OMAP2430 */
+
 
 /* 34XX-specific possible dependencies */
 
@@ -549,7 +554,7 @@ static struct clockdomain mdm_clkdm = {
 	.clkstctrl_reg  = OMAP2430_CM_REGADDR(OMAP2430_MDM_MOD,
 						 OMAP2_CM_CLKSTCTRL),
 	.dep_bit	= OMAP2430_PM_WKDEP_MPU_EN_MDM_SHIFT,
-	.wkdep_srcs	= mdm_24xx_wkdeps,
+	.wkdep_srcs	= mdm_2430_wkdeps,
 	.clktrctrl_mask = OMAP2430_AUTOSTATE_MDM_MASK,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 04/10] OMAP clockdomain/powerdomain: remove runtime register/unregister
  2010-01-12  1:05 [PATCH 00/10] OMAP2/3/4 clockdomains/powerdomains: split shared dependencies and clean up - for 2.6.34 Paul Walmsley
                   ` (2 preceding siblings ...)
  2010-01-12  1:05 ` [PATCH 03/10] OMAP2 clockdomain: modem clockdomain is only present on OMAP2430 Paul Walmsley
@ 2010-01-12  1:05 ` Paul Walmsley
  2010-01-19 23:50   ` Kevin Hilman
  2010-01-12  1:05 ` [PATCH 05/10] OMAP clockdomains: add usecounting for wakeup and sleep dependencies Paul Walmsley
                   ` (5 subsequent siblings)
  9 siblings, 1 reply; 14+ messages in thread
From: Paul Walmsley @ 2010-01-12  1:05 UTC (permalink / raw)
  To: linux-arm-kernel

OMAP clockdomains and powerdomains are currently defined statically,
only registered at boot, and never unregistered, so we can remove the
unregister function and the locking.   A variant of this was originally
suggested a while ago by Dmitry Baryshkov <dbaryshkov@gmail.com>.

Signed-off-by: Paul Walmsley <paul@pwsan.com>
Cc: Dmitry Baryshkov <dbaryshkov@gmail.com>
---
 arch/arm/mach-omap2/clockdomain.c             |  118 ++++++-----------
 arch/arm/mach-omap2/powerdomain.c             |  178 ++++++-------------------
 arch/arm/plat-omap/include/plat/clockdomain.h |    2 
 arch/arm/plat-omap/include/plat/powerdomain.h |    2 
 4 files changed, 85 insertions(+), 215 deletions(-)

diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c
index a70ba29..2af9996 100644
--- a/arch/arm/mach-omap2/clockdomain.c
+++ b/arch/arm/mach-omap2/clockdomain.c
@@ -39,9 +39,6 @@
 /* clkdm_list contains all registered struct clockdomains */
 static LIST_HEAD(clkdm_list);
 
-/* clkdm_mutex protects clkdm_list add and del ops */
-static DEFINE_MUTEX(clkdm_mutex);
-
 /* array of clockdomain deps to be added/removed when clkdm in hwsup mode */
 static struct clkdm_autodep *autodeps;
 
@@ -67,6 +64,45 @@ static struct clockdomain *_clkdm_lookup(const char *name)
 	return clkdm;
 }
 
+/**
+ * _clkdm_register - register a clockdomain
+ * @clkdm: struct clockdomain * to register
+ *
+ * Adds a clockdomain to the internal clockdomain list.
+ * Returns -EINVAL if given a null pointer, -EEXIST if a clockdomain is
+ * already registered by the provided name, or 0 upon success.
+ */
+static int _clkdm_register(struct clockdomain *clkdm)
+{
+	struct powerdomain *pwrdm;
+
+	if (!clkdm || !clkdm->name)
+		return -EINVAL;
+
+	if (!omap_chip_is(clkdm->omap_chip))
+		return -EINVAL;
+
+	pwrdm = pwrdm_lookup(clkdm->pwrdm.name);
+	if (!pwrdm) {
+		pr_err("clockdomain: %s: powerdomain %s does not exist\n",
+			clkdm->name, clkdm->pwrdm.name);
+		return -EINVAL;
+	}
+	clkdm->pwrdm.ptr = pwrdm;
+
+	/* Verify that the clockdomain is not already registered */
+	if (_clkdm_lookup(clkdm->name))
+		return -EEXIST;
+
+	list_add(&clkdm->node, &clkdm_list);
+
+	pwrdm_add_clkdm(pwrdm, clkdm);
+
+	pr_debug("clockdomain: registered %s\n", clkdm->name);
+
+	return 0;
+}
+
 /* _clkdm_deps_lookup - look up the specified clockdomain in a clkdm list */
 static struct clkdm_dep *_clkdm_deps_lookup(struct clockdomain *clkdm,
 					    struct clkdm_dep *deps)
@@ -240,7 +276,7 @@ void clkdm_init(struct clockdomain **clkdms,
 
 	if (clkdms)
 		for (c = clkdms; *c; c++)
-			clkdm_register(*c);
+			_clkdm_register(*c);
 
 	autodeps = init_autodeps;
 	if (autodeps)
@@ -249,76 +285,6 @@ void clkdm_init(struct clockdomain **clkdms,
 }
 
 /**
- * clkdm_register - register a clockdomain
- * @clkdm: struct clockdomain * to register
- *
- * Adds a clockdomain to the internal clockdomain list.
- * Returns -EINVAL if given a null pointer, -EEXIST if a clockdomain is
- * already registered by the provided name, or 0 upon success.
- */
-int clkdm_register(struct clockdomain *clkdm)
-{
-	int ret = -EINVAL;
-	struct powerdomain *pwrdm;
-
-	if (!clkdm || !clkdm->name)
-		return -EINVAL;
-
-	if (!omap_chip_is(clkdm->omap_chip))
-		return -EINVAL;
-
-	pwrdm = pwrdm_lookup(clkdm->pwrdm.name);
-	if (!pwrdm) {
-		pr_err("clockdomain: %s: powerdomain %s does not exist\n",
-			clkdm->name, clkdm->pwrdm.name);
-		return -EINVAL;
-	}
-	clkdm->pwrdm.ptr = pwrdm;
-
-	mutex_lock(&clkdm_mutex);
-	/* Verify that the clockdomain is not already registered */
-	if (_clkdm_lookup(clkdm->name)) {
-		ret = -EEXIST;
-		goto cr_unlock;
-	}
-
-	list_add(&clkdm->node, &clkdm_list);
-
-	pwrdm_add_clkdm(pwrdm, clkdm);
-
-	pr_debug("clockdomain: registered %s\n", clkdm->name);
-	ret = 0;
-
-cr_unlock:
-	mutex_unlock(&clkdm_mutex);
-
-	return ret;
-}
-
-/**
- * clkdm_unregister - unregister a clockdomain
- * @clkdm: struct clockdomain * to unregister
- *
- * Removes a clockdomain from the internal clockdomain list.  Returns
- * -EINVAL if clkdm argument is NULL.
- */
-int clkdm_unregister(struct clockdomain *clkdm)
-{
-	if (!clkdm)
-		return -EINVAL;
-
-	pwrdm_del_clkdm(clkdm->pwrdm.ptr, clkdm);
-
-	mutex_lock(&clkdm_mutex);
-	list_del(&clkdm->node);
-	mutex_unlock(&clkdm_mutex);
-
-	pr_debug("clockdomain: unregistered %s\n", clkdm->name);
-
-	return 0;
-}
-
-/**
  * clkdm_lookup - look up a clockdomain by name, return a pointer
  * @name: name of clockdomain
  *
@@ -334,14 +300,12 @@ struct clockdomain *clkdm_lookup(const char *name)
 
 	clkdm = NULL;
 
-	mutex_lock(&clkdm_mutex);
 	list_for_each_entry(temp_clkdm, &clkdm_list, node) {
 		if (!strcmp(name, temp_clkdm->name)) {
 			clkdm = temp_clkdm;
 			break;
 		}
 	}
-	mutex_unlock(&clkdm_mutex);
 
 	return clkdm;
 }
@@ -369,13 +333,11 @@ int clkdm_for_each(int (*fn)(struct clockdomain *clkdm, void *user),
 	if (!fn)
 		return -EINVAL;
 
-	mutex_lock(&clkdm_mutex);
 	list_for_each_entry(clkdm, &clkdm_list, node) {
 		ret = (*fn)(clkdm, user);
 		if (ret)
 			break;
 	}
-	mutex_unlock(&clkdm_mutex);
 
 	return ret;
 }
diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
index e8e8d88..411361f 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -80,13 +80,6 @@ static u16 pwrstst_reg_offs;
 /* pwrdm_list contains all registered struct powerdomains */
 static LIST_HEAD(pwrdm_list);
 
-/*
- * pwrdm_rwlock protects pwrdm_list add and del ops - also reused to
- * protect pwrdm_clkdms[] during clkdm add/del ops
- */
-static DEFINE_RWLOCK(pwrdm_rwlock);
-
-
 /* Private functions */
 
 static struct powerdomain *_pwrdm_lookup(const char *name)
@@ -105,6 +98,42 @@ static struct powerdomain *_pwrdm_lookup(const char *name)
 	return pwrdm;
 }
 
+/**
+ * _pwrdm_register - register a powerdomain
+ * @pwrdm: struct powerdomain * to register
+ *
+ * Adds a powerdomain to the internal powerdomain list.  Returns
+ * -EINVAL if given a null pointer, -EEXIST if a powerdomain is
+ * already registered by the provided name, or 0 upon success.
+ */
+static int _pwrdm_register(struct powerdomain *pwrdm)
+{
+	int i;
+
+	if (!pwrdm)
+		return -EINVAL;
+
+	if (!omap_chip_is(pwrdm->omap_chip))
+		return -EINVAL;
+
+	if (_pwrdm_lookup(pwrdm->name))
+		return -EEXIST;
+
+	list_add(&pwrdm->node, &pwrdm_list);
+
+	/* Initialize the powerdomain's state counter */
+	for (i = 0; i < 4; i++)
+		pwrdm->state_counter[i] = 0;
+
+	pwrdm_wait_transition(pwrdm);
+	pwrdm->state = pwrdm_read_pwrst(pwrdm);
+	pwrdm->state_counter[pwrdm->state] = 1;
+
+	pr_debug("powerdomain: registered %s\n", pwrdm->name);
+
+	return 0;
+}
+
 static int _pwrdm_state_switch(struct powerdomain *pwrdm, int flag)
 {
 
@@ -152,19 +181,6 @@ static int _pwrdm_post_transition_cb(struct powerdomain *pwrdm, void *unused)
 	return 0;
 }
 
-static __init void _pwrdm_setup(struct powerdomain *pwrdm)
-{
-	int i;
-
-	for (i = 0; i < PWRDM_MAX_PWRSTS; i++)
-		pwrdm->state_counter[i] = 0;
-
-	pwrdm_wait_transition(pwrdm);
-	pwrdm->state = pwrdm_read_pwrst(pwrdm);
-	pwrdm->state_counter[pwrdm->state] = 1;
-
-}
-
 /* Public functions */
 
 /**
@@ -192,73 +208,12 @@ void pwrdm_init(struct powerdomain **pwrdm_list)
 	}
 
 	if (pwrdm_list) {
-		for (p = pwrdm_list; *p; p++) {
-			pwrdm_register(*p);
-			_pwrdm_setup(*p);
-		}
+		for (p = pwrdm_list; *p; p++)
+			_pwrdm_register(*p);
 	}
 }
 
 /**
- * pwrdm_register - register a powerdomain
- * @pwrdm: struct powerdomain * to register
- *
- * Adds a powerdomain to the internal powerdomain list.  Returns
- * -EINVAL if given a null pointer, -EEXIST if a powerdomain is
- * already registered by the provided name, or 0 upon success.
- */
-int pwrdm_register(struct powerdomain *pwrdm)
-{
-	unsigned long flags;
-	int ret = -EINVAL;
-
-	if (!pwrdm)
-		return -EINVAL;
-
-	if (!omap_chip_is(pwrdm->omap_chip))
-		return -EINVAL;
-
-	write_lock_irqsave(&pwrdm_rwlock, flags);
-	if (_pwrdm_lookup(pwrdm->name)) {
-		ret = -EEXIST;
-		goto pr_unlock;
-	}
-
-	list_add(&pwrdm->node, &pwrdm_list);
-
-	pr_debug("powerdomain: registered %s\n", pwrdm->name);
-	ret = 0;
-
-pr_unlock:
-	write_unlock_irqrestore(&pwrdm_rwlock, flags);
-
-	return ret;
-}
-
-/**
- * pwrdm_unregister - unregister a powerdomain
- * @pwrdm: struct powerdomain * to unregister
- *
- * Removes a powerdomain from the internal powerdomain list.  Returns
- * -EINVAL if pwrdm argument is NULL.
- */
-int pwrdm_unregister(struct powerdomain *pwrdm)
-{
-	unsigned long flags;
-
-	if (!pwrdm)
-		return -EINVAL;
-
-	write_lock_irqsave(&pwrdm_rwlock, flags);
-	list_del(&pwrdm->node);
-	write_unlock_irqrestore(&pwrdm_rwlock, flags);
-
-	pr_debug("powerdomain: unregistered %s\n", pwrdm->name);
-
-	return 0;
-}
-
-/**
  * pwrdm_lookup - look up a powerdomain by name, return a pointer
  * @name: name of powerdomain
  *
@@ -268,20 +223,17 @@ int pwrdm_unregister(struct powerdomain *pwrdm)
 struct powerdomain *pwrdm_lookup(const char *name)
 {
 	struct powerdomain *pwrdm;
-	unsigned long flags;
 
 	if (!name)
 		return NULL;
 
-	read_lock_irqsave(&pwrdm_rwlock, flags);
 	pwrdm = _pwrdm_lookup(name);
-	read_unlock_irqrestore(&pwrdm_rwlock, flags);
 
 	return pwrdm;
 }
 
 /**
- * pwrdm_for_each_nolock - call function on each registered clockdomain
+ * pwrdm_for_each - call function on each registered clockdomain
  * @fn: callback function *
  *
  * Call the supplied function for each registered powerdomain.  The
@@ -290,8 +242,8 @@ struct powerdomain *pwrdm_lookup(const char *name)
  * should be 0 for success or anything else to indicate failure; or -EINVAL if
  * the function pointer is null.
  */
-int pwrdm_for_each_nolock(int (*fn)(struct powerdomain *pwrdm, void *user),
-				void *user)
+int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm, void *user),
+		   void *user)
 {
 	struct powerdomain *temp_pwrdm;
 	int ret = 0;
@@ -309,28 +261,6 @@ int pwrdm_for_each_nolock(int (*fn)(struct powerdomain *pwrdm, void *user),
 }
 
 /**
- * pwrdm_for_each - call function on each registered clockdomain
- * @fn: callback function *
- *
- * This function is the same as 'pwrdm_for_each_nolock()', but keeps the
- * &pwrdm_rwlock locked for reading, so no powerdomain structure manipulation
- * functions should be called from the callback, although hardware powerdomain
- * control functions are fine.
- */
-int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm, void *user),
-			void *user)
-{
-	unsigned long flags;
-	int ret;
-
-	read_lock_irqsave(&pwrdm_rwlock, flags);
-	ret = pwrdm_for_each_nolock(fn, user);
-	read_unlock_irqrestore(&pwrdm_rwlock, flags);
-
-	return ret;
-}
-
-/**
  * pwrdm_add_clkdm - add a clockdomain to a powerdomain
  * @pwrdm: struct powerdomain * to add the clockdomain to
  * @clkdm: struct clockdomain * to associate with a powerdomain
@@ -342,7 +272,6 @@ int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm, void *user),
  */
 int pwrdm_add_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm)
 {
-	unsigned long flags;
 	int i;
 	int ret = -EINVAL;
 
@@ -352,8 +281,6 @@ int pwrdm_add_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm)
 	pr_debug("powerdomain: associating clockdomain %s with powerdomain "
 		 "%s\n", clkdm->name, pwrdm->name);
 
-	write_lock_irqsave(&pwrdm_rwlock, flags);
-
 	for (i = 0; i < PWRDM_MAX_CLKDMS; i++) {
 		if (!pwrdm->pwrdm_clkdms[i])
 			break;
@@ -378,8 +305,6 @@ int pwrdm_add_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm)
 	ret = 0;
 
 pac_exit:
-	write_unlock_irqrestore(&pwrdm_rwlock, flags);
-
 	return ret;
 }
 
@@ -395,7 +320,6 @@ pac_exit:
  */
 int pwrdm_del_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm)
 {
-	unsigned long flags;
 	int ret = -EINVAL;
 	int i;
 
@@ -405,8 +329,6 @@ int pwrdm_del_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm)
 	pr_debug("powerdomain: dissociating clockdomain %s from powerdomain "
 		 "%s\n", clkdm->name, pwrdm->name);
 
-	write_lock_irqsave(&pwrdm_rwlock, flags);
-
 	for (i = 0; i < PWRDM_MAX_CLKDMS; i++)
 		if (pwrdm->pwrdm_clkdms[i] == clkdm)
 			break;
@@ -423,8 +345,6 @@ int pwrdm_del_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm)
 	ret = 0;
 
 pdc_exit:
-	write_unlock_irqrestore(&pwrdm_rwlock, flags);
-
 	return ret;
 }
 
@@ -435,32 +355,24 @@ pdc_exit:
  *
  * Call the supplied function for each clockdomain in the powerdomain
  * 'pwrdm'.  The callback function can return anything but 0 to bail
- * out early from the iterator.  The callback function is called with
- * the pwrdm_rwlock held for reading, so no powerdomain structure
- * manipulation functions should be called from the callback, although
- * hardware powerdomain control functions are fine.  Returns -EINVAL
- * if presented with invalid pointers; or passes along the last return
- * value of the callback function, which should be 0 for success or
- * anything else to indicate failure.
+ * out early from the iterator.  Returns -EINVAL if presented with
+ * invalid pointers; or passes along the last return value of the
+ * callback function, which should be 0 for success or anything else
+ * to indicate failure.
  */
 int pwrdm_for_each_clkdm(struct powerdomain *pwrdm,
 			 int (*fn)(struct powerdomain *pwrdm,
 				   struct clockdomain *clkdm))
 {
-	unsigned long flags;
 	int ret = 0;
 	int i;
 
 	if (!fn)
 		return -EINVAL;
 
-	read_lock_irqsave(&pwrdm_rwlock, flags);
-
 	for (i = 0; i < PWRDM_MAX_CLKDMS && !ret; i++)
 		ret = (*fn)(pwrdm, pwrdm->pwrdm_clkdms[i]);
 
-	read_unlock_irqrestore(&pwrdm_rwlock, flags);
-
 	return ret;
 }
 
diff --git a/arch/arm/plat-omap/include/plat/clockdomain.h b/arch/arm/plat-omap/include/plat/clockdomain.h
index f77ca72..2286971 100644
--- a/arch/arm/plat-omap/include/plat/clockdomain.h
+++ b/arch/arm/plat-omap/include/plat/clockdomain.h
@@ -117,8 +117,6 @@ struct clockdomain {
 };
 
 void clkdm_init(struct clockdomain **clkdms, struct clkdm_autodep *autodeps);
-int clkdm_register(struct clockdomain *clkdm);
-int clkdm_unregister(struct clockdomain *clkdm);
 struct clockdomain *clkdm_lookup(const char *name);
 
 int clkdm_for_each(int (*fn)(struct clockdomain *clkdm, void *user),
diff --git a/arch/arm/plat-omap/include/plat/powerdomain.h b/arch/arm/plat-omap/include/plat/powerdomain.h
index dd5f79d..c590e2f 100644
--- a/arch/arm/plat-omap/include/plat/powerdomain.h
+++ b/arch/arm/plat-omap/include/plat/powerdomain.h
@@ -114,8 +114,6 @@ struct powerdomain {
 
 void pwrdm_init(struct powerdomain **pwrdm_list);
 
-int pwrdm_register(struct powerdomain *pwrdm);
-int pwrdm_unregister(struct powerdomain *pwrdm);
 struct powerdomain *pwrdm_lookup(const char *name);
 
 int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm, void *user),

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 05/10] OMAP clockdomains: add usecounting for wakeup and sleep dependencies
  2010-01-12  1:05 [PATCH 00/10] OMAP2/3/4 clockdomains/powerdomains: split shared dependencies and clean up - for 2.6.34 Paul Walmsley
                   ` (3 preceding siblings ...)
  2010-01-12  1:05 ` [PATCH 04/10] OMAP clockdomain/powerdomain: remove runtime register/unregister Paul Walmsley
@ 2010-01-12  1:05 ` Paul Walmsley
  2010-01-21  4:45   ` Paul Walmsley
  2010-01-12  1:05 ` [PATCH 06/10] OMAP2/3/4 clockdomain: add clkdm_clear_all_{wkdep, sleepdep}s() Paul Walmsley
                   ` (4 subsequent siblings)
  9 siblings, 1 reply; 14+ messages in thread
From: Paul Walmsley @ 2010-01-12  1:05 UTC (permalink / raw)
  To: linux-arm-kernel

Add usecounting for wakeup and sleep dependencies.  In the current
situation, if several functions add dependencies on the same clockdomains,
when the first dependency removal function is called, the dependency will
be incorrectly removed from the hardware.

Signed-off-by: Paul Walmsley <paul@pwsan.com>
---
 arch/arm/mach-omap2/clockdomain.c             |  150 ++++++++++++++++++++++---
 arch/arm/plat-omap/include/plat/clockdomain.h |    6 +
 2 files changed, 135 insertions(+), 21 deletions(-)

diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c
index 2af9996..d039df7 100644
--- a/arch/arm/mach-omap2/clockdomain.c
+++ b/arch/arm/mach-omap2/clockdomain.c
@@ -113,7 +113,6 @@ static struct clkdm_dep *_clkdm_deps_lookup(struct clockdomain *clkdm,
 		return ERR_PTR(-EINVAL);
 
 	for (cd = deps; cd->clkdm_name; cd++) {
-
 		if (!omap_chip_is(cd->omap_chip))
 			continue;
 
@@ -122,7 +121,6 @@ static struct clkdm_dep *_clkdm_deps_lookup(struct clockdomain *clkdm,
 
 		if (cd->clkdm == clkdm)
 			break;
-
 	}
 
 	if (!cd->clkdm_name)
@@ -254,6 +252,96 @@ static void _omap2_clkdm_set_hwsup(struct clockdomain *clkdm, int enable)
 
 }
 
+/**
+ * _init_wkdep_usecount - initialize wkdep usecounts to match hardware
+ * @clkdm: clockdomain to initialize wkdep usecounts
+ *
+ * Initialize the wakeup dependency usecount variables for clockdomain @clkdm.
+ * If a wakeup dependency is present in the hardware, the usecount will be
+ * set to 1; otherwise, it will be set to 0.  Software should clear all
+ * software wakeup dependencies prior to calling this function if it wishes
+ * to ensure that all usecounts start at 0.  No return value.
+ */
+static void _init_wkdep_usecount(struct clockdomain *clkdm)
+{
+	u32 v;
+	struct clkdm_dep *cd;
+
+	if (!clkdm->wkdep_srcs)
+		return;
+
+	for (cd = clkdm->wkdep_srcs; cd->clkdm_name; cd++) {
+		if (!omap_chip_is(cd->omap_chip))
+			continue;
+
+		if (!cd->clkdm && cd->clkdm_name)
+			cd->clkdm = _clkdm_lookup(cd->clkdm_name);
+
+		if (!cd->clkdm) {
+			WARN(!cd->clkdm, "clockdomain: %s: wkdep clkdm %s not "
+			     "found\n", clkdm->name, cd->clkdm_name);
+			continue;
+		}
+
+		v = prm_read_mod_bits_shift(clkdm->pwrdm.ptr->prcm_offs,
+					    PM_WKDEP,
+					    (1 << cd->clkdm->dep_bit));
+
+		if (v)
+			pr_debug("clockdomain: %s: wakeup dependency already "
+				 "set to wake up when %s wakes\n",
+				 clkdm->name, cd->clkdm->name);
+
+		atomic_set(&cd->wkdep_usecount, (v) ? 1 : 0);
+	}
+}
+
+/**
+ * _init_sleepdep_usecount - initialize sleepdep usecounts to match hardware
+ * @clkdm: clockdomain to initialize sleepdep usecounts
+ *
+ * Initialize the sleep dependency usecount variables for clockdomain @clkdm.
+ * If a sleep dependency is present in the hardware, the usecount will be
+ * set to 1; otherwise, it will be set to 0.  Software should clear all
+ * software sleep dependencies prior to calling this function if it wishes
+ * to ensure that all usecounts start at 0.  No return value.
+ */
+static void _init_sleepdep_usecount(struct clockdomain *clkdm)
+{
+	u32 v;
+	struct clkdm_dep *cd;
+
+	if (!cpu_is_omap34xx())
+		return;
+
+	if (!clkdm->sleepdep_srcs)
+		return;
+
+	for (cd = clkdm->sleepdep_srcs; cd->clkdm_name; cd++) {
+		if (!omap_chip_is(cd->omap_chip))
+			continue;
+
+		if (!cd->clkdm && cd->clkdm_name)
+			cd->clkdm = _clkdm_lookup(cd->clkdm_name);
+
+		if (!cd->clkdm) {
+			WARN(!cd->clkdm, "clockdomain: %s: sleepdep clkdm %s "
+			     "not found\n", clkdm->name, cd->clkdm_name);
+			continue;
+		}
+
+		v = prm_read_mod_bits_shift(clkdm->pwrdm.ptr->prcm_offs,
+					    OMAP3430_CM_SLEEPDEP,
+					    (1 << cd->clkdm->dep_bit));
+
+		if (v)
+			pr_debug("clockdomain: %s: sleep dependency already "
+				 "set to prevent from idling until %s "
+				 "idles\n", clkdm->name, cd->clkdm->name);
+
+		atomic_set(&cd->sleepdep_usecount, (v) ? 1 : 0);
+	}
+};
 
 /* Public functions */
 
@@ -272,6 +360,7 @@ void clkdm_init(struct clockdomain **clkdms,
 		struct clkdm_autodep *init_autodeps)
 {
 	struct clockdomain **c = NULL;
+	struct clockdomain *clkdm;
 	struct clkdm_autodep *autodep = NULL;
 
 	if (clkdms)
@@ -282,6 +371,15 @@ void clkdm_init(struct clockdomain **clkdms,
 	if (autodeps)
 		for (autodep = autodeps; autodep->clkdm.ptr; autodep++)
 			_autodep_lookup(autodep);
+
+	/*
+	 * Ensure that the *dep_usecount registers reflect the current
+	 * state of the PRCM.
+	 */
+	list_for_each_entry(clkdm, &clkdm_list, node) {
+		_init_wkdep_usecount(clkdm);
+		_init_sleepdep_usecount(clkdm);
+	}
 }
 
 /**
@@ -387,11 +485,13 @@ int clkdm_add_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
 		return PTR_ERR(cd);
 	}
 
-	pr_debug("clockdomain: hardware will wake up %s when %s wakes up\n",
-		 clkdm1->name, clkdm2->name);
+	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);
 
-	prm_set_mod_reg_bits((1 << clkdm2->dep_bit),
-			     clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP);
+		prm_set_mod_reg_bits((1 << clkdm2->dep_bit),
+				     clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP);
+	}
 
 	return 0;
 }
@@ -420,11 +520,13 @@ int clkdm_del_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
 		return PTR_ERR(cd);
 	}
 
-	pr_debug("clockdomain: hardware will no longer wake up %s after %s "
-		 "wakes up\n", clkdm1->name, clkdm2->name);
+	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);
 
-	prm_clear_mod_reg_bits((1 << clkdm2->dep_bit),
-			       clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP);
+		prm_clear_mod_reg_bits((1 << clkdm2->dep_bit),
+				       clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP);
+	}
 
 	return 0;
 }
@@ -457,6 +559,7 @@ int clkdm_read_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
 		return PTR_ERR(cd);
 	}
 
+	/* XXX It's faster to return the atomic wkdep_usecount */
 	return prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP,
 				       (1 << clkdm2->dep_bit));
 }
@@ -491,12 +594,14 @@ int clkdm_add_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
 		return PTR_ERR(cd);
 	}
 
-	pr_debug("clockdomain: will prevent %s from sleeping if %s is active\n",
-		 clkdm1->name, clkdm2->name);
+	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);
 
-	cm_set_mod_reg_bits((1 << clkdm2->dep_bit),
-			    clkdm1->pwrdm.ptr->prcm_offs,
-			    OMAP3430_CM_SLEEPDEP);
+		cm_set_mod_reg_bits((1 << clkdm2->dep_bit),
+				    clkdm1->pwrdm.ptr->prcm_offs,
+				    OMAP3430_CM_SLEEPDEP);
+	}
 
 	return 0;
 }
@@ -531,12 +636,15 @@ int clkdm_del_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
 		return PTR_ERR(cd);
 	}
 
-	pr_debug("clockdomain: will no longer prevent %s from sleeping if "
-		 "%s is active\n", clkdm1->name, clkdm2->name);
+	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);
 
-	cm_clear_mod_reg_bits((1 << clkdm2->dep_bit),
-			      clkdm1->pwrdm.ptr->prcm_offs,
-			      OMAP3430_CM_SLEEPDEP);
+		cm_clear_mod_reg_bits((1 << clkdm2->dep_bit),
+				      clkdm1->pwrdm.ptr->prcm_offs,
+				      OMAP3430_CM_SLEEPDEP);
+	}
 
 	return 0;
 }
@@ -575,12 +683,12 @@ int clkdm_read_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
 		return PTR_ERR(cd);
 	}
 
+	/* XXX It's faster to return the atomic sleepdep_usecount */
 	return prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs,
 				       OMAP3430_CM_SLEEPDEP,
 				       (1 << clkdm2->dep_bit));
 }
 
-
 /**
  * omap2_clkdm_clktrctrl_read - read the clkdm's current state transition mode
  * @clk: struct clk * of a clockdomain
diff --git a/arch/arm/plat-omap/include/plat/clockdomain.h b/arch/arm/plat-omap/include/plat/clockdomain.h
index 2286971..192cc95 100644
--- a/arch/arm/plat-omap/include/plat/clockdomain.h
+++ b/arch/arm/plat-omap/include/plat/clockdomain.h
@@ -70,6 +70,12 @@ struct clkdm_dep {
 	/* Clockdomain pointer - resolved by the clockdomain code */
 	struct clockdomain *clkdm;
 
+	/* Number of wakeup dependencies causing this clkdm to wake  */
+	atomic_t wkdep_usecount;
+
+	/* Number of sleep dependencies that could prevent clkdm from idle */
+	atomic_t sleepdep_usecount;
+
 	/* Flags to mark OMAP chip restrictions, etc. */
 	const struct omap_chip_id omap_chip;
 

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 06/10] OMAP2/3/4 clockdomain: add clkdm_clear_all_{wkdep, sleepdep}s()
  2010-01-12  1:05 [PATCH 00/10] OMAP2/3/4 clockdomains/powerdomains: split shared dependencies and clean up - for 2.6.34 Paul Walmsley
                   ` (4 preceding siblings ...)
  2010-01-12  1:05 ` [PATCH 05/10] OMAP clockdomains: add usecounting for wakeup and sleep dependencies Paul Walmsley
@ 2010-01-12  1:05 ` Paul Walmsley
  2010-01-12  1:05 ` [PATCH 07/10] OMAP powerdomain/PM: use symbolic constants for the max number of power states Paul Walmsley
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 14+ messages in thread
From: Paul Walmsley @ 2010-01-12  1:05 UTC (permalink / raw)
  To: linux-arm-kernel

Add clkdm_clear_all_wkdeps() and clkdm_clear_all_sleepdeps().  These functions
provide a fast way for code to clear all hardware clockdomain dependencies,
since accesses to these registers can be quite slow.  These functions
are currently targeted for use by PM branch code.

Signed-off-by: Paul Walmsley <paul@pwsan.com>
Cc: Kevin Hilman <khilman@deeprootsystems.com>
---
 arch/arm/mach-omap2/clockdomain.c             |   68 +++++++++++++++++++++++++
 arch/arm/plat-omap/include/plat/clockdomain.h |    2 +
 2 files changed, 70 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c
index d039df7..f44d9ea 100644
--- a/arch/arm/mach-omap2/clockdomain.c
+++ b/arch/arm/mach-omap2/clockdomain.c
@@ -565,6 +565,38 @@ int clkdm_read_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
 }
 
 /**
+ * clkdm_clear_all_wkdeps - remove all wakeup dependencies from target clkdm
+ * @clkdm: struct clockdomain * to remove all wakeup dependencies from
+ *
+ * Remove all inter-clockdomain wakeup dependencies that could cause
+ * @clkdm to wake.  Intended to be used during boot to initialize the
+ * PRCM to a known state, after all clockdomains are put into swsup idle
+ * and woken up.  Returns -EINVAL if @clkdm pointer is invalid, or
+ * 0 upon success.
+ */
+int clkdm_clear_all_wkdeps(struct clockdomain *clkdm)
+{
+	struct clkdm_dep *cd;
+	u32 mask = 0;
+
+	if (!clkdm)
+		return -EINVAL;
+
+	for (cd = clkdm->wkdep_srcs; cd->clkdm_name; cd++) {
+		if (!omap_chip_is(cd->omap_chip))
+			continue;
+
+		/* PRM accesses are slow, so minimize them */
+		mask |= 1 << cd->clkdm->dep_bit;
+		atomic_set(&cd->wkdep_usecount, 0);
+	}
+
+	prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs, PM_WKDEP);
+
+	return 0;
+}
+
+/**
  * clkdm_add_sleepdep - add a sleep dependency from clkdm2 to clkdm1
  * @clkdm1: prevent this struct clockdomain * from sleeping (dependent)
  * @clkdm2: when this struct clockdomain * is active (source)
@@ -690,6 +722,42 @@ int clkdm_read_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
 }
 
 /**
+ * clkdm_clear_all_sleepdeps - remove all sleep dependencies from target clkdm
+ * @clkdm: struct clockdomain * to remove all sleep dependencies from
+ *
+ * Remove all inter-clockdomain sleep dependencies that could prevent
+ * @clkdm from idling.	Intended to be used during boot to initialize the
+ * PRCM to a known state, after all clockdomains are put into swsup idle
+ * and woken up.  Returns -EINVAL if @clkdm pointer is invalid, or
+ * 0 upon success.
+ */
+int clkdm_clear_all_sleepdeps(struct clockdomain *clkdm)
+{
+	struct clkdm_dep *cd;
+	u32 mask = 0;
+
+	if (!cpu_is_omap34xx())
+		return -EINVAL;
+
+	if (!clkdm)
+		return -EINVAL;
+
+	for (cd = clkdm->sleepdep_srcs; cd->clkdm_name; cd++) {
+		if (!omap_chip_is(cd->omap_chip))
+			continue;
+
+		/* PRM accesses are slow, so minimize them */
+		mask |= 1 << cd->clkdm->dep_bit;
+		atomic_set(&cd->sleepdep_usecount, 0);
+	}
+
+	prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs,
+			       OMAP3430_CM_SLEEPDEP);
+
+	return 0;
+}
+
+/**
  * omap2_clkdm_clktrctrl_read - read the clkdm's current state transition mode
  * @clk: struct clk * of a clockdomain
  *
diff --git a/arch/arm/plat-omap/include/plat/clockdomain.h b/arch/arm/plat-omap/include/plat/clockdomain.h
index 192cc95..45b5deb 100644
--- a/arch/arm/plat-omap/include/plat/clockdomain.h
+++ b/arch/arm/plat-omap/include/plat/clockdomain.h
@@ -132,9 +132,11 @@ struct powerdomain *clkdm_get_pwrdm(struct clockdomain *clkdm);
 int clkdm_add_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
 int clkdm_del_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
 int clkdm_read_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
+int clkdm_clear_all_wkdeps(struct clockdomain *clkdm);
 int clkdm_add_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
 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 omap2_clkdm_allow_idle(struct clockdomain *clkdm);
 void omap2_clkdm_deny_idle(struct clockdomain *clkdm);

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 07/10] OMAP powerdomain/PM: use symbolic constants for the max number of power states
  2010-01-12  1:05 [PATCH 00/10] OMAP2/3/4 clockdomains/powerdomains: split shared dependencies and clean up - for 2.6.34 Paul Walmsley
                   ` (5 preceding siblings ...)
  2010-01-12  1:05 ` [PATCH 06/10] OMAP2/3/4 clockdomain: add clkdm_clear_all_{wkdep, sleepdep}s() Paul Walmsley
@ 2010-01-12  1:05 ` Paul Walmsley
  2010-01-12  1:05 ` [PATCH 08/10] OMAP powerdomain: rearrange struct powerdomain to save some memory Paul Walmsley
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 14+ messages in thread
From: Paul Walmsley @ 2010-01-12  1:05 UTC (permalink / raw)
  To: linux-arm-kernel

Replace some bare constants with symbolic constants.

Signed-off-by: Paul Walmsley <paul@pwsan.com>
Cc: Kevin Hilman <khilman@deeprootsystems.com>
---
 arch/arm/mach-omap2/powerdomain.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
index 411361f..df6446a 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -122,7 +122,7 @@ static int _pwrdm_register(struct powerdomain *pwrdm)
 	list_add(&pwrdm->node, &pwrdm_list);
 
 	/* Initialize the powerdomain's state counter */
-	for (i = 0; i < 4; i++)
+	for (i = 0; i < PWRDM_MAX_PWRSTS; i++)
 		pwrdm->state_counter[i] = 0;
 
 	pwrdm_wait_transition(pwrdm);

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 08/10] OMAP powerdomain: rearrange struct powerdomain to save some memory
  2010-01-12  1:05 [PATCH 00/10] OMAP2/3/4 clockdomains/powerdomains: split shared dependencies and clean up - for 2.6.34 Paul Walmsley
                   ` (6 preceding siblings ...)
  2010-01-12  1:05 ` [PATCH 07/10] OMAP powerdomain/PM: use symbolic constants for the max number of power states Paul Walmsley
@ 2010-01-12  1:05 ` Paul Walmsley
  2010-01-12  1:05 ` [PATCH 09/10] OMAP powerdomain: remove pwrdm_clk_state_switch Paul Walmsley
  2010-01-12  1:05 ` [PATCH 10/10] OMAP clockdomain/powerdomain: improve documentation Paul Walmsley
  9 siblings, 0 replies; 14+ messages in thread
From: Paul Walmsley @ 2010-01-12  1:05 UTC (permalink / raw)
  To: linux-arm-kernel

This patch rearranges the order of structure members in struct powerdomain
to avoid wasting memory due to alignment restrictions.

Signed-off-by: Paul Walmsley <paul@pwsan.com>
---
 arch/arm/plat-omap/include/plat/powerdomain.h |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/arm/plat-omap/include/plat/powerdomain.h b/arch/arm/plat-omap/include/plat/powerdomain.h
index c590e2f..87e13f8 100644
--- a/arch/arm/plat-omap/include/plat/powerdomain.h
+++ b/arch/arm/plat-omap/include/plat/powerdomain.h
@@ -73,12 +73,12 @@ struct powerdomain {
 	/* Powerdomain name */
 	const char *name;
 
-	/* the address offset from CM_BASE/PRM_BASE */
-	const s16 prcm_offs;
-
 	/* Used to represent the OMAP chip types containing this pwrdm */
 	const struct omap_chip_id omap_chip;
 
+	/* the address offset from CM_BASE/PRM_BASE */
+	const s16 prcm_offs;
+
 	/* Possible powerdomain power states */
 	const u8 pwrsts;
 

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 09/10] OMAP powerdomain: remove pwrdm_clk_state_switch
  2010-01-12  1:05 [PATCH 00/10] OMAP2/3/4 clockdomains/powerdomains: split shared dependencies and clean up - for 2.6.34 Paul Walmsley
                   ` (7 preceding siblings ...)
  2010-01-12  1:05 ` [PATCH 08/10] OMAP powerdomain: rearrange struct powerdomain to save some memory Paul Walmsley
@ 2010-01-12  1:05 ` Paul Walmsley
  2010-01-12  1:05 ` [PATCH 10/10] OMAP clockdomain/powerdomain: improve documentation Paul Walmsley
  9 siblings, 0 replies; 14+ messages in thread
From: Paul Walmsley @ 2010-01-12  1:05 UTC (permalink / raw)
  To: linux-arm-kernel

Nothing calls pwrdm_clk_state_switch(), and the function that seems to be
its ideal use case calls pwrdm_clkdm_state_switch(clk->clkdm), so remove it.

Signed-off-by: Paul Walmsley <paul@pwsan.com>
Cc: Tero Kristo <tero.kristo@nokia.com>
Cc: Kevin Hilman <khilman@deeprootsystems.com>
---
 arch/arm/mach-omap2/powerdomain.c |    6 ------
 1 files changed, 0 insertions(+), 6 deletions(-)

diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
index df6446a..9d4b8f5 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -928,12 +928,6 @@ int pwrdm_clkdm_state_switch(struct clockdomain *clkdm)
 
 	return -EINVAL;
 }
-int pwrdm_clk_state_switch(struct clk *clk)
-{
-	if (clk != NULL && clk->clkdm != NULL)
-		return pwrdm_clkdm_state_switch(clk->clkdm);
-	return -EINVAL;
-}
 
 int pwrdm_pre_transition(void)
 {

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 10/10] OMAP clockdomain/powerdomain: improve documentation
  2010-01-12  1:05 [PATCH 00/10] OMAP2/3/4 clockdomains/powerdomains: split shared dependencies and clean up - for 2.6.34 Paul Walmsley
                   ` (8 preceding siblings ...)
  2010-01-12  1:05 ` [PATCH 09/10] OMAP powerdomain: remove pwrdm_clk_state_switch Paul Walmsley
@ 2010-01-12  1:05 ` Paul Walmsley
  9 siblings, 0 replies; 14+ messages in thread
From: Paul Walmsley @ 2010-01-12  1:05 UTC (permalink / raw)
  To: linux-arm-kernel

This patch only affects documentation; no functional changes are
included.

Clean up comments in the current clockdomain, powerdomain code and
header files.  This mostly involves conversion to kerneldoc format,
although some clarifications are also included.

Signed-off-by: Paul Walmsley <paul@pwsan.com>
---
 arch/arm/mach-omap2/clockdomain.c             |   65 ++++++-----
 arch/arm/mach-omap2/powerdomain.c             |  149 +++++++++++++------------
 arch/arm/plat-omap/include/plat/clockdomain.h |   87 +++++++--------
 arch/arm/plat-omap/include/plat/powerdomain.h |   40 +++----
 4 files changed, 167 insertions(+), 174 deletions(-)

diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c
index f44d9ea..2f68c10 100644
--- a/arch/arm/mach-omap2/clockdomain.c
+++ b/arch/arm/mach-omap2/clockdomain.c
@@ -351,10 +351,10 @@ static void _init_sleepdep_usecount(struct clockdomain *clkdm)
  * @init_autodeps: optional pointer to an array of autodeps to register
  *
  * Set up internal state.  If a pointer to an array of clockdomains
- * was supplied, loop through the list of clockdomains, register all
- * that are available on the current platform. Similarly, if a pointer
- * to an array of clockdomain autodependencies was provided, register
- * those.  No return value.
+ * @clkdms was supplied, loop through the list of clockdomains,
+ * register all that are available on the current platform. Similarly,
+ * if a pointer to an array of clockdomain autodependencies
+ * @init_autodeps was provided, register those.  No return value.
  */
 void clkdm_init(struct clockdomain **clkdms,
 		struct clkdm_autodep *init_autodeps)
@@ -386,8 +386,8 @@ void clkdm_init(struct clockdomain **clkdms,
  * clkdm_lookup - look up a clockdomain by name, return a pointer
  * @name: name of clockdomain
  *
- * Find a registered clockdomain by its name.  Returns a pointer to the
- * struct clockdomain if found, or NULL otherwise.
+ * Find a registered clockdomain by its name @name.  Returns a pointer
+ * to the struct clockdomain if found, or NULL otherwise.
  */
 struct clockdomain *clkdm_lookup(const char *name)
 {
@@ -412,8 +412,8 @@ struct clockdomain *clkdm_lookup(const char *name)
  * clkdm_for_each - call function on each registered clockdomain
  * @fn: callback function *
  *
- * Call the supplied function for each registered clockdomain.
- * The callback function can return anything but 0 to bail
+ * Call the supplied function @fn for each registered clockdomain.
+ * The callback function @fn can return anything but 0 to bail
  * out early from the iterator.  The callback function is called with
  * the clkdm_mutex held, so no clockdomain structure manipulation
  * functions should be called from the callback, although hardware
@@ -446,7 +446,7 @@ int clkdm_for_each(int (*fn)(struct clockdomain *clkdm, void *user),
  * @clkdm: struct clockdomain *
  *
  * Return a pointer to the struct powerdomain that the specified clockdomain
- * 'clkdm' exists in, or returns NULL if clkdm argument is NULL.
+ * @clkdm exists in, or returns NULL if @clkdm is NULL.
  */
 struct powerdomain *clkdm_get_pwrdm(struct clockdomain *clkdm)
 {
@@ -759,10 +759,10 @@ int clkdm_clear_all_sleepdeps(struct clockdomain *clkdm)
 
 /**
  * omap2_clkdm_clktrctrl_read - read the clkdm's current state transition mode
- * @clk: struct clk * of a clockdomain
+ * @clkdm: struct clkdm * of a clockdomain
  *
- * Return the clockdomain's current state transition mode from the
- * corresponding domain OMAP2_CM_CLKSTCTRL register.	Returns -EINVAL if clk
+ * Return the clockdomain @clkdm current state transition mode from the
+ * corresponding domain CM_CLKSTCTRL register.	Returns -EINVAL if @clkdm
  * is NULL or the current mode upon success.
  */
 static int omap2_clkdm_clktrctrl_read(struct clockdomain *clkdm)
@@ -784,7 +784,7 @@ static int omap2_clkdm_clktrctrl_read(struct clockdomain *clkdm)
  * @clkdm: struct clockdomain *
  *
  * Instruct the CM to force a sleep transition on the specified
- * clockdomain 'clkdm'.  Returns -EINVAL if clk is NULL or if
+ * clockdomain @clkdm.  Returns -EINVAL if @clkdm is NULL or if
  * clockdomain does not support software-initiated sleep; 0 upon
  * success.
  */
@@ -828,7 +828,7 @@ int omap2_clkdm_sleep(struct clockdomain *clkdm)
  * @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 @clkdm.  Returns -EINVAL if @clkdm is NULL or if the
  * clockdomain does not support software-controlled wakeup; 0 upon
  * success.
  */
@@ -871,7 +871,7 @@ int omap2_clkdm_wakeup(struct clockdomain *clkdm)
  * omap2_clkdm_allow_idle - enable hwsup idle transitions for clkdm
  * @clkdm: struct clockdomain *
  *
- * Allow the hardware to automatically switch the clockdomain into
+ * 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
@@ -904,8 +904,8 @@ void omap2_clkdm_allow_idle(struct clockdomain *clkdm)
  * @clkdm: struct clockdomain *
  *
  * Prevent the hardware from automatically switching the clockdomain
- * into inactive or idle states.  If the clockdomain has downstream
- * clocks enabled in the clock framework, wkdep/sleepdep
+ * @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 omap2_clkdm_deny_idle(struct clockdomain *clkdm)
@@ -936,14 +936,14 @@ void omap2_clkdm_deny_idle(struct clockdomain *clkdm)
  * @clkdm: struct clockdomain *
  * @clk: struct clk * of the enabled downstream clock
  *
- * Increment the usecount of this clockdomain 'clkdm' and ensure that
- * it is awake.  Intended to be called by clk_enable() code.  If the
- * clockdomain is in software-supervised idle mode, force the
- * clockdomain to wake.  If the clockdomain is in hardware-supervised
- * idle mode, add clkdm-pwrdm autodependencies, to ensure that devices
- * in the clockdomain can be read from/written to by on-chip processors.
- * Returns -EINVAL if passed null pointers; returns 0 upon success or
- * if the clockdomain is in hwsup idle mode.
+ * Increment the usecount of the clockdomain @clkdm and ensure that it
+ * is awake before @clk is enabled.  Intended to be called by
+ * clk_enable() code.  If the clockdomain is in software-supervised
+ * idle mode, force the clockdomain to wake.  If the clockdomain is in
+ * hardware-supervised idle mode, add clkdm-pwrdm autodependencies, to
+ * ensure that devices in the clockdomain can be read from/written to
+ * by on-chip processors.  Returns -EINVAL if passed null pointers;
+ * returns 0 upon success or if the clockdomain is in hwsup idle mode.
  */
 int omap2_clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk)
 {
@@ -988,13 +988,14 @@ int omap2_clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk)
  * @clkdm: struct clockdomain *
  * @clk: struct clk * of the disabled downstream clock
  *
- * Decrement the usecount of this clockdomain 'clkdm'. Intended to be
- * called by clk_disable() code.  If the usecount goes to 0, put the
- * clockdomain to sleep (software-supervised mode) or remove the
- * clkdm-pwrdm autodependencies (hardware-supervised mode).  Returns
- * -EINVAL if passed null pointers; -ERANGE if the clkdm usecount
- * underflows and debugging is enabled; or returns 0 upon success or
- * if the clockdomain is in hwsup idle mode.
+ * Decrement the usecount of this clockdomain @clkdm when @clk is
+ * disabled.  Intended to be called by clk_disable() code.  If the
+ * clockdomain usecount goes to 0, put the clockdomain to sleep
+ * (software-supervised mode) or remove the clkdm autodependencies
+ * (hardware-supervised mode).  Returns -EINVAL if passed null
+ * pointers; -ERANGE if the @clkdm usecount underflows and debugging
+ * is enabled; or returns 0 upon success or if the clockdomain is in
+ * hwsup idle mode.
  */
 int omap2_clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk)
 {
diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
index 9d4b8f5..dc03289 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -185,11 +185,13 @@ static int _pwrdm_post_transition_cb(struct powerdomain *pwrdm, void *unused)
 
 /**
  * pwrdm_init - set up the powerdomain layer
+ * @pwrdm_list: array of struct powerdomain pointers to register
  *
- * Loop through the list of powerdomains, registering all that are
- * available on the current CPU. If pwrdm_list is supplied and not
- * null, all of the referenced powerdomains will be registered.  No
- * return value.
+ * Loop through the array of powerdomains @pwrdm_list, registering all
+ * that are available on the current CPU. If pwrdm_list is supplied
+ * and not null, all of the referenced powerdomains will be
+ * registered.  No return value.  XXX pwrdm_list is not really a
+ * "list"; it is an array.  Rename appropriately.
  */
 void pwrdm_init(struct powerdomain **pwrdm_list)
 {
@@ -217,8 +219,8 @@ void pwrdm_init(struct powerdomain **pwrdm_list)
  * pwrdm_lookup - look up a powerdomain by name, return a pointer
  * @name: name of powerdomain
  *
- * Find a registered powerdomain by its name.  Returns a pointer to the
- * struct powerdomain if found, or NULL otherwise.
+ * Find a registered powerdomain by its name @name.  Returns a pointer
+ * to the struct powerdomain if found, or NULL otherwise.
  */
 struct powerdomain *pwrdm_lookup(const char *name)
 {
@@ -236,11 +238,11 @@ struct powerdomain *pwrdm_lookup(const char *name)
  * pwrdm_for_each - call function on each registered clockdomain
  * @fn: callback function *
  *
- * Call the supplied function for each registered powerdomain.  The
- * callback function can return anything but 0 to bail out early from
- * the iterator.  Returns the last return value of the callback function, which
- * should be 0 for success or anything else to indicate failure; or -EINVAL if
- * the function pointer is null.
+ * Call the supplied function @fn for each registered powerdomain.
+ * The callback function @fn can return anything but 0 to bail out
+ * early from the iterator.  Returns the last return value of the
+ * callback function, which should be 0 for success or anything else
+ * to indicate failure; or -EINVAL if the function pointer is null.
  */
 int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm, void *user),
 		   void *user)
@@ -265,7 +267,7 @@ int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm, void *user),
  * @pwrdm: struct powerdomain * to add the clockdomain to
  * @clkdm: struct clockdomain * to associate with a powerdomain
  *
- * Associate the clockdomain 'clkdm' with a powerdomain 'pwrdm'.  This
+ * Associate the clockdomain @clkdm with a powerdomain @pwrdm.  This
  * enables the use of pwrdm_for_each_clkdm().  Returns -EINVAL if
  * presented with invalid pointers; -ENOMEM if memory could not be allocated;
  * or 0 upon success.
@@ -313,10 +315,10 @@ pac_exit:
  * @pwrdm: struct powerdomain * to add the clockdomain to
  * @clkdm: struct clockdomain * to associate with a powerdomain
  *
- * Dissociate the clockdomain 'clkdm' from the powerdomain
- * 'pwrdm'. Returns -EINVAL if presented with invalid pointers;
- * -ENOENT if the clkdm was not associated with the powerdomain, or 0
- * upon success.
+ * Dissociate the clockdomain @clkdm from the powerdomain
+ * @pwrdm. Returns -EINVAL if presented with invalid pointers; -ENOENT
+ * if @clkdm was not associated with the powerdomain, or 0 upon
+ * success.
  */
 int pwrdm_del_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm)
 {
@@ -353,8 +355,8 @@ pdc_exit:
  * @pwrdm: struct powerdomain * to iterate over
  * @fn: callback function *
  *
- * Call the supplied function for each clockdomain in the powerdomain
- * 'pwrdm'.  The callback function can return anything but 0 to bail
+ * Call the supplied function @fn for each clockdomain in the powerdomain
+ * @pwrdm.  The callback function can return anything but 0 to bail
  * out early from the iterator.  Returns -EINVAL if presented with
  * invalid pointers; or passes along the last return value of the
  * callback function, which should be 0 for success or anything else
@@ -380,7 +382,7 @@ int pwrdm_for_each_clkdm(struct powerdomain *pwrdm,
  * pwrdm_get_mem_bank_count - get number of memory banks in this powerdomain
  * @pwrdm: struct powerdomain *
  *
- * Return the number of controllable memory banks in powerdomain pwrdm,
+ * Return the number of controllable memory banks in powerdomain @pwrdm,
  * starting with 1.  Returns -EINVAL if the powerdomain pointer is null.
  */
 int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm)
@@ -396,7 +398,7 @@ int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm)
  * @pwrdm: struct powerdomain * to set
  * @pwrst: one of the PWRDM_POWER_* macros
  *
- * Set the powerdomain pwrdm's next power state to pwrst.  The powerdomain
+ * Set the powerdomain @pwrdm's next power state to @pwrst.  The powerdomain
  * may not enter this state immediately if the preconditions for this state
  * have not been satisfied.  Returns -EINVAL if the powerdomain pointer is
  * null or if the power state is invalid for the powerdomin, or returns 0
@@ -424,7 +426,7 @@ int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
  * pwrdm_read_next_pwrst - get next powerdomain power state
  * @pwrdm: struct powerdomain * to get power state
  *
- * Return the powerdomain pwrdm's next power state.  Returns -EINVAL
+ * Return the powerdomain @pwrdm's next power state.  Returns -EINVAL
  * if the powerdomain pointer is null or returns the next power state
  * upon success.
  */
@@ -441,7 +443,7 @@ int pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
  * pwrdm_read_pwrst - get current powerdomain power state
  * @pwrdm: struct powerdomain * to get power state
  *
- * Return the powerdomain pwrdm's current power state.	Returns -EINVAL
+ * Return the powerdomain @pwrdm's current power state.	Returns -EINVAL
  * if the powerdomain pointer is null or returns the current power state
  * upon success.
  */
@@ -458,7 +460,7 @@ int pwrdm_read_pwrst(struct powerdomain *pwrdm)
  * pwrdm_read_prev_pwrst - get previous powerdomain power state
  * @pwrdm: struct powerdomain * to get previous power state
  *
- * Return the powerdomain pwrdm's previous power state.  Returns -EINVAL
+ * Return the powerdomain @pwrdm's previous power state.  Returns -EINVAL
  * if the powerdomain pointer is null or returns the previous power state
  * upon success.
  */
@@ -476,11 +478,11 @@ int pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
  * @pwrdm: struct powerdomain * to set
  * @pwrst: one of the PWRDM_POWER_* macros
  *
- * Set the next power state that the logic portion of the powerdomain
- * pwrdm will enter when the powerdomain enters retention.  This will
- * be either RETENTION or OFF, if supported.  Returns -EINVAL if the
- * powerdomain pointer is null or the target power state is not not
- * supported, or returns 0 upon success.
+ * Set the next power state @pwrst that the logic portion of the
+ * powerdomain @pwrdm will enter when the powerdomain enters retention.
+ * This will be either RETENTION or OFF, if supported.  Returns
+ * -EINVAL if the powerdomain pointer is null or the target power
+ * state is not not supported, or returns 0 upon success.
  */
 int pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst)
 {
@@ -512,13 +514,14 @@ int pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst)
  * @bank: memory bank number to set (0-3)
  * @pwrst: one of the PWRDM_POWER_* macros
  *
- * Set the next power state that memory bank x of the powerdomain
- * pwrdm will enter when the powerdomain enters the ON state.  Bank
- * will be a number from 0 to 3, and represents different types of
- * memory, depending on the powerdomain.  Returns -EINVAL if the
- * powerdomain pointer is null or the target power state is not not
- * supported for this memory bank, -EEXIST if the target memory bank
- * does not exist or is not controllable, or returns 0 upon success.
+ * Set the next power state @pwrst that memory bank @bank of the
+ * powerdomain @pwrdm will enter when the powerdomain enters the ON
+ * state.  @bank will be a number from 0 to 3, and represents different
+ * types of memory, depending on the powerdomain.  Returns -EINVAL if
+ * the powerdomain pointer is null or the target power state is not
+ * not supported for this memory bank, -EEXIST if the target memory
+ * bank does not exist or is not controllable, or returns 0 upon
+ * success.
  */
 int pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, u8 pwrst)
 {
@@ -575,14 +578,15 @@ int pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, u8 pwrst)
  * @bank: memory bank number to set (0-3)
  * @pwrst: one of the PWRDM_POWER_* macros
  *
- * Set the next power state that memory bank x of the powerdomain
- * pwrdm will enter when the powerdomain enters the RETENTION state.
- * Bank will be a number from 0 to 3, and represents different types
- * of memory, depending on the powerdomain.  pwrst will be either
- * RETENTION or OFF, if supported. Returns -EINVAL if the powerdomain
- * pointer is null or the target power state is not not supported for
- * this memory bank, -EEXIST if the target memory bank does not exist
- * or is not controllable, or returns 0 upon success.
+ * Set the next power state @pwrst that memory bank @bank of the
+ * powerdomain @pwrdm will enter when the powerdomain enters the
+ * RETENTION state.  Bank will be a number from 0 to 3, and represents
+ * different types of memory, depending on the powerdomain.  @pwrst
+ * will be either RETENTION or OFF, if supported.  Returns -EINVAL if
+ * the powerdomain pointer is null or the target power state is not
+ * not supported for this memory bank, -EEXIST if the target memory
+ * bank does not exist or is not controllable, or returns 0 upon
+ * success.
  */
 int pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank, u8 pwrst)
 {
@@ -637,10 +641,10 @@ int pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank, u8 pwrst)
  * pwrdm_read_logic_pwrst - get current powerdomain logic retention power state
  * @pwrdm: struct powerdomain * to get current logic retention power state
  *
- * Return the current power state that the logic portion of
- * powerdomain pwrdm will enter
- * Returns -EINVAL if the powerdomain pointer is null or returns the
- * current logic retention power state upon success.
+ * Return the power state that the logic portion of powerdomain @pwrdm
+ * will enter when the powerdomain enters retention.  Returns -EINVAL
+ * if the powerdomain pointer is null or returns the logic retention
+ * power state upon success.
  */
 int pwrdm_read_logic_pwrst(struct powerdomain *pwrdm)
 {
@@ -655,9 +659,9 @@ int pwrdm_read_logic_pwrst(struct powerdomain *pwrdm)
  * pwrdm_read_prev_logic_pwrst - get previous powerdomain logic power state
  * @pwrdm: struct powerdomain * to get previous logic power state
  *
- * Return the powerdomain pwrdm's logic power state.  Returns -EINVAL
- * if the powerdomain pointer is null or returns the previous logic
- * power state upon success.
+ * Return the powerdomain @pwrdm's previous logic power state.  Returns
+ * -EINVAL if the powerdomain pointer is null or returns the previous
+ * logic power state upon success.
  */
 int pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm)
 {
@@ -679,8 +683,8 @@ int pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm)
  * @pwrdm: struct powerdomain * to get current memory bank power state
  * @bank: memory bank number (0-3)
  *
- * Return the powerdomain pwrdm's current memory power state for bank
- * x.  Returns -EINVAL if the powerdomain pointer is null, -EEXIST if
+ * Return the powerdomain @pwrdm's current memory power state for bank
+ * @bank.  Returns -EINVAL if the powerdomain pointer is null, -EEXIST if
  * the target memory bank does not exist or is not controllable, or
  * returns the current memory power state upon success.
  */
@@ -733,10 +737,11 @@ int pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
  * @pwrdm: struct powerdomain * to get previous memory bank power state
  * @bank: memory bank number (0-3)
  *
- * Return the powerdomain pwrdm's previous memory power state for bank
- * x.  Returns -EINVAL if the powerdomain pointer is null, -EEXIST if
- * the target memory bank does not exist or is not controllable, or
- * returns the previous memory power state upon success.
+ * Return the powerdomain @pwrdm's previous memory power state for
+ * bank @bank.  Returns -EINVAL if the powerdomain pointer is null,
+ * -EEXIST if the target memory bank does not exist or is not
+ * controllable, or returns the previous memory power state upon
+ * success.
  */
 int pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
 {
@@ -783,10 +788,10 @@ int pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
  * pwrdm_clear_all_prev_pwrst - clear previous powerstate register for a pwrdm
  * @pwrdm: struct powerdomain * to clear
  *
- * Clear the powerdomain's previous power state register.  Clears the
- * entire register, including logic and memory bank previous power states.
- * Returns -EINVAL if the powerdomain pointer is null, or returns 0 upon
- * success.
+ * Clear the powerdomain's previous power state register @pwrdm.
+ * Clears the entire register, including logic and memory bank
+ * previous power states.  Returns -EINVAL if the powerdomain pointer
+ * is null, or returns 0 upon success.
  */
 int pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm)
 {
@@ -811,11 +816,11 @@ int pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm)
  * @pwrdm: struct powerdomain *
  *
  * Enable automatic context save-and-restore upon power state change
- * for some devices in a powerdomain.  Warning: this only affects a
- * subset of devices in a powerdomain; check the TRM closely.  Returns
- * -EINVAL if the powerdomain pointer is null or if the powerdomain
- * does not support automatic save-and-restore, or returns 0 upon
- * success.
+ * for some devices in the powerdomain @pwrdm.  Warning: this only
+ * affects a subset of devices in a powerdomain; check the TRM
+ * closely.  Returns -EINVAL if the powerdomain pointer is null or if
+ * the powerdomain does not support automatic save-and-restore, or
+ * returns 0 upon success.
  */
 int pwrdm_enable_hdwr_sar(struct powerdomain *pwrdm)
 {
@@ -839,11 +844,11 @@ int pwrdm_enable_hdwr_sar(struct powerdomain *pwrdm)
  * @pwrdm: struct powerdomain *
  *
  * Disable automatic context save-and-restore upon power state change
- * for some devices in a powerdomain.  Warning: this only affects a
- * subset of devices in a powerdomain; check the TRM closely.  Returns
- * -EINVAL if the powerdomain pointer is null or if the powerdomain
- * does not support automatic save-and-restore, or returns 0 upon
- * success.
+ * for some devices in the powerdomain @pwrdm.  Warning: this only
+ * affects a subset of devices in a powerdomain; check the TRM
+ * closely.  Returns -EINVAL if the powerdomain pointer is null or if
+ * the powerdomain does not support automatic save-and-restore, or
+ * returns 0 upon success.
  */
 int pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm)
 {
@@ -866,7 +871,7 @@ int pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm)
  * pwrdm_has_hdwr_sar - test whether powerdomain supports hardware SAR
  * @pwrdm: struct powerdomain *
  *
- * Returns 1 if powerdomain 'pwrdm' supports hardware save-and-restore
+ * Returns 1 if powerdomain @pwrdm supports hardware save-and-restore
  * for some devices, or 0 if it does not.
  */
 bool pwrdm_has_hdwr_sar(struct powerdomain *pwrdm)
@@ -878,7 +883,7 @@ bool pwrdm_has_hdwr_sar(struct powerdomain *pwrdm)
  * 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,
+ * 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
diff --git a/arch/arm/plat-omap/include/plat/clockdomain.h b/arch/arm/plat-omap/include/plat/clockdomain.h
index 45b5deb..683fdf0 100644
--- a/arch/arm/plat-omap/include/plat/clockdomain.h
+++ b/arch/arm/plat-omap/include/plat/clockdomain.h
@@ -40,86 +40,77 @@
 #define OMAP34XX_CLKSTCTRL_FORCE_WAKEUP		0x2
 #define OMAP34XX_CLKSTCTRL_ENABLE_AUTO		0x3
 
-/*
- * struct clkdm_autodep - a clockdomain that should have wkdeps
- * and sleepdeps added when a clockdomain should stay active in hwsup mode;
- * and conversely, removed when the clockdomain should be allowed to go
- * inactive in hwsup mode.
+/**
+ * struct clkdm_autodep - clkdm deps to add when entering/exiting hwsup mode
+ * @clkdm: clockdomain to add wkdep+sleepdep on - set name member only
+ * @omap_chip: OMAP chip types that this autodep is valid on
+ *
+ * A clockdomain that should have wkdeps and sleepdeps added when a
+ * clockdomain should stay active in hwsup mode; and conversely,
+ * removed when the clockdomain should be allowed to go inactive in
+ * hwsup mode.
+ *
+ * Autodeps are deprecated and should be removed after
+ * omap_hwmod-based fine-grained module idle control is added.
  */
 struct clkdm_autodep {
-
 	union {
-		/* Name of the clockdomain to add a wkdep/sleepdep on */
 		const char *name;
-
-		/* Clockdomain pointer (looked up at clkdm_init() time) */
 		struct clockdomain *ptr;
 	} clkdm;
-
-	/* OMAP chip types that this clockdomain dep is valid on */
 	const struct omap_chip_id omap_chip;
-
 };
 
-/* Encodes dependencies between clockdomains - statically defined */
+/**
+ * struct clkdm_dep - encode dependencies between clockdomains
+ * @clkdm_name: clockdomain name
+ * @clkdm: pointer to the struct clockdomain of @clkdm_name
+ * @omap_chip: OMAP chip types that this dependency is valid on
+ * @wkdep_usecount: Number of wakeup dependencies causing this clkdm to wake
+ * @sleepdep_usecount: Number of sleep dependencies that could prevent clkdm from idle
+ *
+ * Statically defined.  @clkdm is resolved from @clkdm_name at runtime and
+ * should not be pre-initialized.
+ *
+ * XXX Should also include hardware (fixed) dependencies.
+ */
 struct clkdm_dep {
-
-	/* Clockdomain name */
 	const char *clkdm_name;
-
-	/* Clockdomain pointer - resolved by the clockdomain code */
 	struct clockdomain *clkdm;
-
-	/* Number of wakeup dependencies causing this clkdm to wake  */
 	atomic_t wkdep_usecount;
-
-	/* Number of sleep dependencies that could prevent clkdm from idle */
 	atomic_t sleepdep_usecount;
-
-	/* Flags to mark OMAP chip restrictions, etc. */
 	const struct omap_chip_id omap_chip;
-
 };
 
+/**
+ * struct clockdomain - OMAP clockdomain
+ * @name: clockdomain name
+ * @pwrdm: powerdomain containing this clockdomain
+ * @clktrctrl_reg: CLKSTCTRL reg for the given clock domain
+ * @clktrctrl_mask: CLKTRCTRL/AUTOSTATE field mask in CM_CLKSTCTRL reg
+ * @flags: Clockdomain capability flags
+ * @dep_bit: Bit shift of this clockdomain's PM_WKDEP/CM_SLEEPDEP bit
+ * @wkdep_srcs: Clockdomains that can be told to wake this powerdomain up
+ * @sleepdep_srcs: Clockdomains that can be told to keep this clkdm from inact
+ * @omap_chip: OMAP chip types that this clockdomain is valid on
+ * @usecount: Usecount tracking
+ * @node: list_head to link all clockdomains together
+ */
 struct clockdomain {
-
-	/* Clockdomain name */
 	const char *name;
-
 	union {
-		/* Powerdomain enclosing this clockdomain */
 		const char *name;
-
-		/* Powerdomain pointer assigned at clkdm_register() */
 		struct powerdomain *ptr;
 	} pwrdm;
-
-	/* CLKSTCTRL reg for the given clock domain*/
 	void __iomem *clkstctrl_reg;
-
-	/* CLKTRCTRL/AUTOSTATE field mask in CM_CLKSTCTRL reg */
 	const u16 clktrctrl_mask;
-
-	/* Clockdomain capability flags */
 	const u8 flags;
-
-	/* Bit shift of this clockdomain's PM_WKDEP/CM_SLEEPDEP bit */
 	const u8 dep_bit;
-
-	/* Clockdomains that can be told to wake this powerdomain up */
 	struct clkdm_dep *wkdep_srcs;
-
-	/* Clockdomains that can be told to keep this clkdm from inactivity */
 	struct clkdm_dep *sleepdep_srcs;
-
-	/* OMAP chip types that this clockdomain is valid on */
 	const struct omap_chip_id omap_chip;
-
-	/* Usecount tracking */
 	atomic_t usecount;
-
 	struct list_head node;
-
 };
 
 void clkdm_init(struct clockdomain **clkdms, struct clkdm_autodep *autodeps);
diff --git a/arch/arm/plat-omap/include/plat/powerdomain.h b/arch/arm/plat-omap/include/plat/powerdomain.h
index 87e13f8..e15c7e9 100644
--- a/arch/arm/plat-omap/include/plat/powerdomain.h
+++ b/arch/arm/plat-omap/include/plat/powerdomain.h
@@ -68,40 +68,36 @@
 struct clockdomain;
 struct powerdomain;
 
+/**
+ * struct powerdomain - OMAP powerdomain
+ * @name: Powerdomain name
+ * @omap_chip: represents the OMAP chip types containing this pwrdm
+ * @prcm_offs: the address offset from CM_BASE/PRM_BASE
+ * @pwrsts: Possible powerdomain power states
+ * @pwrsts_logic_ret: Possible logic power states when pwrdm in RETENTION
+ * @flags: Powerdomain flags
+ * @banks: Number of software-controllable memory banks in this powerdomain
+ * @pwrsts_mem_ret: Possible memory bank pwrstates when pwrdm in RETENTION
+ * @pwrsts_mem_on: Possible memory bank pwrstates when pwrdm in ON
+ * @pwrdm_clkdms: Clockdomains in this powerdomain
+ * @node: list_head linking all powerdomains
+ * @state:
+ * @state_counter:
+ * @timer:
+ * @state_timer:
+ */
 struct powerdomain {
-
-	/* Powerdomain name */
 	const char *name;
-
-	/* Used to represent the OMAP chip types containing this pwrdm */
 	const struct omap_chip_id omap_chip;
-
-	/* the address offset from CM_BASE/PRM_BASE */
 	const s16 prcm_offs;
-
-	/* Possible powerdomain power states */
 	const u8 pwrsts;
-
-	/* Possible logic power states when pwrdm in RETENTION */
 	const u8 pwrsts_logic_ret;
-
-	/* Powerdomain flags */
 	const u8 flags;
-
-	/* Number of software-controllable memory banks in this powerdomain */
 	const u8 banks;
-
-	/* Possible memory bank pwrstates when pwrdm in RETENTION */
 	const u8 pwrsts_mem_ret[PWRDM_MAX_MEM_BANKS];
-
-	/* Possible memory bank pwrstates when pwrdm is ON */
 	const u8 pwrsts_mem_on[PWRDM_MAX_MEM_BANKS];
-
-	/* Clockdomains in this powerdomain */
 	struct clockdomain *pwrdm_clkdms[PWRDM_MAX_CLKDMS];
-
 	struct list_head node;
-
 	int state;
 	unsigned state_counter[PWRDM_MAX_PWRSTS];
 

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 04/10] OMAP clockdomain/powerdomain: remove runtime register/unregister
  2010-01-12  1:05 ` [PATCH 04/10] OMAP clockdomain/powerdomain: remove runtime register/unregister Paul Walmsley
@ 2010-01-19 23:50   ` Kevin Hilman
  2010-01-20  0:24     ` Paul Walmsley
  0 siblings, 1 reply; 14+ messages in thread
From: Kevin Hilman @ 2010-01-19 23:50 UTC (permalink / raw)
  To: linux-arm-kernel

Paul Walmsley <paul@pwsan.com> writes:

> OMAP clockdomains and powerdomains are currently defined statically,
> only registered at boot, and never unregistered, so we can remove the
> unregister function and the locking.   A variant of this was originally
> suggested a while ago by Dmitry Baryshkov <dbaryshkov@gmail.com>.
>
> Signed-off-by: Paul Walmsley <paul@pwsan.com>
> Cc: Dmitry Baryshkov <dbaryshkov@gmail.com>

Hi Paul,

This patch removes the _nolock() iterator but forgot to fixup the
users.  I found this when building an updated PM branch on top of your
fixes branch.

Please fold the following diff into this patch.  Applies on top of
your current for_2.6.33rc_d branch.

Thanks,

Kevin

diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c
index 860b755..283bdca 100644
--- a/arch/arm/mach-omap2/pm-debug.c
+++ b/arch/arm/mach-omap2/pm-debug.c
@@ -575,7 +575,7 @@ static int __init pm_dbg_init(void)
 	(void) debugfs_create_file("time", S_IRUGO,
 		d, (void *)DEBUG_FILE_TIMERS, &debug_fops);
 
-	pwrdm_for_each_nolock(pwrdms_setup, (void *)d);
+	pwrdm_for_each(pwrdms_setup, (void *)d);
 
 	pm_dbg_dir = debugfs_create_dir("registers", d);
 	if (IS_ERR(pm_dbg_dir))

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 04/10] OMAP clockdomain/powerdomain: remove runtime register/unregister
  2010-01-19 23:50   ` Kevin Hilman
@ 2010-01-20  0:24     ` Paul Walmsley
  0 siblings, 0 replies; 14+ messages in thread
From: Paul Walmsley @ 2010-01-20  0:24 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Kevin,

On Tue, 19 Jan 2010, Kevin Hilman wrote:

> Paul Walmsley <paul@pwsan.com> writes:
> 
> > OMAP clockdomains and powerdomains are currently defined statically,
> > only registered at boot, and never unregistered, so we can remove the
> > unregister function and the locking.   A variant of this was originally
> > suggested a while ago by Dmitry Baryshkov <dbaryshkov@gmail.com>.
> >
> > Signed-off-by: Paul Walmsley <paul@pwsan.com>
> > Cc: Dmitry Baryshkov <dbaryshkov@gmail.com>
> 
> Hi Paul,
> 
> This patch removes the _nolock() iterator but forgot to fixup the
> users.  I found this when building an updated PM branch on top of your
> fixes branch.

That patch is in the for_2.6.34 branch, so I'll fold your fix in there. 


thanks,

- Paul

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 05/10] OMAP clockdomains: add usecounting for wakeup and sleep dependencies
  2010-01-12  1:05 ` [PATCH 05/10] OMAP clockdomains: add usecounting for wakeup and sleep dependencies Paul Walmsley
@ 2010-01-21  4:45   ` Paul Walmsley
  0 siblings, 0 replies; 14+ messages in thread
From: Paul Walmsley @ 2010-01-21  4:45 UTC (permalink / raw)
  To: linux-arm-kernel


Hi,

Kevin identified two bugs in this patch (and the one that immediately 
followed it) during PM branch testing.  These bugs, and the fixes 
implemented for them, are described below in the revised patch. In the 
process of fixing it, this patch and the next one were combined.

This patch has taken the place of the previously-posted 05/10 and 06/10 
patches in the for_2.6.34 branch.

regards,

- Paul


From: Paul Walmsley <paul@pwsan.com>
Subject: [PATCH] OMAP clockdomains: add usecounting for wakeup and sleep dependencies

Add usecounting for wakeup and sleep dependencies.  In the current
situation, if several functions add dependencies on the same
clockdomains, when the first dependency removal function is called,
the dependency will be incorrectly removed from the hardware.

Add clkdm_clear_all_wkdeps() and clkdm_clear_all_sleepdeps(), which
provide a fast and usecounting-consistent way to clear all hardware
clockdomain dependencies, since accesses to these registers can be
quite slow.  pm{2,3}4xx.c has been updated to use these new functions.
The original version of this patch did not touch these files, which
previously wrote directly to the wkdep registers, and thus confused
the usecounting code.  This problem was found by Kevin Hilman
<khilman@deeprootsystems.com>.

N.B.: This patch introduces one significant functional difference over
the previous pm34xx.c code: sleepdeps are now cleared during
clockdomain initialization, whereas previously they were left
untouched.  This has been tested by Kevin and confirmed to work.

The original version of this patch also did not take into
consideration that some clockdomains do not have sleep or wakeup
dependency sources, which caused NULL pointer dereferences.  This
problem was debugged and fixed by Kevin Hilman
<khilman@deeprootsystems.com>.

Signed-off-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
Cc: Jouni H?gander <jouni.hogander@nokia.com>
---
 arch/arm/mach-omap2/clockdomain.c             |  216 ++++++++++++++++++++++---
 arch/arm/mach-omap2/pm24xx.c                  |   49 ++++---
 arch/arm/mach-omap2/pm34xx.c                  |    3 +
 arch/arm/plat-omap/include/plat/clockdomain.h |    8 +
 4 files changed, 237 insertions(+), 39 deletions(-)

diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c
index 2af9996..6eaa931 100644
--- a/arch/arm/mach-omap2/clockdomain.c
+++ b/arch/arm/mach-omap2/clockdomain.c
@@ -113,7 +113,6 @@ static struct clkdm_dep *_clkdm_deps_lookup(struct clockdomain *clkdm,
 		return ERR_PTR(-EINVAL);
 
 	for (cd = deps; cd->clkdm_name; cd++) {
-
 		if (!omap_chip_is(cd->omap_chip))
 			continue;
 
@@ -122,7 +121,6 @@ static struct clkdm_dep *_clkdm_deps_lookup(struct clockdomain *clkdm,
 
 		if (cd->clkdm == clkdm)
 			break;
-
 	}
 
 	if (!cd->clkdm_name)
@@ -254,6 +252,96 @@ static void _omap2_clkdm_set_hwsup(struct clockdomain *clkdm, int enable)
 
 }
 
+/**
+ * _init_wkdep_usecount - initialize wkdep usecounts to match hardware
+ * @clkdm: clockdomain to initialize wkdep usecounts
+ *
+ * Initialize the wakeup dependency usecount variables for clockdomain @clkdm.
+ * If a wakeup dependency is present in the hardware, the usecount will be
+ * set to 1; otherwise, it will be set to 0.  Software should clear all
+ * software wakeup dependencies prior to calling this function if it wishes
+ * to ensure that all usecounts start at 0.  No return value.
+ */
+static void _init_wkdep_usecount(struct clockdomain *clkdm)
+{
+	u32 v;
+	struct clkdm_dep *cd;
+
+	if (!clkdm->wkdep_srcs)
+		return;
+
+	for (cd = clkdm->wkdep_srcs; cd->clkdm_name; cd++) {
+		if (!omap_chip_is(cd->omap_chip))
+			continue;
+
+		if (!cd->clkdm && cd->clkdm_name)
+			cd->clkdm = _clkdm_lookup(cd->clkdm_name);
+
+		if (!cd->clkdm) {
+			WARN(!cd->clkdm, "clockdomain: %s: wkdep clkdm %s not "
+			     "found\n", clkdm->name, cd->clkdm_name);
+			continue;
+		}
+
+		v = prm_read_mod_bits_shift(clkdm->pwrdm.ptr->prcm_offs,
+					    PM_WKDEP,
+					    (1 << cd->clkdm->dep_bit));
+
+		if (v)
+			pr_debug("clockdomain: %s: wakeup dependency already "
+				 "set to wake up when %s wakes\n",
+				 clkdm->name, cd->clkdm->name);
+
+		atomic_set(&cd->wkdep_usecount, (v) ? 1 : 0);
+	}
+}
+
+/**
+ * _init_sleepdep_usecount - initialize sleepdep usecounts to match hardware
+ * @clkdm: clockdomain to initialize sleepdep usecounts
+ *
+ * Initialize the sleep dependency usecount variables for clockdomain @clkdm.
+ * If a sleep dependency is present in the hardware, the usecount will be
+ * set to 1; otherwise, it will be set to 0.  Software should clear all
+ * software sleep dependencies prior to calling this function if it wishes
+ * to ensure that all usecounts start at 0.  No return value.
+ */
+static void _init_sleepdep_usecount(struct clockdomain *clkdm)
+{
+	u32 v;
+	struct clkdm_dep *cd;
+
+	if (!cpu_is_omap34xx())
+		return;
+
+	if (!clkdm->sleepdep_srcs)
+		return;
+
+	for (cd = clkdm->sleepdep_srcs; cd->clkdm_name; cd++) {
+		if (!omap_chip_is(cd->omap_chip))
+			continue;
+
+		if (!cd->clkdm && cd->clkdm_name)
+			cd->clkdm = _clkdm_lookup(cd->clkdm_name);
+
+		if (!cd->clkdm) {
+			WARN(!cd->clkdm, "clockdomain: %s: sleepdep clkdm %s "
+			     "not found\n", clkdm->name, cd->clkdm_name);
+			continue;
+		}
+
+		v = prm_read_mod_bits_shift(clkdm->pwrdm.ptr->prcm_offs,
+					    OMAP3430_CM_SLEEPDEP,
+					    (1 << cd->clkdm->dep_bit));
+
+		if (v)
+			pr_debug("clockdomain: %s: sleep dependency already "
+				 "set to prevent from idling until %s "
+				 "idles\n", clkdm->name, cd->clkdm->name);
+
+		atomic_set(&cd->sleepdep_usecount, (v) ? 1 : 0);
+	}
+};
 
 /* Public functions */
 
@@ -272,6 +360,7 @@ void clkdm_init(struct clockdomain **clkdms,
 		struct clkdm_autodep *init_autodeps)
 {
 	struct clockdomain **c = NULL;
+	struct clockdomain *clkdm;
 	struct clkdm_autodep *autodep = NULL;
 
 	if (clkdms)
@@ -282,6 +371,15 @@ void clkdm_init(struct clockdomain **clkdms,
 	if (autodeps)
 		for (autodep = autodeps; autodep->clkdm.ptr; autodep++)
 			_autodep_lookup(autodep);
+
+	/*
+	 * Ensure that the *dep_usecount registers reflect the current
+	 * state of the PRCM.
+	 */
+	list_for_each_entry(clkdm, &clkdm_list, node) {
+		_init_wkdep_usecount(clkdm);
+		_init_sleepdep_usecount(clkdm);
+	}
 }
 
 /**
@@ -387,11 +485,13 @@ int clkdm_add_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
 		return PTR_ERR(cd);
 	}
 
-	pr_debug("clockdomain: hardware will wake up %s when %s wakes up\n",
-		 clkdm1->name, clkdm2->name);
+	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);
 
-	prm_set_mod_reg_bits((1 << clkdm2->dep_bit),
-			     clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP);
+		prm_set_mod_reg_bits((1 << clkdm2->dep_bit),
+				     clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP);
+	}
 
 	return 0;
 }
@@ -420,11 +520,13 @@ int clkdm_del_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
 		return PTR_ERR(cd);
 	}
 
-	pr_debug("clockdomain: hardware will no longer wake up %s after %s "
-		 "wakes up\n", clkdm1->name, clkdm2->name);
+	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);
 
-	prm_clear_mod_reg_bits((1 << clkdm2->dep_bit),
-			       clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP);
+		prm_clear_mod_reg_bits((1 << clkdm2->dep_bit),
+				       clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP);
+	}
 
 	return 0;
 }
@@ -457,11 +559,44 @@ int clkdm_read_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
 		return PTR_ERR(cd);
 	}
 
+	/* XXX It's faster to return the atomic wkdep_usecount */
 	return prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP,
 				       (1 << clkdm2->dep_bit));
 }
 
 /**
+ * clkdm_clear_all_wkdeps - remove all wakeup dependencies from target clkdm
+ * @clkdm: struct clockdomain * to remove all wakeup dependencies from
+ *
+ * Remove all inter-clockdomain wakeup dependencies that could cause
+ * @clkdm to wake.  Intended to be used during boot to initialize the
+ * PRCM to a known state, after all clockdomains are put into swsup idle
+ * and woken up.  Returns -EINVAL if @clkdm pointer is invalid, or
+ * 0 upon success.
+ */
+int clkdm_clear_all_wkdeps(struct clockdomain *clkdm)
+{
+	struct clkdm_dep *cd;
+	u32 mask = 0;
+
+	if (!clkdm)
+		return -EINVAL;
+
+	for (cd = clkdm->wkdep_srcs; cd && cd->clkdm_name; cd++) {
+		if (!omap_chip_is(cd->omap_chip))
+			continue;
+
+		/* PRM accesses are slow, so minimize them */
+		mask |= 1 << cd->clkdm->dep_bit;
+		atomic_set(&cd->wkdep_usecount, 0);
+	}
+
+	prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs, PM_WKDEP);
+
+	return 0;
+}
+
+/**
  * clkdm_add_sleepdep - add a sleep dependency from clkdm2 to clkdm1
  * @clkdm1: prevent this struct clockdomain * from sleeping (dependent)
  * @clkdm2: when this struct clockdomain * is active (source)
@@ -491,12 +626,14 @@ int clkdm_add_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
 		return PTR_ERR(cd);
 	}
 
-	pr_debug("clockdomain: will prevent %s from sleeping if %s is active\n",
-		 clkdm1->name, clkdm2->name);
+	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);
 
-	cm_set_mod_reg_bits((1 << clkdm2->dep_bit),
-			    clkdm1->pwrdm.ptr->prcm_offs,
-			    OMAP3430_CM_SLEEPDEP);
+		cm_set_mod_reg_bits((1 << clkdm2->dep_bit),
+				    clkdm1->pwrdm.ptr->prcm_offs,
+				    OMAP3430_CM_SLEEPDEP);
+	}
 
 	return 0;
 }
@@ -531,12 +668,15 @@ int clkdm_del_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
 		return PTR_ERR(cd);
 	}
 
-	pr_debug("clockdomain: will no longer prevent %s from sleeping if "
-		 "%s is active\n", clkdm1->name, clkdm2->name);
+	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);
 
-	cm_clear_mod_reg_bits((1 << clkdm2->dep_bit),
-			      clkdm1->pwrdm.ptr->prcm_offs,
-			      OMAP3430_CM_SLEEPDEP);
+		cm_clear_mod_reg_bits((1 << clkdm2->dep_bit),
+				      clkdm1->pwrdm.ptr->prcm_offs,
+				      OMAP3430_CM_SLEEPDEP);
+	}
 
 	return 0;
 }
@@ -575,11 +715,47 @@ int clkdm_read_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
 		return PTR_ERR(cd);
 	}
 
+	/* XXX It's faster to return the atomic sleepdep_usecount */
 	return prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs,
 				       OMAP3430_CM_SLEEPDEP,
 				       (1 << clkdm2->dep_bit));
 }
 
+/**
+ * clkdm_clear_all_sleepdeps - remove all sleep dependencies from target clkdm
+ * @clkdm: struct clockdomain * to remove all sleep dependencies from
+ *
+ * Remove all inter-clockdomain sleep dependencies that could prevent
+ * @clkdm from idling.  Intended to be used during boot to initialize the
+ * PRCM to a known state, after all clockdomains are put into swsup idle
+ * and woken up.  Returns -EINVAL if @clkdm pointer is invalid, or
+ * 0 upon success.
+ */
+int clkdm_clear_all_sleepdeps(struct clockdomain *clkdm)
+{
+	struct clkdm_dep *cd;
+	u32 mask = 0;
+
+	if (!cpu_is_omap34xx())
+		return -EINVAL;
+
+	if (!clkdm)
+		return -EINVAL;
+
+	for (cd = clkdm->sleepdep_srcs; cd && cd->clkdm_name; cd++) {
+		if (!omap_chip_is(cd->omap_chip))
+			continue;
+
+		/* PRM accesses are slow, so minimize them */
+		mask |= 1 << cd->clkdm->dep_bit;
+		atomic_set(&cd->sleepdep_usecount, 0);
+	}
+
+	prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs,
+			       OMAP3430_CM_SLEEPDEP);
+
+	return 0;
+}
 
 /**
  * omap2_clkdm_clktrctrl_read - read the clkdm's current state transition mode
diff --git a/arch/arm/mach-omap2/pm24xx.c b/arch/arm/mach-omap2/pm24xx.c
index 7543818..374299e 100644
--- a/arch/arm/mach-omap2/pm24xx.c
+++ b/arch/arm/mach-omap2/pm24xx.c
@@ -57,11 +57,8 @@ static void (*omap2_sram_idle)(void);
 static void (*omap2_sram_suspend)(u32 dllctrl, void __iomem *sdrc_dlla_ctrl,
 				  void __iomem *sdrc_power);
 
-static struct powerdomain *mpu_pwrdm;
-static struct powerdomain *core_pwrdm;
-
-static struct clockdomain *dsp_clkdm;
-static struct clockdomain *gfx_clkdm;
+static struct powerdomain *mpu_pwrdm, *core_pwrdm;
+static struct clockdomain *dsp_clkdm, *mpu_clkdm, *wkup_clkdm, *gfx_clkdm;
 
 static struct clk *osc_ck, *emul_ck;
 
@@ -334,9 +331,17 @@ static struct platform_suspend_ops omap_pm_ops = {
 	.valid		= suspend_valid_only_mem,
 };
 
-static int _pm_clkdm_enable_hwsup(struct clockdomain *clkdm, void *unused)
+/* XXX This function should be shareable between OMAP2xxx and OMAP3 */
+static int __init clkdms_setup(struct clockdomain *clkdm, void *unused)
 {
-	omap2_clkdm_allow_idle(clkdm);
+	clkdm_clear_all_wkdeps(clkdm);
+	clkdm_clear_all_sleepdeps(clkdm);
+
+	if (clkdm->flags & CLKDM_CAN_ENABLE_AUTO)
+		omap2_clkdm_allow_idle(clkdm);
+	else if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP &&
+		 atomic_read(&clkdm->usecount) == 0)
+		omap2_clkdm_sleep(clkdm);
 	return 0;
 }
 
@@ -349,14 +354,6 @@ static void __init prcm_setup_regs(void)
 	prm_write_mod_reg(OMAP24XX_AUTOIDLE, OCP_MOD,
 			  OMAP2_PRCM_SYSCONFIG_OFFSET);
 
-	/* Set all domain wakeup dependencies */
-	prm_write_mod_reg(OMAP_EN_WKUP_MASK, MPU_MOD, PM_WKDEP);
-	prm_write_mod_reg(0, OMAP24XX_DSP_MOD, PM_WKDEP);
-	prm_write_mod_reg(0, GFX_MOD, PM_WKDEP);
-	prm_write_mod_reg(0, CORE_MOD, PM_WKDEP);
-	if (cpu_is_omap2430())
-		prm_write_mod_reg(0, OMAP2430_MDM_MOD, PM_WKDEP);
-
 	/*
 	 * Set CORE powerdomain memory banks to retain their contents
 	 * during RETENTION
@@ -385,8 +382,12 @@ static void __init prcm_setup_regs(void)
 	pwrdm_set_next_pwrst(pwrdm, PWRDM_POWER_OFF);
 	omap2_clkdm_sleep(gfx_clkdm);
 
-	/* Enable clockdomain hardware-supervised control for all clkdms */
-	clkdm_for_each(_pm_clkdm_enable_hwsup, NULL);
+	/*
+	 * Clear clockdomain wakeup dependencies and enable
+	 * hardware-supervised idle for all clkdms
+	 */
+	clkdm_for_each(clkdms_setup, NULL);
+	clkdm_add_wkdep(mpu_clkdm, wkup_clkdm);
 
 	/* Enable clock autoidle for all domains */
 	cm_write_mod_reg(OMAP24XX_AUTO_CAM |
@@ -482,7 +483,7 @@ static int __init omap2_pm_init(void)
 	l = prm_read_mod_reg(OCP_MOD, OMAP2_PRCM_REVISION_OFFSET);
 	printk(KERN_INFO "PRCM revision %d.%d\n", (l >> 4) & 0x0f, l & 0x0f);
 
-	/* Look up important powerdomains, clockdomains */
+	/* Look up important powerdomains */
 
 	mpu_pwrdm = pwrdm_lookup("mpu_pwrdm");
 	if (!mpu_pwrdm)
@@ -492,9 +493,19 @@ static int __init omap2_pm_init(void)
 	if (!core_pwrdm)
 		pr_err("PM: core_pwrdm not found\n");
 
+	/* Look up important clockdomains */
+
+	mpu_clkdm = clkdm_lookup("mpu_clkdm");
+	if (!mpu_clkdm)
+		pr_err("PM: mpu_clkdm not found\n");
+
+	wkup_clkdm = clkdm_lookup("wkup_clkdm");
+	if (!wkup_clkdm)
+		pr_err("PM: wkup_clkdm not found\n");
+
 	dsp_clkdm = clkdm_lookup("dsp_clkdm");
 	if (!dsp_clkdm)
-		pr_err("PM: mpu_clkdm not found\n");
+		pr_err("PM: dsp_clkdm not found\n");
 
 	gfx_clkdm = clkdm_lookup("gfx_clkdm");
 	if (!gfx_clkdm)
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index c34c92e..d8c3b9a 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -993,6 +993,9 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
  */
 static int __init clkdms_setup(struct clockdomain *clkdm, void *unused)
 {
+	clkdm_clear_all_wkdeps(clkdm);
+	clkdm_clear_all_sleepdeps(clkdm);
+
 	if (clkdm->flags & CLKDM_CAN_ENABLE_AUTO)
 		omap2_clkdm_allow_idle(clkdm);
 	else if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP &&
diff --git a/arch/arm/plat-omap/include/plat/clockdomain.h b/arch/arm/plat-omap/include/plat/clockdomain.h
index 2286971..45b5deb 100644
--- a/arch/arm/plat-omap/include/plat/clockdomain.h
+++ b/arch/arm/plat-omap/include/plat/clockdomain.h
@@ -70,6 +70,12 @@ struct clkdm_dep {
 	/* Clockdomain pointer - resolved by the clockdomain code */
 	struct clockdomain *clkdm;
 
+	/* Number of wakeup dependencies causing this clkdm to wake  */
+	atomic_t wkdep_usecount;
+
+	/* Number of sleep dependencies that could prevent clkdm from idle */
+	atomic_t sleepdep_usecount;
+
 	/* Flags to mark OMAP chip restrictions, etc. */
 	const struct omap_chip_id omap_chip;
 
@@ -126,9 +132,11 @@ struct powerdomain *clkdm_get_pwrdm(struct clockdomain *clkdm);
 int clkdm_add_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
 int clkdm_del_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
 int clkdm_read_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
+int clkdm_clear_all_wkdeps(struct clockdomain *clkdm);
 int clkdm_add_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
 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 omap2_clkdm_allow_idle(struct clockdomain *clkdm);
 void omap2_clkdm_deny_idle(struct clockdomain *clkdm);
-- 
1.6.6.rc2.5.g49666

^ permalink raw reply related	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2010-01-21  4:45 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-01-12  1:05 [PATCH 00/10] OMAP2/3/4 clockdomains/powerdomains: split shared dependencies and clean up - for 2.6.34 Paul Walmsley
2010-01-12  1:05 ` [PATCH 01/10] OMAP2/3 clkdm/pwrdm: move wkdep/sleepdep handling from pwrdm to clkdm Paul Walmsley
2010-01-12  1:05 ` [PATCH 02/10] OMAP2/3 clockdomains: split shared structures so usecounting works Paul Walmsley
2010-01-12  1:05 ` [PATCH 03/10] OMAP2 clockdomain: modem clockdomain is only present on OMAP2430 Paul Walmsley
2010-01-12  1:05 ` [PATCH 04/10] OMAP clockdomain/powerdomain: remove runtime register/unregister Paul Walmsley
2010-01-19 23:50   ` Kevin Hilman
2010-01-20  0:24     ` Paul Walmsley
2010-01-12  1:05 ` [PATCH 05/10] OMAP clockdomains: add usecounting for wakeup and sleep dependencies Paul Walmsley
2010-01-21  4:45   ` Paul Walmsley
2010-01-12  1:05 ` [PATCH 06/10] OMAP2/3/4 clockdomain: add clkdm_clear_all_{wkdep, sleepdep}s() Paul Walmsley
2010-01-12  1:05 ` [PATCH 07/10] OMAP powerdomain/PM: use symbolic constants for the max number of power states Paul Walmsley
2010-01-12  1:05 ` [PATCH 08/10] OMAP powerdomain: rearrange struct powerdomain to save some memory Paul Walmsley
2010-01-12  1:05 ` [PATCH 09/10] OMAP powerdomain: remove pwrdm_clk_state_switch Paul Walmsley
2010-01-12  1:05 ` [PATCH 10/10] OMAP clockdomain/powerdomain: improve documentation Paul Walmsley

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).