diff options
Diffstat (limited to 'drivers/hwmon/adm1031.c')
-rw-r--r-- | drivers/hwmon/adm1031.c | 40 |
1 files changed, 40 insertions, 0 deletions
diff --git a/drivers/hwmon/adm1031.c b/drivers/hwmon/adm1031.c index 789441830cd8..56905955352c 100644 --- a/drivers/hwmon/adm1031.c +++ b/drivers/hwmon/adm1031.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #define ADM1031_REG_PWM (0x22) | 37 | #define ADM1031_REG_PWM (0x22) |
38 | #define ADM1031_REG_FAN_MIN(nr) (0x10 + (nr)) | 38 | #define ADM1031_REG_FAN_MIN(nr) (0x10 + (nr)) |
39 | 39 | ||
40 | #define ADM1031_REG_TEMP_OFFSET(nr) (0x0d + (nr)) | ||
40 | #define ADM1031_REG_TEMP_MAX(nr) (0x14 + 4 * (nr)) | 41 | #define ADM1031_REG_TEMP_MAX(nr) (0x14 + 4 * (nr)) |
41 | #define ADM1031_REG_TEMP_MIN(nr) (0x15 + 4 * (nr)) | 42 | #define ADM1031_REG_TEMP_MIN(nr) (0x15 + 4 * (nr)) |
42 | #define ADM1031_REG_TEMP_CRIT(nr) (0x16 + 4 * (nr)) | 43 | #define ADM1031_REG_TEMP_CRIT(nr) (0x16 + 4 * (nr)) |
@@ -93,6 +94,7 @@ struct adm1031_data { | |||
93 | u8 auto_temp_min[3]; | 94 | u8 auto_temp_min[3]; |
94 | u8 auto_temp_off[3]; | 95 | u8 auto_temp_off[3]; |
95 | u8 auto_temp_max[3]; | 96 | u8 auto_temp_max[3]; |
97 | s8 temp_offset[3]; | ||
96 | s8 temp_min[3]; | 98 | s8 temp_min[3]; |
97 | s8 temp_max[3]; | 99 | s8 temp_max[3]; |
98 | s8 temp_crit[3]; | 100 | s8 temp_crit[3]; |
@@ -145,6 +147,10 @@ adm1031_write_value(struct i2c_client *client, u8 reg, unsigned int value) | |||
145 | 147 | ||
146 | #define TEMP_FROM_REG_EXT(val, ext) (TEMP_FROM_REG(val) + (ext) * 125) | 148 | #define TEMP_FROM_REG_EXT(val, ext) (TEMP_FROM_REG(val) + (ext) * 125) |
147 | 149 | ||
150 | #define TEMP_OFFSET_TO_REG(val) (TEMP_TO_REG(val) & 0x8f) | ||
151 | #define TEMP_OFFSET_FROM_REG(val) TEMP_FROM_REG((val) < 0 ? \ | ||
152 | (val) | 0x70 : (val)) | ||
153 | |||
148 | #define FAN_FROM_REG(reg, div) ((reg) ? (11250 * 60) / ((reg) * (div)) : 0) | 154 | #define FAN_FROM_REG(reg, div) ((reg) ? (11250 * 60) / ((reg) * (div)) : 0) |
149 | 155 | ||
150 | static int FAN_TO_REG(int reg, int div) | 156 | static int FAN_TO_REG(int reg, int div) |
@@ -585,6 +591,14 @@ static ssize_t show_temp(struct device *dev, | |||
585 | (((data->ext_temp[nr] >> ((nr - 1) * 3)) & 7)); | 591 | (((data->ext_temp[nr] >> ((nr - 1) * 3)) & 7)); |
586 | return sprintf(buf, "%d\n", TEMP_FROM_REG_EXT(data->temp[nr], ext)); | 592 | return sprintf(buf, "%d\n", TEMP_FROM_REG_EXT(data->temp[nr], ext)); |
587 | } | 593 | } |
594 | static ssize_t show_temp_offset(struct device *dev, | ||
595 | struct device_attribute *attr, char *buf) | ||
596 | { | ||
597 | int nr = to_sensor_dev_attr(attr)->index; | ||
598 | struct adm1031_data *data = adm1031_update_device(dev); | ||
599 | return sprintf(buf, "%d\n", | ||
600 | TEMP_OFFSET_FROM_REG(data->temp_offset[nr])); | ||
601 | } | ||
588 | static ssize_t show_temp_min(struct device *dev, | 602 | static ssize_t show_temp_min(struct device *dev, |
589 | struct device_attribute *attr, char *buf) | 603 | struct device_attribute *attr, char *buf) |
590 | { | 604 | { |
@@ -606,6 +620,24 @@ static ssize_t show_temp_crit(struct device *dev, | |||
606 | struct adm1031_data *data = adm1031_update_device(dev); | 620 | struct adm1031_data *data = adm1031_update_device(dev); |
607 | return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_crit[nr])); | 621 | return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_crit[nr])); |
608 | } | 622 | } |
623 | static ssize_t set_temp_offset(struct device *dev, | ||
624 | struct device_attribute *attr, const char *buf, | ||
625 | size_t count) | ||
626 | { | ||
627 | struct i2c_client *client = to_i2c_client(dev); | ||
628 | struct adm1031_data *data = i2c_get_clientdata(client); | ||
629 | int nr = to_sensor_dev_attr(attr)->index; | ||
630 | int val; | ||
631 | |||
632 | val = simple_strtol(buf, NULL, 10); | ||
633 | val = SENSORS_LIMIT(val, -15000, 15000); | ||
634 | mutex_lock(&data->update_lock); | ||
635 | data->temp_offset[nr] = TEMP_OFFSET_TO_REG(val); | ||
636 | adm1031_write_value(client, ADM1031_REG_TEMP_OFFSET(nr), | ||
637 | data->temp_offset[nr]); | ||
638 | mutex_unlock(&data->update_lock); | ||
639 | return count; | ||
640 | } | ||
609 | static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, | 641 | static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, |
610 | const char *buf, size_t count) | 642 | const char *buf, size_t count) |
611 | { | 643 | { |
@@ -661,6 +693,8 @@ static ssize_t set_temp_crit(struct device *dev, struct device_attribute *attr, | |||
661 | #define temp_reg(offset) \ | 693 | #define temp_reg(offset) \ |
662 | static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \ | 694 | static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \ |
663 | show_temp, NULL, offset - 1); \ | 695 | show_temp, NULL, offset - 1); \ |
696 | static SENSOR_DEVICE_ATTR(temp##offset##_offset, S_IRUGO | S_IWUSR, \ | ||
697 | show_temp_offset, set_temp_offset, offset - 1); \ | ||
664 | static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR, \ | 698 | static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR, \ |
665 | show_temp_min, set_temp_min, offset - 1); \ | 699 | show_temp_min, set_temp_min, offset - 1); \ |
666 | static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \ | 700 | static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \ |
@@ -714,6 +748,7 @@ static struct attribute *adm1031_attributes[] = { | |||
714 | &sensor_dev_attr_pwm1.dev_attr.attr, | 748 | &sensor_dev_attr_pwm1.dev_attr.attr, |
715 | &sensor_dev_attr_auto_fan1_channel.dev_attr.attr, | 749 | &sensor_dev_attr_auto_fan1_channel.dev_attr.attr, |
716 | &sensor_dev_attr_temp1_input.dev_attr.attr, | 750 | &sensor_dev_attr_temp1_input.dev_attr.attr, |
751 | &sensor_dev_attr_temp1_offset.dev_attr.attr, | ||
717 | &sensor_dev_attr_temp1_min.dev_attr.attr, | 752 | &sensor_dev_attr_temp1_min.dev_attr.attr, |
718 | &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, | 753 | &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, |
719 | &sensor_dev_attr_temp1_max.dev_attr.attr, | 754 | &sensor_dev_attr_temp1_max.dev_attr.attr, |
@@ -721,6 +756,7 @@ static struct attribute *adm1031_attributes[] = { | |||
721 | &sensor_dev_attr_temp1_crit.dev_attr.attr, | 756 | &sensor_dev_attr_temp1_crit.dev_attr.attr, |
722 | &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr, | 757 | &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr, |
723 | &sensor_dev_attr_temp2_input.dev_attr.attr, | 758 | &sensor_dev_attr_temp2_input.dev_attr.attr, |
759 | &sensor_dev_attr_temp2_offset.dev_attr.attr, | ||
724 | &sensor_dev_attr_temp2_min.dev_attr.attr, | 760 | &sensor_dev_attr_temp2_min.dev_attr.attr, |
725 | &sensor_dev_attr_temp2_min_alarm.dev_attr.attr, | 761 | &sensor_dev_attr_temp2_min_alarm.dev_attr.attr, |
726 | &sensor_dev_attr_temp2_max.dev_attr.attr, | 762 | &sensor_dev_attr_temp2_max.dev_attr.attr, |
@@ -757,6 +793,7 @@ static struct attribute *adm1031_attributes_opt[] = { | |||
757 | &sensor_dev_attr_pwm2.dev_attr.attr, | 793 | &sensor_dev_attr_pwm2.dev_attr.attr, |
758 | &sensor_dev_attr_auto_fan2_channel.dev_attr.attr, | 794 | &sensor_dev_attr_auto_fan2_channel.dev_attr.attr, |
759 | &sensor_dev_attr_temp3_input.dev_attr.attr, | 795 | &sensor_dev_attr_temp3_input.dev_attr.attr, |
796 | &sensor_dev_attr_temp3_offset.dev_attr.attr, | ||
760 | &sensor_dev_attr_temp3_min.dev_attr.attr, | 797 | &sensor_dev_attr_temp3_min.dev_attr.attr, |
761 | &sensor_dev_attr_temp3_min_alarm.dev_attr.attr, | 798 | &sensor_dev_attr_temp3_min_alarm.dev_attr.attr, |
762 | &sensor_dev_attr_temp3_max.dev_attr.attr, | 799 | &sensor_dev_attr_temp3_max.dev_attr.attr, |
@@ -937,6 +974,9 @@ static struct adm1031_data *adm1031_update_device(struct device *dev) | |||
937 | } | 974 | } |
938 | data->temp[chan] = newh; | 975 | data->temp[chan] = newh; |
939 | 976 | ||
977 | data->temp_offset[chan] = | ||
978 | adm1031_read_value(client, | ||
979 | ADM1031_REG_TEMP_OFFSET(chan)); | ||
940 | data->temp_min[chan] = | 980 | data->temp_min[chan] = |
941 | adm1031_read_value(client, | 981 | adm1031_read_value(client, |
942 | ADM1031_REG_TEMP_MIN(chan)); | 982 | ADM1031_REG_TEMP_MIN(chan)); |