nouveau_hwmon.c 19.5 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
/*
 * Copyright 2010 Red Hat Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 *
 * Authors: Ben Skeggs
 */

25 26 27 28
#ifdef CONFIG_ACPI
#include <linux/acpi.h>
#endif
#include <linux/power_supply.h>
29 30 31
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>

32
#include <drm/drmP.h>
33

34
#include "nouveau_drm.h"
35
#include "nouveau_hwmon.h"
36

37 38
#include <nvkm/subdev/volt.h>

39
#if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE))
40 41 42 43
static ssize_t
nouveau_hwmon_show_temp(struct device *d, struct device_attribute *a, char *buf)
{
	struct drm_device *dev = dev_get_drvdata(d);
44
	struct nouveau_drm *drm = nouveau_drm(dev);
45
	struct nvkm_therm *therm = nvxx_therm(&drm->device);
46
	int temp = nvkm_therm_temp_get(therm);
47

48 49 50 51
	if (temp < 0)
		return temp;

	return snprintf(buf, PAGE_SIZE, "%d\n", temp * 1000);
52 53 54 55
}
static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, nouveau_hwmon_show_temp,
						  NULL, 0);

56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
static ssize_t
nouveau_hwmon_show_temp1_auto_point1_pwm(struct device *d,
					 struct device_attribute *a, char *buf)
{
	return snprintf(buf, PAGE_SIZE, "%d\n", 100);
}
static SENSOR_DEVICE_ATTR(temp1_auto_point1_pwm, S_IRUGO,
			  nouveau_hwmon_show_temp1_auto_point1_pwm, NULL, 0);

static ssize_t
nouveau_hwmon_temp1_auto_point1_temp(struct device *d,
				     struct device_attribute *a, char *buf)
{
	struct drm_device *dev = dev_get_drvdata(d);
	struct nouveau_drm *drm = nouveau_drm(dev);
71
	struct nvkm_therm *therm = nvxx_therm(&drm->device);
72 73

	return snprintf(buf, PAGE_SIZE, "%d\n",
74
	      therm->attr_get(therm, NVKM_THERM_ATTR_THRS_FAN_BOOST) * 1000);
75 76 77 78 79 80 81 82
}
static ssize_t
nouveau_hwmon_set_temp1_auto_point1_temp(struct device *d,
					 struct device_attribute *a,
					 const char *buf, size_t count)
{
	struct drm_device *dev = dev_get_drvdata(d);
	struct nouveau_drm *drm = nouveau_drm(dev);
83
	struct nvkm_therm *therm = nvxx_therm(&drm->device);
84 85 86 87 88
	long value;

	if (kstrtol(buf, 10, &value) == -EINVAL)
		return count;

89
	therm->attr_set(therm, NVKM_THERM_ATTR_THRS_FAN_BOOST,
90 91 92 93 94 95 96 97 98 99 100 101 102 103
			value / 1000);

	return count;
}
static SENSOR_DEVICE_ATTR(temp1_auto_point1_temp, S_IRUGO | S_IWUSR,
			  nouveau_hwmon_temp1_auto_point1_temp,
			  nouveau_hwmon_set_temp1_auto_point1_temp, 0);

static ssize_t
nouveau_hwmon_temp1_auto_point1_temp_hyst(struct device *d,
					  struct device_attribute *a, char *buf)
{
	struct drm_device *dev = dev_get_drvdata(d);
	struct nouveau_drm *drm = nouveau_drm(dev);
104
	struct nvkm_therm *therm = nvxx_therm(&drm->device);
105 106

	return snprintf(buf, PAGE_SIZE, "%d\n",
107
	 therm->attr_get(therm, NVKM_THERM_ATTR_THRS_FAN_BOOST_HYST) * 1000);
108 109 110 111 112 113 114 115
}
static ssize_t
nouveau_hwmon_set_temp1_auto_point1_temp_hyst(struct device *d,
					      struct device_attribute *a,
					      const char *buf, size_t count)
{
	struct drm_device *dev = dev_get_drvdata(d);
	struct nouveau_drm *drm = nouveau_drm(dev);
116
	struct nvkm_therm *therm = nvxx_therm(&drm->device);
117 118 119 120 121
	long value;

	if (kstrtol(buf, 10, &value) == -EINVAL)
		return count;

122
	therm->attr_set(therm, NVKM_THERM_ATTR_THRS_FAN_BOOST_HYST,
123 124 125 126 127 128 129 130
			value / 1000);

	return count;
}
static SENSOR_DEVICE_ATTR(temp1_auto_point1_temp_hyst, S_IRUGO | S_IWUSR,
			  nouveau_hwmon_temp1_auto_point1_temp_hyst,
			  nouveau_hwmon_set_temp1_auto_point1_temp_hyst, 0);

131 132 133 134
static ssize_t
nouveau_hwmon_max_temp(struct device *d, struct device_attribute *a, char *buf)
{
	struct drm_device *dev = dev_get_drvdata(d);
135
	struct nouveau_drm *drm = nouveau_drm(dev);
136
	struct nvkm_therm *therm = nvxx_therm(&drm->device);
137

138
	return snprintf(buf, PAGE_SIZE, "%d\n",
139
	       therm->attr_get(therm, NVKM_THERM_ATTR_THRS_DOWN_CLK) * 1000);
140 141 142 143 144 145
}
static ssize_t
nouveau_hwmon_set_max_temp(struct device *d, struct device_attribute *a,
						const char *buf, size_t count)
{
	struct drm_device *dev = dev_get_drvdata(d);
146
	struct nouveau_drm *drm = nouveau_drm(dev);
147
	struct nvkm_therm *therm = nvxx_therm(&drm->device);
148 149
	long value;

M
Martin Peres 已提交
150
	if (kstrtol(buf, 10, &value) == -EINVAL)
151 152
		return count;

153
	therm->attr_set(therm, NVKM_THERM_ATTR_THRS_DOWN_CLK, value / 1000);
154 155 156 157 158 159 160

	return count;
}
static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR, nouveau_hwmon_max_temp,
						  nouveau_hwmon_set_max_temp,
						  0);

161 162 163 164 165 166
static ssize_t
nouveau_hwmon_max_temp_hyst(struct device *d, struct device_attribute *a,
			    char *buf)
{
	struct drm_device *dev = dev_get_drvdata(d);
	struct nouveau_drm *drm = nouveau_drm(dev);
167
	struct nvkm_therm *therm = nvxx_therm(&drm->device);
168 169

	return snprintf(buf, PAGE_SIZE, "%d\n",
170
	  therm->attr_get(therm, NVKM_THERM_ATTR_THRS_DOWN_CLK_HYST) * 1000);
171 172 173 174 175 176 177
}
static ssize_t
nouveau_hwmon_set_max_temp_hyst(struct device *d, struct device_attribute *a,
						const char *buf, size_t count)
{
	struct drm_device *dev = dev_get_drvdata(d);
	struct nouveau_drm *drm = nouveau_drm(dev);
178
	struct nvkm_therm *therm = nvxx_therm(&drm->device);
179 180 181 182 183
	long value;

	if (kstrtol(buf, 10, &value) == -EINVAL)
		return count;

184
	therm->attr_set(therm, NVKM_THERM_ATTR_THRS_DOWN_CLK_HYST,
185 186 187 188 189 190 191 192
			value / 1000);

	return count;
}
static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR,
			  nouveau_hwmon_max_temp_hyst,
			  nouveau_hwmon_set_max_temp_hyst, 0);

193 194 195 196 197
static ssize_t
nouveau_hwmon_critical_temp(struct device *d, struct device_attribute *a,
							char *buf)
{
	struct drm_device *dev = dev_get_drvdata(d);
198
	struct nouveau_drm *drm = nouveau_drm(dev);
199
	struct nvkm_therm *therm = nvxx_therm(&drm->device);
200

201
	return snprintf(buf, PAGE_SIZE, "%d\n",
202
	       therm->attr_get(therm, NVKM_THERM_ATTR_THRS_CRITICAL) * 1000);
203 204 205 206 207 208 209
}
static ssize_t
nouveau_hwmon_set_critical_temp(struct device *d, struct device_attribute *a,
							    const char *buf,
								size_t count)
{
	struct drm_device *dev = dev_get_drvdata(d);
210
	struct nouveau_drm *drm = nouveau_drm(dev);
211
	struct nvkm_therm *therm = nvxx_therm(&drm->device);
212 213
	long value;

M
Martin Peres 已提交
214
	if (kstrtol(buf, 10, &value) == -EINVAL)
215 216
		return count;

217
	therm->attr_set(therm, NVKM_THERM_ATTR_THRS_CRITICAL, value / 1000);
218 219 220 221 222 223 224 225

	return count;
}
static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO | S_IWUSR,
						nouveau_hwmon_critical_temp,
						nouveau_hwmon_set_critical_temp,
						0);

226 227 228 229 230 231
static ssize_t
nouveau_hwmon_critical_temp_hyst(struct device *d, struct device_attribute *a,
							char *buf)
{
	struct drm_device *dev = dev_get_drvdata(d);
	struct nouveau_drm *drm = nouveau_drm(dev);
232
	struct nvkm_therm *therm = nvxx_therm(&drm->device);
233 234

	return snprintf(buf, PAGE_SIZE, "%d\n",
235
	  therm->attr_get(therm, NVKM_THERM_ATTR_THRS_CRITICAL_HYST) * 1000);
236 237 238 239 240 241 242 243 244
}
static ssize_t
nouveau_hwmon_set_critical_temp_hyst(struct device *d,
				     struct device_attribute *a,
				     const char *buf,
				     size_t count)
{
	struct drm_device *dev = dev_get_drvdata(d);
	struct nouveau_drm *drm = nouveau_drm(dev);
245
	struct nvkm_therm *therm = nvxx_therm(&drm->device);
246 247 248 249 250
	long value;

	if (kstrtol(buf, 10, &value) == -EINVAL)
		return count;

251
	therm->attr_set(therm, NVKM_THERM_ATTR_THRS_CRITICAL_HYST,
252 253 254 255 256 257 258 259 260 261 262 263 264
			value / 1000);

	return count;
}
static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO | S_IWUSR,
			  nouveau_hwmon_critical_temp_hyst,
			  nouveau_hwmon_set_critical_temp_hyst, 0);
static ssize_t
nouveau_hwmon_emergency_temp(struct device *d, struct device_attribute *a,
							char *buf)
{
	struct drm_device *dev = dev_get_drvdata(d);
	struct nouveau_drm *drm = nouveau_drm(dev);
265
	struct nvkm_therm *therm = nvxx_therm(&drm->device);
266 267

	return snprintf(buf, PAGE_SIZE, "%d\n",
268
	       therm->attr_get(therm, NVKM_THERM_ATTR_THRS_SHUTDOWN) * 1000);
269 270 271 272 273 274 275 276
}
static ssize_t
nouveau_hwmon_set_emergency_temp(struct device *d, struct device_attribute *a,
							    const char *buf,
								size_t count)
{
	struct drm_device *dev = dev_get_drvdata(d);
	struct nouveau_drm *drm = nouveau_drm(dev);
277
	struct nvkm_therm *therm = nvxx_therm(&drm->device);
278 279 280 281 282
	long value;

	if (kstrtol(buf, 10, &value) == -EINVAL)
		return count;

283
	therm->attr_set(therm, NVKM_THERM_ATTR_THRS_SHUTDOWN, value / 1000);
284 285 286 287 288 289 290 291 292 293 294 295 296 297

	return count;
}
static SENSOR_DEVICE_ATTR(temp1_emergency, S_IRUGO | S_IWUSR,
					nouveau_hwmon_emergency_temp,
					nouveau_hwmon_set_emergency_temp,
					0);

static ssize_t
nouveau_hwmon_emergency_temp_hyst(struct device *d, struct device_attribute *a,
							char *buf)
{
	struct drm_device *dev = dev_get_drvdata(d);
	struct nouveau_drm *drm = nouveau_drm(dev);
298
	struct nvkm_therm *therm = nvxx_therm(&drm->device);
299 300

	return snprintf(buf, PAGE_SIZE, "%d\n",
301
	  therm->attr_get(therm, NVKM_THERM_ATTR_THRS_SHUTDOWN_HYST) * 1000);
302 303 304 305 306 307 308 309 310
}
static ssize_t
nouveau_hwmon_set_emergency_temp_hyst(struct device *d,
				      struct device_attribute *a,
				      const char *buf,
				      size_t count)
{
	struct drm_device *dev = dev_get_drvdata(d);
	struct nouveau_drm *drm = nouveau_drm(dev);
311
	struct nvkm_therm *therm = nvxx_therm(&drm->device);
312 313 314 315 316
	long value;

	if (kstrtol(buf, 10, &value) == -EINVAL)
		return count;

317
	therm->attr_set(therm, NVKM_THERM_ATTR_THRS_SHUTDOWN_HYST,
318 319 320 321 322 323 324 325 326
			value / 1000);

	return count;
}
static SENSOR_DEVICE_ATTR(temp1_emergency_hyst, S_IRUGO | S_IWUSR,
					nouveau_hwmon_emergency_temp_hyst,
					nouveau_hwmon_set_emergency_temp_hyst,
					0);

327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344
static ssize_t nouveau_hwmon_show_name(struct device *dev,
				      struct device_attribute *attr,
				      char *buf)
{
	return sprintf(buf, "nouveau\n");
}
static SENSOR_DEVICE_ATTR(name, S_IRUGO, nouveau_hwmon_show_name, NULL, 0);

static ssize_t nouveau_hwmon_show_update_rate(struct device *dev,
				      struct device_attribute *attr,
				      char *buf)
{
	return sprintf(buf, "1000\n");
}
static SENSOR_DEVICE_ATTR(update_rate, S_IRUGO,
						nouveau_hwmon_show_update_rate,
						NULL, 0);

345
static ssize_t
B
Ben Skeggs 已提交
346
nouveau_hwmon_show_fan1_input(struct device *d, struct device_attribute *attr,
347 348 349
			      char *buf)
{
	struct drm_device *dev = dev_get_drvdata(d);
350
	struct nouveau_drm *drm = nouveau_drm(dev);
351
	struct nvkm_therm *therm = nvxx_therm(&drm->device);
352

353
	return snprintf(buf, PAGE_SIZE, "%d\n", nvkm_therm_fan_sense(therm));
354
}
B
Ben Skeggs 已提交
355
static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, nouveau_hwmon_show_fan1_input,
356 357
			  NULL, 0);

358 359 360 361 362 363
 static ssize_t
nouveau_hwmon_get_pwm1_enable(struct device *d,
			   struct device_attribute *a, char *buf)
{
	struct drm_device *dev = dev_get_drvdata(d);
	struct nouveau_drm *drm = nouveau_drm(dev);
364
	struct nvkm_therm *therm = nvxx_therm(&drm->device);
365
	int ret;
366

367
	ret = therm->attr_get(therm, NVKM_THERM_ATTR_FAN_MODE);
368
	if (ret < 0)
369
		return ret;
370

371 372
	return sprintf(buf, "%i\n", ret);
}
373

374 375 376 377 378 379
static ssize_t
nouveau_hwmon_set_pwm1_enable(struct device *d, struct device_attribute *a,
			   const char *buf, size_t count)
{
	struct drm_device *dev = dev_get_drvdata(d);
	struct nouveau_drm *drm = nouveau_drm(dev);
380
	struct nvkm_therm *therm = nvxx_therm(&drm->device);
381 382 383
	long value;
	int ret;

384 385 386
	ret = kstrtol(buf, 10, &value);
	if (ret)
		return ret;
387

388
	ret = therm->attr_set(therm, NVKM_THERM_ATTR_FAN_MODE, value);
389 390 391 392
	if (ret)
		return ret;
	else
		return count;
393
}
394 395 396
static SENSOR_DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR,
			  nouveau_hwmon_get_pwm1_enable,
			  nouveau_hwmon_set_pwm1_enable, 0);
397 398

static ssize_t
399
nouveau_hwmon_get_pwm1(struct device *d, struct device_attribute *a, char *buf)
400 401
{
	struct drm_device *dev = dev_get_drvdata(d);
402
	struct nouveau_drm *drm = nouveau_drm(dev);
403
	struct nvkm_therm *therm = nvxx_therm(&drm->device);
404
	int ret;
405

406
	ret = therm->fan_get(therm);
407 408 409 410 411 412 413
	if (ret < 0)
		return ret;

	return sprintf(buf, "%i\n", ret);
}

static ssize_t
414
nouveau_hwmon_set_pwm1(struct device *d, struct device_attribute *a,
415 416 417
		       const char *buf, size_t count)
{
	struct drm_device *dev = dev_get_drvdata(d);
418
	struct nouveau_drm *drm = nouveau_drm(dev);
419
	struct nvkm_therm *therm = nvxx_therm(&drm->device);
420 421 422
	int ret = -ENODEV;
	long value;

M
Martin Peres 已提交
423
	if (kstrtol(buf, 10, &value) == -EINVAL)
424 425
		return -EINVAL;

426
	ret = therm->fan_set(therm, value);
427 428 429 430 431 432
	if (ret)
		return ret;

	return count;
}

433 434 435
static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR,
			  nouveau_hwmon_get_pwm1,
			  nouveau_hwmon_set_pwm1, 0);
436 437

static ssize_t
438
nouveau_hwmon_get_pwm1_min(struct device *d,
439 440 441
			   struct device_attribute *a, char *buf)
{
	struct drm_device *dev = dev_get_drvdata(d);
442
	struct nouveau_drm *drm = nouveau_drm(dev);
443
	struct nvkm_therm *therm = nvxx_therm(&drm->device);
444 445
	int ret;

446
	ret = therm->attr_get(therm, NVKM_THERM_ATTR_FAN_MIN_DUTY);
447 448
	if (ret < 0)
		return ret;
449

450
	return sprintf(buf, "%i\n", ret);
451 452 453
}

static ssize_t
454
nouveau_hwmon_set_pwm1_min(struct device *d, struct device_attribute *a,
455 456 457
			   const char *buf, size_t count)
{
	struct drm_device *dev = dev_get_drvdata(d);
458
	struct nouveau_drm *drm = nouveau_drm(dev);
459
	struct nvkm_therm *therm = nvxx_therm(&drm->device);
460
	long value;
461
	int ret;
462

M
Martin Peres 已提交
463
	if (kstrtol(buf, 10, &value) == -EINVAL)
464 465
		return -EINVAL;

466
	ret = therm->attr_set(therm, NVKM_THERM_ATTR_FAN_MIN_DUTY, value);
467 468
	if (ret < 0)
		return ret;
469 470 471 472

	return count;
}

473 474 475
static SENSOR_DEVICE_ATTR(pwm1_min, S_IRUGO | S_IWUSR,
			  nouveau_hwmon_get_pwm1_min,
			  nouveau_hwmon_set_pwm1_min, 0);
476 477

static ssize_t
478
nouveau_hwmon_get_pwm1_max(struct device *d,
479 480 481
			   struct device_attribute *a, char *buf)
{
	struct drm_device *dev = dev_get_drvdata(d);
482
	struct nouveau_drm *drm = nouveau_drm(dev);
483
	struct nvkm_therm *therm = nvxx_therm(&drm->device);
484
	int ret;
485

486
	ret = therm->attr_get(therm, NVKM_THERM_ATTR_FAN_MAX_DUTY);
487 488
	if (ret < 0)
		return ret;
489

490
	return sprintf(buf, "%i\n", ret);
491 492 493
}

static ssize_t
494
nouveau_hwmon_set_pwm1_max(struct device *d, struct device_attribute *a,
495 496 497
			   const char *buf, size_t count)
{
	struct drm_device *dev = dev_get_drvdata(d);
498
	struct nouveau_drm *drm = nouveau_drm(dev);
499
	struct nvkm_therm *therm = nvxx_therm(&drm->device);
500
	long value;
501
	int ret;
502

M
Martin Peres 已提交
503
	if (kstrtol(buf, 10, &value) == -EINVAL)
504 505
		return -EINVAL;

506
	ret = therm->attr_set(therm, NVKM_THERM_ATTR_FAN_MAX_DUTY, value);
507 508
	if (ret < 0)
		return ret;
509 510 511 512

	return count;
}

513 514 515
static SENSOR_DEVICE_ATTR(pwm1_max, S_IRUGO | S_IWUSR,
			  nouveau_hwmon_get_pwm1_max,
			  nouveau_hwmon_set_pwm1_max, 0);
516

517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545
static ssize_t
nouveau_hwmon_get_in0_input(struct device *d,
			    struct device_attribute *a, char *buf)
{
	struct drm_device *dev = dev_get_drvdata(d);
	struct nouveau_drm *drm = nouveau_drm(dev);
	struct nvkm_volt *volt = nvxx_volt(&drm->device);
	int ret;

	ret = nvkm_volt_get(volt);
	if (ret < 0)
		return ret;

	return sprintf(buf, "%i\n", ret / 1000);
}

static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO,
			  nouveau_hwmon_get_in0_input, NULL, 0);

static ssize_t
nouveau_hwmon_get_in0_label(struct device *d,
			    struct device_attribute *a, char *buf)
{
	return sprintf(buf, "GPU core\n");
}

static SENSOR_DEVICE_ATTR(in0_label, S_IRUGO,
			  nouveau_hwmon_get_in0_label, NULL, 0);

546 547 548 549 550 551
static struct attribute *hwmon_default_attributes[] = {
	&sensor_dev_attr_name.dev_attr.attr,
	&sensor_dev_attr_update_rate.dev_attr.attr,
	NULL
};
static struct attribute *hwmon_temp_attributes[] = {
552
	&sensor_dev_attr_temp1_input.dev_attr.attr,
553 554 555
	&sensor_dev_attr_temp1_auto_point1_pwm.dev_attr.attr,
	&sensor_dev_attr_temp1_auto_point1_temp.dev_attr.attr,
	&sensor_dev_attr_temp1_auto_point1_temp_hyst.dev_attr.attr,
556
	&sensor_dev_attr_temp1_max.dev_attr.attr,
557
	&sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
558
	&sensor_dev_attr_temp1_crit.dev_attr.attr,
559 560 561
	&sensor_dev_attr_temp1_crit_hyst.dev_attr.attr,
	&sensor_dev_attr_temp1_emergency.dev_attr.attr,
	&sensor_dev_attr_temp1_emergency_hyst.dev_attr.attr,
562 563
	NULL
};
564
static struct attribute *hwmon_fan_rpm_attributes[] = {
B
Ben Skeggs 已提交
565
	&sensor_dev_attr_fan1_input.dev_attr.attr,
566 567 568
	NULL
};
static struct attribute *hwmon_pwm_fan_attributes[] = {
569
	&sensor_dev_attr_pwm1_enable.dev_attr.attr,
570 571 572
	&sensor_dev_attr_pwm1.dev_attr.attr,
	&sensor_dev_attr_pwm1_min.dev_attr.attr,
	&sensor_dev_attr_pwm1_max.dev_attr.attr,
573 574
	NULL
};
575

576 577 578 579 580 581
static struct attribute *hwmon_in0_attributes[] = {
	&sensor_dev_attr_in0_input.dev_attr.attr,
	&sensor_dev_attr_in0_label.dev_attr.attr,
	NULL
};

582 583 584 585 586
static const struct attribute_group hwmon_default_attrgroup = {
	.attrs = hwmon_default_attributes,
};
static const struct attribute_group hwmon_temp_attrgroup = {
	.attrs = hwmon_temp_attributes,
587
};
588 589 590 591 592 593
static const struct attribute_group hwmon_fan_rpm_attrgroup = {
	.attrs = hwmon_fan_rpm_attributes,
};
static const struct attribute_group hwmon_pwm_fan_attrgroup = {
	.attrs = hwmon_pwm_fan_attributes,
};
594 595 596
static const struct attribute_group hwmon_in0_attrgroup = {
	.attrs = hwmon_in0_attributes,
};
597
#endif
598

599
int
600 601
nouveau_hwmon_init(struct drm_device *dev)
{
602
#if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE))
603
	struct nouveau_drm *drm = nouveau_drm(dev);
604
	struct nvkm_therm *therm = nvxx_therm(&drm->device);
605
	struct nvkm_volt *volt = nvxx_volt(&drm->device);
606
	struct nouveau_hwmon *hwmon;
607
	struct device *hwmon_dev;
608
	int ret = 0;
609

610 611 612 613 614
	hwmon = drm->hwmon = kzalloc(sizeof(*hwmon), GFP_KERNEL);
	if (!hwmon)
		return -ENOMEM;
	hwmon->dev = dev;

615
	if (!therm || !therm->attr_get || !therm->attr_set)
616
		return -ENODEV;
617 618 619 620

	hwmon_dev = hwmon_device_register(&dev->pdev->dev);
	if (IS_ERR(hwmon_dev)) {
		ret = PTR_ERR(hwmon_dev);
621
		NV_ERROR(drm, "Unable to register hwmon device: %d\n", ret);
622 623 624
		return ret;
	}
	dev_set_drvdata(hwmon_dev, dev);
625

626 627
	/* set the default attributes */
	ret = sysfs_create_group(&hwmon_dev->kobj, &hwmon_default_attrgroup);
628 629
	if (ret)
		goto error;
630

631
	/* if the card has a working thermal sensor */
632
	if (nvkm_therm_temp_get(therm) >= 0) {
633
		ret = sysfs_create_group(&hwmon_dev->kobj, &hwmon_temp_attrgroup);
634 635
		if (ret)
			goto error;
636 637
	}

638 639 640 641
	/* if the card has a pwm fan */
	/*XXX: incorrect, need better detection for this, some boards have
	 *     the gpio entries for pwm fan control even when there's no
	 *     actual fan connected to it... therm table? */
642
	if (therm->fan_get && therm->fan_get(therm) >= 0) {
643
		ret = sysfs_create_group(&hwmon_dev->kobj,
644 645 646 647 648 649
					 &hwmon_pwm_fan_attrgroup);
		if (ret)
			goto error;
	}

	/* if the card can read the fan rpm */
650
	if (nvkm_therm_fan_sense(therm) >= 0) {
651
		ret = sysfs_create_group(&hwmon_dev->kobj,
652 653 654
					 &hwmon_fan_rpm_attrgroup);
		if (ret)
			goto error;
655 656
	}

657 658 659 660 661 662 663 664
	if (volt && nvkm_volt_get(volt) >= 0) {
		ret = sysfs_create_group(&hwmon_dev->kobj,
					 &hwmon_in0_attrgroup);

		if (ret)
			goto error;
	}

665
	hwmon->hwmon = hwmon_dev;
666

667
	return 0;
668 669

error:
670
	NV_ERROR(drm, "Unable to create some hwmon sysfs files: %d\n", ret);
671
	hwmon_device_unregister(hwmon_dev);
672
	hwmon->hwmon = NULL;
673 674 675 676
	return ret;
#else
	return 0;
#endif
677 678
}

679
void
680 681
nouveau_hwmon_fini(struct drm_device *dev)
{
682
#if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE))
683
	struct nouveau_hwmon *hwmon = nouveau_hwmon(dev);
684

685 686 687 688 689
	if (hwmon->hwmon) {
		sysfs_remove_group(&hwmon->hwmon->kobj, &hwmon_default_attrgroup);
		sysfs_remove_group(&hwmon->hwmon->kobj, &hwmon_temp_attrgroup);
		sysfs_remove_group(&hwmon->hwmon->kobj, &hwmon_pwm_fan_attrgroup);
		sysfs_remove_group(&hwmon->hwmon->kobj, &hwmon_fan_rpm_attrgroup);
690
		sysfs_remove_group(&hwmon->hwmon->kobj, &hwmon_in0_attrgroup);
691

692
		hwmon_device_unregister(hwmon->hwmon);
693
	}
694

695 696
	nouveau_drm(dev)->hwmon = NULL;
	kfree(hwmon);
697
#endif
698
}