Wiki

This version is outdated by a newer approved version.DiffThis version (17 Jul 2020 15:39) was approved by Nuno Sá.

This is an old revision of the document!


ADRV9002 Integrated Dual RF Transceiver Linux device driver

The ADRV9002 is a highly integrated, RF transceiver offering dual channel transmitters and dual channel receivers, integrated synthesizers, and digital signal processing functions. The IC delivers a versatile combination of high performance and low power consumption required by battery powered radio equipment and can operate in both FDD and TDD modes. The ADRV9002 operates from 30 MHz to 6000 MHz covering the VHF, licensed and unlicensed cellular bands, and ISM bands. The IC is capable of supporting both narrowband and wideband standards up to 40 MHz bandwidth on both receive and transmit. The transceiver consists of direct conversion signal paths with state-of-the-art noise figure and linearity. Each complete receiver and transmitter sub-system includes DC offset correction, quadrature error correction, and programmable digital filters, eliminating the need for these functions in the digital baseband. In addition, several auxiliary functions such as an auxiliary ADC, auxiliary DACs, and GPIOs are integrated to provide additional monitoring and control capability.

Supported Devices

Evaluation Boards

Description

This is a Linux industrial I/O (IIO) subsystem driver, targeting RF Transceivers. 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.

Source Code

Status

Source Mainlined?
git No

Files

Interrelated Device Drivers

Receive AXI-ADC driver

Transmit AXI-DAC / DDS driver

Device Driver Customization

Please follow the link here for detailed options and examples:

Stream Processor Configuration

What is a stream processor and what is the purpose of that?

The stream processor is a processor within the device tasked with performing a series of configuration tasks upon an external request. Upon a request from the user, the stream processor performs a series of defined actions defined in the image loaded into the stream during device initialization. The stream processor therefore has “streams” (series of tasks) for:

  • Tx1 Enable/Tx1 Disable, Tx2 Enable/Tx2 Disable
  • Rx1 Enable/Rx1 Disable, Rx2 Enable/Rx2 Disable
  • ORx1 Enable/ORx1 Disable, ORx2 Enable/ORx2 Disable

The stream is not limited to path enabling events and can also react to other events such as a GPIO input signal. The stream processor image needs to be changed with every different configuration. It is recommended to use TES GUI and generate stream file for required configuration.

This was added to make sure the signal path is not disrupted when ARM crashes and still the link is available with reduced performance as tracking calibrations are not running.

The stream binary NavassaStream.bin must be stored in the /lib/firmware folder, or compiled into the kernel using the CONFIG_FIRMWARE_IN_KERNEL, CONFIG_EXTRA_FIRMWARE config options. Multiple stream binaries can be added. However a unique name must be given.

Function File
Stream firmware/NavassaStream.bin (TBD)
Note the above is still not implemented. As for now, the stream images is statically linked with the kernel for the default profile. For profiles loaded at runtime, there's still no way to also update the stream binary. It will be added later.

Arm Binary Configuration

The device incorporates an ARM processor that needs to be loaded with firmware during boot/setup phase. The processor is responsible, for example, to run the initial and the on the fly calibrations. The ARM binary is also loaded using the kernel firmware framework. Hence, the firmware image needs to be placed in the /lib/firmware folder or compiled into the kernel using the CONFIG_FIRMWARE_IN_KERNEL, CONFIG_EXTRA_FIRMWARE config options. The driver expects the file to have the following name:

Function File
ARM firmware firmware/Navassa_EvaluationFw.bin

Gain Tables

The Gain tables for the RX, ORX and TX paths must also be loaded durint boot/setup phase. They are also loaded using the firmware framework.

Function File
RX Gain table firmware/RxGainTable.csv
ORX Gain table firmware/ORxGainTable.csv
TX Gain table firmware/TxAttenTable.csv

Example Linux Device-Tree Initialization

The ADRV9002 driver is a spi-bus driver and can currently only be instantiated via device tree.

Required devicetree properties:

  • compatible: Should always be “adi,adrv9002” or “adi,adrv9002-rx2tx2”
  • reg: SPI slave select number
  • clocks: Device reference clock
Function File
ADRV9002 Device Tree adi-adrv9002.dtsi
ADRV9002 Device Tree zynqmp-zcu102-rev10-adrv9002.dts
ADRV9002 Device Tree MIMO zynqmp-zcu102-rev10-adrv9002-rx2tx2.dts
ADRV9002 Bindings adi,adrv9002.yaml (TBD)

Enabling Linux driver support

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

The ADRV9002 driver depends on CONFIG_SPI

Adding Linux driver support

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

Linux Kernel Configuration
	Device Drivers  --->
	<*>     Industrial I/O support --->
	    --- Industrial I/O support
	    -*-   Enable ring buffer support within IIO
	    -*-     Industrial I/O lock free software ring
	    -*-   Enable triggered sampling support

	          *** Analog to digital converters ***
	    [--snip--]

		-*- Analog Devices High-Speed AXI ADC driver core
		< > Analog Devices AD9361, AD9364 RF Agile Transceiver driver
		< > Analog Devices AD9371 RF Transceiver driver
		<*> Analog Devices ADRV9001/ADRV9002 RF Transceiver driver
		< > Analog Devices AD6676 Wideband IF Receiver driver
		< > Analog Devices AD9467, AD9680, etc. high speed ADCs
		< > Analog Devices Motor Control (AD-FMCMOTCON) drivers

	    [--snip--]
	    

	Frequency Synthesizers DDS/PLL  --->
    		Direct Digital Synthesis  --->
	 		<*> Analog Devices CoreFPGA AXI DDS driver			
	

Hardware configuration

Device Modes

Depending on the devicetree compatible string used, the driver will behave differently in some aspects. There are two main modes of operaton:

compatible Mode Devicetree
adi,adrv9002-rx2tx2MIMO mode zynqmp-zcu102-rev10-adrv9002-rx2tx2.dts
adi,adrv9002Independent mode zynqmp-zcu102-rev10-adrv9002.dts

In “MIMO” mode, only one DMA buffer is used and both RX1/RX2 physical ports are mapped into the RX1 channel in the hdl axi core. The same happens for TX. For the hdl core is as TX2/RX2 don't exist. As the name implies, this is useful for use cases as MIMO/Diversity. Naturally, in this case, both RX1/RX2 must have the same baseband sample rate.

In the Independent mode both channels are treated separately by the hdl core, each one with it's own DMA buffer. Useful for TDD applications for example.

Driver testing / API

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:


General attribute naming convention:

IIO sysfs attribute naming prefix Target
Transceiver
in_temp0_input Device Temperature
in_voltage0_[…] RX1
in_voltage1_[…] RX2
out_voltage0_[…] TX1
out_voltage1_[…] TX2
out_altvoltage0_[…] RX1 LO
out_altvoltage1_[…] RX2 LO
out_altvoltage2_[…] TX1 LO
out_altvoltage3_[…] TX2 LO

This specifies any shell prompt running on the target

cd /sys/bus/iio/devices/
root@analog:/sys/bus/iio/devices# ls
iio:device0  iio:device1  iio:device2  iio:device3  iio_sysfs_trigger
root@analog:/sys/bus/iio/devices# cd iio:device1
root@analog:/sys/bus/iio/devices/iio:device1# ls -la
total 0
drwxr-xr-x 3 root root     0 Jun  9 09:06 .
drwxr-xr-x 5 root root     0 Jun  9 09:06 ..
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 dev
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 in_temp0_input
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 in_voltage0_agc_tracking_en
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 in_voltage0_bbdc_rejection_tracking_en
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 in_voltage0_decimated_power
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 in_voltage0_digital_gain_control_mode
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 in_voltage0_digital_gain_control_mode_available
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 in_voltage0_dynamic_adc_switch_en
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 in_voltage0_en
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 in_voltage0_ensm_mode
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 in_voltage0_ensm_mode_available
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 in_voltage0_gain_control_mode
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 in_voltage0_gain_control_mode_available
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 in_voltage0_hardwaregain
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 in_voltage0_hd_tracking_en
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 in_voltage0_interface_gain
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 in_voltage0_interface_gain_available
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 in_voltage0_nco_frequency
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 in_voltage0_port_en_mode
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 in_voltage0_port_en_mode_available
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 in_voltage0_quadrature_fic_tracking_en
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 in_voltage0_quadrature_w_poly_tracking_en
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 in_voltage0_rf_bandwidth
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 in_voltage0_rfdc_tracking_en
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 in_voltage0_rssi
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 in_voltage0_rssi_tracking_en
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 in_voltage0_sampling_frequency
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 in_voltage1_agc_tracking_en
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 in_voltage1_bbdc_rejection_tracking_en
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 in_voltage1_decimated_power
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 in_voltage1_digital_gain_control_mode
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 in_voltage1_digital_gain_control_mode_available
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 in_voltage1_dynamic_adc_switch_en
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 in_voltage1_en
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 in_voltage1_ensm_mode
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 in_voltage1_ensm_mode_available
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 in_voltage1_gain_control_mode
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 in_voltage1_gain_control_mode_available
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 in_voltage1_hardwaregain
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 in_voltage1_hd_tracking_en
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 in_voltage1_interface_gain
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 in_voltage1_interface_gain_available
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 in_voltage1_nco_frequency
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 in_voltage1_port_en_mode
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 in_voltage1_port_en_mode_available
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 in_voltage1_quadrature_fic_tracking_en
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 in_voltage1_quadrature_w_poly_tracking_en
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 in_voltage1_rf_bandwidth
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 in_voltage1_rfdc_tracking_en
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 in_voltage1_rssi
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 in_voltage1_rssi_tracking_en
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 in_voltage1_sampling_frequency
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 name
lrwxrwxrwx 1 root root     0 Jun  9 09:06 of_node -> ../../../../../../../../firmware/devicetree/base/amba/spi@ff040000/adrv9002-phy@0
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 out_altvoltage0_RX1_LO_frequency
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 out_altvoltage1_RX2_LO_frequency
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 out_altvoltage2_TX1_LO_frequency
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 out_altvoltage3_TX2_LO_frequency
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 out_voltage0_atten_control_mode
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 out_voltage0_atten_control_mode_available
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 out_voltage0_close_loop_gain_tracking_en
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 out_voltage0_en
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 out_voltage0_ensm_mode
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 out_voltage0_ensm_mode_available
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 out_voltage0_hardwaregain
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 out_voltage0_lo_leakage_tracking_en
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 out_voltage0_loopback_delay_tracking_en
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 out_voltage0_pa_correction_tracking_en
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 out_voltage0_port_en_mode
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 out_voltage0_port_en_mode_available
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 out_voltage0_quadrature_tracking_en
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 out_voltage0_rf_bandwidth
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 out_voltage0_sampling_frequency
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 out_voltage1_atten_control_mode
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 out_voltage1_atten_control_mode_available
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 out_voltage1_close_loop_gain_tracking_en
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 out_voltage1_en
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 out_voltage1_ensm_mode
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 out_voltage1_ensm_mode_available
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 out_voltage1_hardwaregain
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 out_voltage1_lo_leakage_tracking_en
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 out_voltage1_loopback_delay_tracking_en
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 out_voltage1_pa_correction_tracking_en
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 out_voltage1_port_en_mode
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 out_voltage1_port_en_mode_available
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 out_voltage1_quadrature_tracking_en
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 out_voltage1_rf_bandwidth
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 out_voltage1_sampling_frequency
drwxrwxrwx 2 root root     0 Jun  9 09:04 power
-rw-rw-rw- 1 root root 73728 Jun  9 09:04 profile_config
lrwxrwxrwx 1 root root     0 Jun  9 09:06 subsystem -> ../../../../../../../../bus/iio
-rw-rw-rw- 1 root root  4096 Jun  9 09:04 uevent

Show device name

This specifies any shell prompt running on the target

root:/sys/bus/iio/devices/iio:device1> cat name
adrv9002-phy

Show device temperature

This specifies any shell prompt running on the target

root@analog:/sys/bus/iio/devices/iio:device1# cat in_temp0_input 
58000

Channel Enable/Powerdown Controls

For use cases where pin control mode is not used or required, these attributes can be used to enable/disable the Rx/Tx signal paths while in the ENSM radio_on state.

  • in_voltage0_en
  • in_voltage1_en
  • out_voltage0_en
  • out_voltage1_en

This specifies any shell prompt running on the target

root@analog:/sys/bus/iio/devices/iio:device1# cat in_voltage0_en
1
root@analog:/sys/bus/iio/devices/iio:device1# echo 0 > in_voltage0_en
root@analog:/sys/bus/iio/devices/iio:device1# cat in_voltage0_en
0

Enable State Machine Controls

The ADRV9002 transceiver includes an Enable State Machine (ENSM), allowing real time control over the current state of the device. The ENSM has two possible control methods – SPI control (writing ensm_mode), and pin control. For pin control the below attributes can be inspected:

  • [in|out]_voltage[0|1]_port_en_mode_available
  • [in|out]_voltage[0|1]_port_en_mode

There are a pair of these attributes for all RX/TX channels.

This specifies any shell prompt running on the target

root@analog:/sys/bus/iio/devices/iio:device1# cat in_voltage0_port_en_mode_available
spi pin
root@analog:/sys/bus/iio/devices/iio:device1# cat in_voltage0_port_en_mode
spi
root@analog:/sys/bus/iio/devices/iio:device1# echo pin > in_voltage0_port_en_mode
root@analog:/sys/bus/iio/devices/iio:device1# cat in_voltage0_port_en_mode
pin

For controlling the ENSM attribute there are also a pair of attributes for all the RX/TX channels:

  • [in|out]_voltage[0|1]_ensm_mode_available
  • [in|out]_voltage[0|1]_ensm_mode

This specifies any shell prompt running on the target

root@analog:/sys/bus/iio/devices/iio:device1# cat in_voltage0_ensm_mode_available 
calibrated primed rf_enabled
root@analog:/sys/bus/iio/devices/iio:device1# cat in_voltage0_ensm_mode
calibrated
root@analog:/sys/bus/iio/devices/iio:device1# echo rf_enabled > in_voltage0_ensm_mod
root@analog:/sys/bus/iio/devices/iio:device1# cat in_voltage0_ensm_mode
rf_enabled

The above commands will only have any effect if the port_en_mode is set to spi

Local Oscillator Control (LO)

The device contains two RF PLLs. Each RF PLL uses the PLL block common to all synthesizers in the device and employ a 4 core VCO block which provides a 6dB phase noise improvement over the single core VCO. The tuneable range of the RF LO is 30-6000 MHz.It is possible to set the LO frequency independently for each port.

Attribute Port
out_altvoltage0_RX1_LO_frequency RX1
out_altvoltage1_RX2_LO_frequency RX2
out_altvoltage2_TX1_LO_frequency TX1
out_altvoltage3_TX2_LO_frequency TX2

This specifies any shell prompt running on the target

root@analog:/sys/bus/iio/devices/iio:device1# cat out_altvoltage2_TX1_LO_frequency
2700000000
root@analog:/sys/bus/iio/devices/iio:device1# echo 2400000000 > out_altvoltage2_TX1_LO_frequency
root@analog:/sys/bus/iio/devices/iio:device1# cat out_altvoltage2_TX1_LO_frequency
2400000000

Filter and Signal Path Configuration

Profiles

ADRV9002 uses profiles to designate different device configuration settings for the Tx/Rx channels. The profile dictates how the digital filters, analog filters, clock rates, and clock dividers are configured in the device. Some specific parameters set by profiles include the IQ data rate, ADC clock rate, analog filter corners, FIR filter coefficients, and interpolation/decimation factors in the half band filters. Several profiles can be examined in the ADRV9002 Transceiver Evaluation Software for given device clock frequencies. If the desired profile exists in the software, it is recommended to setup the desired profile in and use the generated JSON file by pressing the Generate Profile File button. Custom profiles can be generated using other ADI software tools not described here MATLAB Profile/Filter Generator for ADRV9002.

There are some constrains with the loaded profiles due to the architecture of the reference design:

TX cannot be enabled if the corresponding RX is also not enabled (eg: TX2 enabled and RX2 disabled). The driver will reject such a profile. The reason is that the TX SSI clock is derived from RX. This applies for all device modes!
In MIMO mode, RX1 cannot be disabled. In this mode, RX2 cannot be enabled without RX1!

Loading a Profile

This specifies any shell prompt running on the target

root@analog:/sys/bus/iio/devices/iio:device1# cat LTE_2_4G_40BW_61MSPS.json > profile_config 
root@analog:/sys/bus/iio/devices/iio:device3# 

The user can completely disable some channels with the profile. For example, the generated profile might just want to use RX1/TX1. In that case, all attributes related with RX2/TX2 will return error (No such device) if someone tries to access them

RX Signal Path

The ADRV9002 offers dual receive channels. With a minimum number of external components, each receive channel could build a complete RF-to-bits signal chain which serves as RF front end for a wide range of applications. It supports both time division duplexing (TDD) and frequency division duplexing (FDD) modes and reception of both narrowband (NB) and wideband (WB) signals up to 40MHz. Each receive path RX1 or RX2 contains 2 major subsystems, the Analog Front End (AFE) and a Digital Front End (DFE). The AFE contains the programmable attenuator, matched I and Q mixer, Low pass filter and ADC. The device provides 2 pairs of ADCs, a pair of high performance ADC's for high dynamic range and a pair of low performance ADC's for lower power consumption. The DFE subsystem contains a series of digital signal processing components such as sample rate decimation (DEC), dc offset correction (DC), quadrature error correction (QEC), digital down conversion (DDC) with numerically controlled oscillator (NCO), a programmable 128-tap FIR filter (PFIR), receiver signal strength indicator (RSSI), frequency offset correction, phase offset correction and overload detectors.

Sample Rate and Primary Signal Bandwidth

To query the RX Sample Rate and Primary Signal Bandwidth:

This specifies any shell prompt running on the target

root@analog:/sys/bus/iio/devices/iio:device1# cat in_voltage0_sampling_frequency 
15360000
root@analog:/sys/bus/iio/devices/iio:device1# cat in_voltage0_rf_bandwidth 
10000000

RX Gain Control

The ADRV9002 receivers (Rx1/Rx2) feature automatic and manual gain control modes for flexible gain control in a wide array of applications. Automatic Gain Control (AGC) allows for receivers to autonomously adjust the receiver gain depending on variations of the input signal. It controls the gain of the device based on the information from a number of signal detectors named peak detector and power detector. The use can also control the gain using API functions through SPI communications or using external PINs to increment/decrement the gain.

Gain Control Modes

Mode Description
spi Provides the user full control over the current gain index. Gain controlled through sysfs file
automatic The AGC will determine when gain changes should be made. To setup the AGC block there are a vast number of properties the user can configure. This is done through devicetree. More info at ADRV9001/ADRV9002 Device Driver Customization
pin The gain is controlled trough external pins. The user can also select which pins to use through devicetree. More in ADRV9001/ADRV9002 Device Driver Customization

This specifies any shell prompt running on the target

root@analog:/sys/bus/iio/devices/iio:device1# cat in_voltage0_gain_control_mode_available
spi pin automatic
root@analog:/sys/bus/iio/devices/iio:device1# echo pin > in_voltage0_gain_control_mode
root@analog:/sys/bus/iio/devices/iio:device1# cat in_voltage0_gain_control_mode
pin

Manually control the Gain

This specifies any shell prompt running on the target

root@analog:/sys/bus/iio/devices/iio:device1# cat in_voltage0_hardwaregain 
36.000000 dB
root@analog:/sys/bus/iio/devices/iio:device1# echo 25 > in_voltage0_hardwaregain
root@analog:/sys/bus/iio/devices/iio:device1# cat in_voltage0_hardwaregain 
25.000000 dB

This will only work if gain_control_mode is set to spi

Digital Gain Control

The digital gain control has two major purposes, one for gain correction which is to correct the small step size inaccuracy in analog front-end attenuation and the other for gain compensation which is to compensate for the entire analog front-end attenuation. The digital gain block is controlled by the Rx gain table. Different digital gain will be applied when configured in gain correction or gain compensation mode. The Rx gain table has a unique front-end attenuator setting, with a corresponding amount of digital gain, programmed at each index of the table. In the end of the Rx data path, the interface gain could be further applied by using a “Slicer” block for 2 major purposes. One is to avoid digital saturation in gain compensation mode. The other one is to ensure the overall SNR is limited only by analog noise and unaffected by quantization noise.

Gain Control Modes

Mode Description
Gain_Correction_manual_controlThe digital gain block is used. It applies a small amount of digital gain/attenuation to provide consistent gain steps in a gain table.
Gain_Compensation_manual_controlIn this mode gain compensation is used and the interface gain is determined manually by the user.
Gain_Correction_automatic_controlSimilar to 1 except that the device controls the interface gain automatically.
Gain_Compensation_automatic_controlSimilar to 2 except that the device controls the interface gain automatically

This specifies any shell prompt running on the target

root@analog:/sys/bus/iio/devices/iio:device1# cat in_voltage0_digital_gain_control_mode
Gain_Correction_manual_control
root@analog:/sys/bus/iio/devices/iio:device1# echo Gain_Compensation_manual_control > in_voltage0_digital_gain_control_mode
root@analog:/sys/bus/iio/devices/iio:device1# cat in_voltage0_digital_gain_control_mode
Gain_Compensation_manual_control

Manually change the Interface Gain

The available values can be seen with:

This specifies any shell prompt running on the target

root@analog:/sys/bus/iio/devices/iio:device1# cat in_voltage0_interface_gain_available 
18dB 12dB 6dB 0dB -6dB -12dB -18dB -24dB -30dB -36dB

Ranges for setting the Slicer gain are:

[0dB 18dB]NB and Correction table
[0dB 0dB]WB and Correction table
[-36dB 18dB]NB and Compensation table
[-36dB 0dB]WB and Compensation table

Setting the value:

This specifies any shell prompt running on the target

root@analog:/sys/bus/iio/devices/iio:device1# cat in_voltage0_interface_gain
0dB
root@analog:/sys/bus/iio/devices/iio:device1# echo -6dB > in_voltage0_interface_gain
root@analog:/sys/bus/iio/devices/iio:device1# cat in_voltage0_interface_gain
-6dB

This will only work if digital_gain_control_mode is set to one of the manual options. Furthermore, the port Enable State must be rf_enabled for this to take effect

RSSI and Decimated power

This specifies any shell prompt running on the target

root@analog:/sys/bus/iio/devices/iio:device1# cat in_voltage0_decimated_power 
60.750 dB

This specifies any shell prompt running on the target

root@analog:/sys/bus/iio/devices/iio:device1# cat in_voltage0_rssi
65.535 dB

NCO frequency

In the Rx data chain, a frequency offset correction block is provided as an option to further correct small carrier frequency offset in both NB and WB modes.

This specifies any shell prompt running on the target

root@analog:/sys/bus/iio/devices/iio:device1# cat in_voltage0_nco_frequency 
0
root@analog:/sys/bus/iio/devices/iio:device1# echo 1200 > in_voltage0_nco_frequency
root@analog:/sys/bus/iio/devices/iio:device1# cat in_voltage0_nco_frequency
1200

BBDC

The main difference between this setting and the bbdc tracking calibration is that disabling this setting will completely disable the bbdc algorithm and set the correction value to 0. Disabling the tracking calibration, just disables the algorithm but the last used correction value is still applied.

This specifies any shell prompt running on the target

root@analog:/sys/bus/iio/devices/iio:device1# cat in_voltage0_bbdc_rejection_en
1
root@analog:/sys/bus/iio/devices/iio:device1# echo 0 > in_voltage0_bbdc_rejection_en
root@analog:/sys/bus/iio/devices/iio:device1# cat in_voltage0_bbdc_rejection_en
0

Dynamic ADC switch

The device provides 2 pairs of ADCs, a pair of high performance ADC's for high dynamic range and a pair of low performance ADC's for lower power consumption. This setting enables the dynamic switch between this ADC's.

This specifies any shell prompt running on the target

root@analog:/sys/bus/iio/devices/iio:device1# cat in_voltage0_dynamic_adc_switch_en
0
root@analog:/sys/bus/iio/devices/iio:device1# echo 1 > in_voltage0_dynamic_adc_switch_en
root@analog:/sys/bus/iio/devices/iio:device1# cat in_voltage0_dynamic_adc_switch_en
1

TX Signal Path

The ADRV9001 device integrates dual direct-conversion (Zero-IF) transmitters. It supports both time division duplexing (TDD) and frequency division duplexing (FDD) modes and is capable of transmitting both narrowband (NB) and wideband (WB) signal. Each transmitter consists of an independent I and Q signal path with separate digital filters, DACs, analog Tx low pass filters (LPF) and upconversion mixers. After mixers, an analog attenuator is employed to control the Tx output signal power. There are several signal conditioning functions, such as TX gain control, PA protection, PA digital pre-distortion (DPD), Tx quadrature error correction (QEC) and Tx LO leakage handling, before the data is passed on to the DACs.

Sample Rate and Primary Signal Bandwidth

To query the RX Sample Rate and Primary Signal Bandwidth:

This specifies any shell prompt running on the target

root@analog:/sys/bus/iio/devices/iio:device1# cat out_voltage0_sampling_frequency 
15360000
root@analog:/sys/bus/iio/devices/iio:device1# cat out_voltage0_rf_bandwidth 
10000000

TX Attenuation Control

The Tx attenuation block controls the Tx output power. A Tx gain table with 840 entries is loaded into the ADRV9002’s memory during initialization. Each entry equals a 0.05dB gain step giving a range of 42dB.

Gain Control Modes

Mode Description
spi Provides the user full control over the current gain index. Gain controlled through sysfs file
bypass In this mode, the Tx attenuation functionality is not used which means 0dB total Tx attenuation
pin The gain is controlled trough external pins. The user can also select which pins to use through devicetree. More in ADRV9001/ADRV9002 Device Driver Customization

This specifies any shell prompt running on the target

root@analog:/sys/bus/iio/devices/iio:device1# cat out_voltage0_atten_control_mode_available 
bypass spi pin
root@analog:/sys/bus/iio/devices/iio:device1# echo bypass > out_voltage0_atten_control_mode
root@analog:/sys/bus/iio/devices/iio:device1# cat out_voltage0_atten_control_mode
bypass

Manually control the Gain

This specifies any shell prompt running on the target

root@analog:/sys/bus/iio/devices/iio:device1# cat out_voltage0_hardwaregain 
0.000000 dB
root@analog:/sys/bus/iio/devices/iio:device1# echo -10 > out_voltage0_hardwaregain
root@analog:/sys/bus/iio/devices/iio:device1# cat out_voltage0_hardwaregain 
-10.000000 dB

This will only work if gain_control_mode is set to spi

NCO frequency

As for the RX signal chain, it is also possible to apply a nco correction frequency on TX.

This specifies any shell prompt running on the target

root@analog:/sys/bus/iio/devices/iio:device1# cat out_voltage0_nco_frequency 
0
root@analog:/sys/bus/iio/devices/iio:device1# echo 1200 > out_voltage0_nco_frequency
root@analog:/sys/bus/iio/devices/iio:device1# cat out_voltage0_nco_frequency
1200

Tracking calibrations

In ADRV9002, to achieve optimal performance, an internal microcontroller performs calibrations which can be classified into two categories: initial calibrations performed at the initialization time before the device is operational; and tracking calibrations performed regularly while the device is operational. The following attributes control on the fly tracking calibrations.

Attribute Data Path
in_voltage[01]_agc_tracking_en RX1/RX2
in_voltage[01]_bbdc_rejection_tracking_en RX1/RX2
in_voltage[01]_hd_tracking_en RX1/RX2
in_voltage[01]_quadrature_fic_tracking_en RX1/RX2
in_voltage[01]_quadrature_w_poly_tracking_en RX1/RX2
in_voltage[01]_rfdc_tracking_en RX1/RX2
in_voltage[01]_rssi_tracking_en RX1/RX2
out_voltage[01]_close_loop_gain_tracking_en TX1/TX2
out_voltage[01]_lo_leakage_tracking_en TX1/TX2
out_voltage[01]_loopback_delay_tracking_en TX1/TX2
out_voltage[01]_pa_correction_tracking_en TX1/TX2
out_voltage[01]_quadrature_tracking_en TX1/TX2

This specifies any shell prompt running on the target

root@analog:/sys/bus/iio/devices/iio:device1# cat in_voltage0_agc_tracking_en
1
root@analog:/sys/bus/iio/devices/iio:device1# echo 0 > in_voltage0_agc_tracking_en
root@analog:/sys/bus/iio/devices/iio:device1# cat in_voltage0_agc_tracking_en
0

Advanced Debug Facilities

The ADRV9002 driver supports advanced debug controls via the kernel debugfs. These controls are mostly to debug which settings are currently configured in the device. How these device files/controls can be used is described here.

Runtime Device Driver Customization

There's a large number of options available. Through these controls, the user can debug if the device is properly configured with the wanted options or to test/tweak some features at runtime and then add them to the devicetree (if applicable). In order to identify if the IIO device in question (adrv9002-phy) you first need to identify the IIO device number. Therefore read the name attribute of each IIO device

This specifies any shell prompt running on the target

root@analog:~# grep "" /sys/bus/iio/devices/iio\:device*/name
/sys/bus/iio/devices/iio:device0/name:ams
/sys/bus/iio/devices/iio:device1/name:adrv9002-phy
/sys/bus/iio/devices/iio:device2/name:axi-adrv9002-rx-lpc
/sys/bus/iio/devices/iio:device3/name:axi-adrv9002-tx-lpc
root@analog:~# 

Change directory to /sys/kernel/debug/iio/ iio:deviceX.

This specifies any shell prompt running on the target

root@analog:/sys/kernel/debug/iio/iio:device1# ls -la
total 0
drwxr-xr-x 2 root root 0 Jan  1  1970 .
drwxr-xr-x 5 root root 0 Jan  1  1970 ..
-rw-r--r-- 1 root root 0 Jan  1  1970 direct_reg_access
-rw------- 1 root root 0 Jan  1  1970 initialize
-r-------- 1 root root 0 Jan  1  1970 pll_status
-r-------- 1 root root 0 Jan  1  1970 rx0_adc_type
-r-------- 1 root root 0 Jan  1  1970 rx0_agc_config
-r-------- 1 root root 0 Jan  1  1970 rx0_gain_control_pin_mode
-r-------- 1 root root 0 Jan  1  1970 rx1_adc_type
-r-------- 1 root root 0 Jan  1  1970 rx1_agc_config
-r-------- 1 root root 0 Jan  1  1970 rx1_gain_control_pin_mode
-r-------- 1 root root 0 Jan  1  1970 tx0_attenuation_pin_control
-r-------- 1 root root 0 Jan  1  1970 tx0_dac_boost_en
-rw------- 1 root root 0 Jan  1  1970 tx0_nco_frequency_hz
-r-------- 1 root root 0 Jan  1  1970 tx1_attenuation_pin_control
-r-------- 1 root root 0 Jan  1  1970 tx1_dac_boost_en
-rw------- 1 root root 0 Jan  1  1970 tx1_nco_frequency_hz

Example of changing AGC

All the options available to tweak the automatic gain control are exposed through debugfs files for each RX.

This specifies any shell prompt running on the target

root@analog:/sys/kernel/debug/iio/iio:device1# ls | grep rx0_agc
rx0_agc_agcMode
rx0_agc_attackDelay_us
rx0_agc_changeGainIfThreshHigh
rx0_agc_config
rx0_agc_enableFastRecoveryLoop
rx0_agc_enableSyncPulseForGainCounter
rx0_agc_gainUpdateCounter
rx0_agc_lowThreshPreventGainInc
rx0_agc_maxGainIndex
rx0_agc_minGainIndex
rx0_agc_peak.agcUnderRangeHighInterval
rx0_agc_peak.agcUnderRangeLowInterval
rx0_agc_peak.agcUnderRangeMidInterval
rx0_agc_peak.apdGainStepAttack
rx0_agc_peak.apdGainStepRecovery
rx0_agc_peak.apdHighThresh
rx0_agc_peak.apdLowThresh
rx0_agc_peak.apdLowerThreshPeakExceededCount
rx0_agc_peak.apdUpperThreshPeakExceededCount
rx0_agc_peak.enableHbOverload
rx0_agc_peak.feedback_high_threshold_counter_exceeded
rx0_agc_peak.feedback_low_threshold_counter_exceeded
rx0_agc_peak.hbGainStepHighRecovery
rx0_agc_peak.hbGainStepLowRecovery
rx0_agc_peak.hbGainStepMidRecovery
rx0_agc_peak.hbHighThresh
rx0_agc_peak.hbOverloadDurationCount
rx0_agc_peak.hbOverloadPowerMode
rx0_agc_peak.hbOverloadThreshCount
rx0_agc_peak.hbUnderRangeHighThresh
rx0_agc_peak.hbUnderRangeHighThreshExceededCount
rx0_agc_peak.hbUnderRangeLowThresh
rx0_agc_peak.hbUnderRangeLowThreshExceededCount
rx0_agc_peak.hbUnderRangeMidThresh
rx0_agc_peak.hbUnderRangeMidThreshExceededCount
rx0_agc_peak.hbUpperThreshPeakExceededCount
rx0_agc_peakWaitTime
rx0_agc_power.feedback_high_threshold_exceeded
rx0_agc_power.feedback_lowThreshold_gainChange
rx0_agc_power.overRangeHighPowerGainStepAttack
rx0_agc_power.overRangeHighPowerThresh
rx0_agc_power.overRangeLowPowerGainStepAttack
rx0_agc_power.overRangeLowPowerThresh
rx0_agc_power.powerEnableMeasurement
rx0_agc_power.powerMeasurementDelay
rx0_agc_power.powerMeasurementDuration
rx0_agc_power.rxTddPowerMeasDelay
rx0_agc_power.rxTddPowerMeasDuration
rx0_agc_power.underRangeHighPowerGainStepRecovery
rx0_agc_power.underRangeHighPowerThresh
rx0_agc_power.underRangeLowPowerGainStepRecovery
rx0_agc_power.underRangeLowPowerThresh
rx0_agc_resetOnRxon
rx0_agc_resetOnRxonGainIndex
rx0_agc_slowLoopSettlingDelay

The user can read/write on these files before committing the changes. For the changes to be applied, the user must do:

This specifies any shell prompt running on the target

root@analog:/sys/kernel/debug/iio/iio:device1# echo 1 > rx0_agc_config

The configurations can be read afterwards by reading the file:

This specifies any shell prompt running on the target

root@analog:/sys/kernel/debug/iio/iio:device1# cat rx0_agc_config 
peakWaitTime: 4
maxGainIndex: 255
minGainIndex: 183
gainUpdateCounter: 11520
attackDelay_us: 10
slowLoopSettlingDelay: 16
lowThreshPreventGainInc: 0
changeGainIfThreshHigh: 3
agcMode: 0
resetOnRxon: 0
resetOnRxonGainIndex: 255
enableSyncPulseForGainCounter: 0
enableFastRecoveryLoop: 0
power.powerEnableMeasurement: 1
power.underRangeHighPowerThresh: 10
power.underRangeLowPowerThresh: 4
power.underRangeHighPowerGainStepRecovery: 2
power.underRangeLowPowerGainStepRecovery: 4
power.powerMeasurementDuration: 10
power.powerMeasurementDelay: 2
power.rxTddPowerMeasDuration: 0
power.rxTddPowerMeasDelay: 0
power.overRangeHighPowerThresh: 0
power.overRangeLowPowerThresh: 7
power.overRangeHighPowerGainStepAttack: 4
power.overRangeLowPowerGainStepAttack: 4
power.feedback_lowThreshold_gainChange: 0
power.feedback_high_threshold_exceeded: 0
peak.agcUnderRangeLowInterval: 50
peak.agcUnderRangeMidInterval: 2
peak.agcUnderRangeHighInterval: 4
peak.apdHighThresh: 26
peak.apdLowThresh: 18
peak.apdUpperThreshPeakExceededCount: 6
peak.apdLowerThreshPeakExceededCount: 3
peak.apdGainStepAttack: 4
peak.apdGainStepRecovery: 0
peak.enableHbOverload: 1
peak.hbOverloadDurationCount: 1
peak.hbOverloadThreshCount: 1
peak.hbHighThresh: 16383
peak.hbUnderRangeLowThresh: 5826
peak.hbUnderRangeMidThresh: 8230
peak.hbUnderRangeHighThresh: 11626
peak.hbUpperThreshPeakExceededCount: 6
peak.hbUnderRangeHighThreshExceededCount: 3
peak.hbGainStepHighRecovery: 4
peak.hbGainStepLowRecovery: 6
peak.hbGainStepMidRecovery: 4
peak.hbGainStepMidRecovery: 4
peak.hbOverloadPowerMode: 0
peak.hbUnderRangeMidThreshExceededCount: 3
peak.hbUnderRangeLowThreshExceededCount: 3
peak.feedback_low_threshold_counter_exceeded: 0
peak.feedback_high_threshold_counter_exceeded: 0

Example of configuring SSI test modes

The data mode available can be different depending on whether CMOS or LVDS is being used. To check the available modes:

This specifies any shell prompt running on the target

root@analog:/sys/kernel/debug/iio/iio:device1# cat rx_ssi_test_mode_data_available 
TESTMODE_DATA_NORMAL
TESTMODE_DATA_FIXED_PATTERN
TESTMODE_DATA_RAMP_16_BIT
TESTMODE_DATA_PRBS15
TESTMODE_DATA_PRBS7

We then, set the desired mode:

This specifies any shell prompt running on the target

root@analog:/sys/kernel/debug/iio/iio:device1# echo TESTMODE_DATA_PRBS15 > rx0_ssi_test_mode_data 
root@analog:/sys/kernel/debug/iio/iio:device1# 

To start the test:

This specifies any shell prompt running on the target

root@analog:/sys/kernel/debug/iio/iio:device1# echo 1 > rx0_ssi_test_mode_configure
root@analog:/sys/kernel/debug/iio/iio:device1# 

For TESTMODE_DATA_FIXED_PATTERN, there is an additional file (rx[0/1]_ssi_test_mode_fixed_pattern) that can be written to set the pattern
For TX, the process is identical.

Example of configuring SSI delays

The available configurations for the SSI delays are:

This specifies any shell prompt running on the target

root@analog:/sys/kernel/debug/iio/iio:device1# ls | egrep [rt]x*.*_delay
rx0_ssi_clk_delay
rx0_ssi_i_data_delay
rx0_ssi_q_data_delay
rx0_ssi_strobe_delay
rx1_ssi_clk_delay
rx1_ssi_i_data_delay
rx1_ssi_q_data_delay
rx1_ssi_strobe_delay
tx0_ssi_clk_delay
tx0_ssi_i_data_delay
tx0_ssi_q_data_delay
tx0_ssi_refclk_delay
tx0_ssi_strobe_delay_delay
tx1_ssi_clk_delay
tx1_ssi_i_data_delay
tx1_ssi_q_data_delay
tx1_ssi_refclk_delay
tx1_ssi_strobe_delay_dela

After doing the wanted changes to the previous files, we apply them by:

This specifies any shell prompt running on the target

root@analog:/sys/kernel/debug/iio/iio:device1# echo 1 > ssi_delays 
root@analog:/sys/kernel/debug/iio/iio:device1#

Writing on ssi_delays will have effect on all ports

Example of reinitialize the device

This specifies any shell prompt running on the target

echo 1 > initialize

Example of reading RX Gain Pin Control settings

This specifies any shell prompt running on the target

root@analog:/sys/kernel/debug/iio/iio:device1# cat rx0_gain_control_pin_mode
min_gain_index: 183
max_gain_index: 255
increment_step_size: 1
decrement_step_size: 1
increment_pin: dgpio2
decrement_pin: dgpio1

Low level register access via debugfs (direct_reg_access)

Some IIO drivers feature an optional debug facility, allowing users to read or write registers directly. Special care needs to be taken when using this feature, since you can modify registers on the back of the driver.

To simplify direct register access you may want to use the libiio iio_reg command line utility.

Accessing debugfs requires root privileges.

In order to identify if the IIO device in question feature this option you first need to identify the IIO device number.

Therefore read the name attribute of each IIO device

This specifies any shell prompt running on the target

root@analog:~# grep "" /sys/bus/iio/devices/iio\:device*/name
/sys/bus/iio/devices/iio:device0/name:ad7291
/sys/bus/iio/devices/iio:device1/name:ad9361-phy
/sys/bus/iio/devices/iio:device2/name:xadc
/sys/bus/iio/devices/iio:device3/name:adf4351-udc-rx-pmod
/sys/bus/iio/devices/iio:device4/name:adf4351-udc-tx-pmod
/sys/bus/iio/devices/iio:device5/name:cf-ad9361-dds-core-lpc
/sys/bus/iio/devices/iio:device6/name:cf-ad9361-lpc
root@analog:~# 

Change directory to /sys/kernel/debug/iio/ iio:deviceX and check if the direct_reg_access file exists.

This specifies any shell prompt running on the target

root@analog:~# cd /sys/kernel/debug/iio/iio\:device1
root@analog:/sys/kernel/debug/iio/iio:device1# ls direct_reg_access 
direct_reg_access

Reading

This specifies any shell prompt running on the target

root@analog:/sys/kernel/debug/iio/iio:device1# echo 0x7 > direct_reg_access                                                                                                                                 
root@analog:/sys/kernel/debug/iio/iio:device1# cat direct_reg_access 
0x40

Writing

Write ADDRESS VALUE

This specifies any shell prompt running on the target

root@analog:/sys/kernel/debug/iio/iio:device1# echo 0x7 0x50  > direct_reg_access                                                                                                                            
root@analog:/sys/kernel/debug/iio/iio:device1# cat direct_reg_access 
0x50

Accessing HDL CORE registers

Special ADI device driver convention for devices that have both:

  • a SPI/I2C control interface
  • and some sort of HDL Core with registers (AXI)

In this case when accessing the HDL Core Registers always set BIT31.

The register map for typical ADI HDL cores can be found here: Register Map

This specifies any shell prompt running on the target

root@analog:/sys/kernel/debug/iio/iio:device6# echo 0x80000000 > direct_reg_access                                                                                                                           
root@analog:/sys/kernel/debug/iio/iio:device6# cat direct_reg_access 
0x80062

02 Mar 2011 15:16

More Information

resources/tools-software/linux-drivers/iio-transceiver/adrv9002.1594993185.txt.gz · Last modified: 17 Jul 2020 15:39 by Nuno Sá