aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/thermal/sysfs-api.txt6
-rw-r--r--drivers/thermal/thermal_sys.c88
-rw-r--r--include/linux/thermal.h5
3 files changed, 94 insertions, 5 deletions
diff --git a/Documentation/thermal/sysfs-api.txt b/Documentation/thermal/sysfs-api.txt
index 4c105934c599..2ba4c9bb790a 100644
--- a/Documentation/thermal/sysfs-api.txt
+++ b/Documentation/thermal/sysfs-api.txt
@@ -121,6 +121,7 @@ Thermal zone device sys I/F, created once it's registered:
121 |---mode: Working mode of the thermal zone 121 |---mode: Working mode of the thermal zone
122 |---trip_point_[0-*]_temp: Trip point temperature 122 |---trip_point_[0-*]_temp: Trip point temperature
123 |---trip_point_[0-*]_type: Trip point type 123 |---trip_point_[0-*]_type: Trip point type
124 |---trip_point_[0-*]_hyst: Hysteresis value for this trip point
124 125
125Thermal cooling device sys I/F, created once it's registered: 126Thermal cooling device sys I/F, created once it's registered:
126/sys/class/thermal/cooling_device[0-*]: 127/sys/class/thermal/cooling_device[0-*]:
@@ -190,6 +191,11 @@ trip_point_[0-*]_type
190 thermal zone. 191 thermal zone.
191 RO, Optional 192 RO, Optional
192 193
194trip_point_[0-*]_hyst
195 The hysteresis value for a trip point, represented as an integer
196 Unit: Celsius
197 RW, Optional
198
193cdev[0-*] 199cdev[0-*]
194 Sysfs link to the thermal cooling device node where the sys I/F 200 Sysfs link to the thermal cooling device node where the sys I/F
195 for cooling device throttling control represents. 201 for cooling device throttling control represents.
diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index 5feb3353213f..2d7a9fe8f365 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -240,6 +240,52 @@ trip_point_temp_show(struct device *dev, struct device_attribute *attr,
240} 240}
241 241
242static ssize_t 242static ssize_t
243trip_point_hyst_store(struct device *dev, struct device_attribute *attr,
244 const char *buf, size_t count)
245{
246 struct thermal_zone_device *tz = to_thermal_zone(dev);
247 int trip, ret;
248 unsigned long temperature;
249
250 if (!tz->ops->set_trip_hyst)
251 return -EPERM;
252
253 if (!sscanf(attr->attr.name, "trip_point_%d_hyst", &trip))
254 return -EINVAL;
255
256 if (kstrtoul(buf, 10, &temperature))
257 return -EINVAL;
258
259 /*
260 * We are not doing any check on the 'temperature' value
261 * here. The driver implementing 'set_trip_hyst' has to
262 * take care of this.
263 */
264 ret = tz->ops->set_trip_hyst(tz, trip, temperature);
265
266 return ret ? ret : count;
267}
268
269static ssize_t
270trip_point_hyst_show(struct device *dev, struct device_attribute *attr,
271 char *buf)
272{
273 struct thermal_zone_device *tz = to_thermal_zone(dev);
274 int trip, ret;
275 unsigned long temperature;
276
277 if (!tz->ops->get_trip_hyst)
278 return -EPERM;
279
280 if (!sscanf(attr->attr.name, "trip_point_%d_hyst", &trip))
281 return -EINVAL;
282
283 ret = tz->ops->get_trip_hyst(tz, trip, &temperature);
284
285 return ret ? ret : sprintf(buf, "%ld\n", temperature);
286}
287
288static ssize_t
243passive_store(struct device *dev, struct device_attribute *attr, 289passive_store(struct device *dev, struct device_attribute *attr,
244 const char *buf, size_t count) 290 const char *buf, size_t count)
245{ 291{
@@ -1091,21 +1137,29 @@ EXPORT_SYMBOL(thermal_zone_device_update);
1091static int create_trip_attrs(struct thermal_zone_device *tz, int mask) 1137static int create_trip_attrs(struct thermal_zone_device *tz, int mask)
1092{ 1138{
1093 int indx; 1139 int indx;
1140 int size = sizeof(struct thermal_attr) * tz->trips;
1094 1141
1095 tz->trip_type_attrs = 1142 tz->trip_type_attrs = kzalloc(size, GFP_KERNEL);
1096 kzalloc(sizeof(struct thermal_attr) * tz->trips, GFP_KERNEL);
1097 if (!tz->trip_type_attrs) 1143 if (!tz->trip_type_attrs)
1098 return -ENOMEM; 1144 return -ENOMEM;
1099 1145
1100 tz->trip_temp_attrs = 1146 tz->trip_temp_attrs = kzalloc(size, GFP_KERNEL);
1101 kzalloc(sizeof(struct thermal_attr) * tz->trips, GFP_KERNEL);
1102 if (!tz->trip_temp_attrs) { 1147 if (!tz->trip_temp_attrs) {
1103 kfree(tz->trip_type_attrs); 1148 kfree(tz->trip_type_attrs);
1104 return -ENOMEM; 1149 return -ENOMEM;
1105 } 1150 }
1106 1151
1107 for (indx = 0; indx < tz->trips; indx++) { 1152 if (tz->ops->get_trip_hyst) {
1153 tz->trip_hyst_attrs = kzalloc(size, GFP_KERNEL);
1154 if (!tz->trip_hyst_attrs) {
1155 kfree(tz->trip_type_attrs);
1156 kfree(tz->trip_temp_attrs);
1157 return -ENOMEM;
1158 }
1159 }
1108 1160
1161
1162 for (indx = 0; indx < tz->trips; indx++) {
1109 /* create trip type attribute */ 1163 /* create trip type attribute */
1110 snprintf(tz->trip_type_attrs[indx].name, THERMAL_NAME_LENGTH, 1164 snprintf(tz->trip_type_attrs[indx].name, THERMAL_NAME_LENGTH,
1111 "trip_point_%d_type", indx); 1165 "trip_point_%d_type", indx);
@@ -1136,6 +1190,26 @@ static int create_trip_attrs(struct thermal_zone_device *tz, int mask)
1136 1190
1137 device_create_file(&tz->device, 1191 device_create_file(&tz->device,
1138 &tz->trip_temp_attrs[indx].attr); 1192 &tz->trip_temp_attrs[indx].attr);
1193
1194 /* create Optional trip hyst attribute */
1195 if (!tz->ops->get_trip_hyst)
1196 continue;
1197 snprintf(tz->trip_hyst_attrs[indx].name, THERMAL_NAME_LENGTH,
1198 "trip_point_%d_hyst", indx);
1199
1200 sysfs_attr_init(&tz->trip_hyst_attrs[indx].attr.attr);
1201 tz->trip_hyst_attrs[indx].attr.attr.name =
1202 tz->trip_hyst_attrs[indx].name;
1203 tz->trip_hyst_attrs[indx].attr.attr.mode = S_IRUGO;
1204 tz->trip_hyst_attrs[indx].attr.show = trip_point_hyst_show;
1205 if (tz->ops->set_trip_hyst) {
1206 tz->trip_hyst_attrs[indx].attr.attr.mode |= S_IWUSR;
1207 tz->trip_hyst_attrs[indx].attr.store =
1208 trip_point_hyst_store;
1209 }
1210
1211 device_create_file(&tz->device,
1212 &tz->trip_hyst_attrs[indx].attr);
1139 } 1213 }
1140 return 0; 1214 return 0;
1141} 1215}
@@ -1149,9 +1223,13 @@ static void remove_trip_attrs(struct thermal_zone_device *tz)
1149 &tz->trip_type_attrs[indx].attr); 1223 &tz->trip_type_attrs[indx].attr);
1150 device_remove_file(&tz->device, 1224 device_remove_file(&tz->device,
1151 &tz->trip_temp_attrs[indx].attr); 1225 &tz->trip_temp_attrs[indx].attr);
1226 if (tz->ops->get_trip_hyst)
1227 device_remove_file(&tz->device,
1228 &tz->trip_hyst_attrs[indx].attr);
1152 } 1229 }
1153 kfree(tz->trip_type_attrs); 1230 kfree(tz->trip_type_attrs);
1154 kfree(tz->trip_temp_attrs); 1231 kfree(tz->trip_temp_attrs);
1232 kfree(tz->trip_hyst_attrs);
1155} 1233}
1156 1234
1157/** 1235/**
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index 6eaf9146c847..cfc8d908892e 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -60,6 +60,10 @@ struct thermal_zone_device_ops {
60 unsigned long *); 60 unsigned long *);
61 int (*set_trip_temp) (struct thermal_zone_device *, int, 61 int (*set_trip_temp) (struct thermal_zone_device *, int,
62 unsigned long); 62 unsigned long);
63 int (*get_trip_hyst) (struct thermal_zone_device *, int,
64 unsigned long *);
65 int (*set_trip_hyst) (struct thermal_zone_device *, int,
66 unsigned long);
63 int (*get_crit_temp) (struct thermal_zone_device *, unsigned long *); 67 int (*get_crit_temp) (struct thermal_zone_device *, unsigned long *);
64 int (*notify) (struct thermal_zone_device *, int, 68 int (*notify) (struct thermal_zone_device *, int,
65 enum thermal_trip_type); 69 enum thermal_trip_type);
@@ -98,6 +102,7 @@ struct thermal_zone_device {
98 struct device device; 102 struct device device;
99 struct thermal_attr *trip_temp_attrs; 103 struct thermal_attr *trip_temp_attrs;
100 struct thermal_attr *trip_type_attrs; 104 struct thermal_attr *trip_type_attrs;
105 struct thermal_attr *trip_hyst_attrs;
101 void *devdata; 106 void *devdata;
102 int trips; 107 int trips;
103 int tc1; 108 int tc1;