Wiki

This version (01 Feb 2024 21:48) was approved by Marcelo Schmitt.The Previously approved version (01 Feb 2024 21:24) is available.Diff

AD4003/AD4007/AD4011/AD4020/ADAQ4001/ADAQ4003 Linux Driver

Supported Devices

Evaluation Boards

Description

Analog Devices AD4000 and the above listed devices are high accuracy, high speed, low power SAR ADCs.

This is the Linux industrial I/O (IIO) subsystem driver, targeting single channel SPI interface AD4000 and similar ADC devices. The industrial I/O subsystem provides a unified framework for drivers for many different types of converters and sensors using a number of different physical interfaces (I2C, SPI, etc). See IIO for more information.

See the Evaluating AD400X and ADAQ400X devices user guide for instructions on how to setup and evaluate devices supported by the ad400x Linux driver.

Status

Source Mainlined?
git [No]

Files

Driver setup

Since AD4003/4007/4011/4020 are high speed analog-to-digital converters with speeds up to 2 MSPS, additional components are required to achieve high performance. In this scenario, the following HDL components are required:

The device will interface with these components and follow the device tree bindings.

This specifies any shell prompt running on the target

properties:
  compatible:
    enum:
      - adi,ad4000
      - adi,ad4001
      - adi,ad4002
      - adi,ad4003
      - adi,ad4004
      - adi,ad4005
      - adi,ad4006
      - adi,ad4007
      - adi,ad4008
      - adi,ad4010
      - adi,ad4011
      - adi,ad4020
      - adi,ad4021
      - adi,ad4022
      - adi,adaq4003

  reg: true
  spi-max-frequency: true

  dmas:
    description: |
      DMA specifier, consisting of a phandle to DMA controller node.
    maxItems: 1

  dma-names:
    const: rx

  clocks:
    maxItems: 1

  clock-names:
    const: ref_clk
    description: AD400X reference clock name.

  pwms:
    description: |
      PWM used as trigger source for the SPI engine, also represents the
      acquisition rate for the samples.
    maxItems: 1

  pwm-names:
    const: cnv

  vref-supply:
    description: Phandle to the regulator for ADC reference voltage.

  '#address-cells':
    const: 1

  '#size-cells':
    const: 0

patternProperties:
  "^channel@([0-1])$":
    $ref: adc.yaml
    type: object
    description: Represents the external channel connected to the ADC.

    properties:
      reg:
        maxItems: 1

      diff-channels: true

    required:
      - reg

    additionalProperties: false

required:
  - compatible
  - reg
  - dmas
  - dma-names
  - vref-supply

allOf:
  - $ref: /schemas/spi/spi-peripheral-props.yaml#

  - if:
      properties:
        compatible:
          contains:
            enum:
              - adi,adaq4003

    then:
      required:
        - compatible
        - reg
        - dmas
        - dma-names
        - clocks
        - clock-names
        - pwms
        - pwm-names
        - vref-supply

unevaluatedProperties: false

examples:
  - |
    spi {
        #address-cells = <1>;
        #size-cells = <0>;
        /* Example for a AD400X devices */
        adc@0 {
            compatible = "adi,ad4020";
            reg = <0>;
            spi-max-frequency = <71000000>;
            vref-supply = <&vref>;

            dmas = <&rx_dma 0>;
            dma-names = "rx";

            #address-cells = <1>;
            #size-cells = <0>;

            channel@0 {
                reg = <0>;
                diff-channels = <0 1>;
            };
        };
    };
  - |
    spi {
        #address-cells = <1>;
        #size-cells = <0>;

        /* Example for a ADAQ400X devices */
        adc@0 {
            compatible = "adi,adaq4003";
            reg = <0>;
            spi-max-frequency = <80000000>;
            dmas = <&rx_dma 0>;
            dma-names = "rx";
            clocks = <&spi_clk>;
            clock-names = "ref_clk";
            pwms = <&adc_trigger 0 0>;
            pwm-names = "cnv";
            vref-supply = <&vref>;

            #address-cells = <1>;
            #size-cells = <0>;

            channel@0 {
                reg = <0>;
                diff-channels = <0 1>;
            };
        };
    };

See the Evaluating AD400X and ADAQ400X devices user guide for examples of device trees used with devices supported by the ad400x Linux driver.

Adding Linux driver support

Enabling the driver

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

The AD400x driver depends on CONFIG_SPI_MASTER

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

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.

02 Mar 2011 15:16

TIP: An example program which uses the interface can be found here:


This specifies any shell prompt running on the target

root@analog:~# ls -l /sys/bus/iio/devices/
total 0
lrwxrwxrwx 1 root root 0 Apr  2 21:42 iio:device0 -> ../../../devices/soc0/axi/f8007100.adc/iio:device0
lrwxrwxrwx 1 root root 0 Apr  2 21:43 iio:device1 -> ../../../devices/soc0/fpga-axi@0/44a00000.spi/spi_master/spi0/spi0.0/iio:device1
lrwxrwxrwx 1 root root 0 Apr  2 21:42 iio_sysfs_trigger -> ../../../devices/iio_sysfs_trigger

root@analog:~# ls -l /sys/bus/iio/devices/iio:device1/
total 0
drwxr-xr-x 2 root root    0 Apr  2 21:43 buffer
drwxr-xr-x 2 root root    0 Apr  2 21:43 buffer0
-r--r--r-- 1 root root 4096 Apr  2 21:43 dev
-rw-r--r-- 1 root root 4096 Apr  2 21:43 in_voltage0_offset
-rw-r--r-- 1 root root 4096 Apr  2 21:43 in_voltage0_raw
-rw-r--r-- 1 root root 4096 Apr  2 21:43 in_voltage0_scale
-r--r--r-- 1 root root 4096 Apr  2 21:43 name
lrwxrwxrwx 1 root root    0 Apr  2 21:43 of_node -> ../../../../../../../../firmware/devicetree/base/fpga-axi@0/spi@44a00000/adc@0
drwxr-xr-x 2 root root    0 Apr  2 21:43 power
-rw-r--r-- 1 root root 4096 Apr  2 21:43 sampling_frequency
drwxr-xr-x 2 root root    0 Apr  2 21:43 scan_elements
lrwxrwxrwx 1 root root    0 Apr  2 21:43 subsystem -> ../../../../../../../../bus/iio
-rw-r--r-- 1 root root 4096 Apr  2 21:43 uevent

Show device name

This specifies any shell prompt running on the target

root@analog:~# cat /sys/bus/iio/devices/iio:device1/name
adaq4003

Show channel scale

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

This specifies any shell prompt running on the target

root@analog:~# cat /sys/bus/iio/devices/iio:device1/in_voltage0_scale
0.019073486

Configure sampling rate

Description: /sys/bus/iio/devices/iio:deviceX/sampling_frequency
Configures the input sampling rate.

This specifies any shell prompt running on the target

root@analog:~# cat /sys/bus/iio/devices/iio:device1/sampling_frequency
2000000

This specifies any shell prompt running on the target

root@analog:~# echo 1000000 > /sys/bus/iio/devices/iio:device1/sampling_frequency
root@analog:~# cat /sys/bus/iio/devices/iio:device1/sampling_frequency
1000000

Buffer management

This specifies any shell prompt running on the target

root@analog:~# ls -l /sys/bus/iio/devices/iio:device1/buffer/
total 0
-r--r--r-- 1 root root 4096 Apr  3 08:11 data_available
-r--r--r-- 1 root root 4096 Apr  3 08:11 direction
-rw-r--r-- 1 root root 4096 Apr  3 08:11 enable
-rw-r--r-- 1 root root 4096 Apr  3 08:11 length
-r--r--r-- 1 root root 4096 Apr  3 08:11 length_align_bytes
-r--r--r-- 1 root root 4096 Apr  3 08:11 watermark

The Industrial I/O subsystem provides support for various ring buffer based data acquisition methods. Apart from device specific hardware buffer support, the user can chose between two different software ring buffer implementations. One is the IIO lock free software ring, and the other is based on Linux kfifo. Devices with buffer support feature an additional sub-folder in the /sys/bus/iio/devices/deviceX/ folder hierarchy. Called deviceX:bufferY, where Y defaults to 0, for devices with a single buffer.

Every buffer implementation features a set of files:

length
Get/set the number of sample sets that may be held by the buffer.

enable
Enables/disables the buffer. This file should be written last, after length and selection of scan elements.

watermark
A single positive integer specifying the maximum number of scan elements to wait for. Poll will block until the watermark is reached. Blocking read will wait until the minimum between the requested read amount or the low water mark is available. Non-blocking read will retrieve the available samples from the buffer even if there are less samples then watermark level. This allows the application to block on poll with a timeout and read the available samples after the timeout expires and thus have a maximum delay guarantee.

data_available
A read-only value indicating the bytes of data available in the buffer. In the case of an output buffer, this indicates the amount of empty space available to write data to. In the case of an input buffer, this indicates the amount of data available for reading.

length_align_bytes
Using the high-speed interface. DMA buffers may have an alignment requirement for the buffer length. Newer versions of the kernel will report the alignment requirements associated with a device through the `length_align_bytes` property.

scan_elements
The scan_elements directory contains interfaces for elements that will be captured for a single triggered sample set in the buffer.

02 Mar 2011 15:16

This specifies any shell prompt running on the target

root@analog:~# ls -l /sys/bus/iio/devices/iio:device1/scan_elements/
total 0
-rw-r--r-- 1 root root 4096 Apr  3 08:11 in_voltage0_en
-r--r--r-- 1 root root 4096 Apr  3 08:11 in_voltage0_index
-r--r--r-- 1 root root 4096 Apr  3 08:11 in_voltage0_type

in_voltageX_en / in_voltageX-voltageY_en / timestamp_en:
Scan element control for triggered data capture. Writing 1 will enable the scan element, writing 0 will disable it

in_voltageX_type / in_voltageX-voltageY_type / timestamp_type:
Description of the scan element data storage within the buffer and therefore in the form in which it is read from user-space. Form is [s|u]bits/storage-bits. s or u specifies if signed (2's complement) or unsigned. bits is the number of bits of data and storage-bits is the space (after padding) that it occupies in the buffer. Note that some devices will have additional information in the unused bits so to get a clean value, the bits value must be used to mask the buffer output value appropriately. The storage-bits value also specifies the data alignment. So u12/16 will be a unsigned 12 bit integer stored in a 16 bit location aligned to a 16 bit boundary. For other storage combinations this attribute will be extended appropriately.

in_voltageX_index / in_voltageX-voltageY_index / timestamp_index:
A single positive integer specifying the position of this scan element in the buffer. Note these are not dependent on what is enabled and may not be contiguous. Thus for user-space to establish the full layout these must be used in conjunction with all _en attributes to establish which channels are present, and the relevant _type attributes to establish the data storage format.

02 Mar 2011 15:16

This specifies any shell prompt running on the target

root@analog:/sys/bus/iio/devices/iio:device1/scan_elements# grep "" *
in_voltage0_en:0
in_voltage0_index:0
in_voltage0_type:le:s18/32>>0

Buffer Example

When the buffer is enabled, the ad400x driver prepares a read transfer and configures the SPI Engine Offload module to repeat that transfer each time the offload module is triggered. Then, the ad400x driver sets a PWM device to trigger the offload module at the rate specified by the sampling_frequency attribute. With that, ADC readings are gathered continuously while the buffer remains enabled.

This specifies any shell prompt running on the target - Example command sequence

root@analog:~# echo 1 > /sys/bus/iio/devices/iio:device1/scan_elements/in_voltage0_en
root@analog:~# cat /sys/bus/iio/devices/iio:device1/scan_elements/in_voltage0_en
1
root@analog:~# echo 1 > /sys/bus/iio/devices/iio:device1/buffer/enable
root@analog:~# cat /sys/bus/iio/devices/iio:device1/buffer/data_available
32768

Data interpretation

Each buffer entry contains one sample. The amount of bits and their meaning will vary according to ADC precision and output code pattern (whether output code is twos complement or not). Buffer raw data may be retrieved by reading the character device associated with the ADC device.

This specifies any shell prompt running on the target

root@analog:~# hexdump -n 512 -e ' 32 "%d " "\n"' /dev/iio:device1
4864 4889 4730 4716 4695 4678 4667 4659 4662 4676 4706 4738 4770 4789 4786 4785 4775 4763 4752 4737 4723 4703 4686 4673 4666 4672 4688 4715 4762 4799 4820 4821
4816 4807 4788 4773 4757 4737 4718 4694 4676 4664 4668 4692 4727 4777 4814 4837 4836 4829 4822 4808 4796 4771 4748 4728 4707 4685 4664 4654 4651 4659 4675 4709
4757 4801 4823 4826 4812 4800 4789 4770 4749 4724 4700 4677 4653 4644 4633 4639 4659 4695 4738 4777 4798 4799 4794 4785 4772 4755 4735 4712 4692 4668 4652 4646
4641 4648 4674 4709 4753 4793 4817 4818 4808 4797 4780 4764 4748 4724 4699 4674 4656 4639 4627 4633 4644 4677 4716 4765 4794 4804 4801 4791 4778 4763 4744 4721

Remove the -n parameter to keep reading the buffer continuously. To stop capture, disable the buffer by writing 0 to /sys/bus/iio/devices/iio:device1/buffer/enable.

More Information

resources/tools-software/linux-drivers/iio-adc/ad400x.txt · Last modified: 01 Feb 2024 21:48 by Marcelo Schmitt