m68k: amiga - Zorro host bridge platform device conversion
[linux-2.6-block.git] / drivers / hwmon / applesmc.c
CommitLineData
6f2fad74
NB
1/*
2 * drivers/hwmon/applesmc.c - driver for Apple's SMC (accelerometer, temperature
3 * sensors, fan control, keyboard backlight control) used in Intel-based Apple
4 * computers.
5 *
6 * Copyright (C) 2007 Nicolas Boichat <nicolas@boichat.ch>
7 *
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>
11 *
12 * Fan control based on smcFanControl:
13 * Copyright (C) 2006 Hendrik Holtmann <holtmann@mac.com>
14 *
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.
18 *
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
22 * more details.
23 *
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
27 */
28
29#include <linux/delay.h>
30#include <linux/platform_device.h>
d5cf2b99 31#include <linux/input-polldev.h>
6f2fad74
NB
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>
6055fae8 38#include <linux/io.h>
6f2fad74
NB
39#include <linux/leds.h>
40#include <linux/hwmon.h>
41#include <linux/workqueue.h>
42
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
47
48#define APPLESMC_NR_PORTS 32 /* 0x300-0x31f */
49
50#define APPLESMC_MAX_DATA_LENGTH 32
51
8c9398d1
HR
52#define APPLESMC_MIN_WAIT 0x0040
53#define APPLESMC_MAX_WAIT 0x8000
54
6f2fad74
NB
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
60
61#define KEY_COUNT_KEY "#KEY" /* r-o ui32 */
62
8bd1a12a
HR
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) */
d5cf2b99 65#define BACKLIGHT_KEY "LKSB" /* w-o {lkb (2 bytes) */
6f2fad74 66
d5cf2b99 67#define CLAMSHELL_KEY "MSLD" /* r-o ui8 (unused) */
6f2fad74
NB
68
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 */
73
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] */
82
83/*
84 * Temperature sensors keys (sp78 - 2 bytes).
6f2fad74 85 */
fb9f88e1 86static const char *temperature_sensors_sets[][41] = {
1bed24b9 87/* Set 0: Macbook Pro */
6f2fad74
NB
88 { "TA0P", "TB0T", "TC0D", "TC0P", "TG0H", "TG0P", "TG0T", "Th0H",
89 "Th1H", "Tm0P", "Ts0P", "Ts1P", NULL },
cd19ba13
RO
90/* Set 1: Macbook2 set */
91 { "TB0T", "TC0D", "TC0P", "TM0P", "TN0P", "TN1P", "TTF0", "Th0H",
92 "Th0S", "Th1H", NULL },
93/* Set 2: Macbook set */
1bed24b9
MS
94 { "TB0T", "TC0D", "TC0P", "TM0P", "TN0P", "TN1P", "Th0H", "Th0S",
95 "Th1H", "Ts0P", NULL },
cd19ba13 96/* Set 3: Macmini set */
8de57709 97 { "TC0D", "TC0P", NULL },
cd19ba13 98/* Set 4: Mac Pro (2 x Quad-Core) */
8de57709
RR
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 },
9f86f28d
RDI
104/* Set 5: iMac */
105 { "TC0D", "TA0P", "TG0P", "TG0D", "TG0H", "TH0P", "Tm0P", "TO0P",
106 "Tp0C", NULL },
f91a79fe
GS
107/* Set 6: Macbook3 set */
108 { "TB0T", "TC0D", "TC0P", "TM0P", "TN0P", "TTF0", "TW0P", "Th0H",
109 "Th0S", "Th1H", NULL },
f5274c97
HR
110/* Set 7: Macbook Air */
111 { "TB0T", "TB1S", "TB1T", "TB2S", "TB2T", "TC0D", "TC0P", "TCFP",
112 "TTF0", "TW0P", "Th0H", "Tp0P", "TpFP", "Ts0P", "Ts0S", NULL },
d7549905
HR
113/* Set 8: Macbook Pro 4,1 (Penryn) */
114 { "TB0T", "TC0D", "TC0P", "TG0D", "TG0H", "TTF0", "TW0P", "Th0H",
115 "Th1H", "Th2H", "Tm0P", "Ts0P", NULL },
07e8dbd3
HR
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 },
6e3530fa
HR
119/* Set 10: iMac 5,1 */
120 { "TA0P", "TC0D", "TC0P", "TG0D", "TH0P", "TO0P", "Tm0P", NULL },
181209a1
HR
121/* Set 11: Macbook 5,1 */
122 { "TB0T", "TB1T", "TB2T", "TB3T", "TC0D", "TC0P", "TN0D", "TN0P",
123 "TTF0", "Th0H", "Th1H", "ThFH", "Ts0P", "Ts0S", NULL },
a6660325
HR
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 },
eefc488f
HR
128/* Set 13: iMac 8,1 */
129 { "TA0P", "TC0D", "TC0H", "TC0P", "TG0D", "TG0H", "TG0P", "TH0P",
130 "TL0P", "TO0P", "TW0P", "Tm0P", "Tp0P", NULL },
9ca791bb
HR
131/* Set 14: iMac 6,1 */
132 { "TA0P", "TC0D", "TC0H", "TC0P", "TG0D", "TG0H", "TG0P", "TH0P",
133 "TO0P", "Tp0P", NULL },
85e0e5ad
HR
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",
137 "Ts0S", NULL },
fb9f88e1
BR
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",
144 NULL },
e1741712
JM
145/* Set 17: iMac 9,1 */
146 { "TA0P", "TC0D", "TC0H", "TC0P", "TG0D", "TG0H", "TH0P", "TL0P",
147 "TN0D", "TN0H", "TN0P", "TO0P", "Tm0P", "Tp0P", NULL },
148/* Set 18: MacBook Pro 2,2 */
149 { "TB0T", "TC0D", "TC0P", "TG0H", "TG0P", "TG0T", "TM0P", "TTF0",
150 "Th0H", "Th1H", "Tm0P", "Ts0P", NULL },
6f2fad74
NB
151};
152
153/* List of keys used to read/write fan speeds */
154static const char* fan_speed_keys[] = {
155 FAN_ACTUAL_SPEED,
156 FAN_MIN_SPEED,
157 FAN_MAX_SPEED,
158 FAN_SAFE_SPEED,
159 FAN_TARGET_SPEED
160};
161
162#define INIT_TIMEOUT_MSECS 5000 /* wait up to 5s for device init ... */
163#define INIT_WAIT_MSECS 50 /* ... in 50ms increments */
164
d5cf2b99 165#define APPLESMC_POLL_INTERVAL 50 /* msecs */
6f2fad74
NB
166#define APPLESMC_INPUT_FUZZ 4 /* input event threshold */
167#define APPLESMC_INPUT_FLAT 4
168
169#define SENSOR_X 0
170#define SENSOR_Y 1
171#define SENSOR_Z 2
172
173/* Structure to be passed to DMI_MATCH function */
174struct dmi_match_data {
175/* Indicates whether this computer has an accelerometer. */
176 int accelerometer;
177/* Indicates whether this computer has light sensors and keyboard backlight. */
178 int light;
179/* Indicates which temperature sensors set to use. */
180 int temperature_set;
181};
182
183static const int debug;
184static struct platform_device *pdev;
185static s16 rest_x;
186static s16 rest_y;
a976f150
HR
187static u8 backlight_state[2];
188
1beeffe4 189static struct device *hwmon_dev;
d5cf2b99 190static struct input_polled_dev *applesmc_idev;
6f2fad74
NB
191
192/* Indicates whether this computer has an accelerometer. */
193static unsigned int applesmc_accelerometer;
194
195/* Indicates whether this computer has light sensors and keyboard backlight. */
196static unsigned int applesmc_light;
197
0559a538
HR
198/* The number of fans handled by the driver */
199static unsigned int fans_handled;
200
6f2fad74
NB
201/* Indicates which temperature sensors set to use. */
202static unsigned int applesmc_temperature_set;
203
d5cf2b99 204static DEFINE_MUTEX(applesmc_lock);
6f2fad74
NB
205
206/*
207 * Last index written to key_at_index sysfs file, and value to use for all other
208 * key_at_index_* sysfs files.
209 */
210static unsigned int key_at_index;
211
212static struct workqueue_struct *applesmc_led_wq;
213
214/*
8c9398d1 215 * __wait_status - Wait up to 32ms for the status port to get a certain value
6f2fad74
NB
216 * (masked with 0x0f), returning zero if the value is obtained. Callers must
217 * hold applesmc_lock.
218 */
219static int __wait_status(u8 val)
220{
8c9398d1 221 int us;
6f2fad74
NB
222
223 val = val & APPLESMC_STATUS_MASK;
224
8c9398d1
HR
225 for (us = APPLESMC_MIN_WAIT; us < APPLESMC_MAX_WAIT; us <<= 1) {
226 udelay(us);
6f2fad74
NB
227 if ((inb(APPLESMC_CMD_PORT) & APPLESMC_STATUS_MASK) == val) {
228 if (debug)
229 printk(KERN_DEBUG
8c9398d1
HR
230 "Waited %d us for status %x\n",
231 2 * us - APPLESMC_MIN_WAIT, val);
6f2fad74
NB
232 return 0;
233 }
6f2fad74
NB
234 }
235
236 printk(KERN_WARNING "applesmc: wait status failed: %x != %x\n",
237 val, inb(APPLESMC_CMD_PORT));
238
239 return -EIO;
240}
241
84d2d7f2
HR
242/*
243 * special treatment of command port - on newer macbooks, it seems necessary
244 * to resend the command byte before polling the status again. Callers must
245 * hold applesmc_lock.
246 */
247static int send_command(u8 cmd)
248{
8c9398d1
HR
249 int us;
250 for (us = APPLESMC_MIN_WAIT; us < APPLESMC_MAX_WAIT; us <<= 1) {
84d2d7f2 251 outb(cmd, APPLESMC_CMD_PORT);
8c9398d1 252 udelay(us);
84d2d7f2
HR
253 if ((inb(APPLESMC_CMD_PORT) & APPLESMC_STATUS_MASK) == 0x0c)
254 return 0;
84d2d7f2
HR
255 }
256 printk(KERN_WARNING "applesmc: command failed: %x -> %x\n",
257 cmd, inb(APPLESMC_CMD_PORT));
258 return -EIO;
259}
260
6f2fad74
NB
261/*
262 * applesmc_read_key - reads len bytes from a given key, and put them in buffer.
263 * Returns zero on success or a negative error on failure. Callers must
264 * hold applesmc_lock.
265 */
266static int applesmc_read_key(const char* key, u8* buffer, u8 len)
267{
268 int i;
269
270 if (len > APPLESMC_MAX_DATA_LENGTH) {
271 printk(KERN_ERR "applesmc_read_key: cannot read more than "
272 "%d bytes\n", APPLESMC_MAX_DATA_LENGTH);
273 return -EINVAL;
274 }
275
84d2d7f2 276 if (send_command(APPLESMC_READ_CMD))
6f2fad74
NB
277 return -EIO;
278
279 for (i = 0; i < 4; i++) {
280 outb(key[i], APPLESMC_DATA_PORT);
281 if (__wait_status(0x04))
282 return -EIO;
283 }
284 if (debug)
285 printk(KERN_DEBUG "<%s", key);
286
287 outb(len, APPLESMC_DATA_PORT);
288 if (debug)
289 printk(KERN_DEBUG ">%x", len);
290
291 for (i = 0; i < len; i++) {
292 if (__wait_status(0x05))
293 return -EIO;
294 buffer[i] = inb(APPLESMC_DATA_PORT);
295 if (debug)
296 printk(KERN_DEBUG "<%x", buffer[i]);
297 }
298 if (debug)
299 printk(KERN_DEBUG "\n");
300
301 return 0;
302}
303
304/*
305 * applesmc_write_key - writes len bytes from buffer to a given key.
306 * Returns zero on success or a negative error on failure. Callers must
307 * hold applesmc_lock.
308 */
309static int applesmc_write_key(const char* key, u8* buffer, u8 len)
310{
311 int i;
312
313 if (len > APPLESMC_MAX_DATA_LENGTH) {
314 printk(KERN_ERR "applesmc_write_key: cannot write more than "
315 "%d bytes\n", APPLESMC_MAX_DATA_LENGTH);
316 return -EINVAL;
317 }
318
84d2d7f2 319 if (send_command(APPLESMC_WRITE_CMD))
6f2fad74
NB
320 return -EIO;
321
322 for (i = 0; i < 4; i++) {
323 outb(key[i], APPLESMC_DATA_PORT);
324 if (__wait_status(0x04))
325 return -EIO;
326 }
327
328 outb(len, APPLESMC_DATA_PORT);
329
330 for (i = 0; i < len; i++) {
331 if (__wait_status(0x04))
332 return -EIO;
333 outb(buffer[i], APPLESMC_DATA_PORT);
334 }
335
336 return 0;
337}
338
339/*
340 * applesmc_get_key_at_index - get key at index, and put the result in key
341 * (char[6]). Returns zero on success or a negative error on failure. Callers
342 * must hold applesmc_lock.
343 */
344static int applesmc_get_key_at_index(int index, char* key)
345{
346 int i;
347 u8 readkey[4];
348 readkey[0] = index >> 24;
349 readkey[1] = index >> 16;
350 readkey[2] = index >> 8;
351 readkey[3] = index;
352
84d2d7f2 353 if (send_command(APPLESMC_GET_KEY_BY_INDEX_CMD))
6f2fad74
NB
354 return -EIO;
355
356 for (i = 0; i < 4; i++) {
357 outb(readkey[i], APPLESMC_DATA_PORT);
358 if (__wait_status(0x04))
359 return -EIO;
360 }
361
362 outb(4, APPLESMC_DATA_PORT);
363
364 for (i = 0; i < 4; i++) {
365 if (__wait_status(0x05))
366 return -EIO;
367 key[i] = inb(APPLESMC_DATA_PORT);
368 }
369 key[4] = 0;
370
371 return 0;
372}
373
374/*
375 * applesmc_get_key_type - get key type, and put the result in type (char[6]).
376 * Returns zero on success or a negative error on failure. Callers must
377 * hold applesmc_lock.
378 */
379static int applesmc_get_key_type(char* key, char* type)
380{
381 int i;
382
84d2d7f2 383 if (send_command(APPLESMC_GET_KEY_TYPE_CMD))
6f2fad74
NB
384 return -EIO;
385
386 for (i = 0; i < 4; i++) {
387 outb(key[i], APPLESMC_DATA_PORT);
388 if (__wait_status(0x04))
389 return -EIO;
390 }
391
05224091 392 outb(6, APPLESMC_DATA_PORT);
6f2fad74
NB
393
394 for (i = 0; i < 6; i++) {
395 if (__wait_status(0x05))
396 return -EIO;
397 type[i] = inb(APPLESMC_DATA_PORT);
398 }
399 type[5] = 0;
400
401 return 0;
402}
403
404/*
405 * applesmc_read_motion_sensor - Read motion sensor (X, Y or Z). Callers must
406 * hold applesmc_lock.
407 */
408static int applesmc_read_motion_sensor(int index, s16* value)
409{
410 u8 buffer[2];
411 int ret;
412
413 switch (index) {
414 case SENSOR_X:
415 ret = applesmc_read_key(MOTION_SENSOR_X_KEY, buffer, 2);
416 break;
417 case SENSOR_Y:
418 ret = applesmc_read_key(MOTION_SENSOR_Y_KEY, buffer, 2);
419 break;
420 case SENSOR_Z:
421 ret = applesmc_read_key(MOTION_SENSOR_Z_KEY, buffer, 2);
422 break;
423 default:
424 ret = -EINVAL;
425 }
426
427 *value = ((s16)buffer[0] << 8) | buffer[1];
428
429 return ret;
430}
431
432/*
433 * applesmc_device_init - initialize the accelerometer. Returns zero on success
434 * and negative error code on failure. Can sleep.
435 */
436static int applesmc_device_init(void)
437{
438 int total, ret = -ENXIO;
439 u8 buffer[2];
440
441 if (!applesmc_accelerometer)
442 return 0;
443
444 mutex_lock(&applesmc_lock);
445
446 for (total = INIT_TIMEOUT_MSECS; total > 0; total -= INIT_WAIT_MSECS) {
447 if (debug)
448 printk(KERN_DEBUG "applesmc try %d\n", total);
449 if (!applesmc_read_key(MOTION_SENSOR_KEY, buffer, 2) &&
450 (buffer[0] != 0x00 || buffer[1] != 0x00)) {
451 if (total == INIT_TIMEOUT_MSECS) {
452 printk(KERN_DEBUG "applesmc: device has"
453 " already been initialized"
454 " (0x%02x, 0x%02x).\n",
455 buffer[0], buffer[1]);
456 } else {
457 printk(KERN_DEBUG "applesmc: device"
458 " successfully initialized"
459 " (0x%02x, 0x%02x).\n",
460 buffer[0], buffer[1]);
461 }
462 ret = 0;
463 goto out;
464 }
465 buffer[0] = 0xe0;
466 buffer[1] = 0x00;
467 applesmc_write_key(MOTION_SENSOR_KEY, buffer, 2);
468 msleep(INIT_WAIT_MSECS);
469 }
470
471 printk(KERN_WARNING "applesmc: failed to init the device\n");
472
473out:
474 mutex_unlock(&applesmc_lock);
475 return ret;
476}
477
478/*
479 * applesmc_get_fan_count - get the number of fans. Callers must NOT hold
480 * applesmc_lock.
481 */
482static int applesmc_get_fan_count(void)
483{
484 int ret;
485 u8 buffer[1];
486
487 mutex_lock(&applesmc_lock);
488
489 ret = applesmc_read_key(FANS_COUNT, buffer, 1);
490
491 mutex_unlock(&applesmc_lock);
492 if (ret)
493 return ret;
494 else
495 return buffer[0];
496}
497
498/* Device model stuff */
499static int applesmc_probe(struct platform_device *dev)
500{
501 int ret;
502
503 ret = applesmc_device_init();
504 if (ret)
505 return ret;
506
507 printk(KERN_INFO "applesmc: device successfully initialized.\n");
508 return 0;
509}
510
a976f150
HR
511/* Synchronize device with memorized backlight state */
512static int applesmc_pm_resume(struct device *dev)
513{
514 mutex_lock(&applesmc_lock);
515 if (applesmc_light)
516 applesmc_write_key(BACKLIGHT_KEY, backlight_state, 2);
517 mutex_unlock(&applesmc_lock);
518 return 0;
519}
520
521/* Reinitialize device on resume from hibernation */
522static int applesmc_pm_restore(struct device *dev)
6f2fad74 523{
a976f150
HR
524 int ret = applesmc_device_init();
525 if (ret)
526 return ret;
527 return applesmc_pm_resume(dev);
6f2fad74
NB
528}
529
47145210 530static const struct dev_pm_ops applesmc_pm_ops = {
a976f150
HR
531 .resume = applesmc_pm_resume,
532 .restore = applesmc_pm_restore,
533};
534
6f2fad74
NB
535static struct platform_driver applesmc_driver = {
536 .probe = applesmc_probe,
6f2fad74
NB
537 .driver = {
538 .name = "applesmc",
539 .owner = THIS_MODULE,
a976f150 540 .pm = &applesmc_pm_ops,
6f2fad74
NB
541 },
542};
543
544/*
545 * applesmc_calibrate - Set our "resting" values. Callers must
546 * hold applesmc_lock.
547 */
548static void applesmc_calibrate(void)
549{
550 applesmc_read_motion_sensor(SENSOR_X, &rest_x);
551 applesmc_read_motion_sensor(SENSOR_Y, &rest_y);
552 rest_x = -rest_x;
553}
554
d5cf2b99 555static void applesmc_idev_poll(struct input_polled_dev *dev)
6f2fad74 556{
d5cf2b99 557 struct input_dev *idev = dev->input;
6f2fad74
NB
558 s16 x, y;
559
d5cf2b99 560 mutex_lock(&applesmc_lock);
6f2fad74
NB
561
562 if (applesmc_read_motion_sensor(SENSOR_X, &x))
563 goto out;
564 if (applesmc_read_motion_sensor(SENSOR_Y, &y))
565 goto out;
566
567 x = -x;
d5cf2b99
DT
568 input_report_abs(idev, ABS_X, x - rest_x);
569 input_report_abs(idev, ABS_Y, y - rest_y);
570 input_sync(idev);
6f2fad74
NB
571
572out:
6f2fad74
NB
573 mutex_unlock(&applesmc_lock);
574}
575
576/* Sysfs Files */
577
fa74419b
NB
578static ssize_t applesmc_name_show(struct device *dev,
579 struct device_attribute *attr, char *buf)
580{
581 return snprintf(buf, PAGE_SIZE, "applesmc\n");
582}
583
6f2fad74
NB
584static ssize_t applesmc_position_show(struct device *dev,
585 struct device_attribute *attr, char *buf)
586{
587 int ret;
588 s16 x, y, z;
589
590 mutex_lock(&applesmc_lock);
591
592 ret = applesmc_read_motion_sensor(SENSOR_X, &x);
593 if (ret)
594 goto out;
595 ret = applesmc_read_motion_sensor(SENSOR_Y, &y);
596 if (ret)
597 goto out;
598 ret = applesmc_read_motion_sensor(SENSOR_Z, &z);
599 if (ret)
600 goto out;
601
602out:
603 mutex_unlock(&applesmc_lock);
604 if (ret)
605 return ret;
606 else
607 return snprintf(buf, PAGE_SIZE, "(%d,%d,%d)\n", x, y, z);
608}
609
610static ssize_t applesmc_light_show(struct device *dev,
611 struct device_attribute *attr, char *sysfsbuf)
612{
8bd1a12a 613 static int data_length;
6f2fad74
NB
614 int ret;
615 u8 left = 0, right = 0;
8bd1a12a 616 u8 buffer[10], query[6];
6f2fad74
NB
617
618 mutex_lock(&applesmc_lock);
619
8bd1a12a
HR
620 if (!data_length) {
621 ret = applesmc_get_key_type(LIGHT_SENSOR_LEFT_KEY, query);
622 if (ret)
623 goto out;
624 data_length = clamp_val(query[0], 0, 10);
625 printk(KERN_INFO "applesmc: light sensor data length set to "
626 "%d\n", data_length);
627 }
628
629 ret = applesmc_read_key(LIGHT_SENSOR_LEFT_KEY, buffer, data_length);
c3d6362b
AM
630 /* newer macbooks report a single 10-bit bigendian value */
631 if (data_length == 10) {
632 left = be16_to_cpu(*(__be16 *)(buffer + 6)) >> 2;
633 goto out;
634 }
6f2fad74
NB
635 left = buffer[2];
636 if (ret)
637 goto out;
8bd1a12a 638 ret = applesmc_read_key(LIGHT_SENSOR_RIGHT_KEY, buffer, data_length);
6f2fad74
NB
639 right = buffer[2];
640
641out:
642 mutex_unlock(&applesmc_lock);
643 if (ret)
644 return ret;
645 else
646 return snprintf(sysfsbuf, PAGE_SIZE, "(%d,%d)\n", left, right);
647}
648
649/* Displays degree Celsius * 1000 */
650static ssize_t applesmc_show_temperature(struct device *dev,
651 struct device_attribute *devattr, char *sysfsbuf)
652{
653 int ret;
654 u8 buffer[2];
655 unsigned int temp;
656 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
657 const char* key =
658 temperature_sensors_sets[applesmc_temperature_set][attr->index];
659
660 mutex_lock(&applesmc_lock);
661
662 ret = applesmc_read_key(key, buffer, 2);
663 temp = buffer[0]*1000;
664 temp += (buffer[1] >> 6) * 250;
665
666 mutex_unlock(&applesmc_lock);
667
668 if (ret)
669 return ret;
670 else
671 return snprintf(sysfsbuf, PAGE_SIZE, "%u\n", temp);
672}
673
674static ssize_t applesmc_show_fan_speed(struct device *dev,
675 struct device_attribute *attr, char *sysfsbuf)
676{
677 int ret;
678 unsigned int speed = 0;
679 char newkey[5];
680 u8 buffer[2];
681 struct sensor_device_attribute_2 *sensor_attr =
682 to_sensor_dev_attr_2(attr);
683
684 newkey[0] = fan_speed_keys[sensor_attr->nr][0];
685 newkey[1] = '0' + sensor_attr->index;
686 newkey[2] = fan_speed_keys[sensor_attr->nr][2];
687 newkey[3] = fan_speed_keys[sensor_attr->nr][3];
688 newkey[4] = 0;
689
690 mutex_lock(&applesmc_lock);
691
692 ret = applesmc_read_key(newkey, buffer, 2);
693 speed = ((buffer[0] << 8 | buffer[1]) >> 2);
694
695 mutex_unlock(&applesmc_lock);
696 if (ret)
697 return ret;
698 else
699 return snprintf(sysfsbuf, PAGE_SIZE, "%u\n", speed);
700}
701
702static ssize_t applesmc_store_fan_speed(struct device *dev,
703 struct device_attribute *attr,
704 const char *sysfsbuf, size_t count)
705{
706 int ret;
707 u32 speed;
708 char newkey[5];
709 u8 buffer[2];
710 struct sensor_device_attribute_2 *sensor_attr =
711 to_sensor_dev_attr_2(attr);
712
713 speed = simple_strtoul(sysfsbuf, NULL, 10);
714
715 if (speed > 0x4000) /* Bigger than a 14-bit value */
716 return -EINVAL;
717
718 newkey[0] = fan_speed_keys[sensor_attr->nr][0];
719 newkey[1] = '0' + sensor_attr->index;
720 newkey[2] = fan_speed_keys[sensor_attr->nr][2];
721 newkey[3] = fan_speed_keys[sensor_attr->nr][3];
722 newkey[4] = 0;
723
724 mutex_lock(&applesmc_lock);
725
726 buffer[0] = (speed >> 6) & 0xff;
727 buffer[1] = (speed << 2) & 0xff;
728 ret = applesmc_write_key(newkey, buffer, 2);
729
730 mutex_unlock(&applesmc_lock);
731 if (ret)
732 return ret;
733 else
734 return count;
735}
736
737static ssize_t applesmc_show_fan_manual(struct device *dev,
738 struct device_attribute *devattr, char *sysfsbuf)
739{
740 int ret;
741 u16 manual = 0;
742 u8 buffer[2];
743 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
744
745 mutex_lock(&applesmc_lock);
746
747 ret = applesmc_read_key(FANS_MANUAL, buffer, 2);
748 manual = ((buffer[0] << 8 | buffer[1]) >> attr->index) & 0x01;
749
750 mutex_unlock(&applesmc_lock);
751 if (ret)
752 return ret;
753 else
754 return snprintf(sysfsbuf, PAGE_SIZE, "%d\n", manual);
755}
756
757static ssize_t applesmc_store_fan_manual(struct device *dev,
758 struct device_attribute *devattr,
759 const char *sysfsbuf, size_t count)
760{
761 int ret;
762 u8 buffer[2];
763 u32 input;
764 u16 val;
765 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
766
767 input = simple_strtoul(sysfsbuf, NULL, 10);
768
769 mutex_lock(&applesmc_lock);
770
771 ret = applesmc_read_key(FANS_MANUAL, buffer, 2);
772 val = (buffer[0] << 8 | buffer[1]);
773 if (ret)
774 goto out;
775
776 if (input)
777 val = val | (0x01 << attr->index);
778 else
779 val = val & ~(0x01 << attr->index);
780
781 buffer[0] = (val >> 8) & 0xFF;
782 buffer[1] = val & 0xFF;
783
784 ret = applesmc_write_key(FANS_MANUAL, buffer, 2);
785
786out:
787 mutex_unlock(&applesmc_lock);
788 if (ret)
789 return ret;
790 else
791 return count;
792}
793
794static ssize_t applesmc_show_fan_position(struct device *dev,
795 struct device_attribute *attr, char *sysfsbuf)
796{
797 int ret;
798 char newkey[5];
799 u8 buffer[17];
800 struct sensor_device_attribute_2 *sensor_attr =
801 to_sensor_dev_attr_2(attr);
802
803 newkey[0] = FAN_POSITION[0];
804 newkey[1] = '0' + sensor_attr->index;
805 newkey[2] = FAN_POSITION[2];
806 newkey[3] = FAN_POSITION[3];
807 newkey[4] = 0;
808
809 mutex_lock(&applesmc_lock);
810
811 ret = applesmc_read_key(newkey, buffer, 16);
812 buffer[16] = 0;
813
814 mutex_unlock(&applesmc_lock);
815 if (ret)
816 return ret;
817 else
818 return snprintf(sysfsbuf, PAGE_SIZE, "%s\n", buffer+4);
819}
820
821static ssize_t applesmc_calibrate_show(struct device *dev,
822 struct device_attribute *attr, char *sysfsbuf)
823{
824 return snprintf(sysfsbuf, PAGE_SIZE, "(%d,%d)\n", rest_x, rest_y);
825}
826
827static ssize_t applesmc_calibrate_store(struct device *dev,
828 struct device_attribute *attr, const char *sysfsbuf, size_t count)
829{
830 mutex_lock(&applesmc_lock);
831 applesmc_calibrate();
832 mutex_unlock(&applesmc_lock);
833
834 return count;
835}
836
6f2fad74
NB
837static void applesmc_backlight_set(struct work_struct *work)
838{
6f2fad74 839 mutex_lock(&applesmc_lock);
a976f150 840 applesmc_write_key(BACKLIGHT_KEY, backlight_state, 2);
6f2fad74
NB
841 mutex_unlock(&applesmc_lock);
842}
843static DECLARE_WORK(backlight_work, &applesmc_backlight_set);
844
845static void applesmc_brightness_set(struct led_classdev *led_cdev,
846 enum led_brightness value)
847{
848 int ret;
849
a976f150 850 backlight_state[0] = value;
6f2fad74
NB
851 ret = queue_work(applesmc_led_wq, &backlight_work);
852
853 if (debug && (!ret))
854 printk(KERN_DEBUG "applesmc: work was already on the queue.\n");
855}
856
857static ssize_t applesmc_key_count_show(struct device *dev,
858 struct device_attribute *attr, char *sysfsbuf)
859{
860 int ret;
861 u8 buffer[4];
862 u32 count;
863
864 mutex_lock(&applesmc_lock);
865
866 ret = applesmc_read_key(KEY_COUNT_KEY, buffer, 4);
867 count = ((u32)buffer[0]<<24) + ((u32)buffer[1]<<16) +
868 ((u32)buffer[2]<<8) + buffer[3];
869
870 mutex_unlock(&applesmc_lock);
871 if (ret)
872 return ret;
873 else
874 return snprintf(sysfsbuf, PAGE_SIZE, "%d\n", count);
875}
876
877static ssize_t applesmc_key_at_index_read_show(struct device *dev,
878 struct device_attribute *attr, char *sysfsbuf)
879{
880 char key[5];
881 char info[6];
882 int ret;
883
884 mutex_lock(&applesmc_lock);
885
886 ret = applesmc_get_key_at_index(key_at_index, key);
887
888 if (ret || !key[0]) {
889 mutex_unlock(&applesmc_lock);
890
891 return -EINVAL;
892 }
893
894 ret = applesmc_get_key_type(key, info);
895
896 if (ret) {
897 mutex_unlock(&applesmc_lock);
898
899 return ret;
900 }
901
902 /*
903 * info[0] maximum value (APPLESMC_MAX_DATA_LENGTH) is much lower than
904 * PAGE_SIZE, so we don't need any checks before writing to sysfsbuf.
905 */
906 ret = applesmc_read_key(key, sysfsbuf, info[0]);
907
908 mutex_unlock(&applesmc_lock);
909
910 if (!ret) {
911 return info[0];
d5cf2b99 912 } else {
6f2fad74
NB
913 return ret;
914 }
915}
916
917static ssize_t applesmc_key_at_index_data_length_show(struct device *dev,
918 struct device_attribute *attr, char *sysfsbuf)
919{
920 char key[5];
921 char info[6];
922 int ret;
923
924 mutex_lock(&applesmc_lock);
925
926 ret = applesmc_get_key_at_index(key_at_index, key);
927
928 if (ret || !key[0]) {
929 mutex_unlock(&applesmc_lock);
930
931 return -EINVAL;
932 }
933
934 ret = applesmc_get_key_type(key, info);
935
936 mutex_unlock(&applesmc_lock);
937
938 if (!ret)
939 return snprintf(sysfsbuf, PAGE_SIZE, "%d\n", info[0]);
940 else
941 return ret;
942}
943
944static ssize_t applesmc_key_at_index_type_show(struct device *dev,
945 struct device_attribute *attr, char *sysfsbuf)
946{
947 char key[5];
948 char info[6];
949 int ret;
950
951 mutex_lock(&applesmc_lock);
952
953 ret = applesmc_get_key_at_index(key_at_index, key);
954
955 if (ret || !key[0]) {
956 mutex_unlock(&applesmc_lock);
957
958 return -EINVAL;
959 }
960
961 ret = applesmc_get_key_type(key, info);
962
963 mutex_unlock(&applesmc_lock);
964
965 if (!ret)
966 return snprintf(sysfsbuf, PAGE_SIZE, "%s\n", info+1);
967 else
968 return ret;
969}
970
971static ssize_t applesmc_key_at_index_name_show(struct device *dev,
972 struct device_attribute *attr, char *sysfsbuf)
973{
974 char key[5];
975 int ret;
976
977 mutex_lock(&applesmc_lock);
978
979 ret = applesmc_get_key_at_index(key_at_index, key);
980
981 mutex_unlock(&applesmc_lock);
982
983 if (!ret && key[0])
984 return snprintf(sysfsbuf, PAGE_SIZE, "%s\n", key);
985 else
986 return -EINVAL;
987}
988
989static ssize_t applesmc_key_at_index_show(struct device *dev,
990 struct device_attribute *attr, char *sysfsbuf)
991{
992 return snprintf(sysfsbuf, PAGE_SIZE, "%d\n", key_at_index);
993}
994
995static ssize_t applesmc_key_at_index_store(struct device *dev,
996 struct device_attribute *attr, const char *sysfsbuf, size_t count)
997{
998 mutex_lock(&applesmc_lock);
999
1000 key_at_index = simple_strtoul(sysfsbuf, NULL, 10);
1001
1002 mutex_unlock(&applesmc_lock);
1003
1004 return count;
1005}
1006
1007static struct led_classdev applesmc_backlight = {
6c152bee 1008 .name = "smc::kbd_backlight",
6f2fad74
NB
1009 .default_trigger = "nand-disk",
1010 .brightness_set = applesmc_brightness_set,
1011};
1012
fa74419b
NB
1013static DEVICE_ATTR(name, 0444, applesmc_name_show, NULL);
1014
6f2fad74
NB
1015static DEVICE_ATTR(position, 0444, applesmc_position_show, NULL);
1016static DEVICE_ATTR(calibrate, 0644,
1017 applesmc_calibrate_show, applesmc_calibrate_store);
1018
1019static struct attribute *accelerometer_attributes[] = {
1020 &dev_attr_position.attr,
1021 &dev_attr_calibrate.attr,
1022 NULL
1023};
1024
1025static const struct attribute_group accelerometer_attributes_group =
1026 { .attrs = accelerometer_attributes };
1027
1028static DEVICE_ATTR(light, 0444, applesmc_light_show, NULL);
1029
1030static DEVICE_ATTR(key_count, 0444, applesmc_key_count_show, NULL);
1031static DEVICE_ATTR(key_at_index, 0644,
1032 applesmc_key_at_index_show, applesmc_key_at_index_store);
1033static DEVICE_ATTR(key_at_index_name, 0444,
1034 applesmc_key_at_index_name_show, NULL);
1035static DEVICE_ATTR(key_at_index_type, 0444,
1036 applesmc_key_at_index_type_show, NULL);
1037static DEVICE_ATTR(key_at_index_data_length, 0444,
1038 applesmc_key_at_index_data_length_show, NULL);
1039static DEVICE_ATTR(key_at_index_data, 0444,
1040 applesmc_key_at_index_read_show, NULL);
1041
1042static struct attribute *key_enumeration_attributes[] = {
1043 &dev_attr_key_count.attr,
1044 &dev_attr_key_at_index.attr,
1045 &dev_attr_key_at_index_name.attr,
1046 &dev_attr_key_at_index_type.attr,
1047 &dev_attr_key_at_index_data_length.attr,
1048 &dev_attr_key_at_index_data.attr,
1049 NULL
1050};
1051
1052static const struct attribute_group key_enumeration_group =
1053 { .attrs = key_enumeration_attributes };
1054
1055/*
1056 * Macro defining SENSOR_DEVICE_ATTR for a fan sysfs entries.
1057 * - show actual speed
1058 * - show/store minimum speed
1059 * - show maximum speed
1060 * - show safe speed
1061 * - show/store target speed
1062 * - show/store manual mode
1063 */
1064#define sysfs_fan_speeds_offset(offset) \
1065static SENSOR_DEVICE_ATTR_2(fan##offset##_input, S_IRUGO, \
1066 applesmc_show_fan_speed, NULL, 0, offset-1); \
1067\
1068static SENSOR_DEVICE_ATTR_2(fan##offset##_min, S_IRUGO | S_IWUSR, \
1069 applesmc_show_fan_speed, applesmc_store_fan_speed, 1, offset-1); \
1070\
1071static SENSOR_DEVICE_ATTR_2(fan##offset##_max, S_IRUGO, \
1072 applesmc_show_fan_speed, NULL, 2, offset-1); \
1073\
1074static SENSOR_DEVICE_ATTR_2(fan##offset##_safe, S_IRUGO, \
1075 applesmc_show_fan_speed, NULL, 3, offset-1); \
1076\
1077static SENSOR_DEVICE_ATTR_2(fan##offset##_output, S_IRUGO | S_IWUSR, \
1078 applesmc_show_fan_speed, applesmc_store_fan_speed, 4, offset-1); \
1079\
1080static SENSOR_DEVICE_ATTR(fan##offset##_manual, S_IRUGO | S_IWUSR, \
1081 applesmc_show_fan_manual, applesmc_store_fan_manual, offset-1); \
1082\
da4e8ca3 1083static SENSOR_DEVICE_ATTR(fan##offset##_label, S_IRUGO, \
6f2fad74
NB
1084 applesmc_show_fan_position, NULL, offset-1); \
1085\
1086static struct attribute *fan##offset##_attributes[] = { \
1087 &sensor_dev_attr_fan##offset##_input.dev_attr.attr, \
1088 &sensor_dev_attr_fan##offset##_min.dev_attr.attr, \
1089 &sensor_dev_attr_fan##offset##_max.dev_attr.attr, \
1090 &sensor_dev_attr_fan##offset##_safe.dev_attr.attr, \
1091 &sensor_dev_attr_fan##offset##_output.dev_attr.attr, \
1092 &sensor_dev_attr_fan##offset##_manual.dev_attr.attr, \
da4e8ca3 1093 &sensor_dev_attr_fan##offset##_label.dev_attr.attr, \
6f2fad74
NB
1094 NULL \
1095};
1096
1097/*
1098 * Create the needed functions for each fan using the macro defined above
8de57709 1099 * (4 fans are supported)
6f2fad74
NB
1100 */
1101sysfs_fan_speeds_offset(1);
1102sysfs_fan_speeds_offset(2);
8de57709
RR
1103sysfs_fan_speeds_offset(3);
1104sysfs_fan_speeds_offset(4);
6f2fad74
NB
1105
1106static const struct attribute_group fan_attribute_groups[] = {
1107 { .attrs = fan1_attributes },
8de57709
RR
1108 { .attrs = fan2_attributes },
1109 { .attrs = fan3_attributes },
1110 { .attrs = fan4_attributes },
6f2fad74
NB
1111};
1112
1113/*
1114 * Temperature sensors sysfs entries.
1115 */
1116static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO,
1117 applesmc_show_temperature, NULL, 0);
1118static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO,
1119 applesmc_show_temperature, NULL, 1);
1120static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO,
1121 applesmc_show_temperature, NULL, 2);
1122static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO,
1123 applesmc_show_temperature, NULL, 3);
1124static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO,
1125 applesmc_show_temperature, NULL, 4);
1126static SENSOR_DEVICE_ATTR(temp6_input, S_IRUGO,
1127 applesmc_show_temperature, NULL, 5);
1128static SENSOR_DEVICE_ATTR(temp7_input, S_IRUGO,
1129 applesmc_show_temperature, NULL, 6);
1130static SENSOR_DEVICE_ATTR(temp8_input, S_IRUGO,
1131 applesmc_show_temperature, NULL, 7);
1132static SENSOR_DEVICE_ATTR(temp9_input, S_IRUGO,
1133 applesmc_show_temperature, NULL, 8);
1134static SENSOR_DEVICE_ATTR(temp10_input, S_IRUGO,
1135 applesmc_show_temperature, NULL, 9);
1136static SENSOR_DEVICE_ATTR(temp11_input, S_IRUGO,
1137 applesmc_show_temperature, NULL, 10);
1138static SENSOR_DEVICE_ATTR(temp12_input, S_IRUGO,
1139 applesmc_show_temperature, NULL, 11);
8de57709
RR
1140static SENSOR_DEVICE_ATTR(temp13_input, S_IRUGO,
1141 applesmc_show_temperature, NULL, 12);
1142static SENSOR_DEVICE_ATTR(temp14_input, S_IRUGO,
1143 applesmc_show_temperature, NULL, 13);
1144static SENSOR_DEVICE_ATTR(temp15_input, S_IRUGO,
1145 applesmc_show_temperature, NULL, 14);
1146static SENSOR_DEVICE_ATTR(temp16_input, S_IRUGO,
1147 applesmc_show_temperature, NULL, 15);
1148static SENSOR_DEVICE_ATTR(temp17_input, S_IRUGO,
1149 applesmc_show_temperature, NULL, 16);
1150static SENSOR_DEVICE_ATTR(temp18_input, S_IRUGO,
1151 applesmc_show_temperature, NULL, 17);
1152static SENSOR_DEVICE_ATTR(temp19_input, S_IRUGO,
1153 applesmc_show_temperature, NULL, 18);
1154static SENSOR_DEVICE_ATTR(temp20_input, S_IRUGO,
1155 applesmc_show_temperature, NULL, 19);
1156static SENSOR_DEVICE_ATTR(temp21_input, S_IRUGO,
1157 applesmc_show_temperature, NULL, 20);
1158static SENSOR_DEVICE_ATTR(temp22_input, S_IRUGO,
1159 applesmc_show_temperature, NULL, 21);
1160static SENSOR_DEVICE_ATTR(temp23_input, S_IRUGO,
1161 applesmc_show_temperature, NULL, 22);
1162static SENSOR_DEVICE_ATTR(temp24_input, S_IRUGO,
1163 applesmc_show_temperature, NULL, 23);
1164static SENSOR_DEVICE_ATTR(temp25_input, S_IRUGO,
1165 applesmc_show_temperature, NULL, 24);
1166static SENSOR_DEVICE_ATTR(temp26_input, S_IRUGO,
1167 applesmc_show_temperature, NULL, 25);
1168static SENSOR_DEVICE_ATTR(temp27_input, S_IRUGO,
1169 applesmc_show_temperature, NULL, 26);
1170static SENSOR_DEVICE_ATTR(temp28_input, S_IRUGO,
1171 applesmc_show_temperature, NULL, 27);
1172static SENSOR_DEVICE_ATTR(temp29_input, S_IRUGO,
1173 applesmc_show_temperature, NULL, 28);
1174static SENSOR_DEVICE_ATTR(temp30_input, S_IRUGO,
1175 applesmc_show_temperature, NULL, 29);
1176static SENSOR_DEVICE_ATTR(temp31_input, S_IRUGO,
1177 applesmc_show_temperature, NULL, 30);
1178static SENSOR_DEVICE_ATTR(temp32_input, S_IRUGO,
1179 applesmc_show_temperature, NULL, 31);
1180static SENSOR_DEVICE_ATTR(temp33_input, S_IRUGO,
1181 applesmc_show_temperature, NULL, 32);
1182static SENSOR_DEVICE_ATTR(temp34_input, S_IRUGO,
1183 applesmc_show_temperature, NULL, 33);
1184static SENSOR_DEVICE_ATTR(temp35_input, S_IRUGO,
1185 applesmc_show_temperature, NULL, 34);
fb9f88e1
BR
1186static SENSOR_DEVICE_ATTR(temp36_input, S_IRUGO,
1187 applesmc_show_temperature, NULL, 35);
1188static SENSOR_DEVICE_ATTR(temp37_input, S_IRUGO,
1189 applesmc_show_temperature, NULL, 36);
1190static SENSOR_DEVICE_ATTR(temp38_input, S_IRUGO,
1191 applesmc_show_temperature, NULL, 37);
1192static SENSOR_DEVICE_ATTR(temp39_input, S_IRUGO,
1193 applesmc_show_temperature, NULL, 38);
1194static SENSOR_DEVICE_ATTR(temp40_input, S_IRUGO,
1195 applesmc_show_temperature, NULL, 39);
6f2fad74
NB
1196
1197static struct attribute *temperature_attributes[] = {
1198 &sensor_dev_attr_temp1_input.dev_attr.attr,
1199 &sensor_dev_attr_temp2_input.dev_attr.attr,
1200 &sensor_dev_attr_temp3_input.dev_attr.attr,
1201 &sensor_dev_attr_temp4_input.dev_attr.attr,
1202 &sensor_dev_attr_temp5_input.dev_attr.attr,
1203 &sensor_dev_attr_temp6_input.dev_attr.attr,
1204 &sensor_dev_attr_temp7_input.dev_attr.attr,
1205 &sensor_dev_attr_temp8_input.dev_attr.attr,
1206 &sensor_dev_attr_temp9_input.dev_attr.attr,
1207 &sensor_dev_attr_temp10_input.dev_attr.attr,
1208 &sensor_dev_attr_temp11_input.dev_attr.attr,
1209 &sensor_dev_attr_temp12_input.dev_attr.attr,
8de57709
RR
1210 &sensor_dev_attr_temp13_input.dev_attr.attr,
1211 &sensor_dev_attr_temp14_input.dev_attr.attr,
1212 &sensor_dev_attr_temp15_input.dev_attr.attr,
1213 &sensor_dev_attr_temp16_input.dev_attr.attr,
1214 &sensor_dev_attr_temp17_input.dev_attr.attr,
1215 &sensor_dev_attr_temp18_input.dev_attr.attr,
1216 &sensor_dev_attr_temp19_input.dev_attr.attr,
1217 &sensor_dev_attr_temp20_input.dev_attr.attr,
1218 &sensor_dev_attr_temp21_input.dev_attr.attr,
1219 &sensor_dev_attr_temp22_input.dev_attr.attr,
1220 &sensor_dev_attr_temp23_input.dev_attr.attr,
1221 &sensor_dev_attr_temp24_input.dev_attr.attr,
1222 &sensor_dev_attr_temp25_input.dev_attr.attr,
1223 &sensor_dev_attr_temp26_input.dev_attr.attr,
1224 &sensor_dev_attr_temp27_input.dev_attr.attr,
1225 &sensor_dev_attr_temp28_input.dev_attr.attr,
1226 &sensor_dev_attr_temp29_input.dev_attr.attr,
1227 &sensor_dev_attr_temp30_input.dev_attr.attr,
1228 &sensor_dev_attr_temp31_input.dev_attr.attr,
1229 &sensor_dev_attr_temp32_input.dev_attr.attr,
1230 &sensor_dev_attr_temp33_input.dev_attr.attr,
1231 &sensor_dev_attr_temp34_input.dev_attr.attr,
1232 &sensor_dev_attr_temp35_input.dev_attr.attr,
fb9f88e1
BR
1233 &sensor_dev_attr_temp36_input.dev_attr.attr,
1234 &sensor_dev_attr_temp37_input.dev_attr.attr,
1235 &sensor_dev_attr_temp38_input.dev_attr.attr,
1236 &sensor_dev_attr_temp39_input.dev_attr.attr,
1237 &sensor_dev_attr_temp40_input.dev_attr.attr,
6f2fad74
NB
1238 NULL
1239};
1240
1241static const struct attribute_group temperature_attributes_group =
1242 { .attrs = temperature_attributes };
1243
1244/* Module stuff */
1245
1246/*
1247 * applesmc_dmi_match - found a match. return one, short-circuiting the hunt.
1248 */
1855256c 1249static int applesmc_dmi_match(const struct dmi_system_id *id)
6f2fad74
NB
1250{
1251 int i = 0;
1252 struct dmi_match_data* dmi_data = id->driver_data;
1253 printk(KERN_INFO "applesmc: %s detected:\n", id->ident);
1254 applesmc_accelerometer = dmi_data->accelerometer;
1255 printk(KERN_INFO "applesmc: - Model %s accelerometer\n",
1256 applesmc_accelerometer ? "with" : "without");
1257 applesmc_light = dmi_data->light;
1258 printk(KERN_INFO "applesmc: - Model %s light sensors and backlight\n",
1259 applesmc_light ? "with" : "without");
1260
1261 applesmc_temperature_set = dmi_data->temperature_set;
1262 while (temperature_sensors_sets[applesmc_temperature_set][i] != NULL)
1263 i++;
1264 printk(KERN_INFO "applesmc: - Model with %d temperature sensors\n", i);
1265 return 1;
1266}
1267
1268/* Create accelerometer ressources */
1269static int applesmc_create_accelerometer(void)
1270{
d5cf2b99 1271 struct input_dev *idev;
6f2fad74
NB
1272 int ret;
1273
1274 ret = sysfs_create_group(&pdev->dev.kobj,
1275 &accelerometer_attributes_group);
1276 if (ret)
1277 goto out;
1278
d5cf2b99 1279 applesmc_idev = input_allocate_polled_device();
6f2fad74
NB
1280 if (!applesmc_idev) {
1281 ret = -ENOMEM;
1282 goto out_sysfs;
1283 }
1284
d5cf2b99
DT
1285 applesmc_idev->poll = applesmc_idev_poll;
1286 applesmc_idev->poll_interval = APPLESMC_POLL_INTERVAL;
1287
6f2fad74
NB
1288 /* initial calibrate for the input device */
1289 applesmc_calibrate();
1290
d5cf2b99
DT
1291 /* initialize the input device */
1292 idev = applesmc_idev->input;
1293 idev->name = "applesmc";
1294 idev->id.bustype = BUS_HOST;
1295 idev->dev.parent = &pdev->dev;
7b19ada2 1296 idev->evbit[0] = BIT_MASK(EV_ABS);
d5cf2b99 1297 input_set_abs_params(idev, ABS_X,
6f2fad74 1298 -256, 256, APPLESMC_INPUT_FUZZ, APPLESMC_INPUT_FLAT);
d5cf2b99 1299 input_set_abs_params(idev, ABS_Y,
6f2fad74
NB
1300 -256, 256, APPLESMC_INPUT_FUZZ, APPLESMC_INPUT_FLAT);
1301
d5cf2b99 1302 ret = input_register_polled_device(applesmc_idev);
6f2fad74
NB
1303 if (ret)
1304 goto out_idev;
1305
6f2fad74
NB
1306 return 0;
1307
1308out_idev:
d5cf2b99 1309 input_free_polled_device(applesmc_idev);
6f2fad74
NB
1310
1311out_sysfs:
1312 sysfs_remove_group(&pdev->dev.kobj, &accelerometer_attributes_group);
1313
1314out:
1315 printk(KERN_WARNING "applesmc: driver init failed (ret=%d)!\n", ret);
1316 return ret;
1317}
1318
1319/* Release all ressources used by the accelerometer */
1320static void applesmc_release_accelerometer(void)
1321{
d5cf2b99
DT
1322 input_unregister_polled_device(applesmc_idev);
1323 input_free_polled_device(applesmc_idev);
6f2fad74
NB
1324 sysfs_remove_group(&pdev->dev.kobj, &accelerometer_attributes_group);
1325}
1326
1327static __initdata struct dmi_match_data applesmc_dmi_data[] = {
1328/* MacBook Pro: accelerometer, backlight and temperature set 0 */
1329 { .accelerometer = 1, .light = 1, .temperature_set = 0 },
cd19ba13 1330/* MacBook2: accelerometer and temperature set 1 */
1bed24b9 1331 { .accelerometer = 1, .light = 0, .temperature_set = 1 },
cd19ba13
RO
1332/* MacBook: accelerometer and temperature set 2 */
1333 { .accelerometer = 1, .light = 0, .temperature_set = 2 },
1334/* MacMini: temperature set 3 */
8de57709 1335 { .accelerometer = 0, .light = 0, .temperature_set = 3 },
cd19ba13
RO
1336/* MacPro: temperature set 4 */
1337 { .accelerometer = 0, .light = 0, .temperature_set = 4 },
9f86f28d
RDI
1338/* iMac: temperature set 5 */
1339 { .accelerometer = 0, .light = 0, .temperature_set = 5 },
468cc032 1340/* MacBook3, MacBook4: accelerometer and temperature set 6 */
f91a79fe 1341 { .accelerometer = 1, .light = 0, .temperature_set = 6 },
f5274c97
HR
1342/* MacBook Air: accelerometer, backlight and temperature set 7 */
1343 { .accelerometer = 1, .light = 1, .temperature_set = 7 },
d7549905
HR
1344/* MacBook Pro 4: accelerometer, backlight and temperature set 8 */
1345 { .accelerometer = 1, .light = 1, .temperature_set = 8 },
07e8dbd3
HR
1346/* MacBook Pro 3: accelerometer, backlight and temperature set 9 */
1347 { .accelerometer = 1, .light = 1, .temperature_set = 9 },
6e3530fa
HR
1348/* iMac 5: light sensor only, temperature set 10 */
1349 { .accelerometer = 0, .light = 0, .temperature_set = 10 },
181209a1
HR
1350/* MacBook 5: accelerometer, backlight and temperature set 11 */
1351 { .accelerometer = 1, .light = 1, .temperature_set = 11 },
a6660325
HR
1352/* MacBook Pro 5: accelerometer, backlight and temperature set 12 */
1353 { .accelerometer = 1, .light = 1, .temperature_set = 12 },
eefc488f
HR
1354/* iMac 8: light sensor only, temperature set 13 */
1355 { .accelerometer = 0, .light = 0, .temperature_set = 13 },
9ca791bb
HR
1356/* iMac 6: light sensor only, temperature set 14 */
1357 { .accelerometer = 0, .light = 0, .temperature_set = 14 },
85e0e5ad
HR
1358/* MacBook Air 2,1: accelerometer, backlight and temperature set 15 */
1359 { .accelerometer = 1, .light = 1, .temperature_set = 15 },
fb9f88e1
BR
1360/* MacPro3,1: temperature set 16 */
1361 { .accelerometer = 0, .light = 0, .temperature_set = 16 },
e1741712
JM
1362/* iMac 9,1: light sensor only, temperature set 17 */
1363 { .accelerometer = 0, .light = 0, .temperature_set = 17 },
1364/* MacBook Pro 2,2: accelerometer, backlight and temperature set 18 */
1365 { .accelerometer = 1, .light = 1, .temperature_set = 18 },
6f2fad74
NB
1366};
1367
1368/* Note that DMI_MATCH(...,"MacBook") will match "MacBookPro1,1".
1369 * So we need to put "Apple MacBook Pro" before "Apple MacBook". */
1370static __initdata struct dmi_system_id applesmc_whitelist[] = {
85e0e5ad
HR
1371 { applesmc_dmi_match, "Apple MacBook Air 2", {
1372 DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
1373 DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir2") },
1374 &applesmc_dmi_data[15]},
f5274c97
HR
1375 { applesmc_dmi_match, "Apple MacBook Air", {
1376 DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
1377 DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir") },
7b5e3cb2 1378 &applesmc_dmi_data[7]},
a6660325
HR
1379 { applesmc_dmi_match, "Apple MacBook Pro 5", {
1380 DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
1381 DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5") },
1382 &applesmc_dmi_data[12]},
d7549905
HR
1383 { applesmc_dmi_match, "Apple MacBook Pro 4", {
1384 DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
1385 DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro4") },
1386 &applesmc_dmi_data[8]},
07e8dbd3
HR
1387 { applesmc_dmi_match, "Apple MacBook Pro 3", {
1388 DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
1389 DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro3") },
1390 &applesmc_dmi_data[9]},
e1741712
JM
1391 { applesmc_dmi_match, "Apple MacBook Pro 2,2", {
1392 DMI_MATCH(DMI_BOARD_VENDOR, "Apple Computer, Inc."),
1393 DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro2,2") },
1394 &applesmc_dmi_data[18]},
6f2fad74
NB
1395 { applesmc_dmi_match, "Apple MacBook Pro", {
1396 DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
1397 DMI_MATCH(DMI_PRODUCT_NAME,"MacBookPro") },
7b5e3cb2 1398 &applesmc_dmi_data[0]},
f91a79fe 1399 { applesmc_dmi_match, "Apple MacBook (v2)", {
6f2fad74 1400 DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
cd19ba13 1401 DMI_MATCH(DMI_PRODUCT_NAME,"MacBook2") },
7b5e3cb2 1402 &applesmc_dmi_data[1]},
f91a79fe
GS
1403 { applesmc_dmi_match, "Apple MacBook (v3)", {
1404 DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
1405 DMI_MATCH(DMI_PRODUCT_NAME,"MacBook3") },
7b5e3cb2 1406 &applesmc_dmi_data[6]},
468cc032
HR
1407 { applesmc_dmi_match, "Apple MacBook 4", {
1408 DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
1409 DMI_MATCH(DMI_PRODUCT_NAME, "MacBook4") },
1410 &applesmc_dmi_data[6]},
181209a1
HR
1411 { applesmc_dmi_match, "Apple MacBook 5", {
1412 DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
1413 DMI_MATCH(DMI_PRODUCT_NAME, "MacBook5") },
1414 &applesmc_dmi_data[11]},
cd19ba13
RO
1415 { applesmc_dmi_match, "Apple MacBook", {
1416 DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
1417 DMI_MATCH(DMI_PRODUCT_NAME,"MacBook") },
7b5e3cb2 1418 &applesmc_dmi_data[2]},
6f2fad74
NB
1419 { applesmc_dmi_match, "Apple Macmini", {
1420 DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
1421 DMI_MATCH(DMI_PRODUCT_NAME,"Macmini") },
7b5e3cb2 1422 &applesmc_dmi_data[3]},
8de57709
RR
1423 { applesmc_dmi_match, "Apple MacPro2", {
1424 DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
1425 DMI_MATCH(DMI_PRODUCT_NAME,"MacPro2") },
7b5e3cb2 1426 &applesmc_dmi_data[4]},
fb9f88e1
BR
1427 { applesmc_dmi_match, "Apple MacPro3", {
1428 DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
1429 DMI_MATCH(DMI_PRODUCT_NAME, "MacPro3") },
1430 &applesmc_dmi_data[16]},
45a3a36b
HR
1431 { applesmc_dmi_match, "Apple MacPro", {
1432 DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
1433 DMI_MATCH(DMI_PRODUCT_NAME, "MacPro") },
1434 &applesmc_dmi_data[4]},
e1741712
JM
1435 { applesmc_dmi_match, "Apple iMac 9,1", {
1436 DMI_MATCH(DMI_BOARD_VENDOR, "Apple Inc."),
1437 DMI_MATCH(DMI_PRODUCT_NAME, "iMac9,1") },
1438 &applesmc_dmi_data[17]},
eefc488f
HR
1439 { applesmc_dmi_match, "Apple iMac 8", {
1440 DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
1441 DMI_MATCH(DMI_PRODUCT_NAME, "iMac8") },
1442 &applesmc_dmi_data[13]},
9ca791bb
HR
1443 { applesmc_dmi_match, "Apple iMac 6", {
1444 DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
1445 DMI_MATCH(DMI_PRODUCT_NAME, "iMac6") },
1446 &applesmc_dmi_data[14]},
6e3530fa
HR
1447 { applesmc_dmi_match, "Apple iMac 5", {
1448 DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
1449 DMI_MATCH(DMI_PRODUCT_NAME, "iMac5") },
1450 &applesmc_dmi_data[10]},
9f86f28d
RDI
1451 { applesmc_dmi_match, "Apple iMac", {
1452 DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
1453 DMI_MATCH(DMI_PRODUCT_NAME,"iMac") },
7b5e3cb2 1454 &applesmc_dmi_data[5]},
6f2fad74
NB
1455 { .ident = NULL }
1456};
1457
1458static int __init applesmc_init(void)
1459{
1460 int ret;
1461 int count;
1462 int i;
1463
6f2fad74
NB
1464 if (!dmi_check_system(applesmc_whitelist)) {
1465 printk(KERN_WARNING "applesmc: supported laptop not found!\n");
1466 ret = -ENODEV;
1467 goto out;
1468 }
1469
1470 if (!request_region(APPLESMC_DATA_PORT, APPLESMC_NR_PORTS,
1471 "applesmc")) {
1472 ret = -ENXIO;
1473 goto out;
1474 }
1475
1476 ret = platform_driver_register(&applesmc_driver);
1477 if (ret)
1478 goto out_region;
1479
ddfbf2af
JD
1480 pdev = platform_device_register_simple("applesmc", APPLESMC_DATA_PORT,
1481 NULL, 0);
6f2fad74
NB
1482 if (IS_ERR(pdev)) {
1483 ret = PTR_ERR(pdev);
1484 goto out_driver;
1485 }
1486
fa74419b 1487 ret = sysfs_create_file(&pdev->dev.kobj, &dev_attr_name.attr);
6996abf0
NB
1488 if (ret)
1489 goto out_device;
fa74419b 1490
6f2fad74
NB
1491 /* Create key enumeration sysfs files */
1492 ret = sysfs_create_group(&pdev->dev.kobj, &key_enumeration_group);
1493 if (ret)
6996abf0 1494 goto out_name;
6f2fad74
NB
1495
1496 /* create fan files */
1497 count = applesmc_get_fan_count();
0559a538 1498 if (count < 0)
6f2fad74 1499 printk(KERN_ERR "applesmc: Cannot get the number of fans.\n");
0559a538 1500 else
6f2fad74
NB
1501 printk(KERN_INFO "applesmc: %d fans found.\n", count);
1502
0559a538
HR
1503 if (count > 4) {
1504 count = 4;
1505 printk(KERN_WARNING "applesmc: More than 4 fans found,"
1506 " but at most 4 fans are supported"
1507 " by the driver.\n");
1508 }
1509
1510 while (fans_handled < count) {
1511 ret = sysfs_create_group(&pdev->dev.kobj,
1512 &fan_attribute_groups[fans_handled]);
1513 if (ret)
1514 goto out_fans;
1515 fans_handled++;
6f2fad74
NB
1516 }
1517
1518 for (i = 0;
1519 temperature_sensors_sets[applesmc_temperature_set][i] != NULL;
1520 i++) {
1521 if (temperature_attributes[i] == NULL) {
1522 printk(KERN_ERR "applesmc: More temperature sensors "
1523 "in temperature_sensors_sets (at least %i)"
1524 "than available sysfs files in "
1525 "temperature_attributes (%i), please report "
1526 "this bug.\n", i, i-1);
1527 goto out_temperature;
1528 }
1529 ret = sysfs_create_file(&pdev->dev.kobj,
1530 temperature_attributes[i]);
1531 if (ret)
1532 goto out_temperature;
1533 }
1534
1535 if (applesmc_accelerometer) {
1536 ret = applesmc_create_accelerometer();
1537 if (ret)
1538 goto out_temperature;
1539 }
1540
1541 if (applesmc_light) {
1542 /* Add light sensor file */
1543 ret = sysfs_create_file(&pdev->dev.kobj, &dev_attr_light.attr);
1544 if (ret)
1545 goto out_accelerometer;
1546
1547 /* Create the workqueue */
1548 applesmc_led_wq = create_singlethread_workqueue("applesmc-led");
1549 if (!applesmc_led_wq) {
1550 ret = -ENOMEM;
1551 goto out_light_sysfs;
1552 }
1553
1554 /* register as a led device */
1555 ret = led_classdev_register(&pdev->dev, &applesmc_backlight);
1556 if (ret < 0)
1557 goto out_light_wq;
1558 }
1559
1beeffe4
TJ
1560 hwmon_dev = hwmon_device_register(&pdev->dev);
1561 if (IS_ERR(hwmon_dev)) {
1562 ret = PTR_ERR(hwmon_dev);
6f2fad74
NB
1563 goto out_light_ledclass;
1564 }
1565
1566 printk(KERN_INFO "applesmc: driver successfully loaded.\n");
1567
1568 return 0;
1569
1570out_light_ledclass:
1571 if (applesmc_light)
1572 led_classdev_unregister(&applesmc_backlight);
1573out_light_wq:
1574 if (applesmc_light)
1575 destroy_workqueue(applesmc_led_wq);
1576out_light_sysfs:
1577 if (applesmc_light)
1578 sysfs_remove_file(&pdev->dev.kobj, &dev_attr_light.attr);
1579out_accelerometer:
1580 if (applesmc_accelerometer)
1581 applesmc_release_accelerometer();
1582out_temperature:
1583 sysfs_remove_group(&pdev->dev.kobj, &temperature_attributes_group);
0559a538
HR
1584out_fans:
1585 while (fans_handled)
1586 sysfs_remove_group(&pdev->dev.kobj,
1587 &fan_attribute_groups[--fans_handled]);
6f2fad74 1588 sysfs_remove_group(&pdev->dev.kobj, &key_enumeration_group);
6996abf0
NB
1589out_name:
1590 sysfs_remove_file(&pdev->dev.kobj, &dev_attr_name.attr);
6f2fad74
NB
1591out_device:
1592 platform_device_unregister(pdev);
1593out_driver:
1594 platform_driver_unregister(&applesmc_driver);
1595out_region:
1596 release_region(APPLESMC_DATA_PORT, APPLESMC_NR_PORTS);
1597out:
1598 printk(KERN_WARNING "applesmc: driver init failed (ret=%d)!\n", ret);
1599 return ret;
1600}
1601
1602static void __exit applesmc_exit(void)
1603{
1beeffe4 1604 hwmon_device_unregister(hwmon_dev);
6f2fad74
NB
1605 if (applesmc_light) {
1606 led_classdev_unregister(&applesmc_backlight);
1607 destroy_workqueue(applesmc_led_wq);
1608 sysfs_remove_file(&pdev->dev.kobj, &dev_attr_light.attr);
1609 }
1610 if (applesmc_accelerometer)
1611 applesmc_release_accelerometer();
1612 sysfs_remove_group(&pdev->dev.kobj, &temperature_attributes_group);
0559a538
HR
1613 while (fans_handled)
1614 sysfs_remove_group(&pdev->dev.kobj,
1615 &fan_attribute_groups[--fans_handled]);
6f2fad74 1616 sysfs_remove_group(&pdev->dev.kobj, &key_enumeration_group);
6996abf0 1617 sysfs_remove_file(&pdev->dev.kobj, &dev_attr_name.attr);
6f2fad74
NB
1618 platform_device_unregister(pdev);
1619 platform_driver_unregister(&applesmc_driver);
1620 release_region(APPLESMC_DATA_PORT, APPLESMC_NR_PORTS);
1621
1622 printk(KERN_INFO "applesmc: driver unloaded.\n");
1623}
1624
1625module_init(applesmc_init);
1626module_exit(applesmc_exit);
1627
1628MODULE_AUTHOR("Nicolas Boichat");
1629MODULE_DESCRIPTION("Apple SMC");
1630MODULE_LICENSE("GPL v2");
dc924efb 1631MODULE_DEVICE_TABLE(dmi, applesmc_whitelist);