Devicetree
 help / color / mirror / Atom feed
* [PATCH v2 0/4] iio: adc: ade9000: add support for ADE9078
@ 2026-07-31  8:29 Antoniu Miclaus
  2026-07-31  8:29 ` [PATCH v2 1/4] iio: adc: ade9000: introduce chip_info structure Antoniu Miclaus
                   ` (3 more replies)
  0 siblings, 4 replies; 7+ messages in thread
From: Antoniu Miclaus @ 2026-07-31  8:29 UTC (permalink / raw)
  To: Antoniu Miclaus, Nuno Sá, Michael Hennerich,
	Jonathan Cameron, David Lechner, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Jonathan Corbet, Shuah Khan, Radu Sabau,
	Marcelo Schmitt, Jorge Marques, Salih Erim, Matti Vaittinen,
	Jishnu Prakash, linux-iio, linux, devicetree, linux-kernel,
	linux-doc

The ADE9078 is a polyphase energy metering device from the same family as
the ADE9000 and is register compatible with it. The main differences
relevant to the driver are the absence of the on-chip dip/swell detection,
a lower maximum SPI clock (10 MHz), and slightly different full-scale ADC
codes.

This series adds support for the ADE9078 to the existing ade9000 driver.
It first refactors the driver to move the part-specific values (device
name, channel table, and full-scale codes) into a chip_info structure
retrieved via device match data, then adds the new device tree compatible
and the ADE9078 support itself, and finally updates the documentation.

Changes in v2:
- move the "respective datasheets" comment wording to avoid churn.
- use a generic Kconfig title and list the supported parts.
- duplicate the RMS voltage macro instead of a shared base macro.

v1: https://lore.kernel.org/linux-iio/<FILL-IN-v1-MESSAGE-ID>/

Antoniu Miclaus (4):
  iio: adc: ade9000: introduce chip_info structure
  dt-bindings: iio: adc: adi,ade9000: add adi,ade9078 compatible
  iio: adc: ade9000: add support for ADE9078
  docs: iio: ade9000: document ADE9078 support

 .../bindings/iio/adc/adi,ade9000.yaml         |  30 ++-
 Documentation/iio/ade9000.rst                 |  28 +--
 drivers/iio/adc/Kconfig                       |  16 +-
 drivers/iio/adc/ade9000.c                     | 180 ++++++++++++------
 4 files changed, 175 insertions(+), 79 deletions(-)


base-commit: 0b5e142ced4bcf20532da051934bd694d1bbd470
-- 
2.43.0


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v2 1/4] iio: adc: ade9000: introduce chip_info structure
  2026-07-31  8:29 [PATCH v2 0/4] iio: adc: ade9000: add support for ADE9078 Antoniu Miclaus
@ 2026-07-31  8:29 ` Antoniu Miclaus
  2026-07-31  8:40   ` sashiko-bot
  2026-07-31  8:29 ` [PATCH v2 2/4] dt-bindings: iio: adc: adi,ade9000: add adi,ade9078 compatible Antoniu Miclaus
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 7+ messages in thread
From: Antoniu Miclaus @ 2026-07-31  8:29 UTC (permalink / raw)
  To: Antoniu Miclaus, Nuno Sá, Michael Hennerich,
	Jonathan Cameron, David Lechner, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Jonathan Corbet, Shuah Khan, Radu Sabau,
	Marcelo Schmitt, Jorge Marques, Salih Erim, Matti Vaittinen,
	Jishnu Prakash, linux-iio, linux, devicetree, linux-kernel,
	linux-doc

The driver currently hardcodes the device name and the full-scale ADC
codes used to derive the IIO scale attributes. In preparation for
supporting additional parts of the ADE9000 family, move these
part-specific values into a new struct ade9000_chip_info and retrieve it
via spi_get_device_match_data() at probe time.

The channel table and its size are also referenced through the chip_info
so that parts with a different channel layout can be added without
touching the probe path.

No functional change intended for the ADE9000.

Signed-off-by: Antoniu Miclaus <antoniu.miclaus@analog.com>
---
Changes in v2:
- introduce the "respective datasheets" comment wording here to avoid
  churn in the ADE9078 patch.

 drivers/iio/adc/ade9000.c | 63 +++++++++++++++++++++++++++++----------
 1 file changed, 47 insertions(+), 16 deletions(-)

diff --git a/drivers/iio/adc/ade9000.c b/drivers/iio/adc/ade9000.c
index c6c3ea953fea..030bb9109ab6 100644
--- a/drivers/iio/adc/ade9000.c
+++ b/drivers/iio/adc/ade9000.c
@@ -242,14 +242,6 @@
 #define ADE9000_LAST_PAGE_BIT		BIT(15)
 #define ADE9000_MIDDLE_PAGE_BIT		BIT(7)
 
-/*
- * Full scale Codes referred from Datasheet. Respective digital codes are
- * produced when ADC inputs are at full scale.
- */
-#define ADE9000_RMS_FULL_SCALE_CODES	52866837
-#define ADE9000_WATT_FULL_SCALE_CODES	20694066
-#define ADE9000_PCF_FULL_SCALE_CODES	74770000
-
 /* Phase and channel definitions */
 #define ADE9000_PHASE_A_NR		0
 #define ADE9000_PHASE_B_NR		1
@@ -290,7 +282,29 @@ enum ade9000_wfb_cfg {
 #define ADE9000_ADDR_ADJUST(addr, chan)					\
 	(((chan) == 0 ? 0 : (chan) == 1 ? 2 : 4) << 4 | (addr))
 
+/**
+ * struct ade9000_chip_info - part-specific configuration
+ * @name: IIO device name reported to userspace
+ * @channels: channel specification for this part
+ * @num_channels: number of entries in @channels
+ * @rms_full_scale_codes: digital code produced at full-scale RMS input
+ * @watt_full_scale_codes: digital code produced at full-scale power input
+ * @pcf_full_scale_codes: digital code produced at full-scale xI_PCF/xV_PCF input
+ *
+ * The full-scale codes are taken from the respective datasheets and are used to
+ * derive the IIO scale of the raw measurement channels.
+ */
+struct ade9000_chip_info {
+	const char *name;
+	const struct iio_chan_spec *channels;
+	unsigned int num_channels;
+	unsigned int rms_full_scale_codes;
+	unsigned int watt_full_scale_codes;
+	unsigned int pcf_full_scale_codes;
+};
+
 struct ade9000_state {
+	const struct ade9000_chip_info *info;
 	struct completion reset_completion;
 	struct mutex lock; /* Protects SPI transactions */
 	u8 wf_src;
@@ -623,6 +637,19 @@ static const struct iio_chan_spec ade9000_channels[] = {
 	ADE9000_POWER_FACTOR_CHANNEL(ADE9000_PHASE_C_NR),
 };
 
+/*
+ * Full-scale codes referred from the respective datasheets. These are the
+ * digital codes produced when the ADC inputs are at full scale.
+ */
+static const struct ade9000_chip_info ade9000_chip_info = {
+	.name = "ade9000",
+	.channels = ade9000_channels,
+	.num_channels = ARRAY_SIZE(ade9000_channels),
+	.rms_full_scale_codes = 52866837,
+	.watt_full_scale_codes = 20694066,
+	.pcf_full_scale_codes = 74770000,
+};
+
 static const struct reg_sequence ade9000_initialization_sequence[] = {
 	{ ADE9000_REG_PGA_GAIN, ADE9000_PGA_GAIN },
 	{ ADE9000_REG_CONFIG0, ADE9000_CONFIG0 },
@@ -1064,7 +1091,7 @@ static int ade9000_read_raw(struct iio_dev *indio_dev,
 			case ADE9000_REG_CI_PCF:
 			case ADE9000_REG_CV_PCF:
 				*val = 1;
-				*val2 = ADE9000_PCF_FULL_SCALE_CODES;
+				*val2 = st->info->pcf_full_scale_codes;
 				return IIO_VAL_FRACTIONAL;
 			case ADE9000_REG_AIRMS:
 			case ADE9000_REG_AVRMS:
@@ -1073,14 +1100,14 @@ static int ade9000_read_raw(struct iio_dev *indio_dev,
 			case ADE9000_REG_CIRMS:
 			case ADE9000_REG_CVRMS:
 				*val = 1;
-				*val2 = ADE9000_RMS_FULL_SCALE_CODES;
+				*val2 = st->info->rms_full_scale_codes;
 				return IIO_VAL_FRACTIONAL;
 			default:
 				return -EINVAL;
 			}
 		case IIO_POWER:
 			*val = 1;
-			*val2 = ADE9000_WATT_FULL_SCALE_CODES;
+			*val2 = st->info->watt_full_scale_codes;
 			return IIO_VAL_FRACTIONAL;
 		default:
 			break;
@@ -1692,6 +1719,10 @@ static int ade9000_probe(struct spi_device *spi)
 
 	st = iio_priv(indio_dev);
 
+	st->info = spi_get_device_match_data(spi);
+	if (!st->info)
+		return -ENODEV;
+
 	regmap = devm_regmap_init(dev, NULL, st, &ade9000_regmap_config);
 	if (IS_ERR(regmap))
 		return dev_err_probe(dev, PTR_ERR(regmap), "Unable to allocate ADE9000 regmap");
@@ -1726,7 +1757,7 @@ static int ade9000_probe(struct spi_device *spi)
 	if (ret)
 		return ret;
 
-	indio_dev->name = "ade9000";
+	indio_dev->name = st->info->name;
 	indio_dev->info = &ade9000_info;
 	indio_dev->modes = INDIO_DIRECT_MODE;
 	indio_dev->setup_ops = &ade9000_buffer_ops;
@@ -1736,8 +1767,8 @@ static int ade9000_probe(struct spi_device *spi)
 		return dev_err_probe(&spi->dev, ret,
 				     "Failed to get and enable vdd regulator\n");
 
-	indio_dev->channels = ade9000_channels;
-	indio_dev->num_channels = ARRAY_SIZE(ade9000_channels);
+	indio_dev->channels = st->info->channels;
+	indio_dev->num_channels = st->info->num_channels;
 
 	ret = devm_iio_kfifo_buffer_setup(dev, indio_dev,
 					  &ade9000_buffer_ops);
@@ -1768,13 +1799,13 @@ static int ade9000_probe(struct spi_device *spi)
 };
 
 static const struct spi_device_id ade9000_id[] = {
-	{ .name = "ade9000" },
+	{ .name = "ade9000", .driver_data = (kernel_ulong_t)&ade9000_chip_info },
 	{ }
 };
 MODULE_DEVICE_TABLE(spi, ade9000_id);
 
 static const struct of_device_id ade9000_of_match[] = {
-	{ .compatible = "adi,ade9000" },
+	{ .compatible = "adi,ade9000", .data = &ade9000_chip_info },
 	{ }
 };
 MODULE_DEVICE_TABLE(of, ade9000_of_match);
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v2 2/4] dt-bindings: iio: adc: adi,ade9000: add adi,ade9078 compatible
  2026-07-31  8:29 [PATCH v2 0/4] iio: adc: ade9000: add support for ADE9078 Antoniu Miclaus
  2026-07-31  8:29 ` [PATCH v2 1/4] iio: adc: ade9000: introduce chip_info structure Antoniu Miclaus
@ 2026-07-31  8:29 ` Antoniu Miclaus
  2026-07-31  8:39   ` sashiko-bot
  2026-07-31  8:29 ` [PATCH v2 3/4] iio: adc: ade9000: add support for ADE9078 Antoniu Miclaus
  2026-07-31  8:29 ` [PATCH v2 4/4] docs: iio: ade9000: document ADE9078 support Antoniu Miclaus
  3 siblings, 1 reply; 7+ messages in thread
From: Antoniu Miclaus @ 2026-07-31  8:29 UTC (permalink / raw)
  To: Antoniu Miclaus, Nuno Sá, Michael Hennerich,
	Jonathan Cameron, David Lechner, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Jonathan Corbet, Shuah Khan, Radu Sabau,
	Marcelo Schmitt, Jorge Marques, Salih Erim, Matti Vaittinen,
	Jishnu Prakash, linux-iio, linux, devicetree, linux-kernel,
	linux-doc

The ADE9078 is a polyphase energy metering device from the same family as
the ADE9000. It is register-compatible with the ADE9000 but does not
provide the on-chip dip/swell detection and is limited to a 10 MHz SPI
clock.

Add the new compatible along with a conditional constraint lowering the
maximum spi-max-frequency for the ADE9078.

Signed-off-by: Antoniu Miclaus <antoniu.miclaus@analog.com>
---
no changes in v2.
 .../bindings/iio/adc/adi,ade9000.yaml         | 30 ++++++++++++++-----
 1 file changed, 22 insertions(+), 8 deletions(-)

diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ade9000.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ade9000.yaml
index f22eba0250ee..1e940e8c7297 100644
--- a/Documentation/devicetree/bindings/iio/adc/adi,ade9000.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/adi,ade9000.yaml
@@ -5,21 +5,23 @@
 $id: http://devicetree.org/schemas/iio/adc/adi,ade9000.yaml#
 $schema: http://devicetree.org/meta-schemas/core.yaml#
 
-title: Analog Devices ADE9000 High Performance, Polyphase Energy Metering
+title: Analog Devices ADE9000/ADE9078 High Performance, Polyphase Energy Metering
 
 maintainers:
   - Antoniu Miclaus <antoniu.miclaus@analog.com>
 
 description: |
-  The ADE9000 is a highly accurate, fully integrated, multiphase energy and power
-  quality monitoring device. Superior analog performance and a digital signal
-  processing (DSP) core enable accurate energy monitoring over a wide dynamic
-  range. An integrated high end reference ensures low drift over temperature
-  with a combined drift of less than ±25 ppm/°C maximum for the entire channel
-  including a programmable gain amplifier (PGA) and an analog-to-digital
-  converter (ADC).
+  The ADE9000 and ADE9078 are highly accurate, fully integrated, multiphase
+  energy and power quality monitoring devices. Superior analog performance and a
+  digital signal processing (DSP) core enable accurate energy monitoring over a
+  wide dynamic range. An integrated high end reference ensures low drift over
+  temperature with a combined drift of less than ±25 ppm/°C maximum for the
+  entire channel including a programmable gain amplifier (PGA) and an
+  analog-to-digital converter (ADC). The ADE9078 does not provide the on-chip
+  dip/swell detection available on the ADE9000.
 
   https://www.analog.com/media/en/technical-documentation/data-sheets/ADE9000.pdf
+  https://www.analog.com/media/en/technical-documentation/data-sheets/ADE9078.pdf
 
 $ref: /schemas/spi/spi-peripheral-props.yaml#
 
@@ -27,6 +29,7 @@ properties:
   compatible:
     enum:
       - adi,ade9000
+      - adi,ade9078
 
   reg:
     maxItems: 1
@@ -67,6 +70,17 @@ required:
   - reg
   - vdd-supply
 
+allOf:
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: adi,ade9078
+    then:
+      properties:
+        spi-max-frequency:
+          maximum: 10000000
+
 unevaluatedProperties: false
 
 examples:
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v2 3/4] iio: adc: ade9000: add support for ADE9078
  2026-07-31  8:29 [PATCH v2 0/4] iio: adc: ade9000: add support for ADE9078 Antoniu Miclaus
  2026-07-31  8:29 ` [PATCH v2 1/4] iio: adc: ade9000: introduce chip_info structure Antoniu Miclaus
  2026-07-31  8:29 ` [PATCH v2 2/4] dt-bindings: iio: adc: adi,ade9000: add adi,ade9078 compatible Antoniu Miclaus
@ 2026-07-31  8:29 ` Antoniu Miclaus
  2026-07-31  8:29 ` [PATCH v2 4/4] docs: iio: ade9000: document ADE9078 support Antoniu Miclaus
  3 siblings, 0 replies; 7+ messages in thread
From: Antoniu Miclaus @ 2026-07-31  8:29 UTC (permalink / raw)
  To: Antoniu Miclaus, Nuno Sá, Michael Hennerich,
	Jonathan Cameron, David Lechner, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Jonathan Corbet, Shuah Khan, Radu Sabau,
	Marcelo Schmitt, Jorge Marques, Salih Erim, Matti Vaittinen,
	Jishnu Prakash, linux-iio, linux, devicetree, linux-kernel,
	linux-doc

The ADE9078 is a polyphase energy metering device that is register
compatible with the ADE9000. The main differences relevant to the driver
are the absence of the on-chip dip/swell detection and slightly different
full-scale ADC codes.

Add a dedicated channel table that omits the swell/dip voltage events and
a matching chip_info describing the ADE9078 full-scale codes. A separate
RMS voltage channel macro variant is added that drops the swell/dip event
spec so the ADE9078 channel table can omit those events.

Signed-off-by: Antoniu Miclaus <antoniu.miclaus@analog.com>
---
Changes in v2:
- use a generic Kconfig title and list the supported parts.
- duplicate the RMS voltage macro instead of a shared base macro.
- drop the full-scale codes comment change and reword the commit message.

 drivers/iio/adc/Kconfig   |  16 ++---
 drivers/iio/adc/ade9000.c | 119 ++++++++++++++++++++++++++------------
 2 files changed, 90 insertions(+), 45 deletions(-)

diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 642c42b1fae7..daebffa93a83 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -573,20 +573,22 @@ config AD9467
 	  called ad9467.
 
 config ADE9000
-	tristate "Analog Devices ADE9000 Multiphase Energy, and Power Quality Monitoring IC Driver"
+	tristate "Analog Devices Multiphase Energy and Power Quality Monitoring IC Driver"
 	depends on SPI
 	select REGMAP_SPI
 	select IIO_BUFFER
 	select IIO_KFIFO_BUF
 	help
-	  Say yes here to build support for the Analog Devices ADE9000,
-	  a highly accurate, multiphase energy and power quality monitoring
-	  integrated circuit.
+	  Say yes here to build support for the following Analog Devices
+	  highly accurate, multiphase energy and power quality monitoring
+	  integrated circuits:
+	    - ADE9000
+	    - ADE9078
 
-	  The device features high-precision analog-to-digital converters
+	  The devices feature high-precision analog-to-digital converters
 	  and digital signal processing to compute RMS values, power factor,
-	  frequency, and harmonic analysis. It supports SPI communication
-	  and provides buffered data output through the IIO framework.
+	  frequency, and harmonic analysis. They support SPI communication
+	  and provide buffered data output through the IIO framework.
 
 	  To compile this driver as a module, choose M here: the module will
 	  be called ade9000.
diff --git a/drivers/iio/adc/ade9000.c b/drivers/iio/adc/ade9000.c
index 030bb9109ab6..fd1362a98052 100644
--- a/drivers/iio/adc/ade9000.c
+++ b/drivers/iio/adc/ade9000.c
@@ -502,6 +502,7 @@ static const struct iio_chan_spec_ext_info ade9000_ext_info[] = {
 	.scan_index = -1						\
 }
 
+/* With swell/dip (sag) events - ADE9000 only */
 #define ADE9000_ALTVOLTAGE_RMS_CHANNEL(num) {				\
 	.type = IIO_ALTVOLTAGE,						\
 	.channel = num,							\
@@ -517,6 +518,20 @@ static const struct iio_chan_spec_ext_info ade9000_ext_info[] = {
 	.scan_index = -1						\
 }
 
+/* Without swell/dip events - parts lacking DIP_LVL/SWELL_LVL hardware */
+#define ADE9000_ALTVOLTAGE_RMS_CHANNEL_NO_EVENTS(num) {			\
+	.type = IIO_ALTVOLTAGE,						\
+	.channel = num,							\
+	.address = ADE9000_ADDR_ADJUST(ADE9000_REG_AVRMS, num),		\
+	.channel2 = IIO_MOD_RMS,					\
+	.modified = 1,							\
+	.indexed = 1,							\
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |			\
+			      BIT(IIO_CHAN_INFO_SCALE) |		\
+			      BIT(IIO_CHAN_INFO_CALIBBIAS),		\
+	.scan_index = -1						\
+}
+
 #define ADE9000_POWER_ACTIVE_CHANNEL(num) {				\
 	.type = IIO_POWER,						\
 	.channel = num,							\
@@ -598,44 +613,61 @@ static const struct iio_chan_spec_ext_info ade9000_ext_info[] = {
 	.scan_index = -1						\
 }
 
-static const struct iio_chan_spec ade9000_channels[] = {
-	/* Phase A channels */
-	ADE9000_CURRENT_CHANNEL(ADE9000_PHASE_A_NR),
-	ADE9000_VOLTAGE_CHANNEL(ADE9000_PHASE_A_NR),
-	ADE9000_ALTCURRENT_RMS_CHANNEL(ADE9000_PHASE_A_NR),
-	ADE9000_ALTVOLTAGE_RMS_CHANNEL(ADE9000_PHASE_A_NR),
-	ADE9000_POWER_ACTIVE_CHANNEL(ADE9000_PHASE_A_NR),
-	ADE9000_POWER_REACTIVE_CHANNEL(ADE9000_PHASE_A_NR),
-	ADE9000_POWER_APPARENT_CHANNEL(ADE9000_PHASE_A_NR),
-	ADE9000_ENERGY_ACTIVE_CHANNEL(ADE9000_PHASE_A_NR, ADE9000_REG_AWATTHR_LO),
-	ADE9000_ENERGY_APPARENT_CHANNEL(ADE9000_PHASE_A_NR, ADE9000_REG_AVAHR_LO),
-	ADE9000_ENERGY_REACTIVE_CHANNEL(ADE9000_PHASE_A_NR, ADE9000_REG_AFVARHR_LO),
-	ADE9000_POWER_FACTOR_CHANNEL(ADE9000_PHASE_A_NR),
-	/* Phase B channels */
-	ADE9000_CURRENT_CHANNEL(ADE9000_PHASE_B_NR),
-	ADE9000_VOLTAGE_CHANNEL(ADE9000_PHASE_B_NR),
-	ADE9000_ALTCURRENT_RMS_CHANNEL(ADE9000_PHASE_B_NR),
-	ADE9000_ALTVOLTAGE_RMS_CHANNEL(ADE9000_PHASE_B_NR),
-	ADE9000_POWER_ACTIVE_CHANNEL(ADE9000_PHASE_B_NR),
-	ADE9000_POWER_REACTIVE_CHANNEL(ADE9000_PHASE_B_NR),
-	ADE9000_POWER_APPARENT_CHANNEL(ADE9000_PHASE_B_NR),
-	ADE9000_ENERGY_ACTIVE_CHANNEL(ADE9000_PHASE_B_NR, ADE9000_REG_BWATTHR_LO),
-	ADE9000_ENERGY_APPARENT_CHANNEL(ADE9000_PHASE_B_NR, ADE9000_REG_BVAHR_LO),
-	ADE9000_ENERGY_REACTIVE_CHANNEL(ADE9000_PHASE_B_NR, ADE9000_REG_BFVARHR_LO),
-	ADE9000_POWER_FACTOR_CHANNEL(ADE9000_PHASE_B_NR),
-	/* Phase C channels */
-	ADE9000_CURRENT_CHANNEL(ADE9000_PHASE_C_NR),
-	ADE9000_VOLTAGE_CHANNEL(ADE9000_PHASE_C_NR),
-	ADE9000_ALTCURRENT_RMS_CHANNEL(ADE9000_PHASE_C_NR),
-	ADE9000_ALTVOLTAGE_RMS_CHANNEL(ADE9000_PHASE_C_NR),
-	ADE9000_POWER_ACTIVE_CHANNEL(ADE9000_PHASE_C_NR),
-	ADE9000_POWER_REACTIVE_CHANNEL(ADE9000_PHASE_C_NR),
-	ADE9000_POWER_APPARENT_CHANNEL(ADE9000_PHASE_C_NR),
-	ADE9000_ENERGY_ACTIVE_CHANNEL(ADE9000_PHASE_C_NR, ADE9000_REG_CWATTHR_LO),
-	ADE9000_ENERGY_APPARENT_CHANNEL(ADE9000_PHASE_C_NR, ADE9000_REG_CVAHR_LO),
-	ADE9000_ENERGY_REACTIVE_CHANNEL(ADE9000_PHASE_C_NR, ADE9000_REG_CFVARHR_LO),
-	ADE9000_POWER_FACTOR_CHANNEL(ADE9000_PHASE_C_NR),
-};
+/*
+ * Declare a full channel array. @altvoltage_rms picks the RMS voltage channel
+ * variant so parts without dip/swell hardware (e.g. ADE9078) omit those events.
+ */
+#define ADE9000_DECLARE_CHANNELS(_name, altvoltage_rms)			      \
+	static const struct iio_chan_spec _name[] = {			      \
+		/* Phase A channels */					      \
+		ADE9000_CURRENT_CHANNEL(ADE9000_PHASE_A_NR),		      \
+		ADE9000_VOLTAGE_CHANNEL(ADE9000_PHASE_A_NR),		      \
+		ADE9000_ALTCURRENT_RMS_CHANNEL(ADE9000_PHASE_A_NR),	      \
+		altvoltage_rms(ADE9000_PHASE_A_NR),			      \
+		ADE9000_POWER_ACTIVE_CHANNEL(ADE9000_PHASE_A_NR),	      \
+		ADE9000_POWER_REACTIVE_CHANNEL(ADE9000_PHASE_A_NR),	      \
+		ADE9000_POWER_APPARENT_CHANNEL(ADE9000_PHASE_A_NR),	      \
+		ADE9000_ENERGY_ACTIVE_CHANNEL(ADE9000_PHASE_A_NR,	      \
+					      ADE9000_REG_AWATTHR_LO),	      \
+		ADE9000_ENERGY_APPARENT_CHANNEL(ADE9000_PHASE_A_NR,	      \
+						ADE9000_REG_AVAHR_LO),	      \
+		ADE9000_ENERGY_REACTIVE_CHANNEL(ADE9000_PHASE_A_NR,	      \
+						ADE9000_REG_AFVARHR_LO),      \
+		ADE9000_POWER_FACTOR_CHANNEL(ADE9000_PHASE_A_NR),	      \
+		/* Phase B channels */					      \
+		ADE9000_CURRENT_CHANNEL(ADE9000_PHASE_B_NR),		      \
+		ADE9000_VOLTAGE_CHANNEL(ADE9000_PHASE_B_NR),		      \
+		ADE9000_ALTCURRENT_RMS_CHANNEL(ADE9000_PHASE_B_NR),	      \
+		altvoltage_rms(ADE9000_PHASE_B_NR),			      \
+		ADE9000_POWER_ACTIVE_CHANNEL(ADE9000_PHASE_B_NR),	      \
+		ADE9000_POWER_REACTIVE_CHANNEL(ADE9000_PHASE_B_NR),	      \
+		ADE9000_POWER_APPARENT_CHANNEL(ADE9000_PHASE_B_NR),	      \
+		ADE9000_ENERGY_ACTIVE_CHANNEL(ADE9000_PHASE_B_NR,	      \
+					      ADE9000_REG_BWATTHR_LO),	      \
+		ADE9000_ENERGY_APPARENT_CHANNEL(ADE9000_PHASE_B_NR,	      \
+						ADE9000_REG_BVAHR_LO),	      \
+		ADE9000_ENERGY_REACTIVE_CHANNEL(ADE9000_PHASE_B_NR,	      \
+						ADE9000_REG_BFVARHR_LO),      \
+		ADE9000_POWER_FACTOR_CHANNEL(ADE9000_PHASE_B_NR),	      \
+		/* Phase C channels */					      \
+		ADE9000_CURRENT_CHANNEL(ADE9000_PHASE_C_NR),		      \
+		ADE9000_VOLTAGE_CHANNEL(ADE9000_PHASE_C_NR),		      \
+		ADE9000_ALTCURRENT_RMS_CHANNEL(ADE9000_PHASE_C_NR),	      \
+		altvoltage_rms(ADE9000_PHASE_C_NR),			      \
+		ADE9000_POWER_ACTIVE_CHANNEL(ADE9000_PHASE_C_NR),	      \
+		ADE9000_POWER_REACTIVE_CHANNEL(ADE9000_PHASE_C_NR),	      \
+		ADE9000_POWER_APPARENT_CHANNEL(ADE9000_PHASE_C_NR),	      \
+		ADE9000_ENERGY_ACTIVE_CHANNEL(ADE9000_PHASE_C_NR,	      \
+					      ADE9000_REG_CWATTHR_LO),	      \
+		ADE9000_ENERGY_APPARENT_CHANNEL(ADE9000_PHASE_C_NR,	      \
+						ADE9000_REG_CVAHR_LO),	      \
+		ADE9000_ENERGY_REACTIVE_CHANNEL(ADE9000_PHASE_C_NR,	      \
+						ADE9000_REG_CFVARHR_LO),      \
+		ADE9000_POWER_FACTOR_CHANNEL(ADE9000_PHASE_C_NR),	      \
+	}
+
+ADE9000_DECLARE_CHANNELS(ade9000_channels, ADE9000_ALTVOLTAGE_RMS_CHANNEL);
+ADE9000_DECLARE_CHANNELS(ade9078_channels, ADE9000_ALTVOLTAGE_RMS_CHANNEL_NO_EVENTS);
 
 /*
  * Full-scale codes referred from the respective datasheets. These are the
@@ -650,6 +682,15 @@ static const struct ade9000_chip_info ade9000_chip_info = {
 	.pcf_full_scale_codes = 74770000,
 };
 
+static const struct ade9000_chip_info ade9078_chip_info = {
+	.name = "ade9078",
+	.channels = ade9078_channels,
+	.num_channels = ARRAY_SIZE(ade9078_channels),
+	.rms_full_scale_codes = 52866837,
+	.watt_full_scale_codes = 20823646,
+	.pcf_full_scale_codes = 74680000,
+};
+
 static const struct reg_sequence ade9000_initialization_sequence[] = {
 	{ ADE9000_REG_PGA_GAIN, ADE9000_PGA_GAIN },
 	{ ADE9000_REG_CONFIG0, ADE9000_CONFIG0 },
@@ -1800,12 +1841,14 @@ static int ade9000_probe(struct spi_device *spi)
 
 static const struct spi_device_id ade9000_id[] = {
 	{ .name = "ade9000", .driver_data = (kernel_ulong_t)&ade9000_chip_info },
+	{ .name = "ade9078", .driver_data = (kernel_ulong_t)&ade9078_chip_info },
 	{ }
 };
 MODULE_DEVICE_TABLE(spi, ade9000_id);
 
 static const struct of_device_id ade9000_of_match[] = {
 	{ .compatible = "adi,ade9000", .data = &ade9000_chip_info },
+	{ .compatible = "adi,ade9078", .data = &ade9078_chip_info },
 	{ }
 };
 MODULE_DEVICE_TABLE(of, ade9000_of_match);
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v2 4/4] docs: iio: ade9000: document ADE9078 support
  2026-07-31  8:29 [PATCH v2 0/4] iio: adc: ade9000: add support for ADE9078 Antoniu Miclaus
                   ` (2 preceding siblings ...)
  2026-07-31  8:29 ` [PATCH v2 3/4] iio: adc: ade9000: add support for ADE9078 Antoniu Miclaus
@ 2026-07-31  8:29 ` Antoniu Miclaus
  3 siblings, 0 replies; 7+ messages in thread
From: Antoniu Miclaus @ 2026-07-31  8:29 UTC (permalink / raw)
  To: Antoniu Miclaus, Nuno Sá, Michael Hennerich,
	Jonathan Cameron, David Lechner, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Jonathan Corbet, Shuah Khan, Radu Sabau,
	Marcelo Schmitt, Jorge Marques, Salih Erim, Matti Vaittinen,
	Jishnu Prakash, linux-iio, linux, devicetree, linux-kernel,
	linux-doc

Add the ADE9078 to the list of supported devices and note that the
dip/swell voltage events are only available on the ADE9000.

Signed-off-by: Antoniu Miclaus <antoniu.miclaus@analog.com>
---
no changes in v2.
 Documentation/iio/ade9000.rst | 28 +++++++++++++++++-----------
 1 file changed, 17 insertions(+), 11 deletions(-)

diff --git a/Documentation/iio/ade9000.rst b/Documentation/iio/ade9000.rst
index c9ff702a4251..72737b5ec59c 100644
--- a/Documentation/iio/ade9000.rst
+++ b/Documentation/iio/ade9000.rst
@@ -1,24 +1,30 @@
 .. SPDX-License-Identifier: GPL-2.0
 
-===============
-ADE9000 driver
-===============
+======================
+ADE9000/ADE9078 driver
+======================
 
-This driver supports Analog Device's ADE9000 energy measurement IC on SPI bus.
+This driver supports Analog Device's ADE9000 and ADE9078 energy measurement
+ICs on SPI bus.
 
 1. Supported devices
 ====================
 
 * `ADE9000 <https://www.analog.com/media/en/technical-documentation/data-sheets/ADE9000.pdf>`_
-
-The ADE9000 is a highly accurate, fully integrated, multiphase energy and power
-quality monitoring device. Superior analog performance and a digital signal
-processing (DSP) core enable accurate energy monitoring over a wide dynamic
-range. An integrated high end reference ensures low drift over temperature
-with a combined drift of less than ±25 ppm/°C maximum for the entire channel
-including a programmable gain amplifier (PGA) and an analog-to-digital
+* `ADE9078 <https://www.analog.com/media/en/technical-documentation/data-sheets/ADE9078.pdf>`_
+
+The ADE9000 and ADE9078 are highly accurate, fully integrated, multiphase energy
+and power quality monitoring devices. Superior analog performance and a digital
+signal processing (DSP) core enable accurate energy monitoring over a wide
+dynamic range. An integrated high end reference ensures low drift over
+temperature with a combined drift of less than ±25 ppm/°C maximum for the entire
+channel including a programmable gain amplifier (PGA) and an analog-to-digital
 converter (ADC).
 
+The ADE9078 does not provide the on-chip dip/swell (sag) detection available on
+the ADE9000, so the RMS voltage swell/dip events described below are only
+available on the ADE9000.
+
 2. Device attributes
 ====================
 
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH v2 2/4] dt-bindings: iio: adc: adi,ade9000: add adi,ade9078 compatible
  2026-07-31  8:29 ` [PATCH v2 2/4] dt-bindings: iio: adc: adi,ade9000: add adi,ade9078 compatible Antoniu Miclaus
@ 2026-07-31  8:39   ` sashiko-bot
  0 siblings, 0 replies; 7+ messages in thread
From: sashiko-bot @ 2026-07-31  8:39 UTC (permalink / raw)
  To: Antoniu Miclaus; +Cc: conor+dt, robh, devicetree

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:

Pre-existing issues:
- [High] The IIO channels for Phase B and Phase C have overlapping `scan_index` values, causing them to conflict in the IIO buffer and preventing correct channel configuration.
- [High] The IRQ1 handler loop stops at bit 24, completely ignoring Phase C dip events (`ADE9000_ST1_DIPC_BIT`) which are located at bit 25.
--

--- Patch [2]: [PATCH v2 2/4] dt-bindings: iio: adc: adi,ade9000: add adi,ade9078 compatible ---
commit fea768d482e94a570394d820d69e5c756bc56362
Author: Antoniu Miclaus <antoniu.miclaus@analog.com>

dt-bindings: iio: adc: adi,ade9000: add adi,ade9078 compatible

This commit adds the ADE9078 compatible string to the ADE9000 binding and
lowers the maximum spi frequency for the new variant.

> The ADE9078 is a polyphase energy metering device from the same family as
> the ADE9000. It is register-compatible with the ADE9000 but does not
> provide the on-chip dip/swell detection and is limited to a 10 MHz SPI
> clock.

[Severity: High]
This isn't a bug introduced by this patch, but while reviewing the ADE9000
driver family, I noticed a potential conflict with the channel
configurations.

Looking at drivers/iio/adc/ade9000.c:

#define ADE9000_CURRENT_CHANNEL(num) { \
...
	.scan_index = num,
...
#define ADE9000_VOLTAGE_CHANNEL(num) { \
...
	.scan_index = num + 1, /* interleave with current channels */

Does this cause Phase A Voltage (index 1) to conflict with Phase B Current
(index 1), and Phase B Voltage (index 2) to conflict with Phase C Current
(index 2)?

When a user enables Phase B or C channels via sysfs, it seems this could
cause the active_scan_mask to map to the wrong bits. Could this lead to
an unsupported combination of scans or incorrect channel configuration in
ade9000_waveform_buffer_config():

	bitmap_to_arr32(&active_scans, indio_dev->active_scan_mask,
			iio_get_masklength(indio_dev));

	switch (active_scans) {
	case ADE9000_SCAN_POS_IA | ADE9000_SCAN_POS_VA:


[Severity: High]
This is also a pre-existing issue, but I noticed a potential problem with
the Phase C dip detection logic.

Looking at drivers/iio/adc/ade9000.c:

#define ADE9000_ST1_CROSSING_DEPTH	25
...
#define ADE9000_ST1_DIPC_BIT		BIT(25)

And later in ade9000_irq1_thread():

	bitmap_from_arr32(interrupt_bits, &interrupts, ADE9000_ST1_CROSSING_DEPTH);
	for_each_set_bit_from(bit, interrupt_bits,
			      ADE9000_ST1_CROSSING_DEPTH) {
		tmp = status & BIT(bit);

Since ADE9000_ST1_CROSSING_DEPTH is 25, will these operations only handle
bits 0 through 24? Does this mean bit 25 is missed and Phase C dip events
are silently ignored when the hardware triggers an IRQ1?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260731082951.1228-1-antoniu.miclaus@analog.com?part=2

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v2 1/4] iio: adc: ade9000: introduce chip_info structure
  2026-07-31  8:29 ` [PATCH v2 1/4] iio: adc: ade9000: introduce chip_info structure Antoniu Miclaus
@ 2026-07-31  8:40   ` sashiko-bot
  0 siblings, 0 replies; 7+ messages in thread
From: sashiko-bot @ 2026-07-31  8:40 UTC (permalink / raw)
  To: Antoniu Miclaus; +Cc: devicetree, robh, conor+dt

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:

Pre-existing issues:
- [High] Hardware interrupts are requested before the device is powered up and reset.
--

--- Patch [1]: [PATCH v2 1/4] iio: adc: ade9000: introduce chip_info structure ---
commit 00acfaee941c3f163617be410fa26e35179f3ffc
Author: Antoniu Miclaus <antoniu.miclaus@analog.com>

iio: adc: ade9000: introduce chip_info structure

The driver currently hardcodes the device name and the full-scale ADC codes
used to derive the IIO scale attributes. In preparation for supporting
additional parts of the ADE9000 family, move these part-specific values
into a new struct ade9000_chip_info and retrieve it via
spi_get_device_match_data() at probe time.

> diff --git a/drivers/iio/adc/ade9000.c b/drivers/iio/adc/ade9000.c
> index c6c3ea953feae..030bb9109ab6a 100644
> --- a/drivers/iio/adc/ade9000.c
> +++ b/drivers/iio/adc/ade9000.c
[ ... ]
> @@ -1726,7 +1757,7 @@ static int ade9000_probe(struct spi_device *spi)
>  	if (ret)
>  		return ret;
>  
> -	indio_dev->name = "ade9000";
> +	indio_dev->name = st->info->name;
>  	indio_dev->info = &ade9000_info;
>  	indio_dev->modes = INDIO_DIRECT_MODE;
>  	indio_dev->setup_ops = &ade9000_buffer_ops;
> @@ -1736,8 +1767,8 @@ static int ade9000_probe(struct spi_device *spi)

[Severity: High]
This is a pre-existing issue, but could we look at the interrupt
initialization ordering here?

Hardware interrupts are requested via devm_request_threaded_irq() without
IRQF_NO_AUTOEN earlier in ade9000_probe(), before this vdd regulator is
enabled.

If an interrupt line is active (for example, pulled low by the unpowered
chip or floating) at boot time, wouldn't the unmasked handler like
ade9000_irq1_thread() run immediately?

If that happens, the handler might attempt SPI register accesses while the
chip is still unpowered. Could this lead to SPI bus errors, controller
timeouts, or reading garbage data?

If that garbage data happens to have the ADE9000_ST1_RSTDONE_BIT set, could
it prematurely complete the reset process and lead to driver initialization
failure?

>  		return dev_err_probe(&spi->dev, ret,
>  				     "Failed to get and enable vdd regulator\n");
>  
> -	indio_dev->channels = ade9000_channels;
> -	indio_dev->num_channels = ARRAY_SIZE(ade9000_channels);
> +	indio_dev->channels = st->info->channels;
> +	indio_dev->num_channels = st->info->num_channels;
>  
>  	ret = devm_iio_kfifo_buffer_setup(dev, indio_dev,
>  					  &ade9000_buffer_ops);

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260731082951.1228-1-antoniu.miclaus@analog.com?part=1

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2026-07-31  8:40 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-31  8:29 [PATCH v2 0/4] iio: adc: ade9000: add support for ADE9078 Antoniu Miclaus
2026-07-31  8:29 ` [PATCH v2 1/4] iio: adc: ade9000: introduce chip_info structure Antoniu Miclaus
2026-07-31  8:40   ` sashiko-bot
2026-07-31  8:29 ` [PATCH v2 2/4] dt-bindings: iio: adc: adi,ade9000: add adi,ade9078 compatible Antoniu Miclaus
2026-07-31  8:39   ` sashiko-bot
2026-07-31  8:29 ` [PATCH v2 3/4] iio: adc: ade9000: add support for ADE9078 Antoniu Miclaus
2026-07-31  8:29 ` [PATCH v2 4/4] docs: iio: ade9000: document ADE9078 support Antoniu Miclaus

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox