ADAR4000

ADAR4000/ADAR4001 2 GHz to 18 GHz, Single Beam, 4-Element Beamformer Linux Device Driver.

The ADAR4000 and ADAR4001 are wideband beamformer ICs operating from 2 GHz to 18 GHz, designed for transmit and receive phased array applications, respectively. Both feature a true time delay core for beam-squint free operation, with configurable delays of 0 to 254 ps in 2 ps steps, or 0 to 508 ps in 4 ps steps. Each path includes a 31.5 dB digital step attenuator with 0.5 dB steps. They support SPI control for up to 16 devices and include on-chip RAM and FIFO for storing and sequencing beamstates.

Supported Devices

Evaluation Boards

Description

This is a Linux industrial I/O (Linux Industrial I/O Subsystem) 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 Linux Industrial I/O Subsystem for more information.

Source Code

Status

Source

Mainlined?

adar4000x.c

No

Files

Function

File

driver

adar4000x.c

devicetree bindings

adi,adar400x.yaml

Adding Linux driver support

Kernel configuration

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

Note

The ADAR4000 driver depends on CONFIG_SPI

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 buffer support within IIO
        -*-   Enable triggered sampling support

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

        <*>   Analog Devices ADAR4000 and ADR4001 Beamformer driver

        [--snip--]

Devicetree configuration

Example Linux Device-Tree Initialization

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

Required devicetree properties:

  • compatible: Should always be adi,adar4000, adi,adar4001

  • reg: SPI slave select number

Optional properties:

  • adi,num-devices: Number of devices connected to the SPI bus. Default is 1.

Function

File

RPI Device Tree

Driver testing

Important

SPI writes and reads for certain attributes are delayed because of how the hardware behaves. So, updates to certain properties take a couple of seconds to be reflected in a read-back from hardware.

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
iio:device0  iio:device1  iio:device2  iio:device3
root:/sys/bus/iio/devices> cd iio:device0
root@analog:/sys/bus/iio/devices/iio:device0# ls -l
total 0
-rw-r--r-- 1 root root 4096 Oct  1 14:25 active_device
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_bias_mute_EL0A
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_bias_mute_EL1A
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_bias_mute_EL1B
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_bias_mute_EL2A
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_bias_mute_EL0B
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_bias_mute_EL2B
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_bias_mute_EL3A
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_bias_mute_EL3B
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_bias_operational_EL0A
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_bias_operational_EL0B
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_bias_operational_EL1A
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_bias_operational_EL1B
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_bias_operational_EL2A
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_bias_operational_EL2B
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_bias_operational_EL3A
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_bias_operational_EL3B
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_bias_reset_EL0A
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_bias_reset_EL0B
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_bias_reset_EL1A
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_bias_reset_EL1B
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_bias_reset_EL2A
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_bias_reset_EL2B
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_bias_reset_EL3A
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_bias_reset_EL3B
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_bias_sleep_EL0A
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_bias_sleep_EL0B
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_bias_sleep_EL1A
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_bias_sleep_EL1B
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_bias_sleep_EL2A
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_bias_sleep_EL2B
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_bias_sleep_EL3A
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_bias_sleep_EL3B
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_en_mute_EL0
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_en_mute_EL1
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_en_mute_EL2
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_en_mute_EL3
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_en_operational_EL0
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_en_operational_EL1
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_en_operational_EL2
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_en_operational_EL3
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_en_reset_EL0
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_en_reset_EL1
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_en_reset_EL2
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_en_reset_EL3
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_en_sleep_EL0
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_en_sleep_EL1
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_en_sleep_EL2
-rw-r--r-- 1 root root 4096 Oct  1 14:25 amp_en_sleep_EL3
-r--r--r-- 1 root root 4096 Oct  1 14:25 beam0_fifo_rd
-r--r--r-- 1 root root 4096 Oct  1 14:25 beam0_fifo_wr
-rw-r--r-- 1 root root 4096 Oct  1 14:25 beam0_mode
-r--r--r-- 1 root root 4096 Oct  1 14:25 beam0_mode_available
-rw-r--r-- 1 root root 4096 Oct  1 14:25 beam0_ram_start
-rw-r--r-- 1 root root 4096 Oct  1 14:25 beam0_ram_stop
-rw-r--r-- 1 root root 4096 Oct  1 14:25 beam0_sequencer_ptr_index
-rw-r--r-- 1 root root 4096 Oct  1 14:25 beam0_update
--w------- 1 root root 4096 Oct  1 14:25 beamstate_fifo
--w------- 1 root root 4096 Oct  1 14:25 beamstate_ram
-r--r--r-- 1 root root 4096 Oct  1 14:25 name
lrwxrwxrwx 1 root root    0 Oct  1 14:25 of_node -> ../../../../../../../../firmware/devicetree/base/soc/spi@7e204000/adar4000@0
-rw-r--r-- 1 root root 4096 Oct  1 14:25 out_phase0_raw
-rw-r--r-- 1 root root 4096 Oct  1 14:25 out_phase0_scale
-rw-r--r-- 1 root root 4096 Oct  1 14:25 out_phase1_raw
-rw-r--r-- 1 root root 4096 Oct  1 14:25 out_phase1_scale
-rw-r--r-- 1 root root 4096 Oct  1 14:25 out_phase2_raw
-rw-r--r-- 1 root root 4096 Oct  1 14:25 out_phase2_scale
-rw-r--r-- 1 root root 4096 Oct  1 14:25 out_phase3_raw
-rw-r--r-- 1 root root 4096 Oct  1 14:25 out_phase3_scale
-rw-r--r-- 1 root root 4096 Oct  1 14:25 out_power0_raw
-rw-r--r-- 1 root root 4096 Oct  1 14:25 out_power0_scale
-rw-r--r-- 1 root root 4096 Oct  1 14:25 out_power1_raw
-rw-r--r-- 1 root root 4096 Oct  1 14:25 out_power1_scale
-rw-r--r-- 1 root root 4096 Oct  1 14:25 out_power2_raw
-rw-r--r-- 1 root root 4096 Oct  1 14:25 out_power2_scale
-rw-r--r-- 1 root root 4096 Oct  1 14:25 out_power3_raw
-rw-r--r-- 1 root root 4096 Oct  1 14:25 out_power3_scale
drwxr-xr-x 2 root root    0 Oct  1 14:25 power
lrwxrwxrwx 1 root root    0 Oct  1 14:25 subsystem -> ../../../../../../../../bus/iio
-rw-r--r-- 1 root root 4096 Oct  1 14:25 uevent
-r--r--r-- 1 root root 4096 Oct  1 14:25 waiting_for_supplier
root@analog:/sys/bus/iio/devices/iio:device0#

Identify the device

root@analog:/sys/bus/iio/devices/iio:device0> cat name
adar4000

Channel attributes

  • raw - Multiplied with scale will result in a physical value.

  • scale - Multiplied with raw will result in a physical value.

  • delay = raw * scale

  • gain = raw * scale

Direct Mode

Write:

root@analog:/sys/bus/iio/devices/iio:device0# echo direct > beam0_mode

Read :

root@analog:/sys/bus/iio/devices/iio:device0# cat beam0_mode
direct

This mode means that data will be saved into registers corresponding to the direct mode.

Writing beamstate in direct mode:
root@analog:/sys/bus/iio/devices/iio:device0# echo 10 > out_phase0_raw
root@analog:/sys/bus/iio/devices/iio:device0# echo 11 > out_phase1_raw
root@analog:/sys/bus/iio/devices/iio:device0# echo 12 > out_phase2_raw
root@analog:/sys/bus/iio/devices/iio:device0# echo 13 > out_phase3_raw

root@analog:/sys/bus/iio/devices/iio:device0# echo 21 > out_power0_raw
root@analog:/sys/bus/iio/devices/iio:device0# echo 22 > out_power1_raw
root@analog:/sys/bus/iio/devices/iio:device0# echo 23 > out_power2_raw
root@analog:/sys/bus/iio/devices/iio:device0# echo 24 > out_power3_raw

Input value can be verified by reading the channel attribute.

root@analog:/sys/bus/iio/devices/iio:device0# cat out_phase0_raw
10

To load the current beamstate in the direct control registers into the VAPs, write 1 to beam0_update.

root@analog:/sys/bus/iio/devices/iio:device0# echo 1 > beam0_update

RAM

Custom 64 beamstates can be loaded at any time via the beamstate_ram attribute in table format. Table must be in this format:

Index

Element

Delay

Attenuation

Example beamstate table:

<index elements delay attn ADAR400x beamstate>
0, 0, 12, 23
0, 1, 45, 11
0, 2, 34, 7
0, 3, 29, 18
1, 0, 5, 22
1, 1, 16, 33
1, 2, 8, 44
1, 3, 21, 9
...
63, 0, 8, 18
63, 1, 21, 7
63, 2, 3, 30
63, 3, 17, 13
</beamstate>

Note

Do not modify or remove the header and footer; it will be used as a mark for the driver.

Last row denotes beamstate index 63, element 3 with a delay value of 17 and attenuation value of 13.

The table can be applied to the attribute by setting first the beam mode to ram.

root@analog:/sys/bus/iio/devices/iio:device0# echo ram > beam0_mode

Allow permission to write on the attribute.

root@analog:/sys/bus/iio/devices/iio:device0# chmod 666 beamstate_ram

Lastly apply the beamstate table. Look through your beamstate table.

root@analog:/sys/bus/iio/devices/iio:device0# cat ram_beamstate > beamstate_ram

Write 1 to beam0_update advances the active sequencer pointer and loads that beamstate data into the VAPs.

root@analog:/sys/bus/iio/devices/iio:device0# echo 1 > beam0_update

Alternatively, beamstate data can be applied directly using echo command. Example:

Write one complete four-element beamstate in a single sysfs write. Elements must be ordered 0, 1, 2, 3; writing only element 1 does not commit a beamstate.

printf '0, 0, 12, 23\n0, 1, 32, 28\n0, 2, 34, 7\n0, 3, 29, 18\n' > beamstate_ram

FIFO

Similar process with RAM mode. Table can be modified up to 16 beamstates.

root@analog:/sys/bus/iio/devices/iio:device0# echo fifo > beam0_mode
root@analog:/sys/bus/iio/devices/iio:device0# chmod 666 beamstate_fifo
root@analog:/sys/bus/iio/devices/iio:device0# cat fifo_beamstate > beamstate_fifo

Write 1 to beam0_update to dequeue the next beamstate in the FIFO and load it into the VAPs.

root@analog:/sys/bus/iio/devices/iio:device0# echo 1 > beam0_update

Attribute reference

  • active_device – Select device for multiple connected devices

  • beam0_fifo_rd - FIFO read pointer

  • beam0_fifo_wr - FIFO write pointer

  • beam0_mode - Beam operation mode

  • beam0_mode_available - Possible values: direct ram fifo instant_direct mute reset

  • beam0_ram_index - Starting position in memory for saving beamstates

  • beam0_ram_start - Start beamstate in memory. Default: 0

  • beam0_ram_stop - Stop beamstate in memory. Default: 63

  • beam0_update - Update beamstate

  • beamstate_ram – Beamstate data for RAM mode, can be in table format or echo command

  • beamstate_fifo – Beamstate data for FIFO mode

  • amp_bias_mute_ELxA

  • amp_bias_operational_ELxA

  • amp_bias_operational_ELxA

  • amp_bias_reset_ELxA

  • amp_bias_sleep_ELxA

  • amp_bias_sleep_ELxA

  • amp_en_mute_ELx

  • amp_en_operational_ELx

  • amp_en_operational_ELx

  • amp_en_reset_ELx

  • amp_en_sleep_ELx

  • amp_en_sleep_ELx

Beam components

  • Beam0: power0, phase0, power1, phase1, power2, phase2, power3, phase3

Read/Write Register

Read scratchpad:

root@analog:/sys/bus/iio/devices/iio:device0# iio_reg adar4000 0x0a
0x0

Write scratchpad:

root@analog:/sys/bus/iio/devices/iio:device0# iio_reg adar4000 0x0a 0x12

Beamstate Mode

Description:

  • beam0_mode - Specifies the mode corresponding to where the values are saved. The device can be configured into one of the following modes:

  • Direct: Data will be saved into registers corresponding to the direct mode.

  • RAM: Data will be saved into RAM, allowing for temporary storage and faster access.

  • FIFO: Data will be saved into a First-In-First-Out queue, ensuring that the first data entered is the first to be processed.

  • Reset: Select the predefined reset beamstate and amplifier-bias settings. This beam mode is not a device software reset and does not clear all RAM.

  • Mute: The device will enter a mute state, where no data is processed or saved.

When configuring beam0_mode to mute or reset this will set the commanded beam to a user predefined beamstate and bias setting for the amplifiers.

root@analog:/sys/bus/iio/devices/iio:device0# cat beam0_mode_available
direct ram fifo instant_direct mute reset

More Information