From: ASSI <Stromeko@nexgo.de>
To: linux-iio@vger.kernel.org
Subject: Re: [PATCH v9 1/4] iio: pressure: bmp280: Use sleep and forced mode for oneshot captures
Date: Sun, 27 Jul 2025 21:08:39 +0200 [thread overview]
Message-ID: <87ldo9wix4.fsf@Gerda.invalid> (raw)
In-Reply-To: 87pldm244b.fsf@Gerda.invalid
ASSI writes:
> ASSI writes:
> Since the BMx280 don't actually have a frequency setting and need to set
> standby times between measurements instead (for which I haven't found an
> easily usable parameter in the IIO framework), the permissible frequency
> settings are calculated for the lowest possible measurement time
> (oversampling=1 for all channels). The actual frequencies could be
> caclulated from the current settings and made available on read, but I
> haven't implemented that yet -- at the moment you'll get back the value
> you have set independent of the actual oversampling ratios.
Implemented and that actually helped find another bug hiding in plain
sight in the original code…
> Another issue I found while perusing the sources is that the filter has
> a fixed setting of 4 for these chips, which might be made changeable by
> using the filter_coefficient. Not looked at what that entails,
> though.
Implemented.
> I've got a sparse checkout of the kernel repo now, so if you think that
> this may be acceptable I can work on getting that into the form you are
> expecting (either a single commit or a series) and iron out any kinks
> you see.
I have a patch series that checkpatch.pl no longer complains about, but
I'll probably go over it at least one more time before submission.
Full patch for anybody wanting to give it a try (BMx[135]80 need testing
since I don't have any):
--8<---------------cut here---------------start------------->8---
diff --git a/drivers/iio/pressure/bmp280-core.c b/drivers/iio/pressure/bmp280-core.c
index f37f20776c89..22a49356ca9c 100644
--- a/drivers/iio/pressure/bmp280-core.c
+++ b/drivers/iio/pressure/bmp280-core.c
@@ -64,7 +64,32 @@
*/
enum { AC1, AC2, AC3, AC4, AC5, AC6, B1, B2, MB, MC, MD };
+enum bmp280_odr {
+ BMP280_ODR_0HZ, /* MODE_FORCED */
+ BMP280_ODR_110HZ, /* t_sb = 0.5ms */
+ BMP280_ODR_14HZ, /* t_sb = 62.5ms */
+ BMP280_ODR_7_5HZ, /* t_sb = 125ms */
+ BMP280_ODR_3_85HZ, /* t_sb = 250ms */
+ BMP280_ODR_1_96HZ, /* t_sb = 500ms */
+ BMP280_ODR_0_99HZ, /* t_sb = 1000ms */
+ BMP280_ODR_0_49HZ, /* t_sb = 2000ms */
+ BMP280_ODR_0_24HZ, /* t_sb = 4000ms */
+};
+
+enum bme280_odr {
+ BME280_ODR_0HZ, /* MODE_FORCED */
+ BME280_ODR_110HZ, /* t_sb = 0.5ms */
+ BME280_ODR_14HZ, /* t_sb = 62.5ms */
+ BME280_ODR_7_5HZ, /* t_sb = 125ms */
+ BME280_ODR_3_85HZ, /* t_sb = 250ms */
+ BME280_ODR_1_96HZ, /* t_sb = 500ms */
+ BME280_ODR_0_99HZ, /* t_sb = 1000ms */
+ BME280_ODR_51HZ, /* t_sb = 10ms */
+ BME280_ODR_34HZ, /* t_sb = 20ms */
+};
+
enum bmp380_odr {
+ BMP380_ODR_0HZ, /* MODE_FORCED */
BMP380_ODR_200HZ,
BMP380_ODR_100HZ,
BMP380_ODR_50HZ,
@@ -86,6 +111,7 @@ enum bmp380_odr {
};
enum bmp580_odr {
+ BMP580_ODR_0HZ, /* MODE_FORCED */
BMP580_ODR_240HZ,
BMP580_ODR_218HZ,
BMP580_ODR_199HZ,
@@ -159,6 +185,8 @@ static const struct iio_chan_spec bmp280_channels[] = {
BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_SCALE) |
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ) |
+ BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY),
.scan_index = 0,
.scan_type = {
.sign = 'u',
@@ -174,6 +202,8 @@ static const struct iio_chan_spec bmp280_channels[] = {
BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_SCALE) |
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ) |
+ BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY),
.scan_index = 1,
.scan_type = {
.sign = 's',
@@ -193,6 +223,8 @@ static const struct iio_chan_spec bme280_channels[] = {
BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_SCALE) |
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ) |
+ BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY),
.scan_index = 0,
.scan_type = {
.sign = 'u',
@@ -208,6 +240,8 @@ static const struct iio_chan_spec bme280_channels[] = {
BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_SCALE) |
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ) |
+ BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY),
.scan_index = 1,
.scan_type = {
.sign = 's',
@@ -223,6 +257,8 @@ static const struct iio_chan_spec bme280_channels[] = {
BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_SCALE) |
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ) |
+ BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY),
.scan_index = 2,
.scan_type = {
.sign = 'u',
@@ -612,6 +648,45 @@ static int bme280_read_humid(struct bmp280_data *data, u32 *comp_humidity)
return 0;
}
+static unsigned int bmp280_calc_meas_time_us(struct bmp280_data *data)
+{
+ unsigned int meas_time_us = BMP280_MEAS_OFFSET;
+
+ meas_time_us = BMP280_MEAS_OFFSET;
+
+ /* Check if we are using a BME280 device */
+ if (data->chip_info->oversampling_humid_avail)
+ meas_time_us += BMP280_PRESS_HUMID_MEAS_OFFSET +
+ BIT(data->oversampling_humid) * BMP280_MEAS_DUR;
+
+ /* Pressure measurement time */
+ meas_time_us += BMP280_PRESS_HUMID_MEAS_OFFSET +
+ BIT(data->oversampling_press) * BMP280_MEAS_DUR;
+
+ /* Temperature measurement time */
+ meas_time_us += BIT(data->oversampling_temp) * BMP280_MEAS_DUR;
+
+ /* nominal value */
+ return meas_time_us;
+}
+
+static void bmp280_calc_sampling_frequency(struct bmp280_data *data, int *val, int *val2)
+{
+ unsigned int cycle_time_us;
+ unsigned long freq_uHz;
+
+ if (data->chip_info->sampling_freq_tstby) {
+ cycle_time_us = bmp280_calc_meas_time_us(data);
+ cycle_time_us += data->chip_info->sampling_freq_tstby[data->sampling_freq];
+ freq_uHz = 1000000000000L / cycle_time_us;
+ *val = freq_uHz / 1000000L;
+ *val2 = freq_uHz % 1000000L;
+ } else {
+ *val = data->chip_info->sampling_freq_avail[data->sampling_freq][0];
+ *val2 = data->chip_info->sampling_freq_avail[data->sampling_freq][1];
+ }
+}
+
static int bmp280_read_raw_impl(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
@@ -619,55 +694,68 @@ static int bmp280_read_raw_impl(struct iio_dev *indio_dev,
struct bmp280_data *data = iio_priv(indio_dev);
int chan_value;
int ret;
+ int prev_oversampling_humid, prev_oversampling_press, prev_oversampling_temp;
+ int temp_oversampling_humid, temp_oversampling_press, temp_oversampling_temp;
+ int switch_off, switch_threshold = -1;
+ int raw = 0;
guard(mutex)(&data->lock);
+ prev_oversampling_humid = temp_oversampling_humid = data->oversampling_humid;
+ prev_oversampling_press = temp_oversampling_press = data->oversampling_press;
+ prev_oversampling_temp = temp_oversampling_temp = data->oversampling_temp;
+
+ data->op_mode = data->sampling_freq ? BMP280_NORMAL : BMP280_FORCED;
+
switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ raw = 1;
+ fallthrough;
case IIO_CHAN_INFO_PROCESSED:
- ret = data->chip_info->set_mode(data, BMP280_FORCED);
- if (ret)
- return ret;
+ switch_off = 0;
+ if (data->op_mode == BMP280_FORCED) {
+ /* switch off unused channels */
+ switch (chan->type) {
+ case IIO_HUMIDITYRELATIVE:
+ temp_oversampling_press = 0-1;
+ switch_off |= (prev_oversampling_press > switch_threshold);
+ temp_oversampling_temp = 1-1; /* can't be switched off as it is needed for compensation */
+ break;
+ case IIO_PRESSURE:
+ temp_oversampling_humid = 0-1;
+ switch_off |= (prev_oversampling_humid > switch_threshold);
+ temp_oversampling_temp = 1-1; /* can't be switched off as it is needed for compensation */
+ break;
+ case IIO_TEMP:
+ temp_oversampling_humid = 0-1;
+ temp_oversampling_press = 0-1;
+ switch_off = (prev_oversampling_humid > switch_threshold) | (prev_oversampling_press > switch_threshold);
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
+ if (switch_off) {
+ data->oversampling_humid = temp_oversampling_humid;
+ data->oversampling_press = temp_oversampling_press;
+ data->oversampling_temp = temp_oversampling_temp;
+ ret = data->chip_info->chip_config(data);
+ if (ret)
+ goto restore;
+ }
ret = data->chip_info->wait_conv(data);
if (ret)
- return ret;
+ goto restore;
- switch (chan->type) {
- case IIO_HUMIDITYRELATIVE:
- ret = data->chip_info->read_humid(data, &chan_value);
- if (ret)
- return ret;
-
- *val = data->chip_info->humid_coeffs[0] * chan_value;
- *val2 = data->chip_info->humid_coeffs[1];
- return data->chip_info->humid_coeffs_type;
- case IIO_PRESSURE:
- ret = data->chip_info->read_press(data, &chan_value);
- if (ret)
- return ret;
-
- *val = data->chip_info->press_coeffs[0] * chan_value;
- *val2 = data->chip_info->press_coeffs[1];
- return data->chip_info->press_coeffs_type;
- case IIO_TEMP:
- ret = data->chip_info->read_temp(data, &chan_value);
+ if (switch_off) {
+ data->oversampling_humid = prev_oversampling_humid;
+ data->oversampling_press = prev_oversampling_press;
+ data->oversampling_temp = prev_oversampling_temp;
+ ret = data->chip_info->chip_config(data);
if (ret)
return ret;
-
- *val = data->chip_info->temp_coeffs[0] * chan_value;
- *val2 = data->chip_info->temp_coeffs[1];
- return data->chip_info->temp_coeffs_type;
- default:
- return -EINVAL;
}
- case IIO_CHAN_INFO_RAW:
- ret = data->chip_info->set_mode(data, BMP280_FORCED);
- if (ret)
- return ret;
-
- ret = data->chip_info->wait_conv(data);
- if (ret)
- return ret;
switch (chan->type) {
case IIO_HUMIDITYRELATIVE:
@@ -675,22 +763,40 @@ static int bmp280_read_raw_impl(struct iio_dev *indio_dev,
if (ret)
return ret;
- *val = chan_value;
- return IIO_VAL_INT;
+ if (raw) {
+ *val = chan_value;
+ return IIO_VAL_INT;
+ } else {
+ *val = data->chip_info->humid_coeffs[0] * chan_value;
+ *val2 = data->chip_info->humid_coeffs[1];
+ return data->chip_info->humid_coeffs_type;
+ }
case IIO_PRESSURE:
ret = data->chip_info->read_press(data, &chan_value);
if (ret)
return ret;
- *val = chan_value;
- return IIO_VAL_INT;
+ if (raw) {
+ *val = chan_value;
+ return IIO_VAL_INT;
+ } else {
+ *val = data->chip_info->press_coeffs[0] * chan_value;
+ *val2 = data->chip_info->press_coeffs[1];
+ return data->chip_info->press_coeffs_type;
+ }
case IIO_TEMP:
ret = data->chip_info->read_temp(data, &chan_value);
if (ret)
return ret;
- *val = chan_value;
- return IIO_VAL_INT;
+ if (raw) {
+ *val = chan_value;
+ return IIO_VAL_INT;
+ } else {
+ *val = data->chip_info->temp_coeffs[0] * chan_value;
+ *val2 = data->chip_info->temp_coeffs[1];
+ return data->chip_info->temp_coeffs_type;
+ }
default:
return -EINVAL;
}
@@ -728,19 +834,26 @@ static int bmp280_read_raw_impl(struct iio_dev *indio_dev,
case IIO_CHAN_INFO_SAMP_FREQ:
if (!data->chip_info->sampling_freq_avail)
return -EINVAL;
-
- *val = data->chip_info->sampling_freq_avail[data->sampling_freq][0];
- *val2 = data->chip_info->sampling_freq_avail[data->sampling_freq][1];
+ bmp280_calc_sampling_frequency(data, val, val2);
return IIO_VAL_INT_PLUS_MICRO;
case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
if (!data->chip_info->iir_filter_coeffs_avail)
return -EINVAL;
- *val = (1 << data->iir_filter_coeff) - 1;
+ *val = data->chip_info->iir_filter_coeffs_avail[data->iir_filter_coeff];
return IIO_VAL_INT;
default:
return -EINVAL;
}
+ restore:
+ if (switch_off) {
+ /* restore channel configuration */
+ data->oversampling_humid = prev_oversampling_humid;
+ data->oversampling_press = prev_oversampling_press;
+ data->oversampling_temp = prev_oversampling_temp;
+ data->chip_info->chip_config(data);
+ }
+ return ret;
}
static int bmp280_read_raw(struct iio_dev *indio_dev,
@@ -852,6 +965,10 @@ static int bmp280_write_sampling_frequency(struct bmp280_data *data,
data->chip_info->chip_config(data);
return ret;
}
+ ret = data->chip_info->set_mode(data, (i ? BMP280_NORMAL : BMP280_FORCED));
+ if (ret)
+ return ret;
+
return 0;
}
}
@@ -866,7 +983,7 @@ static int bmp280_write_iir_filter_coeffs(struct bmp280_data *data, int val)
int i;
for (i = 0; i < n; i++) {
- if (avail[i] - 1 == val) {
+ if (avail[i] == val) {
prev = data->iir_filter_coeff;
data->iir_filter_coeff = i;
@@ -988,6 +1105,54 @@ static const unsigned long bme280_avail_scan_masks[] = {
0
};
+static const int bmp280_odr_table[][2] = {
+ [BMP280_ODR_0HZ] = {0, 0}, /* MODE_FORCED */
+ [BMP280_ODR_110HZ] = {110, 0},
+ [BMP280_ODR_14HZ] = {14, 0},
+ [BMP280_ODR_7_5HZ] = {7, 500000},
+ [BMP280_ODR_3_85HZ] = {3, 850000},
+ [BMP280_ODR_1_96HZ] = {1, 960000},
+ [BMP280_ODR_0_99HZ] = {0, 990000},
+ [BMP280_ODR_0_49HZ] = {0, 490000},
+ [BMP280_ODR_0_24HZ] = {0, 240000},
+};
+/* must be the same size as the ODR table */
+static const int bmp280_tstby_table[] = {
+ [BMP280_ODR_0HZ] = 0,
+ [BMP280_ODR_110HZ] = 500,
+ [BMP280_ODR_14HZ] = 62500,
+ [BMP280_ODR_7_5HZ] = 125000,
+ [BMP280_ODR_3_85HZ] = 250000,
+ [BMP280_ODR_1_96HZ] = 500000,
+ [BMP280_ODR_0_99HZ] = 1000000,
+ [BMP280_ODR_0_49HZ] = 2000000,
+ [BMP280_ODR_0_24HZ] = 4000000,
+};
+
+static const int bme280_odr_table[][2] = {
+ [BME280_ODR_0HZ] = {0, 0}, /* MODE_FORCED */
+ [BME280_ODR_110HZ] = {110, 0},
+ [BME280_ODR_14HZ] = {14, 0},
+ [BME280_ODR_7_5HZ] = {7, 500000},
+ [BME280_ODR_3_85HZ] = {3, 850000},
+ [BME280_ODR_1_96HZ] = {1, 960000},
+ [BME280_ODR_0_99HZ] = {0, 990000},
+ [BME280_ODR_51HZ] = {51, 0},
+ [BME280_ODR_34HZ] = {34, 0},
+};
+/* must be the same size as the ODR table */
+static const int bme280_tstby_table[] = {
+ [BME280_ODR_0HZ] = 0,
+ [BME280_ODR_110HZ] = 500,
+ [BME280_ODR_14HZ] = 62500,
+ [BME280_ODR_7_5HZ] = 125000,
+ [BME280_ODR_3_85HZ] = 250000,
+ [BME280_ODR_1_96HZ] = 500000,
+ [BME280_ODR_0_99HZ] = 1000000,
+ [BME280_ODR_51HZ] = 10000,
+ [BME280_ODR_34HZ] = 20000,
+};
+
static int bmp280_preinit(struct bmp280_data *data)
{
struct device *dev = data->dev;
@@ -1025,6 +1190,8 @@ static int bmp280_set_mode(struct bmp280_data *data, enum bmp280_op_mode mode)
{
int ret;
+ data->op_mode = BMP280_SLEEP;
+
ret = regmap_write_bits(data->regmap, BMP280_REG_CTRL_MEAS,
BMP280_MODE_MASK, bmp280_operation_mode[mode]);
if (ret) {
@@ -1041,30 +1208,32 @@ static int bmp280_wait_conv(struct bmp280_data *data)
{
unsigned int reg, meas_time_us;
int ret;
+ int meas_cycles = 4;
- /* Check if we are using a BME280 device */
- if (data->oversampling_humid)
- meas_time_us = BMP280_PRESS_HUMID_MEAS_OFFSET +
- BIT(data->oversampling_humid) * BMP280_MEAS_DUR;
+ /* is this really necessary or can we skip if op_mode is already BMP280_NORMAL? */
+ ret = data->chip_info->set_mode(data, data->op_mode);
+ if (ret)
+ return ret;
- else
- meas_time_us = 0;
+ if (data->op_mode == BMP280_NORMAL)
+ return 0;
- /* Pressure measurement time */
- meas_time_us += BMP280_PRESS_HUMID_MEAS_OFFSET +
- BIT(data->oversampling_press) * BMP280_MEAS_DUR;
+ meas_time_us = bmp280_calc_meas_time_us(data);
- /* Temperature measurement time */
- meas_time_us += BIT(data->oversampling_temp) * BMP280_MEAS_DUR;
+ do {
+ /* Waiting time according to the BM(P/E)2 Sensor API */
+ fsleep(meas_time_us);
- /* Waiting time according to the BM(P/E)2 Sensor API */
- fsleep(meas_time_us);
+ ret = regmap_read(data->regmap, BMP280_REG_STATUS, ®);
+ if (ret) {
+ dev_err(data->dev, "failed to read status register.\n");
+ return ret;
+ }
- ret = regmap_read(data->regmap, BMP280_REG_STATUS, ®);
- if (ret) {
- dev_err(data->dev, "failed to read status register.\n");
- return ret;
- }
+ meas_time_us >>= 3;
+ } while ((reg & BMP280_REG_STATUS_MEAS_BIT) && --meas_cycles);
+
+ data->op_mode = BMP280_SLEEP;
if (reg & BMP280_REG_STATUS_MEAS_BIT) {
dev_err(data->dev, "Measurement cycle didn't complete.\n");
@@ -1078,6 +1247,7 @@ static int bmp280_chip_config(struct bmp280_data *data)
{
u8 osrs = FIELD_PREP(BMP280_OSRS_TEMP_MASK, data->oversampling_temp + 1) |
FIELD_PREP(BMP280_OSRS_PRESS_MASK, data->oversampling_press + 1);
+ u8 tstby = FIELD_PREP(BMP280_TSTBY_MASK, (data->sampling_freq ? data->sampling_freq - 1 : 0));
int ret;
ret = regmap_write_bits(data->regmap, BMP280_REG_CTRL_MEAS,
@@ -1091,8 +1261,9 @@ static int bmp280_chip_config(struct bmp280_data *data)
}
ret = regmap_update_bits(data->regmap, BMP280_REG_CONFIG,
+ BMP280_TSTBY_MASK |
BMP280_FILTER_MASK,
- BMP280_FILTER_4X);
+ tstby | data->iir_filter_coeff);
if (ret) {
dev_err(data->dev, "failed to write config register\n");
return ret;
@@ -1157,6 +1328,7 @@ static const int bmp280_oversampling_avail[] = { 1, 2, 4, 8, 16 };
static const u8 bmp280_chip_ids[] = { BMP280_CHIP_ID };
static const int bmp280_temp_coeffs[] = { 10, 1 };
static const int bmp280_press_coeffs[] = { 1, 256000 };
+static const int bmp280_iir_filter_coeffs_avail[] = { 0, 2, 4, 8, 16 };
const struct bmp280_chip_info bmp280_chip_info = {
.id_reg = BMP280_REG_ID,
@@ -1186,6 +1358,15 @@ const struct bmp280_chip_info bmp280_chip_info = {
.num_oversampling_press_avail = ARRAY_SIZE(bmp280_oversampling_avail),
.oversampling_press_default = BMP280_OSRS_PRESS_16X - 1,
+ .sampling_freq_tstby = bmp280_tstby_table,
+ .sampling_freq_avail = bmp280_odr_table,
+ .num_sampling_freq_avail = ARRAY_SIZE(bmp280_odr_table) * 2,
+ .sampling_freq_default = BMP280_ODR_0HZ, /* MODE_FORCED */
+
+ .iir_filter_coeffs_avail = bmp280_iir_filter_coeffs_avail,
+ .num_iir_filter_coeffs_avail = ARRAY_SIZE(bmp280_iir_filter_coeffs_avail),
+ .iir_filter_coeff_default = 2,
+
.temp_coeffs = bmp280_temp_coeffs,
.temp_coeffs_type = IIO_VAL_FRACTIONAL,
.press_coeffs = bmp280_press_coeffs,
@@ -1371,6 +1552,15 @@ const struct bmp280_chip_info bme280_chip_info = {
.num_oversampling_humid_avail = ARRAY_SIZE(bmp280_oversampling_avail),
.oversampling_humid_default = BME280_OSRS_HUMIDITY_16X - 1,
+ .sampling_freq_tstby = bme280_tstby_table,
+ .sampling_freq_avail = bme280_odr_table,
+ .num_sampling_freq_avail = ARRAY_SIZE(bme280_odr_table) * 2,
+ .sampling_freq_default = BME280_ODR_0HZ, /* MODE_FORCED */
+
+ .iir_filter_coeffs_avail = bmp280_iir_filter_coeffs_avail,
+ .num_iir_filter_coeffs_avail = ARRAY_SIZE(bmp280_iir_filter_coeffs_avail),
+ .iir_filter_coeff_default = 2,
+
.temp_coeffs = bmp280_temp_coeffs,
.temp_coeffs_type = IIO_VAL_FRACTIONAL,
.press_coeffs = bmp280_press_coeffs,
@@ -1701,6 +1891,11 @@ static int bmp380_wait_conv(struct bmp280_data *data)
unsigned int reg;
int ret, meas_time_us;
+ /* is this really necessary or can we skip if op_mode is already BMP280_NORMAL? */
+ ret = data->chip_info->set_mode(data, data->op_mode);
+ if (ret)
+ return ret;
+
/* Offset measurement time */
meas_time_us = BMP380_MEAS_OFFSET;
@@ -1954,7 +2149,7 @@ static irqreturn_t bmp380_trigger_handler(int irq, void *p)
}
static const int bmp380_oversampling_avail[] = { 1, 2, 4, 8, 16, 32 };
-static const int bmp380_iir_filter_coeffs_avail[] = { 1, 2, 4, 8, 16, 32, 64, 128};
+static const int bmp380_iir_filter_coeffs_avail[] = { 0, 1, 3, 7, 15, 31, 63, 127 };
static const u8 bmp380_chip_ids[] = { BMP380_CHIP_ID, BMP390_CHIP_ID };
static const int bmp380_temp_coeffs[] = { 10, 1 };
static const int bmp380_press_coeffs[] = { 1, 100000 };
@@ -2435,6 +2630,12 @@ static int bmp580_wait_conv(struct bmp280_data *data)
21840,
};
int meas_time_us;
+ int ret;
+
+ /* is this really necessary or can we skip if op_mode is already BMP280_NORMAL? */
+ ret = data->chip_info->set_mode(data, data->op_mode);
+ if (ret)
+ return ret;
meas_time_us = 4 * USEC_PER_MSEC +
time_conv_temp[data->oversampling_temp] +
diff --git a/drivers/iio/pressure/bmp280.h b/drivers/iio/pressure/bmp280.h
index 25bb9c743a05..990ccb38da13 100644
--- a/drivers/iio/pressure/bmp280.h
+++ b/drivers/iio/pressure/bmp280.h
@@ -248,6 +248,16 @@
#define BMP280_FILTER_8X 3
#define BMP280_FILTER_16X 4
+#define BMP280_TSTBY_MASK GENMASK(7, 5)
+#define BMP280_TSTBY_0_5 0
+#define BMP280_TSTBY_62_5 1
+#define BMP280_TSTBY_125 2
+#define BMP280_TSTBY_250 3
+#define BMP280_TSTBY_500 4
+#define BMP280_TSTBY_1000 5
+#define BMP280_TSTBY_2000 6
+#define BMP280_TSTBY_4000 7
+
#define BMP280_OSRS_TEMP_MASK GENMASK(7, 5)
#define BMP280_OSRS_TEMP_SKIP 0
#define BMP280_OSRS_TEMP_1X 1
@@ -269,9 +279,9 @@
#define BMP280_MODE_FORCED 1
#define BMP280_MODE_NORMAL 3
-#define BMP280_MEAS_OFFSET 1250
-#define BMP280_MEAS_DUR 2300
-#define BMP280_PRESS_HUMID_MEAS_OFFSET 575
+#define BMP280_MEAS_OFFSET 1095 /* ceil(1250/(1+2^-3+2^-6+2^-9) */
+#define BMP280_MEAS_DUR 2013 /* ceil(2300/(1+2^-3+2^-6+2^-9) */
+#define BMP280_PRESS_HUMID_MEAS_OFFSET 504 /* ceil( 575/(1+2^-3+2^-6+2^-9) */
/* BME280 specific registers */
#define BME280_REG_HUMIDITY_LSB 0xFE
@@ -294,6 +304,16 @@
#define BME280_CONTIGUOUS_CALIB_REGS 7
+#define BME280_TSTBY_MASK GENMASK(7, 5)
+#define BME280_TSTBY_0_5 0
+#define BME280_TSTBY_62_5 1
+#define BME280_TSTBY_125 2
+#define BME280_TSTBY_250 3
+#define BME280_TSTBY_500 4
+#define BME280_TSTBY_1000 5
+#define BME280_TSTBY_1 6
+#define BME280_TSTBY_20 7
+
#define BME280_OSRS_HUMIDITY_MASK GENMASK(2, 0)
#define BME280_OSRS_HUMIDITY_SKIP 0
#define BME280_OSRS_HUMIDITY_1X 1
@@ -501,6 +521,7 @@ struct bmp280_chip_info {
int num_iir_filter_coeffs_avail;
int iir_filter_coeff_default;
+ const int *sampling_freq_tstby;
const int (*sampling_freq_avail)[2];
int num_sampling_freq_avail;
int sampling_freq_default;
--8<---------------cut here---------------end--------------->8---
Regards,
Achim.
--
+<[Q+ Matrix-12 WAVE#46+305 Neuron microQkb Andromeda XTk Blofeld]>+
next prev parent reply other threads:[~2025-07-27 19:08 UTC|newest]
Thread overview: 71+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-10-17 23:30 [PATCH v9 0/4] pressure: bmp280: Minor cleanup and interrupt support Vasileios Amoiridis
2024-10-17 23:30 ` [PATCH v9 1/4] iio: pressure: bmp280: Use sleep and forced mode for oneshot captures Vasileios Amoiridis
2025-06-28 18:45 ` ASSI
2025-06-28 20:57 ` David Lechner
2025-06-29 7:43 ` ASSI
2025-07-11 19:17 ` ASSI
2025-07-12 14:49 ` ASSI
2025-07-21 19:15 ` ASSI
2025-07-26 18:34 ` ASSI
2025-07-27 19:08 ` ASSI [this message]
2024-10-17 23:30 ` [PATCH v9 2/4] dt-bindings: iio: pressure: bmp085: Add interrupts for BMP3xx and BMP5xx devices Vasileios Amoiridis
2024-10-17 23:30 ` [PATCH v9 3/4] iio: pressure: bmp280: Add data ready trigger support Vasileios Amoiridis
2024-10-17 23:30 ` [PATCH v9 4/4] iio: pressure: bmp280: Move bmp085 interrupt to new configuration Vasileios Amoiridis
2024-10-19 13:55 ` [PATCH v9 0/4] pressure: bmp280: Minor cleanup and interrupt support Jonathan Cameron
2025-08-03 14:07 ` [bmp280 v1 0/6] Fixes and enhancements for the bmp280 driver Achim Gratz
2025-08-03 14:07 ` [bmp280 v1 1/6] iio: pressure: bmp280: correct meas_time_us calculation Achim Gratz
2025-08-06 15:46 ` Jonathan Cameron
2025-08-06 17:53 ` ASSI
2025-08-10 18:04 ` Jonathan Cameron
2025-08-03 14:07 ` [bmp280 v1 2/6] iio: pressure: bmp280: reduce overhead on read with MODE_FORCED Achim Gratz
2025-08-03 20:12 ` Andy Shevchenko
2025-08-06 15:58 ` Jonathan Cameron
2025-08-06 18:00 ` ASSI
2025-08-03 14:07 ` [bmp280 v1 3/6] iio: pressure: bmp280: implement sampling_frequency for BMx280 Achim Gratz
2025-08-03 20:26 ` Andy Shevchenko
2025-08-04 17:29 ` ASSI
2025-08-10 18:11 ` Jonathan Cameron
2025-08-10 19:12 ` ASSI
2025-08-11 19:48 ` Jonathan Cameron
2025-08-12 19:53 ` ASSI
2025-08-17 15:10 ` Jonathan Cameron
2025-08-17 16:36 ` ASSI
2025-08-03 14:08 ` [bmp280 v1 4/6] iio: pressure: bmp280: enable filter settings " Achim Gratz
2025-08-03 20:28 ` Andy Shevchenko
2025-08-04 17:14 ` ASSI
2025-08-10 18:13 ` Jonathan Cameron
2025-08-10 19:01 ` ASSI
2025-08-11 20:14 ` Jonathan Cameron
2025-08-12 19:34 ` ASSI
2025-08-17 14:51 ` Jonathan Cameron
2025-08-03 14:08 ` [bmp280 v1 5/6] iio: pressure: bmp280: remove code duplication Achim Gratz
2025-08-03 20:30 ` Andy Shevchenko
2025-08-10 18:19 ` Jonathan Cameron
2025-08-03 14:08 ` [bmp280 v1 6/6] iio: pressure: bmp280: implement sampling_frequency calculation for BMx280 Achim Gratz
2025-08-03 20:37 ` Andy Shevchenko
2025-08-04 17:20 ` ASSI
2025-08-03 19:20 ` [bmp280 v1 0/6] Fixes and enhancements for the bmp280 driver Andy Shevchenko
2025-08-10 18:58 ` [RFC PATCH v2 0/9] " Achim Gratz
2025-08-10 18:58 ` [RFC PATCH v2 1/9] iio: pressure: bmp280: correct meas_time_us calculation Achim Gratz
2025-08-17 15:16 ` Jonathan Cameron
2025-08-10 18:58 ` [RFC PATCH v2 2/9] iio: pressure: bmp280: implement adaptive wait for BMx280 devices Achim Gratz
2025-08-10 19:49 ` Andy Shevchenko
2025-08-16 18:42 ` ASSI
2025-08-10 18:58 ` [RFC PATCH v2 3/9] iio: pressure: bmp280: implement adaptive wait for BMP380 devices Achim Gratz
2025-08-10 18:58 ` [RFC PATCH v2 4/9] iio: pressure: bmp280: refactoring Achim Gratz
2025-08-17 15:23 ` Jonathan Cameron
2025-08-10 18:58 ` [RFC PATCH v2 5/9] iio: pressure: bmp280: remove code duplication Achim Gratz
2025-08-10 18:58 ` [RFC PATCH v2 6/9] iio: pressure: bmp280: enable filter settings for BMx280 Achim Gratz
2025-08-17 16:37 ` Jonathan Cameron
2025-08-10 18:58 ` [RFC PATCH v2 7/9] iio: pressure: bmp280: implement sampling_frequency " Achim Gratz
2025-08-17 16:53 ` Jonathan Cameron
2025-08-17 17:36 ` ASSI
2025-08-10 18:58 ` [RFC PATCH v2 8/9] iio: pressure: bmp280: implement sampling_frequency calculation " Achim Gratz
2025-08-17 17:04 ` Jonathan Cameron
2025-08-17 17:40 ` ASSI
2025-08-18 17:52 ` Jonathan Cameron
2025-08-10 18:58 ` [RFC PATCH v2 9/9] iio: pressure: bmp280: test longer autosuspend (WIP) Achim Gratz
2025-08-17 17:05 ` Jonathan Cameron
2025-08-17 17:44 ` ASSI
2025-08-11 12:14 ` [RFC PATCH v2 0/9] Fixes and enhancements for the bmp280 driver Andy Shevchenko
2025-08-11 20:17 ` Jonathan Cameron
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87ldo9wix4.fsf@Gerda.invalid \
--to=stromeko@nexgo.de \
--cc=linux-iio@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox