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