ar9170: remove get_tx_stats() mac80211 op
[safe/jmp/linux-2.6] / drivers / hwmon / ds1621.c
index 5a861f9..53f88f5 100644 (file)
@@ -34,7 +34,7 @@
 #include "lm75.h"
 
 /* Addresses to scan */
-static unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, 0x4c,
+static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, 0x4c,
                                        0x4d, 0x4e, 0x4f, I2C_CLIENT_END };
 
 /* Insmod parameters */
@@ -72,8 +72,7 @@ static const u8 DS1621_REG_TEMP[3] = {
 
 /* Each client has this additional data */
 struct ds1621_data {
-       struct i2c_client client;
-       struct class_device *class_dev;
+       struct device *hwmon_dev;
        struct mutex update_lock;
        char valid;                     /* !=0 if following fields are valid */
        unsigned long last_updated;     /* In jiffies */
@@ -82,60 +81,84 @@ struct ds1621_data {
        u8 conf;                        /* Register encoding, combined */
 };
 
-static int ds1621_attach_adapter(struct i2c_adapter *adapter);
-static int ds1621_detect(struct i2c_adapter *adapter, int address,
-                        int kind);
-static void ds1621_init_client(struct i2c_client *client);
-static int ds1621_detach_client(struct i2c_client *client);
-static struct ds1621_data *ds1621_update_client(struct device *dev);
-
-/* This is the driver that will be inserted */
-static struct i2c_driver ds1621_driver = {
-       .driver = {
-               .name   = "ds1621",
-       },
-       .id             = I2C_DRIVERID_DS1621,
-       .attach_adapter = ds1621_attach_adapter,
-       .detach_client  = ds1621_detach_client,
-};
-
-/* All registers are word-sized, except for the configuration register.
+/* Temperature registers are word-sized.
    DS1621 uses a high-byte first convention, which is exactly opposite to
    the SMBus standard. */
-static int ds1621_read_value(struct i2c_client *client, u8 reg)
+static int ds1621_read_temp(struct i2c_client *client, u8 reg)
 {
-       if (reg == DS1621_REG_CONF)
-               return i2c_smbus_read_byte_data(client, reg);
-       else
-               return swab16(i2c_smbus_read_word_data(client, reg));
+       int ret;
+
+       ret = i2c_smbus_read_word_data(client, reg);
+       if (ret < 0)
+               return ret;
+       return swab16(ret);
 }
 
-static int ds1621_write_value(struct i2c_client *client, u8 reg, u16 value)
+static int ds1621_write_temp(struct i2c_client *client, u8 reg, u16 value)
 {
-       if (reg == DS1621_REG_CONF)
-               return i2c_smbus_write_byte_data(client, reg, value);
-       else
-               return i2c_smbus_write_word_data(client, reg, swab16(value));
+       return i2c_smbus_write_word_data(client, reg, swab16(value));
 }
 
 static void ds1621_init_client(struct i2c_client *client)
 {
-       int reg = ds1621_read_value(client, DS1621_REG_CONF);
+       u8 conf, new_conf;
+
+       new_conf = conf = i2c_smbus_read_byte_data(client, DS1621_REG_CONF);
        /* switch to continuous conversion mode */
-       reg &= ~ DS1621_REG_CONFIG_1SHOT;
+       new_conf &= ~DS1621_REG_CONFIG_1SHOT;
 
        /* setup output polarity */
        if (polarity == 0)
-               reg &= ~DS1621_REG_CONFIG_POLARITY;
+               new_conf &= ~DS1621_REG_CONFIG_POLARITY;
        else if (polarity == 1)
-               reg |= DS1621_REG_CONFIG_POLARITY;
+               new_conf |= DS1621_REG_CONFIG_POLARITY;
        
-       ds1621_write_value(client, DS1621_REG_CONF, reg);
+       if (conf != new_conf)
+               i2c_smbus_write_byte_data(client, DS1621_REG_CONF, new_conf);
        
        /* start conversion */
        i2c_smbus_write_byte(client, DS1621_COM_START);
 }
 
+static struct ds1621_data *ds1621_update_client(struct device *dev)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct ds1621_data *data = i2c_get_clientdata(client);
+       u8 new_conf;
+
+       mutex_lock(&data->update_lock);
+
+       if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
+           || !data->valid) {
+               int i;
+
+               dev_dbg(&client->dev, "Starting ds1621 update\n");
+
+               data->conf = i2c_smbus_read_byte_data(client, DS1621_REG_CONF);
+
+               for (i = 0; i < ARRAY_SIZE(data->temp); i++)
+                       data->temp[i] = ds1621_read_temp(client,
+                                                        DS1621_REG_TEMP[i]);
+
+               /* reset alarms if necessary */
+               new_conf = data->conf;
+               if (data->temp[0] > data->temp[1])      /* input > min */
+                       new_conf &= ~DS1621_ALARM_TEMP_LOW;
+               if (data->temp[0] < data->temp[2])      /* input < max */
+                       new_conf &= ~DS1621_ALARM_TEMP_HIGH;
+               if (data->conf != new_conf)
+                       i2c_smbus_write_byte_data(client, DS1621_REG_CONF,
+                                                 new_conf);
+
+               data->last_updated = jiffies;
+               data->valid = 1;
+       }
+
+       mutex_unlock(&data->update_lock);
+
+       return data;
+}
+
 static ssize_t show_temp(struct device *dev, struct device_attribute *da,
                         char *buf)
 {
@@ -150,13 +173,13 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *da,
 {
        struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
        struct i2c_client *client = to_i2c_client(dev);
-       struct ds1621_data *data = ds1621_update_client(dev);
+       struct ds1621_data *data = i2c_get_clientdata(client);
        u16 val = LM75_TEMP_TO_REG(simple_strtol(buf, NULL, 10));
 
        mutex_lock(&data->update_lock);
        data->temp[attr->index] = val;
-       ds1621_write_value(client, DS1621_REG_TEMP[attr->index],
-                          data->temp[attr->index]);
+       ds1621_write_temp(client, DS1621_REG_TEMP[attr->index],
+                         data->temp[attr->index]);
        mutex_unlock(&data->update_lock);
        return count;
 }
@@ -200,75 +223,66 @@ static const struct attribute_group ds1621_group = {
 };
 
 
-static int ds1621_attach_adapter(struct i2c_adapter *adapter)
-{
-       if (!(adapter->class & I2C_CLASS_HWMON))
-               return 0;
-       return i2c_probe(adapter, &addr_data, ds1621_detect);
-}
-
-/* This function is called by i2c_probe */
-static int ds1621_detect(struct i2c_adapter *adapter, int address,
-                        int kind)
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int ds1621_detect(struct i2c_client *client, int kind,
+                        struct i2c_board_info *info)
 {
+       struct i2c_adapter *adapter = client->adapter;
        int conf, temp;
-       struct i2c_client *client;
-       struct ds1621_data *data;
-       int i, err = 0;
+       int i;
 
        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA 
                                     | I2C_FUNC_SMBUS_WORD_DATA 
                                     | I2C_FUNC_SMBUS_WRITE_BYTE))
-               goto exit;
-
-       /* OK. For now, we presume we have a valid client. We now create the
-          client structure, even though we cannot fill it completely yet.
-          But it allows us to access ds1621_{read,write}_value. */
-       if (!(data = kzalloc(sizeof(struct ds1621_data), GFP_KERNEL))) {
-               err = -ENOMEM;
-               goto exit;
-       }
-       
-       client = &data->client;
-       i2c_set_clientdata(client, data);
-       client->addr = address;
-       client->adapter = adapter;
-       client->driver = &ds1621_driver;
+               return -ENODEV;
 
        /* 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(client, DS1621_REG_CONF);
-               if (conf & DS1621_REG_CONFIG_NVB)
-                       goto exit_free;
+               conf = i2c_smbus_read_byte_data(client, DS1621_REG_CONF);
+               if (conf < 0 || conf & DS1621_REG_CONFIG_NVB)
+                       return -ENODEV;
                /* The 7 lowest bits of a temperature should always be 0. */
-               for (i = 0; i < ARRAY_SIZE(data->temp); i++) {
-                       temp = ds1621_read_value(client, DS1621_REG_TEMP[i]);
-                       if (temp & 0x007f)
-                               goto exit_free;
+               for (i = 0; i < ARRAY_SIZE(DS1621_REG_TEMP); i++) {
+                       temp = i2c_smbus_read_word_data(client,
+                                                       DS1621_REG_TEMP[i]);
+                       if (temp < 0 || (temp & 0x7f00))
+                               return -ENODEV;
                }
        }
 
-       /* Fill in remaining client fields and put it into the global list */
-       strlcpy(client->name, "ds1621", I2C_NAME_SIZE);
-       mutex_init(&data->update_lock);
+       strlcpy(info->type, "ds1621", I2C_NAME_SIZE);
 
-       /* Tell the I2C layer a new client has arrived */
-       if ((err = i2c_attach_client(client)))
-               goto exit_free;
+       return 0;
+}
+
+static int ds1621_probe(struct i2c_client *client,
+                       const struct i2c_device_id *id)
+{
+       struct ds1621_data *data;
+       int err;
+
+       data = kzalloc(sizeof(struct ds1621_data), GFP_KERNEL);
+       if (!data) {
+               err = -ENOMEM;
+               goto exit;
+       }
+
+       i2c_set_clientdata(client, data);
+       mutex_init(&data->update_lock);
 
        /* Initialize the DS1621 chip */
        ds1621_init_client(client);
 
        /* Register sysfs hooks */
        if ((err = sysfs_create_group(&client->dev.kobj, &ds1621_group)))
-               goto exit_detach;
+               goto exit_free;
 
-       data->class_dev = hwmon_device_register(&client->dev);
-       if (IS_ERR(data->class_dev)) {
-               err = PTR_ERR(data->class_dev);
+       data->hwmon_dev = hwmon_device_register(&client->dev);
+       if (IS_ERR(data->hwmon_dev)) {
+               err = PTR_ERR(data->hwmon_dev);
                goto exit_remove_files;
        }
 
@@ -276,69 +290,43 @@ static int ds1621_detect(struct i2c_adapter *adapter, int address,
 
       exit_remove_files:
        sysfs_remove_group(&client->dev.kobj, &ds1621_group);
-      exit_detach:
-       i2c_detach_client(client);
       exit_free:
        kfree(data);
       exit:
        return err;
 }
 
-static int ds1621_detach_client(struct i2c_client *client)
+static int ds1621_remove(struct i2c_client *client)
 {
        struct ds1621_data *data = i2c_get_clientdata(client);
-       int err;
 
-       hwmon_device_unregister(data->class_dev);
+       hwmon_device_unregister(data->hwmon_dev);
        sysfs_remove_group(&client->dev.kobj, &ds1621_group);
 
-       if ((err = i2c_detach_client(client)))
-               return err;
-
        kfree(data);
 
        return 0;
 }
 
+static const struct i2c_device_id ds1621_id[] = {
+       { "ds1621", ds1621 },
+       { "ds1625", ds1621 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, ds1621_id);
 
-static struct ds1621_data *ds1621_update_client(struct device *dev)
-{
-       struct i2c_client *client = to_i2c_client(dev);
-       struct ds1621_data *data = i2c_get_clientdata(client);
-       u8 new_conf;
-
-       mutex_lock(&data->update_lock);
-
-       if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
-           || !data->valid) {
-               int i;
-
-               dev_dbg(&client->dev, "Starting ds1621 update\n");
-
-               data->conf = ds1621_read_value(client, DS1621_REG_CONF);
-
-               for (i = 0; i < ARRAY_SIZE(data->temp); i++)
-                       data->temp[i] = ds1621_read_value(client,
-                                                         DS1621_REG_TEMP[i]);
-
-               /* reset alarms if necessary */
-               new_conf = data->conf;
-               if (data->temp[0] > data->temp[1])      /* input > min */
-                       new_conf &= ~DS1621_ALARM_TEMP_LOW;
-               if (data->temp[0] < data->temp[2])      /* input < max */
-                       new_conf &= ~DS1621_ALARM_TEMP_HIGH;
-               if (data->conf != new_conf)
-                       ds1621_write_value(client, DS1621_REG_CONF,
-                                          new_conf);
-
-               data->last_updated = jiffies;
-               data->valid = 1;
-       }
-
-       mutex_unlock(&data->update_lock);
-
-       return data;
-}
+/* This is the driver that will be inserted */
+static struct i2c_driver ds1621_driver = {
+       .class          = I2C_CLASS_HWMON,
+       .driver = {
+               .name   = "ds1621",
+       },
+       .probe          = ds1621_probe,
+       .remove         = ds1621_remove,
+       .id_table       = ds1621_id,
+       .detect         = ds1621_detect,
+       .address_data   = &addr_data,
+};
 
 static int __init ds1621_init(void)
 {