diff options
| -rw-r--r-- | drivers/hwmon/smsc47m192.c | 102 |
1 files changed, 46 insertions, 56 deletions
diff --git a/drivers/hwmon/smsc47m192.c b/drivers/hwmon/smsc47m192.c index 3c9db6598ba7..8bb5cb532d4d 100644 --- a/drivers/hwmon/smsc47m192.c +++ b/drivers/hwmon/smsc47m192.c | |||
| @@ -96,7 +96,6 @@ static inline int TEMP_FROM_REG(s8 val) | |||
| 96 | } | 96 | } |
| 97 | 97 | ||
| 98 | struct smsc47m192_data { | 98 | struct smsc47m192_data { |
| 99 | struct i2c_client client; | ||
| 100 | struct device *hwmon_dev; | 99 | struct device *hwmon_dev; |
| 101 | struct mutex update_lock; | 100 | struct mutex update_lock; |
| 102 | char valid; /* !=0 if following fields are valid */ | 101 | char valid; /* !=0 if following fields are valid */ |
| @@ -114,18 +113,29 @@ struct smsc47m192_data { | |||
| 114 | u8 vrm; | 113 | u8 vrm; |
| 115 | }; | 114 | }; |
| 116 | 115 | ||
| 117 | static int smsc47m192_attach_adapter(struct i2c_adapter *adapter); | 116 | static int smsc47m192_probe(struct i2c_client *client, |
| 118 | static int smsc47m192_detect(struct i2c_adapter *adapter, int address, | 117 | const struct i2c_device_id *id); |
| 119 | int kind); | 118 | static int smsc47m192_detect(struct i2c_client *client, int kind, |
| 120 | static int smsc47m192_detach_client(struct i2c_client *client); | 119 | struct i2c_board_info *info); |
| 120 | static int smsc47m192_remove(struct i2c_client *client); | ||
| 121 | static struct smsc47m192_data *smsc47m192_update_device(struct device *dev); | 121 | static struct smsc47m192_data *smsc47m192_update_device(struct device *dev); |
| 122 | 122 | ||
| 123 | static const struct i2c_device_id smsc47m192_id[] = { | ||
| 124 | { "smsc47m192", smsc47m192 }, | ||
| 125 | { } | ||
| 126 | }; | ||
| 127 | MODULE_DEVICE_TABLE(i2c, smsc47m192_id); | ||
| 128 | |||
| 123 | static struct i2c_driver smsc47m192_driver = { | 129 | static struct i2c_driver smsc47m192_driver = { |
| 130 | .class = I2C_CLASS_HWMON, | ||
| 124 | .driver = { | 131 | .driver = { |
| 125 | .name = "smsc47m192", | 132 | .name = "smsc47m192", |
| 126 | }, | 133 | }, |
| 127 | .attach_adapter = smsc47m192_attach_adapter, | 134 | .probe = smsc47m192_probe, |
| 128 | .detach_client = smsc47m192_detach_client, | 135 | .remove = smsc47m192_remove, |
| 136 | .id_table = smsc47m192_id, | ||
| 137 | .detect = smsc47m192_detect, | ||
| 138 | .address_data = &addr_data, | ||
| 129 | }; | 139 | }; |
| 130 | 140 | ||
| 131 | /* Voltages */ | 141 | /* Voltages */ |
| @@ -440,17 +450,6 @@ static const struct attribute_group smsc47m192_group_in4 = { | |||
| 440 | .attrs = smsc47m192_attributes_in4, | 450 | .attrs = smsc47m192_attributes_in4, |
| 441 | }; | 451 | }; |
| 442 | 452 | ||
| 443 | /* This function is called when: | ||
| 444 | * smsc47m192_driver is inserted (when this module is loaded), for each | ||
| 445 | available adapter | ||
| 446 | * when a new adapter is inserted (and smsc47m192_driver is still present) */ | ||
| 447 | static int smsc47m192_attach_adapter(struct i2c_adapter *adapter) | ||
| 448 | { | ||
| 449 | if (!(adapter->class & I2C_CLASS_HWMON)) | ||
| 450 | return 0; | ||
| 451 | return i2c_probe(adapter, &addr_data, smsc47m192_detect); | ||
| 452 | } | ||
| 453 | |||
| 454 | static void smsc47m192_init_client(struct i2c_client *client) | 453 | static void smsc47m192_init_client(struct i2c_client *client) |
| 455 | { | 454 | { |
| 456 | int i; | 455 | int i; |
| @@ -481,31 +480,15 @@ static void smsc47m192_init_client(struct i2c_client *client) | |||
| 481 | } | 480 | } |
| 482 | } | 481 | } |
| 483 | 482 | ||
| 484 | /* This function is called by i2c_probe */ | 483 | /* Return 0 if detection is successful, -ENODEV otherwise */ |
| 485 | static int smsc47m192_detect(struct i2c_adapter *adapter, int address, | 484 | static int smsc47m192_detect(struct i2c_client *client, int kind, |
| 486 | int kind) | 485 | struct i2c_board_info *info) |
| 487 | { | 486 | { |
| 488 | struct i2c_client *client; | 487 | struct i2c_adapter *adapter = client->adapter; |
| 489 | struct smsc47m192_data *data; | 488 | int version; |
| 490 | int err = 0; | ||
| 491 | int version, config; | ||
| 492 | 489 | ||
| 493 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | 490 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) |
| 494 | goto exit; | 491 | return -ENODEV; |
| 495 | |||
| 496 | if (!(data = kzalloc(sizeof(struct smsc47m192_data), GFP_KERNEL))) { | ||
| 497 | err = -ENOMEM; | ||
| 498 | goto exit; | ||
| 499 | } | ||
| 500 | |||
| 501 | client = &data->client; | ||
| 502 | i2c_set_clientdata(client, data); | ||
| 503 | client->addr = address; | ||
| 504 | client->adapter = adapter; | ||
| 505 | client->driver = &smsc47m192_driver; | ||
| 506 | |||
| 507 | if (kind == 0) | ||
| 508 | kind = smsc47m192; | ||
| 509 | 492 | ||
| 510 | /* Detection criteria from sensors_detect script */ | 493 | /* Detection criteria from sensors_detect script */ |
| 511 | if (kind < 0) { | 494 | if (kind < 0) { |
| @@ -523,26 +506,39 @@ static int smsc47m192_detect(struct i2c_adapter *adapter, int address, | |||
| 523 | } else { | 506 | } else { |
| 524 | dev_dbg(&adapter->dev, | 507 | dev_dbg(&adapter->dev, |
| 525 | "SMSC47M192 detection failed at 0x%02x\n", | 508 | "SMSC47M192 detection failed at 0x%02x\n", |
| 526 | address); | 509 | client->addr); |
| 527 | goto exit_free; | 510 | return -ENODEV; |
| 528 | } | 511 | } |
| 529 | } | 512 | } |
| 530 | 513 | ||
| 531 | /* Fill in the remaining client fields and put into the global list */ | 514 | strlcpy(info->type, "smsc47m192", I2C_NAME_SIZE); |
| 532 | strlcpy(client->name, "smsc47m192", I2C_NAME_SIZE); | 515 | |
| 516 | return 0; | ||
| 517 | } | ||
| 518 | |||
| 519 | static int smsc47m192_probe(struct i2c_client *client, | ||
| 520 | const struct i2c_device_id *id) | ||
| 521 | { | ||
| 522 | struct smsc47m192_data *data; | ||
| 523 | int config; | ||
| 524 | int err; | ||
| 525 | |||
| 526 | data = kzalloc(sizeof(struct smsc47m192_data), GFP_KERNEL); | ||
| 527 | if (!data) { | ||
| 528 | err = -ENOMEM; | ||
| 529 | goto exit; | ||
| 530 | } | ||
| 531 | |||
| 532 | i2c_set_clientdata(client, data); | ||
| 533 | data->vrm = vid_which_vrm(); | 533 | data->vrm = vid_which_vrm(); |
| 534 | mutex_init(&data->update_lock); | 534 | mutex_init(&data->update_lock); |
| 535 | 535 | ||
| 536 | /* Tell the I2C layer a new client has arrived */ | ||
| 537 | if ((err = i2c_attach_client(client))) | ||
| 538 | goto exit_free; | ||
| 539 | |||
| 540 | /* Initialize the SMSC47M192 chip */ | 536 | /* Initialize the SMSC47M192 chip */ |
| 541 | smsc47m192_init_client(client); | 537 | smsc47m192_init_client(client); |
| 542 | 538 | ||
| 543 | /* Register sysfs hooks */ | 539 | /* Register sysfs hooks */ |
| 544 | if ((err = sysfs_create_group(&client->dev.kobj, &smsc47m192_group))) | 540 | if ((err = sysfs_create_group(&client->dev.kobj, &smsc47m192_group))) |
| 545 | goto exit_detach; | 541 | goto exit_free; |
| 546 | 542 | ||
| 547 | /* Pin 110 is either in4 (+12V) or VID4 */ | 543 | /* Pin 110 is either in4 (+12V) or VID4 */ |
| 548 | config = i2c_smbus_read_byte_data(client, SMSC47M192_REG_CONFIG); | 544 | config = i2c_smbus_read_byte_data(client, SMSC47M192_REG_CONFIG); |
| @@ -563,26 +559,20 @@ static int smsc47m192_detect(struct i2c_adapter *adapter, int address, | |||
| 563 | exit_remove_files: | 559 | exit_remove_files: |
| 564 | sysfs_remove_group(&client->dev.kobj, &smsc47m192_group); | 560 | sysfs_remove_group(&client->dev.kobj, &smsc47m192_group); |
| 565 | sysfs_remove_group(&client->dev.kobj, &smsc47m192_group_in4); | 561 | sysfs_remove_group(&client->dev.kobj, &smsc47m192_group_in4); |
| 566 | exit_detach: | ||
| 567 | i2c_detach_client(client); | ||
| 568 | exit_free: | 562 | exit_free: |
| 569 | kfree(data); | 563 | kfree(data); |
| 570 | exit: | 564 | exit: |
| 571 | return err; | 565 | return err; |
| 572 | } | 566 | } |
| 573 | 567 | ||
| 574 | static int smsc47m192_detach_client(struct i2c_client *client) | 568 | static int smsc47m192_remove(struct i2c_client *client) |
| 575 | { | 569 | { |
| 576 | struct smsc47m192_data *data = i2c_get_clientdata(client); | 570 | struct smsc47m192_data *data = i2c_get_clientdata(client); |
| 577 | int err; | ||
| 578 | 571 | ||
| 579 | hwmon_device_unregister(data->hwmon_dev); | 572 | hwmon_device_unregister(data->hwmon_dev); |
| 580 | sysfs_remove_group(&client->dev.kobj, &smsc47m192_group); | 573 | sysfs_remove_group(&client->dev.kobj, &smsc47m192_group); |
| 581 | sysfs_remove_group(&client->dev.kobj, &smsc47m192_group_in4); | 574 | sysfs_remove_group(&client->dev.kobj, &smsc47m192_group_in4); |
| 582 | 575 | ||
| 583 | if ((err = i2c_detach_client(client))) | ||
| 584 | return err; | ||
| 585 | |||
| 586 | kfree(data); | 576 | kfree(data); |
| 587 | 577 | ||
| 588 | return 0; | 578 | return 0; |
