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:03 UTC|newest]
Thread overview: 20+ 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 ` [PATCH 01/12] ARM: OMAP2+: powerdomain: consolidate arch_pwrdm check code 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 ` [PATCH 03/12] ARM: OMAP2+: powerdomain: split pwrdm_state_switch() 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 ` [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 [this message]
2012-12-09 20:03 ` [PATCH 08/12] ARM: OMAP2+: powerdomain: cache the powerdomain's previous power state 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-12 10:22 ` Vaibhav Hiremath
2012-12-19 21:09 ` Jon Hunter
2012-12-20 17:22 ` Paul Walmsley
2012-12-21 6:33 ` Santosh Shilimkar
2012-12-26 6:21 ` Bedia, Vaibhav
2012-12-26 6:31 ` Bedia, Vaibhav
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 ` [PATCH 11/12] ARM: OMAP2xxx: powerdomain: add previous power state tracking 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
2013-01-04 14:26 ` [PATCH 00/12] ARM: OMAP2+: powerdomain updates after the functional power state conversion 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=linux-arm-kernel@lists.infradead.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).