diff options
Diffstat (limited to 'drivers/hwmon')
-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; |