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
25#ifdef CONFIG_ACPI
26#include <linux/acpi.h>
27#endif
28#include <linux/power_supply.h>
29#include <linux/hwmon.h>
30#include <linux/hwmon-sysfs.h>
31
32#include <drm/drmP.h>
33
34#include "nouveau_drm.h"
35#include "nouveau_hwmon.h"
36
37#if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE))
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);
42	struct nouveau_drm *drm = nouveau_drm(dev);
43	struct nvkm_therm *therm = nvxx_therm(&drm->device);
44	int temp = therm->temp_get(therm);
45
46	if (temp < 0)
47		return temp;
48
49	return snprintf(buf, PAGE_SIZE, "%d\n", temp * 1000);
50}
51static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, nouveau_hwmon_show_temp,
52						  NULL, 0);
53
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);
69	struct nvkm_therm *therm = nvxx_therm(&drm->device);
70
71	return snprintf(buf, PAGE_SIZE, "%d\n",
72	      therm->attr_get(therm, NVKM_THERM_ATTR_THRS_FAN_BOOST) * 1000);
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);
81	struct nvkm_therm *therm = nvxx_therm(&drm->device);
82	long value;
83
84	if (kstrtol(buf, 10, &value) == -EINVAL)
85		return count;
86
87	therm->attr_set(therm, NVKM_THERM_ATTR_THRS_FAN_BOOST,
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);
102	struct nvkm_therm *therm = nvxx_therm(&drm->device);
103
104	return snprintf(buf, PAGE_SIZE, "%d\n",
105	 therm->attr_get(therm, NVKM_THERM_ATTR_THRS_FAN_BOOST_HYST) * 1000);
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);
114	struct nvkm_therm *therm = nvxx_therm(&drm->device);
115	long value;
116
117	if (kstrtol(buf, 10, &value) == -EINVAL)
118		return count;
119
120	therm->attr_set(therm, NVKM_THERM_ATTR_THRS_FAN_BOOST_HYST,
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
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);
133	struct nouveau_drm *drm = nouveau_drm(dev);
134	struct nvkm_therm *therm = nvxx_therm(&drm->device);
135
136	return snprintf(buf, PAGE_SIZE, "%d\n",
137	       therm->attr_get(therm, NVKM_THERM_ATTR_THRS_DOWN_CLK) * 1000);
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);
144	struct nouveau_drm *drm = nouveau_drm(dev);
145	struct nvkm_therm *therm = nvxx_therm(&drm->device);
146	long value;
147
148	if (kstrtol(buf, 10, &value) == -EINVAL)
149		return count;
150
151	therm->attr_set(therm, NVKM_THERM_ATTR_THRS_DOWN_CLK, value / 1000);
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
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);
165	struct nvkm_therm *therm = nvxx_therm(&drm->device);
166
167	return snprintf(buf, PAGE_SIZE, "%d\n",
168	  therm->attr_get(therm, NVKM_THERM_ATTR_THRS_DOWN_CLK_HYST) * 1000);
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);
176	struct nvkm_therm *therm = nvxx_therm(&drm->device);
177	long value;
178
179	if (kstrtol(buf, 10, &value) == -EINVAL)
180		return count;
181
182	therm->attr_set(therm, NVKM_THERM_ATTR_THRS_DOWN_CLK_HYST,
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
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);
196	struct nouveau_drm *drm = nouveau_drm(dev);
197	struct nvkm_therm *therm = nvxx_therm(&drm->device);
198
199	return snprintf(buf, PAGE_SIZE, "%d\n",
200	       therm->attr_get(therm, NVKM_THERM_ATTR_THRS_CRITICAL) * 1000);
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);
208	struct nouveau_drm *drm = nouveau_drm(dev);
209	struct nvkm_therm *therm = nvxx_therm(&drm->device);
210	long value;
211
212	if (kstrtol(buf, 10, &value) == -EINVAL)
213		return count;
214
215	therm->attr_set(therm, NVKM_THERM_ATTR_THRS_CRITICAL, value / 1000);
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
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);
230	struct nvkm_therm *therm = nvxx_therm(&drm->device);
231
232	return snprintf(buf, PAGE_SIZE, "%d\n",
233	  therm->attr_get(therm, NVKM_THERM_ATTR_THRS_CRITICAL_HYST) * 1000);
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);
243	struct nvkm_therm *therm = nvxx_therm(&drm->device);
244	long value;
245
246	if (kstrtol(buf, 10, &value) == -EINVAL)
247		return count;
248
249	therm->attr_set(therm, NVKM_THERM_ATTR_THRS_CRITICAL_HYST,
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);
263	struct nvkm_therm *therm = nvxx_therm(&drm->device);
264
265	return snprintf(buf, PAGE_SIZE, "%d\n",
266	       therm->attr_get(therm, NVKM_THERM_ATTR_THRS_SHUTDOWN) * 1000);
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);
275	struct nvkm_therm *therm = nvxx_therm(&drm->device);
276	long value;
277
278	if (kstrtol(buf, 10, &value) == -EINVAL)
279		return count;
280
281	therm->attr_set(therm, NVKM_THERM_ATTR_THRS_SHUTDOWN, value / 1000);
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);
296	struct nvkm_therm *therm = nvxx_therm(&drm->device);
297
298	return snprintf(buf, PAGE_SIZE, "%d\n",
299	  therm->attr_get(therm, NVKM_THERM_ATTR_THRS_SHUTDOWN_HYST) * 1000);
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);
309	struct nvkm_therm *therm = nvxx_therm(&drm->device);
310	long value;
311
312	if (kstrtol(buf, 10, &value) == -EINVAL)
313		return count;
314
315	therm->attr_set(therm, NVKM_THERM_ATTR_THRS_SHUTDOWN_HYST,
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
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
343static ssize_t
344nouveau_hwmon_show_fan1_input(struct device *d, struct device_attribute *attr,
345			      char *buf)
346{
347	struct drm_device *dev = dev_get_drvdata(d);
348	struct nouveau_drm *drm = nouveau_drm(dev);
349	struct nvkm_therm *therm = nvxx_therm(&drm->device);
350
351	return snprintf(buf, PAGE_SIZE, "%d\n", therm->fan_sense(therm));
352}
353static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, nouveau_hwmon_show_fan1_input,
354			  NULL, 0);
355
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);
362	struct nvkm_therm *therm = nvxx_therm(&drm->device);
363	int ret;
364
365	ret = therm->attr_get(therm, NVKM_THERM_ATTR_FAN_MODE);
366	if (ret < 0)
367		return ret;
368
369	return sprintf(buf, "%i\n", ret);
370}
371
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);
378	struct nvkm_therm *therm = nvxx_therm(&drm->device);
379	long value;
380	int ret;
381
382	ret = kstrtol(buf, 10, &value);
383	if (ret)
384		return ret;
385
386	ret = therm->attr_set(therm, NVKM_THERM_ATTR_FAN_MODE, value);
387	if (ret)
388		return ret;
389	else
390		return count;
391}
392static SENSOR_DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR,
393			  nouveau_hwmon_get_pwm1_enable,
394			  nouveau_hwmon_set_pwm1_enable, 0);
395
396static ssize_t
397nouveau_hwmon_get_pwm1(struct device *d, struct device_attribute *a, char *buf)
398{
399	struct drm_device *dev = dev_get_drvdata(d);
400	struct nouveau_drm *drm = nouveau_drm(dev);
401	struct nvkm_therm *therm = nvxx_therm(&drm->device);
402	int ret;
403
404	ret = therm->fan_get(therm);
405	if (ret < 0)
406		return ret;
407
408	return sprintf(buf, "%i\n", ret);
409}
410
411static ssize_t
412nouveau_hwmon_set_pwm1(struct device *d, struct device_attribute *a,
413		       const char *buf, size_t count)
414{
415	struct drm_device *dev = dev_get_drvdata(d);
416	struct nouveau_drm *drm = nouveau_drm(dev);
417	struct nvkm_therm *therm = nvxx_therm(&drm->device);
418	int ret = -ENODEV;
419	long value;
420
421	if (kstrtol(buf, 10, &value) == -EINVAL)
422		return -EINVAL;
423
424	ret = therm->fan_set(therm, value);
425	if (ret)
426		return ret;
427
428	return count;
429}
430
431static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR,
432			  nouveau_hwmon_get_pwm1,
433			  nouveau_hwmon_set_pwm1, 0);
434
435static ssize_t
436nouveau_hwmon_get_pwm1_min(struct device *d,
437			   struct device_attribute *a, char *buf)
438{
439	struct drm_device *dev = dev_get_drvdata(d);
440	struct nouveau_drm *drm = nouveau_drm(dev);
441	struct nvkm_therm *therm = nvxx_therm(&drm->device);
442	int ret;
443
444	ret = therm->attr_get(therm, NVKM_THERM_ATTR_FAN_MIN_DUTY);
445	if (ret < 0)
446		return ret;
447
448	return sprintf(buf, "%i\n", ret);
449}
450
451static ssize_t
452nouveau_hwmon_set_pwm1_min(struct device *d, struct device_attribute *a,
453			   const char *buf, size_t count)
454{
455	struct drm_device *dev = dev_get_drvdata(d);
456	struct nouveau_drm *drm = nouveau_drm(dev);
457	struct nvkm_therm *therm = nvxx_therm(&drm->device);
458	long value;
459	int ret;
460
461	if (kstrtol(buf, 10, &value) == -EINVAL)
462		return -EINVAL;
463
464	ret = therm->attr_set(therm, NVKM_THERM_ATTR_FAN_MIN_DUTY, value);
465	if (ret < 0)
466		return ret;
467
468	return count;
469}
470
471static SENSOR_DEVICE_ATTR(pwm1_min, S_IRUGO | S_IWUSR,
472			  nouveau_hwmon_get_pwm1_min,
473			  nouveau_hwmon_set_pwm1_min, 0);
474
475static ssize_t
476nouveau_hwmon_get_pwm1_max(struct device *d,
477			   struct device_attribute *a, char *buf)
478{
479	struct drm_device *dev = dev_get_drvdata(d);
480	struct nouveau_drm *drm = nouveau_drm(dev);
481	struct nvkm_therm *therm = nvxx_therm(&drm->device);
482	int ret;
483
484	ret = therm->attr_get(therm, NVKM_THERM_ATTR_FAN_MAX_DUTY);
485	if (ret < 0)
486		return ret;
487
488	return sprintf(buf, "%i\n", ret);
489}
490
491static ssize_t
492nouveau_hwmon_set_pwm1_max(struct device *d, struct device_attribute *a,
493			   const char *buf, size_t count)
494{
495	struct drm_device *dev = dev_get_drvdata(d);
496	struct nouveau_drm *drm = nouveau_drm(dev);
497	struct nvkm_therm *therm = nvxx_therm(&drm->device);
498	long value;
499	int ret;
500
501	if (kstrtol(buf, 10, &value) == -EINVAL)
502		return -EINVAL;
503
504	ret = therm->attr_set(therm, NVKM_THERM_ATTR_FAN_MAX_DUTY, value);
505	if (ret < 0)
506		return ret;
507
508	return count;
509}
510
511static SENSOR_DEVICE_ATTR(pwm1_max, S_IRUGO | S_IWUSR,
512			  nouveau_hwmon_get_pwm1_max,
513			  nouveau_hwmon_set_pwm1_max, 0);
514
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[] = {
521	&sensor_dev_attr_temp1_input.dev_attr.attr,
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,
525	&sensor_dev_attr_temp1_max.dev_attr.attr,
526	&sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
527	&sensor_dev_attr_temp1_crit.dev_attr.attr,
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,
531	NULL
532};
533static struct attribute *hwmon_fan_rpm_attributes[] = {
534	&sensor_dev_attr_fan1_input.dev_attr.attr,
535	NULL
536};
537static struct attribute *hwmon_pwm_fan_attributes[] = {
538	&sensor_dev_attr_pwm1_enable.dev_attr.attr,
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,
542	NULL
543};
544
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,
550};
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};
557#endif
558
559int
560nouveau_hwmon_init(struct drm_device *dev)
561{
562#if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE))
563	struct nouveau_drm *drm = nouveau_drm(dev);
564	struct nvkm_therm *therm = nvxx_therm(&drm->device);
565	struct nouveau_hwmon *hwmon;
566	struct device *hwmon_dev;
567	int ret = 0;
568
569	hwmon = drm->hwmon = kzalloc(sizeof(*hwmon), GFP_KERNEL);
570	if (!hwmon)
571		return -ENOMEM;
572	hwmon->dev = dev;
573
574	if (!therm || !therm->temp_get || !therm->attr_get || !therm->attr_set)
575		return -ENODEV;
576
577	hwmon_dev = hwmon_device_register(&dev->pdev->dev);
578	if (IS_ERR(hwmon_dev)) {
579		ret = PTR_ERR(hwmon_dev);
580		NV_ERROR(drm, "Unable to register hwmon device: %d\n", ret);
581		return ret;
582	}
583	dev_set_drvdata(hwmon_dev, dev);
584
585	/* set the default attributes */
586	ret = sysfs_create_group(&hwmon_dev->kobj, &hwmon_default_attrgroup);
587	if (ret)
588		goto error;
589
590	/* if the card has a working thermal sensor */
591	if (therm->temp_get(therm) >= 0) {
592		ret = sysfs_create_group(&hwmon_dev->kobj, &hwmon_temp_attrgroup);
593		if (ret)
594			goto error;
595	}
596
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? */
601	if (therm->fan_get && therm->fan_get(therm) >= 0) {
602		ret = sysfs_create_group(&hwmon_dev->kobj,
603					 &hwmon_pwm_fan_attrgroup);
604		if (ret)
605			goto error;
606	}
607
608	/* if the card can read the fan rpm */
609	if (therm->fan_sense(therm) >= 0) {
610		ret = sysfs_create_group(&hwmon_dev->kobj,
611					 &hwmon_fan_rpm_attrgroup);
612		if (ret)
613			goto error;
614	}
615
616	hwmon->hwmon = hwmon_dev;
617
618	return 0;
619
620error:
621	NV_ERROR(drm, "Unable to create some hwmon sysfs files: %d\n", ret);
622	hwmon_device_unregister(hwmon_dev);
623	hwmon->hwmon = NULL;
624	return ret;
625#else
626	return 0;
627#endif
628}
629
630void
631nouveau_hwmon_fini(struct drm_device *dev)
632{
633#if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE))
634	struct nouveau_hwmon *hwmon = nouveau_hwmon(dev);
635
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);
641
642		hwmon_device_unregister(hwmon->hwmon);
643	}
644
645	nouveau_drm(dev)->hwmon = NULL;
646	kfree(hwmon);
647#endif
648}
649