diff mbox series

[4/4] iio: pressure: Add triggered buffer support for BMP280 driver

Message ID 20240303165300.468011-5-vassilisamir@gmail.com (mailing list archive)
State Changes Requested
Headers show
Series Series to add triggered buffer support to BMP280 driver | expand

Commit Message

Vasileios Amoiridis March 3, 2024, 4:53 p.m. UTC
Add a buffer struct that will hold the values of the measurements
and will be pushed to userspace. Modify all read_* functions in order
to just read and compensate the data without though converting to the
required IIO measurement units which are used for the oneshot captures.

Signed-off-by: Vasileios Amoiridis <vassilisamir@gmail.com>
---
 drivers/iio/pressure/Kconfig       |   2 +
 drivers/iio/pressure/bmp280-core.c | 155 +++++++++++++++++++++++------
 drivers/iio/pressure/bmp280.h      |   7 ++
 3 files changed, 134 insertions(+), 30 deletions(-)

Comments

Andy Shevchenko March 4, 2024, 11:52 a.m. UTC | #1
On Sun, Mar 03, 2024 at 05:53:00PM +0100, Vasileios Amoiridis wrote:
> Add a buffer struct that will hold the values of the measurements
> and will be pushed to userspace. Modify all read_* functions in order
> to just read and compensate the data without though converting to the
> required IIO measurement units which are used for the oneshot captures.

> +#include <linux/iio/buffer.h>
>  #include <linux/iio/iio.h>
>  #include <linux/iio/sysfs.h>
> +#include <linux/iio/trigger.h>
> +#include <linux/iio/trigger_consumer.h>
> +#include <linux/iio/triggered_buffer.h>

Yes, taking into account the comment against patch 1, this will become the part
of iio/* group.

...

> +	/* val might be NULL if we're called by the buffer handler */
> +	if (val) {
> +		*val = comp_press;
> +		/* Compensated pressure is in cPa (centipascals) */
> +		*val2 = 100000;

Here and everywhere else where it makes sense

		*val2 = CENTI * 1000; // (What is 1000 here?)

from units.h?

> +		return IIO_VAL_FRACTIONAL;
> +	}

...

> +	struct {
> +		s32 temperature;
> +		u32 pressure;
> +		u32 humidity;

> +		s64 timestamp;

Shouldn't this be aligned properly?

> +	} iio_buffer;
Vasileios Amoiridis March 4, 2024, 7:08 p.m. UTC | #2
On Mon, Mar 04, 2024 at 01:52:05PM +0200, Andy Shevchenko wrote:
> On Sun, Mar 03, 2024 at 05:53:00PM +0100, Vasileios Amoiridis wrote:
> > Add a buffer struct that will hold the values of the measurements
> > and will be pushed to userspace. Modify all read_* functions in order
> > to just read and compensate the data without though converting to the
> > required IIO measurement units which are used for the oneshot captures.
> 
> > +#include <linux/iio/buffer.h>
> >  #include <linux/iio/iio.h>
> >  #include <linux/iio/sysfs.h>
> > +#include <linux/iio/trigger.h>
> > +#include <linux/iio/trigger_consumer.h>
> > +#include <linux/iio/triggered_buffer.h>
> 
> Yes, taking into account the comment against patch 1, this will become the part
> of iio/* group.
> 
> ...
> 
> > +	/* val might be NULL if we're called by the buffer handler */
> > +	if (val) {
> > +		*val = comp_press;
> > +		/* Compensated pressure is in cPa (centipascals) */
> > +		*val2 = 100000;
> 
> Here and everywhere else where it makes sense
> 
> 		*val2 = CENTI * 1000; // (What is 1000 here?)
> 
> from units.h?
> 

I didn't change these values, the addition here is that I put them under an
if statement that checks if we were called by the buffer handler or by the
oneshot capture read_raw function. The point is that every sensor provides
values that need different scaling in order to have the IIO standard
measurement units. In the above code I guess since 1kPa=100000cPa that's
why *val2=100000.

The *val and *val2 values could be moved to the read_raw function as it will
already happen for the IIO_CHAN_INFO_SCALE values from chip_info arrays as
you proposed in Patch No.2. This would require though that all the functions
like this one you commented would need to change. Is that something that you
think as better?

> > +		return IIO_VAL_FRACTIONAL;
> > +	}
> 
> ...
> 
> > +	struct {
> > +		s32 temperature;
> > +		u32 pressure;
> > +		u32 humidity;
> 
> > +		s64 timestamp;
> 
> Shouldn't this be aligned properly?
> 

I saw that in some drivers it was added and in some it was not. What is the
difference of aligning just the timestamp of the kernel?
> > +	} iio_buffer;
> 
> -- 
> With Best Regards,
> Andy Shevchenko
> 
>
Andy Shevchenko March 4, 2024, 7:18 p.m. UTC | #3
On Mon, Mar 04, 2024 at 08:08:38PM +0100, Vasileios Amoiridis wrote:
> On Mon, Mar 04, 2024 at 01:52:05PM +0200, Andy Shevchenko wrote:
> > On Sun, Mar 03, 2024 at 05:53:00PM +0100, Vasileios Amoiridis wrote:

...

> > > +	struct {
> > > +		s32 temperature;
> > > +		u32 pressure;
> > > +		u32 humidity;
> > 
> > > +		s64 timestamp;
> > 
> > Shouldn't this be aligned properly?
> 
> I saw that in some drivers it was added and in some it was not. What is the
> difference of aligning just the timestamp of the kernel?

You can count yourself. With provided structure as above there is a high
probability of misaligned timeout field. The latter has to be aligned on
8 bytes.

> > > +	} iio_buffer;
Vasileios Amoiridis March 4, 2024, 8:05 p.m. UTC | #4
On Mon, Mar 04, 2024 at 09:18:27PM +0200, Andy Shevchenko wrote:
> On Mon, Mar 04, 2024 at 08:08:38PM +0100, Vasileios Amoiridis wrote:
> > On Mon, Mar 04, 2024 at 01:52:05PM +0200, Andy Shevchenko wrote:
> > > On Sun, Mar 03, 2024 at 05:53:00PM +0100, Vasileios Amoiridis wrote:
> 
> ...
> 
> > > > +	struct {
> > > > +		s32 temperature;
> > > > +		u32 pressure;
> > > > +		u32 humidity;
> > > 
> > > > +		s64 timestamp;
> > > 
> > > Shouldn't this be aligned properly?
> > 
> > I saw that in some drivers it was added and in some it was not. What is the
> > difference of aligning just the timestamp of the kernel?
> 
> You can count yourself. With provided structure as above there is a high
> probability of misaligned timeout field. The latter has to be aligned on
> 8 bytes.
> 

I was unaware, but now I am not. Thank you very much for the feedback.
> > > > +	} iio_buffer;
> 
> -- 
> With Best Regards,
> Andy Shevchenko
> 
>
Jonathan Cameron March 9, 2024, 6:19 p.m. UTC | #5
On Mon, 4 Mar 2024 21:05:47 +0100
Vasileios Amoiridis <vassilisamir@gmail.com> wrote:

> On Mon, Mar 04, 2024 at 09:18:27PM +0200, Andy Shevchenko wrote:
> > On Mon, Mar 04, 2024 at 08:08:38PM +0100, Vasileios Amoiridis wrote:  
> > > On Mon, Mar 04, 2024 at 01:52:05PM +0200, Andy Shevchenko wrote:  
> > > > On Sun, Mar 03, 2024 at 05:53:00PM +0100, Vasileios Amoiridis wrote:  
> > 
> > ...
> >   
> > > > > +	struct {
> > > > > +		s32 temperature;
> > > > > +		u32 pressure;
> > > > > +		u32 humidity;  
> > > >   
> > > > > +		s64 timestamp;  
> > > > 
> > > > Shouldn't this be aligned properly?  
> > > 
> > > I saw that in some drivers it was added and in some it was not. What is the
> > > difference of aligning just the timestamp of the kernel?  
> > 
> > You can count yourself. With provided structure as above there is a high
> > probability of misaligned timeout field. The latter has to be aligned on
> > 8 bytes.
> >   
> 
> I was unaware, but now I am not. Thank you very much for the feedback.

Fun bit of C is that you aren't actually aligning just the timestamp.
A C structure is aligned to the alignment of the maximum element within it.
So by specifying that timestamp is aligned to 8 bytes, you also force the
alignment of the whole structure to 8 bytes.

When you see the outer buffer aligned as well (typically the potentially larger
__aligned (IIO_DMA_MINALIGN)) that's for a different reason.  Used on a trailing
element of a structure via iio_priv() that ensures there is nothing else in the
cacheline (maximum one in the system) on systems where this matters due to non
coherent DMA.  Still need the __aligned(8) on the timestamp though as otherwise
the internal padding may be wrong (like here).

On some architectures small buffers are always bounced - if that were true on
all of them we could get rid of the complexity of IIO_DMA_MINALIGN.

Alignment is so much fun - particularly with x86_32 which does 8 byte values aligned
to 4 bytes. We had a massive set of patches fixing subtle issues around that a
few years ago.

Jonathan

  
> > > > > +	} iio_buffer;  
> > 
> > -- 
> > With Best Regards,
> > Andy Shevchenko
> > 
> >
Jonathan Cameron March 9, 2024, 6:32 p.m. UTC | #6
On Sun,  3 Mar 2024 17:53:00 +0100
Vasileios Amoiridis <vassilisamir@gmail.com> wrote:

> Add a buffer struct that will hold the values of the measurements
> and will be pushed to userspace. Modify all read_* functions in order
> to just read and compensate the data without though converting to the
> required IIO measurement units which are used for the oneshot captures.
> 
> Signed-off-by: Vasileios Amoiridis <vassilisamir@gmail.com>
Hi Vasileios,

This falls into the usual problem hole of drivers that provide
only processed channels.  The assumption is that the data in the buffer
obeys the same description as the sysfs files. So if we only have
processsed assumption is that scale should not be applied (it's rare
enough I suspect our test code doesn't know this subtlety.
We can resolve it as per comment on earlier patch to add _raw as well.

> ---
>  drivers/iio/pressure/Kconfig       |   2 +
>  drivers/iio/pressure/bmp280-core.c | 155 +++++++++++++++++++++++------
>  drivers/iio/pressure/bmp280.h      |   7 ++
>  3 files changed, 134 insertions(+), 30 deletions(-)
> 
> diff --git a/drivers/iio/pressure/Kconfig b/drivers/iio/pressure/Kconfig
> index 79adfd059c3a..5145b94b4679 100644
> --- a/drivers/iio/pressure/Kconfig
> +++ b/drivers/iio/pressure/Kconfig
> @@ -31,6 +31,8 @@ config BMP280
>  	select REGMAP
>  	select BMP280_I2C if (I2C)
>  	select BMP280_SPI if (SPI_MASTER)
> +	select IIO_BUFFER
> +	select IIO_TRIGGERED_BUFFER
>  	help
>  	  Say yes here to build support for Bosch Sensortec BMP180, BMP280, BMP380
>  	  and BMP580 pressure and temperature sensors. Also supports the BME280 with
> diff --git a/drivers/iio/pressure/bmp280-core.c b/drivers/iio/pressure/bmp280-core.c
> index 3bdf6002983f..3b1a159e57ea 100644
> --- a/drivers/iio/pressure/bmp280-core.c
> +++ b/drivers/iio/pressure/bmp280-core.c
> @@ -31,8 +31,12 @@
>  #include <linux/delay.h>
>  #include <linux/device.h>
>  #include <linux/gpio/consumer.h>
> +#include <linux/iio/buffer.h>
>  #include <linux/iio/iio.h>
>  #include <linux/iio/sysfs.h>
> +#include <linux/iio/trigger.h>

This is normally only needed for devices registering a trigger.  This one doesn't.

> +#include <linux/iio/trigger_consumer.h>
> +#include <linux/iio/triggered_buffer.h>
>  #include <linux/interrupt.h>
>  #include <linux/irq.h> /* For irq_get_irq_data() */
>  #include <linux/module.h>

>  
> @@ -2133,10 +2179,16 @@ static int bmp180_read_press(struct bmp280_data *data,
>  
>  	comp_press = bmp180_compensate_press(data, adc_press);
>  
> -	*val = comp_press;
> -	*val2 = 1000;
> +	/* val might be NULL if we're called by the buffer handler */
> +	if (val) {
> +		*val = comp_press;
> +		*val2 = 1000;
> +		return IIO_VAL_FRACTIONAL;
> +	}
> +
> +	data->iio_buffer.pressure = comp_press;

Putting the filling of the internal cache in here makes this hard to read.
I think I'd prefer seeing the code shared by the sysfs and this path
factored out to a separate function then a simple
bmp180_read_press_raw() as an additional callback so we can see this value
being set at the caller.

>  
> -	return IIO_VAL_FRACTIONAL;
> +	return 0;
>  }
>  
>  static int bmp180_chip_config(struct bmp280_data *data)
> @@ -2217,6 +2269,43 @@ static int bmp085_fetch_eoc_irq(struct device *dev,
>  	return 0;
>  }
>  
> +static irqreturn_t bmp280_buffer_handler(int irq, void *p)
> +{
> +	struct iio_poll_func *pf = p;
> +	struct iio_dev *indio_dev = pf->indio_dev;
> +	struct bmp280_data *data = iio_priv(indio_dev);
> +	int ret;
> +
> +	mutex_lock(&data->lock);
> +
> +	if (test_bit(BMP280_TEMP, indio_dev->active_scan_mask)) {
> +		ret = data->chip_info->read_temp(data, NULL, NULL);
> +		if (ret < 0)
> +			goto done;
> +	}
> +
> +	if (test_bit(BMP280_PRESS, indio_dev->active_scan_mask)) {
> +		ret = data->chip_info->read_press(data, NULL, NULL);
> +		if (ret < 0)
> +			goto done;
> +	}
> +
> +	if (test_bit(BME280_HUMID, indio_dev->active_scan_mask)) {
> +		ret = data->chip_info->read_humid(data, NULL, NULL);
> +		if (ret < 0)
> +			goto done;
> +	}
> +
> +	iio_push_to_buffers_with_timestamp(indio_dev, &data->iio_buffer,
> +					   pf->timestamp);
> +
> +done:
> +	mutex_unlock(&data->lock);
> +	iio_trigger_notify_done(indio_dev->trig);
> +
> +	return IRQ_HANDLED;
> +
> +}

blank line here.

>  static void bmp280_pm_disable(void *data)
>  {
>  	struct device *dev = data;
> @@ -2358,6 +2447,12 @@ int bmp280_common_probe(struct device *dev,
>  			return ret;
>  	}
>  
> +	ret = devm_iio_triggered_buffer_setup(dev, indio_dev,
> +					      iio_pollfunc_store_time,
> +					      &bmp280_buffer_handler, NULL);
> +	if (ret)
> +		return dev_err_probe(data->dev, ret,
> +				     "iio triggered buffer setup failed\n");
>  	/* Enable runtime PM */
>  	pm_runtime_get_noresume(dev);
>  	pm_runtime_set_active(dev);
> diff --git a/drivers/iio/pressure/bmp280.h b/drivers/iio/pressure/bmp280.h
> index d77402cb3121..d5c0451ebf68 100644
> --- a/drivers/iio/pressure/bmp280.h
> +++ b/drivers/iio/pressure/bmp280.h
> @@ -400,6 +400,13 @@ struct bmp280_data {
>  	 */
>  	s32 t_fine;
>  
> +	/* IIO sysfs buffer */

Sysfs is very much one thing it isn't if you have a timestamp. This is for
the chardev flow. So drop the missleading comment.

> +	struct {
> +		s32 temperature;
> +		u32 pressure;
> +		u32 humidity;
> +		s64 timestamp;
> +	} iio_buffer;
>  	/*
>  	 * DMA (thus cache coherency maintenance) may require the
>  	 * transfer buffers to live in their own cache lines.
diff mbox series

Patch

diff --git a/drivers/iio/pressure/Kconfig b/drivers/iio/pressure/Kconfig
index 79adfd059c3a..5145b94b4679 100644
--- a/drivers/iio/pressure/Kconfig
+++ b/drivers/iio/pressure/Kconfig
@@ -31,6 +31,8 @@  config BMP280
 	select REGMAP
 	select BMP280_I2C if (I2C)
 	select BMP280_SPI if (SPI_MASTER)
+	select IIO_BUFFER
+	select IIO_TRIGGERED_BUFFER
 	help
 	  Say yes here to build support for Bosch Sensortec BMP180, BMP280, BMP380
 	  and BMP580 pressure and temperature sensors. Also supports the BME280 with
diff --git a/drivers/iio/pressure/bmp280-core.c b/drivers/iio/pressure/bmp280-core.c
index 3bdf6002983f..3b1a159e57ea 100644
--- a/drivers/iio/pressure/bmp280-core.c
+++ b/drivers/iio/pressure/bmp280-core.c
@@ -31,8 +31,12 @@ 
 #include <linux/delay.h>
 #include <linux/device.h>
 #include <linux/gpio/consumer.h>
+#include <linux/iio/buffer.h>
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h> /* For irq_get_irq_data() */
 #include <linux/module.h>
@@ -457,13 +461,16 @@  static int bmp280_read_temp(struct bmp280_data *data,
 
 	/*
 	 * val might be NULL if we're called by the read_press routine,
-	 * who only cares about the carry over t_fine value.
+	 * who only cares about the carry over t_fine value or if we're called
+	 * by the buffer handler function.
 	 */
 	if (val) {
 		*val = comp_temp * 10;
 		return IIO_VAL_INT;
 	}
 
+	data->iio_buffer.temperature = comp_temp;
+
 	return 0;
 }
 
@@ -494,10 +501,16 @@  static int bmp280_read_press(struct bmp280_data *data,
 	}
 	comp_press = bmp280_compensate_press(data, adc_press);
 
-	*val = comp_press;
-	*val2 = 256000;
+	/* val might be NULL if we're called by the buffer handler */
+	if (val) {
+		*val = comp_press;
+		*val2 = 256000;
+		return IIO_VAL_FRACTIONAL;
+	}
+
+	data->iio_buffer.pressure = comp_press;
 
-	return IIO_VAL_FRACTIONAL;
+	return 0;
 }
 
 static int bmp280_read_humid(struct bmp280_data *data, int *val, int *val2)
@@ -526,9 +539,15 @@  static int bmp280_read_humid(struct bmp280_data *data, int *val, int *val2)
 	}
 	comp_humidity = bmp280_compensate_humidity(data, adc_humidity);
 
-	*val = comp_humidity * 1000 / 1024;
+	/* val might be NULL if we're called by the buffer handler */
+	if (val) {
+		*val = comp_humidity * 1000 / 1024;
+		return IIO_VAL_INT;
+	}
 
-	return IIO_VAL_INT;
+	data->iio_buffer.humidity = comp_humidity;
+
+	return 0;
 }
 
 static int bmp280_read_raw(struct iio_dev *indio_dev,
@@ -1170,7 +1189,8 @@  static int bmp380_read_temp(struct bmp280_data *data, int *val, int *val2)
 
 	/*
 	 * Val might be NULL if we're called by the read_press routine,
-	 * who only cares about the carry over t_fine value.
+	 * who only cares about the carry over t_fine value or if we're called
+	 * by the buffer handler.
 	 */
 	if (val) {
 		/* IIO reports temperatures in milli Celsius */
@@ -1178,6 +1198,8 @@  static int bmp380_read_temp(struct bmp280_data *data, int *val, int *val2)
 		return IIO_VAL_INT;
 	}
 
+	data->iio_buffer.temperature = comp_temp;
+
 	return 0;
 }
 
@@ -1206,11 +1228,17 @@  static int bmp380_read_press(struct bmp280_data *data, int *val, int *val2)
 	}
 	comp_press = bmp380_compensate_press(data, adc_press);
 
-	*val = comp_press;
-	/* Compensated pressure is in cPa (centipascals) */
-	*val2 = 100000;
+	/* val might be NULL if we're called by the buffer handler */
+	if (val) {
+		*val = comp_press;
+		/* Compensated pressure is in cPa (centipascals) */
+		*val2 = 100000;
+		return IIO_VAL_FRACTIONAL;
+	}
+
+	data->iio_buffer.pressure = comp_press;
 
-	return IIO_VAL_FRACTIONAL;
+	return 0;
 }
 
 static int bmp380_read_calib(struct bmp280_data *data)
@@ -1543,14 +1571,21 @@  static int bmp580_read_temp(struct bmp280_data *data, int *val, int *val2)
 		return -EIO;
 	}
 
-	/*
-	 * Temperature is returned in Celsius degrees in fractional
-	 * form down 2^16. We rescale by x1000 to return milli Celsius
-	 * to respect IIO ABI.
-	 */
-	*val = raw_temp * 1000;
-	*val2 = 16;
-	return IIO_VAL_FRACTIONAL_LOG2;
+	/* val might be NULL if we're called by the buffer handler */
+	if (val) {
+		/*
+		* Temperature is returned in Celsius degrees in fractional
+		* form down 2^16. We rescale by x1000 to return milli Celsius
+		* to respect IIO ABI.
+		*/
+		*val = raw_temp * 1000;
+		*val2 = 16;
+		return IIO_VAL_FRACTIONAL_LOG2;
+	}
+
+	data->iio_buffer.temperature = raw_temp;
+
+	return 0;
 }
 
 static int bmp580_read_press(struct bmp280_data *data, int *val, int *val2)
@@ -1570,13 +1605,21 @@  static int bmp580_read_press(struct bmp280_data *data, int *val, int *val2)
 		dev_err(data->dev, "reading pressure skipped\n");
 		return -EIO;
 	}
-	/*
-	 * Pressure is returned in Pascals in fractional form down 2^16.
-	 * We rescale /1000 to convert to kilopascal to respect IIO ABI.
-	 */
-	*val = raw_press;
-	*val2 = 64000; /* 2^6 * 1000 */
-	return IIO_VAL_FRACTIONAL;
+
+	/* val might be NULL if we're called by the buffer handler */
+	if (val) {
+		/*
+		 * Pressure is returned in Pascals in fractional form down 2^16.
+		 * We rescale /1000 to convert to kilopascal to respect IIO ABI.
+		*/
+		*val = raw_press;
+		*val2 = 64000; /* 2^6 * 1000 */
+		return IIO_VAL_FRACTIONAL;
+	}
+
+	data->iio_buffer.pressure = raw_press;
+
+	return 0;
 }
 
 static const int bmp580_odr_table[][2] = {
@@ -2048,13 +2091,16 @@  static int bmp180_read_temp(struct bmp280_data *data, int *val, int *val2)
 
 	/*
 	 * val might be NULL if we're called by the read_press routine,
-	 * who only cares about the carry over t_fine value.
+	 * who only cares about the carry over t_fine value or if we're called
+	 * by the buffer handler.
 	 */
 	if (val) {
 		*val = comp_temp * 100;
 		return IIO_VAL_INT;
 	}
 
+	data->iio_buffer.temperature = comp_temp;
+
 	return 0;
 }
 
@@ -2133,10 +2179,16 @@  static int bmp180_read_press(struct bmp280_data *data,
 
 	comp_press = bmp180_compensate_press(data, adc_press);
 
-	*val = comp_press;
-	*val2 = 1000;
+	/* val might be NULL if we're called by the buffer handler */
+	if (val) {
+		*val = comp_press;
+		*val2 = 1000;
+		return IIO_VAL_FRACTIONAL;
+	}
+
+	data->iio_buffer.pressure = comp_press;
 
-	return IIO_VAL_FRACTIONAL;
+	return 0;
 }
 
 static int bmp180_chip_config(struct bmp280_data *data)
@@ -2217,6 +2269,43 @@  static int bmp085_fetch_eoc_irq(struct device *dev,
 	return 0;
 }
 
+static irqreturn_t bmp280_buffer_handler(int irq, void *p)
+{
+	struct iio_poll_func *pf = p;
+	struct iio_dev *indio_dev = pf->indio_dev;
+	struct bmp280_data *data = iio_priv(indio_dev);
+	int ret;
+
+	mutex_lock(&data->lock);
+
+	if (test_bit(BMP280_TEMP, indio_dev->active_scan_mask)) {
+		ret = data->chip_info->read_temp(data, NULL, NULL);
+		if (ret < 0)
+			goto done;
+	}
+
+	if (test_bit(BMP280_PRESS, indio_dev->active_scan_mask)) {
+		ret = data->chip_info->read_press(data, NULL, NULL);
+		if (ret < 0)
+			goto done;
+	}
+
+	if (test_bit(BME280_HUMID, indio_dev->active_scan_mask)) {
+		ret = data->chip_info->read_humid(data, NULL, NULL);
+		if (ret < 0)
+			goto done;
+	}
+
+	iio_push_to_buffers_with_timestamp(indio_dev, &data->iio_buffer,
+					   pf->timestamp);
+
+done:
+	mutex_unlock(&data->lock);
+	iio_trigger_notify_done(indio_dev->trig);
+
+	return IRQ_HANDLED;
+
+}
 static void bmp280_pm_disable(void *data)
 {
 	struct device *dev = data;
@@ -2358,6 +2447,12 @@  int bmp280_common_probe(struct device *dev,
 			return ret;
 	}
 
+	ret = devm_iio_triggered_buffer_setup(dev, indio_dev,
+					      iio_pollfunc_store_time,
+					      &bmp280_buffer_handler, NULL);
+	if (ret)
+		return dev_err_probe(data->dev, ret,
+				     "iio triggered buffer setup failed\n");
 	/* Enable runtime PM */
 	pm_runtime_get_noresume(dev);
 	pm_runtime_set_active(dev);
diff --git a/drivers/iio/pressure/bmp280.h b/drivers/iio/pressure/bmp280.h
index d77402cb3121..d5c0451ebf68 100644
--- a/drivers/iio/pressure/bmp280.h
+++ b/drivers/iio/pressure/bmp280.h
@@ -400,6 +400,13 @@  struct bmp280_data {
 	 */
 	s32 t_fine;
 
+	/* IIO sysfs buffer */
+	struct {
+		s32 temperature;
+		u32 pressure;
+		u32 humidity;
+		s64 timestamp;
+	} iio_buffer;
 	/*
 	 * DMA (thus cache coherency maintenance) may require the
 	 * transfer buffers to live in their own cache lines.