Custom Device Tree Overlay - Pin Mapping

Hi,

In the past I’ve enabled PPS input on Pin 7 of the 40 pin GPIO header on a Jetson Nano (see forum thread here: Device Tree Overlay for PPS Support on JP4.6.4) and am attempting to port this to the Orin NX using the nVidia dev kit carrier board.

I had asked on the previous thread how to determine the pin hex codes as functions such as TEGRA234_MAIN_GPIO(AC, 6) and definitions such as GPIO_ACTIVE_HIGH are not available when creating a .dts and not recompiling the kernel, but I didn’t receive an answer and I’m facing the same problem again. I’ve searched for similar threads for the Orin NX but haven’t been able to find an answer.

Here is the current state of the .dts for the overlay, I’ve copied in 0xd8 for the gpio address value from the Nano overlay but would like to replace that with the correct value for pin 7 on the Orin NX 40 pin header. How can I determine its hex code (or import the function TEGRA234_MAIN_GPIO)?

/dts-v1/;
/plugin/;
 
/ {
    overlay-name = "PPS Overlay";
    jetson-header-name = "Jetson 40pin Header";
    compatible = "nvidia,p3768-0000+p3767-0000", "nvidia,p3767-0000", "nvidia,tegra234", "nvidia,tegra23x";
 
    fragment@0 {
        target-path = "/";
        __overlay__ {
            pps_gpio {
                compatible = "pps-gpio";
                gpios = <&tegra_main_gpio 0xd8 0x0>;
                status = "okay";
            };
        };
    };

    gpio@2200000 {
		reg-names = "security\0gpio";
		gpio-controller;
		interrupts = <0x00 0x120 0x04 0x00 0x121 0x04 0x00 0x122 0x04 0x00 0x123 0x04 0x00 0x124 0x04 0x00 0x125 0x04 0x00 0x126 0x04 0x00 0x127 0x04 0x00 0x128 0x04 0x00 0x129 0x04 0x00 0x12a 0x04 0x00 0x12b 0x04 0x00 0x12c 0x04 0x00 0x12d 0x04 0x00 0x12e 0x04 0x00 0x12f 0x04 0x00 0x130 0x04 0x00 0x131 0x04 0x00 0x132 0x04 0x00 0x133 0x04 0x00 0x134 0x04 0x00 0x135 0x04 0x00 0x136 0x04 0x00 0x137 0x04 0x00 0x138 0x04 0x00 0x139 0x04 0x00 0x13a 0x04 0x00 0x13b 0x04 0x00 0x13c 0x04 0x00 0x13d 0x04 0x00 0x13e 0x04 0x00 0x13f 0x04 0x00 0x140 0x04 0x00 0x141 0x04 0x00 0x142 0x04 0x00 0x143 0x04 0x00 0x144 0x04 0x00 0x145 0x04 0x00 0x146 0x04 0x00 0x147 0x04 0x00 0x148 0x04 0x00 0x149 0x04 0x00 0x14a 0x04 0x00 0x14b 0x04 0x00 0x14c 0x04 0x00 0x14d 0x04 0x00 0x14e 0x04 0x00 0x14f 0x04>;
		compatible = "nvidia,tegra234-gpio";
		#interrupt-cells = <0x02>;
		status = "okay";
		reg = <0x00 0x2200000 0x00 0x10000 0x00 0x2210000 0x00 0x10000>;
		phandle = <0x50>;
		#gpio-cells = <0x02>;
		gpio-ranges = <0x2b4 0x00 0x00 0x8a 0x2b4 0x8a 0x92 0x1a>;
		interrupt-controller;

		camera-control-output-low {
			gpio-hog;
			label = "cam0-pwdn\0cam1-pwdn";
			gpios = <0x3e 0x00 0xa0 0x00>;
			output-low;
		};
	};

    __symbols__ {
		tegra_main_gpio = "/gpio@2200000";
	};
};

Note that I copied in the symbols and definitions of tegra_main_gpio from the decompiled /proc/device-tree in an attempt to get the &tegra_main_gpio part to work, which did succeed!

Thanks!

Hi roo,

Have you tried to download the kernel source and add them in device tree source instead of creating overlay package?
In this way, you don’t need to care about the hex value.

Hi Kevin,

I’ve not tried that as my application requirement is that I can apply this as an overlay to the unmodified distribution of the OS provided by nVidia. What’s the best way to look the values up? Surely each GPIO pin has a fixed hex value/index?

If I did take the kernel mod route, could I compile the kernel/device tree then just copy paste the hex values that get generated into my overlay?

What’s the Jetpack version in use for Orin Nano?

You can compare other nodes in device tree for the original string and generated hex value.

Hi Kevin,
I’m trying to build this overlay for JP 5.1.2.
Would /proc/device-tree be the right place to look at for comparing other nodes? I wasn’t able to find any reference to the GPIO pins in there myself.

You can run the following command to get the configuration for the device tree on your board.

$ sudo dtc -I fs -O dts -o extracted_proc.dts /proc/device-tree

And get the kernel source with device tree source(normally, they are under hardware/nvidia/ directory) to compare with.

Thanks Kevin, I’ll try this when back from travel and let you know how it goes.

Hi Kevin,
I found the following in the extracted_proc.dts file from your previous post, this does yield a reference for tegra_main_gpio but not a definition of the function that is generally referenced in other posts. The reference does provide a range of hex values but doesn’t provide me any clues as to what the hex value is for the pin I want to use. Is there a way to figure out what the address is for any given GPIO pin from this output?

tegra_main_gpio = "/gpio@2200000";
...
gpio@2200000 {
		reg-names = "security\0gpio";
		gpio-controller;
		interrupts = <0x00 0x120 0x04 0x00 0x121 0x04 0x00 0x122 0x04 0x00 0x123 0x04 0x00 0x124 0x04 0x00 0x125 0x04 0x00 0x126 0x04 0x00 0x127 0x04 0x00 0x128 0x04 0x00 0x129 0x04 0x00 0x12a 0x04 0x00 0x12b 0x04 0x00 0x12c 0x04 0x00 0x12d 0x04 0x00 0x12e 0x04 0x00 0x12f 0x04 0x00 0x130 0x04 0x00 0x131 0x04 0x00 0x132 0x04 0x00 0x133 0x04 0x00 0x134 0x04 0x00 0x135 0x04 0x00 0x136 0x04 0x00 0x137 0x04 0x00 0x138 0x04 0x00 0x139 0x04 0x00 0x13a 0x04 0x00 0x13b 0x04 0x00 0x13c 0x04 0x00 0x13d 0x04 0x00 0x13e 0x04 0x00 0x13f 0x04 0x00 0x140 0x04 0x00 0x141 0x04 0x00 0x142 0x04 0x00 0x143 0x04 0x00 0x144 0x04 0x00 0x145 0x04 0x00 0x146 0x04 0x00 0x147 0x04 0x00 0x148 0x04 0x00 0x149 0x04 0x00 0x14a 0x04 0x00 0x14b 0x04 0x00 0x14c 0x04 0x00 0x14d 0x04 0x00 0x14e 0x04 0x00 0x14f 0x04>;
		compatible = "nvidia,tegra234-gpio";
		#interrupt-cells = <0x02>;
		status = "okay";
		reg = <0x00 0x2200000 0x00 0x10000 0x00 0x2210000 0x00 0x10000>;
		phandle = <0x50>;
		#gpio-cells = <0x02>;
		gpio-ranges = <0x2b4 0x00 0x00 0x8a 0x2b4 0x8a 0x92 0x1a>;
		interrupt-controller;

		camera-control-output-low {
			gpio-hog;
			label = "cam0-pwdn\0cam1-pwdn";
			gpios = <0x3e 0x00 0xa0 0x00>;
			output-low;
		};
	};

Hi Kevin,
I searched through the kernel source and found the following in hardware\nvidia\soc\tegra\kernel-include\dt-bindings\gpio\tegra186-gpio.h

/* GPIOs implemented by main GPIO controller */
#define TEGRA_MAIN_GPIO_PORT_A 0
#define TEGRA_MAIN_GPIO_PORT_B 1
#define TEGRA_MAIN_GPIO_PORT_C 2
#define TEGRA_MAIN_GPIO_PORT_D 3
#define TEGRA_MAIN_GPIO_PORT_E 4
#define TEGRA_MAIN_GPIO_PORT_F 5
#define TEGRA_MAIN_GPIO_PORT_G 6
#define TEGRA_MAIN_GPIO_PORT_H 7
#define TEGRA_MAIN_GPIO_PORT_I 8
#define TEGRA_MAIN_GPIO_PORT_J 9
#define TEGRA_MAIN_GPIO_PORT_K 10
#define TEGRA_MAIN_GPIO_PORT_L 11
#define TEGRA_MAIN_GPIO_PORT_M 12
#define TEGRA_MAIN_GPIO_PORT_N 13
#define TEGRA_MAIN_GPIO_PORT_O 14
#define TEGRA_MAIN_GPIO_PORT_P 15
#define TEGRA_MAIN_GPIO_PORT_Q 16
#define TEGRA_MAIN_GPIO_PORT_R 17
#define TEGRA_MAIN_GPIO_PORT_T 18
#define TEGRA_MAIN_GPIO_PORT_X 19
#define TEGRA_MAIN_GPIO_PORT_Y 20
#define TEGRA_MAIN_GPIO_PORT_BB 21
#define TEGRA_MAIN_GPIO_PORT_CC 22
#define TEGRA_MAIN_GPIO_PORT_DD 23

#define TEGRA_MAIN_GPIO(port, offset) \
	((TEGRA_MAIN_GPIO_PORT_##port * 8) + offset)

From this it appears possible to calculate the pin address if the port and offset are known.

I found the following in hardware\nvidia\soc\tegra\kernel-include\dt-common\jetson\tegra234-p3767-0000-common.h

#define HDR40_PIN7_GPIO		TEGRA_MAIN_GPIO(AC, 6)

This would indicate that the pin is on port AC offset 6. My only challenge now is finding the definition of port AC, as it’s not in the list from tegra186-gpio.h or any other files within the source package. Can you point me in the right direction there?

I may have posted too soon as I didn’t realize I was incorrectly searching for TEGRA_MAIN_GPIO instead of TEGRA234_MAIN_GPIO. Searching the correct function yields the following from tegra234-gpio.h.

/* GPIOs implemented by main GPIO controller */
...
#define TEGRA234_MAIN_GPIO_PORT_AC 20
...

#define TEGRA234_MAIN_GPIO(port, offset) \
		((TEGRA234_MAIN_GPIO_PORT_##port * 8) + offset)

To me this indicates that the address for pin 7 on the 40 pin GPIO header is as follows:

(20 * 8) + 6 = 166
166 decimal -> 0xA6 hexadecimal

Which would make the overlay as follows, which I will have to test tomorrow.

/dts-v1/;
/plugin/;
 
/ {
    overlay-name = "PPS Overlay";
    jetson-header-name = "Jetson 40pin Header";
    compatible = "nvidia,p3768-0000+p3767-0000", "nvidia,p3767-0000", "nvidia,tegra234", "nvidia,tegra23x";
 
    fragment@0 {
        target-path = "/";
        __overlay__ {
            pps_gpio {
                compatible = "pps-gpio";
                gpios = <&tegra_main_gpio 0xa6 0x0>;
                status = "okay";
            };
        };
    };

    gpio@2200000 {
		reg-names = "security\0gpio";
		gpio-controller;
		interrupts = <0x00 0x120 0x04 0x00 0x121 0x04 0x00 0x122 0x04 0x00 0x123 0x04 0x00 0x124 0x04 0x00 0x125 0x04 0x00 0x126 0x04 0x00 0x127 0x04 0x00 0x128 0x04 0x00 0x129 0x04 0x00 0x12a 0x04 0x00 0x12b 0x04 0x00 0x12c 0x04 0x00 0x12d 0x04 0x00 0x12e 0x04 0x00 0x12f 0x04 0x00 0x130 0x04 0x00 0x131 0x04 0x00 0x132 0x04 0x00 0x133 0x04 0x00 0x134 0x04 0x00 0x135 0x04 0x00 0x136 0x04 0x00 0x137 0x04 0x00 0x138 0x04 0x00 0x139 0x04 0x00 0x13a 0x04 0x00 0x13b 0x04 0x00 0x13c 0x04 0x00 0x13d 0x04 0x00 0x13e 0x04 0x00 0x13f 0x04 0x00 0x140 0x04 0x00 0x141 0x04 0x00 0x142 0x04 0x00 0x143 0x04 0x00 0x144 0x04 0x00 0x145 0x04 0x00 0x146 0x04 0x00 0x147 0x04 0x00 0x148 0x04 0x00 0x149 0x04 0x00 0x14a 0x04 0x00 0x14b 0x04 0x00 0x14c 0x04 0x00 0x14d 0x04 0x00 0x14e 0x04 0x00 0x14f 0x04>;
		compatible = "nvidia,tegra234-gpio";
		#interrupt-cells = <0x02>;
		status = "okay";
		reg = <0x00 0x2200000 0x00 0x10000 0x00 0x2210000 0x00 0x10000>;
		phandle = <0x50>;
		#gpio-cells = <0x02>;
		gpio-ranges = <0x2b4 0x00 0x00 0x8a 0x2b4 0x8a 0x92 0x1a>;
		interrupt-controller;

		camera-control-output-low {
			gpio-hog;
			label = "cam0-pwdn\0cam1-pwdn";
			gpios = <0x3e 0x00 0xa0 0x00>;
			output-low;
		};
	};

    __symbols__ {
		tegra_main_gpio = "/gpio@2200000";
	};
};

Unfortunately this does not work. The following is added into the dtb when I run fdtdump /boot/kernel_tegra234-p3767-0000-p3768-0000-a0-user-custom.dtb after applying the overlay, however no pps device is created at /dev/pps*. Any thoughts Kevin?

pps_gpio {
        status = "okay";
        gpios = <0x00000050 0x000000a6 0x00000000>;
        compatible = "pps-gpio";
    };

This appears correct, the 0x50 address is the phandle of &tegra_main_gpio, the only thing I can think of is that the pin address is still incorrect. Here is a dump from dmesg indicating the issue:

[    1.629970] pps_core: LinuxPPS API ver. 1 registered
[    1.634931] pps_core: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo Giometti <giometti@linux.it>
[    4.513018] pps-gpio pps_gpio: failed to request PPS GPIO
[    4.518564] pps-gpio: probe of pps_gpio failed with error -22

Hello @roo

It seems that your method of mapping the GPIO number is not correct. You could follow Jetson Orin NX and Nano Series — NVIDIA Jetson Linux Developer Guide 1 documentation. Based on the Orin NX pinmux, do you want to use the GPIO09 (AUD_MCLK) which is GPIO3_PAC.06. So, using the formula from the wiki page:

base + port_offset + pin_offset

348 + 138 + 6 = 492

You can check as:

sudo cat /sys/kernel/debug/gpio | grep AC.06
 gpio-492 (PAC.06              )

Hope this helps!

Regards!
Eduardo Salazar
Embedded SW Engineer at RidgeRun

Contact us: support@ridgerun.com
Developers wiki: https://developer.ridgerun.com/
Website: www.ridgerun.com

Hi Eduardo,

I don’t think the pin number is what we want here, I’m looking for the pin address which for AC6 is calculated with the TEGRA234_MAIN_GPIO() function in the kernel source.

Just to be sure I did try the pin number (492/0x1EC) and it did not work either.

Cheers

I found the following post on the forum and had a chat with the user who posted the issue: Failed to request PPS GPIO - #7 by khang.l4es

It appears that the kernel for JP 5.1.2 has a loading order issue that prevents the PPS module from being loaded, best guess is the GPIOs aren’t registered yet at that point in the boot.

I therefore retried the same test on JP 6.0.2 and the PPS overlay works perfectly using the math/functions I determined from the kernel source header files. This appears to confirm that the issue is inerrant to the specific kernel build for JP 5.1.2. Rebuilding my own kernel for that version, or just using a newer JP release seem to be the only options unless someone else can make another suggestion as to loading the PPS module after the GPIOs are available.

This is my working overlay:

/dts-v1/;
/plugin/;
 
/ {
    overlay-name = "PPS Overlay";
    jetson-header-name = "Jetson 40pin Header";
    compatible = "nvidia,p3768-0000+p3767-0000", "nvidia,p3767-0000", "nvidia,tegra234", "nvidia,tegra23x";
 
    fragment@0 {
        target-path = "/";
        __overlay__ {
            pps_gpio {
                compatible = "pps-gpio";
                gpios = <&tegra_main_gpio 0xa6 0x0>;
                status = "okay";
            };
        };
    };
};
1 Like

Are you using JP6.0(r36.3.0) or JP6.1(r36.4.0)?

Can &tegra_main_gpio be recognized in your overlay dts?

Hi Kevin,

I was successful using JP 6.0 (which is listed in the SDK Manager as “Jetpack 6.0 (Rev2)” hence why I called it 6.0.2).

There is a warning generated when I create the dtbo related to &tegra_main_gpio being undefind, however since it’s defined in the Jetpack kernel device tree when the overlay is applied this reference can still be found.

good, it seems you’ve managed to get it working.

1 Like

Hi Kevin, I thought so but may not have…

There appears to be a device registered at /dev/pps0 in the newer Jetpacks (6.0+) even before I have applied my overlay. This device appears to work as a PPS source (ppstest /dev/pps0 shows a 1Hz signal) but I’m assuming this is generated internally to the Jetson since I haven’t applied my overlay yet.

After my overlay is applied, no additional PPS sources are registered (there is no /dev/pps1 for example) and when my PPS source is disconnected from the GPIO I’m using /dev/pps0 doesn’t stop producing a signal. Therefore it’s not actually working.

Can you provide details on where this PPS source is coming from and how it’s configured in JP6.0+? I’m wondering if this is causing my overlay not to function or be applied.

I’ve also noticed that the way overlays are applied with /opt/nvidia/jetson-io/config-by-hardware.py appears to have changed in JP6.0+. Previously a user-custom dtb was generated, now however only extlinux.conf is modified to add an OVERLAYS section to the config. With this method, when I extract the /proc/device-tree my overlay is not present on JP6.0+. Can you point me in the right direction for applying overlays in new Jetpack?

Last post!

It appears the phandle &tegra_main_gpio was renamed in JP 6.0+ to just &gpio. With this changed in the overlay file I do see a second pps device registered and it is functional when my PPS source is connected.

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.