aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon/it87.c
diff options
context:
space:
mode:
authorJean Delvare <khali@linux-fr.org>2006-08-28 08:23:46 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2006-09-28 18:31:13 -0400
commit17d648bf5786ba5b8cbf7cbd5cb18d3d8d2657ca (patch)
tree8761d44284bbff01c0bd720c6cfd47a42b145978 /drivers/hwmon/it87.c
parent0dd7699ec4b27b3662d8980ff7a309cc81276298 (diff)
it87: Add support for the IT8716F
it87: Add support for the IT8716F The IT8716F is a Super-I/O chip with integrated hardware monitoring functions. It is very similar to the IT8712F, so adding support to the it87 driver was pretty straightforward. The most significant change here is that the IT8716F has 16-bit fan speed counters, so the user no more needs to tweak the fan clock dividers to get the best readings. Userspace support is already in lm_sensors SVN (to be soon released as 2.10.1.) Thanks to Stian Oksavik, Olivier Nicolas, Prakash Punnoor and Juergen Kilb for testing the early versions of this patch. Thanks also to ITE for providing datasheets and answering my questions. Signed-off-by: Jean Delvare <khali@linux-fr.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/hwmon/it87.c')
-rw-r--r--drivers/hwmon/it87.c178
1 files changed, 154 insertions, 24 deletions
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c
index b0ee57492228..e7f14e61d6f2 100644
--- a/drivers/hwmon/it87.c
+++ b/drivers/hwmon/it87.c
@@ -4,6 +4,7 @@
4 4
5 Supports: IT8705F Super I/O chip w/LPC interface 5 Supports: IT8705F Super I/O chip w/LPC interface
6 IT8712F Super I/O chip w/LPC interface & SMBus 6 IT8712F Super I/O chip w/LPC interface & SMBus
7 IT8716F Super I/O chip w/LPC interface
7 Sis950 A clone of the IT8705F 8 Sis950 A clone of the IT8705F
8 9
9 Copyright (C) 2001 Chris Gauthron <chrisg@0-in.com> 10 Copyright (C) 2001 Chris Gauthron <chrisg@0-in.com>
@@ -50,7 +51,7 @@ static unsigned short normal_i2c[] = { 0x2d, I2C_CLIENT_END };
50static unsigned short isa_address; 51static unsigned short isa_address;
51 52
52/* Insmod parameters */ 53/* Insmod parameters */
53I2C_CLIENT_INSMOD_2(it87, it8712); 54I2C_CLIENT_INSMOD_3(it87, it8712, it8716);
54 55
55#define REG 0x2e /* The register to read/write */ 56#define REG 0x2e /* The register to read/write */
56#define DEV 0x07 /* Register: Logical device select */ 57#define DEV 0x07 /* Register: Logical device select */
@@ -101,6 +102,7 @@ superio_exit(void)
101 102
102#define IT8712F_DEVID 0x8712 103#define IT8712F_DEVID 0x8712
103#define IT8705F_DEVID 0x8705 104#define IT8705F_DEVID 0x8705
105#define IT8716F_DEVID 0x8716
104#define IT87_ACT_REG 0x30 106#define IT87_ACT_REG 0x30
105#define IT87_BASE_REG 0x60 107#define IT87_BASE_REG 0x60
106 108
@@ -132,12 +134,18 @@ static u16 chip_type;
132#define IT87_REG_ALARM3 0x03 134#define IT87_REG_ALARM3 0x03
133 135
134#define IT87_REG_VID 0x0a 136#define IT87_REG_VID 0x0a
137/* Warning: register 0x0b is used for something completely different in
138 new chips/revisions. I suspect only 16-bit tachometer mode will work
139 for these. */
135#define IT87_REG_FAN_DIV 0x0b 140#define IT87_REG_FAN_DIV 0x0b
141#define IT87_REG_FAN_16BIT 0x0c
136 142
137/* Monitors: 9 voltage (0 to 7, battery), 3 temp (1 to 3), 3 fan (1 to 3) */ 143/* Monitors: 9 voltage (0 to 7, battery), 3 temp (1 to 3), 3 fan (1 to 3) */
138 144
139#define IT87_REG_FAN(nr) (0x0d + (nr)) 145#define IT87_REG_FAN(nr) (0x0d + (nr))
140#define IT87_REG_FAN_MIN(nr) (0x10 + (nr)) 146#define IT87_REG_FAN_MIN(nr) (0x10 + (nr))
147#define IT87_REG_FANX(nr) (0x18 + (nr))
148#define IT87_REG_FANX_MIN(nr) (0x1b + (nr))
141#define IT87_REG_FAN_MAIN_CTRL 0x13 149#define IT87_REG_FAN_MAIN_CTRL 0x13
142#define IT87_REG_FAN_CTL 0x14 150#define IT87_REG_FAN_CTL 0x14
143#define IT87_REG_PWM(nr) (0x15 + (nr)) 151#define IT87_REG_PWM(nr) (0x15 + (nr))
@@ -169,7 +177,16 @@ static inline u8 FAN_TO_REG(long rpm, int div)
169 254); 177 254);
170} 178}
171 179
180static inline u16 FAN16_TO_REG(long rpm)
181{
182 if (rpm == 0)
183 return 0xffff;
184 return SENSORS_LIMIT((1350000 + rpm) / (rpm * 2), 1, 0xfffe);
185}
186
172#define FAN_FROM_REG(val,div) ((val)==0?-1:(val)==255?0:1350000/((val)*(div))) 187#define FAN_FROM_REG(val,div) ((val)==0?-1:(val)==255?0:1350000/((val)*(div)))
188/* The divider is fixed to 2 in 16-bit mode */
189#define FAN16_FROM_REG(val) ((val)==0?-1:(val)==0xffff?0:1350000/((val)*2))
173 190
174#define TEMP_TO_REG(val) (SENSORS_LIMIT(((val)<0?(((val)-500)/1000):\ 191#define TEMP_TO_REG(val) (SENSORS_LIMIT(((val)<0?(((val)-500)/1000):\
175 ((val)+500)/1000),-128,127)) 192 ((val)+500)/1000),-128,127))
@@ -205,8 +222,8 @@ struct it87_data {
205 u8 in[9]; /* Register value */ 222 u8 in[9]; /* Register value */
206 u8 in_max[9]; /* Register value */ 223 u8 in_max[9]; /* Register value */
207 u8 in_min[9]; /* Register value */ 224 u8 in_min[9]; /* Register value */
208 u8 fan[3]; /* Register value */ 225 u16 fan[3]; /* Register values, possibly combined */
209 u8 fan_min[3]; /* Register value */ 226 u16 fan_min[3]; /* Register values, possibly combined */
210 u8 temp[3]; /* Register value */ 227 u8 temp[3]; /* Register value */
211 u8 temp_high[3]; /* Register value */ 228 u8 temp_high[3]; /* Register value */
212 u8 temp_low[3]; /* Register value */ 229 u8 temp_low[3]; /* Register value */
@@ -657,6 +674,59 @@ show_pwm_offset(1);
657show_pwm_offset(2); 674show_pwm_offset(2);
658show_pwm_offset(3); 675show_pwm_offset(3);
659 676
677/* A different set of callbacks for 16-bit fans */
678static ssize_t show_fan16(struct device *dev, struct device_attribute *attr,
679 char *buf)
680{
681 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
682 int nr = sensor_attr->index;
683 struct it87_data *data = it87_update_device(dev);
684 return sprintf(buf, "%d\n", FAN16_FROM_REG(data->fan[nr]));
685}
686
687static ssize_t show_fan16_min(struct device *dev, struct device_attribute *attr,
688 char *buf)
689{
690 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
691 int nr = sensor_attr->index;
692 struct it87_data *data = it87_update_device(dev);
693 return sprintf(buf, "%d\n", FAN16_FROM_REG(data->fan_min[nr]));
694}
695
696static ssize_t set_fan16_min(struct device *dev, struct device_attribute *attr,
697 const char *buf, size_t count)
698{
699 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
700 int nr = sensor_attr->index;
701 struct i2c_client *client = to_i2c_client(dev);
702 struct it87_data *data = i2c_get_clientdata(client);
703 int val = simple_strtol(buf, NULL, 10);
704
705 mutex_lock(&data->update_lock);
706 data->fan_min[nr] = FAN16_TO_REG(val);
707 it87_write_value(client, IT87_REG_FAN_MIN(nr),
708 data->fan_min[nr] & 0xff);
709 it87_write_value(client, IT87_REG_FANX_MIN(nr),
710 data->fan_min[nr] >> 8);
711 mutex_unlock(&data->update_lock);
712 return count;
713}
714
715/* We want to use the same sysfs file names as 8-bit fans, but we need
716 different variable names, so we have to use SENSOR_ATTR instead of
717 SENSOR_DEVICE_ATTR. */
718#define show_fan16_offset(offset) \
719static struct sensor_device_attribute sensor_dev_attr_fan##offset##_input16 \
720 = SENSOR_ATTR(fan##offset##_input, S_IRUGO, \
721 show_fan16, NULL, offset - 1); \
722static struct sensor_device_attribute sensor_dev_attr_fan##offset##_min16 \
723 = SENSOR_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \
724 show_fan16_min, set_fan16_min, offset - 1)
725
726show_fan16_offset(1);
727show_fan16_offset(2);
728show_fan16_offset(3);
729
660/* Alarms */ 730/* Alarms */
661static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf) 731static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf)
662{ 732{
@@ -721,6 +791,7 @@ static int __init it87_find(unsigned short *address)
721 superio_enter(); 791 superio_enter();
722 chip_type = superio_inw(DEVID); 792 chip_type = superio_inw(DEVID);
723 if (chip_type != IT8712F_DEVID 793 if (chip_type != IT8712F_DEVID
794 && chip_type != IT8716F_DEVID
724 && chip_type != IT8705F_DEVID) 795 && chip_type != IT8705F_DEVID)
725 goto exit; 796 goto exit;
726 797
@@ -800,8 +871,16 @@ static int it87_detect(struct i2c_adapter *adapter, int address, int kind)
800 i = it87_read_value(new_client, IT87_REG_CHIPID); 871 i = it87_read_value(new_client, IT87_REG_CHIPID);
801 if (i == 0x90) { 872 if (i == 0x90) {
802 kind = it87; 873 kind = it87;
803 if ((is_isa) && (chip_type == IT8712F_DEVID)) 874 if (is_isa) {
804 kind = it8712; 875 switch (chip_type) {
876 case IT8712F_DEVID:
877 kind = it8712;
878 break;
879 case IT8716F_DEVID:
880 kind = it8716;
881 break;
882 }
883 }
805 } 884 }
806 else { 885 else {
807 if (kind == 0) 886 if (kind == 0)
@@ -818,6 +897,8 @@ static int it87_detect(struct i2c_adapter *adapter, int address, int kind)
818 name = "it87"; 897 name = "it87";
819 } else if (kind == it8712) { 898 } else if (kind == it8712) {
820 name = "it8712"; 899 name = "it8712";
900 } else if (kind == it8716) {
901 name = "it8716";
821 } 902 }
822 903
823 /* Fill in the remaining client fields and put it into the global list */ 904 /* Fill in the remaining client fields and put it into the global list */
@@ -885,15 +966,41 @@ static int it87_detect(struct i2c_adapter *adapter, int address, int kind)
885 device_create_file(&new_client->dev, &sensor_dev_attr_temp1_type.dev_attr); 966 device_create_file(&new_client->dev, &sensor_dev_attr_temp1_type.dev_attr);
886 device_create_file(&new_client->dev, &sensor_dev_attr_temp2_type.dev_attr); 967 device_create_file(&new_client->dev, &sensor_dev_attr_temp2_type.dev_attr);
887 device_create_file(&new_client->dev, &sensor_dev_attr_temp3_type.dev_attr); 968 device_create_file(&new_client->dev, &sensor_dev_attr_temp3_type.dev_attr);
888 device_create_file(&new_client->dev, &sensor_dev_attr_fan1_input.dev_attr); 969
889 device_create_file(&new_client->dev, &sensor_dev_attr_fan2_input.dev_attr); 970 if (data->type == it8716) { /* 16-bit tachometers */
890 device_create_file(&new_client->dev, &sensor_dev_attr_fan3_input.dev_attr); 971 device_create_file(&new_client->dev,
891 device_create_file(&new_client->dev, &sensor_dev_attr_fan1_min.dev_attr); 972 &sensor_dev_attr_fan1_input16.dev_attr);
892 device_create_file(&new_client->dev, &sensor_dev_attr_fan2_min.dev_attr); 973 device_create_file(&new_client->dev,
893 device_create_file(&new_client->dev, &sensor_dev_attr_fan3_min.dev_attr); 974 &sensor_dev_attr_fan2_input16.dev_attr);
894 device_create_file(&new_client->dev, &sensor_dev_attr_fan1_div.dev_attr); 975 device_create_file(&new_client->dev,
895 device_create_file(&new_client->dev, &sensor_dev_attr_fan2_div.dev_attr); 976 &sensor_dev_attr_fan3_input16.dev_attr);
896 device_create_file(&new_client->dev, &sensor_dev_attr_fan3_div.dev_attr); 977 device_create_file(&new_client->dev,
978 &sensor_dev_attr_fan1_min16.dev_attr);
979 device_create_file(&new_client->dev,
980 &sensor_dev_attr_fan2_min16.dev_attr);
981 device_create_file(&new_client->dev,
982 &sensor_dev_attr_fan3_min16.dev_attr);
983 } else {
984 device_create_file(&new_client->dev,
985 &sensor_dev_attr_fan1_input.dev_attr);
986 device_create_file(&new_client->dev,
987 &sensor_dev_attr_fan2_input.dev_attr);
988 device_create_file(&new_client->dev,
989 &sensor_dev_attr_fan3_input.dev_attr);
990 device_create_file(&new_client->dev,
991 &sensor_dev_attr_fan1_min.dev_attr);
992 device_create_file(&new_client->dev,
993 &sensor_dev_attr_fan2_min.dev_attr);
994 device_create_file(&new_client->dev,
995 &sensor_dev_attr_fan3_min.dev_attr);
996 device_create_file(&new_client->dev,
997 &sensor_dev_attr_fan1_div.dev_attr);
998 device_create_file(&new_client->dev,
999 &sensor_dev_attr_fan2_div.dev_attr);
1000 device_create_file(&new_client->dev,
1001 &sensor_dev_attr_fan3_div.dev_attr);
1002 }
1003
897 device_create_file(&new_client->dev, &dev_attr_alarms); 1004 device_create_file(&new_client->dev, &dev_attr_alarms);
898 if (enable_pwm_interface) { 1005 if (enable_pwm_interface) {
899 device_create_file(&new_client->dev, &sensor_dev_attr_pwm1_enable.dev_attr); 1006 device_create_file(&new_client->dev, &sensor_dev_attr_pwm1_enable.dev_attr);
@@ -904,7 +1011,7 @@ static int it87_detect(struct i2c_adapter *adapter, int address, int kind)
904 device_create_file(&new_client->dev, &sensor_dev_attr_pwm3.dev_attr); 1011 device_create_file(&new_client->dev, &sensor_dev_attr_pwm3.dev_attr);
905 } 1012 }
906 1013
907 if (data->type == it8712) { 1014 if (data->type == it8712 || data->type == it8716) {
908 data->vrm = vid_which_vrm(); 1015 data->vrm = vid_which_vrm();
909 device_create_file_vrm(new_client); 1016 device_create_file_vrm(new_client);
910 device_create_file_vid(new_client); 1017 device_create_file_vid(new_client);
@@ -1069,6 +1176,17 @@ static void it87_init_client(struct i2c_client *client, struct it87_data *data)
1069 it87_write_value(client, IT87_REG_FAN_MAIN_CTRL, data->fan_main_ctrl); 1176 it87_write_value(client, IT87_REG_FAN_MAIN_CTRL, data->fan_main_ctrl);
1070 } 1177 }
1071 1178
1179 /* Set tachometers to 16-bit mode if needed */
1180 if (data->type == it8716) {
1181 tmp = it87_read_value(client, IT87_REG_FAN_16BIT);
1182 if ((tmp & 0x07) != 0x07) {
1183 dev_dbg(&client->dev,
1184 "Setting fan1-3 to 16-bit mode\n");
1185 it87_write_value(client, IT87_REG_FAN_16BIT,
1186 tmp | 0x07);
1187 }
1188 }
1189
1072 /* Set current fan mode registers and the default settings for the 1190 /* Set current fan mode registers and the default settings for the
1073 * other mode registers */ 1191 * other mode registers */
1074 for (i = 0; i < 3; i++) { 1192 for (i = 0; i < 3; i++) {
@@ -1126,10 +1244,17 @@ static struct it87_data *it87_update_device(struct device *dev)
1126 data->in_max[8] = 255; 1244 data->in_max[8] = 255;
1127 1245
1128 for (i = 0; i < 3; i++) { 1246 for (i = 0; i < 3; i++) {
1129 data->fan[i] =
1130 it87_read_value(client, IT87_REG_FAN(i));
1131 data->fan_min[i] = 1247 data->fan_min[i] =
1132 it87_read_value(client, IT87_REG_FAN_MIN(i)); 1248 it87_read_value(client, IT87_REG_FAN_MIN(i));
1249 data->fan[i] = it87_read_value(client,
1250 IT87_REG_FAN(i));
1251 /* Add high byte if in 16-bit mode */
1252 if (data->type == it8716) {
1253 data->fan[i] |= it87_read_value(client,
1254 IT87_REG_FANX(i)) << 8;
1255 data->fan_min[i] |= it87_read_value(client,
1256 IT87_REG_FANX_MIN(i)) << 8;
1257 }
1133 } 1258 }
1134 for (i = 0; i < 3; i++) { 1259 for (i = 0; i < 3; i++) {
1135 data->temp[i] = 1260 data->temp[i] =
@@ -1140,10 +1265,13 @@ static struct it87_data *it87_update_device(struct device *dev)
1140 it87_read_value(client, IT87_REG_TEMP_LOW(i)); 1265 it87_read_value(client, IT87_REG_TEMP_LOW(i));
1141 } 1266 }
1142 1267
1143 i = it87_read_value(client, IT87_REG_FAN_DIV); 1268 /* Newer chips don't have clock dividers */
1144 data->fan_div[0] = i & 0x07; 1269 if (data->type != it8716) {
1145 data->fan_div[1] = (i >> 3) & 0x07; 1270 i = it87_read_value(client, IT87_REG_FAN_DIV);
1146 data->fan_div[2] = (i & 0x40) ? 3 : 1; 1271 data->fan_div[0] = i & 0x07;
1272 data->fan_div[1] = (i >> 3) & 0x07;
1273 data->fan_div[2] = (i & 0x40) ? 3 : 1;
1274 }
1147 1275
1148 data->alarms = 1276 data->alarms =
1149 it87_read_value(client, IT87_REG_ALARM1) | 1277 it87_read_value(client, IT87_REG_ALARM1) |
@@ -1153,9 +1281,11 @@ static struct it87_data *it87_update_device(struct device *dev)
1153 1281
1154 data->sensor = it87_read_value(client, IT87_REG_TEMP_ENABLE); 1282 data->sensor = it87_read_value(client, IT87_REG_TEMP_ENABLE);
1155 /* The 8705 does not have VID capability */ 1283 /* The 8705 does not have VID capability */
1156 if (data->type == it8712) { 1284 if (data->type == it8712 || data->type == it8716) {
1157 data->vid = it87_read_value(client, IT87_REG_VID); 1285 data->vid = it87_read_value(client, IT87_REG_VID);
1158 data->vid &= 0x1f; 1286 /* The older IT8712F revisions had only 5 VID pins,
1287 but we assume it is always safe to read 6 bits. */
1288 data->vid &= 0x3f;
1159 } 1289 }
1160 data->last_updated = jiffies; 1290 data->last_updated = jiffies;
1161 data->valid = 1; 1291 data->valid = 1;
@@ -1194,7 +1324,7 @@ static void __exit sm_it87_exit(void)
1194 1324
1195 1325
1196MODULE_AUTHOR("Chris Gauthron <chrisg@0-in.com>"); 1326MODULE_AUTHOR("Chris Gauthron <chrisg@0-in.com>");
1197MODULE_DESCRIPTION("IT8705F, IT8712F, Sis950 driver"); 1327MODULE_DESCRIPTION("IT8705F/8712F/8716F, SiS950 driver");
1198module_param(update_vbat, bool, 0); 1328module_param(update_vbat, bool, 0);
1199MODULE_PARM_DESC(update_vbat, "Update vbat if set else return powerup value"); 1329MODULE_PARM_DESC(update_vbat, "Update vbat if set else return powerup value");
1200module_param(fix_pwm_polarity, bool, 0); 1330module_param(fix_pwm_polarity, bool, 0);