1/* $NetBSD: nouveau_hwmon.c,v 1.1.1.2 2014/08/06 12:36:23 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.1.1.2 2014/08/06 12:36:23 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#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))
47static ssize_t
48nouveau_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}
60static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, nouveau_hwmon_show_temp,
61 NULL, 0);
62
63static ssize_t
64nouveau_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}
69static SENSOR_DEVICE_ATTR(temp1_auto_point1_pwm, S_IRUGO,
70 nouveau_hwmon_show_temp1_auto_point1_pwm, NULL, 0);
71
72static ssize_t
73nouveau_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}
83static ssize_t
84nouveau_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}
101static 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
105static ssize_t
106nouveau_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}
116static ssize_t
117nouveau_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}
134static 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
138static ssize_t
139nouveau_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}
148static ssize_t
149nouveau_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}
164static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR, nouveau_hwmon_max_temp,
165 nouveau_hwmon_set_max_temp,
166 0);
167
168static ssize_t
169nouveau_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}
179static ssize_t
180nouveau_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}
196static 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
200static ssize_t
201nouveau_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}
211static ssize_t
212nouveau_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}
228static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO | S_IWUSR,
229 nouveau_hwmon_critical_temp,
230 nouveau_hwmon_set_critical_temp,
231 0);
232
233static ssize_t
234nouveau_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}
244static ssize_t
245nouveau_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}
263static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO | S_IWUSR,
264 nouveau_hwmon_critical_temp_hyst,
265 nouveau_hwmon_set_critical_temp_hyst, 0);
266static ssize_t
267nouveau_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}
277static ssize_t
278nouveau_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}
294static SENSOR_DEVICE_ATTR(temp1_emergency, S_IRUGO | S_IWUSR,
295 nouveau_hwmon_emergency_temp,
296 nouveau_hwmon_set_emergency_temp,
297 0);
298
299static ssize_t
300nouveau_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}
310static ssize_t
311nouveau_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}
329static 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
334static 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}
340static SENSOR_DEVICE_ATTR(name, S_IRUGO, nouveau_hwmon_show_name, NULL, 0);
341
342static 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}
348static SENSOR_DEVICE_ATTR(update_rate, S_IRUGO,
349 nouveau_hwmon_show_update_rate,
350 NULL, 0);
351
352static ssize_t
353nouveau_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}
362static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, nouveau_hwmon_show_fan1_input,
363 NULL, 0);
364
365 static ssize_t
366nouveau_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
381static ssize_t
382nouveau_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}
401static SENSOR_DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR,
402 nouveau_hwmon_get_pwm1_enable,
403 nouveau_hwmon_set_pwm1_enable, 0);
404
405static ssize_t
406nouveau_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
420static ssize_t
421nouveau_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
440static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR,
441 nouveau_hwmon_get_pwm1,
442 nouveau_hwmon_set_pwm1, 0);
443
444static ssize_t
445nouveau_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
460static ssize_t
461nouveau_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
480static SENSOR_DEVICE_ATTR(pwm1_min, S_IRUGO | S_IWUSR,
481 nouveau_hwmon_get_pwm1_min,
482 nouveau_hwmon_set_pwm1_min, 0);
483
484static ssize_t
485nouveau_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
500static ssize_t
501nouveau_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
520static SENSOR_DEVICE_ATTR(pwm1_max, S_IRUGO | S_IWUSR,
521 nouveau_hwmon_get_pwm1_max,
522 nouveau_hwmon_set_pwm1_max, 0);
523
524static 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};
529static 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};
542static struct attribute *hwmon_fan_rpm_attributes[] = {
543 &sensor_dev_attr_fan1_input.dev_attr.attr,
544 NULL
545};
546static 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
554static const struct attribute_group hwmon_default_attrgroup = {
555 .attrs = hwmon_default_attributes,
556};
557static const struct attribute_group hwmon_temp_attrgroup = {
558 .attrs = hwmon_temp_attributes,
559};
560static const struct attribute_group hwmon_fan_rpm_attrgroup = {
561 .attrs = hwmon_fan_rpm_attributes,
562};
563static const struct attribute_group hwmon_pwm_fan_attrgroup = {
564 .attrs = hwmon_pwm_fan_attributes,
565};
566#endif
567
568int
569nouveau_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
629error:
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
639void
640nouveau_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