Skip to content

clocks: brief survey output, decode APLL lock, drop noisy notes#163

Merged
widgetii merged 2 commits into
masterfrom
ddr-eth-vpll-decode
May 14, 2026
Merged

clocks: brief survey output, decode APLL lock, drop noisy notes#163
widgetii merged 2 commits into
masterfrom
ddr-eth-vpll-decode

Conversation

@widgetii
Copy link
Copy Markdown
Member

@widgetii widgetii commented May 14, 2026

Updated per review feedback. The PR title and scope are now narrower than the original.

Summary

The no-arg ipctool survey now emits a tight 8-line clocks: block (the headline numbers only), while ipctool clocks still produces the full register-by-register YAML. The verbose-but-undecoded entries (ddr_pll, eth_pll, video_pll, pll_lock_status, and the older pll_shadow_* from #162) are removed entirely until their FBDIV layout is anchored against a DDR-throughput / ethernet-PHY-rate cross-check. The one reliable bit -- APLL lock from PERI_CRG_PLL122 bit 0 -- is decoded into cpu_pll.locked in the full output.

Default survey output (3 lab boards, identical):

clocks:
  cpu_pll:
    freq_mhz: 900
  ddr:
    data_rate_mbps: 1800
  hpm:
    bin: mid

That replaces the previous ~35-line survey block.

Full ipctool clocks output (Goke V300 board A):

clocks:
  cpu_pll:
    ctrl_reg1: 0x12010000
    ctrl_reg1_raw: 0x12000000
    ctrl_reg2: 0x12010004
    ctrl_reg2_raw: 0x0100104b
    fbdiv: 75
    refdiv: 1
    postdiv1: 2
    postdiv2: 1
    fracdiv: 0x000000
    freq_mhz: 900
    locked: true
  ddr:
    reg: 0x12010080
    raw: 0x00000549
    cksel: 1
    freq_mhz: 450
    data_rate_mbps: 1800
  hpm:
    reg: 0x1202015c
    raw: 0x00f10000
    value: 241
    bin: mid
    binning_window: [190, 310]
    aux_reg: 0x120280d8
    aux_value: 0x81080106
    aux_name: hpm_core_reg0

No more family: line (chip name already in chip.model above). No more note: fields anywhere.

Changes

  • clocks_build_json() gains a bool brief parameter; survey passes true, subcommand passes false.
  • Drop family:, drop every note:.
  • Drop pll_shadow_0c/14 (originally Add clocks and cpubench subcommands; fix #161 PLL decode #162) and ddr_pll/eth_pll/video_pll/pll_lock_status (this PR's first commit, fe47c5c). Their FBDIV bit layout on V4 differs from APLL ([23:16] vs [11:0]) and the REFDIV/POSTDIV positions aren't confirmed; per review feedback "decypher or remove totally", remove until anchored.
  • Add cpu_pll.locked: bool (full output only) decoded from PERI_CRG_PLL122 bit 0 -- APLL lock bit, confirmed across all three lab boards. The struct pll_info gains optional lock_reg/lock_bit fields so future families can hook in their own lock-status check.

Test plan

  • Brief survey output is exactly 8 lines on all three lab boards (hi3516ev300, gk7205v300 OpenIPC, gk7205v300 XM Sofia).
  • ipctool clocks full output retains all decoded fields; cpu_pll.locked: true on all three boards.
  • ipctool clocks --json produces valid JSON via jq round-trip.
  • CI baseline build (cv100 toolchain + bare UPX) -- no warnings under -Wextra.

🤖 Generated with Claude Code

widgetii and others added 2 commits May 14, 2026 15:56
…status

Follow-up to #162. The `pll_shadow_0c` / `pll_shadow_14` entries shipped
there were honest empirical observations ("vary by per-die HPM, don't
drive CPU clock") but used misleading labels: those registers aren't
shadows, they are real PLL configuration pairs for non-CPU domains.

Source: the V4A / HI3516CV500 mask-ROM reverse engineering at
github.com/widgetii/HI3516CV500-SDK/blob/master/sdk/bootrom/bootrom-re/
regmap-crg.h names them explicitly:

  APLL_CONFIG_0/1 = CRG_BASE + 0x00/0x04   CPU PLL
  DPLL_CONFIG_0/1 = CRG_BASE + 0x08/0x0C   DDR PLL
  EPLL_CONFIG_0/1 = CRG_BASE + 0x10/0x14   Ethernet PLL
  VPLL_CONFIG_0/1 = CRG_BASE + 0x18/0x1C   Video PLL
  PLL_LOCK_STAT   = CRG_BASE + 0x1E8       lock status

V4A is one generation up from V4 but shares the CRG layout (same APLL
definition recurs in the Hi3516A SDK kernel patch and was empirically
validated on V4 in #162), so the per-PLL labelling carries over.

Changes:
- `struct raw_reg_info` gains an optional `reg2` field so a single entry
  can dump both CONFIG_0 and CONFIG_1 of a PLL pair.
- Rename `pll_shadow_0c` -> `ddr_pll`, `pll_shadow_14` -> `eth_pll`.
  Add `video_pll` at (0x18, 0x1C) which was previously unexposed.
- Add `pll_lock_status` reading PERI_CRG_PLL122 (0x120101E8) raw, with
  a note explaining the V4A bootrom polls `0xB` (bits 0/1/3 for
  APLL/DPLL/EPLL) but V4 reads `0x5` (bits 0/2) on all three lab
  boards -- so V4's per-bit assignment likely differs from V4A's;
  ship the raw value, leave per-bit decode as a TODO.

FBDIV decode for DPLL/EPLL/VPLL is also TODO: empirically the
FBDIV-shaped bytes sit at bits [23:16] (0x8F/0x97/0x77 in the field
data) rather than [11:0] like APLL, so the layout differs. Need a
DDR-throughput probe and ethernet PHY rate cross-check before
shipping a frequency calculation. The raw config pair is dumped
verbatim so users can fleet-compare without misreading.

Verified on three lab boards: cpu_pll.freq_mhz still 900 (unchanged),
new fields render as expected, no regressions in ddr / hpm /
cpu_running / cpubench outputs. The hi3516ev300 (HiSi-branded)
firmware reads zero for both DPLL and EPLL config pairs while DDR
still runs at 450 MHz, suggesting the HiSi firmware leaves those
PLLs gated and derives DDR clock differently; the Goke firmware
actively programs DPLL and EPLL. Out of scope for this PR.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
PR review feedback (#163): the YAML emitted by the no-arg `ipctool`
survey was too verbose for a daily-driver summary, and the previous
commit's `note:` fields + `family:` line added noise without helping
anyone read the output.

Changes:

- `clocks_build_json()` gains a `bool brief` parameter.
  - `brief = true`  (used by `ipctool` no-arg survey): emits only
    `cpu_pll.freq_mhz`, `ddr.data_rate_mbps`, `hpm.bin`.
  - `brief = false` (used by `ipctool clocks`): emits the full
    register-by-register YAML the subcommand has always produced.
- Remove the `family:` line; the chip name is already in `chip.model`
  one level up.
- Remove every `note:` field. They were either workarounds for
  "we haven't fully decoded this register" or restated info already
  obvious from sibling fields.
- Remove `pll_shadow_0c/14` (#162) and `ddr_pll/eth_pll/video_pll/
  pll_lock_status` (this PR's earlier commit). Their FBDIV bit layout
  on V4 differs from APLL (field-shaped bytes sit at [23:16] rather
  than [11:0]) and the REFDIV/POSTDIV positions aren't confirmed --
  shipping the raw words with a "decode TBD" note was noise. Per
  review: decypher or remove totally -- removed until a DDR-throughput
  probe and ethernet PHY rate cross-check anchor the layout.
- Keep the lock-bit signal that IS reliable: APLL lock from
  PERI_CRG_PLL122 bit 0. Expose it as `cpu_pll.locked: true/false` in
  the full output (bit 0 = APLL on V4 confirmed across all three lab
  boards; other bits' assignment on V4 still TBD).

Survey output is now (Goke V300 example):

  clocks:
    cpu_pll:
      freq_mhz: 900
    ddr:
      data_rate_mbps: 1800
    hpm:
      bin: mid

Verified end-to-end on all three lab boards (hi3516ev300 OpenIPC,
gk7205v300 OpenIPC, gk7205v300 XM Sofia): identical 8-line `clocks:`
section in survey mode; full `ipctool clocks` output unchanged
except for the dropped notes/family and the added cpu_pll.locked.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@widgetii widgetii changed the title clocks: rename pll_shadow_* to ddr_pll/eth_pll, add video_pll + lock status clocks: brief survey output, decode APLL lock, drop noisy notes May 14, 2026
@widgetii widgetii merged commit f7a640e into master May 14, 2026
3 checks passed
@widgetii widgetii deleted the ddr-eth-vpll-decode branch May 14, 2026 13:13
widgetii added a commit that referenced this pull request May 14, 2026
Adds a `clocks_family_v4a` table covering Hi3516CV500 / Hi3516AV300 /
Hi3516DV300 etc. (chip_generation = HISI_V4A = 0x3516C500).

Register map sourced first-party from the V4A mask-ROM reverse
engineering at widgetii/HI3516CV500-SDK sdk/bootrom/bootrom-re/
regmap-crg.h (CRG offsets) and the V4A SDK
HI3516CV500-SDK/sdk/fastburn/fastboot/Source/ddr_training.c (HPM
register addresses + bit layout).

Decoded on V4A:
- APLL/DPLL/EPLL/VPLL register pairs at (CRG+0x00..0x1C). All four use
  the same Hi3516A APLL bit layout (FBDIV at ctrl_reg2[11:0], REFDIV
  at ctrl_reg2[17:12], POSTDIV1/POSTDIV2 at ctrl_reg1[26:24]/[30:28]),
  unlike V4 where DPLL/EPLL had a different (still-unverified) layout.
- Per-PLL lock state from PERI_CRG_PLL122 (CRG+0x1E8). APLL=bit0,
  DPLL=bit1, EPLL=bit3 (V4A bootrom RE polls `& 0xB == 0xB`); bit 2
  inferred as VPLL since the field board reads 0x0F (all four locked).
- HPM characterization at HPM_CHECK_REG = 0x12020098 (SC_CTRL region,
  not CRG): sys_hpm_core at bits [24:16] is 9-bit on V4A (vs 10-bit on
  V4), and the aux fingerprint moves to HPM_CORE_REG0 = 0x120300D8 in
  the MISC region. Same 150-350 validity window, same 190-310 nominal
  binning range as V4.

Not yet decoded on V4A (kept out per "decypher or remove" rule from
PR #163):
- DDR cksel mux. PERI_CRG31 at 0x7C reads non-zero on hi3516av300 but
  the bit positions for the cksel field aren't in the bootrom RE and
  the V4A SDK clock driver doesn't expose DDR as a tunable Linux
  clock. Skip until a board with known DDR rate anchors it. Brief
  survey on V4A therefore omits `ddr.data_rate_mbps` -- it falls back
  to `cpu_pll.freq_mhz + hpm.bin`.

Also tightens the brief-mode emit: only the first PLL (by convention
the CPU/APLL) is shown in the survey output. DPLL/EPLL/VPLL on V4A
are detail and only appear in the full `ipctool clocks` output. The
V4 brief output is unchanged (V4 only has one PLL entry anyway).

Verified on openipc-hi3516av300.dlab.doty.ru (dual-core Cortex-A7,
SMP, Linux 4.9.37):
- brief:   cpu_pll.freq_mhz=900, hpm.bin=mid (5 lines after `clocks:`)
- full:    APLL=900 / DPLL=594 / EPLL=528 / VPLL=552 MHz, all locked;
           HPM value=260 (mid bin), aux_value=0x81090109
- cpubench median 899 MHz (within 0.1% of register-decoded APLL,
  triangulated from dep_add/indep_add/dep_mul)

V4 boards re-verified: hi3516ev300 OpenIPC + gk7205v300 OpenIPC both
still produce the 8-line brief block they did in #163.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
widgetii added a commit that referenced this pull request May 14, 2026
Adds a `clocks_family_v4a` table covering Hi3516CV500 / Hi3516AV300 /
Hi3516DV300 etc. (chip_generation = HISI_V4A = 0x3516C500).

Register map sourced first-party from the V4A mask-ROM reverse
engineering at widgetii/HI3516CV500-SDK sdk/bootrom/bootrom-re/
regmap-crg.h (CRG offsets) and the V4A SDK
HI3516CV500-SDK/sdk/fastburn/fastboot/Source/ddr_training.c (HPM
register addresses + bit layout).

Decoded on V4A:
- APLL/DPLL/EPLL/VPLL register pairs at (CRG+0x00..0x1C). All four use
  the same Hi3516A APLL bit layout (FBDIV at ctrl_reg2[11:0], REFDIV
  at ctrl_reg2[17:12], POSTDIV1/POSTDIV2 at ctrl_reg1[26:24]/[30:28]),
  unlike V4 where DPLL/EPLL had a different (still-unverified) layout.
- Per-PLL lock state from PERI_CRG_PLL122 (CRG+0x1E8). APLL=bit0,
  DPLL=bit1, EPLL=bit3 (V4A bootrom RE polls `& 0xB == 0xB`); bit 2
  inferred as VPLL since the field board reads 0x0F (all four locked).
- HPM characterization at HPM_CHECK_REG = 0x12020098 (SC_CTRL region,
  not CRG): sys_hpm_core at bits [24:16] is 9-bit on V4A (vs 10-bit on
  V4), and the aux fingerprint moves to HPM_CORE_REG0 = 0x120300D8 in
  the MISC region. Same 150-350 validity window, same 190-310 nominal
  binning range as V4.

Not yet decoded on V4A (kept out per "decypher or remove" rule from
PR #163):
- DDR cksel mux. PERI_CRG31 at 0x7C reads non-zero on hi3516av300 but
  the bit positions for the cksel field aren't in the bootrom RE and
  the V4A SDK clock driver doesn't expose DDR as a tunable Linux
  clock. Skip until a board with known DDR rate anchors it. Brief
  survey on V4A therefore omits `ddr.data_rate_mbps` -- it falls back
  to `cpu_pll.freq_mhz + hpm.bin`.

Also tightens the brief-mode emit: only the first PLL (by convention
the CPU/APLL) is shown in the survey output. DPLL/EPLL/VPLL on V4A
are detail and only appear in the full `ipctool clocks` output. The
V4 brief output is unchanged (V4 only has one PLL entry anyway).

Verified on openipc-hi3516av300.dlab.doty.ru (dual-core Cortex-A7,
SMP, Linux 4.9.37):
- brief:   cpu_pll.freq_mhz=900, hpm.bin=mid (5 lines after `clocks:`)
- full:    APLL=900 / DPLL=594 / EPLL=528 / VPLL=552 MHz, all locked;
           HPM value=260 (mid bin), aux_value=0x81090109
- cpubench median 899 MHz (within 0.1% of register-decoded APLL,
  triangulated from dep_add/indep_add/dep_mul)

V4 boards re-verified: hi3516ev300 OpenIPC + gk7205v300 OpenIPC both
still produce the 8-line brief block they did in #163.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant