@@ -56,6 +56,89 @@ void hal_init(void)
5656 LIBWOLFBOOT_VERSION_STRING ,__DATE__ , __TIME__ );
5757}
5858
59+ /* ============================================================================
60+ * System Controller Mailbox Functions
61+ *
62+ * The MPFS system controller provides various system services via a mailbox
63+ * interface. Commands are sent by writing the opcode to the control register
64+ * and responses are read from the mailbox RAM.
65+ * ============================================================================ */
66+
67+ /**
68+ * mpfs_scb_mailbox_busy - Check if the system controller mailbox is busy
69+ *
70+ * Returns: non-zero if busy, 0 if ready
71+ */
72+ static int mpfs_scb_mailbox_busy (void )
73+ {
74+ return (SCBCTRL_REG (SERVICES_SR_OFFSET ) & SERVICES_SR_BUSY_MASK );
75+ }
76+
77+ /**
78+ * mpfs_read_serial_number - Read the device serial number via system services
79+ * @serial: Buffer to store the 16-byte device serial number
80+ *
81+ * This function sends a serial number request (opcode 0x00) to the system
82+ * controller and reads the 16-byte response from the mailbox RAM.
83+ *
84+ * Returns: 0 on success, negative error code on failure
85+ */
86+ static int mpfs_read_serial_number (uint8_t * serial )
87+ {
88+ uint32_t cmd , status ;
89+ int i , timeout ;
90+
91+ if (serial == NULL ) {
92+ return -1 ;
93+ }
94+
95+ /* Check if mailbox is busy */
96+ if (mpfs_scb_mailbox_busy ()) {
97+ wolfBoot_printf ("SCB mailbox busy\n" );
98+ return -2 ;
99+ }
100+
101+ /* Send serial number request command (opcode 0x00)
102+ * Command format: [31:16] = opcode, [0] = request bit */
103+ cmd = (SYS_SERV_CMD_SERIAL_NUMBER << SERVICES_CR_COMMAND_SHIFT ) |
104+ SERVICES_CR_REQ_MASK ;
105+ SCBCTRL_REG (SERVICES_CR_OFFSET ) = cmd ;
106+
107+ /* Wait for request bit to clear (command accepted) */
108+ timeout = 10000 ;
109+ while ((SCBCTRL_REG (SERVICES_CR_OFFSET ) & SERVICES_CR_REQ_MASK ) && timeout > 0 ) {
110+ timeout -- ;
111+ }
112+ if (timeout == 0 ) {
113+ wolfBoot_printf ("SCB mailbox request timeout\n" );
114+ return -3 ;
115+ }
116+
117+ /* Wait for busy bit to clear (command completed) */
118+ timeout = 10000 ;
119+ while (mpfs_scb_mailbox_busy () && timeout > 0 ) {
120+ timeout -- ;
121+ }
122+ if (timeout == 0 ) {
123+ wolfBoot_printf ("SCB mailbox busy timeout\n" );
124+ return -4 ;
125+ }
126+
127+ /* Check status (upper 16 bits of status register) */
128+ status = (SCBCTRL_REG (SERVICES_SR_OFFSET ) >> SERVICES_SR_STATUS_SHIFT ) & 0xFFFF ;
129+ if (status != 0 ) {
130+ wolfBoot_printf ("SCB mailbox error: 0x%x\n" , status );
131+ return -5 ;
132+ }
133+
134+ /* Read serial number from mailbox RAM (16 bytes) */
135+ for (i = 0 ; i < DEVICE_SERIAL_NUMBER_SIZE ; i ++ ) {
136+ serial [i ] = SCBMBOX_BYTE (i );
137+ }
138+
139+ return 0 ;
140+ }
141+
59142/* Linux kernel command line arguments */
60143#ifndef LINUX_BOOTARGS
61144#ifndef LINUX_BOOTARGS_ROOT
@@ -66,10 +149,17 @@ void hal_init(void)
66149 "earlycon root="LINUX_BOOTARGS_ROOT" rootwait uio_pdrv_genirq.of_id=generic-uio"
67150#endif
68151
152+ /* Microchip OUI (Organizationally Unique Identifier) for MAC address */
153+ #define MICROCHIP_OUI_0 0x00
154+ #define MICROCHIP_OUI_1 0x04
155+ #define MICROCHIP_OUI_2 0xA3
156+
69157int hal_dts_fixup (void * dts_addr )
70158{
71159 int off , ret ;
72160 struct fdt_header * fdt = (struct fdt_header * )dts_addr ;
161+ uint8_t device_serial_number [DEVICE_SERIAL_NUMBER_SIZE ];
162+ uint8_t mac_addr [6 ];
73163
74164 /* Verify FDT header */
75165 ret = fdt_check_header (dts_addr );
@@ -96,8 +186,68 @@ int hal_dts_fixup(void* dts_addr)
96186 fdt_fixup_str (fdt , off , "chosen" , "bootargs" , LINUX_BOOTARGS );
97187 }
98188
99- /* TODO: Consider additional FDT fixups:
100- * ethernet0: local-mac-address {0x00, 0x04, 0xA3, SERIAL2, SERIAL1, SERIAL0} */
189+ /* Read device serial number from system controller */
190+ ret = mpfs_read_serial_number (device_serial_number );
191+ if (ret != 0 ) {
192+ wolfBoot_printf ("FDT: Failed to read serial number (%d)\n" , ret );
193+ /* Continue without setting MAC addresses */
194+ return 0 ;
195+ }
196+
197+ wolfBoot_printf ("FDT: Device serial: %02x%02x%02x%02x-%02x%02x%02x%02x-"
198+ "%02x%02x%02x%02x-%02x%02x%02x%02x\n" ,
199+ device_serial_number [15 ], device_serial_number [14 ],
200+ device_serial_number [13 ], device_serial_number [12 ],
201+ device_serial_number [11 ], device_serial_number [10 ],
202+ device_serial_number [9 ], device_serial_number [8 ],
203+ device_serial_number [7 ], device_serial_number [6 ],
204+ device_serial_number [5 ], device_serial_number [4 ],
205+ device_serial_number [3 ], device_serial_number [2 ],
206+ device_serial_number [1 ], device_serial_number [0 ]);
207+
208+ /* Build MAC address: Microchip OUI + lower 3 bytes of serial number
209+ * Format: {0x00, 0x04, 0xA3, serial[2], serial[1], serial[0]} */
210+ mac_addr [0 ] = MICROCHIP_OUI_0 ;
211+ mac_addr [1 ] = MICROCHIP_OUI_1 ;
212+ mac_addr [2 ] = MICROCHIP_OUI_2 ;
213+ mac_addr [3 ] = device_serial_number [2 ];
214+ mac_addr [4 ] = device_serial_number [1 ];
215+ mac_addr [5 ] = device_serial_number [0 ];
216+
217+ wolfBoot_printf ("FDT: MAC0 = %02x:%02x:%02x:%02x:%02x:%02x\n" ,
218+ mac_addr [0 ], mac_addr [1 ], mac_addr [2 ],
219+ mac_addr [3 ], mac_addr [4 ], mac_addr [5 ]);
220+
221+ /* Set local-mac-address for ethernet@20110000 (mac0) */
222+ off = fdt_find_node_offset (fdt , -1 , "ethernet@20110000" );
223+ if (off >= 0 ) {
224+ ret = fdt_setprop (fdt , off , "local-mac-address" , mac_addr , 6 );
225+ if (ret != 0 ) {
226+ wolfBoot_printf ("FDT: Failed to set mac0 address (%d)\n" , ret );
227+ }
228+ }
229+ else {
230+ wolfBoot_printf ("FDT: ethernet@20110000 not found\n" );
231+ }
232+
233+ /* Set local-mac-address for ethernet@20112000 (mac1)
234+ * Use MAC address + 1 for the second interface */
235+ mac_addr [5 ] = device_serial_number [0 ] + 1 ;
236+
237+ wolfBoot_printf ("FDT: MAC1 = %02x:%02x:%02x:%02x:%02x:%02x\n" ,
238+ mac_addr [0 ], mac_addr [1 ], mac_addr [2 ],
239+ mac_addr [3 ], mac_addr [4 ], mac_addr [5 ]);
240+
241+ off = fdt_find_node_offset (fdt , -1 , "ethernet@20112000" );
242+ if (off >= 0 ) {
243+ ret = fdt_setprop (fdt , off , "local-mac-address" , mac_addr , 6 );
244+ if (ret != 0 ) {
245+ wolfBoot_printf ("FDT: Failed to set mac1 address (%d)\n" , ret );
246+ }
247+ }
248+ else {
249+ wolfBoot_printf ("FDT: ethernet@20112000 not found\n" );
250+ }
101251
102252 return 0 ;
103253}
0 commit comments