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