diff options
Diffstat (limited to 'drivers/hwmon/w83l786ng.c')
| -rw-r--r-- | drivers/hwmon/w83l786ng.c | 98 |
1 files changed, 45 insertions, 53 deletions
diff --git a/drivers/hwmon/w83l786ng.c b/drivers/hwmon/w83l786ng.c index 41e22ddb568a..badca769f350 100644 --- a/drivers/hwmon/w83l786ng.c +++ b/drivers/hwmon/w83l786ng.c | |||
| @@ -121,7 +121,6 @@ DIV_TO_REG(long val) | |||
| 121 | } | 121 | } |
| 122 | 122 | ||
| 123 | struct w83l786ng_data { | 123 | struct w83l786ng_data { |
| 124 | struct i2c_client client; | ||
| 125 | struct device *hwmon_dev; | 124 | struct device *hwmon_dev; |
| 126 | struct mutex update_lock; | 125 | struct mutex update_lock; |
| 127 | char valid; /* !=0 if following fields are valid */ | 126 | char valid; /* !=0 if following fields are valid */ |
| @@ -146,18 +145,30 @@ struct w83l786ng_data { | |||
| 146 | u8 tolerance[2]; | 145 | u8 tolerance[2]; |
| 147 | }; | 146 | }; |
| 148 | 147 | ||
| 149 | static int w83l786ng_attach_adapter(struct i2c_adapter *adapter); | 148 | static int w83l786ng_probe(struct i2c_client *client, |
| 150 | static int w83l786ng_detect(struct i2c_adapter *adapter, int address, int kind); | 149 | const struct i2c_device_id *id); |
| 151 | static int w83l786ng_detach_client(struct i2c_client *client); | 150 | static int w83l786ng_detect(struct i2c_client *client, int kind, |
| 151 | struct i2c_board_info *info); | ||
| 152 | static int w83l786ng_remove(struct i2c_client *client); | ||
| 152 | static void w83l786ng_init_client(struct i2c_client *client); | 153 | static void w83l786ng_init_client(struct i2c_client *client); |
| 153 | static struct w83l786ng_data *w83l786ng_update_device(struct device *dev); | 154 | static struct w83l786ng_data *w83l786ng_update_device(struct device *dev); |
| 154 | 155 | ||
| 156 | static const struct i2c_device_id w83l786ng_id[] = { | ||
| 157 | { "w83l786ng", w83l786ng }, | ||
| 158 | { } | ||
| 159 | }; | ||
| 160 | MODULE_DEVICE_TABLE(i2c, w83l786ng_id); | ||
| 161 | |||
| 155 | static struct i2c_driver w83l786ng_driver = { | 162 | static struct i2c_driver w83l786ng_driver = { |
| 163 | .class = I2C_CLASS_HWMON, | ||
| 156 | .driver = { | 164 | .driver = { |
| 157 | .name = "w83l786ng", | 165 | .name = "w83l786ng", |
| 158 | }, | 166 | }, |
| 159 | .attach_adapter = w83l786ng_attach_adapter, | 167 | .probe = w83l786ng_probe, |
| 160 | .detach_client = w83l786ng_detach_client, | 168 | .remove = w83l786ng_remove, |
| 169 | .id_table = w83l786ng_id, | ||
| 170 | .detect = w83l786ng_detect, | ||
| 171 | .address_data = &addr_data, | ||
| 161 | }; | 172 | }; |
| 162 | 173 | ||
| 163 | static u8 | 174 | static u8 |
| @@ -575,42 +586,15 @@ static const struct attribute_group w83l786ng_group = { | |||
| 575 | }; | 586 | }; |
| 576 | 587 | ||
| 577 | static int | 588 | static int |
| 578 | w83l786ng_attach_adapter(struct i2c_adapter *adapter) | 589 | w83l786ng_detect(struct i2c_client *client, int kind, |
| 590 | struct i2c_board_info *info) | ||
| 579 | { | 591 | { |
| 580 | if (!(adapter->class & I2C_CLASS_HWMON)) | 592 | struct i2c_adapter *adapter = client->adapter; |
| 581 | return 0; | ||
| 582 | return i2c_probe(adapter, &addr_data, w83l786ng_detect); | ||
| 583 | } | ||
| 584 | |||
| 585 | static int | ||
| 586 | w83l786ng_detect(struct i2c_adapter *adapter, int address, int kind) | ||
| 587 | { | ||
| 588 | struct i2c_client *client; | ||
| 589 | struct device *dev; | ||
| 590 | struct w83l786ng_data *data; | ||
| 591 | int i, err = 0; | ||
| 592 | u8 reg_tmp; | ||
| 593 | 593 | ||
| 594 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { | 594 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { |
| 595 | goto exit; | 595 | return -ENODEV; |
| 596 | } | ||
| 597 | |||
| 598 | /* OK. For now, we presume we have a valid client. We now create the | ||
| 599 | client structure, even though we cannot fill it completely yet. | ||
| 600 | But it allows us to access w83l786ng_{read,write}_value. */ | ||
| 601 | |||
| 602 | if (!(data = kzalloc(sizeof(struct w83l786ng_data), GFP_KERNEL))) { | ||
| 603 | err = -ENOMEM; | ||
| 604 | goto exit; | ||
| 605 | } | 596 | } |
| 606 | 597 | ||
| 607 | client = &data->client; | ||
| 608 | dev = &client->dev; | ||
| 609 | i2c_set_clientdata(client, data); | ||
| 610 | client->addr = address; | ||
| 611 | client->adapter = adapter; | ||
| 612 | client->driver = &w83l786ng_driver; | ||
| 613 | |||
| 614 | /* | 598 | /* |
| 615 | * Now we do the remaining detection. A negative kind means that | 599 | * Now we do the remaining detection. A negative kind means that |
| 616 | * the driver was loaded with no force parameter (default), so we | 600 | * the driver was loaded with no force parameter (default), so we |
| @@ -627,8 +611,8 @@ w83l786ng_detect(struct i2c_adapter *adapter, int address, int kind) | |||
| 627 | W83L786NG_REG_CONFIG) & 0x80) != 0x00)) { | 611 | W83L786NG_REG_CONFIG) & 0x80) != 0x00)) { |
| 628 | dev_dbg(&adapter->dev, | 612 | dev_dbg(&adapter->dev, |
| 629 | "W83L786NG detection failed at 0x%02x.\n", | 613 | "W83L786NG detection failed at 0x%02x.\n", |
| 630 | address); | 614 | client->addr); |
| 631 | goto exit_free; | 615 | return -ENODEV; |
| 632 | } | 616 | } |
| 633 | } | 617 | } |
| 634 | 618 | ||
| @@ -651,17 +635,31 @@ w83l786ng_detect(struct i2c_adapter *adapter, int address, int kind) | |||
| 651 | dev_info(&adapter->dev, | 635 | dev_info(&adapter->dev, |
| 652 | "Unsupported chip (man_id=0x%04X, " | 636 | "Unsupported chip (man_id=0x%04X, " |
| 653 | "chip_id=0x%02X).\n", man_id, chip_id); | 637 | "chip_id=0x%02X).\n", man_id, chip_id); |
| 654 | goto exit_free; | 638 | return -ENODEV; |
| 655 | } | 639 | } |
| 656 | } | 640 | } |
| 657 | 641 | ||
| 658 | /* Fill in the remaining client fields and put into the global list */ | 642 | strlcpy(info->type, "w83l786ng", I2C_NAME_SIZE); |
| 659 | strlcpy(client->name, "w83l786ng", I2C_NAME_SIZE); | ||
| 660 | mutex_init(&data->update_lock); | ||
| 661 | 643 | ||
| 662 | /* Tell the I2C layer a new client has arrived */ | 644 | return 0; |
| 663 | if ((err = i2c_attach_client(client))) | 645 | } |
| 664 | goto exit_free; | 646 | |
| 647 | static int | ||
| 648 | w83l786ng_probe(struct i2c_client *client, const struct i2c_device_id *id) | ||
| 649 | { | ||
| 650 | struct device *dev = &client->dev; | ||
| 651 | struct w83l786ng_data *data; | ||
| 652 | int i, err = 0; | ||
| 653 | u8 reg_tmp; | ||
| 654 | |||
| 655 | data = kzalloc(sizeof(struct w83l786ng_data), GFP_KERNEL); | ||
| 656 | if (!data) { | ||
| 657 | err = -ENOMEM; | ||
| 658 | goto exit; | ||
| 659 | } | ||
| 660 | |||
| 661 | i2c_set_clientdata(client, data); | ||
| 662 | mutex_init(&data->update_lock); | ||
| 665 | 663 | ||
| 666 | /* Initialize the chip */ | 664 | /* Initialize the chip */ |
| 667 | w83l786ng_init_client(client); | 665 | w83l786ng_init_client(client); |
| @@ -693,25 +691,19 @@ w83l786ng_detect(struct i2c_adapter *adapter, int address, int kind) | |||
| 693 | 691 | ||
| 694 | exit_remove: | 692 | exit_remove: |
| 695 | sysfs_remove_group(&client->dev.kobj, &w83l786ng_group); | 693 | sysfs_remove_group(&client->dev.kobj, &w83l786ng_group); |
| 696 | i2c_detach_client(client); | ||
| 697 | exit_free: | ||
| 698 | kfree(data); | 694 | kfree(data); |
| 699 | exit: | 695 | exit: |
| 700 | return err; | 696 | return err; |
| 701 | } | 697 | } |
| 702 | 698 | ||
| 703 | static int | 699 | static int |
| 704 | w83l786ng_detach_client(struct i2c_client *client) | 700 | w83l786ng_remove(struct i2c_client *client) |
| 705 | { | 701 | { |
| 706 | struct w83l786ng_data *data = i2c_get_clientdata(client); | 702 | struct w83l786ng_data *data = i2c_get_clientdata(client); |
| 707 | int err; | ||
| 708 | 703 | ||
| 709 | hwmon_device_unregister(data->hwmon_dev); | 704 | hwmon_device_unregister(data->hwmon_dev); |
| 710 | sysfs_remove_group(&client->dev.kobj, &w83l786ng_group); | 705 | sysfs_remove_group(&client->dev.kobj, &w83l786ng_group); |
| 711 | 706 | ||
| 712 | if ((err = i2c_detach_client(client))) | ||
| 713 | return err; | ||
| 714 | |||
| 715 | kfree(data); | 707 | kfree(data); |
| 716 | 708 | ||
| 717 | return 0; | 709 | return 0; |
