Skip to content

Commit d91555f

Browse files
dgarskedanielinux
authored andcommitted
Peer review fixes
1 parent da6e1ab commit d91555f

File tree

5 files changed

+114
-81
lines changed

5 files changed

+114
-81
lines changed

config/examples/polarfire_mpfs250_qspi.config

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ WOLFBOOT_SECTOR_SIZE?=0x10000
7272
# HSS Boot Info: 0x00000000 - 0x00000400 (1KB)
7373
# wolfBoot partition: 0x00000400 - 0x0001FFFF (127KB)
7474
# Boot partition: 0x00020000 - 0x01FFFFFF (~32MB)
75-
# Update partition: 0x02000000 - 0x03FFFFFF (32MB)
75+
# Update partition: 0x02000000 - 0x03FFFFFF (~32MB)
7676
# Swap partition: 0x04000000 - 0x0400FFFF (64KB)
7777
# Remaining: 0x04010000 - 0x07FFFFFF (~64MB available)
7878
WOLFBOOT_PARTITION_SIZE?=0x1FE0000

hal/mpfs250.c

Lines changed: 81 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,13 @@ void hal_init(void)
6666
#endif
6767

6868
#ifdef EXT_FLASH
69-
qspi_init();
70-
69+
if (qspi_init() != 0) {
70+
wolfBoot_printf("QSPI: Init failed\n");
71+
}
7172
#if defined(TEST_EXT_FLASH) && defined(__WOLFBOOT)
72-
test_ext_flash();
73+
else {
74+
test_ext_flash();
75+
}
7376
#endif
7477
#endif /* EXT_FLASH */
7578
}
@@ -82,24 +85,16 @@ void hal_init(void)
8285
* and responses are read from the mailbox RAM.
8386
* ============================================================================ */
8487

85-
static int mpfs_scb_is_busy(void)
86-
{
87-
return (SCBCTRL_REG(SERVICES_SR_OFFSET) & SERVICES_SR_BUSY_MASK);
88-
}
89-
90-
static int mpfs_scb_wait_ready(uint32_t timeout)
88+
/* Wait for SCB register bits to clear, with timeout */
89+
static int mpfs_scb_wait_clear(uint32_t reg_offset, uint32_t mask,
90+
uint32_t timeout)
9191
{
92-
while (mpfs_scb_is_busy() && timeout > 0) {
93-
timeout--;
94-
}
95-
96-
if (timeout == 0) {
97-
return -1;
98-
}
99-
return 0;
92+
while ((SCBCTRL_REG(reg_offset) & mask) && --timeout)
93+
;
94+
return (timeout == 0) ? -1 : 0;
10095
}
10196

102-
static int mpfs_scb_read_mailbox(uint8_t *out, uint32_t len)
97+
int mpfs_scb_read_mailbox(uint8_t *out, uint32_t len)
10398
{
10499
uint32_t i;
105100

@@ -139,27 +134,13 @@ static void mpfs_scb_write_mailbox(const uint8_t *data, uint32_t len)
139134
}
140135
}
141136

142-
static int mpfs_scb_wait_req_clear(uint32_t timeout)
143-
{
144-
while ((SCBCTRL_REG(SERVICES_CR_OFFSET) & SERVICES_CR_REQ_MASK) &&
145-
timeout > 0) {
146-
timeout--;
147-
}
148-
149-
if (timeout == 0) {
150-
return -1;
151-
}
152-
return 0;
153-
}
154-
155-
static int mpfs_scb_service_call_timeout(uint8_t opcode, const uint8_t *mb_data,
156-
uint32_t mb_len, uint32_t req_timeout,
157-
uint32_t busy_timeout)
137+
int mpfs_scb_service_call(uint8_t opcode, const uint8_t *mb_data,
138+
uint32_t mb_len, uint32_t timeout)
158139
{
159140
uint32_t cmd;
160141
uint32_t status;
161142

162-
if (mpfs_scb_is_busy()) {
143+
if (mpfs_scb_wait_clear(SERVICES_SR_OFFSET, SERVICES_SR_BUSY_MASK, 1)) {
163144
return -1;
164145
}
165146

@@ -171,26 +152,25 @@ static int mpfs_scb_service_call_timeout(uint8_t opcode, const uint8_t *mb_data,
171152
SERVICES_CR_REQ_MASK;
172153
SCBCTRL_REG(SERVICES_CR_OFFSET) = cmd;
173154

174-
if (mpfs_scb_wait_req_clear(req_timeout) < 0) {
155+
if (mpfs_scb_wait_clear(SERVICES_CR_OFFSET, SERVICES_CR_REQ_MASK,
156+
timeout) < 0) {
175157
return -2;
176158
}
177159

178-
if (mpfs_scb_wait_ready(busy_timeout) < 0) {
160+
if (mpfs_scb_wait_clear(SERVICES_SR_OFFSET, SERVICES_SR_BUSY_MASK,
161+
timeout) < 0) {
179162
return -3;
180163
}
181164

182-
status = (SCBCTRL_REG(SERVICES_SR_OFFSET) >> SERVICES_SR_STATUS_SHIFT) & 0xFFFF;
165+
status = (SCBCTRL_REG(SERVICES_SR_OFFSET) >> SERVICES_SR_STATUS_SHIFT)
166+
& 0xFFFF;
183167
if (status != 0) {
184168
return -4;
185169
}
186170

187171
return 0;
188172
}
189173

190-
static int mpfs_scb_service_call(uint8_t opcode, const uint8_t *mb_data, uint32_t mb_len)
191-
{
192-
return mpfs_scb_service_call_timeout(opcode, mb_data, mb_len, 10000, 10000);
193-
}
194174
/**
195175
* mpfs_read_serial_number - Read the device serial number via system services
196176
* @serial: Buffer to store the 16-byte device serial number
@@ -200,15 +180,16 @@ static int mpfs_scb_service_call(uint8_t opcode, const uint8_t *mb_data, uint32_
200180
*
201181
* Returns: 0 on success, negative error code on failure
202182
*/
203-
static int mpfs_read_serial_number(uint8_t *serial)
183+
int mpfs_read_serial_number(uint8_t *serial)
204184
{
205185
int ret;
206186

207187
if (serial == NULL) {
208188
return -1;
209189
}
210190

211-
ret = mpfs_scb_service_call(SYS_SERV_CMD_SERIAL_NUMBER, NULL, 0);
191+
ret = mpfs_scb_service_call(SYS_SERV_CMD_SERIAL_NUMBER, NULL, 0,
192+
MPFS_SCB_TIMEOUT);
212193
if (ret != 0) {
213194
wolfBoot_printf("SCB mailbox error: %d\n", ret);
214195
return ret;
@@ -335,10 +316,9 @@ int hal_dts_fixup(void* dts_addr)
335316

336317
return 0;
337318
}
319+
338320
void hal_prepare_boot(void)
339321
{
340-
/* reset the eMMC/SD card? */
341-
342322

343323
}
344324

@@ -400,16 +380,18 @@ static void qspi_flash_wakeup(void)
400380
udelay(10);
401381
}
402382

403-
void qspi_init(void)
383+
int qspi_init(void)
404384
{
405385
uint8_t id[3];
386+
uint32_t timeout;
406387

407388
#ifdef MPFS_SC_SPI
408389
wolfBoot_printf("QSPI: Using SC QSPI Controller (0x%x)\n", QSPI_BASE);
409390

410391
/* Wait for system controller to finish any pending operations before
411392
* taking direct control of the SC QSPI peripheral */
412-
mpfs_scb_wait_ready(100000);
393+
mpfs_scb_wait_clear(SERVICES_SR_OFFSET, SERVICES_SR_BUSY_MASK,
394+
QSPI_TIMEOUT_TRIES);
413395

414396
#ifdef DEBUG_QSPI
415397
wolfBoot_printf("QSPI: Initial CTRL=0x%x, STATUS=0x%x, DIRECT=0x%x\n",
@@ -449,7 +431,12 @@ void qspi_init(void)
449431
QSPI_CTRL_EN;
450432

451433
/* Wait for controller to be ready */
452-
while (!(QSPI_STATUS & QSPI_STATUS_READY));
434+
timeout = QSPI_TIMEOUT_TRIES;
435+
while (!(QSPI_STATUS & QSPI_STATUS_READY) && --timeout);
436+
if (timeout == 0) {
437+
wolfBoot_printf("QSPI: Controller not ready\n");
438+
return -1;
439+
}
453440

454441
/* Wake up flash from deep power-down (if applicable) */
455442
qspi_flash_wakeup();
@@ -462,6 +449,8 @@ void qspi_init(void)
462449

463450
/* Enter 4-byte addressing mode for >16MB flash */
464451
qspi_enter_4byte_mode();
452+
453+
return 0;
465454
}
466455

467456
/* QSPI Block Transfer Function
@@ -482,19 +471,27 @@ static int qspi_transfer_block(uint8_t read_mode, const uint8_t *cmd,
482471
uint32_t frames;
483472
uint32_t i;
484473
uint32_t timeout;
474+
uint32_t frame_cmd;
485475

486476
/* Wait for controller to be ready before starting */
487-
timeout = 100000;
477+
timeout = QSPI_TIMEOUT_TRIES;
488478
while (!(QSPI_STATUS & QSPI_STATUS_READY) && --timeout);
489479
if (timeout == 0) {
490480
wolfBoot_printf("QSPI: Timeout waiting for READY\n");
491481
return -1;
492482
}
493483

494484
/* Drain RX FIFO of any stale data from previous transfers. */
495-
while (QSPI_STATUS & QSPI_STATUS_RXAVAIL) {
485+
timeout = QSPI_TIMEOUT_TRIES;
486+
while ((QSPI_STATUS & QSPI_STATUS_RXAVAIL) && --timeout) {
496487
(void)QSPI_RX_DATA;
497488
}
489+
#ifdef DEBUG_QSPI
490+
if (timeout == 0) {
491+
/* log warning and continue trying to transfer data */
492+
wolfBoot_printf("QSPI: Timeout draining RX FIFO\n");
493+
}
494+
#endif
498495

499496
/* Configure FRAMES register:
500497
* - Total bytes: command + data (idle cycles handled by hardware)
@@ -508,37 +505,35 @@ static int qspi_transfer_block(uint8_t read_mode, const uint8_t *cmd,
508505
* data rotation in the programmed page. Keeping everything in the
509506
* command phase avoids this. The flash determines command vs data
510507
* boundaries from the opcode, not the controller's phase. */
511-
{
512-
uint32_t frame_cmd = read_mode ? cmd_len : total_bytes;
513-
frames = ((total_bytes & 0xFFFF) << QSPI_FRAMES_TOTALBYTES_OFFSET) |
514-
((frame_cmd & 0x1FF) << QSPI_FRAMES_CMDBYTES_OFFSET) |
515-
((dummy_cycles & 0xF) << QSPI_FRAMES_IDLE_OFFSET) |
516-
(1u << QSPI_FRAMES_FBYTE_OFFSET);
517-
}
508+
frame_cmd = read_mode ? cmd_len : total_bytes;
509+
frames = ((total_bytes & 0xFFFF) << QSPI_FRAMES_TOTALBYTES_OFFSET) |
510+
((frame_cmd & 0x1FF) << QSPI_FRAMES_CMDBYTES_OFFSET) |
511+
((dummy_cycles & 0xF) << QSPI_FRAMES_IDLE_OFFSET) |
512+
(1u << QSPI_FRAMES_FBYTE_OFFSET);
518513

519514
QSPI_FRAMES = frames;
520515

521516
/* Send command bytes (opcode + address).
522517
* Use TXAVAIL (bit 3) to check for FIFO space -- CoreQSPI v2 does NOT
523518
* have a TXFULL status bit (bit 5 is reserved/always 0).
524-
* A fence after each TX write ensures the store reaches the peripheral
525-
* before we read STATUS again (RISC-V RVWMO allows posted stores that
526-
* could cause stale TXAVAIL reads and FIFO overflow). */
519+
* A fence (iorw, iorw) after each TX write ensures the store reaches the
520+
* peripheral before we read STATUS again (RISC-V RVWMO allows posted
521+
* stores that could cause stale TXAVAIL reads and FIFO overflow). */
527522
for (i = 0; i < cmd_len; i++) {
528-
timeout = 100000;
523+
timeout = QSPI_TIMEOUT_TRIES;
529524
while (!(QSPI_STATUS & QSPI_STATUS_TXAVAIL) && --timeout);
530525
if (timeout == 0) {
531526
wolfBoot_printf("QSPI: TX FIFO full timeout\n");
532527
return -2;
533528
}
534529
QSPI_TX_DATA = cmd[i];
535-
__asm__ __volatile__("fence o,i" ::: "memory");
530+
QSPI_IO_FENCE();
536531
}
537532

538533
if (read_mode) {
539534
/* Read mode: poll RXAVAIL for each data byte. */
540535
for (i = 0; i < data_len; i++) {
541-
timeout = 1000000;
536+
timeout = QSPI_RX_TIMEOUT_TRIES;
542537
while (!(QSPI_STATUS & QSPI_STATUS_RXAVAIL) && --timeout);
543538
if (timeout == 0) {
544539
wolfBoot_printf("QSPI: RX timeout at byte %d, status=0x%x\n",
@@ -548,29 +543,39 @@ static int qspi_transfer_block(uint8_t read_mode, const uint8_t *cmd,
548543
data[i] = QSPI_RX_DATA;
549544
}
550545
/* Wait for receive complete */
551-
timeout = 1000000;
546+
timeout = QSPI_RX_TIMEOUT_TRIES;
552547
while (!(QSPI_STATUS & QSPI_STATUS_RXDONE) && --timeout);
548+
if (timeout == 0) {
549+
wolfBoot_printf("QSPI: RXDONE timeout\n");
550+
return -5;
551+
}
553552
} else {
554553
/* Write mode: send data bytes.
555554
* Must push bytes without delay -- any gap causes FIFO underflow
556555
* since CoreQSPI continues clocking with empty FIFO.
557-
* Fence after each write ensures the store reaches the FIFO before
558-
* we re-read STATUS (prevents FIFO overflow from posted stores). */
556+
* Fence (iorw, iorw) after each write ensures the store reaches the
557+
* FIFO before we re-read STATUS (prevents FIFO overflow from posted
558+
* stores). */
559559
if (data && data_len > 0) {
560560
for (i = 0; i < data_len; i++) {
561-
timeout = 100000;
561+
timeout = QSPI_TIMEOUT_TRIES;
562562
while (!(QSPI_STATUS & QSPI_STATUS_TXAVAIL) && --timeout);
563563
if (timeout == 0) {
564564
wolfBoot_printf("QSPI: TX data timeout\n");
565565
return -4;
566566
}
567567
QSPI_TX_DATA = data[i];
568-
__asm__ __volatile__("fence o,i" ::: "memory");
568+
QSPI_IO_FENCE();
569569
}
570570
}
571571
/* Wait for transmit complete */
572-
timeout = 100000;
572+
timeout = QSPI_TIMEOUT_TRIES;
573573
while (!(QSPI_STATUS & QSPI_STATUS_TXDONE) && --timeout);
574+
if (timeout == 0) {
575+
wolfBoot_printf("QSPI: TXDONE timeout, status=0x%x\n",
576+
QSPI_STATUS);
577+
return -5;
578+
}
574579
}
575580

576581
#ifdef DEBUG_QSPI
@@ -650,7 +655,7 @@ static int qspi_flash_read(uint32_t address, uint8_t *data, uint32_t len)
650655
remaining -= chunk_len;
651656
}
652657

653-
return len;
658+
return (int)len;
654659
}
655660

656661
/* Write to QSPI flash - single page (max 256 bytes) */
@@ -829,7 +834,11 @@ static int test_ext_flash(void)
829834

830835
/* Verify erase (should be all 0xFF) */
831836
memset(pageData, 0, sizeof(pageData));
832-
ext_flash_read(TEST_EXT_ADDRESS, pageData, sizeof(pageData));
837+
ret = ext_flash_read(TEST_EXT_ADDRESS, pageData, sizeof(pageData));
838+
if (ret < 0) {
839+
wolfBoot_printf("Erase verify read failed: Ret %d\n", ret);
840+
return ret;
841+
}
833842
wolfBoot_printf("Erase verify: ");
834843
for (i = 0; i < 16; i++) {
835844
wolfBoot_printf("%02x ", pageData[i]);

hal/mpfs250.h

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -161,16 +161,35 @@
161161

162162
/* System Service command opcodes */
163163
#define SYS_SERV_CMD_SERIAL_NUMBER 0x00u
164-
#define SYS_SERV_CMD_SPI_COPY 0x50u
164+
#define SYS_SERV_CMD_SPI_COPY 0x50u /* SCB mailbox SPI copy service */
165165

166166
/* Device serial number size in bytes */
167167
#define DEVICE_SERIAL_NUMBER_SIZE 16
168168

169+
/* Timeout loop iteration counts (override at build time via CFLAGS) */
170+
#ifndef MPFS_SCB_TIMEOUT
171+
#define MPFS_SCB_TIMEOUT 10000 /* SCB mailbox polling */
172+
#endif
173+
#ifndef QSPI_TIMEOUT_TRIES
174+
#define QSPI_TIMEOUT_TRIES 100000 /* QSPI controller/TX polling */
175+
#endif
176+
#ifndef QSPI_RX_TIMEOUT_TRIES
177+
#define QSPI_RX_TIMEOUT_TRIES 1000000 /* QSPI RX polling (longer) */
178+
#endif
179+
169180
/* System Controller register access */
170181
#define SCBCTRL_REG(off) (*((volatile uint32_t*)(SCBCTRL_BASE + (off))))
171182
#define SCBMBOX_REG(off) (*((volatile uint32_t*)(SCBMBOX_BASE + (off))))
172183
#define SCBMBOX_BYTE(off) (*((volatile uint8_t*)(SCBMBOX_BASE + (off))))
173184

185+
/* System Controller Mailbox API */
186+
#ifndef __ASSEMBLER__
187+
int mpfs_scb_service_call(uint8_t opcode, const uint8_t *mb_data,
188+
uint32_t mb_len, uint32_t timeout);
189+
int mpfs_scb_read_mailbox(uint8_t *out, uint32_t len);
190+
int mpfs_read_serial_number(uint8_t *serial);
191+
#endif /* __ASSEMBLER__ */
192+
174193
/* Crypto Engine: Athena F5200 TeraFire Crypto Processor (1x), 200 MHz */
175194
#define ATHENA_BASE (SYSREG_BASE + 0x125000)
176195

@@ -356,9 +375,13 @@
356375
#define QSPI_MODE_WRITE 0
357376
#define QSPI_MODE_READ 1
358377

378+
/* I/O fence: ensure MMIO store reaches the peripheral before the next read.
379+
* Required on RISC-V RVWMO to prevent stale TXAVAIL reads after TX writes. */
380+
#define QSPI_IO_FENCE() __asm__ __volatile__("fence iorw, iorw" ::: "memory")
381+
359382
/* Function declarations for QSPI (when EXT_FLASH enabled) */
360383
#ifndef __ASSEMBLER__
361-
void qspi_init(void);
384+
int qspi_init(void);
362385
#endif /* __ASSEMBLER__ */
363386

364387
#endif /* EXT_FLASH */

0 commit comments

Comments
 (0)