Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6
[pandora-kernel.git] / drivers / hwmon / w83627hf.c
index bd87a42..79368d5 100644 (file)
@@ -28,6 +28,7 @@
     w83627hf   9       3       2       3       0x20    0x5ca3  no      yes(LPC)
     w83627thf  7       3       3       3       0x90    0x5ca3  no      yes(LPC)
     w83637hf   7       3       3       3       0x80    0x5ca3  no      yes(LPC)
+    w83687thf  7       3       3       3       0x90    0x5ca3  no      yes(LPC)
     w83697hf   8       2       2       2       0x60    0x5ca3  no      yes(LPC)
 
     For other winbond chips, and for i2c support in the above chips,
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
-#include <linux/i2c-vid.h>
+#include <linux/i2c-isa.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-vid.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
 #include <asm/io.h>
 #include "lm75.h"
 
@@ -56,12 +60,15 @@ module_param(force_i2c, byte, 0);
 MODULE_PARM_DESC(force_i2c,
                 "Initialize the i2c address of the sensors");
 
-/* Addresses to scan */
-static unsigned short normal_i2c[] = { I2C_CLIENT_END };
-static unsigned int normal_isa[] = { 0, I2C_CLIENT_ISA_END };
+/* The actual ISA address is read from Super-I/O configuration space */
+static unsigned short address;
 
 /* Insmod parameters */
-SENSORS_INSMOD_4(w83627hf, w83627thf, w83697hf, w83637hf);
+enum chips { any_chip, w83627hf, w83627thf, w83697hf, w83637hf, w83687thf };
+
+static int reset;
+module_param(reset, bool, 0);
+MODULE_PARM_DESC(reset, "Set to one to reset chip on load");
 
 static int init = 1;
 module_param(init, bool, 0);
@@ -95,6 +102,10 @@ static int VAL;             /* The value to read/write */
 #define W83627THF_GPIO5_IOSR   0xf3 /* w83627thf only */
 #define W83627THF_GPIO5_DR     0xf4 /* w83627thf only */
 
+#define W83687THF_VID_EN       0x29 /* w83687thf only */
+#define W83687THF_VID_CFG      0xF0 /* w83687thf only */
+#define W83687THF_VID_DATA     0xF1 /* w83687thf only */
+
 static inline void
 superio_outb(int reg, int val)
 {
@@ -133,14 +144,19 @@ superio_exit(void)
 #define W627THF_DEVID 0x82
 #define W697_DEVID 0x60
 #define W637_DEVID 0x70
+#define W687THF_DEVID 0x85
 #define WINB_ACT_REG 0x30
 #define WINB_BASE_REG 0x60
 /* Constants specified below */
 
-/* Length of ISA address segment */
-#define WINB_EXTENT 8
+/* Alignment of the base address */
+#define WINB_ALIGNMENT         ~7
+
+/* Offset & size of I/O region we are interested in */
+#define WINB_REGION_OFFSET     5
+#define WINB_REGION_SIZE       2
 
-/* Where are the ISA address/data registers relative to the base address */
+/* Where are the sensors address/data registers relative to the base address */
 #define W83781D_ADDR_REG_OFFSET 5
 #define W83781D_DATA_REG_OFFSET 6
 
@@ -171,11 +187,10 @@ superio_exit(void)
 #define W83781D_REG_BANK 0x4E
 
 #define W83781D_REG_CONFIG 0x40
-#define W83781D_REG_ALARM1 0x41
-#define W83781D_REG_ALARM2 0x42
-#define W83781D_REG_ALARM3 0x450
+#define W83781D_REG_ALARM1 0x459
+#define W83781D_REG_ALARM2 0x45A
+#define W83781D_REG_ALARM3 0x45B
 
-#define W83781D_REG_IRQ 0x4C
 #define W83781D_REG_BEEP_CONFIG 0x4D
 #define W83781D_REG_BEEP_INTS1 0x56
 #define W83781D_REG_BEEP_INTS2 0x57
@@ -192,13 +207,12 @@ superio_exit(void)
 
 #define W83627HF_REG_PWM1 0x5A
 #define W83627HF_REG_PWM2 0x5B
-#define W83627HF_REG_PWMCLK12 0x5C
 
-#define W83627THF_REG_PWM1             0x01    /* 697HF and 637HF too */
-#define W83627THF_REG_PWM2             0x03    /* 697HF and 637HF too */
-#define W83627THF_REG_PWM3             0x11    /* 637HF too */
+#define W83627THF_REG_PWM1             0x01    /* 697HF/637HF/687THF too */
+#define W83627THF_REG_PWM2             0x03    /* 697HF/637HF/687THF too */
+#define W83627THF_REG_PWM3             0x11    /* 637HF/687THF too */
 
-#define W83627THF_REG_VRM_OVT_CFG      0x18    /* 637HF too */
+#define W83627THF_REG_VRM_OVT_CFG      0x18    /* 637HF/687THF too */
 
 static const u8 regpwm_627hf[] = { W83627HF_REG_PWM1, W83627HF_REG_PWM2 };
 static const u8 regpwm[] = { W83627THF_REG_PWM1, W83627THF_REG_PWM2,
@@ -277,10 +291,11 @@ static inline u8 DIV_TO_REG(long val)
    dynamically allocated, at the same time when a new client is allocated. */
 struct w83627hf_data {
        struct i2c_client client;
-       struct semaphore lock;
+       struct class_device *class_dev;
+       struct mutex lock;
        enum chips type;
 
-       struct semaphore update_lock;
+       struct mutex update_lock;
        char valid;             /* !=0 if following fields are valid */
        unsigned long last_updated;     /* In jiffies */
 
@@ -310,27 +325,23 @@ struct w83627hf_data {
                                   Default = 3435.
                                   Other Betas unimplemented */
        u8 vrm;
-       u8 vrm_ovt;             /* Register value, 627thf & 637hf only */
+       u8 vrm_ovt;             /* Register value, 627THF/637HF/687THF only */
 };
 
 
-static int w83627hf_attach_adapter(struct i2c_adapter *adapter);
-static int w83627hf_detect(struct i2c_adapter *adapter, int address,
-                         int kind);
+static int w83627hf_detect(struct i2c_adapter *adapter);
 static int w83627hf_detach_client(struct i2c_client *client);
 
-static int w83627hf_read_value(struct i2c_client *client, u16 register);
-static int w83627hf_write_value(struct i2c_client *client, u16 register,
-                              u16 value);
+static int w83627hf_read_value(struct i2c_client *client, u16 reg);
+static int w83627hf_write_value(struct i2c_client *client, u16 reg, u16 value);
 static struct w83627hf_data *w83627hf_update_device(struct device *dev);
 static void w83627hf_init_client(struct i2c_client *client);
 
 static struct i2c_driver w83627hf_driver = {
-       .owner          = THIS_MODULE,
-       .name           = "w83627hf",
-       .id             = I2C_DRIVERID_W83627HF,
-       .flags          = I2C_DF_NOTIFY,
-       .attach_adapter = w83627hf_attach_adapter,
+       .driver = {
+               .name   = "w83627hf",
+       },
+       .attach_adapter = w83627hf_detect,
        .detach_client  = w83627hf_detach_client,
 };
 
@@ -355,12 +366,12 @@ store_in_##reg (struct device *dev, const char *buf, size_t count, int nr) \
         \
        val = simple_strtoul(buf, NULL, 10); \
         \
-       down(&data->update_lock); \
+       mutex_lock(&data->update_lock); \
        data->in_##reg[nr] = IN_TO_REG(val); \
        w83627hf_write_value(client, W83781D_REG_IN_##REG(nr), \
                            data->in_##reg[nr]); \
         \
-       up(&data->update_lock); \
+       mutex_unlock(&data->update_lock); \
        return count; \
 }
 store_in_reg(MIN, min)
@@ -408,7 +419,8 @@ static ssize_t show_in_0(struct w83627hf_data *data, char *buf, u8 reg)
        long in0;
 
        if ((data->vrm_ovt & 0x01) &&
-               (w83627thf == data->type || w83637hf == data->type))
+               (w83627thf == data->type || w83637hf == data->type
+                || w83687thf == data->type))
 
                /* use VRM9 calculation */
                in0 = (long)((reg * 488 + 70000 + 50) / 100);
@@ -446,19 +458,22 @@ static ssize_t store_regs_in_min0(struct device *dev, struct device_attribute *a
 
        val = simple_strtoul(buf, NULL, 10);
 
-       down(&data->update_lock);
+       mutex_lock(&data->update_lock);
        
        if ((data->vrm_ovt & 0x01) &&
-               (w83627thf == data->type || w83637hf == data->type))
+               (w83627thf == data->type || w83637hf == data->type
+                || w83687thf == data->type))
 
                /* use VRM9 calculation */
-               data->in_min[0] = (u8)(((val * 100) - 70000 + 244) / 488);
+               data->in_min[0] =
+                       SENSORS_LIMIT(((val * 100) - 70000 + 244) / 488, 0,
+                                       255);
        else
                /* use VRM8 (standard) calculation */
                data->in_min[0] = IN_TO_REG(val);
 
        w83627hf_write_value(client, W83781D_REG_IN_MIN(0), data->in_min[0]);
-       up(&data->update_lock);
+       mutex_unlock(&data->update_lock);
        return count;
 }
 
@@ -471,19 +486,22 @@ static ssize_t store_regs_in_max0(struct device *dev, struct device_attribute *a
 
        val = simple_strtoul(buf, NULL, 10);
 
-       down(&data->update_lock);
+       mutex_lock(&data->update_lock);
 
        if ((data->vrm_ovt & 0x01) &&
-               (w83627thf == data->type || w83637hf == data->type))
+               (w83627thf == data->type || w83637hf == data->type
+                || w83687thf == data->type))
                
                /* use VRM9 calculation */
-               data->in_max[0] = (u8)(((val * 100) - 70000 + 244) / 488);
+               data->in_max[0] =
+                       SENSORS_LIMIT(((val * 100) - 70000 + 244) / 488, 0,
+                                       255);
        else
                /* use VRM8 (standard) calculation */
                data->in_max[0] = IN_TO_REG(val);
 
        w83627hf_write_value(client, W83781D_REG_IN_MAX(0), data->in_max[0]);
-       up(&data->update_lock);
+       mutex_unlock(&data->update_lock);
        return count;
 }
 
@@ -520,13 +538,13 @@ store_fan_min(struct device *dev, const char *buf, size_t count, int nr)
 
        val = simple_strtoul(buf, NULL, 10);
 
-       down(&data->update_lock);
+       mutex_lock(&data->update_lock);
        data->fan_min[nr - 1] =
            FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr - 1]));
        w83627hf_write_value(client, W83781D_REG_FAN_MIN(nr),
                            data->fan_min[nr - 1]);
 
-       up(&data->update_lock);
+       mutex_unlock(&data->update_lock);
        return count;
 }
 
@@ -588,7 +606,7 @@ store_temp_##reg (struct device *dev, const char *buf, size_t count, int nr) \
         \
        val = simple_strtoul(buf, NULL, 10); \
         \
-       down(&data->update_lock); \
+       mutex_lock(&data->update_lock); \
         \
        if (nr >= 2) {  /* TEMP2 and TEMP3 */ \
                data->temp_##reg##_add[nr-2] = LM75_TEMP_TO_REG(val); \
@@ -600,7 +618,7 @@ store_temp_##reg (struct device *dev, const char *buf, size_t count, int nr) \
                        data->temp_##reg); \
        } \
         \
-       up(&data->update_lock); \
+       mutex_unlock(&data->update_lock); \
        return count; \
 }
 store_temp_reg(OVER, max);
@@ -709,7 +727,7 @@ store_beep_reg(struct device *dev, const char *buf, size_t count,
 
        val = simple_strtoul(buf, NULL, 10);
 
-       down(&data->update_lock);
+       mutex_lock(&data->update_lock);
 
        if (update_mask == BEEP_MASK) { /* We are storing beep_mask */
                data->beep_mask = BEEP_MASK_TO_REG(val);
@@ -727,7 +745,7 @@ store_beep_reg(struct device *dev, const char *buf, size_t count,
        w83627hf_write_value(client, W83781D_REG_BEEP_INTS2,
                            val2 | data->beep_enable << 7);
 
-       up(&data->update_lock);
+       mutex_unlock(&data->update_lock);
        return count;
 }
 
@@ -763,7 +781,7 @@ show_fan_div_reg(struct device *dev, char *buf, int nr)
 
 /* Note: we save and restore the fan minimum here, because its value is
    determined in part by the fan divisor.  This follows the principle of
-   least suprise; the user doesn't expect the fan minimum to change just
+   least surprise; the user doesn't expect the fan minimum to change just
    because the divisor changed. */
 static ssize_t
 store_fan_div_reg(struct device *dev, const char *buf, size_t count, int nr)
@@ -774,7 +792,7 @@ store_fan_div_reg(struct device *dev, const char *buf, size_t count, int nr)
        u8 reg;
        unsigned long val = simple_strtoul(buf, NULL, 10);
 
-       down(&data->update_lock);
+       mutex_lock(&data->update_lock);
 
        /* Save fan_min */
        min = FAN_FROM_REG(data->fan_min[nr],
@@ -796,7 +814,7 @@ store_fan_div_reg(struct device *dev, const char *buf, size_t count, int nr)
        data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr]));
        w83627hf_write_value(client, W83781D_REG_FAN_MIN(nr+1), data->fan_min[nr]);
 
-       up(&data->update_lock);
+       mutex_unlock(&data->update_lock);
        return count;
 }
 
@@ -839,7 +857,7 @@ store_pwm_reg(struct device *dev, const char *buf, size_t count, int nr)
 
        val = simple_strtoul(buf, NULL, 10);
 
-       down(&data->update_lock);
+       mutex_lock(&data->update_lock);
 
        if (data->type == w83627thf) {
                /* bits 0-3 are reserved  in 627THF */
@@ -856,7 +874,7 @@ store_pwm_reg(struct device *dev, const char *buf, size_t count, int nr)
                                     data->pwm[nr - 1]);
        }
 
-       up(&data->update_lock);
+       mutex_unlock(&data->update_lock);
        return count;
 }
 
@@ -898,7 +916,7 @@ store_sensor_reg(struct device *dev, const char *buf, size_t count, int nr)
 
        val = simple_strtoul(buf, NULL, 10);
 
-       down(&data->update_lock);
+       mutex_lock(&data->update_lock);
 
        switch (val) {
        case 1:         /* PII/Celeron diode */
@@ -932,7 +950,7 @@ store_sensor_reg(struct device *dev, const char *buf, size_t count, int nr)
                break;
        }
 
-       up(&data->update_lock);
+       mutex_unlock(&data->update_lock);
        return count;
 }
 
@@ -959,16 +977,7 @@ device_create_file(&client->dev, &dev_attr_temp##offset##_type); \
 } while (0)
 
 
-/* This function is called when:
-     * w83627hf_driver is inserted (when this module is loaded), for each
-       available adapter
-     * when a new adapter is inserted (and w83627hf_driver is still present) */
-static int w83627hf_attach_adapter(struct i2c_adapter *adapter)
-{
-       return i2c_detect(adapter, &addr_data, w83627hf_detect);
-}
-
-static int w83627hf_find(int sioaddr, int *address)
+static int __init w83627hf_find(int sioaddr, unsigned short *addr)
 {
        u16 val;
 
@@ -980,7 +989,8 @@ static int w83627hf_find(int sioaddr, int *address)
        if(val != W627_DEVID &&
           val != W627THF_DEVID &&
           val != W697_DEVID &&
-          val != W637_DEVID) {
+          val != W637_DEVID &&
+          val != W687THF_DEVID) {
                superio_exit();
                return -ENODEV;
        }
@@ -988,36 +998,29 @@ static int w83627hf_find(int sioaddr, int *address)
        superio_select(W83627HF_LD_HWM);
        val = (superio_inb(WINB_BASE_REG) << 8) |
               superio_inb(WINB_BASE_REG + 1);
-       *address = val & ~(WINB_EXTENT - 1);
-       if (*address == 0 && force_addr == 0) {
+       *addr = val & WINB_ALIGNMENT;
+       if (*addr == 0 && force_addr == 0) {
                superio_exit();
                return -ENODEV;
        }
-       if (force_addr)
-               *address = force_addr;  /* so detect will get called */
 
        superio_exit();
        return 0;
 }
 
-int w83627hf_detect(struct i2c_adapter *adapter, int address,
-                  int kind)
+static int w83627hf_detect(struct i2c_adapter *adapter)
 {
-       int val;
+       int val, kind;
        struct i2c_client *new_client;
        struct w83627hf_data *data;
        int err = 0;
        const char *client_name = "";
 
-       if (!i2c_is_isa_adapter(adapter)) {
-               err = -ENODEV;
-               goto ERROR0;
-       }
-
        if(force_addr)
-               address = force_addr & ~(WINB_EXTENT - 1);
+               address = force_addr & WINB_ALIGNMENT;
 
-       if (!request_region(address, WINB_EXTENT, w83627hf_driver.name)) {
+       if (!request_region(address + WINB_REGION_OFFSET, WINB_REGION_SIZE,
+                           w83627hf_driver.driver.name)) {
                err = -EBUSY;
                goto ERROR0;
        }
@@ -1041,6 +1044,8 @@ int w83627hf_detect(struct i2c_adapter *adapter, int address,
                kind = w83627thf;
        else if(val == W637_DEVID)
                kind = w83637hf;
+       else if (val == W687THF_DEVID)
+               kind = w83687thf;
        else {
                dev_info(&adapter->dev,
                         "Unsupported chip (dev_id=0x%02X).\n", val);
@@ -1056,16 +1061,15 @@ int w83627hf_detect(struct i2c_adapter *adapter, int address,
           client structure, even though we cannot fill it completely yet.
           But it allows us to access w83627hf_{read,write}_value. */
 
-       if (!(data = kmalloc(sizeof(struct w83627hf_data), GFP_KERNEL))) {
+       if (!(data = kzalloc(sizeof(struct w83627hf_data), GFP_KERNEL))) {
                err = -ENOMEM;
                goto ERROR1;
        }
-       memset(data, 0, sizeof(struct w83627hf_data));
 
        new_client = &data->client;
        i2c_set_clientdata(new_client, data);
        new_client->addr = address;
-       init_MUTEX(&data->lock);
+       mutex_init(&data->lock);
        new_client->adapter = adapter;
        new_client->driver = &w83627hf_driver;
        new_client->flags = 0;
@@ -1079,13 +1083,15 @@ int w83627hf_detect(struct i2c_adapter *adapter, int address,
                client_name = "w83697hf";
        } else if (kind == w83637hf) {
                client_name = "w83637hf";
+       } else if (kind == w83687thf) {
+               client_name = "w83687thf";
        }
 
        /* Fill in the remaining client fields and put into the global list */
        strlcpy(new_client->name, client_name, I2C_NAME_SIZE);
        data->type = kind;
        data->valid = 0;
-       init_MUTEX(&data->update_lock);
+       mutex_init(&data->update_lock);
 
        /* Tell the I2C layer a new client has arrived */
        if ((err = i2c_attach_client(new_client)))
@@ -1102,13 +1108,19 @@ int w83627hf_detect(struct i2c_adapter *adapter, int address,
        data->fan_min[2] = w83627hf_read_value(new_client, W83781D_REG_FAN_MIN(3));
 
        /* Register sysfs hooks */
+       data->class_dev = hwmon_device_register(&new_client->dev);
+       if (IS_ERR(data->class_dev)) {
+               err = PTR_ERR(data->class_dev);
+               goto ERROR3;
+       }
+
        device_create_file_in(new_client, 0);
        if (kind != w83697hf)
                device_create_file_in(new_client, 1);
        device_create_file_in(new_client, 2);
        device_create_file_in(new_client, 3);
        device_create_file_in(new_client, 4);
-       if (kind != w83627thf && kind != w83637hf) {
+       if (kind == w83627hf || kind == w83697hf) {
                device_create_file_in(new_client, 5);
                device_create_file_in(new_client, 6);
        }
@@ -1125,11 +1137,10 @@ int w83627hf_detect(struct i2c_adapter *adapter, int address,
        if (kind != w83697hf)
                device_create_file_temp(new_client, 3);
 
-       if (kind != w83697hf)
+       if (kind != w83697hf && data->vid != 0xff) {
                device_create_file_vid(new_client);
-
-       if (kind != w83697hf)
                device_create_file_vrm(new_client);
+       }
 
        device_create_file_fan_div(new_client, 1);
        device_create_file_fan_div(new_client, 2);
@@ -1142,7 +1153,7 @@ int w83627hf_detect(struct i2c_adapter *adapter, int address,
 
        device_create_file_pwm(new_client, 1);
        device_create_file_pwm(new_client, 2);
-       if (kind == w83627thf || kind == w83637hf)
+       if (kind == w83627thf || kind == w83637hf || kind == w83687thf)
                device_create_file_pwm(new_client, 3);
 
        device_create_file_sensor(new_client, 1);
@@ -1152,26 +1163,28 @@ int w83627hf_detect(struct i2c_adapter *adapter, int address,
 
        return 0;
 
+      ERROR3:
+       i2c_detach_client(new_client);
       ERROR2:
        kfree(data);
       ERROR1:
-       release_region(address, WINB_EXTENT);
+       release_region(address + WINB_REGION_OFFSET, WINB_REGION_SIZE);
       ERROR0:
        return err;
 }
 
 static int w83627hf_detach_client(struct i2c_client *client)
 {
+       struct w83627hf_data *data = i2c_get_clientdata(client);
        int err;
 
-       if ((err = i2c_detach_client(client))) {
-               dev_err(&client->dev,
-                      "Client deregistration failed, client not detached.\n");
+       hwmon_device_unregister(data->class_dev);
+
+       if ((err = i2c_detach_client(client)))
                return err;
-       }
 
-       release_region(client->addr, WINB_EXTENT);
-       kfree(i2c_get_clientdata(client));
+       release_region(client->addr + WINB_REGION_OFFSET, WINB_REGION_SIZE);
+       kfree(data);
 
        return 0;
 }
@@ -1188,7 +1201,7 @@ static int w83627hf_read_value(struct i2c_client *client, u16 reg)
        struct w83627hf_data *data = i2c_get_clientdata(client);
        int res, word_sized;
 
-       down(&data->lock);
+       mutex_lock(&data->lock);
        word_sized = (((reg & 0xff00) == 0x100)
                   || ((reg & 0xff00) == 0x200))
                  && (((reg & 0x00ff) == 0x50)
@@ -1214,7 +1227,7 @@ static int w83627hf_read_value(struct i2c_client *client, u16 reg)
                       client->addr + W83781D_ADDR_REG_OFFSET);
                outb_p(0, client->addr + W83781D_DATA_REG_OFFSET);
        }
-       up(&data->lock);
+       mutex_unlock(&data->lock);
        return res;
 }
 
@@ -1233,7 +1246,7 @@ static int w83627thf_read_gpio5(struct i2c_client *client)
 
        /* Make sure the pins are configured for input
           There must be at least five (VRM 9), and possibly 6 (VRM 10) */
-       sel = superio_inb(W83627THF_GPIO5_IOSR);
+       sel = superio_inb(W83627THF_GPIO5_IOSR) & 0x3f;
        if ((sel & 0x1f) != 0x1f) {
                dev_dbg(&client->dev, "GPIO5 not configured for VID "
                        "function\n");
@@ -1248,12 +1261,39 @@ exit:
        return res;
 }
 
+static int w83687thf_read_vid(struct i2c_client *client)
+{
+       int res = 0xff;
+
+       superio_enter();
+       superio_select(W83627HF_LD_HWM);
+
+       /* Make sure these GPIO pins are enabled */
+       if (!(superio_inb(W83687THF_VID_EN) & (1 << 2))) {
+               dev_dbg(&client->dev, "VID disabled, no VID function\n");
+               goto exit;
+       }
+
+       /* Make sure the pins are configured for input */
+       if (!(superio_inb(W83687THF_VID_CFG) & (1 << 4))) {
+               dev_dbg(&client->dev, "VID configured as output, "
+                       "no VID function\n");
+               goto exit;
+       }
+
+       res = superio_inb(W83687THF_VID_DATA) & 0x3f;
+
+exit:
+       superio_exit();
+       return res;
+}
+
 static int w83627hf_write_value(struct i2c_client *client, u16 reg, u16 value)
 {
        struct w83627hf_data *data = i2c_get_clientdata(client);
        int word_sized;
 
-       down(&data->lock);
+       mutex_lock(&data->lock);
        word_sized = (((reg & 0xff00) == 0x100)
                   || ((reg & 0xff00) == 0x200))
                  && (((reg & 0x00ff) == 0x53)
@@ -1278,11 +1318,10 @@ static int w83627hf_write_value(struct i2c_client *client, u16 reg, u16 value)
                       client->addr + W83781D_ADDR_REG_OFFSET);
                outb_p(0, client->addr + W83781D_DATA_REG_OFFSET);
        }
-       up(&data->lock);
+       mutex_unlock(&data->lock);
        return 0;
 }
 
-/* Called when we have found a new W83781D. It should set limits, etc. */
 static void w83627hf_init_client(struct i2c_client *client)
 {
        struct w83627hf_data *data = i2c_get_clientdata(client);
@@ -1290,7 +1329,15 @@ static void w83627hf_init_client(struct i2c_client *client)
        int type = data->type;
        u8 tmp;
 
-       if(init) {
+       if (reset) {
+               /* Resetting the chip has been the default for a long time,
+                  but repeatedly caused problems (fans going to full
+                  speed...) so it is now optional. It might even go away if
+                  nobody reports it as being useful, as I see very little
+                  reason why this would be needed at all. */
+               dev_info(&client->dev, "If reset=1 solved a problem you were "
+                        "having, please report!\n");
+
                /* save this register */
                i = w83627hf_read_value(client, W83781D_REG_BEEP_CONFIG);
                /* Reset all except Watchdog values and last conversion values
@@ -1317,19 +1364,21 @@ static void w83627hf_init_client(struct i2c_client *client)
                int hi = w83627hf_read_value(client, W83781D_REG_CHIPID);
                data->vid = (lo & 0x0f) | ((hi & 0x01) << 4);
        } else if (w83627thf == data->type) {
-               data->vid = w83627thf_read_gpio5(client) & 0x3f;
+               data->vid = w83627thf_read_gpio5(client);
+       } else if (w83687thf == data->type) {
+               data->vid = w83687thf_read_vid(client);
        }
 
        /* Read VRM & OVT Config only once */
-       if (w83627thf == data->type || w83637hf == data->type) {
+       if (w83627thf == data->type || w83637hf == data->type
+        || w83687thf == data->type) {
                data->vrm_ovt = 
                        w83627hf_read_value(client, W83627THF_REG_VRM_OVT_CFG);
-               data->vrm = (data->vrm_ovt & 0x01) ? 90 : 82;
-       } else {
-               /* Convert VID to voltage based on default VRM */
-               data->vrm = i2c_which_vrm();
        }
 
+       /* Convert VID to voltage based on VRM */
+       data->vrm = vid_which_vrm();
+
        tmp = w83627hf_read_value(client, W83781D_REG_SCFG1);
        for (i = 1; i <= 3; i++) {
                if (!(tmp & BIT_SCFG1[i - 1])) {
@@ -1367,19 +1416,6 @@ static void w83627hf_init_client(struct i2c_client *client)
                                        W83781D_REG_TEMP3_CONFIG, tmp & 0xfe);
                        }
                }
-
-               if (type == w83627hf) {
-                       /* enable PWM2 control (can't hurt since PWM reg
-                          should have been reset to 0xff) */
-                       w83627hf_write_value(client, W83627HF_REG_PWMCLK12,
-                                           0x19);
-               }
-               /* enable comparator mode for temp2 and temp3 so
-                  alarm indication will work correctly */
-               i = w83627hf_read_value(client, W83781D_REG_IRQ);
-               if (!(i & 0x40))
-                       w83627hf_write_value(client, W83781D_REG_IRQ,
-                                           i | 0x40);
        }
 
        /* Start monitoring */
@@ -1395,15 +1431,15 @@ static struct w83627hf_data *w83627hf_update_device(struct device *dev)
        struct w83627hf_data *data = i2c_get_clientdata(client);
        int i;
 
-       down(&data->update_lock);
+       mutex_lock(&data->update_lock);
 
        if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
            || !data->valid) {
                for (i = 0; i <= 8; i++) {
                        /* skip missing sensors */
                        if (((data->type == w83697hf) && (i == 1)) ||
-                           ((data->type == w83627thf || data->type == w83637hf)
-                           && (i == 4 || i == 5)))
+                           ((data->type != w83627hf && data->type != w83697hf)
+                           && (i == 5 || i == 6)))
                                continue;
                        data->in[i] =
                            w83627hf_read_value(client, W83781D_REG_IN(i));
@@ -1478,27 +1514,24 @@ static struct w83627hf_data *w83627hf_update_device(struct device *dev)
                data->valid = 1;
        }
 
-       up(&data->update_lock);
+       mutex_unlock(&data->update_lock);
 
        return data;
 }
 
 static int __init sensors_w83627hf_init(void)
 {
-       int addr;
-
-       if (w83627hf_find(0x2e, &addr)
-        && w83627hf_find(0x4e, &addr)) {
+       if (w83627hf_find(0x2e, &address)
+        && w83627hf_find(0x4e, &address)) {
                return -ENODEV;
        }
-       normal_isa[0] = addr;
 
-       return i2c_add_driver(&w83627hf_driver);
+       return i2c_isa_add_driver(&w83627hf_driver);
 }
 
 static void __exit sensors_w83627hf_exit(void)
 {
-       i2c_del_driver(&w83627hf_driver);
+       i2c_isa_del_driver(&w83627hf_driver);
 }
 
 MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, "