aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon/pmbus
diff options
context:
space:
mode:
authorGuenter Roeck <linux@roeck-us.net>2013-01-20 13:05:55 -0500
committerGuenter Roeck <linux@roeck-us.net>2013-02-06 12:58:01 -0500
commit663834f3b796c0a118b84cf18c759f2c2aa537b6 (patch)
tree9494bd7ad43778efe7aa21a70cd84a98b4958300 /drivers/hwmon/pmbus
parent0328461ea954cab13956aedb97f9686bfdfdf2a5 (diff)
hwmon: (pmbus) Improve boolean handling
Boolean handling depends on storing the sensor data index in sensor_device_attr as part of the index variable. This limits the number of sensor attributes to 256, and means the sensor sequence number actually has to be maintained to be able to access sensor data from boolean functions. Rework the code to store sensor pointers in the pmbus_boolean data structure directly. With this approach, the number of supportable sensors is now unlimited. Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Diffstat (limited to 'drivers/hwmon/pmbus')
-rw-r--r--drivers/hwmon/pmbus/pmbus_core.c161
1 files changed, 74 insertions, 87 deletions
diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
index 0f51cd66ecfd..d1792d7195bf 100644
--- a/drivers/hwmon/pmbus/pmbus_core.c
+++ b/drivers/hwmon/pmbus/pmbus_core.c
@@ -98,7 +98,11 @@ struct pmbus_sensor {
98struct pmbus_boolean { 98struct pmbus_boolean {
99 char name[PMBUS_NAME_SIZE]; /* sysfs boolean name */ 99 char name[PMBUS_NAME_SIZE]; /* sysfs boolean name */
100 struct sensor_device_attribute attribute; 100 struct sensor_device_attribute attribute;
101 struct pmbus_sensor *s1;
102 struct pmbus_sensor *s2;
101}; 103};
104#define to_pmbus_boolean(_attr) \
105 container_of(_attr, struct pmbus_boolean, attribute)
102 106
103struct pmbus_label { 107struct pmbus_label {
104 char name[PMBUS_NAME_SIZE]; /* sysfs label name */ 108 char name[PMBUS_NAME_SIZE]; /* sysfs label name */
@@ -673,25 +677,20 @@ static u16 pmbus_data2reg(struct pmbus_data *data,
673 677
674/* 678/*
675 * Return boolean calculated from converted data. 679 * Return boolean calculated from converted data.
676 * <index> defines a status register index and mask, and optionally 680 * <index> defines a status register index and mask.
677 * two sensor indexes. 681 * The mask is in the lower 8 bits, the register index is in bits 8..23.
678 * The upper half-word references the two sensors,
679 * two sensor indices.
680 * The upper half-word references the two optional sensors,
681 * the lower half word references status register and mask.
682 * The function returns true if (status[reg] & mask) is true and,
683 * if specified, if v1 >= v2.
684 * To determine if an object exceeds upper limits, specify <v, limit>.
685 * To determine if an object exceeds lower limits, specify <limit, v>.
686 * 682 *
687 * For booleans created with pmbus_add_boolean_reg(), only the lower 16 bits of 683 * The associated pmbus_boolean structure contains optional pointers to two
688 * index are set. s1 and s2 (the sensor index values) are zero in this case. 684 * sensor attributes. If specified, those attributes are compared against each
689 * The function returns true if (status[reg] & mask) is true. 685 * other to determine if a limit has been exceeded.
690 * 686 *
691 * If the boolean was created with pmbus_add_boolean_cmp(), a comparison against 687 * If the sensor attribute pointers are NULL, the function returns true if
692 * a specified limit has to be performed to determine the boolean result. 688 * (status[reg] & mask) is true.
689 *
690 * If sensor attribute pointers are provided, a comparison against a specified
691 * limit has to be performed to determine the boolean result.
693 * In this case, the function returns true if v1 >= v2 (where v1 and v2 are 692 * In this case, the function returns true if v1 >= v2 (where v1 and v2 are
694 * sensor values referenced by sensor indices s1 and s2). 693 * sensor values referenced by sensor attribute pointers s1 and s2).
695 * 694 *
696 * To determine if an object exceeds upper limits, specify <s1,s2> = <v,limit>. 695 * To determine if an object exceeds upper limits, specify <s1,s2> = <v,limit>.
697 * To determine if an object exceeds lower limits, specify <s1,s2> = <limit,v>. 696 * To determine if an object exceeds lower limits, specify <s1,s2> = <limit,v>.
@@ -699,11 +698,12 @@ static u16 pmbus_data2reg(struct pmbus_data *data,
699 * If a negative value is stored in any of the referenced registers, this value 698 * If a negative value is stored in any of the referenced registers, this value
700 * reflects an error code which will be returned. 699 * reflects an error code which will be returned.
701 */ 700 */
702static int pmbus_get_boolean(struct pmbus_data *data, int index) 701static int pmbus_get_boolean(struct pmbus_data *data, struct pmbus_boolean *b,
702 int index)
703{ 703{
704 u8 s1 = (index >> 24) & 0xff; 704 struct pmbus_sensor *s1 = b->s1;
705 u8 s2 = (index >> 16) & 0xff; 705 struct pmbus_sensor *s2 = b->s2;
706 u8 reg = (index >> 8) & 0xff; 706 u16 reg = (index >> 8) & 0xffff;
707 u8 mask = index & 0xff; 707 u8 mask = index & 0xff;
708 int ret, status; 708 int ret, status;
709 u8 regval; 709 u8 regval;
@@ -713,21 +713,21 @@ static int pmbus_get_boolean(struct pmbus_data *data, int index)
713 return status; 713 return status;
714 714
715 regval = status & mask; 715 regval = status & mask;
716 if (!s1 && !s2) 716 if (!s1 && !s2) {
717 ret = !!regval; 717 ret = !!regval;
718 else { 718 } else if (!s1 || !s2) {
719 BUG();
720 return 0;
721 } else {
719 long v1, v2; 722 long v1, v2;
720 struct pmbus_sensor *sensor1, *sensor2;
721 723
722 sensor1 = &data->sensors[s1]; 724 if (s1->data < 0)
723 if (sensor1->data < 0) 725 return s1->data;
724 return sensor1->data; 726 if (s2->data < 0)
725 sensor2 = &data->sensors[s2]; 727 return s2->data;
726 if (sensor2->data < 0)
727 return sensor2->data;
728 728
729 v1 = pmbus_reg2data(data, sensor1); 729 v1 = pmbus_reg2data(data, s1);
730 v2 = pmbus_reg2data(data, sensor2); 730 v2 = pmbus_reg2data(data, s2);
731 ret = !!(regval && v1 >= v2); 731 ret = !!(regval && v1 >= v2);
732 } 732 }
733 return ret; 733 return ret;
@@ -737,10 +737,11 @@ static ssize_t pmbus_show_boolean(struct device *dev,
737 struct device_attribute *da, char *buf) 737 struct device_attribute *da, char *buf)
738{ 738{
739 struct sensor_device_attribute *attr = to_sensor_dev_attr(da); 739 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
740 struct pmbus_boolean *boolean = to_pmbus_boolean(attr);
740 struct pmbus_data *data = pmbus_update_device(dev); 741 struct pmbus_data *data = pmbus_update_device(dev);
741 int val; 742 int val;
742 743
743 val = pmbus_get_boolean(data, attr->index); 744 val = pmbus_get_boolean(data, boolean, attr->index);
744 if (val < 0) 745 if (val < 0)
745 return val; 746 return val;
746 return snprintf(buf, PAGE_SIZE, "%d\n", val); 747 return snprintf(buf, PAGE_SIZE, "%d\n", val);
@@ -829,7 +830,9 @@ static void pmbus_attr_init(struct sensor_device_attribute *a,
829 830
830static int pmbus_add_boolean(struct pmbus_data *data, 831static int pmbus_add_boolean(struct pmbus_data *data,
831 const char *name, const char *type, int seq, 832 const char *name, const char *type, int seq,
832 int idx) 833 struct pmbus_sensor *s1,
834 struct pmbus_sensor *s2,
835 u16 reg, u8 mask)
833{ 836{
834 struct pmbus_boolean *boolean; 837 struct pmbus_boolean *boolean;
835 struct sensor_device_attribute *a; 838 struct sensor_device_attribute *a;
@@ -844,32 +847,20 @@ static int pmbus_add_boolean(struct pmbus_data *data,
844 847
845 snprintf(boolean->name, sizeof(boolean->name), "%s%d_%s", 848 snprintf(boolean->name, sizeof(boolean->name), "%s%d_%s",
846 name, seq, type); 849 name, seq, type);
850 boolean->s1 = s1;
851 boolean->s2 = s2;
847 pmbus_attr_init(a, boolean->name, S_IRUGO, pmbus_show_boolean, NULL, 852 pmbus_attr_init(a, boolean->name, S_IRUGO, pmbus_show_boolean, NULL,
848 idx); 853 (reg << 8) | mask);
849 data->attributes[data->num_attributes++] = &a->dev_attr.attr; 854 data->attributes[data->num_attributes++] = &a->dev_attr.attr;
850 855
851 return 0; 856 return 0;
852} 857}
853 858
854static int pmbus_add_boolean_reg(struct pmbus_data *data, 859static struct pmbus_sensor *pmbus_add_sensor(struct pmbus_data *data,
855 const char *name, const char *type, 860 const char *name, const char *type,
856 int seq, int reg, int bit) 861 int seq, int page, int reg,
857{ 862 enum pmbus_sensor_classes class,
858 return pmbus_add_boolean(data, name, type, seq, (reg << 8) | bit); 863 bool update, bool readonly)
859}
860
861static int pmbus_add_boolean_cmp(struct pmbus_data *data,
862 const char *name, const char *type,
863 int seq, int i1, int i2, int reg, int mask)
864{
865 return pmbus_add_boolean(data, name, type, seq,
866 (i1 << 24) | (i2 << 16) | (reg << 8) | mask);
867}
868
869static void pmbus_add_sensor(struct pmbus_data *data,
870 const char *name, const char *type, int seq,
871 int page, int reg, enum pmbus_sensor_classes class,
872 bool update, bool readonly)
873{ 864{
874 struct pmbus_sensor *sensor; 865 struct pmbus_sensor *sensor;
875 struct sensor_device_attribute *a; 866 struct sensor_device_attribute *a;
@@ -892,6 +883,8 @@ static void pmbus_add_sensor(struct pmbus_data *data,
892 883
893 data->attributes[data->num_attributes++] = &a->dev_attr.attr; 884 data->attributes[data->num_attributes++] = &a->dev_attr.attr;
894 data->num_sensors++; 885 data->num_sensors++;
886
887 return sensor;
895} 888}
896 889
897static int pmbus_add_label(struct pmbus_data *data, 890static int pmbus_add_label(struct pmbus_data *data,
@@ -1023,38 +1016,31 @@ static int pmbus_add_limit_attrs(struct i2c_client *client,
1023 struct pmbus_data *data, 1016 struct pmbus_data *data,
1024 const struct pmbus_driver_info *info, 1017 const struct pmbus_driver_info *info,
1025 const char *name, int index, int page, 1018 const char *name, int index, int page,
1026 int cbase, 1019 struct pmbus_sensor *base,
1027 const struct pmbus_sensor_attr *attr) 1020 const struct pmbus_sensor_attr *attr)
1028{ 1021{
1029 const struct pmbus_limit_attr *l = attr->limit; 1022 const struct pmbus_limit_attr *l = attr->limit;
1030 int nlimit = attr->nlimit; 1023 int nlimit = attr->nlimit;
1031 int have_alarm = 0; 1024 int have_alarm = 0;
1032 int i, cindex; 1025 int i, ret;
1033 int ret; 1026 struct pmbus_sensor *curr;
1034 1027
1035 for (i = 0; i < nlimit; i++) { 1028 for (i = 0; i < nlimit; i++) {
1036 if (pmbus_check_word_register(client, page, l->reg)) { 1029 if (pmbus_check_word_register(client, page, l->reg)) {
1037 cindex = data->num_sensors; 1030 curr = pmbus_add_sensor(data, name, l->attr, index,
1038 pmbus_add_sensor(data, name, l->attr, index, page, 1031 page, l->reg, attr->class,
1039 l->reg, attr->class, 1032 attr->update || l->update,
1040 attr->update || l->update, 1033 false);
1041 false);
1042 if (l->sbit && (info->func[page] & attr->sfunc)) { 1034 if (l->sbit && (info->func[page] & attr->sfunc)) {
1043 if (attr->compare) { 1035 ret = pmbus_add_boolean(data, name,
1044 ret = pmbus_add_boolean_cmp(data, name, 1036 l->alarm, index,
1045 l->alarm, index, 1037 attr->compare ? l->low ? curr : base
1046 l->low ? cindex : cbase, 1038 : NULL,
1047 l->low ? cbase : cindex, 1039 attr->compare ? l->low ? base : curr
1048 attr->sbase + page, l->sbit); 1040 : NULL,
1049 if (ret) 1041 attr->sbase + page, l->sbit);
1050 return ret; 1042 if (ret)
1051 } else { 1043 return ret;
1052 ret = pmbus_add_boolean_reg(data, name,
1053 l->alarm, index,
1054 attr->sbase + page, l->sbit);
1055 if (ret)
1056 return ret;
1057 }
1058 have_alarm = 1; 1044 have_alarm = 1;
1059 } 1045 }
1060 } 1046 }
@@ -1070,7 +1056,7 @@ static int pmbus_add_sensor_attrs_one(struct i2c_client *client,
1070 int index, int page, 1056 int index, int page,
1071 const struct pmbus_sensor_attr *attr) 1057 const struct pmbus_sensor_attr *attr)
1072{ 1058{
1073 int cbase = data->num_sensors; 1059 struct pmbus_sensor *base;
1074 int ret; 1060 int ret;
1075 1061
1076 if (attr->label) { 1062 if (attr->label) {
@@ -1079,11 +1065,11 @@ static int pmbus_add_sensor_attrs_one(struct i2c_client *client,
1079 if (ret) 1065 if (ret)
1080 return ret; 1066 return ret;
1081 } 1067 }
1082 pmbus_add_sensor(data, name, "input", index, page, attr->reg, 1068 base = pmbus_add_sensor(data, name, "input", index, page, attr->reg,
1083 attr->class, true, true); 1069 attr->class, true, true);
1084 if (attr->sfunc) { 1070 if (attr->sfunc) {
1085 ret = pmbus_add_limit_attrs(client, data, info, name, 1071 ret = pmbus_add_limit_attrs(client, data, info, name,
1086 index, page, cbase, attr); 1072 index, page, base, attr);
1087 if (ret < 0) 1073 if (ret < 0)
1088 return ret; 1074 return ret;
1089 /* 1075 /*
@@ -1094,9 +1080,10 @@ static int pmbus_add_sensor_attrs_one(struct i2c_client *client,
1094 if (!ret && attr->gbit && 1080 if (!ret && attr->gbit &&
1095 pmbus_check_byte_register(client, page, 1081 pmbus_check_byte_register(client, page,
1096 PMBUS_STATUS_BYTE)) { 1082 PMBUS_STATUS_BYTE)) {
1097 ret = pmbus_add_boolean_reg(data, name, "alarm", index, 1083 ret = pmbus_add_boolean(data, name, "alarm", index,
1098 PB_STATUS_BASE + page, 1084 NULL, NULL,
1099 attr->gbit); 1085 PB_STATUS_BASE + page,
1086 attr->gbit);
1100 if (ret) 1087 if (ret)
1101 return ret; 1088 return ret;
1102 } 1089 }
@@ -1635,13 +1622,13 @@ static int pmbus_add_fan_attributes(struct i2c_client *client,
1635 base = PB_STATUS_FAN34_BASE + page; 1622 base = PB_STATUS_FAN34_BASE + page;
1636 else 1623 else
1637 base = PB_STATUS_FAN_BASE + page; 1624 base = PB_STATUS_FAN_BASE + page;
1638 ret = pmbus_add_boolean_reg(data, "fan", 1625 ret = pmbus_add_boolean(data, "fan",
1639 "alarm", index, base, 1626 "alarm", index, NULL, NULL, base,
1640 PB_FAN_FAN1_WARNING >> (f & 1)); 1627 PB_FAN_FAN1_WARNING >> (f & 1));
1641 if (ret) 1628 if (ret)
1642 return ret; 1629 return ret;
1643 ret = pmbus_add_boolean_reg(data, "fan", 1630 ret = pmbus_add_boolean(data, "fan",
1644 "fault", index, base, 1631 "fault", index, NULL, NULL, base,
1645 PB_FAN_FAN1_FAULT >> (f & 1)); 1632 PB_FAN_FAN1_FAULT >> (f & 1));
1646 if (ret) 1633 if (ret)
1647 return ret; 1634 return ret;