Skip to contentSkip to conversation

Add support for AS7343 multi-spectral sensor

PATCH Superseded Chang Yu 5 participants 12 messages Sep 19 – Oct 11

Subsystems (2)

v5 of 7 Superseded Latest is v7 →

lore
Share & tools
lore

Chang Yu

author
#0 lore raw

v5 cover Add support for AS7343 multi-spectral sensor

This series adds initial support for the AMS AS7343 14-channel multi-spectral sensor.

The sensor has 14 optical channels (11 visible + NIR + clear + flicker) in total. This initial driver supports reading raw counts from all 12 spectral channels (11 visible + NIR) via sysfs and basic power management.

Not yet supported:
- Configurable integration time and gain
- Interrupt support
- Clear (VIS) channel and flicker detection

Patch 1 adds device tree bindings.
Patch 2 adds the driver.

Testing was performed on a Raspberry Pi 4.

Datasheet: https://look.ams-osram.com/m/5f2d27fff9a874d2/original/AS7343-14-Channel-Multi-Spectral-Sensor.pdf

Changes in v5:
- Remove the GPIO pin from dt bindings.
- Add autosuspend.
- Start measurements before setting up runtime PM.

Changes in v4:
- Fix led-max-microamp property in dt bindings.
- Use REGCACHE_MAPLE and add volatile table.
- Use PM_RUNTIME_ACQUIRE* when resuming.

Changes in v3:
- Fix gpio description and example in dt.
- Only start measurements after suspend action has been registered.
- Add a mutex and pm_runtime_resume_and_get before reading measurements.

Changes in v2:
- Add the LDR, the interrupt pin, and the GPIO pin to the dt bindings.
- Adjust the default gain to x256 and integration time to 50.1ms as recommended by the datasheet.
- Use read_label instead of .extend
- Remove all unused scan_index related constants.

Chang Yu (2):
dt-bindings: iio: light: add as7343
iio: light: add AS7343 multi-spectral sensor driver

 .../bindings/iio/light/ams,as7343.yaml        |  63 +++
 MAINTAINERS                                   |   7 +
 drivers/iio/light/Kconfig                     |  11 +
 drivers/iio/light/Makefile                    |   1 +
 drivers/iio/light/as7343.c                    | 441 ++++++++++++++++++
 5 files changed, 523 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/iio/light/ams,as7343.yaml
 create mode 100644 drivers/iio/light/as7343.c
Signature · 1 line
2.55.0
author
#1 lore raw

PATCH v5 1/2 dt-bindings: iio: light: add as7343

Add binding for AMS AS7343 which is a 14-channel multi-spectral sensor with i2c address of 0x39.

The GPIO pin is not described because the datasheet does not document how to use it for hardware synchronization at all. The GPIO register also has no mode-select bit to isolate the pin from the chip's internal control logic. Exposing it as a generic GPIO could result in kernel writes being overwritten by internal logic.

Datasheet: https://look.ams-osram.com/m/5f2d27fff9a874d2/original/AS7343-14-Channel-Multi-Spectral-Sensor.pdf

---
Changes in v5:
- Remove the GPIO pin.

Changes in v4:
- Fix led-max-microamp property name.

Changes in v3:
- Add missing include for gpio.
- Expand GPIO descrption to include hardware synchronization.
- Use led-max-microamp instead of led-current-microamp for the LDR pin.

Changes in v2:
- Add the LDR, the interrupt pin, and the GPIO pin to the bindings.
- Fix node name and unit address mismatch.
- Include MAINTAINERS changes.

 .../bindings/iio/light/ams,as7343.yaml        | 63 +++++++++++++++++++
 MAINTAINERS                                   |  6 ++
 2 files changed, 69 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/iio/light/ams,as7343.yaml
Documentation/devicetree/bindings/iio/light/ams,as7343.yaml new file +63 -0
new file mode 100644
index 000000000000..cfb15fc551bf
@@ -0,0 +1,63 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/light/ams,as7343.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: AMS AS7343 14-Channel Multi-Spectral Sensor
+
+maintainers:
+  - Chang Yu <[email protected]>
+
+description: |
+  The AMS AS7343 is a 14-channel multi-spectral sensor with i2c address of 0x39.
+  https://look.ams-osram.com/m/5f2d27fff9a874d2/original/AS7343-14-Channel-Multi-Spectral-Sensor.pdf
+
+properties:
+  compatible:
+    enum:
+      - ams,as7343
+
+  reg:
+    description:
+      I2C address of the device (0x39).
+    maxItems: 1
+
+  interrupts:
+    description:
+      Open drain output active low interrupt pin.
+    maxItems: 1
+
+  vdd-supply: true
+
+  led-max-microamp:
+    description:
+      The driver current for the external LED connected to the LDR pin.
+    minimum: 4000
+    maximum: 258000
+    multipleOf: 2000
+    default: 12000
+
+required:
+  - compatible
+  - reg
+  - vdd-supply
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/irq.h>
+
+    i2c {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        multispectral-sensor@39 {
+            compatible = "ams,as7343";
+            reg = <0x39>;
+            interrupts = <7 IRQ_TYPE_LEVEL_LOW>;
+            vdd-supply = <&vdd_regulator>;
+            led-max-microamp = <14000>;
+        };
+    };
MAINTAINERS +6 -0
index 04fa5322d9f7..8cf4e1635053 100644
@@ -1430,6 +1430,12 @@ S:	Maintained
 F:	Documentation/devicetree/bindings/iio/light/ams,as73211.yaml
 F:	drivers/iio/light/as73211.c
 
+AMS AS7343 DRIVER
+M:	Chang Yu <[email protected]>
+L:	[email protected]
+S:	Maintained
+F:	Documentation/devicetree/bindings/iio/light/ams,as7343.yaml
+
 AMT (Automatic Multicast Tunneling)
 M:	Taehee Yoo <[email protected]>
 L:	[email protected]
Signature · 1 line
2.55.0
maintainer
#2 lore raw

Re: [PATCH v5 1/2] dt-bindings: iio: light: add as7343

Quoted 11 lines

Add binding for AMS AS7343 which is a 14-channel multi-spectral sensor with i2c address of 0x39.

The GPIO pin is not described because the datasheet does not document how to use it for hardware synchronization at all. The GPIO register also has no mode-select bit to isolate the pin from the chip's internal control logic. Exposing it as a generic GPIO could result in kernel writes being overwritten by internal logic.

Datasheet: https://look.ams-osram.com/m/5f2d27fff9a874d2/original/AS7343-14-Channel-Multi-Spectral-Sensor.pdf

I've just replied to the earlier discussion about led-max-microamp and $ref. We need that thread to come to a conclusion before we can move forward.

For future referenc it would have been good to capture that discussion as ongoing as part of the change log and cover letter.

Signature · 1 line
Jonathan Cameron <[email protected]>
author
#3 lore raw

PATCH v5 2/2 iio: light: add AS7343 multi-spectral sensor driver

In reply to Chang Yu

Add a driver for the AMS AS7343 14-channel multi-spectral sensor.

The AS7343 is a 14-channel spectral sensor featuring 11 visible channels, 1 near-infrared channel, 1 clear channel (VIS), and 1 flicker detection channel.

The driver exposes 12 spectral channels (11 visible light and 1 near-infrared) via sysfs. Runtime PM is implemented to stop measurements when the device is suspended or torn down. Power is never cut (PON=1 always) to preserve register values.

Future patches will add configurable gain and integration time, interrupt support, buffered reads, VIS channel, and flicker detection.

Datasheet: https://look.ams-osram.com/m/5f2d27fff9a874d2/original/AS7343-14-Channel-Multi-Spectral-Sensor.pdf

---
Changes in v5:
- Add autosuspend support.
- Start measurements before configuring runtime PM.
- Add functions for computing ASTEP and ATIME.
- Sort registers by addresses.

Changes in v4:
- Use REGCACHE_MAPLE and add volatile register table.
- Use PM_RUNTIME_ACQUIRE* when resuming.
- Use a static array for labels.
- Various code style fixes.

Changes in v3:
- Hold a mutex before reading measurements.
- Add pm_runtime_resume_and_get before reading measurements.
- Only start measurements after suspend action has been successfully registered
- Check the return value of regmap_read when verifying device ID.

Changes in v2:
- Adjust the default gain to x256 and integration time to 50.1ms as recommended by the datasheet.
- Use read_label instead of .extend
- Remove all unused scan_index related constants.
- Add missing calls to pm_runtime_* methods in probe.
- Fix various code style issues

 MAINTAINERS                |   1 +
 drivers/iio/light/Kconfig  |  11 +
 drivers/iio/light/Makefile |   1 +
 drivers/iio/light/as7343.c | 441 +++++++++++++++++++++++++++++++++++++
 4 files changed, 454 insertions(+)
 create mode 100644 drivers/iio/light/as7343.c
MAINTAINERS +1 -0
index 8cf4e1635053..236102b3c28e 100644
@@ -1435,6 +1435,7 @@ M:	Chang Yu <[email protected]>
 L:	[email protected]
 S:	Maintained
 F:	Documentation/devicetree/bindings/iio/light/ams,as7343.yaml
+F:	drivers/iio/light/as7343.c
 
 AMT (Automatic Multicast Tunneling)
 M:	Taehee Yoo <[email protected]>
drivers/iio/light/Kconfig +11 -0
index ef36824f312f..edbeeba9d873 100644
@@ -149,6 +149,17 @@ config AS73211
 	 This driver can also be built as a module.  If so, the module
 	 will be called as73211.
 
+config AS7343
+	tristate "AMS AS7343 14-Channel Multi-Spectral Sensor"
+	depends on I2C
+	select REGMAP_I2C
+	help
+	 Say Y here to build support for the AMS AS7343 14-channel
+	 multi-spectral sensor.
+
+	 To compile this driver as a module, choose M here: the module will
+	 be called as7343.
+
 config BH1745
 	tristate "ROHM BH1745 colour sensor"
 	depends on I2C
drivers/iio/light/Makefile +1 -0
index 64e354c49ed8..5d0d33802519 100644
@@ -16,6 +16,7 @@ obj-$(CONFIG_APDS9306)		+= apds9306.o
 obj-$(CONFIG_APDS9960)		+= apds9960.o
 obj-$(CONFIG_APDS9999)		+= apds9999.o
 obj-$(CONFIG_AS73211)		+= as73211.o
+obj-$(CONFIG_AS7343)		+= as7343.o
 obj-$(CONFIG_BH1745)		+= bh1745.o
 obj-$(CONFIG_BH1750)		+= bh1750.o
 obj-$(CONFIG_BH1780)		+= bh1780.o
drivers/iio/light/as7343.c new file +441 -0

441 lines not on this page · raw message

Signature · 1 line
2.55.0
#4 lore raw

Re: [PATCH v5 2/2] iio: light: add AS7343 multi-spectral sensor driver

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: - [Medium] pm: missing PM runtime idle request prevents initial autosuspend --

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] pm: missing PM runtime idle request prevents initial autosuspend --

commit 87cfb69de7e4c2b750859f6540e61d6d9aef5dcd
Author: Chang Yu <[email protected]>

iio: light: add AS7343 multi-spectral sensor driver

Add a driver for the AMS AS7343 14-channel multi-spectral sensor. The driver exposes 12 spectral channels via sysfs and implements runtime PM to manage device power during measurements.

Quoted 5 lines
drivers/iio/light/as7343.c new file +0 -0
new file mode 100644
index 0000000000000..c079e0c6aa704

[ ... ]

Quoted 2 lines
drivers/iio/light/as7343.c new file +2 -0
+static int as7343_probe(struct i2c_client *client)
+{

[ ... ]

drivers/iio/light/as7343.c line 405

Quoted 9 lines
drivers/iio/light/as7343.c new file +9 -0
+	pm_runtime_set_autosuspend_delay(dev, 3000);
+	pm_runtime_use_autosuspend(dev);
+
+	ret = devm_add_action_or_reset(dev, as7343_suspend_action, dev);
+	if (ret)
+		return dev_err_probe(dev, ret,
+				     "Failed to add suspend action\n");
+
+	ret = devm_pm_runtime_set_active_enabled(dev);

[Severity: Medium]
Does enabling PM runtime here without a subsequent idle check (or without calling pm_runtime_use_autosuspend afterwards) leave the device perpetually active?

Since pm_runtime_use_autosuspend(dev) is called earlier, the device's disable_depth is still greater than 0 at that point. This causes the internal idle check to fail with -EACCES, preventing the autosuspend timer from being queued.

When devm_pm_runtime_set_active_enabled() later enables PM runtime, it does not implicitly trigger an idle check. This might strand the device in the active state until user space initiates a read to kick off a get and put_autosuspend cycle.

Quoted 6 lines
drivers/iio/light/as7343.c new file +6 -0
+	if (ret)
+		return dev_err_probe(dev, ret,
+				     "Failed to activate PM runtime\n");
+
+	return devm_iio_device_register(dev, indio_dev);
+}
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=2
maintainer
#5 lore raw

Re: [PATCH v5 2/2] iio: light: add AS7343 multi-spectral sensor driver

In reply to Chang Yu
Quoted 11 lines

Add a driver for the AMS AS7343 14-channel multi-spectral sensor.

The AS7343 is a 14-channel spectral sensor featuring 11 visible channels, 1 near-infrared channel, 1 clear channel (VIS), and 1 flicker detection channel.

The driver exposes 12 spectral channels (11 visible light and 1 near-infrared) via sysfs. Runtime PM is implemented to stop measurements when the device is suspended or torn down. Power is never cut (PON=1 always) to preserve register values.

Quoted 6 lines

Future patches will add configurable gain and integration time, interrupt support, buffered reads, VIS channel, and flicker detection.

Datasheet: https://look.ams-osram.com/m/5f2d27fff9a874d2/original/AS7343-14-Channel-Multi-Spectral-Sensor.pdf

FWIW I believe the sashiko feedback autosuspend is incorrect, but probably good to sanity check that by proving device and just checking the calls in dd.c are sufficient to put it to sleep after the auto suspend time.

Sashiko generally seems not to spot that probe is special in this regard. Probably doesn't help that there are quite a few drivers that do have the handling it suggests, presumably because humans didn't know it was special either ;)

A couple of follow up comments inline. This is coming together nicely so I think we are down to tiny details now.

Jonathan

Quoted 42 lines
MAINTAINERS +1 -0
index f0c08e634bf4..9496280903d9 100644
@@ -1460,6 +1460,7 @@ M:	Chang Yu <[email protected]>
 L:	[email protected]
 S:	Maintained
 F:	Documentation/devicetree/bindings/iio/light/ams,as7343.yaml
+F:	drivers/iio/light/as7343.c
 
 AMT (Automatic Multicast Tunneling)
 M:	Taehee Yoo <[email protected]>
drivers/iio/light/Kconfig +11 -0
index 462fff1ddef2..d0dea4f3113b 100644
@@ -152,6 +152,17 @@ config AS73211
 	 This driver can also be built as a module.  If so, the module
 	 will be called as73211.
 
+config AS7343
+	tristate "AMS AS7343 14-Channel Multi-Spectral Sensor"
+	depends on I2C
+	select REGMAP_I2C
+	help
+	 Say Y here to build support for the AMS AS7343 14-channel
+	 multi-spectral sensor.
+
+	 To compile this driver as a module, choose M here: the module will
+	 be called as7343.
+
 config BH1745
 	tristate "ROHM BH1745 colour sensor"
 	depends on I2C
drivers/iio/light/as7343.c new file +0 -0
new file mode 100644
index 000000000000..c079e0c6aa70
 

drivers/iio/light/as7343.c line 139

Quoted 10 lines
drivers/iio/light/as7343.c new file +9 -0
 
+
+/*
+ * Integration time is calculated as (ATIME + 1) * ((ASTEP + 1) * 2.78us).
+ * ATIME must be between 0 and 255, inclusive
+ * ASTEP must be between 0 and 65534, inclusive
+ */
+static inline u8 as7343_atime_steps(unsigned int step)
+{
+	BUILD_BUG_ON(step < 1 || step > 256);

Whilst for now this is fine as you aren't making these controllable, I would make them runtime checks just to make a future change to make these userspce adjustable easier to make.

That will complicate the code a little but give less churn in the longer term.

drivers/iio/light/as7343.c line 145

Quoted 6 lines
drivers/iio/light/as7343.c new file +6 -0
+	return step - 1;
+}
+
+static inline u16 as7343_astep_x2780ns(unsigned int n)
+{
+	BUILD_BUG_ON(n < 1 || n > 65535);

Same here.

Quoted 3 lines
drivers/iio/light/as7343.c new file +3 -0
+	return n - 1;
+}
+

...

drivers/iio/light/as7343.c line 283

Quoted 9 lines
drivers/iio/light/as7343.c new file +9 -0
+static int as7343_setup_device(struct device *dev, struct as7343_data *data)
+{
+	struct regmap *map = data->regmap;
+	unsigned int val;
+	__le16 step;
+	int ret;
+
+	/* Power on */
+	ret = regmap_set_bits(map, AS7343_ENABLE_REG, AS7343_ENABLE_PON);

If the regulators are fixed supplies and as such we haven't just turned the power on here and device hasn't just taken default values, could the previously driver / firmware / whatever have left us using bank 1. If so would that power on call do anything?

It's common to have a few control registers on a device accessible from every bank, but that doesn't seem to be the case here. Though given it won't work otherwise, I'm assuming it is the case for CFG0 despite it being at an address of greater than 0x80!
As such expect to see first call being one to get the device using bank 0.

Quoted 45 lines
drivers/iio/light/as7343.c new file +45 -0
+	if (ret)
+		return ret;
+
+	/* Need to set REG_BANK to 1 before we can access ID */
+	ret = regmap_update_bits(map, AS7343_CFG0_REG, AS7343_CFG0_REG_BANK,
+				 FIELD_PREP(AS7343_CFG0_REG_BANK, 1));
+	if (ret)
+		return ret;
+
+	ret = regmap_read(map, AS7343_ID, &val);
+	if (ret)
+		return ret;
+
+	if (val != 0x81)
+		dev_info(dev, "Unknown device ID: %x\n", val);
+
+	ret = regmap_update_bits(map, AS7343_CFG0_REG, AS7343_CFG0_REG_BANK,
+				 FIELD_PREP(AS7343_CFG0_REG_BANK, 0));
+	if (ret)
+		return ret;
+
+	/* Configure the SMUX to readout all channels */
+	ret = regmap_update_bits(map, AS7343_CFG20_REG, AS7343_CFG20_AUTO_SMUX,
+				 FIELD_PREP(AS7343_CFG20_AUTO_SMUX,
+					    AS7343_CFG20_AUTO_SMUX_READOUT_ALL));
+	if (ret)
+		return ret;
+
+	/*
+	 * Setting a 600 * 2.78us * 30 = 50ms integration time as the default
+	 * for now.
+	 */
+	step = cpu_to_le16(as7343_astep_x2780ns(600));
+	ret = regmap_bulk_write(map, AS7343_ASTEP_REG, &step, sizeof(step));
+	if (ret)
+		return ret;
+
+	ret = regmap_write(map, AS7343_ATIME_REG, as7343_atime_steps(30));
+	if (ret)
+		return ret;
+
+	return regmap_update_bits(map, AS7343_CFG1_REG, AS7343_CFG1_AGAIN,
+				  FIELD_PREP(AS7343_CFG1_AGAIN,
+					     AS7343_CFG1_AGAIN_X256));
+}

...

Quoted 38 lines
drivers/iio/light/as7343.c new file +38 -0
+static int as7343_probe(struct i2c_client *client)
+{
+	struct device *dev = &client->dev;
+	struct iio_dev *indio_dev;
+	struct as7343_data *data;
+	struct regmap *regmap;
+	int ret;
+
+	indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
+	if (!indio_dev)
+		return -ENOMEM;
+
+	i2c_set_clientdata(client, indio_dev);
+
+	regmap = devm_regmap_init_i2c(client, &as7343_regmap_config);
+	if (IS_ERR(regmap))
+		return PTR_ERR(regmap);
+
+	data = iio_priv(indio_dev);
+	data->regmap = regmap;
+
+	ret = devm_mutex_init(dev, &data->mutex);
+	if (ret)
+		return ret;
+
+	indio_dev->name = "as7343";
+	indio_dev->info = &as7343_info;
+	indio_dev->channels = as7343_channels;
+	indio_dev->num_channels = ARRAY_SIZE(as7343_channels);
+	indio_dev->modes = INDIO_DIRECT_MODE;
+
+	ret = devm_regulator_get_enable(dev, "vdd");
+	if (ret)
+		return ret;
+
+	ret = as7343_setup_device(dev, data);
+	if (ret)
+		return ret;

drivers/iio/light/as7343.c line 400

Quoted 10 lines
drivers/iio/light/as7343.c new file +10 -0
+
+	/* Start measurements */
+	ret = regmap_set_bits(regmap, AS7343_ENABLE_REG, AS7343_ENABLE_SP_EN);
+	if (ret)
+		return ret;
+
+	pm_runtime_set_autosuspend_delay(dev, 3000);
+	pm_runtime_use_autosuspend(dev);
+
+	ret = devm_add_action_or_reset(dev, as7343_suspend_action, dev);

Why here? Neither of the two calls immediately above have anything to do with what this is unwinding? I think this should logically be before the pm_runtime_set_autosuspend_delay() call so that is is clearly matched with the regmap one above that.

Signature · 1 line
Jonathan Cameron <[email protected]>
author
#6 lore raw

Re: [PATCH v5 2/2] iio: light: add AS7343 multi-spectral sensor driver

Quoted 15 lines · Jonathan Cameron
Quoted 15 lines

Add a driver for the AMS AS7343 14-channel multi-spectral sensor.

The AS7343 is a 14-channel spectral sensor featuring 11 visible channels, 1 near-infrared channel, 1 clear channel (VIS), and 1 flicker detection channel.

The driver exposes 12 spectral channels (11 visible light and 1 near-infrared) via sysfs. Runtime PM is implemented to stop measurements when the device is suspended or torn down. Power is never cut (PON=1 always) to preserve register values.

Future patches will add configurable gain and integration time, interrupt support, buffered reads, VIS channel, and flicker detection.

Quoted 8 lines
Quoted 2 lines

Datasheet: https://look.ams-osram.com/m/5f2d27fff9a874d2/original/AS7343-14-Channel-Multi-Spectral-Sensor.pdf

FWIW I believe the sashiko feedback autosuspend is incorrect, but probably good to sanity check that by proving device and just checking the calls in dd.c are sufficient to put it to sleep after the auto suspend time.

Yep. Did a quick test on hardware. Autosuspend kicks in correctly without any user space initiated reads.

#7 lore raw

Re: [PATCH v5 2/2] iio: light: add AS7343 multi-spectral sensor driver

In reply to Chang Yu
Quoted 14 lines · Chang Yu

Add a driver for the AMS AS7343 14-channel multi-spectral sensor.

The AS7343 is a 14-channel spectral sensor featuring 11 visible channels, 1 near-infrared channel, 1 clear channel (VIS), and 1 flicker detection channel.

The driver exposes 12 spectral channels (11 visible light and 1 near-infrared) via sysfs. Runtime PM is implemented to stop measurements when the device is suspended or torn down. Power is never cut (PON=1 always) to preserve register values.

Future patches will add configurable gain and integration time, interrupt support, buffered reads, VIS channel, and flicker detection.

...

Quoted 1 line

+#include <linux/build_bug.h>

This is unusual to meet...

...

drivers/iio/light/as7343.c line 139

Quoted 3 lines
drivers/iio/light/as7343.c new file +3 -0
+static inline u8 as7343_atime_steps(unsigned int step)
+{
+	BUILD_BUG_ON(step < 1 || step > 256);

How is this any useful? The step == 1 gives the result 0, the step 256, 255 respectively. This covers the whole range of the returned variable (u8).

drivers/iio/light/as7343.c line 147

Quoted 8 lines
drivers/iio/light/as7343.c new file +8 -0
+	return step - 1;
+}
+
+static inline u16 as7343_astep_x2780ns(unsigned int n)
+{
+	BUILD_BUG_ON(n < 1 || n > 65535);
+	return n - 1;
+}

Ditto.

...

TL;DR: I do not see anything meaningful from these BUILD_BUG_ON():s. It's not a problem if the result gives just wrapped-up value. Or is it?

...

drivers/iio/light/as7343.c line 237

Quoted 4 lines
drivers/iio/light/as7343.c new file +4 -0
+static int as7343_read_label(struct iio_dev *indio_dev,
+			     struct iio_chan_spec const *chan, char *label)
+{
+	int channel = chan->channel;

Why signed?
Also split assignment, it will make code more maintainable.

Quoted 5 lines
drivers/iio/light/as7343.c new file +5 -0
+	if (channel < 0 || channel >= ARRAY_SIZE(as7343_channel_labels))
+		return -EINVAL;
+
+	return sysfs_emit(label, "%s\n", as7343_channel_labels[channel]);
+}
Signature · 2 lines
With Best Regards,
Andy Shevchenko
author
#8 lore raw

Re: [PATCH v5 2/2] iio: light: add AS7343 multi-spectral sensor driver

Quoted 43 lines · Andy Shevchenko
Quoted 14 lines · Chang Yu

Add a driver for the AMS AS7343 14-channel multi-spectral sensor.

The AS7343 is a 14-channel spectral sensor featuring 11 visible channels, 1 near-infrared channel, 1 clear channel (VIS), and 1 flicker detection channel.

The driver exposes 12 spectral channels (11 visible light and 1 near-infrared) via sysfs. Runtime PM is implemented to stop measurements when the device is suspended or torn down. Power is never cut (PON=1 always) to preserve register values.

Future patches will add configurable gain and integration time, interrupt support, buffered reads, VIS channel, and flicker detection.

...

Quoted 1 line

+#include <linux/build_bug.h>

This is unusual to meet...

...

drivers/iio/light/as7343.c line 139

Quoted 3 lines
drivers/iio/light/as7343.c new file +3 -0
+static inline u8 as7343_atime_steps(unsigned int step)
+{
+   BUILD_BUG_ON(step < 1 || step > 256);

How is this any useful? The step == 1 gives the result 0, the step 256, 255 respectively. This covers the whole range of the returned variable (u8).

drivers/iio/light/as7343.c line 147

Quoted 8 lines
drivers/iio/light/as7343.c new file +8 -0
+   return step - 1;
+}
+
+static inline u16 as7343_astep_x2780ns(unsigned int n)
+{
+   BUILD_BUG_ON(n < 1 || n > 65535);
+   return n - 1;
+}

Ditto.

Quoted 5 lines

...

TL;DR: I do not see anything meaningful from these BUILD_BUG_ON():s. It's not a problem if the result gives just wrapped-up value. Or is it?

For now just letting them wrap back up is fine. The values are hard coded so it's unlikely to happen anyways. But since these are going to be configurable by the user in the future, I'll make these into runtime checks as per Jonathan's advice so that we have a way to tell the user that they are doing something wrong.

author
#9 lore raw

Re: [PATCH v5 2/2] iio: light: add AS7343 multi-spectral sensor driver

In reply to Andy Shevchenko
Quoted 9 lines · Andy Shevchenko

drivers/iio/light/as7343.c line 237

Quoted 4 lines · Chang Yu
drivers/iio/light/as7343.c new file +4 -0
+static int as7343_read_label(struct iio_dev *indio_dev,
+			     struct iio_chan_spec const *chan, char *label)
+{
+	int channel = chan->channel;

Why signed?
Also split assignment, it will make code more maintainable.

I believe this was mentioned in a previous thread. Basically because iio_chan_spec.channel is an int, so I had to make the local var signed to keep it consistent. Why iio_chan_spec.channel is an int is a mystery to me unfortunately.

#10 lore raw

Re: [PATCH v5 2/2] iio: light: add AS7343 multi-spectral sensor driver

In reply to Chang Yu
Quoted 10 lines · Chang Yu
drivers/iio/light/as7343.c new file +10 -0
+static int as7343_read_raw(struct iio_dev *indio_dev,
+			   struct iio_chan_spec const *chan,
+			   int *val, int *val2, long mask)
+{
+	struct as7343_data *data = iio_priv(indio_dev);
+	struct regmap *map = data->regmap;
+	struct device *dev = regmap_get_device(map);
+	unsigned int unused;
+	__le16 result;
+	int ret;

drivers/iio/light/as7343.c line 174

Quoted 10 lines
drivers/iio/light/as7343.c new file +10 -0
+
+	PM_RUNTIME_ACQUIRE_AUTOSUSPEND(dev, pm);
+	ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
+	if (ret)
+		return ret;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW: {
+		/* Wait until integration time passes for all 3 cycles. */
+		msleep(160);

three integration periods hardcoded next to a hardcoded integration time, so nothing keeps them in sync. make ATIME/ASTEP writable and the fixed wait no longer covers a readout. as73211, which this is based on, computes the timeout and polls NDATA. STATUS2 (0x90) bit 6 is AVALID is defined and never read, does it cover all three cycles? the datasheet does not say.

Quoted 15 lines
drivers/iio/light/as7343.c new file +15 -0
+
+		/*
+		 * Reading ASTATUS latches all data registers to this read.
+		 * We don't care about the returned saturation/gain status for
+		 * now.
+		 */
+		guard(mutex)(&data->mutex);
+
+		ret = regmap_read(map, AS7343_ASTATUS_REG, &unused);
+		if (ret)
+			return ret;
+
+		ret = regmap_bulk_read(map, chan->address,
+				       &result, sizeof(result));
+		if (ret)

drivers/iio/light/as7343.c line 199

Quoted 10 lines
drivers/iio/light/as7343.c new file +10 -0
+			return ret;
+
+		*val = le16_to_cpu(result);
+		return IIO_VAL_INT;
+	}
+
+	default:
+		return -EINVAL;
+	}
+}

--
cheers, jose a. p-a

author
#11 lore raw

Re: [PATCH v5 2/2] iio: light: add AS7343 multi-spectral sensor driver

Quoted 20 lines · Jose A. Perez de Azpillaga
Quoted 19 lines · Chang Yu
drivers/iio/light/as7343.c new file +19 -0
+static int as7343_read_raw(struct iio_dev *indio_dev,
+			   struct iio_chan_spec const *chan,
+			   int *val, int *val2, long mask)
+{
+	struct as7343_data *data = iio_priv(indio_dev);
+	struct regmap *map = data->regmap;
+	struct device *dev = regmap_get_device(map);
+	unsigned int unused;
+	__le16 result;
+	int ret;
+
+	PM_RUNTIME_ACQUIRE_AUTOSUSPEND(dev, pm);
+	ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
+	if (ret)
+		return ret;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW: {
+		/* Wait until integration time passes for all 3 cycles. */
Quoted 9 lines

drivers/iio/light/as7343.c line 174

Quoted 1 line
drivers/iio/light/as7343.c new file +1 -0
+		msleep(160);

three integration periods hardcoded next to a hardcoded integration time, so nothing keeps them in sync. make ATIME/ASTEP writable and the fixed wait no longer covers a readout. as73211, which this is based on, computes the timeout and polls NDATA. STATUS2 (0x90) bit 6 is AVALID is defined and never read, does it cover all three cycles? the datasheet does not say.

Configurable ATIME/ASTEP will be added in future patches since I want to keep the initial driver lean. I'll switch to dynamically computing wait time in those patches. For now I'm inclined to leave the value hardcoded just to keep things simple.

The documentation on AVALID is indeed pretty poorly worded and unclear. I'll test on hardware when I have time and see if it covers all three. I think it's fine even if AVALID turns out to be unreliable? Worst case scenario the userspace reads a stale value, which is OK for my use case at least.