AD5791
AD5791 IIO DAC Linux Driver.
Supported Devices
Evaluation Boards
Reference Circuits
Description
This is a Linux industrial I/O (Linux Industrial I/O Subsystem) subsystem driver, targeting single-channel serial interface DACs. 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 Linux Industrial I/O Subsystem for more information.
Source Code
Status
SPI offload support was added in kernel v6.15.
SPI offload + cyclic DMA buffers is not supported in mainline yet - use ADI tree if needed
Files
Function |
File |
|---|---|
driver |
|
devicetree bindings |
Hardware configuration
Adding Linux driver support
Kernel configuration
Configure kernel with make menuconfig (alternatively use make xconfig or
make qconfig)
Note
The AD5791 Driver depends on CONFIG_SPI
Linux Kernel Configuration
Device Drivers --->
...
<*> Industrial I/O support --->
--- Industrial I/O support
...
Digital to analog converters --->
...
<*> Analog Devices AD5760/AD5780/AD5781/AD5790/AD5791 DAC SPI driver
...
...
...
Devicetree configuration
Devicetree is used to describe how the chip is wired up. The driver uses this to configure the device based on what it is connected to.
An example .dts file for the EVAL-AD5791ARDZ board can be found here.
The DAC node
Since the DAC communicates to the MCU via a SPI bus, the DAC node is a SPI peripheral node, meaning that it is a child node of the SPI controller it is connected to.
spi@0x00040000 {
compatible = "adi,axi-spi-engine-1.00.a";
reg = <0x00040000 0x00010000>;
...
#address-cells = <1>;
#size-cells = <0>;
dac@0 {
compatible = "adi,ad5791";
reg = <0>;
spi-cpha;
spi-max-frequency = <35000000>;
...
};
DAC‘s are always given the node name of ’‘dac’‘. The ’‘0’’ in @0 and
reg = <0> is the chip select number from the SPI controller.
Power supplies and reference voltages
Chips need power to work, so they will always have power supplies wired up to
them. In most cases, the supplies are not connected to the MCU, so in the device
tree, we just use a ``regulator-fixed`` to represent this.
For example if the EVAL-AD5791ARDZ board is connected to a DE10-Nano board, the VCC and IOVCC is connected to the VCC3P3 supply on the DE10-Nano (U9 is the LTC3612EUDC chip that is the actual supply). That supply can be modeled like this (at the top level of the devicetree):
vcc3p3: regulator-vcc3p3 {
compatible = "regulator-fixed";
regulator-name = "DE10-Nano VCC3P3 (U9)";
regulator-always-on;
};
These get referenced in the DAC node like this:
vcc-supply = <&vcc3p3>;
iovcc-supply = <&vcc3p3>;
The reference pins VREFPF/VREFPS and VREFNF/VREFNS are distinct from the
VDD/VSS analog power pins. Connect vdd-supply and vss-supply to the
analog power regulators, and vrefp-supply and vrefn-supply to the
positive and negative reference providers. The reference levels determine the
DAC’s nominal output span and conversion scale/offset.
For a board whose DAC node is labeled dac, reference the regulators
actually connected to these pins:
&dac {
vdd-supply = <&dac_vdd>;
vss-supply = <&dac_vss>;
vrefp-supply = <&dac_vrefp>;
vrefn-supply = <&dac_vrefn>;
};
Define these providers in the board’s devicetree with the correct supply and
reference levels, and retain its separate vcc-supply, iovcc-supply
and SPI configuration.
Output buffer configuration
The output of the DAC can be wired to an amplifier with unity gain or a gain of
two (using the RFB and INV pins). If the chip is wired in the gain of two
configuration, supply the adi,rbuf-gain2-en; property in the .dts file,
otherwise omit it.
GPIOs
Several of the pins on the DAC can be connected to GPIOs on the MCU, namely /RESET, /CLR and /LDAC. All of these are active low signals, so that needs to be specified as well.
reset-gpios = <&gpio_bd 16 GPIO_ACTIVE_LOW>;
clear-gpios = <&gpio_bd 17 GPIO_ACTIVE_LOW>;
ldac-gpios = <&gpio_bd 18 GPIO_ACTIVE_LOW>;
SPI offload support
Specialized SPI controllers such as the AXI SPI Engine can be used to stream data from DMA to the DAC with high speed and precise timing compared to traditional SPI controllers.
There is a reference HDL project available AD57XX_ARDZ HDL project that can be used with the ARDZ evaluation boards.
To enable SPI offload support in this scenario, a few extra properties are added to the SPI controller node (not the DAC peripheral node).
dmas = <&tx_dma 0>;
dma-names = "offload0-tx";
trigger-sources = <&trigger_pwm>;
See the full example .dts file linked above for the full context.
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.
root:/> cd /sys/bus/iio/devices/
root:/sys/bus/iio/devices> ls
device0
root:/sys/bus/iio/devices> cd device0
root:/sys/devices/platform/bfin-spi.0/spi0.3/iio:device0> ls -l
drwxr-xr-x 2 root root 0 Jan 4 12:28 .
drwxr-xr-x 3 root root 0 Jan 4 12:28 ..
-r--r--r-- 1 root root 4096 Jan 4 12:28 name
-rw-r--r-- 1 root root 4096 Jan 4 12:29 out_voltage0_powerdown
-rw-r--r-- 1 root root 4096 Jan 4 12:30 out_voltage0_raw
-rw-r--r-- 1 root root 4096 Jan 4 12:28 out_voltage_powerdown_mode
-r--r--r-- 1 root root 4096 Jan 4 12:28 out_voltage_powerdown_mode_available
-r--r--r-- 1 root root 4096 Jan 4 12:28 out_voltage_scale
lrwxrwxrwx 1 root root 0 Jan 4 12:28 subsystem -> ../../../../../bus/iio
-rw-r--r-- 1 root root 4096 Jan 4 12:28 uevent
Identify the device
root:/sys/devices/platform/bfin-spi.0/spi0.3/iio:device0> cat name
ad5791
Basic operation
Show scale
Description: scale to be applied to out_voltage0_raw in order to obtain the measured voltage in millivolts.
root:/sys/devices/platform/bfin-spi.0/spi0.3/iio:device0> cat out_voltage_scale
0.019
Set channel Y output voltage
Description: /sys/bus/iio/devices/iio:deviceX/out_voltageY_raw
Raw (unscaled, no bias etc.) output voltage for channel Y.
root:/sys/devices/platform/bfin-spi.0/spi0.3/iio:device0> echo 131579 > out_voltage0_raw
Use U_mV = (out_voltage0_raw + out_voltage_offset) * out_voltage_scale.
Read both attributes for the configured references: scale is
(VREFP + |VREFN|) / (2^N - 1), and offset is
-floor(|VREFN| * 2^N / (VREFP + |VREFN|)). The displayed scale of 0.019
is too coarsely rounded for an exact voltage calculation.
For AD5791, calculate an unsigned 20-bit code from the actual reference-dependent scale and offset. This example requests −2500 mV. Run inside the correct device directory after configuring the references and output power state:
set -eu
scale=$(cat out_voltage_scale)
offset=$(cat out_voltage_offset)
raw=$(awk -v scale="$scale" -v offset="$offset" 'BEGIN {
if (scale <= 0) exit 1
code = -2500 / scale - offset
if (code < 0 || code > 1048575) exit 1
printf "%.0f", code
}')
printf '%s\n' "$raw" > out_voltage0_raw
cat out_voltage0_raw
After writing the calculated code, reread raw, scale and offset and use
(raw + offset) * scale to calculate the requested output in millivolts.
The code is unsigned; a negative requested voltage is represented through the
reference-dependent offset, not by assuming a signed DAC code.
List available power down modes
/sys/bus/iio/devices/iio:deviceX/out_voltage_powerdown_mode_available
Description: Lists all available output power down modes.
root:/sys/devices/platform/bfin-spi.0/spi0.3/iio:device0> cat out_voltage_powerdown_mode_available
6kohm_to_gnd three_state
Set power down mode
/sys/bus/iio/devices/iio:deviceX/out_voltage_powerdown_mode
Description: Specifies the output power down mode. DAC output stage is disconnected from the amplifier and
6kohm_to_gnd |
connected to ground via an 6kOhm resistor |
three_state |
left floating |
For a list of available output power down options read out_voltage_powerdown_mode_available.
root:/sys/devices/platform/bfin-spi.0/spi0.3/iio:device0> echo three_state > out_voltage_powerdown_mode
root:/sys/devices/platform/bfin-spi.0/spi0.3/iio:device0> cat out_voltage_powerdown_mode
three_state
Enable power down mode on output Y
/sys/bus/iio/devices/iio:deviceX/out_voltageY_powerdown
Description: Writing 1 causes output Y to enter the power down mode specified by the corresponding out_voltageY_powerdown_mode. Clearing returns to normal operation. Y may be suppressed if all outputs are controlled together.
root:/sys/devices/platform/bfin-spi.0/spi0.3/iio:device0> echo 1 > out_voltage0_powerdown
root:/sys/devices/platform/bfin-spi.0/spi0.3/iio:device0> cat out_voltage0_powerdown
1
root:/sys/devices/platform/bfin-spi.0/spi0.3/iio:device0> echo 0 > out_voltage0_powerdown
root:/sys/devices/platform/bfin-spi.0/spi0.3/iio:device0> cat out_voltage0_powerdown
0
SPI offload usage
When the chip is used together with a SPI controller that support offloading
there are extra sysfs attributes available. A sampling_frequency attribute
that is used to set the update rate for the DAC and a buffer folder
containing attributes for doing buffered writes to the DAC.
Combined with the cyclic DMA feature in the IIO kernel tree, this can be used to
continuously stream a waveform from DMA to the DAC. There is example code for
how to use this to output a basic waveform in libiio.
See: ADI libiio repository (commit/2f6a9ca1771414fb72698df9923e21bf66834aa7) for an iio example app for the ad57xx dac.