mirror of https://github.com/wolfSSL/wolfBoot.git
Support for wolfBoot ZynqMP (UltraScale+ MPSoC) SD Card
parent
3ef250cb33
commit
ff8bb8336c
|
|
@ -343,3 +343,4 @@ image.ub
|
|||
*.pdi
|
||||
system-default.dtb
|
||||
test_output/
|
||||
sdcard.img
|
||||
|
|
|
|||
1
arch.mk
1
arch.mk
|
|
@ -78,6 +78,7 @@ ifeq ($(ARCH),AARCH64)
|
|||
HASH_HAL=1
|
||||
CFLAGS+=-DWOLFBOOT_ZYNQMP_CSU
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
ifeq ($(TARGET),versal)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,113 @@
|
|||
# wolfBoot configuration for AMD ZynqMP ZCU102 - SD Card Boot
|
||||
# Zynq UltraScale+ MPSoC ZU9EG - Quad-core ARM Cortex-A53
|
||||
#
|
||||
# This configuration enables SD card boot for the ZynqMP:
|
||||
# FSBL -> PMUFW -> BL31 (EL3) -> wolfBoot (EL2) -> Linux (EL1)
|
||||
#
|
||||
# wolfBoot loads firmware images from MBR partitions on SD card.
|
||||
# Uses the generic SDHCI driver with SD1 controller (external SD slot on ZCU102).
|
||||
|
||||
ARCH?=AARCH64
|
||||
TARGET?=zynq
|
||||
|
||||
WOLFBOOT_VERSION?=0
|
||||
|
||||
# RSA 4096-bit with SHA3-384 (matching existing zynqmp.config)
|
||||
SIGN?=RSA4096
|
||||
HASH?=SHA3
|
||||
IMAGE_HEADER_SIZE?=1024
|
||||
|
||||
# Debug options
|
||||
DEBUG?=1
|
||||
DEBUG_SYMBOLS=1
|
||||
DEBUG_UART=1
|
||||
CFLAGS_EXTRA+=-DDEBUG_ZYNQ=1
|
||||
|
||||
# SD card support - use SDHCI driver
|
||||
DISK_SDCARD?=1
|
||||
DISK_EMMC?=0
|
||||
# ZynqMP Arasan SDHCI does not support CDSS/CDTL card detect test level.
|
||||
# Since FSBL booted from the same SD card, we know it is present.
|
||||
CFLAGS_EXTRA+=-DSDHCI_FORCE_CARD_DETECT
|
||||
# Note: Arasan SDHCI v3.0 does not support HV4E mode. The platform layer
|
||||
# in hal/zynq.c transparently redirects SRS22/SRS23 to SRS00 for legacy SDMA.
|
||||
|
||||
# Disable QSPI flash when using SD card
|
||||
EXT_FLASH?=0
|
||||
NO_XIP=1
|
||||
|
||||
# ELF loading support
|
||||
ELF?=1
|
||||
|
||||
# Boot Exception Level: transition from EL2 -> EL1 before jumping to app
|
||||
BOOT_EL1?=1
|
||||
|
||||
# General options
|
||||
VTOR?=1
|
||||
CORTEX_M0?=0
|
||||
NO_ASM?=0
|
||||
ALLOW_DOWNGRADE?=0
|
||||
NVM_FLASH_WRITEONCE?=0
|
||||
V?=0
|
||||
SPMATH?=1
|
||||
RAM_CODE?=0
|
||||
DUALBANK_SWAP?=0
|
||||
PKA?=0
|
||||
WOLFTPM?=0
|
||||
|
||||
# Toolchain
|
||||
USE_GCC=1
|
||||
CROSS_COMPILE=aarch64-none-elf-
|
||||
|
||||
# ============================================================================
|
||||
# Partition Layout - MBR
|
||||
# ============================================================================
|
||||
# SD Card partition layout (MBR):
|
||||
# Partition 1: boot (128MB, FAT32 LBA, bootable) - BOOT.BIN
|
||||
# Partition 2: OFP_A (200MB, Linux) - Primary signed image
|
||||
# Partition 3: OFP_B (200MB, Linux) - Update signed image
|
||||
# Partition 4: rootfs (remainder) - Linux root filesystem
|
||||
#
|
||||
# Use partition numbers instead of flash addresses
|
||||
# These are 0-based indices into the parsed partition array:
|
||||
# part[0]=boot, part[1]=OFP_A, part[2]=OFP_B, part[3]=rootfs
|
||||
WOLFBOOT_NO_PARTITIONS=1
|
||||
CFLAGS_EXTRA+=-DBOOT_PART_A=1
|
||||
CFLAGS_EXTRA+=-DBOOT_PART_B=2
|
||||
|
||||
# Disk read chunk size (512KB)
|
||||
CFLAGS_EXTRA+=-DDISK_BLOCK_SIZE=0x80000
|
||||
|
||||
# Linux rootfs is on partition 4 (SD1 = mmcblk1)
|
||||
CFLAGS_EXTRA+=-DLINUX_BOOTARGS_ROOT=\"/dev/mmcblk1p4\"
|
||||
|
||||
# ============================================================================
|
||||
# Boot Memory Layout
|
||||
# ============================================================================
|
||||
# wolfBoot runs from DDR at 0x8000000 (same as U-Boot, loaded via BL31)
|
||||
WOLFBOOT_ORIGIN=0x8000000
|
||||
|
||||
# Load Partition to RAM Address (Linux kernel loads here)
|
||||
WOLFBOOT_LOAD_ADDRESS?=0x10000000
|
||||
|
||||
# DTS (Device Tree) load address
|
||||
WOLFBOOT_LOAD_DTS_ADDRESS?=0x1000
|
||||
|
||||
# ============================================================================
|
||||
# Required for test-app (even with WOLFBOOT_NO_PARTITIONS=1)
|
||||
# ============================================================================
|
||||
WOLFBOOT_PARTITION_BOOT_ADDRESS=0x80200000
|
||||
WOLFBOOT_PARTITION_SIZE=0x4000000
|
||||
WOLFBOOT_SECTOR_SIZE=0x1000
|
||||
|
||||
# ============================================================================
|
||||
# Optional Debug Options (uncomment to enable)
|
||||
# ============================================================================
|
||||
# SDHCI driver debug logs
|
||||
#CFLAGS_EXTRA+=-DDEBUG_SDHCI
|
||||
# Disk layer debug logs
|
||||
#CFLAGS_EXTRA+=-DDEBUG_DISK
|
||||
# GPT partition debug logs
|
||||
#CFLAGS_EXTRA+=-DDEBUG_GPT
|
||||
# Disk read/write test at boot
|
||||
#CFLAGS_EXTRA+=-DDISK_TEST
|
||||
236
docs/Targets.md
236
docs/Targets.md
|
|
@ -1984,28 +1984,50 @@ qemu-system-aarch64 -M raspi3b -m 1024 -serial stdio -kernel wolfboot_linux_rasp
|
|||
|
||||
## Xilinx Zynq UltraScale
|
||||
|
||||
Xilinx UltraScale+ ZCU102 (Aarch64)
|
||||
AMD Zynq UltraScale+ MPSoC ZCU102 Evaluation Kit - Quad-core ARM Cortex-A53 (plus dual Cortex-R5).
|
||||
|
||||
See example .config file at `config/examples/zynqmp.config`.
|
||||
|
||||
Example build options (.config):
|
||||
wolfBoot replaces U-Boot in the ZynqMP boot flow:
|
||||
```
|
||||
TARGET=zynq
|
||||
ARCH=AARCH64
|
||||
SIGN=RSA4096
|
||||
HASH=SHA3
|
||||
FSBL -> PMUFW -> BL31 (EL3) -> wolfBoot (EL2) -> Linux (EL1)
|
||||
```
|
||||
|
||||
### Building Zynq with Xilinx tools (Vitis IDE)
|
||||
wolfBoot runs from DDR at `0x8000000` (128MB, EL2, non-secure) for both QSPI and SD card boot. All clock, MIO, and DDR initialization is handled by the FSBL/PMUFW before wolfBoot starts.
|
||||
|
||||
This target supports **two boot paths**:
|
||||
- **QSPI boot** (primary, production-style): `config/examples/zynqmp.config`
|
||||
- **SD card boot** (MBR, A/B images): `config/examples/zynqmp_sdcard.config`
|
||||
|
||||
### Prerequisites
|
||||
|
||||
1. **Xilinx Vitis 2024.1 or newer**
|
||||
- Set `VITIS_PATH` environment variable: `export VITIS_PATH=/opt/Xilinx/Vitis/2024.1`
|
||||
2. **Toolchain**: `aarch64-none-elf-gcc`
|
||||
3. **Pre-built firmware** (FSBL, PMUFW, BL31):
|
||||
```sh
|
||||
git clone --branch xlnx_rel_v2024.2 https://github.com/Xilinx/soc-prebuilt-firmware.git
|
||||
export PREBUILT_DIR=$(pwd)/../soc-prebuilt-firmware/zcu102-zynqmp
|
||||
```
|
||||
|
||||
### Configuration Options
|
||||
|
||||
Key configuration options:
|
||||
|
||||
- `ARCH=AARCH64` - ARM 64-bit architecture
|
||||
- `TARGET=zynq` - ZynqMP platform target
|
||||
- `SIGN=RSA4096` - RSA 4096-bit signatures
|
||||
- `HASH=SHA3` - SHA3-384 hashing
|
||||
- `ELF=1` - ELF loading support
|
||||
|
||||
### Building with Xilinx tools (Vitis IDE)
|
||||
|
||||
See [IDE/XilinxSDK/README.md](/IDE/XilinxSDK/README.md) for using Xilinx IDE
|
||||
|
||||
### Building Zynq with gcc-aarch64-linux-gnu
|
||||
### Building with gcc-aarch64-linux-gnu
|
||||
|
||||
Requires `gcc-aarch64-linux-gnu` package.
|
||||
Use `make CROSS_COMPILE=aarch64-linux-gnu-`
|
||||
|
||||
### Building Zynq with QNX
|
||||
### Building with QNX
|
||||
|
||||
```sh
|
||||
source ~/qnx700/qnxsdp-env.sh
|
||||
|
|
@ -2014,17 +2036,196 @@ make clean
|
|||
make CROSS_COMPILE=aarch64-unknown-nto-qnx7.0.0-
|
||||
```
|
||||
|
||||
#### Testing Zynq with QEMU
|
||||
### QSPI Boot (default)
|
||||
|
||||
Use `config/examples/zynqmp.config`.
|
||||
|
||||
```sh
|
||||
cp config/examples/zynqmp.config .config
|
||||
make clean
|
||||
make
|
||||
```
|
||||
|
||||
**QSPI layout**
|
||||
| Partition | Size | Address | Description |
|
||||
|-------------|--------|-------------|--------------------------------|
|
||||
| Bootloader | - | 0x8000000 | wolfBoot in DDR (loaded by FSBL) |
|
||||
| Primary | 42MB | 0x800000 | Boot partition in QSPI |
|
||||
| Update | 42MB | 0x3A00000 | Update partition in QSPI |
|
||||
| Swap | - | 0x63E0000 | Swap area in QSPI |
|
||||
|
||||
**Build BOOT.BIN for QSPI**
|
||||
|
||||
See [IDE/XilinxSDK/README.md](/IDE/XilinxSDK/README.md) for creating BOOT.BIN with the Xilinx IDE, or use the existing BIF file:
|
||||
|
||||
```sh
|
||||
cp ${PREBUILT_DIR}/zynqmp_fsbl.elf .
|
||||
cp ${PREBUILT_DIR}/pmufw.elf .
|
||||
cp ${PREBUILT_DIR}/bl31.elf .
|
||||
|
||||
source ${VITIS_PATH}/settings64.sh
|
||||
bootgen -arch zynqmp -image ./IDE/XilinxSDK/boot.bif -w -o BOOT.BIN
|
||||
```
|
||||
|
||||
**Signing**
|
||||
|
||||
```sh
|
||||
tools/keytools/sign --rsa4096 --sha3 /path/to/vmlinux.bin wolfboot_signing_private_key.der 1
|
||||
```
|
||||
|
||||
**Testing with QEMU**
|
||||
|
||||
```sh
|
||||
qemu-system-aarch64 -machine xlnx-zcu102 -cpu cortex-a53 -serial stdio -display none \
|
||||
-device loader,file=wolfboot.bin,cpu-num=0
|
||||
|
||||
```
|
||||
|
||||
#### Signing Zynq
|
||||
### SD Card Boot (MBR + A/B)
|
||||
|
||||
`tools/keytools/sign --rsa4096 --sha3 /srv/linux-rpi4/vmlinux.bin wolfboot_signing_private_key.der 1`
|
||||
Use `config/examples/zynqmp_sdcard.config`. This uses the Arasan SDHCI controller (SD1 - external SD card slot on ZCU102) and an **MBR** partitioned SD card.
|
||||
|
||||
**Partition layout**
|
||||
| Partition | Name | Size | Type | Contents |
|
||||
|-----------|--------|-----------|-------------------------------|-------------------------------------------|
|
||||
| 1 | boot | 128MB | FAT32 LBA (0x0c), bootable | BOOT.BIN (FSBL + PMUFW + BL31 + wolfBoot) |
|
||||
| 2 | OFP_A | 200MB | Linux (0x83) | Primary signed firmware image |
|
||||
| 3 | OFP_B | 200MB | Linux (0x83) | Update signed firmware image |
|
||||
| 4 | rootfs | remainder | Linux (0x83) | Linux root filesystem |
|
||||
|
||||
**Build wolfBoot + sign test images**
|
||||
```sh
|
||||
cp config/examples/zynqmp_sdcard.config .config
|
||||
make clean
|
||||
make
|
||||
|
||||
make test-app/image.bin
|
||||
IMAGE_HEADER_SIZE=1024 ./tools/keytools/sign --rsa4096 --sha3 test-app/image.elf wolfboot_signing_private_key.der 1
|
||||
IMAGE_HEADER_SIZE=1024 ./tools/keytools/sign --rsa4096 --sha3 test-app/image.elf wolfboot_signing_private_key.der 2
|
||||
```
|
||||
|
||||
**Build BOOT.BIN for SD card**
|
||||
|
||||
Copy the pre-built firmware and generate BOOT.BIN:
|
||||
|
||||
```sh
|
||||
cp ${PREBUILT_DIR}/zynqmp_fsbl.elf .
|
||||
cp ${PREBUILT_DIR}/pmufw.elf .
|
||||
cp ${PREBUILT_DIR}/bl31.elf .
|
||||
|
||||
source ${VITIS_PATH}/settings64.sh
|
||||
bootgen -arch zynqmp -image ./tools/scripts/zynqmp_sd_boot.bif -w -o BOOT.BIN
|
||||
```
|
||||
|
||||
The BIF file (`zynqmp_sd_boot.bif`) configures the boot chain:
|
||||
- FSBL at A53-0 (bootloader)
|
||||
- PMUFW at PMU
|
||||
- BL31 at EL3 with TrustZone
|
||||
- wolfBoot at EL2
|
||||
|
||||
**Create SD image**
|
||||
```sh
|
||||
dd if=/dev/zero of=sdcard.img bs=1M count=1024
|
||||
sfdisk sdcard.img <<EOF
|
||||
label: dos
|
||||
|
||||
1 : start=2048, size=128M, type=c, bootable
|
||||
2 : size=200M, type=83
|
||||
3 : size=200M, type=83
|
||||
4 : type=83
|
||||
EOF
|
||||
|
||||
SECTOR2=$(sfdisk -d sdcard.img | awk '/sdcard.img2/ {for (i=1;i<=NF;i++) if ($i ~ /start=/) {gsub(/start=|,/, "", $i); print $i}}')
|
||||
SECTOR3=$(sfdisk -d sdcard.img | awk '/sdcard.img3/ {for (i=1;i<=NF;i++) if ($i ~ /start=/) {gsub(/start=|,/, "", $i); print $i}}')
|
||||
dd if=test-app/image_v1_signed.bin of=sdcard.img bs=512 seek=$SECTOR2 conv=notrunc
|
||||
dd if=test-app/image_v2_signed.bin of=sdcard.img bs=512 seek=$SECTOR3 conv=notrunc
|
||||
```
|
||||
|
||||
**Provision SD card**
|
||||
```sh
|
||||
sudo dd if=sdcard.img of=/dev/sdX bs=4M status=progress conv=fsync
|
||||
sync
|
||||
sudo mkfs.vfat -F 32 -n BOOT /dev/sdX1
|
||||
sudo mount /dev/sdX1 /mnt
|
||||
sudo cp BOOT.BIN /mnt/
|
||||
sudo umount /mnt
|
||||
sudo fdisk -l /dev/sdX
|
||||
```
|
||||
|
||||
Or just mount and copy the BOOT.BIN and "dd" the partitions
|
||||
|
||||
```sh
|
||||
# Mount the FAT boot partition and copy just the updated BOOT.BIN
|
||||
sudo mount /dev/sdX1 /mnt && sudo cp BOOT.BIN /mnt/ && sudo umount /mnt && sync
|
||||
|
||||
# Write the signed image to partition 2 (P:A) and partition 3 (P:B)
|
||||
sudo dd if=test-app/image_v1_signed.bin of=/dev/sdX2 bs=4k
|
||||
sudo dd if=test-app/image_v1_signed.bin of=/dev/sdX3 bs=4k
|
||||
```
|
||||
|
||||
**Boot Mode**
|
||||
|
||||
Set the ZCU102 boot mode switches (SW6) for SD card boot:
|
||||
|
||||
| Boot Mode | MODE Pins 3:0 | SW6[4:1] |
|
||||
| --------- | ------------- | -------------- |
|
||||
| JTAG | 0 0 0 0 | on, on, on, on |
|
||||
| QSPI32 | 0 0 1 0 | on, on, off, on |
|
||||
| SD1 | 1 1 1 0 | off, off, off, on |
|
||||
|
||||
**Debug**
|
||||
|
||||
Enable SDHCI debug output by uncommenting in the config:
|
||||
```
|
||||
CFLAGS_EXTRA+=-DDEBUG_SDHCI
|
||||
CFLAGS_EXTRA+=-DDEBUG_DISK
|
||||
```
|
||||
|
||||
**Example Boot Output**
|
||||
|
||||
```
|
||||
wolfBoot Secure Boot
|
||||
Current EL: 2
|
||||
PMUFW Ver: 1.1
|
||||
SDHCI: SDCard mode
|
||||
Reading MBR...
|
||||
Found MBR partition table
|
||||
MBR part 1: type=0x0C, start=0x100000, size=128MB
|
||||
MBR part 2: type=0x83, start=0x8100000, size=200MB
|
||||
MBR part 3: type=0x83, start=0x14900000, size=200MB
|
||||
MBR part 4: type=0x83, start=0x21100000, size=71MB
|
||||
Total partitions on disk0: 4
|
||||
Checking primary OS image in 0,1...
|
||||
Checking secondary OS image in 0,2...
|
||||
Versions, A:1 B:1
|
||||
Load address 0x10000000
|
||||
Attempting boot from P:A
|
||||
Boot partition: 0x8038AA0 (sz 211096, ver 0x1, type 0x401)
|
||||
Loading image from disk...done
|
||||
Boot partition: 0x8038AA0 (sz 211096, ver 0x1, type 0x401)
|
||||
Checking image integrity...done
|
||||
Verifying image signature...done
|
||||
Firmware Valid.
|
||||
Loading elf at 0x10000000
|
||||
Found valid elf64 (little endian)
|
||||
Program Headers 1 (size 56)
|
||||
Load 29888 bytes (offset 0x10000) to 0x10000000 (p 0x10000000)
|
||||
Clear 17540 bytes at 0x10000000 (p 0x10000000)
|
||||
Entry point 0x10000000
|
||||
Booting at 10000000
|
||||
do_boot: entry=0x10000000, EL=2
|
||||
do_boot: dts=0x00000000
|
||||
|
||||
|
||||
===========================================
|
||||
wolfBoot Test Application - AMD ZynqMP
|
||||
===========================================
|
||||
|
||||
Current EL: 2
|
||||
Boot mode: Disk-based (MBR partitions)
|
||||
Application running successfully!
|
||||
|
||||
Entering idle loop...
|
||||
```
|
||||
|
||||
|
||||
## Versal Gen 1 VMK180
|
||||
|
|
@ -2313,7 +2514,6 @@ make test-app/image.bin
|
|||
dd if=/dev/zero of=sdcard.img bs=1M count=1024
|
||||
sfdisk sdcard.img <<EOF
|
||||
label: dos
|
||||
unit: sectors
|
||||
|
||||
1 : start=2048, size=128M, type=c, bootable
|
||||
2 : size=200M, type=83
|
||||
|
|
@ -2343,8 +2543,8 @@ sudo fdisk -l /dev/sdX
|
|||
| Boot Mode | MODE Pins 3:0 | Mode SW1[4:1] |
|
||||
| --------- | ------------- | -------------- |
|
||||
| JTAG | 0 0 0 0 | on, on, on, on |
|
||||
| QSPI32 | 0 0 1 0 | on, on, off,on |
|
||||
| SD1 | 1 1 1 0 | off,off,off,on |
|
||||
| QSPI32 | 0 0 1 0 | on, on, off, on |
|
||||
| SD1 | 1 1 1 0 | off, off, off, on |
|
||||
|
||||
|
||||
## Cypress PSoC-6
|
||||
|
|
|
|||
360
hal/zynq.c
360
hal/zynq.c
|
|
@ -1563,7 +1563,9 @@ void hal_init(void)
|
|||
wolfBoot_printf(bootMsg);
|
||||
wolfBoot_printf("Current EL: %d\n", current_el());
|
||||
|
||||
#if defined(EXT_FLASH) && (EXT_FLASH == 1)
|
||||
qspi_init();
|
||||
#endif
|
||||
|
||||
pmuVer = pmu_get_version();
|
||||
wolfBoot_printf("PMUFW Ver: %d.%d\n",
|
||||
|
|
@ -1581,7 +1583,7 @@ void hal_init(void)
|
|||
|
||||
void hal_prepare_boot(void)
|
||||
{
|
||||
#if GQPI_USE_4BYTE_ADDR == 1
|
||||
#if defined(EXT_FLASH) && (EXT_FLASH == 1) && GQPI_USE_4BYTE_ADDR == 1
|
||||
/* Exit 4-byte address mode */
|
||||
int ret = qspi_exit_4byte_addr(&mDev);
|
||||
if (ret != GQSPI_CODE_SUCCESS)
|
||||
|
|
@ -1594,6 +1596,24 @@ void hal_prepare_boot(void)
|
|||
mDev.qnx = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Clean and invalidate caches for the loaded application.
|
||||
* The application was written to RAM via D-cache, but the CPU will
|
||||
* fetch instructions via I-cache from main memory. We must:
|
||||
* 1. Clean D-cache (flush dirty data to memory)
|
||||
* 2. Invalidate I-cache (ensure fresh instruction fetch) */
|
||||
__asm__ volatile("dsb sy");
|
||||
{
|
||||
uintptr_t addr;
|
||||
uintptr_t end = WOLFBOOT_LOAD_ADDRESS + APP_CACHE_FLUSH_SIZE;
|
||||
for (addr = WOLFBOOT_LOAD_ADDRESS; addr < end; addr += CACHE_LINE_SIZE) {
|
||||
__asm__ volatile("dc civac, %0" : : "r"(addr));
|
||||
}
|
||||
}
|
||||
__asm__ volatile("dsb sy");
|
||||
__asm__ volatile("ic iallu");
|
||||
__asm__ volatile("dsb sy");
|
||||
__asm__ volatile("isb");
|
||||
}
|
||||
|
||||
/* Flash functions must be relocated to RAM for execution */
|
||||
|
|
@ -1779,7 +1799,13 @@ void RAMFUNCTION ext_flash_unlock(void)
|
|||
#ifdef MMU
|
||||
void* hal_get_dts_address(void)
|
||||
{
|
||||
#ifdef WOLFBOOT_DTS_BOOT_ADDRESS
|
||||
return (void*)WOLFBOOT_DTS_BOOT_ADDRESS;
|
||||
#elif defined(WOLFBOOT_LOAD_DTS_ADDRESS)
|
||||
return (void*)WOLFBOOT_LOAD_DTS_ADDRESS;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
int hal_dts_fixup(void* dts_addr)
|
||||
|
|
@ -1834,4 +1860,336 @@ static int test_ext_flash(QspiDev_t* dev)
|
|||
}
|
||||
#endif /* TEST_EXT_FLASH */
|
||||
|
||||
|
||||
/* ============================================================================
|
||||
* SDHCI (SD Card / eMMC) Platform Support
|
||||
* ============================================================================
|
||||
* Platform-specific hooks for the generic SDHCI driver (src/sdhci.c).
|
||||
* ZynqMP uses the Arasan SDHCI controller with standard register layout.
|
||||
* The generic driver uses Cadence SD4HC register offsets, so we translate:
|
||||
* - HRS registers at 0x000-0x01F (Cadence-specific: reset, PHY, eMMC mode)
|
||||
* - SRS registers at 0x200-0x2FF (standard SDHCI mapped at offset +0x200)
|
||||
* Arasan uses standard SDHCI registers at 0x000-0x0FF (no 0x200 offset).
|
||||
*/
|
||||
#if defined(DISK_SDCARD) || defined(DISK_EMMC)
|
||||
#include "sdhci.h"
|
||||
|
||||
/* SD controller base address selection:
|
||||
* SD0 (ZYNQMP_SD0_BASE = 0xFF160000) - internal, typically eMMC
|
||||
* SD1 (ZYNQMP_SD1_BASE = 0xFF170000) - external SD card slot on ZCU102
|
||||
*/
|
||||
#ifndef ZYNQMP_SDHCI_BASE
|
||||
#define ZYNQMP_SDHCI_BASE ZYNQMP_SD1_BASE
|
||||
#endif
|
||||
|
||||
#define CADENCE_SRS_OFFSET 0x200
|
||||
|
||||
/* Legacy SDMA system address register (standard SDHCI offset 0x00).
|
||||
* The Arasan SDHCI v3.0 on ZynqMP does not support Host Version 4 Enable
|
||||
* (HV4E) mode. The generic SDHCI driver uses HV4E-style 64-bit DMA
|
||||
* addressing via SRS22/SRS23 (offsets 0x58/0x5C), but on this controller
|
||||
* we must use the legacy SRS00 register (offset 0x00) for SDMA addresses.
|
||||
* The platform reg_read/reg_write functions transparently redirect
|
||||
* SRS22 <-> SRS00, making legacy SDMA work without changes to sdhci.c. */
|
||||
#define STD_SDHCI_SDMA_ADDR 0x00 /* SDMA System Address (32-bit) */
|
||||
#define STD_SDHCI_HOST_CTRL2 0x3C /* Auto CMD Err(16) + Host Ctrl 2(16) */
|
||||
|
||||
/* Standard SDHCI register offsets (byte addresses within the controller) */
|
||||
#define STD_SDHCI_HOST_CTRL1 0x28 /* Host Control 1 (8-bit) */
|
||||
#define STD_SDHCI_POWER_CTRL 0x29 /* Power Control (8-bit) */
|
||||
#define STD_SDHCI_BLKGAP_CTRL 0x2A /* Block Gap Control (8-bit) */
|
||||
#define STD_SDHCI_WAKEUP_CTRL 0x2B /* Wakeup Control (8-bit) */
|
||||
#define STD_SDHCI_CLK_CTRL 0x2C /* Clock Control (16-bit) */
|
||||
#define STD_SDHCI_TIMEOUT_CTRL 0x2E /* Timeout Control (8-bit) */
|
||||
#define STD_SDHCI_SW_RESET 0x2F /* Software Reset (8-bit) */
|
||||
|
||||
/* Software Reset register bits (at offset 0x2F, 8-bit register) */
|
||||
#define STD_SDHCI_SRA 0x01 /* Software Reset for All */
|
||||
#define STD_SDHCI_SRCMD 0x02 /* Software Reset for CMD Line */
|
||||
#define STD_SDHCI_SRDAT 0x04 /* Software Reset for DAT Line */
|
||||
|
||||
/* Handle reads from Cadence HRS registers (0x000-0x1FF) */
|
||||
static uint32_t zynqmp_sdhci_hrs_read(uint32_t hrs_offset)
|
||||
{
|
||||
volatile uint8_t *base = (volatile uint8_t *)ZYNQMP_SDHCI_BASE;
|
||||
|
||||
switch (hrs_offset) {
|
||||
case 0x000: /* HRS00 - Software Reset */
|
||||
{
|
||||
/* Map standard SRA (byte at 0x2F) to Cadence SWR (bit 0) */
|
||||
uint8_t val = *((volatile uint8_t *)(base + STD_SDHCI_SW_RESET));
|
||||
return (val & STD_SDHCI_SRA) ? 1U : 0U;
|
||||
}
|
||||
case 0x010: /* HRS04 - PHY access (Cadence-specific) */
|
||||
/* Return ACK set to prevent wait loops from hanging */
|
||||
return (1U << 26); /* SDHCI_HRS04_UIS_ACK */
|
||||
default:
|
||||
/* HRS01 (debounce), HRS02, HRS06 (eMMC mode) - not applicable */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle writes to Cadence HRS registers (0x000-0x1FF) */
|
||||
static void zynqmp_sdhci_hrs_write(uint32_t hrs_offset, uint32_t val)
|
||||
{
|
||||
volatile uint8_t *base = (volatile uint8_t *)ZYNQMP_SDHCI_BASE;
|
||||
|
||||
switch (hrs_offset) {
|
||||
case 0x000: /* HRS00 - Software Reset */
|
||||
if (val & 1U) {
|
||||
/* Issue SRA via 8-bit write to offset 0x2F (per SDHCI spec).
|
||||
* The Arasan controller requires byte-level access for the
|
||||
* Software Reset register. */
|
||||
*((volatile uint8_t *)(base + STD_SDHCI_SW_RESET)) = STD_SDHCI_SRA;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* HRS01, HRS04, HRS06 - not applicable on ZynqMP, ignore */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Register access functions for generic SDHCI driver.
|
||||
* Translates Cadence SD4HC register offsets to standard Arasan SDHCI layout.
|
||||
*
|
||||
* IMPORTANT: The Arasan SDHCI on ZynqMP requires specific register access
|
||||
* widths matching the SDHCI specification (see Xilinx SDPS driver reference):
|
||||
* - Host Control 1 (0x28): 8-bit
|
||||
* - Power Control (0x29): 8-bit
|
||||
* - Clock Control (0x2C): 16-bit
|
||||
* - Timeout Control (0x2E): 8-bit
|
||||
* - Software Reset (0x2F): 8-bit
|
||||
* The Cadence driver uses 32-bit SRS10/SRS11 registers that span these byte
|
||||
* offsets. We decompose 32-bit writes into the correct access widths. */
|
||||
uint32_t sdhci_reg_read(uint32_t offset)
|
||||
{
|
||||
volatile uint8_t *base = (volatile uint8_t *)ZYNQMP_SDHCI_BASE;
|
||||
|
||||
/* Cadence SRS registers (0x200+) -> standard SDHCI (subtract 0x200) */
|
||||
if (offset >= CADENCE_SRS_OFFSET) {
|
||||
uint32_t std_off = offset - CADENCE_SRS_OFFSET;
|
||||
|
||||
/* SRS22 (0x58) -> SRS00 (0x00): Legacy SDMA address register */
|
||||
if (std_off == 0x58) {
|
||||
return *((volatile uint32_t *)(base + STD_SDHCI_SDMA_ADDR));
|
||||
}
|
||||
/* SRS23 (0x5C) -> 0: No 64-bit addressing on SDHCI v3.0 */
|
||||
if (std_off == 0x5C) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
{
|
||||
uint32_t val = *((volatile uint32_t *)(base + std_off));
|
||||
/* Mask out A64S from Capabilities to prevent HV4E init */
|
||||
if (std_off == 0x40) { /* SRS16 - Capabilities */
|
||||
val &= ~SDHCI_SRS16_A64S;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
}
|
||||
/* Cadence HRS registers (0x000-0x1FF) -> translate to standard equivalents */
|
||||
return zynqmp_sdhci_hrs_read(offset);
|
||||
}
|
||||
|
||||
void sdhci_reg_write(uint32_t offset, uint32_t val)
|
||||
{
|
||||
volatile uint8_t *base = (volatile uint8_t *)ZYNQMP_SDHCI_BASE;
|
||||
|
||||
if (offset >= CADENCE_SRS_OFFSET) {
|
||||
uint32_t std_off = offset - CADENCE_SRS_OFFSET;
|
||||
|
||||
/* SRS10 (Cadence 0x228) = standard 0x28-0x2B:
|
||||
* 0x28: Host Control 1 (8-bit)
|
||||
* 0x29: Power Control (8-bit)
|
||||
* 0x2A: Block Gap Control (8-bit)
|
||||
* 0x2B: Wakeup Control (8-bit) */
|
||||
if (std_off == 0x28) {
|
||||
*((volatile uint8_t *)(base + STD_SDHCI_HOST_CTRL1)) =
|
||||
(uint8_t)(val & 0xFF);
|
||||
*((volatile uint8_t *)(base + STD_SDHCI_POWER_CTRL)) =
|
||||
(uint8_t)((val >> 8) & 0xFF);
|
||||
*((volatile uint8_t *)(base + STD_SDHCI_BLKGAP_CTRL)) =
|
||||
(uint8_t)((val >> 16) & 0xFF);
|
||||
*((volatile uint8_t *)(base + STD_SDHCI_WAKEUP_CTRL)) =
|
||||
(uint8_t)((val >> 24) & 0xFF);
|
||||
return;
|
||||
}
|
||||
|
||||
/* SRS11 (Cadence 0x22C) = standard 0x2C-0x2F:
|
||||
* 0x2C: Clock Control (16-bit)
|
||||
* 0x2E: Timeout Control (8-bit)
|
||||
* 0x2F: Software Reset (8-bit) */
|
||||
if (std_off == 0x2C) {
|
||||
*((volatile uint16_t *)(base + STD_SDHCI_CLK_CTRL)) =
|
||||
(uint16_t)(val & 0xFFFF);
|
||||
*((volatile uint8_t *)(base + STD_SDHCI_TIMEOUT_CTRL)) =
|
||||
(uint8_t)((val >> 16) & 0xFF);
|
||||
*((volatile uint8_t *)(base + STD_SDHCI_SW_RESET)) =
|
||||
(uint8_t)((val >> 24) & 0xFF);
|
||||
return;
|
||||
}
|
||||
|
||||
/* SRS22 (0x58) -> SRS00 (0x00): Legacy SDMA address register.
|
||||
* The generic driver writes the DMA buffer address here for HV4E mode.
|
||||
* Redirect to SRS00 which is the legacy SDMA system address register.
|
||||
* Writing SRS00 also restarts DMA after a boundary interrupt. */
|
||||
if (std_off == 0x58) {
|
||||
*((volatile uint32_t *)(base + STD_SDHCI_SDMA_ADDR)) = val;
|
||||
return;
|
||||
}
|
||||
/* SRS23 (0x5C) -> no-op: No 64-bit addressing on SDHCI v3.0 */
|
||||
if (std_off == 0x5C) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* SRS15 (0x3C) -> mask out HV4E and A64 bits.
|
||||
* The generic driver enables HV4E for SDMA, but the Arasan SDHCI v3.0
|
||||
* does not support it. These are reserved bits on v3.0 and must not
|
||||
* be set. */
|
||||
if (std_off == STD_SDHCI_HOST_CTRL2) {
|
||||
val &= ~(SDHCI_SRS15_HV4E | SDHCI_SRS15_A64);
|
||||
}
|
||||
|
||||
/* All other SRS registers: 32-bit write */
|
||||
*((volatile uint32_t *)(base + std_off)) = val;
|
||||
return;
|
||||
}
|
||||
/* Cadence HRS registers (0x000-0x1FF) -> translate to standard equivalents */
|
||||
zynqmp_sdhci_hrs_write(offset, val);
|
||||
}
|
||||
|
||||
/* Platform initialization - called from sdhci_init()
|
||||
* FSBL already initializes the SD controller on ZynqMP when booting from SD,
|
||||
* so we don't need to configure clocks/reset (CRL_APB registers).
|
||||
*
|
||||
* However, the FSBL uses GPIO-based card detect (polling MIO45 as GPIO)
|
||||
* rather than the SDHCI controller's built-in CD mechanism. The default
|
||||
* IOU_SLCR SD_CONFIG_REG2 slot type is "Removable" (00), but MIO45 is not
|
||||
* routed to the SDHCI controller as a CD function. This causes the Arasan
|
||||
* SDHCI to report Card Inserted=0 and gate writes to Bus Power and SD Clock
|
||||
* Enable registers.
|
||||
*
|
||||
* Fix: Set SD1 slot type to "Embedded" (01) in IOU_SLCR SD_CONFIG_REG2.
|
||||
* This makes the controller always assert Card Inserted and Card State
|
||||
* Stable, allowing normal SDHCI register access. */
|
||||
void sdhci_platform_init(void)
|
||||
{
|
||||
uint32_t reg;
|
||||
volatile int i;
|
||||
uint32_t slot_mask;
|
||||
uint32_t slot_shift;
|
||||
uint32_t reset_bit;
|
||||
|
||||
/* Set the selected SDx slot type to "Embedded Slot for One Device" (01).
|
||||
* This feeds into the SDHCI Capabilities register bits 31:30 and makes
|
||||
* the controller report card as always present, bypassing the physical
|
||||
* CD pin that is not connected to the SDHCI controller on ZCU102. */
|
||||
if (ZYNQMP_SDHCI_BASE == ZYNQMP_SD0_BASE) {
|
||||
slot_mask = SD_CONFIG_REG2_SD0_SLOTTYPE_MASK;
|
||||
slot_shift = SD_CONFIG_REG2_SD0_SLOTTYPE_SHIFT;
|
||||
reset_bit = RST_LPD_IOU2_SDIO0;
|
||||
} else {
|
||||
slot_mask = SD_CONFIG_REG2_SD1_SLOTTYPE_MASK;
|
||||
slot_shift = SD_CONFIG_REG2_SD1_SLOTTYPE_SHIFT;
|
||||
reset_bit = RST_LPD_IOU2_SDIO1;
|
||||
}
|
||||
|
||||
reg = IOU_SLCR_SD_CONFIG_REG2;
|
||||
reg &= ~slot_mask;
|
||||
reg |= (1UL << slot_shift); /* 01 = Embedded */
|
||||
IOU_SLCR_SD_CONFIG_REG2 = reg;
|
||||
|
||||
/* The SDHCI Capabilities register latches IOU_SLCR values on controller
|
||||
* reset. Issue SDIOx reset via CRL_APB so the controller picks up the
|
||||
* new slot type configuration. */
|
||||
RST_LPD_IOU2 |= reset_bit; /* Assert SDIOx reset */
|
||||
for (i = 0; i < 100; i++) {} /* Brief delay */
|
||||
RST_LPD_IOU2 &= ~reset_bit; /* De-assert SDIOx reset */
|
||||
for (i = 0; i < 1000; i++) {} /* Wait for controller ready */
|
||||
|
||||
#ifdef DEBUG_SDHCI
|
||||
{
|
||||
volatile uint8_t *base = (volatile uint8_t *)ZYNQMP_SDHCI_BASE;
|
||||
uint32_t val;
|
||||
|
||||
wolfBoot_printf("sdhci_platform_init: SD%d at 0x%x\n",
|
||||
(ZYNQMP_SDHCI_BASE == ZYNQMP_SD0_BASE) ? 0 : 1,
|
||||
(unsigned int)ZYNQMP_SDHCI_BASE);
|
||||
|
||||
wolfBoot_printf(" SD_CONFIG_REG2: 0x%x\n",
|
||||
(unsigned int)IOU_SLCR_SD_CONFIG_REG2);
|
||||
|
||||
/* Read standard SDHCI registers to verify controller access */
|
||||
val = *((volatile uint32_t *)(base + 0x24)); /* Present State */
|
||||
wolfBoot_printf(" Present State: 0x%x\n", (unsigned int)val);
|
||||
|
||||
val = *((volatile uint32_t *)(base + 0x40)); /* Capabilities */
|
||||
wolfBoot_printf(" Capabilities: 0x%x\n", (unsigned int)val);
|
||||
(void)val;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Platform interrupt setup - called from sdhci_init()
|
||||
* Using polling mode for simplicity - no GIC setup needed */
|
||||
void sdhci_platform_irq_init(void)
|
||||
{
|
||||
#ifdef DEBUG_SDHCI
|
||||
wolfBoot_printf("sdhci_platform_irq_init: Using polling mode\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Platform bus mode selection - called from sdhci_init() after software reset */
|
||||
void sdhci_platform_set_bus_mode(int is_emmc)
|
||||
{
|
||||
(void)is_emmc;
|
||||
#ifdef DEBUG_SDHCI
|
||||
wolfBoot_printf("sdhci_platform_set_bus_mode: is_emmc=%d\n", is_emmc);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* DMA cache maintenance - called from sdhci_transfer() around SDMA operations.
|
||||
* The SDMA engine transfers data directly to/from physical memory, bypassing
|
||||
* the CPU's L1/L2 caches. We must ensure cache coherency:
|
||||
* - Before DMA write (card←memory): clean D-cache so DMA reads correct data
|
||||
* - After DMA read (card→memory): invalidate D-cache so CPU sees new data */
|
||||
void sdhci_platform_dma_prepare(void *buf, uint32_t sz, int is_write)
|
||||
{
|
||||
uintptr_t addr;
|
||||
uintptr_t start = (uintptr_t)buf & ~(CACHE_LINE_SIZE - 1);
|
||||
uintptr_t end = (uintptr_t)buf + sz;
|
||||
|
||||
if (is_write) {
|
||||
/* Clean D-cache: flush dirty lines to memory for DMA to read */
|
||||
for (addr = start; addr < end; addr += CACHE_LINE_SIZE) {
|
||||
__asm__ volatile("dc cvac, %0" : : "r"(addr) : "memory");
|
||||
}
|
||||
} else {
|
||||
/* Invalidate D-cache: discard stale lines before DMA writes to memory */
|
||||
for (addr = start; addr < end; addr += CACHE_LINE_SIZE) {
|
||||
__asm__ volatile("dc civac, %0" : : "r"(addr) : "memory");
|
||||
}
|
||||
}
|
||||
__asm__ volatile("dsb sy" : : : "memory");
|
||||
}
|
||||
|
||||
void sdhci_platform_dma_complete(void *buf, uint32_t sz, int is_write)
|
||||
{
|
||||
/* After DMA read (card->memory): invalidate so CPU sees DMA-written data.
|
||||
* For DMA write (card<-memory): DMA only read from memory, so there is no
|
||||
* new data for the CPU to see and invalidation could discard dirty lines. */
|
||||
uintptr_t addr;
|
||||
uintptr_t start = (uintptr_t)buf & ~(CACHE_LINE_SIZE - 1);
|
||||
uintptr_t end = (uintptr_t)buf + sz;
|
||||
|
||||
if (!is_write) {
|
||||
for (addr = start; addr < end; addr += CACHE_LINE_SIZE) {
|
||||
__asm__ volatile("dc civac, %0" : : "r"(addr) : "memory");
|
||||
}
|
||||
__asm__ volatile("dsb sy" : : : "memory");
|
||||
}
|
||||
}
|
||||
#endif /* DISK_SDCARD || DISK_EMMC */
|
||||
|
||||
|
||||
#endif /* TARGET_zynq */
|
||||
|
|
|
|||
33
hal/zynq.h
33
hal/zynq.h
|
|
@ -32,6 +32,11 @@
|
|||
#ifndef EL2_HYPERVISOR
|
||||
#define EL2_HYPERVISOR 1
|
||||
#endif
|
||||
|
||||
/* Cache line size for Cortex-A53 (AArch64) */
|
||||
#define CACHE_LINE_SIZE 64
|
||||
/* Region size to flush before booting application */
|
||||
#define APP_CACHE_FLUSH_SIZE (1 * 1024 * 1024) /* 1MB */
|
||||
#ifndef EL1_NONSECURE
|
||||
#define EL1_NONSECURE 0
|
||||
#endif
|
||||
|
|
@ -58,8 +63,8 @@
|
|||
|
||||
|
||||
/* IOP System-level Control */
|
||||
#define IOU_SLCR_BASSE 0xFF180000
|
||||
#define IOU_TAPDLY_BYPASS_ADDR (IOU_SLCR_BASSE + 0x390)
|
||||
#define IOU_SLCR_BASE 0xFF180000
|
||||
#define IOU_TAPDLY_BYPASS_ADDR (IOU_SLCR_BASE + 0x390)
|
||||
#define IOU_TAPDLY_BYPASS (*((volatile uint32_t*)IOU_TAPDLY_BYPASS_ADDR))
|
||||
#define IOU_TAPDLY_BYPASS_LQSPI_RX (1UL << 2) /* LQSPI Tap Delay Enable on Rx Clock signal. 0: enable. 1: disable (bypass tap delay). */
|
||||
|
||||
|
|
@ -398,7 +403,29 @@
|
|||
#define QSPI_REF_CTRL_DIVISOR0(n) (((n) << 8) & QSPI_REF_CTRL_DIVISOR0_MASK)
|
||||
|
||||
#define QSPI_REF_CTRL_DIVISOR1_MASK (0x3F << 16)
|
||||
#define QSPI_REF_CTRL_DIVISOR1(n) (((n) << 16) & QSPI_REF_CTRL_DIVISOR0_MASK)
|
||||
#define QSPI_REF_CTRL_DIVISOR1(n) (((n) << 16) & QSPI_REF_CTRL_DIVISOR1_MASK)
|
||||
|
||||
/* SD/SDHCI Controller Base Addresses */
|
||||
#define ZYNQMP_SD0_BASE 0xFF160000UL
|
||||
#define ZYNQMP_SD1_BASE 0xFF170000UL
|
||||
|
||||
/* SD/SDIO Reference Clock Control (CRL_APB) */
|
||||
#define SDIO0_REF_CTRL (*((volatile uint32_t*)(CRL_APB_BASE + 0x6C)))
|
||||
#define SDIO1_REF_CTRL (*((volatile uint32_t*)(CRL_APB_BASE + 0x70)))
|
||||
|
||||
/* SD/SDIO Reset Control (CRL_APB RST_LPD_IOU2) */
|
||||
#define RST_LPD_IOU2 (*((volatile uint32_t*)(CRL_APB_BASE + 0x0238)))
|
||||
#define RST_LPD_IOU2_SDIO0 (1UL << 5)
|
||||
#define RST_LPD_IOU2_SDIO1 (1UL << 6)
|
||||
|
||||
/* IOU_SLCR SD Configuration (feeds into SDHCI Capabilities register) */
|
||||
#define IOU_SLCR_SD_CONFIG_REG2 (*((volatile uint32_t*)(IOU_SLCR_BASE + 0x320)))
|
||||
/* SD1 Slot Type: 00=Removable, 01=Embedded, 10=Shared Bus */
|
||||
#define SD_CONFIG_REG2_SD1_SLOTTYPE_SHIFT 28
|
||||
#define SD_CONFIG_REG2_SD1_SLOTTYPE_MASK 0x30000000UL
|
||||
/* SD0 Slot Type */
|
||||
#define SD_CONFIG_REG2_SD0_SLOTTYPE_SHIFT 12
|
||||
#define SD_CONFIG_REG2_SD0_SLOTTYPE_MASK 0x00003000UL
|
||||
|
||||
|
||||
/* Configuration Security Unit (CSU) */
|
||||
|
|
|
|||
11
hal/zynq.ld
11
hal/zynq.ld
|
|
@ -12,8 +12,11 @@ _EL2_STACK_SIZE = DEFINED(_EL2_STACK_SIZE) ? _EL2_STACK_SIZE : 1024;
|
|||
MEMORY
|
||||
{
|
||||
/* psu_ddr_0_MEM_0 : ORIGIN = 0x0, LENGTH = 0x80000000 */
|
||||
/* Use the end of DDR0 for wolfBoot (reserve 1MB) */
|
||||
psu_ddr_0_MEM_0 : ORIGIN = 0x7FF00000, LENGTH = 0x100000
|
||||
/* wolfBoot DDR location (2MB reserved):
|
||||
* Loaded by FSBL/BL31 to DDR at 0x8000000 (128MB)
|
||||
* Same address used for both QSPI and SD card boot
|
||||
*/
|
||||
psu_ddr_0_MEM_0 : ORIGIN = 0x8000000, LENGTH = 0x200000
|
||||
psu_ddr_1_MEM_0 : ORIGIN = 0x800000000, LENGTH = 0x80000000
|
||||
psu_ocm_ram_0_MEM_0 : ORIGIN = 0xFFFC0000, LENGTH = 0x40000
|
||||
psu_qspi_linear_0_MEM_0 : ORIGIN = 0xC0000000, LENGTH = 0x20000000
|
||||
|
|
@ -38,7 +41,7 @@ SECTIONS
|
|||
*(.gnu.linkonce.t.*)
|
||||
*(.plt)
|
||||
*(.gnu_warning)
|
||||
*(.gcc_execpt_table)
|
||||
*(.gcc_except_table)
|
||||
*(.glue_7)
|
||||
*(.glue_7t)
|
||||
*(.ARM.extab)
|
||||
|
|
@ -197,7 +200,7 @@ SECTIONS
|
|||
.ARM.exidx : {
|
||||
__exidx_start = .;
|
||||
*(.ARM.exidx*)
|
||||
*(.gnu.linkonce.armexidix.*.*)
|
||||
*(.gnu.linkonce.armexidx.*.*)
|
||||
__exidx_end = .;
|
||||
} > psu_ddr_0_MEM_0
|
||||
|
||||
|
|
|
|||
|
|
@ -212,6 +212,8 @@
|
|||
/* SRS10 - Host Control 1 / Power / Block Gap / Wakeup */
|
||||
#define SDHCI_SRS10_DTW (1U << 1) /* Data transfer width (4-bit) */
|
||||
#define SDHCI_SRS10_EDTW (1U << 5) /* Extended data transfer width (8-bit) */
|
||||
#define SDHCI_SRS10_CDTL (1U << 6) /* Card Detect Test Level */
|
||||
#define SDHCI_SRS10_CDSS (1U << 7) /* Card Detect Signal Selection */
|
||||
#define SDHCI_SRS10_HSE (1U << 2) /* High speed enable */
|
||||
#define SDHCI_SRS10_BP (1U << 8) /* Bus power */
|
||||
#define SDHCI_SRS10_BVS_MASK (0x7U << 9)
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
#include "image.h"
|
||||
#include "loader.h"
|
||||
#include "printf.h"
|
||||
#include "wolfboot/wolfboot.h"
|
||||
|
||||
/* Include platform-specific header for EL configuration defines */
|
||||
|
|
@ -130,7 +131,10 @@ void RAMFUNCTION do_boot(const uint32_t *app_offset, const uint32_t* dts_offset)
|
|||
void RAMFUNCTION do_boot(const uint32_t *app_offset)
|
||||
#endif
|
||||
{
|
||||
wolfBoot_printf("do_boot: entry=0x%08x, EL=%d\n",
|
||||
(uint32_t)(uintptr_t)app_offset, current_el());
|
||||
#ifdef MMU
|
||||
wolfBoot_printf("do_boot: dts=0x%08x\n", (uint32_t)(uintptr_t)dts_offset);
|
||||
hal_dts_fixup((uint32_t*)dts_offset);
|
||||
#endif
|
||||
|
||||
|
|
@ -155,6 +159,7 @@ void RAMFUNCTION do_boot(const uint32_t *app_offset)
|
|||
#else
|
||||
uintptr_t dts = 0;
|
||||
#endif
|
||||
wolfBoot_printf("do_boot: EL2->EL1 via ERET\n");
|
||||
el2_to_el1_boot((uintptr_t)app_offset, dts);
|
||||
}
|
||||
#else
|
||||
|
|
|
|||
38
src/sdhci.c
38
src/sdhci.c
|
|
@ -34,6 +34,22 @@
|
|||
#include "hal.h"
|
||||
#include "disk.h"
|
||||
|
||||
/* ============================================================================
|
||||
* Platform DMA cache maintenance (weak defaults - override in HAL)
|
||||
* ============================================================================ */
|
||||
#ifndef SDHCI_SDMA_DISABLED
|
||||
void __attribute__((weak)) sdhci_platform_dma_prepare(
|
||||
void *buf, uint32_t sz, int is_write)
|
||||
{
|
||||
(void)buf; (void)sz; (void)is_write;
|
||||
}
|
||||
void __attribute__((weak)) sdhci_platform_dma_complete(
|
||||
void *buf, uint32_t sz, int is_write)
|
||||
{
|
||||
(void)buf; (void)sz; (void)is_write;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* ============================================================================
|
||||
* Internal state
|
||||
* ============================================================================ */
|
||||
|
|
@ -368,7 +384,7 @@ static uint32_t sdhci_set_clock(uint32_t clock_khz)
|
|||
reg = SDHCI_REG(SDHCI_SRS11);
|
||||
reg &= ~(SDHCI_SRS11_SDCFSL_MASK | SDHCI_SRS11_SDCFSH_MASK);
|
||||
reg |= (((mclk & 0x0FF) << SDHCI_SRS11_SDCFSL_SHIFT) & SDHCI_SRS11_SDCFSL_MASK); /* lower 8 bits */
|
||||
reg |= (((mclk & 0x300) << SDHCI_SRS11_SDCFSH_SHIFT) & SDHCI_SRS11_SDCFSH_SHIFT); /* upper 2 bits */
|
||||
reg |= (((mclk & 0x300) >> 2) & SDHCI_SRS11_SDCFSH_MASK); /* upper 2 bits */
|
||||
reg |= SDHCI_SRS11_ICE; /* clock enable */
|
||||
reg &= ~SDHCI_SRS11_CGS; /* select clock */
|
||||
SDHCI_REG_SET(SDHCI_SRS11, reg);
|
||||
|
|
@ -560,6 +576,13 @@ static int sdcard_power_init_seq(uint32_t voltage)
|
|||
{
|
||||
/* Set power to specified voltage */
|
||||
int status = sdhci_set_power(voltage);
|
||||
#ifdef DEBUG_SDHCI
|
||||
wolfBoot_printf("sdcard_power_init: power status=%d, SRS09=0x%x, "
|
||||
"SRS10=0x%x, SRS11=0x%x, SRS12=0x%x\n",
|
||||
status,
|
||||
SDHCI_REG(SDHCI_SRS09), SDHCI_REG(SDHCI_SRS10),
|
||||
SDHCI_REG(SDHCI_SRS11), SDHCI_REG(SDHCI_SRS12));
|
||||
#endif
|
||||
if (status == 0) {
|
||||
/* send CMD0 (go idle) to reset card */
|
||||
status = sdhci_cmd(MMC_CMD0_GO_IDLE, 0, SDHCI_RESP_NONE);
|
||||
|
|
@ -1183,10 +1206,16 @@ static int sdhci_transfer(int dir, uint32_t cmd_index, uint32_t block_addr,
|
|||
/* SDMA mode with Host Version 4 enable.
|
||||
* HV4E is required for SDMA to use the 64-bit address registers
|
||||
* (SRS22/SRS23) instead of the legacy 32-bit register (SRS00).
|
||||
* A64 is cleared in SRS15 to use 32-bit DMA addressing. */
|
||||
* A64 is cleared in SRS15 to use 32-bit DMA addressing.
|
||||
* Note: Platform may redirect SRS22/SRS23 to SRS00 for legacy
|
||||
* SDMA on controllers that don't support HV4E. */
|
||||
sdhci_reg_or(SDHCI_SRS10, SDHCI_SRS10_DMA_SDMA);
|
||||
sdhci_reg_or(SDHCI_SRS15, SDHCI_SRS15_HV4E);
|
||||
sdhci_reg_and(SDHCI_SRS15, ~SDHCI_SRS15_A64);
|
||||
|
||||
/* Platform DMA cache maintenance before transfer */
|
||||
sdhci_platform_dma_prepare(buf, sz, dir == SDHCI_DIR_WRITE);
|
||||
|
||||
/* Set SDMA address */
|
||||
SDHCI_REG_SET(SDHCI_SRS22, (uint32_t)(uintptr_t)buf);
|
||||
SDHCI_REG_SET(SDHCI_SRS23, (uint32_t)(((uint64_t)(uintptr_t)buf) >> 32));
|
||||
|
|
@ -1223,6 +1252,9 @@ static int sdhci_transfer(int dir, uint32_t cmd_index, uint32_t block_addr,
|
|||
}
|
||||
}
|
||||
sdhci_disable_sdma_interrupts();
|
||||
|
||||
/* Platform DMA cache maintenance after transfer */
|
||||
sdhci_platform_dma_complete(buf, sz, dir == SDHCI_DIR_WRITE);
|
||||
}
|
||||
else {
|
||||
/* Blocking mode - buffer ready flag differs for read vs write */
|
||||
|
|
@ -1407,6 +1439,7 @@ int sdhci_init(void)
|
|||
|
||||
/* check if card inserted and stable */
|
||||
reg = SDHCI_REG(SDHCI_SRS09);
|
||||
#ifndef SDHCI_FORCE_CARD_DETECT
|
||||
if ((reg & SDHCI_SRS09_CSS) == 0) {
|
||||
/* card not inserted or not stable */
|
||||
return -1;
|
||||
|
|
@ -1419,6 +1452,7 @@ int sdhci_init(void)
|
|||
return -1;
|
||||
}
|
||||
#endif
|
||||
#endif /* !SDHCI_FORCE_CARD_DETECT */
|
||||
|
||||
/* Start in 1-bit bus mode */
|
||||
reg = SDHCI_REG(SDHCI_SRS10);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* app_zynq.c
|
||||
*
|
||||
* Test bare-metal boot application
|
||||
* Test bare-metal boot application for AMD ZynqMP ZCU102
|
||||
*
|
||||
* Copyright (C) 2025 wolfSSL Inc.
|
||||
*
|
||||
|
|
@ -21,19 +21,56 @@
|
|||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "wolfboot/wolfboot.h"
|
||||
#include "printf.h"
|
||||
|
||||
#ifdef TARGET_zynq
|
||||
|
||||
volatile uint32_t time_elapsed = 0;
|
||||
void main(void) {
|
||||
/* Provide current_el() for hal/zynq.o (normally in boot_aarch64.c) */
|
||||
unsigned int current_el(void)
|
||||
{
|
||||
unsigned long el;
|
||||
__asm__ volatile("mrs %0, CurrentEL" : "=r" (el) : : "cc");
|
||||
return (unsigned int)((el >> 2) & 0x3U);
|
||||
}
|
||||
|
||||
/* Wait for reboot */
|
||||
while(1)
|
||||
;
|
||||
/* Stub for QSPI DMA code in hal/zynq.o (not used with SD card boot) */
|
||||
void flush_dcache_range(unsigned long start, unsigned long end)
|
||||
{
|
||||
(void)start;
|
||||
(void)end;
|
||||
}
|
||||
|
||||
void main(void)
|
||||
{
|
||||
#ifdef WOLFBOOT_FIXED_PARTITIONS
|
||||
uint32_t boot_version, update_version;
|
||||
#endif
|
||||
|
||||
wolfBoot_printf("\n\n");
|
||||
wolfBoot_printf("===========================================\n");
|
||||
wolfBoot_printf(" wolfBoot Test Application - AMD ZynqMP\n");
|
||||
wolfBoot_printf("===========================================\n\n");
|
||||
|
||||
wolfBoot_printf("Current EL: %d\n", current_el());
|
||||
|
||||
#ifdef WOLFBOOT_FIXED_PARTITIONS
|
||||
boot_version = wolfBoot_get_image_version(PART_BOOT);
|
||||
update_version = wolfBoot_get_image_version(PART_UPDATE);
|
||||
wolfBoot_printf("BOOT: Version: %d (0x%08x)\n", boot_version, boot_version);
|
||||
wolfBoot_printf("UPDATE: Version: %d (0x%08x)\n", update_version, update_version);
|
||||
#else
|
||||
wolfBoot_printf("Boot mode: Disk-based (MBR partitions)\n");
|
||||
#endif
|
||||
|
||||
wolfBoot_printf("Application running successfully!\n");
|
||||
wolfBoot_printf("\nEntering idle loop...\n");
|
||||
|
||||
/* Idle loop */
|
||||
while (1) {
|
||||
__asm__ volatile("wfi");
|
||||
}
|
||||
}
|
||||
#endif /** TARGET_zynq **/
|
||||
|
|
|
|||
|
|
@ -0,0 +1,225 @@
|
|||
; Zynq UltraScale+ ZCU102 Quad SPI FLASH Programming Script
|
||||
;
|
||||
; S(D)RAM : 0xFFFC1000
|
||||
; Generic Quad-SPI Controller base: 0xFF0F0000
|
||||
; FLASH: MT25QU512 (Micron)
|
||||
;
|
||||
; Based on Lauterbach TRACE32 ZCU102 QSPI demo scripts.
|
||||
|
||||
LOCAL &arg1
|
||||
ENTRY &arg1
|
||||
&arg1=STRing.UPpeR("&arg1") // for example "PREPAREONLY"
|
||||
&dualqspi=1 ; dual(1) or single(0)
|
||||
|
||||
; Adjust to your TRACE32 installation path
|
||||
LOCAL &pdd
|
||||
&pdd="C:/T32/demo/arm"
|
||||
|
||||
SYStem.RESet
|
||||
SYStem.CPU ZYNQ-ULTRASCALE+-APU
|
||||
SYStem.MemAccess DAP
|
||||
CORE.ASSIGN 1.
|
||||
ETM.OFF
|
||||
Trace.DISable
|
||||
|
||||
; <temporarily switch to BOOTMODE=JTAG>
|
||||
; this sequence forces the SoC to use BOOTMODE=JTAG
|
||||
; a SRST is issued using the debug logic
|
||||
; we use the first A53 for flash programming
|
||||
SYStem.Option ResBreak OFF
|
||||
SYStem.Option EnReset OFF
|
||||
SYStem.Option TRST OFF
|
||||
DO &pdd/hardware/zynq_ultrascale/scripts/zynq-ultrascale_reset.cmm OVERRIDE_BOOTMODE=0x0
|
||||
SYStem.Mode Prepare
|
||||
DO &pdd/hardware/zynq_ultrascale/scripts/zynq-ultrascale_kick_bootcore.cmm "A53_X64"
|
||||
SYStem.Mode.Attach
|
||||
Break.direct
|
||||
; </temporarily switch to BOOTMODE=JTAG>
|
||||
|
||||
SYStem.JtagClock CTCK 24MHz
|
||||
|
||||
; --------------------------------------------------------------------------------
|
||||
; peripheral initializations
|
||||
|
||||
//Pin muxing MIO configuration MIO[0:12]
|
||||
|
||||
Data.Set A:0xFF5E0068 %LE %Long 0x01010c00 ;QSPI_REF_CTRL
|
||||
|
||||
&addr=0xFF180000
|
||||
RePeaT 13.
|
||||
(
|
||||
Data.Set A:&addr %LE %Long 0x2
|
||||
&addr=&addr+0x4
|
||||
)
|
||||
|
||||
Data.Set A:0xFF180204 %LE %Long 0x2240000
|
||||
|
||||
Data.Set A:0xFF5E0238 %Long 0x17FFFE
|
||||
|
||||
IF &dualqspi==1
|
||||
GOSUB READ_ID_TEST_DUAL
|
||||
ELSE
|
||||
GOSUB READ_ID_TEST
|
||||
|
||||
Data.Set A:0xFF0F0144 %LE %Long 1 ;enable GQSPI_SEL
|
||||
Data.Set A:0xFF0F010C %Long 0x0FBE ; Interrupt disable register
|
||||
Data.Set A:0xFF0F0128 %Long 0x01 ; thres hold
|
||||
Data.Set A:0xFF0F012C %Long 0x01 ; thres hold
|
||||
Data.Set A:0xFF0F0104 %Long 0x0FBE ; Interrupt status register
|
||||
|
||||
Data.Set A:0xFF0F014C %Long 0x7 ; reset tx fifo and gen_fifo..
|
||||
WAIT 100.ms
|
||||
Data.Set A:0xFF0F0100 %Long 0x00080010 ;Config register, clk speed control[5:3] , mode==00 [31:30] I/O mode
|
||||
|
||||
;The flash dualport works only under the non-secure mode for the ZYNQ-ULTRASCALE+
|
||||
SYStem.MemAccess DAP
|
||||
Register.Set NS 1.
|
||||
Register.Set M 0x5 ;EL1h
|
||||
|
||||
; --------------------------------------------------------------------------------
|
||||
; Flash Declaration
|
||||
|
||||
Break.RESet
|
||||
|
||||
FLASHFILE.RESet
|
||||
FLASHFILE.CONFIG 0xFF0F0000
|
||||
|
||||
IF &dualqspi==1
|
||||
FLASHFILE.TARGET 0xFFFC1000++0x2FFF E:0xFFFC4000++0x27FF &pdd/flash/word/spiw4b64_zynqultra.bin /KEEP /STACKSIZE 0x400 /DUALPORT
|
||||
ELSE
|
||||
FLASHFILE.TARGET 0xFFFC1000++0x2FFF E:0xFFFC4000++0x27FF &pdd/flash/byte/spi4b64fs_zynqultra.bin /KEEP /STACKSIZE 0x400 /DUALPORT
|
||||
|
||||
FLASHFILE.GETID
|
||||
|
||||
//End of the test prepareonly
|
||||
IF "&arg1"=="PREPAREONLY"
|
||||
ENDDO
|
||||
|
||||
; Save Whole Flash
|
||||
;FLASHFILE.SAVE "flash_dump.bin" 0x0++0x1FFFFFFF
|
||||
|
||||
FLASHFILE.Create 0x0--0x1FFFFFFF 0x20000 Byte
|
||||
|
||||
; Flash BOOT.BIN (wolfBoot) at offset 0x0
|
||||
DIALOG.YESNO "Flash wolfBoot BOOT.BIN now?"
|
||||
ENTRY &programnow
|
||||
if &programnow
|
||||
(
|
||||
FLASHFILE.ReProgram ALL
|
||||
FLASHFILE.Load "BOOT.BIN" 0x0
|
||||
FLASHFILE.ReProgram off
|
||||
)
|
||||
|
||||
; Flash signed application image at partition offset
|
||||
DIALOG.YESNO "Flash signed application image now?"
|
||||
ENTRY &programnow
|
||||
if &programnow
|
||||
(
|
||||
FLASHFILE.ReProgram ALL
|
||||
FLASHFILE.Load "test-app/image_v1_signed.bin" 0x7000000
|
||||
FLASHFILE.ReProgram off
|
||||
)
|
||||
|
||||
ENDDO
|
||||
|
||||
; --------------------------------------------------------------------------------
|
||||
; Subroutines
|
||||
|
||||
READ_ID_TEST:
|
||||
(
|
||||
Data.Set A:0xFF0F0144 %LE %Long 1 ;enable GQSPI_SEL
|
||||
Data.Set A:0xFF0F010C %Long 0x0FBE ;Interrupt disable register
|
||||
Data.Set A:0xFF0F0128 %Long 0x01 ;thres hold
|
||||
Data.Set A:0xFF0F012C %Long 0x01 ;thres hold
|
||||
Data.Set A:0xFF0F0104 %Long 0x0FBE ;Interrupt status register
|
||||
|
||||
;read A:0xFF0F0100 -> 0x0
|
||||
|
||||
Data.Set A:0xFF0f014c %Long 0x7 ; reset tx fifo and gen_fifo..
|
||||
WAIT 100.ms
|
||||
|
||||
Data.Set A:0xFF0F0100 %Long 0x00080010 ;Config register, clk speed control[5:3] , mode==00 [31:30] I/O mode
|
||||
|
||||
&dat_xfer=0x1<<8.
|
||||
&spimode=0x1<<10.
|
||||
&cs_lower=0x1<<12.
|
||||
&cs_upper=0x1<<13.
|
||||
&bus_lower=0x1<<14.
|
||||
&bus_upper=0x2<<14.
|
||||
&bus_both=0x3<<14.
|
||||
&transmit=0x1<<16.
|
||||
&receive=0x1<<17.
|
||||
&stripe=0x1<<18.
|
||||
|
||||
Data.Set A:0xFF0F0114 %Long 0x1 ;spi enable register , cs low
|
||||
|
||||
Data.Set A:0xFF0F011C %Long 0x9f ; tx, data transfer
|
||||
Data.Set A:0xFF0F0140 %Long &transmit|&receive|&bus_lower|&cs_lower|&spimode|&dat_xfer|0x1
|
||||
PRINT "read 0x" Data.Long(A:0xff0f0120) " (dummy)"
|
||||
|
||||
Data.Set A:0xFF0F011C %Long 0x00 ; tx, data transfer
|
||||
Data.Set A:0xFF0F0140 %Long &transmit|&receive|&bus_lower|&cs_lower|&spimode|&dat_xfer|0x1
|
||||
PRINT "read 0x" Data.Long(A:0xff0f0120) " (manufacture id)"
|
||||
|
||||
Data.Set A:0xFF0F011C %Long 0x00 ; tx, data transfer
|
||||
Data.Set A:0xFF0F0140 %Long &transmit|&receive|&bus_lower|&cs_lower|&spimode|&dat_xfer|0x1
|
||||
PRINT "read 0x" Data.Long(A:0xff0f0120) " (device id)"
|
||||
|
||||
Data.Set A:0xFF0F011C %Long 0x00 ; tx, data transfer
|
||||
Data.Set A:0xFF0F0140 %Long &transmit|&receive|&bus_lower|&cs_lower|&spimode|&dat_xfer|0x1
|
||||
PRINT "read 0x" Data.Long(A:0xff0f0120)
|
||||
|
||||
Data.Set A:0xFF0F0114 %Long 0x0 ;spi disable, cs high
|
||||
|
||||
RETURN
|
||||
)
|
||||
|
||||
|
||||
READ_ID_TEST_DUAL:
|
||||
(
|
||||
Data.Set A:0xFF0F0144 %LE %Long 1 ;enable GQSPI_SEL
|
||||
Data.Set A:0xFF0F010C %Long 0x0FBE ;Interrupt disable register
|
||||
Data.Set A:0xFF0F0128 %Long 0x01 ;thres hold
|
||||
Data.Set A:0xFF0F012C %Long 0x01 ;thres hold
|
||||
Data.Set A:0xFF0F0104 %Long 0x0FBE ;Interrupt status register
|
||||
|
||||
;read A:0xFF0F0100 -> 0x0
|
||||
|
||||
Data.Set A:0xFF0f014c %Long 0x7 ; reset tx fifo and gen_fifo..
|
||||
WAIT 100.ms
|
||||
|
||||
Data.Set A:0xFF0F0100 %Long 0x00080010 ;Config register, clk speed control[5:3] , mode==00 [31:30] I/O mode
|
||||
|
||||
&dat_xfer=0x1<<8.
|
||||
&spimode=0x1<<10.
|
||||
&cs_lower=0x1<<12.
|
||||
&cs_upper=0x1<<13.
|
||||
&bus_lower=0x1<<14.
|
||||
&bus_upper=0x2<<14.
|
||||
&bus_both=0x3<<14.
|
||||
&transmit=0x1<<16.
|
||||
&receive=0x1<<17.
|
||||
&stripe=0x1<<18.
|
||||
|
||||
Data.Set A:0xFF0F0114 %Long 0x1 ;spi enable register , cs low
|
||||
|
||||
Data.Set A:0xFF0F011C %Long 0x00009f9f ; tx, data transfer
|
||||
Data.Set A:0xFF0F0140 %Long &stripe|&transmit|&receive|&bus_both|&cs_lower|&cs_upper|&spimode|&dat_xfer|0x4 ; tx,4 byte data transfer
|
||||
PRINT "read 0x" Data.Long(A:0xff0f0120)
|
||||
|
||||
Data.Set A:0xFF0F011C %Long 0x00000000 ; tx, data transfer
|
||||
Data.Set A:0xFF0F0140 %Long &stripe|&transmit|&receive|&bus_both|&cs_lower|&cs_upper|&spimode|&dat_xfer|0x4 ; tx,4 byte data transfer
|
||||
PRINT "read 0x" Data.Long(A:0xff0f0120)
|
||||
|
||||
Data.Set A:0xFF0F011C %Long 0x00000000 ; tx, data transfer
|
||||
Data.Set A:0xFF0F0140 %Long &stripe|&transmit|&receive|&bus_both|&cs_lower|&cs_upper|&spimode|&dat_xfer|0x4 ; tx,4 byte data transfer
|
||||
PRINT "read 0x" Data.Long(A:0xff0f0120)
|
||||
|
||||
Data.Set A:0xFF0F011C %Long 0x00000000 ; tx, data transfer
|
||||
Data.Set A:0xFF0F0140 %Long &stripe|&transmit|&receive|&bus_both|&cs_lower|&cs_upper|&spimode|&dat_xfer|0x4 ; tx,4 byte data transfer
|
||||
PRINT "read 0x" Data.Long(A:0xff0f0120)
|
||||
|
||||
Data.Set A:0xFF0F0114 %Long 0x0 ;spi disable, cs high
|
||||
|
||||
RETURN
|
||||
)
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
; ZCU102 wolfBoot Debug Script
|
||||
;
|
||||
; Debug wolfBoot on Zynq UltraScale+ ZCU102.
|
||||
; Based on Lauterbach TRACE32 ZCU102 demo scripts.
|
||||
;
|
||||
; Prerequisites:
|
||||
; * Connect Debug Cable to J6
|
||||
; * set SW6 = 0y1111 (JTAG Bootmode)
|
||||
|
||||
; --------------------------------------------------------------------------------
|
||||
; initialize and start the debugger
|
||||
SYStem.RESet
|
||||
SYStem.CPU ZYNQ-ULTRASCALE+-APU
|
||||
SYStem.Option TRST OFF
|
||||
SYStem.Option ResBreak OFF
|
||||
SYStem.Option WaitDAPPWR ON
|
||||
SYStem.JtagClock CTCK 20MHz
|
||||
CORE.ASSIGN 1.
|
||||
; disable Trace infrastructure for the moment - TPIU may be unclocked!
|
||||
ETM.OFF
|
||||
Trace.DISable
|
||||
|
||||
SYStem.Mode Prepare
|
||||
;GOSUB DisableWatchdog
|
||||
;DO "C:/T32/demo/arm/hardware/zynq_ultrascale/scripts/zynq-ultrascale_kick_bootcore.cmm" A53_X64
|
||||
|
||||
SYStem.Mode.Attach
|
||||
|
||||
|
||||
; --------------------------------------------------------------------------------
|
||||
; Load symbols for wolfBoot
|
||||
sYmbol.SourcePATH.SetBaseDir "."
|
||||
|
||||
Data.LOAD.Elf "wolfboot.elf" /NoCode
|
||||
;Data.LOAD.Elf "test-app/image.elf" /NoClear /NoCode
|
||||
|
||||
IF STATE.RUN()
|
||||
Break.direct
|
||||
|
||||
B.Delete
|
||||
B.Set wolfBoot_start
|
||||
|
||||
ENDDO
|
||||
|
||||
; ================================================================================
|
||||
DisableWatchdog:
|
||||
(
|
||||
PRIVATE &swdtMode
|
||||
|
||||
&swdtMode=Data.Long(ENAXI:0xFF150000)
|
||||
&swdtMode=&swdtMode&0xFFE ; Mode.WDEN = 0
|
||||
&swdtMode=&swdtMode+0xABC000 ; zKEY
|
||||
|
||||
Data.Set ENAXI:0xFF150000 %LE %Long &swdtMode
|
||||
)
|
||||
RETURN
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
; ZCU102 TRACE32 Window Layout Script
|
||||
|
||||
B::
|
||||
|
||||
; Set working directory to wolfboot root
|
||||
;ChDir "~/wolfboot"
|
||||
|
||||
TOOLBAR ON
|
||||
STATUSBAR ON
|
||||
FramePOS 313.29 58.733 363. 116.
|
||||
WinPAGE.RESet
|
||||
|
||||
WinPAGE.Create P000
|
||||
WinCLEAR
|
||||
|
||||
WinPOS 214.0 1.8 142. 5. 27. 1. W003
|
||||
WinTABS 13. 16. 0. 0. 0. 0. 0. 0. 0. 71.
|
||||
B.List
|
||||
|
||||
WinPOS 0.0 0.0 151. 58. 14. 0. W008
|
||||
PEDIT "tools/scripts/zcu102/zcu102-ca53-qspi.cmm"
|
||||
|
||||
WinPOS 2.1429 1.2667 154. 59. 14. 0. W000
|
||||
PEDIT "tools/scripts/zcu102/zcu102-debug-uboot.cmm"
|
||||
|
||||
WinPOS 4.2857 2.5333 156. 59. 14. 0. W004
|
||||
PEDIT "tools/scripts/zcu102/zcu102-debug-wolfboot.cmm"
|
||||
|
||||
WinPOS 53.571 11.333 164. 76. 24. 1. W001
|
||||
WinTABS 13. 18. 25.
|
||||
List.auto
|
||||
|
||||
WinPOS 228.0 12.933 128. 25. 5. 0. W005
|
||||
Frame
|
||||
|
||||
WinPOS 255.43 43.067 100. 25. 0. 0. W009
|
||||
Var.Local
|
||||
WinPAN 0. 6.
|
||||
|
||||
WinPOS 264.14 71.333 92. 29. 0. 0. W007
|
||||
Register
|
||||
|
||||
WinPOS 1.4286 78.467 154. 23. 0. 0. W002
|
||||
AREA
|
||||
|
||||
WinPAGE.select P000
|
||||
|
||||
ENDDO
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
// Boot BIF for wolfBoot ZynqMP SD Card Boot
|
||||
// FSBL -> PMUFW -> BL31 (EL3) -> wolfBoot (EL2)
|
||||
// wolfBoot loads firmware from MBR partitions on SD card
|
||||
//
|
||||
// Usage:
|
||||
// bootgen -arch zynqmp -image zynqmp_sd_boot.bif -w -o BOOT.BIN
|
||||
//
|
||||
// Required files (copy to same directory):
|
||||
// zynqmp_fsbl.elf - First Stage Boot Loader
|
||||
// pmufw.elf - Platform Management Unit firmware
|
||||
// bl31.elf - ARM Trusted Firmware (EL3)
|
||||
// wolfboot.elf - wolfBoot bootloader
|
||||
//
|
||||
// Optional:
|
||||
// system.bit - PL bitstream (uncomment line below)
|
||||
the_ROM_image:
|
||||
{
|
||||
[bootloader, destination_cpu=a53-0] zynqmp_fsbl.elf
|
||||
[pmufw_image] pmufw.elf
|
||||
// [destination_device=pl] system.bit
|
||||
[destination_cpu=a53-0, exception_level=el-3, trustzone] bl31.elf
|
||||
[destination_cpu=a53-0, exception_level=el-2] wolfboot.elf
|
||||
}
|
||||
Loading…
Reference in New Issue