]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - drivers/gpu/drm/nouveau/nouveau_hwmon.c
Merge branch 'drm-armada-devel' of git://ftp.arm.linux.org.uk/~rmk/linux-arm into...
[mirror_ubuntu-bionic-kernel.git] / drivers / gpu / drm / nouveau / nouveau_hwmon.c
CommitLineData
330c5988
BS
1/*
2 * Copyright 2010 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Ben Skeggs
23 */
24
6032649d
BS
25#ifdef CONFIG_ACPI
26#include <linux/acpi.h>
27#endif
28#include <linux/power_supply.h>
34e9d85a
MP
29#include <linux/hwmon.h>
30#include <linux/hwmon-sysfs.h>
31
612a9aab 32#include <drm/drmP.h>
a175094c 33
77145f1c 34#include "nouveau_drm.h"
b9ed919f 35#include "nouveau_hwmon.h"
a175094c 36
658e86ee 37#if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE))
34e9d85a
MP
38static ssize_t
39nouveau_hwmon_show_temp(struct device *d, struct device_attribute *a, char *buf)
40{
41 struct drm_device *dev = dev_get_drvdata(d);
aa1b9b48 42 struct nouveau_drm *drm = nouveau_drm(dev);
be83cd4e 43 struct nvkm_therm *therm = nvxx_therm(&drm->device);
57113c01 44 int temp = nvkm_therm_temp_get(therm);
34e9d85a 45
804ca90f
MP
46 if (temp < 0)
47 return temp;
48
49 return snprintf(buf, PAGE_SIZE, "%d\n", temp * 1000);
34e9d85a
MP
50}
51static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, nouveau_hwmon_show_temp,
52 NULL, 0);
53
12e32896
MP
54static ssize_t
55nouveau_hwmon_show_temp1_auto_point1_pwm(struct device *d,
56 struct device_attribute *a, char *buf)
57{
58 return snprintf(buf, PAGE_SIZE, "%d\n", 100);
59}
60static SENSOR_DEVICE_ATTR(temp1_auto_point1_pwm, S_IRUGO,
61 nouveau_hwmon_show_temp1_auto_point1_pwm, NULL, 0);
62
63static ssize_t
64nouveau_hwmon_temp1_auto_point1_temp(struct device *d,
65 struct device_attribute *a, char *buf)
66{
67 struct drm_device *dev = dev_get_drvdata(d);
68 struct nouveau_drm *drm = nouveau_drm(dev);
be83cd4e 69 struct nvkm_therm *therm = nvxx_therm(&drm->device);
12e32896
MP
70
71 return snprintf(buf, PAGE_SIZE, "%d\n",
e1404611 72 therm->attr_get(therm, NVKM_THERM_ATTR_THRS_FAN_BOOST) * 1000);
12e32896
MP
73}
74static ssize_t
75nouveau_hwmon_set_temp1_auto_point1_temp(struct device *d,
76 struct device_attribute *a,
77 const char *buf, size_t count)
78{
79 struct drm_device *dev = dev_get_drvdata(d);
80 struct nouveau_drm *drm = nouveau_drm(dev);
be83cd4e 81 struct nvkm_therm *therm = nvxx_therm(&drm->device);
12e32896
MP
82 long value;
83
84 if (kstrtol(buf, 10, &value) == -EINVAL)
85 return count;
86
e1404611 87 therm->attr_set(therm, NVKM_THERM_ATTR_THRS_FAN_BOOST,
12e32896
MP
88 value / 1000);
89
90 return count;
91}
92static SENSOR_DEVICE_ATTR(temp1_auto_point1_temp, S_IRUGO | S_IWUSR,
93 nouveau_hwmon_temp1_auto_point1_temp,
94 nouveau_hwmon_set_temp1_auto_point1_temp, 0);
95
96static ssize_t
97nouveau_hwmon_temp1_auto_point1_temp_hyst(struct device *d,
98 struct device_attribute *a, char *buf)
99{
100 struct drm_device *dev = dev_get_drvdata(d);
101 struct nouveau_drm *drm = nouveau_drm(dev);
be83cd4e 102 struct nvkm_therm *therm = nvxx_therm(&drm->device);
12e32896
MP
103
104 return snprintf(buf, PAGE_SIZE, "%d\n",
e1404611 105 therm->attr_get(therm, NVKM_THERM_ATTR_THRS_FAN_BOOST_HYST) * 1000);
12e32896
MP
106}
107static ssize_t
108nouveau_hwmon_set_temp1_auto_point1_temp_hyst(struct device *d,
109 struct device_attribute *a,
110 const char *buf, size_t count)
111{
112 struct drm_device *dev = dev_get_drvdata(d);
113 struct nouveau_drm *drm = nouveau_drm(dev);
be83cd4e 114 struct nvkm_therm *therm = nvxx_therm(&drm->device);
12e32896
MP
115 long value;
116
117 if (kstrtol(buf, 10, &value) == -EINVAL)
118 return count;
119
e1404611 120 therm->attr_set(therm, NVKM_THERM_ATTR_THRS_FAN_BOOST_HYST,
12e32896
MP
121 value / 1000);
122
123 return count;
124}
125static SENSOR_DEVICE_ATTR(temp1_auto_point1_temp_hyst, S_IRUGO | S_IWUSR,
126 nouveau_hwmon_temp1_auto_point1_temp_hyst,
127 nouveau_hwmon_set_temp1_auto_point1_temp_hyst, 0);
128
34e9d85a
MP
129static ssize_t
130nouveau_hwmon_max_temp(struct device *d, struct device_attribute *a, char *buf)
131{
132 struct drm_device *dev = dev_get_drvdata(d);
aa1b9b48 133 struct nouveau_drm *drm = nouveau_drm(dev);
be83cd4e 134 struct nvkm_therm *therm = nvxx_therm(&drm->device);
34e9d85a 135
aa1b9b48 136 return snprintf(buf, PAGE_SIZE, "%d\n",
e1404611 137 therm->attr_get(therm, NVKM_THERM_ATTR_THRS_DOWN_CLK) * 1000);
34e9d85a
MP
138}
139static ssize_t
140nouveau_hwmon_set_max_temp(struct device *d, struct device_attribute *a,
141 const char *buf, size_t count)
142{
143 struct drm_device *dev = dev_get_drvdata(d);
aa1b9b48 144 struct nouveau_drm *drm = nouveau_drm(dev);
be83cd4e 145 struct nvkm_therm *therm = nvxx_therm(&drm->device);
34e9d85a
MP
146 long value;
147
ddb20055 148 if (kstrtol(buf, 10, &value) == -EINVAL)
34e9d85a
MP
149 return count;
150
e1404611 151 therm->attr_set(therm, NVKM_THERM_ATTR_THRS_DOWN_CLK, value / 1000);
34e9d85a
MP
152
153 return count;
154}
155static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR, nouveau_hwmon_max_temp,
156 nouveau_hwmon_set_max_temp,
157 0);
158
12e32896
MP
159static ssize_t
160nouveau_hwmon_max_temp_hyst(struct device *d, struct device_attribute *a,
161 char *buf)
162{
163 struct drm_device *dev = dev_get_drvdata(d);
164 struct nouveau_drm *drm = nouveau_drm(dev);
be83cd4e 165 struct nvkm_therm *therm = nvxx_therm(&drm->device);
12e32896
MP
166
167 return snprintf(buf, PAGE_SIZE, "%d\n",
e1404611 168 therm->attr_get(therm, NVKM_THERM_ATTR_THRS_DOWN_CLK_HYST) * 1000);
12e32896
MP
169}
170static ssize_t
171nouveau_hwmon_set_max_temp_hyst(struct device *d, struct device_attribute *a,
172 const char *buf, size_t count)
173{
174 struct drm_device *dev = dev_get_drvdata(d);
175 struct nouveau_drm *drm = nouveau_drm(dev);
be83cd4e 176 struct nvkm_therm *therm = nvxx_therm(&drm->device);
12e32896
MP
177 long value;
178
179 if (kstrtol(buf, 10, &value) == -EINVAL)
180 return count;
181
e1404611 182 therm->attr_set(therm, NVKM_THERM_ATTR_THRS_DOWN_CLK_HYST,
12e32896
MP
183 value / 1000);
184
185 return count;
186}
187static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR,
188 nouveau_hwmon_max_temp_hyst,
189 nouveau_hwmon_set_max_temp_hyst, 0);
190
34e9d85a
MP
191static ssize_t
192nouveau_hwmon_critical_temp(struct device *d, struct device_attribute *a,
193 char *buf)
194{
195 struct drm_device *dev = dev_get_drvdata(d);
aa1b9b48 196 struct nouveau_drm *drm = nouveau_drm(dev);
be83cd4e 197 struct nvkm_therm *therm = nvxx_therm(&drm->device);
34e9d85a 198
aa1b9b48 199 return snprintf(buf, PAGE_SIZE, "%d\n",
e1404611 200 therm->attr_get(therm, NVKM_THERM_ATTR_THRS_CRITICAL) * 1000);
34e9d85a
MP
201}
202static ssize_t
203nouveau_hwmon_set_critical_temp(struct device *d, struct device_attribute *a,
204 const char *buf,
205 size_t count)
206{
207 struct drm_device *dev = dev_get_drvdata(d);
aa1b9b48 208 struct nouveau_drm *drm = nouveau_drm(dev);
be83cd4e 209 struct nvkm_therm *therm = nvxx_therm(&drm->device);
34e9d85a
MP
210 long value;
211
ddb20055 212 if (kstrtol(buf, 10, &value) == -EINVAL)
34e9d85a
MP
213 return count;
214
e1404611 215 therm->attr_set(therm, NVKM_THERM_ATTR_THRS_CRITICAL, value / 1000);
34e9d85a
MP
216
217 return count;
218}
219static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO | S_IWUSR,
220 nouveau_hwmon_critical_temp,
221 nouveau_hwmon_set_critical_temp,
222 0);
223
12e32896
MP
224static ssize_t
225nouveau_hwmon_critical_temp_hyst(struct device *d, struct device_attribute *a,
226 char *buf)
227{
228 struct drm_device *dev = dev_get_drvdata(d);
229 struct nouveau_drm *drm = nouveau_drm(dev);
be83cd4e 230 struct nvkm_therm *therm = nvxx_therm(&drm->device);
12e32896
MP
231
232 return snprintf(buf, PAGE_SIZE, "%d\n",
e1404611 233 therm->attr_get(therm, NVKM_THERM_ATTR_THRS_CRITICAL_HYST) * 1000);
12e32896
MP
234}
235static ssize_t
236nouveau_hwmon_set_critical_temp_hyst(struct device *d,
237 struct device_attribute *a,
238 const char *buf,
239 size_t count)
240{
241 struct drm_device *dev = dev_get_drvdata(d);
242 struct nouveau_drm *drm = nouveau_drm(dev);
be83cd4e 243 struct nvkm_therm *therm = nvxx_therm(&drm->device);
12e32896
MP
244 long value;
245
246 if (kstrtol(buf, 10, &value) == -EINVAL)
247 return count;
248
e1404611 249 therm->attr_set(therm, NVKM_THERM_ATTR_THRS_CRITICAL_HYST,
12e32896
MP
250 value / 1000);
251
252 return count;
253}
254static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO | S_IWUSR,
255 nouveau_hwmon_critical_temp_hyst,
256 nouveau_hwmon_set_critical_temp_hyst, 0);
257static ssize_t
258nouveau_hwmon_emergency_temp(struct device *d, struct device_attribute *a,
259 char *buf)
260{
261 struct drm_device *dev = dev_get_drvdata(d);
262 struct nouveau_drm *drm = nouveau_drm(dev);
be83cd4e 263 struct nvkm_therm *therm = nvxx_therm(&drm->device);
12e32896
MP
264
265 return snprintf(buf, PAGE_SIZE, "%d\n",
e1404611 266 therm->attr_get(therm, NVKM_THERM_ATTR_THRS_SHUTDOWN) * 1000);
12e32896
MP
267}
268static ssize_t
269nouveau_hwmon_set_emergency_temp(struct device *d, struct device_attribute *a,
270 const char *buf,
271 size_t count)
272{
273 struct drm_device *dev = dev_get_drvdata(d);
274 struct nouveau_drm *drm = nouveau_drm(dev);
be83cd4e 275 struct nvkm_therm *therm = nvxx_therm(&drm->device);
12e32896
MP
276 long value;
277
278 if (kstrtol(buf, 10, &value) == -EINVAL)
279 return count;
280
e1404611 281 therm->attr_set(therm, NVKM_THERM_ATTR_THRS_SHUTDOWN, value / 1000);
12e32896
MP
282
283 return count;
284}
285static SENSOR_DEVICE_ATTR(temp1_emergency, S_IRUGO | S_IWUSR,
286 nouveau_hwmon_emergency_temp,
287 nouveau_hwmon_set_emergency_temp,
288 0);
289
290static ssize_t
291nouveau_hwmon_emergency_temp_hyst(struct device *d, struct device_attribute *a,
292 char *buf)
293{
294 struct drm_device *dev = dev_get_drvdata(d);
295 struct nouveau_drm *drm = nouveau_drm(dev);
be83cd4e 296 struct nvkm_therm *therm = nvxx_therm(&drm->device);
12e32896
MP
297
298 return snprintf(buf, PAGE_SIZE, "%d\n",
e1404611 299 therm->attr_get(therm, NVKM_THERM_ATTR_THRS_SHUTDOWN_HYST) * 1000);
12e32896
MP
300}
301static ssize_t
302nouveau_hwmon_set_emergency_temp_hyst(struct device *d,
303 struct device_attribute *a,
304 const char *buf,
305 size_t count)
306{
307 struct drm_device *dev = dev_get_drvdata(d);
308 struct nouveau_drm *drm = nouveau_drm(dev);
be83cd4e 309 struct nvkm_therm *therm = nvxx_therm(&drm->device);
12e32896
MP
310 long value;
311
312 if (kstrtol(buf, 10, &value) == -EINVAL)
313 return count;
314
e1404611 315 therm->attr_set(therm, NVKM_THERM_ATTR_THRS_SHUTDOWN_HYST,
12e32896
MP
316 value / 1000);
317
318 return count;
319}
320static SENSOR_DEVICE_ATTR(temp1_emergency_hyst, S_IRUGO | S_IWUSR,
321 nouveau_hwmon_emergency_temp_hyst,
322 nouveau_hwmon_set_emergency_temp_hyst,
323 0);
324
34e9d85a
MP
325static ssize_t nouveau_hwmon_show_name(struct device *dev,
326 struct device_attribute *attr,
327 char *buf)
328{
329 return sprintf(buf, "nouveau\n");
330}
331static SENSOR_DEVICE_ATTR(name, S_IRUGO, nouveau_hwmon_show_name, NULL, 0);
332
333static ssize_t nouveau_hwmon_show_update_rate(struct device *dev,
334 struct device_attribute *attr,
335 char *buf)
336{
337 return sprintf(buf, "1000\n");
338}
339static SENSOR_DEVICE_ATTR(update_rate, S_IRUGO,
340 nouveau_hwmon_show_update_rate,
341 NULL, 0);
342
11b7d895 343static ssize_t
b2c36312 344nouveau_hwmon_show_fan1_input(struct device *d, struct device_attribute *attr,
11b7d895
MP
345 char *buf)
346{
347 struct drm_device *dev = dev_get_drvdata(d);
77145f1c 348 struct nouveau_drm *drm = nouveau_drm(dev);
be83cd4e 349 struct nvkm_therm *therm = nvxx_therm(&drm->device);
11b7d895 350
57113c01 351 return snprintf(buf, PAGE_SIZE, "%d\n", nvkm_therm_fan_sense(therm));
11b7d895 352}
b2c36312 353static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, nouveau_hwmon_show_fan1_input,
11b7d895
MP
354 NULL, 0);
355
2f951a5d
MP
356 static ssize_t
357nouveau_hwmon_get_pwm1_enable(struct device *d,
358 struct device_attribute *a, char *buf)
359{
360 struct drm_device *dev = dev_get_drvdata(d);
361 struct nouveau_drm *drm = nouveau_drm(dev);
be83cd4e 362 struct nvkm_therm *therm = nvxx_therm(&drm->device);
a0b25635 363 int ret;
11b7d895 364
e1404611 365 ret = therm->attr_get(therm, NVKM_THERM_ATTR_FAN_MODE);
2f951a5d 366 if (ret < 0)
a0b25635 367 return ret;
11b7d895 368
2f951a5d
MP
369 return sprintf(buf, "%i\n", ret);
370}
11b7d895 371
2f951a5d
MP
372static ssize_t
373nouveau_hwmon_set_pwm1_enable(struct device *d, struct device_attribute *a,
374 const char *buf, size_t count)
375{
376 struct drm_device *dev = dev_get_drvdata(d);
377 struct nouveau_drm *drm = nouveau_drm(dev);
be83cd4e 378 struct nvkm_therm *therm = nvxx_therm(&drm->device);
2f951a5d
MP
379 long value;
380 int ret;
381
0ac4e3a5
JH
382 ret = kstrtol(buf, 10, &value);
383 if (ret)
384 return ret;
11b7d895 385
e1404611 386 ret = therm->attr_set(therm, NVKM_THERM_ATTR_FAN_MODE, value);
2f951a5d
MP
387 if (ret)
388 return ret;
389 else
390 return count;
11b7d895 391}
2f951a5d
MP
392static SENSOR_DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR,
393 nouveau_hwmon_get_pwm1_enable,
394 nouveau_hwmon_set_pwm1_enable, 0);
11b7d895
MP
395
396static ssize_t
c9cbf135 397nouveau_hwmon_get_pwm1(struct device *d, struct device_attribute *a, char *buf)
11b7d895
MP
398{
399 struct drm_device *dev = dev_get_drvdata(d);
aa1b9b48 400 struct nouveau_drm *drm = nouveau_drm(dev);
be83cd4e 401 struct nvkm_therm *therm = nvxx_therm(&drm->device);
a175094c 402 int ret;
11b7d895 403
aa1b9b48 404 ret = therm->fan_get(therm);
11b7d895
MP
405 if (ret < 0)
406 return ret;
407
408 return sprintf(buf, "%i\n", ret);
409}
410
411static ssize_t
c9cbf135 412nouveau_hwmon_set_pwm1(struct device *d, struct device_attribute *a,
11b7d895
MP
413 const char *buf, size_t count)
414{
415 struct drm_device *dev = dev_get_drvdata(d);
aa1b9b48 416 struct nouveau_drm *drm = nouveau_drm(dev);
be83cd4e 417 struct nvkm_therm *therm = nvxx_therm(&drm->device);
11b7d895
MP
418 int ret = -ENODEV;
419 long value;
420
ddb20055 421 if (kstrtol(buf, 10, &value) == -EINVAL)
11b7d895
MP
422 return -EINVAL;
423
aa1b9b48 424 ret = therm->fan_set(therm, value);
11b7d895
MP
425 if (ret)
426 return ret;
427
428 return count;
429}
430
c9cbf135
MP
431static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR,
432 nouveau_hwmon_get_pwm1,
433 nouveau_hwmon_set_pwm1, 0);
11b7d895
MP
434
435static ssize_t
c9cbf135 436nouveau_hwmon_get_pwm1_min(struct device *d,
11b7d895
MP
437 struct device_attribute *a, char *buf)
438{
439 struct drm_device *dev = dev_get_drvdata(d);
aa1b9b48 440 struct nouveau_drm *drm = nouveau_drm(dev);
be83cd4e 441 struct nvkm_therm *therm = nvxx_therm(&drm->device);
aa1b9b48
MP
442 int ret;
443
e1404611 444 ret = therm->attr_get(therm, NVKM_THERM_ATTR_FAN_MIN_DUTY);
aa1b9b48
MP
445 if (ret < 0)
446 return ret;
11b7d895 447
aa1b9b48 448 return sprintf(buf, "%i\n", ret);
11b7d895
MP
449}
450
451static ssize_t
c9cbf135 452nouveau_hwmon_set_pwm1_min(struct device *d, struct device_attribute *a,
11b7d895
MP
453 const char *buf, size_t count)
454{
455 struct drm_device *dev = dev_get_drvdata(d);
aa1b9b48 456 struct nouveau_drm *drm = nouveau_drm(dev);
be83cd4e 457 struct nvkm_therm *therm = nvxx_therm(&drm->device);
11b7d895 458 long value;
aa1b9b48 459 int ret;
11b7d895 460
ddb20055 461 if (kstrtol(buf, 10, &value) == -EINVAL)
11b7d895
MP
462 return -EINVAL;
463
e1404611 464 ret = therm->attr_set(therm, NVKM_THERM_ATTR_FAN_MIN_DUTY, value);
aa1b9b48
MP
465 if (ret < 0)
466 return ret;
11b7d895
MP
467
468 return count;
469}
470
c9cbf135
MP
471static SENSOR_DEVICE_ATTR(pwm1_min, S_IRUGO | S_IWUSR,
472 nouveau_hwmon_get_pwm1_min,
473 nouveau_hwmon_set_pwm1_min, 0);
11b7d895
MP
474
475static ssize_t
c9cbf135 476nouveau_hwmon_get_pwm1_max(struct device *d,
11b7d895
MP
477 struct device_attribute *a, char *buf)
478{
479 struct drm_device *dev = dev_get_drvdata(d);
aa1b9b48 480 struct nouveau_drm *drm = nouveau_drm(dev);
be83cd4e 481 struct nvkm_therm *therm = nvxx_therm(&drm->device);
aa1b9b48 482 int ret;
11b7d895 483
e1404611 484 ret = therm->attr_get(therm, NVKM_THERM_ATTR_FAN_MAX_DUTY);
aa1b9b48
MP
485 if (ret < 0)
486 return ret;
11b7d895 487
aa1b9b48 488 return sprintf(buf, "%i\n", ret);
11b7d895
MP
489}
490
491static ssize_t
c9cbf135 492nouveau_hwmon_set_pwm1_max(struct device *d, struct device_attribute *a,
11b7d895
MP
493 const char *buf, size_t count)
494{
495 struct drm_device *dev = dev_get_drvdata(d);
aa1b9b48 496 struct nouveau_drm *drm = nouveau_drm(dev);
be83cd4e 497 struct nvkm_therm *therm = nvxx_therm(&drm->device);
11b7d895 498 long value;
aa1b9b48 499 int ret;
11b7d895 500
ddb20055 501 if (kstrtol(buf, 10, &value) == -EINVAL)
11b7d895
MP
502 return -EINVAL;
503
e1404611 504 ret = therm->attr_set(therm, NVKM_THERM_ATTR_FAN_MAX_DUTY, value);
aa1b9b48
MP
505 if (ret < 0)
506 return ret;
11b7d895
MP
507
508 return count;
509}
510
c9cbf135
MP
511static SENSOR_DEVICE_ATTR(pwm1_max, S_IRUGO | S_IWUSR,
512 nouveau_hwmon_get_pwm1_max,
513 nouveau_hwmon_set_pwm1_max, 0);
11b7d895 514
804ca90f
MP
515static struct attribute *hwmon_default_attributes[] = {
516 &sensor_dev_attr_name.dev_attr.attr,
517 &sensor_dev_attr_update_rate.dev_attr.attr,
518 NULL
519};
520static struct attribute *hwmon_temp_attributes[] = {
34e9d85a 521 &sensor_dev_attr_temp1_input.dev_attr.attr,
12e32896
MP
522 &sensor_dev_attr_temp1_auto_point1_pwm.dev_attr.attr,
523 &sensor_dev_attr_temp1_auto_point1_temp.dev_attr.attr,
524 &sensor_dev_attr_temp1_auto_point1_temp_hyst.dev_attr.attr,
34e9d85a 525 &sensor_dev_attr_temp1_max.dev_attr.attr,
12e32896 526 &sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
34e9d85a 527 &sensor_dev_attr_temp1_crit.dev_attr.attr,
12e32896
MP
528 &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr,
529 &sensor_dev_attr_temp1_emergency.dev_attr.attr,
530 &sensor_dev_attr_temp1_emergency_hyst.dev_attr.attr,
34e9d85a
MP
531 NULL
532};
11b7d895 533static struct attribute *hwmon_fan_rpm_attributes[] = {
b2c36312 534 &sensor_dev_attr_fan1_input.dev_attr.attr,
11b7d895
MP
535 NULL
536};
537static struct attribute *hwmon_pwm_fan_attributes[] = {
2f951a5d 538 &sensor_dev_attr_pwm1_enable.dev_attr.attr,
c9cbf135
MP
539 &sensor_dev_attr_pwm1.dev_attr.attr,
540 &sensor_dev_attr_pwm1_min.dev_attr.attr,
541 &sensor_dev_attr_pwm1_max.dev_attr.attr,
11b7d895
MP
542 NULL
543};
34e9d85a 544
804ca90f
MP
545static const struct attribute_group hwmon_default_attrgroup = {
546 .attrs = hwmon_default_attributes,
547};
548static const struct attribute_group hwmon_temp_attrgroup = {
549 .attrs = hwmon_temp_attributes,
34e9d85a 550};
11b7d895
MP
551static const struct attribute_group hwmon_fan_rpm_attrgroup = {
552 .attrs = hwmon_fan_rpm_attributes,
553};
554static const struct attribute_group hwmon_pwm_fan_attrgroup = {
555 .attrs = hwmon_pwm_fan_attributes,
556};
b54262f3 557#endif
34e9d85a 558
b9ed919f 559int
34e9d85a
MP
560nouveau_hwmon_init(struct drm_device *dev)
561{
095f979a 562#if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE))
57cdf82c 563 struct nouveau_drm *drm = nouveau_drm(dev);
be83cd4e 564 struct nvkm_therm *therm = nvxx_therm(&drm->device);
b9ed919f 565 struct nouveau_hwmon *hwmon;
34e9d85a 566 struct device *hwmon_dev;
11b7d895 567 int ret = 0;
34e9d85a 568
b9ed919f
BS
569 hwmon = drm->hwmon = kzalloc(sizeof(*hwmon), GFP_KERNEL);
570 if (!hwmon)
571 return -ENOMEM;
572 hwmon->dev = dev;
573
57113c01 574 if (!therm || !therm->attr_get || !therm->attr_set)
8155cac4 575 return -ENODEV;
34e9d85a
MP
576
577 hwmon_dev = hwmon_device_register(&dev->pdev->dev);
578 if (IS_ERR(hwmon_dev)) {
579 ret = PTR_ERR(hwmon_dev);
77145f1c 580 NV_ERROR(drm, "Unable to register hwmon device: %d\n", ret);
34e9d85a
MP
581 return ret;
582 }
583 dev_set_drvdata(hwmon_dev, dev);
11b7d895 584
804ca90f
MP
585 /* set the default attributes */
586 ret = sysfs_create_group(&hwmon_dev->kobj, &hwmon_default_attrgroup);
aa34efed
DC
587 if (ret)
588 goto error;
11b7d895 589
804ca90f 590 /* if the card has a working thermal sensor */
57113c01 591 if (nvkm_therm_temp_get(therm) >= 0) {
804ca90f 592 ret = sysfs_create_group(&hwmon_dev->kobj, &hwmon_temp_attrgroup);
aa34efed
DC
593 if (ret)
594 goto error;
804ca90f
MP
595 }
596
11b7d895
MP
597 /* if the card has a pwm fan */
598 /*XXX: incorrect, need better detection for this, some boards have
599 * the gpio entries for pwm fan control even when there's no
600 * actual fan connected to it... therm table? */
aa1b9b48 601 if (therm->fan_get && therm->fan_get(therm) >= 0) {
5e90a88c 602 ret = sysfs_create_group(&hwmon_dev->kobj,
11b7d895
MP
603 &hwmon_pwm_fan_attrgroup);
604 if (ret)
605 goto error;
606 }
607
608 /* if the card can read the fan rpm */
57113c01 609 if (nvkm_therm_fan_sense(therm) >= 0) {
5e90a88c 610 ret = sysfs_create_group(&hwmon_dev->kobj,
11b7d895
MP
611 &hwmon_fan_rpm_attrgroup);
612 if (ret)
613 goto error;
34e9d85a
MP
614 }
615
b9ed919f 616 hwmon->hwmon = hwmon_dev;
11b7d895 617
34e9d85a 618 return 0;
11b7d895
MP
619
620error:
77145f1c 621 NV_ERROR(drm, "Unable to create some hwmon sysfs files: %d\n", ret);
11b7d895 622 hwmon_device_unregister(hwmon_dev);
b9ed919f 623 hwmon->hwmon = NULL;
11b7d895
MP
624 return ret;
625#else
11b7d895
MP
626 return 0;
627#endif
34e9d85a
MP
628}
629
b9ed919f 630void
34e9d85a
MP
631nouveau_hwmon_fini(struct drm_device *dev)
632{
658e86ee 633#if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE))
b9ed919f 634 struct nouveau_hwmon *hwmon = nouveau_hwmon(dev);
34e9d85a 635
b9ed919f
BS
636 if (hwmon->hwmon) {
637 sysfs_remove_group(&hwmon->hwmon->kobj, &hwmon_default_attrgroup);
638 sysfs_remove_group(&hwmon->hwmon->kobj, &hwmon_temp_attrgroup);
639 sysfs_remove_group(&hwmon->hwmon->kobj, &hwmon_pwm_fan_attrgroup);
640 sysfs_remove_group(&hwmon->hwmon->kobj, &hwmon_fan_rpm_attrgroup);
11b7d895 641
b9ed919f 642 hwmon_device_unregister(hwmon->hwmon);
34e9d85a 643 }
6032649d 644
b9ed919f
BS
645 nouveau_drm(dev)->hwmon = NULL;
646 kfree(hwmon);
6032649d 647#endif
64f1c11a 648}