devicetree.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v8 0/4] pressure: bmp280: Minor cleanup and interrupt support
@ 2024-10-07 19:49 Vasileios Amoiridis
  2024-10-07 19:49 ` [PATCH v8 1/4] iio: pressure: bmp280: Use sleep and forced mode for oneshot captures Vasileios Amoiridis
                   ` (3 more replies)
  0 siblings, 4 replies; 12+ messages in thread
From: Vasileios Amoiridis @ 2024-10-07 19:49 UTC (permalink / raw)
  To: jic23, lars, robh, krzk+dt, conor+dt, andriy.shevchenko
  Cc: vassilisamir, ang.iglesiasg, linus.walleij, biju.das.jz,
	javier.carrasco.cruz, semen.protsenko, 579lpy, ak, linux-iio,
	devicetree, linux-kernel, christophe.jaillet

Changes in v8:

Rebased and tested on testing branch of iio.git since [0] was accepted.

[1]: https://lore.kernel.org/linux-iio/20240930202353.38203-1-vassilisamir@gmail.com

---
v7: https://lore.kernel.org/linux-iio/20240914002900.45158-1-vassilisamir@gmail.com
v6: https://lore.kernel.org/linux-iio/20240912233234.45519-1-vassilisamir@gmail.com
v5: https://lore.kernel.org/linux-iio/20240902184222.24874-1-vassilisamir@gmail.com
v4: https://lore.kernel.org/linux-iio/20240828205128.92145-1-vassilisamir@gmail.com
v3: https://lore.kernel.org/linux-iio/20240823181714.64545-1-vassilisamir@gmail.com
v2: https://lore.kernel.org/linux-iio/20240725231039.614536-1-vassilisamir@gmail.com
v1: https://lore.kernel.org/linux-iio/20240711211558.106327-1-vassilisamir@gmail.com

Vasileios Amoiridis (4):
  iio: pressure: bmp280: Use sleep and forced mode for oneshot captures
  dt-bindings: iio: pressure: bmp085: Add interrupts for BMP3xx and
    BMP5xx devices
  iio: pressure: bmp280: Add data ready trigger support
  iio: pressure: bmp280: Move bmp085 interrupt to new configuration

 .../bindings/iio/pressure/bmp085.yaml         |  22 +-
 drivers/iio/pressure/bmp280-core.c            | 580 ++++++++++++++++--
 drivers/iio/pressure/bmp280-i2c.c             |   4 +-
 drivers/iio/pressure/bmp280-spi.c             |   4 +-
 drivers/iio/pressure/bmp280.h                 |  43 ++
 5 files changed, 612 insertions(+), 41 deletions(-)


base-commit: 96be67caa0f0420d4128cb67f07bbd7a6f49e03a
-- 
2.25.1


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

* [PATCH v8 1/4] iio: pressure: bmp280: Use sleep and forced mode for oneshot captures
  2024-10-07 19:49 [PATCH v8 0/4] pressure: bmp280: Minor cleanup and interrupt support Vasileios Amoiridis
@ 2024-10-07 19:49 ` Vasileios Amoiridis
  2024-10-11  4:32   ` kernel test robot
  2024-10-12 16:03   ` Jonathan Cameron
  2024-10-07 19:49 ` [PATCH v8 2/4] dt-bindings: iio: pressure: bmp085: Add interrupts for BMP3xx and BMP5xx devices Vasileios Amoiridis
                   ` (2 subsequent siblings)
  3 siblings, 2 replies; 12+ messages in thread
From: Vasileios Amoiridis @ 2024-10-07 19:49 UTC (permalink / raw)
  To: jic23, lars, robh, krzk+dt, conor+dt, andriy.shevchenko
  Cc: vassilisamir, ang.iglesiasg, linus.walleij, biju.das.jz,
	javier.carrasco.cruz, semen.protsenko, 579lpy, ak, linux-iio,
	devicetree, linux-kernel, christophe.jaillet

Add forced mode support in sensors BMP28x, BME28x, BMP3xx and BMP58x.
Sensors BMP18x and BMP085 are old and do not support this feature so
their operation is not affected at all.

Essentially, up to now, the rest of the sensors were used in normal mode
all the time. This means that they are continuously doing measurements
even though these measurements are not used. Even though the sensor does
provide PM support, to cover all the possible use cases, the sensor needs
to go into sleep mode and wake up whenever necessary.

The idea is that the sensor is by default in sleep mode, wakes up in
forced mode when a oneshot capture is requested, or in normal mode
when the buffer is enabled. The difference lays in the fact that in
forced mode, the sensor does only one conversion and goes back to sleep
while in normal mode, the sensor does continuous measurements with the
frequency that was set in the ODR registers.

The bmpX_chip_config() functions which are responsible for applying
the requested configuration to the sensor, are modified accordingly
in order to set the sensor by default in sleep mode.

DEEP STANDBY, Low Power NORMAL and CONTINUOUS modes, supported only by
the BMP58x version, are not added.

Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Vasileios Amoiridis <vassilisamir@gmail.com>
---
 drivers/iio/pressure/bmp280-core.c | 296 +++++++++++++++++++++++++++--
 drivers/iio/pressure/bmp280.h      |  21 ++
 2 files changed, 296 insertions(+), 21 deletions(-)

diff --git a/drivers/iio/pressure/bmp280-core.c b/drivers/iio/pressure/bmp280-core.c
index 6811619c6f11..9ad29cf4c2ac 100644
--- a/drivers/iio/pressure/bmp280-core.c
+++ b/drivers/iio/pressure/bmp280-core.c
@@ -16,6 +16,11 @@
  * https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bmp390-ds002.pdf
  * https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bmp581-ds004.pdf
  *
+ * Sensor API:
+ * https://github.com/boschsensortec/BME280_SensorAPI
+ * https://github.com/boschsensortec/BMP3_SensorAPI
+ * https://github.com/boschsensortec/BMP5_SensorAPI
+ *
  * Notice:
  * The link to the bmp180 datasheet points to an outdated version missing these changes:
  * - Changed document referral from ANP015 to BST-MPS-AN004-00 on page 26
@@ -616,6 +621,14 @@ static int bmp280_read_raw_impl(struct iio_dev *indio_dev,
 
 	switch (mask) {
 	case IIO_CHAN_INFO_PROCESSED:
+		ret = data->chip_info->set_mode(data, BMP280_FORCED);
+		if (ret)
+			return ret;
+
+		ret = data->chip_info->wait_conv(data);
+		if (ret)
+			return ret;
+
 		switch (chan->type) {
 		case IIO_HUMIDITYRELATIVE:
 			ret = data->chip_info->read_humid(data, &chan_value);
@@ -645,6 +658,14 @@ static int bmp280_read_raw_impl(struct iio_dev *indio_dev,
 			return -EINVAL;
 		}
 	case IIO_CHAN_INFO_RAW:
+		ret = data->chip_info->set_mode(data, BMP280_FORCED);
+		if (ret)
+			return ret;
+
+		ret = data->chip_info->wait_conv(data);
+		if (ret)
+			return ret;
+
 		switch (chan->type) {
 		case IIO_HUMIDITYRELATIVE:
 			ret = data->chip_info->read_humid(data, &chan_value);
@@ -991,6 +1012,69 @@ static int bmp280_preinit(struct bmp280_data *data)
 	return 0;
 }
 
+static const u8 bmp280_operation_mode[] = {
+	BMP280_MODE_SLEEP, BMP280_MODE_FORCED, BMP280_MODE_NORMAL,
+};
+
+static int bmp280_set_mode(struct bmp280_data *data, enum bmp280_op_mode mode)
+{
+	int ret;
+
+	switch (mode) {
+	case BMP280_SLEEP:
+	case BMP280_FORCED:
+	case BMP280_NORMAL:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	ret = regmap_write_bits(data->regmap, BMP280_REG_CTRL_MEAS,
+				BMP280_MODE_MASK, bmp280_operation_mode[mode]);
+	if (ret) {
+		dev_err(data->dev, "failed to  write ctrl_meas register.\n");
+		return ret;
+	}
+
+	data->op_mode = mode;
+
+	return 0;
+}
+
+static int bmp280_wait_conv(struct bmp280_data *data)
+{
+	unsigned int reg, meas_time_us;
+	int ret;
+
+	/* Check if we are using a BME280 device */
+	if (data->oversampling_humid)
+		meas_time_us += BMP280_PRESS_HUMID_MEAS_OFFSET +
+				BIT(data->oversampling_humid) * BMP280_MEAS_DUR;
+
+	/* Pressure measurement time */
+	meas_time_us += BMP280_PRESS_HUMID_MEAS_OFFSET +
+			BIT(data->oversampling_press) * BMP280_MEAS_DUR;
+
+	/* Temperature measurement time */
+	meas_time_us += BIT(data->oversampling_temp) * BMP280_MEAS_DUR;
+
+	/* Waiting time according to the BM(P/E)2 Sensor API */
+	fsleep(meas_time_us);
+
+	ret = regmap_read(data->regmap, BMP280_REG_STATUS, &reg);
+	if (ret) {
+		dev_err(data->dev, "failed to read status register.\n");
+		return ret;
+	}
+
+	if (reg & BMP280_REG_STATUS_MEAS_BIT) {
+		dev_err(data->dev, "Measurement cycle didn't complete.\n");
+		return -EBUSY;
+	}
+
+	return 0;
+}
+
 static int bmp280_chip_config(struct bmp280_data *data)
 {
 	u8 osrs = FIELD_PREP(BMP280_OSRS_TEMP_MASK, data->oversampling_temp + 1) |
@@ -1001,7 +1085,7 @@ static int bmp280_chip_config(struct bmp280_data *data)
 				BMP280_OSRS_TEMP_MASK |
 				BMP280_OSRS_PRESS_MASK |
 				BMP280_MODE_MASK,
-				osrs | BMP280_MODE_NORMAL);
+				osrs | BMP280_MODE_SLEEP);
 	if (ret) {
 		dev_err(data->dev, "failed to write ctrl_meas register\n");
 		return ret;
@@ -1111,6 +1195,8 @@ const struct bmp280_chip_info bmp280_chip_info = {
 	.read_temp = bmp280_read_temp,
 	.read_press = bmp280_read_press,
 	.read_calib = bmp280_read_calib,
+	.set_mode = bmp280_set_mode,
+	.wait_conv = bmp280_wait_conv,
 	.preinit = bmp280_preinit,
 
 	.trigger_handler = bmp280_trigger_handler,
@@ -1235,6 +1321,8 @@ const struct bmp280_chip_info bme280_chip_info = {
 	.read_press = bmp280_read_press,
 	.read_humid = bme280_read_humid,
 	.read_calib = bme280_read_calib,
+	.set_mode = bmp280_set_mode,
+	.wait_conv = bmp280_wait_conv,
 	.preinit = bmp280_preinit,
 
 	.trigger_handler = bme280_trigger_handler,
@@ -1522,6 +1610,71 @@ static int bmp380_preinit(struct bmp280_data *data)
 	return bmp380_cmd(data, BMP380_CMD_SOFT_RESET);
 }
 
+static const u8 bmp380_operation_mode[] = {
+	BMP380_MODE_SLEEP, BMP380_MODE_FORCED, BMP380_MODE_NORMAL,
+};
+
+static int bmp380_set_mode(struct bmp280_data *data, enum bmp280_op_mode mode)
+{
+	int ret;
+
+	switch (mode) {
+	case BMP280_SLEEP:
+	case BMP280_FORCED:
+	case BMP280_NORMAL:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	ret = regmap_write_bits(data->regmap, BMP380_REG_POWER_CONTROL,
+				BMP380_MODE_MASK,
+				FIELD_PREP(BMP380_MODE_MASK,
+					   bmp380_operation_mode[mode]));
+	if (ret) {
+		dev_err(data->dev, "failed to  write power control register.\n");
+		return ret;
+	}
+
+	data->op_mode = mode;
+
+	return 0;
+}
+
+static int bmp380_wait_conv(struct bmp280_data *data)
+{
+	unsigned int reg;
+	int ret, meas_time_us;
+
+	/* Offset measurement time */
+	meas_time_us = BMP380_MEAS_OFFSET;
+
+	/* Pressure measurement time */
+	meas_time_us += BMP380_PRESS_MEAS_OFFSET +
+		     BIT(data->oversampling_press) * BMP380_MEAS_DUR;
+
+	/* Temperature measurement time */
+	meas_time_us += BMP380_TEMP_MEAS_OFFSET +
+		     BIT(data->oversampling_temp) * BMP380_MEAS_DUR;
+
+	/* Measurement time defined in Datasheet Section 3.9.2 */
+	fsleep(meas_time_us);
+
+	ret = regmap_read(data->regmap, BMP380_REG_STATUS, &reg);
+	if (ret) {
+		dev_err(data->dev, "failed to read status register.\n");
+		return ret;
+	}
+
+	if (!((reg & BMP380_STATUS_DRDY_PRESS_MASK) &&
+	      (reg & BMP380_STATUS_DRDY_TEMP_MASK))) {
+		dev_err(data->dev, "Measurement cycle didn't complete.\n");
+		return -EBUSY;
+	}
+
+	return 0;
+}
+
 static int bmp380_chip_config(struct bmp280_data *data)
 {
 	bool change = false, aux;
@@ -1582,17 +1735,19 @@ static int bmp380_chip_config(struct bmp280_data *data)
 		 * 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));
+		ret = bmp380_set_mode(data, BMP280_SLEEP);
 		if (ret) {
 			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));
+
+		/*
+		 * According to the BMP3 Sensor API, the sensor needs 5ms
+		 * in order to go to the sleep mode.
+		 */
+		fsleep(5 * USEC_PER_MSEC);
+
+		ret = bmp380_set_mode(data, BMP280_NORMAL);
 		if (ret) {
 			dev_err(data->dev, "failed to set normal mode\n");
 			return ret;
@@ -1618,7 +1773,16 @@ static int bmp380_chip_config(struct bmp280_data *data)
 		}
 	}
 
-	return 0;
+	/* Dummy read to empty data registers. */
+	ret = bmp380_read_press(data, &tmp);
+	if (ret)
+		return ret;
+
+	ret = bmp380_set_mode(data, BMP280_SLEEP);
+	if (ret)
+		dev_err(data->dev, "failed to set sleep mode.\n");
+
+	return ret;
 }
 
 static irqreturn_t bmp380_trigger_handler(int irq, void *p)
@@ -1714,6 +1878,8 @@ const struct bmp280_chip_info bmp380_chip_info = {
 	.read_temp = bmp380_read_temp,
 	.read_press = bmp380_read_press,
 	.read_calib = bmp380_read_calib,
+	.set_mode = bmp380_set_mode,
+	.wait_conv = bmp380_wait_conv,
 	.preinit = bmp380_preinit,
 
 	.trigger_handler = bmp380_trigger_handler,
@@ -2101,6 +2267,75 @@ static int bmp580_preinit(struct bmp280_data *data)
 	return PTR_ERR_OR_ZERO(devm_nvmem_register(config.dev, &config));
 }
 
+static const u8 bmp580_operation_mode[] = {
+	BMP580_MODE_SLEEP, BMP580_MODE_FORCED, BMP580_MODE_NORMAL,
+};
+
+static int bmp580_set_mode(struct bmp280_data *data, enum bmp280_op_mode mode)
+{
+	struct device *dev = data->dev;
+	int ret;
+
+	switch (mode) {
+	case BMP280_SLEEP:
+	case BMP280_NORMAL:
+		break;
+	case BMP280_FORCED:
+		ret = regmap_set_bits(data->regmap, BMP580_REG_DSP_CONFIG,
+				      BMP580_DSP_IIR_FORCED_FLUSH);
+		if (ret) {
+			dev_err(dev, "Could not flush IIR filter constants.\n");
+			return ret;
+		}
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	ret = regmap_write_bits(data->regmap, BMP580_REG_ODR_CONFIG,
+				BMP580_MODE_MASK,
+				FIELD_PREP(BMP580_MODE_MASK,
+					   bmp580_operation_mode[mode]));
+	if (ret) {
+		dev_err(dev, "failed to  write power control register.\n");
+		return ret;
+	}
+
+	data->op_mode = mode;
+
+	return 0;
+}
+
+static int bmp580_wait_conv(struct bmp280_data *data)
+{
+	/*
+	 * Taken from datasheet, Section 2 "Specification, Table 3 "Electrical
+	 * characteristics.
+	 */
+	static const int time_conv_press[] = {
+		0, 1050, 1785, 3045, 5670, 10920, 21420, 42420,
+		84420,
+	};
+	static const int time_conv_temp[] = {
+		0, 1050, 1105, 1575, 2205, 3465, 6090, 11340,
+		21840,
+	};
+	int meas_time_us;
+
+	meas_time_us = 4 * USEC_PER_MSEC +
+		       time_conv_temp[data->oversampling_temp] +
+		       time_conv_press[data->oversampling_press];
+
+	/*
+	 * Measurement time mentioned in Chapter 2, Table 4 of the datasheet.
+	 * The extra 4ms is the required mode change to start of measurement
+	 * time.
+	 */
+	fsleep(meas_time_us);
+
+	return 0;
+}
+
 static int bmp580_chip_config(struct bmp280_data *data)
 {
 	bool change = false, aux;
@@ -2171,17 +2406,6 @@ static int bmp580_chip_config(struct bmp280_data *data)
 		return ret;
 	}
 
-	/* Restore sensor to normal operation mode */
-	ret = regmap_write_bits(data->regmap, BMP580_REG_ODR_CONFIG,
-				BMP580_MODE_MASK,
-				FIELD_PREP(BMP580_MODE_MASK, BMP580_MODE_NORMAL));
-	if (ret) {
-		dev_err(data->dev, "failed to set normal mode\n");
-		return ret;
-	}
-	/* From datasheet's table 4: electrical characteristics */
-	usleep_range(3000, 3500);
-
 	if (change) {
 		/*
 		 * Check if ODR and OSR settings are valid or we are
@@ -2279,6 +2503,8 @@ const struct bmp280_chip_info bmp580_chip_info = {
 	.chip_config = bmp580_chip_config,
 	.read_temp = bmp580_read_temp,
 	.read_press = bmp580_read_press,
+	.set_mode = bmp580_set_mode,
+	.wait_conv = bmp580_wait_conv,
 	.preinit = bmp580_preinit,
 
 	.trigger_handler = bmp580_trigger_handler,
@@ -2526,6 +2752,19 @@ static int bmp180_read_press(struct bmp280_data *data, u32 *comp_press)
 	return 0;
 }
 
+/* Keep compatibility with newer generations of the sensor */
+static int bmp180_set_mode(struct bmp280_data *data, enum bmp280_op_mode mode)
+{
+	return 0;
+}
+
+/* Keep compatibility with newer generations of the sensor */
+static int bmp180_wait_conv(struct bmp280_data *data)
+{
+	return 0;
+}
+
+/* Keep compatibility with newer generations of the sensor */
 static int bmp180_chip_config(struct bmp280_data *data)
 {
 	return 0;
@@ -2597,6 +2836,8 @@ const struct bmp280_chip_info bmp180_chip_info = {
 	.read_temp = bmp180_read_temp,
 	.read_press = bmp180_read_press,
 	.read_calib = bmp180_read_calib,
+	.set_mode = bmp180_set_mode,
+	.wait_conv = bmp180_wait_conv,
 
 	.trigger_handler = bmp180_trigger_handler,
 };
@@ -2649,6 +2890,7 @@ static int bmp280_buffer_preenable(struct iio_dev *indio_dev)
 	struct bmp280_data *data = iio_priv(indio_dev);
 
 	pm_runtime_get_sync(data->dev);
+	data->chip_info->set_mode(data, BMP280_NORMAL);
 
 	return 0;
 }
@@ -2819,6 +3061,10 @@ int bmp280_common_probe(struct device *dev,
 			return ret;
 	}
 
+	ret = data->chip_info->set_mode(data, BMP280_SLEEP);
+	if (ret)
+		return dev_err_probe(dev, ret, "Failed to set sleep mode\n");
+
 	/* Enable runtime PM */
 	pm_runtime_get_noresume(dev);
 	pm_runtime_set_active(dev);
@@ -2844,6 +3090,9 @@ static int bmp280_runtime_suspend(struct device *dev)
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
 	struct bmp280_data *data = iio_priv(indio_dev);
 
+	data->chip_info->set_mode(data, BMP280_SLEEP);
+
+	fsleep(data->start_up_time);
 	return regulator_bulk_disable(BMP280_NUM_SUPPLIES, data->supplies);
 }
 
@@ -2858,7 +3107,12 @@ static int bmp280_runtime_resume(struct device *dev)
 		return ret;
 
 	usleep_range(data->start_up_time, data->start_up_time + 100);
-	return data->chip_info->chip_config(data);
+
+	ret = data->chip_info->chip_config(data);
+	if (ret)
+		return ret;
+
+	return data->chip_info->set_mode(data, data->op_mode);
 }
 
 EXPORT_RUNTIME_DEV_PM_OPS(bmp280_dev_pm_ops, bmp280_runtime_suspend,
diff --git a/drivers/iio/pressure/bmp280.h b/drivers/iio/pressure/bmp280.h
index dc1bf04cb0b5..3babf90ce73c 100644
--- a/drivers/iio/pressure/bmp280.h
+++ b/drivers/iio/pressure/bmp280.h
@@ -170,6 +170,11 @@
 #define BMP380_MODE_FORCED		1
 #define BMP380_MODE_NORMAL		3
 
+#define BMP380_MEAS_OFFSET		234
+#define BMP380_MEAS_DUR			2020
+#define BMP380_TEMP_MEAS_OFFSET		163
+#define BMP380_PRESS_MEAS_OFFSET	392
+
 #define BMP380_MIN_TEMP			-4000
 #define BMP380_MAX_TEMP			8500
 #define BMP380_MIN_PRES			3000000
@@ -206,6 +211,7 @@
 #define BMP280_REG_CTRL_MEAS		0xF4
 #define BMP280_REG_STATUS		0xF3
 #define BMP280_REG_STATUS_IM_UPDATE	BIT(0)
+#define BMP280_REG_STATUS_MEAS_BIT	BIT(3)
 #define BMP280_REG_RESET		0xE0
 #define BMP280_RST_SOFT_CMD		0xB6
 
@@ -246,6 +252,10 @@
 #define BMP280_MODE_FORCED		1
 #define BMP280_MODE_NORMAL		3
 
+#define BMP280_MEAS_OFFSET		1250
+#define BMP280_MEAS_DUR			2300
+#define BMP280_PRESS_HUMID_MEAS_OFFSET	575
+
 /* BME280 specific registers */
 #define BME280_REG_HUMIDITY_LSB		0xFE
 #define BME280_REG_HUMIDITY_MSB		0xFD
@@ -385,6 +395,12 @@ struct bmp380_calib {
 	s8  P11;
 };
 
+enum bmp280_op_mode {
+	BMP280_SLEEP,
+	BMP280_FORCED,
+	BMP280_NORMAL,
+};
+
 struct bmp280_data {
 	struct device *dev;
 	struct mutex lock;
@@ -423,6 +439,9 @@ struct bmp280_data {
 	u8 sensor_data[ALIGN(sizeof(s32) * BME280_NUM_MAX_CHANNELS, sizeof(s64))
 		       + sizeof(s64)] __aligned(sizeof(s64));
 
+	/* Value to hold the current operation mode of the device */
+	enum bmp280_op_mode op_mode;
+
 	/*
 	 * DMA (thus cache coherency maintenance) may require the
 	 * transfer buffers to live in their own cache lines.
@@ -487,6 +506,8 @@ struct bmp280_chip_info {
 	int (*read_humid)(struct bmp280_data *data, u32 *adc_humidity);
 	int (*read_calib)(struct bmp280_data *data);
 	int (*preinit)(struct bmp280_data *data);
+	int (*set_mode)(struct bmp280_data *data, enum bmp280_op_mode mode);
+	int (*wait_conv)(struct bmp280_data *data);
 
 	irqreturn_t (*trigger_handler)(int irq, void *p);
 };
-- 
2.25.1


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

* [PATCH v8 2/4] dt-bindings: iio: pressure: bmp085: Add interrupts for BMP3xx and BMP5xx devices
  2024-10-07 19:49 [PATCH v8 0/4] pressure: bmp280: Minor cleanup and interrupt support Vasileios Amoiridis
  2024-10-07 19:49 ` [PATCH v8 1/4] iio: pressure: bmp280: Use sleep and forced mode for oneshot captures Vasileios Amoiridis
@ 2024-10-07 19:49 ` Vasileios Amoiridis
  2024-10-07 19:49 ` [PATCH v8 3/4] iio: pressure: bmp280: Add data ready trigger support Vasileios Amoiridis
  2024-10-07 19:49 ` [PATCH v8 4/4] iio: pressure: bmp280: Move bmp085 interrupt to new configuration Vasileios Amoiridis
  3 siblings, 0 replies; 12+ messages in thread
From: Vasileios Amoiridis @ 2024-10-07 19:49 UTC (permalink / raw)
  To: jic23, lars, robh, krzk+dt, conor+dt, andriy.shevchenko
  Cc: vassilisamir, ang.iglesiasg, linus.walleij, biju.das.jz,
	javier.carrasco.cruz, semen.protsenko, 579lpy, ak, linux-iio,
	devicetree, linux-kernel, christophe.jaillet, Conor Dooley

Add interrupt options for BMP3xx and BMP5xx devices as well.

Acked-by: Conor Dooley <conor.dooley@microchip.com>
Signed-off-by: Vasileios Amoiridis <vassilisamir@gmail.com>
---
 .../bindings/iio/pressure/bmp085.yaml         | 22 +++++++++++++++++--
 1 file changed, 20 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/iio/pressure/bmp085.yaml b/Documentation/devicetree/bindings/iio/pressure/bmp085.yaml
index 6fda887ee9d4..cb201cecfa1a 100644
--- a/Documentation/devicetree/bindings/iio/pressure/bmp085.yaml
+++ b/Documentation/devicetree/bindings/iio/pressure/bmp085.yaml
@@ -47,15 +47,33 @@ properties:
     maxItems: 1
 
   interrupts:
-    description:
-      interrupt mapping for IRQ (BMP085 only)
     maxItems: 1
 
+  drive-open-drain:
+    description:
+      set if the interrupt pin should be configured as open drain.
+      If not set, defaults to push-pull configuration.
+    type: boolean
+
 required:
   - compatible
   - vddd-supply
   - vdda-supply
 
+allOf:
+  - if:
+      properties:
+        compatible:
+          not:
+            contains:
+              enum:
+                - bosch,bmp085
+                - bosch,bmp380
+                - bosch,bmp580
+    then:
+      properties:
+        interrupts: false
+
 additionalProperties: false
 
 examples:
-- 
2.25.1


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

* [PATCH v8 3/4] iio: pressure: bmp280: Add data ready trigger support
  2024-10-07 19:49 [PATCH v8 0/4] pressure: bmp280: Minor cleanup and interrupt support Vasileios Amoiridis
  2024-10-07 19:49 ` [PATCH v8 1/4] iio: pressure: bmp280: Use sleep and forced mode for oneshot captures Vasileios Amoiridis
  2024-10-07 19:49 ` [PATCH v8 2/4] dt-bindings: iio: pressure: bmp085: Add interrupts for BMP3xx and BMP5xx devices Vasileios Amoiridis
@ 2024-10-07 19:49 ` Vasileios Amoiridis
  2024-10-12 16:08   ` Jonathan Cameron
  2024-10-07 19:49 ` [PATCH v8 4/4] iio: pressure: bmp280: Move bmp085 interrupt to new configuration Vasileios Amoiridis
  3 siblings, 1 reply; 12+ messages in thread
From: Vasileios Amoiridis @ 2024-10-07 19:49 UTC (permalink / raw)
  To: jic23, lars, robh, krzk+dt, conor+dt, andriy.shevchenko
  Cc: vassilisamir, ang.iglesiasg, linus.walleij, biju.das.jz,
	javier.carrasco.cruz, semen.protsenko, 579lpy, ak, linux-iio,
	devicetree, linux-kernel, christophe.jaillet

The BMP3xx and BMP5xx sensors have an interrupt pin which can be used as
a trigger for when there are data ready in the sensor for pick up.

This use case is used along with NORMAL_MODE in the sensor, which allows
the sensor to do consecutive measurements depending on the ODR rate value.

The trigger pin can be configured to be open-drain or push-pull and either
rising or falling edge.

No support is added yet for interrupts for FIFO, WATERMARK and out of range
values.

Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Vasileios Amoiridis <vassilisamir@gmail.com>
---
 drivers/iio/pressure/bmp280-core.c | 225 ++++++++++++++++++++++++++++-
 drivers/iio/pressure/bmp280.h      |  21 +++
 2 files changed, 244 insertions(+), 2 deletions(-)

diff --git a/drivers/iio/pressure/bmp280-core.c b/drivers/iio/pressure/bmp280-core.c
index 9ad29cf4c2ac..5779e1977a7a 100644
--- a/drivers/iio/pressure/bmp280-core.c
+++ b/drivers/iio/pressure/bmp280-core.c
@@ -42,12 +42,14 @@
 #include <linux/module.h>
 #include <linux/nvmem-provider.h>
 #include <linux/pm_runtime.h>
+#include <linux/property.h>
 #include <linux/random.h>
 #include <linux/regmap.h>
 #include <linux/regulator/consumer.h>
 
 #include <linux/iio/buffer.h>
 #include <linux/iio/iio.h>
+#include <linux/iio/trigger.h>
 #include <linux/iio/trigger_consumer.h>
 #include <linux/iio/triggered_buffer.h>
 
@@ -1284,6 +1286,63 @@ static irqreturn_t bme280_trigger_handler(int irq, void *p)
 	return IRQ_HANDLED;
 }
 
+static int __bmp280_trigger_probe(struct iio_dev *indio_dev,
+				  const struct iio_trigger_ops *trigger_ops,
+				  int (*int_pin_config)(struct bmp280_data *data),
+				  irq_handler_t irq_thread_handler)
+{
+	struct bmp280_data *data = iio_priv(indio_dev);
+	struct device *dev = data->dev;
+	u32 irq_type;
+	int ret, irq;
+
+	irq = fwnode_irq_get(dev_fwnode(dev), 0);
+	if (irq < 0)
+		return dev_err_probe(dev, irq, "No interrupt found.\n");
+
+	irq_type = irq_get_trigger_type(irq);
+	switch (irq_type) {
+	case IRQF_TRIGGER_RISING:
+		data->trig_active_high = true;
+		break;
+	case IRQF_TRIGGER_FALLING:
+		data->trig_active_high = false;
+		break;
+	default:
+		return dev_err_probe(dev, -EINVAL, "Invalid interrupt type specified.\n");
+	}
+
+	data->trig_open_drain =
+		fwnode_property_read_bool(dev_fwnode(dev), "int-open-drain");
+
+	ret = int_pin_config(data);
+	if (ret)
+		return ret;
+
+	data->trig = devm_iio_trigger_alloc(data->dev, "%s-dev%d",
+					    indio_dev->name,
+					    iio_device_id(indio_dev));
+	if (!data->trig)
+		return -ENOMEM;
+
+	data->trig->ops = trigger_ops;
+	iio_trigger_set_drvdata(data->trig, data);
+
+	ret = devm_request_threaded_irq(data->dev, irq, NULL,
+					irq_thread_handler, IRQF_ONESHOT,
+					indio_dev->name, indio_dev);
+	if (ret)
+		return dev_err_probe(dev, ret, "request IRQ failed.\n");
+
+	ret = devm_iio_trigger_register(data->dev, data->trig);
+	if (ret)
+		return dev_err_probe(dev, ret, "iio trigger register failed.\n");
+
+	indio_dev->trig = iio_trigger_get(data->trig);
+
+	return 0;
+}
+
 static const u8 bme280_chip_ids[] = { BME280_CHIP_ID };
 static const int bme280_humid_coeffs[] = { 1000, 1024 };
 
@@ -1785,6 +1844,81 @@ static int bmp380_chip_config(struct bmp280_data *data)
 	return ret;
 }
 
+static void bmp380_trigger_reenable(struct iio_trigger *trig)
+{
+	struct bmp280_data *data = iio_trigger_get_drvdata(trig);
+	unsigned int tmp;
+	int ret;
+
+	ret = regmap_read(data->regmap, BMP380_REG_INT_STATUS, &tmp);
+	if (ret)
+		dev_err(data->dev, "Failed to reset interrupt.\n");
+}
+
+static int bmp380_data_rdy_trigger_set_state(struct iio_trigger *trig,
+					     bool state)
+{
+	struct bmp280_data *data = iio_trigger_get_drvdata(trig);
+	int ret;
+
+	guard(mutex)(&data->lock);
+
+	ret = regmap_update_bits(data->regmap, BMP380_REG_INT_CONTROL,
+				 BMP380_INT_CTRL_DRDY_EN,
+				 FIELD_PREP(BMP380_INT_CTRL_DRDY_EN, !!state));
+	if (ret)
+		dev_err(data->dev,
+			"Could not %s interrupt.\n", str_enable_disable(state));
+	return ret;
+}
+
+static const struct iio_trigger_ops bmp380_trigger_ops = {
+	.set_trigger_state = &bmp380_data_rdy_trigger_set_state,
+	.reenable = &bmp380_trigger_reenable,
+};
+
+static int bmp380_int_pin_config(struct bmp280_data *data)
+{
+	int pin_drive_cfg = FIELD_PREP(BMP380_INT_CTRL_OPEN_DRAIN,
+				       data->trig_open_drain);
+	int pin_level_cfg = FIELD_PREP(BMP380_INT_CTRL_LEVEL,
+				       data->trig_active_high);
+	int ret, int_pin_cfg = pin_drive_cfg | pin_level_cfg;
+
+	ret = regmap_update_bits(data->regmap, BMP380_REG_INT_CONTROL,
+				 BMP380_INT_CTRL_SETTINGS_MASK, int_pin_cfg);
+	if (ret)
+		dev_err(data->dev, "Could not set interrupt settings.\n");
+
+	return ret;
+}
+
+static irqreturn_t bmp380_irq_thread_handler(int irq, void *p)
+{
+	struct iio_dev *indio_dev = p;
+	struct bmp280_data *data = iio_priv(indio_dev);
+	unsigned int int_ctrl;
+	int ret;
+
+	scoped_guard(mutex, &data->lock) {
+		ret = regmap_read(data->regmap, BMP380_REG_INT_STATUS, &int_ctrl);
+		if (ret)
+			return IRQ_NONE;
+	}
+
+	if (FIELD_GET(BMP380_INT_STATUS_DRDY, int_ctrl))
+		iio_trigger_poll_nested(data->trig);
+
+	return IRQ_HANDLED;
+}
+
+static int bmp380_trigger_probe(struct iio_dev *indio_dev)
+{
+	return __bmp280_trigger_probe(indio_dev, &bmp380_trigger_ops,
+				      bmp380_int_pin_config,
+				      bmp380_irq_thread_handler);
+}
+
 static irqreturn_t bmp380_trigger_handler(int irq, void *p)
 {
 	struct iio_poll_func *pf = p;
@@ -1882,6 +2016,7 @@ const struct bmp280_chip_info bmp380_chip_info = {
 	.wait_conv = bmp380_wait_conv,
 	.preinit = bmp380_preinit,
 
+	.trigger_probe = bmp380_trigger_probe,
 	.trigger_handler = bmp380_trigger_handler,
 };
 EXPORT_SYMBOL_NS(bmp380_chip_info, IIO_BMP280);
@@ -2429,6 +2564,88 @@ static int bmp580_chip_config(struct bmp280_data *data)
 	return 0;
 }
 
+static void bmp580_trigger_reenable(struct iio_trigger *trig)
+{
+	struct bmp280_data *data = iio_trigger_get_drvdata(trig);
+	unsigned int tmp;
+	int ret;
+
+	ret = regmap_read(data->regmap, BMP580_REG_INT_STATUS, &tmp);
+	if (ret)
+		dev_err(data->dev, "Failed to reset interrupt.\n");
+}
+
+static int bmp580_data_rdy_trigger_set_state(struct iio_trigger *trig,
+					     bool state)
+{
+	struct bmp280_data *data = iio_trigger_get_drvdata(trig);
+	int ret;
+
+	guard(mutex)(&data->lock);
+
+	ret = regmap_update_bits(data->regmap, BMP580_REG_INT_CONFIG,
+				 BMP580_INT_CONFIG_INT_EN,
+				 FIELD_PREP(BMP580_INT_CONFIG_INT_EN, !!state));
+	if (ret)
+		dev_err(data->dev,
+			"Could not %s interrupt.\n", str_enable_disable(state));
+	return ret;
+}
+
+static const struct iio_trigger_ops bmp580_trigger_ops = {
+	.set_trigger_state = &bmp580_data_rdy_trigger_set_state,
+	.reenable = &bmp580_trigger_reenable,
+};
+
+static int bmp580_int_pin_config(struct bmp280_data *data)
+{
+	int pin_drive_cfg = FIELD_PREP(BMP580_INT_CONFIG_OPEN_DRAIN,
+				       data->trig_open_drain);
+	int pin_level_cfg = FIELD_PREP(BMP580_INT_CONFIG_LEVEL,
+				       data->trig_active_high);
+	int ret, int_pin_cfg = pin_drive_cfg | pin_level_cfg;
+
+	ret = regmap_update_bits(data->regmap, BMP580_REG_INT_CONFIG,
+				 BMP580_INT_CONFIG_MASK, int_pin_cfg);
+	if (ret) {
+		dev_err(data->dev, "Could not set interrupt settings.\n");
+		return ret;
+	}
+
+	ret = regmap_set_bits(data->regmap, BMP580_REG_INT_SOURCE,
+			      BMP580_INT_SOURCE_DRDY);
+	if (ret)
+		dev_err(data->dev, "Could not set interrupt source.\n");
+
+	return ret;
+}
+
+static irqreturn_t bmp580_irq_thread_handler(int irq, void *p)
+{
+	struct iio_dev *indio_dev = p;
+	struct bmp280_data *data = iio_priv(indio_dev);
+	unsigned int int_ctrl;
+	int ret;
+
+	scoped_guard(mutex, &data->lock) {
+		ret = regmap_read(data->regmap, BMP580_REG_INT_STATUS, &int_ctrl);
+		if (ret)
+			return IRQ_NONE;
+	}
+
+	if (FIELD_GET(BMP580_INT_STATUS_DRDY_MASK, int_ctrl))
+		iio_trigger_poll_nested(data->trig);
+
+	return IRQ_HANDLED;
+}
+
+static int bmp580_trigger_probe(struct iio_dev *indio_dev)
+{
+	return __bmp280_trigger_probe(indio_dev, &bmp580_trigger_ops,
+				      bmp580_int_pin_config,
+				      bmp580_irq_thread_handler);
+}
+
 static irqreturn_t bmp580_trigger_handler(int irq, void *p)
 {
 	struct iio_poll_func *pf = p;
@@ -2507,6 +2724,7 @@ const struct bmp280_chip_info bmp580_chip_info = {
 	.wait_conv = bmp580_wait_conv,
 	.preinit = bmp580_preinit,
 
+	.trigger_probe = bmp580_trigger_probe,
 	.trigger_handler = bmp580_trigger_handler,
 };
 EXPORT_SYMBOL_NS(bmp580_chip_info, IIO_BMP280);
@@ -3055,8 +3273,11 @@ int bmp280_common_probe(struct device *dev,
 	 * however as it happens, the BMP085 shares the chip ID of BMP180
 	 * so we look for an IRQ if we have that.
 	 */
-	if (irq > 0 && (chip_id  == BMP180_CHIP_ID)) {
-		ret = bmp085_fetch_eoc_irq(dev, name, irq, data);
+	if (irq > 0) {
+		if (chip_id == BMP180_CHIP_ID)
+			ret = bmp085_fetch_eoc_irq(dev, name, irq, data);
+		if (data->chip_info->trigger_probe)
+			ret = data->chip_info->trigger_probe(indio_dev);
 		if (ret)
 			return ret;
 	}
diff --git a/drivers/iio/pressure/bmp280.h b/drivers/iio/pressure/bmp280.h
index 3babf90ce73c..12f6e90b3728 100644
--- a/drivers/iio/pressure/bmp280.h
+++ b/drivers/iio/pressure/bmp280.h
@@ -55,8 +55,17 @@
 #define BMP580_CMD_NVM_WRITE_SEQ_1	0xA0
 #define BMP580_CMD_SOFT_RESET		0xB6
 
+#define BMP580_INT_STATUS_DRDY_MASK	BIT(0)
 #define BMP580_INT_STATUS_POR_MASK	BIT(4)
 
+#define BMP580_INT_SOURCE_DRDY		BIT(0)
+
+#define BMP580_INT_CONFIG_MASK		GENMASK(3, 0)
+#define BMP580_INT_CONFIG_LATCH		BIT(0)
+#define BMP580_INT_CONFIG_LEVEL		BIT(1)
+#define BMP580_INT_CONFIG_OPEN_DRAIN	BIT(2)
+#define BMP580_INT_CONFIG_INT_EN	BIT(3)
+
 #define BMP580_STATUS_CORE_RDY_MASK	BIT(0)
 #define BMP580_STATUS_NVM_RDY_MASK	BIT(1)
 #define BMP580_STATUS_NVM_ERR_MASK	BIT(2)
@@ -175,6 +184,14 @@
 #define BMP380_TEMP_MEAS_OFFSET		163
 #define BMP380_PRESS_MEAS_OFFSET	392
 
+#define BMP380_INT_STATUS_DRDY		BIT(3)
+
+#define BMP380_INT_CTRL_SETTINGS_MASK	GENMASK(2, 0)
+#define BMP380_INT_CTRL_OPEN_DRAIN	BIT(0)
+#define BMP380_INT_CTRL_LEVEL		BIT(1)
+#define BMP380_INT_CTRL_LATCH		BIT(2)
+#define BMP380_INT_CTRL_DRDY_EN		BIT(6)
+
 #define BMP380_MIN_TEMP			-4000
 #define BMP380_MAX_TEMP			8500
 #define BMP380_MIN_PRES			3000000
@@ -407,6 +424,9 @@ struct bmp280_data {
 	struct regmap *regmap;
 	struct completion done;
 	bool use_eoc;
+	bool trig_open_drain;
+	bool trig_active_high;
+	struct iio_trigger *trig;
 	const struct bmp280_chip_info *chip_info;
 	union {
 		struct bmp180_calib bmp180;
@@ -509,6 +529,7 @@ struct bmp280_chip_info {
 	int (*set_mode)(struct bmp280_data *data, enum bmp280_op_mode mode);
 	int (*wait_conv)(struct bmp280_data *data);
 
+	int (*trigger_probe)(struct iio_dev *indio_dev);
 	irqreturn_t (*trigger_handler)(int irq, void *p);
 };
 
-- 
2.25.1


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

* [PATCH v8 4/4] iio: pressure: bmp280: Move bmp085 interrupt to new configuration
  2024-10-07 19:49 [PATCH v8 0/4] pressure: bmp280: Minor cleanup and interrupt support Vasileios Amoiridis
                   ` (2 preceding siblings ...)
  2024-10-07 19:49 ` [PATCH v8 3/4] iio: pressure: bmp280: Add data ready trigger support Vasileios Amoiridis
@ 2024-10-07 19:49 ` Vasileios Amoiridis
  3 siblings, 0 replies; 12+ messages in thread
From: Vasileios Amoiridis @ 2024-10-07 19:49 UTC (permalink / raw)
  To: jic23, lars, robh, krzk+dt, conor+dt, andriy.shevchenko
  Cc: vassilisamir, ang.iglesiasg, linus.walleij, biju.das.jz,
	javier.carrasco.cruz, semen.protsenko, 579lpy, ak, linux-iio,
	devicetree, linux-kernel, christophe.jaillet

This commit intends to add the old BMP085 sensor to the new IRQ interface
of the driver for consistence. No functional changes intended.

The BMP085 sensor is equivalent with the BMP180 with the only difference of
BMP085 having an extra interrupt pin to inform about an End of Conversion.

Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Vasileios Amoiridis <vassilisamir@gmail.com>
---
 drivers/iio/pressure/bmp280-core.c | 63 +++++++++++++++++++++++-------
 drivers/iio/pressure/bmp280-i2c.c  |  4 +-
 drivers/iio/pressure/bmp280-spi.c  |  4 +-
 drivers/iio/pressure/bmp280.h      |  1 +
 4 files changed, 54 insertions(+), 18 deletions(-)

diff --git a/drivers/iio/pressure/bmp280-core.c b/drivers/iio/pressure/bmp280-core.c
index 5779e1977a7a..da7ae7e3164c 100644
--- a/drivers/iio/pressure/bmp280-core.c
+++ b/drivers/iio/pressure/bmp280-core.c
@@ -3070,13 +3070,16 @@ static irqreturn_t bmp085_eoc_irq(int irq, void *d)
 	return IRQ_HANDLED;
 }
 
-static int bmp085_fetch_eoc_irq(struct device *dev,
-				const char *name,
-				int irq,
-				struct bmp280_data *data)
+static int bmp085_trigger_probe(struct iio_dev *indio_dev)
 {
+	struct bmp280_data *data = iio_priv(indio_dev);
+	struct device *dev = data->dev;
 	unsigned long irq_trig;
-	int ret;
+	int ret, irq;
+
+	irq = fwnode_irq_get(dev_fwnode(dev), 0);
+	if (irq < 0)
+		return dev_err_probe(dev, irq, "No interrupt found.\n");
 
 	irq_trig = irq_get_trigger_type(irq);
 	if (irq_trig != IRQF_TRIGGER_RISING) {
@@ -3086,13 +3089,8 @@ static int bmp085_fetch_eoc_irq(struct device *dev,
 
 	init_completion(&data->done);
 
-	ret = devm_request_threaded_irq(dev,
-			irq,
-			bmp085_eoc_irq,
-			NULL,
-			irq_trig,
-			name,
-			data);
+	ret = devm_request_irq(dev, irq, bmp085_eoc_irq, irq_trig,
+			       indio_dev->name, data);
 	if (ret) {
 		/* Bail out without IRQ but keep the driver in place */
 		dev_err(dev, "unable to request DRDY IRQ\n");
@@ -3100,9 +3098,48 @@ static int bmp085_fetch_eoc_irq(struct device *dev,
 	}
 
 	data->use_eoc = true;
+
 	return 0;
 }
 
+/* Identical to bmp180_chip_info + bmp085_trigger_probe */
+const struct bmp280_chip_info bmp085_chip_info = {
+	.id_reg = BMP280_REG_ID,
+	.chip_id = bmp180_chip_ids,
+	.num_chip_id = ARRAY_SIZE(bmp180_chip_ids),
+	.regmap_config = &bmp180_regmap_config,
+	.start_up_time = 2000,
+	.channels = bmp280_channels,
+	.num_channels = ARRAY_SIZE(bmp280_channels),
+	.avail_scan_masks = bmp280_avail_scan_masks,
+
+	.oversampling_temp_avail = bmp180_oversampling_temp_avail,
+	.num_oversampling_temp_avail =
+		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,
+
+	.temp_coeffs = bmp180_temp_coeffs,
+	.temp_coeffs_type = IIO_VAL_FRACTIONAL,
+	.press_coeffs = bmp180_press_coeffs,
+	.press_coeffs_type = IIO_VAL_FRACTIONAL,
+
+	.chip_config = bmp180_chip_config,
+	.read_temp = bmp180_read_temp,
+	.read_press = bmp180_read_press,
+	.read_calib = bmp180_read_calib,
+	.set_mode = bmp180_set_mode,
+	.wait_conv = bmp180_wait_conv,
+
+	.trigger_probe = bmp085_trigger_probe,
+	.trigger_handler = bmp180_trigger_handler,
+};
+EXPORT_SYMBOL_NS(bmp085_chip_info, IIO_BMP280);
+
 static int bmp280_buffer_preenable(struct iio_dev *indio_dev)
 {
 	struct bmp280_data *data = iio_priv(indio_dev);
@@ -3274,8 +3311,6 @@ int bmp280_common_probe(struct device *dev,
 	 * so we look for an IRQ if we have that.
 	 */
 	if (irq > 0) {
-		if (chip_id == BMP180_CHIP_ID)
-			ret = bmp085_fetch_eoc_irq(dev, name, irq, data);
 		if (data->chip_info->trigger_probe)
 			ret = data->chip_info->trigger_probe(indio_dev);
 		if (ret)
diff --git a/drivers/iio/pressure/bmp280-i2c.c b/drivers/iio/pressure/bmp280-i2c.c
index 5c3a63b4327c..2f7b25984c7b 100644
--- a/drivers/iio/pressure/bmp280-i2c.c
+++ b/drivers/iio/pressure/bmp280-i2c.c
@@ -27,7 +27,7 @@ static int bmp280_i2c_probe(struct i2c_client *client)
 }
 
 static const struct of_device_id bmp280_of_i2c_match[] = {
-	{ .compatible = "bosch,bmp085", .data = &bmp180_chip_info },
+	{ .compatible = "bosch,bmp085", .data = &bmp085_chip_info },
 	{ .compatible = "bosch,bmp180", .data = &bmp180_chip_info },
 	{ .compatible = "bosch,bmp280", .data = &bmp280_chip_info },
 	{ .compatible = "bosch,bme280", .data = &bme280_chip_info },
@@ -38,7 +38,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[] = {
-	{"bmp085", (kernel_ulong_t)&bmp180_chip_info },
+	{"bmp085", (kernel_ulong_t)&bmp085_chip_info },
 	{"bmp180", (kernel_ulong_t)&bmp180_chip_info },
 	{"bmp280", (kernel_ulong_t)&bmp280_chip_info },
 	{"bme280", (kernel_ulong_t)&bme280_chip_info },
diff --git a/drivers/iio/pressure/bmp280-spi.c b/drivers/iio/pressure/bmp280-spi.c
index d18549d9bb64..49aa8c2cd85b 100644
--- a/drivers/iio/pressure/bmp280-spi.c
+++ b/drivers/iio/pressure/bmp280-spi.c
@@ -114,7 +114,7 @@ static int bmp280_spi_probe(struct spi_device *spi)
 }
 
 static const struct of_device_id bmp280_of_spi_match[] = {
-	{ .compatible = "bosch,bmp085", .data = &bmp180_chip_info },
+	{ .compatible = "bosch,bmp085", .data = &bmp085_chip_info },
 	{ .compatible = "bosch,bmp180", .data = &bmp180_chip_info },
 	{ .compatible = "bosch,bmp181", .data = &bmp180_chip_info },
 	{ .compatible = "bosch,bmp280", .data = &bmp280_chip_info },
@@ -126,7 +126,7 @@ static const struct of_device_id bmp280_of_spi_match[] = {
 MODULE_DEVICE_TABLE(of, bmp280_of_spi_match);
 
 static const struct spi_device_id bmp280_spi_id[] = {
-	{ "bmp085", (kernel_ulong_t)&bmp180_chip_info },
+	{ "bmp085", (kernel_ulong_t)&bmp085_chip_info },
 	{ "bmp180", (kernel_ulong_t)&bmp180_chip_info },
 	{ "bmp181", (kernel_ulong_t)&bmp180_chip_info },
 	{ "bmp280", (kernel_ulong_t)&bmp280_chip_info },
diff --git a/drivers/iio/pressure/bmp280.h b/drivers/iio/pressure/bmp280.h
index 12f6e90b3728..2df1175b6b85 100644
--- a/drivers/iio/pressure/bmp280.h
+++ b/drivers/iio/pressure/bmp280.h
@@ -534,6 +534,7 @@ struct bmp280_chip_info {
 };
 
 /* Chip infos for each variant */
+extern const struct bmp280_chip_info bmp085_chip_info;
 extern const struct bmp280_chip_info bmp180_chip_info;
 extern const struct bmp280_chip_info bmp280_chip_info;
 extern const struct bmp280_chip_info bme280_chip_info;
-- 
2.25.1


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

* Re: [PATCH v8 1/4] iio: pressure: bmp280: Use sleep and forced mode for oneshot captures
  2024-10-07 19:49 ` [PATCH v8 1/4] iio: pressure: bmp280: Use sleep and forced mode for oneshot captures Vasileios Amoiridis
@ 2024-10-11  4:32   ` kernel test robot
  2024-10-11 10:53     ` Andy Shevchenko
  2024-10-12 16:03   ` Jonathan Cameron
  1 sibling, 1 reply; 12+ messages in thread
From: kernel test robot @ 2024-10-11  4:32 UTC (permalink / raw)
  To: Vasileios Amoiridis, jic23, lars, robh, krzk+dt, conor+dt,
	andriy.shevchenko
  Cc: llvm, oe-kbuild-all, vassilisamir, ang.iglesiasg, linus.walleij,
	biju.das.jz, javier.carrasco.cruz, semen.protsenko, 579lpy, ak,
	linux-iio, devicetree, linux-kernel, christophe.jaillet

Hi Vasileios,

kernel test robot noticed the following build warnings:

[auto build test WARNING on 96be67caa0f0420d4128cb67f07bbd7a6f49e03a]

url:    https://github.com/intel-lab-lkp/linux/commits/Vasileios-Amoiridis/iio-pressure-bmp280-Use-sleep-and-forced-mode-for-oneshot-captures/20241008-035238
base:   96be67caa0f0420d4128cb67f07bbd7a6f49e03a
patch link:    https://lore.kernel.org/r/20241007194945.66192-2-vassilisamir%40gmail.com
patch subject: [PATCH v8 1/4] iio: pressure: bmp280: Use sleep and forced mode for oneshot captures
config: i386-randconfig-006-20241011 (https://download.01.org/0day-ci/archive/20241011/202410111221.YIeXHxOv-lkp@intel.com/config)
compiler: clang version 18.1.8 (https://github.com/llvm/llvm-project 3b5b5c1ec4a3095ab096dd780e84d7ab81f3d7ff)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20241011/202410111221.YIeXHxOv-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202410111221.YIeXHxOv-lkp@intel.com/

All warnings (new ones prefixed by >>):

>> drivers/iio/pressure/bmp280-core.c:1051:3: warning: variable 'meas_time_us' is uninitialized when used here [-Wuninitialized]
    1051 |                 meas_time_us += BMP280_PRESS_HUMID_MEAS_OFFSET +
         |                 ^~~~~~~~~~~~
   drivers/iio/pressure/bmp280-core.c:1046:32: note: initialize the variable 'meas_time_us' to silence this warning
    1046 |         unsigned int reg, meas_time_us;
         |                                       ^
         |                                        = 0
   drivers/iio/pressure/bmp280-core.c:2452:2: warning: variable 'offset' is uninitialized when used here [-Wuninitialized]
    2452 |         offset += sizeof(s32);
         |         ^~~~~~
   drivers/iio/pressure/bmp280-core.c:2437:17: note: initialize the variable 'offset' to silence this warning
    2437 |         int ret, offset;
         |                        ^
         |                         = 0
   2 warnings generated.


vim +/meas_time_us +1051 drivers/iio/pressure/bmp280-core.c

  1043	
  1044	static int bmp280_wait_conv(struct bmp280_data *data)
  1045	{
  1046		unsigned int reg, meas_time_us;
  1047		int ret;
  1048	
  1049		/* Check if we are using a BME280 device */
  1050		if (data->oversampling_humid)
> 1051			meas_time_us += BMP280_PRESS_HUMID_MEAS_OFFSET +
  1052					BIT(data->oversampling_humid) * BMP280_MEAS_DUR;
  1053	
  1054		/* Pressure measurement time */
  1055		meas_time_us += BMP280_PRESS_HUMID_MEAS_OFFSET +
  1056				BIT(data->oversampling_press) * BMP280_MEAS_DUR;
  1057	
  1058		/* Temperature measurement time */
  1059		meas_time_us += BIT(data->oversampling_temp) * BMP280_MEAS_DUR;
  1060	
  1061		/* Waiting time according to the BM(P/E)2 Sensor API */
  1062		fsleep(meas_time_us);
  1063	
  1064		ret = regmap_read(data->regmap, BMP280_REG_STATUS, &reg);
  1065		if (ret) {
  1066			dev_err(data->dev, "failed to read status register.\n");
  1067			return ret;
  1068		}
  1069	
  1070		if (reg & BMP280_REG_STATUS_MEAS_BIT) {
  1071			dev_err(data->dev, "Measurement cycle didn't complete.\n");
  1072			return -EBUSY;
  1073		}
  1074	
  1075		return 0;
  1076	}
  1077	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

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

* Re: [PATCH v8 1/4] iio: pressure: bmp280: Use sleep and forced mode for oneshot captures
  2024-10-11  4:32   ` kernel test robot
@ 2024-10-11 10:53     ` Andy Shevchenko
  2024-10-11 17:35       ` Vasileios Aoiridis
  0 siblings, 1 reply; 12+ messages in thread
From: Andy Shevchenko @ 2024-10-11 10:53 UTC (permalink / raw)
  To: kernel test robot
  Cc: Vasileios Amoiridis, jic23, lars, robh, krzk+dt, conor+dt, llvm,
	oe-kbuild-all, ang.iglesiasg, linus.walleij, biju.das.jz,
	javier.carrasco.cruz, semen.protsenko, 579lpy, ak, linux-iio,
	devicetree, linux-kernel, christophe.jaillet

On Fri, Oct 11, 2024 at 12:32:12PM +0800, kernel test robot wrote:
> Hi Vasileios,
> 
> kernel test robot noticed the following build warnings:
> 
> [auto build test WARNING on 96be67caa0f0420d4128cb67f07bbd7a6f49e03a]
> 
> url:    https://github.com/intel-lab-lkp/linux/commits/Vasileios-Amoiridis/iio-pressure-bmp280-Use-sleep-and-forced-mode-for-oneshot-captures/20241008-035238
> base:   96be67caa0f0420d4128cb67f07bbd7a6f49e03a
> patch link:    https://lore.kernel.org/r/20241007194945.66192-2-vassilisamir%40gmail.com
> patch subject: [PATCH v8 1/4] iio: pressure: bmp280: Use sleep and forced mode for oneshot captures
> config: i386-randconfig-006-20241011 (https://download.01.org/0day-ci/archive/20241011/202410111221.YIeXHxOv-lkp@intel.com/config)
> compiler: clang version 18.1.8 (https://github.com/llvm/llvm-project 3b5b5c1ec4a3095ab096dd780e84d7ab81f3d7ff)
> reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20241011/202410111221.YIeXHxOv-lkp@intel.com/reproduce)
> 
> If you fix the issue in a separate patch/commit (i.e. not just a new version of
> the same patch/commit), kindly add following tags
> | Reported-by: kernel test robot <lkp@intel.com>
> | Closes: https://lore.kernel.org/oe-kbuild-all/202410111221.YIeXHxOv-lkp@intel.com/
> 
> All warnings (new ones prefixed by >>):
> 
> >> drivers/iio/pressure/bmp280-core.c:1051:3: warning: variable 'meas_time_us' is uninitialized when used here [-Wuninitialized]
>     1051 |                 meas_time_us += BMP280_PRESS_HUMID_MEAS_OFFSET +
>          |                 ^~~~~~~~~~~~
>    drivers/iio/pressure/bmp280-core.c:1046:32: note: initialize the variable 'meas_time_us' to silence this warning
>     1046 |         unsigned int reg, meas_time_us;
>          |                                       ^
>          |                                        = 0
>    drivers/iio/pressure/bmp280-core.c:2452:2: warning: variable 'offset' is uninitialized when used here [-Wuninitialized]
>     2452 |         offset += sizeof(s32);
>          |         ^~~~~~
>    drivers/iio/pressure/bmp280-core.c:2437:17: note: initialize the variable 'offset' to silence this warning
>     2437 |         int ret, offset;
>          |                        ^
>          |                         = 0

Rarely, but looks like this suggestion is okay, rather I would do it as 'else'
branch and convert '+=' in the 'if' part to be '='.

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [PATCH v8 1/4] iio: pressure: bmp280: Use sleep and forced mode for oneshot captures
  2024-10-11 10:53     ` Andy Shevchenko
@ 2024-10-11 17:35       ` Vasileios Aoiridis
  0 siblings, 0 replies; 12+ messages in thread
From: Vasileios Aoiridis @ 2024-10-11 17:35 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: kernel test robot, jic23, lars, robh, krzk+dt, conor+dt, llvm,
	oe-kbuild-all, ang.iglesiasg, linus.walleij, biju.das.jz,
	javier.carrasco.cruz, semen.protsenko, 579lpy, ak, linux-iio,
	devicetree, linux-kernel, christophe.jaillet

On Fri, Oct 11, 2024 at 01:53:21PM +0300, Andy Shevchenko wrote:
> On Fri, Oct 11, 2024 at 12:32:12PM +0800, kernel test robot wrote:
> > Hi Vasileios,
> > 
> > kernel test robot noticed the following build warnings:
> > 
> > [auto build test WARNING on 96be67caa0f0420d4128cb67f07bbd7a6f49e03a]
> > 
> > url:    https://github.com/intel-lab-lkp/linux/commits/Vasileios-Amoiridis/iio-pressure-bmp280-Use-sleep-and-forced-mode-for-oneshot-captures/20241008-035238
> > base:   96be67caa0f0420d4128cb67f07bbd7a6f49e03a
> > patch link:    https://lore.kernel.org/r/20241007194945.66192-2-vassilisamir%40gmail.com
> > patch subject: [PATCH v8 1/4] iio: pressure: bmp280: Use sleep and forced mode for oneshot captures
> > config: i386-randconfig-006-20241011 (https://download.01.org/0day-ci/archive/20241011/202410111221.YIeXHxOv-lkp@intel.com/config)
> > compiler: clang version 18.1.8 (https://github.com/llvm/llvm-project 3b5b5c1ec4a3095ab096dd780e84d7ab81f3d7ff)
> > reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20241011/202410111221.YIeXHxOv-lkp@intel.com/reproduce)
> > 
> > If you fix the issue in a separate patch/commit (i.e. not just a new version of
> > the same patch/commit), kindly add following tags
> > | Reported-by: kernel test robot <lkp@intel.com>
> > | Closes: https://lore.kernel.org/oe-kbuild-all/202410111221.YIeXHxOv-lkp@intel.com/
> > 
> > All warnings (new ones prefixed by >>):
> > 
> > >> drivers/iio/pressure/bmp280-core.c:1051:3: warning: variable 'meas_time_us' is uninitialized when used here [-Wuninitialized]
> >     1051 |                 meas_time_us += BMP280_PRESS_HUMID_MEAS_OFFSET +
> >          |                 ^~~~~~~~~~~~
> >    drivers/iio/pressure/bmp280-core.c:1046:32: note: initialize the variable 'meas_time_us' to silence this warning
> >     1046 |         unsigned int reg, meas_time_us;
> >          |                                       ^
> >          |                                        = 0
> >    drivers/iio/pressure/bmp280-core.c:2452:2: warning: variable 'offset' is uninitialized when used here [-Wuninitialized]
> >     2452 |         offset += sizeof(s32);
> >          |         ^~~~~~
> >    drivers/iio/pressure/bmp280-core.c:2437:17: note: initialize the variable 'offset' to silence this warning
> >     2437 |         int ret, offset;
> >          |                        ^
> >          |                         = 0
> 
> Rarely, but looks like this suggestion is okay, rather I would do it as 'else'
> branch and convert '+=' in the 'if' part to be '='.

Hi Andy,

I though exactly the same, thanks for confirming my thoughts and thanks
for taking the time to suggest it!

Cheers,
Vasilis

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

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

* Re: [PATCH v8 1/4] iio: pressure: bmp280: Use sleep and forced mode for oneshot captures
  2024-10-07 19:49 ` [PATCH v8 1/4] iio: pressure: bmp280: Use sleep and forced mode for oneshot captures Vasileios Amoiridis
  2024-10-11  4:32   ` kernel test robot
@ 2024-10-12 16:03   ` Jonathan Cameron
  2024-10-14 19:50     ` Vasileios Amoiridis
  1 sibling, 1 reply; 12+ messages in thread
From: Jonathan Cameron @ 2024-10-12 16:03 UTC (permalink / raw)
  To: Vasileios Amoiridis
  Cc: lars, robh, krzk+dt, conor+dt, andriy.shevchenko, ang.iglesiasg,
	linus.walleij, biju.das.jz, javier.carrasco.cruz, semen.protsenko,
	579lpy, ak, linux-iio, devicetree, linux-kernel,
	christophe.jaillet

On Mon,  7 Oct 2024 21:49:42 +0200
Vasileios Amoiridis <vassilisamir@gmail.com> wrote:

> Add forced mode support in sensors BMP28x, BME28x, BMP3xx and BMP58x.
> Sensors BMP18x and BMP085 are old and do not support this feature so
> their operation is not affected at all.
> 
> Essentially, up to now, the rest of the sensors were used in normal mode
> all the time. This means that they are continuously doing measurements
> even though these measurements are not used. Even though the sensor does
> provide PM support, to cover all the possible use cases, the sensor needs
> to go into sleep mode and wake up whenever necessary.
> 
> The idea is that the sensor is by default in sleep mode, wakes up in
> forced mode when a oneshot capture is requested, or in normal mode
> when the buffer is enabled. The difference lays in the fact that in
> forced mode, the sensor does only one conversion and goes back to sleep
> while in normal mode, the sensor does continuous measurements with the
> frequency that was set in the ODR registers.
> 
> The bmpX_chip_config() functions which are responsible for applying
> the requested configuration to the sensor, are modified accordingly
> in order to set the sensor by default in sleep mode.
> 
> DEEP STANDBY, Low Power NORMAL and CONTINUOUS modes, supported only by
> the BMP58x version, are not added.
> 
> Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> Signed-off-by: Vasileios Amoiridis <vassilisamir@gmail.com>
Hi Vasilieos

Given it looks like you'll be doing a v9 anyway, a few comments inline
on some minor simplifications and potential readability improvements.

Thanks,

Jonathan


> ---
>  drivers/iio/pressure/bmp280-core.c | 296 +++++++++++++++++++++++++++--
>  drivers/iio/pressure/bmp280.h      |  21 ++
>  2 files changed, 296 insertions(+), 21 deletions(-)
> 
> diff --git a/drivers/iio/pressure/bmp280-core.c b/drivers/iio/pressure/bmp280-core.c
> index 6811619c6f11..9ad29cf4c2ac 100644
> --- a/drivers/iio/pressure/bmp280-core.c
> +++ b/drivers/iio/pressure/bmp280-core.c
> @@ -16,6 +16,11 @@


> @@ -1522,6 +1610,71 @@ static int bmp380_preinit(struct bmp280_data *data)
>  	return bmp380_cmd(data, BMP380_CMD_SOFT_RESET);
>  }
>  
> +static const u8 bmp380_operation_mode[] = {
> +	BMP380_MODE_SLEEP, BMP380_MODE_FORCED, BMP380_MODE_NORMAL,
> +};

As below - I'd assign these to specific entries to make the fairly obvious association
even more obvious!

> +
> +static int bmp380_set_mode(struct bmp280_data *data, enum bmp280_op_mode mode)
> +{
> +	int ret;
> +
> +	switch (mode) {
> +	case BMP280_SLEEP:
> +	case BMP280_FORCED:
> +	case BMP280_NORMAL:
> +		break;
> +	default:
> +		return -EINVAL;

Currently there aren't others. So the compiler should shout if you try to pass
something else. Hence this check shouldn't be needed.

> +	}
> +
> +	ret = regmap_write_bits(data->regmap, BMP380_REG_POWER_CONTROL,
> +				BMP380_MODE_MASK,
> +				FIELD_PREP(BMP380_MODE_MASK,
> +					   bmp380_operation_mode[mode]));
> +	if (ret) {
> +		dev_err(data->dev, "failed to  write power control register.\n");
> +		return ret;
> +	}
> +
> +	data->op_mode = mode;
> +
> +	return 0;
> +}
>

>  	return PTR_ERR_OR_ZERO(devm_nvmem_register(config.dev, &config));
>  }
>  
> +static const u8 bmp580_operation_mode[] = {
> +	BMP580_MODE_SLEEP, BMP580_MODE_FORCED, BMP580_MODE_NORMAL,

For these, explicit setting will make it more obvious.
	[BMP280_SLEEP] = BMP580_MODE_SLEEP,
etc

> +};
> +
> +static int bmp580_set_mode(struct bmp280_data *data, enum bmp280_op_mode mode)
> +{
> +	struct device *dev = data->dev;
> +	int ret;
> +
> +	switch (mode) {
> +	case BMP280_SLEEP:
> +	case BMP280_NORMAL:
> +		break;
> +	case BMP280_FORCED:
> +		ret = regmap_set_bits(data->regmap, BMP580_REG_DSP_CONFIG,
> +				      BMP580_DSP_IIR_FORCED_FLUSH);
> +		if (ret) {
> +			dev_err(dev, "Could not flush IIR filter constants.\n");
> +			return ret;
> +		}
> +		break;
> +	default:
There are only the values above, and we should hopefully be able to rely
on compiler warnings to shout at us if a future modification adds more.

So should be able to drop the default here.

> +		return -EINVAL;
> +	}
> +
> +	ret = regmap_write_bits(data->regmap, BMP580_REG_ODR_CONFIG,
> +				BMP580_MODE_MASK,
> +				FIELD_PREP(BMP580_MODE_MASK,
> +					   bmp580_operation_mode[mode]));
> +	if (ret) {
> +		dev_err(dev, "failed to  write power control register.\n");
> +		return ret;
> +	}
> +
> +	data->op_mode = mode;
> +
> +	return 0;
> +}


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

* Re: [PATCH v8 3/4] iio: pressure: bmp280: Add data ready trigger support
  2024-10-07 19:49 ` [PATCH v8 3/4] iio: pressure: bmp280: Add data ready trigger support Vasileios Amoiridis
@ 2024-10-12 16:08   ` Jonathan Cameron
  2024-10-14 20:10     ` Vasileios Amoiridis
  0 siblings, 1 reply; 12+ messages in thread
From: Jonathan Cameron @ 2024-10-12 16:08 UTC (permalink / raw)
  To: Vasileios Amoiridis
  Cc: lars, robh, krzk+dt, conor+dt, andriy.shevchenko, ang.iglesiasg,
	linus.walleij, biju.das.jz, javier.carrasco.cruz, semen.protsenko,
	579lpy, ak, linux-iio, devicetree, linux-kernel,
	christophe.jaillet

On Mon,  7 Oct 2024 21:49:44 +0200
Vasileios Amoiridis <vassilisamir@gmail.com> wrote:

> The BMP3xx and BMP5xx sensors have an interrupt pin which can be used as
> a trigger for when there are data ready in the sensor for pick up.
> 
> This use case is used along with NORMAL_MODE in the sensor, which allows
> the sensor to do consecutive measurements depending on the ODR rate value.
> 
> The trigger pin can be configured to be open-drain or push-pull and either
> rising or falling edge.
> 
> No support is added yet for interrupts for FIFO, WATERMARK and out of range
> values.
> 
> Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> Signed-off-by: Vasileios Amoiridis <vassilisamir@gmail.com>

Hi Vasileios,

One questing about locking below.  What you have is probably correct
but might be tighter than it needs to be, or need a comment to say why
for future readers.

I hate register reads with side effects btw.  It's an 'optimization'
hardware designers thing is nice, but makes for really ugly software
interfaces.

> @@ -2429,6 +2564,88 @@ static int bmp580_chip_config(struct bmp280_data *data)
>  	return 0;
>  }
>  
> +static void bmp580_trigger_reenable(struct iio_trigger *trig)
> +{
> +	struct bmp280_data *data = iio_trigger_get_drvdata(trig);
> +	unsigned int tmp;
> +	int ret;
> +
> +	ret = regmap_read(data->regmap, BMP580_REG_INT_STATUS, &tmp);
As below. Seems this read has side effects (horrible!)
I'm not sure if this is related to the locking though.
> +	if (ret)
> +		dev_err(data->dev, "Failed to reset interrupt.\n");
> +}

> +static int bmp580_int_pin_config(struct bmp280_data *data)
> +{
> +	int pin_drive_cfg = FIELD_PREP(BMP580_INT_CONFIG_OPEN_DRAIN,
> +				       data->trig_open_drain);
> +	int pin_level_cfg = FIELD_PREP(BMP580_INT_CONFIG_LEVEL,
> +				       data->trig_active_high);
> +	int ret, int_pin_cfg = pin_drive_cfg | pin_level_cfg;
	int int_pin_cfg = pin...
	int ret;

Is easier to follow.

> +
> +	ret = regmap_update_bits(data->regmap, BMP580_REG_INT_CONFIG,
> +				 BMP580_INT_CONFIG_MASK, int_pin_cfg);
> +	if (ret) {
> +		dev_err(data->dev, "Could not set interrupt settings.\n");
> +		return ret;
> +	}
> +
> +	ret = regmap_set_bits(data->regmap, BMP580_REG_INT_SOURCE,
> +			      BMP580_INT_SOURCE_DRDY);
> +	if (ret)
> +		dev_err(data->dev, "Could not set interrupt source.\n");
> +
> +	return ret;
> +}
> +
> +static irqreturn_t bmp580_irq_thread_handler(int irq, void *p)
> +{
> +	struct iio_dev *indio_dev = p;
> +	struct bmp280_data *data = iio_priv(indio_dev);
> +	unsigned int int_ctrl;
> +	int ret;
> +
> +	scoped_guard(mutex, &data->lock) {
> +		ret = regmap_read(data->regmap, BMP580_REG_INT_STATUS, &int_ctrl);
What are you locking against here?  Seems this read may have side effects?
If not the regmap internal locking should be enough for a register read.
> +		if (ret)
> +			return IRQ_NONE;
> +	}



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

* Re: [PATCH v8 1/4] iio: pressure: bmp280: Use sleep and forced mode for oneshot captures
  2024-10-12 16:03   ` Jonathan Cameron
@ 2024-10-14 19:50     ` Vasileios Amoiridis
  0 siblings, 0 replies; 12+ messages in thread
From: Vasileios Amoiridis @ 2024-10-14 19:50 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: lars, robh, krzk+dt, conor+dt, andriy.shevchenko, ang.iglesiasg,
	linus.walleij, biju.das.jz, javier.carrasco.cruz, semen.protsenko,
	579lpy, ak, linux-iio, devicetree, linux-kernel,
	christophe.jaillet

On Sat, Oct 12, 2024 at 05:03:33PM +0100, Jonathan Cameron wrote:
> On Mon,  7 Oct 2024 21:49:42 +0200
> Vasileios Amoiridis <vassilisamir@gmail.com> wrote:
> 
> > Add forced mode support in sensors BMP28x, BME28x, BMP3xx and BMP58x.
> > Sensors BMP18x and BMP085 are old and do not support this feature so
> > their operation is not affected at all.
> > 
> > Essentially, up to now, the rest of the sensors were used in normal mode
> > all the time. This means that they are continuously doing measurements
> > even though these measurements are not used. Even though the sensor does
> > provide PM support, to cover all the possible use cases, the sensor needs
> > to go into sleep mode and wake up whenever necessary.
> > 
> > The idea is that the sensor is by default in sleep mode, wakes up in
> > forced mode when a oneshot capture is requested, or in normal mode
> > when the buffer is enabled. The difference lays in the fact that in
> > forced mode, the sensor does only one conversion and goes back to sleep
> > while in normal mode, the sensor does continuous measurements with the
> > frequency that was set in the ODR registers.
> > 
> > The bmpX_chip_config() functions which are responsible for applying
> > the requested configuration to the sensor, are modified accordingly
> > in order to set the sensor by default in sleep mode.
> > 
> > DEEP STANDBY, Low Power NORMAL and CONTINUOUS modes, supported only by
> > the BMP58x version, are not added.
> > 
> > Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> > Signed-off-by: Vasileios Amoiridis <vassilisamir@gmail.com>
> Hi Vasilieos
> 
> Given it looks like you'll be doing a v9 anyway, a few comments inline
> on some minor simplifications and potential readability improvements.
> 
> Thanks,
> 
> Jonathan
> 

Hi Jonathan,

> 
> > ---
> >  drivers/iio/pressure/bmp280-core.c | 296 +++++++++++++++++++++++++++--
> >  drivers/iio/pressure/bmp280.h      |  21 ++
> >  2 files changed, 296 insertions(+), 21 deletions(-)
> > 
> > diff --git a/drivers/iio/pressure/bmp280-core.c b/drivers/iio/pressure/bmp280-core.c
> > index 6811619c6f11..9ad29cf4c2ac 100644
> > --- a/drivers/iio/pressure/bmp280-core.c
> > +++ b/drivers/iio/pressure/bmp280-core.c
> > @@ -16,6 +16,11 @@
> 
> 
> > @@ -1522,6 +1610,71 @@ static int bmp380_preinit(struct bmp280_data *data)
> >  	return bmp380_cmd(data, BMP380_CMD_SOFT_RESET);
> >  }
> >  
> > +static const u8 bmp380_operation_mode[] = {
> > +	BMP380_MODE_SLEEP, BMP380_MODE_FORCED, BMP380_MODE_NORMAL,
> > +};
> 
> As below - I'd assign these to specific entries to make the fairly obvious association
> even more obvious!
> 

ACK! Makes total sense. Thanks for your time!

Cheers,
Vasilis

> > +
> > +static int bmp380_set_mode(struct bmp280_data *data, enum bmp280_op_mode mode)
> > +{
> > +	int ret;
> > +
> > +	switch (mode) {
> > +	case BMP280_SLEEP:
> > +	case BMP280_FORCED:
> > +	case BMP280_NORMAL:
> > +		break;
> > +	default:
> > +		return -EINVAL;
> 
> Currently there aren't others. So the compiler should shout if you try to pass
> something else. Hence this check shouldn't be needed.
> 
> > +	}
> > +
> > +	ret = regmap_write_bits(data->regmap, BMP380_REG_POWER_CONTROL,
> > +				BMP380_MODE_MASK,
> > +				FIELD_PREP(BMP380_MODE_MASK,
> > +					   bmp380_operation_mode[mode]));
> > +	if (ret) {
> > +		dev_err(data->dev, "failed to  write power control register.\n");
> > +		return ret;
> > +	}
> > +
> > +	data->op_mode = mode;
> > +
> > +	return 0;
> > +}
> >
> 
> >  	return PTR_ERR_OR_ZERO(devm_nvmem_register(config.dev, &config));
> >  }
> >  
> > +static const u8 bmp580_operation_mode[] = {
> > +	BMP580_MODE_SLEEP, BMP580_MODE_FORCED, BMP580_MODE_NORMAL,
> 
> For these, explicit setting will make it more obvious.
> 	[BMP280_SLEEP] = BMP580_MODE_SLEEP,
> etc
> 
> > +};
> > +
> > +static int bmp580_set_mode(struct bmp280_data *data, enum bmp280_op_mode mode)
> > +{
> > +	struct device *dev = data->dev;
> > +	int ret;
> > +
> > +	switch (mode) {
> > +	case BMP280_SLEEP:
> > +	case BMP280_NORMAL:
> > +		break;
> > +	case BMP280_FORCED:
> > +		ret = regmap_set_bits(data->regmap, BMP580_REG_DSP_CONFIG,
> > +				      BMP580_DSP_IIR_FORCED_FLUSH);
> > +		if (ret) {
> > +			dev_err(dev, "Could not flush IIR filter constants.\n");
> > +			return ret;
> > +		}
> > +		break;
> > +	default:
> There are only the values above, and we should hopefully be able to rely
> on compiler warnings to shout at us if a future modification adds more.
> 
> So should be able to drop the default here.
> 
> > +		return -EINVAL;
> > +	}
> > +
> > +	ret = regmap_write_bits(data->regmap, BMP580_REG_ODR_CONFIG,
> > +				BMP580_MODE_MASK,
> > +				FIELD_PREP(BMP580_MODE_MASK,
> > +					   bmp580_operation_mode[mode]));
> > +	if (ret) {
> > +		dev_err(dev, "failed to  write power control register.\n");
> > +		return ret;
> > +	}
> > +
> > +	data->op_mode = mode;
> > +
> > +	return 0;
> > +}
> 

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

* Re: [PATCH v8 3/4] iio: pressure: bmp280: Add data ready trigger support
  2024-10-12 16:08   ` Jonathan Cameron
@ 2024-10-14 20:10     ` Vasileios Amoiridis
  0 siblings, 0 replies; 12+ messages in thread
From: Vasileios Amoiridis @ 2024-10-14 20:10 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: lars, robh, krzk+dt, conor+dt, andriy.shevchenko, ang.iglesiasg,
	linus.walleij, biju.das.jz, javier.carrasco.cruz, semen.protsenko,
	579lpy, ak, linux-iio, devicetree, linux-kernel,
	christophe.jaillet

On Sat, Oct 12, 2024 at 05:08:23PM +0100, Jonathan Cameron wrote:
> On Mon,  7 Oct 2024 21:49:44 +0200
> Vasileios Amoiridis <vassilisamir@gmail.com> wrote:
> 
> > The BMP3xx and BMP5xx sensors have an interrupt pin which can be used as
> > a trigger for when there are data ready in the sensor for pick up.
> > 
> > This use case is used along with NORMAL_MODE in the sensor, which allows
> > the sensor to do consecutive measurements depending on the ODR rate value.
> > 
> > The trigger pin can be configured to be open-drain or push-pull and either
> > rising or falling edge.
> > 
> > No support is added yet for interrupts for FIFO, WATERMARK and out of range
> > values.
> > 
> > Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> > Signed-off-by: Vasileios Amoiridis <vassilisamir@gmail.com>
> 
> Hi Vasileios,
> 
> One questing about locking below.  What you have is probably correct
> but might be tighter than it needs to be, or need a comment to say why
> for future readers.
> 
> I hate register reads with side effects btw.  It's an 'optimization'
> hardware designers thing is nice, but makes for really ugly software
> interfaces.
> 

Hi Jonathan,

> > @@ -2429,6 +2564,88 @@ static int bmp580_chip_config(struct bmp280_data *data)
> >  	return 0;
> >  }
> >  
> > +static void bmp580_trigger_reenable(struct iio_trigger *trig)
> > +{
> > +	struct bmp280_data *data = iio_trigger_get_drvdata(trig);
> > +	unsigned int tmp;
> > +	int ret;
> > +
> > +	ret = regmap_read(data->regmap, BMP580_REG_INT_STATUS, &tmp);
> As below. Seems this read has side effects (horrible!)
> I'm not sure if this is related to the locking though.

Yes indeed, this read is needed in order to clear the interrupt. In that
way the interrupt is kind of resetted so it can get triggered again. It
is actually the 1st line in page 28 of [1].

[1]: https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bmp585-ds003.pdf
> > +	if (ret)
> > +		dev_err(data->dev, "Failed to reset interrupt.\n");
> > +}
> 
> > +static int bmp580_int_pin_config(struct bmp280_data *data)
> > +{
> > +	int pin_drive_cfg = FIELD_PREP(BMP580_INT_CONFIG_OPEN_DRAIN,
> > +				       data->trig_open_drain);
> > +	int pin_level_cfg = FIELD_PREP(BMP580_INT_CONFIG_LEVEL,
> > +				       data->trig_active_high);
> > +	int ret, int_pin_cfg = pin_drive_cfg | pin_level_cfg;
> 	int int_pin_cfg = pin...
> 	int ret;
> 
> Is easier to follow.
> 

ACK.

> > +
> > +	ret = regmap_update_bits(data->regmap, BMP580_REG_INT_CONFIG,
> > +				 BMP580_INT_CONFIG_MASK, int_pin_cfg);
> > +	if (ret) {
> > +		dev_err(data->dev, "Could not set interrupt settings.\n");
> > +		return ret;
> > +	}
> > +
> > +	ret = regmap_set_bits(data->regmap, BMP580_REG_INT_SOURCE,
> > +			      BMP580_INT_SOURCE_DRDY);
> > +	if (ret)
> > +		dev_err(data->dev, "Could not set interrupt source.\n");
> > +
> > +	return ret;
> > +}
> > +
> > +static irqreturn_t bmp580_irq_thread_handler(int irq, void *p)
> > +{
> > +	struct iio_dev *indio_dev = p;
> > +	struct bmp280_data *data = iio_priv(indio_dev);
> > +	unsigned int int_ctrl;
> > +	int ret;
> > +
> > +	scoped_guard(mutex, &data->lock) {
> > +		ret = regmap_read(data->regmap, BMP580_REG_INT_STATUS, &int_ctrl);
> What are you locking against here?  Seems this read may have side effects?
> If not the regmap internal locking should be enough for a register read.

I had a 2nd look and the lock is redundant indeed. This came from the
fact that I use the lock in the oneshot captures becasue when we do
reads of pressure or humidity (BME280) measurements, the temp regs are
read first, they are processed and later the pressure/humidity regs are
read so this operation should be kept serialized. But here there is no
problem.

Cheers,
Vasilis

> > +		if (ret)
> > +			return IRQ_NONE;
> > +	}
> 
> 

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

end of thread, other threads:[~2024-10-14 20:10 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-10-07 19:49 [PATCH v8 0/4] pressure: bmp280: Minor cleanup and interrupt support Vasileios Amoiridis
2024-10-07 19:49 ` [PATCH v8 1/4] iio: pressure: bmp280: Use sleep and forced mode for oneshot captures Vasileios Amoiridis
2024-10-11  4:32   ` kernel test robot
2024-10-11 10:53     ` Andy Shevchenko
2024-10-11 17:35       ` Vasileios Aoiridis
2024-10-12 16:03   ` Jonathan Cameron
2024-10-14 19:50     ` Vasileios Amoiridis
2024-10-07 19:49 ` [PATCH v8 2/4] dt-bindings: iio: pressure: bmp085: Add interrupts for BMP3xx and BMP5xx devices Vasileios Amoiridis
2024-10-07 19:49 ` [PATCH v8 3/4] iio: pressure: bmp280: Add data ready trigger support Vasileios Amoiridis
2024-10-12 16:08   ` Jonathan Cameron
2024-10-14 20:10     ` Vasileios Amoiridis
2024-10-07 19:49 ` [PATCH v8 4/4] iio: pressure: bmp280: Move bmp085 interrupt to new configuration Vasileios Amoiridis

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).