xref: /netbsd-src/sys/external/bsd/drm2/dist/drm/nouveau/nouveau_hwmon.c (revision d909946ca08dceb44d7d0f22ec9488679695d976)
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))
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