Skip to content

Commit

Permalink
hwmon: (w83791d) Use fan divisor bits from vbat register
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Marc Hulsman authored and Jean Delvare committed Aug 6, 2008
1 parent 05a5e47 commit ad02ad8
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 7 deletions.
6 changes: 3 additions & 3 deletions Documentation/hwmon/w83791d
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ Credits:

Additional contributors:
Sven Anders <anders@anduras.de>
Marc Hulsman <m.hulsman@tudelft.nl>

Module Parameters
-----------------
Expand Down Expand Up @@ -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
Expand Down
24 changes: 20 additions & 4 deletions drivers/hwmon/w83791d.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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]);
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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,
Expand Down

0 comments on commit ad02ad8

Please sign in to comment.