diff options
author | Jean Delvare <khali@linux-fr.org> | 2008-07-16 13:30:13 -0400 |
---|---|---|
committer | Jean Delvare <khali@mahadeva.delvare> | 2008-07-16 13:30:13 -0400 |
commit | a189dd62d328db7bf8ba68de6a948fdbc93dca25 (patch) | |
tree | 00a53527cbec8ce5aaef2eb5d4c6b698514554af | |
parent | d5957be2f1535b1a6c77eabba0781ec7245c5dea (diff) |
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>
-rw-r--r-- | drivers/hwmon/lm77.c | 102 |
1 files changed, 45 insertions, 57 deletions
diff --git a/drivers/hwmon/lm77.c b/drivers/hwmon/lm77.c index 36d5a8c3ad8c..866b401ab6e8 100644 --- a/drivers/hwmon/lm77.c +++ b/drivers/hwmon/lm77.c | |||
@@ -52,7 +52,6 @@ I2C_CLIENT_INSMOD_1(lm77); | |||
52 | 52 | ||
53 | /* Each client has this additional data */ | 53 | /* Each client has this additional data */ |
54 | struct lm77_data { | 54 | struct lm77_data { |
55 | struct i2c_client client; | ||
56 | struct device *hwmon_dev; | 55 | struct device *hwmon_dev; |
57 | struct mutex update_lock; | 56 | struct mutex update_lock; |
58 | char valid; | 57 | char valid; |
@@ -65,23 +64,35 @@ struct lm77_data { | |||
65 | u8 alarms; | 64 | u8 alarms; |
66 | }; | 65 | }; |
67 | 66 | ||
68 | static int lm77_attach_adapter(struct i2c_adapter *adapter); | 67 | static int lm77_probe(struct i2c_client *client, |
69 | static int lm77_detect(struct i2c_adapter *adapter, int address, int kind); | 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 | static void lm77_init_client(struct i2c_client *client); | 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 | static u16 lm77_read_value(struct i2c_client *client, u8 reg); | 73 | static u16 lm77_read_value(struct i2c_client *client, u8 reg); |
73 | static int lm77_write_value(struct i2c_client *client, u8 reg, u16 value); | 74 | static int lm77_write_value(struct i2c_client *client, u8 reg, u16 value); |
74 | 75 | ||
75 | static struct lm77_data *lm77_update_device(struct device *dev); | 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 | /* This is the driver that will be inserted */ | 85 | /* This is the driver that will be inserted */ |
79 | static struct i2c_driver lm77_driver = { | 86 | static struct i2c_driver lm77_driver = { |
87 | .class = I2C_CLASS_HWMON, | ||
80 | .driver = { | 88 | .driver = { |
81 | .name = "lm77", | 89 | .name = "lm77", |
82 | }, | 90 | }, |
83 | .attach_adapter = lm77_attach_adapter, | 91 | .probe = lm77_probe, |
84 | .detach_client = lm77_detach_client, | 92 | .remove = lm77_remove, |
93 | .id_table = lm77_id, | ||
94 | .detect = lm77_detect, | ||
95 | .address_data = &addr_data, | ||
85 | }; | 96 | }; |
86 | 97 | ||
87 | /* straight from the datasheet */ | 98 | /* straight from the datasheet */ |
@@ -215,13 +226,6 @@ static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 2); | |||
215 | static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_alarm, NULL, 0); | 226 | static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_alarm, NULL, 0); |
216 | static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 1); | 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 | static struct attribute *lm77_attributes[] = { | 229 | static struct attribute *lm77_attributes[] = { |
226 | &dev_attr_temp1_input.attr, | 230 | &dev_attr_temp1_input.attr, |
227 | &dev_attr_temp1_crit.attr, | 231 | &dev_attr_temp1_crit.attr, |
@@ -240,32 +244,15 @@ static const struct attribute_group lm77_group = { | |||
240 | .attrs = lm77_attributes, | 244 | .attrs = lm77_attributes, |
241 | }; | 245 | }; |
242 | 246 | ||
243 | /* This function is called by i2c_probe */ | 247 | /* Return 0 if detection is successful, -ENODEV otherwise */ |
244 | static int lm77_detect(struct i2c_adapter *adapter, int address, int kind) | 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; | 251 | struct i2c_adapter *adapter = new_client->adapter; |
247 | struct lm77_data *data; | ||
248 | int err = 0; | ||
249 | const char *name = ""; | ||
250 | 252 | ||
251 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | | 253 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | |
252 | I2C_FUNC_SMBUS_WORD_DATA)) | 254 | I2C_FUNC_SMBUS_WORD_DATA)) |
253 | goto exit; | 255 | return -ENODEV; |
254 | |||
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 | 256 | ||
270 | /* Here comes the remaining detection. Since the LM77 has no | 257 | /* Here comes the remaining detection. Since the LM77 has no |
271 | register dedicated to identification, we have to rely on the | 258 | register dedicated to identification, we have to rely on the |
@@ -294,7 +281,7 @@ static int lm77_detect(struct i2c_adapter *adapter, int address, int kind) | |||
294 | || i2c_smbus_read_word_data(new_client, i + 3) != crit | 281 | || i2c_smbus_read_word_data(new_client, i + 3) != crit |
295 | || i2c_smbus_read_word_data(new_client, i + 4) != min | 282 | || i2c_smbus_read_word_data(new_client, i + 4) != min |
296 | || i2c_smbus_read_word_data(new_client, i + 5) != max) | 283 | || i2c_smbus_read_word_data(new_client, i + 5) != max) |
297 | goto exit_free; | 284 | return -ENODEV; |
298 | 285 | ||
299 | /* sign bits */ | 286 | /* sign bits */ |
300 | if (((cur & 0x00f0) != 0xf0 && (cur & 0x00f0) != 0x0) | 287 | if (((cur & 0x00f0) != 0xf0 && (cur & 0x00f0) != 0x0) |
@@ -302,51 +289,55 @@ static int lm77_detect(struct i2c_adapter *adapter, int address, int kind) | |||
302 | || ((crit & 0x00f0) != 0xf0 && (crit & 0x00f0) != 0x0) | 289 | || ((crit & 0x00f0) != 0xf0 && (crit & 0x00f0) != 0x0) |
303 | || ((min & 0x00f0) != 0xf0 && (min & 0x00f0) != 0x0) | 290 | || ((min & 0x00f0) != 0xf0 && (min & 0x00f0) != 0x0) |
304 | || ((max & 0x00f0) != 0xf0 && (max & 0x00f0) != 0x0)) | 291 | || ((max & 0x00f0) != 0xf0 && (max & 0x00f0) != 0x0)) |
305 | goto exit_free; | 292 | return -ENODEV; |
306 | 293 | ||
307 | /* unused bits */ | 294 | /* unused bits */ |
308 | if (conf & 0xe0) | 295 | if (conf & 0xe0) |
309 | goto exit_free; | 296 | return -ENODEV; |
310 | 297 | ||
311 | /* 0x06 and 0x07 return the last read value */ | 298 | /* 0x06 and 0x07 return the last read value */ |
312 | cur = i2c_smbus_read_word_data(new_client, 0); | 299 | cur = i2c_smbus_read_word_data(new_client, 0); |
313 | if (i2c_smbus_read_word_data(new_client, 6) != cur | 300 | if (i2c_smbus_read_word_data(new_client, 6) != cur |
314 | || i2c_smbus_read_word_data(new_client, 7) != cur) | 301 | || i2c_smbus_read_word_data(new_client, 7) != cur) |
315 | goto exit_free; | 302 | return -ENODEV; |
316 | hyst = i2c_smbus_read_word_data(new_client, 2); | 303 | hyst = i2c_smbus_read_word_data(new_client, 2); |
317 | if (i2c_smbus_read_word_data(new_client, 6) != hyst | 304 | if (i2c_smbus_read_word_data(new_client, 6) != hyst |
318 | || i2c_smbus_read_word_data(new_client, 7) != hyst) | 305 | || i2c_smbus_read_word_data(new_client, 7) != hyst) |
319 | goto exit_free; | 306 | return -ENODEV; |
320 | min = i2c_smbus_read_word_data(new_client, 4); | 307 | min = i2c_smbus_read_word_data(new_client, 4); |
321 | if (i2c_smbus_read_word_data(new_client, 6) != min | 308 | if (i2c_smbus_read_word_data(new_client, 6) != min |
322 | || i2c_smbus_read_word_data(new_client, 7) != min) | 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! */ | 314 | strlcpy(info->type, "lm77", I2C_NAME_SIZE); |
328 | if (kind <= 0) | ||
329 | kind = lm77; | ||
330 | 315 | ||
331 | if (kind == lm77) { | 316 | return 0; |
332 | name = "lm77"; | 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 */ | 331 | i2c_set_clientdata(new_client, data); |
336 | strlcpy(new_client->name, name, I2C_NAME_SIZE); | ||
337 | data->valid = 0; | 332 | data->valid = 0; |
338 | mutex_init(&data->update_lock); | 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 | /* Initialize the LM77 chip */ | 335 | /* Initialize the LM77 chip */ |
345 | lm77_init_client(new_client); | 336 | lm77_init_client(new_client); |
346 | 337 | ||
347 | /* Register sysfs hooks */ | 338 | /* Register sysfs hooks */ |
348 | if ((err = sysfs_create_group(&new_client->dev.kobj, &lm77_group))) | 339 | if ((err = sysfs_create_group(&new_client->dev.kobj, &lm77_group))) |
349 | goto exit_detach; | 340 | goto exit_free; |
350 | 341 | ||
351 | data->hwmon_dev = hwmon_device_register(&new_client->dev); | 342 | data->hwmon_dev = hwmon_device_register(&new_client->dev); |
352 | if (IS_ERR(data->hwmon_dev)) { | 343 | if (IS_ERR(data->hwmon_dev)) { |
@@ -358,20 +349,17 @@ static int lm77_detect(struct i2c_adapter *adapter, int address, int kind) | |||
358 | 349 | ||
359 | exit_remove: | 350 | exit_remove: |
360 | sysfs_remove_group(&new_client->dev.kobj, &lm77_group); | 351 | sysfs_remove_group(&new_client->dev.kobj, &lm77_group); |
361 | exit_detach: | ||
362 | i2c_detach_client(new_client); | ||
363 | exit_free: | 352 | exit_free: |
364 | kfree(data); | 353 | kfree(data); |
365 | exit: | 354 | exit: |
366 | return err; | 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 | struct lm77_data *data = i2c_get_clientdata(client); | 360 | struct lm77_data *data = i2c_get_clientdata(client); |
372 | hwmon_device_unregister(data->hwmon_dev); | 361 | hwmon_device_unregister(data->hwmon_dev); |
373 | sysfs_remove_group(&client->dev.kobj, &lm77_group); | 362 | sysfs_remove_group(&client->dev.kobj, &lm77_group); |
374 | i2c_detach_client(client); | ||
375 | kfree(data); | 363 | kfree(data); |
376 | return 0; | 364 | return 0; |
377 | } | 365 | } |