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

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxx>
---
 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>
+#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.
-- 
2.25.1





[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Input]     [Linux Kernel]     [Linux SCSI]     [X.org]

  Powered by Linux