mirror of
https://github.com/adulau/aha.git
synced 2024-12-28 11:46:19 +00:00
hwmon: (w83791d) Use fan divisor bits from vbat register
Update w83791d with fan bits in vbat mon register (7.48 of the datasheet). This change allows all fans to have a divisor of 128, and fixes a problem with incorrectly reported fan speeds. Signed-off-by: Marc Hulsman <m.hulsman@tudelft.nl> Signed-off-by: Jean Delvare <khali@linux-fr.org>
This commit is contained in:
parent
05a5e47768
commit
ad02ad85cf
2 changed files with 23 additions and 7 deletions
|
@ -22,6 +22,7 @@ Credits:
|
|||
|
||||
Additional contributors:
|
||||
Sven Anders <anders@anduras.de>
|
||||
Marc Hulsman <m.hulsman@tudelft.nl>
|
||||
|
||||
Module Parameters
|
||||
-----------------
|
||||
|
@ -67,9 +68,8 @@ on until the temperature falls below the Hysteresis value.
|
|||
|
||||
Fan rotation speeds are reported in RPM (rotations per minute). An alarm is
|
||||
triggered if the rotation speed has dropped below a programmable limit. Fan
|
||||
readings can be divided by a programmable divider (1, 2, 4, 8 for fan 1/2/3
|
||||
and 1, 2, 4, 8, 16, 32, 64 or 128 for fan 4/5) to give the readings more
|
||||
range or accuracy.
|
||||
readings can be divided by a programmable divider (1, 2, 4, 8, 16,
|
||||
32, 64 or 128 for all fans) to give the readings more range or accuracy.
|
||||
|
||||
Voltage sensors (also known as IN sensors) report their values in millivolts.
|
||||
An alarm is triggered if the voltage has crossed a programmable minimum
|
||||
|
|
|
@ -233,11 +233,9 @@ static u8 fan_to_reg(long rpm, int div)
|
|||
static u8 div_to_reg(int nr, long val)
|
||||
{
|
||||
int i;
|
||||
int max;
|
||||
|
||||
/* first three fan's divisor max out at 8, rest max out at 128 */
|
||||
max = (nr < 3) ? 8 : 128;
|
||||
val = SENSORS_LIMIT(val, 1, max) >> 1;
|
||||
/* fan divisors max out at 128 */
|
||||
val = SENSORS_LIMIT(val, 1, 128) >> 1;
|
||||
for (i = 0; i < 7; i++) {
|
||||
if (val == 0)
|
||||
break;
|
||||
|
@ -530,6 +528,7 @@ static ssize_t store_fan_div(struct device *dev, struct device_attribute *attr,
|
|||
unsigned long min;
|
||||
u8 tmp_fan_div;
|
||||
u8 fan_div_reg;
|
||||
u8 vbat_reg;
|
||||
int indx = 0;
|
||||
u8 keep_mask = 0;
|
||||
u8 new_shift = 0;
|
||||
|
@ -581,6 +580,16 @@ static ssize_t store_fan_div(struct device *dev, struct device_attribute *attr,
|
|||
w83791d_write(client, W83791D_REG_FAN_DIV[indx],
|
||||
fan_div_reg | tmp_fan_div);
|
||||
|
||||
/* Bit 2 of fans 0-2 is stored in the vbat register (bits 5-7) */
|
||||
if (nr < 3) {
|
||||
keep_mask = ~(1 << (nr + 5));
|
||||
vbat_reg = w83791d_read(client, W83791D_REG_VBAT)
|
||||
& keep_mask;
|
||||
tmp_fan_div = (data->fan_div[nr] << (3 + nr)) & ~keep_mask;
|
||||
w83791d_write(client, W83791D_REG_VBAT,
|
||||
vbat_reg | tmp_fan_div);
|
||||
}
|
||||
|
||||
/* Restore fan_min */
|
||||
data->fan_min[nr] = fan_to_reg(min, DIV_FROM_REG(data->fan_div[nr]));
|
||||
w83791d_write(client, W83791D_REG_FAN_MIN[nr], data->fan_min[nr]);
|
||||
|
@ -1182,6 +1191,7 @@ static struct w83791d_data *w83791d_update_device(struct device *dev)
|
|||
struct w83791d_data *data = i2c_get_clientdata(client);
|
||||
int i, j;
|
||||
u8 reg_array_tmp[3];
|
||||
u8 vbat_reg;
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
|
||||
|
@ -1219,6 +1229,12 @@ static struct w83791d_data *w83791d_update_device(struct device *dev)
|
|||
data->fan_div[3] = reg_array_tmp[2] & 0x07;
|
||||
data->fan_div[4] = (reg_array_tmp[2] >> 4) & 0x07;
|
||||
|
||||
/* The fan divisor for fans 0-2 get bit 2 from
|
||||
bits 5-7 respectively of vbat register */
|
||||
vbat_reg = w83791d_read(client, W83791D_REG_VBAT);
|
||||
for (i = 0; i < 3; i++)
|
||||
data->fan_div[i] |= (vbat_reg >> (3 + i)) & 0x04;
|
||||
|
||||
/* Update the first temperature sensor */
|
||||
for (i = 0; i < 3; i++) {
|
||||
data->temp1[i] = w83791d_read(client,
|
||||
|
|
Loading…
Reference in a new issue