drivers: sensor: tmp108: Handle negative values correctly

Negative temperatures were converted to the sensor_value struct
incorrectly.
This fixes the causes: signed/unsigned mixups and integer overflows.
Also clarified temperature calculation using multiplier/divisor config
values.

Fixes #68240

Signed-off-by: Boris Mulder <b.mulder@innoseis.com>
This commit is contained in:
Boris Mulder 2024-02-01 14:47:18 +01:00 committed by Fabio Baltieri
parent d83c63ecce
commit f87143d919
2 changed files with 13 additions and 9 deletions

View file

@ -152,9 +152,9 @@ static int tmp108_channel_get(const struct device *dev,
return -ENOTSUP; return -ENOTSUP;
} }
uval = ((int32_t)(drv_data->sample) * TMP108_TEMP_MULTIPLIER(dev)) >> 4U; uval = ((int32_t)drv_data->sample * TMP108_TEMP_MULTIPLIER(dev)) / TMP108_TEMP_DIVISOR(dev);
val->val1 = uval / 1000000U; val->val1 = uval / 1000000;
val->val2 = uval % 1000000U; val->val2 = uval % 1000000;
return 0; return 0;
} }
@ -237,7 +237,7 @@ static int tmp108_attr_set(const struct device *dev,
case SENSOR_ATTR_LOWER_THRESH: case SENSOR_ATTR_LOWER_THRESH:
uval = val->val1 * 1000000 + val->val2; uval = val->val1 * 1000000 + val->val2;
reg_value = (uval << 4U) / TMP108_TEMP_MULTIPLIER(dev); reg_value = (uval * TMP108_TEMP_DIVISOR(dev)) / TMP108_TEMP_MULTIPLIER(dev);
result = tmp108_reg_write(dev, result = tmp108_reg_write(dev,
TI_TMP108_REG_LOW_LIMIT, TI_TMP108_REG_LOW_LIMIT,
reg_value); reg_value);
@ -245,7 +245,7 @@ static int tmp108_attr_set(const struct device *dev,
case SENSOR_ATTR_UPPER_THRESH: case SENSOR_ATTR_UPPER_THRESH:
uval = val->val1 * 1000000 + val->val2; uval = val->val1 * 1000000 + val->val2;
reg_value = (uval << 4U) / TMP108_TEMP_MULTIPLIER(dev); reg_value = (uval * TMP108_TEMP_DIVISOR(dev)) / TMP108_TEMP_MULTIPLIER(dev);
result = tmp108_reg_write(dev, result = tmp108_reg_write(dev,
TI_TMP108_REG_HIGH_LIMIT, TI_TMP108_REG_HIGH_LIMIT,
reg_value); reg_value);

View file

@ -29,7 +29,8 @@
.CONF_POL = 0x0400, \ .CONF_POL = 0x0400, \
.CONF_M0 = 0x8000, \ .CONF_M0 = 0x8000, \
.CONF_RST = 0x0080, \ .CONF_RST = 0x0080, \
.TEMP_MULT = 125000, \ .TEMP_MULT = 15625, \
.TEMP_DIV = 2, \
.WAKEUP_TIME_IN_MS = 120 } .WAKEUP_TIME_IN_MS = 120 }
#define TI_TMP108_CONF {.CONF_HYS0 = 0x0010, \ #define TI_TMP108_CONF {.CONF_HYS0 = 0x0010, \
@ -41,7 +42,8 @@
.CONF_CR0 = 0x2000, \ .CONF_CR0 = 0x2000, \
.CONF_CR1 = 0x4000, \ .CONF_CR1 = 0x4000, \
.CONF_RST = 0x0022, \ .CONF_RST = 0x0022, \
.TEMP_MULT = 62500, \ .TEMP_MULT = 15625, \
.TEMP_DIV = 4, \
.WAKEUP_TIME_IN_MS = 30 } .WAKEUP_TIME_IN_MS = 30 }
#define TI_TMP108_MODE_SHUTDOWN(x) 0 #define TI_TMP108_MODE_SHUTDOWN(x) 0
@ -77,6 +79,7 @@
#define TI_TMP108_CONF_M0(x) TI_TMP108_GET_CONF(x, CONF_M0) #define TI_TMP108_CONF_M0(x) TI_TMP108_GET_CONF(x, CONF_M0)
#define TMP108_TEMP_MULTIPLIER(x) TI_TMP108_GET_CONF(x, TEMP_MULT) #define TMP108_TEMP_MULTIPLIER(x) TI_TMP108_GET_CONF(x, TEMP_MULT)
#define TMP108_TEMP_DIVISOR(x) TI_TMP108_GET_CONF(x, TEMP_DIV)
#define TMP108_WAKEUP_TIME_IN_MS(x) TI_TMP108_GET_CONF(x, WAKEUP_TIME_IN_MS) #define TMP108_WAKEUP_TIME_IN_MS(x) TI_TMP108_GET_CONF(x, WAKEUP_TIME_IN_MS)
#define TMP108_CONF_RST(x) TI_TMP108_GET_CONF(x, CONF_RST) #define TMP108_CONF_RST(x) TI_TMP108_GET_CONF(x, CONF_RST)
@ -91,7 +94,8 @@ struct tmp_108_reg_def {
uint16_t CONF_TM; /** Thermostat mode setting bit */ uint16_t CONF_TM; /** Thermostat mode setting bit */
uint16_t CONF_HYS1; /** Temperature hysteresis config 1 bit */ uint16_t CONF_HYS1; /** Temperature hysteresis config 1 bit */
uint16_t CONF_HYS0; /** Temperature hysteresis config 2 bit */ uint16_t CONF_HYS0; /** Temperature hysteresis config 2 bit */
uint32_t TEMP_MULT; /** Temperature multiplier */ int32_t TEMP_MULT; /** Temperature multiplier */
int32_t TEMP_DIV; /** Temperature divisor */
uint16_t WAKEUP_TIME_IN_MS; /** Wake up and conversion time from one shot */ uint16_t WAKEUP_TIME_IN_MS; /** Wake up and conversion time from one shot */
uint16_t CONF_RST; /** default reset values on init */ uint16_t CONF_RST; /** default reset values on init */
}; };
@ -107,7 +111,7 @@ struct tmp108_config {
struct tmp108_data { struct tmp108_data {
const struct device *tmp108_dev; const struct device *tmp108_dev;
uint16_t sample; int16_t sample;
bool one_shot_mode; bool one_shot_mode;