jetson-customize-pcie — Claude Code skill for Jetson PCIe setup
Configures individual PCIe controllers on a Jetson Thor or Orin custom carrier: enable, lane count, link speed. Changes land in a kernel-DT overlay.
npx skills add NVIDIA/skills --skill jetson-customize-pcie -a claude-codeWhat jetson-customize-pcie does
The skill works out which PCIe controllers exist on your board and appends fragment@N blocks to the composite overlay .dts in bsp_sources/. Before that it checks the pinmap and schematic, running pin_verifier.py against PE<N>_CLKREQ_L, PE<N>_RST_L and the optional PE<N>_WAKE_L. Lane width and speed come from the Adaptation Guide; the enable/disable decision comes from the JSON sidecar left by /jetson-customize-uphy.
ODMDATA stays untouched. Every token — pcie@N_status, pcie@N_max-link-speed, pcie@N_pcie-mode, pcie@N_clk-scheme, pcie-cN-endpoint-enable — was already emitted by /jetson-customize-uphy in one atomic commit. This skill translates the lane allocation table into overlay fragments and checks that the overlay agrees with that ODMDATA. On a contradictory row it stops and asks how to recover the two commits. It never runs git reset --hard on its own.
What you need in place: an active profile with reference_devkit: and custom_carrier: blocks, <source.root_path>/Linux_for_Tegra/.git, prior runs of /jetson-derive-carrier and /jetson-customize-uphy, and dtc on PATH. With a custom carrier both the schematic and the pinmux XLS are required — the skill refuses to run if either is missing, since routing cannot be guessed. Mode is hard-pinned to RC; endpoint mode only appears when the operator passes mode_override="ep".
What it helps with
- enable a specific PCIe controller on a Jetson custom carrier
- set lane count and link speed for one slot or M.2 receptacle
- debug a slot that does not enumerate after flashing
- turn the lane allocation table from
/jetson-customize-uphyinto kernel-DT overlay fragments - cross-check the overlay against the committed
ODMDATAand catch a mismatch
Example prompts for the agent
- configure PCIe on my custom carrier, enable controller C3
- set num-lanes and link speed for the M.2 slot
- the slot is missing after flash — check the overlay against ODMDATA
How to install jetson-customize-pcie
1Skills CLI (Vercel)
npx skills add NVIDIA/skills --skill jetson-customize-pcie -a claude-code2Manually: put the files in place
~/.claude/skills/jetson-customize-pcie/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/jetson-customize-pcie/
1Skills CLI (Vercel)
npx skills add NVIDIA/skills --skill jetson-customize-pcie -a codex2Manually: put the files in place
.agents/skills/jetson-customize-pcie/SKILL.mdFor all projects use ~/.agents/skills/
1Skills CLI (Vercel)
npx skills add NVIDIA/skills --skill jetson-customize-pcie -a cursor2Manually: put the files in place
.cursor/skills/jetson-customize-pcie/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
1GitHub CLI
gh skill install NVIDIA/skills jetson-customize-pcie2Manually: put the files in place
.github/skills/jetson-customize-pcie/SKILL.md1Skills CLI (Vercel)
npx skills add NVIDIA/skills --skill jetson-customize-pcie -a gemini-cli2Platform CLI
gemini skills install https://github.com/NVIDIA/skills --path skills/jetson-customize-pcieManually: put the files in place
.devin/skills/jetson-customize-pcie/SKILL.mdThe legacy .windsurf/skills/ path still works
Skills CLI (Vercel)
npx skills add NVIDIA/skills --skill jetson-customize-pcie -a opencodeClaude.ai
Zip the folder and upload it in Settings → Capabilities → Skills
Step by step, with commands for each platform: How to install skills in Claude Code: five ways
Questions about jetson-customize-pcie
How do I install jetson-customize-pcie in Claude?
Run npx skills add NVIDIA/skills --skill jetson-customize-pcie -a claude-code. The skill lands at ~/.claude/skills/jetson-customize-pcie/SKILL.md.
What does jetson-customize-pcie do?
It builds kernel-DT overlay fragments for individual PCIe controllers on a Jetson Thor or Orin custom carrier: enable, lane count, link speed. It does not edit ODMDATA.
What has to be in place before it runs?
A profile with reference_devkit: and custom_carrier: blocks, a ready Linux_for_Tegra/.git, prior runs of /jetson-derive-carrier and /jetson-customize-uphy, and dtc on PATH. A custom carrier also needs its schematic and pinmux XLS.
Source text
SKILL.md · Apache-2.0
---
name: jetson-customize-pcie
description: >-
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.
version: 0.0.1
license: "Apache-2.0"
metadata:
data-classification: public
author: "Jetson Team"
tags:
- bsp
- phase-2
- io
- pcie
domain: meta
---
# Customize PCIe (per-controller status / lanes / speed)
## Overview
PCIe on Tegra264 (Thor, `[email protected]`) and Tegra234 (Orin,
`[email protected]`) 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`](../../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_status` token.
- A specific PCIe slot or M.2 receptacle doesn't enumerate after
flash, OR the link trains at the wrong width / speed.
- `jetson-customize-uphy` ran and re-allocated lanes across PCIe controllers
(e.g. switched from `uphy0-config-7` to `uphy0-config-6` enabling
PCIe C3); the per-controller side now needs to be brought up.
- `jetson-customize-mgbe` reports 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/.git` exists
(`/jetson-init-source`).
- `/jetson-derive-carrier` has run — carrier flash-conf fork is in
the overlay tracker.
- `/jetson-customize-uphy` has run — its JSON sidecar at
`<workspace>/target-platform/<profile-stem>.jetson-customize-uphy.json`
drives the per-controller `enable` decision.
- Source-of-truth docs registered or supplied at prompt: Adaptation
Guide, Module Design Guide, SoC TRM.
- **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 — routing on a custom carrier cannot be guessed.
Reference-devkit-only profiles skip this check.
- `dtc` on PATH.
## Procedure (summary)
Full step-by-step walkthrough lives in
[`references/procedure.md`](references/procedure.md). High-level flow:
1. Resolve active target + open source-of-truth documents (incl.
`<carrier-pinmap>`, `<ref-dtb>`, `<uphy-state>`). Refuse if
`<uphy-state>` is missing.
2. Diff PCIe topology — devkit vs custom carrier — by decompiling
`<ref-dtb>` and grepping the schematic for `PEX<N>_*` net labels.
3. `AskUserQuestion` (multiSelect) — which controllers to customize.
4. Per-controller verification: pinmap + schematic + `pin_verifier.py`
for `PE<N>_CLKREQ_L`, `PE<N>_RST_L`, optional `PE<N>_WAKE_L`.
5. Auto-derive per-controller plan (`enable` from `<uphy-state>`,
`lanes` / `speed` from Adaptation Guide, `mode` hard-pinned to
`"rc"`) → mandatory confirm-or-customize gate.
6. Append per-controller `fragment@N` blocks (marker
`/* custom-bsp: pcie:pcie@<addr> */`) to the composite custom
overlay `.dts` in `bsp_sources/`. Pre-flight `dtc` + `fdtoverlay`.
Commit via the workflow's preview gate.
**Do not edit `ODMDATA`** — `/jetson-customize-uphy` already emitted
`pcie@N_status=…`, `pcie@N_max-link-speed`, `pcie@N_pcie-mode`,
`pcie@N_clk-scheme`, and `pcie-cN-endpoint-enable` in its single
atomic ODMDATA commit. This skill only translates the per-controller
plan into kernel-DT overlay fragments.
7. (Step folded into Step 6 — overlay-only emission.)
8. 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 --hard` autonomously.**
9. 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
`AskUserQuestion` prompts per `references/procedure.md` Step 9.
Never substitute a printed "Next step: …" line for the prompts.
## Limitations
- **Mode hard-pinned to RC.** Endpoint mode is only emitted when the
operator passes `mode_override="ep"` in Step 5c.
- **`enable` is derived, not asked.** UPHY-allocated controllers are
mandatorily `okay`; non-allocated are mandatorily `disabled`.
- **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-source` is authoritative.
- **Flash-conf overlay registration is out of scope.** Owned by
`/jetson-build-source` Step 5.0a.
## Troubleshooting
- **`<uphy-state>` missing** → run `/jetson-customize-uphy` first.
- **Slot doesn't enumerate after flash** → check `dmesg | grep pcie`;
re-verify ODMDATA `pcie@<N>_status=okay` and the overlay fragment
agree (Step 8 table in
[`references/procedure.md`](references/procedure.md)).
- **Link trains at wrong width** → confirm UPHY config in
`<uphy-state>` allocates the expected lane count; the kernel
fragment's `num-lanes` must match.
- **`compatible` mismatch** → 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`](references/gotchas.md) (RC pinning, node-
address sourcing, stock-disabled controllers, intra-file handoff
with `jetson-customize-uphy`).
## References
- [`references/procedure.md`](references/procedure.md) — full nine-
step procedure (topology diff, plan derivation, overlay append,
ODMDATA cross-check, sidecar).
- [`references/gotchas.md`](references/gotchas.md) — failure modes
+ invariants (RC pinning, address sourcing, BPMP handoff).
- [`../../scripts/pin_verifier.py`](../../scripts/pin_verifier.py)
— shared HSIO pin verifier (Step 4).
- [`../../references/platform_template.yaml`](../../references/platform_template.yaml)
— `documents:` block consumed by Step 1.
- [`../../context/bsp-customization-workflow.md`](../../context/bsp-customization-workflow.md#workflow-invariants)
— overlay edit protocol + commit message preview gate.
- [`../../references/bsp-customization-kernel-dtb.md`](../../references/bsp-customization-kernel-dtb.md)
— composite overlay filename / skeleton / append protocol.
- [`../jetson-customize-uphy/SKILL.md`](../jetson-customize-uphy/SKILL.md)
— sibling skill that owns UPHY lane allocation; its sidecar drives
the per-controller `enable` decision.
- [`../jetson-customize-pinmux/SKILL.md`](../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`](../jetson-customize-mgbe/SKILL.md)
— sibling for MGBE controllers; shares the two-surface (ODMDATA
+ overlay) pattern.
- [`../jetson-derive-carrier/SKILL.md`](../jetson-derive-carrier/SKILL.md)
— must run first; produces the carrier flash-conf fork edited in
Step 6.
- [`../jetson-init-source/SKILL.md`](../jetson-init-source/SKILL.md)
— produces the overlay tracker + bsp_sources repo this skill
commits into.
© Jetson Team · Apache-2.0 · NVIDIA/skills