aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAmit Daniel Kachhap <amit.daniel@samsung.com>2013-02-03 19:30:15 -0500
committerZhang Rui <rui.zhang@intel.com>2013-02-06 00:45:42 -0500
commite6e238c38bd4d42d5e2cddb2165e1a46e0fb1200 (patch)
treef09a49a963463468a39a62908583d5b0484c9d99
parentc8165dc0ea75855b0bff6e5edbe4957b8a63d021 (diff)
thermal: sysfs: Add a new sysfs node emul_temp for thermal emulation
This patch adds support to set the emulated temperature method in thermal zone (sensor). After setting this feature thermal zone may report this temperature and not the actual temperature. The emulation implementation may be based on sensor capability through platform specific handler or pure software emulation if no platform handler defined. This is useful in debugging different temperature threshold and its associated cooling action. Critical threshold's cannot be emulated. Writing 0 on this node should disable emulation. Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com> Acked-by: Kukjin Kim <kgene.kim@samsung.com> Signed-off-by: Zhang Rui <rui.zhang@intel.com>
-rw-r--r--Documentation/thermal/sysfs-api.txt13
-rw-r--r--drivers/thermal/Kconfig8
-rw-r--r--drivers/thermal/thermal_sys.c79
-rw-r--r--include/linux/thermal.h2
4 files changed, 91 insertions, 11 deletions
diff --git a/Documentation/thermal/sysfs-api.txt b/Documentation/thermal/sysfs-api.txt
index 526d4b90d6c1..6859661c9d31 100644
--- a/Documentation/thermal/sysfs-api.txt
+++ b/Documentation/thermal/sysfs-api.txt
@@ -55,6 +55,8 @@ temperature) and throttle appropriate devices.
55 .get_trip_type: get the type of certain trip point. 55 .get_trip_type: get the type of certain trip point.
56 .get_trip_temp: get the temperature above which the certain trip point 56 .get_trip_temp: get the temperature above which the certain trip point
57 will be fired. 57 will be fired.
58 .set_emul_temp: set the emulation temperature which helps in debugging
59 different threshold temperature points.
58 60
591.1.2 void thermal_zone_device_unregister(struct thermal_zone_device *tz) 611.1.2 void thermal_zone_device_unregister(struct thermal_zone_device *tz)
60 62
@@ -153,6 +155,7 @@ Thermal zone device sys I/F, created once it's registered:
153 |---trip_point_[0-*]_temp: Trip point temperature 155 |---trip_point_[0-*]_temp: Trip point temperature
154 |---trip_point_[0-*]_type: Trip point type 156 |---trip_point_[0-*]_type: Trip point type
155 |---trip_point_[0-*]_hyst: Hysteresis value for this trip point 157 |---trip_point_[0-*]_hyst: Hysteresis value for this trip point
158 |---emul_temp: Emulated temperature set node
156 159
157Thermal cooling device sys I/F, created once it's registered: 160Thermal cooling device sys I/F, created once it's registered:
158/sys/class/thermal/cooling_device[0-*]: 161/sys/class/thermal/cooling_device[0-*]:
@@ -252,6 +255,16 @@ passive
252 Valid values: 0 (disabled) or greater than 1000 255 Valid values: 0 (disabled) or greater than 1000
253 RW, Optional 256 RW, Optional
254 257
258emul_temp
259 Interface to set the emulated temperature method in thermal zone
260 (sensor). After setting this temperature, the thermal zone may pass
261 this temperature to platform emulation function if registered or
262 cache it locally. This is useful in debugging different temperature
263 threshold and its associated cooling action. This is write only node
264 and writing 0 on this node should disable emulation.
265 Unit: millidegree Celsius
266 WO, Optional
267
255***************************** 268*****************************
256* Cooling device attributes * 269* Cooling device attributes *
257***************************** 270*****************************
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index faf38c522fa8..e4cf7fbc3a59 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -78,6 +78,14 @@ config CPU_THERMAL
78 and not the ACPI interface. 78 and not the ACPI interface.
79 If you want this support, you should say Y here. 79 If you want this support, you should say Y here.
80 80
81config THERMAL_EMULATION
82 bool "Thermal emulation mode support"
83 help
84 Enable this option to make a emul_temp sysfs node in thermal zone
85 directory to support temperature emulation. With emulation sysfs node,
86 user can manually input temperature and test the different trip
87 threshold behaviour for simulation purpose.
88
81config SPEAR_THERMAL 89config SPEAR_THERMAL
82 bool "SPEAr thermal sensor driver" 90 bool "SPEAr thermal sensor driver"
83 depends on PLAT_SPEAR 91 depends on PLAT_SPEAR
diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index 0a1bf6b032ea..0675687c6de8 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -378,24 +378,54 @@ static void handle_thermal_trip(struct thermal_zone_device *tz, int trip)
378 monitor_thermal_zone(tz); 378 monitor_thermal_zone(tz);
379} 379}
380 380
381static int thermal_zone_get_temp(struct thermal_zone_device *tz,
382 unsigned long *temp)
383{
384 int ret = 0, count;
385 unsigned long crit_temp = -1UL;
386 enum thermal_trip_type type;
387
388 mutex_lock(&tz->lock);
389
390 ret = tz->ops->get_temp(tz, temp);
391#ifdef CONFIG_THERMAL_EMULATION
392 if (!tz->emul_temperature)
393 goto skip_emul;
394
395 for (count = 0; count < tz->trips; count++) {
396 ret = tz->ops->get_trip_type(tz, count, &type);
397 if (!ret && type == THERMAL_TRIP_CRITICAL) {
398 ret = tz->ops->get_trip_temp(tz, count, &crit_temp);
399 break;
400 }
401 }
402
403 if (ret)
404 goto skip_emul;
405
406 if (*temp < crit_temp)
407 *temp = tz->emul_temperature;
408skip_emul:
409#endif
410 mutex_unlock(&tz->lock);
411 return ret;
412}
413
381static void update_temperature(struct thermal_zone_device *tz) 414static void update_temperature(struct thermal_zone_device *tz)
382{ 415{
383 long temp; 416 long temp;
384 int ret; 417 int ret;
385 418
386 mutex_lock(&tz->lock); 419 ret = thermal_zone_get_temp(tz, &temp);
387
388 ret = tz->ops->get_temp(tz, &temp);
389 if (ret) { 420 if (ret) {
390 dev_warn(&tz->device, "failed to read out thermal zone %d\n", 421 dev_warn(&tz->device, "failed to read out thermal zone %d\n",
391 tz->id); 422 tz->id);
392 goto exit; 423 return;
393 } 424 }
394 425
426 mutex_lock(&tz->lock);
395 tz->last_temperature = tz->temperature; 427 tz->last_temperature = tz->temperature;
396 tz->temperature = temp; 428 tz->temperature = temp;
397
398exit:
399 mutex_unlock(&tz->lock); 429 mutex_unlock(&tz->lock);
400} 430}
401 431
@@ -438,10 +468,7 @@ temp_show(struct device *dev, struct device_attribute *attr, char *buf)
438 long temperature; 468 long temperature;
439 int ret; 469 int ret;
440 470
441 if (!tz->ops->get_temp) 471 ret = thermal_zone_get_temp(tz, &temperature);
442 return -EPERM;
443
444 ret = tz->ops->get_temp(tz, &temperature);
445 472
446 if (ret) 473 if (ret)
447 return ret; 474 return ret;
@@ -701,6 +728,31 @@ policy_show(struct device *dev, struct device_attribute *devattr, char *buf)
701 return sprintf(buf, "%s\n", tz->governor->name); 728 return sprintf(buf, "%s\n", tz->governor->name);
702} 729}
703 730
731#ifdef CONFIG_THERMAL_EMULATION
732static ssize_t
733emul_temp_store(struct device *dev, struct device_attribute *attr,
734 const char *buf, size_t count)
735{
736 struct thermal_zone_device *tz = to_thermal_zone(dev);
737 int ret = 0;
738 unsigned long temperature;
739
740 if (kstrtoul(buf, 10, &temperature))
741 return -EINVAL;
742
743 if (!tz->ops->set_emul_temp) {
744 mutex_lock(&tz->lock);
745 tz->emul_temperature = temperature;
746 mutex_unlock(&tz->lock);
747 } else {
748 ret = tz->ops->set_emul_temp(tz, temperature);
749 }
750
751 return ret ? ret : count;
752}
753static DEVICE_ATTR(emul_temp, S_IWUSR, NULL, emul_temp_store);
754#endif/*CONFIG_THERMAL_EMULATION*/
755
704static DEVICE_ATTR(type, 0444, type_show, NULL); 756static DEVICE_ATTR(type, 0444, type_show, NULL);
705static DEVICE_ATTR(temp, 0444, temp_show, NULL); 757static DEVICE_ATTR(temp, 0444, temp_show, NULL);
706static DEVICE_ATTR(mode, 0644, mode_show, mode_store); 758static DEVICE_ATTR(mode, 0644, mode_show, mode_store);
@@ -843,7 +895,7 @@ temp_input_show(struct device *dev, struct device_attribute *attr, char *buf)
843 temp_input); 895 temp_input);
844 struct thermal_zone_device *tz = temp->tz; 896 struct thermal_zone_device *tz = temp->tz;
845 897
846 ret = tz->ops->get_temp(tz, &temperature); 898 ret = thermal_zone_get_temp(tz, &temperature);
847 899
848 if (ret) 900 if (ret)
849 return ret; 901 return ret;
@@ -1596,6 +1648,11 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
1596 goto unregister; 1648 goto unregister;
1597 } 1649 }
1598 1650
1651#ifdef CONFIG_THERMAL_EMULATION
1652 result = device_create_file(&tz->device, &dev_attr_emul_temp);
1653 if (result)
1654 goto unregister;
1655#endif
1599 /* Create policy attribute */ 1656 /* Create policy attribute */
1600 result = device_create_file(&tz->device, &dev_attr_policy); 1657 result = device_create_file(&tz->device, &dev_attr_policy);
1601 if (result) 1658 if (result)
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index 9b78f8c6f773..f0bd7f90a90d 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -123,6 +123,7 @@ struct thermal_zone_device_ops {
123 int (*set_trip_hyst) (struct thermal_zone_device *, int, 123 int (*set_trip_hyst) (struct thermal_zone_device *, int,
124 unsigned long); 124 unsigned long);
125 int (*get_crit_temp) (struct thermal_zone_device *, unsigned long *); 125 int (*get_crit_temp) (struct thermal_zone_device *, unsigned long *);
126 int (*set_emul_temp) (struct thermal_zone_device *, unsigned long);
126 int (*get_trend) (struct thermal_zone_device *, int, 127 int (*get_trend) (struct thermal_zone_device *, int,
127 enum thermal_trend *); 128 enum thermal_trend *);
128 int (*notify) (struct thermal_zone_device *, int, 129 int (*notify) (struct thermal_zone_device *, int,
@@ -165,6 +166,7 @@ struct thermal_zone_device {
165 int polling_delay; 166 int polling_delay;
166 int temperature; 167 int temperature;
167 int last_temperature; 168 int last_temperature;
169 int emul_temperature;
168 int passive; 170 int passive;
169 unsigned int forced_passive; 171 unsigned int forced_passive;
170 const struct thermal_zone_device_ops *ops; 172 const struct thermal_zone_device_ops *ops;