Post Go back to editing

AD9081 Pyadi-IIO & Device Tree Channels

Category: Software
Product Number: AD9081

Good evening,

I have an AD9081 running on a custom carrier using the VCK190 example HDL, the meta-adi petalinux layer, and Pyadi-iio. The system is interfacing with my host machine over the network.

I am confused about the mapping of the real ADC channels (ADC0...ADC3) and how these are exposed from the device tree to Pyadi-IIO. I am more confused by this process for the DACs as I cannot see these in Pyadi-IIO at all, with the example ad9081.py script throwing the exception 'TX mapping exceeds available channels' in response to the command "dev.tx_enabled_channels = [0]".

I have attached my device tree below, can you please advise how I can expose 4xADC and 4xDAC channels to Pyadi-IIO? I am looking to run frequency response measurements so I just need real data (no I/Q). As it stands I have the channels voltage0_i/q and voltage1_i/q exposed in Pyadi-IIO, and any explanation how the device tree below maps to that would be very appreciated.

Thanks again for your invaluable support!

All the best

Jack

// SPDX-License-Identifier: GPL-2.0
/*
 * Analog Devices AD9081-FMC-EBZ
 * https://wiki.analog.com/resources/tools-software/linux-drivers/iio-mxfe/ad9081
 * https://wiki.analog.com/resources/eval/user-guides/ad9081_fmca_ebz/ad9081_fmca_ebz_hdl
 *
 * hdl_project: <ad9081_fmca_ebz/vck190>
 * board_revision: <>
 *
 * Copyright (C) 2019-2023 Analog Devices Inc.
 */

#include "versal-vck190-revA.dts"
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/iio/adc/adi,ad9081.h>
#include <dt-bindings/jesd204/adxcvr.h>
#include <dt-bindings/iio/frequency/hmc7044.h>

/* RX path */
#define AD9081_RX_LANERATE_KHZ	24750000
#define AD9081_RX_LINK_CLK	375000000

/* TX path */
#define AD9081_TX_LANERATE_KHZ	24750000
#define AD9081_TX_LINK_CLK	375000000

/ {
	model = "DTS Edit 2";

	chosen {
		bootargs = "console=ttyAMA0 earlycon=pl011,mmio32,0xFF000000,115200n8 clk_ignore_unused root=/dev/mmcblk0p2 rw rootfstype=ext4 rootwait";
		stdout-path = "serial0:115200";
	};

	fpga_axi: fpga-axi@0 {
		interrupt-parent = <&gic>;
		compatible = "simple-bus";
		#address-cells = <0x1>;
		#size-cells = <0x1>;
		ranges = <0 0 0 0xffffffff>;

		clocks {
			rx_fixed_linerate: clock@0 {
				#clock-cells = <0>;
				compatible = "fixed-clock";
				clock-frequency = <AD9081_RX_LANERATE_KHZ>;
				clock-output-names = "rx_lane_clk";
			};

			tx_fixed_linerate: clock@1 {
				#clock-cells = <0>;
				compatible = "fixed-clock";
				clock-frequency = <AD9081_TX_LANERATE_KHZ>;
				clock-output-names = "tx_lane_clk";
			};

			rx_fixed_link_clk: clock@2 {
				#clock-cells = <0>;
				compatible = "fixed-clock";
				clock-frequency = <AD9081_RX_LINK_CLK>;
				clock-output-names = "rx_link_clk";
			};

			tx_fixed_link_clk: clock@3 {
				#clock-cells = <0>;
				compatible = "fixed-clock";
				clock-frequency = <AD9081_TX_LINK_CLK>;
				clock-output-names = "tx_link_clk";
			};
		};

		axi_gpio: gpio@a4000000 {
			#gpio-cells = <2>;
			#interrupt-cells = <2>;
			clock-names = "s_axi_aclk";
			clocks = <&versal_clk PMC_PL0_REF>;
			compatible = "xlnx,axi-gpio-2.0", "xlnx,xps-gpio-1.00.a";
			gpio-controller;
			interrupt-controller;
			interrupt-names = "ip2intc_irpt";
			interrupt-parent = <&gic>;
			interrupts = <0 84 4>;
			reg = <0xa4000000 0x1000>;
			xlnx,all-inputs = <0x0>;
			xlnx,all-inputs-2 = <0x0>;
			xlnx,all-outputs = <0x0>;
			xlnx,all-outputs-2 = <0x0>;
			xlnx,dout-default = <0x00000000>;
			xlnx,dout-default-2 = <0x00000000>;
			xlnx,gpio-width = <0x20>;
			xlnx,gpio2-width = <0x20>;
			xlnx,interrupt-present = <0x1>;
			xlnx,is-dual = <0x1>;
			xlnx,tri-default = <0xFFFFFFFF>;
			xlnx,tri-default-2 = <0xFFFFFFFF>;
		};

		rx_dma: dma@bc420000 {
			compatible = "adi,axi-dmac-1.00.a";
			reg = <0xbc420000 0x10000>;
			#dma-cells = <1>;
			#clock-cells = <0>;
			interrupts = <0 97 IRQ_TYPE_LEVEL_HIGH>;
			clocks = <&versal_clk PMC_PL1_REF>;

			adi,channels {
				#size-cells = <0>;
				#address-cells = <1>;

				dma-channel@0 {
					reg = <0>;
					adi,source-bus-type = <2>;
					adi,destination-bus-type = <0>;
				};
			};
		};

		tx_dma: dma@bc430000  {
			compatible = "adi,axi-dmac-1.00.a";
			reg = <0xbc430000 0x10000>;
			#dma-cells = <1>;
			#clock-cells = <0>;
			interrupts = <0 96 IRQ_TYPE_LEVEL_HIGH>;
			clocks = <&versal_clk PMC_PL1_REF>;

			adi,channels {
				#size-cells = <0>;
				#address-cells = <1>;

				dma-channel@0 {
					reg = <0>;
					adi,source-bus-type = <0>;
					adi,destination-bus-type = <2>;
				};
			};
		};

		axi_ad9081_core_rx: axi-ad9081-rx-hpc@a4a10000 {
			compatible = "adi,axi-ad9081-rx-1.0";
			reg = <0xa4a10000 0x8000>;
			dmas = <&rx_dma 0>;
			dma-names = "rx";
			spibus-connected = <&trx0_ad9081>;

			jesd204-device;
			#jesd204-cells = <2>;
			jesd204-inputs = <&axi_ad9081_rx_jesd 0 FRAMER_LINK0_RX>;
		};

		axi_ad9081_core_tx: axi-ad9081-tx-hpc@a4b10000 {
			compatible = "adi,axi-ad9081-tx-1.0-real";
			reg = <0xa4b10000 0x4000>;
			dmas = <&tx_dma 0>;
			dma-names = "tx";
			clocks = <&trx0_ad9081 1>;
			clock-names = "sampl_clk";
			spibus-connected = <&trx0_ad9081>;

			jesd204-device;
			#jesd204-cells = <2>;
			jesd204-inputs = <&axi_ad9081_tx_jesd 0 DEFRAMER_LINK0_TX>;
		};

		axi_ad9081_rx_jesd: axi-jesd204-rx@a4a90000 {
			compatible = "adi,axi-jesd204-rx-1.0";
			reg = <0xa4a90000 0x1000>;

			interrupts = <0 95 IRQ_TYPE_LEVEL_HIGH>;

			clocks = <&versal_clk PMC_PL0_REF>, <&hmc7044 10>, <&rx_fixed_link_clk>, <&rx_fixed_linerate>;
			clock-names = "s_axi_aclk", "device_clk", "link_clk", "lane_clk";

			#clock-cells = <0>;
			clock-output-names = "jesd_rx_lane_clk";

			jesd204-device;
			#jesd204-cells = <2>;
			jesd204-inputs = <&hmc7044 0 FRAMER_LINK0_RX>;
		};

		axi_ad9081_tx_jesd: axi-jesd204-tx@a4b90000 {
			compatible = "adi,axi-jesd204-tx-1.0";
			reg = <0xa4b90000 0x1000>;

			interrupts = <0 94 IRQ_TYPE_LEVEL_HIGH>;

			clocks = <&versal_clk PMC_PL0_REF>, <&hmc7044 6>, <&tx_fixed_link_clk>, <&tx_fixed_linerate>;
			clock-names = "s_axi_aclk", "device_clk", "link_clk", "lane_clk";

			#clock-cells = <0>;
			clock-output-names = "jesd_tx_lane_clk";

			jesd204-device;
			#jesd204-cells = <2>;
			jesd204-inputs = <&hmc7044 0 DEFRAMER_LINK0_TX>;
		};

		axi_sysid_0: axi-sysid-0@a5000000 {
			compatible = "adi,axi-sysid-1.00.a";
			reg = <0xa5000000 0x10000>;
		};
  

	};
  
};

&gic {
	num_cpus = <2>;
	num_interrupts = <96>;
};

&lpd_dma_chan0 {
	status = "okay";
};

&lpd_dma_chan1 {
	status = "okay";
};

&lpd_dma_chan2 {
	status = "okay";
};

&lpd_dma_chan3 {
	status = "okay";
};

&lpd_dma_chan4 {
	status = "okay";
};

&lpd_dma_chan5 {
	status = "okay";
};

&lpd_dma_chan6 {
	status = "okay";
};

&lpd_dma_chan7 {
	status = "okay";
};

&cci {
	status = "okay";
};

&smmu {
	status = "okay";
};

&i2c1 {
	status = "disabled";
};

&gpio1 {
	status = "okay";
};

&qspi {
	is-dual = <1>;
	num-cs = <1>;
	spi-rx-bus-width = <4>;
	spi-tx-bus-width = <4>;
	status = "okay";
};

&sdhci1 {
	clock-frequency = <199999985>;
	status = "okay";
};

&serial0 {
	cts-override ;
	device_type = "serial";
	port-number = <0>;
};

&spi0 {
	is-decoded-cs = <0>;
	num-cs = <3>;
	status = "okay";
};

&spi1 {
	is-decoded-cs = <0>;
	num-cs = <3>;
	status = "okay";
};

&ttc0 {
	status = "okay";
};

&ref_clk {
	clock-frequency = <50000000>;
};

&gem0 {
	local-mac-address = [00 0a 35 ad 90 81];
};

&fpga_axi {
	axi_data_offload_tx: axi-data-offload-0@bc440000 {
		compatible = "adi,axi-data-offload-1.0.a";
		reg = <0xbc440000 0x10000>;
	};

	axi_data_offload_rx: axi-data-offload-1@bc450000 {
		compatible = "adi,axi-data-offload-1.0.a";
		reg = <0xbc450000 0x10000>;
	};
};

&axi_ad9081_core_tx {
	adi,axi-data-offload-connected = <&axi_data_offload_tx>;
	adi,axi-pl-fifo-enable;
};

#define fmc_spi spi0

&spi1 {
	status = "okay";

	hmc7044: hmc7044@0 {
		#address-cells = <1>;
		#size-cells = <0>;
		#clock-cells = <1>;
		compatible = "adi,hmc7044";
		reg = <0>;
		spi-max-frequency = <1000000>;

		jesd204-device;
		#jesd204-cells = <2>;
		jesd204-sysref-provider;

		adi,jesd204-max-sysref-frequency-hz = <2000000>; /* 2 MHz */

		/*
		 * There are different versions of the AD9081-FMCA-EBZ & AD9082-FMCA-EBZ
		 * VCXO = 122.880 MHz, XO = 122.880MHz (AD9081-FMC-EBZ & AD9082-FMC-EBZ)
		 * VCXO = 100.000 MHz, XO = 100.000MHz (AD9081-FMC-EBZ-A2 & AD9082-FMC-EBZ-A2)
		 * To determine which board is which, read the freqency printed on the VCXO
		 * or use the fru-dump utility:
		 * #fru-dump -b /sys/bus/i2c/devices/15-0050/eeprom
		 */

		//adi,pll1-clkin-frequencies = <122880000 30720000 0 0>;
		//adi,vcxo-frequency = <122880000>;

		adi,pll1-clkin-frequencies = <100000000 10000000 0 0>;
		adi,pll1-ref-prio-ctrl = <0xE1>; /* prefer CLKIN1 -> CLKIN0 -> CLKIN2 -> CLKIN3 */
		adi,pll1-ref-autorevert-enable;
		adi,vcxo-frequency = <100000000>;

		adi,pll1-loop-bandwidth-hz = <200>;
		adi,pll1-charge-pump-current-ua = <720>;
		adi,pfd1-maximum-limit-frequency-hz = <1000000>; /* 1 MHz */

		adi,pll2-output-frequency = <3000000000>;

		adi,sysref-timer-divider = <1024>;
		adi,pulse-generator-mode = <0>;

		adi,clkin0-buffer-mode  = <0x07>;
		adi,clkin1-buffer-mode  = <0x07>;
		adi,oscin-buffer-mode = <0x15>;

		adi,gpi-controls = <0x00 0x00 0x00 0x00>;
		adi,gpo-controls = <0x37 0x33 0x00 0x00>;

		clock-output-names =
		"hmc7044_out0", "hmc7044_out1", "hmc7044_out2",
		"hmc7044_out3", "hmc7044_out4", "hmc7044_out5",
		"hmc7044_out6", "hmc7044_out7", "hmc7044_out8",
		"hmc7044_out9", "hmc7044_out10", "hmc7044_out11",
		"hmc7044_out12", "hmc7044_out13";

		hmc7044_c0: channel@0 {
			reg = <0>;
			adi,extended-name = "CORE_CLK_RX";
			adi,divider = <8>;	// 375
			adi,driver-mode = <HMC7044_DRIVER_MODE_LVDS>;	// LVDS

		};

		hmc7044_c2: channel@2 {
			reg = <2>;
			adi,extended-name = "DEV_REFCLK";
			adi,divider = <8>;	// 375
			adi,driver-mode = <HMC7044_DRIVER_MODE_LVDS>;	// LVDS
		};

		hmc7044_c3: channel@3 {
			reg = <3>;
			adi,extended-name = "DEV_SYSREF";
			adi,divider = <768>;	// 3.90625
			adi,driver-mode = <HMC7044_DRIVER_MODE_LVDS>;	// LVDS
			adi,jesd204-sysref-chan;
		};

		hmc7044_c6: channel@6 {
			reg = <6>;
			adi,extended-name = "CORE_CLK_TX";
			adi,divider = <12>;	// 250 = LR/66*4/6
			adi,driver-mode = <HMC7044_DRIVER_MODE_LVDS>;	// LVDS
		};

		hmc7044_c8: channel@8 {
			reg = <8>;
			adi,extended-name = "FPGA_REFCLK1";
			adi,divider = <4>;	// 750
			adi,driver-mode = <HMC7044_DRIVER_MODE_LVDS>;	// LVDS
		};

		hmc7044_c10: channel@10 {
			reg = <10>;
			adi,extended-name = "CORE_CLK_RX";
			adi,divider = <12>;	// 250 = LR/66*4/6
			adi,driver-mode = <HMC7044_DRIVER_MODE_LVDS>;	// LVDS
		};

		hmc7044_c12: channel@12 {
			reg = <12>;
			adi,extended-name = "FPGA_REFCLK";
			adi,divider = <8>;	// 375
			adi,driver-mode = <HMC7044_DRIVER_MODE_LVDS>;	// LVDS
		};

		hmc7044_c13: channel@13 {
			reg = <13>;
			adi,extended-name = "FPGA_SYSREF";
			adi,divider = <768>;	// 3.90625
			adi,driver-mode = <HMC7044_DRIVER_MODE_LVDS>;	// LVDS
			adi,jesd204-sysref-chan;
		};
	};
};

&fmc_spi {

	trx0_ad9081: ad9081@0 {
		#address-cells = <1>;
		#size-cells = <0>;
		compatible = "adi,ad9081";
		reg = <0>;
		spi-max-frequency = <5000000>;

		/* Clocks */
		clocks = <&hmc7044 2>;
		clock-names = "dev_clk";

		clock-output-names = "rx_sampl_clk", "tx_sampl_clk";
		#clock-cells = <1>;

		reset-gpios = <&axi_gpio 23 0>;
		sysref-req-gpios = <&axi_gpio 11 0>;
		rx2-enable-gpios = <&axi_gpio 25 0>;
		rx1-enable-gpios = <&axi_gpio 24 0>;
		tx2-enable-gpios = <&axi_gpio 27 0>;
		tx1-enable-gpios = <&axi_gpio 26 0>;

		jesd204-device;
		#jesd204-cells = <2>;
		jesd204-top-device = <0>; /* This is the TOP device */
		jesd204-link-ids = <FRAMER_LINK0_RX DEFRAMER_LINK0_TX>;

		jesd204-inputs =
		<&axi_ad9081_core_rx 0 FRAMER_LINK0_RX>,
		<&axi_ad9081_core_tx 0 DEFRAMER_LINK0_TX>;

		adi,tx-dacs {
			#size-cells = <0>;
			#address-cells = <1>;
			adi,dac-frequency-hz = /bits/ 64 <4000000000>;

			adi,main-data-paths {
				#address-cells = <1>;
				#size-cells = <0>;
				adi,interpolation = <1>;

				ad9081_dac0: dac@0 {
					reg = <0>;
					adi,crossbar-select = <&ad9081_tx_fddc_chan0>;
					adi,nco-frequency-shift-hz = /bits/ 64 <0>; /* 200 MHz */
				};

				ad9081_dac1: dac@1 {
					reg = <1>;
					adi,crossbar-select = <&ad9081_tx_fddc_chan1>;
					adi,nco-frequency-shift-hz = /bits/ 64 <0>; /* 1 GHz */
				};

				ad9081_dac2: dac@2 {
					reg = <2>;
					adi,crossbar-select = <&ad9081_tx_fddc_chan2>;
					adi,nco-frequency-shift-hz = /bits/ 64 <0>;  /* 2 GHz */
				};

				ad9081_dac3: dac@3 {
					reg = <3>;
					adi,crossbar-select = <&ad9081_tx_fddc_chan3>;
					adi,nco-frequency-shift-hz = /bits/ 64 <0>; /* 3 GHz */
				};
			};

			adi,channelizer-paths {
				#address-cells = <1>;
				#size-cells = <0>;
				adi,interpolation = <1>;

				ad9081_tx_fddc_chan0: channel@0 {
					reg = <0>;
					adi,gain = <0>; /* 2048 * 10^(gain_dB/20) */
					adi,nco-frequency-shift-hz =  /bits/ 64 <0>;
				};

				ad9081_tx_fddc_chan1: channel@1 {
					reg = <1>;
					adi,gain = <0>; /* 2048 * 10^(gain_dB/20) */
					adi,nco-frequency-shift-hz =  /bits/ 64 <0>;
				};

				ad9081_tx_fddc_chan2: channel@2 {
					reg = <2>;
					adi,gain = <0>; /* 2048 * 10^(gain_dB/20) */
					adi,nco-frequency-shift-hz =  /bits/ 64 <0>;
				};

				ad9081_tx_fddc_chan3: channel@3 {
					reg = <3>;
					adi,gain = <0>; /* 2048 * 10^(gain_dB/20) */
					adi,nco-frequency-shift-hz =  /bits/ 64 <0>;
				};
			};

			adi,jesd-links {
				#size-cells = <0>;
				#address-cells = <1>;

				ad9081_tx_jesd_l0: link@0 {
					#address-cells = <1>;
					#size-cells = <0>;
					reg = <0>;
	
					adi,logical-lane-mapping = /bits/ 8 <0 2 7 6 1 5 4 3>;
					adi,link-mode = <35>;			/* JESD Quick Configuration Mode */
					adi,subclass = <1>;			/* JESD SUBCLASS 0,1,2 */
					adi,version = <2>;			/* JESD VERSION 0=204A,1=204B,2=204C */
					adi,dual-link = <0>;			/* JESD Dual Link Mode */
					adi,converters-per-device = <4>;	/* JESD M */
					adi,octets-per-frame = <3>;		/* JESD F */
					adi,frames-per-multiframe = <256>;	/* JESD K */
					adi,converter-resolution = <12>;	/* JESD N */
					adi,bits-per-sample = <12>;		/* JESD NP' */
					adi,control-bits-per-sample = <0>;	/* JESD CS */
					adi,lanes-per-device = <8>;		/* JESD L */
					adi,samples-per-converter-per-frame = <4>; /* JESD S */
					adi,high-density = <0>;			/* JESD HD */

					adi,tpl-phase-adjust = <0x3b>;
				};
			};
		};

		adi,rx-adcs {
			#size-cells = <0>;
			#address-cells = <1>;
			adi,adc-frequency-hz = /bits/ 64 <4000000000>;

			adi,main-data-paths {
				#address-cells = <1>;
				#size-cells = <0>;

				ad9081_adc0: adc@0 {
					reg = <0>;
					adi,decimation = <1>;
					adi,nco-frequency-shift-hz =  /bits/ 64 <0>;
					adi,nco-mixer-mode = <AD9081_ADC_NCO_ZIF>;
				};

				ad9081_adc1: adc@1 {
					reg = <1>;
					adi,decimation = <1>;
					adi,nco-frequency-shift-hz =  /bits/ 64 <0>;
					adi,nco-mixer-mode = <AD9081_ADC_NCO_ZIF>;
				};

				ad9081_adc2: adc@2 {
					reg = <2>;
					adi,decimation = <1>;
					adi,nco-frequency-shift-hz =  /bits/ 64 <0>;
					adi,nco-mixer-mode = <AD9081_ADC_NCO_ZIF>;
				};

				ad9081_adc3: adc@3 {
					reg = <3>;
					adi,decimation = <1>;
					adi,nco-frequency-shift-hz =  /bits/ 64 <0>;
					adi,nco-mixer-mode = <AD9081_ADC_NCO_ZIF>;
				};
			};

			adi,channelizer-paths {
				#address-cells = <1>;
				#size-cells = <0>;

				ad9081_rx_fddc_chan0: channel@0 {
					reg = <0>;
					adi,decimation = <1>;
					adi,gain = <0>; /* 2048 * 10^(gain_dB/20) */
					adi,nco-frequency-shift-hz =  /bits/ 64 <0>;
				};

				ad9081_rx_fddc_chan1: channel@1 {
					reg = <1>;
					adi,decimation = <1>;
					adi,gain = <0>; /* 2048 * 10^(gain_dB/20) */
					adi,nco-frequency-shift-hz =  /bits/ 64 <0>;
				};

				ad9081_rx_fddc_chan2: channel@2 {
					reg = <2>;
					adi,decimation = <1>;
					adi,gain = <0>; /* 2048 * 10^(gain_dB/20) */
					adi,nco-frequency-shift-hz =  /bits/ 64 <0>;
				};

				ad9081_rx_fddc_chan3: channel@3 {
					reg = <3>;
					adi,decimation = <1>;
					adi,gain = <0>; /* 2048 * 10^(gain_dB/20) */
					adi,nco-frequency-shift-hz =  /bits/ 64 <0>;
				};
			};

			adi,jesd-links {
				#size-cells = <0>;
				#address-cells = <1>;

				ad9081_rx_jesd_l0: link@0 {
					reg = <0>;
					adi,converter-select =
					<&ad9081_rx_fddc_chan0 FDDC_I>,
					<&ad9081_rx_fddc_chan1 FDDC_I>,
					<&ad9081_rx_fddc_chan2 FDDC_I>,
					<&ad9081_rx_fddc_chan3 FDDC_I>;
					adi,logical-lane-mapping = /bits/ 8 <2 0 7 6 5 4 3 1>;
					adi,link-mode = <27>;			/* JESD Quick Configuration Mode */
					adi,subclass = <1>;			/* JESD SUBCLASS 0,1,2 */
					adi,version = <2>;			/* JESD VERSION 0=204A,1=204B,2=204C */
					adi,dual-link = <0>;			/* JESD Dual Link Mode */
					adi,converters-per-device = <4>;	/* JESD M */
					adi,octets-per-frame = <3>;		/* JESD F */
					adi,frames-per-multiframe = <256>;	/* JESD K */
					adi,converter-resolution = <12>;	/* JESD N */
					adi,bits-per-sample = <12>;		/* JESD NP' */
					adi,control-bits-per-sample = <0>;	/* JESD CS */
					adi,lanes-per-device = <8>;		/* JESD L */
					adi,samples-per-converter-per-frame = <4>; /* JESD S */
					adi,high-density = <0>;			/* JESD HD */
				};
			};
		};

	};
};