Skip to content

Commit 633e7f8

Browse files
committed
Cleanups
1 parent 7fa33fd commit 633e7f8

File tree

4 files changed

+186
-113
lines changed

4 files changed

+186
-113
lines changed

hal/mpfs250.c

Lines changed: 147 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -74,76 +74,142 @@ void hal_init(void)
7474
* and responses are read from the mailbox RAM.
7575
* ============================================================================ */
7676

77-
/**
78-
* mpfs_scb_mailbox_busy - Check if the system controller mailbox is busy
79-
*
80-
* Returns: non-zero if busy, 0 if ready
81-
*/
82-
static int mpfs_scb_mailbox_busy(void)
77+
int mpfs_scb_is_busy(void)
8378
{
8479
return (SCBCTRL_REG(SERVICES_SR_OFFSET) & SERVICES_SR_BUSY_MASK);
8580
}
8681

87-
/**
88-
* mpfs_read_serial_number - Read the device serial number via system services
89-
* @serial: Buffer to store the 16-byte device serial number
90-
*
91-
* This function sends a serial number request (opcode 0x00) to the system
92-
* controller and reads the 16-byte response from the mailbox RAM.
93-
*
94-
* Returns: 0 on success, negative error code on failure
95-
*/
96-
static int mpfs_read_serial_number(uint8_t *serial)
82+
int mpfs_scb_wait_ready(uint32_t timeout)
9783
{
98-
uint32_t cmd, status;
99-
int i, timeout;
84+
while (mpfs_scb_is_busy() && timeout > 0) {
85+
timeout--;
86+
}
10087

101-
if (serial == NULL) {
88+
if (timeout == 0) {
10289
return -1;
10390
}
91+
return 0;
92+
}
10493

105-
/* Check if mailbox is busy */
106-
if (mpfs_scb_mailbox_busy()) {
107-
wolfBoot_printf("SCB mailbox busy\n");
108-
return -2;
94+
int mpfs_scb_read_mailbox(uint8_t *out, uint32_t len)
95+
{
96+
uint32_t i;
97+
98+
if (out == NULL) {
99+
return -1;
109100
}
110101

111-
/* Send serial number request command (opcode 0x00)
112-
* Command format: [31:16] = opcode, [0] = request bit */
113-
cmd = (SYS_SERV_CMD_SERIAL_NUMBER << SERVICES_CR_COMMAND_SHIFT) |
114-
SERVICES_CR_REQ_MASK;
115-
SCBCTRL_REG(SERVICES_CR_OFFSET) = cmd;
102+
for (i = 0; i < len; i++) {
103+
out[i] = SCBMBOX_BYTE(i);
104+
}
116105

117-
/* Wait for request bit to clear (command accepted) */
118-
timeout = 10000;
119-
while ((SCBCTRL_REG(SERVICES_CR_OFFSET) & SERVICES_CR_REQ_MASK) && timeout > 0) {
120-
timeout--;
106+
return 0;
107+
}
108+
109+
static void mpfs_scb_write_mailbox(const uint8_t *data, uint32_t len)
110+
{
111+
uint32_t i = 0;
112+
113+
if (data == NULL || len == 0) {
114+
return;
121115
}
122-
if (timeout == 0) {
123-
wolfBoot_printf("SCB mailbox request timeout\n");
124-
return -3;
116+
117+
/* Write full words (little-endian) */
118+
while (i + 4 <= len) {
119+
uint32_t word = ((uint32_t)data[i]) |
120+
((uint32_t)data[i + 1] << 8) |
121+
((uint32_t)data[i + 2] << 16) |
122+
((uint32_t)data[i + 3] << 24);
123+
SCBMBOX_REG(i) = word;
124+
i += 4;
125125
}
126126

127-
/* Wait for busy bit to clear (command completed) */
128-
timeout = 10000;
129-
while (mpfs_scb_mailbox_busy() && timeout > 0) {
127+
/* Write remaining bytes */
128+
while (i < len) {
129+
SCBMBOX_BYTE(i) = data[i];
130+
i++;
131+
}
132+
}
133+
134+
static int mpfs_scb_wait_req_clear(uint32_t timeout)
135+
{
136+
while ((SCBCTRL_REG(SERVICES_CR_OFFSET) & SERVICES_CR_REQ_MASK) &&
137+
timeout > 0) {
130138
timeout--;
131139
}
140+
132141
if (timeout == 0) {
133-
wolfBoot_printf("SCB mailbox busy timeout\n");
134-
return -4;
142+
return -1;
143+
}
144+
return 0;
145+
}
146+
147+
int mpfs_scb_service_call_timeout(uint8_t opcode, const uint8_t *mb_data,
148+
uint32_t mb_len, uint32_t req_timeout,
149+
uint32_t busy_timeout)
150+
{
151+
uint32_t cmd;
152+
uint32_t status;
153+
154+
if (mpfs_scb_is_busy()) {
155+
return -1;
156+
}
157+
158+
if (mb_data && mb_len > 0) {
159+
mpfs_scb_write_mailbox(mb_data, mb_len);
160+
}
161+
162+
cmd = ((opcode & 0x7F) << SERVICES_CR_COMMAND_SHIFT) |
163+
SERVICES_CR_REQ_MASK;
164+
SCBCTRL_REG(SERVICES_CR_OFFSET) = cmd;
165+
166+
if (mpfs_scb_wait_req_clear(req_timeout) < 0) {
167+
return -2;
168+
}
169+
170+
if (mpfs_scb_wait_ready(busy_timeout) < 0) {
171+
return -3;
135172
}
136173

137-
/* Check status (upper 16 bits of status register) */
138174
status = (SCBCTRL_REG(SERVICES_SR_OFFSET) >> SERVICES_SR_STATUS_SHIFT) & 0xFFFF;
139175
if (status != 0) {
140-
wolfBoot_printf("SCB mailbox error: 0x%x\n", status);
141-
return -5;
176+
return -4;
142177
}
143178

144-
/* Read serial number from mailbox RAM (16 bytes) */
145-
for (i = 0; i < DEVICE_SERIAL_NUMBER_SIZE; i++) {
146-
serial[i] = SCBMBOX_BYTE(i);
179+
return 0;
180+
}
181+
182+
int mpfs_scb_service_call(uint8_t opcode, const uint8_t *mb_data, uint32_t mb_len)
183+
{
184+
return mpfs_scb_service_call_timeout(opcode, mb_data, mb_len, 10000, 10000);
185+
}
186+
/**
187+
* mpfs_read_serial_number - Read the device serial number via system services
188+
* @serial: Buffer to store the 16-byte device serial number
189+
*
190+
* This function sends a serial number request (opcode 0x00) to the system
191+
* controller and reads the 16-byte response from the mailbox RAM.
192+
*
193+
* Returns: 0 on success, negative error code on failure
194+
*/
195+
static int mpfs_read_serial_number(uint8_t *serial)
196+
{
197+
int ret;
198+
199+
if (serial == NULL) {
200+
return -1;
201+
}
202+
203+
ret = mpfs_scb_service_call(SYS_SERV_CMD_SERIAL_NUMBER, NULL, 0);
204+
if (ret != 0) {
205+
wolfBoot_printf("SCB mailbox error: %d\n", ret);
206+
return ret;
207+
}
208+
209+
/* Read serial number from mailbox RAM (16 bytes). */
210+
ret = mpfs_scb_read_mailbox(serial, DEVICE_SERIAL_NUMBER_SIZE);
211+
if (ret != 0) {
212+
return ret;
147213
}
148214

149215
return 0;
@@ -534,16 +600,33 @@ int qspi_enter_4byte_mode(void)
534600
/* Read from QSPI flash (4-byte addressing) */
535601
static int qspi_flash_read(uint32_t address, uint8_t *data, uint32_t len)
536602
{
603+
const uint32_t max_chunk = 0xFFFF - 5; /* total_bytes is 16-bit, cmd is 5 */
537604
uint8_t cmd[5];
605+
uint32_t remaining = len;
606+
uint32_t chunk_len;
607+
int ret;
538608

539-
/* Build 4-byte read command */
540-
cmd[0] = QSPI_CMD_4BYTE_READ_OPCODE;
541-
cmd[1] = (address >> 24) & 0xFF;
542-
cmd[2] = (address >> 16) & 0xFF;
543-
cmd[3] = (address >> 8) & 0xFF;
544-
cmd[4] = address & 0xFF;
609+
while (remaining > 0) {
610+
chunk_len = (remaining > max_chunk) ? max_chunk : remaining;
611+
612+
/* Build 4-byte read command */
613+
cmd[0] = QSPI_CMD_4BYTE_READ_OPCODE;
614+
cmd[1] = (address >> 24) & 0xFF;
615+
cmd[2] = (address >> 16) & 0xFF;
616+
cmd[3] = (address >> 8) & 0xFF;
617+
cmd[4] = address & 0xFF;
545618

546-
return qspi_transfer_block(QSPI_MODE_READ, cmd, 5, data, len, 0);
619+
ret = qspi_transfer_block(QSPI_MODE_READ, cmd, 5, data, chunk_len, 0);
620+
if (ret != 0) {
621+
return ret;
622+
}
623+
624+
address += chunk_len;
625+
data += chunk_len;
626+
remaining -= chunk_len;
627+
}
628+
629+
return len;
547630
}
548631

549632
/* Write to QSPI flash - single page (max 256 bytes) */
@@ -629,17 +712,8 @@ static int qspi_flash_sector_erase(uint32_t address)
629712
*/
630713
static int sc_spi_copy(uint64_t dest_addr, uint32_t flash_addr, uint32_t len)
631714
{
632-
uint32_t cmd;
633-
uint32_t status;
634-
int timeout;
635715
uint8_t mb_data[20]; /* 17 bytes needed, aligned to 20 */
636716

637-
/* Check if System Controller is busy */
638-
if (SCBCTRL_REG(SERVICES_SR_OFFSET) & SERVICES_SR_BUSY_MASK) {
639-
wolfBoot_printf("SC: Busy\n");
640-
return -1;
641-
}
642-
643717
/* Prepare mailbox data for SPI_COPY service (17 bytes):
644718
* Bytes 0-7: destination address (64-bit)
645719
* Bytes 8-11: source SPI flash address (32-bit)
@@ -663,47 +737,8 @@ static int sc_spi_copy(uint64_t dest_addr, uint32_t flash_addr, uint32_t len)
663737
mb_data[14] = (len >> 16) & 0xFF;
664738
mb_data[15] = (len >> 24) & 0xFF;
665739
mb_data[16] = SPI_COPY_OPT_13MHZ; /* Use 13.33MHz (safest) */
666-
667-
/* Write mailbox data (word-aligned writes) */
668-
SCBMBOX_REG(0) = *(uint32_t*)&mb_data[0];
669-
SCBMBOX_REG(4) = *(uint32_t*)&mb_data[4];
670-
SCBMBOX_REG(8) = *(uint32_t*)&mb_data[8];
671-
SCBMBOX_REG(12) = *(uint32_t*)&mb_data[12];
672-
SCBMBOX_REG(16) = mb_data[16]; /* Last byte (options) */
673-
674-
/* Build and send service command:
675-
* Bits 0-6: opcode (0x50 for SPI_COPY)
676-
* Bits 7-15: mailbox offset (0)
677-
* Bit 0 of CR: REQ (request bit)
678-
*/
679-
cmd = ((SYS_SERV_CMD_SPI_COPY & 0x7F) << SERVICES_CR_COMMAND_SHIFT) |
680-
SERVICES_CR_REQ_MASK;
681-
SCBCTRL_REG(SERVICES_CR_OFFSET) = cmd;
682-
683-
/* Wait for REQ bit to clear (command accepted) */
684-
timeout = 100000;
685-
while ((SCBCTRL_REG(SERVICES_CR_OFFSET) & SERVICES_CR_REQ_MASK) && --timeout);
686-
if (timeout == 0) {
687-
wolfBoot_printf("SC: REQ timeout\n");
688-
return -2;
689-
}
690-
691-
/* Wait for BUSY bit to clear (command completed) */
692-
timeout = 10000000; /* Long timeout for large transfers */
693-
while ((SCBCTRL_REG(SERVICES_SR_OFFSET) & SERVICES_SR_BUSY_MASK) && --timeout);
694-
if (timeout == 0) {
695-
wolfBoot_printf("SC: BUSY timeout\n");
696-
return -3;
697-
}
698-
699-
/* Check status (upper 16 bits of status register) */
700-
status = (SCBCTRL_REG(SERVICES_SR_OFFSET) >> SERVICES_SR_STATUS_SHIFT) & 0xFFFF;
701-
if (status != 0) {
702-
wolfBoot_printf("SC: Error 0x%x\n", status);
703-
return -4;
704-
}
705-
706-
return 0;
740+
return mpfs_scb_service_call_timeout(SYS_SERV_CMD_SPI_COPY, mb_data, 17,
741+
100000, 10000000);
707742
}
708743
#endif /* MPFS_SC_SPI */
709744

@@ -732,18 +767,20 @@ int ext_flash_write(uintptr_t address, const uint8_t *data, int len)
732767
uint32_t page_offset;
733768
uint32_t chunk_len;
734769
int ret;
770+
int remaining = len;
771+
int total = len;
735772

736773
#ifdef DEBUG_QSPI
737774
wolfBoot_printf("QSPI: Write 0x%x, len %d\n", (uint32_t)address, len);
738775
#endif
739776

740777
/* Write data page by page */
741-
while (len > 0) {
778+
while (remaining > 0) {
742779
/* Calculate bytes to write in this page */
743780
page_offset = address & (FLASH_PAGE_SIZE - 1);
744781
chunk_len = FLASH_PAGE_SIZE - page_offset;
745-
if (chunk_len > (uint32_t)len) {
746-
chunk_len = len;
782+
if (chunk_len > (uint32_t)remaining) {
783+
chunk_len = remaining;
747784
}
748785

749786
/* Write page */
@@ -755,10 +792,10 @@ int ext_flash_write(uintptr_t address, const uint8_t *data, int len)
755792
/* Update pointers */
756793
address += chunk_len;
757794
data += chunk_len;
758-
len -= chunk_len;
795+
remaining -= chunk_len;
759796
}
760797

761-
return 0;
798+
return total;
762799
#endif /* MPFS_SC_SPI */
763800
}
764801

@@ -796,6 +833,7 @@ int ext_flash_erase(uintptr_t address, int len)
796833
uint32_t sector_addr;
797834
uint32_t end_addr;
798835
int ret;
836+
int total = len;
799837

800838
#ifdef DEBUG_QSPI
801839
wolfBoot_printf("QSPI: Erase 0x%x, len %d\n", (uint32_t)address, len);
@@ -820,7 +858,7 @@ int ext_flash_erase(uintptr_t address, int len)
820858
sector_addr += FLASH_SECTOR_SIZE;
821859
}
822860

823-
return 0;
861+
return total;
824862
#endif /* MPFS_SC_SPI */
825863
}
826864

hal/mpfs250.h

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,27 @@
176176
#define SCBMBOX_REG(off) (*((volatile uint32_t*)(SCBMBOX_BASE + (off))))
177177
#define SCBMBOX_BYTE(off) (*((volatile uint8_t*)(SCBMBOX_BASE + (off))))
178178

179+
/* ============================================================================
180+
* System Controller Mailbox API (public)
181+
* ============================================================================ */
182+
#ifndef __ASSEMBLER__
183+
/* Returns non-zero if mailbox is busy */
184+
int mpfs_scb_is_busy(void);
185+
186+
/* Wait until mailbox is ready (busy cleared). Returns 0 on success. */
187+
int mpfs_scb_wait_ready(uint32_t timeout);
188+
189+
/* Read mailbox bytes into buffer. Returns 0 on success. */
190+
int mpfs_scb_read_mailbox(uint8_t *out, uint32_t len);
191+
192+
/* Execute a system service command with optional mailbox payload. */
193+
int mpfs_scb_service_call(uint8_t opcode, const uint8_t *mb_data, uint32_t mb_len);
194+
/* Execute a system service command with explicit timeouts. */
195+
int mpfs_scb_service_call_timeout(uint8_t opcode, const uint8_t *mb_data,
196+
uint32_t mb_len, uint32_t req_timeout,
197+
uint32_t busy_timeout);
198+
#endif /* __ASSEMBLER__ */
199+
179200

180201
/* Crypto Engine: Athena F5200 TeraFire Crypto Processor (1x), 200 MHz */
181202
#define ATHENA_BASE (SYSREG_BASE + 0x125000)
@@ -376,4 +397,3 @@ int qspi_enter_4byte_mode(void);
376397

377398

378399
#endif /* MPFS250_DEF_INCLUDED */
379-

0 commit comments

Comments
 (0)