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
This commit is contained in:
commit
79d2628702
3 changed files with 113 additions and 24 deletions
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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,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;
|
||||
|
|
Loading…
Reference in a new issue