diff options
author | Jean Delvare <khali@linux-fr.org> | 2008-07-16 13:30:09 -0400 |
---|---|---|
committer | Jean Delvare <khali@mahadeva.delvare> | 2008-07-16 13:30:09 -0400 |
commit | af200f881d2cbf3ba2f4c505fa1ae5cfef36f46a (patch) | |
tree | b8d893b082d81ebcee798d0a2e1cc5436c1461a4 | |
parent | 9c97fb4d255fbf6713ee2d77dd8ed8ae770a7e49 (diff) |
hwmon: (adm1031) Convert to a new-style i2c driver
The new-style adm1031 driver implements the optional detect() callback
to cover the use cases of the legacy driver.
Signed-off-by: Jean Delvare <khali@linux-fr.org>
Cc: Alexandre d'Alton <alex@alexdalton.org>
-rw-r--r-- | drivers/hwmon/adm1031.c | 96 |
1 files changed, 49 insertions, 47 deletions
diff --git a/drivers/hwmon/adm1031.c b/drivers/hwmon/adm1031.c index 2bffcab7dc9f..789441830cd8 100644 --- a/drivers/hwmon/adm1031.c +++ b/drivers/hwmon/adm1031.c | |||
@@ -70,7 +70,6 @@ typedef u8 auto_chan_table_t[8][2]; | |||
70 | 70 | ||
71 | /* Each client has this additional data */ | 71 | /* Each client has this additional data */ |
72 | struct adm1031_data { | 72 | struct adm1031_data { |
73 | struct i2c_client client; | ||
74 | struct device *hwmon_dev; | 73 | struct device *hwmon_dev; |
75 | struct mutex update_lock; | 74 | struct mutex update_lock; |
76 | int chip_type; | 75 | int chip_type; |
@@ -99,19 +98,32 @@ struct adm1031_data { | |||
99 | s8 temp_crit[3]; | 98 | s8 temp_crit[3]; |
100 | }; | 99 | }; |
101 | 100 | ||
102 | static int adm1031_attach_adapter(struct i2c_adapter *adapter); | 101 | static int adm1031_probe(struct i2c_client *client, |
103 | static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind); | 102 | const struct i2c_device_id *id); |
103 | static int adm1031_detect(struct i2c_client *client, int kind, | ||
104 | struct i2c_board_info *info); | ||
104 | static void adm1031_init_client(struct i2c_client *client); | 105 | static void adm1031_init_client(struct i2c_client *client); |
105 | static int adm1031_detach_client(struct i2c_client *client); | 106 | static int adm1031_remove(struct i2c_client *client); |
106 | static struct adm1031_data *adm1031_update_device(struct device *dev); | 107 | static struct adm1031_data *adm1031_update_device(struct device *dev); |
107 | 108 | ||
109 | static const struct i2c_device_id adm1031_id[] = { | ||
110 | { "adm1030", adm1030 }, | ||
111 | { "adm1031", adm1031 }, | ||
112 | { } | ||
113 | }; | ||
114 | MODULE_DEVICE_TABLE(i2c, adm1031_id); | ||
115 | |||
108 | /* This is the driver that will be inserted */ | 116 | /* This is the driver that will be inserted */ |
109 | static struct i2c_driver adm1031_driver = { | 117 | static struct i2c_driver adm1031_driver = { |
118 | .class = I2C_CLASS_HWMON, | ||
110 | .driver = { | 119 | .driver = { |
111 | .name = "adm1031", | 120 | .name = "adm1031", |
112 | }, | 121 | }, |
113 | .attach_adapter = adm1031_attach_adapter, | 122 | .probe = adm1031_probe, |
114 | .detach_client = adm1031_detach_client, | 123 | .remove = adm1031_remove, |
124 | .id_table = adm1031_id, | ||
125 | .detect = adm1031_detect, | ||
126 | .address_data = &addr_data, | ||
115 | }; | 127 | }; |
116 | 128 | ||
117 | static inline u8 adm1031_read_value(struct i2c_client *client, u8 reg) | 129 | static inline u8 adm1031_read_value(struct i2c_client *client, u8 reg) |
@@ -693,13 +705,6 @@ static SENSOR_DEVICE_ATTR(temp3_crit_alarm, S_IRUGO, show_alarm, NULL, 12); | |||
693 | static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_alarm, NULL, 13); | 705 | static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_alarm, NULL, 13); |
694 | static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 14); | 706 | static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 14); |
695 | 707 | ||
696 | static int adm1031_attach_adapter(struct i2c_adapter *adapter) | ||
697 | { | ||
698 | if (!(adapter->class & I2C_CLASS_HWMON)) | ||
699 | return 0; | ||
700 | return i2c_probe(adapter, &addr_data, adm1031_detect); | ||
701 | } | ||
702 | |||
703 | static struct attribute *adm1031_attributes[] = { | 708 | static struct attribute *adm1031_attributes[] = { |
704 | &sensor_dev_attr_fan1_input.dev_attr.attr, | 709 | &sensor_dev_attr_fan1_input.dev_attr.attr, |
705 | &sensor_dev_attr_fan1_div.dev_attr.attr, | 710 | &sensor_dev_attr_fan1_div.dev_attr.attr, |
@@ -770,27 +775,15 @@ static const struct attribute_group adm1031_group_opt = { | |||
770 | .attrs = adm1031_attributes_opt, | 775 | .attrs = adm1031_attributes_opt, |
771 | }; | 776 | }; |
772 | 777 | ||
773 | /* This function is called by i2c_probe */ | 778 | /* Return 0 if detection is successful, -ENODEV otherwise */ |
774 | static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind) | 779 | static int adm1031_detect(struct i2c_client *client, int kind, |
780 | struct i2c_board_info *info) | ||
775 | { | 781 | { |
776 | struct i2c_client *client; | 782 | struct i2c_adapter *adapter = client->adapter; |
777 | struct adm1031_data *data; | ||
778 | int err = 0; | ||
779 | const char *name = ""; | 783 | const char *name = ""; |
780 | 784 | ||
781 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | 785 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) |
782 | goto exit; | 786 | return -ENODEV; |
783 | |||
784 | if (!(data = kzalloc(sizeof(struct adm1031_data), GFP_KERNEL))) { | ||
785 | err = -ENOMEM; | ||
786 | goto exit; | ||
787 | } | ||
788 | |||
789 | client = &data->client; | ||
790 | i2c_set_clientdata(client, data); | ||
791 | client->addr = address; | ||
792 | client->adapter = adapter; | ||
793 | client->driver = &adm1031_driver; | ||
794 | 787 | ||
795 | if (kind < 0) { | 788 | if (kind < 0) { |
796 | int id, co; | 789 | int id, co; |
@@ -798,7 +791,7 @@ static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind) | |||
798 | co = i2c_smbus_read_byte_data(client, 0x3e); | 791 | co = i2c_smbus_read_byte_data(client, 0x3e); |
799 | 792 | ||
800 | if (!((id == 0x31 || id == 0x30) && co == 0x41)) | 793 | if (!((id == 0x31 || id == 0x30) && co == 0x41)) |
801 | goto exit_free; | 794 | return -ENODEV; |
802 | kind = (id == 0x30) ? adm1030 : adm1031; | 795 | kind = (id == 0x30) ? adm1030 : adm1031; |
803 | } | 796 | } |
804 | 797 | ||
@@ -809,28 +802,43 @@ static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind) | |||
809 | * auto fan control helper table. */ | 802 | * auto fan control helper table. */ |
810 | if (kind == adm1030) { | 803 | if (kind == adm1030) { |
811 | name = "adm1030"; | 804 | name = "adm1030"; |
812 | data->chan_select_table = &auto_channel_select_table_adm1030; | ||
813 | } else if (kind == adm1031) { | 805 | } else if (kind == adm1031) { |
814 | name = "adm1031"; | 806 | name = "adm1031"; |
815 | data->chan_select_table = &auto_channel_select_table_adm1031; | ||
816 | } | 807 | } |
817 | data->chip_type = kind; | 808 | strlcpy(info->type, name, I2C_NAME_SIZE); |
818 | 809 | ||
819 | strlcpy(client->name, name, I2C_NAME_SIZE); | 810 | return 0; |
811 | } | ||
812 | |||
813 | static int adm1031_probe(struct i2c_client *client, | ||
814 | const struct i2c_device_id *id) | ||
815 | { | ||
816 | struct adm1031_data *data; | ||
817 | int err; | ||
818 | |||
819 | data = kzalloc(sizeof(struct adm1031_data), GFP_KERNEL); | ||
820 | if (!data) { | ||
821 | err = -ENOMEM; | ||
822 | goto exit; | ||
823 | } | ||
824 | |||
825 | i2c_set_clientdata(client, data); | ||
826 | data->chip_type = id->driver_data; | ||
820 | mutex_init(&data->update_lock); | 827 | mutex_init(&data->update_lock); |
821 | 828 | ||
822 | /* Tell the I2C layer a new client has arrived */ | 829 | if (data->chip_type == adm1030) |
823 | if ((err = i2c_attach_client(client))) | 830 | data->chan_select_table = &auto_channel_select_table_adm1030; |
824 | goto exit_free; | 831 | else |
832 | data->chan_select_table = &auto_channel_select_table_adm1031; | ||
825 | 833 | ||
826 | /* Initialize the ADM1031 chip */ | 834 | /* Initialize the ADM1031 chip */ |
827 | adm1031_init_client(client); | 835 | adm1031_init_client(client); |
828 | 836 | ||
829 | /* Register sysfs hooks */ | 837 | /* Register sysfs hooks */ |
830 | if ((err = sysfs_create_group(&client->dev.kobj, &adm1031_group))) | 838 | if ((err = sysfs_create_group(&client->dev.kobj, &adm1031_group))) |
831 | goto exit_detach; | 839 | goto exit_free; |
832 | 840 | ||
833 | if (kind == adm1031) { | 841 | if (data->chip_type == adm1031) { |
834 | if ((err = sysfs_create_group(&client->dev.kobj, | 842 | if ((err = sysfs_create_group(&client->dev.kobj, |
835 | &adm1031_group_opt))) | 843 | &adm1031_group_opt))) |
836 | goto exit_remove; | 844 | goto exit_remove; |
@@ -847,25 +855,19 @@ static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind) | |||
847 | exit_remove: | 855 | exit_remove: |
848 | sysfs_remove_group(&client->dev.kobj, &adm1031_group); | 856 | sysfs_remove_group(&client->dev.kobj, &adm1031_group); |
849 | sysfs_remove_group(&client->dev.kobj, &adm1031_group_opt); | 857 | sysfs_remove_group(&client->dev.kobj, &adm1031_group_opt); |
850 | exit_detach: | ||
851 | i2c_detach_client(client); | ||
852 | exit_free: | 858 | exit_free: |
853 | kfree(data); | 859 | kfree(data); |
854 | exit: | 860 | exit: |
855 | return err; | 861 | return err; |
856 | } | 862 | } |
857 | 863 | ||
858 | static int adm1031_detach_client(struct i2c_client *client) | 864 | static int adm1031_remove(struct i2c_client *client) |
859 | { | 865 | { |
860 | struct adm1031_data *data = i2c_get_clientdata(client); | 866 | struct adm1031_data *data = i2c_get_clientdata(client); |
861 | int ret; | ||
862 | 867 | ||
863 | hwmon_device_unregister(data->hwmon_dev); | 868 | hwmon_device_unregister(data->hwmon_dev); |
864 | sysfs_remove_group(&client->dev.kobj, &adm1031_group); | 869 | sysfs_remove_group(&client->dev.kobj, &adm1031_group); |
865 | sysfs_remove_group(&client->dev.kobj, &adm1031_group_opt); | 870 | sysfs_remove_group(&client->dev.kobj, &adm1031_group_opt); |
866 | if ((ret = i2c_detach_client(client)) != 0) { | ||
867 | return ret; | ||
868 | } | ||
869 | kfree(data); | 871 | kfree(data); |
870 | return 0; | 872 | return 0; |
871 | } | 873 | } |