From a2e91d975776508aba4ae9e189b761ce430163b6 Mon Sep 17 00:00:00 2001 From: David Garske Date: Thu, 20 Aug 2026 12:31:05 -0400 Subject: [PATCH 1/2] zynq: add ZYNQMP_PHY_OP_DELAY step for PHY post-reset settle time --- hal/zynq.c | 11 +++++++++++ hal/zynq.h | 2 ++ 2 files changed, 13 insertions(+) diff --git a/hal/zynq.c b/hal/zynq.c index 0cad42d104..d1ebac3b28 100644 --- a/hal/zynq.c +++ b/hal/zynq.c @@ -1998,6 +1998,11 @@ void hal_delay_ms(uint64_t ms) } } +/* Fallback if CNTFRQ_EL0 is unset (no ATF/BL31); ZynqMP counter is 100 MHz */ +#ifndef ZYNQMP_TIMER_CLK_FREQ +#define ZYNQMP_TIMER_CLK_FREQ 100000000ULL +#endif + uint64_t hal_timer_ms(void) { uint64_t val; @@ -2005,6 +2010,9 @@ uint64_t hal_timer_ms(void) unsigned long cntpct; asm volatile("mrs %0, cntfrq_el0" : "=r" (cntfrq)); asm volatile("mrs %0, cntpct_el0" : "=r" (cntpct)); + /* AArch64 UDIV by 0 yields 0, which would hang hal_delay_ms() */ + if (cntfrq == 0) + cntfrq = ZYNQMP_TIMER_CLK_FREQ; val = cntpct * 1000; val /= cntfrq; return val; @@ -2169,6 +2177,9 @@ static void zynq_phy_init(void) (int)steps[i].arg0, (int)rval); } break; + case ZYNQMP_PHY_OP_DELAY: + hal_delay_ms(steps[i].arg1); + break; default: break; } diff --git a/hal/zynq.h b/hal/zynq.h index 9e6661e965..33c4ef1a9c 100644 --- a/hal/zynq.h +++ b/hal/zynq.h @@ -501,6 +501,8 @@ #define ZYNQMP_PHY_OP_GPIO 0 /* write arg1 to ZYNQMP_PHY_GPIO_ADDR */ #define ZYNQMP_PHY_OP_WR 1 /* MDIO write: reg=arg0, val=arg1 */ #define ZYNQMP_PHY_OP_RD 2 /* MDIO read: reg=arg0 (arg1 ignored) */ +#define ZYNQMP_PHY_OP_DELAY 3 /* delay arg1 ms, max 65535 (arg0 + * ignored); e.g. PHY reset settle */ /* Default sequence: read the PHY ID registers (2, 3) as a diagnostic. With * DEBUG_UART=1 this prints the ID and confirms MDIO reached the PHY. Override From 3bebade37deb045127b2cec54590b51ff088327d Mon Sep 17 00:00:00 2001 From: David Garske Date: Thu, 20 Aug 2026 12:31:05 -0400 Subject: [PATCH 2/2] zynq: provide hal_get_timer_us for BOOT_BENCHMARK/UPDATE_DISK builds without MMU, avoiding libgcc 128-bit division in the test-app link --- .github/workflows/test-configs.yml | 9 +++++++++ hal/zynq.c | 30 ++++++++++++++++-------------- 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/.github/workflows/test-configs.yml b/.github/workflows/test-configs.yml index 2342589dc5..23915d06ed 100644 --- a/.github/workflows/test-configs.yml +++ b/.github/workflows/test-configs.yml @@ -866,6 +866,15 @@ jobs: config-file: ./config/examples/zynqmp.config make-args: CFLAGS_EXTRA=-DWOLFBOOT_ZYNQMP_PHY_INIT + zynqmp_phy_delay_test: + uses: ./.github/workflows/test-build-aarch64.yml + with: + arch: aarch64 + config-file: ./config/examples/zynqmp.config + # Exercise a custom step list using every op (GPIO, WR, RD, DELAY) + # plus BOOT_BENCHMARK's hal_get_timer_us dependency. + make-args: BOOT_BENCHMARK=1 CFLAGS_EXTRA="-DWOLFBOOT_ZYNQMP_PHY_INIT -DZYNQMP_PHY_INIT_STEPS={ZYNQMP_PHY_OP_GPIO,0,1},{ZYNQMP_PHY_OP_DELAY,0,10},{ZYNQMP_PHY_OP_WR,0x1E,0x0819},{ZYNQMP_PHY_OP_RD,0x1F,0}" + zynq7000_test: uses: ./.github/workflows/test-build.yml with: diff --git a/hal/zynq.c b/hal/zynq.c index d1ebac3b28..09c2331416 100644 --- a/hal/zynq.c +++ b/hal/zynq.c @@ -2584,17 +2584,11 @@ void RAMFUNCTION ext_flash_unlock(void) } -/* The following helpers (hal_get_timer_us, hal_get_dts_address, hal_dts_fixup) - * are only compiled into the wolfBoot binary. The test-app build also links - * hal/zynq.o but must not pull in FDT/MMU-specific code, so __WOLFBOOT gates - * these symbols out of that build. */ -#if defined(MMU) && defined(__WOLFBOOT) -/* Fallback timer frequency if CNTFRQ_EL0 is not configured (e.g. boot path - * that did not run ATF/BL31). ZynqMP system counter is 100 MHz. */ -#ifndef ZYNQMP_TIMER_CLK_FREQ -#define ZYNQMP_TIMER_CLK_FREQ 100000000ULL -#endif - +/* hal_get_timer_us serves the BENCHMARK_* macros and update_disk + * (include/hal.h); the extra gate terms keep it available to every build + * variant that can reference it, including the test-app link. */ +#if (defined(MMU) && defined(__WOLFBOOT)) || \ + defined(WOLFBOOT_UPDATE_DISK) || defined(BOOT_BENCHMARK) /* Get current time in microseconds using ARMv8 generic timer */ uint64_t hal_get_timer_us(void) { @@ -2606,10 +2600,18 @@ uint64_t hal_get_timer_us(void) * (matches hal/versal.c). */ if (freq == 0) freq = ZYNQMP_TIMER_CLK_FREQ; - /* Use __uint128_t to avoid overflow of (count * 1e6) at long uptimes - * (would overflow uint64_t after ~51h at 100MHz). */ - return (uint64_t)(((__uint128_t)count * 1000000ULL) / freq); + /* Split divide: no (count * 1e6) uint64 overflow at long uptimes and + * no libgcc 128-bit helper (__udivti3) in links without one */ + return (count / freq) * 1000000ULL + + ((count % freq) * 1000000ULL) / freq; } +#endif /* (MMU && __WOLFBOOT) || WOLFBOOT_UPDATE_DISK || BOOT_BENCHMARK */ + +/* The following helpers (hal_get_dts_address, hal_dts_fixup) are only + * compiled into the wolfBoot binary. The test-app build also links + * hal/zynq.o but must not pull in FDT/MMU-specific code, so __WOLFBOOT gates + * these symbols out of that build. */ +#if defined(MMU) && defined(__WOLFBOOT) void* hal_get_dts_address(void) {