Previous commit committed sibling claims without verifying against
the TRM bit tables. Verification fails for d328:
Sibling: +0x110 = CAL_RD_VWML0 (from TRM §2.4.3).
Blob: writes 0xF000F000 to that offset.
TRM: CAL_RD_VWML0 is READ-ONLY, bits[9:0]=rd_vwml0 code, [25:16]=rd_vwml1.
Writing is a no-op.
Root cause of sibling's error: conflated 'DDRPHY_OPB + offset' with
d328's 'DDRPHY_OPB + 0x8000 + offset'. The +0x8000 sub-block is NOT
documented in the TRM; offsets 0x110/0x118/0x120/0x154/0x160/0x184
WITHIN that sub-block mean something different from CAL_RD_VWML0 etc.
Kept the TRM-verified names I DID check:
- DDRCTL_DFISTAT @ +0x10514 (site 3)
- DDRCTL_STAT @ +0x10014 (sites 2,4,5,7)
- DDRPHY_SCHD_TRAIN_CON0 @ +0xa24 — bit layout verified directly
Retracted names for d328's +0x8XXX accesses; restoring the PHY_CTL_110
etc. RE-guess labels as the safe fallback. True names remain unknown
until we get hardware-trace data or the Synopsys DWC PUB databook.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sibling went back into the TRM and found §2.4.3 'Registers Summary
For DDRPHY' which I'd missed — it names almost every PHY PUB register
we'd been calling 'RE guess':
+0x110 = DDRPHY_CAL_RD_VWML0 (Read Valid Window Margin Left Code 0)
+0x120 = DDRPHY_CAL_RD_VWMR0 (Read Valid Window Margin Right Code 0)
+0x160 = DDRPHY_CAL_CON5 (Calibration Control 5: wrtrn_cyc_mode/en/th)
+0x684 = DDRPHY_PRBS_CON0 (PRBS Training Control — was 'CalBusy')
+0xa24 = DDRPHY_SCHD_TRAIN_CON0 (MASTER training scheduler; full bit map
in the TRM — every training type + per-rank)
+0xb88 = DDRPHY_DQSDUTY_CON2 (DQS rise-duty monitor — was 'UctShadow')
SCHD_TRAIN_CON0 is the master — the blob selects a training type via
its enable bits and polls bit[1] phy_train_done. Four of our 16 poll
sites are almost certainly polling this bit across different training
stages.
Still reserved in TRM: +0x118, +0x154, +0x184 — training-engine
private FSMs. Only dynamic tracing can name these.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Per RK3588 TRM Part 2 chapter 2 (DMC, 522 pages):
+0x10080 = DDRCTL_MRCTRL0 (Mode Register Control, was MicroReset)
+0x10090 = DDRCTL_MRSTAT (MR Status mr_wr_busy, was MicroContMuxSel)
+0x10514 = DDRCTL_DFISTAT (DFI Status dfi_init_complete, was UctWriteProtShadow)
These are uMCTL2 controller registers — Rockchip-documented — NOT the
opaque PHY firmware scratch regs our 2026-04 analysis guessed. Poll
semantics now vendor-grounded: wait for MR command roundtrip, wait
for PHY-side DFI handshake.
Low-offset polls in train_phy_block (0x110, 0x118, 0x120, 0x154, 0x160,
0x184) plus the 0x684/0xa24/0xb88 ones remain DWC PUB and thus
undocumented; kept the best-effort RE names with `(RE)` tag in the
BUG_ANALYSIS table so a reader can tell which ones are vendor-canonical
and which are guesses.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Ghidra decompilation of v1.02-v1.19 blobs (118 functions)
- 53 functions renamed, 79 MMIO registers mapped to TRM
- 45 timeout-less poll loops identified and patched
- Production patcher (patch_prod.py) and QEMU emulator
- Comprehensive analysis, frequency tables, community research
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>