All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v7 0/6] PM QoS: implement the OMAP low level constraints management code
@ 2012-04-18 13:45 ` jean.pihet at newoldbits.com
  0 siblings, 0 replies; 22+ messages in thread
From: jean.pihet @ 2012-04-18 13:45 UTC (permalink / raw)
  To: linux-omap, paul, b-cousson, khilman, linux-arm-kernel; +Cc: Jean Pihet

From: Jean Pihet <j-pihet@ti.com>

. Implement the devices wake-up latency constraints using the global
  device PM QoS notification handler which applies the constraints to the
  underlying layer,
. Implement the low level code which controls the power domains next
  functional power states [3], through the hwmod and pwrdm layers,
. Add cpuidle and power domains wake-up latency figures for OMAP3, cf. 
  comments in the code and [1] for the details on where the numbers
  are magically coming from,
. Implement the relation between the cpuidle and per-device PM QoS frameworks
  in the OMAP3 specific idle callbacks.
  The chosen C-state shall satisfy the following conditions:
   . the 'valid' field is enabled,
   . it satisfies the enable_off_mode flag,
   . the next state for MPU and CORE power domains is not lower than the
     state programmed by the per-device PM QoS.


ToDo:
1. support OMAP4 chipset when the low power modes will be supported
2. validate the constraints framework on OMAP4 HW (done on OMAP3)
3. Re-visit the OMAP power domains states initialization procedure. Currently
   the power states that have been changed from the constraints API which were
   applied before the initialization of the power domains are lost
4. Further clean-up the OMAP PM layer, use the generic frameworks instead (OPP,
   PM QoS for throughput constraints ...)


Based on the pm-qos branch of the linux-omap git tree (3.4.0-rc2) [2] with
the functional power states changes applied [3].

Tested cpuidle and suspend on OMAP3 Beagleboard (ES2.x) with constraints
on MPU, CORE, PER in RETention and OFF modes.

[1] http://www.omappedia.org/wiki/Power_Management_Device_Latencies_Measurement
[2] git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap.git
[3] http://marc.info/?l=linux-omap&m=133475291911194&w=2


History:

v7:
. rebased on top of the functional power state changes [3]

v6:
. minor change in the commits description after Kevin's review
. added Kevin's Reviewed-by

v5:
. rebased on latest linux-omap [2]
. rework after Kevin's comments on the MLs

v4:
. split up the patches which remove the omap_pm_ code from the patch set.
  Those patches are to be submitted later, on top of this patch set.
. latency numbers: provide the measurements setup and conditions in the code
  comments, added the link to the details on wiki [1].
. improved kerneldoc
. split big functions into smaller ones, in order to improve the readability

v3: reworked the error return path and improved the kerneldoc

v2: reworked the OMAP specific cpuidle code to demote the initial C-state to
     a valid C-state which fulfills the per-device constraints

v1: initial version


Jean Pihet (6):
  ARM: OMAP2+: PM QoS: control the power domains next state from the
    constraints
  ARM: OMAP2+: PM QoS: manage the per-device latency constraints in
    hwmod
  ARM: OMAP: omap_device: register to the per-device PM QoS framework
  ARM: OMAP3: cpuidle: next C-state decision depends on the PM QoS MPU
    and CORE constraints
  ARM: OMAP3: update cpuidle latency and threshold figures
  ARM: OMAP3: powerdomain data: add wake-up latency figures

 arch/arm/mach-omap2/cpuidle34xx.c           |  109 ++++++++------
 arch/arm/mach-omap2/omap_hwmod.c            |   22 +--
 arch/arm/mach-omap2/pm.h                    |   17 ++-
 arch/arm/mach-omap2/powerdomain.c           |  216 +++++++++++++++++++++++++++
 arch/arm/mach-omap2/powerdomain.h           |   17 ++
 arch/arm/mach-omap2/powerdomains3xxx_data.c |   83 ++++++++++
 arch/arm/plat-omap/omap_device.c            |   81 ++++++++++-
 7 files changed, 481 insertions(+), 64 deletions(-)

-- 
1.7.7.6


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

* [PATCH v7 0/6] PM QoS: implement the OMAP low level constraints management code
@ 2012-04-18 13:45 ` jean.pihet at newoldbits.com
  0 siblings, 0 replies; 22+ messages in thread
From: jean.pihet at newoldbits.com @ 2012-04-18 13:45 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jean Pihet <j-pihet@ti.com>

. Implement the devices wake-up latency constraints using the global
  device PM QoS notification handler which applies the constraints to the
  underlying layer,
. Implement the low level code which controls the power domains next
  functional power states [3], through the hwmod and pwrdm layers,
. Add cpuidle and power domains wake-up latency figures for OMAP3, cf. 
  comments in the code and [1] for the details on where the numbers
  are magically coming from,
. Implement the relation between the cpuidle and per-device PM QoS frameworks
  in the OMAP3 specific idle callbacks.
  The chosen C-state shall satisfy the following conditions:
   . the 'valid' field is enabled,
   . it satisfies the enable_off_mode flag,
   . the next state for MPU and CORE power domains is not lower than the
     state programmed by the per-device PM QoS.


ToDo:
1. support OMAP4 chipset when the low power modes will be supported
2. validate the constraints framework on OMAP4 HW (done on OMAP3)
3. Re-visit the OMAP power domains states initialization procedure. Currently
   the power states that have been changed from the constraints API which were
   applied before the initialization of the power domains are lost
4. Further clean-up the OMAP PM layer, use the generic frameworks instead (OPP,
   PM QoS for throughput constraints ...)


Based on the pm-qos branch of the linux-omap git tree (3.4.0-rc2) [2] with
the functional power states changes applied [3].

Tested cpuidle and suspend on OMAP3 Beagleboard (ES2.x) with constraints
on MPU, CORE, PER in RETention and OFF modes.

[1] http://www.omappedia.org/wiki/Power_Management_Device_Latencies_Measurement
[2] git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap.git
[3] http://marc.info/?l=linux-omap&m=133475291911194&w=2


History:

v7:
. rebased on top of the functional power state changes [3]

v6:
. minor change in the commits description after Kevin's review
. added Kevin's Reviewed-by

v5:
. rebased on latest linux-omap [2]
. rework after Kevin's comments on the MLs

v4:
. split up the patches which remove the omap_pm_ code from the patch set.
  Those patches are to be submitted later, on top of this patch set.
. latency numbers: provide the measurements setup and conditions in the code
  comments, added the link to the details on wiki [1].
. improved kerneldoc
. split big functions into smaller ones, in order to improve the readability

v3: reworked the error return path and improved the kerneldoc

v2: reworked the OMAP specific cpuidle code to demote the initial C-state to
     a valid C-state which fulfills the per-device constraints

v1: initial version


Jean Pihet (6):
  ARM: OMAP2+: PM QoS: control the power domains next state from the
    constraints
  ARM: OMAP2+: PM QoS: manage the per-device latency constraints in
    hwmod
  ARM: OMAP: omap_device: register to the per-device PM QoS framework
  ARM: OMAP3: cpuidle: next C-state decision depends on the PM QoS MPU
    and CORE constraints
  ARM: OMAP3: update cpuidle latency and threshold figures
  ARM: OMAP3: powerdomain data: add wake-up latency figures

 arch/arm/mach-omap2/cpuidle34xx.c           |  109 ++++++++------
 arch/arm/mach-omap2/omap_hwmod.c            |   22 +--
 arch/arm/mach-omap2/pm.h                    |   17 ++-
 arch/arm/mach-omap2/powerdomain.c           |  216 +++++++++++++++++++++++++++
 arch/arm/mach-omap2/powerdomain.h           |   17 ++
 arch/arm/mach-omap2/powerdomains3xxx_data.c |   83 ++++++++++
 arch/arm/plat-omap/omap_device.c            |   81 ++++++++++-
 7 files changed, 481 insertions(+), 64 deletions(-)

-- 
1.7.7.6

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

* [PATCH 1/6] ARM: OMAP2+: PM QoS: control the power domains next state from the constraints
  2012-04-18 13:45 ` jean.pihet at newoldbits.com
@ 2012-04-18 13:45   ` jean.pihet at newoldbits.com
  -1 siblings, 0 replies; 22+ messages in thread
From: jean.pihet @ 2012-04-18 13:45 UTC (permalink / raw)
  To: linux-omap, paul, b-cousson, khilman, linux-arm-kernel; +Cc: Jean Pihet

From: Jean Pihet <j-pihet@ti.com>

When a PM QoS device latency constraint is requested or removed the
constraint is stored in the constraints list of the corresponding power
domain, then the aggregated constraint value is applied by programming
the next functional power state using omap_set_pwrdm_state.

Tested on OMAP3 Beagleboard and OMAP4 Pandaboard in RET/OFF using
wake-up latency constraints on MPU, CORE and PER.

Signed-off-by: Jean Pihet <j-pihet@ti.com>
---
 arch/arm/mach-omap2/powerdomain.c |  216 +++++++++++++++++++++++++++++++++++++
 arch/arm/mach-omap2/powerdomain.h |   17 +++
 2 files changed, 233 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
index 3f78f16..100c422 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -17,8 +17,10 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/list.h>
+#include <linux/slab.h>
 #include <linux/errno.h>
 #include <linux/string.h>
+#include <linux/pm_qos.h>
 #include <trace/events/power.h>
 
 #include "cm2xxx_3xxx.h"
@@ -113,6 +115,12 @@ static int _pwrdm_register(struct powerdomain *pwrdm)
 	for (i = 0; i < pwrdm->banks; i++)
 		pwrdm->ret_mem_off_counter[i] = 0;
 
+	/* Initialize the per-device wake-up constraints framework data */
+	mutex_init(&pwrdm->wkup_lat_plist_lock);
+	plist_head_init(&pwrdm->wkup_lat_plist_head);
+	pwrdm->wkup_lat_next_state = PWRDM_FUNC_PWRST_OFF;
+
+	/* Initialize the pwrdm state */
 	pwrdm_wait_transition(pwrdm);
 	pwrdm->state = pwrdm_read_func_pwrst(pwrdm);
 	pwrdm->state_counter[pwrdm->state] = 1;
@@ -200,6 +208,58 @@ static int _pwrdm_post_transition_cb(struct powerdomain *pwrdm, void *unused)
 	return 0;
 }
 
+/**
+ * _pwrdm_wakeuplat_update_pwrst - Update power domain power state if needed
+ * @pwrdm: struct powerdomain * to which requesting device belongs to.
+ * @min_latency: the allowed wake-up latency for the given power domain. A
+ *  value of PM_QOS_DEV_LAT_DEFAULT_VALUE means 'no constraint' on the pwrdm.
+ *
+ * Finds the power domain next power state that fulfills the constraint.
+ * Programs a new target state if it is different from current power state.
+ * The power domains get the next power state programmed directly in the
+ * registers.
+ *
+ * Returns 0 in case of success, -EINVAL in case of invalid parameters,
+ * or the return value from omap_set_pwrdm_state.
+ */
+static int _pwrdm_wakeuplat_update_pwrst(struct powerdomain *pwrdm,
+					 long min_latency)
+{
+	int ret = 0, state, new_state = PWRDM_FUNC_PWRST_ON;
+
+	if (!pwrdm) {
+		WARN(1, "powerdomain: %s: invalid parameter(s)", __func__);
+		return -EINVAL;
+	}
+
+	/*
+	 * Find the next supported power state with
+	 *  wakeup latency <= min_latency.
+	 * Pick the lower state if no constraint on the pwrdm
+	 *  (min_latency == PM_QOS_DEV_LAT_DEFAULT_VALUE).
+	 * Skip the states marked as unsupported (UNSUP_STATE).
+	 * If no power state found, fall back to PWRDM_FUNC_PWRST_ON.
+	 */
+        for (state = 0x0; state < PWRDM_MAX_FUNC_PWRSTS; state++) {
+                if ((min_latency == PM_QOS_DEV_LAT_DEFAULT_VALUE) ||
+                    ((pwrdm->wakeup_lat[state] != UNSUP_STATE) &&
+                     (pwrdm->wakeup_lat[state] <= min_latency))) {
+                        new_state = state;
+                        break;
+                }
+        }
+
+	pwrdm->wkup_lat_next_state = new_state;
+	ret = omap_set_pwrdm_state(pwrdm, new_state);
+
+	pr_debug("%s: func pwrst for %s: curr=%d, next=%d, min_latency=%ld, new_state=%d\n",
+		 __func__, pwrdm->name, pwrdm_read_func_pwrst(pwrdm),
+		 pwrdm_read_next_func_pwrst(pwrdm), min_latency, new_state);
+
+	return ret;
+}
+
+
 /* Public functions */
 
 /**
@@ -1224,6 +1284,162 @@ int pwrdm_post_transition(void)
 }
 
 /**
+ * pwrdm_wakeuplat_update_constraint - Set or update a powerdomain wakeup
+ *  latency constraint and apply it
+ * @pwrdm: struct powerdomain * which the constraint applies to
+ * @cookie: constraint identifier, used for tracking
+ * @min_latency: minimum wakeup latency constraint (in microseconds) for
+ *  the given pwrdm
+ *
+ * Tracks the constraints by @cookie.
+ * Constraint set/update: Adds a new entry to powerdomain's wake-up latency
+ * constraint list. If the constraint identifier already exists in the list,
+ * the old value is overwritten.
+ *
+ * Applies the aggregated constraint value for the given pwrdm by calling
+ * _pwrdm_wakeuplat_update_pwrst.
+ *
+ * Returns 0 upon success, -ENOMEM in case of memory shortage, -EINVAL in
+ * case of invalid latency value, or the return value from
+ * _pwrdm_wakeuplat_update_pwrst.
+ *
+ * The caller must check the validity of the parameters.
+ */
+int pwrdm_wakeuplat_update_constraint(struct powerdomain *pwrdm, void *cookie,
+				      long min_latency)
+{
+	struct pwrdm_wkup_constraints_entry *tmp_user, *new_user, *user = NULL;
+	long value = PM_QOS_DEV_LAT_DEFAULT_VALUE;
+	int free_new_user = 0;
+
+	pr_debug("powerdomain: %s: pwrdm %s, cookie=0x%p, min_latency=%ld\n",
+		 __func__, pwrdm->name, cookie, min_latency);
+
+	if (min_latency <= PM_QOS_DEV_LAT_DEFAULT_VALUE) {
+		pr_warn("%s: min_latency >= PM_QOS_DEV_LAT_DEFAULT_VALUE\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	/* Allocate a new entry for insertion in the list */
+	new_user = kzalloc(sizeof(struct pwrdm_wkup_constraints_entry),
+			   GFP_KERNEL);
+	if (!new_user) {
+		pr_err("%s: FATAL ERROR: kzalloc failed\n", __func__);
+		return -ENOMEM;
+	}
+
+	mutex_lock(&pwrdm->wkup_lat_plist_lock);
+
+	/* Check if there already is a constraint for cookie */
+	plist_for_each_entry(tmp_user, &pwrdm->wkup_lat_plist_head, node) {
+		if (tmp_user->cookie == cookie) {
+			user = tmp_user;
+			break;
+		}
+	}
+
+	/* If nothing to update, job done */
+	if (user && (user->node.prio == min_latency))
+		goto out;
+
+	if (!user) {
+		/* Add new entry to the list */
+		user = new_user;
+		user->cookie = cookie;
+	} else {
+		/* Update existing entry */
+		plist_del(&user->node, &pwrdm->wkup_lat_plist_head);
+		free_new_user = 1;
+	}
+
+	plist_node_init(&user->node, min_latency);
+	plist_add(&user->node, &pwrdm->wkup_lat_plist_head);
+
+	/* Find the aggregated constraint value from the list */
+	if (!plist_head_empty(&pwrdm->wkup_lat_plist_head))
+		value = plist_first(&pwrdm->wkup_lat_plist_head)->prio;
+
+	mutex_unlock(&pwrdm->wkup_lat_plist_lock);
+
+	/* Free the newly allocated entry if not in use */
+	if (free_new_user)
+		kfree(new_user);
+
+	/* Apply the constraint to the pwrdm */
+	pr_debug("powerdomain: %s: pwrdm %s, value=%ld\n",
+		 __func__, pwrdm->name, value);
+	return _pwrdm_wakeuplat_update_pwrst(pwrdm, value);
+
+out:
+	mutex_unlock(&pwrdm->wkup_lat_plist_lock);
+	return 0;
+}
+
+/**
+ * pwrdm_wakeuplat_remove_constraint - Release a powerdomain wakeup latency
+ *  constraint and apply it
+ * @pwrdm: struct powerdomain * which the constraint applies to
+ * @cookie: constraint identifier, used for tracking
+ *
+ * Tracks the constraints by @cookie.
+ * Constraint removal: Removes the identifier's entry from powerdomain's
+ * wakeup latency constraint list.
+ *
+ * Applies the aggregated constraint value for the given pwrdm by calling
+ * _pwrdm_wakeuplat_update_pwrst.
+ *
+ * Returns 0 upon success, -EINVAL in case the constraint to remove is not
+ * existing, or the return value from _pwrdm_wakeuplat_update_pwrst.
+ *
+ * The caller must check the validity of the parameters.
+ */
+int pwrdm_wakeuplat_remove_constraint(struct powerdomain *pwrdm, void *cookie)
+{
+	struct pwrdm_wkup_constraints_entry *tmp_user, *user = NULL;
+	long value = PM_QOS_DEV_LAT_DEFAULT_VALUE;
+
+	pr_debug("powerdomain: %s: pwrdm %s, cookie=0x%p\n",
+		 __func__, pwrdm->name, cookie);
+
+	mutex_lock(&pwrdm->wkup_lat_plist_lock);
+
+	/* Check if there is a constraint for cookie */
+	plist_for_each_entry(tmp_user, &pwrdm->wkup_lat_plist_head, node) {
+		if (tmp_user->cookie == cookie) {
+			user = tmp_user;
+			break;
+		}
+	}
+
+	/* If constraint not existing or list empty, do nothing */
+	if (!user) {
+		goto out;
+	}
+
+	/* Remove the constraint from the list */
+	plist_del(&user->node, &pwrdm->wkup_lat_plist_head);
+
+	/* Find the aggregated constraint value from the list */
+	if (!plist_head_empty(&pwrdm->wkup_lat_plist_head))
+		value = plist_first(&pwrdm->wkup_lat_plist_head)->prio;
+
+	mutex_unlock(&pwrdm->wkup_lat_plist_lock);
+
+	/* Release the constraint memory */
+	kfree(user);
+
+	/* Apply the constraint to the pwrdm */
+	pr_debug("powerdomain: %s: pwrdm %s, value=%ld\n",
+		 __func__, pwrdm->name, value);
+	return _pwrdm_wakeuplat_update_pwrst(pwrdm, value);
+
+out:
+	mutex_unlock(&pwrdm->wkup_lat_plist_lock);
+	return -EINVAL;
+}
+
+/**
  * pwrdm_get_context_loss_count - get powerdomain's context loss count
  * @pwrdm: struct powerdomain * to wait for
  *
diff --git a/arch/arm/mach-omap2/powerdomain.h b/arch/arm/mach-omap2/powerdomain.h
index 9249d42..63028c0 100644
--- a/arch/arm/mach-omap2/powerdomain.h
+++ b/arch/arm/mach-omap2/powerdomain.h
@@ -19,6 +19,7 @@
 
 #include <linux/types.h>
 #include <linux/list.h>
+#include <linux/plist.h>
 #include <linux/mutex.h>
 #include <linux/atomic.h>
 
@@ -53,6 +54,7 @@
 #define PWRDM_FUNC_PWRST_ON		0x4
 
 #define PWRDM_MAX_FUNC_PWRSTS	5
+#define UNSUP_STATE		-1
 
 /*
  * Powerdomains logic and memory functional power states,
@@ -143,6 +145,16 @@ struct powerdomain {
 	s64 timer;
 	s64 state_timer[PWRDM_MAX_FUNC_PWRSTS];
 #endif
+	const s32 wakeup_lat[PWRDM_MAX_FUNC_PWRSTS];
+	struct plist_head wkup_lat_plist_head;
+	struct mutex wkup_lat_plist_lock;
+	int wkup_lat_next_state;
+};
+
+/* Linked list for the wake-up latency constraints */
+struct pwrdm_wkup_constraints_entry {
+	void			*cookie;
+	struct plist_node	node;
 };
 
 /**
@@ -253,6 +265,11 @@ int pwrdm_clkdm_state_switch(struct clockdomain *clkdm);
 int pwrdm_pre_transition(void);
 int pwrdm_post_transition(void);
 int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm);
+
+int pwrdm_wakeuplat_update_constraint(struct powerdomain *pwrdm, void *cookie,
+				      long min_latency);
+int pwrdm_wakeuplat_remove_constraint(struct powerdomain *pwrdm, void *cookie);
+
 int pwrdm_get_context_loss_count(struct powerdomain *pwrdm);
 bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm);
 
-- 
1.7.7.6


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

* [PATCH 1/6] ARM: OMAP2+: PM QoS: control the power domains next state from the constraints
@ 2012-04-18 13:45   ` jean.pihet at newoldbits.com
  0 siblings, 0 replies; 22+ messages in thread
From: jean.pihet at newoldbits.com @ 2012-04-18 13:45 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jean Pihet <j-pihet@ti.com>

When a PM QoS device latency constraint is requested or removed the
constraint is stored in the constraints list of the corresponding power
domain, then the aggregated constraint value is applied by programming
the next functional power state using omap_set_pwrdm_state.

Tested on OMAP3 Beagleboard and OMAP4 Pandaboard in RET/OFF using
wake-up latency constraints on MPU, CORE and PER.

Signed-off-by: Jean Pihet <j-pihet@ti.com>
---
 arch/arm/mach-omap2/powerdomain.c |  216 +++++++++++++++++++++++++++++++++++++
 arch/arm/mach-omap2/powerdomain.h |   17 +++
 2 files changed, 233 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
index 3f78f16..100c422 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -17,8 +17,10 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/list.h>
+#include <linux/slab.h>
 #include <linux/errno.h>
 #include <linux/string.h>
+#include <linux/pm_qos.h>
 #include <trace/events/power.h>
 
 #include "cm2xxx_3xxx.h"
@@ -113,6 +115,12 @@ static int _pwrdm_register(struct powerdomain *pwrdm)
 	for (i = 0; i < pwrdm->banks; i++)
 		pwrdm->ret_mem_off_counter[i] = 0;
 
+	/* Initialize the per-device wake-up constraints framework data */
+	mutex_init(&pwrdm->wkup_lat_plist_lock);
+	plist_head_init(&pwrdm->wkup_lat_plist_head);
+	pwrdm->wkup_lat_next_state = PWRDM_FUNC_PWRST_OFF;
+
+	/* Initialize the pwrdm state */
 	pwrdm_wait_transition(pwrdm);
 	pwrdm->state = pwrdm_read_func_pwrst(pwrdm);
 	pwrdm->state_counter[pwrdm->state] = 1;
@@ -200,6 +208,58 @@ static int _pwrdm_post_transition_cb(struct powerdomain *pwrdm, void *unused)
 	return 0;
 }
 
+/**
+ * _pwrdm_wakeuplat_update_pwrst - Update power domain power state if needed
+ * @pwrdm: struct powerdomain * to which requesting device belongs to.
+ * @min_latency: the allowed wake-up latency for the given power domain. A
+ *  value of PM_QOS_DEV_LAT_DEFAULT_VALUE means 'no constraint' on the pwrdm.
+ *
+ * Finds the power domain next power state that fulfills the constraint.
+ * Programs a new target state if it is different from current power state.
+ * The power domains get the next power state programmed directly in the
+ * registers.
+ *
+ * Returns 0 in case of success, -EINVAL in case of invalid parameters,
+ * or the return value from omap_set_pwrdm_state.
+ */
+static int _pwrdm_wakeuplat_update_pwrst(struct powerdomain *pwrdm,
+					 long min_latency)
+{
+	int ret = 0, state, new_state = PWRDM_FUNC_PWRST_ON;
+
+	if (!pwrdm) {
+		WARN(1, "powerdomain: %s: invalid parameter(s)", __func__);
+		return -EINVAL;
+	}
+
+	/*
+	 * Find the next supported power state with
+	 *  wakeup latency <= min_latency.
+	 * Pick the lower state if no constraint on the pwrdm
+	 *  (min_latency == PM_QOS_DEV_LAT_DEFAULT_VALUE).
+	 * Skip the states marked as unsupported (UNSUP_STATE).
+	 * If no power state found, fall back to PWRDM_FUNC_PWRST_ON.
+	 */
+        for (state = 0x0; state < PWRDM_MAX_FUNC_PWRSTS; state++) {
+                if ((min_latency == PM_QOS_DEV_LAT_DEFAULT_VALUE) ||
+                    ((pwrdm->wakeup_lat[state] != UNSUP_STATE) &&
+                     (pwrdm->wakeup_lat[state] <= min_latency))) {
+                        new_state = state;
+                        break;
+                }
+        }
+
+	pwrdm->wkup_lat_next_state = new_state;
+	ret = omap_set_pwrdm_state(pwrdm, new_state);
+
+	pr_debug("%s: func pwrst for %s: curr=%d, next=%d, min_latency=%ld, new_state=%d\n",
+		 __func__, pwrdm->name, pwrdm_read_func_pwrst(pwrdm),
+		 pwrdm_read_next_func_pwrst(pwrdm), min_latency, new_state);
+
+	return ret;
+}
+
+
 /* Public functions */
 
 /**
@@ -1224,6 +1284,162 @@ int pwrdm_post_transition(void)
 }
 
 /**
+ * pwrdm_wakeuplat_update_constraint - Set or update a powerdomain wakeup
+ *  latency constraint and apply it
+ * @pwrdm: struct powerdomain * which the constraint applies to
+ * @cookie: constraint identifier, used for tracking
+ * @min_latency: minimum wakeup latency constraint (in microseconds) for
+ *  the given pwrdm
+ *
+ * Tracks the constraints by @cookie.
+ * Constraint set/update: Adds a new entry to powerdomain's wake-up latency
+ * constraint list. If the constraint identifier already exists in the list,
+ * the old value is overwritten.
+ *
+ * Applies the aggregated constraint value for the given pwrdm by calling
+ * _pwrdm_wakeuplat_update_pwrst.
+ *
+ * Returns 0 upon success, -ENOMEM in case of memory shortage, -EINVAL in
+ * case of invalid latency value, or the return value from
+ * _pwrdm_wakeuplat_update_pwrst.
+ *
+ * The caller must check the validity of the parameters.
+ */
+int pwrdm_wakeuplat_update_constraint(struct powerdomain *pwrdm, void *cookie,
+				      long min_latency)
+{
+	struct pwrdm_wkup_constraints_entry *tmp_user, *new_user, *user = NULL;
+	long value = PM_QOS_DEV_LAT_DEFAULT_VALUE;
+	int free_new_user = 0;
+
+	pr_debug("powerdomain: %s: pwrdm %s, cookie=0x%p, min_latency=%ld\n",
+		 __func__, pwrdm->name, cookie, min_latency);
+
+	if (min_latency <= PM_QOS_DEV_LAT_DEFAULT_VALUE) {
+		pr_warn("%s: min_latency >= PM_QOS_DEV_LAT_DEFAULT_VALUE\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	/* Allocate a new entry for insertion in the list */
+	new_user = kzalloc(sizeof(struct pwrdm_wkup_constraints_entry),
+			   GFP_KERNEL);
+	if (!new_user) {
+		pr_err("%s: FATAL ERROR: kzalloc failed\n", __func__);
+		return -ENOMEM;
+	}
+
+	mutex_lock(&pwrdm->wkup_lat_plist_lock);
+
+	/* Check if there already is a constraint for cookie */
+	plist_for_each_entry(tmp_user, &pwrdm->wkup_lat_plist_head, node) {
+		if (tmp_user->cookie == cookie) {
+			user = tmp_user;
+			break;
+		}
+	}
+
+	/* If nothing to update, job done */
+	if (user && (user->node.prio == min_latency))
+		goto out;
+
+	if (!user) {
+		/* Add new entry to the list */
+		user = new_user;
+		user->cookie = cookie;
+	} else {
+		/* Update existing entry */
+		plist_del(&user->node, &pwrdm->wkup_lat_plist_head);
+		free_new_user = 1;
+	}
+
+	plist_node_init(&user->node, min_latency);
+	plist_add(&user->node, &pwrdm->wkup_lat_plist_head);
+
+	/* Find the aggregated constraint value from the list */
+	if (!plist_head_empty(&pwrdm->wkup_lat_plist_head))
+		value = plist_first(&pwrdm->wkup_lat_plist_head)->prio;
+
+	mutex_unlock(&pwrdm->wkup_lat_plist_lock);
+
+	/* Free the newly allocated entry if not in use */
+	if (free_new_user)
+		kfree(new_user);
+
+	/* Apply the constraint to the pwrdm */
+	pr_debug("powerdomain: %s: pwrdm %s, value=%ld\n",
+		 __func__, pwrdm->name, value);
+	return _pwrdm_wakeuplat_update_pwrst(pwrdm, value);
+
+out:
+	mutex_unlock(&pwrdm->wkup_lat_plist_lock);
+	return 0;
+}
+
+/**
+ * pwrdm_wakeuplat_remove_constraint - Release a powerdomain wakeup latency
+ *  constraint and apply it
+ * @pwrdm: struct powerdomain * which the constraint applies to
+ * @cookie: constraint identifier, used for tracking
+ *
+ * Tracks the constraints by @cookie.
+ * Constraint removal: Removes the identifier's entry from powerdomain's
+ * wakeup latency constraint list.
+ *
+ * Applies the aggregated constraint value for the given pwrdm by calling
+ * _pwrdm_wakeuplat_update_pwrst.
+ *
+ * Returns 0 upon success, -EINVAL in case the constraint to remove is not
+ * existing, or the return value from _pwrdm_wakeuplat_update_pwrst.
+ *
+ * The caller must check the validity of the parameters.
+ */
+int pwrdm_wakeuplat_remove_constraint(struct powerdomain *pwrdm, void *cookie)
+{
+	struct pwrdm_wkup_constraints_entry *tmp_user, *user = NULL;
+	long value = PM_QOS_DEV_LAT_DEFAULT_VALUE;
+
+	pr_debug("powerdomain: %s: pwrdm %s, cookie=0x%p\n",
+		 __func__, pwrdm->name, cookie);
+
+	mutex_lock(&pwrdm->wkup_lat_plist_lock);
+
+	/* Check if there is a constraint for cookie */
+	plist_for_each_entry(tmp_user, &pwrdm->wkup_lat_plist_head, node) {
+		if (tmp_user->cookie == cookie) {
+			user = tmp_user;
+			break;
+		}
+	}
+
+	/* If constraint not existing or list empty, do nothing */
+	if (!user) {
+		goto out;
+	}
+
+	/* Remove the constraint from the list */
+	plist_del(&user->node, &pwrdm->wkup_lat_plist_head);
+
+	/* Find the aggregated constraint value from the list */
+	if (!plist_head_empty(&pwrdm->wkup_lat_plist_head))
+		value = plist_first(&pwrdm->wkup_lat_plist_head)->prio;
+
+	mutex_unlock(&pwrdm->wkup_lat_plist_lock);
+
+	/* Release the constraint memory */
+	kfree(user);
+
+	/* Apply the constraint to the pwrdm */
+	pr_debug("powerdomain: %s: pwrdm %s, value=%ld\n",
+		 __func__, pwrdm->name, value);
+	return _pwrdm_wakeuplat_update_pwrst(pwrdm, value);
+
+out:
+	mutex_unlock(&pwrdm->wkup_lat_plist_lock);
+	return -EINVAL;
+}
+
+/**
  * pwrdm_get_context_loss_count - get powerdomain's context loss count
  * @pwrdm: struct powerdomain * to wait for
  *
diff --git a/arch/arm/mach-omap2/powerdomain.h b/arch/arm/mach-omap2/powerdomain.h
index 9249d42..63028c0 100644
--- a/arch/arm/mach-omap2/powerdomain.h
+++ b/arch/arm/mach-omap2/powerdomain.h
@@ -19,6 +19,7 @@
 
 #include <linux/types.h>
 #include <linux/list.h>
+#include <linux/plist.h>
 #include <linux/mutex.h>
 #include <linux/atomic.h>
 
@@ -53,6 +54,7 @@
 #define PWRDM_FUNC_PWRST_ON		0x4
 
 #define PWRDM_MAX_FUNC_PWRSTS	5
+#define UNSUP_STATE		-1
 
 /*
  * Powerdomains logic and memory functional power states,
@@ -143,6 +145,16 @@ struct powerdomain {
 	s64 timer;
 	s64 state_timer[PWRDM_MAX_FUNC_PWRSTS];
 #endif
+	const s32 wakeup_lat[PWRDM_MAX_FUNC_PWRSTS];
+	struct plist_head wkup_lat_plist_head;
+	struct mutex wkup_lat_plist_lock;
+	int wkup_lat_next_state;
+};
+
+/* Linked list for the wake-up latency constraints */
+struct pwrdm_wkup_constraints_entry {
+	void			*cookie;
+	struct plist_node	node;
 };
 
 /**
@@ -253,6 +265,11 @@ int pwrdm_clkdm_state_switch(struct clockdomain *clkdm);
 int pwrdm_pre_transition(void);
 int pwrdm_post_transition(void);
 int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm);
+
+int pwrdm_wakeuplat_update_constraint(struct powerdomain *pwrdm, void *cookie,
+				      long min_latency);
+int pwrdm_wakeuplat_remove_constraint(struct powerdomain *pwrdm, void *cookie);
+
 int pwrdm_get_context_loss_count(struct powerdomain *pwrdm);
 bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm);
 
-- 
1.7.7.6

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

* [PATCH 2/6] ARM: OMAP2+: PM QoS: manage the per-device latency constraints in hwmod
  2012-04-18 13:45 ` jean.pihet at newoldbits.com
@ 2012-04-18 13:45   ` jean.pihet at newoldbits.com
  -1 siblings, 0 replies; 22+ messages in thread
From: jean.pihet @ 2012-04-18 13:45 UTC (permalink / raw)
  To: linux-omap, paul, b-cousson, khilman, linux-arm-kernel; +Cc: Jean Pihet

From: Jean Pihet <j-pihet@ti.com>

Call the per-device PM QoS functions of the power domain code from the
hwmod layer, in order to apply the constraints requested to a device.

While at it, correct the functions kerneldoc.

Signed-off-by: Jean Pihet <j-pihet@ti.com>
---
 arch/arm/mach-omap2/omap_hwmod.c |   22 ++++++----------------
 1 files changed, 6 insertions(+), 16 deletions(-)

diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index aefd2ee..9485eb1 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -3020,15 +3020,13 @@ ohsps_unlock:
 }
 
 /**
- * omap_hwmod_set_wakeuplat_constraint - set/release a wake-up latency
+ * omap_hwmod_set_wakeuplat_constraint - Set or update a wake-up latency
  * constraint
  * @oh: struct omap_hwmod* to which the target device belongs to.
  * @cookie: identifier of the constraints list for @oh.
  * @min_latency: the minimum allowed wake-up latency for @oh.
  *
- * Sets a wakeup latency contraint.  (To remove a wakeup latency
- * constraint, call omap_hwmod_remove_wakeuplat_constraint()).
- * Returns the return value from pwrdm_wakeuplat_remove_constraint(),
+ * Returns the return value from pwrdm_wakeuplat_update_constraint(),
  * or -EINVAL in case of invalid parameters.
  */
 int omap_hwmod_set_wakeuplat_constraint(struct omap_hwmod *oh, void *cookie,
@@ -3039,21 +3037,17 @@ int omap_hwmod_set_wakeuplat_constraint(struct omap_hwmod *oh, void *cookie,
 	if (!pwrdm)
 		return -EINVAL;
 
-	/*
-	 * XXX Update to use pwrdm_wakeuplat_update_constraint() when
-	 * that code is ready
-	 */
-	return -EINVAL;
+	return pwrdm_wakeuplat_update_constraint(pwrdm, cookie, min_latency);
 }
 
 /**
- * omap_hwmod_remove_wakeuplat_constraint - release a wake-up latency
+ * omap_hwmod_remove_wakeuplat_constraint - Release a wake-up latency
  * constraint
  * @oh: struct omap_hwmod* to which the target device belongs to.
  * @cookie: identifier of the constraints list for @oh.
  *
  * Removes a wakeup latency contraint.  Returns the return value from
- * pwrdm_wakeuplat_update_constraint(), or -EINVAL in case of invalid
+ * pwrdm_wakeuplat_remove_constraint(), or -EINVAL in case of invalid
  * parameters.
  */
 int omap_hwmod_remove_wakeuplat_constraint(struct omap_hwmod *oh, void *cookie)
@@ -3063,11 +3057,7 @@ int omap_hwmod_remove_wakeuplat_constraint(struct omap_hwmod *oh, void *cookie)
 	if (!pwrdm)
 		return -EINVAL;
 
-	/*
-	 * XXX Update to use pwrdm_wakeuplat_remove_constraint() when
-	 * that code is ready
-	 */
-	return -EINVAL;
+	return pwrdm_wakeuplat_remove_constraint(pwrdm, cookie);
 }
 
 /**
-- 
1.7.7.6


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

* [PATCH 2/6] ARM: OMAP2+: PM QoS: manage the per-device latency constraints in hwmod
@ 2012-04-18 13:45   ` jean.pihet at newoldbits.com
  0 siblings, 0 replies; 22+ messages in thread
From: jean.pihet at newoldbits.com @ 2012-04-18 13:45 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jean Pihet <j-pihet@ti.com>

Call the per-device PM QoS functions of the power domain code from the
hwmod layer, in order to apply the constraints requested to a device.

While at it, correct the functions kerneldoc.

Signed-off-by: Jean Pihet <j-pihet@ti.com>
---
 arch/arm/mach-omap2/omap_hwmod.c |   22 ++++++----------------
 1 files changed, 6 insertions(+), 16 deletions(-)

diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index aefd2ee..9485eb1 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -3020,15 +3020,13 @@ ohsps_unlock:
 }
 
 /**
- * omap_hwmod_set_wakeuplat_constraint - set/release a wake-up latency
+ * omap_hwmod_set_wakeuplat_constraint - Set or update a wake-up latency
  * constraint
  * @oh: struct omap_hwmod* to which the target device belongs to.
  * @cookie: identifier of the constraints list for @oh.
  * @min_latency: the minimum allowed wake-up latency for @oh.
  *
- * Sets a wakeup latency contraint.  (To remove a wakeup latency
- * constraint, call omap_hwmod_remove_wakeuplat_constraint()).
- * Returns the return value from pwrdm_wakeuplat_remove_constraint(),
+ * Returns the return value from pwrdm_wakeuplat_update_constraint(),
  * or -EINVAL in case of invalid parameters.
  */
 int omap_hwmod_set_wakeuplat_constraint(struct omap_hwmod *oh, void *cookie,
@@ -3039,21 +3037,17 @@ int omap_hwmod_set_wakeuplat_constraint(struct omap_hwmod *oh, void *cookie,
 	if (!pwrdm)
 		return -EINVAL;
 
-	/*
-	 * XXX Update to use pwrdm_wakeuplat_update_constraint() when
-	 * that code is ready
-	 */
-	return -EINVAL;
+	return pwrdm_wakeuplat_update_constraint(pwrdm, cookie, min_latency);
 }
 
 /**
- * omap_hwmod_remove_wakeuplat_constraint - release a wake-up latency
+ * omap_hwmod_remove_wakeuplat_constraint - Release a wake-up latency
  * constraint
  * @oh: struct omap_hwmod* to which the target device belongs to.
  * @cookie: identifier of the constraints list for @oh.
  *
  * Removes a wakeup latency contraint.  Returns the return value from
- * pwrdm_wakeuplat_update_constraint(), or -EINVAL in case of invalid
+ * pwrdm_wakeuplat_remove_constraint(), or -EINVAL in case of invalid
  * parameters.
  */
 int omap_hwmod_remove_wakeuplat_constraint(struct omap_hwmod *oh, void *cookie)
@@ -3063,11 +3057,7 @@ int omap_hwmod_remove_wakeuplat_constraint(struct omap_hwmod *oh, void *cookie)
 	if (!pwrdm)
 		return -EINVAL;
 
-	/*
-	 * XXX Update to use pwrdm_wakeuplat_remove_constraint() when
-	 * that code is ready
-	 */
-	return -EINVAL;
+	return pwrdm_wakeuplat_remove_constraint(pwrdm, cookie);
 }
 
 /**
-- 
1.7.7.6

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

* [PATCH 3/6] ARM: OMAP: omap_device: register to the per-device PM QoS framework
  2012-04-18 13:45 ` jean.pihet at newoldbits.com
@ 2012-04-18 13:45   ` jean.pihet at newoldbits.com
  -1 siblings, 0 replies; 22+ messages in thread
From: jean.pihet @ 2012-04-18 13:45 UTC (permalink / raw)
  To: linux-omap, paul, b-cousson, khilman, linux-arm-kernel; +Cc: Jean Pihet

From: Jean Pihet <j-pihet@ti.com>

Implement the devices wake-up latency constraints using the global
device PM QoS notification handler which applies the constraints to the
underlying layer by calling the corresponding function at hwmod level.

Tested on OMAP3 Beagleboard and OMAP4 Pandaboard in RET/OFF using wake-up
latency constraints on MPU, CORE and PER.

Signed-off-by: Jean Pihet <j-pihet@ti.com>
Reviewed-by: Kevin Hilman <khilman@ti.com>
[paul@pwsan.com: modified to work with omap_devices with large numbers of
 hwmods; moved code to mach-omap2/omap_device.c; added documentation; use
 notifier return codes]
Signed-off-by: Paul Walmsley <paul@pwsan.com>
---
 arch/arm/plat-omap/omap_device.c |   81 +++++++++++++++++++++++++++++++++++++-
 1 files changed, 80 insertions(+), 1 deletions(-)

diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c
index d50cbc6..fb66879 100644
--- a/arch/arm/plat-omap/omap_device.c
+++ b/arch/arm/plat-omap/omap_device.c
@@ -3,6 +3,7 @@
  * omap_device implementation
  *
  * Copyright (C) 2009-2010 Nokia Corporation
+ * Copyright (C) 2011 Texas Instruments, Inc.
  * Paul Walmsley, Kevin Hilman
  *
  * Developed in collaboration with (alphabetical order): Benoit
@@ -89,6 +90,7 @@
 #include <linux/pm_runtime.h>
 #include <linux/of.h>
 #include <linux/notifier.h>
+#include <linux/pm_qos.h>
 
 #include <plat/omap_device.h>
 #include <plat/omap_hwmod.h>
@@ -401,6 +403,72 @@ static int _omap_device_notifier_call(struct notifier_block *nb,
 	return NOTIFY_DONE;
 }
 
+/**
+ * _omap_device_pm_qos_handler - interface to the per-device PM QoS framework
+ * @nb: pointer to omap_device_pm_qos_nb (not used)
+ * @new_value: new maximum wakeup latency constraint for @req->dev (in µs)
+ * @req: struct dev_pm_qos_request * passed by the Linux PM QoS code
+ *
+ * Called by the Linux core device PM QoS code to alter the maximum
+ * wakeup latency constraint on a device.  If the underlying device is
+ * an omap_device, then this code will pass the constraint on to the
+ * underlying hwmods.  Returns -EINVAL if this code can't handle the
+ * constraint for some reason, or passes along the return code from the
+ * hwmod wakeup latency constraint functions.
+ */
+static int _omap_device_pm_qos_handler(struct notifier_block *nb,
+				       unsigned long new_value,
+				       void *req)
+{
+	struct omap_device *od;
+	struct omap_hwmod *oh;
+	struct platform_device *pdev;
+	struct dev_pm_qos_request *dev_pm_qos_req = req;
+	int ret = NOTIFY_OK;
+	int r, i;
+
+	pr_debug("OMAP PM constraints: req@0x%p, new_value=%lu\n",
+		 req, new_value);
+
+	/* Look for the platform device for the constraint target device */
+	pdev = to_platform_device(dev_pm_qos_req->dev);
+
+	/* Try to catch non platform devices */
+	if (pdev->name == NULL) {
+		pr_err("%s: Error: platform device for device %s not valid\n",
+		       __func__, dev_name(dev_pm_qos_req->dev));
+		return NOTIFY_DONE;
+	}
+
+	/* Find the associated omap_device for dev */
+	od = to_omap_device(pdev);
+	if (od == NULL) {
+		pr_err("%s: Error: no omap_device for device %s\n",
+		       __func__, dev_name(dev_pm_qos_req->dev));
+		return NOTIFY_DONE;
+	}
+
+	pr_debug("OMAP PM constraints: req@0x%p, dev=0x%p, new_value=%lu\n",
+		 req, dev_pm_qos_req->dev, new_value);
+
+	for (i = 0; i < od->hwmods_cnt; i++) {
+		oh = od->hwmods[i];
+		if (new_value == PM_QOS_DEV_LAT_DEFAULT_VALUE)
+			r = omap_hwmod_remove_wakeuplat_constraint(
+							oh,
+							dev_pm_qos_req);
+		else
+			r = omap_hwmod_set_wakeuplat_constraint(
+							oh,
+							dev_pm_qos_req,
+							new_value);
+
+		if (!r)
+			ret = NOTIFY_BAD;
+	}
+
+	return ret;
+}
 
 /* Public functions for use by core code */
 
@@ -1117,13 +1185,24 @@ int omap_device_enable_clocks(struct omap_device *od)
 	return 0;
 }
 
+static struct notifier_block omap_device_pm_qos_nb = {
+	.notifier_call = _omap_device_pm_qos_handler,
+};
+
 static struct notifier_block platform_nb = {
 	.notifier_call = _omap_device_notifier_call,
 };
 
 static int __init omap_device_init(void)
 {
+	int ret;
+
 	bus_register_notifier(&platform_bus_type, &platform_nb);
-	return 0;
+
+	ret = dev_pm_qos_add_global_notifier(&omap_device_pm_qos_nb);
+	if (!ret)
+		pr_err("omap_device: cannot add global notifier for dev PM QoS\n");
+
+	return ret;
 }
 core_initcall(omap_device_init);
-- 
1.7.7.6

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH 3/6] ARM: OMAP: omap_device: register to the per-device PM QoS framework
@ 2012-04-18 13:45   ` jean.pihet at newoldbits.com
  0 siblings, 0 replies; 22+ messages in thread
From: jean.pihet at newoldbits.com @ 2012-04-18 13:45 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jean Pihet <j-pihet@ti.com>

Implement the devices wake-up latency constraints using the global
device PM QoS notification handler which applies the constraints to the
underlying layer by calling the corresponding function at hwmod level.

Tested on OMAP3 Beagleboard and OMAP4 Pandaboard in RET/OFF using wake-up
latency constraints on MPU, CORE and PER.

Signed-off-by: Jean Pihet <j-pihet@ti.com>
Reviewed-by: Kevin Hilman <khilman@ti.com>
[paul at pwsan.com: modified to work with omap_devices with large numbers of
 hwmods; moved code to mach-omap2/omap_device.c; added documentation; use
 notifier return codes]
Signed-off-by: Paul Walmsley <paul@pwsan.com>
---
 arch/arm/plat-omap/omap_device.c |   81 +++++++++++++++++++++++++++++++++++++-
 1 files changed, 80 insertions(+), 1 deletions(-)

diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c
index d50cbc6..fb66879 100644
--- a/arch/arm/plat-omap/omap_device.c
+++ b/arch/arm/plat-omap/omap_device.c
@@ -3,6 +3,7 @@
  * omap_device implementation
  *
  * Copyright (C) 2009-2010 Nokia Corporation
+ * Copyright (C) 2011 Texas Instruments, Inc.
  * Paul Walmsley, Kevin Hilman
  *
  * Developed in collaboration with (alphabetical order): Benoit
@@ -89,6 +90,7 @@
 #include <linux/pm_runtime.h>
 #include <linux/of.h>
 #include <linux/notifier.h>
+#include <linux/pm_qos.h>
 
 #include <plat/omap_device.h>
 #include <plat/omap_hwmod.h>
@@ -401,6 +403,72 @@ static int _omap_device_notifier_call(struct notifier_block *nb,
 	return NOTIFY_DONE;
 }
 
+/**
+ * _omap_device_pm_qos_handler - interface to the per-device PM QoS framework
+ * @nb: pointer to omap_device_pm_qos_nb (not used)
+ * @new_value: new maximum wakeup latency constraint for @req->dev (in ?s)
+ * @req: struct dev_pm_qos_request * passed by the Linux PM QoS code
+ *
+ * Called by the Linux core device PM QoS code to alter the maximum
+ * wakeup latency constraint on a device.  If the underlying device is
+ * an omap_device, then this code will pass the constraint on to the
+ * underlying hwmods.  Returns -EINVAL if this code can't handle the
+ * constraint for some reason, or passes along the return code from the
+ * hwmod wakeup latency constraint functions.
+ */
+static int _omap_device_pm_qos_handler(struct notifier_block *nb,
+				       unsigned long new_value,
+				       void *req)
+{
+	struct omap_device *od;
+	struct omap_hwmod *oh;
+	struct platform_device *pdev;
+	struct dev_pm_qos_request *dev_pm_qos_req = req;
+	int ret = NOTIFY_OK;
+	int r, i;
+
+	pr_debug("OMAP PM constraints: req at 0x%p, new_value=%lu\n",
+		 req, new_value);
+
+	/* Look for the platform device for the constraint target device */
+	pdev = to_platform_device(dev_pm_qos_req->dev);
+
+	/* Try to catch non platform devices */
+	if (pdev->name == NULL) {
+		pr_err("%s: Error: platform device for device %s not valid\n",
+		       __func__, dev_name(dev_pm_qos_req->dev));
+		return NOTIFY_DONE;
+	}
+
+	/* Find the associated omap_device for dev */
+	od = to_omap_device(pdev);
+	if (od == NULL) {
+		pr_err("%s: Error: no omap_device for device %s\n",
+		       __func__, dev_name(dev_pm_qos_req->dev));
+		return NOTIFY_DONE;
+	}
+
+	pr_debug("OMAP PM constraints: req at 0x%p, dev=0x%p, new_value=%lu\n",
+		 req, dev_pm_qos_req->dev, new_value);
+
+	for (i = 0; i < od->hwmods_cnt; i++) {
+		oh = od->hwmods[i];
+		if (new_value == PM_QOS_DEV_LAT_DEFAULT_VALUE)
+			r = omap_hwmod_remove_wakeuplat_constraint(
+							oh,
+							dev_pm_qos_req);
+		else
+			r = omap_hwmod_set_wakeuplat_constraint(
+							oh,
+							dev_pm_qos_req,
+							new_value);
+
+		if (!r)
+			ret = NOTIFY_BAD;
+	}
+
+	return ret;
+}
 
 /* Public functions for use by core code */
 
@@ -1117,13 +1185,24 @@ int omap_device_enable_clocks(struct omap_device *od)
 	return 0;
 }
 
+static struct notifier_block omap_device_pm_qos_nb = {
+	.notifier_call = _omap_device_pm_qos_handler,
+};
+
 static struct notifier_block platform_nb = {
 	.notifier_call = _omap_device_notifier_call,
 };
 
 static int __init omap_device_init(void)
 {
+	int ret;
+
 	bus_register_notifier(&platform_bus_type, &platform_nb);
-	return 0;
+
+	ret = dev_pm_qos_add_global_notifier(&omap_device_pm_qos_nb);
+	if (!ret)
+		pr_err("omap_device: cannot add global notifier for dev PM QoS\n");
+
+	return ret;
 }
 core_initcall(omap_device_init);
-- 
1.7.7.6

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

* [PATCH 4/6] ARM: OMAP3: cpuidle: next C-state decision depends on the PM QoS MPU and CORE constraints
  2012-04-18 13:45 ` jean.pihet at newoldbits.com
@ 2012-04-18 13:45   ` jean.pihet at newoldbits.com
  -1 siblings, 0 replies; 22+ messages in thread
From: jean.pihet @ 2012-04-18 13:45 UTC (permalink / raw)
  To: linux-omap, paul, b-cousson, khilman, linux-arm-kernel; +Cc: Jean Pihet

From: Jean Pihet <j-pihet@ti.com>

The MPU latency figures for cpuidle include the MPU itself and also
the peripherals needed for the MPU to execute instructions (e.g.
main memory, caches, IRQ controller, MMU etc). On OMAP3 those
peripherals belong to the MPU and CORE power domains and so the
cpuidle C-states are a combination of MPU and CORE states.

This patch implements the relation between the cpuidle and per-
device PM QoS frameworks in the OMAP3 specific idle callbacks.

The chosen C-state shall satisfy the following conditions:
 . the 'valid' field is enabled,
 . it satisfies the enable_off_mode flag,
 . the next state for MPU and CORE power domains is not lower than the
   next state calculated by the per-device PM QoS.

Tested on OMAP3 Beagleboard in RET/OFF using wake-up latency constraints
on MPU, CORE and PER.

Signed-off-by: Jean Pihet <j-pihet@ti.com>
Reviewed-by: Kevin Hilman <khilman@ti.com>
---
 arch/arm/mach-omap2/cpuidle34xx.c |   59 ++++++++++++++++++++-----------------
 arch/arm/mach-omap2/pm.h          |   17 +++++++++-
 2 files changed, 47 insertions(+), 29 deletions(-)

diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c
index ff2dea3..2f95cfc 100644
--- a/arch/arm/mach-omap2/cpuidle34xx.c
+++ b/arch/arm/mach-omap2/cpuidle34xx.c
@@ -39,7 +39,7 @@
 #ifdef CONFIG_CPU_IDLE
 
 /*
- * The latencies/thresholds for various C states have
+ * The MPU latencies/thresholds for various C states have
  * to be configured from the respective board files.
  * These are some default values (which might not provide
  * the best power savings) used on boards which do not
@@ -74,22 +74,21 @@ struct omap3_idle_statedata omap3_idle_data[OMAP3_NUM_STATES];
 struct powerdomain *mpu_pd, *core_pd, *per_pd, *cam_pd;
 
 static int _cpuidle_allow_idle(struct powerdomain *pwrdm,
-				struct clockdomain *clkdm)
+			       struct clockdomain *clkdm)
 {
 	clkdm_allow_idle(clkdm);
 	return 0;
 }
 
 static int _cpuidle_deny_idle(struct powerdomain *pwrdm,
-				struct clockdomain *clkdm)
+			      struct clockdomain *clkdm)
 {
 	clkdm_deny_idle(clkdm);
 	return 0;
 }
 
 static int __omap3_enter_idle(struct cpuidle_device *dev,
-				struct cpuidle_driver *drv,
-				int index)
+			      struct cpuidle_driver *drv, int index)
 {
 	struct omap3_idle_statedata *cx =
 			cpuidle_get_statedata(&dev->states_usage[index]);
@@ -147,10 +146,13 @@ return_sleep_time:
  *
  * Called from the CPUidle framework to program the device to the
  * specified target state selected by the governor.
+ *
+ * Note: this function does not check for any pending activity or dependency
+ * between power domains states, so the caller shall check the parameters
+ * correctness.
  */
 static inline int omap3_enter_idle(struct cpuidle_device *dev,
-				struct cpuidle_driver *drv,
-				int index)
+				   struct cpuidle_driver *drv, int index)
 {
 	return cpuidle_wrap_enter(dev, drv, index, __omap3_enter_idle);
 }
@@ -165,18 +167,22 @@ static inline int omap3_enter_idle(struct cpuidle_device *dev,
  * to the caller. Else, this function searches for a lower c-state which is
  * still valid (as defined in omap3_power_states[]) and returns its index.
  *
- * A state is valid if the 'valid' field is enabled and
- * if it satisfies the enable_off_mode condition.
+ * A state is valid if:
+ * . the 'valid' field is enabled,
+ * . it satisfies the enable_off_mode flag,
+ * . the next state for MPU and CORE power domains is not lower than the
+ *   state programmed by the per-device PM QoS.
  */
 static int next_valid_state(struct cpuidle_device *dev,
-			struct cpuidle_driver *drv,
-				int index)
+			    struct cpuidle_driver *drv, int index)
 {
 	struct cpuidle_state_usage *curr_usage = &dev->states_usage[index];
 	struct cpuidle_state *curr = &drv->states[index];
 	struct omap3_idle_statedata *cx = cpuidle_get_statedata(curr_usage);
 	u32 mpu_deepest_state = PWRDM_FUNC_PWRST_CSWR;
 	u32 core_deepest_state = PWRDM_FUNC_PWRST_CSWR;
+	u32 mpu_pm_qos_next_state = mpu_pd->wkup_lat_next_state;
+	u32 core_pm_qos_next_state = core_pd->wkup_lat_next_state;
 	int next_index = -1;
 
 	if (enable_off_mode) {
@@ -193,7 +199,9 @@ static int next_valid_state(struct cpuidle_device *dev,
 	/* Check if current state is valid */
 	if ((cx->valid) &&
 	    (cx->mpu_state >= mpu_deepest_state) &&
-	    (cx->core_state >= core_deepest_state)) {
+	    (cx->core_state >= core_deepest_state) &&
+	    (cx->mpu_state >= mpu_pm_qos_next_state) &&
+	    (cx->core_state >= core_pm_qos_next_state)) {
 		return index;
 	} else {
 		int idx = OMAP3_NUM_STATES - 1;
@@ -218,7 +226,9 @@ static int next_valid_state(struct cpuidle_device *dev,
 			cx = cpuidle_get_statedata(&dev->states_usage[idx]);
 			if ((cx->valid) &&
 			    (cx->mpu_state >= mpu_deepest_state) &&
-			    (cx->core_state >= core_deepest_state)) {
+			    (cx->core_state >= core_deepest_state) &&
+			    (cx->mpu_state >= mpu_pm_qos_next_state) &&
+			    (cx->core_state >= core_pm_qos_next_state)) {
 				next_index = idx;
 				break;
 			}
@@ -239,12 +249,15 @@ static int next_valid_state(struct cpuidle_device *dev,
  * @drv: cpuidle driver
  * @index: array index of target state to be programmed
  *
- * This function checks for any pending activity and then programs
- * the device to the specified or a safer state.
+ * Called from the CPUidle framework to program the device to the
+ * specified target state selected by the governor.
+ *
+ * This function checks for any pending activity or dependency between
+ * power domains states and then programs the device to the specified
+ * or a safer state.
  */
 static int omap3_enter_idle_bm(struct cpuidle_device *dev,
-				struct cpuidle_driver *drv,
-			       int index)
+			       struct cpuidle_driver *drv, int index)
 {
 	int new_state_idx;
 	u32 core_next_state, per_next_state = 0, per_saved_state = 0;
@@ -260,19 +273,13 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
 		goto select_state;
 	}
 
-	/*
-	 * FIXME: we currently manage device-specific idle states
-	 *        for PER and CORE in combination with CPU-specific
-	 *        idle states.  This is wrong, and device-specific
-	 *        idle management needs to be separated out into
-	 *        its own code.
-	 */
+	new_state_idx = next_valid_state(dev, drv, index);
 
 	/*
 	 * Prevent PER off if CORE is not in retention or off as this
 	 * would disable PER wakeups completely.
 	 */
-	cx = cpuidle_get_statedata(&dev->states_usage[index]);
+	cx = cpuidle_get_statedata(&dev->states_usage[new_state_idx]);
 	core_next_state = cx->core_state;
 	per_next_state = per_saved_state = pwrdm_read_next_func_pwrst(per_pd);
 	if ((per_next_state == PWRDM_FUNC_PWRST_OFF) &&
@@ -283,8 +290,6 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
 	if (per_next_state != per_saved_state)
 		omap_set_pwrdm_state(per_pd, per_next_state);
 
-	new_state_idx = next_valid_state(dev, drv, index);
-
 select_state:
 	ret = omap3_enter_idle(dev, drv, new_state_idx);
 
diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
index 36fa90b..c0b196b 100644
--- a/arch/arm/mach-omap2/pm.h
+++ b/arch/arm/mach-omap2/pm.h
@@ -45,9 +45,22 @@ static inline int omap4_opp_init(void)
  * omap3_pm_init_cpuidle
  */
 struct cpuidle_params {
-	u32 exit_latency;	/* exit_latency = sleep + wake-up latencies */
+	/*
+	 * exit_latency = sleep + wake-up latencies of the MPU,
+	 * which include the MPU itself and the peripherals needed
+	 * for the MPU to execute instructions (e.g. main memory,
+	 * caches, IRQ controller, MMU etc). Some of those peripherals
+	 * can belong to other power domains than the MPU subsystem and so
+	 * the corresponding latencies must be included in this figure.
+	 */
+	u32 exit_latency;
+	/*
+	 * target_residency: required amount of time in the C state
+	 * to break even on energy cost
+	 */
 	u32 target_residency;
-	u8 valid;		/* validates the C-state */
+	/* validates the C-state on the given board */
+	u8 valid;
 };
 
 #if defined(CONFIG_PM) && defined(CONFIG_CPU_IDLE)
-- 
1.7.7.6


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

* [PATCH 4/6] ARM: OMAP3: cpuidle: next C-state decision depends on the PM QoS MPU and CORE constraints
@ 2012-04-18 13:45   ` jean.pihet at newoldbits.com
  0 siblings, 0 replies; 22+ messages in thread
From: jean.pihet at newoldbits.com @ 2012-04-18 13:45 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jean Pihet <j-pihet@ti.com>

The MPU latency figures for cpuidle include the MPU itself and also
the peripherals needed for the MPU to execute instructions (e.g.
main memory, caches, IRQ controller, MMU etc). On OMAP3 those
peripherals belong to the MPU and CORE power domains and so the
cpuidle C-states are a combination of MPU and CORE states.

This patch implements the relation between the cpuidle and per-
device PM QoS frameworks in the OMAP3 specific idle callbacks.

The chosen C-state shall satisfy the following conditions:
 . the 'valid' field is enabled,
 . it satisfies the enable_off_mode flag,
 . the next state for MPU and CORE power domains is not lower than the
   next state calculated by the per-device PM QoS.

Tested on OMAP3 Beagleboard in RET/OFF using wake-up latency constraints
on MPU, CORE and PER.

Signed-off-by: Jean Pihet <j-pihet@ti.com>
Reviewed-by: Kevin Hilman <khilman@ti.com>
---
 arch/arm/mach-omap2/cpuidle34xx.c |   59 ++++++++++++++++++++-----------------
 arch/arm/mach-omap2/pm.h          |   17 +++++++++-
 2 files changed, 47 insertions(+), 29 deletions(-)

diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c
index ff2dea3..2f95cfc 100644
--- a/arch/arm/mach-omap2/cpuidle34xx.c
+++ b/arch/arm/mach-omap2/cpuidle34xx.c
@@ -39,7 +39,7 @@
 #ifdef CONFIG_CPU_IDLE
 
 /*
- * The latencies/thresholds for various C states have
+ * The MPU latencies/thresholds for various C states have
  * to be configured from the respective board files.
  * These are some default values (which might not provide
  * the best power savings) used on boards which do not
@@ -74,22 +74,21 @@ struct omap3_idle_statedata omap3_idle_data[OMAP3_NUM_STATES];
 struct powerdomain *mpu_pd, *core_pd, *per_pd, *cam_pd;
 
 static int _cpuidle_allow_idle(struct powerdomain *pwrdm,
-				struct clockdomain *clkdm)
+			       struct clockdomain *clkdm)
 {
 	clkdm_allow_idle(clkdm);
 	return 0;
 }
 
 static int _cpuidle_deny_idle(struct powerdomain *pwrdm,
-				struct clockdomain *clkdm)
+			      struct clockdomain *clkdm)
 {
 	clkdm_deny_idle(clkdm);
 	return 0;
 }
 
 static int __omap3_enter_idle(struct cpuidle_device *dev,
-				struct cpuidle_driver *drv,
-				int index)
+			      struct cpuidle_driver *drv, int index)
 {
 	struct omap3_idle_statedata *cx =
 			cpuidle_get_statedata(&dev->states_usage[index]);
@@ -147,10 +146,13 @@ return_sleep_time:
  *
  * Called from the CPUidle framework to program the device to the
  * specified target state selected by the governor.
+ *
+ * Note: this function does not check for any pending activity or dependency
+ * between power domains states, so the caller shall check the parameters
+ * correctness.
  */
 static inline int omap3_enter_idle(struct cpuidle_device *dev,
-				struct cpuidle_driver *drv,
-				int index)
+				   struct cpuidle_driver *drv, int index)
 {
 	return cpuidle_wrap_enter(dev, drv, index, __omap3_enter_idle);
 }
@@ -165,18 +167,22 @@ static inline int omap3_enter_idle(struct cpuidle_device *dev,
  * to the caller. Else, this function searches for a lower c-state which is
  * still valid (as defined in omap3_power_states[]) and returns its index.
  *
- * A state is valid if the 'valid' field is enabled and
- * if it satisfies the enable_off_mode condition.
+ * A state is valid if:
+ * . the 'valid' field is enabled,
+ * . it satisfies the enable_off_mode flag,
+ * . the next state for MPU and CORE power domains is not lower than the
+ *   state programmed by the per-device PM QoS.
  */
 static int next_valid_state(struct cpuidle_device *dev,
-			struct cpuidle_driver *drv,
-				int index)
+			    struct cpuidle_driver *drv, int index)
 {
 	struct cpuidle_state_usage *curr_usage = &dev->states_usage[index];
 	struct cpuidle_state *curr = &drv->states[index];
 	struct omap3_idle_statedata *cx = cpuidle_get_statedata(curr_usage);
 	u32 mpu_deepest_state = PWRDM_FUNC_PWRST_CSWR;
 	u32 core_deepest_state = PWRDM_FUNC_PWRST_CSWR;
+	u32 mpu_pm_qos_next_state = mpu_pd->wkup_lat_next_state;
+	u32 core_pm_qos_next_state = core_pd->wkup_lat_next_state;
 	int next_index = -1;
 
 	if (enable_off_mode) {
@@ -193,7 +199,9 @@ static int next_valid_state(struct cpuidle_device *dev,
 	/* Check if current state is valid */
 	if ((cx->valid) &&
 	    (cx->mpu_state >= mpu_deepest_state) &&
-	    (cx->core_state >= core_deepest_state)) {
+	    (cx->core_state >= core_deepest_state) &&
+	    (cx->mpu_state >= mpu_pm_qos_next_state) &&
+	    (cx->core_state >= core_pm_qos_next_state)) {
 		return index;
 	} else {
 		int idx = OMAP3_NUM_STATES - 1;
@@ -218,7 +226,9 @@ static int next_valid_state(struct cpuidle_device *dev,
 			cx = cpuidle_get_statedata(&dev->states_usage[idx]);
 			if ((cx->valid) &&
 			    (cx->mpu_state >= mpu_deepest_state) &&
-			    (cx->core_state >= core_deepest_state)) {
+			    (cx->core_state >= core_deepest_state) &&
+			    (cx->mpu_state >= mpu_pm_qos_next_state) &&
+			    (cx->core_state >= core_pm_qos_next_state)) {
 				next_index = idx;
 				break;
 			}
@@ -239,12 +249,15 @@ static int next_valid_state(struct cpuidle_device *dev,
  * @drv: cpuidle driver
  * @index: array index of target state to be programmed
  *
- * This function checks for any pending activity and then programs
- * the device to the specified or a safer state.
+ * Called from the CPUidle framework to program the device to the
+ * specified target state selected by the governor.
+ *
+ * This function checks for any pending activity or dependency between
+ * power domains states and then programs the device to the specified
+ * or a safer state.
  */
 static int omap3_enter_idle_bm(struct cpuidle_device *dev,
-				struct cpuidle_driver *drv,
-			       int index)
+			       struct cpuidle_driver *drv, int index)
 {
 	int new_state_idx;
 	u32 core_next_state, per_next_state = 0, per_saved_state = 0;
@@ -260,19 +273,13 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
 		goto select_state;
 	}
 
-	/*
-	 * FIXME: we currently manage device-specific idle states
-	 *        for PER and CORE in combination with CPU-specific
-	 *        idle states.  This is wrong, and device-specific
-	 *        idle management needs to be separated out into
-	 *        its own code.
-	 */
+	new_state_idx = next_valid_state(dev, drv, index);
 
 	/*
 	 * Prevent PER off if CORE is not in retention or off as this
 	 * would disable PER wakeups completely.
 	 */
-	cx = cpuidle_get_statedata(&dev->states_usage[index]);
+	cx = cpuidle_get_statedata(&dev->states_usage[new_state_idx]);
 	core_next_state = cx->core_state;
 	per_next_state = per_saved_state = pwrdm_read_next_func_pwrst(per_pd);
 	if ((per_next_state == PWRDM_FUNC_PWRST_OFF) &&
@@ -283,8 +290,6 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
 	if (per_next_state != per_saved_state)
 		omap_set_pwrdm_state(per_pd, per_next_state);
 
-	new_state_idx = next_valid_state(dev, drv, index);
-
 select_state:
 	ret = omap3_enter_idle(dev, drv, new_state_idx);
 
diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
index 36fa90b..c0b196b 100644
--- a/arch/arm/mach-omap2/pm.h
+++ b/arch/arm/mach-omap2/pm.h
@@ -45,9 +45,22 @@ static inline int omap4_opp_init(void)
  * omap3_pm_init_cpuidle
  */
 struct cpuidle_params {
-	u32 exit_latency;	/* exit_latency = sleep + wake-up latencies */
+	/*
+	 * exit_latency = sleep + wake-up latencies of the MPU,
+	 * which include the MPU itself and the peripherals needed
+	 * for the MPU to execute instructions (e.g. main memory,
+	 * caches, IRQ controller, MMU etc). Some of those peripherals
+	 * can belong to other power domains than the MPU subsystem and so
+	 * the corresponding latencies must be included in this figure.
+	 */
+	u32 exit_latency;
+	/*
+	 * target_residency: required amount of time in the C state
+	 * to break even on energy cost
+	 */
 	u32 target_residency;
-	u8 valid;		/* validates the C-state */
+	/* validates the C-state on the given board */
+	u8 valid;
 };
 
 #if defined(CONFIG_PM) && defined(CONFIG_CPU_IDLE)
-- 
1.7.7.6

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

* [PATCH 5/6] ARM: OMAP3: update cpuidle latency and threshold figures
  2012-04-18 13:45 ` jean.pihet at newoldbits.com
@ 2012-04-18 13:45   ` jean.pihet at newoldbits.com
  -1 siblings, 0 replies; 22+ messages in thread
From: jean.pihet @ 2012-04-18 13:45 UTC (permalink / raw)
  To: linux-omap, paul, b-cousson, khilman, linux-arm-kernel; +Cc: Jean Pihet

From: Jean Pihet <j-pihet@ti.com>

Update the data from the measurements performed at HW and SW levels.

Cf. http://www.omappedia.org/wiki/Power_Management_Device_Latencies_Measurement
for a detailed explanation on where are the numbers coming from.

ToDo:
- Measure the wake-up latencies for all power domains for OMAP3
- Correct some numbers when sys_clkreq and sys_offmode are supported

Signed-off-by: Jean Pihet <j-pihet@ti.com>
Reviewed-by: Kevin Hilman <khilman@ti.com>
---
 arch/arm/mach-omap2/cpuidle34xx.c |   52 +++++++++++++++++++++++-------------
 1 files changed, 33 insertions(+), 19 deletions(-)

diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c
index 2f95cfc..e406d7b 100644
--- a/arch/arm/mach-omap2/cpuidle34xx.c
+++ b/arch/arm/mach-omap2/cpuidle34xx.c
@@ -39,27 +39,41 @@
 #ifdef CONFIG_CPU_IDLE
 
 /*
- * The MPU latencies/thresholds for various C states have
- * to be configured from the respective board files.
- * These are some default values (which might not provide
- * the best power savings) used on boards which do not
- * pass these details from the board file.
+ * The MPU latency and threshold values for the C-states are the worst case
+ * values from the HW and SW, as described in details at
+ * http://www.omappedia.org/wiki/Power_Management_Device_Latencies_Measurement#cpuidle_results
+ *
+ * Measurements conditions and remarks:
+ *  . the measurements have been performed at OPP50
+ *  . the sys_offmode signal is not supported and so not used for the
+ *    measurements. Instead the latency and threshold values for C9 are
+ *    corrected with the value for Triton 2, which is 11.5ms
+ *  . the sys_clkreq signal is not used and so a correction is needed - TBD
+ *  . the sys_clkoff signal is supported, this value need to be corrected with
+ *    the correct value of SYSCLK on/off timings (1ms for sysclk on, 2.5ms
+ *    for sysclk off)
+ *  . in order to force the cpuidle algorithm to chose the power efficient
+ *    C-states (C1, C3, C5, C7) in preference, the other C-states have a
+ *    threshold value equal to the next power efficient C-state
+ * 
+ * The latency and threshold values can be overriden by data from the board
+ * files, using omap3_pm_init_cpuidle.
  */
 static struct cpuidle_params cpuidle_params_table[] = {
-	/* C1 */
-	{2 + 2, 5, 1},
-	/* C2 */
-	{10 + 10, 30, 1},
-	/* C3 */
-	{50 + 50, 300, 1},
-	/* C4 */
-	{1500 + 1800, 4000, 1},
-	/* C5 */
-	{2500 + 7500, 12000, 1},
-	/* C6 */
-	{3000 + 8500, 15000, 1},
-	/* C7 */
-	{10000 + 30000, 300000, 1},
+	/* C1 . MPU WFI + Core active */
+	{73 + 78, 152, 1},
+	/* C2 . MPU WFI + Core inactive */
+	{165 + 88, 345, 1},
+	/* C3 . MPU CSWR + Core inactive */
+	{163 + 182, 345, 1},
+	/* C4 . MPU OFF + Core inactive */
+	{2852 + 605, 150000, 1},
+	/* C5 . MPU RET + Core RET */
+	{800 + 366, 2120, 1},
+	/* C6 . MPU OFF + Core RET */
+	{4080 + 801, 215000, 1},
+	/* C7 . MPU OFF + Core OFF */
+	{4300 + 13000, 215000, 1},
 };
 #define OMAP3_NUM_STATES ARRAY_SIZE(cpuidle_params_table)
 
-- 
1.7.7.6


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

* [PATCH 5/6] ARM: OMAP3: update cpuidle latency and threshold figures
@ 2012-04-18 13:45   ` jean.pihet at newoldbits.com
  0 siblings, 0 replies; 22+ messages in thread
From: jean.pihet at newoldbits.com @ 2012-04-18 13:45 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jean Pihet <j-pihet@ti.com>

Update the data from the measurements performed at HW and SW levels.

Cf. http://www.omappedia.org/wiki/Power_Management_Device_Latencies_Measurement
for a detailed explanation on where are the numbers coming from.

ToDo:
- Measure the wake-up latencies for all power domains for OMAP3
- Correct some numbers when sys_clkreq and sys_offmode are supported

Signed-off-by: Jean Pihet <j-pihet@ti.com>
Reviewed-by: Kevin Hilman <khilman@ti.com>
---
 arch/arm/mach-omap2/cpuidle34xx.c |   52 +++++++++++++++++++++++-------------
 1 files changed, 33 insertions(+), 19 deletions(-)

diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c
index 2f95cfc..e406d7b 100644
--- a/arch/arm/mach-omap2/cpuidle34xx.c
+++ b/arch/arm/mach-omap2/cpuidle34xx.c
@@ -39,27 +39,41 @@
 #ifdef CONFIG_CPU_IDLE
 
 /*
- * The MPU latencies/thresholds for various C states have
- * to be configured from the respective board files.
- * These are some default values (which might not provide
- * the best power savings) used on boards which do not
- * pass these details from the board file.
+ * The MPU latency and threshold values for the C-states are the worst case
+ * values from the HW and SW, as described in details at
+ * http://www.omappedia.org/wiki/Power_Management_Device_Latencies_Measurement#cpuidle_results
+ *
+ * Measurements conditions and remarks:
+ *  . the measurements have been performed at OPP50
+ *  . the sys_offmode signal is not supported and so not used for the
+ *    measurements. Instead the latency and threshold values for C9 are
+ *    corrected with the value for Triton 2, which is 11.5ms
+ *  . the sys_clkreq signal is not used and so a correction is needed - TBD
+ *  . the sys_clkoff signal is supported, this value need to be corrected with
+ *    the correct value of SYSCLK on/off timings (1ms for sysclk on, 2.5ms
+ *    for sysclk off)
+ *  . in order to force the cpuidle algorithm to chose the power efficient
+ *    C-states (C1, C3, C5, C7) in preference, the other C-states have a
+ *    threshold value equal to the next power efficient C-state
+ * 
+ * The latency and threshold values can be overriden by data from the board
+ * files, using omap3_pm_init_cpuidle.
  */
 static struct cpuidle_params cpuidle_params_table[] = {
-	/* C1 */
-	{2 + 2, 5, 1},
-	/* C2 */
-	{10 + 10, 30, 1},
-	/* C3 */
-	{50 + 50, 300, 1},
-	/* C4 */
-	{1500 + 1800, 4000, 1},
-	/* C5 */
-	{2500 + 7500, 12000, 1},
-	/* C6 */
-	{3000 + 8500, 15000, 1},
-	/* C7 */
-	{10000 + 30000, 300000, 1},
+	/* C1 . MPU WFI + Core active */
+	{73 + 78, 152, 1},
+	/* C2 . MPU WFI + Core inactive */
+	{165 + 88, 345, 1},
+	/* C3 . MPU CSWR + Core inactive */
+	{163 + 182, 345, 1},
+	/* C4 . MPU OFF + Core inactive */
+	{2852 + 605, 150000, 1},
+	/* C5 . MPU RET + Core RET */
+	{800 + 366, 2120, 1},
+	/* C6 . MPU OFF + Core RET */
+	{4080 + 801, 215000, 1},
+	/* C7 . MPU OFF + Core OFF */
+	{4300 + 13000, 215000, 1},
 };
 #define OMAP3_NUM_STATES ARRAY_SIZE(cpuidle_params_table)
 
-- 
1.7.7.6

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

* [PATCH 6/6] ARM: OMAP3: powerdomain data: add wake-up latency figures
  2012-04-18 13:45 ` jean.pihet at newoldbits.com
@ 2012-04-18 13:45   ` jean.pihet at newoldbits.com
  -1 siblings, 0 replies; 22+ messages in thread
From: jean.pihet @ 2012-04-18 13:45 UTC (permalink / raw)
  To: linux-omap, paul, b-cousson, khilman, linux-arm-kernel; +Cc: Jean Pihet

From: Jean Pihet <j-pihet@ti.com>

Figures are added to the power domains structs for RET and OFF modes.

Note: the latency figures for MPU, PER, CORE, NEON have been obtained
from actual measurements.
The latency figures for the other power domains are preliminary and
shall be added.

Cf. http://www.omappedia.org/wiki/Power_Management_Device_Latencies_Measurement
for a detailed explanation on where are the numbers coming from.

Tested on OMAP3 Beagleboard in RET/OFF using wake-up latency constraints
on MPU, CORE and PER.

Signed-off-by: Jean Pihet <j-pihet@ti.com>
Reviewed-by: Kevin Hilman <khilman@ti.com>
---
 arch/arm/mach-omap2/powerdomains3xxx_data.c |   83 +++++++++++++++++++++++++++
 1 files changed, 83 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/powerdomains3xxx_data.c b/arch/arm/mach-omap2/powerdomains3xxx_data.c
index b7ea468..34103f81 100644
--- a/arch/arm/mach-omap2/powerdomains3xxx_data.c
+++ b/arch/arm/mach-omap2/powerdomains3xxx_data.c
@@ -32,6 +32,19 @@
 
 /*
  * Powerdomains
+ *
+ * The wakeup_lat values are derived from HW and SW measurements on
+ * the actual target. For more details cf.
+ * http://www.omappedia.org/wiki/Power_Management_Device_Latencies_Measurement#Results_for_individual_power_domains
+ *
+ * Note: the latency figures for MPU, PER, CORE, NEON have been obtained
+ * from actual measurements.
+ * The latency figures for the other power domains are preliminary and
+ * shall be added.
+ *
+ * Note: only the SW restore timing values are taken into account.
+ * The HW impact of the sys_clkreq and sys_offmode signals is not taken
+ * into account - TDB
  */
 
 static struct powerdomain iva2_pwrdm = {
@@ -52,6 +65,13 @@ static struct powerdomain iva2_pwrdm = {
 		[2] = PWRSTS_OFF_ON,
 		[3] = PWRSTS_ON,
 	},
+	.wakeup_lat = {
+		[PWRDM_FUNC_PWRST_OFF] = 1100,
+		[PWRDM_FUNC_PWRST_OSWR] = UNSUP_STATE,
+		[PWRDM_FUNC_PWRST_CSWR] = 350,
+		[PWRDM_FUNC_PWRST_INACTIVE] = UNSUP_STATE,
+		[PWRDM_FUNC_PWRST_ON] = 0,
+	},
 	.voltdm           = { .name = "mpu_iva" },
 };
 
@@ -68,6 +88,13 @@ static struct powerdomain mpu_3xxx_pwrdm = {
 	.pwrsts_mem_on	  = {
 		[0] = PWRSTS_OFF_ON,
 	},
+	.wakeup_lat = {
+		[PWRDM_FUNC_PWRST_OFF] = 1830,
+		[PWRDM_FUNC_PWRST_OSWR] = UNSUP_STATE,
+		[PWRDM_FUNC_PWRST_CSWR] = 121,
+		[PWRDM_FUNC_PWRST_INACTIVE] = UNSUP_STATE,
+		[PWRDM_FUNC_PWRST_ON] = 0,
+	},
 	.voltdm           = { .name = "mpu_iva" },
 };
 
@@ -95,6 +122,13 @@ static struct powerdomain core_3xxx_pre_es3_1_pwrdm = {
 		[0] = PWRSTS_OFF_RET_ON, /* MEM1ONSTATE */
 		[1] = PWRSTS_OFF_RET_ON, /* MEM2ONSTATE */
 	},
+	.wakeup_lat = {
+		[PWRDM_FUNC_PWRST_OFF] = 3082,
+		[PWRDM_FUNC_PWRST_OSWR] = UNSUP_STATE,
+		[PWRDM_FUNC_PWRST_CSWR] = 153,
+		[PWRDM_FUNC_PWRST_INACTIVE] = UNSUP_STATE,
+		[PWRDM_FUNC_PWRST_ON] = 0,
+	},
 	.voltdm           = { .name = "core" },
 };
 
@@ -117,6 +151,13 @@ static struct powerdomain core_3xxx_es3_1_pwrdm = {
 		[0] = PWRSTS_OFF_RET_ON, /* MEM1ONSTATE */
 		[1] = PWRSTS_OFF_RET_ON, /* MEM2ONSTATE */
 	},
+	.wakeup_lat = {
+		[PWRDM_FUNC_PWRST_OFF] = 3082,
+		[PWRDM_FUNC_PWRST_OSWR] = UNSUP_STATE,
+		[PWRDM_FUNC_PWRST_CSWR] = 153,
+		[PWRDM_FUNC_PWRST_INACTIVE] = UNSUP_STATE,
+		[PWRDM_FUNC_PWRST_ON] = 0,
+	},
 	.voltdm           = { .name = "core" },
 };
 
@@ -132,6 +173,13 @@ static struct powerdomain dss_pwrdm = {
 	.pwrsts_mem_on	  = {
 		[0] = PWRSTS_ON,  /* MEMONSTATE */
 	},
+	.wakeup_lat = {
+		[PWRDM_FUNC_PWRST_OFF] = 70,
+		[PWRDM_FUNC_PWRST_OSWR] = UNSUP_STATE,
+		[PWRDM_FUNC_PWRST_CSWR] = 20,
+		[PWRDM_FUNC_PWRST_INACTIVE] = UNSUP_STATE,
+		[PWRDM_FUNC_PWRST_ON] = 0,
+	},
 	.voltdm           = { .name = "core" },
 };
 
@@ -153,6 +201,13 @@ static struct powerdomain sgx_pwrdm = {
 	.pwrsts_mem_on	  = {
 		[0] = PWRSTS_ON,  /* MEMONSTATE */
 	},
+	.wakeup_lat = {
+		[PWRDM_FUNC_PWRST_OFF] = 1000,
+		[PWRDM_FUNC_PWRST_OSWR] = UNSUP_STATE,
+		[PWRDM_FUNC_PWRST_CSWR] = UNSUP_STATE,
+		[PWRDM_FUNC_PWRST_INACTIVE] = UNSUP_STATE,
+		[PWRDM_FUNC_PWRST_ON] = 0,
+	},
 	.voltdm           = { .name = "core" },
 };
 
@@ -168,6 +223,13 @@ static struct powerdomain cam_pwrdm = {
 	.pwrsts_mem_on	  = {
 		[0] = PWRSTS_ON,  /* MEMONSTATE */
 	},
+	.wakeup_lat = {
+		[PWRDM_FUNC_PWRST_OFF] = 850,
+		[PWRDM_FUNC_PWRST_OSWR] = UNSUP_STATE,
+		[PWRDM_FUNC_PWRST_CSWR] = 35,
+		[PWRDM_FUNC_PWRST_INACTIVE] = UNSUP_STATE,
+		[PWRDM_FUNC_PWRST_ON] = 0,
+	},
 	.voltdm           = { .name = "core" },
 };
 
@@ -183,6 +245,13 @@ static struct powerdomain per_pwrdm = {
 	.pwrsts_mem_on	  = {
 		[0] = PWRSTS_ON,  /* MEMONSTATE */
 	},
+	.wakeup_lat = {
+		[PWRDM_FUNC_PWRST_OFF] = 671,
+		[PWRDM_FUNC_PWRST_OSWR] = UNSUP_STATE,
+		[PWRDM_FUNC_PWRST_CSWR] = 31,
+		[PWRDM_FUNC_PWRST_INACTIVE] = UNSUP_STATE,
+		[PWRDM_FUNC_PWRST_ON] = 0,
+	},
 	.voltdm           = { .name = "core" },
 };
 
@@ -197,6 +266,13 @@ static struct powerdomain neon_pwrdm = {
 	.prcm_offs	  = OMAP3430_NEON_MOD,
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_RET,
+	.wakeup_lat = {
+		[PWRDM_FUNC_PWRST_OFF] = 0,
+		[PWRDM_FUNC_PWRST_OSWR] = UNSUP_STATE,
+		[PWRDM_FUNC_PWRST_CSWR] = 0,
+		[PWRDM_FUNC_PWRST_INACTIVE] = UNSUP_STATE,
+		[PWRDM_FUNC_PWRST_ON] = 0,
+	},
 	.voltdm           = { .name = "mpu_iva" },
 };
 
@@ -219,6 +295,13 @@ static struct powerdomain usbhost_pwrdm = {
 	.pwrsts_mem_on	  = {
 		[0] = PWRSTS_ON,  /* MEMONSTATE */
 	},
+	.wakeup_lat = {
+		[PWRDM_FUNC_PWRST_OFF] = 800,
+		[PWRDM_FUNC_PWRST_OSWR] = UNSUP_STATE,
+		[PWRDM_FUNC_PWRST_CSWR] = 150,
+		[PWRDM_FUNC_PWRST_INACTIVE] = UNSUP_STATE,
+		[PWRDM_FUNC_PWRST_ON] = 0,
+	},
 	.voltdm           = { .name = "core" },
 };
 
-- 
1.7.7.6


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

* [PATCH 6/6] ARM: OMAP3: powerdomain data: add wake-up latency figures
@ 2012-04-18 13:45   ` jean.pihet at newoldbits.com
  0 siblings, 0 replies; 22+ messages in thread
From: jean.pihet at newoldbits.com @ 2012-04-18 13:45 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jean Pihet <j-pihet@ti.com>

Figures are added to the power domains structs for RET and OFF modes.

Note: the latency figures for MPU, PER, CORE, NEON have been obtained
from actual measurements.
The latency figures for the other power domains are preliminary and
shall be added.

Cf. http://www.omappedia.org/wiki/Power_Management_Device_Latencies_Measurement
for a detailed explanation on where are the numbers coming from.

Tested on OMAP3 Beagleboard in RET/OFF using wake-up latency constraints
on MPU, CORE and PER.

Signed-off-by: Jean Pihet <j-pihet@ti.com>
Reviewed-by: Kevin Hilman <khilman@ti.com>
---
 arch/arm/mach-omap2/powerdomains3xxx_data.c |   83 +++++++++++++++++++++++++++
 1 files changed, 83 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/powerdomains3xxx_data.c b/arch/arm/mach-omap2/powerdomains3xxx_data.c
index b7ea468..34103f81 100644
--- a/arch/arm/mach-omap2/powerdomains3xxx_data.c
+++ b/arch/arm/mach-omap2/powerdomains3xxx_data.c
@@ -32,6 +32,19 @@
 
 /*
  * Powerdomains
+ *
+ * The wakeup_lat values are derived from HW and SW measurements on
+ * the actual target. For more details cf.
+ * http://www.omappedia.org/wiki/Power_Management_Device_Latencies_Measurement#Results_for_individual_power_domains
+ *
+ * Note: the latency figures for MPU, PER, CORE, NEON have been obtained
+ * from actual measurements.
+ * The latency figures for the other power domains are preliminary and
+ * shall be added.
+ *
+ * Note: only the SW restore timing values are taken into account.
+ * The HW impact of the sys_clkreq and sys_offmode signals is not taken
+ * into account - TDB
  */
 
 static struct powerdomain iva2_pwrdm = {
@@ -52,6 +65,13 @@ static struct powerdomain iva2_pwrdm = {
 		[2] = PWRSTS_OFF_ON,
 		[3] = PWRSTS_ON,
 	},
+	.wakeup_lat = {
+		[PWRDM_FUNC_PWRST_OFF] = 1100,
+		[PWRDM_FUNC_PWRST_OSWR] = UNSUP_STATE,
+		[PWRDM_FUNC_PWRST_CSWR] = 350,
+		[PWRDM_FUNC_PWRST_INACTIVE] = UNSUP_STATE,
+		[PWRDM_FUNC_PWRST_ON] = 0,
+	},
 	.voltdm           = { .name = "mpu_iva" },
 };
 
@@ -68,6 +88,13 @@ static struct powerdomain mpu_3xxx_pwrdm = {
 	.pwrsts_mem_on	  = {
 		[0] = PWRSTS_OFF_ON,
 	},
+	.wakeup_lat = {
+		[PWRDM_FUNC_PWRST_OFF] = 1830,
+		[PWRDM_FUNC_PWRST_OSWR] = UNSUP_STATE,
+		[PWRDM_FUNC_PWRST_CSWR] = 121,
+		[PWRDM_FUNC_PWRST_INACTIVE] = UNSUP_STATE,
+		[PWRDM_FUNC_PWRST_ON] = 0,
+	},
 	.voltdm           = { .name = "mpu_iva" },
 };
 
@@ -95,6 +122,13 @@ static struct powerdomain core_3xxx_pre_es3_1_pwrdm = {
 		[0] = PWRSTS_OFF_RET_ON, /* MEM1ONSTATE */
 		[1] = PWRSTS_OFF_RET_ON, /* MEM2ONSTATE */
 	},
+	.wakeup_lat = {
+		[PWRDM_FUNC_PWRST_OFF] = 3082,
+		[PWRDM_FUNC_PWRST_OSWR] = UNSUP_STATE,
+		[PWRDM_FUNC_PWRST_CSWR] = 153,
+		[PWRDM_FUNC_PWRST_INACTIVE] = UNSUP_STATE,
+		[PWRDM_FUNC_PWRST_ON] = 0,
+	},
 	.voltdm           = { .name = "core" },
 };
 
@@ -117,6 +151,13 @@ static struct powerdomain core_3xxx_es3_1_pwrdm = {
 		[0] = PWRSTS_OFF_RET_ON, /* MEM1ONSTATE */
 		[1] = PWRSTS_OFF_RET_ON, /* MEM2ONSTATE */
 	},
+	.wakeup_lat = {
+		[PWRDM_FUNC_PWRST_OFF] = 3082,
+		[PWRDM_FUNC_PWRST_OSWR] = UNSUP_STATE,
+		[PWRDM_FUNC_PWRST_CSWR] = 153,
+		[PWRDM_FUNC_PWRST_INACTIVE] = UNSUP_STATE,
+		[PWRDM_FUNC_PWRST_ON] = 0,
+	},
 	.voltdm           = { .name = "core" },
 };
 
@@ -132,6 +173,13 @@ static struct powerdomain dss_pwrdm = {
 	.pwrsts_mem_on	  = {
 		[0] = PWRSTS_ON,  /* MEMONSTATE */
 	},
+	.wakeup_lat = {
+		[PWRDM_FUNC_PWRST_OFF] = 70,
+		[PWRDM_FUNC_PWRST_OSWR] = UNSUP_STATE,
+		[PWRDM_FUNC_PWRST_CSWR] = 20,
+		[PWRDM_FUNC_PWRST_INACTIVE] = UNSUP_STATE,
+		[PWRDM_FUNC_PWRST_ON] = 0,
+	},
 	.voltdm           = { .name = "core" },
 };
 
@@ -153,6 +201,13 @@ static struct powerdomain sgx_pwrdm = {
 	.pwrsts_mem_on	  = {
 		[0] = PWRSTS_ON,  /* MEMONSTATE */
 	},
+	.wakeup_lat = {
+		[PWRDM_FUNC_PWRST_OFF] = 1000,
+		[PWRDM_FUNC_PWRST_OSWR] = UNSUP_STATE,
+		[PWRDM_FUNC_PWRST_CSWR] = UNSUP_STATE,
+		[PWRDM_FUNC_PWRST_INACTIVE] = UNSUP_STATE,
+		[PWRDM_FUNC_PWRST_ON] = 0,
+	},
 	.voltdm           = { .name = "core" },
 };
 
@@ -168,6 +223,13 @@ static struct powerdomain cam_pwrdm = {
 	.pwrsts_mem_on	  = {
 		[0] = PWRSTS_ON,  /* MEMONSTATE */
 	},
+	.wakeup_lat = {
+		[PWRDM_FUNC_PWRST_OFF] = 850,
+		[PWRDM_FUNC_PWRST_OSWR] = UNSUP_STATE,
+		[PWRDM_FUNC_PWRST_CSWR] = 35,
+		[PWRDM_FUNC_PWRST_INACTIVE] = UNSUP_STATE,
+		[PWRDM_FUNC_PWRST_ON] = 0,
+	},
 	.voltdm           = { .name = "core" },
 };
 
@@ -183,6 +245,13 @@ static struct powerdomain per_pwrdm = {
 	.pwrsts_mem_on	  = {
 		[0] = PWRSTS_ON,  /* MEMONSTATE */
 	},
+	.wakeup_lat = {
+		[PWRDM_FUNC_PWRST_OFF] = 671,
+		[PWRDM_FUNC_PWRST_OSWR] = UNSUP_STATE,
+		[PWRDM_FUNC_PWRST_CSWR] = 31,
+		[PWRDM_FUNC_PWRST_INACTIVE] = UNSUP_STATE,
+		[PWRDM_FUNC_PWRST_ON] = 0,
+	},
 	.voltdm           = { .name = "core" },
 };
 
@@ -197,6 +266,13 @@ static struct powerdomain neon_pwrdm = {
 	.prcm_offs	  = OMAP3430_NEON_MOD,
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_RET,
+	.wakeup_lat = {
+		[PWRDM_FUNC_PWRST_OFF] = 0,
+		[PWRDM_FUNC_PWRST_OSWR] = UNSUP_STATE,
+		[PWRDM_FUNC_PWRST_CSWR] = 0,
+		[PWRDM_FUNC_PWRST_INACTIVE] = UNSUP_STATE,
+		[PWRDM_FUNC_PWRST_ON] = 0,
+	},
 	.voltdm           = { .name = "mpu_iva" },
 };
 
@@ -219,6 +295,13 @@ static struct powerdomain usbhost_pwrdm = {
 	.pwrsts_mem_on	  = {
 		[0] = PWRSTS_ON,  /* MEMONSTATE */
 	},
+	.wakeup_lat = {
+		[PWRDM_FUNC_PWRST_OFF] = 800,
+		[PWRDM_FUNC_PWRST_OSWR] = UNSUP_STATE,
+		[PWRDM_FUNC_PWRST_CSWR] = 150,
+		[PWRDM_FUNC_PWRST_INACTIVE] = UNSUP_STATE,
+		[PWRDM_FUNC_PWRST_ON] = 0,
+	},
 	.voltdm           = { .name = "core" },
 };
 
-- 
1.7.7.6

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

* Re: [PATCH 5/6] ARM: OMAP3: update cpuidle latency and threshold figures
  2012-04-18 13:45   ` jean.pihet at newoldbits.com
@ 2012-04-18 15:18     ` Grazvydas Ignotas
  -1 siblings, 0 replies; 22+ messages in thread
From: Grazvydas Ignotas @ 2012-04-18 15:18 UTC (permalink / raw)
  To: jean.pihet
  Cc: linux-omap, paul, b-cousson, khilman, linux-arm-kernel, Jean Pihet

On Wed, Apr 18, 2012 at 4:45 PM,  <jean.pihet@newoldbits.com> wrote:
> From: Jean Pihet <j-pihet@ti.com>
>
> Update the data from the measurements performed at HW and SW levels.
>
> Cf. http://www.omappedia.org/wiki/Power_Management_Device_Latencies_Measurement
> for a detailed explanation on where are the numbers coming from.
>
> ...
> ToDo:
> - Measure the wake-up latencies for all power domains for OMAP3
> - Correct some numbers when sys_clkreq and sys_offmode are supported
>
> Signed-off-by: Jean Pihet <j-pihet@ti.com>
> Reviewed-by: Kevin Hilman <khilman@ti.com>
> ---
>  arch/arm/mach-omap2/cpuidle34xx.c |   52 +++++++++++++++++++++++-------------
>  1 files changed, 33 insertions(+), 19 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c
> index 2f95cfc..e406d7b 100644
> --- a/arch/arm/mach-omap2/cpuidle34xx.c
> +++ b/arch/arm/mach-omap2/cpuidle34xx.c
> @@ -39,27 +39,41 @@
<snip>
>  static struct cpuidle_params cpuidle_params_table[] = {
> -       /* C1 */
> -       {2 + 2, 5, 1},
> -       /* C2 */
> -       {10 + 10, 30, 1},
> -       /* C3 */
> -       {50 + 50, 300, 1},
> -       /* C4 */
> -       {1500 + 1800, 4000, 1},
> -       /* C5 */
> -       {2500 + 7500, 12000, 1},
> -       /* C6 */
> -       {3000 + 8500, 15000, 1},
> -       /* C7 */
> -       {10000 + 30000, 300000, 1},
> +       /* C1 . MPU WFI + Core active */
> +       {73 + 78, 152, 1},
> +       /* C2 . MPU WFI + Core inactive */
> +       {165 + 88, 345, 1},
> +       /* C3 . MPU CSWR + Core inactive */
> +       {163 + 182, 345, 1},
> +       /* C4 . MPU OFF + Core inactive */
> +       {2852 + 605, 150000, 1},
> +       /* C5 . MPU RET + Core RET */
> +       {800 + 366, 2120, 1},
> +       /* C6 . MPU OFF + Core RET */
> +       {4080 + 801, 215000, 1},
> +       /* C7 . MPU OFF + Core OFF */
> +       {4300 + 13000, 215000, 1},
>  };

These (C1 at least) seem to look quite a bit better than what we see here:
http://marc.info/?t=133375282700004&r=1&w=2
according to that wiki log, some of those measurements are from 2010,
I wonder if that still matches today's code well.


-- 
Gražvydas
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH 5/6] ARM: OMAP3: update cpuidle latency and threshold figures
@ 2012-04-18 15:18     ` Grazvydas Ignotas
  0 siblings, 0 replies; 22+ messages in thread
From: Grazvydas Ignotas @ 2012-04-18 15:18 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Apr 18, 2012 at 4:45 PM,  <jean.pihet@newoldbits.com> wrote:
> From: Jean Pihet <j-pihet@ti.com>
>
> Update the data from the measurements performed at HW and SW levels.
>
> Cf. http://www.omappedia.org/wiki/Power_Management_Device_Latencies_Measurement
> for a detailed explanation on where are the numbers coming from.
>
> ...
> ToDo:
> - Measure the wake-up latencies for all power domains for OMAP3
> - Correct some numbers when sys_clkreq and sys_offmode are supported
>
> Signed-off-by: Jean Pihet <j-pihet@ti.com>
> Reviewed-by: Kevin Hilman <khilman@ti.com>
> ---
> ?arch/arm/mach-omap2/cpuidle34xx.c | ? 52 +++++++++++++++++++++++-------------
> ?1 files changed, 33 insertions(+), 19 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c
> index 2f95cfc..e406d7b 100644
> --- a/arch/arm/mach-omap2/cpuidle34xx.c
> +++ b/arch/arm/mach-omap2/cpuidle34xx.c
> @@ -39,27 +39,41 @@
<snip>
> ?static struct cpuidle_params cpuidle_params_table[] = {
> - ? ? ? /* C1 */
> - ? ? ? {2 + 2, 5, 1},
> - ? ? ? /* C2 */
> - ? ? ? {10 + 10, 30, 1},
> - ? ? ? /* C3 */
> - ? ? ? {50 + 50, 300, 1},
> - ? ? ? /* C4 */
> - ? ? ? {1500 + 1800, 4000, 1},
> - ? ? ? /* C5 */
> - ? ? ? {2500 + 7500, 12000, 1},
> - ? ? ? /* C6 */
> - ? ? ? {3000 + 8500, 15000, 1},
> - ? ? ? /* C7 */
> - ? ? ? {10000 + 30000, 300000, 1},
> + ? ? ? /* C1 . MPU WFI + Core active */
> + ? ? ? {73 + 78, 152, 1},
> + ? ? ? /* C2 . MPU WFI + Core inactive */
> + ? ? ? {165 + 88, 345, 1},
> + ? ? ? /* C3 . MPU CSWR + Core inactive */
> + ? ? ? {163 + 182, 345, 1},
> + ? ? ? /* C4 . MPU OFF + Core inactive */
> + ? ? ? {2852 + 605, 150000, 1},
> + ? ? ? /* C5 . MPU RET + Core RET */
> + ? ? ? {800 + 366, 2120, 1},
> + ? ? ? /* C6 . MPU OFF + Core RET */
> + ? ? ? {4080 + 801, 215000, 1},
> + ? ? ? /* C7 . MPU OFF + Core OFF */
> + ? ? ? {4300 + 13000, 215000, 1},
> ?};

These (C1 at least) seem to look quite a bit better than what we see here:
http://marc.info/?t=133375282700004&r=1&w=2
according to that wiki log, some of those measurements are from 2010,
I wonder if that still matches today's code well.


-- 
Gra?vydas

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

* Re: [PATCH 5/6] ARM: OMAP3: update cpuidle latency and threshold figures
  2012-04-18 15:18     ` Grazvydas Ignotas
@ 2012-04-18 15:48       ` Jean Pihet
  -1 siblings, 0 replies; 22+ messages in thread
From: Jean Pihet @ 2012-04-18 15:48 UTC (permalink / raw)
  To: Grazvydas Ignotas
  Cc: linux-omap, paul, b-cousson, khilman, linux-arm-kernel, Jean Pihet

On Wed, Apr 18, 2012 at 5:18 PM, Grazvydas Ignotas <notasas@gmail.com> wrote:
> On Wed, Apr 18, 2012 at 4:45 PM,  <jean.pihet@newoldbits.com> wrote:
>> From: Jean Pihet <j-pihet@ti.com>
>>
>> Update the data from the measurements performed at HW and SW levels.
>>
>> Cf. http://www.omappedia.org/wiki/Power_Management_Device_Latencies_Measurement
>> for a detailed explanation on where are the numbers coming from.
>>
>> ...
>> ToDo:
>> - Measure the wake-up latencies for all power domains for OMAP3
>> - Correct some numbers when sys_clkreq and sys_offmode are supported
>>
>> Signed-off-by: Jean Pihet <j-pihet@ti.com>
>> Reviewed-by: Kevin Hilman <khilman@ti.com>
>> ---
>>  arch/arm/mach-omap2/cpuidle34xx.c |   52 +++++++++++++++++++++++-------------
>>  1 files changed, 33 insertions(+), 19 deletions(-)
>>
>> diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c
>> index 2f95cfc..e406d7b 100644
>> --- a/arch/arm/mach-omap2/cpuidle34xx.c
>> +++ b/arch/arm/mach-omap2/cpuidle34xx.c
>> @@ -39,27 +39,41 @@
> <snip>
>>  static struct cpuidle_params cpuidle_params_table[] = {
>> -       /* C1 */
>> -       {2 + 2, 5, 1},
>> -       /* C2 */
>> -       {10 + 10, 30, 1},
>> -       /* C3 */
>> -       {50 + 50, 300, 1},
>> -       /* C4 */
>> -       {1500 + 1800, 4000, 1},
>> -       /* C5 */
>> -       {2500 + 7500, 12000, 1},
>> -       /* C6 */
>> -       {3000 + 8500, 15000, 1},
>> -       /* C7 */
>> -       {10000 + 30000, 300000, 1},
>> +       /* C1 . MPU WFI + Core active */
>> +       {73 + 78, 152, 1},
>> +       /* C2 . MPU WFI + Core inactive */
>> +       {165 + 88, 345, 1},
>> +       /* C3 . MPU CSWR + Core inactive */
>> +       {163 + 182, 345, 1},
>> +       /* C4 . MPU OFF + Core inactive */
>> +       {2852 + 605, 150000, 1},
>> +       /* C5 . MPU RET + Core RET */
>> +       {800 + 366, 2120, 1},
>> +       /* C6 . MPU OFF + Core RET */
>> +       {4080 + 801, 215000, 1},
>> +       /* C7 . MPU OFF + Core OFF */
>> +       {4300 + 13000, 215000, 1},
>>  };
>
> These (C1 at least) seem to look quite a bit better than what we see here:
> http://marc.info/?t=133375282700004&r=1&w=2
> according to that wiki log, some of those measurements are from 2010,
> I wonder if that still matches today's code well.
Those figures are for the HW part of the low power transitions
assuming that the SW overhead (in omap_sram_idle) is minimal, which
seems to not be true anymore.
I need to measure the latencies again on the latest SW.

Thanks,
Jean

>
>
> --
> Gražvydas
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH 5/6] ARM: OMAP3: update cpuidle latency and threshold figures
@ 2012-04-18 15:48       ` Jean Pihet
  0 siblings, 0 replies; 22+ messages in thread
From: Jean Pihet @ 2012-04-18 15:48 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Apr 18, 2012 at 5:18 PM, Grazvydas Ignotas <notasas@gmail.com> wrote:
> On Wed, Apr 18, 2012 at 4:45 PM, ?<jean.pihet@newoldbits.com> wrote:
>> From: Jean Pihet <j-pihet@ti.com>
>>
>> Update the data from the measurements performed at HW and SW levels.
>>
>> Cf. http://www.omappedia.org/wiki/Power_Management_Device_Latencies_Measurement
>> for a detailed explanation on where are the numbers coming from.
>>
>> ...
>> ToDo:
>> - Measure the wake-up latencies for all power domains for OMAP3
>> - Correct some numbers when sys_clkreq and sys_offmode are supported
>>
>> Signed-off-by: Jean Pihet <j-pihet@ti.com>
>> Reviewed-by: Kevin Hilman <khilman@ti.com>
>> ---
>> ?arch/arm/mach-omap2/cpuidle34xx.c | ? 52 +++++++++++++++++++++++-------------
>> ?1 files changed, 33 insertions(+), 19 deletions(-)
>>
>> diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c
>> index 2f95cfc..e406d7b 100644
>> --- a/arch/arm/mach-omap2/cpuidle34xx.c
>> +++ b/arch/arm/mach-omap2/cpuidle34xx.c
>> @@ -39,27 +39,41 @@
> <snip>
>> ?static struct cpuidle_params cpuidle_params_table[] = {
>> - ? ? ? /* C1 */
>> - ? ? ? {2 + 2, 5, 1},
>> - ? ? ? /* C2 */
>> - ? ? ? {10 + 10, 30, 1},
>> - ? ? ? /* C3 */
>> - ? ? ? {50 + 50, 300, 1},
>> - ? ? ? /* C4 */
>> - ? ? ? {1500 + 1800, 4000, 1},
>> - ? ? ? /* C5 */
>> - ? ? ? {2500 + 7500, 12000, 1},
>> - ? ? ? /* C6 */
>> - ? ? ? {3000 + 8500, 15000, 1},
>> - ? ? ? /* C7 */
>> - ? ? ? {10000 + 30000, 300000, 1},
>> + ? ? ? /* C1 . MPU WFI + Core active */
>> + ? ? ? {73 + 78, 152, 1},
>> + ? ? ? /* C2 . MPU WFI + Core inactive */
>> + ? ? ? {165 + 88, 345, 1},
>> + ? ? ? /* C3 . MPU CSWR + Core inactive */
>> + ? ? ? {163 + 182, 345, 1},
>> + ? ? ? /* C4 . MPU OFF + Core inactive */
>> + ? ? ? {2852 + 605, 150000, 1},
>> + ? ? ? /* C5 . MPU RET + Core RET */
>> + ? ? ? {800 + 366, 2120, 1},
>> + ? ? ? /* C6 . MPU OFF + Core RET */
>> + ? ? ? {4080 + 801, 215000, 1},
>> + ? ? ? /* C7 . MPU OFF + Core OFF */
>> + ? ? ? {4300 + 13000, 215000, 1},
>> ?};
>
> These (C1 at least) seem to look quite a bit better than what we see here:
> http://marc.info/?t=133375282700004&r=1&w=2
> according to that wiki log, some of those measurements are from 2010,
> I wonder if that still matches today's code well.
Those figures are for the HW part of the low power transitions
assuming that the SW overhead (in omap_sram_idle) is minimal, which
seems to not be true anymore.
I need to measure the latencies again on the latest SW.

Thanks,
Jean

>
>
> --
> Gra?vydas

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

* Re: [PATCH v7 0/6] PM QoS: implement the OMAP low level constraints management code
  2012-04-18 13:45 ` jean.pihet at newoldbits.com
@ 2012-04-30 23:15   ` Kevin Hilman
  -1 siblings, 0 replies; 22+ messages in thread
From: Kevin Hilman @ 2012-04-30 23:15 UTC (permalink / raw)
  To: jean.pihet; +Cc: linux-omap, paul, b-cousson, linux-arm-kernel, Jean Pihet

Hi Jean,

jean.pihet@newoldbits.com writes:

> From: Jean Pihet <j-pihet@ti.com>
>
> . Implement the devices wake-up latency constraints using the global
>   device PM QoS notification handler which applies the constraints to the
>   underlying layer,
> . Implement the low level code which controls the power domains next
>   functional power states [3], through the hwmod and pwrdm layers,
> . Add cpuidle and power domains wake-up latency figures for OMAP3, cf. 
>   comments in the code and [1] for the details on where the numbers
>   are magically coming from,
> . Implement the relation between the cpuidle and per-device PM QoS frameworks
>   in the OMAP3 specific idle callbacks.
>   The chosen C-state shall satisfy the following conditions:
>    . the 'valid' field is enabled,
>    . it satisfies the enable_off_mode flag,
>    . the next state for MPU and CORE power domains is not lower than the
>      state programmed by the per-device PM QoS.

I've just been through this series and it looks good to me.  

Reviewed-by: Kevin Hilman <khilman@ti.com>

> ToDo:
> 1. support OMAP4 chipset when the low power modes will be supported

Have you been able to do this with Tero's latest CORE RET and device off
series?

Kevin

> 2. validate the constraints framework on OMAP4 HW (done on OMAP3)
> 3. Re-visit the OMAP power domains states initialization procedure. Currently
>    the power states that have been changed from the constraints API which were
>    applied before the initialization of the power domains are lost
> 4. Further clean-up the OMAP PM layer, use the generic frameworks instead (OPP,
>    PM QoS for throughput constraints ...)
>
>
> Based on the pm-qos branch of the linux-omap git tree (3.4.0-rc2) [2] with
> the functional power states changes applied [3].
>
> Tested cpuidle and suspend on OMAP3 Beagleboard (ES2.x) with constraints
> on MPU, CORE, PER in RETention and OFF modes.
>
> [1] http://www.omappedia.org/wiki/Power_Management_Device_Latencies_Measurement
> [2] git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap.git
> [3] http://marc.info/?l=linux-omap&m=133475291911194&w=2
>
>
> History:
>
> v7:
> . rebased on top of the functional power state changes [3]
>
> v6:
> . minor change in the commits description after Kevin's review
> . added Kevin's Reviewed-by
>
> v5:
> . rebased on latest linux-omap [2]
> . rework after Kevin's comments on the MLs
>
> v4:
> . split up the patches which remove the omap_pm_ code from the patch set.
>   Those patches are to be submitted later, on top of this patch set.
> . latency numbers: provide the measurements setup and conditions in the code
>   comments, added the link to the details on wiki [1].
> . improved kerneldoc
> . split big functions into smaller ones, in order to improve the readability
>
> v3: reworked the error return path and improved the kerneldoc
>
> v2: reworked the OMAP specific cpuidle code to demote the initial C-state to
>      a valid C-state which fulfills the per-device constraints
>
> v1: initial version
>
>
> Jean Pihet (6):
>   ARM: OMAP2+: PM QoS: control the power domains next state from the
>     constraints
>   ARM: OMAP2+: PM QoS: manage the per-device latency constraints in
>     hwmod
>   ARM: OMAP: omap_device: register to the per-device PM QoS framework
>   ARM: OMAP3: cpuidle: next C-state decision depends on the PM QoS MPU
>     and CORE constraints
>   ARM: OMAP3: update cpuidle latency and threshold figures
>   ARM: OMAP3: powerdomain data: add wake-up latency figures
>
>  arch/arm/mach-omap2/cpuidle34xx.c           |  109 ++++++++------
>  arch/arm/mach-omap2/omap_hwmod.c            |   22 +--
>  arch/arm/mach-omap2/pm.h                    |   17 ++-
>  arch/arm/mach-omap2/powerdomain.c           |  216 +++++++++++++++++++++++++++
>  arch/arm/mach-omap2/powerdomain.h           |   17 ++
>  arch/arm/mach-omap2/powerdomains3xxx_data.c |   83 ++++++++++
>  arch/arm/plat-omap/omap_device.c            |   81 ++++++++++-
>  7 files changed, 481 insertions(+), 64 deletions(-)

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

* [PATCH v7 0/6] PM QoS: implement the OMAP low level constraints management code
@ 2012-04-30 23:15   ` Kevin Hilman
  0 siblings, 0 replies; 22+ messages in thread
From: Kevin Hilman @ 2012-04-30 23:15 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Jean,

jean.pihet at newoldbits.com writes:

> From: Jean Pihet <j-pihet@ti.com>
>
> . Implement the devices wake-up latency constraints using the global
>   device PM QoS notification handler which applies the constraints to the
>   underlying layer,
> . Implement the low level code which controls the power domains next
>   functional power states [3], through the hwmod and pwrdm layers,
> . Add cpuidle and power domains wake-up latency figures for OMAP3, cf. 
>   comments in the code and [1] for the details on where the numbers
>   are magically coming from,
> . Implement the relation between the cpuidle and per-device PM QoS frameworks
>   in the OMAP3 specific idle callbacks.
>   The chosen C-state shall satisfy the following conditions:
>    . the 'valid' field is enabled,
>    . it satisfies the enable_off_mode flag,
>    . the next state for MPU and CORE power domains is not lower than the
>      state programmed by the per-device PM QoS.

I've just been through this series and it looks good to me.  

Reviewed-by: Kevin Hilman <khilman@ti.com>

> ToDo:
> 1. support OMAP4 chipset when the low power modes will be supported

Have you been able to do this with Tero's latest CORE RET and device off
series?

Kevin

> 2. validate the constraints framework on OMAP4 HW (done on OMAP3)
> 3. Re-visit the OMAP power domains states initialization procedure. Currently
>    the power states that have been changed from the constraints API which were
>    applied before the initialization of the power domains are lost
> 4. Further clean-up the OMAP PM layer, use the generic frameworks instead (OPP,
>    PM QoS for throughput constraints ...)
>
>
> Based on the pm-qos branch of the linux-omap git tree (3.4.0-rc2) [2] with
> the functional power states changes applied [3].
>
> Tested cpuidle and suspend on OMAP3 Beagleboard (ES2.x) with constraints
> on MPU, CORE, PER in RETention and OFF modes.
>
> [1] http://www.omappedia.org/wiki/Power_Management_Device_Latencies_Measurement
> [2] git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap.git
> [3] http://marc.info/?l=linux-omap&m=133475291911194&w=2
>
>
> History:
>
> v7:
> . rebased on top of the functional power state changes [3]
>
> v6:
> . minor change in the commits description after Kevin's review
> . added Kevin's Reviewed-by
>
> v5:
> . rebased on latest linux-omap [2]
> . rework after Kevin's comments on the MLs
>
> v4:
> . split up the patches which remove the omap_pm_ code from the patch set.
>   Those patches are to be submitted later, on top of this patch set.
> . latency numbers: provide the measurements setup and conditions in the code
>   comments, added the link to the details on wiki [1].
> . improved kerneldoc
> . split big functions into smaller ones, in order to improve the readability
>
> v3: reworked the error return path and improved the kerneldoc
>
> v2: reworked the OMAP specific cpuidle code to demote the initial C-state to
>      a valid C-state which fulfills the per-device constraints
>
> v1: initial version
>
>
> Jean Pihet (6):
>   ARM: OMAP2+: PM QoS: control the power domains next state from the
>     constraints
>   ARM: OMAP2+: PM QoS: manage the per-device latency constraints in
>     hwmod
>   ARM: OMAP: omap_device: register to the per-device PM QoS framework
>   ARM: OMAP3: cpuidle: next C-state decision depends on the PM QoS MPU
>     and CORE constraints
>   ARM: OMAP3: update cpuidle latency and threshold figures
>   ARM: OMAP3: powerdomain data: add wake-up latency figures
>
>  arch/arm/mach-omap2/cpuidle34xx.c           |  109 ++++++++------
>  arch/arm/mach-omap2/omap_hwmod.c            |   22 +--
>  arch/arm/mach-omap2/pm.h                    |   17 ++-
>  arch/arm/mach-omap2/powerdomain.c           |  216 +++++++++++++++++++++++++++
>  arch/arm/mach-omap2/powerdomain.h           |   17 ++
>  arch/arm/mach-omap2/powerdomains3xxx_data.c |   83 ++++++++++
>  arch/arm/plat-omap/omap_device.c            |   81 ++++++++++-
>  7 files changed, 481 insertions(+), 64 deletions(-)

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

* Re: [PATCH v7 0/6] PM QoS: implement the OMAP low level constraints management code
  2012-04-30 23:15   ` Kevin Hilman
@ 2012-05-01  8:38     ` Jean Pihet
  -1 siblings, 0 replies; 22+ messages in thread
From: Jean Pihet @ 2012-05-01  8:38 UTC (permalink / raw)
  To: Kevin Hilman; +Cc: linux-omap, paul, b-cousson, linux-arm-kernel, Jean Pihet

Hi Kevin,

On Tue, May 1, 2012 at 1:15 AM, Kevin Hilman <khilman@ti.com> wrote:
> Hi Jean,
>
> jean.pihet@newoldbits.com writes:
>
>> From: Jean Pihet <j-pihet@ti.com>
>>
>> . Implement the devices wake-up latency constraints using the global
>>   device PM QoS notification handler which applies the constraints to the
>>   underlying layer,
>> . Implement the low level code which controls the power domains next
>>   functional power states [3], through the hwmod and pwrdm layers,
>> . Add cpuidle and power domains wake-up latency figures for OMAP3, cf.
>>   comments in the code and [1] for the details on where the numbers
>>   are magically coming from,
>> . Implement the relation between the cpuidle and per-device PM QoS frameworks
>>   in the OMAP3 specific idle callbacks.
>>   The chosen C-state shall satisfy the following conditions:
>>    . the 'valid' field is enabled,
>>    . it satisfies the enable_off_mode flag,
>>    . the next state for MPU and CORE power domains is not lower than the
>>      state programmed by the per-device PM QoS.
>
> I've just been through this series and it looks good to me.
>
> Reviewed-by: Kevin Hilman <khilman@ti.com>
Thx for reviewing!

>> ToDo:
>> 1. support OMAP4 chipset when the low power modes will be supported
>
> Have you been able to do this with Tero's latest CORE RET and device off
> series?
No I still have to port Tero's latest patch set on top of the
functional power states and the constraints code. This is on my
ToDoNext list ;p

>
> Kevin
>

Thanks,
Jean
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v7 0/6] PM QoS: implement the OMAP low level constraints management code
@ 2012-05-01  8:38     ` Jean Pihet
  0 siblings, 0 replies; 22+ messages in thread
From: Jean Pihet @ 2012-05-01  8:38 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Kevin,

On Tue, May 1, 2012 at 1:15 AM, Kevin Hilman <khilman@ti.com> wrote:
> Hi Jean,
>
> jean.pihet at newoldbits.com writes:
>
>> From: Jean Pihet <j-pihet@ti.com>
>>
>> . Implement the devices wake-up latency constraints using the global
>> ? device PM QoS notification handler which applies the constraints to the
>> ? underlying layer,
>> . Implement the low level code which controls the power domains next
>> ? functional power states [3], through the hwmod and pwrdm layers,
>> . Add cpuidle and power domains wake-up latency figures for OMAP3, cf.
>> ? comments in the code and [1] for the details on where the numbers
>> ? are magically coming from,
>> . Implement the relation between the cpuidle and per-device PM QoS frameworks
>> ? in the OMAP3 specific idle callbacks.
>> ? The chosen C-state shall satisfy the following conditions:
>> ? ?. the 'valid' field is enabled,
>> ? ?. it satisfies the enable_off_mode flag,
>> ? ?. the next state for MPU and CORE power domains is not lower than the
>> ? ? ?state programmed by the per-device PM QoS.
>
> I've just been through this series and it looks good to me.
>
> Reviewed-by: Kevin Hilman <khilman@ti.com>
Thx for reviewing!

>> ToDo:
>> 1. support OMAP4 chipset when the low power modes will be supported
>
> Have you been able to do this with Tero's latest CORE RET and device off
> series?
No I still have to port Tero's latest patch set on top of the
functional power states and the constraints code. This is on my
ToDoNext list ;p

>
> Kevin
>

Thanks,
Jean

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

end of thread, other threads:[~2012-05-01  8:38 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-04-18 13:45 [PATCH v7 0/6] PM QoS: implement the OMAP low level constraints management code jean.pihet
2012-04-18 13:45 ` jean.pihet at newoldbits.com
2012-04-18 13:45 ` [PATCH 1/6] ARM: OMAP2+: PM QoS: control the power domains next state from the constraints jean.pihet
2012-04-18 13:45   ` jean.pihet at newoldbits.com
2012-04-18 13:45 ` [PATCH 2/6] ARM: OMAP2+: PM QoS: manage the per-device latency constraints in hwmod jean.pihet
2012-04-18 13:45   ` jean.pihet at newoldbits.com
2012-04-18 13:45 ` [PATCH 3/6] ARM: OMAP: omap_device: register to the per-device PM QoS framework jean.pihet
2012-04-18 13:45   ` jean.pihet at newoldbits.com
2012-04-18 13:45 ` [PATCH 4/6] ARM: OMAP3: cpuidle: next C-state decision depends on the PM QoS MPU and CORE constraints jean.pihet
2012-04-18 13:45   ` jean.pihet at newoldbits.com
2012-04-18 13:45 ` [PATCH 5/6] ARM: OMAP3: update cpuidle latency and threshold figures jean.pihet
2012-04-18 13:45   ` jean.pihet at newoldbits.com
2012-04-18 15:18   ` Grazvydas Ignotas
2012-04-18 15:18     ` Grazvydas Ignotas
2012-04-18 15:48     ` Jean Pihet
2012-04-18 15:48       ` Jean Pihet
2012-04-18 13:45 ` [PATCH 6/6] ARM: OMAP3: powerdomain data: add wake-up latency figures jean.pihet
2012-04-18 13:45   ` jean.pihet at newoldbits.com
2012-04-30 23:15 ` [PATCH v7 0/6] PM QoS: implement the OMAP low level constraints management code Kevin Hilman
2012-04-30 23:15   ` Kevin Hilman
2012-05-01  8:38   ` Jean Pihet
2012-05-01  8:38     ` Jean Pihet

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.