aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorIra Snyder <iws@ovro.caltech.edu>2009-09-23 16:59:41 -0400
committerJean Delvare <khali@linux-fr.org>2009-09-23 16:59:41 -0400
commit49dc9efed05ad3e49000097ce1ec31cd3bbc909b (patch)
tree6128a0f78cee795c5b1e2273f7c89fc647657b7d /drivers
parent7fa07729e439a6184bd824746d06a49cca553f15 (diff)
hwmon: (adm1031) Add sysfs files for temperature offsets
The ADM1030/ADM1031 chips have temperature offset registers, for both the local and remote temperature sensors. Following the example set forth in the LM90/ADM1032 driver, expose the offset registers to userspace. Signed-off-by: Ira W. Snyder <iws@ovro.caltech.edu> Signed-off-by: Jean Delvare <khali@linux-fr.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/hwmon/adm1031.c40
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
150static int FAN_TO_REG(int reg, int div) 156static 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}
594static 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}
588static ssize_t show_temp_min(struct device *dev, 602static 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}
623static 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}
609static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, 641static 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) \
662static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \ 694static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \
663 show_temp, NULL, offset - 1); \ 695 show_temp, NULL, offset - 1); \
696static SENSOR_DEVICE_ATTR(temp##offset##_offset, S_IRUGO | S_IWUSR, \
697 show_temp_offset, set_temp_offset, offset - 1); \
664static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR, \ 698static 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); \
666static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \ 700static 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));