diff --git a/BUG_ANALYSIS.md b/BUG_ANALYSIS.md index 5cb5c77..a3b20f7 100644 --- a/BUG_ANALYSIS.md +++ b/BUG_ANALYSIS.md @@ -94,16 +94,31 @@ hardware registers indefinitely. If the hardware doesn't respond (due to a clock issue, reset problem, or silicon defect), the system **hangs permanently** during boot with no diagnostic output. -| Register | Offset | Uses | What it waits for | -|----------|--------|------|-------------------| -| SGRF_DDR_STATUS | 0xFE0500E0 | 1 | Security GRF ready | -| SGRF_DDR_CON21 | 0xFE050054 | 2 | SGRF configuration done | -| DfiStatus | +0xA24 | 4 | DFI interface ready (PHY↔controller) | -| MicroContMuxSel | +0x10090 | 4 | PHY firmware mailbox | -| MicroReset | +0x10080 | 2 | PHY firmware reset complete | -| UctWriteProtShadow | +0x10514 | 5 | Training status shadow register | -| CalBusy | +0x684 | 1 | ZQ calibration complete | -| Unknown | +0x10514 bit 2:1 | 1 | Training engine status | +**Updated 2026-04-15 per RK3588 TRM Part 2:** the uMCTL2 controller +offsets are now vendor-named. PHY PUB offsets remain undocumented in +the TRM (DWC / Innosilicon IP is not republished) — the names below +with `(RE)` are our reverse-engineering guesses. + +| Register | Offset (base) | Uses | What it waits for | Source | +|----------|--------------|------|-------------------|--------| +| SGRF_DDR_STATUS | abs 0xFE0500E0 | 1 | Security GRF config done | RK3588 TRM part 1 | +| SGRF_DDR_CON21 | abs 0xFE050054 | 2 | Security GRF configuration done | RK3588 TRM part 1 | +| DDRCTL_DFISTAT | DDRCTL + 0x10514 | 5 | `dfi_init_complete` — PHY↔controller handshake | **TRM part 2 Ch.2** (renamed from "UctWriteProtShadow") | +| DDRCTL_MRSTAT | DDRCTL + 0x10090 | 4 | `mr_wr_busy` — Mode Register Write complete | **TRM part 2 Ch.2** (renamed from "MicroContMuxSel") | +| DDRCTL_MRCTRL0 | DDRCTL + 0x10080 | 2 | Mode Register Control (not a poll target by itself — but polled by code waiting for MR command completion) | **TRM part 2 Ch.2** (renamed from "MicroReset") | +| PHY_CTL_STATE | PHY + 0x14 `(RE)` | 4 | PHY state machine: `[2:0] == 1` (idle) or `(val & 7) == 3` (some training stage) | Reverse-engineered — still not in TRM | +| PHY_CALBUSY | PHY + 0x684 `(RE)` | 1 | ZQ calibration complete — name matches DWC PUB convention | Reverse-engineered | +| PHY_DFI_READY | PHY + 0xa24 `(RE)` | 4 | DFI-side handshake bit from PHY — separate from DDRCTL_DFISTAT | Reverse-engineered | +| PHY_SHADOW_BB8 | PHY + 0xb88 `(RE)` | 2 | Shadow status word that carries training firmware state between sub-blocks | Reverse-engineered | +| PHY_TRAIN_STEP | PHY + 0x118 / 0x120 `(RE)` | 2 | Step-complete bits \[31:28\] — used in train_phy_block (d328) | Reverse-engineered | +| PHY_HANDSHAKE | PHY + 0x184 `(RE)` | 2 | HANDSHAKE bits \[1:0\] — writer/reader sync in d328 | Reverse-engineered | + +**Base conventions:** +- `DDRCTL` = per-channel uMCTL2 controller base (four channels: + DDRCTL0..3 per TRM Table "DDR Channel X IO description", pp. 557-558). +- `PHY` = per-channel PHY base pointer held in `ctx[ch*32]`, with the + `+0x8000` sub-block for the "Master"-class PHY block seen in d328 + and the `+0x10000` sub-block for the larger PHY block seen in d10c. **Impact:** Any of these can cause a boot hang. The most likely failure mode: - Cold boot at extreme temperatures (timing margins shrink) diff --git a/rk3588_regs_annotated.h b/rk3588_regs_annotated.h index 682ba53..e9e92ca 100644 --- a/rk3588_regs_annotated.h +++ b/rk3588_regs_annotated.h @@ -82,3 +82,43 @@ /* === SRAM (0xFF000000) === */ #define _DAT_ff000010 REG32(0xFF000010) /* SRAM: boot flag/mailbox */ + +/* ===================================================================== + * TRM-CANONICAL names for poll-site registers (RK3588 TRM Part 2 Ch.2) + * Added 2026-04-15 after cross-referencing the 522-page DMC chapter. + * Offsets are within a DDRCTL (uMCTL2) per-channel base. + * ===================================================================== + */ + +#define DDRCTL_MRCTRL0 0x10080 /* Mode Register Control 0 + - mr_wr[31]: write a MR command + - mr_addr[23:16]: MR address + - mr_data[15:0]: MR data to write + Previously guessed as "MicroReset". */ + +#define DDRCTL_MRSTAT 0x10090 /* Mode Register Status + - mr_wr_busy[0]: 1 while MR cmd in flight + Poll: WAIT for bit 0 == 0. + Previously guessed as "MicroContMuxSel". */ + +#define DDRCTL_DFISTAT 0x10514 /* DFI Status + - dfi_init_complete[0]: 1 when PHY ready + Poll: WAIT for bit 0 == 1. + Previously guessed as "UctWriteProtShadow". */ + +/* Low-offset polls in FUN_0000d328 (train_phy_block) and friends are + * Synopsys DWC PUB registers — NOT in RK3588 TRM. Still require RE. + * The heuristic labels below come from the d328 analysis (2026-04-15): + */ +#define PHY_OFF_BASE 0x8000 /* sub-block offset within a PHY used by d328 */ + +#define PHY_CTL_110 0x110 /* write 0xF000F000 to trigger step, 0xF0000000 to clear */ +#define PHY_STAT_A_118 0x118 /* wait for bits[31:28] != 0 */ +#define PHY_STAT_B_120 0x120 /* wait for bits[31:28] != 0 */ +#define PHY_CFG_A_154 0x154 /* write 0x30003 (go), 0x30000 (end) */ +#define PHY_CFG_B_160 0x160 /* write 0x30003 (go), 0x30000 (end) */ +#define PHY_HANDSHAKE_184 0x184 /* wait for bits[1:0] non-zero, then zero */ + +/* The large-offset polls (0xb88, 0xa24, 0x684) in the early-cluster + * functions are also DWC PUB; semantic guesses in BUG_ANALYSIS.md. */ +