Commit 7669896f authored by Hans de Goede's avatar Hans de Goede Committed by Jean Delvare

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: default avatarHans de Goede <hdegoede@redhat.com>
Signed-off-by: default avatarJean Delvare <khali@linux-fr.org>
parent fc16c56e
...@@ -14,6 +14,10 @@ Supported chips: ...@@ -14,6 +14,10 @@ Supported chips:
Prefix: 'f71882fg' Prefix: 'f71882fg'
Addresses scanned: none, address read from Super I/O config space Addresses scanned: none, address read from Super I/O config space
Datasheet: Available from the Fintek website Datasheet: Available from the Fintek website
* Fintek F71889FG
Prefix: 'f71889fg'
Addresses scanned: none, address read from Super I/O config space
Datasheet: Should become available on the Fintek website soon
* Fintek F8000 * Fintek F8000
Prefix: 'f8000' Prefix: 'f8000'
Addresses scanned: none, address read from Super I/O config space Addresses scanned: none, address read from Super I/O config space
...@@ -51,6 +55,12 @@ supported. The right one to use depends on external circuitry on the ...@@ -51,6 +55,12 @@ supported. The right one to use depends on external circuitry on the
motherboard, so the driver assumes that the BIOS set the method motherboard, so the driver assumes that the BIOS set the method
properly. properly.
Note that the lowest numbered temperature zone trip point corresponds to
to the border between the highest and one but highest temperature zones, and
vica versa. So the temperature zone trip points 1-4 (or 1-2) go from high temp
to low temp! This is how things are implemented in the IC, and the driver
mimicks this.
There are 2 modes to specify the speed of the fan, PWM duty cycle (or DC There are 2 modes to specify the speed of the fan, PWM duty cycle (or DC
voltage) mode, where 0-100% duty cycle (0-100% of 12V) is specified. And RPM voltage) mode, where 0-100% duty cycle (0-100% of 12V) is specified. And RPM
mode where the actual RPM of the fan (as measured) is controlled and the speed mode where the actual RPM of the fan (as measured) is controlled and the speed
......
...@@ -305,12 +305,12 @@ config SENSORS_F71805F ...@@ -305,12 +305,12 @@ config SENSORS_F71805F
will be called f71805f. will be called f71805f.
config SENSORS_F71882FG config SENSORS_F71882FG
tristate "Fintek F71858FG, F71862FG, F71882FG and F8000" tristate "Fintek F71858FG, F71862FG, F71882FG, F71889FG and F8000"
depends on EXPERIMENTAL depends on EXPERIMENTAL
help help
If you say yes here you get support for hardware monitoring If you say yes here you get support for hardware monitoring
features of the Fintek F71858FG, F71862FG/71863FG, F71882FG/F71883FG features of the Fintek F71858FG, F71862FG/71863FG, F71882FG/F71883FG,
and F8000 Super-I/O chips. F71889FG and F8000 Super-I/O chips.
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called f71882fg. will be called f71882fg.
......
...@@ -48,6 +48,7 @@ ...@@ -48,6 +48,7 @@
#define SIO_F71858_ID 0x0507 /* Chipset ID */ #define SIO_F71858_ID 0x0507 /* Chipset ID */
#define SIO_F71862_ID 0x0601 /* Chipset ID */ #define SIO_F71862_ID 0x0601 /* Chipset ID */
#define SIO_F71882_ID 0x0541 /* Chipset ID */ #define SIO_F71882_ID 0x0541 /* Chipset ID */
#define SIO_F71889_ID 0x0723 /* Chipset ID */
#define SIO_F8000_ID 0x0581 /* Chipset ID */ #define SIO_F8000_ID 0x0581 /* Chipset ID */
#define REGION_LENGTH 8 #define REGION_LENGTH 8
...@@ -95,12 +96,13 @@ static unsigned short force_id; ...@@ -95,12 +96,13 @@ static unsigned short force_id;
module_param(force_id, ushort, 0); module_param(force_id, ushort, 0);
MODULE_PARM_DESC(force_id, "Override the detected device ID"); MODULE_PARM_DESC(force_id, "Override the detected device ID");
enum chips { f71858fg, f71862fg, f71882fg, f8000 }; enum chips { f71858fg, f71862fg, f71882fg, f71889fg, f8000 };
static const char *f71882fg_names[] = { static const char *f71882fg_names[] = {
"f71858fg", "f71858fg",
"f71862fg", "f71862fg",
"f71882fg", "f71882fg",
"f71889fg",
"f8000", "f8000",
}; };
...@@ -155,7 +157,7 @@ struct f71882fg_data { ...@@ -155,7 +157,7 @@ struct f71882fg_data {
u8 pwm_auto_point_hyst[2]; u8 pwm_auto_point_hyst[2];
u8 pwm_auto_point_mapping[4]; u8 pwm_auto_point_mapping[4];
u8 pwm_auto_point_pwm[4][5]; u8 pwm_auto_point_pwm[4][5];
u8 pwm_auto_point_temp[4][4]; s8 pwm_auto_point_temp[4][4];
}; };
/* Sysfs in */ /* Sysfs in */
...@@ -945,7 +947,7 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev) ...@@ -945,7 +947,7 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev)
/* Update once every 60 seconds */ /* Update once every 60 seconds */
if ( time_after(jiffies, data->last_limits + 60 * HZ ) || if ( time_after(jiffies, data->last_limits + 60 * HZ ) ||
!data->valid) { !data->valid) {
if (data->type == f71882fg) { if (data->type == f71882fg || data->type == f71889fg) {
data->in1_max = data->in1_max =
f71882fg_read8(data, F71882FG_REG_IN1_HIGH); f71882fg_read8(data, F71882FG_REG_IN1_HIGH);
data->in_beep = data->in_beep =
...@@ -967,7 +969,8 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev) ...@@ -967,7 +969,8 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev)
F71882FG_REG_TEMP_HYST(1)); F71882FG_REG_TEMP_HYST(1));
} }
if (data->type == f71862fg || data->type == f71882fg) { if (data->type == f71862fg || data->type == f71882fg ||
data->type == f71889fg) {
data->fan_beep = f71882fg_read8(data, data->fan_beep = f71882fg_read8(data,
F71882FG_REG_FAN_BEEP); F71882FG_REG_FAN_BEEP);
data->temp_beep = f71882fg_read8(data, data->temp_beep = f71882fg_read8(data,
...@@ -977,15 +980,33 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev) ...@@ -977,15 +980,33 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev)
data->temp_type[2] = (reg & 0x04) ? 2 : 4; data->temp_type[2] = (reg & 0x04) ? 2 : 4;
data->temp_type[3] = (reg & 0x08) ? 2 : 4; data->temp_type[3] = (reg & 0x08) ? 2 : 4;
} }
/* Determine temp index 1 sensor type */
if (data->type == f71889fg) {
reg2 = f71882fg_read8(data, F71882FG_REG_START);
switch ((reg2 & 0x60) >> 5) {
case 0x00: /* BJT / Thermistor */
data->temp_type[1] = (reg & 0x02) ? 2 : 4;
break;
case 0x01: /* AMDSI */
data->temp_type[1] = 5;
break;
case 0x02: /* PECI */
case 0x03: /* Ibex Peak ?? Report as PECI for now */
data->temp_type[1] = 6;
break;
}
} else {
reg2 = f71882fg_read8(data, F71882FG_REG_PECI); reg2 = f71882fg_read8(data, F71882FG_REG_PECI);
if ((reg2 & 0x03) == 0x01) if ((reg2 & 0x03) == 0x01)
data->temp_type[1] = 6 /* PECI */; data->temp_type[1] = 6; /* PECI */
else if ((reg2 & 0x03) == 0x02) else if ((reg2 & 0x03) == 0x02)
data->temp_type[1] = 5 /* AMDSI */; data->temp_type[1] = 5; /* AMDSI */
else if (data->type == f71862fg || data->type == f71882fg) else if (data->type == f71862fg ||
data->type == f71882fg)
data->temp_type[1] = (reg & 0x02) ? 2 : 4; data->temp_type[1] = (reg & 0x02) ? 2 : 4;
else else /* f71858fg and f8000 only support BJT */
data->temp_type[1] = 2; /* Only supports BJT */ data->temp_type[1] = 2;
}
data->pwm_enable = f71882fg_read8(data, data->pwm_enable = f71882fg_read8(data,
F71882FG_REG_PWM_ENABLE); F71882FG_REG_PWM_ENABLE);
...@@ -1062,7 +1083,7 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev) ...@@ -1062,7 +1083,7 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev)
if (data->type == f8000) if (data->type == f8000)
data->fan[3] = f71882fg_read16(data, data->fan[3] = f71882fg_read16(data,
F71882FG_REG_FAN(3)); F71882FG_REG_FAN(3));
if (data->type == f71882fg) if (data->type == f71882fg || data->type == f71889fg)
data->in_status = f71882fg_read8(data, data->in_status = f71882fg_read8(data,
F71882FG_REG_IN_STATUS); F71882FG_REG_IN_STATUS);
for (nr = 0; nr < nr_ins; nr++) for (nr = 0; nr < nr_ins; nr++)
...@@ -1780,7 +1801,11 @@ static ssize_t store_pwm_auto_point_temp(struct device *dev, ...@@ -1780,7 +1801,11 @@ static ssize_t store_pwm_auto_point_temp(struct device *dev,
int pwm = to_sensor_dev_attr_2(devattr)->index; int pwm = to_sensor_dev_attr_2(devattr)->index;
int point = to_sensor_dev_attr_2(devattr)->nr; int point = to_sensor_dev_attr_2(devattr)->nr;
long val = simple_strtol(buf, NULL, 10) / 1000; long val = simple_strtol(buf, NULL, 10) / 1000;
val = SENSORS_LIMIT(val, 0, 255);
if (data->type == f71889fg)
val = SENSORS_LIMIT(val, -128, 127);
else
val = SENSORS_LIMIT(val, 0, 127);
mutex_lock(&data->update_lock); mutex_lock(&data->update_lock);
f71882fg_write8(data, F71882FG_REG_POINT_TEMP(pwm, point), val); f71882fg_write8(data, F71882FG_REG_POINT_TEMP(pwm, point), val);
...@@ -1871,6 +1896,7 @@ static int __devinit f71882fg_probe(struct platform_device *pdev) ...@@ -1871,6 +1896,7 @@ static int __devinit f71882fg_probe(struct platform_device *pdev)
ARRAY_SIZE(f71858fg_in_temp_attr)); ARRAY_SIZE(f71858fg_in_temp_attr));
break; break;
case f71882fg: case f71882fg:
case f71889fg:
err = f71882fg_create_sysfs_files(pdev, err = f71882fg_create_sysfs_files(pdev,
fxxxx_in1_alarm_attr, fxxxx_in1_alarm_attr,
ARRAY_SIZE(fxxxx_in1_alarm_attr)); ARRAY_SIZE(fxxxx_in1_alarm_attr));
...@@ -1908,6 +1934,7 @@ static int __devinit f71882fg_probe(struct platform_device *pdev) ...@@ -1908,6 +1934,7 @@ static int __devinit f71882fg_probe(struct platform_device *pdev)
err = (data->pwm_enable & 0x15) != 0x15; err = (data->pwm_enable & 0x15) != 0x15;
break; break;
case f71882fg: case f71882fg:
case f71889fg:
err = 0; err = 0;
break; break;
case f8000: case f8000:
...@@ -1927,7 +1954,8 @@ static int __devinit f71882fg_probe(struct platform_device *pdev) ...@@ -1927,7 +1954,8 @@ static int __devinit f71882fg_probe(struct platform_device *pdev)
if (err) if (err)
goto exit_unregister_sysfs; goto exit_unregister_sysfs;
if (data->type == f71862fg || data->type == f71882fg) { if (data->type == f71862fg || data->type == f71882fg ||
data->type == f71889fg) {
err = f71882fg_create_sysfs_files(pdev, err = f71882fg_create_sysfs_files(pdev,
fxxxx_fan_beep_attr, nr_fans); fxxxx_fan_beep_attr, nr_fans);
if (err) if (err)
...@@ -1950,6 +1978,22 @@ static int __devinit f71882fg_probe(struct platform_device *pdev) ...@@ -1950,6 +1978,22 @@ static int __devinit f71882fg_probe(struct platform_device *pdev)
f8000_auto_pwm_attr, f8000_auto_pwm_attr,
ARRAY_SIZE(f8000_auto_pwm_attr)); ARRAY_SIZE(f8000_auto_pwm_attr));
break; break;
case f71889fg:
for (i = 0; i < nr_fans; i++) {
data->pwm_auto_point_mapping[i] =
f71882fg_read8(data,
F71882FG_REG_POINT_MAPPING(i));
if (data->pwm_auto_point_mapping[i] & 0x80)
break;
}
if (i != nr_fans) {
dev_warn(&pdev->dev,
"Auto pwm controlled by raw digital "
"data, disabling pwm auto_point "
"sysfs attributes\n");
break;
}
/* fall through */
default: /* f71858fg / f71882fg */ default: /* f71858fg / f71882fg */
err = f71882fg_create_sysfs_files(pdev, err = f71882fg_create_sysfs_files(pdev,
&fxxxx_auto_pwm_attr[0][0], &fxxxx_auto_pwm_attr[0][0],
...@@ -2006,6 +2050,7 @@ static int f71882fg_remove(struct platform_device *pdev) ...@@ -2006,6 +2050,7 @@ static int f71882fg_remove(struct platform_device *pdev)
ARRAY_SIZE(f71858fg_in_temp_attr)); ARRAY_SIZE(f71858fg_in_temp_attr));
break; break;
case f71882fg: case f71882fg:
case f71889fg:
f71882fg_remove_sysfs_files(pdev, f71882fg_remove_sysfs_files(pdev,
fxxxx_in1_alarm_attr, fxxxx_in1_alarm_attr,
ARRAY_SIZE(fxxxx_in1_alarm_attr)); ARRAY_SIZE(fxxxx_in1_alarm_attr));
...@@ -2027,7 +2072,8 @@ static int f71882fg_remove(struct platform_device *pdev) ...@@ -2027,7 +2072,8 @@ static int f71882fg_remove(struct platform_device *pdev)
f71882fg_remove_sysfs_files(pdev, &fxxxx_fan_attr[0][0], f71882fg_remove_sysfs_files(pdev, &fxxxx_fan_attr[0][0],
ARRAY_SIZE(fxxxx_fan_attr[0]) * nr_fans); ARRAY_SIZE(fxxxx_fan_attr[0]) * nr_fans);
if (data->type == f71862fg || data->type == f71882fg) if (data->type == f71862fg || data->type == f71882fg ||
data->type == f71889fg)
f71882fg_remove_sysfs_files(pdev, f71882fg_remove_sysfs_files(pdev,
fxxxx_fan_beep_attr, nr_fans); fxxxx_fan_beep_attr, nr_fans);
...@@ -2082,11 +2128,15 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, ...@@ -2082,11 +2128,15 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address,
case SIO_F71882_ID: case SIO_F71882_ID:
sio_data->type = f71882fg; sio_data->type = f71882fg;
break; break;
case SIO_F71889_ID:
sio_data->type = f71889fg;
break;
case SIO_F8000_ID: case SIO_F8000_ID:
sio_data->type = f8000; sio_data->type = f8000;
break; break;
default: default:
printk(KERN_INFO DRVNAME ": Unsupported Fintek device\n"); printk(KERN_INFO DRVNAME ": Unsupported Fintek device: %04x\n",
(unsigned int)devid);
goto exit; goto exit;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment