linux/drivers/hwmon/applesmc.c
<<
>>
Prefs
   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 * Copyright (C) 2010 Henrik Rydberg <rydberg@euromail.se>
   8 *
   9 * Based on hdaps.c driver:
  10 * Copyright (C) 2005 Robert Love <rml@novell.com>
  11 * Copyright (C) 2005 Jesper Juhl <jesper.juhl@gmail.com>
  12 *
  13 * Fan control based on smcFanControl:
  14 * Copyright (C) 2006 Hendrik Holtmann <holtmann@mac.com>
  15 *
  16 * This program is free software; you can redistribute it and/or modify it
  17 * under the terms of the GNU General Public License v2 as published by the
  18 * Free Software Foundation.
  19 *
  20 * This program is distributed in the hope that it will be useful, but WITHOUT
  21 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  22 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  23 * more details.
  24 *
  25 * You should have received a copy of the GNU General Public License along with
  26 * this program; if not, write to the Free Software Foundation, Inc.,
  27 * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
  28 */
  29
  30#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  31
  32#include <linux/delay.h>
  33#include <linux/platform_device.h>
  34#include <linux/input-polldev.h>
  35#include <linux/kernel.h>
  36#include <linux/slab.h>
  37#include <linux/module.h>
  38#include <linux/timer.h>
  39#include <linux/dmi.h>
  40#include <linux/mutex.h>
  41#include <linux/hwmon-sysfs.h>
  42#include <linux/io.h>
  43#include <linux/leds.h>
  44#include <linux/hwmon.h>
  45#include <linux/workqueue.h>
  46
  47/* data port used by Apple SMC */
  48#define APPLESMC_DATA_PORT      0x300
  49/* command/status port used by Apple SMC */
  50#define APPLESMC_CMD_PORT       0x304
  51
  52#define APPLESMC_NR_PORTS       32 /* 0x300-0x31f */
  53
  54#define APPLESMC_MAX_DATA_LENGTH 32
  55
  56/* wait up to 32 ms for a status change. */
  57#define APPLESMC_MIN_WAIT       0x0040
  58#define APPLESMC_MAX_WAIT       0x8000
  59
  60#define APPLESMC_STATUS_MASK    0x0f
  61#define APPLESMC_READ_CMD       0x10
  62#define APPLESMC_WRITE_CMD      0x11
  63#define APPLESMC_GET_KEY_BY_INDEX_CMD   0x12
  64#define APPLESMC_GET_KEY_TYPE_CMD       0x13
  65
  66#define KEY_COUNT_KEY           "#KEY" /* r-o ui32 */
  67
  68#define LIGHT_SENSOR_LEFT_KEY   "ALV0" /* r-o {alv (6-10 bytes) */
  69#define LIGHT_SENSOR_RIGHT_KEY  "ALV1" /* r-o {alv (6-10 bytes) */
  70#define BACKLIGHT_KEY           "LKSB" /* w-o {lkb (2 bytes) */
  71
  72#define CLAMSHELL_KEY           "MSLD" /* r-o ui8 (unused) */
  73
  74#define MOTION_SENSOR_X_KEY     "MO_X" /* r-o sp78 (2 bytes) */
  75#define MOTION_SENSOR_Y_KEY     "MO_Y" /* r-o sp78 (2 bytes) */
  76#define MOTION_SENSOR_Z_KEY     "MO_Z" /* r-o sp78 (2 bytes) */
  77#define MOTION_SENSOR_KEY       "MOCN" /* r/w ui16 */
  78
  79#define FANS_COUNT              "FNum" /* r-o ui8 */
  80#define FANS_MANUAL             "FS! " /* r-w ui16 */
  81#define FAN_ID_FMT              "F%dID" /* r-o char[16] */
  82
  83/* List of keys used to read/write fan speeds */
  84static const char *const fan_speed_fmt[] = {
  85        "F%dAc",                /* actual speed */
  86        "F%dMn",                /* minimum speed (rw) */
  87        "F%dMx",                /* maximum speed */
  88        "F%dSf",                /* safe speed - not all models */
  89        "F%dTg",                /* target speed (manual: rw) */
  90};
  91
  92#define INIT_TIMEOUT_MSECS      5000    /* wait up to 5s for device init ... */
  93#define INIT_WAIT_MSECS         50      /* ... in 50ms increments */
  94
  95#define APPLESMC_POLL_INTERVAL  50      /* msecs */
  96#define APPLESMC_INPUT_FUZZ     4       /* input event threshold */
  97#define APPLESMC_INPUT_FLAT     4
  98
  99#define SENSOR_X 0
 100#define SENSOR_Y 1
 101#define SENSOR_Z 2
 102
 103#define to_index(attr) (to_sensor_dev_attr(attr)->index & 0xffff)
 104#define to_option(attr) (to_sensor_dev_attr(attr)->index >> 16)
 105
 106/* Dynamic device node attributes */
 107struct applesmc_dev_attr {
 108        struct sensor_device_attribute sda;     /* hwmon attributes */
 109        char name[32];                          /* room for node file name */
 110};
 111
 112/* Dynamic device node group */
 113struct applesmc_node_group {
 114        char *format;                           /* format string */
 115        void *show;                             /* show function */
 116        void *store;                            /* store function */
 117        int option;                             /* function argument */
 118        struct applesmc_dev_attr *nodes;        /* dynamic node array */
 119};
 120
 121/* AppleSMC entry - cached register information */
 122struct applesmc_entry {
 123        char key[5];            /* four-letter key code */
 124        u8 valid;               /* set when entry is successfully read once */
 125        u8 len;                 /* bounded by APPLESMC_MAX_DATA_LENGTH */
 126        char type[5];           /* four-letter type code */
 127        u8 flags;               /* 0x10: func; 0x40: write; 0x80: read */
 128};
 129
 130/* Register lookup and registers common to all SMCs */
 131static struct applesmc_registers {
 132        struct mutex mutex;             /* register read/write mutex */
 133        unsigned int key_count;         /* number of SMC registers */
 134        unsigned int fan_count;         /* number of fans */
 135        unsigned int temp_count;        /* number of temperature registers */
 136        unsigned int temp_begin;        /* temperature lower index bound */
 137        unsigned int temp_end;          /* temperature upper index bound */
 138        int num_light_sensors;          /* number of light sensors */
 139        bool has_accelerometer;         /* has motion sensor */
 140        bool has_key_backlight;         /* has keyboard backlight */
 141        bool init_complete;             /* true when fully initialized */
 142        struct applesmc_entry *cache;   /* cached key entries */
 143} smcreg = {
 144        .mutex = __MUTEX_INITIALIZER(smcreg.mutex),
 145};
 146
 147static const int debug;
 148static struct platform_device *pdev;
 149static s16 rest_x;
 150static s16 rest_y;
 151static u8 backlight_state[2];
 152
 153static struct device *hwmon_dev;
 154static struct input_polled_dev *applesmc_idev;
 155
 156/*
 157 * Last index written to key_at_index sysfs file, and value to use for all other
 158 * key_at_index_* sysfs files.
 159 */
 160static unsigned int key_at_index;
 161
 162static struct workqueue_struct *applesmc_led_wq;
 163
 164/*
 165 * __wait_status - Wait up to 32ms for the status port to get a certain value
 166 * (masked with 0x0f), returning zero if the value is obtained.  Callers must
 167 * hold applesmc_lock.
 168 */
 169static int __wait_status(u8 val)
 170{
 171        int us;
 172
 173        val = val & APPLESMC_STATUS_MASK;
 174
 175        for (us = APPLESMC_MIN_WAIT; us < APPLESMC_MAX_WAIT; us <<= 1) {
 176                udelay(us);
 177                if ((inb(APPLESMC_CMD_PORT) & APPLESMC_STATUS_MASK) == val)
 178                        return 0;
 179        }
 180
 181        return -EIO;
 182}
 183
 184/*
 185 * special treatment of command port - on newer macbooks, it seems necessary
 186 * to resend the command byte before polling the status again. Callers must
 187 * hold applesmc_lock.
 188 */
 189static int send_command(u8 cmd)
 190{
 191        int us;
 192        for (us = APPLESMC_MIN_WAIT; us < APPLESMC_MAX_WAIT; us <<= 1) {
 193                outb(cmd, APPLESMC_CMD_PORT);
 194                udelay(us);
 195                if ((inb(APPLESMC_CMD_PORT) & APPLESMC_STATUS_MASK) == 0x0c)
 196                        return 0;
 197        }
 198        return -EIO;
 199}
 200
 201static int send_argument(const char *key)
 202{
 203        int i;
 204
 205        for (i = 0; i < 4; i++) {
 206                outb(key[i], APPLESMC_DATA_PORT);
 207                if (__wait_status(0x04))
 208                        return -EIO;
 209        }
 210        return 0;
 211}
 212
 213static int read_smc(u8 cmd, const char *key, u8 *buffer, u8 len)
 214{
 215        int i;
 216
 217        if (send_command(cmd) || send_argument(key)) {
 218                pr_warn("%s: read arg fail\n", key);
 219                return -EIO;
 220        }
 221
 222        outb(len, APPLESMC_DATA_PORT);
 223
 224        for (i = 0; i < len; i++) {
 225                if (__wait_status(0x05)) {
 226                        pr_warn("%s: read data fail\n", key);
 227                        return -EIO;
 228                }
 229                buffer[i] = inb(APPLESMC_DATA_PORT);
 230        }
 231
 232        return 0;
 233}
 234
 235static int write_smc(u8 cmd, const char *key, const u8 *buffer, u8 len)
 236{
 237        int i;
 238
 239        if (send_command(cmd) || send_argument(key)) {
 240                pr_warn("%s: write arg fail\n", key);
 241                return -EIO;
 242        }
 243
 244        outb(len, APPLESMC_DATA_PORT);
 245
 246        for (i = 0; i < len; i++) {
 247                if (__wait_status(0x04)) {
 248                        pr_warn("%s: write data fail\n", key);
 249                        return -EIO;
 250                }
 251                outb(buffer[i], APPLESMC_DATA_PORT);
 252        }
 253
 254        return 0;
 255}
 256
 257static int read_register_count(unsigned int *count)
 258{
 259        __be32 be;
 260        int ret;
 261
 262        ret = read_smc(APPLESMC_READ_CMD, KEY_COUNT_KEY, (u8 *)&be, 4);
 263        if (ret)
 264                return ret;
 265
 266        *count = be32_to_cpu(be);
 267        return 0;
 268}
 269
 270/*
 271 * Serialized I/O
 272 *
 273 * Returns zero on success or a negative error on failure.
 274 * All functions below are concurrency safe - callers should NOT hold lock.
 275 */
 276
 277static int applesmc_read_entry(const struct applesmc_entry *entry,
 278                               u8 *buf, u8 len)
 279{
 280        int ret;
 281
 282        if (entry->len != len)
 283                return -EINVAL;
 284        mutex_lock(&smcreg.mutex);
 285        ret = read_smc(APPLESMC_READ_CMD, entry->key, buf, len);
 286        mutex_unlock(&smcreg.mutex);
 287
 288        return ret;
 289}
 290
 291static int applesmc_write_entry(const struct applesmc_entry *entry,
 292                                const u8 *buf, u8 len)
 293{
 294        int ret;
 295
 296        if (entry->len != len)
 297                return -EINVAL;
 298        mutex_lock(&smcreg.mutex);
 299        ret = write_smc(APPLESMC_WRITE_CMD, entry->key, buf, len);
 300        mutex_unlock(&smcreg.mutex);
 301        return ret;
 302}
 303
 304static const struct applesmc_entry *applesmc_get_entry_by_index(int index)
 305{
 306        struct applesmc_entry *cache = &smcreg.cache[index];
 307        u8 key[4], info[6];
 308        __be32 be;
 309        int ret = 0;
 310
 311        if (cache->valid)
 312                return cache;
 313
 314        mutex_lock(&smcreg.mutex);
 315
 316        if (cache->valid)
 317                goto out;
 318        be = cpu_to_be32(index);
 319        ret = read_smc(APPLESMC_GET_KEY_BY_INDEX_CMD, (u8 *)&be, key, 4);
 320        if (ret)
 321                goto out;
 322        ret = read_smc(APPLESMC_GET_KEY_TYPE_CMD, key, info, 6);
 323        if (ret)
 324                goto out;
 325
 326        memcpy(cache->key, key, 4);
 327        cache->len = info[0];
 328        memcpy(cache->type, &info[1], 4);
 329        cache->flags = info[5];
 330        cache->valid = 1;
 331
 332out:
 333        mutex_unlock(&smcreg.mutex);
 334        if (ret)
 335                return ERR_PTR(ret);
 336        return cache;
 337}
 338
 339static int applesmc_get_lower_bound(unsigned int *lo, const char *key)
 340{
 341        int begin = 0, end = smcreg.key_count;
 342        const struct applesmc_entry *entry;
 343
 344        while (begin != end) {
 345                int middle = begin + (end - begin) / 2;
 346                entry = applesmc_get_entry_by_index(middle);
 347                if (IS_ERR(entry))
 348                        return PTR_ERR(entry);
 349                if (strcmp(entry->key, key) < 0)
 350                        begin = middle + 1;
 351                else
 352                        end = middle;
 353        }
 354
 355        *lo = begin;
 356        return 0;
 357}
 358
 359static int applesmc_get_upper_bound(unsigned int *hi, const char *key)
 360{
 361        int begin = 0, end = smcreg.key_count;
 362        const struct applesmc_entry *entry;
 363
 364        while (begin != end) {
 365                int middle = begin + (end - begin) / 2;
 366                entry = applesmc_get_entry_by_index(middle);
 367                if (IS_ERR(entry))
 368                        return PTR_ERR(entry);
 369                if (strcmp(key, entry->key) < 0)
 370                        end = middle;
 371                else
 372                        begin = middle + 1;
 373        }
 374
 375        *hi = begin;
 376        return 0;
 377}
 378
 379static const struct applesmc_entry *applesmc_get_entry_by_key(const char *key)
 380{
 381        int begin, end;
 382        int ret;
 383
 384        ret = applesmc_get_lower_bound(&begin, key);
 385        if (ret)
 386                return ERR_PTR(ret);
 387        ret = applesmc_get_upper_bound(&end, key);
 388        if (ret)
 389                return ERR_PTR(ret);
 390        if (end - begin != 1)
 391                return ERR_PTR(-EINVAL);
 392
 393        return applesmc_get_entry_by_index(begin);
 394}
 395
 396static int applesmc_read_key(const char *key, u8 *buffer, u8 len)
 397{
 398        const struct applesmc_entry *entry;
 399
 400        entry = applesmc_get_entry_by_key(key);
 401        if (IS_ERR(entry))
 402                return PTR_ERR(entry);
 403
 404        return applesmc_read_entry(entry, buffer, len);
 405}
 406
 407static int applesmc_write_key(const char *key, const u8 *buffer, u8 len)
 408{
 409        const struct applesmc_entry *entry;
 410
 411        entry = applesmc_get_entry_by_key(key);
 412        if (IS_ERR(entry))
 413                return PTR_ERR(entry);
 414
 415        return applesmc_write_entry(entry, buffer, len);
 416}
 417
 418static int applesmc_has_key(const char *key, bool *value)
 419{
 420        const struct applesmc_entry *entry;
 421
 422        entry = applesmc_get_entry_by_key(key);
 423        if (IS_ERR(entry) && PTR_ERR(entry) != -EINVAL)
 424                return PTR_ERR(entry);
 425
 426        *value = !IS_ERR(entry);
 427        return 0;
 428}
 429
 430/*
 431 * applesmc_read_motion_sensor - Read motion sensor (X, Y or Z).
 432 */
 433static int applesmc_read_motion_sensor(int index, s16 *value)
 434{
 435        u8 buffer[2];
 436        int ret;
 437
 438        switch (index) {
 439        case SENSOR_X:
 440                ret = applesmc_read_key(MOTION_SENSOR_X_KEY, buffer, 2);
 441                break;
 442        case SENSOR_Y:
 443                ret = applesmc_read_key(MOTION_SENSOR_Y_KEY, buffer, 2);
 444                break;
 445        case SENSOR_Z:
 446                ret = applesmc_read_key(MOTION_SENSOR_Z_KEY, buffer, 2);
 447                break;
 448        default:
 449                ret = -EINVAL;
 450        }
 451
 452        *value = ((s16)buffer[0] << 8) | buffer[1];
 453
 454        return ret;
 455}
 456
 457/*
 458 * applesmc_device_init - initialize the accelerometer.  Can sleep.
 459 */
 460static void applesmc_device_init(void)
 461{
 462        int total;
 463        u8 buffer[2];
 464
 465        if (!smcreg.has_accelerometer)
 466                return;
 467
 468        for (total = INIT_TIMEOUT_MSECS; total > 0; total -= INIT_WAIT_MSECS) {
 469                if (!applesmc_read_key(MOTION_SENSOR_KEY, buffer, 2) &&
 470                                (buffer[0] != 0x00 || buffer[1] != 0x00))
 471                        return;
 472                buffer[0] = 0xe0;
 473                buffer[1] = 0x00;
 474                applesmc_write_key(MOTION_SENSOR_KEY, buffer, 2);
 475                msleep(INIT_WAIT_MSECS);
 476        }
 477
 478        pr_warn("failed to init the device\n");
 479}
 480
 481/*
 482 * applesmc_init_smcreg_try - Try to initialize register cache. Idempotent.
 483 */
 484static int applesmc_init_smcreg_try(void)
 485{
 486        struct applesmc_registers *s = &smcreg;
 487        bool left_light_sensor, right_light_sensor;
 488        u8 tmp[1];
 489        int ret;
 490
 491        if (s->init_complete)
 492                return 0;
 493
 494        ret = read_register_count(&s->key_count);
 495        if (ret)
 496                return ret;
 497
 498        if (!s->cache)
 499                s->cache = kcalloc(s->key_count, sizeof(*s->cache), GFP_KERNEL);
 500        if (!s->cache)
 501                return -ENOMEM;
 502
 503        ret = applesmc_read_key(FANS_COUNT, tmp, 1);
 504        if (ret)
 505                return ret;
 506        s->fan_count = tmp[0];
 507
 508        ret = applesmc_get_lower_bound(&s->temp_begin, "T");
 509        if (ret)
 510                return ret;
 511        ret = applesmc_get_lower_bound(&s->temp_end, "U");
 512        if (ret)
 513                return ret;
 514        s->temp_count = s->temp_end - s->temp_begin;
 515
 516        ret = applesmc_has_key(LIGHT_SENSOR_LEFT_KEY, &left_light_sensor);
 517        if (ret)
 518                return ret;
 519        ret = applesmc_has_key(LIGHT_SENSOR_RIGHT_KEY, &right_light_sensor);
 520        if (ret)
 521                return ret;
 522        ret = applesmc_has_key(MOTION_SENSOR_KEY, &s->has_accelerometer);
 523        if (ret)
 524                return ret;
 525        ret = applesmc_has_key(BACKLIGHT_KEY, &s->has_key_backlight);
 526        if (ret)
 527                return ret;
 528
 529        s->num_light_sensors = left_light_sensor + right_light_sensor;
 530        s->init_complete = true;
 531
 532        pr_info("key=%d fan=%d temp=%d acc=%d lux=%d kbd=%d\n",
 533               s->key_count, s->fan_count, s->temp_count,
 534               s->has_accelerometer,
 535               s->num_light_sensors,
 536               s->has_key_backlight);
 537
 538        return 0;
 539}
 540
 541/*
 542 * applesmc_init_smcreg - Initialize register cache.
 543 *
 544 * Retries until initialization is successful, or the operation times out.
 545 *
 546 */
 547static int applesmc_init_smcreg(void)
 548{
 549        int ms, ret;
 550
 551        for (ms = 0; ms < INIT_TIMEOUT_MSECS; ms += INIT_WAIT_MSECS) {
 552                ret = applesmc_init_smcreg_try();
 553                if (!ret) {
 554                        if (ms)
 555                                pr_info("init_smcreg() took %d ms\n", ms);
 556                        return 0;
 557                }
 558                msleep(INIT_WAIT_MSECS);
 559        }
 560
 561        kfree(smcreg.cache);
 562        smcreg.cache = NULL;
 563
 564        return ret;
 565}
 566
 567static void applesmc_destroy_smcreg(void)
 568{
 569        kfree(smcreg.cache);
 570        smcreg.cache = NULL;
 571        smcreg.init_complete = false;
 572}
 573
 574/* Device model stuff */
 575static int applesmc_probe(struct platform_device *dev)
 576{
 577        int ret;
 578
 579        ret = applesmc_init_smcreg();
 580        if (ret)
 581                return ret;
 582
 583        applesmc_device_init();
 584
 585        return 0;
 586}
 587
 588/* Synchronize device with memorized backlight state */
 589static int applesmc_pm_resume(struct device *dev)
 590{
 591        if (smcreg.has_key_backlight)
 592                applesmc_write_key(BACKLIGHT_KEY, backlight_state, 2);
 593        return 0;
 594}
 595
 596/* Reinitialize device on resume from hibernation */
 597static int applesmc_pm_restore(struct device *dev)
 598{
 599        applesmc_device_init();
 600        return applesmc_pm_resume(dev);
 601}
 602
 603static const struct dev_pm_ops applesmc_pm_ops = {
 604        .resume = applesmc_pm_resume,
 605        .restore = applesmc_pm_restore,
 606};
 607
 608static struct platform_driver applesmc_driver = {
 609        .probe = applesmc_probe,
 610        .driver = {
 611                .name = "applesmc",
 612                .owner = THIS_MODULE,
 613                .pm = &applesmc_pm_ops,
 614        },
 615};
 616
 617/*
 618 * applesmc_calibrate - Set our "resting" values.  Callers must
 619 * hold applesmc_lock.
 620 */
 621static void applesmc_calibrate(void)
 622{
 623        applesmc_read_motion_sensor(SENSOR_X, &rest_x);
 624        applesmc_read_motion_sensor(SENSOR_Y, &rest_y);
 625        rest_x = -rest_x;
 626}
 627
 628static void applesmc_idev_poll(struct input_polled_dev *dev)
 629{
 630        struct input_dev *idev = dev->input;
 631        s16 x, y;
 632
 633        if (applesmc_read_motion_sensor(SENSOR_X, &x))
 634                return;
 635        if (applesmc_read_motion_sensor(SENSOR_Y, &y))
 636                return;
 637
 638        x = -x;
 639        input_report_abs(idev, ABS_X, x - rest_x);
 640        input_report_abs(idev, ABS_Y, y - rest_y);
 641        input_sync(idev);
 642}
 643
 644/* Sysfs Files */
 645
 646static ssize_t applesmc_name_show(struct device *dev,
 647                                   struct device_attribute *attr, char *buf)
 648{
 649        return snprintf(buf, PAGE_SIZE, "applesmc\n");
 650}
 651
 652static ssize_t applesmc_position_show(struct device *dev,
 653                                   struct device_attribute *attr, char *buf)
 654{
 655        int ret;
 656        s16 x, y, z;
 657
 658        ret = applesmc_read_motion_sensor(SENSOR_X, &x);
 659        if (ret)
 660                goto out;
 661        ret = applesmc_read_motion_sensor(SENSOR_Y, &y);
 662        if (ret)
 663                goto out;
 664        ret = applesmc_read_motion_sensor(SENSOR_Z, &z);
 665        if (ret)
 666                goto out;
 667
 668out:
 669        if (ret)
 670                return ret;
 671        else
 672                return snprintf(buf, PAGE_SIZE, "(%d,%d,%d)\n", x, y, z);
 673}
 674
 675static ssize_t applesmc_light_show(struct device *dev,
 676                                struct device_attribute *attr, char *sysfsbuf)
 677{
 678        const struct applesmc_entry *entry;
 679        static int data_length;
 680        int ret;
 681        u8 left = 0, right = 0;
 682        u8 buffer[10];
 683
 684        if (!data_length) {
 685                entry = applesmc_get_entry_by_key(LIGHT_SENSOR_LEFT_KEY);
 686                if (IS_ERR(entry))
 687                        return PTR_ERR(entry);
 688                if (entry->len > 10)
 689                        return -ENXIO;
 690                data_length = entry->len;
 691                pr_info("light sensor data length set to %d\n", data_length);
 692        }
 693
 694        ret = applesmc_read_key(LIGHT_SENSOR_LEFT_KEY, buffer, data_length);
 695        /* newer macbooks report a single 10-bit bigendian value */
 696        if (data_length == 10) {
 697                left = be16_to_cpu(*(__be16 *)(buffer + 6)) >> 2;
 698                goto out;
 699        }
 700        left = buffer[2];
 701        if (ret)
 702                goto out;
 703        ret = applesmc_read_key(LIGHT_SENSOR_RIGHT_KEY, buffer, data_length);
 704        right = buffer[2];
 705
 706out:
 707        if (ret)
 708                return ret;
 709        else
 710                return snprintf(sysfsbuf, PAGE_SIZE, "(%d,%d)\n", left, right);
 711}
 712
 713/* Displays sensor key as label */
 714static ssize_t applesmc_show_sensor_label(struct device *dev,
 715                        struct device_attribute *devattr, char *sysfsbuf)
 716{
 717        int index = smcreg.temp_begin + to_index(devattr);
 718        const struct applesmc_entry *entry;
 719
 720        entry = applesmc_get_entry_by_index(index);
 721        if (IS_ERR(entry))
 722                return PTR_ERR(entry);
 723
 724        return snprintf(sysfsbuf, PAGE_SIZE, "%s\n", entry->key);
 725}
 726
 727/* Displays degree Celsius * 1000 */
 728static ssize_t applesmc_show_temperature(struct device *dev,
 729                        struct device_attribute *devattr, char *sysfsbuf)
 730{
 731        int index = smcreg.temp_begin + to_index(devattr);
 732        const struct applesmc_entry *entry;
 733        int ret;
 734        u8 buffer[2];
 735        unsigned int temp;
 736
 737        entry = applesmc_get_entry_by_index(index);
 738        if (IS_ERR(entry))
 739                return PTR_ERR(entry);
 740        if (entry->len > 2)
 741                return -EINVAL;
 742
 743        ret = applesmc_read_entry(entry, buffer, entry->len);
 744        if (ret)
 745                return ret;
 746
 747        if (entry->len == 2) {
 748                temp = buffer[0] * 1000;
 749                temp += (buffer[1] >> 6) * 250;
 750        } else {
 751                temp = buffer[0] * 4000;
 752        }
 753
 754        return snprintf(sysfsbuf, PAGE_SIZE, "%u\n", temp);
 755}
 756
 757static ssize_t applesmc_show_fan_speed(struct device *dev,
 758                                struct device_attribute *attr, char *sysfsbuf)
 759{
 760        int ret;
 761        unsigned int speed = 0;
 762        char newkey[5];
 763        u8 buffer[2];
 764
 765        sprintf(newkey, fan_speed_fmt[to_option(attr)], to_index(attr));
 766
 767        ret = applesmc_read_key(newkey, buffer, 2);
 768        speed = ((buffer[0] << 8 | buffer[1]) >> 2);
 769
 770        if (ret)
 771                return ret;
 772        else
 773                return snprintf(sysfsbuf, PAGE_SIZE, "%u\n", speed);
 774}
 775
 776static ssize_t applesmc_store_fan_speed(struct device *dev,
 777                                        struct device_attribute *attr,
 778                                        const char *sysfsbuf, size_t count)
 779{
 780        int ret;
 781        unsigned long speed;
 782        char newkey[5];
 783        u8 buffer[2];
 784
 785        if (strict_strtoul(sysfsbuf, 10, &speed) < 0 || speed >= 0x4000)
 786                return -EINVAL;         /* Bigger than a 14-bit value */
 787
 788        sprintf(newkey, fan_speed_fmt[to_option(attr)], to_index(attr));
 789
 790        buffer[0] = (speed >> 6) & 0xff;
 791        buffer[1] = (speed << 2) & 0xff;
 792        ret = applesmc_write_key(newkey, buffer, 2);
 793
 794        if (ret)
 795                return ret;
 796        else
 797                return count;
 798}
 799
 800static ssize_t applesmc_show_fan_manual(struct device *dev,
 801                        struct device_attribute *attr, char *sysfsbuf)
 802{
 803        int ret;
 804        u16 manual = 0;
 805        u8 buffer[2];
 806
 807        ret = applesmc_read_key(FANS_MANUAL, buffer, 2);
 808        manual = ((buffer[0] << 8 | buffer[1]) >> to_index(attr)) & 0x01;
 809
 810        if (ret)
 811                return ret;
 812        else
 813                return snprintf(sysfsbuf, PAGE_SIZE, "%d\n", manual);
 814}
 815
 816static ssize_t applesmc_store_fan_manual(struct device *dev,
 817                                         struct device_attribute *attr,
 818                                         const char *sysfsbuf, size_t count)
 819{
 820        int ret;
 821        u8 buffer[2];
 822        unsigned long input;
 823        u16 val;
 824
 825        if (strict_strtoul(sysfsbuf, 10, &input) < 0)
 826                return -EINVAL;
 827
 828        ret = applesmc_read_key(FANS_MANUAL, buffer, 2);
 829        val = (buffer[0] << 8 | buffer[1]);
 830        if (ret)
 831                goto out;
 832
 833        if (input)
 834                val = val | (0x01 << to_index(attr));
 835        else
 836                val = val & ~(0x01 << to_index(attr));
 837
 838        buffer[0] = (val >> 8) & 0xFF;
 839        buffer[1] = val & 0xFF;
 840
 841        ret = applesmc_write_key(FANS_MANUAL, buffer, 2);
 842
 843out:
 844        if (ret)
 845                return ret;
 846        else
 847                return count;
 848}
 849
 850static ssize_t applesmc_show_fan_position(struct device *dev,
 851                                struct device_attribute *attr, char *sysfsbuf)
 852{
 853        int ret;
 854        char newkey[5];
 855        u8 buffer[17];
 856
 857        sprintf(newkey, FAN_ID_FMT, to_index(attr));
 858
 859        ret = applesmc_read_key(newkey, buffer, 16);
 860        buffer[16] = 0;
 861
 862        if (ret)
 863                return ret;
 864        else
 865                return snprintf(sysfsbuf, PAGE_SIZE, "%s\n", buffer+4);
 866}
 867
 868static ssize_t applesmc_calibrate_show(struct device *dev,
 869                                struct device_attribute *attr, char *sysfsbuf)
 870{
 871        return snprintf(sysfsbuf, PAGE_SIZE, "(%d,%d)\n", rest_x, rest_y);
 872}
 873
 874static ssize_t applesmc_calibrate_store(struct device *dev,
 875        struct device_attribute *attr, const char *sysfsbuf, size_t count)
 876{
 877        applesmc_calibrate();
 878
 879        return count;
 880}
 881
 882static void applesmc_backlight_set(struct work_struct *work)
 883{
 884        applesmc_write_key(BACKLIGHT_KEY, backlight_state, 2);
 885}
 886static DECLARE_WORK(backlight_work, &applesmc_backlight_set);
 887
 888static void applesmc_brightness_set(struct led_classdev *led_cdev,
 889                                                enum led_brightness value)
 890{
 891        int ret;
 892
 893        backlight_state[0] = value;
 894        ret = queue_work(applesmc_led_wq, &backlight_work);
 895
 896        if (debug && (!ret))
 897                printk(KERN_DEBUG "applesmc: work was already on the queue.\n");
 898}
 899
 900static ssize_t applesmc_key_count_show(struct device *dev,
 901                                struct device_attribute *attr, char *sysfsbuf)
 902{
 903        int ret;
 904        u8 buffer[4];
 905        u32 count;
 906
 907        ret = applesmc_read_key(KEY_COUNT_KEY, buffer, 4);
 908        count = ((u32)buffer[0]<<24) + ((u32)buffer[1]<<16) +
 909                                                ((u32)buffer[2]<<8) + buffer[3];
 910
 911        if (ret)
 912                return ret;
 913        else
 914                return snprintf(sysfsbuf, PAGE_SIZE, "%d\n", count);
 915}
 916
 917static ssize_t applesmc_key_at_index_read_show(struct device *dev,
 918                                struct device_attribute *attr, char *sysfsbuf)
 919{
 920        const struct applesmc_entry *entry;
 921        int ret;
 922
 923        entry = applesmc_get_entry_by_index(key_at_index);
 924        if (IS_ERR(entry))
 925                return PTR_ERR(entry);
 926        ret = applesmc_read_entry(entry, sysfsbuf, entry->len);
 927        if (ret)
 928                return ret;
 929
 930        return entry->len;
 931}
 932
 933static ssize_t applesmc_key_at_index_data_length_show(struct device *dev,
 934                                struct device_attribute *attr, char *sysfsbuf)
 935{
 936        const struct applesmc_entry *entry;
 937
 938        entry = applesmc_get_entry_by_index(key_at_index);
 939        if (IS_ERR(entry))
 940                return PTR_ERR(entry);
 941
 942        return snprintf(sysfsbuf, PAGE_SIZE, "%d\n", entry->len);
 943}
 944
 945static ssize_t applesmc_key_at_index_type_show(struct device *dev,
 946                                struct device_attribute *attr, char *sysfsbuf)
 947{
 948        const struct applesmc_entry *entry;
 949
 950        entry = applesmc_get_entry_by_index(key_at_index);
 951        if (IS_ERR(entry))
 952                return PTR_ERR(entry);
 953
 954        return snprintf(sysfsbuf, PAGE_SIZE, "%s\n", entry->type);
 955}
 956
 957static ssize_t applesmc_key_at_index_name_show(struct device *dev,
 958                                struct device_attribute *attr, char *sysfsbuf)
 959{
 960        const struct applesmc_entry *entry;
 961
 962        entry = applesmc_get_entry_by_index(key_at_index);
 963        if (IS_ERR(entry))
 964                return PTR_ERR(entry);
 965
 966        return snprintf(sysfsbuf, PAGE_SIZE, "%s\n", entry->key);
 967}
 968
 969static ssize_t applesmc_key_at_index_show(struct device *dev,
 970                                struct device_attribute *attr, char *sysfsbuf)
 971{
 972        return snprintf(sysfsbuf, PAGE_SIZE, "%d\n", key_at_index);
 973}
 974
 975static ssize_t applesmc_key_at_index_store(struct device *dev,
 976        struct device_attribute *attr, const char *sysfsbuf, size_t count)
 977{
 978        unsigned long newkey;
 979
 980        if (strict_strtoul(sysfsbuf, 10, &newkey) < 0
 981            || newkey >= smcreg.key_count)
 982                return -EINVAL;
 983
 984        key_at_index = newkey;
 985        return count;
 986}
 987
 988static struct led_classdev applesmc_backlight = {
 989        .name                   = "smc::kbd_backlight",
 990        .default_trigger        = "nand-disk",
 991        .brightness_set         = applesmc_brightness_set,
 992};
 993
 994static struct applesmc_node_group info_group[] = {
 995        { "name", applesmc_name_show },
 996        { "key_count", applesmc_key_count_show },
 997        { "key_at_index", applesmc_key_at_index_show, applesmc_key_at_index_store },
 998        { "key_at_index_name", applesmc_key_at_index_name_show },
 999        { "key_at_index_type", applesmc_key_at_index_type_show },
1000        { "key_at_index_data_length", applesmc_key_at_index_data_length_show },
1001        { "key_at_index_data", applesmc_key_at_index_read_show },
1002        { }
1003};
1004
1005static struct applesmc_node_group accelerometer_group[] = {
1006        { "position", applesmc_position_show },
1007        { "calibrate", applesmc_calibrate_show, applesmc_calibrate_store },
1008        { }
1009};
1010
1011static struct applesmc_node_group light_sensor_group[] = {
1012        { "light", applesmc_light_show },
1013        { }
1014};
1015
1016static struct applesmc_node_group fan_group[] = {
1017        { "fan%d_label", applesmc_show_fan_position },
1018        { "fan%d_input", applesmc_show_fan_speed, NULL, 0 },
1019        { "fan%d_min", applesmc_show_fan_speed, applesmc_store_fan_speed, 1 },
1020        { "fan%d_max", applesmc_show_fan_speed, NULL, 2 },
1021        { "fan%d_safe", applesmc_show_fan_speed, NULL, 3 },
1022        { "fan%d_output", applesmc_show_fan_speed, applesmc_store_fan_speed, 4 },
1023        { "fan%d_manual", applesmc_show_fan_manual, applesmc_store_fan_manual },
1024        { }
1025};
1026
1027static struct applesmc_node_group temp_group[] = {
1028        { "temp%d_label", applesmc_show_sensor_label },
1029        { "temp%d_input", applesmc_show_temperature },
1030        { }
1031};
1032
1033/* Module stuff */
1034
1035/*
1036 * applesmc_destroy_nodes - remove files and free associated memory
1037 */
1038static void applesmc_destroy_nodes(struct applesmc_node_group *groups)
1039{
1040        struct applesmc_node_group *grp;
1041        struct applesmc_dev_attr *node;
1042
1043        for (grp = groups; grp->nodes; grp++) {
1044                for (node = grp->nodes; node->sda.dev_attr.attr.name; node++)
1045                        sysfs_remove_file(&pdev->dev.kobj,
1046                                          &node->sda.dev_attr.attr);
1047                kfree(grp->nodes);
1048                grp->nodes = NULL;
1049        }
1050}
1051
1052/*
1053 * applesmc_create_nodes - create a two-dimensional group of sysfs files
1054 */
1055static int applesmc_create_nodes(struct applesmc_node_group *groups, int num)
1056{
1057        struct applesmc_node_group *grp;
1058        struct applesmc_dev_attr *node;
1059        struct attribute *attr;
1060        int ret, i;
1061
1062        for (grp = groups; grp->format; grp++) {
1063                grp->nodes = kcalloc(num + 1, sizeof(*node), GFP_KERNEL);
1064                if (!grp->nodes) {
1065                        ret = -ENOMEM;
1066                        goto out;
1067                }
1068                for (i = 0; i < num; i++) {
1069                        node = &grp->nodes[i];
1070                        sprintf(node->name, grp->format, i + 1);
1071                        node->sda.index = (grp->option << 16) | (i & 0xffff);
1072                        node->sda.dev_attr.show = grp->show;
1073                        node->sda.dev_attr.store = grp->store;
1074                        attr = &node->sda.dev_attr.attr;
1075                        sysfs_attr_init(attr);
1076                        attr->name = node->name;
1077                        attr->mode = S_IRUGO | (grp->store ? S_IWUSR : 0);
1078                        ret = sysfs_create_file(&pdev->dev.kobj, attr);
1079                        if (ret) {
1080                                attr->name = NULL;
1081                                goto out;
1082                        }
1083                }
1084        }
1085
1086        return 0;
1087out:
1088        applesmc_destroy_nodes(groups);
1089        return ret;
1090}
1091
1092/* Create accelerometer ressources */
1093static int applesmc_create_accelerometer(void)
1094{
1095        struct input_dev *idev;
1096        int ret;
1097
1098        if (!smcreg.has_accelerometer)
1099                return 0;
1100
1101        ret = applesmc_create_nodes(accelerometer_group, 1);
1102        if (ret)
1103                goto out;
1104
1105        applesmc_idev = input_allocate_polled_device();
1106        if (!applesmc_idev) {
1107                ret = -ENOMEM;
1108                goto out_sysfs;
1109        }
1110
1111        applesmc_idev->poll = applesmc_idev_poll;
1112        applesmc_idev->poll_interval = APPLESMC_POLL_INTERVAL;
1113
1114        /* initial calibrate for the input device */
1115        applesmc_calibrate();
1116
1117        /* initialize the input device */
1118        idev = applesmc_idev->input;
1119        idev->name = "applesmc";
1120        idev->id.bustype = BUS_HOST;
1121        idev->dev.parent = &pdev->dev;
1122        idev->evbit[0] = BIT_MASK(EV_ABS);
1123        input_set_abs_params(idev, ABS_X,
1124                        -256, 256, APPLESMC_INPUT_FUZZ, APPLESMC_INPUT_FLAT);
1125        input_set_abs_params(idev, ABS_Y,
1126                        -256, 256, APPLESMC_INPUT_FUZZ, APPLESMC_INPUT_FLAT);
1127
1128        ret = input_register_polled_device(applesmc_idev);
1129        if (ret)
1130                goto out_idev;
1131
1132        return 0;
1133
1134out_idev:
1135        input_free_polled_device(applesmc_idev);
1136
1137out_sysfs:
1138        applesmc_destroy_nodes(accelerometer_group);
1139
1140out:
1141        pr_warn("driver init failed (ret=%d)!\n", ret);
1142        return ret;
1143}
1144
1145/* Release all ressources used by the accelerometer */
1146static void applesmc_release_accelerometer(void)
1147{
1148        if (!smcreg.has_accelerometer)
1149                return;
1150        input_unregister_polled_device(applesmc_idev);
1151        input_free_polled_device(applesmc_idev);
1152        applesmc_destroy_nodes(accelerometer_group);
1153}
1154
1155static int applesmc_create_light_sensor(void)
1156{
1157        if (!smcreg.num_light_sensors)
1158                return 0;
1159        return applesmc_create_nodes(light_sensor_group, 1);
1160}
1161
1162static void applesmc_release_light_sensor(void)
1163{
1164        if (!smcreg.num_light_sensors)
1165                return;
1166        applesmc_destroy_nodes(light_sensor_group);
1167}
1168
1169static int applesmc_create_key_backlight(void)
1170{
1171        if (!smcreg.has_key_backlight)
1172                return 0;
1173        applesmc_led_wq = create_singlethread_workqueue("applesmc-led");
1174        if (!applesmc_led_wq)
1175                return -ENOMEM;
1176        return led_classdev_register(&pdev->dev, &applesmc_backlight);
1177}
1178
1179static void applesmc_release_key_backlight(void)
1180{
1181        if (!smcreg.has_key_backlight)
1182                return;
1183        led_classdev_unregister(&applesmc_backlight);
1184        destroy_workqueue(applesmc_led_wq);
1185}
1186
1187static int applesmc_dmi_match(const struct dmi_system_id *id)
1188{
1189        return 1;
1190}
1191
1192/* Note that DMI_MATCH(...,"MacBook") will match "MacBookPro1,1".
1193 * So we need to put "Apple MacBook Pro" before "Apple MacBook". */
1194static __initdata struct dmi_system_id applesmc_whitelist[] = {
1195        { applesmc_dmi_match, "Apple MacBook Air", {
1196          DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
1197          DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir") },
1198        },
1199        { applesmc_dmi_match, "Apple MacBook Pro", {
1200          DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
1201          DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro") },
1202        },
1203        { applesmc_dmi_match, "Apple MacBook", {
1204          DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
1205          DMI_MATCH(DMI_PRODUCT_NAME, "MacBook") },
1206        },
1207        { applesmc_dmi_match, "Apple Macmini", {
1208          DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
1209          DMI_MATCH(DMI_PRODUCT_NAME, "Macmini") },
1210        },
1211        { applesmc_dmi_match, "Apple MacPro", {
1212          DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
1213          DMI_MATCH(DMI_PRODUCT_NAME, "MacPro") },
1214        },
1215        { applesmc_dmi_match, "Apple iMac", {
1216          DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
1217          DMI_MATCH(DMI_PRODUCT_NAME, "iMac") },
1218        },
1219        { .ident = NULL }
1220};
1221
1222static int __init applesmc_init(void)
1223{
1224        int ret;
1225
1226        if (!dmi_check_system(applesmc_whitelist)) {
1227                pr_warn("supported laptop not found!\n");
1228                ret = -ENODEV;
1229                goto out;
1230        }
1231
1232        if (!request_region(APPLESMC_DATA_PORT, APPLESMC_NR_PORTS,
1233                                                                "applesmc")) {
1234                ret = -ENXIO;
1235                goto out;
1236        }
1237
1238        ret = platform_driver_register(&applesmc_driver);
1239        if (ret)
1240                goto out_region;
1241
1242        pdev = platform_device_register_simple("applesmc", APPLESMC_DATA_PORT,
1243                                               NULL, 0);
1244        if (IS_ERR(pdev)) {
1245                ret = PTR_ERR(pdev);
1246                goto out_driver;
1247        }
1248
1249        /* create register cache */
1250        ret = applesmc_init_smcreg();
1251        if (ret)
1252                goto out_device;
1253
1254        ret = applesmc_create_nodes(info_group, 1);
1255        if (ret)
1256                goto out_smcreg;
1257
1258        ret = applesmc_create_nodes(fan_group, smcreg.fan_count);
1259        if (ret)
1260                goto out_info;
1261
1262        ret = applesmc_create_nodes(temp_group, smcreg.temp_count);
1263        if (ret)
1264                goto out_fans;
1265
1266        ret = applesmc_create_accelerometer();
1267        if (ret)
1268                goto out_temperature;
1269
1270        ret = applesmc_create_light_sensor();
1271        if (ret)
1272                goto out_accelerometer;
1273
1274        ret = applesmc_create_key_backlight();
1275        if (ret)
1276                goto out_light_sysfs;
1277
1278        hwmon_dev = hwmon_device_register(&pdev->dev);
1279        if (IS_ERR(hwmon_dev)) {
1280                ret = PTR_ERR(hwmon_dev);
1281                goto out_light_ledclass;
1282        }
1283
1284        return 0;
1285
1286out_light_ledclass:
1287        applesmc_release_key_backlight();
1288out_light_sysfs:
1289        applesmc_release_light_sensor();
1290out_accelerometer:
1291        applesmc_release_accelerometer();
1292out_temperature:
1293        applesmc_destroy_nodes(temp_group);
1294out_fans:
1295        applesmc_destroy_nodes(fan_group);
1296out_info:
1297        applesmc_destroy_nodes(info_group);
1298out_smcreg:
1299        applesmc_destroy_smcreg();
1300out_device:
1301        platform_device_unregister(pdev);
1302out_driver:
1303        platform_driver_unregister(&applesmc_driver);
1304out_region:
1305        release_region(APPLESMC_DATA_PORT, APPLESMC_NR_PORTS);
1306out:
1307        pr_warn("driver init failed (ret=%d)!\n", ret);
1308        return ret;
1309}
1310
1311static void __exit applesmc_exit(void)
1312{
1313        hwmon_device_unregister(hwmon_dev);
1314        applesmc_release_key_backlight();
1315        applesmc_release_light_sensor();
1316        applesmc_release_accelerometer();
1317        applesmc_destroy_nodes(temp_group);
1318        applesmc_destroy_nodes(fan_group);
1319        applesmc_destroy_nodes(info_group);
1320        applesmc_destroy_smcreg();
1321        platform_device_unregister(pdev);
1322        platform_driver_unregister(&applesmc_driver);
1323        release_region(APPLESMC_DATA_PORT, APPLESMC_NR_PORTS);
1324}
1325
1326module_init(applesmc_init);
1327module_exit(applesmc_exit);
1328
1329MODULE_AUTHOR("Nicolas Boichat");
1330MODULE_DESCRIPTION("Apple SMC");
1331MODULE_LICENSE("GPL v2");
1332MODULE_DEVICE_TABLE(dmi, applesmc_whitelist);
1333