aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-05-09 12:40:49 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-05-09 12:40:49 -0400
commitb29bdba51924f6fd5971352ba111784dee3a5853 (patch)
tree95f8b7adfd75ce1d6c86b06f9347247aefecd075
parente0fd9affeb64088eff407dfc98bbd3a5c17ea479 (diff)
parentde6558dc964f6a3243218f17d8032ad810864e2b (diff)
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux
Pull thermal management update from Zhang Rui: "The most important one is to build thermal core and governor and cpu cooling code into one module. This fixes a regression that thermal core does not work if it is built as module, since 3.7. I'll backport them to stable kernel once those changes are in upstream. The largest batch is the thermal kernel-doc & coding style updates/cleanups from Eduardo. Highlights: - build all thermal framework code into one module to fix a regression that thermal does not work if it is built as module. - Marvell Armada 370/XP thermal sensor driver - thermal core/cpu cooling kernel-doc & coding style updates and cleanups. - Add Eduardo Valentin as thermal sub-maintainer, both in mailing list and patchwork. He will help me on arm thermal drivers." * 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux: (68 commits) thermal: db8500_cpufreq_cooling: remove usage of IS_ERR_OR_NULL() thermal: thermal_core: remove usage of IS_ERR_OR_NULL thermal: cpu_cooling: improve line breaking thermal: cpu_cooling: alignment improvements thermal: cpu_cooling: remove checkpatch.pl warning thermal: cpu_cooling: remove trailing blank line thermal: cpu_cooling: align on open parenthesis thermal: cpu_cooling: standardize comment style thermal: cpu_cooling: standardize end of function thermal: cpu_cooling: remove trailing white spaces Thermal: update documentation for thermal_zone_device_register thermal: update kernel-doc for thermal_zone_device_register thermal: update kernel-doc for create_trip_attrs thermal: update kernel-doc for thermal_cooling_device_register thermal: update kernel-doc for thermal_zone_unbind_cooling_device thermal: update kernel-doc for thermal_zone_bind_cooling_device thermal: use EXPORT_SYMBOL_GPL thermal: rename notify_thermal_framework to thermal_notify_framework thermal: update driver license thermal: use strlcpy instead of strcpy ...
-rw-r--r--Documentation/devicetree/bindings/thermal/armada-thermal.txt22
-rw-r--r--Documentation/thermal/exynos_thermal_emulation8
-rw-r--r--Documentation/thermal/sysfs-api.txt28
-rw-r--r--MAINTAINERS3
-rw-r--r--drivers/thermal/Kconfig28
-rw-r--r--drivers/thermal/Makefile10
-rw-r--r--drivers/thermal/armada_thermal.c232
-rw-r--r--drivers/thermal/cpu_cooling.c295
-rw-r--r--drivers/thermal/db8500_cpufreq_cooling.c2
-rw-r--r--drivers/thermal/db8500_thermal.c19
-rw-r--r--drivers/thermal/dove_thermal.c7
-rw-r--r--drivers/thermal/exynos_thermal.c196
-rw-r--r--drivers/thermal/fair_share.c15
-rw-r--r--drivers/thermal/kirkwood_thermal.c12
-rw-r--r--drivers/thermal/rcar_thermal.c34
-rw-r--r--drivers/thermal/step_wise.c26
-rw-r--r--drivers/thermal/thermal_core.c (renamed from drivers/thermal/thermal_sys.c)197
-rw-r--r--drivers/thermal/thermal_core.h27
-rw-r--r--drivers/thermal/user_space.c15
-rw-r--r--include/linux/cpu_cooling.h25
-rw-r--r--include/linux/thermal.h15
21 files changed, 858 insertions, 358 deletions
diff --git a/Documentation/devicetree/bindings/thermal/armada-thermal.txt b/Documentation/devicetree/bindings/thermal/armada-thermal.txt
new file mode 100644
index 000000000000..fff93d5f92de
--- /dev/null
+++ b/Documentation/devicetree/bindings/thermal/armada-thermal.txt
@@ -0,0 +1,22 @@
1* Marvell Armada 370/XP thermal management
2
3Required properties:
4
5- compatible: Should be set to one of the following:
6 marvell,armada370-thermal
7 marvell,armadaxp-thermal
8
9- reg: Device's register space.
10 Two entries are expected, see the examples below.
11 The first one is required for the sensor register;
12 the second one is required for the control register
13 to be used for sensor initialization (a.k.a. calibration).
14
15Example:
16
17 thermal@d0018300 {
18 compatible = "marvell,armada370-thermal";
19 reg = <0xd0018300 0x4
20 0xd0018304 0x4>;
21 status = "okay";
22 };
diff --git a/Documentation/thermal/exynos_thermal_emulation b/Documentation/thermal/exynos_thermal_emulation
index b73bbfb697bb..36a3e79c1203 100644
--- a/Documentation/thermal/exynos_thermal_emulation
+++ b/Documentation/thermal/exynos_thermal_emulation
@@ -13,11 +13,11 @@ Thermal emulation mode supports software debug for TMU's operation. User can set
13manually with software code and TMU will read current temperature from user value not from 13manually with software code and TMU will read current temperature from user value not from
14sensor's value. 14sensor's value.
15 15
16Enabling CONFIG_EXYNOS_THERMAL_EMUL option will make this support in available. 16Enabling CONFIG_THERMAL_EMULATION option will make this support available.
17When it's enabled, sysfs node will be created under 17When it's enabled, sysfs node will be created as
18/sys/bus/platform/devices/'exynos device name'/ with name of 'emulation'. 18/sys/devices/virtual/thermal/thermal_zone'zone id'/emul_temp.
19 19
20The sysfs node, 'emulation', will contain value 0 for the initial state. When you input any 20The sysfs node, 'emul_node', will contain value 0 for the initial state. When you input any
21temperature you want to update to sysfs node, it automatically enable emulation mode and 21temperature you want to update to sysfs node, it automatically enable emulation mode and
22current temperature will be changed into it. 22current temperature will be changed into it.
23(Exynos also supports user changable delay time which would be used to delay of 23(Exynos also supports user changable delay time which would be used to delay of
diff --git a/Documentation/thermal/sysfs-api.txt b/Documentation/thermal/sysfs-api.txt
index 6859661c9d31..a71bd5b90fe8 100644
--- a/Documentation/thermal/sysfs-api.txt
+++ b/Documentation/thermal/sysfs-api.txt
@@ -31,15 +31,17 @@ temperature) and throttle appropriate devices.
311. thermal sysfs driver interface functions 311. thermal sysfs driver interface functions
32 32
331.1 thermal zone device interface 331.1 thermal zone device interface
341.1.1 struct thermal_zone_device *thermal_zone_device_register(char *name, 341.1.1 struct thermal_zone_device *thermal_zone_device_register(char *type,
35 int trips, int mask, void *devdata, 35 int trips, int mask, void *devdata,
36 struct thermal_zone_device_ops *ops) 36 struct thermal_zone_device_ops *ops,
37 const struct thermal_zone_params *tzp,
38 int passive_delay, int polling_delay))
37 39
38 This interface function adds a new thermal zone device (sensor) to 40 This interface function adds a new thermal zone device (sensor) to
39 /sys/class/thermal folder as thermal_zone[0-*]. It tries to bind all the 41 /sys/class/thermal folder as thermal_zone[0-*]. It tries to bind all the
40 thermal cooling devices registered at the same time. 42 thermal cooling devices registered at the same time.
41 43
42 name: the thermal zone name. 44 type: the thermal zone type.
43 trips: the total number of trip points this thermal zone supports. 45 trips: the total number of trip points this thermal zone supports.
44 mask: Bit string: If 'n'th bit is set, then trip point 'n' is writeable. 46 mask: Bit string: If 'n'th bit is set, then trip point 'n' is writeable.
45 devdata: device private data 47 devdata: device private data
@@ -57,6 +59,12 @@ temperature) and throttle appropriate devices.
57 will be fired. 59 will be fired.
58 .set_emul_temp: set the emulation temperature which helps in debugging 60 .set_emul_temp: set the emulation temperature which helps in debugging
59 different threshold temperature points. 61 different threshold temperature points.
62 tzp: thermal zone platform parameters.
63 passive_delay: number of milliseconds to wait between polls when
64 performing passive cooling.
65 polling_delay: number of milliseconds to wait between polls when checking
66 whether trip points have been crossed (0 for interrupt driven systems).
67
60 68
611.1.2 void thermal_zone_device_unregister(struct thermal_zone_device *tz) 691.1.2 void thermal_zone_device_unregister(struct thermal_zone_device *tz)
62 70
@@ -265,6 +273,10 @@ emul_temp
265 Unit: millidegree Celsius 273 Unit: millidegree Celsius
266 WO, Optional 274 WO, Optional
267 275
276 WARNING: Be careful while enabling this option on production systems,
277 because userland can easily disable the thermal policy by simply
278 flooding this sysfs node with low temperature values.
279
268***************************** 280*****************************
269* Cooling device attributes * 281* Cooling device attributes *
270***************************** 282*****************************
@@ -363,7 +375,7 @@ This function returns the thermal_instance corresponding to a given
363{thermal_zone, cooling_device, trip_point} combination. Returns NULL 375{thermal_zone, cooling_device, trip_point} combination. Returns NULL
364if such an instance does not exist. 376if such an instance does not exist.
365 377
3665.3:notify_thermal_framework: 3785.3:thermal_notify_framework:
367This function handles the trip events from sensor drivers. It starts 379This function handles the trip events from sensor drivers. It starts
368throttling the cooling devices according to the policy configured. 380throttling the cooling devices according to the policy configured.
369For CRITICAL and HOT trip points, this notifies the respective drivers, 381For CRITICAL and HOT trip points, this notifies the respective drivers,
@@ -375,11 +387,3 @@ platform data is provided, this uses the step_wise throttling policy.
375This function serves as an arbitrator to set the state of a cooling 387This function serves as an arbitrator to set the state of a cooling
376device. It sets the cooling device to the deepest cooling state if 388device. It sets the cooling device to the deepest cooling state if
377possible. 389possible.
378
3795.5:thermal_register_governor:
380This function lets the various thermal governors to register themselves
381with the Thermal framework. At run time, depending on a zone's platform
382data, a particular governor is used for throttling.
383
3845.6:thermal_unregister_governor:
385This function unregisters a governor from the thermal framework.
diff --git a/MAINTAINERS b/MAINTAINERS
index 5f5c895e6621..3d7782b9f90d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8029,11 +8029,14 @@ F: arch/xtensa/
8029 8029
8030THERMAL 8030THERMAL
8031M: Zhang Rui <rui.zhang@intel.com> 8031M: Zhang Rui <rui.zhang@intel.com>
8032M: Eduardo Valentin <eduardo.valentin@ti.com>
8032L: linux-pm@vger.kernel.org 8033L: linux-pm@vger.kernel.org
8033T: git git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux.git 8034T: git git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux.git
8035Q: https://patchwork.kernel.org/project/linux-pm/list/
8034S: Supported 8036S: Supported
8035F: drivers/thermal/ 8037F: drivers/thermal/
8036F: include/linux/thermal.h 8038F: include/linux/thermal.h
8039F: include/linux/cpu_cooling.h
8037 8040
8038THINGM BLINK(1) USB RGB LED DRIVER 8041THINGM BLINK(1) USB RGB LED DRIVER
8039M: Vivien Didelot <vivien.didelot@savoirfairelinux.com> 8042M: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index a764f165b589..5e3c02554d99 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -67,15 +67,16 @@ config THERMAL_GOV_USER_SPACE
67 Enable this to let the user space manage the platform thermals. 67 Enable this to let the user space manage the platform thermals.
68 68
69config CPU_THERMAL 69config CPU_THERMAL
70 tristate "generic cpu cooling support" 70 bool "generic cpu cooling support"
71 depends on CPU_FREQ 71 depends on CPU_FREQ
72 select CPU_FREQ_TABLE 72 select CPU_FREQ_TABLE
73 help 73 help
74 This implements the generic cpu cooling mechanism through frequency 74 This implements the generic cpu cooling mechanism through frequency
75 reduction, cpu hotplug and any other ways of reducing temperature. An 75 reduction. An ACPI version of this already exists
76 ACPI version of this already exists(drivers/acpi/processor_thermal.c). 76 (drivers/acpi/processor_thermal.c).
77 This will be useful for platforms using the generic thermal interface 77 This will be useful for platforms using the generic thermal interface
78 and not the ACPI interface. 78 and not the ACPI interface.
79
79 If you want this support, you should say Y here. 80 If you want this support, you should say Y here.
80 81
81config THERMAL_EMULATION 82config THERMAL_EMULATION
@@ -86,6 +87,10 @@ config THERMAL_EMULATION
86 user can manually input temperature and test the different trip 87 user can manually input temperature and test the different trip
87 threshold behaviour for simulation purpose. 88 threshold behaviour for simulation purpose.
88 89
90 WARNING: Be careful while enabling this option on production systems,
91 because userland can easily disable the thermal policy by simply
92 flooding this sysfs node with low temperature values.
93
89config SPEAR_THERMAL 94config SPEAR_THERMAL
90 bool "SPEAr thermal sensor driver" 95 bool "SPEAr thermal sensor driver"
91 depends on PLAT_SPEAR 96 depends on PLAT_SPEAR
@@ -117,15 +122,6 @@ config EXYNOS_THERMAL
117 If you say yes here you get support for TMU (Thermal Management 122 If you say yes here you get support for TMU (Thermal Management
118 Unit) on SAMSUNG EXYNOS series of SoC. 123 Unit) on SAMSUNG EXYNOS series of SoC.
119 124
120config EXYNOS_THERMAL_EMUL
121 bool "EXYNOS TMU emulation mode support"
122 depends on EXYNOS_THERMAL
123 help
124 Exynos 4412 and 4414 and 5 series has emulation mode on TMU.
125 Enable this option will be make sysfs node in exynos thermal platform
126 device directory to support emulation mode. With emulation mode sysfs
127 node, you can manually input temperature to TMU for simulation purpose.
128
129config DOVE_THERMAL 125config DOVE_THERMAL
130 tristate "Temperature sensor on Marvell Dove SoCs" 126 tristate "Temperature sensor on Marvell Dove SoCs"
131 depends on ARCH_DOVE 127 depends on ARCH_DOVE
@@ -144,6 +140,14 @@ config DB8500_THERMAL
144 created. Cooling devices can be bound to the trip points to cool this 140 created. Cooling devices can be bound to the trip points to cool this
145 thermal zone if trip points reached. 141 thermal zone if trip points reached.
146 142
143config ARMADA_THERMAL
144 tristate "Armada 370/XP thermal management"
145 depends on ARCH_MVEBU
146 depends on OF
147 help
148 Enable this option if you want to have support for thermal management
149 controller present in Armada 370 and Armada XP SoC.
150
147config DB8500_CPUFREQ_COOLING 151config DB8500_CPUFREQ_COOLING
148 tristate "DB8500 cpufreq cooling" 152 tristate "DB8500 cpufreq cooling"
149 depends on ARCH_U8500 153 depends on ARCH_U8500
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index d3a2b38c31e8..c054d410ac3f 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -3,14 +3,15 @@
3# 3#
4 4
5obj-$(CONFIG_THERMAL) += thermal_sys.o 5obj-$(CONFIG_THERMAL) += thermal_sys.o
6thermal_sys-y += thermal_core.o
6 7
7# governors 8# governors
8obj-$(CONFIG_THERMAL_GOV_FAIR_SHARE) += fair_share.o 9thermal_sys-$(CONFIG_THERMAL_GOV_FAIR_SHARE) += fair_share.o
9obj-$(CONFIG_THERMAL_GOV_STEP_WISE) += step_wise.o 10thermal_sys-$(CONFIG_THERMAL_GOV_STEP_WISE) += step_wise.o
10obj-$(CONFIG_THERMAL_GOV_USER_SPACE) += user_space.o 11thermal_sys-$(CONFIG_THERMAL_GOV_USER_SPACE) += user_space.o
11 12
12# cpufreq cooling 13# cpufreq cooling
13obj-$(CONFIG_CPU_THERMAL) += cpu_cooling.o 14thermal_sys-$(CONFIG_CPU_THERMAL) += cpu_cooling.o
14 15
15# platform thermal drivers 16# platform thermal drivers
16obj-$(CONFIG_SPEAR_THERMAL) += spear_thermal.o 17obj-$(CONFIG_SPEAR_THERMAL) += spear_thermal.o
@@ -19,6 +20,7 @@ obj-$(CONFIG_KIRKWOOD_THERMAL) += kirkwood_thermal.o
19obj-$(CONFIG_EXYNOS_THERMAL) += exynos_thermal.o 20obj-$(CONFIG_EXYNOS_THERMAL) += exynos_thermal.o
20obj-$(CONFIG_DOVE_THERMAL) += dove_thermal.o 21obj-$(CONFIG_DOVE_THERMAL) += dove_thermal.o
21obj-$(CONFIG_DB8500_THERMAL) += db8500_thermal.o 22obj-$(CONFIG_DB8500_THERMAL) += db8500_thermal.o
23obj-$(CONFIG_ARMADA_THERMAL) += armada_thermal.o
22obj-$(CONFIG_DB8500_CPUFREQ_COOLING) += db8500_cpufreq_cooling.o 24obj-$(CONFIG_DB8500_CPUFREQ_COOLING) += db8500_cpufreq_cooling.o
23obj-$(CONFIG_INTEL_POWERCLAMP) += intel_powerclamp.o 25obj-$(CONFIG_INTEL_POWERCLAMP) += intel_powerclamp.o
24 26
diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c
new file mode 100644
index 000000000000..5b4d75fd7b49
--- /dev/null
+++ b/drivers/thermal/armada_thermal.c
@@ -0,0 +1,232 @@
1/*
2 * Marvell Armada 370/XP thermal sensor driver
3 *
4 * Copyright (C) 2013 Marvell
5 *
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 */
16#include <linux/device.h>
17#include <linux/err.h>
18#include <linux/io.h>
19#include <linux/kernel.h>
20#include <linux/of.h>
21#include <linux/module.h>
22#include <linux/delay.h>
23#include <linux/platform_device.h>
24#include <linux/of_device.h>
25#include <linux/thermal.h>
26
27#define THERMAL_VALID_OFFSET 9
28#define THERMAL_VALID_MASK 0x1
29#define THERMAL_TEMP_OFFSET 10
30#define THERMAL_TEMP_MASK 0x1ff
31
32/* Thermal Manager Control and Status Register */
33#define PMU_TDC0_SW_RST_MASK (0x1 << 1)
34#define PMU_TM_DISABLE_OFFS 0
35#define PMU_TM_DISABLE_MASK (0x1 << PMU_TM_DISABLE_OFFS)
36#define PMU_TDC0_REF_CAL_CNT_OFFS 11
37#define PMU_TDC0_REF_CAL_CNT_MASK (0x1ff << PMU_TDC0_REF_CAL_CNT_OFFS)
38#define PMU_TDC0_OTF_CAL_MASK (0x1 << 30)
39#define PMU_TDC0_START_CAL_MASK (0x1 << 25)
40
41struct armada_thermal_ops;
42
43/* Marvell EBU Thermal Sensor Dev Structure */
44struct armada_thermal_priv {
45 void __iomem *sensor;
46 void __iomem *control;
47 struct armada_thermal_ops *ops;
48};
49
50struct armada_thermal_ops {
51 /* Initialize the sensor */
52 void (*init_sensor)(struct armada_thermal_priv *);
53
54 /* Test for a valid sensor value (optional) */
55 bool (*is_valid)(struct armada_thermal_priv *);
56};
57
58static void armadaxp_init_sensor(struct armada_thermal_priv *priv)
59{
60 unsigned long reg;
61
62 reg = readl_relaxed(priv->control);
63 reg |= PMU_TDC0_OTF_CAL_MASK;
64 writel(reg, priv->control);
65
66 /* Reference calibration value */
67 reg &= ~PMU_TDC0_REF_CAL_CNT_MASK;
68 reg |= (0xf1 << PMU_TDC0_REF_CAL_CNT_OFFS);
69 writel(reg, priv->control);
70
71 /* Reset the sensor */
72 reg = readl_relaxed(priv->control);
73 writel((reg | PMU_TDC0_SW_RST_MASK), priv->control);
74
75 writel(reg, priv->control);
76
77 /* Enable the sensor */
78 reg = readl_relaxed(priv->sensor);
79 reg &= ~PMU_TM_DISABLE_MASK;
80 writel(reg, priv->sensor);
81}
82
83static void armada370_init_sensor(struct armada_thermal_priv *priv)
84{
85 unsigned long reg;
86
87 reg = readl_relaxed(priv->control);
88 reg |= PMU_TDC0_OTF_CAL_MASK;
89 writel(reg, priv->control);
90
91 /* Reference calibration value */
92 reg &= ~PMU_TDC0_REF_CAL_CNT_MASK;
93 reg |= (0xf1 << PMU_TDC0_REF_CAL_CNT_OFFS);
94 writel(reg, priv->control);
95
96 reg &= ~PMU_TDC0_START_CAL_MASK;
97 writel(reg, priv->control);
98
99 mdelay(10);
100}
101
102static bool armada_is_valid(struct armada_thermal_priv *priv)
103{
104 unsigned long reg = readl_relaxed(priv->sensor);
105
106 return (reg >> THERMAL_VALID_OFFSET) & THERMAL_VALID_MASK;
107}
108
109static int armada_get_temp(struct thermal_zone_device *thermal,
110 unsigned long *temp)
111{
112 struct armada_thermal_priv *priv = thermal->devdata;
113 unsigned long reg;
114
115 /* Valid check */
116 if (priv->ops->is_valid && !priv->ops->is_valid(priv)) {
117 dev_err(&thermal->device,
118 "Temperature sensor reading not valid\n");
119 return -EIO;
120 }
121
122 reg = readl_relaxed(priv->sensor);
123 reg = (reg >> THERMAL_TEMP_OFFSET) & THERMAL_TEMP_MASK;
124 *temp = (3153000000UL - (10000000UL*reg)) / 13825;
125 return 0;
126}
127
128static struct thermal_zone_device_ops ops = {
129 .get_temp = armada_get_temp,
130};
131
132static const struct armada_thermal_ops armadaxp_ops = {
133 .init_sensor = armadaxp_init_sensor,
134};
135
136static const struct armada_thermal_ops armada370_ops = {
137 .is_valid = armada_is_valid,
138 .init_sensor = armada370_init_sensor,
139};
140
141static const struct of_device_id armada_thermal_id_table[] = {
142 {
143 .compatible = "marvell,armadaxp-thermal",
144 .data = &armadaxp_ops,
145 },
146 {
147 .compatible = "marvell,armada370-thermal",
148 .data = &armada370_ops,
149 },
150 {
151 /* sentinel */
152 },
153};
154MODULE_DEVICE_TABLE(of, armada_thermal_id_table);
155
156static int armada_thermal_probe(struct platform_device *pdev)
157{
158 struct thermal_zone_device *thermal;
159 const struct of_device_id *match;
160 struct armada_thermal_priv *priv;
161 struct resource *res;
162
163 match = of_match_device(armada_thermal_id_table, &pdev->dev);
164 if (!match)
165 return -ENODEV;
166
167 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
168 if (!priv)
169 return -ENOMEM;
170
171 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
172 if (!res) {
173 dev_err(&pdev->dev, "Failed to get platform resource\n");
174 return -ENODEV;
175 }
176
177 priv->sensor = devm_ioremap_resource(&pdev->dev, res);
178 if (IS_ERR(priv->sensor))
179 return PTR_ERR(priv->sensor);
180
181 res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
182 if (!res) {
183 dev_err(&pdev->dev, "Failed to get platform resource\n");
184 return -ENODEV;
185 }
186
187 priv->control = devm_ioremap_resource(&pdev->dev, res);
188 if (IS_ERR(priv->control))
189 return PTR_ERR(priv->control);
190
191 priv->ops = (struct armada_thermal_ops *)match->data;
192 priv->ops->init_sensor(priv);
193
194 thermal = thermal_zone_device_register("armada_thermal", 0, 0,
195 priv, &ops, NULL, 0, 0);
196 if (IS_ERR(thermal)) {
197 dev_err(&pdev->dev,
198 "Failed to register thermal zone device\n");
199 return PTR_ERR(thermal);
200 }
201
202 platform_set_drvdata(pdev, thermal);
203
204 return 0;
205}
206
207static int armada_thermal_exit(struct platform_device *pdev)
208{
209 struct thermal_zone_device *armada_thermal =
210 platform_get_drvdata(pdev);
211
212 thermal_zone_device_unregister(armada_thermal);
213 platform_set_drvdata(pdev, NULL);
214
215 return 0;
216}
217
218static struct platform_driver armada_thermal_driver = {
219 .probe = armada_thermal_probe,
220 .remove = armada_thermal_exit,
221 .driver = {
222 .name = "armada_thermal",
223 .owner = THIS_MODULE,
224 .of_match_table = of_match_ptr(armada_thermal_id_table),
225 },
226};
227
228module_platform_driver(armada_thermal_driver);
229
230MODULE_AUTHOR("Ezequiel Garcia <ezequiel.garcia@free-electrons.com>");
231MODULE_DESCRIPTION("Armada 370/XP thermal driver");
232MODULE_LICENSE("GPL v2");
diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index 8dc44cbb3e09..c94bf2e5de62 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -20,10 +20,8 @@
20 * 20 *
21 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 21 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
22 */ 22 */
23#include <linux/kernel.h>
24#include <linux/module.h> 23#include <linux/module.h>
25#include <linux/thermal.h> 24#include <linux/thermal.h>
26#include <linux/platform_device.h>
27#include <linux/cpufreq.h> 25#include <linux/cpufreq.h>
28#include <linux/err.h> 26#include <linux/err.h>
29#include <linux/slab.h> 27#include <linux/slab.h>
@@ -31,21 +29,19 @@
31#include <linux/cpu_cooling.h> 29#include <linux/cpu_cooling.h>
32 30
33/** 31/**
34 * struct cpufreq_cooling_device 32 * struct cpufreq_cooling_device - data for cooling device with cpufreq
35 * @id: unique integer value corresponding to each cpufreq_cooling_device 33 * @id: unique integer value corresponding to each cpufreq_cooling_device
36 * registered. 34 * registered.
37 * @cool_dev: thermal_cooling_device pointer to keep track of the the 35 * @cool_dev: thermal_cooling_device pointer to keep track of the
38 * egistered cooling device. 36 * registered cooling device.
39 * @cpufreq_state: integer value representing the current state of cpufreq 37 * @cpufreq_state: integer value representing the current state of cpufreq
40 * cooling devices. 38 * cooling devices.
41 * @cpufreq_val: integer value representing the absolute value of the clipped 39 * @cpufreq_val: integer value representing the absolute value of the clipped
42 * frequency. 40 * frequency.
43 * @allowed_cpus: all the cpus involved for this cpufreq_cooling_device. 41 * @allowed_cpus: all the cpus involved for this cpufreq_cooling_device.
44 * @node: list_head to link all cpufreq_cooling_device together.
45 * 42 *
46 * This structure is required for keeping information of each 43 * This structure is required for keeping information of each
47 * cpufreq_cooling_device registered as a list whose head is represented by 44 * cpufreq_cooling_device registered. In order to prevent corruption of this a
48 * cooling_cpufreq_list. In order to prevent corruption of this list a
49 * mutex lock cooling_cpufreq_lock is used. 45 * mutex lock cooling_cpufreq_lock is used.
50 */ 46 */
51struct cpufreq_cooling_device { 47struct cpufreq_cooling_device {
@@ -54,9 +50,7 @@ struct cpufreq_cooling_device {
54 unsigned int cpufreq_state; 50 unsigned int cpufreq_state;
55 unsigned int cpufreq_val; 51 unsigned int cpufreq_val;
56 struct cpumask allowed_cpus; 52 struct cpumask allowed_cpus;
57 struct list_head node;
58}; 53};
59static LIST_HEAD(cooling_cpufreq_list);
60static DEFINE_IDR(cpufreq_idr); 54static DEFINE_IDR(cpufreq_idr);
61static DEFINE_MUTEX(cooling_cpufreq_lock); 55static DEFINE_MUTEX(cooling_cpufreq_lock);
62 56
@@ -70,6 +64,11 @@ static struct cpufreq_cooling_device *notify_device;
70 * get_idr - function to get a unique id. 64 * get_idr - function to get a unique id.
71 * @idr: struct idr * handle used to create a id. 65 * @idr: struct idr * handle used to create a id.
72 * @id: int * value generated by this function. 66 * @id: int * value generated by this function.
67 *
68 * This function will populate @id with an unique
69 * id, using the idr API.
70 *
71 * Return: 0 on success, an error code on failure.
73 */ 72 */
74static int get_idr(struct idr *idr, int *id) 73static int get_idr(struct idr *idr, int *id)
75{ 74{
@@ -81,6 +80,7 @@ static int get_idr(struct idr *idr, int *id)
81 if (unlikely(ret < 0)) 80 if (unlikely(ret < 0))
82 return ret; 81 return ret;
83 *id = ret; 82 *id = ret;
83
84 return 0; 84 return 0;
85} 85}
86 86
@@ -99,63 +99,162 @@ static void release_idr(struct idr *idr, int id)
99/* Below code defines functions to be used for cpufreq as cooling device */ 99/* Below code defines functions to be used for cpufreq as cooling device */
100 100
101/** 101/**
102 * is_cpufreq_valid - function to check if a cpu has frequency transition policy. 102 * is_cpufreq_valid - function to check frequency transitioning capability.
103 * @cpu: cpu for which check is needed. 103 * @cpu: cpu for which check is needed.
104 *
105 * This function will check the current state of the system if
106 * it is capable of changing the frequency for a given @cpu.
107 *
108 * Return: 0 if the system is not currently capable of changing
109 * the frequency of given cpu. !0 in case the frequency is changeable.
104 */ 110 */
105static int is_cpufreq_valid(int cpu) 111static int is_cpufreq_valid(int cpu)
106{ 112{
107 struct cpufreq_policy policy; 113 struct cpufreq_policy policy;
114
108 return !cpufreq_get_policy(&policy, cpu); 115 return !cpufreq_get_policy(&policy, cpu);
109} 116}
110 117
118enum cpufreq_cooling_property {
119 GET_LEVEL,
120 GET_FREQ,
121 GET_MAXL,
122};
123
111/** 124/**
112 * get_cpu_frequency - get the absolute value of frequency from level. 125 * get_property - fetch a property of interest for a give cpu.
113 * @cpu: cpu for which frequency is fetched. 126 * @cpu: cpu for which the property is required
114 * @level: level of frequency, equals cooling state of cpu cooling device 127 * @input: query parameter
115 * e.g level=0 --> 1st MAX FREQ, level=1 ---> 2nd MAX FREQ, .... etc 128 * @output: query return
129 * @property: type of query (frequency, level, max level)
130 *
131 * This is the common function to
132 * 1. get maximum cpu cooling states
133 * 2. translate frequency to cooling state
134 * 3. translate cooling state to frequency
135 * Note that the code may be not in good shape
136 * but it is written in this way in order to:
137 * a) reduce duplicate code as most of the code can be shared.
138 * b) make sure the logic is consistent when translating between
139 * cooling states and frequencies.
140 *
141 * Return: 0 on success, -EINVAL when invalid parameters are passed.
116 */ 142 */
117static unsigned int get_cpu_frequency(unsigned int cpu, unsigned long level) 143static int get_property(unsigned int cpu, unsigned long input,
144 unsigned int *output,
145 enum cpufreq_cooling_property property)
118{ 146{
119 int ret = 0, i = 0; 147 int i, j;
120 unsigned long level_index; 148 unsigned long max_level = 0, level = 0;
121 bool descend = false; 149 unsigned int freq = CPUFREQ_ENTRY_INVALID;
150 int descend = -1;
122 struct cpufreq_frequency_table *table = 151 struct cpufreq_frequency_table *table =
123 cpufreq_frequency_get_table(cpu); 152 cpufreq_frequency_get_table(cpu);
153
154 if (!output)
155 return -EINVAL;
156
124 if (!table) 157 if (!table)
125 return ret; 158 return -EINVAL;
126 159
127 while (table[i].frequency != CPUFREQ_TABLE_END) { 160 for (i = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) {
161 /* ignore invalid entries */
128 if (table[i].frequency == CPUFREQ_ENTRY_INVALID) 162 if (table[i].frequency == CPUFREQ_ENTRY_INVALID)
129 continue; 163 continue;
130 164
131 /*check if table in ascending or descending order*/ 165 /* ignore duplicate entry */
132 if ((table[i + 1].frequency != CPUFREQ_TABLE_END) && 166 if (freq == table[i].frequency)
133 (table[i + 1].frequency < table[i].frequency) 167 continue;
134 && !descend) { 168
135 descend = true; 169 /* get the frequency order */
136 } 170 if (freq != CPUFREQ_ENTRY_INVALID && descend != -1)
171 descend = !!(freq > table[i].frequency);
137 172
138 /*return if level matched and table in descending order*/ 173 freq = table[i].frequency;
139 if (descend && i == level) 174 max_level++;
140 return table[i].frequency;
141 i++;
142 } 175 }
143 i--;
144 176
145 if (level > i || descend) 177 /* get max level */
146 return ret; 178 if (property == GET_MAXL) {
147 level_index = i - level; 179 *output = (unsigned int)max_level;
180 return 0;
181 }
148 182
149 /*Scan the table in reverse order and match the level*/ 183 if (property == GET_FREQ)
150 while (i >= 0) { 184 level = descend ? input : (max_level - input - 1);
185
186 for (i = 0, j = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) {
187 /* ignore invalid entry */
151 if (table[i].frequency == CPUFREQ_ENTRY_INVALID) 188 if (table[i].frequency == CPUFREQ_ENTRY_INVALID)
152 continue; 189 continue;
153 /*return if level matched*/ 190
154 if (i == level_index) 191 /* ignore duplicate entry */
155 return table[i].frequency; 192 if (freq == table[i].frequency)
156 i--; 193 continue;
194
195 /* now we have a valid frequency entry */
196 freq = table[i].frequency;
197
198 if (property == GET_LEVEL && (unsigned int)input == freq) {
199 /* get level by frequency */
200 *output = descend ? j : (max_level - j - 1);
201 return 0;
202 }
203 if (property == GET_FREQ && level == j) {
204 /* get frequency by level */
205 *output = freq;
206 return 0;
207 }
208 j++;
157 } 209 }
158 return ret; 210
211 return -EINVAL;
212}
213
214/**
215 * cpufreq_cooling_get_level - for a give cpu, return the cooling level.
216 * @cpu: cpu for which the level is required
217 * @freq: the frequency of interest
218 *
219 * This function will match the cooling level corresponding to the
220 * requested @freq and return it.
221 *
222 * Return: The matched cooling level on success or THERMAL_CSTATE_INVALID
223 * otherwise.
224 */
225unsigned long cpufreq_cooling_get_level(unsigned int cpu, unsigned int freq)
226{
227 unsigned int val;
228
229 if (get_property(cpu, (unsigned long)freq, &val, GET_LEVEL))
230 return THERMAL_CSTATE_INVALID;
231
232 return (unsigned long)val;
233}
234EXPORT_SYMBOL_GPL(cpufreq_cooling_get_level);
235
236/**
237 * get_cpu_frequency - get the absolute value of frequency from level.
238 * @cpu: cpu for which frequency is fetched.
239 * @level: cooling level
240 *
241 * This function matches cooling level with frequency. Based on a cooling level
242 * of frequency, equals cooling state of cpu cooling device, it will return
243 * the corresponding frequency.
244 * e.g level=0 --> 1st MAX FREQ, level=1 ---> 2nd MAX FREQ, .... etc
245 *
246 * Return: 0 on error, the corresponding frequency otherwise.
247 */
248static unsigned int get_cpu_frequency(unsigned int cpu, unsigned long level)
249{
250 int ret = 0;
251 unsigned int freq;
252
253 ret = get_property(cpu, level, &freq, GET_FREQ);
254 if (ret)
255 return 0;
256
257 return freq;
159} 258}
160 259
161/** 260/**
@@ -163,13 +262,19 @@ static unsigned int get_cpu_frequency(unsigned int cpu, unsigned long level)
163 * @cpufreq_device: cpufreq_cooling_device pointer containing frequency 262 * @cpufreq_device: cpufreq_cooling_device pointer containing frequency
164 * clipping data. 263 * clipping data.
165 * @cooling_state: value of the cooling state. 264 * @cooling_state: value of the cooling state.
265 *
266 * Function used to make sure the cpufreq layer is aware of current thermal
267 * limits. The limits are applied by updating the cpufreq policy.
268 *
269 * Return: 0 on success, an error code otherwise (-EINVAL in case wrong
270 * cooling state).
166 */ 271 */
167static int cpufreq_apply_cooling(struct cpufreq_cooling_device *cpufreq_device, 272static int cpufreq_apply_cooling(struct cpufreq_cooling_device *cpufreq_device,
168 unsigned long cooling_state) 273 unsigned long cooling_state)
169{ 274{
170 unsigned int cpuid, clip_freq; 275 unsigned int cpuid, clip_freq;
171 struct cpumask *maskPtr = &cpufreq_device->allowed_cpus; 276 struct cpumask *mask = &cpufreq_device->allowed_cpus;
172 unsigned int cpu = cpumask_any(maskPtr); 277 unsigned int cpu = cpumask_any(mask);
173 278
174 279
175 /* Check if the old cooling action is same as new cooling action */ 280 /* Check if the old cooling action is same as new cooling action */
@@ -184,7 +289,7 @@ static int cpufreq_apply_cooling(struct cpufreq_cooling_device *cpufreq_device,
184 cpufreq_device->cpufreq_val = clip_freq; 289 cpufreq_device->cpufreq_val = clip_freq;
185 notify_device = cpufreq_device; 290 notify_device = cpufreq_device;
186 291
187 for_each_cpu(cpuid, maskPtr) { 292 for_each_cpu(cpuid, mask) {
188 if (is_cpufreq_valid(cpuid)) 293 if (is_cpufreq_valid(cpuid))
189 cpufreq_update_policy(cpuid); 294 cpufreq_update_policy(cpuid);
190 } 295 }
@@ -199,9 +304,15 @@ static int cpufreq_apply_cooling(struct cpufreq_cooling_device *cpufreq_device,
199 * @nb: struct notifier_block * with callback info. 304 * @nb: struct notifier_block * with callback info.
200 * @event: value showing cpufreq event for which this function invoked. 305 * @event: value showing cpufreq event for which this function invoked.
201 * @data: callback-specific data 306 * @data: callback-specific data
307 *
308 * Callback to highjack the notification on cpufreq policy transition.
309 * Every time there is a change in policy, we will intercept and
310 * update the cpufreq policy with thermal constraints.
311 *
312 * Return: 0 (success)
202 */ 313 */
203static int cpufreq_thermal_notifier(struct notifier_block *nb, 314static int cpufreq_thermal_notifier(struct notifier_block *nb,
204 unsigned long event, void *data) 315 unsigned long event, void *data)
205{ 316{
206 struct cpufreq_policy *policy = data; 317 struct cpufreq_policy *policy = data;
207 unsigned long max_freq = 0; 318 unsigned long max_freq = 0;
@@ -212,7 +323,7 @@ static int cpufreq_thermal_notifier(struct notifier_block *nb,
212 if (cpumask_test_cpu(policy->cpu, &notify_device->allowed_cpus)) 323 if (cpumask_test_cpu(policy->cpu, &notify_device->allowed_cpus))
213 max_freq = notify_device->cpufreq_val; 324 max_freq = notify_device->cpufreq_val;
214 325
215 /* Never exceed user_policy.max*/ 326 /* Never exceed user_policy.max */
216 if (max_freq > policy->user_policy.max) 327 if (max_freq > policy->user_policy.max)
217 max_freq = policy->user_policy.max; 328 max_freq = policy->user_policy.max;
218 329
@@ -222,50 +333,46 @@ static int cpufreq_thermal_notifier(struct notifier_block *nb,
222 return 0; 333 return 0;
223} 334}
224 335
225/* 336/* cpufreq cooling device callback functions are defined below */
226 * cpufreq cooling device callback functions are defined below
227 */
228 337
229/** 338/**
230 * cpufreq_get_max_state - callback function to get the max cooling state. 339 * cpufreq_get_max_state - callback function to get the max cooling state.
231 * @cdev: thermal cooling device pointer. 340 * @cdev: thermal cooling device pointer.
232 * @state: fill this variable with the max cooling state. 341 * @state: fill this variable with the max cooling state.
342 *
343 * Callback for the thermal cooling device to return the cpufreq
344 * max cooling state.
345 *
346 * Return: 0 on success, an error code otherwise.
233 */ 347 */
234static int cpufreq_get_max_state(struct thermal_cooling_device *cdev, 348static int cpufreq_get_max_state(struct thermal_cooling_device *cdev,
235 unsigned long *state) 349 unsigned long *state)
236{ 350{
237 struct cpufreq_cooling_device *cpufreq_device = cdev->devdata; 351 struct cpufreq_cooling_device *cpufreq_device = cdev->devdata;
238 struct cpumask *maskPtr = &cpufreq_device->allowed_cpus; 352 struct cpumask *mask = &cpufreq_device->allowed_cpus;
239 unsigned int cpu; 353 unsigned int cpu;
240 struct cpufreq_frequency_table *table; 354 unsigned int count = 0;
241 unsigned long count = 0; 355 int ret;
242 int i = 0;
243
244 cpu = cpumask_any(maskPtr);
245 table = cpufreq_frequency_get_table(cpu);
246 if (!table) {
247 *state = 0;
248 return 0;
249 }
250 356
251 for (i = 0; (table[i].frequency != CPUFREQ_TABLE_END); i++) { 357 cpu = cpumask_any(mask);
252 if (table[i].frequency == CPUFREQ_ENTRY_INVALID)
253 continue;
254 count++;
255 }
256 358
257 if (count > 0) { 359 ret = get_property(cpu, 0, &count, GET_MAXL);
258 *state = --count;
259 return 0;
260 }
261 360
262 return -EINVAL; 361 if (count > 0)
362 *state = count;
363
364 return ret;
263} 365}
264 366
265/** 367/**
266 * cpufreq_get_cur_state - callback function to get the current cooling state. 368 * cpufreq_get_cur_state - callback function to get the current cooling state.
267 * @cdev: thermal cooling device pointer. 369 * @cdev: thermal cooling device pointer.
268 * @state: fill this variable with the current cooling state. 370 * @state: fill this variable with the current cooling state.
371 *
372 * Callback for the thermal cooling device to return the cpufreq
373 * current cooling state.
374 *
375 * Return: 0 on success, an error code otherwise.
269 */ 376 */
270static int cpufreq_get_cur_state(struct thermal_cooling_device *cdev, 377static int cpufreq_get_cur_state(struct thermal_cooling_device *cdev,
271 unsigned long *state) 378 unsigned long *state)
@@ -273,6 +380,7 @@ static int cpufreq_get_cur_state(struct thermal_cooling_device *cdev,
273 struct cpufreq_cooling_device *cpufreq_device = cdev->devdata; 380 struct cpufreq_cooling_device *cpufreq_device = cdev->devdata;
274 381
275 *state = cpufreq_device->cpufreq_state; 382 *state = cpufreq_device->cpufreq_state;
383
276 return 0; 384 return 0;
277} 385}
278 386
@@ -280,6 +388,11 @@ static int cpufreq_get_cur_state(struct thermal_cooling_device *cdev,
280 * cpufreq_set_cur_state - callback function to set the current cooling state. 388 * cpufreq_set_cur_state - callback function to set the current cooling state.
281 * @cdev: thermal cooling device pointer. 389 * @cdev: thermal cooling device pointer.
282 * @state: set this variable to the current cooling state. 390 * @state: set this variable to the current cooling state.
391 *
392 * Callback for the thermal cooling device to change the cpufreq
393 * current cooling state.
394 *
395 * Return: 0 on success, an error code otherwise.
283 */ 396 */
284static int cpufreq_set_cur_state(struct thermal_cooling_device *cdev, 397static int cpufreq_set_cur_state(struct thermal_cooling_device *cdev,
285 unsigned long state) 398 unsigned long state)
@@ -304,9 +417,16 @@ static struct notifier_block thermal_cpufreq_notifier_block = {
304/** 417/**
305 * cpufreq_cooling_register - function to create cpufreq cooling device. 418 * cpufreq_cooling_register - function to create cpufreq cooling device.
306 * @clip_cpus: cpumask of cpus where the frequency constraints will happen. 419 * @clip_cpus: cpumask of cpus where the frequency constraints will happen.
420 *
421 * This interface function registers the cpufreq cooling device with the name
422 * "thermal-cpufreq-%x". This api can support multiple instances of cpufreq
423 * cooling devices.
424 *
425 * Return: a valid struct thermal_cooling_device pointer on success,
426 * on failure, it returns a corresponding ERR_PTR().
307 */ 427 */
308struct thermal_cooling_device *cpufreq_cooling_register( 428struct thermal_cooling_device *
309 const struct cpumask *clip_cpus) 429cpufreq_cooling_register(const struct cpumask *clip_cpus)
310{ 430{
311 struct thermal_cooling_device *cool_dev; 431 struct thermal_cooling_device *cool_dev;
312 struct cpufreq_cooling_device *cpufreq_dev = NULL; 432 struct cpufreq_cooling_device *cpufreq_dev = NULL;
@@ -315,9 +435,9 @@ struct thermal_cooling_device *cpufreq_cooling_register(
315 int ret = 0, i; 435 int ret = 0, i;
316 struct cpufreq_policy policy; 436 struct cpufreq_policy policy;
317 437
318 /*Verify that all the clip cpus have same freq_min, freq_max limit*/ 438 /* Verify that all the clip cpus have same freq_min, freq_max limit */
319 for_each_cpu(i, clip_cpus) { 439 for_each_cpu(i, clip_cpus) {
320 /*continue if cpufreq policy not found and not return error*/ 440 /* continue if cpufreq policy not found and not return error */
321 if (!cpufreq_get_policy(&policy, i)) 441 if (!cpufreq_get_policy(&policy, i))
322 continue; 442 continue;
323 if (min == 0 && max == 0) { 443 if (min == 0 && max == 0) {
@@ -325,12 +445,12 @@ struct thermal_cooling_device *cpufreq_cooling_register(
325 max = policy.cpuinfo.max_freq; 445 max = policy.cpuinfo.max_freq;
326 } else { 446 } else {
327 if (min != policy.cpuinfo.min_freq || 447 if (min != policy.cpuinfo.min_freq ||
328 max != policy.cpuinfo.max_freq) 448 max != policy.cpuinfo.max_freq)
329 return ERR_PTR(-EINVAL); 449 return ERR_PTR(-EINVAL);
330 } 450 }
331 } 451 }
332 cpufreq_dev = kzalloc(sizeof(struct cpufreq_cooling_device), 452 cpufreq_dev = kzalloc(sizeof(struct cpufreq_cooling_device),
333 GFP_KERNEL); 453 GFP_KERNEL);
334 if (!cpufreq_dev) 454 if (!cpufreq_dev)
335 return ERR_PTR(-ENOMEM); 455 return ERR_PTR(-ENOMEM);
336 456
@@ -342,10 +462,11 @@ struct thermal_cooling_device *cpufreq_cooling_register(
342 return ERR_PTR(-EINVAL); 462 return ERR_PTR(-EINVAL);
343 } 463 }
344 464
345 sprintf(dev_name, "thermal-cpufreq-%d", cpufreq_dev->id); 465 snprintf(dev_name, sizeof(dev_name), "thermal-cpufreq-%d",
466 cpufreq_dev->id);
346 467
347 cool_dev = thermal_cooling_device_register(dev_name, cpufreq_dev, 468 cool_dev = thermal_cooling_device_register(dev_name, cpufreq_dev,
348 &cpufreq_cooling_ops); 469 &cpufreq_cooling_ops);
349 if (!cool_dev) { 470 if (!cool_dev) {
350 release_idr(&cpufreq_idr, cpufreq_dev->id); 471 release_idr(&cpufreq_idr, cpufreq_dev->id);
351 kfree(cpufreq_dev); 472 kfree(cpufreq_dev);
@@ -358,17 +479,20 @@ struct thermal_cooling_device *cpufreq_cooling_register(
358 /* Register the notifier for first cpufreq cooling device */ 479 /* Register the notifier for first cpufreq cooling device */
359 if (cpufreq_dev_count == 0) 480 if (cpufreq_dev_count == 0)
360 cpufreq_register_notifier(&thermal_cpufreq_notifier_block, 481 cpufreq_register_notifier(&thermal_cpufreq_notifier_block,
361 CPUFREQ_POLICY_NOTIFIER); 482 CPUFREQ_POLICY_NOTIFIER);
362 cpufreq_dev_count++; 483 cpufreq_dev_count++;
363 484
364 mutex_unlock(&cooling_cpufreq_lock); 485 mutex_unlock(&cooling_cpufreq_lock);
486
365 return cool_dev; 487 return cool_dev;
366} 488}
367EXPORT_SYMBOL(cpufreq_cooling_register); 489EXPORT_SYMBOL_GPL(cpufreq_cooling_register);
368 490
369/** 491/**
370 * cpufreq_cooling_unregister - function to remove cpufreq cooling device. 492 * cpufreq_cooling_unregister - function to remove cpufreq cooling device.
371 * @cdev: thermal cooling device pointer. 493 * @cdev: thermal cooling device pointer.
494 *
495 * This interface function unregisters the "thermal-cpufreq-%x" cooling device.
372 */ 496 */
373void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) 497void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev)
374{ 498{
@@ -378,14 +502,13 @@ void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev)
378 cpufreq_dev_count--; 502 cpufreq_dev_count--;
379 503
380 /* Unregister the notifier for the last cpufreq cooling device */ 504 /* Unregister the notifier for the last cpufreq cooling device */
381 if (cpufreq_dev_count == 0) { 505 if (cpufreq_dev_count == 0)
382 cpufreq_unregister_notifier(&thermal_cpufreq_notifier_block, 506 cpufreq_unregister_notifier(&thermal_cpufreq_notifier_block,
383 CPUFREQ_POLICY_NOTIFIER); 507 CPUFREQ_POLICY_NOTIFIER);
384 }
385 mutex_unlock(&cooling_cpufreq_lock); 508 mutex_unlock(&cooling_cpufreq_lock);
386 509
387 thermal_cooling_device_unregister(cpufreq_dev->cool_dev); 510 thermal_cooling_device_unregister(cpufreq_dev->cool_dev);
388 release_idr(&cpufreq_idr, cpufreq_dev->id); 511 release_idr(&cpufreq_idr, cpufreq_dev->id);
389 kfree(cpufreq_dev); 512 kfree(cpufreq_dev);
390} 513}
391EXPORT_SYMBOL(cpufreq_cooling_unregister); 514EXPORT_SYMBOL_GPL(cpufreq_cooling_unregister);
diff --git a/drivers/thermal/db8500_cpufreq_cooling.c b/drivers/thermal/db8500_cpufreq_cooling.c
index 21419851fc02..786d19263ab0 100644
--- a/drivers/thermal/db8500_cpufreq_cooling.c
+++ b/drivers/thermal/db8500_cpufreq_cooling.c
@@ -37,7 +37,7 @@ static int db8500_cpufreq_cooling_probe(struct platform_device *pdev)
37 cpumask_set_cpu(0, &mask_val); 37 cpumask_set_cpu(0, &mask_val);
38 cdev = cpufreq_cooling_register(&mask_val); 38 cdev = cpufreq_cooling_register(&mask_val);
39 39
40 if (IS_ERR_OR_NULL(cdev)) { 40 if (IS_ERR(cdev)) {
41 dev_err(&pdev->dev, "Failed to register cooling device\n"); 41 dev_err(&pdev->dev, "Failed to register cooling device\n");
42 return PTR_ERR(cdev); 42 return PTR_ERR(cdev);
43 } 43 }
diff --git a/drivers/thermal/db8500_thermal.c b/drivers/thermal/db8500_thermal.c
index 61ce60a35921..1e3b3bf9f993 100644
--- a/drivers/thermal/db8500_thermal.c
+++ b/drivers/thermal/db8500_thermal.c
@@ -419,7 +419,8 @@ static int db8500_thermal_probe(struct platform_device *pdev)
419 low_irq = platform_get_irq_byname(pdev, "IRQ_HOTMON_LOW"); 419 low_irq = platform_get_irq_byname(pdev, "IRQ_HOTMON_LOW");
420 if (low_irq < 0) { 420 if (low_irq < 0) {
421 dev_err(&pdev->dev, "Get IRQ_HOTMON_LOW failed.\n"); 421 dev_err(&pdev->dev, "Get IRQ_HOTMON_LOW failed.\n");
422 return low_irq; 422 ret = low_irq;
423 goto out_unlock;
423 } 424 }
424 425
425 ret = devm_request_threaded_irq(&pdev->dev, low_irq, NULL, 426 ret = devm_request_threaded_irq(&pdev->dev, low_irq, NULL,
@@ -427,13 +428,14 @@ static int db8500_thermal_probe(struct platform_device *pdev)
427 "dbx500_temp_low", pzone); 428 "dbx500_temp_low", pzone);
428 if (ret < 0) { 429 if (ret < 0) {
429 dev_err(&pdev->dev, "Failed to allocate temp low irq.\n"); 430 dev_err(&pdev->dev, "Failed to allocate temp low irq.\n");
430 return ret; 431 goto out_unlock;
431 } 432 }
432 433
433 high_irq = platform_get_irq_byname(pdev, "IRQ_HOTMON_HIGH"); 434 high_irq = platform_get_irq_byname(pdev, "IRQ_HOTMON_HIGH");
434 if (high_irq < 0) { 435 if (high_irq < 0) {
435 dev_err(&pdev->dev, "Get IRQ_HOTMON_HIGH failed.\n"); 436 dev_err(&pdev->dev, "Get IRQ_HOTMON_HIGH failed.\n");
436 return high_irq; 437 ret = high_irq;
438 goto out_unlock;
437 } 439 }
438 440
439 ret = devm_request_threaded_irq(&pdev->dev, high_irq, NULL, 441 ret = devm_request_threaded_irq(&pdev->dev, high_irq, NULL,
@@ -441,15 +443,16 @@ static int db8500_thermal_probe(struct platform_device *pdev)
441 "dbx500_temp_high", pzone); 443 "dbx500_temp_high", pzone);
442 if (ret < 0) { 444 if (ret < 0) {
443 dev_err(&pdev->dev, "Failed to allocate temp high irq.\n"); 445 dev_err(&pdev->dev, "Failed to allocate temp high irq.\n");
444 return ret; 446 goto out_unlock;
445 } 447 }
446 448
447 pzone->therm_dev = thermal_zone_device_register("db8500_thermal_zone", 449 pzone->therm_dev = thermal_zone_device_register("db8500_thermal_zone",
448 ptrips->num_trips, 0, pzone, &thdev_ops, NULL, 0, 0); 450 ptrips->num_trips, 0, pzone, &thdev_ops, NULL, 0, 0);
449 451
450 if (IS_ERR_OR_NULL(pzone->therm_dev)) { 452 if (IS_ERR(pzone->therm_dev)) {
451 dev_err(&pdev->dev, "Register thermal zone device failed.\n"); 453 dev_err(&pdev->dev, "Register thermal zone device failed.\n");
452 return PTR_ERR(pzone->therm_dev); 454 ret = PTR_ERR(pzone->therm_dev);
455 goto out_unlock;
453 } 456 }
454 dev_info(&pdev->dev, "Thermal zone device registered.\n"); 457 dev_info(&pdev->dev, "Thermal zone device registered.\n");
455 458
@@ -461,9 +464,11 @@ static int db8500_thermal_probe(struct platform_device *pdev)
461 464
462 platform_set_drvdata(pdev, pzone); 465 platform_set_drvdata(pdev, pzone);
463 pzone->mode = THERMAL_DEVICE_ENABLED; 466 pzone->mode = THERMAL_DEVICE_ENABLED;
467
468out_unlock:
464 mutex_unlock(&pzone->th_lock); 469 mutex_unlock(&pzone->th_lock);
465 470
466 return 0; 471 return ret;
467} 472}
468 473
469static int db8500_thermal_remove(struct platform_device *pdev) 474static int db8500_thermal_remove(struct platform_device *pdev)
diff --git a/drivers/thermal/dove_thermal.c b/drivers/thermal/dove_thermal.c
index 3078c403b42d..4b15a5f270dc 100644
--- a/drivers/thermal/dove_thermal.c
+++ b/drivers/thermal/dove_thermal.c
@@ -107,12 +107,13 @@ static int dove_get_temp(struct thermal_zone_device *thermal,
107 } 107 }
108 108
109 /* 109 /*
110 * Calculate temperature. See Section 8.10.1 of 88AP510, 110 * Calculate temperature. According to Marvell internal
111 * Documentation/arm/Marvell/README 111 * documentation the formula for this is:
112 * Celsius = (322-reg)/1.3625
112 */ 113 */
113 reg = readl_relaxed(priv->sensor); 114 reg = readl_relaxed(priv->sensor);
114 reg = (reg >> DOVE_THERMAL_TEMP_OFFSET) & DOVE_THERMAL_TEMP_MASK; 115 reg = (reg >> DOVE_THERMAL_TEMP_OFFSET) & DOVE_THERMAL_TEMP_MASK;
115 *temp = ((2281638UL - (7298*reg)) / 10); 116 *temp = ((3220000000UL - (10000000UL * reg)) / 13625);
116 117
117 return 0; 118 return 0;
118} 119}
diff --git a/drivers/thermal/exynos_thermal.c b/drivers/thermal/exynos_thermal.c
index b777ae6f0a8f..d20ce9e61403 100644
--- a/drivers/thermal/exynos_thermal.c
+++ b/drivers/thermal/exynos_thermal.c
@@ -98,13 +98,13 @@
98#define IDLE_INTERVAL 10000 98#define IDLE_INTERVAL 10000
99#define MCELSIUS 1000 99#define MCELSIUS 1000
100 100
101#ifdef CONFIG_EXYNOS_THERMAL_EMUL 101#ifdef CONFIG_THERMAL_EMULATION
102#define EXYNOS_EMUL_TIME 0x57F0 102#define EXYNOS_EMUL_TIME 0x57F0
103#define EXYNOS_EMUL_TIME_SHIFT 16 103#define EXYNOS_EMUL_TIME_SHIFT 16
104#define EXYNOS_EMUL_DATA_SHIFT 8 104#define EXYNOS_EMUL_DATA_SHIFT 8
105#define EXYNOS_EMUL_DATA_MASK 0xFF 105#define EXYNOS_EMUL_DATA_MASK 0xFF
106#define EXYNOS_EMUL_ENABLE 0x1 106#define EXYNOS_EMUL_ENABLE 0x1
107#endif /* CONFIG_EXYNOS_THERMAL_EMUL */ 107#endif /* CONFIG_THERMAL_EMULATION */
108 108
109/* CPU Zone information */ 109/* CPU Zone information */
110#define PANIC_ZONE 4 110#define PANIC_ZONE 4
@@ -143,6 +143,7 @@ struct thermal_cooling_conf {
143struct thermal_sensor_conf { 143struct thermal_sensor_conf {
144 char name[SENSOR_NAME_LEN]; 144 char name[SENSOR_NAME_LEN];
145 int (*read_temperature)(void *data); 145 int (*read_temperature)(void *data);
146 int (*write_emul_temp)(void *drv_data, unsigned long temp);
146 struct thermal_trip_point_conf trip_data; 147 struct thermal_trip_point_conf trip_data;
147 struct thermal_cooling_conf cooling_data; 148 struct thermal_cooling_conf cooling_data;
148 void *private_data; 149 void *private_data;
@@ -240,26 +241,6 @@ static int exynos_get_crit_temp(struct thermal_zone_device *thermal,
240 return ret; 241 return ret;
241} 242}
242 243
243static int exynos_get_frequency_level(unsigned int cpu, unsigned int freq)
244{
245 int i = 0, ret = -EINVAL;
246 struct cpufreq_frequency_table *table = NULL;
247#ifdef CONFIG_CPU_FREQ
248 table = cpufreq_frequency_get_table(cpu);
249#endif
250 if (!table)
251 return ret;
252
253 while (table[i].frequency != CPUFREQ_TABLE_END) {
254 if (table[i].frequency == CPUFREQ_ENTRY_INVALID)
255 continue;
256 if (table[i].frequency == freq)
257 return i;
258 i++;
259 }
260 return ret;
261}
262
263/* Bind callback functions for thermal zone */ 244/* Bind callback functions for thermal zone */
264static int exynos_bind(struct thermal_zone_device *thermal, 245static int exynos_bind(struct thermal_zone_device *thermal,
265 struct thermal_cooling_device *cdev) 246 struct thermal_cooling_device *cdev)
@@ -286,8 +267,8 @@ static int exynos_bind(struct thermal_zone_device *thermal,
286 /* Bind the thermal zone to the cpufreq cooling device */ 267 /* Bind the thermal zone to the cpufreq cooling device */
287 for (i = 0; i < tab_size; i++) { 268 for (i = 0; i < tab_size; i++) {
288 clip_data = (struct freq_clip_table *)&(tab_ptr[i]); 269 clip_data = (struct freq_clip_table *)&(tab_ptr[i]);
289 level = exynos_get_frequency_level(0, clip_data->freq_clip_max); 270 level = cpufreq_cooling_get_level(0, clip_data->freq_clip_max);
290 if (level < 0) 271 if (level == THERMAL_CSTATE_INVALID)
291 return 0; 272 return 0;
292 switch (GET_ZONE(i)) { 273 switch (GET_ZONE(i)) {
293 case MONITOR_ZONE: 274 case MONITOR_ZONE:
@@ -367,6 +348,23 @@ static int exynos_get_temp(struct thermal_zone_device *thermal,
367 return 0; 348 return 0;
368} 349}
369 350
351/* Get temperature callback functions for thermal zone */
352static int exynos_set_emul_temp(struct thermal_zone_device *thermal,
353 unsigned long temp)
354{
355 void *data;
356 int ret = -EINVAL;
357
358 if (!th_zone->sensor_conf) {
359 pr_info("Temperature sensor not initialised\n");
360 return -EINVAL;
361 }
362 data = th_zone->sensor_conf->private_data;
363 if (th_zone->sensor_conf->write_emul_temp)
364 ret = th_zone->sensor_conf->write_emul_temp(data, temp);
365 return ret;
366}
367
370/* Get the temperature trend */ 368/* Get the temperature trend */
371static int exynos_get_trend(struct thermal_zone_device *thermal, 369static int exynos_get_trend(struct thermal_zone_device *thermal,
372 int trip, enum thermal_trend *trend) 370 int trip, enum thermal_trend *trend)
@@ -390,6 +388,7 @@ static struct thermal_zone_device_ops const exynos_dev_ops = {
390 .bind = exynos_bind, 388 .bind = exynos_bind,
391 .unbind = exynos_unbind, 389 .unbind = exynos_unbind,
392 .get_temp = exynos_get_temp, 390 .get_temp = exynos_get_temp,
391 .set_emul_temp = exynos_set_emul_temp,
393 .get_trend = exynos_get_trend, 392 .get_trend = exynos_get_trend,
394 .get_mode = exynos_get_mode, 393 .get_mode = exynos_get_mode,
395 .set_mode = exynos_set_mode, 394 .set_mode = exynos_set_mode,
@@ -712,6 +711,47 @@ static int exynos_tmu_read(struct exynos_tmu_data *data)
712 return temp; 711 return temp;
713} 712}
714 713
714#ifdef CONFIG_THERMAL_EMULATION
715static int exynos_tmu_set_emulation(void *drv_data, unsigned long temp)
716{
717 struct exynos_tmu_data *data = drv_data;
718 unsigned int reg;
719 int ret = -EINVAL;
720
721 if (data->soc == SOC_ARCH_EXYNOS4210)
722 goto out;
723
724 if (temp && temp < MCELSIUS)
725 goto out;
726
727 mutex_lock(&data->lock);
728 clk_enable(data->clk);
729
730 reg = readl(data->base + EXYNOS_EMUL_CON);
731
732 if (temp) {
733 temp /= MCELSIUS;
734
735 reg = (EXYNOS_EMUL_TIME << EXYNOS_EMUL_TIME_SHIFT) |
736 (temp_to_code(data, temp)
737 << EXYNOS_EMUL_DATA_SHIFT) | EXYNOS_EMUL_ENABLE;
738 } else {
739 reg &= ~EXYNOS_EMUL_ENABLE;
740 }
741
742 writel(reg, data->base + EXYNOS_EMUL_CON);
743
744 clk_disable(data->clk);
745 mutex_unlock(&data->lock);
746 return 0;
747out:
748 return ret;
749}
750#else
751static int exynos_tmu_set_emulation(void *drv_data, unsigned long temp)
752 { return -EINVAL; }
753#endif/*CONFIG_THERMAL_EMULATION*/
754
715static void exynos_tmu_work(struct work_struct *work) 755static void exynos_tmu_work(struct work_struct *work)
716{ 756{
717 struct exynos_tmu_data *data = container_of(work, 757 struct exynos_tmu_data *data = container_of(work,
@@ -745,6 +785,7 @@ static irqreturn_t exynos_tmu_irq(int irq, void *id)
745static struct thermal_sensor_conf exynos_sensor_conf = { 785static struct thermal_sensor_conf exynos_sensor_conf = {
746 .name = "exynos-therm", 786 .name = "exynos-therm",
747 .read_temperature = (int (*)(void *))exynos_tmu_read, 787 .read_temperature = (int (*)(void *))exynos_tmu_read,
788 .write_emul_temp = exynos_tmu_set_emulation,
748}; 789};
749 790
750#if defined(CONFIG_CPU_EXYNOS4210) 791#if defined(CONFIG_CPU_EXYNOS4210)
@@ -814,6 +855,10 @@ static const struct of_device_id exynos_tmu_match[] = {
814 .data = (void *)EXYNOS4210_TMU_DRV_DATA, 855 .data = (void *)EXYNOS4210_TMU_DRV_DATA,
815 }, 856 },
816 { 857 {
858 .compatible = "samsung,exynos4412-tmu",
859 .data = (void *)EXYNOS_TMU_DRV_DATA,
860 },
861 {
817 .compatible = "samsung,exynos5250-tmu", 862 .compatible = "samsung,exynos5250-tmu",
818 .data = (void *)EXYNOS_TMU_DRV_DATA, 863 .data = (void *)EXYNOS_TMU_DRV_DATA,
819 }, 864 },
@@ -851,93 +896,6 @@ static inline struct exynos_tmu_platform_data *exynos_get_driver_data(
851 platform_get_device_id(pdev)->driver_data; 896 platform_get_device_id(pdev)->driver_data;
852} 897}
853 898
854#ifdef CONFIG_EXYNOS_THERMAL_EMUL
855static ssize_t exynos_tmu_emulation_show(struct device *dev,
856 struct device_attribute *attr,
857 char *buf)
858{
859 struct platform_device *pdev = container_of(dev,
860 struct platform_device, dev);
861 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
862 unsigned int reg;
863 u8 temp_code;
864 int temp = 0;
865
866 if (data->soc == SOC_ARCH_EXYNOS4210)
867 goto out;
868
869 mutex_lock(&data->lock);
870 clk_enable(data->clk);
871 reg = readl(data->base + EXYNOS_EMUL_CON);
872 clk_disable(data->clk);
873 mutex_unlock(&data->lock);
874
875 if (reg & EXYNOS_EMUL_ENABLE) {
876 reg >>= EXYNOS_EMUL_DATA_SHIFT;
877 temp_code = reg & EXYNOS_EMUL_DATA_MASK;
878 temp = code_to_temp(data, temp_code);
879 }
880out:
881 return sprintf(buf, "%d\n", temp * MCELSIUS);
882}
883
884static ssize_t exynos_tmu_emulation_store(struct device *dev,
885 struct device_attribute *attr,
886 const char *buf, size_t count)
887{
888 struct platform_device *pdev = container_of(dev,
889 struct platform_device, dev);
890 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
891 unsigned int reg;
892 int temp;
893
894 if (data->soc == SOC_ARCH_EXYNOS4210)
895 goto out;
896
897 if (!sscanf(buf, "%d\n", &temp) || temp < 0)
898 return -EINVAL;
899
900 mutex_lock(&data->lock);
901 clk_enable(data->clk);
902
903 reg = readl(data->base + EXYNOS_EMUL_CON);
904
905 if (temp) {
906 /* Both CELSIUS and MCELSIUS type are available for input */
907 if (temp > MCELSIUS)
908 temp /= MCELSIUS;
909
910 reg = (EXYNOS_EMUL_TIME << EXYNOS_EMUL_TIME_SHIFT) |
911 (temp_to_code(data, (temp / MCELSIUS))
912 << EXYNOS_EMUL_DATA_SHIFT) | EXYNOS_EMUL_ENABLE;
913 } else {
914 reg &= ~EXYNOS_EMUL_ENABLE;
915 }
916
917 writel(reg, data->base + EXYNOS_EMUL_CON);
918
919 clk_disable(data->clk);
920 mutex_unlock(&data->lock);
921
922out:
923 return count;
924}
925
926static DEVICE_ATTR(emulation, 0644, exynos_tmu_emulation_show,
927 exynos_tmu_emulation_store);
928static int create_emulation_sysfs(struct device *dev)
929{
930 return device_create_file(dev, &dev_attr_emulation);
931}
932static void remove_emulation_sysfs(struct device *dev)
933{
934 device_remove_file(dev, &dev_attr_emulation);
935}
936#else
937static inline int create_emulation_sysfs(struct device *dev) { return 0; }
938static inline void remove_emulation_sysfs(struct device *dev) {}
939#endif
940
941static int exynos_tmu_probe(struct platform_device *pdev) 899static int exynos_tmu_probe(struct platform_device *pdev)
942{ 900{
943 struct exynos_tmu_data *data; 901 struct exynos_tmu_data *data;
@@ -983,12 +941,16 @@ static int exynos_tmu_probe(struct platform_device *pdev)
983 return ret; 941 return ret;
984 } 942 }
985 943
986 data->clk = clk_get(NULL, "tmu_apbif"); 944 data->clk = devm_clk_get(&pdev->dev, "tmu_apbif");
987 if (IS_ERR(data->clk)) { 945 if (IS_ERR(data->clk)) {
988 dev_err(&pdev->dev, "Failed to get clock\n"); 946 dev_err(&pdev->dev, "Failed to get clock\n");
989 return PTR_ERR(data->clk); 947 return PTR_ERR(data->clk);
990 } 948 }
991 949
950 ret = clk_prepare(data->clk);
951 if (ret)
952 return ret;
953
992 if (pdata->type == SOC_ARCH_EXYNOS || 954 if (pdata->type == SOC_ARCH_EXYNOS ||
993 pdata->type == SOC_ARCH_EXYNOS4210) 955 pdata->type == SOC_ARCH_EXYNOS4210)
994 data->soc = pdata->type; 956 data->soc = pdata->type;
@@ -1037,14 +999,10 @@ static int exynos_tmu_probe(struct platform_device *pdev)
1037 goto err_clk; 999 goto err_clk;
1038 } 1000 }
1039 1001
1040 ret = create_emulation_sysfs(&pdev->dev);
1041 if (ret)
1042 dev_err(&pdev->dev, "Failed to create emulation mode sysfs node\n");
1043
1044 return 0; 1002 return 0;
1045err_clk: 1003err_clk:
1046 platform_set_drvdata(pdev, NULL); 1004 platform_set_drvdata(pdev, NULL);
1047 clk_put(data->clk); 1005 clk_unprepare(data->clk);
1048 return ret; 1006 return ret;
1049} 1007}
1050 1008
@@ -1052,13 +1010,11 @@ static int exynos_tmu_remove(struct platform_device *pdev)
1052{ 1010{
1053 struct exynos_tmu_data *data = platform_get_drvdata(pdev); 1011 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
1054 1012
1055 remove_emulation_sysfs(&pdev->dev);
1056
1057 exynos_tmu_control(pdev, false); 1013 exynos_tmu_control(pdev, false);
1058 1014
1059 exynos_unregister_thermal(); 1015 exynos_unregister_thermal();
1060 1016
1061 clk_put(data->clk); 1017 clk_unprepare(data->clk);
1062 1018
1063 platform_set_drvdata(pdev, NULL); 1019 platform_set_drvdata(pdev, NULL);
1064 1020
diff --git a/drivers/thermal/fair_share.c b/drivers/thermal/fair_share.c
index 792479f2b64b..944ba2f340c8 100644
--- a/drivers/thermal/fair_share.c
+++ b/drivers/thermal/fair_share.c
@@ -22,9 +22,6 @@
22 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 22 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
23 */ 23 */
24 24
25#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
26
27#include <linux/module.h>
28#include <linux/thermal.h> 25#include <linux/thermal.h>
29 26
30#include "thermal_core.h" 27#include "thermal_core.h"
@@ -111,23 +108,15 @@ static int fair_share_throttle(struct thermal_zone_device *tz, int trip)
111static struct thermal_governor thermal_gov_fair_share = { 108static struct thermal_governor thermal_gov_fair_share = {
112 .name = "fair_share", 109 .name = "fair_share",
113 .throttle = fair_share_throttle, 110 .throttle = fair_share_throttle,
114 .owner = THIS_MODULE,
115}; 111};
116 112
117static int __init thermal_gov_fair_share_init(void) 113int thermal_gov_fair_share_register(void)
118{ 114{
119 return thermal_register_governor(&thermal_gov_fair_share); 115 return thermal_register_governor(&thermal_gov_fair_share);
120} 116}
121 117
122static void __exit thermal_gov_fair_share_exit(void) 118void thermal_gov_fair_share_unregister(void)
123{ 119{
124 thermal_unregister_governor(&thermal_gov_fair_share); 120 thermal_unregister_governor(&thermal_gov_fair_share);
125} 121}
126 122
127/* This should load after thermal framework */
128fs_initcall(thermal_gov_fair_share_init);
129module_exit(thermal_gov_fair_share_exit);
130
131MODULE_AUTHOR("Durgadoss R");
132MODULE_DESCRIPTION("A simple weight based thermal throttling governor");
133MODULE_LICENSE("GPL");
diff --git a/drivers/thermal/kirkwood_thermal.c b/drivers/thermal/kirkwood_thermal.c
index e5500edb5285..dfeceaffbc03 100644
--- a/drivers/thermal/kirkwood_thermal.c
+++ b/drivers/thermal/kirkwood_thermal.c
@@ -41,21 +41,21 @@ static int kirkwood_get_temp(struct thermal_zone_device *thermal,
41 reg = readl_relaxed(priv->sensor); 41 reg = readl_relaxed(priv->sensor);
42 42
43 /* Valid check */ 43 /* Valid check */
44 if (!(reg >> KIRKWOOD_THERMAL_VALID_OFFSET) & 44 if (!((reg >> KIRKWOOD_THERMAL_VALID_OFFSET) &
45 KIRKWOOD_THERMAL_VALID_MASK) { 45 KIRKWOOD_THERMAL_VALID_MASK)) {
46 dev_err(&thermal->device, 46 dev_err(&thermal->device,
47 "Temperature sensor reading not valid\n"); 47 "Temperature sensor reading not valid\n");
48 return -EIO; 48 return -EIO;
49 } 49 }
50 50
51 /* 51 /*
52 * Calculate temperature. See Section 8.10.1 of the 88AP510, 52 * Calculate temperature. According to Marvell internal
53 * datasheet, which has the same sensor. 53 * documentation the formula for this is:
54 * Documentation/arm/Marvell/README 54 * Celsius = (322-reg)/1.3625
55 */ 55 */
56 reg = (reg >> KIRKWOOD_THERMAL_TEMP_OFFSET) & 56 reg = (reg >> KIRKWOOD_THERMAL_TEMP_OFFSET) &
57 KIRKWOOD_THERMAL_TEMP_MASK; 57 KIRKWOOD_THERMAL_TEMP_MASK;
58 *temp = ((2281638UL - (7298*reg)) / 10); 58 *temp = ((3220000000UL - (10000000UL * reg)) / 13625);
59 59
60 return 0; 60 return 0;
61} 61}
diff --git a/drivers/thermal/rcar_thermal.c b/drivers/thermal/rcar_thermal.c
index 2cc5b6115e3e..8d7edd4c8228 100644
--- a/drivers/thermal/rcar_thermal.c
+++ b/drivers/thermal/rcar_thermal.c
@@ -24,6 +24,7 @@
24#include <linux/io.h> 24#include <linux/io.h>
25#include <linux/module.h> 25#include <linux/module.h>
26#include <linux/platform_device.h> 26#include <linux/platform_device.h>
27#include <linux/pm_runtime.h>
27#include <linux/reboot.h> 28#include <linux/reboot.h>
28#include <linux/slab.h> 29#include <linux/slab.h>
29#include <linux/spinlock.h> 30#include <linux/spinlock.h>
@@ -377,6 +378,9 @@ static int rcar_thermal_probe(struct platform_device *pdev)
377 spin_lock_init(&common->lock); 378 spin_lock_init(&common->lock);
378 common->dev = dev; 379 common->dev = dev;
379 380
381 pm_runtime_enable(dev);
382 pm_runtime_get_sync(dev);
383
380 irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 384 irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
381 if (irq) { 385 if (irq) {
382 int ret; 386 int ret;
@@ -419,12 +423,15 @@ static int rcar_thermal_probe(struct platform_device *pdev)
419 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 423 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
420 if (!priv) { 424 if (!priv) {
421 dev_err(dev, "Could not allocate priv\n"); 425 dev_err(dev, "Could not allocate priv\n");
422 return -ENOMEM; 426 ret = -ENOMEM;
427 goto error_unregister;
423 } 428 }
424 429
425 priv->base = devm_ioremap_resource(dev, res); 430 priv->base = devm_ioremap_resource(dev, res);
426 if (IS_ERR(priv->base)) 431 if (IS_ERR(priv->base)) {
427 return PTR_ERR(priv->base); 432 ret = PTR_ERR(priv->base);
433 goto error_unregister;
434 }
428 435
429 priv->common = common; 436 priv->common = common;
430 priv->id = i; 437 priv->id = i;
@@ -443,10 +450,10 @@ static int rcar_thermal_probe(struct platform_device *pdev)
443 goto error_unregister; 450 goto error_unregister;
444 } 451 }
445 452
446 list_move_tail(&priv->list, &common->head);
447
448 if (rcar_has_irq_support(priv)) 453 if (rcar_has_irq_support(priv))
449 rcar_thermal_irq_enable(priv); 454 rcar_thermal_irq_enable(priv);
455
456 list_move_tail(&priv->list, &common->head);
450 } 457 }
451 458
452 platform_set_drvdata(pdev, common); 459 platform_set_drvdata(pdev, common);
@@ -456,8 +463,14 @@ static int rcar_thermal_probe(struct platform_device *pdev)
456 return 0; 463 return 0;
457 464
458error_unregister: 465error_unregister:
459 rcar_thermal_for_each_priv(priv, common) 466 rcar_thermal_for_each_priv(priv, common) {
460 thermal_zone_device_unregister(priv->zone); 467 thermal_zone_device_unregister(priv->zone);
468 if (rcar_has_irq_support(priv))
469 rcar_thermal_irq_disable(priv);
470 }
471
472 pm_runtime_put_sync(dev);
473 pm_runtime_disable(dev);
461 474
462 return ret; 475 return ret;
463} 476}
@@ -465,13 +478,20 @@ error_unregister:
465static int rcar_thermal_remove(struct platform_device *pdev) 478static int rcar_thermal_remove(struct platform_device *pdev)
466{ 479{
467 struct rcar_thermal_common *common = platform_get_drvdata(pdev); 480 struct rcar_thermal_common *common = platform_get_drvdata(pdev);
481 struct device *dev = &pdev->dev;
468 struct rcar_thermal_priv *priv; 482 struct rcar_thermal_priv *priv;
469 483
470 rcar_thermal_for_each_priv(priv, common) 484 rcar_thermal_for_each_priv(priv, common) {
471 thermal_zone_device_unregister(priv->zone); 485 thermal_zone_device_unregister(priv->zone);
486 if (rcar_has_irq_support(priv))
487 rcar_thermal_irq_disable(priv);
488 }
472 489
473 platform_set_drvdata(pdev, NULL); 490 platform_set_drvdata(pdev, NULL);
474 491
492 pm_runtime_put_sync(dev);
493 pm_runtime_disable(dev);
494
475 return 0; 495 return 0;
476} 496}
477 497
diff --git a/drivers/thermal/step_wise.c b/drivers/thermal/step_wise.c
index 407cde3211c1..4d4ddae1a991 100644
--- a/drivers/thermal/step_wise.c
+++ b/drivers/thermal/step_wise.c
@@ -22,9 +22,6 @@
22 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 22 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
23 */ 23 */
24 24
25#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
26
27#include <linux/module.h>
28#include <linux/thermal.h> 25#include <linux/thermal.h>
29 26
30#include "thermal_core.h" 27#include "thermal_core.h"
@@ -59,9 +56,12 @@ static unsigned long get_target_state(struct thermal_instance *instance,
59 56
60 switch (trend) { 57 switch (trend) {
61 case THERMAL_TREND_RAISING: 58 case THERMAL_TREND_RAISING:
62 if (throttle) 59 if (throttle) {
63 cur_state = cur_state < instance->upper ? 60 cur_state = cur_state < instance->upper ?
64 (cur_state + 1) : instance->upper; 61 (cur_state + 1) : instance->upper;
62 if (cur_state < instance->lower)
63 cur_state = instance->lower;
64 }
65 break; 65 break;
66 case THERMAL_TREND_RAISE_FULL: 66 case THERMAL_TREND_RAISE_FULL:
67 if (throttle) 67 if (throttle)
@@ -71,8 +71,11 @@ static unsigned long get_target_state(struct thermal_instance *instance,
71 if (cur_state == instance->lower) { 71 if (cur_state == instance->lower) {
72 if (!throttle) 72 if (!throttle)
73 cur_state = -1; 73 cur_state = -1;
74 } else 74 } else {
75 cur_state -= 1; 75 cur_state -= 1;
76 if (cur_state > instance->upper)
77 cur_state = instance->upper;
78 }
76 break; 79 break;
77 case THERMAL_TREND_DROP_FULL: 80 case THERMAL_TREND_DROP_FULL:
78 if (cur_state == instance->lower) { 81 if (cur_state == instance->lower) {
@@ -180,23 +183,14 @@ static int step_wise_throttle(struct thermal_zone_device *tz, int trip)
180static struct thermal_governor thermal_gov_step_wise = { 183static struct thermal_governor thermal_gov_step_wise = {
181 .name = "step_wise", 184 .name = "step_wise",
182 .throttle = step_wise_throttle, 185 .throttle = step_wise_throttle,
183 .owner = THIS_MODULE,
184}; 186};
185 187
186static int __init thermal_gov_step_wise_init(void) 188int thermal_gov_step_wise_register(void)
187{ 189{
188 return thermal_register_governor(&thermal_gov_step_wise); 190 return thermal_register_governor(&thermal_gov_step_wise);
189} 191}
190 192
191static void __exit thermal_gov_step_wise_exit(void) 193void thermal_gov_step_wise_unregister(void)
192{ 194{
193 thermal_unregister_governor(&thermal_gov_step_wise); 195 thermal_unregister_governor(&thermal_gov_step_wise);
194} 196}
195
196/* This should load after thermal framework */
197fs_initcall(thermal_gov_step_wise_init);
198module_exit(thermal_gov_step_wise_exit);
199
200MODULE_AUTHOR("Durgadoss R");
201MODULE_DESCRIPTION("A step-by-step thermal throttling governor");
202MODULE_LICENSE("GPL");
diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_core.c
index 5b7863a03f98..d755440791b7 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_core.c
@@ -40,7 +40,7 @@
40 40
41MODULE_AUTHOR("Zhang Rui"); 41MODULE_AUTHOR("Zhang Rui");
42MODULE_DESCRIPTION("Generic thermal management sysfs support"); 42MODULE_DESCRIPTION("Generic thermal management sysfs support");
43MODULE_LICENSE("GPL"); 43MODULE_LICENSE("GPL v2");
44 44
45static DEFINE_IDR(thermal_tz_idr); 45static DEFINE_IDR(thermal_tz_idr);
46static DEFINE_IDR(thermal_cdev_idr); 46static DEFINE_IDR(thermal_cdev_idr);
@@ -99,7 +99,6 @@ int thermal_register_governor(struct thermal_governor *governor)
99 99
100 return err; 100 return err;
101} 101}
102EXPORT_SYMBOL_GPL(thermal_register_governor);
103 102
104void thermal_unregister_governor(struct thermal_governor *governor) 103void thermal_unregister_governor(struct thermal_governor *governor)
105{ 104{
@@ -127,7 +126,6 @@ exit:
127 mutex_unlock(&thermal_governor_lock); 126 mutex_unlock(&thermal_governor_lock);
128 return; 127 return;
129} 128}
130EXPORT_SYMBOL_GPL(thermal_unregister_governor);
131 129
132static int get_idr(struct idr *idr, struct mutex *lock, int *id) 130static int get_idr(struct idr *idr, struct mutex *lock, int *id)
133{ 131{
@@ -371,16 +369,28 @@ static void handle_thermal_trip(struct thermal_zone_device *tz, int trip)
371 monitor_thermal_zone(tz); 369 monitor_thermal_zone(tz);
372} 370}
373 371
374static int thermal_zone_get_temp(struct thermal_zone_device *tz, 372/**
375 unsigned long *temp) 373 * thermal_zone_get_temp() - returns its the temperature of thermal zone
374 * @tz: a valid pointer to a struct thermal_zone_device
375 * @temp: a valid pointer to where to store the resulting temperature.
376 *
377 * When a valid thermal zone reference is passed, it will fetch its
378 * temperature and fill @temp.
379 *
380 * Return: On success returns 0, an error code otherwise
381 */
382int thermal_zone_get_temp(struct thermal_zone_device *tz, unsigned long *temp)
376{ 383{
377 int ret = 0; 384 int ret = -EINVAL;
378#ifdef CONFIG_THERMAL_EMULATION 385#ifdef CONFIG_THERMAL_EMULATION
379 int count; 386 int count;
380 unsigned long crit_temp = -1UL; 387 unsigned long crit_temp = -1UL;
381 enum thermal_trip_type type; 388 enum thermal_trip_type type;
382#endif 389#endif
383 390
391 if (!tz || IS_ERR(tz))
392 goto exit;
393
384 mutex_lock(&tz->lock); 394 mutex_lock(&tz->lock);
385 395
386 ret = tz->ops->get_temp(tz, temp); 396 ret = tz->ops->get_temp(tz, temp);
@@ -404,8 +414,10 @@ static int thermal_zone_get_temp(struct thermal_zone_device *tz,
404skip_emul: 414skip_emul:
405#endif 415#endif
406 mutex_unlock(&tz->lock); 416 mutex_unlock(&tz->lock);
417exit:
407 return ret; 418 return ret;
408} 419}
420EXPORT_SYMBOL_GPL(thermal_zone_get_temp);
409 421
410static void update_temperature(struct thermal_zone_device *tz) 422static void update_temperature(struct thermal_zone_device *tz)
411{ 423{
@@ -434,7 +446,7 @@ void thermal_zone_device_update(struct thermal_zone_device *tz)
434 for (count = 0; count < tz->trips; count++) 446 for (count = 0; count < tz->trips; count++)
435 handle_thermal_trip(tz, count); 447 handle_thermal_trip(tz, count);
436} 448}
437EXPORT_SYMBOL(thermal_zone_device_update); 449EXPORT_SYMBOL_GPL(thermal_zone_device_update);
438 450
439static void thermal_zone_device_check(struct work_struct *work) 451static void thermal_zone_device_check(struct work_struct *work)
440{ 452{
@@ -1097,13 +1109,23 @@ thermal_remove_hwmon_sysfs(struct thermal_zone_device *tz)
1097#endif 1109#endif
1098 1110
1099/** 1111/**
1100 * thermal_zone_bind_cooling_device - bind a cooling device to a thermal zone 1112 * thermal_zone_bind_cooling_device() - bind a cooling device to a thermal zone
1101 * @tz: thermal zone device 1113 * @tz: pointer to struct thermal_zone_device
1102 * @trip: indicates which trip point the cooling devices is 1114 * @trip: indicates which trip point the cooling devices is
1103 * associated with in this thermal zone. 1115 * associated with in this thermal zone.
1104 * @cdev: thermal cooling device 1116 * @cdev: pointer to struct thermal_cooling_device
1117 * @upper: the Maximum cooling state for this trip point.
1118 * THERMAL_NO_LIMIT means no upper limit,
1119 * and the cooling device can be in max_state.
1120 * @lower: the Minimum cooling state can be used for this trip point.
1121 * THERMAL_NO_LIMIT means no lower limit,
1122 * and the cooling device can be in cooling state 0.
1105 * 1123 *
1124 * This interface function bind a thermal cooling device to the certain trip
1125 * point of a thermal zone device.
1106 * This function is usually called in the thermal zone device .bind callback. 1126 * This function is usually called in the thermal zone device .bind callback.
1127 *
1128 * Return: 0 on success, the proper error value otherwise.
1107 */ 1129 */
1108int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz, 1130int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
1109 int trip, 1131 int trip,
@@ -1197,16 +1219,21 @@ free_mem:
1197 kfree(dev); 1219 kfree(dev);
1198 return result; 1220 return result;
1199} 1221}
1200EXPORT_SYMBOL(thermal_zone_bind_cooling_device); 1222EXPORT_SYMBOL_GPL(thermal_zone_bind_cooling_device);
1201 1223
1202/** 1224/**
1203 * thermal_zone_unbind_cooling_device - unbind a cooling device from a thermal zone 1225 * thermal_zone_unbind_cooling_device() - unbind a cooling device from a
1204 * @tz: thermal zone device 1226 * thermal zone.
1227 * @tz: pointer to a struct thermal_zone_device.
1205 * @trip: indicates which trip point the cooling devices is 1228 * @trip: indicates which trip point the cooling devices is
1206 * associated with in this thermal zone. 1229 * associated with in this thermal zone.
1207 * @cdev: thermal cooling device 1230 * @cdev: pointer to a struct thermal_cooling_device.
1208 * 1231 *
1232 * This interface function unbind a thermal cooling device from the certain
1233 * trip point of a thermal zone device.
1209 * This function is usually called in the thermal zone device .unbind callback. 1234 * This function is usually called in the thermal zone device .unbind callback.
1235 *
1236 * Return: 0 on success, the proper error value otherwise.
1210 */ 1237 */
1211int thermal_zone_unbind_cooling_device(struct thermal_zone_device *tz, 1238int thermal_zone_unbind_cooling_device(struct thermal_zone_device *tz,
1212 int trip, 1239 int trip,
@@ -1237,7 +1264,7 @@ unbind:
1237 kfree(pos); 1264 kfree(pos);
1238 return 0; 1265 return 0;
1239} 1266}
1240EXPORT_SYMBOL(thermal_zone_unbind_cooling_device); 1267EXPORT_SYMBOL_GPL(thermal_zone_unbind_cooling_device);
1241 1268
1242static void thermal_release(struct device *dev) 1269static void thermal_release(struct device *dev)
1243{ 1270{
@@ -1260,10 +1287,17 @@ static struct class thermal_class = {
1260}; 1287};
1261 1288
1262/** 1289/**
1263 * thermal_cooling_device_register - register a new thermal cooling device 1290 * thermal_cooling_device_register() - register a new thermal cooling device
1264 * @type: the thermal cooling device type. 1291 * @type: the thermal cooling device type.
1265 * @devdata: device private data. 1292 * @devdata: device private data.
1266 * @ops: standard thermal cooling devices callbacks. 1293 * @ops: standard thermal cooling devices callbacks.
1294 *
1295 * This interface function adds a new thermal cooling device (fan/processor/...)
1296 * to /sys/class/thermal/ folder as cooling_device[0-*]. It tries to bind itself
1297 * to all the thermal zone devices registered at the same time.
1298 *
1299 * Return: a pointer to the created struct thermal_cooling_device or an
1300 * ERR_PTR. Caller must check return value with IS_ERR*() helpers.
1267 */ 1301 */
1268struct thermal_cooling_device * 1302struct thermal_cooling_device *
1269thermal_cooling_device_register(char *type, void *devdata, 1303thermal_cooling_device_register(char *type, void *devdata,
@@ -1289,7 +1323,7 @@ thermal_cooling_device_register(char *type, void *devdata,
1289 return ERR_PTR(result); 1323 return ERR_PTR(result);
1290 } 1324 }
1291 1325
1292 strcpy(cdev->type, type ? : ""); 1326 strlcpy(cdev->type, type ? : "", sizeof(cdev->type));
1293 mutex_init(&cdev->lock); 1327 mutex_init(&cdev->lock);
1294 INIT_LIST_HEAD(&cdev->thermal_instances); 1328 INIT_LIST_HEAD(&cdev->thermal_instances);
1295 cdev->ops = ops; 1329 cdev->ops = ops;
@@ -1334,7 +1368,7 @@ unregister:
1334 device_unregister(&cdev->device); 1368 device_unregister(&cdev->device);
1335 return ERR_PTR(result); 1369 return ERR_PTR(result);
1336} 1370}
1337EXPORT_SYMBOL(thermal_cooling_device_register); 1371EXPORT_SYMBOL_GPL(thermal_cooling_device_register);
1338 1372
1339/** 1373/**
1340 * thermal_cooling_device_unregister - removes the registered thermal cooling device 1374 * thermal_cooling_device_unregister - removes the registered thermal cooling device
@@ -1394,7 +1428,7 @@ void thermal_cooling_device_unregister(struct thermal_cooling_device *cdev)
1394 device_unregister(&cdev->device); 1428 device_unregister(&cdev->device);
1395 return; 1429 return;
1396} 1430}
1397EXPORT_SYMBOL(thermal_cooling_device_unregister); 1431EXPORT_SYMBOL_GPL(thermal_cooling_device_unregister);
1398 1432
1399void thermal_cdev_update(struct thermal_cooling_device *cdev) 1433void thermal_cdev_update(struct thermal_cooling_device *cdev)
1400{ 1434{
@@ -1420,7 +1454,7 @@ void thermal_cdev_update(struct thermal_cooling_device *cdev)
1420EXPORT_SYMBOL(thermal_cdev_update); 1454EXPORT_SYMBOL(thermal_cdev_update);
1421 1455
1422/** 1456/**
1423 * notify_thermal_framework - Sensor drivers use this API to notify framework 1457 * thermal_notify_framework - Sensor drivers use this API to notify framework
1424 * @tz: thermal zone device 1458 * @tz: thermal zone device
1425 * @trip: indicates which trip point has been crossed 1459 * @trip: indicates which trip point has been crossed
1426 * 1460 *
@@ -1431,16 +1465,21 @@ EXPORT_SYMBOL(thermal_cdev_update);
1431 * The throttling policy is based on the configured platform data; if no 1465 * The throttling policy is based on the configured platform data; if no
1432 * platform data is provided, this uses the step_wise throttling policy. 1466 * platform data is provided, this uses the step_wise throttling policy.
1433 */ 1467 */
1434void notify_thermal_framework(struct thermal_zone_device *tz, int trip) 1468void thermal_notify_framework(struct thermal_zone_device *tz, int trip)
1435{ 1469{
1436 handle_thermal_trip(tz, trip); 1470 handle_thermal_trip(tz, trip);
1437} 1471}
1438EXPORT_SYMBOL(notify_thermal_framework); 1472EXPORT_SYMBOL_GPL(thermal_notify_framework);
1439 1473
1440/** 1474/**
1441 * create_trip_attrs - create attributes for trip points 1475 * create_trip_attrs() - create attributes for trip points
1442 * @tz: the thermal zone device 1476 * @tz: the thermal zone device
1443 * @mask: Writeable trip point bitmap. 1477 * @mask: Writeable trip point bitmap.
1478 *
1479 * helper function to instantiate sysfs entries for every trip
1480 * point and its properties of a struct thermal_zone_device.
1481 *
1482 * Return: 0 on success, the proper error value otherwise.
1444 */ 1483 */
1445static int create_trip_attrs(struct thermal_zone_device *tz, int mask) 1484static int create_trip_attrs(struct thermal_zone_device *tz, int mask)
1446{ 1485{
@@ -1541,7 +1580,7 @@ static void remove_trip_attrs(struct thermal_zone_device *tz)
1541} 1580}
1542 1581
1543/** 1582/**
1544 * thermal_zone_device_register - register a new thermal zone device 1583 * thermal_zone_device_register() - register a new thermal zone device
1545 * @type: the thermal zone device type 1584 * @type: the thermal zone device type
1546 * @trips: the number of trip points the thermal zone support 1585 * @trips: the number of trip points the thermal zone support
1547 * @mask: a bit string indicating the writeablility of trip points 1586 * @mask: a bit string indicating the writeablility of trip points
@@ -1554,8 +1593,15 @@ static void remove_trip_attrs(struct thermal_zone_device *tz)
1554 * whether trip points have been crossed (0 for interrupt 1593 * whether trip points have been crossed (0 for interrupt
1555 * driven systems) 1594 * driven systems)
1556 * 1595 *
1596 * This interface function adds a new thermal zone device (sensor) to
1597 * /sys/class/thermal folder as thermal_zone[0-*]. It tries to bind all the
1598 * thermal cooling devices registered at the same time.
1557 * thermal_zone_device_unregister() must be called when the device is no 1599 * thermal_zone_device_unregister() must be called when the device is no
1558 * longer needed. The passive cooling depends on the .get_trend() return value. 1600 * longer needed. The passive cooling depends on the .get_trend() return value.
1601 *
1602 * Return: a pointer to the created struct thermal_zone_device or an
1603 * in case of error, an ERR_PTR. Caller must check return value with
1604 * IS_ERR*() helpers.
1559 */ 1605 */
1560struct thermal_zone_device *thermal_zone_device_register(const char *type, 1606struct thermal_zone_device *thermal_zone_device_register(const char *type,
1561 int trips, int mask, void *devdata, 1607 int trips, int mask, void *devdata,
@@ -1594,7 +1640,7 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
1594 return ERR_PTR(result); 1640 return ERR_PTR(result);
1595 } 1641 }
1596 1642
1597 strcpy(tz->type, type ? : ""); 1643 strlcpy(tz->type, type ? : "", sizeof(tz->type));
1598 tz->ops = ops; 1644 tz->ops = ops;
1599 tz->tzp = tzp; 1645 tz->tzp = tzp;
1600 tz->device.class = &thermal_class; 1646 tz->device.class = &thermal_class;
@@ -1687,7 +1733,7 @@ unregister:
1687 device_unregister(&tz->device); 1733 device_unregister(&tz->device);
1688 return ERR_PTR(result); 1734 return ERR_PTR(result);
1689} 1735}
1690EXPORT_SYMBOL(thermal_zone_device_register); 1736EXPORT_SYMBOL_GPL(thermal_zone_device_register);
1691 1737
1692/** 1738/**
1693 * thermal_device_unregister - removes the registered thermal zone device 1739 * thermal_device_unregister - removes the registered thermal zone device
@@ -1754,7 +1800,45 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz)
1754 device_unregister(&tz->device); 1800 device_unregister(&tz->device);
1755 return; 1801 return;
1756} 1802}
1757EXPORT_SYMBOL(thermal_zone_device_unregister); 1803EXPORT_SYMBOL_GPL(thermal_zone_device_unregister);
1804
1805/**
1806 * thermal_zone_get_zone_by_name() - search for a zone and returns its ref
1807 * @name: thermal zone name to fetch the temperature
1808 *
1809 * When only one zone is found with the passed name, returns a reference to it.
1810 *
1811 * Return: On success returns a reference to an unique thermal zone with
1812 * matching name equals to @name, an ERR_PTR otherwise (-EINVAL for invalid
1813 * paramenters, -ENODEV for not found and -EEXIST for multiple matches).
1814 */
1815struct thermal_zone_device *thermal_zone_get_zone_by_name(const char *name)
1816{
1817 struct thermal_zone_device *pos = NULL, *ref = ERR_PTR(-EINVAL);
1818 unsigned int found = 0;
1819
1820 if (!name)
1821 goto exit;
1822
1823 mutex_lock(&thermal_list_lock);
1824 list_for_each_entry(pos, &thermal_tz_list, node)
1825 if (!strnicmp(name, pos->type, THERMAL_NAME_LENGTH)) {
1826 found++;
1827 ref = pos;
1828 }
1829 mutex_unlock(&thermal_list_lock);
1830
1831 /* nothing has been found, thus an error code for it */
1832 if (found == 0)
1833 ref = ERR_PTR(-ENODEV);
1834 else if (found > 1)
1835 /* Success only when an unique zone is found */
1836 ref = ERR_PTR(-EEXIST);
1837
1838exit:
1839 return ref;
1840}
1841EXPORT_SYMBOL_GPL(thermal_zone_get_zone_by_name);
1758 1842
1759#ifdef CONFIG_NET 1843#ifdef CONFIG_NET
1760static struct genl_family thermal_event_genl_family = { 1844static struct genl_family thermal_event_genl_family = {
@@ -1832,7 +1916,7 @@ int thermal_generate_netlink_event(struct thermal_zone_device *tz,
1832 1916
1833 return result; 1917 return result;
1834} 1918}
1835EXPORT_SYMBOL(thermal_generate_netlink_event); 1919EXPORT_SYMBOL_GPL(thermal_generate_netlink_event);
1836 1920
1837static int genetlink_init(void) 1921static int genetlink_init(void)
1838{ 1922{
@@ -1858,30 +1942,69 @@ static inline int genetlink_init(void) { return 0; }
1858static inline void genetlink_exit(void) {} 1942static inline void genetlink_exit(void) {}
1859#endif /* !CONFIG_NET */ 1943#endif /* !CONFIG_NET */
1860 1944
1945static int __init thermal_register_governors(void)
1946{
1947 int result;
1948
1949 result = thermal_gov_step_wise_register();
1950 if (result)
1951 return result;
1952
1953 result = thermal_gov_fair_share_register();
1954 if (result)
1955 return result;
1956
1957 return thermal_gov_user_space_register();
1958}
1959
1960static void thermal_unregister_governors(void)
1961{
1962 thermal_gov_step_wise_unregister();
1963 thermal_gov_fair_share_unregister();
1964 thermal_gov_user_space_unregister();
1965}
1966
1861static int __init thermal_init(void) 1967static int __init thermal_init(void)
1862{ 1968{
1863 int result = 0; 1969 int result;
1970
1971 result = thermal_register_governors();
1972 if (result)
1973 goto error;
1864 1974
1865 result = class_register(&thermal_class); 1975 result = class_register(&thermal_class);
1866 if (result) { 1976 if (result)
1867 idr_destroy(&thermal_tz_idr); 1977 goto unregister_governors;
1868 idr_destroy(&thermal_cdev_idr); 1978
1869 mutex_destroy(&thermal_idr_lock);
1870 mutex_destroy(&thermal_list_lock);
1871 return result;
1872 }
1873 result = genetlink_init(); 1979 result = genetlink_init();
1980 if (result)
1981 goto unregister_class;
1982
1983 return 0;
1984
1985unregister_governors:
1986 thermal_unregister_governors();
1987unregister_class:
1988 class_unregister(&thermal_class);
1989error:
1990 idr_destroy(&thermal_tz_idr);
1991 idr_destroy(&thermal_cdev_idr);
1992 mutex_destroy(&thermal_idr_lock);
1993 mutex_destroy(&thermal_list_lock);
1994 mutex_destroy(&thermal_governor_lock);
1874 return result; 1995 return result;
1875} 1996}
1876 1997
1877static void __exit thermal_exit(void) 1998static void __exit thermal_exit(void)
1878{ 1999{
2000 genetlink_exit();
1879 class_unregister(&thermal_class); 2001 class_unregister(&thermal_class);
2002 thermal_unregister_governors();
1880 idr_destroy(&thermal_tz_idr); 2003 idr_destroy(&thermal_tz_idr);
1881 idr_destroy(&thermal_cdev_idr); 2004 idr_destroy(&thermal_cdev_idr);
1882 mutex_destroy(&thermal_idr_lock); 2005 mutex_destroy(&thermal_idr_lock);
1883 mutex_destroy(&thermal_list_lock); 2006 mutex_destroy(&thermal_list_lock);
1884 genetlink_exit(); 2007 mutex_destroy(&thermal_governor_lock);
1885} 2008}
1886 2009
1887fs_initcall(thermal_init); 2010fs_initcall(thermal_init);
diff --git a/drivers/thermal/thermal_core.h b/drivers/thermal/thermal_core.h
index 0d3205a18112..7cf2f6626251 100644
--- a/drivers/thermal/thermal_core.h
+++ b/drivers/thermal/thermal_core.h
@@ -50,4 +50,31 @@ struct thermal_instance {
50 struct list_head cdev_node; /* node in cdev->thermal_instances */ 50 struct list_head cdev_node; /* node in cdev->thermal_instances */
51}; 51};
52 52
53int thermal_register_governor(struct thermal_governor *);
54void thermal_unregister_governor(struct thermal_governor *);
55
56#ifdef CONFIG_THERMAL_GOV_STEP_WISE
57int thermal_gov_step_wise_register(void);
58void thermal_gov_step_wise_unregister(void);
59#else
60static inline int thermal_gov_step_wise_register(void) { return 0; }
61static inline void thermal_gov_step_wise_unregister(void) {}
62#endif /* CONFIG_THERMAL_GOV_STEP_WISE */
63
64#ifdef CONFIG_THERMAL_GOV_FAIR_SHARE
65int thermal_gov_fair_share_register(void);
66void thermal_gov_fair_share_unregister(void);
67#else
68static inline int thermal_gov_fair_share_register(void) { return 0; }
69static inline void thermal_gov_fair_share_unregister(void) {}
70#endif /* CONFIG_THERMAL_GOV_FAIR_SHARE */
71
72#ifdef CONFIG_THERMAL_GOV_USER_SPACE
73int thermal_gov_user_space_register(void);
74void thermal_gov_user_space_unregister(void);
75#else
76static inline int thermal_gov_user_space_register(void) { return 0; }
77static inline void thermal_gov_user_space_unregister(void) {}
78#endif /* CONFIG_THERMAL_GOV_USER_SPACE */
79
53#endif /* __THERMAL_CORE_H__ */ 80#endif /* __THERMAL_CORE_H__ */
diff --git a/drivers/thermal/user_space.c b/drivers/thermal/user_space.c
index 6bbb380b6d19..10adcddc8821 100644
--- a/drivers/thermal/user_space.c
+++ b/drivers/thermal/user_space.c
@@ -22,9 +22,6 @@
22 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 22 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
23 */ 23 */
24 24
25#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
26
27#include <linux/module.h>
28#include <linux/thermal.h> 25#include <linux/thermal.h>
29 26
30#include "thermal_core.h" 27#include "thermal_core.h"
@@ -46,23 +43,15 @@ static int notify_user_space(struct thermal_zone_device *tz, int trip)
46static struct thermal_governor thermal_gov_user_space = { 43static struct thermal_governor thermal_gov_user_space = {
47 .name = "user_space", 44 .name = "user_space",
48 .throttle = notify_user_space, 45 .throttle = notify_user_space,
49 .owner = THIS_MODULE,
50}; 46};
51 47
52static int __init thermal_gov_user_space_init(void) 48int thermal_gov_user_space_register(void)
53{ 49{
54 return thermal_register_governor(&thermal_gov_user_space); 50 return thermal_register_governor(&thermal_gov_user_space);
55} 51}
56 52
57static void __exit thermal_gov_user_space_exit(void) 53void thermal_gov_user_space_unregister(void)
58{ 54{
59 thermal_unregister_governor(&thermal_gov_user_space); 55 thermal_unregister_governor(&thermal_gov_user_space);
60} 56}
61 57
62/* This should load after thermal framework */
63fs_initcall(thermal_gov_user_space_init);
64module_exit(thermal_gov_user_space_exit);
65
66MODULE_AUTHOR("Durgadoss R");
67MODULE_DESCRIPTION("A user space Thermal notifier");
68MODULE_LICENSE("GPL");
diff --git a/include/linux/cpu_cooling.h b/include/linux/cpu_cooling.h
index 40b4ef54cc7d..282e27028418 100644
--- a/include/linux/cpu_cooling.h
+++ b/include/linux/cpu_cooling.h
@@ -25,34 +25,39 @@
25#define __CPU_COOLING_H__ 25#define __CPU_COOLING_H__
26 26
27#include <linux/thermal.h> 27#include <linux/thermal.h>
28#include <linux/cpumask.h>
28 29
29#define CPUFREQ_COOLING_START 0 30#ifdef CONFIG_CPU_THERMAL
30#define CPUFREQ_COOLING_STOP 1
31
32#if defined(CONFIG_CPU_THERMAL) || defined(CONFIG_CPU_THERMAL_MODULE)
33/** 31/**
34 * cpufreq_cooling_register - function to create cpufreq cooling device. 32 * cpufreq_cooling_register - function to create cpufreq cooling device.
35 * @clip_cpus: cpumask of cpus where the frequency constraints will happen 33 * @clip_cpus: cpumask of cpus where the frequency constraints will happen
36 */ 34 */
37struct thermal_cooling_device *cpufreq_cooling_register( 35struct thermal_cooling_device *
38 const struct cpumask *clip_cpus); 36cpufreq_cooling_register(const struct cpumask *clip_cpus);
39 37
40/** 38/**
41 * cpufreq_cooling_unregister - function to remove cpufreq cooling device. 39 * cpufreq_cooling_unregister - function to remove cpufreq cooling device.
42 * @cdev: thermal cooling device pointer. 40 * @cdev: thermal cooling device pointer.
43 */ 41 */
44void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev); 42void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev);
43
44unsigned long cpufreq_cooling_get_level(unsigned int, unsigned int);
45#else /* !CONFIG_CPU_THERMAL */ 45#else /* !CONFIG_CPU_THERMAL */
46static inline struct thermal_cooling_device *cpufreq_cooling_register( 46static inline struct thermal_cooling_device *
47 const struct cpumask *clip_cpus) 47cpufreq_cooling_register(const struct cpumask *clip_cpus)
48{ 48{
49 return NULL; 49 return NULL;
50} 50}
51static inline void cpufreq_cooling_unregister( 51static inline
52 struct thermal_cooling_device *cdev) 52void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev)
53{ 53{
54 return; 54 return;
55} 55}
56static inline
57unsigned long cpufreq_cooling_get_level(unsigned int, unsigned int)
58{
59 return THERMAL_CSTATE_INVALID;
60}
56#endif /* CONFIG_CPU_THERMAL */ 61#endif /* CONFIG_CPU_THERMAL */
57 62
58#endif /* __CPU_COOLING_H__ */ 63#endif /* __CPU_COOLING_H__ */
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index e3c0ae9bb1fa..a386a1cbb6e1 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -33,8 +33,11 @@
33#define THERMAL_MAX_TRIPS 12 33#define THERMAL_MAX_TRIPS 12
34#define THERMAL_NAME_LENGTH 20 34#define THERMAL_NAME_LENGTH 20
35 35
36/* invalid cooling state */
37#define THERMAL_CSTATE_INVALID -1UL
38
36/* No upper/lower limit requirement */ 39/* No upper/lower limit requirement */
37#define THERMAL_NO_LIMIT -1UL 40#define THERMAL_NO_LIMIT THERMAL_CSTATE_INVALID
38 41
39/* Unit conversion macros */ 42/* Unit conversion macros */
40#define KELVIN_TO_CELSIUS(t) (long)(((long)t-2732 >= 0) ? \ 43#define KELVIN_TO_CELSIUS(t) (long)(((long)t-2732 >= 0) ? \
@@ -184,7 +187,6 @@ struct thermal_governor {
184 char name[THERMAL_NAME_LENGTH]; 187 char name[THERMAL_NAME_LENGTH];
185 int (*throttle)(struct thermal_zone_device *tz, int trip); 188 int (*throttle)(struct thermal_zone_device *tz, int trip);
186 struct list_head governor_list; 189 struct list_head governor_list;
187 struct module *owner;
188}; 190};
189 191
190/* Structure that holds binding parameters for a zone */ 192/* Structure that holds binding parameters for a zone */
@@ -237,21 +239,20 @@ void thermal_zone_device_update(struct thermal_zone_device *);
237struct thermal_cooling_device *thermal_cooling_device_register(char *, void *, 239struct thermal_cooling_device *thermal_cooling_device_register(char *, void *,
238 const struct thermal_cooling_device_ops *); 240 const struct thermal_cooling_device_ops *);
239void thermal_cooling_device_unregister(struct thermal_cooling_device *); 241void thermal_cooling_device_unregister(struct thermal_cooling_device *);
242struct thermal_zone_device *thermal_zone_get_zone_by_name(const char *name);
243int thermal_zone_get_temp(struct thermal_zone_device *tz, unsigned long *temp);
240 244
241int get_tz_trend(struct thermal_zone_device *, int); 245int get_tz_trend(struct thermal_zone_device *, int);
242struct thermal_instance *get_thermal_instance(struct thermal_zone_device *, 246struct thermal_instance *get_thermal_instance(struct thermal_zone_device *,
243 struct thermal_cooling_device *, int); 247 struct thermal_cooling_device *, int);
244void thermal_cdev_update(struct thermal_cooling_device *); 248void thermal_cdev_update(struct thermal_cooling_device *);
245void notify_thermal_framework(struct thermal_zone_device *, int); 249void thermal_notify_framework(struct thermal_zone_device *, int);
246
247int thermal_register_governor(struct thermal_governor *);
248void thermal_unregister_governor(struct thermal_governor *);
249 250
250#ifdef CONFIG_NET 251#ifdef CONFIG_NET
251extern int thermal_generate_netlink_event(struct thermal_zone_device *tz, 252extern int thermal_generate_netlink_event(struct thermal_zone_device *tz,
252 enum events event); 253 enum events event);
253#else 254#else
254static int thermal_generate_netlink_event(struct thermal_zone_device *tz, 255static inline int thermal_generate_netlink_event(struct thermal_zone_device *tz,
255 enum events event) 256 enum events event)
256{ 257{
257 return 0; 258 return 0;