All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCHv6 00/11]: ARM: OMAP: PM usecounting changes
@ 2012-09-25 16:05 ` Tero Kristo
  0 siblings, 0 replies; 30+ messages in thread
From: Tero Kristo @ 2012-09-25 16:05 UTC (permalink / raw)
  To: linux-omap, khilman, paul; +Cc: linux-arm-kernel

Hi,

Changes compared to previous version:

- Added patch #1 for fixing a potential race condition within clockdomain
  code
- Fixed patch #3 (old patch #2) regarding a similar race condition within
  the voltagedomain code

Tested with OMAP3 beagle, OMAP4460 GP panda, OMAP4430 EMU blaze devices.

Branch available:

git://gitorious.org/~kristo/omap-pm/omap-pm-work.git
branch: mainline-3.6-rc5-pwrdm-changes-v6

-Tero


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

* [PATCHv6 00/11]: ARM: OMAP: PM usecounting changes
@ 2012-09-25 16:05 ` Tero Kristo
  0 siblings, 0 replies; 30+ messages in thread
From: Tero Kristo @ 2012-09-25 16:05 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

Changes compared to previous version:

- Added patch #1 for fixing a potential race condition within clockdomain
  code
- Fixed patch #3 (old patch #2) regarding a similar race condition within
  the voltagedomain code

Tested with OMAP3 beagle, OMAP4460 GP panda, OMAP4430 EMU blaze devices.

Branch available:

git://gitorious.org/~kristo/omap-pm/omap-pm-work.git
branch: mainline-3.6-rc5-pwrdm-changes-v6

-Tero

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

* [PATCHv6 01/11] ARM: OMAP: clockdomain: Fix locking on _clkdm_clk_hwmod_enable / disable
  2012-09-25 16:05 ` Tero Kristo
@ 2012-09-25 16:05   ` Tero Kristo
  -1 siblings, 0 replies; 30+ messages in thread
From: Tero Kristo @ 2012-09-25 16:05 UTC (permalink / raw)
  To: linux-omap, khilman, paul; +Cc: linux-arm-kernel

Previously the code only acquired spinlock after increasing / decreasing
the usecount value, which is wrong. This leaves a small window where
a task switch may occur between the check of the usecount and the actual
wakeup / sleep of the domain. Fixed by moving the spinlock locking before
the usecount access. Left the usecount as atomic_t if someone wants an
easy access to the parameter through atomic_read.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 arch/arm/mach-omap2/clockdomain.c |   15 +++++++++++----
 1 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c
index 8664f5a..173905d 100644
--- a/arch/arm/mach-omap2/clockdomain.c
+++ b/arch/arm/mach-omap2/clockdomain.c
@@ -914,15 +914,18 @@ static int _clkdm_clk_hwmod_enable(struct clockdomain *clkdm)
 	if (!clkdm || !arch_clkdm || !arch_clkdm->clkdm_clk_enable)
 		return -EINVAL;
 
+	spin_lock_irqsave(&clkdm->lock, flags);
+
 	/*
 	 * 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)
+	if ((atomic_inc_return(&clkdm->usecount) > 1) && autodeps) {
+		spin_unlock_irqrestore(&clkdm->lock, flags);
 		return 0;
+	}
 
-	spin_lock_irqsave(&clkdm->lock, flags);
 	arch_clkdm->clkdm_clk_enable(clkdm);
 	pwrdm_state_switch(clkdm->pwrdm.ptr);
 	spin_unlock_irqrestore(&clkdm->lock, flags);
@@ -939,15 +942,19 @@ static int _clkdm_clk_hwmod_disable(struct clockdomain *clkdm)
 	if (!clkdm || !arch_clkdm || !arch_clkdm->clkdm_clk_disable)
 		return -EINVAL;
 
+	spin_lock_irqsave(&clkdm->lock, flags);
+
 	if (atomic_read(&clkdm->usecount) == 0) {
+		spin_unlock_irqrestore(&clkdm->lock, flags);
 		WARN_ON(1); /* underflow */
 		return -ERANGE;
 	}
 
-	if (atomic_dec_return(&clkdm->usecount) > 0)
+	if (atomic_dec_return(&clkdm->usecount) > 0) {
+		spin_unlock_irqrestore(&clkdm->lock, flags);
 		return 0;
+	}
 
-	spin_lock_irqsave(&clkdm->lock, flags);
 	arch_clkdm->clkdm_clk_disable(clkdm);
 	pwrdm_state_switch(clkdm->pwrdm.ptr);
 	spin_unlock_irqrestore(&clkdm->lock, flags);
-- 
1.7.4.1


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

* [PATCHv6 01/11] ARM: OMAP: clockdomain: Fix locking on _clkdm_clk_hwmod_enable / disable
@ 2012-09-25 16:05   ` Tero Kristo
  0 siblings, 0 replies; 30+ messages in thread
From: Tero Kristo @ 2012-09-25 16:05 UTC (permalink / raw)
  To: linux-arm-kernel

Previously the code only acquired spinlock after increasing / decreasing
the usecount value, which is wrong. This leaves a small window where
a task switch may occur between the check of the usecount and the actual
wakeup / sleep of the domain. Fixed by moving the spinlock locking before
the usecount access. Left the usecount as atomic_t if someone wants an
easy access to the parameter through atomic_read.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 arch/arm/mach-omap2/clockdomain.c |   15 +++++++++++----
 1 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c
index 8664f5a..173905d 100644
--- a/arch/arm/mach-omap2/clockdomain.c
+++ b/arch/arm/mach-omap2/clockdomain.c
@@ -914,15 +914,18 @@ static int _clkdm_clk_hwmod_enable(struct clockdomain *clkdm)
 	if (!clkdm || !arch_clkdm || !arch_clkdm->clkdm_clk_enable)
 		return -EINVAL;
 
+	spin_lock_irqsave(&clkdm->lock, flags);
+
 	/*
 	 * 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)
+	if ((atomic_inc_return(&clkdm->usecount) > 1) && autodeps) {
+		spin_unlock_irqrestore(&clkdm->lock, flags);
 		return 0;
+	}
 
-	spin_lock_irqsave(&clkdm->lock, flags);
 	arch_clkdm->clkdm_clk_enable(clkdm);
 	pwrdm_state_switch(clkdm->pwrdm.ptr);
 	spin_unlock_irqrestore(&clkdm->lock, flags);
@@ -939,15 +942,19 @@ static int _clkdm_clk_hwmod_disable(struct clockdomain *clkdm)
 	if (!clkdm || !arch_clkdm || !arch_clkdm->clkdm_clk_disable)
 		return -EINVAL;
 
+	spin_lock_irqsave(&clkdm->lock, flags);
+
 	if (atomic_read(&clkdm->usecount) == 0) {
+		spin_unlock_irqrestore(&clkdm->lock, flags);
 		WARN_ON(1); /* underflow */
 		return -ERANGE;
 	}
 
-	if (atomic_dec_return(&clkdm->usecount) > 0)
+	if (atomic_dec_return(&clkdm->usecount) > 0) {
+		spin_unlock_irqrestore(&clkdm->lock, flags);
 		return 0;
+	}
 
-	spin_lock_irqsave(&clkdm->lock, flags);
 	arch_clkdm->clkdm_clk_disable(clkdm);
 	pwrdm_state_switch(clkdm->pwrdm.ptr);
 	spin_unlock_irqrestore(&clkdm->lock, flags);
-- 
1.7.4.1

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

* [PATCHv6 02/11] ARM: OMAP3+: voltage/pwrdm/clkdm/clock add recursive usecount tracking
  2012-09-25 16:05 ` Tero Kristo
@ 2012-09-25 16:05   ` Tero Kristo
  -1 siblings, 0 replies; 30+ messages in thread
From: Tero Kristo @ 2012-09-25 16:05 UTC (permalink / raw)
  To: linux-omap, khilman, paul; +Cc: linux-arm-kernel

This patch fixes the usecount tracking for omap3+, previously the
usecount numbers were rather bogus and were not really useful for
any purpose. Now usecount numbers track the number of really active
clients on each domain. This patch also adds support for usecount
tracking on powerdomain level and autoidle flag for clocks that
are hardware controlled and should be skipped in usecount
calculations.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
Cc: Paul Walmsley <paul@pwsan.com>
Cc: Kevin Hilman <khilman@ti.com>
---
 arch/arm/mach-omap2/clkt_iclk.c         |   21 ++++++++++++++++++
 arch/arm/mach-omap2/clockdomain.c       |   16 +++++++++++++-
 arch/arm/mach-omap2/dpll3xxx.c          |   19 ++++++++++++++++
 arch/arm/mach-omap2/powerdomain.c       |   35 +++++++++++++++++++++++++++++++
 arch/arm/mach-omap2/powerdomain.h       |    4 +++
 arch/arm/plat-omap/clock.c              |    6 +++++
 arch/arm/plat-omap/include/plat/clock.h |    2 +
 7 files changed, 102 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-omap2/clkt_iclk.c b/arch/arm/mach-omap2/clkt_iclk.c
index 3d43fba..1afc599 100644
--- a/arch/arm/mach-omap2/clkt_iclk.c
+++ b/arch/arm/mach-omap2/clkt_iclk.c
@@ -21,6 +21,7 @@
 #include "clock2xxx.h"
 #include "cm2xxx_3xxx.h"
 #include "cm-regbits-24xx.h"
+#include "clockdomain.h"
 
 /* Private functions */
 
@@ -34,6 +35,16 @@ void omap2_clkt_iclk_allow_idle(struct clk *clk)
 	v = __raw_readl((__force void __iomem *)r);
 	v |= (1 << clk->enable_bit);
 	__raw_writel(v, (__force void __iomem *)r);
+
+	/* Remove this clock from parent clockdomain usecounts */
+	if (clk->usecount && clk->clkdm)
+		clkdm_clk_disable(clk->clkdm, clk);
+
+	/*
+	 * Mark as autoidle, so we continue to ignore this clock in
+	 * parent clkdm usecount calculations
+	 */
+	clk->autoidle = true;
 }
 
 /* XXX */
@@ -46,6 +57,16 @@ void omap2_clkt_iclk_deny_idle(struct clk *clk)
 	v = __raw_readl((__force void __iomem *)r);
 	v &= ~(1 << clk->enable_bit);
 	__raw_writel(v, (__force void __iomem *)r);
+
+	/*
+	 * Disable autoidle flag so further clkdm usecounts take this
+	 * clock into account
+	 */
+	clk->autoidle = false;
+
+	/* Add clock back to parent clockdomain usecount */
+	if (clk->usecount && clk->clkdm)
+		clkdm_clk_enable(clk->clkdm, clk);
 }
 
 /* Public data */
diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c
index 173905d..7715353 100644
--- a/arch/arm/mach-omap2/clockdomain.c
+++ b/arch/arm/mach-omap2/clockdomain.c
@@ -910,6 +910,7 @@ bool clkdm_in_hwsup(struct clockdomain *clkdm)
 static int _clkdm_clk_hwmod_enable(struct clockdomain *clkdm)
 {
 	unsigned long flags;
+	int usecount;
 
 	if (!clkdm || !arch_clkdm || !arch_clkdm->clkdm_clk_enable)
 		return -EINVAL;
@@ -921,12 +922,16 @@ static int _clkdm_clk_hwmod_enable(struct clockdomain *clkdm)
 	 * should be called for every clock instance or hwmod that is
 	 * enabled, so the clkdm can be force woken up.
 	 */
-	if ((atomic_inc_return(&clkdm->usecount) > 1) && autodeps) {
+	usecount = atomic_inc_return(&clkdm->usecount);
+
+	if (usecount > 1 && autodeps) {
 		spin_unlock_irqrestore(&clkdm->lock, flags);
 		return 0;
 	}
 
 	arch_clkdm->clkdm_clk_enable(clkdm);
+	if (usecount == 1)
+		pwrdm_clkdm_enable(clkdm->pwrdm.ptr);
 	pwrdm_state_switch(clkdm->pwrdm.ptr);
 	spin_unlock_irqrestore(&clkdm->lock, flags);
 
@@ -956,6 +961,7 @@ static int _clkdm_clk_hwmod_disable(struct clockdomain *clkdm)
 	}
 
 	arch_clkdm->clkdm_clk_disable(clkdm);
+	pwrdm_clkdm_disable(clkdm->pwrdm.ptr);
 	pwrdm_state_switch(clkdm->pwrdm.ptr);
 	spin_unlock_irqrestore(&clkdm->lock, flags);
 
@@ -988,6 +994,10 @@ int clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk)
 	if (!clk)
 		return -EINVAL;
 
+	/* If autoidle clock, do not update clkdm usecounts */
+	if (clk->autoidle)
+		return 0;
+
 	return _clkdm_clk_hwmod_enable(clkdm);
 }
 
@@ -1014,6 +1024,10 @@ int clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk)
 	if (!clk)
 		return -EINVAL;
 
+	/* If autoidle clock, do not update clkdm usecounts */
+	if (clk->autoidle)
+		return 0;
+
 	return _clkdm_clk_hwmod_disable(clkdm);
 }
 
diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c
index b9c8d2f..da660d2 100644
--- a/arch/arm/mach-omap2/dpll3xxx.c
+++ b/arch/arm/mach-omap2/dpll3xxx.c
@@ -34,6 +34,7 @@
 #include "clock.h"
 #include "cm2xxx_3xxx.h"
 #include "cm-regbits-34xx.h"
+#include "clockdomain.h"
 
 /* CM_AUTOIDLE_PLL*.AUTO_* bit values */
 #define DPLL_AUTOIDLE_DISABLE			0x0
@@ -571,6 +572,15 @@ void omap3_dpll_allow_idle(struct clk *clk)
 	v |= DPLL_AUTOIDLE_LOW_POWER_STOP << __ffs(dd->autoidle_mask);
 	__raw_writel(v, dd->autoidle_reg);
 
+	/* Remove this clock from parent clockdomain usecounts */
+	if (clk->usecount && clk->clkdm)
+		clkdm_clk_disable(clk->clkdm, clk);
+
+	/*
+	 * Mark as autoidle, so we continue to ignore this clock in
+	 * parent clkdm usecount calculations
+	 */
+	clk->autoidle = true;
 }
 
 /**
@@ -600,6 +610,15 @@ void omap3_dpll_deny_idle(struct clk *clk)
 	v |= DPLL_AUTOIDLE_DISABLE << __ffs(dd->autoidle_mask);
 	__raw_writel(v, dd->autoidle_reg);
 
+	/*
+	 * Disable autoidle flag so further clkdm usecounts take this
+	 * clock into account
+	 */
+	clk->autoidle = false;
+
+	/* Add clock back to parent clockdomain usecount */
+	if (clk->usecount && clk->clkdm)
+		clkdm_clk_enable(clk->clkdm, clk);
 }
 
 /* Clock control for DPLL outputs */
diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
index d6daa81..ba49029 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -1466,6 +1466,41 @@ int pwrdm_state_switch(struct powerdomain *pwrdm)
 	return ret;
 }
 
+/**
+ * pwrdm_clkdm_enable - increment powerdomain usecount
+ * @pwrdm: struct powerdomain *
+ *
+ * Increases the usecount for a powerdomain. Called from clockdomain
+ * code once a clockdomain becomes active.
+ */
+void pwrdm_clkdm_enable(struct powerdomain *pwrdm)
+{
+	if (!pwrdm)
+		return;
+
+	atomic_inc(&pwrdm->usecount);
+}
+
+/**
+ * pwrdm_clkdm_disable - decrease powerdomain usecount
+ * @pwrdm: struct powerdomain *
+ *
+ * Decreases the usecount for a powerdomain. Called from clockdomain
+ * code once a clockdomain usecount reaches zero, i.e. it is ready to
+ * idle.
+ */
+void pwrdm_clkdm_disable(struct powerdomain *pwrdm)
+{
+	int val;
+
+	if (!pwrdm)
+		return;
+
+	val = atomic_dec_return(&pwrdm->usecount);
+
+	WARN_ON(val < 0);
+}
+
 int pwrdm_pre_transition(struct powerdomain *pwrdm)
 {
 	if (pwrdm)
diff --git a/arch/arm/mach-omap2/powerdomain.h b/arch/arm/mach-omap2/powerdomain.h
index dcd2315..1bad255 100644
--- a/arch/arm/mach-omap2/powerdomain.h
+++ b/arch/arm/mach-omap2/powerdomain.h
@@ -92,6 +92,9 @@ int pwrdm_state_switch(struct powerdomain *pwrdm);
 int pwrdm_pre_transition(struct powerdomain *pwrdm);
 int pwrdm_post_transition(struct powerdomain *pwrdm);
 
+void pwrdm_clkdm_enable(struct powerdomain *pwrdm);
+void pwrdm_clkdm_disable(struct powerdomain *pwrdm);
+
 int pwrdm_get_context_loss_count(struct powerdomain *pwrdm);
 bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm);
 
@@ -209,6 +212,7 @@ struct powerdomain {
 	unsigned state_counter[PWRDM_MAX_FUNC_PWRSTS];
 	unsigned ret_logic_off_counter;
 	unsigned ret_mem_off_counter[PWRDM_MAX_MEM_BANKS];
+	atomic_t usecount;
 
 	const u8 pwrstctrl_offs;
 	const u8 pwrstst_offs;
diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c
index 706b7e2..d657d39 100644
--- a/arch/arm/plat-omap/clock.c
+++ b/arch/arm/plat-omap/clock.c
@@ -282,6 +282,12 @@ int clk_register(struct clk *clk)
 		list_add(&clk->sibling, &root_clks);
 
 	list_add(&clk->node, &clocks);
+	/*
+	 * If clock has no ops, it is handled by hardware and thus will
+	 * idle automatically
+	 */
+	if (clk->ops == &clkops_null)
+		clk->autoidle = true;
 	if (clk->init)
 		clk->init(clk);
 	mutex_unlock(&clocks_mutex);
diff --git a/arch/arm/plat-omap/include/plat/clock.h b/arch/arm/plat-omap/include/plat/clock.h
index 656b986..3b5acea 100644
--- a/arch/arm/plat-omap/include/plat/clock.h
+++ b/arch/arm/plat-omap/include/plat/clock.h
@@ -206,6 +206,7 @@ struct dpll_data {
  * @init: fn ptr to do clock-specific initialization
  * @enable_bit: bitshift to write to enable/disable the clock (see @enable_reg)
  * @usecount: number of users that have requested this clock to be enabled
+ * @autoidle: indicates hardware controlled clock (not used in domain usecounts)
  * @fixed_div: when > 0, this clock's rate is its parent's rate / @fixed_div
  * @flags: see "struct clk.flags possibilities" above
  * @clksel_reg: for clksel clks, register va containing src/divisor select
@@ -252,6 +253,7 @@ struct clk {
 	void			(*init)(struct clk *);
 	u8			enable_bit;
 	s8			usecount;
+	bool			autoidle;
 	u8			fixed_div;
 	u8			flags;
 #ifdef CONFIG_ARCH_OMAP2PLUS
-- 
1.7.4.1


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

* [PATCHv6 02/11] ARM: OMAP3+: voltage/pwrdm/clkdm/clock add recursive usecount tracking
@ 2012-09-25 16:05   ` Tero Kristo
  0 siblings, 0 replies; 30+ messages in thread
From: Tero Kristo @ 2012-09-25 16:05 UTC (permalink / raw)
  To: linux-arm-kernel

This patch fixes the usecount tracking for omap3+, previously the
usecount numbers were rather bogus and were not really useful for
any purpose. Now usecount numbers track the number of really active
clients on each domain. This patch also adds support for usecount
tracking on powerdomain level and autoidle flag for clocks that
are hardware controlled and should be skipped in usecount
calculations.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
Cc: Paul Walmsley <paul@pwsan.com>
Cc: Kevin Hilman <khilman@ti.com>
---
 arch/arm/mach-omap2/clkt_iclk.c         |   21 ++++++++++++++++++
 arch/arm/mach-omap2/clockdomain.c       |   16 +++++++++++++-
 arch/arm/mach-omap2/dpll3xxx.c          |   19 ++++++++++++++++
 arch/arm/mach-omap2/powerdomain.c       |   35 +++++++++++++++++++++++++++++++
 arch/arm/mach-omap2/powerdomain.h       |    4 +++
 arch/arm/plat-omap/clock.c              |    6 +++++
 arch/arm/plat-omap/include/plat/clock.h |    2 +
 7 files changed, 102 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-omap2/clkt_iclk.c b/arch/arm/mach-omap2/clkt_iclk.c
index 3d43fba..1afc599 100644
--- a/arch/arm/mach-omap2/clkt_iclk.c
+++ b/arch/arm/mach-omap2/clkt_iclk.c
@@ -21,6 +21,7 @@
 #include "clock2xxx.h"
 #include "cm2xxx_3xxx.h"
 #include "cm-regbits-24xx.h"
+#include "clockdomain.h"
 
 /* Private functions */
 
@@ -34,6 +35,16 @@ void omap2_clkt_iclk_allow_idle(struct clk *clk)
 	v = __raw_readl((__force void __iomem *)r);
 	v |= (1 << clk->enable_bit);
 	__raw_writel(v, (__force void __iomem *)r);
+
+	/* Remove this clock from parent clockdomain usecounts */
+	if (clk->usecount && clk->clkdm)
+		clkdm_clk_disable(clk->clkdm, clk);
+
+	/*
+	 * Mark as autoidle, so we continue to ignore this clock in
+	 * parent clkdm usecount calculations
+	 */
+	clk->autoidle = true;
 }
 
 /* XXX */
@@ -46,6 +57,16 @@ void omap2_clkt_iclk_deny_idle(struct clk *clk)
 	v = __raw_readl((__force void __iomem *)r);
 	v &= ~(1 << clk->enable_bit);
 	__raw_writel(v, (__force void __iomem *)r);
+
+	/*
+	 * Disable autoidle flag so further clkdm usecounts take this
+	 * clock into account
+	 */
+	clk->autoidle = false;
+
+	/* Add clock back to parent clockdomain usecount */
+	if (clk->usecount && clk->clkdm)
+		clkdm_clk_enable(clk->clkdm, clk);
 }
 
 /* Public data */
diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c
index 173905d..7715353 100644
--- a/arch/arm/mach-omap2/clockdomain.c
+++ b/arch/arm/mach-omap2/clockdomain.c
@@ -910,6 +910,7 @@ bool clkdm_in_hwsup(struct clockdomain *clkdm)
 static int _clkdm_clk_hwmod_enable(struct clockdomain *clkdm)
 {
 	unsigned long flags;
+	int usecount;
 
 	if (!clkdm || !arch_clkdm || !arch_clkdm->clkdm_clk_enable)
 		return -EINVAL;
@@ -921,12 +922,16 @@ static int _clkdm_clk_hwmod_enable(struct clockdomain *clkdm)
 	 * should be called for every clock instance or hwmod that is
 	 * enabled, so the clkdm can be force woken up.
 	 */
-	if ((atomic_inc_return(&clkdm->usecount) > 1) && autodeps) {
+	usecount = atomic_inc_return(&clkdm->usecount);
+
+	if (usecount > 1 && autodeps) {
 		spin_unlock_irqrestore(&clkdm->lock, flags);
 		return 0;
 	}
 
 	arch_clkdm->clkdm_clk_enable(clkdm);
+	if (usecount == 1)
+		pwrdm_clkdm_enable(clkdm->pwrdm.ptr);
 	pwrdm_state_switch(clkdm->pwrdm.ptr);
 	spin_unlock_irqrestore(&clkdm->lock, flags);
 
@@ -956,6 +961,7 @@ static int _clkdm_clk_hwmod_disable(struct clockdomain *clkdm)
 	}
 
 	arch_clkdm->clkdm_clk_disable(clkdm);
+	pwrdm_clkdm_disable(clkdm->pwrdm.ptr);
 	pwrdm_state_switch(clkdm->pwrdm.ptr);
 	spin_unlock_irqrestore(&clkdm->lock, flags);
 
@@ -988,6 +994,10 @@ int clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk)
 	if (!clk)
 		return -EINVAL;
 
+	/* If autoidle clock, do not update clkdm usecounts */
+	if (clk->autoidle)
+		return 0;
+
 	return _clkdm_clk_hwmod_enable(clkdm);
 }
 
@@ -1014,6 +1024,10 @@ int clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk)
 	if (!clk)
 		return -EINVAL;
 
+	/* If autoidle clock, do not update clkdm usecounts */
+	if (clk->autoidle)
+		return 0;
+
 	return _clkdm_clk_hwmod_disable(clkdm);
 }
 
diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c
index b9c8d2f..da660d2 100644
--- a/arch/arm/mach-omap2/dpll3xxx.c
+++ b/arch/arm/mach-omap2/dpll3xxx.c
@@ -34,6 +34,7 @@
 #include "clock.h"
 #include "cm2xxx_3xxx.h"
 #include "cm-regbits-34xx.h"
+#include "clockdomain.h"
 
 /* CM_AUTOIDLE_PLL*.AUTO_* bit values */
 #define DPLL_AUTOIDLE_DISABLE			0x0
@@ -571,6 +572,15 @@ void omap3_dpll_allow_idle(struct clk *clk)
 	v |= DPLL_AUTOIDLE_LOW_POWER_STOP << __ffs(dd->autoidle_mask);
 	__raw_writel(v, dd->autoidle_reg);
 
+	/* Remove this clock from parent clockdomain usecounts */
+	if (clk->usecount && clk->clkdm)
+		clkdm_clk_disable(clk->clkdm, clk);
+
+	/*
+	 * Mark as autoidle, so we continue to ignore this clock in
+	 * parent clkdm usecount calculations
+	 */
+	clk->autoidle = true;
 }
 
 /**
@@ -600,6 +610,15 @@ void omap3_dpll_deny_idle(struct clk *clk)
 	v |= DPLL_AUTOIDLE_DISABLE << __ffs(dd->autoidle_mask);
 	__raw_writel(v, dd->autoidle_reg);
 
+	/*
+	 * Disable autoidle flag so further clkdm usecounts take this
+	 * clock into account
+	 */
+	clk->autoidle = false;
+
+	/* Add clock back to parent clockdomain usecount */
+	if (clk->usecount && clk->clkdm)
+		clkdm_clk_enable(clk->clkdm, clk);
 }
 
 /* Clock control for DPLL outputs */
diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
index d6daa81..ba49029 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -1466,6 +1466,41 @@ int pwrdm_state_switch(struct powerdomain *pwrdm)
 	return ret;
 }
 
+/**
+ * pwrdm_clkdm_enable - increment powerdomain usecount
+ * @pwrdm: struct powerdomain *
+ *
+ * Increases the usecount for a powerdomain. Called from clockdomain
+ * code once a clockdomain becomes active.
+ */
+void pwrdm_clkdm_enable(struct powerdomain *pwrdm)
+{
+	if (!pwrdm)
+		return;
+
+	atomic_inc(&pwrdm->usecount);
+}
+
+/**
+ * pwrdm_clkdm_disable - decrease powerdomain usecount
+ * @pwrdm: struct powerdomain *
+ *
+ * Decreases the usecount for a powerdomain. Called from clockdomain
+ * code once a clockdomain usecount reaches zero, i.e. it is ready to
+ * idle.
+ */
+void pwrdm_clkdm_disable(struct powerdomain *pwrdm)
+{
+	int val;
+
+	if (!pwrdm)
+		return;
+
+	val = atomic_dec_return(&pwrdm->usecount);
+
+	WARN_ON(val < 0);
+}
+
 int pwrdm_pre_transition(struct powerdomain *pwrdm)
 {
 	if (pwrdm)
diff --git a/arch/arm/mach-omap2/powerdomain.h b/arch/arm/mach-omap2/powerdomain.h
index dcd2315..1bad255 100644
--- a/arch/arm/mach-omap2/powerdomain.h
+++ b/arch/arm/mach-omap2/powerdomain.h
@@ -92,6 +92,9 @@ int pwrdm_state_switch(struct powerdomain *pwrdm);
 int pwrdm_pre_transition(struct powerdomain *pwrdm);
 int pwrdm_post_transition(struct powerdomain *pwrdm);
 
+void pwrdm_clkdm_enable(struct powerdomain *pwrdm);
+void pwrdm_clkdm_disable(struct powerdomain *pwrdm);
+
 int pwrdm_get_context_loss_count(struct powerdomain *pwrdm);
 bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm);
 
@@ -209,6 +212,7 @@ struct powerdomain {
 	unsigned state_counter[PWRDM_MAX_FUNC_PWRSTS];
 	unsigned ret_logic_off_counter;
 	unsigned ret_mem_off_counter[PWRDM_MAX_MEM_BANKS];
+	atomic_t usecount;
 
 	const u8 pwrstctrl_offs;
 	const u8 pwrstst_offs;
diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c
index 706b7e2..d657d39 100644
--- a/arch/arm/plat-omap/clock.c
+++ b/arch/arm/plat-omap/clock.c
@@ -282,6 +282,12 @@ int clk_register(struct clk *clk)
 		list_add(&clk->sibling, &root_clks);
 
 	list_add(&clk->node, &clocks);
+	/*
+	 * If clock has no ops, it is handled by hardware and thus will
+	 * idle automatically
+	 */
+	if (clk->ops == &clkops_null)
+		clk->autoidle = true;
 	if (clk->init)
 		clk->init(clk);
 	mutex_unlock(&clocks_mutex);
diff --git a/arch/arm/plat-omap/include/plat/clock.h b/arch/arm/plat-omap/include/plat/clock.h
index 656b986..3b5acea 100644
--- a/arch/arm/plat-omap/include/plat/clock.h
+++ b/arch/arm/plat-omap/include/plat/clock.h
@@ -206,6 +206,7 @@ struct dpll_data {
  * @init: fn ptr to do clock-specific initialization
  * @enable_bit: bitshift to write to enable/disable the clock (see @enable_reg)
  * @usecount: number of users that have requested this clock to be enabled
+ * @autoidle: indicates hardware controlled clock (not used in domain usecounts)
  * @fixed_div: when > 0, this clock's rate is its parent's rate / @fixed_div
  * @flags: see "struct clk.flags possibilities" above
  * @clksel_reg: for clksel clks, register va containing src/divisor select
@@ -252,6 +253,7 @@ struct clk {
 	void			(*init)(struct clk *);
 	u8			enable_bit;
 	s8			usecount;
+	bool			autoidle;
 	u8			fixed_div;
 	u8			flags;
 #ifdef CONFIG_ARCH_OMAP2PLUS
-- 
1.7.4.1

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

* [PATCHv6 03/11] ARM: OMAP3+: voltage: add support for voltagedomain usecounts
  2012-09-25 16:05 ` Tero Kristo
@ 2012-09-25 16:05   ` Tero Kristo
  -1 siblings, 0 replies; 30+ messages in thread
From: Tero Kristo @ 2012-09-25 16:05 UTC (permalink / raw)
  To: linux-omap, khilman, paul; +Cc: linux-arm-kernel

These are updated based on powerdomain usecounts. Also added support
for voltdm->sleep and voltdm->wakeup calls that will be invoked once
voltagedomain enters sleep or wakes up based on usecount numbers. These
will be used for controlling voltage scaling functionality.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
Cc: Paul Walmsley <paul@pwsan.com>
Cc: Kevin Hilman <khilman@ti.com>
---
 arch/arm/mach-omap2/powerdomain.c |   17 +++++++++-
 arch/arm/mach-omap2/voltage.c     |   65 +++++++++++++++++++++++++++++++++++++
 arch/arm/mach-omap2/voltage.h     |   13 +++++++
 3 files changed, 94 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
index ba49029..abc50c2 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -1475,10 +1475,17 @@ int pwrdm_state_switch(struct powerdomain *pwrdm)
  */
 void pwrdm_clkdm_enable(struct powerdomain *pwrdm)
 {
+	unsigned long flags;
+
 	if (!pwrdm)
 		return;
 
-	atomic_inc(&pwrdm->usecount);
+	spin_lock_irqsave(&pwrdm->lock, flags);
+
+	if (atomic_inc_return(&pwrdm->usecount) == 1)
+		voltdm_pwrdm_enable(pwrdm->voltdm.ptr);
+
+	spin_unlock_irqrestore(&pwrdm->lock, flags);
 }
 
 /**
@@ -1492,12 +1499,20 @@ void pwrdm_clkdm_enable(struct powerdomain *pwrdm)
 void pwrdm_clkdm_disable(struct powerdomain *pwrdm)
 {
 	int val;
+	unsigned long flags;
 
 	if (!pwrdm)
 		return;
 
+	spin_lock_irqsave(&pwrdm->lock, flags);
+
 	val = atomic_dec_return(&pwrdm->usecount);
 
+	if (!val)
+		voltdm_pwrdm_disable(pwrdm->voltdm.ptr);
+
+	spin_unlock_irqrestore(&pwrdm->lock, flags);
+
 	WARN_ON(val < 0);
 }
 
diff --git a/arch/arm/mach-omap2/voltage.c b/arch/arm/mach-omap2/voltage.c
index 4dc60e8..0fc2a25 100644
--- a/arch/arm/mach-omap2/voltage.c
+++ b/arch/arm/mach-omap2/voltage.c
@@ -340,6 +340,70 @@ int voltdm_add_pwrdm(struct voltagedomain *voltdm, struct powerdomain *pwrdm)
 }
 
 /**
+ * voltdm_pwrdm_enable - increase usecount for a voltagedomain
+ * @voltdm: struct voltagedomain * to increase count for
+ *
+ * Increases usecount for a given voltagedomain. If the usecount reaches
+ * 1, the domain is awakened from idle and the function will call the
+ * voltagedomain->wakeup callback for this domain.
+ */
+void voltdm_pwrdm_enable(struct voltagedomain *voltdm)
+{
+	unsigned long flags;
+
+	if (!voltdm)
+		return;
+
+	spin_lock_irqsave(&voltdm->lock, flags);
+
+	if (atomic_inc_return(&voltdm->usecount) == 1 && voltdm->wakeup)
+		voltdm->wakeup(voltdm);
+
+	spin_unlock_irqrestore(&voltdm->lock, flags);
+}
+
+/**
+ * voltdm_pwrdm_disable - decrease usecount for a voltagedomain
+ * @voltdm: struct voltagedomain * to decrease count for
+ *
+ * Decreases the usecount for a given voltagedomain. If the usecount
+ * reaches zero, the domain can idle and the function will call the
+ * voltagedomain->sleep callback, and calculate the overall target
+ * state for the voltagedomain.
+ */
+void voltdm_pwrdm_disable(struct voltagedomain *voltdm)
+{
+	u8 target_state = PWRDM_POWER_OFF;
+	int state;
+	struct powerdomain *pwrdm;
+	int val;
+	unsigned long flags;
+
+	if (!voltdm)
+		return;
+
+	spin_lock_irqsave(&voltdm->lock, flags);
+
+	val = atomic_dec_return(&voltdm->usecount);
+
+	WARN_ON(val < 0);
+
+	if (val == 0) {
+		/* Determine target state for voltdm */
+		list_for_each_entry(pwrdm, &voltdm->pwrdm_list, voltdm_node) {
+			state = pwrdm_read_next_pwrst(pwrdm);
+			if (state > target_state)
+				target_state = state;
+		}
+		voltdm->target_state = target_state;
+		if (voltdm->sleep)
+			voltdm->sleep(voltdm);
+	}
+
+	spin_unlock_irqrestore(&voltdm->lock, flags);
+}
+
+/**
  * voltdm_for_each_pwrdm - call function for each pwrdm in a voltdm
  * @voltdm: struct voltagedomain * to iterate over
  * @fn: callback function *
@@ -402,6 +466,7 @@ static int _voltdm_register(struct voltagedomain *voltdm)
 	INIT_LIST_HEAD(&voltdm->pwrdm_list);
 	list_add(&voltdm->node, &voltdm_list);
 
+	spin_lock_init(&voltdm->lock);
 	pr_debug("voltagedomain: registered %s\n", voltdm->name);
 
 	return 0;
diff --git a/arch/arm/mach-omap2/voltage.h b/arch/arm/mach-omap2/voltage.h
index 0ac2caf..7f4f99d 100644
--- a/arch/arm/mach-omap2/voltage.h
+++ b/arch/arm/mach-omap2/voltage.h
@@ -15,6 +15,7 @@
 #define __ARCH_ARM_MACH_OMAP2_VOLTAGE_H
 
 #include <linux/err.h>
+#include <linux/spinlock.h>
 
 #include <plat/voltage.h>
 
@@ -56,10 +57,14 @@ struct omap_vfsm_instance {
  * @pwrdm_list: list_head linking all powerdomains in this voltagedomain
  * @vc: pointer to VC channel associated with this voltagedomain
  * @vp: pointer to VP associated with this voltagedomain
+ * @usecount: number of users for this voltagedomain
+ * @target_state: calculated target state for the children of this domain
  * @read: read a VC/VP register
  * @write: write a VC/VP register
  * @read: read-modify-write a VC/VP register
  * @sys_clk: system clock name/frequency, used for various timing calculations
+ * @sleep: function to call once the domain enters idle
+ * @wakeup: function to call once the domain wakes up from idle
  * @scale: function used to scale the voltage of the voltagedomain
  * @nominal_volt: current nominal voltage for this voltage domain
  * @volt_data: voltage table having the distinct voltages supported
@@ -75,6 +80,9 @@ struct voltagedomain {
 	struct omap_vp_instance *vp;
 	struct omap_voltdm_pmic *pmic;
 
+	atomic_t usecount;
+	u8 target_state;
+
 	/* VC/VP register access functions: SoC specific */
 	u32 (*read) (u8 offset);
 	void (*write) (u32 val, u8 offset);
@@ -85,11 +93,14 @@ struct voltagedomain {
 		u32 rate;
 	} sys_clk;
 
+	void (*sleep) (struct voltagedomain *voltdm);
+	void (*wakeup) (struct voltagedomain *voltdm);
 	int (*scale) (struct voltagedomain *voltdm,
 		      unsigned long target_volt);
 
 	u32 nominal_volt;
 	struct omap_volt_data *volt_data;
+	spinlock_t lock;
 };
 
 /**
@@ -145,6 +156,8 @@ extern void omap44xx_voltagedomains_init(void);
 struct voltagedomain *voltdm_lookup(const char *name);
 void voltdm_init(struct voltagedomain **voltdm_list);
 int voltdm_add_pwrdm(struct voltagedomain *voltdm, struct powerdomain *pwrdm);
+void voltdm_pwrdm_enable(struct voltagedomain *voltdm);
+void voltdm_pwrdm_disable(struct voltagedomain *voltdm);
 int voltdm_for_each(int (*fn)(struct voltagedomain *voltdm, void *user),
 		    void *user);
 int voltdm_for_each_pwrdm(struct voltagedomain *voltdm,
-- 
1.7.4.1


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

* [PATCHv6 03/11] ARM: OMAP3+: voltage: add support for voltagedomain usecounts
@ 2012-09-25 16:05   ` Tero Kristo
  0 siblings, 0 replies; 30+ messages in thread
From: Tero Kristo @ 2012-09-25 16:05 UTC (permalink / raw)
  To: linux-arm-kernel

These are updated based on powerdomain usecounts. Also added support
for voltdm->sleep and voltdm->wakeup calls that will be invoked once
voltagedomain enters sleep or wakes up based on usecount numbers. These
will be used for controlling voltage scaling functionality.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
Cc: Paul Walmsley <paul@pwsan.com>
Cc: Kevin Hilman <khilman@ti.com>
---
 arch/arm/mach-omap2/powerdomain.c |   17 +++++++++-
 arch/arm/mach-omap2/voltage.c     |   65 +++++++++++++++++++++++++++++++++++++
 arch/arm/mach-omap2/voltage.h     |   13 +++++++
 3 files changed, 94 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
index ba49029..abc50c2 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -1475,10 +1475,17 @@ int pwrdm_state_switch(struct powerdomain *pwrdm)
  */
 void pwrdm_clkdm_enable(struct powerdomain *pwrdm)
 {
+	unsigned long flags;
+
 	if (!pwrdm)
 		return;
 
-	atomic_inc(&pwrdm->usecount);
+	spin_lock_irqsave(&pwrdm->lock, flags);
+
+	if (atomic_inc_return(&pwrdm->usecount) == 1)
+		voltdm_pwrdm_enable(pwrdm->voltdm.ptr);
+
+	spin_unlock_irqrestore(&pwrdm->lock, flags);
 }
 
 /**
@@ -1492,12 +1499,20 @@ void pwrdm_clkdm_enable(struct powerdomain *pwrdm)
 void pwrdm_clkdm_disable(struct powerdomain *pwrdm)
 {
 	int val;
+	unsigned long flags;
 
 	if (!pwrdm)
 		return;
 
+	spin_lock_irqsave(&pwrdm->lock, flags);
+
 	val = atomic_dec_return(&pwrdm->usecount);
 
+	if (!val)
+		voltdm_pwrdm_disable(pwrdm->voltdm.ptr);
+
+	spin_unlock_irqrestore(&pwrdm->lock, flags);
+
 	WARN_ON(val < 0);
 }
 
diff --git a/arch/arm/mach-omap2/voltage.c b/arch/arm/mach-omap2/voltage.c
index 4dc60e8..0fc2a25 100644
--- a/arch/arm/mach-omap2/voltage.c
+++ b/arch/arm/mach-omap2/voltage.c
@@ -340,6 +340,70 @@ int voltdm_add_pwrdm(struct voltagedomain *voltdm, struct powerdomain *pwrdm)
 }
 
 /**
+ * voltdm_pwrdm_enable - increase usecount for a voltagedomain
+ * @voltdm: struct voltagedomain * to increase count for
+ *
+ * Increases usecount for a given voltagedomain. If the usecount reaches
+ * 1, the domain is awakened from idle and the function will call the
+ * voltagedomain->wakeup callback for this domain.
+ */
+void voltdm_pwrdm_enable(struct voltagedomain *voltdm)
+{
+	unsigned long flags;
+
+	if (!voltdm)
+		return;
+
+	spin_lock_irqsave(&voltdm->lock, flags);
+
+	if (atomic_inc_return(&voltdm->usecount) == 1 && voltdm->wakeup)
+		voltdm->wakeup(voltdm);
+
+	spin_unlock_irqrestore(&voltdm->lock, flags);
+}
+
+/**
+ * voltdm_pwrdm_disable - decrease usecount for a voltagedomain
+ * @voltdm: struct voltagedomain * to decrease count for
+ *
+ * Decreases the usecount for a given voltagedomain. If the usecount
+ * reaches zero, the domain can idle and the function will call the
+ * voltagedomain->sleep callback, and calculate the overall target
+ * state for the voltagedomain.
+ */
+void voltdm_pwrdm_disable(struct voltagedomain *voltdm)
+{
+	u8 target_state = PWRDM_POWER_OFF;
+	int state;
+	struct powerdomain *pwrdm;
+	int val;
+	unsigned long flags;
+
+	if (!voltdm)
+		return;
+
+	spin_lock_irqsave(&voltdm->lock, flags);
+
+	val = atomic_dec_return(&voltdm->usecount);
+
+	WARN_ON(val < 0);
+
+	if (val == 0) {
+		/* Determine target state for voltdm */
+		list_for_each_entry(pwrdm, &voltdm->pwrdm_list, voltdm_node) {
+			state = pwrdm_read_next_pwrst(pwrdm);
+			if (state > target_state)
+				target_state = state;
+		}
+		voltdm->target_state = target_state;
+		if (voltdm->sleep)
+			voltdm->sleep(voltdm);
+	}
+
+	spin_unlock_irqrestore(&voltdm->lock, flags);
+}
+
+/**
  * voltdm_for_each_pwrdm - call function for each pwrdm in a voltdm
  * @voltdm: struct voltagedomain * to iterate over
  * @fn: callback function *
@@ -402,6 +466,7 @@ static int _voltdm_register(struct voltagedomain *voltdm)
 	INIT_LIST_HEAD(&voltdm->pwrdm_list);
 	list_add(&voltdm->node, &voltdm_list);
 
+	spin_lock_init(&voltdm->lock);
 	pr_debug("voltagedomain: registered %s\n", voltdm->name);
 
 	return 0;
diff --git a/arch/arm/mach-omap2/voltage.h b/arch/arm/mach-omap2/voltage.h
index 0ac2caf..7f4f99d 100644
--- a/arch/arm/mach-omap2/voltage.h
+++ b/arch/arm/mach-omap2/voltage.h
@@ -15,6 +15,7 @@
 #define __ARCH_ARM_MACH_OMAP2_VOLTAGE_H
 
 #include <linux/err.h>
+#include <linux/spinlock.h>
 
 #include <plat/voltage.h>
 
@@ -56,10 +57,14 @@ struct omap_vfsm_instance {
  * @pwrdm_list: list_head linking all powerdomains in this voltagedomain
  * @vc: pointer to VC channel associated with this voltagedomain
  * @vp: pointer to VP associated with this voltagedomain
+ * @usecount: number of users for this voltagedomain
+ * @target_state: calculated target state for the children of this domain
  * @read: read a VC/VP register
  * @write: write a VC/VP register
  * @read: read-modify-write a VC/VP register
  * @sys_clk: system clock name/frequency, used for various timing calculations
+ * @sleep: function to call once the domain enters idle
+ * @wakeup: function to call once the domain wakes up from idle
  * @scale: function used to scale the voltage of the voltagedomain
  * @nominal_volt: current nominal voltage for this voltage domain
  * @volt_data: voltage table having the distinct voltages supported
@@ -75,6 +80,9 @@ struct voltagedomain {
 	struct omap_vp_instance *vp;
 	struct omap_voltdm_pmic *pmic;
 
+	atomic_t usecount;
+	u8 target_state;
+
 	/* VC/VP register access functions: SoC specific */
 	u32 (*read) (u8 offset);
 	void (*write) (u32 val, u8 offset);
@@ -85,11 +93,14 @@ struct voltagedomain {
 		u32 rate;
 	} sys_clk;
 
+	void (*sleep) (struct voltagedomain *voltdm);
+	void (*wakeup) (struct voltagedomain *voltdm);
 	int (*scale) (struct voltagedomain *voltdm,
 		      unsigned long target_volt);
 
 	u32 nominal_volt;
 	struct omap_volt_data *volt_data;
+	spinlock_t lock;
 };
 
 /**
@@ -145,6 +156,8 @@ extern void omap44xx_voltagedomains_init(void);
 struct voltagedomain *voltdm_lookup(const char *name);
 void voltdm_init(struct voltagedomain **voltdm_list);
 int voltdm_add_pwrdm(struct voltagedomain *voltdm, struct powerdomain *pwrdm);
+void voltdm_pwrdm_enable(struct voltagedomain *voltdm);
+void voltdm_pwrdm_disable(struct voltagedomain *voltdm);
 int voltdm_for_each(int (*fn)(struct voltagedomain *voltdm, void *user),
 		    void *user);
 int voltdm_for_each_pwrdm(struct voltagedomain *voltdm,
-- 
1.7.4.1

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

* [PATCHv6 04/11] ARM: OMAP3: add manual control for mpu / core pwrdm usecounting
  2012-09-25 16:05 ` Tero Kristo
@ 2012-09-25 16:05   ` Tero Kristo
  -1 siblings, 0 replies; 30+ messages in thread
From: Tero Kristo @ 2012-09-25 16:05 UTC (permalink / raw)
  To: linux-omap, khilman, paul; +Cc: linux-arm-kernel

mpu / core powerdomain usecounts are now statically increased
by 1 during MPU activity. This allows the domains to reflect
actual usage, and will allow the usecount to reach 0 just before
all CPUs are ready to idle. Proper powerdomain usecounts are
propageted to voltagedomain level also, and will allow vc
callbacks to be triggered at right point of time.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
Cc: Paul Walmsley <paul@pwsan.com>
Cc: Kevin Hilman <khilman@ti.com>
---
 arch/arm/mach-omap2/common.h              |    6 ++
 arch/arm/mach-omap2/omap-mpuss-lowpower.c |   72 ++++++++++++++++++++++++++++-
 arch/arm/mach-omap2/omap-smp.c            |    2 +
 arch/arm/mach-omap2/pm34xx.c              |   21 ++++++++
 4 files changed, 100 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-omap2/common.h b/arch/arm/mach-omap2/common.h
index 6ea837a..a445a02 100644
--- a/arch/arm/mach-omap2/common.h
+++ b/arch/arm/mach-omap2/common.h
@@ -292,6 +292,8 @@ extern int omap4_finish_suspend(unsigned long cpu_state);
 extern void omap4_cpu_resume(void);
 extern int omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state);
 extern u32 omap4_mpuss_read_prev_context_state(void);
+extern void omap4_pm_cpu_online(void);
+extern void omap4_pm_cpu_offline(void);
 #else
 static inline int omap4_enter_lowpower(unsigned int cpu,
 					unsigned int power_state)
@@ -323,6 +325,10 @@ static inline u32 omap4_mpuss_read_prev_context_state(void)
 {
 	return 0;
 }
+
+static inline void omap4_pm_cpu_online(void) { }
+
+static inline void omap4_pm_cpu_offline(void) { }
 #endif
 
 struct omap_sdrc_params;
diff --git a/arch/arm/mach-omap2/omap-mpuss-lowpower.c b/arch/arm/mach-omap2/omap-mpuss-lowpower.c
index 230bdcd..0ad2337 100644
--- a/arch/arm/mach-omap2/omap-mpuss-lowpower.c
+++ b/arch/arm/mach-omap2/omap-mpuss-lowpower.c
@@ -72,8 +72,9 @@ struct omap4_cpu_pm_info {
 };
 
 static DEFINE_PER_CPU(struct omap4_cpu_pm_info, omap4_pm_info);
-static struct powerdomain *mpuss_pd;
+static struct powerdomain *mpuss_pd, *core_pd;
 static void __iomem *sar_base;
+static atomic_t __initdata init_cpu_online_count;
 
 /*
  * Program the wakeup routine address for the CPU0 and CPU1
@@ -216,6 +217,50 @@ static void save_l2x0_context(void)
 #endif
 
 /**
+ * omap4_pm_cpu_online - increase the number of online CPUs
+ *
+ * This function increases the usecounts for MPU and CORE powerdomains,
+ * which allows the domains to properly reflect usage with online CPUs
+ * also. CORE powerdomain usecount is increased, as MPU is using memories,
+ * which are powered through CORE powerdomain (SDRAM). If this function is
+ * called before PM init has completed (mpuss_pd / core_pd are not defined),
+ * a temporary init time variable is increased instead; its contents
+ * will be moved to the powerdomain usecounts once PM init completes.
+ */
+void omap4_pm_cpu_online(void)
+{
+	if (!mpuss_pd || !core_pd) {
+		atomic_inc(&init_cpu_online_count);
+		return;
+	}
+
+	pwrdm_clkdm_enable(mpuss_pd);
+	pwrdm_clkdm_enable(core_pd);
+}
+
+/**
+ * omap4_pm_cpu_offline - decrease the number of online CPUs
+ *
+ * This function decreases the usecounts for MPU and CORE powerdomains,
+ * which allows the domains to properly reflect usage with online CPUs
+ * also. CORE powerdomain usecount is decreased, as MPU is using memories,
+ * which are powered through CORE powerdomain (SDRAM). If this function is
+ * called before PM init has completed (mpuss_pd / core_pd are not defined),
+ * a temporary init time variable is increased instead; its contents
+ * will be moved to the powerdomain usecounts once PM init completes.
+ */
+void omap4_pm_cpu_offline(void)
+{
+	if (!mpuss_pd || !core_pd) {
+		atomic_dec(&init_cpu_online_count);
+		return;
+	}
+
+	pwrdm_clkdm_disable(mpuss_pd);
+	pwrdm_clkdm_disable(core_pd);
+}
+
+/**
  * omap4_enter_lowpower: OMAP4 MPUSS Low Power Entry Function
  * The purpose of this function is to manage low power programming
  * of OMAP4 MPUSS subsystem
@@ -274,11 +319,17 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
 	scu_pwrst_prepare(cpu, power_state);
 	l2x0_pwrst_prepare(cpu, save_state);
 
+	/* Decrement usecounts for MPU and CORE pd as we are entering idle */
+	omap4_pm_cpu_offline();
+
 	/*
 	 * Call low level function  with targeted low power state.
 	 */
 	cpu_suspend(save_state, omap4_finish_suspend);
 
+	/* Increment usecounts for MPU and CORE pd as we are leaving idle */
+	omap4_pm_cpu_online();
+
 	/*
 	 * Restore the CPUx power state to ON otherwise CPUx
 	 * power domain can transitions to programmed low power
@@ -315,6 +366,8 @@ int __cpuinit omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state)
 	set_cpu_wakeup_addr(cpu, virt_to_phys(pm_info->secondary_startup));
 	scu_pwrst_prepare(cpu, power_state);
 
+	omap4_pm_cpu_offline();
+
 	/*
 	 * CPU never retuns back if targeted power state is OFF mode.
 	 * CPU ONLINE follows normal CPU ONLINE ptah via
@@ -322,6 +375,8 @@ int __cpuinit omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state)
 	 */
 	omap4_finish_suspend(cpu_state);
 
+	omap4_pm_cpu_online();
+
 	set_cpu_next_pwrst(cpu, PWRDM_FUNC_PWRST_ON);
 	return 0;
 }
@@ -386,9 +441,24 @@ int __init omap4_mpuss_init(void)
 		pr_err("Failed to lookup MPUSS power domain\n");
 		return -ENODEV;
 	}
+	core_pd = pwrdm_lookup("core_pwrdm");
+	if (!core_pd) {
+		pr_err("Failed to lookup CORE power domain\n");
+		return -ENODEV;
+	}
 	pwrdm_clear_all_prev_pwrst(mpuss_pd);
 	mpuss_clear_prev_logic_pwrst();
 
+	/* Notify pwrdm usecounters about active CPU */
+	omap4_pm_cpu_online();
+
+	/*
+	 * If CPUs became online / offline during init time, push
+	 * the pending counter updates also.
+	 */
+	while (atomic_dec_return(&init_cpu_online_count) >= 0)
+		omap4_pm_cpu_online();
+
 	/* Save device type on scratchpad for low level code to use */
 	if (omap_type() != OMAP2_DEVICE_TYPE_GP)
 		__raw_writel(1, sar_base + OMAP_TYPE_OFFSET);
diff --git a/arch/arm/mach-omap2/omap-smp.c b/arch/arm/mach-omap2/omap-smp.c
index b9738e2..f296e35 100644
--- a/arch/arm/mach-omap2/omap-smp.c
+++ b/arch/arm/mach-omap2/omap-smp.c
@@ -71,6 +71,8 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
 	 */
 	gic_secondary_init(0);
 
+	omap4_pm_cpu_online();
+
 	/*
 	 * Synchronise with the boot thread.
 	 */
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 5b6505f..7a423f7 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -294,6 +294,14 @@ void omap_sram_idle(void)
 	omap3_intc_prepare_idle();
 
 	/*
+	 * CPU going offline, update pwrdm counters. Core pwrdm
+	 * count is decreased as MPU is using SDRAM which resides
+	 * under core pwrdm.
+	 */
+	pwrdm_clkdm_disable(mpu_pwrdm);
+	pwrdm_clkdm_disable(core_pwrdm);
+
+	/*
 	 * On EMU/HS devices ROM code restores a SRDC value
 	 * from scratchpad which has automatic self refresh on timeout
 	 * of AUTO_CNT = 1 enabled. This takes care of erratum ID i443.
@@ -324,6 +332,12 @@ void omap_sram_idle(void)
 	    core_next_state == PWRDM_FUNC_PWRST_OFF)
 		sdrc_write_reg(sdrc_pwr, SDRC_POWER);
 
+	/*
+	 * CPU is coming back online, increase pwrdm usecounts
+	 */
+	pwrdm_clkdm_enable(mpu_pwrdm);
+	pwrdm_clkdm_enable(core_pwrdm);
+
 	/* CORE */
 	if (core_next_state < PWRDM_FUNC_PWRST_ON) {
 		core_prev_state = pwrdm_read_prev_fpwrst(core_pwrdm);
@@ -718,6 +732,13 @@ int __init omap3_pm_init(void)
 	omap_pm_suspend = omap3_pm_suspend;
 #endif
 
+	/*
+	 * CPU online, increase pwrdm usecounts for MPU and CORE domains.
+	 * MPU is using memory subsystem which resides in CORE domain.
+	 */
+	pwrdm_clkdm_enable(mpu_pwrdm);
+	pwrdm_clkdm_enable(core_pwrdm);
+
 	arm_pm_idle = omap3_pm_idle;
 	omap3_idle_init();
 
-- 
1.7.4.1


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

* [PATCHv6 04/11] ARM: OMAP3: add manual control for mpu / core pwrdm usecounting
@ 2012-09-25 16:05   ` Tero Kristo
  0 siblings, 0 replies; 30+ messages in thread
From: Tero Kristo @ 2012-09-25 16:05 UTC (permalink / raw)
  To: linux-arm-kernel

mpu / core powerdomain usecounts are now statically increased
by 1 during MPU activity. This allows the domains to reflect
actual usage, and will allow the usecount to reach 0 just before
all CPUs are ready to idle. Proper powerdomain usecounts are
propageted to voltagedomain level also, and will allow vc
callbacks to be triggered at right point of time.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
Cc: Paul Walmsley <paul@pwsan.com>
Cc: Kevin Hilman <khilman@ti.com>
---
 arch/arm/mach-omap2/common.h              |    6 ++
 arch/arm/mach-omap2/omap-mpuss-lowpower.c |   72 ++++++++++++++++++++++++++++-
 arch/arm/mach-omap2/omap-smp.c            |    2 +
 arch/arm/mach-omap2/pm34xx.c              |   21 ++++++++
 4 files changed, 100 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-omap2/common.h b/arch/arm/mach-omap2/common.h
index 6ea837a..a445a02 100644
--- a/arch/arm/mach-omap2/common.h
+++ b/arch/arm/mach-omap2/common.h
@@ -292,6 +292,8 @@ extern int omap4_finish_suspend(unsigned long cpu_state);
 extern void omap4_cpu_resume(void);
 extern int omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state);
 extern u32 omap4_mpuss_read_prev_context_state(void);
+extern void omap4_pm_cpu_online(void);
+extern void omap4_pm_cpu_offline(void);
 #else
 static inline int omap4_enter_lowpower(unsigned int cpu,
 					unsigned int power_state)
@@ -323,6 +325,10 @@ static inline u32 omap4_mpuss_read_prev_context_state(void)
 {
 	return 0;
 }
+
+static inline void omap4_pm_cpu_online(void) { }
+
+static inline void omap4_pm_cpu_offline(void) { }
 #endif
 
 struct omap_sdrc_params;
diff --git a/arch/arm/mach-omap2/omap-mpuss-lowpower.c b/arch/arm/mach-omap2/omap-mpuss-lowpower.c
index 230bdcd..0ad2337 100644
--- a/arch/arm/mach-omap2/omap-mpuss-lowpower.c
+++ b/arch/arm/mach-omap2/omap-mpuss-lowpower.c
@@ -72,8 +72,9 @@ struct omap4_cpu_pm_info {
 };
 
 static DEFINE_PER_CPU(struct omap4_cpu_pm_info, omap4_pm_info);
-static struct powerdomain *mpuss_pd;
+static struct powerdomain *mpuss_pd, *core_pd;
 static void __iomem *sar_base;
+static atomic_t __initdata init_cpu_online_count;
 
 /*
  * Program the wakeup routine address for the CPU0 and CPU1
@@ -216,6 +217,50 @@ static void save_l2x0_context(void)
 #endif
 
 /**
+ * omap4_pm_cpu_online - increase the number of online CPUs
+ *
+ * This function increases the usecounts for MPU and CORE powerdomains,
+ * which allows the domains to properly reflect usage with online CPUs
+ * also. CORE powerdomain usecount is increased, as MPU is using memories,
+ * which are powered through CORE powerdomain (SDRAM). If this function is
+ * called before PM init has completed (mpuss_pd / core_pd are not defined),
+ * a temporary init time variable is increased instead; its contents
+ * will be moved to the powerdomain usecounts once PM init completes.
+ */
+void omap4_pm_cpu_online(void)
+{
+	if (!mpuss_pd || !core_pd) {
+		atomic_inc(&init_cpu_online_count);
+		return;
+	}
+
+	pwrdm_clkdm_enable(mpuss_pd);
+	pwrdm_clkdm_enable(core_pd);
+}
+
+/**
+ * omap4_pm_cpu_offline - decrease the number of online CPUs
+ *
+ * This function decreases the usecounts for MPU and CORE powerdomains,
+ * which allows the domains to properly reflect usage with online CPUs
+ * also. CORE powerdomain usecount is decreased, as MPU is using memories,
+ * which are powered through CORE powerdomain (SDRAM). If this function is
+ * called before PM init has completed (mpuss_pd / core_pd are not defined),
+ * a temporary init time variable is increased instead; its contents
+ * will be moved to the powerdomain usecounts once PM init completes.
+ */
+void omap4_pm_cpu_offline(void)
+{
+	if (!mpuss_pd || !core_pd) {
+		atomic_dec(&init_cpu_online_count);
+		return;
+	}
+
+	pwrdm_clkdm_disable(mpuss_pd);
+	pwrdm_clkdm_disable(core_pd);
+}
+
+/**
  * omap4_enter_lowpower: OMAP4 MPUSS Low Power Entry Function
  * The purpose of this function is to manage low power programming
  * of OMAP4 MPUSS subsystem
@@ -274,11 +319,17 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
 	scu_pwrst_prepare(cpu, power_state);
 	l2x0_pwrst_prepare(cpu, save_state);
 
+	/* Decrement usecounts for MPU and CORE pd as we are entering idle */
+	omap4_pm_cpu_offline();
+
 	/*
 	 * Call low level function  with targeted low power state.
 	 */
 	cpu_suspend(save_state, omap4_finish_suspend);
 
+	/* Increment usecounts for MPU and CORE pd as we are leaving idle */
+	omap4_pm_cpu_online();
+
 	/*
 	 * Restore the CPUx power state to ON otherwise CPUx
 	 * power domain can transitions to programmed low power
@@ -315,6 +366,8 @@ int __cpuinit omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state)
 	set_cpu_wakeup_addr(cpu, virt_to_phys(pm_info->secondary_startup));
 	scu_pwrst_prepare(cpu, power_state);
 
+	omap4_pm_cpu_offline();
+
 	/*
 	 * CPU never retuns back if targeted power state is OFF mode.
 	 * CPU ONLINE follows normal CPU ONLINE ptah via
@@ -322,6 +375,8 @@ int __cpuinit omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state)
 	 */
 	omap4_finish_suspend(cpu_state);
 
+	omap4_pm_cpu_online();
+
 	set_cpu_next_pwrst(cpu, PWRDM_FUNC_PWRST_ON);
 	return 0;
 }
@@ -386,9 +441,24 @@ int __init omap4_mpuss_init(void)
 		pr_err("Failed to lookup MPUSS power domain\n");
 		return -ENODEV;
 	}
+	core_pd = pwrdm_lookup("core_pwrdm");
+	if (!core_pd) {
+		pr_err("Failed to lookup CORE power domain\n");
+		return -ENODEV;
+	}
 	pwrdm_clear_all_prev_pwrst(mpuss_pd);
 	mpuss_clear_prev_logic_pwrst();
 
+	/* Notify pwrdm usecounters about active CPU */
+	omap4_pm_cpu_online();
+
+	/*
+	 * If CPUs became online / offline during init time, push
+	 * the pending counter updates also.
+	 */
+	while (atomic_dec_return(&init_cpu_online_count) >= 0)
+		omap4_pm_cpu_online();
+
 	/* Save device type on scratchpad for low level code to use */
 	if (omap_type() != OMAP2_DEVICE_TYPE_GP)
 		__raw_writel(1, sar_base + OMAP_TYPE_OFFSET);
diff --git a/arch/arm/mach-omap2/omap-smp.c b/arch/arm/mach-omap2/omap-smp.c
index b9738e2..f296e35 100644
--- a/arch/arm/mach-omap2/omap-smp.c
+++ b/arch/arm/mach-omap2/omap-smp.c
@@ -71,6 +71,8 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
 	 */
 	gic_secondary_init(0);
 
+	omap4_pm_cpu_online();
+
 	/*
 	 * Synchronise with the boot thread.
 	 */
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 5b6505f..7a423f7 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -294,6 +294,14 @@ void omap_sram_idle(void)
 	omap3_intc_prepare_idle();
 
 	/*
+	 * CPU going offline, update pwrdm counters. Core pwrdm
+	 * count is decreased as MPU is using SDRAM which resides
+	 * under core pwrdm.
+	 */
+	pwrdm_clkdm_disable(mpu_pwrdm);
+	pwrdm_clkdm_disable(core_pwrdm);
+
+	/*
 	 * On EMU/HS devices ROM code restores a SRDC value
 	 * from scratchpad which has automatic self refresh on timeout
 	 * of AUTO_CNT = 1 enabled. This takes care of erratum ID i443.
@@ -324,6 +332,12 @@ void omap_sram_idle(void)
 	    core_next_state == PWRDM_FUNC_PWRST_OFF)
 		sdrc_write_reg(sdrc_pwr, SDRC_POWER);
 
+	/*
+	 * CPU is coming back online, increase pwrdm usecounts
+	 */
+	pwrdm_clkdm_enable(mpu_pwrdm);
+	pwrdm_clkdm_enable(core_pwrdm);
+
 	/* CORE */
 	if (core_next_state < PWRDM_FUNC_PWRST_ON) {
 		core_prev_state = pwrdm_read_prev_fpwrst(core_pwrdm);
@@ -718,6 +732,13 @@ int __init omap3_pm_init(void)
 	omap_pm_suspend = omap3_pm_suspend;
 #endif
 
+	/*
+	 * CPU online, increase pwrdm usecounts for MPU and CORE domains.
+	 * MPU is using memory subsystem which resides in CORE domain.
+	 */
+	pwrdm_clkdm_enable(mpu_pwrdm);
+	pwrdm_clkdm_enable(core_pwrdm);
+
 	arm_pm_idle = omap3_pm_idle;
 	omap3_idle_init();
 
-- 
1.7.4.1

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

* [PATCHv6 05/11] ARM: OMAP3: set autoidle flag for sdrc_ick
  2012-09-25 16:05 ` Tero Kristo
@ 2012-09-25 16:05   ` Tero Kristo
  -1 siblings, 0 replies; 30+ messages in thread
From: Tero Kristo @ 2012-09-25 16:05 UTC (permalink / raw)
  To: linux-omap, khilman, paul; +Cc: linux-arm-kernel

sdrc_ick doesn't have autoidle flag on HW, but is always automatically
idled. Thus mark the autoidle flag statically as true for it to reflect
hardware behavior. The clock will no longer show as active in usecount
dumps and will allow the voltdm->sleep / wakeup calls to work properly.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
Cc: Paul Walmsley <paul@pwsan.com>
Cc: Kevin Hilman <khilman@ti.com>
Reviewed-by: Rajendra Nayak <rnayak@ti.com>
---
 arch/arm/mach-omap2/clock3xxx_data.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/clock3xxx_data.c b/arch/arm/mach-omap2/clock3xxx_data.c
index 83bed9a..1ddc7fc 100644
--- a/arch/arm/mach-omap2/clock3xxx_data.c
+++ b/arch/arm/mach-omap2/clock3xxx_data.c
@@ -1739,6 +1739,7 @@ static struct clk sdrc_ick = {
 	.flags		= ENABLE_ON_INIT,
 	.clkdm_name	= "core_l3_clkdm",
 	.recalc		= &followparent_recalc,
+	.autoidle	= true,
 };
 
 static struct clk gpmc_fck = {
-- 
1.7.4.1


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

* [PATCHv6 05/11] ARM: OMAP3: set autoidle flag for sdrc_ick
@ 2012-09-25 16:05   ` Tero Kristo
  0 siblings, 0 replies; 30+ messages in thread
From: Tero Kristo @ 2012-09-25 16:05 UTC (permalink / raw)
  To: linux-arm-kernel

sdrc_ick doesn't have autoidle flag on HW, but is always automatically
idled. Thus mark the autoidle flag statically as true for it to reflect
hardware behavior. The clock will no longer show as active in usecount
dumps and will allow the voltdm->sleep / wakeup calls to work properly.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
Cc: Paul Walmsley <paul@pwsan.com>
Cc: Kevin Hilman <khilman@ti.com>
Reviewed-by: Rajendra Nayak <rnayak@ti.com>
---
 arch/arm/mach-omap2/clock3xxx_data.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/clock3xxx_data.c b/arch/arm/mach-omap2/clock3xxx_data.c
index 83bed9a..1ddc7fc 100644
--- a/arch/arm/mach-omap2/clock3xxx_data.c
+++ b/arch/arm/mach-omap2/clock3xxx_data.c
@@ -1739,6 +1739,7 @@ static struct clk sdrc_ick = {
 	.flags		= ENABLE_ON_INIT,
 	.clkdm_name	= "core_l3_clkdm",
 	.recalc		= &followparent_recalc,
+	.autoidle	= true,
 };
 
 static struct clk gpmc_fck = {
-- 
1.7.4.1

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

* [PATCHv6 06/11] ARM: OMAP: clockdomain: add support for preventing autodep delete
  2012-09-25 16:05 ` Tero Kristo
@ 2012-09-25 16:05   ` Tero Kristo
  -1 siblings, 0 replies; 30+ messages in thread
From: Tero Kristo @ 2012-09-25 16:05 UTC (permalink / raw)
  To: linux-omap, khilman, paul; +Cc: linux-arm-kernel

Some clockdomains bug out if their autodeps are deleted before idle.
This happens namely with OMAP3 PER domain, it will bug out if it
doesn't have wakedeps enabled when it enters off-mode. This patch
adds support for new flag 'CLKDM_NO_AUTODEP_DISABLE' which does this.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 arch/arm/mach-omap2/clockdomain.c |    3 +++
 arch/arm/mach-omap2/clockdomain.h |    4 ++++
 2 files changed, 7 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c
index 7715353..4f01c8f 100644
--- a/arch/arm/mach-omap2/clockdomain.c
+++ b/arch/arm/mach-omap2/clockdomain.c
@@ -201,6 +201,9 @@ void _clkdm_del_autodeps(struct clockdomain *clkdm)
 	if (!autodeps || clkdm->flags & CLKDM_NO_AUTODEPS)
 		return;
 
+	if (clkdm->flags & CLKDM_NO_AUTODEP_DISABLE)
+		return;
+
 	for (autodep = autodeps; autodep->clkdm.ptr; autodep++) {
 		if (IS_ERR(autodep->clkdm.ptr))
 			continue;
diff --git a/arch/arm/mach-omap2/clockdomain.h b/arch/arm/mach-omap2/clockdomain.h
index 5601dc1..9b8733e 100644
--- a/arch/arm/mach-omap2/clockdomain.h
+++ b/arch/arm/mach-omap2/clockdomain.h
@@ -34,6 +34,9 @@
  * CLKDM_ACTIVE_WITH_MPU: The PRCM guarantees that this clockdomain is
  *     active whenever the MPU is active.  True for interconnects and
  *     the WKUP clockdomains.
+ * CLKDM_NO_AUTODEP_DISABLE: Prevent clockdomain code from deleting autodeps.
+ *     Needed for PER domain on omap3, as it will bug out with off-mode if
+ *     wakedeps are removed.
  */
 #define CLKDM_CAN_FORCE_SLEEP			(1 << 0)
 #define CLKDM_CAN_FORCE_WAKEUP			(1 << 1)
@@ -41,6 +44,7 @@
 #define CLKDM_CAN_DISABLE_AUTO			(1 << 3)
 #define CLKDM_NO_AUTODEPS			(1 << 4)
 #define CLKDM_ACTIVE_WITH_MPU			(1 << 5)
+#define CLKDM_NO_AUTODEP_DISABLE		(1 << 6)
 
 #define CLKDM_CAN_HWSUP		(CLKDM_CAN_ENABLE_AUTO | CLKDM_CAN_DISABLE_AUTO)
 #define CLKDM_CAN_SWSUP		(CLKDM_CAN_FORCE_SLEEP | CLKDM_CAN_FORCE_WAKEUP)
-- 
1.7.4.1


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

* [PATCHv6 06/11] ARM: OMAP: clockdomain: add support for preventing autodep delete
@ 2012-09-25 16:05   ` Tero Kristo
  0 siblings, 0 replies; 30+ messages in thread
From: Tero Kristo @ 2012-09-25 16:05 UTC (permalink / raw)
  To: linux-arm-kernel

Some clockdomains bug out if their autodeps are deleted before idle.
This happens namely with OMAP3 PER domain, it will bug out if it
doesn't have wakedeps enabled when it enters off-mode. This patch
adds support for new flag 'CLKDM_NO_AUTODEP_DISABLE' which does this.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 arch/arm/mach-omap2/clockdomain.c |    3 +++
 arch/arm/mach-omap2/clockdomain.h |    4 ++++
 2 files changed, 7 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c
index 7715353..4f01c8f 100644
--- a/arch/arm/mach-omap2/clockdomain.c
+++ b/arch/arm/mach-omap2/clockdomain.c
@@ -201,6 +201,9 @@ void _clkdm_del_autodeps(struct clockdomain *clkdm)
 	if (!autodeps || clkdm->flags & CLKDM_NO_AUTODEPS)
 		return;
 
+	if (clkdm->flags & CLKDM_NO_AUTODEP_DISABLE)
+		return;
+
 	for (autodep = autodeps; autodep->clkdm.ptr; autodep++) {
 		if (IS_ERR(autodep->clkdm.ptr))
 			continue;
diff --git a/arch/arm/mach-omap2/clockdomain.h b/arch/arm/mach-omap2/clockdomain.h
index 5601dc1..9b8733e 100644
--- a/arch/arm/mach-omap2/clockdomain.h
+++ b/arch/arm/mach-omap2/clockdomain.h
@@ -34,6 +34,9 @@
  * CLKDM_ACTIVE_WITH_MPU: The PRCM guarantees that this clockdomain is
  *     active whenever the MPU is active.  True for interconnects and
  *     the WKUP clockdomains.
+ * CLKDM_NO_AUTODEP_DISABLE: Prevent clockdomain code from deleting autodeps.
+ *     Needed for PER domain on omap3, as it will bug out with off-mode if
+ *     wakedeps are removed.
  */
 #define CLKDM_CAN_FORCE_SLEEP			(1 << 0)
 #define CLKDM_CAN_FORCE_WAKEUP			(1 << 1)
@@ -41,6 +44,7 @@
 #define CLKDM_CAN_DISABLE_AUTO			(1 << 3)
 #define CLKDM_NO_AUTODEPS			(1 << 4)
 #define CLKDM_ACTIVE_WITH_MPU			(1 << 5)
+#define CLKDM_NO_AUTODEP_DISABLE		(1 << 6)
 
 #define CLKDM_CAN_HWSUP		(CLKDM_CAN_ENABLE_AUTO | CLKDM_CAN_DISABLE_AUTO)
 #define CLKDM_CAN_SWSUP		(CLKDM_CAN_FORCE_SLEEP | CLKDM_CAN_FORCE_WAKEUP)
-- 
1.7.4.1

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

* [PATCHv6 07/11] ARM: OMAP3: do not delete per_clkdm autodeps during idle
  2012-09-25 16:05 ` Tero Kristo
@ 2012-09-25 16:05   ` Tero Kristo
  -1 siblings, 0 replies; 30+ messages in thread
From: Tero Kristo @ 2012-09-25 16:05 UTC (permalink / raw)
  To: linux-omap, khilman, paul; +Cc: linux-arm-kernel

Previously, PER clock domain was always enabled, as the usecounts
for this domain incorrectly always showed positive value. On HW
level though, the domain enters idle as it is set in HW supervised
mode. Now, when the usecounts reflect real values, PER domain
will be put to HWSUP sleep mode, which means its autodeps are deleted.
Removing wakedeps for PER domain will cause multiple problems.
First of all, coming back from idle, PER domain remains idle as the
wakedeps have been disabled for the domain, and this causes a crash
with the GPIO code, as the resume code attempts to access domain
which is not active. Just enabling the interface clocks for the GPIO
does not help, as they are autoidled and don't bring the domain out
of idle. Secondly, there are multiple erratas for omap3, which say
that the wakedeps should be enabled for the PER domain, see e.g.
errata i582 for omap3630.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 arch/arm/mach-omap2/clockdomains3xxx_data.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-omap2/clockdomains3xxx_data.c b/arch/arm/mach-omap2/clockdomains3xxx_data.c
index 56089c4..3b3c524 100644
--- a/arch/arm/mach-omap2/clockdomains3xxx_data.c
+++ b/arch/arm/mach-omap2/clockdomains3xxx_data.c
@@ -370,7 +370,7 @@ static struct clockdomain usbhost_am35x_clkdm = {
 static struct clockdomain per_clkdm = {
 	.name		= "per_clkdm",
 	.pwrdm		= { .name = "per_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP_SWSUP,
+	.flags		= CLKDM_CAN_HWSUP_SWSUP | CLKDM_NO_AUTODEP_DISABLE,
 	.dep_bit	= OMAP3430_EN_PER_SHIFT,
 	.wkdep_srcs	= per_wkdeps,
 	.sleepdep_srcs	= per_sleepdeps,
-- 
1.7.4.1


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

* [PATCHv6 07/11] ARM: OMAP3: do not delete per_clkdm autodeps during idle
@ 2012-09-25 16:05   ` Tero Kristo
  0 siblings, 0 replies; 30+ messages in thread
From: Tero Kristo @ 2012-09-25 16:05 UTC (permalink / raw)
  To: linux-arm-kernel

Previously, PER clock domain was always enabled, as the usecounts
for this domain incorrectly always showed positive value. On HW
level though, the domain enters idle as it is set in HW supervised
mode. Now, when the usecounts reflect real values, PER domain
will be put to HWSUP sleep mode, which means its autodeps are deleted.
Removing wakedeps for PER domain will cause multiple problems.
First of all, coming back from idle, PER domain remains idle as the
wakedeps have been disabled for the domain, and this causes a crash
with the GPIO code, as the resume code attempts to access domain
which is not active. Just enabling the interface clocks for the GPIO
does not help, as they are autoidled and don't bring the domain out
of idle. Secondly, there are multiple erratas for omap3, which say
that the wakedeps should be enabled for the PER domain, see e.g.
errata i582 for omap3630.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 arch/arm/mach-omap2/clockdomains3xxx_data.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-omap2/clockdomains3xxx_data.c b/arch/arm/mach-omap2/clockdomains3xxx_data.c
index 56089c4..3b3c524 100644
--- a/arch/arm/mach-omap2/clockdomains3xxx_data.c
+++ b/arch/arm/mach-omap2/clockdomains3xxx_data.c
@@ -370,7 +370,7 @@ static struct clockdomain usbhost_am35x_clkdm = {
 static struct clockdomain per_clkdm = {
 	.name		= "per_clkdm",
 	.pwrdm		= { .name = "per_pwrdm" },
-	.flags		= CLKDM_CAN_HWSUP_SWSUP,
+	.flags		= CLKDM_CAN_HWSUP_SWSUP | CLKDM_NO_AUTODEP_DISABLE,
 	.dep_bit	= OMAP3430_EN_PER_SHIFT,
 	.wkdep_srcs	= per_wkdeps,
 	.sleepdep_srcs	= per_sleepdeps,
-- 
1.7.4.1

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

* [PATCHv6 08/11] ARM: OMAP4: clock data: set autoidle flag for dss_fck
  2012-09-25 16:05 ` Tero Kristo
@ 2012-09-25 16:05   ` Tero Kristo
  -1 siblings, 0 replies; 30+ messages in thread
From: Tero Kristo @ 2012-09-25 16:05 UTC (permalink / raw)
  To: linux-omap, khilman, paul; +Cc: linux-arm-kernel

dss_fck is currently being used improperly within the hwmod database
as an interface clock for DSS hwmods. This causes the dss_fck to
be enabled even if the dss powerdomain itself is idle, resulting
in wrong data within the powerdomain usecounts. Marked dss_fck as
autoidle which makes the clock to disappear from usecounts for now.
This patch can be reverted once the interface clocks for DSS hwmods
have been properly fixed.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 arch/arm/mach-omap2/clock44xx_data.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c
index d7f55e4..95834d7 100644
--- a/arch/arm/mach-omap2/clock44xx_data.c
+++ b/arch/arm/mach-omap2/clock44xx_data.c
@@ -1408,6 +1408,7 @@ static struct clk dss_fck = {
 	.clkdm_name	= "l3_dss_clkdm",
 	.parent		= &l3_div_ck,
 	.recalc		= &followparent_recalc,
+	.autoidle	= true,
 };
 
 static struct clk efuse_ctrl_cust_fck = {
-- 
1.7.4.1


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

* [PATCHv6 08/11] ARM: OMAP4: clock data: set autoidle flag for dss_fck
@ 2012-09-25 16:05   ` Tero Kristo
  0 siblings, 0 replies; 30+ messages in thread
From: Tero Kristo @ 2012-09-25 16:05 UTC (permalink / raw)
  To: linux-arm-kernel

dss_fck is currently being used improperly within the hwmod database
as an interface clock for DSS hwmods. This causes the dss_fck to
be enabled even if the dss powerdomain itself is idle, resulting
in wrong data within the powerdomain usecounts. Marked dss_fck as
autoidle which makes the clock to disappear from usecounts for now.
This patch can be reverted once the interface clocks for DSS hwmods
have been properly fixed.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 arch/arm/mach-omap2/clock44xx_data.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c
index d7f55e4..95834d7 100644
--- a/arch/arm/mach-omap2/clock44xx_data.c
+++ b/arch/arm/mach-omap2/clock44xx_data.c
@@ -1408,6 +1408,7 @@ static struct clk dss_fck = {
 	.clkdm_name	= "l3_dss_clkdm",
 	.parent		= &l3_div_ck,
 	.recalc		= &followparent_recalc,
+	.autoidle	= true,
 };
 
 static struct clk efuse_ctrl_cust_fck = {
-- 
1.7.4.1

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

* [PATCHv6 09/11] ARM: OMAP4: hwmod: add support for hwmod autoidle flag
  2012-09-25 16:05 ` Tero Kristo
@ 2012-09-25 16:05   ` Tero Kristo
  -1 siblings, 0 replies; 30+ messages in thread
From: Tero Kristo @ 2012-09-25 16:05 UTC (permalink / raw)
  To: linux-omap, khilman, paul; +Cc: linux-arm-kernel

If a hwmod is in HWAUTO mode, it will idle automatically and should not
be accounted for in the clkdm / pwrdm usecounts. Thus, flag modules in
such mode as autoidle during init, and ignore these in subsequent
usecount calculations.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 arch/arm/mach-omap2/clockdomain.c            |    6 ++++++
 arch/arm/mach-omap2/omap_hwmod.c             |    3 +++
 arch/arm/plat-omap/include/plat/omap_hwmod.h |    2 ++
 3 files changed, 11 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c
index 4f01c8f..af88ae5 100644
--- a/arch/arm/mach-omap2/clockdomain.c
+++ b/arch/arm/mach-omap2/clockdomain.c
@@ -1063,6 +1063,9 @@ int clkdm_hwmod_enable(struct clockdomain *clkdm, struct omap_hwmod *oh)
 	if (!oh)
 		return -EINVAL;
 
+	if (oh->flags & HWMOD_AUTOIDLE)
+		return 0;
+
 	return _clkdm_clk_hwmod_enable(clkdm);
 }
 
@@ -1094,6 +1097,9 @@ int clkdm_hwmod_disable(struct clockdomain *clkdm, struct omap_hwmod *oh)
 	if (!oh)
 		return -EINVAL;
 
+	if (oh->flags & HWMOD_AUTOIDLE)
+		return 0;
+
 	return _clkdm_clk_hwmod_disable(clkdm);
 }
 
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index f826917..6807b02 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -2377,6 +2377,9 @@ static int __init _register(struct omap_hwmod *oh)
 	INIT_LIST_HEAD(&oh->slave_ports);
 	spin_lock_init(&oh->_lock);
 
+	if (cpu_is_omap44xx() && oh->prcm.omap4.modulemode == MODULEMODE_HWCTRL)
+		oh->flags |= HWMOD_AUTOIDLE;
+
 	oh->_state = _HWMOD_STATE_REGISTERED;
 
 	/*
diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h
index 0f840a9..36130f9 100644
--- a/arch/arm/plat-omap/include/plat/omap_hwmod.h
+++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h
@@ -440,6 +440,7 @@ struct omap_hwmod_omap4_prcm {
  *     in order to complete the reset. Optional clocks will be disabled
  *     again after the reset.
  * HWMOD_16BIT_REG: Module has 16bit registers
+ * HWMOD_AUTOIDLE: Module is controlled automatically by hardware
  */
 #define HWMOD_SWSUP_SIDLE			(1 << 0)
 #define HWMOD_SWSUP_MSTANDBY			(1 << 1)
@@ -450,6 +451,7 @@ struct omap_hwmod_omap4_prcm {
 #define HWMOD_NO_IDLEST				(1 << 6)
 #define HWMOD_CONTROL_OPT_CLKS_IN_RESET		(1 << 7)
 #define HWMOD_16BIT_REG				(1 << 8)
+#define HWMOD_AUTOIDLE				(1 << 9)
 
 /*
  * omap_hwmod._int_flags definitions
-- 
1.7.4.1


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

* [PATCHv6 09/11] ARM: OMAP4: hwmod: add support for hwmod autoidle flag
@ 2012-09-25 16:05   ` Tero Kristo
  0 siblings, 0 replies; 30+ messages in thread
From: Tero Kristo @ 2012-09-25 16:05 UTC (permalink / raw)
  To: linux-arm-kernel

If a hwmod is in HWAUTO mode, it will idle automatically and should not
be accounted for in the clkdm / pwrdm usecounts. Thus, flag modules in
such mode as autoidle during init, and ignore these in subsequent
usecount calculations.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 arch/arm/mach-omap2/clockdomain.c            |    6 ++++++
 arch/arm/mach-omap2/omap_hwmod.c             |    3 +++
 arch/arm/plat-omap/include/plat/omap_hwmod.h |    2 ++
 3 files changed, 11 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c
index 4f01c8f..af88ae5 100644
--- a/arch/arm/mach-omap2/clockdomain.c
+++ b/arch/arm/mach-omap2/clockdomain.c
@@ -1063,6 +1063,9 @@ int clkdm_hwmod_enable(struct clockdomain *clkdm, struct omap_hwmod *oh)
 	if (!oh)
 		return -EINVAL;
 
+	if (oh->flags & HWMOD_AUTOIDLE)
+		return 0;
+
 	return _clkdm_clk_hwmod_enable(clkdm);
 }
 
@@ -1094,6 +1097,9 @@ int clkdm_hwmod_disable(struct clockdomain *clkdm, struct omap_hwmod *oh)
 	if (!oh)
 		return -EINVAL;
 
+	if (oh->flags & HWMOD_AUTOIDLE)
+		return 0;
+
 	return _clkdm_clk_hwmod_disable(clkdm);
 }
 
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index f826917..6807b02 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -2377,6 +2377,9 @@ static int __init _register(struct omap_hwmod *oh)
 	INIT_LIST_HEAD(&oh->slave_ports);
 	spin_lock_init(&oh->_lock);
 
+	if (cpu_is_omap44xx() && oh->prcm.omap4.modulemode == MODULEMODE_HWCTRL)
+		oh->flags |= HWMOD_AUTOIDLE;
+
 	oh->_state = _HWMOD_STATE_REGISTERED;
 
 	/*
diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h
index 0f840a9..36130f9 100644
--- a/arch/arm/plat-omap/include/plat/omap_hwmod.h
+++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h
@@ -440,6 +440,7 @@ struct omap_hwmod_omap4_prcm {
  *     in order to complete the reset. Optional clocks will be disabled
  *     again after the reset.
  * HWMOD_16BIT_REG: Module has 16bit registers
+ * HWMOD_AUTOIDLE: Module is controlled automatically by hardware
  */
 #define HWMOD_SWSUP_SIDLE			(1 << 0)
 #define HWMOD_SWSUP_MSTANDBY			(1 << 1)
@@ -450,6 +451,7 @@ struct omap_hwmod_omap4_prcm {
 #define HWMOD_NO_IDLEST				(1 << 6)
 #define HWMOD_CONTROL_OPT_CLKS_IN_RESET		(1 << 7)
 #define HWMOD_16BIT_REG				(1 << 8)
+#define HWMOD_AUTOIDLE				(1 << 9)
 
 /*
  * omap_hwmod._int_flags definitions
-- 
1.7.4.1

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

* [PATCHv6 10/11] ARM: OMAP4: hwmod data: set mpu hwmod modulemode to hwauto
  2012-09-25 16:05 ` Tero Kristo
@ 2012-09-25 16:05   ` Tero Kristo
  -1 siblings, 0 replies; 30+ messages in thread
From: Tero Kristo @ 2012-09-25 16:05 UTC (permalink / raw)
  To: linux-omap, khilman, paul; +Cc: linux-arm-kernel

This makes sure it is handled as autoidle type by the usecounting.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 arch/arm/mach-omap2/omap_hwmod_44xx_data.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index 2d13b33..367de25 100644
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -2492,6 +2492,7 @@ static struct omap_hwmod omap44xx_mpu_hwmod = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM_MPU_MPU_CLKCTRL_OFFSET,
 			.context_offs = OMAP4_RM_MPU_MPU_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_HWCTRL,
 		},
 	},
 };
-- 
1.7.4.1


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

* [PATCHv6 10/11] ARM: OMAP4: hwmod data: set mpu hwmod modulemode to hwauto
@ 2012-09-25 16:05   ` Tero Kristo
  0 siblings, 0 replies; 30+ messages in thread
From: Tero Kristo @ 2012-09-25 16:05 UTC (permalink / raw)
  To: linux-arm-kernel

This makes sure it is handled as autoidle type by the usecounting.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 arch/arm/mach-omap2/omap_hwmod_44xx_data.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index 2d13b33..367de25 100644
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -2492,6 +2492,7 @@ static struct omap_hwmod omap44xx_mpu_hwmod = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM_MPU_MPU_CLKCTRL_OFFSET,
 			.context_offs = OMAP4_RM_MPU_MPU_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_HWCTRL,
 		},
 	},
 };
-- 
1.7.4.1

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

* [PATCHv6 11/11] ARM: OMAP4: clock data: flag hw controlled clocks as autoidle
  2012-09-25 16:05 ` Tero Kristo
@ 2012-09-25 16:05   ` Tero Kristo
  -1 siblings, 0 replies; 30+ messages in thread
From: Tero Kristo @ 2012-09-25 16:05 UTC (permalink / raw)
  To: linux-omap, khilman, paul; +Cc: linux-arm-kernel

This makes sure these clocks are ignored by the clkdm / pwrdm usecounting.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 arch/arm/mach-omap2/clock44xx_data.c |    5 ++++-
 1 files changed, 4 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c
index 95834d7..d2fb4e8 100644
--- a/arch/arm/mach-omap2/clock44xx_data.c
+++ b/arch/arm/mach-omap2/clock44xx_data.c
@@ -3356,8 +3356,11 @@ int __init omap4xxx_clk_init(void)
 	 */
 
 	for (c = omap44xx_clks; c < omap44xx_clks + ARRAY_SIZE(omap44xx_clks);
-									  c++)
+									  c++) {
+		if (c->lk.clk->enable_bit == OMAP4430_MODULEMODE_HWCTRL)
+			c->lk.clk->autoidle = true;
 		clk_preinit(c->lk.clk);
+	}
 
 	for (c = omap44xx_clks; c < omap44xx_clks + ARRAY_SIZE(omap44xx_clks);
 									  c++)
-- 
1.7.4.1


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

* [PATCHv6 11/11] ARM: OMAP4: clock data: flag hw controlled clocks as autoidle
@ 2012-09-25 16:05   ` Tero Kristo
  0 siblings, 0 replies; 30+ messages in thread
From: Tero Kristo @ 2012-09-25 16:05 UTC (permalink / raw)
  To: linux-arm-kernel

This makes sure these clocks are ignored by the clkdm / pwrdm usecounting.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 arch/arm/mach-omap2/clock44xx_data.c |    5 ++++-
 1 files changed, 4 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c
index 95834d7..d2fb4e8 100644
--- a/arch/arm/mach-omap2/clock44xx_data.c
+++ b/arch/arm/mach-omap2/clock44xx_data.c
@@ -3356,8 +3356,11 @@ int __init omap4xxx_clk_init(void)
 	 */
 
 	for (c = omap44xx_clks; c < omap44xx_clks + ARRAY_SIZE(omap44xx_clks);
-									  c++)
+									  c++) {
+		if (c->lk.clk->enable_bit == OMAP4430_MODULEMODE_HWCTRL)
+			c->lk.clk->autoidle = true;
 		clk_preinit(c->lk.clk);
+	}
 
 	for (c = omap44xx_clks; c < omap44xx_clks + ARRAY_SIZE(omap44xx_clks);
 									  c++)
-- 
1.7.4.1

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

* Re: [PATCHv6 01/11] ARM: OMAP: clockdomain: Fix locking on _clkdm_clk_hwmod_enable / disable
  2012-09-25 16:05   ` Tero Kristo
@ 2012-10-16  5:45     ` Paul Walmsley
  -1 siblings, 0 replies; 30+ messages in thread
From: Paul Walmsley @ 2012-10-16  5:45 UTC (permalink / raw)
  To: Tero Kristo; +Cc: linux-omap, khilman, linux-arm-kernel

On Tue, 25 Sep 2012, Tero Kristo wrote:

> Previously the code only acquired spinlock after increasing / decreasing
> the usecount value, which is wrong. This leaves a small window where
> a task switch may occur between the check of the usecount and the actual
> wakeup / sleep of the domain. Fixed by moving the spinlock locking before
> the usecount access. Left the usecount as atomic_t if someone wants an
> easy access to the parameter through atomic_read.
> 
> Signed-off-by: Tero Kristo <t-kristo@ti.com>

Thanks, queued for 3.7-rc fixes.


- Paul

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

* [PATCHv6 01/11] ARM: OMAP: clockdomain: Fix locking on _clkdm_clk_hwmod_enable / disable
@ 2012-10-16  5:45     ` Paul Walmsley
  0 siblings, 0 replies; 30+ messages in thread
From: Paul Walmsley @ 2012-10-16  5:45 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, 25 Sep 2012, Tero Kristo wrote:

> Previously the code only acquired spinlock after increasing / decreasing
> the usecount value, which is wrong. This leaves a small window where
> a task switch may occur between the check of the usecount and the actual
> wakeup / sleep of the domain. Fixed by moving the spinlock locking before
> the usecount access. Left the usecount as atomic_t if someone wants an
> easy access to the parameter through atomic_read.
> 
> Signed-off-by: Tero Kristo <t-kristo@ti.com>

Thanks, queued for 3.7-rc fixes.


- Paul

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

* Re: [PATCHv6 01/11] ARM: OMAP: clockdomain: Fix locking on _clkdm_clk_hwmod_enable / disable
  2012-09-25 16:05   ` Tero Kristo
@ 2012-10-17  2:25     ` Paul Walmsley
  -1 siblings, 0 replies; 30+ messages in thread
From: Paul Walmsley @ 2012-10-17  2:25 UTC (permalink / raw)
  To: Tero Kristo; +Cc: linux-omap, khilman, linux-arm-kernel, tony

On Tue, 25 Sep 2012, Tero Kristo wrote:

> Previously the code only acquired spinlock after increasing / decreasing
> the usecount value, which is wrong. This leaves a small window where
> a task switch may occur between the check of the usecount and the actual
> wakeup / sleep of the domain. Fixed by moving the spinlock locking before
> the usecount access. Left the usecount as atomic_t if someone wants an
> easy access to the parameter through atomic_read.
> 
> Signed-off-by: Tero Kristo <t-kristo@ti.com>

Acked-by: Paul Walmsley <paul@pwsan.com>

- Paul

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

* [PATCHv6 01/11] ARM: OMAP: clockdomain: Fix locking on _clkdm_clk_hwmod_enable / disable
@ 2012-10-17  2:25     ` Paul Walmsley
  0 siblings, 0 replies; 30+ messages in thread
From: Paul Walmsley @ 2012-10-17  2:25 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, 25 Sep 2012, Tero Kristo wrote:

> Previously the code only acquired spinlock after increasing / decreasing
> the usecount value, which is wrong. This leaves a small window where
> a task switch may occur between the check of the usecount and the actual
> wakeup / sleep of the domain. Fixed by moving the spinlock locking before
> the usecount access. Left the usecount as atomic_t if someone wants an
> easy access to the parameter through atomic_read.
> 
> Signed-off-by: Tero Kristo <t-kristo@ti.com>

Acked-by: Paul Walmsley <paul@pwsan.com>

- Paul

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

* Re: [PATCHv6 01/11] ARM: OMAP: clockdomain: Fix locking on _clkdm_clk_hwmod_enable / disable
  2012-10-17  2:25     ` Paul Walmsley
@ 2012-10-17  2:41       ` Tony Lindgren
  -1 siblings, 0 replies; 30+ messages in thread
From: Tony Lindgren @ 2012-10-17  2:41 UTC (permalink / raw)
  To: Paul Walmsley; +Cc: Tero Kristo, linux-omap, khilman, linux-arm-kernel

* Paul Walmsley <paul@pwsan.com> [121016 19:26]:
> On Tue, 25 Sep 2012, Tero Kristo wrote:
> 
> > Previously the code only acquired spinlock after increasing / decreasing
> > the usecount value, which is wrong. This leaves a small window where
> > a task switch may occur between the check of the usecount and the actual
> > wakeup / sleep of the domain. Fixed by moving the spinlock locking before
> > the usecount access. Left the usecount as atomic_t if someone wants an
> > easy access to the parameter through atomic_read.
> > 
> > Signed-off-by: Tero Kristo <t-kristo@ti.com>
> 
> Acked-by: Paul Walmsley <paul@pwsan.com>

OK I'll apply this into omap-for-v3.7-rc1/fixes-take4.

Regards,

Tony

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

* [PATCHv6 01/11] ARM: OMAP: clockdomain: Fix locking on _clkdm_clk_hwmod_enable / disable
@ 2012-10-17  2:41       ` Tony Lindgren
  0 siblings, 0 replies; 30+ messages in thread
From: Tony Lindgren @ 2012-10-17  2:41 UTC (permalink / raw)
  To: linux-arm-kernel

* Paul Walmsley <paul@pwsan.com> [121016 19:26]:
> On Tue, 25 Sep 2012, Tero Kristo wrote:
> 
> > Previously the code only acquired spinlock after increasing / decreasing
> > the usecount value, which is wrong. This leaves a small window where
> > a task switch may occur between the check of the usecount and the actual
> > wakeup / sleep of the domain. Fixed by moving the spinlock locking before
> > the usecount access. Left the usecount as atomic_t if someone wants an
> > easy access to the parameter through atomic_read.
> > 
> > Signed-off-by: Tero Kristo <t-kristo@ti.com>
> 
> Acked-by: Paul Walmsley <paul@pwsan.com>

OK I'll apply this into omap-for-v3.7-rc1/fixes-take4.

Regards,

Tony

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

end of thread, other threads:[~2012-10-17  2:41 UTC | newest]

Thread overview: 30+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-09-25 16:05 [PATCHv6 00/11]: ARM: OMAP: PM usecounting changes Tero Kristo
2012-09-25 16:05 ` Tero Kristo
2012-09-25 16:05 ` [PATCHv6 01/11] ARM: OMAP: clockdomain: Fix locking on _clkdm_clk_hwmod_enable / disable Tero Kristo
2012-09-25 16:05   ` Tero Kristo
2012-10-16  5:45   ` Paul Walmsley
2012-10-16  5:45     ` Paul Walmsley
2012-10-17  2:25   ` Paul Walmsley
2012-10-17  2:25     ` Paul Walmsley
2012-10-17  2:41     ` Tony Lindgren
2012-10-17  2:41       ` Tony Lindgren
2012-09-25 16:05 ` [PATCHv6 02/11] ARM: OMAP3+: voltage/pwrdm/clkdm/clock add recursive usecount tracking Tero Kristo
2012-09-25 16:05   ` Tero Kristo
2012-09-25 16:05 ` [PATCHv6 03/11] ARM: OMAP3+: voltage: add support for voltagedomain usecounts Tero Kristo
2012-09-25 16:05   ` Tero Kristo
2012-09-25 16:05 ` [PATCHv6 04/11] ARM: OMAP3: add manual control for mpu / core pwrdm usecounting Tero Kristo
2012-09-25 16:05   ` Tero Kristo
2012-09-25 16:05 ` [PATCHv6 05/11] ARM: OMAP3: set autoidle flag for sdrc_ick Tero Kristo
2012-09-25 16:05   ` Tero Kristo
2012-09-25 16:05 ` [PATCHv6 06/11] ARM: OMAP: clockdomain: add support for preventing autodep delete Tero Kristo
2012-09-25 16:05   ` Tero Kristo
2012-09-25 16:05 ` [PATCHv6 07/11] ARM: OMAP3: do not delete per_clkdm autodeps during idle Tero Kristo
2012-09-25 16:05   ` Tero Kristo
2012-09-25 16:05 ` [PATCHv6 08/11] ARM: OMAP4: clock data: set autoidle flag for dss_fck Tero Kristo
2012-09-25 16:05   ` Tero Kristo
2012-09-25 16:05 ` [PATCHv6 09/11] ARM: OMAP4: hwmod: add support for hwmod autoidle flag Tero Kristo
2012-09-25 16:05   ` Tero Kristo
2012-09-25 16:05 ` [PATCHv6 10/11] ARM: OMAP4: hwmod data: set mpu hwmod modulemode to hwauto Tero Kristo
2012-09-25 16:05   ` Tero Kristo
2012-09-25 16:05 ` [PATCHv6 11/11] ARM: OMAP4: clock data: flag hw controlled clocks as autoidle Tero Kristo
2012-09-25 16:05   ` Tero Kristo

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.