aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2/powerdomain.c
diff options
context:
space:
mode:
authorPaul Walmsley <paul@pwsan.com>2013-01-26 00:58:16 -0700
committerPaul Walmsley <paul@pwsan.com>2013-01-29 14:59:57 -0700
commit3a090284056954f382612da42ebe9f3147403ef5 (patch)
tree6e9627679444b04614577cf55ad77f8e17aed0b9 /arch/arm/mach-omap2/powerdomain.c
parentARM: OMAP2+: PM/powerdomain: move omap_set_pwrdm_state() to powerdomain code (diff)
downloadlinux-dev-3a090284056954f382612da42ebe9f3147403ef5.tar.xz
linux-dev-3a090284056954f382612da42ebe9f3147403ef5.zip
ARM: OMAP2+: powerdomain/clockdomain: add a per-powerdomain spinlock
Add a per-powerdomain spinlock. Use that instead of the clockdomain spinlock. Add pwrdm_lock()/pwrdm_unlock() functions to allow other code to acquire or release the powerdomain spinlock without reaching directly into the struct powerdomain. Signed-off-by: Paul Walmsley <paul@pwsan.com> Cc: Jean Pihet <jean.pihet@newoldbits.com>
Diffstat (limited to 'arch/arm/mach-omap2/powerdomain.c')
-rw-r--r--arch/arm/mach-omap2/powerdomain.c60
1 files changed, 52 insertions, 8 deletions
diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
index 65c34645c8ed..8e61d80bf6b3 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -19,6 +19,7 @@
#include <linux/list.h>
#include <linux/errno.h>
#include <linux/string.h>
+#include <linux/spinlock.h>
#include <trace/events/power.h>
#include "cm2xxx_3xxx.h"
@@ -111,6 +112,7 @@ static int _pwrdm_register(struct powerdomain *pwrdm)
pwrdm->voltdm.ptr = voltdm;
INIT_LIST_HEAD(&pwrdm->voltdm_node);
voltdm_add_pwrdm(voltdm, pwrdm);
+ spin_lock_init(&pwrdm->_lock);
list_add(&pwrdm->node, &pwrdm_list);
@@ -241,7 +243,7 @@ static u8 _pwrdm_save_clkdm_state_and_activate(struct powerdomain *pwrdm,
sleep_switch = LOWPOWERSTATE_SWITCH;
} else {
*hwsup = clkdm_in_hwsup(pwrdm->pwrdm_clkdms[0]);
- clkdm_wakeup(pwrdm->pwrdm_clkdms[0]);
+ clkdm_wakeup_nolock(pwrdm->pwrdm_clkdms[0]);
sleep_switch = FORCEWAKEUP_SWITCH;
}
} else {
@@ -271,15 +273,15 @@ static void _pwrdm_restore_clkdm_state(struct powerdomain *pwrdm,
switch (sleep_switch) {
case FORCEWAKEUP_SWITCH:
if (hwsup)
- clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]);
+ clkdm_allow_idle_nolock(pwrdm->pwrdm_clkdms[0]);
else
- clkdm_sleep(pwrdm->pwrdm_clkdms[0]);
+ clkdm_sleep_nolock(pwrdm->pwrdm_clkdms[0]);
break;
case LOWPOWERSTATE_SWITCH:
if (pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE &&
arch_pwrdm->pwrdm_set_lowpwrstchange)
arch_pwrdm->pwrdm_set_lowpwrstchange(pwrdm);
- pwrdm_state_switch(pwrdm);
+ pwrdm_state_switch_nolock(pwrdm);
break;
}
}
@@ -360,6 +362,30 @@ int pwrdm_complete_init(void)
}
/**
+ * pwrdm_lock - acquire a Linux spinlock on a powerdomain
+ * @pwrdm: struct powerdomain * to lock
+ *
+ * Acquire the powerdomain spinlock on @pwrdm. No return value.
+ */
+void pwrdm_lock(struct powerdomain *pwrdm)
+ __acquires(&pwrdm->_lock)
+{
+ spin_lock_irqsave(&pwrdm->_lock, pwrdm->_lock_flags);
+}
+
+/**
+ * pwrdm_unlock - release a Linux spinlock on a powerdomain
+ * @pwrdm: struct powerdomain * to unlock
+ *
+ * Release the powerdomain spinlock on @pwrdm. No return value.
+ */
+void pwrdm_unlock(struct powerdomain *pwrdm)
+ __releases(&pwrdm->_lock)
+{
+ spin_unlock_irqrestore(&pwrdm->_lock, pwrdm->_lock_flags);
+}
+
+/**
* pwrdm_lookup - look up a powerdomain by name, return a pointer
* @name: name of powerdomain
*
@@ -1005,7 +1031,7 @@ bool pwrdm_has_hdwr_sar(struct powerdomain *pwrdm)
return (pwrdm && pwrdm->flags & PWRDM_HAS_HDWR_SAR) ? 1 : 0;
}
-int pwrdm_state_switch(struct powerdomain *pwrdm)
+int pwrdm_state_switch_nolock(struct powerdomain *pwrdm)
{
int ret;
@@ -1019,6 +1045,17 @@ int pwrdm_state_switch(struct powerdomain *pwrdm)
return ret;
}
+int __deprecated pwrdm_state_switch(struct powerdomain *pwrdm)
+{
+ int ret;
+
+ pwrdm_lock(pwrdm);
+ ret = pwrdm_state_switch_nolock(pwrdm);
+ pwrdm_unlock(pwrdm);
+
+ return ret;
+}
+
int pwrdm_pre_transition(struct powerdomain *pwrdm)
{
if (pwrdm)
@@ -1067,15 +1104,19 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u8 pwrst)
pwrst--;
}
+ pwrdm_lock(pwrdm);
+
curr_pwrst = pwrdm_read_pwrst(pwrdm);
next_pwrst = pwrdm_read_next_pwrst(pwrdm);
if (curr_pwrst == pwrst && next_pwrst == pwrst)
- return ret;
+ goto osps_out;
sleep_switch = _pwrdm_save_clkdm_state_and_activate(pwrdm, curr_pwrst,
pwrst, &hwsup);
- if (sleep_switch == ERROR_SWITCH)
- return -EINVAL;
+ if (sleep_switch == ERROR_SWITCH) {
+ ret = -EINVAL;
+ goto osps_out;
+ }
ret = pwrdm_set_next_pwrst(pwrdm, pwrst);
if (ret)
@@ -1084,6 +1125,9 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u8 pwrst)
_pwrdm_restore_clkdm_state(pwrdm, sleep_switch, hwsup);
+osps_out:
+ pwrdm_unlock(pwrdm);
+
return ret;
}