From a25189bc72bc59f86418d701b6bb4a3b906a107e Mon Sep 17 00:00:00 2001 From: Siddartha Mohanadoss Date: Mon, 6 Dec 2010 22:49:26 -0800 Subject: [PATCH] thermal: thermal_sys: Add support for configurable trip points. Add functionality for configurable hi, low and critical low. Change the trip point attributes to allow userspace clients with root access to set temperature for configurable hi and low temperature. Change-Id: I25c9c3bcfd58e44da5369187d1095559062f1860 Signed-off-by: Siddartha Mohanadoss Signed-off-by: David Brown --- drivers/thermal/thermal_sys.c | 151 ++++++++++++++++++++++++++++------ include/linux/thermal.h | 12 +++ 2 files changed, 139 insertions(+), 24 deletions(-) diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c index 022bacb71a7..765c95c533c 100644 --- a/drivers/thermal/thermal_sys.c +++ b/drivers/thermal/thermal_sys.c @@ -186,6 +186,12 @@ trip_point_type_show(struct device *dev, struct device_attribute *attr, return sprintf(buf, "critical\n"); case THERMAL_TRIP_HOT: return sprintf(buf, "hot\n"); + case THERMAL_TRIP_CONFIGURABLE_HI: + return sprintf(buf, "configurable_hi\n"); + case THERMAL_TRIP_CONFIGURABLE_LOW: + return sprintf(buf, "configurable_low\n"); + case THERMAL_TRIP_CRITICAL_LOW: + return sprintf(buf, "critical_low\n"); case THERMAL_TRIP_PASSIVE: return sprintf(buf, "passive\n"); case THERMAL_TRIP_ACTIVE: @@ -195,6 +201,34 @@ trip_point_type_show(struct device *dev, struct device_attribute *attr, } } +static ssize_t +trip_point_type_activate(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct thermal_zone_device *tz = to_thermal_zone(dev); + int trip, result; + + if (!tz->ops->activate_trip_type) + return -EPERM; + + if (!sscanf(attr->attr.name, "trip_point_%d_type", &trip)) + return -EINVAL; + + if (!strncmp(buf, "enabled", sizeof("enabled"))) + result = tz->ops->activate_trip_type(tz, trip, + THERMAL_TRIP_ACTIVATION_ENABLED); + else if (!strncmp(buf, "disabled", sizeof("disabled"))) + result = tz->ops->activate_trip_type(tz, trip, + THERMAL_TRIP_ACTIVATION_DISABLED); + else + result = -EINVAL; + + if (result) + return result; + + return count; +} + static ssize_t trip_point_temp_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -217,6 +251,28 @@ trip_point_temp_show(struct device *dev, struct device_attribute *attr, return sprintf(buf, "%ld\n", temperature); } +static ssize_t +trip_point_temp_set(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct thermal_zone_device *tz = to_thermal_zone(dev); + int trip, ret; + long temperature; + + if (!tz->ops->set_trip_temp) + return -EPERM; + + if (!sscanf(attr->attr.name, "trip_point_%d_temp", &trip)) + return -EINVAL; + + if (!sscanf(buf, "%ld", &temperature)) + return -EINVAL; + + ret = tz->ops->set_trip_temp(tz, trip, temperature); + + return ret; +} + static ssize_t passive_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -284,30 +340,54 @@ static DEVICE_ATTR(mode, 0644, mode_show, mode_store); static DEVICE_ATTR(passive, S_IRUGO | S_IWUSR, passive_show, passive_store); static struct device_attribute trip_point_attrs[] = { - __ATTR(trip_point_0_type, 0444, trip_point_type_show, NULL), - __ATTR(trip_point_0_temp, 0444, trip_point_temp_show, NULL), - __ATTR(trip_point_1_type, 0444, trip_point_type_show, NULL), - __ATTR(trip_point_1_temp, 0444, trip_point_temp_show, NULL), - __ATTR(trip_point_2_type, 0444, trip_point_type_show, NULL), - __ATTR(trip_point_2_temp, 0444, trip_point_temp_show, NULL), - __ATTR(trip_point_3_type, 0444, trip_point_type_show, NULL), - __ATTR(trip_point_3_temp, 0444, trip_point_temp_show, NULL), - __ATTR(trip_point_4_type, 0444, trip_point_type_show, NULL), - __ATTR(trip_point_4_temp, 0444, trip_point_temp_show, NULL), - __ATTR(trip_point_5_type, 0444, trip_point_type_show, NULL), - __ATTR(trip_point_5_temp, 0444, trip_point_temp_show, NULL), - __ATTR(trip_point_6_type, 0444, trip_point_type_show, NULL), - __ATTR(trip_point_6_temp, 0444, trip_point_temp_show, NULL), - __ATTR(trip_point_7_type, 0444, trip_point_type_show, NULL), - __ATTR(trip_point_7_temp, 0444, trip_point_temp_show, NULL), - __ATTR(trip_point_8_type, 0444, trip_point_type_show, NULL), - __ATTR(trip_point_8_temp, 0444, trip_point_temp_show, NULL), - __ATTR(trip_point_9_type, 0444, trip_point_type_show, NULL), - __ATTR(trip_point_9_temp, 0444, trip_point_temp_show, NULL), - __ATTR(trip_point_10_type, 0444, trip_point_type_show, NULL), - __ATTR(trip_point_10_temp, 0444, trip_point_temp_show, NULL), - __ATTR(trip_point_11_type, 0444, trip_point_type_show, NULL), - __ATTR(trip_point_11_temp, 0444, trip_point_temp_show, NULL), + __ATTR(trip_point_0_type, 0644, trip_point_type_show, + trip_point_type_activate), + __ATTR(trip_point_0_temp, 0644, trip_point_temp_show, + trip_point_temp_set), + __ATTR(trip_point_1_type, 0644, trip_point_type_show, + trip_point_type_activate), + __ATTR(trip_point_1_temp, 0644, trip_point_temp_show, + trip_point_temp_set), + __ATTR(trip_point_2_type, 0644, trip_point_type_show, + trip_point_type_activate), + __ATTR(trip_point_2_temp, 0644, trip_point_temp_show, + trip_point_temp_set), + __ATTR(trip_point_3_type, 0644, trip_point_type_show, + trip_point_type_activate), + __ATTR(trip_point_3_temp, 0644, trip_point_temp_show, + trip_point_temp_set), + __ATTR(trip_point_4_type, 0644, trip_point_type_show, + trip_point_type_activate), + __ATTR(trip_point_4_temp, 0644, trip_point_temp_show, + trip_point_temp_set), + __ATTR(trip_point_5_type, 0644, trip_point_type_show, + trip_point_type_activate), + __ATTR(trip_point_5_temp, 0644, trip_point_temp_show, + trip_point_temp_set), + __ATTR(trip_point_6_type, 0644, trip_point_type_show, + trip_point_type_activate), + __ATTR(trip_point_6_temp, 0644, trip_point_temp_show, + trip_point_temp_set), + __ATTR(trip_point_7_type, 0644, trip_point_type_show, + trip_point_type_activate), + __ATTR(trip_point_7_temp, 0644, trip_point_temp_show, + trip_point_temp_set), + __ATTR(trip_point_8_type, 0644, trip_point_type_show, + trip_point_type_activate), + __ATTR(trip_point_8_temp, 0644, trip_point_temp_show, + trip_point_temp_set), + __ATTR(trip_point_9_type, 0644, trip_point_type_show, + trip_point_type_activate), + __ATTR(trip_point_9_temp, 0644, trip_point_temp_show, + trip_point_temp_set), + __ATTR(trip_point_10_type, 0644, trip_point_type_show, + trip_point_type_activate), + __ATTR(trip_point_10_temp, 0644, trip_point_temp_show, + trip_point_temp_set), + __ATTR(trip_point_11_type, 0644, trip_point_type_show, + trip_point_type_activate), + __ATTR(trip_point_11_temp, 0644, trip_point_temp_show, + trip_point_temp_set), }; /* sys I/F for cooling device */ @@ -1049,6 +1129,29 @@ void thermal_zone_device_update(struct thermal_zone_device *tz) if (tz->ops->notify) tz->ops->notify(tz, count, trip_type); break; + case THERMAL_TRIP_CONFIGURABLE_HI: + if (temp >= trip_temp) + if (tz->ops->notify) + tz->ops->notify(tz, count, trip_type); + break; + case THERMAL_TRIP_CONFIGURABLE_LOW: + if (temp <= trip_temp) + if (tz->ops->notify) + tz->ops->notify(tz, count, trip_type); + break; + case THERMAL_TRIP_CRITICAL_LOW: + if (temp <= trip_temp) { + if (tz->ops->notify) + ret = tz->ops->notify(tz, count, + trip_type); + if (!ret) { + printk(KERN_EMERG + "Critical temperature reached (%ld C), \ + shutting down.\n", temp/1000); + orderly_poweroff(true); + } + } + break; case THERMAL_TRIP_ACTIVE: list_for_each_entry(instance, &tz->cooling_devices, node) { diff --git a/include/linux/thermal.h b/include/linux/thermal.h index 796f1ff0388..f740640b32d 100644 --- a/include/linux/thermal.h +++ b/include/linux/thermal.h @@ -37,11 +37,19 @@ enum thermal_device_mode { THERMAL_DEVICE_ENABLED, }; +enum thermal_trip_activation_mode { + THERMAL_TRIP_ACTIVATION_DISABLED = 0, + THERMAL_TRIP_ACTIVATION_ENABLED, +}; + enum thermal_trip_type { THERMAL_TRIP_ACTIVE = 0, THERMAL_TRIP_PASSIVE, THERMAL_TRIP_HOT, THERMAL_TRIP_CRITICAL, + THERMAL_TRIP_CONFIGURABLE_HI, + THERMAL_TRIP_CONFIGURABLE_LOW, + THERMAL_TRIP_CRITICAL_LOW, }; struct thermal_zone_device_ops { @@ -56,8 +64,12 @@ struct thermal_zone_device_ops { enum thermal_device_mode); int (*get_trip_type) (struct thermal_zone_device *, int, enum thermal_trip_type *); + int (*activate_trip_type) (struct thermal_zone_device *, int, + enum thermal_trip_activation_mode); int (*get_trip_temp) (struct thermal_zone_device *, int, unsigned long *); + int (*set_trip_temp) (struct thermal_zone_device *, int, + long); int (*get_crit_temp) (struct thermal_zone_device *, unsigned long *); int (*notify) (struct thermal_zone_device *, int, enum thermal_trip_type);