AD4630
AD4630-24/AD4630-16 Dual Channel and AD4030-24 Single Channel Precision SAR ADC Linux Driver.
Note
A mainlined alternative driver is available at AD4030/AD4630/ADAQ4216/ADAQ4224. This page documents the out-of-tree driver (ad4630.c).
Supported Devices
Evaluation Boards
Carrier |
Evaluation Board |
User Guide |
|---|---|---|
Description
The AD4630-24 is a two-channel, low-noise, 2 MSPS successive approximation register (SAR) analog-to-digital converter (ADC). The AD4030-24 is the single channel version. Both have a guaranteed maximum ±0.9 ppm INL and no missing codes at 24-bits, and achieve unparalleled precision from −40°C to +125°C. The AD4630-16 is a 16-bit, two-channel version.
Operating from 5V and 1.8 V supplies, the AD4630-24, AD4630-16 and AD4030-24 has a ±(65/64 ·VREF) differential input range with VREF ranging from 4.096V to 5V. The input common mode is not restricted – each polarity input may be anywhere from - 1/128 ·VREF to 129/128 ·VREF, simplifying analog signal conditioning requirements and system calibration. A low drift, precision reference buffer makes it easy to share a voltage reference with other circuitry.
The versatile Flexi-SPI serial interface is simple to use. A wide data window, multiple SDO lanes, and optional DDR data can reduce the serial clock to 10 MHz at 2 MSPS. Echo-clock and ADC clock-master modes relax the timing requirements and simplify the use of digital isolators. The parts are compatible with 1.2V to 1.8V logic, using the separate VIO supply.
Source Code
Status
Source |
Mainlined? |
|---|---|
[No] |
Files
Function |
File |
|
|---|---|---|
driver |
||
devicetree |
===== Devicetree =====
Regulator
ADC voltage reference
vref: regulator-vref {
compatible = "regulator-fixed";
regulator-name = "fixed-supply";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
regulator-always-on;
};
External clock
Reference clock used for sampling timing
clocks {
cnv_ext_clk: ext-clk {
#clock-cells = <0x0>;
compatible = "fixed-clock";
clock-frequency = <100000000>;
clock-output-names = "cnv_ext_clk";
};
};
Sampling trigger
This PWM generator is used to start the sampling procedure
axi_pwm_gen: axi-pwm-gen@ {
compatible = "adi,axi-pwmgen";
reg = <0x44b00000 0x1000>;
label = "ad463x_cnv";
#pwm-cells = <2>;
clocks = <&cnv_ext_clk>;
};
ADC node
The ad4630-24 is a SPI-compatible ADC so it should be under a SPI controller. The following custom attributes are available:
Attribute name |
Values |
Description |
|---|---|---|
|
one-lane-shared one-lane-per-ch two-lanes-per-ch four-lanes-per-ch |
Use one data lane, interleaved Use two data lanes, one per ch. Use four data lanes, two per ch. Use eight data lanes, four per ch. |
|
spi-compatible echo-clock |
Valid BUSY signal for the ADC conversion status Bit clock. BUSY_SCKOUT is a delayed version of SCK input |
|
16diff-8com 24diff 24diff-8com 30diff-avg 32pat |
Output is 16-bit differential data + 8-bit common mode data Output is 24-bit differential data Output is 24-bit differential data + 8-bit common mode data Output is 30-bit averaged differential data + OR-bit + SYNC-bit Output is 32-bit test data pattern |
Important
The spi-max-frequency must be a multiple of a 40MHz clock and the
dmas handle should use a 64-bit wide data bus.
&spi{
ad463x: ad463x@0 {
compatible = "adi,ad4630-24";
reg = <0>;
vref-supply = <&vref>;
spi-max-frequency = <80000000>;
adi,lane-mode = <2>;
adi,clock-mode = <1>;
adi,dual-data-rate;
adi,out-data-mode = <2>;
reset-gpios = <&gpio0 86 GPIO_ACTIVE_LOW>;
clocks = <&cnv_ext_clk>;
clock-names = "trigger_clock";
dmas = <&rx_dma 0>;
dma-names = "rx";
pwm-names = "spi_trigger", "cnv";
pwms = <&axi_pwm_gen 0 0>,
<&axi_pwm_gen 1 0>;
};
};
adi,lane-mode is 0 for one lane per channel, 1 for two, 2 for four, or 3
for interleaved lanes on SDO0. adi,clock-mode is 0 for SPI-compatible
clocking, 1 for echo-clock, or 2 for host clock mode. adi,out-data-mode is
0 for native (16/20/24-bit depending on part) differential data, 1 for 16-bit
differential plus 8-bit common mode, 2 for 24-bit differential plus 8-bit
common mode, or 3 for 30-bit averaged differential data; which values are
valid depends on the specific part.
Adding Linux driver support
Kernel configuration
This device depends on a PWM based trigger used to start the sampling procedure. The first step is to enable the support for AXI_PWMGEN.
<blockquote>
Symbol: PWM_AXI_PWMGEN [=y]
Type : tristate
Prompt: Analog Devices AXI PWM generator
Location:
-> Device Drivers
-> Pulse-Width Modulation (PWM) Support (PWM [=y])
Defined at drivers/pwm/Kconfig:78
Depends on: PWM [=y] && HAS_IOMEM [=y]
Selected by [y]:
- KERNEL_ALL_ADI_DRIVERS [=y]
</blockquote>
Another required component is the SPI controller. The AD4630 has a specific set of SPI timing requirements that are supported by the SPI_ENGINE IP.
<blockquote>
Symbol: SPI_AXI_SPI_ENGINE [=y]
Type : tristate
Prompt: Analog Devices AXI SPI Engine controller
Location:
-> Device Drivers
-> SPI support (SPI [=y])
Defined at drivers/spi/Kconfig:112
Depends on: SPI [=y] && SPI_MASTER [=y] && HAS_IOMEM [=y]
Selected by [y]:
- KERNEL_ALL_ADI_DRIVERS [=y]
</blockquote>
And finally, enable support for the AD4630 device family.
<blockquote>
Symbol: AD4630 [=y]
Type : tristate
Prompt: Analog Device AD4630 ADC Driver
Location:
-> Device Drivers
-> Industrial I/O support (IIO [=y])
-> Analog to digital converters
Defined at drivers/iio/adc/Kconfig:26
Depends on: IIO [=y] && SPI_MASTER [=y]
Selects: IIO_BUFFER [=y] && IIO_BUFFER_DMA [=y] && IIO_BUFFER_DMAENGINE [=y]
</blockquote>
Driver testing
This device can be found under /sys/bus/iio/devices/
Each channel is a plain indexed voltage channel (not a differential pair in
the IIO sense), with its own calibbias and calibscale attributes.
in_voltage_scale and sampling_frequency are shared by all channels. In
the 30-bit averaged output mode (adi,out-data-mode = <3>), channels also
expose in_voltage_oversampling_ratio and
in_voltage_oversampling_ratio_available.
Use iio_info to list the channels and attributes of the device.
You can go to the device folder using:
root@analog# cd $(grep -rw /sys/bus/iio/devices//name -e "ad4630-24" -l | xargs dirname)
Power management
The driver uses runtime power management; power transitions are handled by its runtime suspend and resume callbacks.
Sampling frequency
The AD4630 driver supports a variable sampling rate, up to 2 MSPS depending on
the part and output data mode. sampling_frequency accepts any positive
integer rate up to the device maximum and programs the CNV PWM accordingly;
there is no sampling_frequency_available attribute.
See current sampling rate:
root@analog:/sys/bus/iio/devices/iio:device0# cat sampling_frequency
1000000
Change the sampling rate:
root@analog:/sys/bus/iio/devices/iio:device0# echo 2000000 > sampling_frequency
root@analog:/sys/bus/iio/devices/iio:device0# cat sampling_frequency
2000000
Sample average mode
The AD4630 family supports averaging samples in powers of 2, up to 65536,
when the output data mode is 30-bit averaged (adi,out-data-mode = <3>).
This is controlled through in_voltage_oversampling_ratio and
in_voltage_oversampling_ratio_available; after probe the driver sets an
averaging count of 2 as its default. Increasing the averaging count lengthens
the internal fetch period relative to the conversion trigger, so buffer read
timeouts may need to be increased accordingly.
root@analog:/sys/bus/iio/devices/iio:device0# cat in_voltage_oversampling_ratio_available
1 2 4 8 16 32 64 128 256 512 1024 2048 4096 8192 16384 32768 65536
Display current averaging count:
root@analog:/sys/bus/iio/devices/iio:device0# cat in_voltage_oversampling_ratio
2
Change the averaging count:
root@analog:/sys/bus/iio/devices/iio:device0# echo 2048 > in_voltage_oversampling_ratio
root@analog:/sys/bus/iio/devices/iio:device0# cat in_voltage_oversampling_ratio
2048
Channel hardware gain
Each channel has an independent calibscale attribute for gain correction,
accepting values from 0 up to 1.99997 in steps of 1/32768. This gain
correction is separate from in_voltage_scale, which converts raw codes to
a voltage.
root@analog:/sys/bus/iio/devices/iio:device0# ls | grep calibscale
in_voltage0_calibscale
in_voltage1_calibscale
Read the gain for channel 0:
root@analog:/sys/bus/iio/devices/iio:device0# cat in_voltage0_calibscale
1.000000
Set the gain for channel 1:
root@analog:/sys/bus/iio/devices/iio:device0# echo 0.25 > in_voltage1_calibscale
root@analog:/sys/bus/iio/devices/iio:device0# cat in_voltage1_calibscale
0.250000
Channel offset
Each channel has an independent calibbias attribute. For a 24-bit part the
accepted range is -223 to 223-1; 16-bit and 20-bit parts use
the corresponding signed range for their bit width. Calibration writes require
the device to be in direct (non-buffered) mode.
root@analog:/sys/bus/iio/devices/iio:device0# ls | grep calibbias
in_voltage0_calibbias
in_voltage1_calibbias
Read the offset for channel 0:
root@analog:/sys/bus/iio/devices/iio:device0# cat in_voltage0_calibbias
0
Set the offset for channel 1:
root@analog:/sys/bus/iio/devices/iio:device0# echo 256 > in_voltage1_calibbias
root@analog:/sys/bus/iio/devices/iio:device0# cat in_voltage1_calibbias
256
Data acquisition
The data acquisition is performed using a buffer system:
root@analog:/sys/bus/iio/devices/iio:device0/# ls buffer
data_available enable length length_align_bytes watermark
root@analog:/sys/bus/iio/devices/iio:device0# ls scan_elements/
in_voltage0_en in_voltage0_type in_voltage1_index
in_voltage0_index in_voltage1_en in_voltage1_type
Every buffer implementation features a set of files:
buffer: length Get/set the number of sample sets that may be held by the buffer.
buffer: enable Enables/disables the buffer. This file should be written last, after length and selection of scan elements
scan_elements: in_voltageX_en Enable/disables the channel output so the data won’t be buffered for that specific channel.
Each scan is 32 bits per enabled channel. With both channels enabled, 400
scans require 3200 bytes; the hexdump -n 400 below therefore only reads
the first 50 scans.
root@analog:/sys/bus/iio/devices/iio:device0# echo 1 > scan_elements/in_voltage0_en
root@analog:/sys/bus/iio/devices/iio:device0# echo 1 > scan_elements/in_voltage1_en
root@analog:/sys/bus/iio/devices/iio:device0# echo 400 > buffer/length
root@analog:/sys/bus/iio/devices/iio:device0# echo 1 > buffer/enable
root@analog:/sys/bus/iio/devices/iio:device0# hexdump -n 400 /dev/iio\:device0
0000000 e942 000d 0011 0000 afaf 000d 0029 0000
0000010 753b 000d fff5 00ff 39fa 000d 0018 0000
0000020 013e 000d 0017 0000 c776 000c fff4 00ff
0000030 8e84 000c 0017 0000 55d4 000c 0052 0000
0000040 1dab 000c 000b 0000 e5b9 000b 0049 0000
0000050 ab19 000b 0013 0000 6f56 000b 0035 0000
0000060 3470 000b 0020 0000 f9a1 000a 0037 0000
0000070 bcc1 000a 0003 0000 7f89 000a 000d 0000
0000080 4458 000a 0003 0000 0978 000a 000d 0000
0000090 cea9 0009 0041 0000 9551 0009 fff2 00ff
00000a0 5b80 0009 fff1 00ff 210c 0009 0015 0000
00000b0 e486 0008 ffe8 00ff a8d1 0008 ffec 00ff
00000c0 6e13 0008 004e 0000 33a0 0008 001a 0000
00000d0 f7df 0007 fffd 00ff bba2 0007 fffd 00ff
00000e0 7ead 0007 fffe 00ff 43e0 0007 0041 0000
00000f0 08a8 0007 0023 0000 cc9c 0006 ffed 00ff
0000100 9031 0006 001c 0000 5370 0006 fff6 00ff
0000110 1721 0006 0040 0000 dcec 0005 ffe5 00ff
0000120 9ffc 0005 000d 0000 61f3 0005 0016 0000
0000130 247d 0005 0023 0000 e55d 0004 0006 0000
0000140 a725 0004 000e 0000 6d7b 0004 0045 0000
0000150 32e4 0004 ffaa 00ff f77e 0003 ffca 00ff
0000160 bc75 0003 0036 0000 809d 0003 0019 0000
0000170 4582 0003 ffe1 00ff 0921 0003 ffdf 00ff
0000180 c9a5 0002 ffd1 00ff 8a1c 0002 0015 0000
0000190
root@analog:/sys/bus/iio/devices/iio:device0/# echo 0 > buffer/enable
Debug mode
You can write and read the ADC registers using debugfs. Here we will read and write the scratchpad register:
First go to the device debug folder:
root@analog# cd /sys/kernel/debug/iio/iio:device0
Read the 0xA register:
root@analog:/sys/kernel/debug/iio/iio:device0# echo 0xA > direct_reg_access
root@analog:/sys/kernel/debug/iio/iio:device0# cat direct_reg_access
0x0
Write and verify the value:
root@analog:/sys/kernel/debug/iio/iio:device0# echo 0xA 0x5F> direct_reg_access
root@analog:/sys/kernel/debug/iio/iio:device0# cat direct_reg_access
0x5F