Skip to content

ZynqMP ZCU102 SD-card Linux boot: EL2 handoff, SDHCI init, QSPI hardening - #750

Merged
danielinux merged 5 commits into
wolfSSL:masterfrom
dgarske:zynqmp_bb
Apr 28, 2026
Merged

ZynqMP ZCU102 SD-card Linux boot: EL2 handoff, SDHCI init, QSPI hardening#750
danielinux merged 5 commits into
wolfSSL:masterfrom
dgarske:zynqmp_bb

Conversation

@dgarske

@dgarske dgarske commented Apr 14, 2026

Copy link
Copy Markdown
Member

End-to-end fixes for booting Linux from an SD card on the ZynqMP ZCU102
with wolfBoot at EL2, plus QSPI-boot and large-FIT hardening uncovered
during bring-up.

EL2 handoff

  • Cache/MMU teardown (src/boot_aarch64_start.S): new
    el2_flush_and_disable_mmu cleans D-cache to PoC, invalidates I-cache
    to PoU, clears SCTLR_EL2.{M,C,I}. Required by the ARM64 Linux boot
    protocol. Called from do_boot() on the EL2 direct-jump path.
  • Config (config/examples/zynqmp_sdcard.config): default to EL2
    (comment out BOOT_EL1) to match the PetaLinux U-Boot flow and
    preserve KVM/hypervisor use of EL2.

Device-tree fixups

  • hal_dts_fixup() (hal/zynq.c): inject /chosen/bootargs from
    LINUX_BOOTARGS; grow DTB totalsize by 512 bytes for
    fdt_setprop() headroom. Only defined when MMU && __WOLFBOOT.
  • hal_get_timer_us(): ARMv8 generic-timer read via CNTPCT_EL0
    with a 100 MHz fallback when CNTFRQ_EL0 is not programmed.

SDHCI reliability

  • Settling delay after platform init + CMD0 retry loop (up to 10×10 ms)
    so the Arasan controller consistently detects the card after the
    slot-type change / soft reset.
  • SDHCI_DMA_THRESHOLD lowered to 4 KB so multi-block reads use SDMA
    instead of PIO, sidestepping the Arasan BRR re-poll race under
    -Os/-O2.
  • SDHCI_DMA_BUFF_BOUNDARY auto-derived from the threshold; documented
    override uses the raw register value (0x7000) so it is safe inside
    #if expressions.

QSPI hardening (hal/zynq.c)

  • New qspi_flash_reset() (0x66 RESET_ENABLE + 0x99 RESET_MEMORY)
    per chip in qspi_init, so the flash starts from a known state
    regardless of what FSBL/BootROM left behind (XIP, 4-byte addressing,
    auto-boot probing).
  • IOU_TAPDLY_BYPASS writes now route through pmu_request at EL≤2 in
    the ≤40 MHz and ≤100 MHz branches (previously only the ≤150 MHz
    branch handled this); the register is equally unwritable from EL2/EL1
    at lower clocks.

Linker layout (hal/zynq.ld)

  • ORIGIN moved from 0x080000000x10000000 with a 2 MB
    reservation. Kernels loaded at 0x00200000 with payloads >~126 MB
    would otherwise memcpy across 0x08000000 and clobber wolfBoot's own
    .text during handoff.
  • WOLFBOOT_ORIGIN in config/examples/zynqmp_sdcard.config aligned to
    0x10000000 to match the linker (so factory.bin/factory.srec
    encode the correct load address).

TRACE32 tooling (tools/scripts/zcu102/zcu102-ca53-qspi.cmm)

  • Rewritten against the Lauterbach ZCU102 QSPI demo: PREPAREONLY
    entry, single/dual toggle, READ_ID_TEST for single-flash variants,
    separate dialogs for BOOT.BIN at offset 0 and
    test-app/image_v1_signed.bin at the partition boot address.
  • Documented the ~128 MB TRACE32 temp-memory ceiling on
    FLASHFILE.Create: larger files must be split externally (e.g. via
    dd) and loaded in chunks.

Versal alignment

  • hal/versal.c default LINUX_BOOTARGS_ROOT restored to
    /dev/mmcblk0p2 (matching the prior Versal layout); a comment points
    to /dev/mmcblk0p4 for configs using the 4-partition OFP_A/OFP_B
    layout.
  • hal_dts_fixup() no longer masks fdt_find_node_offset errors —
    only -FDT_ERR_NOTFOUND falls through to fdt_add_subnode()
    (applied to both hal/zynq.c and hal/versal.c).

Docs (docs/Targets.md)

  • SDHCI notes (SDMA vs PIO, HV4E redirect, card-detect, block size),
    EL2 cleanup behavior for ZynqMP and Versal SD-card sections.

Behavior changes

  • EL2 payloads now enter with MMU off and caches clean instead of
    inheriting wolfBoot's translation tables. No in-tree payload relies
    on the old state leakage.
  • SDHCI_DMA_THRESHOLD lowered to 4 KB (was 512 KB): virtually all
    multi-block reads go through SDMA.
  • ZynqMP config defaults to EL2 (was EL1).
  • wolfBoot linker ORIGIN is 0x10000000 (was 0x08000000) on
    hal/zynq.ld; WOLFBOOT_ORIGIN in zynqmp_sdcard.config follows.

Verification

  • Boots Linux end-to-end on ZCU102 SD-card; UART shows
    Load address 0x10000000, kernel brings up rootfs on
    /dev/mmcblk0p4.
  • CI builds: zynqmp.config, zynqmp_sdcard.config,
    versal_vmk180.config, versal_vmk180_sdcard.config all build clean
    (via .github/workflows/test-configs.yml).

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Later It won't be fixed in the upcoming release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants