Post Go back to editing

ADRV9002: Configuring the AGPIOs and DGPIOs through the device tree

Hello

I have a working custom system based on Petalinux and the ADRV9002 evaluation board. I can control most of the device features (such as changing LO frequencies) through IIO (either through IIO Oscilloscope) or by accessing the IIO files in /sys/.

I would now like to find out about configuring the GPIOs. The ADRV9002 Device Driver customization page includes the following:

GPIO Settings

All the gpios configurations should be done under adi,gpios node as shown in the next example:

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

        gpio@0 {
                reg = <0>;
                adi,signal = <2>;
                adi,polarity = <1>;
                adi,master = <2>;        
        };
};

I can't work out how to relate this device tree entry to all the options offered by the ADRV9002 API (as detailed in the user guide). For example, say I wanted to configure a specific AGPIO pin for manual control, how would I go about doing this though the device tree? How would I then control this GPIO pin through IIO?

According to the ADRV9001 user guide:

"The API commands adi_adrv9001_gpio_ControlInit_Configure() and adi_adrv9001_gpio_Configure() are used to configure the digital or analog GPIO work modes"

How do I perform the equivalent through IIO? I would like to continue to use IIO as this is working for all the other aspects of the ADRV9002.

According to the wiki, adi,signal defines the function of the GPIO pin (0 to 19). Where can I find the definition of what each of the signal values (0 to 19) mean?

In the ADRV9009 I controlled the GPIOs through the debugfs. I cannot see any GPIO pins in the ADRV9002 debugfs.

Thank you.

Top Replies

    •  Analog Employees 
    Apr 8, 2022 in reply to gavint +1 verified
    Would it be feasible for me to try to integrate support for AGPIOs into the 2019_R2 branch? If so, please can you point me in the direction of the master branch commit where AGPIO support was…
  • Hello

    Is anyone able to help me with my question please?

    Thank you in advance.

  • Hi,

    I can't work out how to relate this device tree entry to all the options offered by the ADRV9002 API (as detailed in the user guide). For example, say I wanted to configure a specific AGPIO pin for manu

    This is a bit awkward I have to admit. This is for when you know you have a gpio that is to be used for a special function/signal (not as a "raw" GPIO). But note (in here is where things get a bit more complicated) that you should be careful to not overlap gpios configured trough adi,gpios with other properties like this. Because the API responsible for handling gain pinctrl will already correctly set the GPIO's. The GPIOs in adi,gpios are the ones (that at least for now) to be configured directly by the driver using 'adi_adrv9001_gpio_Configure()'.

    According to the wiki, adi,signal defines the function of the GPIO pin (0 to 19). Where can I find the definition of what each of the signal values (0 to 19) mean?

    Here are some signals that are to be used (not all them tested though) in devicetree. The complete list as defined in the API can be found here. But again note that some of them you should not touch directly (ex: ADI_ADRV9001_GPIO_SIGNAL_AUX_DAC_0).

    How do I perform the equivalent through IIO? I would like to continue to use IIO as this is working for all the other aspects of the ADRV9002.

    Note that IIO is not for GPIO handling. There's a dedicated GPIO subsystem in linux. We may, in the future, integrate them with adrv9002 so you can manually use them as your normally do in linux (under /sys/class/gpio).

    In the ADRV9009 I controlled the GPIOs through the debugfs. I cannot see any GPIO pins in the ADRV9002 debugfs.

    This is already supported in the master branch. You can manually control the gpios (setting/getting direction/values). Again, you need to be careful in here to not overlap with some gpio that might have been configured by the API. If you use the default devicetree, only dpgio0 and dgpio1 should be configured.

    (Note: I'm aware the wiki needs to be brought up to date)

    - Nuno Sá

  • Hello Nuno

    Thank you for answering my questions. 

    I am still having some difficulty with the implementation though. I have added the following to the top of my system-user.dtsi:

    #define ADI_ADRV9001_GPIO_SIGNAL_ORX_ENABLE_1 0
    #define ADI_ADRV9001_GPIO_SIGNAL_ORX_ENABLE_2 1
    #define ADI_ADRV9001_GPIO_SIGNAL_MON_ENABLE_SPS 2
    #define ADI_ADRV9001_GPIO_SIGNAL_MON_WAKEUP 3
    #define ADI_ADRV9001_GPIO_SIGNAL_POWER_SAVING_CHANNEL1 4
    #define ADI_ADRV9001_GPIO_SIGNAL_POWER_SAVING_CHANNEL2 5
    #define ADI_ADRV9001_GPIO_SIGNAL_FH_HOP 6
    #define ADI_ADRV9001_GPIO_SIGNAL_FH_GAIN_SEL_0 7
    #define ADI_ADRV9001_GPIO_SIGNAL_FH_GAIN_SEL_1 8
    #define ADI_ADRV9001_GPIO_SIGNAL_FH_GAIN_SEL_2 9
    #define ADI_ADRV9001_GPIO_SIGNAL_FH_TABLE_INDEX_0 10
    #define ADI_ADRV9001_GPIO_SIGNAL_FH_TABLE_INDEX_1 11
    #define ADI_ADRV9001_GPIO_SIGNAL_FH_TABLE_INDEX_2 12
    #define ADI_ADRV9001_GPIO_SIGNAL_FH_TABLE_INDEX_3 13
    #define ADI_ADRV9001_GPIO_SIGNAL_FH_TABLE_INDEX_4 14
    #define ADI_ADRV9001_GPIO_SIGNAL_FH_TABLE_INDEX_5 15
    #define ADI_ADRV9001_GPIO_SIGNAL_FH_HOP_TABLE_SELECT 16
    #define ADI_ADRV9001_GPIO_SIGNAL_TX1_PA_RAMP_CTRL 17
    #define ADI_ADRV9001_GPIO_SIGNAL_TX2_PA_RAMP_CTRL 18
    #define ADI_ADRV9001_GPIO_SIGNAL_ADC_SWITCHING_CHANNEL1 19
    #define ADI_ADRV9001_GPIO_SIGNAL_ADC_SWITCHING_CHANNEL2 20
    #define ADI_ADRV9001_GPIO_SIGNAL_TX1_EXT_FRONTEND_CONTROL 21
    #define ADI_ADRV9001_GPIO_SIGNAL_TX2_EXT_FRONTEND_CONTROL 22
    #define ADI_ADRV9001_GPIO_SIGNAL_RX1_EXT_FRONTEND_CONTROL 23
    #define ADI_ADRV9001_GPIO_SIGNAL_RX2_EXT_FRONTEND_CONTROL 24
    #define ADI_ADRV9001_GPIO_SIGNAL_EXT_PLL_1_LOCK 25
    #define ADI_ADRV9001_GPIO_SIGNAL_EXT_PLL_2_LOCK 26
    #define ADI_ADRV9001_GPIO_SIGNAL_EXT_PLL_1_CE 27
    #define ADI_ADRV9001_GPIO_SIGNAL_EXT_PLL_2_CE 28
    #define ADI_ADRV9001_GPIO_SIGNAL_RX_VCO_1_CE 29
    #define ADI_ADRV9001_GPIO_SIGNAL_RX_VCO_2_CE 30
    #define ADI_ADRV9001_GPIO_SIGNAL_AUX_DAC_0 31
    #define ADI_ADRV9001_GPIO_SIGNAL_AUX_DAC_1 32
    #define ADI_ADRV9001_GPIO_SIGNAL_AUX_DAC_2 33
    #define ADI_ADRV9001_GPIO_SIGNAL_AUX_DAC_3 34
    #define ADI_ADRV9001_GPIO_SIGNAL_AUX_ADC_0 35
    #define ADI_ADRV9001_GPIO_SIGNAL_AUX_ADC_1 36
    #define ADI_ADRV9001_GPIO_SIGNAL_AUX_ADC_2 37
    #define ADI_ADRV9001_GPIO_SIGNAL_AUX_ADC_3 38
    #define ADI_ADRV9001_GPIO_SIGNAL_FH_HOP_2 39
    #define ADI_ADRV9001_GPIO_SIGNAL_TX_CAL_EN 40
    #define ADI_ADRV9001_GPIO_SIGNAL_CAL_UPDATE 41

    I then added the ADI GPIO entries under adc0_adrv9002: adrv9002-phy@0:

    	amba {
    		compatible = "simple-bus";
    		u-boot,dm-pre-reloc;
    		#address-cells = <0x2>;
    		#size-cells = <0x2>;
    		ranges;
    
    		mmc@ff160000 {
    			status = "disabled";
    		};
    
    		ethernet@ff0c0000 {
    			status = "disabled";
    		};
    
    		spi@ff040000 {
    			status = "okay";
    			is-decoded-cs = <0x0>;
    			num-cs = <0x3>;
    
    			adc0_adrv9002: adrv9002-phy@0 {
    				compatible = "adi,adrv9002";
    				reg = <0>;
    
    				interrupt-parent = <&gpio>;
    				interrupts = <122 IRQ_TYPE_EDGE_RISING>;
    
    				spi-max-frequency = <20000000>;
    				/* Clocks */
    				clocks = <&adrv9002_clkin 0>;
    				clock-names = "adrv9002_ext_refclk";
    				clock-output-names = "rx1_sampl_clk", "tx1_sampl_clk", "tdd1_intf_clk",
    						"rx2_sampl_clk", "tx2_sampl_clk", "tdd2_intf_clk";
    				#clock-cells = <1>;
    
    				reset-gpios = <&gpio 124 GPIO_ACTIVE_LOW>;
    
    				agc0: agc@0 {
    					adi,peak-wait-time = <4>;
    					adi,gain-update-counter = <11520>;
    					adi,attack-delax-us = <10>;
    					adi,slow-loop-settling-delay = <16>;
    					adi,change-gain-threshold-high = <3>;
    					adi,agc-mode = <1>;
    					adi,reset-on-rx-on-gain-index = <255>;
    					adi,power-measurement-en;
    					adi,power-under-range-high-threshold = <10>;
    					adi,power-under-range-low-threshold = <4>;
    					adi,power-under-range-high-gain-step-recovery = <2>;
    					adi,power-under-range-low-gain-step-recovery = <4>;
    					adi,power-measurement-duration = <10>;
    					adi,power-measurement-delay = <2>;
    					adi,power-rx-tdd-measurement-duration = <0>;
    					adi,power-rx-tdd-measurement-delay = <0>;
    					adi,power-over-range-high-threshold = <0>;
    					adi,power-over-range-low-threshold = <7>;
    					adi,power-over-range-high-gain-step-attack = <4>;
    					adi,power-over-range-low-gain-step-attack = <4>;
    					adi,peak-agc-under-range-low-interval = <50>;
    					adi,peak-agc-under-range-mid-interval = <2>;
    					adi,peak-agc-under-range-high-interval = <4>;
    					adi,peak-apd-high-threshold = <21>;
    					adi,peak-apd-low-threshold = <12>;
    					adi,peak-apd-upper-threshold-exceeded-count = <6>;
    					adi,peak-apd-lower-threshold-exceeded-count = <3>;
    					adi,peak-apd-gain-step-attack = <2>;
    					adi,peak-apd-gain-step-recovery = <0>;
    					adi,peak-hb-overload-en;
    					adi,peak-hb-overload-duration-count = <1>;
    					adi,peak-hb-overload-threshold-count = <1>;
    					adi,peak-hb-high-threshold = <13044>;
    					adi,peak-hb-under-range-low-threshold = <5826>;
    					adi,peak-hb-under-range-mid-threshold = <8230>;
    					adi,peak-hb-under-range-high-threshold = <7335>;
    					adi,peak-hb-upper-threshold-exceeded-count = <6>;
    					adi,peak-hb-under-range-high-threshold-exceeded-count = <3>;
    					adi,peak-hb-gain-step-high-recovery = <2>;
    					adi,peak-hb-gain-step-low-recovery = <6>;
    					adi,peak-hb-gain-step-mid-recovery = <4>;
    					adi,peak-hb-gain-step-attack = <2>;
    					adi,peak-hb-overload-power-mode = <0>;
    					adi,peak-hb-under-range-mid-threshold-exceeded-count = <3>;
    					adi,peak-hb-under-range-low-threshold-exceeded-count = <3>;
    				};
    
    				rx_pinctrl0: rx-pinctrl@0 {
    					adi,increment-step-size = <1>;
    					adi,decrement-step-size = <1>;
    					adi,increment-pin = <2>;
    					adi,decrement-pin = <1>;
    				};
    
    				rx_pinctrl1: rx-pinctrl@1 {
    					adi,increment-step-size = <1>;
    					adi,decrement-step-size = <1>;
    					adi,increment-pin = <4>;
    					adi,decrement-pin = <5>;
    				};
    
    				tx_pinctrl0: tx-pinctrl@0 {
    					adi,step-size-mdB = <500>;
    					adi,increment-pin = <6>;
    					adi,decrement-pin = <7>;
    				};
    
    				tx_pinctrl1: tx-pinctrl@1 {
    					adi,step-size-mdB = <500>;
    					adi,increment-pin = <9>;
    					adi,decrement-pin = <8>;
    				};
    
    				adi,channels {
    					#address-cells = <1>;
    					#size-cells = <0>;
    
    					rx@0 {
    						reg = <0>;
    						adi,port = <0>;
    						adi,agc = <&agc0>;
    						adi,pinctrl = <&rx_pinctrl0>;
    					};
    
    					rx@1 {
    						reg = <1>;
    						adi,port = <0>;
    						adi,agc = <&agc0>;
    						adi,pinctrl = <&rx_pinctrl1>;
    					};
    
    					tx@0 {
    						reg = <0>;
    						adi,port = <1>;
    						adi,pinctrl = <&tx_pinctrl0>;
    					};
    
    					tx@1 {
    						reg = <1>;
    						adi,port = <1>;
    						adi,pinctrl = <&tx_pinctrl1>;
    					};
    
    				};
    
    				adi,gpios {
    				    	#address-cells = <1>;
    					#size-cells = <0>;
    
    					gpio@0 {
    						reg = <0>;
    						adi,signal = <ADI_ADRV9001_GPIO_SIGNAL_TX1_EXT_FRONTEND_CONTROL>;
    						adi,polarity = <0>;
    						adi,master = <2>;        
    					};
    
    					gpio@1 {
    						reg = <1>;
    						adi,signal = <ADI_ADRV9001_GPIO_SIGNAL_TX2_EXT_FRONTEND_CONTROL>;
    						adi,polarity = <0>;
    						adi,master = <2>;        
    					};
    
    					gpio@2 {
    						reg = <2>;
    						adi,signal = <ADI_ADRV9001_GPIO_SIGNAL_RX1_EXT_FRONTEND_CONTROL>;
    						adi,polarity = <0>;
    						adi,master = <2>;        
    					};
    
    					gpio@3 {
    						reg = <3>;
    						adi,signal = <ADI_ADRV9001_GPIO_SIGNAL_RX2_EXT_FRONTEND_CONTROL>;
    						adi,polarity = <0>;
    						adi,master = <2>;        
    					};
    
    
    				};
    			};
    		};
    	};
    

    I am not sure if this is the correct place.

    I am able to build the Petalinux image but it no longer enumerates the ADRV9002 device. Dmesg output is as follows:

    [ 4.206140] adrv9002 spi1.0: Invalid gpio signal: 21
    [ 4.211116] adrv9002: probe of spi1.0 failed with error -22

    This tends to indicate that the SPI driver doesn't like where I have put the ADI,GPIO device tree entries. Can you please check if I have done something wrong in my ADI,GPIO entries?

    I have another thing that I would like to check:
    reg = <0>;

    This is the GPIO number. I am trying to assign AGPIO 0, AGPIO 1, AGPIO 2 and AGPIO 3 to TX1/2 and RX1/2 front end control. Does the GPIO numbers (reg in device tree) start from 0 for AGPIO 0? Do the DGPIOs start from 0 and the AGPIOs start from some offset?

    Thank you.

  • Hi,

    It looks like you are using the 2019_R2 release? In that case, only the dpios are allowed to be set through devicetree. You can switch to the master branch were agpios will be allowed...

    This is the GPIO number. I am trying to assign AGPIO 0, AGPIO 1, AGPIO 2 and AGPIO 3 to TX1/2 and RX1/2 front end control. Does the GPIO numbers (reg in device tree) start from 0 for AGPIO 0? Do the DGPIOs start from 0 and the AGPIOs start from some offset?

    Not really, in the master branch you use this defines...

    - Nuno Sá

  • Look at my previous answer...

  • I found the following in adrv9002.c:

    ret = of_property_read_u32(child, "adi,signal", &signal);
    if (ret) {
    dev_err(&phy->spi->dev,
    "No adi,signal property defined for gpio%d\n",
    gpio);
    goto of_child_put;
    } else if (signal > ADI_ADRV9001_GPIO_SIGNAL_ADC_SWITCHING_CHANNEL2) {
    dev_err(&phy->spi->dev,
    "Invalid gpio signal: %d\n", signal);
    ret = -EINVAL;
    goto of_child_put;
    }

    "(signal > ADI_ADRV9001_GPIO_SIGNAL_ADC_SWITCHING_CHANNEL2) " indicates that this method only supports DGPIO pins. How do you configure and control the AGPIO pins on the ADRV9002? I need to use the AGPIO pins to control switches on the TX and RX RF front end.

    Thanks.

  • OK, I am using an older version of the driver. I see on the latest adrv9002.c the check is against ADI_ADRV9001_GPIO_NUM_SIGNALS, thus allowing both digital and analog GPIOs. 

    The reason that I am using an older version is that I am using the last version that still supported B0 silicon for my evaluation board. With the final hardware I will upgrade to the latest 2019_R2 branch.

  • Hello

    Our customer has a lot of existing firmware infrastructure based on Vivado 2019.1. This infrastructure also extends to using Petalinux 2019.1 to build the Linux image. I have been tasked with integrating the ADRV9002 into their existing infrastructure. As such, I believe I am limited to using the 2019_R2 branch so that they can continue to use Vivado 2019.1/Petalinux 2019.1.

    Based on your answers, it seems that support for AGPIOs is only in the master branch. Is that correct? 
    Would it be feasible for me to try to integrate support for AGPIOs into the 2019_R2 branch? If so, please can you point me in the direction of the master branch commit where AGPIO support was added.

    Thank you.

  • Would it be feasible for me to try to integrate support for AGPIOs into the 2019_R2 branch? If so, please can you point me in the direction of the master branch commit where AGPIO support was added.

    Well, feasible it surely is...

    https://github.com/analogdevicesinc/linux/commit/68961c6550a0e9537cb5bcfc1e7d40473bd58d00

    But note by that time the enum was another (we need to adapt things in the driver as the driver API is modified). But as you can see, only that line was changed, so it should be just a matter of using ADI_ADRV9001_GPIO_NUM_SIGNALS...

    You also expressed desire in manually controlling gpios in debugfs. Here is the commit:

    https://github.com/analogdevicesinc/linux/commit/4e4d3ee47f66a8f94c0d139928941ec24b613719

    Though this might be harder to backport...

    - Nuno Sá

  • Thank you Nuno!

    I can confirm that by updating the following files:

    adrv9002_debugfs.c

    adi_adrv9001_gpio.h (required for adi_adrv9001_gpio_PinDirection_Get)

    adi_adrv9001_gpio.c (required for adi_adrv9001_dpio_PinDirection_Get)


    I can now see debugfs entries for both the DGPIO and the AGPIO pins. I am now able to manually control both the DGPIO and AGPIO pins via debufs which meets my requirements. 

    Thank you for your input in helping to solve this problem.