hwmon: (w83781d) Use new style driver binding
authorWolfgang Grandegger <wg@grandegger.com>
Fri, 17 Oct 2008 15:51:19 +0000 (17:51 +0200)
committerJean Delvare <khali@mahadeva.delvare>
Fri, 17 Oct 2008 15:51:19 +0000 (17:51 +0200)
This patch modifies the w83781d driver to use new style driver binding.
Substantial code modifications are required to deal with the new
interface, especially legacy device detection.

[JD: largely edited to make the patch smaller and to get the driver
to work again on ISA devices.]

Signed-off-by: Wolfgang Grandegger <wg@grandegger.com>
Signed-off-by: Jean Delvare <khali@linux-fr.org>
drivers/hwmon/w83781d.c

index 50580c8..d4d1b85 100644 (file)
@@ -199,7 +199,7 @@ DIV_TO_REG(long val, enum chips type)
 }
 
 struct w83781d_data {
-       struct i2c_client client;
+       struct i2c_client *client;
        struct device *hwmon_dev;
        struct mutex lock;
        enum chips type;
@@ -241,23 +241,11 @@ struct w83781d_data {
 static struct w83781d_data *w83781d_data_if_isa(void);
 static int w83781d_alias_detect(struct i2c_client *client, u8 chipid);
 
-static int w83781d_attach_adapter(struct i2c_adapter *adapter);
-static int w83781d_detect(struct i2c_adapter *adapter, int address, int kind);
-static int w83781d_detach_client(struct i2c_client *client);
-
 static int w83781d_read_value(struct w83781d_data *data, u16 reg);
 static int w83781d_write_value(struct w83781d_data *data, u16 reg, u16 value);
 static struct w83781d_data *w83781d_update_device(struct device *dev);
 static void w83781d_init_device(struct device *dev);
 
-static struct i2c_driver w83781d_driver = {
-       .driver = {
-               .name = "w83781d",
-       },
-       .attach_adapter = w83781d_attach_adapter,
-       .detach_client = w83781d_detach_client,
-};
-
 /* following are the sysfs callback functions */
 #define show_in_reg(reg) \
 static ssize_t show_##reg (struct device *dev, struct device_attribute *da, \
@@ -819,46 +807,19 @@ static SENSOR_DEVICE_ATTR(temp2_type, S_IRUGO | S_IWUSR,
 static SENSOR_DEVICE_ATTR(temp3_type, S_IRUGO | S_IWUSR,
        show_sensor, store_sensor, 2);
 
-/* This function is called when:
-     * w83781d_driver is inserted (when this module is loaded), for each
-       available adapter
-     * when a new adapter is inserted (and w83781d_driver is still present)
-   We block updates of the ISA device to minimize the risk of concurrent
-   access to the same W83781D chip through different interfaces. */
-static int
-w83781d_attach_adapter(struct i2c_adapter *adapter)
-{
-       struct w83781d_data *data = w83781d_data_if_isa();
-       int err;
-
-       if (!(adapter->class & I2C_CLASS_HWMON))
-               return 0;
-
-       if (data)
-               mutex_lock(&data->update_lock);
-       err = i2c_probe(adapter, &addr_data, w83781d_detect);
-       if (data)
-               mutex_unlock(&data->update_lock);
-       return err;
-}
-
 /* Assumes that adapter is of I2C, not ISA variety.
  * OTHERWISE DON'T CALL THIS
  */
 static int
-w83781d_detect_subclients(struct i2c_adapter *adapter, int address, int kind,
-               struct i2c_client *new_client)
+w83781d_detect_subclients(struct i2c_client *new_client)
 {
        int i, val1 = 0, id;
        int err;
-       const char *client_name = "";
+       int address = new_client->addr;
+       unsigned short sc_addr[2];
+       struct i2c_adapter *adapter = new_client->adapter;
        struct w83781d_data *data = i2c_get_clientdata(new_client);
-
-       data->lm75[0] = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
-       if (!(data->lm75[0])) {
-               err = -ENOMEM;
-               goto ERROR_SC_0;
-       }
+       enum chips kind = data->type;
 
        id = i2c_adapter_id(adapter);
 
@@ -876,55 +837,35 @@ w83781d_detect_subclients(struct i2c_adapter *adapter, int address, int kind,
                w83781d_write_value(data, W83781D_REG_I2C_SUBADDR,
                                (force_subclients[2] & 0x07) |
                                ((force_subclients[3] & 0x07) << 4));
-               data->lm75[0]->addr = force_subclients[2];
+               sc_addr[0] = force_subclients[2];
        } else {
                val1 = w83781d_read_value(data, W83781D_REG_I2C_SUBADDR);
-               data->lm75[0]->addr = 0x48 + (val1 & 0x07);
+               sc_addr[0] = 0x48 + (val1 & 0x07);
        }
 
        if (kind != w83783s) {
-               data->lm75[1] = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
-               if (!(data->lm75[1])) {
-                       err = -ENOMEM;
-                       goto ERROR_SC_1;
-               }
-
                if (force_subclients[0] == id &&
                    force_subclients[1] == address) {
-                       data->lm75[1]->addr = force_subclients[3];
+                       sc_addr[1] = force_subclients[3];
                } else {
-                       data->lm75[1]->addr = 0x48 + ((val1 >> 4) & 0x07);
+                       sc_addr[1] = 0x48 + ((val1 >> 4) & 0x07);
                }
-               if (data->lm75[0]->addr == data->lm75[1]->addr) {
+               if (sc_addr[0] == sc_addr[1]) {
                        dev_err(&new_client->dev,
                               "Duplicate addresses 0x%x for subclients.\n",
-                              data->lm75[0]->addr);
+                              sc_addr[0]);
                        err = -EBUSY;
                        goto ERROR_SC_2;
                }
        }
 
-       if (kind == w83781d)
-               client_name = "w83781d subclient";
-       else if (kind == w83782d)
-               client_name = "w83782d subclient";
-       else if (kind == w83783s)
-               client_name = "w83783s subclient";
-       else if (kind == as99127f)
-               client_name = "as99127f subclient";
-
        for (i = 0; i <= 1; i++) {
-               /* store all data in w83781d */
-               i2c_set_clientdata(data->lm75[i], NULL);
-               data->lm75[i]->adapter = adapter;
-               data->lm75[i]->driver = &w83781d_driver;
-               data->lm75[i]->flags = 0;
-               strlcpy(data->lm75[i]->name, client_name,
-                       I2C_NAME_SIZE);
-               if ((err = i2c_attach_client(data->lm75[i]))) {
+               data->lm75[i] = i2c_new_dummy(adapter, sc_addr[i]);
+               if (!data->lm75[i]) {
                        dev_err(&new_client->dev, "Subclient %d "
                                "registration at address 0x%x "
-                               "failed.\n", i, data->lm75[i]->addr);
+                               "failed.\n", i, sc_addr[i]);
+                       err = -ENOMEM;
                        if (i == 1)
                                goto ERROR_SC_3;
                        goto ERROR_SC_2;
@@ -937,12 +878,9 @@ w83781d_detect_subclients(struct i2c_adapter *adapter, int address, int kind,
 
 /* Undo inits in case of errors */
 ERROR_SC_3:
-       i2c_detach_client(data->lm75[0]);
+       i2c_unregister_device(data->lm75[0]);
 ERROR_SC_2:
-       kfree(data->lm75[1]);
 ERROR_SC_1:
-       kfree(data->lm75[0]);
-ERROR_SC_0:
        return err;
 }
 
@@ -1108,87 +1046,71 @@ w83781d_create_files(struct device *dev, int kind, int is_isa)
        return 0;
 }
 
+/* Return 0 if detection is successful, -ENODEV otherwise */
 static int
-w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
+w83781d_detect(struct i2c_client *client, int kind,
+              struct i2c_board_info *info)
 {
        int val1 = 0, val2;
-       struct i2c_client *client;
-       struct device *dev;
-       struct w83781d_data *data;
-       int err;
+       struct w83781d_data *isa = w83781d_data_if_isa();
+       struct i2c_adapter *adapter = client->adapter;
+       int address = client->addr;
        const char *client_name = "";
        enum vendor { winbond, asus } vendid;
 
-       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
-               err = -EINVAL;
-               goto ERROR1;
-       }
-
-       /* 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 w83781d_{read,write}_value. */
-
-       if (!(data = kzalloc(sizeof(struct w83781d_data), GFP_KERNEL))) {
-               err = -ENOMEM;
-               goto ERROR1;
-       }
-
-       client = &data->client;
-       i2c_set_clientdata(client, data);
-       client->addr = address;
-       mutex_init(&data->lock);
-       client->adapter = adapter;
-       client->driver = &w83781d_driver;
-       dev = &client->dev;
+       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+               return -ENODEV;
 
-       /* Now, we do the remaining detection. */
+       /* We block updates of the ISA device to minimize the risk of
+          concurrent access to the same W83781D chip through different
+          interfaces. */
+       if (isa)
+               mutex_lock(&isa->update_lock);
 
        /* The w8378?d may be stuck in some other bank than bank 0. This may
           make reading other information impossible. Specify a force=... or
           force_*=... parameter, and the Winbond will be reset to the right
           bank. */
        if (kind < 0) {
-               if (w83781d_read_value(data, W83781D_REG_CONFIG) & 0x80) {
+               if (i2c_smbus_read_byte_data
+                   (client, W83781D_REG_CONFIG) & 0x80) {
                        dev_dbg(&adapter->dev, "Detection of w83781d chip "
                                "failed at step 3\n");
-                       err = -ENODEV;
-                       goto ERROR2;
+                       goto err_nodev;
                }
-               val1 = w83781d_read_value(data, W83781D_REG_BANK);
-               val2 = w83781d_read_value(data, W83781D_REG_CHIPMAN);
+               val1 = i2c_smbus_read_byte_data(client, W83781D_REG_BANK);
+               val2 = i2c_smbus_read_byte_data(client, W83781D_REG_CHIPMAN);
                /* Check for Winbond or Asus ID if in bank 0 */
                if ((!(val1 & 0x07)) &&
                    (((!(val1 & 0x80)) && (val2 != 0xa3) && (val2 != 0xc3))
                     || ((val1 & 0x80) && (val2 != 0x5c) && (val2 != 0x12)))) {
                        dev_dbg(&adapter->dev, "Detection of w83781d chip "
                                "failed at step 4\n");
-                       err = -ENODEV;
-                       goto ERROR2;
+                       goto err_nodev;
                }
                /* If Winbond SMBus, check address at 0x48.
                   Asus doesn't support, except for as99127f rev.2 */
                if ((!(val1 & 0x80) && (val2 == 0xa3)) ||
                    ((val1 & 0x80) && (val2 == 0x5c))) {
-                       if (w83781d_read_value
-                           (data, W83781D_REG_I2C_ADDR) != address) {
+                       if (i2c_smbus_read_byte_data
+                           (client, W83781D_REG_I2C_ADDR) != address) {
                                dev_dbg(&adapter->dev, "Detection of w83781d "
                                        "chip failed at step 5\n");
-                               err = -ENODEV;
-                               goto ERROR2;
+                               goto err_nodev;
                        }
                }
        }
 
        /* We have either had a force parameter, or we have already detected the
           Winbond. Put it now into bank 0 and Vendor ID High Byte */
-       w83781d_write_value(data, W83781D_REG_BANK,
-                           (w83781d_read_value(data, W83781D_REG_BANK)
-                            & 0x78) | 0x80);
+       i2c_smbus_write_byte_data(client, W83781D_REG_BANK,
+               (i2c_smbus_read_byte_data(client, W83781D_REG_BANK)
+                & 0x78) | 0x80);
 
        /* Determine the chip type. */
        if (kind <= 0) {
                /* get vendor ID */
-               val2 = w83781d_read_value(data, W83781D_REG_CHIPMAN);
+               val2 = i2c_smbus_read_byte_data(client, W83781D_REG_CHIPMAN);
                if (val2 == 0x5c)
                        vendid = winbond;
                else if (val2 == 0x12)
@@ -1196,11 +1118,10 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
                else {
                        dev_dbg(&adapter->dev, "w83781d chip vendor is "
                                "neither Winbond nor Asus\n");
-                       err = -ENODEV;
-                       goto ERROR2;
+                       goto err_nodev;
                }
 
-               val1 = w83781d_read_value(data, W83781D_REG_WCHIPID);
+               val1 = i2c_smbus_read_byte_data(client, W83781D_REG_WCHIPID);
                if ((val1 == 0x10 || val1 == 0x11) && vendid == winbond)
                        kind = w83781d;
                else if (val1 == 0x30 && vendid == winbond)
@@ -1214,19 +1135,20 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
                                dev_warn(&adapter->dev, "Ignoring 'force' "
                                         "parameter for unknown chip at "
                                         "address 0x%02x\n", address);
-                       err = -EINVAL;
-                       goto ERROR2;
+                       goto err_nodev;
                }
 
                if ((kind == w83781d || kind == w83782d)
                 && w83781d_alias_detect(client, val1)) {
                        dev_dbg(&adapter->dev, "Device at 0x%02x appears to "
                                "be the same as ISA device\n", address);
-                       err = -ENODEV;
-                       goto ERROR2;
+                       goto err_nodev;
                }
        }
 
+       if (isa)
+               mutex_unlock(&isa->update_lock);
+
        if (kind == w83781d) {
                client_name = "w83781d";
        } else if (kind == w83782d) {
@@ -1237,24 +1159,46 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
                client_name = "as99127f";
        }
 
-       /* Fill in the remaining client fields and put into the global list */
-       strlcpy(client->name, client_name, I2C_NAME_SIZE);
-       data->type = kind;
+       strlcpy(info->type, client_name, I2C_NAME_SIZE);
 
-       /* Tell the I2C layer a new client has arrived */
-       if ((err = i2c_attach_client(client)))
-               goto ERROR2;
+       return 0;
+
+ err_nodev:
+       if (isa)
+               mutex_unlock(&isa->update_lock);
+       return -ENODEV;
+}
+
+static int
+w83781d_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+       struct device *dev = &client->dev;
+       struct w83781d_data *data;
+       int err;
+
+       data = kzalloc(sizeof(struct w83781d_data), GFP_KERNEL);
+       if (!data) {
+               err = -ENOMEM;
+               goto ERROR1;
+       }
+
+       i2c_set_clientdata(client, data);
+       mutex_init(&data->lock);
+       mutex_init(&data->update_lock);
+
+       data->type = id->driver_data;
+       data->client = client;
 
        /* attach secondary i2c lm75-like clients */
-       if ((err = w83781d_detect_subclients(adapter, address,
-                       kind, client)))
+       err = w83781d_detect_subclients(client);
+       if (err)
                goto ERROR3;
 
        /* Initialize the chip */
        w83781d_init_device(dev);
 
        /* Register sysfs hooks */
-       err = w83781d_create_files(dev, kind, 0);
+       err = w83781d_create_files(dev, data->type, 0);
        if (err)
                goto ERROR4;
 
@@ -1270,45 +1214,35 @@ ERROR4:
        sysfs_remove_group(&dev->kobj, &w83781d_group);
        sysfs_remove_group(&dev->kobj, &w83781d_group_opt);
 
-       if (data->lm75[1]) {
-               i2c_detach_client(data->lm75[1]);
-               kfree(data->lm75[1]);
-       }
-       if (data->lm75[0]) {
-               i2c_detach_client(data->lm75[0]);
-               kfree(data->lm75[0]);
-       }
+       if (data->lm75[0])
+               i2c_unregister_device(data->lm75[0]);
+       if (data->lm75[1])
+               i2c_unregister_device(data->lm75[1]);
 ERROR3:
-       i2c_detach_client(client);
-ERROR2:
+       i2c_set_clientdata(client, NULL);
        kfree(data);
 ERROR1:
        return err;
 }
 
 static int
-w83781d_detach_client(struct i2c_client *client)
+w83781d_remove(struct i2c_client *client)
 {
        struct w83781d_data *data = i2c_get_clientdata(client);
-       int err;
+       struct device *dev = &client->dev;
 
-       /* main client */
-       if (data) {
-               hwmon_device_unregister(data->hwmon_dev);
-               sysfs_remove_group(&client->dev.kobj, &w83781d_group);
-               sysfs_remove_group(&client->dev.kobj, &w83781d_group_opt);
-       }
+       hwmon_device_unregister(data->hwmon_dev);
 
-       if ((err = i2c_detach_client(client)))
-               return err;
+       sysfs_remove_group(&dev->kobj, &w83781d_group);
+       sysfs_remove_group(&dev->kobj, &w83781d_group_opt);
 
-       /* main client */
-       if (data)
-               kfree(data);
+       if (data->lm75[0])
+               i2c_unregister_device(data->lm75[0]);
+       if (data->lm75[1])
+               i2c_unregister_device(data->lm75[1]);
 
-       /* subclient */
-       else
-               kfree(client);
+       i2c_set_clientdata(client, NULL);
+       kfree(data);
 
        return 0;
 }
@@ -1316,7 +1250,7 @@ w83781d_detach_client(struct i2c_client *client)
 static int
 w83781d_read_value_i2c(struct w83781d_data *data, u16 reg)
 {
-       struct i2c_client *client = &data->client;
+       struct i2c_client *client = data->client;
        int res, bank;
        struct i2c_client *cl;
 
@@ -1356,7 +1290,7 @@ w83781d_read_value_i2c(struct w83781d_data *data, u16 reg)
 static int
 w83781d_write_value_i2c(struct w83781d_data *data, u16 reg, u16 value)
 {
-       struct i2c_client *client = &data->client;
+       struct i2c_client *client = data->client;
        int bank;
        struct i2c_client *cl;
 
@@ -1493,7 +1427,7 @@ w83781d_init_device(struct device *dev)
 static struct w83781d_data *w83781d_update_device(struct device *dev)
 {
        struct w83781d_data *data = dev_get_drvdata(dev);
-       struct i2c_client *client = &data->client;
+       struct i2c_client *client = data->client;
        int i;
 
        mutex_lock(&data->update_lock);
@@ -1606,6 +1540,30 @@ static struct w83781d_data *w83781d_update_device(struct device *dev)
        return data;
 }
 
+static const struct i2c_device_id w83781d_ids[] = {
+       { "w83781d", w83781d, },
+       { "w83782d", w83782d, },
+       { "w83783s", w83783s, },
+       { "as99127f", as99127f },
+       { /* LIST END */ }
+};
+MODULE_DEVICE_TABLE(i2c, w83781d_ids);
+
+static struct i2c_driver w83781d_driver = {
+       .class          = I2C_CLASS_HWMON,
+       .driver = {
+               .name = "w83781d",
+       },
+       .probe          = w83781d_probe,
+       .remove         = w83781d_remove,
+       .id_table       = w83781d_ids,
+       .detect         = w83781d_detect,
+       .address_data   = &addr_data,
+};
+
+/*
+ * ISA related code
+ */
 #ifdef CONFIG_ISA
 
 /* ISA device, if found */
@@ -1631,13 +1589,12 @@ static struct w83781d_data *w83781d_data_if_isa(void)
 /* Returns 1 if the I2C chip appears to be an alias of the ISA chip */
 static int w83781d_alias_detect(struct i2c_client *client, u8 chipid)
 {
-       struct w83781d_data *i2c, *isa;
+       struct w83781d_data *isa;
        int i;
 
        if (!pdev)      /* No ISA chip */
                return 0;
 
-       i2c = i2c_get_clientdata(client);
        isa = platform_get_drvdata(pdev);
 
        if (w83781d_read_value(isa, W83781D_REG_I2C_ADDR) != client->addr)
@@ -1648,14 +1605,16 @@ static int w83781d_alias_detect(struct i2c_client *client, u8 chipid)
        /* We compare all the limit registers, the config register and the
         * interrupt mask registers */
        for (i = 0x2b; i <= 0x3d; i++) {
-               if (w83781d_read_value(isa, i) != w83781d_read_value(i2c, i))
+               if (w83781d_read_value(isa, i) !=
+                   i2c_smbus_read_byte_data(client, i))
                        return 0;
        }
        if (w83781d_read_value(isa, W83781D_REG_CONFIG) !=
-           w83781d_read_value(i2c, W83781D_REG_CONFIG))
+           i2c_smbus_read_byte_data(client, W83781D_REG_CONFIG))
                return 0;
        for (i = 0x43; i <= 0x46; i++) {
-               if (w83781d_read_value(isa, i) != w83781d_read_value(i2c, i))
+               if (w83781d_read_value(isa, i) !=
+                   i2c_smbus_read_byte_data(client, i))
                        return 0;
        }
 
@@ -1734,11 +1693,11 @@ w83781d_write_value_isa(struct w83781d_data *data, u16 reg, u16 value)
 static int
 w83781d_read_value(struct w83781d_data *data, u16 reg)
 {
-       struct i2c_client *client = &data->client;
+       struct i2c_client *client = data->client;
        int res;
 
        mutex_lock(&data->lock);
-       if (client->driver)
+       if (client)
                res = w83781d_read_value_i2c(data, reg);
        else
                res = w83781d_read_value_isa(data, reg);
@@ -1749,10 +1708,10 @@ w83781d_read_value(struct w83781d_data *data, u16 reg)
 static int
 w83781d_write_value(struct w83781d_data *data, u16 reg, u16 value)
 {
-       struct i2c_client *client = &data->client;
+       struct i2c_client *client = data->client;
 
        mutex_lock(&data->lock);
-       if (client->driver)
+       if (client)
                w83781d_write_value_i2c(data, reg, value);
        else
                w83781d_write_value_isa(data, reg, value);