Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 79d26287 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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
parents c8fefb1b c70a8c34
Loading
Loading
Loading
Loading
+2 −6
Original line number Diff line number Diff line
@@ -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
Original line number Diff line number Diff line
@@ -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
Original line number Diff line number Diff line
@@ -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 @@ static int w83793_detect(struct i2c_adapter *adapter, int address, int kind)
	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,7 +1618,9 @@ 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));
	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;