Customize USB (per-port enable / disable / role)
Purpose
Enable, disable, or change the role of USB2 / USB3 SS ports on a
Jetson Thor (Tegra264) or Orin (Tegra234) custom carrier. Captures
per-port wiring (role, max speed, VBUS-EN / OC GPIOs, CC1/CC2 GPIOs
for Type-C, USB3 SS UPHY lane), resolves the SS to USB2 companion
graph from the in-tree DTB, then renders a self-contained kernel-DT
overlay that flips every port action in three places in lockstep
(lane status, port status, host xHCI phys + phy-names).
UPHY lane allocation belongs to jetson-customize-uphy. No ODMDATA
edit. Output is one commit to the composite custom overlay .dts in
the bsp_sources/ hardware repo.
Prerequisites
- Active profile with
reference_devkit: + custom_carrier: blocks.
<source.root_path>/Linux_for_Tegra/.git exists
(/jetson-init-source).
/jetson-derive-carrier has run — carrier flash-conf fork in the
overlay tracker.
/jetson-customize-uphy has run when any enabled USB3 SS port
needs a non-stock UPHY lane allocation. Its JSON sidecar at
<workspace>/target-platform/<profile-stem>.jetson-customize-uphy.json
is consulted for SS lane allocation.
- Source-of-truth docs: Adaptation Guide §"Port the Universal Serial
Bus", Module Design Guide §USB, SoC TRM (xusb block).
- When
custom_carrier: is present, both
documents.custom_carrier_schematic AND
documents.custom_carrier_pinmux_xls are REQUIRED. Refuse the run
if either is missing — per-port routing (VBUS-EN / OC / CC GPIOs, SS
lane wiring, hub fan-out) on a custom carrier cannot be guessed.
Reference-devkit-only profiles skip this check.
dtc, fdtoverlay on PATH.
Overview
USB on Tegra spans three IP surfaces: the xusb_padctl block (USB2
OTG + USB3 SS PHYs), the tegra-xusb xHCI host controller, and an
optional tegra-xudc device controller attached to the single
OTG-capable USB2 port (usb2-0).
A per-port flip MUST touch three kernel-DT places in lockstep.
Anything less crashes the host xHCI probe and leaves lsusb empty
on every port (collateral damage to stock-okay ports):
| # |
Place |
Path |
What it controls |
| 1 |
Lane (PHY provider) |
xusb_padctl/pads/usb<2|3>/lanes/usb<2|3>-N |
SS / OTG PHY hardware-binding. status="disabled" then lane stops providing a PHY. |
| 2 |
Port (controller-binding) |
xusb_padctl/ports/usb<2|3>-N |
Per-port mode (host/device/otg), companion link, VBUS / OC / CC pin refs. status="disabled" then port removed from user-facing topology. |
| 3 |
Host xHCI phys-list |
bus@0/usb@<addr>.phys + .phy-names |
Array of phandles + names the xHCI driver iterates. A ref to a disabled PHY returns -ENODEV and aborts the whole host probe. |
NVIDIA's stock-disabled usb3-3 in the Thor base DTB is the canonical
pattern — all three places flipped in lockstep.
Two extra rules ride on top of the three-place pattern:
- Rule A — lane + port pairing. Lane (place 1) and matching port
(place 2) MUST flip together.
- Rule B — companion cascade.
xusb_padctl/ports/usb3-N.nvidia,usb2-companion references a USB2
port phandle. Disabling that USB2 without cascading to its SS
companion then tegra-xusb: failed to enable PHYs: -19.
Agentic, not table-driven — every port, controller, lane,
companion link, phandle, and __symbols__ lookup is resolved at
runtime from docs + DTB + carrier pinmap + schematic.
When to invoke
- The user says "enable USB", "disable USB hub", "configure USB3 SS",
"set USB role", "wire VBUS-EN", "tegra-xusb / xudc / dr_mode", or
asks to bring up / take down a USB controller on a custom carrier.
- A USB receptacle on the carrier doesn't enumerate after flash, OR
collateral USB damage (
lsusb empty after a previous
jetson-customize-usb attempt) needs to be fixed.
jetson-customize-uphy re-allocated UPHY lanes affecting USB3 SS
ports and per-port DT now needs to follow.
Procedure (summary)
The full step-by-step procedure lives in references/procedure.md.
- Step 1 — resolve active target + open source-of-truth docs.
- Step 2 — build the USB topology + companion graph from the
in-tree DTB.
- Step 3 —
AskUserQuestion for port(s) to enable / disable;
surface companion cascade + on-carrier hub fan-out explicitly.
- Step 4 — per-port verify (module + carrier + UPHY lane) and
capture wiring (VBUS-EN / OC / CC GPIOs via
pin_verifier.py).
- Step 5 — render the kernel-DT overlay using the three-place
pattern, append fragments (
usb:padctl, usb:xhci, optional
usb:xudc) to the composite custom overlay .dts, run
fdtoverlay + the three post-merge invariants, commit to
bsp_sources/.
- Step 6 — write run-state JSON sidecar (shape in
references/run-state-sidecar.md), emit headline, then drive the
downstream next-step chain via sequential AskUserQuestion prompts
per references/procedure.md Step 6. Never substitute a printed
"Next step: …" line for the prompts.
See references/gotchas.md for the load-bearing failure modes.
Limitations
- Owns kernel-DT overlay only. ODMDATA does not expose a per-port
USB
status knob; do not edit it.
- Does NOT allocate UPHY lanes —
jetson-customize-uphy owns that.
Refuse to commit an SS-enable until uphy run-state shows the lane
allocated.
- Does NOT directly patch the pinmux DTSI — routes SFIO mismatches
to
/jetson-customize-pinmux set-pin.
- Does NOT compile the
.dtbo or register OVERLAY_DTB_FILE+= —
/jetson-build-source owns build + flash-conf registration.
- Tegra platform invariant: only
usb2-0 is OTG-capable; xudc
attaches there only. All other USB2 ports and all USB3 SS ports
are host-only.
Troubleshooting
- Empty
lsusb on every port, USB-eth at 192.168.55.1 still up:
host xHCI bailed; three-place lockstep was broken. Inspect merged
DTB; verify post-merge invariants in references/procedure.md
Step 5d.
tegra-xusb: failed to enable PHYs: -19: companion cascade
(Rule B) violated — a USB2 was disabled without its SS companion.
no port found or Requested PHY is disabled: Rule A
violated — lane status and port status are mismatched.
FDT_ERR_NOTFOUND from fdtoverlay: a fragment used
target = <&label> for a node whose label is not in
__symbols__ (typical for host xHCI / tegra-xudc). Switch to
target-path = "/bus@0/usb@<addr>".
- dtc warning
phys_property: cell 0 is not a phandle reference:
benign; expected when using raw integer phandles in the host phys
override.
- Port boots but VBUS never asserts:
vbus-supply references a
regulator parent node that does not exist. Ensure the fixed
regulator node is present before referencing it.
- xHCI binds the wrong port at boot: host
phys element order
was not preserved. Only elide disabled entries; never reorder
kept ones.
References
references/procedure.md — full step-by-step procedure.
references/gotchas.md — load-bearing failure modes.
references/run-state-sidecar.md — run-state JSON shape.
references/usb-architecture.md — Tegra USB IP architecture
notes (xusb_padctl, tegra-xusb, xudc).
references/usb-dt-bindings.md — USB DT binding cheatsheet
(lane / port / phys-list shapes).
../../scripts/pin_verifier.py — shared HSIO pin verifier.
../../references/platform_template.yaml — documents: block
consumed by Step 1.
../../context/bsp-customization-workflow.md — overlay edit
protocol.
../../references/bsp-customization-kernel-dtb.md — composite
overlay append protocol.
../jetson-customize-uphy/SKILL.md — sibling skill that owns
UPHY lane allocation.
../jetson-customize-pinmux/SKILL.md — sibling skill for
VBUS-EN / OC / CC SFIO fixes.
../jetson-derive-carrier/SKILL.md — must run first.
../jetson-init-source/SKILL.md — produces the overlay tracker
1---2name: jetson-customize-usb3description: Enable, disable, or change the role of USB2/USB3 SS ports on Jetson custom carriers by generating kernel-DT overlays that flip lane, port, and host xHCI phys in lockstep.4license: Apache-2.05---67# Customize USB (per-port enable / disable / role)89## Purpose1011Enable, disable, or change the role of USB2 / USB3 SS ports on a12Jetson Thor (Tegra264) or Orin (Tegra234) custom carrier. Captures13per-port wiring (role, max speed, VBUS-EN / OC GPIOs, CC1/CC2 GPIOs14for Type-C, USB3 SS UPHY lane), resolves the SS to USB2 companion15graph from the in-tree DTB, then renders a self-contained kernel-DT16overlay that flips every port action in three places in lockstep17(lane status, port status, host xHCI `phys` + `phy-names`).1819UPHY lane allocation belongs to `jetson-customize-uphy`. No ODMDATA20edit. Output is one commit to the composite custom overlay `.dts` in21the `bsp_sources/` hardware repo.2223## Prerequisites2425- Active profile with `reference_devkit:` + `custom_carrier:` blocks.26- `<source.root_path>/Linux_for_Tegra/.git` exists27 (`/jetson-init-source`).28- `/jetson-derive-carrier` has run — carrier flash-conf fork in the29 overlay tracker.30- `/jetson-customize-uphy` has run when any enabled USB3 SS port31 needs a non-stock UPHY lane allocation. Its JSON sidecar at32 `<workspace>/target-platform/<profile-stem>.jetson-customize-uphy.json`33 is consulted for SS lane allocation.34- Source-of-truth docs: Adaptation Guide §"Port the Universal Serial35 Bus", Module Design Guide §USB, SoC TRM (xusb block).36- **When `custom_carrier:` is present, both37 `documents.custom_carrier_schematic` AND38 `documents.custom_carrier_pinmux_xls` are REQUIRED.** Refuse the run39 if either is missing — per-port routing (VBUS-EN / OC / CC GPIOs, SS40 lane wiring, hub fan-out) on a custom carrier cannot be guessed.41 Reference-devkit-only profiles skip this check.42- `dtc`, `fdtoverlay` on PATH.4344## Overview4546USB on Tegra spans three IP surfaces: the `xusb_padctl` block (USB247OTG + USB3 SS PHYs), the `tegra-xusb` xHCI host controller, and an48optional `tegra-xudc` device controller attached to the single49OTG-capable USB2 port (`usb2-0`).5051**A per-port flip MUST touch three kernel-DT places in lockstep.**52Anything less crashes the host xHCI probe and leaves `lsusb` empty53on every port (collateral damage to stock-okay ports):5455| # | Place | Path | What it controls |56|---|---|---|---|57| 1 | **Lane (PHY provider)** | `xusb_padctl/pads/usb<2\|3>/lanes/usb<2\|3>-N` | SS / OTG PHY hardware-binding. `status="disabled"` then lane stops providing a PHY. |58| 2 | **Port (controller-binding)** | `xusb_padctl/ports/usb<2\|3>-N` | Per-port mode (host/device/otg), companion link, VBUS / OC / CC pin refs. `status="disabled"` then port removed from user-facing topology. |59| 3 | **Host xHCI phys-list** | `bus@0/usb@<addr>.phys` + `.phy-names` | Array of phandles + names the xHCI driver iterates. A ref to a disabled PHY returns `-ENODEV` and aborts the whole host probe. |6061NVIDIA's stock-disabled `usb3-3` in the Thor base DTB is the canonical62pattern — all three places flipped in lockstep.6364**Two extra rules ride on top of the three-place pattern:**6566- **Rule A — lane + port pairing.** Lane (place 1) and matching port67 (place 2) MUST flip together.68- **Rule B — companion cascade.**69 `xusb_padctl/ports/usb3-N.nvidia,usb2-companion` references a USB270 port phandle. Disabling that USB2 without cascading to its SS71 companion then `tegra-xusb: failed to enable PHYs: -19`.7273**Agentic, not table-driven** — every port, controller, lane,74companion link, phandle, and `__symbols__` lookup is resolved at75runtime from docs + DTB + carrier pinmap + schematic.7677## When to invoke7879- The user says "enable USB", "disable USB hub", "configure USB3 SS",80 "set USB role", "wire VBUS-EN", "tegra-xusb / xudc / dr_mode", or81 asks to bring up / take down a USB controller on a custom carrier.82- A USB receptacle on the carrier doesn't enumerate after flash, OR83 collateral USB damage (`lsusb` empty after a previous84 jetson-customize-usb attempt) needs to be fixed.85- `jetson-customize-uphy` re-allocated UPHY lanes affecting USB3 SS86 ports and per-port DT now needs to follow.8788## Procedure (summary)8990The full step-by-step procedure lives in `references/procedure.md`.91921. **Step 1** — resolve active target + open source-of-truth docs.932. **Step 2** — build the USB topology + companion graph from the94 in-tree DTB.953. **Step 3** — `AskUserQuestion` for port(s) to enable / disable;96 surface companion cascade + on-carrier hub fan-out explicitly.974. **Step 4** — per-port verify (module + carrier + UPHY lane) and98 capture wiring (VBUS-EN / OC / CC GPIOs via `pin_verifier.py`).995. **Step 5** — render the kernel-DT overlay using the three-place100 pattern, append fragments (`usb:padctl`, `usb:xhci`, optional101 `usb:xudc`) to the composite custom overlay `.dts`, run102 `fdtoverlay` + the three post-merge invariants, commit to103 `bsp_sources/`.1046. **Step 6** — write run-state JSON sidecar (shape in105 `references/run-state-sidecar.md`), emit headline, then drive the106 downstream next-step chain via sequential `AskUserQuestion` prompts107 per `references/procedure.md` Step 6. Never substitute a printed108 "Next step: …" line for the prompts.109110See `references/gotchas.md` for the load-bearing failure modes.111112## Limitations113114- Owns kernel-DT overlay only. ODMDATA does not expose a per-port115 USB `status` knob; do not edit it.116- Does NOT allocate UPHY lanes — `jetson-customize-uphy` owns that.117 Refuse to commit an SS-enable until uphy run-state shows the lane118 allocated.119- Does NOT directly patch the pinmux DTSI — routes SFIO mismatches120 to `/jetson-customize-pinmux set-pin`.121- Does NOT compile the `.dtbo` or register `OVERLAY_DTB_FILE+=` —122 `/jetson-build-source` owns build + flash-conf registration.123- Tegra platform invariant: only `usb2-0` is OTG-capable; `xudc`124 attaches there only. All other USB2 ports and all USB3 SS ports125 are host-only.126127## Troubleshooting128129- **Empty `lsusb` on every port, USB-eth at 192.168.55.1 still up:**130 host xHCI bailed; three-place lockstep was broken. Inspect merged131 DTB; verify post-merge invariants in `references/procedure.md`132 Step 5d.133- **`tegra-xusb: failed to enable PHYs: -19`:** companion cascade134 (Rule B) violated — a USB2 was disabled without its SS companion.135- **`no port found` or `Requested PHY is disabled`:** Rule A136 violated — lane status and port status are mismatched.137- **`FDT_ERR_NOTFOUND` from `fdtoverlay`:** a fragment used138 `target = <&label>` for a node whose label is not in139 `__symbols__` (typical for host xHCI / `tegra-xudc`). Switch to140 `target-path = "/bus@0/usb@<addr>"`.141- **dtc warning `phys_property: cell 0 is not a phandle reference`:**142 benign; expected when using raw integer phandles in the host phys143 override.144- **Port boots but VBUS never asserts:** `vbus-supply` references a145 regulator parent node that does not exist. Ensure the fixed146 regulator node is present before referencing it.147- **xHCI binds the wrong port at boot:** host `phys` element order148 was not preserved. Only elide disabled entries; never reorder149 kept ones.150151## References152153- `references/procedure.md` — full step-by-step procedure.154- `references/gotchas.md` — load-bearing failure modes.155- `references/run-state-sidecar.md` — run-state JSON shape.156- `references/usb-architecture.md` — Tegra USB IP architecture157 notes (`xusb_padctl`, `tegra-xusb`, `xudc`).158- `references/usb-dt-bindings.md` — USB DT binding cheatsheet159 (lane / port / phys-list shapes).160- `../../scripts/pin_verifier.py` — shared HSIO pin verifier.161- `../../references/platform_template.yaml` — `documents:` block162 consumed by Step 1.163- `../../context/bsp-customization-workflow.md` — overlay edit164 protocol.165- `../../references/bsp-customization-kernel-dtb.md` — composite166 overlay append protocol.167- `../jetson-customize-uphy/SKILL.md` — sibling skill that owns168 UPHY lane allocation.169- `../jetson-customize-pinmux/SKILL.md` — sibling skill for170 VBUS-EN / OC / CC SFIO fixes.171- `../jetson-derive-carrier/SKILL.md` — must run first.172- `../jetson-init-source/SKILL.md` — produces the overlay tracker173 + `bsp_sources` repo.