From: Paul Walmsley <paul@pwsan.com>
To: linux-omap@vger.kernel.org, linux-arm-kernel@lists.infradead.org
Cc: Kevin Hilman <khilman@deeprootsystems.com>
Subject: [PATCH 07/12] ARM: OMAP2+: powerdomain: cache the powerdomain next power state
Date: Sun, 09 Dec 2012 13:03:26 -0700 [thread overview]
Message-ID: <20121209200325.3196.52729.stgit@dusk.lan> (raw)
In-Reply-To: <20121209200108.3196.12452.stgit@dusk.lan>
Cache the powerdomain next power state registers. The objective here
is to avoid unneeded reads and writes to the next power state
registers, which are slow compared to RAM & CPU cache.
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Cc: Kevin Hilman <khilman@deeprootsystems.com>
---
arch/arm/mach-omap2/powerdomain.c | 64 +++++++++++++++++--------------------
arch/arm/mach-omap2/powerdomain.h | 17 ++++++++++
2 files changed, 46 insertions(+), 35 deletions(-)
diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
index 62e2f75..425c868 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -376,7 +376,7 @@ static int _pwrdm_pwrst_to_fpwrst(struct powerdomain *pwrdm, u8 pwrst, u8 logic,
* software-controllable, returns 0; otherwise, passes along the
* return value from pwrdm_set_logic_retst() if there is an error
* returned by that function, otherwise, passes along the return value
- * from pwrdm_set_next_pwrst()
+ * from pwrdm_set_next_fpwrst()
*/
static int _set_logic_retst_and_pwrdm_pwrst(struct powerdomain *pwrdm,
u8 logic, u8 pwrst)
@@ -426,6 +426,9 @@ static int _pwrdm_read_next_fpwrst(struct powerdomain *pwrdm)
int next_pwrst, next_logic, ret;
u8 fpwrst;
+ if (pwrdm->_flags & _PWRDM_NEXT_FPWRST_IS_VALID)
+ return pwrdm->next_fpwrst;
+
next_pwrst = arch_pwrdm->pwrdm_read_next_pwrst(pwrdm);
if (next_pwrst < 0)
return next_pwrst;
@@ -438,6 +441,10 @@ static int _pwrdm_read_next_fpwrst(struct powerdomain *pwrdm)
return next_logic;
}
ret = _pwrdm_pwrst_to_fpwrst(pwrdm, next_pwrst, next_logic, &fpwrst);
+ if (!ret) {
+ pwrdm->next_fpwrst = fpwrst;
+ pwrdm->_flags |= _PWRDM_NEXT_FPWRST_IS_VALID;
+ }
return (ret) ? ret : fpwrst;
}
@@ -663,7 +670,7 @@ static int _pwrdm_pre_transition_cb(struct powerdomain *pwrdm, void *unused)
*/
static int _pwrdm_post_transition_cb(struct powerdomain *pwrdm, void *unused)
{
- int prev, next, fpwrst;
+ int prev, fpwrst;
int trace_state = 0;
prev = _pwrdm_read_prev_fpwrst(pwrdm);
@@ -676,10 +683,9 @@ static int _pwrdm_post_transition_cb(struct powerdomain *pwrdm, void *unused)
* If the power domain did not hit the desired state,
* generate a trace event with both the desired and hit states
*/
- next = _pwrdm_read_next_fpwrst(pwrdm);
- if (next != prev) {
- trace_state = (PWRDM_TRACE_STATES_FLAG | next << 8 |
- prev);
+ if (pwrdm->next_fpwrst != prev) {
+ trace_state = (PWRDM_TRACE_STATES_FLAG |
+ pwrdm->next_fpwrst << 8 | prev);
trace_power_domain_target(pwrdm->name, trace_state,
smp_processor_id());
}
@@ -1256,6 +1262,10 @@ int pwrdm_set_next_fpwrst(struct powerdomain *pwrdm, u8 fpwrst)
if (ret)
return ret;
+ if (pwrdm->_flags & _PWRDM_NEXT_FPWRST_IS_VALID &&
+ pwrdm->next_fpwrst == fpwrst)
+ return 0;
+
pr_debug("%s: set fpwrst %0x to pwrdm %s\n", __func__, fpwrst,
pwrdm->name);
@@ -1264,6 +1274,10 @@ int pwrdm_set_next_fpwrst(struct powerdomain *pwrdm, u8 fpwrst)
pwrdm_lock(pwrdm);
ret = _set_logic_retst_and_pwrdm_pwrst(pwrdm, logic, pwrst);
+ if (!ret) {
+ pwrdm->next_fpwrst = fpwrst;
+ pwrdm->_flags |= _PWRDM_NEXT_FPWRST_IS_VALID;
+ }
pwrdm_unlock(pwrdm);
return ret;
@@ -1279,36 +1293,16 @@ int pwrdm_set_next_fpwrst(struct powerdomain *pwrdm, u8 fpwrst)
*/
int pwrdm_read_next_fpwrst(struct powerdomain *pwrdm)
{
- int next_pwrst, next_logic, ret;
- u8 fpwrst;
+ int ret;
- if (!arch_pwrdm)
+ if (!pwrdm)
return -EINVAL;
pwrdm_lock(pwrdm);
-
- next_pwrst = arch_pwrdm->pwrdm_read_next_pwrst(pwrdm);
- if (next_pwrst < 0) {
- ret = next_pwrst;
- goto prnf_out;
- }
-
- next_logic = next_pwrst;
- if (_pwrdm_logic_retst_can_change(pwrdm) &&
- arch_pwrdm->pwrdm_read_logic_pwrst) {
- next_logic = arch_pwrdm->pwrdm_read_logic_pwrst(pwrdm);
- if (next_logic < 0) {
- ret = next_logic;
- goto prnf_out;
- }
- }
-
- ret = _pwrdm_pwrst_to_fpwrst(pwrdm, next_pwrst, next_logic, &fpwrst);
-
-prnf_out:
+ ret = _pwrdm_read_next_fpwrst(pwrdm);
pwrdm_unlock(pwrdm);
- return (ret) ? ret : fpwrst;
+ return ret;
}
/**
@@ -1344,10 +1338,6 @@ int pwrdm_set_fpwrst(struct powerdomain *pwrdm, enum pwrdm_func_state fpwrst)
pwrdm_lock(pwrdm);
- /*
- * XXX quite heavyweight for what this is intended to do; the
- * next fpwrst should simply be cached
- */
next_fpwrst = _pwrdm_read_next_fpwrst(pwrdm);
if (next_fpwrst == fpwrst)
goto psf_out;
@@ -1364,9 +1354,13 @@ int pwrdm_set_fpwrst(struct powerdomain *pwrdm, enum pwrdm_func_state fpwrst)
}
ret = _set_logic_retst_and_pwrdm_pwrst(pwrdm, logic, pwrst);
- if (ret)
+ if (ret) {
pr_err("%s: unable to set power state of powerdomain: %s\n",
__func__, pwrdm->name);
+ } else {
+ pwrdm->next_fpwrst = fpwrst;
+ pwrdm->_flags |= _PWRDM_NEXT_FPWRST_IS_VALID;
+ }
_pwrdm_restore_clkdm_state(pwrdm, sleep_switch, hwsup);
diff --git a/arch/arm/mach-omap2/powerdomain.h b/arch/arm/mach-omap2/powerdomain.h
index c19bdc3..1fb21f5 100644
--- a/arch/arm/mach-omap2/powerdomain.h
+++ b/arch/arm/mach-omap2/powerdomain.h
@@ -84,6 +84,16 @@ enum pwrdm_func_state {
#define PWRDM_HAS_LOWPOWERSTATECHANGE BIT(2)
/*
+ * Powerdomain internal flags (struct powerdomain._flags)
+ *
+ * _PWRDM_NEXT_FPWRST_IS_VALID: the locally-cached copy of the
+ * powerdomain's next-functional-power-state -- struct
+ * powerdomain.next_fpwrst -- is valid. If this bit is not set,
+ * the code needs to load the current value from the hardware.
+ */
+#define _PWRDM_NEXT_FPWRST_IS_VALID BIT(0)
+
+/*
* Number of memory banks that are power-controllable. On OMAP4430, the
* maximum is 5.
*/
@@ -127,12 +137,17 @@ struct powerdomain;
* in @pwrstctrl_offs
* @fpwrst: current func power state (set in pwrdm_state_switch() or post_trans)
* @fpwrst_counter: estimated number of times the pwrdm entered the power states
+ * @next_fpwrst: cache of the powerdomain's next-power-state
* @timer: sched_clock() timestamp of last pwrdm_state_switch()
* @fpwrst_timer: estimated nanoseconds of residency in the various power states
* @_lock: spinlock used to serialize powerdomain and some clockdomain ops
* @_lock_flags: stored flags when @_lock is taken
+ * @_flags: flags (for internal use only)
*
* @prcm_partition possible values are defined in mach-omap2/prcm44xx.h.
+ *
+ * Possible values for @_flags are documented above in the
+ * "Powerdomain internal flags (struct powerdomain._flags)" comments.
*/
struct powerdomain {
const char *name;
@@ -149,6 +164,8 @@ struct powerdomain {
const u8 pwrsts_mem_on[PWRDM_MAX_MEM_BANKS];
const u8 prcm_partition;
u8 fpwrst;
+ u8 next_fpwrst;
+ u8 _flags;
struct clockdomain *pwrdm_clkdms[PWRDM_MAX_CLKDMS];
struct list_head node;
struct list_head voltdm_node;
WARNING: multiple messages have this Message-ID (diff)
From: paul@pwsan.com (Paul Walmsley)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH 07/12] ARM: OMAP2+: powerdomain: cache the powerdomain next power state
Date: Sun, 09 Dec 2012 13:03:26 -0700 [thread overview]
Message-ID: <20121209200325.3196.52729.stgit@dusk.lan> (raw)
In-Reply-To: <20121209200108.3196.12452.stgit@dusk.lan>
Cache the powerdomain next power state registers. The objective here
is to avoid unneeded reads and writes to the next power state
registers, which are slow compared to RAM & CPU cache.
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Cc: Kevin Hilman <khilman@deeprootsystems.com>
---
arch/arm/mach-omap2/powerdomain.c | 64 +++++++++++++++++--------------------
arch/arm/mach-omap2/powerdomain.h | 17 ++++++++++
2 files changed, 46 insertions(+), 35 deletions(-)
diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
index 62e2f75..425c868 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -376,7 +376,7 @@ static int _pwrdm_pwrst_to_fpwrst(struct powerdomain *pwrdm, u8 pwrst, u8 logic,
* software-controllable, returns 0; otherwise, passes along the
* return value from pwrdm_set_logic_retst() if there is an error
* returned by that function, otherwise, passes along the return value
- * from pwrdm_set_next_pwrst()
+ * from pwrdm_set_next_fpwrst()
*/
static int _set_logic_retst_and_pwrdm_pwrst(struct powerdomain *pwrdm,
u8 logic, u8 pwrst)
@@ -426,6 +426,9 @@ static int _pwrdm_read_next_fpwrst(struct powerdomain *pwrdm)
int next_pwrst, next_logic, ret;
u8 fpwrst;
+ if (pwrdm->_flags & _PWRDM_NEXT_FPWRST_IS_VALID)
+ return pwrdm->next_fpwrst;
+
next_pwrst = arch_pwrdm->pwrdm_read_next_pwrst(pwrdm);
if (next_pwrst < 0)
return next_pwrst;
@@ -438,6 +441,10 @@ static int _pwrdm_read_next_fpwrst(struct powerdomain *pwrdm)
return next_logic;
}
ret = _pwrdm_pwrst_to_fpwrst(pwrdm, next_pwrst, next_logic, &fpwrst);
+ if (!ret) {
+ pwrdm->next_fpwrst = fpwrst;
+ pwrdm->_flags |= _PWRDM_NEXT_FPWRST_IS_VALID;
+ }
return (ret) ? ret : fpwrst;
}
@@ -663,7 +670,7 @@ static int _pwrdm_pre_transition_cb(struct powerdomain *pwrdm, void *unused)
*/
static int _pwrdm_post_transition_cb(struct powerdomain *pwrdm, void *unused)
{
- int prev, next, fpwrst;
+ int prev, fpwrst;
int trace_state = 0;
prev = _pwrdm_read_prev_fpwrst(pwrdm);
@@ -676,10 +683,9 @@ static int _pwrdm_post_transition_cb(struct powerdomain *pwrdm, void *unused)
* If the power domain did not hit the desired state,
* generate a trace event with both the desired and hit states
*/
- next = _pwrdm_read_next_fpwrst(pwrdm);
- if (next != prev) {
- trace_state = (PWRDM_TRACE_STATES_FLAG | next << 8 |
- prev);
+ if (pwrdm->next_fpwrst != prev) {
+ trace_state = (PWRDM_TRACE_STATES_FLAG |
+ pwrdm->next_fpwrst << 8 | prev);
trace_power_domain_target(pwrdm->name, trace_state,
smp_processor_id());
}
@@ -1256,6 +1262,10 @@ int pwrdm_set_next_fpwrst(struct powerdomain *pwrdm, u8 fpwrst)
if (ret)
return ret;
+ if (pwrdm->_flags & _PWRDM_NEXT_FPWRST_IS_VALID &&
+ pwrdm->next_fpwrst == fpwrst)
+ return 0;
+
pr_debug("%s: set fpwrst %0x to pwrdm %s\n", __func__, fpwrst,
pwrdm->name);
@@ -1264,6 +1274,10 @@ int pwrdm_set_next_fpwrst(struct powerdomain *pwrdm, u8 fpwrst)
pwrdm_lock(pwrdm);
ret = _set_logic_retst_and_pwrdm_pwrst(pwrdm, logic, pwrst);
+ if (!ret) {
+ pwrdm->next_fpwrst = fpwrst;
+ pwrdm->_flags |= _PWRDM_NEXT_FPWRST_IS_VALID;
+ }
pwrdm_unlock(pwrdm);
return ret;
@@ -1279,36 +1293,16 @@ int pwrdm_set_next_fpwrst(struct powerdomain *pwrdm, u8 fpwrst)
*/
int pwrdm_read_next_fpwrst(struct powerdomain *pwrdm)
{
- int next_pwrst, next_logic, ret;
- u8 fpwrst;
+ int ret;
- if (!arch_pwrdm)
+ if (!pwrdm)
return -EINVAL;
pwrdm_lock(pwrdm);
-
- next_pwrst = arch_pwrdm->pwrdm_read_next_pwrst(pwrdm);
- if (next_pwrst < 0) {
- ret = next_pwrst;
- goto prnf_out;
- }
-
- next_logic = next_pwrst;
- if (_pwrdm_logic_retst_can_change(pwrdm) &&
- arch_pwrdm->pwrdm_read_logic_pwrst) {
- next_logic = arch_pwrdm->pwrdm_read_logic_pwrst(pwrdm);
- if (next_logic < 0) {
- ret = next_logic;
- goto prnf_out;
- }
- }
-
- ret = _pwrdm_pwrst_to_fpwrst(pwrdm, next_pwrst, next_logic, &fpwrst);
-
-prnf_out:
+ ret = _pwrdm_read_next_fpwrst(pwrdm);
pwrdm_unlock(pwrdm);
- return (ret) ? ret : fpwrst;
+ return ret;
}
/**
@@ -1344,10 +1338,6 @@ int pwrdm_set_fpwrst(struct powerdomain *pwrdm, enum pwrdm_func_state fpwrst)
pwrdm_lock(pwrdm);
- /*
- * XXX quite heavyweight for what this is intended to do; the
- * next fpwrst should simply be cached
- */
next_fpwrst = _pwrdm_read_next_fpwrst(pwrdm);
if (next_fpwrst == fpwrst)
goto psf_out;
@@ -1364,9 +1354,13 @@ int pwrdm_set_fpwrst(struct powerdomain *pwrdm, enum pwrdm_func_state fpwrst)
}
ret = _set_logic_retst_and_pwrdm_pwrst(pwrdm, logic, pwrst);
- if (ret)
+ if (ret) {
pr_err("%s: unable to set power state of powerdomain: %s\n",
__func__, pwrdm->name);
+ } else {
+ pwrdm->next_fpwrst = fpwrst;
+ pwrdm->_flags |= _PWRDM_NEXT_FPWRST_IS_VALID;
+ }
_pwrdm_restore_clkdm_state(pwrdm, sleep_switch, hwsup);
diff --git a/arch/arm/mach-omap2/powerdomain.h b/arch/arm/mach-omap2/powerdomain.h
index c19bdc3..1fb21f5 100644
--- a/arch/arm/mach-omap2/powerdomain.h
+++ b/arch/arm/mach-omap2/powerdomain.h
@@ -84,6 +84,16 @@ enum pwrdm_func_state {
#define PWRDM_HAS_LOWPOWERSTATECHANGE BIT(2)
/*
+ * Powerdomain internal flags (struct powerdomain._flags)
+ *
+ * _PWRDM_NEXT_FPWRST_IS_VALID: the locally-cached copy of the
+ * powerdomain's next-functional-power-state -- struct
+ * powerdomain.next_fpwrst -- is valid. If this bit is not set,
+ * the code needs to load the current value from the hardware.
+ */
+#define _PWRDM_NEXT_FPWRST_IS_VALID BIT(0)
+
+/*
* Number of memory banks that are power-controllable. On OMAP4430, the
* maximum is 5.
*/
@@ -127,12 +137,17 @@ struct powerdomain;
* in @pwrstctrl_offs
* @fpwrst: current func power state (set in pwrdm_state_switch() or post_trans)
* @fpwrst_counter: estimated number of times the pwrdm entered the power states
+ * @next_fpwrst: cache of the powerdomain's next-power-state
* @timer: sched_clock() timestamp of last pwrdm_state_switch()
* @fpwrst_timer: estimated nanoseconds of residency in the various power states
* @_lock: spinlock used to serialize powerdomain and some clockdomain ops
* @_lock_flags: stored flags when @_lock is taken
+ * @_flags: flags (for internal use only)
*
* @prcm_partition possible values are defined in mach-omap2/prcm44xx.h.
+ *
+ * Possible values for @_flags are documented above in the
+ * "Powerdomain internal flags (struct powerdomain._flags)" comments.
*/
struct powerdomain {
const char *name;
@@ -149,6 +164,8 @@ struct powerdomain {
const u8 pwrsts_mem_on[PWRDM_MAX_MEM_BANKS];
const u8 prcm_partition;
u8 fpwrst;
+ u8 next_fpwrst;
+ u8 _flags;
struct clockdomain *pwrdm_clkdms[PWRDM_MAX_CLKDMS];
struct list_head node;
struct list_head voltdm_node;
next prev parent reply other threads:[~2012-12-09 20:05 UTC|newest]
Thread overview: 41+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-12-09 20:02 [PATCH 00/12] ARM: OMAP2+: powerdomain updates after the functional power state conversion Paul Walmsley
2012-12-09 20:02 ` Paul Walmsley
2012-12-09 20:02 ` [PATCH 01/12] ARM: OMAP2+: powerdomain: consolidate arch_pwrdm check code Paul Walmsley
2012-12-09 20:02 ` Paul Walmsley
2012-12-09 20:03 ` [PATCH 02/12] ARM: OMAP2+: PM/powerdomain: move the power state time tracking into the powerdomain code Paul Walmsley
2012-12-09 20:03 ` Paul Walmsley
2012-12-09 20:03 ` [PATCH 03/12] ARM: OMAP2+: powerdomain: split pwrdm_state_switch() Paul Walmsley
2012-12-09 20:03 ` Paul Walmsley
2012-12-09 20:03 ` [PATCH 04/12] ARM: OMAP2+: PM: clean up some debugfs functions Paul Walmsley
2012-12-09 20:03 ` Paul Walmsley
2012-12-09 20:03 ` [PATCH 05/12] ARM: OMAP2+: powerdomain: remove some redundant checks; add some notes Paul Walmsley
2012-12-09 20:03 ` [PATCH 06/12] ARM: OMAP2+: CM: use the cached copy of the clockdomain's hwsup state Paul Walmsley
2012-12-09 20:03 ` Paul Walmsley
2012-12-09 20:03 ` Paul Walmsley [this message]
2012-12-09 20:03 ` [PATCH 07/12] ARM: OMAP2+: powerdomain: cache the powerdomain next power state Paul Walmsley
2012-12-09 20:03 ` [PATCH 08/12] ARM: OMAP2+: powerdomain: cache the powerdomain's previous " Paul Walmsley
2012-12-09 20:03 ` Paul Walmsley
2012-12-09 20:03 ` [PATCH 09/12] ARM: OMAP2+: powerdomain: skip register reads for powerdomains known to be on Paul Walmsley
2012-12-09 20:03 ` Paul Walmsley
2012-12-12 10:22 ` Vaibhav Hiremath
2012-12-12 10:22 ` Vaibhav Hiremath
2012-12-19 21:09 ` Jon Hunter
2012-12-19 21:09 ` Jon Hunter
2012-12-20 17:22 ` Paul Walmsley
2012-12-20 17:22 ` Paul Walmsley
2012-12-21 6:33 ` Santosh Shilimkar
2012-12-21 6:33 ` Santosh Shilimkar
2012-12-26 6:21 ` Bedia, Vaibhav
2012-12-26 6:21 ` Bedia, Vaibhav
2012-12-26 6:31 ` Bedia, Vaibhav
2012-12-26 6:31 ` Bedia, Vaibhav
2012-12-26 20:49 ` Paul Walmsley
2012-12-26 20:49 ` Paul Walmsley
2012-12-09 20:03 ` [PATCH 10/12] ARM: OMAP2+: powerdomain: skip previous-power-state read if next_pwrst is ON Paul Walmsley
2012-12-09 20:03 ` Paul Walmsley
2012-12-09 20:03 ` [PATCH 11/12] ARM: OMAP2xxx: powerdomain: add previous power state tracking Paul Walmsley
2012-12-09 20:03 ` Paul Walmsley
2012-12-09 20:03 ` [PATCH 12/12] ARM: OMAP2xxx: PM: add pwrdm_(pre|post)_transition() calls to the 2xxx PM code Paul Walmsley
2012-12-09 20:03 ` Paul Walmsley
2013-01-04 14:26 ` [PATCH 00/12] ARM: OMAP2+: powerdomain updates after the functional power state conversion Tero Kristo
2013-01-04 14:26 ` Tero Kristo
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20121209200325.3196.52729.stgit@dusk.lan \
--to=paul@pwsan.com \
--cc=khilman@deeprootsystems.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-omap@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.