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