diff options
author | Jean Delvare <khali@linux-fr.org> | 2006-08-28 08:37:19 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2006-09-28 18:31:13 -0400 |
commit | 87673dd735b8e089b7f2830edd353aa5f5e743ad (patch) | |
tree | 030b275650c5d8c79285bc3f7b0ba8f1c2cc25b6 /drivers/hwmon/it87.c | |
parent | 8ab4ec3ef45cc2facbe14c733ef7230e7d94fcf2 (diff) |
it87: Add support for the IT8718F
it87: Add support for the IT8718F
The IT8718F is a Super-I/O chip with integrated hardware monitoring
functions. It is very similar to the IT8716F, so adding support to the
it87 driver was pretty straightforward. The most significant difference
is that the IT8718F has up to 8 VID pins, instead of 6 for the older
chips.
For the IT8718F, the VID value can only be read from Super-I/O space.
Userspace support is already in lm_sensors SVN (to be soon released
as 2.10.1.)
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.c | 61 |
1 files changed, 49 insertions, 12 deletions
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index e9ab8a32903b..956cd553c711 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c | |||
@@ -5,6 +5,7 @@ | |||
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 | IT8716F Super I/O chip w/LPC interface |
8 | IT8718F Super I/O chip w/LPC interface | ||
8 | Sis950 A clone of the IT8705F | 9 | Sis950 A clone of the IT8705F |
9 | 10 | ||
10 | Copyright (C) 2001 Chris Gauthron <chrisg@0-in.com> | 11 | Copyright (C) 2001 Chris Gauthron <chrisg@0-in.com> |
@@ -51,12 +52,13 @@ static unsigned short normal_i2c[] = { 0x2d, I2C_CLIENT_END }; | |||
51 | static unsigned short isa_address; | 52 | static unsigned short isa_address; |
52 | 53 | ||
53 | /* Insmod parameters */ | 54 | /* Insmod parameters */ |
54 | I2C_CLIENT_INSMOD_3(it87, it8712, it8716); | 55 | I2C_CLIENT_INSMOD_4(it87, it8712, it8716, it8718); |
55 | 56 | ||
56 | #define REG 0x2e /* The register to read/write */ | 57 | #define REG 0x2e /* The register to read/write */ |
57 | #define DEV 0x07 /* Register: Logical device select */ | 58 | #define DEV 0x07 /* Register: Logical device select */ |
58 | #define VAL 0x2f /* The value to read/write */ | 59 | #define VAL 0x2f /* The value to read/write */ |
59 | #define PME 0x04 /* The device with the fan registers in it */ | 60 | #define PME 0x04 /* The device with the fan registers in it */ |
61 | #define GPIO 0x07 /* The device with the IT8718F VID value in it */ | ||
60 | #define DEVID 0x20 /* Register: Device ID */ | 62 | #define DEVID 0x20 /* Register: Device ID */ |
61 | #define DEVREV 0x22 /* Register: Device Revision */ | 63 | #define DEVREV 0x22 /* Register: Device Revision */ |
62 | 64 | ||
@@ -78,10 +80,10 @@ static int superio_inw(int reg) | |||
78 | } | 80 | } |
79 | 81 | ||
80 | static inline void | 82 | static inline void |
81 | superio_select(void) | 83 | superio_select(int ldn) |
82 | { | 84 | { |
83 | outb(DEV, REG); | 85 | outb(DEV, REG); |
84 | outb(PME, VAL); | 86 | outb(ldn, VAL); |
85 | } | 87 | } |
86 | 88 | ||
87 | static inline void | 89 | static inline void |
@@ -100,21 +102,27 @@ superio_exit(void) | |||
100 | outb(0x02, VAL); | 102 | outb(0x02, VAL); |
101 | } | 103 | } |
102 | 104 | ||
105 | /* Logical device 4 registers */ | ||
103 | #define IT8712F_DEVID 0x8712 | 106 | #define IT8712F_DEVID 0x8712 |
104 | #define IT8705F_DEVID 0x8705 | 107 | #define IT8705F_DEVID 0x8705 |
105 | #define IT8716F_DEVID 0x8716 | 108 | #define IT8716F_DEVID 0x8716 |
109 | #define IT8718F_DEVID 0x8718 | ||
106 | #define IT87_ACT_REG 0x30 | 110 | #define IT87_ACT_REG 0x30 |
107 | #define IT87_BASE_REG 0x60 | 111 | #define IT87_BASE_REG 0x60 |
108 | 112 | ||
113 | /* Logical device 7 registers (IT8712F and later) */ | ||
114 | #define IT87_SIO_PINX2_REG 0x2c /* Pin selection */ | ||
115 | #define IT87_SIO_VID_REG 0xfc /* VID value */ | ||
116 | |||
109 | /* Update battery voltage after every reading if true */ | 117 | /* Update battery voltage after every reading if true */ |
110 | static int update_vbat; | 118 | static int update_vbat; |
111 | 119 | ||
112 | /* Not all BIOSes properly configure the PWM registers */ | 120 | /* Not all BIOSes properly configure the PWM registers */ |
113 | static int fix_pwm_polarity; | 121 | static int fix_pwm_polarity; |
114 | 122 | ||
115 | /* Chip Type */ | 123 | /* Values read from Super-I/O config space */ |
116 | |||
117 | static u16 chip_type; | 124 | static u16 chip_type; |
125 | static u8 vid_value; | ||
118 | 126 | ||
119 | /* Many IT87 constants specified below */ | 127 | /* Many IT87 constants specified below */ |
120 | 128 | ||
@@ -133,6 +141,8 @@ static u16 chip_type; | |||
133 | #define IT87_REG_ALARM2 0x02 | 141 | #define IT87_REG_ALARM2 0x02 |
134 | #define IT87_REG_ALARM3 0x03 | 142 | #define IT87_REG_ALARM3 0x03 |
135 | 143 | ||
144 | /* The IT8718F has the VID value in a different register, in Super-I/O | ||
145 | configuration space. */ | ||
136 | #define IT87_REG_VID 0x0a | 146 | #define IT87_REG_VID 0x0a |
137 | /* Warning: register 0x0b is used for something completely different in | 147 | /* Warning: register 0x0b is used for something completely different in |
138 | new chips/revisions. I suspect only 16-bit tachometer mode will work | 148 | new chips/revisions. I suspect only 16-bit tachometer mode will work |
@@ -793,10 +803,11 @@ static int __init it87_find(unsigned short *address) | |||
793 | chip_type = superio_inw(DEVID); | 803 | chip_type = superio_inw(DEVID); |
794 | if (chip_type != IT8712F_DEVID | 804 | if (chip_type != IT8712F_DEVID |
795 | && chip_type != IT8716F_DEVID | 805 | && chip_type != IT8716F_DEVID |
806 | && chip_type != IT8718F_DEVID | ||
796 | && chip_type != IT8705F_DEVID) | 807 | && chip_type != IT8705F_DEVID) |
797 | goto exit; | 808 | goto exit; |
798 | 809 | ||
799 | superio_select(); | 810 | superio_select(PME); |
800 | if (!(superio_inb(IT87_ACT_REG) & 0x01)) { | 811 | if (!(superio_inb(IT87_ACT_REG) & 0x01)) { |
801 | pr_info("it87: Device not activated, skipping\n"); | 812 | pr_info("it87: Device not activated, skipping\n"); |
802 | goto exit; | 813 | goto exit; |
@@ -812,6 +823,21 @@ static int __init it87_find(unsigned short *address) | |||
812 | pr_info("it87: Found IT%04xF chip at 0x%x, revision %d\n", | 823 | pr_info("it87: Found IT%04xF chip at 0x%x, revision %d\n", |
813 | chip_type, *address, superio_inb(DEVREV) & 0x0f); | 824 | chip_type, *address, superio_inb(DEVREV) & 0x0f); |
814 | 825 | ||
826 | /* Read GPIO config and VID value from LDN 7 (GPIO) */ | ||
827 | if (chip_type != IT8705F_DEVID) { | ||
828 | int reg; | ||
829 | |||
830 | superio_select(GPIO); | ||
831 | if (chip_type == it8718) | ||
832 | vid_value = superio_inb(IT87_SIO_VID_REG); | ||
833 | |||
834 | reg = superio_inb(IT87_SIO_PINX2_REG); | ||
835 | if (reg & (1 << 0)) | ||
836 | pr_info("it87: in3 is VCC (+5V)\n"); | ||
837 | if (reg & (1 << 1)) | ||
838 | pr_info("it87: in7 is VCCH (+5V Stand-By)\n"); | ||
839 | } | ||
840 | |||
815 | exit: | 841 | exit: |
816 | superio_exit(); | 842 | superio_exit(); |
817 | return err; | 843 | return err; |
@@ -880,6 +906,9 @@ static int it87_detect(struct i2c_adapter *adapter, int address, int kind) | |||
880 | case IT8716F_DEVID: | 906 | case IT8716F_DEVID: |
881 | kind = it8716; | 907 | kind = it8716; |
882 | break; | 908 | break; |
909 | case IT8718F_DEVID: | ||
910 | kind = it8718; | ||
911 | break; | ||
883 | } | 912 | } |
884 | } | 913 | } |
885 | } | 914 | } |
@@ -900,6 +929,8 @@ static int it87_detect(struct i2c_adapter *adapter, int address, int kind) | |||
900 | name = "it8712"; | 929 | name = "it8712"; |
901 | } else if (kind == it8716) { | 930 | } else if (kind == it8716) { |
902 | name = "it8716"; | 931 | name = "it8716"; |
932 | } else if (kind == it8718) { | ||
933 | name = "it8718"; | ||
903 | } | 934 | } |
904 | 935 | ||
905 | /* Fill in the remaining client fields and put it into the global list */ | 936 | /* Fill in the remaining client fields and put it into the global list */ |
@@ -969,7 +1000,8 @@ static int it87_detect(struct i2c_adapter *adapter, int address, int kind) | |||
969 | device_create_file(&new_client->dev, &sensor_dev_attr_temp3_type.dev_attr); | 1000 | device_create_file(&new_client->dev, &sensor_dev_attr_temp3_type.dev_attr); |
970 | 1001 | ||
971 | /* Do not create fan files for disabled fans */ | 1002 | /* Do not create fan files for disabled fans */ |
972 | if (data->type == it8716) { /* 16-bit tachometers */ | 1003 | if (data->type == it8716 || data->type == it8718) { |
1004 | /* 16-bit tachometers */ | ||
973 | if (data->has_fan & (1 << 0)) { | 1005 | if (data->has_fan & (1 << 0)) { |
974 | device_create_file(&new_client->dev, | 1006 | device_create_file(&new_client->dev, |
975 | &sensor_dev_attr_fan1_input16.dev_attr); | 1007 | &sensor_dev_attr_fan1_input16.dev_attr); |
@@ -989,6 +1021,7 @@ static int it87_detect(struct i2c_adapter *adapter, int address, int kind) | |||
989 | &sensor_dev_attr_fan3_min16.dev_attr); | 1021 | &sensor_dev_attr_fan3_min16.dev_attr); |
990 | } | 1022 | } |
991 | } else { | 1023 | } else { |
1024 | /* 8-bit tachometers with clock divider */ | ||
992 | if (data->has_fan & (1 << 0)) { | 1025 | if (data->has_fan & (1 << 0)) { |
993 | device_create_file(&new_client->dev, | 1026 | device_create_file(&new_client->dev, |
994 | &sensor_dev_attr_fan1_input.dev_attr); | 1027 | &sensor_dev_attr_fan1_input.dev_attr); |
@@ -1025,8 +1058,11 @@ static int it87_detect(struct i2c_adapter *adapter, int address, int kind) | |||
1025 | device_create_file(&new_client->dev, &sensor_dev_attr_pwm3.dev_attr); | 1058 | device_create_file(&new_client->dev, &sensor_dev_attr_pwm3.dev_attr); |
1026 | } | 1059 | } |
1027 | 1060 | ||
1028 | if (data->type == it8712 || data->type == it8716) { | 1061 | if (data->type == it8712 || data->type == it8716 |
1062 | || data->type == it8718) { | ||
1029 | data->vrm = vid_which_vrm(); | 1063 | data->vrm = vid_which_vrm(); |
1064 | /* VID reading from Super-I/O config space if available */ | ||
1065 | data->vid = vid_value; | ||
1030 | device_create_file_vrm(new_client); | 1066 | device_create_file_vrm(new_client); |
1031 | device_create_file_vid(new_client); | 1067 | device_create_file_vid(new_client); |
1032 | } | 1068 | } |
@@ -1192,7 +1228,7 @@ static void it87_init_client(struct i2c_client *client, struct it87_data *data) | |||
1192 | data->has_fan = (data->fan_main_ctrl >> 4) & 0x07; | 1228 | data->has_fan = (data->fan_main_ctrl >> 4) & 0x07; |
1193 | 1229 | ||
1194 | /* Set tachometers to 16-bit mode if needed */ | 1230 | /* Set tachometers to 16-bit mode if needed */ |
1195 | if (data->type == it8716) { | 1231 | if (data->type == it8716 || data->type == it8718) { |
1196 | tmp = it87_read_value(client, IT87_REG_FAN_16BIT); | 1232 | tmp = it87_read_value(client, IT87_REG_FAN_16BIT); |
1197 | if (~tmp & 0x07 & data->has_fan) { | 1233 | if (~tmp & 0x07 & data->has_fan) { |
1198 | dev_dbg(&client->dev, | 1234 | dev_dbg(&client->dev, |
@@ -1265,7 +1301,7 @@ static struct it87_data *it87_update_device(struct device *dev) | |||
1265 | data->fan[i] = it87_read_value(client, | 1301 | data->fan[i] = it87_read_value(client, |
1266 | IT87_REG_FAN(i)); | 1302 | IT87_REG_FAN(i)); |
1267 | /* Add high byte if in 16-bit mode */ | 1303 | /* Add high byte if in 16-bit mode */ |
1268 | if (data->type == it8716) { | 1304 | if (data->type == it8716 || data->type == it8718) { |
1269 | data->fan[i] |= it87_read_value(client, | 1305 | data->fan[i] |= it87_read_value(client, |
1270 | IT87_REG_FANX(i)) << 8; | 1306 | IT87_REG_FANX(i)) << 8; |
1271 | data->fan_min[i] |= it87_read_value(client, | 1307 | data->fan_min[i] |= it87_read_value(client, |
@@ -1282,7 +1318,8 @@ static struct it87_data *it87_update_device(struct device *dev) | |||
1282 | } | 1318 | } |
1283 | 1319 | ||
1284 | /* Newer chips don't have clock dividers */ | 1320 | /* Newer chips don't have clock dividers */ |
1285 | if ((data->has_fan & 0x07) && data->type != it8716) { | 1321 | if ((data->has_fan & 0x07) && data->type != it8716 |
1322 | && data->type != it8718) { | ||
1286 | i = it87_read_value(client, IT87_REG_FAN_DIV); | 1323 | i = it87_read_value(client, IT87_REG_FAN_DIV); |
1287 | data->fan_div[0] = i & 0x07; | 1324 | data->fan_div[0] = i & 0x07; |
1288 | data->fan_div[1] = (i >> 3) & 0x07; | 1325 | data->fan_div[1] = (i >> 3) & 0x07; |
@@ -1340,7 +1377,7 @@ static void __exit sm_it87_exit(void) | |||
1340 | 1377 | ||
1341 | 1378 | ||
1342 | MODULE_AUTHOR("Chris Gauthron <chrisg@0-in.com>"); | 1379 | MODULE_AUTHOR("Chris Gauthron <chrisg@0-in.com>"); |
1343 | MODULE_DESCRIPTION("IT8705F/8712F/8716F, SiS950 driver"); | 1380 | MODULE_DESCRIPTION("IT8705F/8712F/8716F/8718F, SiS950 driver"); |
1344 | module_param(update_vbat, bool, 0); | 1381 | module_param(update_vbat, bool, 0); |
1345 | MODULE_PARM_DESC(update_vbat, "Update vbat if set else return powerup value"); | 1382 | MODULE_PARM_DESC(update_vbat, "Update vbat if set else return powerup value"); |
1346 | module_param(fix_pwm_polarity, bool, 0); | 1383 | module_param(fix_pwm_polarity, bool, 0); |