mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v2 0/2] iio: pressure: dps310: data-ready trigger
@ 2026-11-14  8:38 Rupesh Majhi
  2026-11-14  8:38 ` [PATCH v2 1/2] dt-bindings: iio: pressure: infineon,dps310: Add interrupts Rupesh Majhi
  2026-11-14  8:38 ` [PATCH v2 2/2] iio: pressure: dps310: add a data-ready trigger Rupesh Majhi
  0 siblings, 2 replies; 3+ messages in thread
From: Rupesh Majhi @ 2026-11-14  8:38 UTC (permalink / raw)
  To: Andy Shevchenko, Conor Dooley, David Lechner, Eddie James,
	Jonathan Cameron, Krzysztof Kozlowski, Nuno Sá,
	Rob Herring
  Cc: devicetree, linux-iio, linux-kernel, Rupesh Majhi, Paulius Zaleckas

DPS310 can raise an interrupt on SDO for each new result. Document it
and use it for a data-ready trigger, so triggered captures follow the
measurements and are stamped with the interrupt time.

With pressure sampled faster than temperature, scans with pressure
need the trigger handler fix [1] to keep up. Without it they come at
the temperature rate, as with any other trigger.

Tested on a DPS310 breakout (0x77) on a BeagleBone Black with SDO to a
GPIO, level-low and falling-edge, with [1] applied: one scan per result
at 1 and 8 Hz, also with the rates at 8/1 and 1/8 Hz, stamps steady to
0.2 ms. With pressure at 1 Hz and temperature at 8 Hz, one temperature
result a second comes 2.4 ms late and the stamps show it. Without an
interrupt nothing changes. Not tested: active high, which needs SDO
strapped low (0x76), and ZTS8032.

If the chip stalls, the case the timeout reset is for, the trigger stops
firing until the buffer is disabled and a read resets the chip.

v2:
- interrupt on temperature results when pressure is not in the scan,
  so a temperature only scan no longer waits in the handler
- limit the trigger to this device, as the interrupt depends on its scan
- local regmap pointer in set_state and probe (Andy)
- rebase on iio/testing

v1: https://lore.kernel.org/linux-iio/20261110154254.39092-1-zoone.rupert@gmail.com/
[1] https://lore.kernel.org/linux-iio/20261113230241.82046-1-zoone.rupert@gmail.com/

Cc: Paulius Zaleckas <paulius.zaleckas@gmail.com>

Rupesh Majhi (2):
  dt-bindings: iio: pressure: infineon,dps310: Add interrupts
  iio: pressure: dps310: add a data-ready trigger

 .../iio/pressure/infineon,dps310.yaml         |  10 ++
 drivers/iio/pressure/dps310.c                 | 139 +++++++++++++++++-
 2 files changed, 145 insertions(+), 4 deletions(-)


base-commit: 7c054db85b5a3ce4d5465cc5cc682cc44ae9eabd
-- 
2.43.0


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

* [PATCH v2 1/2] dt-bindings: iio: pressure: infineon,dps310: Add interrupts
  2026-11-14  8:38 [PATCH v2 0/2] iio: pressure: dps310: data-ready trigger Rupesh Majhi
@ 2026-11-14  8:38 ` Rupesh Majhi
  2026-11-14  8:38 ` [PATCH v2 2/2] iio: pressure: dps310: add a data-ready trigger Rupesh Majhi
  1 sibling, 0 replies; 3+ messages in thread
From: Rupesh Majhi @ 2026-11-14  8:38 UTC (permalink / raw)
  To: Andy Shevchenko, Conor Dooley, David Lechner, Eddie James,
	Jonathan Cameron, Krzysztof Kozlowski, Nuno Sá,
	Rob Herring
  Cc: devicetree, linux-iio, linux-kernel, Rupesh Majhi, Paulius Zaleckas

DPS310 signals new results and a full FIFO on its SDO pin. In I2C mode
the same pin sets the address LSB, and interrupt polarity must be the
opposite of how SDO is strapped.

Signed-off-by: Rupesh Majhi <zoone.rupert@gmail.com>
---
v2: no change

Cc: Paulius Zaleckas <paulius.zaleckas@gmail.com>

 .../bindings/iio/pressure/infineon,dps310.yaml         | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/Documentation/devicetree/bindings/iio/pressure/infineon,dps310.yaml b/Documentation/devicetree/bindings/iio/pressure/infineon,dps310.yaml
index 416117dfd927..cded6e0af147 100644
--- a/Documentation/devicetree/bindings/iio/pressure/infineon,dps310.yaml
+++ b/Documentation/devicetree/bindings/iio/pressure/infineon,dps310.yaml
@@ -23,6 +23,12 @@ properties:
   reg:
     maxItems: 1
 
+  interrupts:
+    maxItems: 1
+    description:
+      New result or full FIFO, on SDO pin. SDO also selects I2C address, so
+      interrupt is active high at 0x76 (SDO low) and active low at 0x77.
+
   "#io-channel-cells":
     const: 0
 
@@ -42,6 +48,8 @@ additionalProperties: false
 
 examples:
   - |
+    #include <dt-bindings/interrupt-controller/irq.h>
+
     i2c {
         #address-cells = <1>;
         #size-cells = <0>;
@@ -49,6 +57,8 @@ examples:
         dps: pressure-sensor@76 {
             compatible = "infineon,dps310";
             reg = <0x76>;
+            interrupt-parent = <&gpio0>;
+            interrupts = <17 IRQ_TYPE_LEVEL_HIGH>;
             #io-channel-cells = <0>;
             vdd-supply = <&vref1>;
             vddio-supply = <&vref2>;
-- 
2.43.0


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

* [PATCH v2 2/2] iio: pressure: dps310: add a data-ready trigger
  2026-11-14  8:38 [PATCH v2 0/2] iio: pressure: dps310: data-ready trigger Rupesh Majhi
  2026-11-14  8:38 ` [PATCH v2 1/2] dt-bindings: iio: pressure: infineon,dps310: Add interrupts Rupesh Majhi
@ 2026-11-14  8:38 ` Rupesh Majhi
  1 sibling, 0 replies; 3+ messages in thread
From: Rupesh Majhi @ 2026-11-14  8:38 UTC (permalink / raw)
  To: Andy Shevchenko, Conor Dooley, David Lechner, Eddie James,
	Jonathan Cameron, Krzysztof Kozlowski, Nuno Sá,
	Rob Herring
  Cc: devicetree, linux-iio, linux-kernel, Rupesh Majhi, Paulius Zaleckas

With an interrupt wired to SDO, the chip can signal each new result.
Expose it as a trigger, so captures follow the measurements and scans
carry the time the result was ready, not when the handler ran.

The trigger fires on new pressure results, or on new temperature
results when pressure is not in the scan. As that depends on the scan,
only this device can use it. Polarity follows the interrupt type.
Status latches while the interrupt is disabled, so it is cleared before
enabling. The trigger is not the default, so FIFO mode without a
trigger is unchanged.

Signed-off-by: Rupesh Majhi <zoone.rupert@gmail.com>
---
v2:
- interrupt on temperature results when pressure is not in the scan
- limit the trigger to this device
- local regmap pointer in set_state and probe (Andy)

Cc: Paulius Zaleckas <paulius.zaleckas@gmail.com>

 drivers/iio/pressure/dps310.c | 139 +++++++++++++++++++++++++++++++++-
 1 file changed, 135 insertions(+), 4 deletions(-)

diff --git a/drivers/iio/pressure/dps310.c b/drivers/iio/pressure/dps310.c
index 5cee23986f30..4bff9e93ea92 100644
--- a/drivers/iio/pressure/dps310.c
+++ b/drivers/iio/pressure/dps310.c
@@ -17,6 +17,8 @@
 #include <linux/cleanup.h>
 #include <linux/devm-helpers.h>
 #include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
 #include <linux/limits.h>
 #include <linux/math64.h>
 #include <linux/module.h>
@@ -31,6 +33,7 @@
 #include <linux/iio/buffer.h>
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
+#include <linux/iio/trigger.h>
 #include <linux/iio/trigger_consumer.h>
 #include <linux/iio/triggered_buffer.h>
 
@@ -62,10 +65,15 @@
 #define  DPS310_COEF_RDY	BIT(7)
 #define DPS310_CFG_REG		0x09
 #define  DPS310_INT_HL		BIT(7)
+#define  DPS310_INT_TMP		BIT(5)
+#define  DPS310_INT_PRS		BIT(4)
 #define  DPS310_TMP_SHIFT_EN	BIT(3)
 #define  DPS310_PRS_SHIFT_EN	BIT(2)
 #define  DPS310_FIFO_EN		BIT(1)
 #define  DPS310_SPI_EN		BIT(0)
+#define DPS310_INT_STS		0x0a
+#define  DPS310_INT_STS_TMP	BIT(1)
+#define  DPS310_INT_STS_PRS	BIT(0)
 #define DPS310_RESET		0x0c
 #define  DPS310_FIFO_FLUSH	BIT(7)
 #define  DPS310_RESET_MAGIC	0x09
@@ -144,6 +152,9 @@ struct dps310_data {
 	bool timeout_recovery_failed;
 	bool fifo_temp_valid;
 
+	struct iio_trigger *trig;
+	s64 irq_timestamp;
+
 	/* Used only while the FIFO is enabled */
 	struct iio_dev *iio;
 	struct delayed_work fifo_work;
@@ -706,6 +717,7 @@ static bool dps310_is_volatile_reg(struct device *dev, unsigned int reg)
 	case DPS310_TMP_B1:
 	case DPS310_TMP_B2:
 	case DPS310_MEAS_CFG:
+	case DPS310_INT_STS:
 	case 0x32:	/* No documentation available on this register */
 		return true;
 	default:
@@ -713,6 +725,12 @@ static bool dps310_is_volatile_reg(struct device *dev, unsigned int reg)
 	}
 }
 
+/* Cleared on read */
+static bool dps310_is_precious_reg(struct device *dev, unsigned int reg)
+{
+	return reg == DPS310_INT_STS;
+}
+
 static int dps310_write_raw(struct iio_dev *iio,
 			    struct iio_chan_spec const *chan, int val,
 			    int val2, long mask)
@@ -1048,7 +1066,7 @@ static int dps310_fifo_set_enable(struct dps310_data *data, bool enable)
 				  enable);
 }
 
-/* No interrupt pin is wired in tree, so drain on a timer */
+/* The FIFO only interrupts when full and then stops, so drain on a timer */
 static unsigned int dps310_fifo_interval(struct dps310_data *data,
 					 int prs_rate, int tmp_rate)
 {
@@ -1375,6 +1393,7 @@ static irqreturn_t dps310_trigger_handler(int irq, void *p)
 		s32 channels[2];
 		aligned_s64 timestamp;
 	} scan = { };
+	s64 timestamp;
 	int rc;
 
 	mutex_lock(&data->lock);
@@ -1383,7 +1402,12 @@ static irqreturn_t dps310_trigger_handler(int irq, void *p)
 	if (rc)
 		goto err;
 
-	iio_push_to_buffers_with_ts(iio, &scan, sizeof(scan), iio_get_time_ns(iio));
+	if (iio_trigger_using_own(iio))
+		timestamp = data->irq_timestamp;
+	else
+		timestamp = iio_get_time_ns(iio);
+
+	iio_push_to_buffers_with_ts(iio, &scan, sizeof(scan), timestamp);
 
 err:
 	iio_trigger_notify_done(iio->trig);
@@ -1391,6 +1415,105 @@ static irqreturn_t dps310_trigger_handler(int irq, void *p)
 	return IRQ_HANDLED;
 }
 
+static irqreturn_t dps310_irq_handler(int irq, void *private)
+{
+	struct dps310_data *data = private;
+
+	data->irq_timestamp = iio_get_time_ns(data->iio);
+
+	return IRQ_WAKE_THREAD;
+}
+
+static irqreturn_t dps310_irq_thread(int irq, void *private)
+{
+	struct dps310_data *data = private;
+	unsigned int status;
+
+	if (regmap_read(data->regmap, DPS310_INT_STS, &status))
+		return IRQ_NONE;
+
+	if (!(status & (DPS310_INT_STS_TMP | DPS310_INT_STS_PRS)))
+		return IRQ_NONE;
+
+	iio_trigger_poll_nested(data->trig);
+
+	return IRQ_HANDLED;
+}
+
+static int dps310_trigger_set_state(struct iio_trigger *trig, bool state)
+{
+	struct dps310_data *data = iio_trigger_get_drvdata(trig);
+	struct regmap *map = data->regmap;
+	unsigned int status, bits = 0;
+	int rc;
+
+	guard(mutex)(&data->lock);
+
+	if (state) {
+		/* Status latched while disabled would fire a stale interrupt */
+		rc = regmap_read(map, DPS310_INT_STS, &status);
+		if (rc)
+			return rc;
+
+		/* Without pressure, scans follow the temperature results */
+		if (test_bit(DPS310_SCAN_PRESSURE, data->iio->active_scan_mask))
+			bits = DPS310_INT_PRS;
+		else
+			bits = DPS310_INT_TMP;
+	}
+
+	return regmap_update_bits(map, DPS310_CFG_REG,
+				  DPS310_INT_TMP | DPS310_INT_PRS, bits);
+}
+
+static const struct iio_trigger_ops dps310_trigger_ops = {
+	.set_trigger_state = dps310_trigger_set_state,
+	.validate_device = iio_trigger_validate_own_device,
+};
+
+static int dps310_trigger_probe(struct dps310_data *data)
+{
+	struct device *dev = &data->client->dev;
+	struct regmap *map = data->regmap;
+	struct iio_dev *iio = data->iio;
+	int irq = data->client->irq;
+	bool active_high;
+	int rc;
+
+	switch (irq_get_trigger_type(irq)) {
+	case IRQ_TYPE_LEVEL_HIGH:
+	case IRQ_TYPE_EDGE_RISING:
+		active_high = true;
+		break;
+	case IRQ_TYPE_LEVEL_LOW:
+	case IRQ_TYPE_EDGE_FALLING:
+		active_high = false;
+		break;
+	default:
+		return dev_err_probe(dev, -EINVAL, "Unsupported interrupt type\n");
+	}
+
+	rc = regmap_assign_bits(map, DPS310_CFG_REG, DPS310_INT_HL, active_high);
+	if (rc)
+		return rc;
+
+	data->trig = devm_iio_trigger_alloc(dev, "%s-dev%d", iio->name,
+					    iio_device_id(iio));
+	if (!data->trig)
+		return -ENOMEM;
+
+	data->trig->ops = &dps310_trigger_ops;
+	iio_trigger_set_drvdata(data->trig, data);
+
+	rc = devm_request_threaded_irq(dev, irq, dps310_irq_handler,
+				       dps310_irq_thread, IRQF_ONESHOT,
+				       iio->name, data);
+	if (rc)
+		return rc;
+
+	return devm_iio_trigger_register(dev, data->trig);
+}
+
 static void dps310_standby(void *action_data)
 {
 	struct dps310_data *data = action_data;
@@ -1404,6 +1527,7 @@ static const struct regmap_config dps310_regmap_config = {
 	.val_bits = 8,
 	.writeable_reg = dps310_is_writeable_reg,
 	.volatile_reg = dps310_is_volatile_reg,
+	.precious_reg = dps310_is_precious_reg,
 	.cache_type = REGCACHE_RBTREE,
 	.max_register = 0x62, /* No documentation available on this register */
 };
@@ -1470,8 +1594,9 @@ static int dps310_probe(struct i2c_client *client)
 	/*
 	 * The device measures continuously in background mode, so a triggered
 	 * capture is just a read of the latest results. The setup ops run the
-	 * FIFO drain when no trigger is attached. The trigger is not aligned
-	 * with the measurements, so the timestamp is taken in the handler.
+	 * FIFO drain when no trigger is attached. Only the data-ready trigger
+	 * is aligned with the measurements, so for others the timestamp is
+	 * taken in the handler.
 	 */
 	rc = devm_iio_triggered_buffer_setup(dev, iio, NULL,
 					     dps310_trigger_handler,
@@ -1484,6 +1609,12 @@ static int dps310_probe(struct i2c_client *client)
 	if (rc)
 		return rc;
 
+	if (client->irq > 0) {
+		rc = dps310_trigger_probe(data);
+		if (rc)
+			return rc;
+	}
+
 	rc = devm_iio_device_register(dev, iio);
 	if (rc)
 		return rc;
-- 
2.43.0


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

end of thread, other threads:[~2026-11-14  8:38 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-14  8:38 [PATCH v2 0/2] iio: pressure: dps310: data-ready trigger Rupesh Majhi
2026-11-14  8:38 ` [PATCH v2 1/2] dt-bindings: iio: pressure: infineon,dps310: Add interrupts Rupesh Majhi
2026-11-14  8:38 ` [PATCH v2 2/2] iio: pressure: dps310: add a data-ready trigger Rupesh Majhi

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®