AD4030/AD4630/ADAQ4216/ADAQ4224

AD4030/AD4630/ADAQ4216/ADAQ4224 ADC Linux Driver.

Note

This is the mainlined driver (ad4030.c). An alternative out-of-tree driver is documented at AD4630.

Supported Devices

Evaluation Boards

Status

Source

Mainlined?

git

Yes

Files

Overview

The ad4030-24, ad4630-24, and similar ADCs are low noise, low power, high speed, 2 MSPS or 500 kSPS SAR ADCs. The digital features include offset correction, gain adjustment, and averaging, which offload the host processor. The user can configure the device for one of several output code formats.

Adding Linux driver support

Enabling the driver

Configure kernel with make menuconfig (alternatively use make xconfig or make qconfig)

Note

The AD4030 driver depends on CONFIG_SPI, CONFIG_GPIOLIB, CONFIG_PWM, CONFIG_REGMAP, CONFIG_IIO_BUFFER, CONFIG_IIO_BUFFER_DMA, CONFIG_IIO_BUFFER_DMAENGINE, CONFIG_IIO_TRIGGERED_BUFFER, CONFIG_SPI_OFFLOAD, and CONFIG_SPI_OFFLOAD_TRIGGER_PWM

Linux Kernel Configuration
    Device Drivers  --->
        ...
        <*>     Industrial I/O support --->
            --- Industrial I/O support
            ...
            Analog to digital converters  --->
                ...
                <*>   Analog Devices AD4030 ADC driver
                ...
            ...
        ...

Adding a device tree entry

Device tree example

// SPDX-License-Identifier: GPL-2.0
/*
 * Analog Devices ADAQ4216 without isolated power supply
 *
 * hdl_project: <ad4630_fmc/zed>
 * board_revision: <3>
 *
 * Copyright (C) 2024 Analog Devices Inc.
 */
/dts-v1/;

#include "zynq-zed.dtsi"
#include "zynq-zed-adv7511.dtsi"
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/pwm/pwm.h>

/ {
    vref: regulator-vref {
        compatible = "regulator-fixed";
        regulator-name = "fixed-supply";
        regulator-min-microvolt = <4096000>;
        regulator-max-microvolt = <4096000>;
        regulator-always-on;
    };

    vdd_1_8: regulator-vdd-1-8 {
        compatible = "regulator-fixed";
        regulator-name = "fixed-supply";
        regulator-min-microvolt = <1800000>;
        regulator-max-microvolt = <1800000>;
        regulator-always-on;
    };

    vio: regulator-vio {
        compatible = "regulator-fixed";
        regulator-name = "fixed-supply";
        regulator-min-microvolt = <1800000>;
        regulator-max-microvolt = <1800000>;
        regulator-always-on;
    };

    trigger_pwm: adc-pwm-trigger {
        compatible = "pwm-trigger";
        #trigger-source-cells = <0>;
        pwms = <&adc_trigger 0 1000000 0>;
    };

    clocks {
        cnv_ext_clk: ext-clk {
            #clock-cells = <0x0>;
            compatible = "fixed-clock";
            clock-frequency = <100000000>;
            clock-output-names = "cnv_ext_clk";
        };
    };
};

&fpga_axi {
    i2c@41620000 {
        compatible = "xlnx,axi-iic-1.01.b", "xlnx,xps-iic-2.00.a";
        reg = <0x41620000 0x10000>;
        interrupt-parent = <&intc>;
        interrupts = <0 55 IRQ_TYPE_LEVEL_HIGH>;
        clocks = <&clkc 15>;
        clock-names = "pclk";
        #size-cells = <0>;
        #address-cells = <1>;

        eeprom1: eeprom@50 {
            compatible = "at24,24c02";
            reg = <0x50>;
        };
    };

    adc_trigger: pwm@44b00000 {
        compatible = "adi,axi-pwmgen-2.00.a";
        reg = <0x44b00000 0x1000>;
        label = "ad463x_cnv";
        #pwm-cells = <3>;
        clocks = <&clkc 15>, <&cnv_ext_clk>;
        clock-names = "axi", "ext";
    };

    rx_dma: dma-controller@44a30000 {
        compatible = "adi,axi-dmac-1.00.a";
        reg = <0x44a30000 0x1000>;
        #dma-cells = <1>;
        interrupts = <0 57 IRQ_TYPE_LEVEL_HIGH>;
        clocks = <&clkc 15>;
    };

    spi_clk: clock-controller@44a70000 {
        compatible = "adi,axi-clkgen-2.00.a";
        reg = <0x44a70000 0x10000>;
        #clock-cells = <0>;
        clocks = <&clkc 15>, <&clkc 15>;
        clock-names = "clkin1", "s_axi_aclk";
        clock-output-names = "spi_clk";
    };

    axi_spi_engine: spi@44a00000 {
        compatible = "adi,axi-spi-engine-1.00.a";
        reg = <0x44a00000 0x1FF>;
        interrupt-parent = <&intc>;
        interrupts = <0 56 IRQ_TYPE_LEVEL_HIGH>;
        clocks = <&clkc 15>, <&spi_clk>;
        clock-names = "s_axi_aclk", "spi_clk";
        dmas = <&rx_dma 0>;
        dma-names = "offload0-rx";
        trigger-sources = <&trigger_pwm>;
        #address-cells = <0x1>;
        #size-cells = <0x0>;

        adaq4216: adaq4216@0 {
            compatible = "adi,adaq4216";
            reg = <0>;
            spi-max-frequency = <80000000>;
            vdd-5v-supply = <&vref>;
            vdd-1v8-supply = <&vdd_1_8>;
            vio-supply = <&vio>;
            ref-supply = <&vref>;
            pwm-names = "cnv";
            pwms = <&adc_trigger 1 1000000 0>;
            reset-gpios = <&gpio0 86 GPIO_ACTIVE_LOW>;
            cnv-gpios = <&gpio0 85 GPIO_ACTIVE_HIGH>;
            pga-gpios = <&gpio0 87 GPIO_ACTIVE_HIGH>,
                    <&gpio0 88 GPIO_ACTIVE_HIGH>;
        };
    };
};

Driver testing

Each and every IIO device, typically a hardware chip, has a device folder under /sys/bus/iio/devices/iio:deviceX. Where X is the IIO index of the device. Under every of these directory folders reside a set of files, depending on the characteristics and features of the hardware device in question. These files are consistently generalized and documented in the IIO ABI documentation. In order to determine which IIO deviceX corresponds to which hardware device, the user can read the name file /sys/bus/iio/devices/iio:deviceX/name. In case the sequence in which the iio device drivers are loaded/registered is constant, the numbering is constant and may be known in advance.

Tip

An example program whiroot@analog:/sys/bus/iio/devices# ls -lch uses the interface can be found here:

Show device name

root@analog:~# cat /sys/bus/iio/devices/iio:device0/name
adaq4216

Show channel scale

Description: Scale to be applied to in_voltageX_raw in order to obtain the measured voltage in millivolts

root@analog:~# cat /sys/bus/iio/devices/iio:device0/in_voltage0-voltage1_scale
0.018750000

Example test single-shot readings through IIO device sysfs interface.

root@analog:~# ls -l /sys/bus/iio/devices/iio:device0/
total 0
drwxr-xr-x 2 root root    0 Feb  4 19:03 buffer
drwxr-xr-x 2 root root    0 Feb  4 19:03 buffer0
-r--r--r-- 1 root root 4096 Feb  4 19:03 dev
-rw-r--r-- 1 root root 4096 Feb  4 19:03 in_voltage0-voltage1_calibbias
-r--r--r-- 1 root root 4096 Feb  4 19:03 in_voltage0-voltage1_calibbias_available
-rw-r--r-- 1 root root 4096 Feb  4 19:03 in_voltage0-voltage1_calibscale
-r--r--r-- 1 root root 4096 Feb  4 19:03 in_voltage0-voltage1_calibscale_available
-r--r--r-- 1 root root 4096 Feb  4 19:03 in_voltage0-voltage1_label
-rw-r--r-- 1 root root 4096 Feb  4 19:03 in_voltage0-voltage1_raw
-rw-r--r-- 1 root root 4096 Feb  4 19:03 in_voltage0-voltage1_scale
-r--r--r-- 1 root root 4096 Feb  4 19:03 in_voltage0-voltage1_scale_available
-r--r--r-- 1 root root 4096 Feb  4 19:03 name
lrwxrwxrwx 1 root root    0 Feb  4 19:03 of_node -> ../../../../../../../../firmware/devicetree/base/fpga-axi@0/spi@44a00000/adaq4216@0
-rw-r--r-- 1 root root 4096 Feb  4 19:03 oversampling_ratio
-r--r--r-- 1 root root 4096 Feb  4 19:03 oversampling_ratio_available
drwxr-xr-x 2 root root    0 Feb  4 19:03 power
-rw-r--r-- 1 root root 4096 Feb  4 19:03 sampling_frequency
drwxr-xr-x 2 root root    0 Feb  4 19:03 scan_elements
lrwxrwxrwx 1 root root    0 Feb  4 19:03 subsystem -> ../../../../../../../../bus/iio
-rw-r--r-- 1 root root 4096 Feb  4 19:03 uevent
-r--r--r-- 1 root root 4096 Feb  4 19:03 waiting_for_supplier

Application Software

Analog Devices ADAQ4003 can be easily managed with IIO Oscilloscope which has interfaces for configuring and retrieving data from IIO devices. After installing IIO Oscilloscope in the host computer, open the application and connect to the IIO context provided by the Kuiper Linux installation running on the ZedBoard.

The example below shows ADAQ4216 running a 125 kSPS data capture of a test sine wave. 1000 samples were kept for the plot.

https://wiki.analog.com/_media/resources/tools-software/linux-drivers/iio-adc/ad4030/adaq4216_125ksps_capture.png

The example below shows the same sine wave but captured at 500 kSPS.

https://wiki.analog.com/_media/resources/tools-software/linux-drivers/iio-adc/ad4030/adaq4216_500ksps_capture.png

Finally, at 2 MSPS, we keep a larger number of samples to be able to visualize the sine wave captured with ADAQ4216.

https://wiki.analog.com/_media/resources/tools-software/linux-drivers/iio-adc/ad4030/adaq4216_2msps_capture.png

More Information