Linux IIO development
 help / color / mirror / Atom feed
From: Jonathan Cameron <jic23@kernel.org>
To: Achim Gratz <Achim.Gratz@Stromeko.DE>
Cc: linux-iio@vger.kernel.org,
	"David Lechner" <dlechner@baylibre.com>,
	"Andy Shevchenko" <andy@kernel.org>,
	"Nuno Sá" <nuno.sa@analog.com>
Subject: Re: [RFC PATCH v3 7/9] iio: pressure: bmp280: implement sampling_frequency for BMx280
Date: Sat, 4 Oct 2025 16:32:52 +0100	[thread overview]
Message-ID: <20251004163252.5ec4e594@jic23-huawei> (raw)
In-Reply-To: <20250928172637.37138-9-Achim.Gratz@Stromeko.DE>

On Sun, 28 Sep 2025 19:26:35 +0200
Achim Gratz <Achim.Gratz@Stromeko.DE> wrote:

> As was already commented in bm280.h:468, sampling_frequency can be
> emulated on BMx280 devices indirectly via t_standby configuration.
> Actually implement it to enable this useful feature.  This allows to
> switch between MODE_FORCED and MODE_NORMAL operation and use the same
> sysfs read implementations for both modes.  As MODE_FORCED is a driver
> feature, the corresponding entry in the ODR table has to be added
> after the actual register settings.  The resulting register setting is
> either masked by the driver or clamped to a permissible value on
> device, so does not disturb the device operation.  MODE_FORCE is
> triggered by setting a sampling frequency of 0Hz, following the
> precedent of stm32_timer_trigger.
> 
> The bmp[235]_conv() functions check if the sensor already operates in
> NORMAL_MODE and skip waiting for measurement completion to save the
> overhead of the superfluous mode seting.
> 
> The actual sampling frequency depends on the oversampling_ratio
> settings. In order to keep the constant ODR tables, the available
> sampling frequency values are fixed and have been calculated for
> oversampling_ratio=1 on all available channels assuming maximum
> measurement duration per the data sheet truncated to three significant
> digits; corresponding to the minimum achievable sampling frequency for
> the highest measurement speed configuration.
> 
> The ODR tables for the BM[35]80 devices have been extended to allow
> for MODE_FORCED operation also and the handling of the table values in
> chip_config is adapted accordingly.
> 
> Report of the actual sampling frequency via sysfs is possible, but not
> yet implemented.  In preparation for that implementation the
> calculation of measurement time has previously been factored out from
> bmp280_conv into bmp280_calc_meas_time_us.
> 
> Signed-off-by: Achim Gratz <Achim.Gratz@Stromeko.DE>
> 
A few unrelated changes have slipped in here that should be broken out
so that this patch is clearly doing just one thing rather than several.

> ---
> 
> BME280 redefines the last two ODR register settings vs. BMP280, which
> are therefore out of order w.r.t. the other values.
> 
> Calculated ODR values:
> |--------+---------+---------|
> |   t_sb | min ODR | min ODR |
> |   [ms] |  BMP280 |  BME280 |
> |--------+---------+---------|
> |      0 | 155.642 | 107.527 |
> |    0.5 | 144.404 | 102.041 |
> |   62.5 |  14.509 |  13.928 |
> |  125.0 |   7.609 |   7.446 |
> |  250.0 |   3.900 |   3.857 |
> |  500.0 |   1.975 |   1.963 |
> | 1000.0 |   0.994 |   0.991 |
> | 2000.0 |   0.498 |     --- |
> | 4000.0 |   0.250 |     --- |
> |   10.0 |     --- |  51.813 |
> |   20.0 |     --- |  34.130 |
> |--------+---------+---------|
> 
> Proper consideration of the OSR when setting sampling_frequency could
> be introduced in a later patch after discussion of how to handle the
> combinatorial explosion of the table size or alternatively a
> complicated on-the-fly computation that also depends on the device
> type.  Note in particular that there are combinations of OSR and ODR
> settings for the BMP580 at least that are illegal and hence replaced
> by the device with a default setting, something this driver also
> currently does not check for or handle.
I'm a little confused. Is calculating this on demand what the next patch
is doing?

> 
> This driver currently also lacks the the *_available attributes and
> all associated implementation for all supported devices.  This should
> be introduced in conjunction with the previously mentioned patch, so
> that the available settings for the current configuration can be
> obtained from user space.
> ---
>  drivers/iio/pressure/bmp280-core.c | 297 ++++++++++++++++++++---------
>  drivers/iio/pressure/bmp280.h      |  22 ++-
>  2 files changed, 228 insertions(+), 91 deletions(-)
> 
> diff --git a/drivers/iio/pressure/bmp280-core.c b/drivers/iio/pressure/bmp280-core.c
> index e72cfd4c10b9..9ade6d9e047b 100644
> --- a/drivers/iio/pressure/bmp280-core.c
> +++ b/drivers/iio/pressure/bmp280-core.c

> @@ -816,7 +869,7 @@ static int bmp280_write_oversampling_ratio_press(struct bmp280_data *data,
>  	return -EINVAL;
>  }
>  
> -static int bmp280_write_sampling_frequency(struct bmp280_data *data,
> +static int bmp280_write_sampling_freq(struct bmp280_data *data,
>  					   int val, int val2)
>  {
>  	const int (*avail)[2] = data->chip_info->sampling_freq_avail;
> @@ -893,7 +946,7 @@ static int bmp280_write_raw_impl(struct iio_dev *indio_dev,
>  			return -EINVAL;
>  		}
>  	case IIO_CHAN_INFO_SAMP_FREQ:
> -		return bmp280_write_sampling_frequency(data, val, val2);
> +		return bmp280_write_sampling_freq(data, val, val2);

Rename is fine, but not in a patch doing anything more substantial.

>  	case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
>  		return bmp280_write_iir_filter_coeffs(data, val);
>  	default:
> @@ -971,6 +1024,34 @@ static const unsigned long bme280_avail_scan_masks[] = {
>  	0
>  };

> @@ -1098,24 +1185,28 @@ static int bmp280_conv(struct bmp280_data *data)
>  
>  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 filter = FIELD_PREP(BMP280_FILTER_MASK, data->iir_filter_coeff;
> +	u8 osr_temp  = FIELD_PREP(BMP280_OSRS_TEMP_MASK, data->oversampling_temp + 1);
> +	u8 osr_press = FIELD_PREP(BMP280_OSRS_PRESS_MASK, data->oversampling_press + 1);
> +	u8 filter    = FIELD_PREP(BMP280_FILTER_MASK, data->iir_filter_coeff);
> +	u8 tstby     = FIELD_PREP(BMP280_TSTBY_MASK, (data->sampling_freq ?: 1) - 1);
> +	u8 mode      = FIELD_PREP(BMP280_MODE_MASK, data->sampling_freq ? BMP280_NORMAL : BMP280_SLEEP);
>  	int ret;
>  
>  	ret = regmap_write_bits(data->regmap, BMP280_REG_CTRL_MEAS,
>  				BMP280_OSRS_TEMP_MASK |
>  				BMP280_OSRS_PRESS_MASK |
>  				BMP280_MODE_MASK,
> -				osrs | BMP280_MODE_SLEEP);
> +				osr_temp | osr_press | mode);
> +	if (ret)
> +		return ret;
>  	if (ret) {

Some rebase issue?  Can't get here for obvious reasons! :)

>  		dev_err(data->dev, "failed to write ctrl_meas register\n");
>  		return ret;
>  	}

> @@ -1675,24 +1774,26 @@ static int bmp380_read_calib(struct bmp280_data *data)
>  }
>  
>  static const int bmp380_odr_table[][2] = {
> -	[BMP380_ODR_200HZ]	= {200, 0},
> -	[BMP380_ODR_100HZ]	= {100, 0},
> -	[BMP380_ODR_50HZ]	= {50, 0},
> -	[BMP380_ODR_25HZ]	= {25, 0},
> -	[BMP380_ODR_12_5HZ]	= {12, 500000},
> -	[BMP380_ODR_6_25HZ]	= {6, 250000},
> -	[BMP380_ODR_3_125HZ]	= {3, 125000},
> -	[BMP380_ODR_1_5625HZ]	= {1, 562500},
> -	[BMP380_ODR_0_78HZ]	= {0, 781250},
> -	[BMP380_ODR_0_39HZ]	= {0, 390625},
> -	[BMP380_ODR_0_2HZ]	= {0, 195313},
> -	[BMP380_ODR_0_1HZ]	= {0, 97656},
> -	[BMP380_ODR_0_05HZ]	= {0, 48828},
> -	[BMP380_ODR_0_02HZ]	= {0, 24414},
> -	[BMP380_ODR_0_01HZ]	= {0, 12207},
> -	[BMP380_ODR_0_006HZ]	= {0, 6104},
> -	[BMP380_ODR_0_003HZ]	= {0, 3052},
> -	[BMP380_ODR_0_0015HZ]	= {0, 1526},
> +	/* BMP380_ODR_FORCED is a driver feature, not a register setting */
> +	[BMP380_ODR_FORCED]	= {   0,      0 },

Similar to below. The reformat is unrelated cause of noise in this patch
(but nice to have in a precursor!)

> +	[BMP380_ODR_200HZ]	= { 200,      0 },
> +	[BMP380_ODR_100HZ]	= { 100,      0 },
> +	[BMP380_ODR_50HZ]	= {  50,      0 },
> +	[BMP380_ODR_25HZ]	= {  25,      0 },
> +	[BMP380_ODR_12_5HZ]	= {  12, 500000 },
> +	[BMP380_ODR_6_25HZ]	= {   6, 250000 },
> +	[BMP380_ODR_3_125HZ]	= {   3, 125000 },
> +	[BMP380_ODR_1_5625HZ]	= {   1, 562500 },
> +	[BMP380_ODR_0_78HZ]	= {   0, 781250 },
> +	[BMP380_ODR_0_39HZ]	= {   0, 390625 },
> +	[BMP380_ODR_0_2HZ]	= {   0, 195313 },
> +	[BMP380_ODR_0_1HZ]	= {   0,  97656 },
> +	[BMP380_ODR_0_05HZ]	= {   0,  48828 },
> +	[BMP380_ODR_0_02HZ]	= {   0,  24414 },
> +	[BMP380_ODR_0_01HZ]	= {   0,  12207 },
> +	[BMP380_ODR_0_006HZ]	= {   0,   6104 },
> +	[BMP380_ODR_0_003HZ]	= {   0,   3052 },
> +	[BMP380_ODR_0_0015HZ]	= {   0,   1526 },
>  };

> @@ -2061,7 +2169,7 @@ static int bmp580_soft_reset(struct bmp280_data *data)
>  	fsleep(2000);
>  
>  	/* Dummy read of chip_id */
> -	ret = regmap_read(data->regmap, BMP580_REG_CHIP_ID, &reg);
> +	ret = regmap_read(data->regmap, BMP580_REG_ID, &reg);

Unrelated change.

>  	if (ret) {
>  		dev_err(data->dev, "failed to reestablish comms after reset\n");
>  		return ret;
> @@ -2205,38 +2313,40 @@ static int bmp580_read_press(struct bmp280_data *data, u32 *raw_press)
>  }
>  
>  static const int bmp580_odr_table[][2] = {
> -	[BMP580_ODR_240HZ] =	{240, 0},

whilst I do prefer your new formatting. That's mostly an unrelated change
that should be in a different patch.  This one should just
introduce the new entrees.

> -	[BMP580_ODR_218HZ] =	{218, 0},
> -	[BMP580_ODR_199HZ] =	{199, 0},
> -	[BMP580_ODR_179HZ] =	{179, 0},
> -	[BMP580_ODR_160HZ] =	{160, 0},
> -	[BMP580_ODR_149HZ] =	{149, 0},
> -	[BMP580_ODR_140HZ] =	{140, 0},
> -	[BMP580_ODR_129HZ] =	{129, 0},
> -	[BMP580_ODR_120HZ] =	{120, 0},
> -	[BMP580_ODR_110HZ] =	{110, 0},
> -	[BMP580_ODR_100HZ] =	{100, 0},
> -	[BMP580_ODR_89HZ] =	{89, 0},
> -	[BMP580_ODR_80HZ] =	{80, 0},
> -	[BMP580_ODR_70HZ] =	{70, 0},
> -	[BMP580_ODR_60HZ] =	{60, 0},
> -	[BMP580_ODR_50HZ] =	{50, 0},
> -	[BMP580_ODR_45HZ] =	{45, 0},
> -	[BMP580_ODR_40HZ] =	{40, 0},
> -	[BMP580_ODR_35HZ] =	{35, 0},
> -	[BMP580_ODR_30HZ] =	{30, 0},
> -	[BMP580_ODR_25HZ] =	{25, 0},
> -	[BMP580_ODR_20HZ] =	{20, 0},
> -	[BMP580_ODR_15HZ] =	{15, 0},
> -	[BMP580_ODR_10HZ] =	{10, 0},
> -	[BMP580_ODR_5HZ] =	{5, 0},
> -	[BMP580_ODR_4HZ] =	{4, 0},
> -	[BMP580_ODR_3HZ] =	{3, 0},
> -	[BMP580_ODR_2HZ] =	{2, 0},
> -	[BMP580_ODR_1HZ] =	{1, 0},
> -	[BMP580_ODR_0_5HZ] =	{0, 500000},
> -	[BMP580_ODR_0_25HZ] =	{0, 250000},
> -	[BMP580_ODR_0_125HZ] =	{0, 125000},
> +	/* BMP580_ODR_FORCED is a driver feature, not a register setting */
> +	[BMP580_ODR_FORCED] =	{   0,      0 },
> +	[BMP580_ODR_240HZ] =	{ 240,	    0 },
> +	[BMP580_ODR_218HZ] =	{ 218,	    0 },
> +	[BMP580_ODR_199HZ] =	{ 199,	    0 },
> +	[BMP580_ODR_179HZ] =	{ 179,	    0 },
> +	[BMP580_ODR_160HZ] =	{ 160,	    0 },
> +	[BMP580_ODR_149HZ] =	{ 149,	    0 },
> +	[BMP580_ODR_140HZ] =	{ 140,	    0 },
> +	[BMP580_ODR_129HZ] =	{ 129,	    0 },
> +	[BMP580_ODR_120HZ] =	{ 120,	    0 },
> +	[BMP580_ODR_110HZ] =	{ 110,	    0 },
> +	[BMP580_ODR_100HZ] =	{ 100,	    0 },
> +	[BMP580_ODR_89HZ] =	{  89,	    0 },
> +	[BMP580_ODR_80HZ] =	{  80,	    0 },
> +	[BMP580_ODR_70HZ] =	{  70,	    0 },
> +	[BMP580_ODR_60HZ] =	{  60,	    0 },
> +	[BMP580_ODR_50HZ] =	{  50,	    0 },
> +	[BMP580_ODR_45HZ] =	{  45,	    0 },
> +	[BMP580_ODR_40HZ] =	{  40,	    0 },
> +	[BMP580_ODR_35HZ] =	{  35,	    0 },
> +	[BMP580_ODR_30HZ] =	{  30,	    0 },
> +	[BMP580_ODR_25HZ] =	{  25,	    0 },
> +	[BMP580_ODR_20HZ] =	{  20,	    0 },
> +	[BMP580_ODR_15HZ] =	{  15,	    0 },
> +	[BMP580_ODR_10HZ] =	{  10,	    0 },
> +	[BMP580_ODR_5HZ] =	{   5,	    0 },
> +	[BMP580_ODR_4HZ] =	{   4,	    0 },
> +	[BMP580_ODR_3HZ] =	{   3,	    0 },
> +	[BMP580_ODR_2HZ] =	{   2,	    0 },
> +	[BMP580_ODR_1HZ] =	{   1,	    0 },
> +	[BMP580_ODR_0_5HZ] =	{   0, 500000 },
> +	[BMP580_ODR_0_25HZ] =	{   0, 250000 },
> +	[BMP580_ODR_0_125HZ] =	{   0, 125000 },
>  };
>  

> @@ -2707,7 +2821,7 @@ static const int bmp580_temp_coeffs[] = { 125, 13 };
>  static const int bmp580_press_coeffs[] = { 1, 64000};
>  
>  const struct bmp280_chip_info bmp580_chip_info = {
> -	.id_reg = BMP580_REG_CHIP_ID,
> +	.id_reg = BMP580_REG_ID,

As below. Unrelated change. Separate patch with clear reasoning for why.

>  	.chip_id = bmp580_chip_ids,
>  	.num_chip_id = ARRAY_SIZE(bmp580_chip_ids),
>  	.regmap_config = &bmp580_regmap_config,
> @@ -3367,10 +3481,13 @@ static int bmp280_runtime_suspend(struct device *dev)
>  {
>  	struct iio_dev *indio_dev = dev_get_drvdata(dev);
>  	struct bmp280_data *data = iio_priv(indio_dev);
> -
> -	data->chip_info->set_mode(data, BMP280_SLEEP);
> +	int ret;
>  
>  	fsleep(data->start_up_time_us);

Add a comment on why we need a sleep before setting the mode.
It's unusual to need resume to sleep before doing anything at all.


> +	ret = data->chip_info->set_mode(data, data->sampling_freq ? BMP280_NORMAL : BMP280_SLEEP);
> +	if (ret)
> +		return ret;
> +
>  	return regulator_bulk_disable(BMP280_NUM_SUPPLIES, data->supplies);
>  }
>  
> diff --git a/drivers/iio/pressure/bmp280.h b/drivers/iio/pressure/bmp280.h
> index df90ed720bc6..8e05cdf869e7 100644
> --- a/drivers/iio/pressure/bmp280.h
> +++ b/drivers/iio/pressure/bmp280.h
> @@ -13,7 +13,7 @@
>  #define BMP580_REG_OSR_CONFIG		0x36
>  #define BMP580_REG_IF_CONFIG		0x13
>  #define BMP580_REG_REV_ID		0x02
> -#define BMP580_REG_CHIP_ID		0x01
> +#define BMP580_REG_ID			0x01

That looks like an unrelated change.

  reply	other threads:[~2025-10-04 15:32 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-09-28 17:26 [RFC PATCH v3 0/9] Fixes and enhancements for the bmp280 driver Achim Gratz
2025-09-28 17:26 ` [RFC PATCH v3 1/9] iio: pressure: bmp280: correct meas_time_us calculation Achim Gratz
2025-10-04 15:21   ` Jonathan Cameron
2025-09-28 17:26 ` [RFC PATCH v3 1/1] iio: pressure: bmp280: test longer autosuspend (WIP) Achim Gratz
2025-09-28 19:10   ` ASSI
2025-09-28 17:26 ` [RFC PATCH v3 2/9] iio: pressure: bmp280: implement adaptive wait for BMx280 devices Achim Gratz
2025-09-28 17:26 ` [RFC PATCH v3 3/9] iio: pressure: bmp280: implement adaptive wait for BMP380 devices Achim Gratz
2025-09-28 17:26 ` [RFC PATCH v3 4/9] iio: pressure: bmp280: rename wait_conv() to conv(), factor out measurement time calculation Achim Gratz
2025-09-28 17:26 ` [RFC PATCH v3 5/9] iio: pressure: bmp280: remove code duplication Achim Gratz
2025-10-04 15:12   ` Jonathan Cameron
2025-09-28 17:26 ` [RFC PATCH v3 6/9] iio: pressure: bmp280: enable filter settings for BMx280 Achim Gratz
2025-10-04 15:21   ` Jonathan Cameron
2025-09-28 17:26 ` [RFC PATCH v3 7/9] iio: pressure: bmp280: implement sampling_frequency " Achim Gratz
2025-10-04 15:32   ` Jonathan Cameron [this message]
2025-09-28 17:26 ` [RFC PATCH v3 8/9] iio: pressure: bmp280: implement sampling_frequency calculation " Achim Gratz
2025-10-04 15:37   ` Jonathan Cameron
2025-09-28 17:26 ` [RFC PATCH v3 9/9] iio: pressure: bmp280: test longer autosuspend (WIP) Achim Gratz
2025-10-04 15:07 ` [RFC PATCH v3 0/9] Fixes and enhancements for the bmp280 driver Jonathan Cameron
2025-10-04 16:59   ` ASSI

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=20251004163252.5ec4e594@jic23-huawei \
    --to=jic23@kernel.org \
    --cc=Achim.Gratz@Stromeko.DE \
    --cc=andy@kernel.org \
    --cc=dlechner@baylibre.com \
    --cc=linux-iio@vger.kernel.org \
    --cc=nuno.sa@analog.com \
    /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