upgrade to fedora-2.6.12-1.1398.FC4 + vserver 2.0.rc7
[linux-2.6.git] / drivers / i2c / chips / w83781d.c
index 3a44fe9..4954e46 100644 (file)
 #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>
 #include <asm/io.h>
 #include "lm75.h"
 
-/* RT Table support #defined so we can take it out if it gets bothersome */
-#define W83781D_RT                     1
-
 /* Addresses to scan */
 static unsigned short normal_i2c[] = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25,
                                        0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
@@ -175,11 +173,6 @@ FAN_TO_REG(long rpm, int div)
                                                : (val)) / 1000, 0, 0xff))
 #define TEMP_FROM_REG(val)             (((val) & 0x80 ? (val)-0x100 : (val)) * 1000)
 
-#define AS99127_TEMP_ADD_TO_REG(val)   (SENSORS_LIMIT((((val) < 0 ? (val)+0x10000*250 \
-                                               : (val)) / 250) << 7, 0, 0xffff))
-#define AS99127_TEMP_ADD_FROM_REG(val) ((((val) & 0x8000 ? (val)-0x10000 : (val)) \
-                                               >> 7) * 250)
-
 #define ALARMS_FROM_REG(val)           (val)
 #define PWM_FROM_REG(val)              (val)
 #define PWM_TO_REG(val)                        (SENSORS_LIMIT((val),0,255))
@@ -262,9 +255,6 @@ struct w83781d_data {
                                   3000-5000 = thermistor beta.
                                   Default = 3435. 
                                   Other Betas unimplemented */
-#ifdef W83781D_RT
-       u8 rt[3][32];           /* Register value */
-#endif
        u8 vrm;
 };
 
@@ -306,9 +296,12 @@ static ssize_t store_in_##reg (struct device *dev, const char *buf, size_t count
        u32 val; \
         \
        val = simple_strtoul(buf, NULL, 10) / 10; \
+        \
+       down(&data->update_lock); \
        data->in_##reg[nr] = IN_TO_REG(val); \
        w83781d_write_value(client, W83781D_REG_IN_##REG(nr), data->in_##reg[nr]); \
         \
+       up(&data->update_lock); \
        return count; \
 }
 store_in_reg(MIN, min);
@@ -373,11 +366,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]));
        w83781d_write_value(client, W83781D_REG_FAN_MIN(nr),
                            data->fan_min[nr - 1]);
 
+       up(&data->update_lock);
        return count;
 }
 
@@ -417,13 +413,8 @@ static ssize_t show_##reg (struct device *dev, char *buf, int nr) \
 { \
        struct w83781d_data *data = w83781d_update_device(dev); \
        if (nr >= 2) {  /* TEMP2 and TEMP3 */ \
-               if (data->type == as99127f) { \
-                       return sprintf(buf,"%ld\n", \
-                               (long)AS99127_TEMP_ADD_FROM_REG(data->reg##_add[nr-2])); \
-               } else { \
-                       return sprintf(buf,"%d\n", \
-                               LM75_TEMP_FROM_REG(data->reg##_add[nr-2])); \
-               } \
+               return sprintf(buf,"%d\n", \
+                       LM75_TEMP_FROM_REG(data->reg##_add[nr-2])); \
        } else {        /* TEMP1 */ \
                return sprintf(buf,"%ld\n", (long)TEMP_FROM_REG(data->reg)); \
        } \
@@ -441,12 +432,10 @@ static ssize_t store_temp_##reg (struct device *dev, const char *buf, size_t cou
         \
        val = simple_strtol(buf, NULL, 10); \
         \
+       down(&data->update_lock); \
+        \
        if (nr >= 2) {  /* TEMP2 and TEMP3 */ \
-               if (data->type == as99127f) \
-                       data->temp_##reg##_add[nr-2] = AS99127_TEMP_ADD_TO_REG(val); \
-               else \
-                       data->temp_##reg##_add[nr-2] = LM75_TEMP_TO_REG(val); \
-                \
+               data->temp_##reg##_add[nr-2] = LM75_TEMP_TO_REG(val); \
                w83781d_write_value(client, W83781D_REG_TEMP_##REG(nr), \
                                data->temp_##reg##_add[nr-2]); \
        } else {        /* TEMP1 */ \
@@ -455,6 +444,7 @@ static ssize_t store_temp_##reg (struct device *dev, const char *buf, size_t cou
                        data->temp_##reg); \
        } \
         \
+       up(&data->update_lock); \
        return count; \
 }
 store_temp_reg(OVER, max);
@@ -567,6 +557,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, data->type);
                w83781d_write_value(client, W83781D_REG_BEEP_INTS1,
@@ -586,6 +578,7 @@ store_beep_reg(struct device *dev, const char *buf, size_t count,
        w83781d_write_value(client, W83781D_REG_BEEP_INTS2,
                            val2 | data->beep_enable << 7);
 
+       up(&data->update_lock);
        return count;
 }
 
@@ -628,13 +621,15 @@ store_fan_div_reg(struct device *dev, const char *buf, size_t count, int nr)
        struct w83781d_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->type);
+       data->fan_div[nr] = DIV_TO_REG(val, data->type);
 
        reg = (w83781d_read_value(client, nr==2 ? W83781D_REG_PIN : W83781D_REG_VID_FANDIV)
               & (nr==0 ? 0xcf : 0x3f))
@@ -653,6 +648,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]));
        w83781d_write_value(client, W83781D_REG_FAN_MIN(nr+1), data->fan_min[nr]);
 
+       up(&data->update_lock);
        return count;
 }
 
@@ -699,9 +695,10 @@ store_pwm_reg(struct device *dev, const char *buf, size_t count, int nr)
 
        val = simple_strtoul(buf, NULL, 10);
 
+       down(&data->update_lock);
        data->pwm[nr - 1] = PWM_TO_REG(val);
        w83781d_write_value(client, W83781D_REG_PWM(nr), data->pwm[nr - 1]);
-
+       up(&data->update_lock);
        return count;
 }
 
@@ -714,6 +711,8 @@ store_pwmenable_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 0:
        case 1:
@@ -729,9 +728,11 @@ store_pwmenable_reg(struct device *dev, const char *buf, size_t count, int nr)
                break;
 
        default:
+               up(&data->update_lock);
                return -EINVAL;
        }
 
+       up(&data->update_lock);
        return count;
 }
 
@@ -793,6 +794,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 = w83781d_read_value(client, W83781D_REG_SCFG1);
@@ -824,6 +827,7 @@ store_sensor_reg(struct device *dev, const char *buf, size_t count, int nr)
                break;
        }
 
+       up(&data->update_lock);
        return count;
 }
 
@@ -847,66 +851,6 @@ do { \
 device_create_file(&client->dev, &dev_attr_temp##offset##_type); \
 } while (0)
 
-#ifdef W83781D_RT
-static ssize_t
-show_rt_reg(struct device *dev, char *buf, int nr)
-{
-       struct w83781d_data *data = w83781d_update_device(dev);
-       int i, j = 0;
-
-       for (i = 0; i < 32; i++) {
-               if (i > 0)
-                       j += sprintf(buf, " %ld", (long) data->rt[nr - 1][i]);
-               else
-                       j += sprintf(buf, "%ld", (long) data->rt[nr - 1][i]);
-       }
-       j += sprintf(buf, "\n");
-
-       return j;
-}
-
-static ssize_t
-store_rt_reg(struct device *dev, const char *buf, size_t count, int nr)
-{
-       struct i2c_client *client = to_i2c_client(dev);
-       struct w83781d_data *data = i2c_get_clientdata(client);
-       u32 val, i;
-
-       for (i = 0; i < count; i++) {
-               val = simple_strtoul(buf + count, NULL, 10);
-
-               /* fixme: no bounds checking 0-255 */
-               data->rt[nr - 1][i] = val & 0xff;
-               w83781d_write_value(client, W83781D_REG_RT_IDX, i);
-               w83781d_write_value(client, W83781D_REG_RT_VAL,
-                                   data->rt[nr - 1][i]);
-       }
-
-       return count;
-}
-
-#define sysfs_rt(offset) \
-static ssize_t show_regs_rt_##offset (struct device *dev, char *buf) \
-{ \
-       return show_rt_reg(dev, buf, offset); \
-} \
-static ssize_t store_regs_rt_##offset (struct device *dev, const char *buf, size_t count) \
-{ \
-    return store_rt_reg(dev, buf, count, offset); \
-} \
-static DEVICE_ATTR(rt##offset, S_IRUGO | S_IWUSR, show_regs_rt_##offset, store_regs_rt_##offset);
-
-sysfs_rt(1);
-sysfs_rt(2);
-sysfs_rt(3);
-
-#define device_create_file_rt(client, offset) \
-do { \
-device_create_file(&client->dev, &dev_attr_rt##offset); \
-} while (0)
-
-#endif                         /* ifdef W83781D_RT */
-
 /* This function is called when:
      * w83781d_driver is inserted (when this module is loaded), for each
        available adapter
@@ -1065,7 +1009,8 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
        }
        
        if (is_isa)
-               if (!request_region(address, W83781D_EXTENT, "w83781d")) {
+               if (!request_region(address, W83781D_EXTENT,
+                                   w83781d_driver.name)) {
                        dev_dbg(&adapter->dev, "Request of region "
                                "0x%x-0x%x for w83781d failed\n", address,
                                address + W83781D_EXTENT - 1);
@@ -1316,13 +1261,6 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
                if (kind != w83783s && kind != w83697hf)
                        device_create_file_sensor(new_client, 3);
        }
-#ifdef W83781D_RT
-       if (kind == w83781d) {
-               device_create_file_rt(new_client, 1);
-               device_create_file_rt(new_client, 2);
-               device_create_file_rt(new_client, 3);
-       }
-#endif
 
        return 0;
 
@@ -1547,39 +1485,29 @@ w83781d_init_client(struct i2c_client *client)
                                break;
                }
        }
-#ifdef W83781D_RT
-/*
-   Fill up the RT Tables.
-   We assume that they are 32 bytes long, in order for temp 1-3.
-   Data sheet documentation is sparse.
-   We also assume that it is only for the 781D although I suspect
-   that the others support it as well....
-*/
 
-       if (init && type == w83781d) {
-               u16 k = 0;
-/*
-    Auto-indexing doesn't seem to work...
-    w83781d_write_value(client,W83781D_REG_RT_IDX,0);
-*/
-               for (i = 0; i < 3; i++) {
-                       int j;
-                       for (j = 0; j < 32; j++) {
-                               w83781d_write_value(client,
-                                                   W83781D_REG_RT_IDX, k++);
-                               data->rt[i][j] =
-                                   w83781d_read_value(client,
-                                                      W83781D_REG_RT_VAL);
-                       }
+       if (init && type != as99127f) {
+               /* Enable temp2 */
+               tmp = w83781d_read_value(client, W83781D_REG_TEMP2_CONFIG);
+               if (tmp & 0x01) {
+                       dev_warn(&client->dev, "Enabling temp2, readings "
+                                "might not make sense\n");
+                       w83781d_write_value(client, W83781D_REG_TEMP2_CONFIG,
+                               tmp & 0xfe);
                }
-       }
-#endif                         /* W83781D_RT */
 
-       if (init) {
+               /* Enable temp3 */
                if (type != w83783s && type != w83697hf) {
-                       w83781d_write_value(client, W83781D_REG_TEMP3_CONFIG,
-                                           0x00);
+                       tmp = w83781d_read_value(client,
+                               W83781D_REG_TEMP3_CONFIG);
+                       if (tmp & 0x01) {
+                               dev_warn(&client->dev, "Enabling temp3, "
+                                        "readings might not make sense\n");
+                               w83781d_write_value(client,
+                                       W83781D_REG_TEMP3_CONFIG, tmp & 0xfe);
+                       }
                }
+
                if (type != w83781d) {
                        /* enable comparator mode for temp2 and temp3 so
                           alarm indication will work correctly */
@@ -1605,9 +1533,8 @@ static struct w83781d_data *w83781d_update_device(struct device *dev)
 
        down(&data->update_lock);
 
-       if (time_after
-           (jiffies - data->last_updated, (unsigned long) (HZ + HZ / 2))
-           || time_before(jiffies, data->last_updated) || !data->valid) {
+       if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
+           || !data->valid) {
                dev_dbg(dev, "Starting device update\n");
 
                for (i = 0; i <= 8; i++) {