Skip to contentSkip to conversation

Add support for AD7091R-2/-4/-8

PATCH Superseded Marcelo Schmitt 4 participants 17 messages Nov 23, 2023 – Nov 27, 2023

Subsystems (4)

v2 of 5 Superseded Latest is v5 →

lore
Share & tools
lore

Marcelo Schmitt

author maintainer
#0 lore raw

v2 cover Add support for AD7091R-2/-4/-8

From: Marcelo Schmitt <[email protected]>

This series adds support for AD7091R-2/-4/-8 ADCs which can do single shot or sequenced readings. Threshold events are also supported.
Overall, AD7091R-2/-4/-8 are very similar to AD7091R-5 except they use SPI interface.

This has been tested with raspberrypi and eval board on kernel 6.1 from ADI fork.

I ran get_maintainers on driver files but completely forgot to run it on the yaml doc, my bad.
I made the changes requested so far.
For v2, I also ran dt_binding_check on iio testing branch to check out for any additional dt-schema issues. None reported.
Didn't see any other warn after running Sparse, Smatch, and Coccicheck. I get a warn from checkpatch about IIO_DMA_MINALIGN which I don't know how to fix :(

Change log v1 -> v2:
- Added device tree related To/Cc recipients.
- Removed extra print of error code
- $ref: "adc.yaml" -> $ref: adc.yaml
- Fixed defined but not used build warn
- Moved dt documentation of required properties to after patternProperties.
- Removed incorrect return before regmap_update_bits().

Marcelo Schmitt (7):
iio: adc: ad7091r-base: Set alert config and drvdata
MAINTAINERS: Add MAINTAINERS entry for AD7091R
iio: adc: ad7091r: Move defines to header file
iio: adc: ad7091r: Alloc IIO device before generic probe
dt-bindings: iio: Add binding documentation for AD7091R-8
iio: adc: Add support for AD7091R-8
iio: adc: ad7091r-base: Add debugfs reg access

 .../bindings/iio/adc/adi,ad7091r8.yaml        | 101 +++++++
 MAINTAINERS                                   |  12 +
 drivers/iio/adc/Kconfig                       |  16 ++
 drivers/iio/adc/Makefile                      |   4 +-
 drivers/iio/adc/ad7091r-base.c                | 114 +++++---
 drivers/iio/adc/ad7091r-base.h                |  64 ++++-
 drivers/iio/adc/ad7091r5.c                    |  55 ++--
 drivers/iio/adc/ad7091r8.c                    | 270 ++++++++++++++++++
 8 files changed, 549 insertions(+), 87 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/iio/adc/adi,ad7091r8.yaml
 create mode 100644 drivers/iio/adc/ad7091r8.c
Signature · 1 line
2.42.0
author maintainer
#1 lore raw

PATCH v2 1/7 iio: adc: ad7091r-base: Set alert config and drvdata

Write 1 to bit 4 in the configuration register to set ALERT/BUSY/GPO pin to be used as ALERT.
Set device driver data so it can be retrieved when handling alert events, avoiding null pointer dereference.

Fixes <ca69300173b6> (iio: adc: Add support for AD7091R5 ADC)
---
 drivers/iio/adc/ad7091r-base.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)
drivers/iio/adc/ad7091r-base.c +10 -2
index 8e252cde735b..3ecac3164446 100644
@@ -28,6 +28,7 @@
 #define AD7091R_REG_RESULT_CONV_RESULT(x)   ((x) & 0xfff)
 
 /* AD7091R_REG_CONF */
+#define AD7091R_REG_CONF_ALERT_EN   BIT(4)
 #define AD7091R_REG_CONF_AUTO   BIT(8)
 #define AD7091R_REG_CONF_CMD    BIT(10)
 
@@ -232,9 +233,16 @@ int ad7091r_probe(struct device *dev, const char *name,
 	iio_dev->channels = chip_info->channels;
 
 	if (irq) {
+		ret = regmap_update_bits(st->map, AD7091R_REG_CONF,
+					 AD7091R_REG_CONF_ALERT_EN, BIT(4));
+		if (ret)
+			return ret;
+
+		dev_set_drvdata(st->dev, iio_dev);
 		ret = devm_request_threaded_irq(dev, irq, NULL,
-				ad7091r_event_handler,
-				IRQF_TRIGGER_FALLING | IRQF_ONESHOT, name, st);
+						ad7091r_event_handler,
+						IRQF_TRIGGER_FALLING |
+						IRQF_ONESHOT, name, st);
 		if (ret)
 			return ret;
 	}
Signature · 1 line
2.42.0
author maintainer
#3 lore raw

PATCH v2 2/7 MAINTAINERS: Add MAINTAINERS entry for AD7091R

In reply to Marcelo Schmitt

The driver for AD7091R was added in
ca693001: iio: adc: Add support for AD7091R5 ADC but no MAINTAINERS file entry was added for it since then. Add a proper MAINTAINERS file entry for the AD7091R driver.

---
 MAINTAINERS | 10 ++++++++++
 1 file changed, 10 insertions(+)
MAINTAINERS +10 -0
index 8e0a91dc8251..008f0e73bead 100644
@@ -1126,6 +1126,16 @@ F:	Documentation/ABI/testing/sysfs-bus-iio-adc-ad4130
 F:	Documentation/devicetree/bindings/iio/adc/adi,ad4130.yaml
 F:	drivers/iio/adc/ad4130.c
 
+ANALOG DEVICES INC AD7091R DRIVER
+M:	Marcelo Schmitt <[email protected]>
+L:	[email protected]
+S:	Supported
+W:	http://ez.analog.com/community/linux-device-drivers
+F:	Documentation/devicetree/bindings/iio/adc/adi,ad7091r5.yaml
+F:	drivers/iio/adc/drivers/iio/adc/ad7091r-base.c
+F:	drivers/iio/adc/drivers/iio/adc/ad7091r-base.h
+F:	drivers/iio/adc/drivers/iio/adc/ad7091r5.c
+
 ANALOG DEVICES INC AD7192 DRIVER
 M:	Alexandru Tachici <[email protected]>
 L:	[email protected]
Signature · 1 line
2.42.0
author maintainer
#5 lore raw

PATCH v2 3/7 iio: adc: ad7091r: Move defines to header file

In reply to Marcelo Schmitt

Move AD7091R register, channel and event definitions to the header file so other AD7091R device drivers may use those declaration in follow up patches.

---
 drivers/iio/adc/ad7091r-base.c | 35 +++++++++++++++++++++---------
 drivers/iio/adc/ad7091r-base.h | 27 +++++++++++++++++++++++
 drivers/iio/adc/ad7091r5.c     | 39 ++++------------------------------
 3 files changed, 56 insertions(+), 45 deletions(-)
drivers/iio/adc/ad7091r-base.c +25 -10
index 3ecac3164446..1d84a57720ca 100644
@@ -15,14 +15,6 @@
 
 #include "ad7091r-base.h"
 
-#define AD7091R_REG_RESULT  0
-#define AD7091R_REG_CHANNEL 1
-#define AD7091R_REG_CONF    2
-#define AD7091R_REG_ALERT   3
-#define AD7091R_REG_CH_LOW_LIMIT(ch) ((ch) * 3 + 4)
-#define AD7091R_REG_CH_HIGH_LIMIT(ch) ((ch) * 3 + 5)
-#define AD7091R_REG_CH_HYSTERESIS(ch) ((ch) * 3 + 6)
-
 /* AD7091R_REG_RESULT */
 #define AD7091R_REG_RESULT_CH_ID(x)	    (((x) >> 13) & 0x3)
 #define AD7091R_REG_RESULT_CONV_RESULT(x)   ((x) & 0xfff)
@@ -50,6 +42,27 @@ struct ad7091r_state {
 	struct mutex lock; /*lock to prevent concurent reads */
 };
 
+const struct iio_event_spec ad7091r_events[] = {
+	{
+		.type = IIO_EV_TYPE_THRESH,
+		.dir = IIO_EV_DIR_RISING,
+		.mask_separate = BIT(IIO_EV_INFO_VALUE) |
+				 BIT(IIO_EV_INFO_ENABLE),
+	},
+	{
+		.type = IIO_EV_TYPE_THRESH,
+		.dir = IIO_EV_DIR_FALLING,
+		.mask_separate = BIT(IIO_EV_INFO_VALUE) |
+				 BIT(IIO_EV_INFO_ENABLE),
+	},
+	{
+		.type = IIO_EV_TYPE_THRESH,
+		.dir = IIO_EV_DIR_EITHER,
+		.mask_separate = BIT(IIO_EV_INFO_HYSTERESIS),
+	},
+};
+EXPORT_SYMBOL_NS_GPL(ad7091r_events, IIO_AD7091R);
+
 static int ad7091r_set_mode(struct ad7091r_state *st, enum ad7091r_mode mode)
 {
 	int ret, conf;
@@ -270,7 +283,7 @@ int ad7091r_probe(struct device *dev, const char *name,
 }
 EXPORT_SYMBOL_NS_GPL(ad7091r_probe, IIO_AD7091R);
 
-static bool ad7091r_writeable_reg(struct device *dev, unsigned int reg)
+bool ad7091r_writeable_reg(struct device *dev, unsigned int reg)
 {
 	switch (reg) {
 	case AD7091R_REG_RESULT:
@@ -280,8 +293,9 @@ static bool ad7091r_writeable_reg(struct device *dev, unsigned int reg)
 		return true;
 	}
 }
+EXPORT_SYMBOL_NS_GPL(ad7091r_writeable_reg, IIO_AD7091R);
 
-static bool ad7091r_volatile_reg(struct device *dev, unsigned int reg)
+bool ad7091r_volatile_reg(struct device *dev, unsigned int reg)
 {
 	switch (reg) {
 	case AD7091R_REG_RESULT:
@@ -291,6 +305,7 @@ static bool ad7091r_volatile_reg(struct device *dev, unsigned int reg)
 		return false;
 	}
 }
+EXPORT_SYMBOL_NS_GPL(ad7091r_volatile_reg, IIO_AD7091R);
 
 const struct regmap_config ad7091r_regmap_config = {
 	.reg_bits = 8,
drivers/iio/adc/ad7091r-base.h +27 -0
index 509748aef9b1..6ff539cd1d39 100644
@@ -8,6 +8,27 @@
 #ifndef __DRIVERS_IIO_ADC_AD7091R_BASE_H__
 #define __DRIVERS_IIO_ADC_AD7091R_BASE_H__
 
+#define AD7091R_REG_RESULT  0
+#define AD7091R_REG_CHANNEL 1
+#define AD7091R_REG_CONF    2
+#define AD7091R_REG_ALERT   3
+
+#define AD7091R_REG_CH_LOW_LIMIT(ch) ((ch) * 3 + 4)
+#define AD7091R_REG_CH_HIGH_LIMIT(ch) ((ch) * 3 + 5)
+#define AD7091R_REG_CH_HYSTERESIS(ch) ((ch) * 3 + 6)
+
+#define AD7091R_CHANNEL(idx, bits, ev, num_ev) {			\
+	.type = IIO_VOLTAGE,						\
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),			\
+	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),		\
+	.indexed = 1,							\
+	.channel = idx,							\
+	.event_spec = ev,						\
+	.num_event_specs = num_ev,					\
+	.scan_type.storagebits = 16,					\
+	.scan_type.realbits = bits,					\
+}
+
 struct device;
 struct ad7091r_state;
 
@@ -17,10 +38,16 @@ struct ad7091r_chip_info {
 	unsigned int vref_mV;
 };
 
+extern const struct iio_event_spec ad7091r_events[3];
+
 extern const struct regmap_config ad7091r_regmap_config;
 
 int ad7091r_probe(struct device *dev, const char *name,
 		const struct ad7091r_chip_info *chip_info,
 		struct regmap *map, int irq);
 
+bool ad7091r_volatile_reg(struct device *dev, unsigned int reg);
+
+bool ad7091r_writeable_reg(struct device *dev, unsigned int reg);
+
 #endif /* __DRIVERS_IIO_ADC_AD7091R_BASE_H__ */
drivers/iio/adc/ad7091r5.c +4 -35
index 2f048527b7b7..9d3ccfca94ec 100644
@@ -12,42 +12,11 @@
 
 #include "ad7091r-base.h"
 
-static const struct iio_event_spec ad7091r5_events[] = {
-	{
-		.type = IIO_EV_TYPE_THRESH,
-		.dir = IIO_EV_DIR_RISING,
-		.mask_separate = BIT(IIO_EV_INFO_VALUE) |
-				 BIT(IIO_EV_INFO_ENABLE),
-	},
-	{
-		.type = IIO_EV_TYPE_THRESH,
-		.dir = IIO_EV_DIR_FALLING,
-		.mask_separate = BIT(IIO_EV_INFO_VALUE) |
-				 BIT(IIO_EV_INFO_ENABLE),
-	},
-	{
-		.type = IIO_EV_TYPE_THRESH,
-		.dir = IIO_EV_DIR_EITHER,
-		.mask_separate = BIT(IIO_EV_INFO_HYSTERESIS),
-	},
-};
-
-#define AD7091R_CHANNEL(idx, bits, ev, num_ev) { \
-	.type = IIO_VOLTAGE, \
-	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
-	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
-	.indexed = 1, \
-	.channel = idx, \
-	.event_spec = ev, \
-	.num_event_specs = num_ev, \
-	.scan_type.storagebits = 16, \
-	.scan_type.realbits = bits, \
-}
 static const struct iio_chan_spec ad7091r5_channels_irq[] = {
-	AD7091R_CHANNEL(0, 12, ad7091r5_events, ARRAY_SIZE(ad7091r5_events)),
-	AD7091R_CHANNEL(1, 12, ad7091r5_events, ARRAY_SIZE(ad7091r5_events)),
-	AD7091R_CHANNEL(2, 12, ad7091r5_events, ARRAY_SIZE(ad7091r5_events)),
-	AD7091R_CHANNEL(3, 12, ad7091r5_events, ARRAY_SIZE(ad7091r5_events)),
+	AD7091R_CHANNEL(0, 12, ad7091r_events, ARRAY_SIZE(ad7091r_events)),
+	AD7091R_CHANNEL(1, 12, ad7091r_events, ARRAY_SIZE(ad7091r_events)),
+	AD7091R_CHANNEL(2, 12, ad7091r_events, ARRAY_SIZE(ad7091r_events)),
+	AD7091R_CHANNEL(3, 12, ad7091r_events, ARRAY_SIZE(ad7091r_events)),
 };
 
 static const struct iio_chan_spec ad7091r5_channels_noirq[] = {
Signature · 1 line
2.42.0
author maintainer
#7 lore raw

PATCH v2 4/7 iio: adc: ad7091r: Alloc IIO device before generic probe

In reply to Marcelo Schmitt

Rework ad7091r probe functions so the IIO device is allocated before the generic device probe function is called.
This change is needed for a follow up patch that passes a pointer to the IIO device to a couple of regmap callback functions.

---
 drivers/iio/adc/ad7091r-base.c | 35 +++++++---------------------------
 drivers/iio/adc/ad7091r-base.h | 22 +++++++++++++++++----
 drivers/iio/adc/ad7091r5.c     | 14 ++++++++++++--
 3 files changed, 37 insertions(+), 34 deletions(-)
drivers/iio/adc/ad7091r-base.c +7 -28
index 1d84a57720ca..c752cd2283e6 100644
@@ -27,21 +27,6 @@
 #define AD7091R_REG_CONF_MODE_MASK  \
 	(AD7091R_REG_CONF_AUTO | AD7091R_REG_CONF_CMD)
 
-enum ad7091r_mode {
-	AD7091R_MODE_SAMPLE,
-	AD7091R_MODE_COMMAND,
-	AD7091R_MODE_AUTOCYCLE,
-};
-
-struct ad7091r_state {
-	struct device *dev;
-	struct regmap *map;
-	struct regulator *vref;
-	const struct ad7091r_chip_info *chip_info;
-	enum ad7091r_mode mode;
-	struct mutex lock; /*lock to prevent concurent reads */
-};
-
 const struct iio_event_spec ad7091r_events[] = {
 	{
 		.type = IIO_EV_TYPE_THRESH,
@@ -221,20 +206,14 @@ static void ad7091r_remove(void *data)
 	regulator_disable(st->vref);
 }
 
-int ad7091r_probe(struct device *dev, const char *name,
-		const struct ad7091r_chip_info *chip_info,
-		struct regmap *map, int irq)
+int ad7091r_probe(struct iio_dev *iio_dev, const char *name,
+		  const struct ad7091r_chip_info *chip_info,
+		  struct regmap *map, int irq)
 {
-	struct iio_dev *iio_dev;
 	struct ad7091r_state *st;
 	int ret;
 
-	iio_dev = devm_iio_device_alloc(dev, sizeof(*st));
-	if (!iio_dev)
-		return -ENOMEM;
-
 	st = iio_priv(iio_dev);
-	st->dev = dev;
 	st->chip_info = chip_info;
 	st->map = map;
 
@@ -252,7 +231,7 @@ int ad7091r_probe(struct device *dev, const char *name,
 			return ret;
 
 		dev_set_drvdata(st->dev, iio_dev);
-		ret = devm_request_threaded_irq(dev, irq, NULL,
+		ret = devm_request_threaded_irq(st->dev, irq, NULL,
 						ad7091r_event_handler,
 						IRQF_TRIGGER_FALLING |
 						IRQF_ONESHOT, name, st);
@@ -260,7 +239,7 @@ int ad7091r_probe(struct device *dev, const char *name,
 			return ret;
 	}
 
-	st->vref = devm_regulator_get_optional(dev, "vref");
+	st->vref = devm_regulator_get_optional(st->dev, "vref");
 	if (IS_ERR(st->vref)) {
 		if (PTR_ERR(st->vref) == -EPROBE_DEFER)
 			return -EPROBE_DEFER;
@@ -269,7 +248,7 @@ int ad7091r_probe(struct device *dev, const char *name,
 		ret = regulator_enable(st->vref);
 		if (ret)
 			return ret;
-		ret = devm_add_action_or_reset(dev, ad7091r_remove, st);
+		ret = devm_add_action_or_reset(st->dev, ad7091r_remove, st);
 		if (ret)
 			return ret;
 	}
@@ -279,7 +258,7 @@ int ad7091r_probe(struct device *dev, const char *name,
 	if (ret)
 		return ret;
 
-	return devm_iio_device_register(dev, iio_dev);
+	return devm_iio_device_register(st->dev, iio_dev);
 }
 EXPORT_SYMBOL_NS_GPL(ad7091r_probe, IIO_AD7091R);
 
drivers/iio/adc/ad7091r-base.h +18 -4
index 6ff539cd1d39..6997ea11998b 100644
@@ -30,7 +30,21 @@
 }
 
 struct device;
-struct ad7091r_state;
+
+enum ad7091r_mode {
+	AD7091R_MODE_SAMPLE,
+	AD7091R_MODE_COMMAND,
+	AD7091R_MODE_AUTOCYCLE,
+};
+
+struct ad7091r_state {
+	struct device *dev;
+	struct regmap *map;
+	struct regulator *vref;
+	const struct ad7091r_chip_info *chip_info;
+	enum ad7091r_mode mode;
+	struct mutex lock; /*lock to prevent concurent reads */
+};
 
 struct ad7091r_chip_info {
 	unsigned int num_channels;
@@ -42,9 +56,9 @@ extern const struct iio_event_spec ad7091r_events[3];
 
 extern const struct regmap_config ad7091r_regmap_config;
 
-int ad7091r_probe(struct device *dev, const char *name,
-		const struct ad7091r_chip_info *chip_info,
-		struct regmap *map, int irq);
+int ad7091r_probe(struct iio_dev *iio_dev, const char *name,
+		  const struct ad7091r_chip_info *chip_info,
+		  struct regmap *map, int irq);
 
 bool ad7091r_volatile_reg(struct device *dev, unsigned int reg);
 
drivers/iio/adc/ad7091r5.c +12 -2
index 9d3ccfca94ec..1a27841d1bbc 100644
@@ -42,8 +42,18 @@ static int ad7091r5_i2c_probe(struct i2c_client *i2c)
 {
 	const struct i2c_device_id *id = i2c_client_get_device_id(i2c);
 	const struct ad7091r_chip_info *chip_info;
-	struct regmap *map = devm_regmap_init_i2c(i2c, &ad7091r_regmap_config);
+	struct ad7091r_state *st;
+	struct iio_dev *iio_dev;
+	struct regmap *map;
 
+	iio_dev = devm_iio_device_alloc(&i2c->dev, sizeof(*st));
+	if (!iio_dev)
+		return -ENOMEM;
+
+	st = iio_priv(iio_dev);
+	st->dev = &i2c->dev;
+
+	map = devm_regmap_init_i2c(i2c, &ad7091r_regmap_config);
 	if (IS_ERR(map))
 		return PTR_ERR(map);
 
@@ -52,7 +62,7 @@ static int ad7091r5_i2c_probe(struct i2c_client *i2c)
 	else
 		chip_info = &ad7091r5_chip_info_noirq;
 
-	return ad7091r_probe(&i2c->dev, id->name, chip_info, map, i2c->irq);
+	return ad7091r_probe(iio_dev, id->name, chip_info, map, i2c->irq);
 }
 
 static const struct of_device_id ad7091r5_dt_ids[] = {
Signature · 1 line
2.42.0
author maintainer
#9 lore raw

PATCH v2 5/7 dt-bindings: iio: Add binding documentation for AD7091R-8

In reply to Marcelo Schmitt

Add device tree binding documentation for AD7091R-8.

---
 .../bindings/iio/adc/adi,ad7091r8.yaml        | 101 ++++++++++++++++++
 MAINTAINERS                                   |   1 +
 2 files changed, 102 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/iio/adc/adi,ad7091r8.yaml
Documentation/devicetree/bindings/iio/adc/adi,ad7091r8.yaml new file +101 -0
new file mode 100644
index 000000000000..3f09f3091a90
@@ -0,0 +1,101 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/adc/adi,ad7091r8.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Analog Devices AD7091R8 8-Channel 12-Bit ADC
+
+maintainers:
+  - Marcelo Schmitt <[email protected]>
+
+description: |
+  Analog Devices AD7091R-8 8-Channel 12-Bit ADC
+  https://www.analog.com/media/en/technical-documentation/data-sheets/AD7091R-2_7091R-4_7091R-8.pdf
+
+properties:
+  compatible:
+    enum:
+      - adi,ad7091r2
+      - adi,ad7091r4
+      - adi,ad7091r8
+
+  reg:
+    maxItems: 1
+
+  vref-supply: true
+
+  spi-max-frequency: true
+
+  adi,conversion-start-gpios:
+    description:
+      Device tree identifier of the CONVST pin.
+      This logic input is used to initiate conversions on the analog
+      input channels.
+    maxItems: 1
+
+  reset-gpios:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+patternProperties:
+  "^channel@[0-7]$":
+    $ref: adc.yaml
+    type: object
+    description: Represents the external channels which are connected to the ADC.
+
+    properties:
+      reg:
+        minimum: 0
+        maximum: 7
+
+    required:
+      - reg
+
+required:
+  - compatible
+  - reg
+  - adi,conversion-start-gpios
+
+allOf:
+  - $ref: /schemas/spi/spi-peripheral-props.yaml#
+
+  # AD7091R-2 does not have ALERT/BUSY/GPO pin
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - adi,ad7091r4
+              - adi,ad7091r8
+    then:
+      properties:
+        interrupts: true
+    else:
+      properties:
+        interrupts: false
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/irq.h>
+    #include <dt-bindings/gpio/gpio.h>
+    spi {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        adc@0 {
+                compatible = "adi,ad7091r8";
+                reg = <0x0>;
+                spi-max-frequency = <45454545>;
+                vref-supply = <&adc_vref>;
+                adi,conversion-start-gpios = <&gpio 25 GPIO_ACTIVE_LOW>;
+                reset-gpios = <&gpio 27 GPIO_ACTIVE_LOW>;
+                interrupts = <22 IRQ_TYPE_EDGE_FALLING>;
+                interrupt-parent = <&gpio>;
+        };
+    };
+...
MAINTAINERS +1 -0
index 008f0e73bead..6e7c6c866396 100644
@@ -1132,6 +1132,7 @@ L:	[email protected]
 S:	Supported
 W:	http://ez.analog.com/community/linux-device-drivers
 F:	Documentation/devicetree/bindings/iio/adc/adi,ad7091r5.yaml
+F:	Documentation/devicetree/bindings/iio/adc/adi,ad7091r8.yaml
 F:	drivers/iio/adc/drivers/iio/adc/ad7091r-base.c
 F:	drivers/iio/adc/drivers/iio/adc/ad7091r-base.h
 F:	drivers/iio/adc/drivers/iio/adc/ad7091r5.c
Signature · 1 line
2.42.0
author maintainer
#12 lore raw

PATCH v2 6/7 iio: adc: Add support for AD7091R-8

In reply to Marcelo Schmitt

Add support for Analog Devices AD7091R-2, AD7091R-4, and AD7091R-8 low power 12-Bit SAR ADCs.
Extend ad7091r-base driver so it can be used by AD7091R-8 drivers.

---
 MAINTAINERS                    |   1 +
 drivers/iio/adc/Kconfig        |  16 ++
 drivers/iio/adc/Makefile       |   4 +-
 drivers/iio/adc/ad7091r-base.c |  24 ++-
 drivers/iio/adc/ad7091r-base.h |  15 ++
 drivers/iio/adc/ad7091r5.c     |   2 +
 drivers/iio/adc/ad7091r8.c     | 270 +++++++++++++++++++++++++++++++++
 7 files changed, 324 insertions(+), 8 deletions(-)
 create mode 100644 drivers/iio/adc/ad7091r8.c
MAINTAINERS +1 -0
index 6e7c6c866396..54eff6f0c358 100644
@@ -1136,6 +1136,7 @@ F:	Documentation/devicetree/bindings/iio/adc/adi,ad7091r8.yaml
 F:	drivers/iio/adc/drivers/iio/adc/ad7091r-base.c
 F:	drivers/iio/adc/drivers/iio/adc/ad7091r-base.h
 F:	drivers/iio/adc/drivers/iio/adc/ad7091r5.c
+F:	drivers/iio/adc/drivers/iio/adc/ad7091r8.c
 
 ANALOG DEVICES INC AD7192 DRIVER
 M:	Alexandru Tachici <[email protected]>
drivers/iio/adc/Kconfig +16 -0
index 1e2b7a2c67c6..284d898790a2 100644
@@ -36,13 +36,29 @@ config AD4130
 	  To compile this driver as a module, choose M here: the module will be
 	  called ad4130.
 
+config AD7091R
+	tristate
+
 config AD7091R5
 	tristate "Analog Devices AD7091R5 ADC Driver"
 	depends on I2C
+	select AD7091R
 	select REGMAP_I2C
 	help
 	  Say yes here to build support for Analog Devices AD7091R-5 ADC.
 
+config AD7091R8
+	tristate "Analog Devices AD7091R8 ADC Driver"
+	depends on SPI
+	select AD7091R
+	select REGMAP_SPI
+	help
+	  Say yes here to build support for Analog Devices AD7091R-2, AD7091R-4,
+	  and AD7091R-8 ADC.
+
+	  To compile this driver as a module, choose M here: the module will be
+	  called ad7091r8.
+
 config AD7124
 	tristate "Analog Devices AD7124 and similar sigma-delta ADCs driver"
 	depends on SPI_MASTER
drivers/iio/adc/Makefile +3 -1
index c0803383a7cc..d2fda54a3259 100644
@@ -7,7 +7,9 @@
 obj-$(CONFIG_AB8500_GPADC) += ab8500-gpadc.o
 obj-$(CONFIG_AD_SIGMA_DELTA) += ad_sigma_delta.o
 obj-$(CONFIG_AD4130) += ad4130.o
-obj-$(CONFIG_AD7091R5) += ad7091r5.o ad7091r-base.o
+obj-$(CONFIG_AD7091R) += ad7091r-base.o
+obj-$(CONFIG_AD7091R5) += ad7091r5.o
+obj-$(CONFIG_AD7091R8) += ad7091r8.o
 obj-$(CONFIG_AD7124) += ad7124.o
 obj-$(CONFIG_AD7192) += ad7192.o
 obj-$(CONFIG_AD7266) += ad7266.o
drivers/iio/adc/ad7091r-base.c +17 -7
index c752cd2283e6..dbc60ea1bafc 100644
@@ -6,6 +6,7 @@
  */
 
 #include <linux/bitops.h>
+#include <linux/bitfield.h>
 #include <linux/iio/events.h>
 #include <linux/iio/iio.h>
 #include <linux/interrupt.h>
@@ -16,7 +17,8 @@
 #include "ad7091r-base.h"
 
 /* AD7091R_REG_RESULT */
-#define AD7091R_REG_RESULT_CH_ID(x)	    (((x) >> 13) & 0x3)
+#define AD7091R5_REG_RESULT_CH_ID(x)	    (((x) >> 13) & 0x3)
+#define AD7091R8_REG_RESULT_CH_ID(x)	    (((x) >> 13) & 0x7)
 #define AD7091R_REG_RESULT_CONV_RESULT(x)   ((x) & 0xfff)
 
 /* AD7091R_REG_CONF */
@@ -66,10 +68,13 @@ static int ad7091r_set_mode(struct ad7091r_state *st, enum ad7091r_mode mode)
 		return -EINVAL;
 	}
 
-	ret = regmap_update_bits(st->map, AD7091R_REG_CONF,
-				 AD7091R_REG_CONF_MODE_MASK, conf);
-	if (ret)
-		return ret;
+	/* AD7091R-2/4/8 don't set normal, command, autocycle modes in conf reg */
+	if (st->chip_info->type == AD7091R5) {
+		ret = regmap_update_bits(st->map, AD7091R_REG_CONF,
+					 AD7091R_REG_CONF_MODE_MASK, conf);
+		if (ret)
+			return ret;
+	}
 
 	st->mode = mode;
 
@@ -109,8 +114,13 @@ static int ad7091r_read_one(struct iio_dev *iio_dev,
 	if (ret)
 		return ret;
 
-	if (AD7091R_REG_RESULT_CH_ID(val) != channel)
-		return -EIO;
+	if (st->chip_info->type == AD7091R5) {
+		if (AD7091R5_REG_RESULT_CH_ID(val) != channel)
+			return -EIO;
+	} else {
+		if (AD7091R8_REG_RESULT_CH_ID(val) != channel)
+			return -EIO;
+	}
 
 	*read_val = AD7091R_REG_RESULT_CONV_RESULT(val);
 
drivers/iio/adc/ad7091r-base.h +15 -0
index 6997ea11998b..a42ea79a2893 100644
@@ -29,6 +29,8 @@
 	.scan_type.realbits = bits,					\
 }
 
+#include <linux/gpio/consumer.h>
+
 struct device;
 
 enum ad7091r_mode {
@@ -40,13 +42,26 @@ enum ad7091r_mode {
 struct ad7091r_state {
 	struct device *dev;
 	struct regmap *map;
+	struct gpio_desc *convst_gpio;
+	struct gpio_desc *reset_gpio;
 	struct regulator *vref;
 	const struct ad7091r_chip_info *chip_info;
 	enum ad7091r_mode mode;
 	struct mutex lock; /*lock to prevent concurent reads */
+	__be16 tx_buf __aligned(IIO_DMA_MINALIGN);
+	__be16 rx_buf;
+};
+
+enum ad7091r_device_type {
+	AD7091R2,
+	AD7091R4,
+	AD7091R5,
+	AD7091R8,
 };
 
 struct ad7091r_chip_info {
+	const char *name;
+	enum ad7091r_device_type type;
 	unsigned int num_channels;
 	const struct iio_chan_spec *channels;
 	unsigned int vref_mV;
drivers/iio/adc/ad7091r5.c +2 -0
index 1a27841d1bbc..5f587e0b55df 100644
@@ -27,12 +27,14 @@ static const struct iio_chan_spec ad7091r5_channels_noirq[] = {
 };
 
 static const struct ad7091r_chip_info ad7091r5_chip_info_irq = {
+	.type = AD7091R5,
 	.channels = ad7091r5_channels_irq,
 	.num_channels = ARRAY_SIZE(ad7091r5_channels_irq),
 	.vref_mV = 2500,
 };
 
 static const struct ad7091r_chip_info ad7091r5_chip_info_noirq = {
+	.type = AD7091R5,
 	.channels = ad7091r5_channels_noirq,
 	.num_channels = ARRAY_SIZE(ad7091r5_channels_noirq),
 	.vref_mV = 2500,
drivers/iio/adc/ad7091r8.c new file +270 -0

270 lines not on this page · raw message

Signature · 1 line
2.42.0
author maintainer
#14 lore raw

PATCH v2 7/7 iio: adc: ad7091r-base: Add debugfs reg access

In reply to Marcelo Schmitt

Add direct register access support for AD7091R-2/-4/-5/-8 ADCs.

---
 drivers/iio/adc/ad7091r-base.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
drivers/iio/adc/ad7091r-base.c +12 -0
index dbc60ea1bafc..4d5051316428 100644
@@ -177,8 +177,20 @@ static int ad7091r_read_raw(struct iio_dev *iio_dev,
 	return ret;
 }
 
+static int ad7091r_reg_access(struct iio_dev *indio_dev, unsigned int reg,
+			      unsigned int writeval, unsigned int *readval)
+{
+	struct ad7091r_state *st  = iio_priv(indio_dev);
+
+	if (readval)
+		return regmap_read(st->map, reg, readval);
+
+	return regmap_write(st->map, reg, writeval);
+}
+
 static const struct iio_info ad7091r_info = {
 	.read_raw = ad7091r_read_raw,
+	.debugfs_reg_access = &ad7091r_reg_access,
 };
 
 static irqreturn_t ad7091r_event_handler(int irq, void *private)
Signature · 1 line
2.42.0
#10 lore raw

Re: [PATCH v2 5/7] dt-bindings: iio: Add binding documentation for AD7091R-8

In reply to Marcelo Schmitt
Quoted 1 line · Marcelo Schmitt

+ spi-max-frequency: true

This is not needed, since you have unevaluatedProperties: false & include the spi periph props.

Documentation/devicetree/bindings/iio/adc/adi,ad7091r8.yaml line 32

Quoted 4 lines
Documentation/devicetree/bindings/iio/adc/adi,ad7091r8.yaml new file +3 -0
+  adi,conversion-start-gpios:
+    description:
 
+      Device tree identifier of the CONVST pin.

"gpio connected to the CONVST pin".

Documentation/devicetree/bindings/iio/adc/adi,ad7091r8.yaml line 35

Quoted 3 lines
Documentation/devicetree/bindings/iio/adc/adi,ad7091r8.yaml new file +3 -0
+      This logic input is used to initiate conversions on the analog
+      input channels.
+    maxItems: 1

This looks pretty decent to be overall though.

maintainer
#16 lore raw
In reply to Marcelo Schmitt
Quoted 9 lines · On Thu, 23 Nov 2023 13:29:12 -0300 Marcelo Schmitt…

From: Marcelo Schmitt <[email protected]>

This series adds support for AD7091R-2/-4/-8 ADCs which can do single shot or sequenced readings. Threshold events are also supported.
Overall, AD7091R-2/-4/-8 are very similar to AD7091R-5 except they use SPI interface.

This has been tested with raspberrypi and eval board on kernel 6.1 from ADI fork.

Quoted 7 lines

I ran get_maintainers on driver files but completely forgot to run it on the yaml doc, my bad.
I made the changes requested so far.
For v2, I also ran dt_binding_check on iio testing branch to check out for any additional dt-schema issues. None reported.
Didn't see any other warn after running Sparse, Smatch, and Coccicheck. I get a warn from checkpatch about IIO_DMA_MINALIGN which I don't know how to fix :(

Fix checkpatch :)
It has some exclusions for some of the warnings so probably look at what was added to avoid issues with __cacheline_aligned and friends.
https://elixir.bootlin.com/linux/latest/source/scripts/checkpatch.pl#L515

Quoted 30 lines

Change log v1 -> v2:
- Added device tree related To/Cc recipients.
- Removed extra print of error code
- $ref: "adc.yaml" -> $ref: adc.yaml
- Fixed defined but not used build warn
- Moved dt documentation of required properties to after patternProperties.
- Removed incorrect return before regmap_update_bits().

Marcelo Schmitt (7):
iio: adc: ad7091r-base: Set alert config and drvdata
MAINTAINERS: Add MAINTAINERS entry for AD7091R
iio: adc: ad7091r: Move defines to header file
iio: adc: ad7091r: Alloc IIO device before generic probe
dt-bindings: iio: Add binding documentation for AD7091R-8
iio: adc: Add support for AD7091R-8
iio: adc: ad7091r-base: Add debugfs reg access

 .../bindings/iio/adc/adi,ad7091r8.yaml        | 101 +++++++
 MAINTAINERS                                   |  12 +
 drivers/iio/adc/Kconfig                       |  16 ++
 drivers/iio/adc/Makefile                      |   4 +-
 drivers/iio/adc/ad7091r-base.c                | 114 +++++---
 drivers/iio/adc/ad7091r-base.h                |  64 ++++-
 drivers/iio/adc/ad7091r5.c                    |  55 ++--
 drivers/iio/adc/ad7091r8.c                    | 270 ++++++++++++++++++
 8 files changed, 549 insertions(+), 87 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/iio/adc/adi,ad7091r8.yaml
 create mode 100644 drivers/iio/adc/ad7091r8.c
maintainer
#2 lore raw

Re: [PATCH v2 1/7] iio: adc: ad7091r-base: Set alert config and drvdata

In reply to Marcelo Schmitt

On Thu, 23 Nov 2023 13:40:16 -0300
Marcelo Schmitt <[email protected]> wrote:

Hi Marcelo,

Thanks for the patch. Content looks fine but it wants breaking up into 2 fixes and one reformat.

Quoted 2 lines

Write 1 to bit 4 in the configuration register to set ALERT/BUSY/GPO pin to be used as ALERT.

That's s one fix.

Quoted 2 lines

Set device driver data so it can be retrieved when handling alert events, avoiding null pointer dereference.

That's one fix - so this should be at least 2 patches.

Quoted 2 lines
Fixes <ca69300173b6> (iio: adc: Add support for AD7091R5 ADC)

That's not the syntax for a fixes tag.

Quoted 23 lines
---
 drivers/iio/adc/ad7091r-base.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)
drivers/iio/adc/ad7091r-base.c +3 -0
index 8e252cde735b..3ecac3164446 100644
@@ -28,6 +28,7 @@
 #define AD7091R_REG_RESULT_CONV_RESULT(x)   ((x) & 0xfff)
 
 /* AD7091R_REG_CONF */
+#define AD7091R_REG_CONF_ALERT_EN   BIT(4)
 #define AD7091R_REG_CONF_AUTO   BIT(8)
 #define AD7091R_REG_CONF_CMD    BIT(10)
 
@@ -232,9 +233,16 @@ int ad7091r_probe(struct device *dev, const char *name,
 	iio_dev->channels = chip_info->channels;
 
 	if (irq) {
+		ret = regmap_update_bits(st->map, AD7091R_REG_CONF,
+					 AD7091R_REG_CONF_ALERT_EN, BIT(4));

drivers/iio/adc/ad7091r-base.c int ad7091r_probe(struct device *dev, const char *name, · line 245

Quoted 10 lines
drivers/iio/adc/ad7091r-base.c +7 -2
+		if (ret)
+			return ret;
+
+		dev_set_drvdata(st->dev, iio_dev);
 		ret = devm_request_threaded_irq(dev, irq, NULL,
-				ad7091r_event_handler,
-				IRQF_TRIGGER_FALLING | IRQF_ONESHOT, name, st);
+						ad7091r_event_handler,
+						IRQF_TRIGGER_FALLING |
+						IRQF_ONESHOT, name, st);

This is alignment cleanup. Should not be in a fix.

Quoted 3 lines
drivers/iio/adc/ad7091r-base.c +0 -0
 		if (ret)
 			return ret;
 	}
maintainer
#4 lore raw

Re: [PATCH v2 2/7] MAINTAINERS: Add MAINTAINERS entry for AD7091R

In reply to Marcelo Schmitt
Quoted 6 lines · On Thu, 23 Nov 2023 13:40:48 -0300 Marcelo Schmitt…

The driver for AD7091R was added in
ca693001: iio: adc: Add support for AD7091R5 ADC but no MAINTAINERS file entry was added for it since then. Add a proper MAINTAINERS file entry for the AD7091R driver.

Hi Marcelo,

Small patch ordering thing. If I apply the series in order, at this point you've not 'yet' contributed much to this driver so it's not obvious that you are in a position to take over maintenance.

Push it to the end of the series then it's fair enough and thanks for stepping up to look after this one!

Jonathan

Quoted 25 lines
---
 MAINTAINERS | 10 ++++++++++
 1 file changed, 10 insertions(+)
MAINTAINERS +10 -0
index 8e0a91dc8251..008f0e73bead 100644
@@ -1126,6 +1126,16 @@ F:	Documentation/ABI/testing/sysfs-bus-iio-adc-ad4130
 F:	Documentation/devicetree/bindings/iio/adc/adi,ad4130.yaml
 F:	drivers/iio/adc/ad4130.c
 
+ANALOG DEVICES INC AD7091R DRIVER
+M:	Marcelo Schmitt <[email protected]>
+L:	[email protected]
+S:	Supported
+W:	http://ez.analog.com/community/linux-device-drivers
+F:	Documentation/devicetree/bindings/iio/adc/adi,ad7091r5.yaml
+F:	drivers/iio/adc/drivers/iio/adc/ad7091r-base.c
+F:	drivers/iio/adc/drivers/iio/adc/ad7091r-base.h
+F:	drivers/iio/adc/drivers/iio/adc/ad7091r5.c
+
 ANALOG DEVICES INC AD7192 DRIVER
 M:	Alexandru Tachici <[email protected]>
 L:	[email protected]
maintainer
#6 lore raw

Re: [PATCH v2 3/7] iio: adc: ad7091r: Move defines to header file

In reply to Marcelo Schmitt
Quoted 3 lines · On Thu, 23 Nov 2023 13:41:28 -0300 Marcelo Schmitt…

Move AD7091R register, channel and event definitions to the header file so other AD7091R device drivers may use those declaration in follow up patches.

Hi,

This is moving stuff into the base.c file as well, but the patch description doesn't talk about that or the exports added. It should describe those parts.

Looks good otherwise - one trivial comment below.

Jonathan

Quoted 8 lines
drivers/iio/adc/ad7091r-base.h +0 -0
index 509748aef9b1..6ff539cd1d39 100644
@@ -8,6 +8,27 @@

...

drivers/iio/adc/ad7091r-base.h

Quoted 3 lines
drivers/iio/adc/ad7091r-base.h +2 -0
+bool ad7091r_volatile_reg(struct device *dev, unsigned int reg);
+

Trivial but I'd not have a blank line here.

Quoted 3 lines
drivers/iio/adc/ad7091r-base.h +2 -0
+bool ad7091r_writeable_reg(struct device *dev, unsigned int reg);
+
 #endif /* __DRIVERS_IIO_ADC_AD7091R_BASE_H__ */
maintainer
#8 lore raw

Re: [PATCH v2 4/7] iio: adc: ad7091r: Alloc IIO device before generic probe

In reply to Marcelo Schmitt
Quoted 7 lines · On Thu, 23 Nov 2023 13:41:59 -0300 Marcelo Schmitt…

Rework ad7091r probe functions so the IIO device is allocated before the generic device probe function is called.
This change is needed for a follow up patch that passes a pointer to the IIO device to a couple of regmap callback functions.

Why the gmail sign off? That's unusual enough that if it makes sense I'd like to see a comment below the --- on why.

Patch is fine, though I'll need to read further for why this is needed!

Jonathan

maintainer
#13 lore raw

Re: [PATCH v2 6/7] iio: adc: Add support for AD7091R-8

In reply to Marcelo Schmitt
Quoted 5 lines · On Thu, 23 Nov 2023 13:42:45 -0300 Marcelo Schmitt…

Add support for Analog Devices AD7091R-2, AD7091R-4, and AD7091R-8 low power 12-Bit SAR ADCs.
Extend ad7091r-base driver so it can be used by AD7091R-8 drivers.

Hi Marcelo,

Mostly looks fine, but I'd rather see all the chip specific information dragged into one place rather than indexing using a type enum. That includes code that does different things based on that enum value.

Doing so will provide a cleaner interface between the different modules. The enum thing has gone wrong far too many times as drivers become more complex.

Jonathan

Quoted 28 lines
---
 MAINTAINERS                    |   1 +
 drivers/iio/adc/Kconfig        |  16 ++
 drivers/iio/adc/Makefile       |   4 +-
 drivers/iio/adc/ad7091r-base.c |  24 ++-
 drivers/iio/adc/ad7091r-base.h |  15 ++
 drivers/iio/adc/ad7091r5.c     |   2 +
 drivers/iio/adc/ad7091r8.c     | 270 +++++++++++++++++++++++++++++++++
 7 files changed, 324 insertions(+), 8 deletions(-)
 create mode 100644 drivers/iio/adc/ad7091r8.c
MAINTAINERS +1 -0
index 6e7c6c866396..54eff6f0c358 100644
@@ -1136,6 +1136,7 @@ F:	Documentation/devicetree/bindings/iio/adc/adi,ad7091r8.yaml
 F:	drivers/iio/adc/drivers/iio/adc/ad7091r-base.c
 F:	drivers/iio/adc/drivers/iio/adc/ad7091r-base.h
 F:	drivers/iio/adc/drivers/iio/adc/ad7091r5.c
+F:	drivers/iio/adc/drivers/iio/adc/ad7091r8.c
 
 ANALOG DEVICES INC AD7192 DRIVER
 M:	Alexandru Tachici <[email protected]>
drivers/iio/adc/Kconfig +0 -0
index 1e2b7a2c67c6..284d898790a2 100644

drivers/iio/adc/Kconfig config AD4130 · line 40

Quoted 5 lines
drivers/iio/adc/Kconfig +2 -0
@@ -36,13 +36,29 @@ config AD4130
 	  To compile this driver as a module, choose M here: the module will be
 	  called ad4130.
 
+config AD7091R
+	tristate

It's fairly trivial but ideal patch split would have had the build changes for a core module and users of it done in an initial patch and only new stuff in the patch adding a driver.

...

Quoted 13 lines
drivers/iio/adc/ad7091r-base.c +1 -0
index c752cd2283e6..dbc60ea1bafc 100644
@@ -6,6 +6,7 @@
  */
 
 #include <linux/bitops.h>
+#include <linux/bitfield.h>
 #include <linux/iio/events.h>
 #include <linux/iio/iio.h>
 #include <linux/interrupt.h>

drivers/iio/adc/ad7091r-base.c line 21

Quoted 6 lines
drivers/iio/adc/ad7091r-base.c +2 -1
@@ -16,7 +17,8 @@
 #include "ad7091r-base.h"
 
 /* AD7091R_REG_RESULT */
-#define AD7091R_REG_RESULT_CH_ID(x)	    (((x) >> 13) & 0x3)
+#define AD7091R5_REG_RESULT_CH_ID(x)	    (((x) >> 13) & 0x3)
+#define AD7091R8_REG_RESULT_CH_ID(x)	    (((x) >> 13) & 0x7)

Hmm. Generally I'd not expect to see registers that only apply on a particular device in a generic library.

Normal trick for this is a define or callback as appropriate.

drivers/iio/adc/ad7091r-base.c static int ad7091r_set_mode(struct ad7091r_state *st, enum ad7091r_mode mode) · line 72

Quoted 13 lines
drivers/iio/adc/ad7091r-base.c +2 -4
 #define AD7091R_REG_RESULT_CONV_RESULT(x)   ((x) & 0xfff)
 
 /* AD7091R_REG_CONF */
@@ -66,10 +68,13 @@ static int ad7091r_set_mode(struct ad7091r_state *st, enum ad7091r_mode mode)
 		return -EINVAL;
 	}
 
-	ret = regmap_update_bits(st->map, AD7091R_REG_CONF,
-				 AD7091R_REG_CONF_MODE_MASK, conf);
-	if (ret)
-		return ret;
+	/* AD7091R-2/4/8 don't set normal, command, autocycle modes in conf reg */
+	if (st->chip_info->type == AD7091R5) {

A type in a chip_info structure often means we are exposing as code something that should really be data.

Quoted 9 lines
drivers/iio/adc/ad7091r-base.c +5 -0
+		ret = regmap_update_bits(st->map, AD7091R_REG_CONF,
+					 AD7091R_REG_CONF_MODE_MASK, conf);
+		if (ret)
+			return ret;
+	}
 
 	st->mode = mode;
 

drivers/iio/adc/ad7091r-base.c static int ad7091r_read_one(struct iio_dev *iio_dev, · line 117

Quoted 6 lines
drivers/iio/adc/ad7091r-base.c +1 -2
@@ -109,8 +114,13 @@ static int ad7091r_read_one(struct iio_dev *iio_dev,
 	if (ret)
 		return ret;
 
-	if (AD7091R_REG_RESULT_CH_ID(val) != channel)
-		return -EIO;
+	if (st->chip_info->type == AD7091R5) {

Here as well. I'd like to see this done either with data or a callback in the chip_info structure.

Quoted 14 lines
drivers/iio/adc/ad7091r-base.c +6 -0
+		if (AD7091R5_REG_RESULT_CH_ID(val) != channel)
+			return -EIO;
+	} else {
+		if (AD7091R8_REG_RESULT_CH_ID(val) != channel)
+			return -EIO;
+	}
 
 	*read_val = AD7091R_REG_RESULT_CONV_RESULT(val);
 
drivers/iio/adc/ad7091r-base.h +0 -0
index 6997ea11998b..a42ea79a2893 100644
@@ -29,6 +29,8 @@

...

drivers/iio/adc/ad7091r-base.h enum ad7091r_mode { · line 64

Quoted 10 lines
drivers/iio/adc/ad7091r-base.h +7 -0
+enum ad7091r_device_type {
+	AD7091R2,
+	AD7091R4,
+	AD7091R5,
+	AD7091R8,
 };
 
 struct ad7091r_chip_info {
+	const char *name;
+	enum ad7091r_device_type type;

This is almost always a design mistake. If we can possibly abstract the differences into either some data, or some callbacks (from the appropriate child module) that is much preferred to having a type enum and doing that in code.

I think it is fairly easy to do, but we need a wrapper structure around irq and non irq versions of this structure. Probably move the name and add a regmap_config to that wrapper structure.

Quoted 3 lines
drivers/iio/adc/ad7091r-base.h +0 -0
 	unsigned int num_channels;
 	const struct iio_chan_spec *channels;
 	unsigned int vref_mV;

...

Quoted 6 lines
drivers/iio/adc/ad7091r8.c new file +0 -0
new file mode 100644
index 000000000000..f062240873c6
@@ -0,0 +1,270 @@

...

Quoted 1 line

+static const struct regmap_config ad7091r_spi_regmap_config[] = {

As mentioned below, I'd like to see this in the info structure rather than a separate array that needs to be indexed.

Quoted 41 lines
drivers/iio/adc/ad7091r8.c new file +41 -0
+	[AD7091R2] = {
+		.reg_bits = 5,
+		.pad_bits = 3,
+		.val_bits = 16,
+		.volatile_reg = ad7091r_volatile_reg,
+		.writeable_reg = ad7091r_writeable_reg,
+		.max_register = AD7091R_REG_CH_HYSTERESIS(2),
+	},
+	[AD7091R4] = {
+		.reg_bits = 5,
+		.pad_bits = 3,
+		.val_bits = 16,
+		.volatile_reg = ad7091r_volatile_reg,
+		.writeable_reg = ad7091r_writeable_reg,
+		.max_register = AD7091R_REG_CH_HYSTERESIS(4),
+	},
+	[AD7091R8] = {
+		.reg_bits = 5,
+		.pad_bits = 3,
+		.write_flag_mask = BIT(2),
+		.val_bits = 16,
+		.volatile_reg = ad7091r_volatile_reg,
+		.writeable_reg = ad7091r_writeable_reg,
+		.max_register = AD7091R_REG_CH_HYSTERESIS(8),
+	},
+};
+
+static int ad7091r_regmap_bus_reg_read(void *context, unsigned int reg,
+				       unsigned int *val)
+{
+	struct ad7091r_state *st = context;
+	struct spi_device *spi = container_of(st->dev, struct spi_device, dev);
+	const struct regmap_config *conf = &ad7091r_spi_regmap_config[st->chip_info->type];
+	int ret;
+
+	struct spi_transfer t[] = {
+		{
+			.tx_buf = &st->tx_buf,
+			.len = 2,
+			.cs_change = 1,
+		}, {

drivers/iio/adc/ad7091r8.c line 150

Quoted 10 lines
drivers/iio/adc/ad7091r8.c new file +10 -0
+			.rx_buf = &st->rx_buf,
+			.len = 2,
+		}
+	};
+
+	if (reg == AD7091R_REG_RESULT)
+		ad7091r_pulse_convst(st);
+
+	reg <<= conf->pad_bits;
+	st->tx_buf = cpu_to_be16(reg << 8);

That's a bit unusual as a way to write the first of two bytes. Perhaps the data type of tx_buf is inappropriate here and it should just be u8 x[2]? I guess maybe it's easier to just keep it this way given the very different tx_buf format for writes.

Quoted 21 lines
drivers/iio/adc/ad7091r8.c new file +20 -0
+
+	ret = spi_sync_transfer(spi, t, ARRAY_SIZE(t));
+	if (ret < 0)
+		return ret;
+
+	*val = be16_to_cpu(st->rx_buf);
+	return 0;
+}
 
+
+static int ad7091r8_spi_probe(struct spi_device *spi)
+{
+	const struct ad7091r_chip_info *chip_info;
+	struct ad7091r_state *st;
+	struct iio_dev *iio_dev;
+	struct regmap *map;
+	int ret;
+
+	chip_info = spi_get_device_match_data(spi);
+	if (!chip_info)
+		return -EINVAL;

drivers/iio/adc/ad7091r8.c line 225

Quoted 10 lines
drivers/iio/adc/ad7091r8.c new file +10 -0
+
+	iio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
+	if (!iio_dev)
+		return -ENOMEM;
+
+	st = iio_priv(iio_dev);
+	st->dev = &spi->dev;
+
+	map = devm_regmap_init(&spi->dev, &ad7091r8_regmap_bus, st,
+			       &ad7091r_spi_regmap_config[chip_info->type]);

regmap config should be accessed via a pointer in the chip_info structure not a separate array.

Quoted 1 line

+

Trivial : No blank line generally between function call an it's error handler.

drivers/iio/adc/ad7091r8.c line 236

Quoted 10 lines
drivers/iio/adc/ad7091r8.c new file +10 -0
+	if (IS_ERR(map))
+		return dev_err_probe(&spi->dev, PTR_ERR(map),
+				     "Error initializing spi regmap\n");
+
+	ret = ad7091r8_gpio_setup(st);
+	if (ret < 0)
+		return ret;
+
+	if (spi->irq)
+		chip_info = &ad7091r_spi_chip_info_irq[chip_info->type];

This is a little ugly and explains your indirection via a type. I'd put a wrapper structure round both chip_info (irq and non irq) and add that to the .data in the look up tables that follow. Thus having a simple tree structure for now we get to the appropriate data

struct ad7091r_chip_info_container {
	struct ad7091r_chip_info irq_info;
	struct ad7091r_chip_info no_irq_info;
	struct regmap_config *regmap_config;
};

Pointers fine as well if that ends up cleaner.

Then spi_get_device_match_data() provides a pointer to this container struct providing all the info for the device, and the stuff we need at runtime is then done by picking between the two info structures under it.

Quoted 7 lines
drivers/iio/adc/ad7091r8.c new file +7 -0
+
+	return ad7091r_probe(iio_dev, chip_info->name, chip_info, map, spi->irq);
+}
+
+static const struct of_device_id ad7091r8_of_match[] = {
+	{ .compatible = "adi,ad7091r2", .data = &ad7091r_spi_chip_info[AD7091R2] },
+	{ .compatible = "adi,ad7091r4", .data = &ad7091r_spi_chip_info[AD7091R4] },

drivers/iio/adc/ad7091r8.c line 253

Quoted 10 lines
drivers/iio/adc/ad7091r8.c new file +10 -0
+	{ .compatible = "adi,ad7091r8", .data = &ad7091r_spi_chip_info[AD7091R8] },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, ad7091r8_of_match);
+
+static const struct spi_device_id ad7091r8_spi_id[] = {
+	{ "ad7091r2", (kernel_ulong_t)&ad7091r_spi_chip_info[AD7091R2] },
+	{ "ad7091r4", (kernel_ulong_t)&ad7091r_spi_chip_info[AD7091R4] },
+	{ "ad7091r8", (kernel_ulong_t)&ad7091r_spi_chip_info[AD7091R8] },
+	{ },

'Null terminators' like these shouldn't be followed by a , We can't add anything after them in future.

Quoted 2 lines
drivers/iio/adc/ad7091r8.c new file +2 -0
+};
+MODULE_DEVICE_TABLE(spi, ad7091r8_spi_id);
maintainer
#15 lore raw

Re: [PATCH v2 7/7] iio: adc: ad7091r-base: Add debugfs reg access

In reply to Marcelo Schmitt
Quoted 3 lines · On Thu, 23 Nov 2023 13:43:06 -0300 Marcelo Schmitt…

Add direct register access support for AD7091R-2/-4/-5/-8 ADCs.

regmap provides it's own version of this, so I'm not sure I'd bother adding the IIO one. See regmap-debugfs.c

Quoted 29 lines
---
 drivers/iio/adc/ad7091r-base.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
drivers/iio/adc/ad7091r-base.c +12 -0
index dbc60ea1bafc..4d5051316428 100644
@@ -177,8 +177,20 @@ static int ad7091r_read_raw(struct iio_dev *iio_dev,
 	return ret;
 }
 
+static int ad7091r_reg_access(struct iio_dev *indio_dev, unsigned int reg,
+			      unsigned int writeval, unsigned int *readval)
+{
+	struct ad7091r_state *st  = iio_priv(indio_dev);
+
+	if (readval)
+		return regmap_read(st->map, reg, readval);
+
+	return regmap_write(st->map, reg, writeval);
+}
+
 static const struct iio_info ad7091r_info = {
 	.read_raw = ad7091r_read_raw,
+	.debugfs_reg_access = &ad7091r_reg_access,
 };
 
 static irqreturn_t ad7091r_event_handler(int irq, void *private)
maintainer
#11 lore raw

Re: [PATCH v2 5/7] dt-bindings: iio: Add binding documentation for AD7091R-8

In reply to Marcelo Schmitt
Quoted 1 line · Marcelo Schmitt

Add device tree binding documentation for AD7091R-8.

Drop 'binding documentation for ' from the subject. You already said that with 'dt-bindings'.

Rob