Linux IIO development
 help / color / mirror / Atom feed
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, &reg);
+		if (ret) {
+			dev_err(data->dev, "failed to read status register.\n");
+			return ret;
+		}
 
-	ret = regmap_read(data->regmap, BMP280_REG_STATUS, &reg);
-	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]>+



  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