diff options
author | Jean Delvare <khali@linux-fr.org> | 2008-07-16 13:30:07 -0400 |
---|---|---|
committer | Jean Delvare <khali@mahadeva.delvare> | 2008-07-16 13:30:07 -0400 |
commit | bd8d421f7ca9f8da3d820d28379d796500f69529 (patch) | |
tree | 705ec8b1dad4cbc4e20e6ca861f8db12a37143db /drivers/i2c/chips/max6875.c | |
parent | 3d63430a26b91fe3daee0dd933f899c225e66daa (diff) |
i2c: Convert the max6875 driver to a new-style i2c driver
The new-style max6875 driver implements the optional detect() callback
to cover the use cases of the legacy driver. I'm curious if anyone
really needs this though, so it might be removed in the feature.
Signed-off-by: Jean Delvare <khali@linux-fr.org>
Diffstat (limited to 'drivers/i2c/chips/max6875.c')
-rw-r--r-- | drivers/i2c/chips/max6875.c | 120 |
1 files changed, 49 insertions, 71 deletions
diff --git a/drivers/i2c/chips/max6875.c b/drivers/i2c/chips/max6875.c index 5a0285d8b6f9..033d9d81ec8a 100644 --- a/drivers/i2c/chips/max6875.c +++ b/drivers/i2c/chips/max6875.c | |||
@@ -53,7 +53,7 @@ I2C_CLIENT_INSMOD_1(max6875); | |||
53 | 53 | ||
54 | /* Each client has this additional data */ | 54 | /* Each client has this additional data */ |
55 | struct max6875_data { | 55 | struct max6875_data { |
56 | struct i2c_client client; | 56 | struct i2c_client *fake_client; |
57 | struct mutex update_lock; | 57 | struct mutex update_lock; |
58 | 58 | ||
59 | u32 valid; | 59 | u32 valid; |
@@ -61,19 +61,6 @@ struct max6875_data { | |||
61 | unsigned long last_updated[USER_EEPROM_SLICES]; | 61 | unsigned long last_updated[USER_EEPROM_SLICES]; |
62 | }; | 62 | }; |
63 | 63 | ||
64 | static int max6875_attach_adapter(struct i2c_adapter *adapter); | ||
65 | static int max6875_detect(struct i2c_adapter *adapter, int address, int kind); | ||
66 | static int max6875_detach_client(struct i2c_client *client); | ||
67 | |||
68 | /* This is the driver that will be inserted */ | ||
69 | static struct i2c_driver max6875_driver = { | ||
70 | .driver = { | ||
71 | .name = "max6875", | ||
72 | }, | ||
73 | .attach_adapter = max6875_attach_adapter, | ||
74 | .detach_client = max6875_detach_client, | ||
75 | }; | ||
76 | |||
77 | static void max6875_update_slice(struct i2c_client *client, int slice) | 64 | static void max6875_update_slice(struct i2c_client *client, int slice) |
78 | { | 65 | { |
79 | struct max6875_data *data = i2c_get_clientdata(client); | 66 | struct max6875_data *data = i2c_get_clientdata(client); |
@@ -159,96 +146,87 @@ static struct bin_attribute user_eeprom_attr = { | |||
159 | .read = max6875_read, | 146 | .read = max6875_read, |
160 | }; | 147 | }; |
161 | 148 | ||
162 | static int max6875_attach_adapter(struct i2c_adapter *adapter) | 149 | /* Return 0 if detection is successful, -ENODEV otherwise */ |
150 | static int max6875_detect(struct i2c_client *client, int kind, | ||
151 | struct i2c_board_info *info) | ||
163 | { | 152 | { |
164 | return i2c_probe(adapter, &addr_data, max6875_detect); | 153 | struct i2c_adapter *adapter = client->adapter; |
165 | } | ||
166 | |||
167 | /* This function is called by i2c_probe */ | ||
168 | static int max6875_detect(struct i2c_adapter *adapter, int address, int kind) | ||
169 | { | ||
170 | struct i2c_client *real_client; | ||
171 | struct i2c_client *fake_client; | ||
172 | struct max6875_data *data; | ||
173 | int err; | ||
174 | 154 | ||
175 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE_DATA | 155 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE_DATA |
176 | | I2C_FUNC_SMBUS_READ_BYTE)) | 156 | | I2C_FUNC_SMBUS_READ_BYTE)) |
177 | return 0; | 157 | return -ENODEV; |
178 | 158 | ||
179 | /* Only check even addresses */ | 159 | /* Only check even addresses */ |
180 | if (address & 1) | 160 | if (client->addr & 1) |
181 | return 0; | 161 | return -ENODEV; |
162 | |||
163 | strlcpy(info->type, "max6875", I2C_NAME_SIZE); | ||
164 | |||
165 | return 0; | ||
166 | } | ||
167 | |||
168 | static int max6875_probe(struct i2c_client *client, | ||
169 | const struct i2c_device_id *id) | ||
170 | { | ||
171 | struct max6875_data *data; | ||
172 | int err; | ||
182 | 173 | ||
183 | if (!(data = kzalloc(sizeof(struct max6875_data), GFP_KERNEL))) | 174 | if (!(data = kzalloc(sizeof(struct max6875_data), GFP_KERNEL))) |
184 | return -ENOMEM; | 175 | return -ENOMEM; |
185 | 176 | ||
186 | /* A fake client is created on the odd address */ | 177 | /* A fake client is created on the odd address */ |
187 | if (!(fake_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL))) { | 178 | data->fake_client = i2c_new_dummy(client->adapter, client->addr + 1); |
179 | if (!data->fake_client) { | ||
188 | err = -ENOMEM; | 180 | err = -ENOMEM; |
189 | goto exit_kfree1; | 181 | goto exit_kfree; |
190 | } | 182 | } |
191 | 183 | ||
192 | /* Init real i2c_client */ | 184 | /* Init real i2c_client */ |
193 | real_client = &data->client; | 185 | i2c_set_clientdata(client, data); |
194 | i2c_set_clientdata(real_client, data); | ||
195 | real_client->addr = address; | ||
196 | real_client->adapter = adapter; | ||
197 | real_client->driver = &max6875_driver; | ||
198 | strlcpy(real_client->name, "max6875", I2C_NAME_SIZE); | ||
199 | mutex_init(&data->update_lock); | 186 | mutex_init(&data->update_lock); |
200 | 187 | ||
201 | /* Init fake client data */ | 188 | err = sysfs_create_bin_file(&client->dev.kobj, &user_eeprom_attr); |
202 | i2c_set_clientdata(fake_client, NULL); | ||
203 | fake_client->addr = address | 1; | ||
204 | fake_client->adapter = adapter; | ||
205 | fake_client->driver = &max6875_driver; | ||
206 | strlcpy(fake_client->name, "max6875 subclient", I2C_NAME_SIZE); | ||
207 | |||
208 | if ((err = i2c_attach_client(real_client)) != 0) | ||
209 | goto exit_kfree2; | ||
210 | |||
211 | if ((err = i2c_attach_client(fake_client)) != 0) | ||
212 | goto exit_detach1; | ||
213 | |||
214 | err = sysfs_create_bin_file(&real_client->dev.kobj, &user_eeprom_attr); | ||
215 | if (err) | 189 | if (err) |
216 | goto exit_detach2; | 190 | goto exit_remove_fake; |
217 | 191 | ||
218 | return 0; | 192 | return 0; |
219 | 193 | ||
220 | exit_detach2: | 194 | exit_remove_fake: |
221 | i2c_detach_client(fake_client); | 195 | i2c_unregister_device(data->fake_client); |
222 | exit_detach1: | 196 | exit_kfree: |
223 | i2c_detach_client(real_client); | ||
224 | exit_kfree2: | ||
225 | kfree(fake_client); | ||
226 | exit_kfree1: | ||
227 | kfree(data); | 197 | kfree(data); |
228 | return err; | 198 | return err; |
229 | } | 199 | } |
230 | 200 | ||
231 | /* Will be called for both the real client and the fake client */ | 201 | static int max6875_remove(struct i2c_client *client) |
232 | static int max6875_detach_client(struct i2c_client *client) | ||
233 | { | 202 | { |
234 | int err; | ||
235 | struct max6875_data *data = i2c_get_clientdata(client); | 203 | struct max6875_data *data = i2c_get_clientdata(client); |
236 | 204 | ||
237 | /* data is NULL for the fake client */ | 205 | i2c_unregister_device(data->fake_client); |
238 | if (data) | ||
239 | sysfs_remove_bin_file(&client->dev.kobj, &user_eeprom_attr); | ||
240 | 206 | ||
241 | err = i2c_detach_client(client); | 207 | sysfs_remove_bin_file(&client->dev.kobj, &user_eeprom_attr); |
242 | if (err) | 208 | kfree(data); |
243 | return err; | ||
244 | 209 | ||
245 | if (data) /* real client */ | ||
246 | kfree(data); | ||
247 | else /* fake client */ | ||
248 | kfree(client); | ||
249 | return 0; | 210 | return 0; |
250 | } | 211 | } |
251 | 212 | ||
213 | static const struct i2c_device_id max6875_id[] = { | ||
214 | { "max6875", 0 }, | ||
215 | { } | ||
216 | }; | ||
217 | |||
218 | static struct i2c_driver max6875_driver = { | ||
219 | .driver = { | ||
220 | .name = "max6875", | ||
221 | }, | ||
222 | .probe = max6875_probe, | ||
223 | .remove = max6875_remove, | ||
224 | .id_table = max6875_id, | ||
225 | |||
226 | .detect = max6875_detect, | ||
227 | .address_data = &addr_data, | ||
228 | }; | ||
229 | |||
252 | static int __init max6875_init(void) | 230 | static int __init max6875_init(void) |
253 | { | 231 | { |
254 | return i2c_add_driver(&max6875_driver); | 232 | return i2c_add_driver(&max6875_driver); |