diff options
author | Jean Delvare <khali@linux-fr.org> | 2008-07-16 13:30:15 -0400 |
---|---|---|
committer | Jean Delvare <khali@mahadeva.delvare> | 2008-07-16 13:30:15 -0400 |
commit | 9b0e85269275159a1f9c3e4a5d254caf5211950b (patch) | |
tree | bab6c522e6c21ba3ca5bd250e5eb4cba054b0f2e /drivers/hwmon | |
parent | a888420af07b9a26b6d518328baa913fb704e950 (diff) |
hwmon: (lm90) Convert to a new-style i2c driver
The new-style lm90 driver implements the optional detect() callback
to cover the use cases of the legacy driver.
Signed-off-by: Jean Delvare <khali@linux-fr.org>
Diffstat (limited to 'drivers/hwmon')
-rw-r--r-- | drivers/hwmon/lm90.c | 119 |
1 files changed, 63 insertions, 56 deletions
diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c index d1a3da3dd8e0..c24fe36ac787 100644 --- a/drivers/hwmon/lm90.c +++ b/drivers/hwmon/lm90.c | |||
@@ -187,23 +187,44 @@ I2C_CLIENT_INSMOD_7(lm90, adm1032, lm99, lm86, max6657, adt7461, max6680); | |||
187 | * Functions declaration | 187 | * Functions declaration |
188 | */ | 188 | */ |
189 | 189 | ||
190 | static int lm90_attach_adapter(struct i2c_adapter *adapter); | 190 | static int lm90_detect(struct i2c_client *client, int kind, |
191 | static int lm90_detect(struct i2c_adapter *adapter, int address, | 191 | struct i2c_board_info *info); |
192 | int kind); | 192 | static int lm90_probe(struct i2c_client *client, |
193 | const struct i2c_device_id *id); | ||
193 | static void lm90_init_client(struct i2c_client *client); | 194 | static void lm90_init_client(struct i2c_client *client); |
194 | static int lm90_detach_client(struct i2c_client *client); | 195 | static int lm90_remove(struct i2c_client *client); |
195 | static struct lm90_data *lm90_update_device(struct device *dev); | 196 | static struct lm90_data *lm90_update_device(struct device *dev); |
196 | 197 | ||
197 | /* | 198 | /* |
198 | * Driver data (common to all clients) | 199 | * Driver data (common to all clients) |
199 | */ | 200 | */ |
200 | 201 | ||
202 | static const struct i2c_device_id lm90_id[] = { | ||
203 | { "adm1032", adm1032 }, | ||
204 | { "adt7461", adt7461 }, | ||
205 | { "lm90", lm90 }, | ||
206 | { "lm86", lm86 }, | ||
207 | { "lm89", lm99 }, | ||
208 | { "lm99", lm99 }, /* Missing temperature offset */ | ||
209 | { "max6657", max6657 }, | ||
210 | { "max6658", max6657 }, | ||
211 | { "max6659", max6657 }, | ||
212 | { "max6680", max6680 }, | ||
213 | { "max6681", max6680 }, | ||
214 | { } | ||
215 | }; | ||
216 | MODULE_DEVICE_TABLE(i2c, lm90_id); | ||
217 | |||
201 | static struct i2c_driver lm90_driver = { | 218 | static struct i2c_driver lm90_driver = { |
219 | .class = I2C_CLASS_HWMON, | ||
202 | .driver = { | 220 | .driver = { |
203 | .name = "lm90", | 221 | .name = "lm90", |
204 | }, | 222 | }, |
205 | .attach_adapter = lm90_attach_adapter, | 223 | .probe = lm90_probe, |
206 | .detach_client = lm90_detach_client, | 224 | .remove = lm90_remove, |
225 | .id_table = lm90_id, | ||
226 | .detect = lm90_detect, | ||
227 | .address_data = &addr_data, | ||
207 | }; | 228 | }; |
208 | 229 | ||
209 | /* | 230 | /* |
@@ -211,7 +232,6 @@ static struct i2c_driver lm90_driver = { | |||
211 | */ | 232 | */ |
212 | 233 | ||
213 | struct lm90_data { | 234 | struct lm90_data { |
214 | struct i2c_client client; | ||
215 | struct device *hwmon_dev; | 235 | struct device *hwmon_dev; |
216 | struct mutex update_lock; | 236 | struct mutex update_lock; |
217 | char valid; /* zero until following fields are valid */ | 237 | char valid; /* zero until following fields are valid */ |
@@ -477,40 +497,16 @@ static int lm90_read_reg(struct i2c_client* client, u8 reg, u8 *value) | |||
477 | return 0; | 497 | return 0; |
478 | } | 498 | } |
479 | 499 | ||
480 | static int lm90_attach_adapter(struct i2c_adapter *adapter) | 500 | /* Return 0 if detection is successful, -ENODEV otherwise */ |
481 | { | 501 | static int lm90_detect(struct i2c_client *new_client, int kind, |
482 | if (!(adapter->class & I2C_CLASS_HWMON)) | 502 | struct i2c_board_info *info) |
483 | return 0; | ||
484 | return i2c_probe(adapter, &addr_data, lm90_detect); | ||
485 | } | ||
486 | |||
487 | /* | ||
488 | * The following function does more than just detection. If detection | ||
489 | * succeeds, it also registers the new chip. | ||
490 | */ | ||
491 | static int lm90_detect(struct i2c_adapter *adapter, int address, int kind) | ||
492 | { | 503 | { |
493 | struct i2c_client *new_client; | 504 | struct i2c_adapter *adapter = new_client->adapter; |
494 | struct lm90_data *data; | 505 | int address = new_client->addr; |
495 | int err = 0; | ||
496 | const char *name = ""; | 506 | const char *name = ""; |
497 | 507 | ||
498 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | 508 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) |
499 | goto exit; | 509 | return -ENODEV; |
500 | |||
501 | if (!(data = kzalloc(sizeof(struct lm90_data), GFP_KERNEL))) { | ||
502 | err = -ENOMEM; | ||
503 | goto exit; | ||
504 | } | ||
505 | |||
506 | /* The common I2C client data is placed right before the | ||
507 | LM90-specific data. */ | ||
508 | new_client = &data->client; | ||
509 | i2c_set_clientdata(new_client, data); | ||
510 | new_client->addr = address; | ||
511 | new_client->adapter = adapter; | ||
512 | new_client->driver = &lm90_driver; | ||
513 | new_client->flags = 0; | ||
514 | 510 | ||
515 | /* | 511 | /* |
516 | * Now we do the remaining detection. A negative kind means that | 512 | * Now we do the remaining detection. A negative kind means that |
@@ -538,7 +534,7 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind) | |||
538 | LM90_REG_R_CONFIG1)) < 0 | 534 | LM90_REG_R_CONFIG1)) < 0 |
539 | || (reg_convrate = i2c_smbus_read_byte_data(new_client, | 535 | || (reg_convrate = i2c_smbus_read_byte_data(new_client, |
540 | LM90_REG_R_CONVRATE)) < 0) | 536 | LM90_REG_R_CONVRATE)) < 0) |
541 | goto exit_free; | 537 | return -ENODEV; |
542 | 538 | ||
543 | if ((address == 0x4C || address == 0x4D) | 539 | if ((address == 0x4C || address == 0x4D) |
544 | && man_id == 0x01) { /* National Semiconductor */ | 540 | && man_id == 0x01) { /* National Semiconductor */ |
@@ -546,7 +542,7 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind) | |||
546 | 542 | ||
547 | if ((reg_config2 = i2c_smbus_read_byte_data(new_client, | 543 | if ((reg_config2 = i2c_smbus_read_byte_data(new_client, |
548 | LM90_REG_R_CONFIG2)) < 0) | 544 | LM90_REG_R_CONFIG2)) < 0) |
549 | goto exit_free; | 545 | return -ENODEV; |
550 | 546 | ||
551 | if ((reg_config1 & 0x2A) == 0x00 | 547 | if ((reg_config1 & 0x2A) == 0x00 |
552 | && (reg_config2 & 0xF8) == 0x00 | 548 | && (reg_config2 & 0xF8) == 0x00 |
@@ -610,10 +606,11 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind) | |||
610 | dev_info(&adapter->dev, | 606 | dev_info(&adapter->dev, |
611 | "Unsupported chip (man_id=0x%02X, " | 607 | "Unsupported chip (man_id=0x%02X, " |
612 | "chip_id=0x%02X).\n", man_id, chip_id); | 608 | "chip_id=0x%02X).\n", man_id, chip_id); |
613 | goto exit_free; | 609 | return -ENODEV; |
614 | } | 610 | } |
615 | } | 611 | } |
616 | 612 | ||
613 | /* Fill the i2c board info */ | ||
617 | if (kind == lm90) { | 614 | if (kind == lm90) { |
618 | name = "lm90"; | 615 | name = "lm90"; |
619 | } else if (kind == adm1032) { | 616 | } else if (kind == adm1032) { |
@@ -621,7 +618,7 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind) | |||
621 | /* The ADM1032 supports PEC, but only if combined | 618 | /* The ADM1032 supports PEC, but only if combined |
622 | transactions are not used. */ | 619 | transactions are not used. */ |
623 | if (i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE)) | 620 | if (i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE)) |
624 | new_client->flags |= I2C_CLIENT_PEC; | 621 | info->flags |= I2C_CLIENT_PEC; |
625 | } else if (kind == lm99) { | 622 | } else if (kind == lm99) { |
626 | name = "lm99"; | 623 | name = "lm99"; |
627 | } else if (kind == lm86) { | 624 | } else if (kind == lm86) { |
@@ -633,23 +630,39 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind) | |||
633 | } else if (kind == adt7461) { | 630 | } else if (kind == adt7461) { |
634 | name = "adt7461"; | 631 | name = "adt7461"; |
635 | } | 632 | } |
633 | strlcpy(info->type, name, I2C_NAME_SIZE); | ||
634 | |||
635 | return 0; | ||
636 | } | ||
637 | |||
638 | static int lm90_probe(struct i2c_client *new_client, | ||
639 | const struct i2c_device_id *id) | ||
640 | { | ||
641 | struct i2c_adapter *adapter = to_i2c_adapter(new_client->dev.parent); | ||
642 | struct lm90_data *data; | ||
643 | int err; | ||
636 | 644 | ||
637 | /* We can fill in the remaining client fields */ | 645 | data = kzalloc(sizeof(struct lm90_data), GFP_KERNEL); |
638 | strlcpy(new_client->name, name, I2C_NAME_SIZE); | 646 | if (!data) { |
639 | data->valid = 0; | 647 | err = -ENOMEM; |
640 | data->kind = kind; | 648 | goto exit; |
649 | } | ||
650 | i2c_set_clientdata(new_client, data); | ||
641 | mutex_init(&data->update_lock); | 651 | mutex_init(&data->update_lock); |
642 | 652 | ||
643 | /* Tell the I2C layer a new client has arrived */ | 653 | /* Set the device type */ |
644 | if ((err = i2c_attach_client(new_client))) | 654 | data->kind = id->driver_data; |
645 | goto exit_free; | 655 | if (data->kind == adm1032) { |
656 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE)) | ||
657 | new_client->flags &= ~I2C_CLIENT_PEC; | ||
658 | } | ||
646 | 659 | ||
647 | /* Initialize the LM90 chip */ | 660 | /* Initialize the LM90 chip */ |
648 | lm90_init_client(new_client); | 661 | lm90_init_client(new_client); |
649 | 662 | ||
650 | /* Register sysfs hooks */ | 663 | /* Register sysfs hooks */ |
651 | if ((err = sysfs_create_group(&new_client->dev.kobj, &lm90_group))) | 664 | if ((err = sysfs_create_group(&new_client->dev.kobj, &lm90_group))) |
652 | goto exit_detach; | 665 | goto exit_free; |
653 | if (new_client->flags & I2C_CLIENT_PEC) { | 666 | if (new_client->flags & I2C_CLIENT_PEC) { |
654 | if ((err = device_create_file(&new_client->dev, | 667 | if ((err = device_create_file(&new_client->dev, |
655 | &dev_attr_pec))) | 668 | &dev_attr_pec))) |
@@ -672,8 +685,6 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind) | |||
672 | exit_remove_files: | 685 | exit_remove_files: |
673 | sysfs_remove_group(&new_client->dev.kobj, &lm90_group); | 686 | sysfs_remove_group(&new_client->dev.kobj, &lm90_group); |
674 | device_remove_file(&new_client->dev, &dev_attr_pec); | 687 | device_remove_file(&new_client->dev, &dev_attr_pec); |
675 | exit_detach: | ||
676 | i2c_detach_client(new_client); | ||
677 | exit_free: | 688 | exit_free: |
678 | kfree(data); | 689 | kfree(data); |
679 | exit: | 690 | exit: |
@@ -710,10 +721,9 @@ static void lm90_init_client(struct i2c_client *client) | |||
710 | i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1, config); | 721 | i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1, config); |
711 | } | 722 | } |
712 | 723 | ||
713 | static int lm90_detach_client(struct i2c_client *client) | 724 | static int lm90_remove(struct i2c_client *client) |
714 | { | 725 | { |
715 | struct lm90_data *data = i2c_get_clientdata(client); | 726 | struct lm90_data *data = i2c_get_clientdata(client); |
716 | int err; | ||
717 | 727 | ||
718 | hwmon_device_unregister(data->hwmon_dev); | 728 | hwmon_device_unregister(data->hwmon_dev); |
719 | sysfs_remove_group(&client->dev.kobj, &lm90_group); | 729 | sysfs_remove_group(&client->dev.kobj, &lm90_group); |
@@ -722,9 +732,6 @@ static int lm90_detach_client(struct i2c_client *client) | |||
722 | device_remove_file(&client->dev, | 732 | device_remove_file(&client->dev, |
723 | &sensor_dev_attr_temp2_offset.dev_attr); | 733 | &sensor_dev_attr_temp2_offset.dev_attr); |
724 | 734 | ||
725 | if ((err = i2c_detach_client(client))) | ||
726 | return err; | ||
727 | |||
728 | kfree(data); | 735 | kfree(data); |
729 | return 0; | 736 | return 0; |
730 | } | 737 | } |