Customize Clocks
Purpose
Customize CPU, GPU, and EMC clock behavior on a Jetson target by editing files under
before flashing the image. Two layers are in scope:
- The BPMP DTB at
Linux_for_Tegra/bootloader/<BPFDTB_FILE>
— per-clock ceilings, plus the EMC DVFS gate (bwmgr + cactmon on all SoCs; osp-controller on T26x only).
- nvpower.sh at
Linux_for_Tegra/rootfs/etc/systemd/nvpower.sh
— cpufreq / devfreq governors and (optionally) per-device min / max / static rates written to sysfs at boot.
Common triggers: "lock CPU/GPU/EMC frequency", "pin GPU to Fmax", "pin EMC to MAXN", "disable/enable EMC DVFS", "disable/enable CPU DVFS", "set CPU/GPU max rate", "change cpufreq governor".
Out of scope: runtime clock tuning on a live target (no flash step), nvpmodel power-mode edits (use the sibling skill
/jetson-customize-nvpmodel
), and silicon-ceiling overrides (
is read-only).
Prerequisites
Resolve the active profile per
../../context/target-platform-contract.md
.
Refuse and route in these cases:
| Condition | Refuse with |
|---|
| No active profile, or | Route to or . |
| Profile lacks block | Route to . |
<bsp_image.root_path>/Linux_for_Tegra/
missing | Route to . |
<source.root_path>/Linux_for_Tegra/
missing or not a git repo | Route to . |
Resolve paths:
- from if present, else .
- from if present, else .
is
read-only for this skill; every write
(Operation 1's BPMP DTB and Operation 2's
) lands under
(the overlay tracker). This is the workflow
invariant in
../../context/bsp-customization-workflow.md#workflow-invariants
—
hand-editing upstream silently destroys the diff trail and makes
a noop.
Instructions
- Resolve the prerequisites above (active profile, BSP image extracted, source overlay tracker initialized).
- Pick the operation from the table below.
- Follow the linked procedure section — Operation 1 (BPMP DTB), Operation 2 (), or the MAXN recipe for both.
- Commit the edit inside the overlay tracker per each Operation's commit convention.
- Deploy with → . The new BPMP DTB and take effect on the next boot.
Supported operations
| Operation | Where the edit lives | Procedure section |
|---|
| Lock a CPU / GPU clock to a specific rate | BPMP DTB on the clock node + governor | "Content edit: " + "Pick the edit" |
| Lock EMC at its init rate (disable EMC DVFS) | BPMP DTB: , , plus /delete-node/ osp-controller
on T26x only | "Content edit: EMC DVFS disable / enable" |
| Re-enable EMC DVFS | BPMP DTB: , , restore on T26x | "Content edit: EMC DVFS disable / enable" |
| Pin everything to MAXN for stress runs | Combine the above + nvpmodel MAXN as boot default | see Recipe |
| Lower a clock's hard ceiling without locking | BPMP DTB only | "Content edit: " |
| Bound a device's rate without pinning | min/max via sysfs | "Pick the edit" |
Operation 1 — BPMP DTB edits
Follow the BPMP-DTB customization protocol in
../../references/bsp-customization-bpmp-dtb.md
.
The protocol owns the mechanics — pristine import on first touch,
decompile, recompile, sanity-check, commit. This skill
supplies only the
clock-specific content (which nodes and
properties to edit during the protocol's "Edit the DTS" step).
The edited
lands in the
<source.root_path>/Linux_for_Tegra/
overlay tracker.
's channel A walks the
tracker and copies the file into
.
Do not edit
<bsp_image.root_path>/Linux_for_Tegra/bootloader/<bpmp-dtb>
directly — that's the promote output, not an input.
Resolve the SKU-correct BPMP DTB
Per the protocol's "Resolving the active BPMP DTB" section, read
from the active flash conf. For the common Thor /
single-SKU conf shapes this is the static
line
in the per-board
and the value is authoritative as-is.
For
SKU-multiplexed conf shapes (Orin AGX devkit conf chain
that selects a different BPMP DTB per
/
via
— see
../../context/bsp-customization-software-layers.md#per-board-conf-dispatch--update_flash_args_common
),
walk the dispatch chain with
and
board_FAB=<module.revision or empty>
from the active profile,
and read
from the dispatch output —
not from
the static line of the per-board
. Static and dispatched
values match for non-multiplexed confs; the dispatch is
mandatory only when the conf chain conditionally overrides
.
List effective max rates (inspection)
Inspect both layers of the runtime ceiling — see
references/clock-control-model.md#effective-runtime-ceiling
— before deciding on a
value.
Inspection cookbook (BPMP-side decompile + grep; nvpmodel-side awk over the boot default mode) is in
references/bpmp-dtb-clock-edits.md#inspection-cookbook
.
For the nvpmodel layer see
/jetson-customize-nvpmodel
.
This step does not mutate state — it's a precondition for sizing
the edit in the "Content edit:
on a named clock node" step.
Content edit: on a named clock node
During the "Edit the DTS" step of the protocol, modify the property
inside the named clock node — never
.
must be strictly below the clock's hard cap (
if
defined, otherwise the live
from a running target of
the same chip / SKU).
DTS edit form, semantics, and the nvpmodel ↔ BPMP clock-node
mapping live in
references/bpmp-dtb-clock-edits.md
.
Then hand control back to the protocol — its "Recompile", "Sanity-check
the recompiled blob", "Stage in the overlay tracker", and "Cleanup"
steps cover the rest.
Commit-message convention per the protocol:
<BPMP_BASENAME>: jetson-customize-clocks — <clock-node> max-rate-custom = <value>
.
Content edit: EMC DVFS disable / enable
Default behavior (EMC DVFS on) requires no edit. Disabling EMC
DVFS is a
multi-node edit applied inside the same "Edit the DTS" step of
the protocol,
not a
toggle:
| # | Edit | Scope |
|---|
| 1 | | All SoCs, mandatory |
| 2 | | All SoCs, mandatory |
| 3 | /delete-node/ osp-controller
| T26x (Thor) mandatory — T23x (Orin) has no such node, skip |
Detection:
dtc -I dtb -O dts <bpmp-dtb> | grep -c osp-controller
— zero hits ⇒ T23x path. Full DTS snippets, the surviving-paths
failure modes, and the re-enable procedure are in
references/emc-dvfs-disable.md
.
Apply the protocol's "Recompile" through "Cleanup" steps once the multi-node edit is in
place. Commit-message convention:
<BPMP_BASENAME>: jetson-customize-clocks — EMC DVFS disable (bwmgr + cactmon[+ osp-controller])
.
Disabling raises idle power; intended for stress / performance
tests, not production rootfs.
Re-run + idempotency
Per the protocol's "Re-runnability" section, re-running this
skill with the same target value produces a no-op commit. Re-
running with a different value rewrites the same property —
shows the per-run history. To return a clock
to its
ceiling, edit the DTS to remove the
line and recompile.
Operation 2 — nvpower.sh edits
Edits
, which runs at boot via
to set
cpufreq / devfreq governors and rates.
The per-script file
The script this Operation edits has the relative path:
Linux_for_Tegra/rootfs/etc/systemd/nvpower.sh
It lives in two roots; the Operation walks both:
| Role | Location | Skill writes? |
|---|
| Detection + pristine source | <bsp_image.root_path>/Linux_for_Tegra/rootfs/etc/systemd/
| no — read-only |
| Overlay edit target + git commit | <source.root_path>/Linux_for_Tegra/rootfs/etc/systemd/
| yes |
Subsequent sub-steps refer to
the per-script file to mean the overlay
copy under
. The
copy is read
once during the pristine-import step below, then never touched again.
Overlay edit recipe (apply before editing nvpower.sh)
Follow the canonical
Off-skill edits recipe
in the workflow doc — pristine import + customization commit pair, both
gated by the preview gate.
is a single file with no
propagation set; one pristine commit + one customization commit covers
the entire change.
Concrete substitutions for this skill:
- is
rootfs/etc/systemd/nvpower.sh
.
- Suggested pristine-import message:
import pristine: rootfs/etc/systemd/nvpower.sh
,
body Source: <bsp_image.root_path>/Linux_for_Tegra/ (BSP <bsp_image.version>)
.
- Suggested customization-commit header:
jetson-customize-clocks: nvpower.sh <summary>
,
body lines like set_cpufreq_governor: desired_cpufreq_gov "schedutil" -> "performance"
.
Pick the edit
Function locations (
,
), common-edit recipes (pin to Fmax, static rate, min/max bounds), and the
package-upgrade caveat live in
references/nvpower-sh-edits.md
.
Deploy
The customization commit in the overlay tracker does not reach the device
on its own. The Deploy chain:
- — copies every tracked file in the overlay
into
<bsp_image.root_path>/Linux_for_Tegra/
. Diff-aware (skip
byte-identical); uses for destinations.
- — flashes the updated to the
device. runs the new script on the next boot.
- (Alternate, no flash) Copy
<source.root_path>/Linux_for_Tegra/rootfs/etc/systemd/nvpower.sh
directly to the running target's , then
sudo systemctl restart nvpower.service
(or reboot).
Editing
without committing — or editing
<bsp_image.root_path>/...
directly — does nothing for
and is silently lost on the next
re-extract.
Recipe — pin everything to MAXN for stress / performance runs
Combines Operations 1 + 2. Operation 1's BPMP edits all flow
through one round of the protocol (a single decompile / multi-node
edit / recompile / commit cycle — don't round-trip the protocol
twice for the same
):
- BPMP DTB (the "Content edit: on a named clock node" step content): leave unset on every CPU / GPU / EMC clock; remove existing lines that lower the ceiling.
- BPMP DTB (the "Content edit: EMC DVFS disable / enable" step content): pin EMC at its init rate — , , plus
/delete-node/ osp-controller
on T26x (skip on T23x).
- Apply both content edits inside one protocol "Edit the DTS" invocation, then run the remaining protocol steps (recompile, sanity-check, single customization commit covering both content edits).
- nvpower.sh (Operation 2): set
desired_cpufreq_gov="performance"
and desired_devfreq_gov="performance"
unconditionally; remove the GPU/nvjpg skip in . Applies via Operation 2's overlay edit recipe (the "Overlay edit recipe (apply before editing nvpower.sh)" step) — a separate overlay-tracker pristine + customization commit pair on the rootfs script, distinct from the BPMP-DTB protocol's commit.
- Set the boot-default nvpmodel mode to MAXN via
/jetson-customize-nvpmodel
— the per-clock nvpmodel cap clamps below regardless of BPMP DTB content.
Deploy
→
picks up the new BPMP DTB (via the overlay tracker) and the edited
(via the same overlay tracker) on the next flash.
Limitations
- Image-build-time only. All edits land under
<source.root_path>/Linux_for_Tegra/
and reach the device only via → . Live-target tuning is out of scope.
- only lowers the ceiling. It must be strictly below ; raising the silicon cap is not supported.
- Effective ceiling is two-layer. The runtime ceiling is
min(BPMP cap, active-nvpmodel-mode cap)
. The nvpmodel cap is owned by /jetson-customize-nvpmodel
; this skill does not edit it.
- SoC-conditional EMC DVFS gate. Disabling EMC DVFS requires editing different node sets on T23x (bwmgr + cactmon) vs T26x (bwmgr + cactmon + delete ). Mis-detection produces undefined behavior.
- T23x GPU cap is multi-node. The GPU clock is split across and every ; the cap binds only when applied to all of them.
- is package-managed. It ships in ; package upgrades clobber in-place edits. Long-lived setups should prefer a systemd drop-in or sibling helper.
- ODMDATA wins. When an ODMDATA token covers a property, the token overrides direct BPMP DTS edits at flash time. Direct BPMP DTS edits are the fallback for properties no NVIDIA token reaches.
- and are off-limits. is the silicon ceiling (read-only). is for boot-time clock init, not ceiling overrides — never touch either.
- BPMP DTB may be SKU-multiplexed. On compound / dispatched flash confs (Orin AGX devkit chain), is selected by / via . Reading the static line is wrong when the chain conditionally overrides it; resolve via the dispatch instead.
Troubleshooting
| Error | Cause | Solution |
|---|
| set but clock still ramps to on T23x GPU | Only was capped; the partitions still run at and dominate the effective ceiling. | Apply the same to and every node enumerated by grep -nE '^\s*nafll_gpc[0-9]+\s*:' <decompiled.dts>
. |
| EMC DVFS disable appears to apply but EMC still scales on T26x | Only was set; survives and re-issues frequency changes via the QoS path. | Add edits #2 () and #3 (/delete-node/ osp-controller
) inside the same "Edit the DTS" step. Verify via dtc -I dtb -O dts <bpmp-dtb> | grep -c osp-controller
→ expect 0. |
| EMC DVFS disable rejected on T23x with "node not found" for | T23x (Orin) BPMP DTBs do not contain ; edit #3 must be skipped on T23x. | Detect SoC family with the step; only apply #3 when the count is ≥1. |
BPMP refuses to load DTB after edit: max-rate-custom >= max-rate-maxn
| was set to or above the silicon ceiling. | Lower strictly below . If is absent from the node, query the live cap on a running target: cat /sys/kernel/debug/bpmp/debug/clk/<clock>/max_rate
. |
| re-appears after | does not remove the node from the device tree; BPMP still walks it. | Replace with /delete-node/ osp-controller;
— the node must not exist for BPMP to skip the path. |
| Edits to lost after | is owned by the deb and gets overwritten on upgrade. | For long-lived test setups, package edits into a systemd drop-in or a sibling helper file referenced by , rather than editing in place. |
| is a no-op after editing the BPMP DTB | The edit was applied to <bsp_image.root_path>/Linux_for_Tegra/
, which is 's output — not its input. | Move the edit to <source.root_path>/Linux_for_Tegra/bootloader/<BPFDTB_FILE>
(the overlay tracker) and commit through the BPMP-DTB protocol. |
| Cap appears to apply on first boot then resets after a power-mode change | The active nvpmodel mode's per-clock cap clamps below . | Inspect both layers; if nvpmodel is binding, raise (or remove) the nvpmodel cap via /jetson-customize-nvpmodel
. The BPMP cap alone is not the runtime ceiling. |
References
../../references/bsp-customization-bpmp-dtb.md
— canonical BPMP-DTB customization protocol (pristine import, decompile, edit, recompile, sanity-check, commit). Operation 1 of this skill is a content-only consumer; the protocol owns the mechanics.
references/clock-control-model.md
— layer stack, two-ceilings overview, effective-runtime-ceiling formula.
references/bpmp-dtb-clock-edits.md
— two-ceilings semantics, DTS edit form, nvpmodel ↔ BPMP clock-node mapping, inspection cookbook.
references/emc-dvfs-disable.md
— full SoC-conditional EMC DVFS disable procedure with DTS snippets, detection, re-enable.
references/nvpower-sh-edits.md
— function locations + common-edit recipes + package-upgrade caveat.
/jetson-customize-nvpmodel
— sibling skill: nvpmodel power modes. The active mode's per-clock cap clamps below the BPMP DTB cap.