upgrade to fedora-2.6.12-1.1398.FC4 + vserver 2.0.rc7
[linux-2.6.git] / drivers / i2c / chips / w83627hf.c
index cf9e887..b1da5ed 100644 (file)
@@ -40,6 +40,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
+#include <linux/jiffies.h>
 #include <linux/i2c.h>
 #include <linux/i2c-sensor.h>
 #include <linux/i2c-vid.h>
@@ -67,9 +68,9 @@ module_param(init, bool, 0);
 MODULE_PARM_DESC(init, "Set to zero to bypass chip initialization");
 
 /* modified from kernel/include/traps.c */
-#define        REG     0x2e    /* The register to read/write */
+static int REG;                /* The register to read/write */
 #define        DEV     0x07    /* Register: Logical device select */
-#define        VAL     0x2f    /* The value to read/write */
+static int VAL;                /* The value to read/write */
 
 /* logical device numbers for superio_select (below) */
 #define W83627HF_LD_FDC                0x00
@@ -90,9 +91,9 @@ MODULE_PARM_DESC(init, "Set to zero to bypass chip initialization");
 
 #define        DEVID   0x20    /* Register: Device ID */
 
+#define W83627THF_GPIO5_EN     0x30 /* w83627thf only */
 #define W83627THF_GPIO5_IOSR   0xf3 /* w83627thf only */
 #define W83627THF_GPIO5_DR     0xf4 /* w83627thf only */
-#define W83627THF_GPIO5_INVR   0xf5 /* w83627thf only */
 
 static inline void
 superio_outb(int reg, int val)
@@ -303,7 +304,6 @@ struct w83627hf_data {
        u32 beep_mask;          /* Register encoding, combined */
        u8 beep_enable;         /* Boolean */
        u8 pwm[3];              /* Register value */
-       u8 pwmenable[3];        /* bool */
        u16 sens[3];            /* 782D/783S only.
                                   1 = pentium diode; 2 = 3904 diode;
                                   3000-5000 = thermistor beta.
@@ -354,10 +354,13 @@ store_in_##reg (struct device *dev, const char *buf, size_t count, int nr) \
        u32 val; \
         \
        val = simple_strtoul(buf, NULL, 10); \
+        \
+       down(&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); \
        return count; \
 }
 store_in_reg(MIN, min)
@@ -442,6 +445,9 @@ static ssize_t store_regs_in_min0(struct device *dev,
        u32 val;
 
        val = simple_strtoul(buf, NULL, 10);
+
+       down(&data->update_lock);
+       
        if ((data->vrm_ovt & 0x01) &&
                (w83627thf == data->type || w83637hf == data->type))
 
@@ -452,6 +458,7 @@ static ssize_t store_regs_in_min0(struct device *dev,
                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);
        return count;
 }
 
@@ -463,6 +470,9 @@ static ssize_t store_regs_in_max0(struct device *dev,
        u32 val;
 
        val = simple_strtoul(buf, NULL, 10);
+
+       down(&data->update_lock);
+
        if ((data->vrm_ovt & 0x01) &&
                (w83627thf == data->type || w83637hf == data->type))
                
@@ -473,6 +483,7 @@ static ssize_t store_regs_in_max0(struct device *dev,
                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);
        return count;
 }
 
@@ -508,11 +519,14 @@ store_fan_min(struct device *dev, const char *buf, size_t count, int nr)
        u32 val;
 
        val = simple_strtoul(buf, NULL, 10);
+
+       down(&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);
        return count;
 }
 
@@ -574,6 +588,8 @@ store_temp_##reg (struct device *dev, const char *buf, size_t count, int nr) \
         \
        val = simple_strtoul(buf, NULL, 10); \
         \
+       down(&data->update_lock); \
+        \
        if (nr >= 2) {  /* TEMP2 and TEMP3 */ \
                data->temp_##reg##_add[nr-2] = LM75_TEMP_TO_REG(val); \
                w83627hf_write_value(client, W83781D_REG_TEMP_##REG(nr), \
@@ -584,6 +600,7 @@ store_temp_##reg (struct device *dev, const char *buf, size_t count, int nr) \
                        data->temp_##reg); \
        } \
         \
+       up(&data->update_lock); \
        return count; \
 }
 store_temp_reg(OVER, max);
@@ -692,6 +709,8 @@ store_beep_reg(struct device *dev, const char *buf, size_t count,
 
        val = simple_strtoul(buf, NULL, 10);
 
+       down(&data->update_lock);
+
        if (update_mask == BEEP_MASK) { /* We are storing beep_mask */
                data->beep_mask = BEEP_MASK_TO_REG(val);
                w83627hf_write_value(client, W83781D_REG_BEEP_INTS1,
@@ -708,6 +727,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);
        return count;
 }
 
@@ -752,12 +772,15 @@ store_fan_div_reg(struct device *dev, const char *buf, size_t count, int nr)
        struct w83627hf_data *data = i2c_get_clientdata(client);
        unsigned long min;
        u8 reg;
+       unsigned long val = simple_strtoul(buf, NULL, 10);
+
+       down(&data->update_lock);
 
        /* Save fan_min */
        min = FAN_FROM_REG(data->fan_min[nr],
                           DIV_FROM_REG(data->fan_div[nr]));
 
-       data->fan_div[nr] = DIV_TO_REG(simple_strtoul(buf, NULL, 10));
+       data->fan_div[nr] = DIV_TO_REG(val);
 
        reg = (w83627hf_read_value(client, nr==2 ? W83781D_REG_PIN : W83781D_REG_VID_FANDIV)
               & (nr==0 ? 0xcf : 0x3f))
@@ -773,6 +796,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);
        return count;
 }
 
@@ -815,6 +839,8 @@ store_pwm_reg(struct device *dev, const char *buf, size_t count, int nr)
 
        val = simple_strtoul(buf, NULL, 10);
 
+       down(&data->update_lock);
+
        if (data->type == w83627thf) {
                /* bits 0-3 are reserved  in 627THF */
                data->pwm[nr - 1] = PWM_TO_REG(val) & 0xf0;
@@ -830,6 +856,7 @@ store_pwm_reg(struct device *dev, const char *buf, size_t count, int nr)
                                     data->pwm[nr - 1]);
        }
 
+       up(&data->update_lock);
        return count;
 }
 
@@ -871,6 +898,8 @@ store_sensor_reg(struct device *dev, const char *buf, size_t count, int nr)
 
        val = simple_strtoul(buf, NULL, 10);
 
+       down(&data->update_lock);
+
        switch (val) {
        case 1:         /* PII/Celeron diode */
                tmp = w83627hf_read_value(client, W83781D_REG_SCFG1);
@@ -903,6 +932,7 @@ store_sensor_reg(struct device *dev, const char *buf, size_t count, int nr)
                break;
        }
 
+       up(&data->update_lock);
        return count;
 }
 
@@ -938,10 +968,13 @@ static int w83627hf_attach_adapter(struct i2c_adapter *adapter)
        return i2c_detect(adapter, &addr_data, w83627hf_detect);
 }
 
-static int w83627hf_find(int *address)
+static int w83627hf_find(int sioaddr, int *address)
 {
        u16 val;
 
+       REG = sioaddr;
+       VAL = sioaddr + 1;
+
        superio_enter();
        val= superio_inb(DEVID);
        if(val != W627_DEVID &&
@@ -984,7 +1017,7 @@ int w83627hf_detect(struct i2c_adapter *adapter, int address,
        if(force_addr)
                address = force_addr & ~(WINB_EXTENT - 1);
 
-       if (!request_region(address, WINB_EXTENT, "w83627hf")) {
+       if (!request_region(address, WINB_EXTENT, w83627hf_driver.name)) {
                err = -EBUSY;
                goto ERROR0;
        }
@@ -1187,16 +1220,31 @@ static int w83627hf_read_value(struct i2c_client *client, u16 reg)
 
 static int w83627thf_read_gpio5(struct i2c_client *client)
 {
-       struct w83627hf_data *data = i2c_get_clientdata(client);
-       int res, inv;
+       int res = 0xff, sel;
 
-       down(&data->lock);
        superio_enter();
        superio_select(W83627HF_LD_GPIO5);
-       res = superio_inb(W83627THF_GPIO5_DR);
-       inv = superio_inb(W83627THF_GPIO5_INVR);
+
+       /* Make sure these GPIO pins are enabled */
+       if (!(superio_inb(W83627THF_GPIO5_EN) & (1<<3))) {
+               dev_dbg(&client->dev, "GPIO5 disabled, no VID function\n");
+               goto exit;
+       }
+
+       /* 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);
+       if ((sel & 0x1f) != 0x1f) {
+               dev_dbg(&client->dev, "GPIO5 not configured for VID "
+                       "function\n");
+               goto exit;
+       }
+
+       dev_info(&client->dev, "Reading VID from GPIO5\n");
+       res = superio_inb(W83627THF_GPIO5_DR) & sel;
+
+exit:
        superio_exit();
-       up(&data->lock);
        return res;
 }
 
@@ -1269,7 +1317,7 @@ 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) & 0x1f;
+               data->vid = w83627thf_read_gpio5(client) & 0x3f;
        }
 
        /* Read VRM & OVT Config only once */
@@ -1298,11 +1346,28 @@ static void w83627hf_init_client(struct i2c_client *client)
                        break;
        }
 
-       data->pwmenable[0] = 1;
-       data->pwmenable[1] = 1;
-       data->pwmenable[2] = 1;
-
        if(init) {
+               /* Enable temp2 */
+               tmp = w83627hf_read_value(client, W83781D_REG_TEMP2_CONFIG);
+               if (tmp & 0x01) {
+                       dev_warn(&client->dev, "Enabling temp2, readings "
+                                "might not make sense\n");
+                       w83627hf_write_value(client, W83781D_REG_TEMP2_CONFIG,
+                               tmp & 0xfe);
+               }
+
+               /* Enable temp3 */
+               if (type != w83697hf) {
+                       tmp = w83627hf_read_value(client,
+                               W83781D_REG_TEMP3_CONFIG);
+                       if (tmp & 0x01) {
+                               dev_warn(&client->dev, "Enabling temp3, "
+                                        "readings might not make sense\n");
+                               w83627hf_write_value(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) */
@@ -1332,8 +1397,8 @@ static struct w83627hf_data *w83627hf_update_device(struct device *dev)
 
        down(&data->update_lock);
 
-       if ((jiffies - data->last_updated > HZ + HZ / 2) ||
-           (jiffies < data->last_updated) || !data->valid) {
+       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)) ||
@@ -1422,7 +1487,8 @@ static int __init sensors_w83627hf_init(void)
 {
        int addr;
 
-       if (w83627hf_find(&addr)) {
+       if (w83627hf_find(0x2e, &addr)
+        && w83627hf_find(0x4e, &addr)) {
                return -ENODEV;
        }
        normal_isa[0] = addr;