All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 0/8] Fix module-mode enable sequence on OMAP4
@ 2011-06-27 16:11 Benoit Cousson
  2011-06-27 16:11 ` [PATCH v3 1/8] OMAP2+: clockdomain: Add an api to read idle mode Benoit Cousson
                   ` (7 more replies)
  0 siblings, 8 replies; 21+ messages in thread
From: Benoit Cousson @ 2011-06-27 16:11 UTC (permalink / raw)
  To: paul, rnayak; +Cc: santosh.shilimkar, linux-omap, toddpoynor, Benoit Cousson

Hi Paul,

Here is an updated version of the series started by Rajendra.
It takes into account comments from Todd.

I had to update it because this series is mandatory for the hwmod
modulemodule control series.
I rebased it on top of the various fixes done on hwmod framework
to take advantage of the new clkdm attribute in omap_hwmod.
I thus added 2 new APIs to handle clockdomain from hwmod instead
of using the clockdomain done for clock.

I drop the clockdomain control for optional clocks because is not
mandatory.


On OMAP4, the PRCM recommended sequence for enabling a module after
power-on-reset is:

-1- Force clkdm to SW_WKUP
-2- Configure desired module mode to "enable" or "auto"
-3- Wait for the desired module idle status to be FUNC
-4- Program clkdm in HW_AUTO(if supported)

This sequence applies to all older OMAPs' as well, however since
they use 'autodeps', it makes sure that no clkdm is in IDLE, and
hence not requiring a force SW_WKUP when a module is being enabled.

OMAP4 does not need to support autodeps, because of the dynamic
dependency feature, wherein the HW takes care of waking up a
clockdomain from idle and hence the module, whenever an interconnect
access happens to the given module.

Implementing the sequence for OMAP4 requires some of the clockdomain
handling that is currently done in clock framework to be done as part
of hwmod framework since the step -3- above to "Wait for the desired
module idle status to be FUNC" is done as part of hwmod framework.

This series moves the clockdomain handling into hwmod framework and
implements the above sequence for OMAP4.

Lastly, with this series drivers which are yet to be adapted to PM
runtime and still rely on clock calls to enable/disable the respective
*main* clocks are expected to be broken. MMC is one such which even
breaks boot, and hence the series has a TEMP workaround patch added
which keeps l3init clockdomain always force-enabled.
This TEMP patch will gate all CORE low power transitions but should
at least allow MPU low power transitions to work.

The series is based on for_3.0.1/4_hwmod_modulemode and tested on
OMAP4430 ES2.1 + SDP. It should not affect OMAP2 & 3, but some
testing are definitively needed.

The patches are available here:
git://gitorious.org/omap-pm/linux.git for_3.0.1/5_hwmod_clkdm_fixes

Regards,
Benoit


Changes since v1: http://www.spinics.net/lists/linux-omap/msg52265.html
    - Rebase series on top on modulemode series
    
Changes since v2: http://www.spinics.net/lists/linux-omap/msg53111.html
    - Remove #ifdef
    - Rename clkdm_is_idle
    - Remove confusing pr_debug message in clkdm_xxx functions
    - Add per clkdm spinlock to avoid concurrent access


Benoit Cousson (1):
  OMAP2+: clockdomain: Add 2 APIs to control clockdomain from hwmod framework

Rajendra Nayak (7):
  OMAP2+: clockdomain: Add an api to read idle mode
  OMAP2+: clockdomain: Add SoC support for clkdm_is_idle
  OMAP2+: PM: Initialise sleep_switch to a non-valid value
  OMAP2+: PM: idle clkdms only if already in idle
  OMAP4: PM: TEMP: Prevent l3init from idling/force sleep
  OMAP2+: clockdomain: Add per clkdm lock to prevent concurrent state programming
  OMAP2+: hwmod: Follow the recommended PRCM module enable sequence

 arch/arm/mach-omap2/clock.c                 |   17 +---
 arch/arm/mach-omap2/clockdomain.c           |  193 +++++++++++++++++++++-----
 arch/arm/mach-omap2/clockdomain.h           |    8 +
 arch/arm/mach-omap2/clockdomain2xxx_3xxx.c  |   18 +++-
 arch/arm/mach-omap2/clockdomain44xx.c       |   20 ++--
 arch/arm/mach-omap2/clockdomains44xx_data.c |    2 +-
 arch/arm/mach-omap2/omap_hwmod.c            |   26 ++++-
 arch/arm/mach-omap2/pm.c                    |    6 +-
 8 files changed, 222 insertions(+), 68 deletions(-)


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

* [PATCH v3 1/8] OMAP2+: clockdomain: Add an api to read idle mode
  2011-06-27 16:11 [PATCH v3 0/8] Fix module-mode enable sequence on OMAP4 Benoit Cousson
@ 2011-06-27 16:11 ` Benoit Cousson
  2011-07-01 12:22   ` Paul Walmsley
  2011-06-27 16:11 ` [PATCH v3 2/8] OMAP2+: clockdomain: Add SoC support for clkdm_is_idle Benoit Cousson
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 21+ messages in thread
From: Benoit Cousson @ 2011-06-27 16:11 UTC (permalink / raw)
  To: paul, rnayak; +Cc: santosh.shilimkar, linux-omap, toddpoynor

From: Rajendra Nayak <rnayak@ti.com>

Add a clockdomain api to check if hardware supervised
idle transitions are enabled on a clockdomain.

Signed-off-by: Rajendra Nayak <rnayak@ti.com>
Cc: Paul Walmsley <paul@pwsan.com>
---
 arch/arm/mach-omap2/clockdomain.c |   21 +++++++++++++++++++++
 arch/arm/mach-omap2/clockdomain.h |    3 +++
 2 files changed, 24 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c
index 6cb6c03..3f2a8e7 100644
--- a/arch/arm/mach-omap2/clockdomain.c
+++ b/arch/arm/mach-omap2/clockdomain.c
@@ -795,6 +795,27 @@ void clkdm_deny_idle(struct clockdomain *clkdm)
 	arch_clkdm->clkdm_deny_idle(clkdm);
 }
 
+/**
+ * clkdm_allows_idle - Check if the clkdm hwsup/autoidle is enabled
+ * @clkdm: struct clockdomain *
+ *
+ * Returns true if the clockdomain is in hardware-supervised
+ * idle mode, or 0 otherwise.
+ *
+ */
+int clkdm_allows_idle(struct clockdomain *clkdm)
+{
+	if (!clkdm)
+		return -EINVAL;
+
+	if (!arch_clkdm || !arch_clkdm->clkdm_allows_idle)
+		return -EINVAL;
+
+	pr_debug("clockdomain: reading idle state for %s\n", clkdm->name);
+
+	return arch_clkdm->clkdm_allows_idle(clkdm);
+}
+
 
 /* Clockdomain-to-clock framework interface code */
 
diff --git a/arch/arm/mach-omap2/clockdomain.h b/arch/arm/mach-omap2/clockdomain.h
index 5823584..2d3d970 100644
--- a/arch/arm/mach-omap2/clockdomain.h
+++ b/arch/arm/mach-omap2/clockdomain.h
@@ -138,6 +138,7 @@ struct clockdomain {
  * @clkdm_wakeup: Force a clockdomain to wakeup
  * @clkdm_allow_idle: Enable hw supervised idle transitions for clock domain
  * @clkdm_deny_idle: Disable hw supervised idle transitions for clock domain
+ * @clkdm_allows_idle: Check if hw supervised idle transitions are enabled
  * @clkdm_clk_enable: Put the clkdm in right state for a clock enable
  * @clkdm_clk_disable: Put the clkdm in right state for a clock disable
  */
@@ -154,6 +155,7 @@ struct clkdm_ops {
 	int	(*clkdm_wakeup)(struct clockdomain *clkdm);
 	void	(*clkdm_allow_idle)(struct clockdomain *clkdm);
 	void	(*clkdm_deny_idle)(struct clockdomain *clkdm);
+	int	(*clkdm_allows_idle)(struct clockdomain *clkdm);
 	int	(*clkdm_clk_enable)(struct clockdomain *clkdm);
 	int	(*clkdm_clk_disable)(struct clockdomain *clkdm);
 };
@@ -177,6 +179,7 @@ int clkdm_clear_all_sleepdeps(struct clockdomain *clkdm);
 
 void clkdm_allow_idle(struct clockdomain *clkdm);
 void clkdm_deny_idle(struct clockdomain *clkdm);
+int clkdm_allows_idle(struct clockdomain *clkdm);
 
 int clkdm_wakeup(struct clockdomain *clkdm);
 int clkdm_sleep(struct clockdomain *clkdm);
-- 
1.7.0.4


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

* [PATCH v3 2/8] OMAP2+: clockdomain: Add SoC support for clkdm_is_idle
  2011-06-27 16:11 [PATCH v3 0/8] Fix module-mode enable sequence on OMAP4 Benoit Cousson
  2011-06-27 16:11 ` [PATCH v3 1/8] OMAP2+: clockdomain: Add an api to read idle mode Benoit Cousson
@ 2011-06-27 16:11 ` Benoit Cousson
  2011-06-27 19:18   ` Todd Poynor
  2011-07-01 12:24   ` Paul Walmsley
  2011-06-27 16:11 ` [PATCH v3 3/8] OMAP2+: PM: Initialise sleep_switch to a non-valid value Benoit Cousson
                   ` (5 subsequent siblings)
  7 siblings, 2 replies; 21+ messages in thread
From: Benoit Cousson @ 2011-06-27 16:11 UTC (permalink / raw)
  To: paul, rnayak; +Cc: santosh.shilimkar, linux-omap, toddpoynor

From: Rajendra Nayak <rnayak@ti.com>

Add the SoC specific implemenation for clkdm_is_idle
for OMAP2/3 and OMAP4.

Signed-off-by: Rajendra Nayak <rnayak@ti.com>
Cc: Paul Walmsley <paul@pwsan.com>
---
 arch/arm/mach-omap2/clockdomain2xxx_3xxx.c |   12 ++++++++++++
 arch/arm/mach-omap2/clockdomain44xx.c      |    7 +++++++
 2 files changed, 19 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c b/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c
index 48d0db7..81f3e46 100644
--- a/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c
+++ b/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c
@@ -13,6 +13,7 @@
  */
 
 #include <linux/types.h>
+#include <linux/errno.h>
 #include <plat/prcm.h>
 #include "prm.h"
 #include "prm2xxx_3xxx.h"
@@ -146,6 +147,15 @@ static void omap2_clkdm_deny_idle(struct clockdomain *clkdm)
 		_clkdm_del_autodeps(clkdm);
 }
 
+static int omap2_clkdm_allows_idle(struct clockdomain *clkdm)
+{
+	if (!clkdm->clktrctrl_mask)
+		return -EINVAL;
+
+	return omap2_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+				clkdm->clktrctrl_mask);
+}
+
 static void _enable_hwsup(struct clockdomain *clkdm)
 {
 	if (cpu_is_omap24xx())
@@ -252,6 +262,7 @@ struct clkdm_ops omap2_clkdm_operations = {
 	.clkdm_wakeup		= omap2_clkdm_wakeup,
 	.clkdm_allow_idle	= omap2_clkdm_allow_idle,
 	.clkdm_deny_idle	= omap2_clkdm_deny_idle,
+	.clkdm_allows_idle	= omap2_clkdm_allows_idle,
 	.clkdm_clk_enable	= omap2_clkdm_clk_enable,
 	.clkdm_clk_disable	= omap2_clkdm_clk_disable,
 };
@@ -269,6 +280,7 @@ struct clkdm_ops omap3_clkdm_operations = {
 	.clkdm_wakeup		= omap3_clkdm_wakeup,
 	.clkdm_allow_idle	= omap3_clkdm_allow_idle,
 	.clkdm_deny_idle	= omap3_clkdm_deny_idle,
+	.clkdm_allows_idle	= omap2_clkdm_allows_idle,
 	.clkdm_clk_enable	= omap2_clkdm_clk_enable,
 	.clkdm_clk_disable	= omap2_clkdm_clk_disable,
 };
diff --git a/arch/arm/mach-omap2/clockdomain44xx.c b/arch/arm/mach-omap2/clockdomain44xx.c
index a1a4ecd..1599b18 100644
--- a/arch/arm/mach-omap2/clockdomain44xx.c
+++ b/arch/arm/mach-omap2/clockdomain44xx.c
@@ -93,6 +93,12 @@ static void omap4_clkdm_deny_idle(struct clockdomain *clkdm)
 					clkdm->cm_inst, clkdm->clkdm_offs);
 }
 
+static int omap4_clkdm_allows_idle(struct clockdomain *clkdm)
+{
+	return omap4_cminst_is_clkdm_in_hwsup(clkdm->prcm_partition,
+				clkdm->cm_inst, clkdm->clkdm_offs);
+}
+
 static int omap4_clkdm_clk_enable(struct clockdomain *clkdm)
 {
 	bool hwsup = false;
@@ -132,6 +138,7 @@ struct clkdm_ops omap4_clkdm_operations = {
 	.clkdm_wakeup		= omap4_clkdm_wakeup,
 	.clkdm_allow_idle	= omap4_clkdm_allow_idle,
 	.clkdm_deny_idle	= omap4_clkdm_deny_idle,
+	.clkdm_allows_idle	= omap4_clkdm_allows_idle,
 	.clkdm_clk_enable	= omap4_clkdm_clk_enable,
 	.clkdm_clk_disable	= omap4_clkdm_clk_disable,
 };
-- 
1.7.0.4


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

* [PATCH v3 3/8] OMAP2+: PM: Initialise sleep_switch to a non-valid value
  2011-06-27 16:11 [PATCH v3 0/8] Fix module-mode enable sequence on OMAP4 Benoit Cousson
  2011-06-27 16:11 ` [PATCH v3 1/8] OMAP2+: clockdomain: Add an api to read idle mode Benoit Cousson
  2011-06-27 16:11 ` [PATCH v3 2/8] OMAP2+: clockdomain: Add SoC support for clkdm_is_idle Benoit Cousson
@ 2011-06-27 16:11 ` Benoit Cousson
  2011-06-27 16:11 ` [PATCH v3 4/8] OMAP2+: PM: idle clkdms only if already in idle Benoit Cousson
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 21+ messages in thread
From: Benoit Cousson @ 2011-06-27 16:11 UTC (permalink / raw)
  To: paul, rnayak; +Cc: santosh.shilimkar, linux-omap, toddpoynor

From: Rajendra Nayak <rnayak@ti.com>

sleep_switch which is initialised to 0 in omap_set_pwrdm_state
happens to be a valid sleep_switch type (FORCEWAKEUP_SWITCH)
which are defined as:

 #define FORCEWAKEUP_SWITCH      0
 #define LOWPOWERSTATE_SWITCH    1

This causes the function to wrongly program some clock domains
even when the Powerdomain is in ON state.

Signed-off-by: Rajendra Nayak <rnayak@ti.com>
Cc: Paul Walmsley <paul@pwsan.com>
---
 arch/arm/mach-omap2/pm.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
index 49486f5..d48813f 100644
--- a/arch/arm/mach-omap2/pm.c
+++ b/arch/arm/mach-omap2/pm.c
@@ -106,7 +106,7 @@ static void omap2_init_processor_devices(void)
 int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state)
 {
 	u32 cur_state;
-	int sleep_switch = 0;
+	int sleep_switch = -1;
 	int ret = 0;
 
 	if (pwrdm == NULL || IS_ERR(pwrdm))
-- 
1.7.0.4


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

* [PATCH v3 4/8] OMAP2+: PM: idle clkdms only if already in idle
  2011-06-27 16:11 [PATCH v3 0/8] Fix module-mode enable sequence on OMAP4 Benoit Cousson
                   ` (2 preceding siblings ...)
  2011-06-27 16:11 ` [PATCH v3 3/8] OMAP2+: PM: Initialise sleep_switch to a non-valid value Benoit Cousson
@ 2011-06-27 16:11 ` Benoit Cousson
  2011-06-28  1:00   ` Todd Poynor
  2011-06-27 16:11 ` [PATCH v3 5/8] OMAP4: PM: TEMP: Prevent l3init from idling/force sleep Benoit Cousson
                   ` (3 subsequent siblings)
  7 siblings, 1 reply; 21+ messages in thread
From: Benoit Cousson @ 2011-06-27 16:11 UTC (permalink / raw)
  To: paul, rnayak; +Cc: santosh.shilimkar, linux-omap, toddpoynor

From: Rajendra Nayak <rnayak@ti.com>

The omap_set_pwrdm_state function forces clockdomains
to idle, without checking the existing idle state
programmed, instead based solely on the HW capability
of the clockdomain to support idle.
This is wrong and the clockdomains should be idled
post a state_switch *only* if idle transitions on the
clockdomain were already enabled.

Signed-off-by: Rajendra Nayak <rnayak@ti.com>
Cc: Paul Walmsley <paul@pwsan.com>
---
 arch/arm/mach-omap2/pm.c |    4 +++-
 1 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
index d48813f..ce1a9f3 100644
--- a/arch/arm/mach-omap2/pm.c
+++ b/arch/arm/mach-omap2/pm.c
@@ -108,6 +108,7 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state)
 	u32 cur_state;
 	int sleep_switch = -1;
 	int ret = 0;
+	int hwsup = 0;
 
 	if (pwrdm == NULL || IS_ERR(pwrdm))
 		return -EINVAL;
@@ -127,6 +128,7 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state)
 			(pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE)) {
 			sleep_switch = LOWPOWERSTATE_SWITCH;
 		} else {
+			hwsup = clkdm_allows_idle(pwrdm->pwrdm_clkdms[0]);
 			clkdm_wakeup(pwrdm->pwrdm_clkdms[0]);
 			pwrdm_wait_transition(pwrdm);
 			sleep_switch = FORCEWAKEUP_SWITCH;
@@ -142,7 +144,7 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state)
 
 	switch (sleep_switch) {
 	case FORCEWAKEUP_SWITCH:
-		if (pwrdm->pwrdm_clkdms[0]->flags & CLKDM_CAN_ENABLE_AUTO)
+		if (hwsup)
 			clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]);
 		else
 			clkdm_sleep(pwrdm->pwrdm_clkdms[0]);
-- 
1.7.0.4


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

* [PATCH v3 5/8] OMAP4: PM: TEMP: Prevent l3init from idling/force sleep
  2011-06-27 16:11 [PATCH v3 0/8] Fix module-mode enable sequence on OMAP4 Benoit Cousson
                   ` (3 preceding siblings ...)
  2011-06-27 16:11 ` [PATCH v3 4/8] OMAP2+: PM: idle clkdms only if already in idle Benoit Cousson
@ 2011-06-27 16:11 ` Benoit Cousson
  2011-06-27 16:11 ` [PATCH v3 6/8] OMAP2+: clockdomain: Add 2 APIs to control clockdomain from hwmod framework Benoit Cousson
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 21+ messages in thread
From: Benoit Cousson @ 2011-06-27 16:11 UTC (permalink / raw)
  To: paul, rnayak; +Cc: santosh.shilimkar, linux-omap, toddpoynor

From: Rajendra Nayak <rnayak@ti.com>

Since MMC driver is yet to be adapted to
runtime PM and still uses direct clock
calls to enable/disable module, its needed
that the clockdomain (for MMC) is always kept force
enabled since the next few patches move
the clockdomain handling from clock framework
to hwmod framework and break MMC.

This will certainlly gate any CORE low power
transitions.

Signed-off-by: Rajendra Nayak <rnayak@ti.com>
Cc: Paul Walmsley <paul@pwsan.com>
---
 arch/arm/mach-omap2/clockdomains44xx_data.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-omap2/clockdomains44xx_data.c b/arch/arm/mach-omap2/clockdomains44xx_data.c
index 66090f2..863006a 100644
--- a/arch/arm/mach-omap2/clockdomains44xx_data.c
+++ b/arch/arm/mach-omap2/clockdomains44xx_data.c
@@ -494,7 +494,7 @@ static struct clockdomain l3_init_44xx_clkdm = {
 	.dep_bit	  = OMAP4430_L3INIT_STATDEP_SHIFT,
 	.wkdep_srcs	  = l3_init_wkup_sleep_deps,
 	.sleepdep_srcs	  = l3_init_wkup_sleep_deps,
-	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
+	.flags		  = CLKDM_CAN_FORCE_WAKEUP,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
-- 
1.7.0.4


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

* [PATCH v3 6/8] OMAP2+: clockdomain: Add 2 APIs to control clockdomain from hwmod framework
  2011-06-27 16:11 [PATCH v3 0/8] Fix module-mode enable sequence on OMAP4 Benoit Cousson
                   ` (4 preceding siblings ...)
  2011-06-27 16:11 ` [PATCH v3 5/8] OMAP4: PM: TEMP: Prevent l3init from idling/force sleep Benoit Cousson
@ 2011-06-27 16:11 ` Benoit Cousson
  2011-06-28  1:08   ` Todd Poynor
  2011-06-27 16:11 ` [PATCH v3 7/8] OMAP2+: clockdomain: Add per clkdm lock to prevent concurrent state programming Benoit Cousson
  2011-06-27 16:11 ` [PATCH v3 8/8] OMAP2+: hwmod: Follow the recommended PRCM module enable sequence Benoit Cousson
  7 siblings, 1 reply; 21+ messages in thread
From: Benoit Cousson @ 2011-06-27 16:11 UTC (permalink / raw)
  To: paul, rnayak; +Cc: santosh.shilimkar, linux-omap, toddpoynor, Benoit Cousson

Duplicate the existing API for clockdomain enable from clock to enable
a clock domain from hwmod framework.
This will be needed when the hwmod framework will move from the current
clock centric approach to the module based approach.

Signed-off-by: Benoit Cousson <b-cousson@ti.com>
Cc: Paul Walmsley <paul@pwsan.com>
Cc: Rajendra Nayak <rnayak@ti.com>
---
 arch/arm/mach-omap2/clockdomain.c |  132 +++++++++++++++++++++++++++----------
 arch/arm/mach-omap2/clockdomain.h |    3 +
 2 files changed, 100 insertions(+), 35 deletions(-)

diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c
index 3f2a8e7..a1b22cd 100644
--- a/arch/arm/mach-omap2/clockdomain.c
+++ b/arch/arm/mach-omap2/clockdomain.c
@@ -817,7 +817,50 @@ int clkdm_allows_idle(struct clockdomain *clkdm)
 }
 
 
-/* Clockdomain-to-clock framework interface code */
+/* Clockdomain-to-clock/hwmod framework interface code */
+
+static int _clkdm_clk_hwmod_enable(struct clockdomain *clkdm)
+{
+	if (!clkdm || !arch_clkdm || !arch_clkdm->clkdm_clk_enable)
+		return -EINVAL;
+
+	/*
+	 * For arch's with no autodeps, clkcm_clk_enable
+	 * should be called for every clock instance or hwmod that is
+	 * enabled, so the clkdm can be force woken up.
+	 */
+	if ((atomic_inc_return(&clkdm->usecount) > 1) && autodeps)
+		return 0;
+
+	arch_clkdm->clkdm_clk_enable(clkdm);
+	pwrdm_wait_transition(clkdm->pwrdm.ptr);
+	pwrdm_clkdm_state_switch(clkdm);
+
+	pr_debug("clockdomain: clkdm %s: enabled\n", clkdm->name);
+
+	return 0;
+}
+
+static int _clkdm_clk_hwmod_disable(struct clockdomain *clkdm)
+{
+	if (!clkdm || !arch_clkdm || !arch_clkdm->clkdm_clk_disable)
+		return -EINVAL;
+
+	if (atomic_read(&clkdm->usecount) == 0) {
+		WARN_ON(1); /* underflow */
+		return -ERANGE;
+	}
+
+	if (atomic_dec_return(&clkdm->usecount) > 0)
+		return 0;
+
+	arch_clkdm->clkdm_clk_disable(clkdm);
+	pwrdm_clkdm_state_switch(clkdm);
+
+	pr_debug("clockdomain: clkdm %s: disabled\n", clkdm->name);
+
+	return 0;
+}
 
 /**
  * clkdm_clk_enable - add an enabled downstream clock to this clkdm
@@ -840,25 +883,10 @@ int clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk)
 	 * downstream clocks for debugging purposes?
 	 */
 
-	if (!clkdm || !clk)
-		return -EINVAL;
-
-	if (!arch_clkdm || !arch_clkdm->clkdm_clk_enable)
+	if (!clk)
 		return -EINVAL;
 
-	if (atomic_inc_return(&clkdm->usecount) > 1)
-		return 0;
-
-	/* Clockdomain now has one enabled downstream clock */
-
-	pr_debug("clockdomain: clkdm %s: clk %s now enabled\n", clkdm->name,
-		 clk->name);
-
-	arch_clkdm->clkdm_clk_enable(clkdm);
-	pwrdm_wait_transition(clkdm->pwrdm.ptr);
-	pwrdm_clkdm_state_switch(clkdm);
-
-	return 0;
+	return _clkdm_clk_hwmod_enable(clkdm);
 }
 
 /**
@@ -882,30 +910,64 @@ int clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk)
 	 * downstream clocks for debugging purposes?
 	 */
 
-	if (!clkdm || !clk)
+	if (!clk)
 		return -EINVAL;
 
-	if (!arch_clkdm || !arch_clkdm->clkdm_clk_disable)
-		return -EINVAL;
+	return _clkdm_clk_hwmod_disable(clkdm);
+}
 
-#ifdef DEBUG
-	if (atomic_read(&clkdm->usecount) == 0) {
-		WARN_ON(1); /* underflow */
-		return -ERANGE;
-	}
-#endif
+/**
+ * clkdm_hwmod_enable - add an enabled downstream hwmod to this clkdm
+ * @clkdm: struct clockdomain *
+ * @oh: struct omap_hwmod * of the enabled downstream hwmod
+ *
+ * Increment the usecount of the clockdomain @clkdm and ensure that it
+ * is awake before @oh is enabled. Intended to be called by
+ * module_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 clkdm_hwmod_enable(struct clockdomain *clkdm, struct omap_hwmod *oh)
+{
+	/*
+	 * XXX Rewrite this code to maintain a list of enabled
+	 * downstream hwmods for debugging purposes?
+	 */
 
-	if (atomic_dec_return(&clkdm->usecount) > 0)
-		return 0;
+	if (!oh)
+		return -EINVAL;
 
-	/* All downstream clocks of this clockdomain are now disabled */
+	return _clkdm_clk_hwmod_enable(clkdm);
+}
 
-	pr_debug("clockdomain: clkdm %s: clk %s now disabled\n", clkdm->name,
-		 clk->name);
+/**
+ * clkdm_hwmod_disable - remove an enabled downstream hwmod from this clkdm
+ * @clkdm: struct clockdomain *
+ * @oh: struct omap_hwmod * of the disabled downstream hwmod
+ *
+ * Decrement the usecount of this clockdomain @clkdm when @oh is
+ * disabled. Intended to be called by module_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 clkdm_hwmod_disable(struct clockdomain *clkdm, struct omap_hwmod *oh)
+{
+	/*
+	 * XXX Rewrite this code to maintain a list of enabled
+	 * downstream hwmods for debugging purposes?
+	 */
 
-	arch_clkdm->clkdm_clk_disable(clkdm);
-	pwrdm_clkdm_state_switch(clkdm);
+	if (!oh)
+		return -EINVAL;
 
-	return 0;
+	return _clkdm_clk_hwmod_disable(clkdm);
 }
 
diff --git a/arch/arm/mach-omap2/clockdomain.h b/arch/arm/mach-omap2/clockdomain.h
index 2d3d970..8f0a7d6 100644
--- a/arch/arm/mach-omap2/clockdomain.h
+++ b/arch/arm/mach-omap2/clockdomain.h
@@ -20,6 +20,7 @@
 
 #include "powerdomain.h"
 #include <plat/clock.h>
+#include <plat/omap_hwmod.h>
 #include <plat/cpu.h>
 
 /*
@@ -186,6 +187,8 @@ int clkdm_sleep(struct clockdomain *clkdm);
 
 int clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk);
 int clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk);
+int clkdm_hwmod_enable(struct clockdomain *clkdm, struct omap_hwmod *oh);
+int clkdm_hwmod_disable(struct clockdomain *clkdm, struct omap_hwmod *oh);
 
 extern void __init omap2xxx_clockdomains_init(void);
 extern void __init omap3xxx_clockdomains_init(void);
-- 
1.7.0.4


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

* [PATCH v3 7/8] OMAP2+: clockdomain: Add per clkdm lock to prevent concurrent state programming
  2011-06-27 16:11 [PATCH v3 0/8] Fix module-mode enable sequence on OMAP4 Benoit Cousson
                   ` (5 preceding siblings ...)
  2011-06-27 16:11 ` [PATCH v3 6/8] OMAP2+: clockdomain: Add 2 APIs to control clockdomain from hwmod framework Benoit Cousson
@ 2011-06-27 16:11 ` Benoit Cousson
  2011-06-27 16:11 ` [PATCH v3 8/8] OMAP2+: hwmod: Follow the recommended PRCM module enable sequence Benoit Cousson
  7 siblings, 0 replies; 21+ messages in thread
From: Benoit Cousson @ 2011-06-27 16:11 UTC (permalink / raw)
  To: paul, rnayak; +Cc: santosh.shilimkar, linux-omap, toddpoynor, Benoit Cousson

From: Rajendra Nayak <rnayak@ti.com>

Since the clkdm state programming is now done from within the hwmod
framework (which uses a per-hwmod lock) instead of the being done
from the clock framework (which used a global lock), there is now a
need to have per-clkdm locking to prevent races between different
hwmods/modules belonging to the same clock domain concurrently
programming the clkdm state.

Signed-off-by: Rajendra Nayak <rnayak@ti.com>
Signed-off-by: Benoit Cousson <b-cousson@ti.com>
Cc: Paul Walmsley <paul@pwsan.com>
---
 arch/arm/mach-omap2/clockdomain.c          |   42 ++++++++++++++++++++++++++--
 arch/arm/mach-omap2/clockdomain.h          |    2 +
 arch/arm/mach-omap2/clockdomain2xxx_3xxx.c |    6 ++-
 arch/arm/mach-omap2/clockdomain44xx.c      |   13 ++------
 4 files changed, 49 insertions(+), 14 deletions(-)

diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c
index a1b22cd..70e74c4 100644
--- a/arch/arm/mach-omap2/clockdomain.c
+++ b/arch/arm/mach-omap2/clockdomain.c
@@ -92,6 +92,8 @@ static int _clkdm_register(struct clockdomain *clkdm)
 
 	pwrdm_add_clkdm(pwrdm, clkdm);
 
+	spin_lock_init(&clkdm->lock);
+
 	pr_debug("clockdomain: registered %s\n", clkdm->name);
 
 	return 0;
@@ -690,6 +692,9 @@ int clkdm_clear_all_sleepdeps(struct clockdomain *clkdm)
  */
 int clkdm_sleep(struct clockdomain *clkdm)
 {
+	int ret;
+	unsigned long flags;
+
 	if (!clkdm)
 		return -EINVAL;
 
@@ -704,7 +709,10 @@ int clkdm_sleep(struct clockdomain *clkdm)
 
 	pr_debug("clockdomain: forcing sleep on %s\n", clkdm->name);
 
-	return arch_clkdm->clkdm_sleep(clkdm);
+	spin_lock_irqsave(&clkdm->lock, flags);
+	ret = arch_clkdm->clkdm_sleep(clkdm);
+	spin_unlock_irqrestore(&clkdm->lock, flags);
+	return ret;
 }
 
 /**
@@ -718,6 +726,9 @@ int clkdm_sleep(struct clockdomain *clkdm)
  */
 int clkdm_wakeup(struct clockdomain *clkdm)
 {
+	int ret;
+	unsigned long flags;
+
 	if (!clkdm)
 		return -EINVAL;
 
@@ -732,7 +743,10 @@ int clkdm_wakeup(struct clockdomain *clkdm)
 
 	pr_debug("clockdomain: forcing wakeup on %s\n", clkdm->name);
 
-	return arch_clkdm->clkdm_wakeup(clkdm);
+	spin_lock_irqsave(&clkdm->lock, flags);
+	ret = arch_clkdm->clkdm_wakeup(clkdm);
+	spin_unlock_irqrestore(&clkdm->lock, flags);
+	return ret;
 }
 
 /**
@@ -747,6 +761,8 @@ int clkdm_wakeup(struct clockdomain *clkdm)
  */
 void clkdm_allow_idle(struct clockdomain *clkdm)
 {
+	unsigned long flags;
+
 	if (!clkdm)
 		return;
 
@@ -762,8 +778,10 @@ void clkdm_allow_idle(struct clockdomain *clkdm)
 	pr_debug("clockdomain: enabling automatic idle transitions for %s\n",
 		 clkdm->name);
 
+	spin_lock_irqsave(&clkdm->lock, flags);
 	arch_clkdm->clkdm_allow_idle(clkdm);
 	pwrdm_clkdm_state_switch(clkdm);
+	spin_unlock_irqrestore(&clkdm->lock, flags);
 }
 
 /**
@@ -777,6 +795,8 @@ void clkdm_allow_idle(struct clockdomain *clkdm)
  */
 void clkdm_deny_idle(struct clockdomain *clkdm)
 {
+	unsigned long flags;
+
 	if (!clkdm)
 		return;
 
@@ -792,7 +812,9 @@ void clkdm_deny_idle(struct clockdomain *clkdm)
 	pr_debug("clockdomain: disabling automatic idle transitions for %s\n",
 		 clkdm->name);
 
+	spin_lock_irqsave(&clkdm->lock, flags);
 	arch_clkdm->clkdm_deny_idle(clkdm);
+	spin_unlock_irqrestore(&clkdm->lock, flags);
 }
 
 /**
@@ -805,6 +827,9 @@ void clkdm_deny_idle(struct clockdomain *clkdm)
  */
 int clkdm_allows_idle(struct clockdomain *clkdm)
 {
+	int ret;
+	unsigned long flags;
+
 	if (!clkdm)
 		return -EINVAL;
 
@@ -813,7 +838,10 @@ int clkdm_allows_idle(struct clockdomain *clkdm)
 
 	pr_debug("clockdomain: reading idle state for %s\n", clkdm->name);
 
-	return arch_clkdm->clkdm_allows_idle(clkdm);
+	spin_lock_irqsave(&clkdm->lock, flags);
+	ret = arch_clkdm->clkdm_allows_idle(clkdm);
+	spin_unlock_irqrestore(&clkdm->lock, flags);
+	return ret;
 }
 
 
@@ -821,6 +849,8 @@ int clkdm_allows_idle(struct clockdomain *clkdm)
 
 static int _clkdm_clk_hwmod_enable(struct clockdomain *clkdm)
 {
+	unsigned long flags;
+
 	if (!clkdm || !arch_clkdm || !arch_clkdm->clkdm_clk_enable)
 		return -EINVAL;
 
@@ -832,9 +862,11 @@ static int _clkdm_clk_hwmod_enable(struct clockdomain *clkdm)
 	if ((atomic_inc_return(&clkdm->usecount) > 1) && autodeps)
 		return 0;
 
+	spin_lock_irqsave(&clkdm->lock, flags);
 	arch_clkdm->clkdm_clk_enable(clkdm);
 	pwrdm_wait_transition(clkdm->pwrdm.ptr);
 	pwrdm_clkdm_state_switch(clkdm);
+	spin_unlock_irqrestore(&clkdm->lock, flags);
 
 	pr_debug("clockdomain: clkdm %s: enabled\n", clkdm->name);
 
@@ -843,6 +875,8 @@ static int _clkdm_clk_hwmod_enable(struct clockdomain *clkdm)
 
 static int _clkdm_clk_hwmod_disable(struct clockdomain *clkdm)
 {
+	unsigned long flags;
+
 	if (!clkdm || !arch_clkdm || !arch_clkdm->clkdm_clk_disable)
 		return -EINVAL;
 
@@ -854,8 +888,10 @@ static int _clkdm_clk_hwmod_disable(struct clockdomain *clkdm)
 	if (atomic_dec_return(&clkdm->usecount) > 0)
 		return 0;
 
+	spin_lock_irqsave(&clkdm->lock, flags);
 	arch_clkdm->clkdm_clk_disable(clkdm);
 	pwrdm_clkdm_state_switch(clkdm);
+	spin_unlock_irqrestore(&clkdm->lock, flags);
 
 	pr_debug("clockdomain: clkdm %s: disabled\n", clkdm->name);
 
diff --git a/arch/arm/mach-omap2/clockdomain.h b/arch/arm/mach-omap2/clockdomain.h
index 8f0a7d6..b51f558 100644
--- a/arch/arm/mach-omap2/clockdomain.h
+++ b/arch/arm/mach-omap2/clockdomain.h
@@ -17,6 +17,7 @@
 #define __ARCH_ARM_MACH_OMAP2_CLOCKDOMAIN_H
 
 #include <linux/init.h>
+#include <linux/spinlock.h>
 
 #include "powerdomain.h"
 #include <plat/clock.h>
@@ -123,6 +124,7 @@ struct clockdomain {
 	const struct omap_chip_id omap_chip;
 	atomic_t usecount;
 	struct list_head node;
+	spinlock_t lock;
 };
 
 /**
diff --git a/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c b/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c
index 81f3e46..d94a121 100644
--- a/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c
+++ b/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c
@@ -193,7 +193,8 @@ static int omap2_clkdm_clk_enable(struct clockdomain *clkdm)
 		_clkdm_add_autodeps(clkdm);
 		_enable_hwsup(clkdm);
 	} else {
-		clkdm_wakeup(clkdm);
+		if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)
+			omap2_clkdm_wakeup(clkdm);
 	}
 
 	return 0;
@@ -215,7 +216,8 @@ static int omap2_clkdm_clk_disable(struct clockdomain *clkdm)
 		_clkdm_del_autodeps(clkdm);
 		_enable_hwsup(clkdm);
 	} else {
-		clkdm_sleep(clkdm);
+		if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP)
+			omap2_clkdm_sleep(clkdm);
 	}
 
 	return 0;
diff --git a/arch/arm/mach-omap2/clockdomain44xx.c b/arch/arm/mach-omap2/clockdomain44xx.c
index 1599b18..3192a5e 100644
--- a/arch/arm/mach-omap2/clockdomain44xx.c
+++ b/arch/arm/mach-omap2/clockdomain44xx.c
@@ -101,13 +101,8 @@ static int omap4_clkdm_allows_idle(struct clockdomain *clkdm)
 
 static int omap4_clkdm_clk_enable(struct clockdomain *clkdm)
 {
-	bool hwsup = false;
-
-	hwsup = omap4_cminst_is_clkdm_in_hwsup(clkdm->prcm_partition,
-					clkdm->cm_inst, clkdm->clkdm_offs);
-
-	if (!hwsup)
-		clkdm_wakeup(clkdm);
+	if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)
+		return omap4_clkdm_wakeup(clkdm);
 
 	return 0;
 }
@@ -119,8 +114,8 @@ static int omap4_clkdm_clk_disable(struct clockdomain *clkdm)
 	hwsup = omap4_cminst_is_clkdm_in_hwsup(clkdm->prcm_partition,
 					clkdm->cm_inst, clkdm->clkdm_offs);
 
-	if (!hwsup)
-		clkdm_sleep(clkdm);
+	if (!hwsup && (clkdm->flags & CLKDM_CAN_FORCE_SLEEP))
+		omap4_clkdm_sleep(clkdm);
 
 	return 0;
 }
-- 
1.7.0.4


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

* [PATCH v3 8/8] OMAP2+: hwmod: Follow the recommended PRCM module enable sequence
  2011-06-27 16:11 [PATCH v3 0/8] Fix module-mode enable sequence on OMAP4 Benoit Cousson
                   ` (6 preceding siblings ...)
  2011-06-27 16:11 ` [PATCH v3 7/8] OMAP2+: clockdomain: Add per clkdm lock to prevent concurrent state programming Benoit Cousson
@ 2011-06-27 16:11 ` Benoit Cousson
  2011-06-28  0:11   ` Kevin Hilman
  2011-06-28 17:16   ` Kevin Hilman
  7 siblings, 2 replies; 21+ messages in thread
From: Benoit Cousson @ 2011-06-27 16:11 UTC (permalink / raw)
  To: paul, rnayak; +Cc: santosh.shilimkar, linux-omap, toddpoynor, Benoit Cousson

From: Rajendra Nayak <rnayak@ti.com>

On OMAP4, the PRCM recommended sequence for enabling
a module after power-on-reset is:
-1- Force clkdm to SW_WKUP
-2- Enabling the clocks
-3- Configure desired module mode to "enable" or "auto"
-4- Wait for the desired module idle status to be FUNC
-5- Program clkdm in HW_AUTO(if supported)

This sequence applies to all older OMAPs' as well,
however since they use autodeps, it makes sure that
no clkdm is in IDLE, and hence not requiring a force
SW_WKUP when a module is being enabled.

OMAP4 does not need to support autodeps, because
of the dyanamic dependency feature, wherein
the HW takes care of waking up a clockdomain from
idle and hence the module, whenever an interconnect
access happens to the given module.

Implementing the sequence for OMAP4 requires
the clockdomain handling that is currently done in
clock framework to be done as part of hwmod framework
since the step -4- above to "Wait for the desired
module idle status to be FUNC" is done as part of
hwmod framework.

Signed-off-by: Rajendra Nayak <rnayak@ti.com>
[b-cousson@ti.com: Adapt it to the new clkdm hwmod attribute and API]
Signed-off-by: Benoit Cousson <b-cousson@ti.com>
Cc: Paul Walmsley <paul@pwsan.com>
---
 arch/arm/mach-omap2/clock.c      |   17 +----------------
 arch/arm/mach-omap2/omap_hwmod.c |   26 +++++++++++++++++++++++++-
 2 files changed, 26 insertions(+), 17 deletions(-)

diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
index 180299e..2828d29 100644
--- a/arch/arm/mach-omap2/clock.c
+++ b/arch/arm/mach-omap2/clock.c
@@ -268,9 +268,6 @@ void omap2_clk_disable(struct clk *clk)
 		clk->ops->disable(clk);
 	}
 
-	if (clk->clkdm)
-		clkdm_clk_disable(clk->clkdm, clk);
-
 	if (clk->parent)
 		omap2_clk_disable(clk->parent);
 }
@@ -308,30 +305,18 @@ int omap2_clk_enable(struct clk *clk)
 		}
 	}
 
-	if (clk->clkdm) {
-		ret = clkdm_clk_enable(clk->clkdm, clk);
-		if (ret) {
-			WARN(1, "clock: %s: could not enable clockdomain %s: "
-			     "%d\n", clk->name, clk->clkdm->name, ret);
-			goto oce_err2;
-		}
-	}
-
 	if (clk->ops && clk->ops->enable) {
 		trace_clock_enable(clk->name, 1, smp_processor_id());
 		ret = clk->ops->enable(clk);
 		if (ret) {
 			WARN(1, "clock: %s: could not enable: %d\n",
 			     clk->name, ret);
-			goto oce_err3;
+			goto oce_err2;
 		}
 	}
 
 	return 0;
 
-oce_err3:
-	if (clk->clkdm)
-		clkdm_clk_disable(clk->clkdm, clk);
 oce_err2:
 	if (clk->parent)
 		omap2_clk_disable(clk->parent);
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index 3eef106..3538805 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -1360,6 +1360,7 @@ static int _reset(struct omap_hwmod *oh)
 static int _enable(struct omap_hwmod *oh)
 {
 	int r;
+	int hwsup = 0;
 
 	if (oh->_state != _HWMOD_STATE_INITIALIZED &&
 	    oh->_state != _HWMOD_STATE_IDLE &&
@@ -1378,6 +1379,19 @@ static int _enable(struct omap_hwmod *oh)
 		omap_hwmod_mux(oh->mux, _HWMOD_STATE_ENABLED);
 
 	_add_initiator_dep(oh, mpu_oh);
+
+	/*
+	 * A clockdomain must be in SW_SUP before enabling completely the
+	 * module. The clockdomain can be set in HW_AUTO only when the module
+	 * become ready.
+	 */
+	hwsup = clkdm_allows_idle(oh->clkdm);
+	r = clkdm_hwmod_enable(oh->clkdm, oh);
+	if (r) {
+		WARN(1, "omap_hwmod: %s: could not enable clockdomain %s: %d\n",
+		     oh->name, oh->clkdm->name, r);
+		return r;
+	}
 	_enable_clocks(oh);
 	_enable_module(oh);
 
@@ -1392,6 +1406,13 @@ static int _enable(struct omap_hwmod *oh)
 
 	r = _wait_target_ready(oh);
 	if (!r) {
+		/*
+		 * Set the clockdomain to HW_AUTO only if the target is ready,
+		 * assuming that the previous state was HW_AUTO
+		 */
+		if (hwsup)
+			clkdm_allow_idle(oh->clkdm);
+
 		oh->_state = _HWMOD_STATE_ENABLED;
 
 		/* Access the sysconfig only if the target is ready */
@@ -1402,7 +1423,8 @@ static int _enable(struct omap_hwmod *oh)
 		}
 	} else {
 		_disable_clocks(oh);
-		pr_debug("omap_hwmod: %s: _wait_target_ready: %d\n",
+		clkdm_hwmod_disable(oh->clkdm, oh);
+		pr_debug("omap_hwmod: %s: _wait_target_ready failed: %d\n",
 			 oh->name, r);
 	}
 
@@ -1444,6 +1466,7 @@ static int _idle(struct omap_hwmod *oh)
 	 * transition to complete properly.
 	 */
 	_disable_clocks(oh);
+	clkdm_hwmod_disable(oh->clkdm, oh);
 
 	/* Mux pins for device idle if populated */
 	if (oh->mux && oh->mux->pads_dynamic)
@@ -1541,6 +1564,7 @@ static int _shutdown(struct omap_hwmod *oh)
 			pr_debug("omap_hwmod: %s: _wait_target_disable failed\n",
 				   oh->name);
 		_disable_clocks(oh);
+		clkdm_hwmod_disable(oh->clkdm, oh);
 	}
 	/* XXX Should this code also force-disable the optional clocks? */
 
-- 
1.7.0.4


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

* Re: [PATCH v3 2/8] OMAP2+: clockdomain: Add SoC support for clkdm_is_idle
  2011-06-27 16:11 ` [PATCH v3 2/8] OMAP2+: clockdomain: Add SoC support for clkdm_is_idle Benoit Cousson
@ 2011-06-27 19:18   ` Todd Poynor
  2011-07-01 12:24   ` Paul Walmsley
  1 sibling, 0 replies; 21+ messages in thread
From: Todd Poynor @ 2011-06-27 19:18 UTC (permalink / raw)
  To: Benoit Cousson; +Cc: paul, rnayak, santosh.shilimkar, linux-omap

On Mon, Jun 27, 2011 at 06:11:37PM +0200, Benoit Cousson wrote:
> From: Rajendra Nayak <rnayak@ti.com>
> 
> Add the SoC specific implemenation for clkdm_is_idle
> for OMAP2/3 and OMAP4.


This is now called clkdm_allows_idle.


Todd

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

* Re: [PATCH v3 8/8] OMAP2+: hwmod: Follow the recommended PRCM module enable sequence
  2011-06-27 16:11 ` [PATCH v3 8/8] OMAP2+: hwmod: Follow the recommended PRCM module enable sequence Benoit Cousson
@ 2011-06-28  0:11   ` Kevin Hilman
  2011-06-28 13:05     ` Cousson, Benoit
  2011-06-28 17:16   ` Kevin Hilman
  1 sibling, 1 reply; 21+ messages in thread
From: Kevin Hilman @ 2011-06-28  0:11 UTC (permalink / raw)
  To: Benoit Cousson; +Cc: paul, rnayak, santosh.shilimkar, linux-omap, toddpoynor

Benoit Cousson <b-cousson@ti.com> writes:

> From: Rajendra Nayak <rnayak@ti.com>
>
> On OMAP4, the PRCM recommended sequence for enabling
> a module after power-on-reset is:
> -1- Force clkdm to SW_WKUP
> -2- Enabling the clocks
> -3- Configure desired module mode to "enable" or "auto"
> -4- Wait for the desired module idle status to be FUNC
> -5- Program clkdm in HW_AUTO(if supported)
>
> This sequence applies to all older OMAPs' as well,
> however since they use autodeps, it makes sure that
> no clkdm is in IDLE, and hence not requiring a force
> SW_WKUP when a module is being enabled.
>
> OMAP4 does not need to support autodeps, because
> of the dyanamic dependency feature, wherein
> the HW takes care of waking up a clockdomain from
> idle and hence the module, whenever an interconnect
> access happens to the given module.
>
> Implementing the sequence for OMAP4 requires
> the clockdomain handling that is currently done in
> clock framework to be done as part of hwmod framework
> since the step -4- above to "Wait for the desired
> module idle status to be FUNC" is done as part of
> hwmod framework.
>
> Signed-off-by: Rajendra Nayak <rnayak@ti.com>
> [b-cousson@ti.com: Adapt it to the new clkdm hwmod attribute and API]
> Signed-off-by: Benoit Cousson <b-cousson@ti.com>
> Cc: Paul Walmsley <paul@pwsan.com>

[...]

> diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
> index 3eef106..3538805 100644
> --- a/arch/arm/mach-omap2/omap_hwmod.c
> +++ b/arch/arm/mach-omap2/omap_hwmod.c
> @@ -1360,6 +1360,7 @@ static int _reset(struct omap_hwmod *oh)
>  static int _enable(struct omap_hwmod *oh)
>  {
>  	int r;
> +	int hwsup = 0;
>  
>  	if (oh->_state != _HWMOD_STATE_INITIALIZED &&
>  	    oh->_state != _HWMOD_STATE_IDLE &&
> @@ -1378,6 +1379,19 @@ static int _enable(struct omap_hwmod *oh)
>  		omap_hwmod_mux(oh->mux, _HWMOD_STATE_ENABLED);
>  
>  	_add_initiator_dep(oh, mpu_oh);
> +
> +	/*
> +	 * A clockdomain must be in SW_SUP before enabling completely the
> +	 * module. The clockdomain can be set in HW_AUTO only when the module
> +	 * become ready.
> +	 */
> +	hwsup = clkdm_allows_idle(oh->clkdm);
> +	r = clkdm_hwmod_enable(oh->clkdm, oh);
> +	if (r) {
> +		WARN(1, "omap_hwmod: %s: could not enable clockdomain %s: %d\n",
> +		     oh->name, oh->clkdm->name, r);
> +		return r;
> +	}

If oh->clkdm == NULL (as it is on OMAP3 since the hwmod data has no
clkdms yet), this hangs trying to dereference oh->clkdm->name.

Simple fix below, but probably better is to not call any of these
functions if oh->clkdm == NULL, otherwise this is very noisy on OMAP3
since that WARN is printed for every hwmod.

Is anyone planning to add the clkdms to OMAP3 hwmod data?

Kevin


diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index 51a13f3..4bcffca 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -1391,9 +1391,10 @@ static int _enable(struct omap_hwmod *oh)
 	r = clkdm_hwmod_enable(oh->clkdm, oh);
 	if (r) {
 		WARN(1, "omap_hwmod: %s: could not enable clockdomain %s: %d\n",
-		     oh->name, oh->clkdm->name, r);
+		     oh->name, oh->clkdm ? oh->clkdm->name : "none", r);
 		return r;
 	}
+
 	_enable_clocks(oh);
 	_enable_module(oh);
 

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

* Re: [PATCH v3 4/8] OMAP2+: PM: idle clkdms only if already in idle
  2011-06-27 16:11 ` [PATCH v3 4/8] OMAP2+: PM: idle clkdms only if already in idle Benoit Cousson
@ 2011-06-28  1:00   ` Todd Poynor
  0 siblings, 0 replies; 21+ messages in thread
From: Todd Poynor @ 2011-06-28  1:00 UTC (permalink / raw)
  To: Benoit Cousson; +Cc: paul, rnayak, santosh.shilimkar, linux-omap

On Mon, Jun 27, 2011 at 06:11:39PM +0200, Benoit Cousson wrote:
> From: Rajendra Nayak <rnayak@ti.com>
> 
> The omap_set_pwrdm_state function forces clockdomains
> to idle, without checking the existing idle state
> programmed, instead based solely on the HW capability
> of the clockdomain to support idle.
> This is wrong and the clockdomains should be idled
> post a state_switch *only* if idle transitions on the
> clockdomain were already enabled.
...
>  		} else {
> +			hwsup = clkdm_allows_idle(pwrdm->pwrdm_clkdms[0]);
>  			clkdm_wakeup(pwrdm->pwrdm_clkdms[0]);
>  			pwrdm_wait_transition(pwrdm);
>  			sleep_switch = FORCEWAKEUP_SWITCH;
> @@ -142,7 +144,7 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state)
>  
>  	switch (sleep_switch) {
>  	case FORCEWAKEUP_SWITCH:
> -		if (pwrdm->pwrdm_clkdms[0]->flags & CLKDM_CAN_ENABLE_AUTO)
> +		if (hwsup)
>  			clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]);
>  		else
>  			clkdm_sleep(pwrdm->pwrdm_clkdms[0]);

Since it seems these power domain state transitions could be executed
concurrently with other operations on the clock domain that is first
in the list, is there still a chance for a race, such that it may no
longer be appropriate to put the clock domain in h/w-supervised idle
mode after the power domain transition is complete?  If so, perhaps an
atomic wakeup refcount could flag when it is OK to allow idle on the
clock domain.


Todd

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

* Re: [PATCH v3 6/8] OMAP2+: clockdomain: Add 2 APIs to control clockdomain from hwmod framework
  2011-06-27 16:11 ` [PATCH v3 6/8] OMAP2+: clockdomain: Add 2 APIs to control clockdomain from hwmod framework Benoit Cousson
@ 2011-06-28  1:08   ` Todd Poynor
  0 siblings, 0 replies; 21+ messages in thread
From: Todd Poynor @ 2011-06-28  1:08 UTC (permalink / raw)
  To: Benoit Cousson; +Cc: paul, rnayak, santosh.shilimkar, linux-omap

On Mon, Jun 27, 2011 at 06:11:41PM +0200, Benoit Cousson wrote:
...
> + * clkdm_hwmod_disable - remove an enabled downstream hwmod from this clkdm
> + * @clkdm: struct clockdomain *
> + * @oh: struct omap_hwmod * of the disabled downstream hwmod
> + *
> + * Decrement the usecount of this clockdomain @clkdm when @oh is
> + * disabled. Intended to be called by module_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

Can take out "and debugging is enabled", this is no longer the case.


Todd

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

* Re: [PATCH v3 8/8] OMAP2+: hwmod: Follow the recommended PRCM module enable sequence
  2011-06-28  0:11   ` Kevin Hilman
@ 2011-06-28 13:05     ` Cousson, Benoit
  2011-06-28 22:03       ` Rajendra Nayak
  0 siblings, 1 reply; 21+ messages in thread
From: Cousson, Benoit @ 2011-06-28 13:05 UTC (permalink / raw)
  To: Hilman, Kevin
  Cc: paul, Nayak, Rajendra, Shilimkar, Santosh, linux-omap, toddpoynor

Hi Kevin,

On 6/28/2011 2:11 AM, Hilman, Kevin wrote:
> Benoit Cousson<b-cousson@ti.com>  writes:
> 
>> From: Rajendra Nayak<rnayak@ti.com>
>>
>> On OMAP4, the PRCM recommended sequence for enabling
>> a module after power-on-reset is:
>> -1- Force clkdm to SW_WKUP
>> -2- Enabling the clocks
>> -3- Configure desired module mode to "enable" or "auto"
>> -4- Wait for the desired module idle status to be FUNC
>> -5- Program clkdm in HW_AUTO(if supported)
>>
>> This sequence applies to all older OMAPs' as well,
>> however since they use autodeps, it makes sure that
>> no clkdm is in IDLE, and hence not requiring a force
>> SW_WKUP when a module is being enabled.
>>
>> OMAP4 does not need to support autodeps, because
>> of the dyanamic dependency feature, wherein
>> the HW takes care of waking up a clockdomain from
>> idle and hence the module, whenever an interconnect
>> access happens to the given module.
>>
>> Implementing the sequence for OMAP4 requires
>> the clockdomain handling that is currently done in
>> clock framework to be done as part of hwmod framework
>> since the step -4- above to "Wait for the desired
>> module idle status to be FUNC" is done as part of
>> hwmod framework.
>>
>> Signed-off-by: Rajendra Nayak<rnayak@ti.com>
>> [b-cousson@ti.com: Adapt it to the new clkdm hwmod attribute and API]
>> Signed-off-by: Benoit Cousson<b-cousson@ti.com>
>> Cc: Paul Walmsley<paul@pwsan.com>
> 
> [...]
> 
>> diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
>> index 3eef106..3538805 100644
>> --- a/arch/arm/mach-omap2/omap_hwmod.c
>> +++ b/arch/arm/mach-omap2/omap_hwmod.c
>> @@ -1360,6 +1360,7 @@ static int _reset(struct omap_hwmod *oh)
>>   static int _enable(struct omap_hwmod *oh)
>>   {
>>   	int r;
>> +	int hwsup = 0;
>>
>>   	if (oh->_state != _HWMOD_STATE_INITIALIZED&&
>>   	oh->_state != _HWMOD_STATE_IDLE&&
>> @@ -1378,6 +1379,19 @@ static int _enable(struct omap_hwmod *oh)
>>   		omap_hwmod_mux(oh->mux, _HWMOD_STATE_ENABLED);
>>
>>   	_add_initiator_dep(oh, mpu_oh);
>> +
>> +	/*
>> +	 * A clockdomain must be in SW_SUP before enabling completely the
>> +	 * module. The clockdomain can be set in HW_AUTO only when the module
>> +	 * become ready.
>> +	 */
>> +	hwsup = clkdm_allows_idle(oh->clkdm);
>> +	r = clkdm_hwmod_enable(oh->clkdm, oh);
>> +	if (r) {
>> +		WARN(1, "omap_hwmod: %s: could not enable clockdomain %s: %d\n",
>> +		     oh->name, oh->clkdm->name, r);
>> +		return r;
>> +	}
> 
> If oh->clkdm == NULL (as it is on OMAP3 since the hwmod data has no
> clkdms yet), this hangs trying to dereference oh->clkdm->name.
> 
> Simple fix below, but probably better is to not call any of these
> functions if oh->clkdm == NULL, otherwise this is very noisy on OMAP3
> since that WARN is printed for every hwmod.

I can as well prevent the clkdm_hwmod_enable function to return any errors in case of omap2 & omap3... 

> Is anyone planning to add the clkdms to OMAP3 hwmod data?

Euh, I'm not sure:-) So I've just updated the OMAP3.
I guess the next question will be: Is anyone planning to add the clkdms to OMAP2 hwmod data?

Regards,
Benoit

---
>From 14916037799ed0d516c8c335f861d2d5248d1c33 Mon Sep 17 00:00:00 2001
From: Benoit Cousson <b-cousson@ti.com>
Date: Tue, 28 Jun 2011 14:53:28 +0200
Subject: [PATCH] OMAP3: hwmod data: Add clock domain attribute

Add a clkdm_name attribute to provide this information per hwmod.

Signed-off-by: Benoit Cousson <b-cousson@ti.com>
Cc: Paul Walmsley <paul@pwsan.com>
Cc: Rajendra Nayak <rnayak@ti.com>
---
 arch/arm/mach-omap2/omap_hwmod_3xxx_data.c |   60 ++++++++++++++++++++++++++++
 1 files changed, 60 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
index d0c82de..91e75cf 100644
--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
@@ -149,6 +149,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_l3_main_masters[] = {
 /* L3 */
 static struct omap_hwmod omap3xxx_l3_main_hwmod = {
 	.name		= "l3_main",
+	.clkdm_name	= "core_l3_clkdm",
 	.class		= &l3_hwmod_class,
 	.mpu_irqs       = omap3xxx_l3_main_irqs,
 	.mpu_irqs_cnt   = ARRAY_SIZE(omap3xxx_l3_main_irqs),
@@ -495,6 +496,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_l4_core_slaves[] = {
 /* L4 CORE */
 static struct omap_hwmod omap3xxx_l4_core_hwmod = {
 	.name		= "l4_core",
+	.clkdm_name	= "core_l4_clkdm",
 	.class		= &l4_hwmod_class,
 	.slaves		= omap3xxx_l4_core_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_l4_core_slaves),
@@ -510,6 +512,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_l4_per_slaves[] = {
 /* L4 PER */
 static struct omap_hwmod omap3xxx_l4_per_hwmod = {
 	.name		= "l4_per",
+	.clkdm_name	= "per_clkdm",
 	.class		= &l4_hwmod_class,
 	.slaves		= omap3xxx_l4_per_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_l4_per_slaves),
@@ -525,6 +528,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_l4_wkup_slaves[] = {
 /* L4 WKUP */
 static struct omap_hwmod omap3xxx_l4_wkup_hwmod = {
 	.name		= "l4_wkup",
+	.clkdm_name	= "wkup_clkdm",
 	.class		= &l4_hwmod_class,
 	.slaves		= omap3xxx_l4_wkup_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_l4_wkup_slaves),
@@ -540,6 +544,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_mpu_masters[] = {
 /* MPU */
 static struct omap_hwmod omap3xxx_mpu_hwmod = {
 	.name		= "mpu",
+	.clkdm_name	= "mpu_clkdm",
 	.class		= &mpu_hwmod_class,
 	.main_clk	= "arm_fck",
 	.masters	= omap3xxx_mpu_masters,
@@ -569,6 +574,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_iva_masters[] = {
 
 static struct omap_hwmod omap3xxx_iva_hwmod = {
 	.name		= "iva",
+	.clkdm_name	= "iva2_clkdm",
 	.class		= &iva_hwmod_class,
 	.masters	= omap3xxx_iva_masters,
 	.masters_cnt	= ARRAY_SIZE(omap3xxx_iva_masters),
@@ -641,6 +647,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_timer1_slaves[] = {
 /* timer1 hwmod */
 static struct omap_hwmod omap3xxx_timer1_hwmod = {
 	.name		= "timer1",
+	.clkdm_name	= "wkup_clkdm",
 	.mpu_irqs	= omap3xxx_timer1_mpu_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_timer1_mpu_irqs),
 	.main_clk	= "gpt1_fck",
@@ -691,6 +698,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_timer2_slaves[] = {
 /* timer2 hwmod */
 static struct omap_hwmod omap3xxx_timer2_hwmod = {
 	.name		= "timer2",
+	.clkdm_name	= "per_clkdm",
 	.mpu_irqs	= omap3xxx_timer2_mpu_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_timer2_mpu_irqs),
 	.main_clk	= "gpt2_fck",
@@ -741,6 +749,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_timer3_slaves[] = {
 /* timer3 hwmod */
 static struct omap_hwmod omap3xxx_timer3_hwmod = {
 	.name		= "timer3",
+	.clkdm_name	= "per_clkdm",
 	.mpu_irqs	= omap3xxx_timer3_mpu_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_timer3_mpu_irqs),
 	.main_clk	= "gpt3_fck",
@@ -791,6 +800,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_timer4_slaves[] = {
 /* timer4 hwmod */
 static struct omap_hwmod omap3xxx_timer4_hwmod = {
 	.name		= "timer4",
+	.clkdm_name	= "per_clkdm",
 	.mpu_irqs	= omap3xxx_timer4_mpu_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_timer4_mpu_irqs),
 	.main_clk	= "gpt4_fck",
@@ -841,6 +851,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_timer5_slaves[] = {
 /* timer5 hwmod */
 static struct omap_hwmod omap3xxx_timer5_hwmod = {
 	.name		= "timer5",
+	.clkdm_name	= "per_clkdm",
 	.mpu_irqs	= omap3xxx_timer5_mpu_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_timer5_mpu_irqs),
 	.main_clk	= "gpt5_fck",
@@ -891,6 +902,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_timer6_slaves[] = {
 /* timer6 hwmod */
 static struct omap_hwmod omap3xxx_timer6_hwmod = {
 	.name		= "timer6",
+	.clkdm_name	= "per_clkdm",
 	.mpu_irqs	= omap3xxx_timer6_mpu_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_timer6_mpu_irqs),
 	.main_clk	= "gpt6_fck",
@@ -941,6 +953,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_timer7_slaves[] = {
 /* timer7 hwmod */
 static struct omap_hwmod omap3xxx_timer7_hwmod = {
 	.name		= "timer7",
+	.clkdm_name	= "per_clkdm",
 	.mpu_irqs	= omap3xxx_timer7_mpu_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_timer7_mpu_irqs),
 	.main_clk	= "gpt7_fck",
@@ -991,6 +1004,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_timer8_slaves[] = {
 /* timer8 hwmod */
 static struct omap_hwmod omap3xxx_timer8_hwmod = {
 	.name		= "timer8",
+	.clkdm_name	= "per_clkdm",
 	.mpu_irqs	= omap3xxx_timer8_mpu_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_timer8_mpu_irqs),
 	.main_clk	= "gpt8_fck",
@@ -1041,6 +1055,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_timer9_slaves[] = {
 /* timer9 hwmod */
 static struct omap_hwmod omap3xxx_timer9_hwmod = {
 	.name		= "timer9",
+	.clkdm_name	= "per_clkdm",
 	.mpu_irqs	= omap3xxx_timer9_mpu_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_timer9_mpu_irqs),
 	.main_clk	= "gpt9_fck",
@@ -1091,6 +1106,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_timer10_slaves[] = {
 /* timer10 hwmod */
 static struct omap_hwmod omap3xxx_timer10_hwmod = {
 	.name		= "timer10",
+	.clkdm_name	= "core_l4_clkdm",
 	.mpu_irqs	= omap3xxx_timer10_mpu_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_timer10_mpu_irqs),
 	.main_clk	= "gpt10_fck",
@@ -1141,6 +1157,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_timer11_slaves[] = {
 /* timer11 hwmod */
 static struct omap_hwmod omap3xxx_timer11_hwmod = {
 	.name		= "timer11",
+	.clkdm_name	= "core_l4_clkdm",
 	.mpu_irqs	= omap3xxx_timer11_mpu_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_timer11_mpu_irqs),
 	.main_clk	= "gpt11_fck",
@@ -1191,6 +1208,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_timer12_slaves[] = {
 /* timer12 hwmod */
 static struct omap_hwmod omap3xxx_timer12_hwmod = {
 	.name		= "timer12",
+	.clkdm_name	= "wkup_clkdm",
 	.mpu_irqs	= omap3xxx_timer12_mpu_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_timer12_mpu_irqs),
 	.main_clk	= "gpt12_fck",
@@ -1271,6 +1289,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_wd_timer2_slaves[] = {
 static struct omap_hwmod omap3xxx_wd_timer2_hwmod = {
 	.name		= "wd_timer2",
 	.class		= &omap3xxx_wd_timer_hwmod_class,
+	.clkdm_name	= "wkup_clkdm",
 	.main_clk	= "wdt2_fck",
 	.prcm		= {
 		.omap2 = {
@@ -1326,6 +1345,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_uart1_slaves[] = {
 
 static struct omap_hwmod omap3xxx_uart1_hwmod = {
 	.name		= "uart1",
+	.clkdm_name	= "core_l4_clkdm",
 	.mpu_irqs	= uart1_mpu_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(uart1_mpu_irqs),
 	.sdma_reqs	= uart1_sdma_reqs,
@@ -1363,6 +1383,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_uart2_slaves[] = {
 
 static struct omap_hwmod omap3xxx_uart2_hwmod = {
 	.name		= "uart2",
+	.clkdm_name	= "core_l4_clkdm",
 	.mpu_irqs	= uart2_mpu_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(uart2_mpu_irqs),
 	.sdma_reqs	= uart2_sdma_reqs,
@@ -1400,6 +1421,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_uart3_slaves[] = {
 
 static struct omap_hwmod omap3xxx_uart3_hwmod = {
 	.name		= "uart3",
+	.clkdm_name	= "per_clkdm",
 	.mpu_irqs	= uart3_mpu_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(uart3_mpu_irqs),
 	.sdma_reqs	= uart3_sdma_reqs,
@@ -1437,6 +1459,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_uart4_slaves[] = {
 
 static struct omap_hwmod omap3xxx_uart4_hwmod = {
 	.name		= "uart4",
+	.clkdm_name	= "per_clkdm",
 	.mpu_irqs	= uart4_mpu_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(uart4_mpu_irqs),
 	.sdma_reqs	= uart4_sdma_reqs,
@@ -1549,6 +1572,7 @@ static struct omap_hwmod_opt_clk dss_opt_clks[] = {
 
 static struct omap_hwmod omap3430es1_dss_core_hwmod = {
 	.name		= "dss_core",
+	.clkdm_name	= "dss_clkdm",
 	.class		= &omap3xxx_dss_hwmod_class,
 	.main_clk	= "dss1_alwon_fck", /* instead of dss_fck */
 	.sdma_reqs	= omap3xxx_dss_sdma_chs,
@@ -1575,6 +1599,7 @@ static struct omap_hwmod omap3430es1_dss_core_hwmod = {
 
 static struct omap_hwmod omap3xxx_dss_core_hwmod = {
 	.name		= "dss_core",
+	.clkdm_name	= "dss_clkdm",
 	.class		= &omap3xxx_dss_hwmod_class,
 	.main_clk	= "dss1_alwon_fck", /* instead of dss_fck */
 	.sdma_reqs	= omap3xxx_dss_sdma_chs,
@@ -1658,6 +1683,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_dispc_slaves[] = {
 
 static struct omap_hwmod omap3xxx_dss_dispc_hwmod = {
 	.name		= "dss_dispc",
+	.clkdm_name	= "dss_clkdm",
 	.class		= &omap3xxx_dispc_hwmod_class,
 	.mpu_irqs	= omap3xxx_dispc_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_dispc_irqs),
@@ -1722,6 +1748,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_dsi1_slaves[] = {
 
 static struct omap_hwmod omap3xxx_dss_dsi1_hwmod = {
 	.name		= "dss_dsi1",
+	.clkdm_name	= "dss_clkdm",
 	.class		= &omap3xxx_dsi_hwmod_class,
 	.mpu_irqs	= omap3xxx_dsi1_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_dsi1_irqs),
@@ -1793,6 +1820,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_rfbi_slaves[] = {
 
 static struct omap_hwmod omap3xxx_dss_rfbi_hwmod = {
 	.name		= "dss_rfbi",
+	.clkdm_name	= "dss_clkdm",
 	.class		= &omap3xxx_rfbi_hwmod_class,
 	.main_clk	= "dss1_alwon_fck",
 	.prcm		= {
@@ -1853,6 +1881,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_venc_slaves[] = {
 
 static struct omap_hwmod omap3xxx_dss_venc_hwmod = {
 	.name		= "dss_venc",
+	.clkdm_name	= "dss_clkdm",
 	.class		= &omap3xxx_venc_hwmod_class,
 	.main_clk	= "dss1_alwon_fck",
 	.prcm		= {
@@ -1891,6 +1920,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_i2c1_slaves[] = {
 
 static struct omap_hwmod omap3xxx_i2c1_hwmod = {
 	.name		= "i2c1",
+	.clkdm_name	= "core_l4_clkdm",
 	.mpu_irqs	= i2c1_mpu_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(i2c1_mpu_irqs),
 	.sdma_reqs	= i2c1_sdma_reqs,
@@ -1933,6 +1963,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_i2c2_slaves[] = {
 
 static struct omap_hwmod omap3xxx_i2c2_hwmod = {
 	.name		= "i2c2",
+	.clkdm_name	= "core_l4_clkdm",
 	.mpu_irqs	= i2c2_mpu_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(i2c2_mpu_irqs),
 	.sdma_reqs	= i2c2_sdma_reqs,
@@ -1975,6 +2006,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_i2c3_slaves[] = {
 
 static struct omap_hwmod omap3xxx_i2c3_hwmod = {
 	.name		= "i2c3",
+	.clkdm_name	= "core_l4_clkdm",
 	.mpu_irqs	= i2c3_mpu_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(i2c3_mpu_irqs),
 	.sdma_reqs	= i2c3_sdma_reqs,
@@ -2141,6 +2173,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_gpio1_slaves[] = {
 
 static struct omap_hwmod omap3xxx_gpio1_hwmod = {
 	.name		= "gpio1",
+	.clkdm_name	= "wkup_clkdm",
 	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
 	.mpu_irqs	= omap3xxx_gpio1_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_gpio1_irqs),
@@ -2178,6 +2211,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_gpio2_slaves[] = {
 
 static struct omap_hwmod omap3xxx_gpio2_hwmod = {
 	.name		= "gpio2",
+	.clkdm_name	= "per_clkdm",
 	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
 	.mpu_irqs	= omap3xxx_gpio2_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_gpio2_irqs),
@@ -2215,6 +2249,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_gpio3_slaves[] = {
 
 static struct omap_hwmod omap3xxx_gpio3_hwmod = {
 	.name		= "gpio3",
+	.clkdm_name	= "per_clkdm",
 	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
 	.mpu_irqs	= omap3xxx_gpio3_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_gpio3_irqs),
@@ -2252,6 +2287,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_gpio4_slaves[] = {
 
 static struct omap_hwmod omap3xxx_gpio4_hwmod = {
 	.name		= "gpio4",
+	.clkdm_name	= "per_clkdm",
 	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
 	.mpu_irqs	= omap3xxx_gpio4_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_gpio4_irqs),
@@ -2289,6 +2325,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_gpio5_slaves[] = {
 
 static struct omap_hwmod omap3xxx_gpio5_hwmod = {
 	.name		= "gpio5",
+	.clkdm_name	= "per_clkdm",
 	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
 	.mpu_irqs	= omap3xxx_gpio5_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_gpio5_irqs),
@@ -2326,6 +2363,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_gpio6_slaves[] = {
 
 static struct omap_hwmod omap3xxx_gpio6_hwmod = {
 	.name		= "gpio6",
+	.clkdm_name	= "per_clkdm",
 	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
 	.mpu_irqs	= omap3xxx_gpio6_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_gpio6_irqs),
@@ -2419,6 +2457,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_dma_system_slaves[] = {
 
 static struct omap_hwmod omap3xxx_dma_system_hwmod = {
 	.name		= "dma",
+	.clkdm_name	= "core_l3_clkdm",
 	.class		= &omap3xxx_dma_hwmod_class,
 	.mpu_irqs	= omap3xxx_dma_system_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_dma_system_irqs),
@@ -2499,6 +2538,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_mcbsp1_slaves[] = {
 
 static struct omap_hwmod omap3xxx_mcbsp1_hwmod = {
 	.name		= "mcbsp1",
+	.clkdm_name	= "core_l4_clkdm",
 	.class		= &omap3xxx_mcbsp_hwmod_class,
 	.mpu_irqs	= omap3xxx_mcbsp1_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_mcbsp1_irqs),
@@ -2561,6 +2601,7 @@ static struct omap_mcbsp_dev_attr omap34xx_mcbsp2_dev_attr = {
 
 static struct omap_hwmod omap3xxx_mcbsp2_hwmod = {
 	.name		= "mcbsp2",
+	.clkdm_name	= "per_clkdm",
 	.class		= &omap3xxx_mcbsp_hwmod_class,
 	.mpu_irqs	= omap3xxx_mcbsp2_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_mcbsp2_irqs),
@@ -2624,6 +2665,7 @@ static struct omap_mcbsp_dev_attr omap34xx_mcbsp3_dev_attr = {
 
 static struct omap_hwmod omap3xxx_mcbsp3_hwmod = {
 	.name		= "mcbsp3",
+	.clkdm_name	= "per_clkdm",
 	.class		= &omap3xxx_mcbsp_hwmod_class,
 	.mpu_irqs	= omap3xxx_mcbsp3_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_mcbsp3_irqs),
@@ -2683,6 +2725,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_mcbsp4_slaves[] = {
 
 static struct omap_hwmod omap3xxx_mcbsp4_hwmod = {
 	.name		= "mcbsp4",
+	.clkdm_name	= "per_clkdm",
 	.class		= &omap3xxx_mcbsp_hwmod_class,
 	.mpu_irqs	= omap3xxx_mcbsp4_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_mcbsp4_irqs),
@@ -2741,6 +2784,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_mcbsp5_slaves[] = {
 
 static struct omap_hwmod omap3xxx_mcbsp5_hwmod = {
 	.name		= "mcbsp5",
+	.clkdm_name	= "core_l4_clkdm",
 	.class		= &omap3xxx_mcbsp_hwmod_class,
 	.mpu_irqs	= omap3xxx_mcbsp5_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_mcbsp5_irqs),
@@ -2804,6 +2848,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_mcbsp2_sidetone_slaves[] = {
 
 static struct omap_hwmod omap3xxx_mcbsp2_sidetone_hwmod = {
 	.name		= "mcbsp2_sidetone",
+	.clkdm_name	= "per_clkdm",
 	.class		= &omap3xxx_mcbsp_sidetone_hwmod_class,
 	.mpu_irqs	= omap3xxx_mcbsp2_sidetone_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_mcbsp2_sidetone_irqs),
@@ -2853,6 +2898,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_mcbsp3_sidetone_slaves[] = {
 
 static struct omap_hwmod omap3xxx_mcbsp3_sidetone_hwmod = {
 	.name		= "mcbsp3_sidetone",
+	.clkdm_name	= "per_clkdm",
 	.class		= &omap3xxx_mcbsp_sidetone_hwmod_class,
 	.mpu_irqs	= omap3xxx_mcbsp3_sidetone_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_mcbsp3_sidetone_irqs),
@@ -2916,6 +2962,7 @@ static struct omap_hwmod_ocp_if *omap3_sr1_slaves[] = {
 
 static struct omap_hwmod omap34xx_sr1_hwmod = {
 	.name		= "sr1_hwmod",
+	.clkdm_name	= "wkup_clkdm",
 	.class		= &omap34xx_smartreflex_hwmod_class,
 	.main_clk	= "sr1_fck",
 	.vdd_name	= "mpu",
@@ -2938,6 +2985,7 @@ static struct omap_hwmod omap34xx_sr1_hwmod = {
 
 static struct omap_hwmod omap36xx_sr1_hwmod = {
 	.name		= "sr1_hwmod",
+	.clkdm_name	= "wkup_clkdm",
 	.class		= &omap36xx_smartreflex_hwmod_class,
 	.main_clk	= "sr1_fck",
 	.vdd_name	= "mpu",
@@ -2962,6 +3010,7 @@ static struct omap_hwmod_ocp_if *omap3_sr2_slaves[] = {
 
 static struct omap_hwmod omap34xx_sr2_hwmod = {
 	.name		= "sr2_hwmod",
+	.clkdm_name	= "wkup_clkdm",
 	.class		= &omap34xx_smartreflex_hwmod_class,
 	.main_clk	= "sr2_fck",
 	.vdd_name	= "core",
@@ -2984,6 +3033,7 @@ static struct omap_hwmod omap34xx_sr2_hwmod = {
 
 static struct omap_hwmod omap36xx_sr2_hwmod = {
 	.name		= "sr2_hwmod",
+	.clkdm_name	= "wkup_clkdm",
 	.class		= &omap36xx_smartreflex_hwmod_class,
 	.main_clk	= "sr2_fck",
 	.vdd_name	= "core",
@@ -3051,6 +3101,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_mailbox_slaves[] = {
 
 static struct omap_hwmod omap3xxx_mailbox_hwmod = {
 	.name		= "mailbox",
+	.clkdm_name	= "core_l4_clkdm",
 	.class		= &omap3xxx_mailbox_hwmod_class,
 	.mpu_irqs	= omap3xxx_mailbox_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_mailbox_irqs),
@@ -3190,6 +3241,7 @@ static struct omap2_mcspi_dev_attr omap_mcspi1_dev_attr = {
 
 static struct omap_hwmod omap34xx_mcspi1 = {
 	.name		= "mcspi1",
+	.clkdm_name	= "core_l4_clkdm",
 	.mpu_irqs	= omap34xx_mcspi1_mpu_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(omap34xx_mcspi1_mpu_irqs),
 	.sdma_reqs	= omap34xx_mcspi1_sdma_reqs,
@@ -3233,6 +3285,7 @@ static struct omap2_mcspi_dev_attr omap_mcspi2_dev_attr = {
 
 static struct omap_hwmod omap34xx_mcspi2 = {
 	.name		= "mcspi2",
+	.clkdm_name	= "core_l4_clkdm",
 	.mpu_irqs	= omap34xx_mcspi2_mpu_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(omap34xx_mcspi2_mpu_irqs),
 	.sdma_reqs	= omap34xx_mcspi2_sdma_reqs,
@@ -3276,6 +3329,7 @@ static struct omap2_mcspi_dev_attr omap_mcspi3_dev_attr = {
 
 static struct omap_hwmod omap34xx_mcspi3 = {
 	.name		= "mcspi3",
+	.clkdm_name	= "core_l4_clkdm",
 	.mpu_irqs	= omap34xx_mcspi3_mpu_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(omap34xx_mcspi3_mpu_irqs),
 	.sdma_reqs	= omap34xx_mcspi3_sdma_reqs,
@@ -3317,6 +3371,7 @@ static struct omap2_mcspi_dev_attr omap_mcspi4_dev_attr = {
 
 static struct omap_hwmod omap34xx_mcspi4 = {
 	.name		= "mcspi4",
+	.clkdm_name	= "core_l4_clkdm",
 	.mpu_irqs	= omap34xx_mcspi4_mpu_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(omap34xx_mcspi4_mpu_irqs),
 	.sdma_reqs	= omap34xx_mcspi4_sdma_reqs,
@@ -3366,6 +3421,7 @@ static struct omap_hwmod_irq_info omap3xxx_usbhsotg_mpu_irqs[] = {
 
 static struct omap_hwmod omap3xxx_usbhsotg_hwmod = {
 	.name		= "usb_otg_hs",
+	.clkdm_name	= "core_l3_clkdm",
 	.mpu_irqs	= omap3xxx_usbhsotg_mpu_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_usbhsotg_mpu_irqs),
 	.main_clk	= "hsotgusb_ick",
@@ -3408,6 +3464,7 @@ static struct omap_hwmod_class am35xx_usbotg_class = {
 
 static struct omap_hwmod am35xx_usbhsotg_hwmod = {
 	.name		= "am35x_otg_hs",
+	.clkdm_name	= "core_l3_clkdm",
 	.mpu_irqs	= am35xx_usbhsotg_mpu_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(am35xx_usbhsotg_mpu_irqs),
 	.main_clk	= NULL,
@@ -3466,6 +3523,7 @@ static struct omap_mmc_dev_attr mmc1_dev_attr = {
 
 static struct omap_hwmod omap3xxx_mmc1_hwmod = {
 	.name		= "mmc1",
+	.clkdm_name	= "core_l4_clkdm",
 	.mpu_irqs	= omap34xx_mmc1_mpu_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(omap34xx_mmc1_mpu_irqs),
 	.sdma_reqs	= omap34xx_mmc1_sdma_reqs,
@@ -3511,6 +3569,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_mmc2_slaves[] = {
 
 static struct omap_hwmod omap3xxx_mmc2_hwmod = {
 	.name		= "mmc2",
+	.clkdm_name	= "core_l4_clkdm",
 	.mpu_irqs	= omap34xx_mmc2_mpu_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(omap34xx_mmc2_mpu_irqs),
 	.sdma_reqs	= omap34xx_mmc2_sdma_reqs,
@@ -3555,6 +3614,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_mmc3_slaves[] = {
 
 static struct omap_hwmod omap3xxx_mmc3_hwmod = {
 	.name		= "mmc3",
+	.clkdm_name	= "core_l4_clkdm",
 	.mpu_irqs	= omap34xx_mmc3_mpu_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(omap34xx_mmc3_mpu_irqs),
 	.sdma_reqs	= omap34xx_mmc3_sdma_reqs,
-- 
1.7.0.4


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

* Re: [PATCH v3 8/8] OMAP2+: hwmod: Follow the recommended PRCM module enable sequence
  2011-06-27 16:11 ` [PATCH v3 8/8] OMAP2+: hwmod: Follow the recommended PRCM module enable sequence Benoit Cousson
  2011-06-28  0:11   ` Kevin Hilman
@ 2011-06-28 17:16   ` Kevin Hilman
  2011-06-28 21:33     ` Cousson, Benoit
  1 sibling, 1 reply; 21+ messages in thread
From: Kevin Hilman @ 2011-06-28 17:16 UTC (permalink / raw)
  To: Benoit Cousson; +Cc: paul, rnayak, santosh.shilimkar, linux-omap, toddpoynor

Benoit Cousson <b-cousson@ti.com> writes:

> From: Rajendra Nayak <rnayak@ti.com>
>
> On OMAP4, the PRCM recommended sequence for enabling
> a module after power-on-reset is:
> -1- Force clkdm to SW_WKUP
> -2- Enabling the clocks
> -3- Configure desired module mode to "enable" or "auto"
> -4- Wait for the desired module idle status to be FUNC
> -5- Program clkdm in HW_AUTO(if supported)
>
> This sequence applies to all older OMAPs' as well,
> however since they use autodeps, it makes sure that
> no clkdm is in IDLE, and hence not requiring a force
> SW_WKUP when a module is being enabled.

OK, I found the problem that prevents booting on OMAP3...

> OMAP4 does not need to support autodeps, because
> of the dyanamic dependency feature, wherein
> the HW takes care of waking up a clockdomain from
> idle and hence the module, whenever an interconnect
> access happens to the given module.
>
> Implementing the sequence for OMAP4 requires
> the clockdomain handling that is currently done in
> clock framework to be done as part of hwmod framework
> since the step -4- above to "Wait for the desired
> module idle status to be FUNC" is done as part of
> hwmod framework.
>
> Signed-off-by: Rajendra Nayak <rnayak@ti.com>
> [b-cousson@ti.com: Adapt it to the new clkdm hwmod attribute and API]
> Signed-off-by: Benoit Cousson <b-cousson@ti.com>
> Cc: Paul Walmsley <paul@pwsan.com>
> ---
>  arch/arm/mach-omap2/clock.c      |   17 +----------------
>  arch/arm/mach-omap2/omap_hwmod.c |   26 +++++++++++++++++++++++++-
>  2 files changed, 26 insertions(+), 17 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
> index 180299e..2828d29 100644
> --- a/arch/arm/mach-omap2/clock.c
> +++ b/arch/arm/mach-omap2/clock.c
> @@ -268,9 +268,6 @@ void omap2_clk_disable(struct clk *clk)
>  		clk->ops->disable(clk);
>  	}
>  
> -	if (clk->clkdm)
> -		clkdm_clk_disable(clk->clkdm, clk);
> -
>  	if (clk->parent)
>  		omap2_clk_disable(clk->parent);
>  }
> @@ -308,30 +305,18 @@ int omap2_clk_enable(struct clk *clk)
>  		}
>  	}
>  
> -	if (clk->clkdm) {
> -		ret = clkdm_clk_enable(clk->clkdm, clk);
> -		if (ret) {
> -			WARN(1, "clock: %s: could not enable clockdomain %s: "
> -			     "%d\n", clk->name, clk->clkdm->name, ret);
> -			goto oce_err2;
> -		}
> -	}
> -
>  	if (clk->ops && clk->ops->enable) {
>  		trace_clock_enable(clk->name, 1, smp_processor_id());
>  		ret = clk->ops->enable(clk);
>  		if (ret) {
>  			WARN(1, "clock: %s: could not enable: %d\n",
>  			     clk->name, ret);
> -			goto oce_err3;
> +			goto oce_err2;
>  		}
>  	}

The clkdm enable/disable in this part of the patch is still required on
OMAP2/3, since the clkdm is still attached to the clock and not to the
hwmod.

Just backing out the mach-omap2/clock.c changes from this patch allows
this series to boot fine on OMAP3.

Kevin

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

* Re: [PATCH v3 8/8] OMAP2+: hwmod: Follow the recommended PRCM module enable sequence
  2011-06-28 17:16   ` Kevin Hilman
@ 2011-06-28 21:33     ` Cousson, Benoit
  2011-06-28 21:55       ` Rajendra Nayak
  0 siblings, 1 reply; 21+ messages in thread
From: Cousson, Benoit @ 2011-06-28 21:33 UTC (permalink / raw)
  To: Hilman, Kevin
  Cc: paul, Nayak, Rajendra, Shilimkar, Santosh, linux-omap, toddpoynor

On 6/28/2011 7:16 PM, Hilman, Kevin wrote:
> Benoit Cousson<b-cousson@ti.com>  writes:
>
>> From: Rajendra Nayak<rnayak@ti.com>
>>
>> On OMAP4, the PRCM recommended sequence for enabling
>> a module after power-on-reset is:
>> -1- Force clkdm to SW_WKUP
>> -2- Enabling the clocks
>> -3- Configure desired module mode to "enable" or "auto"
>> -4- Wait for the desired module idle status to be FUNC
>> -5- Program clkdm in HW_AUTO(if supported)
>>
>> This sequence applies to all older OMAPs' as well,
>> however since they use autodeps, it makes sure that
>> no clkdm is in IDLE, and hence not requiring a force
>> SW_WKUP when a module is being enabled.
>
> OK, I found the problem that prevents booting on OMAP3...

Cool... thanks for that.

>> OMAP4 does not need to support autodeps, because
>> of the dyanamic dependency feature, wherein
>> the HW takes care of waking up a clockdomain from
>> idle and hence the module, whenever an interconnect
>> access happens to the given module.
>>
>> Implementing the sequence for OMAP4 requires
>> the clockdomain handling that is currently done in
>> clock framework to be done as part of hwmod framework
>> since the step -4- above to "Wait for the desired
>> module idle status to be FUNC" is done as part of
>> hwmod framework.
>>
>> Signed-off-by: Rajendra Nayak<rnayak@ti.com>
>> [b-cousson@ti.com: Adapt it to the new clkdm hwmod attribute and API]
>> Signed-off-by: Benoit Cousson<b-cousson@ti.com>
>> Cc: Paul Walmsley<paul@pwsan.com>
>> ---
>>   arch/arm/mach-omap2/clock.c      |   17 +----------------
>>   arch/arm/mach-omap2/omap_hwmod.c |   26 +++++++++++++++++++++++++-
>>   2 files changed, 26 insertions(+), 17 deletions(-)
>>
>> diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
>> index 180299e..2828d29 100644
>> --- a/arch/arm/mach-omap2/clock.c
>> +++ b/arch/arm/mach-omap2/clock.c
>> @@ -268,9 +268,6 @@ void omap2_clk_disable(struct clk *clk)
>>   		clk->ops->disable(clk);
>>   	}
>>
>> -	if (clk->clkdm)
>> -		clkdm_clk_disable(clk->clkdm, clk);
>> -
>>   	if (clk->parent)
>>   		omap2_clk_disable(clk->parent);
>>   }
>> @@ -308,30 +305,18 @@ int omap2_clk_enable(struct clk *clk)
>>   		}
>>   	}
>>
>> -	if (clk->clkdm) {
>> -		ret = clkdm_clk_enable(clk->clkdm, clk);
>> -		if (ret) {
>> -			WARN(1, "clock: %s: could not enable clockdomain %s: "
>> -			     "%d\n", clk->name, clk->clkdm->name, ret);
>> -			goto oce_err2;
>> -		}
>> -	}
>> -
>>   	if (clk->ops&&  clk->ops->enable) {
>>   		trace_clock_enable(clk->name, 1, smp_processor_id());
>>   		ret = clk->ops->enable(clk);
>>   		if (ret) {
>>   			WARN(1, "clock: %s: could not enable: %d\n",
>>   			     clk->name, ret);
>> -			goto oce_err3;
>> +			goto oce_err2;
>>   		}
>>   	}
>
> The clkdm enable/disable in this part of the patch is still required on
> OMAP2/3, since the clkdm is still attached to the clock and not to the
> hwmod.

OK, but I guess that in case of OMAP4, we are probably incrementing 
twice the usage counter... but that should not hurt, because we will 
decrement twice as well.

Rajendra,
Does that seems OK to you?

Thanks,
Benoit

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

* Re: [PATCH v3 8/8] OMAP2+: hwmod: Follow the recommended PRCM module enable sequence
  2011-06-28 21:33     ` Cousson, Benoit
@ 2011-06-28 21:55       ` Rajendra Nayak
  0 siblings, 0 replies; 21+ messages in thread
From: Rajendra Nayak @ 2011-06-28 21:55 UTC (permalink / raw)
  To: Cousson, Benoit
  Cc: Hilman, Kevin, paul, Shilimkar, Santosh, linux-omap, toddpoynor

On 6/28/2011 2:33 PM, Cousson, Benoit wrote:
> On 6/28/2011 7:16 PM, Hilman, Kevin wrote:
>> Benoit Cousson<b-cousson@ti.com> writes:
>>
>>> From: Rajendra Nayak<rnayak@ti.com>
>>>
>>> On OMAP4, the PRCM recommended sequence for enabling
>>> a module after power-on-reset is:
>>> -1- Force clkdm to SW_WKUP
>>> -2- Enabling the clocks
>>> -3- Configure desired module mode to "enable" or "auto"
>>> -4- Wait for the desired module idle status to be FUNC
>>> -5- Program clkdm in HW_AUTO(if supported)
>>>
>>> This sequence applies to all older OMAPs' as well,
>>> however since they use autodeps, it makes sure that
>>> no clkdm is in IDLE, and hence not requiring a force
>>> SW_WKUP when a module is being enabled.
>>
>> OK, I found the problem that prevents booting on OMAP3...
>
> Cool... thanks for that.
>
>>> OMAP4 does not need to support autodeps, because
>>> of the dyanamic dependency feature, wherein
>>> the HW takes care of waking up a clockdomain from
>>> idle and hence the module, whenever an interconnect
>>> access happens to the given module.
>>>
>>> Implementing the sequence for OMAP4 requires
>>> the clockdomain handling that is currently done in
>>> clock framework to be done as part of hwmod framework
>>> since the step -4- above to "Wait for the desired
>>> module idle status to be FUNC" is done as part of
>>> hwmod framework.
>>>
>>> Signed-off-by: Rajendra Nayak<rnayak@ti.com>
>>> [b-cousson@ti.com: Adapt it to the new clkdm hwmod attribute and API]
>>> Signed-off-by: Benoit Cousson<b-cousson@ti.com>
>>> Cc: Paul Walmsley<paul@pwsan.com>
>>> ---
>>> arch/arm/mach-omap2/clock.c | 17 +----------------
>>> arch/arm/mach-omap2/omap_hwmod.c | 26 +++++++++++++++++++++++++-
>>> 2 files changed, 26 insertions(+), 17 deletions(-)
>>>
>>> diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
>>> index 180299e..2828d29 100644
>>> --- a/arch/arm/mach-omap2/clock.c
>>> +++ b/arch/arm/mach-omap2/clock.c
>>> @@ -268,9 +268,6 @@ void omap2_clk_disable(struct clk *clk)
>>> clk->ops->disable(clk);
>>> }
>>>
>>> - if (clk->clkdm)
>>> - clkdm_clk_disable(clk->clkdm, clk);
>>> -
>>> if (clk->parent)
>>> omap2_clk_disable(clk->parent);
>>> }
>>> @@ -308,30 +305,18 @@ int omap2_clk_enable(struct clk *clk)
>>> }
>>> }
>>>
>>> - if (clk->clkdm) {
>>> - ret = clkdm_clk_enable(clk->clkdm, clk);
>>> - if (ret) {
>>> - WARN(1, "clock: %s: could not enable clockdomain %s: "
>>> - "%d\n", clk->name, clk->clkdm->name, ret);
>>> - goto oce_err2;
>>> - }
>>> - }
>>> -
>>> if (clk->ops&& clk->ops->enable) {
>>> trace_clock_enable(clk->name, 1, smp_processor_id());
>>> ret = clk->ops->enable(clk);
>>> if (ret) {
>>> WARN(1, "clock: %s: could not enable: %d\n",
>>> clk->name, ret);
>>> - goto oce_err3;
>>> + goto oce_err2;
>>> }
>>> }
>>
>> The clkdm enable/disable in this part of the patch is still required on
>> OMAP2/3, since the clkdm is still attached to the clock and not to the
>> hwmod.
>
> OK, but I guess that in case of OMAP4, we are probably incrementing
> twice the usage counter... but that should not hurt, because we will
> decrement twice as well.
>
> Rajendra,
> Does that seems OK to you?

When I did the initial patch, all clkdm's were still associated with
clocks, and removing this from clock framework made sense and also
worked on OMAP3/2, because I had clkdm_clk_enable/disable being called
from hwmod framework.
Now that we have clkdm_hwmod_enable/disable being called from hwmod
framework, and clkdm's are associated with hwmod, I guess its best to
do this for all OMAP's. Keeping this association of clkdm with clocks
(for OMAP3/2) and the above piece of code because that association
exits looks messy.

>
> Thanks,
> Benoit


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

* Re: [PATCH v3 8/8] OMAP2+: hwmod: Follow the recommended PRCM module enable sequence
  2011-06-28 13:05     ` Cousson, Benoit
@ 2011-06-28 22:03       ` Rajendra Nayak
  2011-06-28 22:23         ` Cousson, Benoit
  0 siblings, 1 reply; 21+ messages in thread
From: Rajendra Nayak @ 2011-06-28 22:03 UTC (permalink / raw)
  To: Cousson, Benoit
  Cc: Hilman, Kevin, paul, Shilimkar, Santosh, linux-omap, toddpoynor

On 6/28/2011 6:05 AM, Cousson, Benoit wrote:
> Hi Kevin,
>
> On 6/28/2011 2:11 AM, Hilman, Kevin wrote:
>> Benoit Cousson<b-cousson@ti.com>   writes:
>>
>>> From: Rajendra Nayak<rnayak@ti.com>
>>>
>>> On OMAP4, the PRCM recommended sequence for enabling
>>> a module after power-on-reset is:
>>> -1- Force clkdm to SW_WKUP
>>> -2- Enabling the clocks
>>> -3- Configure desired module mode to "enable" or "auto"
>>> -4- Wait for the desired module idle status to be FUNC
>>> -5- Program clkdm in HW_AUTO(if supported)
>>>
>>> This sequence applies to all older OMAPs' as well,
>>> however since they use autodeps, it makes sure that
>>> no clkdm is in IDLE, and hence not requiring a force
>>> SW_WKUP when a module is being enabled.
>>>
>>> OMAP4 does not need to support autodeps, because
>>> of the dyanamic dependency feature, wherein
>>> the HW takes care of waking up a clockdomain from
>>> idle and hence the module, whenever an interconnect
>>> access happens to the given module.
>>>
>>> Implementing the sequence for OMAP4 requires
>>> the clockdomain handling that is currently done in
>>> clock framework to be done as part of hwmod framework
>>> since the step -4- above to "Wait for the desired
>>> module idle status to be FUNC" is done as part of
>>> hwmod framework.
>>>
>>> Signed-off-by: Rajendra Nayak<rnayak@ti.com>
>>> [b-cousson@ti.com: Adapt it to the new clkdm hwmod attribute and API]
>>> Signed-off-by: Benoit Cousson<b-cousson@ti.com>
>>> Cc: Paul Walmsley<paul@pwsan.com>
>>
>> [...]
>>
>>> diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
>>> index 3eef106..3538805 100644
>>> --- a/arch/arm/mach-omap2/omap_hwmod.c
>>> +++ b/arch/arm/mach-omap2/omap_hwmod.c
>>> @@ -1360,6 +1360,7 @@ static int _reset(struct omap_hwmod *oh)
>>>    static int _enable(struct omap_hwmod *oh)
>>>    {
>>>    	int r;
>>> +	int hwsup = 0;
>>>
>>>    	if (oh->_state != _HWMOD_STATE_INITIALIZED&&
>>>    	oh->_state != _HWMOD_STATE_IDLE&&
>>> @@ -1378,6 +1379,19 @@ static int _enable(struct omap_hwmod *oh)
>>>    		omap_hwmod_mux(oh->mux, _HWMOD_STATE_ENABLED);
>>>
>>>    	_add_initiator_dep(oh, mpu_oh);
>>> +
>>> +	/*
>>> +	 * A clockdomain must be in SW_SUP before enabling completely the
>>> +	 * module. The clockdomain can be set in HW_AUTO only when the module
>>> +	 * become ready.
>>> +	 */
>>> +	hwsup = clkdm_allows_idle(oh->clkdm);
>>> +	r = clkdm_hwmod_enable(oh->clkdm, oh);
>>> +	if (r) {
>>> +		WARN(1, "omap_hwmod: %s: could not enable clockdomain %s: %d\n",
>>> +		     oh->name, oh->clkdm->name, r);
>>> +		return r;
>>> +	}
>>
>> If oh->clkdm == NULL (as it is on OMAP3 since the hwmod data has no
>> clkdms yet), this hangs trying to dereference oh->clkdm->name.
>>
>> Simple fix below, but probably better is to not call any of these
>> functions if oh->clkdm == NULL, otherwise this is very noisy on OMAP3
>> since that WARN is printed for every hwmod.
>
> I can as well prevent the clkdm_hwmod_enable function to return any errors in case of omap2&  omap3...

Is'nt it best to do this..

if (oh->clkdm)
	hwsup = clkdm_allows_idle(oh->clkdm);
	r = clkdm_hwmod_enable(oh->clkdm, oh);
	...

My original patch infact had this check :-)

>
>> Is anyone planning to add the clkdms to OMAP3 hwmod data?
>
> Euh, I'm not sure:-) So I've just updated the OMAP3.
> I guess the next question will be: Is anyone planning to add the clkdms to OMAP2 hwmod data?
>
> Regards,
> Benoit
>
> ---
>  From 14916037799ed0d516c8c335f861d2d5248d1c33 Mon Sep 17 00:00:00 2001
> From: Benoit Cousson<b-cousson@ti.com>
> Date: Tue, 28 Jun 2011 14:53:28 +0200
> Subject: [PATCH] OMAP3: hwmod data: Add clock domain attribute
>
> Add a clkdm_name attribute to provide this information per hwmod.
>
> Signed-off-by: Benoit Cousson<b-cousson@ti.com>
> Cc: Paul Walmsley<paul@pwsan.com>
> Cc: Rajendra Nayak<rnayak@ti.com>
> ---
>   arch/arm/mach-omap2/omap_hwmod_3xxx_data.c |   60 ++++++++++++++++++++++++++++
>   1 files changed, 60 insertions(+), 0 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
> index d0c82de..91e75cf 100644
> --- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
> +++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
> @@ -149,6 +149,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_l3_main_masters[] = {
>   /* L3 */
>   static struct omap_hwmod omap3xxx_l3_main_hwmod = {
>   	.name		= "l3_main",
> +	.clkdm_name	= "core_l3_clkdm",
>   	.class		=&l3_hwmod_class,
>   	.mpu_irqs       = omap3xxx_l3_main_irqs,
>   	.mpu_irqs_cnt   = ARRAY_SIZE(omap3xxx_l3_main_irqs),
> @@ -495,6 +496,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_l4_core_slaves[] = {
>   /* L4 CORE */
>   static struct omap_hwmod omap3xxx_l4_core_hwmod = {
>   	.name		= "l4_core",
> +	.clkdm_name	= "core_l4_clkdm",
>   	.class		=&l4_hwmod_class,
>   	.slaves		= omap3xxx_l4_core_slaves,
>   	.slaves_cnt	= ARRAY_SIZE(omap3xxx_l4_core_slaves),
> @@ -510,6 +512,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_l4_per_slaves[] = {
>   /* L4 PER */
>   static struct omap_hwmod omap3xxx_l4_per_hwmod = {
>   	.name		= "l4_per",
> +	.clkdm_name	= "per_clkdm",
>   	.class		=&l4_hwmod_class,
>   	.slaves		= omap3xxx_l4_per_slaves,
>   	.slaves_cnt	= ARRAY_SIZE(omap3xxx_l4_per_slaves),
> @@ -525,6 +528,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_l4_wkup_slaves[] = {
>   /* L4 WKUP */
>   static struct omap_hwmod omap3xxx_l4_wkup_hwmod = {
>   	.name		= "l4_wkup",
> +	.clkdm_name	= "wkup_clkdm",
>   	.class		=&l4_hwmod_class,
>   	.slaves		= omap3xxx_l4_wkup_slaves,
>   	.slaves_cnt	= ARRAY_SIZE(omap3xxx_l4_wkup_slaves),
> @@ -540,6 +544,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_mpu_masters[] = {
>   /* MPU */
>   static struct omap_hwmod omap3xxx_mpu_hwmod = {
>   	.name		= "mpu",
> +	.clkdm_name	= "mpu_clkdm",
>   	.class		=&mpu_hwmod_class,
>   	.main_clk	= "arm_fck",
>   	.masters	= omap3xxx_mpu_masters,
> @@ -569,6 +574,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_iva_masters[] = {
>
>   static struct omap_hwmod omap3xxx_iva_hwmod = {
>   	.name		= "iva",
> +	.clkdm_name	= "iva2_clkdm",
>   	.class		=&iva_hwmod_class,
>   	.masters	= omap3xxx_iva_masters,
>   	.masters_cnt	= ARRAY_SIZE(omap3xxx_iva_masters),
> @@ -641,6 +647,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_timer1_slaves[] = {
>   /* timer1 hwmod */
>   static struct omap_hwmod omap3xxx_timer1_hwmod = {
>   	.name		= "timer1",
> +	.clkdm_name	= "wkup_clkdm",
>   	.mpu_irqs	= omap3xxx_timer1_mpu_irqs,
>   	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_timer1_mpu_irqs),
>   	.main_clk	= "gpt1_fck",
> @@ -691,6 +698,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_timer2_slaves[] = {
>   /* timer2 hwmod */
>   static struct omap_hwmod omap3xxx_timer2_hwmod = {
>   	.name		= "timer2",
> +	.clkdm_name	= "per_clkdm",
>   	.mpu_irqs	= omap3xxx_timer2_mpu_irqs,
>   	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_timer2_mpu_irqs),
>   	.main_clk	= "gpt2_fck",
> @@ -741,6 +749,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_timer3_slaves[] = {
>   /* timer3 hwmod */
>   static struct omap_hwmod omap3xxx_timer3_hwmod = {
>   	.name		= "timer3",
> +	.clkdm_name	= "per_clkdm",
>   	.mpu_irqs	= omap3xxx_timer3_mpu_irqs,
>   	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_timer3_mpu_irqs),
>   	.main_clk	= "gpt3_fck",
> @@ -791,6 +800,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_timer4_slaves[] = {
>   /* timer4 hwmod */
>   static struct omap_hwmod omap3xxx_timer4_hwmod = {
>   	.name		= "timer4",
> +	.clkdm_name	= "per_clkdm",
>   	.mpu_irqs	= omap3xxx_timer4_mpu_irqs,
>   	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_timer4_mpu_irqs),
>   	.main_clk	= "gpt4_fck",
> @@ -841,6 +851,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_timer5_slaves[] = {
>   /* timer5 hwmod */
>   static struct omap_hwmod omap3xxx_timer5_hwmod = {
>   	.name		= "timer5",
> +	.clkdm_name	= "per_clkdm",
>   	.mpu_irqs	= omap3xxx_timer5_mpu_irqs,
>   	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_timer5_mpu_irqs),
>   	.main_clk	= "gpt5_fck",
> @@ -891,6 +902,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_timer6_slaves[] = {
>   /* timer6 hwmod */
>   static struct omap_hwmod omap3xxx_timer6_hwmod = {
>   	.name		= "timer6",
> +	.clkdm_name	= "per_clkdm",
>   	.mpu_irqs	= omap3xxx_timer6_mpu_irqs,
>   	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_timer6_mpu_irqs),
>   	.main_clk	= "gpt6_fck",
> @@ -941,6 +953,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_timer7_slaves[] = {
>   /* timer7 hwmod */
>   static struct omap_hwmod omap3xxx_timer7_hwmod = {
>   	.name		= "timer7",
> +	.clkdm_name	= "per_clkdm",
>   	.mpu_irqs	= omap3xxx_timer7_mpu_irqs,
>   	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_timer7_mpu_irqs),
>   	.main_clk	= "gpt7_fck",
> @@ -991,6 +1004,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_timer8_slaves[] = {
>   /* timer8 hwmod */
>   static struct omap_hwmod omap3xxx_timer8_hwmod = {
>   	.name		= "timer8",
> +	.clkdm_name	= "per_clkdm",
>   	.mpu_irqs	= omap3xxx_timer8_mpu_irqs,
>   	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_timer8_mpu_irqs),
>   	.main_clk	= "gpt8_fck",
> @@ -1041,6 +1055,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_timer9_slaves[] = {
>   /* timer9 hwmod */
>   static struct omap_hwmod omap3xxx_timer9_hwmod = {
>   	.name		= "timer9",
> +	.clkdm_name	= "per_clkdm",
>   	.mpu_irqs	= omap3xxx_timer9_mpu_irqs,
>   	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_timer9_mpu_irqs),
>   	.main_clk	= "gpt9_fck",
> @@ -1091,6 +1106,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_timer10_slaves[] = {
>   /* timer10 hwmod */
>   static struct omap_hwmod omap3xxx_timer10_hwmod = {
>   	.name		= "timer10",
> +	.clkdm_name	= "core_l4_clkdm",
>   	.mpu_irqs	= omap3xxx_timer10_mpu_irqs,
>   	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_timer10_mpu_irqs),
>   	.main_clk	= "gpt10_fck",
> @@ -1141,6 +1157,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_timer11_slaves[] = {
>   /* timer11 hwmod */
>   static struct omap_hwmod omap3xxx_timer11_hwmod = {
>   	.name		= "timer11",
> +	.clkdm_name	= "core_l4_clkdm",
>   	.mpu_irqs	= omap3xxx_timer11_mpu_irqs,
>   	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_timer11_mpu_irqs),
>   	.main_clk	= "gpt11_fck",
> @@ -1191,6 +1208,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_timer12_slaves[] = {
>   /* timer12 hwmod */
>   static struct omap_hwmod omap3xxx_timer12_hwmod = {
>   	.name		= "timer12",
> +	.clkdm_name	= "wkup_clkdm",
>   	.mpu_irqs	= omap3xxx_timer12_mpu_irqs,
>   	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_timer12_mpu_irqs),
>   	.main_clk	= "gpt12_fck",
> @@ -1271,6 +1289,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_wd_timer2_slaves[] = {
>   static struct omap_hwmod omap3xxx_wd_timer2_hwmod = {
>   	.name		= "wd_timer2",
>   	.class		=&omap3xxx_wd_timer_hwmod_class,
> +	.clkdm_name	= "wkup_clkdm",
>   	.main_clk	= "wdt2_fck",
>   	.prcm		= {
>   		.omap2 = {
> @@ -1326,6 +1345,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_uart1_slaves[] = {
>
>   static struct omap_hwmod omap3xxx_uart1_hwmod = {
>   	.name		= "uart1",
> +	.clkdm_name	= "core_l4_clkdm",
>   	.mpu_irqs	= uart1_mpu_irqs,
>   	.mpu_irqs_cnt	= ARRAY_SIZE(uart1_mpu_irqs),
>   	.sdma_reqs	= uart1_sdma_reqs,
> @@ -1363,6 +1383,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_uart2_slaves[] = {
>
>   static struct omap_hwmod omap3xxx_uart2_hwmod = {
>   	.name		= "uart2",
> +	.clkdm_name	= "core_l4_clkdm",
>   	.mpu_irqs	= uart2_mpu_irqs,
>   	.mpu_irqs_cnt	= ARRAY_SIZE(uart2_mpu_irqs),
>   	.sdma_reqs	= uart2_sdma_reqs,
> @@ -1400,6 +1421,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_uart3_slaves[] = {
>
>   static struct omap_hwmod omap3xxx_uart3_hwmod = {
>   	.name		= "uart3",
> +	.clkdm_name	= "per_clkdm",
>   	.mpu_irqs	= uart3_mpu_irqs,
>   	.mpu_irqs_cnt	= ARRAY_SIZE(uart3_mpu_irqs),
>   	.sdma_reqs	= uart3_sdma_reqs,
> @@ -1437,6 +1459,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_uart4_slaves[] = {
>
>   static struct omap_hwmod omap3xxx_uart4_hwmod = {
>   	.name		= "uart4",
> +	.clkdm_name	= "per_clkdm",
>   	.mpu_irqs	= uart4_mpu_irqs,
>   	.mpu_irqs_cnt	= ARRAY_SIZE(uart4_mpu_irqs),
>   	.sdma_reqs	= uart4_sdma_reqs,
> @@ -1549,6 +1572,7 @@ static struct omap_hwmod_opt_clk dss_opt_clks[] = {
>
>   static struct omap_hwmod omap3430es1_dss_core_hwmod = {
>   	.name		= "dss_core",
> +	.clkdm_name	= "dss_clkdm",
>   	.class		=&omap3xxx_dss_hwmod_class,
>   	.main_clk	= "dss1_alwon_fck", /* instead of dss_fck */
>   	.sdma_reqs	= omap3xxx_dss_sdma_chs,
> @@ -1575,6 +1599,7 @@ static struct omap_hwmod omap3430es1_dss_core_hwmod = {
>
>   static struct omap_hwmod omap3xxx_dss_core_hwmod = {
>   	.name		= "dss_core",
> +	.clkdm_name	= "dss_clkdm",
>   	.class		=&omap3xxx_dss_hwmod_class,
>   	.main_clk	= "dss1_alwon_fck", /* instead of dss_fck */
>   	.sdma_reqs	= omap3xxx_dss_sdma_chs,
> @@ -1658,6 +1683,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_dispc_slaves[] = {
>
>   static struct omap_hwmod omap3xxx_dss_dispc_hwmod = {
>   	.name		= "dss_dispc",
> +	.clkdm_name	= "dss_clkdm",
>   	.class		=&omap3xxx_dispc_hwmod_class,
>   	.mpu_irqs	= omap3xxx_dispc_irqs,
>   	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_dispc_irqs),
> @@ -1722,6 +1748,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_dsi1_slaves[] = {
>
>   static struct omap_hwmod omap3xxx_dss_dsi1_hwmod = {
>   	.name		= "dss_dsi1",
> +	.clkdm_name	= "dss_clkdm",
>   	.class		=&omap3xxx_dsi_hwmod_class,
>   	.mpu_irqs	= omap3xxx_dsi1_irqs,
>   	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_dsi1_irqs),
> @@ -1793,6 +1820,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_rfbi_slaves[] = {
>
>   static struct omap_hwmod omap3xxx_dss_rfbi_hwmod = {
>   	.name		= "dss_rfbi",
> +	.clkdm_name	= "dss_clkdm",
>   	.class		=&omap3xxx_rfbi_hwmod_class,
>   	.main_clk	= "dss1_alwon_fck",
>   	.prcm		= {
> @@ -1853,6 +1881,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_venc_slaves[] = {
>
>   static struct omap_hwmod omap3xxx_dss_venc_hwmod = {
>   	.name		= "dss_venc",
> +	.clkdm_name	= "dss_clkdm",
>   	.class		=&omap3xxx_venc_hwmod_class,
>   	.main_clk	= "dss1_alwon_fck",
>   	.prcm		= {
> @@ -1891,6 +1920,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_i2c1_slaves[] = {
>
>   static struct omap_hwmod omap3xxx_i2c1_hwmod = {
>   	.name		= "i2c1",
> +	.clkdm_name	= "core_l4_clkdm",
>   	.mpu_irqs	= i2c1_mpu_irqs,
>   	.mpu_irqs_cnt	= ARRAY_SIZE(i2c1_mpu_irqs),
>   	.sdma_reqs	= i2c1_sdma_reqs,
> @@ -1933,6 +1963,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_i2c2_slaves[] = {
>
>   static struct omap_hwmod omap3xxx_i2c2_hwmod = {
>   	.name		= "i2c2",
> +	.clkdm_name	= "core_l4_clkdm",
>   	.mpu_irqs	= i2c2_mpu_irqs,
>   	.mpu_irqs_cnt	= ARRAY_SIZE(i2c2_mpu_irqs),
>   	.sdma_reqs	= i2c2_sdma_reqs,
> @@ -1975,6 +2006,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_i2c3_slaves[] = {
>
>   static struct omap_hwmod omap3xxx_i2c3_hwmod = {
>   	.name		= "i2c3",
> +	.clkdm_name	= "core_l4_clkdm",
>   	.mpu_irqs	= i2c3_mpu_irqs,
>   	.mpu_irqs_cnt	= ARRAY_SIZE(i2c3_mpu_irqs),
>   	.sdma_reqs	= i2c3_sdma_reqs,
> @@ -2141,6 +2173,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_gpio1_slaves[] = {
>
>   static struct omap_hwmod omap3xxx_gpio1_hwmod = {
>   	.name		= "gpio1",
> +	.clkdm_name	= "wkup_clkdm",
>   	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
>   	.mpu_irqs	= omap3xxx_gpio1_irqs,
>   	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_gpio1_irqs),
> @@ -2178,6 +2211,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_gpio2_slaves[] = {
>
>   static struct omap_hwmod omap3xxx_gpio2_hwmod = {
>   	.name		= "gpio2",
> +	.clkdm_name	= "per_clkdm",
>   	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
>   	.mpu_irqs	= omap3xxx_gpio2_irqs,
>   	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_gpio2_irqs),
> @@ -2215,6 +2249,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_gpio3_slaves[] = {
>
>   static struct omap_hwmod omap3xxx_gpio3_hwmod = {
>   	.name		= "gpio3",
> +	.clkdm_name	= "per_clkdm",
>   	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
>   	.mpu_irqs	= omap3xxx_gpio3_irqs,
>   	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_gpio3_irqs),
> @@ -2252,6 +2287,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_gpio4_slaves[] = {
>
>   static struct omap_hwmod omap3xxx_gpio4_hwmod = {
>   	.name		= "gpio4",
> +	.clkdm_name	= "per_clkdm",
>   	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
>   	.mpu_irqs	= omap3xxx_gpio4_irqs,
>   	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_gpio4_irqs),
> @@ -2289,6 +2325,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_gpio5_slaves[] = {
>
>   static struct omap_hwmod omap3xxx_gpio5_hwmod = {
>   	.name		= "gpio5",
> +	.clkdm_name	= "per_clkdm",
>   	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
>   	.mpu_irqs	= omap3xxx_gpio5_irqs,
>   	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_gpio5_irqs),
> @@ -2326,6 +2363,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_gpio6_slaves[] = {
>
>   static struct omap_hwmod omap3xxx_gpio6_hwmod = {
>   	.name		= "gpio6",
> +	.clkdm_name	= "per_clkdm",
>   	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
>   	.mpu_irqs	= omap3xxx_gpio6_irqs,
>   	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_gpio6_irqs),
> @@ -2419,6 +2457,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_dma_system_slaves[] = {
>
>   static struct omap_hwmod omap3xxx_dma_system_hwmod = {
>   	.name		= "dma",
> +	.clkdm_name	= "core_l3_clkdm",
>   	.class		=&omap3xxx_dma_hwmod_class,
>   	.mpu_irqs	= omap3xxx_dma_system_irqs,
>   	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_dma_system_irqs),
> @@ -2499,6 +2538,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_mcbsp1_slaves[] = {
>
>   static struct omap_hwmod omap3xxx_mcbsp1_hwmod = {
>   	.name		= "mcbsp1",
> +	.clkdm_name	= "core_l4_clkdm",
>   	.class		=&omap3xxx_mcbsp_hwmod_class,
>   	.mpu_irqs	= omap3xxx_mcbsp1_irqs,
>   	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_mcbsp1_irqs),
> @@ -2561,6 +2601,7 @@ static struct omap_mcbsp_dev_attr omap34xx_mcbsp2_dev_attr = {
>
>   static struct omap_hwmod omap3xxx_mcbsp2_hwmod = {
>   	.name		= "mcbsp2",
> +	.clkdm_name	= "per_clkdm",
>   	.class		=&omap3xxx_mcbsp_hwmod_class,
>   	.mpu_irqs	= omap3xxx_mcbsp2_irqs,
>   	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_mcbsp2_irqs),
> @@ -2624,6 +2665,7 @@ static struct omap_mcbsp_dev_attr omap34xx_mcbsp3_dev_attr = {
>
>   static struct omap_hwmod omap3xxx_mcbsp3_hwmod = {
>   	.name		= "mcbsp3",
> +	.clkdm_name	= "per_clkdm",
>   	.class		=&omap3xxx_mcbsp_hwmod_class,
>   	.mpu_irqs	= omap3xxx_mcbsp3_irqs,
>   	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_mcbsp3_irqs),
> @@ -2683,6 +2725,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_mcbsp4_slaves[] = {
>
>   static struct omap_hwmod omap3xxx_mcbsp4_hwmod = {
>   	.name		= "mcbsp4",
> +	.clkdm_name	= "per_clkdm",
>   	.class		=&omap3xxx_mcbsp_hwmod_class,
>   	.mpu_irqs	= omap3xxx_mcbsp4_irqs,
>   	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_mcbsp4_irqs),
> @@ -2741,6 +2784,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_mcbsp5_slaves[] = {
>
>   static struct omap_hwmod omap3xxx_mcbsp5_hwmod = {
>   	.name		= "mcbsp5",
> +	.clkdm_name	= "core_l4_clkdm",
>   	.class		=&omap3xxx_mcbsp_hwmod_class,
>   	.mpu_irqs	= omap3xxx_mcbsp5_irqs,
>   	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_mcbsp5_irqs),
> @@ -2804,6 +2848,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_mcbsp2_sidetone_slaves[] = {
>
>   static struct omap_hwmod omap3xxx_mcbsp2_sidetone_hwmod = {
>   	.name		= "mcbsp2_sidetone",
> +	.clkdm_name	= "per_clkdm",
>   	.class		=&omap3xxx_mcbsp_sidetone_hwmod_class,
>   	.mpu_irqs	= omap3xxx_mcbsp2_sidetone_irqs,
>   	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_mcbsp2_sidetone_irqs),
> @@ -2853,6 +2898,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_mcbsp3_sidetone_slaves[] = {
>
>   static struct omap_hwmod omap3xxx_mcbsp3_sidetone_hwmod = {
>   	.name		= "mcbsp3_sidetone",
> +	.clkdm_name	= "per_clkdm",
>   	.class		=&omap3xxx_mcbsp_sidetone_hwmod_class,
>   	.mpu_irqs	= omap3xxx_mcbsp3_sidetone_irqs,
>   	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_mcbsp3_sidetone_irqs),
> @@ -2916,6 +2962,7 @@ static struct omap_hwmod_ocp_if *omap3_sr1_slaves[] = {
>
>   static struct omap_hwmod omap34xx_sr1_hwmod = {
>   	.name		= "sr1_hwmod",
> +	.clkdm_name	= "wkup_clkdm",
>   	.class		=&omap34xx_smartreflex_hwmod_class,
>   	.main_clk	= "sr1_fck",
>   	.vdd_name	= "mpu",
> @@ -2938,6 +2985,7 @@ static struct omap_hwmod omap34xx_sr1_hwmod = {
>
>   static struct omap_hwmod omap36xx_sr1_hwmod = {
>   	.name		= "sr1_hwmod",
> +	.clkdm_name	= "wkup_clkdm",
>   	.class		=&omap36xx_smartreflex_hwmod_class,
>   	.main_clk	= "sr1_fck",
>   	.vdd_name	= "mpu",
> @@ -2962,6 +3010,7 @@ static struct omap_hwmod_ocp_if *omap3_sr2_slaves[] = {
>
>   static struct omap_hwmod omap34xx_sr2_hwmod = {
>   	.name		= "sr2_hwmod",
> +	.clkdm_name	= "wkup_clkdm",
>   	.class		=&omap34xx_smartreflex_hwmod_class,
>   	.main_clk	= "sr2_fck",
>   	.vdd_name	= "core",
> @@ -2984,6 +3033,7 @@ static struct omap_hwmod omap34xx_sr2_hwmod = {
>
>   static struct omap_hwmod omap36xx_sr2_hwmod = {
>   	.name		= "sr2_hwmod",
> +	.clkdm_name	= "wkup_clkdm",
>   	.class		=&omap36xx_smartreflex_hwmod_class,
>   	.main_clk	= "sr2_fck",
>   	.vdd_name	= "core",
> @@ -3051,6 +3101,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_mailbox_slaves[] = {
>
>   static struct omap_hwmod omap3xxx_mailbox_hwmod = {
>   	.name		= "mailbox",
> +	.clkdm_name	= "core_l4_clkdm",
>   	.class		=&omap3xxx_mailbox_hwmod_class,
>   	.mpu_irqs	= omap3xxx_mailbox_irqs,
>   	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_mailbox_irqs),
> @@ -3190,6 +3241,7 @@ static struct omap2_mcspi_dev_attr omap_mcspi1_dev_attr = {
>
>   static struct omap_hwmod omap34xx_mcspi1 = {
>   	.name		= "mcspi1",
> +	.clkdm_name	= "core_l4_clkdm",
>   	.mpu_irqs	= omap34xx_mcspi1_mpu_irqs,
>   	.mpu_irqs_cnt	= ARRAY_SIZE(omap34xx_mcspi1_mpu_irqs),
>   	.sdma_reqs	= omap34xx_mcspi1_sdma_reqs,
> @@ -3233,6 +3285,7 @@ static struct omap2_mcspi_dev_attr omap_mcspi2_dev_attr = {
>
>   static struct omap_hwmod omap34xx_mcspi2 = {
>   	.name		= "mcspi2",
> +	.clkdm_name	= "core_l4_clkdm",
>   	.mpu_irqs	= omap34xx_mcspi2_mpu_irqs,
>   	.mpu_irqs_cnt	= ARRAY_SIZE(omap34xx_mcspi2_mpu_irqs),
>   	.sdma_reqs	= omap34xx_mcspi2_sdma_reqs,
> @@ -3276,6 +3329,7 @@ static struct omap2_mcspi_dev_attr omap_mcspi3_dev_attr = {
>
>   static struct omap_hwmod omap34xx_mcspi3 = {
>   	.name		= "mcspi3",
> +	.clkdm_name	= "core_l4_clkdm",
>   	.mpu_irqs	= omap34xx_mcspi3_mpu_irqs,
>   	.mpu_irqs_cnt	= ARRAY_SIZE(omap34xx_mcspi3_mpu_irqs),
>   	.sdma_reqs	= omap34xx_mcspi3_sdma_reqs,
> @@ -3317,6 +3371,7 @@ static struct omap2_mcspi_dev_attr omap_mcspi4_dev_attr = {
>
>   static struct omap_hwmod omap34xx_mcspi4 = {
>   	.name		= "mcspi4",
> +	.clkdm_name	= "core_l4_clkdm",
>   	.mpu_irqs	= omap34xx_mcspi4_mpu_irqs,
>   	.mpu_irqs_cnt	= ARRAY_SIZE(omap34xx_mcspi4_mpu_irqs),
>   	.sdma_reqs	= omap34xx_mcspi4_sdma_reqs,
> @@ -3366,6 +3421,7 @@ static struct omap_hwmod_irq_info omap3xxx_usbhsotg_mpu_irqs[] = {
>
>   static struct omap_hwmod omap3xxx_usbhsotg_hwmod = {
>   	.name		= "usb_otg_hs",
> +	.clkdm_name	= "core_l3_clkdm",
>   	.mpu_irqs	= omap3xxx_usbhsotg_mpu_irqs,
>   	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_usbhsotg_mpu_irqs),
>   	.main_clk	= "hsotgusb_ick",
> @@ -3408,6 +3464,7 @@ static struct omap_hwmod_class am35xx_usbotg_class = {
>
>   static struct omap_hwmod am35xx_usbhsotg_hwmod = {
>   	.name		= "am35x_otg_hs",
> +	.clkdm_name	= "core_l3_clkdm",
>   	.mpu_irqs	= am35xx_usbhsotg_mpu_irqs,
>   	.mpu_irqs_cnt	= ARRAY_SIZE(am35xx_usbhsotg_mpu_irqs),
>   	.main_clk	= NULL,
> @@ -3466,6 +3523,7 @@ static struct omap_mmc_dev_attr mmc1_dev_attr = {
>
>   static struct omap_hwmod omap3xxx_mmc1_hwmod = {
>   	.name		= "mmc1",
> +	.clkdm_name	= "core_l4_clkdm",
>   	.mpu_irqs	= omap34xx_mmc1_mpu_irqs,
>   	.mpu_irqs_cnt	= ARRAY_SIZE(omap34xx_mmc1_mpu_irqs),
>   	.sdma_reqs	= omap34xx_mmc1_sdma_reqs,
> @@ -3511,6 +3569,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_mmc2_slaves[] = {
>
>   static struct omap_hwmod omap3xxx_mmc2_hwmod = {
>   	.name		= "mmc2",
> +	.clkdm_name	= "core_l4_clkdm",
>   	.mpu_irqs	= omap34xx_mmc2_mpu_irqs,
>   	.mpu_irqs_cnt	= ARRAY_SIZE(omap34xx_mmc2_mpu_irqs),
>   	.sdma_reqs	= omap34xx_mmc2_sdma_reqs,
> @@ -3555,6 +3614,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_mmc3_slaves[] = {
>
>   static struct omap_hwmod omap3xxx_mmc3_hwmod = {
>   	.name		= "mmc3",
> +	.clkdm_name	= "core_l4_clkdm",
>   	.mpu_irqs	= omap34xx_mmc3_mpu_irqs,
>   	.mpu_irqs_cnt	= ARRAY_SIZE(omap34xx_mmc3_mpu_irqs),
>   	.sdma_reqs	= omap34xx_mmc3_sdma_reqs,


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

* Re: [PATCH v3 8/8] OMAP2+: hwmod: Follow the recommended PRCM module enable sequence
  2011-06-28 22:03       ` Rajendra Nayak
@ 2011-06-28 22:23         ` Cousson, Benoit
  0 siblings, 0 replies; 21+ messages in thread
From: Cousson, Benoit @ 2011-06-28 22:23 UTC (permalink / raw)
  To: Nayak, Rajendra
  Cc: Hilman, Kevin, paul, Shilimkar, Santosh, linux-omap, toddpoynor

On 6/29/2011 12:03 AM, Nayak, Rajendra wrote:
> On 6/28/2011 6:05 AM, Cousson, Benoit wrote:
>> Hi Kevin,
>>
>> On 6/28/2011 2:11 AM, Hilman, Kevin wrote:
>>> Benoit Cousson<b-cousson@ti.com>    writes:
>>>
>>>> From: Rajendra Nayak<rnayak@ti.com>
>>>>
>>>> On OMAP4, the PRCM recommended sequence for enabling
>>>> a module after power-on-reset is:
>>>> -1- Force clkdm to SW_WKUP
>>>> -2- Enabling the clocks
>>>> -3- Configure desired module mode to "enable" or "auto"
>>>> -4- Wait for the desired module idle status to be FUNC
>>>> -5- Program clkdm in HW_AUTO(if supported)
>>>>
>>>> This sequence applies to all older OMAPs' as well,
>>>> however since they use autodeps, it makes sure that
>>>> no clkdm is in IDLE, and hence not requiring a force
>>>> SW_WKUP when a module is being enabled.
>>>>
>>>> OMAP4 does not need to support autodeps, because
>>>> of the dyanamic dependency feature, wherein
>>>> the HW takes care of waking up a clockdomain from
>>>> idle and hence the module, whenever an interconnect
>>>> access happens to the given module.
>>>>
>>>> Implementing the sequence for OMAP4 requires
>>>> the clockdomain handling that is currently done in
>>>> clock framework to be done as part of hwmod framework
>>>> since the step -4- above to "Wait for the desired
>>>> module idle status to be FUNC" is done as part of
>>>> hwmod framework.
>>>>
>>>> Signed-off-by: Rajendra Nayak<rnayak@ti.com>
>>>> [b-cousson@ti.com: Adapt it to the new clkdm hwmod attribute and API]
>>>> Signed-off-by: Benoit Cousson<b-cousson@ti.com>
>>>> Cc: Paul Walmsley<paul@pwsan.com>
>>>
>>> [...]
>>>
>>>> diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
>>>> index 3eef106..3538805 100644
>>>> --- a/arch/arm/mach-omap2/omap_hwmod.c
>>>> +++ b/arch/arm/mach-omap2/omap_hwmod.c
>>>> @@ -1360,6 +1360,7 @@ static int _reset(struct omap_hwmod *oh)
>>>>     static int _enable(struct omap_hwmod *oh)
>>>>     {
>>>>      int r;
>>>> +   int hwsup = 0;
>>>>
>>>>      if (oh->_state != _HWMOD_STATE_INITIALIZED&&
>>>>      oh->_state != _HWMOD_STATE_IDLE&&
>>>> @@ -1378,6 +1379,19 @@ static int _enable(struct omap_hwmod *oh)
>>>>              omap_hwmod_mux(oh->mux, _HWMOD_STATE_ENABLED);
>>>>
>>>>      _add_initiator_dep(oh, mpu_oh);
>>>> +
>>>> +   /*
>>>> +    * A clockdomain must be in SW_SUP before enabling completely the
>>>> +    * module. The clockdomain can be set in HW_AUTO only when the module
>>>> +    * become ready.
>>>> +    */
>>>> +   hwsup = clkdm_allows_idle(oh->clkdm);
>>>> +   r = clkdm_hwmod_enable(oh->clkdm, oh);
>>>> +   if (r) {
>>>> +           WARN(1, "omap_hwmod: %s: could not enable clockdomain %s: %d\n",
>>>> +                oh->name, oh->clkdm->name, r);
>>>> +           return r;
>>>> +   }
>>>
>>> If oh->clkdm == NULL (as it is on OMAP3 since the hwmod data has no
>>> clkdms yet), this hangs trying to dereference oh->clkdm->name.
>>>
>>> Simple fix below, but probably better is to not call any of these
>>> functions if oh->clkdm == NULL, otherwise this is very noisy on OMAP3
>>> since that WARN is printed for every hwmod.
>>
>> I can as well prevent the clkdm_hwmod_enable function to return any errors in case of omap2&   omap3...
>
> Is'nt it best to do this..
>
> if (oh->clkdm)
>          hwsup = clkdm_allows_idle(oh->clkdm);
>          r = clkdm_hwmod_enable(oh->clkdm, oh);
>          ...
>
> My original patch infact had this check :-)

Yep, I remember :-) I removed them because for my point of view that 
attribute is mandatory for every hwmod entries and thus we should not 
have to check for it.
I preferred to hide that inside clkdm_hwmod_enable... but I'm not that 
sure it should be there now :-)

Benoit

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

* Re: [PATCH v3 1/8] OMAP2+: clockdomain: Add an api to read idle mode
  2011-06-27 16:11 ` [PATCH v3 1/8] OMAP2+: clockdomain: Add an api to read idle mode Benoit Cousson
@ 2011-07-01 12:22   ` Paul Walmsley
  0 siblings, 0 replies; 21+ messages in thread
From: Paul Walmsley @ 2011-07-01 12:22 UTC (permalink / raw)
  To: Benoit Cousson; +Cc: rnayak, santosh.shilimkar, linux-omap, toddpoynor

Hi

On Mon, 27 Jun 2011, Benoit Cousson wrote:

> From: Rajendra Nayak <rnayak@ti.com>
> 
> Add a clockdomain api to check if hardware supervised
> idle transitions are enabled on a clockdomain.

This looks good but I'd also suggest crediting Todd in the changelog for 
his review comments...

> 
> Signed-off-by: Rajendra Nayak <rnayak@ti.com>
> Cc: Paul Walmsley <paul@pwsan.com>
> ---
>  arch/arm/mach-omap2/clockdomain.c |   21 +++++++++++++++++++++
>  arch/arm/mach-omap2/clockdomain.h |    3 +++
>  2 files changed, 24 insertions(+), 0 deletions(-)
> 
> diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c
> index 6cb6c03..3f2a8e7 100644
> --- a/arch/arm/mach-omap2/clockdomain.c
> +++ b/arch/arm/mach-omap2/clockdomain.c
> @@ -795,6 +795,27 @@ void clkdm_deny_idle(struct clockdomain *clkdm)
>  	arch_clkdm->clkdm_deny_idle(clkdm);
>  }
>  
> +/**
> + * clkdm_allows_idle - Check if the clkdm hwsup/autoidle is enabled
> + * @clkdm: struct clockdomain *
> + *
> + * Returns true if the clockdomain is in hardware-supervised
> + * idle mode, or 0 otherwise.
> + *
> + */
> +int clkdm_allows_idle(struct clockdomain *clkdm)
> +{
> +	if (!clkdm)
> +		return -EINVAL;
> +
> +	if (!arch_clkdm || !arch_clkdm->clkdm_allows_idle)
> +		return -EINVAL;
> +
> +	pr_debug("clockdomain: reading idle state for %s\n", clkdm->name);
> +
> +	return arch_clkdm->clkdm_allows_idle(clkdm);
> +}
> +
>  
>  /* Clockdomain-to-clock framework interface code */
>  
> diff --git a/arch/arm/mach-omap2/clockdomain.h b/arch/arm/mach-omap2/clockdomain.h
> index 5823584..2d3d970 100644
> --- a/arch/arm/mach-omap2/clockdomain.h
> +++ b/arch/arm/mach-omap2/clockdomain.h
> @@ -138,6 +138,7 @@ struct clockdomain {
>   * @clkdm_wakeup: Force a clockdomain to wakeup
>   * @clkdm_allow_idle: Enable hw supervised idle transitions for clock domain
>   * @clkdm_deny_idle: Disable hw supervised idle transitions for clock domain
> + * @clkdm_allows_idle: Check if hw supervised idle transitions are enabled
>   * @clkdm_clk_enable: Put the clkdm in right state for a clock enable
>   * @clkdm_clk_disable: Put the clkdm in right state for a clock disable
>   */
> @@ -154,6 +155,7 @@ struct clkdm_ops {
>  	int	(*clkdm_wakeup)(struct clockdomain *clkdm);
>  	void	(*clkdm_allow_idle)(struct clockdomain *clkdm);
>  	void	(*clkdm_deny_idle)(struct clockdomain *clkdm);
> +	int	(*clkdm_allows_idle)(struct clockdomain *clkdm);
>  	int	(*clkdm_clk_enable)(struct clockdomain *clkdm);
>  	int	(*clkdm_clk_disable)(struct clockdomain *clkdm);
>  };
> @@ -177,6 +179,7 @@ int clkdm_clear_all_sleepdeps(struct clockdomain *clkdm);
>  
>  void clkdm_allow_idle(struct clockdomain *clkdm);
>  void clkdm_deny_idle(struct clockdomain *clkdm);
> +int clkdm_allows_idle(struct clockdomain *clkdm);
>  
>  int clkdm_wakeup(struct clockdomain *clkdm);
>  int clkdm_sleep(struct clockdomain *clkdm);
> -- 
> 1.7.0.4
> 


- Paul

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

* Re: [PATCH v3 2/8] OMAP2+: clockdomain: Add SoC support for clkdm_is_idle
  2011-06-27 16:11 ` [PATCH v3 2/8] OMAP2+: clockdomain: Add SoC support for clkdm_is_idle Benoit Cousson
  2011-06-27 19:18   ` Todd Poynor
@ 2011-07-01 12:24   ` Paul Walmsley
  1 sibling, 0 replies; 21+ messages in thread
From: Paul Walmsley @ 2011-07-01 12:24 UTC (permalink / raw)
  To: Benoit Cousson; +Cc: rnayak, santosh.shilimkar, linux-omap, toddpoynor

Hi

On Mon, 27 Jun 2011, Benoit Cousson wrote:

> From: Rajendra Nayak <rnayak@ti.com>
> 
> Add the SoC specific implemenation for clkdm_is_idle
> for OMAP2/3 and OMAP4.

The subject line and the changelog needs to be updated to read 
'clkdm_allows_idle'

Other than that, it looks good.


- Paul

> Signed-off-by: Rajendra Nayak <rnayak@ti.com>
> Cc: Paul Walmsley <paul@pwsan.com>
> ---
>  arch/arm/mach-omap2/clockdomain2xxx_3xxx.c |   12 ++++++++++++
>  arch/arm/mach-omap2/clockdomain44xx.c      |    7 +++++++
>  2 files changed, 19 insertions(+), 0 deletions(-)
> 
> diff --git a/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c b/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c
> index 48d0db7..81f3e46 100644
> --- a/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c
> +++ b/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c
> @@ -13,6 +13,7 @@
>   */
>  
>  #include <linux/types.h>
> +#include <linux/errno.h>
>  #include <plat/prcm.h>
>  #include "prm.h"
>  #include "prm2xxx_3xxx.h"
> @@ -146,6 +147,15 @@ static void omap2_clkdm_deny_idle(struct clockdomain *clkdm)
>  		_clkdm_del_autodeps(clkdm);
>  }
>  
> +static int omap2_clkdm_allows_idle(struct clockdomain *clkdm)
> +{
> +	if (!clkdm->clktrctrl_mask)
> +		return -EINVAL;
> +
> +	return omap2_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
> +				clkdm->clktrctrl_mask);
> +}
> +
>  static void _enable_hwsup(struct clockdomain *clkdm)
>  {
>  	if (cpu_is_omap24xx())
> @@ -252,6 +262,7 @@ struct clkdm_ops omap2_clkdm_operations = {
>  	.clkdm_wakeup		= omap2_clkdm_wakeup,
>  	.clkdm_allow_idle	= omap2_clkdm_allow_idle,
>  	.clkdm_deny_idle	= omap2_clkdm_deny_idle,
> +	.clkdm_allows_idle	= omap2_clkdm_allows_idle,
>  	.clkdm_clk_enable	= omap2_clkdm_clk_enable,
>  	.clkdm_clk_disable	= omap2_clkdm_clk_disable,
>  };
> @@ -269,6 +280,7 @@ struct clkdm_ops omap3_clkdm_operations = {
>  	.clkdm_wakeup		= omap3_clkdm_wakeup,
>  	.clkdm_allow_idle	= omap3_clkdm_allow_idle,
>  	.clkdm_deny_idle	= omap3_clkdm_deny_idle,
> +	.clkdm_allows_idle	= omap2_clkdm_allows_idle,
>  	.clkdm_clk_enable	= omap2_clkdm_clk_enable,
>  	.clkdm_clk_disable	= omap2_clkdm_clk_disable,
>  };
> diff --git a/arch/arm/mach-omap2/clockdomain44xx.c b/arch/arm/mach-omap2/clockdomain44xx.c
> index a1a4ecd..1599b18 100644
> --- a/arch/arm/mach-omap2/clockdomain44xx.c
> +++ b/arch/arm/mach-omap2/clockdomain44xx.c
> @@ -93,6 +93,12 @@ static void omap4_clkdm_deny_idle(struct clockdomain *clkdm)
>  					clkdm->cm_inst, clkdm->clkdm_offs);
>  }
>  
> +static int omap4_clkdm_allows_idle(struct clockdomain *clkdm)
> +{
> +	return omap4_cminst_is_clkdm_in_hwsup(clkdm->prcm_partition,
> +				clkdm->cm_inst, clkdm->clkdm_offs);
> +}
> +
>  static int omap4_clkdm_clk_enable(struct clockdomain *clkdm)
>  {
>  	bool hwsup = false;
> @@ -132,6 +138,7 @@ struct clkdm_ops omap4_clkdm_operations = {
>  	.clkdm_wakeup		= omap4_clkdm_wakeup,
>  	.clkdm_allow_idle	= omap4_clkdm_allow_idle,
>  	.clkdm_deny_idle	= omap4_clkdm_deny_idle,
> +	.clkdm_allows_idle	= omap4_clkdm_allows_idle,
>  	.clkdm_clk_enable	= omap4_clkdm_clk_enable,
>  	.clkdm_clk_disable	= omap4_clkdm_clk_disable,
>  };
> -- 
> 1.7.0.4
> 


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

end of thread, other threads:[~2011-07-01 12:24 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-06-27 16:11 [PATCH v3 0/8] Fix module-mode enable sequence on OMAP4 Benoit Cousson
2011-06-27 16:11 ` [PATCH v3 1/8] OMAP2+: clockdomain: Add an api to read idle mode Benoit Cousson
2011-07-01 12:22   ` Paul Walmsley
2011-06-27 16:11 ` [PATCH v3 2/8] OMAP2+: clockdomain: Add SoC support for clkdm_is_idle Benoit Cousson
2011-06-27 19:18   ` Todd Poynor
2011-07-01 12:24   ` Paul Walmsley
2011-06-27 16:11 ` [PATCH v3 3/8] OMAP2+: PM: Initialise sleep_switch to a non-valid value Benoit Cousson
2011-06-27 16:11 ` [PATCH v3 4/8] OMAP2+: PM: idle clkdms only if already in idle Benoit Cousson
2011-06-28  1:00   ` Todd Poynor
2011-06-27 16:11 ` [PATCH v3 5/8] OMAP4: PM: TEMP: Prevent l3init from idling/force sleep Benoit Cousson
2011-06-27 16:11 ` [PATCH v3 6/8] OMAP2+: clockdomain: Add 2 APIs to control clockdomain from hwmod framework Benoit Cousson
2011-06-28  1:08   ` Todd Poynor
2011-06-27 16:11 ` [PATCH v3 7/8] OMAP2+: clockdomain: Add per clkdm lock to prevent concurrent state programming Benoit Cousson
2011-06-27 16:11 ` [PATCH v3 8/8] OMAP2+: hwmod: Follow the recommended PRCM module enable sequence Benoit Cousson
2011-06-28  0:11   ` Kevin Hilman
2011-06-28 13:05     ` Cousson, Benoit
2011-06-28 22:03       ` Rajendra Nayak
2011-06-28 22:23         ` Cousson, Benoit
2011-06-28 17:16   ` Kevin Hilman
2011-06-28 21:33     ` Cousson, Benoit
2011-06-28 21:55       ` Rajendra Nayak

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.