Time sensitive networking [TSN] on NX

@carolyuu, thank you for your response.
Could you share the content of the file gPTP.cfg , please?

NX PPS support seems to require rebuilding the kernel in order to add PPS device outputs to the ptp implementation.
The default stock kernel seems having PPS.GPIO =Y , but it has pps-ktimer=NO

nx2:~/linuxptp$ zcat /proc/config.gz | grep -i pps
# PPS support
# PPS clients support
# PPS generators support
# CONFIG_NVPPS is not set

Is it likely that after rebuilding the kernel with adding PPS-KTIMER module It will be possible to use e.g. simpleRT2K device [ or ublox F9t] PPS to increase the precision of PTP implementation?

does NX support PPS input for PTP?

I think all you need to do is create a device tree binding to set the gpio associated to the pps-gpio driver.

Something like this example from the kernel docs…

	pps {
		pinctrl-names = "default";
		pinctrl-0 = <&pinctrl_pps>;

		gpios = <&gpio1 26 GPIO_ACTIVE_HIGH>;

		echo-gpios = <&gpio1 27 GPIO_ACTIVE_HIGH>;
		echo-active-ms = <100>;

		compatible = "pps-gpio";

/dev/ptp0 already exists but doesn’t have a pps source associated to it (because there are no pps devices). Once the above binding is done, a /dev/pps0 device should automatically show up and be used by ptp0. I can try it later.

The PPS output from the external device would then be connected to the GPIO you chose when you created the binding, using whatever voltage conversion may be necessary.


You could download the gPTP.cfg here:

hello Andrey1984,

if you’re using GPIO pins under AON category to feed PPS signals, you may also use low-level APIs to capture timestamps for system synchronization.
please refer to the approach in post #16 from similar discussion thread, Topic 124003 .

Thank you for your response.
The idea is to setup two NX devices as in the example by @carolyuu.
However, with an extra precision layer provided by PPS from GPS unit. The GPS timepulse will be connected to one of the NX devices.
In order to be able to implement it I have to sort out:

    • To which pins to connect the timepulse outputs of the GPS device [ SimpleRT2K by ardusimple]
  • I understand that there is no hardcoded pin for PPS at NX devices. Which pins of the NX GPIO to use for wiring with gps timepulse outputs?
    • Despite the fact that pps-gpio kernel module is enabled by default, there is no /dev/pps device.

Will building the kernel from sources be required to add pps.ktimer module? NVPPS module? Both? Neither of the two?
Can it be done with just editing dtsi file? which exactly dtsi file? with flashing dtb? without flashing dtb?

to which file the following goes?

pps {
gpios = <&tegra_aon_gpio TEGRA194_AON_GPIO(AA, 0) GPIO_ACTIVE_LOW>;
compatible = “pps-gpio”;
status = “okay”;

What pin will be assigned if using the excerpt above?
Will it also require editing the kernel modules config section?

What is the NVPPS?

    • after the device /dev/pps is somehow created - how to use it as input for ethernet nic linux ptp operations?

Attempt #1
mkdir development
cd development
wget https://developer.nvidia.com/embedded/L4T/r32_Release_v4.2/Sources/T186/public_sources.tbz2
tar -xjf public_sources.tbz2
cd Linux_for_Tegra/
cd source/
cd public/
tar -xjf kernel_src.tbz2
mkdir /mnt/outdir
cd kernel/
cd kernel-4.9/
make ARCH=arm64 O=$TEGRA_KERNEL_OUT tegra_defconfig

  • revising .config file in the outdir folder. Do i need to make any changes to there? enable pps.ktimer? nvpps? CONFIG_TEGRA_HTS_GTE=y
    @gtj what dtsi file should I edit?

You choose the pin. Use the pinmux spreadsheet to pick one. If you’re using the NX devkit, pick a gpio that appears on the 40 pin header. For instance, if you wan to use GPIO01 (pin 29) on the header, look in the spreadsheet and you’ll see it’s GPIO3_PQ.05. The important parts being Q 5.

Without a valid gpio setting, the driver won’t load.

Ha! I didn’t even know there was a NVPPS module but yes, you’ll have to compile the kernel from source to use it as it’s not enabled by default. I’m not sure what it does that the pps-gpio driver doesn’t though and there’s no device tree example for it that I can find. I think it’d be a simple…

nvpps {
    compatible = “nvidia,tegra194-nvpps”;
    gpio = <&gpio TEGRA_GPIO(Q, 5) GPIO_ACTIVE_LOW>;
    status = “okay”;

That will fail as tegra_aon_gpio and TEGRA194_AON_GPIO aren’t valid on this platform.

Using the GPIO01 example from above, you’d want something like this…

pps {
    gpio = <&gpio TEGRA_GPIO(Q, 5) GPIO_ACTIVE_LOW>;
    compatible = “pps-gpio”;
    status = “okay”;

I guess it’s a Tegra specific version of pps-gpio so you’d use one or the other but not both. Someone from nvidia would have to confirm.

That should happen automatically.

More info coming…

which of the files below should I edit?

/mnt/developoment/Linux_for_Tegra/source/public/hardware/nvidia/platform/t19x/jakku/kernel-dts$ ls
/mnt/developoment/Linux_for_Tegra/source/public/hardware/nvidia/platform/t19x/jakku/kernel-dts/common$ ls

I think you just need to enable “Tegra NVPPS Support” under Device Drivers if you want to try that. pps-gpio is already enabled by default.

The best file to modify is probably hardware/nvidia/platform/t19x/jakku/kernel-dts/tegra194-p3668-all-p3509-0000.dts. There are other ways to enable the gpio in the device tree including creating your own overlay but that’s a bit more complicated.

In tegra194-p3668-all-p3509-0000.dts you could just add the appropriate sample from above…

/ {
	nvidia,dtsfilename = __FILE__;
	nvidia,dtbbuildtime = __DATE__, __TIME__;

	compatible = "nvidia,p3449-0000+p3668-0000", "nvidia,p3449-0000+p3668-0001", "nvidia,p3509-0000+p3668-0000", "nvidia,p3509-0000+p3668-0001", "nvidia,tegra194";

	nvpps {
		compatible = “nvidia,tegra194-nvpps”;
		gpio = <&gpio TEGRA_GPIO(Q, 5) GPIO_ACTIVE_LOW>;
		status = “okay”;

it seems that I can edit the device-tree at runtime with the method proposed below

which of the files above do I add the section above to?
nx2:~$ locate tegra194-p3668-all-p3509-0000

which of the two below?


how do I trans code and pass the change to dtb on-the-fly?

sudo fdtput -t i  /boot/tegra194-p3668-all-p3509-0000.dtb nvpps compatible nvidia,tegra194-nvpps gpio &gpio TEGRA_GPIO(Q, 5) GPIO_ACTIVE_LOW status okay

The issue with creating a dtb overlay is that you’ll have to convert the TEGRA_GPIO macro yourself because it’s normally parsed by the kernel build dtb generation process. To convert it, look at kernel-4.9/include/dt-bindings/gpio/tegra-gpio.h. Find the number associated to the GPIO letter, 16 for Q in this case, multiply it by 8, then add the GPIO number, 5 for a result of 133. Now you need to replace GPIO_ACTIVE_LOW by “1”.

So the line becomes…

gpio = <&gpio 133 1>;

So now an overlay source file should look like this…

/ {
    overlay-name = "PPS Overlay";
    compatible = "nvidia,p3509-0000+p3668-0000";
    fragment@pps {
        target-path = "/";
        __overlay__ {
            pps {
                gpio = <&gpio 133 1>;
                compatible = “pps-gpio”;
                status = “okay”;

Once you have that file, follow the instructions in the L4T documentation to enable it…

I haven’t tried these exact steps yet but I will later today.

 cat /mnt/developoment/Linux_for_Tegra/source/public/kernel/kernel-4.9/include/dt-bindings/gpio/tegra-gpio.h
 * This header provides constants for binding nvidia,tegra*-gpio.
 * The first cell in Tegra's GPIO specifier is the GPIO ID. The macros below
 * provide names for this.
 * The second cell contains standard flag values specified in gpio.h.


#include <dt-bindings/gpio/gpio.h>

#define TEGRA_GPIO_PORT_K 10
#define TEGRA_GPIO_PORT_L 11
#define TEGRA_GPIO_PORT_M 12
#define TEGRA_GPIO_PORT_N 13
#define TEGRA_GPIO_PORT_O 14
#define TEGRA_GPIO_PORT_P 15
#define TEGRA_GPIO_PORT_Q 16
#define TEGRA_GPIO_PORT_R 17
#define TEGRA_GPIO_PORT_S 18
#define TEGRA_GPIO_PORT_T 19
#define TEGRA_GPIO_PORT_U 20
#define TEGRA_GPIO_PORT_V 21
#define TEGRA_GPIO_PORT_W 22
#define TEGRA_GPIO_PORT_X 23
#define TEGRA_GPIO_PORT_Y 24
#define TEGRA_GPIO_PORT_Z 25

16 =Q
will it be physical GPIO pin 5 that will be equal to Q equal to 16?

attempt 1 seems failing at this point:

 cat  /mnt/developoment/Linux_for_Tegra/source/public/hardware/nvidia/platform/t19x/jakku/kernel-dts/tegra194-p3668-all-p3509-0000.dts
 * Top level DTS file for CVM:P3668-0001 and CVB:P3509-0000.
 * Copyright (c) 2019-2020, NVIDIA CORPORATION.  All rights reserved.
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 2 of the License.
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.

#include "common/tegra194-p3668-common.dtsi"
#include "common/tegra194-p3509-0000-a00.dtsi"

/ {
        nvidia,dtsfilename = __FILE__;
        nvidia,dtbbuildtime = __DATE__, __TIME__;

        compatible = "nvidia,p3449-0000+p3668-0000", "nvidia,p3449-0000+p3668-0001", "nvidia,p3509-0000+p3668-0000", "nvidia,p3509-0000+p3668-0001", "nvidia,tegra194";

pps {
    gpio = <&gpio TEGRA_GPIO(Q, 5) GPIO_ACTIVE_LOW>;
    compatible = “pps-gpio”;
    status = “okay”;

make -j8 ARCH=arm64 O=$TEGRA_KERNEL_OUT dtbs
make[1]: Entering directory ‘/mnt/outdir’
CHK scripts/mod/devicetable-offsets.h
DTC arch/arm64/boot/dts/ddot/ddot/ddot/ddot/ddot/ddot/hardware/nvidia/platform/t18x/quill/kernel-dts/tegra186-quill-p3310-1000-a00-00-base.dtb
DTC arch/arm64/boot/dts/ddot/ddot/ddot/ddot/ddot/ddot/hardware/nvidia/platform/t18x/quill/kernel-dts/tegra186-quill-p3310-1000-a00-00-ape-cam.dtb
DTC arch/arm64/boot/dts/ddot/ddot/ddot/ddot/ddot/ddot/hardware/nvidia/platform/t18x/quill/kernel-dts/tegra186-quill-p3310-1000-a00-00-edp.dtb
DTC arch/arm64/boot/dts/ddot/ddot/ddot/ddot/ddot/ddot/hardware/nvidia/platform/t18x/quill/kernel-dts/tegra186-quill-p3310-1000-a00-00-dsi-hdmi-dp.dtb
DTC arch/arm64/boot/dts/ddot/ddot/ddot/ddot/ddot/ddot/hardware/nvidia/platform/t18x/quill/kernel-dts/tegra186-quill-p3310-1000-c03-00-dsi-hdmi-dp.dtb
DTC arch/arm64/boot/dts/ddot/ddot/ddot/ddot/ddot/ddot/hardware/nvidia/platform/t18x/quill/kernel-dts/tegra186-quill-p3310-1000-a00-00-dsi-dp.dtb
DTC arch/arm64/boot/dts/ddot/ddot/ddot/ddot/ddot/ddot/hardware/nvidia/platform/t18x/quill/kernel-dts/tegra186-quill-hdmi-primary-p3310-1000-c03-00.dtb
DTC arch/arm64/boot/dts/ddot/ddot/ddot/ddot/ddot/ddot/hardware/nvidia/platform/t18x/quill/kernel-dts/tegra186-quill-hdmi-primary-p3310-1000-a00-00.dtb
DTC arch/arm64/boot/dts/ddot/ddot/ddot/ddot/ddot/ddot/hardware/nvidia/platform/t18x/quill/kernel-dts/tegra186-quill-p3310-1000-a00-00-base-mods-display.dtb
DTC arch/arm64/boot/dts/ddot/ddot/ddot/ddot/ddot/ddot/hardware/nvidia/platform/t18x/quill/kernel-dts/tegra186-quill-p3310-1000-a00-00-imx274.dtb
DTC arch/arm64/boot/dts/ddot/ddot/ddot/ddot/ddot/ddot/hardware/nvidia/platform/t18x/quill/kernel-dts/tegra186-quill-p3310-1000-a00-00-imx185_v1.dtb
DTC arch/arm64/boot/dts/ddot/ddot/ddot/ddot/ddot/ddot/hardware/nvidia/platform/t18x/quill/kernel-dts/tegra186-quill-p3310-1000-a00-00-lc898212.dtb
DTC arch/arm64/boot/dts/ddot/ddot/ddot/ddot/ddot/ddot/hardware/nvidia/platform/t18x/quill/kernel-dts/tegra186-quill-hdmi-primary-p3310-1000-a00-00-imx274.dtb
DTC arch/arm64/boot/dts/ddot/ddot/ddot/ddot/ddot/ddot/hardware/nvidia/platform/t18x/quill/kernel-dts/tegra186-quill-hdmi-primary-p3310-1000-c03-00-imx274.dtb
DTC arch/arm64/boot/dts/ddot/ddot/ddot/ddot/ddot/ddot/hardware/nvidia/platform/t18x/quill/kernel-dts/tegra186-quill-p3310-1000-c03-00-ape-cam.dtb
DTC arch/arm64/boot/dts/ddot/ddot/ddot/ddot/ddot/ddot/hardware/nvidia/platform/t18x/quill/kernel-dts/tegra186-quill-p3310-1000-c03-00-base.dtb
DTC arch/arm64/boot/dts/ddot/ddot/ddot/ddot/ddot/ddot/hardware/nvidia/platform/t18x/quill/kernel-dts/tegra186-quill-p3310-1000-c03-00-imx185_v1.dtb
DTC arch/arm64/boot/dts/ddot/ddot/ddot/ddot/ddot/ddot/hardware/nvidia/platform/t18x/quill/kernel-dts/tegra186-quill-p3310-1000-c03-00-dsi-dp.dtb
DTC arch/arm64/boot/dts/ddot/ddot/ddot/ddot/ddot/ddot/hardware/nvidia/platform/t18x/quill/kernel-dts/tegra186-quill-p3310-1000-c03-00-dsi-hdmi-hdmi.dtb
DTC arch/arm64/boot/dts/ddot/ddot/ddot/ddot/ddot/ddot/hardware/nvidia/platform/t18x/quill/kernel-dts/tegra186-quill-p3310-1000-c03-00-dsi-hdmi-hdmi-imx274-hdmiin.dtb
DTC arch/arm64/boot/dts/ddot/ddot/ddot/ddot/ddot/ddot/hardware/nvidia/platform/t18x/quill/kernel-dts/tegra186-quill-p3310-1000-c00-00-auo-1080p-edp.dtb
DTC arch/arm64/boot/dts/ddot/ddot/ddot/ddot/ddot/ddot/hardware/nvidia/platform/t18x/quill/kernel-dts/tegra186-quill-e3313-1000-a00-00-e2598.dtb
DTC arch/arm64/boot/dts/ddot/ddot/ddot/ddot/ddot/ddot/hardware/nvidia/platform/t18x/quill/kernel-dts/tegra186-quill-p3489-1000-a00-00-ucm1.dtb
DTC arch/arm64/boot/dts/ddot/ddot/ddot/ddot/ddot/ddot/hardware/nvidia/platform/t18x/quill/kernel-dts/tegra186-quill-p3489-1000-a00-00-ucm2.dtb
DTC arch/arm64/boot/dts/ddot/ddot/ddot/ddot/ddot/ddot/hardware/nvidia/platform/t18x/quill/kernel-dts/tegra186-quill-p3489-1000-a00-00-e2598.dtb
DTC arch/arm64/boot/dts/ddot/ddot/ddot/ddot/ddot/ddot/hardware/nvidia/platform/t18x/quill/kernel-dts/tegra186-quill-p3489-0888-a00-00-base.dtb
DTC arch/arm64/boot/dts/ddot/ddot/ddot/ddot/ddot/ddot/hardware/nvidia/platform/t18x/quill/kernel-dts/tegra186-quill-p3489-0888-a00-00-e2598.dtb
DTC arch/arm64/boot/dts/ddot/ddot/ddot/ddot/ddot/ddot/hardware/nvidia/platform/t18x/quill/kernel-dts/tegra186-quill-p3310-1000-as-0888.dtb
DTC arch/arm64/boot/dts/ddot/ddot/ddot/ddot/ddot/ddot/hardware/nvidia/platform/t19x/jakku/kernel-dts/tegra194-p3668-all-p3509-0000.dtb
DTC arch/arm64/boot/dts/ddot/ddot/ddot/ddot/ddot/ddot/hardware/nvidia/platform/t19x/galen/kernel-dts/tegra194-p2888-0001-p2822-0000.dtb
DTC arch/arm64/boot/dts/ddot/ddot/ddot/ddot/ddot/ddot/hardware/nvidia/platform/t19x/galen/kernel-dts/tegra194-p2888-0001-p2822-0000-imx274-hdmi.dtb
DTC arch/arm64/boot/dts/ddot/ddot/ddot/ddot/ddot/ddot/hardware/nvidia/platform/t19x/galen/kernel-dts/tegra194-p2888-0001-p2822-0000-imx185_v1.dtb
Error: /mnt/developoment/Linux_for_Tegra/source/public/kernel/kernel-4.9/arch/arm64/boot/dts/…/…/…/…/…/…/hardware/nvidia/platform/t19x/jakku/kernel-dts/tegra194-p3668-all-p3509-0000.dts:27.19-20 syntax error
FATAL ERROR: Unable to parse input tree
/mnt/developoment/Linux_for_Tegra/source/public/kernel/kernel-4.9/arch/arm64/boot/dts/Makefile:120: recipe for target ‘arch/arm64/boot/dts/ddot/ddot/ddot/ddot/ddot/ddot/hardware/nvidia/platform/t19x/jakku/kernel-dts/tegra194-p3668-all-p3509-0000.dtb’ failed
make[2]: *** [arch/arm64/boot/dts/ddot/ddot/ddot/ddot/ddot/ddot/hardware/nvidia/platform/t19x/jakku/kernel-dts/tegra194-p3668-all-p3509-0000.dtb] Error 1
make[2]: *** Waiting for unfinished jobs…
arch/arm64/Makefile:154: recipe for target ‘dtbs’ failed
make[1]: *** [dtbs] Error 2
make[1]: Leaving directory ‘/mnt/outdir’
Makefile:171: recipe for target ‘sub-make’ failed
make: *** [sub-make] Error 2

dtc -O dtb -o my-overlay.dtbo -@ my-overlay.dts
Error: my-overlay.dts:13.30-31 syntax error
FATAL ERROR: Unable to parse input tree

I think I have it working. I’m just testing with a GPS hat to see if I can actually see the pps transitions with ppstest.

OK, here we go…

Save this file as /boot/pps.dts


/ {
    overlay-name = "Jetson PPS";
    compatible = "nvidia,p3509-0000+p3668-0001";

    fragment {
        target-path = "/";
        __overlay__ {
			pps: pps_gpio {
				compatible = "pps-gpio";
				gpios = <&tegra_main_gpio 148 1>;
				status = "okay";

I changed the gpio to GPIO09 which is pin 7 on the 40 pin header because the GPS hat I have already hard wires the PPS signal to that pin.

Compile the dts into a dtbo

$ cd /boot
$ sudo dtc -I dts -O dtb -@ -o pps.dtbo pps.dts

Create a custom dtb from the stock dtbs and pps.dtbo

$ sudo fdtoverlay -i tegra194-p3668-all-p3509-0000.dtb -o tegra194-p3668-all-p3509-0000-user-custom.dtb tegra194-p3668-all-p3509-0000-hdr40.dtbo pps.dtbo

Now edit /boot/extlinux/extlinux.conf and add the following line to your menu entry…

    LINUX ...
    INITRD ...
    FDT /boot/tegra194-p3668-all-p3509-0000-user-custom.dtb
    APPEND ...

Now reboot.

When the system comes back up you should now have a /dev/pps0 device. If you connect your PPS source to pin 7 and you install the pps-tools package, you should be able to run

$ sudo ppstest /dev/pps0
trying PPS source "pps0"
found PPS source "pps0"
ok, found 1 source(s), now start fetching data...
source 0 - assert 1592529430.097600543, sequence: 2333 - clear  0.000000000, sequence: 0
source 0 - assert 1592529431.097604009, sequence: 2334 - clear  0.000000000, sequence: 0
source 0 - assert 1592529432.097600339, sequence: 2335 - clear  0.000000000, sequence: 0
source 0 - assert 1592529433.097601277, sequence: 2336 - clear  0.000000000, sequence: 0

Your next steps depend on how you want to get the kernel time to sync so that it can be sent by ptpd. What I do is use ntpd to take 2 sources. The first is a reliable upstream ntp server. The second is a generic nmea source that takes both the nmea sentences and the pps signal from the gps unit. Once the kernel is synced, ptpd can be set up as a master server.


Is it the only line that goes to the /boot/extlinux/extlinux.conf ?
Does the order matter?
I added it to the end of the file and rebooted; The remote device never get back online;
I will try to reflash it and repeat steps above.

Also :

sudo dtc -I dts -O dtb -@ -o pps.dtbo pps.dts
pps.dtbo: Warning (gpios_property): Could not get phandle node for /fragment/__overlay__/pps_gpio:gpios(cell 0)