diff options
author | Guenter Roeck <linux@roeck-us.net> | 2021-11-06 02:04:52 +0300 |
---|---|---|
committer | Guenter Roeck <linux@roeck-us.net> | 2022-07-13 18:38:17 +0300 |
commit | 8f19501d87e0e79a50b60ead7e114ed5a8eea34e (patch) | |
tree | 2c12deb3f0b5974ba4183726bf5eb4a6c3a9317d /drivers/hwmon/lm90.c | |
parent | b2644494a4c7145a05af01bee1df8549a71efc20 (diff) | |
download | linux-8f19501d87e0e79a50b60ead7e114ed5a8eea34e.tar.xz |
hwmon: (lm90) Only re-read registers if volatile
When reading 16-bit volatile registers, the code uses a trick to
determine if a temperature is consistent: It reads the high part
of the register twice. If the values are the same, the code assumes
that the reading is consistent. If the value differs, the code
re-reads the second register as well and assumes that it now has
correct values.
This is only necessary for volatile registers. Add a parameter to
lm90_read16() to indicate if the register is volatile to avoid the
extra overhead for non-volatile registers.
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Diffstat (limited to 'drivers/hwmon/lm90.c')
-rw-r--r-- | drivers/hwmon/lm90.c | 41 |
1 files changed, 23 insertions, 18 deletions
diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c index acb9ca3b99b0..b20be0cb28b5 100644 --- a/drivers/hwmon/lm90.c +++ b/drivers/hwmon/lm90.c @@ -602,29 +602,34 @@ static int lm90_write_reg(struct i2c_client *client, u8 reg, u8 val) return i2c_smbus_write_byte_data(client, lm90_write_reg_addr(reg), val); } -static int lm90_read16(struct i2c_client *client, u8 regh, u8 regl) +static int lm90_read16(struct i2c_client *client, u8 regh, u8 regl, + bool is_volatile) { int oldh, newh, l; - /* - * There is a trick here. We have to read two registers to have the - * sensor temperature, but we have to beware a conversion could occur - * between the readings. The datasheet says we should either use - * the one-shot conversion register, which we don't want to do - * (disables hardware monitoring) or monitor the busy bit, which is - * impossible (we can't read the values and monitor that bit at the - * exact same time). So the solution used here is to read the high - * byte once, then the low byte, then the high byte again. If the new - * high byte matches the old one, then we have a valid reading. Else - * we have to read the low byte again, and now we believe we have a - * correct reading. - */ oldh = lm90_read_reg(client, regh); if (oldh < 0) return oldh; l = lm90_read_reg(client, regl); if (l < 0) return l; + + if (!is_volatile) + return (oldh << 8) | l; + + /* + * For volatile registers we have to use a trick. + * We have to read two registers to have the sensor temperature, + * but we have to beware a conversion could occur between the + * readings. The datasheet says we should either use + * the one-shot conversion register, which we don't want to do + * (disables hardware monitoring) or monitor the busy bit, which is + * impossible (we can't read the values and monitor that bit at the + * exact same time). So the solution used here is to read the high + * the high byte again. If the new high byte matches the old one, + * then we have a valid reading. Otherwise we have to read the low + * byte again, and now we believe we have a correct reading. + */ newh = lm90_read_reg(client, regh); if (newh < 0) return newh; @@ -766,7 +771,7 @@ static int lm90_update_limits(struct device *dev) if (data->flags & LM90_HAVE_OFFSET) { val = lm90_read16(client, LM90_REG_REMOTE_OFFSH, - LM90_REG_REMOTE_OFFSL); + LM90_REG_REMOTE_OFFSL, false); if (val < 0) return val; data->temp11[REMOTE_OFFSET] = val; @@ -999,7 +1004,7 @@ static int lm90_update_device(struct device *dev) if (data->reg_local_ext) { val = lm90_read16(client, LM90_REG_LOCAL_TEMP, - data->reg_local_ext); + data->reg_local_ext, true); if (val < 0) return val; data->temp11[LOCAL_TEMP] = val; @@ -1010,7 +1015,7 @@ static int lm90_update_device(struct device *dev) data->temp11[LOCAL_TEMP] = val << 8; } val = lm90_read16(client, LM90_REG_REMOTE_TEMPH, - LM90_REG_REMOTE_TEMPL); + LM90_REG_REMOTE_TEMPL, true); if (val < 0) return val; data->temp11[REMOTE_TEMP] = val; @@ -1021,7 +1026,7 @@ static int lm90_update_device(struct device *dev) return val; val = lm90_read16(client, LM90_REG_REMOTE_TEMPH, - LM90_REG_REMOTE_TEMPL); + LM90_REG_REMOTE_TEMPL, true); if (val < 0) { lm90_select_remote_channel(data, 0); return val; |