Skip to content

Commit fcc8bc3

Browse files
committed
Add wolfBoot FIT support for loading bitstream
1 parent 8fe46bb commit fcc8bc3

20 files changed

Lines changed: 885 additions & 10 deletions

File tree

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,7 @@ include/target.h: $(TARGET_H_TEMPLATE) FORCE
653653
sed -e "s/@WOLFBOOT_LOAD_ADDRESS@/$(WOLFBOOT_LOAD_ADDRESS)/g" | \
654654
sed -e "s/@WOLFBOOT_LOAD_DTS_ADDRESS@/$(WOLFBOOT_LOAD_DTS_ADDRESS)/g" | \
655655
sed -e "s/@WOLFBOOT_LOAD_RAMDISK_ADDRESS@/$(WOLFBOOT_LOAD_RAMDISK_ADDRESS)/g" | \
656+
sed -e "s/@WOLFBOOT_LOAD_FPGA_ADDRESS@/$(WOLFBOOT_LOAD_FPGA_ADDRESS)/g" | \
656657
sed -e "s|@WOLFBOOT_RAMBOOT_MAX_SIZE_DEFINE@|$(if $(strip $(WOLFBOOT_RAMBOOT_MAX_SIZE)),#define WOLFBOOT_RAMBOOT_MAX_SIZE $(WOLFBOOT_RAMBOOT_MAX_SIZE),/* WOLFBOOT_RAMBOOT_MAX_SIZE undefined */)|g" | \
657658
sed -e "s/@WOLFBOOT_PARTITION_SELF_HEADER_ADDRESS@/$(WOLFBOOT_PARTITION_SELF_HEADER_ADDRESS)/g" \
658659
> $@

arch.mk

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ ifeq ($(ARCH),AARCH64)
7474
# Support detection and skip of U-Boot legacy header */
7575
CFLAGS+=-DWOLFBOOT_UBOOT_LEGACY
7676
CFLAGS+=-DWOLFBOOT_DUALBOOT
77+
# FPGA bitstream-from-FIT is supported via the PMU firmware
78+
# (PM_FPGA_LOAD). Enable with FPGA_BITSTREAM=1 (opt-in).
7779

7880
ifeq ($(HW_SHA3),1)
7981
# Use HAL for hash (see zynqmp.c)
@@ -90,6 +92,9 @@ ifeq ($(ARCH),AARCH64)
9092
CFLAGS+=-DWOLFBOOT_DUALBOOT
9193
# Support detection and skip of U-Boot legacy header
9294
CFLAGS+=-DWOLFBOOT_UBOOT_LEGACY
95+
# NOTE: FPGA_BITSTREAM is stubbed on Versal (PL config is a PDI loaded
96+
# by the PLM via XilLoader Load-PDI IPI - not yet implemented). Leave
97+
# FPGA_BITSTREAM off until that path lands.
9398
# PLM owns RVBAR on Versal in JTAG boot; skip RVBAR writes
9499
CFLAGS+=-DSKIP_RVBAR=1
95100
# Disable SDMA for multi-block transfers - use PIO instead.
@@ -350,6 +355,8 @@ ifeq ($(ARCH),ARM)
350355
# positive probability from ~2^-32 to ~2^-64, matching what U-Boot's
351356
# own mkimage/bootm does.
352357
CFLAGS+=-DWOLFBOOT_UBOOT_LEGACY
358+
# FPGA bitstream-from-FIT is supported via the DevC/PCAP DMA engine
359+
# (full bitstream). Enable with FPGA_BITSTREAM=1 (opt-in).
353360
endif
354361

355362
ifeq ($(TARGET),va416x0)

config/examples/zynqmp.config

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,14 @@ WOLFBOOT_LOAD_DTS_ADDRESS?=0x11800000
8181
WOLFBOOT_DTS_BOOT_ADDRESS?=0x7B0000
8282
WOLFBOOT_DTS_UPDATE_ADDRESS?=0x39B0000
8383

84+
# Optional: program the PL from an "fpga" sub-image in the FIT before boot
85+
# (handed to the PMU firmware via PM_FPGA_LOAD). Requires GZIP=1 when the
86+
# bitstream node uses compression="gzip" (the typical mkimage output). The
87+
# fpga node usually has no `load` property, so set a DDR staging address
88+
# clear of the FIT (0x10000000), kernel (0x200000), and DTS (0x11800000).
89+
#FPGA_BITSTREAM?=1
90+
#WOLFBOOT_LOAD_FPGA_ADDRESS?=0x40000000
91+
8492

8593
CROSS_COMPILE=aarch64-none-elf-
8694
#CROSS_COMPILE=aarch64-linux-gnu-

docs/Targets.md

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4070,6 +4070,63 @@ FDT: Set chosen (...), linux,initrd-start=1073741824
40704070
FDT: Set chosen (...), linux,initrd-end=...
40714071
```
40724072
4073+
**FPGA bitstream from FIT**
4074+
4075+
wolfBoot can program the PL (FPGA fabric) from an `fpga` sub-image carried in the same signed FIT, using the standard U-Boot convention: a sub-image with `type = "fpga"`, referenced from the configuration node via an optional `fpga = "<node>"` property, with a `compatible` string naming the load method. The PL is programmed before the kernel/DTB are loaded so PL-dependent clocks and peripherals come up first. The outer wolfBoot signature authenticates the whole FIT (bitstream included), so no per-image hashing is required.
4076+
4077+
Enable with `FPGA_BITSTREAM=1` (off by default). A failed PL load is fatal (`wolfBoot_panic`) unless `FPGA_NONFATAL=1` is also set, which downgrades it to a logged warning that continues the boot.
4078+
4079+
As produced by `mkimage`, the fpga sub-image is typically gzip-compressed (`compression = "gzip"`) and carries NO `load` property (U-Boot decompresses it into a scratch buffer before programming). wolfBoot mirrors this: set `WOLFBOOT_LOAD_FPGA_ADDRESS` to a DDR staging address (clear of the FIT at `WOLFBOOT_LOAD_ADDRESS`, the kernel, and the DTS), and the bitstream is decompressed there before the PL is programmed. Build with `GZIP=1` (already default in the example configs). If the fpga node does provide its own `load`, leave `WOLFBOOT_LOAD_FPGA_ADDRESS=0` to honor it.
4080+
4081+
```sh
4082+
cp config/examples/zynqmp.config .config
4083+
make FPGA_BITSTREAM=1 WOLFBOOT_LOAD_FPGA_ADDRESS=0x40000000
4084+
```
4085+
4086+
Per-target support:
4087+
- **ZynqMP** (`TARGET=zynq`): supported. The bitstream (a bootgen `.bin` with the `66 55 99 aa` sync word, not a Vivado `.bit`) is staged in DDR and handed to the PMU firmware via the `PM_FPGA_LOAD` EEMI call (xilfpga over the CSU DMA / PCAP). The size is passed in bytes and the flags are 0 for a full legacy bitstream, matching stock Xilinx U-Boot; no software byte-swap is applied.
4088+
- **Zynq-7000** (`TARGET=zynq7000`): supported (full bitstream). Programmed directly through the DevC/PCAP DMA engine (UG585 ch.6). Partial reconfiguration is not yet implemented.
4089+
- **Versal** (`TARGET=versal`): not yet implemented - Versal programs the PL with a PDI loaded by the PLM (XilLoader Load-PDI IPI), not a raw bitstream. `hal_fpga_load` is a stub; leave `FPGA_BITSTREAM` off on Versal until that path lands.
4090+
4091+
The `compatible` string selects full vs partial: any value containing `partial` requests partial reconfiguration, otherwise a full bitstream is loaded. Typical full-bitstream values are `u-boot,fpga-legacy`, `u-boot,zynqmp-fpga-ddrauth`, or `u-boot,zynqmp-fpga-enc`.
4092+
4093+
Decompressed-size validation: the fpga node carries no explicit uncompressed-size property, but for `compression = "gzip"` the gzip trailer encodes it. wolfBoot verifies the gzip CRC32 and ISIZE (decompressed length) on completion and bounds the output by `WOLFBOOT_FIT_MAX_FPGA`, so a truncated or corrupt bitstream is rejected (fatal, or skipped under `FPGA_NONFATAL=1`). The byte count handed to `PM_FPGA_LOAD` is the validated decompressed length. Note that `WOLFBOOT_FIT_MAX_FPGA` is a compile-time cap only (set it with `CFLAGS_EXTRA+=-DWOLFBOOT_FIT_MAX_FPGA=...`; it defaults to `WOLFBOOT_FIT_MAX_DECOMP`, 256 MB) - it is a sanity ceiling, NOT the size of your DDR staging region. It does not by itself stop the bitstream from overrunning the kernel/DTB/FIT areas, so choosing a `WOLFBOOT_LOAD_FPGA_ADDRESS` clear of those regions (and, if you want a tight bound, lowering `WOLFBOOT_FIT_MAX_FPGA` to your staging window) is the integrator's responsibility.
4094+
4095+
Multiple configurations: wolfBoot boots the FIT's `default` configuration. For a FIT that carries several boards' configurations selected at runtime (e.g. U-Boot's `bootm <addr>#conf-<board>`), build with `FIT_CONFIG_SELECT=1` and provide a `hal_fit_config_name()` in your integration that returns the config node name to boot (e.g. `"conf-fcm"`), or NULL to fall back to `default`. wolfBoot ships only the weak default (returns NULL) - the board-detection logic (PS GPIO, CHIPID, etc.) is intentionally left to the integrator and is not part of upstream.
4096+
4097+
Example FIT layout (matches `mkimage` output - gzip, no `load`):
4098+
4099+
```dts
4100+
images {
4101+
kernel-1 { ... };
4102+
fdt-1 { ... };
4103+
fpga-1 {
4104+
description = "FPGA bitstream";
4105+
data = /incbin/("system.bit.bin.gz"); /* gzip of bootgen .bin */
4106+
type = "fpga";
4107+
arch = "arm64"; /* informational; not read by wolfBoot */
4108+
compression = "gzip";
4109+
compatible = "u-boot,fpga-legacy";
4110+
hash-1 { algo = "sha256"; }; /* covered by outer sig */
4111+
};
4112+
};
4113+
configurations {
4114+
default = "conf-zcu102";
4115+
conf-zcu102 {
4116+
kernel = "kernel-1";
4117+
fdt = "fdt-1";
4118+
fpga = "fpga-1";
4119+
};
4120+
};
4121+
```
4122+
4123+
Successful programming prints (ZynqMP):
4124+
```
4125+
FIT: programming FPGA 'fpga-1' (N bytes, full)
4126+
FPGA status: 0x...
4127+
FIT: FPGA programmed
4128+
```
4129+
40734130
40744131
## Xilinx Zynq-7000 (ZC702)
40754132

hal/hal.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,3 +356,23 @@ WEAKFUNCTION int hal_dice_get_attest_pubkey(uint8_t *buf, size_t *len)
356356
return -1;
357357
}
358358
#endif /* WOLFBOOT_DICE_HW */
359+
360+
#ifdef WOLFBOOT_FPGA_BITSTREAM
361+
WEAKFUNCTION int hal_fpga_load(uint32_t flags, uintptr_t addr, size_t size)
362+
{
363+
/* No FPGA loader for this target; implement in the target hal. */
364+
(void)flags;
365+
(void)addr;
366+
(void)size;
367+
return -1;
368+
}
369+
#endif /* WOLFBOOT_FPGA_BITSTREAM */
370+
371+
#ifdef WOLFBOOT_FIT_CONFIG_SELECT
372+
WEAKFUNCTION const char* hal_fit_config_name(void)
373+
{
374+
/* Default: use the FIT's own `default` configuration. A target
375+
* implements this to select a per-board configuration at runtime. */
376+
return NULL;
377+
}
378+
#endif /* WOLFBOOT_FIT_CONFIG_SELECT */

hal/versal.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1354,6 +1354,25 @@ int RAMFUNCTION hal_flash_erase(uintptr_t address, int len)
13541354
return -1;
13551355
}
13561356

1357+
#ifdef WOLFBOOT_FPGA_BITSTREAM
1358+
/* Versal programs the PL with a PDI (Programmable Device Image), not a raw
1359+
* bitstream. Runtime PL configuration is done by the PLM via the XilLoader
1360+
* "Load PDI" command (XLOADER_CMD_ID_LOAD_PDI), reached by building an IPI
1361+
* request to the PLM channel with the DDR PDI address/size and polling the
1362+
* PLM response. That path is not yet implemented; until it lands, leave
1363+
* FPGA_BITSTREAM disabled for Versal (the FIT loader treats a failed load
1364+
* as fatal unless FPGA_NONFATAL is set). */
1365+
int hal_fpga_load(uint32_t flags, uintptr_t addr, size_t size)
1366+
{
1367+
(void)flags;
1368+
(void)addr;
1369+
(void)size;
1370+
wolfBoot_printf("Versal FPGA/PDI load not implemented "
1371+
"(needs PLM XilLoader Load-PDI IPI)\n");
1372+
return -1;
1373+
}
1374+
#endif /* WOLFBOOT_FPGA_BITSTREAM */
1375+
13571376

13581377
/* ============================================================================
13591378
* External Flash Interface

hal/versal.its

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,38 @@
2929
algo = "sha256";
3030
};
3131
};
32+
/* FPGA bitstream sub-image (requires FPGA_BITSTREAM=1). Add the
33+
* "fpga = ..." reference to the configuration node below. The
34+
* bitstream must be a bootgen .bin staged to its load address.
35+
* NOTE: Versal PL config is a PDI loaded by the PLM (XilLoader
36+
* Load-PDI IPI) - the wolfBoot Versal hal_fpga_load is currently
37+
* a stub, so leave this disabled on Versal. On ZynqMP/Zynq-7000
38+
* this is the working convention.
39+
*
40+
* As emitted by mkimage the fpga node is usually gzip-compressed
41+
* and has no "load" property; set WOLFBOOT_LOAD_FPGA_ADDRESS to a
42+
* DDR staging address and build with GZIP=1.
43+
*
44+
* fpga-1 {
45+
* description = "FPGA bitstream";
46+
* data = /incbin/("../system.bit.bin.gz");
47+
* type = "fpga";
48+
* arch = "arm64";
49+
* compression = "gzip";
50+
* compatible = "u-boot,fpga-legacy";
51+
* hash-1 {
52+
* algo = "sha256";
53+
* };
54+
* };
55+
*/
3256
};
3357
configurations {
3458
default = "conf1";
3559
conf1 {
3660
description = "Linux kernel and FDT blob";
3761
kernel = "kernel-1";
3862
fdt = "fdt-1";
63+
/* fpga = "fpga-1"; */
3964
hash-1 {
4065
algo = "sha256";
4166
};

hal/zynq.c

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,13 @@ static void smc_call(struct pt_regs *args)
197197
#define PM_MMIO_WRITE 0x13
198198
#define PM_MMIO_READ 0x14
199199

200+
/* FPGA / PL programming (xilfpga via PMU firmware / TF-A) */
201+
#define PM_FPGA_LOAD 0x16 /* 22 */
202+
#define PM_FPGA_GET_STATUS 0x17 /* 23 */
203+
/* pm_fpga_load flags (bit 0 selects full vs partial bitstream) */
204+
#define XFPGA_FULLBIT_EN 0x0
205+
#define XFPGA_PARTIAL_EN 0x1
206+
200207
/* AES */
201208
/* requires PMU built with -DENABLE_SECURE_VAL=1 */
202209
#define PM_SECURE_AES 0x2F
@@ -1713,6 +1720,45 @@ int RAMFUNCTION hal_flash_erase(uintptr_t address, int len)
17131720
return 0;
17141721
}
17151722

1723+
#ifdef WOLFBOOT_FPGA_BITSTREAM
1724+
/* Program the PL by handing the bitstream to the PMU firmware (xilfpga)
1725+
* via the PM_FPGA_LOAD EEMI call. The bitstream must be a bootgen .bin
1726+
* resident in DDR; it is flushed from the D-cache so the CSU DMA sees
1727+
* the committed bytes. */
1728+
int hal_fpga_load(uint32_t flags, uintptr_t addr, size_t size)
1729+
{
1730+
uint32_t ret_payload[PM_ARGS_CNT];
1731+
uint32_t pmflags;
1732+
1733+
/* PM_FPGA_LOAD takes the bitstream size in BYTES (the PMU firmware
1734+
* divides by the word length internally for the CSU DMA). This
1735+
* matches stock Xilinx U-Boot (drivers/fpga/zynqmppl.c passes
1736+
* bsize verbatim). For a legacy full bitstream the flags argument
1737+
* is 0; bit 0 selects partial. */
1738+
pmflags = (flags == HAL_FPGA_PARTIAL) ? XFPGA_PARTIAL_EN : XFPGA_FULLBIT_EN;
1739+
1740+
/* Ensure the bitstream is committed to DDR before the CSU DMA reads it. */
1741+
flush_dcache_range((unsigned long)addr, (unsigned long)(addr + size));
1742+
1743+
memset(ret_payload, 0, sizeof(ret_payload));
1744+
/* arg0=addr_low, arg1=addr_high, arg2=size(bytes), arg3=flags */
1745+
pmu_request(PM_FPGA_LOAD,
1746+
(uint32_t)(addr & 0xFFFFFFFF), (uint32_t)((uint64_t)addr >> 32),
1747+
(uint32_t)size, pmflags, ret_payload);
1748+
if (ret_payload[0] != 0) {
1749+
wolfBoot_printf("PM_FPGA_LOAD failed: %u\n", ret_payload[0]);
1750+
return -1;
1751+
}
1752+
1753+
/* Confirm the PL reports configured (PCAP status). */
1754+
memset(ret_payload, 0, sizeof(ret_payload));
1755+
pmu_request(PM_FPGA_GET_STATUS, 0, 0, 0, 0, ret_payload);
1756+
wolfBoot_printf("FPGA status: 0x%x\n", ret_payload[1]);
1757+
1758+
return 0;
1759+
}
1760+
#endif /* WOLFBOOT_FPGA_BITSTREAM */
1761+
17161762
/* Xilinx Write uses SPI mode and Page Program 0x02 */
17171763
/* Issues using write with QSPI mode */
17181764
int RAMFUNCTION ext_flash_write(uintptr_t address, const uint8_t *data, int len)

hal/zynq7000.c

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -871,6 +871,122 @@ uint64_t hal_get_timer_us(void)
871871
return (count * 1000000ULL) / (uint64_t)Z7_GTIMER_FREQ_HZ;
872872
}
873873

874+
#ifdef WOLFBOOT_FPGA_BITSTREAM
875+
/* PL programming timeout (microseconds). */
876+
#ifndef Z7_FPGA_TIMEOUT_US
877+
#define Z7_FPGA_TIMEOUT_US 1000000ULL /* 1 second */
878+
#endif
879+
880+
/* Clean the D-cache over [start, start+len) by MVA so the DevC DMA sees
881+
* the committed bitstream bytes (DCCMVAC, L1 line = 32B). Mirrors the
882+
* SDMA coherency path. */
883+
static void z7_dcache_clean_range(uintptr_t start, uint32_t len)
884+
{
885+
uintptr_t addr;
886+
uintptr_t end = (start + len + 31U) & ~31U;
887+
start &= ~31U;
888+
for (addr = start; addr < end; addr += 32U) {
889+
__asm__ volatile("mcr p15, 0, %0, c7, c10, 1" : : "r"(addr) : "memory");
890+
}
891+
__asm__ volatile("dsb sy" : : : "memory");
892+
}
893+
894+
/* Program the PL from a bootgen .bin bitstream resident in DDR using the
895+
* DevC PCAP DMA engine (UG585 ch.6 / Xilinx XDcfg full-bitstream flow).
896+
* Only the full-bitstream path is implemented; partial reconfiguration
897+
* returns an error. */
898+
int hal_fpga_load(uint32_t flags, uintptr_t addr, size_t size)
899+
{
900+
uint32_t sts;
901+
uint32_t words = (uint32_t)((size + 3U) / 4U);
902+
uint64_t t0;
903+
904+
if (flags == HAL_FPGA_PARTIAL) {
905+
/* Partial reconfig leaves PROG_B asserted and routes via PCAP_PR;
906+
* not implemented in this initial full-bitstream path. */
907+
wolfBoot_printf("Z7 FPGA: partial reconfig not implemented\n");
908+
return -1;
909+
}
910+
if (addr > 0xFFFFFFFFU || size == 0) {
911+
return -1;
912+
}
913+
/* The DevC DMA descriptor encodes the "last" flag in the source
914+
* address LSB, so the bitstream buffer must be word-aligned. */
915+
if ((addr & 0x3U) != 0U) {
916+
wolfBoot_printf("Z7 FPGA: bitstream addr not word-aligned\n");
917+
return -1;
918+
}
919+
920+
/* 1. Unlock DevC and select PCAP (not ICAP). */
921+
Z7_DEVC_UNLOCK = Z7_DEVC_UNLOCK_KEY;
922+
Z7_DEVC_CTRL |= (Z7_DEVC_CTRL_PCAP_MODE | Z7_DEVC_CTRL_PCAP_PR);
923+
/* Disable internal PCAP loopback. */
924+
Z7_DEVC_MCTRL &= ~Z7_DEVC_MCTRL_PCAP_LPBK;
925+
926+
/* 2. Clear sticky interrupts. */
927+
Z7_DEVC_INT_STS = Z7_DEVC_INT_ALL;
928+
929+
/* 3. Pulse PROG_B low then high to clear the PL (full bitstream). */
930+
Z7_DEVC_CTRL &= ~Z7_DEVC_CTRL_PCFG_PROG_B;
931+
t0 = hal_get_timer_us();
932+
while (Z7_DEVC_STATUS & Z7_DEVC_STATUS_PCFG_INIT) {
933+
if (hal_get_timer_us() - t0 > Z7_FPGA_TIMEOUT_US) {
934+
wolfBoot_printf("Z7 FPGA: timeout waiting PCFG_INIT clear\n");
935+
return -1;
936+
}
937+
}
938+
Z7_DEVC_CTRL |= Z7_DEVC_CTRL_PCFG_PROG_B;
939+
t0 = hal_get_timer_us();
940+
while (!(Z7_DEVC_STATUS & Z7_DEVC_STATUS_PCFG_INIT)) {
941+
if (hal_get_timer_us() - t0 > Z7_FPGA_TIMEOUT_US) {
942+
wolfBoot_printf("Z7 FPGA: timeout waiting PCFG_INIT set\n");
943+
return -1;
944+
}
945+
}
946+
947+
/* 4. Clear interrupts. */
948+
Z7_DEVC_INT_STS = Z7_DEVC_INT_ALL;
949+
950+
/* 5. Make the bitstream coherent in DDR for the DMA. Clean the same
951+
* rounded-up word length the DMA reads (words * 4), not just the
952+
* byte size, so a non-word-aligned tail is covered. (Xilinx .bin
953+
* bitstreams are word streams, so this normally equals size.) */
954+
z7_dcache_clean_range(addr, words * 4U);
955+
956+
/* 6. Program the DMA: src = DDR bitstream (LSB=1 marks last descriptor),
957+
* dst = PCAP sentinel. Lengths are in 32-bit words. */
958+
Z7_DEVC_DMA_SRC = ((uint32_t)addr) | Z7_DEVC_DMA_LAST;
959+
Z7_DEVC_DMA_DST = Z7_DEVC_DMA_DEST_PCAP;
960+
Z7_DEVC_DMA_SRC_LEN = words;
961+
Z7_DEVC_DMA_DST_LEN = words;
962+
963+
/* 7. Wait for DMA done (and check error bits). */
964+
t0 = hal_get_timer_us();
965+
do {
966+
sts = Z7_DEVC_INT_STS;
967+
if (sts & Z7_DEVC_INT_ERR_MASK) {
968+
wolfBoot_printf("Z7 FPGA: DMA error, INT_STS=0x%x\n", sts);
969+
return -1;
970+
}
971+
if (hal_get_timer_us() - t0 > Z7_FPGA_TIMEOUT_US) {
972+
wolfBoot_printf("Z7 FPGA: timeout waiting DMA done\n");
973+
return -1;
974+
}
975+
} while (!(sts & Z7_DEVC_INT_DMA_DONE));
976+
977+
/* 8. Wait for the PL to report configuration complete. */
978+
t0 = hal_get_timer_us();
979+
while (!(Z7_DEVC_INT_STS & Z7_DEVC_INT_PCFG_DONE)) {
980+
if (hal_get_timer_us() - t0 > Z7_FPGA_TIMEOUT_US) {
981+
wolfBoot_printf("Z7 FPGA: timeout waiting PCFG_DONE\n");
982+
return -1;
983+
}
984+
}
985+
986+
return 0;
987+
}
988+
#endif /* WOLFBOOT_FPGA_BITSTREAM */
989+
874990
#if defined(DISK_SDCARD) || defined(DISK_EMMC)
875991
/* ============================================================================
876992
* SDHCI (SD Card / eMMC) Platform Support

0 commit comments

Comments
 (0)