All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v5 0/5] Add support for pressure sensor Bosch BMP380
@ 2022-08-07 11:52 Angel Iglesias
  2022-08-07 11:54 ` [PATCH v5 1/5] iio: pressure: bmp280: simplify driver initialization logic Angel Iglesias
                   ` (4 more replies)
  0 siblings, 5 replies; 22+ messages in thread
From: Angel Iglesias @ 2022-08-07 11:52 UTC (permalink / raw)
  To: linux-iio
  Cc: Jonathan Cameron, Lars-Peter Clausen, Paul Cercueil, Ulf Hansson,
	Rafael J. Wysocki, linux-kernel

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

Patch 1 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 2 fixes DMA unsafe regmap_bulk_* calls reported by Jonathan Cameron
<jic23@kernel.org>.
Patch 3 adds the basic logic to initialize and read measurements from
the sensor.
Patch 4 adds references and sensor id to the devicetree bindings docs.
Patch 5 adds advanced configurable features such as sampling frequency
and IIR filter through the IIO sysfs ABI.

Changes in v5:
 - Moved dt bindings patch (previously patch 2/5) to 4/5 to preserve
    tree coherence as suggested by Jonathan Cameron <jic23@kernel.org>
 - 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 <jic23@kernel.org>.
 - Patch 3: Fixed small typos
 - Patch 3: Fixed incompatible division on 32-bit machines reported by
    Andy Shevchenko <andy.shevchenko@gmail.com> and kernel test robot
    <lkp@intel.com>.
 - 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 <jic23@kernel.org>.
 - Patch 4: Fixed DMA unsafe buffers used on regmap_bulk_* calls reported
    by Jonathan Cameron <jic23@kernel.org>.

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 <dan.carpenter@oracle.com>.
 - Patch 5: Fixed formatting and typos on multiple comments.
 - Patch 5: Fixed missing boolean initialization reported by
    Andy Shevchenko <andy.shevchenko@gmail.com>.
 - 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 <jic23@kernel.org>
    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/cover.1658597501.git.ang.iglesiasg@gmail.com/

Angel Iglesias (5):
  iio: pressure: bmp280: simplify driver initialization logic
  iio: pressure: bmp280: Fix alignment for DMA safety
  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            | 866 +++++++++++++++---
 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                 | 159 +++-
 7 files changed, 952 insertions(+), 148 deletions(-)


base-commit: 180c6cb6b9b79c55b79e8414f4c0208f2463af7d
-- 
2.37.1


^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH v5 1/5] iio: pressure: bmp280: simplify driver initialization logic
  2022-08-07 11:52 [PATCH v5 0/5] Add support for pressure sensor Bosch BMP380 Angel Iglesias
@ 2022-08-07 11:54 ` Angel Iglesias
  2022-08-08  8:18   ` Andy Shevchenko
  2022-08-14 13:43   ` Jonathan Cameron
  2022-08-07 11:55 ` [PATCH v5 2/5] iio: pressure: bmp280: Fix alignment for DMA safety Angel Iglesias
                   ` (3 subsequent siblings)
  4 siblings, 2 replies; 22+ messages in thread
From: Angel Iglesias @ 2022-08-07 11:54 UTC (permalink / raw)
  To: linux-iio
  Cc: Jonathan Cameron, Lars-Peter Clausen, Ulf Hansson,
	Rafael J. Wysocki, Paul Cercueil, linux-kernel

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.

Revised BMP180 and BMP280 definitions and code functions to use GENMASK
and FIELD_PREP/FIELD_GET utilities to homogenize structure with more
recent drivers, in preparation for the patches adding support for the
BMP380 sensors.

Suggested-by: Jonathan Cameron <jic23@kernel.org>
Signed-off-by: Angel Iglesias <ang.iglesiasg@gmail.com>
---
 drivers/iio/pressure/bmp280-core.c | 120 ++++++++++++++++++-----------
 drivers/iio/pressure/bmp280.h      |  73 +++++++++---------
 2 files changed, 113 insertions(+), 80 deletions(-)

diff --git a/drivers/iio/pressure/bmp280-core.c b/drivers/iio/pressure/bmp280-core.c
index fe7aa81e7cc9..a109c2609896 100644
--- a/drivers/iio/pressure/bmp280-core.c
+++ b/drivers/iio/pressure/bmp280-core.c
@@ -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>
@@ -107,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 *, unsigned int);
 };
 
 /*
@@ -147,15 +158,14 @@ 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, unsigned int chip)
 {
 	int ret;
 	unsigned int tmp;
 	__le16 l16;
 	__be16 b16;
 	struct device *dev = data->dev;
+	struct bmp280_calib *calib = &data->calib.bmp280;
 	__le16 t_buf[BMP280_COMP_TEMP_REG_COUNT / 2];
 	__le16 p_buf[BMP280_COMP_PRESS_REG_COUNT / 2];
 
@@ -611,8 +621,8 @@ 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);
+	u8 osrs = FIELD_PREP(BMP280_OSRS_TEMP_MASK, data->oversampling_temp + 1) |
+		  FIELD_PREP(BMP280_OSRS_PRESS_MASK, data->oversampling_press + 1);
 
 	ret = regmap_write_bits(data->regmap, BMP280_REG_CTRL_MEAS,
 				 BMP280_OSRS_TEMP_MASK |
@@ -640,21 +650,38 @@ 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)
 {
 	int ret;
-	u8 osrs = BMP280_OSRS_HUMIDITIY_X(data->oversampling_humid + 1);
+	u8 osrs = FIELD_PREP(BMP280_OSRS_HUMIDITY_MASK, data->oversampling_humid + 1);
 
 	/*
 	 * Oversampling of humidity must be set before oversampling of
@@ -670,19 +697,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 = bmp280_read_calib,
 };
 
 static int bmp180_measure(struct bmp280_data *data, u8 ctrl_meas)
@@ -710,7 +745,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 =
@@ -735,7 +770,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;
 
@@ -748,11 +785,11 @@ 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, unsigned int chip)
 {
 	int ret;
 	int i;
+	struct bmp180_calib *calib = &data->calib.bmp180;
 	__be16 buf[BMP180_REG_CALIB_COUNT / 2];
 
 	ret = regmap_bulk_read(data->regmap, BMP180_REG_CALIB_START, buf,
@@ -832,7 +869,10 @@ static int bmp180_read_adc_press(struct bmp280_data *data, int *val)
 	__be32 tmp = 0;
 	u8 oss = data->oversampling_press;
 
-	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;
 
@@ -913,17 +953,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)
@@ -993,6 +1040,7 @@ int bmp280_common_probe(struct device *dev,
 	int ret;
 	struct iio_dev *indio_dev;
 	struct bmp280_data *data;
+	const struct bmp280_chip_info *chip_info;
 	unsigned int chip_id;
 	struct gpio_desc *gpiod;
 
@@ -1011,30 +1059,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,
@@ -1071,7 +1114,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) {
@@ -1091,21 +1135,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, chip_id);
+	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
diff --git a/drivers/iio/pressure/bmp280.h b/drivers/iio/pressure/bmp280.h
index 57ba0e85db91..5a19c7d04804 100644
--- a/drivers/iio/pressure/bmp280.h
+++ b/drivers/iio/pressure/bmp280.h
@@ -32,44 +32,41 @@
 #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_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 +76,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
-- 
2.37.1


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v5 2/5] iio: pressure: bmp280: Fix alignment for DMA safety
  2022-08-07 11:52 [PATCH v5 0/5] Add support for pressure sensor Bosch BMP380 Angel Iglesias
  2022-08-07 11:54 ` [PATCH v5 1/5] iio: pressure: bmp280: simplify driver initialization logic Angel Iglesias
@ 2022-08-07 11:55 ` Angel Iglesias
  2022-08-08  8:53   ` Andy Shevchenko
  2022-08-14 14:03   ` Jonathan Cameron
  2022-08-07 11:55 ` [PATCH v5 3/5] iio: pressure: bmp280: Add support for BMP380 sensor family Angel Iglesias
                   ` (2 subsequent siblings)
  4 siblings, 2 replies; 22+ messages in thread
From: Angel Iglesias @ 2022-08-07 11:55 UTC (permalink / raw)
  To: linux-iio
  Cc: Jonathan Cameron, Lars-Peter Clausen, Paul Cercueil, Ulf Hansson,
	Rafael J. Wysocki, linux-kernel

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 new,
DMA-safe, buffers.

Suggested-by: Jonathan Cameron <jic23@kernel.org>
Signed-off-by: Angel Iglesias <ang.iglesiasg@gmail.com>
---
 drivers/iio/pressure/bmp280-core.c | 122 ++++++++++++++---------------
 drivers/iio/pressure/bmp280.h      |   3 +
 2 files changed, 64 insertions(+), 61 deletions(-)

diff --git a/drivers/iio/pressure/bmp280-core.c b/drivers/iio/pressure/bmp280-core.c
index a109c2609896..4cd657dcbfed 100644
--- a/drivers/iio/pressure/bmp280-core.c
+++ b/drivers/iio/pressure/bmp280-core.c
@@ -31,6 +31,7 @@
 #include <linux/completion.h>
 #include <linux/pm_runtime.h>
 #include <linux/random.h>
+#include <asm/unaligned.h>
 
 #include "bmp280.h"
 
@@ -106,6 +107,18 @@ 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 data[3];
+		/* calibration data buffers */
+		__le16 bmp280_cal[BMP280_CONTIGUOUS_CALIB_REGS / 2];
+		__be16 bmp180_cal[BMP180_REG_CALIB_COUNT / 2];
+	} buf __aligned(IIO_DMA_MINALIGN);
 };
 
 struct bmp280_chip_info {
@@ -162,41 +175,29 @@ static int bmp280_read_calib(struct bmp280_data *data, unsigned int chip)
 {
 	int ret;
 	unsigned int tmp;
-	__le16 l16;
-	__be16 b16;
 	struct device *dev = data->dev;
+	__le16 *t_buf = data->buf.bmp280_cal;
+	__le16 *p_buf = &data->buf.bmp280_cal[T3+1];
 	struct bmp280_calib *calib = &data->calib.bmp280;
-	__le16 t_buf[BMP280_COMP_TEMP_REG_COUNT / 2];
-	__le16 p_buf[BMP280_COMP_PRESS_REG_COUNT / 2];
 
 	/* Read temperature calibration values. */
 	ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_TEMP_START,
-			       t_buf, BMP280_COMP_TEMP_REG_COUNT);
+			       data->buf.bmp280_cal, sizeof(data->buf.bmp280_cal));
 	if (ret < 0) {
 		dev_err(data->dev,
 			"failed to read temperature calibration parameters\n");
 		return ret;
 	}
 
-	/* Toss the temperature calibration data into the entropy pool */
-	add_device_randomness(t_buf, sizeof(t_buf));
+	/* Toss the temperature and pressure calibration data into the entropy pool */
+	add_device_randomness(data->buf.bmp280_cal, sizeof(data->buf.bmp280_cal));
 
+	/* parse temperature calibration data */
 	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));
-
+	/* parse pressure calibration data */
 	calib->P1 = le16_to_cpu(p_buf[P1]);
 	calib->P2 = le16_to_cpu(p_buf[P2]);
 	calib->P3 = le16_to_cpu(p_buf[P3]);
@@ -224,12 +225,12 @@ static int bmp280_read_calib(struct bmp280_data *data, unsigned int chip)
 	}
 	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->buf.data, 2);
 	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 = get_unaligned_le16(data->buf.data);
 
 	ret = regmap_read(data->regmap, BMP280_REG_COMP_H3, &tmp);
 	if (ret < 0) {
@@ -238,20 +239,20 @@ static int bmp280_read_calib(struct bmp280_data *data, unsigned int chip)
 	}
 	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->buf.data, 2);
 	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(((get_unaligned_be16(data->buf.data) >> 4) & 0xff0) |
+				  (get_unaligned_be16(data->buf.data) & 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->buf.data, 2);
 	if (ret < 0) {
 		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(((get_unaligned_le16(data->buf.data) >> 4) & 0xfff), 11);
 
 	ret = regmap_read(data->regmap, BMP280_REG_COMP_H6, &tmp);
 	if (ret < 0) {
@@ -346,16 +347,16 @@ static int bmp280_read_temp(struct bmp280_data *data,
 			    int *val)
 {
 	int ret;
-	__be32 tmp = 0;
 	s32 adc_temp, comp_temp;
 
-	ret = regmap_bulk_read(data->regmap, BMP280_REG_TEMP_MSB, &tmp, 3);
+	ret = regmap_bulk_read(data->regmap, BMP280_REG_TEMP_MSB,
+			       data->buf.data, sizeof(data->buf.data));
 	if (ret < 0) {
 		dev_err(data->dev, "failed to read temperature\n");
 		return ret;
 	}
 
-	adc_temp = be32_to_cpu(tmp) >> 12;
+	adc_temp = get_unaligned_be24(data->buf.data) >> 4;
 	if (adc_temp == BMP280_TEMP_SKIPPED) {
 		/* reading was skipped */
 		dev_err(data->dev, "reading temperature skipped\n");
@@ -379,7 +380,6 @@ static int bmp280_read_press(struct bmp280_data *data,
 			     int *val, int *val2)
 {
 	int ret;
-	__be32 tmp = 0;
 	s32 adc_press;
 	u32 comp_press;
 
@@ -388,13 +388,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.data, sizeof(data->buf.data));
 	if (ret < 0) {
 		dev_err(data->dev, "failed to read pressure\n");
 		return ret;
 	}
 
-	adc_press = be32_to_cpu(tmp) >> 12;
+	adc_press = get_unaligned_be24(data->buf.data) >> 4;
 	if (adc_press == BMP280_PRESS_SKIPPED) {
 		/* reading was skipped */
 		dev_err(data->dev, "reading pressure skipped\n");
@@ -410,7 +411,6 @@ static int bmp280_read_press(struct bmp280_data *data,
 
 static int bmp280_read_humid(struct bmp280_data *data, int *val, int *val2)
 {
-	__be16 tmp;
 	int ret;
 	s32 adc_humidity;
 	u32 comp_humidity;
@@ -420,13 +420,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->buf.data, 2);
 	if (ret < 0) {
 		dev_err(data->dev, "failed to read humidity\n");
 		return ret;
 	}
 
-	adc_humidity = be16_to_cpu(tmp);
+	adc_humidity = get_unaligned_be16(data->buf.data);
 	if (adc_humidity == BMP280_HUMIDITY_SKIPPED) {
 		/* reading was skipped */
 		dev_err(data->dev, "reading humidity skipped\n");
@@ -767,7 +768,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,
@@ -776,48 +776,48 @@ 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->buf.data, 2);
 	if (ret)
 		return ret;
 
-	*val = be16_to_cpu(tmp);
+	*val = get_unaligned_be16(data->buf.data);
 
 	return 0;
 }
 
 static int bmp180_read_calib(struct bmp280_data *data, unsigned int chip)
 {
+	struct bmp180_calib *calib = &data->calib.bmp180;
 	int ret;
 	int i;
-	struct bmp180_calib *calib = &data->calib.bmp180;
-	__be16 buf[BMP180_REG_CALIB_COUNT / 2];
 
-	ret = regmap_bulk_read(data->regmap, BMP180_REG_CALIB_START, buf,
-			       sizeof(buf));
+	ret = regmap_bulk_read(data->regmap, BMP180_REG_CALIB_START,
+			       data->buf.bmp180_cal, sizeof(data->buf.bmp180_cal));
 
 	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->buf.bmp180_cal); i++) {
+		if (data->buf.bmp180_cal[i] == cpu_to_be16(0) ||
+		    data->buf.bmp180_cal[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->buf.bmp180_cal, sizeof(data->buf.bmp180_cal));
+
+	calib->AC1 = be16_to_cpu(data->buf.bmp180_cal[AC1]);
+	calib->AC2 = be16_to_cpu(data->buf.bmp180_cal[AC2]);
+	calib->AC3 = be16_to_cpu(data->buf.bmp180_cal[AC3]);
+	calib->AC4 = be16_to_cpu(data->buf.bmp180_cal[AC4]);
+	calib->AC5 = be16_to_cpu(data->buf.bmp180_cal[AC5]);
+	calib->AC6 = be16_to_cpu(data->buf.bmp180_cal[AC6]);
+	calib->B1 = be16_to_cpu(data->buf.bmp180_cal[B1]);
+	calib->B2 = be16_to_cpu(data->buf.bmp180_cal[B2]);
+	calib->MB = be16_to_cpu(data->buf.bmp180_cal[MB]);
+	calib->MC = be16_to_cpu(data->buf.bmp180_cal[MC]);
+	calib->MD = be16_to_cpu(data->buf.bmp180_cal[MD]);
 
 	return 0;
 }
@@ -865,9 +865,8 @@ 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;
+	int ret;
 
 	ret = bmp180_measure(data,
 			     FIELD_PREP(BMP180_MEAS_CTRL_MASK, BMP180_MEAS_PRESS) |
@@ -876,11 +875,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.data, sizeof(data->buf.data));
 	if (ret)
 		return ret;
 
-	*val = (be32_to_cpu(tmp) >> 8) >> (8 - oss);
+	*val = get_unaligned_be24(data->buf.data) >> (8 - oss);
 
 	return 0;
 }
diff --git a/drivers/iio/pressure/bmp280.h b/drivers/iio/pressure/bmp280.h
index 5a19c7d04804..c036c7835004 100644
--- a/drivers/iio/pressure/bmp280.h
+++ b/drivers/iio/pressure/bmp280.h
@@ -32,6 +32,9 @@
 #define BMP280_REG_COMP_PRESS_START	0x8E
 #define BMP280_COMP_PRESS_REG_COUNT	18
 
+#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
-- 
2.37.1


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v5 3/5] iio: pressure: bmp280: Add support for BMP380 sensor family
  2022-08-07 11:52 [PATCH v5 0/5] Add support for pressure sensor Bosch BMP380 Angel Iglesias
  2022-08-07 11:54 ` [PATCH v5 1/5] iio: pressure: bmp280: simplify driver initialization logic Angel Iglesias
  2022-08-07 11:55 ` [PATCH v5 2/5] iio: pressure: bmp280: Fix alignment for DMA safety Angel Iglesias
@ 2022-08-07 11:55 ` Angel Iglesias
  2022-08-08  9:08   ` Andy Shevchenko
  2022-08-14 14:15   ` Jonathan Cameron
  2022-08-07 11:56 ` [PATCH v5 4/5] dt-bindings: iio: pressure: bmp085: Add BMP380 compatible string Angel Iglesias
  2022-08-07 11:57 ` [PATCH v5 5/5] iio: pressure: bmp280: Add more tunable config parameters for BMP380 Angel Iglesias
  4 siblings, 2 replies; 22+ messages in thread
From: Angel Iglesias @ 2022-08-07 11:55 UTC (permalink / raw)
  To: linux-iio
  Cc: Jonathan Cameron, Lars-Peter Clausen, Andy Shevchenko,
	Nikita Yushchenko, Ulf Hansson, Rafael J. Wysocki, Paul Cercueil,
	linux-kernel

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

Signed-off-by: Angel Iglesias <ang.iglesiasg@gmail.com>
---
 drivers/iio/pressure/Kconfig         |   6 +-
 drivers/iio/pressure/bmp280-core.c   | 354 +++++++++++++++++++++++++++
 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, 523 insertions(+), 3 deletions(-)

diff --git a/drivers/iio/pressure/Kconfig b/drivers/iio/pressure/Kconfig
index 0ff756cea63a..c9453389e4f7 100644
--- a/drivers/iio/pressure/Kconfig
+++ b/drivers/iio/pressure/Kconfig
@@ -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
diff --git a/drivers/iio/pressure/bmp280-core.c b/drivers/iio/pressure/bmp280-core.c
index 4cd657dcbfed..fe171908a89c 100644
--- a/drivers/iio/pressure/bmp280-core.c
+++ b/drivers/iio/pressure/bmp280-core.c
@@ -12,6 +12,7 @@
  * 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
  */
 
 #define pr_fmt(fmt) "bmp280: " fmt
@@ -77,6 +78,24 @@ struct bmp280_calib {
 	s8  H6;
 };
 
+/* See datasheet Section 3.11.1. */
+struct bmp380_calib {
+	u16 T1;
+	u16 T2;
+	s8  T3;
+	s16 P1;
+	s16 P2;
+	s8  P3;
+	s8  P4;
+	u16 P5;
+	u16 P6;
+	s8  P7;
+	s8  P8;
+	s16 P9;
+	s8  P10;
+	s8  P11;
+};
+
 static const char *const bmp280_supply_names[] = {
 	"vddd", "vdda"
 };
@@ -93,6 +112,7 @@ struct bmp280_data {
 	union {
 		struct bmp180_calib bmp180;
 		struct bmp280_calib bmp280;
+		struct bmp380_calib bmp380;
 	} calib;
 	struct regulator_bulk_data supplies[BMP280_NUM_SUPPLIES];
 	unsigned int start_up_time; /* in microseconds */
@@ -118,6 +138,7 @@ struct bmp280_data {
 		/* calibration data buffers */
 		__le16 bmp280_cal[BMP280_CONTIGUOUS_CALIB_REGS / 2];
 		__be16 bmp180_cal[BMP180_REG_CALIB_COUNT / 2];
+		u8 bmp380_cal[BMP380_CALIB_REG_COUNT];
 	} buf __aligned(IIO_DMA_MINALIGN);
 };
 
@@ -153,6 +174,25 @@ struct bmp280_chip_info {
 enum { T1, T2, T3 };
 enum { P1, P2, P3, P4, P5, P6, P7, P8, P9 };
 
+enum {
+	/* Temperature calib indexes */
+	BMP380_T1 = 0,
+	BMP380_T2 = 2,
+	BMP380_T3 = 4,
+	/* Pressure calib indexes */
+	BMP380_P1 = 5,
+	BMP380_P2 = 7,
+	BMP380_P3 = 9,
+	BMP380_P4 = 10,
+	BMP380_P5 = 11,
+	BMP380_P6 = 13,
+	BMP380_P7 = 15,
+	BMP380_P8 = 16,
+	BMP380_P9 = 17,
+	BMP380_P10 = 19,
+	BMP380_P11 = 20,
+};
+
 static const struct iio_chan_spec bmp280_channels[] = {
 	{
 		.type = IIO_PRESSURE,
@@ -721,6 +761,310 @@ static const struct bmp280_chip_info bme280_chip_info = {
 	.read_calib = bmp280_read_calib,
 };
 
+/* Send a command to BMP3XX sensors */
+static int bmp380_cmd(struct bmp280_data *data, u8 cmd)
+{
+	int ret;
+	unsigned int reg;
+
+	/* check if device is ready to process a command */
+	ret = regmap_read(data->regmap, BMP380_REG_STATUS, &reg);
+	if (ret) {
+		dev_err(data->dev, "failed to read error register\n");
+		return ret;
+	}
+	if (!(reg & BMP380_STATUS_CMD_RDY_MASK)) {
+		dev_err(data->dev, "device is not ready to accept commands\n");
+		return -EBUSY;
+	}
+
+	/* send command to process */
+	ret = regmap_write(data->regmap, BMP380_REG_CMD, cmd);
+	if (ret) {
+		dev_err(data->dev, "failed to send command to device\n");
+		return ret;
+	}
+	/* wait for 2ms for command to be processed */
+	usleep_range(data->start_up_time, data->start_up_time + 100);
+	/* check for command processing error */
+	ret = regmap_read(data->regmap, BMP380_REG_ERROR, &reg);
+	if (ret) {
+		dev_err(data->dev, "error reading ERROR reg\n");
+		return ret;
+	}
+	if (reg & BMP380_ERR_CMD_MASK) {
+		dev_err(data->dev, "error processing command 0x%X\n", cmd);
+		return -EINVAL;
+	}
+	dev_dbg(data->dev, "Command 0x%X processed successfully\n", cmd);
+
+	return 0;
+}
+
+/*
+ * Returns temperature in DegC, resolution is 0.01 DegC.  Output value of
+ * "5123" equals 51.23 DegC.  t_fine carries fine temperature as global
+ * value.
+ *
+ * Taken from datasheet, Section Appendix 9, "Compensation formula" and repo
+ * https://github.com/BoschSensortec/BMP3-Sensor-API
+ */
+static s32 bmp380_compensate_temp(struct bmp280_data *data, u32 adc_temp)
+{
+	s64 var1, var2, var3, var4, var5, var6, comp_temp;
+	struct bmp380_calib *calib = &data->calib.bmp380;
+
+	var1 = ((s64) adc_temp) - (((s64) calib->T1) << 8);
+	var2 = var1 * ((s64) calib->T2);
+	var3 = var1 * var1;
+	var4 = var3 * ((s64) calib->T3);
+	var5 = (var2 << 18) + var4;
+	var6 = var5 >> 32;
+	data->t_fine = (s32) var6;
+	comp_temp = (var6 * 25) >> 14;
+
+	comp_temp = clamp_val(comp_temp, BMP380_MIN_TEMP, BMP380_MAX_TEMP);
+	return (s32) comp_temp;
+}
+
+/*
+ * Returns pressure in Pa as unsigned 32 bit integer in fractional Pascal.
+ * Output value of "9528709" represents 9528709/100 = 95287.09 Pa = 952.8709 hPa
+ *
+ * Taken from datasheet, Section 9.3. "Pressure compensation" and repository
+ * https://github.com/BoschSensortec/BMP3-Sensor-API
+ */
+static u32 bmp380_compensate_press(struct bmp280_data *data, u32 adc_press)
+{
+	s64 var1, var2, var3, var4, var5, var6, offset, sensitivity;
+	u64 comp_press;
+	struct bmp380_calib *calib = &data->calib.bmp380;
+
+	var1 = ((s64)data->t_fine) * ((s64)data->t_fine);
+	var2 = var1 >> 6;
+	var3 = (var2 * ((s64) data->t_fine)) >> 8;
+	var4 = (((s64)calib->P8) * var3) >> 5;
+	var5 = (((s64) calib->P7) * var1) << 4;
+	var6 = (((s64) calib->P6) * ((s64)data->t_fine)) << 22;
+	offset = (((s64)calib->P5) << 47) + var4 + var5 + var6;
+	var2 = (((s64)calib->P4) * var3) >> 5;
+	var4 = (((s64) calib->P3) * var1) << 2;
+	var5 = (((s64) calib->P2) - ((s64) 1<<14)) *
+		(((s64)data->t_fine) << 21);
+	sensitivity = ((((s64) calib->P1) - ((s64) 1 << 14)) << 46) +
+			var2 + var4 + var5;
+	var1 = (sensitivity >> 24) * ((s64)adc_press);
+	var2 = ((s64)calib->P10) * ((s64) data->t_fine);
+	var3 = var2 + (((s64) calib->P9) << 16);
+	var4 = (var3 * ((s64)adc_press)) >> 13;
+
+	/*
+	 * Dividing by 10 followed by multiplying by 10 to avoid
+	 * possible overflow caused by (uncomp_data->pressure * partial_data4)
+	 */
+	var5 = (((s64)adc_press) * div_s64(var4, 10)) >> 9;
+	var5 *= 10;
+	var6 = ((s64)adc_press) * ((s64)adc_press);
+	var2 = (((s64)calib->P11) * var6) >> 16;
+	var3 = (var2 * ((s64)adc_press)) >> 7;
+	var4 = (offset >> 2) + var1 + var5 + var3;
+	comp_press = ((u64)var4 * 25) >> 40;
+
+	comp_press = clamp_val(comp_press, BMP380_MIN_PRES, BMP380_MAX_PRES);
+	return (u32)comp_press;
+}
+
+static int bmp380_read_temp(struct bmp280_data *data, int *val)
+{
+	int ret;
+	u32 adc_temp;
+	s32 comp_temp;
+
+	ret = regmap_bulk_read(data->regmap, BMP380_REG_TEMP_XLSB,
+			       data->buf.data, sizeof(data->buf.data));
+	if (ret < 0) {
+		dev_err(data->dev, "failed to read temperature\n");
+		return ret;
+	}
+
+	adc_temp = get_unaligned_le24(data->buf.data);
+	if (adc_temp == BMP380_TEMP_SKIPPED) {
+		/* reading was skipped */
+		dev_err(data->dev, "reading temperature skipped\n");
+		return -EIO;
+	}
+	comp_temp = bmp380_compensate_temp(data, adc_temp);
+
+	/*
+	 * val might be NULL if we're called by the read_press routine,
+	 * who only cares about the carry over t_fine value.
+	 */
+	if (val) {
+		/* IIO reports temperatures in mC */
+		*val = comp_temp * 10;
+		return IIO_VAL_INT;
+	}
+
+	return 0;
+}
+
+static int bmp380_read_press(struct bmp280_data *data, int *val, int *val2)
+{
+	int ret;
+	u32 adc_press;
+	s32 comp_press;
+
+	/* Read and compensate for temperature so we get a reading of t_fine */
+	ret = bmp380_read_temp(data, NULL);
+	if (ret < 0)
+		return ret;
+
+	ret = regmap_bulk_read(data->regmap, BMP380_REG_PRESS_XLSB,
+			       data->buf.data, sizeof(data->buf.data));
+	if (ret < 0) {
+		dev_err(data->dev, "failed to read pressure\n");
+		return ret;
+	}
+
+	adc_press = get_unaligned_le24(data->buf.data);
+	if (adc_press == BMP380_PRESS_SKIPPED) {
+		/* reading was skipped */
+		dev_err(data->dev, "reading pressure skipped\n");
+		return -EIO;
+	}
+	comp_press = bmp380_compensate_press(data, adc_press);
+
+	*val = comp_press;
+	/* Compensated pressure is in cPa (centipascals) */
+	*val2 = 100000;
+
+	return IIO_VAL_FRACTIONAL;
+}
+
+static int bmp380_read_calib(struct bmp280_data *data, unsigned int chip)
+{
+	struct bmp380_calib *calib = &data->calib.bmp380;
+	int ret;
+
+
+	/* Read temperature calibration values. */
+	ret = regmap_bulk_read(data->regmap, BMP380_REG_CALIB_TEMP_START,
+			       data->buf.bmp380_cal, sizeof(data->buf.bmp380_cal));
+	if (ret < 0) {
+		dev_err(data->dev,
+			"failed to read temperature calibration parameters\n");
+		return ret;
+	}
+
+	/* Toss the temperature calibration data into the entropy pool */
+	add_device_randomness(data->buf.bmp380_cal, sizeof(data->buf.bmp380_cal));
+
+	/* Parse calibration data */
+	calib->T1 = get_unaligned_le16(&data->buf.bmp380_cal[BMP380_T1]);
+	calib->T2 = get_unaligned_le16(&data->buf.bmp380_cal[BMP380_T2]);
+	calib->T3 = data->buf.bmp380_cal[BMP380_T3];
+	calib->P1 = get_unaligned_le16(&data->buf.bmp380_cal[BMP380_P1]);
+	calib->P2 = get_unaligned_le16(&data->buf.bmp380_cal[BMP380_P2]);
+	calib->P3 = data->buf.bmp380_cal[BMP380_P3];
+	calib->P4 = data->buf.bmp380_cal[BMP380_P4];
+	calib->P5 = get_unaligned_le16(&data->buf.bmp380_cal[BMP380_P5]);
+	calib->P6 = get_unaligned_le16(&data->buf.bmp380_cal[BMP380_P6]);
+	calib->P7 = data->buf.bmp380_cal[BMP380_P7];
+	calib->P8 = data->buf.bmp380_cal[BMP380_P8];
+	calib->P9 = get_unaligned_le16(&data->buf.bmp380_cal[BMP380_P9]);
+	calib->P10 = data->buf.bmp380_cal[BMP380_P10];
+	calib->P11 = data->buf.bmp380_cal[BMP380_P11];
+
+	return 0;
+}
+
+static int bmp380_chip_config(struct bmp280_data *data)
+{
+	unsigned int tmp;
+	u8 osrs;
+	int ret;
+
+	/* configure power control register */
+	ret = regmap_write_bits(data->regmap, BMP380_REG_POWER_CONTROL,
+				BMP380_CTRL_SENSORS_MASK | BMP380_MODE_MASK,
+				BMP380_CTRL_SENSORS_PRESS_EN |
+				BMP380_CTRL_SENSORS_TEMP_EN |
+				FIELD_PREP(BMP380_MODE_MASK, BMP380_MODE_NORMAL));
+	if (ret < 0) {
+		dev_err(data->dev,
+			"failed to write operation control register\n");
+		return ret;
+	}
+
+	/* configure oversampling */
+	osrs = FIELD_PREP(BMP380_OSRS_TEMP_MASK, data->oversampling_temp) |
+	       FIELD_PREP(BMP380_OSRS_PRESS_MASK, data->oversampling_press);
+
+	ret = regmap_write_bits(data->regmap, BMP380_REG_OSR,
+				BMP380_OSRS_TEMP_MASK | BMP380_OSRS_PRESS_MASK,
+				osrs);
+	if (ret < 0) {
+		dev_err(data->dev, "failed to write oversampling register\n");
+		return ret;
+	}
+
+	/* configure output data rate */
+	ret = regmap_write_bits(data->regmap, BMP380_REG_ODR,
+				BMP380_ODRS_MASK, BMP380_ODRS_50HZ);
+	if (ret < 0) {
+		dev_err(data->dev, "failed to write ODR selection register\n");
+		return ret;
+	}
+
+	/* set filter data */
+	ret = regmap_update_bits(data->regmap, BMP380_REG_CONFIG,
+				 BMP380_FILTER_MASK,
+				 FIELD_PREP(BMP380_FILTER_MASK, BMP380_FILTER_3X));
+	if (ret < 0) {
+		dev_err(data->dev, "failed to write config register\n");
+		return ret;
+	}
+
+	/* wait startup_time before verifying config changes */
+	usleep_range(data->start_up_time, data->start_up_time + 100);
+
+	/* check config error flag */
+	ret = regmap_read(data->regmap, BMP380_REG_ERROR, &tmp);
+	if (ret < 0) {
+		dev_err(data->dev,
+			"failed to read error register\n");
+		return ret;
+	}
+	if (tmp & BMP380_ERR_CONF_MASK) {
+		dev_warn(data->dev,
+			 "sensor flagged configuration as incompatible\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static const int bmp380_oversampling_avail[] = { 1, 2, 4, 8, 16, 32 };
+
+static const struct bmp280_chip_info bmp380_chip_info = {
+	.id_reg = BMP380_REG_ID,
+	.start_up_time = 2000,
+	.num_channels = 2,
+
+	.oversampling_temp_avail = bmp380_oversampling_avail,
+	.num_oversampling_temp_avail = ARRAY_SIZE(bmp380_oversampling_avail),
+	.oversampling_temp_default = ilog2(1),
+
+	.oversampling_press_avail = bmp380_oversampling_avail,
+	.num_oversampling_press_avail = ARRAY_SIZE(bmp380_oversampling_avail),
+	.oversampling_press_default = ilog2(4),
+
+	.chip_config = bmp380_chip_config,
+	.read_temp = bmp380_read_temp,
+	.read_press = bmp380_read_press,
+	.read_calib = bmp380_read_calib,
+};
+
 static int bmp180_measure(struct bmp280_data *data, u8 ctrl_meas)
 {
 	int ret;
@@ -1067,6 +1411,9 @@ int bmp280_common_probe(struct device *dev,
 	case BME280_CHIP_ID:
 		chip_info = &bme280_chip_info;
 		break;
+	case BMP380_CHIP_ID:
+		chip_info = &bmp380_chip_info;
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -1124,6 +1471,13 @@ int bmp280_common_probe(struct device *dev,
 		return -EINVAL;
 	}
 
+	/* BMP3xx requires soft-reset as part of initialization */
+	if (chip_id == BMP380_CHIP_ID) {
+		ret = bmp380_cmd(data, BMP380_CMD_SOFT_RESET);
+		if (ret < 0)
+			return ret;
+	}
+
 	ret = data->chip_info->chip_config(data);
 	if (ret < 0)
 		return ret;
diff --git a/drivers/iio/pressure/bmp280-i2c.c b/drivers/iio/pressure/bmp280-i2c.c
index bf4a7a617537..744442dbe5f9 100644
--- a/drivers/iio/pressure/bmp280-i2c.c
+++ b/drivers/iio/pressure/bmp280-i2c.c
@@ -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;
 	}
@@ -37,6 +40,7 @@ static int bmp280_i2c_probe(struct i2c_client *client,
 }
 
 static const struct of_device_id bmp280_of_i2c_match[] = {
+	{ .compatible = "bosch,bmp380", .data = (void *)BMP380_CHIP_ID },
 	{ .compatible = "bosch,bme280", .data = (void *)BME280_CHIP_ID },
 	{ .compatible = "bosch,bmp280", .data = (void *)BMP280_CHIP_ID },
 	{ .compatible = "bosch,bmp180", .data = (void *)BMP180_CHIP_ID },
@@ -46,6 +50,7 @@ static const struct of_device_id bmp280_of_i2c_match[] = {
 MODULE_DEVICE_TABLE(of, bmp280_of_i2c_match);
 
 static const struct i2c_device_id bmp280_i2c_id[] = {
+	{"bmp380", BMP380_CHIP_ID },
 	{"bmp280", BMP280_CHIP_ID },
 	{"bmp180", BMP180_CHIP_ID },
 	{"bmp085", BMP180_CHIP_ID },
diff --git a/drivers/iio/pressure/bmp280-regmap.c b/drivers/iio/pressure/bmp280-regmap.c
index 969698518984..c98c67970265 100644
--- a/drivers/iio/pressure/bmp280-regmap.c
+++ b/drivers/iio/pressure/bmp280-regmap.c
@@ -72,6 +72,49 @@ static bool bmp280_is_volatile_reg(struct device *dev, unsigned int reg)
 	}
 }
 
+static bool bmp380_is_writeable_reg(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case BMP380_REG_CMD:
+	case BMP380_REG_CONFIG:
+	case BMP380_REG_FIFO_CONFIG_1:
+	case BMP380_REG_FIFO_CONFIG_2:
+	case BMP380_REG_FIFO_WATERMARK_LSB:
+	case BMP380_REG_FIFO_WATERMARK_MSB:
+	case BMP380_REG_POWER_CONTROL:
+	case BMP380_REG_INT_CONTROL:
+	case BMP380_REG_IF_CONFIG:
+	case BMP380_REG_ODR:
+	case BMP380_REG_OSR:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool bmp380_is_volatile_reg(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case BMP380_REG_TEMP_XLSB:
+	case BMP380_REG_TEMP_LSB:
+	case BMP380_REG_TEMP_MSB:
+	case BMP380_REG_PRESS_XLSB:
+	case BMP380_REG_PRESS_LSB:
+	case BMP380_REG_PRESS_MSB:
+	case BMP380_REG_SENSOR_TIME_XLSB:
+	case BMP380_REG_SENSOR_TIME_LSB:
+	case BMP380_REG_SENSOR_TIME_MSB:
+	case BMP380_REG_INT_STATUS:
+	case BMP380_REG_FIFO_DATA:
+	case BMP380_REG_STATUS:
+	case BMP380_REG_ERROR:
+	case BMP380_REG_EVENT:
+		return true;
+	default:
+		return false;
+	}
+}
+
 const struct regmap_config bmp280_regmap_config = {
 	.reg_bits = 8,
 	.val_bits = 8,
@@ -83,3 +126,15 @@ const struct regmap_config bmp280_regmap_config = {
 	.volatile_reg = bmp280_is_volatile_reg,
 };
 EXPORT_SYMBOL_NS(bmp280_regmap_config, IIO_BMP280);
+
+const struct regmap_config bmp380_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+
+	.max_register = BMP380_REG_CMD,
+	.cache_type = REGCACHE_RBTREE,
+
+	.writeable_reg = bmp380_is_writeable_reg,
+	.volatile_reg = bmp380_is_volatile_reg,
+};
+EXPORT_SYMBOL_NS(bmp380_regmap_config, IIO_BMP280);
diff --git a/drivers/iio/pressure/bmp280-spi.c b/drivers/iio/pressure/bmp280-spi.c
index 4cfaf3e869b8..011c68e07ebf 100644
--- a/drivers/iio/pressure/bmp280-spi.c
+++ b/drivers/iio/pressure/bmp280-spi.c
@@ -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);
diff --git a/drivers/iio/pressure/bmp280.h b/drivers/iio/pressure/bmp280.h
index c036c7835004..827bc6b7ca07 100644
--- a/drivers/iio/pressure/bmp280.h
+++ b/drivers/iio/pressure/bmp280.h
@@ -3,6 +3,105 @@
 #include <linux/device.h>
 #include <linux/regmap.h>
 
+/* BMP380 specific registers */
+#define BMP380_REG_CMD			0x7E
+#define BMP380_REG_CONFIG		0x1F
+#define BMP380_REG_ODR			0x1D
+#define BMP380_REG_OSR			0x1C
+#define BMP380_REG_POWER_CONTROL	0x1B
+#define BMP380_REG_IF_CONFIG		0x1A
+#define BMP380_REG_INT_CONTROL		0x19
+#define BMP380_REG_INT_STATUS		0x11
+#define BMP380_REG_EVENT		0x10
+#define BMP380_REG_STATUS		0x03
+#define BMP380_REG_ERROR		0x02
+#define BMP380_REG_ID			0x00
+
+#define BMP380_REG_FIFO_CONFIG_1	0x18
+#define BMP380_REG_FIFO_CONFIG_2	0x17
+#define BMP380_REG_FIFO_WATERMARK_MSB	0x16
+#define BMP380_REG_FIFO_WATERMARK_LSB	0x15
+#define BMP380_REG_FIFO_DATA		0x14
+#define BMP380_REG_FIFO_LENGTH_MSB	0x13
+#define BMP380_REG_FIFO_LENGTH_LSB	0x12
+
+#define BMP380_REG_SENSOR_TIME_MSB	0x0E
+#define BMP380_REG_SENSOR_TIME_LSB	0x0D
+#define BMP380_REG_SENSOR_TIME_XLSB	0x0C
+
+#define BMP380_REG_TEMP_MSB		0x09
+#define BMP380_REG_TEMP_LSB		0x08
+#define BMP380_REG_TEMP_XLSB		0x07
+
+#define BMP380_REG_PRESS_MSB		0x06
+#define BMP380_REG_PRESS_LSB		0x05
+#define BMP380_REG_PRESS_XLSB		0x04
+
+#define BMP380_REG_CALIB_TEMP_START	0x31
+#define BMP380_CALIB_REG_COUNT		21
+
+#define BMP380_FILTER_MASK		GENMASK(3, 1)
+#define BMP380_FILTER_OFF		0
+#define BMP380_FILTER_1X		1
+#define BMP380_FILTER_3X		2
+#define BMP380_FILTER_7X		3
+#define BMP380_FILTER_15X		4
+#define BMP380_FILTER_31X		5
+#define BMP380_FILTER_63X		6
+#define BMP380_FILTER_127X		7
+
+#define BMP380_OSRS_TEMP_MASK		GENMASK(5, 3)
+#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)
+#define BMP380_CTRL_SENSORS_TEMP_EN	BIT(1)
+#define BMP380_MODE_MASK		GENMASK(5, 4)
+#define BMP380_MODE_SLEEP		0
+#define BMP380_MODE_FORCED		1
+#define BMP380_MODE_NORMAL		3
+
+#define BMP380_MIN_TEMP			-4000
+#define BMP380_MAX_TEMP			8500
+#define BMP380_MIN_PRES			3000000
+#define BMP380_MAX_PRES			12500000
+
+#define BMP380_CMD_NOOP			0x00
+#define BMP380_CMD_EXTMODE_EN_MID	0x34
+#define BMP380_CMD_FIFO_FLUSH		0xB0
+#define BMP380_CMD_SOFT_RESET		0xB6
+
+#define BMP380_STATUS_CMD_RDY_MASK	BIT(4)
+#define BMP380_STATUS_DRDY_PRESS_MASK	BIT(5)
+#define BMP380_STATUS_DRDY_TEMP_MASK	BIT(6)
+
+#define BMP380_ERR_FATAL_MASK		BIT(0)
+#define BMP380_ERR_CMD_MASK		BIT(1)
+#define BMP380_ERR_CONF_MASK		BIT(2)
+
+#define BMP380_TEMP_SKIPPED		0x800000
+#define BMP380_PRESS_SKIPPED		0x800000
+
 /* BMP280 specific registers */
 #define BMP280_REG_HUMIDITY_LSB		0xFE
 #define BMP280_REG_HUMIDITY_MSB		0xFD
@@ -94,6 +193,7 @@
 #define BMP280_REG_RESET		0xE0
 #define BMP280_REG_ID			0xD0
 
+#define BMP380_CHIP_ID			0x50
 #define BMP180_CHIP_ID			0x55
 #define BMP280_CHIP_ID			0x58
 #define BME280_CHIP_ID			0x60
@@ -107,6 +207,7 @@
 /* Regmap configurations */
 extern const struct regmap_config bmp180_regmap_config;
 extern const struct regmap_config bmp280_regmap_config;
+extern const struct regmap_config bmp380_regmap_config;
 
 /* Probe called from different transports */
 int bmp280_common_probe(struct device *dev,
-- 
2.37.1


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v5 4/5] dt-bindings: iio: pressure: bmp085: Add BMP380 compatible string
  2022-08-07 11:52 [PATCH v5 0/5] Add support for pressure sensor Bosch BMP380 Angel Iglesias
                   ` (2 preceding siblings ...)
  2022-08-07 11:55 ` [PATCH v5 3/5] iio: pressure: bmp280: Add support for BMP380 sensor family Angel Iglesias
@ 2022-08-07 11:56 ` Angel Iglesias
  2022-08-07 11:57 ` [PATCH v5 5/5] iio: pressure: bmp280: Add more tunable config parameters for BMP380 Angel Iglesias
  4 siblings, 0 replies; 22+ messages in thread
From: Angel Iglesias @ 2022-08-07 11:56 UTC (permalink / raw)
  To: linux-iio
  Cc: Krzysztof Kozlowski, Jonathan Cameron, Lars-Peter Clausen,
	Rob Herring, Krzysztof Kozlowski, Andreas Klinger, devicetree,
	linux-kernel

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

Signed-off-by: Angel Iglesias <ang.iglesiasg@gmail.com>
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
---
 Documentation/devicetree/bindings/iio/pressure/bmp085.yaml | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/iio/pressure/bmp085.yaml b/Documentation/devicetree/bindings/iio/pressure/bmp085.yaml
index 49257f9251e8..72cd2c2d3f17 100644
--- a/Documentation/devicetree/bindings/iio/pressure/bmp085.yaml
+++ b/Documentation/devicetree/bindings/iio/pressure/bmp085.yaml
@@ -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 <ak@it-klinger.de>
@@ -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
-- 
2.37.1


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v5 5/5] iio: pressure: bmp280: Add more tunable config parameters for BMP380
  2022-08-07 11:52 [PATCH v5 0/5] Add support for pressure sensor Bosch BMP380 Angel Iglesias
                   ` (3 preceding siblings ...)
  2022-08-07 11:56 ` [PATCH v5 4/5] dt-bindings: iio: pressure: bmp085: Add BMP380 compatible string Angel Iglesias
@ 2022-08-07 11:57 ` Angel Iglesias
  2022-08-08  9:13   ` Andy Shevchenko
  4 siblings, 1 reply; 22+ messages in thread
From: Angel Iglesias @ 2022-08-07 11:57 UTC (permalink / raw)
  To: linux-iio
  Cc: Jonathan Cameron, Lars-Peter Clausen, Paul Cercueil, Ulf Hansson,
	Rafael J. Wysocki, linux-kernel

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".

Signed-off-by: Angel Iglesias <ang.iglesiasg@gmail.com>
---
 drivers/iio/pressure/bmp280-core.c | 324 ++++++++++++++++++++++++++---
 drivers/iio/pressure/bmp280.h      |  18 --
 2 files changed, 294 insertions(+), 48 deletions(-)

diff --git a/drivers/iio/pressure/bmp280-core.c b/drivers/iio/pressure/bmp280-core.c
index fe171908a89c..39406f0f1e76 100644
--- a/drivers/iio/pressure/bmp280-core.c
+++ b/drivers/iio/pressure/bmp280-core.c
@@ -100,6 +100,27 @@ static const char *const bmp280_supply_names[] = {
 	"vddd", "vdda"
 };
 
+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,
+};
+
 #define BMP280_NUM_SUPPLIES ARRAY_SIZE(bmp280_supply_names)
 
 struct bmp280_data {
@@ -121,6 +142,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
@@ -145,6 +177,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;
 
@@ -160,6 +193,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 *);
@@ -211,6 +252,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, unsigned int chip)
 {
 	int ret;
@@ -526,6 +591,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 = data->chip_info->iir_filter_coeffs_avail[data->iir_filter_coeff];
+		ret = IIO_VAL_INT;
+		break;
 	default:
 		ret = -EINVAL;
 		break;
@@ -542,14 +626,22 @@ static int bmp280_write_oversampling_ratio_humid(struct bmp280_data *data,
 					       int val)
 {
 	int i;
+	int ret, prev;
 	const int *avail = data->chip_info->oversampling_humid_avail;
 	const int n = data->chip_info->num_oversampling_humid_avail;
 
 	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;
@@ -559,14 +651,22 @@ static int bmp280_write_oversampling_ratio_temp(struct bmp280_data *data,
 					       int val)
 {
 	int i;
+	int ret, prev;
 	const int *avail = data->chip_info->oversampling_temp_avail;
 	const int n = data->chip_info->num_oversampling_temp_avail;
 
 	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;
@@ -576,14 +676,72 @@ static int bmp280_write_oversampling_ratio_press(struct bmp280_data *data,
 					       int val)
 {
 	int i;
+	int ret, prev;
 	const int *avail = data->chip_info->oversampling_press_avail;
 	const int n = data->chip_info->num_oversampling_press_avail;
 
 	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)
+{
+	int i;
+	int ret, prev;
+	const int (*avail)[2] = data->chip_info->sampling_freq_avail;
+	const int n = data->chip_info->num_sampling_freq_avail;
+
+	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)
+{
+	int i;
+	int ret, prev;
+	const int *avail = data->chip_info->iir_filter_coeffs_avail;
+	const int n = data->chip_info->num_iir_filter_coeffs_avail;
+
+	for (i = 0; i < n; i++) {
+		if (avail[i] == 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;
@@ -596,6 +754,12 @@ static int bmp280_write_raw(struct iio_dev *indio_dev,
 	int ret = 0;
 	struct bmp280_data *data = iio_priv(indio_dev);
 
+	/*
+	 * 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);
@@ -618,6 +782,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;
 	}
@@ -648,6 +828,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;
 	}
@@ -693,6 +884,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,
@@ -740,6 +932,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,
@@ -978,18 +1171,39 @@ static int bmp380_read_calib(struct bmp280_data *data, unsigned int chip)
 	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;
 	unsigned int tmp;
 	u8 osrs;
 	int ret;
 
 	/* configure power control register */
-	ret = regmap_write_bits(data->regmap, BMP380_REG_POWER_CONTROL,
-				BMP380_CTRL_SENSORS_MASK | BMP380_MODE_MASK,
-				BMP380_CTRL_SENSORS_PRESS_EN |
-				BMP380_CTRL_SENSORS_TEMP_EN |
-				FIELD_PREP(BMP380_MODE_MASK, BMP380_MODE_NORMAL));
+	ret = regmap_update_bits(data->regmap, BMP380_REG_POWER_CONTROL,
+				 BMP380_CTRL_SENSORS_MASK,
+				 BMP380_CTRL_SENSORS_PRESS_EN |
+				 BMP380_CTRL_SENSORS_TEMP_EN);
 	if (ret < 0) {
 		dev_err(data->dev,
 			"failed to write operation control register\n");
@@ -1000,55 +1214,94 @@ static int bmp380_chip_config(struct bmp280_data *data)
 	osrs = FIELD_PREP(BMP380_OSRS_TEMP_MASK, data->oversampling_temp) |
 	       FIELD_PREP(BMP380_OSRS_PRESS_MASK, data->oversampling_press);
 
-	ret = regmap_write_bits(data->regmap, BMP380_REG_OSR,
-				BMP380_OSRS_TEMP_MASK | BMP380_OSRS_PRESS_MASK,
-				osrs);
+	ret = regmap_update_bits_check(data->regmap, BMP380_REG_OSR,
+				       BMP380_OSRS_TEMP_MASK |
+				       BMP380_OSRS_PRESS_MASK,
+				       osrs, &aux);
 	if (ret < 0) {
 		dev_err(data->dev, "failed to write oversampling register\n");
 		return ret;
 	}
+	change = change || aux;
 
 	/* configure output data rate */
-	ret = regmap_write_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 < 0) {
 		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 < 0) {
 		dev_err(data->dev, "failed to write config register\n");
 		return ret;
 	}
+	change = change || aux;
 
-	/* wait startup_time before verifying config changes */
-	usleep_range(data->start_up_time, data->start_up_time + 100);
+	if (change) {
+		/*
+		 * The configurations errors are detected on the fly during a measurement
+		 * cycle. If the sampling frequency is too low, it's faster to reset
+		 * the measurement loop than wait until the next measurement is due.
+		 *
+		 * Resets sensor measurement loop toggling between sleep and normal
+		 * operating modes.
+		 */
+		ret = regmap_write_bits(data->regmap, BMP380_REG_POWER_CONTROL,
+					BMP380_MODE_MASK,
+					FIELD_PREP(BMP380_MODE_MASK,
+						   BMP380_MODE_SLEEP));
+		if (ret < 0) {
+			dev_err(data->dev, "failed to set sleep mode\n");
+			return ret;
+		}
+		usleep_range(2000, 2500);
+		ret = regmap_write_bits(data->regmap, BMP380_REG_POWER_CONTROL,
+					BMP380_MODE_MASK,
+					FIELD_PREP(BMP380_MODE_MASK,
+						   BMP380_MODE_NORMAL));
+		if (ret < 0) {
+			dev_err(data->dev, "failed to set normal mode\n");
+			return ret;
+		}
+		/*
+		 * Waits for measurement before checking configuration error flag.
+		 * Selected longest measure time indicated in section 3.9.1
+		 * in the datasheet.
+		 */
+		msleep(80);
 
-	/* check config error flag */
-	ret = regmap_read(data->regmap, BMP380_REG_ERROR, &tmp);
-	if (ret < 0) {
-		dev_err(data->dev,
-			"failed to read error register\n");
-		return ret;
-	}
-	if (tmp & BMP380_ERR_CONF_MASK) {
-		dev_warn(data->dev,
-			 "sensor flagged configuration as incompatible\n");
-		return -EINVAL;
+		/* check config error flag */
+		ret = regmap_read(data->regmap, BMP380_REG_ERROR, &tmp);
+		if (ret < 0) {
+			dev_err(data->dev,
+				"failed to read error register\n");
+			return ret;
+		}
+		if (tmp & BMP380_ERR_CONF_MASK) {
+			dev_warn(data->dev,
+				"sensor flagged configuration as incompatible\n");
+			return -EINVAL;
+		}
 	}
 
 	return 0;
 }
 
 static const int bmp380_oversampling_avail[] = { 1, 2, 4, 8, 16, 32 };
+static const int bmp380_iir_filter_coeffs_avail[] = { 0, 1, 3, 7, 15, 31, 63, 127 };
 
 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,
@@ -1059,6 +1312,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,
@@ -1299,6 +1560,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,
@@ -1397,7 +1659,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;
 
@@ -1420,10 +1681,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 */
diff --git a/drivers/iio/pressure/bmp280.h b/drivers/iio/pressure/bmp280.h
index 827bc6b7ca07..15ae3c32f168 100644
--- a/drivers/iio/pressure/bmp280.h
+++ b/drivers/iio/pressure/bmp280.h
@@ -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)
-- 
2.37.1


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* Re: [PATCH v5 1/5] iio: pressure: bmp280: simplify driver initialization logic
  2022-08-07 11:54 ` [PATCH v5 1/5] iio: pressure: bmp280: simplify driver initialization logic Angel Iglesias
@ 2022-08-08  8:18   ` Andy Shevchenko
  2022-08-14 13:43   ` Jonathan Cameron
  1 sibling, 0 replies; 22+ messages in thread
From: Andy Shevchenko @ 2022-08-08  8:18 UTC (permalink / raw)
  To: Angel Iglesias
  Cc: linux-iio, Jonathan Cameron, Lars-Peter Clausen, Ulf Hansson,
	Rafael J. Wysocki, Paul Cercueil, Linux Kernel Mailing List

On Sun, Aug 7, 2022 at 1:55 PM Angel Iglesias <ang.iglesiasg@gmail.com> wrote:
>
> 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.
>
> Revised BMP180 and BMP280 definitions and code functions to use GENMASK
> and FIELD_PREP/FIELD_GET utilities to homogenize structure with more
> recent drivers, in preparation for the patches adding support for the
> BMP380 sensors.

...

>         int ret;
>         unsigned int tmp;
>         __le16 l16;
>         __be16 b16;
>         struct device *dev = data->dev;
> +       struct bmp280_calib *calib = &data->calib.bmp280;

When you add longer lines, try to put them to be first.

>         __le16 t_buf[BMP280_COMP_TEMP_REG_COUNT / 2];
>         __le16 p_buf[BMP280_COMP_PRESS_REG_COUNT / 2];

...

>         int ret;
> -       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);

Ditto, move it to be before `int ret;` at the same time. Same for
other similar cases.

...

> +       /* apply initial values from chip info structure */

Make (one-line) comments consistent...

>         /* Bring up regulators */

...see the difference?

-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH v5 2/5] iio: pressure: bmp280: Fix alignment for DMA safety
  2022-08-07 11:55 ` [PATCH v5 2/5] iio: pressure: bmp280: Fix alignment for DMA safety Angel Iglesias
@ 2022-08-08  8:53   ` Andy Shevchenko
  2022-08-12  9:59     ` Angel Iglesias
  2022-08-14 14:03   ` Jonathan Cameron
  1 sibling, 1 reply; 22+ messages in thread
From: Andy Shevchenko @ 2022-08-08  8:53 UTC (permalink / raw)
  To: Angel Iglesias
  Cc: linux-iio, Jonathan Cameron, Lars-Peter Clausen, Paul Cercueil,
	Ulf Hansson, Rafael J. Wysocki, Linux Kernel Mailing List

On Sun, Aug 7, 2022 at 1:56 PM Angel Iglesias <ang.iglesiasg@gmail.com> wrote:
>
> 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.

...

>  #include <linux/completion.h>
>  #include <linux/pm_runtime.h>
>  #include <linux/random.h>

+ Blank line.

> +#include <asm/unaligned.h>

...

> +       union {
> +               /* sensor data buffer */
> +               u8 data[3];
> +               /* calibration data buffers */
> +               __le16 bmp280_cal[BMP280_CONTIGUOUS_CALIB_REGS / 2];
> +               __be16 bmp180_cal[BMP180_REG_CALIB_COUNT / 2];
> +       } buf __aligned(IIO_DMA_MINALIGN);

Hmm... And which field in the struct defines which of the buffers is being used?
Also, do you need a non-anonymous union?

>  };

...

> +       /* parse temperature calibration data */

Be consistent! Check all your patches for the consistency (comments,
other code style, etc).

...

> +       calib->H5 = sign_extend32(((get_unaligned_le16(data->buf.data) >> 4) & 0xfff), 11);

(It's not directly related to this change, but good to ask)
Are you going to change all those masks to use GENMASK()?

...

> +       struct bmp180_calib *calib = &data->calib.bmp180;
>         int ret;
>         int i;
> -       struct bmp180_calib *calib = &data->calib.bmp180;

Exactly my point given the previous patch, now you have a ping-pong
style of changes: the introduced line in the series is being touched
again in the very same series without any need.

...

>         u8 oss = data->oversampling_press;
> +       int ret;

Ditto.

-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH v5 3/5] iio: pressure: bmp280: Add support for BMP380 sensor family
  2022-08-07 11:55 ` [PATCH v5 3/5] iio: pressure: bmp280: Add support for BMP380 sensor family Angel Iglesias
@ 2022-08-08  9:08   ` Andy Shevchenko
  2022-08-12 10:47     ` Angel Iglesias
  2022-08-14 14:15   ` Jonathan Cameron
  1 sibling, 1 reply; 22+ messages in thread
From: Andy Shevchenko @ 2022-08-08  9:08 UTC (permalink / raw)
  To: Angel Iglesias
  Cc: linux-iio, Jonathan Cameron, Lars-Peter Clausen, Andy Shevchenko,
	Nikita Yushchenko, Ulf Hansson, Rafael J. Wysocki, Paul Cercueil,
	Linux Kernel Mailing List

On Sun, Aug 7, 2022 at 1:56 PM Angel Iglesias <ang.iglesiasg@gmail.com> wrote:
>
> 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

Missed period.

...

>   * 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

Seems like the above links are unresponsive now? Perhaps you may fix
them as well in a separate patch?

> + * https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bmp388-ds001.pdf

...

> +/* See datasheet Section 3.11.1. */

Again, a bit of consistency in (one-line) comments, please.

> +struct bmp380_calib {
> +       u16 T1;
> +       u16 T2;
> +       s8  T3;
> +       s16 P1;
> +       s16 P2;
> +       s8  P3;
> +       s8  P4;
> +       u16 P5;
> +       u16 P6;
> +       s8  P7;
> +       s8  P8;
> +       s16 P9;
> +       s8  P10;
> +       s8  P11;
> +};

__packed ?

...

> +/* Send a command to BMP3XX sensors */

> +       /* check if device is ready to process a command */
> +       /* send command to process */
> +       /* wait for 2ms for command to be processed */
> +       /* check for command processing error */

Consistency, please!

...

> +       dev_dbg(data->dev, "Command 0x%X processed successfully\n", cmd);

Useless.

...

> +/*
> + * Returns temperature in DegC, resolution is 0.01 DegC.  Output value of

DegC?! Perhaps "Celsius degrees"?

> + * "5123" equals 51.23 DegC.  t_fine carries fine temperature as global
> + * value.
> + *
> + * Taken from datasheet, Section Appendix 9, "Compensation formula" and repo
> + * https://github.com/BoschSensortec/BMP3-Sensor-API

Missed period.

> + */

...

> +       return (s32) comp_temp;

Do you need casting?

...

> +/*
> + * Returns pressure in Pa as unsigned 32 bit integer in fractional Pascal.

an unsigned
32-bit

> + * Output value of "9528709" represents 9528709/100 = 95287.09 Pa = 952.8709 hPa
> + *
> + * Taken from datasheet, Section 9.3. "Pressure compensation" and repository
> + * https://github.com/BoschSensortec/BMP3-Sensor-API

Missed period.

> + */

...

> +       var1 = ((s64)data->t_fine) * ((s64)data->t_fine);

Too many parentheses?

...

> +       /*
> +        * Dividing by 10 followed by multiplying by 10 to avoid
> +        * possible overflow caused by (uncomp_data->pressure * partial_data4)

Missed period.

> +        */

...

> +       return (u32)comp_press;

Do you need casting?

...

> +               /* reading was skipped */

The useless comment.

> +               dev_err(data->dev, "reading pressure skipped\n");

...

> +       /* Compensated pressure is in cPa (centipascals) */
> +       *val2 = 100000;

Anything to use from units.h?

...

> +       ret = regmap_write_bits(data->regmap, BMP380_REG_OSR,
> +                               BMP380_OSRS_TEMP_MASK | BMP380_OSRS_PRESS_MASK,
> +                               osrs);
> +       if (ret < 0) {

Do all these ' < 0' parts make any sense?

> +       }

...

> +       { .compatible = "bosch,bmp380", .data = (void *)BMP380_CHIP_ID },
>         { .compatible = "bosch,bme280", .data = (void *)BME280_CHIP_ID },
>         { .compatible = "bosch,bmp280", .data = (void *)BMP280_CHIP_ID },
>         { .compatible = "bosch,bmp180", .data = (void *)BMP180_CHIP_ID },

See below.

...

> +       {"bmp380", BMP380_CHIP_ID },
>         {"bmp280", BMP280_CHIP_ID },
>         {"bmp180", BMP180_CHIP_ID },
>         {"bmp085", BMP180_CHIP_ID },

Can we actually keep them forward-ordered? (Add 380 after 280 here and
in a separate patch sort the rest, or other way around, sort as a
prerequisite patch)

...

> +#define BMP380_MIN_TEMP                        -4000
> +#define BMP380_MAX_TEMP                        8500
> +#define BMP380_MIN_PRES                        3000000
> +#define BMP380_MAX_PRES                        12500000

Units?


--
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH v5 5/5] iio: pressure: bmp280: Add more tunable config parameters for BMP380
  2022-08-07 11:57 ` [PATCH v5 5/5] iio: pressure: bmp280: Add more tunable config parameters for BMP380 Angel Iglesias
@ 2022-08-08  9:13   ` Andy Shevchenko
  2022-09-12  0:53     ` Angel Iglesias
  0 siblings, 1 reply; 22+ messages in thread
From: Andy Shevchenko @ 2022-08-08  9:13 UTC (permalink / raw)
  To: Angel Iglesias
  Cc: linux-iio, Jonathan Cameron, Lars-Peter Clausen, Paul Cercueil,
	Ulf Hansson, Rafael J. Wysocki, Linux Kernel Mailing List

On Sun, Aug 7, 2022 at 2:44 PM Angel Iglesias <ang.iglesiasg@gmail.com> wrote:
>
> 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".

...

> +static const int bmp380_odr_table[][2] = {

s32_fract ?

> +       [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},
> +};

...

> +               ret = regmap_write_bits(data->regmap, BMP380_REG_POWER_CONTROL,
> +                                       BMP380_MODE_MASK,

> +                                       FIELD_PREP(BMP380_MODE_MASK,
> +                                                  BMP380_MODE_SLEEP));

One line?

...

> +               ret = regmap_write_bits(data->regmap, BMP380_REG_POWER_CONTROL,
> +                                       BMP380_MODE_MASK,

> +                                       FIELD_PREP(BMP380_MODE_MASK,
> +                                                  BMP380_MODE_NORMAL));

Ditto.

...

> +static const int bmp380_iir_filter_coeffs_avail[] = { 0, 1, 3, 7, 15, 31, 63, 127 };

This seems like a power of two - 1, can it be replaced by a formula in the code?

-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH v5 2/5] iio: pressure: bmp280: Fix alignment for DMA safety
  2022-08-08  8:53   ` Andy Shevchenko
@ 2022-08-12  9:59     ` Angel Iglesias
  2022-08-14 13:52       ` Jonathan Cameron
  0 siblings, 1 reply; 22+ messages in thread
From: Angel Iglesias @ 2022-08-12  9:59 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: linux-iio, Jonathan Cameron, Lars-Peter Clausen, Paul Cercueil,
	Ulf Hansson, Rafael J. Wysocki, Linux Kernel Mailing List

On lun, 2022-08-08 at 10:53 +0200, Andy Shevchenko wrote:
> On Sun, Aug 7, 2022 at 1:56 PM Angel Iglesias <ang.iglesiasg@gmail.com> wrote:
> > 
> > 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.
> 
> ...
> 
> >  #include <linux/completion.h>
> >  #include <linux/pm_runtime.h>
> >  #include <linux/random.h>
> 
> + Blank line.
> 
> > +#include <asm/unaligned.h>
> 
> ...
> 
> > +       union {
> > +               /* sensor data buffer */
> > +               u8 data[3];
> > +               /* calibration data buffers */
> > +               __le16 bmp280_cal[BMP280_CONTIGUOUS_CALIB_REGS / 2];
> > +               __be16 bmp180_cal[BMP180_REG_CALIB_COUNT / 2];
> > +       } buf __aligned(IIO_DMA_MINALIGN);
> 
> Hmm... And which field in the struct defines which of the buffers is being
> used?

There's no concurrent use of the buffers. Calibration data is read during the
initialization of the sensor. The data buffer is then used to store the raw data
read from the measurement regs, and is also used a few times to read a the humid
calibration on BME280, but again, in a sequential, non concurrent manner.

Regarding which calibration buffer is used, is the same situation as the
calibration data union, helper functions and callback for the sensor use the
buffer reserved for the sensor. I don't know if this is the best approach, I
just followed what I saw previously on this drivers and others from IIO
subsystem.

> Also, do you need a non-anonymous union?

No I could use an anonymous function. Should I change it to an anonymous union?

> >  };
> 
> ...
> 
> > +       /* parse temperature calibration data */
> 
> Be consistent! Check all your patches for the consistency (comments,
> other code style, etc).
> 
> ...
> 
> > +       calib->H5 = sign_extend32(((get_unaligned_le16(data->buf.data) >> 4)
> > & 0xfff), 11);
> 
> (It's not directly related to this change, but good to ask)
> Are you going to change all those masks to use GENMASK()?

I thought I made sense refresh previous code on the driver to use GENMASK() and
FIELD_PREP and FIELD_GET helpers to use the same standards on the BMP380
codepath. Having in mind other feedback you gave me on this iteration, this
GENMASK() and FIELD_PREP/FIELD_GET changes make more sense in a prerequisite
patch and not as part of patch 1.

> ...
> 
> > +       struct bmp180_calib *calib = &data->calib.bmp180;
> >         int ret;
> >         int i;
> > -       struct bmp180_calib *calib = &data->calib.bmp180;
> 
> Exactly my point given the previous patch, now you have a ping-pong
> style of changes: the introduced line in the series is being touched
> again in the very same series without any need.

Yup, apologies. I'll be more careful

> ...
> 
> >         u8 oss = data->oversampling_press;
> > +       int ret;
> 
> Ditto.
> 


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH v5 3/5] iio: pressure: bmp280: Add support for BMP380 sensor family
  2022-08-08  9:08   ` Andy Shevchenko
@ 2022-08-12 10:47     ` Angel Iglesias
  2022-08-14 14:11       ` Jonathan Cameron
  0 siblings, 1 reply; 22+ messages in thread
From: Angel Iglesias @ 2022-08-12 10:47 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: linux-iio, Jonathan Cameron, Lars-Peter Clausen, Andy Shevchenko,
	Nikita Yushchenko, Ulf Hansson, Rafael J. Wysocki, Paul Cercueil,
	Linux Kernel Mailing List

On lun, 2022-08-08 at 11:08 +0200, Andy Shevchenko wrote:
> On Sun, Aug 7, 2022 at 1:56 PM Angel Iglesias <ang.iglesiasg@gmail.com> wrote:
> > 
> > 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
> 
> Missed period.
> 
> ...
> 
> >   *
> > 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
> 
> Seems like the above links are unresponsive now? Perhaps you may fix
> them as well in a separate patch?

Sure. Should I include this patch in this next version of this series, or should
I send the patch as a standalone change?

> > + *
> > https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bmp388-ds001.pdf
> 
> ...
> 
> > +/* See datasheet Section 3.11.1. */
> 
> Again, a bit of consistency in (one-line) comments, please.
> 
> > +struct bmp380_calib {
> > +       u16 T1;
> > +       u16 T2;
> > +       s8  T3;
> > +       s16 P1;
> > +       s16 P2;
> > +       s8  P3;
> > +       s8  P4;
> > +       u16 P5;
> > +       u16 P6;
> > +       s8  P7;
> > +       s8  P8;
> > +       s16 P9;
> > +       s8  P10;
> > +       s8  P11;
> > +};
> 
> __packed ?
> 
> ...
> 
> > +/* Send a command to BMP3XX sensors */
> 
> > +       /* check if device is ready to process a command */
> > +       /* send command to process */
> > +       /* wait for 2ms for command to be processed */
> > +       /* check for command processing error */
> 
> Consistency, please!
> 
> ...
> 
> > +       dev_dbg(data->dev, "Command 0x%X processed successfully\n", cmd);
> 
> Useless.
> 
> ...
> 
> > +/*
> > + * Returns temperature in DegC, resolution is 0.01 DegC.  Output value of
> 
> DegC?! Perhaps "Celsius degrees"?
> 
> > + * "5123" equals 51.23 DegC.  t_fine carries fine temperature as global
> > + * value.
> > + *
> > + * Taken from datasheet, Section Appendix 9, "Compensation formula" and
> > repo
> > + * https://github.com/BoschSensortec/BMP3-Sensor-API
> 
> Missed period.
> 
> > + */
> 
> ...
> 
> > +       return (s32) comp_temp;
> 
> Do you need casting?
> 
> ...
> 
> > +/*
> > + * Returns pressure in Pa as unsigned 32 bit integer in fractional Pascal.
> 
> an unsigned
> 32-bit
> 
> > + * Output value of "9528709" represents 9528709/100 = 95287.09 Pa =
> > 952.8709 hPa
> > + *
> > + * Taken from datasheet, Section 9.3. "Pressure compensation" and
> > repository
> > + * https://github.com/BoschSensortec/BMP3-Sensor-API
> 
> Missed period.
> 
> > + */
> 
> ...
> 
> > +       var1 = ((s64)data->t_fine) * ((s64)data->t_fine);
> 
> Too many parentheses?

Yup, operator precedence of typecast precedes multiplication.

> ...
> 
> > +       /*
> > +        * Dividing by 10 followed by multiplying by 10 to avoid
> > +        * possible overflow caused by (uncomp_data->pressure *
> > partial_data4)
> 
> Missed period.
> 
> > +        */
> 
> ...
> 
> > +       return (u32)comp_press;
> 
> Do you need casting?

Not really, should fall on the implicit conversion rules of the compiler as it
works like an assignment, right?. Also, after shifting 40 bits to the right,
there's no risk of overflow, comp_press can be a u32 from the start instead of a
u64.

> ...
> 
> > +               /* reading was skipped */
> 
> The useless comment.
> 
> > +               dev_err(data->dev, "reading pressure skipped\n");
> 
> ...
> 
> > +       /* Compensated pressure is in cPa (centipascals) */
> > +       *val2 = 100000;
> 
> Anything to use from units.h?
> 
> ...
> 
> > +       ret = regmap_write_bits(data->regmap, BMP380_REG_OSR,
> > +                               BMP380_OSRS_TEMP_MASK |
> > BMP380_OSRS_PRESS_MASK,
> > +                               osrs);
> > +       if (ret < 0) {
> 
> Do all these ' < 0' parts make any sense?

I've checked regmap calls and return 0 when call is successful, so the answer is
no

> > +       }
> 
> ...
> 
> > +       { .compatible = "bosch,bmp380", .data = (void *)BMP380_CHIP_ID },
> >         { .compatible = "bosch,bme280", .data = (void *)BME280_CHIP_ID },
> >         { .compatible = "bosch,bmp280", .data = (void *)BMP280_CHIP_ID },
> >         { .compatible = "bosch,bmp180", .data = (void *)BMP180_CHIP_ID },
> 
> See below.
> 
> ...
> 
> > +       {"bmp380", BMP380_CHIP_ID },
> >         {"bmp280", BMP280_CHIP_ID },
> >         {"bmp180", BMP180_CHIP_ID },
> >         {"bmp085", BMP180_CHIP_ID },
> 
> Can we actually keep them forward-ordered? (Add 380 after 280 here and
> in a separate patch sort the rest, or other way around, sort as a
> prerequisite patch)

Sure!

> ...
> 
> > +#define BMP380_MIN_TEMP                        -4000
> > +#define BMP380_MAX_TEMP                        8500
> > +#define BMP380_MIN_PRES                        3000000
> > +#define BMP380_MAX_PRES                        12500000
> 
> Units?

Units as in I should use units.h constants or also comment in which units are
these constants?

> 
> --
> With Best Regards,
> Andy Shevchenko

Kind regards,
Angel


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH v5 1/5] iio: pressure: bmp280: simplify driver initialization logic
  2022-08-07 11:54 ` [PATCH v5 1/5] iio: pressure: bmp280: simplify driver initialization logic Angel Iglesias
  2022-08-08  8:18   ` Andy Shevchenko
@ 2022-08-14 13:43   ` Jonathan Cameron
  2022-08-14 14:26     ` Angel Iglesias
  1 sibling, 1 reply; 22+ messages in thread
From: Jonathan Cameron @ 2022-08-14 13:43 UTC (permalink / raw)
  To: Angel Iglesias, Lars-Peter Clausen
  Cc: linux-iio, Ulf Hansson, Rafael J. Wysocki, Paul Cercueil, linux-kernel

On Sun,  7 Aug 2022 13:54:40 +0200
Angel Iglesias <ang.iglesiasg@gmail.com> wrote:

> 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.
> 
> Revised BMP180 and BMP280 definitions and code functions to use GENMASK
> and FIELD_PREP/FIELD_GET utilities to homogenize structure with more
> recent drivers, in preparation for the patches adding support for the
> BMP380 sensors.
> 
> Suggested-by: Jonathan Cameron <jic23@kernel.org>
> Signed-off-by: Angel Iglesias <ang.iglesiasg@gmail.com>
Hi Angel, not sure if I commented on this before, but this patch is doing
several different things, so in the ideal case it would be split into
1: FIELD_PREP/FIELD_GET/GENMASK changes. 
2: Chipinfo related changes
3: Maybe the the reordering of defintions of local variables that Andy
   indirectly referered to.

However, this is short enough to be fairly reviewable as it stands
so from my point of view I'll accept leaving 1 and 2 combined if it is
going to be a lot of work to separate them. Doesn't look like it will be hard
but without trying I'm not totally sure!

One question inline on what the chip parameter to the calibration functions
is there for as it appears unused.

Thanks,

Jonathan


> ---
>  drivers/iio/pressure/bmp280-core.c | 120 ++++++++++++++++++-----------
>  drivers/iio/pressure/bmp280.h      |  73 +++++++++---------
>  2 files changed, 113 insertions(+), 80 deletions(-)
> 
> diff --git a/drivers/iio/pressure/bmp280-core.c b/drivers/iio/pressure/bmp280-core.c
> index fe7aa81e7cc9..a109c2609896 100644
> --- a/drivers/iio/pressure/bmp280-core.c
> +++ b/drivers/iio/pressure/bmp280-core.c
> @@ -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>
> @@ -107,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 *, unsigned int);
>  };
>  
>  /*
> @@ -147,15 +158,14 @@ 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, unsigned int chip)
>  {
>  	int ret;
>  	unsigned int tmp;
>  	__le16 l16;
>  	__be16 b16;
>  	struct device *dev = data->dev;
> +	struct bmp280_calib *calib = &data->calib.bmp280;
>  	__le16 t_buf[BMP280_COMP_TEMP_REG_COUNT / 2];
>  	__le16 p_buf[BMP280_COMP_PRESS_REG_COUNT / 2];
>  
> @@ -611,8 +621,8 @@ 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);
> +	u8 osrs = FIELD_PREP(BMP280_OSRS_TEMP_MASK, data->oversampling_temp + 1) |
> +		  FIELD_PREP(BMP280_OSRS_PRESS_MASK, data->oversampling_press + 1);
>  
>  	ret = regmap_write_bits(data->regmap, BMP280_REG_CTRL_MEAS,
>  				 BMP280_OSRS_TEMP_MASK |
> @@ -640,21 +650,38 @@ 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)
>  {
>  	int ret;
> -	u8 osrs = BMP280_OSRS_HUMIDITIY_X(data->oversampling_humid + 1);
> +	u8 osrs = FIELD_PREP(BMP280_OSRS_HUMIDITY_MASK, data->oversampling_humid + 1);
>  
>  	/*
>  	 * Oversampling of humidity must be set before oversampling of
> @@ -670,19 +697,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 = bmp280_read_calib,
>  };
>  
>  static int bmp180_measure(struct bmp280_data *data, u8 ctrl_meas)
> @@ -710,7 +745,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 =
> @@ -735,7 +770,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;
>  
> @@ -748,11 +785,11 @@ 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, unsigned int chip)

What is chip used for?  If there will be a need for it in later patches, then
it's fine to add the additional parameter now but please say why in the patch
description.


>  {
>  	int ret;
>  	int i;
> +	struct bmp180_calib *calib = &data->calib.bmp180;
>  	__be16 buf[BMP180_REG_CALIB_COUNT / 2];
>  
>  	ret = regmap_bulk_read(data->regmap, BMP180_REG_CALIB_START, buf,
> @@ -832,7 +869,10 @@ static int bmp180_read_adc_press(struct bmp280_data *data, int *val)
>  	__be32 tmp = 0;
>  	u8 oss = data->oversampling_press;
>  
> -	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;
>  

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH v5 2/5] iio: pressure: bmp280: Fix alignment for DMA safety
  2022-08-12  9:59     ` Angel Iglesias
@ 2022-08-14 13:52       ` Jonathan Cameron
  0 siblings, 0 replies; 22+ messages in thread
From: Jonathan Cameron @ 2022-08-14 13:52 UTC (permalink / raw)
  To: Angel Iglesias
  Cc: Andy Shevchenko, linux-iio, Lars-Peter Clausen, Paul Cercueil,
	Ulf Hansson, Rafael J. Wysocki, Linux Kernel Mailing List

On Fri, 12 Aug 2022 11:59:50 +0200
Angel Iglesias <ang.iglesiasg@gmail.com> wrote:

> On lun, 2022-08-08 at 10:53 +0200, Andy Shevchenko wrote:
> > On Sun, Aug 7, 2022 at 1:56 PM Angel Iglesias <ang.iglesiasg@gmail.com> wrote:  
> > > 
> > > 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.  
> > 
> > ...
> >   
> > >  #include <linux/completion.h>
> > >  #include <linux/pm_runtime.h>
> > >  #include <linux/random.h>  
> > 
> > + Blank line.
> >   
> > > +#include <asm/unaligned.h>  
> > 
> > ...
> >   
> > > +       union {
> > > +               /* sensor data buffer */
> > > +               u8 data[3];
> > > +               /* calibration data buffers */
> > > +               __le16 bmp280_cal[BMP280_CONTIGUOUS_CALIB_REGS / 2];
> > > +               __be16 bmp180_cal[BMP180_REG_CALIB_COUNT / 2];
> > > +       } buf __aligned(IIO_DMA_MINALIGN);  
> > 
> > Hmm... And which field in the struct defines which of the buffers is being
> > used?  

I think the answer to this is which callback is set in the chip_data structure
defines which one of the calibration buffers is in use for that purpose.
The one used for everything else is defined by the code path, not an explicit
variable.

There might be some (I haven't looked) but lock protection is unnecessary as
_cal buffers used before we register the device so there is no concurrency yet.

> 
> There's no concurrent use of the buffers. Calibration data is read during the
> initialization of the sensor. The data buffer is then used to store the raw data
> read from the measurement regs, and is also used a few times to read a the humid
> calibration on BME280, but again, in a sequential, non concurrent manner.
> 
> Regarding which calibration buffer is used, is the same situation as the
> calibration data union, helper functions and callback for the sensor use the
> buffer reserved for the sensor. I don't know if this is the best approach, I
> just followed what I saw previously on this drivers and others from IIO
> subsystem.
> 
> > Also, do you need a non-anonymous union?  
> 
> No I could use an anonymous function. Should I change it to an anonymous union?
yes.  That seems a good idea.

It's worth giving unions a name if you are using them such that you write via
one element and read via another (e.g. for type conversion) but where it's really
just a case of potential space saving like this, nice to use an anonymous union
and shorten all the lines accessing the elements.

> 
> > >  };  
> > 
> > ...
> >   
> > > +       /* parse temperature calibration data */  
> > 
> > Be consistent! Check all your patches for the consistency (comments,
> > other code style, etc).
> > 
> > ...
> >   
> > > +       calib->H5 = sign_extend32(((get_unaligned_le16(data->buf.data) >> 4)
> > > & 0xfff), 11);  
> > 
> > (It's not directly related to this change, but good to ask)
> > Are you going to change all those masks to use GENMASK()?  
> 
> I thought I made sense refresh previous code on the driver to use GENMASK() and
> FIELD_PREP and FIELD_GET helpers to use the same standards on the BMP380
> codepath. Having in mind other feedback you gave me on this iteration, this
> GENMASK() and FIELD_PREP/FIELD_GET changes make more sense in a prerequisite
> patch and not as part of patch 1.

Agreed. I was thinking the same thing.  Pulling out that conversion as a precursor
nop cleanup will make all the subsequent changes more readable. Great!

> 
> > ...
> >   
> > > +       struct bmp180_calib *calib = &data->calib.bmp180;
> > >         int ret;
> > >         int i;
> > > -       struct bmp180_calib *calib = &data->calib.bmp180;  
> > 
> > Exactly my point given the previous patch, now you have a ping-pong
> > style of changes: the introduced line in the series is being touched
> > again in the very same series without any need.  
> 
> Yup, apologies. I'll be more careful

I'm not particularly fussy about reverse xmas tree so wouldn't normally
advocate a cleanup patch just to reorder local variable definitions.
However, I think in this case it would be good to have such a precursor
patch so as to make the ordering more logical for the additions made
by the rest of the series.

Thanks,

Jonathan

> 
> > ...
> >   
> > >         u8 oss = data->oversampling_press;
> > > +       int ret;  
> > 
> > Ditto.
> >   
> 


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH v5 2/5] iio: pressure: bmp280: Fix alignment for DMA safety
  2022-08-07 11:55 ` [PATCH v5 2/5] iio: pressure: bmp280: Fix alignment for DMA safety Angel Iglesias
  2022-08-08  8:53   ` Andy Shevchenko
@ 2022-08-14 14:03   ` Jonathan Cameron
  1 sibling, 0 replies; 22+ messages in thread
From: Jonathan Cameron @ 2022-08-14 14:03 UTC (permalink / raw)
  To: Angel Iglesias
  Cc: linux-iio, Lars-Peter Clausen, Paul Cercueil, Ulf Hansson,
	Rafael J. Wysocki, linux-kernel

On Sun,  7 Aug 2022 13:55:15 +0200
Angel Iglesias <ang.iglesiasg@gmail.com> wrote:

> 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 new,
> DMA-safe, buffers.
> 
> Suggested-by: Jonathan Cameron <jic23@kernel.org>
> Signed-off-by: Angel Iglesias <ang.iglesiasg@gmail.com>
Hi Angel,

As you are doing a v6 anyway to address Andy's review, I
took another look and have a few additional comments below.
> ---
>  drivers/iio/pressure/bmp280-core.c | 122 ++++++++++++++---------------
>  drivers/iio/pressure/bmp280.h      |   3 +
>  2 files changed, 64 insertions(+), 61 deletions(-)
> 
> diff --git a/drivers/iio/pressure/bmp280-core.c b/drivers/iio/pressure/bmp280-core.c
> index a109c2609896..4cd657dcbfed 100644
> --- a/drivers/iio/pressure/bmp280-core.c
> +++ b/drivers/iio/pressure/bmp280-core.c
> @@ -31,6 +31,7 @@
>  #include <linux/completion.h>
>  #include <linux/pm_runtime.h>
>  #include <linux/random.h>
> +#include <asm/unaligned.h>
>  
>  #include "bmp280.h"
>  
> @@ -106,6 +107,18 @@ 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 data[3];
__le16 le16;
__be16 be16; 

added here would simplify some of the other changes below.

> +		/* calibration data buffers */
> +		__le16 bmp280_cal[BMP280_CONTIGUOUS_CALIB_REGS / 2];
> +		__be16 bmp180_cal[BMP180_REG_CALIB_COUNT / 2];
> +	} buf __aligned(IIO_DMA_MINALIGN);
>  };
>  
>  struct bmp280_chip_info {
> @@ -162,41 +175,29 @@ static int bmp280_read_calib(struct bmp280_data *data, unsigned int chip)
>  {
>  	int ret;
>  	unsigned int tmp;
> -	__le16 l16;
> -	__be16 b16;
>  	struct device *dev = data->dev;
> +	__le16 *t_buf = data->buf.bmp280_cal;
> +	__le16 *p_buf = &data->buf.bmp280_cal[T3+1];

spaces around +

>  	struct bmp280_calib *calib = &data->calib.bmp280;
> -	__le16 t_buf[BMP280_COMP_TEMP_REG_COUNT / 2];
> -	__le16 p_buf[BMP280_COMP_PRESS_REG_COUNT / 2];
>  
>  	/* Read temperature calibration values. */
>  	ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_TEMP_START,
> -			       t_buf, BMP280_COMP_TEMP_REG_COUNT);
> +			       data->buf.bmp280_cal, sizeof(data->buf.bmp280_cal));
Given we don't use the local variable until later (as can't get the size from it,
I would suggest only setting it further down.

>  	if (ret < 0) {
>  		dev_err(data->dev,
>  			"failed to read temperature calibration parameters\n");
>  		return ret;
>  	}
>  
> -	/* Toss the temperature calibration data into the entropy pool */
> -	add_device_randomness(t_buf, sizeof(t_buf));
> +	/* Toss the temperature and pressure calibration data into the entropy pool */
> +	add_device_randomness(data->buf.bmp280_cal, sizeof(data->buf.bmp280_cal));
>  
like here.
	t_buf = data->bmp280_cal;

or just don't bother with those at all as they don't greatly help readability over
	calib->T1 = le16_to_cpu(data->bmp280_cal[T1]);
similar for p_buf.
Note I haven't looked at the existing code to see if there are other reasons to
use t_buf etc, so  may be wrong on this!
It will as make this patch more complex even if the code ends up simpler as a result.

> +	/* parse temperature calibration data */
>  	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));
> -
> +	/* parse pressure calibration data */
>  	calib->P1 = le16_to_cpu(p_buf[P1]);
>  	calib->P2 = le16_to_cpu(p_buf[P2]);
>  	calib->P3 = le16_to_cpu(p_buf[P3]);
> @@ -224,12 +225,12 @@ static int bmp280_read_calib(struct bmp280_data *data, unsigned int chip)
>  	}
>  	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->buf.data, 2);

Bit nasty to read little endian into buf.data which I think is a u8 array.
Maybe we need another entry in that union for each of le16 and be16 similar to the
local variables previously in this function?
 
>  	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 = get_unaligned_le16(data->buf.data);
>  
>  	ret = regmap_read(data->regmap, BMP280_REG_COMP_H3, &tmp);
>  	if (ret < 0) {
> @@ -238,20 +239,20 @@ static int bmp280_read_calib(struct bmp280_data *data, unsigned int chip)
>  	}
>  	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->buf.data, 2);
>  	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(((get_unaligned_be16(data->buf.data) >> 4) & 0xff0) |
> +				  (get_unaligned_be16(data->buf.data) & 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->buf.data, 2);
>  	if (ret < 0) {
>  		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(((get_unaligned_le16(data->buf.data) >> 4) & 0xfff), 11);
>  
>  	ret = regmap_read(data->regmap, BMP280_REG_COMP_H6, &tmp);
>  	if (ret < 0) {

...

>  static int bmp280_read_humid(struct bmp280_data *data, int *val, int *val2)
>  {
> -	__be16 tmp;
>  	int ret;
>  	s32 adc_humidity;
>  	u32 comp_humidity;
> @@ -420,13 +420,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->buf.data, 2);
>  	if (ret < 0) {
>  		dev_err(data->dev, "failed to read humidity\n");
>  		return ret;
>  	}
>  
> -	adc_humidity = be16_to_cpu(tmp);
> +	adc_humidity = get_unaligned_be16(data->buf.data);

We are only unaligned because data is u8 and a dumb compiler might not realize the
alignment is forced.  Use the suggestion above of a couple more entries in the
union and we can switch back to be16_to_cpu()

>  	if (adc_humidity == BMP280_HUMIDITY_SKIPPED) {
>  		/* reading was skipped */
>  		dev_err(data->dev, "reading humidity skipped\n");
> @@ -767,7 +768,6 @@ static int bmp180_measure(struct bmp280_data *data, u8 ctrl_meas)
>  


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH v5 3/5] iio: pressure: bmp280: Add support for BMP380 sensor family
  2022-08-12 10:47     ` Angel Iglesias
@ 2022-08-14 14:11       ` Jonathan Cameron
  0 siblings, 0 replies; 22+ messages in thread
From: Jonathan Cameron @ 2022-08-14 14:11 UTC (permalink / raw)
  To: Angel Iglesias
  Cc: Andy Shevchenko, linux-iio, Lars-Peter Clausen, Andy Shevchenko,
	Nikita Yushchenko, Ulf Hansson, Rafael J. Wysocki, Paul Cercueil,
	Linux Kernel Mailing List

On Fri, 12 Aug 2022 12:47:20 +0200
Angel Iglesias <ang.iglesiasg@gmail.com> wrote:

> On lun, 2022-08-08 at 11:08 +0200, Andy Shevchenko wrote:
> > On Sun, Aug 7, 2022 at 1:56 PM Angel Iglesias <ang.iglesiasg@gmail.com> wrote:  
> > > 
> > > 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  
> > 
> > Missed period.
> > 
> > ...
> >   
> > >   *
> > > 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  
> > 
> > Seems like the above links are unresponsive now? Perhaps you may fix
> > them as well in a separate patch?  
> 
> Sure. Should I include this patch in this next version of this series, or should
> I send the patch as a standalone change?

Either way is fine. Thanks for tidying this up!

> 
> > > + *
> > > https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bmp388-ds001.pdf  
> > 
> > ...
> >   
> > > +/* See datasheet Section 3.11.1. */  
> > 
> > Again, a bit of consistency in (one-line) comments, please.
> >   
> > > +struct bmp380_calib {
> > > +       u16 T1;
> > > +       u16 T2;
> > > +       s8  T3;
> > > +       s16 P1;
> > > +       s16 P2;
> > > +       s8  P3;
> > > +       s8  P4;
> > > +       u16 P5;
> > > +       u16 P6;
> > > +       s8  P7;
> > > +       s8  P8;
> > > +       s16 P9;
> > > +       s8  P10;
> > > +       s8  P11;
> > > +};  
> > 
> > __packed ?
Nope - the unpacking is done on filling this array.

Could reorder to reduce size a little but given the naming vs datasheet
that would look very odd. I'd leave this as it is.


> >   
> > > +       /* Compensated pressure is in cPa (centipascals) */
> > > +       *val2 = 100000;  
> > 
> > Anything to use from units.h?

Not sure we want to add centi to killo conversion!
That combination is rather rare.

Jonathan

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH v5 3/5] iio: pressure: bmp280: Add support for BMP380 sensor family
  2022-08-07 11:55 ` [PATCH v5 3/5] iio: pressure: bmp280: Add support for BMP380 sensor family Angel Iglesias
  2022-08-08  9:08   ` Andy Shevchenko
@ 2022-08-14 14:15   ` Jonathan Cameron
  2022-08-14 14:37     ` Angel Iglesias
  1 sibling, 1 reply; 22+ messages in thread
From: Jonathan Cameron @ 2022-08-14 14:15 UTC (permalink / raw)
  To: Angel Iglesias
  Cc: linux-iio, Lars-Peter Clausen, Andy Shevchenko,
	Nikita Yushchenko, Ulf Hansson, Rafael J. Wysocki, Paul Cercueil,
	linux-kernel

On Sun,  7 Aug 2022 13:55:52 +0200
Angel Iglesias <ang.iglesiasg@gmail.com> wrote:

> 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
> 
> Signed-off-by: Angel Iglesias <ang.iglesiasg@gmail.com>

One additional comment from me inline.

Thanks,

Jonathan


>  	}
> @@ -1124,6 +1471,13 @@ int bmp280_common_probe(struct device *dev,
>  		return -EINVAL;
>  	}
>  
> +	/* BMP3xx requires soft-reset as part of initialization */
> +	if (chip_id == BMP380_CHIP_ID) {

I'd prefer this to be based on a flag in chip_info so that we can
trivially add it to future devices by just setting that flag for the
chip_info added for the new device.

> +		ret = bmp380_cmd(data, BMP380_CMD_SOFT_RESET);
> +		if (ret < 0)
> +			return ret;
> +	}
> +
>  	ret = data->chip_info->chip_config(data);
>  	if (ret < 0)
>  		return ret;


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH v5 1/5] iio: pressure: bmp280: simplify driver initialization logic
  2022-08-14 13:43   ` Jonathan Cameron
@ 2022-08-14 14:26     ` Angel Iglesias
  0 siblings, 0 replies; 22+ messages in thread
From: Angel Iglesias @ 2022-08-14 14:26 UTC (permalink / raw)
  To: Jonathan Cameron, Lars-Peter Clausen
  Cc: linux-iio, Ulf Hansson, Rafael J. Wysocki, Paul Cercueil, linux-kernel

On Sun, 2022-08-14 at 14:43 +0100, Jonathan Cameron wrote:
> On Sun,  7 Aug 2022 13:54:40 +0200
> Angel Iglesias <ang.iglesiasg@gmail.com> wrote:
> 
> > 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.
> > 
> > Revised BMP180 and BMP280 definitions and code functions to use GENMASK
> > and FIELD_PREP/FIELD_GET utilities to homogenize structure with more
> > recent drivers, in preparation for the patches adding support for the
> > BMP380 sensors.
> > 
> > Suggested-by: Jonathan Cameron <jic23@kernel.org>
> > Signed-off-by: Angel Iglesias <ang.iglesiasg@gmail.com>
> Hi Angel, not sure if I commented on this before, but this patch is doing
> several different things, so in the ideal case it would be split into
> 1: FIELD_PREP/FIELD_GET/GENMASK changes. 
> 2: Chipinfo related changes
> 3: Maybe the the reordering of defintions of local variables that Andy
>    indirectly referered to.
> 
> However, this is short enough to be fairly reviewable as it stands
> so from my point of view I'll accept leaving 1 and 2 combined if it is
> going to be a lot of work to separate them. Doesn't look like it will be hard
> but without trying I'm not totally sure!

Sure, splitting the patch and keeping each patch focused on one aspect makes
total sense to me. Thanks as always for your feedback!

> One question inline on what the chip parameter to the calibration functions
> is there for as it appears unused.
> 
> Thanks,
> 
> Jonathan
> 
> 
> > ---
> >  drivers/iio/pressure/bmp280-core.c | 120 ++++++++++++++++++-----------
> >  drivers/iio/pressure/bmp280.h      |  73 +++++++++---------
> >  2 files changed, 113 insertions(+), 80 deletions(-)
> > 
> > diff --git a/drivers/iio/pressure/bmp280-core.c
> > b/drivers/iio/pressure/bmp280-core.c
> > index fe7aa81e7cc9..a109c2609896 100644
> > --- a/drivers/iio/pressure/bmp280-core.c
> > +++ b/drivers/iio/pressure/bmp280-core.c
> > @@ -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>
> > @@ -107,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 *, unsigned int);
> >  };
> >  
> >  /*
> > @@ -147,15 +158,14 @@ 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, unsigned int chip)
> >  {
> >         int ret;
> >         unsigned int tmp;
> >         __le16 l16;
> >         __be16 b16;
> >         struct device *dev = data->dev;
> > +       struct bmp280_calib *calib = &data->calib.bmp280;
> >         __le16 t_buf[BMP280_COMP_TEMP_REG_COUNT / 2];
> >         __le16 p_buf[BMP280_COMP_PRESS_REG_COUNT / 2];
> >  
> > @@ -611,8 +621,8 @@ 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);
> > +       u8 osrs = FIELD_PREP(BMP280_OSRS_TEMP_MASK, data->oversampling_temp
> > + 1) |
> > +                 FIELD_PREP(BMP280_OSRS_PRESS_MASK, data-
> > >oversampling_press + 1);
> >  
> >         ret = regmap_write_bits(data->regmap, BMP280_REG_CTRL_MEAS,
> >                                  BMP280_OSRS_TEMP_MASK |
> > @@ -640,21 +650,38 @@ 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)
> >  {
> >         int ret;
> > -       u8 osrs = BMP280_OSRS_HUMIDITIY_X(data->oversampling_humid + 1);
> > +       u8 osrs = FIELD_PREP(BMP280_OSRS_HUMIDITY_MASK, data-
> > >oversampling_humid + 1);
> >  
> >         /*
> >          * Oversampling of humidity must be set before oversampling of
> > @@ -670,19 +697,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 = bmp280_read_calib,
> >  };
> >  
> >  static int bmp180_measure(struct bmp280_data *data, u8 ctrl_meas)
> > @@ -710,7 +745,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 =
> > @@ -735,7 +770,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;
> >  
> > @@ -748,11 +785,11 @@ 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, unsigned int chip)
> 
> What is chip used for?  If there will be a need for it in later patches, then
> it's fine to add the additional parameter now but please say why in the patch
> description.

In the codepath BMP/BME 280, chip contains the read chip id and is used to check
if humidity calibration needs to be loaded when the sensor is a BME280. I took a
conservative approach and introduced this field on bmp180 and bmp380 codepaths,
assigning the same signature of the three calibration loading functions and use
as callbacks.

Having in mind this parameter has no use in two cases out of three, I think I
could have done better by splitting the BMP/BME280 callback in one shared part
loading pressure and temperature params for both sensors, and a new callback for
BME280 invoking first the common code and then loading humidity params. If it
sounds good, I would include this change for next iteration.

> >  {
> >         int ret;
> >         int i;
> > +       struct bmp180_calib *calib = &data->calib.bmp180;
> >         __be16 buf[BMP180_REG_CALIB_COUNT / 2];
> >  
> >         ret = regmap_bulk_read(data->regmap, BMP180_REG_CALIB_START, buf,
> > @@ -832,7 +869,10 @@ static int bmp180_read_adc_press(struct bmp280_data
> > *data, int *val)
> >         __be32 tmp = 0;
> >         u8 oss = data->oversampling_press;
> >  
> > -       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;
> >  

Kind regards,
Angel 

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH v5 3/5] iio: pressure: bmp280: Add support for BMP380 sensor family
  2022-08-14 14:15   ` Jonathan Cameron
@ 2022-08-14 14:37     ` Angel Iglesias
  2022-08-14 16:56       ` Jonathan Cameron
  0 siblings, 1 reply; 22+ messages in thread
From: Angel Iglesias @ 2022-08-14 14:37 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: linux-iio, Lars-Peter Clausen, Andy Shevchenko,
	Nikita Yushchenko, Ulf Hansson, Rafael J. Wysocki, Paul Cercueil,
	linux-kernel

On Sun, 2022-08-14 at 15:15 +0100, Jonathan Cameron wrote:
> On Sun,  7 Aug 2022 13:55:52 +0200
> Angel Iglesias <ang.iglesiasg@gmail.com> wrote:
> 
> > 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
> > 
> > Signed-off-by: Angel Iglesias <ang.iglesiasg@gmail.com>
> 
> One additional comment from me inline.
> 
> Thanks,
> 
> Jonathan
> 
> 
> >         }
> > @@ -1124,6 +1471,13 @@ int bmp280_common_probe(struct device *dev,
> >                 return -EINVAL;
> >         }
> >  
> > +       /* BMP3xx requires soft-reset as part of initialization */
> > +       if (chip_id == BMP380_CHIP_ID) {
> 
> I'd prefer this to be based on a flag in chip_info so that we can
> trivially add it to future devices by just setting that flag for the
> chip_info added for the new device.

How a new init or preinit callback? For now only BMP380 chip would use it, but I
would like to get my hands on a BMP390 and the new BMP580 and extend the driver
to support for them.

> > +               ret = bmp380_cmd(data, BMP380_CMD_SOFT_RESET);
> > +               if (ret < 0)
> > +                       return ret;
> > +       }
> > +
> >         ret = data->chip_info->chip_config(data);
> >         if (ret < 0)
> >                 return ret;
> 

Kind regards,
Angel

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH v5 3/5] iio: pressure: bmp280: Add support for BMP380 sensor family
  2022-08-14 14:37     ` Angel Iglesias
@ 2022-08-14 16:56       ` Jonathan Cameron
  0 siblings, 0 replies; 22+ messages in thread
From: Jonathan Cameron @ 2022-08-14 16:56 UTC (permalink / raw)
  To: Angel Iglesias
  Cc: linux-iio, Lars-Peter Clausen, Andy Shevchenko,
	Nikita Yushchenko, Ulf Hansson, Rafael J. Wysocki, Paul Cercueil,
	linux-kernel

On Sun, 14 Aug 2022 16:37:58 +0200
Angel Iglesias <ang.iglesiasg@gmail.com> wrote:

> On Sun, 2022-08-14 at 15:15 +0100, Jonathan Cameron wrote:
> > On Sun,  7 Aug 2022 13:55:52 +0200
> > Angel Iglesias <ang.iglesiasg@gmail.com> wrote:
> >   
> > > 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
> > > 
> > > Signed-off-by: Angel Iglesias <ang.iglesiasg@gmail.com>  
> > 
> > One additional comment from me inline.
> > 
> > Thanks,
> > 
> > Jonathan
> > 
> >   
> > >         }
> > > @@ -1124,6 +1471,13 @@ int bmp280_common_probe(struct device *dev,
> > >                 return -EINVAL;
> > >         }
> > >  
> > > +       /* BMP3xx requires soft-reset as part of initialization */
> > > +       if (chip_id == BMP380_CHIP_ID) {  
> > 
> > I'd prefer this to be based on a flag in chip_info so that we can
> > trivially add it to future devices by just setting that flag for the
> > chip_info added for the new device.  
> 
> How a new init or preinit callback? For now only BMP380 chip would use it, but I
> would like to get my hands on a BMP390 and the new BMP580 and extend the driver
> to support for them.

Hmm. Good point, I'd failed to noticed the register is bmp380 specific currently.
Maybe one to leave for a future refactor if you get those newer parts.

Jonathan

> 
> > > +               ret = bmp380_cmd(data, BMP380_CMD_SOFT_RESET);
> > > +               if (ret < 0)
> > > +                       return ret;
> > > +       }
> > > +
> > >         ret = data->chip_info->chip_config(data);
> > >         if (ret < 0)
> > >                 return ret;  
> >   
> 
> Kind regards,
> Angel


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH v5 5/5] iio: pressure: bmp280: Add more tunable config parameters for BMP380
  2022-08-08  9:13   ` Andy Shevchenko
@ 2022-09-12  0:53     ` Angel Iglesias
  2022-09-15 13:33       ` Jonathan Cameron
  0 siblings, 1 reply; 22+ messages in thread
From: Angel Iglesias @ 2022-09-12  0:53 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: linux-iio, Jonathan Cameron, Lars-Peter Clausen, Paul Cercueil,
	Ulf Hansson, Rafael J. Wysocki, Linux Kernel Mailing List

On Mon, 2022-08-08 at 11:13 +0200, Andy Shevchenko wrote:
> On Sun, Aug 7, 2022 at 2:44 PM Angel Iglesias <ang.iglesiasg@gmail.com> wrote:
> > 
> > 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".
> 
> ...
> 
> > +static const int bmp380_odr_table[][2] = {
> 
> s32_fract ?

I modeled this bit and other ODR representations after the adxl355 driver. I see
that s32_fract would be a bit cleaner than having arrays inside arrays, but I'm
failing to see which additional advantages would provide.
Also, technically, these are precomputed frequencies, the first index is the
integer part and the second is the fractional part. The fractions would be
200/1, 200/2, 200/4 ... 200/131072

> > +       [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},
> > +};
> 
> ...
> 
> > +               ret = regmap_write_bits(data->regmap,
> > BMP380_REG_POWER_CONTROL,
> > +                                       BMP380_MODE_MASK,
> 
> > +                                       FIELD_PREP(BMP380_MODE_MASK,
> > +                                                  BMP380_MODE_SLEEP));
> 
> One line?
> 
> ...
> 
> > +               ret = regmap_write_bits(data->regmap,
> > BMP380_REG_POWER_CONTROL,
> > +                                       BMP380_MODE_MASK,
> 
> > +                                       FIELD_PREP(BMP380_MODE_MASK,
> > +                                                  BMP380_MODE_NORMAL));
> 
> Ditto.
> 
> ...
> 
> > +static const int bmp380_iir_filter_coeffs_avail[] = { 0, 1, 3, 7, 15, 31,
> > 63, 127 };
> 
> This seems like a power of two - 1, can it be replaced by a formula in the
> code?
> 


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH v5 5/5] iio: pressure: bmp280: Add more tunable config parameters for BMP380
  2022-09-12  0:53     ` Angel Iglesias
@ 2022-09-15 13:33       ` Jonathan Cameron
  0 siblings, 0 replies; 22+ messages in thread
From: Jonathan Cameron @ 2022-09-15 13:33 UTC (permalink / raw)
  To: Angel Iglesias
  Cc: Andy Shevchenko, linux-iio, Lars-Peter Clausen, Paul Cercueil,
	Ulf Hansson, Rafael J. Wysocki, Linux Kernel Mailing List

On Mon, 12 Sep 2022 02:53:06 +0200
Angel Iglesias <ang.iglesiasg@gmail.com> wrote:

> On Mon, 2022-08-08 at 11:13 +0200, Andy Shevchenko wrote:
> > On Sun, Aug 7, 2022 at 2:44 PM Angel Iglesias <ang.iglesiasg@gmail.com> wrote:  
> > > 
> > > 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".  
> > 
> > ...
> >   
> > > +static const int bmp380_odr_table[][2] = {  
> > 
> > s32_fract ?  
> 
> I modeled this bit and other ODR representations after the adxl355 driver. I see
> that s32_fract would be a bit cleaner than having arrays inside arrays, but I'm
> failing to see which additional advantages would provide.
> Also, technically, these are precomputed frequencies, the first index is the
> integer part and the second is the fractional part. The fractions would be
> 200/1, 200/2, 200/4 ... 200/131072
> 
Agreed. Don't use s32_fract for this.  It would be misleading.

Jonathan

> > > +       [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},
> > > +};  
> > 
> > ...
> >   
> > > +               ret = regmap_write_bits(data->regmap,
> > > BMP380_REG_POWER_CONTROL,
> > > +                                       BMP380_MODE_MASK,  
> >   
> > > +                                       FIELD_PREP(BMP380_MODE_MASK,
> > > +                                                  BMP380_MODE_SLEEP));  
> > 
> > One line?
> > 
> > ...
> >   
> > > +               ret = regmap_write_bits(data->regmap,
> > > BMP380_REG_POWER_CONTROL,
> > > +                                       BMP380_MODE_MASK,  
> >   
> > > +                                       FIELD_PREP(BMP380_MODE_MASK,
> > > +                                                  BMP380_MODE_NORMAL));  
> > 
> > Ditto.
> > 
> > ...
> >   
> > > +static const int bmp380_iir_filter_coeffs_avail[] = { 0, 1, 3, 7, 15, 31,
> > > 63, 127 };  
> > 
> > This seems like a power of two - 1, can it be replaced by a formula in the
> > code?
> >   
> 


^ permalink raw reply	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2022-09-15 13:33 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-08-07 11:52 [PATCH v5 0/5] Add support for pressure sensor Bosch BMP380 Angel Iglesias
2022-08-07 11:54 ` [PATCH v5 1/5] iio: pressure: bmp280: simplify driver initialization logic Angel Iglesias
2022-08-08  8:18   ` Andy Shevchenko
2022-08-14 13:43   ` Jonathan Cameron
2022-08-14 14:26     ` Angel Iglesias
2022-08-07 11:55 ` [PATCH v5 2/5] iio: pressure: bmp280: Fix alignment for DMA safety Angel Iglesias
2022-08-08  8:53   ` Andy Shevchenko
2022-08-12  9:59     ` Angel Iglesias
2022-08-14 13:52       ` Jonathan Cameron
2022-08-14 14:03   ` Jonathan Cameron
2022-08-07 11:55 ` [PATCH v5 3/5] iio: pressure: bmp280: Add support for BMP380 sensor family Angel Iglesias
2022-08-08  9:08   ` Andy Shevchenko
2022-08-12 10:47     ` Angel Iglesias
2022-08-14 14:11       ` Jonathan Cameron
2022-08-14 14:15   ` Jonathan Cameron
2022-08-14 14:37     ` Angel Iglesias
2022-08-14 16:56       ` Jonathan Cameron
2022-08-07 11:56 ` [PATCH v5 4/5] dt-bindings: iio: pressure: bmp085: Add BMP380 compatible string Angel Iglesias
2022-08-07 11:57 ` [PATCH v5 5/5] iio: pressure: bmp280: Add more tunable config parameters for BMP380 Angel Iglesias
2022-08-08  9:13   ` Andy Shevchenko
2022-09-12  0:53     ` Angel Iglesias
2022-09-15 13:33       ` Jonathan Cameron

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.