[PATCH v2 3/4] iio: adc: ade9000: add support for ADE9078
Antoniu Miclaus <[email protected]> Fri, 31 Jul 2026 11:29:49 +0300
| Newsgroups | org.kernel.vger.linux-iio,org.kernel.vger.linux-devicetree,org.kernel.vger.linux-doc,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
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 <[email protected]> --- 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