2 * Copyright 2010 Red Hat Inc.
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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.
26 #include <linux/acpi.h>
28 #include <linux/power_supply.h>
29 #include <linux/hwmon.h>
30 #include <linux/hwmon-sysfs.h>
34 #include "nouveau_drv.h"
35 #include "nouveau_hwmon.h"
37 #include <nvkm/subdev/iccsense.h>
38 #include <nvkm/subdev/volt.h>
40 #if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE))
42 nouveau_hwmon_show_temp(struct device
*d
, struct device_attribute
*a
, char *buf
)
44 struct drm_device
*dev
= dev_get_drvdata(d
);
45 struct nouveau_drm
*drm
= nouveau_drm(dev
);
46 struct nvkm_therm
*therm
= nvxx_therm(&drm
->device
);
47 int temp
= nvkm_therm_temp_get(therm
);
52 return snprintf(buf
, PAGE_SIZE
, "%d\n", temp
* 1000);
54 static SENSOR_DEVICE_ATTR(temp1_input
, S_IRUGO
, nouveau_hwmon_show_temp
,
58 nouveau_hwmon_show_temp1_auto_point1_pwm(struct device
*d
,
59 struct device_attribute
*a
, char *buf
)
61 return snprintf(buf
, PAGE_SIZE
, "%d\n", 100);
63 static SENSOR_DEVICE_ATTR(temp1_auto_point1_pwm
, S_IRUGO
,
64 nouveau_hwmon_show_temp1_auto_point1_pwm
, NULL
, 0);
67 nouveau_hwmon_temp1_auto_point1_temp(struct device
*d
,
68 struct device_attribute
*a
, char *buf
)
70 struct drm_device
*dev
= dev_get_drvdata(d
);
71 struct nouveau_drm
*drm
= nouveau_drm(dev
);
72 struct nvkm_therm
*therm
= nvxx_therm(&drm
->device
);
74 return snprintf(buf
, PAGE_SIZE
, "%d\n",
75 therm
->attr_get(therm
, NVKM_THERM_ATTR_THRS_FAN_BOOST
) * 1000);
78 nouveau_hwmon_set_temp1_auto_point1_temp(struct device
*d
,
79 struct device_attribute
*a
,
80 const char *buf
, size_t count
)
82 struct drm_device
*dev
= dev_get_drvdata(d
);
83 struct nouveau_drm
*drm
= nouveau_drm(dev
);
84 struct nvkm_therm
*therm
= nvxx_therm(&drm
->device
);
87 if (kstrtol(buf
, 10, &value
) == -EINVAL
)
90 therm
->attr_set(therm
, NVKM_THERM_ATTR_THRS_FAN_BOOST
,
95 static SENSOR_DEVICE_ATTR(temp1_auto_point1_temp
, S_IRUGO
| S_IWUSR
,
96 nouveau_hwmon_temp1_auto_point1_temp
,
97 nouveau_hwmon_set_temp1_auto_point1_temp
, 0);
100 nouveau_hwmon_temp1_auto_point1_temp_hyst(struct device
*d
,
101 struct device_attribute
*a
, char *buf
)
103 struct drm_device
*dev
= dev_get_drvdata(d
);
104 struct nouveau_drm
*drm
= nouveau_drm(dev
);
105 struct nvkm_therm
*therm
= nvxx_therm(&drm
->device
);
107 return snprintf(buf
, PAGE_SIZE
, "%d\n",
108 therm
->attr_get(therm
, NVKM_THERM_ATTR_THRS_FAN_BOOST_HYST
) * 1000);
111 nouveau_hwmon_set_temp1_auto_point1_temp_hyst(struct device
*d
,
112 struct device_attribute
*a
,
113 const char *buf
, size_t count
)
115 struct drm_device
*dev
= dev_get_drvdata(d
);
116 struct nouveau_drm
*drm
= nouveau_drm(dev
);
117 struct nvkm_therm
*therm
= nvxx_therm(&drm
->device
);
120 if (kstrtol(buf
, 10, &value
) == -EINVAL
)
123 therm
->attr_set(therm
, NVKM_THERM_ATTR_THRS_FAN_BOOST_HYST
,
128 static SENSOR_DEVICE_ATTR(temp1_auto_point1_temp_hyst
, S_IRUGO
| S_IWUSR
,
129 nouveau_hwmon_temp1_auto_point1_temp_hyst
,
130 nouveau_hwmon_set_temp1_auto_point1_temp_hyst
, 0);
133 nouveau_hwmon_max_temp(struct device
*d
, struct device_attribute
*a
, char *buf
)
135 struct drm_device
*dev
= dev_get_drvdata(d
);
136 struct nouveau_drm
*drm
= nouveau_drm(dev
);
137 struct nvkm_therm
*therm
= nvxx_therm(&drm
->device
);
139 return snprintf(buf
, PAGE_SIZE
, "%d\n",
140 therm
->attr_get(therm
, NVKM_THERM_ATTR_THRS_DOWN_CLK
) * 1000);
143 nouveau_hwmon_set_max_temp(struct device
*d
, struct device_attribute
*a
,
144 const char *buf
, size_t count
)
146 struct drm_device
*dev
= dev_get_drvdata(d
);
147 struct nouveau_drm
*drm
= nouveau_drm(dev
);
148 struct nvkm_therm
*therm
= nvxx_therm(&drm
->device
);
151 if (kstrtol(buf
, 10, &value
) == -EINVAL
)
154 therm
->attr_set(therm
, NVKM_THERM_ATTR_THRS_DOWN_CLK
, value
/ 1000);
158 static SENSOR_DEVICE_ATTR(temp1_max
, S_IRUGO
| S_IWUSR
, nouveau_hwmon_max_temp
,
159 nouveau_hwmon_set_max_temp
,
163 nouveau_hwmon_max_temp_hyst(struct device
*d
, struct device_attribute
*a
,
166 struct drm_device
*dev
= dev_get_drvdata(d
);
167 struct nouveau_drm
*drm
= nouveau_drm(dev
);
168 struct nvkm_therm
*therm
= nvxx_therm(&drm
->device
);
170 return snprintf(buf
, PAGE_SIZE
, "%d\n",
171 therm
->attr_get(therm
, NVKM_THERM_ATTR_THRS_DOWN_CLK_HYST
) * 1000);
174 nouveau_hwmon_set_max_temp_hyst(struct device
*d
, struct device_attribute
*a
,
175 const char *buf
, size_t count
)
177 struct drm_device
*dev
= dev_get_drvdata(d
);
178 struct nouveau_drm
*drm
= nouveau_drm(dev
);
179 struct nvkm_therm
*therm
= nvxx_therm(&drm
->device
);
182 if (kstrtol(buf
, 10, &value
) == -EINVAL
)
185 therm
->attr_set(therm
, NVKM_THERM_ATTR_THRS_DOWN_CLK_HYST
,
190 static SENSOR_DEVICE_ATTR(temp1_max_hyst
, S_IRUGO
| S_IWUSR
,
191 nouveau_hwmon_max_temp_hyst
,
192 nouveau_hwmon_set_max_temp_hyst
, 0);
195 nouveau_hwmon_critical_temp(struct device
*d
, struct device_attribute
*a
,
198 struct drm_device
*dev
= dev_get_drvdata(d
);
199 struct nouveau_drm
*drm
= nouveau_drm(dev
);
200 struct nvkm_therm
*therm
= nvxx_therm(&drm
->device
);
202 return snprintf(buf
, PAGE_SIZE
, "%d\n",
203 therm
->attr_get(therm
, NVKM_THERM_ATTR_THRS_CRITICAL
) * 1000);
206 nouveau_hwmon_set_critical_temp(struct device
*d
, struct device_attribute
*a
,
210 struct drm_device
*dev
= dev_get_drvdata(d
);
211 struct nouveau_drm
*drm
= nouveau_drm(dev
);
212 struct nvkm_therm
*therm
= nvxx_therm(&drm
->device
);
215 if (kstrtol(buf
, 10, &value
) == -EINVAL
)
218 therm
->attr_set(therm
, NVKM_THERM_ATTR_THRS_CRITICAL
, value
/ 1000);
222 static SENSOR_DEVICE_ATTR(temp1_crit
, S_IRUGO
| S_IWUSR
,
223 nouveau_hwmon_critical_temp
,
224 nouveau_hwmon_set_critical_temp
,
228 nouveau_hwmon_critical_temp_hyst(struct device
*d
, struct device_attribute
*a
,
231 struct drm_device
*dev
= dev_get_drvdata(d
);
232 struct nouveau_drm
*drm
= nouveau_drm(dev
);
233 struct nvkm_therm
*therm
= nvxx_therm(&drm
->device
);
235 return snprintf(buf
, PAGE_SIZE
, "%d\n",
236 therm
->attr_get(therm
, NVKM_THERM_ATTR_THRS_CRITICAL_HYST
) * 1000);
239 nouveau_hwmon_set_critical_temp_hyst(struct device
*d
,
240 struct device_attribute
*a
,
244 struct drm_device
*dev
= dev_get_drvdata(d
);
245 struct nouveau_drm
*drm
= nouveau_drm(dev
);
246 struct nvkm_therm
*therm
= nvxx_therm(&drm
->device
);
249 if (kstrtol(buf
, 10, &value
) == -EINVAL
)
252 therm
->attr_set(therm
, NVKM_THERM_ATTR_THRS_CRITICAL_HYST
,
257 static SENSOR_DEVICE_ATTR(temp1_crit_hyst
, S_IRUGO
| S_IWUSR
,
258 nouveau_hwmon_critical_temp_hyst
,
259 nouveau_hwmon_set_critical_temp_hyst
, 0);
261 nouveau_hwmon_emergency_temp(struct device
*d
, struct device_attribute
*a
,
264 struct drm_device
*dev
= dev_get_drvdata(d
);
265 struct nouveau_drm
*drm
= nouveau_drm(dev
);
266 struct nvkm_therm
*therm
= nvxx_therm(&drm
->device
);
268 return snprintf(buf
, PAGE_SIZE
, "%d\n",
269 therm
->attr_get(therm
, NVKM_THERM_ATTR_THRS_SHUTDOWN
) * 1000);
272 nouveau_hwmon_set_emergency_temp(struct device
*d
, struct device_attribute
*a
,
276 struct drm_device
*dev
= dev_get_drvdata(d
);
277 struct nouveau_drm
*drm
= nouveau_drm(dev
);
278 struct nvkm_therm
*therm
= nvxx_therm(&drm
->device
);
281 if (kstrtol(buf
, 10, &value
) == -EINVAL
)
284 therm
->attr_set(therm
, NVKM_THERM_ATTR_THRS_SHUTDOWN
, value
/ 1000);
288 static SENSOR_DEVICE_ATTR(temp1_emergency
, S_IRUGO
| S_IWUSR
,
289 nouveau_hwmon_emergency_temp
,
290 nouveau_hwmon_set_emergency_temp
,
294 nouveau_hwmon_emergency_temp_hyst(struct device
*d
, struct device_attribute
*a
,
297 struct drm_device
*dev
= dev_get_drvdata(d
);
298 struct nouveau_drm
*drm
= nouveau_drm(dev
);
299 struct nvkm_therm
*therm
= nvxx_therm(&drm
->device
);
301 return snprintf(buf
, PAGE_SIZE
, "%d\n",
302 therm
->attr_get(therm
, NVKM_THERM_ATTR_THRS_SHUTDOWN_HYST
) * 1000);
305 nouveau_hwmon_set_emergency_temp_hyst(struct device
*d
,
306 struct device_attribute
*a
,
310 struct drm_device
*dev
= dev_get_drvdata(d
);
311 struct nouveau_drm
*drm
= nouveau_drm(dev
);
312 struct nvkm_therm
*therm
= nvxx_therm(&drm
->device
);
315 if (kstrtol(buf
, 10, &value
) == -EINVAL
)
318 therm
->attr_set(therm
, NVKM_THERM_ATTR_THRS_SHUTDOWN_HYST
,
323 static SENSOR_DEVICE_ATTR(temp1_emergency_hyst
, S_IRUGO
| S_IWUSR
,
324 nouveau_hwmon_emergency_temp_hyst
,
325 nouveau_hwmon_set_emergency_temp_hyst
,
328 static ssize_t
nouveau_hwmon_show_name(struct device
*dev
,
329 struct device_attribute
*attr
,
332 return sprintf(buf
, "nouveau\n");
334 static SENSOR_DEVICE_ATTR(name
, S_IRUGO
, nouveau_hwmon_show_name
, NULL
, 0);
336 static ssize_t
nouveau_hwmon_show_update_rate(struct device
*dev
,
337 struct device_attribute
*attr
,
340 return sprintf(buf
, "1000\n");
342 static SENSOR_DEVICE_ATTR(update_rate
, S_IRUGO
,
343 nouveau_hwmon_show_update_rate
,
347 nouveau_hwmon_show_fan1_input(struct device
*d
, struct device_attribute
*attr
,
350 struct drm_device
*dev
= dev_get_drvdata(d
);
351 struct nouveau_drm
*drm
= nouveau_drm(dev
);
352 struct nvkm_therm
*therm
= nvxx_therm(&drm
->device
);
354 return snprintf(buf
, PAGE_SIZE
, "%d\n", nvkm_therm_fan_sense(therm
));
356 static SENSOR_DEVICE_ATTR(fan1_input
, S_IRUGO
, nouveau_hwmon_show_fan1_input
,
360 nouveau_hwmon_get_pwm1_enable(struct device
*d
,
361 struct device_attribute
*a
, char *buf
)
363 struct drm_device
*dev
= dev_get_drvdata(d
);
364 struct nouveau_drm
*drm
= nouveau_drm(dev
);
365 struct nvkm_therm
*therm
= nvxx_therm(&drm
->device
);
368 ret
= therm
->attr_get(therm
, NVKM_THERM_ATTR_FAN_MODE
);
372 return sprintf(buf
, "%i\n", ret
);
376 nouveau_hwmon_set_pwm1_enable(struct device
*d
, struct device_attribute
*a
,
377 const char *buf
, size_t count
)
379 struct drm_device
*dev
= dev_get_drvdata(d
);
380 struct nouveau_drm
*drm
= nouveau_drm(dev
);
381 struct nvkm_therm
*therm
= nvxx_therm(&drm
->device
);
385 ret
= kstrtol(buf
, 10, &value
);
389 ret
= therm
->attr_set(therm
, NVKM_THERM_ATTR_FAN_MODE
, value
);
395 static SENSOR_DEVICE_ATTR(pwm1_enable
, S_IRUGO
| S_IWUSR
,
396 nouveau_hwmon_get_pwm1_enable
,
397 nouveau_hwmon_set_pwm1_enable
, 0);
400 nouveau_hwmon_get_pwm1(struct device
*d
, struct device_attribute
*a
, char *buf
)
402 struct drm_device
*dev
= dev_get_drvdata(d
);
403 struct nouveau_drm
*drm
= nouveau_drm(dev
);
404 struct nvkm_therm
*therm
= nvxx_therm(&drm
->device
);
407 ret
= therm
->fan_get(therm
);
411 return sprintf(buf
, "%i\n", ret
);
415 nouveau_hwmon_set_pwm1(struct device
*d
, struct device_attribute
*a
,
416 const char *buf
, size_t count
)
418 struct drm_device
*dev
= dev_get_drvdata(d
);
419 struct nouveau_drm
*drm
= nouveau_drm(dev
);
420 struct nvkm_therm
*therm
= nvxx_therm(&drm
->device
);
424 if (kstrtol(buf
, 10, &value
) == -EINVAL
)
427 ret
= therm
->fan_set(therm
, value
);
434 static SENSOR_DEVICE_ATTR(pwm1
, S_IRUGO
| S_IWUSR
,
435 nouveau_hwmon_get_pwm1
,
436 nouveau_hwmon_set_pwm1
, 0);
439 nouveau_hwmon_get_pwm1_min(struct device
*d
,
440 struct device_attribute
*a
, char *buf
)
442 struct drm_device
*dev
= dev_get_drvdata(d
);
443 struct nouveau_drm
*drm
= nouveau_drm(dev
);
444 struct nvkm_therm
*therm
= nvxx_therm(&drm
->device
);
447 ret
= therm
->attr_get(therm
, NVKM_THERM_ATTR_FAN_MIN_DUTY
);
451 return sprintf(buf
, "%i\n", ret
);
455 nouveau_hwmon_set_pwm1_min(struct device
*d
, struct device_attribute
*a
,
456 const char *buf
, size_t count
)
458 struct drm_device
*dev
= dev_get_drvdata(d
);
459 struct nouveau_drm
*drm
= nouveau_drm(dev
);
460 struct nvkm_therm
*therm
= nvxx_therm(&drm
->device
);
464 if (kstrtol(buf
, 10, &value
) == -EINVAL
)
467 ret
= therm
->attr_set(therm
, NVKM_THERM_ATTR_FAN_MIN_DUTY
, value
);
474 static SENSOR_DEVICE_ATTR(pwm1_min
, S_IRUGO
| S_IWUSR
,
475 nouveau_hwmon_get_pwm1_min
,
476 nouveau_hwmon_set_pwm1_min
, 0);
479 nouveau_hwmon_get_pwm1_max(struct device
*d
,
480 struct device_attribute
*a
, char *buf
)
482 struct drm_device
*dev
= dev_get_drvdata(d
);
483 struct nouveau_drm
*drm
= nouveau_drm(dev
);
484 struct nvkm_therm
*therm
= nvxx_therm(&drm
->device
);
487 ret
= therm
->attr_get(therm
, NVKM_THERM_ATTR_FAN_MAX_DUTY
);
491 return sprintf(buf
, "%i\n", ret
);
495 nouveau_hwmon_set_pwm1_max(struct device
*d
, struct device_attribute
*a
,
496 const char *buf
, size_t count
)
498 struct drm_device
*dev
= dev_get_drvdata(d
);
499 struct nouveau_drm
*drm
= nouveau_drm(dev
);
500 struct nvkm_therm
*therm
= nvxx_therm(&drm
->device
);
504 if (kstrtol(buf
, 10, &value
) == -EINVAL
)
507 ret
= therm
->attr_set(therm
, NVKM_THERM_ATTR_FAN_MAX_DUTY
, value
);
514 static SENSOR_DEVICE_ATTR(pwm1_max
, S_IRUGO
| S_IWUSR
,
515 nouveau_hwmon_get_pwm1_max
,
516 nouveau_hwmon_set_pwm1_max
, 0);
519 nouveau_hwmon_get_in0_input(struct device
*d
,
520 struct device_attribute
*a
, char *buf
)
522 struct drm_device
*dev
= dev_get_drvdata(d
);
523 struct nouveau_drm
*drm
= nouveau_drm(dev
);
524 struct nvkm_volt
*volt
= nvxx_volt(&drm
->device
);
527 ret
= nvkm_volt_get(volt
);
531 return sprintf(buf
, "%i\n", ret
/ 1000);
534 static SENSOR_DEVICE_ATTR(in0_input
, S_IRUGO
,
535 nouveau_hwmon_get_in0_input
, NULL
, 0);
538 nouveau_hwmon_get_in0_min(struct device
*d
,
539 struct device_attribute
*a
, char *buf
)
541 struct drm_device
*dev
= dev_get_drvdata(d
);
542 struct nouveau_drm
*drm
= nouveau_drm(dev
);
543 struct nvkm_volt
*volt
= nvxx_volt(&drm
->device
);
545 if (!volt
|| !volt
->min_uv
)
548 return sprintf(buf
, "%i\n", volt
->min_uv
/ 1000);
551 static SENSOR_DEVICE_ATTR(in0_min
, S_IRUGO
,
552 nouveau_hwmon_get_in0_min
, NULL
, 0);
555 nouveau_hwmon_get_in0_max(struct device
*d
,
556 struct device_attribute
*a
, char *buf
)
558 struct drm_device
*dev
= dev_get_drvdata(d
);
559 struct nouveau_drm
*drm
= nouveau_drm(dev
);
560 struct nvkm_volt
*volt
= nvxx_volt(&drm
->device
);
562 if (!volt
|| !volt
->max_uv
)
565 return sprintf(buf
, "%i\n", volt
->max_uv
/ 1000);
568 static SENSOR_DEVICE_ATTR(in0_max
, S_IRUGO
,
569 nouveau_hwmon_get_in0_max
, NULL
, 0);
572 nouveau_hwmon_get_in0_label(struct device
*d
,
573 struct device_attribute
*a
, char *buf
)
575 return sprintf(buf
, "GPU core\n");
578 static SENSOR_DEVICE_ATTR(in0_label
, S_IRUGO
,
579 nouveau_hwmon_get_in0_label
, NULL
, 0);
582 nouveau_hwmon_get_power1_input(struct device
*d
, struct device_attribute
*a
,
585 struct drm_device
*dev
= dev_get_drvdata(d
);
586 struct nouveau_drm
*drm
= nouveau_drm(dev
);
587 struct nvkm_iccsense
*iccsense
= nvxx_iccsense(&drm
->device
);
588 int result
= nvkm_iccsense_read_all(iccsense
);
593 return sprintf(buf
, "%i\n", result
);
596 static SENSOR_DEVICE_ATTR(power1_input
, S_IRUGO
,
597 nouveau_hwmon_get_power1_input
, NULL
, 0);
599 static struct attribute
*hwmon_default_attributes
[] = {
600 &sensor_dev_attr_name
.dev_attr
.attr
,
601 &sensor_dev_attr_update_rate
.dev_attr
.attr
,
604 static struct attribute
*hwmon_temp_attributes
[] = {
605 &sensor_dev_attr_temp1_input
.dev_attr
.attr
,
606 &sensor_dev_attr_temp1_auto_point1_pwm
.dev_attr
.attr
,
607 &sensor_dev_attr_temp1_auto_point1_temp
.dev_attr
.attr
,
608 &sensor_dev_attr_temp1_auto_point1_temp_hyst
.dev_attr
.attr
,
609 &sensor_dev_attr_temp1_max
.dev_attr
.attr
,
610 &sensor_dev_attr_temp1_max_hyst
.dev_attr
.attr
,
611 &sensor_dev_attr_temp1_crit
.dev_attr
.attr
,
612 &sensor_dev_attr_temp1_crit_hyst
.dev_attr
.attr
,
613 &sensor_dev_attr_temp1_emergency
.dev_attr
.attr
,
614 &sensor_dev_attr_temp1_emergency_hyst
.dev_attr
.attr
,
617 static struct attribute
*hwmon_fan_rpm_attributes
[] = {
618 &sensor_dev_attr_fan1_input
.dev_attr
.attr
,
621 static struct attribute
*hwmon_pwm_fan_attributes
[] = {
622 &sensor_dev_attr_pwm1_enable
.dev_attr
.attr
,
623 &sensor_dev_attr_pwm1
.dev_attr
.attr
,
624 &sensor_dev_attr_pwm1_min
.dev_attr
.attr
,
625 &sensor_dev_attr_pwm1_max
.dev_attr
.attr
,
629 static struct attribute
*hwmon_in0_attributes
[] = {
630 &sensor_dev_attr_in0_input
.dev_attr
.attr
,
631 &sensor_dev_attr_in0_min
.dev_attr
.attr
,
632 &sensor_dev_attr_in0_max
.dev_attr
.attr
,
633 &sensor_dev_attr_in0_label
.dev_attr
.attr
,
637 static struct attribute
*hwmon_power_attributes
[] = {
638 &sensor_dev_attr_power1_input
.dev_attr
.attr
,
642 static const struct attribute_group hwmon_default_attrgroup
= {
643 .attrs
= hwmon_default_attributes
,
645 static const struct attribute_group hwmon_temp_attrgroup
= {
646 .attrs
= hwmon_temp_attributes
,
648 static const struct attribute_group hwmon_fan_rpm_attrgroup
= {
649 .attrs
= hwmon_fan_rpm_attributes
,
651 static const struct attribute_group hwmon_pwm_fan_attrgroup
= {
652 .attrs
= hwmon_pwm_fan_attributes
,
654 static const struct attribute_group hwmon_in0_attrgroup
= {
655 .attrs
= hwmon_in0_attributes
,
657 static const struct attribute_group hwmon_power_attrgroup
= {
658 .attrs
= hwmon_power_attributes
,
663 nouveau_hwmon_init(struct drm_device
*dev
)
665 #if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE))
666 struct nouveau_drm
*drm
= nouveau_drm(dev
);
667 struct nvkm_therm
*therm
= nvxx_therm(&drm
->device
);
668 struct nvkm_volt
*volt
= nvxx_volt(&drm
->device
);
669 struct nvkm_iccsense
*iccsense
= nvxx_iccsense(&drm
->device
);
670 struct nouveau_hwmon
*hwmon
;
671 struct device
*hwmon_dev
;
674 hwmon
= drm
->hwmon
= kzalloc(sizeof(*hwmon
), GFP_KERNEL
);
679 hwmon_dev
= hwmon_device_register(dev
->dev
);
680 if (IS_ERR(hwmon_dev
)) {
681 ret
= PTR_ERR(hwmon_dev
);
682 NV_ERROR(drm
, "Unable to register hwmon device: %d\n", ret
);
685 dev_set_drvdata(hwmon_dev
, dev
);
687 /* set the default attributes */
688 ret
= sysfs_create_group(&hwmon_dev
->kobj
, &hwmon_default_attrgroup
);
692 if (therm
&& therm
->attr_get
&& therm
->attr_set
) {
693 /* if the card has a working thermal sensor */
694 if (nvkm_therm_temp_get(therm
) >= 0) {
695 ret
= sysfs_create_group(&hwmon_dev
->kobj
, &hwmon_temp_attrgroup
);
700 /* if the card has a pwm fan */
701 /*XXX: incorrect, need better detection for this, some boards have
702 * the gpio entries for pwm fan control even when there's no
703 * actual fan connected to it... therm table? */
704 if (therm
->fan_get
&& therm
->fan_get(therm
) >= 0) {
705 ret
= sysfs_create_group(&hwmon_dev
->kobj
,
706 &hwmon_pwm_fan_attrgroup
);
712 /* if the card can read the fan rpm */
713 if (therm
&& nvkm_therm_fan_sense(therm
) >= 0) {
714 ret
= sysfs_create_group(&hwmon_dev
->kobj
,
715 &hwmon_fan_rpm_attrgroup
);
720 if (volt
&& nvkm_volt_get(volt
) >= 0) {
721 ret
= sysfs_create_group(&hwmon_dev
->kobj
,
722 &hwmon_in0_attrgroup
);
728 if (iccsense
&& iccsense
->data_valid
&& !list_empty(&iccsense
->rails
)) {
729 ret
= sysfs_create_group(&hwmon_dev
->kobj
,
730 &hwmon_power_attrgroup
);
735 hwmon
->hwmon
= hwmon_dev
;
740 NV_ERROR(drm
, "Unable to create some hwmon sysfs files: %d\n", ret
);
741 hwmon_device_unregister(hwmon_dev
);
750 nouveau_hwmon_fini(struct drm_device
*dev
)
752 #if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE))
753 struct nouveau_hwmon
*hwmon
= nouveau_hwmon(dev
);
756 sysfs_remove_group(&hwmon
->hwmon
->kobj
, &hwmon_default_attrgroup
);
757 sysfs_remove_group(&hwmon
->hwmon
->kobj
, &hwmon_temp_attrgroup
);
758 sysfs_remove_group(&hwmon
->hwmon
->kobj
, &hwmon_pwm_fan_attrgroup
);
759 sysfs_remove_group(&hwmon
->hwmon
->kobj
, &hwmon_fan_rpm_attrgroup
);
760 sysfs_remove_group(&hwmon
->hwmon
->kobj
, &hwmon_in0_attrgroup
);
761 sysfs_remove_group(&hwmon
->hwmon
->kobj
, &hwmon_power_attrgroup
);
763 hwmon_device_unregister(hwmon
->hwmon
);
766 nouveau_drm(dev
)->hwmon
= NULL
;