All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH 00/14] RFCv2: device thermal limits represented in device tree nodes
@ 2013-08-23 23:15 ` Eduardo Valentin
  0 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-23 23:15 UTC (permalink / raw)
  To: swarren, pawel.moll, mark.rutland, ian.campbell, grant.likely,
	rob.herring, linux, rui.zhang, wni
  Cc: durgadoss.r, linux-pm, devicetree, lm-sensors, linux-kernel,
	Eduardo Valentin

Hello all,

First of all, apologize for the very late answer. But I am resuming this work.

This RFC is about describing hardware thermal limits using device tree.

Based on the discussion on the first RFC:
http://lkml.org/lkml/2013/7/22/319

I have changed the code and the device tree bindings as follows:
1. Now bindings may have several thermal zones per device (req. by Wei Ni)
2. The constants used are now using C preprocessor macros (as per Stephen suggestion)
3. Improved the bindings to have a better representation of links between
involved entities (thermal zone, cooling devices, sensors), as suggested
by Pawel and Mark.
4. Couple of changes in code, as per previous reviews.
5. Removed policies from DT bindings.

In summary, based on the discussion of the first RFC, now the idea is
to have thermal zones nodes describing the thermal zones
and the hardware limits. Then sensor devices nodes will point to
thermal zones via phandles and cooling device will also point to
thermal zone via phandles.

So, I am also posting the patch series to dt mailing list as requested.

Please refer to patch 02/14 to a documentation of what I am proposing.

This patch series includes:
a. Required changes in cpufreq-cpu0 driver so that it loads cooling device
when requested.
b. The thermal zone builder based on thermal bindings
c. Changes in sensor drivers (as examples)
d. Changes in device tree DTS files (as examples)

This patch series depends on the fixes I sent to linux-pm:
http://lkml.org/lkml/2013/8/23/572

In the above link you will find also the request to have a flag to
determine if virtual hwmon device will be created, based on thermal device.

All best,

Eduardo Valentin (14):
  cpufreq: cpufreq-cpu0: add dt node parsing for 'cooling-zones'
  drivers: thermal: introduce device tree parser
  hwmon: lm75: expose to thermal fw via DT nodes
  hwmon: tmp102: expose to thermal fw via DT nodes
  thermal: ti-soc-thermal: use thermal DT infrastructure
  arm: dts: add omap4 CPU thermal data
  arm: dts: add omap4430 thermal data
  arm: dts: add omap4460 thermal data
  arm: dts: point to cooling-zones on omap4430 cpu node
  arm: dts: point to cooling-zones on omap4460 cpu node
  arm: dts: add omap5 GPU thermal data
  arm: dts: add omap5 CORE thermal data
  arm: dts: add omap5 thermal data
  arm: dts: point to cooling-zones on omap5 cpu node

 .../devicetree/bindings/cpufreq/cpufreq-cpu0.txt   |   4 +
 .../devicetree/bindings/thermal/thermal.txt        | 160 +++++++
 arch/arm/boot/dts/omap4-cpu-thermal.dtsi           |  40 ++
 arch/arm/boot/dts/omap443x.dtsi                    |   6 +
 arch/arm/boot/dts/omap4460.dtsi                    |   6 +
 arch/arm/boot/dts/omap5-core-thermal.dtsi          |  27 ++
 arch/arm/boot/dts/omap5-gpu-thermal.dtsi           |  27 ++
 arch/arm/boot/dts/omap5.dtsi                       |  10 +
 drivers/cpufreq/cpufreq-cpu0.c                     |  12 +
 drivers/hwmon/lm75.c                               |  31 ++
 drivers/hwmon/tmp102.c                             |  26 ++
 drivers/thermal/Kconfig                            |  13 +
 drivers/thermal/Makefile                           |   1 +
 drivers/thermal/thermal_dt.c                       | 473 +++++++++++++++++++++
 drivers/thermal/ti-soc-thermal/ti-thermal-common.c |  52 ++-
 include/dt-bindings/thermal/thermal.h              |  27 ++
 include/linux/thermal.h                            |   3 +
 17 files changed, 907 insertions(+), 11 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/thermal/thermal.txt
 create mode 100644 arch/arm/boot/dts/omap4-cpu-thermal.dtsi
 create mode 100644 arch/arm/boot/dts/omap5-core-thermal.dtsi
 create mode 100644 arch/arm/boot/dts/omap5-gpu-thermal.dtsi
 create mode 100644 drivers/thermal/thermal_dt.c
 create mode 100644 include/dt-bindings/thermal/thermal.h

-- 
1.8.2.1.342.gfa7285d


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

* [RFC PATCH 00/14] RFCv2: device thermal limits represented in device tree nodes
@ 2013-08-23 23:15 ` Eduardo Valentin
  0 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-23 23:15 UTC (permalink / raw)
  To: swarren, pawel.moll, mark.rutland, ian.campbell, grant.likely,
	rob.herring, linux, rui.zhang, wni
  Cc: durgadoss.r, linux-pm, devicetree, lm-sensors, linux-kernel,
	Eduardo Valentin

Hello all,

First of all, apologize for the very late answer. But I am resuming this work.

This RFC is about describing hardware thermal limits using device tree.

Based on the discussion on the first RFC:
http://lkml.org/lkml/2013/7/22/319

I have changed the code and the device tree bindings as follows:
1. Now bindings may have several thermal zones per device (req. by Wei Ni)
2. The constants used are now using C preprocessor macros (as per Stephen suggestion)
3. Improved the bindings to have a better representation of links between
involved entities (thermal zone, cooling devices, sensors), as suggested
by Pawel and Mark.
4. Couple of changes in code, as per previous reviews.
5. Removed policies from DT bindings.

In summary, based on the discussion of the first RFC, now the idea is
to have thermal zones nodes describing the thermal zones
and the hardware limits. Then sensor devices nodes will point to
thermal zones via phandles and cooling device will also point to
thermal zone via phandles.

So, I am also posting the patch series to dt mailing list as requested.

Please refer to patch 02/14 to a documentation of what I am proposing.

This patch series includes:
a. Required changes in cpufreq-cpu0 driver so that it loads cooling device
when requested.
b. The thermal zone builder based on thermal bindings
c. Changes in sensor drivers (as examples)
d. Changes in device tree DTS files (as examples)

This patch series depends on the fixes I sent to linux-pm:
http://lkml.org/lkml/2013/8/23/572

In the above link you will find also the request to have a flag to
determine if virtual hwmon device will be created, based on thermal device.

All best,

Eduardo Valentin (14):
  cpufreq: cpufreq-cpu0: add dt node parsing for 'cooling-zones'
  drivers: thermal: introduce device tree parser
  hwmon: lm75: expose to thermal fw via DT nodes
  hwmon: tmp102: expose to thermal fw via DT nodes
  thermal: ti-soc-thermal: use thermal DT infrastructure
  arm: dts: add omap4 CPU thermal data
  arm: dts: add omap4430 thermal data
  arm: dts: add omap4460 thermal data
  arm: dts: point to cooling-zones on omap4430 cpu node
  arm: dts: point to cooling-zones on omap4460 cpu node
  arm: dts: add omap5 GPU thermal data
  arm: dts: add omap5 CORE thermal data
  arm: dts: add omap5 thermal data
  arm: dts: point to cooling-zones on omap5 cpu node

 .../devicetree/bindings/cpufreq/cpufreq-cpu0.txt   |   4 +
 .../devicetree/bindings/thermal/thermal.txt        | 160 +++++++
 arch/arm/boot/dts/omap4-cpu-thermal.dtsi           |  40 ++
 arch/arm/boot/dts/omap443x.dtsi                    |   6 +
 arch/arm/boot/dts/omap4460.dtsi                    |   6 +
 arch/arm/boot/dts/omap5-core-thermal.dtsi          |  27 ++
 arch/arm/boot/dts/omap5-gpu-thermal.dtsi           |  27 ++
 arch/arm/boot/dts/omap5.dtsi                       |  10 +
 drivers/cpufreq/cpufreq-cpu0.c                     |  12 +
 drivers/hwmon/lm75.c                               |  31 ++
 drivers/hwmon/tmp102.c                             |  26 ++
 drivers/thermal/Kconfig                            |  13 +
 drivers/thermal/Makefile                           |   1 +
 drivers/thermal/thermal_dt.c                       | 473 +++++++++++++++++++++
 drivers/thermal/ti-soc-thermal/ti-thermal-common.c |  52 ++-
 include/dt-bindings/thermal/thermal.h              |  27 ++
 include/linux/thermal.h                            |   3 +
 17 files changed, 907 insertions(+), 11 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/thermal/thermal.txt
 create mode 100644 arch/arm/boot/dts/omap4-cpu-thermal.dtsi
 create mode 100644 arch/arm/boot/dts/omap5-core-thermal.dtsi
 create mode 100644 arch/arm/boot/dts/omap5-gpu-thermal.dtsi
 create mode 100644 drivers/thermal/thermal_dt.c
 create mode 100644 include/dt-bindings/thermal/thermal.h

-- 
1.8.2.1.342.gfa7285d


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

* [lm-sensors] [RFC PATCH 00/14] RFCv2: device thermal limits represented in device tree nodes
@ 2013-08-23 23:15 ` Eduardo Valentin
  0 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-23 23:15 UTC (permalink / raw)
  To: swarren, pawel.moll, mark.rutland, ian.campbell, grant.likely,
	rob.herring, linux, rui.zhang, wni
  Cc: durgadoss.r, linux-pm, devicetree, lm-sensors, linux-kernel,
	Eduardo Valentin

Hello all,

First of all, apologize for the very late answer. But I am resuming this work.

This RFC is about describing hardware thermal limits using device tree.

Based on the discussion on the first RFC:
http://lkml.org/lkml/2013/7/22/319

I have changed the code and the device tree bindings as follows:
1. Now bindings may have several thermal zones per device (req. by Wei Ni)
2. The constants used are now using C preprocessor macros (as per Stephen suggestion)
3. Improved the bindings to have a better representation of links between
involved entities (thermal zone, cooling devices, sensors), as suggested
by Pawel and Mark.
4. Couple of changes in code, as per previous reviews.
5. Removed policies from DT bindings.

In summary, based on the discussion of the first RFC, now the idea is
to have thermal zones nodes describing the thermal zones
and the hardware limits. Then sensor devices nodes will point to
thermal zones via phandles and cooling device will also point to
thermal zone via phandles.

So, I am also posting the patch series to dt mailing list as requested.

Please refer to patch 02/14 to a documentation of what I am proposing.

This patch series includes:
a. Required changes in cpufreq-cpu0 driver so that it loads cooling device
when requested.
b. The thermal zone builder based on thermal bindings
c. Changes in sensor drivers (as examples)
d. Changes in device tree DTS files (as examples)

This patch series depends on the fixes I sent to linux-pm:
http://lkml.org/lkml/2013/8/23/572

In the above link you will find also the request to have a flag to
determine if virtual hwmon device will be created, based on thermal device.

All best,

Eduardo Valentin (14):
  cpufreq: cpufreq-cpu0: add dt node parsing for 'cooling-zones'
  drivers: thermal: introduce device tree parser
  hwmon: lm75: expose to thermal fw via DT nodes
  hwmon: tmp102: expose to thermal fw via DT nodes
  thermal: ti-soc-thermal: use thermal DT infrastructure
  arm: dts: add omap4 CPU thermal data
  arm: dts: add omap4430 thermal data
  arm: dts: add omap4460 thermal data
  arm: dts: point to cooling-zones on omap4430 cpu node
  arm: dts: point to cooling-zones on omap4460 cpu node
  arm: dts: add omap5 GPU thermal data
  arm: dts: add omap5 CORE thermal data
  arm: dts: add omap5 thermal data
  arm: dts: point to cooling-zones on omap5 cpu node

 .../devicetree/bindings/cpufreq/cpufreq-cpu0.txt   |   4 +
 .../devicetree/bindings/thermal/thermal.txt        | 160 +++++++
 arch/arm/boot/dts/omap4-cpu-thermal.dtsi           |  40 ++
 arch/arm/boot/dts/omap443x.dtsi                    |   6 +
 arch/arm/boot/dts/omap4460.dtsi                    |   6 +
 arch/arm/boot/dts/omap5-core-thermal.dtsi          |  27 ++
 arch/arm/boot/dts/omap5-gpu-thermal.dtsi           |  27 ++
 arch/arm/boot/dts/omap5.dtsi                       |  10 +
 drivers/cpufreq/cpufreq-cpu0.c                     |  12 +
 drivers/hwmon/lm75.c                               |  31 ++
 drivers/hwmon/tmp102.c                             |  26 ++
 drivers/thermal/Kconfig                            |  13 +
 drivers/thermal/Makefile                           |   1 +
 drivers/thermal/thermal_dt.c                       | 473 +++++++++++++++++++++
 drivers/thermal/ti-soc-thermal/ti-thermal-common.c |  52 ++-
 include/dt-bindings/thermal/thermal.h              |  27 ++
 include/linux/thermal.h                            |   3 +
 17 files changed, 907 insertions(+), 11 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/thermal/thermal.txt
 create mode 100644 arch/arm/boot/dts/omap4-cpu-thermal.dtsi
 create mode 100644 arch/arm/boot/dts/omap5-core-thermal.dtsi
 create mode 100644 arch/arm/boot/dts/omap5-gpu-thermal.dtsi
 create mode 100644 drivers/thermal/thermal_dt.c
 create mode 100644 include/dt-bindings/thermal/thermal.h

-- 
1.8.2.1.342.gfa7285d


_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

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

* [RFC PATCH 01/14] cpufreq: cpufreq-cpu0: add dt node parsing for 'cooling-zones'
  2013-08-23 23:15 ` Eduardo Valentin
  (?)
@ 2013-08-23 23:15   ` Eduardo Valentin
  -1 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-23 23:15 UTC (permalink / raw)
  To: swarren, pawel.moll, mark.rutland, ian.campbell, grant.likely,
	rob.herring, linux, rui.zhang, wni
  Cc: durgadoss.r, linux-pm, devicetree, lm-sensors, linux-kernel,
	Eduardo Valentin, Rafael J. Wysocki, Viresh Kumar, cpufreq,
	devicetree-discuss

This patch changes the cpufreq-cpu0 driver to consider if
a cpu needs cooling (with cpufreq). In case the cooling is needed,
it can be flagged at the cpu0 device tree node, with the list
of zones property 'cooling-zones'.

In case this list of zones is present, the driver will
load a cpufreq cooling device in the system. The cpufreq-cpu0
driver is not interested in determining how the system should
be using the cooling device. The driver is responsible
only of loading the cooling device.

Describing how the cooling device will be used can be
accomplished by setting up a thermal zone that references
and is composed by the cpufreq cooling device.

Cc: "Rafael J. Wysocki" <rjw@sisk.pl>
Cc: Viresh Kumar <viresh.kumar@linaro.org>
Cc: Grant Likely <grant.likely@linaro.org>
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: cpufreq@vger.kernel.org
Cc: linux-pm@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: devicetree-discuss@lists.ozlabs.org
Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
---
 Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt |  4 ++++
 drivers/cpufreq/cpufreq-cpu0.c                             | 12 ++++++++++++
 2 files changed, 16 insertions(+)

diff --git a/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt b/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt
index 051f764..add50f7 100644
--- a/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt
+++ b/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt
@@ -15,6 +15,9 @@ Optional properties:
 - clock-latency: Specify the possible maximum transition latency for clock,
   in unit of nanoseconds.
 - voltage-tolerance: Specify the CPU voltage tolerance in percentage.
+- cooling-zones: A list of thermal zones phandles. The generic cpu
+  cooling (freq clipping) is loaded by the generic cpufreq-cpu0 driver
+  in case the device tree node has this list.
 
 Examples:
 
@@ -33,6 +36,7 @@ cpus {
 			198000  850000
 		>;
 		clock-latency = <61036>; /* two CLK32 periods */
+		cooling-zones = <&cpu_thermal>;
 	};
 
 	cpu@1 {
diff --git a/drivers/cpufreq/cpufreq-cpu0.c b/drivers/cpufreq/cpufreq-cpu0.c
index ad1fde2..ede6487 100644
--- a/drivers/cpufreq/cpufreq-cpu0.c
+++ b/drivers/cpufreq/cpufreq-cpu0.c
@@ -20,6 +20,9 @@
 #include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
+#include <linux/thermal.h>
+#include <linux/cpu_cooling.h>
+#include <linux/cpumask.h>
 
 static unsigned int transition_latency;
 static unsigned int voltage_tolerance; /* in percentage */
@@ -28,6 +31,7 @@ static struct device *cpu_dev;
 static struct clk *cpu_clk;
 static struct regulator *cpu_reg;
 static struct cpufreq_frequency_table *freq_table;
+static struct thermal_cooling_device *cdev;
 
 static int cpu0_verify_speed(struct cpufreq_policy *policy)
 {
@@ -268,6 +272,13 @@ static int cpu0_cpufreq_probe(struct platform_device *pdev)
 		goto out_free_table;
 	}
 
+	/*
+	 * For now, just loading the cooling device;
+	 * thermal DT code takes care of matching them.
+	 */
+	if (of_find_property(np, "cooling-zones", NULL))
+		cdev = cpufreq_cooling_register(cpu_present_mask);
+
 	of_node_put(np);
 	of_node_put(parent);
 	return 0;
@@ -283,6 +294,7 @@ out_put_parent:
 
 static int cpu0_cpufreq_remove(struct platform_device *pdev)
 {
+	cpufreq_cooling_unregister(cdev);
 	cpufreq_unregister_driver(&cpu0_cpufreq_driver);
 	opp_free_cpufreq_table(cpu_dev, &freq_table);
 
-- 
1.8.2.1.342.gfa7285d


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

* [RFC PATCH 01/14] cpufreq: cpufreq-cpu0: add dt node parsing for 'cooling-zones'
@ 2013-08-23 23:15   ` Eduardo Valentin
  0 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-23 23:15 UTC (permalink / raw)
  To: swarren, pawel.moll, mark.rutland, ian.campbell, grant.likely,
	rob.herring, linux, rui.zhang, wni
  Cc: durgadoss.r, linux-pm, devicetree, lm-sensors, linux-kernel,
	Eduardo Valentin, Rafael J. Wysocki, Viresh Kumar, cpufreq,
	devicetree-discuss

This patch changes the cpufreq-cpu0 driver to consider if
a cpu needs cooling (with cpufreq). In case the cooling is needed,
it can be flagged at the cpu0 device tree node, with the list
of zones property 'cooling-zones'.

In case this list of zones is present, the driver will
load a cpufreq cooling device in the system. The cpufreq-cpu0
driver is not interested in determining how the system should
be using the cooling device. The driver is responsible
only of loading the cooling device.

Describing how the cooling device will be used can be
accomplished by setting up a thermal zone that references
and is composed by the cpufreq cooling device.

Cc: "Rafael J. Wysocki" <rjw@sisk.pl>
Cc: Viresh Kumar <viresh.kumar@linaro.org>
Cc: Grant Likely <grant.likely@linaro.org>
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: cpufreq@vger.kernel.org
Cc: linux-pm@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: devicetree-discuss@lists.ozlabs.org
Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
---
 Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt |  4 ++++
 drivers/cpufreq/cpufreq-cpu0.c                             | 12 ++++++++++++
 2 files changed, 16 insertions(+)

diff --git a/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt b/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt
index 051f764..add50f7 100644
--- a/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt
+++ b/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt
@@ -15,6 +15,9 @@ Optional properties:
 - clock-latency: Specify the possible maximum transition latency for clock,
   in unit of nanoseconds.
 - voltage-tolerance: Specify the CPU voltage tolerance in percentage.
+- cooling-zones: A list of thermal zones phandles. The generic cpu
+  cooling (freq clipping) is loaded by the generic cpufreq-cpu0 driver
+  in case the device tree node has this list.
 
 Examples:
 
@@ -33,6 +36,7 @@ cpus {
 			198000  850000
 		>;
 		clock-latency = <61036>; /* two CLK32 periods */
+		cooling-zones = <&cpu_thermal>;
 	};
 
 	cpu@1 {
diff --git a/drivers/cpufreq/cpufreq-cpu0.c b/drivers/cpufreq/cpufreq-cpu0.c
index ad1fde2..ede6487 100644
--- a/drivers/cpufreq/cpufreq-cpu0.c
+++ b/drivers/cpufreq/cpufreq-cpu0.c
@@ -20,6 +20,9 @@
 #include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
+#include <linux/thermal.h>
+#include <linux/cpu_cooling.h>
+#include <linux/cpumask.h>
 
 static unsigned int transition_latency;
 static unsigned int voltage_tolerance; /* in percentage */
@@ -28,6 +31,7 @@ static struct device *cpu_dev;
 static struct clk *cpu_clk;
 static struct regulator *cpu_reg;
 static struct cpufreq_frequency_table *freq_table;
+static struct thermal_cooling_device *cdev;
 
 static int cpu0_verify_speed(struct cpufreq_policy *policy)
 {
@@ -268,6 +272,13 @@ static int cpu0_cpufreq_probe(struct platform_device *pdev)
 		goto out_free_table;
 	}
 
+	/*
+	 * For now, just loading the cooling device;
+	 * thermal DT code takes care of matching them.
+	 */
+	if (of_find_property(np, "cooling-zones", NULL))
+		cdev = cpufreq_cooling_register(cpu_present_mask);
+
 	of_node_put(np);
 	of_node_put(parent);
 	return 0;
@@ -283,6 +294,7 @@ out_put_parent:
 
 static int cpu0_cpufreq_remove(struct platform_device *pdev)
 {
+	cpufreq_cooling_unregister(cdev);
 	cpufreq_unregister_driver(&cpu0_cpufreq_driver);
 	opp_free_cpufreq_table(cpu_dev, &freq_table);
 
-- 
1.8.2.1.342.gfa7285d

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

* [lm-sensors] [RFC PATCH 01/14] cpufreq: cpufreq-cpu0: add dt node parsing for 'cooling-zones'
@ 2013-08-23 23:15   ` Eduardo Valentin
  0 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-23 23:15 UTC (permalink / raw)
  To: swarren, pawel.moll, mark.rutland, ian.campbell, grant.likely,
	rob.herring, linux, rui.zhang, wni
  Cc: durgadoss.r, linux-pm, devicetree, lm-sensors, linux-kernel,
	Eduardo Valentin, Rafael J. Wysocki, Viresh Kumar, cpufreq,
	devicetree-discuss

This patch changes the cpufreq-cpu0 driver to consider if
a cpu needs cooling (with cpufreq). In case the cooling is needed,
it can be flagged at the cpu0 device tree node, with the list
of zones property 'cooling-zones'.

In case this list of zones is present, the driver will
load a cpufreq cooling device in the system. The cpufreq-cpu0
driver is not interested in determining how the system should
be using the cooling device. The driver is responsible
only of loading the cooling device.

Describing how the cooling device will be used can be
accomplished by setting up a thermal zone that references
and is composed by the cpufreq cooling device.

Cc: "Rafael J. Wysocki" <rjw@sisk.pl>
Cc: Viresh Kumar <viresh.kumar@linaro.org>
Cc: Grant Likely <grant.likely@linaro.org>
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: cpufreq@vger.kernel.org
Cc: linux-pm@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: devicetree-discuss@lists.ozlabs.org
Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
---
 Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt |  4 ++++
 drivers/cpufreq/cpufreq-cpu0.c                             | 12 ++++++++++++
 2 files changed, 16 insertions(+)

diff --git a/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt b/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt
index 051f764..add50f7 100644
--- a/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt
+++ b/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt
@@ -15,6 +15,9 @@ Optional properties:
 - clock-latency: Specify the possible maximum transition latency for clock,
   in unit of nanoseconds.
 - voltage-tolerance: Specify the CPU voltage tolerance in percentage.
+- cooling-zones: A list of thermal zones phandles. The generic cpu
+  cooling (freq clipping) is loaded by the generic cpufreq-cpu0 driver
+  in case the device tree node has this list.
 
 Examples:
 
@@ -33,6 +36,7 @@ cpus {
 			198000  850000
 		>;
 		clock-latency = <61036>; /* two CLK32 periods */
+		cooling-zones = <&cpu_thermal>;
 	};
 
 	cpu@1 {
diff --git a/drivers/cpufreq/cpufreq-cpu0.c b/drivers/cpufreq/cpufreq-cpu0.c
index ad1fde2..ede6487 100644
--- a/drivers/cpufreq/cpufreq-cpu0.c
+++ b/drivers/cpufreq/cpufreq-cpu0.c
@@ -20,6 +20,9 @@
 #include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
+#include <linux/thermal.h>
+#include <linux/cpu_cooling.h>
+#include <linux/cpumask.h>
 
 static unsigned int transition_latency;
 static unsigned int voltage_tolerance; /* in percentage */
@@ -28,6 +31,7 @@ static struct device *cpu_dev;
 static struct clk *cpu_clk;
 static struct regulator *cpu_reg;
 static struct cpufreq_frequency_table *freq_table;
+static struct thermal_cooling_device *cdev;
 
 static int cpu0_verify_speed(struct cpufreq_policy *policy)
 {
@@ -268,6 +272,13 @@ static int cpu0_cpufreq_probe(struct platform_device *pdev)
 		goto out_free_table;
 	}
 
+	/*
+	 * For now, just loading the cooling device;
+	 * thermal DT code takes care of matching them.
+	 */
+	if (of_find_property(np, "cooling-zones", NULL))
+		cdev = cpufreq_cooling_register(cpu_present_mask);
+
 	of_node_put(np);
 	of_node_put(parent);
 	return 0;
@@ -283,6 +294,7 @@ out_put_parent:
 
 static int cpu0_cpufreq_remove(struct platform_device *pdev)
 {
+	cpufreq_cooling_unregister(cdev);
 	cpufreq_unregister_driver(&cpu0_cpufreq_driver);
 	opp_free_cpufreq_table(cpu_dev, &freq_table);
 
-- 
1.8.2.1.342.gfa7285d


_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

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

* [RFC PATCH 02/14] drivers: thermal: introduce device tree parser
  2013-08-23 23:15 ` Eduardo Valentin
  (?)
@ 2013-08-23 23:15   ` Eduardo Valentin
  -1 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-23 23:15 UTC (permalink / raw)
  To: swarren, pawel.moll, mark.rutland, ian.campbell, grant.likely,
	rob.herring, linux, rui.zhang, wni
  Cc: durgadoss.r, linux-pm, devicetree, lm-sensors, linux-kernel,
	Eduardo Valentin

In order to be able to build thermal policies
based on generic sensors, like I2C device, that
can be places in different points on different boards,
there is a need to have a way to feed board dependent
data into the thermal framework.

This patch introduces a thermal data parser for device
tree. The parsed data is used to build thermal zones
and thermal binding parameters. The output data
can then be used to deploy thermal policies.

This patch adds also documentation regarding this
API and how to define tree nodes to use
this infrastructure.

Cc: Zhang Rui <rui.zhang@intel.com>
Cc: linux-pm@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
---
 .../devicetree/bindings/thermal/thermal.txt        | 160 +++++++
 drivers/thermal/Kconfig                            |  13 +
 drivers/thermal/Makefile                           |   1 +
 drivers/thermal/thermal_dt.c                       | 473 +++++++++++++++++++++
 include/dt-bindings/thermal/thermal.h              |  27 ++
 include/linux/thermal.h                            |   3 +
 6 files changed, 677 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/thermal/thermal.txt
 create mode 100644 drivers/thermal/thermal_dt.c
 create mode 100644 include/dt-bindings/thermal/thermal.h

diff --git a/Documentation/devicetree/bindings/thermal/thermal.txt b/Documentation/devicetree/bindings/thermal/thermal.txt
new file mode 100644
index 0000000..af20ab0
--- /dev/null
+++ b/Documentation/devicetree/bindings/thermal/thermal.txt
@@ -0,0 +1,160 @@
+----------------------------------------
+Thermal Framework Device Tree descriptor
+----------------------------------------
+
+This file describes how to define a thermal structure using device tree.
+A thermal structure includes thermal zones and their components, such
+as name, trip points, polling intervals and cooling devices binding
+descriptors. A binding descriptor may contain information on how to
+react, with a cooling stepped action or a weight on a fair share.
+The target of device tree thermal descriptors is to describe only
+the hardware thermal aspects, not how the system must control or which
+algorithm or policy must take place. It follows a description of each
+type of device tree node.
+
+****
+trip
+****
+
+The trip node is a node to describe a point in the temperature domain
+in which the system takes an action. This node describes just the point,
+not the action.
+
+A node describing a trip must contain:
+- temperature: the trip temperature level, in milliCelsius.
+- hysteresis: a (low) hysteresis value on 'temperature'. This is a relative
+value, in milliCelsius.
+- type: the trip type. Here is the type mapping:
+	THERMAL_TRIP_ACTIVE
+	THERMAL_TRIP_PASSIVE
+	THERMAL_TRIP_HOT
+	THERMAL_TRIP_CRITICAL
+
+**********
+bind_param
+**********
+
+The bind_param node is a node to describe how cooling devices get assigned
+to trip points of the zone. The cooling devices are expected to be loaded
+in the target system.
+
+A node describing a bind_param must contain:
+- cooling_device: A string with the cooling device name.
+- weight: The 'influence' of a particular cooling device on this zone.
+             This is on a percentage scale. The sum of all these weights
+             (for a particular zone) cannot exceed 100.
+- trip_mask: This is a bit mask that gives the binding relation between
+               this thermal zone and cdev, for a particular trip point.
+               If nth bit is set, then the cdev and thermal zone are bound
+               for trip point n.
+- limits: An array integers consisting of 2-tuples items, and each item means
+  lower and upper state limits, like <min-state max-state>.
+
+**************************
+temperature sensor devices
+**************************
+
+Temperature sensor devices have to be linked to a specific thermal zone.
+This is done by means of the 'monitored-zones' list.
+- monitored-zones: A list of thermal zones phandles, identifying which
+thermal zones the temperature sensor device is used to monitor.
+
+************
+thermal_zone
+************
+
+The thermal_zone node is the node containing all the required info
+for describing a thermal zone, including its cdev bindings. The thermal_zone
+node must contain, apart from its own properties, one node containing
+trip nodes and one node containing all the zone bind parameters.
+
+Required properties:
+- mask: Bit string: If 'n'th bit is set, then trip point 'n' is writeable.
+
+- passive_delay: number of milliseconds to wait between polls when
+  performing passive cooling.
+
+- polling_delay: number of milliseconds to wait between polls when checking.
+
+- #thermal-cells: An integer that is used to specify how many cells compose
+  sensor ids.
+
+Below is an example:
+cpu_thermal: thermal_zone {
+            #thermal-cells = <1>;
+            mask = <0x03>; /* trips writability */
+            passive_delay = <250>; /* milliseconds */
+            polling_delay = <1000>; /* milliseconds */
+            trips {
+                    alert@100000{
+                            temperature = <100000>; /* milliCelsius */
+                            hysteresis = <0>; /* milliCelsius */
+                            type = <THERMAL_TRIP_PASSIVE>;
+                    };
+                    crit@125000{
+                            temperature = <125000>; /* milliCelsius */
+                            hysteresis = <0>; /* milliCelsius */
+                            type = <THERMAL_TRIP_CRITICAL>;
+                    };
+            };
+            bind_params {
+                    action@0{
+                            cooling_device = "thermal-cpufreq";
+                            weight = <100>; /* percentage */
+                            mask = <0x01>;
+			    limits = <
+			      /* lower-state		upper-state */
+				1			THERMAL_NO_LIMITS
+				THERMAL_NO_LIMITS	THERMAL_NO_LIMITS
+			    >;
+                    };
+            };
+};
+
+sensor: adc@0xFFFF {
+	...
+	monitored-zones = <&cpu_thermal 0>;
+};
+
+cpu@0 {
+	...
+	cooling-zones = <&cpu_thermal>;
+};
+
+In the example above, the ADC sensor at address 0xFFFF is used to monitor
+the zone 'cpu_thermal' using its the sensor 0. The cpu@0 device is also linked
+to the same thermal zone 'cpu_thermal' as a cooling device.
+
+***************
+cpufreq-cooling
+***************
+
+The generic cpu cooling (freq clipping) can be loaded by the
+generic cpufreq-cpu0 driver in case the device tree node informs
+this need.
+
+In order to load the cpufreq cooling device, it is possible to
+inform that the cpu needs cooling by adding the list of thermal zones
+in the 'cooling-zones' property at the cpu0 phandle.
+
+Example:
+	cpus {
+		cpu@0 {
+			operating-points = <
+				/* kHz    uV */
+				800000  1313000
+				1008000 1375000
+			>;
+			cooling-zones = <&cpu_thermal>;
+		};
+	...
+	};
+
+The above will cause the cpufreq-cpu0 driver to understand that
+the cpu will need passive cooling and while probing that node it will
+also load the cpufreq cpu cooling device in that system.
+
+However, be advised that this flag will not describe what needs to
+be done or how the cpufreq cooling device will be used. In order to
+accomplish this, one needs to write a phandle for a thermal zone, as
+described in the section 'thermal_zone'.
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index 7fb16bc..753f0dc 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -29,6 +29,19 @@ config THERMAL_HWMON
 	  Say 'Y' here if you want all thermal sensors to
 	  have hwmon sysfs interface too.
 
+config THERMAL_OF
+	bool
+	prompt "APIs to parse thermal data out of device tree"
+	depends on OF
+	default y
+	help
+	  This options provides helpers to add the support to
+	  read and parse thermal data definitions out of the
+	  device tree blob.
+
+	  Say 'Y' here if you need to build thermal infrastructure
+	  based on device tree.
+
 choice
 	prompt "Default Thermal governor"
 	default THERMAL_DEFAULT_GOV_STEP_WISE
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index 24cb894..eedb273 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -7,6 +7,7 @@ thermal_sys-y			+= thermal_core.o
 
 # interface to/from other layers providing sensors
 thermal_sys-$(CONFIG_THERMAL_HWMON)		+= thermal_hwmon.o
+thermal_sys-$(CONFIG_THERMAL_OF)		+= thermal_dt.o
 
 # governors
 thermal_sys-$(CONFIG_THERMAL_GOV_FAIR_SHARE)	+= fair_share.o
diff --git a/drivers/thermal/thermal_dt.c b/drivers/thermal/thermal_dt.c
new file mode 100644
index 0000000..cc35485
--- /dev/null
+++ b/drivers/thermal/thermal_dt.c
@@ -0,0 +1,473 @@
+/*
+ *  thermal_dt.c - Generic Thermal Management device tree support.
+ *
+ *  Copyright (C) 2013 Texas Instruments
+ *  Copyright (C) 2013 Eduardo Valentin <eduardo.valentin@ti.com>
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+#include <linux/thermal.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+#include <linux/err.h>
+#include <linux/export.h>
+#include <linux/string.h>
+
+struct __thermal_bind_params {
+	char cooling_device[THERMAL_NAME_LENGTH];
+};
+
+static
+int thermal_of_match(struct thermal_zone_device *tz,
+		     struct thermal_cooling_device *cdev);
+
+static int thermal_of_populate_bind_params(struct device *dev,
+					   struct device_node *node,
+					   struct __thermal_bind_params *__tbp,
+					   struct thermal_bind_params *tbp,
+					   int ntrips)
+{
+	const char *cdev_name;
+	u32 *limits;
+	int ret;
+	u32 prop;
+
+	ret = of_property_read_u32(node, "weight", &prop);
+	if (ret < 0) {
+		dev_err(dev, "missing weight property\n");
+		return ret;
+	}
+	tbp->weight = prop;
+
+	ret = of_property_read_u32(node, "mask", &prop);
+	if (ret < 0) {
+		dev_err(dev, "missing mask property\n");
+		return ret;
+	}
+	tbp->trip_mask = prop;
+
+	/* this will allow us to bind with cooling devices */
+	tbp->match = thermal_of_match;
+
+	ret = of_property_read_string(node, "cooling_device", &cdev_name);
+	if (ret < 0) {
+		dev_err(dev, "missing cooling_device property\n");
+		return ret;
+	}
+	strncpy(__tbp->cooling_device, cdev_name,
+		sizeof(__tbp->cooling_device));
+
+	limits = kzalloc(ntrips * sizeof(*limits) * 2, GFP_KERNEL);
+	if (!limits) {
+		dev_err(dev, "not enough mem for reading limits\n");
+		return -ENOMEM;
+	}
+	ret = of_property_read_u32_array(node, "limits", limits, 2 * ntrips);
+	if (!ret) {
+		int i = ntrips;
+
+		tbp->binding_limits = devm_kzalloc(dev,
+						   ntrips * 2 *
+						   sizeof(*tbp->binding_limits),
+						   GFP_KERNEL);
+		if (!tbp->binding_limits) {
+			dev_err(dev, "not enough mem for storing limits\n");
+			return -ENOMEM;
+		}
+		while (i--)
+			tbp->binding_limits[i] = limits[i];
+	}
+	kfree(limits);
+
+	return 0;
+}
+
+struct __thermal_trip {
+	unsigned long int temperature;
+	unsigned long int hysteresis;
+	enum thermal_trip_type type;
+};
+
+static
+int thermal_of_populate_trip(struct device *dev,
+			     struct device_node *node,
+			     struct __thermal_trip *trip)
+{
+	int ret;
+	int prop;
+
+	ret = of_property_read_u32(node, "temperature", &prop);
+	if (ret < 0) {
+		dev_err(dev, "missing temperature property\n");
+		return ret;
+	}
+	trip->temperature = prop;
+
+	ret = of_property_read_u32(node, "hysteresis", &prop);
+	if (ret < 0) {
+		dev_err(dev, "missing hysteresis property\n");
+		return ret;
+	}
+	trip->hysteresis = prop;
+
+	ret = of_property_read_u32(node, "type", &prop);
+	if (ret < 0) {
+		dev_err(dev, "missing type property\n");
+		return ret;
+	}
+	trip->type = prop;
+
+	return 0;
+}
+
+struct __thermal_zone_device {
+	enum thermal_device_mode mode;
+	int passive_delay;
+	int polling_delay;
+	int mask;
+	int ntrips;
+	char type[THERMAL_NAME_LENGTH];
+	struct __thermal_trip *trips;
+	struct __thermal_bind_params *bind_params;
+	struct thermal_bind_params *tbps;
+	struct thermal_zone_params zone_params;
+	int (*get_temp)(void *, unsigned long *);
+	void *devdata;
+};
+
+static struct __thermal_zone_device *
+thermal_of_build_thermal_zone(struct device *dev, struct device_node *node)
+{
+	struct device_node *child, *gchild;
+	struct __thermal_zone_device *tz;
+	int ret, i;
+	u32 prop;
+
+	if (!node) {
+		dev_err(dev, "no thermal zone node\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	tz = devm_kzalloc(dev, sizeof(*tz), GFP_KERNEL);
+	if (!tz) {
+		dev_err(dev, "not enough memory for thermal of zone\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	ret = of_property_read_u32(node, "passive_delay", &prop);
+	if (ret < 0) {
+		dev_err(dev, "missing passive_delay property\n");
+		return ERR_PTR(ret);
+	}
+	tz->passive_delay = prop;
+
+	ret = of_property_read_u32(node, "polling_delay", &prop);
+	if (ret < 0) {
+		dev_err(dev, "missing polling_delay property\n");
+		return ERR_PTR(ret);
+	}
+	tz->polling_delay = prop;
+
+	ret = of_property_read_u32(node, "mask", &prop);
+	if (ret < 0) {
+		dev_err(dev, "missing mask property\n");
+		return ERR_PTR(ret);
+	}
+	tz->mask = prop;
+
+	/* assume node name as our zone type */
+	strncpy(tz->type, node->name, sizeof(tz->type));
+
+	/* default policy */
+	strncpy(tz->zone_params.governor_name, "step_wise",
+		sizeof(tz->zone_params.governor_name));
+
+	/* trips */
+	child = of_find_node_by_name(node, "trips");
+
+	/* No trips provided */
+	if (!child)
+		goto finish;
+
+	tz->ntrips = of_get_child_count(child);
+	tz->trips = devm_kzalloc(dev, tz->ntrips * sizeof(*tz->trips),
+				 GFP_KERNEL);
+	if (!tz->trips)
+		return ERR_PTR(-ENOMEM);
+	i = 0;
+	for_each_child_of_node(child, gchild)
+		thermal_of_populate_trip(dev, gchild, &tz->trips[i++]);
+
+	/* bind_params */
+	child = of_find_node_by_name(node, "bind_params");
+
+	/* No binding info */
+	if (!child)
+		goto finish;
+
+	tz->zone_params.num_tbps = of_get_child_count(child);
+	tz->bind_params = devm_kzalloc(dev,
+				       tz->zone_params.num_tbps *
+						sizeof(*tz->bind_params),
+				       GFP_KERNEL);
+	if (!tz->bind_params)
+		return ERR_PTR(-ENOMEM);
+	tz->zone_params.tbp = devm_kzalloc(dev,
+					   tz->zone_params.num_tbps *
+						sizeof(*tz->zone_params.tbp),
+					   GFP_KERNEL);
+	if (!tz->zone_params.tbp)
+		return ERR_PTR(-ENOMEM);
+	i = 0;
+	for_each_child_of_node(child, gchild) {
+		thermal_of_populate_bind_params(dev, gchild,
+						&tz->bind_params[i],
+						&tz->zone_params.tbp[i],
+						tz->ntrips);
+		i++;
+	}
+
+finish:
+	tz->mode = THERMAL_DEVICE_ENABLED;
+
+	return tz;
+}
+
+static
+int thermal_of_match(struct thermal_zone_device *tz,
+		     struct thermal_cooling_device *cdev)
+{
+	struct __thermal_zone_device *data = tz->devdata;
+	int i;
+
+	for (i = 0; i < data->zone_params.num_tbps; i++) {
+		if (!strncmp(data->bind_params[i].cooling_device,
+			     cdev->type,
+			     strlen(data->bind_params[i].cooling_device)) &&
+		    (data->zone_params.tbp[i].trip_mask & (1 << i)))
+			return 0;
+	}
+
+	return -EINVAL;
+}
+
+static
+int of_thermal_get_temp(struct thermal_zone_device *tz,
+			unsigned long *temp)
+{
+	struct __thermal_zone_device *data = tz->devdata;
+
+	return data->get_temp(data->devdata, temp);
+}
+
+static
+int of_thermal_get_mode(struct thermal_zone_device *tz,
+			enum thermal_device_mode *mode)
+{
+	struct __thermal_zone_device *data = tz->devdata;
+
+	*mode = data->mode;
+
+	return 0;
+}
+
+static
+int of_thermal_set_mode(struct thermal_zone_device *tz,
+			enum thermal_device_mode mode)
+{
+	struct __thermal_zone_device *data = tz->devdata;
+
+	mutex_lock(&tz->lock);
+
+	if (mode == THERMAL_DEVICE_ENABLED)
+		tz->polling_delay = data->polling_delay;
+	else
+		tz->polling_delay = 0;
+
+	mutex_unlock(&tz->lock);
+
+	data->mode = mode;
+	thermal_zone_device_update(tz);
+
+	return 0;
+}
+
+static
+int of_thermal_get_trip_type(struct thermal_zone_device *tz, int trip,
+			     enum thermal_trip_type *type)
+{
+	struct __thermal_zone_device *data = tz->devdata;
+
+	if (trip >= data->ntrips || trip < 0)
+		return -EDOM;
+
+	*type = data->trips[trip].type;
+
+	return 0;
+}
+
+static
+int of_thermal_get_trip_temp(struct thermal_zone_device *tz, int trip,
+			     unsigned long *temp)
+{
+	struct __thermal_zone_device *data = tz->devdata;
+
+	if (trip >= data->ntrips || trip < 0)
+		return -EDOM;
+
+	*temp = data->trips[trip].temperature;
+
+	return 0;
+}
+
+static
+int of_thermal_set_trip_temp(struct thermal_zone_device *tz, int trip,
+			     unsigned long temp)
+{
+	struct __thermal_zone_device *data = tz->devdata;
+
+	if (trip >= data->ntrips || trip < 0)
+		return -EDOM;
+
+	/* thermal fw should take care of data->mask & (1 << trip) */
+	data->trips[trip].temperature = temp;
+
+	return 0;
+}
+
+static
+int of_thermal_get_trip_hyst(struct thermal_zone_device *tz, int trip,
+			     unsigned long *hyst)
+{
+	struct __thermal_zone_device *data = tz->devdata;
+
+	if (trip >= data->ntrips || trip < 0)
+		return -EDOM;
+
+	*hyst = data->trips[trip].hysteresis;
+
+	return 0;
+}
+
+static
+int of_thermal_set_trip_hyst(struct thermal_zone_device *tz, int trip,
+			     unsigned long hyst)
+{
+	struct __thermal_zone_device *data = tz->devdata;
+
+	if (trip >= data->ntrips || trip < 0)
+		return -EDOM;
+
+	/* thermal fw should take care of data->mask & (1 << trip) */
+	data->trips[trip].hysteresis = hyst;
+
+	return 0;
+}
+
+static int
+of_thermal_get_crit_temp(struct thermal_zone_device *tz, unsigned long *temp)
+{
+	struct __thermal_zone_device *data = tz->devdata;
+	int i;
+
+	for (i = 0; i < data->ntrips; i++)
+		if (data->trips[i].type == THERMAL_TRIP_CRITICAL) {
+			*temp = data->trips[i].temperature;
+			return 0;
+		}
+
+	return -EINVAL;
+}
+
+static const
+struct thermal_zone_device_ops of_thermal_ops = {
+	.get_temp = of_thermal_get_temp,
+	.get_mode = of_thermal_get_mode,
+	.set_mode = of_thermal_set_mode,
+	.get_trip_type = of_thermal_get_trip_type,
+	.get_trip_temp = of_thermal_get_trip_temp,
+	.set_trip_temp = of_thermal_set_trip_temp,
+	.get_trip_hyst = of_thermal_get_trip_hyst,
+	.set_trip_hyst = of_thermal_set_trip_hyst,
+	.get_crit_temp = of_thermal_get_crit_temp,
+};
+
+/**
+ * thermal_zone_of_device_register() - registers a thermal zone based on DT
+ * @device: a valid struct device pointer containing device tree node
+ *          with thermal_zone descriptor.
+ * @data: a private pointer (owned by the caller) that will be passed
+ *        back, when a temperature reading is needed.
+ * @get_temp: a pointer to a function that returns the thermal zone
+ *            temperature.
+ * @add_hwmon:	a boolean to indicate if the thermal to hwmon sysfs interface
+ *		is required. When add_hwmon == true, a hwmon sysfs interface
+ *		will be created. When add_hwmon == false, nothing will be done
+ *
+ * This function will parse the device tree node associated with the
+ * @dev struct and will attempt to build a thermal zone device based
+ * upon the thermal data provided and described by DT.
+ *
+ * The thermal zone temperature is provided by the @get_temp function
+ * pointer. When called, it will have the private pointer @data back.
+ *
+ * Return: On success returns a valid struct thermal_zone_device,
+ * otherwise, it returns a corresponding ERR_PTR(). Caller must
+ * check the return value with help of IS_ERR() helper.
+ */
+struct thermal_zone_device *
+thermal_zone_of_device_register(struct device *dev, int id, bool add_hwmon,
+			void *data, int (*get_temp)(void *, unsigned long *))
+{
+	struct __thermal_zone_device *tz;
+	struct thermal_zone_device_ops *ops;
+	struct of_phandle_args thermal_spec;
+	int ret;
+
+	ret = of_parse_phandle_with_args(dev->of_node,
+					 "monitored-zones",
+					 "#thermal-cells",
+					 id,
+					 &thermal_spec);
+	if (ret) {
+		dev_err(dev, "unable to find desired monitored zone %d\n", id);
+		return ERR_PTR(ret);
+	}
+
+	tz = thermal_of_build_thermal_zone(dev, thermal_spec.np);
+	if (IS_ERR(tz)) {
+		dev_err(dev, "failed to build thermal zone\n");
+		return ERR_CAST(tz);
+	}
+	ops = devm_kzalloc(dev, sizeof(*ops), GFP_KERNEL);
+	if (!ops) {
+		dev_err(dev, "no memory available for thermal ops\n");
+		return ERR_PTR(-ENOMEM);
+	}
+	memcpy(ops, &of_thermal_ops, sizeof(*ops));
+	tz->get_temp = get_temp;
+	tz->devdata = data;
+
+	return thermal_zone_device_register(tz->type, tz->ntrips, tz->mask, tz,
+					    ops, &tz->zone_params,
+					    tz->passive_delay,
+					    tz->polling_delay,
+					    add_hwmon);
+}
+EXPORT_SYMBOL_GPL(thermal_zone_of_device_register);
diff --git a/include/dt-bindings/thermal/thermal.h b/include/dt-bindings/thermal/thermal.h
new file mode 100644
index 0000000..6dd6ccd
--- /dev/null
+++ b/include/dt-bindings/thermal/thermal.h
@@ -0,0 +1,27 @@
+/*
+ * This header provides constants for most thermal bindings.
+ *
+ * Copyright (C) 2013 Texas Instruments
+ *	Eduardo Valentin <eduardo.valentin@ti.com>
+ *
+ * GPLv2 only
+ */
+
+#ifndef _DT_BINDINGS_THERMAL_THERMAL_H
+#define _DT_BINDINGS_THERMAL_THERMAL_H
+
+/*
+ * Here are the thermal trip types. This must
+ * match with enum thermal_trip_type at
+ * include/linux/thermal.h
+ */
+#define THERMAL_TRIP_ACTIVE		0
+#define THERMAL_TRIP_PASSIVE		1
+#define THERMAL_TRIP_HOT		2
+#define THERMAL_TRIP_CRITICAL		3
+
+/* On cooling devices upper and lower limits */
+#define THERMAL_NO_LIMIT		(-1UL)
+
+#endif
+
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index 7c2769c..501b2fe 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -234,6 +234,9 @@ struct thermal_genl_event {
 };
 
 /* Function declarations */
+struct thermal_zone_device
+*thermal_zone_of_device_register(struct device *, int id, bool add_hwmon,
+	void *data, int (*get_temp) (void *, unsigned long *));
 struct thermal_zone_device *thermal_zone_device_register(const char *, int, int,
 		void *, const struct thermal_zone_device_ops *,
 		const struct thermal_zone_params *, int, int, bool);
-- 
1.8.2.1.342.gfa7285d


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

* [RFC PATCH 02/14] drivers: thermal: introduce device tree parser
@ 2013-08-23 23:15   ` Eduardo Valentin
  0 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-23 23:15 UTC (permalink / raw)
  To: swarren, pawel.moll, mark.rutland, ian.campbell, grant.likely,
	rob.herring, linux, rui.zhang, wni
  Cc: durgadoss.r, linux-pm, devicetree, lm-sensors, linux-kernel,
	Eduardo Valentin

In order to be able to build thermal policies
based on generic sensors, like I2C device, that
can be places in different points on different boards,
there is a need to have a way to feed board dependent
data into the thermal framework.

This patch introduces a thermal data parser for device
tree. The parsed data is used to build thermal zones
and thermal binding parameters. The output data
can then be used to deploy thermal policies.

This patch adds also documentation regarding this
API and how to define tree nodes to use
this infrastructure.

Cc: Zhang Rui <rui.zhang@intel.com>
Cc: linux-pm@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
---
 .../devicetree/bindings/thermal/thermal.txt        | 160 +++++++
 drivers/thermal/Kconfig                            |  13 +
 drivers/thermal/Makefile                           |   1 +
 drivers/thermal/thermal_dt.c                       | 473 +++++++++++++++++++++
 include/dt-bindings/thermal/thermal.h              |  27 ++
 include/linux/thermal.h                            |   3 +
 6 files changed, 677 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/thermal/thermal.txt
 create mode 100644 drivers/thermal/thermal_dt.c
 create mode 100644 include/dt-bindings/thermal/thermal.h

diff --git a/Documentation/devicetree/bindings/thermal/thermal.txt b/Documentation/devicetree/bindings/thermal/thermal.txt
new file mode 100644
index 0000000..af20ab0
--- /dev/null
+++ b/Documentation/devicetree/bindings/thermal/thermal.txt
@@ -0,0 +1,160 @@
+----------------------------------------
+Thermal Framework Device Tree descriptor
+----------------------------------------
+
+This file describes how to define a thermal structure using device tree.
+A thermal structure includes thermal zones and their components, such
+as name, trip points, polling intervals and cooling devices binding
+descriptors. A binding descriptor may contain information on how to
+react, with a cooling stepped action or a weight on a fair share.
+The target of device tree thermal descriptors is to describe only
+the hardware thermal aspects, not how the system must control or which
+algorithm or policy must take place. It follows a description of each
+type of device tree node.
+
+****
+trip
+****
+
+The trip node is a node to describe a point in the temperature domain
+in which the system takes an action. This node describes just the point,
+not the action.
+
+A node describing a trip must contain:
+- temperature: the trip temperature level, in milliCelsius.
+- hysteresis: a (low) hysteresis value on 'temperature'. This is a relative
+value, in milliCelsius.
+- type: the trip type. Here is the type mapping:
+	THERMAL_TRIP_ACTIVE
+	THERMAL_TRIP_PASSIVE
+	THERMAL_TRIP_HOT
+	THERMAL_TRIP_CRITICAL
+
+**********
+bind_param
+**********
+
+The bind_param node is a node to describe how cooling devices get assigned
+to trip points of the zone. The cooling devices are expected to be loaded
+in the target system.
+
+A node describing a bind_param must contain:
+- cooling_device: A string with the cooling device name.
+- weight: The 'influence' of a particular cooling device on this zone.
+             This is on a percentage scale. The sum of all these weights
+             (for a particular zone) cannot exceed 100.
+- trip_mask: This is a bit mask that gives the binding relation between
+               this thermal zone and cdev, for a particular trip point.
+               If nth bit is set, then the cdev and thermal zone are bound
+               for trip point n.
+- limits: An array integers consisting of 2-tuples items, and each item means
+  lower and upper state limits, like <min-state max-state>.
+
+**************************
+temperature sensor devices
+**************************
+
+Temperature sensor devices have to be linked to a specific thermal zone.
+This is done by means of the 'monitored-zones' list.
+- monitored-zones: A list of thermal zones phandles, identifying which
+thermal zones the temperature sensor device is used to monitor.
+
+************
+thermal_zone
+************
+
+The thermal_zone node is the node containing all the required info
+for describing a thermal zone, including its cdev bindings. The thermal_zone
+node must contain, apart from its own properties, one node containing
+trip nodes and one node containing all the zone bind parameters.
+
+Required properties:
+- mask: Bit string: If 'n'th bit is set, then trip point 'n' is writeable.
+
+- passive_delay: number of milliseconds to wait between polls when
+  performing passive cooling.
+
+- polling_delay: number of milliseconds to wait between polls when checking.
+
+- #thermal-cells: An integer that is used to specify how many cells compose
+  sensor ids.
+
+Below is an example:
+cpu_thermal: thermal_zone {
+            #thermal-cells = <1>;
+            mask = <0x03>; /* trips writability */
+            passive_delay = <250>; /* milliseconds */
+            polling_delay = <1000>; /* milliseconds */
+            trips {
+                    alert@100000{
+                            temperature = <100000>; /* milliCelsius */
+                            hysteresis = <0>; /* milliCelsius */
+                            type = <THERMAL_TRIP_PASSIVE>;
+                    };
+                    crit@125000{
+                            temperature = <125000>; /* milliCelsius */
+                            hysteresis = <0>; /* milliCelsius */
+                            type = <THERMAL_TRIP_CRITICAL>;
+                    };
+            };
+            bind_params {
+                    action@0{
+                            cooling_device = "thermal-cpufreq";
+                            weight = <100>; /* percentage */
+                            mask = <0x01>;
+			    limits = <
+			      /* lower-state		upper-state */
+				1			THERMAL_NO_LIMITS
+				THERMAL_NO_LIMITS	THERMAL_NO_LIMITS
+			    >;
+                    };
+            };
+};
+
+sensor: adc@0xFFFF {
+	...
+	monitored-zones = <&cpu_thermal 0>;
+};
+
+cpu@0 {
+	...
+	cooling-zones = <&cpu_thermal>;
+};
+
+In the example above, the ADC sensor at address 0xFFFF is used to monitor
+the zone 'cpu_thermal' using its the sensor 0. The cpu@0 device is also linked
+to the same thermal zone 'cpu_thermal' as a cooling device.
+
+***************
+cpufreq-cooling
+***************
+
+The generic cpu cooling (freq clipping) can be loaded by the
+generic cpufreq-cpu0 driver in case the device tree node informs
+this need.
+
+In order to load the cpufreq cooling device, it is possible to
+inform that the cpu needs cooling by adding the list of thermal zones
+in the 'cooling-zones' property at the cpu0 phandle.
+
+Example:
+	cpus {
+		cpu@0 {
+			operating-points = <
+				/* kHz    uV */
+				800000  1313000
+				1008000 1375000
+			>;
+			cooling-zones = <&cpu_thermal>;
+		};
+	...
+	};
+
+The above will cause the cpufreq-cpu0 driver to understand that
+the cpu will need passive cooling and while probing that node it will
+also load the cpufreq cpu cooling device in that system.
+
+However, be advised that this flag will not describe what needs to
+be done or how the cpufreq cooling device will be used. In order to
+accomplish this, one needs to write a phandle for a thermal zone, as
+described in the section 'thermal_zone'.
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index 7fb16bc..753f0dc 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -29,6 +29,19 @@ config THERMAL_HWMON
 	  Say 'Y' here if you want all thermal sensors to
 	  have hwmon sysfs interface too.
 
+config THERMAL_OF
+	bool
+	prompt "APIs to parse thermal data out of device tree"
+	depends on OF
+	default y
+	help
+	  This options provides helpers to add the support to
+	  read and parse thermal data definitions out of the
+	  device tree blob.
+
+	  Say 'Y' here if you need to build thermal infrastructure
+	  based on device tree.
+
 choice
 	prompt "Default Thermal governor"
 	default THERMAL_DEFAULT_GOV_STEP_WISE
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index 24cb894..eedb273 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -7,6 +7,7 @@ thermal_sys-y			+= thermal_core.o
 
 # interface to/from other layers providing sensors
 thermal_sys-$(CONFIG_THERMAL_HWMON)		+= thermal_hwmon.o
+thermal_sys-$(CONFIG_THERMAL_OF)		+= thermal_dt.o
 
 # governors
 thermal_sys-$(CONFIG_THERMAL_GOV_FAIR_SHARE)	+= fair_share.o
diff --git a/drivers/thermal/thermal_dt.c b/drivers/thermal/thermal_dt.c
new file mode 100644
index 0000000..cc35485
--- /dev/null
+++ b/drivers/thermal/thermal_dt.c
@@ -0,0 +1,473 @@
+/*
+ *  thermal_dt.c - Generic Thermal Management device tree support.
+ *
+ *  Copyright (C) 2013 Texas Instruments
+ *  Copyright (C) 2013 Eduardo Valentin <eduardo.valentin@ti.com>
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+#include <linux/thermal.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+#include <linux/err.h>
+#include <linux/export.h>
+#include <linux/string.h>
+
+struct __thermal_bind_params {
+	char cooling_device[THERMAL_NAME_LENGTH];
+};
+
+static
+int thermal_of_match(struct thermal_zone_device *tz,
+		     struct thermal_cooling_device *cdev);
+
+static int thermal_of_populate_bind_params(struct device *dev,
+					   struct device_node *node,
+					   struct __thermal_bind_params *__tbp,
+					   struct thermal_bind_params *tbp,
+					   int ntrips)
+{
+	const char *cdev_name;
+	u32 *limits;
+	int ret;
+	u32 prop;
+
+	ret = of_property_read_u32(node, "weight", &prop);
+	if (ret < 0) {
+		dev_err(dev, "missing weight property\n");
+		return ret;
+	}
+	tbp->weight = prop;
+
+	ret = of_property_read_u32(node, "mask", &prop);
+	if (ret < 0) {
+		dev_err(dev, "missing mask property\n");
+		return ret;
+	}
+	tbp->trip_mask = prop;
+
+	/* this will allow us to bind with cooling devices */
+	tbp->match = thermal_of_match;
+
+	ret = of_property_read_string(node, "cooling_device", &cdev_name);
+	if (ret < 0) {
+		dev_err(dev, "missing cooling_device property\n");
+		return ret;
+	}
+	strncpy(__tbp->cooling_device, cdev_name,
+		sizeof(__tbp->cooling_device));
+
+	limits = kzalloc(ntrips * sizeof(*limits) * 2, GFP_KERNEL);
+	if (!limits) {
+		dev_err(dev, "not enough mem for reading limits\n");
+		return -ENOMEM;
+	}
+	ret = of_property_read_u32_array(node, "limits", limits, 2 * ntrips);
+	if (!ret) {
+		int i = ntrips;
+
+		tbp->binding_limits = devm_kzalloc(dev,
+						   ntrips * 2 *
+						   sizeof(*tbp->binding_limits),
+						   GFP_KERNEL);
+		if (!tbp->binding_limits) {
+			dev_err(dev, "not enough mem for storing limits\n");
+			return -ENOMEM;
+		}
+		while (i--)
+			tbp->binding_limits[i] = limits[i];
+	}
+	kfree(limits);
+
+	return 0;
+}
+
+struct __thermal_trip {
+	unsigned long int temperature;
+	unsigned long int hysteresis;
+	enum thermal_trip_type type;
+};
+
+static
+int thermal_of_populate_trip(struct device *dev,
+			     struct device_node *node,
+			     struct __thermal_trip *trip)
+{
+	int ret;
+	int prop;
+
+	ret = of_property_read_u32(node, "temperature", &prop);
+	if (ret < 0) {
+		dev_err(dev, "missing temperature property\n");
+		return ret;
+	}
+	trip->temperature = prop;
+
+	ret = of_property_read_u32(node, "hysteresis", &prop);
+	if (ret < 0) {
+		dev_err(dev, "missing hysteresis property\n");
+		return ret;
+	}
+	trip->hysteresis = prop;
+
+	ret = of_property_read_u32(node, "type", &prop);
+	if (ret < 0) {
+		dev_err(dev, "missing type property\n");
+		return ret;
+	}
+	trip->type = prop;
+
+	return 0;
+}
+
+struct __thermal_zone_device {
+	enum thermal_device_mode mode;
+	int passive_delay;
+	int polling_delay;
+	int mask;
+	int ntrips;
+	char type[THERMAL_NAME_LENGTH];
+	struct __thermal_trip *trips;
+	struct __thermal_bind_params *bind_params;
+	struct thermal_bind_params *tbps;
+	struct thermal_zone_params zone_params;
+	int (*get_temp)(void *, unsigned long *);
+	void *devdata;
+};
+
+static struct __thermal_zone_device *
+thermal_of_build_thermal_zone(struct device *dev, struct device_node *node)
+{
+	struct device_node *child, *gchild;
+	struct __thermal_zone_device *tz;
+	int ret, i;
+	u32 prop;
+
+	if (!node) {
+		dev_err(dev, "no thermal zone node\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	tz = devm_kzalloc(dev, sizeof(*tz), GFP_KERNEL);
+	if (!tz) {
+		dev_err(dev, "not enough memory for thermal of zone\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	ret = of_property_read_u32(node, "passive_delay", &prop);
+	if (ret < 0) {
+		dev_err(dev, "missing passive_delay property\n");
+		return ERR_PTR(ret);
+	}
+	tz->passive_delay = prop;
+
+	ret = of_property_read_u32(node, "polling_delay", &prop);
+	if (ret < 0) {
+		dev_err(dev, "missing polling_delay property\n");
+		return ERR_PTR(ret);
+	}
+	tz->polling_delay = prop;
+
+	ret = of_property_read_u32(node, "mask", &prop);
+	if (ret < 0) {
+		dev_err(dev, "missing mask property\n");
+		return ERR_PTR(ret);
+	}
+	tz->mask = prop;
+
+	/* assume node name as our zone type */
+	strncpy(tz->type, node->name, sizeof(tz->type));
+
+	/* default policy */
+	strncpy(tz->zone_params.governor_name, "step_wise",
+		sizeof(tz->zone_params.governor_name));
+
+	/* trips */
+	child = of_find_node_by_name(node, "trips");
+
+	/* No trips provided */
+	if (!child)
+		goto finish;
+
+	tz->ntrips = of_get_child_count(child);
+	tz->trips = devm_kzalloc(dev, tz->ntrips * sizeof(*tz->trips),
+				 GFP_KERNEL);
+	if (!tz->trips)
+		return ERR_PTR(-ENOMEM);
+	i = 0;
+	for_each_child_of_node(child, gchild)
+		thermal_of_populate_trip(dev, gchild, &tz->trips[i++]);
+
+	/* bind_params */
+	child = of_find_node_by_name(node, "bind_params");
+
+	/* No binding info */
+	if (!child)
+		goto finish;
+
+	tz->zone_params.num_tbps = of_get_child_count(child);
+	tz->bind_params = devm_kzalloc(dev,
+				       tz->zone_params.num_tbps *
+						sizeof(*tz->bind_params),
+				       GFP_KERNEL);
+	if (!tz->bind_params)
+		return ERR_PTR(-ENOMEM);
+	tz->zone_params.tbp = devm_kzalloc(dev,
+					   tz->zone_params.num_tbps *
+						sizeof(*tz->zone_params.tbp),
+					   GFP_KERNEL);
+	if (!tz->zone_params.tbp)
+		return ERR_PTR(-ENOMEM);
+	i = 0;
+	for_each_child_of_node(child, gchild) {
+		thermal_of_populate_bind_params(dev, gchild,
+						&tz->bind_params[i],
+						&tz->zone_params.tbp[i],
+						tz->ntrips);
+		i++;
+	}
+
+finish:
+	tz->mode = THERMAL_DEVICE_ENABLED;
+
+	return tz;
+}
+
+static
+int thermal_of_match(struct thermal_zone_device *tz,
+		     struct thermal_cooling_device *cdev)
+{
+	struct __thermal_zone_device *data = tz->devdata;
+	int i;
+
+	for (i = 0; i < data->zone_params.num_tbps; i++) {
+		if (!strncmp(data->bind_params[i].cooling_device,
+			     cdev->type,
+			     strlen(data->bind_params[i].cooling_device)) &&
+		    (data->zone_params.tbp[i].trip_mask & (1 << i)))
+			return 0;
+	}
+
+	return -EINVAL;
+}
+
+static
+int of_thermal_get_temp(struct thermal_zone_device *tz,
+			unsigned long *temp)
+{
+	struct __thermal_zone_device *data = tz->devdata;
+
+	return data->get_temp(data->devdata, temp);
+}
+
+static
+int of_thermal_get_mode(struct thermal_zone_device *tz,
+			enum thermal_device_mode *mode)
+{
+	struct __thermal_zone_device *data = tz->devdata;
+
+	*mode = data->mode;
+
+	return 0;
+}
+
+static
+int of_thermal_set_mode(struct thermal_zone_device *tz,
+			enum thermal_device_mode mode)
+{
+	struct __thermal_zone_device *data = tz->devdata;
+
+	mutex_lock(&tz->lock);
+
+	if (mode == THERMAL_DEVICE_ENABLED)
+		tz->polling_delay = data->polling_delay;
+	else
+		tz->polling_delay = 0;
+
+	mutex_unlock(&tz->lock);
+
+	data->mode = mode;
+	thermal_zone_device_update(tz);
+
+	return 0;
+}
+
+static
+int of_thermal_get_trip_type(struct thermal_zone_device *tz, int trip,
+			     enum thermal_trip_type *type)
+{
+	struct __thermal_zone_device *data = tz->devdata;
+
+	if (trip >= data->ntrips || trip < 0)
+		return -EDOM;
+
+	*type = data->trips[trip].type;
+
+	return 0;
+}
+
+static
+int of_thermal_get_trip_temp(struct thermal_zone_device *tz, int trip,
+			     unsigned long *temp)
+{
+	struct __thermal_zone_device *data = tz->devdata;
+
+	if (trip >= data->ntrips || trip < 0)
+		return -EDOM;
+
+	*temp = data->trips[trip].temperature;
+
+	return 0;
+}
+
+static
+int of_thermal_set_trip_temp(struct thermal_zone_device *tz, int trip,
+			     unsigned long temp)
+{
+	struct __thermal_zone_device *data = tz->devdata;
+
+	if (trip >= data->ntrips || trip < 0)
+		return -EDOM;
+
+	/* thermal fw should take care of data->mask & (1 << trip) */
+	data->trips[trip].temperature = temp;
+
+	return 0;
+}
+
+static
+int of_thermal_get_trip_hyst(struct thermal_zone_device *tz, int trip,
+			     unsigned long *hyst)
+{
+	struct __thermal_zone_device *data = tz->devdata;
+
+	if (trip >= data->ntrips || trip < 0)
+		return -EDOM;
+
+	*hyst = data->trips[trip].hysteresis;
+
+	return 0;
+}
+
+static
+int of_thermal_set_trip_hyst(struct thermal_zone_device *tz, int trip,
+			     unsigned long hyst)
+{
+	struct __thermal_zone_device *data = tz->devdata;
+
+	if (trip >= data->ntrips || trip < 0)
+		return -EDOM;
+
+	/* thermal fw should take care of data->mask & (1 << trip) */
+	data->trips[trip].hysteresis = hyst;
+
+	return 0;
+}
+
+static int
+of_thermal_get_crit_temp(struct thermal_zone_device *tz, unsigned long *temp)
+{
+	struct __thermal_zone_device *data = tz->devdata;
+	int i;
+
+	for (i = 0; i < data->ntrips; i++)
+		if (data->trips[i].type == THERMAL_TRIP_CRITICAL) {
+			*temp = data->trips[i].temperature;
+			return 0;
+		}
+
+	return -EINVAL;
+}
+
+static const
+struct thermal_zone_device_ops of_thermal_ops = {
+	.get_temp = of_thermal_get_temp,
+	.get_mode = of_thermal_get_mode,
+	.set_mode = of_thermal_set_mode,
+	.get_trip_type = of_thermal_get_trip_type,
+	.get_trip_temp = of_thermal_get_trip_temp,
+	.set_trip_temp = of_thermal_set_trip_temp,
+	.get_trip_hyst = of_thermal_get_trip_hyst,
+	.set_trip_hyst = of_thermal_set_trip_hyst,
+	.get_crit_temp = of_thermal_get_crit_temp,
+};
+
+/**
+ * thermal_zone_of_device_register() - registers a thermal zone based on DT
+ * @device: a valid struct device pointer containing device tree node
+ *          with thermal_zone descriptor.
+ * @data: a private pointer (owned by the caller) that will be passed
+ *        back, when a temperature reading is needed.
+ * @get_temp: a pointer to a function that returns the thermal zone
+ *            temperature.
+ * @add_hwmon:	a boolean to indicate if the thermal to hwmon sysfs interface
+ *		is required. When add_hwmon == true, a hwmon sysfs interface
+ *		will be created. When add_hwmon == false, nothing will be done
+ *
+ * This function will parse the device tree node associated with the
+ * @dev struct and will attempt to build a thermal zone device based
+ * upon the thermal data provided and described by DT.
+ *
+ * The thermal zone temperature is provided by the @get_temp function
+ * pointer. When called, it will have the private pointer @data back.
+ *
+ * Return: On success returns a valid struct thermal_zone_device,
+ * otherwise, it returns a corresponding ERR_PTR(). Caller must
+ * check the return value with help of IS_ERR() helper.
+ */
+struct thermal_zone_device *
+thermal_zone_of_device_register(struct device *dev, int id, bool add_hwmon,
+			void *data, int (*get_temp)(void *, unsigned long *))
+{
+	struct __thermal_zone_device *tz;
+	struct thermal_zone_device_ops *ops;
+	struct of_phandle_args thermal_spec;
+	int ret;
+
+	ret = of_parse_phandle_with_args(dev->of_node,
+					 "monitored-zones",
+					 "#thermal-cells",
+					 id,
+					 &thermal_spec);
+	if (ret) {
+		dev_err(dev, "unable to find desired monitored zone %d\n", id);
+		return ERR_PTR(ret);
+	}
+
+	tz = thermal_of_build_thermal_zone(dev, thermal_spec.np);
+	if (IS_ERR(tz)) {
+		dev_err(dev, "failed to build thermal zone\n");
+		return ERR_CAST(tz);
+	}
+	ops = devm_kzalloc(dev, sizeof(*ops), GFP_KERNEL);
+	if (!ops) {
+		dev_err(dev, "no memory available for thermal ops\n");
+		return ERR_PTR(-ENOMEM);
+	}
+	memcpy(ops, &of_thermal_ops, sizeof(*ops));
+	tz->get_temp = get_temp;
+	tz->devdata = data;
+
+	return thermal_zone_device_register(tz->type, tz->ntrips, tz->mask, tz,
+					    ops, &tz->zone_params,
+					    tz->passive_delay,
+					    tz->polling_delay,
+					    add_hwmon);
+}
+EXPORT_SYMBOL_GPL(thermal_zone_of_device_register);
diff --git a/include/dt-bindings/thermal/thermal.h b/include/dt-bindings/thermal/thermal.h
new file mode 100644
index 0000000..6dd6ccd
--- /dev/null
+++ b/include/dt-bindings/thermal/thermal.h
@@ -0,0 +1,27 @@
+/*
+ * This header provides constants for most thermal bindings.
+ *
+ * Copyright (C) 2013 Texas Instruments
+ *	Eduardo Valentin <eduardo.valentin@ti.com>
+ *
+ * GPLv2 only
+ */
+
+#ifndef _DT_BINDINGS_THERMAL_THERMAL_H
+#define _DT_BINDINGS_THERMAL_THERMAL_H
+
+/*
+ * Here are the thermal trip types. This must
+ * match with enum thermal_trip_type at
+ * include/linux/thermal.h
+ */
+#define THERMAL_TRIP_ACTIVE		0
+#define THERMAL_TRIP_PASSIVE		1
+#define THERMAL_TRIP_HOT		2
+#define THERMAL_TRIP_CRITICAL		3
+
+/* On cooling devices upper and lower limits */
+#define THERMAL_NO_LIMIT		(-1UL)
+
+#endif
+
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index 7c2769c..501b2fe 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -234,6 +234,9 @@ struct thermal_genl_event {
 };
 
 /* Function declarations */
+struct thermal_zone_device
+*thermal_zone_of_device_register(struct device *, int id, bool add_hwmon,
+	void *data, int (*get_temp) (void *, unsigned long *));
 struct thermal_zone_device *thermal_zone_device_register(const char *, int, int,
 		void *, const struct thermal_zone_device_ops *,
 		const struct thermal_zone_params *, int, int, bool);
-- 
1.8.2.1.342.gfa7285d


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

* [lm-sensors] [RFC PATCH 02/14] drivers: thermal: introduce device tree parser
@ 2013-08-23 23:15   ` Eduardo Valentin
  0 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-23 23:15 UTC (permalink / raw)
  To: swarren, pawel.moll, mark.rutland, ian.campbell, grant.likely,
	rob.herring, linux, rui.zhang, wni
  Cc: durgadoss.r, linux-pm, devicetree, lm-sensors, linux-kernel,
	Eduardo Valentin

In order to be able to build thermal policies
based on generic sensors, like I2C device, that
can be places in different points on different boards,
there is a need to have a way to feed board dependent
data into the thermal framework.

This patch introduces a thermal data parser for device
tree. The parsed data is used to build thermal zones
and thermal binding parameters. The output data
can then be used to deploy thermal policies.

This patch adds also documentation regarding this
API and how to define tree nodes to use
this infrastructure.

Cc: Zhang Rui <rui.zhang@intel.com>
Cc: linux-pm@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
---
 .../devicetree/bindings/thermal/thermal.txt        | 160 +++++++
 drivers/thermal/Kconfig                            |  13 +
 drivers/thermal/Makefile                           |   1 +
 drivers/thermal/thermal_dt.c                       | 473 +++++++++++++++++++++
 include/dt-bindings/thermal/thermal.h              |  27 ++
 include/linux/thermal.h                            |   3 +
 6 files changed, 677 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/thermal/thermal.txt
 create mode 100644 drivers/thermal/thermal_dt.c
 create mode 100644 include/dt-bindings/thermal/thermal.h

diff --git a/Documentation/devicetree/bindings/thermal/thermal.txt b/Documentation/devicetree/bindings/thermal/thermal.txt
new file mode 100644
index 0000000..af20ab0
--- /dev/null
+++ b/Documentation/devicetree/bindings/thermal/thermal.txt
@@ -0,0 +1,160 @@
+----------------------------------------
+Thermal Framework Device Tree descriptor
+----------------------------------------
+
+This file describes how to define a thermal structure using device tree.
+A thermal structure includes thermal zones and their components, such
+as name, trip points, polling intervals and cooling devices binding
+descriptors. A binding descriptor may contain information on how to
+react, with a cooling stepped action or a weight on a fair share.
+The target of device tree thermal descriptors is to describe only
+the hardware thermal aspects, not how the system must control or which
+algorithm or policy must take place. It follows a description of each
+type of device tree node.
+
+****
+trip
+****
+
+The trip node is a node to describe a point in the temperature domain
+in which the system takes an action. This node describes just the point,
+not the action.
+
+A node describing a trip must contain:
+- temperature: the trip temperature level, in milliCelsius.
+- hysteresis: a (low) hysteresis value on 'temperature'. This is a relative
+value, in milliCelsius.
+- type: the trip type. Here is the type mapping:
+	THERMAL_TRIP_ACTIVE
+	THERMAL_TRIP_PASSIVE
+	THERMAL_TRIP_HOT
+	THERMAL_TRIP_CRITICAL
+
+**********
+bind_param
+**********
+
+The bind_param node is a node to describe how cooling devices get assigned
+to trip points of the zone. The cooling devices are expected to be loaded
+in the target system.
+
+A node describing a bind_param must contain:
+- cooling_device: A string with the cooling device name.
+- weight: The 'influence' of a particular cooling device on this zone.
+             This is on a percentage scale. The sum of all these weights
+             (for a particular zone) cannot exceed 100.
+- trip_mask: This is a bit mask that gives the binding relation between
+               this thermal zone and cdev, for a particular trip point.
+               If nth bit is set, then the cdev and thermal zone are bound
+               for trip point n.
+- limits: An array integers consisting of 2-tuples items, and each item means
+  lower and upper state limits, like <min-state max-state>.
+
+**************************
+temperature sensor devices
+**************************
+
+Temperature sensor devices have to be linked to a specific thermal zone.
+This is done by means of the 'monitored-zones' list.
+- monitored-zones: A list of thermal zones phandles, identifying which
+thermal zones the temperature sensor device is used to monitor.
+
+************
+thermal_zone
+************
+
+The thermal_zone node is the node containing all the required info
+for describing a thermal zone, including its cdev bindings. The thermal_zone
+node must contain, apart from its own properties, one node containing
+trip nodes and one node containing all the zone bind parameters.
+
+Required properties:
+- mask: Bit string: If 'n'th bit is set, then trip point 'n' is writeable.
+
+- passive_delay: number of milliseconds to wait between polls when
+  performing passive cooling.
+
+- polling_delay: number of milliseconds to wait between polls when checking.
+
+- #thermal-cells: An integer that is used to specify how many cells compose
+  sensor ids.
+
+Below is an example:
+cpu_thermal: thermal_zone {
+            #thermal-cells = <1>;
+            mask = <0x03>; /* trips writability */
+            passive_delay = <250>; /* milliseconds */
+            polling_delay = <1000>; /* milliseconds */
+            trips {
+                    alert@100000{
+                            temperature = <100000>; /* milliCelsius */
+                            hysteresis = <0>; /* milliCelsius */
+                            type = <THERMAL_TRIP_PASSIVE>;
+                    };
+                    crit@125000{
+                            temperature = <125000>; /* milliCelsius */
+                            hysteresis = <0>; /* milliCelsius */
+                            type = <THERMAL_TRIP_CRITICAL>;
+                    };
+            };
+            bind_params {
+                    action@0{
+                            cooling_device = "thermal-cpufreq";
+                            weight = <100>; /* percentage */
+                            mask = <0x01>;
+			    limits = <
+			      /* lower-state		upper-state */
+				1			THERMAL_NO_LIMITS
+				THERMAL_NO_LIMITS	THERMAL_NO_LIMITS
+			    >;
+                    };
+            };
+};
+
+sensor: adc@0xFFFF {
+	...
+	monitored-zones = <&cpu_thermal 0>;
+};
+
+cpu@0 {
+	...
+	cooling-zones = <&cpu_thermal>;
+};
+
+In the example above, the ADC sensor at address 0xFFFF is used to monitor
+the zone 'cpu_thermal' using its the sensor 0. The cpu@0 device is also linked
+to the same thermal zone 'cpu_thermal' as a cooling device.
+
+***************
+cpufreq-cooling
+***************
+
+The generic cpu cooling (freq clipping) can be loaded by the
+generic cpufreq-cpu0 driver in case the device tree node informs
+this need.
+
+In order to load the cpufreq cooling device, it is possible to
+inform that the cpu needs cooling by adding the list of thermal zones
+in the 'cooling-zones' property at the cpu0 phandle.
+
+Example:
+	cpus {
+		cpu@0 {
+			operating-points = <
+				/* kHz    uV */
+				800000  1313000
+				1008000 1375000
+			>;
+			cooling-zones = <&cpu_thermal>;
+		};
+	...
+	};
+
+The above will cause the cpufreq-cpu0 driver to understand that
+the cpu will need passive cooling and while probing that node it will
+also load the cpufreq cpu cooling device in that system.
+
+However, be advised that this flag will not describe what needs to
+be done or how the cpufreq cooling device will be used. In order to
+accomplish this, one needs to write a phandle for a thermal zone, as
+described in the section 'thermal_zone'.
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index 7fb16bc..753f0dc 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -29,6 +29,19 @@ config THERMAL_HWMON
 	  Say 'Y' here if you want all thermal sensors to
 	  have hwmon sysfs interface too.
 
+config THERMAL_OF
+	bool
+	prompt "APIs to parse thermal data out of device tree"
+	depends on OF
+	default y
+	help
+	  This options provides helpers to add the support to
+	  read and parse thermal data definitions out of the
+	  device tree blob.
+
+	  Say 'Y' here if you need to build thermal infrastructure
+	  based on device tree.
+
 choice
 	prompt "Default Thermal governor"
 	default THERMAL_DEFAULT_GOV_STEP_WISE
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index 24cb894..eedb273 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -7,6 +7,7 @@ thermal_sys-y			+= thermal_core.o
 
 # interface to/from other layers providing sensors
 thermal_sys-$(CONFIG_THERMAL_HWMON)		+= thermal_hwmon.o
+thermal_sys-$(CONFIG_THERMAL_OF)		+= thermal_dt.o
 
 # governors
 thermal_sys-$(CONFIG_THERMAL_GOV_FAIR_SHARE)	+= fair_share.o
diff --git a/drivers/thermal/thermal_dt.c b/drivers/thermal/thermal_dt.c
new file mode 100644
index 0000000..cc35485
--- /dev/null
+++ b/drivers/thermal/thermal_dt.c
@@ -0,0 +1,473 @@
+/*
+ *  thermal_dt.c - Generic Thermal Management device tree support.
+ *
+ *  Copyright (C) 2013 Texas Instruments
+ *  Copyright (C) 2013 Eduardo Valentin <eduardo.valentin@ti.com>
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+#include <linux/thermal.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+#include <linux/err.h>
+#include <linux/export.h>
+#include <linux/string.h>
+
+struct __thermal_bind_params {
+	char cooling_device[THERMAL_NAME_LENGTH];
+};
+
+static
+int thermal_of_match(struct thermal_zone_device *tz,
+		     struct thermal_cooling_device *cdev);
+
+static int thermal_of_populate_bind_params(struct device *dev,
+					   struct device_node *node,
+					   struct __thermal_bind_params *__tbp,
+					   struct thermal_bind_params *tbp,
+					   int ntrips)
+{
+	const char *cdev_name;
+	u32 *limits;
+	int ret;
+	u32 prop;
+
+	ret = of_property_read_u32(node, "weight", &prop);
+	if (ret < 0) {
+		dev_err(dev, "missing weight property\n");
+		return ret;
+	}
+	tbp->weight = prop;
+
+	ret = of_property_read_u32(node, "mask", &prop);
+	if (ret < 0) {
+		dev_err(dev, "missing mask property\n");
+		return ret;
+	}
+	tbp->trip_mask = prop;
+
+	/* this will allow us to bind with cooling devices */
+	tbp->match = thermal_of_match;
+
+	ret = of_property_read_string(node, "cooling_device", &cdev_name);
+	if (ret < 0) {
+		dev_err(dev, "missing cooling_device property\n");
+		return ret;
+	}
+	strncpy(__tbp->cooling_device, cdev_name,
+		sizeof(__tbp->cooling_device));
+
+	limits = kzalloc(ntrips * sizeof(*limits) * 2, GFP_KERNEL);
+	if (!limits) {
+		dev_err(dev, "not enough mem for reading limits\n");
+		return -ENOMEM;
+	}
+	ret = of_property_read_u32_array(node, "limits", limits, 2 * ntrips);
+	if (!ret) {
+		int i = ntrips;
+
+		tbp->binding_limits = devm_kzalloc(dev,
+						   ntrips * 2 *
+						   sizeof(*tbp->binding_limits),
+						   GFP_KERNEL);
+		if (!tbp->binding_limits) {
+			dev_err(dev, "not enough mem for storing limits\n");
+			return -ENOMEM;
+		}
+		while (i--)
+			tbp->binding_limits[i] = limits[i];
+	}
+	kfree(limits);
+
+	return 0;
+}
+
+struct __thermal_trip {
+	unsigned long int temperature;
+	unsigned long int hysteresis;
+	enum thermal_trip_type type;
+};
+
+static
+int thermal_of_populate_trip(struct device *dev,
+			     struct device_node *node,
+			     struct __thermal_trip *trip)
+{
+	int ret;
+	int prop;
+
+	ret = of_property_read_u32(node, "temperature", &prop);
+	if (ret < 0) {
+		dev_err(dev, "missing temperature property\n");
+		return ret;
+	}
+	trip->temperature = prop;
+
+	ret = of_property_read_u32(node, "hysteresis", &prop);
+	if (ret < 0) {
+		dev_err(dev, "missing hysteresis property\n");
+		return ret;
+	}
+	trip->hysteresis = prop;
+
+	ret = of_property_read_u32(node, "type", &prop);
+	if (ret < 0) {
+		dev_err(dev, "missing type property\n");
+		return ret;
+	}
+	trip->type = prop;
+
+	return 0;
+}
+
+struct __thermal_zone_device {
+	enum thermal_device_mode mode;
+	int passive_delay;
+	int polling_delay;
+	int mask;
+	int ntrips;
+	char type[THERMAL_NAME_LENGTH];
+	struct __thermal_trip *trips;
+	struct __thermal_bind_params *bind_params;
+	struct thermal_bind_params *tbps;
+	struct thermal_zone_params zone_params;
+	int (*get_temp)(void *, unsigned long *);
+	void *devdata;
+};
+
+static struct __thermal_zone_device *
+thermal_of_build_thermal_zone(struct device *dev, struct device_node *node)
+{
+	struct device_node *child, *gchild;
+	struct __thermal_zone_device *tz;
+	int ret, i;
+	u32 prop;
+
+	if (!node) {
+		dev_err(dev, "no thermal zone node\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	tz = devm_kzalloc(dev, sizeof(*tz), GFP_KERNEL);
+	if (!tz) {
+		dev_err(dev, "not enough memory for thermal of zone\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	ret = of_property_read_u32(node, "passive_delay", &prop);
+	if (ret < 0) {
+		dev_err(dev, "missing passive_delay property\n");
+		return ERR_PTR(ret);
+	}
+	tz->passive_delay = prop;
+
+	ret = of_property_read_u32(node, "polling_delay", &prop);
+	if (ret < 0) {
+		dev_err(dev, "missing polling_delay property\n");
+		return ERR_PTR(ret);
+	}
+	tz->polling_delay = prop;
+
+	ret = of_property_read_u32(node, "mask", &prop);
+	if (ret < 0) {
+		dev_err(dev, "missing mask property\n");
+		return ERR_PTR(ret);
+	}
+	tz->mask = prop;
+
+	/* assume node name as our zone type */
+	strncpy(tz->type, node->name, sizeof(tz->type));
+
+	/* default policy */
+	strncpy(tz->zone_params.governor_name, "step_wise",
+		sizeof(tz->zone_params.governor_name));
+
+	/* trips */
+	child = of_find_node_by_name(node, "trips");
+
+	/* No trips provided */
+	if (!child)
+		goto finish;
+
+	tz->ntrips = of_get_child_count(child);
+	tz->trips = devm_kzalloc(dev, tz->ntrips * sizeof(*tz->trips),
+				 GFP_KERNEL);
+	if (!tz->trips)
+		return ERR_PTR(-ENOMEM);
+	i = 0;
+	for_each_child_of_node(child, gchild)
+		thermal_of_populate_trip(dev, gchild, &tz->trips[i++]);
+
+	/* bind_params */
+	child = of_find_node_by_name(node, "bind_params");
+
+	/* No binding info */
+	if (!child)
+		goto finish;
+
+	tz->zone_params.num_tbps = of_get_child_count(child);
+	tz->bind_params = devm_kzalloc(dev,
+				       tz->zone_params.num_tbps *
+						sizeof(*tz->bind_params),
+				       GFP_KERNEL);
+	if (!tz->bind_params)
+		return ERR_PTR(-ENOMEM);
+	tz->zone_params.tbp = devm_kzalloc(dev,
+					   tz->zone_params.num_tbps *
+						sizeof(*tz->zone_params.tbp),
+					   GFP_KERNEL);
+	if (!tz->zone_params.tbp)
+		return ERR_PTR(-ENOMEM);
+	i = 0;
+	for_each_child_of_node(child, gchild) {
+		thermal_of_populate_bind_params(dev, gchild,
+						&tz->bind_params[i],
+						&tz->zone_params.tbp[i],
+						tz->ntrips);
+		i++;
+	}
+
+finish:
+	tz->mode = THERMAL_DEVICE_ENABLED;
+
+	return tz;
+}
+
+static
+int thermal_of_match(struct thermal_zone_device *tz,
+		     struct thermal_cooling_device *cdev)
+{
+	struct __thermal_zone_device *data = tz->devdata;
+	int i;
+
+	for (i = 0; i < data->zone_params.num_tbps; i++) {
+		if (!strncmp(data->bind_params[i].cooling_device,
+			     cdev->type,
+			     strlen(data->bind_params[i].cooling_device)) &&
+		    (data->zone_params.tbp[i].trip_mask & (1 << i)))
+			return 0;
+	}
+
+	return -EINVAL;
+}
+
+static
+int of_thermal_get_temp(struct thermal_zone_device *tz,
+			unsigned long *temp)
+{
+	struct __thermal_zone_device *data = tz->devdata;
+
+	return data->get_temp(data->devdata, temp);
+}
+
+static
+int of_thermal_get_mode(struct thermal_zone_device *tz,
+			enum thermal_device_mode *mode)
+{
+	struct __thermal_zone_device *data = tz->devdata;
+
+	*mode = data->mode;
+
+	return 0;
+}
+
+static
+int of_thermal_set_mode(struct thermal_zone_device *tz,
+			enum thermal_device_mode mode)
+{
+	struct __thermal_zone_device *data = tz->devdata;
+
+	mutex_lock(&tz->lock);
+
+	if (mode = THERMAL_DEVICE_ENABLED)
+		tz->polling_delay = data->polling_delay;
+	else
+		tz->polling_delay = 0;
+
+	mutex_unlock(&tz->lock);
+
+	data->mode = mode;
+	thermal_zone_device_update(tz);
+
+	return 0;
+}
+
+static
+int of_thermal_get_trip_type(struct thermal_zone_device *tz, int trip,
+			     enum thermal_trip_type *type)
+{
+	struct __thermal_zone_device *data = tz->devdata;
+
+	if (trip >= data->ntrips || trip < 0)
+		return -EDOM;
+
+	*type = data->trips[trip].type;
+
+	return 0;
+}
+
+static
+int of_thermal_get_trip_temp(struct thermal_zone_device *tz, int trip,
+			     unsigned long *temp)
+{
+	struct __thermal_zone_device *data = tz->devdata;
+
+	if (trip >= data->ntrips || trip < 0)
+		return -EDOM;
+
+	*temp = data->trips[trip].temperature;
+
+	return 0;
+}
+
+static
+int of_thermal_set_trip_temp(struct thermal_zone_device *tz, int trip,
+			     unsigned long temp)
+{
+	struct __thermal_zone_device *data = tz->devdata;
+
+	if (trip >= data->ntrips || trip < 0)
+		return -EDOM;
+
+	/* thermal fw should take care of data->mask & (1 << trip) */
+	data->trips[trip].temperature = temp;
+
+	return 0;
+}
+
+static
+int of_thermal_get_trip_hyst(struct thermal_zone_device *tz, int trip,
+			     unsigned long *hyst)
+{
+	struct __thermal_zone_device *data = tz->devdata;
+
+	if (trip >= data->ntrips || trip < 0)
+		return -EDOM;
+
+	*hyst = data->trips[trip].hysteresis;
+
+	return 0;
+}
+
+static
+int of_thermal_set_trip_hyst(struct thermal_zone_device *tz, int trip,
+			     unsigned long hyst)
+{
+	struct __thermal_zone_device *data = tz->devdata;
+
+	if (trip >= data->ntrips || trip < 0)
+		return -EDOM;
+
+	/* thermal fw should take care of data->mask & (1 << trip) */
+	data->trips[trip].hysteresis = hyst;
+
+	return 0;
+}
+
+static int
+of_thermal_get_crit_temp(struct thermal_zone_device *tz, unsigned long *temp)
+{
+	struct __thermal_zone_device *data = tz->devdata;
+	int i;
+
+	for (i = 0; i < data->ntrips; i++)
+		if (data->trips[i].type = THERMAL_TRIP_CRITICAL) {
+			*temp = data->trips[i].temperature;
+			return 0;
+		}
+
+	return -EINVAL;
+}
+
+static const
+struct thermal_zone_device_ops of_thermal_ops = {
+	.get_temp = of_thermal_get_temp,
+	.get_mode = of_thermal_get_mode,
+	.set_mode = of_thermal_set_mode,
+	.get_trip_type = of_thermal_get_trip_type,
+	.get_trip_temp = of_thermal_get_trip_temp,
+	.set_trip_temp = of_thermal_set_trip_temp,
+	.get_trip_hyst = of_thermal_get_trip_hyst,
+	.set_trip_hyst = of_thermal_set_trip_hyst,
+	.get_crit_temp = of_thermal_get_crit_temp,
+};
+
+/**
+ * thermal_zone_of_device_register() - registers a thermal zone based on DT
+ * @device: a valid struct device pointer containing device tree node
+ *          with thermal_zone descriptor.
+ * @data: a private pointer (owned by the caller) that will be passed
+ *        back, when a temperature reading is needed.
+ * @get_temp: a pointer to a function that returns the thermal zone
+ *            temperature.
+ * @add_hwmon:	a boolean to indicate if the thermal to hwmon sysfs interface
+ *		is required. When add_hwmon = true, a hwmon sysfs interface
+ *		will be created. When add_hwmon = false, nothing will be done
+ *
+ * This function will parse the device tree node associated with the
+ * @dev struct and will attempt to build a thermal zone device based
+ * upon the thermal data provided and described by DT.
+ *
+ * The thermal zone temperature is provided by the @get_temp function
+ * pointer. When called, it will have the private pointer @data back.
+ *
+ * Return: On success returns a valid struct thermal_zone_device,
+ * otherwise, it returns a corresponding ERR_PTR(). Caller must
+ * check the return value with help of IS_ERR() helper.
+ */
+struct thermal_zone_device *
+thermal_zone_of_device_register(struct device *dev, int id, bool add_hwmon,
+			void *data, int (*get_temp)(void *, unsigned long *))
+{
+	struct __thermal_zone_device *tz;
+	struct thermal_zone_device_ops *ops;
+	struct of_phandle_args thermal_spec;
+	int ret;
+
+	ret = of_parse_phandle_with_args(dev->of_node,
+					 "monitored-zones",
+					 "#thermal-cells",
+					 id,
+					 &thermal_spec);
+	if (ret) {
+		dev_err(dev, "unable to find desired monitored zone %d\n", id);
+		return ERR_PTR(ret);
+	}
+
+	tz = thermal_of_build_thermal_zone(dev, thermal_spec.np);
+	if (IS_ERR(tz)) {
+		dev_err(dev, "failed to build thermal zone\n");
+		return ERR_CAST(tz);
+	}
+	ops = devm_kzalloc(dev, sizeof(*ops), GFP_KERNEL);
+	if (!ops) {
+		dev_err(dev, "no memory available for thermal ops\n");
+		return ERR_PTR(-ENOMEM);
+	}
+	memcpy(ops, &of_thermal_ops, sizeof(*ops));
+	tz->get_temp = get_temp;
+	tz->devdata = data;
+
+	return thermal_zone_device_register(tz->type, tz->ntrips, tz->mask, tz,
+					    ops, &tz->zone_params,
+					    tz->passive_delay,
+					    tz->polling_delay,
+					    add_hwmon);
+}
+EXPORT_SYMBOL_GPL(thermal_zone_of_device_register);
diff --git a/include/dt-bindings/thermal/thermal.h b/include/dt-bindings/thermal/thermal.h
new file mode 100644
index 0000000..6dd6ccd
--- /dev/null
+++ b/include/dt-bindings/thermal/thermal.h
@@ -0,0 +1,27 @@
+/*
+ * This header provides constants for most thermal bindings.
+ *
+ * Copyright (C) 2013 Texas Instruments
+ *	Eduardo Valentin <eduardo.valentin@ti.com>
+ *
+ * GPLv2 only
+ */
+
+#ifndef _DT_BINDINGS_THERMAL_THERMAL_H
+#define _DT_BINDINGS_THERMAL_THERMAL_H
+
+/*
+ * Here are the thermal trip types. This must
+ * match with enum thermal_trip_type at
+ * include/linux/thermal.h
+ */
+#define THERMAL_TRIP_ACTIVE		0
+#define THERMAL_TRIP_PASSIVE		1
+#define THERMAL_TRIP_HOT		2
+#define THERMAL_TRIP_CRITICAL		3
+
+/* On cooling devices upper and lower limits */
+#define THERMAL_NO_LIMIT		(-1UL)
+
+#endif
+
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index 7c2769c..501b2fe 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -234,6 +234,9 @@ struct thermal_genl_event {
 };
 
 /* Function declarations */
+struct thermal_zone_device
+*thermal_zone_of_device_register(struct device *, int id, bool add_hwmon,
+	void *data, int (*get_temp) (void *, unsigned long *));
 struct thermal_zone_device *thermal_zone_device_register(const char *, int, int,
 		void *, const struct thermal_zone_device_ops *,
 		const struct thermal_zone_params *, int, int, bool);
-- 
1.8.2.1.342.gfa7285d


_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

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

* [RFC PATCH 03/14] hwmon: lm75: expose to thermal fw via DT nodes
  2013-08-23 23:15 ` Eduardo Valentin
  (?)
@ 2013-08-23 23:15   ` Eduardo Valentin
  -1 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-23 23:15 UTC (permalink / raw)
  To: swarren, pawel.moll, mark.rutland, ian.campbell, grant.likely,
	rob.herring, linux, rui.zhang, wni
  Cc: durgadoss.r, linux-pm, devicetree, lm-sensors, linux-kernel,
	Eduardo Valentin, Jean Delvare

This patch adds to lm75 temperature sensor the possibility
to expose itself as thermal zone device, registered on the
thermal framework.

The thermal zone is built only if a device tree node
describing a thermal zone for this sensor is present
inside the lm75 DT node. Otherwise, the driver behavior
will be the same.

Cc: Jean Delvare <khali@linux-fr.org>
Cc: Guenter Roeck <linux@roeck-us.net>
Cc: lm-sensors@lm-sensors.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
---
 drivers/hwmon/lm75.c | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c
index c03b490..dc55908 100644
--- a/drivers/hwmon/lm75.c
+++ b/drivers/hwmon/lm75.c
@@ -27,6 +27,8 @@
 #include <linux/hwmon-sysfs.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
+#include <linux/thermal.h>
+#include <linux/of.h>
 #include "lm75.h"
 
 
@@ -70,6 +72,7 @@ static const u8 LM75_REG_TEMP[3] = {
 /* Each client has this additional data */
 struct lm75_data {
 	struct device		*hwmon_dev;
+	struct thermal_zone_device	*tz;
 	struct mutex		update_lock;
 	u8			orig_conf;
 	u8			resolution;	/* In bits, between 9 and 12 */
@@ -92,6 +95,19 @@ static struct lm75_data *lm75_update_device(struct device *dev);
 
 /* sysfs attributes for hwmon */
 
+static int lm75_read_temp(void *dev, unsigned long *temp)
+{
+	struct lm75_data *data = lm75_update_device(dev);
+
+	if (IS_ERR(data))
+		return PTR_ERR(data);
+
+	*temp = ((data->temp[0] >> (16 - data->resolution)) * 1000) >>
+			(data->resolution - 8);
+
+	return 0;
+}
+
 static ssize_t show_temp(struct device *dev, struct device_attribute *da,
 			 char *buf)
 {
@@ -271,11 +287,25 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id)
 		goto exit_remove;
 	}
 
+	if (of_find_property(client->dev.of_node, "monitored-zones", NULL)) {
+		data->tz = thermal_zone_of_device_register(&client->dev,
+							   0,
+							   false, /* -hwmon */
+							   &client->dev,
+							   lm75_read_temp);
+		if (IS_ERR(data->tz)) {
+			status = PTR_ERR(data->tz);
+			goto exit_hwmon;
+		}
+	}
+
 	dev_info(&client->dev, "%s: sensor '%s'\n",
 		 dev_name(data->hwmon_dev), client->name);
 
 	return 0;
 
+exit_hwmon:
+	hwmon_device_unregister(data->hwmon_dev);
 exit_remove:
 	sysfs_remove_group(&client->dev.kobj, &lm75_group);
 	return status;
@@ -285,6 +315,7 @@ static int lm75_remove(struct i2c_client *client)
 {
 	struct lm75_data *data = i2c_get_clientdata(client);
 
+	thermal_zone_device_unregister(data->tz);
 	hwmon_device_unregister(data->hwmon_dev);
 	sysfs_remove_group(&client->dev.kobj, &lm75_group);
 	lm75_write_value(client, LM75_REG_CONF, data->orig_conf);
-- 
1.8.2.1.342.gfa7285d


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

* [RFC PATCH 03/14] hwmon: lm75: expose to thermal fw via DT nodes
@ 2013-08-23 23:15   ` Eduardo Valentin
  0 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-23 23:15 UTC (permalink / raw)
  To: swarren, pawel.moll, mark.rutland, ian.campbell, grant.likely,
	rob.herring, linux, rui.zhang, wni
  Cc: durgadoss.r, linux-pm, devicetree, lm-sensors, linux-kernel,
	Eduardo Valentin, Jean Delvare

This patch adds to lm75 temperature sensor the possibility
to expose itself as thermal zone device, registered on the
thermal framework.

The thermal zone is built only if a device tree node
describing a thermal zone for this sensor is present
inside the lm75 DT node. Otherwise, the driver behavior
will be the same.

Cc: Jean Delvare <khali@linux-fr.org>
Cc: Guenter Roeck <linux@roeck-us.net>
Cc: lm-sensors@lm-sensors.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
---
 drivers/hwmon/lm75.c | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c
index c03b490..dc55908 100644
--- a/drivers/hwmon/lm75.c
+++ b/drivers/hwmon/lm75.c
@@ -27,6 +27,8 @@
 #include <linux/hwmon-sysfs.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
+#include <linux/thermal.h>
+#include <linux/of.h>
 #include "lm75.h"
 
 
@@ -70,6 +72,7 @@ static const u8 LM75_REG_TEMP[3] = {
 /* Each client has this additional data */
 struct lm75_data {
 	struct device		*hwmon_dev;
+	struct thermal_zone_device	*tz;
 	struct mutex		update_lock;
 	u8			orig_conf;
 	u8			resolution;	/* In bits, between 9 and 12 */
@@ -92,6 +95,19 @@ static struct lm75_data *lm75_update_device(struct device *dev);
 
 /* sysfs attributes for hwmon */
 
+static int lm75_read_temp(void *dev, unsigned long *temp)
+{
+	struct lm75_data *data = lm75_update_device(dev);
+
+	if (IS_ERR(data))
+		return PTR_ERR(data);
+
+	*temp = ((data->temp[0] >> (16 - data->resolution)) * 1000) >>
+			(data->resolution - 8);
+
+	return 0;
+}
+
 static ssize_t show_temp(struct device *dev, struct device_attribute *da,
 			 char *buf)
 {
@@ -271,11 +287,25 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id)
 		goto exit_remove;
 	}
 
+	if (of_find_property(client->dev.of_node, "monitored-zones", NULL)) {
+		data->tz = thermal_zone_of_device_register(&client->dev,
+							   0,
+							   false, /* -hwmon */
+							   &client->dev,
+							   lm75_read_temp);
+		if (IS_ERR(data->tz)) {
+			status = PTR_ERR(data->tz);
+			goto exit_hwmon;
+		}
+	}
+
 	dev_info(&client->dev, "%s: sensor '%s'\n",
 		 dev_name(data->hwmon_dev), client->name);
 
 	return 0;
 
+exit_hwmon:
+	hwmon_device_unregister(data->hwmon_dev);
 exit_remove:
 	sysfs_remove_group(&client->dev.kobj, &lm75_group);
 	return status;
@@ -285,6 +315,7 @@ static int lm75_remove(struct i2c_client *client)
 {
 	struct lm75_data *data = i2c_get_clientdata(client);
 
+	thermal_zone_device_unregister(data->tz);
 	hwmon_device_unregister(data->hwmon_dev);
 	sysfs_remove_group(&client->dev.kobj, &lm75_group);
 	lm75_write_value(client, LM75_REG_CONF, data->orig_conf);
-- 
1.8.2.1.342.gfa7285d


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

* [lm-sensors] [RFC PATCH 03/14] hwmon: lm75: expose to thermal fw via DT nodes
@ 2013-08-23 23:15   ` Eduardo Valentin
  0 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-23 23:15 UTC (permalink / raw)
  To: swarren, pawel.moll, mark.rutland, ian.campbell, grant.likely,
	rob.herring, linux, rui.zhang, wni
  Cc: durgadoss.r, linux-pm, devicetree, lm-sensors, linux-kernel,
	Eduardo Valentin, Jean Delvare

This patch adds to lm75 temperature sensor the possibility
to expose itself as thermal zone device, registered on the
thermal framework.

The thermal zone is built only if a device tree node
describing a thermal zone for this sensor is present
inside the lm75 DT node. Otherwise, the driver behavior
will be the same.

Cc: Jean Delvare <khali@linux-fr.org>
Cc: Guenter Roeck <linux@roeck-us.net>
Cc: lm-sensors@lm-sensors.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
---
 drivers/hwmon/lm75.c | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c
index c03b490..dc55908 100644
--- a/drivers/hwmon/lm75.c
+++ b/drivers/hwmon/lm75.c
@@ -27,6 +27,8 @@
 #include <linux/hwmon-sysfs.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
+#include <linux/thermal.h>
+#include <linux/of.h>
 #include "lm75.h"
 
 
@@ -70,6 +72,7 @@ static const u8 LM75_REG_TEMP[3] = {
 /* Each client has this additional data */
 struct lm75_data {
 	struct device		*hwmon_dev;
+	struct thermal_zone_device	*tz;
 	struct mutex		update_lock;
 	u8			orig_conf;
 	u8			resolution;	/* In bits, between 9 and 12 */
@@ -92,6 +95,19 @@ static struct lm75_data *lm75_update_device(struct device *dev);
 
 /* sysfs attributes for hwmon */
 
+static int lm75_read_temp(void *dev, unsigned long *temp)
+{
+	struct lm75_data *data = lm75_update_device(dev);
+
+	if (IS_ERR(data))
+		return PTR_ERR(data);
+
+	*temp = ((data->temp[0] >> (16 - data->resolution)) * 1000) >>
+			(data->resolution - 8);
+
+	return 0;
+}
+
 static ssize_t show_temp(struct device *dev, struct device_attribute *da,
 			 char *buf)
 {
@@ -271,11 +287,25 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id)
 		goto exit_remove;
 	}
 
+	if (of_find_property(client->dev.of_node, "monitored-zones", NULL)) {
+		data->tz = thermal_zone_of_device_register(&client->dev,
+							   0,
+							   false, /* -hwmon */
+							   &client->dev,
+							   lm75_read_temp);
+		if (IS_ERR(data->tz)) {
+			status = PTR_ERR(data->tz);
+			goto exit_hwmon;
+		}
+	}
+
 	dev_info(&client->dev, "%s: sensor '%s'\n",
 		 dev_name(data->hwmon_dev), client->name);
 
 	return 0;
 
+exit_hwmon:
+	hwmon_device_unregister(data->hwmon_dev);
 exit_remove:
 	sysfs_remove_group(&client->dev.kobj, &lm75_group);
 	return status;
@@ -285,6 +315,7 @@ static int lm75_remove(struct i2c_client *client)
 {
 	struct lm75_data *data = i2c_get_clientdata(client);
 
+	thermal_zone_device_unregister(data->tz);
 	hwmon_device_unregister(data->hwmon_dev);
 	sysfs_remove_group(&client->dev.kobj, &lm75_group);
 	lm75_write_value(client, LM75_REG_CONF, data->orig_conf);
-- 
1.8.2.1.342.gfa7285d


_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

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

* [RFC PATCH 04/14] hwmon: tmp102: expose to thermal fw via DT nodes
  2013-08-23 23:15 ` Eduardo Valentin
  (?)
@ 2013-08-23 23:15   ` Eduardo Valentin
  -1 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-23 23:15 UTC (permalink / raw)
  To: swarren, pawel.moll, mark.rutland, ian.campbell, grant.likely,
	rob.herring, linux, rui.zhang, wni
  Cc: durgadoss.r, linux-pm, devicetree, lm-sensors, linux-kernel,
	Eduardo Valentin, Jean Delvare

This patch adds to tmp102 temperature sensor the possibility
to expose itself as thermal zone device, registered on the
thermal framework.

The thermal zone is built only if a device tree node
describing a thermal zone for this sensor is present
inside the tmp102 DT node. Otherwise, the driver behavior
will be the same.

Cc: Jean Delvare <khali@linux-fr.org>
Cc: Guenter Roeck <linux@roeck-us.net>
Cc: lm-sensors@lm-sensors.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
---
 drivers/hwmon/tmp102.c | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/drivers/hwmon/tmp102.c b/drivers/hwmon/tmp102.c
index d7b47ab..0f1e44a 100644
--- a/drivers/hwmon/tmp102.c
+++ b/drivers/hwmon/tmp102.c
@@ -27,6 +27,8 @@
 #include <linux/mutex.h>
 #include <linux/device.h>
 #include <linux/jiffies.h>
+#include <linux/thermal.h>
+#include <linux/of.h>
 
 #define	DRIVER_NAME "tmp102"
 
@@ -50,6 +52,7 @@
 
 struct tmp102 {
 	struct device *hwmon_dev;
+	struct thermal_zone_device *tz;
 	struct mutex lock;
 	u16 config_orig;
 	unsigned long last_update;
@@ -93,6 +96,15 @@ static struct tmp102 *tmp102_update_device(struct i2c_client *client)
 	return tmp102;
 }
 
+static int tmp102_read_temp(void *dev, unsigned long *temp)
+{
+	struct tmp102 *tmp102 = tmp102_update_device(to_i2c_client(dev));
+
+	*temp = tmp102->temp[0];
+
+	return 0;
+}
+
 static ssize_t tmp102_show_temp(struct device *dev,
 				struct device_attribute *attr,
 				char *buf)
@@ -204,10 +216,23 @@ static int tmp102_probe(struct i2c_client *client,
 		goto fail_remove_sysfs;
 	}
 
+	if (of_find_property(client->dev.of_node, "monitored-zones", NULL)) {
+		tmp102->tz = thermal_zone_of_device_register(&client->dev, 0,
+							     false, /* -hwmon */
+							     &client->dev,
+							     tmp102_read_temp);
+		if (IS_ERR(tmp102->tz)) {
+			status = PTR_ERR(tmp102->tz);
+			goto exit_hwmon;
+		}
+	}
+
 	dev_info(&client->dev, "initialized\n");
 
 	return 0;
 
+exit_hwmon:
+	hwmon_device_unregister(tmp102->hwmon_dev);
 fail_remove_sysfs:
 	sysfs_remove_group(&client->dev.kobj, &tmp102_attr_group);
 fail_restore_config:
@@ -220,6 +245,7 @@ static int tmp102_remove(struct i2c_client *client)
 {
 	struct tmp102 *tmp102 = i2c_get_clientdata(client);
 
+	thermal_zone_device_unregister(tmp102->tz);
 	hwmon_device_unregister(tmp102->hwmon_dev);
 	sysfs_remove_group(&client->dev.kobj, &tmp102_attr_group);
 
-- 
1.8.2.1.342.gfa7285d


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

* [RFC PATCH 04/14] hwmon: tmp102: expose to thermal fw via DT nodes
@ 2013-08-23 23:15   ` Eduardo Valentin
  0 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-23 23:15 UTC (permalink / raw)
  To: swarren, pawel.moll, mark.rutland, ian.campbell, grant.likely,
	rob.herring, linux, rui.zhang, wni
  Cc: durgadoss.r, linux-pm, devicetree, lm-sensors, linux-kernel,
	Eduardo Valentin, Jean Delvare

This patch adds to tmp102 temperature sensor the possibility
to expose itself as thermal zone device, registered on the
thermal framework.

The thermal zone is built only if a device tree node
describing a thermal zone for this sensor is present
inside the tmp102 DT node. Otherwise, the driver behavior
will be the same.

Cc: Jean Delvare <khali@linux-fr.org>
Cc: Guenter Roeck <linux@roeck-us.net>
Cc: lm-sensors@lm-sensors.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
---
 drivers/hwmon/tmp102.c | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/drivers/hwmon/tmp102.c b/drivers/hwmon/tmp102.c
index d7b47ab..0f1e44a 100644
--- a/drivers/hwmon/tmp102.c
+++ b/drivers/hwmon/tmp102.c
@@ -27,6 +27,8 @@
 #include <linux/mutex.h>
 #include <linux/device.h>
 #include <linux/jiffies.h>
+#include <linux/thermal.h>
+#include <linux/of.h>
 
 #define	DRIVER_NAME "tmp102"
 
@@ -50,6 +52,7 @@
 
 struct tmp102 {
 	struct device *hwmon_dev;
+	struct thermal_zone_device *tz;
 	struct mutex lock;
 	u16 config_orig;
 	unsigned long last_update;
@@ -93,6 +96,15 @@ static struct tmp102 *tmp102_update_device(struct i2c_client *client)
 	return tmp102;
 }
 
+static int tmp102_read_temp(void *dev, unsigned long *temp)
+{
+	struct tmp102 *tmp102 = tmp102_update_device(to_i2c_client(dev));
+
+	*temp = tmp102->temp[0];
+
+	return 0;
+}
+
 static ssize_t tmp102_show_temp(struct device *dev,
 				struct device_attribute *attr,
 				char *buf)
@@ -204,10 +216,23 @@ static int tmp102_probe(struct i2c_client *client,
 		goto fail_remove_sysfs;
 	}
 
+	if (of_find_property(client->dev.of_node, "monitored-zones", NULL)) {
+		tmp102->tz = thermal_zone_of_device_register(&client->dev, 0,
+							     false, /* -hwmon */
+							     &client->dev,
+							     tmp102_read_temp);
+		if (IS_ERR(tmp102->tz)) {
+			status = PTR_ERR(tmp102->tz);
+			goto exit_hwmon;
+		}
+	}
+
 	dev_info(&client->dev, "initialized\n");
 
 	return 0;
 
+exit_hwmon:
+	hwmon_device_unregister(tmp102->hwmon_dev);
 fail_remove_sysfs:
 	sysfs_remove_group(&client->dev.kobj, &tmp102_attr_group);
 fail_restore_config:
@@ -220,6 +245,7 @@ static int tmp102_remove(struct i2c_client *client)
 {
 	struct tmp102 *tmp102 = i2c_get_clientdata(client);
 
+	thermal_zone_device_unregister(tmp102->tz);
 	hwmon_device_unregister(tmp102->hwmon_dev);
 	sysfs_remove_group(&client->dev.kobj, &tmp102_attr_group);
 
-- 
1.8.2.1.342.gfa7285d


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

* [lm-sensors] [RFC PATCH 04/14] hwmon: tmp102: expose to thermal fw via DT nodes
@ 2013-08-23 23:15   ` Eduardo Valentin
  0 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-23 23:15 UTC (permalink / raw)
  To: swarren, pawel.moll, mark.rutland, ian.campbell, grant.likely,
	rob.herring, linux, rui.zhang, wni
  Cc: durgadoss.r, linux-pm, devicetree, lm-sensors, linux-kernel,
	Eduardo Valentin, Jean Delvare

This patch adds to tmp102 temperature sensor the possibility
to expose itself as thermal zone device, registered on the
thermal framework.

The thermal zone is built only if a device tree node
describing a thermal zone for this sensor is present
inside the tmp102 DT node. Otherwise, the driver behavior
will be the same.

Cc: Jean Delvare <khali@linux-fr.org>
Cc: Guenter Roeck <linux@roeck-us.net>
Cc: lm-sensors@lm-sensors.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
---
 drivers/hwmon/tmp102.c | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/drivers/hwmon/tmp102.c b/drivers/hwmon/tmp102.c
index d7b47ab..0f1e44a 100644
--- a/drivers/hwmon/tmp102.c
+++ b/drivers/hwmon/tmp102.c
@@ -27,6 +27,8 @@
 #include <linux/mutex.h>
 #include <linux/device.h>
 #include <linux/jiffies.h>
+#include <linux/thermal.h>
+#include <linux/of.h>
 
 #define	DRIVER_NAME "tmp102"
 
@@ -50,6 +52,7 @@
 
 struct tmp102 {
 	struct device *hwmon_dev;
+	struct thermal_zone_device *tz;
 	struct mutex lock;
 	u16 config_orig;
 	unsigned long last_update;
@@ -93,6 +96,15 @@ static struct tmp102 *tmp102_update_device(struct i2c_client *client)
 	return tmp102;
 }
 
+static int tmp102_read_temp(void *dev, unsigned long *temp)
+{
+	struct tmp102 *tmp102 = tmp102_update_device(to_i2c_client(dev));
+
+	*temp = tmp102->temp[0];
+
+	return 0;
+}
+
 static ssize_t tmp102_show_temp(struct device *dev,
 				struct device_attribute *attr,
 				char *buf)
@@ -204,10 +216,23 @@ static int tmp102_probe(struct i2c_client *client,
 		goto fail_remove_sysfs;
 	}
 
+	if (of_find_property(client->dev.of_node, "monitored-zones", NULL)) {
+		tmp102->tz = thermal_zone_of_device_register(&client->dev, 0,
+							     false, /* -hwmon */
+							     &client->dev,
+							     tmp102_read_temp);
+		if (IS_ERR(tmp102->tz)) {
+			status = PTR_ERR(tmp102->tz);
+			goto exit_hwmon;
+		}
+	}
+
 	dev_info(&client->dev, "initialized\n");
 
 	return 0;
 
+exit_hwmon:
+	hwmon_device_unregister(tmp102->hwmon_dev);
 fail_remove_sysfs:
 	sysfs_remove_group(&client->dev.kobj, &tmp102_attr_group);
 fail_restore_config:
@@ -220,6 +245,7 @@ static int tmp102_remove(struct i2c_client *client)
 {
 	struct tmp102 *tmp102 = i2c_get_clientdata(client);
 
+	thermal_zone_device_unregister(tmp102->tz);
 	hwmon_device_unregister(tmp102->hwmon_dev);
 	sysfs_remove_group(&client->dev.kobj, &tmp102_attr_group);
 
-- 
1.8.2.1.342.gfa7285d


_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

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

* [RFC PATCH 05/14] thermal: ti-soc-thermal: use thermal DT infrastructure
  2013-08-23 23:15 ` Eduardo Valentin
  (?)
@ 2013-08-23 23:15   ` Eduardo Valentin
  -1 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-23 23:15 UTC (permalink / raw)
  To: swarren, pawel.moll, mark.rutland, ian.campbell, grant.likely,
	rob.herring, linux, rui.zhang, wni
  Cc: durgadoss.r, linux-pm, devicetree, lm-sensors, linux-kernel,
	Eduardo Valentin

This patch improves the ti-soc-thermal driver by adding the
support to build the thermal zones based on DT nodes.

The driver will have two options now to build the thermal
zones. The first option is the zones originally coded
in this driver. So, the driver behavior will be same
if there is no DT node describing the zones. The second
option, when it is found a DT node with thermal data,
will used the common infrastructure to build the thermal
zone and bind its cooling devices.

In case the driver loads thermal data using the legacy
mode, this driver still adds to the system
a cpufreq cooling device. Loading the thermal data from
DT, the driver assumes someone else will add the cpufreq
cooling device, like the cpufreq driver.

Cc: Zhang Rui <rui.zhang@intel.com>
Cc: linux-pm@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
---
 drivers/thermal/ti-soc-thermal/ti-thermal-common.c | 52 +++++++++++++++++-----
 1 file changed, 41 insertions(+), 11 deletions(-)

diff --git a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
index 5ab613a..6aac72c 100644
--- a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
+++ b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
@@ -31,6 +31,7 @@
 #include <linux/cpufreq.h>
 #include <linux/cpumask.h>
 #include <linux/cpu_cooling.h>
+#include <linux/of.h>
 
 #include "ti-thermal.h"
 #include "ti-bandgap.h"
@@ -75,11 +76,10 @@ static inline int ti_thermal_hotspot_temperature(int t, int s, int c)
 
 /* thermal zone ops */
 /* Get temperature callback function for thermal zone*/
-static inline int ti_thermal_get_temp(struct thermal_zone_device *thermal,
-				      unsigned long *temp)
+static inline int __ti_thermal_get_temp(void *devdata, unsigned long *temp)
 {
 	struct thermal_zone_device *pcb_tz = NULL;
-	struct ti_thermal_data *data = thermal->devdata;
+	struct ti_thermal_data *data = devdata;
 	struct ti_bandgap *bgp;
 	const struct ti_temp_sensor *s;
 	int ret, tmp, slope, constant;
@@ -117,6 +117,14 @@ static inline int ti_thermal_get_temp(struct thermal_zone_device *thermal,
 	return ret;
 }
 
+static inline int ti_thermal_get_temp(struct thermal_zone_device *thermal,
+				      unsigned long *temp)
+{
+	struct ti_thermal_data *data = thermal->devdata;
+
+	return __ti_thermal_get_temp(data, temp);
+}
+
 /* Bind callback functions for thermal zone */
 static int ti_thermal_bind(struct thermal_zone_device *thermal,
 			   struct thermal_cooling_device *cdev)
@@ -293,6 +301,7 @@ int ti_thermal_expose_sensor(struct ti_bandgap *bgp, int id,
 			     char *domain)
 {
 	struct ti_thermal_data *data;
+	struct device_node *np;
 
 	data = ti_bandgap_get_sensor_data(bgp, id);
 
@@ -302,16 +311,23 @@ int ti_thermal_expose_sensor(struct ti_bandgap *bgp, int id,
 	if (!data)
 		return -EINVAL;
 
-	/* Create thermal zone */
-	data->ti_thermal = thermal_zone_device_register(domain,
+	/* in case this is specified by DT */
+	np = bgp->dev->of_node;
+	data->ti_thermal = thermal_zone_of_device_register(bgp->dev, id,
+					true, /* +hwmon */
+					data, __ti_thermal_get_temp);
+	if (IS_ERR(data->ti_thermal)) {
+		/* Create thermal zone */
+		data->ti_thermal = thermal_zone_device_register(domain,
 				OMAP_TRIP_NUMBER, 0, data, &ti_thermal_ops,
 				NULL, FAST_TEMP_MONITORING_RATE,
 				FAST_TEMP_MONITORING_RATE, true);
-	if (IS_ERR(data->ti_thermal)) {
-		dev_err(bgp->dev, "thermal zone device is NULL\n");
-		return PTR_ERR(data->ti_thermal);
+		if (IS_ERR(data->ti_thermal)) {
+			dev_err(bgp->dev, "thermal zone device is NULL\n");
+			return PTR_ERR(data->ti_thermal);
+		}
+		data->ti_thermal->polling_delay = FAST_TEMP_MONITORING_RATE;
 	}
-	data->ti_thermal->polling_delay = FAST_TEMP_MONITORING_RATE;
 	ti_bandgap_set_sensor_data(bgp, id, data);
 
 	return 0;
@@ -323,7 +339,8 @@ int ti_thermal_remove_sensor(struct ti_bandgap *bgp, int id)
 
 	data = ti_bandgap_get_sensor_data(bgp, id);
 
-	thermal_zone_device_unregister(data->ti_thermal);
+	if (data && data->ti_thermal)
+		thermal_zone_device_unregister(data->ti_thermal);
 
 	return 0;
 }
@@ -342,6 +359,17 @@ int ti_thermal_report_sensor_temperature(struct ti_bandgap *bgp, int id)
 int ti_thermal_register_cpu_cooling(struct ti_bandgap *bgp, int id)
 {
 	struct ti_thermal_data *data;
+	struct device_node *np = bgp->dev->of_node;
+
+	/*
+	 * We are assuming here that if one deploys the zone
+	 * using DT, then it must be aware that the cooling device
+	 * loading has to happen via cpufreq driver.
+	 */
+	if (of_find_property(np, "monitored-zones", NULL)) {
+		of_node_put(np);
+		return 0;
+	}
 
 	data = ti_bandgap_get_sensor_data(bgp, id);
 	if (!data || IS_ERR(data))
@@ -372,7 +400,9 @@ int ti_thermal_unregister_cpu_cooling(struct ti_bandgap *bgp, int id)
 	struct ti_thermal_data *data;
 
 	data = ti_bandgap_get_sensor_data(bgp, id);
-	cpufreq_cooling_unregister(data->cool_dev);
+
+	if (data && data->cool_dev)
+		cpufreq_cooling_unregister(data->cool_dev);
 
 	return 0;
 }
-- 
1.8.2.1.342.gfa7285d


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

* [RFC PATCH 05/14] thermal: ti-soc-thermal: use thermal DT infrastructure
@ 2013-08-23 23:15   ` Eduardo Valentin
  0 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-23 23:15 UTC (permalink / raw)
  To: swarren, pawel.moll, mark.rutland, ian.campbell, grant.likely,
	rob.herring, linux, rui.zhang, wni
  Cc: durgadoss.r, linux-pm, devicetree, lm-sensors, linux-kernel,
	Eduardo Valentin

This patch improves the ti-soc-thermal driver by adding the
support to build the thermal zones based on DT nodes.

The driver will have two options now to build the thermal
zones. The first option is the zones originally coded
in this driver. So, the driver behavior will be same
if there is no DT node describing the zones. The second
option, when it is found a DT node with thermal data,
will used the common infrastructure to build the thermal
zone and bind its cooling devices.

In case the driver loads thermal data using the legacy
mode, this driver still adds to the system
a cpufreq cooling device. Loading the thermal data from
DT, the driver assumes someone else will add the cpufreq
cooling device, like the cpufreq driver.

Cc: Zhang Rui <rui.zhang@intel.com>
Cc: linux-pm@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
---
 drivers/thermal/ti-soc-thermal/ti-thermal-common.c | 52 +++++++++++++++++-----
 1 file changed, 41 insertions(+), 11 deletions(-)

diff --git a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
index 5ab613a..6aac72c 100644
--- a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
+++ b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
@@ -31,6 +31,7 @@
 #include <linux/cpufreq.h>
 #include <linux/cpumask.h>
 #include <linux/cpu_cooling.h>
+#include <linux/of.h>
 
 #include "ti-thermal.h"
 #include "ti-bandgap.h"
@@ -75,11 +76,10 @@ static inline int ti_thermal_hotspot_temperature(int t, int s, int c)
 
 /* thermal zone ops */
 /* Get temperature callback function for thermal zone*/
-static inline int ti_thermal_get_temp(struct thermal_zone_device *thermal,
-				      unsigned long *temp)
+static inline int __ti_thermal_get_temp(void *devdata, unsigned long *temp)
 {
 	struct thermal_zone_device *pcb_tz = NULL;
-	struct ti_thermal_data *data = thermal->devdata;
+	struct ti_thermal_data *data = devdata;
 	struct ti_bandgap *bgp;
 	const struct ti_temp_sensor *s;
 	int ret, tmp, slope, constant;
@@ -117,6 +117,14 @@ static inline int ti_thermal_get_temp(struct thermal_zone_device *thermal,
 	return ret;
 }
 
+static inline int ti_thermal_get_temp(struct thermal_zone_device *thermal,
+				      unsigned long *temp)
+{
+	struct ti_thermal_data *data = thermal->devdata;
+
+	return __ti_thermal_get_temp(data, temp);
+}
+
 /* Bind callback functions for thermal zone */
 static int ti_thermal_bind(struct thermal_zone_device *thermal,
 			   struct thermal_cooling_device *cdev)
@@ -293,6 +301,7 @@ int ti_thermal_expose_sensor(struct ti_bandgap *bgp, int id,
 			     char *domain)
 {
 	struct ti_thermal_data *data;
+	struct device_node *np;
 
 	data = ti_bandgap_get_sensor_data(bgp, id);
 
@@ -302,16 +311,23 @@ int ti_thermal_expose_sensor(struct ti_bandgap *bgp, int id,
 	if (!data)
 		return -EINVAL;
 
-	/* Create thermal zone */
-	data->ti_thermal = thermal_zone_device_register(domain,
+	/* in case this is specified by DT */
+	np = bgp->dev->of_node;
+	data->ti_thermal = thermal_zone_of_device_register(bgp->dev, id,
+					true, /* +hwmon */
+					data, __ti_thermal_get_temp);
+	if (IS_ERR(data->ti_thermal)) {
+		/* Create thermal zone */
+		data->ti_thermal = thermal_zone_device_register(domain,
 				OMAP_TRIP_NUMBER, 0, data, &ti_thermal_ops,
 				NULL, FAST_TEMP_MONITORING_RATE,
 				FAST_TEMP_MONITORING_RATE, true);
-	if (IS_ERR(data->ti_thermal)) {
-		dev_err(bgp->dev, "thermal zone device is NULL\n");
-		return PTR_ERR(data->ti_thermal);
+		if (IS_ERR(data->ti_thermal)) {
+			dev_err(bgp->dev, "thermal zone device is NULL\n");
+			return PTR_ERR(data->ti_thermal);
+		}
+		data->ti_thermal->polling_delay = FAST_TEMP_MONITORING_RATE;
 	}
-	data->ti_thermal->polling_delay = FAST_TEMP_MONITORING_RATE;
 	ti_bandgap_set_sensor_data(bgp, id, data);
 
 	return 0;
@@ -323,7 +339,8 @@ int ti_thermal_remove_sensor(struct ti_bandgap *bgp, int id)
 
 	data = ti_bandgap_get_sensor_data(bgp, id);
 
-	thermal_zone_device_unregister(data->ti_thermal);
+	if (data && data->ti_thermal)
+		thermal_zone_device_unregister(data->ti_thermal);
 
 	return 0;
 }
@@ -342,6 +359,17 @@ int ti_thermal_report_sensor_temperature(struct ti_bandgap *bgp, int id)
 int ti_thermal_register_cpu_cooling(struct ti_bandgap *bgp, int id)
 {
 	struct ti_thermal_data *data;
+	struct device_node *np = bgp->dev->of_node;
+
+	/*
+	 * We are assuming here that if one deploys the zone
+	 * using DT, then it must be aware that the cooling device
+	 * loading has to happen via cpufreq driver.
+	 */
+	if (of_find_property(np, "monitored-zones", NULL)) {
+		of_node_put(np);
+		return 0;
+	}
 
 	data = ti_bandgap_get_sensor_data(bgp, id);
 	if (!data || IS_ERR(data))
@@ -372,7 +400,9 @@ int ti_thermal_unregister_cpu_cooling(struct ti_bandgap *bgp, int id)
 	struct ti_thermal_data *data;
 
 	data = ti_bandgap_get_sensor_data(bgp, id);
-	cpufreq_cooling_unregister(data->cool_dev);
+
+	if (data && data->cool_dev)
+		cpufreq_cooling_unregister(data->cool_dev);
 
 	return 0;
 }
-- 
1.8.2.1.342.gfa7285d


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

* [lm-sensors] [RFC PATCH 05/14] thermal: ti-soc-thermal: use thermal DT infrastructure
@ 2013-08-23 23:15   ` Eduardo Valentin
  0 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-23 23:15 UTC (permalink / raw)
  To: swarren, pawel.moll, mark.rutland, ian.campbell, grant.likely,
	rob.herring, linux, rui.zhang, wni
  Cc: durgadoss.r, linux-pm, devicetree, lm-sensors, linux-kernel,
	Eduardo Valentin

This patch improves the ti-soc-thermal driver by adding the
support to build the thermal zones based on DT nodes.

The driver will have two options now to build the thermal
zones. The first option is the zones originally coded
in this driver. So, the driver behavior will be same
if there is no DT node describing the zones. The second
option, when it is found a DT node with thermal data,
will used the common infrastructure to build the thermal
zone and bind its cooling devices.

In case the driver loads thermal data using the legacy
mode, this driver still adds to the system
a cpufreq cooling device. Loading the thermal data from
DT, the driver assumes someone else will add the cpufreq
cooling device, like the cpufreq driver.

Cc: Zhang Rui <rui.zhang@intel.com>
Cc: linux-pm@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
---
 drivers/thermal/ti-soc-thermal/ti-thermal-common.c | 52 +++++++++++++++++-----
 1 file changed, 41 insertions(+), 11 deletions(-)

diff --git a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
index 5ab613a..6aac72c 100644
--- a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
+++ b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
@@ -31,6 +31,7 @@
 #include <linux/cpufreq.h>
 #include <linux/cpumask.h>
 #include <linux/cpu_cooling.h>
+#include <linux/of.h>
 
 #include "ti-thermal.h"
 #include "ti-bandgap.h"
@@ -75,11 +76,10 @@ static inline int ti_thermal_hotspot_temperature(int t, int s, int c)
 
 /* thermal zone ops */
 /* Get temperature callback function for thermal zone*/
-static inline int ti_thermal_get_temp(struct thermal_zone_device *thermal,
-				      unsigned long *temp)
+static inline int __ti_thermal_get_temp(void *devdata, unsigned long *temp)
 {
 	struct thermal_zone_device *pcb_tz = NULL;
-	struct ti_thermal_data *data = thermal->devdata;
+	struct ti_thermal_data *data = devdata;
 	struct ti_bandgap *bgp;
 	const struct ti_temp_sensor *s;
 	int ret, tmp, slope, constant;
@@ -117,6 +117,14 @@ static inline int ti_thermal_get_temp(struct thermal_zone_device *thermal,
 	return ret;
 }
 
+static inline int ti_thermal_get_temp(struct thermal_zone_device *thermal,
+				      unsigned long *temp)
+{
+	struct ti_thermal_data *data = thermal->devdata;
+
+	return __ti_thermal_get_temp(data, temp);
+}
+
 /* Bind callback functions for thermal zone */
 static int ti_thermal_bind(struct thermal_zone_device *thermal,
 			   struct thermal_cooling_device *cdev)
@@ -293,6 +301,7 @@ int ti_thermal_expose_sensor(struct ti_bandgap *bgp, int id,
 			     char *domain)
 {
 	struct ti_thermal_data *data;
+	struct device_node *np;
 
 	data = ti_bandgap_get_sensor_data(bgp, id);
 
@@ -302,16 +311,23 @@ int ti_thermal_expose_sensor(struct ti_bandgap *bgp, int id,
 	if (!data)
 		return -EINVAL;
 
-	/* Create thermal zone */
-	data->ti_thermal = thermal_zone_device_register(domain,
+	/* in case this is specified by DT */
+	np = bgp->dev->of_node;
+	data->ti_thermal = thermal_zone_of_device_register(bgp->dev, id,
+					true, /* +hwmon */
+					data, __ti_thermal_get_temp);
+	if (IS_ERR(data->ti_thermal)) {
+		/* Create thermal zone */
+		data->ti_thermal = thermal_zone_device_register(domain,
 				OMAP_TRIP_NUMBER, 0, data, &ti_thermal_ops,
 				NULL, FAST_TEMP_MONITORING_RATE,
 				FAST_TEMP_MONITORING_RATE, true);
-	if (IS_ERR(data->ti_thermal)) {
-		dev_err(bgp->dev, "thermal zone device is NULL\n");
-		return PTR_ERR(data->ti_thermal);
+		if (IS_ERR(data->ti_thermal)) {
+			dev_err(bgp->dev, "thermal zone device is NULL\n");
+			return PTR_ERR(data->ti_thermal);
+		}
+		data->ti_thermal->polling_delay = FAST_TEMP_MONITORING_RATE;
 	}
-	data->ti_thermal->polling_delay = FAST_TEMP_MONITORING_RATE;
 	ti_bandgap_set_sensor_data(bgp, id, data);
 
 	return 0;
@@ -323,7 +339,8 @@ int ti_thermal_remove_sensor(struct ti_bandgap *bgp, int id)
 
 	data = ti_bandgap_get_sensor_data(bgp, id);
 
-	thermal_zone_device_unregister(data->ti_thermal);
+	if (data && data->ti_thermal)
+		thermal_zone_device_unregister(data->ti_thermal);
 
 	return 0;
 }
@@ -342,6 +359,17 @@ int ti_thermal_report_sensor_temperature(struct ti_bandgap *bgp, int id)
 int ti_thermal_register_cpu_cooling(struct ti_bandgap *bgp, int id)
 {
 	struct ti_thermal_data *data;
+	struct device_node *np = bgp->dev->of_node;
+
+	/*
+	 * We are assuming here that if one deploys the zone
+	 * using DT, then it must be aware that the cooling device
+	 * loading has to happen via cpufreq driver.
+	 */
+	if (of_find_property(np, "monitored-zones", NULL)) {
+		of_node_put(np);
+		return 0;
+	}
 
 	data = ti_bandgap_get_sensor_data(bgp, id);
 	if (!data || IS_ERR(data))
@@ -372,7 +400,9 @@ int ti_thermal_unregister_cpu_cooling(struct ti_bandgap *bgp, int id)
 	struct ti_thermal_data *data;
 
 	data = ti_bandgap_get_sensor_data(bgp, id);
-	cpufreq_cooling_unregister(data->cool_dev);
+
+	if (data && data->cool_dev)
+		cpufreq_cooling_unregister(data->cool_dev);
 
 	return 0;
 }
-- 
1.8.2.1.342.gfa7285d


_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

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

* [RFC PATCH 06/14] arm: dts: add omap4 CPU thermal data
  2013-08-23 23:15 ` Eduardo Valentin
  (?)
  (?)
@ 2013-08-23 23:15   ` Eduardo Valentin
  -1 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-23 23:15 UTC (permalink / raw)
  To: swarren, pawel.moll, mark.rutland, ian.campbell, grant.likely,
	rob.herring, linux, rui.zhang, wni
  Cc: durgadoss.r, linux-pm, devicetree, lm-sensors, linux-kernel,
	Eduardo Valentin, Benoît Cousson, Tony Lindgren,
	Russell King, linux-omap, linux-arm-kernel

This patch changes a dtsi file to contain the thermal data
for MPU domain on OMAP4 and later SoCs. This data will
enable the passive cooling with CPUfreq cooling device
at 100C and the system will do a thermal shutdown at 125C.

This thermal data can be reused across TI SoC devices.

Cc: "Benoît Cousson" <b-cousson@linaro.org>
Cc: Tony Lindgren <tony@atomide.com>
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: Pawel Moll <pawel.moll@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Stephen Warren <swarren@wwwdotorg.org>
Cc: Ian Campbell <ian.campbell@citrix.com>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: linux-omap@vger.kernel.org
Cc: devicetree@vger.kernel.org
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
---
 arch/arm/boot/dts/omap4-cpu-thermal.dtsi | 40 ++++++++++++++++++++++++++++++++
 1 file changed, 40 insertions(+)
 create mode 100644 arch/arm/boot/dts/omap4-cpu-thermal.dtsi

diff --git a/arch/arm/boot/dts/omap4-cpu-thermal.dtsi b/arch/arm/boot/dts/omap4-cpu-thermal.dtsi
new file mode 100644
index 0000000..d74c565
--- /dev/null
+++ b/arch/arm/boot/dts/omap4-cpu-thermal.dtsi
@@ -0,0 +1,40 @@
+
+/*
+ * Device Tree Source for OMAP4/5 SoC CPU thermal
+ *
+ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
+ * Contact: Eduardo Valentin <eduardo.valentin@ti.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <dt-bindings/thermal/thermal.h>
+
+cpu_thermal: cpu_thermal {
+	#thermal-cells = <1>;
+	mask = <0x03>; /* trips writability */
+	passive_delay = <250>; /* milliseconds */
+	polling_delay = <1000>; /* milliseconds */
+	trips {
+		alert@100000{
+			temperature = <100000>; /* milliCelsius */
+			hysteresis = <2000>; /* milliCelsius */
+			type = <THERMAL_TRIP_PASSIVE>;
+		};
+		crit@125000{
+			temperature = <125000>; /* milliCelsius */
+			hysteresis = <2000>; /* milliCelsius */
+			type = <THERMAL_TRIP_CRITICAL>;
+		};
+	};
+	bind_params {
+		action@0{
+			cooling_device = "thermal-cpufreq";
+			weight = <100>; /* percentage */
+			mask = <0x01>;
+			/* no limits, using defaults */
+		};
+	};
+};
-- 
1.8.2.1.342.gfa7285d


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

* [RFC PATCH 06/14] arm: dts: add omap4 CPU thermal data
@ 2013-08-23 23:15   ` Eduardo Valentin
  0 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-23 23:15 UTC (permalink / raw)
  To: swarren, pawel.moll, mark.rutland, ian.campbell, grant.likely,
	rob.herring, linux, rui.zhang, wni
  Cc: devicetree, durgadoss.r, linux-pm, Tony Lindgren, linux-kernel,
	lm-sensors, Eduardo Valentin, linux-arm-kernel, Russell King,
	linux-omap, Benoît Cousson

This patch changes a dtsi file to contain the thermal data
for MPU domain on OMAP4 and later SoCs. This data will
enable the passive cooling with CPUfreq cooling device
at 100C and the system will do a thermal shutdown at 125C.

This thermal data can be reused across TI SoC devices.

Cc: "Benoît Cousson" <b-cousson@linaro.org>
Cc: Tony Lindgren <tony@atomide.com>
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: Pawel Moll <pawel.moll@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Stephen Warren <swarren@wwwdotorg.org>
Cc: Ian Campbell <ian.campbell@citrix.com>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: linux-omap@vger.kernel.org
Cc: devicetree@vger.kernel.org
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
---
 arch/arm/boot/dts/omap4-cpu-thermal.dtsi | 40 ++++++++++++++++++++++++++++++++
 1 file changed, 40 insertions(+)
 create mode 100644 arch/arm/boot/dts/omap4-cpu-thermal.dtsi

diff --git a/arch/arm/boot/dts/omap4-cpu-thermal.dtsi b/arch/arm/boot/dts/omap4-cpu-thermal.dtsi
new file mode 100644
index 0000000..d74c565
--- /dev/null
+++ b/arch/arm/boot/dts/omap4-cpu-thermal.dtsi
@@ -0,0 +1,40 @@
+
+/*
+ * Device Tree Source for OMAP4/5 SoC CPU thermal
+ *
+ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
+ * Contact: Eduardo Valentin <eduardo.valentin@ti.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <dt-bindings/thermal/thermal.h>
+
+cpu_thermal: cpu_thermal {
+	#thermal-cells = <1>;
+	mask = <0x03>; /* trips writability */
+	passive_delay = <250>; /* milliseconds */
+	polling_delay = <1000>; /* milliseconds */
+	trips {
+		alert@100000{
+			temperature = <100000>; /* milliCelsius */
+			hysteresis = <2000>; /* milliCelsius */
+			type = <THERMAL_TRIP_PASSIVE>;
+		};
+		crit@125000{
+			temperature = <125000>; /* milliCelsius */
+			hysteresis = <2000>; /* milliCelsius */
+			type = <THERMAL_TRIP_CRITICAL>;
+		};
+	};
+	bind_params {
+		action@0{
+			cooling_device = "thermal-cpufreq";
+			weight = <100>; /* percentage */
+			mask = <0x01>;
+			/* no limits, using defaults */
+		};
+	};
+};
-- 
1.8.2.1.342.gfa7285d


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [RFC PATCH 06/14] arm: dts: add omap4 CPU thermal data
@ 2013-08-23 23:15   ` Eduardo Valentin
  0 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-23 23:15 UTC (permalink / raw)
  To: linux-arm-kernel

This patch changes a dtsi file to contain the thermal data
for MPU domain on OMAP4 and later SoCs. This data will
enable the passive cooling with CPUfreq cooling device
at 100C and the system will do a thermal shutdown at 125C.

This thermal data can be reused across TI SoC devices.

Cc: "Beno?t Cousson" <b-cousson@linaro.org>
Cc: Tony Lindgren <tony@atomide.com>
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: Pawel Moll <pawel.moll@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Stephen Warren <swarren@wwwdotorg.org>
Cc: Ian Campbell <ian.campbell@citrix.com>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: linux-omap at vger.kernel.org
Cc: devicetree at vger.kernel.org
Cc: linux-arm-kernel at lists.infradead.org
Cc: linux-kernel at vger.kernel.org
Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
---
 arch/arm/boot/dts/omap4-cpu-thermal.dtsi | 40 ++++++++++++++++++++++++++++++++
 1 file changed, 40 insertions(+)
 create mode 100644 arch/arm/boot/dts/omap4-cpu-thermal.dtsi

diff --git a/arch/arm/boot/dts/omap4-cpu-thermal.dtsi b/arch/arm/boot/dts/omap4-cpu-thermal.dtsi
new file mode 100644
index 0000000..d74c565
--- /dev/null
+++ b/arch/arm/boot/dts/omap4-cpu-thermal.dtsi
@@ -0,0 +1,40 @@
+
+/*
+ * Device Tree Source for OMAP4/5 SoC CPU thermal
+ *
+ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
+ * Contact: Eduardo Valentin <eduardo.valentin@ti.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <dt-bindings/thermal/thermal.h>
+
+cpu_thermal: cpu_thermal {
+	#thermal-cells = <1>;
+	mask = <0x03>; /* trips writability */
+	passive_delay = <250>; /* milliseconds */
+	polling_delay = <1000>; /* milliseconds */
+	trips {
+		alert at 100000{
+			temperature = <100000>; /* milliCelsius */
+			hysteresis = <2000>; /* milliCelsius */
+			type = <THERMAL_TRIP_PASSIVE>;
+		};
+		crit at 125000{
+			temperature = <125000>; /* milliCelsius */
+			hysteresis = <2000>; /* milliCelsius */
+			type = <THERMAL_TRIP_CRITICAL>;
+		};
+	};
+	bind_params {
+		action at 0{
+			cooling_device = "thermal-cpufreq";
+			weight = <100>; /* percentage */
+			mask = <0x01>;
+			/* no limits, using defaults */
+		};
+	};
+};
-- 
1.8.2.1.342.gfa7285d

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

* [lm-sensors] [RFC PATCH 06/14] arm: dts: add omap4 CPU thermal data
@ 2013-08-23 23:15   ` Eduardo Valentin
  0 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-23 23:15 UTC (permalink / raw)
  To: swarren, pawel.moll, mark.rutland, ian.campbell, grant.likely,
	rob.herring, linux, rui.zhang, wni
  Cc: durgadoss.r, linux-pm, devicetree, lm-sensors, linux-kernel,
	Eduardo Valentin, Benoît Cousson, Tony Lindgren,
	Russell King, linux-omap, linux-arm-kernel

VGhpcyBwYXRjaCBjaGFuZ2VzIGEgZHRzaSBmaWxlIHRvIGNvbnRhaW4gdGhlIHRoZXJtYWwgZGF0
YQpmb3IgTVBVIGRvbWFpbiBvbiBPTUFQNCBhbmQgbGF0ZXIgU29Dcy4gVGhpcyBkYXRhIHdpbGwK
ZW5hYmxlIHRoZSBwYXNzaXZlIGNvb2xpbmcgd2l0aCBDUFVmcmVxIGNvb2xpbmcgZGV2aWNlCmF0
IDEwMEMgYW5kIHRoZSBzeXN0ZW0gd2lsbCBkbyBhIHRoZXJtYWwgc2h1dGRvd24gYXQgMTI1Qy4K
ClRoaXMgdGhlcm1hbCBkYXRhIGNhbiBiZSByZXVzZWQgYWNyb3NzIFRJIFNvQyBkZXZpY2VzLgoK
Q2M6ICJCZW5vw650IENvdXNzb24iIDxiLWNvdXNzb25AbGluYXJvLm9yZz4KQ2M6IFRvbnkgTGlu
ZGdyZW4gPHRvbnlAYXRvbWlkZS5jb20+CkNjOiBSb2IgSGVycmluZyA8cm9iLmhlcnJpbmdAY2Fs
eGVkYS5jb20+CkNjOiBQYXdlbCBNb2xsIDxwYXdlbC5tb2xsQGFybS5jb20+CkNjOiBNYXJrIFJ1
dGxhbmQgPG1hcmsucnV0bGFuZEBhcm0uY29tPgpDYzogU3RlcGhlbiBXYXJyZW4gPHN3YXJyZW5A
d3d3ZG90b3JnLm9yZz4KQ2M6IElhbiBDYW1wYmVsbCA8aWFuLmNhbXBiZWxsQGNpdHJpeC5jb20+
CkNjOiBSdXNzZWxsIEtpbmcgPGxpbnV4QGFybS5saW51eC5vcmcudWs+CkNjOiBsaW51eC1vbWFw
QHZnZXIua2VybmVsLm9yZwpDYzogZGV2aWNldHJlZUB2Z2VyLmtlcm5lbC5vcmcKQ2M6IGxpbnV4
LWFybS1rZXJuZWxAbGlzdHMuaW5mcmFkZWFkLm9yZwpDYzogbGludXgta2VybmVsQHZnZXIua2Vy
bmVsLm9yZwpTaWduZWQtb2ZmLWJ5OiBFZHVhcmRvIFZhbGVudGluIDxlZHVhcmRvLnZhbGVudGlu
QHRpLmNvbT4KLS0tCiBhcmNoL2FybS9ib290L2R0cy9vbWFwNC1jcHUtdGhlcm1hbC5kdHNpIHwg
NDAgKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysKIDEgZmlsZSBjaGFuZ2VkLCA0MCBp
bnNlcnRpb25zKCspCiBjcmVhdGUgbW9kZSAxMDA2NDQgYXJjaC9hcm0vYm9vdC9kdHMvb21hcDQt
Y3B1LXRoZXJtYWwuZHRzaQoKZGlmZiAtLWdpdCBhL2FyY2gvYXJtL2Jvb3QvZHRzL29tYXA0LWNw
dS10aGVybWFsLmR0c2kgYi9hcmNoL2FybS9ib290L2R0cy9vbWFwNC1jcHUtdGhlcm1hbC5kdHNp
Cm5ldyBmaWxlIG1vZGUgMTAwNjQ0CmluZGV4IDAwMDAwMDAuLmQ3NGM1NjUKLS0tIC9kZXYvbnVs
bAorKysgYi9hcmNoL2FybS9ib290L2R0cy9vbWFwNC1jcHUtdGhlcm1hbC5kdHNpCkBAIC0wLDAg
KzEsNDAgQEAKKworLyoKKyAqIERldmljZSBUcmVlIFNvdXJjZSBmb3IgT01BUDQvNSBTb0MgQ1BV
IHRoZXJtYWwKKyAqCisgKiBDb3B5cmlnaHQgKEMpIDIwMTMgVGV4YXMgSW5zdHJ1bWVudHMgSW5j
b3Jwb3JhdGVkIC0gaHR0cDovL3d3dy50aS5jb20vCisgKiBDb250YWN0OiBFZHVhcmRvIFZhbGVu
dGluIDxlZHVhcmRvLnZhbGVudGluQHRpLmNvbT4KKyAqCisgKiBUaGlzIGZpbGUgaXMgbGljZW5z
ZWQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZQorICog
dmVyc2lvbiAyLiAgVGhpcyBwcm9ncmFtIGlzIGxpY2Vuc2VkICJhcyBpcyIgd2l0aG91dCBhbnkg
d2FycmFudHkgb2YgYW55CisgKiBraW5kLCB3aGV0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC4KKyAq
LworCisjaW5jbHVkZSA8ZHQtYmluZGluZ3MvdGhlcm1hbC90aGVybWFsLmg+CisKK2NwdV90aGVy
bWFsOiBjcHVfdGhlcm1hbCB7CisJI3RoZXJtYWwtY2VsbHMgPSA8MT47CisJbWFzayA9IDwweDAz
PjsgLyogdHJpcHMgd3JpdGFiaWxpdHkgKi8KKwlwYXNzaXZlX2RlbGF5ID0gPDI1MD47IC8qIG1p
bGxpc2Vjb25kcyAqLworCXBvbGxpbmdfZGVsYXkgPSA8MTAwMD47IC8qIG1pbGxpc2Vjb25kcyAq
LworCXRyaXBzIHsKKwkJYWxlcnRAMTAwMDAweworCQkJdGVtcGVyYXR1cmUgPSA8MTAwMDAwPjsg
LyogbWlsbGlDZWxzaXVzICovCisJCQloeXN0ZXJlc2lzID0gPDIwMDA+OyAvKiBtaWxsaUNlbHNp
dXMgKi8KKwkJCXR5cGUgPSA8VEhFUk1BTF9UUklQX1BBU1NJVkU+OworCQl9OworCQljcml0QDEy
NTAwMHsKKwkJCXRlbXBlcmF0dXJlID0gPDEyNTAwMD47IC8qIG1pbGxpQ2Vsc2l1cyAqLworCQkJ
aHlzdGVyZXNpcyA9IDwyMDAwPjsgLyogbWlsbGlDZWxzaXVzICovCisJCQl0eXBlID0gPFRIRVJN
QUxfVFJJUF9DUklUSUNBTD47CisJCX07CisJfTsKKwliaW5kX3BhcmFtcyB7CisJCWFjdGlvbkAw
eworCQkJY29vbGluZ19kZXZpY2UgPSAidGhlcm1hbC1jcHVmcmVxIjsKKwkJCXdlaWdodCA9IDwx
MDA+OyAvKiBwZXJjZW50YWdlICovCisJCQltYXNrID0gPDB4MDE+OworCQkJLyogbm8gbGltaXRz
LCB1c2luZyBkZWZhdWx0cyAqLworCQl9OworCX07Cit9OwotLSAKMS44LjIuMS4zNDIuZ2ZhNzI4
NWQKCgpfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXwpsbS1z
ZW5zb3JzIG1haWxpbmcgbGlzdApsbS1zZW5zb3JzQGxtLXNlbnNvcnMub3JnCmh0dHA6Ly9saXN0
cy5sbS1zZW5zb3JzLm9yZy9tYWlsbWFuL2xpc3RpbmZvL2xtLXNlbnNvcnM

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

* [RFC PATCH 07/14] arm: dts: add omap4430 thermal data
  2013-08-23 23:15 ` Eduardo Valentin
  (?)
  (?)
@ 2013-08-23 23:15   ` Eduardo Valentin
  -1 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-23 23:15 UTC (permalink / raw)
  To: swarren, pawel.moll, mark.rutland, ian.campbell, grant.likely,
	rob.herring, linux, rui.zhang, wni
  Cc: durgadoss.r, linux-pm, devicetree, lm-sensors, linux-kernel,
	Eduardo Valentin, Benoît Cousson, Tony Lindgren,
	Russell King, linux-omap, devicetree-discuss, linux-arm-kernel

This patch changes the dtsi entry on omap4430 to contain
the thermal data. This data will enable the passive
cooling with CPUfreq cooling device at 100C and the
system will do a thermal shutdown at 125C.

Cc: "Benoît Cousson" <b-cousson@ti.com>
Cc: Tony Lindgren <tony@atomide.com>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: linux-omap@vger.kernel.org
Cc: devicetree-discuss@lists.ozlabs.org
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
---
 arch/arm/boot/dts/omap443x.dtsi | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/arm/boot/dts/omap443x.dtsi b/arch/arm/boot/dts/omap443x.dtsi
index bcf455e..91a3a5d 100644
--- a/arch/arm/boot/dts/omap443x.dtsi
+++ b/arch/arm/boot/dts/omap443x.dtsi
@@ -25,9 +25,14 @@
 		};
 	};
 
+	thermal_zones{
+		#include "omap4-cpu-thermal.dtsi"
+	};
+
 	bandgap {
 		reg = <0x4a002260 0x4
 		       0x4a00232C 0x4>;
 		compatible = "ti,omap4430-bandgap";
+		monitored-zones = <&cpu_thermal 0>;
 	};
 };
-- 
1.8.2.1.342.gfa7285d


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

* [RFC PATCH 07/14] arm: dts: add omap4430 thermal data
@ 2013-08-23 23:15   ` Eduardo Valentin
  0 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-23 23:15 UTC (permalink / raw)
  To: swarren, pawel.moll, mark.rutland, ian.campbell, grant.likely,
	rob.herring, linux, rui.zhang, wni
  Cc: devicetree, durgadoss.r, Benoît Cousson, linux-pm,
	Tony Lindgren, devicetree-discuss, linux-kernel, lm-sensors,
	Eduardo Valentin, Russell King, linux-omap, linux-arm-kernel

This patch changes the dtsi entry on omap4430 to contain
the thermal data. This data will enable the passive
cooling with CPUfreq cooling device at 100C and the
system will do a thermal shutdown at 125C.

Cc: "Benoît Cousson" <b-cousson@ti.com>
Cc: Tony Lindgren <tony@atomide.com>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: linux-omap@vger.kernel.org
Cc: devicetree-discuss@lists.ozlabs.org
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
---
 arch/arm/boot/dts/omap443x.dtsi | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/arm/boot/dts/omap443x.dtsi b/arch/arm/boot/dts/omap443x.dtsi
index bcf455e..91a3a5d 100644
--- a/arch/arm/boot/dts/omap443x.dtsi
+++ b/arch/arm/boot/dts/omap443x.dtsi
@@ -25,9 +25,14 @@
 		};
 	};
 
+	thermal_zones{
+		#include "omap4-cpu-thermal.dtsi"
+	};
+
 	bandgap {
 		reg = <0x4a002260 0x4
 		       0x4a00232C 0x4>;
 		compatible = "ti,omap4430-bandgap";
+		monitored-zones = <&cpu_thermal 0>;
 	};
 };
-- 
1.8.2.1.342.gfa7285d


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [RFC PATCH 07/14] arm: dts: add omap4430 thermal data
@ 2013-08-23 23:15   ` Eduardo Valentin
  0 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-23 23:15 UTC (permalink / raw)
  To: linux-arm-kernel

This patch changes the dtsi entry on omap4430 to contain
the thermal data. This data will enable the passive
cooling with CPUfreq cooling device at 100C and the
system will do a thermal shutdown at 125C.

Cc: "Beno?t Cousson" <b-cousson@ti.com>
Cc: Tony Lindgren <tony@atomide.com>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: linux-omap at vger.kernel.org
Cc: devicetree-discuss at lists.ozlabs.org
Cc: linux-arm-kernel at lists.infradead.org
Cc: linux-kernel at vger.kernel.org
Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
---
 arch/arm/boot/dts/omap443x.dtsi | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/arm/boot/dts/omap443x.dtsi b/arch/arm/boot/dts/omap443x.dtsi
index bcf455e..91a3a5d 100644
--- a/arch/arm/boot/dts/omap443x.dtsi
+++ b/arch/arm/boot/dts/omap443x.dtsi
@@ -25,9 +25,14 @@
 		};
 	};
 
+	thermal_zones{
+		#include "omap4-cpu-thermal.dtsi"
+	};
+
 	bandgap {
 		reg = <0x4a002260 0x4
 		       0x4a00232C 0x4>;
 		compatible = "ti,omap4430-bandgap";
+		monitored-zones = <&cpu_thermal 0>;
 	};
 };
-- 
1.8.2.1.342.gfa7285d

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

* [lm-sensors] [RFC PATCH 07/14] arm: dts: add omap4430 thermal data
@ 2013-08-23 23:15   ` Eduardo Valentin
  0 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-23 23:15 UTC (permalink / raw)
  To: swarren, pawel.moll, mark.rutland, ian.campbell, grant.likely,
	rob.herring, linux, rui.zhang, wni
  Cc: durgadoss.r, linux-pm, devicetree, lm-sensors, linux-kernel,
	Eduardo Valentin, Benoît Cousson, Tony Lindgren,
	Russell King, linux-omap, devicetree-discuss, linux-arm-kernel

VGhpcyBwYXRjaCBjaGFuZ2VzIHRoZSBkdHNpIGVudHJ5IG9uIG9tYXA0NDMwIHRvIGNvbnRhaW4K
dGhlIHRoZXJtYWwgZGF0YS4gVGhpcyBkYXRhIHdpbGwgZW5hYmxlIHRoZSBwYXNzaXZlCmNvb2xp
bmcgd2l0aCBDUFVmcmVxIGNvb2xpbmcgZGV2aWNlIGF0IDEwMEMgYW5kIHRoZQpzeXN0ZW0gd2ls
bCBkbyBhIHRoZXJtYWwgc2h1dGRvd24gYXQgMTI1Qy4KCkNjOiAiQmVub8OudCBDb3Vzc29uIiA8
Yi1jb3Vzc29uQHRpLmNvbT4KQ2M6IFRvbnkgTGluZGdyZW4gPHRvbnlAYXRvbWlkZS5jb20+CkNj
OiBSdXNzZWxsIEtpbmcgPGxpbnV4QGFybS5saW51eC5vcmcudWs+CkNjOiBsaW51eC1vbWFwQHZn
ZXIua2VybmVsLm9yZwpDYzogZGV2aWNldHJlZS1kaXNjdXNzQGxpc3RzLm96bGFicy5vcmcKQ2M6
IGxpbnV4LWFybS1rZXJuZWxAbGlzdHMuaW5mcmFkZWFkLm9yZwpDYzogbGludXgta2VybmVsQHZn
ZXIua2VybmVsLm9yZwpTaWduZWQtb2ZmLWJ5OiBFZHVhcmRvIFZhbGVudGluIDxlZHVhcmRvLnZh
bGVudGluQHRpLmNvbT4KLS0tCiBhcmNoL2FybS9ib290L2R0cy9vbWFwNDQzeC5kdHNpIHwgNSAr
KysrKwogMSBmaWxlIGNoYW5nZWQsIDUgaW5zZXJ0aW9ucygrKQoKZGlmZiAtLWdpdCBhL2FyY2gv
YXJtL2Jvb3QvZHRzL29tYXA0NDN4LmR0c2kgYi9hcmNoL2FybS9ib290L2R0cy9vbWFwNDQzeC5k
dHNpCmluZGV4IGJjZjQ1NWUuLjkxYTNhNWQgMTAwNjQ0Ci0tLSBhL2FyY2gvYXJtL2Jvb3QvZHRz
L29tYXA0NDN4LmR0c2kKKysrIGIvYXJjaC9hcm0vYm9vdC9kdHMvb21hcDQ0M3guZHRzaQpAQCAt
MjUsOSArMjUsMTQgQEAKIAkJfTsKIAl9OwogCisJdGhlcm1hbF96b25lc3sKKwkJI2luY2x1ZGUg
Im9tYXA0LWNwdS10aGVybWFsLmR0c2kiCisJfTsKKwogCWJhbmRnYXAgewogCQlyZWcgPSA8MHg0
YTAwMjI2MCAweDQKIAkJICAgICAgIDB4NGEwMDIzMkMgMHg0PjsKIAkJY29tcGF0aWJsZSA9ICJ0
aSxvbWFwNDQzMC1iYW5kZ2FwIjsKKwkJbW9uaXRvcmVkLXpvbmVzID0gPCZjcHVfdGhlcm1hbCAw
PjsKIAl9OwogfTsKLS0gCjEuOC4yLjEuMzQyLmdmYTcyODVkCgoKX19fX19fX19fX19fX19fX19f
X19fX19fX19fX19fX19fX19fX19fX19fX19fX18KbG0tc2Vuc29ycyBtYWlsaW5nIGxpc3QKbG0t
c2Vuc29yc0BsbS1zZW5zb3JzLm9yZwpodHRwOi8vbGlzdHMubG0tc2Vuc29ycy5vcmcvbWFpbG1h
bi9saXN0aW5mby9sbS1zZW5zb3Jz

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

* [RFC PATCH 08/14] arm: dts: add omap4460 thermal data
  2013-08-23 23:15 ` Eduardo Valentin
  (?)
  (?)
@ 2013-08-23 23:15   ` Eduardo Valentin
  -1 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-23 23:15 UTC (permalink / raw)
  To: swarren, pawel.moll, mark.rutland, ian.campbell, grant.likely,
	rob.herring, linux, rui.zhang, wni
  Cc: durgadoss.r, linux-pm, devicetree, lm-sensors, linux-kernel,
	Eduardo Valentin, Benoît Cousson, Tony Lindgren,
	Russell King, linux-omap, linux-arm-kernel

This patch changes the dtsi entry on omap4460 to contain
the thermal data. This data will enable the passive
cooling with CPUfreq cooling device at 100C and the
system will do a thermal shutdown at 125C.

Cc: "Benoît Cousson" <b-cousson@linaro.org>
Cc: Tony Lindgren <tony@atomide.com>
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: Pawel Moll <pawel.moll@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Stephen Warren <swarren@wwwdotorg.org>
Cc: Ian Campbell <ian.campbell@citrix.com>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: linux-omap@vger.kernel.org
Cc: devicetree@vger.kernel.org
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
---
 arch/arm/boot/dts/omap4460.dtsi | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/arm/boot/dts/omap4460.dtsi b/arch/arm/boot/dts/omap4460.dtsi
index c2f0f39..9855f29 100644
--- a/arch/arm/boot/dts/omap4460.dtsi
+++ b/arch/arm/boot/dts/omap4460.dtsi
@@ -30,6 +30,10 @@
 		ti,hwmods = "debugss";
 	};
 
+	thermal_zones{
+		#include "omap4-cpu-thermal.dtsi"
+	};
+
 	bandgap {
 		reg = <0x4a002260 0x4
 		       0x4a00232C 0x4
@@ -37,5 +41,6 @@
 		compatible = "ti,omap4460-bandgap";
 		interrupts = <0 126 IRQ_TYPE_LEVEL_HIGH>; /* talert */
 		gpios = <&gpio3 22 0>; /* tshut */
+		monitored-zones = <&cpu_thermal 0>;
 	};
 };
-- 
1.8.2.1.342.gfa7285d


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

* [RFC PATCH 08/14] arm: dts: add omap4460 thermal data
@ 2013-08-23 23:15   ` Eduardo Valentin
  0 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-23 23:15 UTC (permalink / raw)
  To: swarren, pawel.moll, mark.rutland, ian.campbell, grant.likely,
	rob.herring, linux, rui.zhang, wni
  Cc: durgadoss.r, linux-pm, devicetree, lm-sensors, linux-kernel,
	Eduardo Valentin, Benoît Cousson, Tony Lindgren,
	Russell King, linux-omap, linux-arm-kernel

This patch changes the dtsi entry on omap4460 to contain
the thermal data. This data will enable the passive
cooling with CPUfreq cooling device at 100C and the
system will do a thermal shutdown at 125C.

Cc: "Benoît Cousson" <b-cousson@linaro.org>
Cc: Tony Lindgren <tony@atomide.com>
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: Pawel Moll <pawel.moll@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Stephen Warren <swarren@wwwdotorg.org>
Cc: Ian Campbell <ian.campbell@citrix.com>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: linux-omap@vger.kernel.org
Cc: devicetree@vger.kernel.org
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
---
 arch/arm/boot/dts/omap4460.dtsi | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/arm/boot/dts/omap4460.dtsi b/arch/arm/boot/dts/omap4460.dtsi
index c2f0f39..9855f29 100644
--- a/arch/arm/boot/dts/omap4460.dtsi
+++ b/arch/arm/boot/dts/omap4460.dtsi
@@ -30,6 +30,10 @@
 		ti,hwmods = "debugss";
 	};
 
+	thermal_zones{
+		#include "omap4-cpu-thermal.dtsi"
+	};
+
 	bandgap {
 		reg = <0x4a002260 0x4
 		       0x4a00232C 0x4
@@ -37,5 +41,6 @@
 		compatible = "ti,omap4460-bandgap";
 		interrupts = <0 126 IRQ_TYPE_LEVEL_HIGH>; /* talert */
 		gpios = <&gpio3 22 0>; /* tshut */
+		monitored-zones = <&cpu_thermal 0>;
 	};
 };
-- 
1.8.2.1.342.gfa7285d

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

* [RFC PATCH 08/14] arm: dts: add omap4460 thermal data
@ 2013-08-23 23:15   ` Eduardo Valentin
  0 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-23 23:15 UTC (permalink / raw)
  To: linux-arm-kernel

This patch changes the dtsi entry on omap4460 to contain
the thermal data. This data will enable the passive
cooling with CPUfreq cooling device at 100C and the
system will do a thermal shutdown at 125C.

Cc: "Beno?t Cousson" <b-cousson@linaro.org>
Cc: Tony Lindgren <tony@atomide.com>
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: Pawel Moll <pawel.moll@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Stephen Warren <swarren@wwwdotorg.org>
Cc: Ian Campbell <ian.campbell@citrix.com>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: linux-omap at vger.kernel.org
Cc: devicetree at vger.kernel.org
Cc: linux-arm-kernel at lists.infradead.org
Cc: linux-kernel at vger.kernel.org
Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
---
 arch/arm/boot/dts/omap4460.dtsi | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/arm/boot/dts/omap4460.dtsi b/arch/arm/boot/dts/omap4460.dtsi
index c2f0f39..9855f29 100644
--- a/arch/arm/boot/dts/omap4460.dtsi
+++ b/arch/arm/boot/dts/omap4460.dtsi
@@ -30,6 +30,10 @@
 		ti,hwmods = "debugss";
 	};
 
+	thermal_zones{
+		#include "omap4-cpu-thermal.dtsi"
+	};
+
 	bandgap {
 		reg = <0x4a002260 0x4
 		       0x4a00232C 0x4
@@ -37,5 +41,6 @@
 		compatible = "ti,omap4460-bandgap";
 		interrupts = <0 126 IRQ_TYPE_LEVEL_HIGH>; /* talert */
 		gpios = <&gpio3 22 0>; /* tshut */
+		monitored-zones = <&cpu_thermal 0>;
 	};
 };
-- 
1.8.2.1.342.gfa7285d

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

* [lm-sensors] [RFC PATCH 08/14] arm: dts: add omap4460 thermal data
@ 2013-08-23 23:15   ` Eduardo Valentin
  0 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-23 23:15 UTC (permalink / raw)
  To: swarren, pawel.moll, mark.rutland, ian.campbell, grant.likely,
	rob.herring, linux, rui.zhang, wni
  Cc: durgadoss.r, linux-pm, devicetree, lm-sensors, linux-kernel,
	Eduardo Valentin, Benoît Cousson, Tony Lindgren,
	Russell King, linux-omap, linux-arm-kernel

VGhpcyBwYXRjaCBjaGFuZ2VzIHRoZSBkdHNpIGVudHJ5IG9uIG9tYXA0NDYwIHRvIGNvbnRhaW4K
dGhlIHRoZXJtYWwgZGF0YS4gVGhpcyBkYXRhIHdpbGwgZW5hYmxlIHRoZSBwYXNzaXZlCmNvb2xp
bmcgd2l0aCBDUFVmcmVxIGNvb2xpbmcgZGV2aWNlIGF0IDEwMEMgYW5kIHRoZQpzeXN0ZW0gd2ls
bCBkbyBhIHRoZXJtYWwgc2h1dGRvd24gYXQgMTI1Qy4KCkNjOiAiQmVub8OudCBDb3Vzc29uIiA8
Yi1jb3Vzc29uQGxpbmFyby5vcmc+CkNjOiBUb255IExpbmRncmVuIDx0b255QGF0b21pZGUuY29t
PgpDYzogUm9iIEhlcnJpbmcgPHJvYi5oZXJyaW5nQGNhbHhlZGEuY29tPgpDYzogUGF3ZWwgTW9s
bCA8cGF3ZWwubW9sbEBhcm0uY29tPgpDYzogTWFyayBSdXRsYW5kIDxtYXJrLnJ1dGxhbmRAYXJt
LmNvbT4KQ2M6IFN0ZXBoZW4gV2FycmVuIDxzd2FycmVuQHd3d2RvdG9yZy5vcmc+CkNjOiBJYW4g
Q2FtcGJlbGwgPGlhbi5jYW1wYmVsbEBjaXRyaXguY29tPgpDYzogUnVzc2VsbCBLaW5nIDxsaW51
eEBhcm0ubGludXgub3JnLnVrPgpDYzogbGludXgtb21hcEB2Z2VyLmtlcm5lbC5vcmcKQ2M6IGRl
dmljZXRyZWVAdmdlci5rZXJuZWwub3JnCkNjOiBsaW51eC1hcm0ta2VybmVsQGxpc3RzLmluZnJh
ZGVhZC5vcmcKQ2M6IGxpbnV4LWtlcm5lbEB2Z2VyLmtlcm5lbC5vcmcKU2lnbmVkLW9mZi1ieTog
RWR1YXJkbyBWYWxlbnRpbiA8ZWR1YXJkby52YWxlbnRpbkB0aS5jb20+Ci0tLQogYXJjaC9hcm0v
Ym9vdC9kdHMvb21hcDQ0NjAuZHRzaSB8IDUgKysrKysKIDEgZmlsZSBjaGFuZ2VkLCA1IGluc2Vy
dGlvbnMoKykKCmRpZmYgLS1naXQgYS9hcmNoL2FybS9ib290L2R0cy9vbWFwNDQ2MC5kdHNpIGIv
YXJjaC9hcm0vYm9vdC9kdHMvb21hcDQ0NjAuZHRzaQppbmRleCBjMmYwZjM5Li45ODU1ZjI5IDEw
MDY0NAotLS0gYS9hcmNoL2FybS9ib290L2R0cy9vbWFwNDQ2MC5kdHNpCisrKyBiL2FyY2gvYXJt
L2Jvb3QvZHRzL29tYXA0NDYwLmR0c2kKQEAgLTMwLDYgKzMwLDEwIEBACiAJCXRpLGh3bW9kcyA9
ICJkZWJ1Z3NzIjsKIAl9OwogCisJdGhlcm1hbF96b25lc3sKKwkJI2luY2x1ZGUgIm9tYXA0LWNw
dS10aGVybWFsLmR0c2kiCisJfTsKKwogCWJhbmRnYXAgewogCQlyZWcgPSA8MHg0YTAwMjI2MCAw
eDQKIAkJICAgICAgIDB4NGEwMDIzMkMgMHg0CkBAIC0zNyw1ICs0MSw2IEBACiAJCWNvbXBhdGli
bGUgPSAidGksb21hcDQ0NjAtYmFuZGdhcCI7CiAJCWludGVycnVwdHMgPSA8MCAxMjYgSVJRX1RZ
UEVfTEVWRUxfSElHSD47IC8qIHRhbGVydCAqLwogCQlncGlvcyA9IDwmZ3BpbzMgMjIgMD47IC8q
IHRzaHV0ICovCisJCW1vbml0b3JlZC16b25lcyA9IDwmY3B1X3RoZXJtYWwgMD47CiAJfTsKIH07
Ci0tIAoxLjguMi4xLjM0Mi5nZmE3Mjg1ZAoKCl9fX19fX19fX19fX19fX19fX19fX19fX19fX19f
X19fX19fX19fX19fX19fX19fCmxtLXNlbnNvcnMgbWFpbGluZyBsaXN0CmxtLXNlbnNvcnNAbG0t
c2Vuc29ycy5vcmcKaHR0cDovL2xpc3RzLmxtLXNlbnNvcnMub3JnL21haWxtYW4vbGlzdGluZm8v
bG0tc2Vuc29ycw=

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

* [RFC PATCH 09/14] arm: dts: point to cooling-zones on omap4430 cpu node
  2013-08-23 23:15 ` Eduardo Valentin
  (?)
  (?)
@ 2013-08-23 23:15   ` Eduardo Valentin
  -1 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-23 23:15 UTC (permalink / raw)
  To: swarren, pawel.moll, mark.rutland, ian.campbell, grant.likely,
	rob.herring, linux, rui.zhang, wni
  Cc: durgadoss.r, linux-pm, devicetree, lm-sensors, linux-kernel,
	Eduardo Valentin, Benoît Cousson, Tony Lindgren,
	Russell King, linux-omap, devicetree-discuss, linux-arm-kernel

OMAP4430 devices can reach high temperatures and thus
needs to have cpufreq-cooling on systems running on it.

This patch links the cpu node to its thermal-zone
so that cpufreq-cpu0 driver loads the cooling device.

Cc: "Benoît Cousson" <b-cousson@ti.com>
Cc: Tony Lindgren <tony@atomide.com>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: linux-omap@vger.kernel.org
Cc: devicetree-discuss@lists.ozlabs.org
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
---
 arch/arm/boot/dts/omap443x.dtsi | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/boot/dts/omap443x.dtsi b/arch/arm/boot/dts/omap443x.dtsi
index 91a3a5d..e4eea43 100644
--- a/arch/arm/boot/dts/omap443x.dtsi
+++ b/arch/arm/boot/dts/omap443x.dtsi
@@ -22,6 +22,7 @@
 				1008000 1375000
 			>;
 			clock-latency = <300000>; /* From legacy driver */
+			cooling-zones = <&cpu_thermal>;
 		};
 	};
 
-- 
1.8.2.1.342.gfa7285d


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

* [RFC PATCH 09/14] arm: dts: point to cooling-zones on omap4430 cpu node
@ 2013-08-23 23:15   ` Eduardo Valentin
  0 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-23 23:15 UTC (permalink / raw)
  To: swarren, pawel.moll, mark.rutland, ian.campbell, grant.likely,
	rob.herring, linux, rui.zhang, wni
  Cc: durgadoss.r, linux-pm, devicetree, lm-sensors, linux-kernel,
	Eduardo Valentin, Benoît Cousson, Tony Lindgren,
	Russell King, linux-omap, devicetree-discuss, linux-arm-kernel

OMAP4430 devices can reach high temperatures and thus
needs to have cpufreq-cooling on systems running on it.

This patch links the cpu node to its thermal-zone
so that cpufreq-cpu0 driver loads the cooling device.

Cc: "Benoît Cousson" <b-cousson@ti.com>
Cc: Tony Lindgren <tony@atomide.com>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: linux-omap@vger.kernel.org
Cc: devicetree-discuss@lists.ozlabs.org
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
---
 arch/arm/boot/dts/omap443x.dtsi | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/boot/dts/omap443x.dtsi b/arch/arm/boot/dts/omap443x.dtsi
index 91a3a5d..e4eea43 100644
--- a/arch/arm/boot/dts/omap443x.dtsi
+++ b/arch/arm/boot/dts/omap443x.dtsi
@@ -22,6 +22,7 @@
 				1008000 1375000
 			>;
 			clock-latency = <300000>; /* From legacy driver */
+			cooling-zones = <&cpu_thermal>;
 		};
 	};
 
-- 
1.8.2.1.342.gfa7285d

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

* [RFC PATCH 09/14] arm: dts: point to cooling-zones on omap4430 cpu node
@ 2013-08-23 23:15   ` Eduardo Valentin
  0 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-23 23:15 UTC (permalink / raw)
  To: linux-arm-kernel

OMAP4430 devices can reach high temperatures and thus
needs to have cpufreq-cooling on systems running on it.

This patch links the cpu node to its thermal-zone
so that cpufreq-cpu0 driver loads the cooling device.

Cc: "Beno?t Cousson" <b-cousson@ti.com>
Cc: Tony Lindgren <tony@atomide.com>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: linux-omap at vger.kernel.org
Cc: devicetree-discuss at lists.ozlabs.org
Cc: linux-arm-kernel at lists.infradead.org
Cc: linux-kernel at vger.kernel.org
Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
---
 arch/arm/boot/dts/omap443x.dtsi | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/boot/dts/omap443x.dtsi b/arch/arm/boot/dts/omap443x.dtsi
index 91a3a5d..e4eea43 100644
--- a/arch/arm/boot/dts/omap443x.dtsi
+++ b/arch/arm/boot/dts/omap443x.dtsi
@@ -22,6 +22,7 @@
 				1008000 1375000
 			>;
 			clock-latency = <300000>; /* From legacy driver */
+			cooling-zones = <&cpu_thermal>;
 		};
 	};
 
-- 
1.8.2.1.342.gfa7285d

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

* [lm-sensors] [RFC PATCH 09/14] arm: dts: point to cooling-zones on omap4430 cpu node
@ 2013-08-23 23:15   ` Eduardo Valentin
  0 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-23 23:15 UTC (permalink / raw)
  To: swarren, pawel.moll, mark.rutland, ian.campbell, grant.likely,
	rob.herring, linux, rui.zhang, wni
  Cc: durgadoss.r, linux-pm, devicetree, lm-sensors, linux-kernel,
	Eduardo Valentin, Benoît Cousson, Tony Lindgren,
	Russell King, linux-omap, devicetree-discuss, linux-arm-kernel

T01BUDQ0MzAgZGV2aWNlcyBjYW4gcmVhY2ggaGlnaCB0ZW1wZXJhdHVyZXMgYW5kIHRodXMKbmVl
ZHMgdG8gaGF2ZSBjcHVmcmVxLWNvb2xpbmcgb24gc3lzdGVtcyBydW5uaW5nIG9uIGl0LgoKVGhp
cyBwYXRjaCBsaW5rcyB0aGUgY3B1IG5vZGUgdG8gaXRzIHRoZXJtYWwtem9uZQpzbyB0aGF0IGNw
dWZyZXEtY3B1MCBkcml2ZXIgbG9hZHMgdGhlIGNvb2xpbmcgZGV2aWNlLgoKQ2M6ICJCZW5vw650
IENvdXNzb24iIDxiLWNvdXNzb25AdGkuY29tPgpDYzogVG9ueSBMaW5kZ3JlbiA8dG9ueUBhdG9t
aWRlLmNvbT4KQ2M6IFJ1c3NlbGwgS2luZyA8bGludXhAYXJtLmxpbnV4Lm9yZy51az4KQ2M6IGxp
bnV4LW9tYXBAdmdlci5rZXJuZWwub3JnCkNjOiBkZXZpY2V0cmVlLWRpc2N1c3NAbGlzdHMub3ps
YWJzLm9yZwpDYzogbGludXgtYXJtLWtlcm5lbEBsaXN0cy5pbmZyYWRlYWQub3JnCkNjOiBsaW51
eC1rZXJuZWxAdmdlci5rZXJuZWwub3JnClNpZ25lZC1vZmYtYnk6IEVkdWFyZG8gVmFsZW50aW4g
PGVkdWFyZG8udmFsZW50aW5AdGkuY29tPgotLS0KIGFyY2gvYXJtL2Jvb3QvZHRzL29tYXA0NDN4
LmR0c2kgfCAxICsKIDEgZmlsZSBjaGFuZ2VkLCAxIGluc2VydGlvbigrKQoKZGlmZiAtLWdpdCBh
L2FyY2gvYXJtL2Jvb3QvZHRzL29tYXA0NDN4LmR0c2kgYi9hcmNoL2FybS9ib290L2R0cy9vbWFw
NDQzeC5kdHNpCmluZGV4IDkxYTNhNWQuLmU0ZWVhNDMgMTAwNjQ0Ci0tLSBhL2FyY2gvYXJtL2Jv
b3QvZHRzL29tYXA0NDN4LmR0c2kKKysrIGIvYXJjaC9hcm0vYm9vdC9kdHMvb21hcDQ0M3guZHRz
aQpAQCAtMjIsNiArMjIsNyBAQAogCQkJCTEwMDgwMDAgMTM3NTAwMAogCQkJPjsKIAkJCWNsb2Nr
LWxhdGVuY3kgPSA8MzAwMDAwPjsgLyogRnJvbSBsZWdhY3kgZHJpdmVyICovCisJCQljb29saW5n
LXpvbmVzID0gPCZjcHVfdGhlcm1hbD47CiAJCX07CiAJfTsKIAotLSAKMS44LjIuMS4zNDIuZ2Zh
NzI4NWQKCgpfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXwps
bS1zZW5zb3JzIG1haWxpbmcgbGlzdApsbS1zZW5zb3JzQGxtLXNlbnNvcnMub3JnCmh0dHA6Ly9s
aXN0cy5sbS1zZW5zb3JzLm9yZy9tYWlsbWFuL2xpc3RpbmZvL2xtLXNlbnNvcnM

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

* [RFC PATCH 10/14] arm: dts: point to cooling-zones on omap4460 cpu node
  2013-08-23 23:15 ` Eduardo Valentin
  (?)
  (?)
@ 2013-08-23 23:15   ` Eduardo Valentin
  -1 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-23 23:15 UTC (permalink / raw)
  To: swarren, pawel.moll, mark.rutland, ian.campbell, grant.likely,
	rob.herring, linux, rui.zhang, wni
  Cc: durgadoss.r, linux-pm, devicetree, lm-sensors, linux-kernel,
	Eduardo Valentin, Benoît Cousson, Tony Lindgren,
	Russell King, linux-omap, linux-arm-kernel

OMAP4460 devices can reach high temperatures and thus
needs to have cpufreq-cooling on systems running on it.

This patch links the cpu node to its thermal-zone
so that cpufreq-cpu0 driver loads the cooling device.

Cc: "Benoît Cousson" <b-cousson@linaro.org>
Cc: Tony Lindgren <tony@atomide.com>
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: Pawel Moll <pawel.moll@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Stephen Warren <swarren@wwwdotorg.org>
Cc: Ian Campbell <ian.campbell@citrix.com>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: linux-omap@vger.kernel.org
Cc: devicetree@vger.kernel.org
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
---
 arch/arm/boot/dts/omap4460.dtsi | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/boot/dts/omap4460.dtsi b/arch/arm/boot/dts/omap4460.dtsi
index 9855f29..991bd1b 100644
--- a/arch/arm/boot/dts/omap4460.dtsi
+++ b/arch/arm/boot/dts/omap4460.dtsi
@@ -20,6 +20,7 @@
 				920000  1313000
 			>;
 			clock-latency = <300000>; /* From legacy driver */
+			cooling-zones = <&cpu_thermal>;
 		};
 	};
 
-- 
1.8.2.1.342.gfa7285d


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

* [RFC PATCH 10/14] arm: dts: point to cooling-zones on omap4460 cpu node
@ 2013-08-23 23:15   ` Eduardo Valentin
  0 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-23 23:15 UTC (permalink / raw)
  To: swarren, pawel.moll, mark.rutland, ian.campbell, grant.likely,
	rob.herring, linux, rui.zhang, wni
  Cc: durgadoss.r, linux-pm, devicetree, lm-sensors, linux-kernel,
	Eduardo Valentin, Benoît Cousson, Tony Lindgren,
	Russell King, linux-omap, linux-arm-kernel

OMAP4460 devices can reach high temperatures and thus
needs to have cpufreq-cooling on systems running on it.

This patch links the cpu node to its thermal-zone
so that cpufreq-cpu0 driver loads the cooling device.

Cc: "Benoît Cousson" <b-cousson@linaro.org>
Cc: Tony Lindgren <tony@atomide.com>
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: Pawel Moll <pawel.moll@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Stephen Warren <swarren@wwwdotorg.org>
Cc: Ian Campbell <ian.campbell@citrix.com>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: linux-omap@vger.kernel.org
Cc: devicetree@vger.kernel.org
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
---
 arch/arm/boot/dts/omap4460.dtsi | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/boot/dts/omap4460.dtsi b/arch/arm/boot/dts/omap4460.dtsi
index 9855f29..991bd1b 100644
--- a/arch/arm/boot/dts/omap4460.dtsi
+++ b/arch/arm/boot/dts/omap4460.dtsi
@@ -20,6 +20,7 @@
 				920000  1313000
 			>;
 			clock-latency = <300000>; /* From legacy driver */
+			cooling-zones = <&cpu_thermal>;
 		};
 	};
 
-- 
1.8.2.1.342.gfa7285d


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

* [RFC PATCH 10/14] arm: dts: point to cooling-zones on omap4460 cpu node
@ 2013-08-23 23:15   ` Eduardo Valentin
  0 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-23 23:15 UTC (permalink / raw)
  To: linux-arm-kernel

OMAP4460 devices can reach high temperatures and thus
needs to have cpufreq-cooling on systems running on it.

This patch links the cpu node to its thermal-zone
so that cpufreq-cpu0 driver loads the cooling device.

Cc: "Beno?t Cousson" <b-cousson@linaro.org>
Cc: Tony Lindgren <tony@atomide.com>
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: Pawel Moll <pawel.moll@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Stephen Warren <swarren@wwwdotorg.org>
Cc: Ian Campbell <ian.campbell@citrix.com>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: linux-omap at vger.kernel.org
Cc: devicetree at vger.kernel.org
Cc: linux-arm-kernel at lists.infradead.org
Cc: linux-kernel at vger.kernel.org
Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
---
 arch/arm/boot/dts/omap4460.dtsi | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/boot/dts/omap4460.dtsi b/arch/arm/boot/dts/omap4460.dtsi
index 9855f29..991bd1b 100644
--- a/arch/arm/boot/dts/omap4460.dtsi
+++ b/arch/arm/boot/dts/omap4460.dtsi
@@ -20,6 +20,7 @@
 				920000  1313000
 			>;
 			clock-latency = <300000>; /* From legacy driver */
+			cooling-zones = <&cpu_thermal>;
 		};
 	};
 
-- 
1.8.2.1.342.gfa7285d

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

* [lm-sensors] [RFC PATCH 10/14] arm: dts: point to cooling-zones on omap4460 cpu node
@ 2013-08-23 23:15   ` Eduardo Valentin
  0 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-23 23:15 UTC (permalink / raw)
  To: swarren, pawel.moll, mark.rutland, ian.campbell, grant.likely,
	rob.herring, linux, rui.zhang, wni
  Cc: durgadoss.r, linux-pm, devicetree, lm-sensors, linux-kernel,
	Eduardo Valentin, Benoît Cousson, Tony Lindgren,
	Russell King, linux-omap, linux-arm-kernel

T01BUDQ0NjAgZGV2aWNlcyBjYW4gcmVhY2ggaGlnaCB0ZW1wZXJhdHVyZXMgYW5kIHRodXMKbmVl
ZHMgdG8gaGF2ZSBjcHVmcmVxLWNvb2xpbmcgb24gc3lzdGVtcyBydW5uaW5nIG9uIGl0LgoKVGhp
cyBwYXRjaCBsaW5rcyB0aGUgY3B1IG5vZGUgdG8gaXRzIHRoZXJtYWwtem9uZQpzbyB0aGF0IGNw
dWZyZXEtY3B1MCBkcml2ZXIgbG9hZHMgdGhlIGNvb2xpbmcgZGV2aWNlLgoKQ2M6ICJCZW5vw650
IENvdXNzb24iIDxiLWNvdXNzb25AbGluYXJvLm9yZz4KQ2M6IFRvbnkgTGluZGdyZW4gPHRvbnlA
YXRvbWlkZS5jb20+CkNjOiBSb2IgSGVycmluZyA8cm9iLmhlcnJpbmdAY2FseGVkYS5jb20+CkNj
OiBQYXdlbCBNb2xsIDxwYXdlbC5tb2xsQGFybS5jb20+CkNjOiBNYXJrIFJ1dGxhbmQgPG1hcmsu
cnV0bGFuZEBhcm0uY29tPgpDYzogU3RlcGhlbiBXYXJyZW4gPHN3YXJyZW5Ad3d3ZG90b3JnLm9y
Zz4KQ2M6IElhbiBDYW1wYmVsbCA8aWFuLmNhbXBiZWxsQGNpdHJpeC5jb20+CkNjOiBSdXNzZWxs
IEtpbmcgPGxpbnV4QGFybS5saW51eC5vcmcudWs+CkNjOiBsaW51eC1vbWFwQHZnZXIua2VybmVs
Lm9yZwpDYzogZGV2aWNldHJlZUB2Z2VyLmtlcm5lbC5vcmcKQ2M6IGxpbnV4LWFybS1rZXJuZWxA
bGlzdHMuaW5mcmFkZWFkLm9yZwpDYzogbGludXgta2VybmVsQHZnZXIua2VybmVsLm9yZwpTaWdu
ZWQtb2ZmLWJ5OiBFZHVhcmRvIFZhbGVudGluIDxlZHVhcmRvLnZhbGVudGluQHRpLmNvbT4KLS0t
CiBhcmNoL2FybS9ib290L2R0cy9vbWFwNDQ2MC5kdHNpIHwgMSArCiAxIGZpbGUgY2hhbmdlZCwg
MSBpbnNlcnRpb24oKykKCmRpZmYgLS1naXQgYS9hcmNoL2FybS9ib290L2R0cy9vbWFwNDQ2MC5k
dHNpIGIvYXJjaC9hcm0vYm9vdC9kdHMvb21hcDQ0NjAuZHRzaQppbmRleCA5ODU1ZjI5Li45OTFi
ZDFiIDEwMDY0NAotLS0gYS9hcmNoL2FybS9ib290L2R0cy9vbWFwNDQ2MC5kdHNpCisrKyBiL2Fy
Y2gvYXJtL2Jvb3QvZHRzL29tYXA0NDYwLmR0c2kKQEAgLTIwLDYgKzIwLDcgQEAKIAkJCQk5MjAw
MDAgIDEzMTMwMDAKIAkJCT47CiAJCQljbG9jay1sYXRlbmN5ID0gPDMwMDAwMD47IC8qIEZyb20g
bGVnYWN5IGRyaXZlciAqLworCQkJY29vbGluZy16b25lcyA9IDwmY3B1X3RoZXJtYWw+OwogCQl9
OwogCX07CiAKLS0gCjEuOC4yLjEuMzQyLmdmYTcyODVkCgoKX19fX19fX19fX19fX19fX19fX19f
X19fX19fX19fX19fX19fX19fX19fX19fX18KbG0tc2Vuc29ycyBtYWlsaW5nIGxpc3QKbG0tc2Vu
c29yc0BsbS1zZW5zb3JzLm9yZwpodHRwOi8vbGlzdHMubG0tc2Vuc29ycy5vcmcvbWFpbG1hbi9s
aXN0aW5mby9sbS1zZW5zb3Jz

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

* [RFC PATCH 11/14] arm: dts: add omap5 GPU thermal data
  2013-08-23 23:15 ` Eduardo Valentin
  (?)
  (?)
@ 2013-08-23 23:15   ` Eduardo Valentin
  -1 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-23 23:15 UTC (permalink / raw)
  To: swarren, pawel.moll, mark.rutland, ian.campbell, grant.likely,
	rob.herring, linux, rui.zhang, wni
  Cc: durgadoss.r, linux-pm, devicetree, lm-sensors, linux-kernel,
	Eduardo Valentin, Benoît Cousson, Tony Lindgren,
	Russell King, linux-omap, linux-arm-kernel

This patch changes a dtsi file to contain the thermal data
for GPU domain on OMAP5 and later SoCs. This data will
enable a thermal shutdown at 125C.

This thermal data can be reused across TI SoC devices.

Cc: "Benoît Cousson" <b-cousson@linaro.org>
Cc: Tony Lindgren <tony@atomide.com>
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: Pawel Moll <pawel.moll@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Stephen Warren <swarren@wwwdotorg.org>
Cc: Ian Campbell <ian.campbell@citrix.com>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: linux-omap@vger.kernel.org
Cc: devicetree@vger.kernel.org
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
---
 arch/arm/boot/dts/omap5-gpu-thermal.dtsi | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)
 create mode 100644 arch/arm/boot/dts/omap5-gpu-thermal.dtsi

diff --git a/arch/arm/boot/dts/omap5-gpu-thermal.dtsi b/arch/arm/boot/dts/omap5-gpu-thermal.dtsi
new file mode 100644
index 0000000..f421492
--- /dev/null
+++ b/arch/arm/boot/dts/omap5-gpu-thermal.dtsi
@@ -0,0 +1,27 @@
+
+/*
+ * Device Tree Source for OMAP543x SoC GPU thermal
+ *
+ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
+ * Contact: Eduardo Valentin <eduardo.valentin@ti.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <dt-bindings/thermal/thermal.h>
+
+gpu_thermal: gpu_thermal {
+	#thermal-cells = <1>;
+	mask = <0x01>; /* trips writability */
+	passive_delay = <250>; /* milliseconds */
+	polling_delay = <1000>; /* milliseconds */
+	trips {
+		crit@125000{
+			temperature = <125000>; /* milliCelsius */
+			hysteresis = <2000>; /* milliCelsius */
+			type = <THERMAL_TRIP_CRITICAL>;
+		};
+	};
+};
-- 
1.8.2.1.342.gfa7285d


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

* [RFC PATCH 11/14] arm: dts: add omap5 GPU thermal data
@ 2013-08-23 23:15   ` Eduardo Valentin
  0 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-23 23:15 UTC (permalink / raw)
  To: swarren, pawel.moll, mark.rutland, ian.campbell, grant.likely,
	rob.herring, linux, rui.zhang, wni
  Cc: durgadoss.r, linux-pm, devicetree, lm-sensors, linux-kernel,
	Eduardo Valentin, Benoît Cousson, Tony Lindgren,
	Russell King, linux-omap, linux-arm-kernel

This patch changes a dtsi file to contain the thermal data
for GPU domain on OMAP5 and later SoCs. This data will
enable a thermal shutdown at 125C.

This thermal data can be reused across TI SoC devices.

Cc: "Benoît Cousson" <b-cousson@linaro.org>
Cc: Tony Lindgren <tony@atomide.com>
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: Pawel Moll <pawel.moll@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Stephen Warren <swarren@wwwdotorg.org>
Cc: Ian Campbell <ian.campbell@citrix.com>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: linux-omap@vger.kernel.org
Cc: devicetree@vger.kernel.org
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
---
 arch/arm/boot/dts/omap5-gpu-thermal.dtsi | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)
 create mode 100644 arch/arm/boot/dts/omap5-gpu-thermal.dtsi

diff --git a/arch/arm/boot/dts/omap5-gpu-thermal.dtsi b/arch/arm/boot/dts/omap5-gpu-thermal.dtsi
new file mode 100644
index 0000000..f421492
--- /dev/null
+++ b/arch/arm/boot/dts/omap5-gpu-thermal.dtsi
@@ -0,0 +1,27 @@
+
+/*
+ * Device Tree Source for OMAP543x SoC GPU thermal
+ *
+ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
+ * Contact: Eduardo Valentin <eduardo.valentin@ti.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <dt-bindings/thermal/thermal.h>
+
+gpu_thermal: gpu_thermal {
+	#thermal-cells = <1>;
+	mask = <0x01>; /* trips writability */
+	passive_delay = <250>; /* milliseconds */
+	polling_delay = <1000>; /* milliseconds */
+	trips {
+		crit@125000{
+			temperature = <125000>; /* milliCelsius */
+			hysteresis = <2000>; /* milliCelsius */
+			type = <THERMAL_TRIP_CRITICAL>;
+		};
+	};
+};
-- 
1.8.2.1.342.gfa7285d

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

* [RFC PATCH 11/14] arm: dts: add omap5 GPU thermal data
@ 2013-08-23 23:15   ` Eduardo Valentin
  0 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-23 23:15 UTC (permalink / raw)
  To: linux-arm-kernel

This patch changes a dtsi file to contain the thermal data
for GPU domain on OMAP5 and later SoCs. This data will
enable a thermal shutdown at 125C.

This thermal data can be reused across TI SoC devices.

Cc: "Beno?t Cousson" <b-cousson@linaro.org>
Cc: Tony Lindgren <tony@atomide.com>
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: Pawel Moll <pawel.moll@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Stephen Warren <swarren@wwwdotorg.org>
Cc: Ian Campbell <ian.campbell@citrix.com>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: linux-omap at vger.kernel.org
Cc: devicetree at vger.kernel.org
Cc: linux-arm-kernel at lists.infradead.org
Cc: linux-kernel at vger.kernel.org
Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
---
 arch/arm/boot/dts/omap5-gpu-thermal.dtsi | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)
 create mode 100644 arch/arm/boot/dts/omap5-gpu-thermal.dtsi

diff --git a/arch/arm/boot/dts/omap5-gpu-thermal.dtsi b/arch/arm/boot/dts/omap5-gpu-thermal.dtsi
new file mode 100644
index 0000000..f421492
--- /dev/null
+++ b/arch/arm/boot/dts/omap5-gpu-thermal.dtsi
@@ -0,0 +1,27 @@
+
+/*
+ * Device Tree Source for OMAP543x SoC GPU thermal
+ *
+ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
+ * Contact: Eduardo Valentin <eduardo.valentin@ti.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <dt-bindings/thermal/thermal.h>
+
+gpu_thermal: gpu_thermal {
+	#thermal-cells = <1>;
+	mask = <0x01>; /* trips writability */
+	passive_delay = <250>; /* milliseconds */
+	polling_delay = <1000>; /* milliseconds */
+	trips {
+		crit at 125000{
+			temperature = <125000>; /* milliCelsius */
+			hysteresis = <2000>; /* milliCelsius */
+			type = <THERMAL_TRIP_CRITICAL>;
+		};
+	};
+};
-- 
1.8.2.1.342.gfa7285d

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

* [lm-sensors] [RFC PATCH 11/14] arm: dts: add omap5 GPU thermal data
@ 2013-08-23 23:15   ` Eduardo Valentin
  0 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-23 23:15 UTC (permalink / raw)
  To: swarren, pawel.moll, mark.rutland, ian.campbell, grant.likely,
	rob.herring, linux, rui.zhang, wni
  Cc: durgadoss.r, linux-pm, devicetree, lm-sensors, linux-kernel,
	Eduardo Valentin, Benoît Cousson, Tony Lindgren,
	Russell King, linux-omap, linux-arm-kernel

VGhpcyBwYXRjaCBjaGFuZ2VzIGEgZHRzaSBmaWxlIHRvIGNvbnRhaW4gdGhlIHRoZXJtYWwgZGF0
YQpmb3IgR1BVIGRvbWFpbiBvbiBPTUFQNSBhbmQgbGF0ZXIgU29Dcy4gVGhpcyBkYXRhIHdpbGwK
ZW5hYmxlIGEgdGhlcm1hbCBzaHV0ZG93biBhdCAxMjVDLgoKVGhpcyB0aGVybWFsIGRhdGEgY2Fu
IGJlIHJldXNlZCBhY3Jvc3MgVEkgU29DIGRldmljZXMuCgpDYzogIkJlbm/DrnQgQ291c3NvbiIg
PGItY291c3NvbkBsaW5hcm8ub3JnPgpDYzogVG9ueSBMaW5kZ3JlbiA8dG9ueUBhdG9taWRlLmNv
bT4KQ2M6IFJvYiBIZXJyaW5nIDxyb2IuaGVycmluZ0BjYWx4ZWRhLmNvbT4KQ2M6IFBhd2VsIE1v
bGwgPHBhd2VsLm1vbGxAYXJtLmNvbT4KQ2M6IE1hcmsgUnV0bGFuZCA8bWFyay5ydXRsYW5kQGFy
bS5jb20+CkNjOiBTdGVwaGVuIFdhcnJlbiA8c3dhcnJlbkB3d3dkb3Rvcmcub3JnPgpDYzogSWFu
IENhbXBiZWxsIDxpYW4uY2FtcGJlbGxAY2l0cml4LmNvbT4KQ2M6IFJ1c3NlbGwgS2luZyA8bGlu
dXhAYXJtLmxpbnV4Lm9yZy51az4KQ2M6IGxpbnV4LW9tYXBAdmdlci5rZXJuZWwub3JnCkNjOiBk
ZXZpY2V0cmVlQHZnZXIua2VybmVsLm9yZwpDYzogbGludXgtYXJtLWtlcm5lbEBsaXN0cy5pbmZy
YWRlYWQub3JnCkNjOiBsaW51eC1rZXJuZWxAdmdlci5rZXJuZWwub3JnClNpZ25lZC1vZmYtYnk6
IEVkdWFyZG8gVmFsZW50aW4gPGVkdWFyZG8udmFsZW50aW5AdGkuY29tPgotLS0KIGFyY2gvYXJt
L2Jvb3QvZHRzL29tYXA1LWdwdS10aGVybWFsLmR0c2kgfCAyNyArKysrKysrKysrKysrKysrKysr
KysrKysrKysKIDEgZmlsZSBjaGFuZ2VkLCAyNyBpbnNlcnRpb25zKCspCiBjcmVhdGUgbW9kZSAx
MDA2NDQgYXJjaC9hcm0vYm9vdC9kdHMvb21hcDUtZ3B1LXRoZXJtYWwuZHRzaQoKZGlmZiAtLWdp
dCBhL2FyY2gvYXJtL2Jvb3QvZHRzL29tYXA1LWdwdS10aGVybWFsLmR0c2kgYi9hcmNoL2FybS9i
b290L2R0cy9vbWFwNS1ncHUtdGhlcm1hbC5kdHNpCm5ldyBmaWxlIG1vZGUgMTAwNjQ0CmluZGV4
IDAwMDAwMDAuLmY0MjE0OTIKLS0tIC9kZXYvbnVsbAorKysgYi9hcmNoL2FybS9ib290L2R0cy9v
bWFwNS1ncHUtdGhlcm1hbC5kdHNpCkBAIC0wLDAgKzEsMjcgQEAKKworLyoKKyAqIERldmljZSBU
cmVlIFNvdXJjZSBmb3IgT01BUDU0M3ggU29DIEdQVSB0aGVybWFsCisgKgorICogQ29weXJpZ2h0
IChDKSAyMDEzIFRleGFzIEluc3RydW1lbnRzIEluY29ycG9yYXRlZCAtIGh0dHA6Ly93d3cudGku
Y29tLworICogQ29udGFjdDogRWR1YXJkbyBWYWxlbnRpbiA8ZWR1YXJkby52YWxlbnRpbkB0aS5j
b20+CisgKgorICogVGhpcyBmaWxlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUg
R05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UKKyAqIHZlcnNpb24gMi4gIFRoaXMgcHJvZ3JhbSBp
cyBsaWNlbnNlZCAiYXMgaXMiIHdpdGhvdXQgYW55IHdhcnJhbnR5IG9mIGFueQorICoga2luZCwg
d2hldGhlciBleHByZXNzIG9yIGltcGxpZWQuCisgKi8KKworI2luY2x1ZGUgPGR0LWJpbmRpbmdz
L3RoZXJtYWwvdGhlcm1hbC5oPgorCitncHVfdGhlcm1hbDogZ3B1X3RoZXJtYWwgeworCSN0aGVy
bWFsLWNlbGxzID0gPDE+OworCW1hc2sgPSA8MHgwMT47IC8qIHRyaXBzIHdyaXRhYmlsaXR5ICov
CisJcGFzc2l2ZV9kZWxheSA9IDwyNTA+OyAvKiBtaWxsaXNlY29uZHMgKi8KKwlwb2xsaW5nX2Rl
bGF5ID0gPDEwMDA+OyAvKiBtaWxsaXNlY29uZHMgKi8KKwl0cmlwcyB7CisJCWNyaXRAMTI1MDAw
eworCQkJdGVtcGVyYXR1cmUgPSA8MTI1MDAwPjsgLyogbWlsbGlDZWxzaXVzICovCisJCQloeXN0
ZXJlc2lzID0gPDIwMDA+OyAvKiBtaWxsaUNlbHNpdXMgKi8KKwkJCXR5cGUgPSA8VEhFUk1BTF9U
UklQX0NSSVRJQ0FMPjsKKwkJfTsKKwl9OworfTsKLS0gCjEuOC4yLjEuMzQyLmdmYTcyODVkCgoK
X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KbG0tc2Vuc29y
cyBtYWlsaW5nIGxpc3QKbG0tc2Vuc29yc0BsbS1zZW5zb3JzLm9yZwpodHRwOi8vbGlzdHMubG0t
c2Vuc29ycy5vcmcvbWFpbG1hbi9saXN0aW5mby9sbS1zZW5zb3Jz

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

* [RFC PATCH 12/14] arm: dts: add omap5 CORE thermal data
  2013-08-23 23:15 ` Eduardo Valentin
  (?)
  (?)
@ 2013-08-23 23:15   ` Eduardo Valentin
  -1 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-23 23:15 UTC (permalink / raw)
  To: swarren, pawel.moll, mark.rutland, ian.campbell, grant.likely,
	rob.herring, linux, rui.zhang, wni
  Cc: durgadoss.r, linux-pm, devicetree, lm-sensors, linux-kernel,
	Eduardo Valentin, Benoît Cousson, Tony Lindgren,
	Russell King, linux-omap, linux-arm-kernel

This patch changes a dtsi file to contain the thermal data
for CORE domain on OMAP5 and later SoCs. This data will
enable a thermal shutdown at 125C.

This thermal data can be reused across TI SoC devices.

Cc: "Benoît Cousson" <b-cousson@ti.com>
Cc: Tony Lindgren <tony@atomide.com>
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: Pawel Moll <pawel.moll@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Stephen Warren <swarren@wwwdotorg.org>
Cc: Ian Campbell <ian.campbell@citrix.com>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: linux-omap@vger.kernel.org
Cc: devicetree@vger.kernel.org
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
---
 arch/arm/boot/dts/omap5-core-thermal.dtsi | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)
 create mode 100644 arch/arm/boot/dts/omap5-core-thermal.dtsi

diff --git a/arch/arm/boot/dts/omap5-core-thermal.dtsi b/arch/arm/boot/dts/omap5-core-thermal.dtsi
new file mode 100644
index 0000000..3d9fa09
--- /dev/null
+++ b/arch/arm/boot/dts/omap5-core-thermal.dtsi
@@ -0,0 +1,27 @@
+
+/*
+ * Device Tree Source for OMAP543x SoC CORE thermal
+ *
+ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
+ * Contact: Eduardo Valentin <eduardo.valentin@ti.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <dt-bindings/thermal/thermal.h>
+
+core_thermal: core_thermal {
+	#thermal-cells = <1>;
+	mask = <0x01>; /* trips writability */
+	passive_delay = <250>; /* milliseconds */
+	polling_delay = <1000>; /* milliseconds */
+	trips {
+		crit@125000{
+			temperature = <125000>; /* milliCelsius */
+			hysteresis = <2000>; /* milliCelsius */
+			type = <THERMAL_TRIP_CRITICAL>;
+		};
+	};
+};
-- 
1.8.2.1.342.gfa7285d


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

* [RFC PATCH 12/14] arm: dts: add omap5 CORE thermal data
@ 2013-08-23 23:15   ` Eduardo Valentin
  0 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-23 23:15 UTC (permalink / raw)
  To: swarren, pawel.moll, mark.rutland, ian.campbell, grant.likely,
	rob.herring, linux, rui.zhang, wni
  Cc: durgadoss.r, linux-pm, devicetree, lm-sensors, linux-kernel,
	Eduardo Valentin, Benoît Cousson, Tony Lindgren,
	Russell King, linux-omap, linux-arm-kernel

This patch changes a dtsi file to contain the thermal data
for CORE domain on OMAP5 and later SoCs. This data will
enable a thermal shutdown at 125C.

This thermal data can be reused across TI SoC devices.

Cc: "Benoît Cousson" <b-cousson@ti.com>
Cc: Tony Lindgren <tony@atomide.com>
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: Pawel Moll <pawel.moll@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Stephen Warren <swarren@wwwdotorg.org>
Cc: Ian Campbell <ian.campbell@citrix.com>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: linux-omap@vger.kernel.org
Cc: devicetree@vger.kernel.org
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
---
 arch/arm/boot/dts/omap5-core-thermal.dtsi | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)
 create mode 100644 arch/arm/boot/dts/omap5-core-thermal.dtsi

diff --git a/arch/arm/boot/dts/omap5-core-thermal.dtsi b/arch/arm/boot/dts/omap5-core-thermal.dtsi
new file mode 100644
index 0000000..3d9fa09
--- /dev/null
+++ b/arch/arm/boot/dts/omap5-core-thermal.dtsi
@@ -0,0 +1,27 @@
+
+/*
+ * Device Tree Source for OMAP543x SoC CORE thermal
+ *
+ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
+ * Contact: Eduardo Valentin <eduardo.valentin@ti.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <dt-bindings/thermal/thermal.h>
+
+core_thermal: core_thermal {
+	#thermal-cells = <1>;
+	mask = <0x01>; /* trips writability */
+	passive_delay = <250>; /* milliseconds */
+	polling_delay = <1000>; /* milliseconds */
+	trips {
+		crit@125000{
+			temperature = <125000>; /* milliCelsius */
+			hysteresis = <2000>; /* milliCelsius */
+			type = <THERMAL_TRIP_CRITICAL>;
+		};
+	};
+};
-- 
1.8.2.1.342.gfa7285d

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

* [RFC PATCH 12/14] arm: dts: add omap5 CORE thermal data
@ 2013-08-23 23:15   ` Eduardo Valentin
  0 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-23 23:15 UTC (permalink / raw)
  To: linux-arm-kernel

This patch changes a dtsi file to contain the thermal data
for CORE domain on OMAP5 and later SoCs. This data will
enable a thermal shutdown at 125C.

This thermal data can be reused across TI SoC devices.

Cc: "Beno?t Cousson" <b-cousson@ti.com>
Cc: Tony Lindgren <tony@atomide.com>
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: Pawel Moll <pawel.moll@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Stephen Warren <swarren@wwwdotorg.org>
Cc: Ian Campbell <ian.campbell@citrix.com>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: linux-omap at vger.kernel.org
Cc: devicetree at vger.kernel.org
Cc: linux-arm-kernel at lists.infradead.org
Cc: linux-kernel at vger.kernel.org
Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
---
 arch/arm/boot/dts/omap5-core-thermal.dtsi | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)
 create mode 100644 arch/arm/boot/dts/omap5-core-thermal.dtsi

diff --git a/arch/arm/boot/dts/omap5-core-thermal.dtsi b/arch/arm/boot/dts/omap5-core-thermal.dtsi
new file mode 100644
index 0000000..3d9fa09
--- /dev/null
+++ b/arch/arm/boot/dts/omap5-core-thermal.dtsi
@@ -0,0 +1,27 @@
+
+/*
+ * Device Tree Source for OMAP543x SoC CORE thermal
+ *
+ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
+ * Contact: Eduardo Valentin <eduardo.valentin@ti.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <dt-bindings/thermal/thermal.h>
+
+core_thermal: core_thermal {
+	#thermal-cells = <1>;
+	mask = <0x01>; /* trips writability */
+	passive_delay = <250>; /* milliseconds */
+	polling_delay = <1000>; /* milliseconds */
+	trips {
+		crit at 125000{
+			temperature = <125000>; /* milliCelsius */
+			hysteresis = <2000>; /* milliCelsius */
+			type = <THERMAL_TRIP_CRITICAL>;
+		};
+	};
+};
-- 
1.8.2.1.342.gfa7285d

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

* [lm-sensors] [RFC PATCH 12/14] arm: dts: add omap5 CORE thermal data
@ 2013-08-23 23:15   ` Eduardo Valentin
  0 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-23 23:15 UTC (permalink / raw)
  To: swarren, pawel.moll, mark.rutland, ian.campbell, grant.likely,
	rob.herring, linux, rui.zhang, wni
  Cc: durgadoss.r, linux-pm, devicetree, lm-sensors, linux-kernel,
	Eduardo Valentin, Benoît Cousson, Tony Lindgren,
	Russell King, linux-omap, linux-arm-kernel

VGhpcyBwYXRjaCBjaGFuZ2VzIGEgZHRzaSBmaWxlIHRvIGNvbnRhaW4gdGhlIHRoZXJtYWwgZGF0
YQpmb3IgQ09SRSBkb21haW4gb24gT01BUDUgYW5kIGxhdGVyIFNvQ3MuIFRoaXMgZGF0YSB3aWxs
CmVuYWJsZSBhIHRoZXJtYWwgc2h1dGRvd24gYXQgMTI1Qy4KClRoaXMgdGhlcm1hbCBkYXRhIGNh
biBiZSByZXVzZWQgYWNyb3NzIFRJIFNvQyBkZXZpY2VzLgoKQ2M6ICJCZW5vw650IENvdXNzb24i
IDxiLWNvdXNzb25AdGkuY29tPgpDYzogVG9ueSBMaW5kZ3JlbiA8dG9ueUBhdG9taWRlLmNvbT4K
Q2M6IFJvYiBIZXJyaW5nIDxyb2IuaGVycmluZ0BjYWx4ZWRhLmNvbT4KQ2M6IFBhd2VsIE1vbGwg
PHBhd2VsLm1vbGxAYXJtLmNvbT4KQ2M6IE1hcmsgUnV0bGFuZCA8bWFyay5ydXRsYW5kQGFybS5j
b20+CkNjOiBTdGVwaGVuIFdhcnJlbiA8c3dhcnJlbkB3d3dkb3Rvcmcub3JnPgpDYzogSWFuIENh
bXBiZWxsIDxpYW4uY2FtcGJlbGxAY2l0cml4LmNvbT4KQ2M6IFJ1c3NlbGwgS2luZyA8bGludXhA
YXJtLmxpbnV4Lm9yZy51az4KQ2M6IGxpbnV4LW9tYXBAdmdlci5rZXJuZWwub3JnCkNjOiBkZXZp
Y2V0cmVlQHZnZXIua2VybmVsLm9yZwpDYzogbGludXgtYXJtLWtlcm5lbEBsaXN0cy5pbmZyYWRl
YWQub3JnCkNjOiBsaW51eC1rZXJuZWxAdmdlci5rZXJuZWwub3JnClNpZ25lZC1vZmYtYnk6IEVk
dWFyZG8gVmFsZW50aW4gPGVkdWFyZG8udmFsZW50aW5AdGkuY29tPgotLS0KIGFyY2gvYXJtL2Jv
b3QvZHRzL29tYXA1LWNvcmUtdGhlcm1hbC5kdHNpIHwgMjcgKysrKysrKysrKysrKysrKysrKysr
KysrKysrCiAxIGZpbGUgY2hhbmdlZCwgMjcgaW5zZXJ0aW9ucygrKQogY3JlYXRlIG1vZGUgMTAw
NjQ0IGFyY2gvYXJtL2Jvb3QvZHRzL29tYXA1LWNvcmUtdGhlcm1hbC5kdHNpCgpkaWZmIC0tZ2l0
IGEvYXJjaC9hcm0vYm9vdC9kdHMvb21hcDUtY29yZS10aGVybWFsLmR0c2kgYi9hcmNoL2FybS9i
b290L2R0cy9vbWFwNS1jb3JlLXRoZXJtYWwuZHRzaQpuZXcgZmlsZSBtb2RlIDEwMDY0NAppbmRl
eCAwMDAwMDAwLi4zZDlmYTA5Ci0tLSAvZGV2L251bGwKKysrIGIvYXJjaC9hcm0vYm9vdC9kdHMv
b21hcDUtY29yZS10aGVybWFsLmR0c2kKQEAgLTAsMCArMSwyNyBAQAorCisvKgorICogRGV2aWNl
IFRyZWUgU291cmNlIGZvciBPTUFQNTQzeCBTb0MgQ09SRSB0aGVybWFsCisgKgorICogQ29weXJp
Z2h0IChDKSAyMDEzIFRleGFzIEluc3RydW1lbnRzIEluY29ycG9yYXRlZCAtIGh0dHA6Ly93d3cu
dGkuY29tLworICogQ29udGFjdDogRWR1YXJkbyBWYWxlbnRpbiA8ZWR1YXJkby52YWxlbnRpbkB0
aS5jb20+CisgKgorICogVGhpcyBmaWxlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSB0ZXJtcyBvZiB0
aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UKKyAqIHZlcnNpb24gMi4gIFRoaXMgcHJvZ3Jh
bSBpcyBsaWNlbnNlZCAiYXMgaXMiIHdpdGhvdXQgYW55IHdhcnJhbnR5IG9mIGFueQorICoga2lu
ZCwgd2hldGhlciBleHByZXNzIG9yIGltcGxpZWQuCisgKi8KKworI2luY2x1ZGUgPGR0LWJpbmRp
bmdzL3RoZXJtYWwvdGhlcm1hbC5oPgorCitjb3JlX3RoZXJtYWw6IGNvcmVfdGhlcm1hbCB7CisJ
I3RoZXJtYWwtY2VsbHMgPSA8MT47CisJbWFzayA9IDwweDAxPjsgLyogdHJpcHMgd3JpdGFiaWxp
dHkgKi8KKwlwYXNzaXZlX2RlbGF5ID0gPDI1MD47IC8qIG1pbGxpc2Vjb25kcyAqLworCXBvbGxp
bmdfZGVsYXkgPSA8MTAwMD47IC8qIG1pbGxpc2Vjb25kcyAqLworCXRyaXBzIHsKKwkJY3JpdEAx
MjUwMDB7CisJCQl0ZW1wZXJhdHVyZSA9IDwxMjUwMDA+OyAvKiBtaWxsaUNlbHNpdXMgKi8KKwkJ
CWh5c3RlcmVzaXMgPSA8MjAwMD47IC8qIG1pbGxpQ2Vsc2l1cyAqLworCQkJdHlwZSA9IDxUSEVS
TUFMX1RSSVBfQ1JJVElDQUw+OworCQl9OworCX07Cit9OwotLSAKMS44LjIuMS4zNDIuZ2ZhNzI4
NWQKCgpfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXwpsbS1z
ZW5zb3JzIG1haWxpbmcgbGlzdApsbS1zZW5zb3JzQGxtLXNlbnNvcnMub3JnCmh0dHA6Ly9saXN0
cy5sbS1zZW5zb3JzLm9yZy9tYWlsbWFuL2xpc3RpbmZvL2xtLXNlbnNvcnM

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

* [RFC PATCH 13/14] arm: dts: add omap5 thermal data
  2013-08-23 23:15 ` Eduardo Valentin
  (?)
  (?)
@ 2013-08-23 23:15   ` Eduardo Valentin
  -1 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-23 23:15 UTC (permalink / raw)
  To: swarren, pawel.moll, mark.rutland, ian.campbell, grant.likely,
	rob.herring, linux, rui.zhang, wni
  Cc: durgadoss.r, linux-pm, devicetree, lm-sensors, linux-kernel,
	Eduardo Valentin, Benoît Cousson, Tony Lindgren,
	Russell King, linux-omap, linux-arm-kernel

This patch changes the dtsi entry on omap5 to contain
the thermal data. This data will enable the passive
cooling with CPUfreq cooling device at 100C. The
system will do a thermal shutdown at 125C whenever
any of its sensors sees this level.

Cc: "Benoît Cousson" <b-cousson@linaro.org>
Cc: Tony Lindgren <tony@atomide.com>
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: Pawel Moll <pawel.moll@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Stephen Warren <swarren@wwwdotorg.org>
Cc: Ian Campbell <ian.campbell@citrix.com>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: linux-omap@vger.kernel.org
Cc: devicetree@vger.kernel.org
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
---
 arch/arm/boot/dts/omap5.dtsi | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/arch/arm/boot/dts/omap5.dtsi b/arch/arm/boot/dts/omap5.dtsi
index e643620..4a33fe0 100644
--- a/arch/arm/boot/dts/omap5.dtsi
+++ b/arch/arm/boot/dts/omap5.dtsi
@@ -45,6 +45,12 @@
 		};
 	};
 
+	thermal_zones {
+		#include "omap4-cpu-thermal.dtsi"
+		#include "omap5-gpu-thermal.dtsi"
+		#include "omap5-core-thermal.dtsi"
+	};
+
 	timer {
 		compatible = "arm,armv7-timer";
 		/* PPI secure/nonsecure IRQ */
@@ -711,6 +717,9 @@
 			       0x4a0023C0 0x3c>;
 			interrupts = <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>;
 			compatible = "ti,omap5430-bandgap";
+			monitored-zones = <&cpu_thermal 0>,
+					  <&gpu_thermal 1>,
+					  <&core_thermal 2>;
 		};
 	};
 };
-- 
1.8.2.1.342.gfa7285d


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

* [RFC PATCH 13/14] arm: dts: add omap5 thermal data
@ 2013-08-23 23:15   ` Eduardo Valentin
  0 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-23 23:15 UTC (permalink / raw)
  To: swarren, pawel.moll, mark.rutland, ian.campbell, grant.likely,
	rob.herring, linux, rui.zhang, wni
  Cc: durgadoss.r, linux-pm, devicetree, lm-sensors, linux-kernel,
	Eduardo Valentin, Benoît Cousson, Tony Lindgren,
	Russell King, linux-omap, linux-arm-kernel

This patch changes the dtsi entry on omap5 to contain
the thermal data. This data will enable the passive
cooling with CPUfreq cooling device at 100C. The
system will do a thermal shutdown at 125C whenever
any of its sensors sees this level.

Cc: "Benoît Cousson" <b-cousson@linaro.org>
Cc: Tony Lindgren <tony@atomide.com>
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: Pawel Moll <pawel.moll@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Stephen Warren <swarren@wwwdotorg.org>
Cc: Ian Campbell <ian.campbell@citrix.com>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: linux-omap@vger.kernel.org
Cc: devicetree@vger.kernel.org
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
---
 arch/arm/boot/dts/omap5.dtsi | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/arch/arm/boot/dts/omap5.dtsi b/arch/arm/boot/dts/omap5.dtsi
index e643620..4a33fe0 100644
--- a/arch/arm/boot/dts/omap5.dtsi
+++ b/arch/arm/boot/dts/omap5.dtsi
@@ -45,6 +45,12 @@
 		};
 	};
 
+	thermal_zones {
+		#include "omap4-cpu-thermal.dtsi"
+		#include "omap5-gpu-thermal.dtsi"
+		#include "omap5-core-thermal.dtsi"
+	};
+
 	timer {
 		compatible = "arm,armv7-timer";
 		/* PPI secure/nonsecure IRQ */
@@ -711,6 +717,9 @@
 			       0x4a0023C0 0x3c>;
 			interrupts = <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>;
 			compatible = "ti,omap5430-bandgap";
+			monitored-zones = <&cpu_thermal 0>,
+					  <&gpu_thermal 1>,
+					  <&core_thermal 2>;
 		};
 	};
 };
-- 
1.8.2.1.342.gfa7285d

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

* [RFC PATCH 13/14] arm: dts: add omap5 thermal data
@ 2013-08-23 23:15   ` Eduardo Valentin
  0 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-23 23:15 UTC (permalink / raw)
  To: linux-arm-kernel

This patch changes the dtsi entry on omap5 to contain
the thermal data. This data will enable the passive
cooling with CPUfreq cooling device at 100C. The
system will do a thermal shutdown at 125C whenever
any of its sensors sees this level.

Cc: "Beno?t Cousson" <b-cousson@linaro.org>
Cc: Tony Lindgren <tony@atomide.com>
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: Pawel Moll <pawel.moll@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Stephen Warren <swarren@wwwdotorg.org>
Cc: Ian Campbell <ian.campbell@citrix.com>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: linux-omap at vger.kernel.org
Cc: devicetree at vger.kernel.org
Cc: linux-arm-kernel at lists.infradead.org
Cc: linux-kernel at vger.kernel.org
Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
---
 arch/arm/boot/dts/omap5.dtsi | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/arch/arm/boot/dts/omap5.dtsi b/arch/arm/boot/dts/omap5.dtsi
index e643620..4a33fe0 100644
--- a/arch/arm/boot/dts/omap5.dtsi
+++ b/arch/arm/boot/dts/omap5.dtsi
@@ -45,6 +45,12 @@
 		};
 	};
 
+	thermal_zones {
+		#include "omap4-cpu-thermal.dtsi"
+		#include "omap5-gpu-thermal.dtsi"
+		#include "omap5-core-thermal.dtsi"
+	};
+
 	timer {
 		compatible = "arm,armv7-timer";
 		/* PPI secure/nonsecure IRQ */
@@ -711,6 +717,9 @@
 			       0x4a0023C0 0x3c>;
 			interrupts = <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>;
 			compatible = "ti,omap5430-bandgap";
+			monitored-zones = <&cpu_thermal 0>,
+					  <&gpu_thermal 1>,
+					  <&core_thermal 2>;
 		};
 	};
 };
-- 
1.8.2.1.342.gfa7285d

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

* [lm-sensors] [RFC PATCH 13/14] arm: dts: add omap5 thermal data
@ 2013-08-23 23:15   ` Eduardo Valentin
  0 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-23 23:15 UTC (permalink / raw)
  To: swarren, pawel.moll, mark.rutland, ian.campbell, grant.likely,
	rob.herring, linux, rui.zhang, wni
  Cc: durgadoss.r, linux-pm, devicetree, lm-sensors, linux-kernel,
	Eduardo Valentin, Benoît Cousson, Tony Lindgren,
	Russell King, linux-omap, linux-arm-kernel

VGhpcyBwYXRjaCBjaGFuZ2VzIHRoZSBkdHNpIGVudHJ5IG9uIG9tYXA1IHRvIGNvbnRhaW4KdGhl
IHRoZXJtYWwgZGF0YS4gVGhpcyBkYXRhIHdpbGwgZW5hYmxlIHRoZSBwYXNzaXZlCmNvb2xpbmcg
d2l0aCBDUFVmcmVxIGNvb2xpbmcgZGV2aWNlIGF0IDEwMEMuIFRoZQpzeXN0ZW0gd2lsbCBkbyBh
IHRoZXJtYWwgc2h1dGRvd24gYXQgMTI1QyB3aGVuZXZlcgphbnkgb2YgaXRzIHNlbnNvcnMgc2Vl
cyB0aGlzIGxldmVsLgoKQ2M6ICJCZW5vw650IENvdXNzb24iIDxiLWNvdXNzb25AbGluYXJvLm9y
Zz4KQ2M6IFRvbnkgTGluZGdyZW4gPHRvbnlAYXRvbWlkZS5jb20+CkNjOiBSb2IgSGVycmluZyA8
cm9iLmhlcnJpbmdAY2FseGVkYS5jb20+CkNjOiBQYXdlbCBNb2xsIDxwYXdlbC5tb2xsQGFybS5j
b20+CkNjOiBNYXJrIFJ1dGxhbmQgPG1hcmsucnV0bGFuZEBhcm0uY29tPgpDYzogU3RlcGhlbiBX
YXJyZW4gPHN3YXJyZW5Ad3d3ZG90b3JnLm9yZz4KQ2M6IElhbiBDYW1wYmVsbCA8aWFuLmNhbXBi
ZWxsQGNpdHJpeC5jb20+CkNjOiBSdXNzZWxsIEtpbmcgPGxpbnV4QGFybS5saW51eC5vcmcudWs+
CkNjOiBsaW51eC1vbWFwQHZnZXIua2VybmVsLm9yZwpDYzogZGV2aWNldHJlZUB2Z2VyLmtlcm5l
bC5vcmcKQ2M6IGxpbnV4LWFybS1rZXJuZWxAbGlzdHMuaW5mcmFkZWFkLm9yZwpDYzogbGludXgt
a2VybmVsQHZnZXIua2VybmVsLm9yZwpTaWduZWQtb2ZmLWJ5OiBFZHVhcmRvIFZhbGVudGluIDxl
ZHVhcmRvLnZhbGVudGluQHRpLmNvbT4KLS0tCiBhcmNoL2FybS9ib290L2R0cy9vbWFwNS5kdHNp
IHwgOSArKysrKysrKysKIDEgZmlsZSBjaGFuZ2VkLCA5IGluc2VydGlvbnMoKykKCmRpZmYgLS1n
aXQgYS9hcmNoL2FybS9ib290L2R0cy9vbWFwNS5kdHNpIGIvYXJjaC9hcm0vYm9vdC9kdHMvb21h
cDUuZHRzaQppbmRleCBlNjQzNjIwLi40YTMzZmUwIDEwMDY0NAotLS0gYS9hcmNoL2FybS9ib290
L2R0cy9vbWFwNS5kdHNpCisrKyBiL2FyY2gvYXJtL2Jvb3QvZHRzL29tYXA1LmR0c2kKQEAgLTQ1
LDYgKzQ1LDEyIEBACiAJCX07CiAJfTsKIAorCXRoZXJtYWxfem9uZXMgeworCQkjaW5jbHVkZSAi
b21hcDQtY3B1LXRoZXJtYWwuZHRzaSIKKwkJI2luY2x1ZGUgIm9tYXA1LWdwdS10aGVybWFsLmR0
c2kiCisJCSNpbmNsdWRlICJvbWFwNS1jb3JlLXRoZXJtYWwuZHRzaSIKKwl9OworCiAJdGltZXIg
ewogCQljb21wYXRpYmxlID0gImFybSxhcm12Ny10aW1lciI7CiAJCS8qIFBQSSBzZWN1cmUvbm9u
c2VjdXJlIElSUSAqLwpAQCAtNzExLDYgKzcxNyw5IEBACiAJCQkgICAgICAgMHg0YTAwMjNDMCAw
eDNjPjsKIAkJCWludGVycnVwdHMgPSA8R0lDX1NQSSAxMjYgSVJRX1RZUEVfTEVWRUxfSElHSD47
CiAJCQljb21wYXRpYmxlID0gInRpLG9tYXA1NDMwLWJhbmRnYXAiOworCQkJbW9uaXRvcmVkLXpv
bmVzID0gPCZjcHVfdGhlcm1hbCAwPiwKKwkJCQkJICA8JmdwdV90aGVybWFsIDE+LAorCQkJCQkg
IDwmY29yZV90aGVybWFsIDI+OwogCQl9OwogCX07CiB9OwotLSAKMS44LjIuMS4zNDIuZ2ZhNzI4
NWQKCgpfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXwpsbS1z
ZW5zb3JzIG1haWxpbmcgbGlzdApsbS1zZW5zb3JzQGxtLXNlbnNvcnMub3JnCmh0dHA6Ly9saXN0
cy5sbS1zZW5zb3JzLm9yZy9tYWlsbWFuL2xpc3RpbmZvL2xtLXNlbnNvcnM

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

* [RFC PATCH 14/14] arm: dts: point to cooling-zones on omap5 cpu node
  2013-08-23 23:15 ` Eduardo Valentin
  (?)
  (?)
@ 2013-08-23 23:15   ` Eduardo Valentin
  -1 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-23 23:15 UTC (permalink / raw)
  To: swarren, pawel.moll, mark.rutland, ian.campbell, grant.likely,
	rob.herring, linux, rui.zhang, wni
  Cc: durgadoss.r, linux-pm, devicetree, lm-sensors, linux-kernel,
	Eduardo Valentin, Benoît Cousson, Tony Lindgren,
	Russell King, linux-omap, linux-arm-kernel

OMAP5 devices can reach high temperatures and thus
needs to have cpufreq-cooling on systems running on it.

This patch links the cpu node to its thermal-zone
so that cpufreq-cpu0 driver loads the cooling device.

Cc: "Benoît Cousson" <b-cousson@linaro.org>
Cc: Tony Lindgren <tony@atomide.com>
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: Pawel Moll <pawel.moll@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Stephen Warren <swarren@wwwdotorg.org>
Cc: Ian Campbell <ian.campbell@citrix.com>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: linux-omap@vger.kernel.org
Cc: devicetree@vger.kernel.org
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
---
 arch/arm/boot/dts/omap5.dtsi | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/boot/dts/omap5.dtsi b/arch/arm/boot/dts/omap5.dtsi
index 4a33fe0..335fcea 100644
--- a/arch/arm/boot/dts/omap5.dtsi
+++ b/arch/arm/boot/dts/omap5.dtsi
@@ -37,6 +37,7 @@
 			device_type = "cpu";
 			compatible = "arm,cortex-a15";
 			reg = <0x0>;
+			cooling-zones = <&cpu_thermal>;
 		};
 		cpu@1 {
 			device_type = "cpu";
-- 
1.8.2.1.342.gfa7285d


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

* [RFC PATCH 14/14] arm: dts: point to cooling-zones on omap5 cpu node
@ 2013-08-23 23:15   ` Eduardo Valentin
  0 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-23 23:15 UTC (permalink / raw)
  To: swarren, pawel.moll, mark.rutland, ian.campbell, grant.likely,
	rob.herring, linux, rui.zhang, wni
  Cc: durgadoss.r, linux-pm, devicetree, lm-sensors, linux-kernel,
	Eduardo Valentin, Benoît Cousson, Tony Lindgren,
	Russell King, linux-omap, linux-arm-kernel

OMAP5 devices can reach high temperatures and thus
needs to have cpufreq-cooling on systems running on it.

This patch links the cpu node to its thermal-zone
so that cpufreq-cpu0 driver loads the cooling device.

Cc: "Benoît Cousson" <b-cousson@linaro.org>
Cc: Tony Lindgren <tony@atomide.com>
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: Pawel Moll <pawel.moll@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Stephen Warren <swarren@wwwdotorg.org>
Cc: Ian Campbell <ian.campbell@citrix.com>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: linux-omap@vger.kernel.org
Cc: devicetree@vger.kernel.org
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
---
 arch/arm/boot/dts/omap5.dtsi | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/boot/dts/omap5.dtsi b/arch/arm/boot/dts/omap5.dtsi
index 4a33fe0..335fcea 100644
--- a/arch/arm/boot/dts/omap5.dtsi
+++ b/arch/arm/boot/dts/omap5.dtsi
@@ -37,6 +37,7 @@
 			device_type = "cpu";
 			compatible = "arm,cortex-a15";
 			reg = <0x0>;
+			cooling-zones = <&cpu_thermal>;
 		};
 		cpu@1 {
 			device_type = "cpu";
-- 
1.8.2.1.342.gfa7285d

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

* [RFC PATCH 14/14] arm: dts: point to cooling-zones on omap5 cpu node
@ 2013-08-23 23:15   ` Eduardo Valentin
  0 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-23 23:15 UTC (permalink / raw)
  To: linux-arm-kernel

OMAP5 devices can reach high temperatures and thus
needs to have cpufreq-cooling on systems running on it.

This patch links the cpu node to its thermal-zone
so that cpufreq-cpu0 driver loads the cooling device.

Cc: "Beno?t Cousson" <b-cousson@linaro.org>
Cc: Tony Lindgren <tony@atomide.com>
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: Pawel Moll <pawel.moll@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Stephen Warren <swarren@wwwdotorg.org>
Cc: Ian Campbell <ian.campbell@citrix.com>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: linux-omap at vger.kernel.org
Cc: devicetree at vger.kernel.org
Cc: linux-arm-kernel at lists.infradead.org
Cc: linux-kernel at vger.kernel.org
Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
---
 arch/arm/boot/dts/omap5.dtsi | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/boot/dts/omap5.dtsi b/arch/arm/boot/dts/omap5.dtsi
index 4a33fe0..335fcea 100644
--- a/arch/arm/boot/dts/omap5.dtsi
+++ b/arch/arm/boot/dts/omap5.dtsi
@@ -37,6 +37,7 @@
 			device_type = "cpu";
 			compatible = "arm,cortex-a15";
 			reg = <0x0>;
+			cooling-zones = <&cpu_thermal>;
 		};
 		cpu at 1 {
 			device_type = "cpu";
-- 
1.8.2.1.342.gfa7285d

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

* [lm-sensors] [RFC PATCH 14/14] arm: dts: point to cooling-zones on omap5 cpu node
@ 2013-08-23 23:15   ` Eduardo Valentin
  0 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-23 23:15 UTC (permalink / raw)
  To: swarren, pawel.moll, mark.rutland, ian.campbell, grant.likely,
	rob.herring, linux, rui.zhang, wni
  Cc: durgadoss.r, linux-pm, devicetree, lm-sensors, linux-kernel,
	Eduardo Valentin, Benoît Cousson, Tony Lindgren,
	Russell King, linux-omap, linux-arm-kernel

T01BUDUgZGV2aWNlcyBjYW4gcmVhY2ggaGlnaCB0ZW1wZXJhdHVyZXMgYW5kIHRodXMKbmVlZHMg
dG8gaGF2ZSBjcHVmcmVxLWNvb2xpbmcgb24gc3lzdGVtcyBydW5uaW5nIG9uIGl0LgoKVGhpcyBw
YXRjaCBsaW5rcyB0aGUgY3B1IG5vZGUgdG8gaXRzIHRoZXJtYWwtem9uZQpzbyB0aGF0IGNwdWZy
ZXEtY3B1MCBkcml2ZXIgbG9hZHMgdGhlIGNvb2xpbmcgZGV2aWNlLgoKQ2M6ICJCZW5vw650IENv
dXNzb24iIDxiLWNvdXNzb25AbGluYXJvLm9yZz4KQ2M6IFRvbnkgTGluZGdyZW4gPHRvbnlAYXRv
bWlkZS5jb20+CkNjOiBSb2IgSGVycmluZyA8cm9iLmhlcnJpbmdAY2FseGVkYS5jb20+CkNjOiBQ
YXdlbCBNb2xsIDxwYXdlbC5tb2xsQGFybS5jb20+CkNjOiBNYXJrIFJ1dGxhbmQgPG1hcmsucnV0
bGFuZEBhcm0uY29tPgpDYzogU3RlcGhlbiBXYXJyZW4gPHN3YXJyZW5Ad3d3ZG90b3JnLm9yZz4K
Q2M6IElhbiBDYW1wYmVsbCA8aWFuLmNhbXBiZWxsQGNpdHJpeC5jb20+CkNjOiBSdXNzZWxsIEtp
bmcgPGxpbnV4QGFybS5saW51eC5vcmcudWs+CkNjOiBsaW51eC1vbWFwQHZnZXIua2VybmVsLm9y
ZwpDYzogZGV2aWNldHJlZUB2Z2VyLmtlcm5lbC5vcmcKQ2M6IGxpbnV4LWFybS1rZXJuZWxAbGlz
dHMuaW5mcmFkZWFkLm9yZwpDYzogbGludXgta2VybmVsQHZnZXIua2VybmVsLm9yZwpTaWduZWQt
b2ZmLWJ5OiBFZHVhcmRvIFZhbGVudGluIDxlZHVhcmRvLnZhbGVudGluQHRpLmNvbT4KLS0tCiBh
cmNoL2FybS9ib290L2R0cy9vbWFwNS5kdHNpIHwgMSArCiAxIGZpbGUgY2hhbmdlZCwgMSBpbnNl
cnRpb24oKykKCmRpZmYgLS1naXQgYS9hcmNoL2FybS9ib290L2R0cy9vbWFwNS5kdHNpIGIvYXJj
aC9hcm0vYm9vdC9kdHMvb21hcDUuZHRzaQppbmRleCA0YTMzZmUwLi4zMzVmY2VhIDEwMDY0NAot
LS0gYS9hcmNoL2FybS9ib290L2R0cy9vbWFwNS5kdHNpCisrKyBiL2FyY2gvYXJtL2Jvb3QvZHRz
L29tYXA1LmR0c2kKQEAgLTM3LDYgKzM3LDcgQEAKIAkJCWRldmljZV90eXBlID0gImNwdSI7CiAJ
CQljb21wYXRpYmxlID0gImFybSxjb3J0ZXgtYTE1IjsKIAkJCXJlZyA9IDwweDA+OworCQkJY29v
bGluZy16b25lcyA9IDwmY3B1X3RoZXJtYWw+OwogCQl9OwogCQljcHVAMSB7CiAJCQlkZXZpY2Vf
dHlwZSA9ICJjcHUiOwotLSAKMS44LjIuMS4zNDIuZ2ZhNzI4NWQKCgpfX19fX19fX19fX19fX19f
X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXwpsbS1zZW5zb3JzIG1haWxpbmcgbGlzdAps
bS1zZW5zb3JzQGxtLXNlbnNvcnMub3JnCmh0dHA6Ly9saXN0cy5sbS1zZW5zb3JzLm9yZy9tYWls
bWFuL2xpc3RpbmZvL2xtLXNlbnNvcnM

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

* Re: [RFC PATCH 03/14] hwmon: lm75: expose to thermal fw via DT nodes
  2013-08-23 23:15   ` Eduardo Valentin
@ 2013-08-23 23:39     ` Guenter Roeck
  -1 siblings, 0 replies; 100+ messages in thread
From: Guenter Roeck @ 2013-08-23 23:39 UTC (permalink / raw)
  To: Eduardo Valentin
  Cc: swarren, pawel.moll, mark.rutland, ian.campbell, grant.likely,
	rob.herring, rui.zhang, wni, durgadoss.r, linux-pm, devicetree,
	lm-sensors, linux-kernel, Jean Delvare

On Fri, Aug 23, 2013 at 07:15:44PM -0400, Eduardo Valentin wrote:
> This patch adds to lm75 temperature sensor the possibility
> to expose itself as thermal zone device, registered on the
> thermal framework.
> 
> The thermal zone is built only if a device tree node
> describing a thermal zone for this sensor is present
> inside the lm75 DT node. Otherwise, the driver behavior
> will be the same.
> 
> Cc: Jean Delvare <khali@linux-fr.org>
> Cc: Guenter Roeck <linux@roeck-us.net>
> Cc: lm-sensors@lm-sensors.org
> Cc: linux-kernel@vger.kernel.org
> Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
> ---
>  drivers/hwmon/lm75.c | 31 +++++++++++++++++++++++++++++++
>  1 file changed, 31 insertions(+)
> 
> diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c
> index c03b490..dc55908 100644
> --- a/drivers/hwmon/lm75.c
> +++ b/drivers/hwmon/lm75.c
> @@ -27,6 +27,8 @@
>  #include <linux/hwmon-sysfs.h>
>  #include <linux/err.h>
>  #include <linux/mutex.h>
> +#include <linux/thermal.h>
> +#include <linux/of.h>
>  #include "lm75.h"
>  
>  
> @@ -70,6 +72,7 @@ static const u8 LM75_REG_TEMP[3] = {
>  /* Each client has this additional data */
>  struct lm75_data {
>  	struct device		*hwmon_dev;
> +	struct thermal_zone_device	*tz;
>  	struct mutex		update_lock;
>  	u8			orig_conf;
>  	u8			resolution;	/* In bits, between 9 and 12 */
> @@ -92,6 +95,19 @@ static struct lm75_data *lm75_update_device(struct device *dev);
>  
>  /* sysfs attributes for hwmon */
>  
> +static int lm75_read_temp(void *dev, unsigned long *temp)
> +{
> +	struct lm75_data *data = lm75_update_device(dev);
> +
> +	if (IS_ERR(data))
> +		return PTR_ERR(data);
> +
> +	*temp = ((data->temp[0] >> (16 - data->resolution)) * 1000) >>
> +			(data->resolution - 8);
> +
> +	return 0;
> +}
> +
>  static ssize_t show_temp(struct device *dev, struct device_attribute *da,
>  			 char *buf)
>  {
> @@ -271,11 +287,25 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id)
>  		goto exit_remove;
>  	}
>  
> +	if (of_find_property(client->dev.of_node, "monitored-zones", NULL)) {
> +		data->tz = thermal_zone_of_device_register(&client->dev,
> +							   0,
> +							   false, /* -hwmon */
> +							   &client->dev,
> +							   lm75_read_temp);
> +		if (IS_ERR(data->tz)) {
> +			status = PTR_ERR(data->tz);
> +			goto exit_hwmon;
> +		}
> +	}
> +
I don't think it should be fatal if thermal_zone_of_device_register fails.
hwmon itself still works fine, and should not be penaltized for a thermal
subsystem failure. Better display a warning if that happens and don't bail out.

The same comment applies to all patches affecting the hwmon subsystem.

>  	dev_info(&client->dev, "%s: sensor '%s'\n",
>  		 dev_name(data->hwmon_dev), client->name);
>  
>  	return 0;
>  
> +exit_hwmon:
> +	hwmon_device_unregister(data->hwmon_dev);
>  exit_remove:
>  	sysfs_remove_group(&client->dev.kobj, &lm75_group);
>  	return status;
> @@ -285,6 +315,7 @@ static int lm75_remove(struct i2c_client *client)
>  {
>  	struct lm75_data *data = i2c_get_clientdata(client);
>  
> +	thermal_zone_device_unregister(data->tz);
>  	hwmon_device_unregister(data->hwmon_dev);
>  	sysfs_remove_group(&client->dev.kobj, &lm75_group);
>  	lm75_write_value(client, LM75_REG_CONF, data->orig_conf);
> -- 
> 1.8.2.1.342.gfa7285d
> 
> 

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

* Re: [lm-sensors] [RFC PATCH 03/14] hwmon: lm75: expose to thermal fw via DT nodes
@ 2013-08-23 23:39     ` Guenter Roeck
  0 siblings, 0 replies; 100+ messages in thread
From: Guenter Roeck @ 2013-08-23 23:39 UTC (permalink / raw)
  To: Eduardo Valentin
  Cc: swarren, pawel.moll, mark.rutland, ian.campbell, grant.likely,
	rob.herring, rui.zhang, wni, durgadoss.r, linux-pm, devicetree,
	lm-sensors, linux-kernel, Jean Delvare

On Fri, Aug 23, 2013 at 07:15:44PM -0400, Eduardo Valentin wrote:
> This patch adds to lm75 temperature sensor the possibility
> to expose itself as thermal zone device, registered on the
> thermal framework.
> 
> The thermal zone is built only if a device tree node
> describing a thermal zone for this sensor is present
> inside the lm75 DT node. Otherwise, the driver behavior
> will be the same.
> 
> Cc: Jean Delvare <khali@linux-fr.org>
> Cc: Guenter Roeck <linux@roeck-us.net>
> Cc: lm-sensors@lm-sensors.org
> Cc: linux-kernel@vger.kernel.org
> Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
> ---
>  drivers/hwmon/lm75.c | 31 +++++++++++++++++++++++++++++++
>  1 file changed, 31 insertions(+)
> 
> diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c
> index c03b490..dc55908 100644
> --- a/drivers/hwmon/lm75.c
> +++ b/drivers/hwmon/lm75.c
> @@ -27,6 +27,8 @@
>  #include <linux/hwmon-sysfs.h>
>  #include <linux/err.h>
>  #include <linux/mutex.h>
> +#include <linux/thermal.h>
> +#include <linux/of.h>
>  #include "lm75.h"
>  
>  
> @@ -70,6 +72,7 @@ static const u8 LM75_REG_TEMP[3] = {
>  /* Each client has this additional data */
>  struct lm75_data {
>  	struct device		*hwmon_dev;
> +	struct thermal_zone_device	*tz;
>  	struct mutex		update_lock;
>  	u8			orig_conf;
>  	u8			resolution;	/* In bits, between 9 and 12 */
> @@ -92,6 +95,19 @@ static struct lm75_data *lm75_update_device(struct device *dev);
>  
>  /* sysfs attributes for hwmon */
>  
> +static int lm75_read_temp(void *dev, unsigned long *temp)
> +{
> +	struct lm75_data *data = lm75_update_device(dev);
> +
> +	if (IS_ERR(data))
> +		return PTR_ERR(data);
> +
> +	*temp = ((data->temp[0] >> (16 - data->resolution)) * 1000) >>
> +			(data->resolution - 8);
> +
> +	return 0;
> +}
> +
>  static ssize_t show_temp(struct device *dev, struct device_attribute *da,
>  			 char *buf)
>  {
> @@ -271,11 +287,25 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id)
>  		goto exit_remove;
>  	}
>  
> +	if (of_find_property(client->dev.of_node, "monitored-zones", NULL)) {
> +		data->tz = thermal_zone_of_device_register(&client->dev,
> +							   0,
> +							   false, /* -hwmon */
> +							   &client->dev,
> +							   lm75_read_temp);
> +		if (IS_ERR(data->tz)) {
> +			status = PTR_ERR(data->tz);
> +			goto exit_hwmon;
> +		}
> +	}
> +
I don't think it should be fatal if thermal_zone_of_device_register fails.
hwmon itself still works fine, and should not be penaltized for a thermal
subsystem failure. Better display a warning if that happens and don't bail out.

The same comment applies to all patches affecting the hwmon subsystem.

>  	dev_info(&client->dev, "%s: sensor '%s'\n",
>  		 dev_name(data->hwmon_dev), client->name);
>  
>  	return 0;
>  
> +exit_hwmon:
> +	hwmon_device_unregister(data->hwmon_dev);
>  exit_remove:
>  	sysfs_remove_group(&client->dev.kobj, &lm75_group);
>  	return status;
> @@ -285,6 +315,7 @@ static int lm75_remove(struct i2c_client *client)
>  {
>  	struct lm75_data *data = i2c_get_clientdata(client);
>  
> +	thermal_zone_device_unregister(data->tz);
>  	hwmon_device_unregister(data->hwmon_dev);
>  	sysfs_remove_group(&client->dev.kobj, &lm75_group);
>  	lm75_write_value(client, LM75_REG_CONF, data->orig_conf);
> -- 
> 1.8.2.1.342.gfa7285d
> 
> 

_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

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

* Re: [RFC PATCH 03/14] hwmon: lm75: expose to thermal fw via DT nodes
  2013-08-23 23:15   ` Eduardo Valentin
@ 2013-08-23 23:50     ` Guenter Roeck
  -1 siblings, 0 replies; 100+ messages in thread
From: Guenter Roeck @ 2013-08-23 23:50 UTC (permalink / raw)
  To: Eduardo Valentin
  Cc: swarren, pawel.moll, mark.rutland, ian.campbell, grant.likely,
	rob.herring, rui.zhang, wni, durgadoss.r, linux-pm, devicetree,
	lm-sensors, linux-kernel, Jean Delvare

On Fri, Aug 23, 2013 at 07:15:44PM -0400, Eduardo Valentin wrote:
> This patch adds to lm75 temperature sensor the possibility
> to expose itself as thermal zone device, registered on the
> thermal framework.
> 
> The thermal zone is built only if a device tree node
> describing a thermal zone for this sensor is present
> inside the lm75 DT node. Otherwise, the driver behavior
> will be the same.
> 
> Cc: Jean Delvare <khali@linux-fr.org>
> Cc: Guenter Roeck <linux@roeck-us.net>
> Cc: lm-sensors@lm-sensors.org
> Cc: linux-kernel@vger.kernel.org
> Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
> ---
>  drivers/hwmon/lm75.c | 31 +++++++++++++++++++++++++++++++
>  1 file changed, 31 insertions(+)
> 
> diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c
> index c03b490..dc55908 100644
> --- a/drivers/hwmon/lm75.c
> +++ b/drivers/hwmon/lm75.c
> @@ -27,6 +27,8 @@
>  #include <linux/hwmon-sysfs.h>
>  #include <linux/err.h>
>  #include <linux/mutex.h>
> +#include <linux/thermal.h>
> +#include <linux/of.h>
>  #include "lm75.h"
>  
>  
> @@ -70,6 +72,7 @@ static const u8 LM75_REG_TEMP[3] = {
>  /* Each client has this additional data */
>  struct lm75_data {
>  	struct device		*hwmon_dev;
> +	struct thermal_zone_device	*tz;
>  	struct mutex		update_lock;
>  	u8			orig_conf;
>  	u8			resolution;	/* In bits, between 9 and 12 */
> @@ -92,6 +95,19 @@ static struct lm75_data *lm75_update_device(struct device *dev);
>  
>  /* sysfs attributes for hwmon */
>  
> +static int lm75_read_temp(void *dev, unsigned long *temp)
> +{
> +	struct lm75_data *data = lm75_update_device(dev);
> +
> +	if (IS_ERR(data))
> +		return PTR_ERR(data);
> +
> +	*temp = ((data->temp[0] >> (16 - data->resolution)) * 1000) >>
> +			(data->resolution - 8);
> +
The reported temperature can be negative, which would result in reporting a very
high temperature (note this applies to the tmp102 driver patch as well).

The computation is quite complex and matches the computation done in show_temp().
Given that, it would make sense to declare an inline function to convert the
register value to the temperature. This function can take the register value
and the resolution as argument.

Guenter

> +	return 0;
> +}
> +
>  static ssize_t show_temp(struct device *dev, struct device_attribute *da,
>  			 char *buf)
>  {
> @@ -271,11 +287,25 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id)
>  		goto exit_remove;
>  	}
>  
> +	if (of_find_property(client->dev.of_node, "monitored-zones", NULL)) {
> +		data->tz = thermal_zone_of_device_register(&client->dev,
> +							   0,
> +							   false, /* -hwmon */
> +							   &client->dev,
> +							   lm75_read_temp);
> +		if (IS_ERR(data->tz)) {
> +			status = PTR_ERR(data->tz);
> +			goto exit_hwmon;
> +		}
> +	}
> +
>  	dev_info(&client->dev, "%s: sensor '%s'\n",
>  		 dev_name(data->hwmon_dev), client->name);
>  
>  	return 0;
>  
> +exit_hwmon:
> +	hwmon_device_unregister(data->hwmon_dev);
>  exit_remove:
>  	sysfs_remove_group(&client->dev.kobj, &lm75_group);
>  	return status;
> @@ -285,6 +315,7 @@ static int lm75_remove(struct i2c_client *client)
>  {
>  	struct lm75_data *data = i2c_get_clientdata(client);
>  
> +	thermal_zone_device_unregister(data->tz);
>  	hwmon_device_unregister(data->hwmon_dev);
>  	sysfs_remove_group(&client->dev.kobj, &lm75_group);
>  	lm75_write_value(client, LM75_REG_CONF, data->orig_conf);
> -- 
> 1.8.2.1.342.gfa7285d
> 
> 

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

* Re: [lm-sensors] [RFC PATCH 03/14] hwmon: lm75: expose to thermal fw via DT nodes
@ 2013-08-23 23:50     ` Guenter Roeck
  0 siblings, 0 replies; 100+ messages in thread
From: Guenter Roeck @ 2013-08-23 23:50 UTC (permalink / raw)
  To: Eduardo Valentin
  Cc: swarren, pawel.moll, mark.rutland, ian.campbell, grant.likely,
	rob.herring, rui.zhang, wni, durgadoss.r, linux-pm, devicetree,
	lm-sensors, linux-kernel, Jean Delvare

On Fri, Aug 23, 2013 at 07:15:44PM -0400, Eduardo Valentin wrote:
> This patch adds to lm75 temperature sensor the possibility
> to expose itself as thermal zone device, registered on the
> thermal framework.
> 
> The thermal zone is built only if a device tree node
> describing a thermal zone for this sensor is present
> inside the lm75 DT node. Otherwise, the driver behavior
> will be the same.
> 
> Cc: Jean Delvare <khali@linux-fr.org>
> Cc: Guenter Roeck <linux@roeck-us.net>
> Cc: lm-sensors@lm-sensors.org
> Cc: linux-kernel@vger.kernel.org
> Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
> ---
>  drivers/hwmon/lm75.c | 31 +++++++++++++++++++++++++++++++
>  1 file changed, 31 insertions(+)
> 
> diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c
> index c03b490..dc55908 100644
> --- a/drivers/hwmon/lm75.c
> +++ b/drivers/hwmon/lm75.c
> @@ -27,6 +27,8 @@
>  #include <linux/hwmon-sysfs.h>
>  #include <linux/err.h>
>  #include <linux/mutex.h>
> +#include <linux/thermal.h>
> +#include <linux/of.h>
>  #include "lm75.h"
>  
>  
> @@ -70,6 +72,7 @@ static const u8 LM75_REG_TEMP[3] = {
>  /* Each client has this additional data */
>  struct lm75_data {
>  	struct device		*hwmon_dev;
> +	struct thermal_zone_device	*tz;
>  	struct mutex		update_lock;
>  	u8			orig_conf;
>  	u8			resolution;	/* In bits, between 9 and 12 */
> @@ -92,6 +95,19 @@ static struct lm75_data *lm75_update_device(struct device *dev);
>  
>  /* sysfs attributes for hwmon */
>  
> +static int lm75_read_temp(void *dev, unsigned long *temp)
> +{
> +	struct lm75_data *data = lm75_update_device(dev);
> +
> +	if (IS_ERR(data))
> +		return PTR_ERR(data);
> +
> +	*temp = ((data->temp[0] >> (16 - data->resolution)) * 1000) >>
> +			(data->resolution - 8);
> +
The reported temperature can be negative, which would result in reporting a very
high temperature (note this applies to the tmp102 driver patch as well).

The computation is quite complex and matches the computation done in show_temp().
Given that, it would make sense to declare an inline function to convert the
register value to the temperature. This function can take the register value
and the resolution as argument.

Guenter

> +	return 0;
> +}
> +
>  static ssize_t show_temp(struct device *dev, struct device_attribute *da,
>  			 char *buf)
>  {
> @@ -271,11 +287,25 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id)
>  		goto exit_remove;
>  	}
>  
> +	if (of_find_property(client->dev.of_node, "monitored-zones", NULL)) {
> +		data->tz = thermal_zone_of_device_register(&client->dev,
> +							   0,
> +							   false, /* -hwmon */
> +							   &client->dev,
> +							   lm75_read_temp);
> +		if (IS_ERR(data->tz)) {
> +			status = PTR_ERR(data->tz);
> +			goto exit_hwmon;
> +		}
> +	}
> +
>  	dev_info(&client->dev, "%s: sensor '%s'\n",
>  		 dev_name(data->hwmon_dev), client->name);
>  
>  	return 0;
>  
> +exit_hwmon:
> +	hwmon_device_unregister(data->hwmon_dev);
>  exit_remove:
>  	sysfs_remove_group(&client->dev.kobj, &lm75_group);
>  	return status;
> @@ -285,6 +315,7 @@ static int lm75_remove(struct i2c_client *client)
>  {
>  	struct lm75_data *data = i2c_get_clientdata(client);
>  
> +	thermal_zone_device_unregister(data->tz);
>  	hwmon_device_unregister(data->hwmon_dev);
>  	sysfs_remove_group(&client->dev.kobj, &lm75_group);
>  	lm75_write_value(client, LM75_REG_CONF, data->orig_conf);
> -- 
> 1.8.2.1.342.gfa7285d
> 
> 

_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

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

* Re: [RFC PATCH 01/14] cpufreq: cpufreq-cpu0: add dt node parsing for 'cooling-zones'
  2013-08-23 23:15   ` Eduardo Valentin
@ 2013-08-26  4:54     ` Viresh Kumar
  -1 siblings, 0 replies; 100+ messages in thread
From: Viresh Kumar @ 2013-08-26  4:42 UTC (permalink / raw)
  To: Eduardo Valentin
  Cc: Stephen Warren, Pawel Moll, Mark Rutland, Ian Campbell,
	Grant Likely, Rob Herring, Guenter Roeck, Zhang Rui, wni, R,
	Durgadoss, linux-pm, devicetree, lm-sensors,
	Linux Kernel Mailing List, Rafael J. Wysocki, cpufreq,
	devicetree-discuss

On 24 August 2013 04:45, Eduardo Valentin <eduardo.valentin@ti.com> wrote:
> diff --git a/drivers/cpufreq/cpufreq-cpu0.c b/drivers/cpufreq/cpufreq-cpu0.c
> index ad1fde2..ede6487 100644
> --- a/drivers/cpufreq/cpufreq-cpu0.c
> +++ b/drivers/cpufreq/cpufreq-cpu0.c
> @@ -20,6 +20,9 @@
>  #include <linux/platform_device.h>
>  #include <linux/regulator/consumer.h>
>  #include <linux/slab.h>
> +#include <linux/thermal.h>
> +#include <linux/cpu_cooling.h>
> +#include <linux/cpumask.h>

In alphabetical order please..

> @@ -268,6 +272,13 @@ static int cpu0_cpufreq_probe(struct platform_device *pdev)
>                 goto out_free_table;
>         }
>
> +       /*
> +        * For now, just loading the cooling device;
> +        * thermal DT code takes care of matching them.
> +        */
> +       if (of_find_property(np, "cooling-zones", NULL))
> +               cdev = cpufreq_cooling_register(cpu_present_mask);

Should we check if it passed or failed? And if failed Atleast flag an
appropriate message?

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

* Re: [lm-sensors] [RFC PATCH 01/14] cpufreq: cpufreq-cpu0: add dt node parsing for 'cooling-zones'
@ 2013-08-26  4:54     ` Viresh Kumar
  0 siblings, 0 replies; 100+ messages in thread
From: Viresh Kumar @ 2013-08-26  4:54 UTC (permalink / raw)
  To: Eduardo Valentin
  Cc: Stephen Warren, Pawel Moll, Mark Rutland, Ian Campbell,
	Grant Likely, Rob Herring, Guenter Roeck, Zhang Rui, wni, R,
	Durgadoss, linux-pm, devicetree, lm-sensors,
	Linux Kernel Mailing List, Rafael J. Wysocki, cpufreq,
	devicetree-discuss

On 24 August 2013 04:45, Eduardo Valentin <eduardo.valentin@ti.com> wrote:
> diff --git a/drivers/cpufreq/cpufreq-cpu0.c b/drivers/cpufreq/cpufreq-cpu0.c
> index ad1fde2..ede6487 100644
> --- a/drivers/cpufreq/cpufreq-cpu0.c
> +++ b/drivers/cpufreq/cpufreq-cpu0.c
> @@ -20,6 +20,9 @@
>  #include <linux/platform_device.h>
>  #include <linux/regulator/consumer.h>
>  #include <linux/slab.h>
> +#include <linux/thermal.h>
> +#include <linux/cpu_cooling.h>
> +#include <linux/cpumask.h>

In alphabetical order please..

> @@ -268,6 +272,13 @@ static int cpu0_cpufreq_probe(struct platform_device *pdev)
>                 goto out_free_table;
>         }
>
> +       /*
> +        * For now, just loading the cooling device;
> +        * thermal DT code takes care of matching them.
> +        */
> +       if (of_find_property(np, "cooling-zones", NULL))
> +               cdev = cpufreq_cooling_register(cpu_present_mask);

Should we check if it passed or failed? And if failed Atleast flag an
appropriate message?

_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

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

* Re: [RFC PATCH 03/14] hwmon: lm75: expose to thermal fw via DT nodes
  2013-08-23 23:39     ` [lm-sensors] " Guenter Roeck
  (?)
@ 2013-08-26 12:11       ` Eduardo Valentin
  -1 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-26 12:11 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Eduardo Valentin, swarren, pawel.moll, mark.rutland,
	ian.campbell, grant.likely, rob.herring, rui.zhang, wni,
	durgadoss.r, linux-pm, devicetree, lm-sensors, linux-kernel,
	Jean Delvare

[-- Attachment #1: Type: text/plain, Size: 4080 bytes --]

On 23-08-2013 19:39, Guenter Roeck wrote:
> On Fri, Aug 23, 2013 at 07:15:44PM -0400, Eduardo Valentin wrote:
>> This patch adds to lm75 temperature sensor the possibility
>> to expose itself as thermal zone device, registered on the
>> thermal framework.
>>
>> The thermal zone is built only if a device tree node
>> describing a thermal zone for this sensor is present
>> inside the lm75 DT node. Otherwise, the driver behavior
>> will be the same.
>>
>> Cc: Jean Delvare <khali@linux-fr.org>
>> Cc: Guenter Roeck <linux@roeck-us.net>
>> Cc: lm-sensors@lm-sensors.org
>> Cc: linux-kernel@vger.kernel.org
>> Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
>> ---
>>  drivers/hwmon/lm75.c | 31 +++++++++++++++++++++++++++++++
>>  1 file changed, 31 insertions(+)
>>
>> diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c
>> index c03b490..dc55908 100644
>> --- a/drivers/hwmon/lm75.c
>> +++ b/drivers/hwmon/lm75.c
>> @@ -27,6 +27,8 @@
>>  #include <linux/hwmon-sysfs.h>
>>  #include <linux/err.h>
>>  #include <linux/mutex.h>
>> +#include <linux/thermal.h>
>> +#include <linux/of.h>
>>  #include "lm75.h"
>>  
>>  
>> @@ -70,6 +72,7 @@ static const u8 LM75_REG_TEMP[3] = {
>>  /* Each client has this additional data */
>>  struct lm75_data {
>>  	struct device		*hwmon_dev;
>> +	struct thermal_zone_device	*tz;
>>  	struct mutex		update_lock;
>>  	u8			orig_conf;
>>  	u8			resolution;	/* In bits, between 9 and 12 */
>> @@ -92,6 +95,19 @@ static struct lm75_data *lm75_update_device(struct device *dev);
>>  
>>  /* sysfs attributes for hwmon */
>>  
>> +static int lm75_read_temp(void *dev, unsigned long *temp)
>> +{
>> +	struct lm75_data *data = lm75_update_device(dev);
>> +
>> +	if (IS_ERR(data))
>> +		return PTR_ERR(data);
>> +
>> +	*temp = ((data->temp[0] >> (16 - data->resolution)) * 1000) >>
>> +			(data->resolution - 8);
>> +
>> +	return 0;
>> +}
>> +
>>  static ssize_t show_temp(struct device *dev, struct device_attribute *da,
>>  			 char *buf)
>>  {
>> @@ -271,11 +287,25 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id)
>>  		goto exit_remove;
>>  	}
>>  
>> +	if (of_find_property(client->dev.of_node, "monitored-zones", NULL)) {
>> +		data->tz = thermal_zone_of_device_register(&client->dev,
>> +							   0,
>> +							   false, /* -hwmon */
>> +							   &client->dev,
>> +							   lm75_read_temp);
>> +		if (IS_ERR(data->tz)) {
>> +			status = PTR_ERR(data->tz);
>> +			goto exit_hwmon;
>> +		}
>> +	}
>> +
> I don't think it should be fatal if thermal_zone_of_device_register fails.
> hwmon itself still works fine, and should not be penaltized for a thermal
> subsystem failure. Better display a warning if that happens and don't bail out.
> 
> The same comment applies to all patches affecting the hwmon subsystem.
> 


OK. Sounds reasonable to me. I am going to simply attempt to parse the
DT node, and in case it fails, will log it and continue, as you suggest:
+	data->tz = thermal_zone_of_device_register(&client->dev,
+						   0,
+						   false, /* -hwmon */
+						   &client->dev,
+						   lm75_read_temp);
+	if (IS_ERR(data->tz))
+		dev_warn(&client->dev, "Could not parse device tree thermal data\n");

>>  	dev_info(&client->dev, "%s: sensor '%s'\n",
>>  		 dev_name(data->hwmon_dev), client->name);
>>  
>>  	return 0;
>>  
>> +exit_hwmon:
>> +	hwmon_device_unregister(data->hwmon_dev);
>>  exit_remove:
>>  	sysfs_remove_group(&client->dev.kobj, &lm75_group);
>>  	return status;
>> @@ -285,6 +315,7 @@ static int lm75_remove(struct i2c_client *client)
>>  {
>>  	struct lm75_data *data = i2c_get_clientdata(client);
>>  
>> +	thermal_zone_device_unregister(data->tz);
>>  	hwmon_device_unregister(data->hwmon_dev);
>>  	sysfs_remove_group(&client->dev.kobj, &lm75_group);
>>  	lm75_write_value(client, LM75_REG_CONF, data->orig_conf);
>> -- 
>> 1.8.2.1.342.gfa7285d
>>
>>
> 
> 


-- 
You have got to be excited about what you are doing. (L. Lamport)

Eduardo Valentin


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 295 bytes --]

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

* Re: [RFC PATCH 03/14] hwmon: lm75: expose to thermal fw via DT nodes
@ 2013-08-26 12:11       ` Eduardo Valentin
  0 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-26 12:11 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Eduardo Valentin, swarren, pawel.moll, mark.rutland,
	ian.campbell, grant.likely, rob.herring, rui.zhang, wni,
	durgadoss.r, linux-pm, devicetree, lm-sensors, linux-kernel,
	Jean Delvare

[-- Attachment #1: Type: text/plain, Size: 4080 bytes --]

On 23-08-2013 19:39, Guenter Roeck wrote:
> On Fri, Aug 23, 2013 at 07:15:44PM -0400, Eduardo Valentin wrote:
>> This patch adds to lm75 temperature sensor the possibility
>> to expose itself as thermal zone device, registered on the
>> thermal framework.
>>
>> The thermal zone is built only if a device tree node
>> describing a thermal zone for this sensor is present
>> inside the lm75 DT node. Otherwise, the driver behavior
>> will be the same.
>>
>> Cc: Jean Delvare <khali@linux-fr.org>
>> Cc: Guenter Roeck <linux@roeck-us.net>
>> Cc: lm-sensors@lm-sensors.org
>> Cc: linux-kernel@vger.kernel.org
>> Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
>> ---
>>  drivers/hwmon/lm75.c | 31 +++++++++++++++++++++++++++++++
>>  1 file changed, 31 insertions(+)
>>
>> diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c
>> index c03b490..dc55908 100644
>> --- a/drivers/hwmon/lm75.c
>> +++ b/drivers/hwmon/lm75.c
>> @@ -27,6 +27,8 @@
>>  #include <linux/hwmon-sysfs.h>
>>  #include <linux/err.h>
>>  #include <linux/mutex.h>
>> +#include <linux/thermal.h>
>> +#include <linux/of.h>
>>  #include "lm75.h"
>>  
>>  
>> @@ -70,6 +72,7 @@ static const u8 LM75_REG_TEMP[3] = {
>>  /* Each client has this additional data */
>>  struct lm75_data {
>>  	struct device		*hwmon_dev;
>> +	struct thermal_zone_device	*tz;
>>  	struct mutex		update_lock;
>>  	u8			orig_conf;
>>  	u8			resolution;	/* In bits, between 9 and 12 */
>> @@ -92,6 +95,19 @@ static struct lm75_data *lm75_update_device(struct device *dev);
>>  
>>  /* sysfs attributes for hwmon */
>>  
>> +static int lm75_read_temp(void *dev, unsigned long *temp)
>> +{
>> +	struct lm75_data *data = lm75_update_device(dev);
>> +
>> +	if (IS_ERR(data))
>> +		return PTR_ERR(data);
>> +
>> +	*temp = ((data->temp[0] >> (16 - data->resolution)) * 1000) >>
>> +			(data->resolution - 8);
>> +
>> +	return 0;
>> +}
>> +
>>  static ssize_t show_temp(struct device *dev, struct device_attribute *da,
>>  			 char *buf)
>>  {
>> @@ -271,11 +287,25 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id)
>>  		goto exit_remove;
>>  	}
>>  
>> +	if (of_find_property(client->dev.of_node, "monitored-zones", NULL)) {
>> +		data->tz = thermal_zone_of_device_register(&client->dev,
>> +							   0,
>> +							   false, /* -hwmon */
>> +							   &client->dev,
>> +							   lm75_read_temp);
>> +		if (IS_ERR(data->tz)) {
>> +			status = PTR_ERR(data->tz);
>> +			goto exit_hwmon;
>> +		}
>> +	}
>> +
> I don't think it should be fatal if thermal_zone_of_device_register fails.
> hwmon itself still works fine, and should not be penaltized for a thermal
> subsystem failure. Better display a warning if that happens and don't bail out.
> 
> The same comment applies to all patches affecting the hwmon subsystem.
> 


OK. Sounds reasonable to me. I am going to simply attempt to parse the
DT node, and in case it fails, will log it and continue, as you suggest:
+	data->tz = thermal_zone_of_device_register(&client->dev,
+						   0,
+						   false, /* -hwmon */
+						   &client->dev,
+						   lm75_read_temp);
+	if (IS_ERR(data->tz))
+		dev_warn(&client->dev, "Could not parse device tree thermal data\n");

>>  	dev_info(&client->dev, "%s: sensor '%s'\n",
>>  		 dev_name(data->hwmon_dev), client->name);
>>  
>>  	return 0;
>>  
>> +exit_hwmon:
>> +	hwmon_device_unregister(data->hwmon_dev);
>>  exit_remove:
>>  	sysfs_remove_group(&client->dev.kobj, &lm75_group);
>>  	return status;
>> @@ -285,6 +315,7 @@ static int lm75_remove(struct i2c_client *client)
>>  {
>>  	struct lm75_data *data = i2c_get_clientdata(client);
>>  
>> +	thermal_zone_device_unregister(data->tz);
>>  	hwmon_device_unregister(data->hwmon_dev);
>>  	sysfs_remove_group(&client->dev.kobj, &lm75_group);
>>  	lm75_write_value(client, LM75_REG_CONF, data->orig_conf);
>> -- 
>> 1.8.2.1.342.gfa7285d
>>
>>
> 
> 


-- 
You have got to be excited about what you are doing. (L. Lamport)

Eduardo Valentin


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 295 bytes --]

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

* Re: [lm-sensors] [RFC PATCH 03/14] hwmon: lm75: expose to thermal fw via DT nodes
@ 2013-08-26 12:11       ` Eduardo Valentin
  0 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-26 12:11 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Eduardo Valentin, swarren, pawel.moll, mark.rutland,
	ian.campbell, grant.likely, rob.herring, rui.zhang, wni,
	durgadoss.r, linux-pm, devicetree, lm-sensors, linux-kernel,
	Jean Delvare


[-- Attachment #1.1: Type: text/plain, Size: 4080 bytes --]

On 23-08-2013 19:39, Guenter Roeck wrote:
> On Fri, Aug 23, 2013 at 07:15:44PM -0400, Eduardo Valentin wrote:
>> This patch adds to lm75 temperature sensor the possibility
>> to expose itself as thermal zone device, registered on the
>> thermal framework.
>>
>> The thermal zone is built only if a device tree node
>> describing a thermal zone for this sensor is present
>> inside the lm75 DT node. Otherwise, the driver behavior
>> will be the same.
>>
>> Cc: Jean Delvare <khali@linux-fr.org>
>> Cc: Guenter Roeck <linux@roeck-us.net>
>> Cc: lm-sensors@lm-sensors.org
>> Cc: linux-kernel@vger.kernel.org
>> Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
>> ---
>>  drivers/hwmon/lm75.c | 31 +++++++++++++++++++++++++++++++
>>  1 file changed, 31 insertions(+)
>>
>> diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c
>> index c03b490..dc55908 100644
>> --- a/drivers/hwmon/lm75.c
>> +++ b/drivers/hwmon/lm75.c
>> @@ -27,6 +27,8 @@
>>  #include <linux/hwmon-sysfs.h>
>>  #include <linux/err.h>
>>  #include <linux/mutex.h>
>> +#include <linux/thermal.h>
>> +#include <linux/of.h>
>>  #include "lm75.h"
>>  
>>  
>> @@ -70,6 +72,7 @@ static const u8 LM75_REG_TEMP[3] = {
>>  /* Each client has this additional data */
>>  struct lm75_data {
>>  	struct device		*hwmon_dev;
>> +	struct thermal_zone_device	*tz;
>>  	struct mutex		update_lock;
>>  	u8			orig_conf;
>>  	u8			resolution;	/* In bits, between 9 and 12 */
>> @@ -92,6 +95,19 @@ static struct lm75_data *lm75_update_device(struct device *dev);
>>  
>>  /* sysfs attributes for hwmon */
>>  
>> +static int lm75_read_temp(void *dev, unsigned long *temp)
>> +{
>> +	struct lm75_data *data = lm75_update_device(dev);
>> +
>> +	if (IS_ERR(data))
>> +		return PTR_ERR(data);
>> +
>> +	*temp = ((data->temp[0] >> (16 - data->resolution)) * 1000) >>
>> +			(data->resolution - 8);
>> +
>> +	return 0;
>> +}
>> +
>>  static ssize_t show_temp(struct device *dev, struct device_attribute *da,
>>  			 char *buf)
>>  {
>> @@ -271,11 +287,25 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id)
>>  		goto exit_remove;
>>  	}
>>  
>> +	if (of_find_property(client->dev.of_node, "monitored-zones", NULL)) {
>> +		data->tz = thermal_zone_of_device_register(&client->dev,
>> +							   0,
>> +							   false, /* -hwmon */
>> +							   &client->dev,
>> +							   lm75_read_temp);
>> +		if (IS_ERR(data->tz)) {
>> +			status = PTR_ERR(data->tz);
>> +			goto exit_hwmon;
>> +		}
>> +	}
>> +
> I don't think it should be fatal if thermal_zone_of_device_register fails.
> hwmon itself still works fine, and should not be penaltized for a thermal
> subsystem failure. Better display a warning if that happens and don't bail out.
> 
> The same comment applies to all patches affecting the hwmon subsystem.
> 


OK. Sounds reasonable to me. I am going to simply attempt to parse the
DT node, and in case it fails, will log it and continue, as you suggest:
+	data->tz = thermal_zone_of_device_register(&client->dev,
+						   0,
+						   false, /* -hwmon */
+						   &client->dev,
+						   lm75_read_temp);
+	if (IS_ERR(data->tz))
+		dev_warn(&client->dev, "Could not parse device tree thermal data\n");

>>  	dev_info(&client->dev, "%s: sensor '%s'\n",
>>  		 dev_name(data->hwmon_dev), client->name);
>>  
>>  	return 0;
>>  
>> +exit_hwmon:
>> +	hwmon_device_unregister(data->hwmon_dev);
>>  exit_remove:
>>  	sysfs_remove_group(&client->dev.kobj, &lm75_group);
>>  	return status;
>> @@ -285,6 +315,7 @@ static int lm75_remove(struct i2c_client *client)
>>  {
>>  	struct lm75_data *data = i2c_get_clientdata(client);
>>  
>> +	thermal_zone_device_unregister(data->tz);
>>  	hwmon_device_unregister(data->hwmon_dev);
>>  	sysfs_remove_group(&client->dev.kobj, &lm75_group);
>>  	lm75_write_value(client, LM75_REG_CONF, data->orig_conf);
>> -- 
>> 1.8.2.1.342.gfa7285d
>>
>>
> 
> 


-- 
You have got to be excited about what you are doing. (L. Lamport)

Eduardo Valentin


[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 295 bytes --]

[-- Attachment #2: Type: text/plain, Size: 153 bytes --]

_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

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

* Re: [RFC PATCH 01/14] cpufreq: cpufreq-cpu0: add dt node parsing for 'cooling-zones'
  2013-08-26  4:54     ` [lm-sensors] " Viresh Kumar
  (?)
@ 2013-08-26 12:13       ` Eduardo Valentin
  -1 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-26 12:13 UTC (permalink / raw)
  To: Viresh Kumar
  Cc: Eduardo Valentin, Stephen Warren, Pawel Moll, Mark Rutland,
	Ian Campbell, Grant Likely, Rob Herring, Guenter Roeck,
	Zhang Rui, wni, R, Durgadoss, linux-pm, devicetree, lm-sensors,
	Linux Kernel Mailing List, Rafael J. Wysocki, cpufreq,
	devicetree-discuss

[-- Attachment #1: Type: text/plain, Size: 1314 bytes --]

On 26-08-2013 00:42, Viresh Kumar wrote:
> On 24 August 2013 04:45, Eduardo Valentin <eduardo.valentin@ti.com> wrote:
>> diff --git a/drivers/cpufreq/cpufreq-cpu0.c b/drivers/cpufreq/cpufreq-cpu0.c
>> index ad1fde2..ede6487 100644
>> --- a/drivers/cpufreq/cpufreq-cpu0.c
>> +++ b/drivers/cpufreq/cpufreq-cpu0.c
>> @@ -20,6 +20,9 @@
>>  #include <linux/platform_device.h>
>>  #include <linux/regulator/consumer.h>
>>  #include <linux/slab.h>
>> +#include <linux/thermal.h>
>> +#include <linux/cpu_cooling.h>
>> +#include <linux/cpumask.h>
> 
> In alphabetical order please..
> 

OK.

>> @@ -268,6 +272,13 @@ static int cpu0_cpufreq_probe(struct platform_device *pdev)
>>                 goto out_free_table;
>>         }
>>
>> +       /*
>> +        * For now, just loading the cooling device;
>> +        * thermal DT code takes care of matching them.
>> +        */
>> +       if (of_find_property(np, "cooling-zones", NULL))
>> +               cdev = cpufreq_cooling_register(cpu_present_mask);
> 
> Should we check if it passed or failed? And if failed Atleast flag an
> appropriate message?
> 

Yes, we need error checking code. I will add in next version. Thanks Kumar.

> 


-- 
You have got to be excited about what you are doing. (L. Lamport)

Eduardo Valentin


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 295 bytes --]

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

* Re: [RFC PATCH 01/14] cpufreq: cpufreq-cpu0: add dt node parsing for 'cooling-zones'
@ 2013-08-26 12:13       ` Eduardo Valentin
  0 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-26 12:13 UTC (permalink / raw)
  To: Viresh Kumar
  Cc: Eduardo Valentin, Stephen Warren, Pawel Moll, Mark Rutland,
	Ian Campbell, Grant Likely, Rob Herring, Guenter Roeck,
	Zhang Rui, wni, R, Durgadoss, linux-pm, devicetree, lm-sensors,
	Linux Kernel Mailing List, Rafael J. Wysocki, cpufreq,
	devicetree-discuss

[-- Attachment #1: Type: text/plain, Size: 1314 bytes --]

On 26-08-2013 00:42, Viresh Kumar wrote:
> On 24 August 2013 04:45, Eduardo Valentin <eduardo.valentin@ti.com> wrote:
>> diff --git a/drivers/cpufreq/cpufreq-cpu0.c b/drivers/cpufreq/cpufreq-cpu0.c
>> index ad1fde2..ede6487 100644
>> --- a/drivers/cpufreq/cpufreq-cpu0.c
>> +++ b/drivers/cpufreq/cpufreq-cpu0.c
>> @@ -20,6 +20,9 @@
>>  #include <linux/platform_device.h>
>>  #include <linux/regulator/consumer.h>
>>  #include <linux/slab.h>
>> +#include <linux/thermal.h>
>> +#include <linux/cpu_cooling.h>
>> +#include <linux/cpumask.h>
> 
> In alphabetical order please..
> 

OK.

>> @@ -268,6 +272,13 @@ static int cpu0_cpufreq_probe(struct platform_device *pdev)
>>                 goto out_free_table;
>>         }
>>
>> +       /*
>> +        * For now, just loading the cooling device;
>> +        * thermal DT code takes care of matching them.
>> +        */
>> +       if (of_find_property(np, "cooling-zones", NULL))
>> +               cdev = cpufreq_cooling_register(cpu_present_mask);
> 
> Should we check if it passed or failed? And if failed Atleast flag an
> appropriate message?
> 

Yes, we need error checking code. I will add in next version. Thanks Kumar.

> 


-- 
You have got to be excited about what you are doing. (L. Lamport)

Eduardo Valentin


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 295 bytes --]

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

* Re: [lm-sensors] [RFC PATCH 01/14] cpufreq: cpufreq-cpu0: add dt node parsing for 'cooling-zones'
@ 2013-08-26 12:13       ` Eduardo Valentin
  0 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-26 12:13 UTC (permalink / raw)
  To: Viresh Kumar
  Cc: Eduardo Valentin, Stephen Warren, Pawel Moll, Mark Rutland,
	Ian Campbell, Grant Likely, Rob Herring, Guenter Roeck,
	Zhang Rui, wni, R, Durgadoss, linux-pm, devicetree, lm-sensors,
	Linux Kernel Mailing List, Rafael J. Wysocki, cpufreq,
	devicetree-discuss


[-- Attachment #1.1: Type: text/plain, Size: 1314 bytes --]

On 26-08-2013 00:42, Viresh Kumar wrote:
> On 24 August 2013 04:45, Eduardo Valentin <eduardo.valentin@ti.com> wrote:
>> diff --git a/drivers/cpufreq/cpufreq-cpu0.c b/drivers/cpufreq/cpufreq-cpu0.c
>> index ad1fde2..ede6487 100644
>> --- a/drivers/cpufreq/cpufreq-cpu0.c
>> +++ b/drivers/cpufreq/cpufreq-cpu0.c
>> @@ -20,6 +20,9 @@
>>  #include <linux/platform_device.h>
>>  #include <linux/regulator/consumer.h>
>>  #include <linux/slab.h>
>> +#include <linux/thermal.h>
>> +#include <linux/cpu_cooling.h>
>> +#include <linux/cpumask.h>
> 
> In alphabetical order please..
> 

OK.

>> @@ -268,6 +272,13 @@ static int cpu0_cpufreq_probe(struct platform_device *pdev)
>>                 goto out_free_table;
>>         }
>>
>> +       /*
>> +        * For now, just loading the cooling device;
>> +        * thermal DT code takes care of matching them.
>> +        */
>> +       if (of_find_property(np, "cooling-zones", NULL))
>> +               cdev = cpufreq_cooling_register(cpu_present_mask);
> 
> Should we check if it passed or failed? And if failed Atleast flag an
> appropriate message?
> 

Yes, we need error checking code. I will add in next version. Thanks Kumar.

> 


-- 
You have got to be excited about what you are doing. (L. Lamport)

Eduardo Valentin


[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 295 bytes --]

[-- Attachment #2: Type: text/plain, Size: 153 bytes --]

_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

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

* Re: [RFC PATCH 03/14] hwmon: lm75: expose to thermal fw via DT nodes
  2013-08-23 23:50     ` [lm-sensors] " Guenter Roeck
  (?)
@ 2013-08-26 12:15       ` Eduardo Valentin
  -1 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-26 12:15 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Eduardo Valentin, swarren, pawel.moll, mark.rutland,
	ian.campbell, grant.likely, rob.herring, rui.zhang, wni,
	durgadoss.r, linux-pm, devicetree, lm-sensors, linux-kernel,
	Jean Delvare

[-- Attachment #1: Type: text/plain, Size: 3894 bytes --]

On 23-08-2013 19:50, Guenter Roeck wrote:
> On Fri, Aug 23, 2013 at 07:15:44PM -0400, Eduardo Valentin wrote:
>> This patch adds to lm75 temperature sensor the possibility
>> to expose itself as thermal zone device, registered on the
>> thermal framework.
>>
>> The thermal zone is built only if a device tree node
>> describing a thermal zone for this sensor is present
>> inside the lm75 DT node. Otherwise, the driver behavior
>> will be the same.
>>
>> Cc: Jean Delvare <khali@linux-fr.org>
>> Cc: Guenter Roeck <linux@roeck-us.net>
>> Cc: lm-sensors@lm-sensors.org
>> Cc: linux-kernel@vger.kernel.org
>> Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
>> ---
>>  drivers/hwmon/lm75.c | 31 +++++++++++++++++++++++++++++++
>>  1 file changed, 31 insertions(+)
>>
>> diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c
>> index c03b490..dc55908 100644
>> --- a/drivers/hwmon/lm75.c
>> +++ b/drivers/hwmon/lm75.c
>> @@ -27,6 +27,8 @@
>>  #include <linux/hwmon-sysfs.h>
>>  #include <linux/err.h>
>>  #include <linux/mutex.h>
>> +#include <linux/thermal.h>
>> +#include <linux/of.h>
>>  #include "lm75.h"
>>  
>>  
>> @@ -70,6 +72,7 @@ static const u8 LM75_REG_TEMP[3] = {
>>  /* Each client has this additional data */
>>  struct lm75_data {
>>  	struct device		*hwmon_dev;
>> +	struct thermal_zone_device	*tz;
>>  	struct mutex		update_lock;
>>  	u8			orig_conf;
>>  	u8			resolution;	/* In bits, between 9 and 12 */
>> @@ -92,6 +95,19 @@ static struct lm75_data *lm75_update_device(struct device *dev);
>>  
>>  /* sysfs attributes for hwmon */
>>  
>> +static int lm75_read_temp(void *dev, unsigned long *temp)
>> +{
>> +	struct lm75_data *data = lm75_update_device(dev);
>> +
>> +	if (IS_ERR(data))
>> +		return PTR_ERR(data);
>> +
>> +	*temp = ((data->temp[0] >> (16 - data->resolution)) * 1000) >>
>> +			(data->resolution - 8);
>> +
> The reported temperature can be negative, which would result in reporting a very
> high temperature (note this applies to the tmp102 driver patch as well).
> 

Good point.

> The computation is quite complex and matches the computation done in show_temp().
> Given that, it would make sense to declare an inline function to convert the
> register value to the temperature. This function can take the register value
> and the resolution as argument.

Sounds reasonable. Modifying accordingly in next version.

> 
> Guenter
> 
>> +	return 0;
>> +}
>> +
>>  static ssize_t show_temp(struct device *dev, struct device_attribute *da,
>>  			 char *buf)
>>  {
>> @@ -271,11 +287,25 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id)
>>  		goto exit_remove;
>>  	}
>>  
>> +	if (of_find_property(client->dev.of_node, "monitored-zones", NULL)) {
>> +		data->tz = thermal_zone_of_device_register(&client->dev,
>> +							   0,
>> +							   false, /* -hwmon */
>> +							   &client->dev,
>> +							   lm75_read_temp);
>> +		if (IS_ERR(data->tz)) {
>> +			status = PTR_ERR(data->tz);
>> +			goto exit_hwmon;
>> +		}
>> +	}
>> +
>>  	dev_info(&client->dev, "%s: sensor '%s'\n",
>>  		 dev_name(data->hwmon_dev), client->name);
>>  
>>  	return 0;
>>  
>> +exit_hwmon:
>> +	hwmon_device_unregister(data->hwmon_dev);
>>  exit_remove:
>>  	sysfs_remove_group(&client->dev.kobj, &lm75_group);
>>  	return status;
>> @@ -285,6 +315,7 @@ static int lm75_remove(struct i2c_client *client)
>>  {
>>  	struct lm75_data *data = i2c_get_clientdata(client);
>>  
>> +	thermal_zone_device_unregister(data->tz);
>>  	hwmon_device_unregister(data->hwmon_dev);
>>  	sysfs_remove_group(&client->dev.kobj, &lm75_group);
>>  	lm75_write_value(client, LM75_REG_CONF, data->orig_conf);
>> -- 
>> 1.8.2.1.342.gfa7285d
>>
>>
> 
> 


-- 
You have got to be excited about what you are doing. (L. Lamport)

Eduardo Valentin


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 295 bytes --]

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

* Re: [RFC PATCH 03/14] hwmon: lm75: expose to thermal fw via DT nodes
@ 2013-08-26 12:15       ` Eduardo Valentin
  0 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-26 12:15 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Eduardo Valentin, swarren, pawel.moll, mark.rutland,
	ian.campbell, grant.likely, rob.herring, rui.zhang, wni,
	durgadoss.r, linux-pm, devicetree, lm-sensors, linux-kernel,
	Jean Delvare

[-- Attachment #1: Type: text/plain, Size: 3894 bytes --]

On 23-08-2013 19:50, Guenter Roeck wrote:
> On Fri, Aug 23, 2013 at 07:15:44PM -0400, Eduardo Valentin wrote:
>> This patch adds to lm75 temperature sensor the possibility
>> to expose itself as thermal zone device, registered on the
>> thermal framework.
>>
>> The thermal zone is built only if a device tree node
>> describing a thermal zone for this sensor is present
>> inside the lm75 DT node. Otherwise, the driver behavior
>> will be the same.
>>
>> Cc: Jean Delvare <khali@linux-fr.org>
>> Cc: Guenter Roeck <linux@roeck-us.net>
>> Cc: lm-sensors@lm-sensors.org
>> Cc: linux-kernel@vger.kernel.org
>> Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
>> ---
>>  drivers/hwmon/lm75.c | 31 +++++++++++++++++++++++++++++++
>>  1 file changed, 31 insertions(+)
>>
>> diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c
>> index c03b490..dc55908 100644
>> --- a/drivers/hwmon/lm75.c
>> +++ b/drivers/hwmon/lm75.c
>> @@ -27,6 +27,8 @@
>>  #include <linux/hwmon-sysfs.h>
>>  #include <linux/err.h>
>>  #include <linux/mutex.h>
>> +#include <linux/thermal.h>
>> +#include <linux/of.h>
>>  #include "lm75.h"
>>  
>>  
>> @@ -70,6 +72,7 @@ static const u8 LM75_REG_TEMP[3] = {
>>  /* Each client has this additional data */
>>  struct lm75_data {
>>  	struct device		*hwmon_dev;
>> +	struct thermal_zone_device	*tz;
>>  	struct mutex		update_lock;
>>  	u8			orig_conf;
>>  	u8			resolution;	/* In bits, between 9 and 12 */
>> @@ -92,6 +95,19 @@ static struct lm75_data *lm75_update_device(struct device *dev);
>>  
>>  /* sysfs attributes for hwmon */
>>  
>> +static int lm75_read_temp(void *dev, unsigned long *temp)
>> +{
>> +	struct lm75_data *data = lm75_update_device(dev);
>> +
>> +	if (IS_ERR(data))
>> +		return PTR_ERR(data);
>> +
>> +	*temp = ((data->temp[0] >> (16 - data->resolution)) * 1000) >>
>> +			(data->resolution - 8);
>> +
> The reported temperature can be negative, which would result in reporting a very
> high temperature (note this applies to the tmp102 driver patch as well).
> 

Good point.

> The computation is quite complex and matches the computation done in show_temp().
> Given that, it would make sense to declare an inline function to convert the
> register value to the temperature. This function can take the register value
> and the resolution as argument.

Sounds reasonable. Modifying accordingly in next version.

> 
> Guenter
> 
>> +	return 0;
>> +}
>> +
>>  static ssize_t show_temp(struct device *dev, struct device_attribute *da,
>>  			 char *buf)
>>  {
>> @@ -271,11 +287,25 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id)
>>  		goto exit_remove;
>>  	}
>>  
>> +	if (of_find_property(client->dev.of_node, "monitored-zones", NULL)) {
>> +		data->tz = thermal_zone_of_device_register(&client->dev,
>> +							   0,
>> +							   false, /* -hwmon */
>> +							   &client->dev,
>> +							   lm75_read_temp);
>> +		if (IS_ERR(data->tz)) {
>> +			status = PTR_ERR(data->tz);
>> +			goto exit_hwmon;
>> +		}
>> +	}
>> +
>>  	dev_info(&client->dev, "%s: sensor '%s'\n",
>>  		 dev_name(data->hwmon_dev), client->name);
>>  
>>  	return 0;
>>  
>> +exit_hwmon:
>> +	hwmon_device_unregister(data->hwmon_dev);
>>  exit_remove:
>>  	sysfs_remove_group(&client->dev.kobj, &lm75_group);
>>  	return status;
>> @@ -285,6 +315,7 @@ static int lm75_remove(struct i2c_client *client)
>>  {
>>  	struct lm75_data *data = i2c_get_clientdata(client);
>>  
>> +	thermal_zone_device_unregister(data->tz);
>>  	hwmon_device_unregister(data->hwmon_dev);
>>  	sysfs_remove_group(&client->dev.kobj, &lm75_group);
>>  	lm75_write_value(client, LM75_REG_CONF, data->orig_conf);
>> -- 
>> 1.8.2.1.342.gfa7285d
>>
>>
> 
> 


-- 
You have got to be excited about what you are doing. (L. Lamport)

Eduardo Valentin


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 295 bytes --]

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

* Re: [lm-sensors] [RFC PATCH 03/14] hwmon: lm75: expose to thermal fw via DT nodes
@ 2013-08-26 12:15       ` Eduardo Valentin
  0 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-26 12:15 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Eduardo Valentin, swarren, pawel.moll, mark.rutland,
	ian.campbell, grant.likely, rob.herring, rui.zhang, wni,
	durgadoss.r, linux-pm, devicetree, lm-sensors, linux-kernel,
	Jean Delvare


[-- Attachment #1.1: Type: text/plain, Size: 3894 bytes --]

On 23-08-2013 19:50, Guenter Roeck wrote:
> On Fri, Aug 23, 2013 at 07:15:44PM -0400, Eduardo Valentin wrote:
>> This patch adds to lm75 temperature sensor the possibility
>> to expose itself as thermal zone device, registered on the
>> thermal framework.
>>
>> The thermal zone is built only if a device tree node
>> describing a thermal zone for this sensor is present
>> inside the lm75 DT node. Otherwise, the driver behavior
>> will be the same.
>>
>> Cc: Jean Delvare <khali@linux-fr.org>
>> Cc: Guenter Roeck <linux@roeck-us.net>
>> Cc: lm-sensors@lm-sensors.org
>> Cc: linux-kernel@vger.kernel.org
>> Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
>> ---
>>  drivers/hwmon/lm75.c | 31 +++++++++++++++++++++++++++++++
>>  1 file changed, 31 insertions(+)
>>
>> diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c
>> index c03b490..dc55908 100644
>> --- a/drivers/hwmon/lm75.c
>> +++ b/drivers/hwmon/lm75.c
>> @@ -27,6 +27,8 @@
>>  #include <linux/hwmon-sysfs.h>
>>  #include <linux/err.h>
>>  #include <linux/mutex.h>
>> +#include <linux/thermal.h>
>> +#include <linux/of.h>
>>  #include "lm75.h"
>>  
>>  
>> @@ -70,6 +72,7 @@ static const u8 LM75_REG_TEMP[3] = {
>>  /* Each client has this additional data */
>>  struct lm75_data {
>>  	struct device		*hwmon_dev;
>> +	struct thermal_zone_device	*tz;
>>  	struct mutex		update_lock;
>>  	u8			orig_conf;
>>  	u8			resolution;	/* In bits, between 9 and 12 */
>> @@ -92,6 +95,19 @@ static struct lm75_data *lm75_update_device(struct device *dev);
>>  
>>  /* sysfs attributes for hwmon */
>>  
>> +static int lm75_read_temp(void *dev, unsigned long *temp)
>> +{
>> +	struct lm75_data *data = lm75_update_device(dev);
>> +
>> +	if (IS_ERR(data))
>> +		return PTR_ERR(data);
>> +
>> +	*temp = ((data->temp[0] >> (16 - data->resolution)) * 1000) >>
>> +			(data->resolution - 8);
>> +
> The reported temperature can be negative, which would result in reporting a very
> high temperature (note this applies to the tmp102 driver patch as well).
> 

Good point.

> The computation is quite complex and matches the computation done in show_temp().
> Given that, it would make sense to declare an inline function to convert the
> register value to the temperature. This function can take the register value
> and the resolution as argument.

Sounds reasonable. Modifying accordingly in next version.

> 
> Guenter
> 
>> +	return 0;
>> +}
>> +
>>  static ssize_t show_temp(struct device *dev, struct device_attribute *da,
>>  			 char *buf)
>>  {
>> @@ -271,11 +287,25 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id)
>>  		goto exit_remove;
>>  	}
>>  
>> +	if (of_find_property(client->dev.of_node, "monitored-zones", NULL)) {
>> +		data->tz = thermal_zone_of_device_register(&client->dev,
>> +							   0,
>> +							   false, /* -hwmon */
>> +							   &client->dev,
>> +							   lm75_read_temp);
>> +		if (IS_ERR(data->tz)) {
>> +			status = PTR_ERR(data->tz);
>> +			goto exit_hwmon;
>> +		}
>> +	}
>> +
>>  	dev_info(&client->dev, "%s: sensor '%s'\n",
>>  		 dev_name(data->hwmon_dev), client->name);
>>  
>>  	return 0;
>>  
>> +exit_hwmon:
>> +	hwmon_device_unregister(data->hwmon_dev);
>>  exit_remove:
>>  	sysfs_remove_group(&client->dev.kobj, &lm75_group);
>>  	return status;
>> @@ -285,6 +315,7 @@ static int lm75_remove(struct i2c_client *client)
>>  {
>>  	struct lm75_data *data = i2c_get_clientdata(client);
>>  
>> +	thermal_zone_device_unregister(data->tz);
>>  	hwmon_device_unregister(data->hwmon_dev);
>>  	sysfs_remove_group(&client->dev.kobj, &lm75_group);
>>  	lm75_write_value(client, LM75_REG_CONF, data->orig_conf);
>> -- 
>> 1.8.2.1.342.gfa7285d
>>
>>
> 
> 


-- 
You have got to be excited about what you are doing. (L. Lamport)

Eduardo Valentin


[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 295 bytes --]

[-- Attachment #2: Type: text/plain, Size: 153 bytes --]

_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

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

* Re: [RFC PATCH 01/14] cpufreq: cpufreq-cpu0: add dt node parsing for 'cooling-zones'
  2013-08-23 23:15   ` Eduardo Valentin
  (?)
@ 2013-08-27  9:29     ` Mark Rutland
  -1 siblings, 0 replies; 100+ messages in thread
From: Mark Rutland @ 2013-08-27  9:29 UTC (permalink / raw)
  To: Eduardo Valentin
  Cc: swarren, Pawel Moll, ian.campbell, grant.likely, rob.herring,
	linux, rui.zhang, wni, durgadoss.r, linux-pm, devicetree,
	lm-sensors, linux-kernel, Rafael J. Wysocki, Viresh Kumar,
	cpufreq, devicetree-discuss

On Sat, Aug 24, 2013 at 12:15:42AM +0100, Eduardo Valentin wrote:
> This patch changes the cpufreq-cpu0 driver to consider if
> a cpu needs cooling (with cpufreq). In case the cooling is needed,
> it can be flagged at the cpu0 device tree node, with the list
> of zones property 'cooling-zones'.
> 
> In case this list of zones is present, the driver will
> load a cpufreq cooling device in the system. The cpufreq-cpu0
> driver is not interested in determining how the system should
> be using the cooling device. The driver is responsible
> only of loading the cooling device.
> 
> Describing how the cooling device will be used can be
> accomplished by setting up a thermal zone that references
> and is composed by the cpufreq cooling device.
> 
> Cc: "Rafael J. Wysocki" <rjw@sisk.pl>
> Cc: Viresh Kumar <viresh.kumar@linaro.org>
> Cc: Grant Likely <grant.likely@linaro.org>
> Cc: Rob Herring <rob.herring@calxeda.com>
> Cc: cpufreq@vger.kernel.org
> Cc: linux-pm@vger.kernel.org
> Cc: linux-kernel@vger.kernel.org
> Cc: devicetree-discuss@lists.ozlabs.org
> Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
> ---
>  Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt |  4 ++++
>  drivers/cpufreq/cpufreq-cpu0.c                             | 12 ++++++++++++
>  2 files changed, 16 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt b/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt
> index 051f764..add50f7 100644
> --- a/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt
> +++ b/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt
> @@ -15,6 +15,9 @@ Optional properties:
>  - clock-latency: Specify the possible maximum transition latency for clock,
>    in unit of nanoseconds.
>  - voltage-tolerance: Specify the CPU voltage tolerance in percentage.
> +- cooling-zones: A list of thermal zones phandles. The generic cpu
> +  cooling (freq clipping) is loaded by the generic cpufreq-cpu0 driver
> +  in case the device tree node has this list.

Bindings should not describe the behaviour of any kernel (and for that
reason I'm not very keen on the current cpufreq-cpu0 binding document).

Bindings should simply describe the hardware. This addition could
instead be:

 - cooling-zones: a list of thermal zone phandles.

However, as the thermal zone binding doesn't seem to have appeared by
this patch, it should get moved later anyway...

Thanks,
Mark.

>  
>  Examples:
>  
> @@ -33,6 +36,7 @@ cpus {
>  			198000  850000
>  		>;
>  		clock-latency = <61036>; /* two CLK32 periods */
> +		cooling-zones = <&cpu_thermal>;
>  	};
>  
>  	cpu@1 {
> diff --git a/drivers/cpufreq/cpufreq-cpu0.c b/drivers/cpufreq/cpufreq-cpu0.c
> index ad1fde2..ede6487 100644
> --- a/drivers/cpufreq/cpufreq-cpu0.c
> +++ b/drivers/cpufreq/cpufreq-cpu0.c
> @@ -20,6 +20,9 @@
>  #include <linux/platform_device.h>
>  #include <linux/regulator/consumer.h>
>  #include <linux/slab.h>
> +#include <linux/thermal.h>
> +#include <linux/cpu_cooling.h>
> +#include <linux/cpumask.h>
>  
>  static unsigned int transition_latency;
>  static unsigned int voltage_tolerance; /* in percentage */
> @@ -28,6 +31,7 @@ static struct device *cpu_dev;
>  static struct clk *cpu_clk;
>  static struct regulator *cpu_reg;
>  static struct cpufreq_frequency_table *freq_table;
> +static struct thermal_cooling_device *cdev;
>  
>  static int cpu0_verify_speed(struct cpufreq_policy *policy)
>  {
> @@ -268,6 +272,13 @@ static int cpu0_cpufreq_probe(struct platform_device *pdev)
>  		goto out_free_table;
>  	}
>  
> +	/*
> +	 * For now, just loading the cooling device;
> +	 * thermal DT code takes care of matching them.
> +	 */
> +	if (of_find_property(np, "cooling-zones", NULL))
> +		cdev = cpufreq_cooling_register(cpu_present_mask);
> +
>  	of_node_put(np);
>  	of_node_put(parent);
>  	return 0;
> @@ -283,6 +294,7 @@ out_put_parent:
>  
>  static int cpu0_cpufreq_remove(struct platform_device *pdev)
>  {
> +	cpufreq_cooling_unregister(cdev);
>  	cpufreq_unregister_driver(&cpu0_cpufreq_driver);
>  	opp_free_cpufreq_table(cpu_dev, &freq_table);
>  
> -- 
> 1.8.2.1.342.gfa7285d
> 
> 

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

* Re: [RFC PATCH 01/14] cpufreq: cpufreq-cpu0: add dt node parsing for 'cooling-zones'
@ 2013-08-27  9:29     ` Mark Rutland
  0 siblings, 0 replies; 100+ messages in thread
From: Mark Rutland @ 2013-08-27  9:29 UTC (permalink / raw)
  To: Eduardo Valentin
  Cc: swarren, Pawel Moll, ian.campbell, grant.likely, rob.herring,
	linux, rui.zhang, wni, durgadoss.r, linux-pm, devicetree,
	lm-sensors, linux-kernel, Rafael J. Wysocki, Viresh Kumar,
	cpufreq, devicetree-discuss

On Sat, Aug 24, 2013 at 12:15:42AM +0100, Eduardo Valentin wrote:
> This patch changes the cpufreq-cpu0 driver to consider if
> a cpu needs cooling (with cpufreq). In case the cooling is needed,
> it can be flagged at the cpu0 device tree node, with the list
> of zones property 'cooling-zones'.
> 
> In case this list of zones is present, the driver will
> load a cpufreq cooling device in the system. The cpufreq-cpu0
> driver is not interested in determining how the system should
> be using the cooling device. The driver is responsible
> only of loading the cooling device.
> 
> Describing how the cooling device will be used can be
> accomplished by setting up a thermal zone that references
> and is composed by the cpufreq cooling device.
> 
> Cc: "Rafael J. Wysocki" <rjw@sisk.pl>
> Cc: Viresh Kumar <viresh.kumar@linaro.org>
> Cc: Grant Likely <grant.likely@linaro.org>
> Cc: Rob Herring <rob.herring@calxeda.com>
> Cc: cpufreq@vger.kernel.org
> Cc: linux-pm@vger.kernel.org
> Cc: linux-kernel@vger.kernel.org
> Cc: devicetree-discuss@lists.ozlabs.org
> Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
> ---
>  Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt |  4 ++++
>  drivers/cpufreq/cpufreq-cpu0.c                             | 12 ++++++++++++
>  2 files changed, 16 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt b/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt
> index 051f764..add50f7 100644
> --- a/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt
> +++ b/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt
> @@ -15,6 +15,9 @@ Optional properties:
>  - clock-latency: Specify the possible maximum transition latency for clock,
>    in unit of nanoseconds.
>  - voltage-tolerance: Specify the CPU voltage tolerance in percentage.
> +- cooling-zones: A list of thermal zones phandles. The generic cpu
> +  cooling (freq clipping) is loaded by the generic cpufreq-cpu0 driver
> +  in case the device tree node has this list.

Bindings should not describe the behaviour of any kernel (and for that
reason I'm not very keen on the current cpufreq-cpu0 binding document).

Bindings should simply describe the hardware. This addition could
instead be:

 - cooling-zones: a list of thermal zone phandles.

However, as the thermal zone binding doesn't seem to have appeared by
this patch, it should get moved later anyway...

Thanks,
Mark.

>  
>  Examples:
>  
> @@ -33,6 +36,7 @@ cpus {
>  			198000  850000
>  		>;
>  		clock-latency = <61036>; /* two CLK32 periods */
> +		cooling-zones = <&cpu_thermal>;
>  	};
>  
>  	cpu@1 {
> diff --git a/drivers/cpufreq/cpufreq-cpu0.c b/drivers/cpufreq/cpufreq-cpu0.c
> index ad1fde2..ede6487 100644
> --- a/drivers/cpufreq/cpufreq-cpu0.c
> +++ b/drivers/cpufreq/cpufreq-cpu0.c
> @@ -20,6 +20,9 @@
>  #include <linux/platform_device.h>
>  #include <linux/regulator/consumer.h>
>  #include <linux/slab.h>
> +#include <linux/thermal.h>
> +#include <linux/cpu_cooling.h>
> +#include <linux/cpumask.h>
>  
>  static unsigned int transition_latency;
>  static unsigned int voltage_tolerance; /* in percentage */
> @@ -28,6 +31,7 @@ static struct device *cpu_dev;
>  static struct clk *cpu_clk;
>  static struct regulator *cpu_reg;
>  static struct cpufreq_frequency_table *freq_table;
> +static struct thermal_cooling_device *cdev;
>  
>  static int cpu0_verify_speed(struct cpufreq_policy *policy)
>  {
> @@ -268,6 +272,13 @@ static int cpu0_cpufreq_probe(struct platform_device *pdev)
>  		goto out_free_table;
>  	}
>  
> +	/*
> +	 * For now, just loading the cooling device;
> +	 * thermal DT code takes care of matching them.
> +	 */
> +	if (of_find_property(np, "cooling-zones", NULL))
> +		cdev = cpufreq_cooling_register(cpu_present_mask);
> +
>  	of_node_put(np);
>  	of_node_put(parent);
>  	return 0;
> @@ -283,6 +294,7 @@ out_put_parent:
>  
>  static int cpu0_cpufreq_remove(struct platform_device *pdev)
>  {
> +	cpufreq_cooling_unregister(cdev);
>  	cpufreq_unregister_driver(&cpu0_cpufreq_driver);
>  	opp_free_cpufreq_table(cpu_dev, &freq_table);
>  
> -- 
> 1.8.2.1.342.gfa7285d
> 
> 

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

* Re: [lm-sensors] [RFC PATCH 01/14] cpufreq: cpufreq-cpu0: add dt node parsing for 'cooling-zones'
@ 2013-08-27  9:29     ` Mark Rutland
  0 siblings, 0 replies; 100+ messages in thread
From: Mark Rutland @ 2013-08-27  9:29 UTC (permalink / raw)
  To: Eduardo Valentin
  Cc: swarren, Pawel Moll, ian.campbell, grant.likely, rob.herring,
	linux, rui.zhang, wni, durgadoss.r, linux-pm, devicetree,
	lm-sensors, linux-kernel, Rafael J. Wysocki, Viresh Kumar,
	cpufreq, devicetree-discuss

On Sat, Aug 24, 2013 at 12:15:42AM +0100, Eduardo Valentin wrote:
> This patch changes the cpufreq-cpu0 driver to consider if
> a cpu needs cooling (with cpufreq). In case the cooling is needed,
> it can be flagged at the cpu0 device tree node, with the list
> of zones property 'cooling-zones'.
> 
> In case this list of zones is present, the driver will
> load a cpufreq cooling device in the system. The cpufreq-cpu0
> driver is not interested in determining how the system should
> be using the cooling device. The driver is responsible
> only of loading the cooling device.
> 
> Describing how the cooling device will be used can be
> accomplished by setting up a thermal zone that references
> and is composed by the cpufreq cooling device.
> 
> Cc: "Rafael J. Wysocki" <rjw@sisk.pl>
> Cc: Viresh Kumar <viresh.kumar@linaro.org>
> Cc: Grant Likely <grant.likely@linaro.org>
> Cc: Rob Herring <rob.herring@calxeda.com>
> Cc: cpufreq@vger.kernel.org
> Cc: linux-pm@vger.kernel.org
> Cc: linux-kernel@vger.kernel.org
> Cc: devicetree-discuss@lists.ozlabs.org
> Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
> ---
>  Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt |  4 ++++
>  drivers/cpufreq/cpufreq-cpu0.c                             | 12 ++++++++++++
>  2 files changed, 16 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt b/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt
> index 051f764..add50f7 100644
> --- a/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt
> +++ b/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt
> @@ -15,6 +15,9 @@ Optional properties:
>  - clock-latency: Specify the possible maximum transition latency for clock,
>    in unit of nanoseconds.
>  - voltage-tolerance: Specify the CPU voltage tolerance in percentage.
> +- cooling-zones: A list of thermal zones phandles. The generic cpu
> +  cooling (freq clipping) is loaded by the generic cpufreq-cpu0 driver
> +  in case the device tree node has this list.

Bindings should not describe the behaviour of any kernel (and for that
reason I'm not very keen on the current cpufreq-cpu0 binding document).

Bindings should simply describe the hardware. This addition could
instead be:

 - cooling-zones: a list of thermal zone phandles.

However, as the thermal zone binding doesn't seem to have appeared by
this patch, it should get moved later anyway...

Thanks,
Mark.

>  
>  Examples:
>  
> @@ -33,6 +36,7 @@ cpus {
>  			198000  850000
>  		>;
>  		clock-latency = <61036>; /* two CLK32 periods */
> +		cooling-zones = <&cpu_thermal>;
>  	};
>  
>  	cpu@1 {
> diff --git a/drivers/cpufreq/cpufreq-cpu0.c b/drivers/cpufreq/cpufreq-cpu0.c
> index ad1fde2..ede6487 100644
> --- a/drivers/cpufreq/cpufreq-cpu0.c
> +++ b/drivers/cpufreq/cpufreq-cpu0.c
> @@ -20,6 +20,9 @@
>  #include <linux/platform_device.h>
>  #include <linux/regulator/consumer.h>
>  #include <linux/slab.h>
> +#include <linux/thermal.h>
> +#include <linux/cpu_cooling.h>
> +#include <linux/cpumask.h>
>  
>  static unsigned int transition_latency;
>  static unsigned int voltage_tolerance; /* in percentage */
> @@ -28,6 +31,7 @@ static struct device *cpu_dev;
>  static struct clk *cpu_clk;
>  static struct regulator *cpu_reg;
>  static struct cpufreq_frequency_table *freq_table;
> +static struct thermal_cooling_device *cdev;
>  
>  static int cpu0_verify_speed(struct cpufreq_policy *policy)
>  {
> @@ -268,6 +272,13 @@ static int cpu0_cpufreq_probe(struct platform_device *pdev)
>  		goto out_free_table;
>  	}
>  
> +	/*
> +	 * For now, just loading the cooling device;
> +	 * thermal DT code takes care of matching them.
> +	 */
> +	if (of_find_property(np, "cooling-zones", NULL))
> +		cdev = cpufreq_cooling_register(cpu_present_mask);
> +
>  	of_node_put(np);
>  	of_node_put(parent);
>  	return 0;
> @@ -283,6 +294,7 @@ out_put_parent:
>  
>  static int cpu0_cpufreq_remove(struct platform_device *pdev)
>  {
> +	cpufreq_cooling_unregister(cdev);
>  	cpufreq_unregister_driver(&cpu0_cpufreq_driver);
>  	opp_free_cpufreq_table(cpu_dev, &freq_table);
>  
> -- 
> 1.8.2.1.342.gfa7285d
> 
> 

_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

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

* Re: [RFC PATCH 02/14] drivers: thermal: introduce device tree parser
  2013-08-23 23:15   ` Eduardo Valentin
@ 2013-08-27 10:22     ` Mark Rutland
  -1 siblings, 0 replies; 100+ messages in thread
From: Mark Rutland @ 2013-08-27 10:22 UTC (permalink / raw)
  To: Eduardo Valentin
  Cc: swarren, Pawel Moll, ian.campbell, grant.likely, rob.herring,
	linux, rui.zhang, wni, durgadoss.r, linux-pm, devicetree,
	lm-sensors, linux-kernel

Hi,

On Sat, Aug 24, 2013 at 12:15:43AM +0100, Eduardo Valentin wrote:
> In order to be able to build thermal policies
> based on generic sensors, like I2C device, that
> can be places in different points on different boards,
> there is a need to have a way to feed board dependent
> data into the thermal framework.
> 
> This patch introduces a thermal data parser for device
> tree. The parsed data is used to build thermal zones
> and thermal binding parameters. The output data
> can then be used to deploy thermal policies.
> 
> This patch adds also documentation regarding this
> API and how to define tree nodes to use
> this infrastructure.
> 
> Cc: Zhang Rui <rui.zhang@intel.com>
> Cc: linux-pm@vger.kernel.org
> Cc: linux-kernel@vger.kernel.org
> Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
> ---
>  .../devicetree/bindings/thermal/thermal.txt        | 160 +++++++
>  drivers/thermal/Kconfig                            |  13 +
>  drivers/thermal/Makefile                           |   1 +
>  drivers/thermal/thermal_dt.c                       | 473 +++++++++++++++++++++
>  include/dt-bindings/thermal/thermal.h              |  27 ++
>  include/linux/thermal.h                            |   3 +
>  6 files changed, 677 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/thermal/thermal.txt
>  create mode 100644 drivers/thermal/thermal_dt.c
>  create mode 100644 include/dt-bindings/thermal/thermal.h
> 
> diff --git a/Documentation/devicetree/bindings/thermal/thermal.txt b/Documentation/devicetree/bindings/thermal/thermal.txt
> new file mode 100644
> index 0000000..af20ab0
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/thermal/thermal.txt
> @@ -0,0 +1,160 @@
> +----------------------------------------
> +Thermal Framework Device Tree descriptor
> +----------------------------------------
> +
> +This file describes how to define a thermal structure using device tree.
> +A thermal structure includes thermal zones and their components, such
> +as name, trip points, polling intervals and cooling devices binding
> +descriptors. A binding descriptor may contain information on how to
> +react, with a cooling stepped action or a weight on a fair share.
> +The target of device tree thermal descriptors is to describe only
> +the hardware thermal aspects, not how the system must control or which
> +algorithm or policy must take place. It follows a description of each
> +type of device tree node.
> +
> +****
> +trip
> +****
> +
> +The trip node is a node to describe a point in the temperature domain
> +in which the system takes an action. This node describes just the point,
> +not the action.
> +
> +A node describing a trip must contain:
> +- temperature: the trip temperature level, in milliCelsius.
> +- hysteresis: a (low) hysteresis value on 'temperature'. This is a relative
> +value, in milliCelsius.

Presumably this is a single (u32) cell?

> +- type: the trip type. Here is the type mapping:
> +       THERMAL_TRIP_ACTIVE
> +       THERMAL_TRIP_PASSIVE
> +       THERMAL_TRIP_HOT
> +       THERMAL_TRIP_CRITICAL

What type is this property?

What are these values? Do you need to refer to a header somewhere?
Symbolic constants should have an associated value for an ABI.

> +
> +**********
> +bind_param
> +**********
> +
> +The bind_param node is a node to describe how cooling devices get assigned
> +to trip points of the zone. The cooling devices are expected to be loaded
> +in the target system.
> +
> +A node describing a bind_param must contain:
> +- cooling_device: A string with the cooling device name.

Please use '-' rather than '_' in bindings. That's the normal devicetree
convention, and there's no point gonig against it and causing more
confusion.

What are valid values of this string, and what do they mean?

Why not a phandle + cells binding to cooling devices?

> +- weight: The 'influence' of a particular cooling device on this zone.
> +             This is on a percentage scale. The sum of all these weights
> +             (for a particular zone) cannot exceed 100.

This is a bit fuzzy, and certainly needs more guidance.

> +- trip_mask: This is a bit mask that gives the binding relation between
> +               this thermal zone and cdev, for a particular trip point.
> +               If nth bit is set, then the cdev and thermal zone are bound
> +               for trip point n.

What type is this?

The nth bit from which end?

Could you explain what "bound for trip point n" means?

Just because this is a bitmask in Linux does not mean it needs to be so
in the dt.

> +- limits: An array integers consisting of 2-tuples items, and each item means
> +  lower and upper state limits, like <min-state max-state>.
> +
> +**************************
> +temperature sensor devices
> +**************************
> +
> +Temperature sensor devices have to be linked to a specific thermal zone.
> +This is done by means of the 'monitored-zones' list.
> +- monitored-zones: A list of thermal zones phandles, identifying which
> +thermal zones the temperature sensor device is used to monitor.

Why does this need to be described that way around?

Can the zone not have a link to the sensor(s) it needs?

> +
> +************
> +thermal_zone
> +************
> +
> +The thermal_zone node is the node containing all the required info
> +for describing a thermal zone, including its cdev bindings. The thermal_zone
> +node must contain, apart from its own properties, one node containing
> +trip nodes and one node containing all the zone bind parameters.
> +
> +Required properties:
> +- mask: Bit string: If 'n'th bit is set, then trip point 'n' is writeable.

What type is a bit string in devicetree? I'm aware of cells and (byte)
strings, but not bit strings.

What does 'writeable' mean in this context?

There's presumably a better name than 'mask'.

> +
> +- passive_delay: number of milliseconds to wait between polls when
> +  performing passive cooling.
> +
> +- polling_delay: number of milliseconds to wait between polls when checking.

These sound very much like configuration of the driver rather than
hardware description. What if my temperature sensor can generate an
interrupt at some trigger temperature? Why would I need polling times?

Why does this need to be in the dt at all? Surely the OS can choose some
sensible polling period, possibly dynamically?

> +
> +- #thermal-cells: An integer that is used to specify how many cells compose
> +  sensor ids.

I don't see why this is necessary. If the zone itself described its
related sensors rather than the other way around, we wouldn't need it at
all. Most bindings so far have consumers link to their providers rather
than the other way around.

> +
> +Below is an example:
> +cpu_thermal: thermal_zone {
> +            #thermal-cells = <1>;
> +            mask = <0x03>; /* trips writability */
> +            passive_delay = <250>; /* milliseconds */
> +            polling_delay = <1000>; /* milliseconds */
> +            trips {
> +                    alert@100000{
> +                            temperature = <100000>; /* milliCelsius */
> +                            hysteresis = <0>; /* milliCelsius */
> +                            type = <THERMAL_TRIP_PASSIVE>;
> +                    };
> +                    crit@125000{
> +                            temperature = <125000>; /* milliCelsius */
> +                            hysteresis = <0>; /* milliCelsius */
> +                            type = <THERMAL_TRIP_CRITICAL>;
> +                    };
> +            };
> +            bind_params {
> +                    action@0{
> +                            cooling_device = "thermal-cpufreq";

NAK. That value was not defined anywhere, and represents Linux
infrastructure rather than hardware.

For this case, we could just as easily describe the thermal points, and
if no physical cooling device (e.g. a fan) is present, assume
cpufreq-base cooling.  Other OSs could choose to do otherwise, and we
could change later...

> +                            weight = <100>; /* percentage */
> +                            mask = <0x01>;

This should presumably be trip-mask (assuming my suggested corrections).

What is it supposed to mean here?

> +                           limits = <
> +                             /* lower-state            upper-state */
> +                               1                       THERMAL_NO_LIMITS
> +                               THERMAL_NO_LIMITS       THERMAL_NO_LIMITS
> +                           >;
> +                    };
> +            };
> +};
> +
> +sensor: adc@0xFFFF {
> +       ...
> +       monitored-zones = <&cpu_thermal 0>;
> +};
> +
> +cpu@0 {
> +       ...
> +       cooling-zones = <&cpu_thermal>;
> +};
> +
> +In the example above, the ADC sensor at address 0xFFFF is used to monitor
> +the zone 'cpu_thermal' using its the sensor 0. The cpu@0 device is also linked
> +to the same thermal zone 'cpu_thermal' as a cooling device.

Huh? That seems to imply the the '0' in '<&cpu_thermal 0>' on the sensor
node describes a property of the sensor rather than the thermal node,
unless I've misunderstood?

> +
> +***************
> +cpufreq-cooling
> +***************
> +
> +The generic cpu cooling (freq clipping) can be loaded by the
> +generic cpufreq-cpu0 driver in case the device tree node informs
> +this need.
> +
> +In order to load the cpufreq cooling device, it is possible to
> +inform that the cpu needs cooling by adding the list of thermal zones
> +in the 'cooling-zones' property at the cpu0 phandle.

This should be reworded so as to describe the binding rather than the
Linux behaviour based on the binding.

> +
> +Example:
> +       cpus {
> +               cpu@0 {
> +                       operating-points = <
> +                               /* kHz    uV */
> +                               800000  1313000
> +                               1008000 1375000
> +                       >;
> +                       cooling-zones = <&cpu_thermal>;
> +               };
> +       ...
> +       };
> +
> +The above will cause the cpufreq-cpu0 driver to understand that
> +the cpu will need passive cooling and while probing that node it will
> +also load the cpufreq cpu cooling device in that system.

The above describe that the CPU is part of a cooling (thermal?) zone and
requires cooling.

> +
> +However, be advised that this flag will not describe what needs to
> +be done or how the cpufreq cooling device will be used. In order to
> +accomplish this, one needs to write a phandle for a thermal zone, as
> +described in the section 'thermal_zone'.

The above already has a phandle to a thermal (cooling?) zone.

Please choose either cooling zone or thermal zone, having the two names
makes this more confusing than necessary.

> diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
> index 7fb16bc..753f0dc 100644
> --- a/drivers/thermal/Kconfig
> +++ b/drivers/thermal/Kconfig
> @@ -29,6 +29,19 @@ config THERMAL_HWMON
>           Say 'Y' here if you want all thermal sensors to
>           have hwmon sysfs interface too.
> 
> +config THERMAL_OF
> +       bool
> +       prompt "APIs to parse thermal data out of device tree"
> +       depends on OF
> +       default y
> +       help
> +         This options provides helpers to add the support to
> +         read and parse thermal data definitions out of the
> +         device tree blob.
> +
> +         Say 'Y' here if you need to build thermal infrastructure
> +         based on device tree.
> +
>  choice
>         prompt "Default Thermal governor"
>         default THERMAL_DEFAULT_GOV_STEP_WISE
> diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
> index 24cb894..eedb273 100644
> --- a/drivers/thermal/Makefile
> +++ b/drivers/thermal/Makefile
> @@ -7,6 +7,7 @@ thermal_sys-y                   += thermal_core.o
> 
>  # interface to/from other layers providing sensors
>  thermal_sys-$(CONFIG_THERMAL_HWMON)            += thermal_hwmon.o
> +thermal_sys-$(CONFIG_THERMAL_OF)               += thermal_dt.o
> 
>  # governors
>  thermal_sys-$(CONFIG_THERMAL_GOV_FAIR_SHARE)   += fair_share.o
> diff --git a/drivers/thermal/thermal_dt.c b/drivers/thermal/thermal_dt.c
> new file mode 100644
> index 0000000..cc35485
> --- /dev/null
> +++ b/drivers/thermal/thermal_dt.c
> @@ -0,0 +1,473 @@
> +/*
> + *  thermal_dt.c - Generic Thermal Management device tree support.
> + *
> + *  Copyright (C) 2013 Texas Instruments
> + *  Copyright (C) 2013 Eduardo Valentin <eduardo.valentin@ti.com>
> + *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> + *
> + *  This program is free software; you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License as published by
> + *  the Free Software Foundation; version 2 of the License.
> + *
> + *  This program is distributed in the hope that it will be useful, but
> + *  WITHOUT ANY WARRANTY; without even the implied warranty of
> + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + *  General Public License for more details.
> + *
> + *  You should have received a copy of the GNU General Public License along
> + *  with this program; if not, write to the Free Software Foundation, Inc.,
> + *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
> + *
> + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> + */
> +#include <linux/thermal.h>
> +#include <linux/slab.h>
> +#include <linux/types.h>
> +#include <linux/of_device.h>
> +#include <linux/of_platform.h>
> +#include <linux/err.h>
> +#include <linux/export.h>
> +#include <linux/string.h>
> +
> +struct __thermal_bind_params {
> +       char cooling_device[THERMAL_NAME_LENGTH];
> +};
> +
> +static
> +int thermal_of_match(struct thermal_zone_device *tz,
> +                    struct thermal_cooling_device *cdev);
> +
> +static int thermal_of_populate_bind_params(struct device *dev,
> +                                          struct device_node *node,
> +                                          struct __thermal_bind_params *__tbp,
> +                                          struct thermal_bind_params *tbp,
> +                                          int ntrips)
> +{
> +       const char *cdev_name;
> +       u32 *limits;
> +       int ret;
> +       u32 prop;
> +
> +       ret = of_property_read_u32(node, "weight", &prop);
> +       if (ret < 0) {
> +               dev_err(dev, "missing weight property\n");
> +               return ret;
> +       }
> +       tbp->weight = prop;
> +
> +       ret = of_property_read_u32(node, "mask", &prop);
> +       if (ret < 0) {
> +               dev_err(dev, "missing mask property\n");
> +               return ret;
> +       }
> +       tbp->trip_mask = prop;
> +
> +       /* this will allow us to bind with cooling devices */
> +       tbp->match = thermal_of_match;
> +
> +       ret = of_property_read_string(node, "cooling_device", &cdev_name);
> +       if (ret < 0) {
> +               dev_err(dev, "missing cooling_device property\n");
> +               return ret;
> +       }
> +       strncpy(__tbp->cooling_device, cdev_name,
> +               sizeof(__tbp->cooling_device));
> +
> +       limits = kzalloc(ntrips * sizeof(*limits) * 2, GFP_KERNEL);

Why do you use kzalloc here, but devm_kzalloc elsewhere? That'll lead to
problems as the driver gets refactored over time.

> +       if (!limits) {
> +               dev_err(dev, "not enough mem for reading limits\n");
> +               return -ENOMEM;
> +       }
> +       ret = of_property_read_u32_array(node, "limits", limits, 2 * ntrips);
> +       if (!ret) {
> +               int i = ntrips;
> +
> +               tbp->binding_limits = devm_kzalloc(dev,
> +                                                  ntrips * 2 *
> +                                                  sizeof(*tbp->binding_limits),
> +                                                  GFP_KERNEL);
> +               if (!tbp->binding_limits) {
> +                       dev_err(dev, "not enough mem for storing limits\n");
> +                       return -ENOMEM;
> +               }
> +               while (i--)
> +                       tbp->binding_limits[i] = limits[i];
> +       }
> +       kfree(limits);
> +
> +       return 0;

What if you failed to read the array? Surely you should return an error?

> +}
> +
> +struct __thermal_trip {
> +       unsigned long int temperature;
> +       unsigned long int hysteresis;
> +       enum thermal_trip_type type;
> +};
> +
> +static
> +int thermal_of_populate_trip(struct device *dev,
> +                            struct device_node *node,
> +                            struct __thermal_trip *trip)
> +{
> +       int ret;
> +       int prop;
> +
> +       ret = of_property_read_u32(node, "temperature", &prop);
> +       if (ret < 0) {
> +               dev_err(dev, "missing temperature property\n");
> +               return ret;
> +       }
> +       trip->temperature = prop;
> +
> +       ret = of_property_read_u32(node, "hysteresis", &prop);
> +       if (ret < 0) {
> +               dev_err(dev, "missing hysteresis property\n");
> +               return ret;
> +       }
> +       trip->hysteresis = prop;
> +
> +       ret = of_property_read_u32(node, "type", &prop);
> +       if (ret < 0) {
> +               dev_err(dev, "missing type property\n");
> +               return ret;
> +       }
> +       trip->type = prop;

This will require sanity checking.

> +
> +       return 0;
> +}
> +
> +struct __thermal_zone_device {
> +       enum thermal_device_mode mode;
> +       int passive_delay;
> +       int polling_delay;
> +       int mask;
> +       int ntrips;
> +       char type[THERMAL_NAME_LENGTH];
> +       struct __thermal_trip *trips;
> +       struct __thermal_bind_params *bind_params;
> +       struct thermal_bind_params *tbps;
> +       struct thermal_zone_params zone_params;
> +       int (*get_temp)(void *, unsigned long *);
> +       void *devdata;
> +};
> +
> +static struct __thermal_zone_device *
> +thermal_of_build_thermal_zone(struct device *dev, struct device_node *node)
> +{
> +       struct device_node *child, *gchild;
> +       struct __thermal_zone_device *tz;
> +       int ret, i;
> +       u32 prop;
> +
> +       if (!node) {
> +               dev_err(dev, "no thermal zone node\n");
> +               return ERR_PTR(-EINVAL);
> +       }
> +
> +       tz = devm_kzalloc(dev, sizeof(*tz), GFP_KERNEL);
> +       if (!tz) {
> +               dev_err(dev, "not enough memory for thermal of zone\n");
> +               return ERR_PTR(-ENOMEM);
> +       }
> +
> +       ret = of_property_read_u32(node, "passive_delay", &prop);
> +       if (ret < 0) {
> +               dev_err(dev, "missing passive_delay property\n");
> +               return ERR_PTR(ret);
> +       }
> +       tz->passive_delay = prop;
> +
> +       ret = of_property_read_u32(node, "polling_delay", &prop);
> +       if (ret < 0) {
> +               dev_err(dev, "missing polling_delay property\n");
> +               return ERR_PTR(ret);
> +       }
> +       tz->polling_delay = prop;
> +
> +       ret = of_property_read_u32(node, "mask", &prop);
> +       if (ret < 0) {
> +               dev_err(dev, "missing mask property\n");
> +               return ERR_PTR(ret);
> +       }
> +       tz->mask = prop;
> +
> +       /* assume node name as our zone type */
> +       strncpy(tz->type, node->name, sizeof(tz->type));
> +
> +       /* default policy */
> +       strncpy(tz->zone_params.governor_name, "step_wise",
> +               sizeof(tz->zone_params.governor_name));
> +
> +       /* trips */
> +       child = of_find_node_by_name(node, "trips");

That might not be a child node, as of_find_node_by_name walks over the
list of all nodes. Use of_get_child_by_name.

> +
> +       /* No trips provided */
> +       if (!child)
> +               goto finish;
> +
> +       tz->ntrips = of_get_child_count(child);
> +       tz->trips = devm_kzalloc(dev, tz->ntrips * sizeof(*tz->trips),
> +                                GFP_KERNEL);
> +       if (!tz->trips)
> +               return ERR_PTR(-ENOMEM);
> +       i = 0;
> +       for_each_child_of_node(child, gchild)
> +               thermal_of_populate_trip(dev, gchild, &tz->trips[i++]);

What if a child node was not a valid trip node? It seems
thermal_of_populate_trip returns errors you're ignoring.

> +
> +       /* bind_params */
> +       child = of_find_node_by_name(node, "bind_params");

Another of_get_child_by_name candidate.

> +
> +       /* No binding info */
> +       if (!child)
> +               goto finish;
> +
> +       tz->zone_params.num_tbps = of_get_child_count(child);
> +       tz->bind_params = devm_kzalloc(dev,
> +                                      tz->zone_params.num_tbps *
> +                                               sizeof(*tz->bind_params),
> +                                      GFP_KERNEL);
> +       if (!tz->bind_params)
> +               return ERR_PTR(-ENOMEM);
> +       tz->zone_params.tbp = devm_kzalloc(dev,
> +                                          tz->zone_params.num_tbps *
> +                                               sizeof(*tz->zone_params.tbp),
> +                                          GFP_KERNEL);
> +       if (!tz->zone_params.tbp)
> +               return ERR_PTR(-ENOMEM);
> +       i = 0;
> +       for_each_child_of_node(child, gchild) {
> +               thermal_of_populate_bind_params(dev, gchild,
> +                                               &tz->bind_params[i],
> +                                               &tz->zone_params.tbp[i],
> +                                               tz->ntrips);

Similarly, you're ignoring error conditions here. What if a bind_params
node was malformed?

> +               i++;
> +       }
> +
> +finish:
> +       tz->mode = THERMAL_DEVICE_ENABLED;
> +
> +       return tz;
> +}
> +
> +static
> +int thermal_of_match(struct thermal_zone_device *tz,
> +                    struct thermal_cooling_device *cdev)
> +{
> +       struct __thermal_zone_device *data = tz->devdata;
> +       int i;
> +
> +       for (i = 0; i < data->zone_params.num_tbps; i++) {
> +               if (!strncmp(data->bind_params[i].cooling_device,
> +                            cdev->type,
> +                            strlen(data->bind_params[i].cooling_device)) &&
> +                   (data->zone_params.tbp[i].trip_mask & (1 << i)))
> +                       return 0;
> +       }
> +
> +       return -EINVAL;
> +}

I'm not keen on binding to cooling devices using a string, as suddenly a
name to allow humans to inspect the system is turned into an ABI.

> +
> +static
> +int of_thermal_get_temp(struct thermal_zone_device *tz,
> +                       unsigned long *temp)
> +{
> +       struct __thermal_zone_device *data = tz->devdata;
> +
> +       return data->get_temp(data->devdata, temp);
> +}
> +
> +static
> +int of_thermal_get_mode(struct thermal_zone_device *tz,
> +                       enum thermal_device_mode *mode)
> +{
> +       struct __thermal_zone_device *data = tz->devdata;
> +
> +       *mode = data->mode;
> +
> +       return 0;
> +}
> +
> +static
> +int of_thermal_set_mode(struct thermal_zone_device *tz,
> +                       enum thermal_device_mode mode)
> +{
> +       struct __thermal_zone_device *data = tz->devdata;
> +
> +       mutex_lock(&tz->lock);
> +
> +       if (mode == THERMAL_DEVICE_ENABLED)
> +               tz->polling_delay = data->polling_delay;
> +       else
> +               tz->polling_delay = 0;
> +
> +       mutex_unlock(&tz->lock);
> +
> +       data->mode = mode;
> +       thermal_zone_device_update(tz);
> +
> +       return 0;
> +}
> +
> +static
> +int of_thermal_get_trip_type(struct thermal_zone_device *tz, int trip,
> +                            enum thermal_trip_type *type)
> +{
> +       struct __thermal_zone_device *data = tz->devdata;
> +
> +       if (trip >= data->ntrips || trip < 0)
> +               return -EDOM;

It's far more common to use -EINVAL.

> +
> +       *type = data->trips[trip].type;
> +
> +       return 0;
> +}
> +
> +static
> +int of_thermal_get_trip_temp(struct thermal_zone_device *tz, int trip,
> +                            unsigned long *temp)
> +{
> +       struct __thermal_zone_device *data = tz->devdata;
> +
> +       if (trip >= data->ntrips || trip < 0)
> +               return -EDOM;
> +
> +       *temp = data->trips[trip].temperature;
> +
> +       return 0;
> +}
> +
> +static
> +int of_thermal_set_trip_temp(struct thermal_zone_device *tz, int trip,
> +                            unsigned long temp)
> +{
> +       struct __thermal_zone_device *data = tz->devdata;
> +
> +       if (trip >= data->ntrips || trip < 0)
> +               return -EDOM;
> +
> +       /* thermal fw should take care of data->mask & (1 << trip) */
> +       data->trips[trip].temperature = temp;
> +
> +       return 0;
> +}
> +
> +static
> +int of_thermal_get_trip_hyst(struct thermal_zone_device *tz, int trip,
> +                            unsigned long *hyst)
> +{
> +       struct __thermal_zone_device *data = tz->devdata;
> +
> +       if (trip >= data->ntrips || trip < 0)
> +               return -EDOM;
> +
> +       *hyst = data->trips[trip].hysteresis;
> +
> +       return 0;
> +}
> +
> +static
> +int of_thermal_set_trip_hyst(struct thermal_zone_device *tz, int trip,
> +                            unsigned long hyst)
> +{
> +       struct __thermal_zone_device *data = tz->devdata;
> +
> +       if (trip >= data->ntrips || trip < 0)
> +               return -EDOM;
> +
> +       /* thermal fw should take care of data->mask & (1 << trip) */

Could you elaborate on that comment?

> +       data->trips[trip].hysteresis = hyst;
> +
> +       return 0;
> +}

[...]

Thanks,
Mark.

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

* Re: [lm-sensors] [RFC PATCH 02/14] drivers: thermal: introduce device tree parser
@ 2013-08-27 10:22     ` Mark Rutland
  0 siblings, 0 replies; 100+ messages in thread
From: Mark Rutland @ 2013-08-27 10:22 UTC (permalink / raw)
  To: Eduardo Valentin
  Cc: swarren, Pawel Moll, ian.campbell, grant.likely, rob.herring,
	linux, rui.zhang, wni, durgadoss.r, linux-pm, devicetree,
	lm-sensors, linux-kernel

Hi,

On Sat, Aug 24, 2013 at 12:15:43AM +0100, Eduardo Valentin wrote:
> In order to be able to build thermal policies
> based on generic sensors, like I2C device, that
> can be places in different points on different boards,
> there is a need to have a way to feed board dependent
> data into the thermal framework.
> 
> This patch introduces a thermal data parser for device
> tree. The parsed data is used to build thermal zones
> and thermal binding parameters. The output data
> can then be used to deploy thermal policies.
> 
> This patch adds also documentation regarding this
> API and how to define tree nodes to use
> this infrastructure.
> 
> Cc: Zhang Rui <rui.zhang@intel.com>
> Cc: linux-pm@vger.kernel.org
> Cc: linux-kernel@vger.kernel.org
> Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
> ---
>  .../devicetree/bindings/thermal/thermal.txt        | 160 +++++++
>  drivers/thermal/Kconfig                            |  13 +
>  drivers/thermal/Makefile                           |   1 +
>  drivers/thermal/thermal_dt.c                       | 473 +++++++++++++++++++++
>  include/dt-bindings/thermal/thermal.h              |  27 ++
>  include/linux/thermal.h                            |   3 +
>  6 files changed, 677 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/thermal/thermal.txt
>  create mode 100644 drivers/thermal/thermal_dt.c
>  create mode 100644 include/dt-bindings/thermal/thermal.h
> 
> diff --git a/Documentation/devicetree/bindings/thermal/thermal.txt b/Documentation/devicetree/bindings/thermal/thermal.txt
> new file mode 100644
> index 0000000..af20ab0
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/thermal/thermal.txt
> @@ -0,0 +1,160 @@
> +----------------------------------------
> +Thermal Framework Device Tree descriptor
> +----------------------------------------
> +
> +This file describes how to define a thermal structure using device tree.
> +A thermal structure includes thermal zones and their components, such
> +as name, trip points, polling intervals and cooling devices binding
> +descriptors. A binding descriptor may contain information on how to
> +react, with a cooling stepped action or a weight on a fair share.
> +The target of device tree thermal descriptors is to describe only
> +the hardware thermal aspects, not how the system must control or which
> +algorithm or policy must take place. It follows a description of each
> +type of device tree node.
> +
> +****
> +trip
> +****
> +
> +The trip node is a node to describe a point in the temperature domain
> +in which the system takes an action. This node describes just the point,
> +not the action.
> +
> +A node describing a trip must contain:
> +- temperature: the trip temperature level, in milliCelsius.
> +- hysteresis: a (low) hysteresis value on 'temperature'. This is a relative
> +value, in milliCelsius.

Presumably this is a single (u32) cell?

> +- type: the trip type. Here is the type mapping:
> +       THERMAL_TRIP_ACTIVE
> +       THERMAL_TRIP_PASSIVE
> +       THERMAL_TRIP_HOT
> +       THERMAL_TRIP_CRITICAL

What type is this property?

What are these values? Do you need to refer to a header somewhere?
Symbolic constants should have an associated value for an ABI.

> +
> +**********
> +bind_param
> +**********
> +
> +The bind_param node is a node to describe how cooling devices get assigned
> +to trip points of the zone. The cooling devices are expected to be loaded
> +in the target system.
> +
> +A node describing a bind_param must contain:
> +- cooling_device: A string with the cooling device name.

Please use '-' rather than '_' in bindings. That's the normal devicetree
convention, and there's no point gonig against it and causing more
confusion.

What are valid values of this string, and what do they mean?

Why not a phandle + cells binding to cooling devices?

> +- weight: The 'influence' of a particular cooling device on this zone.
> +             This is on a percentage scale. The sum of all these weights
> +             (for a particular zone) cannot exceed 100.

This is a bit fuzzy, and certainly needs more guidance.

> +- trip_mask: This is a bit mask that gives the binding relation between
> +               this thermal zone and cdev, for a particular trip point.
> +               If nth bit is set, then the cdev and thermal zone are bound
> +               for trip point n.

What type is this?

The nth bit from which end?

Could you explain what "bound for trip point n" means?

Just because this is a bitmask in Linux does not mean it needs to be so
in the dt.

> +- limits: An array integers consisting of 2-tuples items, and each item means
> +  lower and upper state limits, like <min-state max-state>.
> +
> +**************************
> +temperature sensor devices
> +**************************
> +
> +Temperature sensor devices have to be linked to a specific thermal zone.
> +This is done by means of the 'monitored-zones' list.
> +- monitored-zones: A list of thermal zones phandles, identifying which
> +thermal zones the temperature sensor device is used to monitor.

Why does this need to be described that way around?

Can the zone not have a link to the sensor(s) it needs?

> +
> +************
> +thermal_zone
> +************
> +
> +The thermal_zone node is the node containing all the required info
> +for describing a thermal zone, including its cdev bindings. The thermal_zone
> +node must contain, apart from its own properties, one node containing
> +trip nodes and one node containing all the zone bind parameters.
> +
> +Required properties:
> +- mask: Bit string: If 'n'th bit is set, then trip point 'n' is writeable.

What type is a bit string in devicetree? I'm aware of cells and (byte)
strings, but not bit strings.

What does 'writeable' mean in this context?

There's presumably a better name than 'mask'.

> +
> +- passive_delay: number of milliseconds to wait between polls when
> +  performing passive cooling.
> +
> +- polling_delay: number of milliseconds to wait between polls when checking.

These sound very much like configuration of the driver rather than
hardware description. What if my temperature sensor can generate an
interrupt at some trigger temperature? Why would I need polling times?

Why does this need to be in the dt at all? Surely the OS can choose some
sensible polling period, possibly dynamically?

> +
> +- #thermal-cells: An integer that is used to specify how many cells compose
> +  sensor ids.

I don't see why this is necessary. If the zone itself described its
related sensors rather than the other way around, we wouldn't need it at
all. Most bindings so far have consumers link to their providers rather
than the other way around.

> +
> +Below is an example:
> +cpu_thermal: thermal_zone {
> +            #thermal-cells = <1>;
> +            mask = <0x03>; /* trips writability */
> +            passive_delay = <250>; /* milliseconds */
> +            polling_delay = <1000>; /* milliseconds */
> +            trips {
> +                    alert@100000{
> +                            temperature = <100000>; /* milliCelsius */
> +                            hysteresis = <0>; /* milliCelsius */
> +                            type = <THERMAL_TRIP_PASSIVE>;
> +                    };
> +                    crit@125000{
> +                            temperature = <125000>; /* milliCelsius */
> +                            hysteresis = <0>; /* milliCelsius */
> +                            type = <THERMAL_TRIP_CRITICAL>;
> +                    };
> +            };
> +            bind_params {
> +                    action@0{
> +                            cooling_device = "thermal-cpufreq";

NAK. That value was not defined anywhere, and represents Linux
infrastructure rather than hardware.

For this case, we could just as easily describe the thermal points, and
if no physical cooling device (e.g. a fan) is present, assume
cpufreq-base cooling.  Other OSs could choose to do otherwise, and we
could change later...

> +                            weight = <100>; /* percentage */
> +                            mask = <0x01>;

This should presumably be trip-mask (assuming my suggested corrections).

What is it supposed to mean here?

> +                           limits = <
> +                             /* lower-state            upper-state */
> +                               1                       THERMAL_NO_LIMITS
> +                               THERMAL_NO_LIMITS       THERMAL_NO_LIMITS
> +                           >;
> +                    };
> +            };
> +};
> +
> +sensor: adc@0xFFFF {
> +       ...
> +       monitored-zones = <&cpu_thermal 0>;
> +};
> +
> +cpu@0 {
> +       ...
> +       cooling-zones = <&cpu_thermal>;
> +};
> +
> +In the example above, the ADC sensor at address 0xFFFF is used to monitor
> +the zone 'cpu_thermal' using its the sensor 0. The cpu@0 device is also linked
> +to the same thermal zone 'cpu_thermal' as a cooling device.

Huh? That seems to imply the the '0' in '<&cpu_thermal 0>' on the sensor
node describes a property of the sensor rather than the thermal node,
unless I've misunderstood?

> +
> +***************
> +cpufreq-cooling
> +***************
> +
> +The generic cpu cooling (freq clipping) can be loaded by the
> +generic cpufreq-cpu0 driver in case the device tree node informs
> +this need.
> +
> +In order to load the cpufreq cooling device, it is possible to
> +inform that the cpu needs cooling by adding the list of thermal zones
> +in the 'cooling-zones' property at the cpu0 phandle.

This should be reworded so as to describe the binding rather than the
Linux behaviour based on the binding.

> +
> +Example:
> +       cpus {
> +               cpu@0 {
> +                       operating-points = <
> +                               /* kHz    uV */
> +                               800000  1313000
> +                               1008000 1375000
> +                       >;
> +                       cooling-zones = <&cpu_thermal>;
> +               };
> +       ...
> +       };
> +
> +The above will cause the cpufreq-cpu0 driver to understand that
> +the cpu will need passive cooling and while probing that node it will
> +also load the cpufreq cpu cooling device in that system.

The above describe that the CPU is part of a cooling (thermal?) zone and
requires cooling.

> +
> +However, be advised that this flag will not describe what needs to
> +be done or how the cpufreq cooling device will be used. In order to
> +accomplish this, one needs to write a phandle for a thermal zone, as
> +described in the section 'thermal_zone'.

The above already has a phandle to a thermal (cooling?) zone.

Please choose either cooling zone or thermal zone, having the two names
makes this more confusing than necessary.

> diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
> index 7fb16bc..753f0dc 100644
> --- a/drivers/thermal/Kconfig
> +++ b/drivers/thermal/Kconfig
> @@ -29,6 +29,19 @@ config THERMAL_HWMON
>           Say 'Y' here if you want all thermal sensors to
>           have hwmon sysfs interface too.
> 
> +config THERMAL_OF
> +       bool
> +       prompt "APIs to parse thermal data out of device tree"
> +       depends on OF
> +       default y
> +       help
> +         This options provides helpers to add the support to
> +         read and parse thermal data definitions out of the
> +         device tree blob.
> +
> +         Say 'Y' here if you need to build thermal infrastructure
> +         based on device tree.
> +
>  choice
>         prompt "Default Thermal governor"
>         default THERMAL_DEFAULT_GOV_STEP_WISE
> diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
> index 24cb894..eedb273 100644
> --- a/drivers/thermal/Makefile
> +++ b/drivers/thermal/Makefile
> @@ -7,6 +7,7 @@ thermal_sys-y                   += thermal_core.o
> 
>  # interface to/from other layers providing sensors
>  thermal_sys-$(CONFIG_THERMAL_HWMON)            += thermal_hwmon.o
> +thermal_sys-$(CONFIG_THERMAL_OF)               += thermal_dt.o
> 
>  # governors
>  thermal_sys-$(CONFIG_THERMAL_GOV_FAIR_SHARE)   += fair_share.o
> diff --git a/drivers/thermal/thermal_dt.c b/drivers/thermal/thermal_dt.c
> new file mode 100644
> index 0000000..cc35485
> --- /dev/null
> +++ b/drivers/thermal/thermal_dt.c
> @@ -0,0 +1,473 @@
> +/*
> + *  thermal_dt.c - Generic Thermal Management device tree support.
> + *
> + *  Copyright (C) 2013 Texas Instruments
> + *  Copyright (C) 2013 Eduardo Valentin <eduardo.valentin@ti.com>
> + *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> + *
> + *  This program is free software; you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License as published by
> + *  the Free Software Foundation; version 2 of the License.
> + *
> + *  This program is distributed in the hope that it will be useful, but
> + *  WITHOUT ANY WARRANTY; without even the implied warranty of
> + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + *  General Public License for more details.
> + *
> + *  You should have received a copy of the GNU General Public License along
> + *  with this program; if not, write to the Free Software Foundation, Inc.,
> + *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
> + *
> + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> + */
> +#include <linux/thermal.h>
> +#include <linux/slab.h>
> +#include <linux/types.h>
> +#include <linux/of_device.h>
> +#include <linux/of_platform.h>
> +#include <linux/err.h>
> +#include <linux/export.h>
> +#include <linux/string.h>
> +
> +struct __thermal_bind_params {
> +       char cooling_device[THERMAL_NAME_LENGTH];
> +};
> +
> +static
> +int thermal_of_match(struct thermal_zone_device *tz,
> +                    struct thermal_cooling_device *cdev);
> +
> +static int thermal_of_populate_bind_params(struct device *dev,
> +                                          struct device_node *node,
> +                                          struct __thermal_bind_params *__tbp,
> +                                          struct thermal_bind_params *tbp,
> +                                          int ntrips)
> +{
> +       const char *cdev_name;
> +       u32 *limits;
> +       int ret;
> +       u32 prop;
> +
> +       ret = of_property_read_u32(node, "weight", &prop);
> +       if (ret < 0) {
> +               dev_err(dev, "missing weight property\n");
> +               return ret;
> +       }
> +       tbp->weight = prop;
> +
> +       ret = of_property_read_u32(node, "mask", &prop);
> +       if (ret < 0) {
> +               dev_err(dev, "missing mask property\n");
> +               return ret;
> +       }
> +       tbp->trip_mask = prop;
> +
> +       /* this will allow us to bind with cooling devices */
> +       tbp->match = thermal_of_match;
> +
> +       ret = of_property_read_string(node, "cooling_device", &cdev_name);
> +       if (ret < 0) {
> +               dev_err(dev, "missing cooling_device property\n");
> +               return ret;
> +       }
> +       strncpy(__tbp->cooling_device, cdev_name,
> +               sizeof(__tbp->cooling_device));
> +
> +       limits = kzalloc(ntrips * sizeof(*limits) * 2, GFP_KERNEL);

Why do you use kzalloc here, but devm_kzalloc elsewhere? That'll lead to
problems as the driver gets refactored over time.

> +       if (!limits) {
> +               dev_err(dev, "not enough mem for reading limits\n");
> +               return -ENOMEM;
> +       }
> +       ret = of_property_read_u32_array(node, "limits", limits, 2 * ntrips);
> +       if (!ret) {
> +               int i = ntrips;
> +
> +               tbp->binding_limits = devm_kzalloc(dev,
> +                                                  ntrips * 2 *
> +                                                  sizeof(*tbp->binding_limits),
> +                                                  GFP_KERNEL);
> +               if (!tbp->binding_limits) {
> +                       dev_err(dev, "not enough mem for storing limits\n");
> +                       return -ENOMEM;
> +               }
> +               while (i--)
> +                       tbp->binding_limits[i] = limits[i];
> +       }
> +       kfree(limits);
> +
> +       return 0;

What if you failed to read the array? Surely you should return an error?

> +}
> +
> +struct __thermal_trip {
> +       unsigned long int temperature;
> +       unsigned long int hysteresis;
> +       enum thermal_trip_type type;
> +};
> +
> +static
> +int thermal_of_populate_trip(struct device *dev,
> +                            struct device_node *node,
> +                            struct __thermal_trip *trip)
> +{
> +       int ret;
> +       int prop;
> +
> +       ret = of_property_read_u32(node, "temperature", &prop);
> +       if (ret < 0) {
> +               dev_err(dev, "missing temperature property\n");
> +               return ret;
> +       }
> +       trip->temperature = prop;
> +
> +       ret = of_property_read_u32(node, "hysteresis", &prop);
> +       if (ret < 0) {
> +               dev_err(dev, "missing hysteresis property\n");
> +               return ret;
> +       }
> +       trip->hysteresis = prop;
> +
> +       ret = of_property_read_u32(node, "type", &prop);
> +       if (ret < 0) {
> +               dev_err(dev, "missing type property\n");
> +               return ret;
> +       }
> +       trip->type = prop;

This will require sanity checking.

> +
> +       return 0;
> +}
> +
> +struct __thermal_zone_device {
> +       enum thermal_device_mode mode;
> +       int passive_delay;
> +       int polling_delay;
> +       int mask;
> +       int ntrips;
> +       char type[THERMAL_NAME_LENGTH];
> +       struct __thermal_trip *trips;
> +       struct __thermal_bind_params *bind_params;
> +       struct thermal_bind_params *tbps;
> +       struct thermal_zone_params zone_params;
> +       int (*get_temp)(void *, unsigned long *);
> +       void *devdata;
> +};
> +
> +static struct __thermal_zone_device *
> +thermal_of_build_thermal_zone(struct device *dev, struct device_node *node)
> +{
> +       struct device_node *child, *gchild;
> +       struct __thermal_zone_device *tz;
> +       int ret, i;
> +       u32 prop;
> +
> +       if (!node) {
> +               dev_err(dev, "no thermal zone node\n");
> +               return ERR_PTR(-EINVAL);
> +       }
> +
> +       tz = devm_kzalloc(dev, sizeof(*tz), GFP_KERNEL);
> +       if (!tz) {
> +               dev_err(dev, "not enough memory for thermal of zone\n");
> +               return ERR_PTR(-ENOMEM);
> +       }
> +
> +       ret = of_property_read_u32(node, "passive_delay", &prop);
> +       if (ret < 0) {
> +               dev_err(dev, "missing passive_delay property\n");
> +               return ERR_PTR(ret);
> +       }
> +       tz->passive_delay = prop;
> +
> +       ret = of_property_read_u32(node, "polling_delay", &prop);
> +       if (ret < 0) {
> +               dev_err(dev, "missing polling_delay property\n");
> +               return ERR_PTR(ret);
> +       }
> +       tz->polling_delay = prop;
> +
> +       ret = of_property_read_u32(node, "mask", &prop);
> +       if (ret < 0) {
> +               dev_err(dev, "missing mask property\n");
> +               return ERR_PTR(ret);
> +       }
> +       tz->mask = prop;
> +
> +       /* assume node name as our zone type */
> +       strncpy(tz->type, node->name, sizeof(tz->type));
> +
> +       /* default policy */
> +       strncpy(tz->zone_params.governor_name, "step_wise",
> +               sizeof(tz->zone_params.governor_name));
> +
> +       /* trips */
> +       child = of_find_node_by_name(node, "trips");

That might not be a child node, as of_find_node_by_name walks over the
list of all nodes. Use of_get_child_by_name.

> +
> +       /* No trips provided */
> +       if (!child)
> +               goto finish;
> +
> +       tz->ntrips = of_get_child_count(child);
> +       tz->trips = devm_kzalloc(dev, tz->ntrips * sizeof(*tz->trips),
> +                                GFP_KERNEL);
> +       if (!tz->trips)
> +               return ERR_PTR(-ENOMEM);
> +       i = 0;
> +       for_each_child_of_node(child, gchild)
> +               thermal_of_populate_trip(dev, gchild, &tz->trips[i++]);

What if a child node was not a valid trip node? It seems
thermal_of_populate_trip returns errors you're ignoring.

> +
> +       /* bind_params */
> +       child = of_find_node_by_name(node, "bind_params");

Another of_get_child_by_name candidate.

> +
> +       /* No binding info */
> +       if (!child)
> +               goto finish;
> +
> +       tz->zone_params.num_tbps = of_get_child_count(child);
> +       tz->bind_params = devm_kzalloc(dev,
> +                                      tz->zone_params.num_tbps *
> +                                               sizeof(*tz->bind_params),
> +                                      GFP_KERNEL);
> +       if (!tz->bind_params)
> +               return ERR_PTR(-ENOMEM);
> +       tz->zone_params.tbp = devm_kzalloc(dev,
> +                                          tz->zone_params.num_tbps *
> +                                               sizeof(*tz->zone_params.tbp),
> +                                          GFP_KERNEL);
> +       if (!tz->zone_params.tbp)
> +               return ERR_PTR(-ENOMEM);
> +       i = 0;
> +       for_each_child_of_node(child, gchild) {
> +               thermal_of_populate_bind_params(dev, gchild,
> +                                               &tz->bind_params[i],
> +                                               &tz->zone_params.tbp[i],
> +                                               tz->ntrips);

Similarly, you're ignoring error conditions here. What if a bind_params
node was malformed?

> +               i++;
> +       }
> +
> +finish:
> +       tz->mode = THERMAL_DEVICE_ENABLED;
> +
> +       return tz;
> +}
> +
> +static
> +int thermal_of_match(struct thermal_zone_device *tz,
> +                    struct thermal_cooling_device *cdev)
> +{
> +       struct __thermal_zone_device *data = tz->devdata;
> +       int i;
> +
> +       for (i = 0; i < data->zone_params.num_tbps; i++) {
> +               if (!strncmp(data->bind_params[i].cooling_device,
> +                            cdev->type,
> +                            strlen(data->bind_params[i].cooling_device)) &&
> +                   (data->zone_params.tbp[i].trip_mask & (1 << i)))
> +                       return 0;
> +       }
> +
> +       return -EINVAL;
> +}

I'm not keen on binding to cooling devices using a string, as suddenly a
name to allow humans to inspect the system is turned into an ABI.

> +
> +static
> +int of_thermal_get_temp(struct thermal_zone_device *tz,
> +                       unsigned long *temp)
> +{
> +       struct __thermal_zone_device *data = tz->devdata;
> +
> +       return data->get_temp(data->devdata, temp);
> +}
> +
> +static
> +int of_thermal_get_mode(struct thermal_zone_device *tz,
> +                       enum thermal_device_mode *mode)
> +{
> +       struct __thermal_zone_device *data = tz->devdata;
> +
> +       *mode = data->mode;
> +
> +       return 0;
> +}
> +
> +static
> +int of_thermal_set_mode(struct thermal_zone_device *tz,
> +                       enum thermal_device_mode mode)
> +{
> +       struct __thermal_zone_device *data = tz->devdata;
> +
> +       mutex_lock(&tz->lock);
> +
> +       if (mode = THERMAL_DEVICE_ENABLED)
> +               tz->polling_delay = data->polling_delay;
> +       else
> +               tz->polling_delay = 0;
> +
> +       mutex_unlock(&tz->lock);
> +
> +       data->mode = mode;
> +       thermal_zone_device_update(tz);
> +
> +       return 0;
> +}
> +
> +static
> +int of_thermal_get_trip_type(struct thermal_zone_device *tz, int trip,
> +                            enum thermal_trip_type *type)
> +{
> +       struct __thermal_zone_device *data = tz->devdata;
> +
> +       if (trip >= data->ntrips || trip < 0)
> +               return -EDOM;

It's far more common to use -EINVAL.

> +
> +       *type = data->trips[trip].type;
> +
> +       return 0;
> +}
> +
> +static
> +int of_thermal_get_trip_temp(struct thermal_zone_device *tz, int trip,
> +                            unsigned long *temp)
> +{
> +       struct __thermal_zone_device *data = tz->devdata;
> +
> +       if (trip >= data->ntrips || trip < 0)
> +               return -EDOM;
> +
> +       *temp = data->trips[trip].temperature;
> +
> +       return 0;
> +}
> +
> +static
> +int of_thermal_set_trip_temp(struct thermal_zone_device *tz, int trip,
> +                            unsigned long temp)
> +{
> +       struct __thermal_zone_device *data = tz->devdata;
> +
> +       if (trip >= data->ntrips || trip < 0)
> +               return -EDOM;
> +
> +       /* thermal fw should take care of data->mask & (1 << trip) */
> +       data->trips[trip].temperature = temp;
> +
> +       return 0;
> +}
> +
> +static
> +int of_thermal_get_trip_hyst(struct thermal_zone_device *tz, int trip,
> +                            unsigned long *hyst)
> +{
> +       struct __thermal_zone_device *data = tz->devdata;
> +
> +       if (trip >= data->ntrips || trip < 0)
> +               return -EDOM;
> +
> +       *hyst = data->trips[trip].hysteresis;
> +
> +       return 0;
> +}
> +
> +static
> +int of_thermal_set_trip_hyst(struct thermal_zone_device *tz, int trip,
> +                            unsigned long hyst)
> +{
> +       struct __thermal_zone_device *data = tz->devdata;
> +
> +       if (trip >= data->ntrips || trip < 0)
> +               return -EDOM;
> +
> +       /* thermal fw should take care of data->mask & (1 << trip) */

Could you elaborate on that comment?

> +       data->trips[trip].hysteresis = hyst;
> +
> +       return 0;
> +}

[...]

Thanks,
Mark.

_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

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

* Re: [RFC PATCH 03/14] hwmon: lm75: expose to thermal fw via DT nodes
  2013-08-23 23:15   ` Eduardo Valentin
@ 2013-08-27 10:26     ` Mark Rutland
  -1 siblings, 0 replies; 100+ messages in thread
From: Mark Rutland @ 2013-08-27 10:26 UTC (permalink / raw)
  To: Eduardo Valentin
  Cc: swarren, Pawel Moll, ian.campbell, grant.likely, rob.herring,
	linux, rui.zhang, wni, durgadoss.r, linux-pm, devicetree,
	lm-sensors, linux-kernel, Jean Delvare

On Sat, Aug 24, 2013 at 12:15:44AM +0100, Eduardo Valentin wrote:
> This patch adds to lm75 temperature sensor the possibility
> to expose itself as thermal zone device, registered on the
> thermal framework.
> 
> The thermal zone is built only if a device tree node
> describing a thermal zone for this sensor is present
> inside the lm75 DT node. Otherwise, the driver behavior
> will be the same.

There'll need to be a binding document if you're extending the lm75
binding. See the comment at the top of [1]. However, I don't think you
need this at all, as I explain in my comments on the previous patch.

Thanks,
Mark.

[1] Documentation/devicetree/bindings/i2c/trivial-devices.txt

> 
> Cc: Jean Delvare <khali@linux-fr.org>
> Cc: Guenter Roeck <linux@roeck-us.net>
> Cc: lm-sensors@lm-sensors.org
> Cc: linux-kernel@vger.kernel.org
> Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
> ---
>  drivers/hwmon/lm75.c | 31 +++++++++++++++++++++++++++++++
>  1 file changed, 31 insertions(+)
> 
> diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c
> index c03b490..dc55908 100644
> --- a/drivers/hwmon/lm75.c
> +++ b/drivers/hwmon/lm75.c
> @@ -27,6 +27,8 @@
>  #include <linux/hwmon-sysfs.h>
>  #include <linux/err.h>
>  #include <linux/mutex.h>
> +#include <linux/thermal.h>
> +#include <linux/of.h>
>  #include "lm75.h"
>  
>  
> @@ -70,6 +72,7 @@ static const u8 LM75_REG_TEMP[3] = {
>  /* Each client has this additional data */
>  struct lm75_data {
>  	struct device		*hwmon_dev;
> +	struct thermal_zone_device	*tz;
>  	struct mutex		update_lock;
>  	u8			orig_conf;
>  	u8			resolution;	/* In bits, between 9 and 12 */
> @@ -92,6 +95,19 @@ static struct lm75_data *lm75_update_device(struct device *dev);
>  
>  /* sysfs attributes for hwmon */
>  
> +static int lm75_read_temp(void *dev, unsigned long *temp)
> +{
> +	struct lm75_data *data = lm75_update_device(dev);
> +
> +	if (IS_ERR(data))
> +		return PTR_ERR(data);
> +
> +	*temp = ((data->temp[0] >> (16 - data->resolution)) * 1000) >>
> +			(data->resolution - 8);
> +
> +	return 0;
> +}
> +
>  static ssize_t show_temp(struct device *dev, struct device_attribute *da,
>  			 char *buf)
>  {
> @@ -271,11 +287,25 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id)
>  		goto exit_remove;
>  	}
>  
> +	if (of_find_property(client->dev.of_node, "monitored-zones", NULL)) {
> +		data->tz = thermal_zone_of_device_register(&client->dev,
> +							   0,
> +							   false, /* -hwmon */
> +							   &client->dev,
> +							   lm75_read_temp);
> +		if (IS_ERR(data->tz)) {
> +			status = PTR_ERR(data->tz);
> +			goto exit_hwmon;
> +		}
> +	}
> +
>  	dev_info(&client->dev, "%s: sensor '%s'\n",
>  		 dev_name(data->hwmon_dev), client->name);
>  
>  	return 0;
>  
> +exit_hwmon:
> +	hwmon_device_unregister(data->hwmon_dev);
>  exit_remove:
>  	sysfs_remove_group(&client->dev.kobj, &lm75_group);
>  	return status;
> @@ -285,6 +315,7 @@ static int lm75_remove(struct i2c_client *client)
>  {
>  	struct lm75_data *data = i2c_get_clientdata(client);
>  
> +	thermal_zone_device_unregister(data->tz);
>  	hwmon_device_unregister(data->hwmon_dev);
>  	sysfs_remove_group(&client->dev.kobj, &lm75_group);
>  	lm75_write_value(client, LM75_REG_CONF, data->orig_conf);
> -- 
> 1.8.2.1.342.gfa7285d
> 
> 

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

* Re: [lm-sensors] [RFC PATCH 03/14] hwmon: lm75: expose to thermal fw via DT nodes
@ 2013-08-27 10:26     ` Mark Rutland
  0 siblings, 0 replies; 100+ messages in thread
From: Mark Rutland @ 2013-08-27 10:26 UTC (permalink / raw)
  To: Eduardo Valentin
  Cc: swarren, Pawel Moll, ian.campbell, grant.likely, rob.herring,
	linux, rui.zhang, wni, durgadoss.r, linux-pm, devicetree,
	lm-sensors, linux-kernel, Jean Delvare

On Sat, Aug 24, 2013 at 12:15:44AM +0100, Eduardo Valentin wrote:
> This patch adds to lm75 temperature sensor the possibility
> to expose itself as thermal zone device, registered on the
> thermal framework.
> 
> The thermal zone is built only if a device tree node
> describing a thermal zone for this sensor is present
> inside the lm75 DT node. Otherwise, the driver behavior
> will be the same.

There'll need to be a binding document if you're extending the lm75
binding. See the comment at the top of [1]. However, I don't think you
need this at all, as I explain in my comments on the previous patch.

Thanks,
Mark.

[1] Documentation/devicetree/bindings/i2c/trivial-devices.txt

> 
> Cc: Jean Delvare <khali@linux-fr.org>
> Cc: Guenter Roeck <linux@roeck-us.net>
> Cc: lm-sensors@lm-sensors.org
> Cc: linux-kernel@vger.kernel.org
> Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
> ---
>  drivers/hwmon/lm75.c | 31 +++++++++++++++++++++++++++++++
>  1 file changed, 31 insertions(+)
> 
> diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c
> index c03b490..dc55908 100644
> --- a/drivers/hwmon/lm75.c
> +++ b/drivers/hwmon/lm75.c
> @@ -27,6 +27,8 @@
>  #include <linux/hwmon-sysfs.h>
>  #include <linux/err.h>
>  #include <linux/mutex.h>
> +#include <linux/thermal.h>
> +#include <linux/of.h>
>  #include "lm75.h"
>  
>  
> @@ -70,6 +72,7 @@ static const u8 LM75_REG_TEMP[3] = {
>  /* Each client has this additional data */
>  struct lm75_data {
>  	struct device		*hwmon_dev;
> +	struct thermal_zone_device	*tz;
>  	struct mutex		update_lock;
>  	u8			orig_conf;
>  	u8			resolution;	/* In bits, between 9 and 12 */
> @@ -92,6 +95,19 @@ static struct lm75_data *lm75_update_device(struct device *dev);
>  
>  /* sysfs attributes for hwmon */
>  
> +static int lm75_read_temp(void *dev, unsigned long *temp)
> +{
> +	struct lm75_data *data = lm75_update_device(dev);
> +
> +	if (IS_ERR(data))
> +		return PTR_ERR(data);
> +
> +	*temp = ((data->temp[0] >> (16 - data->resolution)) * 1000) >>
> +			(data->resolution - 8);
> +
> +	return 0;
> +}
> +
>  static ssize_t show_temp(struct device *dev, struct device_attribute *da,
>  			 char *buf)
>  {
> @@ -271,11 +287,25 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id)
>  		goto exit_remove;
>  	}
>  
> +	if (of_find_property(client->dev.of_node, "monitored-zones", NULL)) {
> +		data->tz = thermal_zone_of_device_register(&client->dev,
> +							   0,
> +							   false, /* -hwmon */
> +							   &client->dev,
> +							   lm75_read_temp);
> +		if (IS_ERR(data->tz)) {
> +			status = PTR_ERR(data->tz);
> +			goto exit_hwmon;
> +		}
> +	}
> +
>  	dev_info(&client->dev, "%s: sensor '%s'\n",
>  		 dev_name(data->hwmon_dev), client->name);
>  
>  	return 0;
>  
> +exit_hwmon:
> +	hwmon_device_unregister(data->hwmon_dev);
>  exit_remove:
>  	sysfs_remove_group(&client->dev.kobj, &lm75_group);
>  	return status;
> @@ -285,6 +315,7 @@ static int lm75_remove(struct i2c_client *client)
>  {
>  	struct lm75_data *data = i2c_get_clientdata(client);
>  
> +	thermal_zone_device_unregister(data->tz);
>  	hwmon_device_unregister(data->hwmon_dev);
>  	sysfs_remove_group(&client->dev.kobj, &lm75_group);
>  	lm75_write_value(client, LM75_REG_CONF, data->orig_conf);
> -- 
> 1.8.2.1.342.gfa7285d
> 
> 

_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

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

* Re: [RFC PATCH 04/14] hwmon: tmp102: expose to thermal fw via DT nodes
  2013-08-23 23:15   ` Eduardo Valentin
@ 2013-08-27 10:27     ` Mark Rutland
  -1 siblings, 0 replies; 100+ messages in thread
From: Mark Rutland @ 2013-08-27 10:27 UTC (permalink / raw)
  To: Eduardo Valentin
  Cc: swarren, Pawel Moll, ian.campbell, grant.likely, rob.herring,
	linux, rui.zhang, wni, durgadoss.r, linux-pm, devicetree,
	lm-sensors, linux-kernel, Jean Delvare

On Sat, Aug 24, 2013 at 12:15:45AM +0100, Eduardo Valentin wrote:
> This patch adds to tmp102 temperature sensor the possibility
> to expose itself as thermal zone device, registered on the
> thermal framework.
> 
> The thermal zone is built only if a device tree node
> describing a thermal zone for this sensor is present
> inside the tmp102 DT node. Otherwise, the driver behavior
> will be the same.

Similarly to the lm75, this requires a binding document update, but I
don't think the binding extension's necessary anyway.

Thanks,
Mark.

> 
> Cc: Jean Delvare <khali@linux-fr.org>
> Cc: Guenter Roeck <linux@roeck-us.net>
> Cc: lm-sensors@lm-sensors.org
> Cc: linux-kernel@vger.kernel.org
> Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
> ---
>  drivers/hwmon/tmp102.c | 26 ++++++++++++++++++++++++++
>  1 file changed, 26 insertions(+)
> 
> diff --git a/drivers/hwmon/tmp102.c b/drivers/hwmon/tmp102.c
> index d7b47ab..0f1e44a 100644
> --- a/drivers/hwmon/tmp102.c
> +++ b/drivers/hwmon/tmp102.c
> @@ -27,6 +27,8 @@
>  #include <linux/mutex.h>
>  #include <linux/device.h>
>  #include <linux/jiffies.h>
> +#include <linux/thermal.h>
> +#include <linux/of.h>
>  
>  #define	DRIVER_NAME "tmp102"
>  
> @@ -50,6 +52,7 @@
>  
>  struct tmp102 {
>  	struct device *hwmon_dev;
> +	struct thermal_zone_device *tz;
>  	struct mutex lock;
>  	u16 config_orig;
>  	unsigned long last_update;
> @@ -93,6 +96,15 @@ static struct tmp102 *tmp102_update_device(struct i2c_client *client)
>  	return tmp102;
>  }
>  
> +static int tmp102_read_temp(void *dev, unsigned long *temp)
> +{
> +	struct tmp102 *tmp102 = tmp102_update_device(to_i2c_client(dev));
> +
> +	*temp = tmp102->temp[0];
> +
> +	return 0;
> +}
> +
>  static ssize_t tmp102_show_temp(struct device *dev,
>  				struct device_attribute *attr,
>  				char *buf)
> @@ -204,10 +216,23 @@ static int tmp102_probe(struct i2c_client *client,
>  		goto fail_remove_sysfs;
>  	}
>  
> +	if (of_find_property(client->dev.of_node, "monitored-zones", NULL)) {
> +		tmp102->tz = thermal_zone_of_device_register(&client->dev, 0,
> +							     false, /* -hwmon */
> +							     &client->dev,
> +							     tmp102_read_temp);
> +		if (IS_ERR(tmp102->tz)) {
> +			status = PTR_ERR(tmp102->tz);
> +			goto exit_hwmon;
> +		}
> +	}
> +
>  	dev_info(&client->dev, "initialized\n");
>  
>  	return 0;
>  
> +exit_hwmon:
> +	hwmon_device_unregister(tmp102->hwmon_dev);
>  fail_remove_sysfs:
>  	sysfs_remove_group(&client->dev.kobj, &tmp102_attr_group);
>  fail_restore_config:
> @@ -220,6 +245,7 @@ static int tmp102_remove(struct i2c_client *client)
>  {
>  	struct tmp102 *tmp102 = i2c_get_clientdata(client);
>  
> +	thermal_zone_device_unregister(tmp102->tz);
>  	hwmon_device_unregister(tmp102->hwmon_dev);
>  	sysfs_remove_group(&client->dev.kobj, &tmp102_attr_group);
>  
> -- 
> 1.8.2.1.342.gfa7285d
> 
> 

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

* Re: [lm-sensors] [RFC PATCH 04/14] hwmon: tmp102: expose to thermal fw via DT nodes
@ 2013-08-27 10:27     ` Mark Rutland
  0 siblings, 0 replies; 100+ messages in thread
From: Mark Rutland @ 2013-08-27 10:27 UTC (permalink / raw)
  To: Eduardo Valentin
  Cc: swarren, Pawel Moll, ian.campbell, grant.likely, rob.herring,
	linux, rui.zhang, wni, durgadoss.r, linux-pm, devicetree,
	lm-sensors, linux-kernel, Jean Delvare

On Sat, Aug 24, 2013 at 12:15:45AM +0100, Eduardo Valentin wrote:
> This patch adds to tmp102 temperature sensor the possibility
> to expose itself as thermal zone device, registered on the
> thermal framework.
> 
> The thermal zone is built only if a device tree node
> describing a thermal zone for this sensor is present
> inside the tmp102 DT node. Otherwise, the driver behavior
> will be the same.

Similarly to the lm75, this requires a binding document update, but I
don't think the binding extension's necessary anyway.

Thanks,
Mark.

> 
> Cc: Jean Delvare <khali@linux-fr.org>
> Cc: Guenter Roeck <linux@roeck-us.net>
> Cc: lm-sensors@lm-sensors.org
> Cc: linux-kernel@vger.kernel.org
> Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
> ---
>  drivers/hwmon/tmp102.c | 26 ++++++++++++++++++++++++++
>  1 file changed, 26 insertions(+)
> 
> diff --git a/drivers/hwmon/tmp102.c b/drivers/hwmon/tmp102.c
> index d7b47ab..0f1e44a 100644
> --- a/drivers/hwmon/tmp102.c
> +++ b/drivers/hwmon/tmp102.c
> @@ -27,6 +27,8 @@
>  #include <linux/mutex.h>
>  #include <linux/device.h>
>  #include <linux/jiffies.h>
> +#include <linux/thermal.h>
> +#include <linux/of.h>
>  
>  #define	DRIVER_NAME "tmp102"
>  
> @@ -50,6 +52,7 @@
>  
>  struct tmp102 {
>  	struct device *hwmon_dev;
> +	struct thermal_zone_device *tz;
>  	struct mutex lock;
>  	u16 config_orig;
>  	unsigned long last_update;
> @@ -93,6 +96,15 @@ static struct tmp102 *tmp102_update_device(struct i2c_client *client)
>  	return tmp102;
>  }
>  
> +static int tmp102_read_temp(void *dev, unsigned long *temp)
> +{
> +	struct tmp102 *tmp102 = tmp102_update_device(to_i2c_client(dev));
> +
> +	*temp = tmp102->temp[0];
> +
> +	return 0;
> +}
> +
>  static ssize_t tmp102_show_temp(struct device *dev,
>  				struct device_attribute *attr,
>  				char *buf)
> @@ -204,10 +216,23 @@ static int tmp102_probe(struct i2c_client *client,
>  		goto fail_remove_sysfs;
>  	}
>  
> +	if (of_find_property(client->dev.of_node, "monitored-zones", NULL)) {
> +		tmp102->tz = thermal_zone_of_device_register(&client->dev, 0,
> +							     false, /* -hwmon */
> +							     &client->dev,
> +							     tmp102_read_temp);
> +		if (IS_ERR(tmp102->tz)) {
> +			status = PTR_ERR(tmp102->tz);
> +			goto exit_hwmon;
> +		}
> +	}
> +
>  	dev_info(&client->dev, "initialized\n");
>  
>  	return 0;
>  
> +exit_hwmon:
> +	hwmon_device_unregister(tmp102->hwmon_dev);
>  fail_remove_sysfs:
>  	sysfs_remove_group(&client->dev.kobj, &tmp102_attr_group);
>  fail_restore_config:
> @@ -220,6 +245,7 @@ static int tmp102_remove(struct i2c_client *client)
>  {
>  	struct tmp102 *tmp102 = i2c_get_clientdata(client);
>  
> +	thermal_zone_device_unregister(tmp102->tz);
>  	hwmon_device_unregister(tmp102->hwmon_dev);
>  	sysfs_remove_group(&client->dev.kobj, &tmp102_attr_group);
>  
> -- 
> 1.8.2.1.342.gfa7285d
> 
> 

_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

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

* Re: [RFC PATCH 01/14] cpufreq: cpufreq-cpu0: add dt node parsing for 'cooling-zones'
  2013-08-27  9:29     ` Mark Rutland
  (?)
  (?)
@ 2013-08-27 13:05       ` Eduardo Valentin
  -1 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-27 13:05 UTC (permalink / raw)
  To: Mark Rutland
  Cc: Eduardo Valentin, swarren, Pawel Moll, ian.campbell,
	grant.likely, rob.herring, linux, rui.zhang, wni, durgadoss.r,
	linux-pm, devicetree, lm-sensors, linux-kernel,
	Rafael J. Wysocki, Viresh Kumar, cpufreq, devicetree-discuss

[-- Attachment #1: Type: text/plain, Size: 4619 bytes --]

Hey Mark,

On 27-08-2013 05:29, Mark Rutland wrote:
> On Sat, Aug 24, 2013 at 12:15:42AM +0100, Eduardo Valentin wrote:
>> This patch changes the cpufreq-cpu0 driver to consider if
>> a cpu needs cooling (with cpufreq). In case the cooling is needed,
>> it can be flagged at the cpu0 device tree node, with the list
>> of zones property 'cooling-zones'.
>>
>> In case this list of zones is present, the driver will
>> load a cpufreq cooling device in the system. The cpufreq-cpu0
>> driver is not interested in determining how the system should
>> be using the cooling device. The driver is responsible
>> only of loading the cooling device.
>>
>> Describing how the cooling device will be used can be
>> accomplished by setting up a thermal zone that references
>> and is composed by the cpufreq cooling device.
>>
>> Cc: "Rafael J. Wysocki" <rjw@sisk.pl>
>> Cc: Viresh Kumar <viresh.kumar@linaro.org>
>> Cc: Grant Likely <grant.likely@linaro.org>
>> Cc: Rob Herring <rob.herring@calxeda.com>
>> Cc: cpufreq@vger.kernel.org
>> Cc: linux-pm@vger.kernel.org
>> Cc: linux-kernel@vger.kernel.org
>> Cc: devicetree-discuss@lists.ozlabs.org
>> Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
>> ---
>>  Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt |  4 ++++
>>  drivers/cpufreq/cpufreq-cpu0.c                             | 12 ++++++++++++
>>  2 files changed, 16 insertions(+)
>>
>> diff --git a/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt b/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt
>> index 051f764..add50f7 100644
>> --- a/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt
>> +++ b/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt
>> @@ -15,6 +15,9 @@ Optional properties:
>>  - clock-latency: Specify the possible maximum transition latency for clock,
>>    in unit of nanoseconds.
>>  - voltage-tolerance: Specify the CPU voltage tolerance in percentage.
>> +- cooling-zones: A list of thermal zones phandles. The generic cpu
>> +  cooling (freq clipping) is loaded by the generic cpufreq-cpu0 driver
>> +  in case the device tree node has this list.
> 
> Bindings should not describe the behaviour of any kernel (and for that
> reason I'm not very keen on the current cpufreq-cpu0 binding document).
> 

Right.

> Bindings should simply describe the hardware. This addition could
> instead be:
> 
>  - cooling-zones: a list of thermal zone phandles.
> 

OK. This works for me.

> However, as the thermal zone binding doesn't seem to have appeared by
> this patch, it should get moved later anyway...

Yeah, I will reorder them.

> 
> Thanks,
> Mark.
> 
>>  
>>  Examples:
>>  
>> @@ -33,6 +36,7 @@ cpus {
>>  			198000  850000
>>  		>;
>>  		clock-latency = <61036>; /* two CLK32 periods */
>> +		cooling-zones = <&cpu_thermal>;
>>  	};
>>  
>>  	cpu@1 {
>> diff --git a/drivers/cpufreq/cpufreq-cpu0.c b/drivers/cpufreq/cpufreq-cpu0.c
>> index ad1fde2..ede6487 100644
>> --- a/drivers/cpufreq/cpufreq-cpu0.c
>> +++ b/drivers/cpufreq/cpufreq-cpu0.c
>> @@ -20,6 +20,9 @@
>>  #include <linux/platform_device.h>
>>  #include <linux/regulator/consumer.h>
>>  #include <linux/slab.h>
>> +#include <linux/thermal.h>
>> +#include <linux/cpu_cooling.h>
>> +#include <linux/cpumask.h>
>>  
>>  static unsigned int transition_latency;
>>  static unsigned int voltage_tolerance; /* in percentage */
>> @@ -28,6 +31,7 @@ static struct device *cpu_dev;
>>  static struct clk *cpu_clk;
>>  static struct regulator *cpu_reg;
>>  static struct cpufreq_frequency_table *freq_table;
>> +static struct thermal_cooling_device *cdev;
>>  
>>  static int cpu0_verify_speed(struct cpufreq_policy *policy)
>>  {
>> @@ -268,6 +272,13 @@ static int cpu0_cpufreq_probe(struct platform_device *pdev)
>>  		goto out_free_table;
>>  	}
>>  
>> +	/*
>> +	 * For now, just loading the cooling device;
>> +	 * thermal DT code takes care of matching them.
>> +	 */
>> +	if (of_find_property(np, "cooling-zones", NULL))
>> +		cdev = cpufreq_cooling_register(cpu_present_mask);
>> +
>>  	of_node_put(np);
>>  	of_node_put(parent);
>>  	return 0;
>> @@ -283,6 +294,7 @@ out_put_parent:
>>  
>>  static int cpu0_cpufreq_remove(struct platform_device *pdev)
>>  {
>> +	cpufreq_cooling_unregister(cdev);
>>  	cpufreq_unregister_driver(&cpu0_cpufreq_driver);
>>  	opp_free_cpufreq_table(cpu_dev, &freq_table);
>>  
>> -- 
>> 1.8.2.1.342.gfa7285d
>>
>>
> 
> 


-- 
You have got to be excited about what you are doing. (L. Lamport)

Eduardo Valentin


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 295 bytes --]

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

* Re: [RFC PATCH 01/14] cpufreq: cpufreq-cpu0: add dt node parsing for 'cooling-zones'
@ 2013-08-27 13:05       ` Eduardo Valentin
  0 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-27 13:05 UTC (permalink / raw)
  To: Mark Rutland
  Cc: Eduardo Valentin, swarren, Pawel Moll, ian.campbell,
	grant.likely, rob.herring, linux, rui.zhang, wni, durgadoss.r,
	linux-pm, devicetree, lm-sensors, linux-kernel,
	Rafael J. Wysocki, Viresh Kumar, cpufreq,
	devicetree-discuss@lists.ozlabs.org

[-- Attachment #1: Type: text/plain, Size: 4619 bytes --]

Hey Mark,

On 27-08-2013 05:29, Mark Rutland wrote:
> On Sat, Aug 24, 2013 at 12:15:42AM +0100, Eduardo Valentin wrote:
>> This patch changes the cpufreq-cpu0 driver to consider if
>> a cpu needs cooling (with cpufreq). In case the cooling is needed,
>> it can be flagged at the cpu0 device tree node, with the list
>> of zones property 'cooling-zones'.
>>
>> In case this list of zones is present, the driver will
>> load a cpufreq cooling device in the system. The cpufreq-cpu0
>> driver is not interested in determining how the system should
>> be using the cooling device. The driver is responsible
>> only of loading the cooling device.
>>
>> Describing how the cooling device will be used can be
>> accomplished by setting up a thermal zone that references
>> and is composed by the cpufreq cooling device.
>>
>> Cc: "Rafael J. Wysocki" <rjw@sisk.pl>
>> Cc: Viresh Kumar <viresh.kumar@linaro.org>
>> Cc: Grant Likely <grant.likely@linaro.org>
>> Cc: Rob Herring <rob.herring@calxeda.com>
>> Cc: cpufreq@vger.kernel.org
>> Cc: linux-pm@vger.kernel.org
>> Cc: linux-kernel@vger.kernel.org
>> Cc: devicetree-discuss@lists.ozlabs.org
>> Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
>> ---
>>  Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt |  4 ++++
>>  drivers/cpufreq/cpufreq-cpu0.c                             | 12 ++++++++++++
>>  2 files changed, 16 insertions(+)
>>
>> diff --git a/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt b/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt
>> index 051f764..add50f7 100644
>> --- a/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt
>> +++ b/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt
>> @@ -15,6 +15,9 @@ Optional properties:
>>  - clock-latency: Specify the possible maximum transition latency for clock,
>>    in unit of nanoseconds.
>>  - voltage-tolerance: Specify the CPU voltage tolerance in percentage.
>> +- cooling-zones: A list of thermal zones phandles. The generic cpu
>> +  cooling (freq clipping) is loaded by the generic cpufreq-cpu0 driver
>> +  in case the device tree node has this list.
> 
> Bindings should not describe the behaviour of any kernel (and for that
> reason I'm not very keen on the current cpufreq-cpu0 binding document).
> 

Right.

> Bindings should simply describe the hardware. This addition could
> instead be:
> 
>  - cooling-zones: a list of thermal zone phandles.
> 

OK. This works for me.

> However, as the thermal zone binding doesn't seem to have appeared by
> this patch, it should get moved later anyway...

Yeah, I will reorder them.

> 
> Thanks,
> Mark.
> 
>>  
>>  Examples:
>>  
>> @@ -33,6 +36,7 @@ cpus {
>>  			198000  850000
>>  		>;
>>  		clock-latency = <61036>; /* two CLK32 periods */
>> +		cooling-zones = <&cpu_thermal>;
>>  	};
>>  
>>  	cpu@1 {
>> diff --git a/drivers/cpufreq/cpufreq-cpu0.c b/drivers/cpufreq/cpufreq-cpu0.c
>> index ad1fde2..ede6487 100644
>> --- a/drivers/cpufreq/cpufreq-cpu0.c
>> +++ b/drivers/cpufreq/cpufreq-cpu0.c
>> @@ -20,6 +20,9 @@
>>  #include <linux/platform_device.h>
>>  #include <linux/regulator/consumer.h>
>>  #include <linux/slab.h>
>> +#include <linux/thermal.h>
>> +#include <linux/cpu_cooling.h>
>> +#include <linux/cpumask.h>
>>  
>>  static unsigned int transition_latency;
>>  static unsigned int voltage_tolerance; /* in percentage */
>> @@ -28,6 +31,7 @@ static struct device *cpu_dev;
>>  static struct clk *cpu_clk;
>>  static struct regulator *cpu_reg;
>>  static struct cpufreq_frequency_table *freq_table;
>> +static struct thermal_cooling_device *cdev;
>>  
>>  static int cpu0_verify_speed(struct cpufreq_policy *policy)
>>  {
>> @@ -268,6 +272,13 @@ static int cpu0_cpufreq_probe(struct platform_device *pdev)
>>  		goto out_free_table;
>>  	}
>>  
>> +	/*
>> +	 * For now, just loading the cooling device;
>> +	 * thermal DT code takes care of matching them.
>> +	 */
>> +	if (of_find_property(np, "cooling-zones", NULL))
>> +		cdev = cpufreq_cooling_register(cpu_present_mask);
>> +
>>  	of_node_put(np);
>>  	of_node_put(parent);
>>  	return 0;
>> @@ -283,6 +294,7 @@ out_put_parent:
>>  
>>  static int cpu0_cpufreq_remove(struct platform_device *pdev)
>>  {
>> +	cpufreq_cooling_unregister(cdev);
>>  	cpufreq_unregister_driver(&cpu0_cpufreq_driver);
>>  	opp_free_cpufreq_table(cpu_dev, &freq_table);
>>  
>> -- 
>> 1.8.2.1.342.gfa7285d
>>
>>
> 
> 


-- 
You have got to be excited about what you are doing. (L. Lamport)

Eduardo Valentin


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 295 bytes --]

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

* Re: [RFC PATCH 01/14] cpufreq: cpufreq-cpu0: add dt node parsing for 'cooling-zones'
@ 2013-08-27 13:05       ` Eduardo Valentin
  0 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-27 13:05 UTC (permalink / raw)
  To: Mark Rutland
  Cc: Eduardo Valentin, swarren, Pawel Moll, ian.campbell,
	grant.likely, rob.herring, linux, rui.zhang, wni, durgadoss.r,
	linux-pm, devicetree, lm-sensors, linux-kernel,
	Rafael J. Wysocki, Viresh Kumar, cpufreq,
	devicetree-discuss@lists.ozlabs.org

[-- Attachment #1: Type: text/plain, Size: 4619 bytes --]

Hey Mark,

On 27-08-2013 05:29, Mark Rutland wrote:
> On Sat, Aug 24, 2013 at 12:15:42AM +0100, Eduardo Valentin wrote:
>> This patch changes the cpufreq-cpu0 driver to consider if
>> a cpu needs cooling (with cpufreq). In case the cooling is needed,
>> it can be flagged at the cpu0 device tree node, with the list
>> of zones property 'cooling-zones'.
>>
>> In case this list of zones is present, the driver will
>> load a cpufreq cooling device in the system. The cpufreq-cpu0
>> driver is not interested in determining how the system should
>> be using the cooling device. The driver is responsible
>> only of loading the cooling device.
>>
>> Describing how the cooling device will be used can be
>> accomplished by setting up a thermal zone that references
>> and is composed by the cpufreq cooling device.
>>
>> Cc: "Rafael J. Wysocki" <rjw@sisk.pl>
>> Cc: Viresh Kumar <viresh.kumar@linaro.org>
>> Cc: Grant Likely <grant.likely@linaro.org>
>> Cc: Rob Herring <rob.herring@calxeda.com>
>> Cc: cpufreq@vger.kernel.org
>> Cc: linux-pm@vger.kernel.org
>> Cc: linux-kernel@vger.kernel.org
>> Cc: devicetree-discuss@lists.ozlabs.org
>> Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
>> ---
>>  Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt |  4 ++++
>>  drivers/cpufreq/cpufreq-cpu0.c                             | 12 ++++++++++++
>>  2 files changed, 16 insertions(+)
>>
>> diff --git a/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt b/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt
>> index 051f764..add50f7 100644
>> --- a/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt
>> +++ b/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt
>> @@ -15,6 +15,9 @@ Optional properties:
>>  - clock-latency: Specify the possible maximum transition latency for clock,
>>    in unit of nanoseconds.
>>  - voltage-tolerance: Specify the CPU voltage tolerance in percentage.
>> +- cooling-zones: A list of thermal zones phandles. The generic cpu
>> +  cooling (freq clipping) is loaded by the generic cpufreq-cpu0 driver
>> +  in case the device tree node has this list.
> 
> Bindings should not describe the behaviour of any kernel (and for that
> reason I'm not very keen on the current cpufreq-cpu0 binding document).
> 

Right.

> Bindings should simply describe the hardware. This addition could
> instead be:
> 
>  - cooling-zones: a list of thermal zone phandles.
> 

OK. This works for me.

> However, as the thermal zone binding doesn't seem to have appeared by
> this patch, it should get moved later anyway...

Yeah, I will reorder them.

> 
> Thanks,
> Mark.
> 
>>  
>>  Examples:
>>  
>> @@ -33,6 +36,7 @@ cpus {
>>  			198000  850000
>>  		>;
>>  		clock-latency = <61036>; /* two CLK32 periods */
>> +		cooling-zones = <&cpu_thermal>;
>>  	};
>>  
>>  	cpu@1 {
>> diff --git a/drivers/cpufreq/cpufreq-cpu0.c b/drivers/cpufreq/cpufreq-cpu0.c
>> index ad1fde2..ede6487 100644
>> --- a/drivers/cpufreq/cpufreq-cpu0.c
>> +++ b/drivers/cpufreq/cpufreq-cpu0.c
>> @@ -20,6 +20,9 @@
>>  #include <linux/platform_device.h>
>>  #include <linux/regulator/consumer.h>
>>  #include <linux/slab.h>
>> +#include <linux/thermal.h>
>> +#include <linux/cpu_cooling.h>
>> +#include <linux/cpumask.h>
>>  
>>  static unsigned int transition_latency;
>>  static unsigned int voltage_tolerance; /* in percentage */
>> @@ -28,6 +31,7 @@ static struct device *cpu_dev;
>>  static struct clk *cpu_clk;
>>  static struct regulator *cpu_reg;
>>  static struct cpufreq_frequency_table *freq_table;
>> +static struct thermal_cooling_device *cdev;
>>  
>>  static int cpu0_verify_speed(struct cpufreq_policy *policy)
>>  {
>> @@ -268,6 +272,13 @@ static int cpu0_cpufreq_probe(struct platform_device *pdev)
>>  		goto out_free_table;
>>  	}
>>  
>> +	/*
>> +	 * For now, just loading the cooling device;
>> +	 * thermal DT code takes care of matching them.
>> +	 */
>> +	if (of_find_property(np, "cooling-zones", NULL))
>> +		cdev = cpufreq_cooling_register(cpu_present_mask);
>> +
>>  	of_node_put(np);
>>  	of_node_put(parent);
>>  	return 0;
>> @@ -283,6 +294,7 @@ out_put_parent:
>>  
>>  static int cpu0_cpufreq_remove(struct platform_device *pdev)
>>  {
>> +	cpufreq_cooling_unregister(cdev);
>>  	cpufreq_unregister_driver(&cpu0_cpufreq_driver);
>>  	opp_free_cpufreq_table(cpu_dev, &freq_table);
>>  
>> -- 
>> 1.8.2.1.342.gfa7285d
>>
>>
> 
> 


-- 
You have got to be excited about what you are doing. (L. Lamport)

Eduardo Valentin


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 295 bytes --]

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

* Re: [lm-sensors] [RFC PATCH 01/14] cpufreq: cpufreq-cpu0: add dt node parsing for 'cooling-zones'
@ 2013-08-27 13:05       ` Eduardo Valentin
  0 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-27 13:05 UTC (permalink / raw)
  To: Mark Rutland
  Cc: Eduardo Valentin, swarren, Pawel Moll, ian.campbell,
	grant.likely, rob.herring, linux, rui.zhang, wni, durgadoss.r,
	linux-pm, devicetree, lm-sensors, linux-kernel,
	Rafael J. Wysocki, Viresh Kumar, cpufreq, devicetree-discuss


[-- Attachment #1.1: Type: text/plain, Size: 4619 bytes --]

Hey Mark,

On 27-08-2013 05:29, Mark Rutland wrote:
> On Sat, Aug 24, 2013 at 12:15:42AM +0100, Eduardo Valentin wrote:
>> This patch changes the cpufreq-cpu0 driver to consider if
>> a cpu needs cooling (with cpufreq). In case the cooling is needed,
>> it can be flagged at the cpu0 device tree node, with the list
>> of zones property 'cooling-zones'.
>>
>> In case this list of zones is present, the driver will
>> load a cpufreq cooling device in the system. The cpufreq-cpu0
>> driver is not interested in determining how the system should
>> be using the cooling device. The driver is responsible
>> only of loading the cooling device.
>>
>> Describing how the cooling device will be used can be
>> accomplished by setting up a thermal zone that references
>> and is composed by the cpufreq cooling device.
>>
>> Cc: "Rafael J. Wysocki" <rjw@sisk.pl>
>> Cc: Viresh Kumar <viresh.kumar@linaro.org>
>> Cc: Grant Likely <grant.likely@linaro.org>
>> Cc: Rob Herring <rob.herring@calxeda.com>
>> Cc: cpufreq@vger.kernel.org
>> Cc: linux-pm@vger.kernel.org
>> Cc: linux-kernel@vger.kernel.org
>> Cc: devicetree-discuss@lists.ozlabs.org
>> Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
>> ---
>>  Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt |  4 ++++
>>  drivers/cpufreq/cpufreq-cpu0.c                             | 12 ++++++++++++
>>  2 files changed, 16 insertions(+)
>>
>> diff --git a/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt b/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt
>> index 051f764..add50f7 100644
>> --- a/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt
>> +++ b/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt
>> @@ -15,6 +15,9 @@ Optional properties:
>>  - clock-latency: Specify the possible maximum transition latency for clock,
>>    in unit of nanoseconds.
>>  - voltage-tolerance: Specify the CPU voltage tolerance in percentage.
>> +- cooling-zones: A list of thermal zones phandles. The generic cpu
>> +  cooling (freq clipping) is loaded by the generic cpufreq-cpu0 driver
>> +  in case the device tree node has this list.
> 
> Bindings should not describe the behaviour of any kernel (and for that
> reason I'm not very keen on the current cpufreq-cpu0 binding document).
> 

Right.

> Bindings should simply describe the hardware. This addition could
> instead be:
> 
>  - cooling-zones: a list of thermal zone phandles.
> 

OK. This works for me.

> However, as the thermal zone binding doesn't seem to have appeared by
> this patch, it should get moved later anyway...

Yeah, I will reorder them.

> 
> Thanks,
> Mark.
> 
>>  
>>  Examples:
>>  
>> @@ -33,6 +36,7 @@ cpus {
>>  			198000  850000
>>  		>;
>>  		clock-latency = <61036>; /* two CLK32 periods */
>> +		cooling-zones = <&cpu_thermal>;
>>  	};
>>  
>>  	cpu@1 {
>> diff --git a/drivers/cpufreq/cpufreq-cpu0.c b/drivers/cpufreq/cpufreq-cpu0.c
>> index ad1fde2..ede6487 100644
>> --- a/drivers/cpufreq/cpufreq-cpu0.c
>> +++ b/drivers/cpufreq/cpufreq-cpu0.c
>> @@ -20,6 +20,9 @@
>>  #include <linux/platform_device.h>
>>  #include <linux/regulator/consumer.h>
>>  #include <linux/slab.h>
>> +#include <linux/thermal.h>
>> +#include <linux/cpu_cooling.h>
>> +#include <linux/cpumask.h>
>>  
>>  static unsigned int transition_latency;
>>  static unsigned int voltage_tolerance; /* in percentage */
>> @@ -28,6 +31,7 @@ static struct device *cpu_dev;
>>  static struct clk *cpu_clk;
>>  static struct regulator *cpu_reg;
>>  static struct cpufreq_frequency_table *freq_table;
>> +static struct thermal_cooling_device *cdev;
>>  
>>  static int cpu0_verify_speed(struct cpufreq_policy *policy)
>>  {
>> @@ -268,6 +272,13 @@ static int cpu0_cpufreq_probe(struct platform_device *pdev)
>>  		goto out_free_table;
>>  	}
>>  
>> +	/*
>> +	 * For now, just loading the cooling device;
>> +	 * thermal DT code takes care of matching them.
>> +	 */
>> +	if (of_find_property(np, "cooling-zones", NULL))
>> +		cdev = cpufreq_cooling_register(cpu_present_mask);
>> +
>>  	of_node_put(np);
>>  	of_node_put(parent);
>>  	return 0;
>> @@ -283,6 +294,7 @@ out_put_parent:
>>  
>>  static int cpu0_cpufreq_remove(struct platform_device *pdev)
>>  {
>> +	cpufreq_cooling_unregister(cdev);
>>  	cpufreq_unregister_driver(&cpu0_cpufreq_driver);
>>  	opp_free_cpufreq_table(cpu_dev, &freq_table);
>>  
>> -- 
>> 1.8.2.1.342.gfa7285d
>>
>>
> 
> 


-- 
You have got to be excited about what you are doing. (L. Lamport)

Eduardo Valentin


[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 295 bytes --]

[-- Attachment #2: Type: text/plain, Size: 153 bytes --]

_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

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

* Re: [RFC PATCH 02/14] drivers: thermal: introduce device tree parser
  2013-08-27 10:22     ` [lm-sensors] " Mark Rutland
@ 2013-08-27 13:44       ` Eduardo Valentin
  -1 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-27 13:44 UTC (permalink / raw)
  To: Mark Rutland
  Cc: Eduardo Valentin, swarren, Pawel Moll, ian.campbell,
	grant.likely, rob.herring, linux, rui.zhang, wni, durgadoss.r,
	linux-pm, devicetree, lm-sensors, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 31475 bytes --]

Hello Mark,


First of all, thanks for taking the time to review in such level of
detail. Lets try to align and have a common understanding. Answers go
inline. Please let me know if I missed something or if I made it more
confusing :-)

On 27-08-2013 06:22, Mark Rutland wrote:
> Hi,
> 
> On Sat, Aug 24, 2013 at 12:15:43AM +0100, Eduardo Valentin wrote:
>> In order to be able to build thermal policies
>> based on generic sensors, like I2C device, that
>> can be places in different points on different boards,
>> there is a need to have a way to feed board dependent
>> data into the thermal framework.
>>
>> This patch introduces a thermal data parser for device
>> tree. The parsed data is used to build thermal zones
>> and thermal binding parameters. The output data
>> can then be used to deploy thermal policies.
>>
>> This patch adds also documentation regarding this
>> API and how to define tree nodes to use
>> this infrastructure.
>>
>> Cc: Zhang Rui <rui.zhang@intel.com>
>> Cc: linux-pm@vger.kernel.org
>> Cc: linux-kernel@vger.kernel.org
>> Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
>> ---
>>  .../devicetree/bindings/thermal/thermal.txt        | 160 +++++++
>>  drivers/thermal/Kconfig                            |  13 +
>>  drivers/thermal/Makefile                           |   1 +
>>  drivers/thermal/thermal_dt.c                       | 473 +++++++++++++++++++++
>>  include/dt-bindings/thermal/thermal.h              |  27 ++
>>  include/linux/thermal.h                            |   3 +
>>  6 files changed, 677 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/thermal/thermal.txt
>>  create mode 100644 drivers/thermal/thermal_dt.c
>>  create mode 100644 include/dt-bindings/thermal/thermal.h
>>


General question on device tree documentation. Assuming there is such an
effort to make it Linux independent, is there other places out of Linux
tree that these binding must be documented?


>> diff --git a/Documentation/devicetree/bindings/thermal/thermal.txt b/Documentation/devicetree/bindings/thermal/thermal.txt
>> new file mode 100644
>> index 0000000..af20ab0
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/thermal/thermal.txt
>> @@ -0,0 +1,160 @@
>> +----------------------------------------
>> +Thermal Framework Device Tree descriptor
>> +----------------------------------------
>> +
>> +This file describes how to define a thermal structure using device tree.
>> +A thermal structure includes thermal zones and their components, such
>> +as name, trip points, polling intervals and cooling devices binding
>> +descriptors. A binding descriptor may contain information on how to
>> +react, with a cooling stepped action or a weight on a fair share.
>> +The target of device tree thermal descriptors is to describe only
>> +the hardware thermal aspects, not how the system must control or which
>> +algorithm or policy must take place. It follows a description of each
>> +type of device tree node.
>> +
>> +****
>> +trip
>> +****
>> +
>> +The trip node is a node to describe a point in the temperature domain
>> +in which the system takes an action. This node describes just the point,
>> +not the action.
>> +
>> +A node describing a trip must contain:
>> +- temperature: the trip temperature level, in milliCelsius.
>> +- hysteresis: a (low) hysteresis value on 'temperature'. This is a relative
>> +value, in milliCelsius.
> 
> Presumably this is a single (u32) cell?

Yes, both of them above are a single u32.

> 
>> +- type: the trip type. Here is the type mapping:
>> +       THERMAL_TRIP_ACTIVE
>> +       THERMAL_TRIP_PASSIVE
>> +       THERMAL_TRIP_HOT
>> +       THERMAL_TRIP_CRITICAL
> 
> What type is this property?
> 
> What are these values? Do you need to refer to a header somewhere?

There is a header, introduced in this patch.
include/dt-bindings/thermal/thermal.h

> Symbolic constants should have an associated value for an ABI.

OK. Sounds reasonable to me. Shall we be descriptive and enlist the
values in this doc too or just pointing to header is fine?

> 
>> +
>> +**********
>> +bind_param
>> +**********
>> +
>> +The bind_param node is a node to describe how cooling devices get assigned
>> +to trip points of the zone. The cooling devices are expected to be loaded
>> +in the target system.
>> +
>> +A node describing a bind_param must contain:
>> +- cooling_device: A string with the cooling device name.
> 
> Please use '-' rather than '_' in bindings. That's the normal devicetree
> convention, and there's no point gonig against it and causing more
> confusion.

Agreed.

> 
> What are valid values of this string, and what do they mean?

These are the name of the cooling devices to match to.

> 
> Why not a phandle + cells binding to cooling devices?
> 

Yeah, this could work too. I am going to check how that would look like
and come back to you.

>> +- weight: The 'influence' of a particular cooling device on this zone.
>> +             This is on a percentage scale. The sum of all these weights
>> +             (for a particular zone) cannot exceed 100.
> 
> This is a bit fuzzy, and certainly needs more guidance.

OK. This property is used to describe the amount of cooling contribution
when activating a cooling device at a certain trip point. I will work on
a better guidance.

> 
>> +- trip_mask: This is a bit mask that gives the binding relation between
>> +               this thermal zone and cdev, for a particular trip point.
>> +               If nth bit is set, then the cdev and thermal zone are bound
>> +               for trip point n.
> 
> What type is this?
> 
> The nth bit from which end?
> 
> Could you explain what "bound for trip point n" means?
> 

It is just a way to match a cooling device with a set of trip points.
Say you want to match one specific cooling device with trips 0 and 1,
you would then create a bind_param with trip_mask = 0x3.

> Just because this is a bitmask in Linux does not mean it needs to be so
> in the dt.

Indeed.

In case we work with phandle + cell binging parameters, the trip and
weight could be passed as params.

	cooling-devices = <&devX tripY weightZ>, <... >;



> 
>> +- limits: An array integers consisting of 2-tuples items, and each item means
>> +  lower and upper state limits, like <min-state max-state>.
>> +
>> +**************************
>> +temperature sensor devices
>> +**************************
>> +
>> +Temperature sensor devices have to be linked to a specific thermal zone.
>> +This is done by means of the 'monitored-zones' list.
>> +- monitored-zones: A list of thermal zones phandles, identifying which
>> +thermal zones the temperature sensor device is used to monitor.
> 
> Why does this need to be described that way around?
> 
> Can the zone not have a link to the sensor(s) it needs?
> 

Do you see any issues with it?

Idea is that sensor nodes would list which zones they are used.  Same
idea goes to cooling devices. It can be the other way around, yes. It
depends on what is the best way to describe these relations. Idea would
be so that sensors and cooling devices would be composing a thermal zone.

>> +
>> +************
>> +thermal_zone
>> +************
>> +
>> +The thermal_zone node is the node containing all the required info
>> +for describing a thermal zone, including its cdev bindings. The thermal_zone
>> +node must contain, apart from its own properties, one node containing
>> +trip nodes and one node containing all the zone bind parameters.
>> +
>> +Required properties:
>> +- mask: Bit string: If 'n'th bit is set, then trip point 'n' is writeable.
> 
> What type is a bit string in devicetree? I'm aware of cells and (byte)
> strings, but not bit strings.
> 
> What does 'writeable' mean in this context?
> 
> There's presumably a better name than 'mask'.
> 

This is used to describe if trip points are writeable under sysfs. I
think this is a OS implementation leak. I will be removing this from
device tree and making them RO by default.

>> +
>> +- passive_delay: number of milliseconds to wait between polls when
>> +  performing passive cooling.
>> +
>> +- polling_delay: number of milliseconds to wait between polls when checking.
> 
> These sound very much like configuration of the driver rather than
> hardware description. What if my temperature sensor can generate an
> interrupt at some trigger temperature? Why would I need polling times?
> 
> Why does this need to be in the dt at all? Surely the OS can choose some
> sensible polling period, possibly dynamically?

Well, let me answer this one with another question. How the OS will
determine how fast is the temperature rise on a thermal zone described
in device tree?

> 
>> +
>> +- #thermal-cells: An integer that is used to specify how many cells compose
>> +  sensor ids.
> 
> I don't see why this is necessary. If the zone itself described its
> related sensors rather than the other way around, we wouldn't need it at
> all. Most bindings so far have consumers link to their providers rather
> than the other way around.
> 

I see.


>> +
>> +Below is an example:
>> +cpu_thermal: thermal_zone {
>> +            #thermal-cells = <1>;
>> +            mask = <0x03>; /* trips writability */
>> +            passive_delay = <250>; /* milliseconds */
>> +            polling_delay = <1000>; /* milliseconds */
>> +            trips {
>> +                    alert@100000{
>> +                            temperature = <100000>; /* milliCelsius */
>> +                            hysteresis = <0>; /* milliCelsius */
>> +                            type = <THERMAL_TRIP_PASSIVE>;
>> +                    };
>> +                    crit@125000{
>> +                            temperature = <125000>; /* milliCelsius */
>> +                            hysteresis = <0>; /* milliCelsius */
>> +                            type = <THERMAL_TRIP_CRITICAL>;
>> +                    };
>> +            };
>> +            bind_params {
>> +                    action@0{
>> +                            cooling_device = "thermal-cpufreq";
> 
> NAK. That value was not defined anywhere, and represents Linux
> infrastructure rather than hardware.
> 

Yes, this was another leak as discussed above in the upper part of the
doc file.

> For this case, we could just as easily describe the thermal points, and
> if no physical cooling device (e.g. a fan) is present, assume
> cpufreq-base cooling.  Other OSs could choose to do otherwise, and we
> could change later...
> 

The way other specifications do (aka ACPI) is to have trip types. In
case a trip type is passive cooling, it means one is supposed to
modulate the dissipated power rather than activating a device to remove
heat (active cooling).

The part of 'assuming' things that bothers me. I would rather have a way
to really say one wants to have passive cooling at a specific trip point.


>> +                            weight = <100>; /* percentage */
>> +                            mask = <0x01>;
> 
> This should presumably be trip-mask (assuming my suggested corrections).
> 
> What is it supposed to mean here?

As stated above, it means the trip points that this binding represents.

> 
>> +                           limits = <
>> +                             /* lower-state            upper-state */
>> +                               1                       THERMAL_NO_LIMITS
>> +                               THERMAL_NO_LIMITS       THERMAL_NO_LIMITS
>> +                           >;
>> +                    };
>> +            };
>> +};
>> +
>> +sensor: adc@0xFFFF {
>> +       ...
>> +       monitored-zones = <&cpu_thermal 0>;
>> +};
>> +
>> +cpu@0 {
>> +       ...
>> +       cooling-zones = <&cpu_thermal>;
>> +};
>> +
>> +In the example above, the ADC sensor at address 0xFFFF is used to monitor
>> +the zone 'cpu_thermal' using its the sensor 0. The cpu@0 device is also linked
>> +to the same thermal zone 'cpu_thermal' as a cooling device.
> 
> Huh? That seems to imply the the '0' in '<&cpu_thermal 0>' on the sensor
> node describes a property of the sensor rather than the thermal node,
> unless I've misunderstood?
> 

It is essentially which sensor id is used to monitor a specific zone. In
case of sensor IPs that feature several internal sensors, one needs to
have a way to describe which sensor monitors which zone. Example of this
type of IPs: lm90 (up to 3 sensors) and TI bandgap IP (can contain up to
5 internal sensors). The probe happens for the IP device and not for the
internal sensors.


>> +
>> +***************
>> +cpufreq-cooling
>> +***************
>> +
>> +The generic cpu cooling (freq clipping) can be loaded by the
>> +generic cpufreq-cpu0 driver in case the device tree node informs
>> +this need.
>> +
>> +In order to load the cpufreq cooling device, it is possible to
>> +inform that the cpu needs cooling by adding the list of thermal zones
>> +in the 'cooling-zones' property at the cpu0 phandle.
> 
> This should be reworded so as to describe the binding rather than the
> Linux behaviour based on the binding.

OK.

> 
>> +
>> +Example:
>> +       cpus {
>> +               cpu@0 {
>> +                       operating-points = <
>> +                               /* kHz    uV */
>> +                               800000  1313000
>> +                               1008000 1375000
>> +                       >;
>> +                       cooling-zones = <&cpu_thermal>;
>> +               };
>> +       ...
>> +       };
>> +
>> +The above will cause the cpufreq-cpu0 driver to understand that
>> +the cpu will need passive cooling and while probing that node it will
>> +also load the cpufreq cpu cooling device in that system.
> 
> The above describe that the CPU is part of a cooling (thermal?) zone and
> requires cooling.

That says the cpu participates in a thermal zone as a cooling
device/mechanism, thus cpu cooling (passive cooling) is required in
target system.

> 
>> +
>> +However, be advised that this flag will not describe what needs to
>> +be done or how the cpufreq cooling device will be used. In order to
>> +accomplish this, one needs to write a phandle for a thermal zone, as
>> +described in the section 'thermal_zone'.
> 
> The above already has a phandle to a thermal (cooling?) zone.
> 
> Please choose either cooling zone or thermal zone, having the two names
> makes this more confusing than necessary.

I see. Idea is to have thermal zone as a node. cooling-zone is just a
list of thermal zones that the referred device will be used as cooling
device.

> 
>> diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
>> index 7fb16bc..753f0dc 100644
>> --- a/drivers/thermal/Kconfig
>> +++ b/drivers/thermal/Kconfig
>> @@ -29,6 +29,19 @@ config THERMAL_HWMON
>>           Say 'Y' here if you want all thermal sensors to
>>           have hwmon sysfs interface too.
>>
>> +config THERMAL_OF
>> +       bool
>> +       prompt "APIs to parse thermal data out of device tree"
>> +       depends on OF
>> +       default y
>> +       help
>> +         This options provides helpers to add the support to
>> +         read and parse thermal data definitions out of the
>> +         device tree blob.
>> +
>> +         Say 'Y' here if you need to build thermal infrastructure
>> +         based on device tree.
>> +
>>  choice
>>         prompt "Default Thermal governor"
>>         default THERMAL_DEFAULT_GOV_STEP_WISE
>> diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
>> index 24cb894..eedb273 100644
>> --- a/drivers/thermal/Makefile
>> +++ b/drivers/thermal/Makefile
>> @@ -7,6 +7,7 @@ thermal_sys-y                   += thermal_core.o
>>
>>  # interface to/from other layers providing sensors
>>  thermal_sys-$(CONFIG_THERMAL_HWMON)            += thermal_hwmon.o
>> +thermal_sys-$(CONFIG_THERMAL_OF)               += thermal_dt.o
>>
>>  # governors
>>  thermal_sys-$(CONFIG_THERMAL_GOV_FAIR_SHARE)   += fair_share.o
>> diff --git a/drivers/thermal/thermal_dt.c b/drivers/thermal/thermal_dt.c
>> new file mode 100644
>> index 0000000..cc35485
>> --- /dev/null
>> +++ b/drivers/thermal/thermal_dt.c
>> @@ -0,0 +1,473 @@
>> +/*
>> + *  thermal_dt.c - Generic Thermal Management device tree support.
>> + *
>> + *  Copyright (C) 2013 Texas Instruments
>> + *  Copyright (C) 2013 Eduardo Valentin <eduardo.valentin@ti.com>
>> + *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>> + *
>> + *  This program is free software; you can redistribute it and/or modify
>> + *  it under the terms of the GNU General Public License as published by
>> + *  the Free Software Foundation; version 2 of the License.
>> + *
>> + *  This program is distributed in the hope that it will be useful, but
>> + *  WITHOUT ANY WARRANTY; without even the implied warranty of
>> + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> + *  General Public License for more details.
>> + *
>> + *  You should have received a copy of the GNU General Public License along
>> + *  with this program; if not, write to the Free Software Foundation, Inc.,
>> + *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
>> + *
>> + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>> + */
>> +#include <linux/thermal.h>
>> +#include <linux/slab.h>
>> +#include <linux/types.h>
>> +#include <linux/of_device.h>
>> +#include <linux/of_platform.h>
>> +#include <linux/err.h>
>> +#include <linux/export.h>
>> +#include <linux/string.h>
>> +
>> +struct __thermal_bind_params {
>> +       char cooling_device[THERMAL_NAME_LENGTH];
>> +};
>> +
>> +static
>> +int thermal_of_match(struct thermal_zone_device *tz,
>> +                    struct thermal_cooling_device *cdev);
>> +
>> +static int thermal_of_populate_bind_params(struct device *dev,
>> +                                          struct device_node *node,
>> +                                          struct __thermal_bind_params *__tbp,
>> +                                          struct thermal_bind_params *tbp,
>> +                                          int ntrips)
>> +{
>> +       const char *cdev_name;
>> +       u32 *limits;
>> +       int ret;
>> +       u32 prop;
>> +
>> +       ret = of_property_read_u32(node, "weight", &prop);
>> +       if (ret < 0) {
>> +               dev_err(dev, "missing weight property\n");
>> +               return ret;
>> +       }
>> +       tbp->weight = prop;
>> +
>> +       ret = of_property_read_u32(node, "mask", &prop);
>> +       if (ret < 0) {
>> +               dev_err(dev, "missing mask property\n");
>> +               return ret;
>> +       }
>> +       tbp->trip_mask = prop;
>> +
>> +       /* this will allow us to bind with cooling devices */
>> +       tbp->match = thermal_of_match;
>> +
>> +       ret = of_property_read_string(node, "cooling_device", &cdev_name);
>> +       if (ret < 0) {
>> +               dev_err(dev, "missing cooling_device property\n");
>> +               return ret;
>> +       }
>> +       strncpy(__tbp->cooling_device, cdev_name,
>> +               sizeof(__tbp->cooling_device));
>> +
>> +       limits = kzalloc(ntrips * sizeof(*limits) * 2, GFP_KERNEL);
> 
> Why do you use kzalloc here, but devm_kzalloc elsewhere? That'll lead to
> problems as the driver gets refactored over time.

Because this memory is used only  within this function and thus released
at the bottom of it.

> 
>> +       if (!limits) {
>> +               dev_err(dev, "not enough mem for reading limits\n");
>> +               return -ENOMEM;
>> +       }
>> +       ret = of_property_read_u32_array(node, "limits", limits, 2 * ntrips);
>> +       if (!ret) {
>> +               int i = ntrips;
>> +
>> +               tbp->binding_limits = devm_kzalloc(dev,
>> +                                                  ntrips * 2 *
>> +                                                  sizeof(*tbp->binding_limits),
>> +                                                  GFP_KERNEL);
>> +               if (!tbp->binding_limits) {
>> +                       dev_err(dev, "not enough mem for storing limits\n");
>> +                       return -ENOMEM;
>> +               }
>> +               while (i--)
>> +                       tbp->binding_limits[i] = limits[i];
>> +       }
>> +       kfree(limits);

here.

>> +
>> +       return 0;
> 
> What if you failed to read the array? Surely you should return an error?

Attempting to make this property not mandatory.

> 
>> +}
>> +
>> +struct __thermal_trip {
>> +       unsigned long int temperature;
>> +       unsigned long int hysteresis;
>> +       enum thermal_trip_type type;
>> +};
>> +
>> +static
>> +int thermal_of_populate_trip(struct device *dev,
>> +                            struct device_node *node,
>> +                            struct __thermal_trip *trip)
>> +{
>> +       int ret;
>> +       int prop;
>> +
>> +       ret = of_property_read_u32(node, "temperature", &prop);
>> +       if (ret < 0) {
>> +               dev_err(dev, "missing temperature property\n");
>> +               return ret;
>> +       }
>> +       trip->temperature = prop;
>> +
>> +       ret = of_property_read_u32(node, "hysteresis", &prop);
>> +       if (ret < 0) {
>> +               dev_err(dev, "missing hysteresis property\n");
>> +               return ret;
>> +       }
>> +       trip->hysteresis = prop;
>> +
>> +       ret = of_property_read_u32(node, "type", &prop);
>> +       if (ret < 0) {
>> +               dev_err(dev, "missing type property\n");
>> +               return ret;
>> +       }
>> +       trip->type = prop;
> 
> This will require sanity checking.

OK.

> 
>> +
>> +       return 0;
>> +}
>> +
>> +struct __thermal_zone_device {
>> +       enum thermal_device_mode mode;
>> +       int passive_delay;
>> +       int polling_delay;
>> +       int mask;
>> +       int ntrips;
>> +       char type[THERMAL_NAME_LENGTH];
>> +       struct __thermal_trip *trips;
>> +       struct __thermal_bind_params *bind_params;
>> +       struct thermal_bind_params *tbps;
>> +       struct thermal_zone_params zone_params;
>> +       int (*get_temp)(void *, unsigned long *);
>> +       void *devdata;
>> +};
>> +
>> +static struct __thermal_zone_device *
>> +thermal_of_build_thermal_zone(struct device *dev, struct device_node *node)
>> +{
>> +       struct device_node *child, *gchild;
>> +       struct __thermal_zone_device *tz;
>> +       int ret, i;
>> +       u32 prop;
>> +
>> +       if (!node) {
>> +               dev_err(dev, "no thermal zone node\n");
>> +               return ERR_PTR(-EINVAL);
>> +       }
>> +
>> +       tz = devm_kzalloc(dev, sizeof(*tz), GFP_KERNEL);
>> +       if (!tz) {
>> +               dev_err(dev, "not enough memory for thermal of zone\n");
>> +               return ERR_PTR(-ENOMEM);
>> +       }
>> +
>> +       ret = of_property_read_u32(node, "passive_delay", &prop);
>> +       if (ret < 0) {
>> +               dev_err(dev, "missing passive_delay property\n");
>> +               return ERR_PTR(ret);
>> +       }
>> +       tz->passive_delay = prop;
>> +
>> +       ret = of_property_read_u32(node, "polling_delay", &prop);
>> +       if (ret < 0) {
>> +               dev_err(dev, "missing polling_delay property\n");
>> +               return ERR_PTR(ret);
>> +       }
>> +       tz->polling_delay = prop;
>> +
>> +       ret = of_property_read_u32(node, "mask", &prop);
>> +       if (ret < 0) {
>> +               dev_err(dev, "missing mask property\n");
>> +               return ERR_PTR(ret);
>> +       }
>> +       tz->mask = prop;
>> +
>> +       /* assume node name as our zone type */
>> +       strncpy(tz->type, node->name, sizeof(tz->type));
>> +
>> +       /* default policy */
>> +       strncpy(tz->zone_params.governor_name, "step_wise",
>> +               sizeof(tz->zone_params.governor_name));
>> +
>> +       /* trips */
>> +       child = of_find_node_by_name(node, "trips");
> 
> That might not be a child node, as of_find_node_by_name walks over the
> list of all nodes. Use of_get_child_by_name.

Right! This is a bug.

> 
>> +
>> +       /* No trips provided */
>> +       if (!child)
>> +               goto finish;
>> +
>> +       tz->ntrips = of_get_child_count(child);
>> +       tz->trips = devm_kzalloc(dev, tz->ntrips * sizeof(*tz->trips),
>> +                                GFP_KERNEL);
>> +       if (!tz->trips)
>> +               return ERR_PTR(-ENOMEM);
>> +       i = 0;
>> +       for_each_child_of_node(child, gchild)
>> +               thermal_of_populate_trip(dev, gchild, &tz->trips[i++]);
> 
> What if a child node was not a valid trip node? It seems
> thermal_of_populate_trip returns errors you're ignoring.

OK. Adding proper treatment.

> 
>> +
>> +       /* bind_params */
>> +       child = of_find_node_by_name(node, "bind_params");
> 
> Another of_get_child_by_name candidate.

OK.

> 
>> +
>> +       /* No binding info */
>> +       if (!child)
>> +               goto finish;
>> +
>> +       tz->zone_params.num_tbps = of_get_child_count(child);
>> +       tz->bind_params = devm_kzalloc(dev,
>> +                                      tz->zone_params.num_tbps *
>> +                                               sizeof(*tz->bind_params),
>> +                                      GFP_KERNEL);
>> +       if (!tz->bind_params)
>> +               return ERR_PTR(-ENOMEM);
>> +       tz->zone_params.tbp = devm_kzalloc(dev,
>> +                                          tz->zone_params.num_tbps *
>> +                                               sizeof(*tz->zone_params.tbp),
>> +                                          GFP_KERNEL);
>> +       if (!tz->zone_params.tbp)
>> +               return ERR_PTR(-ENOMEM);
>> +       i = 0;
>> +       for_each_child_of_node(child, gchild) {
>> +               thermal_of_populate_bind_params(dev, gchild,
>> +                                               &tz->bind_params[i],
>> +                                               &tz->zone_params.tbp[i],
>> +                                               tz->ntrips);
> 
> Similarly, you're ignoring error conditions here. What if a bind_params
> node was malformed?


Adding proper error handling.

> 
>> +               i++;
>> +       }
>> +
>> +finish:
>> +       tz->mode = THERMAL_DEVICE_ENABLED;
>> +
>> +       return tz;
>> +}
>> +
>> +static
>> +int thermal_of_match(struct thermal_zone_device *tz,
>> +                    struct thermal_cooling_device *cdev)
>> +{
>> +       struct __thermal_zone_device *data = tz->devdata;
>> +       int i;
>> +
>> +       for (i = 0; i < data->zone_params.num_tbps; i++) {
>> +               if (!strncmp(data->bind_params[i].cooling_device,
>> +                            cdev->type,
>> +                            strlen(data->bind_params[i].cooling_device)) &&
>> +                   (data->zone_params.tbp[i].trip_mask & (1 << i)))
>> +                       return 0;
>> +       }
>> +
>> +       return -EINVAL;
>> +}
> 
> I'm not keen on binding to cooling devices using a string, as suddenly a
> name to allow humans to inspect the system is turned into an ABI.

OK. We need to align on how we describe the binding then.

> 
>> +
>> +static
>> +int of_thermal_get_temp(struct thermal_zone_device *tz,
>> +                       unsigned long *temp)
>> +{
>> +       struct __thermal_zone_device *data = tz->devdata;
>> +
>> +       return data->get_temp(data->devdata, temp);
>> +}
>> +
>> +static
>> +int of_thermal_get_mode(struct thermal_zone_device *tz,
>> +                       enum thermal_device_mode *mode)
>> +{
>> +       struct __thermal_zone_device *data = tz->devdata;
>> +
>> +       *mode = data->mode;
>> +
>> +       return 0;
>> +}
>> +
>> +static
>> +int of_thermal_set_mode(struct thermal_zone_device *tz,
>> +                       enum thermal_device_mode mode)
>> +{
>> +       struct __thermal_zone_device *data = tz->devdata;
>> +
>> +       mutex_lock(&tz->lock);
>> +
>> +       if (mode == THERMAL_DEVICE_ENABLED)
>> +               tz->polling_delay = data->polling_delay;
>> +       else
>> +               tz->polling_delay = 0;
>> +
>> +       mutex_unlock(&tz->lock);
>> +
>> +       data->mode = mode;
>> +       thermal_zone_device_update(tz);
>> +
>> +       return 0;
>> +}
>> +
>> +static
>> +int of_thermal_get_trip_type(struct thermal_zone_device *tz, int trip,
>> +                            enum thermal_trip_type *type)
>> +{
>> +       struct __thermal_zone_device *data = tz->devdata;
>> +
>> +       if (trip >= data->ntrips || trip < 0)
>> +               return -EDOM;
> 
> It's far more common to use -EINVAL.

hmm.. OK.

> 
>> +
>> +       *type = data->trips[trip].type;
>> +
>> +       return 0;
>> +}
>> +
>> +static
>> +int of_thermal_get_trip_temp(struct thermal_zone_device *tz, int trip,
>> +                            unsigned long *temp)
>> +{
>> +       struct __thermal_zone_device *data = tz->devdata;
>> +
>> +       if (trip >= data->ntrips || trip < 0)
>> +               return -EDOM;
>> +
>> +       *temp = data->trips[trip].temperature;
>> +
>> +       return 0;
>> +}
>> +
>> +static
>> +int of_thermal_set_trip_temp(struct thermal_zone_device *tz, int trip,
>> +                            unsigned long temp)
>> +{
>> +       struct __thermal_zone_device *data = tz->devdata;
>> +
>> +       if (trip >= data->ntrips || trip < 0)
>> +               return -EDOM;
>> +
>> +       /* thermal fw should take care of data->mask & (1 << trip) */
>> +       data->trips[trip].temperature = temp;
>> +
>> +       return 0;
>> +}
>> +
>> +static
>> +int of_thermal_get_trip_hyst(struct thermal_zone_device *tz, int trip,
>> +                            unsigned long *hyst)
>> +{
>> +       struct __thermal_zone_device *data = tz->devdata;
>> +
>> +       if (trip >= data->ntrips || trip < 0)
>> +               return -EDOM;
>> +
>> +       *hyst = data->trips[trip].hysteresis;
>> +
>> +       return 0;
>> +}
>> +
>> +static
>> +int of_thermal_set_trip_hyst(struct thermal_zone_device *tz, int trip,
>> +                            unsigned long hyst)
>> +{
>> +       struct __thermal_zone_device *data = tz->devdata;
>> +
>> +       if (trip >= data->ntrips || trip < 0)
>> +               return -EDOM;
>> +
>> +       /* thermal fw should take care of data->mask & (1 << trip) */
> 
> Could you elaborate on that comment?

In  case the trip is not assigned to be writable, this function won't be
called.


> 
>> +       data->trips[trip].hysteresis = hyst;
>> +
>> +       return 0;
>> +}
> 
> [...]
> 
> Thanks,
> Mark.
> 
> 


-- 
You have got to be excited about what you are doing. (L. Lamport)

Eduardo Valentin


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 295 bytes --]

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

* Re: [lm-sensors] [RFC PATCH 02/14] drivers: thermal: introduce device tree parser
@ 2013-08-27 13:44       ` Eduardo Valentin
  0 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-27 13:44 UTC (permalink / raw)
  To: Mark Rutland
  Cc: Eduardo Valentin, swarren, Pawel Moll, ian.campbell,
	grant.likely, rob.herring, linux, rui.zhang, wni, durgadoss.r,
	linux-pm, devicetree, lm-sensors, linux-kernel


[-- Attachment #1.1: Type: text/plain, Size: 31475 bytes --]

Hello Mark,


First of all, thanks for taking the time to review in such level of
detail. Lets try to align and have a common understanding. Answers go
inline. Please let me know if I missed something or if I made it more
confusing :-)

On 27-08-2013 06:22, Mark Rutland wrote:
> Hi,
> 
> On Sat, Aug 24, 2013 at 12:15:43AM +0100, Eduardo Valentin wrote:
>> In order to be able to build thermal policies
>> based on generic sensors, like I2C device, that
>> can be places in different points on different boards,
>> there is a need to have a way to feed board dependent
>> data into the thermal framework.
>>
>> This patch introduces a thermal data parser for device
>> tree. The parsed data is used to build thermal zones
>> and thermal binding parameters. The output data
>> can then be used to deploy thermal policies.
>>
>> This patch adds also documentation regarding this
>> API and how to define tree nodes to use
>> this infrastructure.
>>
>> Cc: Zhang Rui <rui.zhang@intel.com>
>> Cc: linux-pm@vger.kernel.org
>> Cc: linux-kernel@vger.kernel.org
>> Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
>> ---
>>  .../devicetree/bindings/thermal/thermal.txt        | 160 +++++++
>>  drivers/thermal/Kconfig                            |  13 +
>>  drivers/thermal/Makefile                           |   1 +
>>  drivers/thermal/thermal_dt.c                       | 473 +++++++++++++++++++++
>>  include/dt-bindings/thermal/thermal.h              |  27 ++
>>  include/linux/thermal.h                            |   3 +
>>  6 files changed, 677 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/thermal/thermal.txt
>>  create mode 100644 drivers/thermal/thermal_dt.c
>>  create mode 100644 include/dt-bindings/thermal/thermal.h
>>


General question on device tree documentation. Assuming there is such an
effort to make it Linux independent, is there other places out of Linux
tree that these binding must be documented?


>> diff --git a/Documentation/devicetree/bindings/thermal/thermal.txt b/Documentation/devicetree/bindings/thermal/thermal.txt
>> new file mode 100644
>> index 0000000..af20ab0
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/thermal/thermal.txt
>> @@ -0,0 +1,160 @@
>> +----------------------------------------
>> +Thermal Framework Device Tree descriptor
>> +----------------------------------------
>> +
>> +This file describes how to define a thermal structure using device tree.
>> +A thermal structure includes thermal zones and their components, such
>> +as name, trip points, polling intervals and cooling devices binding
>> +descriptors. A binding descriptor may contain information on how to
>> +react, with a cooling stepped action or a weight on a fair share.
>> +The target of device tree thermal descriptors is to describe only
>> +the hardware thermal aspects, not how the system must control or which
>> +algorithm or policy must take place. It follows a description of each
>> +type of device tree node.
>> +
>> +****
>> +trip
>> +****
>> +
>> +The trip node is a node to describe a point in the temperature domain
>> +in which the system takes an action. This node describes just the point,
>> +not the action.
>> +
>> +A node describing a trip must contain:
>> +- temperature: the trip temperature level, in milliCelsius.
>> +- hysteresis: a (low) hysteresis value on 'temperature'. This is a relative
>> +value, in milliCelsius.
> 
> Presumably this is a single (u32) cell?

Yes, both of them above are a single u32.

> 
>> +- type: the trip type. Here is the type mapping:
>> +       THERMAL_TRIP_ACTIVE
>> +       THERMAL_TRIP_PASSIVE
>> +       THERMAL_TRIP_HOT
>> +       THERMAL_TRIP_CRITICAL
> 
> What type is this property?
> 
> What are these values? Do you need to refer to a header somewhere?

There is a header, introduced in this patch.
include/dt-bindings/thermal/thermal.h

> Symbolic constants should have an associated value for an ABI.

OK. Sounds reasonable to me. Shall we be descriptive and enlist the
values in this doc too or just pointing to header is fine?

> 
>> +
>> +**********
>> +bind_param
>> +**********
>> +
>> +The bind_param node is a node to describe how cooling devices get assigned
>> +to trip points of the zone. The cooling devices are expected to be loaded
>> +in the target system.
>> +
>> +A node describing a bind_param must contain:
>> +- cooling_device: A string with the cooling device name.
> 
> Please use '-' rather than '_' in bindings. That's the normal devicetree
> convention, and there's no point gonig against it and causing more
> confusion.

Agreed.

> 
> What are valid values of this string, and what do they mean?

These are the name of the cooling devices to match to.

> 
> Why not a phandle + cells binding to cooling devices?
> 

Yeah, this could work too. I am going to check how that would look like
and come back to you.

>> +- weight: The 'influence' of a particular cooling device on this zone.
>> +             This is on a percentage scale. The sum of all these weights
>> +             (for a particular zone) cannot exceed 100.
> 
> This is a bit fuzzy, and certainly needs more guidance.

OK. This property is used to describe the amount of cooling contribution
when activating a cooling device at a certain trip point. I will work on
a better guidance.

> 
>> +- trip_mask: This is a bit mask that gives the binding relation between
>> +               this thermal zone and cdev, for a particular trip point.
>> +               If nth bit is set, then the cdev and thermal zone are bound
>> +               for trip point n.
> 
> What type is this?
> 
> The nth bit from which end?
> 
> Could you explain what "bound for trip point n" means?
> 

It is just a way to match a cooling device with a set of trip points.
Say you want to match one specific cooling device with trips 0 and 1,
you would then create a bind_param with trip_mask = 0x3.

> Just because this is a bitmask in Linux does not mean it needs to be so
> in the dt.

Indeed.

In case we work with phandle + cell binging parameters, the trip and
weight could be passed as params.

	cooling-devices = <&devX tripY weightZ>, <... >;



> 
>> +- limits: An array integers consisting of 2-tuples items, and each item means
>> +  lower and upper state limits, like <min-state max-state>.
>> +
>> +**************************
>> +temperature sensor devices
>> +**************************
>> +
>> +Temperature sensor devices have to be linked to a specific thermal zone.
>> +This is done by means of the 'monitored-zones' list.
>> +- monitored-zones: A list of thermal zones phandles, identifying which
>> +thermal zones the temperature sensor device is used to monitor.
> 
> Why does this need to be described that way around?
> 
> Can the zone not have a link to the sensor(s) it needs?
> 

Do you see any issues with it?

Idea is that sensor nodes would list which zones they are used.  Same
idea goes to cooling devices. It can be the other way around, yes. It
depends on what is the best way to describe these relations. Idea would
be so that sensors and cooling devices would be composing a thermal zone.

>> +
>> +************
>> +thermal_zone
>> +************
>> +
>> +The thermal_zone node is the node containing all the required info
>> +for describing a thermal zone, including its cdev bindings. The thermal_zone
>> +node must contain, apart from its own properties, one node containing
>> +trip nodes and one node containing all the zone bind parameters.
>> +
>> +Required properties:
>> +- mask: Bit string: If 'n'th bit is set, then trip point 'n' is writeable.
> 
> What type is a bit string in devicetree? I'm aware of cells and (byte)
> strings, but not bit strings.
> 
> What does 'writeable' mean in this context?
> 
> There's presumably a better name than 'mask'.
> 

This is used to describe if trip points are writeable under sysfs. I
think this is a OS implementation leak. I will be removing this from
device tree and making them RO by default.

>> +
>> +- passive_delay: number of milliseconds to wait between polls when
>> +  performing passive cooling.
>> +
>> +- polling_delay: number of milliseconds to wait between polls when checking.
> 
> These sound very much like configuration of the driver rather than
> hardware description. What if my temperature sensor can generate an
> interrupt at some trigger temperature? Why would I need polling times?
> 
> Why does this need to be in the dt at all? Surely the OS can choose some
> sensible polling period, possibly dynamically?

Well, let me answer this one with another question. How the OS will
determine how fast is the temperature rise on a thermal zone described
in device tree?

> 
>> +
>> +- #thermal-cells: An integer that is used to specify how many cells compose
>> +  sensor ids.
> 
> I don't see why this is necessary. If the zone itself described its
> related sensors rather than the other way around, we wouldn't need it at
> all. Most bindings so far have consumers link to their providers rather
> than the other way around.
> 

I see.


>> +
>> +Below is an example:
>> +cpu_thermal: thermal_zone {
>> +            #thermal-cells = <1>;
>> +            mask = <0x03>; /* trips writability */
>> +            passive_delay = <250>; /* milliseconds */
>> +            polling_delay = <1000>; /* milliseconds */
>> +            trips {
>> +                    alert@100000{
>> +                            temperature = <100000>; /* milliCelsius */
>> +                            hysteresis = <0>; /* milliCelsius */
>> +                            type = <THERMAL_TRIP_PASSIVE>;
>> +                    };
>> +                    crit@125000{
>> +                            temperature = <125000>; /* milliCelsius */
>> +                            hysteresis = <0>; /* milliCelsius */
>> +                            type = <THERMAL_TRIP_CRITICAL>;
>> +                    };
>> +            };
>> +            bind_params {
>> +                    action@0{
>> +                            cooling_device = "thermal-cpufreq";
> 
> NAK. That value was not defined anywhere, and represents Linux
> infrastructure rather than hardware.
> 

Yes, this was another leak as discussed above in the upper part of the
doc file.

> For this case, we could just as easily describe the thermal points, and
> if no physical cooling device (e.g. a fan) is present, assume
> cpufreq-base cooling.  Other OSs could choose to do otherwise, and we
> could change later...
> 

The way other specifications do (aka ACPI) is to have trip types. In
case a trip type is passive cooling, it means one is supposed to
modulate the dissipated power rather than activating a device to remove
heat (active cooling).

The part of 'assuming' things that bothers me. I would rather have a way
to really say one wants to have passive cooling at a specific trip point.


>> +                            weight = <100>; /* percentage */
>> +                            mask = <0x01>;
> 
> This should presumably be trip-mask (assuming my suggested corrections).
> 
> What is it supposed to mean here?

As stated above, it means the trip points that this binding represents.

> 
>> +                           limits = <
>> +                             /* lower-state            upper-state */
>> +                               1                       THERMAL_NO_LIMITS
>> +                               THERMAL_NO_LIMITS       THERMAL_NO_LIMITS
>> +                           >;
>> +                    };
>> +            };
>> +};
>> +
>> +sensor: adc@0xFFFF {
>> +       ...
>> +       monitored-zones = <&cpu_thermal 0>;
>> +};
>> +
>> +cpu@0 {
>> +       ...
>> +       cooling-zones = <&cpu_thermal>;
>> +};
>> +
>> +In the example above, the ADC sensor at address 0xFFFF is used to monitor
>> +the zone 'cpu_thermal' using its the sensor 0. The cpu@0 device is also linked
>> +to the same thermal zone 'cpu_thermal' as a cooling device.
> 
> Huh? That seems to imply the the '0' in '<&cpu_thermal 0>' on the sensor
> node describes a property of the sensor rather than the thermal node,
> unless I've misunderstood?
> 

It is essentially which sensor id is used to monitor a specific zone. In
case of sensor IPs that feature several internal sensors, one needs to
have a way to describe which sensor monitors which zone. Example of this
type of IPs: lm90 (up to 3 sensors) and TI bandgap IP (can contain up to
5 internal sensors). The probe happens for the IP device and not for the
internal sensors.


>> +
>> +***************
>> +cpufreq-cooling
>> +***************
>> +
>> +The generic cpu cooling (freq clipping) can be loaded by the
>> +generic cpufreq-cpu0 driver in case the device tree node informs
>> +this need.
>> +
>> +In order to load the cpufreq cooling device, it is possible to
>> +inform that the cpu needs cooling by adding the list of thermal zones
>> +in the 'cooling-zones' property at the cpu0 phandle.
> 
> This should be reworded so as to describe the binding rather than the
> Linux behaviour based on the binding.

OK.

> 
>> +
>> +Example:
>> +       cpus {
>> +               cpu@0 {
>> +                       operating-points = <
>> +                               /* kHz    uV */
>> +                               800000  1313000
>> +                               1008000 1375000
>> +                       >;
>> +                       cooling-zones = <&cpu_thermal>;
>> +               };
>> +       ...
>> +       };
>> +
>> +The above will cause the cpufreq-cpu0 driver to understand that
>> +the cpu will need passive cooling and while probing that node it will
>> +also load the cpufreq cpu cooling device in that system.
> 
> The above describe that the CPU is part of a cooling (thermal?) zone and
> requires cooling.

That says the cpu participates in a thermal zone as a cooling
device/mechanism, thus cpu cooling (passive cooling) is required in
target system.

> 
>> +
>> +However, be advised that this flag will not describe what needs to
>> +be done or how the cpufreq cooling device will be used. In order to
>> +accomplish this, one needs to write a phandle for a thermal zone, as
>> +described in the section 'thermal_zone'.
> 
> The above already has a phandle to a thermal (cooling?) zone.
> 
> Please choose either cooling zone or thermal zone, having the two names
> makes this more confusing than necessary.

I see. Idea is to have thermal zone as a node. cooling-zone is just a
list of thermal zones that the referred device will be used as cooling
device.

> 
>> diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
>> index 7fb16bc..753f0dc 100644
>> --- a/drivers/thermal/Kconfig
>> +++ b/drivers/thermal/Kconfig
>> @@ -29,6 +29,19 @@ config THERMAL_HWMON
>>           Say 'Y' here if you want all thermal sensors to
>>           have hwmon sysfs interface too.
>>
>> +config THERMAL_OF
>> +       bool
>> +       prompt "APIs to parse thermal data out of device tree"
>> +       depends on OF
>> +       default y
>> +       help
>> +         This options provides helpers to add the support to
>> +         read and parse thermal data definitions out of the
>> +         device tree blob.
>> +
>> +         Say 'Y' here if you need to build thermal infrastructure
>> +         based on device tree.
>> +
>>  choice
>>         prompt "Default Thermal governor"
>>         default THERMAL_DEFAULT_GOV_STEP_WISE
>> diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
>> index 24cb894..eedb273 100644
>> --- a/drivers/thermal/Makefile
>> +++ b/drivers/thermal/Makefile
>> @@ -7,6 +7,7 @@ thermal_sys-y                   += thermal_core.o
>>
>>  # interface to/from other layers providing sensors
>>  thermal_sys-$(CONFIG_THERMAL_HWMON)            += thermal_hwmon.o
>> +thermal_sys-$(CONFIG_THERMAL_OF)               += thermal_dt.o
>>
>>  # governors
>>  thermal_sys-$(CONFIG_THERMAL_GOV_FAIR_SHARE)   += fair_share.o
>> diff --git a/drivers/thermal/thermal_dt.c b/drivers/thermal/thermal_dt.c
>> new file mode 100644
>> index 0000000..cc35485
>> --- /dev/null
>> +++ b/drivers/thermal/thermal_dt.c
>> @@ -0,0 +1,473 @@
>> +/*
>> + *  thermal_dt.c - Generic Thermal Management device tree support.
>> + *
>> + *  Copyright (C) 2013 Texas Instruments
>> + *  Copyright (C) 2013 Eduardo Valentin <eduardo.valentin@ti.com>
>> + *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>> + *
>> + *  This program is free software; you can redistribute it and/or modify
>> + *  it under the terms of the GNU General Public License as published by
>> + *  the Free Software Foundation; version 2 of the License.
>> + *
>> + *  This program is distributed in the hope that it will be useful, but
>> + *  WITHOUT ANY WARRANTY; without even the implied warranty of
>> + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> + *  General Public License for more details.
>> + *
>> + *  You should have received a copy of the GNU General Public License along
>> + *  with this program; if not, write to the Free Software Foundation, Inc.,
>> + *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
>> + *
>> + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>> + */
>> +#include <linux/thermal.h>
>> +#include <linux/slab.h>
>> +#include <linux/types.h>
>> +#include <linux/of_device.h>
>> +#include <linux/of_platform.h>
>> +#include <linux/err.h>
>> +#include <linux/export.h>
>> +#include <linux/string.h>
>> +
>> +struct __thermal_bind_params {
>> +       char cooling_device[THERMAL_NAME_LENGTH];
>> +};
>> +
>> +static
>> +int thermal_of_match(struct thermal_zone_device *tz,
>> +                    struct thermal_cooling_device *cdev);
>> +
>> +static int thermal_of_populate_bind_params(struct device *dev,
>> +                                          struct device_node *node,
>> +                                          struct __thermal_bind_params *__tbp,
>> +                                          struct thermal_bind_params *tbp,
>> +                                          int ntrips)
>> +{
>> +       const char *cdev_name;
>> +       u32 *limits;
>> +       int ret;
>> +       u32 prop;
>> +
>> +       ret = of_property_read_u32(node, "weight", &prop);
>> +       if (ret < 0) {
>> +               dev_err(dev, "missing weight property\n");
>> +               return ret;
>> +       }
>> +       tbp->weight = prop;
>> +
>> +       ret = of_property_read_u32(node, "mask", &prop);
>> +       if (ret < 0) {
>> +               dev_err(dev, "missing mask property\n");
>> +               return ret;
>> +       }
>> +       tbp->trip_mask = prop;
>> +
>> +       /* this will allow us to bind with cooling devices */
>> +       tbp->match = thermal_of_match;
>> +
>> +       ret = of_property_read_string(node, "cooling_device", &cdev_name);
>> +       if (ret < 0) {
>> +               dev_err(dev, "missing cooling_device property\n");
>> +               return ret;
>> +       }
>> +       strncpy(__tbp->cooling_device, cdev_name,
>> +               sizeof(__tbp->cooling_device));
>> +
>> +       limits = kzalloc(ntrips * sizeof(*limits) * 2, GFP_KERNEL);
> 
> Why do you use kzalloc here, but devm_kzalloc elsewhere? That'll lead to
> problems as the driver gets refactored over time.

Because this memory is used only  within this function and thus released
at the bottom of it.

> 
>> +       if (!limits) {
>> +               dev_err(dev, "not enough mem for reading limits\n");
>> +               return -ENOMEM;
>> +       }
>> +       ret = of_property_read_u32_array(node, "limits", limits, 2 * ntrips);
>> +       if (!ret) {
>> +               int i = ntrips;
>> +
>> +               tbp->binding_limits = devm_kzalloc(dev,
>> +                                                  ntrips * 2 *
>> +                                                  sizeof(*tbp->binding_limits),
>> +                                                  GFP_KERNEL);
>> +               if (!tbp->binding_limits) {
>> +                       dev_err(dev, "not enough mem for storing limits\n");
>> +                       return -ENOMEM;
>> +               }
>> +               while (i--)
>> +                       tbp->binding_limits[i] = limits[i];
>> +       }
>> +       kfree(limits);

here.

>> +
>> +       return 0;
> 
> What if you failed to read the array? Surely you should return an error?

Attempting to make this property not mandatory.

> 
>> +}
>> +
>> +struct __thermal_trip {
>> +       unsigned long int temperature;
>> +       unsigned long int hysteresis;
>> +       enum thermal_trip_type type;
>> +};
>> +
>> +static
>> +int thermal_of_populate_trip(struct device *dev,
>> +                            struct device_node *node,
>> +                            struct __thermal_trip *trip)
>> +{
>> +       int ret;
>> +       int prop;
>> +
>> +       ret = of_property_read_u32(node, "temperature", &prop);
>> +       if (ret < 0) {
>> +               dev_err(dev, "missing temperature property\n");
>> +               return ret;
>> +       }
>> +       trip->temperature = prop;
>> +
>> +       ret = of_property_read_u32(node, "hysteresis", &prop);
>> +       if (ret < 0) {
>> +               dev_err(dev, "missing hysteresis property\n");
>> +               return ret;
>> +       }
>> +       trip->hysteresis = prop;
>> +
>> +       ret = of_property_read_u32(node, "type", &prop);
>> +       if (ret < 0) {
>> +               dev_err(dev, "missing type property\n");
>> +               return ret;
>> +       }
>> +       trip->type = prop;
> 
> This will require sanity checking.

OK.

> 
>> +
>> +       return 0;
>> +}
>> +
>> +struct __thermal_zone_device {
>> +       enum thermal_device_mode mode;
>> +       int passive_delay;
>> +       int polling_delay;
>> +       int mask;
>> +       int ntrips;
>> +       char type[THERMAL_NAME_LENGTH];
>> +       struct __thermal_trip *trips;
>> +       struct __thermal_bind_params *bind_params;
>> +       struct thermal_bind_params *tbps;
>> +       struct thermal_zone_params zone_params;
>> +       int (*get_temp)(void *, unsigned long *);
>> +       void *devdata;
>> +};
>> +
>> +static struct __thermal_zone_device *
>> +thermal_of_build_thermal_zone(struct device *dev, struct device_node *node)
>> +{
>> +       struct device_node *child, *gchild;
>> +       struct __thermal_zone_device *tz;
>> +       int ret, i;
>> +       u32 prop;
>> +
>> +       if (!node) {
>> +               dev_err(dev, "no thermal zone node\n");
>> +               return ERR_PTR(-EINVAL);
>> +       }
>> +
>> +       tz = devm_kzalloc(dev, sizeof(*tz), GFP_KERNEL);
>> +       if (!tz) {
>> +               dev_err(dev, "not enough memory for thermal of zone\n");
>> +               return ERR_PTR(-ENOMEM);
>> +       }
>> +
>> +       ret = of_property_read_u32(node, "passive_delay", &prop);
>> +       if (ret < 0) {
>> +               dev_err(dev, "missing passive_delay property\n");
>> +               return ERR_PTR(ret);
>> +       }
>> +       tz->passive_delay = prop;
>> +
>> +       ret = of_property_read_u32(node, "polling_delay", &prop);
>> +       if (ret < 0) {
>> +               dev_err(dev, "missing polling_delay property\n");
>> +               return ERR_PTR(ret);
>> +       }
>> +       tz->polling_delay = prop;
>> +
>> +       ret = of_property_read_u32(node, "mask", &prop);
>> +       if (ret < 0) {
>> +               dev_err(dev, "missing mask property\n");
>> +               return ERR_PTR(ret);
>> +       }
>> +       tz->mask = prop;
>> +
>> +       /* assume node name as our zone type */
>> +       strncpy(tz->type, node->name, sizeof(tz->type));
>> +
>> +       /* default policy */
>> +       strncpy(tz->zone_params.governor_name, "step_wise",
>> +               sizeof(tz->zone_params.governor_name));
>> +
>> +       /* trips */
>> +       child = of_find_node_by_name(node, "trips");
> 
> That might not be a child node, as of_find_node_by_name walks over the
> list of all nodes. Use of_get_child_by_name.

Right! This is a bug.

> 
>> +
>> +       /* No trips provided */
>> +       if (!child)
>> +               goto finish;
>> +
>> +       tz->ntrips = of_get_child_count(child);
>> +       tz->trips = devm_kzalloc(dev, tz->ntrips * sizeof(*tz->trips),
>> +                                GFP_KERNEL);
>> +       if (!tz->trips)
>> +               return ERR_PTR(-ENOMEM);
>> +       i = 0;
>> +       for_each_child_of_node(child, gchild)
>> +               thermal_of_populate_trip(dev, gchild, &tz->trips[i++]);
> 
> What if a child node was not a valid trip node? It seems
> thermal_of_populate_trip returns errors you're ignoring.

OK. Adding proper treatment.

> 
>> +
>> +       /* bind_params */
>> +       child = of_find_node_by_name(node, "bind_params");
> 
> Another of_get_child_by_name candidate.

OK.

> 
>> +
>> +       /* No binding info */
>> +       if (!child)
>> +               goto finish;
>> +
>> +       tz->zone_params.num_tbps = of_get_child_count(child);
>> +       tz->bind_params = devm_kzalloc(dev,
>> +                                      tz->zone_params.num_tbps *
>> +                                               sizeof(*tz->bind_params),
>> +                                      GFP_KERNEL);
>> +       if (!tz->bind_params)
>> +               return ERR_PTR(-ENOMEM);
>> +       tz->zone_params.tbp = devm_kzalloc(dev,
>> +                                          tz->zone_params.num_tbps *
>> +                                               sizeof(*tz->zone_params.tbp),
>> +                                          GFP_KERNEL);
>> +       if (!tz->zone_params.tbp)
>> +               return ERR_PTR(-ENOMEM);
>> +       i = 0;
>> +       for_each_child_of_node(child, gchild) {
>> +               thermal_of_populate_bind_params(dev, gchild,
>> +                                               &tz->bind_params[i],
>> +                                               &tz->zone_params.tbp[i],
>> +                                               tz->ntrips);
> 
> Similarly, you're ignoring error conditions here. What if a bind_params
> node was malformed?


Adding proper error handling.

> 
>> +               i++;
>> +       }
>> +
>> +finish:
>> +       tz->mode = THERMAL_DEVICE_ENABLED;
>> +
>> +       return tz;
>> +}
>> +
>> +static
>> +int thermal_of_match(struct thermal_zone_device *tz,
>> +                    struct thermal_cooling_device *cdev)
>> +{
>> +       struct __thermal_zone_device *data = tz->devdata;
>> +       int i;
>> +
>> +       for (i = 0; i < data->zone_params.num_tbps; i++) {
>> +               if (!strncmp(data->bind_params[i].cooling_device,
>> +                            cdev->type,
>> +                            strlen(data->bind_params[i].cooling_device)) &&
>> +                   (data->zone_params.tbp[i].trip_mask & (1 << i)))
>> +                       return 0;
>> +       }
>> +
>> +       return -EINVAL;
>> +}
> 
> I'm not keen on binding to cooling devices using a string, as suddenly a
> name to allow humans to inspect the system is turned into an ABI.

OK. We need to align on how we describe the binding then.

> 
>> +
>> +static
>> +int of_thermal_get_temp(struct thermal_zone_device *tz,
>> +                       unsigned long *temp)
>> +{
>> +       struct __thermal_zone_device *data = tz->devdata;
>> +
>> +       return data->get_temp(data->devdata, temp);
>> +}
>> +
>> +static
>> +int of_thermal_get_mode(struct thermal_zone_device *tz,
>> +                       enum thermal_device_mode *mode)
>> +{
>> +       struct __thermal_zone_device *data = tz->devdata;
>> +
>> +       *mode = data->mode;
>> +
>> +       return 0;
>> +}
>> +
>> +static
>> +int of_thermal_set_mode(struct thermal_zone_device *tz,
>> +                       enum thermal_device_mode mode)
>> +{
>> +       struct __thermal_zone_device *data = tz->devdata;
>> +
>> +       mutex_lock(&tz->lock);
>> +
>> +       if (mode == THERMAL_DEVICE_ENABLED)
>> +               tz->polling_delay = data->polling_delay;
>> +       else
>> +               tz->polling_delay = 0;
>> +
>> +       mutex_unlock(&tz->lock);
>> +
>> +       data->mode = mode;
>> +       thermal_zone_device_update(tz);
>> +
>> +       return 0;
>> +}
>> +
>> +static
>> +int of_thermal_get_trip_type(struct thermal_zone_device *tz, int trip,
>> +                            enum thermal_trip_type *type)
>> +{
>> +       struct __thermal_zone_device *data = tz->devdata;
>> +
>> +       if (trip >= data->ntrips || trip < 0)
>> +               return -EDOM;
> 
> It's far more common to use -EINVAL.

hmm.. OK.

> 
>> +
>> +       *type = data->trips[trip].type;
>> +
>> +       return 0;
>> +}
>> +
>> +static
>> +int of_thermal_get_trip_temp(struct thermal_zone_device *tz, int trip,
>> +                            unsigned long *temp)
>> +{
>> +       struct __thermal_zone_device *data = tz->devdata;
>> +
>> +       if (trip >= data->ntrips || trip < 0)
>> +               return -EDOM;
>> +
>> +       *temp = data->trips[trip].temperature;
>> +
>> +       return 0;
>> +}
>> +
>> +static
>> +int of_thermal_set_trip_temp(struct thermal_zone_device *tz, int trip,
>> +                            unsigned long temp)
>> +{
>> +       struct __thermal_zone_device *data = tz->devdata;
>> +
>> +       if (trip >= data->ntrips || trip < 0)
>> +               return -EDOM;
>> +
>> +       /* thermal fw should take care of data->mask & (1 << trip) */
>> +       data->trips[trip].temperature = temp;
>> +
>> +       return 0;
>> +}
>> +
>> +static
>> +int of_thermal_get_trip_hyst(struct thermal_zone_device *tz, int trip,
>> +                            unsigned long *hyst)
>> +{
>> +       struct __thermal_zone_device *data = tz->devdata;
>> +
>> +       if (trip >= data->ntrips || trip < 0)
>> +               return -EDOM;
>> +
>> +       *hyst = data->trips[trip].hysteresis;
>> +
>> +       return 0;
>> +}
>> +
>> +static
>> +int of_thermal_set_trip_hyst(struct thermal_zone_device *tz, int trip,
>> +                            unsigned long hyst)
>> +{
>> +       struct __thermal_zone_device *data = tz->devdata;
>> +
>> +       if (trip >= data->ntrips || trip < 0)
>> +               return -EDOM;
>> +
>> +       /* thermal fw should take care of data->mask & (1 << trip) */
> 
> Could you elaborate on that comment?

In  case the trip is not assigned to be writable, this function won't be
called.


> 
>> +       data->trips[trip].hysteresis = hyst;
>> +
>> +       return 0;
>> +}
> 
> [...]
> 
> Thanks,
> Mark.
> 
> 


-- 
You have got to be excited about what you are doing. (L. Lamport)

Eduardo Valentin


[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 295 bytes --]

[-- Attachment #2: Type: text/plain, Size: 153 bytes --]

_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

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

* Re: [RFC PATCH 02/14] drivers: thermal: introduce device tree parser
  2013-08-27 13:44       ` [lm-sensors] " Eduardo Valentin
@ 2013-08-27 16:23         ` Mark Rutland
  -1 siblings, 0 replies; 100+ messages in thread
From: Mark Rutland @ 2013-08-27 16:23 UTC (permalink / raw)
  To: Eduardo Valentin, swarren
  Cc: Pawel Moll, ian.campbell, grant.likely, rob.herring, linux,
	rui.zhang, wni, durgadoss.r, linux-pm, devicetree, lm-sensors,
	linux-kernel

On Tue, Aug 27, 2013 at 02:44:40PM +0100, Eduardo Valentin wrote:
> Hello Mark,
>
>
> First of all, thanks for taking the time to review in such level of
> detail. Lets try to align and have a common understanding. Answers go
> inline. Please let me know if I missed something or if I made it more
> confusing :-)
>
> On 27-08-2013 06:22, Mark Rutland wrote:
> > Hi,
> >
> > On Sat, Aug 24, 2013 at 12:15:43AM +0100, Eduardo Valentin wrote:
> >> In order to be able to build thermal policies
> >> based on generic sensors, like I2C device, that
> >> can be places in different points on different boards,
> >> there is a need to have a way to feed board dependent
> >> data into the thermal framework.
> >>
> >> This patch introduces a thermal data parser for device
> >> tree. The parsed data is used to build thermal zones
> >> and thermal binding parameters. The output data
> >> can then be used to deploy thermal policies.
> >>
> >> This patch adds also documentation regarding this
> >> API and how to define tree nodes to use
> >> this infrastructure.
> >>
> >> Cc: Zhang Rui <rui.zhang@intel.com>
> >> Cc: linux-pm@vger.kernel.org
> >> Cc: linux-kernel@vger.kernel.org
> >> Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
> >> ---
> >>  .../devicetree/bindings/thermal/thermal.txt        | 160 +++++++
> >>  drivers/thermal/Kconfig                            |  13 +
> >>  drivers/thermal/Makefile                           |   1 +
> >>  drivers/thermal/thermal_dt.c                       | 473 +++++++++++++++++++++
> >>  include/dt-bindings/thermal/thermal.h              |  27 ++
> >>  include/linux/thermal.h                            |   3 +
> >>  6 files changed, 677 insertions(+)
> >>  create mode 100644 Documentation/devicetree/bindings/thermal/thermal.txt
> >>  create mode 100644 drivers/thermal/thermal_dt.c
> >>  create mode 100644 include/dt-bindings/thermal/thermal.h
> >>
>
>
> General question on device tree documentation. Assuming there is such an
> effort to make it Linux independent, is there other places out of Linux
> tree that these binding must be documented?

At present, no. There is a plan to move the documentation out of the
kernel, but I'm not sure on how that's currently progressing. Some
general cleanup needs to occur before we can actually do that.

>
>
> >> diff --git a/Documentation/devicetree/bindings/thermal/thermal.txt b/Documentation/devicetree/bindings/thermal/thermal.txt
> >> new file mode 100644
> >> index 0000000..af20ab0
> >> --- /dev/null
> >> +++ b/Documentation/devicetree/bindings/thermal/thermal.txt
> >> @@ -0,0 +1,160 @@
> >> +----------------------------------------
> >> +Thermal Framework Device Tree descriptor
> >> +----------------------------------------
> >> +
> >> +This file describes how to define a thermal structure using device tree.
> >> +A thermal structure includes thermal zones and their components, such
> >> +as name, trip points, polling intervals and cooling devices binding
> >> +descriptors. A binding descriptor may contain information on how to
> >> +react, with a cooling stepped action or a weight on a fair share.
> >> +The target of device tree thermal descriptors is to describe only
> >> +the hardware thermal aspects, not how the system must control or which
> >> +algorithm or policy must take place. It follows a description of each
> >> +type of device tree node.
> >> +
> >> +****
> >> +trip
> >> +****
> >> +
> >> +The trip node is a node to describe a point in the temperature domain
> >> +in which the system takes an action. This node describes just the point,
> >> +not the action.
> >> +
> >> +A node describing a trip must contain:
> >> +- temperature: the trip temperature level, in milliCelsius.
> >> +- hysteresis: a (low) hysteresis value on 'temperature'. This is a relative
> >> +value, in milliCelsius.
> >
> > Presumably this is a single (u32) cell?
>
> Yes, both of them above are a single u32.

Ok. This seems to be the default assumption in many bindings, so I
shan't argue against it here, but in general we should be as precise as
possible as to the format of the devicetree.

>
> >
> >> +- type: the trip type. Here is the type mapping:
> >> +       THERMAL_TRIP_ACTIVE
> >> +       THERMAL_TRIP_PASSIVE
> >> +       THERMAL_TRIP_HOT
> >> +       THERMAL_TRIP_CRITICAL
> >
> > What type is this property?
> >
> > What are these values? Do you need to refer to a header somewhere?
>
> There is a header, introduced in this patch.
> include/dt-bindings/thermal/thermal.h
>
> > Symbolic constants should have an associated value for an ABI.
>
> OK. Sounds reasonable to me. Shall we be descriptive and enlist the
> values in this doc too or just pointing to header is fine?

I believe that referring to the header is fine, though personally I'd
prefer if we were explicit in binding docs. I'll leave Stephen to
comment on what the preferred way of handling header constants with
binding documents is.

>
> >
> >> +
> >> +**********
> >> +bind_param
> >> +**********
> >> +
> >> +The bind_param node is a node to describe how cooling devices get assigned
> >> +to trip points of the zone. The cooling devices are expected to be loaded
> >> +in the target system.
> >> +
> >> +A node describing a bind_param must contain:
> >> +- cooling_device: A string with the cooling device name.
> >
> > Please use '-' rather than '_' in bindings. That's the normal devicetree
> > convention, and there's no point gonig against it and causing more
> > confusion.
>
> Agreed.
>
> >
> > What are valid values of this string, and what do they mean?
>
> These are the name of the cooling devices to match to.

Which are what exactly? What constitutes a "cooling device"?

Is "black-body radiation" [1] a valid cooling device?

How about "copper heat sink"?

>
> >
> > Why not a phandle + cells binding to cooling devices?
> >
>
> Yeah, this could work too. I am going to check how that would look like
> and come back to you.

Ok.

>
> >> +- weight: The 'influence' of a particular cooling device on this zone.
> >> +             This is on a percentage scale. The sum of all these weights
> >> +             (for a particular zone) cannot exceed 100.
> >
> > This is a bit fuzzy, and certainly needs more guidance.
>
> OK. This property is used to describe the amount of cooling contribution
> when activating a cooling device at a certain trip point. I will work on
> a better guidance.
>
> >
> >> +- trip_mask: This is a bit mask that gives the binding relation between
> >> +               this thermal zone and cdev, for a particular trip point.
> >> +               If nth bit is set, then the cdev and thermal zone are bound
> >> +               for trip point n.
> >
> > What type is this?
> >
> > The nth bit from which end?
> >
> > Could you explain what "bound for trip point n" means?
> >
>
> It is just a way to match a cooling device with a set of trip points.
> Say you want to match one specific cooling device with trips 0 and 1,
> you would then create a bind_param with trip_mask = 0x3.
>
> > Just because this is a bitmask in Linux does not mean it needs to be so
> > in the dt.
>
> Indeed.
>
> In case we work with phandle + cell binging parameters, the trip and
> weight could be passed as params.
>
>       cooling-devices = <&devX tripY weightZ>, <... >;

Something like that could certainly work.

>
> >
> >> +- limits: An array integers consisting of 2-tuples items, and each item means
> >> +  lower and upper state limits, like <min-state max-state>.
> >> +
> >> +**************************
> >> +temperature sensor devices
> >> +**************************
> >> +
> >> +Temperature sensor devices have to be linked to a specific thermal zone.
> >> +This is done by means of the 'monitored-zones' list.
> >> +- monitored-zones: A list of thermal zones phandles, identifying which
> >> +thermal zones the temperature sensor device is used to monitor.
> >
> > Why does this need to be described that way around?
> >
> > Can the zone not have a link to the sensor(s) it needs?
> >
>
> Do you see any issues with it?
>
> Idea is that sensor nodes would list which zones they are used.  Same
> idea goes to cooling devices. It can be the other way around, yes. It
> depends on what is the best way to describe these relations. Idea would
> be so that sensors and cooling devices would be composing a thermal zone.

I think that having a zone refer to the sensors that monitor it would be
preferable. Otherwise we're encoding that way a devices output is to be
consumed on the binding for the device itself, which feels odd (it's
arguable as to whether it's a property of the device, however).

>
> >> +
> >> +************
> >> +thermal_zone
> >> +************
> >> +
> >> +The thermal_zone node is the node containing all the required info
> >> +for describing a thermal zone, including its cdev bindings. The thermal_zone
> >> +node must contain, apart from its own properties, one node containing
> >> +trip nodes and one node containing all the zone bind parameters.
> >> +
> >> +Required properties:
> >> +- mask: Bit string: If 'n'th bit is set, then trip point 'n' is writeable.
> >
> > What type is a bit string in devicetree? I'm aware of cells and (byte)
> > strings, but not bit strings.
> >
> > What does 'writeable' mean in this context?
> >
> > There's presumably a better name than 'mask'.
> >
>
> This is used to describe if trip points are writeable under sysfs. I
> think this is a OS implementation leak. I will be removing this from
> device tree and making them RO by default.

Ok.

>
> >> +
> >> +- passive_delay: number of milliseconds to wait between polls when
> >> +  performing passive cooling.
> >> +
> >> +- polling_delay: number of milliseconds to wait between polls when checking.
> >
> > These sound very much like configuration of the driver rather than
> > hardware description. What if my temperature sensor can generate an
> > interrupt at some trigger temperature? Why would I need polling times?
> >
> > Why does this need to be in the dt at all? Surely the OS can choose some
> > sensible polling period, possibly dynamically?
>
> Well, let me answer this one with another question. How the OS will
> determine how fast is the temperature rise on a thermal zone described
> in device tree?

How will the devicetree writer determine this?

It's possible for the thermal management code to dynamically adjust the
rate between some extreme polling intervals based on how big a rise it
detects between polls or possibly something more complex taking into
account some metric for load.

>
> >
> >> +
> >> +- #thermal-cells: An integer that is used to specify how many cells compose
> >> +  sensor ids.
> >
> > I don't see why this is necessary. If the zone itself described its
> > related sensors rather than the other way around, we wouldn't need it at
> > all. Most bindings so far have consumers link to their providers rather
> > than the other way around.
> >
>
> I see.
>
>
> >> +
> >> +Below is an example:
> >> +cpu_thermal: thermal_zone {
> >> +            #thermal-cells = <1>;
> >> +            mask = <0x03>; /* trips writability */
> >> +            passive_delay = <250>; /* milliseconds */
> >> +            polling_delay = <1000>; /* milliseconds */
> >> +            trips {
> >> +                    alert@100000{
> >> +                            temperature = <100000>; /* milliCelsius */
> >> +                            hysteresis = <0>; /* milliCelsius */
> >> +                            type = <THERMAL_TRIP_PASSIVE>;
> >> +                    };
> >> +                    crit@125000{
> >> +                            temperature = <125000>; /* milliCelsius */
> >> +                            hysteresis = <0>; /* milliCelsius */
> >> +                            type = <THERMAL_TRIP_CRITICAL>;
> >> +                    };

I didn't spot this on my first round, but the trips node will need
#address-cells and #size-cells, and the sub nodes unit-addresses should
match their reg properties.

> >> +            };
> >> +            bind_params {
> >> +                    action@0{
> >> +                            cooling_device = "thermal-cpufreq";
> >
> > NAK. That value was not defined anywhere, and represents Linux
> > infrastructure rather than hardware.
> >
>
> Yes, this was another leak as discussed above in the upper part of the
> doc file.
>
> > For this case, we could just as easily describe the thermal points, and
> > if no physical cooling device (e.g. a fan) is present, assume
> > cpufreq-base cooling.  Other OSs could choose to do otherwise, and we
> > could change later...
> >
>
> The way other specifications do (aka ACPI) is to have trip types. In
> case a trip type is passive cooling, it means one is supposed to
> modulate the dissipated power rather than activating a device to remove
> heat (active cooling).
>
> The part of 'assuming' things that bothers me. I would rather have a way
> to really say one wants to have passive cooling at a specific trip point.

I don't see the problem here. If you don't specify a device, your only
options will be some sort of passive management.

>
>
> >> +                            weight = <100>; /* percentage */
> >> +                            mask = <0x01>;
> >
> > This should presumably be trip-mask (assuming my suggested corrections).
> >
> > What is it supposed to mean here?
>
> As stated above, it means the trip points that this binding represents.

If you have more than 32 trip points (which is admittedly unlikely), how
do you represent them? I'm not sure a mask is the best representation
here, as it's difficult for a human to match up with a list of entries.

Additionally, the trip points don't have a logical contiguous numbering
from zero, so how do the bits in the mask correspond to entries in the
list? This seems to rely on the order that the subnodes are in, which
AFAIK is not guaranteed. It would be far nicer to have an explicit
linkage.

>
> >
> >> +                           limits = <
> >> +                             /* lower-state            upper-state */
> >> +                               1                       THERMAL_NO_LIMITS
> >> +                               THERMAL_NO_LIMITS       THERMAL_NO_LIMITS
> >> +                           >;
> >> +                    };
> >> +            };
> >> +};
> >> +
> >> +sensor: adc@0xFFFF {
> >> +       ...
> >> +       monitored-zones = <&cpu_thermal 0>;
> >> +};
> >> +
> >> +cpu@0 {
> >> +       ...
> >> +       cooling-zones = <&cpu_thermal>;
> >> +};
> >> +
> >> +In the example above, the ADC sensor at address 0xFFFF is used to monitor
> >> +the zone 'cpu_thermal' using its the sensor 0. The cpu@0 device is also linked
> >> +to the same thermal zone 'cpu_thermal' as a cooling device.
> >
> > Huh? That seems to imply the the '0' in '<&cpu_thermal 0>' on the sensor
> > node describes a property of the sensor rather than the thermal node,
> > unless I've misunderstood?
> >
>
> It is essentially which sensor id is used to monitor a specific zone. In
> case of sensor IPs that feature several internal sensors, one needs to
> have a way to describe which sensor monitors which zone. Example of this
> type of IPs: lm90 (up to 3 sensors) and TI bandgap IP (can contain up to
> 5 internal sensors). The probe happens for the IP device and not for the
> internal sensors.

Which is exactly why this should be the opposite way round, with thermal
zones referring to sensors in this fashion.

The way you're suggesting means that the phandle+cells specifier refers
half to the consumer and half to the producer. Having thermal zones
refer to sensors would make this refer solely to the producer (the
sensor).

>
>
> >> +
> >> +***************
> >> +cpufreq-cooling
> >> +***************
> >> +
> >> +The generic cpu cooling (freq clipping) can be loaded by the
> >> +generic cpufreq-cpu0 driver in case the device tree node informs
> >> +this need.
> >> +
> >> +In order to load the cpufreq cooling device, it is possible to
> >> +inform that the cpu needs cooling by adding the list of thermal zones
> >> +in the 'cooling-zones' property at the cpu0 phandle.
> >
> > This should be reworded so as to describe the binding rather than the
> > Linux behaviour based on the binding.
>
> OK.
>
> >
> >> +
> >> +Example:
> >> +       cpus {
> >> +               cpu@0 {
> >> +                       operating-points = <
> >> +                               /* kHz    uV */
> >> +                               800000  1313000
> >> +                               1008000 1375000
> >> +                       >;
> >> +                       cooling-zones = <&cpu_thermal>;
> >> +               };
> >> +       ...
> >> +       };
> >> +
> >> +The above will cause the cpufreq-cpu0 driver to understand that
> >> +the cpu will need passive cooling and while probing that node it will
> >> +also load the cpufreq cpu cooling device in that system.
> >
> > The above describe that the CPU is part of a cooling (thermal?) zone and
> > requires cooling.
>
> That says the cpu participates in a thermal zone as a cooling
> device/mechanism, thus cpu cooling (passive cooling) is required in
> target system.

I think you need the rest of the nodes in this example. You don't show
whether or not there's a cooling-device, so it's not clear that the CPU
is required to be passively cooled...

>
> >
> >> +
> >> +However, be advised that this flag will not describe what needs to
> >> +be done or how the cpufreq cooling device will be used. In order to
> >> +accomplish this, one needs to write a phandle for a thermal zone, as
> >> +described in the section 'thermal_zone'.
> >
> > The above already has a phandle to a thermal (cooling?) zone.
> >
> > Please choose either cooling zone or thermal zone, having the two names
> > makes this more confusing than necessary.
>
> I see. Idea is to have thermal zone as a node. cooling-zone is just a
> list of thermal zones that the referred device will be used as cooling
> device.

While I can see a distinction, the nomenclature is horrendously
confusing.

>
> >
> >> diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
> >> index 7fb16bc..753f0dc 100644
> >> --- a/drivers/thermal/Kconfig
> >> +++ b/drivers/thermal/Kconfig
> >> @@ -29,6 +29,19 @@ config THERMAL_HWMON
> >>           Say 'Y' here if you want all thermal sensors to
> >>           have hwmon sysfs interface too.
> >>
> >> +config THERMAL_OF
> >> +       bool
> >> +       prompt "APIs to parse thermal data out of device tree"
> >> +       depends on OF
> >> +       default y
> >> +       help
> >> +         This options provides helpers to add the support to
> >> +         read and parse thermal data definitions out of the
> >> +         device tree blob.
> >> +
> >> +         Say 'Y' here if you need to build thermal infrastructure
> >> +         based on device tree.
> >> +
> >>  choice
> >>         prompt "Default Thermal governor"
> >>         default THERMAL_DEFAULT_GOV_STEP_WISE
> >> diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
> >> index 24cb894..eedb273 100644
> >> --- a/drivers/thermal/Makefile
> >> +++ b/drivers/thermal/Makefile
> >> @@ -7,6 +7,7 @@ thermal_sys-y                   += thermal_core.o
> >>
> >>  # interface to/from other layers providing sensors
> >>  thermal_sys-$(CONFIG_THERMAL_HWMON)            += thermal_hwmon.o
> >> +thermal_sys-$(CONFIG_THERMAL_OF)               += thermal_dt.o
> >>
> >>  # governors
> >>  thermal_sys-$(CONFIG_THERMAL_GOV_FAIR_SHARE)   += fair_share.o
> >> diff --git a/drivers/thermal/thermal_dt.c b/drivers/thermal/thermal_dt.c
> >> new file mode 100644
> >> index 0000000..cc35485
> >> --- /dev/null
> >> +++ b/drivers/thermal/thermal_dt.c
> >> @@ -0,0 +1,473 @@
> >> +/*
> >> + *  thermal_dt.c - Generic Thermal Management device tree support.
> >> + *
> >> + *  Copyright (C) 2013 Texas Instruments
> >> + *  Copyright (C) 2013 Eduardo Valentin <eduardo.valentin@ti.com>
> >> + *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> >> + *
> >> + *  This program is free software; you can redistribute it and/or modify
> >> + *  it under the terms of the GNU General Public License as published by
> >> + *  the Free Software Foundation; version 2 of the License.
> >> + *
> >> + *  This program is distributed in the hope that it will be useful, but
> >> + *  WITHOUT ANY WARRANTY; without even the implied warranty of
> >> + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> >> + *  General Public License for more details.
> >> + *
> >> + *  You should have received a copy of the GNU General Public License along
> >> + *  with this program; if not, write to the Free Software Foundation, Inc.,
> >> + *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
> >> + *
> >> + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> >> + */
> >> +#include <linux/thermal.h>
> >> +#include <linux/slab.h>
> >> +#include <linux/types.h>
> >> +#include <linux/of_device.h>
> >> +#include <linux/of_platform.h>
> >> +#include <linux/err.h>
> >> +#include <linux/export.h>
> >> +#include <linux/string.h>
> >> +
> >> +struct __thermal_bind_params {
> >> +       char cooling_device[THERMAL_NAME_LENGTH];
> >> +};
> >> +
> >> +static
> >> +int thermal_of_match(struct thermal_zone_device *tz,
> >> +                    struct thermal_cooling_device *cdev);
> >> +
> >> +static int thermal_of_populate_bind_params(struct device *dev,
> >> +                                          struct device_node *node,
> >> +                                          struct __thermal_bind_params *__tbp,
> >> +                                          struct thermal_bind_params *tbp,
> >> +                                          int ntrips)
> >> +{
> >> +       const char *cdev_name;
> >> +       u32 *limits;
> >> +       int ret;
> >> +       u32 prop;
> >> +
> >> +       ret = of_property_read_u32(node, "weight", &prop);
> >> +       if (ret < 0) {
> >> +               dev_err(dev, "missing weight property\n");
> >> +               return ret;
> >> +       }
> >> +       tbp->weight = prop;
> >> +
> >> +       ret = of_property_read_u32(node, "mask", &prop);
> >> +       if (ret < 0) {
> >> +               dev_err(dev, "missing mask property\n");
> >> +               return ret;
> >> +       }
> >> +       tbp->trip_mask = prop;
> >> +
> >> +       /* this will allow us to bind with cooling devices */
> >> +       tbp->match = thermal_of_match;
> >> +
> >> +       ret = of_property_read_string(node, "cooling_device", &cdev_name);
> >> +       if (ret < 0) {
> >> +               dev_err(dev, "missing cooling_device property\n");
> >> +               return ret;
> >> +       }
> >> +       strncpy(__tbp->cooling_device, cdev_name,
> >> +               sizeof(__tbp->cooling_device));
> >> +
> >> +       limits = kzalloc(ntrips * sizeof(*limits) * 2, GFP_KERNEL);
> >
> > Why do you use kzalloc here, but devm_kzalloc elsewhere? That'll lead to
> > problems as the driver gets refactored over time.
>
> Because this memory is used only  within this function and thus released
> at the bottom of it.
>
> >
> >> +       if (!limits) {
> >> +               dev_err(dev, "not enough mem for reading limits\n");
> >> +               return -ENOMEM;
> >> +       }
> >> +       ret = of_property_read_u32_array(node, "limits", limits, 2 * ntrips);
> >> +       if (!ret) {
> >> +               int i = ntrips;
> >> +
> >> +               tbp->binding_limits = devm_kzalloc(dev,
> >> +                                                  ntrips * 2 *
> >> +                                                  sizeof(*tbp->binding_limits),
> >> +                                                  GFP_KERNEL);
> >> +               if (!tbp->binding_limits) {
> >> +                       dev_err(dev, "not enough mem for storing limits\n");
> >> +                       return -ENOMEM;
> >> +               }
> >> +               while (i--)
> >> +                       tbp->binding_limits[i] = limits[i];
> >> +       }
> >> +       kfree(limits);
>
> here.

I saw that, I did say that this may lead to problems in future if the
function's reorganised, not now. :)

>
> >> +
> >> +       return 0;
> >
> > What if you failed to read the array? Surely you should return an error?
>
> Attempting to make this property not mandatory.

That wasn't clear from the binding, and now I've re-read it, I'm still
not entirely clear on what the limits represent, and why you may have
multiple sets of pairs.

>
> >
> >> +}
> >> +
> >> +struct __thermal_trip {
> >> +       unsigned long int temperature;
> >> +       unsigned long int hysteresis;
> >> +       enum thermal_trip_type type;
> >> +};
> >> +
> >> +static
> >> +int thermal_of_populate_trip(struct device *dev,
> >> +                            struct device_node *node,
> >> +                            struct __thermal_trip *trip)
> >> +{
> >> +       int ret;
> >> +       int prop;
> >> +
> >> +       ret = of_property_read_u32(node, "temperature", &prop);
> >> +       if (ret < 0) {
> >> +               dev_err(dev, "missing temperature property\n");
> >> +               return ret;
> >> +       }
> >> +       trip->temperature = prop;
> >> +
> >> +       ret = of_property_read_u32(node, "hysteresis", &prop);
> >> +       if (ret < 0) {
> >> +               dev_err(dev, "missing hysteresis property\n");
> >> +               return ret;
> >> +       }
> >> +       trip->hysteresis = prop;
> >> +
> >> +       ret = of_property_read_u32(node, "type", &prop);
> >> +       if (ret < 0) {
> >> +               dev_err(dev, "missing type property\n");
> >> +               return ret;
> >> +       }
> >> +       trip->type = prop;
> >
> > This will require sanity checking.
>
> OK.
>
> >
> >> +
> >> +       return 0;
> >> +}
> >> +
> >> +struct __thermal_zone_device {
> >> +       enum thermal_device_mode mode;
> >> +       int passive_delay;
> >> +       int polling_delay;
> >> +       int mask;
> >> +       int ntrips;
> >> +       char type[THERMAL_NAME_LENGTH];
> >> +       struct __thermal_trip *trips;
> >> +       struct __thermal_bind_params *bind_params;
> >> +       struct thermal_bind_params *tbps;
> >> +       struct thermal_zone_params zone_params;
> >> +       int (*get_temp)(void *, unsigned long *);
> >> +       void *devdata;
> >> +};
> >> +
> >> +static struct __thermal_zone_device *
> >> +thermal_of_build_thermal_zone(struct device *dev, struct device_node *node)
> >> +{
> >> +       struct device_node *child, *gchild;
> >> +       struct __thermal_zone_device *tz;
> >> +       int ret, i;
> >> +       u32 prop;
> >> +
> >> +       if (!node) {
> >> +               dev_err(dev, "no thermal zone node\n");
> >> +               return ERR_PTR(-EINVAL);
> >> +       }
> >> +
> >> +       tz = devm_kzalloc(dev, sizeof(*tz), GFP_KERNEL);
> >> +       if (!tz) {
> >> +               dev_err(dev, "not enough memory for thermal of zone\n");
> >> +               return ERR_PTR(-ENOMEM);
> >> +       }
> >> +
> >> +       ret = of_property_read_u32(node, "passive_delay", &prop);
> >> +       if (ret < 0) {
> >> +               dev_err(dev, "missing passive_delay property\n");
> >> +               return ERR_PTR(ret);
> >> +       }
> >> +       tz->passive_delay = prop;
> >> +
> >> +       ret = of_property_read_u32(node, "polling_delay", &prop);
> >> +       if (ret < 0) {
> >> +               dev_err(dev, "missing polling_delay property\n");
> >> +               return ERR_PTR(ret);
> >> +       }
> >> +       tz->polling_delay = prop;
> >> +
> >> +       ret = of_property_read_u32(node, "mask", &prop);
> >> +       if (ret < 0) {
> >> +               dev_err(dev, "missing mask property\n");
> >> +               return ERR_PTR(ret);
> >> +       }
> >> +       tz->mask = prop;
> >> +
> >> +       /* assume node name as our zone type */
> >> +       strncpy(tz->type, node->name, sizeof(tz->type));
> >> +
> >> +       /* default policy */
> >> +       strncpy(tz->zone_params.governor_name, "step_wise",
> >> +               sizeof(tz->zone_params.governor_name));
> >> +
> >> +       /* trips */
> >> +       child = of_find_node_by_name(node, "trips");
> >
> > That might not be a child node, as of_find_node_by_name walks over the
> > list of all nodes. Use of_get_child_by_name.
>
> Right! This is a bug.
>
> >
> >> +
> >> +       /* No trips provided */
> >> +       if (!child)
> >> +               goto finish;
> >> +
> >> +       tz->ntrips = of_get_child_count(child);
> >> +       tz->trips = devm_kzalloc(dev, tz->ntrips * sizeof(*tz->trips),
> >> +                                GFP_KERNEL);
> >> +       if (!tz->trips)
> >> +               return ERR_PTR(-ENOMEM);
> >> +       i = 0;
> >> +       for_each_child_of_node(child, gchild)
> >> +               thermal_of_populate_trip(dev, gchild, &tz->trips[i++]);
> >
> > What if a child node was not a valid trip node? It seems
> > thermal_of_populate_trip returns errors you're ignoring.
>
> OK. Adding proper treatment.
>
> >
> >> +
> >> +       /* bind_params */
> >> +       child = of_find_node_by_name(node, "bind_params");
> >
> > Another of_get_child_by_name candidate.
>
> OK.
>
> >
> >> +
> >> +       /* No binding info */
> >> +       if (!child)
> >> +               goto finish;
> >> +
> >> +       tz->zone_params.num_tbps = of_get_child_count(child);
> >> +       tz->bind_params = devm_kzalloc(dev,
> >> +                                      tz->zone_params.num_tbps *
> >> +                                               sizeof(*tz->bind_params),
> >> +                                      GFP_KERNEL);
> >> +       if (!tz->bind_params)
> >> +               return ERR_PTR(-ENOMEM);
> >> +       tz->zone_params.tbp = devm_kzalloc(dev,
> >> +                                          tz->zone_params.num_tbps *
> >> +                                               sizeof(*tz->zone_params.tbp),
> >> +                                          GFP_KERNEL);
> >> +       if (!tz->zone_params.tbp)
> >> +               return ERR_PTR(-ENOMEM);
> >> +       i = 0;
> >> +       for_each_child_of_node(child, gchild) {
> >> +               thermal_of_populate_bind_params(dev, gchild,
> >> +                                               &tz->bind_params[i],
> >> +                                               &tz->zone_params.tbp[i],
> >> +                                               tz->ntrips);
> >
> > Similarly, you're ignoring error conditions here. What if a bind_params
> > node was malformed?
>
>
> Adding proper error handling.
>
> >
> >> +               i++;
> >> +       }
> >> +
> >> +finish:
> >> +       tz->mode = THERMAL_DEVICE_ENABLED;
> >> +
> >> +       return tz;
> >> +}
> >> +
> >> +static
> >> +int thermal_of_match(struct thermal_zone_device *tz,
> >> +                    struct thermal_cooling_device *cdev)
> >> +{
> >> +       struct __thermal_zone_device *data = tz->devdata;
> >> +       int i;
> >> +
> >> +       for (i = 0; i < data->zone_params.num_tbps; i++) {
> >> +               if (!strncmp(data->bind_params[i].cooling_device,
> >> +                            cdev->type,
> >> +                            strlen(data->bind_params[i].cooling_device)) &&
> >> +                   (data->zone_params.tbp[i].trip_mask & (1 << i)))
> >> +                       return 0;
> >> +       }
> >> +
> >> +       return -EINVAL;
> >> +}
> >
> > I'm not keen on binding to cooling devices using a string, as suddenly a
> > name to allow humans to inspect the system is turned into an ABI.
>
> OK. We need to align on how we describe the binding then.

Definitely. We need to ensure that we fully define the relationship too
cooling devices, and don't suddenly expose some piece of internal Linux
infrastructure to the world.

>
> >
> >> +
> >> +static
> >> +int of_thermal_get_temp(struct thermal_zone_device *tz,
> >> +                       unsigned long *temp)
> >> +{
> >> +       struct __thermal_zone_device *data = tz->devdata;
> >> +
> >> +       return data->get_temp(data->devdata, temp);
> >> +}
> >> +
> >> +static
> >> +int of_thermal_get_mode(struct thermal_zone_device *tz,
> >> +                       enum thermal_device_mode *mode)
> >> +{
> >> +       struct __thermal_zone_device *data = tz->devdata;
> >> +
> >> +       *mode = data->mode;
> >> +
> >> +       return 0;
> >> +}
> >> +
> >> +static
> >> +int of_thermal_set_mode(struct thermal_zone_device *tz,
> >> +                       enum thermal_device_mode mode)
> >> +{
> >> +       struct __thermal_zone_device *data = tz->devdata;
> >> +
> >> +       mutex_lock(&tz->lock);
> >> +
> >> +       if (mode == THERMAL_DEVICE_ENABLED)
> >> +               tz->polling_delay = data->polling_delay;
> >> +       else
> >> +               tz->polling_delay = 0;
> >> +
> >> +       mutex_unlock(&tz->lock);
> >> +
> >> +       data->mode = mode;
> >> +       thermal_zone_device_update(tz);
> >> +
> >> +       return 0;
> >> +}
> >> +
> >> +static
> >> +int of_thermal_get_trip_type(struct thermal_zone_device *tz, int trip,
> >> +                            enum thermal_trip_type *type)
> >> +{
> >> +       struct __thermal_zone_device *data = tz->devdata;
> >> +
> >> +       if (trip >= data->ntrips || trip < 0)
> >> +               return -EDOM;
> >
> > It's far more common to use -EINVAL.
>
> hmm.. OK.
>
> >
> >> +
> >> +       *type = data->trips[trip].type;
> >> +
> >> +       return 0;
> >> +}
> >> +
> >> +static
> >> +int of_thermal_get_trip_temp(struct thermal_zone_device *tz, int trip,
> >> +                            unsigned long *temp)
> >> +{
> >> +       struct __thermal_zone_device *data = tz->devdata;
> >> +
> >> +       if (trip >= data->ntrips || trip < 0)
> >> +               return -EDOM;
> >> +
> >> +       *temp = data->trips[trip].temperature;
> >> +
> >> +       return 0;
> >> +}
> >> +
> >> +static
> >> +int of_thermal_set_trip_temp(struct thermal_zone_device *tz, int trip,
> >> +                            unsigned long temp)
> >> +{
> >> +       struct __thermal_zone_device *data = tz->devdata;
> >> +
> >> +       if (trip >= data->ntrips || trip < 0)
> >> +               return -EDOM;
> >> +
> >> +       /* thermal fw should take care of data->mask & (1 << trip) */
> >> +       data->trips[trip].temperature = temp;
> >> +
> >> +       return 0;
> >> +}
> >> +
> >> +static
> >> +int of_thermal_get_trip_hyst(struct thermal_zone_device *tz, int trip,
> >> +                            unsigned long *hyst)
> >> +{
> >> +       struct __thermal_zone_device *data = tz->devdata;
> >> +
> >> +       if (trip >= data->ntrips || trip < 0)
> >> +               return -EDOM;
> >> +
> >> +       *hyst = data->trips[trip].hysteresis;
> >> +
> >> +       return 0;
> >> +}
> >> +
> >> +static
> >> +int of_thermal_set_trip_hyst(struct thermal_zone_device *tz, int trip,
> >> +                            unsigned long hyst)
> >> +{
> >> +       struct __thermal_zone_device *data = tz->devdata;
> >> +
> >> +       if (trip >= data->ntrips || trip < 0)
> >> +               return -EDOM;
> >> +
> >> +       /* thermal fw should take care of data->mask & (1 << trip) */
> >
> > Could you elaborate on that comment?
>
> In  case the trip is not assigned to be writable, this function won't be
> called.

Ah. I misunderstood "fw" as "firmware", rather than "framework", and got
confused. It would be nice if you could expand "fw" to make this
clearer. :)

Thanks,
Mark.

[1] http://en.wikipedia.org/wiki/Black-body_radiation

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

* Re: [lm-sensors] [RFC PATCH 02/14] drivers: thermal: introduce device tree parser
@ 2013-08-27 16:23         ` Mark Rutland
  0 siblings, 0 replies; 100+ messages in thread
From: Mark Rutland @ 2013-08-27 16:23 UTC (permalink / raw)
  To: Eduardo Valentin, swarren
  Cc: Pawel Moll, ian.campbell, grant.likely, rob.herring, linux,
	rui.zhang, wni, durgadoss.r, linux-pm, devicetree, lm-sensors,
	linux-kernel

On Tue, Aug 27, 2013 at 02:44:40PM +0100, Eduardo Valentin wrote:
> Hello Mark,
>
>
> First of all, thanks for taking the time to review in such level of
> detail. Lets try to align and have a common understanding. Answers go
> inline. Please let me know if I missed something or if I made it more
> confusing :-)
>
> On 27-08-2013 06:22, Mark Rutland wrote:
> > Hi,
> >
> > On Sat, Aug 24, 2013 at 12:15:43AM +0100, Eduardo Valentin wrote:
> >> In order to be able to build thermal policies
> >> based on generic sensors, like I2C device, that
> >> can be places in different points on different boards,
> >> there is a need to have a way to feed board dependent
> >> data into the thermal framework.
> >>
> >> This patch introduces a thermal data parser for device
> >> tree. The parsed data is used to build thermal zones
> >> and thermal binding parameters. The output data
> >> can then be used to deploy thermal policies.
> >>
> >> This patch adds also documentation regarding this
> >> API and how to define tree nodes to use
> >> this infrastructure.
> >>
> >> Cc: Zhang Rui <rui.zhang@intel.com>
> >> Cc: linux-pm@vger.kernel.org
> >> Cc: linux-kernel@vger.kernel.org
> >> Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
> >> ---
> >>  .../devicetree/bindings/thermal/thermal.txt        | 160 +++++++
> >>  drivers/thermal/Kconfig                            |  13 +
> >>  drivers/thermal/Makefile                           |   1 +
> >>  drivers/thermal/thermal_dt.c                       | 473 +++++++++++++++++++++
> >>  include/dt-bindings/thermal/thermal.h              |  27 ++
> >>  include/linux/thermal.h                            |   3 +
> >>  6 files changed, 677 insertions(+)
> >>  create mode 100644 Documentation/devicetree/bindings/thermal/thermal.txt
> >>  create mode 100644 drivers/thermal/thermal_dt.c
> >>  create mode 100644 include/dt-bindings/thermal/thermal.h
> >>
>
>
> General question on device tree documentation. Assuming there is such an
> effort to make it Linux independent, is there other places out of Linux
> tree that these binding must be documented?

At present, no. There is a plan to move the documentation out of the
kernel, but I'm not sure on how that's currently progressing. Some
general cleanup needs to occur before we can actually do that.

>
>
> >> diff --git a/Documentation/devicetree/bindings/thermal/thermal.txt b/Documentation/devicetree/bindings/thermal/thermal.txt
> >> new file mode 100644
> >> index 0000000..af20ab0
> >> --- /dev/null
> >> +++ b/Documentation/devicetree/bindings/thermal/thermal.txt
> >> @@ -0,0 +1,160 @@
> >> +----------------------------------------
> >> +Thermal Framework Device Tree descriptor
> >> +----------------------------------------
> >> +
> >> +This file describes how to define a thermal structure using device tree.
> >> +A thermal structure includes thermal zones and their components, such
> >> +as name, trip points, polling intervals and cooling devices binding
> >> +descriptors. A binding descriptor may contain information on how to
> >> +react, with a cooling stepped action or a weight on a fair share.
> >> +The target of device tree thermal descriptors is to describe only
> >> +the hardware thermal aspects, not how the system must control or which
> >> +algorithm or policy must take place. It follows a description of each
> >> +type of device tree node.
> >> +
> >> +****
> >> +trip
> >> +****
> >> +
> >> +The trip node is a node to describe a point in the temperature domain
> >> +in which the system takes an action. This node describes just the point,
> >> +not the action.
> >> +
> >> +A node describing a trip must contain:
> >> +- temperature: the trip temperature level, in milliCelsius.
> >> +- hysteresis: a (low) hysteresis value on 'temperature'. This is a relative
> >> +value, in milliCelsius.
> >
> > Presumably this is a single (u32) cell?
>
> Yes, both of them above are a single u32.

Ok. This seems to be the default assumption in many bindings, so I
shan't argue against it here, but in general we should be as precise as
possible as to the format of the devicetree.

>
> >
> >> +- type: the trip type. Here is the type mapping:
> >> +       THERMAL_TRIP_ACTIVE
> >> +       THERMAL_TRIP_PASSIVE
> >> +       THERMAL_TRIP_HOT
> >> +       THERMAL_TRIP_CRITICAL
> >
> > What type is this property?
> >
> > What are these values? Do you need to refer to a header somewhere?
>
> There is a header, introduced in this patch.
> include/dt-bindings/thermal/thermal.h
>
> > Symbolic constants should have an associated value for an ABI.
>
> OK. Sounds reasonable to me. Shall we be descriptive and enlist the
> values in this doc too or just pointing to header is fine?

I believe that referring to the header is fine, though personally I'd
prefer if we were explicit in binding docs. I'll leave Stephen to
comment on what the preferred way of handling header constants with
binding documents is.

>
> >
> >> +
> >> +**********
> >> +bind_param
> >> +**********
> >> +
> >> +The bind_param node is a node to describe how cooling devices get assigned
> >> +to trip points of the zone. The cooling devices are expected to be loaded
> >> +in the target system.
> >> +
> >> +A node describing a bind_param must contain:
> >> +- cooling_device: A string with the cooling device name.
> >
> > Please use '-' rather than '_' in bindings. That's the normal devicetree
> > convention, and there's no point gonig against it and causing more
> > confusion.
>
> Agreed.
>
> >
> > What are valid values of this string, and what do they mean?
>
> These are the name of the cooling devices to match to.

Which are what exactly? What constitutes a "cooling device"?

Is "black-body radiation" [1] a valid cooling device?

How about "copper heat sink"?

>
> >
> > Why not a phandle + cells binding to cooling devices?
> >
>
> Yeah, this could work too. I am going to check how that would look like
> and come back to you.

Ok.

>
> >> +- weight: The 'influence' of a particular cooling device on this zone.
> >> +             This is on a percentage scale. The sum of all these weights
> >> +             (for a particular zone) cannot exceed 100.
> >
> > This is a bit fuzzy, and certainly needs more guidance.
>
> OK. This property is used to describe the amount of cooling contribution
> when activating a cooling device at a certain trip point. I will work on
> a better guidance.
>
> >
> >> +- trip_mask: This is a bit mask that gives the binding relation between
> >> +               this thermal zone and cdev, for a particular trip point.
> >> +               If nth bit is set, then the cdev and thermal zone are bound
> >> +               for trip point n.
> >
> > What type is this?
> >
> > The nth bit from which end?
> >
> > Could you explain what "bound for trip point n" means?
> >
>
> It is just a way to match a cooling device with a set of trip points.
> Say you want to match one specific cooling device with trips 0 and 1,
> you would then create a bind_param with trip_mask = 0x3.
>
> > Just because this is a bitmask in Linux does not mean it needs to be so
> > in the dt.
>
> Indeed.
>
> In case we work with phandle + cell binging parameters, the trip and
> weight could be passed as params.
>
>       cooling-devices = <&devX tripY weightZ>, <... >;

Something like that could certainly work.

>
> >
> >> +- limits: An array integers consisting of 2-tuples items, and each item means
> >> +  lower and upper state limits, like <min-state max-state>.
> >> +
> >> +**************************
> >> +temperature sensor devices
> >> +**************************
> >> +
> >> +Temperature sensor devices have to be linked to a specific thermal zone.
> >> +This is done by means of the 'monitored-zones' list.
> >> +- monitored-zones: A list of thermal zones phandles, identifying which
> >> +thermal zones the temperature sensor device is used to monitor.
> >
> > Why does this need to be described that way around?
> >
> > Can the zone not have a link to the sensor(s) it needs?
> >
>
> Do you see any issues with it?
>
> Idea is that sensor nodes would list which zones they are used.  Same
> idea goes to cooling devices. It can be the other way around, yes. It
> depends on what is the best way to describe these relations. Idea would
> be so that sensors and cooling devices would be composing a thermal zone.

I think that having a zone refer to the sensors that monitor it would be
preferable. Otherwise we're encoding that way a devices output is to be
consumed on the binding for the device itself, which feels odd (it's
arguable as to whether it's a property of the device, however).

>
> >> +
> >> +************
> >> +thermal_zone
> >> +************
> >> +
> >> +The thermal_zone node is the node containing all the required info
> >> +for describing a thermal zone, including its cdev bindings. The thermal_zone
> >> +node must contain, apart from its own properties, one node containing
> >> +trip nodes and one node containing all the zone bind parameters.
> >> +
> >> +Required properties:
> >> +- mask: Bit string: If 'n'th bit is set, then trip point 'n' is writeable.
> >
> > What type is a bit string in devicetree? I'm aware of cells and (byte)
> > strings, but not bit strings.
> >
> > What does 'writeable' mean in this context?
> >
> > There's presumably a better name than 'mask'.
> >
>
> This is used to describe if trip points are writeable under sysfs. I
> think this is a OS implementation leak. I will be removing this from
> device tree and making them RO by default.

Ok.

>
> >> +
> >> +- passive_delay: number of milliseconds to wait between polls when
> >> +  performing passive cooling.
> >> +
> >> +- polling_delay: number of milliseconds to wait between polls when checking.
> >
> > These sound very much like configuration of the driver rather than
> > hardware description. What if my temperature sensor can generate an
> > interrupt at some trigger temperature? Why would I need polling times?
> >
> > Why does this need to be in the dt at all? Surely the OS can choose some
> > sensible polling period, possibly dynamically?
>
> Well, let me answer this one with another question. How the OS will
> determine how fast is the temperature rise on a thermal zone described
> in device tree?

How will the devicetree writer determine this?

It's possible for the thermal management code to dynamically adjust the
rate between some extreme polling intervals based on how big a rise it
detects between polls or possibly something more complex taking into
account some metric for load.

>
> >
> >> +
> >> +- #thermal-cells: An integer that is used to specify how many cells compose
> >> +  sensor ids.
> >
> > I don't see why this is necessary. If the zone itself described its
> > related sensors rather than the other way around, we wouldn't need it at
> > all. Most bindings so far have consumers link to their providers rather
> > than the other way around.
> >
>
> I see.
>
>
> >> +
> >> +Below is an example:
> >> +cpu_thermal: thermal_zone {
> >> +            #thermal-cells = <1>;
> >> +            mask = <0x03>; /* trips writability */
> >> +            passive_delay = <250>; /* milliseconds */
> >> +            polling_delay = <1000>; /* milliseconds */
> >> +            trips {
> >> +                    alert@100000{
> >> +                            temperature = <100000>; /* milliCelsius */
> >> +                            hysteresis = <0>; /* milliCelsius */
> >> +                            type = <THERMAL_TRIP_PASSIVE>;
> >> +                    };
> >> +                    crit@125000{
> >> +                            temperature = <125000>; /* milliCelsius */
> >> +                            hysteresis = <0>; /* milliCelsius */
> >> +                            type = <THERMAL_TRIP_CRITICAL>;
> >> +                    };

I didn't spot this on my first round, but the trips node will need
#address-cells and #size-cells, and the sub nodes unit-addresses should
match their reg properties.

> >> +            };
> >> +            bind_params {
> >> +                    action@0{
> >> +                            cooling_device = "thermal-cpufreq";
> >
> > NAK. That value was not defined anywhere, and represents Linux
> > infrastructure rather than hardware.
> >
>
> Yes, this was another leak as discussed above in the upper part of the
> doc file.
>
> > For this case, we could just as easily describe the thermal points, and
> > if no physical cooling device (e.g. a fan) is present, assume
> > cpufreq-base cooling.  Other OSs could choose to do otherwise, and we
> > could change later...
> >
>
> The way other specifications do (aka ACPI) is to have trip types. In
> case a trip type is passive cooling, it means one is supposed to
> modulate the dissipated power rather than activating a device to remove
> heat (active cooling).
>
> The part of 'assuming' things that bothers me. I would rather have a way
> to really say one wants to have passive cooling at a specific trip point.

I don't see the problem here. If you don't specify a device, your only
options will be some sort of passive management.

>
>
> >> +                            weight = <100>; /* percentage */
> >> +                            mask = <0x01>;
> >
> > This should presumably be trip-mask (assuming my suggested corrections).
> >
> > What is it supposed to mean here?
>
> As stated above, it means the trip points that this binding represents.

If you have more than 32 trip points (which is admittedly unlikely), how
do you represent them? I'm not sure a mask is the best representation
here, as it's difficult for a human to match up with a list of entries.

Additionally, the trip points don't have a logical contiguous numbering
from zero, so how do the bits in the mask correspond to entries in the
list? This seems to rely on the order that the subnodes are in, which
AFAIK is not guaranteed. It would be far nicer to have an explicit
linkage.

>
> >
> >> +                           limits = <
> >> +                             /* lower-state            upper-state */
> >> +                               1                       THERMAL_NO_LIMITS
> >> +                               THERMAL_NO_LIMITS       THERMAL_NO_LIMITS
> >> +                           >;
> >> +                    };
> >> +            };
> >> +};
> >> +
> >> +sensor: adc@0xFFFF {
> >> +       ...
> >> +       monitored-zones = <&cpu_thermal 0>;
> >> +};
> >> +
> >> +cpu@0 {
> >> +       ...
> >> +       cooling-zones = <&cpu_thermal>;
> >> +};
> >> +
> >> +In the example above, the ADC sensor at address 0xFFFF is used to monitor
> >> +the zone 'cpu_thermal' using its the sensor 0. The cpu@0 device is also linked
> >> +to the same thermal zone 'cpu_thermal' as a cooling device.
> >
> > Huh? That seems to imply the the '0' in '<&cpu_thermal 0>' on the sensor
> > node describes a property of the sensor rather than the thermal node,
> > unless I've misunderstood?
> >
>
> It is essentially which sensor id is used to monitor a specific zone. In
> case of sensor IPs that feature several internal sensors, one needs to
> have a way to describe which sensor monitors which zone. Example of this
> type of IPs: lm90 (up to 3 sensors) and TI bandgap IP (can contain up to
> 5 internal sensors). The probe happens for the IP device and not for the
> internal sensors.

Which is exactly why this should be the opposite way round, with thermal
zones referring to sensors in this fashion.

The way you're suggesting means that the phandle+cells specifier refers
half to the consumer and half to the producer. Having thermal zones
refer to sensors would make this refer solely to the producer (the
sensor).

>
>
> >> +
> >> +***************
> >> +cpufreq-cooling
> >> +***************
> >> +
> >> +The generic cpu cooling (freq clipping) can be loaded by the
> >> +generic cpufreq-cpu0 driver in case the device tree node informs
> >> +this need.
> >> +
> >> +In order to load the cpufreq cooling device, it is possible to
> >> +inform that the cpu needs cooling by adding the list of thermal zones
> >> +in the 'cooling-zones' property at the cpu0 phandle.
> >
> > This should be reworded so as to describe the binding rather than the
> > Linux behaviour based on the binding.
>
> OK.
>
> >
> >> +
> >> +Example:
> >> +       cpus {
> >> +               cpu@0 {
> >> +                       operating-points = <
> >> +                               /* kHz    uV */
> >> +                               800000  1313000
> >> +                               1008000 1375000
> >> +                       >;
> >> +                       cooling-zones = <&cpu_thermal>;
> >> +               };
> >> +       ...
> >> +       };
> >> +
> >> +The above will cause the cpufreq-cpu0 driver to understand that
> >> +the cpu will need passive cooling and while probing that node it will
> >> +also load the cpufreq cpu cooling device in that system.
> >
> > The above describe that the CPU is part of a cooling (thermal?) zone and
> > requires cooling.
>
> That says the cpu participates in a thermal zone as a cooling
> device/mechanism, thus cpu cooling (passive cooling) is required in
> target system.

I think you need the rest of the nodes in this example. You don't show
whether or not there's a cooling-device, so it's not clear that the CPU
is required to be passively cooled...

>
> >
> >> +
> >> +However, be advised that this flag will not describe what needs to
> >> +be done or how the cpufreq cooling device will be used. In order to
> >> +accomplish this, one needs to write a phandle for a thermal zone, as
> >> +described in the section 'thermal_zone'.
> >
> > The above already has a phandle to a thermal (cooling?) zone.
> >
> > Please choose either cooling zone or thermal zone, having the two names
> > makes this more confusing than necessary.
>
> I see. Idea is to have thermal zone as a node. cooling-zone is just a
> list of thermal zones that the referred device will be used as cooling
> device.

While I can see a distinction, the nomenclature is horrendously
confusing.

>
> >
> >> diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
> >> index 7fb16bc..753f0dc 100644
> >> --- a/drivers/thermal/Kconfig
> >> +++ b/drivers/thermal/Kconfig
> >> @@ -29,6 +29,19 @@ config THERMAL_HWMON
> >>           Say 'Y' here if you want all thermal sensors to
> >>           have hwmon sysfs interface too.
> >>
> >> +config THERMAL_OF
> >> +       bool
> >> +       prompt "APIs to parse thermal data out of device tree"
> >> +       depends on OF
> >> +       default y
> >> +       help
> >> +         This options provides helpers to add the support to
> >> +         read and parse thermal data definitions out of the
> >> +         device tree blob.
> >> +
> >> +         Say 'Y' here if you need to build thermal infrastructure
> >> +         based on device tree.
> >> +
> >>  choice
> >>         prompt "Default Thermal governor"
> >>         default THERMAL_DEFAULT_GOV_STEP_WISE
> >> diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
> >> index 24cb894..eedb273 100644
> >> --- a/drivers/thermal/Makefile
> >> +++ b/drivers/thermal/Makefile
> >> @@ -7,6 +7,7 @@ thermal_sys-y                   += thermal_core.o
> >>
> >>  # interface to/from other layers providing sensors
> >>  thermal_sys-$(CONFIG_THERMAL_HWMON)            += thermal_hwmon.o
> >> +thermal_sys-$(CONFIG_THERMAL_OF)               += thermal_dt.o
> >>
> >>  # governors
> >>  thermal_sys-$(CONFIG_THERMAL_GOV_FAIR_SHARE)   += fair_share.o
> >> diff --git a/drivers/thermal/thermal_dt.c b/drivers/thermal/thermal_dt.c
> >> new file mode 100644
> >> index 0000000..cc35485
> >> --- /dev/null
> >> +++ b/drivers/thermal/thermal_dt.c
> >> @@ -0,0 +1,473 @@
> >> +/*
> >> + *  thermal_dt.c - Generic Thermal Management device tree support.
> >> + *
> >> + *  Copyright (C) 2013 Texas Instruments
> >> + *  Copyright (C) 2013 Eduardo Valentin <eduardo.valentin@ti.com>
> >> + *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> >> + *
> >> + *  This program is free software; you can redistribute it and/or modify
> >> + *  it under the terms of the GNU General Public License as published by
> >> + *  the Free Software Foundation; version 2 of the License.
> >> + *
> >> + *  This program is distributed in the hope that it will be useful, but
> >> + *  WITHOUT ANY WARRANTY; without even the implied warranty of
> >> + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> >> + *  General Public License for more details.
> >> + *
> >> + *  You should have received a copy of the GNU General Public License along
> >> + *  with this program; if not, write to the Free Software Foundation, Inc.,
> >> + *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
> >> + *
> >> + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> >> + */
> >> +#include <linux/thermal.h>
> >> +#include <linux/slab.h>
> >> +#include <linux/types.h>
> >> +#include <linux/of_device.h>
> >> +#include <linux/of_platform.h>
> >> +#include <linux/err.h>
> >> +#include <linux/export.h>
> >> +#include <linux/string.h>
> >> +
> >> +struct __thermal_bind_params {
> >> +       char cooling_device[THERMAL_NAME_LENGTH];
> >> +};
> >> +
> >> +static
> >> +int thermal_of_match(struct thermal_zone_device *tz,
> >> +                    struct thermal_cooling_device *cdev);
> >> +
> >> +static int thermal_of_populate_bind_params(struct device *dev,
> >> +                                          struct device_node *node,
> >> +                                          struct __thermal_bind_params *__tbp,
> >> +                                          struct thermal_bind_params *tbp,
> >> +                                          int ntrips)
> >> +{
> >> +       const char *cdev_name;
> >> +       u32 *limits;
> >> +       int ret;
> >> +       u32 prop;
> >> +
> >> +       ret = of_property_read_u32(node, "weight", &prop);
> >> +       if (ret < 0) {
> >> +               dev_err(dev, "missing weight property\n");
> >> +               return ret;
> >> +       }
> >> +       tbp->weight = prop;
> >> +
> >> +       ret = of_property_read_u32(node, "mask", &prop);
> >> +       if (ret < 0) {
> >> +               dev_err(dev, "missing mask property\n");
> >> +               return ret;
> >> +       }
> >> +       tbp->trip_mask = prop;
> >> +
> >> +       /* this will allow us to bind with cooling devices */
> >> +       tbp->match = thermal_of_match;
> >> +
> >> +       ret = of_property_read_string(node, "cooling_device", &cdev_name);
> >> +       if (ret < 0) {
> >> +               dev_err(dev, "missing cooling_device property\n");
> >> +               return ret;
> >> +       }
> >> +       strncpy(__tbp->cooling_device, cdev_name,
> >> +               sizeof(__tbp->cooling_device));
> >> +
> >> +       limits = kzalloc(ntrips * sizeof(*limits) * 2, GFP_KERNEL);
> >
> > Why do you use kzalloc here, but devm_kzalloc elsewhere? That'll lead to
> > problems as the driver gets refactored over time.
>
> Because this memory is used only  within this function and thus released
> at the bottom of it.
>
> >
> >> +       if (!limits) {
> >> +               dev_err(dev, "not enough mem for reading limits\n");
> >> +               return -ENOMEM;
> >> +       }
> >> +       ret = of_property_read_u32_array(node, "limits", limits, 2 * ntrips);
> >> +       if (!ret) {
> >> +               int i = ntrips;
> >> +
> >> +               tbp->binding_limits = devm_kzalloc(dev,
> >> +                                                  ntrips * 2 *
> >> +                                                  sizeof(*tbp->binding_limits),
> >> +                                                  GFP_KERNEL);
> >> +               if (!tbp->binding_limits) {
> >> +                       dev_err(dev, "not enough mem for storing limits\n");
> >> +                       return -ENOMEM;
> >> +               }
> >> +               while (i--)
> >> +                       tbp->binding_limits[i] = limits[i];
> >> +       }
> >> +       kfree(limits);
>
> here.

I saw that, I did say that this may lead to problems in future if the
function's reorganised, not now. :)

>
> >> +
> >> +       return 0;
> >
> > What if you failed to read the array? Surely you should return an error?
>
> Attempting to make this property not mandatory.

That wasn't clear from the binding, and now I've re-read it, I'm still
not entirely clear on what the limits represent, and why you may have
multiple sets of pairs.

>
> >
> >> +}
> >> +
> >> +struct __thermal_trip {
> >> +       unsigned long int temperature;
> >> +       unsigned long int hysteresis;
> >> +       enum thermal_trip_type type;
> >> +};
> >> +
> >> +static
> >> +int thermal_of_populate_trip(struct device *dev,
> >> +                            struct device_node *node,
> >> +                            struct __thermal_trip *trip)
> >> +{
> >> +       int ret;
> >> +       int prop;
> >> +
> >> +       ret = of_property_read_u32(node, "temperature", &prop);
> >> +       if (ret < 0) {
> >> +               dev_err(dev, "missing temperature property\n");
> >> +               return ret;
> >> +       }
> >> +       trip->temperature = prop;
> >> +
> >> +       ret = of_property_read_u32(node, "hysteresis", &prop);
> >> +       if (ret < 0) {
> >> +               dev_err(dev, "missing hysteresis property\n");
> >> +               return ret;
> >> +       }
> >> +       trip->hysteresis = prop;
> >> +
> >> +       ret = of_property_read_u32(node, "type", &prop);
> >> +       if (ret < 0) {
> >> +               dev_err(dev, "missing type property\n");
> >> +               return ret;
> >> +       }
> >> +       trip->type = prop;
> >
> > This will require sanity checking.
>
> OK.
>
> >
> >> +
> >> +       return 0;
> >> +}
> >> +
> >> +struct __thermal_zone_device {
> >> +       enum thermal_device_mode mode;
> >> +       int passive_delay;
> >> +       int polling_delay;
> >> +       int mask;
> >> +       int ntrips;
> >> +       char type[THERMAL_NAME_LENGTH];
> >> +       struct __thermal_trip *trips;
> >> +       struct __thermal_bind_params *bind_params;
> >> +       struct thermal_bind_params *tbps;
> >> +       struct thermal_zone_params zone_params;
> >> +       int (*get_temp)(void *, unsigned long *);
> >> +       void *devdata;
> >> +};
> >> +
> >> +static struct __thermal_zone_device *
> >> +thermal_of_build_thermal_zone(struct device *dev, struct device_node *node)
> >> +{
> >> +       struct device_node *child, *gchild;
> >> +       struct __thermal_zone_device *tz;
> >> +       int ret, i;
> >> +       u32 prop;
> >> +
> >> +       if (!node) {
> >> +               dev_err(dev, "no thermal zone node\n");
> >> +               return ERR_PTR(-EINVAL);
> >> +       }
> >> +
> >> +       tz = devm_kzalloc(dev, sizeof(*tz), GFP_KERNEL);
> >> +       if (!tz) {
> >> +               dev_err(dev, "not enough memory for thermal of zone\n");
> >> +               return ERR_PTR(-ENOMEM);
> >> +       }
> >> +
> >> +       ret = of_property_read_u32(node, "passive_delay", &prop);
> >> +       if (ret < 0) {
> >> +               dev_err(dev, "missing passive_delay property\n");
> >> +               return ERR_PTR(ret);
> >> +       }
> >> +       tz->passive_delay = prop;
> >> +
> >> +       ret = of_property_read_u32(node, "polling_delay", &prop);
> >> +       if (ret < 0) {
> >> +               dev_err(dev, "missing polling_delay property\n");
> >> +               return ERR_PTR(ret);
> >> +       }
> >> +       tz->polling_delay = prop;
> >> +
> >> +       ret = of_property_read_u32(node, "mask", &prop);
> >> +       if (ret < 0) {
> >> +               dev_err(dev, "missing mask property\n");
> >> +               return ERR_PTR(ret);
> >> +       }
> >> +       tz->mask = prop;
> >> +
> >> +       /* assume node name as our zone type */
> >> +       strncpy(tz->type, node->name, sizeof(tz->type));
> >> +
> >> +       /* default policy */
> >> +       strncpy(tz->zone_params.governor_name, "step_wise",
> >> +               sizeof(tz->zone_params.governor_name));
> >> +
> >> +       /* trips */
> >> +       child = of_find_node_by_name(node, "trips");
> >
> > That might not be a child node, as of_find_node_by_name walks over the
> > list of all nodes. Use of_get_child_by_name.
>
> Right! This is a bug.
>
> >
> >> +
> >> +       /* No trips provided */
> >> +       if (!child)
> >> +               goto finish;
> >> +
> >> +       tz->ntrips = of_get_child_count(child);
> >> +       tz->trips = devm_kzalloc(dev, tz->ntrips * sizeof(*tz->trips),
> >> +                                GFP_KERNEL);
> >> +       if (!tz->trips)
> >> +               return ERR_PTR(-ENOMEM);
> >> +       i = 0;
> >> +       for_each_child_of_node(child, gchild)
> >> +               thermal_of_populate_trip(dev, gchild, &tz->trips[i++]);
> >
> > What if a child node was not a valid trip node? It seems
> > thermal_of_populate_trip returns errors you're ignoring.
>
> OK. Adding proper treatment.
>
> >
> >> +
> >> +       /* bind_params */
> >> +       child = of_find_node_by_name(node, "bind_params");
> >
> > Another of_get_child_by_name candidate.
>
> OK.
>
> >
> >> +
> >> +       /* No binding info */
> >> +       if (!child)
> >> +               goto finish;
> >> +
> >> +       tz->zone_params.num_tbps = of_get_child_count(child);
> >> +       tz->bind_params = devm_kzalloc(dev,
> >> +                                      tz->zone_params.num_tbps *
> >> +                                               sizeof(*tz->bind_params),
> >> +                                      GFP_KERNEL);
> >> +       if (!tz->bind_params)
> >> +               return ERR_PTR(-ENOMEM);
> >> +       tz->zone_params.tbp = devm_kzalloc(dev,
> >> +                                          tz->zone_params.num_tbps *
> >> +                                               sizeof(*tz->zone_params.tbp),
> >> +                                          GFP_KERNEL);
> >> +       if (!tz->zone_params.tbp)
> >> +               return ERR_PTR(-ENOMEM);
> >> +       i = 0;
> >> +       for_each_child_of_node(child, gchild) {
> >> +               thermal_of_populate_bind_params(dev, gchild,
> >> +                                               &tz->bind_params[i],
> >> +                                               &tz->zone_params.tbp[i],
> >> +                                               tz->ntrips);
> >
> > Similarly, you're ignoring error conditions here. What if a bind_params
> > node was malformed?
>
>
> Adding proper error handling.
>
> >
> >> +               i++;
> >> +       }
> >> +
> >> +finish:
> >> +       tz->mode = THERMAL_DEVICE_ENABLED;
> >> +
> >> +       return tz;
> >> +}
> >> +
> >> +static
> >> +int thermal_of_match(struct thermal_zone_device *tz,
> >> +                    struct thermal_cooling_device *cdev)
> >> +{
> >> +       struct __thermal_zone_device *data = tz->devdata;
> >> +       int i;
> >> +
> >> +       for (i = 0; i < data->zone_params.num_tbps; i++) {
> >> +               if (!strncmp(data->bind_params[i].cooling_device,
> >> +                            cdev->type,
> >> +                            strlen(data->bind_params[i].cooling_device)) &&
> >> +                   (data->zone_params.tbp[i].trip_mask & (1 << i)))
> >> +                       return 0;
> >> +       }
> >> +
> >> +       return -EINVAL;
> >> +}
> >
> > I'm not keen on binding to cooling devices using a string, as suddenly a
> > name to allow humans to inspect the system is turned into an ABI.
>
> OK. We need to align on how we describe the binding then.

Definitely. We need to ensure that we fully define the relationship too
cooling devices, and don't suddenly expose some piece of internal Linux
infrastructure to the world.

>
> >
> >> +
> >> +static
> >> +int of_thermal_get_temp(struct thermal_zone_device *tz,
> >> +                       unsigned long *temp)
> >> +{
> >> +       struct __thermal_zone_device *data = tz->devdata;
> >> +
> >> +       return data->get_temp(data->devdata, temp);
> >> +}
> >> +
> >> +static
> >> +int of_thermal_get_mode(struct thermal_zone_device *tz,
> >> +                       enum thermal_device_mode *mode)
> >> +{
> >> +       struct __thermal_zone_device *data = tz->devdata;
> >> +
> >> +       *mode = data->mode;
> >> +
> >> +       return 0;
> >> +}
> >> +
> >> +static
> >> +int of_thermal_set_mode(struct thermal_zone_device *tz,
> >> +                       enum thermal_device_mode mode)
> >> +{
> >> +       struct __thermal_zone_device *data = tz->devdata;
> >> +
> >> +       mutex_lock(&tz->lock);
> >> +
> >> +       if (mode = THERMAL_DEVICE_ENABLED)
> >> +               tz->polling_delay = data->polling_delay;
> >> +       else
> >> +               tz->polling_delay = 0;
> >> +
> >> +       mutex_unlock(&tz->lock);
> >> +
> >> +       data->mode = mode;
> >> +       thermal_zone_device_update(tz);
> >> +
> >> +       return 0;
> >> +}
> >> +
> >> +static
> >> +int of_thermal_get_trip_type(struct thermal_zone_device *tz, int trip,
> >> +                            enum thermal_trip_type *type)
> >> +{
> >> +       struct __thermal_zone_device *data = tz->devdata;
> >> +
> >> +       if (trip >= data->ntrips || trip < 0)
> >> +               return -EDOM;
> >
> > It's far more common to use -EINVAL.
>
> hmm.. OK.
>
> >
> >> +
> >> +       *type = data->trips[trip].type;
> >> +
> >> +       return 0;
> >> +}
> >> +
> >> +static
> >> +int of_thermal_get_trip_temp(struct thermal_zone_device *tz, int trip,
> >> +                            unsigned long *temp)
> >> +{
> >> +       struct __thermal_zone_device *data = tz->devdata;
> >> +
> >> +       if (trip >= data->ntrips || trip < 0)
> >> +               return -EDOM;
> >> +
> >> +       *temp = data->trips[trip].temperature;
> >> +
> >> +       return 0;
> >> +}
> >> +
> >> +static
> >> +int of_thermal_set_trip_temp(struct thermal_zone_device *tz, int trip,
> >> +                            unsigned long temp)
> >> +{
> >> +       struct __thermal_zone_device *data = tz->devdata;
> >> +
> >> +       if (trip >= data->ntrips || trip < 0)
> >> +               return -EDOM;
> >> +
> >> +       /* thermal fw should take care of data->mask & (1 << trip) */
> >> +       data->trips[trip].temperature = temp;
> >> +
> >> +       return 0;
> >> +}
> >> +
> >> +static
> >> +int of_thermal_get_trip_hyst(struct thermal_zone_device *tz, int trip,
> >> +                            unsigned long *hyst)
> >> +{
> >> +       struct __thermal_zone_device *data = tz->devdata;
> >> +
> >> +       if (trip >= data->ntrips || trip < 0)
> >> +               return -EDOM;
> >> +
> >> +       *hyst = data->trips[trip].hysteresis;
> >> +
> >> +       return 0;
> >> +}
> >> +
> >> +static
> >> +int of_thermal_set_trip_hyst(struct thermal_zone_device *tz, int trip,
> >> +                            unsigned long hyst)
> >> +{
> >> +       struct __thermal_zone_device *data = tz->devdata;
> >> +
> >> +       if (trip >= data->ntrips || trip < 0)
> >> +               return -EDOM;
> >> +
> >> +       /* thermal fw should take care of data->mask & (1 << trip) */
> >
> > Could you elaborate on that comment?
>
> In  case the trip is not assigned to be writable, this function won't be
> called.

Ah. I misunderstood "fw" as "firmware", rather than "framework", and got
confused. It would be nice if you could expand "fw" to make this
clearer. :)

Thanks,
Mark.

[1] http://en.wikipedia.org/wiki/Black-body_radiation

_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

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

* Re: [RFC PATCH 02/14] drivers: thermal: introduce device tree parser
  2013-08-27 16:23         ` [lm-sensors] " Mark Rutland
@ 2013-08-27 18:17           ` Eduardo Valentin
  -1 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-27 18:17 UTC (permalink / raw)
  To: Mark Rutland
  Cc: Eduardo Valentin, swarren, Pawel Moll, ian.campbell,
	grant.likely, rob.herring, linux, rui.zhang, wni, durgadoss.r,
	linux-pm, devicetree, lm-sensors, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 39359 bytes --]

On 27-08-2013 12:23, Mark Rutland wrote:
> On Tue, Aug 27, 2013 at 02:44:40PM +0100, Eduardo Valentin wrote:
>> Hello Mark,
>>
>>
>> First of all, thanks for taking the time to review in such level of
>> detail. Lets try to align and have a common understanding. Answers go
>> inline. Please let me know if I missed something or if I made it more
>> confusing :-)
>>
>> On 27-08-2013 06:22, Mark Rutland wrote:
>>> Hi,
>>>
>>> On Sat, Aug 24, 2013 at 12:15:43AM +0100, Eduardo Valentin wrote:
>>>> In order to be able to build thermal policies
>>>> based on generic sensors, like I2C device, that
>>>> can be places in different points on different boards,
>>>> there is a need to have a way to feed board dependent
>>>> data into the thermal framework.
>>>>
>>>> This patch introduces a thermal data parser for device
>>>> tree. The parsed data is used to build thermal zones
>>>> and thermal binding parameters. The output data
>>>> can then be used to deploy thermal policies.
>>>>
>>>> This patch adds also documentation regarding this
>>>> API and how to define tree nodes to use
>>>> this infrastructure.
>>>>
>>>> Cc: Zhang Rui <rui.zhang@intel.com>
>>>> Cc: linux-pm@vger.kernel.org
>>>> Cc: linux-kernel@vger.kernel.org
>>>> Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
>>>> ---
>>>>  .../devicetree/bindings/thermal/thermal.txt        | 160 +++++++
>>>>  drivers/thermal/Kconfig                            |  13 +
>>>>  drivers/thermal/Makefile                           |   1 +
>>>>  drivers/thermal/thermal_dt.c                       | 473 +++++++++++++++++++++
>>>>  include/dt-bindings/thermal/thermal.h              |  27 ++
>>>>  include/linux/thermal.h                            |   3 +
>>>>  6 files changed, 677 insertions(+)
>>>>  create mode 100644 Documentation/devicetree/bindings/thermal/thermal.txt
>>>>  create mode 100644 drivers/thermal/thermal_dt.c
>>>>  create mode 100644 include/dt-bindings/thermal/thermal.h
>>>>
>>
>>
>> General question on device tree documentation. Assuming there is such an
>> effort to make it Linux independent, is there other places out of Linux
>> tree that these binding must be documented?
> 
> At present, no. There is a plan to move the documentation out of the
> kernel, but I'm not sure on how that's currently progressing. Some
> general cleanup needs to occur before we can actually do that.
> 

OK.

>>
>>
>>>> diff --git a/Documentation/devicetree/bindings/thermal/thermal.txt b/Documentation/devicetree/bindings/thermal/thermal.txt
>>>> new file mode 100644
>>>> index 0000000..af20ab0
>>>> --- /dev/null
>>>> +++ b/Documentation/devicetree/bindings/thermal/thermal.txt
>>>> @@ -0,0 +1,160 @@
>>>> +----------------------------------------
>>>> +Thermal Framework Device Tree descriptor
>>>> +----------------------------------------
>>>> +
>>>> +This file describes how to define a thermal structure using device tree.
>>>> +A thermal structure includes thermal zones and their components, such
>>>> +as name, trip points, polling intervals and cooling devices binding
>>>> +descriptors. A binding descriptor may contain information on how to
>>>> +react, with a cooling stepped action or a weight on a fair share.
>>>> +The target of device tree thermal descriptors is to describe only
>>>> +the hardware thermal aspects, not how the system must control or which
>>>> +algorithm or policy must take place. It follows a description of each
>>>> +type of device tree node.
>>>> +
>>>> +****
>>>> +trip
>>>> +****
>>>> +
>>>> +The trip node is a node to describe a point in the temperature domain
>>>> +in which the system takes an action. This node describes just the point,
>>>> +not the action.
>>>> +
>>>> +A node describing a trip must contain:
>>>> +- temperature: the trip temperature level, in milliCelsius.
>>>> +- hysteresis: a (low) hysteresis value on 'temperature'. This is a relative
>>>> +value, in milliCelsius.
>>>
>>> Presumably this is a single (u32) cell?
>>
>> Yes, both of them above are a single u32.
> 
> Ok. This seems to be the default assumption in many bindings, so I
> shan't argue against it here, but in general we should be as precise as
> possible as to the format of the devicetree.
> 

Yeah, I followed the default assumption. It does not hurt to be
descriptive though.

>>
>>>
>>>> +- type: the trip type. Here is the type mapping:
>>>> +       THERMAL_TRIP_ACTIVE
>>>> +       THERMAL_TRIP_PASSIVE
>>>> +       THERMAL_TRIP_HOT
>>>> +       THERMAL_TRIP_CRITICAL
>>>
>>> What type is this property?
>>>
>>> What are these values? Do you need to refer to a header somewhere?
>>
>> There is a header, introduced in this patch.
>> include/dt-bindings/thermal/thermal.h
>>
>>> Symbolic constants should have an associated value for an ABI.
>>
>> OK. Sounds reasonable to me. Shall we be descriptive and enlist the
>> values in this doc too or just pointing to header is fine?
> 
> I believe that referring to the header is fine, though personally I'd
> prefer if we were explicit in binding docs. I'll leave Stephen to
> comment on what the preferred way of handling header constants with
> binding documents is.
> 

OK. I will do both.

>>
>>>
>>>> +
>>>> +**********
>>>> +bind_param
>>>> +**********
>>>> +
>>>> +The bind_param node is a node to describe how cooling devices get assigned
>>>> +to trip points of the zone. The cooling devices are expected to be loaded
>>>> +in the target system.
>>>> +
>>>> +A node describing a bind_param must contain:
>>>> +- cooling_device: A string with the cooling device name.
>>>
>>> Please use '-' rather than '_' in bindings. That's the normal devicetree
>>> convention, and there's no point gonig against it and causing more
>>> confusion.
>>
>> Agreed.
>>
>>>
>>> What are valid values of this string, and what do they mean?
>>
>> These are the name of the cooling devices to match to.
> 
> Which are what exactly? What constitutes a "cooling device"?
> 
> Is "black-body radiation" [1] a valid cooling device?
> 
> How about "copper heat sink"?
> 

Those are example of cooling devices, yes. But in this context what is
interesting is those devices that allow you to control the amount of
dissipated power, i.e. operating frequency/voltage, lcd brightness,
audio volume, radio transmission power, or if those that you burn power
by turning them on but you remove heat out of your thermal zone, like a
speed controllable fan.

>>
>>>
>>> Why not a phandle + cells binding to cooling devices?
>>>
>>
>> Yeah, this could work too. I am going to check how that would look like
>> and come back to you.
> 
> Ok.
> 
>>
>>>> +- weight: The 'influence' of a particular cooling device on this zone.
>>>> +             This is on a percentage scale. The sum of all these weights
>>>> +             (for a particular zone) cannot exceed 100.
>>>
>>> This is a bit fuzzy, and certainly needs more guidance.
>>
>> OK. This property is used to describe the amount of cooling contribution
>> when activating a cooling device at a certain trip point. I will work on
>> a better guidance.
>>
>>>
>>>> +- trip_mask: This is a bit mask that gives the binding relation between
>>>> +               this thermal zone and cdev, for a particular trip point.
>>>> +               If nth bit is set, then the cdev and thermal zone are bound
>>>> +               for trip point n.
>>>
>>> What type is this?
>>>
>>> The nth bit from which end?
>>>
>>> Could you explain what "bound for trip point n" means?
>>>
>>
>> It is just a way to match a cooling device with a set of trip points.
>> Say you want to match one specific cooling device with trips 0 and 1,
>> you would then create a bind_param with trip_mask = 0x3.
>>
>>> Just because this is a bitmask in Linux does not mean it needs to be so
>>> in the dt.
>>
>> Indeed.
>>
>> In case we work with phandle + cell binging parameters, the trip and
>> weight could be passed as params.
>>
>>       cooling-devices = <&devX tripY weightZ>, <... >;
> 
> Something like that could certainly work.

I see. I will check that option.

> 
>>
>>>
>>>> +- limits: An array integers consisting of 2-tuples items, and each item means
>>>> +  lower and upper state limits, like <min-state max-state>.
>>>> +
>>>> +**************************
>>>> +temperature sensor devices
>>>> +**************************
>>>> +
>>>> +Temperature sensor devices have to be linked to a specific thermal zone.
>>>> +This is done by means of the 'monitored-zones' list.
>>>> +- monitored-zones: A list of thermal zones phandles, identifying which
>>>> +thermal zones the temperature sensor device is used to monitor.
>>>
>>> Why does this need to be described that way around?
>>>
>>> Can the zone not have a link to the sensor(s) it needs?
>>>
>>
>> Do you see any issues with it?
>>
>> Idea is that sensor nodes would list which zones they are used.  Same
>> idea goes to cooling devices. It can be the other way around, yes. It
>> depends on what is the best way to describe these relations. Idea would
>> be so that sensors and cooling devices would be composing a thermal zone.
> 
> I think that having a zone refer to the sensors that monitor it would be
> preferable. Otherwise we're encoding that way a devices output is to be
> consumed on the binding for the device itself, which feels odd (it's
> arguable as to whether it's a property of the device, however).
> 

I got confused now. How adding a monitored-zones property on sensor's
nodes would imply that device's output is to be consumed on the binding
for the device itself?

>>
>>>> +
>>>> +************
>>>> +thermal_zone
>>>> +************
>>>> +
>>>> +The thermal_zone node is the node containing all the required info
>>>> +for describing a thermal zone, including its cdev bindings. The thermal_zone
>>>> +node must contain, apart from its own properties, one node containing
>>>> +trip nodes and one node containing all the zone bind parameters.
>>>> +
>>>> +Required properties:
>>>> +- mask: Bit string: If 'n'th bit is set, then trip point 'n' is writeable.
>>>
>>> What type is a bit string in devicetree? I'm aware of cells and (byte)
>>> strings, but not bit strings.
>>>
>>> What does 'writeable' mean in this context?
>>>
>>> There's presumably a better name than 'mask'.
>>>
>>
>> This is used to describe if trip points are writeable under sysfs. I
>> think this is a OS implementation leak. I will be removing this from
>> device tree and making them RO by default.
> 
> Ok.
> 
>>
>>>> +
>>>> +- passive_delay: number of milliseconds to wait between polls when
>>>> +  performing passive cooling.
>>>> +
>>>> +- polling_delay: number of milliseconds to wait between polls when checking.
>>>
>>> These sound very much like configuration of the driver rather than
>>> hardware description. What if my temperature sensor can generate an
>>> interrupt at some trigger temperature? Why would I need polling times?
>>>
>>> Why does this need to be in the dt at all? Surely the OS can choose some
>>> sensible polling period, possibly dynamically?
>>
>> Well, let me answer this one with another question. How the OS will
>> determine how fast is the temperature rise on a thermal zone described
>> in device tree?
> 
> How will the devicetree writer determine this?
> 
> It's possible for the thermal management code to dynamically adjust the
> rate between some extreme polling intervals based on how big a rise it
> detects between polls or possibly something more complex taking into
> account some metric for load.

It is possible yes, by means of a couple of complex differential
equations implementation.  But still, determining the maximum dT/dt may
require unnecessary polling on low activity use cases. Besides, people
who do transient thermal simulation should have a better estimate on
necessary polling requirement. I don't see why we should not use that
handy info and impose hard software requirements.

> 
>>
>>>
>>>> +
>>>> +- #thermal-cells: An integer that is used to specify how many cells compose
>>>> +  sensor ids.
>>>
>>> I don't see why this is necessary. If the zone itself described its
>>> related sensors rather than the other way around, we wouldn't need it at
>>> all. Most bindings so far have consumers link to their providers rather
>>> than the other way around.
>>>
>>
>> I see.
>>
>>
>>>> +
>>>> +Below is an example:
>>>> +cpu_thermal: thermal_zone {
>>>> +            #thermal-cells = <1>;
>>>> +            mask = <0x03>; /* trips writability */
>>>> +            passive_delay = <250>; /* milliseconds */
>>>> +            polling_delay = <1000>; /* milliseconds */
>>>> +            trips {
>>>> +                    alert@100000{
>>>> +                            temperature = <100000>; /* milliCelsius */
>>>> +                            hysteresis = <0>; /* milliCelsius */
>>>> +                            type = <THERMAL_TRIP_PASSIVE>;
>>>> +                    };
>>>> +                    crit@125000{
>>>> +                            temperature = <125000>; /* milliCelsius */
>>>> +                            hysteresis = <0>; /* milliCelsius */
>>>> +                            type = <THERMAL_TRIP_CRITICAL>;
>>>> +                    };
> 
> I didn't spot this on my first round, but the trips node will need
> #address-cells and #size-cells, and the sub nodes unit-addresses should
> match their reg properties.

You mean, thermal zones must have address and size cells to describe trips?

> 
>>>> +            };
>>>> +            bind_params {
>>>> +                    action@0{
>>>> +                            cooling_device = "thermal-cpufreq";
>>>
>>> NAK. That value was not defined anywhere, and represents Linux
>>> infrastructure rather than hardware.
>>>
>>
>> Yes, this was another leak as discussed above in the upper part of the
>> doc file.
>>
>>> For this case, we could just as easily describe the thermal points, and
>>> if no physical cooling device (e.g. a fan) is present, assume
>>> cpufreq-base cooling.  Other OSs could choose to do otherwise, and we
>>> could change later...
>>>
>>
>> The way other specifications do (aka ACPI) is to have trip types. In
>> case a trip type is passive cooling, it means one is supposed to
>> modulate the dissipated power rather than activating a device to remove
>> heat (active cooling).
>>
>> The part of 'assuming' things that bothers me. I would rather have a way
>> to really say one wants to have passive cooling at a specific trip point.
> 
> I don't see the problem here. If you don't specify a device, your only
> options will be some sort of passive management.

But it does not need to be active all the time. You need to say when (in
temperature domain) that is need. Besides, there are even other means of
managing average power other than cpufreq cooling. idle injections is
another passive cooling device, for instance.

> 
>>
>>
>>>> +                            weight = <100>; /* percentage */
>>>> +                            mask = <0x01>;
>>>
>>> This should presumably be trip-mask (assuming my suggested corrections).
>>>
>>> What is it supposed to mean here?
>>
>> As stated above, it means the trip points that this binding represents.
> 
> If you have more than 32 trip points (which is admittedly unlikely), how
> do you represent them? I'm not sure a mask is the best representation
> here, as it's difficult for a human to match up with a list of entries.
> 
> Additionally, the trip points don't have a logical contiguous numbering
> from zero, so how do the bits in the mask correspond to entries in the
> list? This seems to rely on the order that the subnodes are in, which
> AFAIK is not guaranteed. It would be far nicer to have an explicit
> linkage.


Do you mean some sort of list of trip points property inside binding
params node?

> 
>>
>>>
>>>> +                           limits = <
>>>> +                             /* lower-state            upper-state */
>>>> +                               1                       THERMAL_NO_LIMITS
>>>> +                               THERMAL_NO_LIMITS       THERMAL_NO_LIMITS
>>>> +                           >;
>>>> +                    };
>>>> +            };
>>>> +};
>>>> +
>>>> +sensor: adc@0xFFFF {
>>>> +       ...
>>>> +       monitored-zones = <&cpu_thermal 0>;
>>>> +};
>>>> +
>>>> +cpu@0 {
>>>> +       ...
>>>> +       cooling-zones = <&cpu_thermal>;
>>>> +};
>>>> +
>>>> +In the example above, the ADC sensor at address 0xFFFF is used to monitor
>>>> +the zone 'cpu_thermal' using its the sensor 0. The cpu@0 device is also linked
>>>> +to the same thermal zone 'cpu_thermal' as a cooling device.
>>>
>>> Huh? That seems to imply the the '0' in '<&cpu_thermal 0>' on the sensor
>>> node describes a property of the sensor rather than the thermal node,
>>> unless I've misunderstood?
>>>
>>
>> It is essentially which sensor id is used to monitor a specific zone. In
>> case of sensor IPs that feature several internal sensors, one needs to
>> have a way to describe which sensor monitors which zone. Example of this
>> type of IPs: lm90 (up to 3 sensors) and TI bandgap IP (can contain up to
>> 5 internal sensors). The probe happens for the IP device and not for the
>> internal sensors.
> 
> Which is exactly why this should be the opposite way round, with thermal
> zones referring to sensors in this fashion.
> 
> The way you're suggesting means that the phandle+cells specifier refers
> half to the consumer and half to the producer. Having thermal zones
> refer to sensors would make this refer solely to the producer (the
> sensor).
> 

Are you suggesting having inside thermal zone node:

	sensors = <&sensor0 Y>, ...., <&sensorN Z> ;

Where sensor0 and sensorN are sensor IPs nodes and Y and Z represent
their internal sensor instances?

>>
>>
>>>> +
>>>> +***************
>>>> +cpufreq-cooling
>>>> +***************
>>>> +
>>>> +The generic cpu cooling (freq clipping) can be loaded by the
>>>> +generic cpufreq-cpu0 driver in case the device tree node informs
>>>> +this need.
>>>> +
>>>> +In order to load the cpufreq cooling device, it is possible to
>>>> +inform that the cpu needs cooling by adding the list of thermal zones
>>>> +in the 'cooling-zones' property at the cpu0 phandle.
>>>
>>> This should be reworded so as to describe the binding rather than the
>>> Linux behaviour based on the binding.
>>
>> OK.
>>
>>>
>>>> +
>>>> +Example:
>>>> +       cpus {
>>>> +               cpu@0 {
>>>> +                       operating-points = <
>>>> +                               /* kHz    uV */
>>>> +                               800000  1313000
>>>> +                               1008000 1375000
>>>> +                       >;
>>>> +                       cooling-zones = <&cpu_thermal>;
>>>> +               };
>>>> +       ...
>>>> +       };
>>>> +
>>>> +The above will cause the cpufreq-cpu0 driver to understand that
>>>> +the cpu will need passive cooling and while probing that node it will
>>>> +also load the cpufreq cpu cooling device in that system.
>>>
>>> The above describe that the CPU is part of a cooling (thermal?) zone and
>>> requires cooling.
>>
>> That says the cpu participates in a thermal zone as a cooling
>> device/mechanism, thus cpu cooling (passive cooling) is required in
>> target system.
> 
> I think you need the rest of the nodes in this example. You don't show
> whether or not there's a cooling-device, so it's not clear that the CPU
> is required to be passively cooled...

The property states the cpu is used as cooling device for those thermal
zones in the list 'cooling-zones'

> 
>>
>>>
>>>> +
>>>> +However, be advised that this flag will not describe what needs to
>>>> +be done or how the cpufreq cooling device will be used. In order to
>>>> +accomplish this, one needs to write a phandle for a thermal zone, as
>>>> +described in the section 'thermal_zone'.
>>>
>>> The above already has a phandle to a thermal (cooling?) zone.
>>>
>>> Please choose either cooling zone or thermal zone, having the two names
>>> makes this more confusing than necessary.
>>
>> I see. Idea is to have thermal zone as a node. cooling-zone is just a
>> list of thermal zones that the referred device will be used as cooling
>> device.
> 
> While I can see a distinction, the nomenclature is horrendously
> confusing.


OK. I will try harder to improve it.

> 
>>
>>>
>>>> diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
>>>> index 7fb16bc..753f0dc 100644
>>>> --- a/drivers/thermal/Kconfig
>>>> +++ b/drivers/thermal/Kconfig
>>>> @@ -29,6 +29,19 @@ config THERMAL_HWMON
>>>>           Say 'Y' here if you want all thermal sensors to
>>>>           have hwmon sysfs interface too.
>>>>
>>>> +config THERMAL_OF
>>>> +       bool
>>>> +       prompt "APIs to parse thermal data out of device tree"
>>>> +       depends on OF
>>>> +       default y
>>>> +       help
>>>> +         This options provides helpers to add the support to
>>>> +         read and parse thermal data definitions out of the
>>>> +         device tree blob.
>>>> +
>>>> +         Say 'Y' here if you need to build thermal infrastructure
>>>> +         based on device tree.
>>>> +
>>>>  choice
>>>>         prompt "Default Thermal governor"
>>>>         default THERMAL_DEFAULT_GOV_STEP_WISE
>>>> diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
>>>> index 24cb894..eedb273 100644
>>>> --- a/drivers/thermal/Makefile
>>>> +++ b/drivers/thermal/Makefile
>>>> @@ -7,6 +7,7 @@ thermal_sys-y                   += thermal_core.o
>>>>
>>>>  # interface to/from other layers providing sensors
>>>>  thermal_sys-$(CONFIG_THERMAL_HWMON)            += thermal_hwmon.o
>>>> +thermal_sys-$(CONFIG_THERMAL_OF)               += thermal_dt.o
>>>>
>>>>  # governors
>>>>  thermal_sys-$(CONFIG_THERMAL_GOV_FAIR_SHARE)   += fair_share.o
>>>> diff --git a/drivers/thermal/thermal_dt.c b/drivers/thermal/thermal_dt.c
>>>> new file mode 100644
>>>> index 0000000..cc35485
>>>> --- /dev/null
>>>> +++ b/drivers/thermal/thermal_dt.c
>>>> @@ -0,0 +1,473 @@
>>>> +/*
>>>> + *  thermal_dt.c - Generic Thermal Management device tree support.
>>>> + *
>>>> + *  Copyright (C) 2013 Texas Instruments
>>>> + *  Copyright (C) 2013 Eduardo Valentin <eduardo.valentin@ti.com>
>>>> + *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>>>> + *
>>>> + *  This program is free software; you can redistribute it and/or modify
>>>> + *  it under the terms of the GNU General Public License as published by
>>>> + *  the Free Software Foundation; version 2 of the License.
>>>> + *
>>>> + *  This program is distributed in the hope that it will be useful, but
>>>> + *  WITHOUT ANY WARRANTY; without even the implied warranty of
>>>> + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>>>> + *  General Public License for more details.
>>>> + *
>>>> + *  You should have received a copy of the GNU General Public License along
>>>> + *  with this program; if not, write to the Free Software Foundation, Inc.,
>>>> + *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
>>>> + *
>>>> + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>>>> + */
>>>> +#include <linux/thermal.h>
>>>> +#include <linux/slab.h>
>>>> +#include <linux/types.h>
>>>> +#include <linux/of_device.h>
>>>> +#include <linux/of_platform.h>
>>>> +#include <linux/err.h>
>>>> +#include <linux/export.h>
>>>> +#include <linux/string.h>
>>>> +
>>>> +struct __thermal_bind_params {
>>>> +       char cooling_device[THERMAL_NAME_LENGTH];
>>>> +};
>>>> +
>>>> +static
>>>> +int thermal_of_match(struct thermal_zone_device *tz,
>>>> +                    struct thermal_cooling_device *cdev);
>>>> +
>>>> +static int thermal_of_populate_bind_params(struct device *dev,
>>>> +                                          struct device_node *node,
>>>> +                                          struct __thermal_bind_params *__tbp,
>>>> +                                          struct thermal_bind_params *tbp,
>>>> +                                          int ntrips)
>>>> +{
>>>> +       const char *cdev_name;
>>>> +       u32 *limits;
>>>> +       int ret;
>>>> +       u32 prop;
>>>> +
>>>> +       ret = of_property_read_u32(node, "weight", &prop);
>>>> +       if (ret < 0) {
>>>> +               dev_err(dev, "missing weight property\n");
>>>> +               return ret;
>>>> +       }
>>>> +       tbp->weight = prop;
>>>> +
>>>> +       ret = of_property_read_u32(node, "mask", &prop);
>>>> +       if (ret < 0) {
>>>> +               dev_err(dev, "missing mask property\n");
>>>> +               return ret;
>>>> +       }
>>>> +       tbp->trip_mask = prop;
>>>> +
>>>> +       /* this will allow us to bind with cooling devices */
>>>> +       tbp->match = thermal_of_match;
>>>> +
>>>> +       ret = of_property_read_string(node, "cooling_device", &cdev_name);
>>>> +       if (ret < 0) {
>>>> +               dev_err(dev, "missing cooling_device property\n");
>>>> +               return ret;
>>>> +       }
>>>> +       strncpy(__tbp->cooling_device, cdev_name,
>>>> +               sizeof(__tbp->cooling_device));
>>>> +
>>>> +       limits = kzalloc(ntrips * sizeof(*limits) * 2, GFP_KERNEL);
>>>
>>> Why do you use kzalloc here, but devm_kzalloc elsewhere? That'll lead to
>>> problems as the driver gets refactored over time.
>>
>> Because this memory is used only  within this function and thus released
>> at the bottom of it.
>>
>>>
>>>> +       if (!limits) {
>>>> +               dev_err(dev, "not enough mem for reading limits\n");
>>>> +               return -ENOMEM;
>>>> +       }
>>>> +       ret = of_property_read_u32_array(node, "limits", limits, 2 * ntrips);
>>>> +       if (!ret) {
>>>> +               int i = ntrips;
>>>> +
>>>> +               tbp->binding_limits = devm_kzalloc(dev,
>>>> +                                                  ntrips * 2 *
>>>> +                                                  sizeof(*tbp->binding_limits),
>>>> +                                                  GFP_KERNEL);
>>>> +               if (!tbp->binding_limits) {
>>>> +                       dev_err(dev, "not enough mem for storing limits\n");
>>>> +                       return -ENOMEM;
>>>> +               }
>>>> +               while (i--)
>>>> +                       tbp->binding_limits[i] = limits[i];
>>>> +       }
>>>> +       kfree(limits);
>>
>> here.
> 
> I saw that, I did say that this may lead to problems in future if the
> function's reorganised, not now. :)

Ahh.. OK. I just didnt want o let the memory be managed and freed only
when the struct device is release.

> 
>>
>>>> +
>>>> +       return 0;
>>>
>>> What if you failed to read the array? Surely you should return an error?
>>
>> Attempting to make this property not mandatory.
> 
> That wasn't clear from the binding, and now I've re-read it, I'm still
> not entirely clear on what the limits represent, and why you may have
> multiple sets of pairs.

Because you may assign cooling state limits to specific trip points,
e.g., a fan with 5 different speeds would operate from speed 0 to 2 in
the first trip point, while from speed 3 to 4 on last trip point.

> 
>>
>>>
>>>> +}
>>>> +
>>>> +struct __thermal_trip {
>>>> +       unsigned long int temperature;
>>>> +       unsigned long int hysteresis;
>>>> +       enum thermal_trip_type type;
>>>> +};
>>>> +
>>>> +static
>>>> +int thermal_of_populate_trip(struct device *dev,
>>>> +                            struct device_node *node,
>>>> +                            struct __thermal_trip *trip)
>>>> +{
>>>> +       int ret;
>>>> +       int prop;
>>>> +
>>>> +       ret = of_property_read_u32(node, "temperature", &prop);
>>>> +       if (ret < 0) {
>>>> +               dev_err(dev, "missing temperature property\n");
>>>> +               return ret;
>>>> +       }
>>>> +       trip->temperature = prop;
>>>> +
>>>> +       ret = of_property_read_u32(node, "hysteresis", &prop);
>>>> +       if (ret < 0) {
>>>> +               dev_err(dev, "missing hysteresis property\n");
>>>> +               return ret;
>>>> +       }
>>>> +       trip->hysteresis = prop;
>>>> +
>>>> +       ret = of_property_read_u32(node, "type", &prop);
>>>> +       if (ret < 0) {
>>>> +               dev_err(dev, "missing type property\n");
>>>> +               return ret;
>>>> +       }
>>>> +       trip->type = prop;
>>>
>>> This will require sanity checking.
>>
>> OK.
>>
>>>
>>>> +
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +struct __thermal_zone_device {
>>>> +       enum thermal_device_mode mode;
>>>> +       int passive_delay;
>>>> +       int polling_delay;
>>>> +       int mask;
>>>> +       int ntrips;
>>>> +       char type[THERMAL_NAME_LENGTH];
>>>> +       struct __thermal_trip *trips;
>>>> +       struct __thermal_bind_params *bind_params;
>>>> +       struct thermal_bind_params *tbps;
>>>> +       struct thermal_zone_params zone_params;
>>>> +       int (*get_temp)(void *, unsigned long *);
>>>> +       void *devdata;
>>>> +};
>>>> +
>>>> +static struct __thermal_zone_device *
>>>> +thermal_of_build_thermal_zone(struct device *dev, struct device_node *node)
>>>> +{
>>>> +       struct device_node *child, *gchild;
>>>> +       struct __thermal_zone_device *tz;
>>>> +       int ret, i;
>>>> +       u32 prop;
>>>> +
>>>> +       if (!node) {
>>>> +               dev_err(dev, "no thermal zone node\n");
>>>> +               return ERR_PTR(-EINVAL);
>>>> +       }
>>>> +
>>>> +       tz = devm_kzalloc(dev, sizeof(*tz), GFP_KERNEL);
>>>> +       if (!tz) {
>>>> +               dev_err(dev, "not enough memory for thermal of zone\n");
>>>> +               return ERR_PTR(-ENOMEM);
>>>> +       }
>>>> +
>>>> +       ret = of_property_read_u32(node, "passive_delay", &prop);
>>>> +       if (ret < 0) {
>>>> +               dev_err(dev, "missing passive_delay property\n");
>>>> +               return ERR_PTR(ret);
>>>> +       }
>>>> +       tz->passive_delay = prop;
>>>> +
>>>> +       ret = of_property_read_u32(node, "polling_delay", &prop);
>>>> +       if (ret < 0) {
>>>> +               dev_err(dev, "missing polling_delay property\n");
>>>> +               return ERR_PTR(ret);
>>>> +       }
>>>> +       tz->polling_delay = prop;
>>>> +
>>>> +       ret = of_property_read_u32(node, "mask", &prop);
>>>> +       if (ret < 0) {
>>>> +               dev_err(dev, "missing mask property\n");
>>>> +               return ERR_PTR(ret);
>>>> +       }
>>>> +       tz->mask = prop;
>>>> +
>>>> +       /* assume node name as our zone type */
>>>> +       strncpy(tz->type, node->name, sizeof(tz->type));
>>>> +
>>>> +       /* default policy */
>>>> +       strncpy(tz->zone_params.governor_name, "step_wise",
>>>> +               sizeof(tz->zone_params.governor_name));
>>>> +
>>>> +       /* trips */
>>>> +       child = of_find_node_by_name(node, "trips");
>>>
>>> That might not be a child node, as of_find_node_by_name walks over the
>>> list of all nodes. Use of_get_child_by_name.
>>
>> Right! This is a bug.
>>
>>>
>>>> +
>>>> +       /* No trips provided */
>>>> +       if (!child)
>>>> +               goto finish;
>>>> +
>>>> +       tz->ntrips = of_get_child_count(child);
>>>> +       tz->trips = devm_kzalloc(dev, tz->ntrips * sizeof(*tz->trips),
>>>> +                                GFP_KERNEL);
>>>> +       if (!tz->trips)
>>>> +               return ERR_PTR(-ENOMEM);
>>>> +       i = 0;
>>>> +       for_each_child_of_node(child, gchild)
>>>> +               thermal_of_populate_trip(dev, gchild, &tz->trips[i++]);
>>>
>>> What if a child node was not a valid trip node? It seems
>>> thermal_of_populate_trip returns errors you're ignoring.
>>
>> OK. Adding proper treatment.
>>
>>>
>>>> +
>>>> +       /* bind_params */
>>>> +       child = of_find_node_by_name(node, "bind_params");
>>>
>>> Another of_get_child_by_name candidate.
>>
>> OK.
>>
>>>
>>>> +
>>>> +       /* No binding info */
>>>> +       if (!child)
>>>> +               goto finish;
>>>> +
>>>> +       tz->zone_params.num_tbps = of_get_child_count(child);
>>>> +       tz->bind_params = devm_kzalloc(dev,
>>>> +                                      tz->zone_params.num_tbps *
>>>> +                                               sizeof(*tz->bind_params),
>>>> +                                      GFP_KERNEL);
>>>> +       if (!tz->bind_params)
>>>> +               return ERR_PTR(-ENOMEM);
>>>> +       tz->zone_params.tbp = devm_kzalloc(dev,
>>>> +                                          tz->zone_params.num_tbps *
>>>> +                                               sizeof(*tz->zone_params.tbp),
>>>> +                                          GFP_KERNEL);
>>>> +       if (!tz->zone_params.tbp)
>>>> +               return ERR_PTR(-ENOMEM);
>>>> +       i = 0;
>>>> +       for_each_child_of_node(child, gchild) {
>>>> +               thermal_of_populate_bind_params(dev, gchild,
>>>> +                                               &tz->bind_params[i],
>>>> +                                               &tz->zone_params.tbp[i],
>>>> +                                               tz->ntrips);
>>>
>>> Similarly, you're ignoring error conditions here. What if a bind_params
>>> node was malformed?
>>
>>
>> Adding proper error handling.
>>
>>>
>>>> +               i++;
>>>> +       }
>>>> +
>>>> +finish:
>>>> +       tz->mode = THERMAL_DEVICE_ENABLED;
>>>> +
>>>> +       return tz;
>>>> +}
>>>> +
>>>> +static
>>>> +int thermal_of_match(struct thermal_zone_device *tz,
>>>> +                    struct thermal_cooling_device *cdev)
>>>> +{
>>>> +       struct __thermal_zone_device *data = tz->devdata;
>>>> +       int i;
>>>> +
>>>> +       for (i = 0; i < data->zone_params.num_tbps; i++) {
>>>> +               if (!strncmp(data->bind_params[i].cooling_device,
>>>> +                            cdev->type,
>>>> +                            strlen(data->bind_params[i].cooling_device)) &&
>>>> +                   (data->zone_params.tbp[i].trip_mask & (1 << i)))
>>>> +                       return 0;
>>>> +       }
>>>> +
>>>> +       return -EINVAL;
>>>> +}
>>>
>>> I'm not keen on binding to cooling devices using a string, as suddenly a
>>> name to allow humans to inspect the system is turned into an ABI.
>>
>> OK. We need to align on how we describe the binding then.
> 
> Definitely. We need to ensure that we fully define the relationship too
> cooling devices, and don't suddenly expose some piece of internal Linux
> infrastructure to the world.
> 

Yeah, agreed, any suggestions?

>>
>>>
>>>> +
>>>> +static
>>>> +int of_thermal_get_temp(struct thermal_zone_device *tz,
>>>> +                       unsigned long *temp)
>>>> +{
>>>> +       struct __thermal_zone_device *data = tz->devdata;
>>>> +
>>>> +       return data->get_temp(data->devdata, temp);
>>>> +}
>>>> +
>>>> +static
>>>> +int of_thermal_get_mode(struct thermal_zone_device *tz,
>>>> +                       enum thermal_device_mode *mode)
>>>> +{
>>>> +       struct __thermal_zone_device *data = tz->devdata;
>>>> +
>>>> +       *mode = data->mode;
>>>> +
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +static
>>>> +int of_thermal_set_mode(struct thermal_zone_device *tz,
>>>> +                       enum thermal_device_mode mode)
>>>> +{
>>>> +       struct __thermal_zone_device *data = tz->devdata;
>>>> +
>>>> +       mutex_lock(&tz->lock);
>>>> +
>>>> +       if (mode == THERMAL_DEVICE_ENABLED)
>>>> +               tz->polling_delay = data->polling_delay;
>>>> +       else
>>>> +               tz->polling_delay = 0;
>>>> +
>>>> +       mutex_unlock(&tz->lock);
>>>> +
>>>> +       data->mode = mode;
>>>> +       thermal_zone_device_update(tz);
>>>> +
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +static
>>>> +int of_thermal_get_trip_type(struct thermal_zone_device *tz, int trip,
>>>> +                            enum thermal_trip_type *type)
>>>> +{
>>>> +       struct __thermal_zone_device *data = tz->devdata;
>>>> +
>>>> +       if (trip >= data->ntrips || trip < 0)
>>>> +               return -EDOM;
>>>
>>> It's far more common to use -EINVAL.
>>
>> hmm.. OK.
>>
>>>
>>>> +
>>>> +       *type = data->trips[trip].type;
>>>> +
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +static
>>>> +int of_thermal_get_trip_temp(struct thermal_zone_device *tz, int trip,
>>>> +                            unsigned long *temp)
>>>> +{
>>>> +       struct __thermal_zone_device *data = tz->devdata;
>>>> +
>>>> +       if (trip >= data->ntrips || trip < 0)
>>>> +               return -EDOM;
>>>> +
>>>> +       *temp = data->trips[trip].temperature;
>>>> +
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +static
>>>> +int of_thermal_set_trip_temp(struct thermal_zone_device *tz, int trip,
>>>> +                            unsigned long temp)
>>>> +{
>>>> +       struct __thermal_zone_device *data = tz->devdata;
>>>> +
>>>> +       if (trip >= data->ntrips || trip < 0)
>>>> +               return -EDOM;
>>>> +
>>>> +       /* thermal fw should take care of data->mask & (1 << trip) */
>>>> +       data->trips[trip].temperature = temp;
>>>> +
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +static
>>>> +int of_thermal_get_trip_hyst(struct thermal_zone_device *tz, int trip,
>>>> +                            unsigned long *hyst)
>>>> +{
>>>> +       struct __thermal_zone_device *data = tz->devdata;
>>>> +
>>>> +       if (trip >= data->ntrips || trip < 0)
>>>> +               return -EDOM;
>>>> +
>>>> +       *hyst = data->trips[trip].hysteresis;
>>>> +
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +static
>>>> +int of_thermal_set_trip_hyst(struct thermal_zone_device *tz, int trip,
>>>> +                            unsigned long hyst)
>>>> +{
>>>> +       struct __thermal_zone_device *data = tz->devdata;
>>>> +
>>>> +       if (trip >= data->ntrips || trip < 0)
>>>> +               return -EDOM;
>>>> +
>>>> +       /* thermal fw should take care of data->mask & (1 << trip) */
>>>
>>> Could you elaborate on that comment?
>>
>> In  case the trip is not assigned to be writable, this function won't be
>> called.
> 
> Ah. I misunderstood "fw" as "firmware", rather than "framework", and got
> confused. It would be nice if you could expand "fw" to make this
> clearer. :)

Sorry for that :-)

> 
> Thanks,
> Mark.
> 
> [1] http://en.wikipedia.org/wiki/Black-body_radiation
> 
> 


-- 
You have got to be excited about what you are doing. (L. Lamport)

Eduardo Valentin


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 295 bytes --]

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

* Re: [lm-sensors] [RFC PATCH 02/14] drivers: thermal: introduce device tree parser
@ 2013-08-27 18:17           ` Eduardo Valentin
  0 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-27 18:17 UTC (permalink / raw)
  To: Mark Rutland
  Cc: Eduardo Valentin, swarren, Pawel Moll, ian.campbell,
	grant.likely, rob.herring, linux, rui.zhang, wni, durgadoss.r,
	linux-pm, devicetree, lm-sensors, linux-kernel


[-- Attachment #1.1: Type: text/plain, Size: 39359 bytes --]

On 27-08-2013 12:23, Mark Rutland wrote:
> On Tue, Aug 27, 2013 at 02:44:40PM +0100, Eduardo Valentin wrote:
>> Hello Mark,
>>
>>
>> First of all, thanks for taking the time to review in such level of
>> detail. Lets try to align and have a common understanding. Answers go
>> inline. Please let me know if I missed something or if I made it more
>> confusing :-)
>>
>> On 27-08-2013 06:22, Mark Rutland wrote:
>>> Hi,
>>>
>>> On Sat, Aug 24, 2013 at 12:15:43AM +0100, Eduardo Valentin wrote:
>>>> In order to be able to build thermal policies
>>>> based on generic sensors, like I2C device, that
>>>> can be places in different points on different boards,
>>>> there is a need to have a way to feed board dependent
>>>> data into the thermal framework.
>>>>
>>>> This patch introduces a thermal data parser for device
>>>> tree. The parsed data is used to build thermal zones
>>>> and thermal binding parameters. The output data
>>>> can then be used to deploy thermal policies.
>>>>
>>>> This patch adds also documentation regarding this
>>>> API and how to define tree nodes to use
>>>> this infrastructure.
>>>>
>>>> Cc: Zhang Rui <rui.zhang@intel.com>
>>>> Cc: linux-pm@vger.kernel.org
>>>> Cc: linux-kernel@vger.kernel.org
>>>> Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
>>>> ---
>>>>  .../devicetree/bindings/thermal/thermal.txt        | 160 +++++++
>>>>  drivers/thermal/Kconfig                            |  13 +
>>>>  drivers/thermal/Makefile                           |   1 +
>>>>  drivers/thermal/thermal_dt.c                       | 473 +++++++++++++++++++++
>>>>  include/dt-bindings/thermal/thermal.h              |  27 ++
>>>>  include/linux/thermal.h                            |   3 +
>>>>  6 files changed, 677 insertions(+)
>>>>  create mode 100644 Documentation/devicetree/bindings/thermal/thermal.txt
>>>>  create mode 100644 drivers/thermal/thermal_dt.c
>>>>  create mode 100644 include/dt-bindings/thermal/thermal.h
>>>>
>>
>>
>> General question on device tree documentation. Assuming there is such an
>> effort to make it Linux independent, is there other places out of Linux
>> tree that these binding must be documented?
> 
> At present, no. There is a plan to move the documentation out of the
> kernel, but I'm not sure on how that's currently progressing. Some
> general cleanup needs to occur before we can actually do that.
> 

OK.

>>
>>
>>>> diff --git a/Documentation/devicetree/bindings/thermal/thermal.txt b/Documentation/devicetree/bindings/thermal/thermal.txt
>>>> new file mode 100644
>>>> index 0000000..af20ab0
>>>> --- /dev/null
>>>> +++ b/Documentation/devicetree/bindings/thermal/thermal.txt
>>>> @@ -0,0 +1,160 @@
>>>> +----------------------------------------
>>>> +Thermal Framework Device Tree descriptor
>>>> +----------------------------------------
>>>> +
>>>> +This file describes how to define a thermal structure using device tree.
>>>> +A thermal structure includes thermal zones and their components, such
>>>> +as name, trip points, polling intervals and cooling devices binding
>>>> +descriptors. A binding descriptor may contain information on how to
>>>> +react, with a cooling stepped action or a weight on a fair share.
>>>> +The target of device tree thermal descriptors is to describe only
>>>> +the hardware thermal aspects, not how the system must control or which
>>>> +algorithm or policy must take place. It follows a description of each
>>>> +type of device tree node.
>>>> +
>>>> +****
>>>> +trip
>>>> +****
>>>> +
>>>> +The trip node is a node to describe a point in the temperature domain
>>>> +in which the system takes an action. This node describes just the point,
>>>> +not the action.
>>>> +
>>>> +A node describing a trip must contain:
>>>> +- temperature: the trip temperature level, in milliCelsius.
>>>> +- hysteresis: a (low) hysteresis value on 'temperature'. This is a relative
>>>> +value, in milliCelsius.
>>>
>>> Presumably this is a single (u32) cell?
>>
>> Yes, both of them above are a single u32.
> 
> Ok. This seems to be the default assumption in many bindings, so I
> shan't argue against it here, but in general we should be as precise as
> possible as to the format of the devicetree.
> 

Yeah, I followed the default assumption. It does not hurt to be
descriptive though.

>>
>>>
>>>> +- type: the trip type. Here is the type mapping:
>>>> +       THERMAL_TRIP_ACTIVE
>>>> +       THERMAL_TRIP_PASSIVE
>>>> +       THERMAL_TRIP_HOT
>>>> +       THERMAL_TRIP_CRITICAL
>>>
>>> What type is this property?
>>>
>>> What are these values? Do you need to refer to a header somewhere?
>>
>> There is a header, introduced in this patch.
>> include/dt-bindings/thermal/thermal.h
>>
>>> Symbolic constants should have an associated value for an ABI.
>>
>> OK. Sounds reasonable to me. Shall we be descriptive and enlist the
>> values in this doc too or just pointing to header is fine?
> 
> I believe that referring to the header is fine, though personally I'd
> prefer if we were explicit in binding docs. I'll leave Stephen to
> comment on what the preferred way of handling header constants with
> binding documents is.
> 

OK. I will do both.

>>
>>>
>>>> +
>>>> +**********
>>>> +bind_param
>>>> +**********
>>>> +
>>>> +The bind_param node is a node to describe how cooling devices get assigned
>>>> +to trip points of the zone. The cooling devices are expected to be loaded
>>>> +in the target system.
>>>> +
>>>> +A node describing a bind_param must contain:
>>>> +- cooling_device: A string with the cooling device name.
>>>
>>> Please use '-' rather than '_' in bindings. That's the normal devicetree
>>> convention, and there's no point gonig against it and causing more
>>> confusion.
>>
>> Agreed.
>>
>>>
>>> What are valid values of this string, and what do they mean?
>>
>> These are the name of the cooling devices to match to.
> 
> Which are what exactly? What constitutes a "cooling device"?
> 
> Is "black-body radiation" [1] a valid cooling device?
> 
> How about "copper heat sink"?
> 

Those are example of cooling devices, yes. But in this context what is
interesting is those devices that allow you to control the amount of
dissipated power, i.e. operating frequency/voltage, lcd brightness,
audio volume, radio transmission power, or if those that you burn power
by turning them on but you remove heat out of your thermal zone, like a
speed controllable fan.

>>
>>>
>>> Why not a phandle + cells binding to cooling devices?
>>>
>>
>> Yeah, this could work too. I am going to check how that would look like
>> and come back to you.
> 
> Ok.
> 
>>
>>>> +- weight: The 'influence' of a particular cooling device on this zone.
>>>> +             This is on a percentage scale. The sum of all these weights
>>>> +             (for a particular zone) cannot exceed 100.
>>>
>>> This is a bit fuzzy, and certainly needs more guidance.
>>
>> OK. This property is used to describe the amount of cooling contribution
>> when activating a cooling device at a certain trip point. I will work on
>> a better guidance.
>>
>>>
>>>> +- trip_mask: This is a bit mask that gives the binding relation between
>>>> +               this thermal zone and cdev, for a particular trip point.
>>>> +               If nth bit is set, then the cdev and thermal zone are bound
>>>> +               for trip point n.
>>>
>>> What type is this?
>>>
>>> The nth bit from which end?
>>>
>>> Could you explain what "bound for trip point n" means?
>>>
>>
>> It is just a way to match a cooling device with a set of trip points.
>> Say you want to match one specific cooling device with trips 0 and 1,
>> you would then create a bind_param with trip_mask = 0x3.
>>
>>> Just because this is a bitmask in Linux does not mean it needs to be so
>>> in the dt.
>>
>> Indeed.
>>
>> In case we work with phandle + cell binging parameters, the trip and
>> weight could be passed as params.
>>
>>       cooling-devices = <&devX tripY weightZ>, <... >;
> 
> Something like that could certainly work.

I see. I will check that option.

> 
>>
>>>
>>>> +- limits: An array integers consisting of 2-tuples items, and each item means
>>>> +  lower and upper state limits, like <min-state max-state>.
>>>> +
>>>> +**************************
>>>> +temperature sensor devices
>>>> +**************************
>>>> +
>>>> +Temperature sensor devices have to be linked to a specific thermal zone.
>>>> +This is done by means of the 'monitored-zones' list.
>>>> +- monitored-zones: A list of thermal zones phandles, identifying which
>>>> +thermal zones the temperature sensor device is used to monitor.
>>>
>>> Why does this need to be described that way around?
>>>
>>> Can the zone not have a link to the sensor(s) it needs?
>>>
>>
>> Do you see any issues with it?
>>
>> Idea is that sensor nodes would list which zones they are used.  Same
>> idea goes to cooling devices. It can be the other way around, yes. It
>> depends on what is the best way to describe these relations. Idea would
>> be so that sensors and cooling devices would be composing a thermal zone.
> 
> I think that having a zone refer to the sensors that monitor it would be
> preferable. Otherwise we're encoding that way a devices output is to be
> consumed on the binding for the device itself, which feels odd (it's
> arguable as to whether it's a property of the device, however).
> 

I got confused now. How adding a monitored-zones property on sensor's
nodes would imply that device's output is to be consumed on the binding
for the device itself?

>>
>>>> +
>>>> +************
>>>> +thermal_zone
>>>> +************
>>>> +
>>>> +The thermal_zone node is the node containing all the required info
>>>> +for describing a thermal zone, including its cdev bindings. The thermal_zone
>>>> +node must contain, apart from its own properties, one node containing
>>>> +trip nodes and one node containing all the zone bind parameters.
>>>> +
>>>> +Required properties:
>>>> +- mask: Bit string: If 'n'th bit is set, then trip point 'n' is writeable.
>>>
>>> What type is a bit string in devicetree? I'm aware of cells and (byte)
>>> strings, but not bit strings.
>>>
>>> What does 'writeable' mean in this context?
>>>
>>> There's presumably a better name than 'mask'.
>>>
>>
>> This is used to describe if trip points are writeable under sysfs. I
>> think this is a OS implementation leak. I will be removing this from
>> device tree and making them RO by default.
> 
> Ok.
> 
>>
>>>> +
>>>> +- passive_delay: number of milliseconds to wait between polls when
>>>> +  performing passive cooling.
>>>> +
>>>> +- polling_delay: number of milliseconds to wait between polls when checking.
>>>
>>> These sound very much like configuration of the driver rather than
>>> hardware description. What if my temperature sensor can generate an
>>> interrupt at some trigger temperature? Why would I need polling times?
>>>
>>> Why does this need to be in the dt at all? Surely the OS can choose some
>>> sensible polling period, possibly dynamically?
>>
>> Well, let me answer this one with another question. How the OS will
>> determine how fast is the temperature rise on a thermal zone described
>> in device tree?
> 
> How will the devicetree writer determine this?
> 
> It's possible for the thermal management code to dynamically adjust the
> rate between some extreme polling intervals based on how big a rise it
> detects between polls or possibly something more complex taking into
> account some metric for load.

It is possible yes, by means of a couple of complex differential
equations implementation.  But still, determining the maximum dT/dt may
require unnecessary polling on low activity use cases. Besides, people
who do transient thermal simulation should have a better estimate on
necessary polling requirement. I don't see why we should not use that
handy info and impose hard software requirements.

> 
>>
>>>
>>>> +
>>>> +- #thermal-cells: An integer that is used to specify how many cells compose
>>>> +  sensor ids.
>>>
>>> I don't see why this is necessary. If the zone itself described its
>>> related sensors rather than the other way around, we wouldn't need it at
>>> all. Most bindings so far have consumers link to their providers rather
>>> than the other way around.
>>>
>>
>> I see.
>>
>>
>>>> +
>>>> +Below is an example:
>>>> +cpu_thermal: thermal_zone {
>>>> +            #thermal-cells = <1>;
>>>> +            mask = <0x03>; /* trips writability */
>>>> +            passive_delay = <250>; /* milliseconds */
>>>> +            polling_delay = <1000>; /* milliseconds */
>>>> +            trips {
>>>> +                    alert@100000{
>>>> +                            temperature = <100000>; /* milliCelsius */
>>>> +                            hysteresis = <0>; /* milliCelsius */
>>>> +                            type = <THERMAL_TRIP_PASSIVE>;
>>>> +                    };
>>>> +                    crit@125000{
>>>> +                            temperature = <125000>; /* milliCelsius */
>>>> +                            hysteresis = <0>; /* milliCelsius */
>>>> +                            type = <THERMAL_TRIP_CRITICAL>;
>>>> +                    };
> 
> I didn't spot this on my first round, but the trips node will need
> #address-cells and #size-cells, and the sub nodes unit-addresses should
> match their reg properties.

You mean, thermal zones must have address and size cells to describe trips?

> 
>>>> +            };
>>>> +            bind_params {
>>>> +                    action@0{
>>>> +                            cooling_device = "thermal-cpufreq";
>>>
>>> NAK. That value was not defined anywhere, and represents Linux
>>> infrastructure rather than hardware.
>>>
>>
>> Yes, this was another leak as discussed above in the upper part of the
>> doc file.
>>
>>> For this case, we could just as easily describe the thermal points, and
>>> if no physical cooling device (e.g. a fan) is present, assume
>>> cpufreq-base cooling.  Other OSs could choose to do otherwise, and we
>>> could change later...
>>>
>>
>> The way other specifications do (aka ACPI) is to have trip types. In
>> case a trip type is passive cooling, it means one is supposed to
>> modulate the dissipated power rather than activating a device to remove
>> heat (active cooling).
>>
>> The part of 'assuming' things that bothers me. I would rather have a way
>> to really say one wants to have passive cooling at a specific trip point.
> 
> I don't see the problem here. If you don't specify a device, your only
> options will be some sort of passive management.

But it does not need to be active all the time. You need to say when (in
temperature domain) that is need. Besides, there are even other means of
managing average power other than cpufreq cooling. idle injections is
another passive cooling device, for instance.

> 
>>
>>
>>>> +                            weight = <100>; /* percentage */
>>>> +                            mask = <0x01>;
>>>
>>> This should presumably be trip-mask (assuming my suggested corrections).
>>>
>>> What is it supposed to mean here?
>>
>> As stated above, it means the trip points that this binding represents.
> 
> If you have more than 32 trip points (which is admittedly unlikely), how
> do you represent them? I'm not sure a mask is the best representation
> here, as it's difficult for a human to match up with a list of entries.
> 
> Additionally, the trip points don't have a logical contiguous numbering
> from zero, so how do the bits in the mask correspond to entries in the
> list? This seems to rely on the order that the subnodes are in, which
> AFAIK is not guaranteed. It would be far nicer to have an explicit
> linkage.


Do you mean some sort of list of trip points property inside binding
params node?

> 
>>
>>>
>>>> +                           limits = <
>>>> +                             /* lower-state            upper-state */
>>>> +                               1                       THERMAL_NO_LIMITS
>>>> +                               THERMAL_NO_LIMITS       THERMAL_NO_LIMITS
>>>> +                           >;
>>>> +                    };
>>>> +            };
>>>> +};
>>>> +
>>>> +sensor: adc@0xFFFF {
>>>> +       ...
>>>> +       monitored-zones = <&cpu_thermal 0>;
>>>> +};
>>>> +
>>>> +cpu@0 {
>>>> +       ...
>>>> +       cooling-zones = <&cpu_thermal>;
>>>> +};
>>>> +
>>>> +In the example above, the ADC sensor at address 0xFFFF is used to monitor
>>>> +the zone 'cpu_thermal' using its the sensor 0. The cpu@0 device is also linked
>>>> +to the same thermal zone 'cpu_thermal' as a cooling device.
>>>
>>> Huh? That seems to imply the the '0' in '<&cpu_thermal 0>' on the sensor
>>> node describes a property of the sensor rather than the thermal node,
>>> unless I've misunderstood?
>>>
>>
>> It is essentially which sensor id is used to monitor a specific zone. In
>> case of sensor IPs that feature several internal sensors, one needs to
>> have a way to describe which sensor monitors which zone. Example of this
>> type of IPs: lm90 (up to 3 sensors) and TI bandgap IP (can contain up to
>> 5 internal sensors). The probe happens for the IP device and not for the
>> internal sensors.
> 
> Which is exactly why this should be the opposite way round, with thermal
> zones referring to sensors in this fashion.
> 
> The way you're suggesting means that the phandle+cells specifier refers
> half to the consumer and half to the producer. Having thermal zones
> refer to sensors would make this refer solely to the producer (the
> sensor).
> 

Are you suggesting having inside thermal zone node:

	sensors = <&sensor0 Y>, ...., <&sensorN Z> ;

Where sensor0 and sensorN are sensor IPs nodes and Y and Z represent
their internal sensor instances?

>>
>>
>>>> +
>>>> +***************
>>>> +cpufreq-cooling
>>>> +***************
>>>> +
>>>> +The generic cpu cooling (freq clipping) can be loaded by the
>>>> +generic cpufreq-cpu0 driver in case the device tree node informs
>>>> +this need.
>>>> +
>>>> +In order to load the cpufreq cooling device, it is possible to
>>>> +inform that the cpu needs cooling by adding the list of thermal zones
>>>> +in the 'cooling-zones' property at the cpu0 phandle.
>>>
>>> This should be reworded so as to describe the binding rather than the
>>> Linux behaviour based on the binding.
>>
>> OK.
>>
>>>
>>>> +
>>>> +Example:
>>>> +       cpus {
>>>> +               cpu@0 {
>>>> +                       operating-points = <
>>>> +                               /* kHz    uV */
>>>> +                               800000  1313000
>>>> +                               1008000 1375000
>>>> +                       >;
>>>> +                       cooling-zones = <&cpu_thermal>;
>>>> +               };
>>>> +       ...
>>>> +       };
>>>> +
>>>> +The above will cause the cpufreq-cpu0 driver to understand that
>>>> +the cpu will need passive cooling and while probing that node it will
>>>> +also load the cpufreq cpu cooling device in that system.
>>>
>>> The above describe that the CPU is part of a cooling (thermal?) zone and
>>> requires cooling.
>>
>> That says the cpu participates in a thermal zone as a cooling
>> device/mechanism, thus cpu cooling (passive cooling) is required in
>> target system.
> 
> I think you need the rest of the nodes in this example. You don't show
> whether or not there's a cooling-device, so it's not clear that the CPU
> is required to be passively cooled...

The property states the cpu is used as cooling device for those thermal
zones in the list 'cooling-zones'

> 
>>
>>>
>>>> +
>>>> +However, be advised that this flag will not describe what needs to
>>>> +be done or how the cpufreq cooling device will be used. In order to
>>>> +accomplish this, one needs to write a phandle for a thermal zone, as
>>>> +described in the section 'thermal_zone'.
>>>
>>> The above already has a phandle to a thermal (cooling?) zone.
>>>
>>> Please choose either cooling zone or thermal zone, having the two names
>>> makes this more confusing than necessary.
>>
>> I see. Idea is to have thermal zone as a node. cooling-zone is just a
>> list of thermal zones that the referred device will be used as cooling
>> device.
> 
> While I can see a distinction, the nomenclature is horrendously
> confusing.


OK. I will try harder to improve it.

> 
>>
>>>
>>>> diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
>>>> index 7fb16bc..753f0dc 100644
>>>> --- a/drivers/thermal/Kconfig
>>>> +++ b/drivers/thermal/Kconfig
>>>> @@ -29,6 +29,19 @@ config THERMAL_HWMON
>>>>           Say 'Y' here if you want all thermal sensors to
>>>>           have hwmon sysfs interface too.
>>>>
>>>> +config THERMAL_OF
>>>> +       bool
>>>> +       prompt "APIs to parse thermal data out of device tree"
>>>> +       depends on OF
>>>> +       default y
>>>> +       help
>>>> +         This options provides helpers to add the support to
>>>> +         read and parse thermal data definitions out of the
>>>> +         device tree blob.
>>>> +
>>>> +         Say 'Y' here if you need to build thermal infrastructure
>>>> +         based on device tree.
>>>> +
>>>>  choice
>>>>         prompt "Default Thermal governor"
>>>>         default THERMAL_DEFAULT_GOV_STEP_WISE
>>>> diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
>>>> index 24cb894..eedb273 100644
>>>> --- a/drivers/thermal/Makefile
>>>> +++ b/drivers/thermal/Makefile
>>>> @@ -7,6 +7,7 @@ thermal_sys-y                   += thermal_core.o
>>>>
>>>>  # interface to/from other layers providing sensors
>>>>  thermal_sys-$(CONFIG_THERMAL_HWMON)            += thermal_hwmon.o
>>>> +thermal_sys-$(CONFIG_THERMAL_OF)               += thermal_dt.o
>>>>
>>>>  # governors
>>>>  thermal_sys-$(CONFIG_THERMAL_GOV_FAIR_SHARE)   += fair_share.o
>>>> diff --git a/drivers/thermal/thermal_dt.c b/drivers/thermal/thermal_dt.c
>>>> new file mode 100644
>>>> index 0000000..cc35485
>>>> --- /dev/null
>>>> +++ b/drivers/thermal/thermal_dt.c
>>>> @@ -0,0 +1,473 @@
>>>> +/*
>>>> + *  thermal_dt.c - Generic Thermal Management device tree support.
>>>> + *
>>>> + *  Copyright (C) 2013 Texas Instruments
>>>> + *  Copyright (C) 2013 Eduardo Valentin <eduardo.valentin@ti.com>
>>>> + *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>>>> + *
>>>> + *  This program is free software; you can redistribute it and/or modify
>>>> + *  it under the terms of the GNU General Public License as published by
>>>> + *  the Free Software Foundation; version 2 of the License.
>>>> + *
>>>> + *  This program is distributed in the hope that it will be useful, but
>>>> + *  WITHOUT ANY WARRANTY; without even the implied warranty of
>>>> + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>>>> + *  General Public License for more details.
>>>> + *
>>>> + *  You should have received a copy of the GNU General Public License along
>>>> + *  with this program; if not, write to the Free Software Foundation, Inc.,
>>>> + *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
>>>> + *
>>>> + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>>>> + */
>>>> +#include <linux/thermal.h>
>>>> +#include <linux/slab.h>
>>>> +#include <linux/types.h>
>>>> +#include <linux/of_device.h>
>>>> +#include <linux/of_platform.h>
>>>> +#include <linux/err.h>
>>>> +#include <linux/export.h>
>>>> +#include <linux/string.h>
>>>> +
>>>> +struct __thermal_bind_params {
>>>> +       char cooling_device[THERMAL_NAME_LENGTH];
>>>> +};
>>>> +
>>>> +static
>>>> +int thermal_of_match(struct thermal_zone_device *tz,
>>>> +                    struct thermal_cooling_device *cdev);
>>>> +
>>>> +static int thermal_of_populate_bind_params(struct device *dev,
>>>> +                                          struct device_node *node,
>>>> +                                          struct __thermal_bind_params *__tbp,
>>>> +                                          struct thermal_bind_params *tbp,
>>>> +                                          int ntrips)
>>>> +{
>>>> +       const char *cdev_name;
>>>> +       u32 *limits;
>>>> +       int ret;
>>>> +       u32 prop;
>>>> +
>>>> +       ret = of_property_read_u32(node, "weight", &prop);
>>>> +       if (ret < 0) {
>>>> +               dev_err(dev, "missing weight property\n");
>>>> +               return ret;
>>>> +       }
>>>> +       tbp->weight = prop;
>>>> +
>>>> +       ret = of_property_read_u32(node, "mask", &prop);
>>>> +       if (ret < 0) {
>>>> +               dev_err(dev, "missing mask property\n");
>>>> +               return ret;
>>>> +       }
>>>> +       tbp->trip_mask = prop;
>>>> +
>>>> +       /* this will allow us to bind with cooling devices */
>>>> +       tbp->match = thermal_of_match;
>>>> +
>>>> +       ret = of_property_read_string(node, "cooling_device", &cdev_name);
>>>> +       if (ret < 0) {
>>>> +               dev_err(dev, "missing cooling_device property\n");
>>>> +               return ret;
>>>> +       }
>>>> +       strncpy(__tbp->cooling_device, cdev_name,
>>>> +               sizeof(__tbp->cooling_device));
>>>> +
>>>> +       limits = kzalloc(ntrips * sizeof(*limits) * 2, GFP_KERNEL);
>>>
>>> Why do you use kzalloc here, but devm_kzalloc elsewhere? That'll lead to
>>> problems as the driver gets refactored over time.
>>
>> Because this memory is used only  within this function and thus released
>> at the bottom of it.
>>
>>>
>>>> +       if (!limits) {
>>>> +               dev_err(dev, "not enough mem for reading limits\n");
>>>> +               return -ENOMEM;
>>>> +       }
>>>> +       ret = of_property_read_u32_array(node, "limits", limits, 2 * ntrips);
>>>> +       if (!ret) {
>>>> +               int i = ntrips;
>>>> +
>>>> +               tbp->binding_limits = devm_kzalloc(dev,
>>>> +                                                  ntrips * 2 *
>>>> +                                                  sizeof(*tbp->binding_limits),
>>>> +                                                  GFP_KERNEL);
>>>> +               if (!tbp->binding_limits) {
>>>> +                       dev_err(dev, "not enough mem for storing limits\n");
>>>> +                       return -ENOMEM;
>>>> +               }
>>>> +               while (i--)
>>>> +                       tbp->binding_limits[i] = limits[i];
>>>> +       }
>>>> +       kfree(limits);
>>
>> here.
> 
> I saw that, I did say that this may lead to problems in future if the
> function's reorganised, not now. :)

Ahh.. OK. I just didnt want o let the memory be managed and freed only
when the struct device is release.

> 
>>
>>>> +
>>>> +       return 0;
>>>
>>> What if you failed to read the array? Surely you should return an error?
>>
>> Attempting to make this property not mandatory.
> 
> That wasn't clear from the binding, and now I've re-read it, I'm still
> not entirely clear on what the limits represent, and why you may have
> multiple sets of pairs.

Because you may assign cooling state limits to specific trip points,
e.g., a fan with 5 different speeds would operate from speed 0 to 2 in
the first trip point, while from speed 3 to 4 on last trip point.

> 
>>
>>>
>>>> +}
>>>> +
>>>> +struct __thermal_trip {
>>>> +       unsigned long int temperature;
>>>> +       unsigned long int hysteresis;
>>>> +       enum thermal_trip_type type;
>>>> +};
>>>> +
>>>> +static
>>>> +int thermal_of_populate_trip(struct device *dev,
>>>> +                            struct device_node *node,
>>>> +                            struct __thermal_trip *trip)
>>>> +{
>>>> +       int ret;
>>>> +       int prop;
>>>> +
>>>> +       ret = of_property_read_u32(node, "temperature", &prop);
>>>> +       if (ret < 0) {
>>>> +               dev_err(dev, "missing temperature property\n");
>>>> +               return ret;
>>>> +       }
>>>> +       trip->temperature = prop;
>>>> +
>>>> +       ret = of_property_read_u32(node, "hysteresis", &prop);
>>>> +       if (ret < 0) {
>>>> +               dev_err(dev, "missing hysteresis property\n");
>>>> +               return ret;
>>>> +       }
>>>> +       trip->hysteresis = prop;
>>>> +
>>>> +       ret = of_property_read_u32(node, "type", &prop);
>>>> +       if (ret < 0) {
>>>> +               dev_err(dev, "missing type property\n");
>>>> +               return ret;
>>>> +       }
>>>> +       trip->type = prop;
>>>
>>> This will require sanity checking.
>>
>> OK.
>>
>>>
>>>> +
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +struct __thermal_zone_device {
>>>> +       enum thermal_device_mode mode;
>>>> +       int passive_delay;
>>>> +       int polling_delay;
>>>> +       int mask;
>>>> +       int ntrips;
>>>> +       char type[THERMAL_NAME_LENGTH];
>>>> +       struct __thermal_trip *trips;
>>>> +       struct __thermal_bind_params *bind_params;
>>>> +       struct thermal_bind_params *tbps;
>>>> +       struct thermal_zone_params zone_params;
>>>> +       int (*get_temp)(void *, unsigned long *);
>>>> +       void *devdata;
>>>> +};
>>>> +
>>>> +static struct __thermal_zone_device *
>>>> +thermal_of_build_thermal_zone(struct device *dev, struct device_node *node)
>>>> +{
>>>> +       struct device_node *child, *gchild;
>>>> +       struct __thermal_zone_device *tz;
>>>> +       int ret, i;
>>>> +       u32 prop;
>>>> +
>>>> +       if (!node) {
>>>> +               dev_err(dev, "no thermal zone node\n");
>>>> +               return ERR_PTR(-EINVAL);
>>>> +       }
>>>> +
>>>> +       tz = devm_kzalloc(dev, sizeof(*tz), GFP_KERNEL);
>>>> +       if (!tz) {
>>>> +               dev_err(dev, "not enough memory for thermal of zone\n");
>>>> +               return ERR_PTR(-ENOMEM);
>>>> +       }
>>>> +
>>>> +       ret = of_property_read_u32(node, "passive_delay", &prop);
>>>> +       if (ret < 0) {
>>>> +               dev_err(dev, "missing passive_delay property\n");
>>>> +               return ERR_PTR(ret);
>>>> +       }
>>>> +       tz->passive_delay = prop;
>>>> +
>>>> +       ret = of_property_read_u32(node, "polling_delay", &prop);
>>>> +       if (ret < 0) {
>>>> +               dev_err(dev, "missing polling_delay property\n");
>>>> +               return ERR_PTR(ret);
>>>> +       }
>>>> +       tz->polling_delay = prop;
>>>> +
>>>> +       ret = of_property_read_u32(node, "mask", &prop);
>>>> +       if (ret < 0) {
>>>> +               dev_err(dev, "missing mask property\n");
>>>> +               return ERR_PTR(ret);
>>>> +       }
>>>> +       tz->mask = prop;
>>>> +
>>>> +       /* assume node name as our zone type */
>>>> +       strncpy(tz->type, node->name, sizeof(tz->type));
>>>> +
>>>> +       /* default policy */
>>>> +       strncpy(tz->zone_params.governor_name, "step_wise",
>>>> +               sizeof(tz->zone_params.governor_name));
>>>> +
>>>> +       /* trips */
>>>> +       child = of_find_node_by_name(node, "trips");
>>>
>>> That might not be a child node, as of_find_node_by_name walks over the
>>> list of all nodes. Use of_get_child_by_name.
>>
>> Right! This is a bug.
>>
>>>
>>>> +
>>>> +       /* No trips provided */
>>>> +       if (!child)
>>>> +               goto finish;
>>>> +
>>>> +       tz->ntrips = of_get_child_count(child);
>>>> +       tz->trips = devm_kzalloc(dev, tz->ntrips * sizeof(*tz->trips),
>>>> +                                GFP_KERNEL);
>>>> +       if (!tz->trips)
>>>> +               return ERR_PTR(-ENOMEM);
>>>> +       i = 0;
>>>> +       for_each_child_of_node(child, gchild)
>>>> +               thermal_of_populate_trip(dev, gchild, &tz->trips[i++]);
>>>
>>> What if a child node was not a valid trip node? It seems
>>> thermal_of_populate_trip returns errors you're ignoring.
>>
>> OK. Adding proper treatment.
>>
>>>
>>>> +
>>>> +       /* bind_params */
>>>> +       child = of_find_node_by_name(node, "bind_params");
>>>
>>> Another of_get_child_by_name candidate.
>>
>> OK.
>>
>>>
>>>> +
>>>> +       /* No binding info */
>>>> +       if (!child)
>>>> +               goto finish;
>>>> +
>>>> +       tz->zone_params.num_tbps = of_get_child_count(child);
>>>> +       tz->bind_params = devm_kzalloc(dev,
>>>> +                                      tz->zone_params.num_tbps *
>>>> +                                               sizeof(*tz->bind_params),
>>>> +                                      GFP_KERNEL);
>>>> +       if (!tz->bind_params)
>>>> +               return ERR_PTR(-ENOMEM);
>>>> +       tz->zone_params.tbp = devm_kzalloc(dev,
>>>> +                                          tz->zone_params.num_tbps *
>>>> +                                               sizeof(*tz->zone_params.tbp),
>>>> +                                          GFP_KERNEL);
>>>> +       if (!tz->zone_params.tbp)
>>>> +               return ERR_PTR(-ENOMEM);
>>>> +       i = 0;
>>>> +       for_each_child_of_node(child, gchild) {
>>>> +               thermal_of_populate_bind_params(dev, gchild,
>>>> +                                               &tz->bind_params[i],
>>>> +                                               &tz->zone_params.tbp[i],
>>>> +                                               tz->ntrips);
>>>
>>> Similarly, you're ignoring error conditions here. What if a bind_params
>>> node was malformed?
>>
>>
>> Adding proper error handling.
>>
>>>
>>>> +               i++;
>>>> +       }
>>>> +
>>>> +finish:
>>>> +       tz->mode = THERMAL_DEVICE_ENABLED;
>>>> +
>>>> +       return tz;
>>>> +}
>>>> +
>>>> +static
>>>> +int thermal_of_match(struct thermal_zone_device *tz,
>>>> +                    struct thermal_cooling_device *cdev)
>>>> +{
>>>> +       struct __thermal_zone_device *data = tz->devdata;
>>>> +       int i;
>>>> +
>>>> +       for (i = 0; i < data->zone_params.num_tbps; i++) {
>>>> +               if (!strncmp(data->bind_params[i].cooling_device,
>>>> +                            cdev->type,
>>>> +                            strlen(data->bind_params[i].cooling_device)) &&
>>>> +                   (data->zone_params.tbp[i].trip_mask & (1 << i)))
>>>> +                       return 0;
>>>> +       }
>>>> +
>>>> +       return -EINVAL;
>>>> +}
>>>
>>> I'm not keen on binding to cooling devices using a string, as suddenly a
>>> name to allow humans to inspect the system is turned into an ABI.
>>
>> OK. We need to align on how we describe the binding then.
> 
> Definitely. We need to ensure that we fully define the relationship too
> cooling devices, and don't suddenly expose some piece of internal Linux
> infrastructure to the world.
> 

Yeah, agreed, any suggestions?

>>
>>>
>>>> +
>>>> +static
>>>> +int of_thermal_get_temp(struct thermal_zone_device *tz,
>>>> +                       unsigned long *temp)
>>>> +{
>>>> +       struct __thermal_zone_device *data = tz->devdata;
>>>> +
>>>> +       return data->get_temp(data->devdata, temp);
>>>> +}
>>>> +
>>>> +static
>>>> +int of_thermal_get_mode(struct thermal_zone_device *tz,
>>>> +                       enum thermal_device_mode *mode)
>>>> +{
>>>> +       struct __thermal_zone_device *data = tz->devdata;
>>>> +
>>>> +       *mode = data->mode;
>>>> +
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +static
>>>> +int of_thermal_set_mode(struct thermal_zone_device *tz,
>>>> +                       enum thermal_device_mode mode)
>>>> +{
>>>> +       struct __thermal_zone_device *data = tz->devdata;
>>>> +
>>>> +       mutex_lock(&tz->lock);
>>>> +
>>>> +       if (mode == THERMAL_DEVICE_ENABLED)
>>>> +               tz->polling_delay = data->polling_delay;
>>>> +       else
>>>> +               tz->polling_delay = 0;
>>>> +
>>>> +       mutex_unlock(&tz->lock);
>>>> +
>>>> +       data->mode = mode;
>>>> +       thermal_zone_device_update(tz);
>>>> +
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +static
>>>> +int of_thermal_get_trip_type(struct thermal_zone_device *tz, int trip,
>>>> +                            enum thermal_trip_type *type)
>>>> +{
>>>> +       struct __thermal_zone_device *data = tz->devdata;
>>>> +
>>>> +       if (trip >= data->ntrips || trip < 0)
>>>> +               return -EDOM;
>>>
>>> It's far more common to use -EINVAL.
>>
>> hmm.. OK.
>>
>>>
>>>> +
>>>> +       *type = data->trips[trip].type;
>>>> +
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +static
>>>> +int of_thermal_get_trip_temp(struct thermal_zone_device *tz, int trip,
>>>> +                            unsigned long *temp)
>>>> +{
>>>> +       struct __thermal_zone_device *data = tz->devdata;
>>>> +
>>>> +       if (trip >= data->ntrips || trip < 0)
>>>> +               return -EDOM;
>>>> +
>>>> +       *temp = data->trips[trip].temperature;
>>>> +
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +static
>>>> +int of_thermal_set_trip_temp(struct thermal_zone_device *tz, int trip,
>>>> +                            unsigned long temp)
>>>> +{
>>>> +       struct __thermal_zone_device *data = tz->devdata;
>>>> +
>>>> +       if (trip >= data->ntrips || trip < 0)
>>>> +               return -EDOM;
>>>> +
>>>> +       /* thermal fw should take care of data->mask & (1 << trip) */
>>>> +       data->trips[trip].temperature = temp;
>>>> +
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +static
>>>> +int of_thermal_get_trip_hyst(struct thermal_zone_device *tz, int trip,
>>>> +                            unsigned long *hyst)
>>>> +{
>>>> +       struct __thermal_zone_device *data = tz->devdata;
>>>> +
>>>> +       if (trip >= data->ntrips || trip < 0)
>>>> +               return -EDOM;
>>>> +
>>>> +       *hyst = data->trips[trip].hysteresis;
>>>> +
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +static
>>>> +int of_thermal_set_trip_hyst(struct thermal_zone_device *tz, int trip,
>>>> +                            unsigned long hyst)
>>>> +{
>>>> +       struct __thermal_zone_device *data = tz->devdata;
>>>> +
>>>> +       if (trip >= data->ntrips || trip < 0)
>>>> +               return -EDOM;
>>>> +
>>>> +       /* thermal fw should take care of data->mask & (1 << trip) */
>>>
>>> Could you elaborate on that comment?
>>
>> In  case the trip is not assigned to be writable, this function won't be
>> called.
> 
> Ah. I misunderstood "fw" as "firmware", rather than "framework", and got
> confused. It would be nice if you could expand "fw" to make this
> clearer. :)

Sorry for that :-)

> 
> Thanks,
> Mark.
> 
> [1] http://en.wikipedia.org/wiki/Black-body_radiation
> 
> 


-- 
You have got to be excited about what you are doing. (L. Lamport)

Eduardo Valentin


[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 295 bytes --]

[-- Attachment #2: Type: text/plain, Size: 153 bytes --]

_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

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

* Re: [RFC PATCH 02/14] drivers: thermal: introduce device tree parser
  2013-08-27 18:17           ` [lm-sensors] " Eduardo Valentin
@ 2013-08-29 23:19             ` Eduardo Valentin
  -1 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-29 23:19 UTC (permalink / raw)
  To: Eduardo Valentin
  Cc: Mark Rutland, swarren, Pawel Moll, ian.campbell, grant.likely,
	rob.herring, linux, rui.zhang, wni, durgadoss.r, linux-pm,
	devicetree, lm-sensors, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 7361 bytes --]

Mark, Pawel and Stephen,


On 27-08-2013 14:17, Eduardo Valentin wrote:
> On 27-08-2013 12:23, Mark Rutland wrote:
>> On Tue, Aug 27, 2013 at 02:44:40PM +0100, Eduardo Valentin wrote:
>>> Hello Mark,

<cut>

I believe now we need to align on thermal bindings, before I propose
next version of this series. So, following the discussions on this
thread, I believe a typical CPU thermal zone would look like the following:
+ #include <dt-bindings/thermal/thermal.h>
+
+ cpu_thermal: cpu_thermal {
+         passive-delay = <250>; /* milliseconds */
+         polling-delay = <1000>; /* milliseconds */
+                 /*
+                  * sensor       ID
+                  */
+         sensors = <&bandgap0     0>;
+                         /*
+                          * cooling
+                          * device       Usage   Trip            lower
bound             upper bound
+                          */
+         cooling-devices = <&cpu0        100     &cpu-alert
THERMAL_NO_LIMITS        THERMAL_NO_LIMITS>;
+         trips {
+                 cpu-alert: cpu-alert {
+                         temperature = <100000>; /* milliCelsius */
+                         hysteresis = <2000>; /* milliCelsius */
+                         type = <THERMAL_TRIP_PASSIVE>;
+                 };
+                 cpu-crit: cpu-crit {
+                         temperature = <125000>; /* milliCelsius */
+                         hysteresis = <2000>; /* milliCelsius */
+                         type = <THERMAL_TRIP_CRITICAL>;
+                 };
+         };
+ };

*Note: THERMAL_NO_LIMIT means, it will be using the cooling device
minimum and maximum limits.

Couple of comments.
1. I am keeping the pooling intervals. A possible alternative way to
describe that would be specifying the maximum dT/dt. Essentially because
I am still convinced that this is part of hw specs.

2. The above follows your suggestion to use consumer pointing to
producers. Although, I still need to figure out how this could be
implemented for Linux. But I think that is another story, at least for
now. We need to first align on the DT binding itself.

3. The link from cooling device specification to trip points, from my
perspective, should be enough, and thus we shall not need the thermal
cells and size for trip points, as you proposed. Let me know what you think.

Below is another example, on a more complex scenario, board specific
case (hypothetical, just for exemplification):

+ #include <dt-bindings/thermal/thermal.h>
+
+ board_thermal: board_thermal {
+         passive-delay = <1000>; /* milliseconds */
+         polling-delay = <2500>; /* milliseconds */
+                 /*
+                  * sensor       ID
+                  */
+         sensors = <&adc-dummy     0>,
+		    <&adc-dummy     1>,
+		    <&adc-dymmy     2>;
+                         /*
+                          * cooling
+                          * device       Usage   Trip		lower	upper
+                          */
+         cooling-devices = <&cpu0       75     &cpu-trip	0      2>,
+			    <&gpu0       40     &gpu-trip	0      2>;
+			    <&lcd0       25     &lcd-trip	5      10>;
+         trips {
+                 cpu-trip: cpu-trip {
+                         temperature = <60000>; /* milliCelsius */
+                         hysteresis = <2000>; /* milliCelsius */
+                         type = <THERMAL_TRIP_PASSIVE>;
+                 };
+                 gpu-trip: gpu-trip {
+                         temperature = <55000>; /* milliCelsius */
+                         hysteresis = <2000>; /* milliCelsius */
+                         type = <THERMAL_TRIP_PASSIVE>;
+                 }
+                 lcd-trip: lcp-trip {
+                         temperature = <53000>; /* milliCelsius */
+                         hysteresis = <2000>; /* milliCelsius */
+                         type = <THERMAL_TRIP_PASSIVE>;
+                 };
+                 crit-trip: crit-trip {
+                         temperature = <68000>; /* milliCelsius */
+                         hysteresis = <2000>; /* milliCelsius */
+                         type = <THERMAL_TRIP_CRITICAL>;
+                 };
+         };
+ };

Now writing the above example, one might want to have a way to say the
sensor correlation equation.

Another example:
+ #include <dt-bindings/thermal/thermal.h>
+
+ dsp_thermal: dsp_thermal {
+         passive-delay = <250>; /* milliseconds */
+         polling-delay = <1000>; /* milliseconds */
+                 /*
+                  * sensor       ID
+                  */
+         sensors = <&bandgap0     1>;
+                         /*
+                          * cooling
+                          * device       Usage   Trip            lower
bound             upper bound
+                          */
+         cooling-devices = <&dsp0        100     &dsp-alert
THERMAL_NO_LIMIT        THERMAL_NO_LIMIT>;
+         trips {
+                 dsp-alert: dsp-alert {
+                         temperature = <100000>; /* milliCelsius */
+                         hysteresis = <2000>; /* milliCelsius */
+                         type = <THERMAL_TRIP_PASSIVE>;
+                 };
+                 dsp-crit: cdsp-crit {
+                         temperature = <125000>; /* milliCelsius */
+                         hysteresis = <2000>; /* milliCelsius */
+                         type = <THERMAL_TRIP_CRITICAL>;
+                 };
+         };
+ };
+
+ gpu_thermal: gpu_thermal {
+         passive-delay = <500>; /* milliseconds */
+         polling-delay = <1000>; /* milliseconds */
+                 /*
+                  * sensor       ID
+                  */
+         sensors = <&bandgap0     2>;
+                         /*
+                          * cooling
+                          * device       Usage   Trip            lower
bound             upper bound
+                          */
+         cooling-devices = <&gpu0        100     &gpu-alert
THERMAL_NO_LIMIT        THERMAL_NO_LIMIT>;
+         trips {
+                 gpu-alert: gpu-alert {
+                         temperature = <100000>; /* milliCelsius */
+                         hysteresis = <2000>; /* milliCelsius */
+                         type = <THERMAL_TRIP_PASSIVE>;
+                 };
+                 gpu-crit: gpu-crit {
+                         temperature = <125000>; /* milliCelsius */
+                         hysteresis = <2000>; /* milliCelsius */
+                         type = <THERMAL_TRIP_CRITICAL>;
+                 };
+         };
+ };


Wei, I think the above would cover for the IPs with multiple internal
sensors cases you were looking for, right?

Durga, please also check if I am missing something to cover for your
plans to, in case you will be using DT to describe your HW.

Anyways, Mark and Pawel, let me know if I missed something from our
discussion. I believe the above bindings would look more like regular
standard DT bindings. And also they should be now slim enough, without
Linux implementation details and also without policies.

> 
> 


-- 
You have got to be excited about what you are doing. (L. Lamport)

Eduardo Valentin


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 295 bytes --]

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

* Re: [lm-sensors] [RFC PATCH 02/14] drivers: thermal: introduce device tree parser
@ 2013-08-29 23:19             ` Eduardo Valentin
  0 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-08-29 23:19 UTC (permalink / raw)
  To: Eduardo Valentin
  Cc: Mark Rutland, swarren, Pawel Moll, ian.campbell, grant.likely,
	rob.herring, linux, rui.zhang, wni, durgadoss.r, linux-pm,
	devicetree, lm-sensors, linux-kernel


[-- Attachment #1.1: Type: text/plain, Size: 7361 bytes --]

Mark, Pawel and Stephen,


On 27-08-2013 14:17, Eduardo Valentin wrote:
> On 27-08-2013 12:23, Mark Rutland wrote:
>> On Tue, Aug 27, 2013 at 02:44:40PM +0100, Eduardo Valentin wrote:
>>> Hello Mark,

<cut>

I believe now we need to align on thermal bindings, before I propose
next version of this series. So, following the discussions on this
thread, I believe a typical CPU thermal zone would look like the following:
+ #include <dt-bindings/thermal/thermal.h>
+
+ cpu_thermal: cpu_thermal {
+         passive-delay = <250>; /* milliseconds */
+         polling-delay = <1000>; /* milliseconds */
+                 /*
+                  * sensor       ID
+                  */
+         sensors = <&bandgap0     0>;
+                         /*
+                          * cooling
+                          * device       Usage   Trip            lower
bound             upper bound
+                          */
+         cooling-devices = <&cpu0        100     &cpu-alert
THERMAL_NO_LIMITS        THERMAL_NO_LIMITS>;
+         trips {
+                 cpu-alert: cpu-alert {
+                         temperature = <100000>; /* milliCelsius */
+                         hysteresis = <2000>; /* milliCelsius */
+                         type = <THERMAL_TRIP_PASSIVE>;
+                 };
+                 cpu-crit: cpu-crit {
+                         temperature = <125000>; /* milliCelsius */
+                         hysteresis = <2000>; /* milliCelsius */
+                         type = <THERMAL_TRIP_CRITICAL>;
+                 };
+         };
+ };

*Note: THERMAL_NO_LIMIT means, it will be using the cooling device
minimum and maximum limits.

Couple of comments.
1. I am keeping the pooling intervals. A possible alternative way to
describe that would be specifying the maximum dT/dt. Essentially because
I am still convinced that this is part of hw specs.

2. The above follows your suggestion to use consumer pointing to
producers. Although, I still need to figure out how this could be
implemented for Linux. But I think that is another story, at least for
now. We need to first align on the DT binding itself.

3. The link from cooling device specification to trip points, from my
perspective, should be enough, and thus we shall not need the thermal
cells and size for trip points, as you proposed. Let me know what you think.

Below is another example, on a more complex scenario, board specific
case (hypothetical, just for exemplification):

+ #include <dt-bindings/thermal/thermal.h>
+
+ board_thermal: board_thermal {
+         passive-delay = <1000>; /* milliseconds */
+         polling-delay = <2500>; /* milliseconds */
+                 /*
+                  * sensor       ID
+                  */
+         sensors = <&adc-dummy     0>,
+		    <&adc-dummy     1>,
+		    <&adc-dymmy     2>;
+                         /*
+                          * cooling
+                          * device       Usage   Trip		lower	upper
+                          */
+         cooling-devices = <&cpu0       75     &cpu-trip	0      2>,
+			    <&gpu0       40     &gpu-trip	0      2>;
+			    <&lcd0       25     &lcd-trip	5      10>;
+         trips {
+                 cpu-trip: cpu-trip {
+                         temperature = <60000>; /* milliCelsius */
+                         hysteresis = <2000>; /* milliCelsius */
+                         type = <THERMAL_TRIP_PASSIVE>;
+                 };
+                 gpu-trip: gpu-trip {
+                         temperature = <55000>; /* milliCelsius */
+                         hysteresis = <2000>; /* milliCelsius */
+                         type = <THERMAL_TRIP_PASSIVE>;
+                 }
+                 lcd-trip: lcp-trip {
+                         temperature = <53000>; /* milliCelsius */
+                         hysteresis = <2000>; /* milliCelsius */
+                         type = <THERMAL_TRIP_PASSIVE>;
+                 };
+                 crit-trip: crit-trip {
+                         temperature = <68000>; /* milliCelsius */
+                         hysteresis = <2000>; /* milliCelsius */
+                         type = <THERMAL_TRIP_CRITICAL>;
+                 };
+         };
+ };

Now writing the above example, one might want to have a way to say the
sensor correlation equation.

Another example:
+ #include <dt-bindings/thermal/thermal.h>
+
+ dsp_thermal: dsp_thermal {
+         passive-delay = <250>; /* milliseconds */
+         polling-delay = <1000>; /* milliseconds */
+                 /*
+                  * sensor       ID
+                  */
+         sensors = <&bandgap0     1>;
+                         /*
+                          * cooling
+                          * device       Usage   Trip            lower
bound             upper bound
+                          */
+         cooling-devices = <&dsp0        100     &dsp-alert
THERMAL_NO_LIMIT        THERMAL_NO_LIMIT>;
+         trips {
+                 dsp-alert: dsp-alert {
+                         temperature = <100000>; /* milliCelsius */
+                         hysteresis = <2000>; /* milliCelsius */
+                         type = <THERMAL_TRIP_PASSIVE>;
+                 };
+                 dsp-crit: cdsp-crit {
+                         temperature = <125000>; /* milliCelsius */
+                         hysteresis = <2000>; /* milliCelsius */
+                         type = <THERMAL_TRIP_CRITICAL>;
+                 };
+         };
+ };
+
+ gpu_thermal: gpu_thermal {
+         passive-delay = <500>; /* milliseconds */
+         polling-delay = <1000>; /* milliseconds */
+                 /*
+                  * sensor       ID
+                  */
+         sensors = <&bandgap0     2>;
+                         /*
+                          * cooling
+                          * device       Usage   Trip            lower
bound             upper bound
+                          */
+         cooling-devices = <&gpu0        100     &gpu-alert
THERMAL_NO_LIMIT        THERMAL_NO_LIMIT>;
+         trips {
+                 gpu-alert: gpu-alert {
+                         temperature = <100000>; /* milliCelsius */
+                         hysteresis = <2000>; /* milliCelsius */
+                         type = <THERMAL_TRIP_PASSIVE>;
+                 };
+                 gpu-crit: gpu-crit {
+                         temperature = <125000>; /* milliCelsius */
+                         hysteresis = <2000>; /* milliCelsius */
+                         type = <THERMAL_TRIP_CRITICAL>;
+                 };
+         };
+ };


Wei, I think the above would cover for the IPs with multiple internal
sensors cases you were looking for, right?

Durga, please also check if I am missing something to cover for your
plans to, in case you will be using DT to describe your HW.

Anyways, Mark and Pawel, let me know if I missed something from our
discussion. I believe the above bindings would look more like regular
standard DT bindings. And also they should be now slim enough, without
Linux implementation details and also without policies.

> 
> 


-- 
You have got to be excited about what you are doing. (L. Lamport)

Eduardo Valentin


[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 295 bytes --]

[-- Attachment #2: Type: text/plain, Size: 153 bytes --]

_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

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

* Re: [RFC PATCH 02/14] drivers: thermal: introduce device tree parser
  2013-08-29 23:19             ` [lm-sensors] " Eduardo Valentin
@ 2013-09-02  8:14               ` Wei Ni
  -1 siblings, 0 replies; 100+ messages in thread
From: Wei Ni @ 2013-09-02  8:14 UTC (permalink / raw)
  To: Eduardo Valentin
  Cc: Mark Rutland, swarren, Pawel Moll, ian.campbell, grant.likely,
	rob.herring, linux, rui.zhang, durgadoss.r, linux-pm, devicetree,
	lm-sensors, linux-kernel

On 08/30/2013 07:19 AM, Eduardo Valentin wrote:
> * PGP Signed: 08/29/2013 at 04:19:46 PM
> 
> Mark, Pawel and Stephen,
> 
> 
> On 27-08-2013 14:17, Eduardo Valentin wrote:
>> On 27-08-2013 12:23, Mark Rutland wrote:
>>> On Tue, Aug 27, 2013 at 02:44:40PM +0100, Eduardo Valentin wrote:
>>>> Hello Mark,
> 
> <cut>
> 
> I believe now we need to align on thermal bindings, before I propose
> next version of this series. So, following the discussions on this
> thread, I believe a typical CPU thermal zone would look like the following:
> + #include <dt-bindings/thermal/thermal.h>
> +
> + cpu_thermal: cpu_thermal {
> +         passive-delay = <250>; /* milliseconds */
> +         polling-delay = <1000>; /* milliseconds */
> +                 /*
> +                  * sensor       ID
> +                  */
> +         sensors = <&bandgap0     0>;
> +                         /*
> +                          * cooling
> +                          * device       Usage   Trip            lower
> bound             upper bound
> +                          */
> +         cooling-devices = <&cpu0        100     &cpu-alert
> THERMAL_NO_LIMITS        THERMAL_NO_LIMITS>;
> +         trips {
> +                 cpu-alert: cpu-alert {
> +                         temperature = <100000>; /* milliCelsius */
> +                         hysteresis = <2000>; /* milliCelsius */
> +                         type = <THERMAL_TRIP_PASSIVE>;
> +                 };
> +                 cpu-crit: cpu-crit {
> +                         temperature = <125000>; /* milliCelsius */
> +                         hysteresis = <2000>; /* milliCelsius */
> +                         type = <THERMAL_TRIP_CRITICAL>;
> +                 };
> +         };
> + };
> 
> *Note: THERMAL_NO_LIMIT means, it will be using the cooling device
> minimum and maximum limits.
> 
> Couple of comments.
> 1. I am keeping the pooling intervals. A possible alternative way to
> describe that would be specifying the maximum dT/dt. Essentially because
> I am still convinced that this is part of hw specs.
> 
> 2. The above follows your suggestion to use consumer pointing to
> producers. Although, I still need to figure out how this could be
> implemented for Linux. But I think that is another story, at least for
> now. We need to first align on the DT binding itself.
> 
> 3. The link from cooling device specification to trip points, from my
> perspective, should be enough, and thus we shall not need the thermal
> cells and size for trip points, as you proposed. Let me know what you think.
> 
> Below is another example, on a more complex scenario, board specific
> case (hypothetical, just for exemplification):
> 
> + #include <dt-bindings/thermal/thermal.h>
> +
> + board_thermal: board_thermal {
> +         passive-delay = <1000>; /* milliseconds */
> +         polling-delay = <2500>; /* milliseconds */
> +                 /*
> +                  * sensor       ID
> +                  */
> +         sensors = <&adc-dummy     0>,
> +		    <&adc-dummy     1>,
> +		    <&adc-dymmy     2>;
> +                         /*
> +                          * cooling
> +                          * device       Usage   Trip		lower	upper
> +                          */
> +         cooling-devices = <&cpu0       75     &cpu-trip	0      2>,
> +			    <&gpu0       40     &gpu-trip	0      2>;
> +			    <&lcd0       25     &lcd-trip	5      10>;
> +         trips {
> +                 cpu-trip: cpu-trip {
> +                         temperature = <60000>; /* milliCelsius */
> +                         hysteresis = <2000>; /* milliCelsius */
> +                         type = <THERMAL_TRIP_PASSIVE>;
> +                 };
> +                 gpu-trip: gpu-trip {
> +                         temperature = <55000>; /* milliCelsius */
> +                         hysteresis = <2000>; /* milliCelsius */
> +                         type = <THERMAL_TRIP_PASSIVE>;
> +                 }
> +                 lcd-trip: lcp-trip {
> +                         temperature = <53000>; /* milliCelsius */
> +                         hysteresis = <2000>; /* milliCelsius */
> +                         type = <THERMAL_TRIP_PASSIVE>;
> +                 };
> +                 crit-trip: crit-trip {
> +                         temperature = <68000>; /* milliCelsius */
> +                         hysteresis = <2000>; /* milliCelsius */
> +                         type = <THERMAL_TRIP_CRITICAL>;
> +                 };
> +         };
> + };
> 
> Now writing the above example, one might want to have a way to say the
> sensor correlation equation.
> 
> Another example:
> + #include <dt-bindings/thermal/thermal.h>
> +
> + dsp_thermal: dsp_thermal {
> +         passive-delay = <250>; /* milliseconds */
> +         polling-delay = <1000>; /* milliseconds */
> +                 /*
> +                  * sensor       ID
> +                  */
> +         sensors = <&bandgap0     1>;
> +                         /*
> +                          * cooling
> +                          * device       Usage   Trip            lower
> bound             upper bound
> +                          */
> +         cooling-devices = <&dsp0        100     &dsp-alert
> THERMAL_NO_LIMIT        THERMAL_NO_LIMIT>;
> +         trips {
> +                 dsp-alert: dsp-alert {
> +                         temperature = <100000>; /* milliCelsius */
> +                         hysteresis = <2000>; /* milliCelsius */
> +                         type = <THERMAL_TRIP_PASSIVE>;
> +                 };
> +                 dsp-crit: cdsp-crit {
> +                         temperature = <125000>; /* milliCelsius */
> +                         hysteresis = <2000>; /* milliCelsius */
> +                         type = <THERMAL_TRIP_CRITICAL>;
> +                 };
> +         };
> + };
> +
> + gpu_thermal: gpu_thermal {
> +         passive-delay = <500>; /* milliseconds */
> +         polling-delay = <1000>; /* milliseconds */
> +                 /*
> +                  * sensor       ID
> +                  */
> +         sensors = <&bandgap0     2>;
> +                         /*
> +                          * cooling
> +                          * device       Usage   Trip            lower
> bound             upper bound
> +                          */
> +         cooling-devices = <&gpu0        100     &gpu-alert
> THERMAL_NO_LIMIT        THERMAL_NO_LIMIT>;
> +         trips {
> +                 gpu-alert: gpu-alert {
> +                         temperature = <100000>; /* milliCelsius */
> +                         hysteresis = <2000>; /* milliCelsius */
> +                         type = <THERMAL_TRIP_PASSIVE>;
> +                 };
> +                 gpu-crit: gpu-crit {
> +                         temperature = <125000>; /* milliCelsius */
> +                         hysteresis = <2000>; /* milliCelsius */
> +                         type = <THERMAL_TRIP_CRITICAL>;
> +                 };
> +         };
> + };
> 
> 
> Wei, I think the above would cover for the IPs with multiple internal
> sensors cases you were looking for, right?
Yes, I think so, and this series is what I'm looking for, thanks again.

> 
> Durga, please also check if I am missing something to cover for your
> plans to, in case you will be using DT to describe your HW.
> 
> Anyways, Mark and Pawel, let me know if I missed something from our
> discussion. I believe the above bindings would look more like regular
> standard DT bindings. And also they should be now slim enough, without
> Linux implementation details and also without policies.
> 
>>
>>
> 
> 


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

* Re: [lm-sensors] [RFC PATCH 02/14] drivers: thermal: introduce device tree parser
@ 2013-09-02  8:14               ` Wei Ni
  0 siblings, 0 replies; 100+ messages in thread
From: Wei Ni @ 2013-09-02  8:14 UTC (permalink / raw)
  To: Eduardo Valentin
  Cc: Mark Rutland, swarren, Pawel Moll, ian.campbell, grant.likely,
	rob.herring, linux, rui.zhang, durgadoss.r, linux-pm, devicetree,
	lm-sensors, linux-kernel

On 08/30/2013 07:19 AM, Eduardo Valentin wrote:
> * PGP Signed: 08/29/2013 at 04:19:46 PM
> 
> Mark, Pawel and Stephen,
> 
> 
> On 27-08-2013 14:17, Eduardo Valentin wrote:
>> On 27-08-2013 12:23, Mark Rutland wrote:
>>> On Tue, Aug 27, 2013 at 02:44:40PM +0100, Eduardo Valentin wrote:
>>>> Hello Mark,
> 
> <cut>
> 
> I believe now we need to align on thermal bindings, before I propose
> next version of this series. So, following the discussions on this
> thread, I believe a typical CPU thermal zone would look like the following:
> + #include <dt-bindings/thermal/thermal.h>
> +
> + cpu_thermal: cpu_thermal {
> +         passive-delay = <250>; /* milliseconds */
> +         polling-delay = <1000>; /* milliseconds */
> +                 /*
> +                  * sensor       ID
> +                  */
> +         sensors = <&bandgap0     0>;
> +                         /*
> +                          * cooling
> +                          * device       Usage   Trip            lower
> bound             upper bound
> +                          */
> +         cooling-devices = <&cpu0        100     &cpu-alert
> THERMAL_NO_LIMITS        THERMAL_NO_LIMITS>;
> +         trips {
> +                 cpu-alert: cpu-alert {
> +                         temperature = <100000>; /* milliCelsius */
> +                         hysteresis = <2000>; /* milliCelsius */
> +                         type = <THERMAL_TRIP_PASSIVE>;
> +                 };
> +                 cpu-crit: cpu-crit {
> +                         temperature = <125000>; /* milliCelsius */
> +                         hysteresis = <2000>; /* milliCelsius */
> +                         type = <THERMAL_TRIP_CRITICAL>;
> +                 };
> +         };
> + };
> 
> *Note: THERMAL_NO_LIMIT means, it will be using the cooling device
> minimum and maximum limits.
> 
> Couple of comments.
> 1. I am keeping the pooling intervals. A possible alternative way to
> describe that would be specifying the maximum dT/dt. Essentially because
> I am still convinced that this is part of hw specs.
> 
> 2. The above follows your suggestion to use consumer pointing to
> producers. Although, I still need to figure out how this could be
> implemented for Linux. But I think that is another story, at least for
> now. We need to first align on the DT binding itself.
> 
> 3. The link from cooling device specification to trip points, from my
> perspective, should be enough, and thus we shall not need the thermal
> cells and size for trip points, as you proposed. Let me know what you think.
> 
> Below is another example, on a more complex scenario, board specific
> case (hypothetical, just for exemplification):
> 
> + #include <dt-bindings/thermal/thermal.h>
> +
> + board_thermal: board_thermal {
> +         passive-delay = <1000>; /* milliseconds */
> +         polling-delay = <2500>; /* milliseconds */
> +                 /*
> +                  * sensor       ID
> +                  */
> +         sensors = <&adc-dummy     0>,
> +		    <&adc-dummy     1>,
> +		    <&adc-dymmy     2>;
> +                         /*
> +                          * cooling
> +                          * device       Usage   Trip		lower	upper
> +                          */
> +         cooling-devices = <&cpu0       75     &cpu-trip	0      2>,
> +			    <&gpu0       40     &gpu-trip	0      2>;
> +			    <&lcd0       25     &lcd-trip	5      10>;
> +         trips {
> +                 cpu-trip: cpu-trip {
> +                         temperature = <60000>; /* milliCelsius */
> +                         hysteresis = <2000>; /* milliCelsius */
> +                         type = <THERMAL_TRIP_PASSIVE>;
> +                 };
> +                 gpu-trip: gpu-trip {
> +                         temperature = <55000>; /* milliCelsius */
> +                         hysteresis = <2000>; /* milliCelsius */
> +                         type = <THERMAL_TRIP_PASSIVE>;
> +                 }
> +                 lcd-trip: lcp-trip {
> +                         temperature = <53000>; /* milliCelsius */
> +                         hysteresis = <2000>; /* milliCelsius */
> +                         type = <THERMAL_TRIP_PASSIVE>;
> +                 };
> +                 crit-trip: crit-trip {
> +                         temperature = <68000>; /* milliCelsius */
> +                         hysteresis = <2000>; /* milliCelsius */
> +                         type = <THERMAL_TRIP_CRITICAL>;
> +                 };
> +         };
> + };
> 
> Now writing the above example, one might want to have a way to say the
> sensor correlation equation.
> 
> Another example:
> + #include <dt-bindings/thermal/thermal.h>
> +
> + dsp_thermal: dsp_thermal {
> +         passive-delay = <250>; /* milliseconds */
> +         polling-delay = <1000>; /* milliseconds */
> +                 /*
> +                  * sensor       ID
> +                  */
> +         sensors = <&bandgap0     1>;
> +                         /*
> +                          * cooling
> +                          * device       Usage   Trip            lower
> bound             upper bound
> +                          */
> +         cooling-devices = <&dsp0        100     &dsp-alert
> THERMAL_NO_LIMIT        THERMAL_NO_LIMIT>;
> +         trips {
> +                 dsp-alert: dsp-alert {
> +                         temperature = <100000>; /* milliCelsius */
> +                         hysteresis = <2000>; /* milliCelsius */
> +                         type = <THERMAL_TRIP_PASSIVE>;
> +                 };
> +                 dsp-crit: cdsp-crit {
> +                         temperature = <125000>; /* milliCelsius */
> +                         hysteresis = <2000>; /* milliCelsius */
> +                         type = <THERMAL_TRIP_CRITICAL>;
> +                 };
> +         };
> + };
> +
> + gpu_thermal: gpu_thermal {
> +         passive-delay = <500>; /* milliseconds */
> +         polling-delay = <1000>; /* milliseconds */
> +                 /*
> +                  * sensor       ID
> +                  */
> +         sensors = <&bandgap0     2>;
> +                         /*
> +                          * cooling
> +                          * device       Usage   Trip            lower
> bound             upper bound
> +                          */
> +         cooling-devices = <&gpu0        100     &gpu-alert
> THERMAL_NO_LIMIT        THERMAL_NO_LIMIT>;
> +         trips {
> +                 gpu-alert: gpu-alert {
> +                         temperature = <100000>; /* milliCelsius */
> +                         hysteresis = <2000>; /* milliCelsius */
> +                         type = <THERMAL_TRIP_PASSIVE>;
> +                 };
> +                 gpu-crit: gpu-crit {
> +                         temperature = <125000>; /* milliCelsius */
> +                         hysteresis = <2000>; /* milliCelsius */
> +                         type = <THERMAL_TRIP_CRITICAL>;
> +                 };
> +         };
> + };
> 
> 
> Wei, I think the above would cover for the IPs with multiple internal
> sensors cases you were looking for, right?
Yes, I think so, and this series is what I'm looking for, thanks again.

> 
> Durga, please also check if I am missing something to cover for your
> plans to, in case you will be using DT to describe your HW.
> 
> Anyways, Mark and Pawel, let me know if I missed something from our
> discussion. I believe the above bindings would look more like regular
> standard DT bindings. And also they should be now slim enough, without
> Linux implementation details and also without policies.
> 
>>
>>
> 
> 


_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

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

* Re: [RFC PATCH 02/14] drivers: thermal: introduce device tree parser
  2013-08-29 23:19             ` [lm-sensors] " Eduardo Valentin
@ 2013-09-02 16:28               ` Eduardo Valentin
  -1 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-09-02 16:28 UTC (permalink / raw)
  To: Eduardo Valentin
  Cc: Mark Rutland, swarren, Pawel Moll, ian.campbell, grant.likely,
	rob.herring, linux, rui.zhang, wni, durgadoss.r, linux-pm,
	devicetree, lm-sensors, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 7821 bytes --]

On 29-08-2013 19:19, Eduardo Valentin wrote:
> Mark, Pawel and Stephen,
> 
> 
> On 27-08-2013 14:17, Eduardo Valentin wrote:
>> On 27-08-2013 12:23, Mark Rutland wrote:
>>> On Tue, Aug 27, 2013 at 02:44:40PM +0100, Eduardo Valentin wrote:
>>>> Hello Mark,
> 
> <cut>
> 
> I believe now we need to align on thermal bindings, before I propose
> next version of this series. So, following the discussions on this
> thread, I believe a typical CPU thermal zone would look like the following:
> + #include <dt-bindings/thermal/thermal.h>
> +
> + cpu_thermal: cpu_thermal {
> +         passive-delay = <250>; /* milliseconds */
> +         polling-delay = <1000>; /* milliseconds */
> +                 /*
> +                  * sensor       ID
> +                  */
> +         sensors = <&bandgap0     0>;
> +                         /*
> +                          * cooling
> +                          * device       Usage   Trip            lower
> bound             upper bound
> +                          */
> +         cooling-devices = <&cpu0        100     &cpu-alert
> THERMAL_NO_LIMITS        THERMAL_NO_LIMITS>;
> +         trips {
> +                 cpu-alert: cpu-alert {
> +                         temperature = <100000>; /* milliCelsius */
> +                         hysteresis = <2000>; /* milliCelsius */
> +                         type = <THERMAL_TRIP_PASSIVE>;
> +                 };
> +                 cpu-crit: cpu-crit {
> +                         temperature = <125000>; /* milliCelsius */
> +                         hysteresis = <2000>; /* milliCelsius */
> +                         type = <THERMAL_TRIP_CRITICAL>;
> +                 };
> +         };
> + };
> 
> *Note: THERMAL_NO_LIMIT means, it will be using the cooling device
> minimum and maximum limits.
> 
> Couple of comments.
> 1. I am keeping the pooling intervals. A possible alternative way to
> describe that would be specifying the maximum dT/dt. Essentially because
> I am still convinced that this is part of hw specs.
> 
> 2. The above follows your suggestion to use consumer pointing to
> producers. Although, I still need to figure out how this could be
> implemented for Linux. But I think that is another story, at least for
> now. We need to first align on the DT binding itself.
> 
> 3. The link from cooling device specification to trip points, from my
> perspective, should be enough, and thus we shall not need the thermal
> cells and size for trip points, as you proposed. Let me know what you think.
> 
> Below is another example, on a more complex scenario, board specific
> case (hypothetical, just for exemplification):
> 
> + #include <dt-bindings/thermal/thermal.h>
> +
> + board_thermal: board_thermal {
> +         passive-delay = <1000>; /* milliseconds */
> +         polling-delay = <2500>; /* milliseconds */
> +                 /*
> +                  * sensor       ID
> +                  */
> +         sensors = <&adc-dummy     0>,
> +		    <&adc-dummy     1>,
> +		    <&adc-dymmy     2>;
> +                         /*
> +                          * cooling
> +                          * device       Usage   Trip		lower	upper
> +                          */
> +         cooling-devices = <&cpu0       75     &cpu-trip	0      2>,
> +			    <&gpu0       40     &gpu-trip	0      2>;
> +			    <&lcd0       25     &lcd-trip	5      10>;
> +         trips {
> +                 cpu-trip: cpu-trip {
> +                         temperature = <60000>; /* milliCelsius */
> +                         hysteresis = <2000>; /* milliCelsius */
> +                         type = <THERMAL_TRIP_PASSIVE>;
> +                 };
> +                 gpu-trip: gpu-trip {
> +                         temperature = <55000>; /* milliCelsius */
> +                         hysteresis = <2000>; /* milliCelsius */
> +                         type = <THERMAL_TRIP_PASSIVE>;
> +                 }
> +                 lcd-trip: lcp-trip {
> +                         temperature = <53000>; /* milliCelsius */
> +                         hysteresis = <2000>; /* milliCelsius */
> +                         type = <THERMAL_TRIP_PASSIVE>;
> +                 };
> +                 crit-trip: crit-trip {
> +                         temperature = <68000>; /* milliCelsius */
> +                         hysteresis = <2000>; /* milliCelsius */
> +                         type = <THERMAL_TRIP_CRITICAL>;
> +                 };
> +         };
> + };
> 
> Now writing the above example, one might want to have a way to say the
> sensor correlation equation.
> 
> Another example:
> + #include <dt-bindings/thermal/thermal.h>
> +
> + dsp_thermal: dsp_thermal {
> +         passive-delay = <250>; /* milliseconds */
> +         polling-delay = <1000>; /* milliseconds */
> +                 /*
> +                  * sensor       ID
> +                  */
> +         sensors = <&bandgap0     1>;
> +                         /*
> +                          * cooling
> +                          * device       Usage   Trip            lower
> bound             upper bound
> +                          */
> +         cooling-devices = <&dsp0        100     &dsp-alert
> THERMAL_NO_LIMIT        THERMAL_NO_LIMIT>;
> +         trips {
> +                 dsp-alert: dsp-alert {
> +                         temperature = <100000>; /* milliCelsius */
> +                         hysteresis = <2000>; /* milliCelsius */
> +                         type = <THERMAL_TRIP_PASSIVE>;
> +                 };
> +                 dsp-crit: cdsp-crit {
> +                         temperature = <125000>; /* milliCelsius */
> +                         hysteresis = <2000>; /* milliCelsius */
> +                         type = <THERMAL_TRIP_CRITICAL>;
> +                 };
> +         };
> + };
> +
> + gpu_thermal: gpu_thermal {
> +         passive-delay = <500>; /* milliseconds */
> +         polling-delay = <1000>; /* milliseconds */
> +                 /*
> +                  * sensor       ID
> +                  */
> +         sensors = <&bandgap0     2>;
> +                         /*
> +                          * cooling
> +                          * device       Usage   Trip            lower
> bound             upper bound
> +                          */
> +         cooling-devices = <&gpu0        100     &gpu-alert
> THERMAL_NO_LIMIT        THERMAL_NO_LIMIT>;
> +         trips {
> +                 gpu-alert: gpu-alert {
> +                         temperature = <100000>; /* milliCelsius */
> +                         hysteresis = <2000>; /* milliCelsius */
> +                         type = <THERMAL_TRIP_PASSIVE>;
> +                 };
> +                 gpu-crit: gpu-crit {
> +                         temperature = <125000>; /* milliCelsius */
> +                         hysteresis = <2000>; /* milliCelsius */
> +                         type = <THERMAL_TRIP_CRITICAL>;
> +                 };
> +         };
> + };
> 
> 
> Wei, I think the above would cover for the IPs with multiple internal
> sensors cases you were looking for, right?
> 
> Durga, please also check if I am missing something to cover for your
> plans to, in case you will be using DT to describe your HW.
> 
> Anyways, Mark and Pawel, let me know if I missed something from our
> discussion. I believe the above bindings would look more like regular
> standard DT bindings. And also they should be now slim enough, without
> Linux implementation details and also without policies.

Any objections on the above binding proposal?

> 
>>
>>
> 
> 


-- 
You have got to be excited about what you are doing. (L. Lamport)

Eduardo Valentin


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 295 bytes --]

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

* Re: [lm-sensors] [RFC PATCH 02/14] drivers: thermal: introduce device tree parser
@ 2013-09-02 16:28               ` Eduardo Valentin
  0 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-09-02 16:28 UTC (permalink / raw)
  To: Eduardo Valentin
  Cc: Mark Rutland, swarren, Pawel Moll, ian.campbell, grant.likely,
	rob.herring, linux, rui.zhang, wni, durgadoss.r, linux-pm,
	devicetree, lm-sensors, linux-kernel


[-- Attachment #1.1: Type: text/plain, Size: 7821 bytes --]

On 29-08-2013 19:19, Eduardo Valentin wrote:
> Mark, Pawel and Stephen,
> 
> 
> On 27-08-2013 14:17, Eduardo Valentin wrote:
>> On 27-08-2013 12:23, Mark Rutland wrote:
>>> On Tue, Aug 27, 2013 at 02:44:40PM +0100, Eduardo Valentin wrote:
>>>> Hello Mark,
> 
> <cut>
> 
> I believe now we need to align on thermal bindings, before I propose
> next version of this series. So, following the discussions on this
> thread, I believe a typical CPU thermal zone would look like the following:
> + #include <dt-bindings/thermal/thermal.h>
> +
> + cpu_thermal: cpu_thermal {
> +         passive-delay = <250>; /* milliseconds */
> +         polling-delay = <1000>; /* milliseconds */
> +                 /*
> +                  * sensor       ID
> +                  */
> +         sensors = <&bandgap0     0>;
> +                         /*
> +                          * cooling
> +                          * device       Usage   Trip            lower
> bound             upper bound
> +                          */
> +         cooling-devices = <&cpu0        100     &cpu-alert
> THERMAL_NO_LIMITS        THERMAL_NO_LIMITS>;
> +         trips {
> +                 cpu-alert: cpu-alert {
> +                         temperature = <100000>; /* milliCelsius */
> +                         hysteresis = <2000>; /* milliCelsius */
> +                         type = <THERMAL_TRIP_PASSIVE>;
> +                 };
> +                 cpu-crit: cpu-crit {
> +                         temperature = <125000>; /* milliCelsius */
> +                         hysteresis = <2000>; /* milliCelsius */
> +                         type = <THERMAL_TRIP_CRITICAL>;
> +                 };
> +         };
> + };
> 
> *Note: THERMAL_NO_LIMIT means, it will be using the cooling device
> minimum and maximum limits.
> 
> Couple of comments.
> 1. I am keeping the pooling intervals. A possible alternative way to
> describe that would be specifying the maximum dT/dt. Essentially because
> I am still convinced that this is part of hw specs.
> 
> 2. The above follows your suggestion to use consumer pointing to
> producers. Although, I still need to figure out how this could be
> implemented for Linux. But I think that is another story, at least for
> now. We need to first align on the DT binding itself.
> 
> 3. The link from cooling device specification to trip points, from my
> perspective, should be enough, and thus we shall not need the thermal
> cells and size for trip points, as you proposed. Let me know what you think.
> 
> Below is another example, on a more complex scenario, board specific
> case (hypothetical, just for exemplification):
> 
> + #include <dt-bindings/thermal/thermal.h>
> +
> + board_thermal: board_thermal {
> +         passive-delay = <1000>; /* milliseconds */
> +         polling-delay = <2500>; /* milliseconds */
> +                 /*
> +                  * sensor       ID
> +                  */
> +         sensors = <&adc-dummy     0>,
> +		    <&adc-dummy     1>,
> +		    <&adc-dymmy     2>;
> +                         /*
> +                          * cooling
> +                          * device       Usage   Trip		lower	upper
> +                          */
> +         cooling-devices = <&cpu0       75     &cpu-trip	0      2>,
> +			    <&gpu0       40     &gpu-trip	0      2>;
> +			    <&lcd0       25     &lcd-trip	5      10>;
> +         trips {
> +                 cpu-trip: cpu-trip {
> +                         temperature = <60000>; /* milliCelsius */
> +                         hysteresis = <2000>; /* milliCelsius */
> +                         type = <THERMAL_TRIP_PASSIVE>;
> +                 };
> +                 gpu-trip: gpu-trip {
> +                         temperature = <55000>; /* milliCelsius */
> +                         hysteresis = <2000>; /* milliCelsius */
> +                         type = <THERMAL_TRIP_PASSIVE>;
> +                 }
> +                 lcd-trip: lcp-trip {
> +                         temperature = <53000>; /* milliCelsius */
> +                         hysteresis = <2000>; /* milliCelsius */
> +                         type = <THERMAL_TRIP_PASSIVE>;
> +                 };
> +                 crit-trip: crit-trip {
> +                         temperature = <68000>; /* milliCelsius */
> +                         hysteresis = <2000>; /* milliCelsius */
> +                         type = <THERMAL_TRIP_CRITICAL>;
> +                 };
> +         };
> + };
> 
> Now writing the above example, one might want to have a way to say the
> sensor correlation equation.
> 
> Another example:
> + #include <dt-bindings/thermal/thermal.h>
> +
> + dsp_thermal: dsp_thermal {
> +         passive-delay = <250>; /* milliseconds */
> +         polling-delay = <1000>; /* milliseconds */
> +                 /*
> +                  * sensor       ID
> +                  */
> +         sensors = <&bandgap0     1>;
> +                         /*
> +                          * cooling
> +                          * device       Usage   Trip            lower
> bound             upper bound
> +                          */
> +         cooling-devices = <&dsp0        100     &dsp-alert
> THERMAL_NO_LIMIT        THERMAL_NO_LIMIT>;
> +         trips {
> +                 dsp-alert: dsp-alert {
> +                         temperature = <100000>; /* milliCelsius */
> +                         hysteresis = <2000>; /* milliCelsius */
> +                         type = <THERMAL_TRIP_PASSIVE>;
> +                 };
> +                 dsp-crit: cdsp-crit {
> +                         temperature = <125000>; /* milliCelsius */
> +                         hysteresis = <2000>; /* milliCelsius */
> +                         type = <THERMAL_TRIP_CRITICAL>;
> +                 };
> +         };
> + };
> +
> + gpu_thermal: gpu_thermal {
> +         passive-delay = <500>; /* milliseconds */
> +         polling-delay = <1000>; /* milliseconds */
> +                 /*
> +                  * sensor       ID
> +                  */
> +         sensors = <&bandgap0     2>;
> +                         /*
> +                          * cooling
> +                          * device       Usage   Trip            lower
> bound             upper bound
> +                          */
> +         cooling-devices = <&gpu0        100     &gpu-alert
> THERMAL_NO_LIMIT        THERMAL_NO_LIMIT>;
> +         trips {
> +                 gpu-alert: gpu-alert {
> +                         temperature = <100000>; /* milliCelsius */
> +                         hysteresis = <2000>; /* milliCelsius */
> +                         type = <THERMAL_TRIP_PASSIVE>;
> +                 };
> +                 gpu-crit: gpu-crit {
> +                         temperature = <125000>; /* milliCelsius */
> +                         hysteresis = <2000>; /* milliCelsius */
> +                         type = <THERMAL_TRIP_CRITICAL>;
> +                 };
> +         };
> + };
> 
> 
> Wei, I think the above would cover for the IPs with multiple internal
> sensors cases you were looking for, right?
> 
> Durga, please also check if I am missing something to cover for your
> plans to, in case you will be using DT to describe your HW.
> 
> Anyways, Mark and Pawel, let me know if I missed something from our
> discussion. I believe the above bindings would look more like regular
> standard DT bindings. And also they should be now slim enough, without
> Linux implementation details and also without policies.

Any objections on the above binding proposal?

> 
>>
>>
> 
> 


-- 
You have got to be excited about what you are doing. (L. Lamport)

Eduardo Valentin


[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 295 bytes --]

[-- Attachment #2: Type: text/plain, Size: 153 bytes --]

_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

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

* Re: [RFC PATCH 02/14] drivers: thermal: introduce device tree parser
  2013-08-29 23:19             ` [lm-sensors] " Eduardo Valentin
@ 2013-09-03 13:15               ` Mark Rutland
  -1 siblings, 0 replies; 100+ messages in thread
From: Mark Rutland @ 2013-09-03 13:15 UTC (permalink / raw)
  To: Eduardo Valentin
  Cc: swarren, Pawel Moll, ian.campbell, grant.likely, rob.herring,
	linux, rui.zhang, wni, durgadoss.r, linux-pm, devicetree,
	lm-sensors, linux-kernel

On Fri, Aug 30, 2013 at 12:19:43AM +0100, Eduardo Valentin wrote:
> Mark, Pawel and Stephen,
> 
> 
> On 27-08-2013 14:17, Eduardo Valentin wrote:
> > On 27-08-2013 12:23, Mark Rutland wrote:
> >> On Tue, Aug 27, 2013 at 02:44:40PM +0100, Eduardo Valentin wrote:
> >>> Hello Mark,

Hi, sorry for the delay.

> 
> <cut>
> 
> I believe now we need to align on thermal bindings, before I propose
> next version of this series. So, following the discussions on this
> thread, I believe a typical CPU thermal zone would look like the following:
> + #include <dt-bindings/thermal/thermal.h>
> +
> + cpu_thermal: cpu_thermal {
> +         passive-delay = <250>; /* milliseconds */
> +         polling-delay = <1000>; /* milliseconds */

I'm still not keen on placing these intervals in the dt. Why can the
kernel not choose sensible values?

> +                 /*
> +                  * sensor       ID
> +                  */
> +         sensors = <&bandgap0     0>;
> +                         /*
> +                          * cooling
> +                          * device       Usage   Trip            lower
> bound             upper bound
> +                          */
> +         cooling-devices = <&cpu0        100     &cpu-alert
> THERMAL_NO_LIMITS        THERMAL_NO_LIMITS>;

I'm not sure it makes sense to group this data within a property. We
might need to extend this in future and it might not be possible to
extend this unambiguously. It may make more sense as a sub-node or
collection of properties.

> +         trips {
> +                 cpu-alert: cpu-alert {
> +                         temperature = <100000>; /* milliCelsius */
> +                         hysteresis = <2000>; /* milliCelsius */
> +                         type = <THERMAL_TRIP_PASSIVE>;
> +                 };
> +                 cpu-crit: cpu-crit {
> +                         temperature = <125000>; /* milliCelsius */
> +                         hysteresis = <2000>; /* milliCelsius */
> +                         type = <THERMAL_TRIP_CRITICAL>;
> +                 };
> +         };
> + };

How do the upper and lower bounds in the cooling-devices property
interact with temperatures described in the trips node?

> 
> *Note: THERMAL_NO_LIMIT means, it will be using the cooling device
> minimum and maximum limits.

I'm confused what are the cooling device min and max limits? Where are
they defined if not in the lower bound and upper bound entries of the
cooling-devices property?

> 
> Couple of comments.
> 1. I am keeping the pooling intervals. A possible alternative way to
> describe that would be specifying the maximum dT/dt. Essentially because
> I am still convinced that this is part of hw specs.

I still don't see why it's not possible to do this dynamically. I am not
entirely convinced this is part of the hw spec.

> 
> 2. The above follows your suggestion to use consumer pointing to
> producers. Although, I still need to figure out how this could be
> implemented for Linux. But I think that is another story, at least for
> now. We need to first align on the DT binding itself.

I assume you mean the sensors property? That looks fine to me, though we
may need to specify the way sensors relate to temperatures in trip
points and cooling device properties -- do those temperatures correspond
to an average of sensors readings, min/max, etc?

> 
> 3. The link from cooling device specification to trip points, from my
> perspective, should be enough, and thus we shall not need the thermal
> cells and size for trip points, as you proposed. Let me know what you think.

I'm not keen on the mixed bag of values in the cooling-device property,
as it's difficult to extend in future if necessary. I think we may need
cells for cooling devices -- what if a single fan controller controls
fans in different thermal zones?

I'm also not keen on devices being described as their own cooling
device, as I think this is more difficult to support than not listing a
cooling device -- it'll have to be special-cased anyway.

> Below is another example, on a more complex scenario, board specific
> case (hypothetical, just for exemplification):
> 
> + #include <dt-bindings/thermal/thermal.h>
> +
> + board_thermal: board_thermal {
> +         passive-delay = <1000>; /* milliseconds */
> +         polling-delay = <2500>; /* milliseconds */
> +                 /*
> +                  * sensor       ID
> +                  */
> +         sensors = <&adc-dummy     0>,
> +		    <&adc-dummy     1>,
> +		    <&adc-dymmy     2>;

Here we have a set of sensors, but no relationship between these sensors
and the trips or cooling-devices are described. How does that work?

> +                         /*
> +                          * cooling
> +                          * device       Usage   Trip		lower	upper
> +                          */
> +         cooling-devices = <&cpu0       75     &cpu-trip	0      2>,
> +			    <&gpu0       40     &gpu-trip	0      2>;
> +			    <&lcd0       25     &lcd-trip	5      10>;
> +         trips {
> +                 cpu-trip: cpu-trip {
> +                         temperature = <60000>; /* milliCelsius */
> +                         hysteresis = <2000>; /* milliCelsius */
> +                         type = <THERMAL_TRIP_PASSIVE>;
> +                 };
> +                 gpu-trip: gpu-trip {
> +                         temperature = <55000>; /* milliCelsius */
> +                         hysteresis = <2000>; /* milliCelsius */
> +                         type = <THERMAL_TRIP_PASSIVE>;
> +                 }
> +                 lcd-trip: lcp-trip {
> +                         temperature = <53000>; /* milliCelsius */
> +                         hysteresis = <2000>; /* milliCelsius */
> +                         type = <THERMAL_TRIP_PASSIVE>;
> +                 };
> +                 crit-trip: crit-trip {
> +                         temperature = <68000>; /* milliCelsius */
> +                         hysteresis = <2000>; /* milliCelsius */
> +                         type = <THERMAL_TRIP_CRITICAL>;
> +                 };
> +         };
> + };
> 
> Now writing the above example, one might want to have a way to say the
> sensor correlation equation.
> 
> Another example:
> + #include <dt-bindings/thermal/thermal.h>
> +
> + dsp_thermal: dsp_thermal {
> +         passive-delay = <250>; /* milliseconds */
> +         polling-delay = <1000>; /* milliseconds */
> +                 /*
> +                  * sensor       ID
> +                  */
> +         sensors = <&bandgap0     1>;
> +                         /*
> +                          * cooling
> +                          * device       Usage   Trip            lower
> bound             upper bound
> +                          */
> +         cooling-devices = <&dsp0        100     &dsp-alert
> THERMAL_NO_LIMIT        THERMAL_NO_LIMIT>;
> +         trips {
> +                 dsp-alert: dsp-alert {
> +                         temperature = <100000>; /* milliCelsius */
> +                         hysteresis = <2000>; /* milliCelsius */
> +                         type = <THERMAL_TRIP_PASSIVE>;
> +                 };
> +                 dsp-crit: cdsp-crit {
> +                         temperature = <125000>; /* milliCelsius */
> +                         hysteresis = <2000>; /* milliCelsius */
> +                         type = <THERMAL_TRIP_CRITICAL>;
> +                 };
> +         };
> + };
> +
> + gpu_thermal: gpu_thermal {
> +         passive-delay = <500>; /* milliseconds */
> +         polling-delay = <1000>; /* milliseconds */
> +                 /*
> +                  * sensor       ID
> +                  */
> +         sensors = <&bandgap0     2>;
> +                         /*
> +                          * cooling
> +                          * device       Usage   Trip            lower
> bound             upper bound
> +                          */
> +         cooling-devices = <&gpu0        100     &gpu-alert
> THERMAL_NO_LIMIT        THERMAL_NO_LIMIT>;
> +         trips {
> +                 gpu-alert: gpu-alert {
> +                         temperature = <100000>; /* milliCelsius */
> +                         hysteresis = <2000>; /* milliCelsius */
> +                         type = <THERMAL_TRIP_PASSIVE>;
> +                 };
> +                 gpu-crit: gpu-crit {
> +                         temperature = <125000>; /* milliCelsius */
> +                         hysteresis = <2000>; /* milliCelsius */
> +                         type = <THERMAL_TRIP_CRITICAL>;
> +                 };
> +         };
> + };
> 
> 
> Wei, I think the above would cover for the IPs with multiple internal
> sensors cases you were looking for, right?
> 
> Durga, please also check if I am missing something to cover for your
> plans to, in case you will be using DT to describe your HW.
> 
> Anyways, Mark and Pawel, let me know if I missed something from our
> discussion. I believe the above bindings would look more like regular
> standard DT bindings. And also they should be now slim enough, without
> Linux implementation details and also without policies.

I think that the above can describe that, but I'd like to see a binding
document so we can consider it in more detail.

Thanks,
Mark.

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

* Re: [lm-sensors] [RFC PATCH 02/14] drivers: thermal: introduce device tree parser
@ 2013-09-03 13:15               ` Mark Rutland
  0 siblings, 0 replies; 100+ messages in thread
From: Mark Rutland @ 2013-09-03 13:15 UTC (permalink / raw)
  To: Eduardo Valentin
  Cc: swarren, Pawel Moll, ian.campbell, grant.likely, rob.herring,
	linux, rui.zhang, wni, durgadoss.r, linux-pm, devicetree,
	lm-sensors, linux-kernel

On Fri, Aug 30, 2013 at 12:19:43AM +0100, Eduardo Valentin wrote:
> Mark, Pawel and Stephen,
> 
> 
> On 27-08-2013 14:17, Eduardo Valentin wrote:
> > On 27-08-2013 12:23, Mark Rutland wrote:
> >> On Tue, Aug 27, 2013 at 02:44:40PM +0100, Eduardo Valentin wrote:
> >>> Hello Mark,

Hi, sorry for the delay.

> 
> <cut>
> 
> I believe now we need to align on thermal bindings, before I propose
> next version of this series. So, following the discussions on this
> thread, I believe a typical CPU thermal zone would look like the following:
> + #include <dt-bindings/thermal/thermal.h>
> +
> + cpu_thermal: cpu_thermal {
> +         passive-delay = <250>; /* milliseconds */
> +         polling-delay = <1000>; /* milliseconds */

I'm still not keen on placing these intervals in the dt. Why can the
kernel not choose sensible values?

> +                 /*
> +                  * sensor       ID
> +                  */
> +         sensors = <&bandgap0     0>;
> +                         /*
> +                          * cooling
> +                          * device       Usage   Trip            lower
> bound             upper bound
> +                          */
> +         cooling-devices = <&cpu0        100     &cpu-alert
> THERMAL_NO_LIMITS        THERMAL_NO_LIMITS>;

I'm not sure it makes sense to group this data within a property. We
might need to extend this in future and it might not be possible to
extend this unambiguously. It may make more sense as a sub-node or
collection of properties.

> +         trips {
> +                 cpu-alert: cpu-alert {
> +                         temperature = <100000>; /* milliCelsius */
> +                         hysteresis = <2000>; /* milliCelsius */
> +                         type = <THERMAL_TRIP_PASSIVE>;
> +                 };
> +                 cpu-crit: cpu-crit {
> +                         temperature = <125000>; /* milliCelsius */
> +                         hysteresis = <2000>; /* milliCelsius */
> +                         type = <THERMAL_TRIP_CRITICAL>;
> +                 };
> +         };
> + };

How do the upper and lower bounds in the cooling-devices property
interact with temperatures described in the trips node?

> 
> *Note: THERMAL_NO_LIMIT means, it will be using the cooling device
> minimum and maximum limits.

I'm confused what are the cooling device min and max limits? Where are
they defined if not in the lower bound and upper bound entries of the
cooling-devices property?

> 
> Couple of comments.
> 1. I am keeping the pooling intervals. A possible alternative way to
> describe that would be specifying the maximum dT/dt. Essentially because
> I am still convinced that this is part of hw specs.

I still don't see why it's not possible to do this dynamically. I am not
entirely convinced this is part of the hw spec.

> 
> 2. The above follows your suggestion to use consumer pointing to
> producers. Although, I still need to figure out how this could be
> implemented for Linux. But I think that is another story, at least for
> now. We need to first align on the DT binding itself.

I assume you mean the sensors property? That looks fine to me, though we
may need to specify the way sensors relate to temperatures in trip
points and cooling device properties -- do those temperatures correspond
to an average of sensors readings, min/max, etc?

> 
> 3. The link from cooling device specification to trip points, from my
> perspective, should be enough, and thus we shall not need the thermal
> cells and size for trip points, as you proposed. Let me know what you think.

I'm not keen on the mixed bag of values in the cooling-device property,
as it's difficult to extend in future if necessary. I think we may need
cells for cooling devices -- what if a single fan controller controls
fans in different thermal zones?

I'm also not keen on devices being described as their own cooling
device, as I think this is more difficult to support than not listing a
cooling device -- it'll have to be special-cased anyway.

> Below is another example, on a more complex scenario, board specific
> case (hypothetical, just for exemplification):
> 
> + #include <dt-bindings/thermal/thermal.h>
> +
> + board_thermal: board_thermal {
> +         passive-delay = <1000>; /* milliseconds */
> +         polling-delay = <2500>; /* milliseconds */
> +                 /*
> +                  * sensor       ID
> +                  */
> +         sensors = <&adc-dummy     0>,
> +		    <&adc-dummy     1>,
> +		    <&adc-dymmy     2>;

Here we have a set of sensors, but no relationship between these sensors
and the trips or cooling-devices are described. How does that work?

> +                         /*
> +                          * cooling
> +                          * device       Usage   Trip		lower	upper
> +                          */
> +         cooling-devices = <&cpu0       75     &cpu-trip	0      2>,
> +			    <&gpu0       40     &gpu-trip	0      2>;
> +			    <&lcd0       25     &lcd-trip	5      10>;
> +         trips {
> +                 cpu-trip: cpu-trip {
> +                         temperature = <60000>; /* milliCelsius */
> +                         hysteresis = <2000>; /* milliCelsius */
> +                         type = <THERMAL_TRIP_PASSIVE>;
> +                 };
> +                 gpu-trip: gpu-trip {
> +                         temperature = <55000>; /* milliCelsius */
> +                         hysteresis = <2000>; /* milliCelsius */
> +                         type = <THERMAL_TRIP_PASSIVE>;
> +                 }
> +                 lcd-trip: lcp-trip {
> +                         temperature = <53000>; /* milliCelsius */
> +                         hysteresis = <2000>; /* milliCelsius */
> +                         type = <THERMAL_TRIP_PASSIVE>;
> +                 };
> +                 crit-trip: crit-trip {
> +                         temperature = <68000>; /* milliCelsius */
> +                         hysteresis = <2000>; /* milliCelsius */
> +                         type = <THERMAL_TRIP_CRITICAL>;
> +                 };
> +         };
> + };
> 
> Now writing the above example, one might want to have a way to say the
> sensor correlation equation.
> 
> Another example:
> + #include <dt-bindings/thermal/thermal.h>
> +
> + dsp_thermal: dsp_thermal {
> +         passive-delay = <250>; /* milliseconds */
> +         polling-delay = <1000>; /* milliseconds */
> +                 /*
> +                  * sensor       ID
> +                  */
> +         sensors = <&bandgap0     1>;
> +                         /*
> +                          * cooling
> +                          * device       Usage   Trip            lower
> bound             upper bound
> +                          */
> +         cooling-devices = <&dsp0        100     &dsp-alert
> THERMAL_NO_LIMIT        THERMAL_NO_LIMIT>;
> +         trips {
> +                 dsp-alert: dsp-alert {
> +                         temperature = <100000>; /* milliCelsius */
> +                         hysteresis = <2000>; /* milliCelsius */
> +                         type = <THERMAL_TRIP_PASSIVE>;
> +                 };
> +                 dsp-crit: cdsp-crit {
> +                         temperature = <125000>; /* milliCelsius */
> +                         hysteresis = <2000>; /* milliCelsius */
> +                         type = <THERMAL_TRIP_CRITICAL>;
> +                 };
> +         };
> + };
> +
> + gpu_thermal: gpu_thermal {
> +         passive-delay = <500>; /* milliseconds */
> +         polling-delay = <1000>; /* milliseconds */
> +                 /*
> +                  * sensor       ID
> +                  */
> +         sensors = <&bandgap0     2>;
> +                         /*
> +                          * cooling
> +                          * device       Usage   Trip            lower
> bound             upper bound
> +                          */
> +         cooling-devices = <&gpu0        100     &gpu-alert
> THERMAL_NO_LIMIT        THERMAL_NO_LIMIT>;
> +         trips {
> +                 gpu-alert: gpu-alert {
> +                         temperature = <100000>; /* milliCelsius */
> +                         hysteresis = <2000>; /* milliCelsius */
> +                         type = <THERMAL_TRIP_PASSIVE>;
> +                 };
> +                 gpu-crit: gpu-crit {
> +                         temperature = <125000>; /* milliCelsius */
> +                         hysteresis = <2000>; /* milliCelsius */
> +                         type = <THERMAL_TRIP_CRITICAL>;
> +                 };
> +         };
> + };
> 
> 
> Wei, I think the above would cover for the IPs with multiple internal
> sensors cases you were looking for, right?
> 
> Durga, please also check if I am missing something to cover for your
> plans to, in case you will be using DT to describe your HW.
> 
> Anyways, Mark and Pawel, let me know if I missed something from our
> discussion. I believe the above bindings would look more like regular
> standard DT bindings. And also they should be now slim enough, without
> Linux implementation details and also without policies.

I think that the above can describe that, but I'd like to see a binding
document so we can consider it in more detail.

Thanks,
Mark.

_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

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

* Re: [RFC PATCH 02/14] drivers: thermal: introduce device tree parser
  2013-09-03 13:15               ` [lm-sensors] " Mark Rutland
@ 2013-09-03 17:12                 ` Eduardo Valentin
  -1 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-09-03 17:12 UTC (permalink / raw)
  To: Mark Rutland
  Cc: Eduardo Valentin, swarren, Pawel Moll, ian.campbell,
	grant.likely, rob.herring, linux, rui.zhang, wni, durgadoss.r,
	linux-pm, devicetree, lm-sensors, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 12549 bytes --]

Hi Mark,

On 03-09-2013 09:15, Mark Rutland wrote:
> On Fri, Aug 30, 2013 at 12:19:43AM +0100, Eduardo Valentin wrote:
>> Mark, Pawel and Stephen,
>>
>>
>> On 27-08-2013 14:17, Eduardo Valentin wrote:
>>> On 27-08-2013 12:23, Mark Rutland wrote:
>>>> On Tue, Aug 27, 2013 at 02:44:40PM +0100, Eduardo Valentin wrote:
>>>>> Hello Mark,
> 
> Hi, sorry for the delay.
> 

No issues,

>>
>> <cut>
>>
>> I believe now we need to align on thermal bindings, before I propose
>> next version of this series. So, following the discussions on this
>> thread, I believe a typical CPU thermal zone would look like the following:
>> + #include <dt-bindings/thermal/thermal.h>
>> +
>> + cpu_thermal: cpu_thermal {
>> +         passive-delay = <250>; /* milliseconds */
>> +         polling-delay = <1000>; /* milliseconds */
> 
> I'm still not keen on placing these intervals in the dt. Why can the
> kernel not choose sensible values?
> 
>> +                 /*
>> +                  * sensor       ID
>> +                  */
>> +         sensors = <&bandgap0     0>;
>> +                         /*
>> +                          * cooling
>> +                          * device       Usage   Trip            lower
>> bound             upper bound
>> +                          */
>> +         cooling-devices = <&cpu0        100     &cpu-alert
>> THERMAL_NO_LIMITS        THERMAL_NO_LIMITS>;
> 
> I'm not sure it makes sense to group this data within a property. We
> might need to extend this in future and it might not be possible to
> extend this unambiguously. It may make more sense as a sub-node or
> collection of properties.
> 

I see. Something like the previous DT binding? My previous proposal was
using sub-nodes.

>> +         trips {
>> +                 cpu-alert: cpu-alert {
>> +                         temperature = <100000>; /* milliCelsius */
>> +                         hysteresis = <2000>; /* milliCelsius */
>> +                         type = <THERMAL_TRIP_PASSIVE>;
>> +                 };
>> +                 cpu-crit: cpu-crit {
>> +                         temperature = <125000>; /* milliCelsius */
>> +                         hysteresis = <2000>; /* milliCelsius */
>> +                         type = <THERMAL_TRIP_CRITICAL>;
>> +                 };
>> +         };
>> + };
> 
> How do the upper and lower bounds in the cooling-devices property
> interact with temperatures described in the trips node?

By means of the trip phandle. It would mean once the trip is crossed, it
is expected to modulate the cooling device between the specified limits.

> 
>>
>> *Note: THERMAL_NO_LIMIT means, it will be using the cooling device
>> minimum and maximum limits.
> 
> I'm confused what are the cooling device min and max limits? Where are
> they defined if not in the lower bound and upper bound entries of the
> cooling-devices property?

They were not specified in this example, because previous discussions
suggested that we shall not represent cooling devices as dt nodes as
they are virtual. Those would be part of the cooling device node, in the
case we want to have cooling devices nodes and property in DT.

> 
>>
>> Couple of comments.
>> 1. I am keeping the pooling intervals. A possible alternative way to
>> describe that would be specifying the maximum dT/dt. Essentially because
>> I am still convinced that this is part of hw specs.
> 
> I still don't see why it's not possible to do this dynamically. I am not
> entirely convinced this is part of the hw spec.

Because not all hardware have power sensors and deriving power vs.
temperature vs. time is not a simple task, specially based on estimates,
say on cpu load. Remember that we are not only talking about CPU
temperature here, there are other heat sources. Same load has different
consumption on different HW, how SW is supposed to find that out wihtout
proper sensing?

> 
>>
>> 2. The above follows your suggestion to use consumer pointing to
>> producers. Although, I still need to figure out how this could be
>> implemented for Linux. But I think that is another story, at least for
>> now. We need to first align on the DT binding itself.
> 
> I assume you mean the sensors property? That looks fine to me, though we

Sensors and cooling-devices.

> may need to specify the way sensors relate to temperatures in trip
> points and cooling device properties -- do those temperatures correspond
> to an average of sensors readings, min/max, etc?

Those are based on instant measurements.

> 
>>
>> 3. The link from cooling device specification to trip points, from my
>> perspective, should be enough, and thus we shall not need the thermal
>> cells and size for trip points, as you proposed. Let me know what you think.
> 
> I'm not keen on the mixed bag of values in the cooling-device property,
> as it's difficult to extend in future if necessary. I think we may need
> cells for cooling devices -- what if a single fan controller controls
> fans in different thermal zones?

I believe it is just a matter of representation. Using either a list or
subnodes would imply that one would need to add links to fan device
twice, one in each thermal zone (it does not matter if inside a subnode
or inside a list).

> 
> I'm also not keen on devices being described as their own cooling
> device, as I think this is more difficult to support than not listing a
> cooling device -- it'll have to be special-cased anyway.

Then we need to have cooling device nodes, even if they are virtual.

> 
>> Below is another example, on a more complex scenario, board specific
>> case (hypothetical, just for exemplification):
>>
>> + #include <dt-bindings/thermal/thermal.h>
>> +
>> + board_thermal: board_thermal {
>> +         passive-delay = <1000>; /* milliseconds */
>> +         polling-delay = <2500>; /* milliseconds */
>> +                 /*
>> +                  * sensor       ID
>> +                  */
>> +         sensors = <&adc-dummy     0>,
>> +		    <&adc-dummy     1>,
>> +		    <&adc-dymmy     2>;
> 
> Here we have a set of sensors, but no relationship between these sensors
> and the trips or cooling-devices are described. How does that work?

See my query below.

> 
>> +                         /*
>> +                          * cooling
>> +                          * device       Usage   Trip		lower	upper
>> +                          */
>> +         cooling-devices = <&cpu0       75     &cpu-trip	0      2>,
>> +			    <&gpu0       40     &gpu-trip	0      2>;
>> +			    <&lcd0       25     &lcd-trip	5      10>;
>> +         trips {
>> +                 cpu-trip: cpu-trip {
>> +                         temperature = <60000>; /* milliCelsius */
>> +                         hysteresis = <2000>; /* milliCelsius */
>> +                         type = <THERMAL_TRIP_PASSIVE>;
>> +                 };
>> +                 gpu-trip: gpu-trip {
>> +                         temperature = <55000>; /* milliCelsius */
>> +                         hysteresis = <2000>; /* milliCelsius */
>> +                         type = <THERMAL_TRIP_PASSIVE>;
>> +                 }
>> +                 lcd-trip: lcp-trip {
>> +                         temperature = <53000>; /* milliCelsius */
>> +                         hysteresis = <2000>; /* milliCelsius */
>> +                         type = <THERMAL_TRIP_PASSIVE>;
>> +                 };
>> +                 crit-trip: crit-trip {
>> +                         temperature = <68000>; /* milliCelsius */
>> +                         hysteresis = <2000>; /* milliCelsius */
>> +                         type = <THERMAL_TRIP_CRITICAL>;
>> +                 };
>> +         };
>> + };
>>
>> Now writing the above example, one might want to have a way to say the
>> sensor correlation equation.

One way to go is to add a property to describe the linear relation
between them.

>>
>> Another example:
>> + #include <dt-bindings/thermal/thermal.h>
>> +
>> + dsp_thermal: dsp_thermal {
>> +         passive-delay = <250>; /* milliseconds */
>> +         polling-delay = <1000>; /* milliseconds */
>> +                 /*
>> +                  * sensor       ID
>> +                  */
>> +         sensors = <&bandgap0     1>;
>> +                         /*
>> +                          * cooling
>> +                          * device       Usage   Trip            lower
>> bound             upper bound
>> +                          */
>> +         cooling-devices = <&dsp0        100     &dsp-alert
>> THERMAL_NO_LIMIT        THERMAL_NO_LIMIT>;
>> +         trips {
>> +                 dsp-alert: dsp-alert {
>> +                         temperature = <100000>; /* milliCelsius */
>> +                         hysteresis = <2000>; /* milliCelsius */
>> +                         type = <THERMAL_TRIP_PASSIVE>;
>> +                 };
>> +                 dsp-crit: cdsp-crit {
>> +                         temperature = <125000>; /* milliCelsius */
>> +                         hysteresis = <2000>; /* milliCelsius */
>> +                         type = <THERMAL_TRIP_CRITICAL>;
>> +                 };
>> +         };
>> + };
>> +
>> + gpu_thermal: gpu_thermal {
>> +         passive-delay = <500>; /* milliseconds */
>> +         polling-delay = <1000>; /* milliseconds */
>> +                 /*
>> +                  * sensor       ID
>> +                  */
>> +         sensors = <&bandgap0     2>;
>> +                         /*
>> +                          * cooling
>> +                          * device       Usage   Trip            lower
>> bound             upper bound
>> +                          */
>> +         cooling-devices = <&gpu0        100     &gpu-alert
>> THERMAL_NO_LIMIT        THERMAL_NO_LIMIT>;
>> +         trips {
>> +                 gpu-alert: gpu-alert {
>> +                         temperature = <100000>; /* milliCelsius */
>> +                         hysteresis = <2000>; /* milliCelsius */
>> +                         type = <THERMAL_TRIP_PASSIVE>;
>> +                 };
>> +                 gpu-crit: gpu-crit {
>> +                         temperature = <125000>; /* milliCelsius */
>> +                         hysteresis = <2000>; /* milliCelsius */
>> +                         type = <THERMAL_TRIP_CRITICAL>;
>> +                 };
>> +         };
>> + };
>>
>>
>> Wei, I think the above would cover for the IPs with multiple internal
>> sensors cases you were looking for, right?
>>
>> Durga, please also check if I am missing something to cover for your
>> plans to, in case you will be using DT to describe your HW.
>>
>> Anyways, Mark and Pawel, let me know if I missed something from our
>> discussion. I believe the above bindings would look more like regular
>> standard DT bindings. And also they should be now slim enough, without
>> Linux implementation details and also without policies.
> 
> I think that the above can describe that, but I'd like to see a binding
> document so we can consider it in more detail.

Well, I can write another RFC based on this discussion, for sure. I just
want to know what really blocks this work, that is why I sent the
examples above. But it does not seam we are progressing, looks like we
are move discussing in circles.

Cooling devices seams to be bouncing back and forward. I can send an RFC
considering:
i) addition of cooling devices virtual device nodes
ii) description of used cooling devices inside thermal zones by means of
sub-nodes, instead of lists

Pooling intervals seams to be also a loose lace. To me it is a matter of
choosing a good way to avoid missing events. We can either get the info
from HW simulation / experimentation based on HW itself or we can rely
on SW and assume SW can handle to see all events based on loose info
(assume that sw can be smart to do a self adaptive closed loop control
system based on no defined set of inputs). Both solutions are doable,
except that one may be closer to reality than the other. Also, one is
based on HW info and the other forces sw to deduce HW info. If you can
provide info that your proposal has strong evidence to be closer to
reality, I am find to signed it off.

All best,


Eduardo.
> 
> Thanks,
> Mark.
> 
> 


-- 
You have got to be excited about what you are doing. (L. Lamport)

Eduardo Valentin


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 295 bytes --]

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

* Re: [lm-sensors] [RFC PATCH 02/14] drivers: thermal: introduce device tree parser
@ 2013-09-03 17:12                 ` Eduardo Valentin
  0 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-09-03 17:12 UTC (permalink / raw)
  To: Mark Rutland
  Cc: Eduardo Valentin, swarren, Pawel Moll, ian.campbell,
	grant.likely, rob.herring, linux, rui.zhang, wni, durgadoss.r,
	linux-pm, devicetree, lm-sensors, linux-kernel


[-- Attachment #1.1: Type: text/plain, Size: 12549 bytes --]

Hi Mark,

On 03-09-2013 09:15, Mark Rutland wrote:
> On Fri, Aug 30, 2013 at 12:19:43AM +0100, Eduardo Valentin wrote:
>> Mark, Pawel and Stephen,
>>
>>
>> On 27-08-2013 14:17, Eduardo Valentin wrote:
>>> On 27-08-2013 12:23, Mark Rutland wrote:
>>>> On Tue, Aug 27, 2013 at 02:44:40PM +0100, Eduardo Valentin wrote:
>>>>> Hello Mark,
> 
> Hi, sorry for the delay.
> 

No issues,

>>
>> <cut>
>>
>> I believe now we need to align on thermal bindings, before I propose
>> next version of this series. So, following the discussions on this
>> thread, I believe a typical CPU thermal zone would look like the following:
>> + #include <dt-bindings/thermal/thermal.h>
>> +
>> + cpu_thermal: cpu_thermal {
>> +         passive-delay = <250>; /* milliseconds */
>> +         polling-delay = <1000>; /* milliseconds */
> 
> I'm still not keen on placing these intervals in the dt. Why can the
> kernel not choose sensible values?
> 
>> +                 /*
>> +                  * sensor       ID
>> +                  */
>> +         sensors = <&bandgap0     0>;
>> +                         /*
>> +                          * cooling
>> +                          * device       Usage   Trip            lower
>> bound             upper bound
>> +                          */
>> +         cooling-devices = <&cpu0        100     &cpu-alert
>> THERMAL_NO_LIMITS        THERMAL_NO_LIMITS>;
> 
> I'm not sure it makes sense to group this data within a property. We
> might need to extend this in future and it might not be possible to
> extend this unambiguously. It may make more sense as a sub-node or
> collection of properties.
> 

I see. Something like the previous DT binding? My previous proposal was
using sub-nodes.

>> +         trips {
>> +                 cpu-alert: cpu-alert {
>> +                         temperature = <100000>; /* milliCelsius */
>> +                         hysteresis = <2000>; /* milliCelsius */
>> +                         type = <THERMAL_TRIP_PASSIVE>;
>> +                 };
>> +                 cpu-crit: cpu-crit {
>> +                         temperature = <125000>; /* milliCelsius */
>> +                         hysteresis = <2000>; /* milliCelsius */
>> +                         type = <THERMAL_TRIP_CRITICAL>;
>> +                 };
>> +         };
>> + };
> 
> How do the upper and lower bounds in the cooling-devices property
> interact with temperatures described in the trips node?

By means of the trip phandle. It would mean once the trip is crossed, it
is expected to modulate the cooling device between the specified limits.

> 
>>
>> *Note: THERMAL_NO_LIMIT means, it will be using the cooling device
>> minimum and maximum limits.
> 
> I'm confused what are the cooling device min and max limits? Where are
> they defined if not in the lower bound and upper bound entries of the
> cooling-devices property?

They were not specified in this example, because previous discussions
suggested that we shall not represent cooling devices as dt nodes as
they are virtual. Those would be part of the cooling device node, in the
case we want to have cooling devices nodes and property in DT.

> 
>>
>> Couple of comments.
>> 1. I am keeping the pooling intervals. A possible alternative way to
>> describe that would be specifying the maximum dT/dt. Essentially because
>> I am still convinced that this is part of hw specs.
> 
> I still don't see why it's not possible to do this dynamically. I am not
> entirely convinced this is part of the hw spec.

Because not all hardware have power sensors and deriving power vs.
temperature vs. time is not a simple task, specially based on estimates,
say on cpu load. Remember that we are not only talking about CPU
temperature here, there are other heat sources. Same load has different
consumption on different HW, how SW is supposed to find that out wihtout
proper sensing?

> 
>>
>> 2. The above follows your suggestion to use consumer pointing to
>> producers. Although, I still need to figure out how this could be
>> implemented for Linux. But I think that is another story, at least for
>> now. We need to first align on the DT binding itself.
> 
> I assume you mean the sensors property? That looks fine to me, though we

Sensors and cooling-devices.

> may need to specify the way sensors relate to temperatures in trip
> points and cooling device properties -- do those temperatures correspond
> to an average of sensors readings, min/max, etc?

Those are based on instant measurements.

> 
>>
>> 3. The link from cooling device specification to trip points, from my
>> perspective, should be enough, and thus we shall not need the thermal
>> cells and size for trip points, as you proposed. Let me know what you think.
> 
> I'm not keen on the mixed bag of values in the cooling-device property,
> as it's difficult to extend in future if necessary. I think we may need
> cells for cooling devices -- what if a single fan controller controls
> fans in different thermal zones?

I believe it is just a matter of representation. Using either a list or
subnodes would imply that one would need to add links to fan device
twice, one in each thermal zone (it does not matter if inside a subnode
or inside a list).

> 
> I'm also not keen on devices being described as their own cooling
> device, as I think this is more difficult to support than not listing a
> cooling device -- it'll have to be special-cased anyway.

Then we need to have cooling device nodes, even if they are virtual.

> 
>> Below is another example, on a more complex scenario, board specific
>> case (hypothetical, just for exemplification):
>>
>> + #include <dt-bindings/thermal/thermal.h>
>> +
>> + board_thermal: board_thermal {
>> +         passive-delay = <1000>; /* milliseconds */
>> +         polling-delay = <2500>; /* milliseconds */
>> +                 /*
>> +                  * sensor       ID
>> +                  */
>> +         sensors = <&adc-dummy     0>,
>> +		    <&adc-dummy     1>,
>> +		    <&adc-dymmy     2>;
> 
> Here we have a set of sensors, but no relationship between these sensors
> and the trips or cooling-devices are described. How does that work?

See my query below.

> 
>> +                         /*
>> +                          * cooling
>> +                          * device       Usage   Trip		lower	upper
>> +                          */
>> +         cooling-devices = <&cpu0       75     &cpu-trip	0      2>,
>> +			    <&gpu0       40     &gpu-trip	0      2>;
>> +			    <&lcd0       25     &lcd-trip	5      10>;
>> +         trips {
>> +                 cpu-trip: cpu-trip {
>> +                         temperature = <60000>; /* milliCelsius */
>> +                         hysteresis = <2000>; /* milliCelsius */
>> +                         type = <THERMAL_TRIP_PASSIVE>;
>> +                 };
>> +                 gpu-trip: gpu-trip {
>> +                         temperature = <55000>; /* milliCelsius */
>> +                         hysteresis = <2000>; /* milliCelsius */
>> +                         type = <THERMAL_TRIP_PASSIVE>;
>> +                 }
>> +                 lcd-trip: lcp-trip {
>> +                         temperature = <53000>; /* milliCelsius */
>> +                         hysteresis = <2000>; /* milliCelsius */
>> +                         type = <THERMAL_TRIP_PASSIVE>;
>> +                 };
>> +                 crit-trip: crit-trip {
>> +                         temperature = <68000>; /* milliCelsius */
>> +                         hysteresis = <2000>; /* milliCelsius */
>> +                         type = <THERMAL_TRIP_CRITICAL>;
>> +                 };
>> +         };
>> + };
>>
>> Now writing the above example, one might want to have a way to say the
>> sensor correlation equation.

One way to go is to add a property to describe the linear relation
between them.

>>
>> Another example:
>> + #include <dt-bindings/thermal/thermal.h>
>> +
>> + dsp_thermal: dsp_thermal {
>> +         passive-delay = <250>; /* milliseconds */
>> +         polling-delay = <1000>; /* milliseconds */
>> +                 /*
>> +                  * sensor       ID
>> +                  */
>> +         sensors = <&bandgap0     1>;
>> +                         /*
>> +                          * cooling
>> +                          * device       Usage   Trip            lower
>> bound             upper bound
>> +                          */
>> +         cooling-devices = <&dsp0        100     &dsp-alert
>> THERMAL_NO_LIMIT        THERMAL_NO_LIMIT>;
>> +         trips {
>> +                 dsp-alert: dsp-alert {
>> +                         temperature = <100000>; /* milliCelsius */
>> +                         hysteresis = <2000>; /* milliCelsius */
>> +                         type = <THERMAL_TRIP_PASSIVE>;
>> +                 };
>> +                 dsp-crit: cdsp-crit {
>> +                         temperature = <125000>; /* milliCelsius */
>> +                         hysteresis = <2000>; /* milliCelsius */
>> +                         type = <THERMAL_TRIP_CRITICAL>;
>> +                 };
>> +         };
>> + };
>> +
>> + gpu_thermal: gpu_thermal {
>> +         passive-delay = <500>; /* milliseconds */
>> +         polling-delay = <1000>; /* milliseconds */
>> +                 /*
>> +                  * sensor       ID
>> +                  */
>> +         sensors = <&bandgap0     2>;
>> +                         /*
>> +                          * cooling
>> +                          * device       Usage   Trip            lower
>> bound             upper bound
>> +                          */
>> +         cooling-devices = <&gpu0        100     &gpu-alert
>> THERMAL_NO_LIMIT        THERMAL_NO_LIMIT>;
>> +         trips {
>> +                 gpu-alert: gpu-alert {
>> +                         temperature = <100000>; /* milliCelsius */
>> +                         hysteresis = <2000>; /* milliCelsius */
>> +                         type = <THERMAL_TRIP_PASSIVE>;
>> +                 };
>> +                 gpu-crit: gpu-crit {
>> +                         temperature = <125000>; /* milliCelsius */
>> +                         hysteresis = <2000>; /* milliCelsius */
>> +                         type = <THERMAL_TRIP_CRITICAL>;
>> +                 };
>> +         };
>> + };
>>
>>
>> Wei, I think the above would cover for the IPs with multiple internal
>> sensors cases you were looking for, right?
>>
>> Durga, please also check if I am missing something to cover for your
>> plans to, in case you will be using DT to describe your HW.
>>
>> Anyways, Mark and Pawel, let me know if I missed something from our
>> discussion. I believe the above bindings would look more like regular
>> standard DT bindings. And also they should be now slim enough, without
>> Linux implementation details and also without policies.
> 
> I think that the above can describe that, but I'd like to see a binding
> document so we can consider it in more detail.

Well, I can write another RFC based on this discussion, for sure. I just
want to know what really blocks this work, that is why I sent the
examples above. But it does not seam we are progressing, looks like we
are move discussing in circles.

Cooling devices seams to be bouncing back and forward. I can send an RFC
considering:
i) addition of cooling devices virtual device nodes
ii) description of used cooling devices inside thermal zones by means of
sub-nodes, instead of lists

Pooling intervals seams to be also a loose lace. To me it is a matter of
choosing a good way to avoid missing events. We can either get the info
from HW simulation / experimentation based on HW itself or we can rely
on SW and assume SW can handle to see all events based on loose info
(assume that sw can be smart to do a self adaptive closed loop control
system based on no defined set of inputs). Both solutions are doable,
except that one may be closer to reality than the other. Also, one is
based on HW info and the other forces sw to deduce HW info. If you can
provide info that your proposal has strong evidence to be closer to
reality, I am find to signed it off.

All best,


Eduardo.
> 
> Thanks,
> Mark.
> 
> 


-- 
You have got to be excited about what you are doing. (L. Lamport)

Eduardo Valentin


[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 295 bytes --]

[-- Attachment #2: Type: text/plain, Size: 153 bytes --]

_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

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

* Re: [RFC PATCH 02/14] drivers: thermal: introduce device tree parser
  2013-09-03 13:15               ` [lm-sensors] " Mark Rutland
@ 2013-09-07  0:19                 ` Eduardo Valentin
  -1 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-09-07  0:19 UTC (permalink / raw)
  To: Mark Rutland
  Cc: Eduardo Valentin, swarren, Pawel Moll, ian.campbell,
	grant.likely, rob.herring, linux, rui.zhang, wni, durgadoss.r,
	linux-pm, devicetree, lm-sensors, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 18358 bytes --]

Hi Mark, Stephen and Pawel,

On 03-09-2013 09:15, Mark Rutland wrote:
> On Fri, Aug 30, 2013 at 12:19:43AM +0100, Eduardo Valentin wrote:

<cut>

> I think that the above can describe that, but I'd like to see a binding
> document so we can consider it in more detail.

Find below another proposal. It is the updated binding document, with
the your comments applied (at least those I agree :-) ). It is obviously
an work in progress, but I think it is getting closer to what we are
trying to achieve, I believe. And of course, much better after using
your suggestions.

As I stated before, I believe it is crucial to first agree on the
bindings, then I can go ahead and update the corresponding code.

The change from the last binding examples I sent is basically on sensors
and cooling devices. This time, as suggested by Mark, I am adding
cooling device nodes (or at least properties to be embedded into
existing nodes). At some point, I remember that Pawel was not so in
favor on this type of node, but lets discuss on top of the document
below. I also added the #cells properties, as needed.

Hopefully we may end with an agreement. :-)

So, the document would look like this:

-----------------------------------------------------------------------
* Thermal Framework Device Tree descriptor

Generic binding to provide a way of defining hardware thermal
structure using device tree. A thermal structure includes thermal
zones and their components, such as trip points, polling intervals,
sensors and cooling devices binding descriptors.

The target of device tree thermal descriptors is to describe only
the hardware thermal aspects, not how the system must control or which
algorithm or policy must be taken in place.

There are five types of nodes involved to describe thermal bindings:
- sensors: used to describe the device source of temperature sensing;
- cooling devices: used to describe devices source of power dissipation
control;
- trip points: used to describe points in temperature domain defined to
make the system aware of hardware limits;
- cooling attachments: used to describe links between trip points and
cooling devices;
- thermal zones: used to describe thermal data within the hardware;

It follows a description of each type of these device tree nodes.

* Sensor devices

Sensor devices are nodes providing temperature sensing capabilities on
thermal
zones. Typical devices are I2C ADC converters and bandgaps. Theses are nodes
providing temperature data to thermal zones. Temperature sensor devices may
control one or more internal sensors.

Required property:
- #sensor-cells:	Used to provide sensor device specific information
			while referring to it. Must be at least 1, in order
			to identify uniquely the sensor instances within
			the IC. See thermal zone binding for more details
			on how consumers refer to sensor devices.

* Cooling device nodes

Cooling devices are nodes providing control on power dissipation. There
are essentially two ways to provide control on power dissipation. First
is by means of regulating device performance, which is known as passive
cooling. Second is by means of activating devices in order to remove
the dissipated heat, which is known as active cooling, e.g. regulating
fan speeds. In both cases, cooling devices shall have a way to determine
the level of cooling.

Required property:
- cooling-min-level:	A unsigned integer indicating the smallest
			cooling level accepted. Typically 0.
- cooling-max-level:	An unsigned integer indicating the largest
			cooling level accepted.
- #cooling-cells:	Used to provide cooling device specific information
			while referring to it. Must be at least 2, in order
			to specify minimum and maximum cooling level used
			in the reference. See Cooling device attachments section
			below for more details on how consumers refer to
			cooling devices.

* Trip points

The trip node is a node to describe a point in the temperature domain
in which the system takes an action. This node describes just the point,
not the action.

Required properties:
- temperature:		the trip temperature level, in milliCelsius.
- hysteresis:		a (low) hysteresis value on 'temperature'. This is a
			relative value, in milliCelsius.
- type:			the trip type. Here is the type mapping:
	THERMAL_TRIP_ACTIVE	0:	A trip point to enable active cooling
	THERMAL_TRIP_PASSIVE	1:	A trip point to enable passive cooling
	THERMAL_TRIP_HOT	2:	A trip point to notify emergency
	THERMAL_TRIP_CRITICAL	3:	Hardware not reliable.

Refer to include/dt-bindings/thermal/thermal.h for definition of these
consts.

* Cooling device attachments

The cooling device attachments node is a node to describe how cooling
devices
get assigned to trip points of the zone. The cooling devices are expected
to be loaded in the target system.

Required properties:
- cooling-device:	A phandle of a cooling device with its parameters,
			referring to which cooling device is used in this
			binding. The required parameters are: the minimum
			cooling level and the maximum cooling level used
			in this attach.
- trip:			A phandle of a trip point node within the same thermal
			zone.

Optional property:
- contribution:		The cooling contribution to the thermal zone of the
			referred cooling device at the referred trip point.
			The contribution is a value from 0 to 100. The sum
			of all cooling contributions within a thermal zone
			must never exceed 100.

Note: Using the THERMAL_NO_LIMIT (-1L) constant in the cooling-device
phandle
limit parameters means:
(i)   - minimum level allowed for minimum cooling level used in the
reference.
(ii)  - maximum level allowed for maximum cooling level used in the
reference.
Refer to include/dt-bindings/thermal/thermal.h for definition of this
constant.

* Thermal zones

The thermal-zone node is the node containing all the required info
for describing a thermal zone, including its cdev bindings. The thermal_zone
node must contain, apart from its own properties, one node containing
trip nodes and one node containing all the zone cooling attachments.

Required properties:
- passive-delay:	The maximum number of milliseconds to wait between polls
			when performing passive cooling.
- polling-delay:	The maximum number of milliseconds to wait between polls
			when checking this thermal zone.
- sensors:		A list of sensor phandles and their parameters. The
			required parameter is the sensor id, in order to
			identify internal sensors when the sensor IC features
			several sensing units.
- trips:		A sub-node containing several trip point nodes required
			to describe the thermal zone.
- cooling-attachments	A sub-node containing several cooling device attaches
			nodes, used to describe the relation between trips
			and cooling devices.

Optional property:
- coefficients:		An array of integers (one signed cell) containing
			coefficients to compose a linear relation between
			the sensors described in the sensors property.
			Coefficients defaults to 1, in case this property
			is not specified. A simple linear polynomial is used:
			Z = c0 * x0 + c1 + x1 + ... + c(n-1) * x(n-1) + cn.

			The coefficients are ordered and they match with sensors
			by means of sensor ID. Additional coefficients are
			interpreted as constant offsets.

Note: The delay properties are bound to the maximum dT/dt (temperature
derivative over time) in two situations for a thermal zone:
(i)  - when active cooling is activated (passive-delay); and
(ii) - when the zone just needs to be monitored (polling-delay).
The maximum dT/dt is highly bound to hardware power consumption and
dissipation
capability.

* Examples

Below are several examples on how to use thermal data descriptors
using device tree bindings:

(a) - CPU thermal zone

The CPU thermal zone example below describes how to setup one thermal zone
using one single sensor as temperature source and many cooling devices and
power dissipation control sources.

#include <dt-bindings/thermal/thermal.h>

cpus {
	cpu0: cpu@0 {
		...
		cooling-min-level = 0;
		cooling-max-level = 3;
		#cooling-cells = <2>; /* min followed by max */
	};
	...
};

&i2c1 {
	...
	fan0: fan@0x48 {
		...
		cooling-min-level = 0;
		cooling-max-level = 9;
		#cooling-cells = <2>; /* min followed by max */
	};
};

bandgap0: bandgap@0x0000ED00 {
	...
	#sensor-cells = <1>;
};

cpu-thermal: cpu-thermal {
	passive-delay = <250>; /* milliseconds */
	polling-delay = <1000>; /* milliseconds */

		/* sensor       ID */
        sensors = <&bandgap0     0>;

        trips {
                cpu-alert0: cpu-alert {
                        temperature = <90000>; /* milliCelsius */
                        hysteresis = <2000>; /* milliCelsius */
                        type = <THERMAL_TRIP_ACTIVE>;
                };
                cpu-alert1: cpu-alert {
                        temperature = <100000>; /* milliCelsius */
                        hysteresis = <2000>; /* milliCelsius */
                        type = <THERMAL_TRIP_PASSIVE>;
                };
                cpu-crit: cpu-crit {
                        temperature = <125000>; /* milliCelsius */
                        hysteresis = <2000>; /* milliCelsius */
                        type = <THERMAL_TRIP_CRITICAL>;
                };
        };

	cooling-attachments {
		attach0 {
			trip = <&cpu-alert0>;
			cooling-devices = <&fan0 THERMAL_NO_LIMITS 4>;
 		};
		attach1 {
			trip = <&cpu-alert1>;
			cooling-device = <&fan0 5 THERMAL_NO_LIMITS>;
		};
		attach2 {
			trip = <&cpu-alert1>;
			cooling-device =
				<&cpu0 THERMAL_NO_LIMITS THERMAL_NO_LIMITS>;
		};
	};
};

In the example above, the ADC sensor at address 0x0000ED00 is used to
monitor
the zone 'cpu-thermal' using its the sensor 0. The fan0, a fan device
controlled
via I2C bus 1, at adress 0x48, is used to remove the heat out of the thermal
zone 'cpu-thermal' using its cooling levels from its minimum to 4, when it
reaches trip point 'cpu-alert0' at 90C, as an example of active cooling. The
same cooling device is used at 'cpu-alert1', but from 5 to its maximum
level.
The cpu@0 device is also linked to the same thermal zone, 'cpu-thermal',
as a
passive cooling device, using all its cooling levels at trip point
'cpu-alert1',
which is a trip point at 100C.

(b) - IC with several internal sensors

The example below describes how to deploy several thermal zones based off a
single sensor IC, assuming it has several internal sensors. This is a common
case on SoC designs with several internal IPs that may need different
thermal
requirements, and thus may have their own sensor to monitor or detect
internal
hotspots in their silicon.

#include <dt-bindings/thermal/thermal.h>

bandgap0: bandgap@0x0000ED00 {
	...
	#sensor-cells = <1>;
};

cpu-thermal: cpu-thermal {
	passive-delay = <250>; /* milliseconds */
	polling-delay = <1000>; /* milliseconds */

		/* sensor       ID */
        sensors = <&bandgap0     0>;

        trips {
		/* each zone within the SoC may have its own trips */
                cpu-alert: cpu-alert {
                        temperature = <100000>; /* milliCelsius */
                        hysteresis = <2000>; /* milliCelsius */
                        type = <THERMAL_TRIP_PASSIVE>;
                };
                cpu-crit: cpu-crit {
                        temperature = <125000>; /* milliCelsius */
                        hysteresis = <2000>; /* milliCelsius */
                        type = <THERMAL_TRIP_CRITICAL>;
                };
        };

	cooling-attachments {
		/* each zone within the SoC may have its own cooling */
		...
	};
};

gpu-thermal: gpu-thermal {
	passive-delay = <120>; /* milliseconds */
	polling-delay = <1000>; /* milliseconds */

		/* sensor       ID */
        sensors = <&bandgap0     1>;

        trips {
		/* each zone within the SoC may have its own trips */
                gpu-alert: gpu-alert {
                        temperature = <90000>; /* milliCelsius */
                        hysteresis = <2000>; /* milliCelsius */
                        type = <THERMAL_TRIP_PASSIVE>;
                };
                gpu-crit: gpu-crit {
                        temperature = <105000>; /* milliCelsius */
                        hysteresis = <2000>; /* milliCelsius */
                        type = <THERMAL_TRIP_CRITICAL>;
                };
        };

	cooling-attachments {
		/* each zone within the SoC may have its own cooling */
		...
	};
};

dsp-thermal: dsp-thermal {
	passive-delay = <50>; /* milliseconds */
	polling-delay = <1000>; /* milliseconds */

		/* sensor       ID */
        sensors = <&bandgap0     2>;

        trips {
		/* each zone within the SoC may have its own trips */
                dsp-alert: gpu-alert {
                        temperature = <90000>; /* milliCelsius */
                        hysteresis = <2000>; /* milliCelsius */
                        type = <THERMAL_TRIP_PASSIVE>;
                };
                dsp-crit: gpu-crit {
                        temperature = <135000>; /* milliCelsius */
                        hysteresis = <2000>; /* milliCelsius */
                        type = <THERMAL_TRIP_CRITICAL>;
                };
        };

	cooling-attachments {
		/* each zone within the SoC may have its own cooling */
		...
	};
};

In the example above there is one bandgap IC which has the capability to
monitor three sensors. The hardware has been designed so that sensors are
placed on different places in the DIE to monitor different temperature
hotspots: one for CPU thermal zone, one for GPU thermal zone and the
other to monitor a DSP thermal zone.

Thus, there is a need to assign each sensor provided by the bandgap IC
to different thermal zones. This is achieved by means of using the
#sensor-cells property and using the first parameter as sensor ID.
In the example, then, bandgap.sensor0 is used to monitor CPU thermal zone,
bandgap.sensor1 is used to monitor GPU thermal zone and bandgap.sensor2
is used to monitor DSP thermal zone. Each zone may be uncorrelated,
having its own dT/dt requirements, trips and cooling attachments.

(c) - Several sensors within one single thermal zone

The example below illustrates how to use more than one sensor within
one thermal zone.

#include <dt-bindings/thermal/thermal.h>

&i2c1 {
	...
	adc: sensor@0x49 {
		...
		#sensor-cells = <1>;
	};
};

bandgap0: bandgap@0x0000ED00 {
	...
	#sensor-cells = <1>;
};

cpu-thermal: cpu-thermal {
	passive-delay = <250>; /* milliseconds */
	polling-delay = <1000>; /* milliseconds */

		/* sensor       ID */
        sensors = <&bandgap0	0>,
		  <&adc		0>;

		/* hotspot = 100 * bandgap - 120 * adc + 484 */
 	coefficients = 		<100	-120	484>;

        trips {
		...
        };

	cooling-attachments {
		...
	};
};

In some cases, there is a need to use more than one sensor to extrapolate
a thermal hotspot in the silicon. The above example illustrate this
situation.
For instance, it may be the case that a sensor external to CPU IP may be
place
close to CPU hotspot and together with internal CPU sensor, it is used
to determine the hotspot. The hyppotetical extrapolation rule would be:
		hotspot = 100 * bandgap - 120 * adc + 484

The same idea can be used to add fixed offset:
	passive-delay = <1000>; /* milliseconds */
	polling-delay = <2500>; /* milliseconds */
		hotspot = 1 * adc + 6000

In the above equation, the hotspot is always 6C higher than what is read
from the sensor ADC. The binding would be then:
		/* sensor       ID */
        sensors =  <&adc	0>;

		/* hotspot = 1 * adc + 6000 */
	coefficients = 		<1	6000>;

(d) - Board thermal

The board thermal example below illustrates how to setup one thermal zone
with many sensors and many cooling devices.

#include <dt-bindings/thermal/thermal.h>

&i2c1 {
 	...
	adc-dummy: sensor@0x50 {
		...
		#sensor-cells = <1>; /* sensor internal ID */
	};
};

batt-thermal {
	passive-delay = <500>; /* milliseconds */
	polling-delay = <2500>; /* milliseconds */

	/* sensor       ID */
	sensors = <&adc-dummy     4>;

	trips {
		...
	};

	cooling-attachments {
		...
	};
};

board-thermal: board-thermal {
	passive-delay = <1000>; /* milliseconds */
	polling-delay = <2500>; /* milliseconds */

		/* sensor       ID */
	sensors = <&adc-dummy     0>,
		  <&adc-dummy     1>,
		  <&adc-dymmy     2>;
			/*
			 * An array of coefficients describing the sensor
			 * linear relation. E.g.:
			 * z = c1*x1 + c2*x2 + c3*x3
			 */
	coefficients =		<1200	-345	890>;

	trips {
		/* Trips are based on resulting linear equation */
		cpu-trip: cpu-trip {
			temperature = <60000>; /* milliCelsius */
			hysteresis = <2000>; /* milliCelsius */
			type = <THERMAL_TRIP_PASSIVE>;
		};
		gpu-trip: gpu-trip {
			temperature = <55000>; /* milliCelsius */
			hysteresis = <2000>; /* milliCelsius */
			type = <THERMAL_TRIP_PASSIVE>;
		}
		lcd-trip: lcp-trip {
			temperature = <53000>; /* milliCelsius */
			hysteresis = <2000>; /* milliCelsius */
			type = <THERMAL_TRIP_PASSIVE>;
		};
		crit-trip: crit-trip {
			temperature = <68000>; /* milliCelsius */
			hysteresis = <2000>; /* milliCelsius */
 			type = <THERMAL_TRIP_CRITICAL>;
		};
	};

	cooling-attachments {
		attach0 {
			trip = <&cpu-trip>;
			cooling-device = <&cpu0 0 2>;
			contribution = <55>;
		};
		attach1 {
			trip = <&gpu-trip>;
			cooling-device = <&gpu0 0 2>;
			contribution = <20>;
		};
 		attach2 {
			trip = <&lcd-trip>;
			cooling-device = <&lcd0 5 10>;
			contribution = <15>;
		};
	};
};

The above example is a mix of previous examples, a sensor IP with
several internal
sensors used to monitor different zones, one of them is composed by
several sensors and
with different cooling devices.
-----------------------------------------------------------------------

All best,


-- 
You have got to be excited about what you are doing. (L. Lamport)

Eduardo Valentin


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 295 bytes --]

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

* Re: [lm-sensors] [RFC PATCH 02/14] drivers: thermal: introduce device tree parser
@ 2013-09-07  0:19                 ` Eduardo Valentin
  0 siblings, 0 replies; 100+ messages in thread
From: Eduardo Valentin @ 2013-09-07  0:19 UTC (permalink / raw)
  To: Mark Rutland
  Cc: Eduardo Valentin, swarren, Pawel Moll, ian.campbell,
	grant.likely, rob.herring, linux, rui.zhang, wni, durgadoss.r,
	linux-pm, devicetree, lm-sensors, linux-kernel


[-- Attachment #1.1: Type: text/plain, Size: 18358 bytes --]

Hi Mark, Stephen and Pawel,

On 03-09-2013 09:15, Mark Rutland wrote:
> On Fri, Aug 30, 2013 at 12:19:43AM +0100, Eduardo Valentin wrote:

<cut>

> I think that the above can describe that, but I'd like to see a binding
> document so we can consider it in more detail.

Find below another proposal. It is the updated binding document, with
the your comments applied (at least those I agree :-) ). It is obviously
an work in progress, but I think it is getting closer to what we are
trying to achieve, I believe. And of course, much better after using
your suggestions.

As I stated before, I believe it is crucial to first agree on the
bindings, then I can go ahead and update the corresponding code.

The change from the last binding examples I sent is basically on sensors
and cooling devices. This time, as suggested by Mark, I am adding
cooling device nodes (or at least properties to be embedded into
existing nodes). At some point, I remember that Pawel was not so in
favor on this type of node, but lets discuss on top of the document
below. I also added the #cells properties, as needed.

Hopefully we may end with an agreement. :-)

So, the document would look like this:

-----------------------------------------------------------------------
* Thermal Framework Device Tree descriptor

Generic binding to provide a way of defining hardware thermal
structure using device tree. A thermal structure includes thermal
zones and their components, such as trip points, polling intervals,
sensors and cooling devices binding descriptors.

The target of device tree thermal descriptors is to describe only
the hardware thermal aspects, not how the system must control or which
algorithm or policy must be taken in place.

There are five types of nodes involved to describe thermal bindings:
- sensors: used to describe the device source of temperature sensing;
- cooling devices: used to describe devices source of power dissipation
control;
- trip points: used to describe points in temperature domain defined to
make the system aware of hardware limits;
- cooling attachments: used to describe links between trip points and
cooling devices;
- thermal zones: used to describe thermal data within the hardware;

It follows a description of each type of these device tree nodes.

* Sensor devices

Sensor devices are nodes providing temperature sensing capabilities on
thermal
zones. Typical devices are I2C ADC converters and bandgaps. Theses are nodes
providing temperature data to thermal zones. Temperature sensor devices may
control one or more internal sensors.

Required property:
- #sensor-cells:	Used to provide sensor device specific information
			while referring to it. Must be at least 1, in order
			to identify uniquely the sensor instances within
			the IC. See thermal zone binding for more details
			on how consumers refer to sensor devices.

* Cooling device nodes

Cooling devices are nodes providing control on power dissipation. There
are essentially two ways to provide control on power dissipation. First
is by means of regulating device performance, which is known as passive
cooling. Second is by means of activating devices in order to remove
the dissipated heat, which is known as active cooling, e.g. regulating
fan speeds. In both cases, cooling devices shall have a way to determine
the level of cooling.

Required property:
- cooling-min-level:	A unsigned integer indicating the smallest
			cooling level accepted. Typically 0.
- cooling-max-level:	An unsigned integer indicating the largest
			cooling level accepted.
- #cooling-cells:	Used to provide cooling device specific information
			while referring to it. Must be at least 2, in order
			to specify minimum and maximum cooling level used
			in the reference. See Cooling device attachments section
			below for more details on how consumers refer to
			cooling devices.

* Trip points

The trip node is a node to describe a point in the temperature domain
in which the system takes an action. This node describes just the point,
not the action.

Required properties:
- temperature:		the trip temperature level, in milliCelsius.
- hysteresis:		a (low) hysteresis value on 'temperature'. This is a
			relative value, in milliCelsius.
- type:			the trip type. Here is the type mapping:
	THERMAL_TRIP_ACTIVE	0:	A trip point to enable active cooling
	THERMAL_TRIP_PASSIVE	1:	A trip point to enable passive cooling
	THERMAL_TRIP_HOT	2:	A trip point to notify emergency
	THERMAL_TRIP_CRITICAL	3:	Hardware not reliable.

Refer to include/dt-bindings/thermal/thermal.h for definition of these
consts.

* Cooling device attachments

The cooling device attachments node is a node to describe how cooling
devices
get assigned to trip points of the zone. The cooling devices are expected
to be loaded in the target system.

Required properties:
- cooling-device:	A phandle of a cooling device with its parameters,
			referring to which cooling device is used in this
			binding. The required parameters are: the minimum
			cooling level and the maximum cooling level used
			in this attach.
- trip:			A phandle of a trip point node within the same thermal
			zone.

Optional property:
- contribution:		The cooling contribution to the thermal zone of the
			referred cooling device at the referred trip point.
			The contribution is a value from 0 to 100. The sum
			of all cooling contributions within a thermal zone
			must never exceed 100.

Note: Using the THERMAL_NO_LIMIT (-1L) constant in the cooling-device
phandle
limit parameters means:
(i)   - minimum level allowed for minimum cooling level used in the
reference.
(ii)  - maximum level allowed for maximum cooling level used in the
reference.
Refer to include/dt-bindings/thermal/thermal.h for definition of this
constant.

* Thermal zones

The thermal-zone node is the node containing all the required info
for describing a thermal zone, including its cdev bindings. The thermal_zone
node must contain, apart from its own properties, one node containing
trip nodes and one node containing all the zone cooling attachments.

Required properties:
- passive-delay:	The maximum number of milliseconds to wait between polls
			when performing passive cooling.
- polling-delay:	The maximum number of milliseconds to wait between polls
			when checking this thermal zone.
- sensors:		A list of sensor phandles and their parameters. The
			required parameter is the sensor id, in order to
			identify internal sensors when the sensor IC features
			several sensing units.
- trips:		A sub-node containing several trip point nodes required
			to describe the thermal zone.
- cooling-attachments	A sub-node containing several cooling device attaches
			nodes, used to describe the relation between trips
			and cooling devices.

Optional property:
- coefficients:		An array of integers (one signed cell) containing
			coefficients to compose a linear relation between
			the sensors described in the sensors property.
			Coefficients defaults to 1, in case this property
			is not specified. A simple linear polynomial is used:
			Z = c0 * x0 + c1 + x1 + ... + c(n-1) * x(n-1) + cn.

			The coefficients are ordered and they match with sensors
			by means of sensor ID. Additional coefficients are
			interpreted as constant offsets.

Note: The delay properties are bound to the maximum dT/dt (temperature
derivative over time) in two situations for a thermal zone:
(i)  - when active cooling is activated (passive-delay); and
(ii) - when the zone just needs to be monitored (polling-delay).
The maximum dT/dt is highly bound to hardware power consumption and
dissipation
capability.

* Examples

Below are several examples on how to use thermal data descriptors
using device tree bindings:

(a) - CPU thermal zone

The CPU thermal zone example below describes how to setup one thermal zone
using one single sensor as temperature source and many cooling devices and
power dissipation control sources.

#include <dt-bindings/thermal/thermal.h>

cpus {
	cpu0: cpu@0 {
		...
		cooling-min-level = 0;
		cooling-max-level = 3;
		#cooling-cells = <2>; /* min followed by max */
	};
	...
};

&i2c1 {
	...
	fan0: fan@0x48 {
		...
		cooling-min-level = 0;
		cooling-max-level = 9;
		#cooling-cells = <2>; /* min followed by max */
	};
};

bandgap0: bandgap@0x0000ED00 {
	...
	#sensor-cells = <1>;
};

cpu-thermal: cpu-thermal {
	passive-delay = <250>; /* milliseconds */
	polling-delay = <1000>; /* milliseconds */

		/* sensor       ID */
        sensors = <&bandgap0     0>;

        trips {
                cpu-alert0: cpu-alert {
                        temperature = <90000>; /* milliCelsius */
                        hysteresis = <2000>; /* milliCelsius */
                        type = <THERMAL_TRIP_ACTIVE>;
                };
                cpu-alert1: cpu-alert {
                        temperature = <100000>; /* milliCelsius */
                        hysteresis = <2000>; /* milliCelsius */
                        type = <THERMAL_TRIP_PASSIVE>;
                };
                cpu-crit: cpu-crit {
                        temperature = <125000>; /* milliCelsius */
                        hysteresis = <2000>; /* milliCelsius */
                        type = <THERMAL_TRIP_CRITICAL>;
                };
        };

	cooling-attachments {
		attach0 {
			trip = <&cpu-alert0>;
			cooling-devices = <&fan0 THERMAL_NO_LIMITS 4>;
 		};
		attach1 {
			trip = <&cpu-alert1>;
			cooling-device = <&fan0 5 THERMAL_NO_LIMITS>;
		};
		attach2 {
			trip = <&cpu-alert1>;
			cooling-device =
				<&cpu0 THERMAL_NO_LIMITS THERMAL_NO_LIMITS>;
		};
	};
};

In the example above, the ADC sensor at address 0x0000ED00 is used to
monitor
the zone 'cpu-thermal' using its the sensor 0. The fan0, a fan device
controlled
via I2C bus 1, at adress 0x48, is used to remove the heat out of the thermal
zone 'cpu-thermal' using its cooling levels from its minimum to 4, when it
reaches trip point 'cpu-alert0' at 90C, as an example of active cooling. The
same cooling device is used at 'cpu-alert1', but from 5 to its maximum
level.
The cpu@0 device is also linked to the same thermal zone, 'cpu-thermal',
as a
passive cooling device, using all its cooling levels at trip point
'cpu-alert1',
which is a trip point at 100C.

(b) - IC with several internal sensors

The example below describes how to deploy several thermal zones based off a
single sensor IC, assuming it has several internal sensors. This is a common
case on SoC designs with several internal IPs that may need different
thermal
requirements, and thus may have their own sensor to monitor or detect
internal
hotspots in their silicon.

#include <dt-bindings/thermal/thermal.h>

bandgap0: bandgap@0x0000ED00 {
	...
	#sensor-cells = <1>;
};

cpu-thermal: cpu-thermal {
	passive-delay = <250>; /* milliseconds */
	polling-delay = <1000>; /* milliseconds */

		/* sensor       ID */
        sensors = <&bandgap0     0>;

        trips {
		/* each zone within the SoC may have its own trips */
                cpu-alert: cpu-alert {
                        temperature = <100000>; /* milliCelsius */
                        hysteresis = <2000>; /* milliCelsius */
                        type = <THERMAL_TRIP_PASSIVE>;
                };
                cpu-crit: cpu-crit {
                        temperature = <125000>; /* milliCelsius */
                        hysteresis = <2000>; /* milliCelsius */
                        type = <THERMAL_TRIP_CRITICAL>;
                };
        };

	cooling-attachments {
		/* each zone within the SoC may have its own cooling */
		...
	};
};

gpu-thermal: gpu-thermal {
	passive-delay = <120>; /* milliseconds */
	polling-delay = <1000>; /* milliseconds */

		/* sensor       ID */
        sensors = <&bandgap0     1>;

        trips {
		/* each zone within the SoC may have its own trips */
                gpu-alert: gpu-alert {
                        temperature = <90000>; /* milliCelsius */
                        hysteresis = <2000>; /* milliCelsius */
                        type = <THERMAL_TRIP_PASSIVE>;
                };
                gpu-crit: gpu-crit {
                        temperature = <105000>; /* milliCelsius */
                        hysteresis = <2000>; /* milliCelsius */
                        type = <THERMAL_TRIP_CRITICAL>;
                };
        };

	cooling-attachments {
		/* each zone within the SoC may have its own cooling */
		...
	};
};

dsp-thermal: dsp-thermal {
	passive-delay = <50>; /* milliseconds */
	polling-delay = <1000>; /* milliseconds */

		/* sensor       ID */
        sensors = <&bandgap0     2>;

        trips {
		/* each zone within the SoC may have its own trips */
                dsp-alert: gpu-alert {
                        temperature = <90000>; /* milliCelsius */
                        hysteresis = <2000>; /* milliCelsius */
                        type = <THERMAL_TRIP_PASSIVE>;
                };
                dsp-crit: gpu-crit {
                        temperature = <135000>; /* milliCelsius */
                        hysteresis = <2000>; /* milliCelsius */
                        type = <THERMAL_TRIP_CRITICAL>;
                };
        };

	cooling-attachments {
		/* each zone within the SoC may have its own cooling */
		...
	};
};

In the example above there is one bandgap IC which has the capability to
monitor three sensors. The hardware has been designed so that sensors are
placed on different places in the DIE to monitor different temperature
hotspots: one for CPU thermal zone, one for GPU thermal zone and the
other to monitor a DSP thermal zone.

Thus, there is a need to assign each sensor provided by the bandgap IC
to different thermal zones. This is achieved by means of using the
#sensor-cells property and using the first parameter as sensor ID.
In the example, then, bandgap.sensor0 is used to monitor CPU thermal zone,
bandgap.sensor1 is used to monitor GPU thermal zone and bandgap.sensor2
is used to monitor DSP thermal zone. Each zone may be uncorrelated,
having its own dT/dt requirements, trips and cooling attachments.

(c) - Several sensors within one single thermal zone

The example below illustrates how to use more than one sensor within
one thermal zone.

#include <dt-bindings/thermal/thermal.h>

&i2c1 {
	...
	adc: sensor@0x49 {
		...
		#sensor-cells = <1>;
	};
};

bandgap0: bandgap@0x0000ED00 {
	...
	#sensor-cells = <1>;
};

cpu-thermal: cpu-thermal {
	passive-delay = <250>; /* milliseconds */
	polling-delay = <1000>; /* milliseconds */

		/* sensor       ID */
        sensors = <&bandgap0	0>,
		  <&adc		0>;

		/* hotspot = 100 * bandgap - 120 * adc + 484 */
 	coefficients = 		<100	-120	484>;

        trips {
		...
        };

	cooling-attachments {
		...
	};
};

In some cases, there is a need to use more than one sensor to extrapolate
a thermal hotspot in the silicon. The above example illustrate this
situation.
For instance, it may be the case that a sensor external to CPU IP may be
place
close to CPU hotspot and together with internal CPU sensor, it is used
to determine the hotspot. The hyppotetical extrapolation rule would be:
		hotspot = 100 * bandgap - 120 * adc + 484

The same idea can be used to add fixed offset:
	passive-delay = <1000>; /* milliseconds */
	polling-delay = <2500>; /* milliseconds */
		hotspot = 1 * adc + 6000

In the above equation, the hotspot is always 6C higher than what is read
from the sensor ADC. The binding would be then:
		/* sensor       ID */
        sensors =  <&adc	0>;

		/* hotspot = 1 * adc + 6000 */
	coefficients = 		<1	6000>;

(d) - Board thermal

The board thermal example below illustrates how to setup one thermal zone
with many sensors and many cooling devices.

#include <dt-bindings/thermal/thermal.h>

&i2c1 {
 	...
	adc-dummy: sensor@0x50 {
		...
		#sensor-cells = <1>; /* sensor internal ID */
	};
};

batt-thermal {
	passive-delay = <500>; /* milliseconds */
	polling-delay = <2500>; /* milliseconds */

	/* sensor       ID */
	sensors = <&adc-dummy     4>;

	trips {
		...
	};

	cooling-attachments {
		...
	};
};

board-thermal: board-thermal {
	passive-delay = <1000>; /* milliseconds */
	polling-delay = <2500>; /* milliseconds */

		/* sensor       ID */
	sensors = <&adc-dummy     0>,
		  <&adc-dummy     1>,
		  <&adc-dymmy     2>;
			/*
			 * An array of coefficients describing the sensor
			 * linear relation. E.g.:
			 * z = c1*x1 + c2*x2 + c3*x3
			 */
	coefficients =		<1200	-345	890>;

	trips {
		/* Trips are based on resulting linear equation */
		cpu-trip: cpu-trip {
			temperature = <60000>; /* milliCelsius */
			hysteresis = <2000>; /* milliCelsius */
			type = <THERMAL_TRIP_PASSIVE>;
		};
		gpu-trip: gpu-trip {
			temperature = <55000>; /* milliCelsius */
			hysteresis = <2000>; /* milliCelsius */
			type = <THERMAL_TRIP_PASSIVE>;
		}
		lcd-trip: lcp-trip {
			temperature = <53000>; /* milliCelsius */
			hysteresis = <2000>; /* milliCelsius */
			type = <THERMAL_TRIP_PASSIVE>;
		};
		crit-trip: crit-trip {
			temperature = <68000>; /* milliCelsius */
			hysteresis = <2000>; /* milliCelsius */
 			type = <THERMAL_TRIP_CRITICAL>;
		};
	};

	cooling-attachments {
		attach0 {
			trip = <&cpu-trip>;
			cooling-device = <&cpu0 0 2>;
			contribution = <55>;
		};
		attach1 {
			trip = <&gpu-trip>;
			cooling-device = <&gpu0 0 2>;
			contribution = <20>;
		};
 		attach2 {
			trip = <&lcd-trip>;
			cooling-device = <&lcd0 5 10>;
			contribution = <15>;
		};
	};
};

The above example is a mix of previous examples, a sensor IP with
several internal
sensors used to monitor different zones, one of them is composed by
several sensors and
with different cooling devices.
-----------------------------------------------------------------------

All best,


-- 
You have got to be excited about what you are doing. (L. Lamport)

Eduardo Valentin


[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 295 bytes --]

[-- Attachment #2: Type: text/plain, Size: 153 bytes --]

_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

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

end of thread, other threads:[~2013-09-07  0:20 UTC | newest]

Thread overview: 100+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-08-23 23:15 [RFC PATCH 00/14] RFCv2: device thermal limits represented in device tree nodes Eduardo Valentin
2013-08-23 23:15 ` [lm-sensors] " Eduardo Valentin
2013-08-23 23:15 ` Eduardo Valentin
2013-08-23 23:15 ` [RFC PATCH 01/14] cpufreq: cpufreq-cpu0: add dt node parsing for 'cooling-zones' Eduardo Valentin
2013-08-23 23:15   ` [lm-sensors] " Eduardo Valentin
2013-08-23 23:15   ` Eduardo Valentin
2013-08-26  4:42   ` Viresh Kumar
2013-08-26  4:54     ` [lm-sensors] " Viresh Kumar
2013-08-26 12:13     ` Eduardo Valentin
2013-08-26 12:13       ` [lm-sensors] " Eduardo Valentin
2013-08-26 12:13       ` Eduardo Valentin
2013-08-27  9:29   ` Mark Rutland
2013-08-27  9:29     ` [lm-sensors] " Mark Rutland
2013-08-27  9:29     ` Mark Rutland
2013-08-27 13:05     ` Eduardo Valentin
2013-08-27 13:05       ` [lm-sensors] " Eduardo Valentin
2013-08-27 13:05       ` Eduardo Valentin
2013-08-27 13:05       ` Eduardo Valentin
2013-08-23 23:15 ` [RFC PATCH 02/14] drivers: thermal: introduce device tree parser Eduardo Valentin
2013-08-23 23:15   ` [lm-sensors] " Eduardo Valentin
2013-08-23 23:15   ` Eduardo Valentin
2013-08-27 10:22   ` Mark Rutland
2013-08-27 10:22     ` [lm-sensors] " Mark Rutland
2013-08-27 13:44     ` Eduardo Valentin
2013-08-27 13:44       ` [lm-sensors] " Eduardo Valentin
2013-08-27 16:23       ` Mark Rutland
2013-08-27 16:23         ` [lm-sensors] " Mark Rutland
2013-08-27 18:17         ` Eduardo Valentin
2013-08-27 18:17           ` [lm-sensors] " Eduardo Valentin
2013-08-29 23:19           ` Eduardo Valentin
2013-08-29 23:19             ` [lm-sensors] " Eduardo Valentin
2013-09-02  8:14             ` Wei Ni
2013-09-02  8:14               ` [lm-sensors] " Wei Ni
2013-09-02 16:28             ` Eduardo Valentin
2013-09-02 16:28               ` [lm-sensors] " Eduardo Valentin
2013-09-03 13:15             ` Mark Rutland
2013-09-03 13:15               ` [lm-sensors] " Mark Rutland
2013-09-03 17:12               ` Eduardo Valentin
2013-09-03 17:12                 ` [lm-sensors] " Eduardo Valentin
2013-09-07  0:19               ` Eduardo Valentin
2013-09-07  0:19                 ` [lm-sensors] " Eduardo Valentin
2013-08-23 23:15 ` [RFC PATCH 03/14] hwmon: lm75: expose to thermal fw via DT nodes Eduardo Valentin
2013-08-23 23:15   ` [lm-sensors] " Eduardo Valentin
2013-08-23 23:15   ` Eduardo Valentin
2013-08-23 23:39   ` Guenter Roeck
2013-08-23 23:39     ` [lm-sensors] " Guenter Roeck
2013-08-26 12:11     ` Eduardo Valentin
2013-08-26 12:11       ` [lm-sensors] " Eduardo Valentin
2013-08-26 12:11       ` Eduardo Valentin
2013-08-23 23:50   ` Guenter Roeck
2013-08-23 23:50     ` [lm-sensors] " Guenter Roeck
2013-08-26 12:15     ` Eduardo Valentin
2013-08-26 12:15       ` [lm-sensors] " Eduardo Valentin
2013-08-26 12:15       ` Eduardo Valentin
2013-08-27 10:26   ` Mark Rutland
2013-08-27 10:26     ` [lm-sensors] " Mark Rutland
2013-08-23 23:15 ` [RFC PATCH 04/14] hwmon: tmp102: " Eduardo Valentin
2013-08-23 23:15   ` [lm-sensors] " Eduardo Valentin
2013-08-23 23:15   ` Eduardo Valentin
2013-08-27 10:27   ` Mark Rutland
2013-08-27 10:27     ` [lm-sensors] " Mark Rutland
2013-08-23 23:15 ` [RFC PATCH 05/14] thermal: ti-soc-thermal: use thermal DT infrastructure Eduardo Valentin
2013-08-23 23:15   ` [lm-sensors] " Eduardo Valentin
2013-08-23 23:15   ` Eduardo Valentin
2013-08-23 23:15 ` [RFC PATCH 06/14] arm: dts: add omap4 CPU thermal data Eduardo Valentin
2013-08-23 23:15   ` [lm-sensors] " Eduardo Valentin
2013-08-23 23:15   ` Eduardo Valentin
2013-08-23 23:15   ` Eduardo Valentin
2013-08-23 23:15 ` [RFC PATCH 07/14] arm: dts: add omap4430 " Eduardo Valentin
2013-08-23 23:15   ` [lm-sensors] " Eduardo Valentin
2013-08-23 23:15   ` Eduardo Valentin
2013-08-23 23:15   ` Eduardo Valentin
2013-08-23 23:15 ` [RFC PATCH 08/14] arm: dts: add omap4460 " Eduardo Valentin
2013-08-23 23:15   ` [lm-sensors] " Eduardo Valentin
2013-08-23 23:15   ` Eduardo Valentin
2013-08-23 23:15   ` Eduardo Valentin
2013-08-23 23:15 ` [RFC PATCH 09/14] arm: dts: point to cooling-zones on omap4430 cpu node Eduardo Valentin
2013-08-23 23:15   ` [lm-sensors] " Eduardo Valentin
2013-08-23 23:15   ` Eduardo Valentin
2013-08-23 23:15   ` Eduardo Valentin
2013-08-23 23:15 ` [RFC PATCH 10/14] arm: dts: point to cooling-zones on omap4460 " Eduardo Valentin
2013-08-23 23:15   ` [lm-sensors] " Eduardo Valentin
2013-08-23 23:15   ` Eduardo Valentin
2013-08-23 23:15   ` Eduardo Valentin
2013-08-23 23:15 ` [RFC PATCH 11/14] arm: dts: add omap5 GPU thermal data Eduardo Valentin
2013-08-23 23:15   ` [lm-sensors] " Eduardo Valentin
2013-08-23 23:15   ` Eduardo Valentin
2013-08-23 23:15   ` Eduardo Valentin
2013-08-23 23:15 ` [RFC PATCH 12/14] arm: dts: add omap5 CORE " Eduardo Valentin
2013-08-23 23:15   ` [lm-sensors] " Eduardo Valentin
2013-08-23 23:15   ` Eduardo Valentin
2013-08-23 23:15   ` Eduardo Valentin
2013-08-23 23:15 ` [RFC PATCH 13/14] arm: dts: add omap5 " Eduardo Valentin
2013-08-23 23:15   ` [lm-sensors] " Eduardo Valentin
2013-08-23 23:15   ` Eduardo Valentin
2013-08-23 23:15   ` Eduardo Valentin
2013-08-23 23:15 ` [RFC PATCH 14/14] arm: dts: point to cooling-zones on omap5 cpu node Eduardo Valentin
2013-08-23 23:15   ` [lm-sensors] " Eduardo Valentin
2013-08-23 23:15   ` Eduardo Valentin
2013-08-23 23:15   ` Eduardo Valentin

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.