hwmon: (dell-smm) Detect fan with index=2
[deliverable/linux.git] / drivers / hwmon / dell-smm-hwmon.c
CommitLineData
1da177e4 1/*
a5afba16 2 * dell-smm-hwmon.c -- Linux driver for accessing the SMM BIOS on Dell laptops.
1da177e4
LT
3 *
4 * Copyright (C) 2001 Massimo Dal Zotto <dz@debian.org>
5 *
949a9d70 6 * Hwmon integration:
7c81c60f 7 * Copyright (C) 2011 Jean Delvare <jdelvare@suse.de>
564132d9 8 * Copyright (C) 2013, 2014 Guenter Roeck <linux@roeck-us.net>
a5afba16 9 * Copyright (C) 2014, 2015 Pali Rohár <pali.rohar@gmail.com>
949a9d70 10 *
1da177e4
LT
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by the
13 * Free Software Foundation; either version 2, or (at your option) any
14 * later version.
15 *
16 * This program is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
20 */
21
60e71aaf
GR
22#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
23
564132d9 24#include <linux/delay.h>
1da177e4
LT
25#include <linux/module.h>
26#include <linux/types.h>
27#include <linux/init.h>
28#include <linux/proc_fs.h>
352f8f8b 29#include <linux/seq_file.h>
e70c9d5e 30#include <linux/dmi.h>
7e80d0d0 31#include <linux/capability.h>
613655fa 32#include <linux/mutex.h>
949a9d70
JD
33#include <linux/hwmon.h>
34#include <linux/hwmon-sysfs.h>
12186f51
GR
35#include <linux/uaccess.h>
36#include <linux/io.h>
f36fdb9f 37#include <linux/sched.h>
053ea640 38#include <linux/ctype.h>
1da177e4
LT
39
40#include <linux/i8k.h>
41
1da177e4
LT
42#define I8K_SMM_FN_STATUS 0x0025
43#define I8K_SMM_POWER_STATUS 0x0069
44#define I8K_SMM_SET_FAN 0x01a3
45#define I8K_SMM_GET_FAN 0x00a3
46#define I8K_SMM_GET_SPEED 0x02a3
f989e554 47#define I8K_SMM_GET_FAN_TYPE 0x03a3
8f21d8e9 48#define I8K_SMM_GET_NOM_SPEED 0x04a3
1da177e4 49#define I8K_SMM_GET_TEMP 0x10a3
5114b474 50#define I8K_SMM_GET_TEMP_TYPE 0x11a3
7e0fa31d
DT
51#define I8K_SMM_GET_DELL_SIG1 0xfea3
52#define I8K_SMM_GET_DELL_SIG2 0xffa3
1da177e4
LT
53
54#define I8K_FAN_MULT 30
8f21d8e9 55#define I8K_FAN_MAX_RPM 30000
1da177e4
LT
56#define I8K_MAX_TEMP 127
57
58#define I8K_FN_NONE 0x00
59#define I8K_FN_UP 0x01
60#define I8K_FN_DOWN 0x02
61#define I8K_FN_MUTE 0x04
62#define I8K_FN_MASK 0x07
63#define I8K_FN_SHIFT 8
64
65#define I8K_POWER_AC 0x05
66#define I8K_POWER_BATTERY 0x01
67
613655fa 68static DEFINE_MUTEX(i8k_mutex);
e70c9d5e 69static char bios_version[4];
7613663c 70static char bios_machineid[16];
949a9d70 71static struct device *i8k_hwmon_dev;
82ba1d3f 72static u32 i8k_hwmon_flags;
8f21d8e9 73static uint i8k_fan_mult = I8K_FAN_MULT;
7f69fb03
PR
74static uint i8k_pwm_mult;
75static uint i8k_fan_max = I8K_FAN_HIGH;
2744d2fd 76static bool disallow_fan_type_call;
82ba1d3f
GR
77
78#define I8K_HWMON_HAVE_TEMP1 (1 << 0)
d83c39de
GR
79#define I8K_HWMON_HAVE_TEMP2 (1 << 1)
80#define I8K_HWMON_HAVE_TEMP3 (1 << 2)
81#define I8K_HWMON_HAVE_TEMP4 (1 << 3)
82#define I8K_HWMON_HAVE_FAN1 (1 << 4)
83#define I8K_HWMON_HAVE_FAN2 (1 << 5)
747bc8b0 84#define I8K_HWMON_HAVE_FAN3 (1 << 6)
1da177e4
LT
85
86MODULE_AUTHOR("Massimo Dal Zotto (dz@debian.org)");
a5afba16 87MODULE_AUTHOR("Pali Rohár <pali.rohar@gmail.com>");
039ae585 88MODULE_DESCRIPTION("Dell laptop SMM BIOS hwmon driver");
1da177e4 89MODULE_LICENSE("GPL");
a5afba16 90MODULE_ALIAS("i8k");
1da177e4 91
90ab5ee9 92static bool force;
1da177e4
LT
93module_param(force, bool, 0);
94MODULE_PARM_DESC(force, "Force loading without checking for supported models");
95
90ab5ee9 96static bool ignore_dmi;
e70c9d5e
DT
97module_param(ignore_dmi, bool, 0);
98MODULE_PARM_DESC(ignore_dmi, "Continue probing hardware even if DMI data does not match");
99
039ae585 100#if IS_ENABLED(CONFIG_I8K)
7613663c 101static bool restricted = true;
1da177e4 102module_param(restricted, bool, 0);
7613663c 103MODULE_PARM_DESC(restricted, "Restrict fan control and serial number to CAP_SYS_ADMIN (default: 1)");
1da177e4 104
90ab5ee9 105static bool power_status;
1da177e4 106module_param(power_status, bool, 0600);
7613663c 107MODULE_PARM_DESC(power_status, "Report power status in /proc/i8k (default: 0)");
039ae585 108#endif
1da177e4 109
8f21d8e9 110static uint fan_mult;
7f69fb03 111module_param(fan_mult, uint, 0);
8f21d8e9 112MODULE_PARM_DESC(fan_mult, "Factor to multiply fan speed with (default: autodetect)");
4ed99a27 113
8f21d8e9 114static uint fan_max;
7f69fb03 115module_param(fan_max, uint, 0);
8f21d8e9 116MODULE_PARM_DESC(fan_max, "Maximum configurable fan speed (default: autodetect)");
81474fc2 117
8378b924 118struct smm_regs {
dec63ec3 119 unsigned int eax;
12186f51
GR
120 unsigned int ebx __packed;
121 unsigned int ecx __packed;
122 unsigned int edx __packed;
123 unsigned int esi __packed;
124 unsigned int edi __packed;
8378b924 125};
1da177e4 126
1855256c 127static inline const char *i8k_get_dmi_data(int field)
e70c9d5e 128{
1855256c 129 const char *dmi_data = dmi_get_system_info(field);
4f005551
DT
130
131 return dmi_data && *dmi_data ? dmi_data : "?";
e70c9d5e 132}
1da177e4
LT
133
134/*
135 * Call the System Management Mode BIOS. Code provided by Jonathan Buzzard.
136 */
8378b924 137static int i8k_smm(struct smm_regs *regs)
1da177e4 138{
dec63ec3
DT
139 int rc;
140 int eax = regs->eax;
f36fdb9f
GR
141 cpumask_var_t old_mask;
142
143 /* SMM requires CPU 0 */
144 if (!alloc_cpumask_var(&old_mask, GFP_KERNEL))
145 return -ENOMEM;
146 cpumask_copy(old_mask, &current->cpus_allowed);
6d827fbc
GR
147 rc = set_cpus_allowed_ptr(current, cpumask_of(0));
148 if (rc)
149 goto out;
f36fdb9f
GR
150 if (smp_processor_id() != 0) {
151 rc = -EBUSY;
152 goto out;
153 }
dec63ec3 154
fe04f22f 155#if defined(CONFIG_X86_64)
22d3243d 156 asm volatile("pushq %%rax\n\t"
fe04f22f
BS
157 "movl 0(%%rax),%%edx\n\t"
158 "pushq %%rdx\n\t"
159 "movl 4(%%rax),%%ebx\n\t"
160 "movl 8(%%rax),%%ecx\n\t"
161 "movl 12(%%rax),%%edx\n\t"
162 "movl 16(%%rax),%%esi\n\t"
163 "movl 20(%%rax),%%edi\n\t"
164 "popq %%rax\n\t"
165 "out %%al,$0xb2\n\t"
166 "out %%al,$0x84\n\t"
167 "xchgq %%rax,(%%rsp)\n\t"
168 "movl %%ebx,4(%%rax)\n\t"
169 "movl %%ecx,8(%%rax)\n\t"
170 "movl %%edx,12(%%rax)\n\t"
171 "movl %%esi,16(%%rax)\n\t"
172 "movl %%edi,20(%%rax)\n\t"
173 "popq %%rdx\n\t"
174 "movl %%edx,0(%%rax)\n\t"
bc1f419c
LT
175 "pushfq\n\t"
176 "popq %%rax\n\t"
fe04f22f 177 "andl $1,%%eax\n"
12186f51 178 : "=a"(rc)
fe04f22f
BS
179 : "a"(regs)
180 : "%ebx", "%ecx", "%edx", "%esi", "%edi", "memory");
181#else
22d3243d 182 asm volatile("pushl %%eax\n\t"
dec63ec3
DT
183 "movl 0(%%eax),%%edx\n\t"
184 "push %%edx\n\t"
185 "movl 4(%%eax),%%ebx\n\t"
186 "movl 8(%%eax),%%ecx\n\t"
187 "movl 12(%%eax),%%edx\n\t"
188 "movl 16(%%eax),%%esi\n\t"
189 "movl 20(%%eax),%%edi\n\t"
190 "popl %%eax\n\t"
191 "out %%al,$0xb2\n\t"
192 "out %%al,$0x84\n\t"
193 "xchgl %%eax,(%%esp)\n\t"
194 "movl %%ebx,4(%%eax)\n\t"
195 "movl %%ecx,8(%%eax)\n\t"
196 "movl %%edx,12(%%eax)\n\t"
197 "movl %%esi,16(%%eax)\n\t"
198 "movl %%edi,20(%%eax)\n\t"
199 "popl %%edx\n\t"
200 "movl %%edx,0(%%eax)\n\t"
201 "lahf\n\t"
202 "shrl $8,%%eax\n\t"
6b4e81db 203 "andl $1,%%eax\n"
12186f51 204 : "=a"(rc)
dec63ec3
DT
205 : "a"(regs)
206 : "%ebx", "%ecx", "%edx", "%esi", "%edi", "memory");
fe04f22f 207#endif
8378b924 208 if (rc != 0 || (regs->eax & 0xffff) == 0xffff || regs->eax == eax)
f36fdb9f 209 rc = -EINVAL;
dec63ec3 210
f36fdb9f
GR
211out:
212 set_cpus_allowed_ptr(current, old_mask);
213 free_cpumask_var(old_mask);
214 return rc;
1da177e4
LT
215}
216
1da177e4
LT
217/*
218 * Read the fan status.
219 */
220static int i8k_get_fan_status(int fan)
221{
8378b924 222 struct smm_regs regs = { .eax = I8K_SMM_GET_FAN, };
1da177e4 223
dec63ec3 224 regs.ebx = fan & 0xff;
8378b924 225 return i8k_smm(&regs) ? : regs.eax & 0xff;
1da177e4
LT
226}
227
228/*
229 * Read the fan speed in RPM.
230 */
231static int i8k_get_fan_speed(int fan)
232{
8378b924 233 struct smm_regs regs = { .eax = I8K_SMM_GET_SPEED, };
1da177e4 234
dec63ec3 235 regs.ebx = fan & 0xff;
26d09382 236 return i8k_smm(&regs) ? : (regs.eax & 0xffff) * i8k_fan_mult;
1da177e4
LT
237}
238
f989e554
PR
239/*
240 * Read the fan type.
241 */
5ce91714 242static int _i8k_get_fan_type(int fan)
f989e554
PR
243{
244 struct smm_regs regs = { .eax = I8K_SMM_GET_FAN_TYPE, };
245
2744d2fd
PR
246 if (disallow_fan_type_call)
247 return -EINVAL;
248
f989e554
PR
249 regs.ebx = fan & 0xff;
250 return i8k_smm(&regs) ? : regs.eax & 0xff;
251}
252
5ce91714
PR
253static int i8k_get_fan_type(int fan)
254{
255 /* I8K_SMM_GET_FAN_TYPE SMM call is expensive, so cache values */
747bc8b0 256 static int types[3] = { INT_MIN, INT_MIN, INT_MIN };
5ce91714
PR
257
258 if (types[fan] == INT_MIN)
259 types[fan] = _i8k_get_fan_type(fan);
260
261 return types[fan];
262}
263
8f21d8e9
PR
264/*
265 * Read the fan nominal rpm for specific fan speed.
266 */
267static int i8k_get_fan_nominal_speed(int fan, int speed)
268{
269 struct smm_regs regs = { .eax = I8K_SMM_GET_NOM_SPEED, };
270
271 regs.ebx = (fan & 0xff) | (speed << 8);
272 return i8k_smm(&regs) ? : (regs.eax & 0xffff) * i8k_fan_mult;
273}
274
1da177e4
LT
275/*
276 * Set the fan speed (off, low, high). Returns the new fan status.
277 */
278static int i8k_set_fan(int fan, int speed)
279{
8378b924 280 struct smm_regs regs = { .eax = I8K_SMM_SET_FAN, };
1da177e4 281
81474fc2 282 speed = (speed < 0) ? 0 : ((speed > i8k_fan_max) ? i8k_fan_max : speed);
dec63ec3 283 regs.ebx = (fan & 0xff) | (speed << 8);
1da177e4 284
8378b924 285 return i8k_smm(&regs) ? : i8k_get_fan_status(fan);
1da177e4
LT
286}
287
5114b474
PR
288static int i8k_get_temp_type(int sensor)
289{
290 struct smm_regs regs = { .eax = I8K_SMM_GET_TEMP_TYPE, };
291
292 regs.ebx = sensor & 0xff;
293 return i8k_smm(&regs) ? : regs.eax & 0xff;
294}
295
1da177e4
LT
296/*
297 * Read the cpu temperature.
298 */
564132d9 299static int _i8k_get_temp(int sensor)
1da177e4 300{
564132d9
GR
301 struct smm_regs regs = {
302 .eax = I8K_SMM_GET_TEMP,
303 .ebx = sensor & 0xff,
304 };
1da177e4 305
564132d9
GR
306 return i8k_smm(&regs) ? : regs.eax & 0xff;
307}
8378b924 308
564132d9
GR
309static int i8k_get_temp(int sensor)
310{
311 int temp = _i8k_get_temp(sensor);
1da177e4 312
dec63ec3
DT
313 /*
314 * Sometimes the temperature sensor returns 0x99, which is out of range.
564132d9 315 * In this case we retry (once) before returning an error.
dec63ec3
DT
316 # 1003655137 00000058 00005a4b
317 # 1003655138 00000099 00003a80 <--- 0x99 = 153 degrees
318 # 1003655139 00000054 00005c52
319 */
564132d9
GR
320 if (temp == 0x99) {
321 msleep(100);
322 temp = _i8k_get_temp(sensor);
dec63ec3 323 }
564132d9
GR
324 /*
325 * Return -ENODATA for all invalid temperatures.
326 *
327 * Known instances are the 0x99 value as seen above as well as
328 * 0xc1 (193), which may be returned when trying to read the GPU
329 * temperature if the system supports a GPU and it is currently
330 * turned off.
331 */
723493ca 332 if (temp > I8K_MAX_TEMP)
83d514d7 333 return -ENODATA;
1da177e4 334
dec63ec3 335 return temp;
1da177e4
LT
336}
337
7e0fa31d 338static int i8k_get_dell_signature(int req_fn)
1da177e4 339{
7e0fa31d 340 struct smm_regs regs = { .eax = req_fn, };
dec63ec3 341 int rc;
1da177e4 342
12186f51
GR
343 rc = i8k_smm(&regs);
344 if (rc < 0)
dec63ec3 345 return rc;
1da177e4 346
8378b924 347 return regs.eax == 1145651527 && regs.edx == 1145392204 ? 0 : -1;
1da177e4
LT
348}
349
039ae585
PR
350#if IS_ENABLED(CONFIG_I8K)
351
352/*
353 * Read the Fn key status.
354 */
355static int i8k_get_fn_status(void)
356{
357 struct smm_regs regs = { .eax = I8K_SMM_FN_STATUS, };
358 int rc;
359
360 rc = i8k_smm(&regs);
361 if (rc < 0)
362 return rc;
363
364 switch ((regs.eax >> I8K_FN_SHIFT) & I8K_FN_MASK) {
365 case I8K_FN_UP:
366 return I8K_VOL_UP;
367 case I8K_FN_DOWN:
368 return I8K_VOL_DOWN;
369 case I8K_FN_MUTE:
370 return I8K_VOL_MUTE;
371 default:
372 return 0;
373 }
374}
375
376/*
377 * Read the power status.
378 */
379static int i8k_get_power_status(void)
380{
381 struct smm_regs regs = { .eax = I8K_SMM_POWER_STATUS, };
382 int rc;
383
384 rc = i8k_smm(&regs);
385 if (rc < 0)
386 return rc;
387
388 return (regs.eax & 0xff) == I8K_POWER_AC ? I8K_AC : I8K_BATTERY;
389}
390
391/*
392 * Procfs interface
393 */
394
d79b6f4d
FW
395static int
396i8k_ioctl_unlocked(struct file *fp, unsigned int cmd, unsigned long arg)
1da177e4 397{
e70c9d5e 398 int val = 0;
dec63ec3
DT
399 int speed;
400 unsigned char buff[16];
401 int __user *argp = (int __user *)arg;
402
403 if (!argp)
404 return -EINVAL;
405
406 switch (cmd) {
407 case I8K_BIOS_VERSION:
053ea640
PR
408 if (!isdigit(bios_version[0]) || !isdigit(bios_version[1]) ||
409 !isdigit(bios_version[2]))
410 return -EINVAL;
411
e551b152
GR
412 val = (bios_version[0] << 16) |
413 (bios_version[1] << 8) | bios_version[2];
dec63ec3
DT
414 break;
415
416 case I8K_MACHINE_ID:
7613663c
PR
417 if (restricted && !capable(CAP_SYS_ADMIN))
418 return -EPERM;
419
420 memset(buff, 0, sizeof(buff));
421 strlcpy(buff, bios_machineid, sizeof(buff));
dec63ec3
DT
422 break;
423
424 case I8K_FN_STATUS:
425 val = i8k_get_fn_status();
426 break;
427
428 case I8K_POWER_STATUS:
429 val = i8k_get_power_status();
430 break;
431
432 case I8K_GET_TEMP:
7e0fa31d 433 val = i8k_get_temp(0);
dec63ec3
DT
434 break;
435
436 case I8K_GET_SPEED:
8378b924 437 if (copy_from_user(&val, argp, sizeof(int)))
dec63ec3 438 return -EFAULT;
8378b924 439
dec63ec3
DT
440 val = i8k_get_fan_speed(val);
441 break;
1da177e4 442
dec63ec3 443 case I8K_GET_FAN:
8378b924 444 if (copy_from_user(&val, argp, sizeof(int)))
dec63ec3 445 return -EFAULT;
8378b924 446
dec63ec3
DT
447 val = i8k_get_fan_status(val);
448 break;
1da177e4 449
dec63ec3 450 case I8K_SET_FAN:
8378b924 451 if (restricted && !capable(CAP_SYS_ADMIN))
dec63ec3 452 return -EPERM;
8378b924
DT
453
454 if (copy_from_user(&val, argp, sizeof(int)))
dec63ec3 455 return -EFAULT;
8378b924
DT
456
457 if (copy_from_user(&speed, argp + 1, sizeof(int)))
dec63ec3 458 return -EFAULT;
8378b924 459
dec63ec3
DT
460 val = i8k_set_fan(val, speed);
461 break;
1da177e4 462
dec63ec3
DT
463 default:
464 return -EINVAL;
1da177e4 465 }
1da177e4 466
8378b924 467 if (val < 0)
dec63ec3 468 return val;
1da177e4 469
dec63ec3
DT
470 switch (cmd) {
471 case I8K_BIOS_VERSION:
8378b924 472 if (copy_to_user(argp, &val, 4))
dec63ec3 473 return -EFAULT;
8378b924 474
dec63ec3
DT
475 break;
476 case I8K_MACHINE_ID:
8378b924 477 if (copy_to_user(argp, buff, 16))
dec63ec3 478 return -EFAULT;
8378b924 479
dec63ec3
DT
480 break;
481 default:
8378b924 482 if (copy_to_user(argp, &val, sizeof(int)))
dec63ec3 483 return -EFAULT;
8378b924 484
dec63ec3 485 break;
1da177e4 486 }
1da177e4 487
dec63ec3 488 return 0;
1da177e4
LT
489}
490
d79b6f4d
FW
491static long i8k_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
492{
493 long ret;
494
613655fa 495 mutex_lock(&i8k_mutex);
d79b6f4d 496 ret = i8k_ioctl_unlocked(fp, cmd, arg);
613655fa 497 mutex_unlock(&i8k_mutex);
d79b6f4d
FW
498
499 return ret;
500}
501
1da177e4
LT
502/*
503 * Print the information for /proc/i8k.
504 */
352f8f8b 505static int i8k_proc_show(struct seq_file *seq, void *offset)
1da177e4 506{
352f8f8b 507 int fn_key, cpu_temp, ac_power;
dec63ec3
DT
508 int left_fan, right_fan, left_speed, right_speed;
509
96de0e25
JE
510 cpu_temp = i8k_get_temp(0); /* 11100 µs */
511 left_fan = i8k_get_fan_status(I8K_FAN_LEFT); /* 580 µs */
512 right_fan = i8k_get_fan_status(I8K_FAN_RIGHT); /* 580 µs */
513 left_speed = i8k_get_fan_speed(I8K_FAN_LEFT); /* 580 µs */
514 right_speed = i8k_get_fan_speed(I8K_FAN_RIGHT); /* 580 µs */
515 fn_key = i8k_get_fn_status(); /* 750 µs */
8378b924 516 if (power_status)
96de0e25 517 ac_power = i8k_get_power_status(); /* 14700 µs */
8378b924 518 else
dec63ec3 519 ac_power = -1;
dec63ec3
DT
520
521 /*
522 * Info:
523 *
524 * 1) Format version (this will change if format changes)
525 * 2) BIOS version
526 * 3) BIOS machine ID
527 * 4) Cpu temperature
528 * 5) Left fan status
529 * 6) Right fan status
530 * 7) Left fan speed
531 * 8) Right fan speed
532 * 9) AC power
533 * 10) Fn Key status
534 */
3a267d3b
JP
535 seq_printf(seq, "%s %s %s %d %d %d %d %d %d %d\n",
536 I8K_PROC_FMT,
537 bios_version,
7613663c 538 (restricted && !capable(CAP_SYS_ADMIN)) ? "-1" : bios_machineid,
3a267d3b
JP
539 cpu_temp,
540 left_fan, right_fan, left_speed, right_speed,
541 ac_power, fn_key);
542
543 return 0;
1da177e4
LT
544}
545
352f8f8b 546static int i8k_open_fs(struct inode *inode, struct file *file)
1da177e4 547{
352f8f8b 548 return single_open(file, i8k_proc_show, NULL);
1da177e4
LT
549}
550
039ae585
PR
551static const struct file_operations i8k_fops = {
552 .owner = THIS_MODULE,
553 .open = i8k_open_fs,
554 .read = seq_read,
555 .llseek = seq_lseek,
556 .release = single_release,
557 .unlocked_ioctl = i8k_ioctl,
558};
559
560static void __init i8k_init_procfs(void)
561{
562 /* Register the proc entry */
563 proc_create("i8k", 0, NULL, &i8k_fops);
564}
565
566static void __exit i8k_exit_procfs(void)
567{
568 remove_proc_entry("i8k", NULL);
569}
570
571#else
572
573static inline void __init i8k_init_procfs(void)
574{
575}
576
577static inline void __exit i8k_exit_procfs(void)
578{
579}
580
581#endif
949a9d70
JD
582
583/*
584 * Hwmon interface
585 */
586
5114b474
PR
587static ssize_t i8k_hwmon_show_temp_label(struct device *dev,
588 struct device_attribute *devattr,
589 char *buf)
590{
591 static const char * const labels[] = {
592 "CPU",
593 "GPU",
594 "SODIMM",
595 "Other",
596 "Ambient",
597 "Other",
598 };
599 int index = to_sensor_dev_attr(devattr)->index;
600 int type;
601
602 type = i8k_get_temp_type(index);
603 if (type < 0)
604 return type;
605 if (type >= ARRAY_SIZE(labels))
606 type = ARRAY_SIZE(labels) - 1;
607 return sprintf(buf, "%s\n", labels[type]);
608}
609
949a9d70
JD
610static ssize_t i8k_hwmon_show_temp(struct device *dev,
611 struct device_attribute *devattr,
612 char *buf)
613{
d83c39de
GR
614 int index = to_sensor_dev_attr(devattr)->index;
615 int temp;
949a9d70 616
d83c39de
GR
617 temp = i8k_get_temp(index);
618 if (temp < 0)
619 return temp;
620 return sprintf(buf, "%d\n", temp * 1000);
949a9d70
JD
621}
622
f989e554
PR
623static ssize_t i8k_hwmon_show_fan_label(struct device *dev,
624 struct device_attribute *devattr,
625 char *buf)
626{
627 static const char * const labels[] = {
628 "Processor Fan",
629 "Motherboard Fan",
630 "Video Fan",
631 "Power Supply Fan",
632 "Chipset Fan",
633 "Other Fan",
634 };
635 int index = to_sensor_dev_attr(devattr)->index;
636 bool dock = false;
637 int type;
638
639 type = i8k_get_fan_type(index);
640 if (type < 0)
641 return type;
642
643 if (type & 0x10) {
644 dock = true;
645 type &= 0x0F;
646 }
647
648 if (type >= ARRAY_SIZE(labels))
649 type = (ARRAY_SIZE(labels) - 1);
650
651 return sprintf(buf, "%s%s\n", (dock ? "Docking " : ""), labels[type]);
652}
653
949a9d70
JD
654static ssize_t i8k_hwmon_show_fan(struct device *dev,
655 struct device_attribute *devattr,
656 char *buf)
657{
658 int index = to_sensor_dev_attr(devattr)->index;
659 int fan_speed;
660
661 fan_speed = i8k_get_fan_speed(index);
662 if (fan_speed < 0)
663 return fan_speed;
664 return sprintf(buf, "%d\n", fan_speed);
665}
666
e7f5f275
GR
667static ssize_t i8k_hwmon_show_pwm(struct device *dev,
668 struct device_attribute *devattr,
669 char *buf)
670{
671 int index = to_sensor_dev_attr(devattr)->index;
672 int status;
673
674 status = i8k_get_fan_status(index);
675 if (status < 0)
676 return -EIO;
81474fc2 677 return sprintf(buf, "%d\n", clamp_val(status * i8k_pwm_mult, 0, 255));
e7f5f275
GR
678}
679
680static ssize_t i8k_hwmon_set_pwm(struct device *dev,
681 struct device_attribute *attr,
682 const char *buf, size_t count)
683{
684 int index = to_sensor_dev_attr(attr)->index;
685 unsigned long val;
686 int err;
687
688 err = kstrtoul(buf, 10, &val);
689 if (err)
690 return err;
81474fc2 691 val = clamp_val(DIV_ROUND_CLOSEST(val, i8k_pwm_mult), 0, i8k_fan_max);
e7f5f275
GR
692
693 mutex_lock(&i8k_mutex);
694 err = i8k_set_fan(index, val);
695 mutex_unlock(&i8k_mutex);
696
697 return err < 0 ? -EIO : count;
698}
699
d83c39de 700static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, i8k_hwmon_show_temp, NULL, 0);
5114b474
PR
701static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, i8k_hwmon_show_temp_label, NULL,
702 0);
d83c39de 703static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, i8k_hwmon_show_temp, NULL, 1);
5114b474
PR
704static SENSOR_DEVICE_ATTR(temp2_label, S_IRUGO, i8k_hwmon_show_temp_label, NULL,
705 1);
d83c39de 706static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, i8k_hwmon_show_temp, NULL, 2);
5114b474
PR
707static SENSOR_DEVICE_ATTR(temp3_label, S_IRUGO, i8k_hwmon_show_temp_label, NULL,
708 2);
d83c39de 709static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, i8k_hwmon_show_temp, NULL, 3);
5114b474
PR
710static SENSOR_DEVICE_ATTR(temp4_label, S_IRUGO, i8k_hwmon_show_temp_label, NULL,
711 3);
f989e554
PR
712static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, i8k_hwmon_show_fan, NULL, 0);
713static SENSOR_DEVICE_ATTR(fan1_label, S_IRUGO, i8k_hwmon_show_fan_label, NULL,
714 0);
e7f5f275 715static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, i8k_hwmon_show_pwm,
f989e554 716 i8k_hwmon_set_pwm, 0);
949a9d70 717static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, i8k_hwmon_show_fan, NULL,
f989e554
PR
718 1);
719static SENSOR_DEVICE_ATTR(fan2_label, S_IRUGO, i8k_hwmon_show_fan_label, NULL,
720 1);
e7f5f275 721static SENSOR_DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR, i8k_hwmon_show_pwm,
f989e554 722 i8k_hwmon_set_pwm, 1);
747bc8b0
PR
723static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, i8k_hwmon_show_fan, NULL,
724 2);
725static SENSOR_DEVICE_ATTR(fan3_label, S_IRUGO, i8k_hwmon_show_fan_label, NULL,
726 2);
727static SENSOR_DEVICE_ATTR(pwm3, S_IRUGO | S_IWUSR, i8k_hwmon_show_pwm,
728 i8k_hwmon_set_pwm, 2);
82ba1d3f
GR
729
730static struct attribute *i8k_attrs[] = {
d83c39de 731 &sensor_dev_attr_temp1_input.dev_attr.attr, /* 0 */
5114b474
PR
732 &sensor_dev_attr_temp1_label.dev_attr.attr, /* 1 */
733 &sensor_dev_attr_temp2_input.dev_attr.attr, /* 2 */
734 &sensor_dev_attr_temp2_label.dev_attr.attr, /* 3 */
735 &sensor_dev_attr_temp3_input.dev_attr.attr, /* 4 */
736 &sensor_dev_attr_temp3_label.dev_attr.attr, /* 5 */
737 &sensor_dev_attr_temp4_input.dev_attr.attr, /* 6 */
738 &sensor_dev_attr_temp4_label.dev_attr.attr, /* 7 */
739 &sensor_dev_attr_fan1_input.dev_attr.attr, /* 8 */
f989e554
PR
740 &sensor_dev_attr_fan1_label.dev_attr.attr, /* 9 */
741 &sensor_dev_attr_pwm1.dev_attr.attr, /* 10 */
742 &sensor_dev_attr_fan2_input.dev_attr.attr, /* 11 */
743 &sensor_dev_attr_fan2_label.dev_attr.attr, /* 12 */
744 &sensor_dev_attr_pwm2.dev_attr.attr, /* 13 */
747bc8b0
PR
745 &sensor_dev_attr_fan3_input.dev_attr.attr, /* 14 */
746 &sensor_dev_attr_fan3_label.dev_attr.attr, /* 15 */
747 &sensor_dev_attr_pwm3.dev_attr.attr, /* 16 */
82ba1d3f
GR
748 NULL
749};
949a9d70 750
82ba1d3f
GR
751static umode_t i8k_is_visible(struct kobject *kobj, struct attribute *attr,
752 int index)
949a9d70 753{
2744d2fd 754 if (disallow_fan_type_call &&
747bc8b0 755 (index == 9 || index == 12 || index == 15))
2744d2fd 756 return 0;
5114b474
PR
757 if (index >= 0 && index <= 1 &&
758 !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP1))
82ba1d3f 759 return 0;
5114b474
PR
760 if (index >= 2 && index <= 3 &&
761 !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP2))
d83c39de 762 return 0;
5114b474
PR
763 if (index >= 4 && index <= 5 &&
764 !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP3))
d83c39de 765 return 0;
5114b474
PR
766 if (index >= 6 && index <= 7 &&
767 !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP4))
d83c39de 768 return 0;
f989e554 769 if (index >= 8 && index <= 10 &&
82ba1d3f
GR
770 !(i8k_hwmon_flags & I8K_HWMON_HAVE_FAN1))
771 return 0;
f989e554 772 if (index >= 11 && index <= 13 &&
82ba1d3f
GR
773 !(i8k_hwmon_flags & I8K_HWMON_HAVE_FAN2))
774 return 0;
747bc8b0
PR
775 if (index >= 14 && index <= 16 &&
776 !(i8k_hwmon_flags & I8K_HWMON_HAVE_FAN3))
777 return 0;
82ba1d3f
GR
778
779 return attr->mode;
949a9d70
JD
780}
781
82ba1d3f
GR
782static const struct attribute_group i8k_group = {
783 .attrs = i8k_attrs,
784 .is_visible = i8k_is_visible,
785};
786__ATTRIBUTE_GROUPS(i8k);
787
949a9d70
JD
788static int __init i8k_init_hwmon(void)
789{
790 int err;
791
82ba1d3f 792 i8k_hwmon_flags = 0;
949a9d70 793
672af223
PR
794 /* CPU temperature attributes, if temperature type is OK */
795 err = i8k_get_temp_type(0);
796 if (err >= 0)
82ba1d3f 797 i8k_hwmon_flags |= I8K_HWMON_HAVE_TEMP1;
d83c39de 798 /* check for additional temperature sensors */
672af223
PR
799 err = i8k_get_temp_type(1);
800 if (err >= 0)
d83c39de 801 i8k_hwmon_flags |= I8K_HWMON_HAVE_TEMP2;
672af223
PR
802 err = i8k_get_temp_type(2);
803 if (err >= 0)
d83c39de 804 i8k_hwmon_flags |= I8K_HWMON_HAVE_TEMP3;
672af223
PR
805 err = i8k_get_temp_type(3);
806 if (err >= 0)
d83c39de 807 i8k_hwmon_flags |= I8K_HWMON_HAVE_TEMP4;
949a9d70 808
5ce91714
PR
809 /* First fan attributes, if fan status or type is OK */
810 err = i8k_get_fan_status(0);
811 if (err < 0)
812 err = i8k_get_fan_type(0);
82ba1d3f
GR
813 if (err >= 0)
814 i8k_hwmon_flags |= I8K_HWMON_HAVE_FAN1;
949a9d70 815
5ce91714
PR
816 /* Second fan attributes, if fan status or type is OK */
817 err = i8k_get_fan_status(1);
818 if (err < 0)
819 err = i8k_get_fan_type(1);
82ba1d3f
GR
820 if (err >= 0)
821 i8k_hwmon_flags |= I8K_HWMON_HAVE_FAN2;
949a9d70 822
747bc8b0
PR
823 /* Third fan attributes, if fan status or type is OK */
824 err = i8k_get_fan_status(2);
825 if (err < 0)
826 err = i8k_get_fan_type(2);
827 if (err >= 0)
828 i8k_hwmon_flags |= I8K_HWMON_HAVE_FAN3;
829
9026cae1 830 i8k_hwmon_dev = hwmon_device_register_with_groups(NULL, "dell_smm",
039ae585 831 NULL, i8k_groups);
82ba1d3f
GR
832 if (IS_ERR(i8k_hwmon_dev)) {
833 err = PTR_ERR(i8k_hwmon_dev);
834 i8k_hwmon_dev = NULL;
835 pr_err("hwmon registration failed (%d)\n", err);
836 return err;
837 }
949a9d70 838 return 0;
949a9d70
JD
839}
840
81474fc2 841struct i8k_config_data {
7f69fb03
PR
842 uint fan_mult;
843 uint fan_max;
81474fc2
GR
844};
845
846enum i8k_configs {
7b883446
GR
847 DELL_LATITUDE_D520,
848 DELL_PRECISION_490,
81474fc2 849 DELL_STUDIO,
34ae40f6 850 DELL_XPS,
81474fc2
GR
851};
852
853static const struct i8k_config_data i8k_config_data[] = {
7b883446
GR
854 [DELL_LATITUDE_D520] = {
855 .fan_mult = 1,
856 .fan_max = I8K_FAN_TURBO,
857 },
858 [DELL_PRECISION_490] = {
859 .fan_mult = 1,
860 .fan_max = I8K_FAN_TURBO,
861 },
81474fc2
GR
862 [DELL_STUDIO] = {
863 .fan_mult = 1,
864 .fan_max = I8K_FAN_HIGH,
865 },
34ae40f6 866 [DELL_XPS] = {
81474fc2
GR
867 .fan_mult = 1,
868 .fan_max = I8K_FAN_HIGH,
869 },
870};
871
12186f51 872static struct dmi_system_id i8k_dmi_table[] __initdata = {
e70c9d5e
DT
873 {
874 .ident = "Dell Inspiron",
875 .matches = {
876 DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer"),
877 DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron"),
878 },
879 },
880 {
881 .ident = "Dell Latitude",
882 .matches = {
883 DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer"),
884 DMI_MATCH(DMI_PRODUCT_NAME, "Latitude"),
885 },
886 },
7e0fa31d
DT
887 {
888 .ident = "Dell Inspiron 2",
889 .matches = {
890 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
891 DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron"),
892 },
893 },
7b883446
GR
894 {
895 .ident = "Dell Latitude D520",
896 .matches = {
897 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
898 DMI_MATCH(DMI_PRODUCT_NAME, "Latitude D520"),
899 },
900 .driver_data = (void *)&i8k_config_data[DELL_LATITUDE_D520],
901 },
7e0fa31d
DT
902 {
903 .ident = "Dell Latitude 2",
904 .matches = {
905 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
906 DMI_MATCH(DMI_PRODUCT_NAME, "Latitude"),
907 },
908 },
a9000d03
NW
909 { /* UK Inspiron 6400 */
910 .ident = "Dell Inspiron 3",
911 .matches = {
912 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
913 DMI_MATCH(DMI_PRODUCT_NAME, "MM061"),
914 },
915 },
48103c52
FS
916 {
917 .ident = "Dell Inspiron 3",
918 .matches = {
919 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
920 DMI_MATCH(DMI_PRODUCT_NAME, "MP061"),
921 },
922 },
7b883446
GR
923 {
924 .ident = "Dell Precision 490",
925 .matches = {
926 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
927 DMI_MATCH(DMI_PRODUCT_NAME,
928 "Precision WorkStation 490"),
929 },
930 .driver_data = (void *)&i8k_config_data[DELL_PRECISION_490],
931 },
7ab21a86
AS
932 {
933 .ident = "Dell Precision",
934 .matches = {
935 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
936 DMI_MATCH(DMI_PRODUCT_NAME, "Precision"),
937 },
938 },
bef2a508
FH
939 {
940 .ident = "Dell Vostro",
941 .matches = {
942 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
943 DMI_MATCH(DMI_PRODUCT_NAME, "Vostro"),
944 },
945 },
9aa5b018
AC
946 {
947 .ident = "Dell XPS421",
948 .matches = {
949 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
950 DMI_MATCH(DMI_PRODUCT_NAME, "XPS L421X"),
951 },
952 },
ff457bde
GR
953 {
954 .ident = "Dell Studio",
955 .matches = {
956 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
957 DMI_MATCH(DMI_PRODUCT_NAME, "Studio"),
958 },
81474fc2 959 .driver_data = (void *)&i8k_config_data[DELL_STUDIO],
ff457bde 960 },
34ae40f6
GR
961 {
962 .ident = "Dell XPS 13",
963 .matches = {
964 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
965 DMI_MATCH(DMI_PRODUCT_NAME, "XPS13"),
966 },
967 .driver_data = (void *)&i8k_config_data[DELL_XPS],
968 },
919a0304
GR
969 {
970 .ident = "Dell XPS M140",
971 .matches = {
972 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
973 DMI_MATCH(DMI_PRODUCT_NAME, "MXC051"),
974 },
34ae40f6 975 .driver_data = (void *)&i8k_config_data[DELL_XPS],
919a0304 976 },
12186f51 977 { }
e70c9d5e 978};
1da177e4 979
148b1fda
PR
980MODULE_DEVICE_TABLE(dmi, i8k_dmi_table);
981
2744d2fd
PR
982/*
983 * On some machines once I8K_SMM_GET_FAN_TYPE is issued then CPU fan speed
984 * randomly going up and down due to bug in Dell SMM or BIOS. Here is blacklist
985 * of affected Dell machines for which we disallow I8K_SMM_GET_FAN_TYPE call.
986 * See bug: https://bugzilla.kernel.org/show_bug.cgi?id=100121
987 */
988static struct dmi_system_id i8k_blacklist_fan_type_dmi_table[] __initdata = {
6220f4eb 989 {
6220f4eb
TL
990 .ident = "Dell Studio XPS 8000",
991 .matches = {
992 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
993 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Studio XPS 8000"),
994 },
995 },
a4b45b25 996 {
a4b45b25
PR
997 .ident = "Dell Studio XPS 8100",
998 .matches = {
999 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
1000 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Studio XPS 8100"),
1001 },
1002 },
2744d2fd
PR
1003 {
1004 .ident = "Dell Inspiron 580",
1005 .matches = {
1006 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
1007 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Inspiron 580 "),
1008 },
1009 },
a4b45b25
PR
1010 { }
1011};
1012
1da177e4
LT
1013/*
1014 * Probe for the presence of a supported laptop.
1015 */
1016static int __init i8k_probe(void)
1017{
26d09382 1018 const struct dmi_system_id *id;
8f21d8e9 1019 int fan, ret;
dec63ec3 1020
1da177e4 1021 /*
dec63ec3 1022 * Get DMI information
1da177e4 1023 */
2744d2fd 1024 if (!dmi_check_system(i8k_dmi_table)) {
e70c9d5e
DT
1025 if (!ignore_dmi && !force)
1026 return -ENODEV;
1027
60e71aaf
GR
1028 pr_info("not running on a supported Dell system.\n");
1029 pr_info("vendor=%s, model=%s, version=%s\n",
e70c9d5e
DT
1030 i8k_get_dmi_data(DMI_SYS_VENDOR),
1031 i8k_get_dmi_data(DMI_PRODUCT_NAME),
1032 i8k_get_dmi_data(DMI_BIOS_VERSION));
1da177e4 1033 }
dec63ec3 1034
2744d2fd
PR
1035 if (dmi_check_system(i8k_blacklist_fan_type_dmi_table))
1036 disallow_fan_type_call = true;
1037
12186f51
GR
1038 strlcpy(bios_version, i8k_get_dmi_data(DMI_BIOS_VERSION),
1039 sizeof(bios_version));
7613663c
PR
1040 strlcpy(bios_machineid, i8k_get_dmi_data(DMI_PRODUCT_SERIAL),
1041 sizeof(bios_machineid));
e70c9d5e 1042
1da177e4 1043 /*
dec63ec3 1044 * Get SMM Dell signature
1da177e4 1045 */
7e0fa31d
DT
1046 if (i8k_get_dell_signature(I8K_SMM_GET_DELL_SIG1) &&
1047 i8k_get_dell_signature(I8K_SMM_GET_DELL_SIG2)) {
60e71aaf 1048 pr_err("unable to get SMM Dell signature\n");
e70c9d5e
DT
1049 if (!force)
1050 return -ENODEV;
1da177e4 1051 }
1da177e4 1052
8f21d8e9
PR
1053 /*
1054 * Set fan multiplier and maximal fan speed from dmi config
1055 * Values specified in module parameters override values from dmi
1056 */
26d09382 1057 id = dmi_first_match(i8k_dmi_table);
81474fc2
GR
1058 if (id && id->driver_data) {
1059 const struct i8k_config_data *conf = id->driver_data;
8f21d8e9
PR
1060 if (!fan_mult && conf->fan_mult)
1061 fan_mult = conf->fan_mult;
1062 if (!fan_max && conf->fan_max)
1063 fan_max = conf->fan_max;
81474fc2 1064 }
8f21d8e9
PR
1065
1066 i8k_fan_max = fan_max ? : I8K_FAN_HIGH; /* Must not be 0 */
81474fc2 1067 i8k_pwm_mult = DIV_ROUND_UP(255, i8k_fan_max);
26d09382 1068
8f21d8e9
PR
1069 if (!fan_mult) {
1070 /*
1071 * Autodetect fan multiplier based on nominal rpm
1072 * If fan reports rpm value too high then set multiplier to 1
1073 */
1074 for (fan = 0; fan < 2; ++fan) {
1075 ret = i8k_get_fan_nominal_speed(fan, i8k_fan_max);
1076 if (ret < 0)
1077 continue;
1078 if (ret > I8K_FAN_MAX_RPM)
1079 i8k_fan_mult = 1;
1080 break;
1081 }
1082 } else {
1083 /* Fan multiplier was specified in module param or in dmi */
1084 i8k_fan_mult = fan_mult;
1085 }
1086
dec63ec3 1087 return 0;
1da177e4
LT
1088}
1089
8378b924 1090static int __init i8k_init(void)
1da177e4 1091{
949a9d70 1092 int err;
dec63ec3
DT
1093
1094 /* Are we running on an supported laptop? */
e70c9d5e 1095 if (i8k_probe())
dec63ec3 1096 return -ENODEV;
dec63ec3 1097
949a9d70
JD
1098 err = i8k_init_hwmon();
1099 if (err)
039ae585 1100 return err;
949a9d70 1101
039ae585 1102 i8k_init_procfs();
dec63ec3 1103 return 0;
1da177e4
LT
1104}
1105
8378b924 1106static void __exit i8k_exit(void)
1da177e4 1107{
82ba1d3f 1108 hwmon_device_unregister(i8k_hwmon_dev);
039ae585 1109 i8k_exit_procfs();
1da177e4 1110}
1da177e4 1111
8378b924
DT
1112module_init(i8k_init);
1113module_exit(i8k_exit);
This page took 0.858003 seconds and 5 git commands to generate.