mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-01 02:33:57 +00:00
iio: chemical: bme680: Refactorize reading functions
The reading of the pressure and humidity value, requires an update of the t_fine variable which happens by reading the temperature value. So the bme680_read_{press/humid}() functions of the above sensors are internally calling the equivalent bme680_read_temp() function in order to update the t_fine value. By just looking at the code this relation is a bit hidden and is not easy to understand why those channels are not independent. This commit tries to clear these thing a bit by splitting the bme680_{read/compensate}_{temp/press/humid}() to the following: i. bme680_read_{temp/press/humid}_adc(): read the raw value from the sensor. ii. bme680_calc_t_fine(): calculate the t_fine variable. iii. bme680_get_t_fine(): get the t_fine variable. iv. bme680_compensate_{temp/press/humid}(): compensate the adc values and return the calculated value. v. bme680_read_{temp/press/humid}(): combine calls of the aforementioned functions to return the requested value. Signed-off-by: Vasileios Amoiridis <vassilisamir@gmail.com> Link: https://patch.msgid.link/20240609233826.330516-16-vassilisamir@gmail.com Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
This commit is contained in:
parent
ed4bb53c46
commit
d2651a43f3
@ -104,11 +104,6 @@ struct bme680_data {
|
||||
u8 oversampling_humid;
|
||||
u16 heater_dur;
|
||||
u16 heater_temp;
|
||||
/*
|
||||
* Carryover value from temperature conversion, used in pressure
|
||||
* and humidity compensation calculations.
|
||||
*/
|
||||
s32 t_fine;
|
||||
|
||||
union {
|
||||
u8 buf[3];
|
||||
@ -237,6 +232,31 @@ static int bme680_read_calib(struct bme680_data *data,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bme680_read_temp_adc(struct bme680_data *data, u32 *adc_temp)
|
||||
{
|
||||
struct device *dev = regmap_get_device(data->regmap);
|
||||
u32 value_temp;
|
||||
int ret;
|
||||
|
||||
ret = regmap_bulk_read(data->regmap, BME680_REG_TEMP_MSB,
|
||||
data->buf, BME680_TEMP_NUM_BYTES);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to read temperature\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
value_temp = FIELD_GET(BME680_MEAS_TRIM_MASK,
|
||||
get_unaligned_be24(data->buf));
|
||||
if (value_temp == BME680_MEAS_SKIPPED) {
|
||||
/* reading was skipped */
|
||||
dev_err(dev, "reading temperature skipped\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
*adc_temp = value_temp;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Taken from Bosch BME680 API:
|
||||
* https://github.com/BoschSensortec/BME680_driver/blob/63bb5336/bme680.c#L876
|
||||
@ -244,12 +264,10 @@ static int bme680_read_calib(struct bme680_data *data,
|
||||
* Returns temperature measurement in DegC, resolutions is 0.01 DegC. Therefore,
|
||||
* output value of "3233" represents 32.33 DegC.
|
||||
*/
|
||||
static s16 bme680_compensate_temp(struct bme680_data *data,
|
||||
u32 adc_temp)
|
||||
static s32 bme680_calc_t_fine(struct bme680_data *data, u32 adc_temp)
|
||||
{
|
||||
struct bme680_calib *calib = &data->bme680;
|
||||
s64 var1, var2, var3;
|
||||
s16 calc_temp;
|
||||
|
||||
/* If the calibration is invalid, attempt to reload it */
|
||||
if (!calib->par_t2)
|
||||
@ -259,10 +277,52 @@ static s16 bme680_compensate_temp(struct bme680_data *data,
|
||||
var2 = (var1 * calib->par_t2) >> 11;
|
||||
var3 = ((var1 >> 1) * (var1 >> 1)) >> 12;
|
||||
var3 = (var3 * ((s32)calib->par_t3 << 4)) >> 14;
|
||||
data->t_fine = var2 + var3;
|
||||
calc_temp = (data->t_fine * 5 + 128) >> 8;
|
||||
return var2 + var3; /* t_fine = var2 + var3 */
|
||||
}
|
||||
|
||||
return calc_temp;
|
||||
static int bme680_get_t_fine(struct bme680_data *data, s32 *t_fine)
|
||||
{
|
||||
u32 adc_temp;
|
||||
int ret;
|
||||
|
||||
ret = bme680_read_temp_adc(data, &adc_temp);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
*t_fine = bme680_calc_t_fine(data, adc_temp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static s16 bme680_compensate_temp(struct bme680_data *data,
|
||||
u32 adc_temp)
|
||||
{
|
||||
return (bme680_calc_t_fine(data, adc_temp) * 5 + 128) / 256;
|
||||
}
|
||||
|
||||
static int bme680_read_press_adc(struct bme680_data *data, u32 *adc_press)
|
||||
{
|
||||
struct device *dev = regmap_get_device(data->regmap);
|
||||
u32 value_press;
|
||||
int ret;
|
||||
|
||||
ret = regmap_bulk_read(data->regmap, BME680_REG_PRESS_MSB,
|
||||
data->buf, BME680_PRESS_NUM_BYTES);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to read pressure\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
value_press = FIELD_GET(BME680_MEAS_TRIM_MASK,
|
||||
get_unaligned_be24(data->buf));
|
||||
if (value_press == BME680_MEAS_SKIPPED) {
|
||||
/* reading was skipped */
|
||||
dev_err(dev, "reading pressure skipped\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
*adc_press = value_press;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -273,12 +333,12 @@ static s16 bme680_compensate_temp(struct bme680_data *data,
|
||||
* 97356 Pa = 973.56 hPa.
|
||||
*/
|
||||
static u32 bme680_compensate_press(struct bme680_data *data,
|
||||
u32 adc_press)
|
||||
u32 adc_press, s32 t_fine)
|
||||
{
|
||||
struct bme680_calib *calib = &data->bme680;
|
||||
s32 var1, var2, var3, press_comp;
|
||||
|
||||
var1 = (data->t_fine >> 1) - 64000;
|
||||
var1 = (t_fine >> 1) - 64000;
|
||||
var2 = ((((var1 >> 2) * (var1 >> 2)) >> 11) * calib->par_p6) >> 2;
|
||||
var2 = var2 + (var1 * calib->par_p5 << 1);
|
||||
var2 = (var2 >> 2) + ((s32)calib->par_p4 << 16);
|
||||
@ -306,6 +366,30 @@ static u32 bme680_compensate_press(struct bme680_data *data,
|
||||
return press_comp;
|
||||
}
|
||||
|
||||
static int bme680_read_humid_adc(struct bme680_data *data, u32 *adc_humidity)
|
||||
{
|
||||
struct device *dev = regmap_get_device(data->regmap);
|
||||
u32 value_humidity;
|
||||
int ret;
|
||||
|
||||
ret = regmap_bulk_read(data->regmap, BME680_REG_HUMIDITY_MSB,
|
||||
&data->be16, BME680_HUMID_NUM_BYTES);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to read humidity\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
value_humidity = be16_to_cpu(data->be16);
|
||||
if (value_humidity == BME680_MEAS_SKIPPED) {
|
||||
/* reading was skipped */
|
||||
dev_err(dev, "reading humidity skipped\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
*adc_humidity = value_humidity;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Taken from Bosch BME680 API:
|
||||
* https://github.com/BoschSensortec/BME680_driver/blob/63bb5336/bme680.c#L937
|
||||
@ -314,12 +398,12 @@ static u32 bme680_compensate_press(struct bme680_data *data,
|
||||
* value of "43215" represents 43.215 %rH.
|
||||
*/
|
||||
static u32 bme680_compensate_humid(struct bme680_data *data,
|
||||
u16 adc_humid)
|
||||
u16 adc_humid, s32 t_fine)
|
||||
{
|
||||
struct bme680_calib *calib = &data->bme680;
|
||||
s32 var1, var2, var3, var4, var5, var6, temp_scaled, calc_hum;
|
||||
|
||||
temp_scaled = (data->t_fine * 5 + 128) >> 8;
|
||||
temp_scaled = (t_fine * 5 + 128) >> 8;
|
||||
var1 = (adc_humid - (((s32)calib->par_h1 * 16))) -
|
||||
(((temp_scaled * calib->par_h3) / 100) >> 1);
|
||||
var2 = (calib->par_h2 *
|
||||
@ -567,68 +651,35 @@ static int bme680_gas_config(struct bme680_data *data)
|
||||
|
||||
static int bme680_read_temp(struct bme680_data *data, int *val)
|
||||
{
|
||||
struct device *dev = regmap_get_device(data->regmap);
|
||||
int ret;
|
||||
u32 adc_temp;
|
||||
s16 comp_temp;
|
||||
|
||||
ret = regmap_bulk_read(data->regmap, BME680_REG_TEMP_MSB,
|
||||
data->buf, BME680_TEMP_NUM_BYTES);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to read temperature\n");
|
||||
ret = bme680_read_temp_adc(data, &adc_temp);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
adc_temp = FIELD_GET(BME680_MEAS_TRIM_MASK,
|
||||
get_unaligned_be24(data->buf));
|
||||
if (adc_temp == BME680_MEAS_SKIPPED) {
|
||||
/* reading was skipped */
|
||||
dev_err(dev, "reading temperature skipped\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
comp_temp = bme680_compensate_temp(data, adc_temp);
|
||||
/*
|
||||
* val might be NULL if we're called by the read_press/read_humid
|
||||
* routine which is called to get t_fine value used in
|
||||
* compensate_press/compensate_humid to get compensated
|
||||
* pressure/humidity readings.
|
||||
*/
|
||||
if (val) {
|
||||
*val = comp_temp * 10; /* Centidegrees to millidegrees */
|
||||
return IIO_VAL_INT;
|
||||
}
|
||||
|
||||
return ret;
|
||||
*val = comp_temp * 10; /* Centidegrees to millidegrees */
|
||||
return IIO_VAL_INT;
|
||||
}
|
||||
|
||||
static int bme680_read_press(struct bme680_data *data,
|
||||
int *val, int *val2)
|
||||
{
|
||||
struct device *dev = regmap_get_device(data->regmap);
|
||||
int ret;
|
||||
u32 adc_press;
|
||||
s32 t_fine;
|
||||
|
||||
/* Read and compensate temperature to get a reading of t_fine */
|
||||
ret = bme680_read_temp(data, NULL);
|
||||
if (ret < 0)
|
||||
ret = bme680_get_t_fine(data, &t_fine);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = regmap_bulk_read(data->regmap, BME680_REG_PRESS_MSB,
|
||||
data->buf, BME680_PRESS_NUM_BYTES);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to read pressure\n");
|
||||
ret = bme680_read_press_adc(data, &adc_press);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
adc_press = FIELD_GET(BME680_MEAS_TRIM_MASK,
|
||||
get_unaligned_be24(data->buf));
|
||||
if (adc_press == BME680_MEAS_SKIPPED) {
|
||||
/* reading was skipped */
|
||||
dev_err(dev, "reading pressure skipped\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
*val = bme680_compensate_press(data, adc_press);
|
||||
*val = bme680_compensate_press(data, adc_press, t_fine);
|
||||
*val2 = 1000;
|
||||
return IIO_VAL_FRACTIONAL;
|
||||
}
|
||||
@ -636,30 +687,19 @@ static int bme680_read_press(struct bme680_data *data,
|
||||
static int bme680_read_humid(struct bme680_data *data,
|
||||
int *val, int *val2)
|
||||
{
|
||||
struct device *dev = regmap_get_device(data->regmap);
|
||||
int ret;
|
||||
u16 adc_humidity;
|
||||
u32 comp_humidity;
|
||||
u32 adc_humidity, comp_humidity;
|
||||
s32 t_fine;
|
||||
|
||||
/* Read and compensate temperature to get a reading of t_fine */
|
||||
ret = bme680_read_temp(data, NULL);
|
||||
if (ret < 0)
|
||||
ret = bme680_get_t_fine(data, &t_fine);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = regmap_bulk_read(data->regmap, BME680_REG_HUMIDITY_MSB,
|
||||
&data->be16, BME680_HUMID_NUM_BYTES);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to read humidity\n");
|
||||
ret = bme680_read_humid_adc(data, &adc_humidity);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
adc_humidity = be16_to_cpu(data->be16);
|
||||
if (adc_humidity == BME680_MEAS_SKIPPED) {
|
||||
/* reading was skipped */
|
||||
dev_err(dev, "reading humidity skipped\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
comp_humidity = bme680_compensate_humid(data, adc_humidity);
|
||||
comp_humidity = bme680_compensate_humid(data, adc_humidity, t_fine);
|
||||
|
||||
*val = comp_humidity;
|
||||
*val2 = 1000;
|
||||
|
Loading…
Reference in New Issue
Block a user