From nobody Mon Feb 9 10:39:29 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9EC631FC114; Mon, 28 Apr 2025 10:50:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1745837434; cv=none; b=fxCidEKQLs0Kah7mETpmHtTanER6qqhsyhkmBd8B/vmRwIPK0+n35lGqncnUiU69gSWpBZXS6QecV/oLK1fj/8l3Pn4bMgPjX8PdsxaHYbMxL1Vb8bDTHCPNQFbxt7d59u4zKLEQdoP5yGY2CwptOdBcF99wS7ixazkaBpYg8yI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1745837434; c=relaxed/simple; bh=twpXuJB+cfsFJsY8tYMM4GKFf3+aZHniWnw6MjKaaZo=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=gFHJLMi7LcuKxgAokgQz+EHpB2u8rzn0JapWaNoayGBggaxjaPuOYeIGORoCSccqnITMhJRcdd+oIRk81rpQpa6oeFen2/o3VWbwPHOv1n2U0rKUncSS8soIFpWcY3tMfRHhd35BhahsA0eHxTq+HURkJ6baM/8E5FglNUmI0Fk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=LqtYcUy4; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="LqtYcUy4" Received: by smtp.kernel.org (Postfix) with ESMTPS id 3384CC4CEED; Mon, 28 Apr 2025 10:50:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1745837434; bh=twpXuJB+cfsFJsY8tYMM4GKFf3+aZHniWnw6MjKaaZo=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=LqtYcUy4XKAvpzevlWJ5xkiFSoKl/VZsh4R0OLp7dk+IkLUJ/wDfI2JJ09Vy1Mwa5 wAMz+kKfHB8BS7ToUUY0Eo/1t/oCRMt4JgFSnDuN/3TXJ0K7ULqENsAamtpPiGntQX bEkF/Dl/mEa3rXDTjS+3w22buNUBT8bDYfTKlSqxCjErHx9yk9LddTC0FSPt/I+MCu l0nDzrMa/DksHKS/SJY0Hio/jJbN0PqyNmUvaN8c8dFfczG0E/mOZfreU/m5lvPeOu 3q6vbmrOGmPw2eGnYBrFl4NaxdoTxTr6U4hBx45QCH1Xv2VNMXIZShNDfZKryk6jGs ecIRkPP7YT9CA== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 224F1C369D3; Mon, 28 Apr 2025 10:50:34 +0000 (UTC) From: =?utf-8?q?T=C3=B3th_J=C3=A1nos_via_B4_Relay?= Date: Mon, 28 Apr 2025 12:50:13 +0200 Subject: [PATCH 1/2] dt-bindings: iio: chemical: Document SEN0322 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250428-iio-chemical-sen0322-v1-1-9b18363ffe42@gmail.com> References: <20250428-iio-chemical-sen0322-v1-0-9b18363ffe42@gmail.com> In-Reply-To: <20250428-iio-chemical-sen0322-v1-0-9b18363ffe42@gmail.com> To: Jonathan Cameron , Lars-Peter Clausen , Rob Herring , Krzysztof Kozlowski , Conor Dooley Cc: linux-iio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, =?utf-8?q?T=C3=B3th_J=C3=A1nos?= X-Mailer: b4 0.13.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1745837432; l=1418; i=gomba007@gmail.com; s=20230706; h=from:subject:message-id; bh=0xoZK3utDzrQmadpl8iAFzEdDReFTnsvqPVnBKUfQhE=; b=gcjxH5FV6xoBddG8KX8yGpC+BYXKxA+r2MBnFPA0kEZ0bO/lhMjI2cyKcg286Is61lO2TMqLN yFi3gDFnqn3CG0ZtmO2pXR7YJqgdXtJL4qMWZEIj6POgdLliYXegYRd X-Developer-Key: i=gomba007@gmail.com; a=ed25519; pk=iY9MjPCbud82ULS2PQJIq3QwjKyP/Sg730I6T2M8Y5U= X-Endpoint-Received: by B4 Relay for gomba007@gmail.com/20230706 with auth_id=60 X-Original-From: =?utf-8?q?T=C3=B3th_J=C3=A1nos?= Reply-To: gomba007@gmail.com From: T=C3=B3th J=C3=A1nos Add documentation for the DFRobot SEN0322 oxygen sensor. Signed-off-by: T=C3=B3th J=C3=A1nos --- .../bindings/iio/chemical/dfrobot,sen0322.yaml | 41 ++++++++++++++++++= ++++ 1 file changed, 41 insertions(+) diff --git a/Documentation/devicetree/bindings/iio/chemical/dfrobot,sen0322= .yaml b/Documentation/devicetree/bindings/iio/chemical/dfrobot,sen0322.yaml new file mode 100644 index 000000000000..9410d04fb91d --- /dev/null +++ b/Documentation/devicetree/bindings/iio/chemical/dfrobot,sen0322.yaml @@ -0,0 +1,41 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/chemical/dfrobot,sen0322.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: DFRobot SEN0322 oxygen sensor + +maintainers: + - T=C3=B3th J=C3=A1nos + +description: > + DFRobot SEN0322 is an oxygen sensor. It supports I2C for communication. + + Datasheet: + https://wiki.dfrobot.com/Gravity_I2C_Oxygen_Sensor_SKU_SEN0322 + +properties: + compatible: + const: dfrobot,sen0322 + + reg: + maxItems: 1 + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + i2c { + #address-cells =3D <1>; + #size-cells =3D <0>; + + sen0322@73 { + compatible =3D "dfrobot,sen0322"; + reg =3D <0x73>; + }; + }; --=20 2.34.1 From nobody Mon Feb 9 10:39:29 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9ECCA2356BC; Mon, 28 Apr 2025 10:50:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1745837434; cv=none; b=IqLgqodl6akxskVt+egtz3zIgij0l9XOos+Rf/DAhkD/4cmoRsKo63KnEb1/61sgdhuleatJ5xB+z7+Au/D2EC+0QYwC+2qLJ1Ik/3p2wHl0MEjDQks0MZLS2B5UcVeDPCZqnvts0/2wAOzeX2FEt5bTvv92y8kJSotcwBiAmvw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1745837434; c=relaxed/simple; bh=hMeNKiOKKFWOmvzql0ooVumxoWM7K7FV4b1JMI801XA=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=owixTTNDvyRl0/K9VG3jYmzvLCqEICFTe1rLkv4aPu/HBSpCxQSxChLh+Yo1Bvsb6q5OH+8knoHh1SitESGWRkB2kYc71on4Qg1mccVv2vIgYwHKBya4tdjQNI7zLNSj3t64CG8kxYgD6HwN4zqQ6aPemTM/cD4igkm7icYxKAo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=L+C7nyFg; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="L+C7nyFg" Received: by smtp.kernel.org (Postfix) with ESMTPS id 3CCC4C4CEE9; Mon, 28 Apr 2025 10:50:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1745837434; bh=hMeNKiOKKFWOmvzql0ooVumxoWM7K7FV4b1JMI801XA=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=L+C7nyFgVezISuRI+54TCYyo9/kjGgdQjBYVh0HoOJDDIE0OoDgcz0qqxBjkRDvlu zHmDfGcTFi8MxA4Vz5sgw54m6ATbokob8oTngnJB/CimNAgYtfTRGG0bw7+wPph5vo Oa8ltQgGwXvq6sAV590dkn4ziu/aTcaBqMD5OWh/+yevlu4SsfbwcSxQ9h8SXCSXI9 KTYy62Ta4YJLRzCiGknXEjKKCmb/zV/8elRRZ9ebr6VZeN9rsDEn0e3EW1+S8KvEY0 fzXJVsFM56IeN/4j0Ugq26tRHu9iQWU3QaTngGMw1BHp2Qqvdk2TG0RLrI7YOrA4MR g4OcBT1e8Tg8A== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2F8EAC3ABA3; Mon, 28 Apr 2025 10:50:34 +0000 (UTC) From: =?utf-8?q?T=C3=B3th_J=C3=A1nos_via_B4_Relay?= Date: Mon, 28 Apr 2025 12:50:14 +0200 Subject: [PATCH 2/2] iio: chemical: Add driver for SEN0322 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250428-iio-chemical-sen0322-v1-2-9b18363ffe42@gmail.com> References: <20250428-iio-chemical-sen0322-v1-0-9b18363ffe42@gmail.com> In-Reply-To: <20250428-iio-chemical-sen0322-v1-0-9b18363ffe42@gmail.com> To: Jonathan Cameron , Lars-Peter Clausen , Rob Herring , Krzysztof Kozlowski , Conor Dooley Cc: linux-iio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, =?utf-8?q?T=C3=B3th_J=C3=A1nos?= X-Mailer: b4 0.13.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1745837433; l=7866; i=gomba007@gmail.com; s=20230706; h=from:subject:message-id; bh=z/iKIdGo85HiWXBMjUced4yjKpzR3DKHdB+pOCkYBQ8=; b=DlsEdiWp/qZ1z5NCPzuU4VaF+5OHiNfxo+kiqZttbUOSVBduVmrbysWNI0VNS7IZiKq69t+3H UbyyIIpKv+MAgnUONxRDEI60qeJe2MY6Aink3AVk+SakzwgqcpkChxc X-Developer-Key: i=gomba007@gmail.com; a=ed25519; pk=iY9MjPCbud82ULS2PQJIq3QwjKyP/Sg730I6T2M8Y5U= X-Endpoint-Received: by B4 Relay for gomba007@gmail.com/20230706 with auth_id=60 X-Original-From: =?utf-8?q?T=C3=B3th_J=C3=A1nos?= Reply-To: gomba007@gmail.com From: T=C3=B3th J=C3=A1nos Add support for the DFRobot SEN0322 oxygen sensor. Datasheet: https://wiki.dfrobot.com/Gravity_I2C_Oxygen_Sensor_SKU_SEN0322 To instantiate (assuming device is connected to I2C-2): echo 'sen0322 0x73' > /sys/class/i2c-dev/i2c-2/device/new_device To read the oxygen concentration (assuming device is iio:device0): cat /sys/bus/iio/devices/iio:device0/in_concentration_input Signed-off-by: T=C3=B3th J=C3=A1nos --- MAINTAINERS | 6 ++ drivers/iio/chemical/Kconfig | 10 ++ drivers/iio/chemical/Makefile | 1 + drivers/iio/chemical/sen0322.c | 238 +++++++++++++++++++++++++++++++++++++= ++++ 4 files changed, 255 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 3cbf9ac0d83f..6fda7a2f1248 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6852,6 +6852,12 @@ L: linux-rtc@vger.kernel.org S: Maintained F: drivers/rtc/rtc-sd2405al.c =20 +DFROBOT SEN0322 DRIVER +M: T=C3=B3th J=C3=A1nos +L: linux-iio@vger.kernel.org +S: Maintained +F: drivers/iio/chemical/sen0322.c + DH ELECTRONICS DHSOM SOM AND BOARD SUPPORT M: Christoph Niedermaier M: Marek Vasut diff --git a/drivers/iio/chemical/Kconfig b/drivers/iio/chemical/Kconfig index 330fe0af946f..60a81863d123 100644 --- a/drivers/iio/chemical/Kconfig +++ b/drivers/iio/chemical/Kconfig @@ -166,6 +166,16 @@ config SCD4X To compile this driver as a module, choose M here: the module will be called scd4x. =20 +config SEN0322 + tristate "SEN0322 oxygen sensor" + depends on I2C + select REGMAP_I2C + help + Say Y here to build support for the DFRobot SEN0322 oxygen sensor. + + To compile this driver as a module, choose M here: the module will + be called sen0322. + config SENSIRION_SGP30 tristate "Sensirion SGPxx gas sensors" depends on I2C diff --git a/drivers/iio/chemical/Makefile b/drivers/iio/chemical/Makefile index 4866db06bdc9..deeff0e4e6f7 100644 --- a/drivers/iio/chemical/Makefile +++ b/drivers/iio/chemical/Makefile @@ -20,6 +20,7 @@ obj-$(CONFIG_SCD30_CORE) +=3D scd30_core.o obj-$(CONFIG_SCD30_I2C) +=3D scd30_i2c.o obj-$(CONFIG_SCD30_SERIAL) +=3D scd30_serial.o obj-$(CONFIG_SCD4X) +=3D scd4x.o +obj-$(CONFIG_SEN0322) +=3D sen0322.o obj-$(CONFIG_SENSEAIR_SUNRISE_CO2) +=3D sunrise_co2.o obj-$(CONFIG_SENSIRION_SGP30) +=3D sgp30.o obj-$(CONFIG_SENSIRION_SGP40) +=3D sgp40.o diff --git a/drivers/iio/chemical/sen0322.c b/drivers/iio/chemical/sen0322.c new file mode 100644 index 000000000000..5f1f4528401e --- /dev/null +++ b/drivers/iio/chemical/sen0322.c @@ -0,0 +1,238 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Driver for the DFRobot SEN0322 oxygen sensor. + * + * Datasheet: + * https://wiki.dfrobot.com/Gravity_I2C_Oxygen_Sensor_SKU_SEN0322 + * + * Possible I2C slave addresses: + * 0x70 + * 0x71 + * 0x72 + * 0x73 + * + * Copyright (C) 2025 T=C3=B3th J=C3=A1nos + */ + +#include +#include +#include +#include + +#include + +#define DRIVER_NAME "sen0322" + +#define SEN0322_REG_DATA 0x03 +#define SEN0322_REG_COEFF 0x0A + +#define FIXED_FRAC_BITS 18 +#define FIXED_INT(x) ((fixed_t)((x) << FIXED_FRAC_BITS)) + +typedef u32 fixed_t; + +struct sen0322 { + struct i2c_client *client; + struct regmap *regmap; + fixed_t coeff; +}; + +static fixed_t fixed_mul(fixed_t a, fixed_t b) +{ + u64 tmp; + + tmp =3D (u64)a * (u64)b; + tmp =3D (tmp >> FIXED_FRAC_BITS) + ((tmp >> FIXED_FRAC_BITS) & 1); + + if (tmp > U32_MAX) + return (fixed_t)U32_MAX; + else + return (fixed_t)tmp; +} + +static fixed_t fixed_div(fixed_t a, fixed_t b) +{ + u64 tmp; + + tmp =3D (uint64_t)a << FIXED_FRAC_BITS; + tmp +=3D (b >> 1); + + return (fixed_t)(div_u64(tmp, b)); +} + +static int sen0322_read_coeff(struct sen0322 *sen0322) +{ + u32 val; + int ret; + + ret =3D regmap_read(sen0322->regmap, SEN0322_REG_COEFF, &val); + if (ret < 0) + return ret; + + if (val) + sen0322->coeff =3D fixed_div(FIXED_INT(val), FIXED_INT(1000)); + else + sen0322->coeff =3D fixed_div(FIXED_INT(209), FIXED_INT(1200)); + + dev_dbg(&sen0322->client->dev, "coeff: %08X\n", sen0322->coeff); + + return 0; +} + +static int sen0322_read_data(struct sen0322 *sen0322) +{ + u8 data[4] =3D { 0 }; + int ret; + + ret =3D regmap_bulk_read(sen0322->regmap, SEN0322_REG_DATA, data, 3); + if (ret < 0) + return ret; + + ret =3D data[0] * 100 + data[1] * 10 + data[2]; + + dev_dbg(&sen0322->client->dev, "raw data: %d\n", ret); + + return ret; +} + +static int sen0322_read_prep_data(struct sen0322 *sen0322) +{ + fixed_t val; + int ret; + + if (!sen0322->coeff) { + ret =3D sen0322_read_coeff(sen0322); + if (ret < 0) + return ret; + } + + ret =3D sen0322_read_data(sen0322); + if (ret < 0) + return ret; + + val =3D fixed_mul(sen0322->coeff, FIXED_INT(ret)); + + dev_dbg(&sen0322->client->dev, "prep data: %08X\n", val); + + return val >> FIXED_FRAC_BITS; +} + +static int sen0322_read_raw(struct iio_dev *iio_dev, + const struct iio_chan_spec *chan, + int *val, int *val2, long mask) +{ + struct sen0322 *sen0322 =3D iio_priv(iio_dev); + int ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + switch (chan->type) { + case IIO_CONCENTRATION: + ret =3D sen0322_read_data(sen0322); + if (ret < 0) + return ret; + + *val =3D ret; + return IIO_VAL_INT; + + default: + return -EINVAL; + } + + case IIO_CHAN_INFO_PROCESSED: + switch (chan->type) { + case IIO_CONCENTRATION: + ret =3D sen0322_read_prep_data(sen0322); + if (ret < 0) + return ret; + + *val =3D ret; + return IIO_VAL_INT; + + default: + return -EINVAL; + } + + case IIO_CHAN_INFO_SCALE: + switch (chan->type) { + case IIO_CONCENTRATION: + *val =3D 1; + *val2 =3D 100; + return IIO_VAL_FRACTIONAL; + + default: + return -EINVAL; + } + + default: + return -EINVAL; + } +} + +static const struct iio_info sen0322_info =3D { + .read_raw =3D sen0322_read_raw, +}; + +static const struct regmap_config sen0322_regmap_conf =3D { + .reg_bits =3D 8, + .val_bits =3D 8, +}; + +static const struct iio_chan_spec sen0322_channels[] =3D { + { + .type =3D IIO_CONCENTRATION, + .info_mask_separate =3D BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_PROCESSED) | + BIT(IIO_CHAN_INFO_SCALE), + }, +}; + +static int sen0322_probe(struct i2c_client *client) +{ + struct sen0322 *sen0322; + struct iio_dev *iio_dev; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) + return -ENODEV; + + iio_dev =3D devm_iio_device_alloc(&client->dev, sizeof(*sen0322)); + if (!iio_dev) + return -ENOMEM; + + sen0322 =3D iio_priv(iio_dev); + sen0322->client =3D client; + sen0322->coeff =3D 0; + + sen0322->regmap =3D devm_regmap_init_i2c(client, &sen0322_regmap_conf); + if (IS_ERR(sen0322->regmap)) + return PTR_ERR(sen0322->regmap); + + i2c_set_clientdata(client, sen0322); + + iio_dev->info =3D &sen0322_info; + iio_dev->name =3D DRIVER_NAME; + iio_dev->channels =3D sen0322_channels; + iio_dev->num_channels =3D ARRAY_SIZE(sen0322_channels); + iio_dev->modes =3D INDIO_DIRECT_MODE; + + return devm_iio_device_register(&client->dev, iio_dev); +} + +static const struct of_device_id sen0322_of_match[] =3D { + { .compatible =3D "dfrobot,sen0322" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, sen0322_of_match); + +static struct i2c_driver sen0322_driver =3D { + .driver =3D { + .name =3D DRIVER_NAME, + .of_match_table =3D sen0322_of_match, + }, + .probe =3D sen0322_probe, +}; +module_i2c_driver(sen0322_driver); + +MODULE_AUTHOR("T=C3=B3th J=C3=A1nos "); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("SEN0322 oxygen sensor driver"); --=20 2.34.1