mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Jaakko Koivisto <jmatko@utu.fi>
To: "Andreas Klinger" <ak@it-klinger.de>,
	"Jonathan Cameron" <jic23@kernel.org>,
	"David Lechner" <dlechner@baylibre.com>,
	"Nuno Sá" <nuno.sa@analog.com>,
	"Andy Shevchenko" <andy@kernel.org>
Cc: <linux-iio@vger.kernel.org>, <linux-kernel@vger.kernel.org>,
	Jaakko Koivisto <jmatko@utu.fi>
Subject: [PATCH v2 3/5] iio: chemical: sgp40: Implement get_serial_number-command
Date: Mon, 2 Nov 2026 11:12:56 +0200	[thread overview]
Message-ID: <20261102091258.247402-4-jmatko@utu.fi> (raw)
In-Reply-To: <20261102091258.247402-1-jmatko@utu.fi>

Add functionality for retrieving SGP40 sensor serial number
and present it to the userspace using serialnumber ABI.

Signed-off-by: Jaakko Koivisto <jmatko@utu.fi>
---
Currently only the bno055 driver uses the serialnumber ABI, and presents
the SN in hex. Documentation gives hex output as example format, not hard
requirement, but should we use the same format here anyway?

 drivers/iio/chemical/sgp40.c | 76 ++++++++++++++++++++++++++++++++++++
 1 file changed, 76 insertions(+)

diff --git a/drivers/iio/chemical/sgp40.c b/drivers/iio/chemical/sgp40.c
index 080d51f9f53c..e0a300720fce 100644
--- a/drivers/iio/chemical/sgp40.c
+++ b/drivers/iio/chemical/sgp40.c
@@ -35,6 +35,7 @@
 #include <linux/mutex.h>
 #include <linux/i2c.h>
 #include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
 
 /*
  * floating point calculation of voc is done as integer
@@ -70,6 +71,18 @@ struct sgp40_tg_result {
 	u8	res_crc;
 } __packed;
 
+/*
+ * Datasheet table 16. Serial number is given as 48-bit value 0xAAAABBBBCCCC.
+ */
+struct sgp40_serial_number_result {
+	__be16	A;
+	u8	A_crc;
+	__be16	B;
+	u8	B_crc;
+	__be16	C;
+	u8	C_crc;
+} __packed;
+
 static const struct iio_chan_spec sgp40_channels[] = {
 	{
 		.type = IIO_CONCENTRATION,
@@ -161,6 +174,41 @@ static int sgp40_calc_voc(struct sgp40_data *data, u16 resistance_raw, int *voc)
 	return 0;
 }
 
+static int sgp40_get_serial_number(struct sgp40_data *data, u64 *serial_number)
+{
+	int ret;
+	struct i2c_client *client = data->client;
+	struct sgp40_tg_measure get_sn = { .command = {0x36, 0x82} };
+	struct sgp40_serial_number_result res;
+
+	guard(mutex)(&data->lock);
+
+	ret = i2c_master_send(client, (char *)&get_sn, sizeof(get_sn.command));
+	if (ret < 0)
+		return ret;
+	if (ret != sizeof(get_sn.command))
+		return dev_err_probe(data->dev, -EIO,
+		       "i2c_master_send ret: %d, expected %zu\n", ret, sizeof(get_sn.command));
+
+	fsleep(1000); /* Max duration for get_serial_number command. Datasheet table 8. */
+
+	ret = i2c_master_recv(client, (char *)&res, sizeof(res));
+	if (ret < 0)
+		return ret;
+	if (ret != sizeof(res))
+		return dev_err_probe(data->dev, -EIO,
+		       "i2c_master_recv ret: %d, expected: %zu\n", ret, sizeof(res));
+
+	if (crc8(sgp40_crc8_table, (u8 *)&res.A, 2, SGP40_CRC8_INIT) != res.A_crc ||
+	    crc8(sgp40_crc8_table, (u8 *)&res.B, 2, SGP40_CRC8_INIT) != res.B_crc ||
+	    crc8(sgp40_crc8_table, (u8 *)&res.C, 2, SGP40_CRC8_INIT) != res.C_crc)
+		return dev_err_probe(data->dev, -EIO, "CRC error in get_serial_number\n");
+
+	*serial_number = ((u64)be16_to_cpu(res.A) << 32) | ((u64)be16_to_cpu(res.B) << 16) | (u64)be16_to_cpu(res.C);
+
+	return 0;
+}
+
 static int sgp40_measure_resistance_raw(struct sgp40_data *data, u16 *resistance_raw)
 {
 	int ret;
@@ -306,9 +354,37 @@ static int sgp40_write_raw(struct iio_dev *indio_dev,
 	return -EINVAL;
 }
 
+static ssize_t serialnumber_show(struct device *dev,
+				  struct device_attribute *attr,
+				  char *buf)
+{
+	int ret;
+	u64 serial_number;
+	struct sgp40_data *data = iio_priv(dev_to_iio_dev(dev));
+
+	ret = sgp40_get_serial_number(data, &serial_number);
+	if (ret < 0)
+		return ret;
+
+	return sysfs_emit_at(buf, 0, "%llu\n", serial_number);
+}
+
+static IIO_DEVICE_ATTR_RO(serialnumber, 0);
+
+static struct attribute *sgp40_attributes[] = {
+	&iio_dev_attr_serialnumber.dev_attr.attr,
+	NULL
+};
+
+static struct attribute_group sgp40_attribute_group = {
+	.attrs = sgp40_attributes,
+};
+
+
 static const struct iio_info sgp40_info = {
 	.read_raw	= sgp40_read_raw,
 	.write_raw	= sgp40_write_raw,
+	.attrs		= &sgp40_attribute_group,
 };
 
 static int sgp40_probe(struct i2c_client *client)
-- 
2.56.0


  parent reply	other threads:[~2026-11-02  9:15 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-02  9:12 [PATCH v2 0/5] iio: chemical: sgp40: add funtions for serial number readback, self-test, and heater control Jaakko Koivisto
2026-11-02  9:12 ` [PATCH v2 1/5] iio: chemical: sgp40: Do not convert I2C errors to EIO Jaakko Koivisto
2026-11-02  9:54   ` Joshua Crofts
2026-11-02  9:12 ` [PATCH v2 2/5] iio: chemical: sgp40: Replace manual locking with guard() Jaakko Koivisto
2026-11-02 10:10   ` Joshua Crofts
2026-11-02  9:12 ` Jaakko Koivisto [this message]
2026-11-02 10:20   ` [PATCH v2 3/5] iio: chemical: sgp40: Implement get_serial_number-command Joshua Crofts
2026-11-02  9:12 ` [PATCH v2 4/5] iio: chemical: sgp40: Implement execute_self_test-command Jaakko Koivisto
2026-11-02 10:21   ` Joshua Crofts
2026-11-02  9:56 ` [PATCH v2 5/5] iio: chemical: sgp40: Implement turn_heater_off-command Jaakko Koivisto
2026-11-02 10:24   ` Joshua Crofts

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261102091258.247402-4-jmatko@utu.fi \
    --to=jmatko@utu.fi \
    --cc=ak@it-klinger.de \
    --cc=andy@kernel.org \
    --cc=dlechner@baylibre.com \
    --cc=jic23@kernel.org \
    --cc=linux-iio@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=nuno.sa@analog.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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®