diff options
author | Hans de Goede <hdegoede@redhat.com> | 2009-12-09 14:36:01 -0500 |
---|---|---|
committer | Jean Delvare <khali@linux-fr.org> | 2009-12-09 14:36:01 -0500 |
commit | 7669896f499e1bce5cfb38f2685ff583ecdb24dd (patch) | |
tree | ac73a6c61327d36518ebbe9625620de974fa878e /drivers | |
parent | fc16c56e694d361388bae701894fd719dbc0f7eb (diff) |
hwmon: (f71882fg) Add support for the f71889fg (version 2)
This adds support for the Fintek f71889fg to the f71882fg driver,
many thanks to Gerd v. Egidy for providing (remote) access to a
machine which such an ic.
Note that this bit of the patch:
- val = SENSORS_LIMIT(val, 0, 255);
+
+ if (data->type == f71889fg)
+ val = SENSORS_LIMIT(val, -128, 127);
+ else
+ val = SENSORS_LIMIT(val, 0, 127);
Changes behaviour for already supported models, the new behaviour is correct
as the already supported models have bit 7 of the involved registers fixed at
0, so the previous behaviour which allowed setting temp zone limits > 127
was not correct.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Jean Delvare <khali@linux-fr.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/hwmon/Kconfig | 6 | ||||
-rw-r--r-- | drivers/hwmon/f71882fg.c | 86 |
2 files changed, 71 insertions, 21 deletions
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index dd6939370f75..edf8febb5bc4 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig | |||
@@ -305,12 +305,12 @@ config SENSORS_F71805F | |||
305 | will be called f71805f. | 305 | will be called f71805f. |
306 | 306 | ||
307 | config SENSORS_F71882FG | 307 | config SENSORS_F71882FG |
308 | tristate "Fintek F71858FG, F71862FG, F71882FG and F8000" | 308 | tristate "Fintek F71858FG, F71862FG, F71882FG, F71889FG and F8000" |
309 | depends on EXPERIMENTAL | 309 | depends on EXPERIMENTAL |
310 | help | 310 | help |
311 | If you say yes here you get support for hardware monitoring | 311 | If you say yes here you get support for hardware monitoring |
312 | features of the Fintek F71858FG, F71862FG/71863FG, F71882FG/F71883FG | 312 | features of the Fintek F71858FG, F71862FG/71863FG, F71882FG/F71883FG, |
313 | and F8000 Super-I/O chips. | 313 | F71889FG and F8000 Super-I/O chips. |
314 | 314 | ||
315 | This driver can also be built as a module. If so, the module | 315 | This driver can also be built as a module. If so, the module |
316 | will be called f71882fg. | 316 | will be called f71882fg. |
diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index 3a695f06905e..a95fa4256caa 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c | |||
@@ -48,6 +48,7 @@ | |||
48 | #define SIO_F71858_ID 0x0507 /* Chipset ID */ | 48 | #define SIO_F71858_ID 0x0507 /* Chipset ID */ |
49 | #define SIO_F71862_ID 0x0601 /* Chipset ID */ | 49 | #define SIO_F71862_ID 0x0601 /* Chipset ID */ |
50 | #define SIO_F71882_ID 0x0541 /* Chipset ID */ | 50 | #define SIO_F71882_ID 0x0541 /* Chipset ID */ |
51 | #define SIO_F71889_ID 0x0723 /* Chipset ID */ | ||
51 | #define SIO_F8000_ID 0x0581 /* Chipset ID */ | 52 | #define SIO_F8000_ID 0x0581 /* Chipset ID */ |
52 | 53 | ||
53 | #define REGION_LENGTH 8 | 54 | #define REGION_LENGTH 8 |
@@ -95,12 +96,13 @@ static unsigned short force_id; | |||
95 | module_param(force_id, ushort, 0); | 96 | module_param(force_id, ushort, 0); |
96 | MODULE_PARM_DESC(force_id, "Override the detected device ID"); | 97 | MODULE_PARM_DESC(force_id, "Override the detected device ID"); |
97 | 98 | ||
98 | enum chips { f71858fg, f71862fg, f71882fg, f8000 }; | 99 | enum chips { f71858fg, f71862fg, f71882fg, f71889fg, f8000 }; |
99 | 100 | ||
100 | static const char *f71882fg_names[] = { | 101 | static const char *f71882fg_names[] = { |
101 | "f71858fg", | 102 | "f71858fg", |
102 | "f71862fg", | 103 | "f71862fg", |
103 | "f71882fg", | 104 | "f71882fg", |
105 | "f71889fg", | ||
104 | "f8000", | 106 | "f8000", |
105 | }; | 107 | }; |
106 | 108 | ||
@@ -155,7 +157,7 @@ struct f71882fg_data { | |||
155 | u8 pwm_auto_point_hyst[2]; | 157 | u8 pwm_auto_point_hyst[2]; |
156 | u8 pwm_auto_point_mapping[4]; | 158 | u8 pwm_auto_point_mapping[4]; |
157 | u8 pwm_auto_point_pwm[4][5]; | 159 | u8 pwm_auto_point_pwm[4][5]; |
158 | u8 pwm_auto_point_temp[4][4]; | 160 | s8 pwm_auto_point_temp[4][4]; |
159 | }; | 161 | }; |
160 | 162 | ||
161 | /* Sysfs in */ | 163 | /* Sysfs in */ |
@@ -945,7 +947,7 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev) | |||
945 | /* Update once every 60 seconds */ | 947 | /* Update once every 60 seconds */ |
946 | if ( time_after(jiffies, data->last_limits + 60 * HZ ) || | 948 | if ( time_after(jiffies, data->last_limits + 60 * HZ ) || |
947 | !data->valid) { | 949 | !data->valid) { |
948 | if (data->type == f71882fg) { | 950 | if (data->type == f71882fg || data->type == f71889fg) { |
949 | data->in1_max = | 951 | data->in1_max = |
950 | f71882fg_read8(data, F71882FG_REG_IN1_HIGH); | 952 | f71882fg_read8(data, F71882FG_REG_IN1_HIGH); |
951 | data->in_beep = | 953 | data->in_beep = |
@@ -967,7 +969,8 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev) | |||
967 | F71882FG_REG_TEMP_HYST(1)); | 969 | F71882FG_REG_TEMP_HYST(1)); |
968 | } | 970 | } |
969 | 971 | ||
970 | if (data->type == f71862fg || data->type == f71882fg) { | 972 | if (data->type == f71862fg || data->type == f71882fg || |
973 | data->type == f71889fg) { | ||
971 | data->fan_beep = f71882fg_read8(data, | 974 | data->fan_beep = f71882fg_read8(data, |
972 | F71882FG_REG_FAN_BEEP); | 975 | F71882FG_REG_FAN_BEEP); |
973 | data->temp_beep = f71882fg_read8(data, | 976 | data->temp_beep = f71882fg_read8(data, |
@@ -977,15 +980,33 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev) | |||
977 | data->temp_type[2] = (reg & 0x04) ? 2 : 4; | 980 | data->temp_type[2] = (reg & 0x04) ? 2 : 4; |
978 | data->temp_type[3] = (reg & 0x08) ? 2 : 4; | 981 | data->temp_type[3] = (reg & 0x08) ? 2 : 4; |
979 | } | 982 | } |
980 | reg2 = f71882fg_read8(data, F71882FG_REG_PECI); | 983 | /* Determine temp index 1 sensor type */ |
981 | if ((reg2 & 0x03) == 0x01) | 984 | if (data->type == f71889fg) { |
982 | data->temp_type[1] = 6 /* PECI */; | 985 | reg2 = f71882fg_read8(data, F71882FG_REG_START); |
983 | else if ((reg2 & 0x03) == 0x02) | 986 | switch ((reg2 & 0x60) >> 5) { |
984 | data->temp_type[1] = 5 /* AMDSI */; | 987 | case 0x00: /* BJT / Thermistor */ |
985 | else if (data->type == f71862fg || data->type == f71882fg) | 988 | data->temp_type[1] = (reg & 0x02) ? 2 : 4; |
986 | data->temp_type[1] = (reg & 0x02) ? 2 : 4; | 989 | break; |
987 | else | 990 | case 0x01: /* AMDSI */ |
988 | data->temp_type[1] = 2; /* Only supports BJT */ | 991 | data->temp_type[1] = 5; |
992 | break; | ||
993 | case 0x02: /* PECI */ | ||
994 | case 0x03: /* Ibex Peak ?? Report as PECI for now */ | ||
995 | data->temp_type[1] = 6; | ||
996 | break; | ||
997 | } | ||
998 | } else { | ||
999 | reg2 = f71882fg_read8(data, F71882FG_REG_PECI); | ||
1000 | if ((reg2 & 0x03) == 0x01) | ||
1001 | data->temp_type[1] = 6; /* PECI */ | ||
1002 | else if ((reg2 & 0x03) == 0x02) | ||
1003 | data->temp_type[1] = 5; /* AMDSI */ | ||
1004 | else if (data->type == f71862fg || | ||
1005 | data->type == f71882fg) | ||
1006 | data->temp_type[1] = (reg & 0x02) ? 2 : 4; | ||
1007 | else /* f71858fg and f8000 only support BJT */ | ||
1008 | data->temp_type[1] = 2; | ||
1009 | } | ||
989 | 1010 | ||
990 | data->pwm_enable = f71882fg_read8(data, | 1011 | data->pwm_enable = f71882fg_read8(data, |
991 | F71882FG_REG_PWM_ENABLE); | 1012 | F71882FG_REG_PWM_ENABLE); |
@@ -1062,7 +1083,7 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev) | |||
1062 | if (data->type == f8000) | 1083 | if (data->type == f8000) |
1063 | data->fan[3] = f71882fg_read16(data, | 1084 | data->fan[3] = f71882fg_read16(data, |
1064 | F71882FG_REG_FAN(3)); | 1085 | F71882FG_REG_FAN(3)); |
1065 | if (data->type == f71882fg) | 1086 | if (data->type == f71882fg || data->type == f71889fg) |
1066 | data->in_status = f71882fg_read8(data, | 1087 | data->in_status = f71882fg_read8(data, |
1067 | F71882FG_REG_IN_STATUS); | 1088 | F71882FG_REG_IN_STATUS); |
1068 | for (nr = 0; nr < nr_ins; nr++) | 1089 | for (nr = 0; nr < nr_ins; nr++) |
@@ -1780,7 +1801,11 @@ static ssize_t store_pwm_auto_point_temp(struct device *dev, | |||
1780 | int pwm = to_sensor_dev_attr_2(devattr)->index; | 1801 | int pwm = to_sensor_dev_attr_2(devattr)->index; |
1781 | int point = to_sensor_dev_attr_2(devattr)->nr; | 1802 | int point = to_sensor_dev_attr_2(devattr)->nr; |
1782 | long val = simple_strtol(buf, NULL, 10) / 1000; | 1803 | long val = simple_strtol(buf, NULL, 10) / 1000; |
1783 | val = SENSORS_LIMIT(val, 0, 255); | 1804 | |
1805 | if (data->type == f71889fg) | ||
1806 | val = SENSORS_LIMIT(val, -128, 127); | ||
1807 | else | ||
1808 | val = SENSORS_LIMIT(val, 0, 127); | ||
1784 | 1809 | ||
1785 | mutex_lock(&data->update_lock); | 1810 | mutex_lock(&data->update_lock); |
1786 | f71882fg_write8(data, F71882FG_REG_POINT_TEMP(pwm, point), val); | 1811 | f71882fg_write8(data, F71882FG_REG_POINT_TEMP(pwm, point), val); |
@@ -1871,6 +1896,7 @@ static int __devinit f71882fg_probe(struct platform_device *pdev) | |||
1871 | ARRAY_SIZE(f71858fg_in_temp_attr)); | 1896 | ARRAY_SIZE(f71858fg_in_temp_attr)); |
1872 | break; | 1897 | break; |
1873 | case f71882fg: | 1898 | case f71882fg: |
1899 | case f71889fg: | ||
1874 | err = f71882fg_create_sysfs_files(pdev, | 1900 | err = f71882fg_create_sysfs_files(pdev, |
1875 | fxxxx_in1_alarm_attr, | 1901 | fxxxx_in1_alarm_attr, |
1876 | ARRAY_SIZE(fxxxx_in1_alarm_attr)); | 1902 | ARRAY_SIZE(fxxxx_in1_alarm_attr)); |
@@ -1908,6 +1934,7 @@ static int __devinit f71882fg_probe(struct platform_device *pdev) | |||
1908 | err = (data->pwm_enable & 0x15) != 0x15; | 1934 | err = (data->pwm_enable & 0x15) != 0x15; |
1909 | break; | 1935 | break; |
1910 | case f71882fg: | 1936 | case f71882fg: |
1937 | case f71889fg: | ||
1911 | err = 0; | 1938 | err = 0; |
1912 | break; | 1939 | break; |
1913 | case f8000: | 1940 | case f8000: |
@@ -1927,7 +1954,8 @@ static int __devinit f71882fg_probe(struct platform_device *pdev) | |||
1927 | if (err) | 1954 | if (err) |
1928 | goto exit_unregister_sysfs; | 1955 | goto exit_unregister_sysfs; |
1929 | 1956 | ||
1930 | if (data->type == f71862fg || data->type == f71882fg) { | 1957 | if (data->type == f71862fg || data->type == f71882fg || |
1958 | data->type == f71889fg) { | ||
1931 | err = f71882fg_create_sysfs_files(pdev, | 1959 | err = f71882fg_create_sysfs_files(pdev, |
1932 | fxxxx_fan_beep_attr, nr_fans); | 1960 | fxxxx_fan_beep_attr, nr_fans); |
1933 | if (err) | 1961 | if (err) |
@@ -1950,6 +1978,22 @@ static int __devinit f71882fg_probe(struct platform_device *pdev) | |||
1950 | f8000_auto_pwm_attr, | 1978 | f8000_auto_pwm_attr, |
1951 | ARRAY_SIZE(f8000_auto_pwm_attr)); | 1979 | ARRAY_SIZE(f8000_auto_pwm_attr)); |
1952 | break; | 1980 | break; |
1981 | case f71889fg: | ||
1982 | for (i = 0; i < nr_fans; i++) { | ||
1983 | data->pwm_auto_point_mapping[i] = | ||
1984 | f71882fg_read8(data, | ||
1985 | F71882FG_REG_POINT_MAPPING(i)); | ||
1986 | if (data->pwm_auto_point_mapping[i] & 0x80) | ||
1987 | break; | ||
1988 | } | ||
1989 | if (i != nr_fans) { | ||
1990 | dev_warn(&pdev->dev, | ||
1991 | "Auto pwm controlled by raw digital " | ||
1992 | "data, disabling pwm auto_point " | ||
1993 | "sysfs attributes\n"); | ||
1994 | break; | ||
1995 | } | ||
1996 | /* fall through */ | ||
1953 | default: /* f71858fg / f71882fg */ | 1997 | default: /* f71858fg / f71882fg */ |
1954 | err = f71882fg_create_sysfs_files(pdev, | 1998 | err = f71882fg_create_sysfs_files(pdev, |
1955 | &fxxxx_auto_pwm_attr[0][0], | 1999 | &fxxxx_auto_pwm_attr[0][0], |
@@ -2006,6 +2050,7 @@ static int f71882fg_remove(struct platform_device *pdev) | |||
2006 | ARRAY_SIZE(f71858fg_in_temp_attr)); | 2050 | ARRAY_SIZE(f71858fg_in_temp_attr)); |
2007 | break; | 2051 | break; |
2008 | case f71882fg: | 2052 | case f71882fg: |
2053 | case f71889fg: | ||
2009 | f71882fg_remove_sysfs_files(pdev, | 2054 | f71882fg_remove_sysfs_files(pdev, |
2010 | fxxxx_in1_alarm_attr, | 2055 | fxxxx_in1_alarm_attr, |
2011 | ARRAY_SIZE(fxxxx_in1_alarm_attr)); | 2056 | ARRAY_SIZE(fxxxx_in1_alarm_attr)); |
@@ -2027,7 +2072,8 @@ static int f71882fg_remove(struct platform_device *pdev) | |||
2027 | f71882fg_remove_sysfs_files(pdev, &fxxxx_fan_attr[0][0], | 2072 | f71882fg_remove_sysfs_files(pdev, &fxxxx_fan_attr[0][0], |
2028 | ARRAY_SIZE(fxxxx_fan_attr[0]) * nr_fans); | 2073 | ARRAY_SIZE(fxxxx_fan_attr[0]) * nr_fans); |
2029 | 2074 | ||
2030 | if (data->type == f71862fg || data->type == f71882fg) | 2075 | if (data->type == f71862fg || data->type == f71882fg || |
2076 | data->type == f71889fg) | ||
2031 | f71882fg_remove_sysfs_files(pdev, | 2077 | f71882fg_remove_sysfs_files(pdev, |
2032 | fxxxx_fan_beep_attr, nr_fans); | 2078 | fxxxx_fan_beep_attr, nr_fans); |
2033 | 2079 | ||
@@ -2082,11 +2128,15 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, | |||
2082 | case SIO_F71882_ID: | 2128 | case SIO_F71882_ID: |
2083 | sio_data->type = f71882fg; | 2129 | sio_data->type = f71882fg; |
2084 | break; | 2130 | break; |
2131 | case SIO_F71889_ID: | ||
2132 | sio_data->type = f71889fg; | ||
2133 | break; | ||
2085 | case SIO_F8000_ID: | 2134 | case SIO_F8000_ID: |
2086 | sio_data->type = f8000; | 2135 | sio_data->type = f8000; |
2087 | break; | 2136 | break; |
2088 | default: | 2137 | default: |
2089 | printk(KERN_INFO DRVNAME ": Unsupported Fintek device\n"); | 2138 | printk(KERN_INFO DRVNAME ": Unsupported Fintek device: %04x\n", |
2139 | (unsigned int)devid); | ||
2090 | goto exit; | 2140 | goto exit; |
2091 | } | 2141 | } |
2092 | 2142 | ||