2024-05-08 16:42:33

by Vasileios Amoiridis

[permalink] [raw]
Subject: [PATCH 0/9] iio: pressure: bmp280: Add triggered buffer support and

Based on upstream master with the previous patches of this series applied
as well.

IMPORTANT NOTE: There is a fix queued up for this driver here [1]. It is going
to conflict with PATCH [7-9/9]. The previous patches should be fine. The
solution should be quite trivial with minor changes in all 3 PATCH [7-9/9].
When it is deemed necessary I can resubmit the patches or help with resolving
the issue.

Changes in v6:

PATCH [1-3/9]: new:
- split of PATCH [5/10] of v5 according to proposal here [2].

PATCH [4/9]: new:
- split of PATCH [6/10] of v5 according to proposal here [3].

PATCH [6/9]:
- Removed mutex_lock() and added guard(mutex) to
bmp580_nvmem_{read/write}() functions as well.

PATCH [9/9]:
- In the buffer handlers, add 'goto out;' instead of just returning the
error because iio_trigger_notify_done() wouldn't be called in case of
error.

[1]: https://lore.kernel.org/linux-iio/[email protected]/
[2]: https://lore.kernel.org/linux-iio/20240505200818.1e70c664@jic23-huawei/
[3]: https://lore.kernel.org/linux-iio/20240505202106.1c780044@jic23-huawei/

Vasileios Amoiridis (9):
iio: pressure: bmp280: Remove dead error checks
iio: pressure: bmp280: Remove, add and update error messages
iio: pressure: bmp280: Make error checks consistent
iio: pressure: bmp280: Use unsigned data types for raw sensor data
iio: pressure: bmp280: Refactorize reading functions
iio: pressure: bmp280: Introduce new cleanup routines
iio: pressure: bmp280: Generalize read_{temp,press,humid}() functions
iio: pressure: bmp280: Add SCALE, RAW values in channels and
refactorize them
iio: pressure: bmp280: Add triggered buffer support

drivers/iio/pressure/Kconfig | 2 +
drivers/iio/pressure/bmp280-core.c | 1130 ++++++++++++++++++++--------
drivers/iio/pressure/bmp280-spi.c | 8 +-
drivers/iio/pressure/bmp280.h | 34 +-
4 files changed, 844 insertions(+), 330 deletions(-)


base-commit: dccb07f2914cdab2ac3a5b6c98406f765acab803
--
2.25.1



2024-05-08 16:43:01

by Vasileios Amoiridis

[permalink] [raw]
Subject: [PATCH 1/9] iio: pressure: bmp280: Remove dead error checks

The ret value is being checked already in all the previous
paths which exit in case of error, so this path can never
become true.

Signed-off-by: Vasileios Amoiridis <[email protected]>
---
drivers/iio/pressure/bmp280-core.c | 4 ----
1 file changed, 4 deletions(-)

diff --git a/drivers/iio/pressure/bmp280-core.c b/drivers/iio/pressure/bmp280-core.c
index ed49e0779d41..311a011604da 100644
--- a/drivers/iio/pressure/bmp280-core.c
+++ b/drivers/iio/pressure/bmp280-core.c
@@ -1350,10 +1350,6 @@ static int bmp580_nvm_operation(struct bmp280_data *data, bool is_write)
poll = 50;
timeout = 400;
}
- if (ret) {
- dev_err(data->dev, "failed to write command sequence\n");
- return -EIO;
- }

/* Wait until NVM is ready again */
ret = regmap_read_poll_timeout(data->regmap, BMP580_REG_STATUS, reg,

base-commit: dccb07f2914cdab2ac3a5b6c98406f765acab803
prerequisite-patch-id: 97b99b1106cbfd65cef8d256e4dc1a3a9257511e
prerequisite-patch-id: c60e8ef6fae62417c3430b7598b1a3d2a551be79
prerequisite-patch-id: 6a49484a6d154ddcd1b45b71a6be2c3542ae0be6
prerequisite-patch-id: 5aae62fa92c719fb65a8701ec4e1c4284bef7fd9
prerequisite-patch-id: 6943297d5f70f74bfcf5d5b26198423e428773d9
--
2.25.1


2024-05-08 16:43:17

by Vasileios Amoiridis

[permalink] [raw]
Subject: [PATCH 2/9] iio: pressure: bmp280: Remove, add and update error messages

Remove duplicate error messages, add missing error messages and
update redundant ones.

Signed-off-by: Vasileios Amoiridis <[email protected]>
---
drivers/iio/pressure/bmp280-core.c | 55 +++++++++++++++++++++---------
1 file changed, 38 insertions(+), 17 deletions(-)

diff --git a/drivers/iio/pressure/bmp280-core.c b/drivers/iio/pressure/bmp280-core.c
index 311a011604da..0aa16fb135c1 100644
--- a/drivers/iio/pressure/bmp280-core.c
+++ b/drivers/iio/pressure/bmp280-core.c
@@ -222,10 +222,8 @@ static int bme280_read_calib(struct bmp280_data *data)

/* Load shared calibration params with bmp280 first */
ret = bmp280_read_calib(data);
- if (ret < 0) {
- dev_err(dev, "failed to read calibration parameters\n");
+ if (ret < 0)
return ret;
- }

/*
* Read humidity calibration values.
@@ -841,8 +839,10 @@ static int bme280_chip_config(struct bmp280_data *data)
*/
ret = regmap_update_bits(data->regmap, BME280_REG_CTRL_HUMIDITY,
BME280_OSRS_HUMIDITY_MASK, osrs);
- if (ret < 0)
+ if (ret < 0) {
+ dev_err(data->dev, "failed to set humidity oversampling");
return ret;
+ }

return bmp280_chip_config(data);
}
@@ -1071,7 +1071,7 @@ static int bmp380_read_calib(struct bmp280_data *data)
sizeof(data->bmp380_cal_buf));
if (ret) {
dev_err(data->dev,
- "failed to read temperature calibration parameters\n");
+ "failed to read calibration parameters\n");
return ret;
}

@@ -1609,20 +1609,24 @@ static int bmp580_preinit(struct bmp280_data *data)

/* Post powerup sequence */
ret = regmap_read(data->regmap, BMP580_REG_CHIP_ID, &reg);
- if (ret)
+ if (ret) {
+ dev_err(data->dev, "failed to establish comms with the chip\n");
return ret;
+ }

/* Print warn message if we don't know the chip id */
if (reg != BMP580_CHIP_ID && reg != BMP580_CHIP_ID_ALT)
- dev_warn(data->dev, "preinit: unexpected chip_id\n");
+ dev_warn(data->dev, "unexpected chip_id\n");

ret = regmap_read(data->regmap, BMP580_REG_STATUS, &reg);
- if (ret)
+ if (ret) {
+ dev_err(data->dev, "failed to read nvm status\n");
return ret;
+ }

/* Check nvm status */
if (!(reg & BMP580_STATUS_NVM_RDY_MASK) || (reg & BMP580_STATUS_NVM_ERR_MASK)) {
- dev_err(data->dev, "preinit: nvm error on powerup sequence\n");
+ dev_err(data->dev, "nvm error on powerup sequence\n");
return -EIO;
}

@@ -1657,6 +1661,10 @@ static int bmp580_chip_config(struct bmp280_data *data)
BMP580_DSP_COMP_MASK |
BMP580_DSP_SHDW_IIR_TEMP_EN |
BMP580_DSP_SHDW_IIR_PRESS_EN, reg_val);
+ if (ret) {
+ dev_err(data->dev, "failed to change DSP mode settings\n");
+ return ret;
+ }

/* Configure oversampling */
reg_val = FIELD_PREP(BMP580_OSR_TEMP_MASK, data->oversampling_temp) |
@@ -1778,8 +1786,10 @@ static int bmp180_wait_for_eoc(struct bmp280_data *data, u8 ctrl_meas)
reinit_completion(&data->done);

ret = regmap_write(data->regmap, BMP280_REG_CTRL_MEAS, ctrl_meas);
- if (ret)
+ if (ret) {
+ dev_err(data->dev, "failed to write crtl_meas register\n");
return ret;
+ }

if (data->use_eoc) {
/*
@@ -1802,12 +1812,16 @@ static int bmp180_wait_for_eoc(struct bmp280_data *data, u8 ctrl_meas)
}

ret = regmap_read(data->regmap, BMP280_REG_CTRL_MEAS, &ctrl);
- if (ret)
+ if (ret) {
+ dev_err(data->dev, "failed to read ctrl_meas register\n");
return ret;
+ }

/* The value of this bit reset to "0" after conversion is complete */
- if (ctrl & BMP180_MEAS_SCO)
+ if (ctrl & BMP180_MEAS_SCO) {
+ dev_err(data->dev, "conversion didn't complete\n");
return -EIO;
+ }

return 0;
}
@@ -1824,8 +1838,10 @@ static int bmp180_read_adc_temp(struct bmp280_data *data, int *val)

ret = regmap_bulk_read(data->regmap, BMP180_REG_OUT_MSB,
&data->be16, sizeof(data->be16));
- if (ret)
+ if (ret) {
+ dev_err(data->dev, "failed to read temperature\n");
return ret;
+ }

*val = be16_to_cpu(data->be16);

@@ -1840,9 +1856,10 @@ static int bmp180_read_calib(struct bmp280_data *data)

ret = regmap_bulk_read(data->regmap, BMP180_REG_CALIB_START,
data->bmp180_cal_buf, sizeof(data->bmp180_cal_buf));
-
- if (ret < 0)
+ if (ret < 0) {
+ dev_err(data->dev, "failed to read calibration parameters\n");
return ret;
+ }

/* None of the words has the value 0 or 0xFFFF */
for (i = 0; i < ARRAY_SIZE(data->bmp180_cal_buf); i++) {
@@ -1925,8 +1942,10 @@ static int bmp180_read_adc_press(struct bmp280_data *data, int *val)

ret = regmap_bulk_read(data->regmap, BMP180_REG_OUT_MSB,
data->buf, sizeof(data->buf));
- if (ret)
+ if (ret) {
+ dev_err(data->dev, "failed to read pressure\n");
return ret;
+ }

*val = get_unaligned_be24(data->buf) >> (8 - oss);

@@ -2158,8 +2177,10 @@ int bmp280_common_probe(struct device *dev,
data->regmap = regmap;

ret = regmap_read(regmap, data->chip_info->id_reg, &chip_id);
- if (ret < 0)
+ if (ret < 0) {
+ dev_err(data->dev, "failed to read chip id\n");
return ret;
+ }

for (i = 0; i < data->chip_info->num_chip_id; i++) {
if (chip_id == data->chip_info->chip_id[i]) {
--
2.25.1


2024-05-08 16:46:21

by Vasileios Amoiridis

[permalink] [raw]
Subject: [PATCH 9/9] iio: pressure: bmp280: Add triggered buffer support

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 <[email protected]>
Signed-off-by: Vasileios Amoiridis <[email protected]>
---
drivers/iio/pressure/Kconfig | 2 +
drivers/iio/pressure/bmp280-core.c | 339 +++++++++++++++++++++++++++--
drivers/iio/pressure/bmp280-spi.c | 8 +-
drivers/iio/pressure/bmp280.h | 21 +-
4 files changed, 348 insertions(+), 22 deletions(-)

diff --git a/drivers/iio/pressure/Kconfig b/drivers/iio/pressure/Kconfig
index 3ad38506028e..0b5406a3f85d 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 3f8144a0355b..95f56836fd86 100644
--- a/drivers/iio/pressure/bmp280-core.c
+++ b/drivers/iio/pressure/bmp280-core.c
@@ -41,7 +41,10 @@
#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,13 @@ 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,
@@ -200,7 +253,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 = 32,
+ .storagebits = 32,
+ .endianness = IIO_CPU,
+ },
},
+ IIO_CHAN_SOFT_TIMESTAMP(2),
};

static int bmp280_read_calib(struct bmp280_data *data)
@@ -322,7 +383,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;
@@ -369,7 +430,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;
@@ -430,7 +491,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 +935,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 +972,74 @@ static int bmp280_chip_config(struct bmp280_data *data)
return ret;
}

+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);
+ s32 adc_temp, adc_press, adc_humidity, t_fine;
+ u8 sizeof_burst_read;
+ int ret;
+
+ guard(mutex)(&data->lock);
+
+ /*
+ * If humidity channel is enabled it means that we are called for the
+ * BME280 humidity sensor.
+ */
+ if (test_bit(BME280_HUMID, indio_dev->active_scan_mask))
+ sizeof_burst_read = BME280_BURST_READ_BYTES;
+ else
+ sizeof_burst_read = BMP280_BURST_READ_BYTES;
+
+ /* Burst read data registers */
+ ret = regmap_bulk_read(data->regmap, BMP280_REG_PRESS_MSB,
+ data->buf, sizeof_burst_read);
+ 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 */
+ if (test_bit(BME280_HUMID, indio_dev->active_scan_mask)) {
+ 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 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 };
@@ -913,7 +1052,8 @@ const struct bmp280_chip_info bmp280_chip_info = {
.regmap_config = &bmp280_regmap_config,
.start_up_time = 2000,
.channels = bmp280_channels,
- .num_channels = 2,
+ .num_channels = 3,
+ .avail_scan_masks = bmp280_avail_scan_masks,

.oversampling_temp_avail = bmp280_oversampling_avail,
.num_oversampling_temp_avail = ARRAY_SIZE(bmp280_oversampling_avail),
@@ -942,6 +1082,8 @@ const struct bmp280_chip_info bmp280_chip_info = {
.read_temp = bmp280_read_temp,
.read_press = bmp280_read_press,
.read_calib = bmp280_read_calib,
+
+ .buffer_handler = bmp280_buffer_handler,
};
EXPORT_SYMBOL_NS(bmp280_chip_info, IIO_BMP280);

@@ -974,7 +1116,8 @@ const struct bmp280_chip_info bme280_chip_info = {
.regmap_config = &bmp280_regmap_config,
.start_up_time = 2000,
.channels = bme280_channels,
- .num_channels = 3,
+ .num_channels = 4,
+ .avail_scan_masks = bme280_avail_scan_masks,

.oversampling_temp_avail = bmp280_oversampling_avail,
.num_oversampling_temp_avail = ARRAY_SIZE(bmp280_oversampling_avail),
@@ -1000,6 +1143,8 @@ const struct bmp280_chip_info bme280_chip_info = {
.read_press = bmp280_read_press,
.read_humid = bme280_read_humid,
.read_calib = bme280_read_calib,
+
+ .buffer_handler = bmp280_buffer_handler,
};
EXPORT_SYMBOL_NS(bme280_chip_info, IIO_BMP280);

@@ -1061,7 +1206,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;
@@ -1130,7 +1275,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 +1529,53 @@ static int bmp380_chip_config(struct bmp280_data *data)
return 0;
}

+static irqreturn_t bmp380_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);
+ 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 };
@@ -1398,7 +1590,8 @@ const struct bmp280_chip_info bmp380_chip_info = {
.spi_read_extra_byte = true,
.start_up_time = 2000,
.channels = bmp380_channels,
- .num_channels = 2,
+ .num_channels = 3,
+ .avail_scan_masks = bmp280_avail_scan_masks,

.oversampling_temp_avail = bmp380_oversampling_avail,
.num_oversampling_temp_avail = ARRAY_SIZE(bmp380_oversampling_avail),
@@ -1426,6 +1619,8 @@ const struct bmp280_chip_info bmp380_chip_info = {
.read_press = bmp380_read_press,
.read_calib = bmp380_read_calib,
.preinit = bmp380_preinit,
+
+ .buffer_handler = bmp380_buffer_handler,
};
EXPORT_SYMBOL_NS(bmp380_chip_info, IIO_BMP280);

@@ -1545,8 +1740,8 @@ static int bmp580_read_temp(struct bmp280_data *data, s32 *raw_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;
@@ -1565,8 +1760,8 @@ static int bmp580_read_press(struct bmp280_data *data, u32 *raw_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;
@@ -1890,6 +2085,51 @@ static int bmp580_chip_config(struct bmp280_data *data)
return 0;
}

+static irqreturn_t bmp580_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);
+ s32 adc_temp, adc_press;
+ 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 */
+ adc_temp = get_unaligned_le24(&data->buf[0]);
+ if (adc_temp == BMP580_TEMP_SKIPPED) {
+ dev_err(data->dev, "reading temperature skipped\n");
+ goto out;
+ }
+
+ data->sensor_data[1] = adc_temp;
+
+ /* Pressure calculations */
+ adc_press = get_unaligned_le24(&data->buf[3]);
+ if (adc_press == BMP380_PRESS_SKIPPED) {
+ dev_err(data->dev, "reading pressure skipped\n");
+ goto out;
+ }
+
+ data->sensor_data[0] = adc_press;
+
+ 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 };
static const int bmp580_temp_coeffs[] = { 1000, 16 };
@@ -1902,7 +2142,8 @@ const struct bmp280_chip_info bmp580_chip_info = {
.regmap_config = &bmp580_regmap_config,
.start_up_time = 2000,
.channels = bmp380_channels,
- .num_channels = 2,
+ .num_channels = 3,
+ .avail_scan_masks = bmp280_avail_scan_masks,

.oversampling_temp_avail = bmp580_oversampling_avail,
.num_oversampling_temp_avail = ARRAY_SIZE(bmp580_oversampling_avail),
@@ -1929,6 +2170,8 @@ const struct bmp280_chip_info bmp580_chip_info = {
.read_temp = bmp580_read_temp,
.read_press = bmp580_read_press,
.preinit = bmp580_preinit,
+
+ .buffer_handler = bmp580_buffer_handler,
};
EXPORT_SYMBOL_NS(bmp580_chip_info, IIO_BMP280);

@@ -2107,7 +2350,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;
@@ -2178,6 +2421,36 @@ static int bmp180_chip_config(struct bmp280_data *data)
return 0;
}

+static irqreturn_t bmp180_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, 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 };
@@ -2191,7 +2464,8 @@ const struct bmp280_chip_info bmp180_chip_info = {
.regmap_config = &bmp180_regmap_config,
.start_up_time = 2000,
.channels = bmp280_channels,
- .num_channels = 2,
+ .num_channels = 3,
+ .avail_scan_masks = bmp280_avail_scan_masks,

.oversampling_temp_avail = bmp180_oversampling_temp_avail,
.num_oversampling_temp_avail =
@@ -2212,6 +2486,8 @@ const struct bmp280_chip_info bmp180_chip_info = {
.read_temp = bmp180_read_temp,
.read_press = bmp180_read_press,
.read_calib = bmp180_read_calib,
+
+ .buffer_handler = bmp180_buffer_handler,
};
EXPORT_SYMBOL_NS(bmp180_chip_info, IIO_BMP280);

@@ -2257,6 +2533,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;
+}
+
+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;
@@ -2303,6 +2603,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;
@@ -2388,6 +2689,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->buffer_handler,
+ NULL);
+ 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
diff --git a/drivers/iio/pressure/bmp280-spi.c b/drivers/iio/pressure/bmp280-spi.c
index 62b4e58104cf..e5abee15950e 100644
--- a/drivers/iio/pressure/bmp280-spi.c
+++ b/drivers/iio/pressure/bmp280-spi.c
@@ -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;

/*
diff --git a/drivers/iio/pressure/bmp280.h b/drivers/iio/pressure/bmp280.h
index a3d2cd722760..756c644354c2 100644
--- a/drivers/iio/pressure/bmp280.h
+++ b/drivers/iio/pressure/bmp280.h
@@ -304,6 +304,16 @@
#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 (*buffer_handler)(int irq, void *p);
};

/* Chip infos for each variant */
--
2.25.1


2024-05-08 16:55:41

by Vasileios Amoiridis

[permalink] [raw]
Subject: Re: [PATCH 0/9] iio: pressure: bmp280: Add triggered buffer support and

On Wed, May 08, 2024 at 06:34:16PM +0200, Vasileios Amoiridis wrote:
> Based on upstream master with the previous patches of this series applied
> as well.
>
> IMPORTANT NOTE: There is a fix queued up for this driver here [1]. It is going
> to conflict with PATCH [7-9/9]. The previous patches should be fine. The
> solution should be quite trivial with minor changes in all 3 PATCH [7-9/9].
> When it is deemed necessary I can resubmit the patches or help with resolving
> the issue.
>
> Changes in v6:
>
> PATCH [1-3/9]: new:
> - split of PATCH [5/10] of v5 according to proposal here [2].
>
> PATCH [4/9]: new:
> - split of PATCH [6/10] of v5 according to proposal here [3].
>
> PATCH [6/9]:
> - Removed mutex_lock() and added guard(mutex) to
> bmp580_nvmem_{read/write}() functions as well.
>
> PATCH [9/9]:
> - In the buffer handlers, add 'goto out;' instead of just returning the
> error because iio_trigger_notify_done() wouldn't be called in case of
> error.
>
> [1]: https://lore.kernel.org/linux-iio/[email protected]/
> [2]: https://lore.kernel.org/linux-iio/20240505200818.1e70c664@jic23-huawei/
> [3]: https://lore.kernel.org/linux-iio/20240505202106.1c780044@jic23-huawei/
>
> Vasileios Amoiridis (9):
> iio: pressure: bmp280: Remove dead error checks
> iio: pressure: bmp280: Remove, add and update error messages
> iio: pressure: bmp280: Make error checks consistent
> iio: pressure: bmp280: Use unsigned data types for raw sensor data
> iio: pressure: bmp280: Refactorize reading functions
> iio: pressure: bmp280: Introduce new cleanup routines
> iio: pressure: bmp280: Generalize read_{temp,press,humid}() functions
> iio: pressure: bmp280: Add SCALE, RAW values in channels and
> refactorize them
> iio: pressure: bmp280: Add triggered buffer support
>
> drivers/iio/pressure/Kconfig | 2 +
> drivers/iio/pressure/bmp280-core.c | 1130 ++++++++++++++++++++--------
> drivers/iio/pressure/bmp280-spi.c | 8 +-
> drivers/iio/pressure/bmp280.h | 34 +-
> 4 files changed, 844 insertions(+), 330 deletions(-)
>
>
> base-commit: dccb07f2914cdab2ac3a5b6c98406f765acab803
> --
> 2.25.1
>

I messed up with the versioning before, please don't comment here if
possible. The correct thread is the following:

https://lore.kernel.org/linux-iio/[email protected]/T/#t

Sorry for the mess up.

Cheers,
Vasilis