diff options
| -rw-r--r-- | drivers/hwmon/vt8231.c | 186 |
1 files changed, 132 insertions, 54 deletions
diff --git a/drivers/hwmon/vt8231.c b/drivers/hwmon/vt8231.c index 236ccf0e915d..93f93d4fb8ae 100644 --- a/drivers/hwmon/vt8231.c +++ b/drivers/hwmon/vt8231.c | |||
| @@ -451,37 +451,6 @@ define_temperature_sysfs(4); | |||
| 451 | define_temperature_sysfs(5); | 451 | define_temperature_sysfs(5); |
| 452 | define_temperature_sysfs(6); | 452 | define_temperature_sysfs(6); |
| 453 | 453 | ||
| 454 | #define CFG_INFO_TEMP(id) { &sensor_dev_attr_temp##id##_input.dev_attr, \ | ||
| 455 | &sensor_dev_attr_temp##id##_max_hyst.dev_attr, \ | ||
| 456 | &sensor_dev_attr_temp##id##_max.dev_attr } | ||
| 457 | #define CFG_INFO_VOLT(id) { &sensor_dev_attr_in##id##_input.dev_attr, \ | ||
| 458 | &sensor_dev_attr_in##id##_min.dev_attr, \ | ||
| 459 | &sensor_dev_attr_in##id##_max.dev_attr } | ||
| 460 | |||
| 461 | struct str_device_attr_table { | ||
| 462 | struct device_attribute *input; | ||
| 463 | struct device_attribute *min; | ||
| 464 | struct device_attribute *max; | ||
| 465 | }; | ||
| 466 | |||
| 467 | static struct str_device_attr_table cfg_info_temp[] = { | ||
| 468 | { &dev_attr_temp1_input, &dev_attr_temp1_max_hyst, &dev_attr_temp1_max }, | ||
| 469 | CFG_INFO_TEMP(2), | ||
| 470 | CFG_INFO_TEMP(3), | ||
| 471 | CFG_INFO_TEMP(4), | ||
| 472 | CFG_INFO_TEMP(5), | ||
| 473 | CFG_INFO_TEMP(6) | ||
| 474 | }; | ||
| 475 | |||
| 476 | static struct str_device_attr_table cfg_info_volt[] = { | ||
| 477 | CFG_INFO_VOLT(0), | ||
| 478 | CFG_INFO_VOLT(1), | ||
| 479 | CFG_INFO_VOLT(2), | ||
| 480 | CFG_INFO_VOLT(3), | ||
| 481 | CFG_INFO_VOLT(4), | ||
| 482 | { &dev_attr_in5_input, &dev_attr_in5_min, &dev_attr_in5_max } | ||
| 483 | }; | ||
| 484 | |||
| 485 | /* Fans */ | 454 | /* Fans */ |
| 486 | static ssize_t show_fan(struct device *dev, struct device_attribute *attr, | 455 | static ssize_t show_fan(struct device *dev, struct device_attribute *attr, |
| 487 | char *buf) | 456 | char *buf) |
| @@ -585,6 +554,107 @@ static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, | |||
| 585 | 554 | ||
| 586 | static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); | 555 | static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); |
| 587 | 556 | ||
| 557 | static struct attribute *vt8231_attributes_temps[6][4] = { | ||
| 558 | { | ||
| 559 | &dev_attr_temp1_input.attr, | ||
| 560 | &dev_attr_temp1_max_hyst.attr, | ||
| 561 | &dev_attr_temp1_max.attr, | ||
| 562 | NULL | ||
| 563 | }, { | ||
| 564 | &sensor_dev_attr_temp2_input.dev_attr.attr, | ||
| 565 | &sensor_dev_attr_temp2_max_hyst.dev_attr.attr, | ||
| 566 | &sensor_dev_attr_temp2_max.dev_attr.attr, | ||
| 567 | NULL | ||
| 568 | }, { | ||
| 569 | &sensor_dev_attr_temp3_input.dev_attr.attr, | ||
| 570 | &sensor_dev_attr_temp3_max_hyst.dev_attr.attr, | ||
| 571 | &sensor_dev_attr_temp3_max.dev_attr.attr, | ||
| 572 | NULL | ||
| 573 | }, { | ||
| 574 | &sensor_dev_attr_temp4_input.dev_attr.attr, | ||
| 575 | &sensor_dev_attr_temp4_max_hyst.dev_attr.attr, | ||
| 576 | &sensor_dev_attr_temp4_max.dev_attr.attr, | ||
| 577 | NULL | ||
| 578 | }, { | ||
| 579 | &sensor_dev_attr_temp5_input.dev_attr.attr, | ||
| 580 | &sensor_dev_attr_temp5_max_hyst.dev_attr.attr, | ||
| 581 | &sensor_dev_attr_temp5_max.dev_attr.attr, | ||
| 582 | NULL | ||
| 583 | }, { | ||
| 584 | &sensor_dev_attr_temp6_input.dev_attr.attr, | ||
| 585 | &sensor_dev_attr_temp6_max_hyst.dev_attr.attr, | ||
| 586 | &sensor_dev_attr_temp6_max.dev_attr.attr, | ||
| 587 | NULL | ||
| 588 | } | ||
| 589 | }; | ||
| 590 | |||
| 591 | static const struct attribute_group vt8231_group_temps[6] = { | ||
| 592 | { .attrs = vt8231_attributes_temps[0] }, | ||
| 593 | { .attrs = vt8231_attributes_temps[1] }, | ||
| 594 | { .attrs = vt8231_attributes_temps[2] }, | ||
| 595 | { .attrs = vt8231_attributes_temps[3] }, | ||
| 596 | { .attrs = vt8231_attributes_temps[4] }, | ||
| 597 | { .attrs = vt8231_attributes_temps[5] }, | ||
| 598 | }; | ||
| 599 | |||
| 600 | static struct attribute *vt8231_attributes_volts[6][4] = { | ||
| 601 | { | ||
| 602 | &sensor_dev_attr_in0_input.dev_attr.attr, | ||
| 603 | &sensor_dev_attr_in0_min.dev_attr.attr, | ||
| 604 | &sensor_dev_attr_in0_max.dev_attr.attr, | ||
| 605 | NULL | ||
| 606 | }, { | ||
| 607 | &sensor_dev_attr_in1_input.dev_attr.attr, | ||
| 608 | &sensor_dev_attr_in1_min.dev_attr.attr, | ||
| 609 | &sensor_dev_attr_in1_max.dev_attr.attr, | ||
| 610 | NULL | ||
| 611 | }, { | ||
| 612 | &sensor_dev_attr_in2_input.dev_attr.attr, | ||
| 613 | &sensor_dev_attr_in2_min.dev_attr.attr, | ||
| 614 | &sensor_dev_attr_in2_max.dev_attr.attr, | ||
| 615 | NULL | ||
| 616 | }, { | ||
| 617 | &sensor_dev_attr_in3_input.dev_attr.attr, | ||
| 618 | &sensor_dev_attr_in3_min.dev_attr.attr, | ||
| 619 | &sensor_dev_attr_in3_max.dev_attr.attr, | ||
| 620 | NULL | ||
| 621 | }, { | ||
| 622 | &sensor_dev_attr_in4_input.dev_attr.attr, | ||
| 623 | &sensor_dev_attr_in4_min.dev_attr.attr, | ||
| 624 | &sensor_dev_attr_in4_max.dev_attr.attr, | ||
| 625 | NULL | ||
| 626 | }, { | ||
| 627 | &dev_attr_in5_input.attr, | ||
| 628 | &dev_attr_in5_min.attr, | ||
| 629 | &dev_attr_in5_max.attr, | ||
| 630 | NULL | ||
| 631 | } | ||
| 632 | }; | ||
| 633 | |||
| 634 | static const struct attribute_group vt8231_group_volts[6] = { | ||
| 635 | { .attrs = vt8231_attributes_volts[0] }, | ||
| 636 | { .attrs = vt8231_attributes_volts[1] }, | ||
| 637 | { .attrs = vt8231_attributes_volts[2] }, | ||
| 638 | { .attrs = vt8231_attributes_volts[3] }, | ||
| 639 | { .attrs = vt8231_attributes_volts[4] }, | ||
| 640 | { .attrs = vt8231_attributes_volts[5] }, | ||
| 641 | }; | ||
| 642 | |||
| 643 | static struct attribute *vt8231_attributes[] = { | ||
| 644 | &sensor_dev_attr_fan1_input.dev_attr.attr, | ||
| 645 | &sensor_dev_attr_fan2_input.dev_attr.attr, | ||
| 646 | &sensor_dev_attr_fan1_min.dev_attr.attr, | ||
| 647 | &sensor_dev_attr_fan2_min.dev_attr.attr, | ||
| 648 | &sensor_dev_attr_fan1_div.dev_attr.attr, | ||
| 649 | &sensor_dev_attr_fan2_div.dev_attr.attr, | ||
| 650 | &dev_attr_alarms.attr, | ||
| 651 | NULL | ||
| 652 | }; | ||
| 653 | |||
| 654 | static const struct attribute_group vt8231_group = { | ||
| 655 | .attrs = vt8231_attributes, | ||
| 656 | }; | ||
| 657 | |||
| 588 | static struct i2c_driver vt8231_driver = { | 658 | static struct i2c_driver vt8231_driver = { |
| 589 | .driver = { | 659 | .driver = { |
| 590 | .owner = THIS_MODULE, | 660 | .owner = THIS_MODULE, |
| @@ -671,43 +741,43 @@ int vt8231_detect(struct i2c_adapter *adapter) | |||
| 671 | vt8231_init_client(client); | 741 | vt8231_init_client(client); |
| 672 | 742 | ||
| 673 | /* Register sysfs hooks */ | 743 | /* Register sysfs hooks */ |
| 674 | data->class_dev = hwmon_device_register(&client->dev); | 744 | if ((err = sysfs_create_group(&client->dev.kobj, &vt8231_group))) |
| 675 | if (IS_ERR(data->class_dev)) { | ||
| 676 | err = PTR_ERR(data->class_dev); | ||
| 677 | goto exit_detach; | 745 | goto exit_detach; |
| 678 | } | ||
| 679 | 746 | ||
| 680 | /* Must update device information to find out the config field */ | 747 | /* Must update device information to find out the config field */ |
| 681 | data->uch_config = vt8231_read_value(client, VT8231_REG_UCH_CONFIG); | 748 | data->uch_config = vt8231_read_value(client, VT8231_REG_UCH_CONFIG); |
| 682 | 749 | ||
| 683 | for (i = 0; i < ARRAY_SIZE(cfg_info_temp); i++) { | 750 | for (i = 0; i < ARRAY_SIZE(vt8231_group_temps); i++) { |
| 684 | if (ISTEMP(i, data->uch_config)) { | 751 | if (ISTEMP(i, data->uch_config)) { |
| 685 | device_create_file(&client->dev, | 752 | if ((err = sysfs_create_group(&client->dev.kobj, |
| 686 | cfg_info_temp[i].input); | 753 | &vt8231_group_temps[i]))) |
| 687 | device_create_file(&client->dev, cfg_info_temp[i].max); | 754 | goto exit_remove_files; |
| 688 | device_create_file(&client->dev, cfg_info_temp[i].min); | ||
| 689 | } | 755 | } |
| 690 | } | 756 | } |
| 691 | 757 | ||
| 692 | for (i = 0; i < ARRAY_SIZE(cfg_info_volt); i++) { | 758 | for (i = 0; i < ARRAY_SIZE(vt8231_group_volts); i++) { |
| 693 | if (ISVOLT(i, data->uch_config)) { | 759 | if (ISVOLT(i, data->uch_config)) { |
| 694 | device_create_file(&client->dev, | 760 | if ((err = sysfs_create_group(&client->dev.kobj, |
| 695 | cfg_info_volt[i].input); | 761 | &vt8231_group_volts[i]))) |
| 696 | device_create_file(&client->dev, cfg_info_volt[i].max); | 762 | goto exit_remove_files; |
| 697 | device_create_file(&client->dev, cfg_info_volt[i].min); | ||
| 698 | } | 763 | } |
| 699 | } | 764 | } |
| 700 | 765 | ||
| 701 | device_create_file(&client->dev, &sensor_dev_attr_fan1_input.dev_attr); | 766 | data->class_dev = hwmon_device_register(&client->dev); |
| 702 | device_create_file(&client->dev, &sensor_dev_attr_fan2_input.dev_attr); | 767 | if (IS_ERR(data->class_dev)) { |
| 703 | device_create_file(&client->dev, &sensor_dev_attr_fan1_min.dev_attr); | 768 | err = PTR_ERR(data->class_dev); |
| 704 | device_create_file(&client->dev, &sensor_dev_attr_fan2_min.dev_attr); | 769 | goto exit_remove_files; |
| 705 | device_create_file(&client->dev, &sensor_dev_attr_fan1_div.dev_attr); | 770 | } |
| 706 | device_create_file(&client->dev, &sensor_dev_attr_fan2_div.dev_attr); | ||
| 707 | |||
| 708 | device_create_file(&client->dev, &dev_attr_alarms); | ||
| 709 | return 0; | 771 | return 0; |
| 710 | 772 | ||
| 773 | exit_remove_files: | ||
| 774 | for (i = 0; i < ARRAY_SIZE(vt8231_group_volts); i++) | ||
| 775 | sysfs_remove_group(&client->dev.kobj, &vt8231_group_volts[i]); | ||
| 776 | |||
| 777 | for (i = 0; i < ARRAY_SIZE(vt8231_group_temps); i++) | ||
| 778 | sysfs_remove_group(&client->dev.kobj, &vt8231_group_temps[i]); | ||
| 779 | |||
| 780 | sysfs_remove_group(&client->dev.kobj, &vt8231_group); | ||
| 711 | exit_detach: | 781 | exit_detach: |
| 712 | i2c_detach_client(client); | 782 | i2c_detach_client(client); |
| 713 | exit_free: | 783 | exit_free: |
| @@ -720,10 +790,18 @@ exit_release: | |||
| 720 | static int vt8231_detach_client(struct i2c_client *client) | 790 | static int vt8231_detach_client(struct i2c_client *client) |
| 721 | { | 791 | { |
| 722 | struct vt8231_data *data = i2c_get_clientdata(client); | 792 | struct vt8231_data *data = i2c_get_clientdata(client); |
| 723 | int err; | 793 | int err, i; |
| 724 | 794 | ||
| 725 | hwmon_device_unregister(data->class_dev); | 795 | hwmon_device_unregister(data->class_dev); |
| 726 | 796 | ||
| 797 | for (i = 0; i < ARRAY_SIZE(vt8231_group_volts); i++) | ||
| 798 | sysfs_remove_group(&client->dev.kobj, &vt8231_group_volts[i]); | ||
| 799 | |||
| 800 | for (i = 0; i < ARRAY_SIZE(vt8231_group_temps); i++) | ||
| 801 | sysfs_remove_group(&client->dev.kobj, &vt8231_group_temps[i]); | ||
| 802 | |||
| 803 | sysfs_remove_group(&client->dev.kobj, &vt8231_group); | ||
| 804 | |||
| 727 | if ((err = i2c_detach_client(client))) { | 805 | if ((err = i2c_detach_client(client))) { |
| 728 | return err; | 806 | return err; |
| 729 | } | 807 | } |
