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 | d5957be2f1535b1a6c77eabba0781ec7245c5dea (patch) | |
tree | 8597a5a25444c8cfb222b5fae63674b837919ffa | |
parent | a23a9fe1d4d725e1624635f49e9790ec32deffd0 (diff) |
hwmon: (lm63) Convert to a new-style i2c driver
The new-style lm63 driver implements the optional detect() callback
to cover the use cases of the legacy driver.
Signed-off-by: Jean Delvare <khali@linux-fr.org>
-rw-r--r-- | drivers/hwmon/lm63.c | 99 |
1 files changed, 44 insertions, 55 deletions
diff --git a/drivers/hwmon/lm63.c b/drivers/hwmon/lm63.c index 116287008083..3195a265f0e9 100644 --- a/drivers/hwmon/lm63.c +++ b/drivers/hwmon/lm63.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * lm63.c - driver for the National Semiconductor LM63 temperature sensor | 2 | * lm63.c - driver for the National Semiconductor LM63 temperature sensor |
3 | * with integrated fan control | 3 | * with integrated fan control |
4 | * Copyright (C) 2004-2006 Jean Delvare <khali@linux-fr.org> | 4 | * Copyright (C) 2004-2008 Jean Delvare <khali@linux-fr.org> |
5 | * Based on the lm90 driver. | 5 | * Based on the lm90 driver. |
6 | * | 6 | * |
7 | * The LM63 is a sensor chip made by National Semiconductor. It measures | 7 | * The LM63 is a sensor chip made by National Semiconductor. It measures |
@@ -128,24 +128,36 @@ I2C_CLIENT_INSMOD_1(lm63); | |||
128 | * Functions declaration | 128 | * Functions declaration |
129 | */ | 129 | */ |
130 | 130 | ||
131 | static int lm63_attach_adapter(struct i2c_adapter *adapter); | 131 | static int lm63_probe(struct i2c_client *client, |
132 | static int lm63_detach_client(struct i2c_client *client); | 132 | const struct i2c_device_id *id); |
133 | static int lm63_remove(struct i2c_client *client); | ||
133 | 134 | ||
134 | static struct lm63_data *lm63_update_device(struct device *dev); | 135 | static struct lm63_data *lm63_update_device(struct device *dev); |
135 | 136 | ||
136 | static int lm63_detect(struct i2c_adapter *adapter, int address, int kind); | 137 | static int lm63_detect(struct i2c_client *client, int kind, |
138 | struct i2c_board_info *info); | ||
137 | static void lm63_init_client(struct i2c_client *client); | 139 | static void lm63_init_client(struct i2c_client *client); |
138 | 140 | ||
139 | /* | 141 | /* |
140 | * Driver data (common to all clients) | 142 | * Driver data (common to all clients) |
141 | */ | 143 | */ |
142 | 144 | ||
145 | static const struct i2c_device_id lm63_id[] = { | ||
146 | { "lm63", lm63 }, | ||
147 | { } | ||
148 | }; | ||
149 | MODULE_DEVICE_TABLE(i2c, lm63_id); | ||
150 | |||
143 | static struct i2c_driver lm63_driver = { | 151 | static struct i2c_driver lm63_driver = { |
152 | .class = I2C_CLASS_HWMON, | ||
144 | .driver = { | 153 | .driver = { |
145 | .name = "lm63", | 154 | .name = "lm63", |
146 | }, | 155 | }, |
147 | .attach_adapter = lm63_attach_adapter, | 156 | .probe = lm63_probe, |
148 | .detach_client = lm63_detach_client, | 157 | .remove = lm63_remove, |
158 | .id_table = lm63_id, | ||
159 | .detect = lm63_detect, | ||
160 | .address_data = &addr_data, | ||
149 | }; | 161 | }; |
150 | 162 | ||
151 | /* | 163 | /* |
@@ -153,7 +165,6 @@ static struct i2c_driver lm63_driver = { | |||
153 | */ | 165 | */ |
154 | 166 | ||
155 | struct lm63_data { | 167 | struct lm63_data { |
156 | struct i2c_client client; | ||
157 | struct device *hwmon_dev; | 168 | struct device *hwmon_dev; |
158 | struct mutex update_lock; | 169 | struct mutex update_lock; |
159 | char valid; /* zero until following fields are valid */ | 170 | char valid; /* zero until following fields are valid */ |
@@ -411,43 +422,14 @@ static const struct attribute_group lm63_group_fan1 = { | |||
411 | * Real code | 422 | * Real code |
412 | */ | 423 | */ |
413 | 424 | ||
414 | static int lm63_attach_adapter(struct i2c_adapter *adapter) | 425 | /* Return 0 if detection is successful, -ENODEV otherwise */ |
426 | static int lm63_detect(struct i2c_client *new_client, int kind, | ||
427 | struct i2c_board_info *info) | ||
415 | { | 428 | { |
416 | if (!(adapter->class & I2C_CLASS_HWMON)) | 429 | struct i2c_adapter *adapter = new_client->adapter; |
417 | return 0; | ||
418 | return i2c_probe(adapter, &addr_data, lm63_detect); | ||
419 | } | ||
420 | |||
421 | /* | ||
422 | * The following function does more than just detection. If detection | ||
423 | * succeeds, it also registers the new chip. | ||
424 | */ | ||
425 | static int lm63_detect(struct i2c_adapter *adapter, int address, int kind) | ||
426 | { | ||
427 | struct i2c_client *new_client; | ||
428 | struct lm63_data *data; | ||
429 | int err = 0; | ||
430 | 430 | ||
431 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | 431 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) |
432 | goto exit; | 432 | return -ENODEV; |
433 | |||
434 | if (!(data = kzalloc(sizeof(struct lm63_data), GFP_KERNEL))) { | ||
435 | err = -ENOMEM; | ||
436 | goto exit; | ||
437 | } | ||
438 | |||
439 | /* The common I2C client data is placed right before the | ||
440 | LM63-specific data. */ | ||
441 | new_client = &data->client; | ||
442 | i2c_set_clientdata(new_client, data); | ||
443 | new_client->addr = address; | ||
444 | new_client->adapter = adapter; | ||
445 | new_client->driver = &lm63_driver; | ||
446 | new_client->flags = 0; | ||
447 | |||
448 | /* Default to an LM63 if forced */ | ||
449 | if (kind == 0) | ||
450 | kind = lm63; | ||
451 | 433 | ||
452 | if (kind < 0) { /* must identify */ | 434 | if (kind < 0) { /* must identify */ |
453 | u8 man_id, chip_id, reg_config1, reg_config2; | 435 | u8 man_id, chip_id, reg_config1, reg_config2; |
@@ -477,25 +459,38 @@ static int lm63_detect(struct i2c_adapter *adapter, int address, int kind) | |||
477 | dev_dbg(&adapter->dev, "Unsupported chip " | 459 | dev_dbg(&adapter->dev, "Unsupported chip " |
478 | "(man_id=0x%02X, chip_id=0x%02X).\n", | 460 | "(man_id=0x%02X, chip_id=0x%02X).\n", |
479 | man_id, chip_id); | 461 | man_id, chip_id); |
480 | goto exit_free; | 462 | return -ENODEV; |
481 | } | 463 | } |
482 | } | 464 | } |
483 | 465 | ||
484 | strlcpy(new_client->name, "lm63", I2C_NAME_SIZE); | 466 | strlcpy(info->type, "lm63", I2C_NAME_SIZE); |
467 | |||
468 | return 0; | ||
469 | } | ||
470 | |||
471 | static int lm63_probe(struct i2c_client *new_client, | ||
472 | const struct i2c_device_id *id) | ||
473 | { | ||
474 | struct lm63_data *data; | ||
475 | int err; | ||
476 | |||
477 | data = kzalloc(sizeof(struct lm63_data), GFP_KERNEL); | ||
478 | if (!data) { | ||
479 | err = -ENOMEM; | ||
480 | goto exit; | ||
481 | } | ||
482 | |||
483 | i2c_set_clientdata(new_client, data); | ||
485 | data->valid = 0; | 484 | data->valid = 0; |
486 | mutex_init(&data->update_lock); | 485 | mutex_init(&data->update_lock); |
487 | 486 | ||
488 | /* Tell the I2C layer a new client has arrived */ | ||
489 | if ((err = i2c_attach_client(new_client))) | ||
490 | goto exit_free; | ||
491 | |||
492 | /* Initialize the LM63 chip */ | 487 | /* Initialize the LM63 chip */ |
493 | lm63_init_client(new_client); | 488 | lm63_init_client(new_client); |
494 | 489 | ||
495 | /* Register sysfs hooks */ | 490 | /* Register sysfs hooks */ |
496 | if ((err = sysfs_create_group(&new_client->dev.kobj, | 491 | if ((err = sysfs_create_group(&new_client->dev.kobj, |
497 | &lm63_group))) | 492 | &lm63_group))) |
498 | goto exit_detach; | 493 | goto exit_free; |
499 | if (data->config & 0x04) { /* tachometer enabled */ | 494 | if (data->config & 0x04) { /* tachometer enabled */ |
500 | if ((err = sysfs_create_group(&new_client->dev.kobj, | 495 | if ((err = sysfs_create_group(&new_client->dev.kobj, |
501 | &lm63_group_fan1))) | 496 | &lm63_group_fan1))) |
@@ -513,8 +508,6 @@ static int lm63_detect(struct i2c_adapter *adapter, int address, int kind) | |||
513 | exit_remove_files: | 508 | exit_remove_files: |
514 | sysfs_remove_group(&new_client->dev.kobj, &lm63_group); | 509 | sysfs_remove_group(&new_client->dev.kobj, &lm63_group); |
515 | sysfs_remove_group(&new_client->dev.kobj, &lm63_group_fan1); | 510 | sysfs_remove_group(&new_client->dev.kobj, &lm63_group_fan1); |
516 | exit_detach: | ||
517 | i2c_detach_client(new_client); | ||
518 | exit_free: | 511 | exit_free: |
519 | kfree(data); | 512 | kfree(data); |
520 | exit: | 513 | exit: |
@@ -556,18 +549,14 @@ static void lm63_init_client(struct i2c_client *client) | |||
556 | (data->config_fan & 0x20) ? "manual" : "auto"); | 549 | (data->config_fan & 0x20) ? "manual" : "auto"); |
557 | } | 550 | } |
558 | 551 | ||
559 | static int lm63_detach_client(struct i2c_client *client) | 552 | static int lm63_remove(struct i2c_client *client) |
560 | { | 553 | { |
561 | struct lm63_data *data = i2c_get_clientdata(client); | 554 | struct lm63_data *data = i2c_get_clientdata(client); |
562 | int err; | ||
563 | 555 | ||
564 | hwmon_device_unregister(data->hwmon_dev); | 556 | hwmon_device_unregister(data->hwmon_dev); |
565 | sysfs_remove_group(&client->dev.kobj, &lm63_group); | 557 | sysfs_remove_group(&client->dev.kobj, &lm63_group); |
566 | sysfs_remove_group(&client->dev.kobj, &lm63_group_fan1); | 558 | sysfs_remove_group(&client->dev.kobj, &lm63_group_fan1); |
567 | 559 | ||
568 | if ((err = i2c_detach_client(client))) | ||
569 | return err; | ||
570 | |||
571 | kfree(data); | 560 | kfree(data); |
572 | return 0; | 561 | return 0; |
573 | } | 562 | } |