JetPack 6 USB Enumeration Failure: Root Cause in 4 Hours
UncommonLab called on a Thursday. Their team had been debugging a USB enumeration failure for three weeks. Every USB device connected to their custom carrier board came up dead — no enumeration, no error, nothing in dmesg beyond the host controller initializing. They’d upgraded to JetPack 6 two weeks before a demo deadline. The board had worked on JetPack 5.
We found the root cause in 4 hours. Fixed it in under 20.
Key Insights
-
JetPack 6 is a bigger jump than it looks. L4T R35 to R36 moves the kernel from 5.10 to 5.15. The USB subsystem changes between those versions are not minor — PHY node bindings changed, PINMUX assignments changed, and device tree properties that worked in R35 are silently ignored in R36. No warning, no error, just a USB controller that initializes and does nothing.
-
The failure mode is deceptive. The host controller comes up. dmesg shows it initializing. But devices never enumerate. There’s no obvious error to search. The forums don’t have the answer. You’re debugging silence, which is harder than debugging a crash.
-
Four device tree mismatches cause most JetPack 6 USB failures. PINMUX not updated for R36, VBUS sequencing mismatch, deprecated USB PHY node properties, and host controller binding conventions from JetPack 5. Any one of them can cause the failure. All four need to be checked before you’ve confirmed root cause.
-
Pattern recognition is the time multiplier. We found root cause in 4 hours because we’d been in that exact configuration before — different carrier board, same JetPack 6 upgrade, same symptom. Without that pattern, it’s 2-4 weeks of debugging cycles.
-
Full IP transfer was a standard term. The corrected device tree, the PINMUX patch, and the diagnostic notes went to UncommonLab with full IP ownership at handoff. No retainer. No lock-in.
What JetPack 6 actually changed in USB
When JetPack 5 moved to JetPack 6, the headline changes were performance: Jetson Orin support, updated TensorRT, new DeepStream pipeline. What the release notes don’t emphasize is that L4T R36 also updated the Linux kernel from 5.10 to 5.15, and the USB subsystem in 5.15 is not backwards-compatible with device trees written for 5.10.
The specific changes:
- USB PHY node bindings changed. Properties valid in the 5.10 USB PHY driver are deprecated in 5.15. They won’t throw a hard error on boot — they’ll be silently ignored. The PHY comes up without the configuration you specified.
- PINMUX assignments shifted. L4T R36 revised the pin multiplexing configuration for USB-related pins on Orin. A device tree that correctly configured PINMUX for JetPack 5 will not configure the same pins correctly in R36 without explicit updates.
- VBUS sequencing changed. The power-enable GPIO timing for the USB VBUS rail changed between BSP versions. If your device tree fires the GPIO at the wrong point in the bring-up sequence, the host controller initializes before the VBUS rail is stable — and devices never enumerate.
- Host controller driver binding conventions changed. The compatible string and register map for the USB host controller node follows JetPack 5 conventions in boards that shipped before JetPack 6. R36 expects different node structure.
None of these produce loud failures. They produce silence. The controller starts. The enumeration never happens.
How we diagnosed the UncommonLab JetPack 6 USB enumeration failure
When UncommonLab described the symptom — host controller up, no device enumeration, no error — the pattern matched immediately. We’d seen the same symptom on two prior JetPack 6 boards. Both times, the root cause was in the same four places.
Step 1: Check the kernel version and BSP against the device tree origin.
We confirmed they were running L4T R36 with a device tree written against R35. That’s the first thing to verify on any JetPack 6 USB failure. Many custom carrier boards ship with device trees based on NVIDIA’s reference BSP for JetPack 5. When the team upgrades JetPack, the device tree doesn’t automatically update.
Step 2: Audit the USB PHY node.
We pulled the device tree source and compared the PHY node properties against the R36 BSP documentation. Deprecated properties were present. The PHY was initializing without the VBUS current limit and turn-on delay settings the team had specified — they were being silently dropped by the kernel.
Step 3: Check the PINMUX configuration.
NVIDIA’s Jetson Pin Mux tool generates a PINMUX configuration for each BSP version. The team had used the R35 tool output. We ran a diff against the R36 reference configuration for the USB pins — the assignments had changed for several of them.
Step 4: Trace VBUS sequencing.
We added boot-time logging to trace when the VBUS power-enable GPIO was firing relative to USB host controller initialization. The GPIO was firing before the controller was ready. VBUS came up too early, the host controller missed it, and devices had no power to enumerate against.
Four issues, all present simultaneously. That’s typical for a JetPack 5-to-6 migration on a custom carrier board — you’re not dealing with one wrong thing, you’re dealing with four things written against a BSP that no longer matches.
The fix
We corrected the device tree in three passes.
PHY node update: Removed the deprecated properties, added R36-compatible bindings with the correct VBUS current and turn-on delay configuration. Verified the PHY was picking up the new configuration with usbcore.autosuspend=-1 disabled.
PINMUX patch: Generated a fresh PINMUX configuration using the R36 Jetson Pin Mux tool with the correct target hardware. Applied it as a device tree overlay rather than modifying the base board DTS directly — cleaner for future BSP migrations.
VBUS sequencing fix: Added a regulator-fixed node for the VBUS rail with the correct enable timing and GPIO assignment for R36. The host controller now waits for the regulator to come up before attempting enumeration.
Total time from first call to validated fix: under 20 hours. UncommonLab had USB enumeration working across all ports before the end of the next business day.
Everything we built — the corrected device tree, the overlay structure, the PINMUX patch, the diagnostic notes — transferred to UncommonLab at handoff. No ongoing dependency.
Why this keeps appearing on JetPack 6 upgrades
JetPack 6 is not a drop-in upgrade for custom carrier boards. The BSP changes at the kernel level, and device trees written against R35 reference hardware don’t automatically become valid R36 device trees.
The upgrade looks seamless at first. You flash JetPack 6. The board boots. Most things work. It’s only when you connect a USB device — or a camera over USB — that the device tree gap becomes visible. The failure shows up weeks after the upgrade, when you’re deep into integration and the demo is close.
The other reason this pattern keeps appearing: the documentation gap. NVIDIA publishes the R36 BSP and migration notes, but specific PHY property deprecations aren’t flagged with loud kernel warnings. Engineers debugging this for the first time are searching for errors that don’t exist. What they need is someone who has already debugged it before.
If you’re planning a JetPack 5-to-6 migration on a custom carrier board, audit your device tree against the R36 BSP before you flash. Check the PHY nodes, the PINMUX configuration, and the VBUS sequencing. If you’ve already hit the wall — host controller up, no enumeration, no error — the four areas above are where to start.
For teams weighing whether to debug this in-house or bring in a specialist, the timeline and cost breakdown is in our post on hiring vs contracting for Jetson work.
Frequently Asked Questions (FAQs)
Why does USB enumeration fail after upgrading to JetPack 6?
JetPack 6 moves from L4T R35 to L4T R36, updating the kernel from 5.10 to 5.15 with a revised USB subsystem. Device trees written for JetPack 5 use deprecated PHY node bindings and PINMUX configurations that don’t map to R36. The host controller initializes, devices never enumerate. No error. Just silence.
What are the most common root causes of JetPack 6 USB enumeration failures?
Four issues cover the majority of cases: PINMUX configuration not updated for L4T R36, VBUS sequencing mismatch where the power-enable GPIO fires before the controller is ready, deprecated USB PHY node properties silently ignored by the R36 kernel, and USB host controller device tree nodes still using JetPack 5 binding conventions. Check all four before declaring root cause.
How long does it take to diagnose a JetPack 6 USB enumeration failure?
With pattern recognition, 4 hours. Working through it fresh — reading the L4T documentation, bisecting the device tree, cross-referencing the kernel changelog — it’s 2-4 weeks. We found UncommonLab’s root cause in 4 hours because we’d diagnosed the same JetPack 6 USB failure on prior carrier boards and knew exactly where to look.
What kernel version does JetPack 6 use?
JetPack 6 uses L4T R36 with Linux kernel 5.15 — a significant jump from JetPack 5’s L4T R35 (kernel 5.10). The USB subsystem in 5.15 deprecated several device tree properties and changed PHY node binding conventions. Device trees written for 5.10 won’t work correctly in R36 without explicit updates.
Is JetPack 6 USB debugging different on Jetson Orin vs Jetson AGX?
The root causes are the same — L4T R36 USB subsystem changes apply across Orin modules — but the specific device tree paths and PHY configuration differ between Orin NX, Orin Nano, and AGX Orin. A fix for one module’s carrier board won’t transfer directly to another without verifying the module-specific PHY bindings in the R36 BSP.
Blocked on a USB enumeration failure after upgrading to JetPack 6? Book a scoping call — we’ll tell you whether it’s the four issues above and what it takes to fix it.