linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / drivers / i2c / chips / ds1621.c
index 3aa7298..bb1fefb 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 "lm75.h"
 
 /* Addresses to scan */
-static unsigned short normal_i2c[] = { I2C_CLIENT_END };
-static unsigned short normal_i2c_range[] = { 0x48, 0x4f, I2C_CLIENT_END };
+static unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, 0x4c,
+                                       0x4d, 0x4e, 0x4f, I2C_CLIENT_END };
 static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
-static unsigned int normal_isa_range[] = { I2C_CLIENT_ISA_END };
 
 /* Insmod parameters */
 SENSORS_INSMOD_1(ds1621);
@@ -43,9 +43,8 @@ MODULE_PARM_DESC(polarity, "Output's polarity: 0 = active high, 1 = active low")
 /* Many DS1621 constants specified below */
 /* Config register used for detection         */
 /*  7    6    5    4    3    2    1    0      */
-/* |Done|THF |TLF |NVB | 1  | 0  |POL |1SHOT| */
-#define DS1621_REG_CONFIG_MASK         0x0C
-#define DS1621_REG_CONFIG_VAL          0x08
+/* |Done|THF |TLF |NVB | X  | X  |POL |1SHOT| */
+#define DS1621_REG_CONFIG_NVB          0x10
 #define DS1621_REG_CONFIG_POLARITY     0x02
 #define DS1621_REG_CONFIG_1SHOT                0x01
 #define DS1621_REG_CONFIG_DONE         0x80
@@ -56,6 +55,7 @@ MODULE_PARM_DESC(polarity, "Output's polarity: 0 = active high, 1 = active low")
 #define DS1621_REG_TEMP_MAX            0xA2 /* word, RW */
 #define DS1621_REG_CONF                        0xAC /* byte, RW */
 #define DS1621_COM_START               0xEE /* no data */
+#define DS1621_COM_STOP                        0x22 /* no data */
 
 /* The DS1621 configuration register */
 #define DS1621_ALARM_TEMP_HIGH         0x40
@@ -96,8 +96,6 @@ static struct i2c_driver ds1621_driver = {
        .detach_client  = ds1621_detach_client,
 };
 
-static int ds1621_id = 0;
-
 /* All registers are word-sized, except for the configuration register.
    DS1621 uses a high-byte first convention, which is exactly opposite to
    the usual practice. */
@@ -155,8 +153,12 @@ static ssize_t set_temp_##suffix(struct device *dev, const char *buf,      \
 {                                                                      \
        struct i2c_client *client = to_i2c_client(dev);                 \
        struct ds1621_data *data = ds1621_update_client(dev);           \
-       data->value = LM75_TEMP_TO_REG(simple_strtoul(buf, NULL, 10));  \
+       u16 val = LM75_TEMP_TO_REG(simple_strtoul(buf, NULL, 10));      \
+                                                                       \
+       down(&data->update_lock);                                       \
+       data->value = val;                                              \
        ds1621_write_value(client, reg, data->value);                   \
+       up(&data->update_lock);                                         \
        return count;                                                   \
 }
 
@@ -213,9 +215,13 @@ int ds1621_detect(struct i2c_adapter *adapter, int address,
 
        /* Now, we do the remaining detection. It is lousy. */
        if (kind < 0) {
+               /* The NVB bit should be low if no EEPROM write has been 
+                  requested during the latest 10ms, which is highly 
+                  improbable in our case. */
                conf = ds1621_read_value(new_client, DS1621_REG_CONF);
-               if ((conf & DS1621_REG_CONFIG_MASK) != DS1621_REG_CONFIG_VAL)
+               if (conf & DS1621_REG_CONFIG_NVB)
                        goto exit_free;
+               /* The 7 lowest bits of a temperature should always be 0. */
                temp = ds1621_read_value(new_client, DS1621_REG_TEMP);
                if (temp & 0x007f)
                        goto exit_free;
@@ -233,8 +239,6 @@ int ds1621_detect(struct i2c_adapter *adapter, int address,
 
        /* Fill in remaining client fields and put it into the global list */
        strlcpy(new_client->name, "ds1621", I2C_NAME_SIZE);
-
-       new_client->id = ds1621_id++;
        data->valid = 0;
        init_MUTEX(&data->update_lock);
 
@@ -285,8 +289,8 @@ static struct ds1621_data *ds1621_update_client(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) {
 
                dev_dbg(&client->dev, "Starting ds1621 update\n");