From 8f19501d87e0e79a50b60ead7e114ed5a8eea34e Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Fri, 5 Nov 2021 16:04:52 -0700 Subject: 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 --- drivers/hwmon/lm90.c | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) (limited to 'drivers/hwmon/lm90.c') 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; -- cgit v1.2.3