/* Function of sending firmware to M7 in fragments */
int imx_rproc_flash_firmware(struct udevice *dev, ulong src_image_addr, ulong image_size)
{
struct imx_rproc *priv = dev_get_priv(dev);
const struct imx_rproc_dcfg *dcfg = priv->dcfg;
volatile struct rproc_update_ipc_a55 *ipc = (struct rproc_update_ipc_a55 *)IMX95_M7_TCM_IPC_A55_BASE;
uint8_t *src_ptr = (uint8_t *)src_image_addr;
uint32_t bytes_left = image_size;
uint32_t chunk_len = 204800;
uint32_t current_target_ddr = 0x80000000U;
printf("RPROC: Starting flash of %lu bytes to M7 via TCM...\n", image_size);
/* 1. We calculate the full CRC32 of the reference image using the built-in U-Boot function */
uint32_t total_expected_crc = crc32(0, src_ptr, image_size);
printf("RPROC: Calculated image CRC32: 0x%08X\n", total_expected_crc);
/* 2. Cycle-by-cycle sending of fragments */
while (bytes_left > 0)
{
if (bytes_left < chunk_len) {
chunk_len = bytes_left;
}
while (ipc->status == STAT_BUSY);
printf("RPROC: Sending chunk of %d bytes...\n", chunk_len);
/* Copy the data packet to the M7 firmware TCM buffer */
memcpy((void *)ipc->buffer, src_ptr, chunk_len);
ipc->chunk_size = chunk_len;
ipc->target_ddr = current_target_ddr;
ipc->command = CMD_DATA_READY;
/* Pinging the M7 via the hardware Mailbox (MU) (optional if the M7 is sleeping) */
// imx_mu_send_signal();
/* Waiting for confirmation (ACK) from M7 */
while (ipc->status == STAT_BUSY || ipc->command == CMD_DATA_READY);
if (ipc->status != STAT_ACK) {
printf("RPROC: Error! M7 rejected chunk at DDR 0x%08X\n", current_target_ddr);
return -1;
}
src_ptr += chunk_len;
current_target_ddr += chunk_len;
bytes_left -= chunk_len;
}
/* 3. Sending the final CRC check command */
printf("RPROC: All chunks sent. Verifying total CRC...\n");
ipc->expected_crc = total_expected_crc;
ipc->command = CMD_VERIFY_CRC;
while (ipc->status == STAT_BUSY || ipc->command == CMD_VERIFY_CRC);
if (ipc->status == STAT_ACK) {
printf("RPROC: SUCCESS! CRC matches. M7 booted into DDR 0x80000000!\n");
return 0;
} else {
printf("RPROC: CRC VERIFICATION FAILED! Firmware corrupted.\n");
return -1;
}
}