|
From: <nbo...@us...> - 2007-04-12 16:38:08
|
Revision: 114
http://svn.sourceforge.net/mactel-linux/?rev=114&view=rev
Author: nboichat
Date: 2007-04-12 09:38:05 -0700 (Thu, 12 Apr 2007)
Log Message:
-----------
Fix applesmc patch, and break it in parts (standard and enum will be sent first to -mm, int needs more testing on different hardware).
Added Paths:
-----------
trunk/kernel/mactel-patches-2.6.21/0011-applesmc_standard.patch
trunk/kernel/mactel-patches-2.6.21/0012-applesmc_enum.patch
trunk/kernel/mactel-patches-2.6.21/0013-applesmc_int.patch
Removed Paths:
-------------
trunk/kernel/mactel-patches-2.6.21/0011-applesmc2.patch
Deleted: trunk/kernel/mactel-patches-2.6.21/0011-applesmc2.patch
===================================================================
--- trunk/kernel/mactel-patches-2.6.21/0011-applesmc2.patch 2007-04-12 16:36:44 UTC (rev 113)
+++ trunk/kernel/mactel-patches-2.6.21/0011-applesmc2.patch 2007-04-12 16:38:05 UTC (rev 114)
@@ -1,799 +0,0 @@
-New features for applesmc: 1. Add support for keys enumeration. 2. IRQ support for the accelerometer. 3. Add more temperature sensors on the Macbook Pro. 4. Add fan description reading.
-
-From: Nicolas Boichat <ni...@bo...>
-
-
----
-
- drivers/hwmon/applesmc.c | 601 +++++++++++++++++++++++++++++++++++++++++-----
- 1 files changed, 535 insertions(+), 66 deletions(-)
-
-diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c
-index f7b59fc..f320f7b 100644
---- a/drivers/hwmon/applesmc.c
-+++ b/drivers/hwmon/applesmc.c
-@@ -37,40 +37,69 @@
- #include <linux/hwmon-sysfs.h>
- #include <asm/io.h>
- #include <linux/leds.h>
-+#include <linux/interrupt.h>
-
--/* data port used by apple SMC */
--#define APPLESMC_DATA_PORT 0x300
--/* command/status port used by apple SMC */
--#define APPLESMC_CMD_PORT 0x304
-+/* data port used by Apple SMC */
-+#define APPLESMC_DATA_PORT 0x300
-+/* command/status port used by Apple SMC */
-+#define APPLESMC_CMD_PORT 0x304
-+/* status port used by Apple SMC to get which interrupt type just happened */
-+#define APPLESMC_INT_PORT 0x31f
-
--#define APPLESMC_NR_PORTS 5 /* 0x300-0x304 */
-+#define APPLESMC_NR_PORTS 32 /* 0x300-0x31f */
-
--#define APPLESMC_STATUS_MASK 0x0f
--#define APPLESMC_READ_CMD 0x10
--#define APPLESMC_WRITE_CMD 0x11
-+#define APPLESMC_MAX_DATA_LENGTH 32
-+
-+/* Defined in ACPI DSDT table, should we read it from there? */
-+#define APPLESMC_IRQ 6
-+
-+#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_INFO_CMD 0x13
-+
-+#define KEY_COUNT_KEY "#KEY" /* r-o ui32 */
-+
-+#define INTERRUPT_OK_KEY "NTOK" /* w-o ui8 */
-
- #define LIGHT_SENSOR_LEFT_KEY "ALV0" /* r-o length 6 */
- #define LIGHT_SENSOR_RIGHT_KEY "ALV1" /* r-o length 6 */
--#define BACKLIGHT_KEY "LKSB" /* w-o */
-+#define BACKLIGHT_KEY "LKSB" /* w-o length 2 */
-
--#define CLAMSHELL_KEY "MSLD" /* r-o length 1 (unused) */
-+#define CLAMSHELL_KEY "MSLD" /* r-o ui8 (unused) */
-
--#define MOTION_SENSOR_X_KEY "MO_X" /* r-o length 2 */
--#define MOTION_SENSOR_Y_KEY "MO_Y" /* r-o length 2 */
--#define MOTION_SENSOR_Z_KEY "MO_Z" /* r-o length 2 */
--#define MOTION_SENSOR_KEY "MOCN" /* r/w length 2 */
-+#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 length 1 */
--#define FANS_MANUAL "FS! " /* r-w length 2 */
--#define FAN_ACTUAL_SPEED "F0Ac" /* r-o length 2 */
--#define FAN_MIN_SPEED "F0Mn" /* r-o length 2 */
--#define FAN_MAX_SPEED "F0Mx" /* r-o length 2 */
--#define FAN_SAFE_SPEED "F0Sf" /* r-o length 2 */
--#define FAN_TARGET_SPEED "F0Tg" /* r-w length 2 */
-+/*
-+ * Interrupt controls.
-+ * If the norm of the position (sqrt(MO_X^2+MO_Y^2+MO_Z^2)) is smaller than
-+ * MOLT (free fall), or bigger than MOHT (high acceleration) for longer than the
-+ * value of MOLD (or MOHD), SMC will trigger an interrupt.
-+ */
-+#define MOTION_LOW_NORM "MOLT" /* r/w sp78 (2 bytes) */
-+#define MOTION_HIGH_NORM "MOHT" /* r/w sp78 (2 bytes) */
-+#define MOTION_LOW_NORM_INTERVAL "MOLD" /* r/w ui8 */
-+#define MOTION_HIGH_NORM_INTERVAL "MOHD" /* r/w ui8 */
-+
-+#define MSDW_KEY "MSDW" /* r/w flag (1 byte) */
-+
-+#define FANS_COUNT "FNum" /* r-o ui8 */
-+#define FANS_MANUAL "FS! " /* r-w ui16 */
-+#define FAN_ACTUAL_SPEED "F0Ac" /* r-o fpe2 */
-+#define FAN_MIN_SPEED "F0Mn" /* r-o fpe2 */
-+#define FAN_MAX_SPEED "F0Mx" /* r-o fpe2 */
-+#define FAN_SAFE_SPEED "F0Sf" /* r-o fpe2 */
-+#define FAN_TARGET_SPEED "F0Tg" /* r-w fpe2 */
-+#define FAN_ID "F0ID" /* r-o char[16] */
-
- /* Temperature sensors keys. First set for Macbook(Pro), second for Macmini */
--static const char* temperature_sensors_sets[][8] = {
-- { "TB0T", "TC0D", "TC0P", "Th0H", "Ts0P", "Th1H", "Ts1P", NULL },
-+static const char* temperature_sensors_sets[][13] = {
-+ { "TA0P", "TB0T", "TC0D", "TC0P", "TG0H", "TG0P", "TG0T", "Th0H",
-+ "Th1H", "Tm0P", "Ts0P", "Ts1P", NULL },
- { "TC0D", "TC0P", NULL }
- };
-
-@@ -122,6 +151,9 @@ static unsigned int applesmc_temperature_set;
-
- static struct mutex applesmc_lock;
-
-+/* Last index written to key_at_index sysfs file. */
-+static unsigned int key_at_index;
-+
- /*
- * __wait_status - Wait up to 100ms for the status port to get a certain value
- * (masked with 0x0f), returning zero if the value is obtained. Callers must
-@@ -152,17 +184,22 @@ static int __wait_status(u8 val)
- */
- static int applesmc_read_key(const char* key, u8* buffer, u8 len)
- {
-- int ret = -EIO;
- int i;
-
-+ if (len > APPLESMC_MAX_DATA_LENGTH) {
-+ printk(KERN_ERR "applesmc_read_key: cannot read more than "
-+ "%d bytes\n", APPLESMC_MAX_DATA_LENGTH);
-+ return -EINVAL;
-+ }
-+
- outb(APPLESMC_READ_CMD, APPLESMC_CMD_PORT);
- if (__wait_status(0x0c))
-- goto out;
-+ return -EIO;
-
- for (i = 0; i < 4; i++) {
- outb(key[i], APPLESMC_DATA_PORT);
- if (__wait_status(0x04))
-- goto out;
-+ return -EIO;
- }
- if (debug)
- printk(KERN_DEBUG "<%s", key);
-@@ -173,7 +210,7 @@ static int applesmc_read_key(const char* key, u8* buffer, u8 len)
-
- for (i = 0; i < len; i++) {
- if (__wait_status(0x05))
-- goto out;
-+ return -EIO;
- buffer[i] = inb(APPLESMC_DATA_PORT);
- if (debug)
- printk(KERN_DEBUG "<%x", buffer[i]);
-@@ -181,10 +218,7 @@ static int applesmc_read_key(const char* key, u8* buffer, u8 len)
- if (debug)
- printk(KERN_DEBUG "\n");
-
-- ret = 0;
--
--out:
-- return ret;
-+ return 0;
- }
-
- /*
-@@ -194,30 +228,100 @@ out:
- */
- static int applesmc_write_key(const char* key, u8* buffer, u8 len)
- {
-- int ret = -EIO;
- int i;
-
-+ if (len > APPLESMC_MAX_DATA_LENGTH) {
-+ printk(KERN_ERR "applesmc_write_key: cannot write more than "
-+ "%d bytes\n", APPLESMC_MAX_DATA_LENGTH);
-+ return -EINVAL;
-+ }
-+
- outb(APPLESMC_WRITE_CMD, APPLESMC_CMD_PORT);
- if (__wait_status(0x0c))
-- goto out;
-+ return -EIO;
-
- for (i = 0; i < 4; i++) {
- outb(key[i], APPLESMC_DATA_PORT);
- if (__wait_status(0x04))
-- goto out;
-+ return -EIO;
- }
-
- outb(len, APPLESMC_DATA_PORT);
-
- for (i = 0; i < len; i++) {
- if (__wait_status(0x04))
-- goto out;
-+ return -EIO;
- outb(buffer[i], APPLESMC_DATA_PORT);
- }
-
-- ret = 0;
--out:
-- return ret;
-+ return 0;
-+}
-+
-+/*
-+ * applesmc_get_key_at_index - get key at index, and put the result in key.
-+ * Returns zero on success or a negative error on failure. Callers must
-+ * hold applesmc_lock.
-+ */
-+static int applesmc_get_key_at_index(int index, char* key)
-+{
-+ int i;
-+ u8 readkey[4];
-+ readkey[0] = index >> 24;
-+ readkey[1] = index >> 16;
-+ readkey[2] = index >> 8;
-+ readkey[3] = index;
-+
-+ outb(APPLESMC_GET_KEY_BY_INDEX_CMD, APPLESMC_CMD_PORT);
-+ if (__wait_status(0x0c))
-+ return -EIO;
-+
-+ for (i = 0; i < 4; i++) {
-+ outb(readkey[i], APPLESMC_DATA_PORT);
-+ if (__wait_status(0x04))
-+ return -EIO;
-+ }
-+
-+ outb(4, APPLESMC_DATA_PORT);
-+
-+ for (i = 0; i < 4; i++) {
-+ if (__wait_status(0x05))
-+ return -EIO;
-+ key[i] = inb(APPLESMC_DATA_PORT);
-+ }
-+ key[4] = 0;
-+
-+ return 0;
-+}
-+
-+/*
-+ * applesmc_get_key_info - get key info, and put the result in info (char[6]).
-+ * Returns zero on success or a negative error on failure. Callers must
-+ * hold applesmc_lock.
-+ */
-+static int applesmc_get_key_info(char* key, char* info)
-+{
-+ int i;
-+
-+ outb(APPLESMC_GET_KEY_INFO_CMD, APPLESMC_CMD_PORT);
-+ if (__wait_status(0x0c))
-+ return -EIO;
-+
-+ for (i = 0; i < 4; i++) {
-+ outb(key[i], APPLESMC_DATA_PORT);
-+ if (__wait_status(0x04))
-+ return -EIO;
-+ }
-+
-+ outb(5, APPLESMC_DATA_PORT);
-+
-+ for (i = 0; i < 6; i++) {
-+ if (__wait_status(0x05))
-+ return -EIO;
-+ info[i] = inb(APPLESMC_DATA_PORT);
-+ }
-+ info[5] = 0;
-+
-+ return 0;
- }
-
- /*
-@@ -249,12 +353,79 @@ static int applesmc_read_motion_sensor(int index, s16* value)
- }
-
- /*
-+ * applesmc_init_check_key_value - checks if a given key contains the bytes in
-+ * buffer, if not, writes these bytes.
-+ * In case of failure retry every INIT_WAIT_MSECS msec, and timeout if it
-+ * waited more than INIT_TIMEOUT_MSECS in total.
-+ * Returns zero on success or a negative error on failure. Callers must
-+ * hold applesmc_lock.
-+ */
-+static int applesmc_init_check_key_value(const char* key, u8* buffer, u8 len)
-+{
-+ int total, ret, i, compare;
-+ u8 rdbuffer[APPLESMC_MAX_DATA_LENGTH];
-+
-+ if (len > APPLESMC_MAX_DATA_LENGTH) {
-+ printk(KERN_ERR "applesmc_init_check_key_value: cannot "
-+ "read/write more than %d bytes",
-+ APPLESMC_MAX_DATA_LENGTH);
-+ return -EINVAL;
-+ }
-+
-+ for (total = INIT_TIMEOUT_MSECS; total > 0; total -= INIT_WAIT_MSECS) {
-+ if (!(ret = applesmc_read_key(key, rdbuffer, len))) {
-+ compare = 1;
-+ for (i = 0; i < len; i++) {
-+ if (rdbuffer[i] != buffer[i]) {
-+ compare = 0;
-+ break;
-+ }
-+ }
-+
-+ if (compare) {
-+ return 0;
-+ }
-+ }
-+ ret = applesmc_write_key(key, buffer, len);
-+ msleep(INIT_WAIT_MSECS);
-+ }
-+
-+ if (ret)
-+ return ret;
-+ else
-+ return -EIO;
-+}
-+
-+irqreturn_t applesmc_irq_handler(int irq, void *dev_id)
-+{
-+ u8 int_type = inb(APPLESMC_INT_PORT);
-+
-+ switch (int_type) {
-+ case 0x60:
-+ printk("applesmc: received a free fall interrupt\n");
-+ break;
-+ case 0x6f:
-+ printk("applesmc: received a high acceleration interrupt\n");
-+ break;
-+ case 0x80:
-+ printk("applesmc: received a shock interrupt\n");
-+ break;
-+ default:
-+ printk("applesmc: received an unknown interrupt %x\n", int_type);
-+ }
-+
-+ return IRQ_NONE;
-+}
-+
-+/*
- * applesmc_device_init - initialize the accelerometer. Returns zero on success
- * and negative error code on failure. Can sleep.
- */
- static int applesmc_device_init(void)
- {
-- int total, ret = -ENXIO;
-+ int total;
-+ int ret = -ENXIO;
-+ int ret1, ret2;
- u8 buffer[2];
-
- if (!applesmc_accelerometer)
-@@ -262,32 +433,76 @@ static int applesmc_device_init(void)
-
- mutex_lock(&applesmc_lock);
-
-+ /* Accept interrupts */
-+ buffer[0] = 0x01;
- for (total = INIT_TIMEOUT_MSECS; total > 0; total -= INIT_WAIT_MSECS) {
-- if (debug)
-- printk(KERN_DEBUG "applesmc try %d\n", total);
-- if (!applesmc_read_key(MOTION_SENSOR_KEY, buffer, 2) &&
-- (buffer[0] != 0x00 || buffer[1] != 0x00)) {
-- if (total == INIT_TIMEOUT_MSECS) {
-- printk(KERN_DEBUG "applesmc: device has"
-- " already been initialized"
-- " (0x%02x, 0x%02x).\n",
-- buffer[0], buffer[1]);
-- } else {
-- printk(KERN_DEBUG "applesmc: device"
-- " successfully initialized"
-- " (0x%02x, 0x%02x).\n",
-- buffer[0], buffer[1]);
-- }
-- ret = 0;
-- goto out;
-- }
-- buffer[0] = 0xe0;
-- buffer[1] = 0x00;
-- applesmc_write_key(MOTION_SENSOR_KEY, buffer, 2);
-+ ret1 = applesmc_write_key(INTERRUPT_OK_KEY, buffer, 1);
-+ msleep(INIT_WAIT_MSECS);
-+
-+ if (!ret1)
-+ break;
-+ }
-+ if (ret1)
-+ printk(KERN_WARNING "applesmc: Cannot set NTOK key, "
-+ "will not receive interrupts.\n");
-+
-+ /* Setup interrupt controls. */
-+ buffer[0] = 20; /* 20 msecs */
-+ ret1 = applesmc_init_check_key_value(MOTION_LOW_NORM_INTERVAL, buffer, 1);
-+
-+ buffer[0] = 20; /* 20 msecs */
-+ ret2 = applesmc_init_check_key_value(MOTION_HIGH_NORM_INTERVAL, buffer, 1);
-+
-+ if (ret1 || ret2) {
-+ printk(KERN_WARNING "applesmc: Cannot set motion sensor "
-+ "parameter 1, might not receive some interrupts.");
-+ }
-+
-+ buffer[0] = 0x00;
-+ buffer[1] = 0x60;
-+ ret1 = applesmc_init_check_key_value(MOTION_LOW_NORM, buffer, 2);
-+
-+ buffer[0] = 0x01;
-+ buffer[1] = 0xc0;
-+ ret2 = applesmc_init_check_key_value(MOTION_HIGH_NORM, buffer, 2);
-+
-+ if (ret1 || ret2) {
-+ printk(KERN_WARNING "applesmc: Cannot set motion sensor "
-+ "min/max norm parameters, "
-+ "might not receive some interrupts.");
-+ }
-+
-+ /* Mysterious key. */
-+ buffer[0] = 0x01;
-+ for (total = INIT_TIMEOUT_MSECS; total > 0; total -= INIT_WAIT_MSECS) {
-+ ret1 = applesmc_write_key(MSDW_KEY, buffer, 1);
- msleep(INIT_WAIT_MSECS);
-+
-+ if (!ret1)
-+ break;
-+ }
-+ if (ret1)
-+ printk(KERN_WARNING "applesmc: Cannot set MSDW key\n");
-+
-+ /* Initialize the device. */
-+ buffer[0] = 0xe0;
-+ buffer[1] = 0xf8;
-+ if (applesmc_init_check_key_value(MOTION_SENSOR_KEY, buffer, 2)) {
-+ printk(KERN_WARNING "applesmc: failed to init "
-+ "the accelerometer\n");
-+ goto out;
-+ }
-+
-+ ret1 = request_irq(APPLESMC_IRQ, applesmc_irq_handler, IRQF_DISABLED,
-+ "applesmc_irq_handler", NULL);
-+
-+ if (ret1) {
-+ printk(KERN_WARNING "applesmc: cannot setup irq handler\n");
- }
-
-- printk(KERN_WARNING "applesmc: failed to init the device\n");
-+ printk(KERN_DEBUG "applesmc: accelerometer "
-+ "successfully initialized.\n");
-+ ret = 0;
-
- out:
- mutex_unlock(&applesmc_lock);
-@@ -332,9 +547,16 @@ static int applesmc_resume(struct platform_device *dev)
- return applesmc_device_init();
- }
-
-+static int applesmc_remove(struct platform_device *dev)
-+{
-+ free_irq(6, NULL);
-+ return 0;
-+}
-+
- static struct platform_driver applesmc_driver = {
- .probe = applesmc_probe,
- .resume = applesmc_resume,
-+ .remove = applesmc_remove,
- .driver = {
- .name = "applesmc",
- .owner = THIS_MODULE,
-@@ -587,6 +809,33 @@ out:
- return count;
- }
-
-+static ssize_t applesmc_show_fan_id(struct device *dev,
-+ struct device_attribute *attr, char *sysfsbuf)
-+{
-+ int ret;
-+ char newkey[5];
-+ u8 buffer[17];
-+ struct sensor_device_attribute_2 *sensor_attr =
-+ to_sensor_dev_attr_2(attr);
-+
-+ newkey[0] = FAN_ID[0];
-+ newkey[1] = '0' + sensor_attr->index;
-+ newkey[2] = FAN_ID[2];
-+ newkey[3] = FAN_ID[3];
-+ newkey[4] = 0;
-+
-+ mutex_lock(&applesmc_lock);
-+
-+ ret = applesmc_read_key(newkey, buffer, 16);
-+ buffer[16] = 0;
-+
-+ mutex_unlock(&applesmc_lock);
-+ if (ret)
-+ return ret;
-+ else
-+ return sprintf(sysfsbuf, "%s\n", buffer+4);
-+}
-+
- static ssize_t applesmc_calibrate_show(struct device *dev,
- struct device_attribute *attr, char *sysfsbuf)
- {
-@@ -603,6 +852,26 @@ static ssize_t applesmc_calibrate_store(struct device *dev,
- return count;
- }
-
-+static ssize_t applesmc_key_count_show(struct device *dev,
-+ struct device_attribute *attr, char *sysfsbuf)
-+{
-+ int ret;
-+ u8 buffer[4];
-+ u32 count;
-+
-+ mutex_lock(&applesmc_lock);
-+
-+ ret = applesmc_read_key(KEY_COUNT_KEY, buffer, 4);
-+ count = ((u32)buffer[0]<<24) + ((u32)buffer[1]<<16) +
-+ ((u32)buffer[2]<<8) + buffer[3];
-+
-+ mutex_unlock(&applesmc_lock);
-+ if (ret)
-+ return ret;
-+ else
-+ return sprintf(sysfsbuf, "%d\n", count);
-+}
-+
- static void applesmc_backlight_set(struct led_classdev *led_cdev,
- enum led_brightness value)
- {
-@@ -615,6 +884,165 @@ static void applesmc_backlight_set(struct led_classdev *led_cdev,
- mutex_unlock(&applesmc_lock);
- }
-
-+static ssize_t applesmc_key_at_index_show(struct device *dev,
-+ struct device_attribute *attr, char *sysfsbuf)
-+{
-+ char key[5];
-+ char info[6];
-+ u8 buffer[APPLESMC_MAX_DATA_LENGTH];
-+ char outbuffer[256];
-+ int ret, ret2;
-+ int i;
-+
-+ outbuffer[0] = 0;
-+
-+ mutex_lock(&applesmc_lock);
-+
-+ ret = applesmc_get_key_at_index(key_at_index, key);
-+
-+ if (!ret && key[0]) {
-+ applesmc_get_key_info(key, info);
-+
-+ ret2 = applesmc_read_key(key, buffer, info[0]);
-+ if (!ret2) {
-+ for (i = 0; i < info[0]; i++) {
-+ sprintf(outbuffer+(i*2), "%02x", buffer[i]);
-+ }
-+ outbuffer[info[0]*2] = 0;
-+ }
-+ }
-+
-+ mutex_unlock(&applesmc_lock);
-+
-+ if (!ret && key[0])
-+ return sprintf(sysfsbuf, "%d: %s [%d:%s] - %s\n", key_at_index, key, info[0], info+1, outbuffer);
-+ else
-+ return sprintf(sysfsbuf, "%d=invalid\n", key_at_index);
-+}
-+
-+static ssize_t applesmc_key_at_index_store(struct device *dev,
-+ struct device_attribute *attr, const char *sysfsbuf, size_t count)
-+{
-+ mutex_lock(&applesmc_lock);
-+
-+ key_at_index = simple_strtoul(sysfsbuf, NULL, 10);
-+
-+ mutex_unlock(&applesmc_lock);
-+
-+ return count;
-+}
-+
-+static ssize_t applesmc_param_show(char* key, int length, char *sysfsbuf)
-+{
-+ int ret;
-+ unsigned int value = 0;
-+ u8 buffer[2];
-+
-+ mutex_lock(&applesmc_lock);
-+
-+ ret = applesmc_read_key(key, buffer, length);
-+ if (length == 2) {
-+ value = ((unsigned int)buffer[0] << 8) | buffer[1];
-+ }
-+ else if (length == 1) {
-+ value = buffer[0];
-+ }
-+ else {
-+ printk("Invalid length for applesmc_param_show");
-+ ret = -EINVAL;
-+ }
-+
-+ mutex_unlock(&applesmc_lock);
-+ if (ret)
-+ return ret;
-+ else
-+ return sprintf(sysfsbuf, "%u\n", value);
-+}
-+
-+static ssize_t applesmc_param_store(char* key, int length,
-+ const char *sysfsbuf, size_t count)
-+{
-+ int ret;
-+ u32 value;
-+ u8 buffer[2];
-+
-+ value = simple_strtoul(sysfsbuf, NULL, 10);
-+
-+ if (length == 2) {
-+ if (value > 0xffff)
-+ return -EINVAL;
-+
-+ buffer[0] = (value >> 8) & 0xff;
-+ buffer[1] = value & 0xff;
-+ } else if (length == 1) {
-+ if (value > 0xff)
-+ return -EINVAL;
-+
-+ buffer[0] = value & 0xff;
-+ } else {
-+ printk("Invalid length for applesmc_param_store");
-+ return -EINVAL;
-+ }
-+
-+ mutex_lock(&applesmc_lock);
-+
-+ ret = applesmc_write_key(key, buffer, length);
-+
-+ mutex_unlock(&applesmc_lock);
-+ if (ret)
-+ return ret;
-+ else
-+ return count;
-+}
-+
-+static ssize_t applesmc_low_norm_trigger_show(struct device *dev,
-+ struct device_attribute *attr, char *sysfsbuf)
-+{
-+ return applesmc_param_show(MOTION_LOW_NORM_INTERVAL, 1, sysfsbuf);
-+}
-+
-+static ssize_t applesmc_high_norm_trigger_show(struct device *dev,
-+ struct device_attribute *attr, char *sysfsbuf)
-+{
-+ return applesmc_param_show(MOTION_HIGH_NORM_INTERVAL, 1, sysfsbuf);
-+}
-+
-+static ssize_t applesmc_low_norm_show(struct device *dev,
-+ struct device_attribute *attr, char *sysfsbuf)
-+{
-+ return applesmc_param_show(MOTION_LOW_NORM, 2, sysfsbuf);
-+}
-+
-+static ssize_t applesmc_high_norm_show(struct device *dev,
-+ struct device_attribute *attr, char *sysfsbuf)
-+{
-+ return applesmc_param_show(MOTION_HIGH_NORM, 2, sysfsbuf);
-+}
-+
-+static ssize_t applesmc_low_norm_trigger_store(struct device *dev,
-+ struct device_attribute *attr, const char *sysfsbuf, size_t count)
-+{
-+ return applesmc_param_store(MOTION_LOW_NORM_INTERVAL, 1, sysfsbuf, count);
-+}
-+
-+static ssize_t applesmc_high_norm_trigger_store(struct device *dev,
-+ struct device_attribute *attr, const char *sysfsbuf, size_t count)
-+{
-+ return applesmc_param_store(MOTION_HIGH_NORM_INTERVAL, 1, sysfsbuf, count);
-+}
-+
-+static ssize_t applesmc_low_norm_store(struct device *dev,
-+ struct device_attribute *attr, const char *sysfsbuf, size_t count)
-+{
-+ return applesmc_param_store(MOTION_LOW_NORM, 2, sysfsbuf, count);
-+}
-+
-+static ssize_t applesmc_high_norm_store(struct device *dev,
-+ struct device_attribute *attr, const char *sysfsbuf, size_t count)
-+{
-+ return applesmc_param_store(MOTION_HIGH_NORM, 2, sysfsbuf, count);
-+}
-+
- static struct led_classdev applesmc_backlight = {
- .name = "smc:kbd_backlight",
- .default_trigger = "nand-disk",
-@@ -624,9 +1052,29 @@ static struct led_classdev applesmc_backlight = {
- static DEVICE_ATTR(position, 0444, applesmc_position_show, NULL);
- static DEVICE_ATTR(calibrate, 0644,
- applesmc_calibrate_show, applesmc_calibrate_store);
-+static DEVICE_ATTR(low_norm_trigger_interval, 0644, applesmc_low_norm_trigger_show, applesmc_low_norm_trigger_store);
-+static DEVICE_ATTR(high_norm_trigger_interval, 0644, applesmc_high_norm_trigger_show, applesmc_high_norm_trigger_store);
-+static DEVICE_ATTR(low_norm_trigger, 0644, applesmc_low_norm_show, applesmc_low_norm_store);
-+static DEVICE_ATTR(high_norm_trigger, 0644, applesmc_high_norm_show, applesmc_high_norm_store);
-
- static DEVICE_ATTR(light, 0444, applesmc_light_show, NULL);
-
-+static DEVICE_ATTR(key_count, 0444, applesmc_key_count_show, NULL);
-+static DEVICE_ATTR(key_at_index, 0600, applesmc_key_at_index_show, applesmc_key_at_index_store);
-+
-+static struct attribute *accelerometer_attributes[] = {
-+ &dev_attr_position.attr,
-+ &dev_attr_calibrate.attr,
-+ &dev_attr_low_norm_trigger.attr,
-+ &dev_attr_high_norm_trigger.attr,
-+ &dev_attr_low_norm_trigger_interval.attr,
-+ &dev_attr_high_norm_trigger_interval.attr,
-+ NULL
-+};
-+
-+static const struct attribute_group accelerometer_attributes_group =
-+ { .attrs = accelerometer_attributes };
-+
- /*
- * Macro defining SENSOR_DEVICE_ATTR for a fan sysfs entries.
- * - show actual speed
-@@ -655,6 +1103,9 @@ static SENSOR_DEVICE_ATTR_2(fan##offset##_target_speed, S_IRUGO | S_IWUSR, \
- static SENSOR_DEVICE_ATTR(fan##offset##_manual, S_IRUGO | S_IWUSR, \
- applesmc_show_fan_manual, applesmc_store_fan_manual, offset); \
- \
-+static SENSOR_DEVICE_ATTR(fan##offset##_id, S_IRUGO, \
-+ applesmc_show_fan_id, NULL, offset); \
-+\
- static struct attribute *fan##offset##_attributes[] = { \
- &sensor_dev_attr_fan##offset##_actual_speed.dev_attr.attr, \
- &sensor_dev_attr_fan##offset##_minimum_speed.dev_attr.attr, \
-@@ -662,6 +1113,7 @@ static struct attribute *fan##offset##_attributes[] = { \
- &sensor_dev_attr_fan##offset##_safe_speed.dev_attr.attr, \
- &sensor_dev_attr_fan##offset##_target_speed.dev_attr.attr, \
- &sensor_dev_attr_fan##offset##_manual.dev_attr.attr, \
-+ &sensor_dev_attr_fan##offset##_id.dev_attr.attr, \
- NULL \
- };
-
-@@ -694,6 +1146,16 @@ static SENSOR_DEVICE_ATTR(temperature_5, S_IRUGO,
- applesmc_show_temperature, NULL, 5);
- static SENSOR_DEVICE_ATTR(temperature_6, S_IRUGO,
- applesmc_show_temperature, NULL, 6);
-+static SENSOR_DEVICE_ATTR(temperature_7, S_IRUGO,
-+ applesmc_show_temperature, NULL, 7);
-+static SENSOR_DEVICE_ATTR(temperature_8, S_IRUGO,
-+ applesmc_show_temperature, NULL, 8);
-+static SENSOR_DEVICE_ATTR(temperature_9, S_IRUGO,
-+ applesmc_show_temperature, NULL, 9);
-+static SENSOR_DEVICE_ATTR(temperature_10, S_IRUGO,
-+ applesmc_show_temperature, NULL, 10);
-+static SENSOR_DEVICE_ATTR(temperature_11, S_IRUGO,
-+ applesmc_show_temperature, NULL, 11);
-
- static struct attribute *temperature_attributes[] = {
- &sensor_dev_attr_temperature_0.dev_attr.attr,
-@@ -703,6 +1165,11 @@ static struct attribute *temperature_attributes[] = {
- &sensor_dev_attr_temperature_4.dev_attr.attr,
- &sensor_dev_attr_temperature_5.dev_attr.attr,
- &sensor_dev_attr_temperature_6.dev_attr.attr,
-+ &sensor_dev_attr_temperature_7.dev_attr.attr,
-+ &sensor_dev_attr_temperature_8.dev_attr.attr,
-+ &sensor_dev_attr_temperature_9.dev_attr.attr,
-+ &sensor_dev_attr_temperature_10.dev_attr.attr,
-+ &sensor_dev_attr_temperature_11.dev_attr.attr,
- };
-
- /* Module stuff */
-@@ -734,11 +1201,8 @@ static int applesmc_create_accelerometer(void)
- {
- int ret;
-
-- ret = sysfs_create_file(&pdev->dev.kobj, &dev_attr_position.attr);
-- if (ret)
-- goto out;
--
-- ret = sysfs_create_file(&pdev->dev.kobj, &dev_attr_calibrate.attr);
-+ ret = sysfs_create_group(&pdev->dev.kobj,
-+ &accelerometer_attributes_group);
- if (ret)
- goto out;
-
-@@ -900,6 +1364,11 @@ static int __init applesmc_init(void)
- goto out_accelerometer;
- }
-
-+ ret = sysfs_create_file(&pdev->dev.kobj, &dev_attr_key_count.attr);
-+ ret = sysfs_create_file(&pdev->dev.kobj, &dev_attr_key_at_index.attr);
-+ if (ret)
-+ goto out_accelerometer;
-+
- printk(KERN_INFO "applesmc: driver successfully loaded.\n");
- return 0;
-
Added: trunk/kernel/mactel-patches-2.6.21/0011-applesmc_standard.patch
===================================================================
--- trunk/kernel/mactel-patches-2.6.21/0011-applesmc_standard.patch (rev 0)
+++ trunk/kernel/mactel-patches-2.6.21/0011-applesmc_standard.patch 2007-04-12 16:38:05 UTC (rev 114)
@@ -0,0 +1,556 @@
+- Standardize applesmc to use sysfs filenames recommended by
+
+From: Nicolas Boichat <ni...@bo...>
+
+Documentation/hwmon/sysfs-interface.
+- Use snprintf instead of sprintf in sysfs show handlers.
+- Remove the sysfs files properly in case of initialisation problem, and when
+ the driver is unloaded.
+- Add various sanity checks and improvements of SMC key comments.
+- Add support for reading fan physical position (e.g. "Left Side")
+---
+
+ drivers/hwmon/applesmc.c | 280 ++++++++++++++++++++++++++++++++--------------
+ 1 files changed, 192 insertions(+), 88 deletions(-)
+
+diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c
+index f7b59fc..531bc9a 100644
+--- a/drivers/hwmon/applesmc.c
++++ b/drivers/hwmon/applesmc.c
+@@ -37,40 +37,48 @@
+ #include <linux/hwmon-sysfs.h>
+ #include <asm/io.h>
+ #include <linux/leds.h>
++#include <linux/hwmon.h>
+
+-/* data port used by apple SMC */
++/* data port used by Apple SMC */
+ #define APPLESMC_DATA_PORT 0x300
+-/* command/status port used by apple SMC */
++/* command/status port used by Apple SMC */
+ #define APPLESMC_CMD_PORT 0x304
+
+-#define APPLESMC_NR_PORTS 5 /* 0x300-0x304 */
++#define APPLESMC_NR_PORTS 32 /* 0x300-0x31f */
++
++#define APPLESMC_MAX_DATA_LENGTH 32
+
+ #define APPLESMC_STATUS_MASK 0x0f
+ #define APPLESMC_READ_CMD 0x10
+ #define APPLESMC_WRITE_CMD 0x11
+
+-#define LIGHT_SENSOR_LEFT_KEY "ALV0" /* r-o length 6 */
+-#define LIGHT_SENSOR_RIGHT_KEY "ALV1" /* r-o length 6 */
+-#define BACKLIGHT_KEY "LKSB" /* w-o */
++#define LIGHT_SENSOR_LEFT_KEY "ALV0" /* r-o {alv (6 bytes) */
++#define LIGHT_SENSOR_RIGHT_KEY "ALV1" /* r-o {alv (6 bytes) */
++#define BACKLIGHT_KEY "LKSB" /* w-o {lkb (2 bytes) */
+
+-#define CLAMSHELL_KEY "MSLD" /* r-o length 1 (unused) */
++#define CLAMSHELL_KEY "MSLD" /* r-o ui8 (unused) */
+
+-#define MOTION_SENSOR_X_KEY "MO_X" /* r-o length 2 */
+-#define MOTION_SENSOR_Y_KEY "MO_Y" /* r-o length 2 */
+-#define MOTION_SENSOR_Z_KEY "MO_Z" /* r-o length 2 */
+-#define MOTION_SENSOR_KEY "MOCN" /* r/w length 2 */
++#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 length 1 */
+-#define FANS_MANUAL "FS! " /* r-w length 2 */
+-#define FAN_ACTUAL_SPEED "F0Ac" /* r-o length 2 */
+-#define FAN_MIN_SPEED "F0Mn" /* r-o length 2 */
+-#define FAN_MAX_SPEED "F0Mx" /* r-o length 2 */
+-#define FAN_SAFE_SPEED "F0Sf" /* r-o length 2 */
+-#define FAN_TARGET_SPEED "F0Tg" /* r-w length 2 */
++#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. First set for Macbook(Pro), second for Macmini */
+-static const char* temperature_sensors_sets[][8] = {
+- { "TB0T", "TC0D", "TC0P", "Th0H", "Ts0P", "Th1H", "Ts1P", NULL },
++/*
++ * Temperature sensors keys (sp78 - 2 bytes).
++ * First set for Macbook(Pro), second for Macmini.
++ */
++static const char* temperature_sensors_sets[][13] = {
++ { "TA0P", "TB0T", "TC0D", "TC0P", "TG0H", "TG0P", "TG0T", "Th0H",
++ "Th1H", "Tm0P", "Ts0P", "Ts1P", NULL },
+ { "TC0D", "TC0P", NULL }
+ };
+
+@@ -110,6 +118,7 @@ static s16 rest_x;
+ static s16 rest_y;
+ static struct timer_list applesmc_timer;
+ static struct input_dev *applesmc_idev;
++static struct class_device *hwmon_class_dev;
+
+ /* Indicates whether this computer has an accelerometer. */
+ static unsigned int applesmc_accelerometer;
+@@ -152,17 +161,22 @@ static int __wait_status(u8 val)
+ */
+ static int applesmc_read_key(const char* key, u8* buffer, u8 len)
+ {
+- int ret = -EIO;
+ int i;
+
++ if (len > APPLESMC_MAX_DATA_LENGTH) {
++ printk(KERN_ERR "applesmc_read_key: cannot read more than "
++ "%d bytes\n", APPLESMC_MAX_DATA_LENGTH);
++ return -EINVAL;
++ }
++
+ outb(APPLESMC_READ_CMD, APPLESMC_CMD_PORT);
+ if (__wait_status(0x0c))
+- goto out;
++ return -EIO;
+
+ for (i = 0; i < 4; i++) {
+ outb(key[i], APPLESMC_DATA_PORT);
+ if (__wait_status(0x04))
+- goto out;
++ return -EIO;
+ }
+ if (debug)
+ printk(KERN_DEBUG "<%s", key);
+@@ -173,7 +187,7 @@ static int applesmc_read_key(const char* key, u8* buffer, u8 len)
+
+ for (i = 0; i < len; i++) {
+ if (__wait_status(0x05))
+- goto out;
++ return -EIO;
+ buffer[i] = inb(APPLESMC_DATA_PORT);
+ if (debug)
+ printk(KERN_DEBUG "<%x", buffer[i]);
+@@ -181,10 +195,7 @@ static int applesmc_read_key(const char* key, u8* buffer, u8 len)
+ if (debug)
+ printk(KERN_DEBUG "\n");
+
+- ret = 0;
+-
+-out:
+- return ret;
++ return 0;
+ }
+
+ /*
+@@ -194,30 +205,33 @@ out:
+ */
+ static int applesmc_write_key(const char* key, u8* buffer, u8 len)
+ {
+- int ret = -EIO;
+ int i;
+
++ if (len > APPLESMC_MAX_DATA_LENGTH) {
++ printk(KERN_ERR "applesmc_write_key: cannot write more than "
++ "%d bytes\n", APPLESMC_MAX_DATA_LENGTH);
++ return -EINVAL;
++ }
++
+ outb(APPLESMC_WRITE_CMD, APPLESMC_CMD_PORT);
+ if (__wait_status(0x0c))
+- goto out;
++ return -EIO;
+
+ for (i = 0; i < 4; i++) {
+ outb(key[i], APPLESMC_DATA_PORT);
+ if (__wait_status(0x04))
+- goto out;
++ return -EIO;
+ }
+
+ outb(len, APPLESMC_DATA_PORT);
+
+ for (i = 0; i < len; i++) {
+ if (__wait_status(0x04))
+- goto out;
++ return -EIO;
+ outb(buffer[i], APPLESMC_DATA_PORT);
+ }
+
+- ret = 0;
+-out:
+- return ret;
++ return 0;
+ }
+
+ /*
+@@ -415,7 +429,7 @@ out:
+ if (ret)
+ return ret;
+ else
+- return sprintf(buf, "(%d,%d,%d)\n", x, y, z);
++ return snprintf(buf, PAGE_SIZE, "(%d,%d,%d)\n", x, y, z);
+ }
+
+ static ssize_t applesmc_light_show(struct device *dev,
+@@ -439,10 +453,10 @@ out:
+ if (ret)
+ return ret;
+ else
+- return sprintf(sysfsbuf, "(%d,%d)\n", left, right);
++ return snprintf(sysfsbuf, PAGE_SIZE, "(%d,%d)\n", left, right);
+ }
+
+-/* Displays degree Celsius * 100 */
++/* Displays degree Celsius * 1000 */
+ static ssize_t applesmc_show_temperature(struct device *dev,
+ struct device_attribute *devattr, char *sysfsbuf)
+ {
+@@ -456,15 +470,15 @@ static ssize_t applesmc_show_temperature(struct device *dev,
+ mutex_lock(&applesmc_lock);
+
+ ret = applesmc_read_key(key, buffer, 2);
+- temp = buffer[0]*100;
+- temp += (buffer[1] >> 6) * 25;
++ temp = buffer[0]*1000;
++ temp += (buffer[1] >> 6) * 250;
+
+ mutex_unlock(&applesmc_lock);
+
+ if (ret)
+ return ret;
+ else
+- return sprintf(sysfsbuf, "%u\n", temp);
++ return snprintf(sysfsbuf, PAGE_SIZE, "%u\n", temp);
+ }
+
+ static ssize_t applesmc_show_fan_speed(struct device *dev,
+@@ -492,7 +506,7 @@ static ssize_t applesmc_show_fan_speed(struct device *dev,
+ if (ret)
+ return ret;
+ else
+- return sprintf(sysfsbuf, "%u\n", speed);
++ return snprintf(sysfsbuf, PAGE_SIZE, "%u\n", speed);
+ }
+
+ static ssize_t applesmc_store_fan_speed(struct device *dev,
+@@ -547,7 +561,7 @@ static ssize_t applesmc_show_fan_manual(struct device *dev,
+ if (ret)
+ return ret;
+ else
+- return sprintf(sysfsbuf, "%d\n", manual);
++ return snprintf(sysfsbuf, PAGE_SIZE, "%d\n", manual);
+ }
+
+ static ssize_t applesmc_store_fan_manual(struct device *dev,
+@@ -587,10 +601,37 @@ out:
+ return count;
+ }
+
++static ssize_t applesmc_show_fan_position(struct device *dev,
++ struct device_attribute *attr, char *sysfsbuf)
++{
++ int ret;
++ char newkey[5];
++ u8 buffer[17];
++ struct sensor_device_attribute_2 *sensor_attr =
++ to_sensor_dev_attr_2(attr);
++
++ newkey[0] = FAN_POSITION[0];
++ newkey[1] = '0' + sensor_attr->index;
++ newkey[2] = FAN_POSITION[2];
++ newkey[3] = FAN_POSITION[3];
++ newkey[4] = 0;
++
++ mutex_lock(&applesmc_lock);
++
++ ret = applesmc_read_key(newkey, buffer, 16);
++ buffer[16] = 0;
++
++ mutex_unlock(&applesmc_lock);
++ if (ret)
++ return ret;
++ else
++ return snprintf(sysfsbuf, PAGE_SIZE, "%s\n", buffer+4);
++}
++
+ static ssize_t applesmc_calibrate_show(struct device *dev,
+ struct device_attribute *attr, char *sysfsbuf)
+ {
+- return sprintf(sysfsbuf, "(%d,%d)\n", rest_x, rest_y);
++ return snprintf(sysfsbuf, PAGE_SIZE, "(%d,%d)\n", rest_x, rest_y);
+ }
+
+ static ssize_t applesmc_calibrate_store(struct device *dev,
+@@ -625,6 +666,15 @@ static DEVICE_ATTR(position, 0444, applesmc_position_show, NULL);
+ static DEVICE_ATTR(calibrate, 0644,
+ applesmc_calibrate_show, applesmc_calibrate_store);
+
++static struct attribute *accelerometer_attributes[] = {
++ &dev_attr_position.attr,
++ &dev_attr_calibrate.attr,
++ NULL
++};
++
++static const struct attribute_group accelerometer_attributes_group =
++ { .attrs = accelerometer_attributes };
++
+ static DEVICE_ATTR(light, 0444, applesmc_light_show, NULL);
+
+ /*
+@@ -637,31 +687,35 @@ static DEVICE_ATTR(light, 0444, applesmc_light_show, NULL);
+ * - show/store manual mode
+ */
+ #define sysfs_fan_speeds_offset(offset) \
+-static SENSOR_DEVICE_ATTR_2(fan##offset##_actual_speed, S_IRUGO, \
+- applesmc_show_fan_speed, NULL, 0, offset); \
++static SENSOR_DEVICE_ATTR_2(fan##offset##_input, S_IRUGO, \
++ applesmc_show_fan_speed, NULL, 0, offset-1); \
+ \
+-static SENSOR_DEVICE_ATTR_2(fan##offset##_minimum_speed, S_IRUGO | S_IWUSR, \
+- applesmc_show_fan_speed, applesmc_store_fan_speed, 1, offset); \
++static SENSOR_DEVICE_ATTR_2(fan##offset##_min, S_IRUGO | S_IWUSR, \
++ applesmc_show_fan_speed, applesmc_store_fan_speed, 1, offset-1); \
+ \
+-static SENSOR_DEVICE_ATTR_2(fan##offset##_maximum_speed, S_IRUGO, \
+- applesmc_show_fan_speed, NULL, 2, offset); \
++static SENSOR_DEVICE_ATTR_2(fan##offset##_max, S_IRUGO, \
++ applesmc_show_fan_speed, NULL, 2, offset-1); \
+ \
+-static SENSOR_DEVICE_ATTR_2(fan##offset##_safe_speed, S_IRUGO, \
+- applesmc_show_fan_speed, NULL, 3, offset); \
++static SENSOR_DEVICE_ATTR_2(fan##offset##_safe, S_IRUGO, \
++ applesmc_show_fan_speed, NULL, 3, offset-1); \
+ \
+-static SENSOR_DEVICE_ATTR_2(fan##offset##_target_speed, S_IRUGO | S_IWUSR, \
+- applesmc_show_fan_speed, applesmc_store_fan_speed, 4, offset); \
++static SENSOR_DEVICE_ATTR_2(fan##offset##_output, S_IRUGO | S_IWUSR, \
++ applesmc_show_fan_speed, applesmc_store_fan_speed, 4, offset-1); \
+ \
+ static SENSOR_DEVICE_ATTR(fan##offset##_manual, S_IRUGO | S_IWUSR, \
+- applesmc_show_fan_manual, applesmc_store_fan_manual, offset); \
++ applesmc_show_fan_manual, applesmc_store_fan_manual, offset-1); \
++\
++static SENSOR_DEVICE_ATTR(fan##offset##_position, S_IRUGO, \
++ applesmc_show_fan_position, NULL, offset-1); \
+ \
+ static struct attribute *fan##offset##_attributes[] = { \
+- &sensor_dev_attr_fan##offset##_actual_speed.dev_attr.attr, \
+- &sensor_dev_attr_fan##offset##_minimum_speed.dev_attr.attr, \
+- &sensor_dev_attr_fan##offset##_maximum_speed.dev_attr.attr, \
+- &sensor_dev_attr_fan##offset##_safe_speed.dev_attr.attr, \
+- &sensor_dev_attr_fan##offset##_target_speed.dev_attr.attr, \
++ &sensor_dev_attr_fan##offset##_input.dev_attr.attr, \
++ &sensor_dev_attr_fan##offset##_min.dev_attr.attr, \
++ &sensor_dev_attr_fan##offset##_max.dev_attr.attr, \
++ &sensor_dev_attr_fan##offset##_safe.dev_attr.attr, \
++ &sensor_dev_attr_fan##offset##_output.dev_attr.attr, \
+ &sensor_dev_attr_fan##offset##_manual.dev_attr.attr, \
++ &sensor_dev_attr_fan##offset##_position.dev_attr.attr, \
+ NULL \
+ };
+
+@@ -669,42 +723,61 @@ static struct attribute *fan##offset##_attributes[] = { \
+ * Create the needed functions for each fan using the macro defined above
+ * (2 fans are supported)
+ */
+-sysfs_fan_speeds_offset(0);
+ sysfs_fan_speeds_offset(1);
++sysfs_fan_speeds_offset(2);
+
+ static const struct attribute_group fan_attribute_groups[] = {
+- { .attrs = fan0_attributes },
+- { .attrs = fan1_attributes }
++ { .attrs = fan1_attributes },
++ { .attrs = fan2_attributes }
+ };
+
+ /*
+ * Temperature sensors sysfs entries.
+ */
+-static SENSOR_DEVICE_ATTR(temperature_0, S_IRUGO,
++static SENSOR_DEVICE_ATTR(temp_1_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 0);
+-static SENSOR_DEVICE_ATTR(temperature_1, S_IRUGO,
++static SENSOR_DEVICE_ATTR(temp_2_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 1);
+-static SENSOR_DEVICE_ATTR(temperature_2, S_IRUGO,
++static SENSOR_DEVICE_ATTR(temp_3_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 2);
+-static SENSOR_DEVICE_ATTR(temperature_3, S_IRUGO,
++static SENSOR_DEVICE_ATTR(temp_4_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 3);
+-static SENSOR_DEVICE_ATTR(temperature_4, S_IRUGO,
++static SENSOR_DEVICE_ATTR(temp_5_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 4);
+-static SENSOR_DEVICE_ATTR(temperature_5, S_IRUGO,
++static SENSOR_DEVICE_ATTR(temp_6_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 5);
+-static SENSOR_DEVICE_ATTR(temperature_6, S_IRUGO,
++static SENSOR_DEVICE_ATTR(temp_7_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 6);
++static SENSOR_DEVICE_ATTR(temp_8_input, S_IRUGO,
++ applesmc_show_temperature, NULL, 7);
++static SENSOR_DEVICE_ATTR(temp_9_input, S_IRUGO,
++ applesmc_show_temperature, NULL, 8);
++static SENSOR_DEVICE_ATTR(temp_10_input, S_IRUGO,
++ applesmc_show_temperature, NULL, 9);
++static SENSOR_DEVICE_ATTR(temp_11_input, S_IRUGO,
++ applesmc_show_temperature, NULL, 10);
++static SENSOR_DEVICE_ATTR(temp_12_input, S_IRUGO,
++ applesmc_show_temperature, NULL, 11);
+
+ static struct attribute *temperature_attributes[] = {
+- &sensor_dev_attr_temperature_0.dev_attr.attr,
+- &sensor_dev_attr_temperature_1.dev_attr.attr,
+- &sensor_dev_attr_temperature_2.dev_attr.attr,
+- &sensor_dev_attr_temperature_3.dev_attr.attr,
+- &sensor_dev_attr_temperature_4.dev_attr.attr,
+- &sensor_dev_attr_temperature_5.dev_attr.attr,
+- &sensor_dev_attr_temperature_6.dev_attr.attr,
++ &sensor_dev_attr_temp_1_input.dev_attr.attr,
++ &sensor_dev_attr_temp_2_input.dev_attr.attr,
++ &sensor_dev_attr_temp_3_input.dev_attr.attr,
++ &sensor_dev_attr_temp_4_input.dev_attr.attr,
++ &sensor_dev_attr_temp_5_input.dev_attr.attr,
++ &sensor_dev_attr_temp_6_input.dev_attr.attr,
++ &sensor_dev_attr_temp_7_input.dev_attr.attr,
++ &sensor_dev_attr_temp_8_input.dev_attr.attr,
++ &sensor_dev_attr_temp_9_input.dev_attr.attr,
++ &sensor_dev_attr_temp_10_input.dev_attr.attr,
++ &sensor_dev_attr_temp_11_input.dev_attr.attr,
++ &sensor_dev_attr_temp_12_input.dev_attr.attr,
++ NULL
+ };
+
++static const struct attribute_group temperature_attributes_group =
++ { .attrs = temperature_attributes };
++
+ /* Module stuff */
+
+ /*
+@@ -734,18 +807,15 @@ static int applesmc_create_accelerometer(void)
+ {
+ int ret;
+
+- ret = sysfs_create_file(&pdev->dev.kobj, &dev_attr_position.attr);
+- if (ret)
+- goto out;
+-
+- ret = sysfs_create_file(&pdev->dev.kobj, &dev_attr_calibrate.attr);
++ ret = sysfs_create_group(&pdev->dev.kobj,
++ &accelerometer_attributes_group);
+ if (ret)
+ goto out;
+
+ applesmc_idev = input_allocate_device();
+ if (!applesmc_idev) {
+ ret = -ENOMEM;
+- goto out;
++ goto out_sysfs;
+ }
+
+ /* initial calibrate for the input device */
+@@ -777,6 +847,9 @@ static int applesmc_create_accelerometer(void)
+ out_idev:
+ input_free_device(applesmc_idev);
+
++out_sysfs:
++ sysfs_remove_group(&pdev->dev.kobj, &accelerometer_attributes_group);
++
+ out:
+ printk(KERN_WARNING "applesmc: driver init failed (ret=%d)!\n", ret);
+ return ret;
+@@ -787,6 +860,7 @@ static void applesmc_release_accelerometer(void)
+ {
+ del_timer_sync(&applesmc_timer);
+ input_unregister_device(applesmc_idev);
++ sysfs_remove_group(&pdev->dev.kobj, &accelerometer_attributes_group);
+ }
+
+ static __initdata struct dmi_match_data applesmc_dmi_data[] = {
+@@ -867,7 +941,7 @@ static int __init applesmc_init(void)
+ ret = sysfs_create_group(&pdev->dev.kobj,
+ &fan_attribute_groups[0]);
+ if (ret)
+- goto out_device;
++ goto out_fan_1;
+ case 0:
+ ;
+ }
+@@ -876,16 +950,24 @@ static int __init applesmc_init(void)
+ for (i = 0;
+ temperature_sensors_sets[applesmc_temperature_set][i] != NULL;
+ i++) {
++ if (temperature_attributes[i] == NULL) {
++ printk(KERN_ERR "applesmc: More temperature sensors "
++ "in temperature_sensors_sets (at least %i)"
++ "than available sysfs files in "
++ "temperature_attributes (%i), please report "
++ "this bug.\n", i, i-1);
++ goto out_temperature;
++ }
+ ret = sysfs_create_file(&pdev->dev.kobj,
+ temperature_attributes[i]);
+ if (ret)
+- goto out_device;
++ goto out_temperature;
+ }
+
+ if (applesmc_accelerometer) {
+ ret = applesmc_create_accelerometer();
+ if (ret)
+- goto out_device;
++ goto out_temperature;
+ }
+
+ if (applesmc_light) {
+@@ -897,15 +979,33 @@ static int __init applesmc_init(void)
+ /* register as a led device */
+ ret = led_classdev_register(&pdev->dev, &applesmc_backlight);
+ if (ret < 0)
+- goto out_accelerometer;
++ goto out_light_sysfs;
++ }
++
++ hwmon_class_dev = hwmon_device_register(&pdev->dev);
++ if (IS_ERR(hwmon_class_dev)) {
++ ret = PTR_ERR(hwmon_class_dev);
++ goto out_light;
+ }
+
+ printk(KERN_INFO "applesmc: driver successfully loaded.\n");
++
+ return 0;
+
++out_light:
++ if (applesmc_light)
++ led_classdev_unregister(&applesmc_backlight);
++out_light_sysfs:
++ if (applesmc_light)
++ sysfs_remove_file(&pdev->dev.kobj, &dev_attr_light.attr);
+ out_accelerometer:
+ if (applesmc_accelerometer)
+ applesmc_release_accelerometer();
++out_temperature:
++ sysfs_remove_group(&pdev->dev.kobj, &temperature_attributes_group);
++ sysfs_remove_group(&pdev->dev.kobj, &fan_attribute_groups[0]);
++out_fan_1:
++ sysfs_remove_group(&pdev->dev.kobj, &fan_attribute_groups[1]);
+ out_device:
+ platform_device_unregister(pdev);
+ out_driver:
+@@ -919,10 +1019,14 @@ out:
+
+ static void __exit applesmc_exit(void)
+ {
++ hwmon_device_unregister(hwmon_class_dev);
+ if (applesmc_light)
+ led_classdev_unregister(&applesmc_backlight);
+ if (applesmc_accelerometer)
+ applesmc_release_accelerometer();
++ sysfs_remove_group(&pdev->dev.kobj, &temperature_attributes_group);
++ sysfs_remove_group(&pdev->dev.kobj, &fan_attribute_groups[0]);
++ sysfs_remove_group(&pdev->dev.kobj, &fan_attribute_groups[1]);
+ platform_device_unregister(pdev);
+ platform_driver_unregister(&applesmc_driver);
+ release_region(APPLESMC_DATA_PORT, APPLESMC_NR_PORTS);
Added: trunk/kernel/mactel-patches-2.6.21/0012-applesmc_enum.patch
===================================================================
--- trunk/kernel/mactel-patches-2.6.21/0012-applesmc_enum.patch (rev 0)
+++ trunk/kernel/mactel-patches-2.6.21/0012-applesmc_enum.patch 2007-04-12 16:38:05 UTC (rev 114)
@@ -0,0 +1,340 @@
+Implement key enumeration in applesmc.
+
+From: Nicolas Boichat <ni...@bo...>
+
+
+---
+
+ drivers/hwmon/applesmc.c | 263 ++++++++++++++++++++++++++++++++++++++++++++++
+ 1 files changed, 262 insertions(+), 1 deletions(-)
+
+diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c
+index 531bc9a..4ec38ef 100644
+--- a/drivers/hwmon/applesmc.c
++++ b/drivers/hwmon/applesmc.c
+@@ -51,6 +51,10 @@
+ #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 bytes) */
+ #define LIGHT_SENSOR_RIGHT_KEY "ALV1" /* r-o {alv (6 bytes) */
+@@ -131,6 +135,12 @@ static unsigned int applesmc_temperature_set;
+
+ static struct mutex applesmc_lock;
+
++/*
++ * Last index written to key_at_index sysfs file, and value to use for all other
++ * key_at_index_* sysfs files.
++ */
++static unsigned int key_at_index;
++
+ /*
+ * __wait_status - Wait up to 100ms for the status port to get a certain value
+ * (masked with 0x0f), returning zero if the value is obtained. Callers must
+@@ -235,6 +245,73 @@ static int applesmc_write_key(const char* key, u8* buffer, u8 len)
+ }
+
+ /*
++ * applesmc_get_key_at_index - get key at index, and put the result in key
++ * (char[6]). Returns zero on success or a negative error on failure. Callers
++ * must hold applesmc_lock.
++ */
++static int applesmc_get_key_at_index(int index, char* key)
++{
++ int i;
++ u8 readkey[4];
++ readkey[0] = index >> 24;
++ readkey[1] = index >> 16;
++ readkey[2] = index >> 8;
++ readkey[3] = index;
++
++ outb(APPLESMC_GET_KEY_BY_INDEX_CMD, APPLESMC_CMD_PORT);
++ if (__wait_status(0x0c))
++ return -EIO;
++
++ for (i = 0; i < 4; i++) {
++ outb(readkey[i], APPLESMC_DATA_PORT);
++ if (__wait_status(0x04))
++ return -EIO;
++ }
++
++ outb(4, APPLESMC_DATA_PORT);
++
++ for (i = 0; i < 4; i++) {
++ if (__wait_status(0x05))
++ return -EIO;
++ key[i] = inb(APPLESMC_DATA_PORT);
++ }
++ key[4] = 0;
++
++ return 0;
++}
++
++/*
++ * applesmc_get_key_type - get key type, and put the result in type (char[6]).
++ * Returns zero on success or a negative error on failure. Callers must
++ * hold applesmc_lock.
++ */
++static int applesmc_get_key_type(char* key, char* type)
++{
++ int i;
++
++ outb(APPLESMC_GET_KEY_TYPE_CMD, APPLESMC_CMD_PORT);
++ if (__wait_status(0x0c))
++ return -EIO;
++
++ for (i = 0; i < 4; i++) {
++ outb(key[i], APPLESMC_DATA_PORT);
++ if (__wait_status(0x04))
++ return -EIO;
++ }
++
++ outb(5, APPLESMC_DATA_PORT);
++
++ for (i = 0; i < 6; i++) {
++ if (__wait_status(0x05))
++ return -EIO;
++ type[i] = inb(APPLESMC_DATA_PORT);
++ }
++ type[5] = 0;
++
++ return 0;
++}
++
++/*
+ * applesmc_read_motion_sensor - Read motion sensor (X, Y or Z). Callers must
+ * hold applesmc_lock.
+ */
+@@ -656,6 +733,157 @@ static void applesmc_backlight_set(struct led_classdev *led_cdev,
+ mutex_unlock(&applesmc_lock);
+ }
+
++static ssize_t applesmc_key_count_show(struct device *dev,
++ struct device_attribute *attr, char *sysfsbuf)
++{
++ int ret;
++ u8 buffer[4];
++ u32 count;
++
++ mutex_lock(&applesmc_lock);
++
++ ret = applesmc_read_key(KEY_COUNT_KEY, buffer, 4);
++ count = ((u32)buffer[0]<<24) + ((u32)buffer[1]<<16) +
++ ((u32)buffer[2]<<8) + buffer[3];
++
++ mutex_unlock(&applesmc_lock);
++ if (ret)
++ return ret;
++ else
++ return snprintf(sysfsbuf, PAGE_SIZE, "%d\n", count);
++}
++
++static ssize_t applesmc_key_at_index_read_show(struct device *dev,
++ struct device_attribute *attr, char *sysfsbuf)
++{
++ char key[5];
++ char info[6];
++ int ret;
++
++ mutex_lock(&applesmc_lock);
++
++ ret = applesmc_get_key_at_index(key_at_index, key);
++
++ if (ret || !key[0]) {
++ mutex_unlock(&applesmc_lock);
++
++ return -EINVAL;
++ }
++
++ ret = applesmc_get_key_type(key, info);
++
++ if (ret) {
++ mutex_unlock(&applesmc_lock);
++
++ return ret;
++ }
++
++ /*
++ * info[0] maximum value (APPLESMC_MAX_DATA_LENGTH) is much lower than
++ * PAGE_SIZE, so we don't need any checks before writing to sysfsbuf.
++ */
++ ret = applesmc_read_key(key, sysfsbuf, info[0]);
++
++ mutex_unlock(&applesmc_lock);
++
++ if (!ret) {
++ return info[0];
++ }
++ else {
++ return ret;
++ }
++}
++
++static ssize_t applesmc_key_at_index_data_length_show(struct device *dev,
++ struct device_attribute *attr, char *sysfsbuf)
++{
++ char key[5];
++ char info[6];
++ int ret;
++
++ mutex_lock(&applesmc_lock);
++
++ ret = applesmc_get_key_at_index(key_at_index, key);
++
++ if (ret || !key[0]) {
++ mutex_unlock(&applesmc_lock);
++
++ return -EINVAL;
++ }
++
++ ret = applesmc_get_key_type(key, info);
++
++ mutex_unlock(&applesmc_lock);
++
++ if (!ret)
++ return snprintf(sysfsbuf, PAGE_SIZE, "%d\n", info[0]);
++ else
++ return ret;
++}
++
++static ssize_t applesmc_key_at_index_type_show(struct device *dev,
++ struct device_attribute *attr, char *sysfsbuf)
++{
++ char key[5];
++ char info[6];
++ int ret;
++
++ mutex_lock(&applesmc_lock);
++
++ ret = applesmc_get_key_at_index(key_at_index, key);
++
++ if (ret || !key[0]) {
++ mutex_unlock(&applesmc_lock);
++
++ return -EINVAL;
++ }
++
++ ret = applesmc_get_key_type(key, info);
++
++ mutex_unlock(&applesmc_lock);
++
++ if (!ret)
++ return snprintf(sysfsbuf, PAGE_SIZE, "%s\n", info+1);
++ else
++ return ret;
++}
++
++static ssize_t applesmc_key_at_index_name_show(struct device *dev,
++ struct device_attribute *attr, char *sysfsbuf)
++{
++ char key[5];
++ int ret;
++
++ mutex_lock(&applesmc_lock);
++
++ ret = applesmc_get_key_at_index(key_at_index, key);
++
++ mutex_unlock(&applesmc_lock);
++
++ if (!ret && key[0])
++ return snprintf(sysfsbuf, PAGE_SIZE, "%s\n", key);
++ else
++ return -EINVAL;
++}
++
++static ssize_t applesmc_key_at_index_show(struct device *dev,
++ struct device_attribute *attr, char *sysfsbuf)
++{
++ return snprintf(sysfsbuf, PAGE_SIZE, "%d\n", key_at_index);
++}
++
++static ssize_t applesmc_key_at_index_store(struct device *dev,
++ struct device_attribute *attr, const char *sysfsbuf, size_t count)
++{
++ mutex_lock(&applesmc_lock);
++
++ key_at_index = simple_strtoul(sysfsbuf, NULL, 10);
++
++ mutex_unlock(&applesmc_lock);
++
++ return count;
++}
++
+ static struct led_classdev applesmc_backlight = {
+ .name = "smc:kbd_backlight",
+ .default_trigger = "nand-disk",
+@@ -677,6 +905,31 @@ static const struct attribute_group accelerometer_attributes_group =
+
+ static DEVICE_ATTR(light, 0444, applesmc_light_show, NULL);
+
++static DEVICE_ATTR(key_count, 0444, applesmc_key_count_show, NULL);
++static DEVICE_ATTR(key_at_index, 0644,
++ applesmc_key_at_index_show, applesmc_key_at_index_store);
++static DEVICE_ATTR(key_at_index_name, 0444,
++ applesmc_key_at_index_name_show, NULL);
++static DEVICE_ATTR(key_at_index_type, 0444,
++ applesmc_key_at_index_type_show, NULL);
++static DEVICE_ATTR(key_at_index_data_length, 0444,
++ applesmc_key_at_index_data_length_show, NULL);
++static DEVICE_ATTR(key_at_index_data, 0444,
++ applesmc_key_at_index_read_show, NULL);
++
++static struct attribute *key_enumeration_attributes[] = {
++ &dev_attr_key_count.attr,
++ &dev_attr_key_at_index.attr,
++ &dev_attr_key_at_index_name.attr,
++ &dev_attr_key_at_index_type.attr,
++ &dev_attr_key_at_index_data_length.attr,
++ &dev_attr_key_at_index_data.attr,
++ NULL
++};
++
++static const struct attribute_group key_enumeration_group =
++ { .attrs = key_enumeration_attributes };
++
+ /*
+ * Macro defining SENSOR_DEVICE_ATTR for a fan sysfs entries.
+ * - show actual speed
+@@ -920,6 +1173,11 @@ static int __init applesmc_init(void)
+ goto out_driver;
+ }
+
++ /* Create key enumeration sysfs files */
++ ret = sysfs_create_group(&pdev->dev.kobj, &key_enumeration_group);
++ if (ret)
++ goto out_device;
++
+ /* create fan files */
+ count = applesmc_get_fan_count();
+ if (count < 0) {
+@@ -936,7 +1194,7 @@ static int __init applesmc_init(void)
+ ret = sysfs_create_group(&pdev->dev.kobj,
+ &fan_attribute_groups[1]);
+ if (ret)
+- goto out_device;
++ goto out_key_enumeration;
+ case 1:
+ ret = sysfs_create_group(&pdev->dev.kobj,
+ &fan_attribute_groups[0]);
+@@ -1006,6 +1264,8 @@ out_temperature:
+ sysfs_remove_group(&pdev->dev.kobj, &fan_attribute_groups[0]);
+ out_fan_1:
+ sysfs_remove_group(&pdev->dev.kobj, &fan_attribute_groups[1]);
++out_key_enumeration:
++ sysfs_remove_group(&pdev->dev.kobj, &key_enumeration_group);
+ out_device:
+ platform_device_unregister(pdev);
+ out_driver:
+@@ -1027,6 +1287,7 @@ static void __exit applesmc_exit(void)
+ sysfs_remove_group(&pdev->dev.kobj, &temperature_attributes_group);
+ sysfs_remove_group(&pdev->dev.kobj, &fan_attribute_groups[0]);
+ sysfs_remove_group(&pdev->dev.kobj, &fan_attribute_groups[1]);
++ sysfs_remove_group(&pdev->dev.kobj, &key_enumeration_group);
+ platform_device_unregister(pdev);
+ platform_driver_unregister(&applesmc_driver);
+ release_region(APPLESMC_DATA_PORT, APPLESMC_NR_PORTS);
Added: trunk/kernel/mactel-patches-2.6.21/0013-applesmc_int.patch
===================================================================
--- trunk/kernel/mactel-patches-2.6.21/0013-applesmc_int.patch (rev 0)
+++ trunk/kernel/mactel-patches-2.6.21/0013-applesmc_int.patch 2007-04-12 16:38:05 UTC (rev 114)
@@ -0,0 +1,410 @@
+Interrupt support for the accelerometer.
+
+From: Nicolas Boichat <ni...@bo...>
+
+
+---
+
+ drivers/hwmon/applesmc.c | 316 +++++++++++++++++++++++++++++++++++++++++++---
+ 1 files changed, 293 insertions(+), 23 deletions(-)
+
+diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c
+index 4ec38ef..6ad1c2d 100644
+--- a/drivers/hwmon/applesmc.c
++++ b/drivers/hwmon/applesmc.c
+@@ -38,14 +38,20 @@
+ #include <asm/io.h>
+ #include <linux/leds.h>
+ #include <linux/hwmon.h>
++#include <linux/interrupt.h>
+
+ /* data port used by Apple SMC */
+ #define APPLESMC_DATA_PORT 0x300
+ /* command/status port used by Apple SMC */
+ #define APPLESMC_CMD_PORT 0x304
++/* status port used by Apple SMC to get which interrupt type just happened */
++#define APPLESMC_INT_PORT 0x31f
+
+ #define APPLESMC_NR_PORTS 32 /* 0x300-0x31f */
+
++/* Defined in ACPI DSDT table, should we read it from there? */
++#define APPLESMC_IRQ 6
++
+ #define APPLESMC_MAX_DATA_LENGTH 32
+
+ #define APPLESMC_STATUS_MASK 0x0f
+@@ -56,6 +62,8 @@
+
+ #define KEY_COUNT_KEY "#KEY" /* r-o ui32 */
+
++#define INTERRUPT_OK_KEY "NTOK" /* w-o ui8 */
++
+ #define LIGHT_SENSOR_LEFT_KEY "ALV0" /* r-o {alv (6 bytes) */
+ #define LIGHT_SENSOR_RIGHT_KEY "ALV1" /* r-o {alv (6 bytes) */
+ #define BACKLIGHT_KEY "LKSB" /* w-o {lkb (2 bytes) */
+@@ -67,6 +75,19 @@
+ #define MOTION_SENSOR_Z_KEY "MO_Z" /* r-o sp78 (2 bytes) */
+ #define MOTION_SENSOR_KEY "MOCN" /* r/w ui16 */
+
++/*
++ * Interrupt controls.
++ * If the norm of the position (sqrt(MO_X^2+MO_Y^2+MO_Z^2)) is smaller than
++ * MOLT (free fall), or bigger than MOHT (high acceleration) for longer than the
++ * value of MOLD (or MOHD), SMC will trigger an interrupt.
++ */
++#define MOTION_LOW_NORM "MOLT" /* r/w sp78 (2 bytes) */
++#define MOTION_HIGH_NORM "MOHT" /* r/w sp78 (2 bytes) */
++#define MOTION_LOW_NORM_INTERVAL "MOLD" /* r/w ui8 */
++#define MOTION_HIGH_NORM_INTERVAL "MOHD" /* r/w ui8 */
++
++#define MSDW_KEY "MSDW" /* r/w flag (1 byte) */
++
+ #define FANS_COUNT "FNum" /* r-o ui8 */
+ #define FANS_MANUAL "FS! " /* r-w ui16 */
+ #define FAN_ACTUAL_SPEED "F0Ac" /* r-o fpe2 (2 bytes) */
+@@ -340,12 +361,79 @@ static int applesmc_read_motion_sensor(int index, s16* value)
+ }
+
+ /*
++ * applesmc_init_check_key_value - checks if a given key contains the bytes in
++ * buffer, if not, writes these bytes.
++ * In case of failure retry every INIT_WAIT_MSECS msec, and timeout if it
++ * waited more than INIT_TIMEOUT_MSECS in total.
++ * Returns zero on success or a negative error on failure. Callers must
++ * hold applesmc_lock.
++ */
++static int applesmc_init_check_key_value(const char* key, u8* buffer, u8 len)
++{
++ int total, ret, i, compare;
++ u8 rdbuffer[APPLESMC_MAX_DATA_LENGTH];
++
++ if (len > APPLESMC_MAX_DATA_LENGTH) {
++ printk(KERN_ERR "applesmc_init_check_key_value: cannot "
++ "read/write more than %d bytes",
++ APPLESMC_MAX_DATA_LENGTH);
++ return -EINVAL;
++ }
++
++ for (total = INIT_TIMEOUT_MSECS; total > 0; total -= INIT_WAIT_MSECS) {
++ if (!(ret = applesmc_read_key(key, rdbuffer, len))) {
++ compare = 1;
++ for (i = 0; i < len; i++) {
++ if (rdbuffer[i] != buffer[i]) {
++ compare = 0;
++ break;
++ }
++ }
++
++ if (compare) {
++ return 0;
++ }
++ }
++ ret = applesmc_write_key(key, buffer, len);
++ msleep(INIT_WAIT_MSECS);
++ }
++
++ if (ret)
++ return ret;
++ else
++ return -EIO;
++}
++
++irqreturn_t applesmc_irq_handler(int irq, void *dev_id)
++{
++ u8 int_type = inb(APPLESMC_INT_PORT);
++
++ switch (int_type) {
++ case 0x60:
++ printk("applesmc: received a free fall interrupt\n");
++ break;
++ case 0x6f:
++ printk("applesmc: received a high acceleration interrupt\n");
++ break;
++ case 0x80:
++ printk("applesmc: received a shock interrupt\n");
++ break;
++ default:
++ printk("applesmc: received an unknown interrupt %x\n", int_type);
++ }
++
++ return IRQ_NONE;
++}
++
++/*
+ * applesmc_device_init - initialize the accelerometer. Returns zero on success
+ * and negative error code on failure. Can sleep.
+ */
+ static int applesmc_device_init(void)
+ {
+- int total, ret = -ENXIO;
++ int total;
++ int ret = -ENXIO;
++ int ret1, ret2;
+ u8 buffer[2];
+
+ if (!applesmc_accelerometer)
+@@ -353,32 +441,79 @@ static int applesmc_device_init(void)
+
+ mutex_lock(&applesmc_lock);
+
++ /* Accept interrupts */
++ buffer[0] = 0x01;
+ for (total = INIT_TIMEOUT_MSECS; total > 0; total -= INIT_WAIT_MSECS) {
+- if (debug)
+- printk(KERN_DEBUG "applesmc try %d\n", total);
+- if (!applesmc_read_key(MOTION_SENSOR_KEY, buffer, 2) &&
+- (buffer[0] != 0x00 || buffer[1] != 0x00)) {
+- if (total == INIT_TIMEOUT_MSECS) {
+- printk(KERN_DEBUG "applesmc: device has"
+- " already been initialized"
+- " (0x%02x, 0x%02x).\n",
+- buffer[0], buffer[1]);
+- } else {
+- printk(KERN_DEBUG "applesmc: device"
+- " successfully initialized"
+- " (0x%02x, 0x%02x).\n",
+- buffer[0], buffer[1]);
+- }
+- ret = 0;
+- goto out;
+- }
+- buffer[0] = 0xe0;
+- buffer[1] = 0x00;
+- applesmc_write_key(MOTION_SENSOR_KEY, buffer, 2);
++ ret1 = applesmc_write_key(INTERRUPT_OK_KEY, buffer, 1);
++ msleep(INIT_WAIT_MSECS);
++
++ if (!ret1)
++ break;
++ }
++ if (ret1)
++ printk(KERN_WARNING "applesmc: Cannot set NTOK key, "
++ "will not receive interrupts.\n");
++
++ /* Setup interrupt controls. */
++ buffer[0] = 20; /* 20 msecs */
++ ret1 = applesmc_init_check_key_value(MOTION_LOW_NORM_INTERVAL,
++ buffer, 1);
++
++ buffer[0] = 20; /* 20 msecs */
++ ret2 = applesmc_init_check_key_value(MOTION_HIGH_NORM_INTERVAL,
++ buffer, 1);
++
++ if (ret1 || ret2) {
++ printk(KERN_WARNING "applesmc: Cannot set motion sensor "
++ "interrupt interval, might not receive "
++ "some interrupts.");
++ }
++
++ buffer[0] = 0x00;
++ buffer[1] = 0x60;
++ ret1 = applesmc_init_check_key_value(MOTION_LOW_NORM, buffer, 2);
++
++ buffer[0] = 0x01;
++ buffer[1] = 0xc0;
++ ret2 = applesmc_init_check_key_value(MOTION_HIGH_NORM, buffer, 2);
++
++ if (ret1 || ret2) {
++ printk(KERN_WARNING "applesmc: Cannot set motion sensor "
++ "min/max norm parameters, "
++ "might not receive some interrupts.");
++ }
++
++ /* Mysterious key. */
++ buffer[0] = 0x01;
++ for (total = INIT_TIMEOUT_MSECS; total > 0; total -= INIT_WAIT_MSECS) {
++ ret1 = applesmc_write_key(MSDW_KEY, buffer, 1);
+ msleep(INIT_WAIT_MSECS);
++
++ if (!ret1)
++ break;
++ }
++ if (ret1)
++ printk(KERN_WARNING "applesmc: Cannot set MSDW key\n");
++
++ /* Initialize the device. */
++ buffer[0] = 0xe0;
++ buffer[1] = 0xf8;
++ if (applesmc_init_check_key_value(MOTION_SENSOR_KEY, buffer, 2)) {
++ printk(KERN_WARNING "applesmc: failed to init "
++ "the accelerometer\n");
++ goto out;
+ }
+
+- printk(KERN_WARNING "applesmc: failed to init the device\n");
++ ret1 = request_irq(APPLESMC_IRQ, applesmc_irq_handler, IRQF_DISABLED,
++ "applesmc_irq_handler", NULL);
++
++ if (ret1) {
++ printk(KERN_WARNING "applesmc: cannot setup irq handler\n");
++ }
++
++ printk(KERN_DEBUG "applesmc: accelerometer "
++ "successfully initialized.\n");
++ ret = 0;
+
+ out:
+ mutex_unl...
[truncated message content] |