diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-24 20:13:49 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-24 20:13:49 -0500 |
commit | 91466574be1a3701fab4abf5ac1539b556575a81 (patch) | |
tree | 89373ef6b0c9e024a9688207b832552dfbcca666 /drivers/thermal/ti-soc-thermal/ti-thermal-common.c | |
parent | 09da8dfa98682d871987145ed11e3232accac860 (diff) | |
parent | c698a4492f01127ca90fc28cd5157f3d616fe4ff (diff) |
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux
Pull thermal management updates from Zhang Rui:
"This time, the biggest change is the work of representing hardware
thermal properties in device tree infrastructure.
This work includes the introduction of a device tree bindings for
describing the hardware thermal behavior and limits, and also a parser
to read and interpret the data, and build thermal zones and thermal
binding parameters. It also contains three examples on how to use the
new representation on sensor devices, using three different drivers to
accomplish it. One driver is in thermal subsystem, the TI SoC
thermal, and the other two drivers are in hwmon subsystem.
Actually, this would be the first step of the complete work because we
still need to check other potential drivers to be converted and then
validate the proposed API. But the reason why I include it in this
pull request is that, first, this change does not hurt any others
without using this approach, second, the principle and concept of this
change would not break after converting the remaining drivers. BTW,
as you can see, there are several points in this change that do not
belong to thermal subsystem. Because it has been suggested by Guenter
R that in such cases, it is recommended to send the complete series
via one single subsystem.
Specifics:
- representing hardware thermal properties in device tree
infrastructure
- fix a regression that the imx thermal driver breaks system suspend.
- introduce ACPI INT3403 thermal driver to retrieve temperature data
from the INT3403 ACPI device object present on some systems.
- introduce debug statement for thermal core and step_wise governor.
- assorted fixes and cleanups for thermal core, cpu cooling, exynos
thrmal, intel powerclamp and imx thermal driver"
* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux: (34 commits)
thermal: remove const flag from .ops of imx thermal
Thermal: update thermal zone device after setting emul_temp
intel_powerclamp: Fix cstate counter detection.
thermal: imx: add necessary clk operation
Thermal cpu cooling: return error if no valid cpu frequency entry
thermal: fix cpu_cooling max_level behavior
thermal: rcar-thermal: Enable driver compilation with COMPILE_TEST
thermal: debug: add debug statement for core and step_wise
thermal: imx_thermal: add module device table
drivers: thermal: Mark function as static in x86_pkg_temp_thermal.c
thermal:samsung: fix compilation warning
thermal: imx: correct suspend/resume flow
thermal: exynos: fix error return code
Thermal: ACPI INT3403 thermal driver
MAINTAINERS: add thermal bindings entry in thermal domain
arm: dts: make OMAP4460 bandgap node to belong to OCP
arm: dts: make OMAP443x bandgap node to belong to OCP
arm: dts: add cooling properties on omap5 cpu node
arm: dts: add omap5 thermal data
arm: dts: add omap5 CORE thermal data
...
Diffstat (limited to 'drivers/thermal/ti-soc-thermal/ti-thermal-common.c')
-rw-r--r-- | drivers/thermal/ti-soc-thermal/ti-thermal-common.c | 77 |
1 files changed, 62 insertions, 15 deletions
diff --git a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c index 5a47cc8c8f85..9eec26dc0448 100644 --- a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c +++ b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/cpufreq.h> | 31 | #include <linux/cpufreq.h> |
32 | #include <linux/cpumask.h> | 32 | #include <linux/cpumask.h> |
33 | #include <linux/cpu_cooling.h> | 33 | #include <linux/cpu_cooling.h> |
34 | #include <linux/of.h> | ||
34 | 35 | ||
35 | #include "ti-thermal.h" | 36 | #include "ti-thermal.h" |
36 | #include "ti-bandgap.h" | 37 | #include "ti-bandgap.h" |
@@ -44,6 +45,7 @@ struct ti_thermal_data { | |||
44 | enum thermal_device_mode mode; | 45 | enum thermal_device_mode mode; |
45 | struct work_struct thermal_wq; | 46 | struct work_struct thermal_wq; |
46 | int sensor_id; | 47 | int sensor_id; |
48 | bool our_zone; | ||
47 | }; | 49 | }; |
48 | 50 | ||
49 | static void ti_thermal_work(struct work_struct *work) | 51 | static void ti_thermal_work(struct work_struct *work) |
@@ -75,11 +77,10 @@ static inline int ti_thermal_hotspot_temperature(int t, int s, int c) | |||
75 | 77 | ||
76 | /* thermal zone ops */ | 78 | /* thermal zone ops */ |
77 | /* Get temperature callback function for thermal zone*/ | 79 | /* Get temperature callback function for thermal zone*/ |
78 | static inline int ti_thermal_get_temp(struct thermal_zone_device *thermal, | 80 | static inline int __ti_thermal_get_temp(void *devdata, long *temp) |
79 | unsigned long *temp) | ||
80 | { | 81 | { |
81 | struct thermal_zone_device *pcb_tz = NULL; | 82 | struct thermal_zone_device *pcb_tz = NULL; |
82 | struct ti_thermal_data *data = thermal->devdata; | 83 | struct ti_thermal_data *data = devdata; |
83 | struct ti_bandgap *bgp; | 84 | struct ti_bandgap *bgp; |
84 | const struct ti_temp_sensor *s; | 85 | const struct ti_temp_sensor *s; |
85 | int ret, tmp, slope, constant; | 86 | int ret, tmp, slope, constant; |
@@ -118,6 +119,14 @@ static inline int ti_thermal_get_temp(struct thermal_zone_device *thermal, | |||
118 | return ret; | 119 | return ret; |
119 | } | 120 | } |
120 | 121 | ||
122 | static inline int ti_thermal_get_temp(struct thermal_zone_device *thermal, | ||
123 | unsigned long *temp) | ||
124 | { | ||
125 | struct ti_thermal_data *data = thermal->devdata; | ||
126 | |||
127 | return __ti_thermal_get_temp(data, temp); | ||
128 | } | ||
129 | |||
121 | /* Bind callback functions for thermal zone */ | 130 | /* Bind callback functions for thermal zone */ |
122 | static int ti_thermal_bind(struct thermal_zone_device *thermal, | 131 | static int ti_thermal_bind(struct thermal_zone_device *thermal, |
123 | struct thermal_cooling_device *cdev) | 132 | struct thermal_cooling_device *cdev) |
@@ -230,11 +239,9 @@ static int ti_thermal_get_trip_temp(struct thermal_zone_device *thermal, | |||
230 | return 0; | 239 | return 0; |
231 | } | 240 | } |
232 | 241 | ||
233 | /* Get the temperature trend callback functions for thermal zone */ | 242 | static int __ti_thermal_get_trend(void *p, long *trend) |
234 | static int ti_thermal_get_trend(struct thermal_zone_device *thermal, | ||
235 | int trip, enum thermal_trend *trend) | ||
236 | { | 243 | { |
237 | struct ti_thermal_data *data = thermal->devdata; | 244 | struct ti_thermal_data *data = p; |
238 | struct ti_bandgap *bgp; | 245 | struct ti_bandgap *bgp; |
239 | int id, tr, ret = 0; | 246 | int id, tr, ret = 0; |
240 | 247 | ||
@@ -245,6 +252,22 @@ static int ti_thermal_get_trend(struct thermal_zone_device *thermal, | |||
245 | if (ret) | 252 | if (ret) |
246 | return ret; | 253 | return ret; |
247 | 254 | ||
255 | *trend = tr; | ||
256 | |||
257 | return 0; | ||
258 | } | ||
259 | |||
260 | /* Get the temperature trend callback functions for thermal zone */ | ||
261 | static int ti_thermal_get_trend(struct thermal_zone_device *thermal, | ||
262 | int trip, enum thermal_trend *trend) | ||
263 | { | ||
264 | int ret; | ||
265 | long tr; | ||
266 | |||
267 | ret = __ti_thermal_get_trend(thermal->devdata, &tr); | ||
268 | if (ret) | ||
269 | return ret; | ||
270 | |||
248 | if (tr > 0) | 271 | if (tr > 0) |
249 | *trend = THERMAL_TREND_RAISING; | 272 | *trend = THERMAL_TREND_RAISING; |
250 | else if (tr < 0) | 273 | else if (tr < 0) |
@@ -308,16 +331,23 @@ int ti_thermal_expose_sensor(struct ti_bandgap *bgp, int id, | |||
308 | if (!data) | 331 | if (!data) |
309 | return -EINVAL; | 332 | return -EINVAL; |
310 | 333 | ||
311 | /* Create thermal zone */ | 334 | /* in case this is specified by DT */ |
312 | data->ti_thermal = thermal_zone_device_register(domain, | 335 | data->ti_thermal = thermal_zone_of_sensor_register(bgp->dev, id, |
336 | data, __ti_thermal_get_temp, | ||
337 | __ti_thermal_get_trend); | ||
338 | if (IS_ERR(data->ti_thermal)) { | ||
339 | /* Create thermal zone */ | ||
340 | data->ti_thermal = thermal_zone_device_register(domain, | ||
313 | OMAP_TRIP_NUMBER, 0, data, &ti_thermal_ops, | 341 | OMAP_TRIP_NUMBER, 0, data, &ti_thermal_ops, |
314 | NULL, FAST_TEMP_MONITORING_RATE, | 342 | NULL, FAST_TEMP_MONITORING_RATE, |
315 | FAST_TEMP_MONITORING_RATE); | 343 | FAST_TEMP_MONITORING_RATE); |
316 | if (IS_ERR(data->ti_thermal)) { | 344 | if (IS_ERR(data->ti_thermal)) { |
317 | dev_err(bgp->dev, "thermal zone device is NULL\n"); | 345 | dev_err(bgp->dev, "thermal zone device is NULL\n"); |
318 | return PTR_ERR(data->ti_thermal); | 346 | return PTR_ERR(data->ti_thermal); |
347 | } | ||
348 | data->ti_thermal->polling_delay = FAST_TEMP_MONITORING_RATE; | ||
349 | data->our_zone = true; | ||
319 | } | 350 | } |
320 | data->ti_thermal->polling_delay = FAST_TEMP_MONITORING_RATE; | ||
321 | ti_bandgap_set_sensor_data(bgp, id, data); | 351 | ti_bandgap_set_sensor_data(bgp, id, data); |
322 | ti_bandgap_write_update_interval(bgp, data->sensor_id, | 352 | ti_bandgap_write_update_interval(bgp, data->sensor_id, |
323 | data->ti_thermal->polling_delay); | 353 | data->ti_thermal->polling_delay); |
@@ -331,7 +361,13 @@ int ti_thermal_remove_sensor(struct ti_bandgap *bgp, int id) | |||
331 | 361 | ||
332 | data = ti_bandgap_get_sensor_data(bgp, id); | 362 | data = ti_bandgap_get_sensor_data(bgp, id); |
333 | 363 | ||
334 | thermal_zone_device_unregister(data->ti_thermal); | 364 | if (data && data->ti_thermal) { |
365 | if (data->our_zone) | ||
366 | thermal_zone_device_unregister(data->ti_thermal); | ||
367 | else | ||
368 | thermal_zone_of_sensor_unregister(bgp->dev, | ||
369 | data->ti_thermal); | ||
370 | } | ||
335 | 371 | ||
336 | return 0; | 372 | return 0; |
337 | } | 373 | } |
@@ -350,6 +386,15 @@ int ti_thermal_report_sensor_temperature(struct ti_bandgap *bgp, int id) | |||
350 | int ti_thermal_register_cpu_cooling(struct ti_bandgap *bgp, int id) | 386 | int ti_thermal_register_cpu_cooling(struct ti_bandgap *bgp, int id) |
351 | { | 387 | { |
352 | struct ti_thermal_data *data; | 388 | struct ti_thermal_data *data; |
389 | struct device_node *np = bgp->dev->of_node; | ||
390 | |||
391 | /* | ||
392 | * We are assuming here that if one deploys the zone | ||
393 | * using DT, then it must be aware that the cooling device | ||
394 | * loading has to happen via cpufreq driver. | ||
395 | */ | ||
396 | if (of_find_property(np, "#thermal-sensor-cells", NULL)) | ||
397 | return 0; | ||
353 | 398 | ||
354 | data = ti_bandgap_get_sensor_data(bgp, id); | 399 | data = ti_bandgap_get_sensor_data(bgp, id); |
355 | if (!data || IS_ERR(data)) | 400 | if (!data || IS_ERR(data)) |
@@ -380,7 +425,9 @@ int ti_thermal_unregister_cpu_cooling(struct ti_bandgap *bgp, int id) | |||
380 | struct ti_thermal_data *data; | 425 | struct ti_thermal_data *data; |
381 | 426 | ||
382 | data = ti_bandgap_get_sensor_data(bgp, id); | 427 | data = ti_bandgap_get_sensor_data(bgp, id); |
383 | cpufreq_cooling_unregister(data->cool_dev); | 428 | |
429 | if (data && data->cool_dev) | ||
430 | cpufreq_cooling_unregister(data->cool_dev); | ||
384 | 431 | ||
385 | return 0; | 432 | return 0; |
386 | } | 433 | } |