2023-11-21 10:01:22

by Anshul Dalal

[permalink] [raw]
Subject: [PATCH v3 1/3] dt-bindings: vendor-prefixes: add aosong

Aosong Electronic Co., LTD. is a supplier for MEMS sensors such as AHT20
temperature and humidity sensor under the brand name Asair

Signed-off-by: Anshul Dalal <[email protected]>
---

Changes for v3:
- no updates

v2: https://lore.kernel.org/lkml/[email protected]/

Changes for v2:
- Changed vendor prefix from asair to aosong

v1: https://lore.kernel.org/lkml/[email protected]/
---
Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++
1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml
index 573578db9509..48d4ff635562 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
+++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
@@ -117,6 +117,8 @@ patternProperties:
description: Andes Technology Corporation
"^anvo,.*":
description: Anvo-Systems Dresden GmbH
+ "^aosong,.*":
+ description: Guangzhou Aosong Electronic Co., Ltd.
"^apm,.*":
description: Applied Micro Circuits Corporation (APM)
"^apple,.*":
--
2.42.1


2023-11-21 10:02:53

by Anshul Dalal

[permalink] [raw]
Subject: [PATCH v3 3/3] iio: chemical: add support for Aosong AGS02MA

A simple driver for the TVOC (Total Volatile Organic Compounds)
sensor from Aosong: AGS02MA

Steps in reading the VOC sensor value over i2c:
1. Read 5 bytes from the register `AGS02MA_TVOC_READ_REG` [0x00]
2. The first 4 bytes are taken as the big endian sensor data with final
byte being the CRC
3. The CRC is verified and the value is returned over an
`IIO_CHAN_INFO_RAW` channel as percents

Tested on Raspberry Pi Zero 2W

Datasheet:
https://asairsensors.com/wp-content/uploads/2021/09/AGS02MA.pdf
Product-Page:
http://www.aosong.com/m/en/products-33.html

Signed-off-by: Anshul Dalal <[email protected]>
---

Changes for v3:
- Added of_device_id

v2: https://lore.kernel.org/lkml/[email protected]/

Changes for v2:
- Fixed Kconfig not selecting CRC8 (used to be `select crc8`)
- Changed instances of asair to aosong
- Report raw readings in percents instead of ppb
- Added myself as maintainer for the device binding

v1: https://lore.kernel.org/lkml/[email protected]/
---
MAINTAINERS | 7 ++
drivers/iio/chemical/Kconfig | 11 +++
drivers/iio/chemical/Makefile | 1 +
drivers/iio/chemical/ags02ma.c | 168 +++++++++++++++++++++++++++++++++
4 files changed, 187 insertions(+)
create mode 100644 drivers/iio/chemical/ags02ma.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 81d5fc0bba68..ba3c950aca1b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3028,6 +3028,13 @@ S: Supported
W: http://www.akm.com/
F: drivers/iio/magnetometer/ak8974.c

+AOSONG AGS02MA TVOC SENSOR DRIVER
+M: Anshul Dalal <[email protected]>
+L: [email protected]
+S: Maintained
+F: Documentation/devicetree/bindings/iio/chemical/aosong,ags02ma.yaml
+F: drivers/iio/chemical/ags02ma.c
+
ASC7621 HARDWARE MONITOR DRIVER
M: George Joseph <[email protected]>
L: [email protected]
diff --git a/drivers/iio/chemical/Kconfig b/drivers/iio/chemical/Kconfig
index c30657e10ee1..02649ab81b3c 100644
--- a/drivers/iio/chemical/Kconfig
+++ b/drivers/iio/chemical/Kconfig
@@ -5,6 +5,17 @@

menu "Chemical Sensors"

+config AOSONG_AGS02MA
+ tristate "Aosong AGS02MA TVOC sensor driver"
+ depends on I2C
+ select CRC8
+ help
+ Say Y here to build support for Aosong AGS02MA TVOC (Total Volatile
+ Organic Compounds) sensor.
+
+ To compile this driver as module, choose M here: the module will be
+ called ags02ma.
+
config ATLAS_PH_SENSOR
tristate "Atlas Scientific OEM SM sensors"
depends on I2C
diff --git a/drivers/iio/chemical/Makefile b/drivers/iio/chemical/Makefile
index a11e777a7a00..2f3dee8bb779 100644
--- a/drivers/iio/chemical/Makefile
+++ b/drivers/iio/chemical/Makefile
@@ -4,6 +4,7 @@
#

# When adding new entries keep the list in alphabetical order
+obj-$(CONFIG_AOSONG_AGS02MA) += ags02ma.o
obj-$(CONFIG_ATLAS_PH_SENSOR) += atlas-sensor.o
obj-$(CONFIG_ATLAS_EZO_SENSOR) += atlas-ezo-sensor.o
obj-$(CONFIG_BME680) += bme680_core.o
diff --git a/drivers/iio/chemical/ags02ma.c b/drivers/iio/chemical/ags02ma.c
new file mode 100644
index 000000000000..04a07307caa9
--- /dev/null
+++ b/drivers/iio/chemical/ags02ma.c
@@ -0,0 +1,168 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2023 Anshul Dalal <[email protected]>
+ *
+ * Driver for Aosong AGS02MA
+ *
+ * Datasheet:
+ * https://asairsensors.com/wp-content/uploads/2021/09/AGS02MA.pdf
+ * Product Page:
+ * http://www.aosong.com/m/en/products-33.html
+ *
+ * TODO:
+ * - Add support for ug/m^3 units of measurement
+ * - Add support for modifying i2c address
+ */
+
+#include <linux/crc8.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/iio/iio.h>
+#include <linux/module.h>
+
+#define AGS02MA_DEVICE_NAME "ags02ma"
+
+#define AGS02MA_TVOC_READ_REG 0x00
+#define AGS02MA_VERSION_REG 0x11
+
+#define AGS02MA_VERSION_PROCESSING_DELAY 30
+#define AGS02MA_TVOC_READ_PROCESSING_DELAY 1500
+
+#define AGS02MA_CRC8_INIT 0xff
+#define AGS02MA_CRC8_POLYNOMIAL 0x31
+#define AGS02MA_PPB_PERCENT_CONVERSION 10000000
+
+DECLARE_CRC8_TABLE(ags02ma_crc8_table);
+
+struct ags02ma_data {
+ struct i2c_client *client;
+};
+
+struct ags02ma_reading {
+ __be32 data;
+ u8 crc;
+} __packed;
+
+static u32 ags02ma_register_read(struct i2c_client *client, u8 reg, u16 delay)
+{
+ u32 ret;
+ u8 crc;
+ struct ags02ma_reading read_buffer;
+
+ ret = i2c_master_send(client, &reg, sizeof(reg));
+ if (ret < 0) {
+ dev_err(&client->dev,
+ "Failed to send data to register 0x%x: %d", reg, ret);
+ return ret;
+ }
+
+ /* Processing Delay, Check Table 7.7 in the datasheet */
+ msleep_interruptible(delay);
+
+ ret = i2c_master_recv(client, (u8 *)&read_buffer, sizeof(read_buffer));
+ if (ret < 0) {
+ dev_err(&client->dev,
+ "Failed to receive from register 0x%x: %d", reg, ret);
+ return ret;
+ }
+ ret = be32_to_cpu(read_buffer.data);
+
+ crc = crc8(ags02ma_crc8_table, (u8 *)&read_buffer.data,
+ sizeof(read_buffer.data), AGS02MA_CRC8_INIT);
+ if (crc != read_buffer.crc) {
+ dev_err(&client->dev, "CRC error\n");
+ return -EIO;
+ }
+
+ return ret;
+}
+
+static int ags02ma_read_raw(struct iio_dev *iio_device,
+ struct iio_chan_spec const *chan, int *val,
+ int *val2, long mask)
+{
+ int ret;
+ struct ags02ma_data *data = iio_priv(iio_device);
+
+ if (mask == IIO_CHAN_INFO_RAW) {
+ /* The sensor reads data as ppb */
+ ret = ags02ma_register_read(data->client, AGS02MA_TVOC_READ_REG,
+ AGS02MA_TVOC_READ_PROCESSING_DELAY);
+ if (ret < 0)
+ return ret;
+ *val = ret;
+ *val2 = AGS02MA_PPB_PERCENT_CONVERSION;
+ return IIO_VAL_FRACTIONAL;
+ } else {
+ return -EINVAL;
+ }
+}
+
+static const struct iio_info ags02ma_info = {
+ .read_raw = ags02ma_read_raw,
+};
+
+static const struct iio_chan_spec ags02ma_channels[] = {
+ { .type = IIO_CONCENTRATION,
+ .channel2 = IIO_MOD_VOC,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) }
+};
+
+static int ags02ma_probe(struct i2c_client *client)
+{
+ int ret;
+ struct ags02ma_data *data;
+ struct iio_dev *indio_dev;
+ u32 version;
+
+ indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ crc8_populate_msb(ags02ma_crc8_table, AGS02MA_CRC8_POLYNOMIAL);
+
+ ret = ags02ma_register_read(client, AGS02MA_VERSION_REG,
+ AGS02MA_VERSION_PROCESSING_DELAY);
+ if (ret < 0) {
+ dev_err(&client->dev, "Failed to read device version: %d", ret);
+ return ret;
+ }
+ version = ret;
+ dev_dbg(&client->dev, "Aosong AGS02MA, Version: 0x%x", version);
+
+ data = iio_priv(indio_dev);
+ i2c_set_clientdata(client, indio_dev);
+ data->client = client;
+ indio_dev->info = &ags02ma_info;
+ indio_dev->channels = ags02ma_channels;
+ indio_dev->num_channels = ARRAY_SIZE(ags02ma_channels);
+ indio_dev->name = AGS02MA_DEVICE_NAME;
+
+ return devm_iio_device_register(&client->dev, indio_dev);
+}
+
+static const struct i2c_device_id ags02ma_id_table[] = {
+ { AGS02MA_DEVICE_NAME, 0 },
+ { /* Sentinel */ }
+};
+MODULE_DEVICE_TABLE(i2c, ags02ma_id_table);
+
+static const struct of_device_id ags02ma_of_table[] = {
+ { .compatible = "aosong,ags02ma"},
+ { /* Sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, ags02ma_of_table);
+
+static struct i2c_driver ags02ma_driver = {
+ .driver = {
+ .name = AGS02MA_DEVICE_NAME,
+ .of_match_table = of_match_ptr(ags02ma_of_table),
+ },
+ .id_table = ags02ma_id_table,
+ .probe = ags02ma_probe,
+};
+module_i2c_driver(ags02ma_driver);
+
+MODULE_AUTHOR("Anshul Dalal <[email protected]>");
+MODULE_DESCRIPTION("Aosong AGS02MA TVOC Driver");
+MODULE_LICENSE("GPL");
--
2.42.1

2023-11-21 10:03:09

by Krzysztof Kozlowski

[permalink] [raw]
Subject: Re: [PATCH v3 1/3] dt-bindings: vendor-prefixes: add aosong

On 21/11/2023 10:57, Anshul Dalal wrote:
> Aosong Electronic Co., LTD. is a supplier for MEMS sensors such as AHT20
> temperature and humidity sensor under the brand name Asair
>
> Signed-off-by: Anshul Dalal <[email protected]>
> ---
>


Acked-by: Krzysztof Kozlowski <[email protected]>

Best regards,
Krzysztof

2023-11-24 07:58:47

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH v3 3/3] iio: chemical: add support for Aosong AGS02MA

Hi Anshul,

kernel test robot noticed the following build warnings:

[auto build test WARNING on jic23-iio/togreg]
[also build test WARNING on linus/master v6.7-rc2 next-20231124]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url: https://github.com/intel-lab-lkp/linux/commits/Anshul-Dalal/dt-bindings-iio-chemical-add-aosong-ags02ma/20231121-180435
base: https://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio.git togreg
patch link: https://lore.kernel.org/r/20231121095800.2180870-3-anshulusr%40gmail.com
patch subject: [PATCH v3 3/3] iio: chemical: add support for Aosong AGS02MA
config: s390-randconfig-r081-20231123 (https://download.01.org/0day-ci/archive/20231124/[email protected]/config)
compiler: clang version 17.0.0 (https://github.com/llvm/llvm-project.git 4a5ac14ee968ff0ad5d2cc1ffa0299048db4c88a)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20231124/[email protected]/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 <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/

All warnings (new ones prefixed by >>):

>> drivers/iio/chemical/ags02ma.c:150:34: warning: unused variable 'ags02ma_of_table' [-Wunused-const-variable]
150 | static const struct of_device_id ags02ma_of_table[] = {
| ^
1 warning generated.


vim +/ags02ma_of_table +150 drivers/iio/chemical/ags02ma.c

149
> 150 static const struct of_device_id ags02ma_of_table[] = {
151 { .compatible = "aosong,ags02ma"},
152 { /* Sentinel */ }
153 };
154 MODULE_DEVICE_TABLE(of, ags02ma_of_table);
155

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

2023-11-25 09:10:36

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH v3 3/3] iio: chemical: add support for Aosong AGS02MA

Hi Anshul,

kernel test robot noticed the following build warnings:

[auto build test WARNING on jic23-iio/togreg]
[also build test WARNING on linus/master v6.7-rc2 next-20231124]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url: https://github.com/intel-lab-lkp/linux/commits/Anshul-Dalal/dt-bindings-iio-chemical-add-aosong-ags02ma/20231121-180435
base: https://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio.git togreg
patch link: https://lore.kernel.org/r/20231121095800.2180870-3-anshulusr%40gmail.com
patch subject: [PATCH v3 3/3] iio: chemical: add support for Aosong AGS02MA
config: arm-randconfig-r081-20231123 (https://download.01.org/0day-ci/archive/20231125/[email protected]/config)
compiler: arm-linux-gnueabi-gcc (GCC) 13.2.0
reproduce: (https://download.01.org/0day-ci/archive/20231125/[email protected]/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 <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/

New smatch warnings:
drivers/iio/chemical/ags02ma.c:53 ags02ma_register_read() warn: unsigned 'ret' is never less than zero.

Old smatch warnings:
drivers/iio/chemical/ags02ma.c:63 ags02ma_register_read() warn: unsigned 'ret' is never less than zero.

vim +/ret +53 drivers/iio/chemical/ags02ma.c

45
46 static u32 ags02ma_register_read(struct i2c_client *client, u8 reg, u16 delay)
47 {
48 u32 ret;
49 u8 crc;
50 struct ags02ma_reading read_buffer;
51
52 ret = i2c_master_send(client, &reg, sizeof(reg));
> 53 if (ret < 0) {
54 dev_err(&client->dev,
55 "Failed to send data to register 0x%x: %d", reg, ret);
56 return ret;
57 }
58
59 /* Processing Delay, Check Table 7.7 in the datasheet */
60 msleep_interruptible(delay);
61
62 ret = i2c_master_recv(client, (u8 *)&read_buffer, sizeof(read_buffer));
63 if (ret < 0) {
64 dev_err(&client->dev,
65 "Failed to receive from register 0x%x: %d", reg, ret);
66 return ret;
67 }
68 ret = be32_to_cpu(read_buffer.data);
69
70 crc = crc8(ags02ma_crc8_table, (u8 *)&read_buffer.data,
71 sizeof(read_buffer.data), AGS02MA_CRC8_INIT);
72 if (crc != read_buffer.crc) {
73 dev_err(&client->dev, "CRC error\n");
74 return -EIO;
75 }
76
77 return ret;
78 }
79

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