Add Agilex 5 FCS and wolfBoot integration - #846
Conversation
7e310c9 to
d67e834
Compare
There was a problem hiding this comment.
Pull request overview
Warning
Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.
Adds an Altera Agilex 5 (013B) port and integration points to boot wolfBoot as BL33 in the GSRD SD-card flow, including SDHCI/platform init, memory mapping, example FIT artifacts, and CI build coverage.
Changes:
- Adds Agilex 5 HAL (C + header), linker script, FIT example, and a BL33 smoke-test app.
- Updates AArch64 startup/MMU mappings and SDHCI behavior to support Agilex 5 boot/SD timing.
- Updates disk-boot logging and adds docs/config + GitHub Actions build coverage for the new target.
Reviewed changes
Copilot reviewed 16 out of 16 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| test-app/app_agilex5.c | Adds a BL33 smoke-test app for Agilex 5 (timer + EL print). |
| src/update_disk.c | Improves disk-boot debug output (block size + pointer-format prints). |
| src/sdhci.c | Adds command-line reset, inhibit timeouts, optional post-command delay, and CMD8 retry logic. |
| src/boot_aarch64_start.S | Adds Agilex 5 include, adjusts CNTFRQ/RVBAR handling, and adds Agilex 5 MMU mappings. |
| src/boot_aarch64.c | Adds Agilex 5 HAL include selection for AArch64 boot code. |
| include/sdhci.h | Adds reset bit definitions and new SDHCI tuning/behavior macros. |
| hal/agilex5.ld | New linker script matching BL33 placement at 0x80200000. |
| hal/agilex5.its | Example FIT description for Agilex 5 Linux payload (kernel + DTB). |
| hal/agilex5.h | New Agilex 5 target configuration and platform constants. |
| hal/agilex5.c | New Agilex 5 HAL implementation (timer, UART, DT fixups, SDHCI PHY + DMA cache ops). |
| docs/Targets.md | Documents the new Agilex 5 target and references Agilex5 bring-up doc. |
| docs/Agilex5.md | Adds bring-up and integration documentation (GSRD/FIT/WIC/test order/CI). |
| config/examples/agilex5_013b_sdcard.config | Adds a buildable example config for Agilex 5 SD-card boot flow. |
| arch.mk | Adds Agilex 5 AArch64 flags + target-specific bootloader responsibilities. |
| .github/workflows/test-configs.yml | Adds Agilex 5 config to existing CI matrix via reusable workflow. |
| .github/workflows/test-build-agilex5.yml | Adds a dedicated Agilex 5 build workflow (path-filtered). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
wolfSSL-Fenrir-bot
left a comment
There was a problem hiding this comment.
Fenrir Automated Review — PR #846
Scan targets checked: wolfboot-bugs, wolfboot-src
Findings: 4
4 finding(s) posted as inline comments (see file-level comments below)
This review was generated automatically by Fenrir. Findings are non-blocking.
|
@aidangarske please rebase. |
058516e to
5525e40
Compare
| SDHCI_REG_SET(SDHCI_SRS12, SDHCI_SRS12_CC); /* clear command complete */ | ||
| while ((SDHCI_REG(SDHCI_SRS09) & SDHCI_SRS09_CICMD) != 0); | ||
| timeout = 0x000FFFFF; | ||
| while (((SDHCI_REG(SDHCI_SRS09) & SDHCI_SRS09_CICMD) != 0U) && |
There was a problem hiding this comment.
This trailing inhibit wait is now bounded, but the one at the top of sdhci_send_cmd_internal is untouched:
/* src/sdhci.c:582 */
while ((SDHCI_REG(SDHCI_SRS09) & SDHCI_SRS09_CICMD) != 0);That is the loop this PR makes most likely to hang. arch.mk:178 sets SDHCI_SKIP_HOST_RESET=1 for agilex5, which deliberately inherits whatever state SPL/TF-A left the Cadence host in. If that stage leaves CMD inhibit asserted — exactly the condition skipping the soft reset exposes you to — the first command spins forever, before any of the new timeouts can fire, with no output at all.
Bounding the entry wait with the same idiom and the same sdhci_reset_cmd_line() recovery is what makes SDHCI_SKIP_HOST_RESET safe to ship.
| } | ||
| } | ||
|
|
||
| #if SDHCI_WAIT_AFTER_CMD_US > 0U |
There was a problem hiding this comment.
This fires on every command, not just the init commands arch.mk:179 describes ("the controller's required post-command settle time"). sdhci_send_cmd_internal is the common path for CMD17/18/24/25 and CMD12 as well.
With SDHCI_WAIT_AFTER_CMD_US=1000 and DISK_BLOCK_SIZE=0x80000, each 512 KB chunk pays ~1 ms for CMD18, ~1 ms for CMD12, and ~1 ms per sdhci_wait_busy() CMD13 — several hundred ms to over a second of pure udelay on a Linux FIT, for a settle requirement that only applies to command setup.
The sharper problem is the footgun for the next target: combined with SDHCI_FORCE_SINGLE_BLOCK_READ (zynq/versal/mpfs250 use it) this becomes 1 ms per 512-byte block, i.e. roughly seven minutes for a 200 MB read. Either scope the delay to sdhci_init() / the card-init sequence, or document that the two options are mutually exclusive.
|
|
||
| #define DEVICE_BUSY 1 | ||
|
|
||
| static int sdhci_reset_cmd_line(void) |
There was a problem hiding this comment.
This changes command-error recovery on every SDHCI target, not just agilex5 — sdhci_reset_cmd_line() now runs on the EINT path for zynq, versal, mpfs250, zynq7000 and tegra234 too.
It is the right thing per SDHCI spec 3.10.1, and it arguably fixes the pre-existing CMD0 retry loop which retried without ever resetting the line. But it is an unguarded change to five validated paths backed by hardware testing on one board, while the other two behaviour changes in this PR (SDHCI_SKIP_HOST_RESET, SDHCI_WAIT_AFTER_CMD_US) are both opt-in.
Either gate it the same way, or state in the PR description that it is a deliberate cross-target change so it isn't discovered later.
| uint32_t timeout = 0x000FFFFF; | ||
|
|
||
| sdhci_reg_or(SDHCI_SRS11, SDHCI_SRS11_RESET_CMD); | ||
| while (((SDHCI_REG(SDHCI_SRS11) & SDHCI_SRS11_RESET_CMD) != 0U) && |
There was a problem hiding this comment.
There is already a reset helper 130 lines below this one, and it is the unbounded one:
/* src/sdhci.c:691 */
static inline void sdhci_reset_lines(void)
{
sdhci_reg_or(SDHCI_SRS11, SDHCI_SRS11_RESET_DAT_CMD);
while (SDHCI_REG(SDHCI_SRS11) & SDHCI_SRS11_RESET_DAT_CMD);
}Same register, same wait, no bound — and it is on the data-transfer path (sdhci_transfer calls it at :1365 and again at the end). Since you are already in this code adding a bounded version, giving sdhci_reset_lines() the same treatment, or expressing one in terms of the other, closes a hang the rest of the PR is otherwise eliminating.
| uint32_t sdhci_platform_set_clock(uint32_t clock_khz, uint32_t base_clk_khz); | ||
|
|
||
| /* Preserve a host controller initialized by an earlier boot stage. */ | ||
| #ifndef SDHCI_SKIP_HOST_RESET |
There was a problem hiding this comment.
Both new knobs break if defined without a value. #if SDHCI_SKIP_HOST_RESET == 0 here, and #if SDHCI_WAIT_AFTER_CMD_US > 0U at :492, are preprocessor errors when the macro expands to nothing — so -DSDHCI_SKIP_HOST_RESET fails where -DSDHCI_SKIP_HOST_RESET=1 works.
The neighbouring SDHCI options are all #ifdef-style (SDHCI_FORCE_CARD_DETECT, SDHCI_SDMA_DISABLED, SDHCI_BLOCK_VIA_PDMA), so the valueless form is what someone will reach for. #if defined(X) && (X != 0) costs nothing and removes the trap.
| UART_REG(UART_THR) = '\r'; | ||
| timeout = UART_TIMEOUT; | ||
| } | ||
| while (((UART_REG(UART_LSR) & UART_LSR_THRE) == 0U) && |
There was a problem hiding this comment.
The timeout is measured but not acted on: both THRE waits fall through to UART_REG(UART_THR) = ... whether or not timeout reached zero, so a wedged UART produces corrupted output rather than dropped output.
Not a boot hazard — bounding the loop is the important part and you have that — but skipping the write when the timeout expires is one line and makes the bound mean something.
Description
partner pr: wolfSSL/meta-wolfssl#177