iio: pressure: bmp280: Add triggered buffer support
authorVasileios Amoiridis <vassilisamir@gmail.com>
Fri, 28 Jun 2024 17:17:26 +0000 (19:17 +0200)
committerJonathan Cameron <Jonathan.Cameron@huawei.com>
Sat, 3 Aug 2024 09:13:36 +0000 (10:13 +0100)
BMP2xx, BME280, BMP3xx, and BMP5xx use continuous buffers for their
temperature, pressure and humidity readings. This facilitates the
use of burst/bulk reads in order to acquire data faster. The
approach is different from the one used in oneshot captures.

BMP085 & BMP1xx devices use a completely different measurement
process that is well defined and is used in their buffer_handler().

Suggested-by: Angel Iglesias <ang.iglesiasg@gmail.com>
Signed-off-by: Vasileios Amoiridis <vassilisamir@gmail.com>
Link: https://lore.kernel.org/r/20240512230524.53990-6-vassilisamir@gmail.com
Link: https://patch.msgid.link/20240628171726.124852-4-vassilisamir@gmail.com
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
drivers/iio/pressure/Kconfig
drivers/iio/pressure/bmp280-core.c
drivers/iio/pressure/bmp280-spi.c
drivers/iio/pressure/bmp280.h

index 3ad3850..0b5406a 100644 (file)
@@ -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
index f709ad8..2fc5724 100644 (file)
 #include <linux/regmap.h>
 #include <linux/regulator/consumer.h>
 
+#include <linux/iio/buffer.h>
 #include <linux/iio/iio.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
 
 #include <asm/unaligned.h>
 
@@ -134,6 +137,12 @@ enum {
        BMP380_P11 = 20,
 };
 
+enum bmp280_scan {
+       BMP280_PRESS,
+       BMP280_TEMP,
+       BME280_HUMID,
+};
+
 static const struct iio_chan_spec bmp280_channels[] = {
        {
                .type = IIO_PRESSURE,
@@ -142,6 +151,13 @@ static const struct iio_chan_spec bmp280_channels[] = {
                                      BIT(IIO_CHAN_INFO_RAW) |
                                      BIT(IIO_CHAN_INFO_SCALE) |
                                      BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
+               .scan_index = 0,
+               .scan_type = {
+                       .sign = 'u',
+                       .realbits = 32,
+                       .storagebits = 32,
+                       .endianness = IIO_CPU,
+               },
        },
        {
                .type = IIO_TEMP,
@@ -150,7 +166,15 @@ static const struct iio_chan_spec bmp280_channels[] = {
                                      BIT(IIO_CHAN_INFO_RAW) |
                                      BIT(IIO_CHAN_INFO_SCALE) |
                                      BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
+               .scan_index = 1,
+               .scan_type = {
+                       .sign = 's',
+                       .realbits = 32,
+                       .storagebits = 32,
+                       .endianness = IIO_CPU,
+               },
        },
+       IIO_CHAN_SOFT_TIMESTAMP(2),
 };
 
 static const struct iio_chan_spec bme280_channels[] = {
@@ -161,6 +185,13 @@ static const struct iio_chan_spec bme280_channels[] = {
                                      BIT(IIO_CHAN_INFO_RAW) |
                                      BIT(IIO_CHAN_INFO_SCALE) |
                                      BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
+               .scan_index = 0,
+               .scan_type = {
+                       .sign = 'u',
+                       .realbits = 32,
+                       .storagebits = 32,
+                       .endianness = IIO_CPU,
+               },
        },
        {
                .type = IIO_TEMP,
@@ -169,6 +200,13 @@ static const struct iio_chan_spec bme280_channels[] = {
                                      BIT(IIO_CHAN_INFO_RAW) |
                                      BIT(IIO_CHAN_INFO_SCALE) |
                                      BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
+               .scan_index = 1,
+               .scan_type = {
+                       .sign = 's',
+                       .realbits = 32,
+                       .storagebits = 32,
+                       .endianness = IIO_CPU,
+               },
        },
        {
                .type = IIO_HUMIDITYRELATIVE,
@@ -177,7 +215,15 @@ static const struct iio_chan_spec bme280_channels[] = {
                                      BIT(IIO_CHAN_INFO_RAW) |
                                      BIT(IIO_CHAN_INFO_SCALE) |
                                      BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
+               .scan_index = 2,
+               .scan_type = {
+                       .sign = 'u',
+                       .realbits = 32,
+                       .storagebits = 32,
+                       .endianness = IIO_CPU,
+               },
        },
+       IIO_CHAN_SOFT_TIMESTAMP(3),
 };
 
 static const struct iio_chan_spec bmp380_channels[] = {
@@ -190,6 +236,51 @@ static const struct iio_chan_spec bmp380_channels[] = {
                                      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',
+                       .realbits = 32,
+                       .storagebits = 32,
+                       .endianness = IIO_CPU,
+               },
+       },
+       {
+               .type = IIO_TEMP,
+               /* PROCESSED maintained for ABI backwards compatibility */
+               .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
+                                     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',
+                       .realbits = 32,
+                       .storagebits = 32,
+                       .endianness = IIO_CPU,
+               },
+       },
+       IIO_CHAN_SOFT_TIMESTAMP(2),
+};
+
+static const struct iio_chan_spec bmp580_channels[] = {
+       {
+               .type = IIO_PRESSURE,
+               /* PROCESSED maintained for ABI backwards compatibility */
+               .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
+                                     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',
+                       .realbits = 24,
+                       .storagebits = 32,
+                       .endianness = IIO_LE,
+               },
        },
        {
                .type = IIO_TEMP,
@@ -200,7 +291,15 @@ static const struct iio_chan_spec bmp380_channels[] = {
                                      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',
+                       .realbits = 24,
+                       .storagebits = 32,
+                       .endianness = IIO_LE,
+               },
        },
+       IIO_CHAN_SOFT_TIMESTAMP(2),
 };
 
 static int bmp280_read_calib(struct bmp280_data *data)
@@ -316,7 +415,7 @@ static int bme280_read_humid_adc(struct bmp280_data *data, u16 *adc_humidity)
        int ret;
 
        ret = regmap_bulk_read(data->regmap, BME280_REG_HUMIDITY_MSB,
-                              &data->be16, sizeof(data->be16));
+                              &data->be16, BME280_NUM_HUMIDITY_BYTES);
        if (ret) {
                dev_err(data->dev, "failed to read humidity\n");
                return ret;
@@ -362,7 +461,7 @@ static int bmp280_read_temp_adc(struct bmp280_data *data, u32 *adc_temp)
        int ret;
 
        ret = regmap_bulk_read(data->regmap, BMP280_REG_TEMP_MSB,
-                              data->buf, sizeof(data->buf));
+                              data->buf, BMP280_NUM_TEMP_BYTES);
        if (ret) {
                dev_err(data->dev, "failed to read temperature\n");
                return ret;
@@ -423,7 +522,7 @@ static int bmp280_read_press_adc(struct bmp280_data *data, u32 *adc_press)
        int ret;
 
        ret = regmap_bulk_read(data->regmap, BMP280_REG_PRESS_MSB,
-                              data->buf, sizeof(data->buf));
+                              data->buf, BMP280_NUM_PRESS_BYTES);
        if (ret) {
                dev_err(data->dev, "failed to read pressure\n");
                return ret;
@@ -874,6 +973,16 @@ static const struct iio_info bmp280_info = {
        .write_raw = &bmp280_write_raw,
 };
 
+static const unsigned long bmp280_avail_scan_masks[] = {
+       BIT(BMP280_TEMP) | BIT(BMP280_PRESS),
+       0
+};
+
+static const unsigned long bme280_avail_scan_masks[] = {
+       BIT(BME280_HUMID) | BIT(BMP280_TEMP) | BIT(BMP280_PRESS),
+       0
+};
+
 static int bmp280_chip_config(struct bmp280_data *data)
 {
        u8 osrs = FIELD_PREP(BMP280_OSRS_TEMP_MASK, data->oversampling_temp + 1) |
@@ -901,6 +1010,53 @@ static int bmp280_chip_config(struct bmp280_data *data)
        return ret;
 }
 
+static irqreturn_t bmp280_trigger_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);
+       s32 adc_temp, adc_press, t_fine;
+       int ret;
+
+       guard(mutex)(&data->lock);
+
+       /* Burst read data registers */
+       ret = regmap_bulk_read(data->regmap, BMP280_REG_PRESS_MSB,
+                              data->buf, BMP280_BURST_READ_BYTES);
+       if (ret) {
+               dev_err(data->dev, "failed to burst read sensor data\n");
+               goto out;
+       }
+
+       /* Temperature calculations */
+       adc_temp = FIELD_GET(BMP280_MEAS_TRIM_MASK, get_unaligned_be24(&data->buf[3]));
+       if (adc_temp == BMP280_TEMP_SKIPPED) {
+               dev_err(data->dev, "reading temperature skipped\n");
+               goto out;
+       }
+
+       data->sensor_data[1] = bmp280_compensate_temp(data, adc_temp);
+
+       /* Pressure calculations */
+       adc_press = FIELD_GET(BMP280_MEAS_TRIM_MASK, get_unaligned_be24(&data->buf[0]));
+       if (adc_press == BMP280_PRESS_SKIPPED) {
+               dev_err(data->dev, "reading pressure skipped\n");
+               goto out;
+       }
+
+       t_fine = bmp280_calc_t_fine(data, adc_temp);
+
+       data->sensor_data[0] = bmp280_compensate_press(data, adc_press, t_fine);
+
+       iio_push_to_buffers_with_timestamp(indio_dev, &data->sensor_data,
+                                          iio_get_time_ns(indio_dev));
+
+out:
+       iio_trigger_notify_done(indio_dev->trig);
+
+       return IRQ_HANDLED;
+}
+
 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 };
@@ -914,6 +1070,7 @@ const struct bmp280_chip_info bmp280_chip_info = {
        .start_up_time = 2000,
        .channels = bmp280_channels,
        .num_channels = ARRAY_SIZE(bmp280_channels),
+       .avail_scan_masks = bmp280_avail_scan_masks,
 
        .oversampling_temp_avail = bmp280_oversampling_avail,
        .num_oversampling_temp_avail = ARRAY_SIZE(bmp280_oversampling_avail),
@@ -942,6 +1099,8 @@ const struct bmp280_chip_info bmp280_chip_info = {
        .read_temp = bmp280_read_temp,
        .read_press = bmp280_read_press,
        .read_calib = bmp280_read_calib,
+
+       .trigger_handler = bmp280_trigger_handler,
 };
 EXPORT_SYMBOL_NS(bmp280_chip_info, IIO_BMP280);
 
@@ -964,6 +1123,62 @@ static int bme280_chip_config(struct bmp280_data *data)
        return bmp280_chip_config(data);
 }
 
+static irqreturn_t bme280_trigger_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);
+       s32 adc_temp, adc_press, adc_humidity, t_fine;
+       int ret;
+
+       guard(mutex)(&data->lock);
+
+       /* Burst read data registers */
+       ret = regmap_bulk_read(data->regmap, BMP280_REG_PRESS_MSB,
+                              data->buf, BME280_BURST_READ_BYTES);
+       if (ret) {
+               dev_err(data->dev, "failed to burst read sensor data\n");
+               goto out;
+       }
+
+       /* Temperature calculations */
+       adc_temp = FIELD_GET(BMP280_MEAS_TRIM_MASK, get_unaligned_be24(&data->buf[3]));
+       if (adc_temp == BMP280_TEMP_SKIPPED) {
+               dev_err(data->dev, "reading temperature skipped\n");
+               goto out;
+       }
+
+       data->sensor_data[1] = bmp280_compensate_temp(data, adc_temp);
+
+       /* Pressure calculations */
+       adc_press = FIELD_GET(BMP280_MEAS_TRIM_MASK, get_unaligned_be24(&data->buf[0]));
+       if (adc_press == BMP280_PRESS_SKIPPED) {
+               dev_err(data->dev, "reading pressure skipped\n");
+               goto out;
+       }
+
+       t_fine = bmp280_calc_t_fine(data, adc_temp);
+
+       data->sensor_data[0] = bmp280_compensate_press(data, adc_press, t_fine);
+
+       /* Humidity calculations */
+       adc_humidity = get_unaligned_be16(&data->buf[6]);
+
+       if (adc_humidity == BMP280_HUMIDITY_SKIPPED) {
+               dev_err(data->dev, "reading humidity skipped\n");
+               goto out;
+       }
+       data->sensor_data[2] = bme280_compensate_humidity(data, adc_humidity, t_fine);
+
+       iio_push_to_buffers_with_timestamp(indio_dev, &data->sensor_data,
+                                          iio_get_time_ns(indio_dev));
+
+out:
+       iio_trigger_notify_done(indio_dev->trig);
+
+       return IRQ_HANDLED;
+}
+
 static const u8 bme280_chip_ids[] = { BME280_CHIP_ID };
 static const int bme280_humid_coeffs[] = { 1000, 1024 };
 
@@ -975,6 +1190,7 @@ const struct bmp280_chip_info bme280_chip_info = {
        .start_up_time = 2000,
        .channels = bme280_channels,
        .num_channels = ARRAY_SIZE(bme280_channels),
+       .avail_scan_masks = bme280_avail_scan_masks,
 
        .oversampling_temp_avail = bmp280_oversampling_avail,
        .num_oversampling_temp_avail = ARRAY_SIZE(bmp280_oversampling_avail),
@@ -1000,6 +1216,8 @@ const struct bmp280_chip_info bme280_chip_info = {
        .read_press = bmp280_read_press,
        .read_humid = bme280_read_humid,
        .read_calib = bme280_read_calib,
+
+       .trigger_handler = bme280_trigger_handler,
 };
 EXPORT_SYMBOL_NS(bme280_chip_info, IIO_BMP280);
 
@@ -1054,7 +1272,7 @@ static int bmp380_read_temp_adc(struct bmp280_data *data, u32 *adc_temp)
        int ret;
 
        ret = regmap_bulk_read(data->regmap, BMP380_REG_TEMP_XLSB,
-                              data->buf, sizeof(data->buf));
+                              data->buf, BMP280_NUM_TEMP_BYTES);
        if (ret) {
                dev_err(data->dev, "failed to read temperature\n");
                return ret;
@@ -1123,7 +1341,7 @@ static int bmp380_read_press_adc(struct bmp280_data *data, u32 *adc_press)
        int ret;
 
        ret = regmap_bulk_read(data->regmap, BMP380_REG_PRESS_XLSB,
-                              data->buf, sizeof(data->buf));
+                              data->buf, BMP280_NUM_PRESS_BYTES);
        if (ret) {
                dev_err(data->dev, "failed to read pressure\n");
                return ret;
@@ -1384,6 +1602,53 @@ static int bmp380_chip_config(struct bmp280_data *data)
        return 0;
 }
 
+static irqreturn_t bmp380_trigger_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);
+       s32 adc_temp, adc_press, t_fine;
+       int ret;
+
+       guard(mutex)(&data->lock);
+
+       /* Burst read data registers */
+       ret = regmap_bulk_read(data->regmap, BMP380_REG_PRESS_XLSB,
+                              data->buf, BMP280_BURST_READ_BYTES);
+       if (ret) {
+               dev_err(data->dev, "failed to burst read sensor data\n");
+               goto out;
+       }
+
+       /* Temperature calculations */
+       adc_temp = get_unaligned_le24(&data->buf[3]);
+       if (adc_temp == BMP380_TEMP_SKIPPED) {
+               dev_err(data->dev, "reading temperature skipped\n");
+               goto out;
+       }
+
+       data->sensor_data[1] = bmp380_compensate_temp(data, adc_temp);
+
+       /* Pressure calculations */
+       adc_press = get_unaligned_le24(&data->buf[0]);
+       if (adc_press == BMP380_PRESS_SKIPPED) {
+               dev_err(data->dev, "reading pressure skipped\n");
+               goto out;
+       }
+
+       t_fine = bmp380_calc_t_fine(data, adc_temp);
+
+       data->sensor_data[0] = bmp380_compensate_press(data, adc_press, t_fine);
+
+       iio_push_to_buffers_with_timestamp(indio_dev, &data->sensor_data,
+                                          iio_get_time_ns(indio_dev));
+
+out:
+       iio_trigger_notify_done(indio_dev->trig);
+
+       return IRQ_HANDLED;
+}
+
 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 u8 bmp380_chip_ids[] = { BMP380_CHIP_ID, BMP390_CHIP_ID };
@@ -1399,6 +1664,7 @@ const struct bmp280_chip_info bmp380_chip_info = {
        .start_up_time = 2000,
        .channels = bmp380_channels,
        .num_channels = ARRAY_SIZE(bmp380_channels),
+       .avail_scan_masks = bmp280_avail_scan_masks,
 
        .oversampling_temp_avail = bmp380_oversampling_avail,
        .num_oversampling_temp_avail = ARRAY_SIZE(bmp380_oversampling_avail),
@@ -1426,6 +1692,8 @@ const struct bmp280_chip_info bmp380_chip_info = {
        .read_press = bmp380_read_press,
        .read_calib = bmp380_read_calib,
        .preinit = bmp380_preinit,
+
+       .trigger_handler = bmp380_trigger_handler,
 };
 EXPORT_SYMBOL_NS(bmp380_chip_info, IIO_BMP280);
 
@@ -1546,8 +1814,8 @@ static int bmp580_read_temp(struct bmp280_data *data, s32 *raw_temp)
        s32 value_temp;
        int ret;
 
-       ret = regmap_bulk_read(data->regmap, BMP580_REG_TEMP_XLSB, data->buf,
-                              sizeof(data->buf));
+       ret = regmap_bulk_read(data->regmap, BMP580_REG_TEMP_XLSB,
+                              data->buf, BMP280_NUM_TEMP_BYTES);
        if (ret) {
                dev_err(data->dev, "failed to read temperature\n");
                return ret;
@@ -1568,8 +1836,8 @@ static int bmp580_read_press(struct bmp280_data *data, u32 *raw_press)
        u32 value_press;
        int ret;
 
-       ret = regmap_bulk_read(data->regmap, BMP580_REG_PRESS_XLSB, data->buf,
-                              sizeof(data->buf));
+       ret = regmap_bulk_read(data->regmap, BMP580_REG_PRESS_XLSB,
+                              data->buf, BMP280_NUM_PRESS_BYTES);
        if (ret) {
                dev_err(data->dev, "failed to read pressure\n");
                return ret;
@@ -1916,6 +2184,38 @@ static int bmp580_chip_config(struct bmp280_data *data)
        return 0;
 }
 
+static irqreturn_t bmp580_trigger_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;
+
+       guard(mutex)(&data->lock);
+
+       /* Burst read data registers */
+       ret = regmap_bulk_read(data->regmap, BMP580_REG_TEMP_XLSB,
+                              data->buf, BMP280_BURST_READ_BYTES);
+       if (ret) {
+               dev_err(data->dev, "failed to burst read sensor data\n");
+               goto out;
+       }
+
+       /* Temperature calculations */
+       memcpy(&data->sensor_data[1], &data->buf[0], 3);
+
+       /* Pressure calculations */
+       memcpy(&data->sensor_data[0], &data->buf[3], 3);
+
+       iio_push_to_buffers_with_timestamp(indio_dev, &data->sensor_data,
+                                          iio_get_time_ns(indio_dev));
+
+out:
+       iio_trigger_notify_done(indio_dev->trig);
+
+       return IRQ_HANDLED;
+}
+
 static const int bmp580_oversampling_avail[] = { 1, 2, 4, 8, 16, 32, 64, 128 };
 static const u8 bmp580_chip_ids[] = { BMP580_CHIP_ID, BMP580_CHIP_ID_ALT };
 /* Instead of { 1000, 16 } we do this, to avoid overflow issues */
@@ -1928,8 +2228,9 @@ const struct bmp280_chip_info bmp580_chip_info = {
        .num_chip_id = ARRAY_SIZE(bmp580_chip_ids),
        .regmap_config = &bmp580_regmap_config,
        .start_up_time = 2000,
-       .channels = bmp380_channels,
-       .num_channels = ARRAY_SIZE(bmp380_channels),
+       .channels = bmp580_channels,
+       .num_channels = ARRAY_SIZE(bmp580_channels),
+       .avail_scan_masks = bmp280_avail_scan_masks,
 
        .oversampling_temp_avail = bmp580_oversampling_avail,
        .num_oversampling_temp_avail = ARRAY_SIZE(bmp580_oversampling_avail),
@@ -1956,6 +2257,8 @@ const struct bmp280_chip_info bmp580_chip_info = {
        .read_temp = bmp580_read_temp,
        .read_press = bmp580_read_press,
        .preinit = bmp580_preinit,
+
+       .trigger_handler = bmp580_trigger_handler,
 };
 EXPORT_SYMBOL_NS(bmp580_chip_info, IIO_BMP280);
 
@@ -2134,7 +2437,7 @@ static int bmp180_read_press_adc(struct bmp280_data *data, u32 *adc_press)
                return ret;
 
        ret = regmap_bulk_read(data->regmap, BMP180_REG_OUT_MSB,
-                              data->buf, sizeof(data->buf));
+                              data->buf, BMP280_NUM_PRESS_BYTES);
        if (ret) {
                dev_err(data->dev, "failed to read pressure\n");
                return ret;
@@ -2205,6 +2508,36 @@ static int bmp180_chip_config(struct bmp280_data *data)
        return 0;
 }
 
+static irqreturn_t bmp180_trigger_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, chan_value;
+
+       guard(mutex)(&data->lock);
+
+       ret = bmp180_read_temp(data, &chan_value);
+       if (ret)
+               goto out;
+
+       data->sensor_data[1] = chan_value;
+
+       ret = bmp180_read_press(data, &chan_value);
+       if (ret)
+               goto out;
+
+       data->sensor_data[0] = chan_value;
+
+       iio_push_to_buffers_with_timestamp(indio_dev, &data->sensor_data,
+                                          iio_get_time_ns(indio_dev));
+
+out:
+       iio_trigger_notify_done(indio_dev->trig);
+
+       return IRQ_HANDLED;
+}
+
 static const int bmp180_oversampling_temp_avail[] = { 1 };
 static const int bmp180_oversampling_press_avail[] = { 1, 2, 4, 8 };
 static const u8 bmp180_chip_ids[] = { BMP180_CHIP_ID };
@@ -2219,6 +2552,7 @@ const struct bmp280_chip_info bmp180_chip_info = {
        .start_up_time = 2000,
        .channels = bmp280_channels,
        .num_channels = ARRAY_SIZE(bmp280_channels),
+       .avail_scan_masks = bmp280_avail_scan_masks,
 
        .oversampling_temp_avail = bmp180_oversampling_temp_avail,
        .num_oversampling_temp_avail =
@@ -2239,6 +2573,8 @@ const struct bmp280_chip_info bmp180_chip_info = {
        .read_temp = bmp180_read_temp,
        .read_press = bmp180_read_press,
        .read_calib = bmp180_read_calib,
+
+       .trigger_handler = bmp180_trigger_handler,
 };
 EXPORT_SYMBOL_NS(bmp180_chip_info, IIO_BMP280);
 
@@ -2284,6 +2620,30 @@ static int bmp085_fetch_eoc_irq(struct device *dev,
        return 0;
 }
 
+static int bmp280_buffer_preenable(struct iio_dev *indio_dev)
+{
+       struct bmp280_data *data = iio_priv(indio_dev);
+
+       pm_runtime_get_sync(data->dev);
+
+       return 0;
+}
+
+static int bmp280_buffer_postdisable(struct iio_dev *indio_dev)
+{
+       struct bmp280_data *data = iio_priv(indio_dev);
+
+       pm_runtime_mark_last_busy(data->dev);
+       pm_runtime_put_autosuspend(data->dev);
+
+       return 0;
+}
+
+static const struct iio_buffer_setup_ops bmp280_buffer_setup_ops = {
+       .preenable = bmp280_buffer_preenable,
+       .postdisable = bmp280_buffer_postdisable,
+};
+
 static void bmp280_pm_disable(void *data)
 {
        struct device *dev = data;
@@ -2330,6 +2690,7 @@ int bmp280_common_probe(struct device *dev,
        /* Apply initial values from chip info structure */
        indio_dev->channels = chip_info->channels;
        indio_dev->num_channels = chip_info->num_channels;
+       indio_dev->available_scan_masks = chip_info->avail_scan_masks;
        data->oversampling_press = chip_info->oversampling_press_default;
        data->oversampling_humid = chip_info->oversampling_humid_default;
        data->oversampling_temp = chip_info->oversampling_temp_default;
@@ -2415,6 +2776,14 @@ int bmp280_common_probe(struct device *dev,
                                             "failed to read calibration coefficients\n");
        }
 
+       ret = devm_iio_triggered_buffer_setup(data->dev, indio_dev,
+                                             iio_pollfunc_store_time,
+                                             data->chip_info->trigger_handler,
+                                             &bmp280_buffer_setup_ops);
+       if (ret)
+               return dev_err_probe(data->dev, ret,
+                                    "iio triggered buffer setup failed\n");
+
        /*
         * Attempt to grab an optional EOC IRQ - only the BMP085 has this
         * however as it happens, the BMP085 shares the chip ID of BMP180
index fee266d..f855f56 100644 (file)
@@ -40,14 +40,10 @@ static int bmp380_regmap_spi_read(void *context, const void *reg,
                                  size_t reg_size, void *val, size_t val_size)
 {
        struct spi_device *spi = to_spi_device(context);
-       u8 rx_buf[4];
+       u8 rx_buf[BME280_BURST_READ_BYTES + 1];
        ssize_t status;
 
-       /*
-        * Maximum number of consecutive bytes read for a temperature or
-        * pressure measurement is 3.
-        */
-       if (val_size > 3)
+       if (val_size > BME280_BURST_READ_BYTES)
                return -EINVAL;
 
        /*
index a3d2cd7..0933e41 100644 (file)
 #define BMP280_PRESS_SKIPPED           0x80000
 #define BMP280_HUMIDITY_SKIPPED                0x8000
 
+/* Number of bytes for each value */
+#define BMP280_NUM_PRESS_BYTES         3
+#define BMP280_NUM_TEMP_BYTES          3
+#define BME280_NUM_HUMIDITY_BYTES      2
+#define BMP280_BURST_READ_BYTES                (BMP280_NUM_PRESS_BYTES + \
+                                        BMP280_NUM_TEMP_BYTES)
+#define BME280_BURST_READ_BYTES                (BMP280_NUM_PRESS_BYTES + \
+                                        BMP280_NUM_TEMP_BYTES + \
+                                        BME280_NUM_HUMIDITY_BYTES)
+
 /* Core exported structs */
 
 static const char *const bmp280_supply_names[] = {
@@ -397,13 +407,19 @@ struct bmp280_data {
         */
        int sampling_freq;
 
+       /*
+        * Data to push to userspace triggered buffer. Up to 3 channels and
+        * s64 timestamp, aligned.
+        */
+       s32 sensor_data[6] __aligned(8);
+
        /*
         * DMA (thus cache coherency maintenance) may require the
         * transfer buffers to live in their own cache lines.
         */
        union {
                /* Sensor data buffer */
-               u8 buf[3];
+               u8 buf[BME280_BURST_READ_BYTES];
                /* Calibration data buffers */
                __le16 bmp280_cal_buf[BMP280_CONTIGUOUS_CALIB_REGS / 2];
                __be16 bmp180_cal_buf[BMP180_REG_CALIB_COUNT / 2];
@@ -425,6 +441,7 @@ struct bmp280_chip_info {
        const struct iio_chan_spec *channels;
        int num_channels;
        unsigned int start_up_time;
+       const unsigned long *avail_scan_masks;
 
        const int *oversampling_temp_avail;
        int num_oversampling_temp_avail;
@@ -459,6 +476,8 @@ struct bmp280_chip_info {
        int (*read_humid)(struct bmp280_data *data, u32 *adc_humidity);
        int (*read_calib)(struct bmp280_data *data);
        int (*preinit)(struct bmp280_data *data);
+
+       irqreturn_t (*trigger_handler)(int irq, void *p);
 };
 
 /* Chip infos for each variant */