[Jetson T5000 Custom Carrier Board] USB Type-C port stuck at High Speed after SuperSpeed+ device disconnect/reconnect, until reboot or ELPG triggered

Hi,

Software version: JetPack 7.1 / L4T R38.4

We are using a Jetson T5000 module on a custom-designed carrier board (not the Developer Kit). We have implemented a CC chip on the board and configured both USB2-0 and USB3-1 lanes in OTG mode for a Type-C port. Data role switching between Host mode / Device mode / Not Connected works correctly and reliably.

Issue description:

We found a reproducible issue that is specific to SuperSpeed+ (Gen2) USB Type-C devices, and the key trigger condition is the data role transition to “Not Connected” after disconnection — not simply the physical unplug event itself.

Reproduction steps:

  1. Connect a Type-C SuperSpeed+ USB device (e.g., a Type-C USB SSD) to the port — it enumerates correctly at SuperSpeed+ speed.
  2. Disconnect the device, and confirm the data role transitions back to “Not Connected” (this step is essential — if the data role does not go through this transition, the issue does not occur).
  3. Reconnect the same (or another) SuperSpeed+ USB device to the same port.
  4. Result: The port only enumerates the device at High Speed (USB 2.0). It can no longer negotiate SuperSpeed or SuperSpeed+ link speed.

Notably, this issue only occurs with SuperSpeed+ devices. When testing with a SuperSpeed (Gen1) only device, the port correctly re-enumerates at SuperSpeed on every disconnect/reconnect cycle, with no degradation — regardless of the data role transition.

Recovery methods:

The port only regains the ability to enumerate SuperSpeed+ devices after either:

  • A full system reboot, or
  • Disconnecting all USB devices on the system (including a USB-based BT module), which triggers the USB host controller to enter ELPG. After ELPG is entered, reconnecting a SuperSpeed+ device is recognized correctly again at full speed.

Questions:

  • Is this a known issue related to the data role transition to “Not Connected” not properly resetting the SuperSpeed+ (Gen2) PHY/link state?
  • Any guidance, debug suggestions (e.g., relevant logs to collect, register dumps), or known workarounds would be greatly appreciated.

I don’t know; could a udev rule help for your usb idVendor/idProduct?

lsusb
Bus 002 Device 002: ID 0bda:0489 Realtek Semiconductor Corp. 4-Port USB 3.0 Hub

grep usb /etc/udev/rules.d/99-nv*
/etc/udev/rules.d/99-nv-l4t-usb-host-config.rules:ACTION=="add", KERNEL=="2-3", SUBSYSTEM=="usb", ATTR{idVendor}=="0bda", ATTR{idProduct}=="0489", RUN+="/bin/sh -c 'echo enabled > /sys/bus/usb/devices/2-3/power/wakeup"

Can you post your device tree changes?

Hi,

Thank you very much for looking into this issue and for your quick response! Please find our device tree configuration for the USB Type-C port below.

Note that in our design, both id-gpio and vbus-gpio are provided by the CC chip on our custom carrier board. Due to the limited capability of this CC chip, we adopted compatible = "gpio-usb-b-connector" as our implementation for the dual-role switch.

dts

padctl@a808680000 {
    status = "okay";
    ports {
        usb2-0 {
            usb-role-switch;
            mode = "otg";
            status = "okay";
            connector {
                compatible = "gpio-usb-b-connector";
                label = "micro-USB";
                type = "micro";
                vbus-gpio = <&gpio_main
                             TEGRA264_MAIN_GPIO(P, 2)
                             GPIO_ACTIVE_HIGH>;
                id-gpio = <&gpio_uphy
                           TEGRA264_UPHY_GPIO(B, 7)
                           GPIO_ACTIVE_HIGH>;
            };
        };
        usb2-1 {
            mode = "host";
            status = "okay";
        };
        usb2-2 {
            mode = "host";
            status = "okay";
        };
        usb2-3 {
            mode = "host";
            status = "okay";
        };
        usb3-0 {
            nvidia,usb2-companion = <1>;
            status = "okay";
        };
        usb3-1 {
            nvidia,usb2-companion = <0>;
            status = "okay";
        };
        usb3-2 {
            nvidia,usb2-companion = <2>;
            status = "okay";
        };
    };
};

/* XUDC - usb device controller */
usb@a808670000 {
    phys = <&{/bus@0/padctl@a808680000/pads/usb2/lanes/usb2-0}>,
           <&{/bus@0/padctl@a808680000/pads/usb3/lanes/usb3-1}>;
    phy-names = "usb2-0", "usb3-1";
    status = "okay";
};

/* XUSB - usb host controller */
usb@a80aa10000 {
    phys = <&{/bus@0/padctl@a808680000/pads/usb2/lanes/usb2-0}>,
           <&{/bus@0/padctl@a808680000/pads/usb2/lanes/usb2-1}>,
           <&{/bus@0/padctl@a808680000/pads/usb2/lanes/usb2-2}>,
           <&{/bus@0/padctl@a808680000/pads/usb2/lanes/usb2-3}>,
           <&{/bus@0/padctl@a808680000/pads/usb3/lanes/usb3-0}>,
           <&{/bus@0/padctl@a808680000/pads/usb3/lanes/usb3-1}>,
           <&{/bus@0/padctl@a808680000/pads/usb3/lanes/usb3-2}>;
    phy-names = "usb2-0", "usb2-1", "usb2-2", "usb2-3",
                "usb3-0", "usb3-1", "usb3-2";
    status = "okay";
};

In addition, we found a possible workaround: limiting the maximum speed of the dual-role usb3 port (usb3-1) to SuperSpeed avoids the issue entirely:

dts

usb3-1 {
    nvidia,usb2-companion = <0>;
    maximum-speed = "super-speed";
    status = "okay";
};

While this workaround does mitigate the problem, our goal is to fully support SuperSpeed+ on this port for our product, so we would still greatly appreciate any guidance on resolving the root cause rather than relying on this speed limitation.

Please let us know if you need any further information to help investigate this issue. We really appreciate your support and look forward to your findings.

Thanks again!

Just wonder. Will this issue happen if you set mode to host instead of otg?

Hi,

Thanks for the question. No, this issue does not occur when the port is set to host mode. As mentioned earlier, since the port stays in host mode, it does not go through the data role transition to “Not Connected”, and as we noted, this transition is the essential trigger condition for the issue.

To further confirm this, we also tested a host-only Type-C port on our carrier board (formed by combining usb2-1 and usb3-0), and it works correctly — we are able to repeatedly disconnect and reconnect SuperSpeed+ devices on this port without any issue, consistently running at full SuperSpeed+ speed.

This further supports that the issue is specific to the OTG-mode port transitioning through “Not Connected”, rather than a general SuperSpeed+ signal integrity or hardware issue on our carrier board.

Please let us know if this helps narrow down the root cause.

Thanks again for your continued support!

should it be id-gpios vbus-gpios rather than id-gpio vbus -gpio

./kernel/kernel-noble/Documentation/devicetree/bindings/connector/usb-connector.yaml: vbus-gpios:
./kernel/kernel-noble/Documentation/devicetree/bindings/connector/usb-connector.yaml: - vbus-gpios

./kernel/kernel-noble/Documentation/devicetree/bindings/phy/nvidia,tegra186-xusb-padctl.yaml: id-gpios = <&pmic 0 GPIO_ACTIVE_HIGH>;


&xusb_padctl {
    status = "okay";

    ports {
        usb2-0 {
            mode = "otg";
            usb-role-switch;
            vbus-supply = <&vdd_usb0_5v>;
            status = "okay";

            connector {
                compatible = "gpio-usb-b-connector",
                             "usb-b-connector";
                label = "USB OTG";
                type = "micro";

                vbus-gpios = <&gpio_main
                              TEGRA264_MAIN_GPIO(P, 2)
                              GPIO_ACTIVE_HIGH>;

                id-gpios = <&gpio_uphy
                            TEGRA264_UPHY_GPIO(B, 7)
                            GPIO_ACTIVE_HIGH>;
            };
        };

        usb2-1 {
            mode = "host";
            vbus-supply = <&vdd_usb1_5v>;
            status = "okay";
        };

        usb2-2 {
            mode = "host";
            vbus-supply = <&vdd_usb2_5v>;
            status = "okay";
        };

        usb2-3 {
            mode = "host";
            vbus-supply = <&vdd_usb3_5v>;
            status = "okay";
        };

        usb3-0 {
            nvidia,usb2-companion = <1>;
            status = "okay";
        };

        usb3-1 {
            nvidia,usb2-companion = <0>;
            status = "okay";
        };

        usb3-2 {
            nvidia,usb2-companion = <2>;
            status = "okay";
        };
    };
};

&tegra_xudc {
    phys = <&{/bus@0/padctl@a808680000/pads/usb2/lanes/usb2-0}>,
           <&{/bus@0/padctl@a808680000/pads/usb3/lanes/usb3-1}>;
    phy-names = "usb2-0", "usb3-1";
    status = "okay";
};

&tegra_xhci {
    phys = <&{/bus@0/padctl@a808680000/pads/usb2/lanes/usb2-0}>,
           <&{/bus@0/padctl@a808680000/pads/usb2/lanes/usb2-1}>,
           <&{/bus@0/padctl@a808680000/pads/usb2/lanes/usb2-2}>,
           <&{/bus@0/padctl@a808680000/pads/usb2/lanes/usb2-3}>,
           <&{/bus@0/padctl@a808680000/pads/usb3/lanes/usb3-0}>,
           <&{/bus@0/padctl@a808680000/pads/usb3/lanes/usb3-1}>,
           <&{/bus@0/padctl@a808680000/pads/usb3/lanes/usb3-2}>;

    phy-names = "usb2-0", "usb2-1", "usb2-2", "usb2-3",
                "usb3-0", "usb3-1", "usb3-2";

    nvidia,xusb-padctl = <&xusb_padctl>;
    status = "okay";
};

Hi whitesscott,

Thanks for the suggestion. However, enabling USB hub wakeup does not seem to be related to this issue. Since SuperSpeed+ is only supported on the Type-C port, our Type-C port is wired directly from the Jetson T5000 module, without going through any USB hub.

Additionally, this issue does not appear to be related to suspend/resume either — the transition we’re describing is purely the data role switching to “Not Connected” during normal runtime, not a system-level power state change.

should it be id-gpios vbus-gpios rather than id-gpio vbus -gpio…

Thanks for checking on this. To clarify, this part is not an issue on our side — we have already confirmed that the role switch is functioning correctly on our carrier board.

We’d also like to note that we found several inconsistencies/errors in the YAML configuration examples and the official Developer Guide during our bring-up, which can actually prevent the intended settings from taking effect if followed as-is. We had to work around these documentation issues ourselves to get the role switch working properly.

Please let us know if this helps clarify the setup, or if there are other directions worth investigating.

Do you have USB analyzer that can dump the bus trace? This would be the most precise way to debug.

I’d already just done this so might as well post.

When attached Image boots on the JP 7.1 machine, every role switch to HOST on the OTG port should send MBOX_CMD_RESET_SSPI to the xHC firmware before re-powering the SS port.

cd Linux_for_Tegra
patch -p1 < 0001-xhci-tegra-enable-otg_reset_sspi-on-tegra264.patch
# or
git apply 0001-xhci-tegra-enable-otg_reset_sspi-on-tegra264.patch

It includes a commit-message-style description of a hypothesised cause, and hits
source/kernel/kernel-noble/drivers/usb/host/xhci-tegra.c.

The patched Image was just built and is attached. You could copy that 
Image to /boot/Image (after backing up the original and enabling 
the extlinux backup entry) and reboot. The patch file is mainly 
useful as documentation or if you want to rebuild Image.

0001-xhci-tegra-enable-otg_reset_sspi-on-tegra264.patch.txt (1.0 KB)
Image.txt (49.6 MB)

Hi Wayne,

We’re sorry, but we don’t have a USB analyzer available on hand for this analysis. If adding any debug logs would be helpful, please let us know — for example, from drivers/phy/tegra/xusb.c or drivers/usb/host/xhci-tegra.c.

We’re happy to enable additional debug prints or logging in these drivers if that would help narrow down the root cause.

Thanks!

Hi whitesscott,

For your reference, our AI Agent had also suggested the same approach earlier, but it did not resolve the issue. The log returned a “mailbox is busy” error.

We have also tried powering off/on the U3 PHY, but this did not help either.

Would appreciate any further suggestions on where to look next.

Thanks!

00002*.patch attached. It adds

  in tegra_xhci_id_work():

  1. Pre-send register dump — mbox pre-send: owner=... cmd=... data_out=... smi_intr=... in dmesg on every NONE→HOST switch
  2. Force-clear of a stale owner back to MBOX_OWNER_NONE before sending
  3. Success log — RESET_SSPI sent for usb3 port N (v1 only logged failure)

If:
  dmesg shows: owner=0xffffffff
  BAR2 ARU mailbox registers aren't accessible on T264 — RESET_SSPI can't be delivered this way; pivot to forcing ELPG entry/exit on role switch 
  ────────────────────────────────────────
  dmesg shows: force-clearing mbox owner 0x1/0x2 → RESET_SSPI sent
  Handshake was stuck because skip_mbox_config never negotiated MSG_ENABLED; the real test is now live — does Gen2 survive cycling?
  ────────────────────────────────────────
  dmesg shows: RESET_SSPI sent but Gen2 still dies
  Firmware took the command but ignored it (T264 firmware may not implement RESET_SSPI) — strong evidence for NVIDIA that a firmware-side fix is needed.

0002-xhci-tegra-otg-reset-sspi-t264-mbox-diagnostics.patch.txt (3.6 KB)

Hi whitesscott,

Here is the log with the 0002 patch applied, with each step of the reproduction annotated:

Step 1: Insert the test device (both High Speed and SuperSpeed+ interfaces enumerate)

[   65.998109] tegra-xusb a80aa10000.usb: tegra_xhci_id_notify(): action is 2
[   65.998246] tegra-xusb a80aa10000.usb: host mode on
[   65.998309] tegra-xusb a80aa10000.usb: mbox pre-send: owner=0x2 cmd=0x88000000 data_out=0x0 smi_intr=0x0
[   66.005242] tegra-xusb a80aa10000.usb: force-clearing mbox owner 0x2
[   66.261581] tegra-xusb a80aa10000.usb: failed to RESET_SSPI -110
[   66.261607] tegra-xusb a80aa10000.usb: tegra_xhci_set_port_power():set SS port power
[   66.261981] tegra-xusb a80aa10000.usb: failed to set SS PP 160
[   66.267289] tegra-xusb a80aa10000.usb: tegra_xhci_set_port_power():set HS port power
[   66.275325] tegra-xusb a80aa10000.usb: failed to set HS PP 0
[   66.649613] usb 1-1: new high-speed USB device number 7 using tegra-xusb
[   66.876739] usb 1-1: New USB device found, idVendor=1043, idProduct=0808, bcdDevice= 5.16
[   66.876792] usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[   66.877946] usb 1-1: Product: ASUSTEK0.01
[   66.882118] usb 1-1: Manufacturer: ASUSTEK
[   76.235478] start_addr=(0x20000), end_addr=(0x40000), buffer_size=(0x20000), smp_number_max=(16384)
[   77.798244] usb 2-2: new SuperSpeed Plus Gen 2x1 USB device number 4 using tegra-xusb
[   77.829675] usb 2-2: New USB device found, idVendor=174c, idProduct=1351, bcdDevice= 1.00
[   77.829726] usb 2-2: New USB device strings: Mfr=2, Product=3, SerialNumber=1
[   77.830844] usb 2-2: Product: USB3.1
[   77.834365] usb 2-2: Manufacturer: ASUSTEK
[   77.838544] usb 2-2: SerialNumber: 00008012192352533797
[   77.870918] usb-storage 2-2:1.0: USB Mass Storage device detected
[   77.872024] scsi host0: usb-storage 2-2:1.0
[   78.889590] scsi 0:0:0:0: Direct-Access     ASMT     2135             0    PQ: 0 ANSI: 6
[   78.895477] sd 0:0:0:0: [sda] Media removed, stopped polling
[   78.896523] sd 0:0:0:0: [sda] Attached SCSI removable disk

Step 2: Disconnect the test device


[   89.311605] usb 1-1: USB disconnect, device number 7
[   89.341403] usb 2-2: USB disconnect, device number 4
[   89.513653] tegra-xusb a80aa10000.usb: tegra_xhci_id_notify(): action is 0
[   89.513748] tegra-xusb a80aa10000.usb: host mode off
[   89.513801] tegra-xusb a80aa10000.usb: tegra_xhci_set_port_power():clear SS port power
[   89.531485] tegra-xusb a80aa10000.usb: tegra_xhci_set_port_power():clear HS port power
[   89.541717] tegra-xusb a80aa10000.usb: failed to clear HS PP 256

Step 3: Reconnect the device — this time SuperSpeed+ is NOT recognized (only High Speed)

[   92.441638] tegra-xusb a80aa10000.usb: tegra_xhci_id_notify(): action is 2
[   92.441758] tegra-xusb a80aa10000.usb: host mode on
[   92.441819] tegra-xusb a80aa10000.usb: mbox pre-send: owner=0x2 cmd=0x88000000 data_out=0x0 smi_intr=0x0
[   92.448753] tegra-xusb a80aa10000.usb: force-clearing mbox owner 0x2
[   92.705581] tegra-xusb a80aa10000.usb: failed to RESET_SSPI -110
[   92.705600] tegra-xusb a80aa10000.usb: tegra_xhci_set_port_power():set SS port power
[   92.705980] tegra-xusb a80aa10000.usb: failed to set SS PP 160
[   92.711281] tegra-xusb a80aa10000.usb: tegra_xhci_set_port_power():set HS port power
[   92.719284] tegra-xusb a80aa10000.usb: failed to set HS PP 0
[   93.077598] usb 1-1: new high-speed USB device number 8 using tegra-xusb
[   93.304878] usb 1-1: New USB device found, idVendor=1043, idProduct=0808, bcdDevice= 5.16
[   93.304912] usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[   93.306052] usb 1-1: Product: ASUSTEK0.01
[   93.310253] usb 1-1: Manufacturer: ASUSTEK

As shown above, even with the 0002 patch applied, the same failed to RESET_SSPI -110 / failed to set SS PP 160 / failed to set HS PP 0 sequence appears in both Step 1 (SuperSpeed+ successfully enumerates) and Step 3 (only High Speed enumerates), so the issue still reproduces after the patch.

Please let us know if there’s any additional information we can provide, or any further patches to try.

Thanks!

What changed vs v2:

Mailbox send removed — proven undeliverable (also eliminates the 250 ms stall on every role switch)

Warm (BH) reset added — after the SS companion port is re-powered on NONE→HOST, the driver issues SetPortFeature(USB_PORT_FEAT_BH_PORT_RESET), which sets PORTSC.WPR. That’s handled by the xHC LTSSM in hardware — no firmware mailbox involvement — and forces retraining from Rx.Detect with the full warm-reset LFPS handshake.

dmesg marker: warm reset issued on usb3 port N
0003-xhci-tegra-t264-warm-reset-otg-ss-port-on-role-switch.patch.txt (3.3 KB)


edit: also grab result of:
sudo dmesg -T |grep "Firmware timestamp"

Hi whitesscott,

Here is the log with the (updated) 0003 patch applied:

Step 1: Insert the test device (both High Speed and SuperSpeed+ interfaces enumerate)

[   55.695850] tegra-xusb a80aa10000.usb: tegra_xhci_id_notify(): action is 2
[   55.695901] tegra-xusb a80aa10000.usb: host mode on
[   55.695924] tegra-xusb a80aa10000.usb: tegra_xhci_set_port_power():set SS port power
[   55.695996] tegra-xusb a80aa10000.usb: warm reset issued on usb3 port 1
[   55.695998] tegra-xusb a80aa10000.usb: tegra_xhci_set_port_power():set HS port power
[   55.696247] tegra-xusb a80aa10000.usb: failed to set HS PP 0
[   55.967793] usb 1-1: new high-speed USB device number 8 using tegra-xusb
[   56.119395] usb 1-1: New USB device found, idVendor=1043, idProduct=0808, bcdDevice= 5.16
[   56.119402] usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[   56.119405] usb 1-1: Product: ASUSTEK0.01
[   56.119408] usb 1-1: Manufacturer: ASUSTEK
[   59.237443] start_addr=(0x20000), end_addr=(0x40000), buffer_size=(0x20000), smp_number_max=(16384)
[   72.652727] usb 2-2: new SuperSpeed Plus Gen 2x1 USB device number 5 using tegra-xusb
[   72.677579] usb 2-2: New USB device found, idVendor=174c, idProduct=1351, bcdDevice= 1.00
[   72.677604] usb 2-2: New USB device strings: Mfr=2, Product=3, SerialNumber=1
[   72.677610] usb 2-2: Product: USB3.1
[   72.677613] usb 2-2: Manufacturer: ASUSTEK
[   72.677617] usb 2-2: SerialNumber: 00008012192352533797
[   72.680034] usb-storage 2-2:1.0: USB Mass Storage device detected
[   72.681318] scsi host0: usb-storage 2-2:1.0
[   73.702755] scsi 0:0:0:0: Direct-Access     ASMT     2135             0    PQ: 0 ANSI: 6
[   73.705579] sd 0:0:0:0: [sda] Media removed, stopped polling
[   73.706393] sd 0:0:0:0: [sda] Attached SCSI removable disk

Step 2: Disconnect the test device

[   78.326619] usb 1-1: USB disconnect, device number 8
[   78.363802] usb 2-2: USB disconnect, device number 5
[   78.531861] tegra-xusb a80aa10000.usb: tegra_xhci_id_notify(): action is 0
[   78.531945] tegra-xusb a80aa10000.usb: host mode off
[   78.531989] tegra-xusb a80aa10000.usb: tegra_xhci_set_port_power():clear SS port power
[   78.532713] tegra-xusb a80aa10000.usb: tegra_xhci_set_port_power():clear HS port power
[   79.237485] start_addr=(0x20000), end_addr=(0x40000), buffer_size=(0x20000), smp_number_max=(16384)

Step 3: Reconnect the device — SuperSpeed+ is NOT recognized (only High Speed enumerates)

[   81.767845] tegra-xusb a80aa10000.usb: tegra_xhci_id_notify(): action is 2
[   81.767935] tegra-xusb a80aa10000.usb: host mode on
[   81.767981] tegra-xusb a80aa10000.usb: tegra_xhci_set_port_power():set SS port power
[   81.768247] tegra-xusb a80aa10000.usb: failed to set SS PP 160
[   81.768259] tegra-xusb a80aa10000.usb: warm reset issued on usb3 port 1
[   81.768262] tegra-xusb a80aa10000.usb: tegra_xhci_set_port_power():set HS port power
[   81.768527] tegra-xusb a80aa10000.usb: failed to set HS PP 0
[   82.043790] usb 1-1: new high-speed USB device number 9 using tegra-xusb
[   82.195410] usb 1-1: New USB device found, idVendor=1043, idProduct=0808, bcdDevice= 5.16
[   82.195420] usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[   82.195427] usb 1-1: Product: ASUSTEK0.01
[   82.195431] usb 1-1: Manufacturer: ASUSTEK

Hi tzuwen_chang,

0004-xhci-tegra-t264-warm-reset-wait-for-pp-and-log-portsc.patch - supersedes 0003 apply to a pristine xhci-tegra.c , not on top of 0003.

What it does differently than 0003:

  1. Waits up to ~100 ms for PP=1 to actually read back before issuing the warm reset (v3 fired WPR at a port that was still unpowered in Step 3 — a
    no-op per xHCI)
  2. Logs pre-reset status including how long PP took — SS port 1 pre-warm-reset status 0x… (PP on, waited ~N ms); if it says PP STILL OFF after 100
    ms, that may be a major finding (the firmware is refusing to power the port after role cycling)
  3. Logs post-reset status 120 ms after WPR — decode the link-state field (bits 8:5 of the status word):

Table: how to read the logs post 0004 run.

              post-warm-reset status              │       Meaning                                         

CCS+PED set, link state 0 (U0) — e.g. 0x203/0x703 │ Warm reset retrained the link — workaround found                                        

Link state 5 (RxDetect, 0xa0-ish)                 │ Port doesn't even see far-end termination — stale state blocks detection                

Link state 7 (Polling) or 10 (Compliance)         │ Device detected but training fails — stale Gen2 training state confirmed at LTSSM level 

PP STILL OFF in pre-reset line                    │ Firmware refuses port power after role cycle 

Note:
Reviewed the github/NVIDIA/edk2-nvidia XhciControllerDxe source to rule out boot-time involvement: on T264 neither UEFI nor the kernel loads or messages the xHC firmware (it boots from IFR on unpowergate), consistent with the mailbox being unserviced. However, the FW_IOCTL interface via XUSB_BAR2_ARU_FW_SCRATCH clearly is serviced (the driver reads the firmware config table through it at probe). Is there an FW_IOCTL equivalent of MBOX_CMD_RESET_SSPI, or could one be added? That seems like a much smaller change than restoring full mailbox support.

0004-xhci-tegra-t264-warm-reset-wait-for-pp-and-log-portsc.patch.txt (4.3 KB)

Hi whitesscott,

We applied patch 0004, but the SuperSpeed+ device still fails to be recognized after disconnect/reconnect. We suspect we may be looking in the wrong direction for this issue.

[   70.469612] tegra-xusb a80aa10000.usb: tegra_xhci_id_notify(): action is 0
[   70.469752] tegra-xusb a80aa10000.usb: host mode off
[   70.469811] tegra-xusb a80aa10000.usb: tegra_xhci_set_port_power():clear SS port power
[   70.476047] tegra-xusb a80aa10000.usb: tegra_xhci_set_port_power():clear HS port power
[   85.829939] tegra-xusb a80aa10000.usb: tegra_xhci_id_notify(): action is 2
[   85.830098] tegra-xusb a80aa10000.usb: host mode on
[   85.830156] tegra-xusb a80aa10000.usb: tegra_xhci_set_port_power():set SS port power
[   85.836423] tegra-xusb a80aa10000.usb: SS port 1 pre-warm-reset status 0x2a0 (PP on, waited ~0 ms)
[   85.969549] tegra-xusb a80aa10000.usb: SS port 1 post-warm-reset status 0x2a0
[   85.969594] tegra-xusb a80aa10000.usb: tegra_xhci_set_port_power():set HS port power
[   86.241525] usb 1-1: new high-speed USB device number 7 using tegra-xusb
[   86.393131] usb 1-1: New USB device found, idVendor=1043, idProduct=0808, bcdDevice= 5.16
[   86.393159] usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[   86.394299] usb 1-1: Product: ASUSTEK0.01
[   86.398493] usb 1-1: Manufacturer: ASUSTEK
[   92.024872] usb 2-2: new SuperSpeed Plus Gen 2x1 USB device number 5 using tegra-xusb
[   92.046164] usb 2-2: New USB device found, idVendor=174c, idProduct=1351, bcdDevice= 1.00
[   92.046192] usb 2-2: New USB device strings: Mfr=2, Product=3, SerialNumber=1
[   92.047320] usb 2-2: Product: USB3.1
[   92.050824] usb 2-2: Manufacturer: ASUSTEK
[   92.055020] usb 2-2: SerialNumber: 00008012192352533797
[   92.062187] usb-storage 2-2:1.0: USB Mass Storage device detected
[   92.067971] scsi host0: usb-storage 2-2:1.0
[   93.095788] scsi 0:0:0:0: Direct-Access     ASMT     2135             0    PQ: 0 ANSI: 6
[   93.098200] sd 0:0:0:0: [sda] Media removed, stopped polling
[   93.098885] sd 0:0:0:0: [sda] Attached SCSI removable disk
[   98.557536] usb 2-2: USB disconnect, device number 5
[   99.238718] usb 1-1: USB disconnect, device number 7
[   99.445580] tegra-xusb a80aa10000.usb: tegra_xhci_id_notify(): action is 0
[   99.445684] tegra-xusb a80aa10000.usb: host mode off
[   99.445738] tegra-xusb a80aa10000.usb: tegra_xhci_set_port_power():clear SS port power
[   99.452142] tegra-xusb a80aa10000.usb: tegra_xhci_set_port_power():clear HS port power
[  107.965905] tegra-xusb a80aa10000.usb: tegra_xhci_id_notify(): action is 2
[  107.966053] tegra-xusb a80aa10000.usb: host mode on
[  107.966109] tegra-xusb a80aa10000.usb: tegra_xhci_set_port_power():set SS port power
[  107.971348] tegra-xusb a80aa10000.usb: SS port 1 pre-warm-reset status 0x2a0 (PP on, waited ~0 ms)
[  108.105850] tegra-xusb a80aa10000.usb: SS port 1 post-warm-reset status 0x2a0
[  108.105902] tegra-xusb a80aa10000.usb: tegra_xhci_set_port_power():set HS port power
[  108.377529] usb 1-1: new high-speed USB device number 8 using tegra-xusb
[  108.529131] usb 1-1: New USB device found, idVendor=1043, idProduct=0808, bcdDevice= 5.16
[  108.529158] usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[  108.530301] usb 1-1: Product: ASUSTEK0.01
[  108.534487] usb 1-1: Manufacturer: ASUSTEK

Hi WayneWWW,

Could you share any insight from NVIDIA’s side on this issue?

Thanks!

Hi @WayneWWW and @tzuwen_chang

The fact that these drivers are loaded suggested another avenue:
lsmod|grep ucsi
ucsi_ccg 20480 0
typec_ucsi 45056 1 ucsi_ccg
typec 61440 1 typec_ucsi


tegra264-p4071-ucsi-ccg.dtbo.txt (2.2 KB)
tegra264-p4071-ucsi-ccg-overlay.dts.txt (2.5 KB)

Jetson_Thor_Series_Modules_Pinmux_Template
Row 286: I2CS_INT_CCG_SOC_ALT = SOC_GPIO283 = GPIO3_PZ.05 (ball A38), pulled up to 3V3 in the module —
the only CCG signal in the sheet, and the name says exactly what it is: the CCG’s I2C-slave interrupt to the SoC.

Hardware verification on the live devkit: gpioget on gpiochip2 (tegra264-gpio main) line 53 reads driven low — with the 3V3 pull-up, that means the CCG is actively asserting its active-low INT right now, with events queued since boot that no driver has ever serviced. Pin, chip, and behavior all corroborate.

Overlay created and built:

  • tegra264-p4071-ucsi-ccg-overlay.dts — interrupts = <TEGRA264_MAIN_GPIO(Z, 5)
    IRQ_TYPE_LEVEL_LOW> on &gpio_main, CCG at &i2c2 reg 0x08, connector graph tying connector@0 to padctl
    usb2-0 (HS) + usb3-1 (SS companion)
  • tegra264-p4071-ucsi-ccg.dtbo — compiled, fixups verified (0x35/0x8 = pin 53, level-low)

To test:
sudo cp tegra264-p4071-ucsi-ccg.dtbo /boot/
Add to /boot/extlinux/extlinux.conf under the LINUX/FDT lines:
OVERLAYS /boot/tegra264-p4071-ucsi-ccg.dtbo
sudo reboot

Success looks like: ucsi_ccg 2-0008 binding in dmesg, /sys/class/typec/port0 appearing, and role flips in usb2-0-role-switch/role on physical plug/unplug — which would turn the manual sysfs repro into the true plug-driven field scenario. If get_fw_info failed appears instead, the CCG firmware build doesn’t expose UCSI to the SoC and this path is closed.

Hi,

There is not much to do here unless you could dump usb bus trace.

Other minor checks are like removing something that is related to 2.4G sideband (e.g. LTE/BT/WIFI) to avoid interference.

And check the hardware layout. Doing compliance test might clarify.

The standard way to check why speed stuck in USB2 are just above.

Hi @WayneWWW,

Thanks for the reply. I’d like to push back a bit on the interference/layout angle before we go spend time on a bus analyzer or compliance test, because I don’t think the evidence fits that theory.

Why we don’t think this is signal interference or a layout issue

The same physical port, same cable, same device, same board – successfully trains to SuperSpeedPlus the first time, every time. It only degrades after a specific software sequence (detach → OTG role switch to “none” → switch back to “host”). If this were EMI (2.4G sideband) or a layout/signal-integrity problem, I’d expect it to affect the first connection too, or at least be intermittent/statistical regardless of history. What we see instead is fully deterministic and tied to a specific event sequence, not to physical conditions – nothing on the board or in the environment changes between “before” and “after” that sequence. So I don’t think a compliance test or removing the 2.4G radios would tell us anything new here; the hardware is demonstrably capable of full SuperSpeedPlus link training when the software/firmware state hasn’t been perturbed by that sequence.

Given that, we’ve been focusing on the software/firmware side, and think we’ve narrowed the trigger condition down quite a bit:

Refined repro condition

The port isn’t stuck at USB2 in general – it only gets stuck after this specific sequence:

  1. Attach a SuperSpeedPlus (Gen2, 10Gbps) device to the OTG port while it’s in host mode – enumerates fine at SuperSpeedPlus.
  2. Detach it.
  3. Switch the OTG port’s role to “none” and back to “host” (through the normal ID/role-switch path, tegra_xhci_id_work()).
  4. Attach any SuperSpeed-class device (Gen1 or Gen2) to the same port.

After step 3, the port can no longer train to SuperSpeed at all (Gen1 or Gen2) – it falls back to USB2-only. USB2 devices on that same port still enumerate fine, so the port/pad itself isn’t dead.

Importantly: we confirmed this only happens if a Gen2 device was previously attached. If we only ever attach Gen1 SuperSpeed devices, the same host → none → host role-switch cycle does not reproduce the problem. That’s a second piece of evidence against interference/layout: EMI or a marginal signal path wouldn’t care whether a previous device happened to negotiate Gen1 vs Gen2 – it would affect the current connection attempt based on physical conditions at that moment, not on history. The fact that it’s gated entirely on “was a Gen2 device attached before” tells us this is state that gets created during Gen2 link training and isn’t being cleared, not a physical-layer problem.

What we’ve already tried (neither helped)

  1. Power-cycling the OTG port’s usb2 and usb3 phys (phy_power_off → phy_exit → phy_init → phy_power_on) when the role switches away from host, before switching back. This only touches the padctl analog macro power domain (XUSB_PADCTL_ELPG_PROGRAM_1 SSPX_ELPG_* bits) – no effect.
  2. A warm (BH) port reset (SetPortFeature USB_PORT_FEAT_BH_PORT_RESET) on the SS port after re-powering it on the way back into host mode, to force the xHCI-side LTSSM to retrain from scratch – no effect either.

Since neither the padctl/PHY register layer nor the xHCI-controller port-reset layer clears the problem, our current best guess is that some Gen2-specific link-training state (e.g. DFE/CTLE receiver-equalization context) is cached inside the XUSB falcon firmware for that port, and isn’t invalidated by either of the above.

Two things in the driver support this guess:

  • MBOX_CMD_SAVE_DFE_CTLE_CTX is a firmware->driver mailbox message for saving a port’s DFE/CTLE context after training, but the driver-side usb3_save_context padctl op is only implemented for Tegra124 – on T186/T194/T234/T264 it’s left NULL (tegra_xusb_padctl_usb3_save_context() just returns -ENOSYS). So on T264 this context looks fully firmware/hardware-owned and invisible to the kernel driver.
  • The existing otg_reset_sspi path (sends MBOX_CMD_RESET_SSPI to ask firmware to reset the SS Port Interface when re-entering host mode) doesn’t appear to be serviced by T264 firmware – the mailbox call just times out unanswered, which is why it’s currently disabled for T264 (otg_reset_sspi = false).

What we’d like to avoid

We know a full firmware reload (cycling the whole controller through our ELPG suspend/resume path, which calls xhci_suspend/xhci_resume and reloads firmware) would very likely clear this. But that’s controller-wide – it would disrupt every other USB device on both root hubs, not just the OTG port – so it’s not something we want to do on every OTG role switch.

Questions

  1. Is this a known limitation on T264 – per-port Gen2 link-training/DFE-CTLE state cached in firmware that survives both a port power-cycle and a warm (BH) port reset?
  2. Is there any other mailbox command, padctl register, or firmware API that can make firmware discard/reinitialize a single port’s Gen2 training state, short of a full controller suspend/resume + firmware reload?
  3. If full firmware reload is really the only way today, is there any way to scope it to a single port?

We’re happy to pull dmesg / PORTSC dumps before and after the failure, or a bus trace if you still think that’s needed once you’ve seen the above – just let us know what would be most useful given this more specific trigger condition.

Thanks again for taking the time to look into this.