@@ -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) */
535601static 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 */
630713static 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
0 commit comments