Skip to content

Commit dae84a8

Browse files
committed
Cleanups and added BOOT_EL2 option.
1 parent f3f8f53 commit dae84a8

File tree

5 files changed

+97
-109
lines changed

5 files changed

+97
-109
lines changed

config/examples/versal_vmk180.config

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,15 @@ WOLFTPM?=0
4747
EXT_FLASH?=1
4848
NO_XIP=1
4949

50+
# Boot Exception Level
51+
# Choose the exception level for booting applications (mutually exclusive):
52+
# BOOT_EL1: Transition applications to EL1 (default - for Linux, most bare-metal)
53+
# BOOT_EL2: Boot applications at EL2 (for hypervisors, RTOSes that expect EL2)
54+
# Default is BOOT_EL1 if neither is specified.
55+
# Uncomment one of the following to override:
56+
#BOOT_EL1=1
57+
#BOOT_EL2=1
58+
5059
# ELF loading support
5160
ELF?=1
5261

hal/versal.c

Lines changed: 50 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,6 @@ void uart_init(void)
117117
/* When booting via PLM -> BL31 -> wolfBoot (EL2), UART is already
118118
* fully configured by PLM. Do NOT reinitialize - just use it as-is.
119119
* Any reconfiguration at EL2 may fail or corrupt the UART state. */
120-
(void)0; /* UART already configured by PLM - nothing to do */
121120
#else
122121
/* Full UART initialization for JTAG boot mode or EL3 boot */
123122
uint32_t ibrd, fbrd;
@@ -237,72 +236,42 @@ void uart_write(const char *buf, uint32_t len)
237236
* ============================================================================
238237
*/
239238

240-
/**
241-
* Get current timer count (physical counter)
242-
*/
239+
/* Get current timer count (physical counter) */
243240
static inline uint64_t timer_get_count(void)
244241
{
245242
uint64_t cntpct;
246243
__asm__ volatile("mrs %0, cntpct_el0" : "=r" (cntpct));
247244
return cntpct;
248245
}
249246

250-
/**
251-
* Get timer frequency
252-
*/
247+
/* Get timer frequency with fallback to TIMER_CLK_FREQ if not configured */
253248
static inline uint64_t timer_get_freq(void)
254249
{
255250
uint64_t cntfrq;
256251
__asm__ volatile("mrs %0, cntfrq_el0" : "=r" (cntfrq));
257-
return cntfrq;
252+
return cntfrq ? cntfrq : TIMER_CLK_FREQ;
258253
}
259254

260-
/**
261-
* Get current time in milliseconds
262-
*/
255+
/* Get current time in milliseconds */
263256
uint64_t hal_timer_ms(void)
264257
{
265-
uint64_t cntpct = timer_get_count();
266-
uint64_t cntfrq = timer_get_freq();
267-
268-
if (cntfrq == 0)
269-
cntfrq = TIMER_CLK_FREQ;
270-
271-
/* Convert to milliseconds: (count * 1000) / freq */
272-
return (cntpct * 1000ULL) / cntfrq;
258+
return (timer_get_count() * 1000ULL) / timer_get_freq();
273259
}
274260

275-
/**
276-
* Delay for specified number of microseconds
277-
*/
261+
/* Delay for specified number of microseconds */
278262
void hal_delay_us(uint32_t us)
279263
{
280-
uint64_t cntfrq = timer_get_freq();
281-
uint64_t start, target;
282-
283-
if (cntfrq == 0)
284-
cntfrq = TIMER_CLK_FREQ;
285-
286-
start = timer_get_count();
287-
target = start + ((uint64_t)us * cntfrq) / 1000000ULL;
264+
uint64_t freq = timer_get_freq();
265+
uint64_t target = timer_get_count() + ((uint64_t)us * freq) / 1000000ULL;
288266

289267
while (timer_get_count() < target)
290268
;
291269
}
292270

293-
/**
294-
* Get current time in microseconds (for benchmarking)
295-
*/
271+
/* Get current time in microseconds (for benchmarking) */
296272
uint64_t hal_get_timer_us(void)
297273
{
298-
uint64_t cntpct = timer_get_count();
299-
uint64_t cntfrq = timer_get_freq();
300-
301-
if (cntfrq == 0)
302-
cntfrq = TIMER_CLK_FREQ;
303-
304-
/* Convert to microseconds: (count * 1000000) / freq */
305-
return (cntpct * 1000000ULL) / cntfrq;
274+
return (timer_get_count() * 1000000ULL) / timer_get_freq();
306275
}
307276

308277

@@ -351,6 +320,19 @@ typedef struct {
351320
uint32_t stripe; /* 0 or GQSPI_GEN_FIFO_STRIPE for dual parallel */
352321
} QspiDev_t;
353322

323+
/* Macros to configure QspiDev_t for single-chip access in dual-parallel mode */
324+
#define QSPI_DEV_LOWER(tmpDev, srcDev) do { \
325+
(tmpDev) = *(srcDev); \
326+
(tmpDev).bus = GQSPI_GEN_FIFO_BUS_LOW; \
327+
(tmpDev).cs = GQSPI_GEN_FIFO_CS_LOWER; \
328+
(tmpDev).stripe = 0; \
329+
} while(0)
330+
331+
#define QSPI_DEV_UPPER(tmpDev) do { \
332+
(tmpDev).bus = GQSPI_GEN_FIFO_BUS_UP; \
333+
(tmpDev).cs = GQSPI_GEN_FIFO_CS_UPPER; \
334+
} while(0)
335+
354336
static QspiDev_t qspiDev;
355337
static int qspi_initialized = 0;
356338

@@ -439,16 +421,6 @@ static int qspi_gen_fifo_start_and_wait(void)
439421
return 0;
440422
}
441423

442-
/* Legacy wrapper for compatibility */
443-
static int qspi_gen_fifo_write(uint32_t entry)
444-
{
445-
int ret = qspi_gen_fifo_push(entry);
446-
if (ret == 0) {
447-
ret = qspi_gen_fifo_start_and_wait();
448-
}
449-
return ret;
450-
}
451-
452424
/* Calculate EXP mode for large transfers (returns actual transfer size)
453425
* For transfers > 255 bytes, use exponent mode where IMM = power of 2
454426
* Pattern from zynq.c qspi_calc_exp() */
@@ -480,6 +452,7 @@ static uint32_t qspi_calc_exp(uint32_t xferSz, uint32_t *reg_genfifo)
480452
static int qspi_cs(QspiDev_t *dev, int assert)
481453
{
482454
uint32_t entry;
455+
int ret;
483456

484457
entry = (dev->bus & GQSPI_GEN_FIFO_BUS_MASK) | GQSPI_GEN_FIFO_MODE_SPI;
485458
if (assert) {
@@ -488,7 +461,11 @@ static int qspi_cs(QspiDev_t *dev, int assert)
488461
/* Idle clocks for CS setup/hold */
489462
entry |= GQSPI_GEN_FIFO_IMM(2);
490463

491-
return qspi_gen_fifo_write(entry);
464+
ret = qspi_gen_fifo_push(entry);
465+
if (ret == 0) {
466+
ret = qspi_gen_fifo_start_and_wait();
467+
}
468+
return ret;
492469
}
493470

494471
/* DMA temporary buffer for unaligned transfers (DMA is default, IO is optional) */
@@ -843,29 +820,22 @@ static int qspi_read_id(QspiDev_t *dev, uint8_t *id, uint32_t len)
843820
static int qspi_read_register(QspiDev_t *dev, uint8_t cmd, uint8_t *status)
844821
{
845822
uint8_t cmdByte[1];
846-
uint8_t data[4]; /* Space for 2 bytes from each chip */
823+
uint8_t data[2];
847824
int ret;
848825
QspiDev_t tmpDev;
849826

850827
cmdByte[0] = cmd;
851828

852829
/* For dual parallel, read from each chip separately and AND the results */
853830
if (dev->stripe) {
854-
/* Read from lower chip */
855-
tmpDev = *dev;
856-
tmpDev.bus = GQSPI_GEN_FIFO_BUS_LOW;
857-
tmpDev.cs = GQSPI_GEN_FIFO_CS_LOWER;
858-
tmpDev.stripe = 0;
831+
QSPI_DEV_LOWER(tmpDev, dev);
859832
ret = qspi_transfer(&tmpDev, cmdByte, 1, &data[0], 1, 0, NULL, 0);
860833
if (ret != 0) return ret;
861834

862-
/* Read from upper chip */
863-
tmpDev.bus = GQSPI_GEN_FIFO_BUS_UP;
864-
tmpDev.cs = GQSPI_GEN_FIFO_CS_UPPER;
835+
QSPI_DEV_UPPER(tmpDev);
865836
ret = qspi_transfer(&tmpDev, cmdByte, 1, &data[1], 1, 0, NULL, 0);
866837
if (ret != 0) return ret;
867838

868-
/* AND the status from both chips */
869839
*status = data[0] & data[1];
870840
return 0;
871841
}
@@ -912,17 +882,11 @@ static int qspi_write_enable(QspiDev_t *dev)
912882

913883
/* For dual parallel, send write enable to both chips separately */
914884
if (dev->stripe) {
915-
/* Send to lower chip */
916-
tmpDev = *dev;
917-
tmpDev.bus = GQSPI_GEN_FIFO_BUS_LOW;
918-
tmpDev.cs = GQSPI_GEN_FIFO_CS_LOWER;
919-
tmpDev.stripe = 0;
885+
QSPI_DEV_LOWER(tmpDev, dev);
920886
ret = qspi_transfer(&tmpDev, cmd, sizeof(cmd), NULL, 0, 0, NULL, 0);
921887
if (ret != 0) return ret;
922888

923-
/* Send to upper chip */
924-
tmpDev.bus = GQSPI_GEN_FIFO_BUS_UP;
925-
tmpDev.cs = GQSPI_GEN_FIFO_CS_UPPER;
889+
QSPI_DEV_UPPER(tmpDev);
926890
ret = qspi_transfer(&tmpDev, cmd, sizeof(cmd), NULL, 0, 0, NULL, 0);
927891
if (ret != 0) return ret;
928892
} else {
@@ -1001,13 +965,12 @@ static int qspi_exit_4byte_addr(QspiDev_t *dev)
1001965
#define TEST_EXT_SIZE (FLASH_PAGE_SIZE * 4)
1002966
#endif
1003967

1004-
static int test_ext_flash(QspiDev_t* dev)
968+
static int test_ext_flash(void)
1005969
{
1006970
int ret;
1007971
uint32_t i;
1008972
uint8_t pageData[TEST_EXT_SIZE];
1009973

1010-
(void)dev;
1011974
wolfBoot_printf("Testing ext flash at 0x%x...\n", TEST_EXT_ADDRESS);
1012975

1013976
#ifndef TEST_FLASH_READONLY
@@ -1121,7 +1084,7 @@ static void qspi_init(void)
11211084
qspiDev.stripe = 0;
11221085

11231086
memset(id, 0, sizeof(id));
1124-
ret = qspi_read_id(&qspiDev, id, 3);
1087+
(void)qspi_read_id(&qspiDev, id, 3);
11251088
wolfBoot_printf("QSPI: Lower ID: %02x %02x %02x\n", id[0], id[1], id[2]);
11261089

11271090
#if GQPI_USE_4BYTE_ADDR == 1
@@ -1138,7 +1101,7 @@ static void qspi_init(void)
11381101
qspiDev.cs = GQSPI_GEN_FIFO_CS_UPPER;
11391102

11401103
memset(id, 0, sizeof(id));
1141-
ret = qspi_read_id(&qspiDev, id, 3);
1104+
(void)qspi_read_id(&qspiDev, id, 3);
11421105
wolfBoot_printf("QSPI: Upper ID: %02x %02x %02x\n", id[0], id[1], id[2]);
11431106

11441107
#if GQPI_USE_4BYTE_ADDR == 1
@@ -1157,27 +1120,27 @@ static void qspi_init(void)
11571120
#endif
11581121

11591122
/* QSPI bare-metal driver info */
1160-
wolfBoot_printf("QSPI: %dMHz, %s mode, %s\n",
1161-
(GQSPI_CLK_REF / (2 << GQSPI_CLK_DIV)) / 1000000,
1123+
{
11621124
#if GQSPI_QSPI_MODE == GQSPI_GEN_FIFO_MODE_QSPI
1163-
"Quad"
1125+
const char *mode_str = "Quad";
11641126
#elif GQSPI_QSPI_MODE == GQSPI_GEN_FIFO_MODE_DSPI
1165-
"Dual"
1127+
const char *mode_str = "Dual";
11661128
#else
1167-
"SPI"
1129+
const char *mode_str = "SPI";
11681130
#endif
1169-
,
11701131
#ifdef GQSPI_MODE_IO
1171-
"Poll"
1132+
const char *xfer_str = "Poll";
11721133
#else
1173-
"DMA"
1134+
const char *xfer_str = "DMA";
11741135
#endif
1175-
);
1136+
wolfBoot_printf("QSPI: %dMHz, %s, %s\n",
1137+
(GQSPI_CLK_REF / (2 << GQSPI_CLK_DIV)) / 1000000, mode_str, xfer_str);
1138+
}
11761139

11771140
qspi_initialized = 1;
11781141

11791142
#ifdef TEST_EXT_FLASH
1180-
test_ext_flash(&qspiDev);
1143+
test_ext_flash();
11811144
#endif
11821145
}
11831146

@@ -1238,11 +1201,11 @@ void hal_prepare_boot(void)
12381201
/* Clean entire D-cache to Point of Coherency */
12391202
__asm__ volatile("dsb sy");
12401203

1241-
/* Clean D-cache for application region (0x10000000, 1MB should be enough) */
1204+
/* Clean D-cache for application region */
12421205
{
12431206
uintptr_t addr;
1244-
uintptr_t end = 0x10000000 + (1 * 1024 * 1024);
1245-
for (addr = 0x10000000; addr < end; addr += 64) {
1207+
uintptr_t end = WOLFBOOT_LOAD_ADDRESS + APP_CACHE_FLUSH_SIZE;
1208+
for (addr = WOLFBOOT_LOAD_ADDRESS; addr < end; addr += CACHE_LINE_SIZE) {
12461209
/* DC CVAC - Clean data cache line by VA to PoC */
12471210
__asm__ volatile("dc cvac, %0" : : "r"(addr));
12481211
}

hal/versal.h

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -76,14 +76,25 @@
7676
* ============================================================================
7777
* SKIP_GIC_INIT: Versal uses GICv3 (not GICv2 like ZynqMP).
7878
* BL31 handles GIC initialization, so skip gicv2_init_secure().
79-
* BOOT_EL1: wolfBoot runs at EL2, but applications (Linux, test-app)
80-
* expect EL1. Transition from EL2 to EL1 before jumping to app.
79+
*
80+
* Boot Exception Level Configuration (mutually exclusive):
81+
* BOOT_EL1: wolfBoot runs at EL2, but applications (Linux, most bare-metal)
82+
* are transitioned to EL1 before jumping (default)
83+
* BOOT_EL2: Applications boot at EL2 (for hypervisors/RTOSes that
84+
* expect to run at EL2)
85+
*
86+
* Default: BOOT_EL1 (most applications expect EL1)
8187
*/
8288
#ifndef SKIP_GIC_INIT
8389
#define SKIP_GIC_INIT 1
8490
#endif
85-
#ifndef BOOT_EL1
86-
#define BOOT_EL1 1
91+
92+
#if !defined(BOOT_EL1) && !defined(BOOT_EL2)
93+
#define BOOT_EL1 1
94+
#endif
95+
96+
#if defined(BOOT_EL1) && defined(BOOT_EL2)
97+
#error "BOOT_EL1 and BOOT_EL2 are mutually exclusive"
8798
#endif
8899

89100

@@ -102,6 +113,13 @@
102113
#define VERSAL_DDR_1_BASE 0x800000000ULL
103114
#define VERSAL_DDR_1_HIGH 0x87FFFFFFFULL
104115

116+
/* Application load address and cache flush size for hal_prepare_boot() */
117+
#ifndef WOLFBOOT_LOAD_ADDRESS
118+
#define WOLFBOOT_LOAD_ADDRESS 0x10000000UL
119+
#endif
120+
#define CACHE_LINE_SIZE 64
121+
#define APP_CACHE_FLUSH_SIZE (1 * 1024 * 1024) /* 1MB */
122+
105123
/* DDR defines for MMU table setup (used by boot_aarch64_start.S)
106124
* These macros enable proper DDR mapping in the page tables.
107125
* Without these, the MMU tables would have DDR_0_REG=0 and no DDR mapped! */
@@ -299,10 +317,9 @@
299317

300318

301319
/* ============================================================================
302-
* Clock and Reset (CRL/CRF)
320+
* Clock and Reset (CRF - FPD only, CRL defined above)
303321
* ============================================================================
304322
*/
305-
#define VERSAL_CRL_BASE 0xFF5E0000UL /* Clock and Reset LPD */
306323
#define VERSAL_CRF_BASE 0xFD1A0000UL /* Clock and Reset FPD */
307324

308325

options.mk

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -607,9 +607,19 @@ endif
607607
ifeq ($(SKIP_GIC_INIT),1)
608608
CFLAGS+=-D"SKIP_GIC_INIT"
609609
endif
610+
611+
# Boot Exception Level (mutually exclusive)
610612
ifeq ($(BOOT_EL1),1)
613+
ifeq ($(BOOT_EL2),1)
614+
$(error BOOT_EL1 and BOOT_EL2 are mutually exclusive. Choose one.)
615+
endif
611616
CFLAGS+=-D"BOOT_EL1"
612617
endif
618+
619+
ifeq ($(BOOT_EL2),1)
620+
CFLAGS+=-D"BOOT_EL2"
621+
endif
622+
613623
ifeq ($(BOOT_BENCHMARK),1)
614624
CFLAGS+=-D"BOOT_BENCHMARK"
615625
endif

0 commit comments

Comments
 (0)