Commit a4f765e7 authored by Vasileios Amoiridis's avatar Vasileios Amoiridis Committed by Jonathan Cameron

iio: chemical: bme680: Use bulk reads for calibration data

Calibration data are located in contiguous-ish registers inside the chip.
For that reason we can use bulk reads as is done as well in the BME68x
Sensor API [1].

The arrays that are used for reading the data out of the sensor
are located inside DMA safe buffer.

Link: https://github.com/boschsensortec/BME68x_SensorAPI/blob/v4.4.8/bme68x.c#L1769 # [1]
Signed-off-by: default avatarVasileios Amoiridis <vassilisamir@gmail.com>
Link: https://patch.msgid.link/20240609233826.330516-8-vassilisamir@gmail.comSigned-off-by: default avatarJonathan Cameron <Jonathan.Cameron@huawei.com>
parent 5a387668
...@@ -39,10 +39,8 @@ ...@@ -39,10 +39,8 @@
#define BME680_HUM_REG_SHIFT_VAL 4 #define BME680_HUM_REG_SHIFT_VAL 4
#define BME680_BIT_H1_DATA_MASK GENMASK(3, 0) #define BME680_BIT_H1_DATA_MASK GENMASK(3, 0)
#define BME680_REG_RES_HEAT_RANGE 0x02
#define BME680_RHRANGE_MASK GENMASK(5, 4) #define BME680_RHRANGE_MASK GENMASK(5, 4)
#define BME680_REG_RES_HEAT_VAL 0x00 #define BME680_REG_RES_HEAT_VAL 0x00
#define BME680_REG_RANGE_SW_ERR 0x04
#define BME680_RSERROR_MASK GENMASK(7, 4) #define BME680_RSERROR_MASK GENMASK(7, 4)
#define BME680_REG_RES_HEAT_0 0x5A #define BME680_REG_RES_HEAT_0 0x5A
#define BME680_REG_GAS_WAIT_0 0x64 #define BME680_REG_GAS_WAIT_0 0x64
...@@ -60,31 +58,13 @@ ...@@ -60,31 +58,13 @@
/* Calibration Parameters */ /* Calibration Parameters */
#define BME680_T2_LSB_REG 0x8A #define BME680_T2_LSB_REG 0x8A
#define BME680_T3_REG 0x8C
#define BME680_P1_LSB_REG 0x8E
#define BME680_P2_LSB_REG 0x90
#define BME680_P3_REG 0x92
#define BME680_P4_LSB_REG 0x94
#define BME680_P5_LSB_REG 0x96
#define BME680_P7_REG 0x98
#define BME680_P6_REG 0x99
#define BME680_P8_LSB_REG 0x9C
#define BME680_P9_LSB_REG 0x9E
#define BME680_P10_REG 0xA0
#define BME680_H2_LSB_REG 0xE2
#define BME680_H2_MSB_REG 0xE1 #define BME680_H2_MSB_REG 0xE1
#define BME680_H1_MSB_REG 0xE3
#define BME680_H1_LSB_REG 0xE2
#define BME680_H3_REG 0xE4
#define BME680_H4_REG 0xE5
#define BME680_H5_REG 0xE6
#define BME680_H6_REG 0xE7
#define BME680_H7_REG 0xE8
#define BME680_T1_LSB_REG 0xE9
#define BME680_GH2_LSB_REG 0xEB
#define BME680_GH1_REG 0xED
#define BME680_GH3_REG 0xEE #define BME680_GH3_REG 0xEE
#define BME680_CALIB_RANGE_1_LEN 23
#define BME680_CALIB_RANGE_2_LEN 14
#define BME680_CALIB_RANGE_3_LEN 5
extern const struct regmap_config bme680_regmap_config; extern const struct regmap_config bme680_regmap_config;
int bme680_core_probe(struct device *dev, struct regmap *regmap, int bme680_core_probe(struct device *dev, struct regmap *regmap,
......
...@@ -19,8 +19,53 @@ ...@@ -19,8 +19,53 @@
#include <linux/iio/iio.h> #include <linux/iio/iio.h>
#include <linux/iio/sysfs.h> #include <linux/iio/sysfs.h>
#include <asm/unaligned.h>
#include "bme680.h" #include "bme680.h"
/* 1st set of calibration data */
enum {
/* Temperature calib indexes */
T2_LSB = 0,
T3 = 2,
/* Pressure calib indexes */
P1_LSB = 4,
P2_LSB = 6,
P3 = 8,
P4_LSB = 10,
P5_LSB = 12,
P7 = 14,
P6 = 15,
P8_LSB = 18,
P9_LSB = 20,
P10 = 22,
};
/* 2nd set of calibration data */
enum {
/* Humidity calib indexes */
H2_MSB = 0,
H1_LSB = 1,
H3 = 3,
H4 = 4,
H5 = 5,
H6 = 6,
H7 = 7,
/* Stray T1 calib index */
T1_LSB = 8,
/* Gas heater calib indexes */
GH2_LSB = 10,
GH1 = 12,
GH3 = 13,
};
/* 3rd set of calibration data */
enum {
RES_HEAT_VAL = 0,
RES_HEAT_RANGE = 2,
RANGE_SW_ERR = 4,
};
struct bme680_calib { struct bme680_calib {
u16 par_t1; u16 par_t1;
s16 par_t2; s16 par_t2;
...@@ -64,6 +109,12 @@ struct bme680_data { ...@@ -64,6 +109,12 @@ struct bme680_data {
* and humidity compensation calculations. * and humidity compensation calculations.
*/ */
s32 t_fine; s32 t_fine;
union {
u8 bme680_cal_buf_1[BME680_CALIB_RANGE_1_LEN];
u8 bme680_cal_buf_2[BME680_CALIB_RANGE_2_LEN];
u8 bme680_cal_buf_3[BME680_CALIB_RANGE_3_LEN];
};
}; };
static const struct regmap_range bme680_volatile_ranges[] = { static const struct regmap_range bme680_volatile_ranges[] = {
...@@ -112,217 +163,73 @@ static int bme680_read_calib(struct bme680_data *data, ...@@ -112,217 +163,73 @@ static int bme680_read_calib(struct bme680_data *data,
struct bme680_calib *calib) struct bme680_calib *calib)
{ {
struct device *dev = regmap_get_device(data->regmap); struct device *dev = regmap_get_device(data->regmap);
unsigned int tmp, tmp_msb, tmp_lsb; unsigned int tmp_msb, tmp_lsb;
int ret; int ret;
__le16 buf;
/* Temperature related coefficients */
ret = regmap_bulk_read(data->regmap, BME680_T1_LSB_REG,
&buf, sizeof(buf));
if (ret < 0) {
dev_err(dev, "failed to read BME680_T1_LSB_REG\n");
return ret;
}
calib->par_t1 = le16_to_cpu(buf);
ret = regmap_bulk_read(data->regmap, BME680_T2_LSB_REG, ret = regmap_bulk_read(data->regmap, BME680_T2_LSB_REG,
&buf, sizeof(buf)); data->bme680_cal_buf_1,
if (ret < 0) { sizeof(data->bme680_cal_buf_1));
dev_err(dev, "failed to read BME680_T2_LSB_REG\n");
return ret;
}
calib->par_t2 = le16_to_cpu(buf);
ret = regmap_read(data->regmap, BME680_T3_REG, &tmp);
if (ret < 0) {
dev_err(dev, "failed to read BME680_T3_REG\n");
return ret;
}
calib->par_t3 = tmp;
/* Pressure related coefficients */
ret = regmap_bulk_read(data->regmap, BME680_P1_LSB_REG,
&buf, sizeof(buf));
if (ret < 0) {
dev_err(dev, "failed to read BME680_P1_LSB_REG\n");
return ret;
}
calib->par_p1 = le16_to_cpu(buf);
ret = regmap_bulk_read(data->regmap, BME680_P2_LSB_REG,
&buf, sizeof(buf));
if (ret < 0) {
dev_err(dev, "failed to read BME680_P2_LSB_REG\n");
return ret;
}
calib->par_p2 = le16_to_cpu(buf);
ret = regmap_read(data->regmap, BME680_P3_REG, &tmp);
if (ret < 0) { if (ret < 0) {
dev_err(dev, "failed to read BME680_P3_REG\n"); dev_err(dev, "failed to read 1st set of calib data;\n");
return ret; return ret;
} }
calib->par_p3 = tmp;
ret = regmap_bulk_read(data->regmap, BME680_P4_LSB_REG, calib->par_t2 = get_unaligned_le16(&data->bme680_cal_buf_1[T2_LSB]);
&buf, sizeof(buf)); calib->par_t3 = data->bme680_cal_buf_1[T3];
if (ret < 0) { calib->par_p1 = get_unaligned_le16(&data->bme680_cal_buf_1[P1_LSB]);
dev_err(dev, "failed to read BME680_P4_LSB_REG\n"); calib->par_p2 = get_unaligned_le16(&data->bme680_cal_buf_1[P2_LSB]);
return ret; calib->par_p3 = data->bme680_cal_buf_1[P3];
} calib->par_p4 = get_unaligned_le16(&data->bme680_cal_buf_1[P4_LSB]);
calib->par_p4 = le16_to_cpu(buf); calib->par_p5 = get_unaligned_le16(&data->bme680_cal_buf_1[P5_LSB]);
calib->par_p7 = data->bme680_cal_buf_1[P7];
calib->par_p6 = data->bme680_cal_buf_1[P6];
calib->par_p8 = get_unaligned_le16(&data->bme680_cal_buf_1[P8_LSB]);
calib->par_p9 = get_unaligned_le16(&data->bme680_cal_buf_1[P9_LSB]);
calib->par_p10 = data->bme680_cal_buf_1[P10];
ret = regmap_bulk_read(data->regmap, BME680_P5_LSB_REG, ret = regmap_bulk_read(data->regmap, BME680_H2_MSB_REG,
&buf, sizeof(buf)); data->bme680_cal_buf_2,
sizeof(data->bme680_cal_buf_2));
if (ret < 0) { if (ret < 0) {
dev_err(dev, "failed to read BME680_P5_LSB_REG\n"); dev_err(dev, "failed to read 2nd set of calib data;\n");
return ret; return ret;
} }
calib->par_p5 = le16_to_cpu(buf);
ret = regmap_read(data->regmap, BME680_P6_REG, &tmp); tmp_lsb = data->bme680_cal_buf_2[H1_LSB];
if (ret < 0) { tmp_msb = data->bme680_cal_buf_2[H1_LSB + 1];
dev_err(dev, "failed to read BME680_P6_REG\n");
return ret;
}
calib->par_p6 = tmp;
ret = regmap_read(data->regmap, BME680_P7_REG, &tmp);
if (ret < 0) {
dev_err(dev, "failed to read BME680_P7_REG\n");
return ret;
}
calib->par_p7 = tmp;
ret = regmap_bulk_read(data->regmap, BME680_P8_LSB_REG,
&buf, sizeof(buf));
if (ret < 0) {
dev_err(dev, "failed to read BME680_P8_LSB_REG\n");
return ret;
}
calib->par_p8 = le16_to_cpu(buf);
ret = regmap_bulk_read(data->regmap, BME680_P9_LSB_REG,
&buf, sizeof(buf));
if (ret < 0) {
dev_err(dev, "failed to read BME680_P9_LSB_REG\n");
return ret;
}
calib->par_p9 = le16_to_cpu(buf);
ret = regmap_read(data->regmap, BME680_P10_REG, &tmp);
if (ret < 0) {
dev_err(dev, "failed to read BME680_P10_REG\n");
return ret;
}
calib->par_p10 = tmp;
/* Humidity related coefficients */
ret = regmap_read(data->regmap, BME680_H1_MSB_REG, &tmp_msb);
if (ret < 0) {
dev_err(dev, "failed to read BME680_H1_MSB_REG\n");
return ret;
}
ret = regmap_read(data->regmap, BME680_H1_LSB_REG, &tmp_lsb);
if (ret < 0) {
dev_err(dev, "failed to read BME680_H1_LSB_REG\n");
return ret;
}
calib->par_h1 = (tmp_msb << BME680_HUM_REG_SHIFT_VAL) | calib->par_h1 = (tmp_msb << BME680_HUM_REG_SHIFT_VAL) |
(tmp_lsb & BME680_BIT_H1_DATA_MASK); (tmp_lsb & BME680_BIT_H1_DATA_MASK);
ret = regmap_read(data->regmap, BME680_H2_MSB_REG, &tmp_msb); tmp_msb = data->bme680_cal_buf_2[H2_MSB];
if (ret < 0) { tmp_lsb = data->bme680_cal_buf_2[H2_MSB + 1];
dev_err(dev, "failed to read BME680_H2_MSB_REG\n");
return ret;
}
ret = regmap_read(data->regmap, BME680_H2_LSB_REG, &tmp_lsb);
if (ret < 0) {
dev_err(dev, "failed to read BME680_H2_LSB_REG\n");
return ret;
}
calib->par_h2 = (tmp_msb << BME680_HUM_REG_SHIFT_VAL) | calib->par_h2 = (tmp_msb << BME680_HUM_REG_SHIFT_VAL) |
(tmp_lsb >> BME680_HUM_REG_SHIFT_VAL); (tmp_lsb >> BME680_HUM_REG_SHIFT_VAL);
ret = regmap_read(data->regmap, BME680_H3_REG, &tmp); calib->par_h3 = data->bme680_cal_buf_2[H3];
if (ret < 0) { calib->par_h4 = data->bme680_cal_buf_2[H4];
dev_err(dev, "failed to read BME680_H3_REG\n"); calib->par_h5 = data->bme680_cal_buf_2[H5];
return ret; calib->par_h6 = data->bme680_cal_buf_2[H6];
} calib->par_h7 = data->bme680_cal_buf_2[H7];
calib->par_h3 = tmp; calib->par_t1 = get_unaligned_le16(&data->bme680_cal_buf_2[T1_LSB]);
calib->par_gh2 = get_unaligned_le16(&data->bme680_cal_buf_2[GH2_LSB]);
calib->par_gh1 = data->bme680_cal_buf_2[GH1];
calib->par_gh3 = data->bme680_cal_buf_2[GH3];
ret = regmap_read(data->regmap, BME680_H4_REG, &tmp); ret = regmap_bulk_read(data->regmap, BME680_REG_RES_HEAT_VAL,
data->bme680_cal_buf_3,
sizeof(data->bme680_cal_buf_3));
if (ret < 0) { if (ret < 0) {
dev_err(dev, "failed to read BME680_H4_REG\n"); dev_err(dev, "failed to read 3rd set of calib data;\n");
return ret; return ret;
} }
calib->par_h4 = tmp;
ret = regmap_read(data->regmap, BME680_H5_REG, &tmp); calib->res_heat_val = data->bme680_cal_buf_3[RES_HEAT_VAL];
if (ret < 0) {
dev_err(dev, "failed to read BME680_H5_REG\n");
return ret;
}
calib->par_h5 = tmp;
ret = regmap_read(data->regmap, BME680_H6_REG, &tmp); calib->res_heat_range = FIELD_GET(BME680_RHRANGE_MASK,
if (ret < 0) { data->bme680_cal_buf_3[RES_HEAT_RANGE]);
dev_err(dev, "failed to read BME680_H6_REG\n");
return ret;
}
calib->par_h6 = tmp;
ret = regmap_read(data->regmap, BME680_H7_REG, &tmp); calib->range_sw_err = FIELD_GET(BME680_RSERROR_MASK,
if (ret < 0) { data->bme680_cal_buf_3[RANGE_SW_ERR]);
dev_err(dev, "failed to read BME680_H7_REG\n");
return ret;
}
calib->par_h7 = tmp;
/* Gas heater related coefficients */
ret = regmap_read(data->regmap, BME680_GH1_REG, &tmp);
if (ret < 0) {
dev_err(dev, "failed to read BME680_GH1_REG\n");
return ret;
}
calib->par_gh1 = tmp;
ret = regmap_bulk_read(data->regmap, BME680_GH2_LSB_REG,
&buf, sizeof(buf));
if (ret < 0) {
dev_err(dev, "failed to read BME680_GH2_LSB_REG\n");
return ret;
}
calib->par_gh2 = le16_to_cpu(buf);
ret = regmap_read(data->regmap, BME680_GH3_REG, &tmp);
if (ret < 0) {
dev_err(dev, "failed to read BME680_GH3_REG\n");
return ret;
}
calib->par_gh3 = tmp;
/* Other coefficients */
ret = regmap_read(data->regmap, BME680_REG_RES_HEAT_RANGE, &tmp);
if (ret < 0) {
dev_err(dev, "failed to read resistance heat range\n");
return ret;
}
calib->res_heat_range = FIELD_GET(BME680_RHRANGE_MASK, tmp);
ret = regmap_read(data->regmap, BME680_REG_RES_HEAT_VAL, &tmp);
if (ret < 0) {
dev_err(dev, "failed to read resistance heat value\n");
return ret;
}
calib->res_heat_val = tmp;
ret = regmap_read(data->regmap, BME680_REG_RANGE_SW_ERR, &tmp);
if (ret < 0) {
dev_err(dev, "failed to read range software error\n");
return ret;
}
calib->range_sw_err = FIELD_GET(BME680_RSERROR_MASK, tmp);
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment