diff options
| -rw-r--r-- | Documentation/hwmon/it87 | 40 | ||||
| -rw-r--r-- | drivers/hwmon/Kconfig | 4 | ||||
| -rw-r--r-- | drivers/hwmon/it87.c | 178 |
3 files changed, 185 insertions, 37 deletions
diff --git a/Documentation/hwmon/it87 b/Documentation/hwmon/it87 index 9555be1ed999..aff680784222 100644 --- a/Documentation/hwmon/it87 +++ b/Documentation/hwmon/it87 | |||
| @@ -13,6 +13,11 @@ Supported chips: | |||
| 13 | from Super I/O config space (8 I/O ports) | 13 | from Super I/O config space (8 I/O ports) |
| 14 | Datasheet: Publicly available at the ITE website | 14 | Datasheet: Publicly available at the ITE website |
| 15 | http://www.ite.com.tw/ | 15 | http://www.ite.com.tw/ |
| 16 | * IT8716F | ||
| 17 | Prefix: 'it8716' | ||
| 18 | Addresses scanned: from Super I/O config space (8 I/O ports) | ||
| 19 | Datasheet: Publicly available at the ITE website | ||
| 20 | http://www.ite.com.tw/product_info/file/pc/IT8716F_V0.3.ZIP | ||
| 16 | * SiS950 [clone of IT8705F] | 21 | * SiS950 [clone of IT8705F] |
| 17 | Prefix: 'it87' | 22 | Prefix: 'it87' |
| 18 | Addresses scanned: from Super I/O config space (8 I/O ports) | 23 | Addresses scanned: from Super I/O config space (8 I/O ports) |
| @@ -43,26 +48,39 @@ Module Parameters | |||
| 43 | Description | 48 | Description |
| 44 | ----------- | 49 | ----------- |
| 45 | 50 | ||
| 46 | This driver implements support for the IT8705F, IT8712F and SiS950 chips. | 51 | This driver implements support for the IT8705F, IT8712F, IT8716F and |
| 47 | 52 | SiS950 chips. | |
| 48 | This driver also supports IT8712F, which adds SMBus access, and a VID | ||
| 49 | input, used to report the Vcore voltage of the Pentium processor. | ||
| 50 | The IT8712F additionally features VID inputs. | ||
| 51 | 53 | ||
| 52 | These chips are 'Super I/O chips', supporting floppy disks, infrared ports, | 54 | These chips are 'Super I/O chips', supporting floppy disks, infrared ports, |
| 53 | joysticks and other miscellaneous stuff. For hardware monitoring, they | 55 | joysticks and other miscellaneous stuff. For hardware monitoring, they |
| 54 | include an 'environment controller' with 3 temperature sensors, 3 fan | 56 | include an 'environment controller' with 3 temperature sensors, 3 fan |
| 55 | rotation speed sensors, 8 voltage sensors, and associated alarms. | 57 | rotation speed sensors, 8 voltage sensors, and associated alarms. |
| 56 | 58 | ||
| 59 | The IT8712F and IT8716F additionally feature VID inputs, used to report | ||
| 60 | the Vcore voltage of the processor. The early IT8712F have 5 VID pins, | ||
| 61 | the IT8716F and late IT8712F have 6. They are shared with other functions | ||
| 62 | though, so the functionality may not be available on a given system. | ||
| 63 | The driver dumbly assume it is there. | ||
| 64 | |||
| 65 | The IT8716F and later IT8712F revisions have support for 2 additional | ||
| 66 | fans. They are not yet supported by the driver. | ||
| 67 | |||
| 68 | The IT8716F and late IT8712F and IT8705F also have optional 16-bit | ||
| 69 | tachometer counters for fans 1 to 3. This is better (no more fan | ||
| 70 | clock divider mess) but not compatible with the older chips and | ||
| 71 | revisions. For now, the driver only uses the 16-bit mode on the | ||
| 72 | IT8716F. | ||
| 73 | |||
| 57 | Temperatures are measured in degrees Celsius. An alarm is triggered once | 74 | Temperatures are measured in degrees Celsius. An alarm is triggered once |
| 58 | when the Overtemperature Shutdown limit is crossed. | 75 | when the Overtemperature Shutdown limit is crossed. |
| 59 | 76 | ||
| 60 | Fan rotation speeds are reported in RPM (rotations per minute). An alarm is | 77 | Fan rotation speeds are reported in RPM (rotations per minute). An alarm is |
| 61 | triggered if the rotation speed has dropped below a programmable limit. Fan | 78 | triggered if the rotation speed has dropped below a programmable limit. When |
| 62 | readings can be divided by a programmable divider (1, 2, 4 or 8) to give the | 79 | 16-bit tachometer counters aren't used, fan readings can be divided by |
| 63 | readings more range or accuracy. Not all RPM values can accurately be | 80 | a programmable divider (1, 2, 4 or 8) to give the readings more range or |
| 64 | represented, so some rounding is done. With a divider of 2, the lowest | 81 | accuracy. With a divider of 2, the lowest representable value is around |
| 65 | representable value is around 2600 RPM. | 82 | 2600 RPM. Not all RPM values can accurately be represented, so some rounding |
| 83 | is done. | ||
| 66 | 84 | ||
| 67 | Voltage sensors (also known as IN sensors) report their values in volts. An | 85 | Voltage sensors (also known as IN sensors) report their values in volts. An |
| 68 | alarm is triggered if the voltage has crossed a programmable minimum or | 86 | alarm is triggered if the voltage has crossed a programmable minimum or |
| @@ -71,7 +89,7 @@ zero'; this is important for negative voltage measurements. All voltage | |||
| 71 | inputs can measure voltages between 0 and 4.08 volts, with a resolution of | 89 | inputs can measure voltages between 0 and 4.08 volts, with a resolution of |
| 72 | 0.016 volt. The battery voltage in8 does not have limit registers. | 90 | 0.016 volt. The battery voltage in8 does not have limit registers. |
| 73 | 91 | ||
| 74 | The VID lines (IT8712F only) encode the core voltage value: the voltage | 92 | The VID lines (IT8712F/IT8716F) encode the core voltage value: the voltage |
| 75 | level your processor should work with. This is hardcoded by the mainboard | 93 | level your processor should work with. This is hardcoded by the mainboard |
| 76 | and/or processor itself. It is a value in volts. | 94 | and/or processor itself. It is a value in volts. |
| 77 | 95 | ||
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 0e31a0c496e8..cefb1adf4534 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig | |||
| @@ -186,8 +186,8 @@ config SENSORS_IT87 | |||
| 186 | select I2C_ISA | 186 | select I2C_ISA |
| 187 | select HWMON_VID | 187 | select HWMON_VID |
| 188 | help | 188 | help |
| 189 | If you say yes here you get support for ITE IT87xx sensor chips | 189 | If you say yes here you get support for ITE IT8705F, IT8712F and |
| 190 | and clones: SiS960. | 190 | IT8716F sensor chips, and the SiS960 clone. |
| 191 | 191 | ||
| 192 | This driver can also be built as a module. If so, the module | 192 | This driver can also be built as a module. If so, the module |
| 193 | will be called it87. | 193 | will be called it87. |
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 }; | |||
| 50 | static unsigned short isa_address; | 51 | static unsigned short isa_address; |
| 51 | 52 | ||
| 52 | /* Insmod parameters */ | 53 | /* Insmod parameters */ |
| 53 | I2C_CLIENT_INSMOD_2(it87, it8712); | 54 | I2C_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 | ||
| 180 | static 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); | |||
| 657 | show_pwm_offset(2); | 674 | show_pwm_offset(2); |
| 658 | show_pwm_offset(3); | 675 | show_pwm_offset(3); |
| 659 | 676 | ||
| 677 | /* A different set of callbacks for 16-bit fans */ | ||
| 678 | static 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 | |||
| 687 | static 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 | |||
| 696 | static 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) \ | ||
| 719 | static struct sensor_device_attribute sensor_dev_attr_fan##offset##_input16 \ | ||
| 720 | = SENSOR_ATTR(fan##offset##_input, S_IRUGO, \ | ||
| 721 | show_fan16, NULL, offset - 1); \ | ||
| 722 | static 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 | |||
| 726 | show_fan16_offset(1); | ||
| 727 | show_fan16_offset(2); | ||
| 728 | show_fan16_offset(3); | ||
| 729 | |||
| 660 | /* Alarms */ | 730 | /* Alarms */ |
| 661 | static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf) | 731 | static 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 | ||
| 1196 | MODULE_AUTHOR("Chris Gauthron <chrisg@0-in.com>"); | 1326 | MODULE_AUTHOR("Chris Gauthron <chrisg@0-in.com>"); |
| 1197 | MODULE_DESCRIPTION("IT8705F, IT8712F, Sis950 driver"); | 1327 | MODULE_DESCRIPTION("IT8705F/8712F/8716F, SiS950 driver"); |
| 1198 | module_param(update_vbat, bool, 0); | 1328 | module_param(update_vbat, bool, 0); |
| 1199 | MODULE_PARM_DESC(update_vbat, "Update vbat if set else return powerup value"); | 1329 | MODULE_PARM_DESC(update_vbat, "Update vbat if set else return powerup value"); |
| 1200 | module_param(fix_pwm_polarity, bool, 0); | 1330 | module_param(fix_pwm_polarity, bool, 0); |
