PolarFire SoC M-Mode LPDDR4 + minimal SBI runtime#774
Open
dgarske wants to merge 2 commits into
Open
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Adds standalone wolfBoot M-mode support for the PolarFire SoC MPFS250T Video Kit, including LPDDR4 bring-up (replacing HSS in the early boot path) and Linux S-mode handoff plumbing.
Changes:
- Enhance SDHCI diagnostics and reliability workarounds (CMD0→CMD8 delay, single-block read option, capability logging).
- Extend RISC-V M-mode boot flow with a reusable M→S handoff API and MPFS-specific “release U54 hart” implementation.
- Introduce MPFS250 DDR/PHY init infrastructure, build-time enablement via
LIBERO_FPGA_CONFIG_DIR, new config template, and CI build job.
Reviewed changes
Copilot reviewed 7 out of 8 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| src/sdhci.c | Adds richer error logging, controller register dump, and reliability workarounds for Cadence SD4HC. |
| src/boot_riscv.c | Adds trap register dump support (regs frame) and factors M→S handoff into overridable helpers. |
| hal/mpfs250.h | Adds MPFS250 peripheral bits and extensive DDRC/PHY register definitions + DDR init declarations. |
| hal/mpfs250.c | Implements MPFS250 DDR/PLL/PHY init, M→S boot on a U54 via IPI handoff, and UART reinit after PLL. |
| docs/Targets.md | Documents new “M-Mode + DDR” configuration and build-time Libero config integration. |
| config/examples/polarfire_mpfs250_m.config | Adds new example config for M-mode + LPDDR4 + SD + S-mode Linux boot. |
| arch.mk | Enables MPFS DDR init when LIBERO_FPGA_CONFIG_DIR is provided (adds -DMPFS_DDR_INIT and include path). |
| .github/workflows/test-configs.yml | Adds CI build job for the new MPFS250 M-mode + DDR config template. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Standalone M-mode wolfBoot on the E51 (replacing HSS): software LPDDR4 init with WRCALIB all-4-lane training gate and retry, SD card secure boot of a signed 19MB Yocto FIT (SDHCI PIO + PDMA staging with per-block verify and retry; CPU writes to DDR do not land on this board), SHA384+ECC384 verification, FIT parse with PDMA kernel/dtb extraction, L2-buffered dtb fixups, and S-mode handoff of a U54 hart via mailbox+IPI. Removes the per-boot DDR diagnostics whose cached-write L2 thrash corrupted L2-scratch code, and adds an L2 headroom linker assert.
Comment on lines
+37
to
+39
| #ifdef SDHCI_BLOCK_VIA_PDMA | ||
| extern int mpfs_pdma_memcpy(void *dst, const void *src, uint32_t bytes); | ||
| #endif |
Comment on lines
+1701
to
+1713
| for (retry = 0; retry < 8 && mism != 0; retry++) { | ||
| mpfs_pdma_memcpy(buf, tmp_buf + start_offset, read_sz); | ||
| *(volatile uint32_t *)0x20001000UL = 0xDEADC0DEU; | ||
| __asm__ volatile("fence iorw,iorw" ::: "memory"); | ||
| mism = 0; | ||
| for (k = 0; k < read_sz; k++) { | ||
| if (ncv[k] != tmp_buf[start_offset + k]) { | ||
| mism = 1; | ||
| break; | ||
| } | ||
| } | ||
| } | ||
| } |
Comment on lines
+1774
to
+1795
| mism = 0; | ||
| for (retry = 0; retry < 8; retry++) { | ||
| __asm__ volatile("fence iorw,iorw" ::: "memory"); | ||
| mism = 0; | ||
| for (w = 0; w < SDHCI_BLOCK_SIZE / 4U; w++) { | ||
| if (ncv[w] != sdhci_pdma_staging[w]) { | ||
| mism = 1; | ||
| break; | ||
| } | ||
| } | ||
| if (mism == 0) { | ||
| break; | ||
| } | ||
| pdma_retries++; | ||
| mpfs_pdma_memcpy(block_dst, sdhci_pdma_staging, | ||
| SDHCI_BLOCK_SIZE); | ||
| *(volatile uint32_t *)0x20001000UL = 0xDEADC0DEU; | ||
| } | ||
| if (mism != 0) { | ||
| pdma_hard++; | ||
| } | ||
| } |
| #define SBI_HSM_STOPPED 1 | ||
| #define SBI_HSM_START_PENDING 2 | ||
|
|
||
| /* Register-frame indices (regs[N] == xN), see src/vector_riscv.S trap_entry */ |
Comment on lines
+477
to
+483
| if (sbi_hart_state[h] != SBI_HSM_STARTED) { | ||
| continue; /* parked harts consume MSIP in their wake loop */ | ||
| } | ||
| sbi_ipi_ops[h] |= op; | ||
| __asm__ volatile("fence rw, rw" ::: "memory"); | ||
| CLINT_MSIP(h) = 1U; | ||
| } |
Adds a minimal M-mode SBI runtime (src/riscv_sbi.c) so wolfBoot can boot an S-mode OS with no external firmware: SBI BASE/TIME/IPI/RFENCE/HSM/DBCN plus the legacy calls; per-hart M-mode trap stacks switched via mscratch with a re-entrant trap entry (the OS stack pointer is virtual at trap time) and a wolfBoot gp reload in the handler; rdtime emulation for S and U mode (these harts have no time CSR) and byte-wise misaligned load/store emulation via MPRV (misaligned traps are not delegatable); MPRV-based guest memory access for console buffers; HSM hart_start with per-hart start mailboxes and remote RFENCE fence fan-out with completion wait. PolarFire SoC platform wiring: CLINT MTIME time-base enable (SYSREG RTC divider, HSS parity) with all comparators parked (the reset value left MTIP pending, so parked harts' WFI never slept); eNVM clock (ENVM_CR) programmed before the AHB clock raise (HSS parity; unprogrammed it ran eNVM reads out of spec and corrupted L2-scratch code); mailbox-check-before-wfi fix in the U54 park loop; secondary harts set gp in the eNVM wake stub; cross-hart SBI state and start mailboxes live in the E51 DTIM and the M-mode trap stacks in the nomap-reserved hss-buffer DDR region, because cacheable stores to the L2 scratchpad can be lost on cache-line eviction; STACK_SIZE_PER_HART unified between the linker script and CFLAGS (the mismatch placed woken harts' stacks inside the E51 stack); watchdog policy (the MSS WDTs always count and reset at timeout: one final all-hart refresh at handoff, the parked E51 monitor keeps petting, OS watchdog nodes disabled in the dtb); SDHCI software-reset-all at handoff so the OS driver finds a clean controller; dtb fixups (no memory-node override -- the 1GB 32-bit window must not be widened over the non-cached alias; root on mmcblk0p3); DEBUG_DDR off by default (training no longer depends on printf timing thanks to the auto-init-disable reorder and the WRCALIB all-4-lane gate); obsolete bring-up diagnostics removed and the boot log reduced to milestones and errors. Verified on the MPFS250T Video Kit: 'smp: Brought up 1 node, 4 CPUs', repeated clean cold boots to the systemd login prompt in ~40 s (10/10 and 5/5 gates), and 12-minute idle soaks with no reset.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
wolfBoot fully replaces HSS (and OpenSBI) on the Microchip PolarFire SoC MPFS250T Video Kit: it boots on the E51 monitor core in M-mode from eNVM, performs software LPDDR4 init/training, loads a signed 19 MB Yocto FIT image from SD card into DDR, verifies it (SHA384 + ECC384), applies device-tree fixups, hands off a U54 hart to S-mode Linux, and stays resident as a minimal SBI runtime. Result: secure-boot 4-CPU SMP Yocto Linux to a login prompt in ~40 s from power-on, with no Microchip firmware in the boot chain.
Commits
1.
PolarFire SoC: LPDDR4 init for MPFS250T Video Kit (M-Mode)(d986616)fpga_design_config.h(pulled in via theLIBERO_FPGA_CONFIG_DIRmake variable; a CI stub keeps the path compiling in GitHub Actions).DEBUG_DDRis now diagnostic-only, off by default).2.
RISC-V: minimal SBI runtime; PolarFire SoC boots 4-CPU SMP Yocto Linux(8432eb5)Generic
src/riscv_sbi.c(reusable for other RISC-V M-mode targets, enabled byWOLFBOOT_MMODE_SMODE_BOOT):mscratchwith a re-entrant trap entry (the trapped OSspis a virtual address) andgpreload in the handler.rdtimeemulation for S/U-mode (notimeCSR on these harts) and byte-wise misaligned load/store emulation via MPRV (misaligned traps are not delegatable).hart_startbacked by per-hart start mailboxes; remote RFENCE fan-out with completion wait.PolarFire SoC platform wiring (
hal/mpfs250.c):ENVM_CR) programmed before the AHB clock raise (unprogrammed, eNVM reads ran out of spec and corrupted the L2-scratch code copy).hss-bufferDDR region: cacheable stores to the L2 scratchpad can be silently lost on dirty-line eviction, which made cross-hart flags layout-dependently invisible.Validation
Notes for reviewers
src/vector_riscv.Strap macro changes are#ifdef WOLFBOOT_RISCV_MMODEgated; S-mode builds keep the original frame behavior (mscratchis an M-mode-only CSR).src/fdt.cgains a weakwolfBoot_fit_memcpyhook so the platform can route FIT subimage copies through PDMA.docs/Targets.mddocuments the new M-Mode + DDR Linux boot flow, the wolfSBI runtime, and the watchdog policy.