/*
* drivers/hwmon/applesmc.c - driver for Apple's SMC (accelerometer, temperature
* sensors, fan control, keyboard backlight control) used in Intel-based Apple
* computers.
*
* Copyright (C) 2007 Nicolas Boichat <nicolas@boichat.ch>
*
* Based on hdaps.c driver:
* Copyright (C) 2005 Robert Love <rml@novell.com>
* Copyright (C) 2005 Jesper Juhl <jesper.juhl@gmail.com>
*
* Fan control based on smcFanControl:
* Copyright (C) 2006 Hendrik Holtmann <holtmann@mac.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License v2 as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/input-polldev.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/timer.h>
#include <linux/dmi.h>
#include <linux/mutex.h>
#include <linux/hwmon-sysfs.h>
#include <linux/io.h>
#include <linux/leds.h>
#include <linux/hwmon.h>
#include <linux/workqueue.h>
/* data port used by Apple SMC */
#define APPLESMC_DATA_PORT 0x300
/* command/status port used by Apple SMC */
#define APPLESMC_CMD_PORT 0x304
#define APPLESMC_NR_PORTS 32 /* 0x300-0x31f */
#define APPLESMC_MAX_DATA_LENGTH 32
#define APPLESMC_MIN_WAIT 0x0040
#define APPLESMC_MAX_WAIT 0x8000
#define APPLESMC_STATUS_MASK 0x0f
#define APPLESMC_READ_CMD 0x10
#define APPLESMC_WRITE_CMD 0x11
#define APPLESMC_GET_KEY_BY_INDEX_CMD 0x12
#define APPLESMC_GET_KEY_TYPE_CMD 0x13
#define KEY_COUNT_KEY "#KEY" /* r-o ui32 */
#define LIGHT_SENSOR_LEFT_KEY "ALV0" /* r-o {alv (6-10 bytes) */
#define LIGHT_SENSOR_RIGHT_KEY "ALV1" /* r-o {alv (6-10 bytes) */
#define BACKLIGHT_KEY "LKSB" /* w-o {lkb (2 bytes) */
#define CLAMSHELL_KEY "MSLD" /* r-o ui8 (unused) */
#define MOTION_SENSOR_X_KEY "MO_X" /* r-o sp78 (2 bytes) */
#define MOTION_SENSOR_Y_KEY "MO_Y" /* r-o sp78 (2 bytes) */
#define MOTION_SENSOR_Z_KEY "MO_Z" /* r-o sp78 (2 bytes) */
#define MOTION_SENSOR_KEY "MOCN" /* r/w ui16 */
#define FANS_COUNT "FNum" /* r-o ui8 */
#define FANS_MANUAL "FS! " /* r-w ui16 */
#define FAN_ACTUAL_SPEED "F0Ac" /* r-o fpe2 (2 bytes) */
#define FAN_MIN_SPEED "F0Mn" /* r-o fpe2 (2 bytes) */
#define FAN_MAX_SPEED "F0Mx" /* r-o fpe2 (2 bytes) */
#define FAN_SAFE_SPEED "F0Sf" /* r-o fpe2 (2 bytes) */
#define FAN_TARGET_SPEED "F0Tg" /* r-w fpe2 (2 bytes) */
#define FAN_POSITION "F0ID" /* r-o char[16] */
/*
* Temperature sensors keys (sp78 - 2 bytes).
*/
static const char *temperature_sensors_sets[][41] = {
/* Set 0: Macbook Pro */
{ "TA0P", "TB0T", "TC0D", "TC0P", "TG0H", "TG0P", "TG0T", "Th0H",
"Th1H", "Tm0P", "Ts0P", "Ts1P", NULL },
/* Set 1: Macbook2 set */
{ "TB0T", "TC0D", "TC0P", "TM0P", "TN0P", "TN1P", "TTF0", "Th0H",
"Th0S", "Th1H", NULL },
/* Set 2: Macbook set */
{ "TB0T", "TC0D", "TC0P", "TM0P", "TN0P", "TN1P", "Th0H", "Th0S",
"Th1H", "Ts0P", NULL },
/* Set 3: Macmini set */
{ "TC0D", "TC0P", NULL },
/* Set 4: Mac Pro (2 x Quad-Core) */
{ "TA0P", "TCAG", "TCAH", "TCBG", "TCBH", "TC0C", "TC0D", "TC0P",
"TC1C", "TC1D", "TC2C", "TC2D", "TC3C", "TC3D", "THTG", "TH0P",
"TH1P", "TH2P", "TH3P", "TMAP", "TMAS", "TMBS", "TM0P", "TM0S",
"TM1P", "TM1S", "TM2P", "TM2S", "TM3S", "TM8P", "TM8S", "TM9P",
"TM9S", "TN0H", "TS0C", NULL },
/* Set 5: iMac */
{ "TC0D", "TA0P", "TG0P", "TG0D", "TG0H", "TH0P", "Tm0P", "TO0P",
"Tp0C", NULL },
/* Set 6: Macbook3 set */
{ "TB0T", "TC0D", "TC0P", "TM0P", "TN0P", "TTF0", "TW0P", "Th0H",
"Th0S", "Th1H", NULL },
/* Set 7: Macbook Air */
{ "TB0T", "TB1S", "TB1T"
|