mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v4 0/2] iio: pressure: add Sensirion SDP31 driver
       [not found] <20260928215422.3720-1-m.abubakar365.ref@yahoo.com>
@ 2026-09-28 21:54 ` Muhammad Abu Bakar
  2026-09-28 21:54   ` [PATCH v4 1/2] dt-bindings: iio: pressure: add Sensirion SDP31 Muhammad Abu Bakar
  2026-09-28 21:54   ` [PATCH v4 2/2] iio: pressure: add Sensirion SDP31 driver Muhammad Abu Bakar
  0 siblings, 2 replies; 4+ messages in thread
From: Muhammad Abu Bakar @ 2026-09-28 21:54 UTC (permalink / raw)
  To: Jonathan Cameron, Rob Herring, Krzysztof Kozlowski, Conor Dooley
  Cc: dlechner, nuno.sa, andy, linux-iio, devicetree, linux-kernel,
	m.abubakar365

This series adds support for the Sensirion SDP3x family of differential
pressure sensors (SDP31, SDP32 and SDP33), I2C devices that also report
temperature.

The SDP3x uses a completely different I2C command protocol from the
already supported SDP500, so extending the sdp500 driver does not make
sense.

Patch 1 adds the device tree binding.
Patch 2 adds the IIO driver, which exposes differential pressure and
temperature channels and validates each measurement using the sensor's
CRC-8 checksum. The scale factor is read from the sensor at runtime, so
the SDP31, SDP32 and SDP33 (which differ only in range) are all supported.
Tested on an SDP31 wired to the I2C bus of a Raspberry Pi 4.

Changes since v3:
- dt-bindings: support the whole SDP3x family (sdp31/sdp32/sdp33) and
  describe the optional interrupt line.
- driver: for a normal measurement read only the pressure and temperature
  words (6 bytes); read the scale factor once at probe.
- driver: add sdp32/sdp33 to the match tables and report the matched part
  name.
- driver: add a file header with the datasheet link and drop comments that
  only restated the code.

v1: https://lore.kernel.org/linux-iio/20260919223650.13396-1-m.abubakar365@yahoo.com/
v2: https://lore.kernel.org/linux-iio/20260920164533.31988-1-m.abubakar365@yahoo.com/
v3: https://lore.kernel.org/linux-iio/20260926154118.5471-1-m.abubakar365@yahoo.com/

Muhammad Abu Bakar (2):
  dt-bindings: iio: pressure: add Sensirion SDP31
  iio: pressure: add Sensirion SDP31 driver

 .../iio/pressure/sensirion,sdp31.yaml         |  48 ++++
 MAINTAINERS                                   |   6 +
 drivers/iio/pressure/Kconfig                  |  11 +
 drivers/iio/pressure/Makefile                 |   1 +
 drivers/iio/pressure/sdp31.c                  | 241 ++++++++++++++++++
 5 files changed, 307 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/iio/pressure/sensirion,sdp31.yaml
 create mode 100644 drivers/iio/pressure/sdp31.c

-- 
2.43.0


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

* [PATCH v4 1/2] dt-bindings: iio: pressure: add Sensirion SDP31
  2026-09-28 21:54 ` [PATCH v4 0/2] iio: pressure: add Sensirion SDP31 driver Muhammad Abu Bakar
@ 2026-09-28 21:54   ` Muhammad Abu Bakar
  2026-09-28 21:54   ` [PATCH v4 2/2] iio: pressure: add Sensirion SDP31 driver Muhammad Abu Bakar
  1 sibling, 0 replies; 4+ messages in thread
From: Muhammad Abu Bakar @ 2026-09-28 21:54 UTC (permalink / raw)
  To: Jonathan Cameron, Rob Herring, Krzysztof Kozlowski, Conor Dooley
  Cc: dlechner, nuno.sa, andy, linux-iio, devicetree, linux-kernel,
	m.abubakar365

Add device tree bindings for the Sensirion SDP3x family of differential
pressure sensors (SDP31, SDP32 and SDP33), I2C devices that also report
temperature.

Signed-off-by: Muhammad Abu Bakar <m.abubakar365@yahoo.com>
---
 .../iio/pressure/sensirion,sdp31.yaml         | 48 +++++++++++++++++++
 MAINTAINERS                                   |  5 ++
 2 files changed, 53 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/iio/pressure/sensirion,sdp31.yaml

diff --git a/Documentation/devicetree/bindings/iio/pressure/sensirion,sdp31.yaml b/Documentation/devicetree/bindings/iio/pressure/sensirion,sdp31.yaml
new file mode 100644
index 000000000..b9d3c6441
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/pressure/sensirion,sdp31.yaml
@@ -0,0 +1,48 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/pressure/sensirion,sdp31.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Sensirion SDP31, SDP32 and SDP33 differential pressure sensors
+
+maintainers:
+  - Muhammad Abu Bakar <m.abubakar365@yahoo.com>
+
+description: |
+  Differential pressure sensors from Sensirion with an I2C interface.
+  The SDP31, SDP32 and SDP33 differ only in their measurement range.
+
+properties:
+  compatible:
+    enum:
+      - sensirion,sdp31
+      - sensirion,sdp32
+      - sensirion,sdp33
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  vdd-supply: true
+
+required:
+  - compatible
+  - reg
+  - vdd-supply
+
+additionalProperties: false
+
+examples:
+  - |
+    i2c {
+      #address-cells = <1>;
+      #size-cells = <0>;
+      pressure@21 {
+        compatible = "sensirion,sdp31";
+        reg = <0x21>;
+        vdd-supply = <&vdd_3v3>;
+      };
+    };
diff --git a/MAINTAINERS b/MAINTAINERS
index 214aeee76..e285147be 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -24855,6 +24855,11 @@ S:	Maintained
 F:	Documentation/devicetree/bindings/iio/chemical/sensirion,scd4x.yaml
 F:	drivers/iio/chemical/scd4x.c
 
+SENSIRION SDP31 DIFFERENTIAL PRESSURE SENSOR DRIVER
+M:	Muhammad Abu Bakar <m.abubakar365@yahoo.com>
+S:	Maintained
+F:	Documentation/devicetree/bindings/iio/pressure/sensirion,sdp31.yaml
+
 SENSIRION SDP500 DIFFERENTIAL PRESSURE SENSOR DRIVER
 M:	Petar Stoykov <petar.stoykov@prodrive-technologies.com>
 S:	Maintained
-- 
2.43.0


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

* [PATCH v4 2/2] iio: pressure: add Sensirion SDP31 driver
  2026-09-28 21:54 ` [PATCH v4 0/2] iio: pressure: add Sensirion SDP31 driver Muhammad Abu Bakar
  2026-09-28 21:54   ` [PATCH v4 1/2] dt-bindings: iio: pressure: add Sensirion SDP31 Muhammad Abu Bakar
@ 2026-09-28 21:54   ` Muhammad Abu Bakar
  2026-09-28 22:04     ` Andy Shevchenko
  1 sibling, 1 reply; 4+ messages in thread
From: Muhammad Abu Bakar @ 2026-09-28 21:54 UTC (permalink / raw)
  To: Jonathan Cameron, Rob Herring, Krzysztof Kozlowski, Conor Dooley
  Cc: dlechner, nuno.sa, andy, linux-iio, devicetree, linux-kernel,
	m.abubakar365

Add an IIO driver for the Sensirion SDP3x family of differential pressure
sensors (SDP31, SDP32 and SDP33). The devices are accessed over I2C and
report differential pressure and temperature. Each measurement is
validated using the sensor's CRC-8 checksum. The scale factor is read
from the sensor at runtime, so all three parts are supported.

Tested on an SDP31 connected to a Raspberry Pi 4 I2C bus.

Signed-off-by: Muhammad Abu Bakar <m.abubakar365@yahoo.com>
---
 MAINTAINERS                   |   1 +
 drivers/iio/pressure/Kconfig  |  11 ++
 drivers/iio/pressure/Makefile |   1 +
 drivers/iio/pressure/sdp31.c  | 241 ++++++++++++++++++++++++++++++++++
 4 files changed, 254 insertions(+)
 create mode 100644 drivers/iio/pressure/sdp31.c

diff --git a/MAINTAINERS b/MAINTAINERS
index e285147be..a053a530e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -24859,6 +24859,7 @@ SENSIRION SDP31 DIFFERENTIAL PRESSURE SENSOR DRIVER
 M:	Muhammad Abu Bakar <m.abubakar365@yahoo.com>
 S:	Maintained
 F:	Documentation/devicetree/bindings/iio/pressure/sensirion,sdp31.yaml
+F:	drivers/iio/pressure/sdp31.c
 
 SENSIRION SDP500 DIFFERENTIAL PRESSURE SENSOR DRIVER
 M:	Petar Stoykov <petar.stoykov@prodrive-technologies.com>
diff --git a/drivers/iio/pressure/Kconfig b/drivers/iio/pressure/Kconfig
index 838a8340c..58172639c 100644
--- a/drivers/iio/pressure/Kconfig
+++ b/drivers/iio/pressure/Kconfig
@@ -286,6 +286,17 @@ config MS5637
 	  This driver can also be built as a module. If so, the module will
 	  be called ms5637.
 
+config SDP31
+	tristate "Sensirion SDP31 differential pressure sensor I2C driver"
+	depends on I2C
+	select CRC8
+	help
+	  Say Y here to build support for Sensirion SDP31 differential pressure
+	  sensor I2C driver.
+
+	  To compile this driver as a module, choose M here: the core module
+	  will be called sdp31.
+
 config SDP500
 	tristate "Sensirion SDP500 differential pressure sensor I2C driver"
 	depends on I2C
diff --git a/drivers/iio/pressure/Makefile b/drivers/iio/pressure/Makefile
index bc0d11a20..5279a0ebd 100644
--- a/drivers/iio/pressure/Makefile
+++ b/drivers/iio/pressure/Makefile
@@ -35,6 +35,7 @@ obj-$(CONFIG_MS5611) += ms5611_core.o
 obj-$(CONFIG_MS5611_I2C) += ms5611_i2c.o
 obj-$(CONFIG_MS5611_SPI) += ms5611_spi.o
 obj-$(CONFIG_MS5637) += ms5637.o
+obj-$(CONFIG_SDP31) += sdp31.o
 obj-$(CONFIG_SDP500) += sdp500.o
 obj-$(CONFIG_IIO_ST_PRESS) += st_pressure.o
 st_pressure-y := st_pressure_core.o
diff --git a/drivers/iio/pressure/sdp31.c b/drivers/iio/pressure/sdp31.c
new file mode 100644
index 000000000..78ab776ab
--- /dev/null
+++ b/drivers/iio/pressure/sdp31.c
@@ -0,0 +1,241 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Driver for Sensirion SDP31, SDP32 and SDP33 differential pressure sensors
+ *
+ * Datasheet:
+ * https://sensirion.com/media/documents/4D045D69/6375F34F/DP_DS_SDP3x_digital_D1.pdf
+ */
+#include <linux/cleanup.h>
+#include <linux/crc8.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/once.h>
+#include <linux/regulator/consumer.h>
+#include <linux/unaligned.h>
+
+#include <linux/iio/iio.h>
+
+#define SDP31_CMD_TRIG_DP     0x362F
+#define SDP31_MEAS_DELAY_MS   50
+#define SDP31_POWERUP_TIME_MS 25   /* datasheet t_PU (max) */
+#define SDP31_CRC8_POLY       0x31
+#define SDP31_CRC8_INIT       0xff
+
+DECLARE_CRC8_TABLE(sdp31_crc8_table);
+
+struct sdp31_data {
+	struct i2c_client *client;
+	struct mutex lock; /* serializes access to the sensor */
+	u16 dp_scale;
+};
+
+static int sdp31_send_cmd(struct i2c_client *client, u16 cmd)
+{
+	__be16 buf = cpu_to_be16(cmd);
+	int ret;
+
+	ret = i2c_master_send(client, (u8 *)&buf, sizeof(buf));
+	if (ret < 0)
+		return ret;
+
+	return (ret == sizeof(buf)) ? 0 : -EIO;
+}
+
+static int sdp31_check_crc(const u8 *word)
+{
+	if (crc8(sdp31_crc8_table, word, 2, SDP31_CRC8_INIT) != word[2])
+		return -EIO;
+
+	return 0;
+}
+
+/*
+ * Trigger a differential-pressure measurement and read the first len bytes
+ * of the result. A short read is ended by the usual I2C NACK + stop, so
+ * reading fewer than the full nine bytes is fine.
+ */
+static int sdp31_trigger_read(struct sdp31_data *data, u8 *rx, int len)
+{
+	int ret;
+
+	guard(mutex)(&data->lock);
+
+	ret = sdp31_send_cmd(data->client, SDP31_CMD_TRIG_DP);
+	if (ret)
+		return ret;
+
+	msleep(SDP31_MEAS_DELAY_MS);
+
+	ret = i2c_master_recv(data->client, rx, len);
+	if (ret < 0)
+		return ret;
+
+	return (ret == len) ? 0 : -EIO;
+}
+
+static int sdp31_read_measurement(struct sdp31_data *data, s16 *pressure,
+				  s16 *temp)
+{
+	u8 rx[6];
+	int ret;
+
+	ret = sdp31_trigger_read(data, rx, sizeof(rx));
+	if (ret)
+		return ret;
+
+	if (sdp31_check_crc(&rx[0]) || sdp31_check_crc(&rx[3]))
+		return -EIO;
+
+	*pressure = (s16)get_unaligned_be16(&rx[0]);
+	*temp = (s16)get_unaligned_be16(&rx[3]);
+
+	return 0;
+}
+
+static int sdp31_read_scale(struct sdp31_data *data, u16 *scale)
+{
+	u8 rx[9];
+	int ret;
+
+	ret = sdp31_trigger_read(data, rx, sizeof(rx));
+	if (ret)
+		return ret;
+
+	if (sdp31_check_crc(&rx[6]))
+		return -EIO;
+
+	*scale = get_unaligned_be16(&rx[6]);
+
+	return 0;
+}
+
+static int sdp31_read_raw(struct iio_dev *indio_dev,
+			  struct iio_chan_spec const *chan,
+			  int *val, int *val2, long mask)
+{
+	struct sdp31_data *data = iio_priv(indio_dev);
+	s16 pressure, temp;
+	int ret;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		ret = sdp31_read_measurement(data, &pressure, &temp);
+		if (ret)
+			return ret;
+		switch (chan->type) {
+		case IIO_PRESSURE:
+			*val = pressure;
+			return IIO_VAL_INT;
+		case IIO_TEMP:
+			*val = temp;
+			return IIO_VAL_INT;
+		default:
+			return -EINVAL;
+		}
+	case IIO_CHAN_INFO_SCALE:
+		switch (chan->type) {
+		case IIO_PRESSURE:
+			*val = 1;
+			*val2 = data->dp_scale * 1000;
+			return IIO_VAL_FRACTIONAL;
+		case IIO_TEMP:
+			/* raw / 200 = degC, so raw * 5 = milli-degC */
+			*val = 5;
+			return IIO_VAL_INT;
+		default:
+			return -EINVAL;
+		}
+	default:
+		return -EINVAL;
+	}
+}
+
+static const struct iio_info sdp31_info = {
+	.read_raw = sdp31_read_raw,
+};
+
+static const struct iio_chan_spec sdp31_channels[] = {
+	{
+		.type = IIO_PRESSURE,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+				      BIT(IIO_CHAN_INFO_SCALE),
+	},
+	{
+		.type = IIO_TEMP,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+				      BIT(IIO_CHAN_INFO_SCALE),
+	},
+};
+
+static int sdp31_probe(struct i2c_client *client)
+{
+	struct device *dev = &client->dev;
+	struct iio_dev *indio_dev;
+	struct sdp31_data *data;
+	int ret;
+
+	ret = devm_regulator_get_enable(dev, "vdd");
+	if (ret)
+		return dev_err_probe(dev, ret, "failed to enable regulator\n");
+
+	msleep(SDP31_POWERUP_TIME_MS);
+
+	indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
+	if (!indio_dev)
+		return -ENOMEM;
+
+	data = iio_priv(indio_dev);
+	data->client = client;
+
+	ret = devm_mutex_init(dev, &data->lock);
+	if (ret)
+		return ret;
+
+	DO_ONCE(crc8_populate_msb, sdp31_crc8_table, SDP31_CRC8_POLY);
+
+	ret = sdp31_read_scale(data, &data->dp_scale);
+	if (ret)
+		return dev_err_probe(dev, ret, "failed to read from sensor\n");
+	if (!data->dp_scale)
+		return dev_err_probe(dev, -EINVAL, "invalid scale factor\n");
+
+	indio_dev->name = client->name;
+	indio_dev->info = &sdp31_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->channels = sdp31_channels;
+	indio_dev->num_channels = ARRAY_SIZE(sdp31_channels);
+
+	return devm_iio_device_register(dev, indio_dev);
+}
+
+static const struct i2c_device_id sdp31_id[] = {
+	{ .name = "sdp31" },
+	{ .name = "sdp32" },
+	{ .name = "sdp33" },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, sdp31_id);
+
+static const struct of_device_id sdp31_of_match[] = {
+	{ .compatible = "sensirion,sdp31" },
+	{ .compatible = "sensirion,sdp32" },
+	{ .compatible = "sensirion,sdp33" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, sdp31_of_match);
+
+static struct i2c_driver sdp31_driver = {
+	.driver = {
+		.name = "sdp31",
+		.of_match_table = sdp31_of_match,
+	},
+	.probe = sdp31_probe,
+	.id_table = sdp31_id,
+};
+module_i2c_driver(sdp31_driver);
+
+MODULE_AUTHOR("Muhammad Abu Bakar");
+MODULE_DESCRIPTION("Sensirion SDP3x differential pressure sensors");
+MODULE_LICENSE("GPL");
-- 
2.43.0


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

* Re: [PATCH v4 2/2] iio: pressure: add Sensirion SDP31 driver
  2026-09-28 21:54   ` [PATCH v4 2/2] iio: pressure: add Sensirion SDP31 driver Muhammad Abu Bakar
@ 2026-09-28 22:04     ` Andy Shevchenko
  0 siblings, 0 replies; 4+ messages in thread
From: Andy Shevchenko @ 2026-09-28 22:04 UTC (permalink / raw)
  To: Muhammad Abu Bakar
  Cc: Jonathan Cameron, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	dlechner, nuno.sa, andy, linux-iio, devicetree, linux-kernel

On Tue, Sep 29, 2026 at 02:54:22AM +0500, Muhammad Abu Bakar wrote:
> Add an IIO driver for the Sensirion SDP3x family of differential pressure
> sensors (SDP31, SDP32 and SDP33). The devices are accessed over I2C and
> report differential pressure and temperature. Each measurement is
> validated using the sensor's CRC-8 checksum. The scale factor is read
> from the sensor at runtime, so all three parts are supported.
> 
> Tested on an SDP31 connected to a Raspberry Pi 4 I2C bus.

...

> +#include <linux/cleanup.h>
> +#include <linux/crc8.h>
> +#include <linux/delay.h>
> +#include <linux/i2c.h>
> +#include <linux/module.h>
> +#include <linux/mutex.h>
> +#include <linux/once.h>
> +#include <linux/regulator/consumer.h>
> +#include <linux/unaligned.h>

Follow IWYU principle.
At least types.h, err.h or errno.h are absent.

...

> +static int sdp31_read_measurement(struct sdp31_data *data, s16 *pressure,
> +				  s16 *temp)
> +{
> +	u8 rx[6];
> +	int ret;
> +
> +	ret = sdp31_trigger_read(data, rx, sizeof(rx));
> +	if (ret)
> +		return ret;
> +
> +	if (sdp31_check_crc(&rx[0]) || sdp31_check_crc(&rx[3]))
> +		return -EIO;

> +	*pressure = (s16)get_unaligned_be16(&rx[0]);
> +	*temp = (s16)get_unaligned_be16(&rx[3]);

And casting is for...?

> +	return 0;
> +}

...

> +	case IIO_CHAN_INFO_SCALE:
> +		switch (chan->type) {
> +		case IIO_PRESSURE:
> +			*val = 1;
> +			*val2 = data->dp_scale * 1000;

KILO?

> +			return IIO_VAL_FRACTIONAL;
> +		case IIO_TEMP:
> +			/* raw / 200 = degC, so raw * 5 = milli-degC */
> +			*val = 5;
> +			return IIO_VAL_INT;
> +		default:
> +			return -EINVAL;
> +		}

-- 
With Best Regards,
Andy Shevchenko



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

end of thread, other threads:[~2026-09-28 22:04 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <20260928215422.3720-1-m.abubakar365.ref@yahoo.com>
2026-09-28 21:54 ` [PATCH v4 0/2] iio: pressure: add Sensirion SDP31 driver Muhammad Abu Bakar
2026-09-28 21:54   ` [PATCH v4 1/2] dt-bindings: iio: pressure: add Sensirion SDP31 Muhammad Abu Bakar
2026-09-28 21:54   ` [PATCH v4 2/2] iio: pressure: add Sensirion SDP31 driver Muhammad Abu Bakar
2026-09-28 22:04     ` Andy Shevchenko

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®