All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH V3 00/16] OPP: Add code to support operating-points-v2 bindings
@ 2015-07-29 10:52 ` Viresh Kumar
  0 siblings, 0 replies; 92+ messages in thread
From: Viresh Kumar @ 2015-07-29 10:52 UTC (permalink / raw)
  To: Rafael Wysocki, sboyd
  Cc: linaro-kernel, linux-pm, rob.herring, arnd.bergmann, nm, broonie,
	mturquette, Sudeep.Holla, viswanath.puttagunta, l.stach,
	thomas.petazzoni, linux-arm-kernel, ta.omasab, kesavan.abhilash,
	khilman, santosh.shilimkar, b.zolnierkie, Viresh Kumar

Hi Guys,

Resending this again because:
- opp-hz is now 64 bit long and so that required a binding update.
- There is another 4 patch series that as updating turbo OPP support,
  along with updates to cpufreq core and cpufreq-dt driver.
- A minor bug-fix in V2 4/11, which caused false positive for duplicate
  OPPs in some cases.

Tested this on dual-core exynos board with the driver inbuilt as well as
a module. Tried multiple insertion/removals of the module. Have tested
cpufreq-dt driver with both old and new bindings.

Also tried by sending some dummy OPPs that contained opp-hz greater than
what can be captured by u32, to test the u64 updates.

----------x-----------------x-------------

This adds code to support operating-points-v2 bindings. Not everything
is supported yet, but most of the basic stuff is.

Pushed here as well for reference:
ssh://git@git.linaro.org/people/viresh.kumar/linux.git opp/v2

V2->V3:
- Update to opp-hz binding to make it pass u64 value instead of 32 bit
  value. This is done to support clock rates greater than 4 GHz.
- Merged two inter-related series, opp-v2 and turbo mode updates.
- Fixed 4/11 from opp-v2 series, which cased false positive for
  duplicate OPPs in some cases.
- Add a separate comment in _opp_add_dynamic() (5/16), to clearly
  specify that we pass &dev_opp->opp_list to list_for_each_entry_rcu()
  and not pass 'head' which contains the same value. Because head will
  get modified by the code and that may result in an infinite loop.
- Accumulate more RBY tags.

V1->V2:
- 1/11 is a new patch which moves the bindings file into opp specific
  folder.
- 'opp-suspend' binding got updated and is part of individual OPPs now,
  instead of a phandle present in the opp table.
- Some more minor reformatting as suggested by Bartlomiej and Stephen,
  they were already posted as reply to earlier patches in V1.

Bartlomiej Zolnierkiewicz (2):
  PM / OPP: add dev_pm_opp_is_turbo() helper
  cpufreq: Update boost flag while initializing freq table from OPPs

Viresh Kumar (14):
  PM / OPP: Update bindings to make opp-hz a 64 bit value
  PM / OPP: Create a directory for opp bindings
  PM / OPP: Relocate few routines
  PM / OPP: Create _remove_device_opp() for freeing dev_opp
  PM / OPP: Allocate dev_opp from _add_device_opp()
  PM / OPP: Break _opp_add_dynamic() into smaller functions
  PM / OPP: Add support to parse "operating-points-v2" bindings
  PM / OPP: Add clock-latency-ns support
  PM / OPP: Add OPP sharing information to OPP library
  PM / OPP: Add support for opp-suspend
  PM / OPP: Add helpers for initializing CPU OPPs
  cpufreq: Allow drivers to enable boost support after registering
    driver
  cpufreq: dt: Add support for operating-points-v2 bindings
  cpufreq: dt: Add support for turbo/boost mode

 .../devicetree/bindings/power/{ => opp}/opp.txt    |   40 +-
 drivers/base/power/opp.c                           | 1084 ++++++++++++++++----
 drivers/cpufreq/cpufreq-dt.c                       |   64 +-
 drivers/cpufreq/cpufreq.c                          |   68 +-
 drivers/cpufreq/cpufreq_opp.c                      |    4 +
 drivers/cpufreq/freq_table.c                       |   15 +
 include/linux/cpufreq.h                            |   12 +
 include/linux/pm_opp.h                             |   36 +
 8 files changed, 1049 insertions(+), 274 deletions(-)
 rename Documentation/devicetree/bindings/power/{ => opp}/opp.txt (93%)

-- 
2.4.0


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

* [PATCH V3 00/16] OPP: Add code to support operating-points-v2 bindings
@ 2015-07-29 10:52 ` Viresh Kumar
  0 siblings, 0 replies; 92+ messages in thread
From: Viresh Kumar @ 2015-07-29 10:52 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Guys,

Resending this again because:
- opp-hz is now 64 bit long and so that required a binding update.
- There is another 4 patch series that as updating turbo OPP support,
  along with updates to cpufreq core and cpufreq-dt driver.
- A minor bug-fix in V2 4/11, which caused false positive for duplicate
  OPPs in some cases.

Tested this on dual-core exynos board with the driver inbuilt as well as
a module. Tried multiple insertion/removals of the module. Have tested
cpufreq-dt driver with both old and new bindings.

Also tried by sending some dummy OPPs that contained opp-hz greater than
what can be captured by u32, to test the u64 updates.

----------x-----------------x-------------

This adds code to support operating-points-v2 bindings. Not everything
is supported yet, but most of the basic stuff is.

Pushed here as well for reference:
ssh://git at git.linaro.org/people/viresh.kumar/linux.git opp/v2

V2->V3:
- Update to opp-hz binding to make it pass u64 value instead of 32 bit
  value. This is done to support clock rates greater than 4 GHz.
- Merged two inter-related series, opp-v2 and turbo mode updates.
- Fixed 4/11 from opp-v2 series, which cased false positive for
  duplicate OPPs in some cases.
- Add a separate comment in _opp_add_dynamic() (5/16), to clearly
  specify that we pass &dev_opp->opp_list to list_for_each_entry_rcu()
  and not pass 'head' which contains the same value. Because head will
  get modified by the code and that may result in an infinite loop.
- Accumulate more RBY tags.

V1->V2:
- 1/11 is a new patch which moves the bindings file into opp specific
  folder.
- 'opp-suspend' binding got updated and is part of individual OPPs now,
  instead of a phandle present in the opp table.
- Some more minor reformatting as suggested by Bartlomiej and Stephen,
  they were already posted as reply to earlier patches in V1.

Bartlomiej Zolnierkiewicz (2):
  PM / OPP: add dev_pm_opp_is_turbo() helper
  cpufreq: Update boost flag while initializing freq table from OPPs

Viresh Kumar (14):
  PM / OPP: Update bindings to make opp-hz a 64 bit value
  PM / OPP: Create a directory for opp bindings
  PM / OPP: Relocate few routines
  PM / OPP: Create _remove_device_opp() for freeing dev_opp
  PM / OPP: Allocate dev_opp from _add_device_opp()
  PM / OPP: Break _opp_add_dynamic() into smaller functions
  PM / OPP: Add support to parse "operating-points-v2" bindings
  PM / OPP: Add clock-latency-ns support
  PM / OPP: Add OPP sharing information to OPP library
  PM / OPP: Add support for opp-suspend
  PM / OPP: Add helpers for initializing CPU OPPs
  cpufreq: Allow drivers to enable boost support after registering
    driver
  cpufreq: dt: Add support for operating-points-v2 bindings
  cpufreq: dt: Add support for turbo/boost mode

 .../devicetree/bindings/power/{ => opp}/opp.txt    |   40 +-
 drivers/base/power/opp.c                           | 1084 ++++++++++++++++----
 drivers/cpufreq/cpufreq-dt.c                       |   64 +-
 drivers/cpufreq/cpufreq.c                          |   68 +-
 drivers/cpufreq/cpufreq_opp.c                      |    4 +
 drivers/cpufreq/freq_table.c                       |   15 +
 include/linux/cpufreq.h                            |   12 +
 include/linux/pm_opp.h                             |   36 +
 8 files changed, 1049 insertions(+), 274 deletions(-)
 rename Documentation/devicetree/bindings/power/{ => opp}/opp.txt (93%)

-- 
2.4.0

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

* [PATCH V3 01/16] PM / OPP: Update bindings to make opp-hz a 64 bit value
  2015-07-29 10:52 ` Viresh Kumar
  (?)
@ 2015-07-29 10:52   ` Viresh Kumar
  -1 siblings, 0 replies; 92+ messages in thread
From: Viresh Kumar @ 2015-07-29 10:52 UTC (permalink / raw)
  To: Rafael Wysocki, sboyd
  Cc: linaro-kernel, linux-pm, rob.herring, arnd.bergmann, nm, broonie,
	mturquette, Sudeep.Holla, viswanath.puttagunta, l.stach,
	thomas.petazzoni, linux-arm-kernel, ta.omasab, kesavan.abhilash,
	khilman, santosh.shilimkar, b.zolnierkie, Viresh Kumar,
	devicetree, Ian Campbell, Kumar Gala, open list, Mark Rutland,
	Pawel Moll, Rafael J. Wysocki, Rob Herring

With a 32 bit value, the maximum frequency that the bindings can
support is ~ 4 GHz. And that might fall short of what newer systems may
have.

Allow opp-hz to be a 64 bit big-endian value.

Cc: Rob Herring <rob.herring@linaro.org>
Cc: devicetree@vger.kernel.org
Suggested-by: Stephen Boyd <sboyd@codeaurora.org>
Suggested-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 Documentation/devicetree/bindings/power/opp.txt | 40 ++++++++++++-------------
 1 file changed, 20 insertions(+), 20 deletions(-)

diff --git a/Documentation/devicetree/bindings/power/opp.txt b/Documentation/devicetree/bindings/power/opp.txt
index 0d5e7c978121..0cb44dc21f97 100644
--- a/Documentation/devicetree/bindings/power/opp.txt
+++ b/Documentation/devicetree/bindings/power/opp.txt
@@ -88,7 +88,7 @@ This defines voltage-current-frequency combinations along with other related
 properties.
 
 Required properties:
-- opp-hz: Frequency in Hz
+- opp-hz: Frequency in Hz, expressed as a 64-bit big-endian integer.
 
 Optional properties:
 - opp-microvolt: voltage in micro Volts.
@@ -158,20 +158,20 @@ Example 1: Single cluster Dual-core ARM cortex A9, switch DVFS states together.
 		opp-shared;
 
 		opp00 {
-			opp-hz = <1000000000>;
+			opp-hz = /bits/ 64 <1000000000>;
 			opp-microvolt = <970000 975000 985000>;
 			opp-microamp = <70000>;
 			clock-latency-ns = <300000>;
 			opp-suspend;
 		};
 		opp01 {
-			opp-hz = <1100000000>;
+			opp-hz = /bits/ 64 <1100000000>;
 			opp-microvolt = <980000 1000000 1010000>;
 			opp-microamp = <80000>;
 			clock-latency-ns = <310000>;
 		};
 		opp02 {
-			opp-hz = <1200000000>;
+			opp-hz = /bits/ 64 <1200000000>;
 			opp-microvolt = <1025000>;
 			clock-latency-ns = <290000>;
 			turbo-mode;
@@ -237,20 +237,20 @@ independently.
 		 */
 
 		opp00 {
-			opp-hz = <1000000000>;
+			opp-hz = /bits/ 64 <1000000000>;
 			opp-microvolt = <970000 975000 985000>;
 			opp-microamp = <70000>;
 			clock-latency-ns = <300000>;
 			opp-suspend;
 		};
 		opp01 {
-			opp-hz = <1100000000>;
+			opp-hz = /bits/ 64 <1100000000>;
 			opp-microvolt = <980000 1000000 1010000>;
 			opp-microamp = <80000>;
 			clock-latency-ns = <310000>;
 		};
 		opp02 {
-			opp-hz = <1200000000>;
+			opp-hz = /bits/ 64 <1200000000>;
 			opp-microvolt = <1025000>;
 			opp-microamp = <90000;
 			lock-latency-ns = <290000>;
@@ -313,20 +313,20 @@ DVFS state together.
 		opp-shared;
 
 		opp00 {
-			opp-hz = <1000000000>;
+			opp-hz = /bits/ 64 <1000000000>;
 			opp-microvolt = <970000 975000 985000>;
 			opp-microamp = <70000>;
 			clock-latency-ns = <300000>;
 			opp-suspend;
 		};
 		opp01 {
-			opp-hz = <1100000000>;
+			opp-hz = /bits/ 64 <1100000000>;
 			opp-microvolt = <980000 1000000 1010000>;
 			opp-microamp = <80000>;
 			clock-latency-ns = <310000>;
 		};
 		opp02 {
-			opp-hz = <1200000000>;
+			opp-hz = /bits/ 64 <1200000000>;
 			opp-microvolt = <1025000>;
 			opp-microamp = <90000>;
 			clock-latency-ns = <290000>;
@@ -339,20 +339,20 @@ DVFS state together.
 		opp-shared;
 
 		opp10 {
-			opp-hz = <1300000000>;
+			opp-hz = /bits/ 64 <1300000000>;
 			opp-microvolt = <1045000 1050000 1055000>;
 			opp-microamp = <95000>;
 			clock-latency-ns = <400000>;
 			opp-suspend;
 		};
 		opp11 {
-			opp-hz = <1400000000>;
+			opp-hz = /bits/ 64 <1400000000>;
 			opp-microvolt = <1075000>;
 			opp-microamp = <100000>;
 			clock-latency-ns = <400000>;
 		};
 		opp12 {
-			opp-hz = <1500000000>;
+			opp-hz = /bits/ 64 <1500000000>;
 			opp-microvolt = <1010000 1100000 1110000>;
 			opp-microamp = <95000>;
 			clock-latency-ns = <400000>;
@@ -379,7 +379,7 @@ Example 4: Handling multiple regulators
 		opp-shared;
 
 		opp00 {
-			opp-hz = <1000000000>;
+			opp-hz = /bits/ 64 <1000000000>;
 			opp-microvolt = <970000>, /* Supply 0 */
 					<960000>, /* Supply 1 */
 					<960000>; /* Supply 2 */
@@ -392,7 +392,7 @@ Example 4: Handling multiple regulators
 		/* OR */
 
 		opp00 {
-			opp-hz = <1000000000>;
+			opp-hz = /bits/ 64 <1000000000>;
 			opp-microvolt = <970000 975000 985000>, /* Supply 0 */
 					<960000 965000 975000>, /* Supply 1 */
 					<960000 965000 975000>; /* Supply 2 */
@@ -405,7 +405,7 @@ Example 4: Handling multiple regulators
 		/* OR */
 
 		opp00 {
-			opp-hz = <1000000000>;
+			opp-hz = /bits/ 64 <1000000000>;
 			opp-microvolt = <970000 975000 985000>, /* Supply 0 */
 					<960000 965000 975000>, /* Supply 1 */
 					<960000 965000 975000>; /* Supply 2 */
@@ -437,12 +437,12 @@ Example 5: Multiple OPP tables
 		opp-shared;
 
 		opp00 {
-			opp-hz = <600000000>;
+			opp-hz = /bits/ 64 <600000000>;
 			...
 		};
 
 		opp01 {
-			opp-hz = <800000000>;
+			opp-hz = /bits/ 64 <800000000>;
 			...
 		};
 	};
@@ -453,12 +453,12 @@ Example 5: Multiple OPP tables
 		opp-shared;
 
 		opp10 {
-			opp-hz = <1000000000>;
+			opp-hz = /bits/ 64 <1000000000>;
 			...
 		};
 
 		opp11 {
-			opp-hz = <1100000000>;
+			opp-hz = /bits/ 64 <1100000000>;
 			...
 		};
 	};
-- 
2.4.0


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

* [PATCH V3 01/16] PM / OPP: Update bindings to make opp-hz a 64 bit value
@ 2015-07-29 10:52   ` Viresh Kumar
  0 siblings, 0 replies; 92+ messages in thread
From: Viresh Kumar @ 2015-07-29 10:52 UTC (permalink / raw)
  To: Rafael Wysocki, sboyd
  Cc: linaro-kernel, linux-pm, rob.herring, arnd.bergmann, nm, broonie,
	mturquette, Sudeep.Holla, viswanath.puttagunta, l.stach,
	thomas.petazzoni, linux-arm-kernel, ta.omasab, kesavan.abhilash,
	khilman, santosh.shilimkar, b.zolnierkie, Viresh Kumar,
	devicetree, Ian Campbell, Kumar Gala, open list, Mark Rutland,
	Pawel Moll, Rafael J. Wysocki, Rob Herring

With a 32 bit value, the maximum frequency that the bindings can
support is ~ 4 GHz. And that might fall short of what newer systems may
have.

Allow opp-hz to be a 64 bit big-endian value.

Cc: Rob Herring <rob.herring@linaro.org>
Cc: devicetree@vger.kernel.org
Suggested-by: Stephen Boyd <sboyd@codeaurora.org>
Suggested-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 Documentation/devicetree/bindings/power/opp.txt | 40 ++++++++++++-------------
 1 file changed, 20 insertions(+), 20 deletions(-)

diff --git a/Documentation/devicetree/bindings/power/opp.txt b/Documentation/devicetree/bindings/power/opp.txt
index 0d5e7c978121..0cb44dc21f97 100644
--- a/Documentation/devicetree/bindings/power/opp.txt
+++ b/Documentation/devicetree/bindings/power/opp.txt
@@ -88,7 +88,7 @@ This defines voltage-current-frequency combinations along with other related
 properties.
 
 Required properties:
-- opp-hz: Frequency in Hz
+- opp-hz: Frequency in Hz, expressed as a 64-bit big-endian integer.
 
 Optional properties:
 - opp-microvolt: voltage in micro Volts.
@@ -158,20 +158,20 @@ Example 1: Single cluster Dual-core ARM cortex A9, switch DVFS states together.
 		opp-shared;
 
 		opp00 {
-			opp-hz = <1000000000>;
+			opp-hz = /bits/ 64 <1000000000>;
 			opp-microvolt = <970000 975000 985000>;
 			opp-microamp = <70000>;
 			clock-latency-ns = <300000>;
 			opp-suspend;
 		};
 		opp01 {
-			opp-hz = <1100000000>;
+			opp-hz = /bits/ 64 <1100000000>;
 			opp-microvolt = <980000 1000000 1010000>;
 			opp-microamp = <80000>;
 			clock-latency-ns = <310000>;
 		};
 		opp02 {
-			opp-hz = <1200000000>;
+			opp-hz = /bits/ 64 <1200000000>;
 			opp-microvolt = <1025000>;
 			clock-latency-ns = <290000>;
 			turbo-mode;
@@ -237,20 +237,20 @@ independently.
 		 */
 
 		opp00 {
-			opp-hz = <1000000000>;
+			opp-hz = /bits/ 64 <1000000000>;
 			opp-microvolt = <970000 975000 985000>;
 			opp-microamp = <70000>;
 			clock-latency-ns = <300000>;
 			opp-suspend;
 		};
 		opp01 {
-			opp-hz = <1100000000>;
+			opp-hz = /bits/ 64 <1100000000>;
 			opp-microvolt = <980000 1000000 1010000>;
 			opp-microamp = <80000>;
 			clock-latency-ns = <310000>;
 		};
 		opp02 {
-			opp-hz = <1200000000>;
+			opp-hz = /bits/ 64 <1200000000>;
 			opp-microvolt = <1025000>;
 			opp-microamp = <90000;
 			lock-latency-ns = <290000>;
@@ -313,20 +313,20 @@ DVFS state together.
 		opp-shared;
 
 		opp00 {
-			opp-hz = <1000000000>;
+			opp-hz = /bits/ 64 <1000000000>;
 			opp-microvolt = <970000 975000 985000>;
 			opp-microamp = <70000>;
 			clock-latency-ns = <300000>;
 			opp-suspend;
 		};
 		opp01 {
-			opp-hz = <1100000000>;
+			opp-hz = /bits/ 64 <1100000000>;
 			opp-microvolt = <980000 1000000 1010000>;
 			opp-microamp = <80000>;
 			clock-latency-ns = <310000>;
 		};
 		opp02 {
-			opp-hz = <1200000000>;
+			opp-hz = /bits/ 64 <1200000000>;
 			opp-microvolt = <1025000>;
 			opp-microamp = <90000>;
 			clock-latency-ns = <290000>;
@@ -339,20 +339,20 @@ DVFS state together.
 		opp-shared;
 
 		opp10 {
-			opp-hz = <1300000000>;
+			opp-hz = /bits/ 64 <1300000000>;
 			opp-microvolt = <1045000 1050000 1055000>;
 			opp-microamp = <95000>;
 			clock-latency-ns = <400000>;
 			opp-suspend;
 		};
 		opp11 {
-			opp-hz = <1400000000>;
+			opp-hz = /bits/ 64 <1400000000>;
 			opp-microvolt = <1075000>;
 			opp-microamp = <100000>;
 			clock-latency-ns = <400000>;
 		};
 		opp12 {
-			opp-hz = <1500000000>;
+			opp-hz = /bits/ 64 <1500000000>;
 			opp-microvolt = <1010000 1100000 1110000>;
 			opp-microamp = <95000>;
 			clock-latency-ns = <400000>;
@@ -379,7 +379,7 @@ Example 4: Handling multiple regulators
 		opp-shared;
 
 		opp00 {
-			opp-hz = <1000000000>;
+			opp-hz = /bits/ 64 <1000000000>;
 			opp-microvolt = <970000>, /* Supply 0 */
 					<960000>, /* Supply 1 */
 					<960000>; /* Supply 2 */
@@ -392,7 +392,7 @@ Example 4: Handling multiple regulators
 		/* OR */
 
 		opp00 {
-			opp-hz = <1000000000>;
+			opp-hz = /bits/ 64 <1000000000>;
 			opp-microvolt = <970000 975000 985000>, /* Supply 0 */
 					<960000 965000 975000>, /* Supply 1 */
 					<960000 965000 975000>; /* Supply 2 */
@@ -405,7 +405,7 @@ Example 4: Handling multiple regulators
 		/* OR */
 
 		opp00 {
-			opp-hz = <1000000000>;
+			opp-hz = /bits/ 64 <1000000000>;
 			opp-microvolt = <970000 975000 985000>, /* Supply 0 */
 					<960000 965000 975000>, /* Supply 1 */
 					<960000 965000 975000>; /* Supply 2 */
@@ -437,12 +437,12 @@ Example 5: Multiple OPP tables
 		opp-shared;
 
 		opp00 {
-			opp-hz = <600000000>;
+			opp-hz = /bits/ 64 <600000000>;
 			...
 		};
 
 		opp01 {
-			opp-hz = <800000000>;
+			opp-hz = /bits/ 64 <800000000>;
 			...
 		};
 	};
@@ -453,12 +453,12 @@ Example 5: Multiple OPP tables
 		opp-shared;
 
 		opp10 {
-			opp-hz = <1000000000>;
+			opp-hz = /bits/ 64 <1000000000>;
 			...
 		};
 
 		opp11 {
-			opp-hz = <1100000000>;
+			opp-hz = /bits/ 64 <1100000000>;
 			...
 		};
 	};
-- 
2.4.0


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

* [PATCH V3 01/16] PM / OPP: Update bindings to make opp-hz a 64 bit value
@ 2015-07-29 10:52   ` Viresh Kumar
  0 siblings, 0 replies; 92+ messages in thread
From: Viresh Kumar @ 2015-07-29 10:52 UTC (permalink / raw)
  To: linux-arm-kernel

With a 32 bit value, the maximum frequency that the bindings can
support is ~ 4 GHz. And that might fall short of what newer systems may
have.

Allow opp-hz to be a 64 bit big-endian value.

Cc: Rob Herring <rob.herring@linaro.org>
Cc: devicetree at vger.kernel.org
Suggested-by: Stephen Boyd <sboyd@codeaurora.org>
Suggested-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 Documentation/devicetree/bindings/power/opp.txt | 40 ++++++++++++-------------
 1 file changed, 20 insertions(+), 20 deletions(-)

diff --git a/Documentation/devicetree/bindings/power/opp.txt b/Documentation/devicetree/bindings/power/opp.txt
index 0d5e7c978121..0cb44dc21f97 100644
--- a/Documentation/devicetree/bindings/power/opp.txt
+++ b/Documentation/devicetree/bindings/power/opp.txt
@@ -88,7 +88,7 @@ This defines voltage-current-frequency combinations along with other related
 properties.
 
 Required properties:
-- opp-hz: Frequency in Hz
+- opp-hz: Frequency in Hz, expressed as a 64-bit big-endian integer.
 
 Optional properties:
 - opp-microvolt: voltage in micro Volts.
@@ -158,20 +158,20 @@ Example 1: Single cluster Dual-core ARM cortex A9, switch DVFS states together.
 		opp-shared;
 
 		opp00 {
-			opp-hz = <1000000000>;
+			opp-hz = /bits/ 64 <1000000000>;
 			opp-microvolt = <970000 975000 985000>;
 			opp-microamp = <70000>;
 			clock-latency-ns = <300000>;
 			opp-suspend;
 		};
 		opp01 {
-			opp-hz = <1100000000>;
+			opp-hz = /bits/ 64 <1100000000>;
 			opp-microvolt = <980000 1000000 1010000>;
 			opp-microamp = <80000>;
 			clock-latency-ns = <310000>;
 		};
 		opp02 {
-			opp-hz = <1200000000>;
+			opp-hz = /bits/ 64 <1200000000>;
 			opp-microvolt = <1025000>;
 			clock-latency-ns = <290000>;
 			turbo-mode;
@@ -237,20 +237,20 @@ independently.
 		 */
 
 		opp00 {
-			opp-hz = <1000000000>;
+			opp-hz = /bits/ 64 <1000000000>;
 			opp-microvolt = <970000 975000 985000>;
 			opp-microamp = <70000>;
 			clock-latency-ns = <300000>;
 			opp-suspend;
 		};
 		opp01 {
-			opp-hz = <1100000000>;
+			opp-hz = /bits/ 64 <1100000000>;
 			opp-microvolt = <980000 1000000 1010000>;
 			opp-microamp = <80000>;
 			clock-latency-ns = <310000>;
 		};
 		opp02 {
-			opp-hz = <1200000000>;
+			opp-hz = /bits/ 64 <1200000000>;
 			opp-microvolt = <1025000>;
 			opp-microamp = <90000;
 			lock-latency-ns = <290000>;
@@ -313,20 +313,20 @@ DVFS state together.
 		opp-shared;
 
 		opp00 {
-			opp-hz = <1000000000>;
+			opp-hz = /bits/ 64 <1000000000>;
 			opp-microvolt = <970000 975000 985000>;
 			opp-microamp = <70000>;
 			clock-latency-ns = <300000>;
 			opp-suspend;
 		};
 		opp01 {
-			opp-hz = <1100000000>;
+			opp-hz = /bits/ 64 <1100000000>;
 			opp-microvolt = <980000 1000000 1010000>;
 			opp-microamp = <80000>;
 			clock-latency-ns = <310000>;
 		};
 		opp02 {
-			opp-hz = <1200000000>;
+			opp-hz = /bits/ 64 <1200000000>;
 			opp-microvolt = <1025000>;
 			opp-microamp = <90000>;
 			clock-latency-ns = <290000>;
@@ -339,20 +339,20 @@ DVFS state together.
 		opp-shared;
 
 		opp10 {
-			opp-hz = <1300000000>;
+			opp-hz = /bits/ 64 <1300000000>;
 			opp-microvolt = <1045000 1050000 1055000>;
 			opp-microamp = <95000>;
 			clock-latency-ns = <400000>;
 			opp-suspend;
 		};
 		opp11 {
-			opp-hz = <1400000000>;
+			opp-hz = /bits/ 64 <1400000000>;
 			opp-microvolt = <1075000>;
 			opp-microamp = <100000>;
 			clock-latency-ns = <400000>;
 		};
 		opp12 {
-			opp-hz = <1500000000>;
+			opp-hz = /bits/ 64 <1500000000>;
 			opp-microvolt = <1010000 1100000 1110000>;
 			opp-microamp = <95000>;
 			clock-latency-ns = <400000>;
@@ -379,7 +379,7 @@ Example 4: Handling multiple regulators
 		opp-shared;
 
 		opp00 {
-			opp-hz = <1000000000>;
+			opp-hz = /bits/ 64 <1000000000>;
 			opp-microvolt = <970000>, /* Supply 0 */
 					<960000>, /* Supply 1 */
 					<960000>; /* Supply 2 */
@@ -392,7 +392,7 @@ Example 4: Handling multiple regulators
 		/* OR */
 
 		opp00 {
-			opp-hz = <1000000000>;
+			opp-hz = /bits/ 64 <1000000000>;
 			opp-microvolt = <970000 975000 985000>, /* Supply 0 */
 					<960000 965000 975000>, /* Supply 1 */
 					<960000 965000 975000>; /* Supply 2 */
@@ -405,7 +405,7 @@ Example 4: Handling multiple regulators
 		/* OR */
 
 		opp00 {
-			opp-hz = <1000000000>;
+			opp-hz = /bits/ 64 <1000000000>;
 			opp-microvolt = <970000 975000 985000>, /* Supply 0 */
 					<960000 965000 975000>, /* Supply 1 */
 					<960000 965000 975000>; /* Supply 2 */
@@ -437,12 +437,12 @@ Example 5: Multiple OPP tables
 		opp-shared;
 
 		opp00 {
-			opp-hz = <600000000>;
+			opp-hz = /bits/ 64 <600000000>;
 			...
 		};
 
 		opp01 {
-			opp-hz = <800000000>;
+			opp-hz = /bits/ 64 <800000000>;
 			...
 		};
 	};
@@ -453,12 +453,12 @@ Example 5: Multiple OPP tables
 		opp-shared;
 
 		opp10 {
-			opp-hz = <1000000000>;
+			opp-hz = /bits/ 64 <1000000000>;
 			...
 		};
 
 		opp11 {
-			opp-hz = <1100000000>;
+			opp-hz = /bits/ 64 <1100000000>;
 			...
 		};
 	};
-- 
2.4.0

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

* [PATCH V3 02/16] PM / OPP: Create a directory for opp bindings
  2015-07-29 10:52 ` Viresh Kumar
@ 2015-07-29 10:52   ` Viresh Kumar
  -1 siblings, 0 replies; 92+ messages in thread
From: Viresh Kumar @ 2015-07-29 10:52 UTC (permalink / raw)
  To: Rafael Wysocki, sboyd
  Cc: linaro-kernel, linux-pm, rob.herring, arnd.bergmann, nm, broonie,
	mturquette, Sudeep.Holla, viswanath.puttagunta, l.stach,
	thomas.petazzoni, linux-arm-kernel, ta.omasab, kesavan.abhilash,
	khilman, santosh.shilimkar, b.zolnierkie, Viresh Kumar,
	devicetree

More platform specific extended opp bindings will follow and it would be
easy to manage them with a directory for opp. Lets create that and move
the existing opp bindings into it.

Cc: Rob Herring <rob.herring@linaro.org>
Cc: devicetree@vger.kernel.org
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 Documentation/devicetree/bindings/power/{ => opp}/opp.txt | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 rename Documentation/devicetree/bindings/power/{ => opp}/opp.txt (100%)

diff --git a/Documentation/devicetree/bindings/power/opp.txt b/Documentation/devicetree/bindings/power/opp/opp.txt
similarity index 100%
rename from Documentation/devicetree/bindings/power/opp.txt
rename to Documentation/devicetree/bindings/power/opp/opp.txt
-- 
2.4.0


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

* [PATCH V3 02/16] PM / OPP: Create a directory for opp bindings
@ 2015-07-29 10:52   ` Viresh Kumar
  0 siblings, 0 replies; 92+ messages in thread
From: Viresh Kumar @ 2015-07-29 10:52 UTC (permalink / raw)
  To: linux-arm-kernel

More platform specific extended opp bindings will follow and it would be
easy to manage them with a directory for opp. Lets create that and move
the existing opp bindings into it.

Cc: Rob Herring <rob.herring@linaro.org>
Cc: devicetree at vger.kernel.org
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 Documentation/devicetree/bindings/power/{ => opp}/opp.txt | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 rename Documentation/devicetree/bindings/power/{ => opp}/opp.txt (100%)

diff --git a/Documentation/devicetree/bindings/power/opp.txt b/Documentation/devicetree/bindings/power/opp/opp.txt
similarity index 100%
rename from Documentation/devicetree/bindings/power/opp.txt
rename to Documentation/devicetree/bindings/power/opp/opp.txt
-- 
2.4.0

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

* [PATCH V3 03/16] PM / OPP: Relocate few routines
  2015-07-29 10:52 ` Viresh Kumar
  (?)
@ 2015-07-29 10:52   ` Viresh Kumar
  -1 siblings, 0 replies; 92+ messages in thread
From: Viresh Kumar @ 2015-07-29 10:52 UTC (permalink / raw)
  To: Rafael Wysocki, sboyd
  Cc: linaro-kernel, linux-pm, rob.herring, arnd.bergmann, nm, broonie,
	mturquette, Sudeep.Holla, viswanath.puttagunta, l.stach,
	thomas.petazzoni, linux-arm-kernel, ta.omasab, kesavan.abhilash,
	khilman, santosh.shilimkar, b.zolnierkie, Viresh Kumar,
	Greg Kroah-Hartman, Len Brown, open list, Pavel Machek

In order to prepare for the later commits, this relocates few routines
towards the top as they will be used earlier in the code.

Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>
Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/base/power/opp.c | 277 ++++++++++++++++++++++++-----------------------
 1 file changed, 139 insertions(+), 138 deletions(-)

diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c
index 677fb2843553..8c3fd57975fb 100644
--- a/drivers/base/power/opp.c
+++ b/drivers/base/power/opp.c
@@ -438,6 +438,102 @@ static struct device_opp *_add_device_opp(struct device *dev)
 }
 
 /**
+ * _kfree_device_rcu() - Free device_opp RCU handler
+ * @head:	RCU head
+ */
+static void _kfree_device_rcu(struct rcu_head *head)
+{
+	struct device_opp *device_opp = container_of(head, struct device_opp, rcu_head);
+
+	kfree_rcu(device_opp, rcu_head);
+}
+
+/**
+ * _kfree_opp_rcu() - Free OPP RCU handler
+ * @head:	RCU head
+ */
+static void _kfree_opp_rcu(struct rcu_head *head)
+{
+	struct dev_pm_opp *opp = container_of(head, struct dev_pm_opp, rcu_head);
+
+	kfree_rcu(opp, rcu_head);
+}
+
+/**
+ * _opp_remove()  - Remove an OPP from a table definition
+ * @dev_opp:	points back to the device_opp struct this opp belongs to
+ * @opp:	pointer to the OPP to remove
+ *
+ * This function removes an opp definition from the opp list.
+ *
+ * Locking: The internal device_opp and opp structures are RCU protected.
+ * It is assumed that the caller holds required mutex for an RCU updater
+ * strategy.
+ */
+static void _opp_remove(struct device_opp *dev_opp,
+			struct dev_pm_opp *opp)
+{
+	/*
+	 * Notify the changes in the availability of the operable
+	 * frequency/voltage list.
+	 */
+	srcu_notifier_call_chain(&dev_opp->srcu_head, OPP_EVENT_REMOVE, opp);
+	list_del_rcu(&opp->node);
+	call_srcu(&dev_opp->srcu_head.srcu, &opp->rcu_head, _kfree_opp_rcu);
+
+	if (list_empty(&dev_opp->opp_list)) {
+		list_del_rcu(&dev_opp->node);
+		call_srcu(&dev_opp->srcu_head.srcu, &dev_opp->rcu_head,
+			  _kfree_device_rcu);
+	}
+}
+
+/**
+ * dev_pm_opp_remove()  - Remove an OPP from OPP list
+ * @dev:	device for which we do this operation
+ * @freq:	OPP to remove with matching 'freq'
+ *
+ * This function removes an opp from the opp list.
+ *
+ * Locking: The internal device_opp and opp structures are RCU protected.
+ * Hence this function internally uses RCU updater strategy with mutex locks
+ * to keep the integrity of the internal data structures. Callers should ensure
+ * that this function is *NOT* called under RCU protection or in contexts where
+ * mutex cannot be locked.
+ */
+void dev_pm_opp_remove(struct device *dev, unsigned long freq)
+{
+	struct dev_pm_opp *opp;
+	struct device_opp *dev_opp;
+	bool found = false;
+
+	/* Hold our list modification lock here */
+	mutex_lock(&dev_opp_list_lock);
+
+	dev_opp = _find_device_opp(dev);
+	if (IS_ERR(dev_opp))
+		goto unlock;
+
+	list_for_each_entry(opp, &dev_opp->opp_list, node) {
+		if (opp->rate == freq) {
+			found = true;
+			break;
+		}
+	}
+
+	if (!found) {
+		dev_warn(dev, "%s: Couldn't find OPP with freq: %lu\n",
+			 __func__, freq);
+		goto unlock;
+	}
+
+	_opp_remove(dev_opp, opp);
+unlock:
+	mutex_unlock(&dev_opp_list_lock);
+}
+EXPORT_SYMBOL_GPL(dev_pm_opp_remove);
+
+/**
  * _opp_add_dynamic() - Allocate a dynamic OPP.
  * @dev:	device for which we do this operation
  * @freq:	Frequency in Hz for this OPP
@@ -570,102 +666,6 @@ int dev_pm_opp_add(struct device *dev, unsigned long freq, unsigned long u_volt)
 EXPORT_SYMBOL_GPL(dev_pm_opp_add);
 
 /**
- * _kfree_opp_rcu() - Free OPP RCU handler
- * @head:	RCU head
- */
-static void _kfree_opp_rcu(struct rcu_head *head)
-{
-	struct dev_pm_opp *opp = container_of(head, struct dev_pm_opp, rcu_head);
-
-	kfree_rcu(opp, rcu_head);
-}
-
-/**
- * _kfree_device_rcu() - Free device_opp RCU handler
- * @head:	RCU head
- */
-static void _kfree_device_rcu(struct rcu_head *head)
-{
-	struct device_opp *device_opp = container_of(head, struct device_opp, rcu_head);
-
-	kfree_rcu(device_opp, rcu_head);
-}
-
-/**
- * _opp_remove()  - Remove an OPP from a table definition
- * @dev_opp:	points back to the device_opp struct this opp belongs to
- * @opp:	pointer to the OPP to remove
- *
- * This function removes an opp definition from the opp list.
- *
- * Locking: The internal device_opp and opp structures are RCU protected.
- * It is assumed that the caller holds required mutex for an RCU updater
- * strategy.
- */
-static void _opp_remove(struct device_opp *dev_opp,
-			struct dev_pm_opp *opp)
-{
-	/*
-	 * Notify the changes in the availability of the operable
-	 * frequency/voltage list.
-	 */
-	srcu_notifier_call_chain(&dev_opp->srcu_head, OPP_EVENT_REMOVE, opp);
-	list_del_rcu(&opp->node);
-	call_srcu(&dev_opp->srcu_head.srcu, &opp->rcu_head, _kfree_opp_rcu);
-
-	if (list_empty(&dev_opp->opp_list)) {
-		list_del_rcu(&dev_opp->node);
-		call_srcu(&dev_opp->srcu_head.srcu, &dev_opp->rcu_head,
-			  _kfree_device_rcu);
-	}
-}
-
-/**
- * dev_pm_opp_remove()  - Remove an OPP from OPP list
- * @dev:	device for which we do this operation
- * @freq:	OPP to remove with matching 'freq'
- *
- * This function removes an opp from the opp list.
- *
- * Locking: The internal device_opp and opp structures are RCU protected.
- * Hence this function internally uses RCU updater strategy with mutex locks
- * to keep the integrity of the internal data structures. Callers should ensure
- * that this function is *NOT* called under RCU protection or in contexts where
- * mutex cannot be locked.
- */
-void dev_pm_opp_remove(struct device *dev, unsigned long freq)
-{
-	struct dev_pm_opp *opp;
-	struct device_opp *dev_opp;
-	bool found = false;
-
-	/* Hold our list modification lock here */
-	mutex_lock(&dev_opp_list_lock);
-
-	dev_opp = _find_device_opp(dev);
-	if (IS_ERR(dev_opp))
-		goto unlock;
-
-	list_for_each_entry(opp, &dev_opp->opp_list, node) {
-		if (opp->rate == freq) {
-			found = true;
-			break;
-		}
-	}
-
-	if (!found) {
-		dev_warn(dev, "%s: Couldn't find OPP with freq: %lu\n",
-			 __func__, freq);
-		goto unlock;
-	}
-
-	_opp_remove(dev_opp, opp);
-unlock:
-	mutex_unlock(&dev_opp_list_lock);
-}
-EXPORT_SYMBOL_GPL(dev_pm_opp_remove);
-
-/**
  * _opp_set_availability() - helper to set the availability of an opp
  * @dev:		device for which we do this operation
  * @freq:		OPP frequency to modify availability
@@ -825,6 +825,49 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_get_notifier);
 
 #ifdef CONFIG_OF
 /**
+ * of_free_opp_table() - Free OPP table entries created from static DT entries
+ * @dev:	device pointer used to lookup device OPPs.
+ *
+ * Free OPPs created using static entries present in DT.
+ *
+ * Locking: The internal device_opp and opp structures are RCU protected.
+ * Hence this function indirectly uses RCU updater strategy with mutex locks
+ * to keep the integrity of the internal data structures. Callers should ensure
+ * that this function is *NOT* called under RCU protection or in contexts where
+ * mutex cannot be locked.
+ */
+void of_free_opp_table(struct device *dev)
+{
+	struct device_opp *dev_opp;
+	struct dev_pm_opp *opp, *tmp;
+
+	/* Check for existing list for 'dev' */
+	dev_opp = _find_device_opp(dev);
+	if (IS_ERR(dev_opp)) {
+		int error = PTR_ERR(dev_opp);
+
+		if (error != -ENODEV)
+			WARN(1, "%s: dev_opp: %d\n",
+			     IS_ERR_OR_NULL(dev) ?
+					"Invalid device" : dev_name(dev),
+			     error);
+		return;
+	}
+
+	/* Hold our list modification lock here */
+	mutex_lock(&dev_opp_list_lock);
+
+	/* Free static OPPs */
+	list_for_each_entry_safe(opp, tmp, &dev_opp->opp_list, node) {
+		if (!opp->dynamic)
+			_opp_remove(dev_opp, opp);
+	}
+
+	mutex_unlock(&dev_opp_list_lock);
+}
+EXPORT_SYMBOL_GPL(of_free_opp_table);
+
+/**
  * of_init_opp_table() - Initialize opp table from device tree
  * @dev:	device pointer used to lookup device OPPs.
  *
@@ -882,46 +925,4 @@ int of_init_opp_table(struct device *dev)
 	return 0;
 }
 EXPORT_SYMBOL_GPL(of_init_opp_table);
-
-/**
- * of_free_opp_table() - Free OPP table entries created from static DT entries
- * @dev:	device pointer used to lookup device OPPs.
- *
- * Free OPPs created using static entries present in DT.
- *
- * Locking: The internal device_opp and opp structures are RCU protected.
- * Hence this function indirectly uses RCU updater strategy with mutex locks
- * to keep the integrity of the internal data structures. Callers should ensure
- * that this function is *NOT* called under RCU protection or in contexts where
- * mutex cannot be locked.
- */
-void of_free_opp_table(struct device *dev)
-{
-	struct device_opp *dev_opp;
-	struct dev_pm_opp *opp, *tmp;
-
-	/* Check for existing list for 'dev' */
-	dev_opp = _find_device_opp(dev);
-	if (IS_ERR(dev_opp)) {
-		int error = PTR_ERR(dev_opp);
-		if (error != -ENODEV)
-			WARN(1, "%s: dev_opp: %d\n",
-			     IS_ERR_OR_NULL(dev) ?
-					"Invalid device" : dev_name(dev),
-			     error);
-		return;
-	}
-
-	/* Hold our list modification lock here */
-	mutex_lock(&dev_opp_list_lock);
-
-	/* Free static OPPs */
-	list_for_each_entry_safe(opp, tmp, &dev_opp->opp_list, node) {
-		if (!opp->dynamic)
-			_opp_remove(dev_opp, opp);
-	}
-
-	mutex_unlock(&dev_opp_list_lock);
-}
-EXPORT_SYMBOL_GPL(of_free_opp_table);
 #endif
-- 
2.4.0


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

* [PATCH V3 03/16] PM / OPP: Relocate few routines
@ 2015-07-29 10:52   ` Viresh Kumar
  0 siblings, 0 replies; 92+ messages in thread
From: Viresh Kumar @ 2015-07-29 10:52 UTC (permalink / raw)
  To: Rafael Wysocki, sboyd
  Cc: linaro-kernel, linux-pm, rob.herring, arnd.bergmann, nm, broonie,
	mturquette, Sudeep.Holla, viswanath.puttagunta, l.stach,
	thomas.petazzoni, linux-arm-kernel, ta.omasab, kesavan.abhilash,
	khilman, santosh.shilimkar, b.zolnierkie, Viresh Kumar,
	Greg Kroah-Hartman, Len Brown, open list, Pavel Machek

In order to prepare for the later commits, this relocates few routines
towards the top as they will be used earlier in the code.

Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>
Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/base/power/opp.c | 277 ++++++++++++++++++++++++-----------------------
 1 file changed, 139 insertions(+), 138 deletions(-)

diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c
index 677fb2843553..8c3fd57975fb 100644
--- a/drivers/base/power/opp.c
+++ b/drivers/base/power/opp.c
@@ -438,6 +438,102 @@ static struct device_opp *_add_device_opp(struct device *dev)
 }
 
 /**
+ * _kfree_device_rcu() - Free device_opp RCU handler
+ * @head:	RCU head
+ */
+static void _kfree_device_rcu(struct rcu_head *head)
+{
+	struct device_opp *device_opp = container_of(head, struct device_opp, rcu_head);
+
+	kfree_rcu(device_opp, rcu_head);
+}
+
+/**
+ * _kfree_opp_rcu() - Free OPP RCU handler
+ * @head:	RCU head
+ */
+static void _kfree_opp_rcu(struct rcu_head *head)
+{
+	struct dev_pm_opp *opp = container_of(head, struct dev_pm_opp, rcu_head);
+
+	kfree_rcu(opp, rcu_head);
+}
+
+/**
+ * _opp_remove()  - Remove an OPP from a table definition
+ * @dev_opp:	points back to the device_opp struct this opp belongs to
+ * @opp:	pointer to the OPP to remove
+ *
+ * This function removes an opp definition from the opp list.
+ *
+ * Locking: The internal device_opp and opp structures are RCU protected.
+ * It is assumed that the caller holds required mutex for an RCU updater
+ * strategy.
+ */
+static void _opp_remove(struct device_opp *dev_opp,
+			struct dev_pm_opp *opp)
+{
+	/*
+	 * Notify the changes in the availability of the operable
+	 * frequency/voltage list.
+	 */
+	srcu_notifier_call_chain(&dev_opp->srcu_head, OPP_EVENT_REMOVE, opp);
+	list_del_rcu(&opp->node);
+	call_srcu(&dev_opp->srcu_head.srcu, &opp->rcu_head, _kfree_opp_rcu);
+
+	if (list_empty(&dev_opp->opp_list)) {
+		list_del_rcu(&dev_opp->node);
+		call_srcu(&dev_opp->srcu_head.srcu, &dev_opp->rcu_head,
+			  _kfree_device_rcu);
+	}
+}
+
+/**
+ * dev_pm_opp_remove()  - Remove an OPP from OPP list
+ * @dev:	device for which we do this operation
+ * @freq:	OPP to remove with matching 'freq'
+ *
+ * This function removes an opp from the opp list.
+ *
+ * Locking: The internal device_opp and opp structures are RCU protected.
+ * Hence this function internally uses RCU updater strategy with mutex locks
+ * to keep the integrity of the internal data structures. Callers should ensure
+ * that this function is *NOT* called under RCU protection or in contexts where
+ * mutex cannot be locked.
+ */
+void dev_pm_opp_remove(struct device *dev, unsigned long freq)
+{
+	struct dev_pm_opp *opp;
+	struct device_opp *dev_opp;
+	bool found = false;
+
+	/* Hold our list modification lock here */
+	mutex_lock(&dev_opp_list_lock);
+
+	dev_opp = _find_device_opp(dev);
+	if (IS_ERR(dev_opp))
+		goto unlock;
+
+	list_for_each_entry(opp, &dev_opp->opp_list, node) {
+		if (opp->rate == freq) {
+			found = true;
+			break;
+		}
+	}
+
+	if (!found) {
+		dev_warn(dev, "%s: Couldn't find OPP with freq: %lu\n",
+			 __func__, freq);
+		goto unlock;
+	}
+
+	_opp_remove(dev_opp, opp);
+unlock:
+	mutex_unlock(&dev_opp_list_lock);
+}
+EXPORT_SYMBOL_GPL(dev_pm_opp_remove);
+
+/**
  * _opp_add_dynamic() - Allocate a dynamic OPP.
  * @dev:	device for which we do this operation
  * @freq:	Frequency in Hz for this OPP
@@ -570,102 +666,6 @@ int dev_pm_opp_add(struct device *dev, unsigned long freq, unsigned long u_volt)
 EXPORT_SYMBOL_GPL(dev_pm_opp_add);
 
 /**
- * _kfree_opp_rcu() - Free OPP RCU handler
- * @head:	RCU head
- */
-static void _kfree_opp_rcu(struct rcu_head *head)
-{
-	struct dev_pm_opp *opp = container_of(head, struct dev_pm_opp, rcu_head);
-
-	kfree_rcu(opp, rcu_head);
-}
-
-/**
- * _kfree_device_rcu() - Free device_opp RCU handler
- * @head:	RCU head
- */
-static void _kfree_device_rcu(struct rcu_head *head)
-{
-	struct device_opp *device_opp = container_of(head, struct device_opp, rcu_head);
-
-	kfree_rcu(device_opp, rcu_head);
-}
-
-/**
- * _opp_remove()  - Remove an OPP from a table definition
- * @dev_opp:	points back to the device_opp struct this opp belongs to
- * @opp:	pointer to the OPP to remove
- *
- * This function removes an opp definition from the opp list.
- *
- * Locking: The internal device_opp and opp structures are RCU protected.
- * It is assumed that the caller holds required mutex for an RCU updater
- * strategy.
- */
-static void _opp_remove(struct device_opp *dev_opp,
-			struct dev_pm_opp *opp)
-{
-	/*
-	 * Notify the changes in the availability of the operable
-	 * frequency/voltage list.
-	 */
-	srcu_notifier_call_chain(&dev_opp->srcu_head, OPP_EVENT_REMOVE, opp);
-	list_del_rcu(&opp->node);
-	call_srcu(&dev_opp->srcu_head.srcu, &opp->rcu_head, _kfree_opp_rcu);
-
-	if (list_empty(&dev_opp->opp_list)) {
-		list_del_rcu(&dev_opp->node);
-		call_srcu(&dev_opp->srcu_head.srcu, &dev_opp->rcu_head,
-			  _kfree_device_rcu);
-	}
-}
-
-/**
- * dev_pm_opp_remove()  - Remove an OPP from OPP list
- * @dev:	device for which we do this operation
- * @freq:	OPP to remove with matching 'freq'
- *
- * This function removes an opp from the opp list.
- *
- * Locking: The internal device_opp and opp structures are RCU protected.
- * Hence this function internally uses RCU updater strategy with mutex locks
- * to keep the integrity of the internal data structures. Callers should ensure
- * that this function is *NOT* called under RCU protection or in contexts where
- * mutex cannot be locked.
- */
-void dev_pm_opp_remove(struct device *dev, unsigned long freq)
-{
-	struct dev_pm_opp *opp;
-	struct device_opp *dev_opp;
-	bool found = false;
-
-	/* Hold our list modification lock here */
-	mutex_lock(&dev_opp_list_lock);
-
-	dev_opp = _find_device_opp(dev);
-	if (IS_ERR(dev_opp))
-		goto unlock;
-
-	list_for_each_entry(opp, &dev_opp->opp_list, node) {
-		if (opp->rate == freq) {
-			found = true;
-			break;
-		}
-	}
-
-	if (!found) {
-		dev_warn(dev, "%s: Couldn't find OPP with freq: %lu\n",
-			 __func__, freq);
-		goto unlock;
-	}
-
-	_opp_remove(dev_opp, opp);
-unlock:
-	mutex_unlock(&dev_opp_list_lock);
-}
-EXPORT_SYMBOL_GPL(dev_pm_opp_remove);
-
-/**
  * _opp_set_availability() - helper to set the availability of an opp
  * @dev:		device for which we do this operation
  * @freq:		OPP frequency to modify availability
@@ -825,6 +825,49 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_get_notifier);
 
 #ifdef CONFIG_OF
 /**
+ * of_free_opp_table() - Free OPP table entries created from static DT entries
+ * @dev:	device pointer used to lookup device OPPs.
+ *
+ * Free OPPs created using static entries present in DT.
+ *
+ * Locking: The internal device_opp and opp structures are RCU protected.
+ * Hence this function indirectly uses RCU updater strategy with mutex locks
+ * to keep the integrity of the internal data structures. Callers should ensure
+ * that this function is *NOT* called under RCU protection or in contexts where
+ * mutex cannot be locked.
+ */
+void of_free_opp_table(struct device *dev)
+{
+	struct device_opp *dev_opp;
+	struct dev_pm_opp *opp, *tmp;
+
+	/* Check for existing list for 'dev' */
+	dev_opp = _find_device_opp(dev);
+	if (IS_ERR(dev_opp)) {
+		int error = PTR_ERR(dev_opp);
+
+		if (error != -ENODEV)
+			WARN(1, "%s: dev_opp: %d\n",
+			     IS_ERR_OR_NULL(dev) ?
+					"Invalid device" : dev_name(dev),
+			     error);
+		return;
+	}
+
+	/* Hold our list modification lock here */
+	mutex_lock(&dev_opp_list_lock);
+
+	/* Free static OPPs */
+	list_for_each_entry_safe(opp, tmp, &dev_opp->opp_list, node) {
+		if (!opp->dynamic)
+			_opp_remove(dev_opp, opp);
+	}
+
+	mutex_unlock(&dev_opp_list_lock);
+}
+EXPORT_SYMBOL_GPL(of_free_opp_table);
+
+/**
  * of_init_opp_table() - Initialize opp table from device tree
  * @dev:	device pointer used to lookup device OPPs.
  *
@@ -882,46 +925,4 @@ int of_init_opp_table(struct device *dev)
 	return 0;
 }
 EXPORT_SYMBOL_GPL(of_init_opp_table);
-
-/**
- * of_free_opp_table() - Free OPP table entries created from static DT entries
- * @dev:	device pointer used to lookup device OPPs.
- *
- * Free OPPs created using static entries present in DT.
- *
- * Locking: The internal device_opp and opp structures are RCU protected.
- * Hence this function indirectly uses RCU updater strategy with mutex locks
- * to keep the integrity of the internal data structures. Callers should ensure
- * that this function is *NOT* called under RCU protection or in contexts where
- * mutex cannot be locked.
- */
-void of_free_opp_table(struct device *dev)
-{
-	struct device_opp *dev_opp;
-	struct dev_pm_opp *opp, *tmp;
-
-	/* Check for existing list for 'dev' */
-	dev_opp = _find_device_opp(dev);
-	if (IS_ERR(dev_opp)) {
-		int error = PTR_ERR(dev_opp);
-		if (error != -ENODEV)
-			WARN(1, "%s: dev_opp: %d\n",
-			     IS_ERR_OR_NULL(dev) ?
-					"Invalid device" : dev_name(dev),
-			     error);
-		return;
-	}
-
-	/* Hold our list modification lock here */
-	mutex_lock(&dev_opp_list_lock);
-
-	/* Free static OPPs */
-	list_for_each_entry_safe(opp, tmp, &dev_opp->opp_list, node) {
-		if (!opp->dynamic)
-			_opp_remove(dev_opp, opp);
-	}
-
-	mutex_unlock(&dev_opp_list_lock);
-}
-EXPORT_SYMBOL_GPL(of_free_opp_table);
 #endif
-- 
2.4.0


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

* [PATCH V3 03/16] PM / OPP: Relocate few routines
@ 2015-07-29 10:52   ` Viresh Kumar
  0 siblings, 0 replies; 92+ messages in thread
From: Viresh Kumar @ 2015-07-29 10:52 UTC (permalink / raw)
  To: linux-arm-kernel

In order to prepare for the later commits, this relocates few routines
towards the top as they will be used earlier in the code.

Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>
Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/base/power/opp.c | 277 ++++++++++++++++++++++++-----------------------
 1 file changed, 139 insertions(+), 138 deletions(-)

diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c
index 677fb2843553..8c3fd57975fb 100644
--- a/drivers/base/power/opp.c
+++ b/drivers/base/power/opp.c
@@ -438,6 +438,102 @@ static struct device_opp *_add_device_opp(struct device *dev)
 }
 
 /**
+ * _kfree_device_rcu() - Free device_opp RCU handler
+ * @head:	RCU head
+ */
+static void _kfree_device_rcu(struct rcu_head *head)
+{
+	struct device_opp *device_opp = container_of(head, struct device_opp, rcu_head);
+
+	kfree_rcu(device_opp, rcu_head);
+}
+
+/**
+ * _kfree_opp_rcu() - Free OPP RCU handler
+ * @head:	RCU head
+ */
+static void _kfree_opp_rcu(struct rcu_head *head)
+{
+	struct dev_pm_opp *opp = container_of(head, struct dev_pm_opp, rcu_head);
+
+	kfree_rcu(opp, rcu_head);
+}
+
+/**
+ * _opp_remove()  - Remove an OPP from a table definition
+ * @dev_opp:	points back to the device_opp struct this opp belongs to
+ * @opp:	pointer to the OPP to remove
+ *
+ * This function removes an opp definition from the opp list.
+ *
+ * Locking: The internal device_opp and opp structures are RCU protected.
+ * It is assumed that the caller holds required mutex for an RCU updater
+ * strategy.
+ */
+static void _opp_remove(struct device_opp *dev_opp,
+			struct dev_pm_opp *opp)
+{
+	/*
+	 * Notify the changes in the availability of the operable
+	 * frequency/voltage list.
+	 */
+	srcu_notifier_call_chain(&dev_opp->srcu_head, OPP_EVENT_REMOVE, opp);
+	list_del_rcu(&opp->node);
+	call_srcu(&dev_opp->srcu_head.srcu, &opp->rcu_head, _kfree_opp_rcu);
+
+	if (list_empty(&dev_opp->opp_list)) {
+		list_del_rcu(&dev_opp->node);
+		call_srcu(&dev_opp->srcu_head.srcu, &dev_opp->rcu_head,
+			  _kfree_device_rcu);
+	}
+}
+
+/**
+ * dev_pm_opp_remove()  - Remove an OPP from OPP list
+ * @dev:	device for which we do this operation
+ * @freq:	OPP to remove with matching 'freq'
+ *
+ * This function removes an opp from the opp list.
+ *
+ * Locking: The internal device_opp and opp structures are RCU protected.
+ * Hence this function internally uses RCU updater strategy with mutex locks
+ * to keep the integrity of the internal data structures. Callers should ensure
+ * that this function is *NOT* called under RCU protection or in contexts where
+ * mutex cannot be locked.
+ */
+void dev_pm_opp_remove(struct device *dev, unsigned long freq)
+{
+	struct dev_pm_opp *opp;
+	struct device_opp *dev_opp;
+	bool found = false;
+
+	/* Hold our list modification lock here */
+	mutex_lock(&dev_opp_list_lock);
+
+	dev_opp = _find_device_opp(dev);
+	if (IS_ERR(dev_opp))
+		goto unlock;
+
+	list_for_each_entry(opp, &dev_opp->opp_list, node) {
+		if (opp->rate == freq) {
+			found = true;
+			break;
+		}
+	}
+
+	if (!found) {
+		dev_warn(dev, "%s: Couldn't find OPP with freq: %lu\n",
+			 __func__, freq);
+		goto unlock;
+	}
+
+	_opp_remove(dev_opp, opp);
+unlock:
+	mutex_unlock(&dev_opp_list_lock);
+}
+EXPORT_SYMBOL_GPL(dev_pm_opp_remove);
+
+/**
  * _opp_add_dynamic() - Allocate a dynamic OPP.
  * @dev:	device for which we do this operation
  * @freq:	Frequency in Hz for this OPP
@@ -570,102 +666,6 @@ int dev_pm_opp_add(struct device *dev, unsigned long freq, unsigned long u_volt)
 EXPORT_SYMBOL_GPL(dev_pm_opp_add);
 
 /**
- * _kfree_opp_rcu() - Free OPP RCU handler
- * @head:	RCU head
- */
-static void _kfree_opp_rcu(struct rcu_head *head)
-{
-	struct dev_pm_opp *opp = container_of(head, struct dev_pm_opp, rcu_head);
-
-	kfree_rcu(opp, rcu_head);
-}
-
-/**
- * _kfree_device_rcu() - Free device_opp RCU handler
- * @head:	RCU head
- */
-static void _kfree_device_rcu(struct rcu_head *head)
-{
-	struct device_opp *device_opp = container_of(head, struct device_opp, rcu_head);
-
-	kfree_rcu(device_opp, rcu_head);
-}
-
-/**
- * _opp_remove()  - Remove an OPP from a table definition
- * @dev_opp:	points back to the device_opp struct this opp belongs to
- * @opp:	pointer to the OPP to remove
- *
- * This function removes an opp definition from the opp list.
- *
- * Locking: The internal device_opp and opp structures are RCU protected.
- * It is assumed that the caller holds required mutex for an RCU updater
- * strategy.
- */
-static void _opp_remove(struct device_opp *dev_opp,
-			struct dev_pm_opp *opp)
-{
-	/*
-	 * Notify the changes in the availability of the operable
-	 * frequency/voltage list.
-	 */
-	srcu_notifier_call_chain(&dev_opp->srcu_head, OPP_EVENT_REMOVE, opp);
-	list_del_rcu(&opp->node);
-	call_srcu(&dev_opp->srcu_head.srcu, &opp->rcu_head, _kfree_opp_rcu);
-
-	if (list_empty(&dev_opp->opp_list)) {
-		list_del_rcu(&dev_opp->node);
-		call_srcu(&dev_opp->srcu_head.srcu, &dev_opp->rcu_head,
-			  _kfree_device_rcu);
-	}
-}
-
-/**
- * dev_pm_opp_remove()  - Remove an OPP from OPP list
- * @dev:	device for which we do this operation
- * @freq:	OPP to remove with matching 'freq'
- *
- * This function removes an opp from the opp list.
- *
- * Locking: The internal device_opp and opp structures are RCU protected.
- * Hence this function internally uses RCU updater strategy with mutex locks
- * to keep the integrity of the internal data structures. Callers should ensure
- * that this function is *NOT* called under RCU protection or in contexts where
- * mutex cannot be locked.
- */
-void dev_pm_opp_remove(struct device *dev, unsigned long freq)
-{
-	struct dev_pm_opp *opp;
-	struct device_opp *dev_opp;
-	bool found = false;
-
-	/* Hold our list modification lock here */
-	mutex_lock(&dev_opp_list_lock);
-
-	dev_opp = _find_device_opp(dev);
-	if (IS_ERR(dev_opp))
-		goto unlock;
-
-	list_for_each_entry(opp, &dev_opp->opp_list, node) {
-		if (opp->rate == freq) {
-			found = true;
-			break;
-		}
-	}
-
-	if (!found) {
-		dev_warn(dev, "%s: Couldn't find OPP with freq: %lu\n",
-			 __func__, freq);
-		goto unlock;
-	}
-
-	_opp_remove(dev_opp, opp);
-unlock:
-	mutex_unlock(&dev_opp_list_lock);
-}
-EXPORT_SYMBOL_GPL(dev_pm_opp_remove);
-
-/**
  * _opp_set_availability() - helper to set the availability of an opp
  * @dev:		device for which we do this operation
  * @freq:		OPP frequency to modify availability
@@ -825,6 +825,49 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_get_notifier);
 
 #ifdef CONFIG_OF
 /**
+ * of_free_opp_table() - Free OPP table entries created from static DT entries
+ * @dev:	device pointer used to lookup device OPPs.
+ *
+ * Free OPPs created using static entries present in DT.
+ *
+ * Locking: The internal device_opp and opp structures are RCU protected.
+ * Hence this function indirectly uses RCU updater strategy with mutex locks
+ * to keep the integrity of the internal data structures. Callers should ensure
+ * that this function is *NOT* called under RCU protection or in contexts where
+ * mutex cannot be locked.
+ */
+void of_free_opp_table(struct device *dev)
+{
+	struct device_opp *dev_opp;
+	struct dev_pm_opp *opp, *tmp;
+
+	/* Check for existing list for 'dev' */
+	dev_opp = _find_device_opp(dev);
+	if (IS_ERR(dev_opp)) {
+		int error = PTR_ERR(dev_opp);
+
+		if (error != -ENODEV)
+			WARN(1, "%s: dev_opp: %d\n",
+			     IS_ERR_OR_NULL(dev) ?
+					"Invalid device" : dev_name(dev),
+			     error);
+		return;
+	}
+
+	/* Hold our list modification lock here */
+	mutex_lock(&dev_opp_list_lock);
+
+	/* Free static OPPs */
+	list_for_each_entry_safe(opp, tmp, &dev_opp->opp_list, node) {
+		if (!opp->dynamic)
+			_opp_remove(dev_opp, opp);
+	}
+
+	mutex_unlock(&dev_opp_list_lock);
+}
+EXPORT_SYMBOL_GPL(of_free_opp_table);
+
+/**
  * of_init_opp_table() - Initialize opp table from device tree
  * @dev:	device pointer used to lookup device OPPs.
  *
@@ -882,46 +925,4 @@ int of_init_opp_table(struct device *dev)
 	return 0;
 }
 EXPORT_SYMBOL_GPL(of_init_opp_table);
-
-/**
- * of_free_opp_table() - Free OPP table entries created from static DT entries
- * @dev:	device pointer used to lookup device OPPs.
- *
- * Free OPPs created using static entries present in DT.
- *
- * Locking: The internal device_opp and opp structures are RCU protected.
- * Hence this function indirectly uses RCU updater strategy with mutex locks
- * to keep the integrity of the internal data structures. Callers should ensure
- * that this function is *NOT* called under RCU protection or in contexts where
- * mutex cannot be locked.
- */
-void of_free_opp_table(struct device *dev)
-{
-	struct device_opp *dev_opp;
-	struct dev_pm_opp *opp, *tmp;
-
-	/* Check for existing list for 'dev' */
-	dev_opp = _find_device_opp(dev);
-	if (IS_ERR(dev_opp)) {
-		int error = PTR_ERR(dev_opp);
-		if (error != -ENODEV)
-			WARN(1, "%s: dev_opp: %d\n",
-			     IS_ERR_OR_NULL(dev) ?
-					"Invalid device" : dev_name(dev),
-			     error);
-		return;
-	}
-
-	/* Hold our list modification lock here */
-	mutex_lock(&dev_opp_list_lock);
-
-	/* Free static OPPs */
-	list_for_each_entry_safe(opp, tmp, &dev_opp->opp_list, node) {
-		if (!opp->dynamic)
-			_opp_remove(dev_opp, opp);
-	}
-
-	mutex_unlock(&dev_opp_list_lock);
-}
-EXPORT_SYMBOL_GPL(of_free_opp_table);
 #endif
-- 
2.4.0

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

* [PATCH V3 04/16] PM / OPP: Create _remove_device_opp() for freeing dev_opp
  2015-07-29 10:52 ` Viresh Kumar
  (?)
@ 2015-07-29 10:52   ` Viresh Kumar
  -1 siblings, 0 replies; 92+ messages in thread
From: Viresh Kumar @ 2015-07-29 10:52 UTC (permalink / raw)
  To: Rafael Wysocki, sboyd
  Cc: linaro-kernel, linux-pm, rob.herring, arnd.bergmann, nm, broonie,
	mturquette, Sudeep.Holla, viswanath.puttagunta, l.stach,
	thomas.petazzoni, linux-arm-kernel, ta.omasab, kesavan.abhilash,
	khilman, santosh.shilimkar, b.zolnierkie, Viresh Kumar,
	Greg Kroah-Hartman, Len Brown, open list, Pavel Machek

This will be used from multiple places later. Lets create a separate
routine for that.

Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>
Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/base/power/opp.c | 22 +++++++++++++++++-----
 1 file changed, 17 insertions(+), 5 deletions(-)

diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c
index 8c3fd57975fb..7895fdd64192 100644
--- a/drivers/base/power/opp.c
+++ b/drivers/base/power/opp.c
@@ -449,6 +449,22 @@ static void _kfree_device_rcu(struct rcu_head *head)
 }
 
 /**
+ * _remove_device_opp() - Removes a device OPP table
+ * @dev_opp: device OPP table to be removed.
+ *
+ * Removes/frees device OPP table it it doesn't contain any OPPs.
+ */
+static void _remove_device_opp(struct device_opp *dev_opp)
+{
+	if (!list_empty(&dev_opp->opp_list))
+		return;
+
+	list_del_rcu(&dev_opp->node);
+	call_srcu(&dev_opp->srcu_head.srcu, &dev_opp->rcu_head,
+		  _kfree_device_rcu);
+}
+
+/**
  * _kfree_opp_rcu() - Free OPP RCU handler
  * @head:	RCU head
  */
@@ -481,11 +497,7 @@ static void _opp_remove(struct device_opp *dev_opp,
 	list_del_rcu(&opp->node);
 	call_srcu(&dev_opp->srcu_head.srcu, &opp->rcu_head, _kfree_opp_rcu);
 
-	if (list_empty(&dev_opp->opp_list)) {
-		list_del_rcu(&dev_opp->node);
-		call_srcu(&dev_opp->srcu_head.srcu, &dev_opp->rcu_head,
-			  _kfree_device_rcu);
-	}
+	_remove_device_opp(dev_opp);
 }
 
 /**
-- 
2.4.0


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

* [PATCH V3 04/16] PM / OPP: Create _remove_device_opp() for freeing dev_opp
@ 2015-07-29 10:52   ` Viresh Kumar
  0 siblings, 0 replies; 92+ messages in thread
From: Viresh Kumar @ 2015-07-29 10:52 UTC (permalink / raw)
  To: Rafael Wysocki, sboyd
  Cc: linaro-kernel, linux-pm, rob.herring, arnd.bergmann, nm, broonie,
	mturquette, Sudeep.Holla, viswanath.puttagunta, l.stach,
	thomas.petazzoni, linux-arm-kernel, ta.omasab, kesavan.abhilash,
	khilman, santosh.shilimkar, b.zolnierkie, Viresh Kumar,
	Greg Kroah-Hartman, Len Brown, open list, Pavel Machek

This will be used from multiple places later. Lets create a separate
routine for that.

Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>
Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/base/power/opp.c | 22 +++++++++++++++++-----
 1 file changed, 17 insertions(+), 5 deletions(-)

diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c
index 8c3fd57975fb..7895fdd64192 100644
--- a/drivers/base/power/opp.c
+++ b/drivers/base/power/opp.c
@@ -449,6 +449,22 @@ static void _kfree_device_rcu(struct rcu_head *head)
 }
 
 /**
+ * _remove_device_opp() - Removes a device OPP table
+ * @dev_opp: device OPP table to be removed.
+ *
+ * Removes/frees device OPP table it it doesn't contain any OPPs.
+ */
+static void _remove_device_opp(struct device_opp *dev_opp)
+{
+	if (!list_empty(&dev_opp->opp_list))
+		return;
+
+	list_del_rcu(&dev_opp->node);
+	call_srcu(&dev_opp->srcu_head.srcu, &dev_opp->rcu_head,
+		  _kfree_device_rcu);
+}
+
+/**
  * _kfree_opp_rcu() - Free OPP RCU handler
  * @head:	RCU head
  */
@@ -481,11 +497,7 @@ static void _opp_remove(struct device_opp *dev_opp,
 	list_del_rcu(&opp->node);
 	call_srcu(&dev_opp->srcu_head.srcu, &opp->rcu_head, _kfree_opp_rcu);
 
-	if (list_empty(&dev_opp->opp_list)) {
-		list_del_rcu(&dev_opp->node);
-		call_srcu(&dev_opp->srcu_head.srcu, &dev_opp->rcu_head,
-			  _kfree_device_rcu);
-	}
+	_remove_device_opp(dev_opp);
 }
 
 /**
-- 
2.4.0

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

* [PATCH V3 04/16] PM / OPP: Create _remove_device_opp() for freeing dev_opp
@ 2015-07-29 10:52   ` Viresh Kumar
  0 siblings, 0 replies; 92+ messages in thread
From: Viresh Kumar @ 2015-07-29 10:52 UTC (permalink / raw)
  To: linux-arm-kernel

This will be used from multiple places later. Lets create a separate
routine for that.

Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>
Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/base/power/opp.c | 22 +++++++++++++++++-----
 1 file changed, 17 insertions(+), 5 deletions(-)

diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c
index 8c3fd57975fb..7895fdd64192 100644
--- a/drivers/base/power/opp.c
+++ b/drivers/base/power/opp.c
@@ -449,6 +449,22 @@ static void _kfree_device_rcu(struct rcu_head *head)
 }
 
 /**
+ * _remove_device_opp() - Removes a device OPP table
+ * @dev_opp: device OPP table to be removed.
+ *
+ * Removes/frees device OPP table it it doesn't contain any OPPs.
+ */
+static void _remove_device_opp(struct device_opp *dev_opp)
+{
+	if (!list_empty(&dev_opp->opp_list))
+		return;
+
+	list_del_rcu(&dev_opp->node);
+	call_srcu(&dev_opp->srcu_head.srcu, &dev_opp->rcu_head,
+		  _kfree_device_rcu);
+}
+
+/**
  * _kfree_opp_rcu() - Free OPP RCU handler
  * @head:	RCU head
  */
@@ -481,11 +497,7 @@ static void _opp_remove(struct device_opp *dev_opp,
 	list_del_rcu(&opp->node);
 	call_srcu(&dev_opp->srcu_head.srcu, &opp->rcu_head, _kfree_opp_rcu);
 
-	if (list_empty(&dev_opp->opp_list)) {
-		list_del_rcu(&dev_opp->node);
-		call_srcu(&dev_opp->srcu_head.srcu, &dev_opp->rcu_head,
-			  _kfree_device_rcu);
-	}
+	_remove_device_opp(dev_opp);
 }
 
 /**
-- 
2.4.0

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

* [PATCH V3 05/16] PM / OPP: Allocate dev_opp from _add_device_opp()
  2015-07-29 10:52 ` Viresh Kumar
  (?)
@ 2015-07-29 10:53   ` Viresh Kumar
  -1 siblings, 0 replies; 92+ messages in thread
From: Viresh Kumar @ 2015-07-29 10:53 UTC (permalink / raw)
  To: Rafael Wysocki, sboyd
  Cc: linaro-kernel, linux-pm, rob.herring, arnd.bergmann, nm, broonie,
	mturquette, Sudeep.Holla, viswanath.puttagunta, l.stach,
	thomas.petazzoni, linux-arm-kernel, ta.omasab, kesavan.abhilash,
	khilman, santosh.shilimkar, b.zolnierkie, Viresh Kumar,
	Greg Kroah-Hartman, Len Brown, open list, Pavel Machek

There is no need to complicate _opp_add_dynamic() with allocation of
dev_opp as well. Allocate it from _add_device_opp() instead.

Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>
Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/base/power/opp.c | 50 ++++++++++++++++++++++++++----------------------
 1 file changed, 27 insertions(+), 23 deletions(-)

diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c
index 7895fdd64192..28d70c9f86ed 100644
--- a/drivers/base/power/opp.c
+++ b/drivers/base/power/opp.c
@@ -408,11 +408,11 @@ struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev,
 EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_floor);
 
 /**
- * _add_device_opp() - Allocate a new device OPP table
+ * _add_device_opp() - Find device OPP table or allocate a new one
  * @dev:	device for which we do this operation
  *
- * New device node which uses OPPs - used when multiple devices with OPP tables
- * are maintained.
+ * It tries to find an existing table first, if it couldn't find one, it
+ * allocates a new OPP table and returns that.
  *
  * Return: valid device_opp pointer if success, else NULL.
  */
@@ -420,6 +420,11 @@ static struct device_opp *_add_device_opp(struct device *dev)
 {
 	struct device_opp *dev_opp;
 
+	/* Check for existing list for 'dev' first */
+	dev_opp = _find_device_opp(dev);
+	if (!IS_ERR(dev_opp))
+		return dev_opp;
+
 	/*
 	 * Allocate a new device OPP table. In the infrequent case where a new
 	 * device is needed to be added, we pay this penalty.
@@ -575,7 +580,7 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_remove);
 static int _opp_add_dynamic(struct device *dev, unsigned long freq,
 			    long u_volt, bool dynamic)
 {
-	struct device_opp *dev_opp = NULL;
+	struct device_opp *dev_opp;
 	struct dev_pm_opp *opp, *new_opp;
 	struct list_head *head;
 	int ret;
@@ -592,19 +597,11 @@ static int _opp_add_dynamic(struct device *dev, unsigned long freq,
 	new_opp->rate = freq;
 	new_opp->u_volt = u_volt;
 	new_opp->available = true;
-	new_opp->dynamic = dynamic;
-
-	/* Check for existing list for 'dev' */
-	dev_opp = _find_device_opp(dev);
-	if (IS_ERR(dev_opp)) {
-		dev_opp = _add_device_opp(dev);
-		if (!dev_opp) {
-			ret = -ENOMEM;
-			goto free_opp;
-		}
 
-		head = &dev_opp->opp_list;
-		goto list_add;
+	dev_opp = _add_device_opp(dev);
+	if (!dev_opp) {
+		ret = -ENOMEM;
+		goto free_opp;
 	}
 
 	/*
@@ -612,15 +609,22 @@ static int _opp_add_dynamic(struct device *dev, unsigned long freq,
 	 * and discard if already present
 	 */
 	head = &dev_opp->opp_list;
+
+	/*
+	 * Need to use &dev_opp->opp_list in the condition part of the 'for'
+	 * loop, don't replace it with head otherwise it will become an infinite
+	 * loop.
+	 */
 	list_for_each_entry_rcu(opp, &dev_opp->opp_list, node) {
-		if (new_opp->rate <= opp->rate)
-			break;
-		else
+		if (new_opp->rate > opp->rate) {
 			head = &opp->node;
-	}
+			continue;
+		}
+
+		if (new_opp->rate < opp->rate)
+			break;
 
-	/* Duplicate OPPs ? */
-	if (new_opp->rate == opp->rate) {
+		/* Duplicate OPPs */
 		ret = opp->available && new_opp->u_volt == opp->u_volt ?
 			0 : -EEXIST;
 
@@ -630,7 +634,7 @@ static int _opp_add_dynamic(struct device *dev, unsigned long freq,
 		goto free_opp;
 	}
 
-list_add:
+	new_opp->dynamic = dynamic;
 	new_opp->dev_opp = dev_opp;
 	list_add_rcu(&new_opp->node, head);
 	mutex_unlock(&dev_opp_list_lock);
-- 
2.4.0


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

* [PATCH V3 05/16] PM / OPP: Allocate dev_opp from _add_device_opp()
@ 2015-07-29 10:53   ` Viresh Kumar
  0 siblings, 0 replies; 92+ messages in thread
From: Viresh Kumar @ 2015-07-29 10:53 UTC (permalink / raw)
  To: Rafael Wysocki, sboyd
  Cc: nm, ta.omasab, Viresh Kumar, mturquette, khilman, Pavel Machek,
	rob.herring, kesavan.abhilash, b.zolnierkie, arnd.bergmann,
	Len Brown, linaro-kernel, linux-pm, santosh.shilimkar, broonie,
	linux-arm-kernel, thomas.petazzoni, viswanath.puttagunta,
	Greg Kroah-Hartman, open list, Sudeep.Holla, l.stach

There is no need to complicate _opp_add_dynamic() with allocation of
dev_opp as well. Allocate it from _add_device_opp() instead.

Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>
Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/base/power/opp.c | 50 ++++++++++++++++++++++++++----------------------
 1 file changed, 27 insertions(+), 23 deletions(-)

diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c
index 7895fdd64192..28d70c9f86ed 100644
--- a/drivers/base/power/opp.c
+++ b/drivers/base/power/opp.c
@@ -408,11 +408,11 @@ struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev,
 EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_floor);
 
 /**
- * _add_device_opp() - Allocate a new device OPP table
+ * _add_device_opp() - Find device OPP table or allocate a new one
  * @dev:	device for which we do this operation
  *
- * New device node which uses OPPs - used when multiple devices with OPP tables
- * are maintained.
+ * It tries to find an existing table first, if it couldn't find one, it
+ * allocates a new OPP table and returns that.
  *
  * Return: valid device_opp pointer if success, else NULL.
  */
@@ -420,6 +420,11 @@ static struct device_opp *_add_device_opp(struct device *dev)
 {
 	struct device_opp *dev_opp;
 
+	/* Check for existing list for 'dev' first */
+	dev_opp = _find_device_opp(dev);
+	if (!IS_ERR(dev_opp))
+		return dev_opp;
+
 	/*
 	 * Allocate a new device OPP table. In the infrequent case where a new
 	 * device is needed to be added, we pay this penalty.
@@ -575,7 +580,7 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_remove);
 static int _opp_add_dynamic(struct device *dev, unsigned long freq,
 			    long u_volt, bool dynamic)
 {
-	struct device_opp *dev_opp = NULL;
+	struct device_opp *dev_opp;
 	struct dev_pm_opp *opp, *new_opp;
 	struct list_head *head;
 	int ret;
@@ -592,19 +597,11 @@ static int _opp_add_dynamic(struct device *dev, unsigned long freq,
 	new_opp->rate = freq;
 	new_opp->u_volt = u_volt;
 	new_opp->available = true;
-	new_opp->dynamic = dynamic;
-
-	/* Check for existing list for 'dev' */
-	dev_opp = _find_device_opp(dev);
-	if (IS_ERR(dev_opp)) {
-		dev_opp = _add_device_opp(dev);
-		if (!dev_opp) {
-			ret = -ENOMEM;
-			goto free_opp;
-		}
 
-		head = &dev_opp->opp_list;
-		goto list_add;
+	dev_opp = _add_device_opp(dev);
+	if (!dev_opp) {
+		ret = -ENOMEM;
+		goto free_opp;
 	}
 
 	/*
@@ -612,15 +609,22 @@ static int _opp_add_dynamic(struct device *dev, unsigned long freq,
 	 * and discard if already present
 	 */
 	head = &dev_opp->opp_list;
+
+	/*
+	 * Need to use &dev_opp->opp_list in the condition part of the 'for'
+	 * loop, don't replace it with head otherwise it will become an infinite
+	 * loop.
+	 */
 	list_for_each_entry_rcu(opp, &dev_opp->opp_list, node) {
-		if (new_opp->rate <= opp->rate)
-			break;
-		else
+		if (new_opp->rate > opp->rate) {
 			head = &opp->node;
-	}
+			continue;
+		}
+
+		if (new_opp->rate < opp->rate)
+			break;
 
-	/* Duplicate OPPs ? */
-	if (new_opp->rate == opp->rate) {
+		/* Duplicate OPPs */
 		ret = opp->available && new_opp->u_volt == opp->u_volt ?
 			0 : -EEXIST;
 
@@ -630,7 +634,7 @@ static int _opp_add_dynamic(struct device *dev, unsigned long freq,
 		goto free_opp;
 	}
 
-list_add:
+	new_opp->dynamic = dynamic;
 	new_opp->dev_opp = dev_opp;
 	list_add_rcu(&new_opp->node, head);
 	mutex_unlock(&dev_opp_list_lock);
-- 
2.4.0

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

* [PATCH V3 05/16] PM / OPP: Allocate dev_opp from _add_device_opp()
@ 2015-07-29 10:53   ` Viresh Kumar
  0 siblings, 0 replies; 92+ messages in thread
From: Viresh Kumar @ 2015-07-29 10:53 UTC (permalink / raw)
  To: linux-arm-kernel

There is no need to complicate _opp_add_dynamic() with allocation of
dev_opp as well. Allocate it from _add_device_opp() instead.

Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>
Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/base/power/opp.c | 50 ++++++++++++++++++++++++++----------------------
 1 file changed, 27 insertions(+), 23 deletions(-)

diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c
index 7895fdd64192..28d70c9f86ed 100644
--- a/drivers/base/power/opp.c
+++ b/drivers/base/power/opp.c
@@ -408,11 +408,11 @@ struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev,
 EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_floor);
 
 /**
- * _add_device_opp() - Allocate a new device OPP table
+ * _add_device_opp() - Find device OPP table or allocate a new one
  * @dev:	device for which we do this operation
  *
- * New device node which uses OPPs - used when multiple devices with OPP tables
- * are maintained.
+ * It tries to find an existing table first, if it couldn't find one, it
+ * allocates a new OPP table and returns that.
  *
  * Return: valid device_opp pointer if success, else NULL.
  */
@@ -420,6 +420,11 @@ static struct device_opp *_add_device_opp(struct device *dev)
 {
 	struct device_opp *dev_opp;
 
+	/* Check for existing list for 'dev' first */
+	dev_opp = _find_device_opp(dev);
+	if (!IS_ERR(dev_opp))
+		return dev_opp;
+
 	/*
 	 * Allocate a new device OPP table. In the infrequent case where a new
 	 * device is needed to be added, we pay this penalty.
@@ -575,7 +580,7 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_remove);
 static int _opp_add_dynamic(struct device *dev, unsigned long freq,
 			    long u_volt, bool dynamic)
 {
-	struct device_opp *dev_opp = NULL;
+	struct device_opp *dev_opp;
 	struct dev_pm_opp *opp, *new_opp;
 	struct list_head *head;
 	int ret;
@@ -592,19 +597,11 @@ static int _opp_add_dynamic(struct device *dev, unsigned long freq,
 	new_opp->rate = freq;
 	new_opp->u_volt = u_volt;
 	new_opp->available = true;
-	new_opp->dynamic = dynamic;
-
-	/* Check for existing list for 'dev' */
-	dev_opp = _find_device_opp(dev);
-	if (IS_ERR(dev_opp)) {
-		dev_opp = _add_device_opp(dev);
-		if (!dev_opp) {
-			ret = -ENOMEM;
-			goto free_opp;
-		}
 
-		head = &dev_opp->opp_list;
-		goto list_add;
+	dev_opp = _add_device_opp(dev);
+	if (!dev_opp) {
+		ret = -ENOMEM;
+		goto free_opp;
 	}
 
 	/*
@@ -612,15 +609,22 @@ static int _opp_add_dynamic(struct device *dev, unsigned long freq,
 	 * and discard if already present
 	 */
 	head = &dev_opp->opp_list;
+
+	/*
+	 * Need to use &dev_opp->opp_list in the condition part of the 'for'
+	 * loop, don't replace it with head otherwise it will become an infinite
+	 * loop.
+	 */
 	list_for_each_entry_rcu(opp, &dev_opp->opp_list, node) {
-		if (new_opp->rate <= opp->rate)
-			break;
-		else
+		if (new_opp->rate > opp->rate) {
 			head = &opp->node;
-	}
+			continue;
+		}
+
+		if (new_opp->rate < opp->rate)
+			break;
 
-	/* Duplicate OPPs ? */
-	if (new_opp->rate == opp->rate) {
+		/* Duplicate OPPs */
 		ret = opp->available && new_opp->u_volt == opp->u_volt ?
 			0 : -EEXIST;
 
@@ -630,7 +634,7 @@ static int _opp_add_dynamic(struct device *dev, unsigned long freq,
 		goto free_opp;
 	}
 
-list_add:
+	new_opp->dynamic = dynamic;
 	new_opp->dev_opp = dev_opp;
 	list_add_rcu(&new_opp->node, head);
 	mutex_unlock(&dev_opp_list_lock);
-- 
2.4.0

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

* [PATCH V3 06/16] PM / OPP: Break _opp_add_dynamic() into smaller functions
  2015-07-29 10:52 ` Viresh Kumar
  (?)
@ 2015-07-29 10:53   ` Viresh Kumar
  -1 siblings, 0 replies; 92+ messages in thread
From: Viresh Kumar @ 2015-07-29 10:53 UTC (permalink / raw)
  To: Rafael Wysocki, sboyd
  Cc: linaro-kernel, linux-pm, rob.herring, arnd.bergmann, nm, broonie,
	mturquette, Sudeep.Holla, viswanath.puttagunta, l.stach,
	thomas.petazzoni, linux-arm-kernel, ta.omasab, kesavan.abhilash,
	khilman, santosh.shilimkar, b.zolnierkie, Viresh Kumar,
	Greg Kroah-Hartman, Len Brown, open list, Pavel Machek

Later commits would add support for new OPP bindings and this would be
required then. So, lets do it in a separate patch to make it easily
reviewable.

Another change worth noticing is INIT_LIST_HEAD(&opp->node). We weren't
doing it earlier as we never tried to delete a list node before it is
added to list. But this wouldn't be the case anymore. We might try to
delete a node (just to reuse the same code paths), without it being
getting added to the list.

Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/base/power/opp.c | 125 ++++++++++++++++++++++++++++-------------------
 1 file changed, 76 insertions(+), 49 deletions(-)

diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c
index 28d70c9f86ed..0d8dbf21c299 100644
--- a/drivers/base/power/opp.c
+++ b/drivers/base/power/opp.c
@@ -484,6 +484,7 @@ static void _kfree_opp_rcu(struct rcu_head *head)
  * _opp_remove()  - Remove an OPP from a table definition
  * @dev_opp:	points back to the device_opp struct this opp belongs to
  * @opp:	pointer to the OPP to remove
+ * @notify:	OPP_EVENT_REMOVE notification should be sent or not
  *
  * This function removes an opp definition from the opp list.
  *
@@ -492,13 +493,14 @@ static void _kfree_opp_rcu(struct rcu_head *head)
  * strategy.
  */
 static void _opp_remove(struct device_opp *dev_opp,
-			struct dev_pm_opp *opp)
+			struct dev_pm_opp *opp, bool notify)
 {
 	/*
 	 * Notify the changes in the availability of the operable
 	 * frequency/voltage list.
 	 */
-	srcu_notifier_call_chain(&dev_opp->srcu_head, OPP_EVENT_REMOVE, opp);
+	if (notify)
+		srcu_notifier_call_chain(&dev_opp->srcu_head, OPP_EVENT_REMOVE, opp);
 	list_del_rcu(&opp->node);
 	call_srcu(&dev_opp->srcu_head.srcu, &opp->rcu_head, _kfree_opp_rcu);
 
@@ -544,12 +546,70 @@ void dev_pm_opp_remove(struct device *dev, unsigned long freq)
 		goto unlock;
 	}
 
-	_opp_remove(dev_opp, opp);
+	_opp_remove(dev_opp, opp, true);
 unlock:
 	mutex_unlock(&dev_opp_list_lock);
 }
 EXPORT_SYMBOL_GPL(dev_pm_opp_remove);
 
+static struct dev_pm_opp *_allocate_opp(struct device *dev,
+					struct device_opp **dev_opp)
+{
+	struct dev_pm_opp *opp;
+
+	/* allocate new OPP node */
+	opp = kzalloc(sizeof(*opp), GFP_KERNEL);
+	if (!opp)
+		return NULL;
+
+	INIT_LIST_HEAD(&opp->node);
+
+	*dev_opp = _add_device_opp(dev);
+	if (!*dev_opp) {
+		kfree(opp);
+		return NULL;
+	}
+
+	return opp;
+}
+
+static int _opp_add(struct dev_pm_opp *new_opp, struct device_opp *dev_opp)
+{
+	struct dev_pm_opp *opp;
+	struct list_head *head = &dev_opp->opp_list;
+
+	/*
+	 * Insert new OPP in order of increasing frequency and discard if
+	 * already present.
+	 *
+	 * Need to use &dev_opp->opp_list in the condition part of the 'for'
+	 * loop, don't replace it with head otherwise it will become an infinite
+	 * loop.
+	 */
+	list_for_each_entry_rcu(opp, &dev_opp->opp_list, node) {
+		if (new_opp->rate > opp->rate) {
+			head = &opp->node;
+			continue;
+		}
+
+		if (new_opp->rate < opp->rate)
+			break;
+
+		/* Duplicate OPPs */
+		dev_warn(dev_opp->dev, "%s: duplicate OPPs detected. Existing: freq: %lu, volt: %lu, enabled: %d. New: freq: %lu, volt: %lu, enabled: %d\n",
+			 __func__, opp->rate, opp->u_volt, opp->available,
+			 new_opp->rate, new_opp->u_volt, new_opp->available);
+
+		return opp->available && new_opp->u_volt == opp->u_volt ?
+			0 : -EEXIST;
+	}
+
+	new_opp->dev_opp = dev_opp;
+	list_add_rcu(&new_opp->node, head);
+
+	return 0;
+}
+
 /**
  * _opp_add_dynamic() - Allocate a dynamic OPP.
  * @dev:	device for which we do this operation
@@ -581,62 +641,28 @@ static int _opp_add_dynamic(struct device *dev, unsigned long freq,
 			    long u_volt, bool dynamic)
 {
 	struct device_opp *dev_opp;
-	struct dev_pm_opp *opp, *new_opp;
-	struct list_head *head;
+	struct dev_pm_opp *new_opp;
 	int ret;
 
-	/* allocate new OPP node */
-	new_opp = kzalloc(sizeof(*new_opp), GFP_KERNEL);
-	if (!new_opp)
-		return -ENOMEM;
-
 	/* Hold our list modification lock here */
 	mutex_lock(&dev_opp_list_lock);
 
+	new_opp = _allocate_opp(dev, &dev_opp);
+	if (!new_opp) {
+		ret = -ENOMEM;
+		goto unlock;
+	}
+
 	/* populate the opp table */
 	new_opp->rate = freq;
 	new_opp->u_volt = u_volt;
 	new_opp->available = true;
+	new_opp->dynamic = dynamic;
 
-	dev_opp = _add_device_opp(dev);
-	if (!dev_opp) {
-		ret = -ENOMEM;
-		goto free_opp;
-	}
-
-	/*
-	 * Insert new OPP in order of increasing frequency
-	 * and discard if already present
-	 */
-	head = &dev_opp->opp_list;
-
-	/*
-	 * Need to use &dev_opp->opp_list in the condition part of the 'for'
-	 * loop, don't replace it with head otherwise it will become an infinite
-	 * loop.
-	 */
-	list_for_each_entry_rcu(opp, &dev_opp->opp_list, node) {
-		if (new_opp->rate > opp->rate) {
-			head = &opp->node;
-			continue;
-		}
-
-		if (new_opp->rate < opp->rate)
-			break;
-
-		/* Duplicate OPPs */
-		ret = opp->available && new_opp->u_volt == opp->u_volt ?
-			0 : -EEXIST;
-
-		dev_warn(dev, "%s: duplicate OPPs detected. Existing: freq: %lu, volt: %lu, enabled: %d. New: freq: %lu, volt: %lu, enabled: %d\n",
-			 __func__, opp->rate, opp->u_volt, opp->available,
-			 new_opp->rate, new_opp->u_volt, new_opp->available);
+	ret = _opp_add(new_opp, dev_opp);
+	if (ret)
 		goto free_opp;
-	}
 
-	new_opp->dynamic = dynamic;
-	new_opp->dev_opp = dev_opp;
-	list_add_rcu(&new_opp->node, head);
 	mutex_unlock(&dev_opp_list_lock);
 
 	/*
@@ -647,8 +673,9 @@ static int _opp_add_dynamic(struct device *dev, unsigned long freq,
 	return 0;
 
 free_opp:
+	_opp_remove(dev_opp, new_opp, false);
+unlock:
 	mutex_unlock(&dev_opp_list_lock);
-	kfree(new_opp);
 	return ret;
 }
 
@@ -876,7 +903,7 @@ void of_free_opp_table(struct device *dev)
 	/* Free static OPPs */
 	list_for_each_entry_safe(opp, tmp, &dev_opp->opp_list, node) {
 		if (!opp->dynamic)
-			_opp_remove(dev_opp, opp);
+			_opp_remove(dev_opp, opp, true);
 	}
 
 	mutex_unlock(&dev_opp_list_lock);
-- 
2.4.0


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

* [PATCH V3 06/16] PM / OPP: Break _opp_add_dynamic() into smaller functions
@ 2015-07-29 10:53   ` Viresh Kumar
  0 siblings, 0 replies; 92+ messages in thread
From: Viresh Kumar @ 2015-07-29 10:53 UTC (permalink / raw)
  To: Rafael Wysocki, sboyd
  Cc: nm, ta.omasab, Viresh Kumar, mturquette, khilman, Pavel Machek,
	rob.herring, kesavan.abhilash, b.zolnierkie, arnd.bergmann,
	Len Brown, linaro-kernel, linux-pm, santosh.shilimkar, broonie,
	linux-arm-kernel, thomas.petazzoni, viswanath.puttagunta,
	Greg Kroah-Hartman, open list, Sudeep.Holla, l.stach

Later commits would add support for new OPP bindings and this would be
required then. So, lets do it in a separate patch to make it easily
reviewable.

Another change worth noticing is INIT_LIST_HEAD(&opp->node). We weren't
doing it earlier as we never tried to delete a list node before it is
added to list. But this wouldn't be the case anymore. We might try to
delete a node (just to reuse the same code paths), without it being
getting added to the list.

Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/base/power/opp.c | 125 ++++++++++++++++++++++++++++-------------------
 1 file changed, 76 insertions(+), 49 deletions(-)

diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c
index 28d70c9f86ed..0d8dbf21c299 100644
--- a/drivers/base/power/opp.c
+++ b/drivers/base/power/opp.c
@@ -484,6 +484,7 @@ static void _kfree_opp_rcu(struct rcu_head *head)
  * _opp_remove()  - Remove an OPP from a table definition
  * @dev_opp:	points back to the device_opp struct this opp belongs to
  * @opp:	pointer to the OPP to remove
+ * @notify:	OPP_EVENT_REMOVE notification should be sent or not
  *
  * This function removes an opp definition from the opp list.
  *
@@ -492,13 +493,14 @@ static void _kfree_opp_rcu(struct rcu_head *head)
  * strategy.
  */
 static void _opp_remove(struct device_opp *dev_opp,
-			struct dev_pm_opp *opp)
+			struct dev_pm_opp *opp, bool notify)
 {
 	/*
 	 * Notify the changes in the availability of the operable
 	 * frequency/voltage list.
 	 */
-	srcu_notifier_call_chain(&dev_opp->srcu_head, OPP_EVENT_REMOVE, opp);
+	if (notify)
+		srcu_notifier_call_chain(&dev_opp->srcu_head, OPP_EVENT_REMOVE, opp);
 	list_del_rcu(&opp->node);
 	call_srcu(&dev_opp->srcu_head.srcu, &opp->rcu_head, _kfree_opp_rcu);
 
@@ -544,12 +546,70 @@ void dev_pm_opp_remove(struct device *dev, unsigned long freq)
 		goto unlock;
 	}
 
-	_opp_remove(dev_opp, opp);
+	_opp_remove(dev_opp, opp, true);
 unlock:
 	mutex_unlock(&dev_opp_list_lock);
 }
 EXPORT_SYMBOL_GPL(dev_pm_opp_remove);
 
+static struct dev_pm_opp *_allocate_opp(struct device *dev,
+					struct device_opp **dev_opp)
+{
+	struct dev_pm_opp *opp;
+
+	/* allocate new OPP node */
+	opp = kzalloc(sizeof(*opp), GFP_KERNEL);
+	if (!opp)
+		return NULL;
+
+	INIT_LIST_HEAD(&opp->node);
+
+	*dev_opp = _add_device_opp(dev);
+	if (!*dev_opp) {
+		kfree(opp);
+		return NULL;
+	}
+
+	return opp;
+}
+
+static int _opp_add(struct dev_pm_opp *new_opp, struct device_opp *dev_opp)
+{
+	struct dev_pm_opp *opp;
+	struct list_head *head = &dev_opp->opp_list;
+
+	/*
+	 * Insert new OPP in order of increasing frequency and discard if
+	 * already present.
+	 *
+	 * Need to use &dev_opp->opp_list in the condition part of the 'for'
+	 * loop, don't replace it with head otherwise it will become an infinite
+	 * loop.
+	 */
+	list_for_each_entry_rcu(opp, &dev_opp->opp_list, node) {
+		if (new_opp->rate > opp->rate) {
+			head = &opp->node;
+			continue;
+		}
+
+		if (new_opp->rate < opp->rate)
+			break;
+
+		/* Duplicate OPPs */
+		dev_warn(dev_opp->dev, "%s: duplicate OPPs detected. Existing: freq: %lu, volt: %lu, enabled: %d. New: freq: %lu, volt: %lu, enabled: %d\n",
+			 __func__, opp->rate, opp->u_volt, opp->available,
+			 new_opp->rate, new_opp->u_volt, new_opp->available);
+
+		return opp->available && new_opp->u_volt == opp->u_volt ?
+			0 : -EEXIST;
+	}
+
+	new_opp->dev_opp = dev_opp;
+	list_add_rcu(&new_opp->node, head);
+
+	return 0;
+}
+
 /**
  * _opp_add_dynamic() - Allocate a dynamic OPP.
  * @dev:	device for which we do this operation
@@ -581,62 +641,28 @@ static int _opp_add_dynamic(struct device *dev, unsigned long freq,
 			    long u_volt, bool dynamic)
 {
 	struct device_opp *dev_opp;
-	struct dev_pm_opp *opp, *new_opp;
-	struct list_head *head;
+	struct dev_pm_opp *new_opp;
 	int ret;
 
-	/* allocate new OPP node */
-	new_opp = kzalloc(sizeof(*new_opp), GFP_KERNEL);
-	if (!new_opp)
-		return -ENOMEM;
-
 	/* Hold our list modification lock here */
 	mutex_lock(&dev_opp_list_lock);
 
+	new_opp = _allocate_opp(dev, &dev_opp);
+	if (!new_opp) {
+		ret = -ENOMEM;
+		goto unlock;
+	}
+
 	/* populate the opp table */
 	new_opp->rate = freq;
 	new_opp->u_volt = u_volt;
 	new_opp->available = true;
+	new_opp->dynamic = dynamic;
 
-	dev_opp = _add_device_opp(dev);
-	if (!dev_opp) {
-		ret = -ENOMEM;
-		goto free_opp;
-	}
-
-	/*
-	 * Insert new OPP in order of increasing frequency
-	 * and discard if already present
-	 */
-	head = &dev_opp->opp_list;
-
-	/*
-	 * Need to use &dev_opp->opp_list in the condition part of the 'for'
-	 * loop, don't replace it with head otherwise it will become an infinite
-	 * loop.
-	 */
-	list_for_each_entry_rcu(opp, &dev_opp->opp_list, node) {
-		if (new_opp->rate > opp->rate) {
-			head = &opp->node;
-			continue;
-		}
-
-		if (new_opp->rate < opp->rate)
-			break;
-
-		/* Duplicate OPPs */
-		ret = opp->available && new_opp->u_volt == opp->u_volt ?
-			0 : -EEXIST;
-
-		dev_warn(dev, "%s: duplicate OPPs detected. Existing: freq: %lu, volt: %lu, enabled: %d. New: freq: %lu, volt: %lu, enabled: %d\n",
-			 __func__, opp->rate, opp->u_volt, opp->available,
-			 new_opp->rate, new_opp->u_volt, new_opp->available);
+	ret = _opp_add(new_opp, dev_opp);
+	if (ret)
 		goto free_opp;
-	}
 
-	new_opp->dynamic = dynamic;
-	new_opp->dev_opp = dev_opp;
-	list_add_rcu(&new_opp->node, head);
 	mutex_unlock(&dev_opp_list_lock);
 
 	/*
@@ -647,8 +673,9 @@ static int _opp_add_dynamic(struct device *dev, unsigned long freq,
 	return 0;
 
 free_opp:
+	_opp_remove(dev_opp, new_opp, false);
+unlock:
 	mutex_unlock(&dev_opp_list_lock);
-	kfree(new_opp);
 	return ret;
 }
 
@@ -876,7 +903,7 @@ void of_free_opp_table(struct device *dev)
 	/* Free static OPPs */
 	list_for_each_entry_safe(opp, tmp, &dev_opp->opp_list, node) {
 		if (!opp->dynamic)
-			_opp_remove(dev_opp, opp);
+			_opp_remove(dev_opp, opp, true);
 	}
 
 	mutex_unlock(&dev_opp_list_lock);
-- 
2.4.0

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

* [PATCH V3 06/16] PM / OPP: Break _opp_add_dynamic() into smaller functions
@ 2015-07-29 10:53   ` Viresh Kumar
  0 siblings, 0 replies; 92+ messages in thread
From: Viresh Kumar @ 2015-07-29 10:53 UTC (permalink / raw)
  To: linux-arm-kernel

Later commits would add support for new OPP bindings and this would be
required then. So, lets do it in a separate patch to make it easily
reviewable.

Another change worth noticing is INIT_LIST_HEAD(&opp->node). We weren't
doing it earlier as we never tried to delete a list node before it is
added to list. But this wouldn't be the case anymore. We might try to
delete a node (just to reuse the same code paths), without it being
getting added to the list.

Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/base/power/opp.c | 125 ++++++++++++++++++++++++++++-------------------
 1 file changed, 76 insertions(+), 49 deletions(-)

diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c
index 28d70c9f86ed..0d8dbf21c299 100644
--- a/drivers/base/power/opp.c
+++ b/drivers/base/power/opp.c
@@ -484,6 +484,7 @@ static void _kfree_opp_rcu(struct rcu_head *head)
  * _opp_remove()  - Remove an OPP from a table definition
  * @dev_opp:	points back to the device_opp struct this opp belongs to
  * @opp:	pointer to the OPP to remove
+ * @notify:	OPP_EVENT_REMOVE notification should be sent or not
  *
  * This function removes an opp definition from the opp list.
  *
@@ -492,13 +493,14 @@ static void _kfree_opp_rcu(struct rcu_head *head)
  * strategy.
  */
 static void _opp_remove(struct device_opp *dev_opp,
-			struct dev_pm_opp *opp)
+			struct dev_pm_opp *opp, bool notify)
 {
 	/*
 	 * Notify the changes in the availability of the operable
 	 * frequency/voltage list.
 	 */
-	srcu_notifier_call_chain(&dev_opp->srcu_head, OPP_EVENT_REMOVE, opp);
+	if (notify)
+		srcu_notifier_call_chain(&dev_opp->srcu_head, OPP_EVENT_REMOVE, opp);
 	list_del_rcu(&opp->node);
 	call_srcu(&dev_opp->srcu_head.srcu, &opp->rcu_head, _kfree_opp_rcu);
 
@@ -544,12 +546,70 @@ void dev_pm_opp_remove(struct device *dev, unsigned long freq)
 		goto unlock;
 	}
 
-	_opp_remove(dev_opp, opp);
+	_opp_remove(dev_opp, opp, true);
 unlock:
 	mutex_unlock(&dev_opp_list_lock);
 }
 EXPORT_SYMBOL_GPL(dev_pm_opp_remove);
 
+static struct dev_pm_opp *_allocate_opp(struct device *dev,
+					struct device_opp **dev_opp)
+{
+	struct dev_pm_opp *opp;
+
+	/* allocate new OPP node */
+	opp = kzalloc(sizeof(*opp), GFP_KERNEL);
+	if (!opp)
+		return NULL;
+
+	INIT_LIST_HEAD(&opp->node);
+
+	*dev_opp = _add_device_opp(dev);
+	if (!*dev_opp) {
+		kfree(opp);
+		return NULL;
+	}
+
+	return opp;
+}
+
+static int _opp_add(struct dev_pm_opp *new_opp, struct device_opp *dev_opp)
+{
+	struct dev_pm_opp *opp;
+	struct list_head *head = &dev_opp->opp_list;
+
+	/*
+	 * Insert new OPP in order of increasing frequency and discard if
+	 * already present.
+	 *
+	 * Need to use &dev_opp->opp_list in the condition part of the 'for'
+	 * loop, don't replace it with head otherwise it will become an infinite
+	 * loop.
+	 */
+	list_for_each_entry_rcu(opp, &dev_opp->opp_list, node) {
+		if (new_opp->rate > opp->rate) {
+			head = &opp->node;
+			continue;
+		}
+
+		if (new_opp->rate < opp->rate)
+			break;
+
+		/* Duplicate OPPs */
+		dev_warn(dev_opp->dev, "%s: duplicate OPPs detected. Existing: freq: %lu, volt: %lu, enabled: %d. New: freq: %lu, volt: %lu, enabled: %d\n",
+			 __func__, opp->rate, opp->u_volt, opp->available,
+			 new_opp->rate, new_opp->u_volt, new_opp->available);
+
+		return opp->available && new_opp->u_volt == opp->u_volt ?
+			0 : -EEXIST;
+	}
+
+	new_opp->dev_opp = dev_opp;
+	list_add_rcu(&new_opp->node, head);
+
+	return 0;
+}
+
 /**
  * _opp_add_dynamic() - Allocate a dynamic OPP.
  * @dev:	device for which we do this operation
@@ -581,62 +641,28 @@ static int _opp_add_dynamic(struct device *dev, unsigned long freq,
 			    long u_volt, bool dynamic)
 {
 	struct device_opp *dev_opp;
-	struct dev_pm_opp *opp, *new_opp;
-	struct list_head *head;
+	struct dev_pm_opp *new_opp;
 	int ret;
 
-	/* allocate new OPP node */
-	new_opp = kzalloc(sizeof(*new_opp), GFP_KERNEL);
-	if (!new_opp)
-		return -ENOMEM;
-
 	/* Hold our list modification lock here */
 	mutex_lock(&dev_opp_list_lock);
 
+	new_opp = _allocate_opp(dev, &dev_opp);
+	if (!new_opp) {
+		ret = -ENOMEM;
+		goto unlock;
+	}
+
 	/* populate the opp table */
 	new_opp->rate = freq;
 	new_opp->u_volt = u_volt;
 	new_opp->available = true;
+	new_opp->dynamic = dynamic;
 
-	dev_opp = _add_device_opp(dev);
-	if (!dev_opp) {
-		ret = -ENOMEM;
-		goto free_opp;
-	}
-
-	/*
-	 * Insert new OPP in order of increasing frequency
-	 * and discard if already present
-	 */
-	head = &dev_opp->opp_list;
-
-	/*
-	 * Need to use &dev_opp->opp_list in the condition part of the 'for'
-	 * loop, don't replace it with head otherwise it will become an infinite
-	 * loop.
-	 */
-	list_for_each_entry_rcu(opp, &dev_opp->opp_list, node) {
-		if (new_opp->rate > opp->rate) {
-			head = &opp->node;
-			continue;
-		}
-
-		if (new_opp->rate < opp->rate)
-			break;
-
-		/* Duplicate OPPs */
-		ret = opp->available && new_opp->u_volt == opp->u_volt ?
-			0 : -EEXIST;
-
-		dev_warn(dev, "%s: duplicate OPPs detected. Existing: freq: %lu, volt: %lu, enabled: %d. New: freq: %lu, volt: %lu, enabled: %d\n",
-			 __func__, opp->rate, opp->u_volt, opp->available,
-			 new_opp->rate, new_opp->u_volt, new_opp->available);
+	ret = _opp_add(new_opp, dev_opp);
+	if (ret)
 		goto free_opp;
-	}
 
-	new_opp->dynamic = dynamic;
-	new_opp->dev_opp = dev_opp;
-	list_add_rcu(&new_opp->node, head);
 	mutex_unlock(&dev_opp_list_lock);
 
 	/*
@@ -647,8 +673,9 @@ static int _opp_add_dynamic(struct device *dev, unsigned long freq,
 	return 0;
 
 free_opp:
+	_opp_remove(dev_opp, new_opp, false);
+unlock:
 	mutex_unlock(&dev_opp_list_lock);
-	kfree(new_opp);
 	return ret;
 }
 
@@ -876,7 +903,7 @@ void of_free_opp_table(struct device *dev)
 	/* Free static OPPs */
 	list_for_each_entry_safe(opp, tmp, &dev_opp->opp_list, node) {
 		if (!opp->dynamic)
-			_opp_remove(dev_opp, opp);
+			_opp_remove(dev_opp, opp, true);
 	}
 
 	mutex_unlock(&dev_opp_list_lock);
-- 
2.4.0

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

* [PATCH V3 07/16] PM / OPP: Add support to parse "operating-points-v2" bindings
  2015-07-29 10:52 ` Viresh Kumar
  (?)
@ 2015-07-29 10:53   ` Viresh Kumar
  -1 siblings, 0 replies; 92+ messages in thread
From: Viresh Kumar @ 2015-07-29 10:53 UTC (permalink / raw)
  To: Rafael Wysocki, sboyd
  Cc: linaro-kernel, linux-pm, rob.herring, arnd.bergmann, nm, broonie,
	mturquette, Sudeep.Holla, viswanath.puttagunta, l.stach,
	thomas.petazzoni, linux-arm-kernel, ta.omasab, kesavan.abhilash,
	khilman, santosh.shilimkar, b.zolnierkie, Viresh Kumar,
	Greg Kroah-Hartman, Len Brown, open list, Pavel Machek

This adds support in OPP library to parse and create list of OPPs from
operating-points-v2 bindings. It takes care of most of the properties of
new bindings (except shared-opp, which will be handled separately).

For backward compatibility, we keep supporting earlier bindings. We try
to search for the new bindings first, in case they aren't present we
look for the old deprecated ones.

There are few things marked as TODO:
- Support for multiple OPP tables
- Support for multiple regulators

They should be fixed separately.

Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/base/power/opp.c | 257 ++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 233 insertions(+), 24 deletions(-)

diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c
index 0d8dbf21c299..0e0eff4d9299 100644
--- a/drivers/base/power/opp.c
+++ b/drivers/base/power/opp.c
@@ -51,10 +51,15 @@
  *		order.
  * @dynamic:	not-created from static DT entries.
  * @available:	true/false - marks if this OPP as available or not
+ * @turbo:	true if turbo (boost) OPP
  * @rate:	Frequency in hertz
- * @u_volt:	Nominal voltage in microvolts corresponding to this OPP
+ * @u_volt:	Target voltage in microvolts corresponding to this OPP
+ * @u_volt_min:	Minimum voltage in microvolts corresponding to this OPP
+ * @u_volt_max:	Maximum voltage in microvolts corresponding to this OPP
+ * @u_amp:	Maximum current drawn by the device in microamperes
  * @dev_opp:	points back to the device_opp struct this opp belongs to
  * @rcu_head:	RCU callback head used for deferred freeing
+ * @np:		OPP's device node.
  *
  * This structure stores the OPP information for a given device.
  */
@@ -63,11 +68,18 @@ struct dev_pm_opp {
 
 	bool available;
 	bool dynamic;
+	bool turbo;
 	unsigned long rate;
+
 	unsigned long u_volt;
+	unsigned long u_volt_min;
+	unsigned long u_volt_max;
+	unsigned long u_amp;
 
 	struct device_opp *dev_opp;
 	struct rcu_head rcu_head;
+
+	struct device_node *np;
 };
 
 /**
@@ -679,6 +691,125 @@ static int _opp_add_dynamic(struct device *dev, unsigned long freq,
 	return ret;
 }
 
+/* TODO: Support multiple regulators */
+static int opp_get_microvolt(struct dev_pm_opp *opp, struct device *dev)
+{
+	u32 microvolt[3] = {0};
+	int count, ret;
+
+	count = of_property_count_u32_elems(opp->np, "opp-microvolt");
+	if (!count)
+		return 0;
+
+	/* There can be one or three elements here */
+	if (count != 1 && count != 3) {
+		dev_err(dev, "%s: Invalid number of elements in opp-microvolt property (%d)\n",
+			__func__, count);
+		return -EINVAL;
+	}
+
+	ret = of_property_read_u32_array(opp->np, "opp-microvolt", microvolt,
+					 count);
+	if (ret) {
+		dev_err(dev, "%s: error parsing opp-microvolt: %d\n", __func__,
+			ret);
+		return -EINVAL;
+	}
+
+	opp->u_volt = microvolt[0];
+	opp->u_volt_min = microvolt[1];
+	opp->u_volt_max = microvolt[2];
+
+	return 0;
+}
+
+/**
+ * _opp_add_static_v2() - Allocate static OPPs (As per 'v2' DT bindings)
+ * @dev:	device for which we do this operation
+ * @np:		device node
+ *
+ * This function adds an opp definition to the opp list and returns status. The
+ * opp can be controlled using dev_pm_opp_enable/disable functions and may be
+ * removed by dev_pm_opp_remove.
+ *
+ * Locking: The internal device_opp and opp structures are RCU protected.
+ * Hence this function internally uses RCU updater strategy with mutex locks
+ * to keep the integrity of the internal data structures. Callers should ensure
+ * that this function is *NOT* called under RCU protection or in contexts where
+ * mutex cannot be locked.
+ *
+ * Return:
+ * 0		On success OR
+ *		Duplicate OPPs (both freq and volt are same) and opp->available
+ * -EEXIST	Freq are same and volt are different OR
+ *		Duplicate OPPs (both freq and volt are same) and !opp->available
+ * -ENOMEM	Memory allocation failure
+ * -EINVAL	Failed parsing the OPP node
+ */
+static int _opp_add_static_v2(struct device *dev, struct device_node *np)
+{
+	struct device_opp *dev_opp;
+	struct dev_pm_opp *new_opp;
+	u64 rate;
+	int ret;
+
+	/* Hold our list modification lock here */
+	mutex_lock(&dev_opp_list_lock);
+
+	new_opp = _allocate_opp(dev, &dev_opp);
+	if (!new_opp) {
+		ret = -ENOMEM;
+		goto unlock;
+	}
+
+	ret = of_property_read_u64(np, "opp-hz", &rate);
+	if (ret < 0) {
+		dev_err(dev, "%s: opp-hz not found\n", __func__);
+		goto free_opp;
+	}
+
+	/*
+	 * Rate is defined as an unsigned long in clk API, and so casting
+	 * explicitly to its type. Must be fixed once rate is 64 bit
+	 * guaranteed in clk API.
+	 */
+	new_opp->rate = (unsigned long)rate;
+	new_opp->turbo = of_property_read_bool(np, "turbo-mode");
+
+	new_opp->np = np;
+	new_opp->dynamic = false;
+	new_opp->available = true;
+
+	ret = opp_get_microvolt(new_opp, dev);
+	if (ret)
+		goto free_opp;
+
+	of_property_read_u32(np, "opp-microamp", (u32 *)&new_opp->u_amp);
+
+	ret = _opp_add(new_opp, dev_opp);
+	if (ret)
+		goto free_opp;
+
+	mutex_unlock(&dev_opp_list_lock);
+
+	pr_debug("%s: turbo:%d rate:%lu uv:%lu uvmin:%lu uvmax:%lu\n",
+		 __func__, new_opp->turbo, new_opp->rate, new_opp->u_volt,
+		 new_opp->u_volt_min, new_opp->u_volt_max);
+
+	/*
+	 * Notify the changes in the availability of the operable
+	 * frequency/voltage list.
+	 */
+	srcu_notifier_call_chain(&dev_opp->srcu_head, OPP_EVENT_ADD, new_opp);
+	return 0;
+
+free_opp:
+	_opp_remove(dev_opp, new_opp, false);
+unlock:
+	mutex_unlock(&dev_opp_list_lock);
+	return ret;
+}
+
 /**
  * dev_pm_opp_add()  - Add an OPP table from a table definitions
  * @dev:	device for which we do this operation
@@ -910,29 +1041,64 @@ void of_free_opp_table(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(of_free_opp_table);
 
-/**
- * of_init_opp_table() - Initialize opp table from device tree
- * @dev:	device pointer used to lookup device OPPs.
- *
- * Register the initial OPP table with the OPP library for given device.
- *
- * Locking: The internal device_opp and opp structures are RCU protected.
- * Hence this function indirectly uses RCU updater strategy with mutex locks
- * to keep the integrity of the internal data structures. Callers should ensure
- * that this function is *NOT* called under RCU protection or in contexts where
- * mutex cannot be locked.
- *
- * Return:
- * 0		On success OR
- *		Duplicate OPPs (both freq and volt are same) and opp->available
- * -EEXIST	Freq are same and volt are different OR
- *		Duplicate OPPs (both freq and volt are same) and !opp->available
- * -ENOMEM	Memory allocation failure
- * -ENODEV	when 'operating-points' property is not found or is invalid data
- *		in device node.
- * -ENODATA	when empty 'operating-points' property is found
- */
-int of_init_opp_table(struct device *dev)
+/* Returns opp descriptor node from its phandle. Caller must do of_node_put() */
+static struct device_node *
+_of_get_opp_desc_node_from_prop(struct device *dev, const struct property *prop)
+{
+	struct device_node *opp_np;
+
+	opp_np = of_find_node_by_phandle(be32_to_cpup(prop->value));
+	if (!opp_np) {
+		dev_err(dev, "%s: Prop: %s contains invalid opp desc phandle\n",
+			__func__, prop->name);
+		return ERR_PTR(-EINVAL);
+	}
+
+	return opp_np;
+}
+
+/* Initializes OPP tables based on new bindings */
+static int _of_init_opp_table_v2(struct device *dev,
+				 const struct property *prop)
+{
+	struct device_node *opp_np, *np;
+	int ret = 0, count = 0;
+
+	if (!prop->value)
+		return -ENODATA;
+
+	/* Get opp node */
+	opp_np = _of_get_opp_desc_node_from_prop(dev, prop);
+	if (IS_ERR(opp_np))
+		return PTR_ERR(opp_np);
+
+	/* We have opp-list node now, iterate over it and add OPPs */
+	for_each_available_child_of_node(opp_np, np) {
+		count++;
+
+		ret = _opp_add_static_v2(dev, np);
+		if (ret) {
+			dev_err(dev, "%s: Failed to add OPP, %d\n", __func__,
+				ret);
+			break;
+		}
+	}
+
+	/* There should be one of more OPP defined */
+	if (WARN_ON(!count))
+		goto put_opp_np;
+
+	if (ret)
+		of_free_opp_table(dev);
+
+put_opp_np:
+	of_node_put(opp_np);
+
+	return ret;
+}
+
+/* Initializes OPP tables based on old-deprecated bindings */
+static int _of_init_opp_table_v1(struct device *dev)
 {
 	const struct property *prop;
 	const __be32 *val;
@@ -967,5 +1133,48 @@ int of_init_opp_table(struct device *dev)
 
 	return 0;
 }
+
+/**
+ * of_init_opp_table() - Initialize opp table from device tree
+ * @dev:	device pointer used to lookup device OPPs.
+ *
+ * Register the initial OPP table with the OPP library for given device.
+ *
+ * Locking: The internal device_opp and opp structures are RCU protected.
+ * Hence this function indirectly uses RCU updater strategy with mutex locks
+ * to keep the integrity of the internal data structures. Callers should ensure
+ * that this function is *NOT* called under RCU protection or in contexts where
+ * mutex cannot be locked.
+ *
+ * Return:
+ * 0		On success OR
+ *		Duplicate OPPs (both freq and volt are same) and opp->available
+ * -EEXIST	Freq are same and volt are different OR
+ *		Duplicate OPPs (both freq and volt are same) and !opp->available
+ * -ENOMEM	Memory allocation failure
+ * -ENODEV	when 'operating-points' property is not found or is invalid data
+ *		in device node.
+ * -ENODATA	when empty 'operating-points' property is found
+ * -EINVAL	when invalid entries are found in opp-v2 table
+ */
+int of_init_opp_table(struct device *dev)
+{
+	const struct property *prop;
+
+	/*
+	 * OPPs have two version of bindings now. The older one is deprecated,
+	 * try for the new binding first.
+	 */
+	prop = of_find_property(dev->of_node, "operating-points-v2", NULL);
+	if (!prop) {
+		/*
+		 * Try old-deprecated bindings for backward compatibility with
+		 * older dtbs.
+		 */
+		return _of_init_opp_table_v1(dev);
+	}
+
+	return _of_init_opp_table_v2(dev, prop);
+}
 EXPORT_SYMBOL_GPL(of_init_opp_table);
 #endif
-- 
2.4.0


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

* [PATCH V3 07/16] PM / OPP: Add support to parse "operating-points-v2" bindings
@ 2015-07-29 10:53   ` Viresh Kumar
  0 siblings, 0 replies; 92+ messages in thread
From: Viresh Kumar @ 2015-07-29 10:53 UTC (permalink / raw)
  To: Rafael Wysocki, sboyd
  Cc: linaro-kernel, linux-pm, rob.herring, arnd.bergmann, nm, broonie,
	mturquette, Sudeep.Holla, viswanath.puttagunta, l.stach,
	thomas.petazzoni, linux-arm-kernel, ta.omasab, kesavan.abhilash,
	khilman, santosh.shilimkar, b.zolnierkie, Viresh Kumar,
	Greg Kroah-Hartman, Len Brown, open list, Pavel Machek

This adds support in OPP library to parse and create list of OPPs from
operating-points-v2 bindings. It takes care of most of the properties of
new bindings (except shared-opp, which will be handled separately).

For backward compatibility, we keep supporting earlier bindings. We try
to search for the new bindings first, in case they aren't present we
look for the old deprecated ones.

There are few things marked as TODO:
- Support for multiple OPP tables
- Support for multiple regulators

They should be fixed separately.

Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/base/power/opp.c | 257 ++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 233 insertions(+), 24 deletions(-)

diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c
index 0d8dbf21c299..0e0eff4d9299 100644
--- a/drivers/base/power/opp.c
+++ b/drivers/base/power/opp.c
@@ -51,10 +51,15 @@
  *		order.
  * @dynamic:	not-created from static DT entries.
  * @available:	true/false - marks if this OPP as available or not
+ * @turbo:	true if turbo (boost) OPP
  * @rate:	Frequency in hertz
- * @u_volt:	Nominal voltage in microvolts corresponding to this OPP
+ * @u_volt:	Target voltage in microvolts corresponding to this OPP
+ * @u_volt_min:	Minimum voltage in microvolts corresponding to this OPP
+ * @u_volt_max:	Maximum voltage in microvolts corresponding to this OPP
+ * @u_amp:	Maximum current drawn by the device in microamperes
  * @dev_opp:	points back to the device_opp struct this opp belongs to
  * @rcu_head:	RCU callback head used for deferred freeing
+ * @np:		OPP's device node.
  *
  * This structure stores the OPP information for a given device.
  */
@@ -63,11 +68,18 @@ struct dev_pm_opp {
 
 	bool available;
 	bool dynamic;
+	bool turbo;
 	unsigned long rate;
+
 	unsigned long u_volt;
+	unsigned long u_volt_min;
+	unsigned long u_volt_max;
+	unsigned long u_amp;
 
 	struct device_opp *dev_opp;
 	struct rcu_head rcu_head;
+
+	struct device_node *np;
 };
 
 /**
@@ -679,6 +691,125 @@ static int _opp_add_dynamic(struct device *dev, unsigned long freq,
 	return ret;
 }
 
+/* TODO: Support multiple regulators */
+static int opp_get_microvolt(struct dev_pm_opp *opp, struct device *dev)
+{
+	u32 microvolt[3] = {0};
+	int count, ret;
+
+	count = of_property_count_u32_elems(opp->np, "opp-microvolt");
+	if (!count)
+		return 0;
+
+	/* There can be one or three elements here */
+	if (count != 1 && count != 3) {
+		dev_err(dev, "%s: Invalid number of elements in opp-microvolt property (%d)\n",
+			__func__, count);
+		return -EINVAL;
+	}
+
+	ret = of_property_read_u32_array(opp->np, "opp-microvolt", microvolt,
+					 count);
+	if (ret) {
+		dev_err(dev, "%s: error parsing opp-microvolt: %d\n", __func__,
+			ret);
+		return -EINVAL;
+	}
+
+	opp->u_volt = microvolt[0];
+	opp->u_volt_min = microvolt[1];
+	opp->u_volt_max = microvolt[2];
+
+	return 0;
+}
+
+/**
+ * _opp_add_static_v2() - Allocate static OPPs (As per 'v2' DT bindings)
+ * @dev:	device for which we do this operation
+ * @np:		device node
+ *
+ * This function adds an opp definition to the opp list and returns status. The
+ * opp can be controlled using dev_pm_opp_enable/disable functions and may be
+ * removed by dev_pm_opp_remove.
+ *
+ * Locking: The internal device_opp and opp structures are RCU protected.
+ * Hence this function internally uses RCU updater strategy with mutex locks
+ * to keep the integrity of the internal data structures. Callers should ensure
+ * that this function is *NOT* called under RCU protection or in contexts where
+ * mutex cannot be locked.
+ *
+ * Return:
+ * 0		On success OR
+ *		Duplicate OPPs (both freq and volt are same) and opp->available
+ * -EEXIST	Freq are same and volt are different OR
+ *		Duplicate OPPs (both freq and volt are same) and !opp->available
+ * -ENOMEM	Memory allocation failure
+ * -EINVAL	Failed parsing the OPP node
+ */
+static int _opp_add_static_v2(struct device *dev, struct device_node *np)
+{
+	struct device_opp *dev_opp;
+	struct dev_pm_opp *new_opp;
+	u64 rate;
+	int ret;
+
+	/* Hold our list modification lock here */
+	mutex_lock(&dev_opp_list_lock);
+
+	new_opp = _allocate_opp(dev, &dev_opp);
+	if (!new_opp) {
+		ret = -ENOMEM;
+		goto unlock;
+	}
+
+	ret = of_property_read_u64(np, "opp-hz", &rate);
+	if (ret < 0) {
+		dev_err(dev, "%s: opp-hz not found\n", __func__);
+		goto free_opp;
+	}
+
+	/*
+	 * Rate is defined as an unsigned long in clk API, and so casting
+	 * explicitly to its type. Must be fixed once rate is 64 bit
+	 * guaranteed in clk API.
+	 */
+	new_opp->rate = (unsigned long)rate;
+	new_opp->turbo = of_property_read_bool(np, "turbo-mode");
+
+	new_opp->np = np;
+	new_opp->dynamic = false;
+	new_opp->available = true;
+
+	ret = opp_get_microvolt(new_opp, dev);
+	if (ret)
+		goto free_opp;
+
+	of_property_read_u32(np, "opp-microamp", (u32 *)&new_opp->u_amp);
+
+	ret = _opp_add(new_opp, dev_opp);
+	if (ret)
+		goto free_opp;
+
+	mutex_unlock(&dev_opp_list_lock);
+
+	pr_debug("%s: turbo:%d rate:%lu uv:%lu uvmin:%lu uvmax:%lu\n",
+		 __func__, new_opp->turbo, new_opp->rate, new_opp->u_volt,
+		 new_opp->u_volt_min, new_opp->u_volt_max);
+
+	/*
+	 * Notify the changes in the availability of the operable
+	 * frequency/voltage list.
+	 */
+	srcu_notifier_call_chain(&dev_opp->srcu_head, OPP_EVENT_ADD, new_opp);
+	return 0;
+
+free_opp:
+	_opp_remove(dev_opp, new_opp, false);
+unlock:
+	mutex_unlock(&dev_opp_list_lock);
+	return ret;
+}
+
 /**
  * dev_pm_opp_add()  - Add an OPP table from a table definitions
  * @dev:	device for which we do this operation
@@ -910,29 +1041,64 @@ void of_free_opp_table(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(of_free_opp_table);
 
-/**
- * of_init_opp_table() - Initialize opp table from device tree
- * @dev:	device pointer used to lookup device OPPs.
- *
- * Register the initial OPP table with the OPP library for given device.
- *
- * Locking: The internal device_opp and opp structures are RCU protected.
- * Hence this function indirectly uses RCU updater strategy with mutex locks
- * to keep the integrity of the internal data structures. Callers should ensure
- * that this function is *NOT* called under RCU protection or in contexts where
- * mutex cannot be locked.
- *
- * Return:
- * 0		On success OR
- *		Duplicate OPPs (both freq and volt are same) and opp->available
- * -EEXIST	Freq are same and volt are different OR
- *		Duplicate OPPs (both freq and volt are same) and !opp->available
- * -ENOMEM	Memory allocation failure
- * -ENODEV	when 'operating-points' property is not found or is invalid data
- *		in device node.
- * -ENODATA	when empty 'operating-points' property is found
- */
-int of_init_opp_table(struct device *dev)
+/* Returns opp descriptor node from its phandle. Caller must do of_node_put() */
+static struct device_node *
+_of_get_opp_desc_node_from_prop(struct device *dev, const struct property *prop)
+{
+	struct device_node *opp_np;
+
+	opp_np = of_find_node_by_phandle(be32_to_cpup(prop->value));
+	if (!opp_np) {
+		dev_err(dev, "%s: Prop: %s contains invalid opp desc phandle\n",
+			__func__, prop->name);
+		return ERR_PTR(-EINVAL);
+	}
+
+	return opp_np;
+}
+
+/* Initializes OPP tables based on new bindings */
+static int _of_init_opp_table_v2(struct device *dev,
+				 const struct property *prop)
+{
+	struct device_node *opp_np, *np;
+	int ret = 0, count = 0;
+
+	if (!prop->value)
+		return -ENODATA;
+
+	/* Get opp node */
+	opp_np = _of_get_opp_desc_node_from_prop(dev, prop);
+	if (IS_ERR(opp_np))
+		return PTR_ERR(opp_np);
+
+	/* We have opp-list node now, iterate over it and add OPPs */
+	for_each_available_child_of_node(opp_np, np) {
+		count++;
+
+		ret = _opp_add_static_v2(dev, np);
+		if (ret) {
+			dev_err(dev, "%s: Failed to add OPP, %d\n", __func__,
+				ret);
+			break;
+		}
+	}
+
+	/* There should be one of more OPP defined */
+	if (WARN_ON(!count))
+		goto put_opp_np;
+
+	if (ret)
+		of_free_opp_table(dev);
+
+put_opp_np:
+	of_node_put(opp_np);
+
+	return ret;
+}
+
+/* Initializes OPP tables based on old-deprecated bindings */
+static int _of_init_opp_table_v1(struct device *dev)
 {
 	const struct property *prop;
 	const __be32 *val;
@@ -967,5 +1133,48 @@ int of_init_opp_table(struct device *dev)
 
 	return 0;
 }
+
+/**
+ * of_init_opp_table() - Initialize opp table from device tree
+ * @dev:	device pointer used to lookup device OPPs.
+ *
+ * Register the initial OPP table with the OPP library for given device.
+ *
+ * Locking: The internal device_opp and opp structures are RCU protected.
+ * Hence this function indirectly uses RCU updater strategy with mutex locks
+ * to keep the integrity of the internal data structures. Callers should ensure
+ * that this function is *NOT* called under RCU protection or in contexts where
+ * mutex cannot be locked.
+ *
+ * Return:
+ * 0		On success OR
+ *		Duplicate OPPs (both freq and volt are same) and opp->available
+ * -EEXIST	Freq are same and volt are different OR
+ *		Duplicate OPPs (both freq and volt are same) and !opp->available
+ * -ENOMEM	Memory allocation failure
+ * -ENODEV	when 'operating-points' property is not found or is invalid data
+ *		in device node.
+ * -ENODATA	when empty 'operating-points' property is found
+ * -EINVAL	when invalid entries are found in opp-v2 table
+ */
+int of_init_opp_table(struct device *dev)
+{
+	const struct property *prop;
+
+	/*
+	 * OPPs have two version of bindings now. The older one is deprecated,
+	 * try for the new binding first.
+	 */
+	prop = of_find_property(dev->of_node, "operating-points-v2", NULL);
+	if (!prop) {
+		/*
+		 * Try old-deprecated bindings for backward compatibility with
+		 * older dtbs.
+		 */
+		return _of_init_opp_table_v1(dev);
+	}
+
+	return _of_init_opp_table_v2(dev, prop);
+}
 EXPORT_SYMBOL_GPL(of_init_opp_table);
 #endif
-- 
2.4.0


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

* [PATCH V3 07/16] PM / OPP: Add support to parse "operating-points-v2" bindings
@ 2015-07-29 10:53   ` Viresh Kumar
  0 siblings, 0 replies; 92+ messages in thread
From: Viresh Kumar @ 2015-07-29 10:53 UTC (permalink / raw)
  To: linux-arm-kernel

This adds support in OPP library to parse and create list of OPPs from
operating-points-v2 bindings. It takes care of most of the properties of
new bindings (except shared-opp, which will be handled separately).

For backward compatibility, we keep supporting earlier bindings. We try
to search for the new bindings first, in case they aren't present we
look for the old deprecated ones.

There are few things marked as TODO:
- Support for multiple OPP tables
- Support for multiple regulators

They should be fixed separately.

Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/base/power/opp.c | 257 ++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 233 insertions(+), 24 deletions(-)

diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c
index 0d8dbf21c299..0e0eff4d9299 100644
--- a/drivers/base/power/opp.c
+++ b/drivers/base/power/opp.c
@@ -51,10 +51,15 @@
  *		order.
  * @dynamic:	not-created from static DT entries.
  * @available:	true/false - marks if this OPP as available or not
+ * @turbo:	true if turbo (boost) OPP
  * @rate:	Frequency in hertz
- * @u_volt:	Nominal voltage in microvolts corresponding to this OPP
+ * @u_volt:	Target voltage in microvolts corresponding to this OPP
+ * @u_volt_min:	Minimum voltage in microvolts corresponding to this OPP
+ * @u_volt_max:	Maximum voltage in microvolts corresponding to this OPP
+ * @u_amp:	Maximum current drawn by the device in microamperes
  * @dev_opp:	points back to the device_opp struct this opp belongs to
  * @rcu_head:	RCU callback head used for deferred freeing
+ * @np:		OPP's device node.
  *
  * This structure stores the OPP information for a given device.
  */
@@ -63,11 +68,18 @@ struct dev_pm_opp {
 
 	bool available;
 	bool dynamic;
+	bool turbo;
 	unsigned long rate;
+
 	unsigned long u_volt;
+	unsigned long u_volt_min;
+	unsigned long u_volt_max;
+	unsigned long u_amp;
 
 	struct device_opp *dev_opp;
 	struct rcu_head rcu_head;
+
+	struct device_node *np;
 };
 
 /**
@@ -679,6 +691,125 @@ static int _opp_add_dynamic(struct device *dev, unsigned long freq,
 	return ret;
 }
 
+/* TODO: Support multiple regulators */
+static int opp_get_microvolt(struct dev_pm_opp *opp, struct device *dev)
+{
+	u32 microvolt[3] = {0};
+	int count, ret;
+
+	count = of_property_count_u32_elems(opp->np, "opp-microvolt");
+	if (!count)
+		return 0;
+
+	/* There can be one or three elements here */
+	if (count != 1 && count != 3) {
+		dev_err(dev, "%s: Invalid number of elements in opp-microvolt property (%d)\n",
+			__func__, count);
+		return -EINVAL;
+	}
+
+	ret = of_property_read_u32_array(opp->np, "opp-microvolt", microvolt,
+					 count);
+	if (ret) {
+		dev_err(dev, "%s: error parsing opp-microvolt: %d\n", __func__,
+			ret);
+		return -EINVAL;
+	}
+
+	opp->u_volt = microvolt[0];
+	opp->u_volt_min = microvolt[1];
+	opp->u_volt_max = microvolt[2];
+
+	return 0;
+}
+
+/**
+ * _opp_add_static_v2() - Allocate static OPPs (As per 'v2' DT bindings)
+ * @dev:	device for which we do this operation
+ * @np:		device node
+ *
+ * This function adds an opp definition to the opp list and returns status. The
+ * opp can be controlled using dev_pm_opp_enable/disable functions and may be
+ * removed by dev_pm_opp_remove.
+ *
+ * Locking: The internal device_opp and opp structures are RCU protected.
+ * Hence this function internally uses RCU updater strategy with mutex locks
+ * to keep the integrity of the internal data structures. Callers should ensure
+ * that this function is *NOT* called under RCU protection or in contexts where
+ * mutex cannot be locked.
+ *
+ * Return:
+ * 0		On success OR
+ *		Duplicate OPPs (both freq and volt are same) and opp->available
+ * -EEXIST	Freq are same and volt are different OR
+ *		Duplicate OPPs (both freq and volt are same) and !opp->available
+ * -ENOMEM	Memory allocation failure
+ * -EINVAL	Failed parsing the OPP node
+ */
+static int _opp_add_static_v2(struct device *dev, struct device_node *np)
+{
+	struct device_opp *dev_opp;
+	struct dev_pm_opp *new_opp;
+	u64 rate;
+	int ret;
+
+	/* Hold our list modification lock here */
+	mutex_lock(&dev_opp_list_lock);
+
+	new_opp = _allocate_opp(dev, &dev_opp);
+	if (!new_opp) {
+		ret = -ENOMEM;
+		goto unlock;
+	}
+
+	ret = of_property_read_u64(np, "opp-hz", &rate);
+	if (ret < 0) {
+		dev_err(dev, "%s: opp-hz not found\n", __func__);
+		goto free_opp;
+	}
+
+	/*
+	 * Rate is defined as an unsigned long in clk API, and so casting
+	 * explicitly to its type. Must be fixed once rate is 64 bit
+	 * guaranteed in clk API.
+	 */
+	new_opp->rate = (unsigned long)rate;
+	new_opp->turbo = of_property_read_bool(np, "turbo-mode");
+
+	new_opp->np = np;
+	new_opp->dynamic = false;
+	new_opp->available = true;
+
+	ret = opp_get_microvolt(new_opp, dev);
+	if (ret)
+		goto free_opp;
+
+	of_property_read_u32(np, "opp-microamp", (u32 *)&new_opp->u_amp);
+
+	ret = _opp_add(new_opp, dev_opp);
+	if (ret)
+		goto free_opp;
+
+	mutex_unlock(&dev_opp_list_lock);
+
+	pr_debug("%s: turbo:%d rate:%lu uv:%lu uvmin:%lu uvmax:%lu\n",
+		 __func__, new_opp->turbo, new_opp->rate, new_opp->u_volt,
+		 new_opp->u_volt_min, new_opp->u_volt_max);
+
+	/*
+	 * Notify the changes in the availability of the operable
+	 * frequency/voltage list.
+	 */
+	srcu_notifier_call_chain(&dev_opp->srcu_head, OPP_EVENT_ADD, new_opp);
+	return 0;
+
+free_opp:
+	_opp_remove(dev_opp, new_opp, false);
+unlock:
+	mutex_unlock(&dev_opp_list_lock);
+	return ret;
+}
+
 /**
  * dev_pm_opp_add()  - Add an OPP table from a table definitions
  * @dev:	device for which we do this operation
@@ -910,29 +1041,64 @@ void of_free_opp_table(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(of_free_opp_table);
 
-/**
- * of_init_opp_table() - Initialize opp table from device tree
- * @dev:	device pointer used to lookup device OPPs.
- *
- * Register the initial OPP table with the OPP library for given device.
- *
- * Locking: The internal device_opp and opp structures are RCU protected.
- * Hence this function indirectly uses RCU updater strategy with mutex locks
- * to keep the integrity of the internal data structures. Callers should ensure
- * that this function is *NOT* called under RCU protection or in contexts where
- * mutex cannot be locked.
- *
- * Return:
- * 0		On success OR
- *		Duplicate OPPs (both freq and volt are same) and opp->available
- * -EEXIST	Freq are same and volt are different OR
- *		Duplicate OPPs (both freq and volt are same) and !opp->available
- * -ENOMEM	Memory allocation failure
- * -ENODEV	when 'operating-points' property is not found or is invalid data
- *		in device node.
- * -ENODATA	when empty 'operating-points' property is found
- */
-int of_init_opp_table(struct device *dev)
+/* Returns opp descriptor node from its phandle. Caller must do of_node_put() */
+static struct device_node *
+_of_get_opp_desc_node_from_prop(struct device *dev, const struct property *prop)
+{
+	struct device_node *opp_np;
+
+	opp_np = of_find_node_by_phandle(be32_to_cpup(prop->value));
+	if (!opp_np) {
+		dev_err(dev, "%s: Prop: %s contains invalid opp desc phandle\n",
+			__func__, prop->name);
+		return ERR_PTR(-EINVAL);
+	}
+
+	return opp_np;
+}
+
+/* Initializes OPP tables based on new bindings */
+static int _of_init_opp_table_v2(struct device *dev,
+				 const struct property *prop)
+{
+	struct device_node *opp_np, *np;
+	int ret = 0, count = 0;
+
+	if (!prop->value)
+		return -ENODATA;
+
+	/* Get opp node */
+	opp_np = _of_get_opp_desc_node_from_prop(dev, prop);
+	if (IS_ERR(opp_np))
+		return PTR_ERR(opp_np);
+
+	/* We have opp-list node now, iterate over it and add OPPs */
+	for_each_available_child_of_node(opp_np, np) {
+		count++;
+
+		ret = _opp_add_static_v2(dev, np);
+		if (ret) {
+			dev_err(dev, "%s: Failed to add OPP, %d\n", __func__,
+				ret);
+			break;
+		}
+	}
+
+	/* There should be one of more OPP defined */
+	if (WARN_ON(!count))
+		goto put_opp_np;
+
+	if (ret)
+		of_free_opp_table(dev);
+
+put_opp_np:
+	of_node_put(opp_np);
+
+	return ret;
+}
+
+/* Initializes OPP tables based on old-deprecated bindings */
+static int _of_init_opp_table_v1(struct device *dev)
 {
 	const struct property *prop;
 	const __be32 *val;
@@ -967,5 +1133,48 @@ int of_init_opp_table(struct device *dev)
 
 	return 0;
 }
+
+/**
+ * of_init_opp_table() - Initialize opp table from device tree
+ * @dev:	device pointer used to lookup device OPPs.
+ *
+ * Register the initial OPP table with the OPP library for given device.
+ *
+ * Locking: The internal device_opp and opp structures are RCU protected.
+ * Hence this function indirectly uses RCU updater strategy with mutex locks
+ * to keep the integrity of the internal data structures. Callers should ensure
+ * that this function is *NOT* called under RCU protection or in contexts where
+ * mutex cannot be locked.
+ *
+ * Return:
+ * 0		On success OR
+ *		Duplicate OPPs (both freq and volt are same) and opp->available
+ * -EEXIST	Freq are same and volt are different OR
+ *		Duplicate OPPs (both freq and volt are same) and !opp->available
+ * -ENOMEM	Memory allocation failure
+ * -ENODEV	when 'operating-points' property is not found or is invalid data
+ *		in device node.
+ * -ENODATA	when empty 'operating-points' property is found
+ * -EINVAL	when invalid entries are found in opp-v2 table
+ */
+int of_init_opp_table(struct device *dev)
+{
+	const struct property *prop;
+
+	/*
+	 * OPPs have two version of bindings now. The older one is deprecated,
+	 * try for the new binding first.
+	 */
+	prop = of_find_property(dev->of_node, "operating-points-v2", NULL);
+	if (!prop) {
+		/*
+		 * Try old-deprecated bindings for backward compatibility with
+		 * older dtbs.
+		 */
+		return _of_init_opp_table_v1(dev);
+	}
+
+	return _of_init_opp_table_v2(dev, prop);
+}
 EXPORT_SYMBOL_GPL(of_init_opp_table);
 #endif
-- 
2.4.0

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

* [PATCH V3 08/16] PM / OPP: Add clock-latency-ns support
  2015-07-29 10:52 ` Viresh Kumar
  (?)
@ 2015-07-29 10:53   ` Viresh Kumar
  -1 siblings, 0 replies; 92+ messages in thread
From: Viresh Kumar @ 2015-07-29 10:53 UTC (permalink / raw)
  To: Rafael Wysocki, sboyd
  Cc: linaro-kernel, linux-pm, rob.herring, arnd.bergmann, nm, broonie,
	mturquette, Sudeep.Holla, viswanath.puttagunta, l.stach,
	thomas.petazzoni, linux-arm-kernel, ta.omasab, kesavan.abhilash,
	khilman, santosh.shilimkar, b.zolnierkie, Viresh Kumar,
	Greg Kroah-Hartman, Len Brown, open list, Pavel Machek

With "operating-points-v2" bindings, clock-latency is defined per OPP.
Users of this value expect a single value which defines the latency to
switch to any clock rate. Find maximum clock-latency-ns from the OPP
table to service requests from such users.

Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>
Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/base/power/opp.c | 41 +++++++++++++++++++++++++++++++++++++++--
 include/linux/pm_opp.h   |  6 ++++++
 2 files changed, 45 insertions(+), 2 deletions(-)

diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c
index 0e0eff4d9299..8638204c457e 100644
--- a/drivers/base/power/opp.c
+++ b/drivers/base/power/opp.c
@@ -57,6 +57,8 @@
  * @u_volt_min:	Minimum voltage in microvolts corresponding to this OPP
  * @u_volt_max:	Maximum voltage in microvolts corresponding to this OPP
  * @u_amp:	Maximum current drawn by the device in microamperes
+ * @clock_latency_ns: Latency (in nanoseconds) of switching to this OPP's
+ *		frequency from any other OPP's frequency.
  * @dev_opp:	points back to the device_opp struct this opp belongs to
  * @rcu_head:	RCU callback head used for deferred freeing
  * @np:		OPP's device node.
@@ -75,6 +77,7 @@ struct dev_pm_opp {
 	unsigned long u_volt_min;
 	unsigned long u_volt_max;
 	unsigned long u_amp;
+	unsigned long clock_latency_ns;
 
 	struct device_opp *dev_opp;
 	struct rcu_head rcu_head;
@@ -109,6 +112,8 @@ struct device_opp {
 	struct srcu_notifier_head srcu_head;
 	struct rcu_head rcu_head;
 	struct list_head opp_list;
+
+	unsigned long clock_latency_ns_max;
 };
 
 /*
@@ -226,6 +231,32 @@ unsigned long dev_pm_opp_get_freq(struct dev_pm_opp *opp)
 EXPORT_SYMBOL_GPL(dev_pm_opp_get_freq);
 
 /**
+ * dev_pm_opp_get_max_clock_latency() - Get max clock latency in nanoseconds
+ * @dev:	device for which we do this operation
+ *
+ * Return: This function returns the max clock latency in nanoseconds.
+ *
+ * Locking: This function takes rcu_read_lock().
+ */
+unsigned long dev_pm_opp_get_max_clock_latency(struct device *dev)
+{
+	struct device_opp *dev_opp;
+	unsigned long clock_latency_ns;
+
+	rcu_read_lock();
+
+	dev_opp = _find_device_opp(dev);
+	if (IS_ERR(dev_opp))
+		clock_latency_ns = 0;
+	else
+		clock_latency_ns = dev_opp->clock_latency_ns_max;
+
+	rcu_read_unlock();
+	return clock_latency_ns;
+}
+EXPORT_SYMBOL_GPL(dev_pm_opp_get_max_clock_latency);
+
+/**
  * dev_pm_opp_get_opp_count() - Get number of opps available in the opp list
  * @dev:	device for which we do this operation
  *
@@ -779,6 +810,8 @@ static int _opp_add_static_v2(struct device *dev, struct device_node *np)
 	new_opp->np = np;
 	new_opp->dynamic = false;
 	new_opp->available = true;
+	of_property_read_u32(np, "clock-latency-ns",
+			     (u32 *)&new_opp->clock_latency_ns);
 
 	ret = opp_get_microvolt(new_opp, dev);
 	if (ret)
@@ -790,11 +823,15 @@ static int _opp_add_static_v2(struct device *dev, struct device_node *np)
 	if (ret)
 		goto free_opp;
 
+	if (new_opp->clock_latency_ns > dev_opp->clock_latency_ns_max)
+		dev_opp->clock_latency_ns_max = new_opp->clock_latency_ns;
+
 	mutex_unlock(&dev_opp_list_lock);
 
-	pr_debug("%s: turbo:%d rate:%lu uv:%lu uvmin:%lu uvmax:%lu\n",
+	pr_debug("%s: turbo:%d rate:%lu uv:%lu uvmin:%lu uvmax:%lu latency:%lu\n",
 		 __func__, new_opp->turbo, new_opp->rate, new_opp->u_volt,
-		 new_opp->u_volt_min, new_opp->u_volt_max);
+		 new_opp->u_volt_min, new_opp->u_volt_max,
+		 new_opp->clock_latency_ns);
 
 	/*
 	 * Notify the changes in the availability of the operable
diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h
index cec2d4540914..20324b579adc 100644
--- a/include/linux/pm_opp.h
+++ b/include/linux/pm_opp.h
@@ -31,6 +31,7 @@ unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp);
 unsigned long dev_pm_opp_get_freq(struct dev_pm_opp *opp);
 
 int dev_pm_opp_get_opp_count(struct device *dev);
+unsigned long dev_pm_opp_get_max_clock_latency(struct device *dev);
 
 struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev,
 					      unsigned long freq,
@@ -67,6 +68,11 @@ static inline int dev_pm_opp_get_opp_count(struct device *dev)
 	return 0;
 }
 
+static inline unsigned long dev_pm_opp_get_max_clock_latency(struct device *dev)
+{
+	return 0;
+}
+
 static inline struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev,
 					unsigned long freq, bool available)
 {
-- 
2.4.0


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

* [PATCH V3 08/16] PM / OPP: Add clock-latency-ns support
@ 2015-07-29 10:53   ` Viresh Kumar
  0 siblings, 0 replies; 92+ messages in thread
From: Viresh Kumar @ 2015-07-29 10:53 UTC (permalink / raw)
  To: Rafael Wysocki, sboyd
  Cc: linaro-kernel, linux-pm, rob.herring, arnd.bergmann, nm, broonie,
	mturquette, Sudeep.Holla, viswanath.puttagunta, l.stach,
	thomas.petazzoni, linux-arm-kernel, ta.omasab, kesavan.abhilash,
	khilman, santosh.shilimkar, b.zolnierkie, Viresh Kumar,
	Greg Kroah-Hartman, Len Brown, open list, Pavel Machek

With "operating-points-v2" bindings, clock-latency is defined per OPP.
Users of this value expect a single value which defines the latency to
switch to any clock rate. Find maximum clock-latency-ns from the OPP
table to service requests from such users.

Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>
Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/base/power/opp.c | 41 +++++++++++++++++++++++++++++++++++++++--
 include/linux/pm_opp.h   |  6 ++++++
 2 files changed, 45 insertions(+), 2 deletions(-)

diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c
index 0e0eff4d9299..8638204c457e 100644
--- a/drivers/base/power/opp.c
+++ b/drivers/base/power/opp.c
@@ -57,6 +57,8 @@
  * @u_volt_min:	Minimum voltage in microvolts corresponding to this OPP
  * @u_volt_max:	Maximum voltage in microvolts corresponding to this OPP
  * @u_amp:	Maximum current drawn by the device in microamperes
+ * @clock_latency_ns: Latency (in nanoseconds) of switching to this OPP's
+ *		frequency from any other OPP's frequency.
  * @dev_opp:	points back to the device_opp struct this opp belongs to
  * @rcu_head:	RCU callback head used for deferred freeing
  * @np:		OPP's device node.
@@ -75,6 +77,7 @@ struct dev_pm_opp {
 	unsigned long u_volt_min;
 	unsigned long u_volt_max;
 	unsigned long u_amp;
+	unsigned long clock_latency_ns;
 
 	struct device_opp *dev_opp;
 	struct rcu_head rcu_head;
@@ -109,6 +112,8 @@ struct device_opp {
 	struct srcu_notifier_head srcu_head;
 	struct rcu_head rcu_head;
 	struct list_head opp_list;
+
+	unsigned long clock_latency_ns_max;
 };
 
 /*
@@ -226,6 +231,32 @@ unsigned long dev_pm_opp_get_freq(struct dev_pm_opp *opp)
 EXPORT_SYMBOL_GPL(dev_pm_opp_get_freq);
 
 /**
+ * dev_pm_opp_get_max_clock_latency() - Get max clock latency in nanoseconds
+ * @dev:	device for which we do this operation
+ *
+ * Return: This function returns the max clock latency in nanoseconds.
+ *
+ * Locking: This function takes rcu_read_lock().
+ */
+unsigned long dev_pm_opp_get_max_clock_latency(struct device *dev)
+{
+	struct device_opp *dev_opp;
+	unsigned long clock_latency_ns;
+
+	rcu_read_lock();
+
+	dev_opp = _find_device_opp(dev);
+	if (IS_ERR(dev_opp))
+		clock_latency_ns = 0;
+	else
+		clock_latency_ns = dev_opp->clock_latency_ns_max;
+
+	rcu_read_unlock();
+	return clock_latency_ns;
+}
+EXPORT_SYMBOL_GPL(dev_pm_opp_get_max_clock_latency);
+
+/**
  * dev_pm_opp_get_opp_count() - Get number of opps available in the opp list
  * @dev:	device for which we do this operation
  *
@@ -779,6 +810,8 @@ static int _opp_add_static_v2(struct device *dev, struct device_node *np)
 	new_opp->np = np;
 	new_opp->dynamic = false;
 	new_opp->available = true;
+	of_property_read_u32(np, "clock-latency-ns",
+			     (u32 *)&new_opp->clock_latency_ns);
 
 	ret = opp_get_microvolt(new_opp, dev);
 	if (ret)
@@ -790,11 +823,15 @@ static int _opp_add_static_v2(struct device *dev, struct device_node *np)
 	if (ret)
 		goto free_opp;
 
+	if (new_opp->clock_latency_ns > dev_opp->clock_latency_ns_max)
+		dev_opp->clock_latency_ns_max = new_opp->clock_latency_ns;
+
 	mutex_unlock(&dev_opp_list_lock);
 
-	pr_debug("%s: turbo:%d rate:%lu uv:%lu uvmin:%lu uvmax:%lu\n",
+	pr_debug("%s: turbo:%d rate:%lu uv:%lu uvmin:%lu uvmax:%lu latency:%lu\n",
 		 __func__, new_opp->turbo, new_opp->rate, new_opp->u_volt,
-		 new_opp->u_volt_min, new_opp->u_volt_max);
+		 new_opp->u_volt_min, new_opp->u_volt_max,
+		 new_opp->clock_latency_ns);
 
 	/*
 	 * Notify the changes in the availability of the operable
diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h
index cec2d4540914..20324b579adc 100644
--- a/include/linux/pm_opp.h
+++ b/include/linux/pm_opp.h
@@ -31,6 +31,7 @@ unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp);
 unsigned long dev_pm_opp_get_freq(struct dev_pm_opp *opp);
 
 int dev_pm_opp_get_opp_count(struct device *dev);
+unsigned long dev_pm_opp_get_max_clock_latency(struct device *dev);
 
 struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev,
 					      unsigned long freq,
@@ -67,6 +68,11 @@ static inline int dev_pm_opp_get_opp_count(struct device *dev)
 	return 0;
 }
 
+static inline unsigned long dev_pm_opp_get_max_clock_latency(struct device *dev)
+{
+	return 0;
+}
+
 static inline struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev,
 					unsigned long freq, bool available)
 {
-- 
2.4.0

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

* [PATCH V3 08/16] PM / OPP: Add clock-latency-ns support
@ 2015-07-29 10:53   ` Viresh Kumar
  0 siblings, 0 replies; 92+ messages in thread
From: Viresh Kumar @ 2015-07-29 10:53 UTC (permalink / raw)
  To: linux-arm-kernel

With "operating-points-v2" bindings, clock-latency is defined per OPP.
Users of this value expect a single value which defines the latency to
switch to any clock rate. Find maximum clock-latency-ns from the OPP
table to service requests from such users.

Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>
Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/base/power/opp.c | 41 +++++++++++++++++++++++++++++++++++++++--
 include/linux/pm_opp.h   |  6 ++++++
 2 files changed, 45 insertions(+), 2 deletions(-)

diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c
index 0e0eff4d9299..8638204c457e 100644
--- a/drivers/base/power/opp.c
+++ b/drivers/base/power/opp.c
@@ -57,6 +57,8 @@
  * @u_volt_min:	Minimum voltage in microvolts corresponding to this OPP
  * @u_volt_max:	Maximum voltage in microvolts corresponding to this OPP
  * @u_amp:	Maximum current drawn by the device in microamperes
+ * @clock_latency_ns: Latency (in nanoseconds) of switching to this OPP's
+ *		frequency from any other OPP's frequency.
  * @dev_opp:	points back to the device_opp struct this opp belongs to
  * @rcu_head:	RCU callback head used for deferred freeing
  * @np:		OPP's device node.
@@ -75,6 +77,7 @@ struct dev_pm_opp {
 	unsigned long u_volt_min;
 	unsigned long u_volt_max;
 	unsigned long u_amp;
+	unsigned long clock_latency_ns;
 
 	struct device_opp *dev_opp;
 	struct rcu_head rcu_head;
@@ -109,6 +112,8 @@ struct device_opp {
 	struct srcu_notifier_head srcu_head;
 	struct rcu_head rcu_head;
 	struct list_head opp_list;
+
+	unsigned long clock_latency_ns_max;
 };
 
 /*
@@ -226,6 +231,32 @@ unsigned long dev_pm_opp_get_freq(struct dev_pm_opp *opp)
 EXPORT_SYMBOL_GPL(dev_pm_opp_get_freq);
 
 /**
+ * dev_pm_opp_get_max_clock_latency() - Get max clock latency in nanoseconds
+ * @dev:	device for which we do this operation
+ *
+ * Return: This function returns the max clock latency in nanoseconds.
+ *
+ * Locking: This function takes rcu_read_lock().
+ */
+unsigned long dev_pm_opp_get_max_clock_latency(struct device *dev)
+{
+	struct device_opp *dev_opp;
+	unsigned long clock_latency_ns;
+
+	rcu_read_lock();
+
+	dev_opp = _find_device_opp(dev);
+	if (IS_ERR(dev_opp))
+		clock_latency_ns = 0;
+	else
+		clock_latency_ns = dev_opp->clock_latency_ns_max;
+
+	rcu_read_unlock();
+	return clock_latency_ns;
+}
+EXPORT_SYMBOL_GPL(dev_pm_opp_get_max_clock_latency);
+
+/**
  * dev_pm_opp_get_opp_count() - Get number of opps available in the opp list
  * @dev:	device for which we do this operation
  *
@@ -779,6 +810,8 @@ static int _opp_add_static_v2(struct device *dev, struct device_node *np)
 	new_opp->np = np;
 	new_opp->dynamic = false;
 	new_opp->available = true;
+	of_property_read_u32(np, "clock-latency-ns",
+			     (u32 *)&new_opp->clock_latency_ns);
 
 	ret = opp_get_microvolt(new_opp, dev);
 	if (ret)
@@ -790,11 +823,15 @@ static int _opp_add_static_v2(struct device *dev, struct device_node *np)
 	if (ret)
 		goto free_opp;
 
+	if (new_opp->clock_latency_ns > dev_opp->clock_latency_ns_max)
+		dev_opp->clock_latency_ns_max = new_opp->clock_latency_ns;
+
 	mutex_unlock(&dev_opp_list_lock);
 
-	pr_debug("%s: turbo:%d rate:%lu uv:%lu uvmin:%lu uvmax:%lu\n",
+	pr_debug("%s: turbo:%d rate:%lu uv:%lu uvmin:%lu uvmax:%lu latency:%lu\n",
 		 __func__, new_opp->turbo, new_opp->rate, new_opp->u_volt,
-		 new_opp->u_volt_min, new_opp->u_volt_max);
+		 new_opp->u_volt_min, new_opp->u_volt_max,
+		 new_opp->clock_latency_ns);
 
 	/*
 	 * Notify the changes in the availability of the operable
diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h
index cec2d4540914..20324b579adc 100644
--- a/include/linux/pm_opp.h
+++ b/include/linux/pm_opp.h
@@ -31,6 +31,7 @@ unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp);
 unsigned long dev_pm_opp_get_freq(struct dev_pm_opp *opp);
 
 int dev_pm_opp_get_opp_count(struct device *dev);
+unsigned long dev_pm_opp_get_max_clock_latency(struct device *dev);
 
 struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev,
 					      unsigned long freq,
@@ -67,6 +68,11 @@ static inline int dev_pm_opp_get_opp_count(struct device *dev)
 	return 0;
 }
 
+static inline unsigned long dev_pm_opp_get_max_clock_latency(struct device *dev)
+{
+	return 0;
+}
+
 static inline struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev,
 					unsigned long freq, bool available)
 {
-- 
2.4.0

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

* [PATCH V3 09/16] PM / OPP: Add OPP sharing information to OPP library
  2015-07-29 10:52 ` Viresh Kumar
  (?)
@ 2015-07-29 10:53   ` Viresh Kumar
  -1 siblings, 0 replies; 92+ messages in thread
From: Viresh Kumar @ 2015-07-29 10:53 UTC (permalink / raw)
  To: Rafael Wysocki, sboyd
  Cc: linaro-kernel, linux-pm, rob.herring, arnd.bergmann, nm, broonie,
	mturquette, Sudeep.Holla, viswanath.puttagunta, l.stach,
	thomas.petazzoni, linux-arm-kernel, ta.omasab, kesavan.abhilash,
	khilman, santosh.shilimkar, b.zolnierkie, Viresh Kumar,
	Greg Kroah-Hartman, Len Brown, open list, Pavel Machek

An opp can be shared by multiple devices, for example its very common
for CPUs to share the OPPs, i.e. when they share clock/voltage rails.

This patch adds support of shared OPPs to the OPP library.

Instead of a single device, dev_opp will now contain a list of devices
that use it. It also senses if the device (we are trying to initialize
OPPs for) shares OPPs with a device added earlier and in that case we
update the list of devices managed by OPPs instead of duplicating OPPs
again.

The same infrastructure will be used for the old OPP bindings, with
later patches.

Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>
Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/base/power/opp.c | 174 ++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 150 insertions(+), 24 deletions(-)

diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c
index 8638204c457e..5d699e3ec136 100644
--- a/drivers/base/power/opp.c
+++ b/drivers/base/power/opp.c
@@ -86,16 +86,33 @@ struct dev_pm_opp {
 };
 
 /**
+ * struct device_list_opp - devices managed by 'struct device_opp'
+ * @node:	list node
+ * @dev:	device to which the struct object belongs
+ * @rcu_head:	RCU callback head used for deferred freeing
+ *
+ * This is an internal data structure maintaining the list of devices that are
+ * managed by 'struct device_opp'.
+ */
+struct device_list_opp {
+	struct list_head node;
+	const struct device *dev;
+	struct rcu_head rcu_head;
+};
+
+/**
  * struct device_opp - Device opp structure
  * @node:	list node - contains the devices with OPPs that
  *		have been registered. Nodes once added are not modified in this
  *		list.
  *		RCU usage: nodes are not modified in the list of device_opp,
  *		however addition is possible and is secured by dev_opp_list_lock
- * @dev:	device pointer
  * @srcu_head:	notifier head to notify the OPP availability changes.
  * @rcu_head:	RCU callback head used for deferred freeing
+ * @dev_list:	list of devices that share these OPPs
  * @opp_list:	list of opps
+ * @np:		struct device_node pointer for opp's DT node.
+ * @shared_opp: OPP is shared between multiple devices.
  *
  * This is an internal data structure maintaining the link to opps attached to
  * a device. This structure is not meant to be shared to users as it is
@@ -108,12 +125,14 @@ struct dev_pm_opp {
 struct device_opp {
 	struct list_head node;
 
-	struct device *dev;
 	struct srcu_notifier_head srcu_head;
 	struct rcu_head rcu_head;
+	struct list_head dev_list;
 	struct list_head opp_list;
 
+	struct device_node *np;
 	unsigned long clock_latency_ns_max;
+	bool shared_opp;
 };
 
 /*
@@ -133,6 +152,38 @@ do {									\
 			   "dev_opp_list_lock protection");		\
 } while (0)
 
+static struct device_list_opp *_find_list_dev(const struct device *dev,
+					      struct device_opp *dev_opp)
+{
+	struct device_list_opp *list_dev;
+
+	list_for_each_entry(list_dev, &dev_opp->dev_list, node)
+		if (list_dev->dev == dev)
+			return list_dev;
+
+	return NULL;
+}
+
+static struct device_opp *_managed_opp(const struct device_node *np)
+{
+	struct device_opp *dev_opp;
+
+	list_for_each_entry_rcu(dev_opp, &dev_opp_list, node) {
+		if (dev_opp->np == np) {
+			/*
+			 * Multiple devices can point to the same OPP table and
+			 * so will have same node-pointer, np.
+			 *
+			 * But the OPPs will be considered as shared only if the
+			 * OPP table contains a "opp-shared" property.
+			 */
+			return dev_opp->shared_opp ? dev_opp : NULL;
+		}
+	}
+
+	return NULL;
+}
+
 /**
  * _find_device_opp() - find device_opp struct using device pointer
  * @dev:	device pointer used to lookup device OPPs
@@ -149,21 +200,18 @@ do {									\
  */
 static struct device_opp *_find_device_opp(struct device *dev)
 {
-	struct device_opp *tmp_dev_opp, *dev_opp = ERR_PTR(-ENODEV);
+	struct device_opp *dev_opp;
 
 	if (unlikely(IS_ERR_OR_NULL(dev))) {
 		pr_err("%s: Invalid parameters\n", __func__);
 		return ERR_PTR(-EINVAL);
 	}
 
-	list_for_each_entry_rcu(tmp_dev_opp, &dev_opp_list, node) {
-		if (tmp_dev_opp->dev == dev) {
-			dev_opp = tmp_dev_opp;
-			break;
-		}
-	}
+	list_for_each_entry_rcu(dev_opp, &dev_opp_list, node)
+		if (_find_list_dev(dev, dev_opp))
+			return dev_opp;
 
-	return dev_opp;
+	return ERR_PTR(-ENODEV);
 }
 
 /**
@@ -450,6 +498,39 @@ struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev,
 }
 EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_floor);
 
+/* List-dev Helpers */
+static void _kfree_list_dev_rcu(struct rcu_head *head)
+{
+	struct device_list_opp *list_dev;
+
+	list_dev = container_of(head, struct device_list_opp, rcu_head);
+	kfree_rcu(list_dev, rcu_head);
+}
+
+static void _remove_list_dev(struct device_list_opp *list_dev,
+			     struct device_opp *dev_opp)
+{
+	list_del(&list_dev->node);
+	call_srcu(&dev_opp->srcu_head.srcu, &list_dev->rcu_head,
+		  _kfree_list_dev_rcu);
+}
+
+static struct device_list_opp *_add_list_dev(const struct device *dev,
+					     struct device_opp *dev_opp)
+{
+	struct device_list_opp *list_dev;
+
+	list_dev = kzalloc(sizeof(*list_dev), GFP_KERNEL);
+	if (!list_dev)
+		return NULL;
+
+	/* Initialize list-dev */
+	list_dev->dev = dev;
+	list_add_rcu(&list_dev->node, &dev_opp->dev_list);
+
+	return list_dev;
+}
+
 /**
  * _add_device_opp() - Find device OPP table or allocate a new one
  * @dev:	device for which we do this operation
@@ -462,6 +543,7 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_floor);
 static struct device_opp *_add_device_opp(struct device *dev)
 {
 	struct device_opp *dev_opp;
+	struct device_list_opp *list_dev;
 
 	/* Check for existing list for 'dev' first */
 	dev_opp = _find_device_opp(dev);
@@ -476,7 +558,14 @@ static struct device_opp *_add_device_opp(struct device *dev)
 	if (!dev_opp)
 		return NULL;
 
-	dev_opp->dev = dev;
+	INIT_LIST_HEAD(&dev_opp->dev_list);
+
+	list_dev = _add_list_dev(dev, dev_opp);
+	if (!list_dev) {
+		kfree(dev_opp);
+		return NULL;
+	}
+
 	srcu_init_notifier_head(&dev_opp->srcu_head);
 	INIT_LIST_HEAD(&dev_opp->opp_list);
 
@@ -504,9 +593,19 @@ static void _kfree_device_rcu(struct rcu_head *head)
  */
 static void _remove_device_opp(struct device_opp *dev_opp)
 {
+	struct device_list_opp *list_dev;
+
 	if (!list_empty(&dev_opp->opp_list))
 		return;
 
+	list_dev = list_first_entry(&dev_opp->dev_list, struct device_list_opp,
+				    node);
+
+	_remove_list_dev(list_dev, dev_opp);
+
+	/* dev_list must be empty now */
+	WARN_ON(!list_empty(&dev_opp->dev_list));
+
 	list_del_rcu(&dev_opp->node);
 	call_srcu(&dev_opp->srcu_head.srcu, &dev_opp->rcu_head,
 		  _kfree_device_rcu);
@@ -616,7 +715,8 @@ static struct dev_pm_opp *_allocate_opp(struct device *dev,
 	return opp;
 }
 
-static int _opp_add(struct dev_pm_opp *new_opp, struct device_opp *dev_opp)
+static int _opp_add(struct device *dev, struct dev_pm_opp *new_opp,
+		    struct device_opp *dev_opp)
 {
 	struct dev_pm_opp *opp;
 	struct list_head *head = &dev_opp->opp_list;
@@ -639,7 +739,7 @@ static int _opp_add(struct dev_pm_opp *new_opp, struct device_opp *dev_opp)
 			break;
 
 		/* Duplicate OPPs */
-		dev_warn(dev_opp->dev, "%s: duplicate OPPs detected. Existing: freq: %lu, volt: %lu, enabled: %d. New: freq: %lu, volt: %lu, enabled: %d\n",
+		dev_warn(dev, "%s: duplicate OPPs detected. Existing: freq: %lu, volt: %lu, enabled: %d. New: freq: %lu, volt: %lu, enabled: %d\n",
 			 __func__, opp->rate, opp->u_volt, opp->available,
 			 new_opp->rate, new_opp->u_volt, new_opp->available);
 
@@ -702,7 +802,7 @@ static int _opp_add_dynamic(struct device *dev, unsigned long freq,
 	new_opp->available = true;
 	new_opp->dynamic = dynamic;
 
-	ret = _opp_add(new_opp, dev_opp);
+	ret = _opp_add(dev, new_opp, dev_opp);
 	if (ret)
 		goto free_opp;
 
@@ -819,7 +919,7 @@ static int _opp_add_static_v2(struct device *dev, struct device_node *np)
 
 	of_property_read_u32(np, "opp-microamp", (u32 *)&new_opp->u_amp);
 
-	ret = _opp_add(new_opp, dev_opp);
+	ret = _opp_add(dev, new_opp, dev_opp);
 	if (ret)
 		goto free_opp;
 
@@ -1052,6 +1152,9 @@ void of_free_opp_table(struct device *dev)
 	struct device_opp *dev_opp;
 	struct dev_pm_opp *opp, *tmp;
 
+	/* Hold our list modification lock here */
+	mutex_lock(&dev_opp_list_lock);
+
 	/* Check for existing list for 'dev' */
 	dev_opp = _find_device_opp(dev);
 	if (IS_ERR(dev_opp)) {
@@ -1062,18 +1165,21 @@ void of_free_opp_table(struct device *dev)
 			     IS_ERR_OR_NULL(dev) ?
 					"Invalid device" : dev_name(dev),
 			     error);
-		return;
+		goto unlock;
 	}
 
-	/* Hold our list modification lock here */
-	mutex_lock(&dev_opp_list_lock);
-
-	/* Free static OPPs */
-	list_for_each_entry_safe(opp, tmp, &dev_opp->opp_list, node) {
-		if (!opp->dynamic)
-			_opp_remove(dev_opp, opp, true);
+	/* Find if dev_opp manages a single device */
+	if (list_is_singular(&dev_opp->dev_list)) {
+		/* Free static OPPs */
+		list_for_each_entry_safe(opp, tmp, &dev_opp->opp_list, node) {
+			if (!opp->dynamic)
+				_opp_remove(dev_opp, opp, true);
+		}
+	} else {
+		_remove_list_dev(_find_list_dev(dev, dev_opp), dev_opp);
 	}
 
+unlock:
 	mutex_unlock(&dev_opp_list_lock);
 }
 EXPORT_SYMBOL_GPL(of_free_opp_table);
@@ -1099,6 +1205,7 @@ static int _of_init_opp_table_v2(struct device *dev,
 				 const struct property *prop)
 {
 	struct device_node *opp_np, *np;
+	struct device_opp *dev_opp;
 	int ret = 0, count = 0;
 
 	if (!prop->value)
@@ -1109,6 +1216,14 @@ static int _of_init_opp_table_v2(struct device *dev,
 	if (IS_ERR(opp_np))
 		return PTR_ERR(opp_np);
 
+	dev_opp = _managed_opp(opp_np);
+	if (dev_opp) {
+		/* OPPs are already managed */
+		if (!_add_list_dev(dev, dev_opp))
+			ret = -ENOMEM;
+		goto put_opp_np;
+	}
+
 	/* We have opp-list node now, iterate over it and add OPPs */
 	for_each_available_child_of_node(opp_np, np) {
 		count++;
@@ -1125,8 +1240,19 @@ static int _of_init_opp_table_v2(struct device *dev,
 	if (WARN_ON(!count))
 		goto put_opp_np;
 
-	if (ret)
+	if (!ret) {
+		if (!dev_opp) {
+			dev_opp = _find_device_opp(dev);
+			if (WARN_ON(!dev_opp))
+				goto put_opp_np;
+		}
+
+		dev_opp->np = opp_np;
+		dev_opp->shared_opp = of_property_read_bool(opp_np,
+							    "opp-shared");
+	} else {
 		of_free_opp_table(dev);
+	}
 
 put_opp_np:
 	of_node_put(opp_np);
-- 
2.4.0


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

* [PATCH V3 09/16] PM / OPP: Add OPP sharing information to OPP library
@ 2015-07-29 10:53   ` Viresh Kumar
  0 siblings, 0 replies; 92+ messages in thread
From: Viresh Kumar @ 2015-07-29 10:53 UTC (permalink / raw)
  To: Rafael Wysocki, sboyd
  Cc: linaro-kernel, linux-pm, rob.herring, arnd.bergmann, nm, broonie,
	mturquette, Sudeep.Holla, viswanath.puttagunta, l.stach,
	thomas.petazzoni, linux-arm-kernel, ta.omasab, kesavan.abhilash,
	khilman, santosh.shilimkar, b.zolnierkie, Viresh Kumar,
	Greg Kroah-Hartman, Len Brown, open list, Pavel Machek

An opp can be shared by multiple devices, for example its very common
for CPUs to share the OPPs, i.e. when they share clock/voltage rails.

This patch adds support of shared OPPs to the OPP library.

Instead of a single device, dev_opp will now contain a list of devices
that use it. It also senses if the device (we are trying to initialize
OPPs for) shares OPPs with a device added earlier and in that case we
update the list of devices managed by OPPs instead of duplicating OPPs
again.

The same infrastructure will be used for the old OPP bindings, with
later patches.

Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>
Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/base/power/opp.c | 174 ++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 150 insertions(+), 24 deletions(-)

diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c
index 8638204c457e..5d699e3ec136 100644
--- a/drivers/base/power/opp.c
+++ b/drivers/base/power/opp.c
@@ -86,16 +86,33 @@ struct dev_pm_opp {
 };
 
 /**
+ * struct device_list_opp - devices managed by 'struct device_opp'
+ * @node:	list node
+ * @dev:	device to which the struct object belongs
+ * @rcu_head:	RCU callback head used for deferred freeing
+ *
+ * This is an internal data structure maintaining the list of devices that are
+ * managed by 'struct device_opp'.
+ */
+struct device_list_opp {
+	struct list_head node;
+	const struct device *dev;
+	struct rcu_head rcu_head;
+};
+
+/**
  * struct device_opp - Device opp structure
  * @node:	list node - contains the devices with OPPs that
  *		have been registered. Nodes once added are not modified in this
  *		list.
  *		RCU usage: nodes are not modified in the list of device_opp,
  *		however addition is possible and is secured by dev_opp_list_lock
- * @dev:	device pointer
  * @srcu_head:	notifier head to notify the OPP availability changes.
  * @rcu_head:	RCU callback head used for deferred freeing
+ * @dev_list:	list of devices that share these OPPs
  * @opp_list:	list of opps
+ * @np:		struct device_node pointer for opp's DT node.
+ * @shared_opp: OPP is shared between multiple devices.
  *
  * This is an internal data structure maintaining the link to opps attached to
  * a device. This structure is not meant to be shared to users as it is
@@ -108,12 +125,14 @@ struct dev_pm_opp {
 struct device_opp {
 	struct list_head node;
 
-	struct device *dev;
 	struct srcu_notifier_head srcu_head;
 	struct rcu_head rcu_head;
+	struct list_head dev_list;
 	struct list_head opp_list;
 
+	struct device_node *np;
 	unsigned long clock_latency_ns_max;
+	bool shared_opp;
 };
 
 /*
@@ -133,6 +152,38 @@ do {									\
 			   "dev_opp_list_lock protection");		\
 } while (0)
 
+static struct device_list_opp *_find_list_dev(const struct device *dev,
+					      struct device_opp *dev_opp)
+{
+	struct device_list_opp *list_dev;
+
+	list_for_each_entry(list_dev, &dev_opp->dev_list, node)
+		if (list_dev->dev == dev)
+			return list_dev;
+
+	return NULL;
+}
+
+static struct device_opp *_managed_opp(const struct device_node *np)
+{
+	struct device_opp *dev_opp;
+
+	list_for_each_entry_rcu(dev_opp, &dev_opp_list, node) {
+		if (dev_opp->np == np) {
+			/*
+			 * Multiple devices can point to the same OPP table and
+			 * so will have same node-pointer, np.
+			 *
+			 * But the OPPs will be considered as shared only if the
+			 * OPP table contains a "opp-shared" property.
+			 */
+			return dev_opp->shared_opp ? dev_opp : NULL;
+		}
+	}
+
+	return NULL;
+}
+
 /**
  * _find_device_opp() - find device_opp struct using device pointer
  * @dev:	device pointer used to lookup device OPPs
@@ -149,21 +200,18 @@ do {									\
  */
 static struct device_opp *_find_device_opp(struct device *dev)
 {
-	struct device_opp *tmp_dev_opp, *dev_opp = ERR_PTR(-ENODEV);
+	struct device_opp *dev_opp;
 
 	if (unlikely(IS_ERR_OR_NULL(dev))) {
 		pr_err("%s: Invalid parameters\n", __func__);
 		return ERR_PTR(-EINVAL);
 	}
 
-	list_for_each_entry_rcu(tmp_dev_opp, &dev_opp_list, node) {
-		if (tmp_dev_opp->dev == dev) {
-			dev_opp = tmp_dev_opp;
-			break;
-		}
-	}
+	list_for_each_entry_rcu(dev_opp, &dev_opp_list, node)
+		if (_find_list_dev(dev, dev_opp))
+			return dev_opp;
 
-	return dev_opp;
+	return ERR_PTR(-ENODEV);
 }
 
 /**
@@ -450,6 +498,39 @@ struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev,
 }
 EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_floor);
 
+/* List-dev Helpers */
+static void _kfree_list_dev_rcu(struct rcu_head *head)
+{
+	struct device_list_opp *list_dev;
+
+	list_dev = container_of(head, struct device_list_opp, rcu_head);
+	kfree_rcu(list_dev, rcu_head);
+}
+
+static void _remove_list_dev(struct device_list_opp *list_dev,
+			     struct device_opp *dev_opp)
+{
+	list_del(&list_dev->node);
+	call_srcu(&dev_opp->srcu_head.srcu, &list_dev->rcu_head,
+		  _kfree_list_dev_rcu);
+}
+
+static struct device_list_opp *_add_list_dev(const struct device *dev,
+					     struct device_opp *dev_opp)
+{
+	struct device_list_opp *list_dev;
+
+	list_dev = kzalloc(sizeof(*list_dev), GFP_KERNEL);
+	if (!list_dev)
+		return NULL;
+
+	/* Initialize list-dev */
+	list_dev->dev = dev;
+	list_add_rcu(&list_dev->node, &dev_opp->dev_list);
+
+	return list_dev;
+}
+
 /**
  * _add_device_opp() - Find device OPP table or allocate a new one
  * @dev:	device for which we do this operation
@@ -462,6 +543,7 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_floor);
 static struct device_opp *_add_device_opp(struct device *dev)
 {
 	struct device_opp *dev_opp;
+	struct device_list_opp *list_dev;
 
 	/* Check for existing list for 'dev' first */
 	dev_opp = _find_device_opp(dev);
@@ -476,7 +558,14 @@ static struct device_opp *_add_device_opp(struct device *dev)
 	if (!dev_opp)
 		return NULL;
 
-	dev_opp->dev = dev;
+	INIT_LIST_HEAD(&dev_opp->dev_list);
+
+	list_dev = _add_list_dev(dev, dev_opp);
+	if (!list_dev) {
+		kfree(dev_opp);
+		return NULL;
+	}
+
 	srcu_init_notifier_head(&dev_opp->srcu_head);
 	INIT_LIST_HEAD(&dev_opp->opp_list);
 
@@ -504,9 +593,19 @@ static void _kfree_device_rcu(struct rcu_head *head)
  */
 static void _remove_device_opp(struct device_opp *dev_opp)
 {
+	struct device_list_opp *list_dev;
+
 	if (!list_empty(&dev_opp->opp_list))
 		return;
 
+	list_dev = list_first_entry(&dev_opp->dev_list, struct device_list_opp,
+				    node);
+
+	_remove_list_dev(list_dev, dev_opp);
+
+	/* dev_list must be empty now */
+	WARN_ON(!list_empty(&dev_opp->dev_list));
+
 	list_del_rcu(&dev_opp->node);
 	call_srcu(&dev_opp->srcu_head.srcu, &dev_opp->rcu_head,
 		  _kfree_device_rcu);
@@ -616,7 +715,8 @@ static struct dev_pm_opp *_allocate_opp(struct device *dev,
 	return opp;
 }
 
-static int _opp_add(struct dev_pm_opp *new_opp, struct device_opp *dev_opp)
+static int _opp_add(struct device *dev, struct dev_pm_opp *new_opp,
+		    struct device_opp *dev_opp)
 {
 	struct dev_pm_opp *opp;
 	struct list_head *head = &dev_opp->opp_list;
@@ -639,7 +739,7 @@ static int _opp_add(struct dev_pm_opp *new_opp, struct device_opp *dev_opp)
 			break;
 
 		/* Duplicate OPPs */
-		dev_warn(dev_opp->dev, "%s: duplicate OPPs detected. Existing: freq: %lu, volt: %lu, enabled: %d. New: freq: %lu, volt: %lu, enabled: %d\n",
+		dev_warn(dev, "%s: duplicate OPPs detected. Existing: freq: %lu, volt: %lu, enabled: %d. New: freq: %lu, volt: %lu, enabled: %d\n",
 			 __func__, opp->rate, opp->u_volt, opp->available,
 			 new_opp->rate, new_opp->u_volt, new_opp->available);
 
@@ -702,7 +802,7 @@ static int _opp_add_dynamic(struct device *dev, unsigned long freq,
 	new_opp->available = true;
 	new_opp->dynamic = dynamic;
 
-	ret = _opp_add(new_opp, dev_opp);
+	ret = _opp_add(dev, new_opp, dev_opp);
 	if (ret)
 		goto free_opp;
 
@@ -819,7 +919,7 @@ static int _opp_add_static_v2(struct device *dev, struct device_node *np)
 
 	of_property_read_u32(np, "opp-microamp", (u32 *)&new_opp->u_amp);
 
-	ret = _opp_add(new_opp, dev_opp);
+	ret = _opp_add(dev, new_opp, dev_opp);
 	if (ret)
 		goto free_opp;
 
@@ -1052,6 +1152,9 @@ void of_free_opp_table(struct device *dev)
 	struct device_opp *dev_opp;
 	struct dev_pm_opp *opp, *tmp;
 
+	/* Hold our list modification lock here */
+	mutex_lock(&dev_opp_list_lock);
+
 	/* Check for existing list for 'dev' */
 	dev_opp = _find_device_opp(dev);
 	if (IS_ERR(dev_opp)) {
@@ -1062,18 +1165,21 @@ void of_free_opp_table(struct device *dev)
 			     IS_ERR_OR_NULL(dev) ?
 					"Invalid device" : dev_name(dev),
 			     error);
-		return;
+		goto unlock;
 	}
 
-	/* Hold our list modification lock here */
-	mutex_lock(&dev_opp_list_lock);
-
-	/* Free static OPPs */
-	list_for_each_entry_safe(opp, tmp, &dev_opp->opp_list, node) {
-		if (!opp->dynamic)
-			_opp_remove(dev_opp, opp, true);
+	/* Find if dev_opp manages a single device */
+	if (list_is_singular(&dev_opp->dev_list)) {
+		/* Free static OPPs */
+		list_for_each_entry_safe(opp, tmp, &dev_opp->opp_list, node) {
+			if (!opp->dynamic)
+				_opp_remove(dev_opp, opp, true);
+		}
+	} else {
+		_remove_list_dev(_find_list_dev(dev, dev_opp), dev_opp);
 	}
 
+unlock:
 	mutex_unlock(&dev_opp_list_lock);
 }
 EXPORT_SYMBOL_GPL(of_free_opp_table);
@@ -1099,6 +1205,7 @@ static int _of_init_opp_table_v2(struct device *dev,
 				 const struct property *prop)
 {
 	struct device_node *opp_np, *np;
+	struct device_opp *dev_opp;
 	int ret = 0, count = 0;
 
 	if (!prop->value)
@@ -1109,6 +1216,14 @@ static int _of_init_opp_table_v2(struct device *dev,
 	if (IS_ERR(opp_np))
 		return PTR_ERR(opp_np);
 
+	dev_opp = _managed_opp(opp_np);
+	if (dev_opp) {
+		/* OPPs are already managed */
+		if (!_add_list_dev(dev, dev_opp))
+			ret = -ENOMEM;
+		goto put_opp_np;
+	}
+
 	/* We have opp-list node now, iterate over it and add OPPs */
 	for_each_available_child_of_node(opp_np, np) {
 		count++;
@@ -1125,8 +1240,19 @@ static int _of_init_opp_table_v2(struct device *dev,
 	if (WARN_ON(!count))
 		goto put_opp_np;
 
-	if (ret)
+	if (!ret) {
+		if (!dev_opp) {
+			dev_opp = _find_device_opp(dev);
+			if (WARN_ON(!dev_opp))
+				goto put_opp_np;
+		}
+
+		dev_opp->np = opp_np;
+		dev_opp->shared_opp = of_property_read_bool(opp_np,
+							    "opp-shared");
+	} else {
 		of_free_opp_table(dev);
+	}
 
 put_opp_np:
 	of_node_put(opp_np);
-- 
2.4.0

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

* [PATCH V3 09/16] PM / OPP: Add OPP sharing information to OPP library
@ 2015-07-29 10:53   ` Viresh Kumar
  0 siblings, 0 replies; 92+ messages in thread
From: Viresh Kumar @ 2015-07-29 10:53 UTC (permalink / raw)
  To: linux-arm-kernel

An opp can be shared by multiple devices, for example its very common
for CPUs to share the OPPs, i.e. when they share clock/voltage rails.

This patch adds support of shared OPPs to the OPP library.

Instead of a single device, dev_opp will now contain a list of devices
that use it. It also senses if the device (we are trying to initialize
OPPs for) shares OPPs with a device added earlier and in that case we
update the list of devices managed by OPPs instead of duplicating OPPs
again.

The same infrastructure will be used for the old OPP bindings, with
later patches.

Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>
Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/base/power/opp.c | 174 ++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 150 insertions(+), 24 deletions(-)

diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c
index 8638204c457e..5d699e3ec136 100644
--- a/drivers/base/power/opp.c
+++ b/drivers/base/power/opp.c
@@ -86,16 +86,33 @@ struct dev_pm_opp {
 };
 
 /**
+ * struct device_list_opp - devices managed by 'struct device_opp'
+ * @node:	list node
+ * @dev:	device to which the struct object belongs
+ * @rcu_head:	RCU callback head used for deferred freeing
+ *
+ * This is an internal data structure maintaining the list of devices that are
+ * managed by 'struct device_opp'.
+ */
+struct device_list_opp {
+	struct list_head node;
+	const struct device *dev;
+	struct rcu_head rcu_head;
+};
+
+/**
  * struct device_opp - Device opp structure
  * @node:	list node - contains the devices with OPPs that
  *		have been registered. Nodes once added are not modified in this
  *		list.
  *		RCU usage: nodes are not modified in the list of device_opp,
  *		however addition is possible and is secured by dev_opp_list_lock
- * @dev:	device pointer
  * @srcu_head:	notifier head to notify the OPP availability changes.
  * @rcu_head:	RCU callback head used for deferred freeing
+ * @dev_list:	list of devices that share these OPPs
  * @opp_list:	list of opps
+ * @np:		struct device_node pointer for opp's DT node.
+ * @shared_opp: OPP is shared between multiple devices.
  *
  * This is an internal data structure maintaining the link to opps attached to
  * a device. This structure is not meant to be shared to users as it is
@@ -108,12 +125,14 @@ struct dev_pm_opp {
 struct device_opp {
 	struct list_head node;
 
-	struct device *dev;
 	struct srcu_notifier_head srcu_head;
 	struct rcu_head rcu_head;
+	struct list_head dev_list;
 	struct list_head opp_list;
 
+	struct device_node *np;
 	unsigned long clock_latency_ns_max;
+	bool shared_opp;
 };
 
 /*
@@ -133,6 +152,38 @@ do {									\
 			   "dev_opp_list_lock protection");		\
 } while (0)
 
+static struct device_list_opp *_find_list_dev(const struct device *dev,
+					      struct device_opp *dev_opp)
+{
+	struct device_list_opp *list_dev;
+
+	list_for_each_entry(list_dev, &dev_opp->dev_list, node)
+		if (list_dev->dev == dev)
+			return list_dev;
+
+	return NULL;
+}
+
+static struct device_opp *_managed_opp(const struct device_node *np)
+{
+	struct device_opp *dev_opp;
+
+	list_for_each_entry_rcu(dev_opp, &dev_opp_list, node) {
+		if (dev_opp->np == np) {
+			/*
+			 * Multiple devices can point to the same OPP table and
+			 * so will have same node-pointer, np.
+			 *
+			 * But the OPPs will be considered as shared only if the
+			 * OPP table contains a "opp-shared" property.
+			 */
+			return dev_opp->shared_opp ? dev_opp : NULL;
+		}
+	}
+
+	return NULL;
+}
+
 /**
  * _find_device_opp() - find device_opp struct using device pointer
  * @dev:	device pointer used to lookup device OPPs
@@ -149,21 +200,18 @@ do {									\
  */
 static struct device_opp *_find_device_opp(struct device *dev)
 {
-	struct device_opp *tmp_dev_opp, *dev_opp = ERR_PTR(-ENODEV);
+	struct device_opp *dev_opp;
 
 	if (unlikely(IS_ERR_OR_NULL(dev))) {
 		pr_err("%s: Invalid parameters\n", __func__);
 		return ERR_PTR(-EINVAL);
 	}
 
-	list_for_each_entry_rcu(tmp_dev_opp, &dev_opp_list, node) {
-		if (tmp_dev_opp->dev == dev) {
-			dev_opp = tmp_dev_opp;
-			break;
-		}
-	}
+	list_for_each_entry_rcu(dev_opp, &dev_opp_list, node)
+		if (_find_list_dev(dev, dev_opp))
+			return dev_opp;
 
-	return dev_opp;
+	return ERR_PTR(-ENODEV);
 }
 
 /**
@@ -450,6 +498,39 @@ struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev,
 }
 EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_floor);
 
+/* List-dev Helpers */
+static void _kfree_list_dev_rcu(struct rcu_head *head)
+{
+	struct device_list_opp *list_dev;
+
+	list_dev = container_of(head, struct device_list_opp, rcu_head);
+	kfree_rcu(list_dev, rcu_head);
+}
+
+static void _remove_list_dev(struct device_list_opp *list_dev,
+			     struct device_opp *dev_opp)
+{
+	list_del(&list_dev->node);
+	call_srcu(&dev_opp->srcu_head.srcu, &list_dev->rcu_head,
+		  _kfree_list_dev_rcu);
+}
+
+static struct device_list_opp *_add_list_dev(const struct device *dev,
+					     struct device_opp *dev_opp)
+{
+	struct device_list_opp *list_dev;
+
+	list_dev = kzalloc(sizeof(*list_dev), GFP_KERNEL);
+	if (!list_dev)
+		return NULL;
+
+	/* Initialize list-dev */
+	list_dev->dev = dev;
+	list_add_rcu(&list_dev->node, &dev_opp->dev_list);
+
+	return list_dev;
+}
+
 /**
  * _add_device_opp() - Find device OPP table or allocate a new one
  * @dev:	device for which we do this operation
@@ -462,6 +543,7 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_floor);
 static struct device_opp *_add_device_opp(struct device *dev)
 {
 	struct device_opp *dev_opp;
+	struct device_list_opp *list_dev;
 
 	/* Check for existing list for 'dev' first */
 	dev_opp = _find_device_opp(dev);
@@ -476,7 +558,14 @@ static struct device_opp *_add_device_opp(struct device *dev)
 	if (!dev_opp)
 		return NULL;
 
-	dev_opp->dev = dev;
+	INIT_LIST_HEAD(&dev_opp->dev_list);
+
+	list_dev = _add_list_dev(dev, dev_opp);
+	if (!list_dev) {
+		kfree(dev_opp);
+		return NULL;
+	}
+
 	srcu_init_notifier_head(&dev_opp->srcu_head);
 	INIT_LIST_HEAD(&dev_opp->opp_list);
 
@@ -504,9 +593,19 @@ static void _kfree_device_rcu(struct rcu_head *head)
  */
 static void _remove_device_opp(struct device_opp *dev_opp)
 {
+	struct device_list_opp *list_dev;
+
 	if (!list_empty(&dev_opp->opp_list))
 		return;
 
+	list_dev = list_first_entry(&dev_opp->dev_list, struct device_list_opp,
+				    node);
+
+	_remove_list_dev(list_dev, dev_opp);
+
+	/* dev_list must be empty now */
+	WARN_ON(!list_empty(&dev_opp->dev_list));
+
 	list_del_rcu(&dev_opp->node);
 	call_srcu(&dev_opp->srcu_head.srcu, &dev_opp->rcu_head,
 		  _kfree_device_rcu);
@@ -616,7 +715,8 @@ static struct dev_pm_opp *_allocate_opp(struct device *dev,
 	return opp;
 }
 
-static int _opp_add(struct dev_pm_opp *new_opp, struct device_opp *dev_opp)
+static int _opp_add(struct device *dev, struct dev_pm_opp *new_opp,
+		    struct device_opp *dev_opp)
 {
 	struct dev_pm_opp *opp;
 	struct list_head *head = &dev_opp->opp_list;
@@ -639,7 +739,7 @@ static int _opp_add(struct dev_pm_opp *new_opp, struct device_opp *dev_opp)
 			break;
 
 		/* Duplicate OPPs */
-		dev_warn(dev_opp->dev, "%s: duplicate OPPs detected. Existing: freq: %lu, volt: %lu, enabled: %d. New: freq: %lu, volt: %lu, enabled: %d\n",
+		dev_warn(dev, "%s: duplicate OPPs detected. Existing: freq: %lu, volt: %lu, enabled: %d. New: freq: %lu, volt: %lu, enabled: %d\n",
 			 __func__, opp->rate, opp->u_volt, opp->available,
 			 new_opp->rate, new_opp->u_volt, new_opp->available);
 
@@ -702,7 +802,7 @@ static int _opp_add_dynamic(struct device *dev, unsigned long freq,
 	new_opp->available = true;
 	new_opp->dynamic = dynamic;
 
-	ret = _opp_add(new_opp, dev_opp);
+	ret = _opp_add(dev, new_opp, dev_opp);
 	if (ret)
 		goto free_opp;
 
@@ -819,7 +919,7 @@ static int _opp_add_static_v2(struct device *dev, struct device_node *np)
 
 	of_property_read_u32(np, "opp-microamp", (u32 *)&new_opp->u_amp);
 
-	ret = _opp_add(new_opp, dev_opp);
+	ret = _opp_add(dev, new_opp, dev_opp);
 	if (ret)
 		goto free_opp;
 
@@ -1052,6 +1152,9 @@ void of_free_opp_table(struct device *dev)
 	struct device_opp *dev_opp;
 	struct dev_pm_opp *opp, *tmp;
 
+	/* Hold our list modification lock here */
+	mutex_lock(&dev_opp_list_lock);
+
 	/* Check for existing list for 'dev' */
 	dev_opp = _find_device_opp(dev);
 	if (IS_ERR(dev_opp)) {
@@ -1062,18 +1165,21 @@ void of_free_opp_table(struct device *dev)
 			     IS_ERR_OR_NULL(dev) ?
 					"Invalid device" : dev_name(dev),
 			     error);
-		return;
+		goto unlock;
 	}
 
-	/* Hold our list modification lock here */
-	mutex_lock(&dev_opp_list_lock);
-
-	/* Free static OPPs */
-	list_for_each_entry_safe(opp, tmp, &dev_opp->opp_list, node) {
-		if (!opp->dynamic)
-			_opp_remove(dev_opp, opp, true);
+	/* Find if dev_opp manages a single device */
+	if (list_is_singular(&dev_opp->dev_list)) {
+		/* Free static OPPs */
+		list_for_each_entry_safe(opp, tmp, &dev_opp->opp_list, node) {
+			if (!opp->dynamic)
+				_opp_remove(dev_opp, opp, true);
+		}
+	} else {
+		_remove_list_dev(_find_list_dev(dev, dev_opp), dev_opp);
 	}
 
+unlock:
 	mutex_unlock(&dev_opp_list_lock);
 }
 EXPORT_SYMBOL_GPL(of_free_opp_table);
@@ -1099,6 +1205,7 @@ static int _of_init_opp_table_v2(struct device *dev,
 				 const struct property *prop)
 {
 	struct device_node *opp_np, *np;
+	struct device_opp *dev_opp;
 	int ret = 0, count = 0;
 
 	if (!prop->value)
@@ -1109,6 +1216,14 @@ static int _of_init_opp_table_v2(struct device *dev,
 	if (IS_ERR(opp_np))
 		return PTR_ERR(opp_np);
 
+	dev_opp = _managed_opp(opp_np);
+	if (dev_opp) {
+		/* OPPs are already managed */
+		if (!_add_list_dev(dev, dev_opp))
+			ret = -ENOMEM;
+		goto put_opp_np;
+	}
+
 	/* We have opp-list node now, iterate over it and add OPPs */
 	for_each_available_child_of_node(opp_np, np) {
 		count++;
@@ -1125,8 +1240,19 @@ static int _of_init_opp_table_v2(struct device *dev,
 	if (WARN_ON(!count))
 		goto put_opp_np;
 
-	if (ret)
+	if (!ret) {
+		if (!dev_opp) {
+			dev_opp = _find_device_opp(dev);
+			if (WARN_ON(!dev_opp))
+				goto put_opp_np;
+		}
+
+		dev_opp->np = opp_np;
+		dev_opp->shared_opp = of_property_read_bool(opp_np,
+							    "opp-shared");
+	} else {
 		of_free_opp_table(dev);
+	}
 
 put_opp_np:
 	of_node_put(opp_np);
-- 
2.4.0

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

* [PATCH V3 10/16] PM / OPP: Add support for opp-suspend
  2015-07-29 10:52 ` Viresh Kumar
  (?)
@ 2015-07-29 10:53   ` Viresh Kumar
  -1 siblings, 0 replies; 92+ messages in thread
From: Viresh Kumar @ 2015-07-29 10:53 UTC (permalink / raw)
  To: Rafael Wysocki, sboyd
  Cc: linaro-kernel, linux-pm, rob.herring, arnd.bergmann, nm, broonie,
	mturquette, Sudeep.Holla, viswanath.puttagunta, l.stach,
	thomas.petazzoni, linux-arm-kernel, ta.omasab, kesavan.abhilash,
	khilman, santosh.shilimkar, b.zolnierkie, Viresh Kumar,
	Greg Kroah-Hartman, Len Brown, open list, Pavel Machek

With "operating-points-v2" bindings, its possible to specify the OPP to
which the device must be switched, before suspending.

This patch adds support for getting that information.

Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/base/power/opp.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c
index 5d699e3ec136..0ebcea49145a 100644
--- a/drivers/base/power/opp.c
+++ b/drivers/base/power/opp.c
@@ -133,6 +133,7 @@ struct device_opp {
 	struct device_node *np;
 	unsigned long clock_latency_ns_max;
 	bool shared_opp;
+	struct dev_pm_opp *suspend_opp;
 };
 
 /*
@@ -923,6 +924,16 @@ static int _opp_add_static_v2(struct device *dev, struct device_node *np)
 	if (ret)
 		goto free_opp;
 
+	/* OPP to select on device suspend */
+	if (of_property_read_bool(np, "opp-suspend")) {
+		if (dev_opp->suspend_opp)
+			dev_warn(dev, "%s: Multiple suspend OPPs found (%lu %lu)\n",
+				 __func__, dev_opp->suspend_opp->rate,
+				 new_opp->rate);
+		else
+			dev_opp->suspend_opp = new_opp;
+	}
+
 	if (new_opp->clock_latency_ns > dev_opp->clock_latency_ns_max)
 		dev_opp->clock_latency_ns_max = new_opp->clock_latency_ns;
 
-- 
2.4.0


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

* [PATCH V3 10/16] PM / OPP: Add support for opp-suspend
@ 2015-07-29 10:53   ` Viresh Kumar
  0 siblings, 0 replies; 92+ messages in thread
From: Viresh Kumar @ 2015-07-29 10:53 UTC (permalink / raw)
  To: Rafael Wysocki, sboyd
  Cc: linaro-kernel, linux-pm, rob.herring, arnd.bergmann, nm, broonie,
	mturquette, Sudeep.Holla, viswanath.puttagunta, l.stach,
	thomas.petazzoni, linux-arm-kernel, ta.omasab, kesavan.abhilash,
	khilman, santosh.shilimkar, b.zolnierkie, Viresh Kumar,
	Greg Kroah-Hartman, Len Brown, open list, Pavel Machek

With "operating-points-v2" bindings, its possible to specify the OPP to
which the device must be switched, before suspending.

This patch adds support for getting that information.

Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/base/power/opp.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c
index 5d699e3ec136..0ebcea49145a 100644
--- a/drivers/base/power/opp.c
+++ b/drivers/base/power/opp.c
@@ -133,6 +133,7 @@ struct device_opp {
 	struct device_node *np;
 	unsigned long clock_latency_ns_max;
 	bool shared_opp;
+	struct dev_pm_opp *suspend_opp;
 };
 
 /*
@@ -923,6 +924,16 @@ static int _opp_add_static_v2(struct device *dev, struct device_node *np)
 	if (ret)
 		goto free_opp;
 
+	/* OPP to select on device suspend */
+	if (of_property_read_bool(np, "opp-suspend")) {
+		if (dev_opp->suspend_opp)
+			dev_warn(dev, "%s: Multiple suspend OPPs found (%lu %lu)\n",
+				 __func__, dev_opp->suspend_opp->rate,
+				 new_opp->rate);
+		else
+			dev_opp->suspend_opp = new_opp;
+	}
+
 	if (new_opp->clock_latency_ns > dev_opp->clock_latency_ns_max)
 		dev_opp->clock_latency_ns_max = new_opp->clock_latency_ns;
 
-- 
2.4.0

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

* [PATCH V3 10/16] PM / OPP: Add support for opp-suspend
@ 2015-07-29 10:53   ` Viresh Kumar
  0 siblings, 0 replies; 92+ messages in thread
From: Viresh Kumar @ 2015-07-29 10:53 UTC (permalink / raw)
  To: linux-arm-kernel

With "operating-points-v2" bindings, its possible to specify the OPP to
which the device must be switched, before suspending.

This patch adds support for getting that information.

Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/base/power/opp.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c
index 5d699e3ec136..0ebcea49145a 100644
--- a/drivers/base/power/opp.c
+++ b/drivers/base/power/opp.c
@@ -133,6 +133,7 @@ struct device_opp {
 	struct device_node *np;
 	unsigned long clock_latency_ns_max;
 	bool shared_opp;
+	struct dev_pm_opp *suspend_opp;
 };
 
 /*
@@ -923,6 +924,16 @@ static int _opp_add_static_v2(struct device *dev, struct device_node *np)
 	if (ret)
 		goto free_opp;
 
+	/* OPP to select on device suspend */
+	if (of_property_read_bool(np, "opp-suspend")) {
+		if (dev_opp->suspend_opp)
+			dev_warn(dev, "%s: Multiple suspend OPPs found (%lu %lu)\n",
+				 __func__, dev_opp->suspend_opp->rate,
+				 new_opp->rate);
+		else
+			dev_opp->suspend_opp = new_opp;
+	}
+
 	if (new_opp->clock_latency_ns > dev_opp->clock_latency_ns_max)
 		dev_opp->clock_latency_ns_max = new_opp->clock_latency_ns;
 
-- 
2.4.0

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

* [PATCH V3 11/16] PM / OPP: Add helpers for initializing CPU OPPs
  2015-07-29 10:52 ` Viresh Kumar
  (?)
@ 2015-07-29 10:53   ` Viresh Kumar
  -1 siblings, 0 replies; 92+ messages in thread
From: Viresh Kumar @ 2015-07-29 10:53 UTC (permalink / raw)
  To: Rafael Wysocki, sboyd
  Cc: linaro-kernel, linux-pm, rob.herring, arnd.bergmann, nm, broonie,
	mturquette, Sudeep.Holla, viswanath.puttagunta, l.stach,
	thomas.petazzoni, linux-arm-kernel, ta.omasab, kesavan.abhilash,
	khilman, santosh.shilimkar, b.zolnierkie, Viresh Kumar,
	Greg Kroah-Hartman, Len Brown, open list, Pavel Machek

With "operating-points-v2" its possible to tell which devices share
OPPs. We already have infrastructure to decode that information.

This patch adds following APIs:
- of_get_cpus_sharing_opps: Returns cpumask of CPUs sharing OPPs (only
  valid with v2 bindings).
- of_cpumask_init_opp_table: Initializes OPPs for all CPUs present in
  cpumask.
- of_cpumask_free_opp_table: Frees OPPs for all CPUs present in cpumask.

- set_cpus_sharing_opps: Sets which CPUs share OPPs (only valid with old
  OPP bindings, as this information isn't present in DT).

Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/base/power/opp.c | 175 +++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/pm_opp.h   |  23 +++++++
 2 files changed, 198 insertions(+)

diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c
index 0ebcea49145a..9bc4e7c21deb 100644
--- a/drivers/base/power/opp.c
+++ b/drivers/base/power/opp.c
@@ -11,6 +11,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/cpu.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/err.h>
@@ -1195,6 +1196,26 @@ void of_free_opp_table(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(of_free_opp_table);
 
+void of_cpumask_free_opp_table(cpumask_var_t cpumask)
+{
+	struct device *cpu_dev;
+	int cpu;
+
+	WARN_ON(cpumask_empty(cpumask));
+
+	for_each_cpu(cpu, cpumask) {
+		cpu_dev = get_cpu_device(cpu);
+		if (!cpu_dev) {
+			pr_err("%s: failed to get cpu%d device\n", __func__,
+			       cpu);
+			continue;
+		}
+
+		of_free_opp_table(cpu_dev);
+	}
+}
+EXPORT_SYMBOL_GPL(of_cpumask_free_opp_table);
+
 /* Returns opp descriptor node from its phandle. Caller must do of_node_put() */
 static struct device_node *
 _of_get_opp_desc_node_from_prop(struct device *dev, const struct property *prop)
@@ -1211,6 +1232,31 @@ _of_get_opp_desc_node_from_prop(struct device *dev, const struct property *prop)
 	return opp_np;
 }
 
+/* Returns opp descriptor node for a device. Caller must do of_node_put() */
+static struct device_node *_of_get_opp_desc_node(struct device *dev)
+{
+	const struct property *prop;
+
+	prop = of_find_property(dev->of_node, "operating-points-v2", NULL);
+	if (!prop)
+		return ERR_PTR(-ENODEV);
+	if (!prop->value)
+		return ERR_PTR(-ENODATA);
+
+	/*
+	 * TODO: Support for multiple OPP tables.
+	 *
+	 * There should be only ONE phandle present in "operating-points-v2"
+	 * property.
+	 */
+	if (prop->length != sizeof(__be32)) {
+		dev_err(dev, "%s: Invalid opp desc phandle\n", __func__);
+		return ERR_PTR(-EINVAL);
+	}
+
+	return _of_get_opp_desc_node_from_prop(dev, prop);
+}
+
 /* Initializes OPP tables based on new bindings */
 static int _of_init_opp_table_v2(struct device *dev,
 				 const struct property *prop)
@@ -1351,4 +1397,133 @@ int of_init_opp_table(struct device *dev)
 	return _of_init_opp_table_v2(dev, prop);
 }
 EXPORT_SYMBOL_GPL(of_init_opp_table);
+
+int of_cpumask_init_opp_table(cpumask_var_t cpumask)
+{
+	struct device *cpu_dev;
+	int cpu, ret = 0;
+
+	WARN_ON(cpumask_empty(cpumask));
+
+	for_each_cpu(cpu, cpumask) {
+		cpu_dev = get_cpu_device(cpu);
+		if (!cpu_dev) {
+			pr_err("%s: failed to get cpu%d device\n", __func__,
+			       cpu);
+			continue;
+		}
+
+		ret = of_init_opp_table(cpu_dev);
+		if (ret) {
+			pr_err("%s: couldn't find opp table for cpu:%d, %d\n",
+			       __func__, cpu, ret);
+
+			/* Free all other OPPs */
+			of_cpumask_free_opp_table(cpumask);
+			break;
+		}
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(of_cpumask_init_opp_table);
+
+/* Required only for V1 bindings, as v2 can manage it from DT itself */
+int set_cpus_sharing_opps(struct device *cpu_dev, cpumask_var_t cpumask)
+{
+	struct device_list_opp *list_dev;
+	struct device_opp *dev_opp;
+	struct device *dev;
+	int cpu, ret = 0;
+
+	rcu_read_lock();
+
+	dev_opp = _find_device_opp(cpu_dev);
+	if (IS_ERR(dev_opp)) {
+		ret = -EINVAL;
+		goto out_rcu_read_unlock;
+	}
+
+	for_each_cpu(cpu, cpumask) {
+		if (cpu == cpu_dev->id)
+			continue;
+
+		dev = get_cpu_device(cpu);
+		if (!dev) {
+			dev_err(cpu_dev, "%s: failed to get cpu%d device\n",
+				__func__, cpu);
+			continue;
+		}
+
+		list_dev = _add_list_dev(dev, dev_opp);
+		if (!list_dev) {
+			dev_err(dev, "%s: failed to add list-dev for cpu%d device\n",
+				__func__, cpu);
+			continue;
+		}
+	}
+out_rcu_read_unlock:
+	rcu_read_unlock();
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(set_cpus_sharing_opps);
+
+/*
+ * Works only for OPP v2 bindings.
+ *
+ * cpumask should be already set to mask of cpu_dev->id.
+ * Returns -ENOENT if operating-points-v2 bindings aren't supported.
+ */
+int of_get_cpus_sharing_opps(struct device *cpu_dev, cpumask_var_t cpumask)
+{
+	struct device_node *np, *tmp_np;
+	struct device *tcpu_dev;
+	int cpu, ret = 0;
+
+	/* Get OPP descriptor node */
+	np = _of_get_opp_desc_node(cpu_dev);
+	if (IS_ERR(np)) {
+		dev_dbg(cpu_dev, "%s: Couldn't find opp node: %ld\n", __func__,
+			PTR_ERR(np));
+		return -ENOENT;
+	}
+
+	/* OPPs are shared ? */
+	if (!of_get_property(np, "opp-shared", NULL))
+		goto put_cpu_node;
+
+	for_each_possible_cpu(cpu) {
+		if (cpu == cpu_dev->id)
+			continue;
+
+		tcpu_dev = get_cpu_device(cpu);
+		if (!tcpu_dev) {
+			dev_err(cpu_dev, "%s: failed to get cpu%d device\n",
+				__func__, cpu);
+			ret = -ENODEV;
+			goto put_cpu_node;
+		}
+
+		/* Get OPP descriptor node */
+		tmp_np = _of_get_opp_desc_node(tcpu_dev);
+		if (IS_ERR(tmp_np)) {
+			dev_info(tcpu_dev, "%s: Couldn't find opp node: %ld\n",
+				 __func__, PTR_ERR(tmp_np));
+			ret = -EINVAL;
+			goto put_cpu_node;
+		}
+
+		/* CPUs are sharing opp node */
+		if (np == tmp_np)
+			cpumask_set_cpu(cpu, cpumask);
+
+		of_node_put(tmp_np);
+	}
+
+put_cpu_node:
+	of_node_put(np);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(of_get_cpus_sharing_opps);
 #endif
diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h
index 20324b579adc..bb52fae5b921 100644
--- a/include/linux/pm_opp.h
+++ b/include/linux/pm_opp.h
@@ -121,6 +121,10 @@ static inline struct srcu_notifier_head *dev_pm_opp_get_notifier(
 #if defined(CONFIG_PM_OPP) && defined(CONFIG_OF)
 int of_init_opp_table(struct device *dev);
 void of_free_opp_table(struct device *dev);
+int of_cpumask_init_opp_table(cpumask_var_t cpumask);
+void of_cpumask_free_opp_table(cpumask_var_t cpumask);
+int of_get_cpus_sharing_opps(struct device *cpu_dev, cpumask_var_t cpumask);
+int set_cpus_sharing_opps(struct device *cpu_dev, cpumask_var_t cpumask);
 #else
 static inline int of_init_opp_table(struct device *dev)
 {
@@ -130,6 +134,25 @@ static inline int of_init_opp_table(struct device *dev)
 static inline void of_free_opp_table(struct device *dev)
 {
 }
+
+static inline int of_cpumask_init_opp_table(cpumask_var_t cpumask)
+{
+	return -ENOSYS;
+}
+
+static inline void of_cpumask_free_opp_table(cpumask_var_t cpumask)
+{
+}
+
+static inline int of_get_cpus_sharing_opps(struct device *cpu_dev, cpumask_var_t cpumask)
+{
+	return -ENOSYS;
+}
+
+static inline int set_cpus_sharing_opps(struct device *cpu_dev, cpumask_var_t cpumask)
+{
+	return -ENOSYS;
+}
 #endif
 
 #endif		/* __LINUX_OPP_H__ */
-- 
2.4.0


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

* [PATCH V3 11/16] PM / OPP: Add helpers for initializing CPU OPPs
@ 2015-07-29 10:53   ` Viresh Kumar
  0 siblings, 0 replies; 92+ messages in thread
From: Viresh Kumar @ 2015-07-29 10:53 UTC (permalink / raw)
  To: Rafael Wysocki, sboyd
  Cc: linaro-kernel, linux-pm, rob.herring, arnd.bergmann, nm, broonie,
	mturquette, Sudeep.Holla, viswanath.puttagunta, l.stach,
	thomas.petazzoni, linux-arm-kernel, ta.omasab, kesavan.abhilash,
	khilman, santosh.shilimkar, b.zolnierkie, Viresh Kumar,
	Greg Kroah-Hartman, Len Brown, open list, Pavel Machek

With "operating-points-v2" its possible to tell which devices share
OPPs. We already have infrastructure to decode that information.

This patch adds following APIs:
- of_get_cpus_sharing_opps: Returns cpumask of CPUs sharing OPPs (only
  valid with v2 bindings).
- of_cpumask_init_opp_table: Initializes OPPs for all CPUs present in
  cpumask.
- of_cpumask_free_opp_table: Frees OPPs for all CPUs present in cpumask.

- set_cpus_sharing_opps: Sets which CPUs share OPPs (only valid with old
  OPP bindings, as this information isn't present in DT).

Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/base/power/opp.c | 175 +++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/pm_opp.h   |  23 +++++++
 2 files changed, 198 insertions(+)

diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c
index 0ebcea49145a..9bc4e7c21deb 100644
--- a/drivers/base/power/opp.c
+++ b/drivers/base/power/opp.c
@@ -11,6 +11,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/cpu.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/err.h>
@@ -1195,6 +1196,26 @@ void of_free_opp_table(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(of_free_opp_table);
 
+void of_cpumask_free_opp_table(cpumask_var_t cpumask)
+{
+	struct device *cpu_dev;
+	int cpu;
+
+	WARN_ON(cpumask_empty(cpumask));
+
+	for_each_cpu(cpu, cpumask) {
+		cpu_dev = get_cpu_device(cpu);
+		if (!cpu_dev) {
+			pr_err("%s: failed to get cpu%d device\n", __func__,
+			       cpu);
+			continue;
+		}
+
+		of_free_opp_table(cpu_dev);
+	}
+}
+EXPORT_SYMBOL_GPL(of_cpumask_free_opp_table);
+
 /* Returns opp descriptor node from its phandle. Caller must do of_node_put() */
 static struct device_node *
 _of_get_opp_desc_node_from_prop(struct device *dev, const struct property *prop)
@@ -1211,6 +1232,31 @@ _of_get_opp_desc_node_from_prop(struct device *dev, const struct property *prop)
 	return opp_np;
 }
 
+/* Returns opp descriptor node for a device. Caller must do of_node_put() */
+static struct device_node *_of_get_opp_desc_node(struct device *dev)
+{
+	const struct property *prop;
+
+	prop = of_find_property(dev->of_node, "operating-points-v2", NULL);
+	if (!prop)
+		return ERR_PTR(-ENODEV);
+	if (!prop->value)
+		return ERR_PTR(-ENODATA);
+
+	/*
+	 * TODO: Support for multiple OPP tables.
+	 *
+	 * There should be only ONE phandle present in "operating-points-v2"
+	 * property.
+	 */
+	if (prop->length != sizeof(__be32)) {
+		dev_err(dev, "%s: Invalid opp desc phandle\n", __func__);
+		return ERR_PTR(-EINVAL);
+	}
+
+	return _of_get_opp_desc_node_from_prop(dev, prop);
+}
+
 /* Initializes OPP tables based on new bindings */
 static int _of_init_opp_table_v2(struct device *dev,
 				 const struct property *prop)
@@ -1351,4 +1397,133 @@ int of_init_opp_table(struct device *dev)
 	return _of_init_opp_table_v2(dev, prop);
 }
 EXPORT_SYMBOL_GPL(of_init_opp_table);
+
+int of_cpumask_init_opp_table(cpumask_var_t cpumask)
+{
+	struct device *cpu_dev;
+	int cpu, ret = 0;
+
+	WARN_ON(cpumask_empty(cpumask));
+
+	for_each_cpu(cpu, cpumask) {
+		cpu_dev = get_cpu_device(cpu);
+		if (!cpu_dev) {
+			pr_err("%s: failed to get cpu%d device\n", __func__,
+			       cpu);
+			continue;
+		}
+
+		ret = of_init_opp_table(cpu_dev);
+		if (ret) {
+			pr_err("%s: couldn't find opp table for cpu:%d, %d\n",
+			       __func__, cpu, ret);
+
+			/* Free all other OPPs */
+			of_cpumask_free_opp_table(cpumask);
+			break;
+		}
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(of_cpumask_init_opp_table);
+
+/* Required only for V1 bindings, as v2 can manage it from DT itself */
+int set_cpus_sharing_opps(struct device *cpu_dev, cpumask_var_t cpumask)
+{
+	struct device_list_opp *list_dev;
+	struct device_opp *dev_opp;
+	struct device *dev;
+	int cpu, ret = 0;
+
+	rcu_read_lock();
+
+	dev_opp = _find_device_opp(cpu_dev);
+	if (IS_ERR(dev_opp)) {
+		ret = -EINVAL;
+		goto out_rcu_read_unlock;
+	}
+
+	for_each_cpu(cpu, cpumask) {
+		if (cpu == cpu_dev->id)
+			continue;
+
+		dev = get_cpu_device(cpu);
+		if (!dev) {
+			dev_err(cpu_dev, "%s: failed to get cpu%d device\n",
+				__func__, cpu);
+			continue;
+		}
+
+		list_dev = _add_list_dev(dev, dev_opp);
+		if (!list_dev) {
+			dev_err(dev, "%s: failed to add list-dev for cpu%d device\n",
+				__func__, cpu);
+			continue;
+		}
+	}
+out_rcu_read_unlock:
+	rcu_read_unlock();
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(set_cpus_sharing_opps);
+
+/*
+ * Works only for OPP v2 bindings.
+ *
+ * cpumask should be already set to mask of cpu_dev->id.
+ * Returns -ENOENT if operating-points-v2 bindings aren't supported.
+ */
+int of_get_cpus_sharing_opps(struct device *cpu_dev, cpumask_var_t cpumask)
+{
+	struct device_node *np, *tmp_np;
+	struct device *tcpu_dev;
+	int cpu, ret = 0;
+
+	/* Get OPP descriptor node */
+	np = _of_get_opp_desc_node(cpu_dev);
+	if (IS_ERR(np)) {
+		dev_dbg(cpu_dev, "%s: Couldn't find opp node: %ld\n", __func__,
+			PTR_ERR(np));
+		return -ENOENT;
+	}
+
+	/* OPPs are shared ? */
+	if (!of_get_property(np, "opp-shared", NULL))
+		goto put_cpu_node;
+
+	for_each_possible_cpu(cpu) {
+		if (cpu == cpu_dev->id)
+			continue;
+
+		tcpu_dev = get_cpu_device(cpu);
+		if (!tcpu_dev) {
+			dev_err(cpu_dev, "%s: failed to get cpu%d device\n",
+				__func__, cpu);
+			ret = -ENODEV;
+			goto put_cpu_node;
+		}
+
+		/* Get OPP descriptor node */
+		tmp_np = _of_get_opp_desc_node(tcpu_dev);
+		if (IS_ERR(tmp_np)) {
+			dev_info(tcpu_dev, "%s: Couldn't find opp node: %ld\n",
+				 __func__, PTR_ERR(tmp_np));
+			ret = -EINVAL;
+			goto put_cpu_node;
+		}
+
+		/* CPUs are sharing opp node */
+		if (np == tmp_np)
+			cpumask_set_cpu(cpu, cpumask);
+
+		of_node_put(tmp_np);
+	}
+
+put_cpu_node:
+	of_node_put(np);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(of_get_cpus_sharing_opps);
 #endif
diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h
index 20324b579adc..bb52fae5b921 100644
--- a/include/linux/pm_opp.h
+++ b/include/linux/pm_opp.h
@@ -121,6 +121,10 @@ static inline struct srcu_notifier_head *dev_pm_opp_get_notifier(
 #if defined(CONFIG_PM_OPP) && defined(CONFIG_OF)
 int of_init_opp_table(struct device *dev);
 void of_free_opp_table(struct device *dev);
+int of_cpumask_init_opp_table(cpumask_var_t cpumask);
+void of_cpumask_free_opp_table(cpumask_var_t cpumask);
+int of_get_cpus_sharing_opps(struct device *cpu_dev, cpumask_var_t cpumask);
+int set_cpus_sharing_opps(struct device *cpu_dev, cpumask_var_t cpumask);
 #else
 static inline int of_init_opp_table(struct device *dev)
 {
@@ -130,6 +134,25 @@ static inline int of_init_opp_table(struct device *dev)
 static inline void of_free_opp_table(struct device *dev)
 {
 }
+
+static inline int of_cpumask_init_opp_table(cpumask_var_t cpumask)
+{
+	return -ENOSYS;
+}
+
+static inline void of_cpumask_free_opp_table(cpumask_var_t cpumask)
+{
+}
+
+static inline int of_get_cpus_sharing_opps(struct device *cpu_dev, cpumask_var_t cpumask)
+{
+	return -ENOSYS;
+}
+
+static inline int set_cpus_sharing_opps(struct device *cpu_dev, cpumask_var_t cpumask)
+{
+	return -ENOSYS;
+}
 #endif
 
 #endif		/* __LINUX_OPP_H__ */
-- 
2.4.0

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

* [PATCH V3 11/16] PM / OPP: Add helpers for initializing CPU OPPs
@ 2015-07-29 10:53   ` Viresh Kumar
  0 siblings, 0 replies; 92+ messages in thread
From: Viresh Kumar @ 2015-07-29 10:53 UTC (permalink / raw)
  To: linux-arm-kernel

With "operating-points-v2" its possible to tell which devices share
OPPs. We already have infrastructure to decode that information.

This patch adds following APIs:
- of_get_cpus_sharing_opps: Returns cpumask of CPUs sharing OPPs (only
  valid with v2 bindings).
- of_cpumask_init_opp_table: Initializes OPPs for all CPUs present in
  cpumask.
- of_cpumask_free_opp_table: Frees OPPs for all CPUs present in cpumask.

- set_cpus_sharing_opps: Sets which CPUs share OPPs (only valid with old
  OPP bindings, as this information isn't present in DT).

Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/base/power/opp.c | 175 +++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/pm_opp.h   |  23 +++++++
 2 files changed, 198 insertions(+)

diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c
index 0ebcea49145a..9bc4e7c21deb 100644
--- a/drivers/base/power/opp.c
+++ b/drivers/base/power/opp.c
@@ -11,6 +11,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/cpu.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/err.h>
@@ -1195,6 +1196,26 @@ void of_free_opp_table(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(of_free_opp_table);
 
+void of_cpumask_free_opp_table(cpumask_var_t cpumask)
+{
+	struct device *cpu_dev;
+	int cpu;
+
+	WARN_ON(cpumask_empty(cpumask));
+
+	for_each_cpu(cpu, cpumask) {
+		cpu_dev = get_cpu_device(cpu);
+		if (!cpu_dev) {
+			pr_err("%s: failed to get cpu%d device\n", __func__,
+			       cpu);
+			continue;
+		}
+
+		of_free_opp_table(cpu_dev);
+	}
+}
+EXPORT_SYMBOL_GPL(of_cpumask_free_opp_table);
+
 /* Returns opp descriptor node from its phandle. Caller must do of_node_put() */
 static struct device_node *
 _of_get_opp_desc_node_from_prop(struct device *dev, const struct property *prop)
@@ -1211,6 +1232,31 @@ _of_get_opp_desc_node_from_prop(struct device *dev, const struct property *prop)
 	return opp_np;
 }
 
+/* Returns opp descriptor node for a device. Caller must do of_node_put() */
+static struct device_node *_of_get_opp_desc_node(struct device *dev)
+{
+	const struct property *prop;
+
+	prop = of_find_property(dev->of_node, "operating-points-v2", NULL);
+	if (!prop)
+		return ERR_PTR(-ENODEV);
+	if (!prop->value)
+		return ERR_PTR(-ENODATA);
+
+	/*
+	 * TODO: Support for multiple OPP tables.
+	 *
+	 * There should be only ONE phandle present in "operating-points-v2"
+	 * property.
+	 */
+	if (prop->length != sizeof(__be32)) {
+		dev_err(dev, "%s: Invalid opp desc phandle\n", __func__);
+		return ERR_PTR(-EINVAL);
+	}
+
+	return _of_get_opp_desc_node_from_prop(dev, prop);
+}
+
 /* Initializes OPP tables based on new bindings */
 static int _of_init_opp_table_v2(struct device *dev,
 				 const struct property *prop)
@@ -1351,4 +1397,133 @@ int of_init_opp_table(struct device *dev)
 	return _of_init_opp_table_v2(dev, prop);
 }
 EXPORT_SYMBOL_GPL(of_init_opp_table);
+
+int of_cpumask_init_opp_table(cpumask_var_t cpumask)
+{
+	struct device *cpu_dev;
+	int cpu, ret = 0;
+
+	WARN_ON(cpumask_empty(cpumask));
+
+	for_each_cpu(cpu, cpumask) {
+		cpu_dev = get_cpu_device(cpu);
+		if (!cpu_dev) {
+			pr_err("%s: failed to get cpu%d device\n", __func__,
+			       cpu);
+			continue;
+		}
+
+		ret = of_init_opp_table(cpu_dev);
+		if (ret) {
+			pr_err("%s: couldn't find opp table for cpu:%d, %d\n",
+			       __func__, cpu, ret);
+
+			/* Free all other OPPs */
+			of_cpumask_free_opp_table(cpumask);
+			break;
+		}
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(of_cpumask_init_opp_table);
+
+/* Required only for V1 bindings, as v2 can manage it from DT itself */
+int set_cpus_sharing_opps(struct device *cpu_dev, cpumask_var_t cpumask)
+{
+	struct device_list_opp *list_dev;
+	struct device_opp *dev_opp;
+	struct device *dev;
+	int cpu, ret = 0;
+
+	rcu_read_lock();
+
+	dev_opp = _find_device_opp(cpu_dev);
+	if (IS_ERR(dev_opp)) {
+		ret = -EINVAL;
+		goto out_rcu_read_unlock;
+	}
+
+	for_each_cpu(cpu, cpumask) {
+		if (cpu == cpu_dev->id)
+			continue;
+
+		dev = get_cpu_device(cpu);
+		if (!dev) {
+			dev_err(cpu_dev, "%s: failed to get cpu%d device\n",
+				__func__, cpu);
+			continue;
+		}
+
+		list_dev = _add_list_dev(dev, dev_opp);
+		if (!list_dev) {
+			dev_err(dev, "%s: failed to add list-dev for cpu%d device\n",
+				__func__, cpu);
+			continue;
+		}
+	}
+out_rcu_read_unlock:
+	rcu_read_unlock();
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(set_cpus_sharing_opps);
+
+/*
+ * Works only for OPP v2 bindings.
+ *
+ * cpumask should be already set to mask of cpu_dev->id.
+ * Returns -ENOENT if operating-points-v2 bindings aren't supported.
+ */
+int of_get_cpus_sharing_opps(struct device *cpu_dev, cpumask_var_t cpumask)
+{
+	struct device_node *np, *tmp_np;
+	struct device *tcpu_dev;
+	int cpu, ret = 0;
+
+	/* Get OPP descriptor node */
+	np = _of_get_opp_desc_node(cpu_dev);
+	if (IS_ERR(np)) {
+		dev_dbg(cpu_dev, "%s: Couldn't find opp node: %ld\n", __func__,
+			PTR_ERR(np));
+		return -ENOENT;
+	}
+
+	/* OPPs are shared ? */
+	if (!of_get_property(np, "opp-shared", NULL))
+		goto put_cpu_node;
+
+	for_each_possible_cpu(cpu) {
+		if (cpu == cpu_dev->id)
+			continue;
+
+		tcpu_dev = get_cpu_device(cpu);
+		if (!tcpu_dev) {
+			dev_err(cpu_dev, "%s: failed to get cpu%d device\n",
+				__func__, cpu);
+			ret = -ENODEV;
+			goto put_cpu_node;
+		}
+
+		/* Get OPP descriptor node */
+		tmp_np = _of_get_opp_desc_node(tcpu_dev);
+		if (IS_ERR(tmp_np)) {
+			dev_info(tcpu_dev, "%s: Couldn't find opp node: %ld\n",
+				 __func__, PTR_ERR(tmp_np));
+			ret = -EINVAL;
+			goto put_cpu_node;
+		}
+
+		/* CPUs are sharing opp node */
+		if (np == tmp_np)
+			cpumask_set_cpu(cpu, cpumask);
+
+		of_node_put(tmp_np);
+	}
+
+put_cpu_node:
+	of_node_put(np);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(of_get_cpus_sharing_opps);
 #endif
diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h
index 20324b579adc..bb52fae5b921 100644
--- a/include/linux/pm_opp.h
+++ b/include/linux/pm_opp.h
@@ -121,6 +121,10 @@ static inline struct srcu_notifier_head *dev_pm_opp_get_notifier(
 #if defined(CONFIG_PM_OPP) && defined(CONFIG_OF)
 int of_init_opp_table(struct device *dev);
 void of_free_opp_table(struct device *dev);
+int of_cpumask_init_opp_table(cpumask_var_t cpumask);
+void of_cpumask_free_opp_table(cpumask_var_t cpumask);
+int of_get_cpus_sharing_opps(struct device *cpu_dev, cpumask_var_t cpumask);
+int set_cpus_sharing_opps(struct device *cpu_dev, cpumask_var_t cpumask);
 #else
 static inline int of_init_opp_table(struct device *dev)
 {
@@ -130,6 +134,25 @@ static inline int of_init_opp_table(struct device *dev)
 static inline void of_free_opp_table(struct device *dev)
 {
 }
+
+static inline int of_cpumask_init_opp_table(cpumask_var_t cpumask)
+{
+	return -ENOSYS;
+}
+
+static inline void of_cpumask_free_opp_table(cpumask_var_t cpumask)
+{
+}
+
+static inline int of_get_cpus_sharing_opps(struct device *cpu_dev, cpumask_var_t cpumask)
+{
+	return -ENOSYS;
+}
+
+static inline int set_cpus_sharing_opps(struct device *cpu_dev, cpumask_var_t cpumask)
+{
+	return -ENOSYS;
+}
 #endif
 
 #endif		/* __LINUX_OPP_H__ */
-- 
2.4.0

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

* [PATCH V3 12/16] PM / OPP: add dev_pm_opp_is_turbo() helper
  2015-07-29 10:52 ` Viresh Kumar
  (?)
@ 2015-07-29 10:53   ` Viresh Kumar
  -1 siblings, 0 replies; 92+ messages in thread
From: Viresh Kumar @ 2015-07-29 10:53 UTC (permalink / raw)
  To: Rafael Wysocki, sboyd
  Cc: linaro-kernel, linux-pm, rob.herring, arnd.bergmann, nm, broonie,
	mturquette, Sudeep.Holla, viswanath.puttagunta, l.stach,
	thomas.petazzoni, linux-arm-kernel, ta.omasab, kesavan.abhilash,
	khilman, santosh.shilimkar, b.zolnierkie, Tomasz Figa,
	Javier Martinez Canillas, Thomas Abraham, Viresh Kumar,
	Greg Kroah-Hartman, Len Brown, open list, Pavel Machek

From: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>

Add dev_pm_opp_is_turbo() helper to verify if an opp is to be used only
for turbo mode or not.

Cc: Tomasz Figa <tomasz.figa@gmail.com>
Cc: Michael Turquette <mturquette@baylibre.com>
Cc: Javier Martinez Canillas <javier@dowhile0.org>
Cc: Thomas Abraham <thomas.ab@samsung.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/base/power/opp.c | 34 ++++++++++++++++++++++++++++++++++
 include/linux/pm_opp.h   |  7 +++++++
 2 files changed, 41 insertions(+)

diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c
index 9bc4e7c21deb..da8ec7f824d5 100644
--- a/drivers/base/power/opp.c
+++ b/drivers/base/power/opp.c
@@ -281,6 +281,40 @@ unsigned long dev_pm_opp_get_freq(struct dev_pm_opp *opp)
 EXPORT_SYMBOL_GPL(dev_pm_opp_get_freq);
 
 /**
+ * dev_pm_opp_is_turbo() - Returns if opp is turbo OPP or not
+ * @opp: opp for which turbo mode is being verified
+ *
+ * Turbo OPPs are not for normal use, and can be enabled (under certain
+ * conditions) for short duration of times to finish high throughput work
+ * quickly. Running on them for longer times may overheat the chip.
+ *
+ * Return: true if opp is turbo opp, else false.
+ *
+ * Locking: This function must be called under rcu_read_lock(). opp is a rcu
+ * protected pointer. This means that opp which could have been fetched by
+ * opp_find_freq_{exact,ceil,floor} functions is valid as long as we are
+ * under RCU lock. The pointer returned by the opp_find_freq family must be
+ * used in the same section as the usage of this function with the pointer
+ * prior to unlocking with rcu_read_unlock() to maintain the integrity of the
+ * pointer.
+ */
+bool dev_pm_opp_is_turbo(struct dev_pm_opp *opp)
+{
+	struct dev_pm_opp *tmp_opp;
+
+	opp_rcu_lockdep_assert();
+
+	tmp_opp = rcu_dereference(opp);
+	if (unlikely(IS_ERR_OR_NULL(tmp_opp)) || !tmp_opp->available) {
+		pr_err("%s: Invalid parameters\n", __func__);
+		return false;
+	}
+
+	return tmp_opp->turbo;
+}
+EXPORT_SYMBOL_GPL(dev_pm_opp_is_turbo);
+
+/**
  * dev_pm_opp_get_max_clock_latency() - Get max clock latency in nanoseconds
  * @dev:	device for which we do this operation
  *
diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h
index bb52fae5b921..cab7ba55bedb 100644
--- a/include/linux/pm_opp.h
+++ b/include/linux/pm_opp.h
@@ -30,6 +30,8 @@ unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp);
 
 unsigned long dev_pm_opp_get_freq(struct dev_pm_opp *opp);
 
+bool dev_pm_opp_is_turbo(struct dev_pm_opp *opp);
+
 int dev_pm_opp_get_opp_count(struct device *dev);
 unsigned long dev_pm_opp_get_max_clock_latency(struct device *dev);
 
@@ -63,6 +65,11 @@ static inline unsigned long dev_pm_opp_get_freq(struct dev_pm_opp *opp)
 	return 0;
 }
 
+static inline bool dev_pm_opp_is_turbo(struct dev_pm_opp *opp)
+{
+	return false;
+}
+
 static inline int dev_pm_opp_get_opp_count(struct device *dev)
 {
 	return 0;
-- 
2.4.0


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

* [PATCH V3 12/16] PM / OPP: add dev_pm_opp_is_turbo() helper
@ 2015-07-29 10:53   ` Viresh Kumar
  0 siblings, 0 replies; 92+ messages in thread
From: Viresh Kumar @ 2015-07-29 10:53 UTC (permalink / raw)
  To: Rafael Wysocki, sboyd
  Cc: linaro-kernel, linux-pm, rob.herring, arnd.bergmann, nm, broonie,
	mturquette, Sudeep.Holla, viswanath.puttagunta, l.stach,
	thomas.petazzoni, linux-arm-kernel, ta.omasab, kesavan.abhilash,
	khilman, santosh.shilimkar, b.zolnierkie, Tomasz Figa,
	Javier Martinez Canillas, Thomas Abraham, Viresh Kumar,
	Greg Kroah-Hartman, Len Brown, open list, Pavel Machek

From: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>

Add dev_pm_opp_is_turbo() helper to verify if an opp is to be used only
for turbo mode or not.

Cc: Tomasz Figa <tomasz.figa@gmail.com>
Cc: Michael Turquette <mturquette@baylibre.com>
Cc: Javier Martinez Canillas <javier@dowhile0.org>
Cc: Thomas Abraham <thomas.ab@samsung.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/base/power/opp.c | 34 ++++++++++++++++++++++++++++++++++
 include/linux/pm_opp.h   |  7 +++++++
 2 files changed, 41 insertions(+)

diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c
index 9bc4e7c21deb..da8ec7f824d5 100644
--- a/drivers/base/power/opp.c
+++ b/drivers/base/power/opp.c
@@ -281,6 +281,40 @@ unsigned long dev_pm_opp_get_freq(struct dev_pm_opp *opp)
 EXPORT_SYMBOL_GPL(dev_pm_opp_get_freq);
 
 /**
+ * dev_pm_opp_is_turbo() - Returns if opp is turbo OPP or not
+ * @opp: opp for which turbo mode is being verified
+ *
+ * Turbo OPPs are not for normal use, and can be enabled (under certain
+ * conditions) for short duration of times to finish high throughput work
+ * quickly. Running on them for longer times may overheat the chip.
+ *
+ * Return: true if opp is turbo opp, else false.
+ *
+ * Locking: This function must be called under rcu_read_lock(). opp is a rcu
+ * protected pointer. This means that opp which could have been fetched by
+ * opp_find_freq_{exact,ceil,floor} functions is valid as long as we are
+ * under RCU lock. The pointer returned by the opp_find_freq family must be
+ * used in the same section as the usage of this function with the pointer
+ * prior to unlocking with rcu_read_unlock() to maintain the integrity of the
+ * pointer.
+ */
+bool dev_pm_opp_is_turbo(struct dev_pm_opp *opp)
+{
+	struct dev_pm_opp *tmp_opp;
+
+	opp_rcu_lockdep_assert();
+
+	tmp_opp = rcu_dereference(opp);
+	if (unlikely(IS_ERR_OR_NULL(tmp_opp)) || !tmp_opp->available) {
+		pr_err("%s: Invalid parameters\n", __func__);
+		return false;
+	}
+
+	return tmp_opp->turbo;
+}
+EXPORT_SYMBOL_GPL(dev_pm_opp_is_turbo);
+
+/**
  * dev_pm_opp_get_max_clock_latency() - Get max clock latency in nanoseconds
  * @dev:	device for which we do this operation
  *
diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h
index bb52fae5b921..cab7ba55bedb 100644
--- a/include/linux/pm_opp.h
+++ b/include/linux/pm_opp.h
@@ -30,6 +30,8 @@ unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp);
 
 unsigned long dev_pm_opp_get_freq(struct dev_pm_opp *opp);
 
+bool dev_pm_opp_is_turbo(struct dev_pm_opp *opp);
+
 int dev_pm_opp_get_opp_count(struct device *dev);
 unsigned long dev_pm_opp_get_max_clock_latency(struct device *dev);
 
@@ -63,6 +65,11 @@ static inline unsigned long dev_pm_opp_get_freq(struct dev_pm_opp *opp)
 	return 0;
 }
 
+static inline bool dev_pm_opp_is_turbo(struct dev_pm_opp *opp)
+{
+	return false;
+}
+
 static inline int dev_pm_opp_get_opp_count(struct device *dev)
 {
 	return 0;
-- 
2.4.0

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

* [PATCH V3 12/16] PM / OPP: add dev_pm_opp_is_turbo() helper
@ 2015-07-29 10:53   ` Viresh Kumar
  0 siblings, 0 replies; 92+ messages in thread
From: Viresh Kumar @ 2015-07-29 10:53 UTC (permalink / raw)
  To: linux-arm-kernel

From: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>

Add dev_pm_opp_is_turbo() helper to verify if an opp is to be used only
for turbo mode or not.

Cc: Tomasz Figa <tomasz.figa@gmail.com>
Cc: Michael Turquette <mturquette@baylibre.com>
Cc: Javier Martinez Canillas <javier@dowhile0.org>
Cc: Thomas Abraham <thomas.ab@samsung.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/base/power/opp.c | 34 ++++++++++++++++++++++++++++++++++
 include/linux/pm_opp.h   |  7 +++++++
 2 files changed, 41 insertions(+)

diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c
index 9bc4e7c21deb..da8ec7f824d5 100644
--- a/drivers/base/power/opp.c
+++ b/drivers/base/power/opp.c
@@ -281,6 +281,40 @@ unsigned long dev_pm_opp_get_freq(struct dev_pm_opp *opp)
 EXPORT_SYMBOL_GPL(dev_pm_opp_get_freq);
 
 /**
+ * dev_pm_opp_is_turbo() - Returns if opp is turbo OPP or not
+ * @opp: opp for which turbo mode is being verified
+ *
+ * Turbo OPPs are not for normal use, and can be enabled (under certain
+ * conditions) for short duration of times to finish high throughput work
+ * quickly. Running on them for longer times may overheat the chip.
+ *
+ * Return: true if opp is turbo opp, else false.
+ *
+ * Locking: This function must be called under rcu_read_lock(). opp is a rcu
+ * protected pointer. This means that opp which could have been fetched by
+ * opp_find_freq_{exact,ceil,floor} functions is valid as long as we are
+ * under RCU lock. The pointer returned by the opp_find_freq family must be
+ * used in the same section as the usage of this function with the pointer
+ * prior to unlocking with rcu_read_unlock() to maintain the integrity of the
+ * pointer.
+ */
+bool dev_pm_opp_is_turbo(struct dev_pm_opp *opp)
+{
+	struct dev_pm_opp *tmp_opp;
+
+	opp_rcu_lockdep_assert();
+
+	tmp_opp = rcu_dereference(opp);
+	if (unlikely(IS_ERR_OR_NULL(tmp_opp)) || !tmp_opp->available) {
+		pr_err("%s: Invalid parameters\n", __func__);
+		return false;
+	}
+
+	return tmp_opp->turbo;
+}
+EXPORT_SYMBOL_GPL(dev_pm_opp_is_turbo);
+
+/**
  * dev_pm_opp_get_max_clock_latency() - Get max clock latency in nanoseconds
  * @dev:	device for which we do this operation
  *
diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h
index bb52fae5b921..cab7ba55bedb 100644
--- a/include/linux/pm_opp.h
+++ b/include/linux/pm_opp.h
@@ -30,6 +30,8 @@ unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp);
 
 unsigned long dev_pm_opp_get_freq(struct dev_pm_opp *opp);
 
+bool dev_pm_opp_is_turbo(struct dev_pm_opp *opp);
+
 int dev_pm_opp_get_opp_count(struct device *dev);
 unsigned long dev_pm_opp_get_max_clock_latency(struct device *dev);
 
@@ -63,6 +65,11 @@ static inline unsigned long dev_pm_opp_get_freq(struct dev_pm_opp *opp)
 	return 0;
 }
 
+static inline bool dev_pm_opp_is_turbo(struct dev_pm_opp *opp)
+{
+	return false;
+}
+
 static inline int dev_pm_opp_get_opp_count(struct device *dev)
 {
 	return 0;
-- 
2.4.0

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

* [PATCH V3 13/16] cpufreq: Update boost flag while initializing freq table from OPPs
  2015-07-29 10:52 ` Viresh Kumar
  (?)
@ 2015-07-29 10:53   ` Viresh Kumar
  -1 siblings, 0 replies; 92+ messages in thread
From: Viresh Kumar @ 2015-07-29 10:53 UTC (permalink / raw)
  To: Rafael Wysocki, sboyd
  Cc: linaro-kernel, linux-pm, rob.herring, arnd.bergmann, nm, broonie,
	mturquette, Sudeep.Holla, viswanath.puttagunta, l.stach,
	thomas.petazzoni, linux-arm-kernel, ta.omasab, kesavan.abhilash,
	khilman, santosh.shilimkar, b.zolnierkie, Tomasz Figa,
	Javier Martinez Canillas, Thomas Abraham, Viresh Kumar,
	open list

From: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>

cpufreq table entries for OPPs with turbo modes enabled, should be
marked with CPUFREQ_BOOST_FREQ flag. This ensures that these states are
only used while operating in boost or turbo mode.

Cc: Tomasz Figa <tomasz.figa@gmail.com>
Cc: Michael Turquette <mturquette@baylibre.com>
Cc: Javier Martinez Canillas <javier@dowhile0.org>
Cc: Thomas Abraham <thomas.ab@samsung.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/cpufreq/cpufreq_opp.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/cpufreq/cpufreq_opp.c b/drivers/cpufreq/cpufreq_opp.c
index 773bcde893c0..0f5e6d5f6da0 100644
--- a/drivers/cpufreq/cpufreq_opp.c
+++ b/drivers/cpufreq/cpufreq_opp.c
@@ -75,6 +75,10 @@ int dev_pm_opp_init_cpufreq_table(struct device *dev,
 		}
 		freq_table[i].driver_data = i;
 		freq_table[i].frequency = rate / 1000;
+
+		/* Is Boost/turbo opp ? */
+		if (dev_pm_opp_is_turbo(opp))
+			freq_table[i].flags = CPUFREQ_BOOST_FREQ;
 	}
 
 	freq_table[i].driver_data = i;
-- 
2.4.0


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

* [PATCH V3 13/16] cpufreq: Update boost flag while initializing freq table from OPPs
@ 2015-07-29 10:53   ` Viresh Kumar
  0 siblings, 0 replies; 92+ messages in thread
From: Viresh Kumar @ 2015-07-29 10:53 UTC (permalink / raw)
  To: Rafael Wysocki, sboyd
  Cc: linaro-kernel, linux-pm, rob.herring, arnd.bergmann, nm, broonie,
	mturquette, Sudeep.Holla, viswanath.puttagunta, l.stach,
	thomas.petazzoni, linux-arm-kernel, ta.omasab, kesavan.abhilash,
	khilman, santosh.shilimkar, b.zolnierkie, Tomasz Figa,
	Javier Martinez Canillas, Thomas Abraham, Viresh Kumar,
	open list

From: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>

cpufreq table entries for OPPs with turbo modes enabled, should be
marked with CPUFREQ_BOOST_FREQ flag. This ensures that these states are
only used while operating in boost or turbo mode.

Cc: Tomasz Figa <tomasz.figa@gmail.com>
Cc: Michael Turquette <mturquette@baylibre.com>
Cc: Javier Martinez Canillas <javier@dowhile0.org>
Cc: Thomas Abraham <thomas.ab@samsung.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/cpufreq/cpufreq_opp.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/cpufreq/cpufreq_opp.c b/drivers/cpufreq/cpufreq_opp.c
index 773bcde893c0..0f5e6d5f6da0 100644
--- a/drivers/cpufreq/cpufreq_opp.c
+++ b/drivers/cpufreq/cpufreq_opp.c
@@ -75,6 +75,10 @@ int dev_pm_opp_init_cpufreq_table(struct device *dev,
 		}
 		freq_table[i].driver_data = i;
 		freq_table[i].frequency = rate / 1000;
+
+		/* Is Boost/turbo opp ? */
+		if (dev_pm_opp_is_turbo(opp))
+			freq_table[i].flags = CPUFREQ_BOOST_FREQ;
 	}
 
 	freq_table[i].driver_data = i;
-- 
2.4.0

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

* [PATCH V3 13/16] cpufreq: Update boost flag while initializing freq table from OPPs
@ 2015-07-29 10:53   ` Viresh Kumar
  0 siblings, 0 replies; 92+ messages in thread
From: Viresh Kumar @ 2015-07-29 10:53 UTC (permalink / raw)
  To: linux-arm-kernel

From: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>

cpufreq table entries for OPPs with turbo modes enabled, should be
marked with CPUFREQ_BOOST_FREQ flag. This ensures that these states are
only used while operating in boost or turbo mode.

Cc: Tomasz Figa <tomasz.figa@gmail.com>
Cc: Michael Turquette <mturquette@baylibre.com>
Cc: Javier Martinez Canillas <javier@dowhile0.org>
Cc: Thomas Abraham <thomas.ab@samsung.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/cpufreq/cpufreq_opp.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/cpufreq/cpufreq_opp.c b/drivers/cpufreq/cpufreq_opp.c
index 773bcde893c0..0f5e6d5f6da0 100644
--- a/drivers/cpufreq/cpufreq_opp.c
+++ b/drivers/cpufreq/cpufreq_opp.c
@@ -75,6 +75,10 @@ int dev_pm_opp_init_cpufreq_table(struct device *dev,
 		}
 		freq_table[i].driver_data = i;
 		freq_table[i].frequency = rate / 1000;
+
+		/* Is Boost/turbo opp ? */
+		if (dev_pm_opp_is_turbo(opp))
+			freq_table[i].flags = CPUFREQ_BOOST_FREQ;
 	}
 
 	freq_table[i].driver_data = i;
-- 
2.4.0

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

* [PATCH V3 14/16] cpufreq: Allow drivers to enable boost support after registering driver
  2015-07-29 10:52 ` Viresh Kumar
  (?)
@ 2015-07-29 10:53   ` Viresh Kumar
  -1 siblings, 0 replies; 92+ messages in thread
From: Viresh Kumar @ 2015-07-29 10:53 UTC (permalink / raw)
  To: Rafael Wysocki, sboyd
  Cc: linaro-kernel, linux-pm, rob.herring, arnd.bergmann, nm, broonie,
	mturquette, Sudeep.Holla, viswanath.puttagunta, l.stach,
	thomas.petazzoni, linux-arm-kernel, ta.omasab, kesavan.abhilash,
	khilman, santosh.shilimkar, b.zolnierkie, Viresh Kumar,
	open list

In some cases it wouldn't be known at time of driver registration, if
the driver needs to support boost frequencies.

For example, while getting boost information from DT with opp-v2
bindings, we need to parse the bindings for all the CPUs to know if
turbo/boost OPPs are supported or not.

One way out to do that efficiently is to delay supporting boost mode
(i.e. creating /sys/devices/system/cpu/cpufreq/boost file), until the
time OPP bindings are parsed.

At that point, the driver can enable boost support. This can be done at
->init(), where the frequency table is created.

To do that, the driver requires few APIs from cpufreq core that let him
do this. This patch provides these APIs.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/cpufreq/cpufreq.c    | 68 +++++++++++++++++++++++++++++++-------------
 drivers/cpufreq/freq_table.c | 15 ++++++++++
 include/linux/cpufreq.h      | 12 ++++++++
 3 files changed, 75 insertions(+), 20 deletions(-)

diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 46251e8d30f2..db4390ca5243 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -2459,6 +2459,49 @@ int cpufreq_boost_supported(void)
 }
 EXPORT_SYMBOL_GPL(cpufreq_boost_supported);
 
+static int create_boost_sysfs_file(void)
+{
+	int ret;
+
+	if (!cpufreq_boost_supported())
+		return 0;
+
+	/*
+	 * Check if driver provides function to enable boost -
+	 * if not, use cpufreq_boost_set_sw as default
+	 */
+	if (!cpufreq_driver->set_boost)
+		cpufreq_driver->set_boost = cpufreq_boost_set_sw;
+
+	ret = cpufreq_sysfs_create_file(&boost.attr);
+	if (ret)
+		pr_err("%s: cannot register global BOOST sysfs file\n",
+		       __func__);
+
+	return ret;
+}
+
+static void remove_boost_sysfs_file(void)
+{
+	if (cpufreq_boost_supported())
+		cpufreq_sysfs_remove_file(&boost.attr);
+}
+
+int cpufreq_enable_boost_support(void)
+{
+	if (!cpufreq_driver)
+		return -EINVAL;
+
+	if (cpufreq_boost_supported())
+		return 0;
+
+	cpufreq_driver->boost_supported = true;
+
+	/* This will get removed on driver unregister */
+	return create_boost_sysfs_file();
+}
+EXPORT_SYMBOL_GPL(cpufreq_enable_boost_support);
+
 int cpufreq_boost_enabled(void)
 {
 	return cpufreq_driver->boost_enabled;
@@ -2508,21 +2551,9 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data)
 	if (driver_data->setpolicy)
 		driver_data->flags |= CPUFREQ_CONST_LOOPS;
 
-	if (cpufreq_boost_supported()) {
-		/*
-		 * Check if driver provides function to enable boost -
-		 * if not, use cpufreq_boost_set_sw as default
-		 */
-		if (!cpufreq_driver->set_boost)
-			cpufreq_driver->set_boost = cpufreq_boost_set_sw;
-
-		ret = cpufreq_sysfs_create_file(&boost.attr);
-		if (ret) {
-			pr_err("%s: cannot register global BOOST sysfs file\n",
-			       __func__);
-			goto err_null_driver;
-		}
-	}
+	ret = create_boost_sysfs_file();
+	if (ret)
+		goto err_null_driver;
 
 	ret = subsys_interface_register(&cpufreq_interface);
 	if (ret)
@@ -2543,8 +2574,7 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data)
 err_if_unreg:
 	subsys_interface_unregister(&cpufreq_interface);
 err_boost_unreg:
-	if (cpufreq_boost_supported())
-		cpufreq_sysfs_remove_file(&boost.attr);
+	remove_boost_sysfs_file();
 err_null_driver:
 	write_lock_irqsave(&cpufreq_driver_lock, flags);
 	cpufreq_driver = NULL;
@@ -2573,9 +2603,7 @@ int cpufreq_unregister_driver(struct cpufreq_driver *driver)
 	/* Protect against concurrent cpu hotplug */
 	get_online_cpus();
 	subsys_interface_unregister(&cpufreq_interface);
-	if (cpufreq_boost_supported())
-		cpufreq_sysfs_remove_file(&boost.attr);
-
+	remove_boost_sysfs_file();
 	unregister_hotcpu_notifier(&cpufreq_cpu_notifier);
 
 	write_lock_irqsave(&cpufreq_driver_lock, flags);
diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c
index dfbbf981ed56..a8f1daffc9bc 100644
--- a/drivers/cpufreq/freq_table.c
+++ b/drivers/cpufreq/freq_table.c
@@ -18,6 +18,21 @@
  *                     FREQUENCY TABLE HELPERS                       *
  *********************************************************************/
 
+bool policy_has_boost_freq(struct cpufreq_policy *policy)
+{
+	struct cpufreq_frequency_table *pos, *table = policy->freq_table;
+
+	if (!table)
+		return false;
+
+	cpufreq_for_each_valid_entry(pos, table)
+		if (pos->flags & CPUFREQ_BOOST_FREQ)
+			return true;
+
+	return false;
+}
+EXPORT_SYMBOL_GPL(policy_has_boost_freq);
+
 int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy,
 				    struct cpufreq_frequency_table *table)
 {
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index bde1e567b3a9..95f018649abf 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -578,6 +578,8 @@ ssize_t cpufreq_show_cpus(const struct cpumask *mask, char *buf);
 int cpufreq_boost_trigger_state(int state);
 int cpufreq_boost_supported(void);
 int cpufreq_boost_enabled(void);
+int cpufreq_enable_boost_support(void);
+bool policy_has_boost_freq(struct cpufreq_policy *policy);
 #else
 static inline int cpufreq_boost_trigger_state(int state)
 {
@@ -591,6 +593,16 @@ static inline int cpufreq_boost_enabled(void)
 {
 	return 0;
 }
+
+static inline int cpufreq_enable_boost_support(void)
+{
+	return -EINVAL;
+}
+
+static inline bool policy_has_boost_freq(struct cpufreq_policy *policy)
+{
+	return false;
+}
 #endif
 /* the following funtion is for cpufreq core use only */
 struct cpufreq_frequency_table *cpufreq_frequency_get_table(unsigned int cpu);
-- 
2.4.0


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

* [PATCH V3 14/16] cpufreq: Allow drivers to enable boost support after registering driver
@ 2015-07-29 10:53   ` Viresh Kumar
  0 siblings, 0 replies; 92+ messages in thread
From: Viresh Kumar @ 2015-07-29 10:53 UTC (permalink / raw)
  To: Rafael Wysocki, sboyd
  Cc: linaro-kernel, linux-pm, rob.herring, arnd.bergmann, nm, broonie,
	mturquette, Sudeep.Holla, viswanath.puttagunta, l.stach,
	thomas.petazzoni, linux-arm-kernel, ta.omasab, kesavan.abhilash,
	khilman, santosh.shilimkar, b.zolnierkie, Viresh Kumar,
	open list

In some cases it wouldn't be known at time of driver registration, if
the driver needs to support boost frequencies.

For example, while getting boost information from DT with opp-v2
bindings, we need to parse the bindings for all the CPUs to know if
turbo/boost OPPs are supported or not.

One way out to do that efficiently is to delay supporting boost mode
(i.e. creating /sys/devices/system/cpu/cpufreq/boost file), until the
time OPP bindings are parsed.

At that point, the driver can enable boost support. This can be done at
->init(), where the frequency table is created.

To do that, the driver requires few APIs from cpufreq core that let him
do this. This patch provides these APIs.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/cpufreq/cpufreq.c    | 68 +++++++++++++++++++++++++++++++-------------
 drivers/cpufreq/freq_table.c | 15 ++++++++++
 include/linux/cpufreq.h      | 12 ++++++++
 3 files changed, 75 insertions(+), 20 deletions(-)

diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 46251e8d30f2..db4390ca5243 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -2459,6 +2459,49 @@ int cpufreq_boost_supported(void)
 }
 EXPORT_SYMBOL_GPL(cpufreq_boost_supported);
 
+static int create_boost_sysfs_file(void)
+{
+	int ret;
+
+	if (!cpufreq_boost_supported())
+		return 0;
+
+	/*
+	 * Check if driver provides function to enable boost -
+	 * if not, use cpufreq_boost_set_sw as default
+	 */
+	if (!cpufreq_driver->set_boost)
+		cpufreq_driver->set_boost = cpufreq_boost_set_sw;
+
+	ret = cpufreq_sysfs_create_file(&boost.attr);
+	if (ret)
+		pr_err("%s: cannot register global BOOST sysfs file\n",
+		       __func__);
+
+	return ret;
+}
+
+static void remove_boost_sysfs_file(void)
+{
+	if (cpufreq_boost_supported())
+		cpufreq_sysfs_remove_file(&boost.attr);
+}
+
+int cpufreq_enable_boost_support(void)
+{
+	if (!cpufreq_driver)
+		return -EINVAL;
+
+	if (cpufreq_boost_supported())
+		return 0;
+
+	cpufreq_driver->boost_supported = true;
+
+	/* This will get removed on driver unregister */
+	return create_boost_sysfs_file();
+}
+EXPORT_SYMBOL_GPL(cpufreq_enable_boost_support);
+
 int cpufreq_boost_enabled(void)
 {
 	return cpufreq_driver->boost_enabled;
@@ -2508,21 +2551,9 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data)
 	if (driver_data->setpolicy)
 		driver_data->flags |= CPUFREQ_CONST_LOOPS;
 
-	if (cpufreq_boost_supported()) {
-		/*
-		 * Check if driver provides function to enable boost -
-		 * if not, use cpufreq_boost_set_sw as default
-		 */
-		if (!cpufreq_driver->set_boost)
-			cpufreq_driver->set_boost = cpufreq_boost_set_sw;
-
-		ret = cpufreq_sysfs_create_file(&boost.attr);
-		if (ret) {
-			pr_err("%s: cannot register global BOOST sysfs file\n",
-			       __func__);
-			goto err_null_driver;
-		}
-	}
+	ret = create_boost_sysfs_file();
+	if (ret)
+		goto err_null_driver;
 
 	ret = subsys_interface_register(&cpufreq_interface);
 	if (ret)
@@ -2543,8 +2574,7 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data)
 err_if_unreg:
 	subsys_interface_unregister(&cpufreq_interface);
 err_boost_unreg:
-	if (cpufreq_boost_supported())
-		cpufreq_sysfs_remove_file(&boost.attr);
+	remove_boost_sysfs_file();
 err_null_driver:
 	write_lock_irqsave(&cpufreq_driver_lock, flags);
 	cpufreq_driver = NULL;
@@ -2573,9 +2603,7 @@ int cpufreq_unregister_driver(struct cpufreq_driver *driver)
 	/* Protect against concurrent cpu hotplug */
 	get_online_cpus();
 	subsys_interface_unregister(&cpufreq_interface);
-	if (cpufreq_boost_supported())
-		cpufreq_sysfs_remove_file(&boost.attr);
-
+	remove_boost_sysfs_file();
 	unregister_hotcpu_notifier(&cpufreq_cpu_notifier);
 
 	write_lock_irqsave(&cpufreq_driver_lock, flags);
diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c
index dfbbf981ed56..a8f1daffc9bc 100644
--- a/drivers/cpufreq/freq_table.c
+++ b/drivers/cpufreq/freq_table.c
@@ -18,6 +18,21 @@
  *                     FREQUENCY TABLE HELPERS                       *
  *********************************************************************/
 
+bool policy_has_boost_freq(struct cpufreq_policy *policy)
+{
+	struct cpufreq_frequency_table *pos, *table = policy->freq_table;
+
+	if (!table)
+		return false;
+
+	cpufreq_for_each_valid_entry(pos, table)
+		if (pos->flags & CPUFREQ_BOOST_FREQ)
+			return true;
+
+	return false;
+}
+EXPORT_SYMBOL_GPL(policy_has_boost_freq);
+
 int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy,
 				    struct cpufreq_frequency_table *table)
 {
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index bde1e567b3a9..95f018649abf 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -578,6 +578,8 @@ ssize_t cpufreq_show_cpus(const struct cpumask *mask, char *buf);
 int cpufreq_boost_trigger_state(int state);
 int cpufreq_boost_supported(void);
 int cpufreq_boost_enabled(void);
+int cpufreq_enable_boost_support(void);
+bool policy_has_boost_freq(struct cpufreq_policy *policy);
 #else
 static inline int cpufreq_boost_trigger_state(int state)
 {
@@ -591,6 +593,16 @@ static inline int cpufreq_boost_enabled(void)
 {
 	return 0;
 }
+
+static inline int cpufreq_enable_boost_support(void)
+{
+	return -EINVAL;
+}
+
+static inline bool policy_has_boost_freq(struct cpufreq_policy *policy)
+{
+	return false;
+}
 #endif
 /* the following funtion is for cpufreq core use only */
 struct cpufreq_frequency_table *cpufreq_frequency_get_table(unsigned int cpu);
-- 
2.4.0

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

* [PATCH V3 14/16] cpufreq: Allow drivers to enable boost support after registering driver
@ 2015-07-29 10:53   ` Viresh Kumar
  0 siblings, 0 replies; 92+ messages in thread
From: Viresh Kumar @ 2015-07-29 10:53 UTC (permalink / raw)
  To: linux-arm-kernel

In some cases it wouldn't be known at time of driver registration, if
the driver needs to support boost frequencies.

For example, while getting boost information from DT with opp-v2
bindings, we need to parse the bindings for all the CPUs to know if
turbo/boost OPPs are supported or not.

One way out to do that efficiently is to delay supporting boost mode
(i.e. creating /sys/devices/system/cpu/cpufreq/boost file), until the
time OPP bindings are parsed.

At that point, the driver can enable boost support. This can be done at
->init(), where the frequency table is created.

To do that, the driver requires few APIs from cpufreq core that let him
do this. This patch provides these APIs.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/cpufreq/cpufreq.c    | 68 +++++++++++++++++++++++++++++++-------------
 drivers/cpufreq/freq_table.c | 15 ++++++++++
 include/linux/cpufreq.h      | 12 ++++++++
 3 files changed, 75 insertions(+), 20 deletions(-)

diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 46251e8d30f2..db4390ca5243 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -2459,6 +2459,49 @@ int cpufreq_boost_supported(void)
 }
 EXPORT_SYMBOL_GPL(cpufreq_boost_supported);
 
+static int create_boost_sysfs_file(void)
+{
+	int ret;
+
+	if (!cpufreq_boost_supported())
+		return 0;
+
+	/*
+	 * Check if driver provides function to enable boost -
+	 * if not, use cpufreq_boost_set_sw as default
+	 */
+	if (!cpufreq_driver->set_boost)
+		cpufreq_driver->set_boost = cpufreq_boost_set_sw;
+
+	ret = cpufreq_sysfs_create_file(&boost.attr);
+	if (ret)
+		pr_err("%s: cannot register global BOOST sysfs file\n",
+		       __func__);
+
+	return ret;
+}
+
+static void remove_boost_sysfs_file(void)
+{
+	if (cpufreq_boost_supported())
+		cpufreq_sysfs_remove_file(&boost.attr);
+}
+
+int cpufreq_enable_boost_support(void)
+{
+	if (!cpufreq_driver)
+		return -EINVAL;
+
+	if (cpufreq_boost_supported())
+		return 0;
+
+	cpufreq_driver->boost_supported = true;
+
+	/* This will get removed on driver unregister */
+	return create_boost_sysfs_file();
+}
+EXPORT_SYMBOL_GPL(cpufreq_enable_boost_support);
+
 int cpufreq_boost_enabled(void)
 {
 	return cpufreq_driver->boost_enabled;
@@ -2508,21 +2551,9 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data)
 	if (driver_data->setpolicy)
 		driver_data->flags |= CPUFREQ_CONST_LOOPS;
 
-	if (cpufreq_boost_supported()) {
-		/*
-		 * Check if driver provides function to enable boost -
-		 * if not, use cpufreq_boost_set_sw as default
-		 */
-		if (!cpufreq_driver->set_boost)
-			cpufreq_driver->set_boost = cpufreq_boost_set_sw;
-
-		ret = cpufreq_sysfs_create_file(&boost.attr);
-		if (ret) {
-			pr_err("%s: cannot register global BOOST sysfs file\n",
-			       __func__);
-			goto err_null_driver;
-		}
-	}
+	ret = create_boost_sysfs_file();
+	if (ret)
+		goto err_null_driver;
 
 	ret = subsys_interface_register(&cpufreq_interface);
 	if (ret)
@@ -2543,8 +2574,7 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data)
 err_if_unreg:
 	subsys_interface_unregister(&cpufreq_interface);
 err_boost_unreg:
-	if (cpufreq_boost_supported())
-		cpufreq_sysfs_remove_file(&boost.attr);
+	remove_boost_sysfs_file();
 err_null_driver:
 	write_lock_irqsave(&cpufreq_driver_lock, flags);
 	cpufreq_driver = NULL;
@@ -2573,9 +2603,7 @@ int cpufreq_unregister_driver(struct cpufreq_driver *driver)
 	/* Protect against concurrent cpu hotplug */
 	get_online_cpus();
 	subsys_interface_unregister(&cpufreq_interface);
-	if (cpufreq_boost_supported())
-		cpufreq_sysfs_remove_file(&boost.attr);
-
+	remove_boost_sysfs_file();
 	unregister_hotcpu_notifier(&cpufreq_cpu_notifier);
 
 	write_lock_irqsave(&cpufreq_driver_lock, flags);
diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c
index dfbbf981ed56..a8f1daffc9bc 100644
--- a/drivers/cpufreq/freq_table.c
+++ b/drivers/cpufreq/freq_table.c
@@ -18,6 +18,21 @@
  *                     FREQUENCY TABLE HELPERS                       *
  *********************************************************************/
 
+bool policy_has_boost_freq(struct cpufreq_policy *policy)
+{
+	struct cpufreq_frequency_table *pos, *table = policy->freq_table;
+
+	if (!table)
+		return false;
+
+	cpufreq_for_each_valid_entry(pos, table)
+		if (pos->flags & CPUFREQ_BOOST_FREQ)
+			return true;
+
+	return false;
+}
+EXPORT_SYMBOL_GPL(policy_has_boost_freq);
+
 int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy,
 				    struct cpufreq_frequency_table *table)
 {
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index bde1e567b3a9..95f018649abf 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -578,6 +578,8 @@ ssize_t cpufreq_show_cpus(const struct cpumask *mask, char *buf);
 int cpufreq_boost_trigger_state(int state);
 int cpufreq_boost_supported(void);
 int cpufreq_boost_enabled(void);
+int cpufreq_enable_boost_support(void);
+bool policy_has_boost_freq(struct cpufreq_policy *policy);
 #else
 static inline int cpufreq_boost_trigger_state(int state)
 {
@@ -591,6 +593,16 @@ static inline int cpufreq_boost_enabled(void)
 {
 	return 0;
 }
+
+static inline int cpufreq_enable_boost_support(void)
+{
+	return -EINVAL;
+}
+
+static inline bool policy_has_boost_freq(struct cpufreq_policy *policy)
+{
+	return false;
+}
 #endif
 /* the following funtion is for cpufreq core use only */
 struct cpufreq_frequency_table *cpufreq_frequency_get_table(unsigned int cpu);
-- 
2.4.0

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

* [PATCH V3 15/16] cpufreq: dt: Add support for operating-points-v2 bindings
  2015-07-29 10:52 ` Viresh Kumar
  (?)
@ 2015-07-29 10:53   ` Viresh Kumar
  -1 siblings, 0 replies; 92+ messages in thread
From: Viresh Kumar @ 2015-07-29 10:53 UTC (permalink / raw)
  To: Rafael Wysocki, sboyd
  Cc: linaro-kernel, linux-pm, rob.herring, arnd.bergmann, nm, broonie,
	mturquette, Sudeep.Holla, viswanath.puttagunta, l.stach,
	thomas.petazzoni, linux-arm-kernel, ta.omasab, kesavan.abhilash,
	khilman, santosh.shilimkar, b.zolnierkie, Viresh Kumar,
	open list

Support for parsing operating-points-v2 bindings is in place now, lets
modify cpufreq-dt driver to use them.

For backward compatibility we will continue to support earlier bindings.
Special handling for that is required, to make sure OPPs are initialized
for all the CPUs.

Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/cpufreq/cpufreq-dt.c | 56 ++++++++++++++++++++++++++++++++++++--------
 1 file changed, 46 insertions(+), 10 deletions(-)

diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c
index 528a82bf5038..c6e7033076de 100644
--- a/drivers/cpufreq/cpufreq-dt.c
+++ b/drivers/cpufreq/cpufreq-dt.c
@@ -184,7 +184,6 @@ static int allocate_resources(int cpu, struct device **cdev,
 
 static int cpufreq_init(struct cpufreq_policy *policy)
 {
-	struct cpufreq_dt_platform_data *pd;
 	struct cpufreq_frequency_table *freq_table;
 	struct device_node *np;
 	struct private_data *priv;
@@ -193,6 +192,7 @@ static int cpufreq_init(struct cpufreq_policy *policy)
 	struct clk *cpu_clk;
 	unsigned long min_uV = ~0, max_uV = 0;
 	unsigned int transition_latency;
+	bool need_update = false;
 	int ret;
 
 	ret = allocate_resources(policy->cpu, &cpu_dev, &cpu_reg, &cpu_clk);
@@ -208,8 +208,47 @@ static int cpufreq_init(struct cpufreq_policy *policy)
 		goto out_put_reg_clk;
 	}
 
-	/* OPPs might be populated at runtime, don't check for error here */
-	of_init_opp_table(cpu_dev);
+	/* Get OPP-sharing information from "operating-points-v2" bindings */
+	ret = of_get_cpus_sharing_opps(cpu_dev, policy->cpus);
+	if (ret) {
+		/*
+		 * operating-points-v2 not supported, fallback to old method of
+		 * finding shared-OPPs for backward compatibility.
+		 */
+		if (ret == -ENOENT)
+			need_update = true;
+		else
+			goto out_node_put;
+	}
+
+	/*
+	 * Initialize OPP tables for all policy->cpus. They will be shared by
+	 * all CPUs which have marked their CPUs shared with OPP bindings.
+	 *
+	 * For platforms not using operating-points-v2 bindings, we do this
+	 * before updating policy->cpus. Otherwise, we will end up creating
+	 * duplicate OPPs for policy->cpus.
+	 *
+	 * OPPs might be populated at runtime, don't check for error here
+	 */
+	of_cpumask_init_opp_table(policy->cpus);
+
+	if (need_update) {
+		struct cpufreq_dt_platform_data *pd = cpufreq_get_driver_data();
+
+		if (!pd || !pd->independent_clocks)
+			cpumask_setall(policy->cpus);
+
+		/*
+		 * OPP tables are initialized only for policy->cpu, do it for
+		 * others as well.
+		 */
+		set_cpus_sharing_opps(cpu_dev, policy->cpus);
+
+		of_property_read_u32(np, "clock-latency", &transition_latency);
+	} else {
+		transition_latency = dev_pm_opp_get_max_clock_latency(cpu_dev);
+	}
 
 	/*
 	 * But we need OPP table to function so if it is not there let's
@@ -230,7 +269,7 @@ static int cpufreq_init(struct cpufreq_policy *policy)
 
 	of_property_read_u32(np, "voltage-tolerance", &priv->voltage_tolerance);
 
-	if (of_property_read_u32(np, "clock-latency", &transition_latency))
+	if (!transition_latency)
 		transition_latency = CPUFREQ_ETERNAL;
 
 	if (!IS_ERR(cpu_reg)) {
@@ -293,10 +332,6 @@ static int cpufreq_init(struct cpufreq_policy *policy)
 
 	policy->cpuinfo.transition_latency = transition_latency;
 
-	pd = cpufreq_get_driver_data();
-	if (!pd || !pd->independent_clocks)
-		cpumask_setall(policy->cpus);
-
 	of_node_put(np);
 
 	return 0;
@@ -306,7 +341,8 @@ static int cpufreq_init(struct cpufreq_policy *policy)
 out_free_priv:
 	kfree(priv);
 out_free_opp:
-	of_free_opp_table(cpu_dev);
+	of_cpumask_free_opp_table(policy->cpus);
+out_node_put:
 	of_node_put(np);
 out_put_reg_clk:
 	clk_put(cpu_clk);
@@ -322,7 +358,7 @@ static int cpufreq_exit(struct cpufreq_policy *policy)
 
 	cpufreq_cooling_unregister(priv->cdev);
 	dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table);
-	of_free_opp_table(priv->cpu_dev);
+	of_cpumask_free_opp_table(policy->related_cpus);
 	clk_put(policy->clk);
 	if (!IS_ERR(priv->cpu_reg))
 		regulator_put(priv->cpu_reg);
-- 
2.4.0


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

* [PATCH V3 15/16] cpufreq: dt: Add support for operating-points-v2 bindings
@ 2015-07-29 10:53   ` Viresh Kumar
  0 siblings, 0 replies; 92+ messages in thread
From: Viresh Kumar @ 2015-07-29 10:53 UTC (permalink / raw)
  To: Rafael Wysocki, sboyd
  Cc: linaro-kernel, linux-pm, rob.herring, arnd.bergmann, nm, broonie,
	mturquette, Sudeep.Holla, viswanath.puttagunta, l.stach,
	thomas.petazzoni, linux-arm-kernel, ta.omasab, kesavan.abhilash,
	khilman, santosh.shilimkar, b.zolnierkie, Viresh Kumar,
	open list

Support for parsing operating-points-v2 bindings is in place now, lets
modify cpufreq-dt driver to use them.

For backward compatibility we will continue to support earlier bindings.
Special handling for that is required, to make sure OPPs are initialized
for all the CPUs.

Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/cpufreq/cpufreq-dt.c | 56 ++++++++++++++++++++++++++++++++++++--------
 1 file changed, 46 insertions(+), 10 deletions(-)

diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c
index 528a82bf5038..c6e7033076de 100644
--- a/drivers/cpufreq/cpufreq-dt.c
+++ b/drivers/cpufreq/cpufreq-dt.c
@@ -184,7 +184,6 @@ static int allocate_resources(int cpu, struct device **cdev,
 
 static int cpufreq_init(struct cpufreq_policy *policy)
 {
-	struct cpufreq_dt_platform_data *pd;
 	struct cpufreq_frequency_table *freq_table;
 	struct device_node *np;
 	struct private_data *priv;
@@ -193,6 +192,7 @@ static int cpufreq_init(struct cpufreq_policy *policy)
 	struct clk *cpu_clk;
 	unsigned long min_uV = ~0, max_uV = 0;
 	unsigned int transition_latency;
+	bool need_update = false;
 	int ret;
 
 	ret = allocate_resources(policy->cpu, &cpu_dev, &cpu_reg, &cpu_clk);
@@ -208,8 +208,47 @@ static int cpufreq_init(struct cpufreq_policy *policy)
 		goto out_put_reg_clk;
 	}
 
-	/* OPPs might be populated at runtime, don't check for error here */
-	of_init_opp_table(cpu_dev);
+	/* Get OPP-sharing information from "operating-points-v2" bindings */
+	ret = of_get_cpus_sharing_opps(cpu_dev, policy->cpus);
+	if (ret) {
+		/*
+		 * operating-points-v2 not supported, fallback to old method of
+		 * finding shared-OPPs for backward compatibility.
+		 */
+		if (ret == -ENOENT)
+			need_update = true;
+		else
+			goto out_node_put;
+	}
+
+	/*
+	 * Initialize OPP tables for all policy->cpus. They will be shared by
+	 * all CPUs which have marked their CPUs shared with OPP bindings.
+	 *
+	 * For platforms not using operating-points-v2 bindings, we do this
+	 * before updating policy->cpus. Otherwise, we will end up creating
+	 * duplicate OPPs for policy->cpus.
+	 *
+	 * OPPs might be populated at runtime, don't check for error here
+	 */
+	of_cpumask_init_opp_table(policy->cpus);
+
+	if (need_update) {
+		struct cpufreq_dt_platform_data *pd = cpufreq_get_driver_data();
+
+		if (!pd || !pd->independent_clocks)
+			cpumask_setall(policy->cpus);
+
+		/*
+		 * OPP tables are initialized only for policy->cpu, do it for
+		 * others as well.
+		 */
+		set_cpus_sharing_opps(cpu_dev, policy->cpus);
+
+		of_property_read_u32(np, "clock-latency", &transition_latency);
+	} else {
+		transition_latency = dev_pm_opp_get_max_clock_latency(cpu_dev);
+	}
 
 	/*
 	 * But we need OPP table to function so if it is not there let's
@@ -230,7 +269,7 @@ static int cpufreq_init(struct cpufreq_policy *policy)
 
 	of_property_read_u32(np, "voltage-tolerance", &priv->voltage_tolerance);
 
-	if (of_property_read_u32(np, "clock-latency", &transition_latency))
+	if (!transition_latency)
 		transition_latency = CPUFREQ_ETERNAL;
 
 	if (!IS_ERR(cpu_reg)) {
@@ -293,10 +332,6 @@ static int cpufreq_init(struct cpufreq_policy *policy)
 
 	policy->cpuinfo.transition_latency = transition_latency;
 
-	pd = cpufreq_get_driver_data();
-	if (!pd || !pd->independent_clocks)
-		cpumask_setall(policy->cpus);
-
 	of_node_put(np);
 
 	return 0;
@@ -306,7 +341,8 @@ static int cpufreq_init(struct cpufreq_policy *policy)
 out_free_priv:
 	kfree(priv);
 out_free_opp:
-	of_free_opp_table(cpu_dev);
+	of_cpumask_free_opp_table(policy->cpus);
+out_node_put:
 	of_node_put(np);
 out_put_reg_clk:
 	clk_put(cpu_clk);
@@ -322,7 +358,7 @@ static int cpufreq_exit(struct cpufreq_policy *policy)
 
 	cpufreq_cooling_unregister(priv->cdev);
 	dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table);
-	of_free_opp_table(priv->cpu_dev);
+	of_cpumask_free_opp_table(policy->related_cpus);
 	clk_put(policy->clk);
 	if (!IS_ERR(priv->cpu_reg))
 		regulator_put(priv->cpu_reg);
-- 
2.4.0


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

* [PATCH V3 15/16] cpufreq: dt: Add support for operating-points-v2 bindings
@ 2015-07-29 10:53   ` Viresh Kumar
  0 siblings, 0 replies; 92+ messages in thread
From: Viresh Kumar @ 2015-07-29 10:53 UTC (permalink / raw)
  To: linux-arm-kernel

Support for parsing operating-points-v2 bindings is in place now, lets
modify cpufreq-dt driver to use them.

For backward compatibility we will continue to support earlier bindings.
Special handling for that is required, to make sure OPPs are initialized
for all the CPUs.

Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/cpufreq/cpufreq-dt.c | 56 ++++++++++++++++++++++++++++++++++++--------
 1 file changed, 46 insertions(+), 10 deletions(-)

diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c
index 528a82bf5038..c6e7033076de 100644
--- a/drivers/cpufreq/cpufreq-dt.c
+++ b/drivers/cpufreq/cpufreq-dt.c
@@ -184,7 +184,6 @@ static int allocate_resources(int cpu, struct device **cdev,
 
 static int cpufreq_init(struct cpufreq_policy *policy)
 {
-	struct cpufreq_dt_platform_data *pd;
 	struct cpufreq_frequency_table *freq_table;
 	struct device_node *np;
 	struct private_data *priv;
@@ -193,6 +192,7 @@ static int cpufreq_init(struct cpufreq_policy *policy)
 	struct clk *cpu_clk;
 	unsigned long min_uV = ~0, max_uV = 0;
 	unsigned int transition_latency;
+	bool need_update = false;
 	int ret;
 
 	ret = allocate_resources(policy->cpu, &cpu_dev, &cpu_reg, &cpu_clk);
@@ -208,8 +208,47 @@ static int cpufreq_init(struct cpufreq_policy *policy)
 		goto out_put_reg_clk;
 	}
 
-	/* OPPs might be populated at runtime, don't check for error here */
-	of_init_opp_table(cpu_dev);
+	/* Get OPP-sharing information from "operating-points-v2" bindings */
+	ret = of_get_cpus_sharing_opps(cpu_dev, policy->cpus);
+	if (ret) {
+		/*
+		 * operating-points-v2 not supported, fallback to old method of
+		 * finding shared-OPPs for backward compatibility.
+		 */
+		if (ret == -ENOENT)
+			need_update = true;
+		else
+			goto out_node_put;
+	}
+
+	/*
+	 * Initialize OPP tables for all policy->cpus. They will be shared by
+	 * all CPUs which have marked their CPUs shared with OPP bindings.
+	 *
+	 * For platforms not using operating-points-v2 bindings, we do this
+	 * before updating policy->cpus. Otherwise, we will end up creating
+	 * duplicate OPPs for policy->cpus.
+	 *
+	 * OPPs might be populated at runtime, don't check for error here
+	 */
+	of_cpumask_init_opp_table(policy->cpus);
+
+	if (need_update) {
+		struct cpufreq_dt_platform_data *pd = cpufreq_get_driver_data();
+
+		if (!pd || !pd->independent_clocks)
+			cpumask_setall(policy->cpus);
+
+		/*
+		 * OPP tables are initialized only for policy->cpu, do it for
+		 * others as well.
+		 */
+		set_cpus_sharing_opps(cpu_dev, policy->cpus);
+
+		of_property_read_u32(np, "clock-latency", &transition_latency);
+	} else {
+		transition_latency = dev_pm_opp_get_max_clock_latency(cpu_dev);
+	}
 
 	/*
 	 * But we need OPP table to function so if it is not there let's
@@ -230,7 +269,7 @@ static int cpufreq_init(struct cpufreq_policy *policy)
 
 	of_property_read_u32(np, "voltage-tolerance", &priv->voltage_tolerance);
 
-	if (of_property_read_u32(np, "clock-latency", &transition_latency))
+	if (!transition_latency)
 		transition_latency = CPUFREQ_ETERNAL;
 
 	if (!IS_ERR(cpu_reg)) {
@@ -293,10 +332,6 @@ static int cpufreq_init(struct cpufreq_policy *policy)
 
 	policy->cpuinfo.transition_latency = transition_latency;
 
-	pd = cpufreq_get_driver_data();
-	if (!pd || !pd->independent_clocks)
-		cpumask_setall(policy->cpus);
-
 	of_node_put(np);
 
 	return 0;
@@ -306,7 +341,8 @@ static int cpufreq_init(struct cpufreq_policy *policy)
 out_free_priv:
 	kfree(priv);
 out_free_opp:
-	of_free_opp_table(cpu_dev);
+	of_cpumask_free_opp_table(policy->cpus);
+out_node_put:
 	of_node_put(np);
 out_put_reg_clk:
 	clk_put(cpu_clk);
@@ -322,7 +358,7 @@ static int cpufreq_exit(struct cpufreq_policy *policy)
 
 	cpufreq_cooling_unregister(priv->cdev);
 	dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table);
-	of_free_opp_table(priv->cpu_dev);
+	of_cpumask_free_opp_table(policy->related_cpus);
 	clk_put(policy->clk);
 	if (!IS_ERR(priv->cpu_reg))
 		regulator_put(priv->cpu_reg);
-- 
2.4.0

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

* [PATCH V3 16/16] cpufreq: dt: Add support for turbo/boost mode
  2015-07-29 10:52 ` Viresh Kumar
  (?)
@ 2015-07-29 10:53   ` Viresh Kumar
  -1 siblings, 0 replies; 92+ messages in thread
From: Viresh Kumar @ 2015-07-29 10:53 UTC (permalink / raw)
  To: Rafael Wysocki, sboyd
  Cc: linaro-kernel, linux-pm, rob.herring, arnd.bergmann, nm, broonie,
	mturquette, Sudeep.Holla, viswanath.puttagunta, l.stach,
	thomas.petazzoni, linux-arm-kernel, ta.omasab, kesavan.abhilash,
	khilman, santosh.shilimkar, b.zolnierkie, Viresh Kumar,
	open list

With opp-v2 DT bindings, few OPPs can be used only for the boost mode.
But using such OPPs require the boost mode to be supported by cpufreq
driver.

We will parse DT bindings only during ->init() and so can enable boost
support only after registering cpufreq driver.

This enables boost support as soon as any policy has boost/turbo OPPs
for its CPUs.

We don't need to disable boost support as that is done by the core, when
the driver is unregistered.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/cpufreq/cpufreq-dt.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c
index c6e7033076de..b9259abd25d4 100644
--- a/drivers/cpufreq/cpufreq-dt.c
+++ b/drivers/cpufreq/cpufreq-dt.c
@@ -330,6 +330,14 @@ static int cpufreq_init(struct cpufreq_policy *policy)
 		goto out_free_cpufreq_table;
 	}
 
+	/* Support turbo/boost mode */
+	if (policy_has_boost_freq(policy)) {
+		/* This gets disabled by core on driver unregister */
+		ret = cpufreq_enable_boost_support();
+		if (ret)
+			goto out_free_cpufreq_table;
+	}
+
 	policy->cpuinfo.transition_latency = transition_latency;
 
 	of_node_put(np);
-- 
2.4.0


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

* [PATCH V3 16/16] cpufreq: dt: Add support for turbo/boost mode
@ 2015-07-29 10:53   ` Viresh Kumar
  0 siblings, 0 replies; 92+ messages in thread
From: Viresh Kumar @ 2015-07-29 10:53 UTC (permalink / raw)
  To: Rafael Wysocki, sboyd
  Cc: linaro-kernel, linux-pm, rob.herring, arnd.bergmann, nm, broonie,
	mturquette, Sudeep.Holla, viswanath.puttagunta, l.stach,
	thomas.petazzoni, linux-arm-kernel, ta.omasab, kesavan.abhilash,
	khilman, santosh.shilimkar, b.zolnierkie, Viresh Kumar,
	open list

With opp-v2 DT bindings, few OPPs can be used only for the boost mode.
But using such OPPs require the boost mode to be supported by cpufreq
driver.

We will parse DT bindings only during ->init() and so can enable boost
support only after registering cpufreq driver.

This enables boost support as soon as any policy has boost/turbo OPPs
for its CPUs.

We don't need to disable boost support as that is done by the core, when
the driver is unregistered.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/cpufreq/cpufreq-dt.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c
index c6e7033076de..b9259abd25d4 100644
--- a/drivers/cpufreq/cpufreq-dt.c
+++ b/drivers/cpufreq/cpufreq-dt.c
@@ -330,6 +330,14 @@ static int cpufreq_init(struct cpufreq_policy *policy)
 		goto out_free_cpufreq_table;
 	}
 
+	/* Support turbo/boost mode */
+	if (policy_has_boost_freq(policy)) {
+		/* This gets disabled by core on driver unregister */
+		ret = cpufreq_enable_boost_support();
+		if (ret)
+			goto out_free_cpufreq_table;
+	}
+
 	policy->cpuinfo.transition_latency = transition_latency;
 
 	of_node_put(np);
-- 
2.4.0

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

* [PATCH V3 16/16] cpufreq: dt: Add support for turbo/boost mode
@ 2015-07-29 10:53   ` Viresh Kumar
  0 siblings, 0 replies; 92+ messages in thread
From: Viresh Kumar @ 2015-07-29 10:53 UTC (permalink / raw)
  To: linux-arm-kernel

With opp-v2 DT bindings, few OPPs can be used only for the boost mode.
But using such OPPs require the boost mode to be supported by cpufreq
driver.

We will parse DT bindings only during ->init() and so can enable boost
support only after registering cpufreq driver.

This enables boost support as soon as any policy has boost/turbo OPPs
for its CPUs.

We don't need to disable boost support as that is done by the core, when
the driver is unregistered.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/cpufreq/cpufreq-dt.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c
index c6e7033076de..b9259abd25d4 100644
--- a/drivers/cpufreq/cpufreq-dt.c
+++ b/drivers/cpufreq/cpufreq-dt.c
@@ -330,6 +330,14 @@ static int cpufreq_init(struct cpufreq_policy *policy)
 		goto out_free_cpufreq_table;
 	}
 
+	/* Support turbo/boost mode */
+	if (policy_has_boost_freq(policy)) {
+		/* This gets disabled by core on driver unregister */
+		ret = cpufreq_enable_boost_support();
+		if (ret)
+			goto out_free_cpufreq_table;
+	}
+
 	policy->cpuinfo.transition_latency = transition_latency;
 
 	of_node_put(np);
-- 
2.4.0

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

* Re: [PATCH V3 02/16] PM / OPP: Create a directory for opp bindings
  2015-07-29 10:52   ` Viresh Kumar
@ 2015-07-30 13:18     ` Rob Herring
  -1 siblings, 0 replies; 92+ messages in thread
From: Rob Herring @ 2015-07-30 13:18 UTC (permalink / raw)
  To: Viresh Kumar
  Cc: Rafael Wysocki, Stephen Boyd, Nishanth Menon, Abhilash Kesavan,
	linaro-kernel, Kevin Hilman, linux-pm, Viswanath Puttagunta,
	Michael Turquette, Santosh Shilimkar, Bartlomiej Zolnierkiewicz,
	Mark Brown, Sudeep Holla, devicetree, Thomas Petazzoni,
	linux-arm-kernel, Lucas Stach

On Wed, Jul 29, 2015 at 5:52 AM, Viresh Kumar <viresh.kumar@linaro.org> wrote:
> More platform specific extended opp bindings will follow and it would be
> easy to manage them with a directory for opp. Lets create that and move
> the existing opp bindings into it.
>
> Cc: Rob Herring <rob.herring@linaro.org>

Use get_maintainers.pl please so you send to right people and right email.

> Cc: devicetree@vger.kernel.org
> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
> ---
>  Documentation/devicetree/bindings/power/{ => opp}/opp.txt | 0
>  1 file changed, 0 insertions(+), 0 deletions(-)
>  rename Documentation/devicetree/bindings/power/{ => opp}/opp.txt (100%)
>
> diff --git a/Documentation/devicetree/bindings/power/opp.txt b/Documentation/devicetree/bindings/power/opp/opp.txt
> similarity index 100%
> rename from Documentation/devicetree/bindings/power/opp.txt
> rename to Documentation/devicetree/bindings/power/opp/opp.txt

"power" seems to be a random collection of things. I'd prefer you move
this to .../bindings/opp/opp.txt.

Rob

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

* [PATCH V3 02/16] PM / OPP: Create a directory for opp bindings
@ 2015-07-30 13:18     ` Rob Herring
  0 siblings, 0 replies; 92+ messages in thread
From: Rob Herring @ 2015-07-30 13:18 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jul 29, 2015 at 5:52 AM, Viresh Kumar <viresh.kumar@linaro.org> wrote:
> More platform specific extended opp bindings will follow and it would be
> easy to manage them with a directory for opp. Lets create that and move
> the existing opp bindings into it.
>
> Cc: Rob Herring <rob.herring@linaro.org>

Use get_maintainers.pl please so you send to right people and right email.

> Cc: devicetree at vger.kernel.org
> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
> ---
>  Documentation/devicetree/bindings/power/{ => opp}/opp.txt | 0
>  1 file changed, 0 insertions(+), 0 deletions(-)
>  rename Documentation/devicetree/bindings/power/{ => opp}/opp.txt (100%)
>
> diff --git a/Documentation/devicetree/bindings/power/opp.txt b/Documentation/devicetree/bindings/power/opp/opp.txt
> similarity index 100%
> rename from Documentation/devicetree/bindings/power/opp.txt
> rename to Documentation/devicetree/bindings/power/opp/opp.txt

"power" seems to be a random collection of things. I'd prefer you move
this to .../bindings/opp/opp.txt.

Rob

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

* Re: [PATCH V3 01/16] PM / OPP: Update bindings to make opp-hz a 64 bit value
@ 2015-07-30 13:23     ` Rob Herring
  0 siblings, 0 replies; 92+ messages in thread
From: Rob Herring @ 2015-07-30 13:23 UTC (permalink / raw)
  To: Viresh Kumar
  Cc: Rafael Wysocki, Stephen Boyd, linaro-kernel, linux-pm,
	Arnd Bergmann, Nishanth Menon, Mark Brown, Michael Turquette,
	Sudeep Holla, Viswanath Puttagunta, Lucas Stach,
	Thomas Petazzoni, linux-arm-kernel, Thomas Abraham,
	Abhilash Kesavan, Kevin Hilman, Santosh Shilimkar,
	Bartlomiej Zolnierkiewicz, devicetree, Ian Campbell, Kumar Gala,
	open list, Mark Rutland, Pawel Moll, Rafael J. Wysocki,
	Rob Herring

On Wed, Jul 29, 2015 at 5:52 AM, Viresh Kumar <viresh.kumar@linaro.org> wrote:
> With a 32 bit value, the maximum frequency that the bindings can
> support is ~ 4 GHz. And that might fall short of what newer systems may
> have.

4GHz should be fast enough for anyone...

> Allow opp-hz to be a 64 bit big-endian value.
>
> Cc: Rob Herring <rob.herring@linaro.org>

Acked-by: Rob Herring <robh@kernel.org>

> Cc: devicetree@vger.kernel.org
> Suggested-by: Stephen Boyd <sboyd@codeaurora.org>
> Suggested-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
> ---
>  Documentation/devicetree/bindings/power/opp.txt | 40 ++++++++++++-------------
>  1 file changed, 20 insertions(+), 20 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/power/opp.txt b/Documentation/devicetree/bindings/power/opp.txt
> index 0d5e7c978121..0cb44dc21f97 100644
> --- a/Documentation/devicetree/bindings/power/opp.txt
> +++ b/Documentation/devicetree/bindings/power/opp.txt
> @@ -88,7 +88,7 @@ This defines voltage-current-frequency combinations along with other related
>  properties.
>
>  Required properties:
> -- opp-hz: Frequency in Hz
> +- opp-hz: Frequency in Hz, expressed as a 64-bit big-endian integer.
>
>  Optional properties:
>  - opp-microvolt: voltage in micro Volts.
> @@ -158,20 +158,20 @@ Example 1: Single cluster Dual-core ARM cortex A9, switch DVFS states together.
>                 opp-shared;
>
>                 opp00 {
> -                       opp-hz = <1000000000>;
> +                       opp-hz = /bits/ 64 <1000000000>;
>                         opp-microvolt = <970000 975000 985000>;
>                         opp-microamp = <70000>;
>                         clock-latency-ns = <300000>;
>                         opp-suspend;
>                 };
>                 opp01 {
> -                       opp-hz = <1100000000>;
> +                       opp-hz = /bits/ 64 <1100000000>;
>                         opp-microvolt = <980000 1000000 1010000>;
>                         opp-microamp = <80000>;
>                         clock-latency-ns = <310000>;
>                 };
>                 opp02 {
> -                       opp-hz = <1200000000>;
> +                       opp-hz = /bits/ 64 <1200000000>;
>                         opp-microvolt = <1025000>;
>                         clock-latency-ns = <290000>;
>                         turbo-mode;
> @@ -237,20 +237,20 @@ independently.
>                  */
>
>                 opp00 {
> -                       opp-hz = <1000000000>;
> +                       opp-hz = /bits/ 64 <1000000000>;
>                         opp-microvolt = <970000 975000 985000>;
>                         opp-microamp = <70000>;
>                         clock-latency-ns = <300000>;
>                         opp-suspend;
>                 };
>                 opp01 {
> -                       opp-hz = <1100000000>;
> +                       opp-hz = /bits/ 64 <1100000000>;
>                         opp-microvolt = <980000 1000000 1010000>;
>                         opp-microamp = <80000>;
>                         clock-latency-ns = <310000>;
>                 };
>                 opp02 {
> -                       opp-hz = <1200000000>;
> +                       opp-hz = /bits/ 64 <1200000000>;
>                         opp-microvolt = <1025000>;
>                         opp-microamp = <90000;
>                         lock-latency-ns = <290000>;
> @@ -313,20 +313,20 @@ DVFS state together.
>                 opp-shared;
>
>                 opp00 {
> -                       opp-hz = <1000000000>;
> +                       opp-hz = /bits/ 64 <1000000000>;
>                         opp-microvolt = <970000 975000 985000>;
>                         opp-microamp = <70000>;
>                         clock-latency-ns = <300000>;
>                         opp-suspend;
>                 };
>                 opp01 {
> -                       opp-hz = <1100000000>;
> +                       opp-hz = /bits/ 64 <1100000000>;
>                         opp-microvolt = <980000 1000000 1010000>;
>                         opp-microamp = <80000>;
>                         clock-latency-ns = <310000>;
>                 };
>                 opp02 {
> -                       opp-hz = <1200000000>;
> +                       opp-hz = /bits/ 64 <1200000000>;
>                         opp-microvolt = <1025000>;
>                         opp-microamp = <90000>;
>                         clock-latency-ns = <290000>;
> @@ -339,20 +339,20 @@ DVFS state together.
>                 opp-shared;
>
>                 opp10 {
> -                       opp-hz = <1300000000>;
> +                       opp-hz = /bits/ 64 <1300000000>;
>                         opp-microvolt = <1045000 1050000 1055000>;
>                         opp-microamp = <95000>;
>                         clock-latency-ns = <400000>;
>                         opp-suspend;
>                 };
>                 opp11 {
> -                       opp-hz = <1400000000>;
> +                       opp-hz = /bits/ 64 <1400000000>;
>                         opp-microvolt = <1075000>;
>                         opp-microamp = <100000>;
>                         clock-latency-ns = <400000>;
>                 };
>                 opp12 {
> -                       opp-hz = <1500000000>;
> +                       opp-hz = /bits/ 64 <1500000000>;
>                         opp-microvolt = <1010000 1100000 1110000>;
>                         opp-microamp = <95000>;
>                         clock-latency-ns = <400000>;
> @@ -379,7 +379,7 @@ Example 4: Handling multiple regulators
>                 opp-shared;
>
>                 opp00 {
> -                       opp-hz = <1000000000>;
> +                       opp-hz = /bits/ 64 <1000000000>;
>                         opp-microvolt = <970000>, /* Supply 0 */
>                                         <960000>, /* Supply 1 */
>                                         <960000>; /* Supply 2 */
> @@ -392,7 +392,7 @@ Example 4: Handling multiple regulators
>                 /* OR */
>
>                 opp00 {
> -                       opp-hz = <1000000000>;
> +                       opp-hz = /bits/ 64 <1000000000>;
>                         opp-microvolt = <970000 975000 985000>, /* Supply 0 */
>                                         <960000 965000 975000>, /* Supply 1 */
>                                         <960000 965000 975000>; /* Supply 2 */
> @@ -405,7 +405,7 @@ Example 4: Handling multiple regulators
>                 /* OR */
>
>                 opp00 {
> -                       opp-hz = <1000000000>;
> +                       opp-hz = /bits/ 64 <1000000000>;
>                         opp-microvolt = <970000 975000 985000>, /* Supply 0 */
>                                         <960000 965000 975000>, /* Supply 1 */
>                                         <960000 965000 975000>; /* Supply 2 */
> @@ -437,12 +437,12 @@ Example 5: Multiple OPP tables
>                 opp-shared;
>
>                 opp00 {
> -                       opp-hz = <600000000>;
> +                       opp-hz = /bits/ 64 <600000000>;
>                         ...
>                 };
>
>                 opp01 {
> -                       opp-hz = <800000000>;
> +                       opp-hz = /bits/ 64 <800000000>;
>                         ...
>                 };
>         };
> @@ -453,12 +453,12 @@ Example 5: Multiple OPP tables
>                 opp-shared;
>
>                 opp10 {
> -                       opp-hz = <1000000000>;
> +                       opp-hz = /bits/ 64 <1000000000>;
>                         ...
>                 };
>
>                 opp11 {
> -                       opp-hz = <1100000000>;
> +                       opp-hz = /bits/ 64 <1100000000>;
>                         ...
>                 };
>         };
> --
> 2.4.0
>

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

* Re: [PATCH V3 01/16] PM / OPP: Update bindings to make opp-hz a 64 bit value
@ 2015-07-30 13:23     ` Rob Herring
  0 siblings, 0 replies; 92+ messages in thread
From: Rob Herring @ 2015-07-30 13:23 UTC (permalink / raw)
  To: Viresh Kumar
  Cc: Rafael Wysocki, Stephen Boyd,
	linaro-kernel-cunTk1MwBs8s++Sfvej+rw,
	linux-pm-u79uwXL29TY76Z2rM5mHXA, Arnd Bergmann, Nishanth Menon,
	Mark Brown, Michael Turquette, Sudeep Holla,
	Viswanath Puttagunta, Lucas Stach, Thomas Petazzoni,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	Thomas Abraham, Abhilash Kesavan, Kevin Hilman,
	Santosh Shilimkar, Bartlomiej Zolnierkiewicz,
	devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org

On Wed, Jul 29, 2015 at 5:52 AM, Viresh Kumar <viresh.kumar-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org> wrote:
> With a 32 bit value, the maximum frequency that the bindings can
> support is ~ 4 GHz. And that might fall short of what newer systems may
> have.

4GHz should be fast enough for anyone...

> Allow opp-hz to be a 64 bit big-endian value.
>
> Cc: Rob Herring <rob.herring-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>

> Cc: devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> Suggested-by: Stephen Boyd <sboyd-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
> Suggested-by: Bartlomiej Zolnierkiewicz <b.zolnierkie-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
> Signed-off-by: Viresh Kumar <viresh.kumar-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> ---
>  Documentation/devicetree/bindings/power/opp.txt | 40 ++++++++++++-------------
>  1 file changed, 20 insertions(+), 20 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/power/opp.txt b/Documentation/devicetree/bindings/power/opp.txt
> index 0d5e7c978121..0cb44dc21f97 100644
> --- a/Documentation/devicetree/bindings/power/opp.txt
> +++ b/Documentation/devicetree/bindings/power/opp.txt
> @@ -88,7 +88,7 @@ This defines voltage-current-frequency combinations along with other related
>  properties.
>
>  Required properties:
> -- opp-hz: Frequency in Hz
> +- opp-hz: Frequency in Hz, expressed as a 64-bit big-endian integer.
>
>  Optional properties:
>  - opp-microvolt: voltage in micro Volts.
> @@ -158,20 +158,20 @@ Example 1: Single cluster Dual-core ARM cortex A9, switch DVFS states together.
>                 opp-shared;
>
>                 opp00 {
> -                       opp-hz = <1000000000>;
> +                       opp-hz = /bits/ 64 <1000000000>;
>                         opp-microvolt = <970000 975000 985000>;
>                         opp-microamp = <70000>;
>                         clock-latency-ns = <300000>;
>                         opp-suspend;
>                 };
>                 opp01 {
> -                       opp-hz = <1100000000>;
> +                       opp-hz = /bits/ 64 <1100000000>;
>                         opp-microvolt = <980000 1000000 1010000>;
>                         opp-microamp = <80000>;
>                         clock-latency-ns = <310000>;
>                 };
>                 opp02 {
> -                       opp-hz = <1200000000>;
> +                       opp-hz = /bits/ 64 <1200000000>;
>                         opp-microvolt = <1025000>;
>                         clock-latency-ns = <290000>;
>                         turbo-mode;
> @@ -237,20 +237,20 @@ independently.
>                  */
>
>                 opp00 {
> -                       opp-hz = <1000000000>;
> +                       opp-hz = /bits/ 64 <1000000000>;
>                         opp-microvolt = <970000 975000 985000>;
>                         opp-microamp = <70000>;
>                         clock-latency-ns = <300000>;
>                         opp-suspend;
>                 };
>                 opp01 {
> -                       opp-hz = <1100000000>;
> +                       opp-hz = /bits/ 64 <1100000000>;
>                         opp-microvolt = <980000 1000000 1010000>;
>                         opp-microamp = <80000>;
>                         clock-latency-ns = <310000>;
>                 };
>                 opp02 {
> -                       opp-hz = <1200000000>;
> +                       opp-hz = /bits/ 64 <1200000000>;
>                         opp-microvolt = <1025000>;
>                         opp-microamp = <90000;
>                         lock-latency-ns = <290000>;
> @@ -313,20 +313,20 @@ DVFS state together.
>                 opp-shared;
>
>                 opp00 {
> -                       opp-hz = <1000000000>;
> +                       opp-hz = /bits/ 64 <1000000000>;
>                         opp-microvolt = <970000 975000 985000>;
>                         opp-microamp = <70000>;
>                         clock-latency-ns = <300000>;
>                         opp-suspend;
>                 };
>                 opp01 {
> -                       opp-hz = <1100000000>;
> +                       opp-hz = /bits/ 64 <1100000000>;
>                         opp-microvolt = <980000 1000000 1010000>;
>                         opp-microamp = <80000>;
>                         clock-latency-ns = <310000>;
>                 };
>                 opp02 {
> -                       opp-hz = <1200000000>;
> +                       opp-hz = /bits/ 64 <1200000000>;
>                         opp-microvolt = <1025000>;
>                         opp-microamp = <90000>;
>                         clock-latency-ns = <290000>;
> @@ -339,20 +339,20 @@ DVFS state together.
>                 opp-shared;
>
>                 opp10 {
> -                       opp-hz = <1300000000>;
> +                       opp-hz = /bits/ 64 <1300000000>;
>                         opp-microvolt = <1045000 1050000 1055000>;
>                         opp-microamp = <95000>;
>                         clock-latency-ns = <400000>;
>                         opp-suspend;
>                 };
>                 opp11 {
> -                       opp-hz = <1400000000>;
> +                       opp-hz = /bits/ 64 <1400000000>;
>                         opp-microvolt = <1075000>;
>                         opp-microamp = <100000>;
>                         clock-latency-ns = <400000>;
>                 };
>                 opp12 {
> -                       opp-hz = <1500000000>;
> +                       opp-hz = /bits/ 64 <1500000000>;
>                         opp-microvolt = <1010000 1100000 1110000>;
>                         opp-microamp = <95000>;
>                         clock-latency-ns = <400000>;
> @@ -379,7 +379,7 @@ Example 4: Handling multiple regulators
>                 opp-shared;
>
>                 opp00 {
> -                       opp-hz = <1000000000>;
> +                       opp-hz = /bits/ 64 <1000000000>;
>                         opp-microvolt = <970000>, /* Supply 0 */
>                                         <960000>, /* Supply 1 */
>                                         <960000>; /* Supply 2 */
> @@ -392,7 +392,7 @@ Example 4: Handling multiple regulators
>                 /* OR */
>
>                 opp00 {
> -                       opp-hz = <1000000000>;
> +                       opp-hz = /bits/ 64 <1000000000>;
>                         opp-microvolt = <970000 975000 985000>, /* Supply 0 */
>                                         <960000 965000 975000>, /* Supply 1 */
>                                         <960000 965000 975000>; /* Supply 2 */
> @@ -405,7 +405,7 @@ Example 4: Handling multiple regulators
>                 /* OR */
>
>                 opp00 {
> -                       opp-hz = <1000000000>;
> +                       opp-hz = /bits/ 64 <1000000000>;
>                         opp-microvolt = <970000 975000 985000>, /* Supply 0 */
>                                         <960000 965000 975000>, /* Supply 1 */
>                                         <960000 965000 975000>; /* Supply 2 */
> @@ -437,12 +437,12 @@ Example 5: Multiple OPP tables
>                 opp-shared;
>
>                 opp00 {
> -                       opp-hz = <600000000>;
> +                       opp-hz = /bits/ 64 <600000000>;
>                         ...
>                 };
>
>                 opp01 {
> -                       opp-hz = <800000000>;
> +                       opp-hz = /bits/ 64 <800000000>;
>                         ...
>                 };
>         };
> @@ -453,12 +453,12 @@ Example 5: Multiple OPP tables
>                 opp-shared;
>
>                 opp10 {
> -                       opp-hz = <1000000000>;
> +                       opp-hz = /bits/ 64 <1000000000>;
>                         ...
>                 };
>
>                 opp11 {
> -                       opp-hz = <1100000000>;
> +                       opp-hz = /bits/ 64 <1100000000>;
>                         ...
>                 };
>         };
> --
> 2.4.0
>
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH V3 01/16] PM / OPP: Update bindings to make opp-hz a 64 bit value
@ 2015-07-30 13:23     ` Rob Herring
  0 siblings, 0 replies; 92+ messages in thread
From: Rob Herring @ 2015-07-30 13:23 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jul 29, 2015 at 5:52 AM, Viresh Kumar <viresh.kumar@linaro.org> wrote:
> With a 32 bit value, the maximum frequency that the bindings can
> support is ~ 4 GHz. And that might fall short of what newer systems may
> have.

4GHz should be fast enough for anyone...

> Allow opp-hz to be a 64 bit big-endian value.
>
> Cc: Rob Herring <rob.herring@linaro.org>

Acked-by: Rob Herring <robh@kernel.org>

> Cc: devicetree at vger.kernel.org
> Suggested-by: Stephen Boyd <sboyd@codeaurora.org>
> Suggested-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
> ---
>  Documentation/devicetree/bindings/power/opp.txt | 40 ++++++++++++-------------
>  1 file changed, 20 insertions(+), 20 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/power/opp.txt b/Documentation/devicetree/bindings/power/opp.txt
> index 0d5e7c978121..0cb44dc21f97 100644
> --- a/Documentation/devicetree/bindings/power/opp.txt
> +++ b/Documentation/devicetree/bindings/power/opp.txt
> @@ -88,7 +88,7 @@ This defines voltage-current-frequency combinations along with other related
>  properties.
>
>  Required properties:
> -- opp-hz: Frequency in Hz
> +- opp-hz: Frequency in Hz, expressed as a 64-bit big-endian integer.
>
>  Optional properties:
>  - opp-microvolt: voltage in micro Volts.
> @@ -158,20 +158,20 @@ Example 1: Single cluster Dual-core ARM cortex A9, switch DVFS states together.
>                 opp-shared;
>
>                 opp00 {
> -                       opp-hz = <1000000000>;
> +                       opp-hz = /bits/ 64 <1000000000>;
>                         opp-microvolt = <970000 975000 985000>;
>                         opp-microamp = <70000>;
>                         clock-latency-ns = <300000>;
>                         opp-suspend;
>                 };
>                 opp01 {
> -                       opp-hz = <1100000000>;
> +                       opp-hz = /bits/ 64 <1100000000>;
>                         opp-microvolt = <980000 1000000 1010000>;
>                         opp-microamp = <80000>;
>                         clock-latency-ns = <310000>;
>                 };
>                 opp02 {
> -                       opp-hz = <1200000000>;
> +                       opp-hz = /bits/ 64 <1200000000>;
>                         opp-microvolt = <1025000>;
>                         clock-latency-ns = <290000>;
>                         turbo-mode;
> @@ -237,20 +237,20 @@ independently.
>                  */
>
>                 opp00 {
> -                       opp-hz = <1000000000>;
> +                       opp-hz = /bits/ 64 <1000000000>;
>                         opp-microvolt = <970000 975000 985000>;
>                         opp-microamp = <70000>;
>                         clock-latency-ns = <300000>;
>                         opp-suspend;
>                 };
>                 opp01 {
> -                       opp-hz = <1100000000>;
> +                       opp-hz = /bits/ 64 <1100000000>;
>                         opp-microvolt = <980000 1000000 1010000>;
>                         opp-microamp = <80000>;
>                         clock-latency-ns = <310000>;
>                 };
>                 opp02 {
> -                       opp-hz = <1200000000>;
> +                       opp-hz = /bits/ 64 <1200000000>;
>                         opp-microvolt = <1025000>;
>                         opp-microamp = <90000;
>                         lock-latency-ns = <290000>;
> @@ -313,20 +313,20 @@ DVFS state together.
>                 opp-shared;
>
>                 opp00 {
> -                       opp-hz = <1000000000>;
> +                       opp-hz = /bits/ 64 <1000000000>;
>                         opp-microvolt = <970000 975000 985000>;
>                         opp-microamp = <70000>;
>                         clock-latency-ns = <300000>;
>                         opp-suspend;
>                 };
>                 opp01 {
> -                       opp-hz = <1100000000>;
> +                       opp-hz = /bits/ 64 <1100000000>;
>                         opp-microvolt = <980000 1000000 1010000>;
>                         opp-microamp = <80000>;
>                         clock-latency-ns = <310000>;
>                 };
>                 opp02 {
> -                       opp-hz = <1200000000>;
> +                       opp-hz = /bits/ 64 <1200000000>;
>                         opp-microvolt = <1025000>;
>                         opp-microamp = <90000>;
>                         clock-latency-ns = <290000>;
> @@ -339,20 +339,20 @@ DVFS state together.
>                 opp-shared;
>
>                 opp10 {
> -                       opp-hz = <1300000000>;
> +                       opp-hz = /bits/ 64 <1300000000>;
>                         opp-microvolt = <1045000 1050000 1055000>;
>                         opp-microamp = <95000>;
>                         clock-latency-ns = <400000>;
>                         opp-suspend;
>                 };
>                 opp11 {
> -                       opp-hz = <1400000000>;
> +                       opp-hz = /bits/ 64 <1400000000>;
>                         opp-microvolt = <1075000>;
>                         opp-microamp = <100000>;
>                         clock-latency-ns = <400000>;
>                 };
>                 opp12 {
> -                       opp-hz = <1500000000>;
> +                       opp-hz = /bits/ 64 <1500000000>;
>                         opp-microvolt = <1010000 1100000 1110000>;
>                         opp-microamp = <95000>;
>                         clock-latency-ns = <400000>;
> @@ -379,7 +379,7 @@ Example 4: Handling multiple regulators
>                 opp-shared;
>
>                 opp00 {
> -                       opp-hz = <1000000000>;
> +                       opp-hz = /bits/ 64 <1000000000>;
>                         opp-microvolt = <970000>, /* Supply 0 */
>                                         <960000>, /* Supply 1 */
>                                         <960000>; /* Supply 2 */
> @@ -392,7 +392,7 @@ Example 4: Handling multiple regulators
>                 /* OR */
>
>                 opp00 {
> -                       opp-hz = <1000000000>;
> +                       opp-hz = /bits/ 64 <1000000000>;
>                         opp-microvolt = <970000 975000 985000>, /* Supply 0 */
>                                         <960000 965000 975000>, /* Supply 1 */
>                                         <960000 965000 975000>; /* Supply 2 */
> @@ -405,7 +405,7 @@ Example 4: Handling multiple regulators
>                 /* OR */
>
>                 opp00 {
> -                       opp-hz = <1000000000>;
> +                       opp-hz = /bits/ 64 <1000000000>;
>                         opp-microvolt = <970000 975000 985000>, /* Supply 0 */
>                                         <960000 965000 975000>, /* Supply 1 */
>                                         <960000 965000 975000>; /* Supply 2 */
> @@ -437,12 +437,12 @@ Example 5: Multiple OPP tables
>                 opp-shared;
>
>                 opp00 {
> -                       opp-hz = <600000000>;
> +                       opp-hz = /bits/ 64 <600000000>;
>                         ...
>                 };
>
>                 opp01 {
> -                       opp-hz = <800000000>;
> +                       opp-hz = /bits/ 64 <800000000>;
>                         ...
>                 };
>         };
> @@ -453,12 +453,12 @@ Example 5: Multiple OPP tables
>                 opp-shared;
>
>                 opp10 {
> -                       opp-hz = <1000000000>;
> +                       opp-hz = /bits/ 64 <1000000000>;
>                         ...
>                 };
>
>                 opp11 {
> -                       opp-hz = <1100000000>;
> +                       opp-hz = /bits/ 64 <1100000000>;
>                         ...
>                 };
>         };
> --
> 2.4.0
>

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

* Re: [PATCH V3 02/16] PM / OPP: Create a directory for opp bindings
  2015-07-30 13:18     ` Rob Herring
@ 2015-07-30 13:49       ` Viresh Kumar
  -1 siblings, 0 replies; 92+ messages in thread
From: Viresh Kumar @ 2015-07-30 13:49 UTC (permalink / raw)
  To: Rob Herring
  Cc: Rafael Wysocki, Stephen Boyd, Nishanth Menon, Abhilash Kesavan,
	linaro-kernel, Kevin Hilman, linux-pm, Viswanath Puttagunta,
	Michael Turquette, Santosh Shilimkar, Bartlomiej Zolnierkiewicz,
	Mark Brown, Sudeep Holla, devicetree, Thomas Petazzoni,
	linux-arm-kernel, Lucas Stach

On 30-07-15, 08:18, Rob Herring wrote:
> On Wed, Jul 29, 2015 at 5:52 AM, Viresh Kumar <viresh.kumar@linaro.org> wrote:
> > More platform specific extended opp bindings will follow and it would be
> > easy to manage them with a directory for opp. Lets create that and move
> > the existing opp bindings into it.
> >
> > Cc: Rob Herring <rob.herring@linaro.org>
> 
> Use get_maintainers.pl please so you send to right people and right email.

Already done, you were just cc'd as an extra guy :)

> > Cc: devicetree@vger.kernel.org
> > Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
> > ---
> >  Documentation/devicetree/bindings/power/{ => opp}/opp.txt | 0
> >  1 file changed, 0 insertions(+), 0 deletions(-)
> >  rename Documentation/devicetree/bindings/power/{ => opp}/opp.txt (100%)
> >
> > diff --git a/Documentation/devicetree/bindings/power/opp.txt b/Documentation/devicetree/bindings/power/opp/opp.txt
> > similarity index 100%
> > rename from Documentation/devicetree/bindings/power/opp.txt
> > rename to Documentation/devicetree/bindings/power/opp/opp.txt
> 
> "power" seems to be a random collection of things. I'd prefer you move
> this to .../bindings/opp/opp.txt.

Hmm, sure. That would be better I think.

--------------8<-------------------

Message-Id: <29597667e2c8afdbf396c5fcc9269fb27794131c.1438264123.git.viresh.kumar@linaro.org>
From: Viresh Kumar <viresh.kumar@linaro.org>
Date: Mon, 27 Jul 2015 10:04:21 +0530
Subject: [PATCH] PM / OPP: Create a directory for opp bindings

More platform specific extended opp bindings will follow and it would be
easy to manage them with a directory for opp. Lets create that and move
the existing opp bindings into it.

Cc: Rob Herring <rob.herring@linaro.org>
Cc: devicetree@vger.kernel.org
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 Documentation/devicetree/bindings/{power => opp}/opp.txt | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 rename Documentation/devicetree/bindings/{power => opp}/opp.txt (100%)

diff --git a/Documentation/devicetree/bindings/power/opp.txt b/Documentation/devicetree/bindings/opp/opp.txt
similarity index 100%
rename from Documentation/devicetree/bindings/power/opp.txt
rename to Documentation/devicetree/bindings/opp/opp.txt

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

* [PATCH V3 02/16] PM / OPP: Create a directory for opp bindings
@ 2015-07-30 13:49       ` Viresh Kumar
  0 siblings, 0 replies; 92+ messages in thread
From: Viresh Kumar @ 2015-07-30 13:49 UTC (permalink / raw)
  To: linux-arm-kernel

On 30-07-15, 08:18, Rob Herring wrote:
> On Wed, Jul 29, 2015 at 5:52 AM, Viresh Kumar <viresh.kumar@linaro.org> wrote:
> > More platform specific extended opp bindings will follow and it would be
> > easy to manage them with a directory for opp. Lets create that and move
> > the existing opp bindings into it.
> >
> > Cc: Rob Herring <rob.herring@linaro.org>
> 
> Use get_maintainers.pl please so you send to right people and right email.

Already done, you were just cc'd as an extra guy :)

> > Cc: devicetree at vger.kernel.org
> > Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
> > ---
> >  Documentation/devicetree/bindings/power/{ => opp}/opp.txt | 0
> >  1 file changed, 0 insertions(+), 0 deletions(-)
> >  rename Documentation/devicetree/bindings/power/{ => opp}/opp.txt (100%)
> >
> > diff --git a/Documentation/devicetree/bindings/power/opp.txt b/Documentation/devicetree/bindings/power/opp/opp.txt
> > similarity index 100%
> > rename from Documentation/devicetree/bindings/power/opp.txt
> > rename to Documentation/devicetree/bindings/power/opp/opp.txt
> 
> "power" seems to be a random collection of things. I'd prefer you move
> this to .../bindings/opp/opp.txt.

Hmm, sure. That would be better I think.

--------------8<-------------------

Message-Id: <29597667e2c8afdbf396c5fcc9269fb27794131c.1438264123.git.viresh.kumar@linaro.org>
From: Viresh Kumar <viresh.kumar@linaro.org>
Date: Mon, 27 Jul 2015 10:04:21 +0530
Subject: [PATCH] PM / OPP: Create a directory for opp bindings

More platform specific extended opp bindings will follow and it would be
easy to manage them with a directory for opp. Lets create that and move
the existing opp bindings into it.

Cc: Rob Herring <rob.herring@linaro.org>
Cc: devicetree at vger.kernel.org
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 Documentation/devicetree/bindings/{power => opp}/opp.txt | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 rename Documentation/devicetree/bindings/{power => opp}/opp.txt (100%)

diff --git a/Documentation/devicetree/bindings/power/opp.txt b/Documentation/devicetree/bindings/opp/opp.txt
similarity index 100%
rename from Documentation/devicetree/bindings/power/opp.txt
rename to Documentation/devicetree/bindings/opp/opp.txt

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

* Re: [PATCH V3 02/16] PM / OPP: Create a directory for opp bindings
  2015-07-30 13:49       ` Viresh Kumar
@ 2015-07-30 16:24         ` Rob Herring
  -1 siblings, 0 replies; 92+ messages in thread
From: Rob Herring @ 2015-07-30 16:24 UTC (permalink / raw)
  To: Viresh Kumar
  Cc: Rafael Wysocki, Stephen Boyd, Nishanth Menon, Abhilash Kesavan,
	linaro-kernel, Kevin Hilman, linux-pm, Viswanath Puttagunta,
	Michael Turquette, Santosh Shilimkar, Bartlomiej Zolnierkiewicz,
	Mark Brown, Sudeep Holla, devicetree, Thomas Petazzoni,
	linux-arm-kernel, Lucas Stach

On Thu, Jul 30, 2015 at 8:49 AM, Viresh Kumar <viresh.kumar@linaro.org> wrote:
> On 30-07-15, 08:18, Rob Herring wrote:
>> On Wed, Jul 29, 2015 at 5:52 AM, Viresh Kumar <viresh.kumar@linaro.org> wrote:
>> > More platform specific extended opp bindings will follow and it would be
>> > easy to manage them with a directory for opp. Lets create that and move
>> > the existing opp bindings into it.
>> >
>> > Cc: Rob Herring <rob.herring@linaro.org>
>>
>> Use get_maintainers.pl please so you send to right people and right email.
>
> Already done, you were just cc'd as an extra guy :)

No, because no one that is a maintainer of
Documentation/devicetree/bindings is cc'ed here. You did on the other
patch, but not here as neither Ian, Mark, Kumar nor Pawel are cc'ed.

>> > Cc: devicetree@vger.kernel.org
>> > Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
>> > ---
>> >  Documentation/devicetree/bindings/power/{ => opp}/opp.txt | 0
>> >  1 file changed, 0 insertions(+), 0 deletions(-)
>> >  rename Documentation/devicetree/bindings/power/{ => opp}/opp.txt (100%)
>> >
>> > diff --git a/Documentation/devicetree/bindings/power/opp.txt b/Documentation/devicetree/bindings/power/opp/opp.txt
>> > similarity index 100%
>> > rename from Documentation/devicetree/bindings/power/opp.txt
>> > rename to Documentation/devicetree/bindings/power/opp/opp.txt
>>
>> "power" seems to be a random collection of things. I'd prefer you move
>> this to .../bindings/opp/opp.txt.
>
> Hmm, sure. That would be better I think.
>
> --------------8<-------------------
>
> Message-Id: <29597667e2c8afdbf396c5fcc9269fb27794131c.1438264123.git.viresh.kumar@linaro.org>
> From: Viresh Kumar <viresh.kumar@linaro.org>
> Date: Mon, 27 Jul 2015 10:04:21 +0530
> Subject: [PATCH] PM / OPP: Create a directory for opp bindings
>
> More platform specific extended opp bindings will follow and it would be
> easy to manage them with a directory for opp. Lets create that and move
> the existing opp bindings into it.
>
> Cc: Rob Herring <rob.herring@linaro.org>

Still wrong...


> Cc: devicetree@vger.kernel.org
> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
> ---
>  Documentation/devicetree/bindings/{power => opp}/opp.txt | 0
>  1 file changed, 0 insertions(+), 0 deletions(-)
>  rename Documentation/devicetree/bindings/{power => opp}/opp.txt (100%)
>
> diff --git a/Documentation/devicetree/bindings/power/opp.txt b/Documentation/devicetree/bindings/opp/opp.txt
> similarity index 100%
> rename from Documentation/devicetree/bindings/power/opp.txt
> rename to Documentation/devicetree/bindings/opp/opp.txt

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

* [PATCH V3 02/16] PM / OPP: Create a directory for opp bindings
@ 2015-07-30 16:24         ` Rob Herring
  0 siblings, 0 replies; 92+ messages in thread
From: Rob Herring @ 2015-07-30 16:24 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Jul 30, 2015 at 8:49 AM, Viresh Kumar <viresh.kumar@linaro.org> wrote:
> On 30-07-15, 08:18, Rob Herring wrote:
>> On Wed, Jul 29, 2015 at 5:52 AM, Viresh Kumar <viresh.kumar@linaro.org> wrote:
>> > More platform specific extended opp bindings will follow and it would be
>> > easy to manage them with a directory for opp. Lets create that and move
>> > the existing opp bindings into it.
>> >
>> > Cc: Rob Herring <rob.herring@linaro.org>
>>
>> Use get_maintainers.pl please so you send to right people and right email.
>
> Already done, you were just cc'd as an extra guy :)

No, because no one that is a maintainer of
Documentation/devicetree/bindings is cc'ed here. You did on the other
patch, but not here as neither Ian, Mark, Kumar nor Pawel are cc'ed.

>> > Cc: devicetree at vger.kernel.org
>> > Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
>> > ---
>> >  Documentation/devicetree/bindings/power/{ => opp}/opp.txt | 0
>> >  1 file changed, 0 insertions(+), 0 deletions(-)
>> >  rename Documentation/devicetree/bindings/power/{ => opp}/opp.txt (100%)
>> >
>> > diff --git a/Documentation/devicetree/bindings/power/opp.txt b/Documentation/devicetree/bindings/power/opp/opp.txt
>> > similarity index 100%
>> > rename from Documentation/devicetree/bindings/power/opp.txt
>> > rename to Documentation/devicetree/bindings/power/opp/opp.txt
>>
>> "power" seems to be a random collection of things. I'd prefer you move
>> this to .../bindings/opp/opp.txt.
>
> Hmm, sure. That would be better I think.
>
> --------------8<-------------------
>
> Message-Id: <29597667e2c8afdbf396c5fcc9269fb27794131c.1438264123.git.viresh.kumar@linaro.org>
> From: Viresh Kumar <viresh.kumar@linaro.org>
> Date: Mon, 27 Jul 2015 10:04:21 +0530
> Subject: [PATCH] PM / OPP: Create a directory for opp bindings
>
> More platform specific extended opp bindings will follow and it would be
> easy to manage them with a directory for opp. Lets create that and move
> the existing opp bindings into it.
>
> Cc: Rob Herring <rob.herring@linaro.org>

Still wrong...


> Cc: devicetree at vger.kernel.org
> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
> ---
>  Documentation/devicetree/bindings/{power => opp}/opp.txt | 0
>  1 file changed, 0 insertions(+), 0 deletions(-)
>  rename Documentation/devicetree/bindings/{power => opp}/opp.txt (100%)
>
> diff --git a/Documentation/devicetree/bindings/power/opp.txt b/Documentation/devicetree/bindings/opp/opp.txt
> similarity index 100%
> rename from Documentation/devicetree/bindings/power/opp.txt
> rename to Documentation/devicetree/bindings/opp/opp.txt

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

* Re: [PATCH V3 02/16] PM / OPP: Create a directory for opp bindings
  2015-07-30 16:24         ` Rob Herring
@ 2015-07-30 16:52           ` Viresh Kumar
  -1 siblings, 0 replies; 92+ messages in thread
From: Viresh Kumar @ 2015-07-30 16:52 UTC (permalink / raw)
  To: Rob Herring, Joe Perches
  Cc: Rafael Wysocki, Stephen Boyd, Nishanth Menon, Abhilash Kesavan,
	linaro-kernel, Kevin Hilman, linux-pm, Viswanath Puttagunta,
	Michael Turquette, Santosh Shilimkar, Bartlomiej Zolnierkiewicz,
	Mark Brown, Sudeep Holla, devicetree, Thomas Petazzoni,
	linux-arm-kernel, Lucas Stach

On 30-07-15, 11:24, Rob Herring wrote:
> On Thu, Jul 30, 2015 at 8:49 AM, Viresh Kumar <viresh.kumar@linaro.org> wrote:
> > On 30-07-15, 08:18, Rob Herring wrote:
> >> On Wed, Jul 29, 2015 at 5:52 AM, Viresh Kumar <viresh.kumar@linaro.org> wrote:
> >> > More platform specific extended opp bindings will follow and it would be
> >> > easy to manage them with a directory for opp. Lets create that and move
> >> > the existing opp bindings into it.
> >> >
> >> > Cc: Rob Herring <rob.herring@linaro.org>
> >>
> >> Use get_maintainers.pl please so you send to right people and right email.
> >
> > Already done, you were just cc'd as an extra guy :)
> 
> No, because no one that is a maintainer of
> Documentation/devicetree/bindings is cc'ed here. You did on the other
> patch, but not here as neither Ian, Mark, Kumar nor Pawel are cc'ed.

No. I sent all of them together and get_maintainers is invoked for all
of them. I checked again and its a bug with get_maintainers.

@Joe: Can you please take a look at that?

Problem description: Because my patch only had this:

-----------8<-------------

---
 Documentation/devicetree/bindings/{power => opp}/opp.txt | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 rename Documentation/devicetree/bindings/{power => opp}/opp.txt (100%)

diff --git a/Documentation/devicetree/bindings/power/opp.txt b/Documentation/devicetree/bindings/opp/opp.txt
similarity index 100%
rename from Documentation/devicetree/bindings/power/opp.txt
rename to Documentation/devicetree/bindings/opp/opp.txt

------------>8------------

get_maintainers reports this for the patch:

scripts/get_maintainer.pl: file
'0001-PM-OPP-Create-a-directory-for-opp-bindings.patch' doesn't appear
to be a patch.  Add -f to options?

 
> > Cc: Rob Herring <rob.herring@linaro.org>
> 
> Still wrong...

Let me send the patch as reply to this one, with personally cc'ing all
people you want me to.

-- 
viresh

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

* [PATCH V3 02/16] PM / OPP: Create a directory for opp bindings
@ 2015-07-30 16:52           ` Viresh Kumar
  0 siblings, 0 replies; 92+ messages in thread
From: Viresh Kumar @ 2015-07-30 16:52 UTC (permalink / raw)
  To: linux-arm-kernel

On 30-07-15, 11:24, Rob Herring wrote:
> On Thu, Jul 30, 2015 at 8:49 AM, Viresh Kumar <viresh.kumar@linaro.org> wrote:
> > On 30-07-15, 08:18, Rob Herring wrote:
> >> On Wed, Jul 29, 2015 at 5:52 AM, Viresh Kumar <viresh.kumar@linaro.org> wrote:
> >> > More platform specific extended opp bindings will follow and it would be
> >> > easy to manage them with a directory for opp. Lets create that and move
> >> > the existing opp bindings into it.
> >> >
> >> > Cc: Rob Herring <rob.herring@linaro.org>
> >>
> >> Use get_maintainers.pl please so you send to right people and right email.
> >
> > Already done, you were just cc'd as an extra guy :)
> 
> No, because no one that is a maintainer of
> Documentation/devicetree/bindings is cc'ed here. You did on the other
> patch, but not here as neither Ian, Mark, Kumar nor Pawel are cc'ed.

No. I sent all of them together and get_maintainers is invoked for all
of them. I checked again and its a bug with get_maintainers.

@Joe: Can you please take a look at that?

Problem description: Because my patch only had this:

-----------8<-------------

---
 Documentation/devicetree/bindings/{power => opp}/opp.txt | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 rename Documentation/devicetree/bindings/{power => opp}/opp.txt (100%)

diff --git a/Documentation/devicetree/bindings/power/opp.txt b/Documentation/devicetree/bindings/opp/opp.txt
similarity index 100%
rename from Documentation/devicetree/bindings/power/opp.txt
rename to Documentation/devicetree/bindings/opp/opp.txt

------------>8------------

get_maintainers reports this for the patch:

scripts/get_maintainer.pl: file
'0001-PM-OPP-Create-a-directory-for-opp-bindings.patch' doesn't appear
to be a patch.  Add -f to options?

 
> > Cc: Rob Herring <rob.herring@linaro.org>
> 
> Still wrong...

Let me send the patch as reply to this one, with personally cc'ing all
people you want me to.

-- 
viresh

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

* [PATCH V3 resend] PM / OPP: Create a directory for opp bindings
  2015-07-30 16:52           ` Viresh Kumar
@ 2015-07-30 16:57             ` Viresh Kumar
  -1 siblings, 0 replies; 92+ messages in thread
From: Viresh Kumar @ 2015-07-30 16:57 UTC (permalink / raw)
  To: Rafael Wysocki, rob.herring
  Cc: linaro-kernel, linux-pm, arnd.bergmann, nm, broonie, mturquette,
	sboyd, Sudeep.Holla, viswanath.puttagunta, l.stach,
	thomas.petazzoni, linux-arm-kernel, ta.omasab, kesavan.abhilash,
	khilman, santosh.shilimkar, b.zolnierkie, pawel.moll,
	mark.rutland, ijc+devicetree, galak, devicetree, Viresh Kumar

More platform specific extended opp bindings will follow and it would be
easy to manage them with a directory for opp. Lets create that and move
the existing opp bindings into it.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
Resending to get cc list fixed, which isn't getting populated due to a
bug with get_maintainers.

 Documentation/devicetree/bindings/{power => opp}/opp.txt | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 rename Documentation/devicetree/bindings/{power => opp}/opp.txt (100%)

diff --git a/Documentation/devicetree/bindings/power/opp.txt b/Documentation/devicetree/bindings/opp/opp.txt
similarity index 100%
rename from Documentation/devicetree/bindings/power/opp.txt
rename to Documentation/devicetree/bindings/opp/opp.txt
-- 
2.4.0


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

* [PATCH V3 resend] PM / OPP: Create a directory for opp bindings
@ 2015-07-30 16:57             ` Viresh Kumar
  0 siblings, 0 replies; 92+ messages in thread
From: Viresh Kumar @ 2015-07-30 16:57 UTC (permalink / raw)
  To: linux-arm-kernel

More platform specific extended opp bindings will follow and it would be
easy to manage them with a directory for opp. Lets create that and move
the existing opp bindings into it.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
Resending to get cc list fixed, which isn't getting populated due to a
bug with get_maintainers.

 Documentation/devicetree/bindings/{power => opp}/opp.txt | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 rename Documentation/devicetree/bindings/{power => opp}/opp.txt (100%)

diff --git a/Documentation/devicetree/bindings/power/opp.txt b/Documentation/devicetree/bindings/opp/opp.txt
similarity index 100%
rename from Documentation/devicetree/bindings/power/opp.txt
rename to Documentation/devicetree/bindings/opp/opp.txt
-- 
2.4.0

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

* Re: [PATCH V3 06/16] PM / OPP: Break _opp_add_dynamic() into smaller functions
  2015-07-29 10:53   ` Viresh Kumar
@ 2015-07-31  5:43     ` Stephen Boyd
  -1 siblings, 0 replies; 92+ messages in thread
From: Stephen Boyd @ 2015-07-31  5:43 UTC (permalink / raw)
  To: Viresh Kumar
  Cc: Rafael Wysocki, linaro-kernel, linux-pm, rob.herring,
	arnd.bergmann, nm, broonie, mturquette, Sudeep.Holla,
	viswanath.puttagunta, l.stach, thomas.petazzoni,
	linux-arm-kernel, ta.omasab, kesavan.abhilash, khilman,
	santosh.shilimkar, b.zolnierkie, Greg Kroah-Hartman, Len Brown,
	open list, Pavel Machek

On 07/29, Viresh Kumar wrote:
> Later commits would add support for new OPP bindings and this would be
> required then. So, lets do it in a separate patch to make it easily
> reviewable.
> 
> Another change worth noticing is INIT_LIST_HEAD(&opp->node). We weren't
> doing it earlier as we never tried to delete a list node before it is
> added to list. But this wouldn't be the case anymore. We might try to
> delete a node (just to reuse the same code paths), without it being
> getting added to the list.
> 
> Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
> ---

Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

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

* [PATCH V3 06/16] PM / OPP: Break _opp_add_dynamic() into smaller functions
@ 2015-07-31  5:43     ` Stephen Boyd
  0 siblings, 0 replies; 92+ messages in thread
From: Stephen Boyd @ 2015-07-31  5:43 UTC (permalink / raw)
  To: linux-arm-kernel

On 07/29, Viresh Kumar wrote:
> Later commits would add support for new OPP bindings and this would be
> required then. So, lets do it in a separate patch to make it easily
> reviewable.
> 
> Another change worth noticing is INIT_LIST_HEAD(&opp->node). We weren't
> doing it earlier as we never tried to delete a list node before it is
> added to list. But this wouldn't be the case anymore. We might try to
> delete a node (just to reuse the same code paths), without it being
> getting added to the list.
> 
> Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
> ---

Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

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

* Re: [PATCH V3 07/16] PM / OPP: Add support to parse "operating-points-v2" bindings
  2015-07-29 10:53   ` Viresh Kumar
@ 2015-07-31  5:51     ` Stephen Boyd
  -1 siblings, 0 replies; 92+ messages in thread
From: Stephen Boyd @ 2015-07-31  5:51 UTC (permalink / raw)
  To: Viresh Kumar
  Cc: Rafael Wysocki, linaro-kernel, linux-pm, rob.herring,
	arnd.bergmann, nm, broonie, mturquette, Sudeep.Holla,
	viswanath.puttagunta, l.stach, thomas.petazzoni,
	linux-arm-kernel, ta.omasab, kesavan.abhilash, khilman,
	santosh.shilimkar, b.zolnierkie, Greg Kroah-Hartman, Len Brown,
	open list, Pavel Machek

On 07/29, Viresh Kumar wrote:
> This adds support in OPP library to parse and create list of OPPs from
> operating-points-v2 bindings. It takes care of most of the properties of
> new bindings (except shared-opp, which will be handled separately).
> 
> For backward compatibility, we keep supporting earlier bindings. We try
> to search for the new bindings first, in case they aren't present we
> look for the old deprecated ones.
> 
> There are few things marked as TODO:
> - Support for multiple OPP tables
> - Support for multiple regulators
> 
> They should be fixed separately.
> 
> Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>

Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>

One question below:

> @@ -679,6 +691,125 @@ static int _opp_add_dynamic(struct device *dev, unsigned long freq,
>  	return ret;
>  }
>  
> +/* TODO: Support multiple regulators */
> +static int opp_get_microvolt(struct dev_pm_opp *opp, struct device *dev)
> +{
> +	u32 microvolt[3] = {0};
> +	int count, ret;
> +
> +	count = of_property_count_u32_elems(opp->np, "opp-microvolt");
> +	if (!count)
> +		return 0;
> +
> +	/* There can be one or three elements here */
> +	if (count != 1 && count != 3) {
> +		dev_err(dev, "%s: Invalid number of elements in opp-microvolt property (%d)\n",
> +			__func__, count);
> +		return -EINVAL;
> +	}
> +
> +	ret = of_property_read_u32_array(opp->np, "opp-microvolt", microvolt,
> +					 count);
> +	if (ret) {
> +		dev_err(dev, "%s: error parsing opp-microvolt: %d\n", __func__,
> +			ret);
> +		return -EINVAL;
> +	}
> +
> +	opp->u_volt = microvolt[0];
> +	opp->u_volt_min = microvolt[1];
> +	opp->u_volt_max = microvolt[2];

Should the default be 0 and ULONG_MAX for volt_min/volt_max when
there's on element?

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

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

* [PATCH V3 07/16] PM / OPP: Add support to parse "operating-points-v2" bindings
@ 2015-07-31  5:51     ` Stephen Boyd
  0 siblings, 0 replies; 92+ messages in thread
From: Stephen Boyd @ 2015-07-31  5:51 UTC (permalink / raw)
  To: linux-arm-kernel

On 07/29, Viresh Kumar wrote:
> This adds support in OPP library to parse and create list of OPPs from
> operating-points-v2 bindings. It takes care of most of the properties of
> new bindings (except shared-opp, which will be handled separately).
> 
> For backward compatibility, we keep supporting earlier bindings. We try
> to search for the new bindings first, in case they aren't present we
> look for the old deprecated ones.
> 
> There are few things marked as TODO:
> - Support for multiple OPP tables
> - Support for multiple regulators
> 
> They should be fixed separately.
> 
> Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>

Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>

One question below:

> @@ -679,6 +691,125 @@ static int _opp_add_dynamic(struct device *dev, unsigned long freq,
>  	return ret;
>  }
>  
> +/* TODO: Support multiple regulators */
> +static int opp_get_microvolt(struct dev_pm_opp *opp, struct device *dev)
> +{
> +	u32 microvolt[3] = {0};
> +	int count, ret;
> +
> +	count = of_property_count_u32_elems(opp->np, "opp-microvolt");
> +	if (!count)
> +		return 0;
> +
> +	/* There can be one or three elements here */
> +	if (count != 1 && count != 3) {
> +		dev_err(dev, "%s: Invalid number of elements in opp-microvolt property (%d)\n",
> +			__func__, count);
> +		return -EINVAL;
> +	}
> +
> +	ret = of_property_read_u32_array(opp->np, "opp-microvolt", microvolt,
> +					 count);
> +	if (ret) {
> +		dev_err(dev, "%s: error parsing opp-microvolt: %d\n", __func__,
> +			ret);
> +		return -EINVAL;
> +	}
> +
> +	opp->u_volt = microvolt[0];
> +	opp->u_volt_min = microvolt[1];
> +	opp->u_volt_max = microvolt[2];

Should the default be 0 and ULONG_MAX for volt_min/volt_max when
there's on element?

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

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

* Re: [PATCH V3 07/16] PM / OPP: Add support to parse "operating-points-v2" bindings
  2015-07-31  5:51     ` Stephen Boyd
@ 2015-07-31  5:58       ` Viresh Kumar
  -1 siblings, 0 replies; 92+ messages in thread
From: Viresh Kumar @ 2015-07-31  5:58 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Rafael Wysocki, linaro-kernel, linux-pm, rob.herring,
	arnd.bergmann, nm, broonie, mturquette, Sudeep.Holla,
	viswanath.puttagunta, l.stach, thomas.petazzoni,
	linux-arm-kernel, ta.omasab, kesavan.abhilash, khilman,
	santosh.shilimkar, b.zolnierkie, Greg Kroah-Hartman, Len Brown,
	open list, Pavel Machek

On 30-07-15, 22:51, Stephen Boyd wrote:
> > +	opp->u_volt = microvolt[0];
> > +	opp->u_volt_min = microvolt[1];
> > +	opp->u_volt_max = microvolt[2];
> 
> Should the default be 0 and ULONG_MAX for volt_min/volt_max when
> there's on element?

I am not still sure how the regulator API is going to look like for
this target/min/max thing. So, lets defer it until that is resolved.
For now they are initialized to 0.

And, because the user has just passed in a target voltage, maybe all
three must be == u_volt. :)

-- 
viresh

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

* [PATCH V3 07/16] PM / OPP: Add support to parse "operating-points-v2" bindings
@ 2015-07-31  5:58       ` Viresh Kumar
  0 siblings, 0 replies; 92+ messages in thread
From: Viresh Kumar @ 2015-07-31  5:58 UTC (permalink / raw)
  To: linux-arm-kernel

On 30-07-15, 22:51, Stephen Boyd wrote:
> > +	opp->u_volt = microvolt[0];
> > +	opp->u_volt_min = microvolt[1];
> > +	opp->u_volt_max = microvolt[2];
> 
> Should the default be 0 and ULONG_MAX for volt_min/volt_max when
> there's on element?

I am not still sure how the regulator API is going to look like for
this target/min/max thing. So, lets defer it until that is resolved.
For now they are initialized to 0.

And, because the user has just passed in a target voltage, maybe all
three must be == u_volt. :)

-- 
viresh

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

* Re: [PATCH V3 11/16] PM / OPP: Add helpers for initializing CPU OPPs
  2015-07-29 10:53   ` Viresh Kumar
@ 2015-07-31  6:07     ` Stephen Boyd
  -1 siblings, 0 replies; 92+ messages in thread
From: Stephen Boyd @ 2015-07-31  6:07 UTC (permalink / raw)
  To: Viresh Kumar
  Cc: Rafael Wysocki, linaro-kernel, linux-pm, rob.herring,
	arnd.bergmann, nm, broonie, mturquette, Sudeep.Holla,
	viswanath.puttagunta, l.stach, thomas.petazzoni,
	linux-arm-kernel, ta.omasab, kesavan.abhilash, khilman,
	santosh.shilimkar, b.zolnierkie, Greg Kroah-Hartman, Len Brown,
	open list, Pavel Machek

On 07/29, Viresh Kumar wrote:
> With "operating-points-v2" its possible to tell which devices share
> OPPs. We already have infrastructure to decode that information.
> 
> This patch adds following APIs:
> - of_get_cpus_sharing_opps: Returns cpumask of CPUs sharing OPPs (only
>   valid with v2 bindings).
> - of_cpumask_init_opp_table: Initializes OPPs for all CPUs present in
>   cpumask.
> - of_cpumask_free_opp_table: Frees OPPs for all CPUs present in cpumask.
> 
> - set_cpus_sharing_opps: Sets which CPUs share OPPs (only valid with old
>   OPP bindings, as this information isn't present in DT).
> 
> Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>

Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>

Some minor nitpicks below:

> +
> +/*
> + * Works only for OPP v2 bindings.
> + *
> + * cpumask should be already set to mask of cpu_dev->id.
> + * Returns -ENOENT if operating-points-v2 bindings aren't supported.
> + */
> +int of_get_cpus_sharing_opps(struct device *cpu_dev, cpumask_var_t cpumask)
> +{
> +	struct device_node *np, *tmp_np;
> +	struct device *tcpu_dev;
> +	int cpu, ret = 0;
> +
> +	/* Get OPP descriptor node */
> +	np = _of_get_opp_desc_node(cpu_dev);
> +	if (IS_ERR(np)) {
> +		dev_dbg(cpu_dev, "%s: Couldn't find opp node: %ld\n", __func__,
> +			PTR_ERR(np));
> +		return -ENOENT;
> +	}
> +
> +	/* OPPs are shared ? */
> +	if (!of_get_property(np, "opp-shared", NULL))

if (!of_property_read_bool(np, "opp-shared")) ?

> +		goto put_cpu_node;
> +
> +	for_each_possible_cpu(cpu) {
> +		if (cpu == cpu_dev->id)
> +			continue;
> +
> +		tcpu_dev = get_cpu_device(cpu);
> +		if (!tcpu_dev) {
> +			dev_err(cpu_dev, "%s: failed to get cpu%d device\n",
> +				__func__, cpu);
> +			ret = -ENODEV;
> +			goto put_cpu_node;
> +		}
> +
> +		/* Get OPP descriptor node */
> +		tmp_np = _of_get_opp_desc_node(tcpu_dev);
> +		if (IS_ERR(tmp_np)) {
> +			dev_info(tcpu_dev, "%s: Couldn't find opp node: %ld\n",

dev_err?

> +				 __func__, PTR_ERR(tmp_np));
> +			ret = -EINVAL;

Why aren't we returning the PTR_ERR value here?

> +			goto put_cpu_node;

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

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

* [PATCH V3 11/16] PM / OPP: Add helpers for initializing CPU OPPs
@ 2015-07-31  6:07     ` Stephen Boyd
  0 siblings, 0 replies; 92+ messages in thread
From: Stephen Boyd @ 2015-07-31  6:07 UTC (permalink / raw)
  To: linux-arm-kernel

On 07/29, Viresh Kumar wrote:
> With "operating-points-v2" its possible to tell which devices share
> OPPs. We already have infrastructure to decode that information.
> 
> This patch adds following APIs:
> - of_get_cpus_sharing_opps: Returns cpumask of CPUs sharing OPPs (only
>   valid with v2 bindings).
> - of_cpumask_init_opp_table: Initializes OPPs for all CPUs present in
>   cpumask.
> - of_cpumask_free_opp_table: Frees OPPs for all CPUs present in cpumask.
> 
> - set_cpus_sharing_opps: Sets which CPUs share OPPs (only valid with old
>   OPP bindings, as this information isn't present in DT).
> 
> Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>

Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>

Some minor nitpicks below:

> +
> +/*
> + * Works only for OPP v2 bindings.
> + *
> + * cpumask should be already set to mask of cpu_dev->id.
> + * Returns -ENOENT if operating-points-v2 bindings aren't supported.
> + */
> +int of_get_cpus_sharing_opps(struct device *cpu_dev, cpumask_var_t cpumask)
> +{
> +	struct device_node *np, *tmp_np;
> +	struct device *tcpu_dev;
> +	int cpu, ret = 0;
> +
> +	/* Get OPP descriptor node */
> +	np = _of_get_opp_desc_node(cpu_dev);
> +	if (IS_ERR(np)) {
> +		dev_dbg(cpu_dev, "%s: Couldn't find opp node: %ld\n", __func__,
> +			PTR_ERR(np));
> +		return -ENOENT;
> +	}
> +
> +	/* OPPs are shared ? */
> +	if (!of_get_property(np, "opp-shared", NULL))

if (!of_property_read_bool(np, "opp-shared")) ?

> +		goto put_cpu_node;
> +
> +	for_each_possible_cpu(cpu) {
> +		if (cpu == cpu_dev->id)
> +			continue;
> +
> +		tcpu_dev = get_cpu_device(cpu);
> +		if (!tcpu_dev) {
> +			dev_err(cpu_dev, "%s: failed to get cpu%d device\n",
> +				__func__, cpu);
> +			ret = -ENODEV;
> +			goto put_cpu_node;
> +		}
> +
> +		/* Get OPP descriptor node */
> +		tmp_np = _of_get_opp_desc_node(tcpu_dev);
> +		if (IS_ERR(tmp_np)) {
> +			dev_info(tcpu_dev, "%s: Couldn't find opp node: %ld\n",

dev_err?

> +				 __func__, PTR_ERR(tmp_np));
> +			ret = -EINVAL;

Why aren't we returning the PTR_ERR value here?

> +			goto put_cpu_node;

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

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

* Re: [PATCH V3 12/16] PM / OPP: add dev_pm_opp_is_turbo() helper
  2015-07-29 10:53   ` Viresh Kumar
@ 2015-07-31  6:10     ` Stephen Boyd
  -1 siblings, 0 replies; 92+ messages in thread
From: Stephen Boyd @ 2015-07-31  6:10 UTC (permalink / raw)
  To: Viresh Kumar
  Cc: Rafael Wysocki, linaro-kernel, linux-pm, rob.herring,
	arnd.bergmann, nm, broonie, mturquette, Sudeep.Holla,
	viswanath.puttagunta, l.stach, thomas.petazzoni,
	linux-arm-kernel, ta.omasab, kesavan.abhilash, khilman,
	santosh.shilimkar, b.zolnierkie, Tomasz Figa,
	Javier Martinez Canillas, Thomas Abraham, Greg Kroah-Hartman,
	Len Brown, open list, Pavel Machek

On 07/29, Viresh Kumar wrote:
> +bool dev_pm_opp_is_turbo(struct dev_pm_opp *opp)
> +{
> +	struct dev_pm_opp *tmp_opp;
> +
> +	opp_rcu_lockdep_assert();
> +
> +	tmp_opp = rcu_dereference(opp);
> +	if (unlikely(IS_ERR_OR_NULL(tmp_opp)) || !tmp_opp->available) {

IS_ERR_OR_NULL already has unlikely inside it on the error
pointer path so it seems redundant here.

Otherwise

Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

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

* [PATCH V3 12/16] PM / OPP: add dev_pm_opp_is_turbo() helper
@ 2015-07-31  6:10     ` Stephen Boyd
  0 siblings, 0 replies; 92+ messages in thread
From: Stephen Boyd @ 2015-07-31  6:10 UTC (permalink / raw)
  To: linux-arm-kernel

On 07/29, Viresh Kumar wrote:
> +bool dev_pm_opp_is_turbo(struct dev_pm_opp *opp)
> +{
> +	struct dev_pm_opp *tmp_opp;
> +
> +	opp_rcu_lockdep_assert();
> +
> +	tmp_opp = rcu_dereference(opp);
> +	if (unlikely(IS_ERR_OR_NULL(tmp_opp)) || !tmp_opp->available) {

IS_ERR_OR_NULL already has unlikely inside it on the error
pointer path so it seems redundant here.

Otherwise

Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

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

* Re: [PATCH V3 13/16] cpufreq: Update boost flag while initializing freq table from OPPs
  2015-07-29 10:53   ` Viresh Kumar
@ 2015-07-31  6:11     ` Stephen Boyd
  -1 siblings, 0 replies; 92+ messages in thread
From: Stephen Boyd @ 2015-07-31  6:11 UTC (permalink / raw)
  To: Viresh Kumar
  Cc: Rafael Wysocki, linaro-kernel, linux-pm, rob.herring,
	arnd.bergmann, nm, broonie, mturquette, Sudeep.Holla,
	viswanath.puttagunta, l.stach, thomas.petazzoni,
	linux-arm-kernel, ta.omasab, kesavan.abhilash, khilman,
	santosh.shilimkar, b.zolnierkie, Tomasz Figa,
	Javier Martinez Canillas, Thomas Abraham, open list

On 07/29, Viresh Kumar wrote:
> From: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
> 
> cpufreq table entries for OPPs with turbo modes enabled, should be
> marked with CPUFREQ_BOOST_FREQ flag. This ensures that these states are
> only used while operating in boost or turbo mode.
> 
> Cc: Tomasz Figa <tomasz.figa@gmail.com>
> Cc: Michael Turquette <mturquette@baylibre.com>
> Cc: Javier Martinez Canillas <javier@dowhile0.org>
> Cc: Thomas Abraham <thomas.ab@samsung.com>
> Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
> ---

Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

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

* [PATCH V3 13/16] cpufreq: Update boost flag while initializing freq table from OPPs
@ 2015-07-31  6:11     ` Stephen Boyd
  0 siblings, 0 replies; 92+ messages in thread
From: Stephen Boyd @ 2015-07-31  6:11 UTC (permalink / raw)
  To: linux-arm-kernel

On 07/29, Viresh Kumar wrote:
> From: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
> 
> cpufreq table entries for OPPs with turbo modes enabled, should be
> marked with CPUFREQ_BOOST_FREQ flag. This ensures that these states are
> only used while operating in boost or turbo mode.
> 
> Cc: Tomasz Figa <tomasz.figa@gmail.com>
> Cc: Michael Turquette <mturquette@baylibre.com>
> Cc: Javier Martinez Canillas <javier@dowhile0.org>
> Cc: Thomas Abraham <thomas.ab@samsung.com>
> Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
> ---

Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

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

* Re: [PATCH V3 14/16] cpufreq: Allow drivers to enable boost support after registering driver
  2015-07-29 10:53   ` Viresh Kumar
@ 2015-07-31  6:12     ` Stephen Boyd
  -1 siblings, 0 replies; 92+ messages in thread
From: Stephen Boyd @ 2015-07-31  6:12 UTC (permalink / raw)
  To: Viresh Kumar
  Cc: Rafael Wysocki, linaro-kernel, linux-pm, rob.herring,
	arnd.bergmann, nm, broonie, mturquette, Sudeep.Holla,
	viswanath.puttagunta, l.stach, thomas.petazzoni,
	linux-arm-kernel, ta.omasab, kesavan.abhilash, khilman,
	santosh.shilimkar, b.zolnierkie, open list

On 07/29, Viresh Kumar wrote:
> In some cases it wouldn't be known at time of driver registration, if
> the driver needs to support boost frequencies.
> 
> For example, while getting boost information from DT with opp-v2
> bindings, we need to parse the bindings for all the CPUs to know if
> turbo/boost OPPs are supported or not.
> 
> One way out to do that efficiently is to delay supporting boost mode
> (i.e. creating /sys/devices/system/cpu/cpufreq/boost file), until the
> time OPP bindings are parsed.
> 
> At that point, the driver can enable boost support. This can be done at
> ->init(), where the frequency table is created.
> 
> To do that, the driver requires few APIs from cpufreq core that let him
> do this. This patch provides these APIs.
> 
> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
> ---

Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

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

* [PATCH V3 14/16] cpufreq: Allow drivers to enable boost support after registering driver
@ 2015-07-31  6:12     ` Stephen Boyd
  0 siblings, 0 replies; 92+ messages in thread
From: Stephen Boyd @ 2015-07-31  6:12 UTC (permalink / raw)
  To: linux-arm-kernel

On 07/29, Viresh Kumar wrote:
> In some cases it wouldn't be known at time of driver registration, if
> the driver needs to support boost frequencies.
> 
> For example, while getting boost information from DT with opp-v2
> bindings, we need to parse the bindings for all the CPUs to know if
> turbo/boost OPPs are supported or not.
> 
> One way out to do that efficiently is to delay supporting boost mode
> (i.e. creating /sys/devices/system/cpu/cpufreq/boost file), until the
> time OPP bindings are parsed.
> 
> At that point, the driver can enable boost support. This can be done at
> ->init(), where the frequency table is created.
> 
> To do that, the driver requires few APIs from cpufreq core that let him
> do this. This patch provides these APIs.
> 
> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
> ---

Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

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

* Re: [PATCH V3 11/16] PM / OPP: Add helpers for initializing CPU OPPs
  2015-07-31  6:07     ` Stephen Boyd
@ 2015-07-31  6:13       ` Viresh Kumar
  -1 siblings, 0 replies; 92+ messages in thread
From: Viresh Kumar @ 2015-07-31  6:13 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Rafael Wysocki, linaro-kernel, linux-pm, rob.herring,
	arnd.bergmann, nm, broonie, mturquette, Sudeep.Holla,
	viswanath.puttagunta, l.stach, thomas.petazzoni,
	linux-arm-kernel, ta.omasab, kesavan.abhilash, khilman,
	santosh.shilimkar, b.zolnierkie, Greg Kroah-Hartman, Len Brown,
	open list, Pavel Machek

On 30-07-15, 23:07, Stephen Boyd wrote:
> On 07/29, Viresh Kumar wrote:
> > With "operating-points-v2" its possible to tell which devices share
> > OPPs. We already have infrastructure to decode that information.
> > 
> > This patch adds following APIs:
> > - of_get_cpus_sharing_opps: Returns cpumask of CPUs sharing OPPs (only
> >   valid with v2 bindings).
> > - of_cpumask_init_opp_table: Initializes OPPs for all CPUs present in
> >   cpumask.
> > - of_cpumask_free_opp_table: Frees OPPs for all CPUs present in cpumask.
> > 
> > - set_cpus_sharing_opps: Sets which CPUs share OPPs (only valid with old
> >   OPP bindings, as this information isn't present in DT).
> > 
> > Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
> > Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
> 
> Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>
> 
> Some minor nitpicks below:

> if (!of_property_read_bool(np, "opp-shared")) ?

> dev_err?

> Why aren't we returning the PTR_ERR value here?

----------8<---------------

Message-Id: <6e499ed9e4d1eead26550f96002ef7ea9d067cb9.1438323186.git.viresh.kumar@linaro.org>
From: Viresh Kumar <viresh.kumar@linaro.org>
Date: Fri, 12 Jun 2015 17:10:38 +0530
Subject: [PATCH] PM / OPP: Add helpers for initializing CPU OPPs

With "operating-points-v2" its possible to tell which devices share
OPPs. We already have infrastructure to decode that information.

This patch adds following APIs:
- of_get_cpus_sharing_opps: Returns cpumask of CPUs sharing OPPs (only
  valid with v2 bindings).
- of_cpumask_init_opp_table: Initializes OPPs for all CPUs present in
  cpumask.
- of_cpumask_free_opp_table: Frees OPPs for all CPUs present in cpumask.

- set_cpus_sharing_opps: Sets which CPUs share OPPs (only valid with old
  OPP bindings, as this information isn't present in DT).

Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>
Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/base/power/opp.c | 175 +++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/pm_opp.h   |  23 +++++++
 2 files changed, 198 insertions(+)

diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c
index 0ebcea49145a..663aae1c9834 100644
--- a/drivers/base/power/opp.c
+++ b/drivers/base/power/opp.c
@@ -11,6 +11,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/cpu.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/err.h>
@@ -1195,6 +1196,26 @@ void of_free_opp_table(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(of_free_opp_table);
 
+void of_cpumask_free_opp_table(cpumask_var_t cpumask)
+{
+	struct device *cpu_dev;
+	int cpu;
+
+	WARN_ON(cpumask_empty(cpumask));
+
+	for_each_cpu(cpu, cpumask) {
+		cpu_dev = get_cpu_device(cpu);
+		if (!cpu_dev) {
+			pr_err("%s: failed to get cpu%d device\n", __func__,
+			       cpu);
+			continue;
+		}
+
+		of_free_opp_table(cpu_dev);
+	}
+}
+EXPORT_SYMBOL_GPL(of_cpumask_free_opp_table);
+
 /* Returns opp descriptor node from its phandle. Caller must do of_node_put() */
 static struct device_node *
 _of_get_opp_desc_node_from_prop(struct device *dev, const struct property *prop)
@@ -1211,6 +1232,31 @@ _of_get_opp_desc_node_from_prop(struct device *dev, const struct property *prop)
 	return opp_np;
 }
 
+/* Returns opp descriptor node for a device. Caller must do of_node_put() */
+static struct device_node *_of_get_opp_desc_node(struct device *dev)
+{
+	const struct property *prop;
+
+	prop = of_find_property(dev->of_node, "operating-points-v2", NULL);
+	if (!prop)
+		return ERR_PTR(-ENODEV);
+	if (!prop->value)
+		return ERR_PTR(-ENODATA);
+
+	/*
+	 * TODO: Support for multiple OPP tables.
+	 *
+	 * There should be only ONE phandle present in "operating-points-v2"
+	 * property.
+	 */
+	if (prop->length != sizeof(__be32)) {
+		dev_err(dev, "%s: Invalid opp desc phandle\n", __func__);
+		return ERR_PTR(-EINVAL);
+	}
+
+	return _of_get_opp_desc_node_from_prop(dev, prop);
+}
+
 /* Initializes OPP tables based on new bindings */
 static int _of_init_opp_table_v2(struct device *dev,
 				 const struct property *prop)
@@ -1351,4 +1397,133 @@ int of_init_opp_table(struct device *dev)
 	return _of_init_opp_table_v2(dev, prop);
 }
 EXPORT_SYMBOL_GPL(of_init_opp_table);
+
+int of_cpumask_init_opp_table(cpumask_var_t cpumask)
+{
+	struct device *cpu_dev;
+	int cpu, ret = 0;
+
+	WARN_ON(cpumask_empty(cpumask));
+
+	for_each_cpu(cpu, cpumask) {
+		cpu_dev = get_cpu_device(cpu);
+		if (!cpu_dev) {
+			pr_err("%s: failed to get cpu%d device\n", __func__,
+			       cpu);
+			continue;
+		}
+
+		ret = of_init_opp_table(cpu_dev);
+		if (ret) {
+			pr_err("%s: couldn't find opp table for cpu:%d, %d\n",
+			       __func__, cpu, ret);
+
+			/* Free all other OPPs */
+			of_cpumask_free_opp_table(cpumask);
+			break;
+		}
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(of_cpumask_init_opp_table);
+
+/* Required only for V1 bindings, as v2 can manage it from DT itself */
+int set_cpus_sharing_opps(struct device *cpu_dev, cpumask_var_t cpumask)
+{
+	struct device_list_opp *list_dev;
+	struct device_opp *dev_opp;
+	struct device *dev;
+	int cpu, ret = 0;
+
+	rcu_read_lock();
+
+	dev_opp = _find_device_opp(cpu_dev);
+	if (IS_ERR(dev_opp)) {
+		ret = -EINVAL;
+		goto out_rcu_read_unlock;
+	}
+
+	for_each_cpu(cpu, cpumask) {
+		if (cpu == cpu_dev->id)
+			continue;
+
+		dev = get_cpu_device(cpu);
+		if (!dev) {
+			dev_err(cpu_dev, "%s: failed to get cpu%d device\n",
+				__func__, cpu);
+			continue;
+		}
+
+		list_dev = _add_list_dev(dev, dev_opp);
+		if (!list_dev) {
+			dev_err(dev, "%s: failed to add list-dev for cpu%d device\n",
+				__func__, cpu);
+			continue;
+		}
+	}
+out_rcu_read_unlock:
+	rcu_read_unlock();
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(set_cpus_sharing_opps);
+
+/*
+ * Works only for OPP v2 bindings.
+ *
+ * cpumask should be already set to mask of cpu_dev->id.
+ * Returns -ENOENT if operating-points-v2 bindings aren't supported.
+ */
+int of_get_cpus_sharing_opps(struct device *cpu_dev, cpumask_var_t cpumask)
+{
+	struct device_node *np, *tmp_np;
+	struct device *tcpu_dev;
+	int cpu, ret = 0;
+
+	/* Get OPP descriptor node */
+	np = _of_get_opp_desc_node(cpu_dev);
+	if (IS_ERR(np)) {
+		dev_dbg(cpu_dev, "%s: Couldn't find opp node: %ld\n", __func__,
+			PTR_ERR(np));
+		return -ENOENT;
+	}
+
+	/* OPPs are shared ? */
+	if (!of_property_read_bool(np, "opp-shared"))
+		goto put_cpu_node;
+
+	for_each_possible_cpu(cpu) {
+		if (cpu == cpu_dev->id)
+			continue;
+
+		tcpu_dev = get_cpu_device(cpu);
+		if (!tcpu_dev) {
+			dev_err(cpu_dev, "%s: failed to get cpu%d device\n",
+				__func__, cpu);
+			ret = -ENODEV;
+			goto put_cpu_node;
+		}
+
+		/* Get OPP descriptor node */
+		tmp_np = _of_get_opp_desc_node(tcpu_dev);
+		if (IS_ERR(tmp_np)) {
+			dev_err(tcpu_dev, "%s: Couldn't find opp node: %ld\n",
+				__func__, PTR_ERR(tmp_np));
+			ret = PTR_ERR(tmp_np);
+			goto put_cpu_node;
+		}
+
+		/* CPUs are sharing opp node */
+		if (np == tmp_np)
+			cpumask_set_cpu(cpu, cpumask);
+
+		of_node_put(tmp_np);
+	}
+
+put_cpu_node:
+	of_node_put(np);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(of_get_cpus_sharing_opps);
 #endif
diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h
index 20324b579adc..bb52fae5b921 100644
--- a/include/linux/pm_opp.h
+++ b/include/linux/pm_opp.h
@@ -121,6 +121,10 @@ static inline struct srcu_notifier_head *dev_pm_opp_get_notifier(
 #if defined(CONFIG_PM_OPP) && defined(CONFIG_OF)
 int of_init_opp_table(struct device *dev);
 void of_free_opp_table(struct device *dev);
+int of_cpumask_init_opp_table(cpumask_var_t cpumask);
+void of_cpumask_free_opp_table(cpumask_var_t cpumask);
+int of_get_cpus_sharing_opps(struct device *cpu_dev, cpumask_var_t cpumask);
+int set_cpus_sharing_opps(struct device *cpu_dev, cpumask_var_t cpumask);
 #else
 static inline int of_init_opp_table(struct device *dev)
 {
@@ -130,6 +134,25 @@ static inline int of_init_opp_table(struct device *dev)
 static inline void of_free_opp_table(struct device *dev)
 {
 }
+
+static inline int of_cpumask_init_opp_table(cpumask_var_t cpumask)
+{
+	return -ENOSYS;
+}
+
+static inline void of_cpumask_free_opp_table(cpumask_var_t cpumask)
+{
+}
+
+static inline int of_get_cpus_sharing_opps(struct device *cpu_dev, cpumask_var_t cpumask)
+{
+	return -ENOSYS;
+}
+
+static inline int set_cpus_sharing_opps(struct device *cpu_dev, cpumask_var_t cpumask)
+{
+	return -ENOSYS;
+}
 #endif
 
 #endif		/* __LINUX_OPP_H__ */

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

* [PATCH V3 11/16] PM / OPP: Add helpers for initializing CPU OPPs
@ 2015-07-31  6:13       ` Viresh Kumar
  0 siblings, 0 replies; 92+ messages in thread
From: Viresh Kumar @ 2015-07-31  6:13 UTC (permalink / raw)
  To: linux-arm-kernel

On 30-07-15, 23:07, Stephen Boyd wrote:
> On 07/29, Viresh Kumar wrote:
> > With "operating-points-v2" its possible to tell which devices share
> > OPPs. We already have infrastructure to decode that information.
> > 
> > This patch adds following APIs:
> > - of_get_cpus_sharing_opps: Returns cpumask of CPUs sharing OPPs (only
> >   valid with v2 bindings).
> > - of_cpumask_init_opp_table: Initializes OPPs for all CPUs present in
> >   cpumask.
> > - of_cpumask_free_opp_table: Frees OPPs for all CPUs present in cpumask.
> > 
> > - set_cpus_sharing_opps: Sets which CPUs share OPPs (only valid with old
> >   OPP bindings, as this information isn't present in DT).
> > 
> > Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
> > Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
> 
> Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>
> 
> Some minor nitpicks below:

> if (!of_property_read_bool(np, "opp-shared")) ?

> dev_err?

> Why aren't we returning the PTR_ERR value here?

----------8<---------------

Message-Id: <6e499ed9e4d1eead26550f96002ef7ea9d067cb9.1438323186.git.viresh.kumar@linaro.org>
From: Viresh Kumar <viresh.kumar@linaro.org>
Date: Fri, 12 Jun 2015 17:10:38 +0530
Subject: [PATCH] PM / OPP: Add helpers for initializing CPU OPPs

With "operating-points-v2" its possible to tell which devices share
OPPs. We already have infrastructure to decode that information.

This patch adds following APIs:
- of_get_cpus_sharing_opps: Returns cpumask of CPUs sharing OPPs (only
  valid with v2 bindings).
- of_cpumask_init_opp_table: Initializes OPPs for all CPUs present in
  cpumask.
- of_cpumask_free_opp_table: Frees OPPs for all CPUs present in cpumask.

- set_cpus_sharing_opps: Sets which CPUs share OPPs (only valid with old
  OPP bindings, as this information isn't present in DT).

Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>
Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/base/power/opp.c | 175 +++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/pm_opp.h   |  23 +++++++
 2 files changed, 198 insertions(+)

diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c
index 0ebcea49145a..663aae1c9834 100644
--- a/drivers/base/power/opp.c
+++ b/drivers/base/power/opp.c
@@ -11,6 +11,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/cpu.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/err.h>
@@ -1195,6 +1196,26 @@ void of_free_opp_table(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(of_free_opp_table);
 
+void of_cpumask_free_opp_table(cpumask_var_t cpumask)
+{
+	struct device *cpu_dev;
+	int cpu;
+
+	WARN_ON(cpumask_empty(cpumask));
+
+	for_each_cpu(cpu, cpumask) {
+		cpu_dev = get_cpu_device(cpu);
+		if (!cpu_dev) {
+			pr_err("%s: failed to get cpu%d device\n", __func__,
+			       cpu);
+			continue;
+		}
+
+		of_free_opp_table(cpu_dev);
+	}
+}
+EXPORT_SYMBOL_GPL(of_cpumask_free_opp_table);
+
 /* Returns opp descriptor node from its phandle. Caller must do of_node_put() */
 static struct device_node *
 _of_get_opp_desc_node_from_prop(struct device *dev, const struct property *prop)
@@ -1211,6 +1232,31 @@ _of_get_opp_desc_node_from_prop(struct device *dev, const struct property *prop)
 	return opp_np;
 }
 
+/* Returns opp descriptor node for a device. Caller must do of_node_put() */
+static struct device_node *_of_get_opp_desc_node(struct device *dev)
+{
+	const struct property *prop;
+
+	prop = of_find_property(dev->of_node, "operating-points-v2", NULL);
+	if (!prop)
+		return ERR_PTR(-ENODEV);
+	if (!prop->value)
+		return ERR_PTR(-ENODATA);
+
+	/*
+	 * TODO: Support for multiple OPP tables.
+	 *
+	 * There should be only ONE phandle present in "operating-points-v2"
+	 * property.
+	 */
+	if (prop->length != sizeof(__be32)) {
+		dev_err(dev, "%s: Invalid opp desc phandle\n", __func__);
+		return ERR_PTR(-EINVAL);
+	}
+
+	return _of_get_opp_desc_node_from_prop(dev, prop);
+}
+
 /* Initializes OPP tables based on new bindings */
 static int _of_init_opp_table_v2(struct device *dev,
 				 const struct property *prop)
@@ -1351,4 +1397,133 @@ int of_init_opp_table(struct device *dev)
 	return _of_init_opp_table_v2(dev, prop);
 }
 EXPORT_SYMBOL_GPL(of_init_opp_table);
+
+int of_cpumask_init_opp_table(cpumask_var_t cpumask)
+{
+	struct device *cpu_dev;
+	int cpu, ret = 0;
+
+	WARN_ON(cpumask_empty(cpumask));
+
+	for_each_cpu(cpu, cpumask) {
+		cpu_dev = get_cpu_device(cpu);
+		if (!cpu_dev) {
+			pr_err("%s: failed to get cpu%d device\n", __func__,
+			       cpu);
+			continue;
+		}
+
+		ret = of_init_opp_table(cpu_dev);
+		if (ret) {
+			pr_err("%s: couldn't find opp table for cpu:%d, %d\n",
+			       __func__, cpu, ret);
+
+			/* Free all other OPPs */
+			of_cpumask_free_opp_table(cpumask);
+			break;
+		}
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(of_cpumask_init_opp_table);
+
+/* Required only for V1 bindings, as v2 can manage it from DT itself */
+int set_cpus_sharing_opps(struct device *cpu_dev, cpumask_var_t cpumask)
+{
+	struct device_list_opp *list_dev;
+	struct device_opp *dev_opp;
+	struct device *dev;
+	int cpu, ret = 0;
+
+	rcu_read_lock();
+
+	dev_opp = _find_device_opp(cpu_dev);
+	if (IS_ERR(dev_opp)) {
+		ret = -EINVAL;
+		goto out_rcu_read_unlock;
+	}
+
+	for_each_cpu(cpu, cpumask) {
+		if (cpu == cpu_dev->id)
+			continue;
+
+		dev = get_cpu_device(cpu);
+		if (!dev) {
+			dev_err(cpu_dev, "%s: failed to get cpu%d device\n",
+				__func__, cpu);
+			continue;
+		}
+
+		list_dev = _add_list_dev(dev, dev_opp);
+		if (!list_dev) {
+			dev_err(dev, "%s: failed to add list-dev for cpu%d device\n",
+				__func__, cpu);
+			continue;
+		}
+	}
+out_rcu_read_unlock:
+	rcu_read_unlock();
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(set_cpus_sharing_opps);
+
+/*
+ * Works only for OPP v2 bindings.
+ *
+ * cpumask should be already set to mask of cpu_dev->id.
+ * Returns -ENOENT if operating-points-v2 bindings aren't supported.
+ */
+int of_get_cpus_sharing_opps(struct device *cpu_dev, cpumask_var_t cpumask)
+{
+	struct device_node *np, *tmp_np;
+	struct device *tcpu_dev;
+	int cpu, ret = 0;
+
+	/* Get OPP descriptor node */
+	np = _of_get_opp_desc_node(cpu_dev);
+	if (IS_ERR(np)) {
+		dev_dbg(cpu_dev, "%s: Couldn't find opp node: %ld\n", __func__,
+			PTR_ERR(np));
+		return -ENOENT;
+	}
+
+	/* OPPs are shared ? */
+	if (!of_property_read_bool(np, "opp-shared"))
+		goto put_cpu_node;
+
+	for_each_possible_cpu(cpu) {
+		if (cpu == cpu_dev->id)
+			continue;
+
+		tcpu_dev = get_cpu_device(cpu);
+		if (!tcpu_dev) {
+			dev_err(cpu_dev, "%s: failed to get cpu%d device\n",
+				__func__, cpu);
+			ret = -ENODEV;
+			goto put_cpu_node;
+		}
+
+		/* Get OPP descriptor node */
+		tmp_np = _of_get_opp_desc_node(tcpu_dev);
+		if (IS_ERR(tmp_np)) {
+			dev_err(tcpu_dev, "%s: Couldn't find opp node: %ld\n",
+				__func__, PTR_ERR(tmp_np));
+			ret = PTR_ERR(tmp_np);
+			goto put_cpu_node;
+		}
+
+		/* CPUs are sharing opp node */
+		if (np == tmp_np)
+			cpumask_set_cpu(cpu, cpumask);
+
+		of_node_put(tmp_np);
+	}
+
+put_cpu_node:
+	of_node_put(np);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(of_get_cpus_sharing_opps);
 #endif
diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h
index 20324b579adc..bb52fae5b921 100644
--- a/include/linux/pm_opp.h
+++ b/include/linux/pm_opp.h
@@ -121,6 +121,10 @@ static inline struct srcu_notifier_head *dev_pm_opp_get_notifier(
 #if defined(CONFIG_PM_OPP) && defined(CONFIG_OF)
 int of_init_opp_table(struct device *dev);
 void of_free_opp_table(struct device *dev);
+int of_cpumask_init_opp_table(cpumask_var_t cpumask);
+void of_cpumask_free_opp_table(cpumask_var_t cpumask);
+int of_get_cpus_sharing_opps(struct device *cpu_dev, cpumask_var_t cpumask);
+int set_cpus_sharing_opps(struct device *cpu_dev, cpumask_var_t cpumask);
 #else
 static inline int of_init_opp_table(struct device *dev)
 {
@@ -130,6 +134,25 @@ static inline int of_init_opp_table(struct device *dev)
 static inline void of_free_opp_table(struct device *dev)
 {
 }
+
+static inline int of_cpumask_init_opp_table(cpumask_var_t cpumask)
+{
+	return -ENOSYS;
+}
+
+static inline void of_cpumask_free_opp_table(cpumask_var_t cpumask)
+{
+}
+
+static inline int of_get_cpus_sharing_opps(struct device *cpu_dev, cpumask_var_t cpumask)
+{
+	return -ENOSYS;
+}
+
+static inline int set_cpus_sharing_opps(struct device *cpu_dev, cpumask_var_t cpumask)
+{
+	return -ENOSYS;
+}
 #endif
 
 #endif		/* __LINUX_OPP_H__ */

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

* Re: [PATCH V3 15/16] cpufreq: dt: Add support for operating-points-v2 bindings
  2015-07-29 10:53   ` Viresh Kumar
@ 2015-07-31  6:15     ` Stephen Boyd
  -1 siblings, 0 replies; 92+ messages in thread
From: Stephen Boyd @ 2015-07-31  6:15 UTC (permalink / raw)
  To: Viresh Kumar
  Cc: Rafael Wysocki, linaro-kernel, linux-pm, rob.herring,
	arnd.bergmann, nm, broonie, mturquette, Sudeep.Holla,
	viswanath.puttagunta, l.stach, thomas.petazzoni,
	linux-arm-kernel, ta.omasab, kesavan.abhilash, khilman,
	santosh.shilimkar, b.zolnierkie, open list

On 07/29, Viresh Kumar wrote:
> Support for parsing operating-points-v2 bindings is in place now, lets
> modify cpufreq-dt driver to use them.
> 
> For backward compatibility we will continue to support earlier bindings.
> Special handling for that is required, to make sure OPPs are initialized
> for all the CPUs.
> 
> Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
> ---

Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

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

* [PATCH V3 15/16] cpufreq: dt: Add support for operating-points-v2 bindings
@ 2015-07-31  6:15     ` Stephen Boyd
  0 siblings, 0 replies; 92+ messages in thread
From: Stephen Boyd @ 2015-07-31  6:15 UTC (permalink / raw)
  To: linux-arm-kernel

On 07/29, Viresh Kumar wrote:
> Support for parsing operating-points-v2 bindings is in place now, lets
> modify cpufreq-dt driver to use them.
> 
> For backward compatibility we will continue to support earlier bindings.
> Special handling for that is required, to make sure OPPs are initialized
> for all the CPUs.
> 
> Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
> ---

Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

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

* Re: [PATCH V3 16/16] cpufreq: dt: Add support for turbo/boost mode
  2015-07-29 10:53   ` Viresh Kumar
@ 2015-07-31  6:16     ` Stephen Boyd
  -1 siblings, 0 replies; 92+ messages in thread
From: Stephen Boyd @ 2015-07-31  6:16 UTC (permalink / raw)
  To: Viresh Kumar
  Cc: Rafael Wysocki, linaro-kernel, linux-pm, rob.herring,
	arnd.bergmann, nm, broonie, mturquette, Sudeep.Holla,
	viswanath.puttagunta, l.stach, thomas.petazzoni,
	linux-arm-kernel, ta.omasab, kesavan.abhilash, khilman,
	santosh.shilimkar, b.zolnierkie, open list

On 07/29, Viresh Kumar wrote:
> With opp-v2 DT bindings, few OPPs can be used only for the boost mode.
> But using such OPPs require the boost mode to be supported by cpufreq
> driver.
> 
> We will parse DT bindings only during ->init() and so can enable boost
> support only after registering cpufreq driver.
> 
> This enables boost support as soon as any policy has boost/turbo OPPs
> for its CPUs.
> 
> We don't need to disable boost support as that is done by the core, when
> the driver is unregistered.
> 
> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
> ---

Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

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

* [PATCH V3 16/16] cpufreq: dt: Add support for turbo/boost mode
@ 2015-07-31  6:16     ` Stephen Boyd
  0 siblings, 0 replies; 92+ messages in thread
From: Stephen Boyd @ 2015-07-31  6:16 UTC (permalink / raw)
  To: linux-arm-kernel

On 07/29, Viresh Kumar wrote:
> With opp-v2 DT bindings, few OPPs can be used only for the boost mode.
> But using such OPPs require the boost mode to be supported by cpufreq
> driver.
> 
> We will parse DT bindings only during ->init() and so can enable boost
> support only after registering cpufreq driver.
> 
> This enables boost support as soon as any policy has boost/turbo OPPs
> for its CPUs.
> 
> We don't need to disable boost support as that is done by the core, when
> the driver is unregistered.
> 
> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
> ---

Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

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

* Re: [PATCH V3 12/16] PM / OPP: add dev_pm_opp_is_turbo() helper
  2015-07-31  6:10     ` Stephen Boyd
@ 2015-07-31  6:17       ` Viresh Kumar
  -1 siblings, 0 replies; 92+ messages in thread
From: Viresh Kumar @ 2015-07-31  6:17 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Rafael Wysocki, linaro-kernel, linux-pm, rob.herring,
	arnd.bergmann, nm, broonie, mturquette, Sudeep.Holla,
	viswanath.puttagunta, l.stach, thomas.petazzoni,
	linux-arm-kernel, ta.omasab, kesavan.abhilash, khilman,
	santosh.shilimkar, b.zolnierkie, Tomasz Figa,
	Javier Martinez Canillas, Thomas Abraham, Greg Kroah-Hartman,
	Len Brown, open list, Pavel Machek

On 30-07-15, 23:10, Stephen Boyd wrote:
> On 07/29, Viresh Kumar wrote:
> > +bool dev_pm_opp_is_turbo(struct dev_pm_opp *opp)
> > +{
> > +	struct dev_pm_opp *tmp_opp;
> > +
> > +	opp_rcu_lockdep_assert();
> > +
> > +	tmp_opp = rcu_dereference(opp);
> > +	if (unlikely(IS_ERR_OR_NULL(tmp_opp)) || !tmp_opp->available) {
> 
> IS_ERR_OR_NULL already has unlikely inside it on the error
> pointer path so it seems redundant here.
> 
> Otherwise
> 
> Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>

----------------------8<----------------------
Message-Id: <f925cccfbe4765bc6b15740a43e5688d2a283fb0.1438323394.git.viresh.kumar@linaro.org>
From: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Date: Thu, 9 Jul 2015 17:43:35 +0200
Subject: [PATCH] PM / OPP: add dev_pm_opp_is_turbo() helper

Add dev_pm_opp_is_turbo() helper to verify if an opp is to be used only
for turbo mode or not.

Cc: Tomasz Figa <tomasz.figa@gmail.com>
Cc: Michael Turquette <mturquette@baylibre.com>
Cc: Javier Martinez Canillas <javier@dowhile0.org>
Cc: Thomas Abraham <thomas.ab@samsung.com>
Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>
Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/base/power/opp.c | 34 ++++++++++++++++++++++++++++++++++
 include/linux/pm_opp.h   |  7 +++++++
 2 files changed, 41 insertions(+)

diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c
index 663aae1c9834..204c6c945168 100644
--- a/drivers/base/power/opp.c
+++ b/drivers/base/power/opp.c
@@ -281,6 +281,40 @@ unsigned long dev_pm_opp_get_freq(struct dev_pm_opp *opp)
 EXPORT_SYMBOL_GPL(dev_pm_opp_get_freq);
 
 /**
+ * dev_pm_opp_is_turbo() - Returns if opp is turbo OPP or not
+ * @opp: opp for which turbo mode is being verified
+ *
+ * Turbo OPPs are not for normal use, and can be enabled (under certain
+ * conditions) for short duration of times to finish high throughput work
+ * quickly. Running on them for longer times may overheat the chip.
+ *
+ * Return: true if opp is turbo opp, else false.
+ *
+ * Locking: This function must be called under rcu_read_lock(). opp is a rcu
+ * protected pointer. This means that opp which could have been fetched by
+ * opp_find_freq_{exact,ceil,floor} functions is valid as long as we are
+ * under RCU lock. The pointer returned by the opp_find_freq family must be
+ * used in the same section as the usage of this function with the pointer
+ * prior to unlocking with rcu_read_unlock() to maintain the integrity of the
+ * pointer.
+ */
+bool dev_pm_opp_is_turbo(struct dev_pm_opp *opp)
+{
+	struct dev_pm_opp *tmp_opp;
+
+	opp_rcu_lockdep_assert();
+
+	tmp_opp = rcu_dereference(opp);
+	if (IS_ERR_OR_NULL(tmp_opp) || !tmp_opp->available) {
+		pr_err("%s: Invalid parameters\n", __func__);
+		return false;
+	}
+
+	return tmp_opp->turbo;
+}
+EXPORT_SYMBOL_GPL(dev_pm_opp_is_turbo);
+
+/**
  * dev_pm_opp_get_max_clock_latency() - Get max clock latency in nanoseconds
  * @dev:	device for which we do this operation
  *
diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h
index bb52fae5b921..cab7ba55bedb 100644
--- a/include/linux/pm_opp.h
+++ b/include/linux/pm_opp.h
@@ -30,6 +30,8 @@ unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp);
 
 unsigned long dev_pm_opp_get_freq(struct dev_pm_opp *opp);
 
+bool dev_pm_opp_is_turbo(struct dev_pm_opp *opp);
+
 int dev_pm_opp_get_opp_count(struct device *dev);
 unsigned long dev_pm_opp_get_max_clock_latency(struct device *dev);
 
@@ -63,6 +65,11 @@ static inline unsigned long dev_pm_opp_get_freq(struct dev_pm_opp *opp)
 	return 0;
 }
 
+static inline bool dev_pm_opp_is_turbo(struct dev_pm_opp *opp)
+{
+	return false;
+}
+
 static inline int dev_pm_opp_get_opp_count(struct device *dev)
 {
 	return 0;

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

* [PATCH V3 12/16] PM / OPP: add dev_pm_opp_is_turbo() helper
@ 2015-07-31  6:17       ` Viresh Kumar
  0 siblings, 0 replies; 92+ messages in thread
From: Viresh Kumar @ 2015-07-31  6:17 UTC (permalink / raw)
  To: linux-arm-kernel

On 30-07-15, 23:10, Stephen Boyd wrote:
> On 07/29, Viresh Kumar wrote:
> > +bool dev_pm_opp_is_turbo(struct dev_pm_opp *opp)
> > +{
> > +	struct dev_pm_opp *tmp_opp;
> > +
> > +	opp_rcu_lockdep_assert();
> > +
> > +	tmp_opp = rcu_dereference(opp);
> > +	if (unlikely(IS_ERR_OR_NULL(tmp_opp)) || !tmp_opp->available) {
> 
> IS_ERR_OR_NULL already has unlikely inside it on the error
> pointer path so it seems redundant here.
> 
> Otherwise
> 
> Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>

----------------------8<----------------------
Message-Id: <f925cccfbe4765bc6b15740a43e5688d2a283fb0.1438323394.git.viresh.kumar@linaro.org>
From: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Date: Thu, 9 Jul 2015 17:43:35 +0200
Subject: [PATCH] PM / OPP: add dev_pm_opp_is_turbo() helper

Add dev_pm_opp_is_turbo() helper to verify if an opp is to be used only
for turbo mode or not.

Cc: Tomasz Figa <tomasz.figa@gmail.com>
Cc: Michael Turquette <mturquette@baylibre.com>
Cc: Javier Martinez Canillas <javier@dowhile0.org>
Cc: Thomas Abraham <thomas.ab@samsung.com>
Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>
Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/base/power/opp.c | 34 ++++++++++++++++++++++++++++++++++
 include/linux/pm_opp.h   |  7 +++++++
 2 files changed, 41 insertions(+)

diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c
index 663aae1c9834..204c6c945168 100644
--- a/drivers/base/power/opp.c
+++ b/drivers/base/power/opp.c
@@ -281,6 +281,40 @@ unsigned long dev_pm_opp_get_freq(struct dev_pm_opp *opp)
 EXPORT_SYMBOL_GPL(dev_pm_opp_get_freq);
 
 /**
+ * dev_pm_opp_is_turbo() - Returns if opp is turbo OPP or not
+ * @opp: opp for which turbo mode is being verified
+ *
+ * Turbo OPPs are not for normal use, and can be enabled (under certain
+ * conditions) for short duration of times to finish high throughput work
+ * quickly. Running on them for longer times may overheat the chip.
+ *
+ * Return: true if opp is turbo opp, else false.
+ *
+ * Locking: This function must be called under rcu_read_lock(). opp is a rcu
+ * protected pointer. This means that opp which could have been fetched by
+ * opp_find_freq_{exact,ceil,floor} functions is valid as long as we are
+ * under RCU lock. The pointer returned by the opp_find_freq family must be
+ * used in the same section as the usage of this function with the pointer
+ * prior to unlocking with rcu_read_unlock() to maintain the integrity of the
+ * pointer.
+ */
+bool dev_pm_opp_is_turbo(struct dev_pm_opp *opp)
+{
+	struct dev_pm_opp *tmp_opp;
+
+	opp_rcu_lockdep_assert();
+
+	tmp_opp = rcu_dereference(opp);
+	if (IS_ERR_OR_NULL(tmp_opp) || !tmp_opp->available) {
+		pr_err("%s: Invalid parameters\n", __func__);
+		return false;
+	}
+
+	return tmp_opp->turbo;
+}
+EXPORT_SYMBOL_GPL(dev_pm_opp_is_turbo);
+
+/**
  * dev_pm_opp_get_max_clock_latency() - Get max clock latency in nanoseconds
  * @dev:	device for which we do this operation
  *
diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h
index bb52fae5b921..cab7ba55bedb 100644
--- a/include/linux/pm_opp.h
+++ b/include/linux/pm_opp.h
@@ -30,6 +30,8 @@ unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp);
 
 unsigned long dev_pm_opp_get_freq(struct dev_pm_opp *opp);
 
+bool dev_pm_opp_is_turbo(struct dev_pm_opp *opp);
+
 int dev_pm_opp_get_opp_count(struct device *dev);
 unsigned long dev_pm_opp_get_max_clock_latency(struct device *dev);
 
@@ -63,6 +65,11 @@ static inline unsigned long dev_pm_opp_get_freq(struct dev_pm_opp *opp)
 	return 0;
 }
 
+static inline bool dev_pm_opp_is_turbo(struct dev_pm_opp *opp)
+{
+	return false;
+}
+
 static inline int dev_pm_opp_get_opp_count(struct device *dev)
 {
 	return 0;

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

* Re: [PATCH V3 07/16] PM / OPP: Add support to parse "operating-points-v2" bindings
  2015-07-31  5:58       ` Viresh Kumar
@ 2015-07-31  6:20         ` Stephen Boyd
  -1 siblings, 0 replies; 92+ messages in thread
From: Stephen Boyd @ 2015-07-31  6:20 UTC (permalink / raw)
  To: Viresh Kumar
  Cc: Rafael Wysocki, linaro-kernel, linux-pm, rob.herring,
	arnd.bergmann, nm, broonie, mturquette, Sudeep.Holla,
	viswanath.puttagunta, l.stach, thomas.petazzoni,
	linux-arm-kernel, ta.omasab, kesavan.abhilash, khilman,
	santosh.shilimkar, b.zolnierkie, Greg Kroah-Hartman, Len Brown,
	open list, Pavel Machek

On 07/31, Viresh Kumar wrote:
> On 30-07-15, 22:51, Stephen Boyd wrote:
> > > +	opp->u_volt = microvolt[0];
> > > +	opp->u_volt_min = microvolt[1];
> > > +	opp->u_volt_max = microvolt[2];
> > 
> > Should the default be 0 and ULONG_MAX for volt_min/volt_max when
> > there's on element?
> 
> I am not still sure how the regulator API is going to look like for
> this target/min/max thing. So, lets defer it until that is resolved.
> For now they are initialized to 0.
> 
> And, because the user has just passed in a target voltage, maybe all
> three must be == u_volt. :)
> 

Ok. Sounds fair enough.

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

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

* [PATCH V3 07/16] PM / OPP: Add support to parse "operating-points-v2" bindings
@ 2015-07-31  6:20         ` Stephen Boyd
  0 siblings, 0 replies; 92+ messages in thread
From: Stephen Boyd @ 2015-07-31  6:20 UTC (permalink / raw)
  To: linux-arm-kernel

On 07/31, Viresh Kumar wrote:
> On 30-07-15, 22:51, Stephen Boyd wrote:
> > > +	opp->u_volt = microvolt[0];
> > > +	opp->u_volt_min = microvolt[1];
> > > +	opp->u_volt_max = microvolt[2];
> > 
> > Should the default be 0 and ULONG_MAX for volt_min/volt_max when
> > there's on element?
> 
> I am not still sure how the regulator API is going to look like for
> this target/min/max thing. So, lets defer it until that is resolved.
> For now they are initialized to 0.
> 
> And, because the user has just passed in a target voltage, maybe all
> three must be == u_volt. :)
> 

Ok. Sounds fair enough.

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

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

* Re: [PATCH V3 10/16] PM / OPP: Add support for opp-suspend
  2015-07-29 10:53   ` Viresh Kumar
@ 2015-07-31  6:24     ` Stephen Boyd
  -1 siblings, 0 replies; 92+ messages in thread
From: Stephen Boyd @ 2015-07-31  6:24 UTC (permalink / raw)
  To: Viresh Kumar
  Cc: Rafael Wysocki, linaro-kernel, linux-pm, rob.herring,
	arnd.bergmann, nm, broonie, mturquette, Sudeep.Holla,
	viswanath.puttagunta, l.stach, thomas.petazzoni,
	linux-arm-kernel, ta.omasab, kesavan.abhilash, khilman,
	santosh.shilimkar, b.zolnierkie, Greg Kroah-Hartman, Len Brown,
	open list, Pavel Machek

On 07/29, Viresh Kumar wrote:
> With "operating-points-v2" bindings, its possible to specify the OPP to

s/its/it's/ ?

> which the device must be switched, before suspending.
> 
> This patch adds support for getting that information.
> 
> Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
> ---

Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

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

* [PATCH V3 10/16] PM / OPP: Add support for opp-suspend
@ 2015-07-31  6:24     ` Stephen Boyd
  0 siblings, 0 replies; 92+ messages in thread
From: Stephen Boyd @ 2015-07-31  6:24 UTC (permalink / raw)
  To: linux-arm-kernel

On 07/29, Viresh Kumar wrote:
> With "operating-points-v2" bindings, its possible to specify the OPP to

s/its/it's/ ?

> which the device must be switched, before suspending.
> 
> This patch adds support for getting that information.
> 
> Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
> ---

Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

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

* Re: [PATCH V3 10/16] PM / OPP: Add support for opp-suspend
  2015-07-31  6:24     ` Stephen Boyd
@ 2015-07-31  6:26       ` Viresh Kumar
  -1 siblings, 0 replies; 92+ messages in thread
From: Viresh Kumar @ 2015-07-31  6:26 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Rafael Wysocki, linaro-kernel, linux-pm, rob.herring,
	arnd.bergmann, nm, broonie, mturquette, Sudeep.Holla,
	viswanath.puttagunta, l.stach, thomas.petazzoni,
	linux-arm-kernel, ta.omasab, kesavan.abhilash, khilman,
	santosh.shilimkar, b.zolnierkie, Greg Kroah-Hartman, Len Brown,
	open list, Pavel Machek

On 30-07-15, 23:24, Stephen Boyd wrote:
> On 07/29, Viresh Kumar wrote:
> > With "operating-points-v2" bindings, its possible to specify the OPP to
> 
> s/its/it's/ ?
> 
> > which the device must be switched, before suspending.
> > 
> > This patch adds support for getting that information.
> > 
> > Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
> > Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
> > ---
> 
> Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>

---------------------8<-------------------

Message-Id: <5e0cf40cc78bfa327cbbccae016d03a1dfbd1a84.1438323941.git.viresh.kumar@linaro.org>
From: Viresh Kumar <viresh.kumar@linaro.org>
Date: Sat, 13 Jun 2015 15:10:21 +0530
Subject: [PATCH] PM / OPP: Add support for opp-suspend

With "operating-points-v2" bindings, it's possible to specify the OPP to
which the device must be switched, before suspending.

This patch adds support for getting that information.

Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>
Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/base/power/opp.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c
index 5d699e3ec136..0ebcea49145a 100644
--- a/drivers/base/power/opp.c
+++ b/drivers/base/power/opp.c
@@ -133,6 +133,7 @@ struct device_opp {
 	struct device_node *np;
 	unsigned long clock_latency_ns_max;
 	bool shared_opp;
+	struct dev_pm_opp *suspend_opp;
 };
 
 /*
@@ -923,6 +924,16 @@ static int _opp_add_static_v2(struct device *dev, struct device_node *np)
 	if (ret)
 		goto free_opp;
 
+	/* OPP to select on device suspend */
+	if (of_property_read_bool(np, "opp-suspend")) {
+		if (dev_opp->suspend_opp)
+			dev_warn(dev, "%s: Multiple suspend OPPs found (%lu %lu)\n",
+				 __func__, dev_opp->suspend_opp->rate,
+				 new_opp->rate);
+		else
+			dev_opp->suspend_opp = new_opp;
+	}
+
 	if (new_opp->clock_latency_ns > dev_opp->clock_latency_ns_max)
 		dev_opp->clock_latency_ns_max = new_opp->clock_latency_ns;
 

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

* [PATCH V3 10/16] PM / OPP: Add support for opp-suspend
@ 2015-07-31  6:26       ` Viresh Kumar
  0 siblings, 0 replies; 92+ messages in thread
From: Viresh Kumar @ 2015-07-31  6:26 UTC (permalink / raw)
  To: linux-arm-kernel

On 30-07-15, 23:24, Stephen Boyd wrote:
> On 07/29, Viresh Kumar wrote:
> > With "operating-points-v2" bindings, its possible to specify the OPP to
> 
> s/its/it's/ ?
> 
> > which the device must be switched, before suspending.
> > 
> > This patch adds support for getting that information.
> > 
> > Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
> > Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
> > ---
> 
> Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>

---------------------8<-------------------

Message-Id: <5e0cf40cc78bfa327cbbccae016d03a1dfbd1a84.1438323941.git.viresh.kumar@linaro.org>
From: Viresh Kumar <viresh.kumar@linaro.org>
Date: Sat, 13 Jun 2015 15:10:21 +0530
Subject: [PATCH] PM / OPP: Add support for opp-suspend

With "operating-points-v2" bindings, it's possible to specify the OPP to
which the device must be switched, before suspending.

This patch adds support for getting that information.

Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>
Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/base/power/opp.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c
index 5d699e3ec136..0ebcea49145a 100644
--- a/drivers/base/power/opp.c
+++ b/drivers/base/power/opp.c
@@ -133,6 +133,7 @@ struct device_opp {
 	struct device_node *np;
 	unsigned long clock_latency_ns_max;
 	bool shared_opp;
+	struct dev_pm_opp *suspend_opp;
 };
 
 /*
@@ -923,6 +924,16 @@ static int _opp_add_static_v2(struct device *dev, struct device_node *np)
 	if (ret)
 		goto free_opp;
 
+	/* OPP to select on device suspend */
+	if (of_property_read_bool(np, "opp-suspend")) {
+		if (dev_opp->suspend_opp)
+			dev_warn(dev, "%s: Multiple suspend OPPs found (%lu %lu)\n",
+				 __func__, dev_opp->suspend_opp->rate,
+				 new_opp->rate);
+		else
+			dev_opp->suspend_opp = new_opp;
+	}
+
 	if (new_opp->clock_latency_ns > dev_opp->clock_latency_ns_max)
 		dev_opp->clock_latency_ns_max = new_opp->clock_latency_ns;
 

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

* Re: [PATCH V3 00/16] OPP: Add code to support operating-points-v2 bindings
  2015-07-29 10:52 ` Viresh Kumar
@ 2015-07-31 18:55   ` Bartlomiej Zolnierkiewicz
  -1 siblings, 0 replies; 92+ messages in thread
From: Bartlomiej Zolnierkiewicz @ 2015-07-31 18:55 UTC (permalink / raw)
  To: Viresh Kumar
  Cc: Rafael Wysocki, sboyd, linaro-kernel, linux-pm, rob.herring,
	arnd.bergmann, nm, broonie, mturquette, Sudeep.Holla,
	viswanath.puttagunta, l.stach, thomas.petazzoni,
	linux-arm-kernel, ta.omasab, kesavan.abhilash, khilman,
	santosh.shilimkar


Hi,

On Wednesday, July 29, 2015 04:22:55 PM Viresh Kumar wrote:
> Hi Guys,
> 
> Resending this again because:
> - opp-hz is now 64 bit long and so that required a binding update.
> - There is another 4 patch series that as updating turbo OPP support,
>   along with updates to cpufreq core and cpufreq-dt driver.
> - A minor bug-fix in V2 4/11, which caused false positive for duplicate
>   OPPs in some cases.
> 
> Tested this on dual-core exynos board with the driver inbuilt as well as
> a module. Tried multiple insertion/removals of the module. Have tested
> cpufreq-dt driver with both old and new bindings.

I have tested these patches (including boost support) together with my
cpufreq-dt conversion patches for Exynos4x12 platforms on Odroid-U3 and
Trats2 boards.

Tested-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>

Best regards,
--
Bartlomiej Zolnierkiewicz
Samsung R&D Institute Poland
Samsung Electronics


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

* [PATCH V3 00/16] OPP: Add code to support operating-points-v2 bindings
@ 2015-07-31 18:55   ` Bartlomiej Zolnierkiewicz
  0 siblings, 0 replies; 92+ messages in thread
From: Bartlomiej Zolnierkiewicz @ 2015-07-31 18:55 UTC (permalink / raw)
  To: linux-arm-kernel


Hi,

On Wednesday, July 29, 2015 04:22:55 PM Viresh Kumar wrote:
> Hi Guys,
> 
> Resending this again because:
> - opp-hz is now 64 bit long and so that required a binding update.
> - There is another 4 patch series that as updating turbo OPP support,
>   along with updates to cpufreq core and cpufreq-dt driver.
> - A minor bug-fix in V2 4/11, which caused false positive for duplicate
>   OPPs in some cases.
> 
> Tested this on dual-core exynos board with the driver inbuilt as well as
> a module. Tried multiple insertion/removals of the module. Have tested
> cpufreq-dt driver with both old and new bindings.

I have tested these patches (including boost support) together with my
cpufreq-dt conversion patches for Exynos4x12 platforms on Odroid-U3 and
Trats2 boards.

Tested-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>

Best regards,
--
Bartlomiej Zolnierkiewicz
Samsung R&D Institute Poland
Samsung Electronics

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

end of thread, other threads:[~2015-07-31 18:56 UTC | newest]

Thread overview: 92+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-07-29 10:52 [PATCH V3 00/16] OPP: Add code to support operating-points-v2 bindings Viresh Kumar
2015-07-29 10:52 ` Viresh Kumar
2015-07-29 10:52 ` [PATCH V3 01/16] PM / OPP: Update bindings to make opp-hz a 64 bit value Viresh Kumar
2015-07-29 10:52   ` Viresh Kumar
2015-07-29 10:52   ` Viresh Kumar
2015-07-30 13:23   ` Rob Herring
2015-07-30 13:23     ` Rob Herring
2015-07-30 13:23     ` Rob Herring
2015-07-29 10:52 ` [PATCH V3 02/16] PM / OPP: Create a directory for opp bindings Viresh Kumar
2015-07-29 10:52   ` Viresh Kumar
2015-07-30 13:18   ` Rob Herring
2015-07-30 13:18     ` Rob Herring
2015-07-30 13:49     ` Viresh Kumar
2015-07-30 13:49       ` Viresh Kumar
2015-07-30 16:24       ` Rob Herring
2015-07-30 16:24         ` Rob Herring
2015-07-30 16:52         ` Viresh Kumar
2015-07-30 16:52           ` Viresh Kumar
2015-07-30 16:57           ` [PATCH V3 resend] " Viresh Kumar
2015-07-30 16:57             ` Viresh Kumar
2015-07-29 10:52 ` [PATCH V3 03/16] PM / OPP: Relocate few routines Viresh Kumar
2015-07-29 10:52   ` Viresh Kumar
2015-07-29 10:52   ` Viresh Kumar
2015-07-29 10:52 ` [PATCH V3 04/16] PM / OPP: Create _remove_device_opp() for freeing dev_opp Viresh Kumar
2015-07-29 10:52   ` Viresh Kumar
2015-07-29 10:52   ` Viresh Kumar
2015-07-29 10:53 ` [PATCH V3 05/16] PM / OPP: Allocate dev_opp from _add_device_opp() Viresh Kumar
2015-07-29 10:53   ` Viresh Kumar
2015-07-29 10:53   ` Viresh Kumar
2015-07-29 10:53 ` [PATCH V3 06/16] PM / OPP: Break _opp_add_dynamic() into smaller functions Viresh Kumar
2015-07-29 10:53   ` Viresh Kumar
2015-07-29 10:53   ` Viresh Kumar
2015-07-31  5:43   ` Stephen Boyd
2015-07-31  5:43     ` Stephen Boyd
2015-07-29 10:53 ` [PATCH V3 07/16] PM / OPP: Add support to parse "operating-points-v2" bindings Viresh Kumar
2015-07-29 10:53   ` Viresh Kumar
2015-07-29 10:53   ` Viresh Kumar
2015-07-31  5:51   ` Stephen Boyd
2015-07-31  5:51     ` Stephen Boyd
2015-07-31  5:58     ` Viresh Kumar
2015-07-31  5:58       ` Viresh Kumar
2015-07-31  6:20       ` Stephen Boyd
2015-07-31  6:20         ` Stephen Boyd
2015-07-29 10:53 ` [PATCH V3 08/16] PM / OPP: Add clock-latency-ns support Viresh Kumar
2015-07-29 10:53   ` Viresh Kumar
2015-07-29 10:53   ` Viresh Kumar
2015-07-29 10:53 ` [PATCH V3 09/16] PM / OPP: Add OPP sharing information to OPP library Viresh Kumar
2015-07-29 10:53   ` Viresh Kumar
2015-07-29 10:53   ` Viresh Kumar
2015-07-29 10:53 ` [PATCH V3 10/16] PM / OPP: Add support for opp-suspend Viresh Kumar
2015-07-29 10:53   ` Viresh Kumar
2015-07-29 10:53   ` Viresh Kumar
2015-07-31  6:24   ` Stephen Boyd
2015-07-31  6:24     ` Stephen Boyd
2015-07-31  6:26     ` Viresh Kumar
2015-07-31  6:26       ` Viresh Kumar
2015-07-29 10:53 ` [PATCH V3 11/16] PM / OPP: Add helpers for initializing CPU OPPs Viresh Kumar
2015-07-29 10:53   ` Viresh Kumar
2015-07-29 10:53   ` Viresh Kumar
2015-07-31  6:07   ` Stephen Boyd
2015-07-31  6:07     ` Stephen Boyd
2015-07-31  6:13     ` Viresh Kumar
2015-07-31  6:13       ` Viresh Kumar
2015-07-29 10:53 ` [PATCH V3 12/16] PM / OPP: add dev_pm_opp_is_turbo() helper Viresh Kumar
2015-07-29 10:53   ` Viresh Kumar
2015-07-29 10:53   ` Viresh Kumar
2015-07-31  6:10   ` Stephen Boyd
2015-07-31  6:10     ` Stephen Boyd
2015-07-31  6:17     ` Viresh Kumar
2015-07-31  6:17       ` Viresh Kumar
2015-07-29 10:53 ` [PATCH V3 13/16] cpufreq: Update boost flag while initializing freq table from OPPs Viresh Kumar
2015-07-29 10:53   ` Viresh Kumar
2015-07-29 10:53   ` Viresh Kumar
2015-07-31  6:11   ` Stephen Boyd
2015-07-31  6:11     ` Stephen Boyd
2015-07-29 10:53 ` [PATCH V3 14/16] cpufreq: Allow drivers to enable boost support after registering driver Viresh Kumar
2015-07-29 10:53   ` Viresh Kumar
2015-07-29 10:53   ` Viresh Kumar
2015-07-31  6:12   ` Stephen Boyd
2015-07-31  6:12     ` Stephen Boyd
2015-07-29 10:53 ` [PATCH V3 15/16] cpufreq: dt: Add support for operating-points-v2 bindings Viresh Kumar
2015-07-29 10:53   ` Viresh Kumar
2015-07-29 10:53   ` Viresh Kumar
2015-07-31  6:15   ` Stephen Boyd
2015-07-31  6:15     ` Stephen Boyd
2015-07-29 10:53 ` [PATCH V3 16/16] cpufreq: dt: Add support for turbo/boost mode Viresh Kumar
2015-07-29 10:53   ` Viresh Kumar
2015-07-29 10:53   ` Viresh Kumar
2015-07-31  6:16   ` Stephen Boyd
2015-07-31  6:16     ` Stephen Boyd
2015-07-31 18:55 ` [PATCH V3 00/16] OPP: Add code to support operating-points-v2 bindings Bartlomiej Zolnierkiewicz
2015-07-31 18:55   ` Bartlomiej Zolnierkiewicz

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.