Quellcode durchsuchen

Merge branch 'hwmon-for-linus' of git://jdelvare.pck.nerim.net/jdelvare-2.6

* 'hwmon-for-linus' of git://jdelvare.pck.nerim.net/jdelvare-2.6:
  hwmon/w83793: Hide invalid VID readings
  hwmon/w83793: Fix the fan input detection
  hwmon/w83793: Ignore disabled temperature channels
  hwmon: Fix the VRD 11 decoding
  hwmon/w83793: Remove the description of AMDSI and update the voltage formula
Linus Torvalds vor 18 Jahren
Ursprung
Commit
79d2628702
3 geänderte Dateien mit 113 neuen und 24 gelöschten Zeilen
  1. 2 6
      Documentation/hwmon/w83793
  2. 1 1
      drivers/hwmon/hwmon-vid.c
  3. 110 17
      drivers/hwmon/w83793.c

+ 2 - 6
Documentation/hwmon/w83793

@@ -45,18 +45,14 @@ This driver implements support for Winbond W83793G/W83793R chips.
   temp5-6 have a 1 degree Celsiis resolution.
 
 * Temperature sensor types
-  Temp1-4 have 3 possible types. It can be read from (and written to)
+  Temp1-4 have 2 possible types. It can be read from (and written to)
   temp[1-4]_type.
-  - If the value of 0, the related temperature channel stops
-    monitoring.
   - If the value is 3, it starts monitoring using a remote termal diode
     (default).
-  - If the value is 5, it starts monitoring using the temperature sensor
-    in AMD CPU and get result by AMDSI.
   - If the value is 6, it starts monitoring using the temperature sensor
     in Intel CPU and get result by PECI.
   Temp5-6 can be connected to external thermistors (value of
-  temp[5-6]_type is 4). They can also be disabled (value is 0).
+  temp[5-6]_type is 4).
 
 * Alarm mechanism
   For voltage sensors, an alarm triggers if the measured value is below

+ 1 - 1
drivers/hwmon/hwmon-vid.c

@@ -93,7 +93,7 @@ int vid_from_reg(int val, u8 vrm)
 	case 110:		/* Intel Conroe */
 				/* compute in uV, round to mV */
 		val &= 0xff;
-		if(((val & 0x7e) == 0xfe) || (!(val & 0x7e)))
+		if (val < 0x02 || val > 0xb2)
 			return 0;
 		return((1600000 - (val - 2) * 6250 + 500) / 1000);
 	case 24:                /* Opteron processor */

+ 110 - 17
drivers/hwmon/w83793.c

@@ -117,6 +117,7 @@ static const u16 W83793_REG_IN[][3] = {
 /* Low Bits of Vcore A/B Vtt Read/High/Low */
 static const u16 W83793_REG_IN_LOW_BITS[] = { 0x1b, 0x68, 0x69 };
 static u8 scale_in[] = { 2, 2, 2, 16, 16, 16, 8, 24, 24, 16 };
+static u8 scale_in_add[] = { 0, 0, 0, 0, 0, 0, 0, 150, 150, 0 };
 
 #define W83793_REG_FAN(index)		(0x23 + 2 * (index))	/* High byte */
 #define W83793_REG_FAN_MIN(index)	(0x90 + 2 * (index))	/* High byte */
@@ -203,6 +204,8 @@ struct w83793_data {
 	u8 temp_fan_map[6];	/* Temp controls which pwm fan, bit field */
 
 	u8 has_pwm;
+	u8 has_temp;
+	u8 has_vid;
 	u8 pwm_enable;		/* Register value, each Temp has 1 bit */
 	u8 pwm_uptime;		/* Register value */
 	u8 pwm_downtime;	/* Register value */
@@ -500,7 +503,7 @@ store_temp(struct device *dev, struct device_attribute *attr,
 	each has 4 mode:(2 bits)
 	0:	Stop monitor
 	1:	Use internal temp sensor(default)
-	2:	Use sensor in AMD CPU and get result by AMDSI
+	2:	Reserved
 	3:	Use sensor in Intel CPU and get result by PECI
 
 	TR1-TR2
@@ -509,8 +512,8 @@ store_temp(struct device *dev, struct device_attribute *attr,
 	1:	To enable temp sensors monitor
 */
 
-/* 0 disable, 5 AMDSI, 6 PECI */
-static u8 TO_TEMP_MODE[] = { 0, 0, 5, 6 };
+/* 0 disable, 6 PECI */
+static u8 TO_TEMP_MODE[] = { 0, 0, 0, 6 };
 
 static ssize_t
 show_temp_mode(struct device *dev, struct device_attribute *attr, char *buf)
@@ -550,11 +553,10 @@ store_temp_mode(struct device *dev, struct device_attribute *attr,
 	u8 val = simple_strtoul(buf, NULL, 10);
 
 	/* transform the sysfs interface values into table above */
-	if ((val == 5 || val == 6) && (index < 4)) {
+	if ((val == 6) && (index < 4)) {
 		val -= 3;
 	} else if ((val == 3 && index < 4)
-		|| (val == 4 && index >= 4)
-		|| val == 0) {
+		|| (val == 4 && index >= 4)) {
 		/* transform diode or thermistor into internal enable */
 		val = !!val;
 	} else {
@@ -839,7 +841,9 @@ show_in(struct device *dev, struct device_attribute *attr, char *buf)
 		val <<= 2;
 		val += (data->in_low_bits[nr] >> (index * 2)) & 0x3;
 	}
-	return sprintf(buf, "%d\n", val * scale_in[index]);
+	/* voltage inputs 5VDD and 5VSB needs 150mV offset */
+	val = val * scale_in[index] + scale_in_add[index];
+	return sprintf(buf, "%d\n", val);
 }
 
 static ssize_t
@@ -859,6 +863,10 @@ store_in(struct device *dev, struct device_attribute *attr,
 	     scale_in[index] / 2) / scale_in[index];
 	mutex_lock(&data->update_lock);
 	if (index > 2) {
+		/* fix the limit values of 5VDD and 5VSB to ALARM mechanism */
+		if (1 == nr || 2 == nr) {
+			val -= scale_in_add[index] / scale_in[index];
+		}
 		val = SENSORS_LIMIT(val, 0, 255);
 	} else {
 		val = SENSORS_LIMIT(val, 0, 0x3FF);
@@ -979,12 +987,6 @@ static struct sensor_device_attribute_2 w83793_sensor_attr_2[] = {
 	SENSOR_ATTR_IN(7),
 	SENSOR_ATTR_IN(8),
 	SENSOR_ATTR_IN(9),
-	SENSOR_ATTR_TEMP(1),
-	SENSOR_ATTR_TEMP(2),
-	SENSOR_ATTR_TEMP(3),
-	SENSOR_ATTR_TEMP(4),
-	SENSOR_ATTR_TEMP(5),
-	SENSOR_ATTR_TEMP(6),
 	SENSOR_ATTR_FAN(1),
 	SENSOR_ATTR_FAN(2),
 	SENSOR_ATTR_FAN(3),
@@ -995,6 +997,15 @@ static struct sensor_device_attribute_2 w83793_sensor_attr_2[] = {
 	SENSOR_ATTR_PWM(3),
 };
 
+static struct sensor_device_attribute_2 w83793_temp[] = {
+	SENSOR_ATTR_TEMP(1),
+	SENSOR_ATTR_TEMP(2),
+	SENSOR_ATTR_TEMP(3),
+	SENSOR_ATTR_TEMP(4),
+	SENSOR_ATTR_TEMP(5),
+	SENSOR_ATTR_TEMP(6),
+};
+
 /* Fan6-Fan12 */
 static struct sensor_device_attribute_2 w83793_left_fan[] = {
 	SENSOR_ATTR_FAN(6),
@@ -1015,9 +1026,12 @@ static struct sensor_device_attribute_2 w83793_left_pwm[] = {
 	SENSOR_ATTR_PWM(8),
 };
 
-static struct sensor_device_attribute_2 sda_single_files[] = {
+static struct sensor_device_attribute_2 w83793_vid[] = {
 	SENSOR_ATTR_2(cpu0_vid, S_IRUGO, show_vid, NULL, NOT_USED, 0),
 	SENSOR_ATTR_2(cpu1_vid, S_IRUGO, show_vid, NULL, NOT_USED, 1),
+};
+
+static struct sensor_device_attribute_2 sda_single_files[] = {
 	SENSOR_ATTR_2(vrm, S_IWUSR | S_IRUGO, show_vrm, store_vrm,
 		      NOT_USED, NOT_USED),
 	SENSOR_ATTR_2(chassis, S_IWUSR | S_IRUGO, show_alarm_beep,
@@ -1070,11 +1084,17 @@ static int w83793_detach_client(struct i2c_client *client)
 		for (i = 0; i < ARRAY_SIZE(sda_single_files); i++)
 			device_remove_file(dev, &sda_single_files[i].dev_attr);
 
+		for (i = 0; i < ARRAY_SIZE(w83793_vid); i++)
+			device_remove_file(dev, &w83793_vid[i].dev_attr);
+
 		for (i = 0; i < ARRAY_SIZE(w83793_left_fan); i++)
 			device_remove_file(dev, &w83793_left_fan[i].dev_attr);
 
 		for (i = 0; i < ARRAY_SIZE(w83793_left_pwm); i++)
 			device_remove_file(dev, &w83793_left_pwm[i].dev_attr);
+
+		for (i = 0; i < ARRAY_SIZE(w83793_temp); i++)
+			device_remove_file(dev, &w83793_temp[i].dev_attr);
 	}
 
 	if ((err = i2c_detach_client(client)))
@@ -1187,6 +1207,7 @@ static int w83793_detect(struct i2c_adapter *adapter, int address, int kind)
 	struct w83793_data *data;
 	int files_fan = ARRAY_SIZE(w83793_left_fan) / 7;
 	int files_pwm = ARRAY_SIZE(w83793_left_pwm) / 5;
+	int files_temp = ARRAY_SIZE(w83793_temp) / 6;
 	int err = 0;
 
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
@@ -1313,6 +1334,44 @@ static int w83793_detect(struct i2c_adapter *adapter, int address, int kind)
 		data->has_pwm |= 0x80;
 	}
 
+	tmp = w83793_read_value(client, W83793_REG_FANIN_SEL);
+	if ((tmp & 0x01) && (val & 0x08)) {	/* fan 9, second location */
+		data->has_fan |= 0x100;
+	}
+	if ((tmp & 0x02) && (val & 0x10)) {	/* fan 10, second location */
+		data->has_fan |= 0x200;
+	}
+	if ((tmp & 0x04) && (val & 0x20)) {	/* fan 11, second location */
+		data->has_fan |= 0x400;
+	}
+	if ((tmp & 0x08) && (val & 0x40)) {	/* fan 12, second location */
+		data->has_fan |= 0x800;
+	}
+
+	/* check the temp1-6 mode, ignore former AMDSI selected inputs */
+	tmp = w83793_read_value(client,W83793_REG_TEMP_MODE[0]);
+	if (tmp & 0x01)
+		data->has_temp |= 0x01;
+	if (tmp & 0x04)
+		data->has_temp |= 0x02;
+	if (tmp & 0x10)
+		data->has_temp |= 0x04;
+	if (tmp & 0x40)
+		data->has_temp |= 0x08;
+
+	tmp = w83793_read_value(client,W83793_REG_TEMP_MODE[1]);
+	if (tmp & 0x01)
+		data->has_temp |= 0x10;
+	if (tmp & 0x02)
+		data->has_temp |= 0x20;
+
+	/* Detect the VID usage and ignore unused input */
+	tmp = w83793_read_value(client, W83793_REG_MFC);
+	if (!(tmp & 0x29))
+		data->has_vid |= 0x1;	/* has VIDA */
+	if (tmp & 0x80)
+		data->has_vid |= 0x2;	/* has VIDB */
+
 	/* Register sysfs hooks */
 	for (i = 0; i < ARRAY_SIZE(w83793_sensor_attr_2); i++) {
 		err = device_create_file(dev,
@@ -1321,6 +1380,14 @@ static int w83793_detect(struct i2c_adapter *adapter, int address, int kind)
 			goto exit_remove;
 	}
 
+	for (i = 0; i < ARRAY_SIZE(w83793_vid); i++) {
+		if (!(data->has_vid & (1 << i)))
+			continue;
+		err = device_create_file(dev, &w83793_vid[i].dev_attr);
+		if (err)
+			goto exit_remove;
+	}
+
 	for (i = 0; i < ARRAY_SIZE(sda_single_files); i++) {
 		err = device_create_file(dev, &sda_single_files[i].dev_attr);
 		if (err)
@@ -1328,6 +1395,19 @@ static int w83793_detect(struct i2c_adapter *adapter, int address, int kind)
 
 	}
 
+	for (i = 0; i < 6; i++) {
+		int j;
+		if (!(data->has_temp & (1 << i)))
+			continue;
+		for (j = 0; j < files_temp; j++) {
+			err = device_create_file(dev,
+						&w83793_temp[(i) * files_temp
+								+ j].dev_attr);
+			if (err)
+				goto exit_remove;
+		}
+	}
+
 	for (i = 5; i < 12; i++) {
 		int j;
 		if (!(data->has_fan & (1 << i)))
@@ -1371,12 +1451,18 @@ exit_remove:
 	for (i = 0; i < ARRAY_SIZE(sda_single_files); i++)
 		device_remove_file(dev, &sda_single_files[i].dev_attr);
 
+	for (i = 0; i < ARRAY_SIZE(w83793_vid); i++)
+		device_remove_file(dev, &w83793_vid[i].dev_attr);
+
 	for (i = 0; i < ARRAY_SIZE(w83793_left_fan); i++)
 		device_remove_file(dev, &w83793_left_fan[i].dev_attr);
 
 	for (i = 0; i < ARRAY_SIZE(w83793_left_pwm); i++)
 		device_remove_file(dev, &w83793_left_pwm[i].dev_attr);
 
+	for (i = 0; i < ARRAY_SIZE(w83793_temp); i++)
+		device_remove_file(dev, &w83793_temp[i].dev_attr);
+
 	if (data->lm75[0] != NULL) {
 		i2c_detach_client(data->lm75[0]);
 		kfree(data->lm75[0]);
@@ -1428,6 +1514,8 @@ static void w83793_update_nonvolatile(struct device *dev)
 	}
 
 	for (i = 0; i < ARRAY_SIZE(data->temp_fan_map); i++) {
+		if (!(data->has_temp & (1 << i)))
+			continue;
 		data->temp_fan_map[i] =
 		    w83793_read_value(client, W83793_REG_TEMP_FAN_MAP(i));
 		for (j = 1; j < 5; j++) {
@@ -1510,9 +1598,12 @@ static struct w83793_data *w83793_update_device(struct device *dev)
 		    w83793_read_value(client, W83793_REG_FAN(i) + 1);
 	}
 
-	for (i = 0; i < ARRAY_SIZE(data->temp); i++)
+	for (i = 0; i < ARRAY_SIZE(data->temp); i++) {
+		if (!(data->has_temp & (1 << i)))
+			continue;
 		data->temp[i][TEMP_READ] =
 		    w83793_read_value(client, W83793_REG_TEMP[i][TEMP_READ]);
+	}
 
 	data->temp_low_bits =
 	    w83793_read_value(client, W83793_REG_TEMP_LOW_BITS);
@@ -1527,8 +1618,10 @@ static struct w83793_data *w83793_update_device(struct device *dev)
 	for (i = 0; i < ARRAY_SIZE(data->alarms); i++)
 		data->alarms[i] =
 		    w83793_read_value(client, W83793_REG_ALARM(i));
-	data->vid[0] = w83793_read_value(client, W83793_REG_VID_INA);
-	data->vid[1] = w83793_read_value(client, W83793_REG_VID_INB);
+	if (data->has_vid & 0x01)
+		data->vid[0] = w83793_read_value(client, W83793_REG_VID_INA);
+	if (data->has_vid & 0x02)
+		data->vid[1] = w83793_read_value(client, W83793_REG_VID_INB);
 	w83793_update_nonvolatile(dev);
 	data->last_updated = jiffies;
 	data->valid = 1;