aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c
diff options
context:
space:
mode:
authorJean Delvare <khali@linux-fr.org>2008-07-16 13:30:07 -0400
committerJean Delvare <khali@mahadeva.delvare>2008-07-16 13:30:07 -0400
commitbd8d421f7ca9f8da3d820d28379d796500f69529 (patch)
tree705ec8b1dad4cbc4e20e6ca861f8db12a37143db /drivers/i2c
parent3d63430a26b91fe3daee0dd933f899c225e66daa (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')
-rw-r--r--drivers/i2c/chips/max6875.c120
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 */
55struct max6875_data { 55struct 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
64static int max6875_attach_adapter(struct i2c_adapter *adapter);
65static int max6875_detect(struct i2c_adapter *adapter, int address, int kind);
66static int max6875_detach_client(struct i2c_client *client);
67
68/* This is the driver that will be inserted */
69static 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
77static void max6875_update_slice(struct i2c_client *client, int slice) 64static 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
162static int max6875_attach_adapter(struct i2c_adapter *adapter) 149/* Return 0 if detection is successful, -ENODEV otherwise */
150static 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 */
168static 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
168static 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
220exit_detach2: 194exit_remove_fake:
221 i2c_detach_client(fake_client); 195 i2c_unregister_device(data->fake_client);
222exit_detach1: 196exit_kfree:
223 i2c_detach_client(real_client);
224exit_kfree2:
225 kfree(fake_client);
226exit_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 */ 201static int max6875_remove(struct i2c_client *client)
232static 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
213static const struct i2c_device_id max6875_id[] = {
214 { "max6875", 0 },
215 { }
216};
217
218static 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
252static int __init max6875_init(void) 230static int __init max6875_init(void)
253{ 231{
254 return i2c_add_driver(&max6875_driver); 232 return i2c_add_driver(&max6875_driver);