2 * drivers/hwmon/applesmc.c - driver for Apple's SMC (accelerometer, temperature
3 * sensors, fan control, keyboard backlight control) used in Intel-based Apple
6 * Copyright (C) 2007 Nicolas Boichat <nicolas@boichat.ch>
8 * Based on hdaps.c driver:
9 * Copyright (C) 2005 Robert Love <rml@novell.com>
10 * Copyright (C) 2005 Jesper Juhl <jesper.juhl@gmail.com>
12 * Fan control based on smcFanControl:
13 * Copyright (C) 2006 Hendrik Holtmann <holtmann@mac.com>
15 * This program is free software; you can redistribute it and/or modify it
16 * under the terms of the GNU General Public License v2 as published by the
17 * Free Software Foundation.
19 * This program is distributed in the hope that it will be useful, but WITHOUT
20 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
24 * You should have received a copy of the GNU General Public License along with
25 * this program; if not, write to the Free Software Foundation, Inc.,
26 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
29 #include <linux/delay.h>
30 #include <linux/platform_device.h>
31 #include <linux/input-polldev.h>
32 #include <linux/kernel.h>
33 #include <linux/module.h>
34 #include <linux/timer.h>
35 #include <linux/dmi.h>
36 #include <linux/mutex.h>
37 #include <linux/hwmon-sysfs.h>
39 #include <linux/leds.h>
40 #include <linux/hwmon.h>
41 #include <linux/workqueue.h>
43 /* data port used by Apple SMC */
44 #define APPLESMC_DATA_PORT 0x300
45 /* command/status port used by Apple SMC */
46 #define APPLESMC_CMD_PORT 0x304
48 #define APPLESMC_NR_PORTS 32 /* 0x300-0x31f */
50 #define APPLESMC_MAX_DATA_LENGTH 32
52 #define APPLESMC_MIN_WAIT 0x0040
53 #define APPLESMC_MAX_WAIT 0x8000
55 #define APPLESMC_STATUS_MASK 0x0f
56 #define APPLESMC_READ_CMD 0x10
57 #define APPLESMC_WRITE_CMD 0x11
58 #define APPLESMC_GET_KEY_BY_INDEX_CMD 0x12
59 #define APPLESMC_GET_KEY_TYPE_CMD 0x13
61 #define KEY_COUNT_KEY "#KEY" /* r-o ui32 */
63 #define LIGHT_SENSOR_LEFT_KEY "ALV0" /* r-o {alv (6-10 bytes) */
64 #define LIGHT_SENSOR_RIGHT_KEY "ALV1" /* r-o {alv (6-10 bytes) */
65 #define BACKLIGHT_KEY "LKSB" /* w-o {lkb (2 bytes) */
67 #define CLAMSHELL_KEY "MSLD" /* r-o ui8 (unused) */
69 #define MOTION_SENSOR_X_KEY "MO_X" /* r-o sp78 (2 bytes) */
70 #define MOTION_SENSOR_Y_KEY "MO_Y" /* r-o sp78 (2 bytes) */
71 #define MOTION_SENSOR_Z_KEY "MO_Z" /* r-o sp78 (2 bytes) */
72 #define MOTION_SENSOR_KEY "MOCN" /* r/w ui16 */
74 #define FANS_COUNT "FNum" /* r-o ui8 */
75 #define FANS_MANUAL "FS! " /* r-w ui16 */
76 #define FAN_ACTUAL_SPEED "F0Ac" /* r-o fpe2 (2 bytes) */
77 #define FAN_MIN_SPEED "F0Mn" /* r-o fpe2 (2 bytes) */
78 #define FAN_MAX_SPEED "F0Mx" /* r-o fpe2 (2 bytes) */
79 #define FAN_SAFE_SPEED "F0Sf" /* r-o fpe2 (2 bytes) */
80 #define FAN_TARGET_SPEED "F0Tg" /* r-w fpe2 (2 bytes) */
81 #define FAN_POSITION "F0ID" /* r-o char[16] */
84 * Temperature sensors keys (sp78 - 2 bytes).
86 static const char *temperature_sensors_sets
[][41] = {
87 /* Set 0: Macbook Pro */
88 { "TA0P", "TB0T", "TC0D", "TC0P", "TG0H", "TG0P", "TG0T", "Th0H",
89 "Th1H", "Tm0P", "Ts0P", "Ts1P", NULL
},
90 /* Set 1: Macbook2 set */
91 { "TB0T", "TC0D", "TC0P", "TM0P", "TN0P", "TN1P", "TTF0", "Th0H",
92 "Th0S", "Th1H", NULL
},
93 /* Set 2: Macbook set */
94 { "TB0T", "TC0D", "TC0P", "TM0P", "TN0P", "TN1P", "Th0H", "Th0S",
95 "Th1H", "Ts0P", NULL
},
96 /* Set 3: Macmini set */
97 { "TC0D", "TC0P", NULL
},
98 /* Set 4: Mac Pro (2 x Quad-Core) */
99 { "TA0P", "TCAG", "TCAH", "TCBG", "TCBH", "TC0C", "TC0D", "TC0P",
100 "TC1C", "TC1D", "TC2C", "TC2D", "TC3C", "TC3D", "THTG", "TH0P",
101 "TH1P", "TH2P", "TH3P", "TMAP", "TMAS", "TMBS", "TM0P", "TM0S",
102 "TM1P", "TM1S", "TM2P", "TM2S", "TM3S", "TM8P", "TM8S", "TM9P",
103 "TM9S", "TN0H", "TS0C", NULL
},
105 { "TC0D", "TA0P", "TG0P", "TG0D", "TG0H", "TH0P", "Tm0P", "TO0P",
107 /* Set 6: Macbook3 set */
108 { "TB0T", "TC0D", "TC0P", "TM0P", "TN0P", "TTF0", "TW0P", "Th0H",
109 "Th0S", "Th1H", NULL
},
110 /* Set 7: Macbook Air */
111 { "TB0T", "TB1S", "TB1T", "TB2S", "TB2T", "TC0D", "TC0P", "TCFP",
112 "TTF0", "TW0P", "Th0H", "Tp0P", "TpFP", "Ts0P", "Ts0S", NULL
},
113 /* Set 8: Macbook Pro 4,1 (Penryn) */
114 { "TB0T", "TC0D", "TC0P", "TG0D", "TG0H", "TTF0", "TW0P", "Th0H",
115 "Th1H", "Th2H", "Tm0P", "Ts0P", NULL
},
116 /* Set 9: Macbook Pro 3,1 (Santa Rosa) */
117 { "TALP", "TB0T", "TC0D", "TC0P", "TG0D", "TG0H", "TTF0", "TW0P",
118 "Th0H", "Th1H", "Th2H", "Tm0P", "Ts0P", NULL
},
119 /* Set 10: iMac 5,1 */
120 { "TA0P", "TC0D", "TC0P", "TG0D", "TH0P", "TO0P", "Tm0P", NULL
},
121 /* Set 11: Macbook 5,1 */
122 { "TB0T", "TB1T", "TB2T", "TB3T", "TC0D", "TC0P", "TN0D", "TN0P",
123 "TTF0", "Th0H", "Th1H", "ThFH", "Ts0P", "Ts0S", NULL
},
124 /* Set 12: Macbook Pro 5,1 */
125 { "TB0T", "TB1T", "TB2T", "TB3T", "TC0D", "TC0F", "TC0P", "TG0D",
126 "TG0F", "TG0H", "TG0P", "TG0T", "TG1H", "TN0D", "TN0P", "TTF0",
127 "Th2H", "Tm0P", "Ts0P", "Ts0S", NULL
},
128 /* Set 13: iMac 8,1 */
129 { "TA0P", "TC0D", "TC0H", "TC0P", "TG0D", "TG0H", "TG0P", "TH0P",
130 "TL0P", "TO0P", "TW0P", "Tm0P", "Tp0P", NULL
},
131 /* Set 14: iMac 6,1 */
132 { "TA0P", "TC0D", "TC0H", "TC0P", "TG0D", "TG0H", "TG0P", "TH0P",
133 "TO0P", "Tp0P", NULL
},
134 /* Set 15: MacBook Air 2,1 */
135 { "TB0T", "TB1S", "TB1T", "TB2S", "TB2T", "TC0D", "TN0D", "TTF0",
136 "TV0P", "TVFP", "TW0P", "Th0P", "Tp0P", "Tp1P", "TpFP", "Ts0P",
138 /* Set 16: Mac Pro 3,1 (2 x Quad-Core) */
139 { "TA0P", "TCAG", "TCAH", "TCBG", "TCBH", "TC0C", "TC0D", "TC0P",
140 "TC1C", "TC1D", "TC2C", "TC2D", "TC3C", "TC3D", "TH0P", "TH1P",
141 "TH2P", "TH3P", "TMAP", "TMAS", "TMBS", "TM0P", "TM0S", "TM1P",
142 "TM1S", "TM2P", "TM2S", "TM3S", "TM8P", "TM8S", "TM9P", "TM9S",
143 "TN0C", "TN0D", "TN0H", "TS0C", "Tp0C", "Tp1C", "Tv0S", "Tv1S",
147 /* List of keys used to read/write fan speeds */
148 static const char* fan_speed_keys
[] = {
156 #define INIT_TIMEOUT_MSECS 5000 /* wait up to 5s for device init ... */
157 #define INIT_WAIT_MSECS 50 /* ... in 50ms increments */
159 #define APPLESMC_POLL_INTERVAL 50 /* msecs */
160 #define APPLESMC_INPUT_FUZZ 4 /* input event threshold */
161 #define APPLESMC_INPUT_FLAT 4
167 /* Structure to be passed to DMI_MATCH function */
168 struct dmi_match_data
{
169 /* Indicates whether this computer has an accelerometer. */
171 /* Indicates whether this computer has light sensors and keyboard backlight. */
173 /* Indicates which temperature sensors set to use. */
177 static const int debug
;
178 static struct platform_device
*pdev
;
181 static struct device
*hwmon_dev
;
182 static struct input_polled_dev
*applesmc_idev
;
184 /* Indicates whether this computer has an accelerometer. */
185 static unsigned int applesmc_accelerometer
;
187 /* Indicates whether this computer has light sensors and keyboard backlight. */
188 static unsigned int applesmc_light
;
190 /* Indicates which temperature sensors set to use. */
191 static unsigned int applesmc_temperature_set
;
193 static DEFINE_MUTEX(applesmc_lock
);
196 * Last index written to key_at_index sysfs file, and value to use for all other
197 * key_at_index_* sysfs files.
199 static unsigned int key_at_index
;
201 static struct workqueue_struct
*applesmc_led_wq
;
204 * __wait_status - Wait up to 32ms for the status port to get a certain value
205 * (masked with 0x0f), returning zero if the value is obtained. Callers must
206 * hold applesmc_lock.
208 static int __wait_status(u8 val
)
212 val
= val
& APPLESMC_STATUS_MASK
;
214 for (us
= APPLESMC_MIN_WAIT
; us
< APPLESMC_MAX_WAIT
; us
<<= 1) {
216 if ((inb(APPLESMC_CMD_PORT
) & APPLESMC_STATUS_MASK
) == val
) {
219 "Waited %d us for status %x\n",
220 2 * us
- APPLESMC_MIN_WAIT
, val
);
225 printk(KERN_WARNING
"applesmc: wait status failed: %x != %x\n",
226 val
, inb(APPLESMC_CMD_PORT
));
232 * special treatment of command port - on newer macbooks, it seems necessary
233 * to resend the command byte before polling the status again. Callers must
234 * hold applesmc_lock.
236 static int send_command(u8 cmd
)
239 for (us
= APPLESMC_MIN_WAIT
; us
< APPLESMC_MAX_WAIT
; us
<<= 1) {
240 outb(cmd
, APPLESMC_CMD_PORT
);
242 if ((inb(APPLESMC_CMD_PORT
) & APPLESMC_STATUS_MASK
) == 0x0c)
245 printk(KERN_WARNING
"applesmc: command failed: %x -> %x\n",
246 cmd
, inb(APPLESMC_CMD_PORT
));
251 * applesmc_read_key - reads len bytes from a given key, and put them in buffer.
252 * Returns zero on success or a negative error on failure. Callers must
253 * hold applesmc_lock.
255 static int applesmc_read_key(const char* key
, u8
* buffer
, u8 len
)
259 if (len
> APPLESMC_MAX_DATA_LENGTH
) {
260 printk(KERN_ERR
"applesmc_read_key: cannot read more than "
261 "%d bytes\n", APPLESMC_MAX_DATA_LENGTH
);
265 if (send_command(APPLESMC_READ_CMD
))
268 for (i
= 0; i
< 4; i
++) {
269 outb(key
[i
], APPLESMC_DATA_PORT
);
270 if (__wait_status(0x04))
274 printk(KERN_DEBUG
"<%s", key
);
276 outb(len
, APPLESMC_DATA_PORT
);
278 printk(KERN_DEBUG
">%x", len
);
280 for (i
= 0; i
< len
; i
++) {
281 if (__wait_status(0x05))
283 buffer
[i
] = inb(APPLESMC_DATA_PORT
);
285 printk(KERN_DEBUG
"<%x", buffer
[i
]);
288 printk(KERN_DEBUG
"\n");
294 * applesmc_write_key - writes len bytes from buffer to a given key.
295 * Returns zero on success or a negative error on failure. Callers must
296 * hold applesmc_lock.
298 static int applesmc_write_key(const char* key
, u8
* buffer
, u8 len
)
302 if (len
> APPLESMC_MAX_DATA_LENGTH
) {
303 printk(KERN_ERR
"applesmc_write_key: cannot write more than "
304 "%d bytes\n", APPLESMC_MAX_DATA_LENGTH
);
308 if (send_command(APPLESMC_WRITE_CMD
))
311 for (i
= 0; i
< 4; i
++) {
312 outb(key
[i
], APPLESMC_DATA_PORT
);
313 if (__wait_status(0x04))
317 outb(len
, APPLESMC_DATA_PORT
);
319 for (i
= 0; i
< len
; i
++) {
320 if (__wait_status(0x04))
322 outb(buffer
[i
], APPLESMC_DATA_PORT
);
329 * applesmc_get_key_at_index - get key at index, and put the result in key
330 * (char[6]). Returns zero on success or a negative error on failure. Callers
331 * must hold applesmc_lock.
333 static int applesmc_get_key_at_index(int index
, char* key
)
337 readkey
[0] = index
>> 24;
338 readkey
[1] = index
>> 16;
339 readkey
[2] = index
>> 8;
342 if (send_command(APPLESMC_GET_KEY_BY_INDEX_CMD
))
345 for (i
= 0; i
< 4; i
++) {
346 outb(readkey
[i
], APPLESMC_DATA_PORT
);
347 if (__wait_status(0x04))
351 outb(4, APPLESMC_DATA_PORT
);
353 for (i
= 0; i
< 4; i
++) {
354 if (__wait_status(0x05))
356 key
[i
] = inb(APPLESMC_DATA_PORT
);
364 * applesmc_get_key_type - get key type, and put the result in type (char[6]).
365 * Returns zero on success or a negative error on failure. Callers must
366 * hold applesmc_lock.
368 static int applesmc_get_key_type(char* key
, char* type
)
372 if (send_command(APPLESMC_GET_KEY_TYPE_CMD
))
375 for (i
= 0; i
< 4; i
++) {
376 outb(key
[i
], APPLESMC_DATA_PORT
);
377 if (__wait_status(0x04))
381 outb(6, APPLESMC_DATA_PORT
);
383 for (i
= 0; i
< 6; i
++) {
384 if (__wait_status(0x05))
386 type
[i
] = inb(APPLESMC_DATA_PORT
);
394 * applesmc_read_motion_sensor - Read motion sensor (X, Y or Z). Callers must
395 * hold applesmc_lock.
397 static int applesmc_read_motion_sensor(int index
, s16
* value
)
404 ret
= applesmc_read_key(MOTION_SENSOR_X_KEY
, buffer
, 2);
407 ret
= applesmc_read_key(MOTION_SENSOR_Y_KEY
, buffer
, 2);
410 ret
= applesmc_read_key(MOTION_SENSOR_Z_KEY
, buffer
, 2);
416 *value
= ((s16
)buffer
[0] << 8) | buffer
[1];
422 * applesmc_device_init - initialize the accelerometer. Returns zero on success
423 * and negative error code on failure. Can sleep.
425 static int applesmc_device_init(void)
427 int total
, ret
= -ENXIO
;
430 if (!applesmc_accelerometer
)
433 mutex_lock(&applesmc_lock
);
435 for (total
= INIT_TIMEOUT_MSECS
; total
> 0; total
-= INIT_WAIT_MSECS
) {
437 printk(KERN_DEBUG
"applesmc try %d\n", total
);
438 if (!applesmc_read_key(MOTION_SENSOR_KEY
, buffer
, 2) &&
439 (buffer
[0] != 0x00 || buffer
[1] != 0x00)) {
440 if (total
== INIT_TIMEOUT_MSECS
) {
441 printk(KERN_DEBUG
"applesmc: device has"
442 " already been initialized"
443 " (0x%02x, 0x%02x).\n",
444 buffer
[0], buffer
[1]);
446 printk(KERN_DEBUG
"applesmc: device"
447 " successfully initialized"
448 " (0x%02x, 0x%02x).\n",
449 buffer
[0], buffer
[1]);
456 applesmc_write_key(MOTION_SENSOR_KEY
, buffer
, 2);
457 msleep(INIT_WAIT_MSECS
);
460 printk(KERN_WARNING
"applesmc: failed to init the device\n");
463 mutex_unlock(&applesmc_lock
);
468 * applesmc_get_fan_count - get the number of fans. Callers must NOT hold
471 static int applesmc_get_fan_count(void)
476 mutex_lock(&applesmc_lock
);
478 ret
= applesmc_read_key(FANS_COUNT
, buffer
, 1);
480 mutex_unlock(&applesmc_lock
);
487 /* Device model stuff */
488 static int applesmc_probe(struct platform_device
*dev
)
492 ret
= applesmc_device_init();
496 printk(KERN_INFO
"applesmc: device successfully initialized.\n");
500 static int applesmc_resume(struct platform_device
*dev
)
502 return applesmc_device_init();
505 static struct platform_driver applesmc_driver
= {
506 .probe
= applesmc_probe
,
507 .resume
= applesmc_resume
,
510 .owner
= THIS_MODULE
,
515 * applesmc_calibrate - Set our "resting" values. Callers must
516 * hold applesmc_lock.
518 static void applesmc_calibrate(void)
520 applesmc_read_motion_sensor(SENSOR_X
, &rest_x
);
521 applesmc_read_motion_sensor(SENSOR_Y
, &rest_y
);
525 static void applesmc_idev_poll(struct input_polled_dev
*dev
)
527 struct input_dev
*idev
= dev
->input
;
530 mutex_lock(&applesmc_lock
);
532 if (applesmc_read_motion_sensor(SENSOR_X
, &x
))
534 if (applesmc_read_motion_sensor(SENSOR_Y
, &y
))
538 input_report_abs(idev
, ABS_X
, x
- rest_x
);
539 input_report_abs(idev
, ABS_Y
, y
- rest_y
);
543 mutex_unlock(&applesmc_lock
);
548 static ssize_t
applesmc_name_show(struct device
*dev
,
549 struct device_attribute
*attr
, char *buf
)
551 return snprintf(buf
, PAGE_SIZE
, "applesmc\n");
554 static ssize_t
applesmc_position_show(struct device
*dev
,
555 struct device_attribute
*attr
, char *buf
)
560 mutex_lock(&applesmc_lock
);
562 ret
= applesmc_read_motion_sensor(SENSOR_X
, &x
);
565 ret
= applesmc_read_motion_sensor(SENSOR_Y
, &y
);
568 ret
= applesmc_read_motion_sensor(SENSOR_Z
, &z
);
573 mutex_unlock(&applesmc_lock
);
577 return snprintf(buf
, PAGE_SIZE
, "(%d,%d,%d)\n", x
, y
, z
);
580 static ssize_t
applesmc_light_show(struct device
*dev
,
581 struct device_attribute
*attr
, char *sysfsbuf
)
583 static int data_length
;
585 u8 left
= 0, right
= 0;
586 u8 buffer
[10], query
[6];
588 mutex_lock(&applesmc_lock
);
591 ret
= applesmc_get_key_type(LIGHT_SENSOR_LEFT_KEY
, query
);
594 data_length
= clamp_val(query
[0], 0, 10);
595 printk(KERN_INFO
"applesmc: light sensor data length set to "
596 "%d\n", data_length
);
599 ret
= applesmc_read_key(LIGHT_SENSOR_LEFT_KEY
, buffer
, data_length
);
600 /* newer macbooks report a single 10-bit bigendian value */
601 if (data_length
== 10) {
602 left
= be16_to_cpu(*(__be16
*)(buffer
+ 6)) >> 2;
608 ret
= applesmc_read_key(LIGHT_SENSOR_RIGHT_KEY
, buffer
, data_length
);
612 mutex_unlock(&applesmc_lock
);
616 return snprintf(sysfsbuf
, PAGE_SIZE
, "(%d,%d)\n", left
, right
);
619 /* Displays degree Celsius * 1000 */
620 static ssize_t
applesmc_show_temperature(struct device
*dev
,
621 struct device_attribute
*devattr
, char *sysfsbuf
)
626 struct sensor_device_attribute
*attr
= to_sensor_dev_attr(devattr
);
628 temperature_sensors_sets
[applesmc_temperature_set
][attr
->index
];
630 mutex_lock(&applesmc_lock
);
632 ret
= applesmc_read_key(key
, buffer
, 2);
633 temp
= buffer
[0]*1000;
634 temp
+= (buffer
[1] >> 6) * 250;
636 mutex_unlock(&applesmc_lock
);
641 return snprintf(sysfsbuf
, PAGE_SIZE
, "%u\n", temp
);
644 static ssize_t
applesmc_show_fan_speed(struct device
*dev
,
645 struct device_attribute
*attr
, char *sysfsbuf
)
648 unsigned int speed
= 0;
651 struct sensor_device_attribute_2
*sensor_attr
=
652 to_sensor_dev_attr_2(attr
);
654 newkey
[0] = fan_speed_keys
[sensor_attr
->nr
][0];
655 newkey
[1] = '0' + sensor_attr
->index
;
656 newkey
[2] = fan_speed_keys
[sensor_attr
->nr
][2];
657 newkey
[3] = fan_speed_keys
[sensor_attr
->nr
][3];
660 mutex_lock(&applesmc_lock
);
662 ret
= applesmc_read_key(newkey
, buffer
, 2);
663 speed
= ((buffer
[0] << 8 | buffer
[1]) >> 2);
665 mutex_unlock(&applesmc_lock
);
669 return snprintf(sysfsbuf
, PAGE_SIZE
, "%u\n", speed
);
672 static ssize_t
applesmc_store_fan_speed(struct device
*dev
,
673 struct device_attribute
*attr
,
674 const char *sysfsbuf
, size_t count
)
680 struct sensor_device_attribute_2
*sensor_attr
=
681 to_sensor_dev_attr_2(attr
);
683 speed
= simple_strtoul(sysfsbuf
, NULL
, 10);
685 if (speed
> 0x4000) /* Bigger than a 14-bit value */
688 newkey
[0] = fan_speed_keys
[sensor_attr
->nr
][0];
689 newkey
[1] = '0' + sensor_attr
->index
;
690 newkey
[2] = fan_speed_keys
[sensor_attr
->nr
][2];
691 newkey
[3] = fan_speed_keys
[sensor_attr
->nr
][3];
694 mutex_lock(&applesmc_lock
);
696 buffer
[0] = (speed
>> 6) & 0xff;
697 buffer
[1] = (speed
<< 2) & 0xff;
698 ret
= applesmc_write_key(newkey
, buffer
, 2);
700 mutex_unlock(&applesmc_lock
);
707 static ssize_t
applesmc_show_fan_manual(struct device
*dev
,
708 struct device_attribute
*devattr
, char *sysfsbuf
)
713 struct sensor_device_attribute
*attr
= to_sensor_dev_attr(devattr
);
715 mutex_lock(&applesmc_lock
);
717 ret
= applesmc_read_key(FANS_MANUAL
, buffer
, 2);
718 manual
= ((buffer
[0] << 8 | buffer
[1]) >> attr
->index
) & 0x01;
720 mutex_unlock(&applesmc_lock
);
724 return snprintf(sysfsbuf
, PAGE_SIZE
, "%d\n", manual
);
727 static ssize_t
applesmc_store_fan_manual(struct device
*dev
,
728 struct device_attribute
*devattr
,
729 const char *sysfsbuf
, size_t count
)
735 struct sensor_device_attribute
*attr
= to_sensor_dev_attr(devattr
);
737 input
= simple_strtoul(sysfsbuf
, NULL
, 10);
739 mutex_lock(&applesmc_lock
);
741 ret
= applesmc_read_key(FANS_MANUAL
, buffer
, 2);
742 val
= (buffer
[0] << 8 | buffer
[1]);
747 val
= val
| (0x01 << attr
->index
);
749 val
= val
& ~(0x01 << attr
->index
);
751 buffer
[0] = (val
>> 8) & 0xFF;
752 buffer
[1] = val
& 0xFF;
754 ret
= applesmc_write_key(FANS_MANUAL
, buffer
, 2);
757 mutex_unlock(&applesmc_lock
);
764 static ssize_t
applesmc_show_fan_position(struct device
*dev
,
765 struct device_attribute
*attr
, char *sysfsbuf
)
770 struct sensor_device_attribute_2
*sensor_attr
=
771 to_sensor_dev_attr_2(attr
);
773 newkey
[0] = FAN_POSITION
[0];
774 newkey
[1] = '0' + sensor_attr
->index
;
775 newkey
[2] = FAN_POSITION
[2];
776 newkey
[3] = FAN_POSITION
[3];
779 mutex_lock(&applesmc_lock
);
781 ret
= applesmc_read_key(newkey
, buffer
, 16);
784 mutex_unlock(&applesmc_lock
);
788 return snprintf(sysfsbuf
, PAGE_SIZE
, "%s\n", buffer
+4);
791 static ssize_t
applesmc_calibrate_show(struct device
*dev
,
792 struct device_attribute
*attr
, char *sysfsbuf
)
794 return snprintf(sysfsbuf
, PAGE_SIZE
, "(%d,%d)\n", rest_x
, rest_y
);
797 static ssize_t
applesmc_calibrate_store(struct device
*dev
,
798 struct device_attribute
*attr
, const char *sysfsbuf
, size_t count
)
800 mutex_lock(&applesmc_lock
);
801 applesmc_calibrate();
802 mutex_unlock(&applesmc_lock
);
807 /* Store the next backlight value to be written by the work */
808 static unsigned int backlight_value
;
810 static void applesmc_backlight_set(struct work_struct
*work
)
814 mutex_lock(&applesmc_lock
);
815 buffer
[0] = backlight_value
;
817 applesmc_write_key(BACKLIGHT_KEY
, buffer
, 2);
818 mutex_unlock(&applesmc_lock
);
820 static DECLARE_WORK(backlight_work
, &applesmc_backlight_set
);
822 static void applesmc_brightness_set(struct led_classdev
*led_cdev
,
823 enum led_brightness value
)
827 backlight_value
= value
;
828 ret
= queue_work(applesmc_led_wq
, &backlight_work
);
831 printk(KERN_DEBUG
"applesmc: work was already on the queue.\n");
834 static ssize_t
applesmc_key_count_show(struct device
*dev
,
835 struct device_attribute
*attr
, char *sysfsbuf
)
841 mutex_lock(&applesmc_lock
);
843 ret
= applesmc_read_key(KEY_COUNT_KEY
, buffer
, 4);
844 count
= ((u32
)buffer
[0]<<24) + ((u32
)buffer
[1]<<16) +
845 ((u32
)buffer
[2]<<8) + buffer
[3];
847 mutex_unlock(&applesmc_lock
);
851 return snprintf(sysfsbuf
, PAGE_SIZE
, "%d\n", count
);
854 static ssize_t
applesmc_key_at_index_read_show(struct device
*dev
,
855 struct device_attribute
*attr
, char *sysfsbuf
)
861 mutex_lock(&applesmc_lock
);
863 ret
= applesmc_get_key_at_index(key_at_index
, key
);
865 if (ret
|| !key
[0]) {
866 mutex_unlock(&applesmc_lock
);
871 ret
= applesmc_get_key_type(key
, info
);
874 mutex_unlock(&applesmc_lock
);
880 * info[0] maximum value (APPLESMC_MAX_DATA_LENGTH) is much lower than
881 * PAGE_SIZE, so we don't need any checks before writing to sysfsbuf.
883 ret
= applesmc_read_key(key
, sysfsbuf
, info
[0]);
885 mutex_unlock(&applesmc_lock
);
894 static ssize_t
applesmc_key_at_index_data_length_show(struct device
*dev
,
895 struct device_attribute
*attr
, char *sysfsbuf
)
901 mutex_lock(&applesmc_lock
);
903 ret
= applesmc_get_key_at_index(key_at_index
, key
);
905 if (ret
|| !key
[0]) {
906 mutex_unlock(&applesmc_lock
);
911 ret
= applesmc_get_key_type(key
, info
);
913 mutex_unlock(&applesmc_lock
);
916 return snprintf(sysfsbuf
, PAGE_SIZE
, "%d\n", info
[0]);
921 static ssize_t
applesmc_key_at_index_type_show(struct device
*dev
,
922 struct device_attribute
*attr
, char *sysfsbuf
)
928 mutex_lock(&applesmc_lock
);
930 ret
= applesmc_get_key_at_index(key_at_index
, key
);
932 if (ret
|| !key
[0]) {
933 mutex_unlock(&applesmc_lock
);
938 ret
= applesmc_get_key_type(key
, info
);
940 mutex_unlock(&applesmc_lock
);
943 return snprintf(sysfsbuf
, PAGE_SIZE
, "%s\n", info
+1);
948 static ssize_t
applesmc_key_at_index_name_show(struct device
*dev
,
949 struct device_attribute
*attr
, char *sysfsbuf
)
954 mutex_lock(&applesmc_lock
);
956 ret
= applesmc_get_key_at_index(key_at_index
, key
);
958 mutex_unlock(&applesmc_lock
);
961 return snprintf(sysfsbuf
, PAGE_SIZE
, "%s\n", key
);
966 static ssize_t
applesmc_key_at_index_show(struct device
*dev
,
967 struct device_attribute
*attr
, char *sysfsbuf
)
969 return snprintf(sysfsbuf
, PAGE_SIZE
, "%d\n", key_at_index
);
972 static ssize_t
applesmc_key_at_index_store(struct device
*dev
,
973 struct device_attribute
*attr
, const char *sysfsbuf
, size_t count
)
975 mutex_lock(&applesmc_lock
);
977 key_at_index
= simple_strtoul(sysfsbuf
, NULL
, 10);
979 mutex_unlock(&applesmc_lock
);
984 static struct led_classdev applesmc_backlight
= {
985 .name
= "smc::kbd_backlight",
986 .default_trigger
= "nand-disk",
987 .brightness_set
= applesmc_brightness_set
,
990 static DEVICE_ATTR(name
, 0444, applesmc_name_show
, NULL
);
992 static DEVICE_ATTR(position
, 0444, applesmc_position_show
, NULL
);
993 static DEVICE_ATTR(calibrate
, 0644,
994 applesmc_calibrate_show
, applesmc_calibrate_store
);
996 static struct attribute
*accelerometer_attributes
[] = {
997 &dev_attr_position
.attr
,
998 &dev_attr_calibrate
.attr
,
1002 static const struct attribute_group accelerometer_attributes_group
=
1003 { .attrs
= accelerometer_attributes
};
1005 static DEVICE_ATTR(light
, 0444, applesmc_light_show
, NULL
);
1007 static DEVICE_ATTR(key_count
, 0444, applesmc_key_count_show
, NULL
);
1008 static DEVICE_ATTR(key_at_index
, 0644,
1009 applesmc_key_at_index_show
, applesmc_key_at_index_store
);
1010 static DEVICE_ATTR(key_at_index_name
, 0444,
1011 applesmc_key_at_index_name_show
, NULL
);
1012 static DEVICE_ATTR(key_at_index_type
, 0444,
1013 applesmc_key_at_index_type_show
, NULL
);
1014 static DEVICE_ATTR(key_at_index_data_length
, 0444,
1015 applesmc_key_at_index_data_length_show
, NULL
);
1016 static DEVICE_ATTR(key_at_index_data
, 0444,
1017 applesmc_key_at_index_read_show
, NULL
);
1019 static struct attribute
*key_enumeration_attributes
[] = {
1020 &dev_attr_key_count
.attr
,
1021 &dev_attr_key_at_index
.attr
,
1022 &dev_attr_key_at_index_name
.attr
,
1023 &dev_attr_key_at_index_type
.attr
,
1024 &dev_attr_key_at_index_data_length
.attr
,
1025 &dev_attr_key_at_index_data
.attr
,
1029 static const struct attribute_group key_enumeration_group
=
1030 { .attrs
= key_enumeration_attributes
};
1033 * Macro defining SENSOR_DEVICE_ATTR for a fan sysfs entries.
1034 * - show actual speed
1035 * - show/store minimum speed
1036 * - show maximum speed
1038 * - show/store target speed
1039 * - show/store manual mode
1041 #define sysfs_fan_speeds_offset(offset) \
1042 static SENSOR_DEVICE_ATTR_2(fan##offset##_input, S_IRUGO, \
1043 applesmc_show_fan_speed, NULL, 0, offset-1); \
1045 static SENSOR_DEVICE_ATTR_2(fan##offset##_min, S_IRUGO | S_IWUSR, \
1046 applesmc_show_fan_speed, applesmc_store_fan_speed, 1, offset-1); \
1048 static SENSOR_DEVICE_ATTR_2(fan##offset##_max, S_IRUGO, \
1049 applesmc_show_fan_speed, NULL, 2, offset-1); \
1051 static SENSOR_DEVICE_ATTR_2(fan##offset##_safe, S_IRUGO, \
1052 applesmc_show_fan_speed, NULL, 3, offset-1); \
1054 static SENSOR_DEVICE_ATTR_2(fan##offset##_output, S_IRUGO | S_IWUSR, \
1055 applesmc_show_fan_speed, applesmc_store_fan_speed, 4, offset-1); \
1057 static SENSOR_DEVICE_ATTR(fan##offset##_manual, S_IRUGO | S_IWUSR, \
1058 applesmc_show_fan_manual, applesmc_store_fan_manual, offset-1); \
1060 static SENSOR_DEVICE_ATTR(fan##offset##_label, S_IRUGO, \
1061 applesmc_show_fan_position, NULL, offset-1); \
1063 static struct attribute *fan##offset##_attributes[] = { \
1064 &sensor_dev_attr_fan##offset##_input.dev_attr.attr, \
1065 &sensor_dev_attr_fan##offset##_min.dev_attr.attr, \
1066 &sensor_dev_attr_fan##offset##_max.dev_attr.attr, \
1067 &sensor_dev_attr_fan##offset##_safe.dev_attr.attr, \
1068 &sensor_dev_attr_fan##offset##_output.dev_attr.attr, \
1069 &sensor_dev_attr_fan##offset##_manual.dev_attr.attr, \
1070 &sensor_dev_attr_fan##offset##_label.dev_attr.attr, \
1075 * Create the needed functions for each fan using the macro defined above
1076 * (4 fans are supported)
1078 sysfs_fan_speeds_offset(1);
1079 sysfs_fan_speeds_offset(2);
1080 sysfs_fan_speeds_offset(3);
1081 sysfs_fan_speeds_offset(4);
1083 static const struct attribute_group fan_attribute_groups
[] = {
1084 { .attrs
= fan1_attributes
},
1085 { .attrs
= fan2_attributes
},
1086 { .attrs
= fan3_attributes
},
1087 { .attrs
= fan4_attributes
},
1091 * Temperature sensors sysfs entries.
1093 static SENSOR_DEVICE_ATTR(temp1_input
, S_IRUGO
,
1094 applesmc_show_temperature
, NULL
, 0);
1095 static SENSOR_DEVICE_ATTR(temp2_input
, S_IRUGO
,
1096 applesmc_show_temperature
, NULL
, 1);
1097 static SENSOR_DEVICE_ATTR(temp3_input
, S_IRUGO
,
1098 applesmc_show_temperature
, NULL
, 2);
1099 static SENSOR_DEVICE_ATTR(temp4_input
, S_IRUGO
,
1100 applesmc_show_temperature
, NULL
, 3);
1101 static SENSOR_DEVICE_ATTR(temp5_input
, S_IRUGO
,
1102 applesmc_show_temperature
, NULL
, 4);
1103 static SENSOR_DEVICE_ATTR(temp6_input
, S_IRUGO
,
1104 applesmc_show_temperature
, NULL
, 5);
1105 static SENSOR_DEVICE_ATTR(temp7_input
, S_IRUGO
,
1106 applesmc_show_temperature
, NULL
, 6);
1107 static SENSOR_DEVICE_ATTR(temp8_input
, S_IRUGO
,
1108 applesmc_show_temperature
, NULL
, 7);
1109 static SENSOR_DEVICE_ATTR(temp9_input
, S_IRUGO
,
1110 applesmc_show_temperature
, NULL
, 8);
1111 static SENSOR_DEVICE_ATTR(temp10_input
, S_IRUGO
,
1112 applesmc_show_temperature
, NULL
, 9);
1113 static SENSOR_DEVICE_ATTR(temp11_input
, S_IRUGO
,
1114 applesmc_show_temperature
, NULL
, 10);
1115 static SENSOR_DEVICE_ATTR(temp12_input
, S_IRUGO
,
1116 applesmc_show_temperature
, NULL
, 11);
1117 static SENSOR_DEVICE_ATTR(temp13_input
, S_IRUGO
,
1118 applesmc_show_temperature
, NULL
, 12);
1119 static SENSOR_DEVICE_ATTR(temp14_input
, S_IRUGO
,
1120 applesmc_show_temperature
, NULL
, 13);
1121 static SENSOR_DEVICE_ATTR(temp15_input
, S_IRUGO
,
1122 applesmc_show_temperature
, NULL
, 14);
1123 static SENSOR_DEVICE_ATTR(temp16_input
, S_IRUGO
,
1124 applesmc_show_temperature
, NULL
, 15);
1125 static SENSOR_DEVICE_ATTR(temp17_input
, S_IRUGO
,
1126 applesmc_show_temperature
, NULL
, 16);
1127 static SENSOR_DEVICE_ATTR(temp18_input
, S_IRUGO
,
1128 applesmc_show_temperature
, NULL
, 17);
1129 static SENSOR_DEVICE_ATTR(temp19_input
, S_IRUGO
,
1130 applesmc_show_temperature
, NULL
, 18);
1131 static SENSOR_DEVICE_ATTR(temp20_input
, S_IRUGO
,
1132 applesmc_show_temperature
, NULL
, 19);
1133 static SENSOR_DEVICE_ATTR(temp21_input
, S_IRUGO
,
1134 applesmc_show_temperature
, NULL
, 20);
1135 static SENSOR_DEVICE_ATTR(temp22_input
, S_IRUGO
,
1136 applesmc_show_temperature
, NULL
, 21);
1137 static SENSOR_DEVICE_ATTR(temp23_input
, S_IRUGO
,
1138 applesmc_show_temperature
, NULL
, 22);
1139 static SENSOR_DEVICE_ATTR(temp24_input
, S_IRUGO
,
1140 applesmc_show_temperature
, NULL
, 23);
1141 static SENSOR_DEVICE_ATTR(temp25_input
, S_IRUGO
,
1142 applesmc_show_temperature
, NULL
, 24);
1143 static SENSOR_DEVICE_ATTR(temp26_input
, S_IRUGO
,
1144 applesmc_show_temperature
, NULL
, 25);
1145 static SENSOR_DEVICE_ATTR(temp27_input
, S_IRUGO
,
1146 applesmc_show_temperature
, NULL
, 26);
1147 static SENSOR_DEVICE_ATTR(temp28_input
, S_IRUGO
,
1148 applesmc_show_temperature
, NULL
, 27);
1149 static SENSOR_DEVICE_ATTR(temp29_input
, S_IRUGO
,
1150 applesmc_show_temperature
, NULL
, 28);
1151 static SENSOR_DEVICE_ATTR(temp30_input
, S_IRUGO
,
1152 applesmc_show_temperature
, NULL
, 29);
1153 static SENSOR_DEVICE_ATTR(temp31_input
, S_IRUGO
,
1154 applesmc_show_temperature
, NULL
, 30);
1155 static SENSOR_DEVICE_ATTR(temp32_input
, S_IRUGO
,
1156 applesmc_show_temperature
, NULL
, 31);
1157 static SENSOR_DEVICE_ATTR(temp33_input
, S_IRUGO
,
1158 applesmc_show_temperature
, NULL
, 32);
1159 static SENSOR_DEVICE_ATTR(temp34_input
, S_IRUGO
,
1160 applesmc_show_temperature
, NULL
, 33);
1161 static SENSOR_DEVICE_ATTR(temp35_input
, S_IRUGO
,
1162 applesmc_show_temperature
, NULL
, 34);
1163 static SENSOR_DEVICE_ATTR(temp36_input
, S_IRUGO
,
1164 applesmc_show_temperature
, NULL
, 35);
1165 static SENSOR_DEVICE_ATTR(temp37_input
, S_IRUGO
,
1166 applesmc_show_temperature
, NULL
, 36);
1167 static SENSOR_DEVICE_ATTR(temp38_input
, S_IRUGO
,
1168 applesmc_show_temperature
, NULL
, 37);
1169 static SENSOR_DEVICE_ATTR(temp39_input
, S_IRUGO
,
1170 applesmc_show_temperature
, NULL
, 38);
1171 static SENSOR_DEVICE_ATTR(temp40_input
, S_IRUGO
,
1172 applesmc_show_temperature
, NULL
, 39);
1174 static struct attribute
*temperature_attributes
[] = {
1175 &sensor_dev_attr_temp1_input
.dev_attr
.attr
,
1176 &sensor_dev_attr_temp2_input
.dev_attr
.attr
,
1177 &sensor_dev_attr_temp3_input
.dev_attr
.attr
,
1178 &sensor_dev_attr_temp4_input
.dev_attr
.attr
,
1179 &sensor_dev_attr_temp5_input
.dev_attr
.attr
,
1180 &sensor_dev_attr_temp6_input
.dev_attr
.attr
,
1181 &sensor_dev_attr_temp7_input
.dev_attr
.attr
,
1182 &sensor_dev_attr_temp8_input
.dev_attr
.attr
,
1183 &sensor_dev_attr_temp9_input
.dev_attr
.attr
,
1184 &sensor_dev_attr_temp10_input
.dev_attr
.attr
,
1185 &sensor_dev_attr_temp11_input
.dev_attr
.attr
,
1186 &sensor_dev_attr_temp12_input
.dev_attr
.attr
,
1187 &sensor_dev_attr_temp13_input
.dev_attr
.attr
,
1188 &sensor_dev_attr_temp14_input
.dev_attr
.attr
,
1189 &sensor_dev_attr_temp15_input
.dev_attr
.attr
,
1190 &sensor_dev_attr_temp16_input
.dev_attr
.attr
,
1191 &sensor_dev_attr_temp17_input
.dev_attr
.attr
,
1192 &sensor_dev_attr_temp18_input
.dev_attr
.attr
,
1193 &sensor_dev_attr_temp19_input
.dev_attr
.attr
,
1194 &sensor_dev_attr_temp20_input
.dev_attr
.attr
,
1195 &sensor_dev_attr_temp21_input
.dev_attr
.attr
,
1196 &sensor_dev_attr_temp22_input
.dev_attr
.attr
,
1197 &sensor_dev_attr_temp23_input
.dev_attr
.attr
,
1198 &sensor_dev_attr_temp24_input
.dev_attr
.attr
,
1199 &sensor_dev_attr_temp25_input
.dev_attr
.attr
,
1200 &sensor_dev_attr_temp26_input
.dev_attr
.attr
,
1201 &sensor_dev_attr_temp27_input
.dev_attr
.attr
,
1202 &sensor_dev_attr_temp28_input
.dev_attr
.attr
,
1203 &sensor_dev_attr_temp29_input
.dev_attr
.attr
,
1204 &sensor_dev_attr_temp30_input
.dev_attr
.attr
,
1205 &sensor_dev_attr_temp31_input
.dev_attr
.attr
,
1206 &sensor_dev_attr_temp32_input
.dev_attr
.attr
,
1207 &sensor_dev_attr_temp33_input
.dev_attr
.attr
,
1208 &sensor_dev_attr_temp34_input
.dev_attr
.attr
,
1209 &sensor_dev_attr_temp35_input
.dev_attr
.attr
,
1210 &sensor_dev_attr_temp36_input
.dev_attr
.attr
,
1211 &sensor_dev_attr_temp37_input
.dev_attr
.attr
,
1212 &sensor_dev_attr_temp38_input
.dev_attr
.attr
,
1213 &sensor_dev_attr_temp39_input
.dev_attr
.attr
,
1214 &sensor_dev_attr_temp40_input
.dev_attr
.attr
,
1218 static const struct attribute_group temperature_attributes_group
=
1219 { .attrs
= temperature_attributes
};
1224 * applesmc_dmi_match - found a match. return one, short-circuiting the hunt.
1226 static int applesmc_dmi_match(const struct dmi_system_id
*id
)
1229 struct dmi_match_data
* dmi_data
= id
->driver_data
;
1230 printk(KERN_INFO
"applesmc: %s detected:\n", id
->ident
);
1231 applesmc_accelerometer
= dmi_data
->accelerometer
;
1232 printk(KERN_INFO
"applesmc: - Model %s accelerometer\n",
1233 applesmc_accelerometer
? "with" : "without");
1234 applesmc_light
= dmi_data
->light
;
1235 printk(KERN_INFO
"applesmc: - Model %s light sensors and backlight\n",
1236 applesmc_light
? "with" : "without");
1238 applesmc_temperature_set
= dmi_data
->temperature_set
;
1239 while (temperature_sensors_sets
[applesmc_temperature_set
][i
] != NULL
)
1241 printk(KERN_INFO
"applesmc: - Model with %d temperature sensors\n", i
);
1245 /* Create accelerometer ressources */
1246 static int applesmc_create_accelerometer(void)
1248 struct input_dev
*idev
;
1251 ret
= sysfs_create_group(&pdev
->dev
.kobj
,
1252 &accelerometer_attributes_group
);
1256 applesmc_idev
= input_allocate_polled_device();
1257 if (!applesmc_idev
) {
1262 applesmc_idev
->poll
= applesmc_idev_poll
;
1263 applesmc_idev
->poll_interval
= APPLESMC_POLL_INTERVAL
;
1265 /* initial calibrate for the input device */
1266 applesmc_calibrate();
1268 /* initialize the input device */
1269 idev
= applesmc_idev
->input
;
1270 idev
->name
= "applesmc";
1271 idev
->id
.bustype
= BUS_HOST
;
1272 idev
->dev
.parent
= &pdev
->dev
;
1273 idev
->evbit
[0] = BIT_MASK(EV_ABS
);
1274 input_set_abs_params(idev
, ABS_X
,
1275 -256, 256, APPLESMC_INPUT_FUZZ
, APPLESMC_INPUT_FLAT
);
1276 input_set_abs_params(idev
, ABS_Y
,
1277 -256, 256, APPLESMC_INPUT_FUZZ
, APPLESMC_INPUT_FLAT
);
1279 ret
= input_register_polled_device(applesmc_idev
);
1286 input_free_polled_device(applesmc_idev
);
1289 sysfs_remove_group(&pdev
->dev
.kobj
, &accelerometer_attributes_group
);
1292 printk(KERN_WARNING
"applesmc: driver init failed (ret=%d)!\n", ret
);
1296 /* Release all ressources used by the accelerometer */
1297 static void applesmc_release_accelerometer(void)
1299 input_unregister_polled_device(applesmc_idev
);
1300 input_free_polled_device(applesmc_idev
);
1301 sysfs_remove_group(&pdev
->dev
.kobj
, &accelerometer_attributes_group
);
1304 static __initdata
struct dmi_match_data applesmc_dmi_data
[] = {
1305 /* MacBook Pro: accelerometer, backlight and temperature set 0 */
1306 { .accelerometer
= 1, .light
= 1, .temperature_set
= 0 },
1307 /* MacBook2: accelerometer and temperature set 1 */
1308 { .accelerometer
= 1, .light
= 0, .temperature_set
= 1 },
1309 /* MacBook: accelerometer and temperature set 2 */
1310 { .accelerometer
= 1, .light
= 0, .temperature_set
= 2 },
1311 /* MacMini: temperature set 3 */
1312 { .accelerometer
= 0, .light
= 0, .temperature_set
= 3 },
1313 /* MacPro: temperature set 4 */
1314 { .accelerometer
= 0, .light
= 0, .temperature_set
= 4 },
1315 /* iMac: temperature set 5 */
1316 { .accelerometer
= 0, .light
= 0, .temperature_set
= 5 },
1317 /* MacBook3, MacBook4: accelerometer and temperature set 6 */
1318 { .accelerometer
= 1, .light
= 0, .temperature_set
= 6 },
1319 /* MacBook Air: accelerometer, backlight and temperature set 7 */
1320 { .accelerometer
= 1, .light
= 1, .temperature_set
= 7 },
1321 /* MacBook Pro 4: accelerometer, backlight and temperature set 8 */
1322 { .accelerometer
= 1, .light
= 1, .temperature_set
= 8 },
1323 /* MacBook Pro 3: accelerometer, backlight and temperature set 9 */
1324 { .accelerometer
= 1, .light
= 1, .temperature_set
= 9 },
1325 /* iMac 5: light sensor only, temperature set 10 */
1326 { .accelerometer
= 0, .light
= 0, .temperature_set
= 10 },
1327 /* MacBook 5: accelerometer, backlight and temperature set 11 */
1328 { .accelerometer
= 1, .light
= 1, .temperature_set
= 11 },
1329 /* MacBook Pro 5: accelerometer, backlight and temperature set 12 */
1330 { .accelerometer
= 1, .light
= 1, .temperature_set
= 12 },
1331 /* iMac 8: light sensor only, temperature set 13 */
1332 { .accelerometer
= 0, .light
= 0, .temperature_set
= 13 },
1333 /* iMac 6: light sensor only, temperature set 14 */
1334 { .accelerometer
= 0, .light
= 0, .temperature_set
= 14 },
1335 /* MacBook Air 2,1: accelerometer, backlight and temperature set 15 */
1336 { .accelerometer
= 1, .light
= 1, .temperature_set
= 15 },
1337 /* MacPro3,1: temperature set 16 */
1338 { .accelerometer
= 0, .light
= 0, .temperature_set
= 16 },
1341 /* Note that DMI_MATCH(...,"MacBook") will match "MacBookPro1,1".
1342 * So we need to put "Apple MacBook Pro" before "Apple MacBook". */
1343 static __initdata
struct dmi_system_id applesmc_whitelist
[] = {
1344 { applesmc_dmi_match
, "Apple MacBook Air 2", {
1345 DMI_MATCH(DMI_BOARD_VENDOR
, "Apple"),
1346 DMI_MATCH(DMI_PRODUCT_NAME
, "MacBookAir2") },
1347 &applesmc_dmi_data
[15]},
1348 { applesmc_dmi_match
, "Apple MacBook Air", {
1349 DMI_MATCH(DMI_BOARD_VENDOR
, "Apple"),
1350 DMI_MATCH(DMI_PRODUCT_NAME
, "MacBookAir") },
1351 &applesmc_dmi_data
[7]},
1352 { applesmc_dmi_match
, "Apple MacBook Pro 5", {
1353 DMI_MATCH(DMI_BOARD_VENDOR
, "Apple"),
1354 DMI_MATCH(DMI_PRODUCT_NAME
, "MacBookPro5") },
1355 &applesmc_dmi_data
[12]},
1356 { applesmc_dmi_match
, "Apple MacBook Pro 4", {
1357 DMI_MATCH(DMI_BOARD_VENDOR
, "Apple"),
1358 DMI_MATCH(DMI_PRODUCT_NAME
, "MacBookPro4") },
1359 &applesmc_dmi_data
[8]},
1360 { applesmc_dmi_match
, "Apple MacBook Pro 3", {
1361 DMI_MATCH(DMI_BOARD_VENDOR
, "Apple"),
1362 DMI_MATCH(DMI_PRODUCT_NAME
, "MacBookPro3") },
1363 &applesmc_dmi_data
[9]},
1364 { applesmc_dmi_match
, "Apple MacBook Pro", {
1365 DMI_MATCH(DMI_BOARD_VENDOR
,"Apple"),
1366 DMI_MATCH(DMI_PRODUCT_NAME
,"MacBookPro") },
1367 &applesmc_dmi_data
[0]},
1368 { applesmc_dmi_match
, "Apple MacBook (v2)", {
1369 DMI_MATCH(DMI_BOARD_VENDOR
,"Apple"),
1370 DMI_MATCH(DMI_PRODUCT_NAME
,"MacBook2") },
1371 &applesmc_dmi_data
[1]},
1372 { applesmc_dmi_match
, "Apple MacBook (v3)", {
1373 DMI_MATCH(DMI_BOARD_VENDOR
,"Apple"),
1374 DMI_MATCH(DMI_PRODUCT_NAME
,"MacBook3") },
1375 &applesmc_dmi_data
[6]},
1376 { applesmc_dmi_match
, "Apple MacBook 4", {
1377 DMI_MATCH(DMI_BOARD_VENDOR
, "Apple"),
1378 DMI_MATCH(DMI_PRODUCT_NAME
, "MacBook4") },
1379 &applesmc_dmi_data
[6]},
1380 { applesmc_dmi_match
, "Apple MacBook 5", {
1381 DMI_MATCH(DMI_BOARD_VENDOR
, "Apple"),
1382 DMI_MATCH(DMI_PRODUCT_NAME
, "MacBook5") },
1383 &applesmc_dmi_data
[11]},
1384 { applesmc_dmi_match
, "Apple MacBook", {
1385 DMI_MATCH(DMI_BOARD_VENDOR
,"Apple"),
1386 DMI_MATCH(DMI_PRODUCT_NAME
,"MacBook") },
1387 &applesmc_dmi_data
[2]},
1388 { applesmc_dmi_match
, "Apple Macmini", {
1389 DMI_MATCH(DMI_BOARD_VENDOR
,"Apple"),
1390 DMI_MATCH(DMI_PRODUCT_NAME
,"Macmini") },
1391 &applesmc_dmi_data
[3]},
1392 { applesmc_dmi_match
, "Apple MacPro2", {
1393 DMI_MATCH(DMI_BOARD_VENDOR
,"Apple"),
1394 DMI_MATCH(DMI_PRODUCT_NAME
,"MacPro2") },
1395 &applesmc_dmi_data
[4]},
1396 { applesmc_dmi_match
, "Apple MacPro3", {
1397 DMI_MATCH(DMI_BOARD_VENDOR
, "Apple"),
1398 DMI_MATCH(DMI_PRODUCT_NAME
, "MacPro3") },
1399 &applesmc_dmi_data
[16]},
1400 { applesmc_dmi_match
, "Apple MacPro", {
1401 DMI_MATCH(DMI_BOARD_VENDOR
, "Apple"),
1402 DMI_MATCH(DMI_PRODUCT_NAME
, "MacPro") },
1403 &applesmc_dmi_data
[4]},
1404 { applesmc_dmi_match
, "Apple iMac 8", {
1405 DMI_MATCH(DMI_BOARD_VENDOR
, "Apple"),
1406 DMI_MATCH(DMI_PRODUCT_NAME
, "iMac8") },
1407 &applesmc_dmi_data
[13]},
1408 { applesmc_dmi_match
, "Apple iMac 6", {
1409 DMI_MATCH(DMI_BOARD_VENDOR
, "Apple"),
1410 DMI_MATCH(DMI_PRODUCT_NAME
, "iMac6") },
1411 &applesmc_dmi_data
[14]},
1412 { applesmc_dmi_match
, "Apple iMac 5", {
1413 DMI_MATCH(DMI_BOARD_VENDOR
, "Apple"),
1414 DMI_MATCH(DMI_PRODUCT_NAME
, "iMac5") },
1415 &applesmc_dmi_data
[10]},
1416 { applesmc_dmi_match
, "Apple iMac", {
1417 DMI_MATCH(DMI_BOARD_VENDOR
,"Apple"),
1418 DMI_MATCH(DMI_PRODUCT_NAME
,"iMac") },
1419 &applesmc_dmi_data
[5]},
1423 static int __init
applesmc_init(void)
1429 if (!dmi_check_system(applesmc_whitelist
)) {
1430 printk(KERN_WARNING
"applesmc: supported laptop not found!\n");
1435 if (!request_region(APPLESMC_DATA_PORT
, APPLESMC_NR_PORTS
,
1441 ret
= platform_driver_register(&applesmc_driver
);
1445 pdev
= platform_device_register_simple("applesmc", APPLESMC_DATA_PORT
,
1448 ret
= PTR_ERR(pdev
);
1452 ret
= sysfs_create_file(&pdev
->dev
.kobj
, &dev_attr_name
.attr
);
1456 /* Create key enumeration sysfs files */
1457 ret
= sysfs_create_group(&pdev
->dev
.kobj
, &key_enumeration_group
);
1461 /* create fan files */
1462 count
= applesmc_get_fan_count();
1464 printk(KERN_ERR
"applesmc: Cannot get the number of fans.\n");
1466 printk(KERN_INFO
"applesmc: %d fans found.\n", count
);
1470 printk(KERN_WARNING
"applesmc: More than 4 fans found,"
1471 " but at most 4 fans are supported"
1472 " by the driver.\n");
1474 ret
= sysfs_create_group(&pdev
->dev
.kobj
,
1475 &fan_attribute_groups
[3]);
1477 goto out_key_enumeration
;
1479 ret
= sysfs_create_group(&pdev
->dev
.kobj
,
1480 &fan_attribute_groups
[2]);
1482 goto out_key_enumeration
;
1484 ret
= sysfs_create_group(&pdev
->dev
.kobj
,
1485 &fan_attribute_groups
[1]);
1487 goto out_key_enumeration
;
1489 ret
= sysfs_create_group(&pdev
->dev
.kobj
,
1490 &fan_attribute_groups
[0]);
1499 temperature_sensors_sets
[applesmc_temperature_set
][i
] != NULL
;
1501 if (temperature_attributes
[i
] == NULL
) {
1502 printk(KERN_ERR
"applesmc: More temperature sensors "
1503 "in temperature_sensors_sets (at least %i)"
1504 "than available sysfs files in "
1505 "temperature_attributes (%i), please report "
1506 "this bug.\n", i
, i
-1);
1507 goto out_temperature
;
1509 ret
= sysfs_create_file(&pdev
->dev
.kobj
,
1510 temperature_attributes
[i
]);
1512 goto out_temperature
;
1515 if (applesmc_accelerometer
) {
1516 ret
= applesmc_create_accelerometer();
1518 goto out_temperature
;
1521 if (applesmc_light
) {
1522 /* Add light sensor file */
1523 ret
= sysfs_create_file(&pdev
->dev
.kobj
, &dev_attr_light
.attr
);
1525 goto out_accelerometer
;
1527 /* Create the workqueue */
1528 applesmc_led_wq
= create_singlethread_workqueue("applesmc-led");
1529 if (!applesmc_led_wq
) {
1531 goto out_light_sysfs
;
1534 /* register as a led device */
1535 ret
= led_classdev_register(&pdev
->dev
, &applesmc_backlight
);
1540 hwmon_dev
= hwmon_device_register(&pdev
->dev
);
1541 if (IS_ERR(hwmon_dev
)) {
1542 ret
= PTR_ERR(hwmon_dev
);
1543 goto out_light_ledclass
;
1546 printk(KERN_INFO
"applesmc: driver successfully loaded.\n");
1552 led_classdev_unregister(&applesmc_backlight
);
1555 destroy_workqueue(applesmc_led_wq
);
1558 sysfs_remove_file(&pdev
->dev
.kobj
, &dev_attr_light
.attr
);
1560 if (applesmc_accelerometer
)
1561 applesmc_release_accelerometer();
1563 sysfs_remove_group(&pdev
->dev
.kobj
, &temperature_attributes_group
);
1564 sysfs_remove_group(&pdev
->dev
.kobj
, &fan_attribute_groups
[0]);
1566 sysfs_remove_group(&pdev
->dev
.kobj
, &fan_attribute_groups
[1]);
1567 out_key_enumeration
:
1568 sysfs_remove_group(&pdev
->dev
.kobj
, &key_enumeration_group
);
1570 sysfs_remove_file(&pdev
->dev
.kobj
, &dev_attr_name
.attr
);
1572 platform_device_unregister(pdev
);
1574 platform_driver_unregister(&applesmc_driver
);
1576 release_region(APPLESMC_DATA_PORT
, APPLESMC_NR_PORTS
);
1578 printk(KERN_WARNING
"applesmc: driver init failed (ret=%d)!\n", ret
);
1582 static void __exit
applesmc_exit(void)
1584 hwmon_device_unregister(hwmon_dev
);
1585 if (applesmc_light
) {
1586 led_classdev_unregister(&applesmc_backlight
);
1587 destroy_workqueue(applesmc_led_wq
);
1588 sysfs_remove_file(&pdev
->dev
.kobj
, &dev_attr_light
.attr
);
1590 if (applesmc_accelerometer
)
1591 applesmc_release_accelerometer();
1592 sysfs_remove_group(&pdev
->dev
.kobj
, &temperature_attributes_group
);
1593 sysfs_remove_group(&pdev
->dev
.kobj
, &fan_attribute_groups
[0]);
1594 sysfs_remove_group(&pdev
->dev
.kobj
, &fan_attribute_groups
[1]);
1595 sysfs_remove_group(&pdev
->dev
.kobj
, &key_enumeration_group
);
1596 sysfs_remove_file(&pdev
->dev
.kobj
, &dev_attr_name
.attr
);
1597 platform_device_unregister(pdev
);
1598 platform_driver_unregister(&applesmc_driver
);
1599 release_region(APPLESMC_DATA_PORT
, APPLESMC_NR_PORTS
);
1601 printk(KERN_INFO
"applesmc: driver unloaded.\n");
1604 module_init(applesmc_init
);
1605 module_exit(applesmc_exit
);
1607 MODULE_AUTHOR("Nicolas Boichat");
1608 MODULE_DESCRIPTION("Apple SMC");
1609 MODULE_LICENSE("GPL v2");
1610 MODULE_DEVICE_TABLE(dmi
, applesmc_whitelist
);