public inbox for linux-omap@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/8] OMAP: convert I2C driver to PM QoS for latency constraints
  2011-09-02 13:13 [PATCH 0/8] PM QoS: implement the OMAP low level constraints management code Jean Pihet
@ 2011-09-02 13:13 ` Jean Pihet
  2011-09-15 22:46   ` Kevin Hilman
  0 siblings, 1 reply; 36+ messages in thread
From: Jean Pihet @ 2011-09-02 13:13 UTC (permalink / raw)
  To: Kevin Hilman, Linux PM mailing list, linux-omap,
	Rafael J. Wysocki, Paul Walmsley
  Cc: Jean Pihet

Convert the driver from the outdated omap_pm_set_max_mpu_wakeup_lat
API to the new PM QoS API.
Since the constraint is on the MPU subsystem, use the PM_QOS_CPU_DMA_LATENCY
class of PM QoS. The resulting MPU constraints are used by cpuidle to
decide the next power state of the MPU subsystem.

Currently only OMAP3 is placing constraints on the MPU.

Signed-off-by: Jean Pihet <j-pihet@ti.com>
---
 arch/arm/plat-omap/i2c.c      |   20 --------------------
 drivers/i2c/busses/i2c-omap.c |   31 ++++++++++++++++++-------------
 2 files changed, 18 insertions(+), 33 deletions(-)

diff --git a/arch/arm/plat-omap/i2c.c b/arch/arm/plat-omap/i2c.c
index 3341ca4..e1e2502 100644
--- a/arch/arm/plat-omap/i2c.c
+++ b/arch/arm/plat-omap/i2c.c
@@ -34,7 +34,6 @@
 #include <mach/irqs.h>
 #include <plat/mux.h>
 #include <plat/i2c.h>
-#include <plat/omap-pm.h>
 #include <plat/omap_device.h>
 
 #define OMAP_I2C_SIZE		0x3f
@@ -113,16 +112,6 @@ static inline int omap1_i2c_add_bus(int bus_id)
 
 
 #ifdef CONFIG_ARCH_OMAP2PLUS
-/*
- * XXX This function is a temporary compatibility wrapper - only
- * needed until the I2C driver can be converted to call
- * omap_pm_set_max_dev_wakeup_lat() and handle a return code.
- */
-static void omap_pm_set_max_mpu_wakeup_lat_compat(struct device *dev, long t)
-{
-	omap_pm_set_max_mpu_wakeup_lat(dev, t);
-}
-
 static struct omap_device_pm_latency omap_i2c_latency[] = {
 	[0] = {
 		.deactivate_func	= omap_device_idle_hwmods,
@@ -151,15 +140,6 @@ static inline int omap2_i2c_add_bus(int bus_id)
 	}
 
 	pdata = &i2c_pdata[bus_id - 1];
-	/*
-	 * When waiting for completion of a i2c transfer, we need to
-	 * set a wake up latency constraint for the MPU. This is to
-	 * ensure quick enough wakeup from idle, when transfer
-	 * completes.
-	 * Only omap3 has support for constraints
-	 */
-	if (cpu_is_omap34xx())
-		pdata->set_mpu_wkup_lat = omap_pm_set_max_mpu_wakeup_lat_compat;
 	od = omap_device_build(name, bus_id, oh, pdata,
 			sizeof(struct omap_i2c_bus_platform_data),
 			omap_i2c_latency, ARRAY_SIZE(omap_i2c_latency), 0);
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index 1a766cf..1c762ba 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -40,6 +40,7 @@
 #include <linux/slab.h>
 #include <linux/i2c-omap.h>
 #include <linux/pm_runtime.h>
+#include <linux/pm_qos.h>
 
 /* I2C controller revisions */
 #define OMAP_I2C_REV_2			0x20
@@ -179,8 +180,7 @@ struct omap_i2c_dev {
 	struct completion	cmd_complete;
 	struct resource		*ioarea;
 	u32			latency;	/* maximum mpu wkup latency */
-	void			(*set_mpu_wkup_lat)(struct device *dev,
-						    long latency);
+	struct pm_qos_request	pm_qos_request;
 	u32			speed;		/* Speed of bus in Khz */
 	u16			cmd_err;
 	u8			*buf;
@@ -648,8 +648,16 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
 	if (r < 0)
 		goto out;
 
-	if (dev->set_mpu_wkup_lat != NULL)
-		dev->set_mpu_wkup_lat(dev->dev, dev->latency);
+	/*
+	 * When waiting for completion of a i2c transfer, we need to
+	 * set a wake up latency constraint for the MPU. This is to
+	 * ensure quick enough wakeup from idle, when transfer
+	 * completes.
+	 * Used on OMAP3 Only
+	 */
+	if (cpu_is_omap34xx())
+		pm_qos_add_request(&dev->pm_qos_request, PM_QOS_CPU_DMA_LATENCY,
+				   dev->latency);
 
 	for (i = 0; i < num; i++) {
 		r = omap_i2c_xfer_msg(adap, &msgs[i], (i == (num - 1)));
@@ -657,8 +665,8 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
 			break;
 	}
 
-	if (dev->set_mpu_wkup_lat != NULL)
-		dev->set_mpu_wkup_lat(dev->dev, -1);
+	if (cpu_is_omap34xx())
+		pm_qos_remove_request(&dev->pm_qos_request);
 
 	if (r == 0)
 		r = num;
@@ -1007,13 +1015,10 @@ omap_i2c_probe(struct platform_device *pdev)
 		goto err_release_region;
 	}
 
-	if (pdata != NULL) {
+	if (pdata != NULL)
 		speed = pdata->clkrate;
-		dev->set_mpu_wkup_lat = pdata->set_mpu_wkup_lat;
-	} else {
+	else
 		speed = 100;	/* Default speed */
-		dev->set_mpu_wkup_lat = NULL;
-	}
 
 	dev->speed = speed;
 	dev->idle = 1;
@@ -1066,8 +1071,8 @@ omap_i2c_probe(struct platform_device *pdev)
 			dev->fifo_size = (dev->fifo_size / 2);
 			dev->b_hw = 1; /* Enable hardware fixes */
 		}
-		/* calculate wakeup latency constraint for MPU */
-		if (dev->set_mpu_wkup_lat != NULL)
+		/* calculate wakeup latency constraint */
+		if (cpu_is_omap34xx())
 			dev->latency = (1000000 * dev->fifo_size) /
 				       (1000 * speed / 8);
 	}
-- 
1.7.4.1


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

* Re: [PATCH 1/8] OMAP: convert I2C driver to PM QoS for latency constraints
  2011-09-02 13:13 ` [PATCH 1/8] OMAP: convert I2C driver to PM QoS for latency constraints Jean Pihet
@ 2011-09-15 22:46   ` Kevin Hilman
  2011-09-16 15:39     ` Jean Pihet
  0 siblings, 1 reply; 36+ messages in thread
From: Kevin Hilman @ 2011-09-15 22:46 UTC (permalink / raw)
  To: Jean Pihet
  Cc: Linux PM mailing list, linux-omap, Rafael J. Wysocki,
	Paul Walmsley, magnus.damm, Todd Poynor, Jean Pihet

Hi Jean,

Jean Pihet <jean.pihet@newoldbits.com> writes:

> Convert the driver from the outdated omap_pm_set_max_mpu_wakeup_lat
> API to the new PM QoS API.
> Since the constraint is on the MPU subsystem, use the PM_QOS_CPU_DMA_LATENCY
> class of PM QoS. The resulting MPU constraints are used by cpuidle to
> decide the next power state of the MPU subsystem.
>
> Currently only OMAP3 is placing constraints on the MPU.
>
> Signed-off-by: Jean Pihet <j-pihet@ti.com>

[...]

> @@ -648,8 +648,16 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
>  	if (r < 0)
>  		goto out;
>  
> -	if (dev->set_mpu_wkup_lat != NULL)
> -		dev->set_mpu_wkup_lat(dev->dev, dev->latency);
> +	/*
> +	 * When waiting for completion of a i2c transfer, we need to
> +	 * set a wake up latency constraint for the MPU. This is to
> +	 * ensure quick enough wakeup from idle, when transfer
> +	 * completes.
> +	 * Used on OMAP3 Only
> +	 */
> +	if (cpu_is_omap34xx())

We don't want any cpu_is_* checking  in drivers.

If this is only done on certain SoCs, then a flag should be passed from
device init code via pdata.

That being said, I don't see why this shouldn't be set for all SoCs
since it's using the FIFO size to determine the latency.

Kevin


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

* Re: [PATCH 1/8] OMAP: convert I2C driver to PM QoS for latency constraints
  2011-09-15 22:46   ` Kevin Hilman
@ 2011-09-16 15:39     ` Jean Pihet
  2011-09-16 16:06       ` Kevin Hilman
  0 siblings, 1 reply; 36+ messages in thread
From: Jean Pihet @ 2011-09-16 15:39 UTC (permalink / raw)
  To: Kevin Hilman
  Cc: Linux PM mailing list, linux-omap, Rafael J. Wysocki,
	Paul Walmsley, magnus.damm, Todd Poynor, Jean Pihet

Kevin,

On Fri, Sep 16, 2011 at 12:46 AM, Kevin Hilman <khilman@ti.com> wrote:
> Hi Jean,
>
> Jean Pihet <jean.pihet@newoldbits.com> writes:
>
>> Convert the driver from the outdated omap_pm_set_max_mpu_wakeup_lat
>> API to the new PM QoS API.
>> Since the constraint is on the MPU subsystem, use the PM_QOS_CPU_DMA_LATENCY
>> class of PM QoS. The resulting MPU constraints are used by cpuidle to
>> decide the next power state of the MPU subsystem.
>>
>> Currently only OMAP3 is placing constraints on the MPU.
>>
>> Signed-off-by: Jean Pihet <j-pihet@ti.com>
>
> [...]
>
>> @@ -648,8 +648,16 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
>>       if (r < 0)
>>               goto out;
>>
>> -     if (dev->set_mpu_wkup_lat != NULL)
>> -             dev->set_mpu_wkup_lat(dev->dev, dev->latency);
>> +     /*
>> +      * When waiting for completion of a i2c transfer, we need to
>> +      * set a wake up latency constraint for the MPU. This is to
>> +      * ensure quick enough wakeup from idle, when transfer
>> +      * completes.
>> +      * Used on OMAP3 Only
>> +      */
>> +     if (cpu_is_omap34xx())
>
> We don't want any cpu_is_* checking  in drivers.
>
> If this is only done on certain SoCs, then a flag should be passed from
> device init code via pdata.
>
> That being said, I don't see why this shouldn't be set for all SoCs
> since it's using the FIFO size to determine the latency.
I am OK to have the constraints active for all OMAPs. Side question:
what if different SOCs need different values for the constraint?

>
> Kevin
>

Regards,
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] 36+ messages in thread

* Re: [PATCH 1/8] OMAP: convert I2C driver to PM QoS for latency constraints
  2011-09-16 15:39     ` Jean Pihet
@ 2011-09-16 16:06       ` Kevin Hilman
  0 siblings, 0 replies; 36+ messages in thread
From: Kevin Hilman @ 2011-09-16 16:06 UTC (permalink / raw)
  To: Jean Pihet
  Cc: Linux PM mailing list, linux-omap, Rafael J. Wysocki,
	Paul Walmsley, magnus.damm, Todd Poynor, Jean Pihet

Jean Pihet <jean.pihet@newoldbits.com> writes:

> Kevin,
>
> On Fri, Sep 16, 2011 at 12:46 AM, Kevin Hilman <khilman@ti.com> wrote:
>> Hi Jean,
>>
>> Jean Pihet <jean.pihet@newoldbits.com> writes:
>>
>>> Convert the driver from the outdated omap_pm_set_max_mpu_wakeup_lat
>>> API to the new PM QoS API.
>>> Since the constraint is on the MPU subsystem, use the PM_QOS_CPU_DMA_LATENCY
>>> class of PM QoS. The resulting MPU constraints are used by cpuidle to
>>> decide the next power state of the MPU subsystem.
>>>
>>> Currently only OMAP3 is placing constraints on the MPU.
>>>
>>> Signed-off-by: Jean Pihet <j-pihet@ti.com>
>>
>> [...]
>>
>>> @@ -648,8 +648,16 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
>>>       if (r < 0)
>>>               goto out;
>>>
>>> -     if (dev->set_mpu_wkup_lat != NULL)
>>> -             dev->set_mpu_wkup_lat(dev->dev, dev->latency);
>>> +     /*
>>> +      * When waiting for completion of a i2c transfer, we need to
>>> +      * set a wake up latency constraint for the MPU. This is to
>>> +      * ensure quick enough wakeup from idle, when transfer
>>> +      * completes.
>>> +      * Used on OMAP3 Only
>>> +      */
>>> +     if (cpu_is_omap34xx())
>>
>> We don't want any cpu_is_* checking  in drivers.
>>
>> If this is only done on certain SoCs, then a flag should be passed from
>> device init code via pdata.
>>
>> That being said, I don't see why this shouldn't be set for all SoCs
>> since it's using the FIFO size to determine the latency.
> I am OK to have the constraints active for all OMAPs. Side question:
> what if different SOCs need different values for the constraint?

This latency calculation is based on FIFO size and drain rate, so it
should be completely SoC independent.

However, if for some reason there are SoC dependencies, the SoC specific
parts need to be passed in to the driver.

Kevin
--
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] 36+ messages in thread

* [PATCH v2 0/8] PM QoS: implement the OMAP low level constraints management code
@ 2011-09-21 16:14 Jean Pihet
  2011-09-21 16:14 ` [PATCH 1/8] OMAP: convert I2C driver to PM QoS for latency constraints Jean Pihet
                   ` (8 more replies)
  0 siblings, 9 replies; 36+ messages in thread
From: Jean Pihet @ 2011-09-21 16:14 UTC (permalink / raw)
  To: Kevin Hilman, Linux PM mailing list, linux-omap,
	Rafael J. Wysocki, Paul Walmsley
  Cc: Jean Pihet

. Convert the OMAP I2C driver to the PM QoS API for MPU latency constraints
. Remove the remove the latency related functions from OMAP PM in favor of
  the generic per-device PM QoS API
. 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 power
  states, through the hwmod and pwrdm layers
. Add cpuidle and power domains wake-up latency figures for OMAP3, cf. [1]
  for the details on where the numbers are 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. validate the constraints framework on OMAP4 HW (done on OMAP3)
2. 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
3. Further clean-up the OMAP PM layer, use the generic frameworks instead (OPP,
   PM QoS...)


Based on the pm-qos branch of the linux-pm git tree (3.1.0-rc3), cf. [2].

Tested 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/rafael/linux-pm.git


Jean Pihet (8):
  OMAP: convert I2C driver to PM QoS for latency constraints
  OMAP: PM: remove the latency related functions from the API
  OMAP2+: powerdomain: control power domains next state
  OMAP2+: omap_hwmod: manage the wake-up latency constraints
  OMAP: PM: register to the per-device PM QoS framework
  OMAP3: cpuidle: next C-state decision depends on the PM QoS MPU and
    CORE constraints
  OMAP3: update cpuidle latency and threshold figures
  OMAP3: powerdomain data: add wake-up latency figures

 Documentation/arm/OMAP/omap_pm               |   55 ++------
 arch/arm/mach-omap2/cpuidle34xx.c            |   77 ++++++-----
 arch/arm/mach-omap2/omap_hwmod.c             |   26 ++++-
 arch/arm/mach-omap2/pm.c                     |   63 ++++++++
 arch/arm/mach-omap2/pm.h                     |   17 ++-
 arch/arm/mach-omap2/powerdomain.c            |  197 ++++++++++++++++++++++++++
 arch/arm/mach-omap2/powerdomain.h            |   35 +++++-
 arch/arm/mach-omap2/powerdomains3xxx_data.c  |   78 ++++++++++
 arch/arm/plat-omap/i2c.c                     |   20 ---
 arch/arm/plat-omap/include/plat/omap-pm.h    |   99 -------------
 arch/arm/plat-omap/include/plat/omap_hwmod.h |    2 +
 arch/arm/plat-omap/omap-pm-noop.c            |   88 ------------
 drivers/i2c/busses/i2c-omap.c                |   30 ++--
 include/linux/i2c-omap.h                     |    1 -
 14 files changed, 480 insertions(+), 308 deletions(-)

-- 
1.7.4.1


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

* [PATCH 1/8] OMAP: convert I2C driver to PM QoS for latency constraints
  2011-09-21 16:14 [PATCH v2 0/8] PM QoS: implement the OMAP low level constraints management code Jean Pihet
@ 2011-09-21 16:14 ` Jean Pihet
  2011-09-21 16:14 ` [PATCH 2/8] OMAP: PM: remove the latency related functions from the API Jean Pihet
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 36+ messages in thread
From: Jean Pihet @ 2011-09-21 16:14 UTC (permalink / raw)
  To: Kevin Hilman, Linux PM mailing list, linux-omap,
	Rafael J. Wysocki, Paul Walmsley
  Cc: Jean Pihet

Convert the driver from the outdated omap_pm_set_max_mpu_wakeup_lat
API to the new PM QoS API.
Since the constraint is on the MPU subsystem, use the PM_QOS_CPU_DMA_LATENCY
class of PM QoS. The resulting MPU constraints are used by cpuidle to
decide the next power state of the MPU subsystem.

The I2C device latency timing is derived from the FIFO size and the
clock speed and so is applicable to all OMAP SoCs.

Signed-off-by: Jean Pihet <j-pihet@ti.com>
---
 arch/arm/plat-omap/i2c.c      |   20 --------------------
 drivers/i2c/busses/i2c-omap.c |   30 +++++++++++++++---------------
 include/linux/i2c-omap.h      |    1 -
 3 files changed, 15 insertions(+), 36 deletions(-)

diff --git a/arch/arm/plat-omap/i2c.c b/arch/arm/plat-omap/i2c.c
index 3341ca4..e1e2502 100644
--- a/arch/arm/plat-omap/i2c.c
+++ b/arch/arm/plat-omap/i2c.c
@@ -34,7 +34,6 @@
 #include <mach/irqs.h>
 #include <plat/mux.h>
 #include <plat/i2c.h>
-#include <plat/omap-pm.h>
 #include <plat/omap_device.h>
 
 #define OMAP_I2C_SIZE		0x3f
@@ -113,16 +112,6 @@ static inline int omap1_i2c_add_bus(int bus_id)
 
 
 #ifdef CONFIG_ARCH_OMAP2PLUS
-/*
- * XXX This function is a temporary compatibility wrapper - only
- * needed until the I2C driver can be converted to call
- * omap_pm_set_max_dev_wakeup_lat() and handle a return code.
- */
-static void omap_pm_set_max_mpu_wakeup_lat_compat(struct device *dev, long t)
-{
-	omap_pm_set_max_mpu_wakeup_lat(dev, t);
-}
-
 static struct omap_device_pm_latency omap_i2c_latency[] = {
 	[0] = {
 		.deactivate_func	= omap_device_idle_hwmods,
@@ -151,15 +140,6 @@ static inline int omap2_i2c_add_bus(int bus_id)
 	}
 
 	pdata = &i2c_pdata[bus_id - 1];
-	/*
-	 * When waiting for completion of a i2c transfer, we need to
-	 * set a wake up latency constraint for the MPU. This is to
-	 * ensure quick enough wakeup from idle, when transfer
-	 * completes.
-	 * Only omap3 has support for constraints
-	 */
-	if (cpu_is_omap34xx())
-		pdata->set_mpu_wkup_lat = omap_pm_set_max_mpu_wakeup_lat_compat;
 	od = omap_device_build(name, bus_id, oh, pdata,
 			sizeof(struct omap_i2c_bus_platform_data),
 			omap_i2c_latency, ARRAY_SIZE(omap_i2c_latency), 0);
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index 1a766cf..95e5205 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -40,6 +40,7 @@
 #include <linux/slab.h>
 #include <linux/i2c-omap.h>
 #include <linux/pm_runtime.h>
+#include <linux/pm_qos.h>
 
 /* I2C controller revisions */
 #define OMAP_I2C_REV_2			0x20
@@ -179,8 +180,7 @@ struct omap_i2c_dev {
 	struct completion	cmd_complete;
 	struct resource		*ioarea;
 	u32			latency;	/* maximum mpu wkup latency */
-	void			(*set_mpu_wkup_lat)(struct device *dev,
-						    long latency);
+	struct pm_qos_request	pm_qos_request;
 	u32			speed;		/* Speed of bus in Khz */
 	u16			cmd_err;
 	u8			*buf;
@@ -648,8 +648,14 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
 	if (r < 0)
 		goto out;
 
-	if (dev->set_mpu_wkup_lat != NULL)
-		dev->set_mpu_wkup_lat(dev->dev, dev->latency);
+	/*
+	 * When waiting for completion of a i2c transfer, we need to
+	 * set a wake up latency constraint for the MPU. This is to
+	 * ensure quick enough wakeup from idle, when transfer
+	 * completes.
+	 */
+	pm_qos_add_request(&dev->pm_qos_request, PM_QOS_CPU_DMA_LATENCY,
+			   dev->latency);
 
 	for (i = 0; i < num; i++) {
 		r = omap_i2c_xfer_msg(adap, &msgs[i], (i == (num - 1)));
@@ -657,8 +663,7 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
 			break;
 	}
 
-	if (dev->set_mpu_wkup_lat != NULL)
-		dev->set_mpu_wkup_lat(dev->dev, -1);
+	pm_qos_remove_request(&dev->pm_qos_request);
 
 	if (r == 0)
 		r = num;
@@ -1007,13 +1012,10 @@ omap_i2c_probe(struct platform_device *pdev)
 		goto err_release_region;
 	}
 
-	if (pdata != NULL) {
+	if (pdata != NULL)
 		speed = pdata->clkrate;
-		dev->set_mpu_wkup_lat = pdata->set_mpu_wkup_lat;
-	} else {
+	else
 		speed = 100;	/* Default speed */
-		dev->set_mpu_wkup_lat = NULL;
-	}
 
 	dev->speed = speed;
 	dev->idle = 1;
@@ -1066,10 +1068,8 @@ omap_i2c_probe(struct platform_device *pdev)
 			dev->fifo_size = (dev->fifo_size / 2);
 			dev->b_hw = 1; /* Enable hardware fixes */
 		}
-		/* calculate wakeup latency constraint for MPU */
-		if (dev->set_mpu_wkup_lat != NULL)
-			dev->latency = (1000000 * dev->fifo_size) /
-				       (1000 * speed / 8);
+		/* calculate wakeup latency constraint */
+		dev->latency = (1000000 * dev->fifo_size) / (1000 * speed / 8);
 	}
 
 	/* reset ASAP, clearing any IRQs */
diff --git a/include/linux/i2c-omap.h b/include/linux/i2c-omap.h
index 0aa0cbd..d06a8aa 100644
--- a/include/linux/i2c-omap.h
+++ b/include/linux/i2c-omap.h
@@ -32,7 +32,6 @@
 
 struct omap_i2c_bus_platform_data {
 	u32		clkrate;
-	void		(*set_mpu_wkup_lat)(struct device *dev, long set);
 	int		(*device_enable) (struct platform_device *pdev);
 	int		(*device_shutdown) (struct platform_device *pdev);
 	int		(*device_idle) (struct platform_device *pdev);
-- 
1.7.4.1


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

* [PATCH 2/8] OMAP: PM: remove the latency related functions from the API
  2011-09-21 16:14 [PATCH v2 0/8] PM QoS: implement the OMAP low level constraints management code Jean Pihet
  2011-09-21 16:14 ` [PATCH 1/8] OMAP: convert I2C driver to PM QoS for latency constraints Jean Pihet
@ 2011-09-21 16:14 ` Jean Pihet
  2011-09-21 16:14 ` [PATCH 3/8] OMAP2+: powerdomain: control power domains next state Jean Pihet
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 36+ messages in thread
From: Jean Pihet @ 2011-09-21 16:14 UTC (permalink / raw)
  To: Kevin Hilman, Linux PM mailing list, linux-omap,
	Rafael J. Wysocki, Paul Walmsley
  Cc: Jean Pihet

Remove the following functions from the API:
 omap_pm_set_max_mpu_wakeup_lat
 omap_pm_set_max_dev_wakeup_lat
 omap_pm_set_max_sdma_lat

The generic per-device PM QoS functions shall be used instead, cf.
include/linux/pm_qos.h.

Signed-off-by: Jean Pihet <j-pihet@ti.com>
---
 Documentation/arm/OMAP/omap_pm            |   55 +++-------------
 arch/arm/plat-omap/include/plat/omap-pm.h |   99 -----------------------------
 arch/arm/plat-omap/omap-pm-noop.c         |   88 -------------------------
 3 files changed, 9 insertions(+), 233 deletions(-)

diff --git a/Documentation/arm/OMAP/omap_pm b/Documentation/arm/OMAP/omap_pm
index 9012bb0..26f9669 100644
--- a/Documentation/arm/OMAP/omap_pm
+++ b/Documentation/arm/OMAP/omap_pm
@@ -29,21 +29,12 @@ Drivers need to express PM parameters which:
 
 
 This document proposes the OMAP PM interface, including the following
-five power management functions for driver code:
+power management functions for driver code:
 
-1. Set the maximum MPU wakeup latency:
-   (*pdata->set_max_mpu_wakeup_lat)(struct device *dev, unsigned long t)
-
-2. Set the maximum device wakeup latency:
-   (*pdata->set_max_dev_wakeup_lat)(struct device *dev, unsigned long t)
-
-3. Set the maximum system DMA transfer start latency (CORE pwrdm):
-   (*pdata->set_max_sdma_lat)(struct device *dev, long t)
-
-4. Set the minimum bus throughput needed by a device:
+1. Set the minimum bus throughput needed by a device:
    (*pdata->set_min_bus_tput)(struct device *dev, u8 agent_id, unsigned long r)
 
-5. Return the number of times the device has lost context
+2. Return the number of times the device has lost context
    (*pdata->get_dev_context_loss_count)(struct device *dev)
 
 
@@ -55,10 +46,12 @@ The OMAP PM layer is intended to be temporary
 ---------------------------------------------
 
 The intention is that eventually the Linux PM QoS layer should support
-the range of power management features present in OMAP3.  As this
+the range of power management features present in OMAP3. As this
 happens, existing drivers using the OMAP PM interface can be modified
 to use the Linux PM QoS code; and the OMAP PM interface can disappear.
 
+The set_min_bus_tput function shall be converted to a throughput PM QoS
+framework.
 
 Driver usage of the OMAP PM functions
 -------------------------------------
@@ -66,39 +59,9 @@ Driver usage of the OMAP PM functions
 As the 'pdata' in the above examples indicates, these functions are
 exposed to drivers through function pointers in driver .platform_data
 structures.  The function pointers are initialized by the board-*.c
-files to point to the corresponding OMAP PM functions:
-.set_max_dev_wakeup_lat will point to
-omap_pm_set_max_dev_wakeup_lat(), etc.  Other architectures which do
-not support these functions should leave these function pointers set
-to NULL.  Drivers should use the following idiom:
-
-        if (pdata->set_max_dev_wakeup_lat)
-            (*pdata->set_max_dev_wakeup_lat)(dev, t);
-
-The most common usage of these functions will probably be to specify
-the maximum time from when an interrupt occurs, to when the device
-becomes accessible.  To accomplish this, driver writers should use the
-set_max_mpu_wakeup_lat() function to to constrain the MPU wakeup
-latency, and the set_max_dev_wakeup_lat() function to constrain the
-device wakeup latency (from clk_enable() to accessibility).  For
-example,
-
-        /* Limit MPU wakeup latency */
-        if (pdata->set_max_mpu_wakeup_lat)
-            (*pdata->set_max_mpu_wakeup_lat)(dev, tc);
-
-        /* Limit device powerdomain wakeup latency */
-        if (pdata->set_max_dev_wakeup_lat)
-            (*pdata->set_max_dev_wakeup_lat)(dev, td);
-
-        /* total wakeup latency in this example: (tc + td) */
-
-The PM parameters can be overwritten by calling the function again
-with the new value.  The settings can be removed by calling the
-function with a t argument of -1 (except in the case of
-set_max_bus_tput(), which should be called with an r argument of 0).
-
-The fifth function above, omap_pm_get_dev_context_loss_count(),
+files to point to the corresponding OMAP PM functions.
+
+The omap_pm_get_dev_context_loss_count() function
 is intended as an optimization to allow drivers to determine whether the
 device has lost its internal context.  If context has been lost, the
 driver must restore its internal context before proceeding.
diff --git a/arch/arm/plat-omap/include/plat/omap-pm.h b/arch/arm/plat-omap/include/plat/omap-pm.h
index 0840df8..c371364 100644
--- a/arch/arm/plat-omap/include/plat/omap-pm.h
+++ b/arch/arm/plat-omap/include/plat/omap-pm.h
@@ -62,44 +62,6 @@ void omap_pm_if_exit(void);
  * Device-driver-originated constraints (via board-*.c files, platform_data)
  */
 
-
-/**
- * omap_pm_set_max_mpu_wakeup_lat - set the maximum MPU wakeup latency
- * @dev: struct device * requesting the constraint
- * @t: maximum MPU wakeup latency in microseconds
- *
- * Request that the maximum interrupt latency for the MPU to be no
- * greater than @t microseconds. "Interrupt latency" in this case is
- * defined as the elapsed time from the occurrence of a hardware or
- * timer interrupt to the time when the device driver's interrupt
- * service routine has been entered by the MPU.
- *
- * It is intended that underlying PM code will use this information to
- * determine what power state to put the MPU powerdomain into, and
- * possibly the CORE powerdomain as well, since interrupt handling
- * code currently runs from SDRAM.  Advanced PM or board*.c code may
- * also configure interrupt controller priorities, OCP bus priorities,
- * CPU speed(s), etc.
- *
- * This function will not affect device wakeup latency, e.g., time
- * elapsed from when a device driver enables a hardware device with
- * clk_enable(), to when the device is ready for register access or
- * other use.  To control this device wakeup latency, use
- * omap_pm_set_max_dev_wakeup_lat()
- *
- * Multiple calls to omap_pm_set_max_mpu_wakeup_lat() will replace the
- * previous t value.  To remove the latency target for the MPU, call
- * with t = -1.
- *
- * XXX This constraint will be deprecated soon in favor of the more
- * general omap_pm_set_max_dev_wakeup_lat()
- *
- * Returns -EINVAL for an invalid argument, -ERANGE if the constraint
- * is not satisfiable, or 0 upon success.
- */
-int omap_pm_set_max_mpu_wakeup_lat(struct device *dev, long t);
-
-
 /**
  * omap_pm_set_min_bus_tput - set minimum bus throughput needed by device
  * @dev: struct device * requesting the constraint
@@ -131,67 +93,6 @@ int omap_pm_set_max_mpu_wakeup_lat(struct device *dev, long t);
  */
 int omap_pm_set_min_bus_tput(struct device *dev, u8 agent_id, unsigned long r);
 
-
-/**
- * omap_pm_set_max_dev_wakeup_lat - set the maximum device enable latency
- * @req_dev: struct device * requesting the constraint, or NULL if none
- * @dev: struct device * to set the constraint one
- * @t: maximum device wakeup latency in microseconds
- *
- * Request that the maximum amount of time necessary for a device @dev
- * to become accessible after its clocks are enabled should be no
- * greater than @t microseconds.  Specifically, this represents the
- * time from when a device driver enables device clocks with
- * clk_enable(), to when the register reads and writes on the device
- * will succeed.  This function should be called before clk_disable()
- * is called, since the power state transition decision may be made
- * during clk_disable().
- *
- * It is intended that underlying PM code will use this information to
- * determine what power state to put the powerdomain enclosing this
- * device into.
- *
- * Multiple calls to omap_pm_set_max_dev_wakeup_lat() will replace the
- * previous wakeup latency values for this device.  To remove the
- * wakeup latency restriction for this device, call with t = -1.
- *
- * Returns -EINVAL for an invalid argument, -ERANGE if the constraint
- * is not satisfiable, or 0 upon success.
- */
-int omap_pm_set_max_dev_wakeup_lat(struct device *req_dev, struct device *dev,
-				   long t);
-
-
-/**
- * omap_pm_set_max_sdma_lat - set the maximum system DMA transfer start latency
- * @dev: struct device *
- * @t: maximum DMA transfer start latency in microseconds
- *
- * Request that the maximum system DMA transfer start latency for this
- * device 'dev' should be no greater than 't' microseconds.  "DMA
- * transfer start latency" here is defined as the elapsed time from
- * when a device (e.g., McBSP) requests that a system DMA transfer
- * start or continue, to the time at which data starts to flow into
- * that device from the system DMA controller.
- *
- * It is intended that underlying PM code will use this information to
- * determine what power state to put the CORE powerdomain into.
- *
- * Since system DMA transfers may not involve the MPU, this function
- * will not affect MPU wakeup latency.  Use set_max_cpu_lat() to do
- * so.  Similarly, this function will not affect device wakeup latency
- * -- use set_max_dev_wakeup_lat() to affect that.
- *
- * Multiple calls to set_max_sdma_lat() will replace the previous t
- * value for this device.  To remove the maximum DMA latency for this
- * device, call with t = -1.
- *
- * Returns -EINVAL for an invalid argument, -ERANGE if the constraint
- * is not satisfiable, or 0 upon success.
- */
-int omap_pm_set_max_sdma_lat(struct device *dev, long t);
-
-
 /**
  * omap_pm_set_min_clk_rate - set minimum clock rate requested by @dev
  * @dev: struct device * requesting the constraint
diff --git a/arch/arm/plat-omap/omap-pm-noop.c b/arch/arm/plat-omap/omap-pm-noop.c
index b0471bb2..bf9ad37 100644
--- a/arch/arm/plat-omap/omap-pm-noop.c
+++ b/arch/arm/plat-omap/omap-pm-noop.c
@@ -33,34 +33,6 @@ static u32 dummy_context_loss_counter;
  * Device-driver-originated constraints (via board-*.c files)
  */
 
-int omap_pm_set_max_mpu_wakeup_lat(struct device *dev, long t)
-{
-	if (!dev || t < -1) {
-		WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__);
-		return -EINVAL;
-	};
-
-	if (t == -1)
-		pr_debug("OMAP PM: remove max MPU wakeup latency constraint: "
-			 "dev %s\n", dev_name(dev));
-	else
-		pr_debug("OMAP PM: add max MPU wakeup latency constraint: "
-			 "dev %s, t = %ld usec\n", dev_name(dev), t);
-
-	/*
-	 * For current Linux, this needs to map the MPU to a
-	 * powerdomain, then go through the list of current max lat
-	 * constraints on the MPU and find the smallest.  If
-	 * the latency constraint has changed, the code should
-	 * recompute the state to enter for the next powerdomain
-	 * state.
-	 *
-	 * TI CDP code can call constraint_set here.
-	 */
-
-	return 0;
-}
-
 int omap_pm_set_min_bus_tput(struct device *dev, u8 agent_id, unsigned long r)
 {
 	if (!dev || (agent_id != OCP_INITIATOR_AGENT &&
@@ -88,66 +60,6 @@ int omap_pm_set_min_bus_tput(struct device *dev, u8 agent_id, unsigned long r)
 	return 0;
 }
 
-int omap_pm_set_max_dev_wakeup_lat(struct device *req_dev, struct device *dev,
-				   long t)
-{
-	if (!req_dev || !dev || t < -1) {
-		WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__);
-		return -EINVAL;
-	};
-
-	if (t == -1)
-		pr_debug("OMAP PM: remove max device latency constraint: "
-			 "dev %s\n", dev_name(dev));
-	else
-		pr_debug("OMAP PM: add max device latency constraint: "
-			 "dev %s, t = %ld usec\n", dev_name(dev), t);
-
-	/*
-	 * For current Linux, this needs to map the device to a
-	 * powerdomain, then go through the list of current max lat
-	 * constraints on that powerdomain and find the smallest.  If
-	 * the latency constraint has changed, the code should
-	 * recompute the state to enter for the next powerdomain
-	 * state.  Conceivably, this code should also determine
-	 * whether to actually disable the device clocks or not,
-	 * depending on how long it takes to re-enable the clocks.
-	 *
-	 * TI CDP code can call constraint_set here.
-	 */
-
-	return 0;
-}
-
-int omap_pm_set_max_sdma_lat(struct device *dev, long t)
-{
-	if (!dev || t < -1) {
-		WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__);
-		return -EINVAL;
-	};
-
-	if (t == -1)
-		pr_debug("OMAP PM: remove max DMA latency constraint: "
-			 "dev %s\n", dev_name(dev));
-	else
-		pr_debug("OMAP PM: add max DMA latency constraint: "
-			 "dev %s, t = %ld usec\n", dev_name(dev), t);
-
-	/*
-	 * For current Linux PM QOS params, this code should scan the
-	 * list of maximum CPU and DMA latencies and select the
-	 * smallest, then set cpu_dma_latency pm_qos_param
-	 * accordingly.
-	 *
-	 * For future Linux PM QOS params, with separate CPU and DMA
-	 * latency params, this code should just set the dma_latency param.
-	 *
-	 * TI CDP code can call constraint_set here.
-	 */
-
-	return 0;
-}
-
 int omap_pm_set_min_clk_rate(struct device *dev, struct clk *c, long r)
 {
 	if (!dev || !c || r < 0) {
-- 
1.7.4.1


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

* [PATCH 3/8] OMAP2+: powerdomain: control power domains next state
  2011-09-21 16:14 [PATCH v2 0/8] PM QoS: implement the OMAP low level constraints management code Jean Pihet
  2011-09-21 16:14 ` [PATCH 1/8] OMAP: convert I2C driver to PM QoS for latency constraints Jean Pihet
  2011-09-21 16:14 ` [PATCH 2/8] OMAP: PM: remove the latency related functions from the API Jean Pihet
@ 2011-09-21 16:14 ` Jean Pihet
  2011-09-21 16:14 ` [PATCH 4/8] OMAP2+: omap_hwmod: manage the wake-up latency constraints Jean Pihet
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 36+ messages in thread
From: Jean Pihet @ 2011-09-21 16:14 UTC (permalink / raw)
  To: Kevin Hilman, Linux PM mailing list, linux-omap,
	Rafael J. Wysocki, Paul Walmsley
  Cc: Jean Pihet

When a PM QoS device latency constraint is requested or removed the
PM QoS layer notifies the underlying layer with the updated aggregated
constraint value. The constraint is stored in the powerdomain constraints
list and then applied to the corresponding power domain.
The power domains get the next power state programmed directly in the
registers via pwrdm_wakeuplat_update_pwrst.

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 |  197 +++++++++++++++++++++++++++++++++++++
 arch/arm/mach-omap2/powerdomain.h |   35 ++++++-
 2 files changed, 230 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
index 9af0847..8fc0aaa 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"
@@ -104,6 +106,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-od wake-up constraints data */
+	spin_lock_init(&pwrdm->wkup_lat_plist_lock);
+	plist_head_init(&pwrdm->wkup_lat_plist_head);
+	pwrdm->wkup_lat_next_state = PWRDM_POWER_OFF;
+
+	/* Initialize the pwrdm state */
 	pwrdm_wait_transition(pwrdm);
 	pwrdm->state = pwrdm_read_pwrst(pwrdm);
 	pwrdm->state_counter[pwrdm->state] = 1;
@@ -191,6 +199,83 @@ 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 upon success.
+ */
+static int pwrdm_wakeuplat_update_pwrst(struct powerdomain *pwrdm,
+					long min_latency)
+{
+	int ret = 0, new_state;
+
+	if (!pwrdm) {
+		WARN(1, "powerdomain: %s: invalid parameter(s)", __func__);
+		return -EINVAL;
+	}
+
+	/*
+	 * Apply constraints to power domains by programming
+	 * the pwrdm next power state.
+	 */
+
+	/*
+	 * Find the next supported power state with
+	 * wakeup latency < minimum constraint
+	 */
+	for (new_state = 0x0; new_state < PWRDM_MAX_PWRSTS; new_state++) {
+		if (min_latency == PM_QOS_DEV_LAT_DEFAULT_VALUE)
+			break;
+		if ((pwrdm->wakeup_lat[new_state] != UNSUP_STATE) &&
+		    (pwrdm->wakeup_lat[new_state] <= min_latency))
+			break;
+	}
+
+	switch (new_state) {
+	case PWRDM_FUNC_PWRST_OFF:
+		new_state = PWRDM_POWER_OFF;
+		break;
+	case PWRDM_FUNC_PWRST_OSWR:
+		pwrdm_set_logic_retst(pwrdm, PWRDM_POWER_OFF);
+		new_state = PWRDM_POWER_RET;
+		break;
+	case PWRDM_FUNC_PWRST_CSWR:
+		pwrdm_set_logic_retst(pwrdm, PWRDM_POWER_RET);
+		new_state = PWRDM_POWER_RET;
+		break;
+	case PWRDM_FUNC_PWRST_INACTIVE:
+		new_state = PWRDM_POWER_INACTIVE;
+		break;
+	case PWRDM_FUNC_PWRST_ON:
+		new_state = PWRDM_POWER_ON;
+		break;
+	default:
+		pr_warn("powerdomain: requested latency constraint not "
+			"supported %s set to ON state\n", pwrdm->name);
+		new_state = PWRDM_POWER_ON;
+		break;
+	}
+
+	pwrdm->wkup_lat_next_state = new_state;
+	if (pwrdm_read_next_pwrst(pwrdm) != new_state)
+		ret = omap_set_pwrdm_state(pwrdm, new_state);
+
+	pr_debug("powerdomain: %s pwrst: curr=%d, prev=%d next=%d "
+		 "min_latency=%ld, set_state=%d\n", pwrdm->name,
+		 pwrdm_read_pwrst(pwrdm), pwrdm_read_prev_pwrst(pwrdm),
+		 pwrdm_read_next_pwrst(pwrdm), min_latency, new_state);
+
+	return ret;
+}
+
 /* Public functions */
 
 /**
@@ -930,6 +1015,118 @@ int pwrdm_post_transition(void)
 	return 0;
 }
 
+/*
+ * pwrdm_set_wkup_lat_constraint - Set/update/remove 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. The value of PM_QOS_DEV_LAT_DEFAULT_VALUE removes
+ *  the constraint.
+ *
+ * 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.
+ * Constraint removal: Removes the identifier's entry from powerdomain's
+ * wakeup latency constraint list.
+ *
+ * Applies the strongest constraint value for the given pwrdm by calling
+ * pwrdm_wakeuplat_update_pwrst.
+ *
+ * Returns 0 upon success or a negative value in case of error.
+ *
+ * The caller must check the validity of the parameters.
+ */
+int pwrdm_set_wkup_lat_constraint(struct powerdomain *pwrdm, void *cookie,
+				  long min_latency)
+{
+	struct pwrdm_wkup_constraints_entry *user = NULL;
+	struct pwrdm_wkup_constraints_entry *tmp_user, *new_user = NULL;
+	int ret = 0, free_new_user = 0, free_node = 0;
+	long value = PM_QOS_DEV_LAT_DEFAULT_VALUE;
+	unsigned long flags;
+
+	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) {
+		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;
+		}
+		free_new_user = 1;
+	}
+
+	spin_lock_irqsave(&pwrdm->wkup_lat_plist_lock, flags);
+
+	/* 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 (min_latency != PM_QOS_DEV_LAT_DEFAULT_VALUE) {
+		/* If nothing to update, job done */
+		if (user && (user->node.prio == min_latency))
+			goto exit_ok;
+
+		if (!user) {
+			/* Add new entry to the list */
+			user = new_user;
+			user->cookie = cookie;
+			free_new_user = 0;
+		} else {
+			/* Update existing entry */
+			plist_del(&user->node, &pwrdm->wkup_lat_plist_head);
+		}
+
+		plist_node_init(&user->node, min_latency);
+		plist_add(&user->node, &pwrdm->wkup_lat_plist_head);
+	} else {
+		if (user) {
+			/* Remove the constraint from the list */
+			plist_del(&user->node, &pwrdm->wkup_lat_plist_head);
+			free_node = 1;
+		} else {
+			/* Constraint not existing or list empty, do nothing */
+			ret = -EINVAL;
+			goto exit_error;
+		}
+
+	}
+
+exit_ok:
+	/* Find the strongest constraint from the list */
+	if (!plist_head_empty(&pwrdm->wkup_lat_plist_head))
+		value = plist_first(&pwrdm->wkup_lat_plist_head)->prio;
+
+	spin_unlock_irqrestore(&pwrdm->wkup_lat_plist_lock, flags);
+
+	if (free_node)
+		kfree(user);
+
+	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);
+	pwrdm_wakeuplat_update_pwrst(pwrdm, value);
+
+	return 0;
+
+exit_error:
+	spin_unlock_irqrestore(&pwrdm->wkup_lat_plist_lock, flags);
+
+	return ret;
+}
+
 /**
  * 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 d23d979..41630ec 100644
--- a/arch/arm/mach-omap2/powerdomain.h
+++ b/arch/arm/mach-omap2/powerdomain.h
@@ -19,7 +19,9 @@
 
 #include <linux/types.h>
 #include <linux/list.h>
-
+#include <linux/plist.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
 #include <linux/atomic.h>
 
 #include <plat/cpu.h>
@@ -43,6 +45,16 @@
 #define PWRSTS_RET_ON		(PWRSTS_RET | PWRSTS_ON)
 #define PWRSTS_OFF_RET_ON	(PWRSTS_OFF_RET | PWRSTS_ON)
 
+/* Powerdomain functional power states */
+#define PWRDM_FUNC_PWRST_OFF		0x0
+#define PWRDM_FUNC_PWRST_OSWR		0x1
+#define PWRDM_FUNC_PWRST_CSWR		0x2
+#define PWRDM_FUNC_PWRST_INACTIVE	0x3
+#define PWRDM_FUNC_PWRST_ON		0x4
+
+#define PWRDM_MAX_FUNC_PWRSTS	5
+
+#define UNSUP_STATE		-1
 
 /* Powerdomain flags */
 #define PWRDM_HAS_HDWR_SAR	(1 << 0) /* hardware save-and-restore support */
@@ -93,7 +105,13 @@ struct powerdomain;
  * @state_counter:
  * @timer:
  * @state_timer:
- *
+ * @wakeup_lat: wakeup latencies (in us) for possible powerdomain power states
+ * Note about the wakeup latencies ordering: the values must be sorted
+ *  in decremental order
+ * @wkup_lat_plist_head: pwrdm wake-up latency constraints list
+ * @wkup_lat_plist_lock: spinlock that protects the constraints lists
+ *  domains states
+ * @wkup_lat_next_state: next pwrdm state, calculated from the constraints list
  * @prcm_partition possible values are defined in mach-omap2/prcm44xx.h.
  */
 struct powerdomain {
@@ -118,6 +136,16 @@ struct powerdomain {
 	s64 timer;
 	s64 state_timer[PWRDM_MAX_PWRSTS];
 #endif
+	const s32 wakeup_lat[PWRDM_MAX_FUNC_PWRSTS];
+	struct plist_head wkup_lat_plist_head;
+	spinlock_t 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;
 };
 
 /**
@@ -207,6 +235,9 @@ 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_set_wkup_lat_constraint(struct powerdomain *pwrdm, void *cookie,
+				  long min_latency);
 u32 pwrdm_get_context_loss_count(struct powerdomain *pwrdm);
 bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm);
 
-- 
1.7.4.1


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

* [PATCH 4/8] OMAP2+: omap_hwmod: manage the wake-up latency constraints
  2011-09-21 16:14 [PATCH v2 0/8] PM QoS: implement the OMAP low level constraints management code Jean Pihet
                   ` (2 preceding siblings ...)
  2011-09-21 16:14 ` [PATCH 3/8] OMAP2+: powerdomain: control power domains next state Jean Pihet
@ 2011-09-21 16:14 ` Jean Pihet
  2011-09-21 16:14 ` [PATCH 5/8] OMAP: PM: register to the per-device PM QoS framework Jean Pihet
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 36+ messages in thread
From: Jean Pihet @ 2011-09-21 16:14 UTC (permalink / raw)
  To: Kevin Hilman, Linux PM mailing list, linux-omap,
	Rafael J. Wysocki, Paul Walmsley
  Cc: Jean Pihet

Hwmod is queried from the OMAP_PM layer to manage the power domains
wake-up latency constraints. Hwmod retrieves the correct power domain
and if it exists it calls the corresponding power domain function.

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/omap_hwmod.c             |   26 +++++++++++++++++++++++++-
 arch/arm/plat-omap/include/plat/omap_hwmod.h |    2 ++
 2 files changed, 27 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index 84cc0bd..c6b1cc9 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -143,6 +143,7 @@
 #include "powerdomain.h"
 #include <plat/clock.h>
 #include <plat/omap_hwmod.h>
+#include <plat/omap_device.h>
 #include <plat/prcm.h>
 
 #include "cm2xxx_3xxx.h"
@@ -2618,11 +2619,34 @@ ohsps_unlock:
 	return ret;
 }
 
+/*
+ * omap_hwmod_set_wkup_constraint- set/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.
+ * @min_latency: the minimum allowed wake-up latency for @oh.
+ *
+ * Returns 0 upon success.
+ */
+int omap_hwmod_set_wkup_lat_constraint(struct omap_hwmod *oh,
+				       void *cookie, long min_latency)
+{
+	struct powerdomain *pwrdm = omap_hwmod_get_pwrdm(oh);
+
+	if (!pwrdm) {
+		pr_err("%s: Error: could not find powerdomain "
+		       "for %s\n", __func__, oh->name);
+		return -EINVAL;
+	}
+
+	return pwrdm_set_wkup_lat_constraint(pwrdm, cookie, min_latency);
+}
+
 /**
  * omap_hwmod_get_context_loss_count - get lost context count
  * @oh: struct omap_hwmod *
  *
- * Query the powerdomain of of @oh to get the context loss
+ * Query the powerdomain of @oh to get the context loss
  * count for this device.
  *
  * Returns the context loss count of the powerdomain assocated with @oh
diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h
index 0e329ca..75e0e7a 100644
--- a/arch/arm/plat-omap/include/plat/omap_hwmod.h
+++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h
@@ -603,6 +603,8 @@ int omap_hwmod_for_each_by_class(const char *classname,
 				 void *user);
 
 int omap_hwmod_set_postsetup_state(struct omap_hwmod *oh, u8 state);
+int omap_hwmod_set_wkup_lat_constraint(struct omap_hwmod *oh, void *cookie,
+				       long min_latency);
 u32 omap_hwmod_get_context_loss_count(struct omap_hwmod *oh);
 
 int omap_hwmod_no_setup_reset(struct omap_hwmod *oh);
-- 
1.7.4.1


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

* [PATCH 5/8] OMAP: PM: register to the per-device PM QoS framework
  2011-09-21 16:14 [PATCH v2 0/8] PM QoS: implement the OMAP low level constraints management code Jean Pihet
                   ` (3 preceding siblings ...)
  2011-09-21 16:14 ` [PATCH 4/8] OMAP2+: omap_hwmod: manage the wake-up latency constraints Jean Pihet
@ 2011-09-21 16:14 ` Jean Pihet
  2011-09-21 16:14 ` [PATCH 6/8] OMAP3: cpuidle: next C-state decision depends on the PM QoS MPU and CORE constraints Jean Pihet
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 36+ messages in thread
From: Jean Pihet @ 2011-09-21 16:14 UTC (permalink / raw)
  To: Kevin Hilman, Linux PM mailing list, linux-omap,
	Rafael J. Wysocki, Paul Walmsley
  Cc: Jean Pihet

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>
---
 arch/arm/mach-omap2/pm.c |   63 ++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 63 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
index 3feb359..58b4b76 100644
--- a/arch/arm/mach-omap2/pm.c
+++ b/arch/arm/mach-omap2/pm.c
@@ -11,13 +11,16 @@
 
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/notifier.h>
 #include <linux/io.h>
 #include <linux/err.h>
 #include <linux/opp.h>
+#include <linux/pm_qos.h>
 
 #include <plat/omap-pm.h>
 #include <plat/omap_device.h>
 #include <plat/common.h>
+#include <plat/omap_hwmod.h>
 
 #include "voltage.h"
 #include "powerdomain.h"
@@ -242,11 +245,71 @@ static void __init omap4_init_voltages(void)
 	omap2_set_init_voltage("iva", "dpll_iva_m5x2_ck", iva_dev);
 }
 
+/* Interface to the per-device PM QoS framework */
+static int omap2_dev_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;
+
+	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 -EINVAL;
+	}
+
+	/* Find the associated omap_device for dev */
+	od = container_of(pdev, struct omap_device, pdev);
+	if (od->hwmods_cnt != 1) {
+		pr_err("%s: Error: No unique hwmod for device %s\n",
+		       __func__, dev_name(dev_pm_qos_req->dev));
+		return -EINVAL;
+	}
+
+	/* Find the primary omap_hwmod for dev */
+	oh = od->hwmods[0];
+
+	pr_debug("OMAP PM CONSTRAINTS: req@0x%p, dev=0x%p, new_value=%lu\n",
+		 req, dev_pm_qos_req->dev, new_value);
+
+	/* Apply the constraint */
+	return omap_hwmod_set_wkup_lat_constraint(oh, dev_pm_qos_req,
+						  new_value);
+}
+
+static struct notifier_block omap2_dev_pm_qos_notifier = {
+	.notifier_call	= omap2_dev_pm_qos_handler,
+};
+
+static int __init omap2_dev_pm_qos_init(void)
+{
+	int ret;
+
+	ret = dev_pm_qos_add_global_notifier(&omap2_dev_pm_qos_notifier);
+	if (ret)
+		WARN(1, KERN_ERR "Cannot add global notifier for dev PM QoS\n");
+
+	return ret;
+}
+
 static int __init omap2_common_pm_init(void)
 {
 	omap2_init_processor_devices();
 	omap_pm_if_init();
 
+	/* Register to the per-device PM QoS framework */
+	omap2_dev_pm_qos_init();
+
 	return 0;
 }
 postcore_initcall(omap2_common_pm_init);
-- 
1.7.4.1


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

* [PATCH 6/8] OMAP3: cpuidle: next C-state decision depends on the PM QoS MPU and CORE constraints
  2011-09-21 16:14 [PATCH v2 0/8] PM QoS: implement the OMAP low level constraints management code Jean Pihet
                   ` (4 preceding siblings ...)
  2011-09-21 16:14 ` [PATCH 5/8] OMAP: PM: register to the per-device PM QoS framework Jean Pihet
@ 2011-09-21 16:14 ` Jean Pihet
  2011-09-21 16:14 ` [PATCH 7/8] OMAP3: update cpuidle latency and threshold figures Jean Pihet
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 36+ messages in thread
From: Jean Pihet @ 2011-09-21 16:14 UTC (permalink / raw)
  To: Kevin Hilman, Linux PM mailing list, linux-omap,
	Rafael J. Wysocki, Paul Walmsley
  Cc: Jean Pihet

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>
---
 arch/arm/mach-omap2/cpuidle34xx.c |   49 ++++++++++++++++++++++---------------
 arch/arm/mach-omap2/pm.h          |   17 +++++++++++-
 2 files changed, 44 insertions(+), 22 deletions(-)

diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c
index 4bf6e6e..1b8e0da 100644
--- a/arch/arm/mach-omap2/cpuidle34xx.c
+++ b/arch/arm/mach-omap2/cpuidle34xx.c
@@ -37,7 +37,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
@@ -72,14 +72,14 @@ 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;
@@ -92,9 +92,13 @@ static int _cpuidle_deny_idle(struct powerdomain *pwrdm,
  *
  * 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 int omap3_enter_idle(struct cpuidle_device *dev,
-			struct cpuidle_state *state)
+			    struct cpuidle_state *state)
 {
 	struct omap3_idle_statedata *cx = cpuidle_get_statedata(state);
 	struct timespec ts_preidle, ts_postidle, ts_idle;
@@ -146,8 +150,11 @@ return_sleep_time:
  * Else, this function searches for a lower c-state which is still
  * valid.
  *
- * 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 struct cpuidle_state *next_valid_state(struct cpuidle_device *dev,
 					      struct cpuidle_state *curr)
@@ -156,6 +163,8 @@ static struct cpuidle_state *next_valid_state(struct cpuidle_device *dev,
 	struct omap3_idle_statedata *cx = cpuidle_get_statedata(curr);
 	u32 mpu_deepest_state = PWRDM_POWER_RET;
 	u32 core_deepest_state = PWRDM_POWER_RET;
+	u32 mpu_pm_qos_next_state = mpu_pd->wkup_lat_next_state;
+	u32 core_pm_qos_next_state = core_pd->wkup_lat_next_state;
 
 	if (enable_off_mode) {
 		mpu_deepest_state = PWRDM_POWER_OFF;
@@ -171,7 +180,9 @@ static struct cpuidle_state *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 curr;
 	} else {
 		int idx = OMAP3_NUM_STATES - 1;
@@ -196,7 +207,9 @@ static struct cpuidle_state *next_valid_state(struct cpuidle_device *dev,
 			cx = cpuidle_get_statedata(&dev->states[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 = &dev->states[idx];
 				break;
 			}
@@ -215,8 +228,12 @@ static struct cpuidle_state *next_valid_state(struct cpuidle_device *dev,
  * @dev: cpuidle device
  * @state: The 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_state *state)
@@ -241,19 +258,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 = next_valid_state(dev, state);
 
 	/*
 	 * Prevent PER off if CORE is not in retention or off as this
 	 * would disable PER wakeups completely.
 	 */
-	cx = cpuidle_get_statedata(state);
+	cx = cpuidle_get_statedata(new_state);
 	core_next_state = cx->core_state;
 	per_next_state = per_saved_state = pwrdm_read_next_pwrst(per_pd);
 	if ((per_next_state == PWRDM_POWER_OFF) &&
@@ -264,8 +275,6 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
 	if (per_next_state != per_saved_state)
 		pwrdm_set_next_pwrst(per_pd, per_next_state);
 
-	new_state = next_valid_state(dev, state);
-
 select_state:
 	dev->last_state = new_state;
 	ret = omap3_enter_idle(dev, new_state);
diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
index 4e166ad..aca3b6c 100644
--- a/arch/arm/mach-omap2/pm.h
+++ b/arch/arm/mach-omap2/pm.h
@@ -43,9 +43,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.4.1


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

* [PATCH 7/8] OMAP3: update cpuidle latency and threshold figures
  2011-09-21 16:14 [PATCH v2 0/8] PM QoS: implement the OMAP low level constraints management code Jean Pihet
                   ` (5 preceding siblings ...)
  2011-09-21 16:14 ` [PATCH 6/8] OMAP3: cpuidle: next C-state decision depends on the PM QoS MPU and CORE constraints Jean Pihet
@ 2011-09-21 16:14 ` Jean Pihet
  2011-10-12  2:48   ` Ming Lei
  2011-09-21 16:14 ` [PATCH 8/8] OMAP3: powerdomain data: add wake-up latency figures Jean Pihet
  2011-09-21 16:24 ` [PATCH v2 0/8] PM QoS: implement the OMAP low level constraints management code jean.pihet
  8 siblings, 1 reply; 36+ messages in thread
From: Jean Pihet @ 2011-09-21 16:14 UTC (permalink / raw)
  To: Kevin Hilman, Linux PM mailing list, linux-omap,
	Rafael J. Wysocki, Paul Walmsley
  Cc: Jean Pihet

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 magically 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>
---
 arch/arm/mach-omap2/cpuidle34xx.c |   28 ++++++++++++++--------------
 1 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c
index 1b8e0da..4b3e994 100644
--- a/arch/arm/mach-omap2/cpuidle34xx.c
+++ b/arch/arm/mach-omap2/cpuidle34xx.c
@@ -44,20 +44,20 @@
  * pass these details from the board file.
  */
 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.4.1


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

* [PATCH 8/8] OMAP3: powerdomain data: add wake-up latency figures
  2011-09-21 16:14 [PATCH v2 0/8] PM QoS: implement the OMAP low level constraints management code Jean Pihet
                   ` (6 preceding siblings ...)
  2011-09-21 16:14 ` [PATCH 7/8] OMAP3: update cpuidle latency and threshold figures Jean Pihet
@ 2011-09-21 16:14 ` Jean Pihet
  2011-09-21 16:24 ` [PATCH v2 0/8] PM QoS: implement the OMAP low level constraints management code jean.pihet
  8 siblings, 0 replies; 36+ messages in thread
From: Jean Pihet @ 2011-09-21 16:14 UTC (permalink / raw)
  To: Kevin Hilman, Linux PM mailing list, linux-omap,
	Rafael J. Wysocki, Paul Walmsley
  Cc: Jean Pihet

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 magically 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>
---
 arch/arm/mach-omap2/powerdomains3xxx_data.c |   78 +++++++++++++++++++++++++++
 1 files changed, 78 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/powerdomains3xxx_data.c b/arch/arm/mach-omap2/powerdomains3xxx_data.c
index 469a920..32922bb 100644
--- a/arch/arm/mach-omap2/powerdomains3xxx_data.c
+++ b/arch/arm/mach-omap2/powerdomains3xxx_data.c
@@ -31,6 +31,14 @@
 
 /*
  * Powerdomains
+ *
+ * The wakeup_lat values are derived from measurements on
+ * the actual target.
+ *
+ * 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.
  */
 
 static struct powerdomain iva2_pwrdm = {
@@ -52,6 +60,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,
+	},
 };
 
 static struct powerdomain mpu_3xxx_pwrdm = {
@@ -68,6 +83,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,
+	},
 };
 
 /*
@@ -98,6 +120,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,
+	},
 };
 
 static struct powerdomain core_3xxx_es3_1_pwrdm = {
@@ -121,6 +150,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,
+	},
 };
 
 static struct powerdomain dss_pwrdm = {
@@ -136,6 +172,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,
+	},
 };
 
 /*
@@ -157,6 +200,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,
+	},
 };
 
 static struct powerdomain cam_pwrdm = {
@@ -172,6 +222,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,
+	},
 };
 
 static struct powerdomain per_pwrdm = {
@@ -187,6 +244,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,
+	},
 };
 
 static struct powerdomain emu_pwrdm = {
@@ -201,6 +265,13 @@ static struct powerdomain neon_pwrdm = {
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 	.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,
+	},
 };
 
 static struct powerdomain usbhost_pwrdm = {
@@ -223,6 +294,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,
+	},
 };
 
 static struct powerdomain dpll1_pwrdm = {
-- 
1.7.4.1


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

* [PATCH v2 0/8] PM QoS: implement the OMAP low level constraints management code
  2011-09-21 16:14 [PATCH v2 0/8] PM QoS: implement the OMAP low level constraints management code Jean Pihet
                   ` (7 preceding siblings ...)
  2011-09-21 16:14 ` [PATCH 8/8] OMAP3: powerdomain data: add wake-up latency figures Jean Pihet
@ 2011-09-21 16:24 ` jean.pihet
  2011-09-21 16:24   ` [PATCH 1/8] OMAP: convert I2C driver to PM QoS for latency constraints jean.pihet
                     ` (8 more replies)
  8 siblings, 9 replies; 36+ messages in thread
From: jean.pihet @ 2011-09-21 16:24 UTC (permalink / raw)
  To: Kevin Hilman, Linux PM mailing list, linux-omap,
	Rafael J. Wysocki, Paul Walmsley
  Cc: Jean Pihet

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

. Convert the OMAP I2C driver to the PM QoS API for MPU latency constraints
. Remove the remove the latency related functions from OMAP PM in favor of
  the generic per-device PM QoS API
. 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 power
  states, through the hwmod and pwrdm layers
. Add cpuidle and power domains wake-up latency figures for OMAP3, cf. [1]
  for the details on where the numbers are 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. validate the constraints framework on OMAP4 HW (done on OMAP3)
2. 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
3. Further clean-up the OMAP PM layer, use the generic frameworks instead (OPP,
   PM QoS...)


Based on the pm-qos branch of the linux-pm git tree (3.1.0-rc3), cf. [2].

Tested 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/rafael/linux-pm.git


Jean Pihet (8):
  OMAP: convert I2C driver to PM QoS for latency constraints
  OMAP: PM: remove the latency related functions from the API
  OMAP2+: powerdomain: control power domains next state
  OMAP2+: omap_hwmod: manage the wake-up latency constraints
  OMAP: PM: register to the per-device PM QoS framework
  OMAP3: cpuidle: next C-state decision depends on the PM QoS MPU and
    CORE constraints
  OMAP3: update cpuidle latency and threshold figures
  OMAP3: powerdomain data: add wake-up latency figures

 Documentation/arm/OMAP/omap_pm               |   55 ++------
 arch/arm/mach-omap2/cpuidle34xx.c            |   77 ++++++-----
 arch/arm/mach-omap2/omap_hwmod.c             |   26 ++++-
 arch/arm/mach-omap2/pm.c                     |   63 ++++++++
 arch/arm/mach-omap2/pm.h                     |   17 ++-
 arch/arm/mach-omap2/powerdomain.c            |  197 ++++++++++++++++++++++++++
 arch/arm/mach-omap2/powerdomain.h            |   35 +++++-
 arch/arm/mach-omap2/powerdomains3xxx_data.c  |   78 ++++++++++
 arch/arm/plat-omap/i2c.c                     |   20 ---
 arch/arm/plat-omap/include/plat/omap-pm.h    |   99 -------------
 arch/arm/plat-omap/include/plat/omap_hwmod.h |    2 +
 arch/arm/plat-omap/omap-pm-noop.c            |   88 ------------
 drivers/i2c/busses/i2c-omap.c                |   30 ++--
 include/linux/i2c-omap.h                     |    1 -
 14 files changed, 480 insertions(+), 308 deletions(-)

-- 
1.7.4.1


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

* [PATCH 1/8] OMAP: convert I2C driver to PM QoS for latency constraints
  2011-09-21 16:24 ` [PATCH v2 0/8] PM QoS: implement the OMAP low level constraints management code jean.pihet
@ 2011-09-21 16:24   ` jean.pihet
  2011-09-21 16:24   ` [PATCH 2/8] OMAP: PM: remove the latency related functions from the API jean.pihet
                     ` (7 subsequent siblings)
  8 siblings, 0 replies; 36+ messages in thread
From: jean.pihet @ 2011-09-21 16:24 UTC (permalink / raw)
  To: Kevin Hilman, Linux PM mailing list, linux-omap,
	Rafael J. Wysocki, Paul Walmsley
  Cc: Jean Pihet

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

Convert the driver from the outdated omap_pm_set_max_mpu_wakeup_lat
API to the new PM QoS API.
Since the constraint is on the MPU subsystem, use the PM_QOS_CPU_DMA_LATENCY
class of PM QoS. The resulting MPU constraints are used by cpuidle to
decide the next power state of the MPU subsystem.

The I2C device latency timing is derived from the FIFO size and the
clock speed and so is applicable to all OMAP SoCs.

Signed-off-by: Jean Pihet <j-pihet@ti.com>
---
 arch/arm/plat-omap/i2c.c      |   20 --------------------
 drivers/i2c/busses/i2c-omap.c |   30 +++++++++++++++---------------
 include/linux/i2c-omap.h      |    1 -
 3 files changed, 15 insertions(+), 36 deletions(-)

diff --git a/arch/arm/plat-omap/i2c.c b/arch/arm/plat-omap/i2c.c
index 3341ca4..e1e2502 100644
--- a/arch/arm/plat-omap/i2c.c
+++ b/arch/arm/plat-omap/i2c.c
@@ -34,7 +34,6 @@
 #include <mach/irqs.h>
 #include <plat/mux.h>
 #include <plat/i2c.h>
-#include <plat/omap-pm.h>
 #include <plat/omap_device.h>
 
 #define OMAP_I2C_SIZE		0x3f
@@ -113,16 +112,6 @@ static inline int omap1_i2c_add_bus(int bus_id)
 
 
 #ifdef CONFIG_ARCH_OMAP2PLUS
-/*
- * XXX This function is a temporary compatibility wrapper - only
- * needed until the I2C driver can be converted to call
- * omap_pm_set_max_dev_wakeup_lat() and handle a return code.
- */
-static void omap_pm_set_max_mpu_wakeup_lat_compat(struct device *dev, long t)
-{
-	omap_pm_set_max_mpu_wakeup_lat(dev, t);
-}
-
 static struct omap_device_pm_latency omap_i2c_latency[] = {
 	[0] = {
 		.deactivate_func	= omap_device_idle_hwmods,
@@ -151,15 +140,6 @@ static inline int omap2_i2c_add_bus(int bus_id)
 	}
 
 	pdata = &i2c_pdata[bus_id - 1];
-	/*
-	 * When waiting for completion of a i2c transfer, we need to
-	 * set a wake up latency constraint for the MPU. This is to
-	 * ensure quick enough wakeup from idle, when transfer
-	 * completes.
-	 * Only omap3 has support for constraints
-	 */
-	if (cpu_is_omap34xx())
-		pdata->set_mpu_wkup_lat = omap_pm_set_max_mpu_wakeup_lat_compat;
 	od = omap_device_build(name, bus_id, oh, pdata,
 			sizeof(struct omap_i2c_bus_platform_data),
 			omap_i2c_latency, ARRAY_SIZE(omap_i2c_latency), 0);
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index 1a766cf..95e5205 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -40,6 +40,7 @@
 #include <linux/slab.h>
 #include <linux/i2c-omap.h>
 #include <linux/pm_runtime.h>
+#include <linux/pm_qos.h>
 
 /* I2C controller revisions */
 #define OMAP_I2C_REV_2			0x20
@@ -179,8 +180,7 @@ struct omap_i2c_dev {
 	struct completion	cmd_complete;
 	struct resource		*ioarea;
 	u32			latency;	/* maximum mpu wkup latency */
-	void			(*set_mpu_wkup_lat)(struct device *dev,
-						    long latency);
+	struct pm_qos_request	pm_qos_request;
 	u32			speed;		/* Speed of bus in Khz */
 	u16			cmd_err;
 	u8			*buf;
@@ -648,8 +648,14 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
 	if (r < 0)
 		goto out;
 
-	if (dev->set_mpu_wkup_lat != NULL)
-		dev->set_mpu_wkup_lat(dev->dev, dev->latency);
+	/*
+	 * When waiting for completion of a i2c transfer, we need to
+	 * set a wake up latency constraint for the MPU. This is to
+	 * ensure quick enough wakeup from idle, when transfer
+	 * completes.
+	 */
+	pm_qos_add_request(&dev->pm_qos_request, PM_QOS_CPU_DMA_LATENCY,
+			   dev->latency);
 
 	for (i = 0; i < num; i++) {
 		r = omap_i2c_xfer_msg(adap, &msgs[i], (i == (num - 1)));
@@ -657,8 +663,7 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
 			break;
 	}
 
-	if (dev->set_mpu_wkup_lat != NULL)
-		dev->set_mpu_wkup_lat(dev->dev, -1);
+	pm_qos_remove_request(&dev->pm_qos_request);
 
 	if (r == 0)
 		r = num;
@@ -1007,13 +1012,10 @@ omap_i2c_probe(struct platform_device *pdev)
 		goto err_release_region;
 	}
 
-	if (pdata != NULL) {
+	if (pdata != NULL)
 		speed = pdata->clkrate;
-		dev->set_mpu_wkup_lat = pdata->set_mpu_wkup_lat;
-	} else {
+	else
 		speed = 100;	/* Default speed */
-		dev->set_mpu_wkup_lat = NULL;
-	}
 
 	dev->speed = speed;
 	dev->idle = 1;
@@ -1066,10 +1068,8 @@ omap_i2c_probe(struct platform_device *pdev)
 			dev->fifo_size = (dev->fifo_size / 2);
 			dev->b_hw = 1; /* Enable hardware fixes */
 		}
-		/* calculate wakeup latency constraint for MPU */
-		if (dev->set_mpu_wkup_lat != NULL)
-			dev->latency = (1000000 * dev->fifo_size) /
-				       (1000 * speed / 8);
+		/* calculate wakeup latency constraint */
+		dev->latency = (1000000 * dev->fifo_size) / (1000 * speed / 8);
 	}
 
 	/* reset ASAP, clearing any IRQs */
diff --git a/include/linux/i2c-omap.h b/include/linux/i2c-omap.h
index 0aa0cbd..d06a8aa 100644
--- a/include/linux/i2c-omap.h
+++ b/include/linux/i2c-omap.h
@@ -32,7 +32,6 @@
 
 struct omap_i2c_bus_platform_data {
 	u32		clkrate;
-	void		(*set_mpu_wkup_lat)(struct device *dev, long set);
 	int		(*device_enable) (struct platform_device *pdev);
 	int		(*device_shutdown) (struct platform_device *pdev);
 	int		(*device_idle) (struct platform_device *pdev);
-- 
1.7.4.1


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

* [PATCH 2/8] OMAP: PM: remove the latency related functions from the API
  2011-09-21 16:24 ` [PATCH v2 0/8] PM QoS: implement the OMAP low level constraints management code jean.pihet
  2011-09-21 16:24   ` [PATCH 1/8] OMAP: convert I2C driver to PM QoS for latency constraints jean.pihet
@ 2011-09-21 16:24   ` jean.pihet
  2011-09-21 16:24   ` [PATCH 3/8] OMAP2+: powerdomain: control power domains next state jean.pihet
                     ` (6 subsequent siblings)
  8 siblings, 0 replies; 36+ messages in thread
From: jean.pihet @ 2011-09-21 16:24 UTC (permalink / raw)
  To: Kevin Hilman, Linux PM mailing list, linux-omap,
	Rafael J. Wysocki, Paul Walmsley
  Cc: Jean Pihet

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

Remove the following functions from the API:
 omap_pm_set_max_mpu_wakeup_lat
 omap_pm_set_max_dev_wakeup_lat
 omap_pm_set_max_sdma_lat

The generic per-device PM QoS functions shall be used instead, cf.
include/linux/pm_qos.h.

Signed-off-by: Jean Pihet <j-pihet@ti.com>
---
 Documentation/arm/OMAP/omap_pm            |   55 +++-------------
 arch/arm/plat-omap/include/plat/omap-pm.h |   99 -----------------------------
 arch/arm/plat-omap/omap-pm-noop.c         |   88 -------------------------
 3 files changed, 9 insertions(+), 233 deletions(-)

diff --git a/Documentation/arm/OMAP/omap_pm b/Documentation/arm/OMAP/omap_pm
index 9012bb0..26f9669 100644
--- a/Documentation/arm/OMAP/omap_pm
+++ b/Documentation/arm/OMAP/omap_pm
@@ -29,21 +29,12 @@ Drivers need to express PM parameters which:
 
 
 This document proposes the OMAP PM interface, including the following
-five power management functions for driver code:
+power management functions for driver code:
 
-1. Set the maximum MPU wakeup latency:
-   (*pdata->set_max_mpu_wakeup_lat)(struct device *dev, unsigned long t)
-
-2. Set the maximum device wakeup latency:
-   (*pdata->set_max_dev_wakeup_lat)(struct device *dev, unsigned long t)
-
-3. Set the maximum system DMA transfer start latency (CORE pwrdm):
-   (*pdata->set_max_sdma_lat)(struct device *dev, long t)
-
-4. Set the minimum bus throughput needed by a device:
+1. Set the minimum bus throughput needed by a device:
    (*pdata->set_min_bus_tput)(struct device *dev, u8 agent_id, unsigned long r)
 
-5. Return the number of times the device has lost context
+2. Return the number of times the device has lost context
    (*pdata->get_dev_context_loss_count)(struct device *dev)
 
 
@@ -55,10 +46,12 @@ The OMAP PM layer is intended to be temporary
 ---------------------------------------------
 
 The intention is that eventually the Linux PM QoS layer should support
-the range of power management features present in OMAP3.  As this
+the range of power management features present in OMAP3. As this
 happens, existing drivers using the OMAP PM interface can be modified
 to use the Linux PM QoS code; and the OMAP PM interface can disappear.
 
+The set_min_bus_tput function shall be converted to a throughput PM QoS
+framework.
 
 Driver usage of the OMAP PM functions
 -------------------------------------
@@ -66,39 +59,9 @@ Driver usage of the OMAP PM functions
 As the 'pdata' in the above examples indicates, these functions are
 exposed to drivers through function pointers in driver .platform_data
 structures.  The function pointers are initialized by the board-*.c
-files to point to the corresponding OMAP PM functions:
-.set_max_dev_wakeup_lat will point to
-omap_pm_set_max_dev_wakeup_lat(), etc.  Other architectures which do
-not support these functions should leave these function pointers set
-to NULL.  Drivers should use the following idiom:
-
-        if (pdata->set_max_dev_wakeup_lat)
-            (*pdata->set_max_dev_wakeup_lat)(dev, t);
-
-The most common usage of these functions will probably be to specify
-the maximum time from when an interrupt occurs, to when the device
-becomes accessible.  To accomplish this, driver writers should use the
-set_max_mpu_wakeup_lat() function to to constrain the MPU wakeup
-latency, and the set_max_dev_wakeup_lat() function to constrain the
-device wakeup latency (from clk_enable() to accessibility).  For
-example,
-
-        /* Limit MPU wakeup latency */
-        if (pdata->set_max_mpu_wakeup_lat)
-            (*pdata->set_max_mpu_wakeup_lat)(dev, tc);
-
-        /* Limit device powerdomain wakeup latency */
-        if (pdata->set_max_dev_wakeup_lat)
-            (*pdata->set_max_dev_wakeup_lat)(dev, td);
-
-        /* total wakeup latency in this example: (tc + td) */
-
-The PM parameters can be overwritten by calling the function again
-with the new value.  The settings can be removed by calling the
-function with a t argument of -1 (except in the case of
-set_max_bus_tput(), which should be called with an r argument of 0).
-
-The fifth function above, omap_pm_get_dev_context_loss_count(),
+files to point to the corresponding OMAP PM functions.
+
+The omap_pm_get_dev_context_loss_count() function
 is intended as an optimization to allow drivers to determine whether the
 device has lost its internal context.  If context has been lost, the
 driver must restore its internal context before proceeding.
diff --git a/arch/arm/plat-omap/include/plat/omap-pm.h b/arch/arm/plat-omap/include/plat/omap-pm.h
index 0840df8..c371364 100644
--- a/arch/arm/plat-omap/include/plat/omap-pm.h
+++ b/arch/arm/plat-omap/include/plat/omap-pm.h
@@ -62,44 +62,6 @@ void omap_pm_if_exit(void);
  * Device-driver-originated constraints (via board-*.c files, platform_data)
  */
 
-
-/**
- * omap_pm_set_max_mpu_wakeup_lat - set the maximum MPU wakeup latency
- * @dev: struct device * requesting the constraint
- * @t: maximum MPU wakeup latency in microseconds
- *
- * Request that the maximum interrupt latency for the MPU to be no
- * greater than @t microseconds. "Interrupt latency" in this case is
- * defined as the elapsed time from the occurrence of a hardware or
- * timer interrupt to the time when the device driver's interrupt
- * service routine has been entered by the MPU.
- *
- * It is intended that underlying PM code will use this information to
- * determine what power state to put the MPU powerdomain into, and
- * possibly the CORE powerdomain as well, since interrupt handling
- * code currently runs from SDRAM.  Advanced PM or board*.c code may
- * also configure interrupt controller priorities, OCP bus priorities,
- * CPU speed(s), etc.
- *
- * This function will not affect device wakeup latency, e.g., time
- * elapsed from when a device driver enables a hardware device with
- * clk_enable(), to when the device is ready for register access or
- * other use.  To control this device wakeup latency, use
- * omap_pm_set_max_dev_wakeup_lat()
- *
- * Multiple calls to omap_pm_set_max_mpu_wakeup_lat() will replace the
- * previous t value.  To remove the latency target for the MPU, call
- * with t = -1.
- *
- * XXX This constraint will be deprecated soon in favor of the more
- * general omap_pm_set_max_dev_wakeup_lat()
- *
- * Returns -EINVAL for an invalid argument, -ERANGE if the constraint
- * is not satisfiable, or 0 upon success.
- */
-int omap_pm_set_max_mpu_wakeup_lat(struct device *dev, long t);
-
-
 /**
  * omap_pm_set_min_bus_tput - set minimum bus throughput needed by device
  * @dev: struct device * requesting the constraint
@@ -131,67 +93,6 @@ int omap_pm_set_max_mpu_wakeup_lat(struct device *dev, long t);
  */
 int omap_pm_set_min_bus_tput(struct device *dev, u8 agent_id, unsigned long r);
 
-
-/**
- * omap_pm_set_max_dev_wakeup_lat - set the maximum device enable latency
- * @req_dev: struct device * requesting the constraint, or NULL if none
- * @dev: struct device * to set the constraint one
- * @t: maximum device wakeup latency in microseconds
- *
- * Request that the maximum amount of time necessary for a device @dev
- * to become accessible after its clocks are enabled should be no
- * greater than @t microseconds.  Specifically, this represents the
- * time from when a device driver enables device clocks with
- * clk_enable(), to when the register reads and writes on the device
- * will succeed.  This function should be called before clk_disable()
- * is called, since the power state transition decision may be made
- * during clk_disable().
- *
- * It is intended that underlying PM code will use this information to
- * determine what power state to put the powerdomain enclosing this
- * device into.
- *
- * Multiple calls to omap_pm_set_max_dev_wakeup_lat() will replace the
- * previous wakeup latency values for this device.  To remove the
- * wakeup latency restriction for this device, call with t = -1.
- *
- * Returns -EINVAL for an invalid argument, -ERANGE if the constraint
- * is not satisfiable, or 0 upon success.
- */
-int omap_pm_set_max_dev_wakeup_lat(struct device *req_dev, struct device *dev,
-				   long t);
-
-
-/**
- * omap_pm_set_max_sdma_lat - set the maximum system DMA transfer start latency
- * @dev: struct device *
- * @t: maximum DMA transfer start latency in microseconds
- *
- * Request that the maximum system DMA transfer start latency for this
- * device 'dev' should be no greater than 't' microseconds.  "DMA
- * transfer start latency" here is defined as the elapsed time from
- * when a device (e.g., McBSP) requests that a system DMA transfer
- * start or continue, to the time at which data starts to flow into
- * that device from the system DMA controller.
- *
- * It is intended that underlying PM code will use this information to
- * determine what power state to put the CORE powerdomain into.
- *
- * Since system DMA transfers may not involve the MPU, this function
- * will not affect MPU wakeup latency.  Use set_max_cpu_lat() to do
- * so.  Similarly, this function will not affect device wakeup latency
- * -- use set_max_dev_wakeup_lat() to affect that.
- *
- * Multiple calls to set_max_sdma_lat() will replace the previous t
- * value for this device.  To remove the maximum DMA latency for this
- * device, call with t = -1.
- *
- * Returns -EINVAL for an invalid argument, -ERANGE if the constraint
- * is not satisfiable, or 0 upon success.
- */
-int omap_pm_set_max_sdma_lat(struct device *dev, long t);
-
-
 /**
  * omap_pm_set_min_clk_rate - set minimum clock rate requested by @dev
  * @dev: struct device * requesting the constraint
diff --git a/arch/arm/plat-omap/omap-pm-noop.c b/arch/arm/plat-omap/omap-pm-noop.c
index b0471bb2..bf9ad37 100644
--- a/arch/arm/plat-omap/omap-pm-noop.c
+++ b/arch/arm/plat-omap/omap-pm-noop.c
@@ -33,34 +33,6 @@ static u32 dummy_context_loss_counter;
  * Device-driver-originated constraints (via board-*.c files)
  */
 
-int omap_pm_set_max_mpu_wakeup_lat(struct device *dev, long t)
-{
-	if (!dev || t < -1) {
-		WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__);
-		return -EINVAL;
-	};
-
-	if (t == -1)
-		pr_debug("OMAP PM: remove max MPU wakeup latency constraint: "
-			 "dev %s\n", dev_name(dev));
-	else
-		pr_debug("OMAP PM: add max MPU wakeup latency constraint: "
-			 "dev %s, t = %ld usec\n", dev_name(dev), t);
-
-	/*
-	 * For current Linux, this needs to map the MPU to a
-	 * powerdomain, then go through the list of current max lat
-	 * constraints on the MPU and find the smallest.  If
-	 * the latency constraint has changed, the code should
-	 * recompute the state to enter for the next powerdomain
-	 * state.
-	 *
-	 * TI CDP code can call constraint_set here.
-	 */
-
-	return 0;
-}
-
 int omap_pm_set_min_bus_tput(struct device *dev, u8 agent_id, unsigned long r)
 {
 	if (!dev || (agent_id != OCP_INITIATOR_AGENT &&
@@ -88,66 +60,6 @@ int omap_pm_set_min_bus_tput(struct device *dev, u8 agent_id, unsigned long r)
 	return 0;
 }
 
-int omap_pm_set_max_dev_wakeup_lat(struct device *req_dev, struct device *dev,
-				   long t)
-{
-	if (!req_dev || !dev || t < -1) {
-		WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__);
-		return -EINVAL;
-	};
-
-	if (t == -1)
-		pr_debug("OMAP PM: remove max device latency constraint: "
-			 "dev %s\n", dev_name(dev));
-	else
-		pr_debug("OMAP PM: add max device latency constraint: "
-			 "dev %s, t = %ld usec\n", dev_name(dev), t);
-
-	/*
-	 * For current Linux, this needs to map the device to a
-	 * powerdomain, then go through the list of current max lat
-	 * constraints on that powerdomain and find the smallest.  If
-	 * the latency constraint has changed, the code should
-	 * recompute the state to enter for the next powerdomain
-	 * state.  Conceivably, this code should also determine
-	 * whether to actually disable the device clocks or not,
-	 * depending on how long it takes to re-enable the clocks.
-	 *
-	 * TI CDP code can call constraint_set here.
-	 */
-
-	return 0;
-}
-
-int omap_pm_set_max_sdma_lat(struct device *dev, long t)
-{
-	if (!dev || t < -1) {
-		WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__);
-		return -EINVAL;
-	};
-
-	if (t == -1)
-		pr_debug("OMAP PM: remove max DMA latency constraint: "
-			 "dev %s\n", dev_name(dev));
-	else
-		pr_debug("OMAP PM: add max DMA latency constraint: "
-			 "dev %s, t = %ld usec\n", dev_name(dev), t);
-
-	/*
-	 * For current Linux PM QOS params, this code should scan the
-	 * list of maximum CPU and DMA latencies and select the
-	 * smallest, then set cpu_dma_latency pm_qos_param
-	 * accordingly.
-	 *
-	 * For future Linux PM QOS params, with separate CPU and DMA
-	 * latency params, this code should just set the dma_latency param.
-	 *
-	 * TI CDP code can call constraint_set here.
-	 */
-
-	return 0;
-}
-
 int omap_pm_set_min_clk_rate(struct device *dev, struct clk *c, long r)
 {
 	if (!dev || !c || r < 0) {
-- 
1.7.4.1


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

* [PATCH 3/8] OMAP2+: powerdomain: control power domains next state
  2011-09-21 16:24 ` [PATCH v2 0/8] PM QoS: implement the OMAP low level constraints management code jean.pihet
  2011-09-21 16:24   ` [PATCH 1/8] OMAP: convert I2C driver to PM QoS for latency constraints jean.pihet
  2011-09-21 16:24   ` [PATCH 2/8] OMAP: PM: remove the latency related functions from the API jean.pihet
@ 2011-09-21 16:24   ` jean.pihet
  2011-09-21 16:24   ` [PATCH 4/8] OMAP2+: omap_hwmod: manage the wake-up latency constraints jean.pihet
                     ` (5 subsequent siblings)
  8 siblings, 0 replies; 36+ messages in thread
From: jean.pihet @ 2011-09-21 16:24 UTC (permalink / raw)
  To: Kevin Hilman, Linux PM mailing list, linux-omap,
	Rafael J. Wysocki, Paul Walmsley
  Cc: Jean Pihet

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

When a PM QoS device latency constraint is requested or removed the
PM QoS layer notifies the underlying layer with the updated aggregated
constraint value. The constraint is stored in the powerdomain constraints
list and then applied to the corresponding power domain.
The power domains get the next power state programmed directly in the
registers via pwrdm_wakeuplat_update_pwrst.

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 |  197 +++++++++++++++++++++++++++++++++++++
 arch/arm/mach-omap2/powerdomain.h |   35 ++++++-
 2 files changed, 230 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
index 9af0847..8fc0aaa 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"
@@ -104,6 +106,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-od wake-up constraints data */
+	spin_lock_init(&pwrdm->wkup_lat_plist_lock);
+	plist_head_init(&pwrdm->wkup_lat_plist_head);
+	pwrdm->wkup_lat_next_state = PWRDM_POWER_OFF;
+
+	/* Initialize the pwrdm state */
 	pwrdm_wait_transition(pwrdm);
 	pwrdm->state = pwrdm_read_pwrst(pwrdm);
 	pwrdm->state_counter[pwrdm->state] = 1;
@@ -191,6 +199,83 @@ 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 upon success.
+ */
+static int pwrdm_wakeuplat_update_pwrst(struct powerdomain *pwrdm,
+					long min_latency)
+{
+	int ret = 0, new_state;
+
+	if (!pwrdm) {
+		WARN(1, "powerdomain: %s: invalid parameter(s)", __func__);
+		return -EINVAL;
+	}
+
+	/*
+	 * Apply constraints to power domains by programming
+	 * the pwrdm next power state.
+	 */
+
+	/*
+	 * Find the next supported power state with
+	 * wakeup latency < minimum constraint
+	 */
+	for (new_state = 0x0; new_state < PWRDM_MAX_PWRSTS; new_state++) {
+		if (min_latency == PM_QOS_DEV_LAT_DEFAULT_VALUE)
+			break;
+		if ((pwrdm->wakeup_lat[new_state] != UNSUP_STATE) &&
+		    (pwrdm->wakeup_lat[new_state] <= min_latency))
+			break;
+	}
+
+	switch (new_state) {
+	case PWRDM_FUNC_PWRST_OFF:
+		new_state = PWRDM_POWER_OFF;
+		break;
+	case PWRDM_FUNC_PWRST_OSWR:
+		pwrdm_set_logic_retst(pwrdm, PWRDM_POWER_OFF);
+		new_state = PWRDM_POWER_RET;
+		break;
+	case PWRDM_FUNC_PWRST_CSWR:
+		pwrdm_set_logic_retst(pwrdm, PWRDM_POWER_RET);
+		new_state = PWRDM_POWER_RET;
+		break;
+	case PWRDM_FUNC_PWRST_INACTIVE:
+		new_state = PWRDM_POWER_INACTIVE;
+		break;
+	case PWRDM_FUNC_PWRST_ON:
+		new_state = PWRDM_POWER_ON;
+		break;
+	default:
+		pr_warn("powerdomain: requested latency constraint not "
+			"supported %s set to ON state\n", pwrdm->name);
+		new_state = PWRDM_POWER_ON;
+		break;
+	}
+
+	pwrdm->wkup_lat_next_state = new_state;
+	if (pwrdm_read_next_pwrst(pwrdm) != new_state)
+		ret = omap_set_pwrdm_state(pwrdm, new_state);
+
+	pr_debug("powerdomain: %s pwrst: curr=%d, prev=%d next=%d "
+		 "min_latency=%ld, set_state=%d\n", pwrdm->name,
+		 pwrdm_read_pwrst(pwrdm), pwrdm_read_prev_pwrst(pwrdm),
+		 pwrdm_read_next_pwrst(pwrdm), min_latency, new_state);
+
+	return ret;
+}
+
 /* Public functions */
 
 /**
@@ -930,6 +1015,118 @@ int pwrdm_post_transition(void)
 	return 0;
 }
 
+/*
+ * pwrdm_set_wkup_lat_constraint - Set/update/remove 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. The value of PM_QOS_DEV_LAT_DEFAULT_VALUE removes
+ *  the constraint.
+ *
+ * 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.
+ * Constraint removal: Removes the identifier's entry from powerdomain's
+ * wakeup latency constraint list.
+ *
+ * Applies the strongest constraint value for the given pwrdm by calling
+ * pwrdm_wakeuplat_update_pwrst.
+ *
+ * Returns 0 upon success or a negative value in case of error.
+ *
+ * The caller must check the validity of the parameters.
+ */
+int pwrdm_set_wkup_lat_constraint(struct powerdomain *pwrdm, void *cookie,
+				  long min_latency)
+{
+	struct pwrdm_wkup_constraints_entry *user = NULL;
+	struct pwrdm_wkup_constraints_entry *tmp_user, *new_user = NULL;
+	int ret = 0, free_new_user = 0, free_node = 0;
+	long value = PM_QOS_DEV_LAT_DEFAULT_VALUE;
+	unsigned long flags;
+
+	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) {
+		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;
+		}
+		free_new_user = 1;
+	}
+
+	spin_lock_irqsave(&pwrdm->wkup_lat_plist_lock, flags);
+
+	/* 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 (min_latency != PM_QOS_DEV_LAT_DEFAULT_VALUE) {
+		/* If nothing to update, job done */
+		if (user && (user->node.prio == min_latency))
+			goto exit_ok;
+
+		if (!user) {
+			/* Add new entry to the list */
+			user = new_user;
+			user->cookie = cookie;
+			free_new_user = 0;
+		} else {
+			/* Update existing entry */
+			plist_del(&user->node, &pwrdm->wkup_lat_plist_head);
+		}
+
+		plist_node_init(&user->node, min_latency);
+		plist_add(&user->node, &pwrdm->wkup_lat_plist_head);
+	} else {
+		if (user) {
+			/* Remove the constraint from the list */
+			plist_del(&user->node, &pwrdm->wkup_lat_plist_head);
+			free_node = 1;
+		} else {
+			/* Constraint not existing or list empty, do nothing */
+			ret = -EINVAL;
+			goto exit_error;
+		}
+
+	}
+
+exit_ok:
+	/* Find the strongest constraint from the list */
+	if (!plist_head_empty(&pwrdm->wkup_lat_plist_head))
+		value = plist_first(&pwrdm->wkup_lat_plist_head)->prio;
+
+	spin_unlock_irqrestore(&pwrdm->wkup_lat_plist_lock, flags);
+
+	if (free_node)
+		kfree(user);
+
+	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);
+	pwrdm_wakeuplat_update_pwrst(pwrdm, value);
+
+	return 0;
+
+exit_error:
+	spin_unlock_irqrestore(&pwrdm->wkup_lat_plist_lock, flags);
+
+	return ret;
+}
+
 /**
  * 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 d23d979..41630ec 100644
--- a/arch/arm/mach-omap2/powerdomain.h
+++ b/arch/arm/mach-omap2/powerdomain.h
@@ -19,7 +19,9 @@
 
 #include <linux/types.h>
 #include <linux/list.h>
-
+#include <linux/plist.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
 #include <linux/atomic.h>
 
 #include <plat/cpu.h>
@@ -43,6 +45,16 @@
 #define PWRSTS_RET_ON		(PWRSTS_RET | PWRSTS_ON)
 #define PWRSTS_OFF_RET_ON	(PWRSTS_OFF_RET | PWRSTS_ON)
 
+/* Powerdomain functional power states */
+#define PWRDM_FUNC_PWRST_OFF		0x0
+#define PWRDM_FUNC_PWRST_OSWR		0x1
+#define PWRDM_FUNC_PWRST_CSWR		0x2
+#define PWRDM_FUNC_PWRST_INACTIVE	0x3
+#define PWRDM_FUNC_PWRST_ON		0x4
+
+#define PWRDM_MAX_FUNC_PWRSTS	5
+
+#define UNSUP_STATE		-1
 
 /* Powerdomain flags */
 #define PWRDM_HAS_HDWR_SAR	(1 << 0) /* hardware save-and-restore support */
@@ -93,7 +105,13 @@ struct powerdomain;
  * @state_counter:
  * @timer:
  * @state_timer:
- *
+ * @wakeup_lat: wakeup latencies (in us) for possible powerdomain power states
+ * Note about the wakeup latencies ordering: the values must be sorted
+ *  in decremental order
+ * @wkup_lat_plist_head: pwrdm wake-up latency constraints list
+ * @wkup_lat_plist_lock: spinlock that protects the constraints lists
+ *  domains states
+ * @wkup_lat_next_state: next pwrdm state, calculated from the constraints list
  * @prcm_partition possible values are defined in mach-omap2/prcm44xx.h.
  */
 struct powerdomain {
@@ -118,6 +136,16 @@ struct powerdomain {
 	s64 timer;
 	s64 state_timer[PWRDM_MAX_PWRSTS];
 #endif
+	const s32 wakeup_lat[PWRDM_MAX_FUNC_PWRSTS];
+	struct plist_head wkup_lat_plist_head;
+	spinlock_t 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;
 };
 
 /**
@@ -207,6 +235,9 @@ 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_set_wkup_lat_constraint(struct powerdomain *pwrdm, void *cookie,
+				  long min_latency);
 u32 pwrdm_get_context_loss_count(struct powerdomain *pwrdm);
 bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm);
 
-- 
1.7.4.1


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

* [PATCH 4/8] OMAP2+: omap_hwmod: manage the wake-up latency constraints
  2011-09-21 16:24 ` [PATCH v2 0/8] PM QoS: implement the OMAP low level constraints management code jean.pihet
                     ` (2 preceding siblings ...)
  2011-09-21 16:24   ` [PATCH 3/8] OMAP2+: powerdomain: control power domains next state jean.pihet
@ 2011-09-21 16:24   ` jean.pihet
  2011-10-07  2:53     ` Paul Walmsley
  2011-09-21 16:24   ` [PATCH 5/8] OMAP: PM: register to the per-device PM QoS framework jean.pihet
                     ` (4 subsequent siblings)
  8 siblings, 1 reply; 36+ messages in thread
From: jean.pihet @ 2011-09-21 16:24 UTC (permalink / raw)
  To: Kevin Hilman, Linux PM mailing list, linux-omap,
	Rafael J. Wysocki, Paul Walmsley
  Cc: Jean Pihet

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

Hwmod is queried from the OMAP_PM layer to manage the power domains
wake-up latency constraints. Hwmod retrieves the correct power domain
and if it exists it calls the corresponding power domain function.

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/omap_hwmod.c             |   26 +++++++++++++++++++++++++-
 arch/arm/plat-omap/include/plat/omap_hwmod.h |    2 ++
 2 files changed, 27 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index 84cc0bd..c6b1cc9 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -143,6 +143,7 @@
 #include "powerdomain.h"
 #include <plat/clock.h>
 #include <plat/omap_hwmod.h>
+#include <plat/omap_device.h>
 #include <plat/prcm.h>
 
 #include "cm2xxx_3xxx.h"
@@ -2618,11 +2619,34 @@ ohsps_unlock:
 	return ret;
 }
 
+/*
+ * omap_hwmod_set_wkup_constraint- set/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.
+ * @min_latency: the minimum allowed wake-up latency for @oh.
+ *
+ * Returns 0 upon success.
+ */
+int omap_hwmod_set_wkup_lat_constraint(struct omap_hwmod *oh,
+				       void *cookie, long min_latency)
+{
+	struct powerdomain *pwrdm = omap_hwmod_get_pwrdm(oh);
+
+	if (!pwrdm) {
+		pr_err("%s: Error: could not find powerdomain "
+		       "for %s\n", __func__, oh->name);
+		return -EINVAL;
+	}
+
+	return pwrdm_set_wkup_lat_constraint(pwrdm, cookie, min_latency);
+}
+
 /**
  * omap_hwmod_get_context_loss_count - get lost context count
  * @oh: struct omap_hwmod *
  *
- * Query the powerdomain of of @oh to get the context loss
+ * Query the powerdomain of @oh to get the context loss
  * count for this device.
  *
  * Returns the context loss count of the powerdomain assocated with @oh
diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h
index 0e329ca..75e0e7a 100644
--- a/arch/arm/plat-omap/include/plat/omap_hwmod.h
+++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h
@@ -603,6 +603,8 @@ int omap_hwmod_for_each_by_class(const char *classname,
 				 void *user);
 
 int omap_hwmod_set_postsetup_state(struct omap_hwmod *oh, u8 state);
+int omap_hwmod_set_wkup_lat_constraint(struct omap_hwmod *oh, void *cookie,
+				       long min_latency);
 u32 omap_hwmod_get_context_loss_count(struct omap_hwmod *oh);
 
 int omap_hwmod_no_setup_reset(struct omap_hwmod *oh);
-- 
1.7.4.1


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

* [PATCH 5/8] OMAP: PM: register to the per-device PM QoS framework
  2011-09-21 16:24 ` [PATCH v2 0/8] PM QoS: implement the OMAP low level constraints management code jean.pihet
                     ` (3 preceding siblings ...)
  2011-09-21 16:24   ` [PATCH 4/8] OMAP2+: omap_hwmod: manage the wake-up latency constraints jean.pihet
@ 2011-09-21 16:24   ` jean.pihet
  2011-09-21 16:24   ` [PATCH 6/8] OMAP3: cpuidle: next C-state decision depends on the PM QoS MPU and CORE constraints jean.pihet
                     ` (3 subsequent siblings)
  8 siblings, 0 replies; 36+ messages in thread
From: jean.pihet @ 2011-09-21 16:24 UTC (permalink / raw)
  To: Kevin Hilman, Linux PM mailing list, linux-omap,
	Rafael J. Wysocki, Paul Walmsley
  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>
---
 arch/arm/mach-omap2/pm.c |   63 ++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 63 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
index 3feb359..58b4b76 100644
--- a/arch/arm/mach-omap2/pm.c
+++ b/arch/arm/mach-omap2/pm.c
@@ -11,13 +11,16 @@
 
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/notifier.h>
 #include <linux/io.h>
 #include <linux/err.h>
 #include <linux/opp.h>
+#include <linux/pm_qos.h>
 
 #include <plat/omap-pm.h>
 #include <plat/omap_device.h>
 #include <plat/common.h>
+#include <plat/omap_hwmod.h>
 
 #include "voltage.h"
 #include "powerdomain.h"
@@ -242,11 +245,71 @@ static void __init omap4_init_voltages(void)
 	omap2_set_init_voltage("iva", "dpll_iva_m5x2_ck", iva_dev);
 }
 
+/* Interface to the per-device PM QoS framework */
+static int omap2_dev_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;
+
+	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 -EINVAL;
+	}
+
+	/* Find the associated omap_device for dev */
+	od = container_of(pdev, struct omap_device, pdev);
+	if (od->hwmods_cnt != 1) {
+		pr_err("%s: Error: No unique hwmod for device %s\n",
+		       __func__, dev_name(dev_pm_qos_req->dev));
+		return -EINVAL;
+	}
+
+	/* Find the primary omap_hwmod for dev */
+	oh = od->hwmods[0];
+
+	pr_debug("OMAP PM CONSTRAINTS: req@0x%p, dev=0x%p, new_value=%lu\n",
+		 req, dev_pm_qos_req->dev, new_value);
+
+	/* Apply the constraint */
+	return omap_hwmod_set_wkup_lat_constraint(oh, dev_pm_qos_req,
+						  new_value);
+}
+
+static struct notifier_block omap2_dev_pm_qos_notifier = {
+	.notifier_call	= omap2_dev_pm_qos_handler,
+};
+
+static int __init omap2_dev_pm_qos_init(void)
+{
+	int ret;
+
+	ret = dev_pm_qos_add_global_notifier(&omap2_dev_pm_qos_notifier);
+	if (ret)
+		WARN(1, KERN_ERR "Cannot add global notifier for dev PM QoS\n");
+
+	return ret;
+}
+
 static int __init omap2_common_pm_init(void)
 {
 	omap2_init_processor_devices();
 	omap_pm_if_init();
 
+	/* Register to the per-device PM QoS framework */
+	omap2_dev_pm_qos_init();
+
 	return 0;
 }
 postcore_initcall(omap2_common_pm_init);
-- 
1.7.4.1


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

* [PATCH 6/8] OMAP3: cpuidle: next C-state decision depends on the PM QoS MPU and CORE constraints
  2011-09-21 16:24 ` [PATCH v2 0/8] PM QoS: implement the OMAP low level constraints management code jean.pihet
                     ` (4 preceding siblings ...)
  2011-09-21 16:24   ` [PATCH 5/8] OMAP: PM: register to the per-device PM QoS framework jean.pihet
@ 2011-09-21 16:24   ` jean.pihet
  2011-09-21 16:24   ` [PATCH 7/8] OMAP3: update cpuidle latency and threshold figures jean.pihet
                     ` (2 subsequent siblings)
  8 siblings, 0 replies; 36+ messages in thread
From: jean.pihet @ 2011-09-21 16:24 UTC (permalink / raw)
  To: Kevin Hilman, Linux PM mailing list, linux-omap,
	Rafael J. Wysocki, Paul Walmsley
  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>
---
 arch/arm/mach-omap2/cpuidle34xx.c |   49 ++++++++++++++++++++++---------------
 arch/arm/mach-omap2/pm.h          |   17 +++++++++++-
 2 files changed, 44 insertions(+), 22 deletions(-)

diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c
index 4bf6e6e..1b8e0da 100644
--- a/arch/arm/mach-omap2/cpuidle34xx.c
+++ b/arch/arm/mach-omap2/cpuidle34xx.c
@@ -37,7 +37,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
@@ -72,14 +72,14 @@ 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;
@@ -92,9 +92,13 @@ static int _cpuidle_deny_idle(struct powerdomain *pwrdm,
  *
  * 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 int omap3_enter_idle(struct cpuidle_device *dev,
-			struct cpuidle_state *state)
+			    struct cpuidle_state *state)
 {
 	struct omap3_idle_statedata *cx = cpuidle_get_statedata(state);
 	struct timespec ts_preidle, ts_postidle, ts_idle;
@@ -146,8 +150,11 @@ return_sleep_time:
  * Else, this function searches for a lower c-state which is still
  * valid.
  *
- * 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 struct cpuidle_state *next_valid_state(struct cpuidle_device *dev,
 					      struct cpuidle_state *curr)
@@ -156,6 +163,8 @@ static struct cpuidle_state *next_valid_state(struct cpuidle_device *dev,
 	struct omap3_idle_statedata *cx = cpuidle_get_statedata(curr);
 	u32 mpu_deepest_state = PWRDM_POWER_RET;
 	u32 core_deepest_state = PWRDM_POWER_RET;
+	u32 mpu_pm_qos_next_state = mpu_pd->wkup_lat_next_state;
+	u32 core_pm_qos_next_state = core_pd->wkup_lat_next_state;
 
 	if (enable_off_mode) {
 		mpu_deepest_state = PWRDM_POWER_OFF;
@@ -171,7 +180,9 @@ static struct cpuidle_state *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 curr;
 	} else {
 		int idx = OMAP3_NUM_STATES - 1;
@@ -196,7 +207,9 @@ static struct cpuidle_state *next_valid_state(struct cpuidle_device *dev,
 			cx = cpuidle_get_statedata(&dev->states[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 = &dev->states[idx];
 				break;
 			}
@@ -215,8 +228,12 @@ static struct cpuidle_state *next_valid_state(struct cpuidle_device *dev,
  * @dev: cpuidle device
  * @state: The 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_state *state)
@@ -241,19 +258,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 = next_valid_state(dev, state);
 
 	/*
 	 * Prevent PER off if CORE is not in retention or off as this
 	 * would disable PER wakeups completely.
 	 */
-	cx = cpuidle_get_statedata(state);
+	cx = cpuidle_get_statedata(new_state);
 	core_next_state = cx->core_state;
 	per_next_state = per_saved_state = pwrdm_read_next_pwrst(per_pd);
 	if ((per_next_state == PWRDM_POWER_OFF) &&
@@ -264,8 +275,6 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
 	if (per_next_state != per_saved_state)
 		pwrdm_set_next_pwrst(per_pd, per_next_state);
 
-	new_state = next_valid_state(dev, state);
-
 select_state:
 	dev->last_state = new_state;
 	ret = omap3_enter_idle(dev, new_state);
diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
index 4e166ad..aca3b6c 100644
--- a/arch/arm/mach-omap2/pm.h
+++ b/arch/arm/mach-omap2/pm.h
@@ -43,9 +43,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.4.1


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

* [PATCH 7/8] OMAP3: update cpuidle latency and threshold figures
  2011-09-21 16:24 ` [PATCH v2 0/8] PM QoS: implement the OMAP low level constraints management code jean.pihet
                     ` (5 preceding siblings ...)
  2011-09-21 16:24   ` [PATCH 6/8] OMAP3: cpuidle: next C-state decision depends on the PM QoS MPU and CORE constraints jean.pihet
@ 2011-09-21 16:24   ` jean.pihet
  2011-09-21 16:24   ` [PATCH 8/8] OMAP3: powerdomain data: add wake-up latency figures jean.pihet
  2011-09-21 16:27   ` [PATCH v2 0/8] PM QoS: implement the OMAP low level constraints management code Jean Pihet
  8 siblings, 0 replies; 36+ messages in thread
From: jean.pihet @ 2011-09-21 16:24 UTC (permalink / raw)
  To: Kevin Hilman, Linux PM mailing list, linux-omap,
	Rafael J. Wysocki, Paul Walmsley
  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 magically 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>
---
 arch/arm/mach-omap2/cpuidle34xx.c |   28 ++++++++++++++--------------
 1 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c
index 1b8e0da..4b3e994 100644
--- a/arch/arm/mach-omap2/cpuidle34xx.c
+++ b/arch/arm/mach-omap2/cpuidle34xx.c
@@ -44,20 +44,20 @@
  * pass these details from the board file.
  */
 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.4.1


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

* [PATCH 8/8] OMAP3: powerdomain data: add wake-up latency figures
  2011-09-21 16:24 ` [PATCH v2 0/8] PM QoS: implement the OMAP low level constraints management code jean.pihet
                     ` (6 preceding siblings ...)
  2011-09-21 16:24   ` [PATCH 7/8] OMAP3: update cpuidle latency and threshold figures jean.pihet
@ 2011-09-21 16:24   ` jean.pihet
  2011-10-07  4:17     ` Paul Walmsley
  2011-10-07 15:26     ` Paul Walmsley
  2011-09-21 16:27   ` [PATCH v2 0/8] PM QoS: implement the OMAP low level constraints management code Jean Pihet
  8 siblings, 2 replies; 36+ messages in thread
From: jean.pihet @ 2011-09-21 16:24 UTC (permalink / raw)
  To: Kevin Hilman, Linux PM mailing list, linux-omap,
	Rafael J. Wysocki, Paul Walmsley
  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 magically 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>
---
 arch/arm/mach-omap2/powerdomains3xxx_data.c |   78 +++++++++++++++++++++++++++
 1 files changed, 78 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/powerdomains3xxx_data.c b/arch/arm/mach-omap2/powerdomains3xxx_data.c
index 469a920..32922bb 100644
--- a/arch/arm/mach-omap2/powerdomains3xxx_data.c
+++ b/arch/arm/mach-omap2/powerdomains3xxx_data.c
@@ -31,6 +31,14 @@
 
 /*
  * Powerdomains
+ *
+ * The wakeup_lat values are derived from measurements on
+ * the actual target.
+ *
+ * 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.
  */
 
 static struct powerdomain iva2_pwrdm = {
@@ -52,6 +60,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,
+	},
 };
 
 static struct powerdomain mpu_3xxx_pwrdm = {
@@ -68,6 +83,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,
+	},
 };
 
 /*
@@ -98,6 +120,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,
+	},
 };
 
 static struct powerdomain core_3xxx_es3_1_pwrdm = {
@@ -121,6 +150,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,
+	},
 };
 
 static struct powerdomain dss_pwrdm = {
@@ -136,6 +172,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,
+	},
 };
 
 /*
@@ -157,6 +200,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,
+	},
 };
 
 static struct powerdomain cam_pwrdm = {
@@ -172,6 +222,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,
+	},
 };
 
 static struct powerdomain per_pwrdm = {
@@ -187,6 +244,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,
+	},
 };
 
 static struct powerdomain emu_pwrdm = {
@@ -201,6 +265,13 @@ static struct powerdomain neon_pwrdm = {
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 	.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,
+	},
 };
 
 static struct powerdomain usbhost_pwrdm = {
@@ -223,6 +294,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,
+	},
 };
 
 static struct powerdomain dpll1_pwrdm = {
-- 
1.7.4.1


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

* Re: [PATCH v2 0/8] PM QoS: implement the OMAP low level constraints management code
  2011-09-21 16:24 ` [PATCH v2 0/8] PM QoS: implement the OMAP low level constraints management code jean.pihet
                     ` (7 preceding siblings ...)
  2011-09-21 16:24   ` [PATCH 8/8] OMAP3: powerdomain data: add wake-up latency figures jean.pihet
@ 2011-09-21 16:27   ` Jean Pihet
  8 siblings, 0 replies; 36+ messages in thread
From: Jean Pihet @ 2011-09-21 16:27 UTC (permalink / raw)
  To: Kevin Hilman, Linux PM mailing list, linux-omap,
	Rafael J. Wysocki, Paul Walmsley
  Cc: Jean Pihet

Hi,

Sorry I was missing the 'From:' line. Patch sent has been resent properly.

On Wed, Sep 21, 2011 at 6:24 PM,  <jean.pihet@newoldbits.com> wrote:
> From: Jean Pihet <j-pihet@ti.com>

Regards,
Jean

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

* Re: [PATCH 4/8] OMAP2+: omap_hwmod: manage the wake-up latency constraints
  2011-09-21 16:24   ` [PATCH 4/8] OMAP2+: omap_hwmod: manage the wake-up latency constraints jean.pihet
@ 2011-10-07  2:53     ` Paul Walmsley
  2011-10-10  8:08       ` Jean Pihet
  0 siblings, 1 reply; 36+ messages in thread
From: Paul Walmsley @ 2011-10-07  2:53 UTC (permalink / raw)
  To: jean.pihet
  Cc: Kevin Hilman, Linux PM mailing list, linux-omap,
	Rafael J. Wysocki, magnus.damm, Todd Poynor, Jean Pihet

Hi

a comment:

On Wed, 21 Sep 2011, jean.pihet@newoldbits.com wrote:

> From: Jean Pihet <j-pihet@ti.com>
> 
> Hwmod is queried from the OMAP_PM layer to manage the power domains
> wake-up latency constraints. Hwmod retrieves the correct power domain
> and if it exists it calls the corresponding power domain function.
> 
> 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/omap_hwmod.c             |   26 +++++++++++++++++++++++++-
>  arch/arm/plat-omap/include/plat/omap_hwmod.h |    2 ++
>  2 files changed, 27 insertions(+), 1 deletions(-)
> 
> diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
> index 84cc0bd..c6b1cc9 100644
> --- a/arch/arm/mach-omap2/omap_hwmod.c
> +++ b/arch/arm/mach-omap2/omap_hwmod.c
> @@ -2618,11 +2619,34 @@ ohsps_unlock:
>  	return ret;
>  }
>  
> +/*
> + * omap_hwmod_set_wkup_constraint- set/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.
> + * @min_latency: the minimum allowed wake-up latency for @oh.
> + *
> + * Returns 0 upon success.
> + */

It's good that there is some documentation here, but it would be better if 
it were kerneldoc-style documentation.  Please see 
Documentation/kernel-doc-nano-HOWTO.txt.

Also it would be good to have a bit more documentation here beyond simply 
"Returns 0 upon success."  For example, how should a caller remove a 
wakeup latency constraint?  Also, this function can return -EINVAL, not 
counting whatever pwrdm_set_wkup_lat_constraint() can return, so that 
should be documented above also.

This applies to the function comments in the rest of the patches too.  
Some of them have quite good kerneldoc comments, such as 
pwrdm_wakeuplat_update_pwrst(); others need some work, like 
pwrdm_set_wkup_lat_constraint().

> +int omap_hwmod_set_wkup_lat_constraint(struct omap_hwmod *oh,
> +				       void *cookie, long min_latency)
> +{
> +	struct powerdomain *pwrdm = omap_hwmod_get_pwrdm(oh);
> +
> +	if (!pwrdm) {
> +		pr_err("%s: Error: could not find powerdomain "
> +		       "for %s\n", __func__, oh->name);
> +		return -EINVAL;
> +	}
> +
> +	return pwrdm_set_wkup_lat_constraint(pwrdm, cookie, min_latency);
> +}
> +
>  /**
>   * omap_hwmod_get_context_loss_count - get lost context count
>   * @oh: struct omap_hwmod *
>   *
> - * Query the powerdomain of of @oh to get the context loss
> + * Query the powerdomain of @oh to get the context loss
>   * count for this device.
>   *
>   * Returns the context loss count of the powerdomain assocated with @oh
> diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h
> index 0e329ca..75e0e7a 100644
> --- a/arch/arm/plat-omap/include/plat/omap_hwmod.h
> +++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h
> @@ -603,6 +603,8 @@ int omap_hwmod_for_each_by_class(const char *classname,
>  				 void *user);
>  
>  int omap_hwmod_set_postsetup_state(struct omap_hwmod *oh, u8 state);
> +int omap_hwmod_set_wkup_lat_constraint(struct omap_hwmod *oh, void *cookie,
> +				       long min_latency);
>  u32 omap_hwmod_get_context_loss_count(struct omap_hwmod *oh);
>  
>  int omap_hwmod_no_setup_reset(struct omap_hwmod *oh);
> -- 
> 1.7.4.1
> 


- Paul

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

* Re: [PATCH 8/8] OMAP3: powerdomain data: add wake-up latency figures
  2011-09-21 16:24   ` [PATCH 8/8] OMAP3: powerdomain data: add wake-up latency figures jean.pihet
@ 2011-10-07  4:17     ` Paul Walmsley
  2011-10-10  8:17       ` Jean Pihet
  2011-10-07 15:26     ` Paul Walmsley
  1 sibling, 1 reply; 36+ messages in thread
From: Paul Walmsley @ 2011-10-07  4:17 UTC (permalink / raw)
  To: jean.pihet
  Cc: Kevin Hilman, Linux PM mailing list, linux-omap,
	Rafael J. Wysocki, magnus.damm, Todd Poynor, Jean Pihet

Hi Jean

On Wed, 21 Sep 2011, jean.pihet@newoldbits.com wrote:

> 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 magically coming from.
> 
> Tested on OMAP3 Beagleboard in RET/OFF using wake-up latency constraints
> on MPU, CORE and PER.

Do the CSWR measurements include the time for the PMIC to scale the 
voltage, or do they just represent the time to enter and exit clock stop 
(presumably with DPLL idling)? 


- Paul

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

* Re: [PATCH 8/8] OMAP3: powerdomain data: add wake-up latency figures
  2011-09-21 16:24   ` [PATCH 8/8] OMAP3: powerdomain data: add wake-up latency figures jean.pihet
  2011-10-07  4:17     ` Paul Walmsley
@ 2011-10-07 15:26     ` Paul Walmsley
  2011-10-10  8:19       ` Jean Pihet
  1 sibling, 1 reply; 36+ messages in thread
From: Paul Walmsley @ 2011-10-07 15:26 UTC (permalink / raw)
  To: jean.pihet
  Cc: Kevin Hilman, Linux PM mailing list, linux-omap,
	Rafael J. Wysocki, magnus.damm, Todd Poynor, Jean Pihet

Hi Jean

On Wed, 21 Sep 2011, jean.pihet@newoldbits.com wrote:

> 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 magically coming from.
> 
> Tested on OMAP3 Beagleboard in RET/OFF using wake-up latency constraints
> on MPU, CORE and PER.

A few more question about these numbers.

- Are these numbers the ones right off the hardware, or rounded, or 
worst-case plus a certain percentage?

- What frequency/voltage were these measured at?

- Also, you mention OMAP3 Beagleboard.  Is that 34xx or 36xx Beagleboard?

> Signed-off-by: Jean Pihet <j-pihet@ti.com>
> ---
>  arch/arm/mach-omap2/powerdomains3xxx_data.c |   78 +++++++++++++++++++++++++++
>  1 files changed, 78 insertions(+), 0 deletions(-)
> 
> diff --git a/arch/arm/mach-omap2/powerdomains3xxx_data.c b/arch/arm/mach-omap2/powerdomains3xxx_data.c
> index 469a920..32922bb 100644
> --- a/arch/arm/mach-omap2/powerdomains3xxx_data.c
> +++ b/arch/arm/mach-omap2/powerdomains3xxx_data.c
> @@ -31,6 +31,14 @@
>  
>  /*
>   * Powerdomains
> + *
> + * The wakeup_lat values are derived from measurements on
> + * the actual target.
> + *
> + * 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.
>   */
>  
>  static struct powerdomain iva2_pwrdm = {
> @@ -52,6 +60,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,
> +	},
>  };
>  
>  static struct powerdomain mpu_3xxx_pwrdm = {
> @@ -68,6 +83,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,
> +	},
>  };
>  
>  /*
> @@ -98,6 +120,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,
> +	},
>  };
>  
>  static struct powerdomain core_3xxx_es3_1_pwrdm = {
> @@ -121,6 +150,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,
> +	},
>  };
>  
>  static struct powerdomain dss_pwrdm = {
> @@ -136,6 +172,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,
> +	},
>  };
>  
>  /*
> @@ -157,6 +200,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,
> +	},
>  };
>  
>  static struct powerdomain cam_pwrdm = {
> @@ -172,6 +222,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,
> +	},
>  };
>  
>  static struct powerdomain per_pwrdm = {
> @@ -187,6 +244,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,
> +	},
>  };
>  
>  static struct powerdomain emu_pwrdm = {
> @@ -201,6 +265,13 @@ static struct powerdomain neon_pwrdm = {
>  	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
>  	.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,
> +	},
>  };
>  
>  static struct powerdomain usbhost_pwrdm = {
> @@ -223,6 +294,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,
> +	},
>  };
>  
>  static struct powerdomain dpll1_pwrdm = {
> -- 
> 1.7.4.1
> 
> --
> 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
> 


- Paul

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

* Re: [PATCH 4/8] OMAP2+: omap_hwmod: manage the wake-up latency constraints
  2011-10-07  2:53     ` Paul Walmsley
@ 2011-10-10  8:08       ` Jean Pihet
  2011-10-12 15:27         ` Jean Pihet
  0 siblings, 1 reply; 36+ messages in thread
From: Jean Pihet @ 2011-10-10  8:08 UTC (permalink / raw)
  To: Paul Walmsley
  Cc: Kevin Hilman, Linux PM mailing list, linux-omap,
	Rafael J. Wysocki, magnus.damm, Todd Poynor, Jean Pihet

Hi Paull,

On Fri, Oct 7, 2011 at 4:53 AM, Paul Walmsley <paul@pwsan.com> wrote:
> Hi
>
> a comment:
>
> On Wed, 21 Sep 2011, jean.pihet@newoldbits.com wrote:
>
>> From: Jean Pihet <j-pihet@ti.com>
>>
>> Hwmod is queried from the OMAP_PM layer to manage the power domains
>> wake-up latency constraints. Hwmod retrieves the correct power domain
>> and if it exists it calls the corresponding power domain function.
>>
>> 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/omap_hwmod.c             |   26 +++++++++++++++++++++++++-
>>  arch/arm/plat-omap/include/plat/omap_hwmod.h |    2 ++
>>  2 files changed, 27 insertions(+), 1 deletions(-)
>>
>> diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
>> index 84cc0bd..c6b1cc9 100644
>> --- a/arch/arm/mach-omap2/omap_hwmod.c
>> +++ b/arch/arm/mach-omap2/omap_hwmod.c
>> @@ -2618,11 +2619,34 @@ ohsps_unlock:
>>       return ret;
>>  }
>>
>> +/*
>> + * omap_hwmod_set_wkup_constraint- set/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.
>> + * @min_latency: the minimum allowed wake-up latency for @oh.
>> + *
>> + * Returns 0 upon success.
>> + */
>
> It's good that there is some documentation here, but it would be better if
> it were kerneldoc-style documentation.  Please see
> Documentation/kernel-doc-nano-HOWTO.txt.
> Also it would be good to have a bit more documentation here beyond simply
> "Returns 0 upon success."  For example, how should a caller remove a
> wakeup latency constraint?  Also, this function can return -EINVAL, not
> counting whatever pwrdm_set_wkup_lat_constraint() can return, so that
> should be documented above also.
>
> This applies to the function comments in the rest of the patches too.
> Some of them have quite good kerneldoc comments, such as
> pwrdm_wakeuplat_update_pwrst(); others need some work, like
> pwrdm_set_wkup_lat_constraint().

Not all functions have kernel doc comments, i.e. this one does not (no
/** at the start of the header).
The intention is to document the functions from the API and the ones
that implement the core service (pwrdm_set_wkup_lat_constraint()), and
not the pure pass-through functions (omap_hwmod_set_wkup_constraint).

In any case I will review the comments and resubmit.

Thanks,
Jean

>
> - Paul
>
--
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] 36+ messages in thread

* Re: [PATCH 8/8] OMAP3: powerdomain data: add wake-up latency figures
  2011-10-07  4:17     ` Paul Walmsley
@ 2011-10-10  8:17       ` Jean Pihet
  2011-10-10 22:44         ` Paul Walmsley
  0 siblings, 1 reply; 36+ messages in thread
From: Jean Pihet @ 2011-10-10  8:17 UTC (permalink / raw)
  To: Paul Walmsley
  Cc: Kevin Hilman, Linux PM mailing list, linux-omap,
	Rafael J. Wysocki, magnus.damm, Todd Poynor, Jean Pihet

Hi Paul,

On Fri, Oct 7, 2011 at 6:17 AM, Paul Walmsley <paul@pwsan.com> wrote:
> Hi Jean
>
> On Wed, 21 Sep 2011, jean.pihet@newoldbits.com wrote:
>
>> 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 magically coming from.
>>
>> Tested on OMAP3 Beagleboard in RET/OFF using wake-up latency constraints
>> on MPU, CORE and PER.
>
> Do the CSWR measurements include the time for the PMIC to scale the
> voltage, or do they just represent the time to enter and exit clock stop
> (presumably with DPLL idling)?

As described at [1] the measurements have not been performed with
sys_offmode and sys_clkreq signals toggling correctly, because of the
lack of support for it in the kernel.
However the results are including a correction for the sys_offmode
transition time (11.5ms), but no correction for the sys_clkreq signal
(which should be 1ms for sysclk on, 2.5ms for sysclk off).

[1] http://www.omappedia.org/wiki/Power_Management_Device_Latencies_Measurement#cpuidle_results

Regards,
Jean

>
>
> - Paul
>

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

* Re: [PATCH 8/8] OMAP3: powerdomain data: add wake-up latency figures
  2011-10-07 15:26     ` Paul Walmsley
@ 2011-10-10  8:19       ` Jean Pihet
  0 siblings, 0 replies; 36+ messages in thread
From: Jean Pihet @ 2011-10-10  8:19 UTC (permalink / raw)
  To: Paul Walmsley
  Cc: Kevin Hilman, Linux PM mailing list, linux-omap,
	Rafael J. Wysocki, magnus.damm, Todd Poynor, Jean Pihet

Paul,

On Fri, Oct 7, 2011 at 5:26 PM, Paul Walmsley <paul@pwsan.com> wrote:
> Hi Jean
>
> On Wed, 21 Sep 2011, jean.pihet@newoldbits.com wrote:
>
>> 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 magically coming from.
>>
>> Tested on OMAP3 Beagleboard in RET/OFF using wake-up latency constraints
>> on MPU, CORE and PER.
>
> A few more question about these numbers.
>
> - Are these numbers the ones right off the hardware, or rounded, or
> worst-case plus a certain percentage?
All measurements results are the worst case values right from the
hardware (HW and SW measurements on the target).

>
> - What frequency/voltage were these measured at?
OPP50

>
> - Also, you mention OMAP3 Beagleboard.  Is that 34xx or 36xx Beagleboard?
34xx Beagleboard

Cf. http://www.omappedia.org/wiki/Power_Management_Device_Latencies_Measurement#cpuidle_results
for the details.

Regards,
Jean

>
> - Paul
>
--
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] 36+ messages in thread

* Re: [PATCH 8/8] OMAP3: powerdomain data: add wake-up latency figures
  2011-10-10  8:17       ` Jean Pihet
@ 2011-10-10 22:44         ` Paul Walmsley
  2011-10-10 22:52           ` Paul Walmsley
  0 siblings, 1 reply; 36+ messages in thread
From: Paul Walmsley @ 2011-10-10 22:44 UTC (permalink / raw)
  To: Jean Pihet
  Cc: Kevin Hilman, Linux PM mailing list, linux-omap,
	Rafael J. Wysocki, magnus.damm, Todd Poynor, Jean Pihet

On Mon, 10 Oct 2011, Jean Pihet wrote:

> On Fri, Oct 7, 2011 at 6:17 AM, Paul Walmsley <paul@pwsan.com> wrote:
> > On Wed, 21 Sep 2011, jean.pihet@newoldbits.com wrote:
> >
> >> 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 magically coming from.
> >>
> >> Tested on OMAP3 Beagleboard in RET/OFF using wake-up latency constraints
> >> on MPU, CORE and PER.
> >
> > Do the CSWR measurements include the time for the PMIC to scale the
> > voltage, or do they just represent the time to enter and exit clock stop
> > (presumably with DPLL idling)?
> 
> As described at [1] the measurements have not been performed with
> sys_offmode and sys_clkreq signals toggling correctly, because of the
> lack of support for it in the kernel.
> However the results are including a correction for the sys_offmode
> transition time (11.5ms), but no correction for the sys_clkreq signal
> (which should be 1ms for sysclk on, 2.5ms for sysclk off).
> 
> [1] http://www.omappedia.org/wiki/Power_Management_Device_Latencies_Measurement#cpuidle_results

OK.  sys_offmode only applies to OFF mode.  Voltage scaling can also occur 
during RETENTION and INACTIVE ("sleep").  So were these results with 
retention and voltage scaling disabled?


- Paul

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

* Re: [PATCH 8/8] OMAP3: powerdomain data: add wake-up latency figures
  2011-10-10 22:44         ` Paul Walmsley
@ 2011-10-10 22:52           ` Paul Walmsley
  2011-10-11  6:50             ` Pihet-XID, Jean
  0 siblings, 1 reply; 36+ messages in thread
From: Paul Walmsley @ 2011-10-10 22:52 UTC (permalink / raw)
  To: Jean Pihet
  Cc: Kevin Hilman, Linux PM mailing list, linux-omap,
	Rafael J. Wysocki, magnus.damm, Todd Poynor, Jean Pihet

On Mon, 10 Oct 2011, Paul Walmsley wrote:

> OK.  sys_offmode only applies to OFF mode.  Voltage scaling can also occur 
> during RETENTION and INACTIVE ("sleep").  So were these results with 
> retention and voltage scaling disabled?

This last sentence should have read:

So were these results with retention and sleep voltage scaling disabled?

- Paul

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

* Re: [PATCH 8/8] OMAP3: powerdomain data: add wake-up latency figures
  2011-10-10 22:52           ` Paul Walmsley
@ 2011-10-11  6:50             ` Pihet-XID, Jean
  0 siblings, 0 replies; 36+ messages in thread
From: Pihet-XID, Jean @ 2011-10-11  6:50 UTC (permalink / raw)
  To: Paul Walmsley
  Cc: Jean Pihet, Kevin Hilman, Linux PM mailing list, linux-omap,
	Rafael J. Wysocki, magnus.damm, Todd Poynor

Hi Paul,

On Tue, Oct 11, 2011 at 12:52 AM, Paul Walmsley <paul@pwsan.com> wrote:
> On Mon, 10 Oct 2011, Paul Walmsley wrote:
>
>> OK.  sys_offmode only applies to OFF mode.  Voltage scaling can also occur
>> during RETENTION and INACTIVE ("sleep").  So were these results with
>> retention and voltage scaling disabled?
>
> This last sentence should have read:
>
> So were these results with retention and sleep voltage scaling disabled?
In that case, yes. The scaling timings are only applicable to OFF mode.

I think we need to have a bench setup for the latency measurements.
That way I will be easier to repeat the measurements for next
generation chips and variations.

Regards,
Jean

>
> - Paul
>
--
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] 36+ messages in thread

* Re: [PATCH 7/8] OMAP3: update cpuidle latency and threshold figures
  2011-09-21 16:14 ` [PATCH 7/8] OMAP3: update cpuidle latency and threshold figures Jean Pihet
@ 2011-10-12  2:48   ` Ming Lei
  2011-10-12  7:29     ` Jean Pihet
  0 siblings, 1 reply; 36+ messages in thread
From: Ming Lei @ 2011-10-12  2:48 UTC (permalink / raw)
  To: Jean Pihet
  Cc: Kevin Hilman, Linux PM mailing list, linux-omap,
	Rafael J. Wysocki, Paul Walmsley, magnus.damm, Todd Poynor,
	Jean Pihet

Hi,

On Thu, Sep 22, 2011 at 12:14 AM, Jean Pihet <jean.pihet@newoldbits.com> wrote:
> 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 magically 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>
> ---
>  arch/arm/mach-omap2/cpuidle34xx.c |   28 ++++++++++++++--------------
>  1 files changed, 14 insertions(+), 14 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c
> index 1b8e0da..4b3e994 100644
> --- a/arch/arm/mach-omap2/cpuidle34xx.c
> +++ b/arch/arm/mach-omap2/cpuidle34xx.c
> @@ -44,20 +44,20 @@
>  * pass these details from the board file.
>  */
>  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},

C4 exit_latency is longer than C5's, not sure if it is correct?

> +       /* 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.4.1
>
> --
> 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
>


thanks,
-- 
Ming Lei
--
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] 36+ messages in thread

* Re: [PATCH 7/8] OMAP3: update cpuidle latency and threshold figures
  2011-10-12  2:48   ` Ming Lei
@ 2011-10-12  7:29     ` Jean Pihet
  0 siblings, 0 replies; 36+ messages in thread
From: Jean Pihet @ 2011-10-12  7:29 UTC (permalink / raw)
  To: Ming Lei
  Cc: Kevin Hilman, Linux PM mailing list, linux-omap,
	Rafael J. Wysocki, Paul Walmsley, magnus.damm, Todd Poynor,
	Jean Pihet

Hi Ming,

On Wed, Oct 12, 2011 at 4:48 AM, Ming Lei <tom.leiming@gmail.com> wrote:
> Hi,
>
> On Thu, Sep 22, 2011 at 12:14 AM, Jean Pihet <jean.pihet@newoldbits.com> wrote:
>> 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 magically 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>
>> ---
>>  arch/arm/mach-omap2/cpuidle34xx.c |   28 ++++++++++++++--------------
>>  1 files changed, 14 insertions(+), 14 deletions(-)
>>
>> diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c
>> index 1b8e0da..4b3e994 100644
>> --- a/arch/arm/mach-omap2/cpuidle34xx.c
>> +++ b/arch/arm/mach-omap2/cpuidle34xx.c
>> @@ -44,20 +44,20 @@
>>  * pass these details from the board file.
>>  */
>>  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},
>
> C4 exit_latency is longer than C5's, not sure if it is correct?
Since MPU is OFF in C4 the impact is bigger in latency. In MPU OFF
mode the caches and MPU context are saved and later restored, which is
costly.

Thanks for the review!

Regards,
Jean

>
>> +       /* 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.4.1
>>
>> --
>> 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
>>
>
>
> thanks,
> --
> Ming Lei
>
--
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] 36+ messages in thread

* [PATCH 1/8] OMAP: convert I2C driver to PM QoS for latency constraints
  2011-10-12 15:24 [PATCH v3 " jean.pihet
@ 2011-10-12 15:24 ` jean.pihet
  0 siblings, 0 replies; 36+ messages in thread
From: jean.pihet @ 2011-10-12 15:24 UTC (permalink / raw)
  To: Kevin Hilman, Linux PM mailing list, linux-omap,
	Rafael J. Wysocki, Paul Walmsley
  Cc: Jean Pihet

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

Convert the driver from the outdated omap_pm_set_max_mpu_wakeup_lat
API to the new PM QoS API.
Since the constraint is on the MPU subsystem, use the PM_QOS_CPU_DMA_LATENCY
class of PM QoS. The resulting MPU constraints are used by cpuidle to
decide the next power state of the MPU subsystem.

The I2C device latency timing is derived from the FIFO size and the
clock speed and so is applicable to all OMAP SoCs.

Signed-off-by: Jean Pihet <j-pihet@ti.com>
---
 arch/arm/plat-omap/i2c.c      |   20 --------------------
 drivers/i2c/busses/i2c-omap.c |   30 +++++++++++++++---------------
 include/linux/i2c-omap.h      |    1 -
 3 files changed, 15 insertions(+), 36 deletions(-)

diff --git a/arch/arm/plat-omap/i2c.c b/arch/arm/plat-omap/i2c.c
index 3341ca4..e1e2502 100644
--- a/arch/arm/plat-omap/i2c.c
+++ b/arch/arm/plat-omap/i2c.c
@@ -34,7 +34,6 @@
 #include <mach/irqs.h>
 #include <plat/mux.h>
 #include <plat/i2c.h>
-#include <plat/omap-pm.h>
 #include <plat/omap_device.h>
 
 #define OMAP_I2C_SIZE		0x3f
@@ -113,16 +112,6 @@ static inline int omap1_i2c_add_bus(int bus_id)
 
 
 #ifdef CONFIG_ARCH_OMAP2PLUS
-/*
- * XXX This function is a temporary compatibility wrapper - only
- * needed until the I2C driver can be converted to call
- * omap_pm_set_max_dev_wakeup_lat() and handle a return code.
- */
-static void omap_pm_set_max_mpu_wakeup_lat_compat(struct device *dev, long t)
-{
-	omap_pm_set_max_mpu_wakeup_lat(dev, t);
-}
-
 static struct omap_device_pm_latency omap_i2c_latency[] = {
 	[0] = {
 		.deactivate_func	= omap_device_idle_hwmods,
@@ -151,15 +140,6 @@ static inline int omap2_i2c_add_bus(int bus_id)
 	}
 
 	pdata = &i2c_pdata[bus_id - 1];
-	/*
-	 * When waiting for completion of a i2c transfer, we need to
-	 * set a wake up latency constraint for the MPU. This is to
-	 * ensure quick enough wakeup from idle, when transfer
-	 * completes.
-	 * Only omap3 has support for constraints
-	 */
-	if (cpu_is_omap34xx())
-		pdata->set_mpu_wkup_lat = omap_pm_set_max_mpu_wakeup_lat_compat;
 	od = omap_device_build(name, bus_id, oh, pdata,
 			sizeof(struct omap_i2c_bus_platform_data),
 			omap_i2c_latency, ARRAY_SIZE(omap_i2c_latency), 0);
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index 1a766cf..95e5205 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -40,6 +40,7 @@
 #include <linux/slab.h>
 #include <linux/i2c-omap.h>
 #include <linux/pm_runtime.h>
+#include <linux/pm_qos.h>
 
 /* I2C controller revisions */
 #define OMAP_I2C_REV_2			0x20
@@ -179,8 +180,7 @@ struct omap_i2c_dev {
 	struct completion	cmd_complete;
 	struct resource		*ioarea;
 	u32			latency;	/* maximum mpu wkup latency */
-	void			(*set_mpu_wkup_lat)(struct device *dev,
-						    long latency);
+	struct pm_qos_request	pm_qos_request;
 	u32			speed;		/* Speed of bus in Khz */
 	u16			cmd_err;
 	u8			*buf;
@@ -648,8 +648,14 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
 	if (r < 0)
 		goto out;
 
-	if (dev->set_mpu_wkup_lat != NULL)
-		dev->set_mpu_wkup_lat(dev->dev, dev->latency);
+	/*
+	 * When waiting for completion of a i2c transfer, we need to
+	 * set a wake up latency constraint for the MPU. This is to
+	 * ensure quick enough wakeup from idle, when transfer
+	 * completes.
+	 */
+	pm_qos_add_request(&dev->pm_qos_request, PM_QOS_CPU_DMA_LATENCY,
+			   dev->latency);
 
 	for (i = 0; i < num; i++) {
 		r = omap_i2c_xfer_msg(adap, &msgs[i], (i == (num - 1)));
@@ -657,8 +663,7 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
 			break;
 	}
 
-	if (dev->set_mpu_wkup_lat != NULL)
-		dev->set_mpu_wkup_lat(dev->dev, -1);
+	pm_qos_remove_request(&dev->pm_qos_request);
 
 	if (r == 0)
 		r = num;
@@ -1007,13 +1012,10 @@ omap_i2c_probe(struct platform_device *pdev)
 		goto err_release_region;
 	}
 
-	if (pdata != NULL) {
+	if (pdata != NULL)
 		speed = pdata->clkrate;
-		dev->set_mpu_wkup_lat = pdata->set_mpu_wkup_lat;
-	} else {
+	else
 		speed = 100;	/* Default speed */
-		dev->set_mpu_wkup_lat = NULL;
-	}
 
 	dev->speed = speed;
 	dev->idle = 1;
@@ -1066,10 +1068,8 @@ omap_i2c_probe(struct platform_device *pdev)
 			dev->fifo_size = (dev->fifo_size / 2);
 			dev->b_hw = 1; /* Enable hardware fixes */
 		}
-		/* calculate wakeup latency constraint for MPU */
-		if (dev->set_mpu_wkup_lat != NULL)
-			dev->latency = (1000000 * dev->fifo_size) /
-				       (1000 * speed / 8);
+		/* calculate wakeup latency constraint */
+		dev->latency = (1000000 * dev->fifo_size) / (1000 * speed / 8);
 	}
 
 	/* reset ASAP, clearing any IRQs */
diff --git a/include/linux/i2c-omap.h b/include/linux/i2c-omap.h
index 0aa0cbd..d06a8aa 100644
--- a/include/linux/i2c-omap.h
+++ b/include/linux/i2c-omap.h
@@ -32,7 +32,6 @@
 
 struct omap_i2c_bus_platform_data {
 	u32		clkrate;
-	void		(*set_mpu_wkup_lat)(struct device *dev, long set);
 	int		(*device_enable) (struct platform_device *pdev);
 	int		(*device_shutdown) (struct platform_device *pdev);
 	int		(*device_idle) (struct platform_device *pdev);
-- 
1.7.4.1


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

* Re: [PATCH 4/8] OMAP2+: omap_hwmod: manage the wake-up latency constraints
  2011-10-10  8:08       ` Jean Pihet
@ 2011-10-12 15:27         ` Jean Pihet
  0 siblings, 0 replies; 36+ messages in thread
From: Jean Pihet @ 2011-10-12 15:27 UTC (permalink / raw)
  To: Paul Walmsley
  Cc: Kevin Hilman, Linux PM mailing list, linux-omap,
	Rafael J. Wysocki, magnus.damm, Todd Poynor, Jean Pihet, Ming Lei

Hi Paul,

The series has been updated with the kerneldoc and error path rework,
then re-submitted as v3.
Can you please look at it and possibly pull it?

Please let me know.

Regards,
Jean

On Mon, Oct 10, 2011 at 10:08 AM, Jean Pihet <jean.pihet@newoldbits.com> wrote:
> Hi Paull,
>
> On Fri, Oct 7, 2011 at 4:53 AM, Paul Walmsley <paul@pwsan.com> wrote:
>> Hi
>>
>> a comment:
>>
>> On Wed, 21 Sep 2011, jean.pihet@newoldbits.com wrote:
>>
>>> From: Jean Pihet <j-pihet@ti.com>
>>>
>>> Hwmod is queried from the OMAP_PM layer to manage the power domains
>>> wake-up latency constraints. Hwmod retrieves the correct power domain
>>> and if it exists it calls the corresponding power domain function.
>>>
>>> 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/omap_hwmod.c             |   26 +++++++++++++++++++++++++-
>>>  arch/arm/plat-omap/include/plat/omap_hwmod.h |    2 ++
>>>  2 files changed, 27 insertions(+), 1 deletions(-)
>>>
>>> diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
>>> index 84cc0bd..c6b1cc9 100644
>>> --- a/arch/arm/mach-omap2/omap_hwmod.c
>>> +++ b/arch/arm/mach-omap2/omap_hwmod.c
>>> @@ -2618,11 +2619,34 @@ ohsps_unlock:
>>>       return ret;
>>>  }
>>>
>>> +/*
>>> + * omap_hwmod_set_wkup_constraint- set/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.
>>> + * @min_latency: the minimum allowed wake-up latency for @oh.
>>> + *
>>> + * Returns 0 upon success.
>>> + */
>>
>> It's good that there is some documentation here, but it would be better if
>> it were kerneldoc-style documentation.  Please see
>> Documentation/kernel-doc-nano-HOWTO.txt.
>> Also it would be good to have a bit more documentation here beyond simply
>> "Returns 0 upon success."  For example, how should a caller remove a
>> wakeup latency constraint?  Also, this function can return -EINVAL, not
>> counting whatever pwrdm_set_wkup_lat_constraint() can return, so that
>> should be documented above also.
>>
>> This applies to the function comments in the rest of the patches too.
>> Some of them have quite good kerneldoc comments, such as
>> pwrdm_wakeuplat_update_pwrst(); others need some work, like
>> pwrdm_set_wkup_lat_constraint().
>
> Not all functions have kernel doc comments, i.e. this one does not (no
> /** at the start of the header).
> The intention is to document the functions from the API and the ones
> that implement the core service (pwrdm_set_wkup_lat_constraint()), and
> not the pure pass-through functions (omap_hwmod_set_wkup_constraint).
>
> In any case I will review the comments and resubmit.
>
> Thanks,
> Jean
>
>>
>> - Paul
>>
>
--
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] 36+ messages in thread

end of thread, other threads:[~2011-10-12 15:27 UTC | newest]

Thread overview: 36+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-09-21 16:14 [PATCH v2 0/8] PM QoS: implement the OMAP low level constraints management code Jean Pihet
2011-09-21 16:14 ` [PATCH 1/8] OMAP: convert I2C driver to PM QoS for latency constraints Jean Pihet
2011-09-21 16:14 ` [PATCH 2/8] OMAP: PM: remove the latency related functions from the API Jean Pihet
2011-09-21 16:14 ` [PATCH 3/8] OMAP2+: powerdomain: control power domains next state Jean Pihet
2011-09-21 16:14 ` [PATCH 4/8] OMAP2+: omap_hwmod: manage the wake-up latency constraints Jean Pihet
2011-09-21 16:14 ` [PATCH 5/8] OMAP: PM: register to the per-device PM QoS framework Jean Pihet
2011-09-21 16:14 ` [PATCH 6/8] OMAP3: cpuidle: next C-state decision depends on the PM QoS MPU and CORE constraints Jean Pihet
2011-09-21 16:14 ` [PATCH 7/8] OMAP3: update cpuidle latency and threshold figures Jean Pihet
2011-10-12  2:48   ` Ming Lei
2011-10-12  7:29     ` Jean Pihet
2011-09-21 16:14 ` [PATCH 8/8] OMAP3: powerdomain data: add wake-up latency figures Jean Pihet
2011-09-21 16:24 ` [PATCH v2 0/8] PM QoS: implement the OMAP low level constraints management code jean.pihet
2011-09-21 16:24   ` [PATCH 1/8] OMAP: convert I2C driver to PM QoS for latency constraints jean.pihet
2011-09-21 16:24   ` [PATCH 2/8] OMAP: PM: remove the latency related functions from the API jean.pihet
2011-09-21 16:24   ` [PATCH 3/8] OMAP2+: powerdomain: control power domains next state jean.pihet
2011-09-21 16:24   ` [PATCH 4/8] OMAP2+: omap_hwmod: manage the wake-up latency constraints jean.pihet
2011-10-07  2:53     ` Paul Walmsley
2011-10-10  8:08       ` Jean Pihet
2011-10-12 15:27         ` Jean Pihet
2011-09-21 16:24   ` [PATCH 5/8] OMAP: PM: register to the per-device PM QoS framework jean.pihet
2011-09-21 16:24   ` [PATCH 6/8] OMAP3: cpuidle: next C-state decision depends on the PM QoS MPU and CORE constraints jean.pihet
2011-09-21 16:24   ` [PATCH 7/8] OMAP3: update cpuidle latency and threshold figures jean.pihet
2011-09-21 16:24   ` [PATCH 8/8] OMAP3: powerdomain data: add wake-up latency figures jean.pihet
2011-10-07  4:17     ` Paul Walmsley
2011-10-10  8:17       ` Jean Pihet
2011-10-10 22:44         ` Paul Walmsley
2011-10-10 22:52           ` Paul Walmsley
2011-10-11  6:50             ` Pihet-XID, Jean
2011-10-07 15:26     ` Paul Walmsley
2011-10-10  8:19       ` Jean Pihet
2011-09-21 16:27   ` [PATCH v2 0/8] PM QoS: implement the OMAP low level constraints management code Jean Pihet
  -- strict thread matches above, loose matches on Subject: below --
2011-10-12 15:24 [PATCH v3 " jean.pihet
2011-10-12 15:24 ` [PATCH 1/8] OMAP: convert I2C driver to PM QoS for latency constraints jean.pihet
2011-09-02 13:13 [PATCH 0/8] PM QoS: implement the OMAP low level constraints management code Jean Pihet
2011-09-02 13:13 ` [PATCH 1/8] OMAP: convert I2C driver to PM QoS for latency constraints Jean Pihet
2011-09-15 22:46   ` Kevin Hilman
2011-09-16 15:39     ` Jean Pihet
2011-09-16 16:06       ` Kevin Hilman

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox