Skip to content

Commit 4fe9f1e

Browse files
committed
Peer review feedback (thanks Copilot)
1 parent 590ae95 commit 4fe9f1e

6 files changed

Lines changed: 88 additions & 26 deletions

File tree

.github/workflows/test-configs.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,16 +307,21 @@ jobs:
307307
with:
308308
arch: riscv64
309309
config-file: ./config/examples/polarfire_mpfs250_qspi.config
310+
# M-mode + LPDDR4 build: point LIBERO_FPGA_CONFIG_DIR at the in-tree
311+
# CI stub so MPFS_DDR_INIT actually compiles in CI (the upstream config
312+
# leaves the var empty so real boards must override it explicitly).
310313
microchip_mpfs250_m_test:
311314
uses: ./.github/workflows/test-build-riscv.yml
312315
with:
313316
arch: riscv64
314317
config-file: ./config/examples/polarfire_mpfs250_m.config
318+
make-args: LIBERO_FPGA_CONFIG_DIR=tools/ci/mpfs_libero_stub
315319
microchip_mpfs250_m_qspi_test:
316320
uses: ./.github/workflows/test-build-riscv.yml
317321
with:
318322
arch: riscv64
319323
config-file: ./config/examples/polarfire_mpfs250_m_qspi.config
324+
make-args: LIBERO_FPGA_CONFIG_DIR=tools/ci/mpfs_libero_stub
320325

321326
raspi3_test:
322327
uses: ./.github/workflows/test-build.yml

docs/Targets.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -828,6 +828,13 @@ still produces a working M-mode wolfBoot without DDR. Add
828828
`-DDEBUG_DDR` to `CFLAGS_EXTRA` for verbose register-level traces
829829
during bring-up.
830830

831+
A compile-only stub `tools/ci/mpfs_libero_stub/fpga_design_config.h`
832+
exists for GitHub Actions: every `LIBERO_SETTING_*` symbol referenced
833+
by the HAL is defined to `0` so the M-Mode + DDR build path stays
834+
under continuous integration. The stub is **not** runnable - real
835+
boards must point `LIBERO_FPGA_CONFIG_DIR` at the actual Libero / HSS
836+
output.
837+
831838
Key build settings that differ between configurations:
832839

833840
| Setting | SDCard | eMMC | QSPI | L2-LIM | M-Mode | M-Mode + DDR |

hal/mpfs250.c

Lines changed: 52 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -279,16 +279,14 @@ static inline void mb(void)
279279
__asm__ volatile("fence iorw, iorw" ::: "memory");
280280
}
281281

282-
/* Simple busy-loop delay
283-
* Approximately us microseconds at ~40MHz (early boot clock)
284-
* This is used before the timer is fully reliable */
282+
/* DDR-init delay. Forwards to rdcycle-based udelay() so the effective
283+
* delay tracks the current CPU frequency. The previous implementation
284+
* was a hardcoded ~40 MHz busy loop; after mss_pll_init() switches the
285+
* CPU clock to ~600 MHz it ran ~15x too short, silently violating
286+
* LPDDR4 reset / MR-write timing windows. */
285287
static void ddr_delay(uint32_t us)
286288
{
287-
volatile uint32_t i;
288-
/* At ~40MHz, ~10 loop iterations per microsecond */
289-
for (i = 0; i < us * 10; i++) {
290-
__asm__ volatile("nop");
291-
}
289+
udelay(us);
292290
}
293291

294292
/* IOSCB Bank Controllers and DLL bases */
@@ -559,8 +557,13 @@ static int mss_pll_init(void)
559557
}
560558
}
561559

562-
/* Reinitialize UART for new clock frequency */
560+
/* Reinitialize UART for new clock frequency. hal_uart_reinit
561+
* is defined under #ifdef DEBUG_UART (the only path that uses
562+
* the UART driver); skip the call when that block is absent so
563+
* the build links cleanly without DEBUG_UART. */
564+
#ifdef DEBUG_UART
563565
hal_uart_reinit();
566+
#endif
564567
return 0;
565568
}
566569
if ((timeout % 100000) == 0) {
@@ -1953,18 +1956,37 @@ static int run_training(void)
19531956
uint32_t div0_1_orig = DDR_PLL_REG(PLL_DIV_0_1);
19541957
uint32_t div2_3_orig = DDR_PLL_REG(PLL_DIV_2_3);
19551958
{
1956-
uint32_t div0 = div0_1_orig & 0x3F00UL;
1957-
uint32_t div1 = div0_1_orig & 0x3F000000UL;
1958-
uint32_t div2 = div2_3_orig & 0x3F00UL;
1959-
uint32_t div3 = div2_3_orig & 0x3F000000UL;
1960-
uint32_t mult = 2;
1961-
1962-
/* Double the dividers for MR writes */
1963-
DDR_PLL_REG(PLL_DIV_0_1) = (div0 | div1) * mult;
1964-
DDR_PLL_REG(PLL_DIV_2_3) = (div2 | div3) * mult;
1965-
1966-
/* Wait for PHY PLL to lock */
1967-
while ((DDRPHY_REG(PHY_PLL_CTRL_MAIN) & 0x2000000UL) == 0) {}
1959+
/* Each register holds two 6-bit divider fields at bits [13:8] and
1960+
* [29:24]. Extract numeric values, double (LPDDR4 MR writes need a
1961+
* slower PLL output), clamp to the 6-bit field max so the doubled
1962+
* value cannot overflow into adjacent bits, then re-encode while
1963+
* preserving all other bits of the original register. */
1964+
uint32_t f0 = (div0_1_orig >> 8) & 0x3FUL;
1965+
uint32_t f1 = (div0_1_orig >> 24) & 0x3FUL;
1966+
uint32_t f2 = (div2_3_orig >> 8) & 0x3FUL;
1967+
uint32_t f3 = (div2_3_orig >> 24) & 0x3FUL;
1968+
1969+
f0 = (f0 > 0x1FUL) ? 0x3FUL : (f0 << 1);
1970+
f1 = (f1 > 0x1FUL) ? 0x3FUL : (f1 << 1);
1971+
f2 = (f2 > 0x1FUL) ? 0x3FUL : (f2 << 1);
1972+
f3 = (f3 > 0x1FUL) ? 0x3FUL : (f3 << 1);
1973+
1974+
DDR_PLL_REG(PLL_DIV_0_1) = (div0_1_orig & ~0x3F003F00UL) |
1975+
(f0 << 8) | (f1 << 24);
1976+
DDR_PLL_REG(PLL_DIV_2_3) = (div2_3_orig & ~0x3F003F00UL) |
1977+
(f2 << 8) | (f3 << 24);
1978+
1979+
/* Wait for PHY PLL to lock. Bounded at 100 ms so a bad refclk,
1980+
* power glitch, or mis-programmed divider cannot brick boot in
1981+
* an infinite spin -- bail out so the caller can fail cleanly. */
1982+
timeout = 100000;
1983+
while ((DDRPHY_REG(PHY_PLL_CTRL_MAIN) & 0x2000000UL) == 0) {
1984+
if (timeout-- == 0) {
1985+
wolfBoot_printf("DDR: PHY PLL lock timeout (post-doubling)\n");
1986+
return -1;
1987+
}
1988+
udelay(1);
1989+
}
19681990
ddr_delay(5000);
19691991

19701992
/* Reset delay lines after frequency change */
@@ -2075,8 +2097,15 @@ static int run_training(void)
20752097
DDR_PLL_REG(PLL_DIV_0_1) = div0_1_orig;
20762098
DDR_PLL_REG(PLL_DIV_2_3) = div2_3_orig;
20772099

2078-
/* Wait for PHY PLL to lock */
2079-
while ((DDRPHY_REG(PHY_PLL_CTRL_MAIN) & 0x2000000UL) == 0) {}
2100+
/* Wait for PHY PLL to lock; bounded as in the post-doubling wait above. */
2101+
timeout = 100000;
2102+
while ((DDRPHY_REG(PHY_PLL_CTRL_MAIN) & 0x2000000UL) == 0) {
2103+
if (timeout-- == 0) {
2104+
wolfBoot_printf("DDR: PHY PLL lock timeout (post-restore)\n");
2105+
return -1;
2106+
}
2107+
udelay(1);
2108+
}
20802109
ddr_delay(500);
20812110

20822111
/* Reset delay lines after frequency change */

src/boot_riscv.c

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,22 @@ static void handle_external_interrupt(void)
133133
}
134134
#endif /* PLIC_BASE */
135135

136+
/* Backward-compatible 3-arg weak hook. Out-of-tree platforms that override
137+
* this in their own HAL keep working; the asm trap entry now calls
138+
* handle_trap_ex, which forwards here so legacy overrides still execute. */
136139
unsigned long WEAKFUNCTION handle_trap(unsigned long cause, unsigned long epc,
140+
unsigned long tval)
141+
{
142+
(void)cause;
143+
(void)tval;
144+
return epc;
145+
}
146+
147+
/* Regs-aware trap dispatch -- called directly from src/vector_riscv.S.
148+
* Override this (also weak) to take full control including the saved
149+
* register frame. Falls through to weak handle_trap so legacy 3-arg
150+
* overrides still run. */
151+
unsigned long WEAKFUNCTION handle_trap_ex(unsigned long cause, unsigned long epc,
137152
unsigned long tval, unsigned long *regs)
138153
{
139154
last_cause = cause;
@@ -225,7 +240,8 @@ unsigned long WEAKFUNCTION handle_trap(unsigned long cause, unsigned long epc,
225240
/* Synchronous exceptions are not handled - just record them */
226241
#endif
227242

228-
return epc;
243+
/* Forward to the legacy 3-arg hook so out-of-tree overrides still run */
244+
return handle_trap(cause, epc, tval);
229245
}
230246

231247
/* ============================================================================

src/sdhci.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1428,11 +1428,13 @@ int sdhci_init(void)
14281428
/* Call platform-specific initialization (clocks, resets, pin mux) */
14291429
sdhci_platform_init();
14301430

1431+
#ifdef DEBUG_SDHCI
14311432
/* Dump capability + presence registers so the bring-up log shows the
14321433
* controller's reported base clock and whether a card was detected. */
14331434
wolfBoot_printf("SDHCI: SRS09=0x%08X SRS16=0x%08X SRS17=0x%08X\n",
14341435
SDHCI_REG(SDHCI_SRS09), SDHCI_REG(SDHCI_SRS16),
14351436
SDHCI_REG(SDHCI_SRS17));
1437+
#endif
14361438

14371439
/* Allow controller to settle after platform init (slot type change,
14381440
* soft reset, clock configuration). Without this, the controller may

src/vector_riscv.S

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,10 @@
3131

3232
#if __riscv_xlen == 64
3333

34-
/* RV64: Save all caller-saved registers and call handle_trap */
34+
/* RV64: Save all caller-saved registers and call handle_trap_ex.
35+
* handle_trap_ex (in src/boot_riscv.c) is the regs-aware weak hook;
36+
* it forwards to the legacy 3-arg weak handle_trap so out-of-tree
37+
* platform overrides keep working. */
3538
.macro trap_entry
3639
addi sp, sp, -32 * REGBYTES
3740
STORE x1, 1 * REGBYTES(sp)
@@ -71,7 +74,7 @@
7174
csrr a2, MODE_PREFIX(tval)
7275

7376
mv a3, sp
74-
jal handle_trap
77+
jal handle_trap_ex
7578
csrw MODE_PREFIX(epc), a0
7679

7780
.endm

0 commit comments

Comments
 (0)