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