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 up to 508 ps and fine resolution down to 2 ps. 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
Files
Function |
File |
|
|---|---|---|
driver |
||
devicetree bindings |
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,adar4001reg: 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 |
Enabling Linux driver support
Configure kernel with make menuconfig (alternatively use make xconfig or
make qconfig)
Note
The ADAR4000 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 ADAR4000 and ADR4001 Beamformer driver
[--snip--]
Driver testing / API
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#
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
Device attributes
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 memory fifo instant_direct reset mute
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
Show device name
root@analog:/sys/bus/iio/devices/iio:device0> cat name
adar4000
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
directmode.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: The device will reset, clearing any stored data, and returning to its initial state.
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
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:
root@analog:/sys/bus/iio/devices/iio:device0# echo 0, 1, 32, 28 > 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