Skip to contentSkip to conversation

Add support for pressure sensor Bosch BMP380

PATCH Applied Angel Iglesias 3 participants 22 messages Sep 12, 2022 – Sep 18, 2022

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

v6 cover Add support for pressure sensor Bosch BMP380

This patchset adds BMP380 variant to the already existing drivers for the Bosch BMP180/280 pressure sensors.

Patch 1 reorder local variables declarations following reverse xmas tree conventions, as suggested by Andy Shevchenko <[email protected]>. Patch 2 migrates existing code to use FIELD_GET/FIELD_PREP and GENMASK utilities.
Patch 3 is a minor refactor of the function that loads bmp280 calibration params, taking advantage of the data contiguity in memory. Patch 4 is a minor refactor simplifying driver initialization logic to facilitate the integration of the new sensor variant extending the information stored in the "chip_info" struct.
Patch 5 fixes DMA unsafe regmap_bulk_* calls reported by Jonathan Cameron <[email protected]>.
Patch 6 is a minor refactor reordering device match tables declarations in forward order as suggested by Andy Shevchenko <[email protected]>. Patch 7 adds the basic logic to initialize and read measurements from the sensor.
Patch 8 adds references and sensor id to the devicetree bindings docs. Patch 9 adds advanced configurable features such as sampling frequency and IIR filter through the IIO sysfs ABI.

Changes in v6:
- Introduced patch 1 reordering local variables declarations.
- Patch 2 is separated form v5 patch 1, separating initialization refactor from migration to FIELD_GET, FIELD_PREP and GENMASK.
- Patch 3 backports a refactor made to bmp280 calibration load on v5 patch 2.
- Introduced patch 6 reordering i2c device match tables declarations.
- Revised patch 7 and 9 and smoothed transition to patch 9 moving some code on v5 patch 5 to patch 7 (BMP380 basic enablement).
- Cleaned error handling of regmap calls thorough patches.
- Changed formula used to handle IIR filter on patch 9 following feedback made by Andy Shevchenko <[email protected]>.
- Made union with data buffers on patch 5 anonymous (suggested by Andy Shevchenko <[email protected]>)
- Improved handling of be16 and le16 data on patch 5 integrating changes suggested by Jonathan Cameron <[email protected]>.

Changes in v5:
- Moved dt bindings patch (previously patch 2/5) to 4/5 to preserve tree coherence as suggested by Jonathan Cameron <[email protected]>
- Patch 1: Simplified initial oversampling values assignation.
- Patch 1: Updated codepaths for bmp180 and bmp280 to use FIELD_GET and FIELD_GET helpers. Migrated compatible masks to use GENMASK.
- Patch 2: Store DMA-safe buffers on the device data struct instead of using dynamic allocations for calibration buffers.
Thanks Jonathan Cameron <[email protected]>.
- Patch 3: Fixed small typos
- Patch 3: Fixed incompatible division on 32-bit machines reported by Andy Shevchenko <[email protected]> and kernel test robot <[email protected]>.
- Patch 3: Fixed inconsistent use of "x" and "X" declaring constants.
- Patch 5: Dropped incorrect reported-by tag on changelog message.
- Patch 5: Fixed typos on various comments.

Changes in v4:
- Patch 4 and 2: Merged v3 patch 2 (Kconfig refs update) into this patch.
- Patch 3: Added patch fixing unsafe DMA regmap_bulk_* calls reported by Jonathan Cameron <[email protected]>.
- Patch 4: Fixed DMA unsafe buffers used on regmap_bulk_* calls reported by Jonathan Cameron <[email protected]>.

Changes in v3:
- Patch 2: Fixed incorrect abbreviation.
- Patch 3: use dev_err_probe helper to handle error initializing sensor.
- Patch 4: Fixed kernel test robot warning provoked by missing include.
- Patch 4: Fixed bug reported by Dan Carpenter <[email protected]>.
- Patch 5: Fixed formatting and typos on multiple comments.
- Patch 5: Fixed missing boolean initialization reported by Andy Shevchenko <[email protected]>.
- Patch 5: Replaced duplicated comments with a single comment containing a brief explantation in a shared location.
- Patch 5: Dropped incorrect use of unlikely macro.

Changes in v2:
- Added patch 2 updating Kconfig with references to new sensor.
- Patch 3 adds changes proposed by Jonathan Cameron <[email protected]> to declutter and unify configuration logic for the different sensors extending "chip_info" struct with default configuration parameters.
- Patch 4: store temperature and pressure adc values on 3 byte array instead of using the type __le32. Uses function get_unaligned_le24 to convert the little-endian encoded 3 byte value to an integer.
- Patch 4: drops custom macro le16_from_bytes and use get_unaligned_le16.
- Patch 4: generate masks using GENMASK macro.
- Patch 4: use FIELD_PREP to generate bitfields for registries.
- Patch 4: dropped stray formatting change.
- Patch 5: adds sanity checks in bmp280_read_raw for channel properties only available in the BMP380.
- Patch 5: on bmp280_write_* checks if a problem occurred committing new configuration and tries to restore previous working configuration to keep the sensor in a previous working state.
- Patch 5: refactored bmp380_chip_config to only check for configuration errors when a configuration change is detected.
- Patch 5: improved invalid configuration detection on BMP380 restarting measurement loop to force a new measurement after the configuration is updated.

Previous patch version available on:
https://lore.kernel.org/all/[email protected]/

Angel Iglesias (9):
iio: pressure: bmp280: reorder local variables following reverse xmas
tree
iio: pressure: bmp280: use FIELD_GET, FIELD_PREP and GENMASK
iio: pressure: bmp280: Simplify bmp280 calibration data reading
iio: pressure: bmp280: simplify driver initialization logic
iio: pressure: bmp280: Fix alignment for DMA safety
iio: pressure: bmp280: reorder i2c device tables declarations
iio: pressure: bmp280: Add support for BMP380 sensor family
dt-bindings: iio: pressure: bmp085: Add BMP380 compatible string
iio: pressure: bmp280: Add more tunable config parameters for BMP380

 .../bindings/iio/pressure/bmp085.yaml         |   4 +-
 drivers/iio/pressure/Kconfig                  |   6 +-
 drivers/iio/pressure/bmp280-core.c            | 962 +++++++++++++++---
 drivers/iio/pressure/bmp280-i2c.c             |  15 +-
 drivers/iio/pressure/bmp280-regmap.c          |  55 +
 drivers/iio/pressure/bmp280-spi.c             |   5 +
 drivers/iio/pressure/bmp280.h                 | 164 ++-
 7 files changed, 1018 insertions(+), 193 deletions(-)

base-commit: 2f61ff8272967c9bdcba810aa978170814b08f7c

Signature · 1 line
2.37.3
#1 lore raw

PATCH v6 1/9 iio: pressure: bmp280: reorder local variables following reverse xmas tree

Reordered definitions of local variables following the reverse christmas tree convention.

---
 drivers/iio/pressure/bmp280-core.c | 65 +++++++++++++++---------------
 1 file changed, 33 insertions(+), 32 deletions(-)
drivers/iio/pressure/bmp280-core.c +33 -32
index fe7aa81e7cc9..42b29f30e9d1 100644
@@ -151,13 +151,14 @@ static int bmp280_read_calib(struct bmp280_data *data,
 			     struct bmp280_calib *calib,
 			     unsigned int chip)
 {
-	int ret;
+	__le16 p_buf[BMP280_COMP_PRESS_REG_COUNT / 2];
+	__le16 t_buf[BMP280_COMP_TEMP_REG_COUNT / 2];
+	struct device *dev = data->dev;
 	unsigned int tmp;
 	__le16 l16;
 	__be16 b16;
-	struct device *dev = data->dev;
-	__le16 t_buf[BMP280_COMP_TEMP_REG_COUNT / 2];
-	__le16 p_buf[BMP280_COMP_PRESS_REG_COUNT / 2];
+	int ret;
+
 
 	/* Read temperature calibration values. */
 	ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_TEMP_START,
@@ -261,8 +262,8 @@ static int bmp280_read_calib(struct bmp280_data *data,
 static u32 bmp280_compensate_humidity(struct bmp280_data *data,
 				      s32 adc_humidity)
 {
-	s32 var;
 	struct bmp280_calib *calib = &data->calib.bmp280;
+	s32 var;
 
 	var = ((s32)data->t_fine) - (s32)76800;
 	var = ((((adc_humidity << 14) - (calib->H4 << 20) - (calib->H5 * var))
@@ -286,8 +287,8 @@ static u32 bmp280_compensate_humidity(struct bmp280_data *data,
 static s32 bmp280_compensate_temp(struct bmp280_data *data,
 				  s32 adc_temp)
 {
-	s32 var1, var2;
 	struct bmp280_calib *calib = &data->calib.bmp280;
+	s32 var1, var2;
 
 	var1 = (((adc_temp >> 3) - ((s32)calib->T1 << 1)) *
 		((s32)calib->T2)) >> 11;
@@ -309,8 +310,8 @@ static s32 bmp280_compensate_temp(struct bmp280_data *data,
 static u32 bmp280_compensate_press(struct bmp280_data *data,
 				   s32 adc_press)
 {
-	s64 var1, var2, p;
 	struct bmp280_calib *calib = &data->calib.bmp280;
+	s64 var1, var2, p;
 
 	var1 = ((s64)data->t_fine) - 128000;
 	var2 = var1 * var1 * (s64)calib->P6;
@@ -335,9 +336,9 @@ static u32 bmp280_compensate_press(struct bmp280_data *data,
 static int bmp280_read_temp(struct bmp280_data *data,
 			    int *val)
 {
-	int ret;
-	__be32 tmp = 0;
 	s32 adc_temp, comp_temp;
+	__be32 tmp = 0;
+	int ret;
 
 	ret = regmap_bulk_read(data->regmap, BMP280_REG_TEMP_MSB, &tmp, 3);
 	if (ret < 0) {
@@ -368,10 +369,10 @@ static int bmp280_read_temp(struct bmp280_data *data,
 static int bmp280_read_press(struct bmp280_data *data,
 			     int *val, int *val2)
 {
-	int ret;
+	u32 comp_press;
 	__be32 tmp = 0;
 	s32 adc_press;
-	u32 comp_press;
+	int ret;
 
 	/* Read and compensate temperature so we get a reading of t_fine. */
 	ret = bmp280_read_temp(data, NULL);
@@ -400,10 +401,10 @@ static int bmp280_read_press(struct bmp280_data *data,
 
 static int bmp280_read_humid(struct bmp280_data *data, int *val, int *val2)
 {
+	u32 comp_humidity;
+	s32 adc_humidity;
 	__be16 tmp;
 	int ret;
-	s32 adc_humidity;
-	u32 comp_humidity;
 
 	/* Read and compensate temperature so we get a reading of t_fine. */
 	ret = bmp280_read_temp(data, NULL);
@@ -433,8 +434,8 @@ static int bmp280_read_raw(struct iio_dev *indio_dev,
 			   struct iio_chan_spec const *chan,
 			   int *val, int *val2, long mask)
 {
-	int ret;
 	struct bmp280_data *data = iio_priv(indio_dev);
+	int ret;
 
 	pm_runtime_get_sync(data->dev);
 	mutex_lock(&data->lock);
@@ -490,9 +491,9 @@ static int bmp280_read_raw(struct iio_dev *indio_dev,
 static int bmp280_write_oversampling_ratio_humid(struct bmp280_data *data,
 					       int val)
 {
-	int i;
 	const int *avail = data->chip_info->oversampling_humid_avail;
 	const int n = data->chip_info->num_oversampling_humid_avail;
+	int i;
 
 	for (i = 0; i < n; i++) {
 		if (avail[i] == val) {
@@ -507,9 +508,9 @@ static int bmp280_write_oversampling_ratio_humid(struct bmp280_data *data,
 static int bmp280_write_oversampling_ratio_temp(struct bmp280_data *data,
 					       int val)
 {
-	int i;
 	const int *avail = data->chip_info->oversampling_temp_avail;
 	const int n = data->chip_info->num_oversampling_temp_avail;
+	int i;
 
 	for (i = 0; i < n; i++) {
 		if (avail[i] == val) {
@@ -524,9 +525,9 @@ static int bmp280_write_oversampling_ratio_temp(struct bmp280_data *data,
 static int bmp280_write_oversampling_ratio_press(struct bmp280_data *data,
 					       int val)
 {
-	int i;
 	const int *avail = data->chip_info->oversampling_press_avail;
 	const int n = data->chip_info->num_oversampling_press_avail;
+	int i;
 
 	for (i = 0; i < n; i++) {
 		if (avail[i] == val) {
@@ -542,8 +543,8 @@ static int bmp280_write_raw(struct iio_dev *indio_dev,
 			    struct iio_chan_spec const *chan,
 			    int val, int val2, long mask)
 {
-	int ret = 0;
 	struct bmp280_data *data = iio_priv(indio_dev);
+	int ret = 0;
 
 	switch (mask) {
 	case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
@@ -610,9 +611,9 @@ static const struct iio_info bmp280_info = {
 
 static int bmp280_chip_config(struct bmp280_data *data)
 {
-	int ret;
 	u8 osrs = BMP280_OSRS_TEMP_X(data->oversampling_temp + 1) |
 		  BMP280_OSRS_PRESS_X(data->oversampling_press + 1);
+	int ret;
 
 	ret = regmap_write_bits(data->regmap, BMP280_REG_CTRL_MEAS,
 				 BMP280_OSRS_TEMP_MASK |
@@ -653,8 +654,8 @@ static const struct bmp280_chip_info bmp280_chip_info = {
 
 static int bme280_chip_config(struct bmp280_data *data)
 {
-	int ret;
 	u8 osrs = BMP280_OSRS_HUMIDITIY_X(data->oversampling_humid + 1);
+	int ret;
 
 	/*
 	 * Oversampling of humidity must be set before oversampling of
@@ -687,10 +688,10 @@ static const struct bmp280_chip_info bme280_chip_info = {
 
 static int bmp180_measure(struct bmp280_data *data, u8 ctrl_meas)
 {
-	int ret;
 	const int conversion_time_max[] = { 4500, 7500, 13500, 25500 };
 	unsigned int delay_us;
 	unsigned int ctrl;
+	int ret;
 
 	if (data->use_eoc)
 		reinit_completion(&data->done);
@@ -751,9 +752,9 @@ static int bmp180_read_adc_temp(struct bmp280_data *data, int *val)
 static int bmp180_read_calib(struct bmp280_data *data,
 			     struct bmp180_calib *calib)
 {
+	__be16 buf[BMP180_REG_CALIB_COUNT / 2];
 	int ret;
 	int i;
-	__be16 buf[BMP180_REG_CALIB_COUNT / 2];
 
 	ret = regmap_bulk_read(data->regmap, BMP180_REG_CALIB_START, buf,
 			       sizeof(buf));
@@ -793,8 +794,8 @@ static int bmp180_read_calib(struct bmp280_data *data,
  */
 static s32 bmp180_compensate_temp(struct bmp280_data *data, s32 adc_temp)
 {
-	s32 x1, x2;
 	struct bmp180_calib *calib = &data->calib.bmp180;
+	s32 x1, x2;
 
 	x1 = ((adc_temp - calib->AC6) * calib->AC5) >> 15;
 	x2 = (calib->MC << 11) / (x1 + calib->MD);
@@ -805,8 +806,8 @@ static s32 bmp180_compensate_temp(struct bmp280_data *data, s32 adc_temp)
 
 static int bmp180_read_temp(struct bmp280_data *data, int *val)
 {
-	int ret;
 	s32 adc_temp, comp_temp;
+	int ret;
 
 	ret = bmp180_read_adc_temp(data, &adc_temp);
 	if (ret)
@@ -828,9 +829,9 @@ static int bmp180_read_temp(struct bmp280_data *data, int *val)
 
 static int bmp180_read_adc_press(struct bmp280_data *data, int *val)
 {
-	int ret;
-	__be32 tmp = 0;
 	u8 oss = data->oversampling_press;
+	__be32 tmp = 0;
+	int ret;
 
 	ret = bmp180_measure(data, BMP180_MEAS_PRESS_X(oss));
 	if (ret)
@@ -852,11 +853,11 @@ static int bmp180_read_adc_press(struct bmp280_data *data, int *val)
  */
 static u32 bmp180_compensate_press(struct bmp280_data *data, s32 adc_press)
 {
+	struct bmp180_calib *calib = &data->calib.bmp180;
+	s32 oss = data->oversampling_press;
 	s32 x1, x2, x3, p;
 	s32 b3, b6;
 	u32 b4, b7;
-	s32 oss = data->oversampling_press;
-	struct bmp180_calib *calib = &data->calib.bmp180;
 
 	b6 = data->t_fine - 4000;
 	x1 = (calib->B2 * (b6 * b6 >> 12)) >> 11;
@@ -883,9 +884,9 @@ static u32 bmp180_compensate_press(struct bmp280_data *data, s32 adc_press)
 static int bmp180_read_press(struct bmp280_data *data,
 			     int *val, int *val2)
 {
-	int ret;
-	s32 adc_press;
 	u32 comp_press;
+	s32 adc_press;
+	int ret;
 
 	/* Read and compensate temperature so we get a reading of t_fine. */
 	ret = bmp180_read_temp(data, NULL);
@@ -990,11 +991,11 @@ int bmp280_common_probe(struct device *dev,
 			const char *name,
 			int irq)
 {
-	int ret;
 	struct iio_dev *indio_dev;
 	struct bmp280_data *data;
-	unsigned int chip_id;
 	struct gpio_desc *gpiod;
+	unsigned int chip_id;
+	int ret;
 
 	indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
 	if (!indio_dev)
Signature · 1 line
2.37.3
#2 lore raw

PATCH v6 2/9 iio: pressure: bmp280: use FIELD_GET, FIELD_PREP and GENMASK

In reply to Angel Iglesias

Cleaned and simplified register values construction and extraction converting to use FIELD_PREP and FIELD_GET macros.

Replaced hardcoded bit masks with GENMASK macro.

---
 drivers/iio/pressure/bmp280-core.c | 25 ++++++----
 drivers/iio/pressure/bmp280.h      | 78 ++++++++++++++++--------------
 2 files changed, 57 insertions(+), 46 deletions(-)
drivers/iio/pressure/bmp280-core.c +16 -9
index 42b29f30e9d1..0ba4ff999f33 100644
@@ -16,6 +16,8 @@
 
 #define pr_fmt(fmt) "bmp280: " fmt
 
+#include <linux/bitops.h>
+#include <linux/bitfield.h>
 #include <linux/device.h>
 #include <linux/module.h>
 #include <linux/regmap.h>
@@ -242,7 +244,7 @@ static int bmp280_read_calib(struct bmp280_data *data,
 		dev_err(dev, "failed to read H5 comp value\n");
 		return ret;
 	}
-	calib->H5 = sign_extend32(((le16_to_cpu(l16) >> 4) & 0xfff), 11);
+	calib->H5 = sign_extend32(FIELD_GET(BMP280_COMP_H5_MASK, le16_to_cpu(l16)), 11);
 
 	ret = regmap_read(data->regmap, BMP280_REG_COMP_H6, &tmp);
 	if (ret < 0) {
@@ -346,7 +348,7 @@ static int bmp280_read_temp(struct bmp280_data *data,
 		return ret;
 	}
 
-	adc_temp = be32_to_cpu(tmp) >> 12;
+	adc_temp = FIELD_GET(BMP280_MEAS_TRIM_MASK, be32_to_cpu(tmp));
 	if (adc_temp == BMP280_TEMP_SKIPPED) {
 		/* reading was skipped */
 		dev_err(data->dev, "reading temperature skipped\n");
@@ -385,7 +387,7 @@ static int bmp280_read_press(struct bmp280_data *data,
 		return ret;
 	}
 
-	adc_press = be32_to_cpu(tmp) >> 12;
+	adc_press = FIELD_GET(BMP280_MEAS_TRIM_MASK, be32_to_cpu(tmp));
 	if (adc_press == BMP280_PRESS_SKIPPED) {
 		/* reading was skipped */
 		dev_err(data->dev, "reading pressure skipped\n");
@@ -611,8 +613,8 @@ static const struct iio_info bmp280_info = {
 
 static int bmp280_chip_config(struct bmp280_data *data)
 {
-	u8 osrs = BMP280_OSRS_TEMP_X(data->oversampling_temp + 1) |
-		  BMP280_OSRS_PRESS_X(data->oversampling_press + 1);
+	u8 osrs = FIELD_PREP(BMP280_OSRS_TEMP_MASK, data->oversampling_temp + 1) |
+		  FIELD_PREP(BMP280_OSRS_PRESS_MASK, data->oversampling_press + 1);
 	int ret;
 
 	ret = regmap_write_bits(data->regmap, BMP280_REG_CTRL_MEAS,
@@ -654,7 +656,7 @@ static const struct bmp280_chip_info bmp280_chip_info = {
 
 static int bme280_chip_config(struct bmp280_data *data)
 {
-	u8 osrs = BMP280_OSRS_HUMIDITIY_X(data->oversampling_humid + 1);
+	u8 osrs = FIELD_PREP(BMP280_OSRS_HUMIDITY_MASK, data->oversampling_humid + 1);
 	int ret;
 
 	/*
@@ -711,7 +713,7 @@ static int bmp180_measure(struct bmp280_data *data, u8 ctrl_meas)
 		if (!ret)
 			dev_err(data->dev, "timeout waiting for completion\n");
 	} else {
-		if (ctrl_meas == BMP180_MEAS_TEMP)
+		if (FIELD_GET(BMP180_MEAS_CTRL_MASK, ctrl_meas) == BMP180_MEAS_TEMP)
 			delay_us = 4500;
 		else
 			delay_us =
@@ -736,7 +738,9 @@ static int bmp180_read_adc_temp(struct bmp280_data *data, int *val)
 	__be16 tmp;
 	int ret;
 
-	ret = bmp180_measure(data, BMP180_MEAS_TEMP);
+	ret = bmp180_measure(data,
+			     FIELD_PREP(BMP180_MEAS_CTRL_MASK, BMP180_MEAS_TEMP) |
+			     BMP180_MEAS_SCO);
 	if (ret)
 		return ret;
 
@@ -833,7 +837,10 @@ static int bmp180_read_adc_press(struct bmp280_data *data, int *val)
 	__be32 tmp = 0;
 	int ret;
 
-	ret = bmp180_measure(data, BMP180_MEAS_PRESS_X(oss));
+	ret = bmp180_measure(data,
+			     FIELD_PREP(BMP180_MEAS_CTRL_MASK, BMP180_MEAS_PRESS) |
+			     FIELD_PREP(BMP180_OSRS_PRESS_MASK, oss) |
+			     BMP180_MEAS_SCO);
 	if (ret)
 		return ret;
 
drivers/iio/pressure/bmp280.h +41 -37

104 lines not on this page · raw message

Signature · 1 line
2.37.3
maintainer
#3 lore raw

Re: [PATCH v6 2/9] iio: pressure: bmp280: use FIELD_GET, FIELD_PREP and GENMASK

Quoted 6 lines · On Tue, 13 Sep 2022 01:45:49 +0200 Angel Iglesias <[email protected]>…

Cleaned and simplified register values construction and extraction converting to use FIELD_PREP and FIELD_GET macros.

Replaced hardcoded bit masks with GENMASK macro.

Random thought whilst checking this..

I wonder how many users a FIELD_GET_SIGNED() would have with the assumption it returned a sign extended value...

Anyhow, I'm picking up these patches as I look through them (mainly because I'm waiting for a late flight and not sure how far I'll get!)

So applied up to here so far...

Jonathan

Quoted 208 lines
---
 drivers/iio/pressure/bmp280-core.c | 25 ++++++----
 drivers/iio/pressure/bmp280.h      | 78 ++++++++++++++++--------------
 2 files changed, 57 insertions(+), 46 deletions(-)
drivers/iio/pressure/bmp280-core.c +16 -9
index 42b29f30e9d1..0ba4ff999f33 100644
@@ -16,6 +16,8 @@
 
 #define pr_fmt(fmt) "bmp280: " fmt
 
+#include <linux/bitops.h>
+#include <linux/bitfield.h>
 #include <linux/device.h>
 #include <linux/module.h>
 #include <linux/regmap.h>
@@ -242,7 +244,7 @@ static int bmp280_read_calib(struct bmp280_data *data,
 		dev_err(dev, "failed to read H5 comp value\n");
 		return ret;
 	}
-	calib->H5 = sign_extend32(((le16_to_cpu(l16) >> 4) & 0xfff), 11);
+	calib->H5 = sign_extend32(FIELD_GET(BMP280_COMP_H5_MASK, le16_to_cpu(l16)), 11);
 
 	ret = regmap_read(data->regmap, BMP280_REG_COMP_H6, &tmp);
 	if (ret < 0) {
@@ -346,7 +348,7 @@ static int bmp280_read_temp(struct bmp280_data *data,
 		return ret;
 	}
 
-	adc_temp = be32_to_cpu(tmp) >> 12;
+	adc_temp = FIELD_GET(BMP280_MEAS_TRIM_MASK, be32_to_cpu(tmp));
 	if (adc_temp == BMP280_TEMP_SKIPPED) {
 		/* reading was skipped */
 		dev_err(data->dev, "reading temperature skipped\n");
@@ -385,7 +387,7 @@ static int bmp280_read_press(struct bmp280_data *data,
 		return ret;
 	}
 
-	adc_press = be32_to_cpu(tmp) >> 12;
+	adc_press = FIELD_GET(BMP280_MEAS_TRIM_MASK, be32_to_cpu(tmp));
 	if (adc_press == BMP280_PRESS_SKIPPED) {
 		/* reading was skipped */
 		dev_err(data->dev, "reading pressure skipped\n");
@@ -611,8 +613,8 @@ static const struct iio_info bmp280_info = {
 
 static int bmp280_chip_config(struct bmp280_data *data)
 {
-	u8 osrs = BMP280_OSRS_TEMP_X(data->oversampling_temp + 1) |
-		  BMP280_OSRS_PRESS_X(data->oversampling_press + 1);
+	u8 osrs = FIELD_PREP(BMP280_OSRS_TEMP_MASK, data->oversampling_temp + 1) |
+		  FIELD_PREP(BMP280_OSRS_PRESS_MASK, data->oversampling_press + 1);
 	int ret;
 
 	ret = regmap_write_bits(data->regmap, BMP280_REG_CTRL_MEAS,
@@ -654,7 +656,7 @@ static const struct bmp280_chip_info bmp280_chip_info = {
 
 static int bme280_chip_config(struct bmp280_data *data)
 {
-	u8 osrs = BMP280_OSRS_HUMIDITIY_X(data->oversampling_humid + 1);
+	u8 osrs = FIELD_PREP(BMP280_OSRS_HUMIDITY_MASK, data->oversampling_humid + 1);
 	int ret;
 
 	/*
@@ -711,7 +713,7 @@ static int bmp180_measure(struct bmp280_data *data, u8 ctrl_meas)
 		if (!ret)
 			dev_err(data->dev, "timeout waiting for completion\n");
 	} else {
-		if (ctrl_meas == BMP180_MEAS_TEMP)
+		if (FIELD_GET(BMP180_MEAS_CTRL_MASK, ctrl_meas) == BMP180_MEAS_TEMP)
 			delay_us = 4500;
 		else
 			delay_us =
@@ -736,7 +738,9 @@ static int bmp180_read_adc_temp(struct bmp280_data *data, int *val)
 	__be16 tmp;
 	int ret;
 
-	ret = bmp180_measure(data, BMP180_MEAS_TEMP);
+	ret = bmp180_measure(data,
+			     FIELD_PREP(BMP180_MEAS_CTRL_MASK, BMP180_MEAS_TEMP) |
+			     BMP180_MEAS_SCO);
 	if (ret)
 		return ret;
 
@@ -833,7 +837,10 @@ static int bmp180_read_adc_press(struct bmp280_data *data, int *val)
 	__be32 tmp = 0;
 	int ret;
 
-	ret = bmp180_measure(data, BMP180_MEAS_PRESS_X(oss));
+	ret = bmp180_measure(data,
+			     FIELD_PREP(BMP180_MEAS_CTRL_MASK, BMP180_MEAS_PRESS) |
+			     FIELD_PREP(BMP180_OSRS_PRESS_MASK, oss) |
+			     BMP180_MEAS_SCO);
 	if (ret)
 		return ret;
 
drivers/iio/pressure/bmp280.h +41 -37
index 57ba0e85db91..4a501836d27a 100644
@@ -13,6 +13,9 @@
 #define BMP280_REG_PRESS_LSB		0xF8
 #define BMP280_REG_PRESS_MSB		0xF7
 
+/* Helper mask to truncate excess 12 bits on pressure and temp readings */
+#define BMP280_MEAS_TRIM_MASK		GENMASK(31, 12)
+
 #define BMP280_REG_CONFIG		0xF5
 #define BMP280_REG_CTRL_MEAS		0xF4
 #define BMP280_REG_STATUS		0xF3
@@ -32,44 +35,43 @@
 #define BMP280_REG_COMP_PRESS_START	0x8E
 #define BMP280_COMP_PRESS_REG_COUNT	18
 
-#define BMP280_FILTER_MASK		(BIT(4) | BIT(3) | BIT(2))
+#define BMP280_COMP_H5_MASK		GENMASK(15, 4)
+
+#define BMP280_FILTER_MASK		GENMASK(4, 2)
 #define BMP280_FILTER_OFF		0
-#define BMP280_FILTER_2X		BIT(2)
-#define BMP280_FILTER_4X		BIT(3)
-#define BMP280_FILTER_8X		(BIT(3) | BIT(2))
-#define BMP280_FILTER_16X		BIT(4)
+#define BMP280_FILTER_2X		1
+#define BMP280_FILTER_4X		2
+#define BMP280_FILTER_8X		3
+#define BMP280_FILTER_16X		4
 
-#define BMP280_OSRS_HUMIDITY_MASK	(BIT(2) | BIT(1) | BIT(0))
-#define BMP280_OSRS_HUMIDITIY_X(osrs_h)	((osrs_h) << 0)
+#define BMP280_OSRS_HUMIDITY_MASK	GENMASK(2, 0)
 #define BMP280_OSRS_HUMIDITY_SKIP	0
-#define BMP280_OSRS_HUMIDITY_1X		BMP280_OSRS_HUMIDITIY_X(1)
-#define BMP280_OSRS_HUMIDITY_2X		BMP280_OSRS_HUMIDITIY_X(2)
-#define BMP280_OSRS_HUMIDITY_4X		BMP280_OSRS_HUMIDITIY_X(3)
-#define BMP280_OSRS_HUMIDITY_8X		BMP280_OSRS_HUMIDITIY_X(4)
-#define BMP280_OSRS_HUMIDITY_16X	BMP280_OSRS_HUMIDITIY_X(5)
+#define BMP280_OSRS_HUMIDITY_1X		1
+#define BMP280_OSRS_HUMIDITY_2X		2
+#define BMP280_OSRS_HUMIDITY_4X		3
+#define BMP280_OSRS_HUMIDITY_8X		4
+#define BMP280_OSRS_HUMIDITY_16X	5
 
-#define BMP280_OSRS_TEMP_MASK		(BIT(7) | BIT(6) | BIT(5))
+#define BMP280_OSRS_TEMP_MASK		GENMASK(7, 5)
 #define BMP280_OSRS_TEMP_SKIP		0
-#define BMP280_OSRS_TEMP_X(osrs_t)	((osrs_t) << 5)
-#define BMP280_OSRS_TEMP_1X		BMP280_OSRS_TEMP_X(1)
-#define BMP280_OSRS_TEMP_2X		BMP280_OSRS_TEMP_X(2)
-#define BMP280_OSRS_TEMP_4X		BMP280_OSRS_TEMP_X(3)
-#define BMP280_OSRS_TEMP_8X		BMP280_OSRS_TEMP_X(4)
-#define BMP280_OSRS_TEMP_16X		BMP280_OSRS_TEMP_X(5)
-
-#define BMP280_OSRS_PRESS_MASK		(BIT(4) | BIT(3) | BIT(2))
+#define BMP280_OSRS_TEMP_1X		1
+#define BMP280_OSRS_TEMP_2X		2
+#define BMP280_OSRS_TEMP_4X		3
+#define BMP280_OSRS_TEMP_8X		4
+#define BMP280_OSRS_TEMP_16X		5
+
+#define BMP280_OSRS_PRESS_MASK		GENMASK(4, 2)
 #define BMP280_OSRS_PRESS_SKIP		0
-#define BMP280_OSRS_PRESS_X(osrs_p)	((osrs_p) << 2)
-#define BMP280_OSRS_PRESS_1X		BMP280_OSRS_PRESS_X(1)
-#define BMP280_OSRS_PRESS_2X		BMP280_OSRS_PRESS_X(2)
-#define BMP280_OSRS_PRESS_4X		BMP280_OSRS_PRESS_X(3)
-#define BMP280_OSRS_PRESS_8X		BMP280_OSRS_PRESS_X(4)
-#define BMP280_OSRS_PRESS_16X		BMP280_OSRS_PRESS_X(5)
-
-#define BMP280_MODE_MASK		(BIT(1) | BIT(0))
+#define BMP280_OSRS_PRESS_1X		1
+#define BMP280_OSRS_PRESS_2X		2
+#define BMP280_OSRS_PRESS_4X		3
+#define BMP280_OSRS_PRESS_8X		4
+#define BMP280_OSRS_PRESS_16X		5
+
+#define BMP280_MODE_MASK		GENMASK(1, 0)
 #define BMP280_MODE_SLEEP		0
-#define BMP280_MODE_FORCED		BIT(0)
-#define BMP280_MODE_NORMAL		(BIT(1) | BIT(0))
+#define BMP280_MODE_FORCED		1
+#define BMP280_MODE_NORMAL		3
 
 /* BMP180 specific registers */
 #define BMP180_REG_OUT_XLSB		0xF8
@@ -79,13 +81,15 @@
 #define BMP180_REG_CALIB_START		0xAA
 #define BMP180_REG_CALIB_COUNT		22
 
+#define BMP180_MEAS_CTRL_MASK		GENMASK(4, 0)
+#define BMP180_MEAS_TEMP		0x0E
+#define BMP180_MEAS_PRESS		0x14
 #define BMP180_MEAS_SCO			BIT(5)
-#define BMP180_MEAS_TEMP		(0x0E | BMP180_MEAS_SCO)
-#define BMP180_MEAS_PRESS_X(oss)	((oss) << 6 | 0x14 | BMP180_MEAS_SCO)
-#define BMP180_MEAS_PRESS_1X		BMP180_MEAS_PRESS_X(0)
-#define BMP180_MEAS_PRESS_2X		BMP180_MEAS_PRESS_X(1)
-#define BMP180_MEAS_PRESS_4X		BMP180_MEAS_PRESS_X(2)
-#define BMP180_MEAS_PRESS_8X		BMP180_MEAS_PRESS_X(3)
+#define BMP180_OSRS_PRESS_MASK		GENMASK(7, 6)
+#define BMP180_MEAS_PRESS_1X		0
+#define BMP180_MEAS_PRESS_2X		1
+#define BMP180_MEAS_PRESS_4X		2
+#define BMP180_MEAS_PRESS_8X		3
 
 /* BMP180 and BMP280 common registers */
 #define BMP280_REG_CTRL_MEAS		0xF4
#4 lore raw

PATCH v6 3/9 iio: pressure: bmp280: Simplify bmp280 calibration data reading

In reply to Angel Iglesias

On bmp280 and bme280, the temperature and pressure calibration parameters are available on a contiguous memory region. Considering this arrangement, simplified the calibration reading function by using only one buffer to read in batch temperature and pressure registers.

---
 drivers/iio/pressure/bmp280-core.c | 58 ++++++++++++------------------
 drivers/iio/pressure/bmp280.h      |  3 ++
 2 files changed, 26 insertions(+), 35 deletions(-)
drivers/iio/pressure/bmp280-core.c +23 -35
index 0ba4ff999f33..4793bcd9f0b3 100644
@@ -128,8 +128,7 @@ struct bmp280_chip_info {
  * These enums are used for indexing into the array of compensation
  * parameters for BMP280.
  */
-enum { T1, T2, T3 };
-enum { P1, P2, P3, P4, P5, P6, P7, P8, P9 };
+enum { T1, T2, T3, P1, P2, P3, P4, P5, P6, P7, P8, P9 };
 
 static const struct iio_chan_spec bmp280_channels[] = {
 	{
@@ -153,8 +152,7 @@ static int bmp280_read_calib(struct bmp280_data *data,
 			     struct bmp280_calib *calib,
 			     unsigned int chip)
 {
-	__le16 p_buf[BMP280_COMP_PRESS_REG_COUNT / 2];
-	__le16 t_buf[BMP280_COMP_TEMP_REG_COUNT / 2];
+	__le16 c_buf[BMP280_CONTIGUOUS_CALIB_REGS / 2];
 	struct device *dev = data->dev;
 	unsigned int tmp;
 	__le16 l16;
@@ -162,43 +160,33 @@ static int bmp280_read_calib(struct bmp280_data *data,
 	int ret;
 
 
-	/* Read temperature calibration values. */
+	/* Read temperature and pressure calibration values. */
 	ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_TEMP_START,
-			       t_buf, BMP280_COMP_TEMP_REG_COUNT);
+			       c_buf, sizeof(c_buf));
 	if (ret < 0) {
 		dev_err(data->dev,
-			"failed to read temperature calibration parameters\n");
+			"failed to read temperature and pressure calibration parameters\n");
 		return ret;
 	}
 
-	/* Toss the temperature calibration data into the entropy pool */
-	add_device_randomness(t_buf, sizeof(t_buf));
-
-	calib->T1 = le16_to_cpu(t_buf[T1]);
-	calib->T2 = le16_to_cpu(t_buf[T2]);
-	calib->T3 = le16_to_cpu(t_buf[T3]);
-
-	/* Read pressure calibration values. */
-	ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_PRESS_START,
-			       p_buf, BMP280_COMP_PRESS_REG_COUNT);
-	if (ret < 0) {
-		dev_err(data->dev,
-			"failed to read pressure calibration parameters\n");
-		return ret;
-	}
-
-	/* Toss the pressure calibration data into the entropy pool */
-	add_device_randomness(p_buf, sizeof(p_buf));
-
-	calib->P1 = le16_to_cpu(p_buf[P1]);
-	calib->P2 = le16_to_cpu(p_buf[P2]);
-	calib->P3 = le16_to_cpu(p_buf[P3]);
-	calib->P4 = le16_to_cpu(p_buf[P4]);
-	calib->P5 = le16_to_cpu(p_buf[P5]);
-	calib->P6 = le16_to_cpu(p_buf[P6]);
-	calib->P7 = le16_to_cpu(p_buf[P7]);
-	calib->P8 = le16_to_cpu(p_buf[P8]);
-	calib->P9 = le16_to_cpu(p_buf[P9]);
+	/* Toss the temperature and pressure calibration data into the entropy pool */
+	add_device_randomness(c_buf, sizeof(c_buf));
+
+	/* Parse temperature calibration values. */
+	calib->T1 = le16_to_cpu(c_buf[T1]);
+	calib->T2 = le16_to_cpu(c_buf[T2]);
+	calib->T3 = le16_to_cpu(c_buf[T3]);
+
+	/* Parse pressure calibration values. */
+	calib->P1 = le16_to_cpu(c_buf[P1]);
+	calib->P2 = le16_to_cpu(c_buf[P2]);
+	calib->P3 = le16_to_cpu(c_buf[P3]);
+	calib->P4 = le16_to_cpu(c_buf[P4]);
+	calib->P5 = le16_to_cpu(c_buf[P5]);
+	calib->P6 = le16_to_cpu(c_buf[P6]);
+	calib->P7 = le16_to_cpu(c_buf[P7]);
+	calib->P8 = le16_to_cpu(c_buf[P8]);
+	calib->P9 = le16_to_cpu(c_buf[P9]);
 
 	/*
 	 * Read humidity calibration values.
drivers/iio/pressure/bmp280.h +3 -0
index 4a501836d27a..03a539223417 100644
@@ -37,6 +37,9 @@
 
 #define BMP280_COMP_H5_MASK		GENMASK(15, 4)
 
+#define BMP280_CONTIGUOUS_CALIB_REGS	(BMP280_COMP_TEMP_REG_COUNT + \
+					 BMP280_COMP_PRESS_REG_COUNT)
+
 #define BMP280_FILTER_MASK		GENMASK(4, 2)
 #define BMP280_FILTER_OFF		0
 #define BMP280_FILTER_2X		1
Signature · 1 line
2.37.3
maintainer Applied
#5 lore raw

Re: [PATCH v6 3/9] iio: pressure: bmp280: Simplify bmp280 calibration data reading

Quoted 6 lines · On Tue, 13 Sep 2022 01:46:42 +0200 Angel Iglesias <[email protected]>…

On bmp280 and bme280, the temperature and pressure calibration parameters are available on a contiguous memory region. Considering this arrangement, simplified the calibration reading function by using only one buffer to read in batch temperature and pressure registers.

Applied. Apparently we have a plane, so I'll stop here for now...

Jonathan

Quoted 108 lines
---
 drivers/iio/pressure/bmp280-core.c | 58 ++++++++++++------------------
 drivers/iio/pressure/bmp280.h      |  3 ++
 2 files changed, 26 insertions(+), 35 deletions(-)
drivers/iio/pressure/bmp280-core.c +23 -35
index 0ba4ff999f33..4793bcd9f0b3 100644
@@ -128,8 +128,7 @@ struct bmp280_chip_info {
  * These enums are used for indexing into the array of compensation
  * parameters for BMP280.
  */
-enum { T1, T2, T3 };
-enum { P1, P2, P3, P4, P5, P6, P7, P8, P9 };
+enum { T1, T2, T3, P1, P2, P3, P4, P5, P6, P7, P8, P9 };
 
 static const struct iio_chan_spec bmp280_channels[] = {
 	{
@@ -153,8 +152,7 @@ static int bmp280_read_calib(struct bmp280_data *data,
 			     struct bmp280_calib *calib,
 			     unsigned int chip)
 {
-	__le16 p_buf[BMP280_COMP_PRESS_REG_COUNT / 2];
-	__le16 t_buf[BMP280_COMP_TEMP_REG_COUNT / 2];
+	__le16 c_buf[BMP280_CONTIGUOUS_CALIB_REGS / 2];
 	struct device *dev = data->dev;
 	unsigned int tmp;
 	__le16 l16;
@@ -162,43 +160,33 @@ static int bmp280_read_calib(struct bmp280_data *data,
 	int ret;
 
 
-	/* Read temperature calibration values. */
+	/* Read temperature and pressure calibration values. */
 	ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_TEMP_START,
-			       t_buf, BMP280_COMP_TEMP_REG_COUNT);
+			       c_buf, sizeof(c_buf));
 	if (ret < 0) {
 		dev_err(data->dev,
-			"failed to read temperature calibration parameters\n");
+			"failed to read temperature and pressure calibration parameters\n");
 		return ret;
 	}
 
-	/* Toss the temperature calibration data into the entropy pool */
-	add_device_randomness(t_buf, sizeof(t_buf));
-
-	calib->T1 = le16_to_cpu(t_buf[T1]);
-	calib->T2 = le16_to_cpu(t_buf[T2]);
-	calib->T3 = le16_to_cpu(t_buf[T3]);
-
-	/* Read pressure calibration values. */
-	ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_PRESS_START,
-			       p_buf, BMP280_COMP_PRESS_REG_COUNT);
-	if (ret < 0) {
-		dev_err(data->dev,
-			"failed to read pressure calibration parameters\n");
-		return ret;
-	}
-
-	/* Toss the pressure calibration data into the entropy pool */
-	add_device_randomness(p_buf, sizeof(p_buf));
-
-	calib->P1 = le16_to_cpu(p_buf[P1]);
-	calib->P2 = le16_to_cpu(p_buf[P2]);
-	calib->P3 = le16_to_cpu(p_buf[P3]);
-	calib->P4 = le16_to_cpu(p_buf[P4]);
-	calib->P5 = le16_to_cpu(p_buf[P5]);
-	calib->P6 = le16_to_cpu(p_buf[P6]);
-	calib->P7 = le16_to_cpu(p_buf[P7]);
-	calib->P8 = le16_to_cpu(p_buf[P8]);
-	calib->P9 = le16_to_cpu(p_buf[P9]);
+	/* Toss the temperature and pressure calibration data into the entropy pool */
+	add_device_randomness(c_buf, sizeof(c_buf));
+
+	/* Parse temperature calibration values. */
+	calib->T1 = le16_to_cpu(c_buf[T1]);
+	calib->T2 = le16_to_cpu(c_buf[T2]);
+	calib->T3 = le16_to_cpu(c_buf[T3]);
+
+	/* Parse pressure calibration values. */
+	calib->P1 = le16_to_cpu(c_buf[P1]);
+	calib->P2 = le16_to_cpu(c_buf[P2]);
+	calib->P3 = le16_to_cpu(c_buf[P3]);
+	calib->P4 = le16_to_cpu(c_buf[P4]);
+	calib->P5 = le16_to_cpu(c_buf[P5]);
+	calib->P6 = le16_to_cpu(c_buf[P6]);
+	calib->P7 = le16_to_cpu(c_buf[P7]);
+	calib->P8 = le16_to_cpu(c_buf[P8]);
+	calib->P9 = le16_to_cpu(c_buf[P9]);
 
 	/*
 	 * Read humidity calibration values.
drivers/iio/pressure/bmp280.h +3 -0
index 4a501836d27a..03a539223417 100644
@@ -37,6 +37,9 @@
 
 #define BMP280_COMP_H5_MASK		GENMASK(15, 4)
 
+#define BMP280_CONTIGUOUS_CALIB_REGS	(BMP280_COMP_TEMP_REG_COUNT + \
+					 BMP280_COMP_PRESS_REG_COUNT)
+
 #define BMP280_FILTER_MASK		GENMASK(4, 2)
 #define BMP280_FILTER_OFF		0
 #define BMP280_FILTER_2X		1
#6 lore raw

PATCH v6 4/9 iio: pressure: bmp280: simplify driver initialization logic

In reply to Angel Iglesias

Simplified common initialization logic of different sensor types unifying calibration and initial configuration recovery.

Default config param values of each sensor type are stored inside chip_info structure and used to initialize sensor data struct instance.

The helper functions for read each sensor type calibration are converted to a callback available on the chip_info struct.

Separated bme280 specific calibration code from bmp280 function. Dropped the additional chip_id argument in bmp280 code as is not longer required. Now both bmp280/bme280 calibration function use same signature as bmp180.

---
 drivers/iio/pressure/bmp280-core.c | 126 +++++++++++++++++++----------
 1 file changed, 83 insertions(+), 43 deletions(-)
drivers/iio/pressure/bmp280-core.c +83 -43
index 4793bcd9f0b3..203623d32032 100644
@@ -109,19 +109,28 @@ struct bmp280_data {
 };
 
 struct bmp280_chip_info {
+	unsigned int id_reg;
+
+	int num_channels;
+	unsigned int start_up_time;
+
 	const int *oversampling_temp_avail;
 	int num_oversampling_temp_avail;
+	int oversampling_temp_default;
 
 	const int *oversampling_press_avail;
 	int num_oversampling_press_avail;
+	int oversampling_press_default;
 
 	const int *oversampling_humid_avail;
 	int num_oversampling_humid_avail;
+	int oversampling_humid_default;
 
 	int (*chip_config)(struct bmp280_data *);
 	int (*read_temp)(struct bmp280_data *, int *);
 	int (*read_press)(struct bmp280_data *, int *, int *);
 	int (*read_humid)(struct bmp280_data *, int *, int *);
+	int (*read_calib)(struct bmp280_data *);
 };
 
 /*
@@ -148,15 +157,10 @@ static const struct iio_chan_spec bmp280_channels[] = {
 	},
 };
 
-static int bmp280_read_calib(struct bmp280_data *data,
-			     struct bmp280_calib *calib,
-			     unsigned int chip)
+static int bmp280_read_calib(struct bmp280_data *data)
 {
+	struct bmp280_calib *calib = &data->calib.bmp280;
 	__le16 c_buf[BMP280_CONTIGUOUS_CALIB_REGS / 2];
-	struct device *dev = data->dev;
-	unsigned int tmp;
-	__le16 l16;
-	__be16 b16;
 	int ret;
 
 
@@ -188,6 +192,25 @@ static int bmp280_read_calib(struct bmp280_data *data,
 	calib->P8 = le16_to_cpu(c_buf[P8]);
 	calib->P9 = le16_to_cpu(c_buf[P9]);
 
+	return 0;
+}
+
+static int bme280_read_calib(struct bmp280_data *data)
+{
+	struct bmp280_calib *calib = &data->calib.bmp280;
+	struct device *dev = data->dev;
+	unsigned int tmp;
+	__le16 l16;
+	__be16 b16;
+	int ret;
+
+	/* Load shared calibration params with bmp280 first */
+	ret = bmp280_read_calib(data);
+	if  (ret < 0) {
+		dev_err(dev, "failed to read common bmp280 calibration parameters\n");
+		return ret;
+	}
+
 	/*
 	 * Read humidity calibration values.
 	 * Due to some odd register addressing we cannot just
@@ -195,8 +218,6 @@ static int bmp280_read_calib(struct bmp280_data *data,
 	 * value separately and sometimes do some bit shifting...
 	 * Humidity data is only available on BME280.
 	 */
-	if (chip != BME280_CHIP_ID)
-		return 0;
 
 	ret = regmap_read(data->regmap, BMP280_REG_COMP_H1, &tmp);
 	if (ret < 0) {
@@ -631,15 +652,32 @@ static int bmp280_chip_config(struct bmp280_data *data)
 static const int bmp280_oversampling_avail[] = { 1, 2, 4, 8, 16 };
 
 static const struct bmp280_chip_info bmp280_chip_info = {
+	.id_reg = BMP280_REG_ID,
+	.start_up_time = 2000,
+	.num_channels = 2,
+
 	.oversampling_temp_avail = bmp280_oversampling_avail,
 	.num_oversampling_temp_avail = ARRAY_SIZE(bmp280_oversampling_avail),
+	/*
+	 * Oversampling config values on BMx280 have one additional setting
+	 * that other generations of the family don't:
+	 * The value 0 means the measurement is bypassed instead of
+	 * oversampling set to x1.
+	 *
+	 * To account for this difference, and preserve the same common
+	 * config logic, this is handled later on chip_config callback
+	 * incrementing one unit the oversampling setting.
+	 */
+	.oversampling_temp_default = BMP280_OSRS_TEMP_2X - 1,
 
 	.oversampling_press_avail = bmp280_oversampling_avail,
 	.num_oversampling_press_avail = ARRAY_SIZE(bmp280_oversampling_avail),
+	.oversampling_press_default = BMP280_OSRS_PRESS_16X - 1,
 
 	.chip_config = bmp280_chip_config,
 	.read_temp = bmp280_read_temp,
 	.read_press = bmp280_read_press,
+	.read_calib = bmp280_read_calib,
 };
 
 static int bme280_chip_config(struct bmp280_data *data)
@@ -661,19 +699,27 @@ static int bme280_chip_config(struct bmp280_data *data)
 }
 
 static const struct bmp280_chip_info bme280_chip_info = {
+	.id_reg = BMP280_REG_ID,
+	.start_up_time = 2000,
+	.num_channels = 3,
+
 	.oversampling_temp_avail = bmp280_oversampling_avail,
 	.num_oversampling_temp_avail = ARRAY_SIZE(bmp280_oversampling_avail),
+	.oversampling_temp_default = BMP280_OSRS_TEMP_2X - 1,
 
 	.oversampling_press_avail = bmp280_oversampling_avail,
 	.num_oversampling_press_avail = ARRAY_SIZE(bmp280_oversampling_avail),
+	.oversampling_press_default = BMP280_OSRS_PRESS_16X - 1,
 
 	.oversampling_humid_avail = bmp280_oversampling_avail,
 	.num_oversampling_humid_avail = ARRAY_SIZE(bmp280_oversampling_avail),
+	.oversampling_humid_default = BMP280_OSRS_HUMIDITY_16X - 1,
 
 	.chip_config = bme280_chip_config,
 	.read_temp = bmp280_read_temp,
 	.read_press = bmp280_read_press,
 	.read_humid = bmp280_read_humid,
+	.read_calib = bme280_read_calib,
 };
 
 static int bmp180_measure(struct bmp280_data *data, u8 ctrl_meas)
@@ -741,9 +787,9 @@ static int bmp180_read_adc_temp(struct bmp280_data *data, int *val)
 	return 0;
 }
 
-static int bmp180_read_calib(struct bmp280_data *data,
-			     struct bmp180_calib *calib)
+static int bmp180_read_calib(struct bmp280_data *data)
 {
+	struct bmp180_calib *calib = &data->calib.bmp180;
 	__be16 buf[BMP180_REG_CALIB_COUNT / 2];
 	int ret;
 	int i;
@@ -909,17 +955,24 @@ static const int bmp180_oversampling_temp_avail[] = { 1 };
 static const int bmp180_oversampling_press_avail[] = { 1, 2, 4, 8 };
 
 static const struct bmp280_chip_info bmp180_chip_info = {
+	.id_reg = BMP280_REG_ID,
+	.start_up_time = 2000,
+	.num_channels = 2,
+
 	.oversampling_temp_avail = bmp180_oversampling_temp_avail,
 	.num_oversampling_temp_avail =
 		ARRAY_SIZE(bmp180_oversampling_temp_avail),
+	.oversampling_temp_default = 0,
 
 	.oversampling_press_avail = bmp180_oversampling_press_avail,
 	.num_oversampling_press_avail =
 		ARRAY_SIZE(bmp180_oversampling_press_avail),
+	.oversampling_press_default = BMP180_MEAS_PRESS_8X,
 
 	.chip_config = bmp180_chip_config,
 	.read_temp = bmp180_read_temp,
 	.read_press = bmp180_read_press,
+	.read_calib = bmp180_read_calib,
 };
 
 static irqreturn_t bmp085_eoc_irq(int irq, void *d)
@@ -986,6 +1039,7 @@ int bmp280_common_probe(struct device *dev,
 			const char *name,
 			int irq)
 {
+	const struct bmp280_chip_info *chip_info;
 	struct iio_dev *indio_dev;
 	struct bmp280_data *data;
 	struct gpio_desc *gpiod;
@@ -1007,30 +1061,25 @@ int bmp280_common_probe(struct device *dev,
 
 	switch (chip) {
 	case BMP180_CHIP_ID:
-		indio_dev->num_channels = 2;
-		data->chip_info = &bmp180_chip_info;
-		data->oversampling_press = ilog2(8);
-		data->oversampling_temp = ilog2(1);
-		data->start_up_time = 10000;
+		chip_info = &bmp180_chip_info;
 		break;
 	case BMP280_CHIP_ID:
-		indio_dev->num_channels = 2;
-		data->chip_info = &bmp280_chip_info;
-		data->oversampling_press = ilog2(16);
-		data->oversampling_temp = ilog2(2);
-		data->start_up_time = 2000;
+		chip_info = &bmp280_chip_info;
 		break;
 	case BME280_CHIP_ID:
-		indio_dev->num_channels = 3;
-		data->chip_info = &bme280_chip_info;
-		data->oversampling_press = ilog2(16);
-		data->oversampling_humid = ilog2(16);
-		data->oversampling_temp = ilog2(2);
-		data->start_up_time = 2000;
+		chip_info = &bme280_chip_info;
 		break;
 	default:
 		return -EINVAL;
 	}
+	data->chip_info = chip_info;
+
+	/* Apply initial values from chip info structure */
+	indio_dev->num_channels = chip_info->num_channels;
+	data->oversampling_press = chip_info->oversampling_press_default;
+	data->oversampling_humid = chip_info->oversampling_humid_default;
+	data->oversampling_temp = chip_info->oversampling_temp_default;
+	data->start_up_time = chip_info->start_up_time;
 
 	/* Bring up regulators */
 	regulator_bulk_set_supply_names(data->supplies,
@@ -1067,7 +1116,8 @@ int bmp280_common_probe(struct device *dev,
 	}
 
 	data->regmap = regmap;
-	ret = regmap_read(regmap, BMP280_REG_ID, &chip_id);
+
+	ret = regmap_read(regmap, data->chip_info->id_reg, &chip_id);
 	if (ret < 0)
 		return ret;
 	if (chip_id != chip) {
@@ -1087,21 +1137,11 @@ int bmp280_common_probe(struct device *dev,
 	 * non-volatile memory during production". Let's read them out at probe
 	 * time once. They will not change.
 	 */
-	if (chip_id  == BMP180_CHIP_ID) {
-		ret = bmp180_read_calib(data, &data->calib.bmp180);
-		if (ret < 0) {
-			dev_err(data->dev,
-				"failed to read calibration coefficients\n");
-			return ret;
-		}
-	} else if (chip_id == BMP280_CHIP_ID || chip_id == BME280_CHIP_ID) {
-		ret = bmp280_read_calib(data, &data->calib.bmp280, chip_id);
-		if (ret < 0) {
-			dev_err(data->dev,
-				"failed to read calibration coefficients\n");
-			return ret;
-		}
-	}
+
+	ret = data->chip_info->read_calib(data);
+	if (ret < 0)
+		return dev_err_probe(data->dev, ret,
+				     "failed to read calibration coefficients\n");
 
 	/*
 	 * Attempt to grab an optional EOC IRQ - only the BMP085 has this
Signature · 1 line
2.37.3
maintainer Applied
#7 lore raw

Re: [PATCH v6 4/9] iio: pressure: bmp280: simplify driver initialization logic

Quoted 9 lines · On Tue, 13 Sep 2022 01:47:31 +0200 Angel Iglesias <[email protected]>…

Simplified common initialization logic of different sensor types unifying calibration and initial configuration recovery.

Default config param values of each sensor type are stored inside chip_info structure and used to initialize sensor data struct instance.

The helper functions for read each sensor type calibration are converted to a callback available on the chip_info struct.

Quoted 6 lines

Separated bme280 specific calibration code from bmp280 function. Dropped the additional chip_id argument in bmp280 code as is not longer required. Now both bmp280/bme280 calibration function use same signature as bmp180.

Applied

Quoted 275 lines
---
 drivers/iio/pressure/bmp280-core.c | 126 +++++++++++++++++++----------
 1 file changed, 83 insertions(+), 43 deletions(-)
drivers/iio/pressure/bmp280-core.c +83 -43
index 4793bcd9f0b3..203623d32032 100644
@@ -109,19 +109,28 @@ struct bmp280_data {
 };
 
 struct bmp280_chip_info {
+	unsigned int id_reg;
+
+	int num_channels;
+	unsigned int start_up_time;
+
 	const int *oversampling_temp_avail;
 	int num_oversampling_temp_avail;
+	int oversampling_temp_default;
 
 	const int *oversampling_press_avail;
 	int num_oversampling_press_avail;
+	int oversampling_press_default;
 
 	const int *oversampling_humid_avail;
 	int num_oversampling_humid_avail;
+	int oversampling_humid_default;
 
 	int (*chip_config)(struct bmp280_data *);
 	int (*read_temp)(struct bmp280_data *, int *);
 	int (*read_press)(struct bmp280_data *, int *, int *);
 	int (*read_humid)(struct bmp280_data *, int *, int *);
+	int (*read_calib)(struct bmp280_data *);
 };
 
 /*
@@ -148,15 +157,10 @@ static const struct iio_chan_spec bmp280_channels[] = {
 	},
 };
 
-static int bmp280_read_calib(struct bmp280_data *data,
-			     struct bmp280_calib *calib,
-			     unsigned int chip)
+static int bmp280_read_calib(struct bmp280_data *data)
 {
+	struct bmp280_calib *calib = &data->calib.bmp280;
 	__le16 c_buf[BMP280_CONTIGUOUS_CALIB_REGS / 2];
-	struct device *dev = data->dev;
-	unsigned int tmp;
-	__le16 l16;
-	__be16 b16;
 	int ret;
 
 
@@ -188,6 +192,25 @@ static int bmp280_read_calib(struct bmp280_data *data,
 	calib->P8 = le16_to_cpu(c_buf[P8]);
 	calib->P9 = le16_to_cpu(c_buf[P9]);
 
+	return 0;
+}
+
+static int bme280_read_calib(struct bmp280_data *data)
+{
+	struct bmp280_calib *calib = &data->calib.bmp280;
+	struct device *dev = data->dev;
+	unsigned int tmp;
+	__le16 l16;
+	__be16 b16;
+	int ret;
+
+	/* Load shared calibration params with bmp280 first */
+	ret = bmp280_read_calib(data);
+	if  (ret < 0) {
+		dev_err(dev, "failed to read common bmp280 calibration parameters\n");
+		return ret;
+	}
+
 	/*
 	 * Read humidity calibration values.
 	 * Due to some odd register addressing we cannot just
@@ -195,8 +218,6 @@ static int bmp280_read_calib(struct bmp280_data *data,
 	 * value separately and sometimes do some bit shifting...
 	 * Humidity data is only available on BME280.
 	 */
-	if (chip != BME280_CHIP_ID)
-		return 0;
 
 	ret = regmap_read(data->regmap, BMP280_REG_COMP_H1, &tmp);
 	if (ret < 0) {
@@ -631,15 +652,32 @@ static int bmp280_chip_config(struct bmp280_data *data)
 static const int bmp280_oversampling_avail[] = { 1, 2, 4, 8, 16 };
 
 static const struct bmp280_chip_info bmp280_chip_info = {
+	.id_reg = BMP280_REG_ID,
+	.start_up_time = 2000,
+	.num_channels = 2,
+
 	.oversampling_temp_avail = bmp280_oversampling_avail,
 	.num_oversampling_temp_avail = ARRAY_SIZE(bmp280_oversampling_avail),
+	/*
+	 * Oversampling config values on BMx280 have one additional setting
+	 * that other generations of the family don't:
+	 * The value 0 means the measurement is bypassed instead of
+	 * oversampling set to x1.
+	 *
+	 * To account for this difference, and preserve the same common
+	 * config logic, this is handled later on chip_config callback
+	 * incrementing one unit the oversampling setting.
+	 */
+	.oversampling_temp_default = BMP280_OSRS_TEMP_2X - 1,
 
 	.oversampling_press_avail = bmp280_oversampling_avail,
 	.num_oversampling_press_avail = ARRAY_SIZE(bmp280_oversampling_avail),
+	.oversampling_press_default = BMP280_OSRS_PRESS_16X - 1,
 
 	.chip_config = bmp280_chip_config,
 	.read_temp = bmp280_read_temp,
 	.read_press = bmp280_read_press,
+	.read_calib = bmp280_read_calib,
 };
 
 static int bme280_chip_config(struct bmp280_data *data)
@@ -661,19 +699,27 @@ static int bme280_chip_config(struct bmp280_data *data)
 }
 
 static const struct bmp280_chip_info bme280_chip_info = {
+	.id_reg = BMP280_REG_ID,
+	.start_up_time = 2000,
+	.num_channels = 3,
+
 	.oversampling_temp_avail = bmp280_oversampling_avail,
 	.num_oversampling_temp_avail = ARRAY_SIZE(bmp280_oversampling_avail),
+	.oversampling_temp_default = BMP280_OSRS_TEMP_2X - 1,
 
 	.oversampling_press_avail = bmp280_oversampling_avail,
 	.num_oversampling_press_avail = ARRAY_SIZE(bmp280_oversampling_avail),
+	.oversampling_press_default = BMP280_OSRS_PRESS_16X - 1,
 
 	.oversampling_humid_avail = bmp280_oversampling_avail,
 	.num_oversampling_humid_avail = ARRAY_SIZE(bmp280_oversampling_avail),
+	.oversampling_humid_default = BMP280_OSRS_HUMIDITY_16X - 1,
 
 	.chip_config = bme280_chip_config,
 	.read_temp = bmp280_read_temp,
 	.read_press = bmp280_read_press,
 	.read_humid = bmp280_read_humid,
+	.read_calib = bme280_read_calib,
 };
 
 static int bmp180_measure(struct bmp280_data *data, u8 ctrl_meas)
@@ -741,9 +787,9 @@ static int bmp180_read_adc_temp(struct bmp280_data *data, int *val)
 	return 0;
 }
 
-static int bmp180_read_calib(struct bmp280_data *data,
-			     struct bmp180_calib *calib)
+static int bmp180_read_calib(struct bmp280_data *data)
 {
+	struct bmp180_calib *calib = &data->calib.bmp180;
 	__be16 buf[BMP180_REG_CALIB_COUNT / 2];
 	int ret;
 	int i;
@@ -909,17 +955,24 @@ static const int bmp180_oversampling_temp_avail[] = { 1 };
 static const int bmp180_oversampling_press_avail[] = { 1, 2, 4, 8 };
 
 static const struct bmp280_chip_info bmp180_chip_info = {
+	.id_reg = BMP280_REG_ID,
+	.start_up_time = 2000,
+	.num_channels = 2,
+
 	.oversampling_temp_avail = bmp180_oversampling_temp_avail,
 	.num_oversampling_temp_avail =
 		ARRAY_SIZE(bmp180_oversampling_temp_avail),
+	.oversampling_temp_default = 0,
 
 	.oversampling_press_avail = bmp180_oversampling_press_avail,
 	.num_oversampling_press_avail =
 		ARRAY_SIZE(bmp180_oversampling_press_avail),
+	.oversampling_press_default = BMP180_MEAS_PRESS_8X,
 
 	.chip_config = bmp180_chip_config,
 	.read_temp = bmp180_read_temp,
 	.read_press = bmp180_read_press,
+	.read_calib = bmp180_read_calib,
 };
 
 static irqreturn_t bmp085_eoc_irq(int irq, void *d)
@@ -986,6 +1039,7 @@ int bmp280_common_probe(struct device *dev,
 			const char *name,
 			int irq)
 {
+	const struct bmp280_chip_info *chip_info;
 	struct iio_dev *indio_dev;
 	struct bmp280_data *data;
 	struct gpio_desc *gpiod;
@@ -1007,30 +1061,25 @@ int bmp280_common_probe(struct device *dev,
 
 	switch (chip) {
 	case BMP180_CHIP_ID:
-		indio_dev->num_channels = 2;
-		data->chip_info = &bmp180_chip_info;
-		data->oversampling_press = ilog2(8);
-		data->oversampling_temp = ilog2(1);
-		data->start_up_time = 10000;
+		chip_info = &bmp180_chip_info;
 		break;
 	case BMP280_CHIP_ID:
-		indio_dev->num_channels = 2;
-		data->chip_info = &bmp280_chip_info;
-		data->oversampling_press = ilog2(16);
-		data->oversampling_temp = ilog2(2);
-		data->start_up_time = 2000;
+		chip_info = &bmp280_chip_info;
 		break;
 	case BME280_CHIP_ID:
-		indio_dev->num_channels = 3;
-		data->chip_info = &bme280_chip_info;
-		data->oversampling_press = ilog2(16);
-		data->oversampling_humid = ilog2(16);
-		data->oversampling_temp = ilog2(2);
-		data->start_up_time = 2000;
+		chip_info = &bme280_chip_info;
 		break;
 	default:
 		return -EINVAL;
 	}
+	data->chip_info = chip_info;
+
+	/* Apply initial values from chip info structure */
+	indio_dev->num_channels = chip_info->num_channels;
+	data->oversampling_press = chip_info->oversampling_press_default;
+	data->oversampling_humid = chip_info->oversampling_humid_default;
+	data->oversampling_temp = chip_info->oversampling_temp_default;
+	data->start_up_time = chip_info->start_up_time;
 
 	/* Bring up regulators */
 	regulator_bulk_set_supply_names(data->supplies,
@@ -1067,7 +1116,8 @@ int bmp280_common_probe(struct device *dev,
 	}
 
 	data->regmap = regmap;
-	ret = regmap_read(regmap, BMP280_REG_ID, &chip_id);
+
+	ret = regmap_read(regmap, data->chip_info->id_reg, &chip_id);
 	if (ret < 0)
 		return ret;
 	if (chip_id != chip) {
@@ -1087,21 +1137,11 @@ int bmp280_common_probe(struct device *dev,
 	 * non-volatile memory during production". Let's read them out at probe
 	 * time once. They will not change.
 	 */
-	if (chip_id  == BMP180_CHIP_ID) {
-		ret = bmp180_read_calib(data, &data->calib.bmp180);
-		if (ret < 0) {
-			dev_err(data->dev,
-				"failed to read calibration coefficients\n");
-			return ret;
-		}
-	} else if (chip_id == BMP280_CHIP_ID || chip_id == BME280_CHIP_ID) {
-		ret = bmp280_read_calib(data, &data->calib.bmp280, chip_id);
-		if (ret < 0) {
-			dev_err(data->dev,
-				"failed to read calibration coefficients\n");
-			return ret;
-		}
-	}
+
+	ret = data->chip_info->read_calib(data);
+	if (ret < 0)
+		return dev_err_probe(data->dev, ret,
+				     "failed to read calibration coefficients\n");
 
 	/*
 	 * Attempt to grab an optional EOC IRQ - only the BMP085 has this
#8 lore raw

PATCH v6 5/9 iio: pressure: bmp280: Fix alignment for DMA safety

In reply to Angel Iglesias

Adds DMA-safe buffers to driver data struct to store raw data from sensors

The multiple buffers used thorough the driver share the same memory allocated as part of the device data instance. The union containing the buffers is aligned to allow safe usage with DMA operations, such as regmap bulk read calls.

Updated measurement and calibration reading functions to use the safe DMA buffers.

---
 drivers/iio/pressure/bmp280-core.c | 131 ++++++++++++++++-------------
 drivers/iio/pressure/bmp280.h      |   4 +-
 2 files changed, 76 insertions(+), 59 deletions(-)
drivers/iio/pressure/bmp280-core.c +74 -57
index 203623d32032..b6a16a580962 100644
@@ -32,6 +32,8 @@
 #include <linux/pm_runtime.h>
 #include <linux/random.h>
 
+#include <asm/unaligned.h>
+
 #include "bmp280.h"
 
 /*
@@ -106,6 +108,21 @@ struct bmp280_data {
 	 * calculation.
 	 */
 	s32 t_fine;
+
+	/*
+	 * DMA (thus cache coherency maintenance) may require the
+	 * transfer buffers to live in their own cache lines.
+	 */
+	union {
+		/* Sensor data buffer */
+		u8 buf[3];
+		/* Calibration data buffers */
+		__le16 bmp280_cal_buf[BMP280_CONTIGUOUS_CALIB_REGS / 2];
+		__be16 bmp180_cal_buf[BMP180_REG_CALIB_COUNT / 2];
+		/* Miscellaneous, endianess-aware data buffers */
+		__le16 le16;
+		__be16 be16;
+	} __aligned(IIO_DMA_MINALIGN);
 };
 
 struct bmp280_chip_info {
@@ -160,13 +177,12 @@ static const struct iio_chan_spec bmp280_channels[] = {
 static int bmp280_read_calib(struct bmp280_data *data)
 {
 	struct bmp280_calib *calib = &data->calib.bmp280;
-	__le16 c_buf[BMP280_CONTIGUOUS_CALIB_REGS / 2];
 	int ret;
 
 
 	/* Read temperature and pressure calibration values. */
 	ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_TEMP_START,
-			       c_buf, sizeof(c_buf));
+			       data->bmp280_cal_buf, sizeof(data->bmp280_cal_buf));
 	if (ret < 0) {
 		dev_err(data->dev,
 			"failed to read temperature and pressure calibration parameters\n");
@@ -174,23 +190,23 @@ static int bmp280_read_calib(struct bmp280_data *data)
 	}
 
 	/* Toss the temperature and pressure calibration data into the entropy pool */
-	add_device_randomness(c_buf, sizeof(c_buf));
+	add_device_randomness(data->bmp280_cal_buf, sizeof(data->bmp280_cal_buf));
 
 	/* Parse temperature calibration values. */
-	calib->T1 = le16_to_cpu(c_buf[T1]);
-	calib->T2 = le16_to_cpu(c_buf[T2]);
-	calib->T3 = le16_to_cpu(c_buf[T3]);
+	calib->T1 = le16_to_cpu(data->bmp280_cal_buf[T1]);
+	calib->T2 = le16_to_cpu(data->bmp280_cal_buf[T2]);
+	calib->T3 = le16_to_cpu(data->bmp280_cal_buf[T3]);
 
 	/* Parse pressure calibration values. */
-	calib->P1 = le16_to_cpu(c_buf[P1]);
-	calib->P2 = le16_to_cpu(c_buf[P2]);
-	calib->P3 = le16_to_cpu(c_buf[P3]);
-	calib->P4 = le16_to_cpu(c_buf[P4]);
-	calib->P5 = le16_to_cpu(c_buf[P5]);
-	calib->P6 = le16_to_cpu(c_buf[P6]);
-	calib->P7 = le16_to_cpu(c_buf[P7]);
-	calib->P8 = le16_to_cpu(c_buf[P8]);
-	calib->P9 = le16_to_cpu(c_buf[P9]);
+	calib->P1 = le16_to_cpu(data->bmp280_cal_buf[P1]);
+	calib->P2 = le16_to_cpu(data->bmp280_cal_buf[P2]);
+	calib->P3 = le16_to_cpu(data->bmp280_cal_buf[P3]);
+	calib->P4 = le16_to_cpu(data->bmp280_cal_buf[P4]);
+	calib->P5 = le16_to_cpu(data->bmp280_cal_buf[P5]);
+	calib->P6 = le16_to_cpu(data->bmp280_cal_buf[P6]);
+	calib->P7 = le16_to_cpu(data->bmp280_cal_buf[P7]);
+	calib->P8 = le16_to_cpu(data->bmp280_cal_buf[P8]);
+	calib->P9 = le16_to_cpu(data->bmp280_cal_buf[P9]);
 
 	return 0;
 }
@@ -200,8 +216,6 @@ static int bme280_read_calib(struct bmp280_data *data)
 	struct bmp280_calib *calib = &data->calib.bmp280;
 	struct device *dev = data->dev;
 	unsigned int tmp;
-	__le16 l16;
-	__be16 b16;
 	int ret;
 
 	/* Load shared calibration params with bmp280 first */
@@ -226,12 +240,13 @@ static int bme280_read_calib(struct bmp280_data *data)
 	}
 	calib->H1 = tmp;
 
-	ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_H2, &l16, 2);
+	ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_H2,
+			       &data->le16, sizeof(data->le16));
 	if (ret < 0) {
 		dev_err(dev, "failed to read H2 comp value\n");
 		return ret;
 	}
-	calib->H2 = sign_extend32(le16_to_cpu(l16), 15);
+	calib->H2 = sign_extend32(le16_to_cpu(data->le16), 15);
 
 	ret = regmap_read(data->regmap, BMP280_REG_COMP_H3, &tmp);
 	if (ret < 0) {
@@ -240,20 +255,22 @@ static int bme280_read_calib(struct bmp280_data *data)
 	}
 	calib->H3 = tmp;
 
-	ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_H4, &b16, 2);
+	ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_H4,
+			       &data->be16, sizeof(data->be16));
 	if (ret < 0) {
 		dev_err(dev, "failed to read H4 comp value\n");
 		return ret;
 	}
-	calib->H4 = sign_extend32(((be16_to_cpu(b16) >> 4) & 0xff0) |
-				  (be16_to_cpu(b16) & 0xf), 11);
+	calib->H4 = sign_extend32(((be16_to_cpu(data->be16) >> 4) & 0xff0) |
+				  (be16_to_cpu(data->be16) & 0xf), 11);
 
-	ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_H5, &l16, 2);
+	ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_H5,
+			       &data->le16, sizeof(data->le16));
 	if (ret < 0) {
 		dev_err(dev, "failed to read H5 comp value\n");
 		return ret;
 	}
-	calib->H5 = sign_extend32(FIELD_GET(BMP280_COMP_H5_MASK, le16_to_cpu(l16)), 11);
+	calib->H5 = sign_extend32(FIELD_GET(BMP280_COMP_H5_MASK, le16_to_cpu(data->le16)), 11);
 
 	ret = regmap_read(data->regmap, BMP280_REG_COMP_H6, &tmp);
 	if (ret < 0) {
@@ -348,16 +365,16 @@ static int bmp280_read_temp(struct bmp280_data *data,
 			    int *val)
 {
 	s32 adc_temp, comp_temp;
-	__be32 tmp = 0;
 	int ret;
 
-	ret = regmap_bulk_read(data->regmap, BMP280_REG_TEMP_MSB, &tmp, 3);
+	ret = regmap_bulk_read(data->regmap, BMP280_REG_TEMP_MSB,
+			       data->buf, sizeof(data->buf));
 	if (ret < 0) {
 		dev_err(data->dev, "failed to read temperature\n");
 		return ret;
 	}
 
-	adc_temp = FIELD_GET(BMP280_MEAS_TRIM_MASK, be32_to_cpu(tmp));
+	adc_temp = FIELD_GET(BMP280_MEAS_TRIM_MASK, get_unaligned_be24(data->buf));
 	if (adc_temp == BMP280_TEMP_SKIPPED) {
 		/* reading was skipped */
 		dev_err(data->dev, "reading temperature skipped\n");
@@ -381,7 +398,6 @@ static int bmp280_read_press(struct bmp280_data *data,
 			     int *val, int *val2)
 {
 	u32 comp_press;
-	__be32 tmp = 0;
 	s32 adc_press;
 	int ret;
 
@@ -390,13 +406,14 @@ static int bmp280_read_press(struct bmp280_data *data,
 	if (ret < 0)
 		return ret;
 
-	ret = regmap_bulk_read(data->regmap, BMP280_REG_PRESS_MSB, &tmp, 3);
+	ret = regmap_bulk_read(data->regmap, BMP280_REG_PRESS_MSB,
+			       data->buf, sizeof(data->buf));
 	if (ret < 0) {
 		dev_err(data->dev, "failed to read pressure\n");
 		return ret;
 	}
 
-	adc_press = FIELD_GET(BMP280_MEAS_TRIM_MASK, be32_to_cpu(tmp));
+	adc_press = FIELD_GET(BMP280_MEAS_TRIM_MASK, get_unaligned_be24(data->buf));
 	if (adc_press == BMP280_PRESS_SKIPPED) {
 		/* reading was skipped */
 		dev_err(data->dev, "reading pressure skipped\n");
@@ -414,7 +431,6 @@ static int bmp280_read_humid(struct bmp280_data *data, int *val, int *val2)
 {
 	u32 comp_humidity;
 	s32 adc_humidity;
-	__be16 tmp;
 	int ret;
 
 	/* Read and compensate temperature so we get a reading of t_fine. */
@@ -422,13 +438,14 @@ static int bmp280_read_humid(struct bmp280_data *data, int *val, int *val2)
 	if (ret < 0)
 		return ret;
 
-	ret = regmap_bulk_read(data->regmap, BMP280_REG_HUMIDITY_MSB, &tmp, 2);
+	ret = regmap_bulk_read(data->regmap, BMP280_REG_HUMIDITY_MSB,
+			       &data->be16, sizeof(data->be16));
 	if (ret < 0) {
 		dev_err(data->dev, "failed to read humidity\n");
 		return ret;
 	}
 
-	adc_humidity = be16_to_cpu(tmp);
+	adc_humidity = be16_to_cpu(data->be16);
 	if (adc_humidity == BMP280_HUMIDITY_SKIPPED) {
 		/* reading was skipped */
 		dev_err(data->dev, "reading humidity skipped\n");
@@ -769,7 +786,6 @@ static int bmp180_measure(struct bmp280_data *data, u8 ctrl_meas)
 
 static int bmp180_read_adc_temp(struct bmp280_data *data, int *val)
 {
-	__be16 tmp;
 	int ret;
 
 	ret = bmp180_measure(data,
@@ -778,11 +794,12 @@ static int bmp180_read_adc_temp(struct bmp280_data *data, int *val)
 	if (ret)
 		return ret;
 
-	ret = regmap_bulk_read(data->regmap, BMP180_REG_OUT_MSB, &tmp, 2);
+	ret = regmap_bulk_read(data->regmap, BMP180_REG_OUT_MSB,
+			       &data->be16, sizeof(data->be16));
 	if (ret)
 		return ret;
 
-	*val = be16_to_cpu(tmp);
+	*val = be16_to_cpu(data->be16);
 
 	return 0;
 }
@@ -790,36 +807,36 @@ static int bmp180_read_adc_temp(struct bmp280_data *data, int *val)
 static int bmp180_read_calib(struct bmp280_data *data)
 {
 	struct bmp180_calib *calib = &data->calib.bmp180;
-	__be16 buf[BMP180_REG_CALIB_COUNT / 2];
 	int ret;
 	int i;
 
-	ret = regmap_bulk_read(data->regmap, BMP180_REG_CALIB_START, buf,
-			       sizeof(buf));
+	ret = regmap_bulk_read(data->regmap, BMP180_REG_CALIB_START,
+			       data->bmp180_cal_buf, sizeof(data->bmp180_cal_buf));
 
 	if (ret < 0)
 		return ret;
 
 	/* None of the words has the value 0 or 0xFFFF */
-	for (i = 0; i < ARRAY_SIZE(buf); i++) {
-		if (buf[i] == cpu_to_be16(0) || buf[i] == cpu_to_be16(0xffff))
+	for (i = 0; i < ARRAY_SIZE(data->bmp180_cal_buf); i++) {
+		if (data->bmp180_cal_buf[i] == cpu_to_be16(0) ||
+		    data->bmp180_cal_buf[i] == cpu_to_be16(0xffff))
 			return -EIO;
 	}
 
 	/* Toss the calibration data into the entropy pool */
-	add_device_randomness(buf, sizeof(buf));
-
-	calib->AC1 = be16_to_cpu(buf[AC1]);
-	calib->AC2 = be16_to_cpu(buf[AC2]);
-	calib->AC3 = be16_to_cpu(buf[AC3]);
-	calib->AC4 = be16_to_cpu(buf[AC4]);
-	calib->AC5 = be16_to_cpu(buf[AC5]);
-	calib->AC6 = be16_to_cpu(buf[AC6]);
-	calib->B1 = be16_to_cpu(buf[B1]);
-	calib->B2 = be16_to_cpu(buf[B2]);
-	calib->MB = be16_to_cpu(buf[MB]);
-	calib->MC = be16_to_cpu(buf[MC]);
-	calib->MD = be16_to_cpu(buf[MD]);
+	add_device_randomness(data->bmp180_cal_buf, sizeof(data->bmp180_cal_buf));
+
+	calib->AC1 = be16_to_cpu(data->bmp180_cal_buf[AC1]);
+	calib->AC2 = be16_to_cpu(data->bmp180_cal_buf[AC2]);
+	calib->AC3 = be16_to_cpu(data->bmp180_cal_buf[AC3]);
+	calib->AC4 = be16_to_cpu(data->bmp180_cal_buf[AC4]);
+	calib->AC5 = be16_to_cpu(data->bmp180_cal_buf[AC5]);
+	calib->AC6 = be16_to_cpu(data->bmp180_cal_buf[AC6]);
+	calib->B1 = be16_to_cpu(data->bmp180_cal_buf[B1]);
+	calib->B2 = be16_to_cpu(data->bmp180_cal_buf[B2]);
+	calib->MB = be16_to_cpu(data->bmp180_cal_buf[MB]);
+	calib->MC = be16_to_cpu(data->bmp180_cal_buf[MC]);
+	calib->MD = be16_to_cpu(data->bmp180_cal_buf[MD]);
 
 	return 0;
 }
@@ -868,7 +885,6 @@ static int bmp180_read_temp(struct bmp280_data *data, int *val)
 static int bmp180_read_adc_press(struct bmp280_data *data, int *val)
 {
 	u8 oss = data->oversampling_press;
-	__be32 tmp = 0;
 	int ret;
 
 	ret = bmp180_measure(data,
@@ -878,11 +894,12 @@ static int bmp180_read_adc_press(struct bmp280_data *data, int *val)
 	if (ret)
 		return ret;
 
-	ret = regmap_bulk_read(data->regmap, BMP180_REG_OUT_MSB, &tmp, 3);
+	ret = regmap_bulk_read(data->regmap, BMP180_REG_OUT_MSB,
+			       data->buf, sizeof(data->buf));
 	if (ret)
 		return ret;
 
-	*val = (be32_to_cpu(tmp) >> 8) >> (8 - oss);
+	*val = get_unaligned_be24(data->buf) >> (8 - oss);
 
 	return 0;
 }
drivers/iio/pressure/bmp280.h +2 -2
index 03a539223417..c9214a7e5cc6 100644
@@ -13,8 +13,8 @@
 #define BMP280_REG_PRESS_LSB		0xF8
 #define BMP280_REG_PRESS_MSB		0xF7
 
-/* Helper mask to truncate excess 12 bits on pressure and temp readings */
-#define BMP280_MEAS_TRIM_MASK		GENMASK(31, 12)
+/* Helper mask to truncate excess 4 bits on pressure and temp readings */
+#define BMP280_MEAS_TRIM_MASK		GENMASK(24, 4)
 
 #define BMP280_REG_CONFIG		0xF5
 #define BMP280_REG_CTRL_MEAS		0xF4
Signature · 1 line
2.37.3
maintainer Applied
#9 lore raw

Re: [PATCH v6 5/9] iio: pressure: bmp280: Fix alignment for DMA safety

Quoted 7 lines · On Tue, 13 Sep 2022 01:48:21 +0200 Angel Iglesias <[email protected]>…

Adds DMA-safe buffers to driver data struct to store raw data from sensors

The multiple buffers used thorough the driver share the same memory allocated as part of the device data instance. The union containing the buffers is aligned to allow safe usage with DMA operations, such as regmap bulk read calls.

Quoted 5 lines

Updated measurement and calibration reading functions to use the safe DMA buffers.

Applied

Quoted 331 lines
---
 drivers/iio/pressure/bmp280-core.c | 131 ++++++++++++++++-------------
 drivers/iio/pressure/bmp280.h      |   4 +-
 2 files changed, 76 insertions(+), 59 deletions(-)
drivers/iio/pressure/bmp280-core.c +74 -57
index 203623d32032..b6a16a580962 100644
@@ -32,6 +32,8 @@
 #include <linux/pm_runtime.h>
 #include <linux/random.h>
 
+#include <asm/unaligned.h>
+
 #include "bmp280.h"
 
 /*
@@ -106,6 +108,21 @@ struct bmp280_data {
 	 * calculation.
 	 */
 	s32 t_fine;
+
+	/*
+	 * DMA (thus cache coherency maintenance) may require the
+	 * transfer buffers to live in their own cache lines.
+	 */
+	union {
+		/* Sensor data buffer */
+		u8 buf[3];
+		/* Calibration data buffers */
+		__le16 bmp280_cal_buf[BMP280_CONTIGUOUS_CALIB_REGS / 2];
+		__be16 bmp180_cal_buf[BMP180_REG_CALIB_COUNT / 2];
+		/* Miscellaneous, endianess-aware data buffers */
+		__le16 le16;
+		__be16 be16;
+	} __aligned(IIO_DMA_MINALIGN);
 };
 
 struct bmp280_chip_info {
@@ -160,13 +177,12 @@ static const struct iio_chan_spec bmp280_channels[] = {
 static int bmp280_read_calib(struct bmp280_data *data)
 {
 	struct bmp280_calib *calib = &data->calib.bmp280;
-	__le16 c_buf[BMP280_CONTIGUOUS_CALIB_REGS / 2];
 	int ret;
 
 
 	/* Read temperature and pressure calibration values. */
 	ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_TEMP_START,
-			       c_buf, sizeof(c_buf));
+			       data->bmp280_cal_buf, sizeof(data->bmp280_cal_buf));
 	if (ret < 0) {
 		dev_err(data->dev,
 			"failed to read temperature and pressure calibration parameters\n");
@@ -174,23 +190,23 @@ static int bmp280_read_calib(struct bmp280_data *data)
 	}
 
 	/* Toss the temperature and pressure calibration data into the entropy pool */
-	add_device_randomness(c_buf, sizeof(c_buf));
+	add_device_randomness(data->bmp280_cal_buf, sizeof(data->bmp280_cal_buf));
 
 	/* Parse temperature calibration values. */
-	calib->T1 = le16_to_cpu(c_buf[T1]);
-	calib->T2 = le16_to_cpu(c_buf[T2]);
-	calib->T3 = le16_to_cpu(c_buf[T3]);
+	calib->T1 = le16_to_cpu(data->bmp280_cal_buf[T1]);
+	calib->T2 = le16_to_cpu(data->bmp280_cal_buf[T2]);
+	calib->T3 = le16_to_cpu(data->bmp280_cal_buf[T3]);
 
 	/* Parse pressure calibration values. */
-	calib->P1 = le16_to_cpu(c_buf[P1]);
-	calib->P2 = le16_to_cpu(c_buf[P2]);
-	calib->P3 = le16_to_cpu(c_buf[P3]);
-	calib->P4 = le16_to_cpu(c_buf[P4]);
-	calib->P5 = le16_to_cpu(c_buf[P5]);
-	calib->P6 = le16_to_cpu(c_buf[P6]);
-	calib->P7 = le16_to_cpu(c_buf[P7]);
-	calib->P8 = le16_to_cpu(c_buf[P8]);
-	calib->P9 = le16_to_cpu(c_buf[P9]);
+	calib->P1 = le16_to_cpu(data->bmp280_cal_buf[P1]);
+	calib->P2 = le16_to_cpu(data->bmp280_cal_buf[P2]);
+	calib->P3 = le16_to_cpu(data->bmp280_cal_buf[P3]);
+	calib->P4 = le16_to_cpu(data->bmp280_cal_buf[P4]);
+	calib->P5 = le16_to_cpu(data->bmp280_cal_buf[P5]);
+	calib->P6 = le16_to_cpu(data->bmp280_cal_buf[P6]);
+	calib->P7 = le16_to_cpu(data->bmp280_cal_buf[P7]);
+	calib->P8 = le16_to_cpu(data->bmp280_cal_buf[P8]);
+	calib->P9 = le16_to_cpu(data->bmp280_cal_buf[P9]);
 
 	return 0;
 }
@@ -200,8 +216,6 @@ static int bme280_read_calib(struct bmp280_data *data)
 	struct bmp280_calib *calib = &data->calib.bmp280;
 	struct device *dev = data->dev;
 	unsigned int tmp;
-	__le16 l16;
-	__be16 b16;
 	int ret;
 
 	/* Load shared calibration params with bmp280 first */
@@ -226,12 +240,13 @@ static int bme280_read_calib(struct bmp280_data *data)
 	}
 	calib->H1 = tmp;
 
-	ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_H2, &l16, 2);
+	ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_H2,
+			       &data->le16, sizeof(data->le16));
 	if (ret < 0) {
 		dev_err(dev, "failed to read H2 comp value\n");
 		return ret;
 	}
-	calib->H2 = sign_extend32(le16_to_cpu(l16), 15);
+	calib->H2 = sign_extend32(le16_to_cpu(data->le16), 15);
 
 	ret = regmap_read(data->regmap, BMP280_REG_COMP_H3, &tmp);
 	if (ret < 0) {
@@ -240,20 +255,22 @@ static int bme280_read_calib(struct bmp280_data *data)
 	}
 	calib->H3 = tmp;
 
-	ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_H4, &b16, 2);
+	ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_H4,
+			       &data->be16, sizeof(data->be16));
 	if (ret < 0) {
 		dev_err(dev, "failed to read H4 comp value\n");
 		return ret;
 	}
-	calib->H4 = sign_extend32(((be16_to_cpu(b16) >> 4) & 0xff0) |
-				  (be16_to_cpu(b16) & 0xf), 11);
+	calib->H4 = sign_extend32(((be16_to_cpu(data->be16) >> 4) & 0xff0) |
+				  (be16_to_cpu(data->be16) & 0xf), 11);
 
-	ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_H5, &l16, 2);
+	ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_H5,
+			       &data->le16, sizeof(data->le16));
 	if (ret < 0) {
 		dev_err(dev, "failed to read H5 comp value\n");
 		return ret;
 	}
-	calib->H5 = sign_extend32(FIELD_GET(BMP280_COMP_H5_MASK, le16_to_cpu(l16)), 11);
+	calib->H5 = sign_extend32(FIELD_GET(BMP280_COMP_H5_MASK, le16_to_cpu(data->le16)), 11);
 
 	ret = regmap_read(data->regmap, BMP280_REG_COMP_H6, &tmp);
 	if (ret < 0) {
@@ -348,16 +365,16 @@ static int bmp280_read_temp(struct bmp280_data *data,
 			    int *val)
 {
 	s32 adc_temp, comp_temp;
-	__be32 tmp = 0;
 	int ret;
 
-	ret = regmap_bulk_read(data->regmap, BMP280_REG_TEMP_MSB, &tmp, 3);
+	ret = regmap_bulk_read(data->regmap, BMP280_REG_TEMP_MSB,
+			       data->buf, sizeof(data->buf));
 	if (ret < 0) {
 		dev_err(data->dev, "failed to read temperature\n");
 		return ret;
 	}
 
-	adc_temp = FIELD_GET(BMP280_MEAS_TRIM_MASK, be32_to_cpu(tmp));
+	adc_temp = FIELD_GET(BMP280_MEAS_TRIM_MASK, get_unaligned_be24(data->buf));
 	if (adc_temp == BMP280_TEMP_SKIPPED) {
 		/* reading was skipped */
 		dev_err(data->dev, "reading temperature skipped\n");
@@ -381,7 +398,6 @@ static int bmp280_read_press(struct bmp280_data *data,
 			     int *val, int *val2)
 {
 	u32 comp_press;
-	__be32 tmp = 0;
 	s32 adc_press;
 	int ret;
 
@@ -390,13 +406,14 @@ static int bmp280_read_press(struct bmp280_data *data,
 	if (ret < 0)
 		return ret;
 
-	ret = regmap_bulk_read(data->regmap, BMP280_REG_PRESS_MSB, &tmp, 3);
+	ret = regmap_bulk_read(data->regmap, BMP280_REG_PRESS_MSB,
+			       data->buf, sizeof(data->buf));
 	if (ret < 0) {
 		dev_err(data->dev, "failed to read pressure\n");
 		return ret;
 	}
 
-	adc_press = FIELD_GET(BMP280_MEAS_TRIM_MASK, be32_to_cpu(tmp));
+	adc_press = FIELD_GET(BMP280_MEAS_TRIM_MASK, get_unaligned_be24(data->buf));
 	if (adc_press == BMP280_PRESS_SKIPPED) {
 		/* reading was skipped */
 		dev_err(data->dev, "reading pressure skipped\n");
@@ -414,7 +431,6 @@ static int bmp280_read_humid(struct bmp280_data *data, int *val, int *val2)
 {
 	u32 comp_humidity;
 	s32 adc_humidity;
-	__be16 tmp;
 	int ret;
 
 	/* Read and compensate temperature so we get a reading of t_fine. */
@@ -422,13 +438,14 @@ static int bmp280_read_humid(struct bmp280_data *data, int *val, int *val2)
 	if (ret < 0)
 		return ret;
 
-	ret = regmap_bulk_read(data->regmap, BMP280_REG_HUMIDITY_MSB, &tmp, 2);
+	ret = regmap_bulk_read(data->regmap, BMP280_REG_HUMIDITY_MSB,
+			       &data->be16, sizeof(data->be16));
 	if (ret < 0) {
 		dev_err(data->dev, "failed to read humidity\n");
 		return ret;
 	}
 
-	adc_humidity = be16_to_cpu(tmp);
+	adc_humidity = be16_to_cpu(data->be16);
 	if (adc_humidity == BMP280_HUMIDITY_SKIPPED) {
 		/* reading was skipped */
 		dev_err(data->dev, "reading humidity skipped\n");
@@ -769,7 +786,6 @@ static int bmp180_measure(struct bmp280_data *data, u8 ctrl_meas)
 
 static int bmp180_read_adc_temp(struct bmp280_data *data, int *val)
 {
-	__be16 tmp;
 	int ret;
 
 	ret = bmp180_measure(data,
@@ -778,11 +794,12 @@ static int bmp180_read_adc_temp(struct bmp280_data *data, int *val)
 	if (ret)
 		return ret;
 
-	ret = regmap_bulk_read(data->regmap, BMP180_REG_OUT_MSB, &tmp, 2);
+	ret = regmap_bulk_read(data->regmap, BMP180_REG_OUT_MSB,
+			       &data->be16, sizeof(data->be16));
 	if (ret)
 		return ret;
 
-	*val = be16_to_cpu(tmp);
+	*val = be16_to_cpu(data->be16);
 
 	return 0;
 }
@@ -790,36 +807,36 @@ static int bmp180_read_adc_temp(struct bmp280_data *data, int *val)
 static int bmp180_read_calib(struct bmp280_data *data)
 {
 	struct bmp180_calib *calib = &data->calib.bmp180;
-	__be16 buf[BMP180_REG_CALIB_COUNT / 2];
 	int ret;
 	int i;
 
-	ret = regmap_bulk_read(data->regmap, BMP180_REG_CALIB_START, buf,
-			       sizeof(buf));
+	ret = regmap_bulk_read(data->regmap, BMP180_REG_CALIB_START,
+			       data->bmp180_cal_buf, sizeof(data->bmp180_cal_buf));
 
 	if (ret < 0)
 		return ret;
 
 	/* None of the words has the value 0 or 0xFFFF */
-	for (i = 0; i < ARRAY_SIZE(buf); i++) {
-		if (buf[i] == cpu_to_be16(0) || buf[i] == cpu_to_be16(0xffff))
+	for (i = 0; i < ARRAY_SIZE(data->bmp180_cal_buf); i++) {
+		if (data->bmp180_cal_buf[i] == cpu_to_be16(0) ||
+		    data->bmp180_cal_buf[i] == cpu_to_be16(0xffff))
 			return -EIO;
 	}
 
 	/* Toss the calibration data into the entropy pool */
-	add_device_randomness(buf, sizeof(buf));
-
-	calib->AC1 = be16_to_cpu(buf[AC1]);
-	calib->AC2 = be16_to_cpu(buf[AC2]);
-	calib->AC3 = be16_to_cpu(buf[AC3]);
-	calib->AC4 = be16_to_cpu(buf[AC4]);
-	calib->AC5 = be16_to_cpu(buf[AC5]);
-	calib->AC6 = be16_to_cpu(buf[AC6]);
-	calib->B1 = be16_to_cpu(buf[B1]);
-	calib->B2 = be16_to_cpu(buf[B2]);
-	calib->MB = be16_to_cpu(buf[MB]);
-	calib->MC = be16_to_cpu(buf[MC]);
-	calib->MD = be16_to_cpu(buf[MD]);
+	add_device_randomness(data->bmp180_cal_buf, sizeof(data->bmp180_cal_buf));
+
+	calib->AC1 = be16_to_cpu(data->bmp180_cal_buf[AC1]);
+	calib->AC2 = be16_to_cpu(data->bmp180_cal_buf[AC2]);
+	calib->AC3 = be16_to_cpu(data->bmp180_cal_buf[AC3]);
+	calib->AC4 = be16_to_cpu(data->bmp180_cal_buf[AC4]);
+	calib->AC5 = be16_to_cpu(data->bmp180_cal_buf[AC5]);
+	calib->AC6 = be16_to_cpu(data->bmp180_cal_buf[AC6]);
+	calib->B1 = be16_to_cpu(data->bmp180_cal_buf[B1]);
+	calib->B2 = be16_to_cpu(data->bmp180_cal_buf[B2]);
+	calib->MB = be16_to_cpu(data->bmp180_cal_buf[MB]);
+	calib->MC = be16_to_cpu(data->bmp180_cal_buf[MC]);
+	calib->MD = be16_to_cpu(data->bmp180_cal_buf[MD]);
 
 	return 0;
 }
@@ -868,7 +885,6 @@ static int bmp180_read_temp(struct bmp280_data *data, int *val)
 static int bmp180_read_adc_press(struct bmp280_data *data, int *val)
 {
 	u8 oss = data->oversampling_press;
-	__be32 tmp = 0;
 	int ret;
 
 	ret = bmp180_measure(data,
@@ -878,11 +894,12 @@ static int bmp180_read_adc_press(struct bmp280_data *data, int *val)
 	if (ret)
 		return ret;
 
-	ret = regmap_bulk_read(data->regmap, BMP180_REG_OUT_MSB, &tmp, 3);
+	ret = regmap_bulk_read(data->regmap, BMP180_REG_OUT_MSB,
+			       data->buf, sizeof(data->buf));
 	if (ret)
 		return ret;
 
-	*val = (be32_to_cpu(tmp) >> 8) >> (8 - oss);
+	*val = get_unaligned_be24(data->buf) >> (8 - oss);
 
 	return 0;
 }
drivers/iio/pressure/bmp280.h +2 -2
index 03a539223417..c9214a7e5cc6 100644
@@ -13,8 +13,8 @@
 #define BMP280_REG_PRESS_LSB		0xF8
 #define BMP280_REG_PRESS_MSB		0xF7
 
-/* Helper mask to truncate excess 12 bits on pressure and temp readings */
-#define BMP280_MEAS_TRIM_MASK		GENMASK(31, 12)
+/* Helper mask to truncate excess 4 bits on pressure and temp readings */
+#define BMP280_MEAS_TRIM_MASK		GENMASK(24, 4)
 
 #define BMP280_REG_CONFIG		0xF5
 #define BMP280_REG_CTRL_MEAS		0xF4
#10 lore raw

PATCH v6 6/9 iio: pressure: bmp280: reorder i2c device tables declarations

In reply to Angel Iglesias

Change device tables declarations to forward order like in SPI codepath.

---
 drivers/iio/pressure/bmp280-i2c.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)
drivers/iio/pressure/bmp280-i2c.c +5 -5
index bf4a7a617537..5b51ebfc6f2b 100644
@@ -37,18 +37,18 @@ static int bmp280_i2c_probe(struct i2c_client *client,
 }
 
 static const struct of_device_id bmp280_of_i2c_match[] = {
-	{ .compatible = "bosch,bme280", .data = (void *)BME280_CHIP_ID },
-	{ .compatible = "bosch,bmp280", .data = (void *)BMP280_CHIP_ID },
-	{ .compatible = "bosch,bmp180", .data = (void *)BMP180_CHIP_ID },
 	{ .compatible = "bosch,bmp085", .data = (void *)BMP180_CHIP_ID },
+	{ .compatible = "bosch,bmp180", .data = (void *)BMP180_CHIP_ID },
+	{ .compatible = "bosch,bmp280", .data = (void *)BMP280_CHIP_ID },
+	{ .compatible = "bosch,bme280", .data = (void *)BME280_CHIP_ID },
 	{ },
 };
 MODULE_DEVICE_TABLE(of, bmp280_of_i2c_match);
 
 static const struct i2c_device_id bmp280_i2c_id[] = {
-	{"bmp280", BMP280_CHIP_ID },
-	{"bmp180", BMP180_CHIP_ID },
 	{"bmp085", BMP180_CHIP_ID },
+	{"bmp180", BMP180_CHIP_ID },
+	{"bmp280", BMP280_CHIP_ID },
 	{"bme280", BME280_CHIP_ID },
 	{ },
 };
Signature · 1 line
2.37.3
maintainer Applied
#11 lore raw

Re: [PATCH v6 6/9] iio: pressure: bmp280: reorder i2c device tables declarations

Quoted 4 lines · On Tue, 13 Sep 2022 01:50:07 +0200 Angel Iglesias <[email protected]>…

Change device tables declarations to forward order like in SPI codepath.

Applied

Quoted 32 lines
---
 drivers/iio/pressure/bmp280-i2c.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)
drivers/iio/pressure/bmp280-i2c.c +5 -5
index bf4a7a617537..5b51ebfc6f2b 100644
@@ -37,18 +37,18 @@ static int bmp280_i2c_probe(struct i2c_client *client,
 }
 
 static const struct of_device_id bmp280_of_i2c_match[] = {
-	{ .compatible = "bosch,bme280", .data = (void *)BME280_CHIP_ID },
-	{ .compatible = "bosch,bmp280", .data = (void *)BMP280_CHIP_ID },
-	{ .compatible = "bosch,bmp180", .data = (void *)BMP180_CHIP_ID },
 	{ .compatible = "bosch,bmp085", .data = (void *)BMP180_CHIP_ID },
+	{ .compatible = "bosch,bmp180", .data = (void *)BMP180_CHIP_ID },
+	{ .compatible = "bosch,bmp280", .data = (void *)BMP280_CHIP_ID },
+	{ .compatible = "bosch,bme280", .data = (void *)BME280_CHIP_ID },
 	{ },
 };
 MODULE_DEVICE_TABLE(of, bmp280_of_i2c_match);
 
 static const struct i2c_device_id bmp280_i2c_id[] = {
-	{"bmp280", BMP280_CHIP_ID },
-	{"bmp180", BMP180_CHIP_ID },
 	{"bmp085", BMP180_CHIP_ID },
+	{"bmp180", BMP180_CHIP_ID },
+	{"bmp280", BMP280_CHIP_ID },
 	{"bme280", BME280_CHIP_ID },
 	{ },
 };
#12 lore raw

PATCH v6 7/9 iio: pressure: bmp280: Add support for BMP380 sensor family

In reply to Angel Iglesias

Adds compatibility with the new generation of this sensor, the BMP380.

Includes basic sensor initialization to do pressure and temp measurements and allows tuning oversampling settings for each channel.

The compensation algorithms are adapted from the device datasheet and the repository https://github.com/BoschSensortec/BMP3-Sensor-API.

---
 drivers/iio/pressure/Kconfig         |   6 +-
 drivers/iio/pressure/bmp280-core.c   | 386 +++++++++++++++++++++++++++
 drivers/iio/pressure/bmp280-i2c.c    |   5 +
 drivers/iio/pressure/bmp280-regmap.c |  55 ++++
 drivers/iio/pressure/bmp280-spi.c    |   5 +
 drivers/iio/pressure/bmp280.h        | 101 +++++++
 6 files changed, 555 insertions(+), 3 deletions(-)
drivers/iio/pressure/Kconfig +3 -3
index 0ff756cea63a..c9453389e4f7 100644
@@ -17,14 +17,14 @@ config ABP060MG
 	  will be called abp060mg.
 
 config BMP280
-	tristate "Bosch Sensortec BMP180/BMP280 pressure sensor I2C driver"
+	tristate "Bosch Sensortec BMP180/BMP280/BMP380 pressure sensor I2C driver"
 	depends on (I2C || SPI_MASTER)
 	select REGMAP
 	select BMP280_I2C if (I2C)
 	select BMP280_SPI if (SPI_MASTER)
 	help
-	  Say yes here to build support for Bosch Sensortec BMP180 and BMP280
-	  pressure and temperature sensors. Also supports the BME280 with
+	  Say yes here to build support for Bosch Sensortec BMP180, BMP280 and
+	  BMP380 pressure and temperature sensors. Also supports the BME280 with
 	  an additional humidity sensor channel.
 
 	  To compile this driver as a module, choose M here: the core module
drivers/iio/pressure/bmp280-core.c +386 -0

434 lines not on this page · raw message

drivers/iio/pressure/bmp280-i2c.c +5 -0
index 5b51ebfc6f2b..0c27211f3ea0 100644
@@ -19,6 +19,9 @@ static int bmp280_i2c_probe(struct i2c_client *client,
 	case BME280_CHIP_ID:
 		regmap_config = &bmp280_regmap_config;
 		break;
+	case BMP380_CHIP_ID:
+		regmap_config = &bmp380_regmap_config;
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -41,6 +44,7 @@ static const struct of_device_id bmp280_of_i2c_match[] = {
 	{ .compatible = "bosch,bmp180", .data = (void *)BMP180_CHIP_ID },
 	{ .compatible = "bosch,bmp280", .data = (void *)BMP280_CHIP_ID },
 	{ .compatible = "bosch,bme280", .data = (void *)BME280_CHIP_ID },
+	{ .compatible = "bosch,bmp380", .data = (void *)BMP380_CHIP_ID },
 	{ },
 };
 MODULE_DEVICE_TABLE(of, bmp280_of_i2c_match);
@@ -50,6 +54,7 @@ static const struct i2c_device_id bmp280_i2c_id[] = {
 	{"bmp180", BMP180_CHIP_ID },
 	{"bmp280", BMP280_CHIP_ID },
 	{"bme280", BME280_CHIP_ID },
+	{"bmp380", BMP380_CHIP_ID },
 	{ },
 };
 MODULE_DEVICE_TABLE(i2c, bmp280_i2c_id);
drivers/iio/pressure/bmp280-regmap.c +55 -0

64 lines not on this page · raw message

drivers/iio/pressure/bmp280-spi.c +5 -0
index 4cfaf3e869b8..011c68e07ebf 100644
@@ -66,6 +66,9 @@ static int bmp280_spi_probe(struct spi_device *spi)
 	case BME280_CHIP_ID:
 		regmap_config = &bmp280_regmap_config;
 		break;
+	case BMP380_CHIP_ID:
+		regmap_config = &bmp380_regmap_config;
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -92,6 +95,7 @@ static const struct of_device_id bmp280_of_spi_match[] = {
 	{ .compatible = "bosch,bmp181", },
 	{ .compatible = "bosch,bmp280", },
 	{ .compatible = "bosch,bme280", },
+	{ .compatible = "bosch,bmp380", },
 	{ },
 };
 MODULE_DEVICE_TABLE(of, bmp280_of_spi_match);
@@ -101,6 +105,7 @@ static const struct spi_device_id bmp280_spi_id[] = {
 	{ "bmp181", BMP180_CHIP_ID },
 	{ "bmp280", BMP280_CHIP_ID },
 	{ "bme280", BME280_CHIP_ID },
+	{ "bmp380", BMP380_CHIP_ID },
 	{ }
 };
 MODULE_DEVICE_TABLE(spi, bmp280_spi_id);
drivers/iio/pressure/bmp280.h +101 -0

119 lines not on this page · raw message

Signature · 1 line
2.37.3
#13 lore raw

Re: [PATCH v6 7/9] iio: pressure: bmp280: Add support for BMP380 sensor family

Quoted 7 lines · Angel Iglesias

Adds compatibility with the new generation of this sensor, the BMP380.

Includes basic sensor initialization to do pressure and temp measurements and allows tuning oversampling settings for each channel.

The compensation algorithms are adapted from the device datasheet and the repository https://github.com/BoschSensortec/BMP3-Sensor-API.

...

Quoted 5 lines

* https://ae-bst.resource.bosch.com/media/_tech/media/datasheets/BST-BMP180-DS000-121.pdf
* https://ae-bst.resource.bosch.com/media/_tech/media/datasheets/BST-BMP280-DS001-12.pdf
* https://ae-bst.resource.bosch.com/media/_tech/media/datasheets/BST-BME280_DS001-11.pdf
+ * https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bmp388-ds001.pdf
*/

Shouldn't it be based on your patch to fix the links?

Signature · 2 lines
With Best Regards,
Andy Shevchenko
#14 lore raw

Re: [PATCH v6 7/9] iio: pressure: bmp280: Add support for BMP380 sensor family

Quoted 21 lines · Andy Shevchenko
Quoted 7 lines · Angel Iglesias

Adds compatibility with the new generation of this sensor, the BMP380.

Includes basic sensor initialization to do pressure and temp measurements and allows tuning oversampling settings for each channel.

The compensation algorithms are adapted from the device datasheet and the repository https://github.com/BoschSensortec/BMP3-Sensor-API.

...

Quoted 9 lines

  *
https://ae-bst.resource.bosch.com/media/_tech/media/datasheets/BST-BMP180-DS000-121.pdf
  *
https://ae-bst.resource.bosch.com/media/_tech/media/datasheets/BST-BMP280-DS001-12.pdf
  *
https://ae-bst.resource.bosch.com/media/_tech/media/datasheets/BST-BME280_DS001-11.pdf
+ *
https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bmp388-ds001.pdf
  */

Quoted 2 lines

Shouldn't it be based on your patch to fix the links?

I thought of adding the patch fixing the links as a prerequisite commit, but in the end decided to keep the patchsets independent to avoid codependencies.

Kind regards,
Angel

#15 lore raw

Re: [PATCH v6 7/9] iio: pressure: bmp280: Add support for BMP380 sensor family

Quoted 2 lines · Angel Iglesias
Quoted 1 line · Andy Shevchenko

On Tue, Sep 13, 2022 at 01:52:13AM +0200, Angel Iglesias wrote:

...

Quoted 10 lines
Quoted 10 lines
Quoted 9 lines

  *
https://ae-bst.resource.bosch.com/media/_tech/media/datasheets/BST-BMP180-DS000-121.pdf
  *
https://ae-bst.resource.bosch.com/media/_tech/media/datasheets/BST-BMP280-DS001-12.pdf
  *
https://ae-bst.resource.bosch.com/media/_tech/media/datasheets/BST-BME280_DS001-11.pdf
+ *
https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bmp388-ds001.pdf
  */

Quoted 4 lines
Quoted 2 lines

Shouldn't it be based on your patch to fix the links?

I thought of adding the patch fixing the links as a prerequisite commit, but in the end decided to keep the patchsets independent to avoid codependencies.

I see, then whatever Jonathan decides.

Signature · 2 lines
With Best Regards,
Andy Shevchenko
maintainer
#16 lore raw

Re: [PATCH v6 7/9] iio: pressure: bmp280: Add support for BMP380 sensor family

In reply to Angel Iglesias
Quoted 9 lines · On Tue, 13 Sep 2022 01:52:13 +0200 Angel Iglesias <[email protected]>…

Adds compatibility with the new generation of this sensor, the BMP380.

Includes basic sensor initialization to do pressure and temp measurements and allows tuning oversampling settings for each channel.

The compensation algorithms are adapted from the device datasheet and the repository https://github.com/BoschSensortec/BMP3-Sensor-API.

There is one place (around the reset handing) in here where I suspect we'll end up revisiting it because the matching by device ID is not particularly extensible to new devices.

Anyhow, can handle that at the time.

I had to hand apply parts of this because of the clash Andy raised. As a general rule it's better to keep one linear flow of patches unless they are on well separate parts of a driver. Saves me effort :) Here it was just one line to cut and paste, but you still get to now check I didn't mess that up ;)

Applied - please check result in testing branch of iio.git.

Note I plan to rebase that branch after the first pull request is accepted as I have some dependencies blocking other patches and a fast forward rebase is the easiest way to deal with those cleanly.

Jonathan

#17 lore raw

Re: [PATCH v6 7/9] iio: pressure: bmp280: Add support for BMP380 sensor family

Quoted 8 lines · Jonathan Cameron
Quoted 5 lines · On Tue, 13 Sep 2022 01:52:13 +0200 Angel Iglesias <[email protected]>…

Adds compatibility with the new generation of this sensor, the BMP380.

Includes basic sensor initialization to do pressure and temp measurements and allows tuning oversampling settings for each channel.

Quoted 7 lines
Quoted 4 lines

The compensation algorithms are adapted from the device datasheet and the repository https://github.com/BoschSensortec/BMP3-Sensor-API.

There is one place (around the reset handing) in here where I suspect we'll end up revisiting it because the matching by device ID is not particularly extensible to new devices.

Yeah, after the first time you raised that concern I've been thinking that maybe it would be better to add a new "init" or "preinit" callback executing first boot tasks for a sensor, such as this reset. Please, let me know how I can help with this matter. On the other hand, I'll have the BMP390 and BMP581 on my hands in a week or two. The BMP390 is almost the same regmap and operations as the BMP380, so I think it will be an easy addition. The BMP581 is a new beast that brings in lots of changes, but still has a good bunch of similarities.

Quoted 8 lines

Anyhow, can handle that at the time.

I had to hand apply parts of this because of the clash Andy raised.  As a general rule it's better to keep one linear flow of patches unless they are on well separate parts of a driver.  Saves me effort :)  Here it was just one line to cut and paste, but you still get to now check I didn't mess that up ;)

Sorry about that. Thanks to you and Andy for the extra patience with my messy patches.

Quoted 8 lines

Applied - please check result in testing branch of iio.git.

Note I plan to rebase that branch after the first pull request is accepted as I have some dependencies blocking other patches and a fast forward rebase is the easiest way to deal with those cleanly.

Jonathan

With kind regards,
Angel

maintainer
#18 lore raw

Re: [PATCH v6 7/9] iio: pressure: bmp280: Add support for BMP380 sensor family

Quoted 17 lines · On Sun, 18 Sep 2022 12:06:45 +0200 Angel Iglesias <[email protected]>…
Quoted 8 lines · Jonathan Cameron
Quoted 5 lines · On Tue, 13 Sep 2022 01:52:13 +0200 Angel Iglesias <[email protected]>…

Adds compatibility with the new generation of this sensor, the BMP380.

Includes basic sensor initialization to do pressure and temp measurements and allows tuning oversampling settings for each channel.

Quoted 7 lines
Quoted 4 lines

The compensation algorithms are adapted from the device datasheet and the repository https://github.com/BoschSensortec/BMP3-Sensor-API.

There is one place (around the reset handing) in here where I suspect we'll end up revisiting it because the matching by device ID is not particularly extensible to new devices.

Quoted 7 lines

Yeah, after the first time you raised that concern I've been thinking that maybe it would be better to add a new "init" or "preinit" callback executing first boot tasks for a sensor, such as this reset. Please, let me know how I can help with this matter. On the other hand, I'll have the BMP390 and BMP581 on my hands in a week or two. The BMP390 is almost the same regmap and operations as the BMP380, so I think it will be an easy addition. The BMP581 is a new beast that brings in lots of changes, but still has a good bunch of similarities.

Agreed, an .init()/.preinit() callback might make sense.

Given you are planning to look at new parts, perhaps wait until you have a series adding one of those rather than creating churn in the driver before that point. Perhaps the BMP581 will require changes in this area of the driver anyway and we don't want to end up changing it twice!

Thanks,

Jonathan

#19 lore raw

PATCH v6 8/9 dt-bindings: iio: pressure: bmp085: Add BMP380 compatible string

In reply to Angel Iglesias

Add bosch,bmp380 compatible string for the new family of sensors. This family includes the BMP380, BMP384 and BMP388. The register map in this family changes substantially and introduces new features but core concepts and operations carryover from the previous iterations

---
 Documentation/devicetree/bindings/iio/pressure/bmp085.yaml | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
Documentation/devicetree/bindings/iio/pressure/bmp085.yaml +3 -1
index 49257f9251e8..72cd2c2d3f17 100644
@@ -4,7 +4,7 @@
 $id: http://devicetree.org/schemas/iio/pressure/bmp085.yaml#
 $schema: http://devicetree.org/meta-schemas/core.yaml#
 
-title: BMP085/BMP180/BMP280/BME280 pressure iio sensors
+title: BMP085/BMP180/BMP280/BME280/BMP380 pressure iio sensors
 
 maintainers:
   - Andreas Klinger <[email protected]>
@@ -16,6 +16,7 @@ description: |
     https://www.bosch-sensortec.com/bst/products/all_products/bmp180
     https://www.bosch-sensortec.com/bst/products/all_products/bmp280
     https://www.bosch-sensortec.com/bst/products/all_products/bme280
+    https://www.bosch-sensortec.com/bst/products/all_products/bmp380
 
 properties:
   compatible:
@@ -24,6 +25,7 @@ properties:
       - bosch,bmp180
       - bosch,bmp280
       - bosch,bme280
+      - bosch,bmp380
 
   reg:
     maxItems: 1
Signature · 1 line
2.37.3
#20 lore raw

PATCH v6 9/9 iio: pressure: bmp280: Add more tunable config parameters for BMP380

In reply to Angel Iglesias

Allows sampling frequency and IIR filter coefficients configuration using sysfs ABI.

The IIR filter coefficient is configurable using the sysfs attribute "filter_low_pass_3db_frequency".

---
 drivers/iio/pressure/bmp280-core.c | 247 +++++++++++++++++++++++++++--
 drivers/iio/pressure/bmp280.h      |  18 ---
 2 files changed, 238 insertions(+), 27 deletions(-)
drivers/iio/pressure/bmp280-core.c +238 -9
index 19ac93bb1b83..743bc5a527f8 100644
@@ -103,6 +103,27 @@ static const char *const bmp280_supply_names[] = {
 
 #define BMP280_NUM_SUPPLIES ARRAY_SIZE(bmp280_supply_names)
 
+enum bmp380_odr {
+	BMP380_ODR_200HZ,
+	BMP380_ODR_100HZ,
+	BMP380_ODR_50HZ,
+	BMP380_ODR_25HZ,
+	BMP380_ODR_12_5HZ,
+	BMP380_ODR_6_25HZ,
+	BMP380_ODR_3_125HZ,
+	BMP380_ODR_1_5625HZ,
+	BMP380_ODR_0_78HZ,
+	BMP380_ODR_0_39HZ,
+	BMP380_ODR_0_2HZ,
+	BMP380_ODR_0_1HZ,
+	BMP380_ODR_0_05HZ,
+	BMP380_ODR_0_02HZ,
+	BMP380_ODR_0_01HZ,
+	BMP380_ODR_0_006HZ,
+	BMP380_ODR_0_003HZ,
+	BMP380_ODR_0_0015HZ,
+};
+
 struct bmp280_data {
 	struct device *dev;
 	struct mutex lock;
@@ -122,6 +143,17 @@ struct bmp280_data {
 	u8 oversampling_press;
 	u8 oversampling_temp;
 	u8 oversampling_humid;
+	u8 iir_filter_coeff;
+
+	/*
+	 * BMP380 devices introduce sampling frequency configuration. See
+	 * datasheet sections 3.3.3. and 4.3.19 for more details.
+	 *
+	 * BMx280 devices allowed indirect configuration of sampling frequency
+	 * changing the t_standby duration between measurements, as detailed on
+	 * section 3.6.3 of the datasheet.
+	 */
+	int sampling_freq;
 
 	/*
 	 * Carryover value from temperature conversion, used in pressure
@@ -149,6 +181,7 @@ struct bmp280_data {
 struct bmp280_chip_info {
 	unsigned int id_reg;
 
+	const struct iio_chan_spec *channels;
 	int num_channels;
 	unsigned int start_up_time;
 
@@ -164,6 +197,14 @@ struct bmp280_chip_info {
 	int num_oversampling_humid_avail;
 	int oversampling_humid_default;
 
+	const int *iir_filter_coeffs_avail;
+	int num_iir_filter_coeffs_avail;
+	int iir_filter_coeff_default;
+
+	const int (*sampling_freq_avail)[2];
+	int num_sampling_freq_avail;
+	int sampling_freq_default;
+
 	int (*chip_config)(struct bmp280_data *);
 	int (*read_temp)(struct bmp280_data *, int *);
 	int (*read_press)(struct bmp280_data *, int *, int *);
@@ -214,6 +255,30 @@ static const struct iio_chan_spec bmp280_channels[] = {
 	},
 };
 
+static const struct iio_chan_spec bmp380_channels[] = {
+	{
+		.type = IIO_PRESSURE,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
+				      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),
+	},
+	{
+		.type = IIO_TEMP,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
+				      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),
+	},
+	{
+		.type = IIO_HUMIDITYRELATIVE,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
+				      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),
+	},
+};
+
 static int bmp280_read_calib(struct bmp280_data *data)
 {
 	struct bmp280_calib *calib = &data->calib.bmp280;
@@ -544,6 +609,25 @@ static int bmp280_read_raw(struct iio_dev *indio_dev,
 			break;
 		}
 		break;
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		if (!data->chip_info->sampling_freq_avail) {
+			ret = -EINVAL;
+			break;
+		}
+
+		*val = data->chip_info->sampling_freq_avail[data->sampling_freq][0];
+		*val2 = data->chip_info->sampling_freq_avail[data->sampling_freq][1];
+		ret = IIO_VAL_INT_PLUS_MICRO;
+		break;
+	case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
+		if (!data->chip_info->iir_filter_coeffs_avail) {
+			ret = -EINVAL;
+			break;
+		}
+
+		*val = (1 << data->iir_filter_coeff) - 1;
+		ret = IIO_VAL_INT;
+		break;
 	default:
 		ret = -EINVAL;
 		break;
@@ -561,13 +645,21 @@ static int bmp280_write_oversampling_ratio_humid(struct bmp280_data *data,
 {
 	const int *avail = data->chip_info->oversampling_humid_avail;
 	const int n = data->chip_info->num_oversampling_humid_avail;
+	int ret, prev;
 	int i;
 
 	for (i = 0; i < n; i++) {
 		if (avail[i] == val) {
+			prev = data->oversampling_humid;
 			data->oversampling_humid = ilog2(val);
 
-			return data->chip_info->chip_config(data);
+			ret = data->chip_info->chip_config(data);
+			if (ret) {
+				data->oversampling_humid = prev;
+				data->chip_info->chip_config(data);
+				return ret;
+			}
+			return 0;
 		}
 	}
 	return -EINVAL;
@@ -578,13 +670,21 @@ static int bmp280_write_oversampling_ratio_temp(struct bmp280_data *data,
 {
 	const int *avail = data->chip_info->oversampling_temp_avail;
 	const int n = data->chip_info->num_oversampling_temp_avail;
+	int ret, prev;
 	int i;
 
 	for (i = 0; i < n; i++) {
 		if (avail[i] == val) {
+			prev = data->oversampling_temp;
 			data->oversampling_temp = ilog2(val);
 
-			return data->chip_info->chip_config(data);
+			ret = data->chip_info->chip_config(data);
+			if (ret) {
+				data->oversampling_temp = prev;
+				data->chip_info->chip_config(data);
+				return ret;
+			}
+			return 0;
 		}
 	}
 	return -EINVAL;
@@ -595,13 +695,71 @@ static int bmp280_write_oversampling_ratio_press(struct bmp280_data *data,
 {
 	const int *avail = data->chip_info->oversampling_press_avail;
 	const int n = data->chip_info->num_oversampling_press_avail;
+	int ret, prev;
 	int i;
 
 	for (i = 0; i < n; i++) {
 		if (avail[i] == val) {
+			prev = data->oversampling_press;
 			data->oversampling_press = ilog2(val);
 
-			return data->chip_info->chip_config(data);
+			ret = data->chip_info->chip_config(data);
+			if (ret) {
+				data->oversampling_press = prev;
+				data->chip_info->chip_config(data);
+				return ret;
+			}
+			return 0;
+		}
+	}
+	return -EINVAL;
+}
+
+static int bmp280_write_sampling_frequency(struct bmp280_data *data,
+					   int val, int val2)
+{
+	const int (*avail)[2] = data->chip_info->sampling_freq_avail;
+	const int n = data->chip_info->num_sampling_freq_avail;
+	int ret, prev;
+	int i;
+
+	for (i = 0; i < n; i++) {
+		if (avail[i][0] == val && avail[i][1] == val2) {
+			prev = data->sampling_freq;
+			data->sampling_freq = i;
+
+			ret = data->chip_info->chip_config(data);
+			if (ret) {
+				data->sampling_freq = prev;
+				data->chip_info->chip_config(data);
+				return ret;
+			}
+			return 0;
+		}
+	}
+	return -EINVAL;
+}
+
+static int bmp280_write_iir_filter_coeffs(struct bmp280_data *data, int val)
+{
+	const int *avail = data->chip_info->iir_filter_coeffs_avail;
+	const int n = data->chip_info->num_iir_filter_coeffs_avail;
+	int ret, prev;
+	int i;
+
+	for (i = 0; i < n; i++) {
+		if (avail[i] - 1  == val) {
+			prev = data->iir_filter_coeff;
+			data->iir_filter_coeff = i;
+
+			ret = data->chip_info->chip_config(data);
+			if (ret) {
+				data->iir_filter_coeff = prev;
+				data->chip_info->chip_config(data);
+				return ret;
+
+			}
+			return 0;
 		}
 	}
 	return -EINVAL;
@@ -614,6 +772,12 @@ static int bmp280_write_raw(struct iio_dev *indio_dev,
 	struct bmp280_data *data = iio_priv(indio_dev);
 	int ret = 0;
 
+	/*
+	 * Helper functions to update sensor running configuration.
+	 * If an error happens applying new settings, will try restore
+	 * previous parameters to ensure the sensor is left in a known
+	 * working configuration.
+	 */
 	switch (mask) {
 	case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
 		pm_runtime_get_sync(data->dev);
@@ -636,6 +800,22 @@ static int bmp280_write_raw(struct iio_dev *indio_dev,
 		pm_runtime_mark_last_busy(data->dev);
 		pm_runtime_put_autosuspend(data->dev);
 		break;
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		pm_runtime_get_sync(data->dev);
+		mutex_lock(&data->lock);
+		ret = bmp280_write_sampling_frequency(data, val, val2);
+		mutex_unlock(&data->lock);
+		pm_runtime_mark_last_busy(data->dev);
+		pm_runtime_put_autosuspend(data->dev);
+		break;
+	case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
+		pm_runtime_get_sync(data->dev);
+		mutex_lock(&data->lock);
+		ret = bmp280_write_iir_filter_coeffs(data, val);
+		mutex_unlock(&data->lock);
+		pm_runtime_mark_last_busy(data->dev);
+		pm_runtime_put_autosuspend(data->dev);
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -666,6 +846,17 @@ static int bmp280_read_avail(struct iio_dev *indio_dev,
 		}
 		*type = IIO_VAL_INT;
 		return IIO_AVAIL_LIST;
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		*vals = (const int *)data->chip_info->sampling_freq_avail;
+		*type = IIO_VAL_INT_PLUS_MICRO;
+		/* Values are stored in a 2D matrix */
+		*length = data->chip_info->num_sampling_freq_avail;
+		return IIO_AVAIL_LIST;
+	case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
+		*vals = data->chip_info->iir_filter_coeffs_avail;
+		*type = IIO_VAL_INT;
+		*length = data->chip_info->num_iir_filter_coeffs_avail;
+		return IIO_AVAIL_LIST;
 	default:
 		return -EINVAL;
 	}
@@ -711,6 +902,7 @@ static const int bmp280_oversampling_avail[] = { 1, 2, 4, 8, 16 };
 static const struct bmp280_chip_info bmp280_chip_info = {
 	.id_reg = BMP280_REG_ID,
 	.start_up_time = 2000,
+	.channels = bmp280_channels,
 	.num_channels = 2,
 
 	.oversampling_temp_avail = bmp280_oversampling_avail,
@@ -758,6 +950,7 @@ static int bme280_chip_config(struct bmp280_data *data)
 static const struct bmp280_chip_info bme280_chip_info = {
 	.id_reg = BMP280_REG_ID,
 	.start_up_time = 2000,
+	.channels = bmp280_channels,
 	.num_channels = 3,
 
 	.oversampling_temp_avail = bmp280_oversampling_avail,
@@ -997,6 +1190,27 @@ static int bmp380_read_calib(struct bmp280_data *data)
 	return 0;
 }
 
+static const int bmp380_odr_table[][2] = {
+	[BMP380_ODR_200HZ]	= {200, 0},
+	[BMP380_ODR_100HZ]	= {100, 0},
+	[BMP380_ODR_50HZ]	= {50, 0},
+	[BMP380_ODR_25HZ]	= {25, 0},
+	[BMP380_ODR_12_5HZ]	= {12, 500000},
+	[BMP380_ODR_6_25HZ]	= {6, 250000},
+	[BMP380_ODR_3_125HZ]	= {3, 125000},
+	[BMP380_ODR_1_5625HZ]	= {1, 562500},
+	[BMP380_ODR_0_78HZ]	= {0, 781250},
+	[BMP380_ODR_0_39HZ]	= {0, 390625},
+	[BMP380_ODR_0_2HZ]	= {0, 195313},
+	[BMP380_ODR_0_1HZ]	= {0, 97656},
+	[BMP380_ODR_0_05HZ]	= {0, 48828},
+	[BMP380_ODR_0_02HZ]	= {0, 24414},
+	[BMP380_ODR_0_01HZ]	= {0, 12207},
+	[BMP380_ODR_0_006HZ]	= {0, 6104},
+	[BMP380_ODR_0_003HZ]	= {0, 3052},
+	[BMP380_ODR_0_0015HZ]	= {0, 1526},
+};
+
 static int bmp380_chip_config(struct bmp280_data *data)
 {
 	bool change = false, aux;
@@ -1030,21 +1244,23 @@ static int bmp380_chip_config(struct bmp280_data *data)
 	change = change || aux;
 
 	/* Configure output data rate */
-	ret = regmap_update_bits(data->regmap, BMP380_REG_ODR,
-				 BMP380_ODRS_MASK, BMP380_ODRS_50HZ);
+	ret = regmap_update_bits_check(data->regmap, BMP380_REG_ODR,
+				       BMP380_ODRS_MASK, data->sampling_freq, &aux);
 	if (ret) {
 		dev_err(data->dev, "failed to write ODR selection register\n");
 		return ret;
 	}
+	change = change || aux;
 
 	/* Set filter data */
-	ret = regmap_update_bits(data->regmap, BMP380_REG_CONFIG,
-				 BMP380_FILTER_MASK,
-				 FIELD_PREP(BMP380_FILTER_MASK, BMP380_FILTER_3X));
+	ret = regmap_update_bits_check(data->regmap, BMP380_REG_CONFIG, BMP380_FILTER_MASK,
+				       FIELD_PREP(BMP380_FILTER_MASK, data->iir_filter_coeff),
+				       &aux);
 	if (ret) {
 		dev_err(data->dev, "failed to write config register\n");
 		return ret;
 	}
+	change = change || aux;
 
 	if (change) {
 		/*
@@ -1095,10 +1311,12 @@ static int bmp380_chip_config(struct bmp280_data *data)
 }
 
 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 struct bmp280_chip_info bmp380_chip_info = {
 	.id_reg = BMP380_REG_ID,
 	.start_up_time = 2000,
+	.channels = bmp380_channels,
 	.num_channels = 2,
 
 	.oversampling_temp_avail = bmp380_oversampling_avail,
@@ -1109,6 +1327,14 @@ static const struct bmp280_chip_info bmp380_chip_info = {
 	.num_oversampling_press_avail = ARRAY_SIZE(bmp380_oversampling_avail),
 	.oversampling_press_default = ilog2(4),
 
+	.sampling_freq_avail = bmp380_odr_table,
+	.num_sampling_freq_avail = ARRAY_SIZE(bmp380_odr_table) * 2,
+	.sampling_freq_default = BMP380_ODR_50HZ,
+
+	.iir_filter_coeffs_avail = bmp380_iir_filter_coeffs_avail,
+	.num_iir_filter_coeffs_avail = ARRAY_SIZE(bmp380_iir_filter_coeffs_avail),
+	.iir_filter_coeff_default = 2,
+
 	.chip_config = bmp380_chip_config,
 	.read_temp = bmp380_read_temp,
 	.read_press = bmp380_read_press,
@@ -1350,6 +1576,7 @@ static const int bmp180_oversampling_press_avail[] = { 1, 2, 4, 8 };
 static const struct bmp280_chip_info bmp180_chip_info = {
 	.id_reg = BMP280_REG_ID,
 	.start_up_time = 2000,
+	.channels = bmp280_channels,
 	.num_channels = 2,
 
 	.oversampling_temp_avail = bmp180_oversampling_temp_avail,
@@ -1448,7 +1675,6 @@ int bmp280_common_probe(struct device *dev,
 	data->dev = dev;
 
 	indio_dev->name = name;
-	indio_dev->channels = bmp280_channels;
 	indio_dev->info = &bmp280_info;
 	indio_dev->modes = INDIO_DIRECT_MODE;
 
@@ -1471,10 +1697,13 @@ int bmp280_common_probe(struct device *dev,
 	data->chip_info = chip_info;
 
 	/* Apply initial values from chip info structure */
+	indio_dev->channels = chip_info->channels;
 	indio_dev->num_channels = chip_info->num_channels;
 	data->oversampling_press = chip_info->oversampling_press_default;
 	data->oversampling_humid = chip_info->oversampling_humid_default;
 	data->oversampling_temp = chip_info->oversampling_temp_default;
+	data->iir_filter_coeff = chip_info->iir_filter_coeff_default;
+	data->sampling_freq = chip_info->sampling_freq_default;
 	data->start_up_time = chip_info->start_up_time;
 
 	/* Bring up regulators */
drivers/iio/pressure/bmp280.h +0 -18
index b546d7727a96..c791325c7416 100644
@@ -54,24 +54,6 @@
 #define BMP380_OSRS_PRESS_MASK		GENMASK(2, 0)
 
 #define BMP380_ODRS_MASK		GENMASK(4, 0)
-#define BMP380_ODRS_200HZ		0x00
-#define BMP380_ODRS_100HZ		0x01
-#define BMP380_ODRS_50HZ		0x02
-#define BMP380_ODRS_25HZ		0x03
-#define BMP380_ODRS_12_5HZ		0x04
-#define BMP380_ODRS_6_25HZ		0x05
-#define BMP380_ODRS_3_1HZ		0x06
-#define BMP380_ODRS_1_5HZ		0x07
-#define BMP380_ODRS_0_78HZ		0x08
-#define BMP380_ODRS_0_39HZ		0x09
-#define BMP380_ODRS_0_2HZ		0x0A
-#define BMP380_ODRS_0_1HZ		0x0B
-#define BMP380_ODRS_0_05HZ		0x0C
-#define BMP380_ODRS_0_02HZ		0x0D
-#define BMP380_ODRS_0_01HZ		0x0E
-#define BMP380_ODRS_0_006HZ		0x0F
-#define BMP380_ODRS_0_003HZ		0x10
-#define BMP380_ODRS_0_0015HZ		0x11
 
 #define BMP380_CTRL_SENSORS_MASK	GENMASK(1, 0)
 #define BMP380_CTRL_SENSORS_PRESS_EN	BIT(0)
Signature · 1 line
2.37.3
maintainer Applied
#21 lore raw

Re: [PATCH v6 9/9] iio: pressure: bmp280: Add more tunable config parameters for BMP380

Quoted 7 lines · On Tue, 13 Sep 2022 01:54:42 +0200 Angel Iglesias <[email protected]>…

Allows sampling frequency and IIR filter coefficients configuration using sysfs ABI.

The IIR filter coefficient is configurable using the sysfs attribute "filter_low_pass_3db_frequency".

Applied to the togreg branch of iio.git and initially pushed out as testing for the autobuilders to poke at it.

Thanks,

Jonathan