thermal: Set trip-point temperature via debugfs
[linux-3.10.git] / drivers / thermal / thermal_debugfs.c
1 /*
2  * Copyright (c) 2015, NVIDIA Corporation. All rights reserved.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation version 2.
7  *
8  * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
9  * whether express or implied; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  * General Public License for more details.
12  */
13 #include <linux/kernel.h>
14 #include <linux/debugfs.h>
15 #include <linux/seq_file.h>
16 #include <linux/uaccess.h>
17 #include <linux/err.h>
18 #include <linux/thermal.h>
19
20 static DEFINE_MUTEX(thermal_debug_lock);
21
22 static struct dentry *thermal_debugfs_root;
23
24 int debug_tz_match(struct thermal_zone_device *tz, void *data)
25 {
26         long tz_id = (long)data;
27         return tz->id == tz_id;
28 }
29
30 static ssize_t set_trip_write(struct file *file,
31         const char __user *userbuf, size_t count, loff_t *ppos)
32 {
33         char buf[40];
34         long tz_id, trip, temperature;
35         struct thermal_zone_device *tz;
36         int ret = -ENODEV;
37
38         if (sizeof(buf) <= count)
39                 return -EINVAL;
40
41         if (copy_from_user(buf, userbuf, count))
42                 return -EFAULT;
43
44         buf[count] = '\0';
45         strim(buf);
46
47         if (sscanf(buf, "%ld_%ld_%ld", &tz_id, &trip, &temperature) != 3)
48                 return -EINVAL;
49
50         mutex_lock(&thermal_debug_lock);
51
52         tz = thermal_zone_device_find((void *)tz_id, debug_tz_match);
53
54         if (tz) {
55                 ret = -EPERM;
56                 if (tz->ops->set_trip_temp)
57                         ret = tz->ops->set_trip_temp(tz, trip, temperature);
58         }
59         mutex_unlock(&thermal_debug_lock);
60         return ret ? : count;
61 }
62
63 static const struct file_operations set_trip_fops = {
64         .write          = set_trip_write,
65 };
66
67 static int __init thermal_debugfs_init(void)
68 {
69         struct dentry *d;
70
71         d = debugfs_create_dir("thermal", NULL);
72         if (!d)
73                 return -ENOMEM;
74
75         thermal_debugfs_root = d;
76
77         d = debugfs_create_file("tz_trip_temperature", S_IWUSR,
78                                 thermal_debugfs_root, NULL, &set_trip_fops);
79         if (!d)
80                 goto err_out;
81
82         return 0;
83 err_out:
84         debugfs_remove_recursive(thermal_debugfs_root);
85         thermal_debugfs_root = NULL;
86         return -ENOMEM;
87 }
88 late_initcall(thermal_debugfs_init);