diff options
author | Jean Delvare <khali@linux-fr.org> | 2008-07-16 13:30:11 -0400 |
---|---|---|
committer | Jean Delvare <khali@mahadeva.delvare> | 2008-07-16 13:30:11 -0400 |
commit | 063675b15608dfbb8404b3a19546d579bd039d02 (patch) | |
tree | e3d00f1e141ef0e2718983ad27f48ea18ee5c2ac /drivers/hwmon/asb100.c | |
parent | eea54766c6e3f9850affa91061164aeb6bba44b6 (diff) |
hwmon: (asb100) Convert to a new-style i2c driver
The new-style asb100 driver implements the optional detect() callback
to cover the use cases of the legacy driver.
Signed-off-by: Jean Delvare <khali@linux-fr.org>
Diffstat (limited to 'drivers/hwmon/asb100.c')
-rw-r--r-- | drivers/hwmon/asb100.c | 207 |
1 files changed, 83 insertions, 124 deletions
diff --git a/drivers/hwmon/asb100.c b/drivers/hwmon/asb100.c index fe2eea4d799b..8a45a2e6ba8a 100644 --- a/drivers/hwmon/asb100.c +++ b/drivers/hwmon/asb100.c | |||
@@ -176,10 +176,8 @@ static u8 DIV_TO_REG(long val) | |||
176 | data is pointed to by client->data. The structure itself is | 176 | data is pointed to by client->data. The structure itself is |
177 | dynamically allocated, at the same time the client itself is allocated. */ | 177 | dynamically allocated, at the same time the client itself is allocated. */ |
178 | struct asb100_data { | 178 | struct asb100_data { |
179 | struct i2c_client client; | ||
180 | struct device *hwmon_dev; | 179 | struct device *hwmon_dev; |
181 | struct mutex lock; | 180 | struct mutex lock; |
182 | enum chips type; | ||
183 | 181 | ||
184 | struct mutex update_lock; | 182 | struct mutex update_lock; |
185 | unsigned long last_updated; /* In jiffies */ | 183 | unsigned long last_updated; /* In jiffies */ |
@@ -206,18 +204,30 @@ struct asb100_data { | |||
206 | static int asb100_read_value(struct i2c_client *client, u16 reg); | 204 | static int asb100_read_value(struct i2c_client *client, u16 reg); |
207 | static void asb100_write_value(struct i2c_client *client, u16 reg, u16 val); | 205 | static void asb100_write_value(struct i2c_client *client, u16 reg, u16 val); |
208 | 206 | ||
209 | static int asb100_attach_adapter(struct i2c_adapter *adapter); | 207 | static int asb100_probe(struct i2c_client *client, |
210 | static int asb100_detect(struct i2c_adapter *adapter, int address, int kind); | 208 | const struct i2c_device_id *id); |
211 | static int asb100_detach_client(struct i2c_client *client); | 209 | static int asb100_detect(struct i2c_client *client, int kind, |
210 | struct i2c_board_info *info); | ||
211 | static int asb100_remove(struct i2c_client *client); | ||
212 | static struct asb100_data *asb100_update_device(struct device *dev); | 212 | static struct asb100_data *asb100_update_device(struct device *dev); |
213 | static void asb100_init_client(struct i2c_client *client); | 213 | static void asb100_init_client(struct i2c_client *client); |
214 | 214 | ||
215 | static const struct i2c_device_id asb100_id[] = { | ||
216 | { "asb100", asb100 }, | ||
217 | { } | ||
218 | }; | ||
219 | MODULE_DEVICE_TABLE(i2c, asb100_id); | ||
220 | |||
215 | static struct i2c_driver asb100_driver = { | 221 | static struct i2c_driver asb100_driver = { |
222 | .class = I2C_CLASS_HWMON, | ||
216 | .driver = { | 223 | .driver = { |
217 | .name = "asb100", | 224 | .name = "asb100", |
218 | }, | 225 | }, |
219 | .attach_adapter = asb100_attach_adapter, | 226 | .probe = asb100_probe, |
220 | .detach_client = asb100_detach_client, | 227 | .remove = asb100_remove, |
228 | .id_table = asb100_id, | ||
229 | .detect = asb100_detect, | ||
230 | .address_data = &addr_data, | ||
221 | }; | 231 | }; |
222 | 232 | ||
223 | /* 7 Voltages */ | 233 | /* 7 Voltages */ |
@@ -619,35 +629,13 @@ static const struct attribute_group asb100_group = { | |||
619 | .attrs = asb100_attributes, | 629 | .attrs = asb100_attributes, |
620 | }; | 630 | }; |
621 | 631 | ||
622 | /* This function is called when: | 632 | static int asb100_detect_subclients(struct i2c_client *client) |
623 | asb100_driver is inserted (when this module is loaded), for each | ||
624 | available adapter | ||
625 | when a new adapter is inserted (and asb100_driver is still present) | ||
626 | */ | ||
627 | static int asb100_attach_adapter(struct i2c_adapter *adapter) | ||
628 | { | ||
629 | if (!(adapter->class & I2C_CLASS_HWMON)) | ||
630 | return 0; | ||
631 | return i2c_probe(adapter, &addr_data, asb100_detect); | ||
632 | } | ||
633 | |||
634 | static int asb100_detect_subclients(struct i2c_adapter *adapter, int address, | ||
635 | int kind, struct i2c_client *client) | ||
636 | { | 633 | { |
637 | int i, id, err; | 634 | int i, id, err; |
635 | int address = client->addr; | ||
636 | unsigned short sc_addr[2]; | ||
638 | struct asb100_data *data = i2c_get_clientdata(client); | 637 | struct asb100_data *data = i2c_get_clientdata(client); |
639 | 638 | struct i2c_adapter *adapter = client->adapter; | |
640 | data->lm75[0] = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); | ||
641 | if (!(data->lm75[0])) { | ||
642 | err = -ENOMEM; | ||
643 | goto ERROR_SC_0; | ||
644 | } | ||
645 | |||
646 | data->lm75[1] = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); | ||
647 | if (!(data->lm75[1])) { | ||
648 | err = -ENOMEM; | ||
649 | goto ERROR_SC_1; | ||
650 | } | ||
651 | 639 | ||
652 | id = i2c_adapter_id(adapter); | 640 | id = i2c_adapter_id(adapter); |
653 | 641 | ||
@@ -665,37 +653,34 @@ static int asb100_detect_subclients(struct i2c_adapter *adapter, int address, | |||
665 | asb100_write_value(client, ASB100_REG_I2C_SUBADDR, | 653 | asb100_write_value(client, ASB100_REG_I2C_SUBADDR, |
666 | (force_subclients[2] & 0x07) | | 654 | (force_subclients[2] & 0x07) | |
667 | ((force_subclients[3] & 0x07) << 4)); | 655 | ((force_subclients[3] & 0x07) << 4)); |
668 | data->lm75[0]->addr = force_subclients[2]; | 656 | sc_addr[0] = force_subclients[2]; |
669 | data->lm75[1]->addr = force_subclients[3]; | 657 | sc_addr[1] = force_subclients[3]; |
670 | } else { | 658 | } else { |
671 | int val = asb100_read_value(client, ASB100_REG_I2C_SUBADDR); | 659 | int val = asb100_read_value(client, ASB100_REG_I2C_SUBADDR); |
672 | data->lm75[0]->addr = 0x48 + (val & 0x07); | 660 | sc_addr[0] = 0x48 + (val & 0x07); |
673 | data->lm75[1]->addr = 0x48 + ((val >> 4) & 0x07); | 661 | sc_addr[1] = 0x48 + ((val >> 4) & 0x07); |
674 | } | 662 | } |
675 | 663 | ||
676 | if (data->lm75[0]->addr == data->lm75[1]->addr) { | 664 | if (sc_addr[0] == sc_addr[1]) { |
677 | dev_err(&client->dev, "duplicate addresses 0x%x " | 665 | dev_err(&client->dev, "duplicate addresses 0x%x " |
678 | "for subclients\n", data->lm75[0]->addr); | 666 | "for subclients\n", sc_addr[0]); |
679 | err = -ENODEV; | 667 | err = -ENODEV; |
680 | goto ERROR_SC_2; | 668 | goto ERROR_SC_2; |
681 | } | 669 | } |
682 | 670 | ||
683 | for (i = 0; i <= 1; i++) { | 671 | data->lm75[0] = i2c_new_dummy(adapter, sc_addr[0]); |
684 | i2c_set_clientdata(data->lm75[i], NULL); | 672 | if (!data->lm75[0]) { |
685 | data->lm75[i]->adapter = adapter; | ||
686 | data->lm75[i]->driver = &asb100_driver; | ||
687 | strlcpy(data->lm75[i]->name, "asb100 subclient", I2C_NAME_SIZE); | ||
688 | } | ||
689 | |||
690 | if ((err = i2c_attach_client(data->lm75[0]))) { | ||
691 | dev_err(&client->dev, "subclient %d registration " | 673 | dev_err(&client->dev, "subclient %d registration " |
692 | "at address 0x%x failed.\n", i, data->lm75[0]->addr); | 674 | "at address 0x%x failed.\n", 1, sc_addr[0]); |
675 | err = -ENOMEM; | ||
693 | goto ERROR_SC_2; | 676 | goto ERROR_SC_2; |
694 | } | 677 | } |
695 | 678 | ||
696 | if ((err = i2c_attach_client(data->lm75[1]))) { | 679 | data->lm75[1] = i2c_new_dummy(adapter, sc_addr[1]); |
680 | if (!data->lm75[1]) { | ||
697 | dev_err(&client->dev, "subclient %d registration " | 681 | dev_err(&client->dev, "subclient %d registration " |
698 | "at address 0x%x failed.\n", i, data->lm75[1]->addr); | 682 | "at address 0x%x failed.\n", 2, sc_addr[1]); |
683 | err = -ENOMEM; | ||
699 | goto ERROR_SC_3; | 684 | goto ERROR_SC_3; |
700 | } | 685 | } |
701 | 686 | ||
@@ -703,55 +688,31 @@ static int asb100_detect_subclients(struct i2c_adapter *adapter, int address, | |||
703 | 688 | ||
704 | /* Undo inits in case of errors */ | 689 | /* Undo inits in case of errors */ |
705 | ERROR_SC_3: | 690 | ERROR_SC_3: |
706 | i2c_detach_client(data->lm75[0]); | 691 | i2c_unregister_device(data->lm75[0]); |
707 | ERROR_SC_2: | 692 | ERROR_SC_2: |
708 | kfree(data->lm75[1]); | ||
709 | ERROR_SC_1: | ||
710 | kfree(data->lm75[0]); | ||
711 | ERROR_SC_0: | ||
712 | return err; | 693 | return err; |
713 | } | 694 | } |
714 | 695 | ||
715 | static int asb100_detect(struct i2c_adapter *adapter, int address, int kind) | 696 | /* Return 0 if detection is successful, -ENODEV otherwise */ |
697 | static int asb100_detect(struct i2c_client *client, int kind, | ||
698 | struct i2c_board_info *info) | ||
716 | { | 699 | { |
717 | int err; | 700 | struct i2c_adapter *adapter = client->adapter; |
718 | struct i2c_client *client; | ||
719 | struct asb100_data *data; | ||
720 | 701 | ||
721 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { | 702 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { |
722 | pr_debug("asb100.o: detect failed, " | 703 | pr_debug("asb100.o: detect failed, " |
723 | "smbus byte data not supported!\n"); | 704 | "smbus byte data not supported!\n"); |
724 | err = -ENODEV; | 705 | return -ENODEV; |
725 | goto ERROR0; | ||
726 | } | 706 | } |
727 | 707 | ||
728 | /* OK. For now, we presume we have a valid client. We now create the | ||
729 | client structure, even though we cannot fill it completely yet. | ||
730 | But it allows us to access asb100_{read,write}_value. */ | ||
731 | |||
732 | if (!(data = kzalloc(sizeof(struct asb100_data), GFP_KERNEL))) { | ||
733 | pr_debug("asb100.o: detect failed, kzalloc failed!\n"); | ||
734 | err = -ENOMEM; | ||
735 | goto ERROR0; | ||
736 | } | ||
737 | |||
738 | client = &data->client; | ||
739 | mutex_init(&data->lock); | ||
740 | i2c_set_clientdata(client, data); | ||
741 | client->addr = address; | ||
742 | client->adapter = adapter; | ||
743 | client->driver = &asb100_driver; | ||
744 | |||
745 | /* Now, we do the remaining detection. */ | ||
746 | |||
747 | /* The chip may be stuck in some other bank than bank 0. This may | 708 | /* The chip may be stuck in some other bank than bank 0. This may |
748 | make reading other information impossible. Specify a force=... or | 709 | make reading other information impossible. Specify a force=... or |
749 | force_*=... parameter, and the chip will be reset to the right | 710 | force_*=... parameter, and the chip will be reset to the right |
750 | bank. */ | 711 | bank. */ |
751 | if (kind < 0) { | 712 | if (kind < 0) { |
752 | 713 | ||
753 | int val1 = asb100_read_value(client, ASB100_REG_BANK); | 714 | int val1 = i2c_smbus_read_byte_data(client, ASB100_REG_BANK); |
754 | int val2 = asb100_read_value(client, ASB100_REG_CHIPMAN); | 715 | int val2 = i2c_smbus_read_byte_data(client, ASB100_REG_CHIPMAN); |
755 | 716 | ||
756 | /* If we're in bank 0 */ | 717 | /* If we're in bank 0 */ |
757 | if ((!(val1 & 0x07)) && | 718 | if ((!(val1 & 0x07)) && |
@@ -761,48 +722,60 @@ static int asb100_detect(struct i2c_adapter *adapter, int address, int kind) | |||
761 | ((val1 & 0x80) && (val2 != 0x06)))) { | 722 | ((val1 & 0x80) && (val2 != 0x06)))) { |
762 | pr_debug("asb100.o: detect failed, " | 723 | pr_debug("asb100.o: detect failed, " |
763 | "bad chip id 0x%02x!\n", val2); | 724 | "bad chip id 0x%02x!\n", val2); |
764 | err = -ENODEV; | 725 | return -ENODEV; |
765 | goto ERROR1; | ||
766 | } | 726 | } |
767 | 727 | ||
768 | } /* kind < 0 */ | 728 | } /* kind < 0 */ |
769 | 729 | ||
770 | /* We have either had a force parameter, or we have already detected | 730 | /* We have either had a force parameter, or we have already detected |
771 | Winbond. Put it now into bank 0 and Vendor ID High Byte */ | 731 | Winbond. Put it now into bank 0 and Vendor ID High Byte */ |
772 | asb100_write_value(client, ASB100_REG_BANK, | 732 | i2c_smbus_write_byte_data(client, ASB100_REG_BANK, |
773 | (asb100_read_value(client, ASB100_REG_BANK) & 0x78) | 0x80); | 733 | (i2c_smbus_read_byte_data(client, ASB100_REG_BANK) & 0x78) |
734 | | 0x80); | ||
774 | 735 | ||
775 | /* Determine the chip type. */ | 736 | /* Determine the chip type. */ |
776 | if (kind <= 0) { | 737 | if (kind <= 0) { |
777 | int val1 = asb100_read_value(client, ASB100_REG_WCHIPID); | 738 | int val1 = i2c_smbus_read_byte_data(client, ASB100_REG_WCHIPID); |
778 | int val2 = asb100_read_value(client, ASB100_REG_CHIPMAN); | 739 | int val2 = i2c_smbus_read_byte_data(client, ASB100_REG_CHIPMAN); |
779 | 740 | ||
780 | if ((val1 == 0x31) && (val2 == 0x06)) | 741 | if ((val1 == 0x31) && (val2 == 0x06)) |
781 | kind = asb100; | 742 | kind = asb100; |
782 | else { | 743 | else { |
783 | if (kind == 0) | 744 | if (kind == 0) |
784 | dev_warn(&client->dev, "ignoring " | 745 | dev_warn(&adapter->dev, "ignoring " |
785 | "'force' parameter for unknown chip " | 746 | "'force' parameter for unknown chip " |
786 | "at adapter %d, address 0x%02x.\n", | 747 | "at adapter %d, address 0x%02x.\n", |
787 | i2c_adapter_id(adapter), address); | 748 | i2c_adapter_id(adapter), client->addr); |
788 | err = -ENODEV; | 749 | return -ENODEV; |
789 | goto ERROR1; | ||
790 | } | 750 | } |
791 | } | 751 | } |
792 | 752 | ||
793 | /* Fill in remaining client fields and put it into the global list */ | 753 | strlcpy(info->type, "asb100", I2C_NAME_SIZE); |
794 | strlcpy(client->name, "asb100", I2C_NAME_SIZE); | ||
795 | data->type = kind; | ||
796 | mutex_init(&data->update_lock); | ||
797 | 754 | ||
798 | /* Tell the I2C layer a new client has arrived */ | 755 | return 0; |
799 | if ((err = i2c_attach_client(client))) | 756 | } |
800 | goto ERROR1; | 757 | |
758 | static int asb100_probe(struct i2c_client *client, | ||
759 | const struct i2c_device_id *id) | ||
760 | { | ||
761 | int err; | ||
762 | struct asb100_data *data; | ||
763 | |||
764 | data = kzalloc(sizeof(struct asb100_data), GFP_KERNEL); | ||
765 | if (!data) { | ||
766 | pr_debug("asb100.o: probe failed, kzalloc failed!\n"); | ||
767 | err = -ENOMEM; | ||
768 | goto ERROR0; | ||
769 | } | ||
770 | |||
771 | i2c_set_clientdata(client, data); | ||
772 | mutex_init(&data->lock); | ||
773 | mutex_init(&data->update_lock); | ||
801 | 774 | ||
802 | /* Attach secondary lm75 clients */ | 775 | /* Attach secondary lm75 clients */ |
803 | if ((err = asb100_detect_subclients(adapter, address, kind, | 776 | err = asb100_detect_subclients(client); |
804 | client))) | 777 | if (err) |
805 | goto ERROR2; | 778 | goto ERROR1; |
806 | 779 | ||
807 | /* Initialize the chip */ | 780 | /* Initialize the chip */ |
808 | asb100_init_client(client); | 781 | asb100_init_client(client); |
@@ -827,39 +800,25 @@ static int asb100_detect(struct i2c_adapter *adapter, int address, int kind) | |||
827 | ERROR4: | 800 | ERROR4: |
828 | sysfs_remove_group(&client->dev.kobj, &asb100_group); | 801 | sysfs_remove_group(&client->dev.kobj, &asb100_group); |
829 | ERROR3: | 802 | ERROR3: |
830 | i2c_detach_client(data->lm75[1]); | 803 | i2c_unregister_device(data->lm75[1]); |
831 | i2c_detach_client(data->lm75[0]); | 804 | i2c_unregister_device(data->lm75[0]); |
832 | kfree(data->lm75[1]); | ||
833 | kfree(data->lm75[0]); | ||
834 | ERROR2: | ||
835 | i2c_detach_client(client); | ||
836 | ERROR1: | 805 | ERROR1: |
837 | kfree(data); | 806 | kfree(data); |
838 | ERROR0: | 807 | ERROR0: |
839 | return err; | 808 | return err; |
840 | } | 809 | } |
841 | 810 | ||
842 | static int asb100_detach_client(struct i2c_client *client) | 811 | static int asb100_remove(struct i2c_client *client) |
843 | { | 812 | { |
844 | struct asb100_data *data = i2c_get_clientdata(client); | 813 | struct asb100_data *data = i2c_get_clientdata(client); |
845 | int err; | ||
846 | |||
847 | /* main client */ | ||
848 | if (data) { | ||
849 | hwmon_device_unregister(data->hwmon_dev); | ||
850 | sysfs_remove_group(&client->dev.kobj, &asb100_group); | ||
851 | } | ||
852 | 814 | ||
853 | if ((err = i2c_detach_client(client))) | 815 | hwmon_device_unregister(data->hwmon_dev); |
854 | return err; | 816 | sysfs_remove_group(&client->dev.kobj, &asb100_group); |
855 | 817 | ||
856 | /* main client */ | 818 | i2c_unregister_device(data->lm75[1]); |
857 | if (data) | 819 | i2c_unregister_device(data->lm75[0]); |
858 | kfree(data); | ||
859 | 820 | ||
860 | /* subclient */ | 821 | kfree(data); |
861 | else | ||
862 | kfree(client); | ||
863 | 822 | ||
864 | return 0; | 823 | return 0; |
865 | } | 824 | } |