thermal: core: move thermal_zone sysfs to thermal_sysfs.c
[linux-2.6-microblaze.git] / drivers / thermal / thermal_sysfs.c
1 /*
2  *  thermal.c - sysfs interface of thermal devices
3  *
4  *  Copyright (C) 2016 Eduardo Valentin <edubezval@gmail.com>
5  *
6  *  Highly based on original thermal_core.c
7  *  Copyright (C) 2008 Intel Corp
8  *  Copyright (C) 2008 Zhang Rui <rui.zhang@intel.com>
9  *  Copyright (C) 2008 Sujith Thomas <sujith.thomas@intel.com>
10  *
11  *  This program is free software; you can redistribute it and/or modify
12  *  it under the terms of the GNU General Public License as published by
13  *  the Free Software Foundation; version 2 of the License.
14  */
15
16 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
17
18 #include <linux/sysfs.h>
19 #include <linux/device.h>
20 #include <linux/err.h>
21 #include <linux/slab.h>
22 #include <linux/string.h>
23
24 #include "thermal_core.h"
25
26 /* sys I/F for thermal zone */
27
28 static ssize_t
29 type_show(struct device *dev, struct device_attribute *attr, char *buf)
30 {
31         struct thermal_zone_device *tz = to_thermal_zone(dev);
32
33         return sprintf(buf, "%s\n", tz->type);
34 }
35
36 static ssize_t
37 temp_show(struct device *dev, struct device_attribute *attr, char *buf)
38 {
39         struct thermal_zone_device *tz = to_thermal_zone(dev);
40         int temperature, ret;
41
42         ret = thermal_zone_get_temp(tz, &temperature);
43
44         if (ret)
45                 return ret;
46
47         return sprintf(buf, "%d\n", temperature);
48 }
49
50 static ssize_t
51 mode_show(struct device *dev, struct device_attribute *attr, char *buf)
52 {
53         struct thermal_zone_device *tz = to_thermal_zone(dev);
54         enum thermal_device_mode mode;
55         int result;
56
57         if (!tz->ops->get_mode)
58                 return -EPERM;
59
60         result = tz->ops->get_mode(tz, &mode);
61         if (result)
62                 return result;
63
64         return sprintf(buf, "%s\n", mode == THERMAL_DEVICE_ENABLED ? "enabled"
65                        : "disabled");
66 }
67
68 static ssize_t
69 mode_store(struct device *dev, struct device_attribute *attr,
70            const char *buf, size_t count)
71 {
72         struct thermal_zone_device *tz = to_thermal_zone(dev);
73         int result;
74
75         if (!tz->ops->set_mode)
76                 return -EPERM;
77
78         if (!strncmp(buf, "enabled", sizeof("enabled") - 1))
79                 result = tz->ops->set_mode(tz, THERMAL_DEVICE_ENABLED);
80         else if (!strncmp(buf, "disabled", sizeof("disabled") - 1))
81                 result = tz->ops->set_mode(tz, THERMAL_DEVICE_DISABLED);
82         else
83                 result = -EINVAL;
84
85         if (result)
86                 return result;
87
88         return count;
89 }
90
91 static ssize_t
92 trip_point_type_show(struct device *dev, struct device_attribute *attr,
93                      char *buf)
94 {
95         struct thermal_zone_device *tz = to_thermal_zone(dev);
96         enum thermal_trip_type type;
97         int trip, result;
98
99         if (!tz->ops->get_trip_type)
100                 return -EPERM;
101
102         if (sscanf(attr->attr.name, "trip_point_%d_type", &trip) != 1)
103                 return -EINVAL;
104
105         result = tz->ops->get_trip_type(tz, trip, &type);
106         if (result)
107                 return result;
108
109         switch (type) {
110         case THERMAL_TRIP_CRITICAL:
111                 return sprintf(buf, "critical\n");
112         case THERMAL_TRIP_HOT:
113                 return sprintf(buf, "hot\n");
114         case THERMAL_TRIP_PASSIVE:
115                 return sprintf(buf, "passive\n");
116         case THERMAL_TRIP_ACTIVE:
117                 return sprintf(buf, "active\n");
118         default:
119                 return sprintf(buf, "unknown\n");
120         }
121 }
122
123 static ssize_t
124 trip_point_temp_store(struct device *dev, struct device_attribute *attr,
125                       const char *buf, size_t count)
126 {
127         struct thermal_zone_device *tz = to_thermal_zone(dev);
128         int trip, ret;
129         int temperature;
130
131         if (!tz->ops->set_trip_temp)
132                 return -EPERM;
133
134         if (sscanf(attr->attr.name, "trip_point_%d_temp", &trip) != 1)
135                 return -EINVAL;
136
137         if (kstrtoint(buf, 10, &temperature))
138                 return -EINVAL;
139
140         ret = tz->ops->set_trip_temp(tz, trip, temperature);
141         if (ret)
142                 return ret;
143
144         thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
145
146         return count;
147 }
148
149 static ssize_t
150 trip_point_temp_show(struct device *dev, struct device_attribute *attr,
151                      char *buf)
152 {
153         struct thermal_zone_device *tz = to_thermal_zone(dev);
154         int trip, ret;
155         int temperature;
156
157         if (!tz->ops->get_trip_temp)
158                 return -EPERM;
159
160         if (sscanf(attr->attr.name, "trip_point_%d_temp", &trip) != 1)
161                 return -EINVAL;
162
163         ret = tz->ops->get_trip_temp(tz, trip, &temperature);
164
165         if (ret)
166                 return ret;
167
168         return sprintf(buf, "%d\n", temperature);
169 }
170
171 static ssize_t
172 trip_point_hyst_store(struct device *dev, struct device_attribute *attr,
173                       const char *buf, size_t count)
174 {
175         struct thermal_zone_device *tz = to_thermal_zone(dev);
176         int trip, ret;
177         int temperature;
178
179         if (!tz->ops->set_trip_hyst)
180                 return -EPERM;
181
182         if (sscanf(attr->attr.name, "trip_point_%d_hyst", &trip) != 1)
183                 return -EINVAL;
184
185         if (kstrtoint(buf, 10, &temperature))
186                 return -EINVAL;
187
188         /*
189          * We are not doing any check on the 'temperature' value
190          * here. The driver implementing 'set_trip_hyst' has to
191          * take care of this.
192          */
193         ret = tz->ops->set_trip_hyst(tz, trip, temperature);
194
195         if (!ret)
196                 thermal_zone_set_trips(tz);
197
198         return ret ? ret : count;
199 }
200
201 static ssize_t
202 trip_point_hyst_show(struct device *dev, struct device_attribute *attr,
203                      char *buf)
204 {
205         struct thermal_zone_device *tz = to_thermal_zone(dev);
206         int trip, ret;
207         int temperature;
208
209         if (!tz->ops->get_trip_hyst)
210                 return -EPERM;
211
212         if (sscanf(attr->attr.name, "trip_point_%d_hyst", &trip) != 1)
213                 return -EINVAL;
214
215         ret = tz->ops->get_trip_hyst(tz, trip, &temperature);
216
217         return ret ? ret : sprintf(buf, "%d\n", temperature);
218 }
219
220 static ssize_t
221 passive_store(struct device *dev, struct device_attribute *attr,
222               const char *buf, size_t count)
223 {
224         struct thermal_zone_device *tz = to_thermal_zone(dev);
225         int state;
226
227         if (sscanf(buf, "%d\n", &state) != 1)
228                 return -EINVAL;
229
230         /* sanity check: values below 1000 millicelcius don't make sense
231          * and can cause the system to go into a thermal heart attack
232          */
233         if (state && state < 1000)
234                 return -EINVAL;
235
236         if (state && !tz->forced_passive) {
237                 if (!tz->passive_delay)
238                         tz->passive_delay = 1000;
239                 thermal_zone_device_rebind_exception(tz, "Processor",
240                                                      sizeof("Processor"));
241         } else if (!state && tz->forced_passive) {
242                 tz->passive_delay = 0;
243                 thermal_zone_device_unbind_exception(tz, "Processor",
244                                                      sizeof("Processor"));
245         }
246
247         tz->forced_passive = state;
248
249         thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
250
251         return count;
252 }
253
254 static ssize_t
255 passive_show(struct device *dev, struct device_attribute *attr,
256              char *buf)
257 {
258         struct thermal_zone_device *tz = to_thermal_zone(dev);
259
260         return sprintf(buf, "%d\n", tz->forced_passive);
261 }
262
263 static ssize_t
264 policy_store(struct device *dev, struct device_attribute *attr,
265              const char *buf, size_t count)
266 {
267         struct thermal_zone_device *tz = to_thermal_zone(dev);
268         char name[THERMAL_NAME_LENGTH];
269         int ret;
270
271         snprintf(name, sizeof(name), "%s", buf);
272
273         ret = thermal_zone_device_set_policy(tz, name);
274         if (!ret)
275                 ret = count;
276
277         return ret;
278 }
279
280 static ssize_t
281 policy_show(struct device *dev, struct device_attribute *devattr, char *buf)
282 {
283         struct thermal_zone_device *tz = to_thermal_zone(dev);
284
285         return sprintf(buf, "%s\n", tz->governor->name);
286 }
287
288 static ssize_t
289 available_policies_show(struct device *dev, struct device_attribute *devattr,
290                         char *buf)
291 {
292         return thermal_build_list_of_policies(buf);
293 }
294
295 static ssize_t
296 emul_temp_store(struct device *dev, struct device_attribute *attr,
297                 const char *buf, size_t count)
298 {
299         struct thermal_zone_device *tz = to_thermal_zone(dev);
300         int ret = 0;
301         int temperature;
302
303         if (kstrtoint(buf, 10, &temperature))
304                 return -EINVAL;
305
306         if (!tz->ops->set_emul_temp) {
307                 mutex_lock(&tz->lock);
308                 tz->emul_temperature = temperature;
309                 mutex_unlock(&tz->lock);
310         } else {
311                 ret = tz->ops->set_emul_temp(tz, temperature);
312         }
313
314         if (!ret)
315                 thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
316
317         return ret ? ret : count;
318 }
319
320 static ssize_t
321 sustainable_power_show(struct device *dev, struct device_attribute *devattr,
322                        char *buf)
323 {
324         struct thermal_zone_device *tz = to_thermal_zone(dev);
325
326         if (tz->tzp)
327                 return sprintf(buf, "%u\n", tz->tzp->sustainable_power);
328         else
329                 return -EIO;
330 }
331
332 static ssize_t
333 sustainable_power_store(struct device *dev, struct device_attribute *devattr,
334                         const char *buf, size_t count)
335 {
336         struct thermal_zone_device *tz = to_thermal_zone(dev);
337         u32 sustainable_power;
338
339         if (!tz->tzp)
340                 return -EIO;
341
342         if (kstrtou32(buf, 10, &sustainable_power))
343                 return -EINVAL;
344
345         tz->tzp->sustainable_power = sustainable_power;
346
347         return count;
348 }
349
350 #define create_s32_tzp_attr(name)                                       \
351         static ssize_t                                                  \
352         name##_show(struct device *dev, struct device_attribute *devattr, \
353                 char *buf)                                              \
354         {                                                               \
355         struct thermal_zone_device *tz = to_thermal_zone(dev);          \
356                                                                         \
357         if (tz->tzp)                                                    \
358                 return sprintf(buf, "%d\n", tz->tzp->name);             \
359         else                                                            \
360                 return -EIO;                                            \
361         }                                                               \
362                                                                         \
363         static ssize_t                                                  \
364         name##_store(struct device *dev, struct device_attribute *devattr, \
365                 const char *buf, size_t count)                          \
366         {                                                               \
367                 struct thermal_zone_device *tz = to_thermal_zone(dev);  \
368                 s32 value;                                              \
369                                                                         \
370                 if (!tz->tzp)                                           \
371                         return -EIO;                                    \
372                                                                         \
373                 if (kstrtos32(buf, 10, &value))                         \
374                         return -EINVAL;                                 \
375                                                                         \
376                 tz->tzp->name = value;                                  \
377                                                                         \
378                 return count;                                           \
379         }                                                               \
380         static DEVICE_ATTR(name, S_IWUSR | S_IRUGO, name##_show, name##_store)
381
382 create_s32_tzp_attr(k_po);
383 create_s32_tzp_attr(k_pu);
384 create_s32_tzp_attr(k_i);
385 create_s32_tzp_attr(k_d);
386 create_s32_tzp_attr(integral_cutoff);
387 create_s32_tzp_attr(slope);
388 create_s32_tzp_attr(offset);
389 #undef create_s32_tzp_attr
390
391 /*
392  * These are thermal zone device attributes that will always be present.
393  * All the attributes created for tzp (create_s32_tzp_attr) also are always
394  * present on the sysfs interface.
395  */
396 static DEVICE_ATTR(type, 0444, type_show, NULL);
397 static DEVICE_ATTR(temp, 0444, temp_show, NULL);
398 static DEVICE_ATTR(emul_temp, S_IWUSR, NULL, emul_temp_store);
399 static DEVICE_ATTR(policy, S_IRUGO | S_IWUSR, policy_show, policy_store);
400 static DEVICE_ATTR(available_policies, S_IRUGO, available_policies_show, NULL);
401 static DEVICE_ATTR(sustainable_power, S_IWUSR | S_IRUGO, sustainable_power_show,
402                    sustainable_power_store);
403
404 /* These thermal zone device attributes are created based on conditions */
405 static DEVICE_ATTR(mode, 0644, mode_show, mode_store);
406 static DEVICE_ATTR(passive, S_IRUGO | S_IWUSR, passive_show, passive_store);
407
408 /* These attributes are unconditionally added to a thermal zone */
409 static struct attribute *thermal_zone_dev_attrs[] = {
410         &dev_attr_type.attr,
411         &dev_attr_temp.attr,
412 #if (IS_ENABLED(CONFIG_THERMAL_EMULATION))
413         &dev_attr_emul_temp.attr,
414 #endif
415         &dev_attr_policy.attr,
416         &dev_attr_available_policies.attr,
417         &dev_attr_sustainable_power.attr,
418         &dev_attr_k_po.attr,
419         &dev_attr_k_pu.attr,
420         &dev_attr_k_i.attr,
421         &dev_attr_k_d.attr,
422         &dev_attr_integral_cutoff.attr,
423         &dev_attr_slope.attr,
424         &dev_attr_offset.attr,
425         NULL,
426 };
427
428 static struct attribute_group thermal_zone_attribute_group = {
429         .attrs = thermal_zone_dev_attrs,
430 };
431
432 /* We expose mode only if .get_mode is present */
433 static struct attribute *thermal_zone_mode_attrs[] = {
434         &dev_attr_mode.attr,
435         NULL,
436 };
437
438 static umode_t thermal_zone_mode_is_visible(struct kobject *kobj,
439                                             struct attribute *attr,
440                                             int attrno)
441 {
442         struct device *dev = container_of(kobj, struct device, kobj);
443         struct thermal_zone_device *tz;
444
445         tz = container_of(dev, struct thermal_zone_device, device);
446
447         if (tz->ops->get_mode)
448                 return attr->mode;
449
450         return 0;
451 }
452
453 static struct attribute_group thermal_zone_mode_attribute_group = {
454         .attrs = thermal_zone_mode_attrs,
455         .is_visible = thermal_zone_mode_is_visible,
456 };
457
458 /* We expose passive only if passive trips are present */
459 static struct attribute *thermal_zone_passive_attrs[] = {
460         &dev_attr_passive.attr,
461         NULL,
462 };
463
464 static umode_t thermal_zone_passive_is_visible(struct kobject *kobj,
465                                                struct attribute *attr,
466                                                int attrno)
467 {
468         struct device *dev = container_of(kobj, struct device, kobj);
469         struct thermal_zone_device *tz;
470         enum thermal_trip_type trip_type;
471         int count, passive = 0;
472
473         tz = container_of(dev, struct thermal_zone_device, device);
474
475         for (count = 0; count < tz->trips && !passive; count++) {
476                 tz->ops->get_trip_type(tz, count, &trip_type);
477
478                 if (trip_type == THERMAL_TRIP_PASSIVE)
479                         passive = 1;
480         }
481
482         if (!passive)
483                 return attr->mode;
484
485         return 0;
486 }
487
488 static struct attribute_group thermal_zone_passive_attribute_group = {
489         .attrs = thermal_zone_passive_attrs,
490         .is_visible = thermal_zone_passive_is_visible,
491 };
492
493 static const struct attribute_group *thermal_zone_attribute_groups[] = {
494         &thermal_zone_attribute_group,
495         &thermal_zone_mode_attribute_group,
496         &thermal_zone_passive_attribute_group,
497         /* This is not NULL terminated as we create the group dynamically */
498 };
499
500 /**
501  * create_trip_attrs() - create attributes for trip points
502  * @tz:         the thermal zone device
503  * @mask:       Writeable trip point bitmap.
504  *
505  * helper function to instantiate sysfs entries for every trip
506  * point and its properties of a struct thermal_zone_device.
507  *
508  * Return: 0 on success, the proper error value otherwise.
509  */
510 static int create_trip_attrs(struct thermal_zone_device *tz, int mask)
511 {
512         int size = sizeof(struct thermal_attr) * tz->trips;
513         struct attribute **attrs;
514         int indx;
515
516         /* This function works only for zones with at least one trip */
517         if (tz->trips <= 0)
518                 return -EINVAL;
519
520         tz->trip_type_attrs = kzalloc(size, GFP_KERNEL);
521         if (!tz->trip_type_attrs)
522                 return -ENOMEM;
523
524         tz->trip_temp_attrs = kzalloc(size, GFP_KERNEL);
525         if (!tz->trip_temp_attrs) {
526                 kfree(tz->trip_type_attrs);
527                 return -ENOMEM;
528         }
529
530         if (tz->ops->get_trip_hyst) {
531                 tz->trip_hyst_attrs = kzalloc(size, GFP_KERNEL);
532                 if (!tz->trip_hyst_attrs) {
533                         kfree(tz->trip_type_attrs);
534                         kfree(tz->trip_temp_attrs);
535                         return -ENOMEM;
536                 }
537         }
538
539         attrs = kzalloc(sizeof(*attrs) * tz->trips * 3 + 1, GFP_KERNEL);
540         if (!attrs) {
541                 kfree(tz->trip_type_attrs);
542                 kfree(tz->trip_temp_attrs);
543                 if (tz->ops->get_trip_hyst)
544                         kfree(tz->trip_hyst_attrs);
545                 return -ENOMEM;
546         }
547
548         for (indx = 0; indx < tz->trips; indx++) {
549                 /* create trip type attribute */
550                 snprintf(tz->trip_type_attrs[indx].name, THERMAL_NAME_LENGTH,
551                          "trip_point_%d_type", indx);
552
553                 sysfs_attr_init(&tz->trip_type_attrs[indx].attr.attr);
554                 tz->trip_type_attrs[indx].attr.attr.name =
555                                                 tz->trip_type_attrs[indx].name;
556                 tz->trip_type_attrs[indx].attr.attr.mode = S_IRUGO;
557                 tz->trip_type_attrs[indx].attr.show = trip_point_type_show;
558                 attrs[indx] = &tz->trip_type_attrs[indx].attr.attr;
559
560                 /* create trip temp attribute */
561                 snprintf(tz->trip_temp_attrs[indx].name, THERMAL_NAME_LENGTH,
562                          "trip_point_%d_temp", indx);
563
564                 sysfs_attr_init(&tz->trip_temp_attrs[indx].attr.attr);
565                 tz->trip_temp_attrs[indx].attr.attr.name =
566                                                 tz->trip_temp_attrs[indx].name;
567                 tz->trip_temp_attrs[indx].attr.attr.mode = S_IRUGO;
568                 tz->trip_temp_attrs[indx].attr.show = trip_point_temp_show;
569                 if (IS_ENABLED(CONFIG_THERMAL_WRITABLE_TRIPS) &&
570                     mask & (1 << indx)) {
571                         tz->trip_temp_attrs[indx].attr.attr.mode |= S_IWUSR;
572                         tz->trip_temp_attrs[indx].attr.store =
573                                                         trip_point_temp_store;
574                 }
575                 attrs[indx + tz->trips] = &tz->trip_temp_attrs[indx].attr.attr;
576
577                 /* create Optional trip hyst attribute */
578                 if (!tz->ops->get_trip_hyst)
579                         continue;
580                 snprintf(tz->trip_hyst_attrs[indx].name, THERMAL_NAME_LENGTH,
581                          "trip_point_%d_hyst", indx);
582
583                 sysfs_attr_init(&tz->trip_hyst_attrs[indx].attr.attr);
584                 tz->trip_hyst_attrs[indx].attr.attr.name =
585                                         tz->trip_hyst_attrs[indx].name;
586                 tz->trip_hyst_attrs[indx].attr.attr.mode = S_IRUGO;
587                 tz->trip_hyst_attrs[indx].attr.show = trip_point_hyst_show;
588                 if (tz->ops->set_trip_hyst) {
589                         tz->trip_hyst_attrs[indx].attr.attr.mode |= S_IWUSR;
590                         tz->trip_hyst_attrs[indx].attr.store =
591                                         trip_point_hyst_store;
592                 }
593                 attrs[indx + tz->trips * 2] =
594                                         &tz->trip_hyst_attrs[indx].attr.attr;
595         }
596         attrs[tz->trips * 3] = NULL;
597
598         tz->trips_attribute_group.attrs = attrs;
599
600         return 0;
601 }
602
603 int thermal_zone_create_device_groups(struct thermal_zone_device *tz,
604                                       int mask)
605 {
606         const struct attribute_group **groups;
607         int i, size, result;
608
609         /* we need one extra for trips and the NULL to terminate the array */
610         size = ARRAY_SIZE(thermal_zone_attribute_groups) + 2;
611         /* This also takes care of API requirement to be NULL terminated */
612         groups = kcalloc(size, sizeof(*groups), GFP_KERNEL);
613         if (!groups)
614                 return -ENOMEM;
615
616         for (i = 0; i < size - 2; i++)
617                 groups[i] = thermal_zone_attribute_groups[i];
618
619         if (tz->trips) {
620                 result = create_trip_attrs(tz, mask);
621                 if (result) {
622                         kfree(groups);
623
624                         return result;
625                 }
626
627                 groups[size - 2] = &tz->trips_attribute_group;
628         }
629
630         tz->device.groups = groups;
631
632         return 0;
633 }