mirror of
https://github.com/adulau/aha.git
synced 2024-12-30 20:56:23 +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:
|
Additional contributors:
|
||||||
Sven Anders <anders@anduras.de>
|
Sven Anders <anders@anduras.de>
|
||||||
|
Marc Hulsman <m.hulsman@tudelft.nl>
|
||||||
|
|
||||||
Module Parameters
|
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
|
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
|
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
|
readings can be divided by a programmable divider (1, 2, 4, 8, 16,
|
||||||
and 1, 2, 4, 8, 16, 32, 64 or 128 for fan 4/5) to give the readings more
|
32, 64 or 128 for all fans) to give the readings more range or accuracy.
|
||||||
range or accuracy.
|
|
||||||
|
|
||||||
Voltage sensors (also known as IN sensors) report their values in millivolts.
|
Voltage sensors (also known as IN sensors) report their values in millivolts.
|
||||||
An alarm is triggered if the voltage has crossed a programmable minimum
|
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)
|
static u8 div_to_reg(int nr, long val)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int max;
|
|
||||||
|
|
||||||
/* first three fan's divisor max out at 8, rest max out at 128 */
|
/* fan divisors max out at 128 */
|
||||||
max = (nr < 3) ? 8 : 128;
|
val = SENSORS_LIMIT(val, 1, 128) >> 1;
|
||||||
val = SENSORS_LIMIT(val, 1, max) >> 1;
|
|
||||||
for (i = 0; i < 7; i++) {
|
for (i = 0; i < 7; i++) {
|
||||||
if (val == 0)
|
if (val == 0)
|
||||||
break;
|
break;
|
||||||
|
@ -530,6 +528,7 @@ static ssize_t store_fan_div(struct device *dev, struct device_attribute *attr,
|
||||||
unsigned long min;
|
unsigned long min;
|
||||||
u8 tmp_fan_div;
|
u8 tmp_fan_div;
|
||||||
u8 fan_div_reg;
|
u8 fan_div_reg;
|
||||||
|
u8 vbat_reg;
|
||||||
int indx = 0;
|
int indx = 0;
|
||||||
u8 keep_mask = 0;
|
u8 keep_mask = 0;
|
||||||
u8 new_shift = 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],
|
w83791d_write(client, W83791D_REG_FAN_DIV[indx],
|
||||||
fan_div_reg | tmp_fan_div);
|
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 */
|
/* Restore fan_min */
|
||||||
data->fan_min[nr] = fan_to_reg(min, DIV_FROM_REG(data->fan_div[nr]));
|
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]);
|
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);
|
struct w83791d_data *data = i2c_get_clientdata(client);
|
||||||
int i, j;
|
int i, j;
|
||||||
u8 reg_array_tmp[3];
|
u8 reg_array_tmp[3];
|
||||||
|
u8 vbat_reg;
|
||||||
|
|
||||||
mutex_lock(&data->update_lock);
|
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[3] = reg_array_tmp[2] & 0x07;
|
||||||
data->fan_div[4] = (reg_array_tmp[2] >> 4) & 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 */
|
/* Update the first temperature sensor */
|
||||||
for (i = 0; i < 3; i++) {
|
for (i = 0; i < 3; i++) {
|
||||||
data->temp1[i] = w83791d_read(client,
|
data->temp1[i] = w83791d_read(client,
|
||||||
|
|
Loading…
Reference in a new issue