Commit a189dd62d328db7bf8ba68de6a948fdbc93dca25
Committed by
Jean Delvare
1 parent
d5957be2f1
Exists in
master
and in
7 other branches
hwmon: (lm77) Convert to a new-style i2c driver
The new-style lm77 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: Andras Bali <drewie@freemail.hu>
Showing 1 changed file with 45 additions and 57 deletions Side-by-side Diff
drivers/hwmon/lm77.c
... | ... | @@ -52,7 +52,6 @@ |
52 | 52 | |
53 | 53 | /* Each client has this additional data */ |
54 | 54 | struct lm77_data { |
55 | - struct i2c_client client; | |
56 | 55 | struct device *hwmon_dev; |
57 | 56 | struct mutex update_lock; |
58 | 57 | char valid; |
59 | 58 | |
60 | 59 | |
61 | 60 | |
62 | 61 | |
... | ... | @@ -65,23 +64,35 @@ |
65 | 64 | u8 alarms; |
66 | 65 | }; |
67 | 66 | |
68 | -static int lm77_attach_adapter(struct i2c_adapter *adapter); | |
69 | -static int lm77_detect(struct i2c_adapter *adapter, int address, int kind); | |
67 | +static int lm77_probe(struct i2c_client *client, | |
68 | + const struct i2c_device_id *id); | |
69 | +static int lm77_detect(struct i2c_client *client, int kind, | |
70 | + struct i2c_board_info *info); | |
70 | 71 | static void lm77_init_client(struct i2c_client *client); |
71 | -static int lm77_detach_client(struct i2c_client *client); | |
72 | +static int lm77_remove(struct i2c_client *client); | |
72 | 73 | static u16 lm77_read_value(struct i2c_client *client, u8 reg); |
73 | 74 | static int lm77_write_value(struct i2c_client *client, u8 reg, u16 value); |
74 | 75 | |
75 | 76 | static struct lm77_data *lm77_update_device(struct device *dev); |
76 | 77 | |
77 | 78 | |
79 | +static const struct i2c_device_id lm77_id[] = { | |
80 | + { "lm77", lm77 }, | |
81 | + { } | |
82 | +}; | |
83 | +MODULE_DEVICE_TABLE(i2c, lm77_id); | |
84 | + | |
78 | 85 | /* This is the driver that will be inserted */ |
79 | 86 | static struct i2c_driver lm77_driver = { |
87 | + .class = I2C_CLASS_HWMON, | |
80 | 88 | .driver = { |
81 | 89 | .name = "lm77", |
82 | 90 | }, |
83 | - .attach_adapter = lm77_attach_adapter, | |
84 | - .detach_client = lm77_detach_client, | |
91 | + .probe = lm77_probe, | |
92 | + .remove = lm77_remove, | |
93 | + .id_table = lm77_id, | |
94 | + .detect = lm77_detect, | |
95 | + .address_data = &addr_data, | |
85 | 96 | }; |
86 | 97 | |
87 | 98 | /* straight from the datasheet */ |
... | ... | @@ -215,13 +226,6 @@ |
215 | 226 | static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_alarm, NULL, 0); |
216 | 227 | static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 1); |
217 | 228 | |
218 | -static int lm77_attach_adapter(struct i2c_adapter *adapter) | |
219 | -{ | |
220 | - if (!(adapter->class & I2C_CLASS_HWMON)) | |
221 | - return 0; | |
222 | - return i2c_probe(adapter, &addr_data, lm77_detect); | |
223 | -} | |
224 | - | |
225 | 229 | static struct attribute *lm77_attributes[] = { |
226 | 230 | &dev_attr_temp1_input.attr, |
227 | 231 | &dev_attr_temp1_crit.attr, |
228 | 232 | |
229 | 233 | |
230 | 234 | |
... | ... | @@ -240,33 +244,16 @@ |
240 | 244 | .attrs = lm77_attributes, |
241 | 245 | }; |
242 | 246 | |
243 | -/* This function is called by i2c_probe */ | |
244 | -static int lm77_detect(struct i2c_adapter *adapter, int address, int kind) | |
247 | +/* Return 0 if detection is successful, -ENODEV otherwise */ | |
248 | +static int lm77_detect(struct i2c_client *new_client, int kind, | |
249 | + struct i2c_board_info *info) | |
245 | 250 | { |
246 | - struct i2c_client *new_client; | |
247 | - struct lm77_data *data; | |
248 | - int err = 0; | |
249 | - const char *name = ""; | |
251 | + struct i2c_adapter *adapter = new_client->adapter; | |
250 | 252 | |
251 | 253 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | |
252 | 254 | I2C_FUNC_SMBUS_WORD_DATA)) |
253 | - goto exit; | |
255 | + return -ENODEV; | |
254 | 256 | |
255 | - /* OK. For now, we presume we have a valid client. We now create the | |
256 | - client structure, even though we cannot fill it completely yet. | |
257 | - But it allows us to access lm77_{read,write}_value. */ | |
258 | - if (!(data = kzalloc(sizeof(struct lm77_data), GFP_KERNEL))) { | |
259 | - err = -ENOMEM; | |
260 | - goto exit; | |
261 | - } | |
262 | - | |
263 | - new_client = &data->client; | |
264 | - i2c_set_clientdata(new_client, data); | |
265 | - new_client->addr = address; | |
266 | - new_client->adapter = adapter; | |
267 | - new_client->driver = &lm77_driver; | |
268 | - new_client->flags = 0; | |
269 | - | |
270 | 257 | /* Here comes the remaining detection. Since the LM77 has no |
271 | 258 | register dedicated to identification, we have to rely on the |
272 | 259 | following tricks: |
... | ... | @@ -294,7 +281,7 @@ |
294 | 281 | || i2c_smbus_read_word_data(new_client, i + 3) != crit |
295 | 282 | || i2c_smbus_read_word_data(new_client, i + 4) != min |
296 | 283 | || i2c_smbus_read_word_data(new_client, i + 5) != max) |
297 | - goto exit_free; | |
284 | + return -ENODEV; | |
298 | 285 | |
299 | 286 | /* sign bits */ |
300 | 287 | if (((cur & 0x00f0) != 0xf0 && (cur & 0x00f0) != 0x0) |
301 | 288 | |
302 | 289 | |
303 | 290 | |
304 | 291 | |
305 | 292 | |
306 | 293 | |
307 | 294 | |
308 | 295 | |
309 | 296 | |
... | ... | @@ -302,51 +289,55 @@ |
302 | 289 | || ((crit & 0x00f0) != 0xf0 && (crit & 0x00f0) != 0x0) |
303 | 290 | || ((min & 0x00f0) != 0xf0 && (min & 0x00f0) != 0x0) |
304 | 291 | || ((max & 0x00f0) != 0xf0 && (max & 0x00f0) != 0x0)) |
305 | - goto exit_free; | |
292 | + return -ENODEV; | |
306 | 293 | |
307 | 294 | /* unused bits */ |
308 | 295 | if (conf & 0xe0) |
309 | - goto exit_free; | |
296 | + return -ENODEV; | |
310 | 297 | |
311 | 298 | /* 0x06 and 0x07 return the last read value */ |
312 | 299 | cur = i2c_smbus_read_word_data(new_client, 0); |
313 | 300 | if (i2c_smbus_read_word_data(new_client, 6) != cur |
314 | 301 | || i2c_smbus_read_word_data(new_client, 7) != cur) |
315 | - goto exit_free; | |
302 | + return -ENODEV; | |
316 | 303 | hyst = i2c_smbus_read_word_data(new_client, 2); |
317 | 304 | if (i2c_smbus_read_word_data(new_client, 6) != hyst |
318 | 305 | || i2c_smbus_read_word_data(new_client, 7) != hyst) |
319 | - goto exit_free; | |
306 | + return -ENODEV; | |
320 | 307 | min = i2c_smbus_read_word_data(new_client, 4); |
321 | 308 | if (i2c_smbus_read_word_data(new_client, 6) != min |
322 | 309 | || i2c_smbus_read_word_data(new_client, 7) != min) |
323 | - goto exit_free; | |
310 | + return -ENODEV; | |
324 | 311 | |
325 | 312 | } |
326 | 313 | |
327 | - /* Determine the chip type - only one kind supported! */ | |
328 | - if (kind <= 0) | |
329 | - kind = lm77; | |
314 | + strlcpy(info->type, "lm77", I2C_NAME_SIZE); | |
330 | 315 | |
331 | - if (kind == lm77) { | |
332 | - name = "lm77"; | |
316 | + return 0; | |
317 | +} | |
318 | + | |
319 | +static int lm77_probe(struct i2c_client *new_client, | |
320 | + const struct i2c_device_id *id) | |
321 | +{ | |
322 | + struct lm77_data *data; | |
323 | + int err; | |
324 | + | |
325 | + data = kzalloc(sizeof(struct lm77_data), GFP_KERNEL); | |
326 | + if (!data) { | |
327 | + err = -ENOMEM; | |
328 | + goto exit; | |
333 | 329 | } |
334 | 330 | |
335 | - /* Fill in the remaining client fields and put it into the global list */ | |
336 | - strlcpy(new_client->name, name, I2C_NAME_SIZE); | |
331 | + i2c_set_clientdata(new_client, data); | |
337 | 332 | data->valid = 0; |
338 | 333 | mutex_init(&data->update_lock); |
339 | 334 | |
340 | - /* Tell the I2C layer a new client has arrived */ | |
341 | - if ((err = i2c_attach_client(new_client))) | |
342 | - goto exit_free; | |
343 | - | |
344 | 335 | /* Initialize the LM77 chip */ |
345 | 336 | lm77_init_client(new_client); |
346 | 337 | |
347 | 338 | /* Register sysfs hooks */ |
348 | 339 | if ((err = sysfs_create_group(&new_client->dev.kobj, &lm77_group))) |
349 | - goto exit_detach; | |
340 | + goto exit_free; | |
350 | 341 | |
351 | 342 | data->hwmon_dev = hwmon_device_register(&new_client->dev); |
352 | 343 | if (IS_ERR(data->hwmon_dev)) { |
353 | 344 | |
354 | 345 | |
... | ... | @@ -358,20 +349,17 @@ |
358 | 349 | |
359 | 350 | exit_remove: |
360 | 351 | sysfs_remove_group(&new_client->dev.kobj, &lm77_group); |
361 | -exit_detach: | |
362 | - i2c_detach_client(new_client); | |
363 | 352 | exit_free: |
364 | 353 | kfree(data); |
365 | 354 | exit: |
366 | 355 | return err; |
367 | 356 | } |
368 | 357 | |
369 | -static int lm77_detach_client(struct i2c_client *client) | |
358 | +static int lm77_remove(struct i2c_client *client) | |
370 | 359 | { |
371 | 360 | struct lm77_data *data = i2c_get_clientdata(client); |
372 | 361 | hwmon_device_unregister(data->hwmon_dev); |
373 | 362 | sysfs_remove_group(&client->dev.kobj, &lm77_group); |
374 | - i2c_detach_client(client); | |
375 | 363 | kfree(data); |
376 | 364 | return 0; |
377 | 365 | } |