xref: /linux/drivers/gpu/drm/nouveau/nouveau_hwmon.c (revision ca55b2fef3a9373fcfc30f82fd26bc7fccbda732)
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))
38 static ssize_t
39 nouveau_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 = nvkm_therm_temp_get(therm);
45 
46 	if (temp < 0)
47 		return temp;
48 
49 	return snprintf(buf, PAGE_SIZE, "%d\n", temp * 1000);
50 }
51 static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, nouveau_hwmon_show_temp,
52 						  NULL, 0);
53 
54 static ssize_t
55 nouveau_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 }
60 static SENSOR_DEVICE_ATTR(temp1_auto_point1_pwm, S_IRUGO,
61 			  nouveau_hwmon_show_temp1_auto_point1_pwm, NULL, 0);
62 
63 static ssize_t
64 nouveau_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 }
74 static ssize_t
75 nouveau_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 }
92 static 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 
96 static ssize_t
97 nouveau_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 }
107 static ssize_t
108 nouveau_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 }
125 static 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 
129 static ssize_t
130 nouveau_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 }
139 static ssize_t
140 nouveau_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 }
155 static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR, nouveau_hwmon_max_temp,
156 						  nouveau_hwmon_set_max_temp,
157 						  0);
158 
159 static ssize_t
160 nouveau_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 }
170 static ssize_t
171 nouveau_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 }
187 static 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 
191 static ssize_t
192 nouveau_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 }
202 static ssize_t
203 nouveau_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 }
219 static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO | S_IWUSR,
220 						nouveau_hwmon_critical_temp,
221 						nouveau_hwmon_set_critical_temp,
222 						0);
223 
224 static ssize_t
225 nouveau_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 }
235 static ssize_t
236 nouveau_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 }
254 static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO | S_IWUSR,
255 			  nouveau_hwmon_critical_temp_hyst,
256 			  nouveau_hwmon_set_critical_temp_hyst, 0);
257 static ssize_t
258 nouveau_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 }
268 static ssize_t
269 nouveau_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 }
285 static SENSOR_DEVICE_ATTR(temp1_emergency, S_IRUGO | S_IWUSR,
286 					nouveau_hwmon_emergency_temp,
287 					nouveau_hwmon_set_emergency_temp,
288 					0);
289 
290 static ssize_t
291 nouveau_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 }
301 static ssize_t
302 nouveau_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 }
320 static 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 
325 static 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 }
331 static SENSOR_DEVICE_ATTR(name, S_IRUGO, nouveau_hwmon_show_name, NULL, 0);
332 
333 static 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 }
339 static SENSOR_DEVICE_ATTR(update_rate, S_IRUGO,
340 						nouveau_hwmon_show_update_rate,
341 						NULL, 0);
342 
343 static ssize_t
344 nouveau_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", nvkm_therm_fan_sense(therm));
352 }
353 static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, nouveau_hwmon_show_fan1_input,
354 			  NULL, 0);
355 
356  static ssize_t
357 nouveau_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 
372 static ssize_t
373 nouveau_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 }
392 static SENSOR_DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR,
393 			  nouveau_hwmon_get_pwm1_enable,
394 			  nouveau_hwmon_set_pwm1_enable, 0);
395 
396 static ssize_t
397 nouveau_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 
411 static ssize_t
412 nouveau_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 
431 static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR,
432 			  nouveau_hwmon_get_pwm1,
433 			  nouveau_hwmon_set_pwm1, 0);
434 
435 static ssize_t
436 nouveau_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 
451 static ssize_t
452 nouveau_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 
471 static SENSOR_DEVICE_ATTR(pwm1_min, S_IRUGO | S_IWUSR,
472 			  nouveau_hwmon_get_pwm1_min,
473 			  nouveau_hwmon_set_pwm1_min, 0);
474 
475 static ssize_t
476 nouveau_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 
491 static ssize_t
492 nouveau_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 
511 static SENSOR_DEVICE_ATTR(pwm1_max, S_IRUGO | S_IWUSR,
512 			  nouveau_hwmon_get_pwm1_max,
513 			  nouveau_hwmon_set_pwm1_max, 0);
514 
515 static 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 };
520 static 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 };
533 static struct attribute *hwmon_fan_rpm_attributes[] = {
534 	&sensor_dev_attr_fan1_input.dev_attr.attr,
535 	NULL
536 };
537 static 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 
545 static const struct attribute_group hwmon_default_attrgroup = {
546 	.attrs = hwmon_default_attributes,
547 };
548 static const struct attribute_group hwmon_temp_attrgroup = {
549 	.attrs = hwmon_temp_attributes,
550 };
551 static const struct attribute_group hwmon_fan_rpm_attrgroup = {
552 	.attrs = hwmon_fan_rpm_attributes,
553 };
554 static const struct attribute_group hwmon_pwm_fan_attrgroup = {
555 	.attrs = hwmon_pwm_fan_attributes,
556 };
557 #endif
558 
559 int
560 nouveau_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->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 (nvkm_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 (nvkm_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 
620 error:
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 
630 void
631 nouveau_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