jetson-customize-pcie
Per-controller PCIe enable / disable / lanes / link-speed for a Jetson Thor or Orin custom carrier via ODMDATA + kernel-DT overlay. Do NOT use for UPHY lane allocation or endpoint-mode bring-up.
Skill body
Customize PCIe (per-controller status / lanes / speed)
Overview
PCIe on Tegra264 (Thor, pcie@C0..C5) and Tegra234 (Orin,
pcie@C0..C10) is split across multiple controllers that share the
UPHY lane pool with USB3 / MGBE / UFS. Each controller’s runtime
behavior is determined by two surfaces, both required:
| Surface | Target | Authoritative for |
|---|---|---|
ODMDATA pcie@N_status=… (+ pcie@N_max-link-speed, pcie@N_pcie-mode, pcie@N_clk-scheme, pcie-cN-endpoint-enable) |
/pcie/pcie@N in BPMP DTB |
UPHY lane power, refclk gating, controller-side power rails |
Kernel-DT overlay on &pcieN |
/bus@0/pcie@<addr> in kernel DTB |
Kernel probe, lane width, link speed, RC/EP mode |
Skipping the kernel overlay on a disable lets the kernel probe a powered-down PHY (link timeouts in dmesg). Skipping the ODMDATA token on a disable leaves BPMP holding the PHY hot.
Agentic, not table-driven — no controller table, no
questions.json. Every controller, lane width, schematic-routed
receptacle, and authoritative DT node address is discovered at runtime
from the docs + DTB + carrier pinmap.
The output is a kernel-DT overlay commit only. Per-controller
fragment@N blocks are appended to the composite custom overlay
.dts per
../../references/bsp-customization-kernel-dtb.md
and committed to the bsp_sources/ hardware repo.
/jetson-build-source compiles the composite to .dtbo and owns its
Makefile + flash-conf registration.
This skill MUST NOT edit ODMDATA="...". All ODMDATA tokens
(pcie@N_status=…, pcie@N_max-link-speed, pcie@N_pcie-mode,
pcie@N_clk-scheme, pcie-cN-endpoint-enable, plus the
uphyX-config-N surface tokens and UPHY_CONFIG="" clear) are
emitted by /jetson-customize-uphy in a single atomic commit on the
carrier flash-conf fork. The allocation table this skill consumes
from the UPHY sidecar already tells the operator which controllers
are okay / disabled / per-lane sized; this skill only translates
that table into kernel-DT overlay fragments and verifies that the
overlay agrees with the ODMDATA already committed by customize-uphy
(consistency check in Step 8 — disagreement is reported, not silently
fixed).
When to invoke
- The user says “configure PCIe”, “enable PCIe controller”, “set PCIe
num-lanes”, “change PCIe link speed”, or asks to flip a
pcie@N_statustoken. - A specific PCIe slot or M.2 receptacle doesn’t enumerate after flash, OR the link trains at the wrong width / speed.
jetson-customize-uphyran and re-allocated lanes across PCIe controllers (e.g. switched fromuphy0-config-7touphy0-config-6enabling PCIe C3); the per-controller side now needs to be brought up.jetson-customize-mgbereports the QSFP path is wired but the kernel doesn’t probe its PCIe-side companion (rare; XFI configurations).
Prerequisites:
- Active profile with
reference_devkit:+custom_carrier:blocks. <source.root_path>/Linux_for_Tegra/.gitexists (/jetson-init-source)./jetson-derive-carrierhas run — carrier flash-conf fork is in the overlay tracker./jetson-customize-uphyhas run — its JSON sidecar at<workspace>/target-platform/<profile-stem>.jetson-customize-uphy.jsondrives the per-controllerenabledecision.- Source-of-truth docs registered or supplied at prompt: Adaptation Guide, Module Design Guide, SoC TRM.
- When
custom_carrier:is present, bothdocuments.custom_carrier_schematicANDdocuments.custom_carrier_pinmux_xlsare REQUIRED. Refuse the run if either is missing — routing on a custom carrier cannot be guessed. Reference-devkit-only profiles skip this check. dtcon PATH.
Procedure (summary)
Full step-by-step walkthrough lives in
references/procedure.md. High-level flow:
- Resolve active target + open source-of-truth documents (incl.
<carrier-pinmap>,<ref-dtb>,<uphy-state>). Refuse if<uphy-state>is missing. - Diff PCIe topology — devkit vs custom carrier — by decompiling
<ref-dtb>and grepping the schematic forPEX<N>_*net labels. AskUserQuestion(multiSelect) — which controllers to customize.- Per-controller verification: pinmap + schematic +
pin_verifier.pyforPE<N>_CLKREQ_L,PE<N>_RST_L, optionalPE<N>_WAKE_L. - Auto-derive per-controller plan (
enablefrom<uphy-state>,lanes/speedfrom Adaptation Guide,modehard-pinned to"rc") → mandatory confirm-or-customize gate. - Append per-controller
fragment@Nblocks (marker/* custom-bsp: pcie:pcie@<addr> */) to the composite custom overlay.dtsinbsp_sources/. Pre-flightdtc+fdtoverlay. Commit via the workflow’s preview gate. Do not editODMDATA—/jetson-customize-uphyalready emittedpcie@N_status=…,pcie@N_max-link-speed,pcie@N_pcie-mode,pcie@N_clk-scheme, andpcie-cN-endpoint-enablein its single atomic ODMDATA commit. This skill only translates the per-controller plan into kernel-DT overlay fragments. - (Step folded into Step 6 — overlay-only emission.)
- Cross-check ODMDATA vs overlay consistency. On a contradictory
row, stop and ask the user how to recover the two commits.
Never run
git reset --hardautonomously. - Write run-state JSON sidecar at
<workspace>/target-platform/<profile-stem>.jetson-customize-pcie.json- summary, then drive the downstream next-step chain via sequential
AskUserQuestionprompts perreferences/procedure.mdStep 9. Never substitute a printed “Next step: …” line for the prompts.
- summary, then drive the downstream next-step chain via sequential
Limitations
- Mode hard-pinned to RC. Endpoint mode is only emitted when the
operator passes
mode_override="ep"in Step 5c. enableis derived, not asked. UPHY-allocated controllers are mandatorilyokay; non-allocated are mandatorilydisabled.- No upstream BSP edits. Output lands in
Linux_for_Tegra/+bsp_sources/only. - Pre-flight overlay merge is a sanity check, not the production
build.
/jetson-build-sourceis authoritative. - Flash-conf overlay registration is out of scope. Owned by
/jetson-build-sourceStep 5.0a.
Troubleshooting
<uphy-state>missing → run/jetson-customize-uphyfirst.- Slot doesn’t enumerate after flash → check
dmesg | grep pcie; re-verify ODMDATApcie@<N>_status=okayand the overlay fragment agree (Step 8 table inreferences/procedure.md). - Link trains at wrong width → confirm UPHY config in
<uphy-state>allocates the expected lane count; the kernel fragment’snum-lanesmust match. compatiblemismatch → fix the composite root, not the fragment. UEFI plugin-manager silently skips on mismatch.- Contradictory ODMDATA-vs-overlay row → ask the user; do not
auto-
git reset --hard. See gotchas. - Common pitfalls — see
references/gotchas.md(RC pinning, node- address sourcing, stock-disabled controllers, intra-file handoff withjetson-customize-uphy).
References
references/procedure.md— full nine- step procedure (topology diff, plan derivation, overlay append, ODMDATA cross-check, sidecar).references/gotchas.md— failure modes- invariants (RC pinning, address sourcing, BPMP handoff).
../../scripts/pin_verifier.py— shared HSIO pin verifier (Step 4).../../references/platform_template.yaml—documents:block consumed by Step 1.../../context/bsp-customization-workflow.md— overlay edit protocol + commit message preview gate.../../references/bsp-customization-kernel-dtb.md— composite overlay filename / skeleton / append protocol.../jetson-customize-uphy/SKILL.md— sibling skill that owns UPHY lane allocation; its sidecar drives the per-controllerenabledecision.../jetson-customize-pinmux/SKILL.md— sibling skill invoked by Step 4 (with operator confirmation) to fix HSIO pin SFIO mismatches.../jetson-customize-mgbe/SKILL.md— sibling for MGBE controllers; shares the two-surface (ODMDATA- overlay) pattern.
../jetson-derive-carrier/SKILL.md— must run first; produces the carrier flash-conf fork edited in Step 6.../jetson-init-source/SKILL.md— produces the overlay tracker + bsp_sources repo this skill commits into.