ADRV9009, ADRV9008-1, ADRV9008-2

../../../../_images/adrv9009-bc.jpg

The ADRV9009 is a highly integrated, radio frequency (RF) agile transceiver offering dual transmitters and receivers, integrated synthesizers, and digital signal processing functions. The IC delivers a versatile combination of the high performance and low power consumption demanded by 3G and 4G macro cell TDD base station applications. The receive path consists of two independent, wide bandwidth, direct conversion receivers with state-of-the-art dynamic range. The part also supports a wide-bandwidth time-shared observation path receiver for use in TDD applications. The complete receive subsystem includes automatic and manual attenuation control, dc offset correction, quadrature error correction (QEC), and digital filtering, thus eliminating the need for these functions in the digital baseband. Several auxiliary functions such as ADCs, DACs, and GPIOs for PA and RF-front-end control are also integrated. In addition to the autonomous AGC, it also has flexible external gain control modes, allowing significant flexibility in setting system level gain dynamically.

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

Files

Interrelated Device Drivers

Receive AXI-ADC driver
Transmit AXI-DAC / DDS driver
AXI JESD204B HDL driver
AXI JESD204B GT (Gigabit Tranceiver) HDL driver (AMD XILINX/ALTERA-INTEL)

Function

File

driver

drivers/iio/jesd204/axi_adxcvr.c

Device Driver Customization

For detailed options and examples see ADRV9009/ADRV9008 Device Driver Customization.

Stream Processor Configuration

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

The stream processor is a processor within the Talise 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 TaliseStream.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. The stream binary loaded during driver probe can be specified using following device tree property:

stream-firmware-name = “TaliseStreamXYZ.bin”;

In case no stream is specified or loaded, the driver will continue to use the standard TaliseStream.bin file.

Function

File

Steam

firmware/TaliseStream.bin

Example Linux Device-Tree Initialization

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

Required devicetree properties:

  • compatible: Should always be either “adrv9009”, “adrv9008-1” or “adrv9008-2”

  • reg: SPI slave select number

Enabling Linux driver support

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

Note

The ADRV9009 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 ADRV9009/ADRV9008 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
        Clock Generator/Distribution  --->
            < > Analog Devices AD9508 Clock Fanout Buffer
            < > Analog Devices AD9523 Low Jitter Clock Generator
            <*> Analog Devices AD9528 Low Jitter Clock Generator
            < > Analog Devices AD9548 Network Clock Generator/Synchronizer
            < > Analog Devices AD9517 12-Output Clock Generator

    <*>   JESD204 High-Speed Serial Interface Support  --->
        --- JESD204 High-Speed Serial Interface Support
        < >   Altera Arria10 JESD204 PHY Support
        <*>   Analog Devices AXI ADXCVR PHY Support
        < >   Generic AXI JESD204B configuration driver
        <*>   Analog Devices AXI JESD204B TX Support
        <*>   Analog Devices AXI JESD204B RX Support

Hardware configuration

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.

Tip

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

General attribute naming convention:

IIO sysfs attribute naming prefix

Target

Transceiver

in_voltage0_[…]

RX1

in_voltage1_[…]

RX2

in_voltage2_[…]

Observation RX1

in_voltage3_[…]

Observation RX2

out_voltage0_[…]

TX1

out_voltage1_[…]

TX2

out_altvoltage0_[…]

TRX LO

out_altvoltage1_[…]

AUX LO

Auxilary Converters

in_voltage4_[…]

AUX ADC0

in_voltage5_[…]

AUX ADC1

in_voltage6_[…]

AUX ADC2

in_voltage7_[…]

AUX ADC3

out_voltage2_[…]

AUX DAC0

out_voltage3_[…]

AUX DAC1

out_voltage4_[…]

AUX DAC2

out_voltage5_[…]

AUX DAC3

out_voltage6_[…]

AUX DAC4

out_voltage7_[…]

AUX DAC5

out_voltage8_[…]

AUX DAC6

out_voltage9_[…]

AUX DAC7

out_voltage10_[…]

AUX DAC8

out_voltage11_[…]

AUX DAC9

out_voltage12_[…]

AUX DAC10

out_voltage13_[…]

AUX DAC11

~$
cd /sys/bus/iio/devices/
/sys/bus/iio/devices$
ls
iio:device0  iio:device3  iio:device2  iio:device3  iio:device4  iio:device5  iio:device6
/sys/bus/iio/devices$
cd iio:device3

/sys/bus/iio/devices/iio:device3$
ls -al
total 0
drwxr-xr-x 3 root root     0 May 16 14:21 .
drwxr-xr-x 5 root root     0 May 16 14:21 ..
-rw-rw-rw- 1 root root  4096 May 16 14:22 calibrate
-rw-rw-rw- 1 root root  4096 May 16 14:22 calibrate_frm_en
-rw-rw-rw- 1 root root  4096 May 16 14:22 calibrate_rx_phase_correction_en
-rw-rw-rw- 1 root root  4096 May 16 14:22 calibrate_rx_qec_en
-rw-rw-rw- 1 root root  4096 May 16 14:22 calibrate_tx_lol_en
-rw-rw-rw- 1 root root  4096 May 16 14:22 calibrate_tx_lol_ext_en
-rw-rw-rw- 1 root root  4096 May 16 14:22 calibrate_tx_qec_en
-rw-rw-rw- 1 root root  4096 May 16 14:22 dev
-rw-rw-rw- 1 root root  4096 May 16 14:22 ensm_mode
-rw-rw-rw- 1 root root  4096 May 16 14:22 ensm_mode_available
-rw-rw-rw- 1 root root 32768 May 16 14:22 gain_table_config
-rw-rw-rw- 1 root root  4096 May 16 14:22 in_temp0_input
-rw-rw-rw- 1 root root  4096 May 16 14:22 in_voltage0_gain_control_mode
-rw-rw-rw- 1 root root  4096 May 16 14:22 in_voltage0_gain_control_mode_available
-rw-rw-rw- 1 root root  4096 May 16 14:22 in_voltage0_gain_control_pin_mode_en
-rw-rw-rw- 1 root root  4096 May 16 14:22 in_voltage0_hardwaregain
-rw-rw-rw- 1 root root  4096 May 16 14:22 in_voltage0_hd2_tracking_en
-rw-rw-rw- 1 root root  4096 May 16 14:22 in_voltage0_powerdown
-rw-rw-rw- 1 root root  4096 May 16 14:22 in_voltage0_quadrature_tracking_en
-rw-rw-rw- 1 root root  4096 May 16 14:22 in_voltage0_rf_bandwidth
-rw-rw-rw- 1 root root  4096 May 16 14:22 in_voltage0_sampling_frequency
-rw-rw-rw- 1 root root  4096 May 16 14:22 in_voltage1_gain_control_mode
-rw-rw-rw- 1 root root  4096 May 16 14:22 in_voltage1_gain_control_mode_available
-rw-rw-rw- 1 root root  4096 May 16 14:22 in_voltage1_gain_control_pin_mode_en
-rw-rw-rw- 1 root root  4096 May 16 14:22 in_voltage1_hardwaregain
-rw-rw-rw- 1 root root  4096 May 16 14:22 in_voltage1_hd2_tracking_en
-rw-rw-rw- 1 root root  4096 May 16 14:22 in_voltage1_powerdown
-rw-rw-rw- 1 root root  4096 May 16 14:22 in_voltage1_quadrature_tracking_en
-rw-rw-rw- 1 root root  4096 May 16 14:22 in_voltage1_rf_bandwidth
-rw-rw-rw- 1 root root  4096 May 16 14:22 in_voltage1_sampling_frequency
-rw-rw-rw- 1 root root  4096 May 16 14:22 in_voltage2_hardwaregain
-rw-rw-rw- 1 root root  4096 May 16 14:22 in_voltage2_powerdown
-rw-rw-rw- 1 root root  4096 May 16 14:22 in_voltage2_quadrature_tracking_en
-rw-rw-rw- 1 root root  4096 May 16 14:22 in_voltage2_rf_bandwidth
-rw-rw-rw- 1 root root  4096 May 16 14:22 in_voltage2_rf_port_select
-rw-rw-rw- 1 root root  4096 May 16 14:22 in_voltage2_rf_port_select_available
-rw-rw-rw- 1 root root  4096 May 16 14:22 in_voltage2_sampling_frequency
-rw-rw-rw- 1 root root  4096 May 16 14:22 in_voltage3_hardwaregain
-rw-rw-rw- 1 root root  4096 May 16 14:22 in_voltage3_powerdown
-rw-rw-rw- 1 root root  4096 May 16 14:22 in_voltage3_quadrature_tracking_en
-rw-rw-rw- 1 root root  4096 May 16 14:22 in_voltage3_rf_bandwidth
-rw-rw-rw- 1 root root  4096 May 16 14:22 in_voltage3_rf_port_select
-rw-rw-rw- 1 root root  4096 May 16 14:22 in_voltage3_rf_port_select_available
-rw-rw-rw- 1 root root  4096 May 16 14:22 in_voltage3_sampling_frequency
-rw-rw-rw- 1 root root  4096 May 16 14:22 in_voltage4_offset
-rw-rw-rw- 1 root root  4096 May 16 14:22 in_voltage4_raw
-rw-rw-rw- 1 root root  4096 May 16 14:22 in_voltage4_scale
-rw-rw-rw- 1 root root  4096 May 16 14:22 in_voltage5_offset
-rw-rw-rw- 1 root root  4096 May 16 14:22 in_voltage5_raw
-rw-rw-rw- 1 root root  4096 May 16 14:22 in_voltage5_scale
-rw-rw-rw- 1 root root  4096 May 16 14:22 in_voltage6_offset
-rw-rw-rw- 1 root root  4096 May 16 14:22 in_voltage6_raw
-rw-rw-rw- 1 root root  4096 May 16 14:22 in_voltage6_scale
-rw-rw-rw- 1 root root  4096 May 16 14:22 in_voltage7_offset
-rw-rw-rw- 1 root root  4096 May 16 14:22 in_voltage7_raw
-rw-rw-rw- 1 root root  4096 May 16 14:22 in_voltage7_scale
-rw-rw-rw- 1 root root  4096 May 16 14:22 name
lrwxrwxrwx 1 root root     0 May 16 14:22 of_node -> ../../../../../../../../firmware/devicetree/base/amba/spi@ff040000/adrv9009-phy@1
-rw-rw-rw- 1 root root  4096 May 16 14:22 out_altvoltage0_TRX_LO_frequency
-rw-rw-rw- 1 root root  4096 May 16 14:22 out_altvoltage0_TRX_LO_frequency_hopping_mode_enable
-rw-rw-rw- 1 root root  4096 May 16 14:22 out_altvoltage1_AUX_OBS_RX_LO_frequency
-rw-rw-rw- 1 root root  4096 May 16 14:22 out_voltage0_atten_control_pin_mode_en
-rw-rw-rw- 1 root root  4096 May 16 14:22 out_voltage0_hardwaregain
-rw-rw-rw- 1 root root  4096 May 16 14:22 out_voltage0_lo_leakage_tracking_en
-rw-rw-rw- 1 root root  4096 May 16 14:22 out_voltage0_pa_protection_en
-rw-rw-rw- 1 root root  4096 May 16 14:22 out_voltage0_powerdown
-rw-rw-rw- 1 root root  4096 May 16 14:22 out_voltage0_quadrature_tracking_en
-rw-rw-rw- 1 root root  4096 May 16 14:22 out_voltage0_rf_bandwidth
-rw-rw-rw- 1 root root  4096 May 16 14:22 out_voltage10_offset
-rw-rw-rw- 1 root root  4096 May 16 14:22 out_voltage10_raw
-rw-rw-rw- 1 root root  4096 May 16 14:22 out_voltage10_scale
-rw-rw-rw- 1 root root  4096 May 16 14:22 out_voltage11_offset
-rw-rw-rw- 1 root root  4096 May 16 14:22 out_voltage11_raw
-rw-rw-rw- 1 root root  4096 May 16 14:22 out_voltage11_scale
-rw-rw-rw- 1 root root  4096 May 16 14:22 out_voltage12_raw
-rw-rw-rw- 1 root root  4096 May 16 14:22 out_voltage12_scale
-rw-rw-rw- 1 root root  4096 May 16 14:22 out_voltage13_raw
-rw-rw-rw- 1 root root  4096 May 16 14:22 out_voltage13_scale
-rw-rw-rw- 1 root root  4096 May 16 14:22 out_voltage1_atten_control_pin_mode_en
-rw-rw-rw- 1 root root  4096 May 16 14:22 out_voltage1_hardwaregain
-rw-rw-rw- 1 root root  4096 May 16 14:22 out_voltage1_lo_leakage_tracking_en
-rw-rw-rw- 1 root root  4096 May 16 14:22 out_voltage1_pa_protection_en
-rw-rw-rw- 1 root root  4096 May 16 14:22 out_voltage1_powerdown
-rw-rw-rw- 1 root root  4096 May 16 14:22 out_voltage1_quadrature_tracking_en
-rw-rw-rw- 1 root root  4096 May 16 14:22 out_voltage1_rf_bandwidth
-rw-rw-rw- 1 root root  4096 May 16 14:22 out_voltage2_offset
-rw-rw-rw- 1 root root  4096 May 16 14:22 out_voltage2_raw
-rw-rw-rw- 1 root root  4096 May 16 14:22 out_voltage2_scale
-rw-rw-rw- 1 root root  4096 May 16 14:22 out_voltage3_offset
-rw-rw-rw- 1 root root  4096 May 16 14:22 out_voltage3_raw
-rw-rw-rw- 1 root root  4096 May 16 14:22 out_voltage3_scale
-rw-rw-rw- 1 root root  4096 May 16 14:22 out_voltage4_offset
-rw-rw-rw- 1 root root  4096 May 16 14:22 out_voltage4_raw
-rw-rw-rw- 1 root root  4096 May 16 14:22 out_voltage4_scale
-rw-rw-rw- 1 root root  4096 May 16 14:22 out_voltage5_offset
-rw-rw-rw- 1 root root  4096 May 16 14:22 out_voltage5_raw
-rw-rw-rw- 1 root root  4096 May 16 14:22 out_voltage5_scale
-rw-rw-rw- 1 root root  4096 May 16 14:22 out_voltage6_offset
-rw-rw-rw- 1 root root  4096 May 16 14:22 out_voltage6_raw
-rw-rw-rw- 1 root root  4096 May 16 14:22 out_voltage6_scale
-rw-rw-rw- 1 root root  4096 May 16 14:22 out_voltage7_offset
-rw-rw-rw- 1 root root  4096 May 16 14:22 out_voltage7_raw
-rw-rw-rw- 1 root root  4096 May 16 14:22 out_voltage7_scale
-rw-rw-rw- 1 root root  4096 May 16 14:22 out_voltage8_offset
-rw-rw-rw- 1 root root  4096 May 16 14:22 out_voltage8_raw
-rw-rw-rw- 1 root root  4096 May 16 14:22 out_voltage8_scale
-rw-rw-rw- 1 root root  4096 May 16 14:22 out_voltage9_offset
-rw-rw-rw- 1 root root  4096 May 16 14:22 out_voltage9_raw
-rw-rw-rw- 1 root root  4096 May 16 14:22 out_voltage9_scale
-rw-rw-rw- 1 root root  4096 May 16 14:22 out_voltage_sampling_frequency
drwxrwxrwx 2 root root     0 May 16 14:22 power
-rw-rw-rw- 1 root root  8192 May 16 14:22 profile_config
lrwxrwxrwx 1 root root     0 May 16 14:22 subsystem -> ../../../../../../../../bus/iio
-rw-rw-rw- 1 root root  4096 May 16 14:22 uevent
/sys/bus/iio/devices/iio:device3$

Show device name

/sys/bus/iio/devices/iio:device3$
cat name
adrv9009-phy

Enable State Machine Controls

The ADRV9009 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.

/sys/bus/iio/devices/iio:device3$
cat ensm_mode_available
radio_on radio_off
/sys/bus/iio/devices/iio:device3$
cat ensm_mode
radio_on
/sys/bus/iio/devices/iio:device3$
echo radio_off > ensm_mode
/sys/bus/iio/devices/iio:device3$
cat ensm_mode
radio_of

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/ORx/Tx signal paths while in the ENSM radio_on state.

Important

Rx and ORx channels can not be enabled at the same time, since they share the same converter. So when stitching from RX to ORx, first powerdown RX, then clear the powerdown controls on ORx.

Writing 0, N or 1, Y to the below attributes either disables or enables the corresponding channel powerdown option.

  • in_voltage0_powerdown

  • in_voltage1_powerdown

  • in_voltage2_powerdown

  • in_voltage3_powerdown

  • out_voltage0_powerdown

  • out_voltage1_powerdown

/sys/bus/iio/devices/iio:device3$
cat in_voltage0_powerdown
0
/sys/bus/iio/devices/iio:device3$
echo 1 > in_voltage0_powerdown
/sys/bus/iio/devices/iio:device3$
cat in_voltage0_powerdown_en
1

Local Oscillator Control (LO)

The ADRV9009 contains two fractional-N PLLs RF PLL and AUX PLL. The RF PLL generate the RF LO used by the transmitter & receiver, and observation receiver. The LO mux controlled via in_voltage2_rf_port_select allows either the RF PLL or the AUX PLL to provide the local oscillator signal source for the observation receiver ORx1 and ORx2 mixers. The tuning range supported by this driver covers 75MHz to 6GHz. The lower end cannot go below TxProfile or RxProfile RFBW/2.

Attribute

PLL Name

Source Target

out_altvoltage0_TRX_LO_frequency

RF PLL

RX1, RX2, TX1, TX2, ORX1, ORX2

out_altvoltage1_AUX_OBS_RX_LO_frequency

AUX PLL

ORX1, ORX2

/sys/bus/iio/devices/iio:device3$
cat out_altvoltage1_TX_LO_frequency
2400000000
/sys/bus/iio/devices/iio:device3$
echo 2450000000 >  out_altvoltage0_TRX_LO_frequency
/sys/bus/iio/devices/iio:device3$
cat out_altvoltage0_TRX_LO_frequency
2450000000
/sys/bus/iio/devices/iio:device3$
cat out_altvoltage1_TX_LO_frequency
2450000000

Frequency Hopping Mode

The RF PLL in ADRV9009 has the ability to change frequency quickly to another predetermined LO frequency set by the user via the customization interface. The frequency hopping mode can be enabled using the out_altvoltage0_TRX_LO_frequency_hopping_mode_enable channel attribute.

  • out_altvoltage0_TRX_LO_frequency_hopping_mode_enable

/sys/bus/iio/devices/iio:device3$
cat out_altvoltage0_TRX_LO_frequency_hopping_mode_enable
0
/sys/bus/iio/devices/iio:device3$
echo 1 > out_altvoltage0_TRX_LO_frequency_hopping_mode_enable
/sys/bus/iio/devices/iio:device3$
cat out_altvoltage0_TRX_LO_frequency_hopping_mode_enable
1
Next Hop Frequency

The RF PLL in ADRV9009 has the ability to change frequency quickly to another predetermined LO frequency set by the user via this attribute. There are two use cases through which a user can control frequency hopping. GPIO mode, and API mode. In order to use API mode device tree attribute: adi,fhm-mode-fhm-trigger-mode must be set to 1, in case it’s set to 0 GPIO mode is used and adi,fhm-config-fhm-gpio-pin must be in the range of 0..15.

  • out_altvoltage0_TRX_LO_frequency_hopping_mode

/sys/bus/iio/devices/iio:device3$
cat out_altvoltage0_TRX_LO_frequency_hopping_mode
2400000000
/sys/bus/iio/devices/iio:device3$
echo 2460000000 > out_altvoltage0_TRX_LO_frequency_hopping_mode
/sys/bus/iio/devices/iio:device3$
cat out_altvoltage0_TRX_LO_frequency_hopping_mode
2460000000

Filter and Signal Path Configuration

Profiles

ADRV9009 uses profiles to designate different device configuration settings for the Tx/Rx/ORx channels. When selecting a profile, note that Rx1 and Rx2 use the same profile; Tx1 and Tx2 use the same profile; ORx1 and ORx2 use the same profile. 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 ADRV9009 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 data structure values generated by the “Create Config.c File” button for the Tx/Rx/ORx profile data structures. Custom profiles can be generated using other ADI software tools not described here MATLAB Profile/Filter Generator for ADRV9009.

Loading a Profile
user@analog:~$
cat Tx_BW200_IR245p76_Rx_BW200_OR245p76_ORx_BW200_OR245p76_DC245p76.txt \
  > profile_config
user@analog:~$

RX Signal Path

The ADRV9009 receiver contains all blocks necessary to receive RF signals and convert them to digital data usable by a baseband processor (BBP). Each receiver can be configured as a direct conversion system that supports up to 200MHz bandwidth. Each receiver contains a programmable attenuator stage, followed by matched in-phase (I) and quadrature (Q) mixers that down convert received signals to baseband for digitization. Gain control can be achieved by using the on-chip AGC or by letting the BBP make gain adjustments in a manual gain control mode. Performance is optimized by mapping each gain control setting to specific attenuation levels at each adjustable gain block in the receive signal path. Additionally, each channel contains independent quadrature error correction capability, dc offset tracking, and all circuitry necessary for self calibration. The receivers include ADCs and adjustable sample rates that produce data streams from the received signals. The signals can be conditioned further by a series of decimation filters and a programmable FIR filter with additional decimation settings. The sample rate of each digital filter block is adjustable by changing decimation factors to produce the desired output data rate.

Querying the RX Sample Rate and Primary Signal Bandwidth
/sys/bus/iio/devices/iio:device3$
cat in_voltage0_sampling_frequency
122880000
/sys/bus/iio/devices/iio:device3$
cat in_voltage0_rf_bandwidth
100000000

Observation RX Signal Path

The ADRV9009 contains an independent DPD observation receiver (ORx) front-end with 2 multiplexed inputs and a common digital back-end that is shared with the traffic receiver. The innovative configuration enables a highly efficient shared Rx/ORx mode where the device can support fast switching between Rx and ORx mode in TDD applications. The ORx shares the common frequency synthesizer with the transmitter. The ORx is a direct conversion system that contains a programmable attenuator stage, followed by matched in-phase (I) and quadrature (Q) mixers, baseband filters and ADCs. The continuous-time sigma-delta ADCs have inherent anti-aliasing which reduces the RF filtering requirement. The ADC outputs can be conditioned further by a series of decimation filters and a programmable FIR filter with additional decimation settings. The sample rate of each digital filter block is adjustable by changing decimation factors to produce the desired output data rate.

Querying the ORx Sample Rate
/sys/bus/iio/devices/iio:device3$
cat in_voltage2_sampling_frequency
245760000
/sys/bus/iio/devices/iio:device3$
cat in_voltage2_rf_bandwidth
200000000
Setting the Observation Path LO Source

This attribute sets the LO source for ORx to RFLO or AuxLO, but the setting does not take effect until the ORx rising edge to power up the ORx channel(s). If the LO source is changed while ORx is powered up, the LO source will not take effect until ORx is disabled and re-enabled. This is valid when using pins to set the LO source and control when ORx is enabled as well.

  • OBS_TX_LO Selects RF PLL

  • OBS_AUX_LO Selects AUX PLL

/sys/bus/iio/devices/iio:device3$
cat in_voltage_rf_port_select_available
OBS_TX_LO  OBS_AUX_LO
/sys/bus/iio/devices/iio:device3$
echo OBS_TX_LO > in_voltage2_rf_port_select
/sys/bus/iio/devices/iio:device3$
cat in_voltage2_rf_port_select
OBS_TX_LO

TX Signal Path

The ADRV9009 transmitter section consists of two identical and independently controlled channels that provide all digital processing, mixed-signal, and RF blocks necessary to implement a direct conversion system while sharing a common frequency synthesizer. The digital data from the JESD204B lanes pass through a fully programmable 128-tap FIR filter with variable interpolation rates. The FIR output is sent to a series of interpolation filters that provide additional filtering and interpolation prior to reaching the DAC. Each 14-bit DAC has an adjustable sample rate. When converted to baseband analog signals, the I and Q signals are filtered to remove sampling artifacts and fed to the upconversion mixers. Each transmit chain provides a wide attenuation adjustment range with fine granularity to help designers optimize signal-to-noise ratio (SNR).

Querying the TX Sample Rate and Primary Signal Bandwidth
/sys/bus/iio/devices/iio:device3$
cat out_voltage_sampling_frequency
245760000
/sys/bus/iio/devices/iio:device3$
cat out_voltage0_rf_bandwidth
75000000
PA Protection
/sys/bus/iio/devices/iio:device3$
cat out_voltage0_pa_protection_en
0
/sys/bus/iio/devices/iio:device3$
echo 1 > out_voltage0_pa_protection_en
/sys/bus/iio/devices/iio:device3$
cat out_voltage0_pa_protection_en
1

RX Gain Control

The ADRV9009 Receivers (Rx1, Rx2) feature Automatic and Manual gain control modes allowing 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, such as the onset of a strong interferer that can overload the receiver data path. It controls the gain of Talise based on the state of certain signals that are available as inputs to the AGC block. The AGC has the ability to control Talise gain with very fine resolution if required. The receivers are also capable of operating in Manual Gain Control (MGC) mode where changes in gain are initiated by the Baseband Processor (BBP). The Talise gain control blocks are configured by means of the API data structures and several API functions exist to allow for user interaction with the gain control mechanisms. There are three main gain control modes available for the Talise receivers – Manual Gain Control (MGC), Automatic Gain Control (AGC), Automatic Gain Control Fast (AGCFast).

The default gain tables can be found in the talise_user.c file, and are loaded by default. Custom gain tables can be loaded automatically during driver probe or anytime later via the write only gain_table_config sysfs attribute. Tables must be stored in the /lib/firmware folder, or compiled into the kernel using the CONFIG_FIRMWARE_IN_KERNEL, CONFIG_EXTRA_FIRMWARE config options. The table loaded during driver probe can be specified using following device tree property:

adi,gaintable-name = “adrv9009_std_gaintable”;

In case no table is specified or loaded, the driver will continue to use the provided standard gain tables.

Gain tables are stored in a human readable file, with the format specified below.

Example: firmware/adrv9009_std_gaintable

<list>
 <gaintable ADRV9009 type=FULL dest=[0|1|2|3|4|5] start=FREQUENCY1_Hz end=FREQUENCY2_Hz>
  gain_in_mdB, rxFeGain, extControl, adcTiaGain, digGain[, phaseOffset] /* index 255 */
  gain_in_mdB, rxFeGain, extControl, adcTiaGain, digGain[, phaseOffset] /* index 254 */
  gain_in_mdB, rxFeGain, extControl, adcTiaGain, digGain[, phaseOffset] /* index 253 */
  gain_in_mdB, rxFeGain, extControl, adcTiaGain, digGain[, phaseOffset] /* index 252 */

 …
 </gaintable>

...

</list>

Assumptions: * Gain tables must be monotonic

  • The format of the columns in the Rx gain table rows are: { gain_in_mdB, rxFeGain, extControl, adcTiaGain, digGain[, phaseOffset }

  • The format of the columns in the ORx gain table rows are: { gain_in_mdB, rxFeGain, extControl, adcTiaGain, digGain }

  • gain_in_mdB: is the absolute Gain in mdB (signed int format)

  • end must be greater than start frequency (in Hz)

  • There must be sufficient tables provided to support the entire used tuning range

  • dest specifies the targeted RX. (0=RX1, 1=RX2, 2=RX1 and RX2, 3=ORX1, 4=ORX2, 5=ORX1 and ORX2)

Loading a gain table

/sys/bus/iio/devices/iio:device3$
ls /lib/firmware/ad9*
adrv9009_std_gaintable
/sys/bus/iio/devices/iio:device3$
cat /lib/firmware/adrv9009_std_gaintable > gain_table_config

Gain control modes

The ADRV9009 Rx supports four modes of gain control. These modes are described in brief below:

Mode

Description

Manual Gain Control (MGC)

Provides the user full control over the current gain index. In MGC, the gain index can be controlled in two ways: through API commands and through GPIO signaling.

Automatic Gain Control (AGC)

The AGC will determine when gain changes should be made. There are several configurations that can be used in AGC. Examples include the option to reduce gain as soon as an overrange has been detected (fast attack mode), change gain (if necessary) only at the expiry of a variable length counter (AGC gain update counter, operating without fast attack), synchronization of the counter to an external pulse (AGC enable sync pulse), and others. .

Hybrid Mode

Tip

Automatic Gain Control (AGC) and Hybrid Mode are only available on RX1 and RX2

/sys/bus/iio/devices/iio:device3$
cat in_voltage_gain_control_mode_available
manual fast_attack slow_attack hybrid

Querying or Setting a Gain Control Mode

/sys/bus/iio/devices/iio:device3$
cat in_voltage0_gain_control_mode
manual
/sys/bus/iio/devices/iio:device3$
echo slow_attack > in_voltage0_gain_control_mode
/sys/bus/iio/devices/iio:device3$
cat in_voltage0_gain_control_mode
slow_attack
/sys/bus/iio/devices/iio:device3$
cat in_voltage1_gain_control_mode
manual

Reading the current Gain

Supported in all available Gain control modes

/sys/bus/iio/devices/iio:device3$
cat in_voltage0_hardwaregain
30.000000 dB
/sys/bus/iio/devices/iio:device3$
cat in_voltage1_hardwaregain
30.000000 dB

MGC setting the current Gain

Only available in Manual Gain Control Mode (MGC)

Attribute

Data Path

in_voltage0_hardwaregain

RX1

in_voltage1_hardwaregain

RX2

in_voltage2_hardwaregain

OBS1 if in_voltage2_powerdown == 0

in_voltage3_hardwaregain

OBS2 if in_voltage3_powerdown == 0

/sys/bus/iio/devices/iio:device3$
echo 20 > in_voltage0_hardwaregain
/sys/bus/iio/devices/iio:device3$
cat in_voltage0_hardwaregain
20.000000 dB

MGC controlling the gain using pin control

These attributes configure the GPIO input pin and step size to allow the BBP to control gain changes in Rx signal chain. A high pulse on the ‘rxGainIncPin’ in pin control mode will increment the gain by the value set in ‘incStep’. A high pulse on the ‘rxGainDecPin’ in pin control mode will decrement the gain by the value set in ‘decStep’.

Writing 0, N or 1, Y to the below attributes either disables or enables the corresponding channel pincontrol option.

Attribute

Data Path

in_voltage0_gain_control_pin_mode_en

RX1

in_voltage1_gain_control_pin_mode_en

RX2

Tx Attenuation Control

The TX attenuation/gain can be individually controlled for TX1 and TX2. The range is from 0 to -41.95 dB in programmable steps sizes. The nomenclature used here is gain instead of attenuation, so all values are expressed negative.

/sys/bus/iio/devices/iio:device3$
cat out_voltage0_hardwaregain
-10.000000 dB
/sys/bus/iio/devices/iio:device3$
echo -40.25 > out_voltage0_hardwaregain
/sys/bus/iio/devices/iio:device3$
cat out_voltage0_hardwaregain
-40.250000 dB
/sys/bus/iio/devices/iio:device3$
cat out_voltage1_hardwaregain
-10.000000 dB

Tx Attenuation Pin Control

These attributes configure the GPIO input pin and step size to allow the BBP to control attenuation changes in Tx signal chain. A high pulse on the ‘txAttenIncPin’ in pin control mode will increment the gain by the value set in ‘stepSize’. A high pulse on the ‘txAttenDecPin’ in pin control mode will decrement the gain by the value set in ‘stepSize’.

Writing 0, N or 1, Y to the below attributes either disables or enables the corresponding channel pincontrol option.

Attribute

Data Path

out_voltage0_atten_control_pin_mode_en

TX1

out_voltage1_atten_control_pin_mode_en

TX2

Received Strength Signal Indicator (RSSI)

This attribute will report RSSI - however currently it reports Decimated Power instead.

/sys/bus/iio/devices/iio:device3$
cat in_voltage0_rssi
12.75 dB

Calibration Tracking Controls

Tracking Calibrations: The ARM processor is tasked with ensuring that Quadrature Error Correction (QEC) and Local Oscillator Leakage (LOL) corrections are optimal throughout device operation, i.e. over time, attenuation, and temperature. It achieves this by performing calibrations at regular intervals. These calibrations are termed “tracking calibrations”, and utilize normal traffic data to update the path correction coefficients.

Writing 0, N or 1, Y to the below attributes either disables or enables the corresponding tracking option.

Attribute

Data Path

in_voltage0_quadrature_tracking_en

RX1

in_voltage1_quadrature_tracking_en

RX2

in_voltage2_quadrature_tracking_en

ORX1

in_voltage3_quadrature_tracking_en

ORX2

out_voltage0_lo_leakage_tracking_en

TX1

out_voltage0_quadrature_tracking_en

TX1

out_voltage1_lo_leakage_tracking_en

TX2

out_voltage1_quadrature_tracking_en

TX2

/sys/bus/iio/devices/iio:device3$
cat in_voltage_quadrature_tracking_en
1
/sys/bus/iio/devices/iio:device3$
echo 0 > in_voltage0_quadrature_tracking_en
/sys/bus/iio/devices/iio:device3$
cat in_voltage0_quadrature_tracking_en
0

ARM Calibrations

Sometimes a certain calibration is not required during power-up, or some other external condition must be met. The attributes detailed below allow the user to reschedule a calibration. Please see “SYSTEM CONSIDERATIONS FOR ARM CALIBRATIONS” section of the Talise User Guide for more information.

Writing 0, N or 1, Y to the below attributes either disables or enables the corresponding init calibration. They are not run immediately, they are just masked. In order to run them the calibrate attributes must be written 1 or Y.

  • calibrate_frm_en

  • calibrate_rx_phase_correction_en

  • calibrate_rx_qec_en

  • calibrate_tx_lol_en

  • calibrate_tx_lol_ext_en

  • calibrate_tx_qec_en

  • calibrate

/sys/bus/iio/devices/iio:device3$
cat calibrate_tx_lol_ext_en
0
/sys/bus/iio/devices/iio:device3$
echo 1 > calibrate_tx_lol_ext_en
/sys/bus/iio/devices/iio:device3$
cat calibrate_tx_lol_ext_en
1
/sys/bus/iio/devices/iio:device3$
echo 1 > calibrate

AuxADC Reading

The ADRV9009 contains an auxiliary ADC that is multiplexed to 4 input pins (AUXADC_x). The auxiliary ADC is 12 bits with an input voltage range of 0.05 V to VDDA_3P3 – 0.05 V. When enabled, the auxiliary ADC is free running. SPI reads provide the last value latched at the ADC output. TheAuxiliary ADCs can be read like any other IIO ADC.

Attributes are:

  • in_voltage[4..7]_offset

  • in_voltage[4..7]_raw

  • in_voltage[4..7]_scale

To obtain the reading in mV calculate: (in_voltage4_raw + in_voltage4_offset) * in_voltage4_scale

/sys/bus/iio/devices/iio:device3$
grep "" in_voltage4_
in_voltage4_offset:45
in_voltage4_raw:66
in_voltage4_scale:0.775194

AuxDAC Writing

The ADRV9009 contains ten identical auxiliary DACs (AUXDAC_0 to AUXDAC_9) that can supply bias voltages, analog control voltages, or other system functionality. TheAuxiliary DACs can be accessed like any other IIO DAC.

Attributes are:

  • out_voltage[2..11]_raw

  • out_voltage[2..11]_offset

  • out_voltage[2..11]_scale

/sys/bus/iio/devices/iio:device3$
grep "" out_voltage2
out_voltage2_offset: 2726
out_voltage2_raw:0
out_voltage2_scale: 0.782954
/sys/bus/iio/devices/iio:device3$
echo 1000 > out_voltage2_raw

Advanced Debug Facilities

The ADRV9009 driver supports a number of advanced debug controls via the kernel debugfs. How these device files/controls can be used is described here. The ADRV9009 Advanced Plugin directly controls these and adds a user friendly interface.

Runtime Device Driver Customization

There is a large number of customization options available. Typically these are supplied via Devicetree. However for debug and evaluation purposes these can be changed during runtime. Please note that changes will be lost if the device is unbinded or the platform is rebooted. Changes will only take affect once the initialize attribute is written 1. It should also be noted that the ADRV9009 will take a RESET, so current settings done via the main IIO API will be lost. Accessing debugfs requires root privileges. Only device files prefixed with adi, are customizable.

In order to identify if the IIO device in question (adrv9009-phy) you first need to identify the IIO device number. Therefore read the name attribute of each IIO device

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:ad9528-1
/sys/bus/iio/devices/iio:device2/name:ad7291
/sys/bus/iio/devices/iio:device3/name:adrv9009-phy
/sys/bus/iio/devices/iio:device4/name:axi-adrv9009-rx-obs-hpc
/sys/bus/iio/devices/iio:device5/name:axi-adrv9009-tx-hpc
/sys/bus/iio/devices/iio:device6/name:axi-adrv9009-rx-hpc
root@analog:~$

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

~$
cd /sys/kernel/debug/iio/iio\:device3
/sys/kernel/debug/iio/iio:device3$
ls
[--snip--]
adi,tx-settings-tx1-atten_md-b
adi,tx-settings-tx2-atten_md-b
adi,tx1-atten-ctrl-pin-enable
adi,tx1-atten-ctrl-pin-step-size
adi,tx1-atten-ctrl-pin-tx-atten-dec-pin
adi,tx1-atten-ctrl-pin-tx-atten-inc-pin
adi,tx2-atten-ctrl-pin-enable
adi,tx2-atten-ctrl-pin-step-size
adi,tx2-atten-ctrl-pin-tx-atten-dec-pin
adi,tx2-atten-ctrl-pin-tx-atten-inc-pin
bist_framer_a_prbs
bist_framer_b_prbs
bist_tone
direct_reg_access
initialize

Example to change from internal to external TX LO

/sys/kernel/debug/iio/iio:device3$
cat adi,dig-clocks-rf-pll-use-external-lo
0
/sys/kernel/debug/iio/iio:device3$
echo 1 > adi,dig-clocks-rf-pll-use-external-lo
/sys/kernel/debug/iio/iio:device3$
echo 1 > initialize

Build-In Self-Test (BIST)

Controling these attribute files directly take effect and therefore don’t require the initialize sequence. Test functionality exposed here is only meant to route or inject test patterns/data than can be used to validate the Digital Interface or functionality of the device.

BIST Tone

Digital numerically controlled oscillator (NCO) to create a CW test tone on the Tx1 and Tx2 RF outputs. The TxAttenuation is forced in this function to max analog output power, but the digital attenuation is backed off 6dB to make sure the digital filter does not clip and cause spurs in the tx spectrum.

SYNTAX:

bist_tone <Enable> <TX1 Tone Frequency in kHz> <TX2 Tone Frequency in kHz>

NCO Tone frequency Valid range from -IQrate/2 to IQrate/2

Enable

Value

Function

0

Disable

1

Enable

Example: Inject 3MHz tone into TX1 and 5MHz into TX2

/sys/kernel/debug/iio/iio:device3$
echo 5 > bist_framer_a_prbs

PRBS

Pseudorandom Binary Sequence (PRBS) that can either injected into the RX or OBS path.

SYNTAX:

bist_framer_a_prbs <Value>
bist_framer_b_prbs <Value>
bist_serializer_a_prbs <Value>
bist_serializer_b_prbs <Value>

Injection Point Framer A/B

Value

Function and polynomial order

ADC_DATA

0

CHECKERBOARD

1

TOGGLE0_1

2

PRBS31

3

PRBS23

4

PRBS15

5

PRBS9

6

PRBS7

7

RAMP

8

PATTERN_REPEAT

14

PATTERN_ONCE

15

Example: Inject PRBS15 into RX

/sys/kernel/debug/iio/iio:device3$
echo 5 > bist_framer_a_prbs

Loopback

Deframer framer loopback. Injects TX data back into the digital RX path, while bypassing all the analog and converter sections.

SYNTAX:

bist_framer_a_loopback <Value>
bist_framer_b_loopback <Value>

Enable

Value

Function

0

Disable

1

Enable

Example: Enable framer A loopback

/sys/kernel/debug/iio/iio:device3$
echo 1 > bist_framer_a_loopback

GPIO 3v3 Controls

This attribute allows controlling the 12 GPIO3v3 via debugfs. In order to use these pins, the adi,gpio3v3-source-control attribute must be set. Please refer to the reference manual UG-1295. In addition, dedicated output pins must be masked via adi,gpio3v3-output-enable-mask.

adi,gpio3v3-source-control = <0x333>;
adi,gpio3v3-output-enable-mask = <0xFFF>;
adi,gpio3v3-output-level-mask = <0x0>;

For test purposes these attributes can be also set via debugfs.

~$
cd /sys/kernel/debug/iio/iio:device3
/sys/kernel/debug/iio/iio:device3$
echo 0x333 > adi,gpio3v3-source-control
/sys/kernel/debug/iio/iio:device3$
echo 0xFFF > adi,gpio3v3-output-enable-mask
/sys/kernel/debug/iio/iio:device3$
echo 1 > initialize

The gpio3v3 debugfs control allows setting individual GPIOs by number 0…11. Or altogether using the 0xFFF mask. GPIOs masked as inputs can also be read.

SYNTAX:

gpio3v3 <Identifier> <Value>

Enable

Value

Function

0

Disable

1

Enable

X

Enable Mask if Identifier=0xFFF

Example:

/sys/kernel/debug/iio/iio:device3$
echo 0 1 > gpio3v3
/sys/kernel/debug/iio/iio:device3$
echo 0xFFF 0x123 > gpio3v3
/sys/kernel/debug/iio/iio:device3$
echo 0xFFF 0x0 > gpio3v3

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.

Tip

To simplify direct register access you may want to use the libiio Libiio 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

~$
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

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

~$
cd /sys/kernel/debug/iio/iio\:device1
/sys/kernel/debug/iio/iio:device1$
ls direct_reg_access
direct_reg_access

Reading

/sys/kernel/debug/iio/iio:device1$
echo 0x7 > direct_reg_access
/sys/kernel/debug/iio/iio:device1$
cat direct_reg_access
0x40

Writing

/sys/kernel/debug/iio/iio:device1$
echo 0x7 0x50  > direct_reg_access
/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 ADI HDL cores can be found at section “Register Map” of each IP Cores documentation (example).

/sys/kernel/debug/iio/iio:device6$
echo 0x80000000 > direct_reg_access
/sys/kernel/debug/iio/iio:device6$
cat direct_reg_access
0x80062