in habanalabs/common/firmware_if.c [2473:2664]
static int hl_fw_static_init_cpu(struct hl_device *hdev,
struct fw_load_mgr *fw_loader)
{
u32 cpu_msg_status_reg, cpu_timeout, msg_to_cpu_reg, status;
u32 cpu_boot_dev_status0_reg, cpu_boot_dev_status1_reg;
struct static_fw_load_mgr *static_loader;
u32 cpu_boot_status_reg;
int rc;
if (!(hdev->fw_components & FW_TYPE_BOOT_CPU))
return 0;
/* init common loader parameters */
cpu_timeout = fw_loader->cpu_timeout;
/* init static loader parameters */
static_loader = &fw_loader->static_loader;
cpu_msg_status_reg = static_loader->cpu_cmd_status_to_host_reg;
msg_to_cpu_reg = static_loader->kmd_msg_to_cpu_reg;
cpu_boot_dev_status0_reg = static_loader->cpu_boot_dev_status0_reg;
cpu_boot_dev_status1_reg = static_loader->cpu_boot_dev_status1_reg;
cpu_boot_status_reg = static_loader->cpu_boot_status_reg;
dev_info(hdev->dev, "Going to wait for device boot (up to %lds)\n",
cpu_timeout / USEC_PER_SEC);
/* Wait for boot FIT request */
rc = hl_poll_timeout(
hdev,
cpu_boot_status_reg,
status,
status == CPU_BOOT_STATUS_WAITING_FOR_BOOT_FIT,
hdev->fw_poll_interval_usec,
fw_loader->boot_fit_timeout);
if (rc) {
dev_dbg(hdev->dev,
"No boot fit request received, resuming boot\n");
} else {
rc = hdev->asic_funcs->load_boot_fit_to_device(hdev);
if (rc)
goto out;
/* Clear device CPU message status */
WREG32(cpu_msg_status_reg, CPU_MSG_CLR);
/* Signal device CPU that boot loader is ready */
WREG32(msg_to_cpu_reg, KMD_MSG_FIT_RDY);
/* Poll for CPU device ack */
rc = hl_poll_timeout(
hdev,
cpu_msg_status_reg,
status,
status == CPU_MSG_OK,
hdev->fw_poll_interval_usec,
fw_loader->boot_fit_timeout);
if (rc) {
dev_err(hdev->dev,
"Timeout waiting for boot fit load ack\n");
goto out;
}
/* Clear message */
WREG32(msg_to_cpu_reg, KMD_MSG_NA);
}
/*
* Make sure CPU boot-loader is running
* Note that the CPU_BOOT_STATUS_SRAM_AVAIL is generally set by Linux
* yet there is a debug scenario in which we loading uboot (without Linux)
* which at later stage is relocated to DRAM. In this case we expect
* uboot to set the CPU_BOOT_STATUS_SRAM_AVAIL and so we add it to the
* poll flags
*/
rc = hl_poll_timeout(
hdev,
cpu_boot_status_reg,
status,
(status == CPU_BOOT_STATUS_DRAM_RDY) ||
(status == CPU_BOOT_STATUS_NIC_FW_RDY) ||
(status == CPU_BOOT_STATUS_READY_TO_BOOT) ||
(status == CPU_BOOT_STATUS_SRAM_AVAIL),
hdev->fw_poll_interval_usec,
cpu_timeout);
dev_dbg(hdev->dev, "uboot status = %d\n", status);
/* Read U-Boot version now in case we will later fail */
hl_fw_static_read_device_fw_version(hdev, FW_COMP_BOOT_FIT);
/* update state according to boot stage */
hl_fw_boot_fit_update_state(hdev, cpu_boot_dev_status0_reg,
cpu_boot_dev_status1_reg);
if (rc) {
detect_cpu_boot_status(hdev, status);
rc = -EIO;
goto out;
}
/* Enable DRAM scrambling before Linux boot and after successful
* UBoot
*/
hdev->asic_funcs->init_cpu_scrambler_dram(hdev);
if (!(hdev->fw_components & FW_TYPE_LINUX)) {
dev_info(hdev->dev, "Skip loading Linux F/W\n");
rc = 0;
goto out;
}
if (status == CPU_BOOT_STATUS_SRAM_AVAIL) {
rc = 0;
goto out;
}
dev_info(hdev->dev,
"Loading firmware to device, may take some time...\n");
rc = hdev->asic_funcs->load_firmware_to_device(hdev);
if (rc)
goto out;
if (fw_loader->skip_bmc) {
WREG32(msg_to_cpu_reg, KMD_MSG_SKIP_BMC);
rc = hl_poll_timeout(
hdev,
cpu_boot_status_reg,
status,
(status == CPU_BOOT_STATUS_BMC_WAITING_SKIPPED),
hdev->fw_poll_interval_usec,
cpu_timeout);
if (rc) {
dev_err(hdev->dev,
"Failed to get ACK on skipping BMC, %d\n",
status);
WREG32(msg_to_cpu_reg, KMD_MSG_NA);
rc = -EIO;
goto out;
}
}
WREG32(msg_to_cpu_reg, KMD_MSG_FIT_RDY);
rc = hl_poll_timeout(
hdev,
cpu_boot_status_reg,
status,
(status == CPU_BOOT_STATUS_SRAM_AVAIL),
hdev->fw_poll_interval_usec,
cpu_timeout);
/* Clear message */
WREG32(msg_to_cpu_reg, KMD_MSG_NA);
if (rc) {
if (status == CPU_BOOT_STATUS_FIT_CORRUPTED)
dev_err(hdev->dev,
"Device reports FIT image is corrupted\n");
else
dev_err(hdev->dev,
"Failed to load firmware to device, %d\n",
status);
rc = -EIO;
goto out;
}
rc = fw_read_errors(hdev, fw_loader->static_loader.boot_err0_reg,
fw_loader->static_loader.boot_err1_reg,
cpu_boot_dev_status0_reg,
cpu_boot_dev_status1_reg);
if (rc)
return rc;
hl_fw_linux_update_state(hdev, cpu_boot_dev_status0_reg,
cpu_boot_dev_status1_reg);
return 0;
out:
fw_read_errors(hdev, fw_loader->static_loader.boot_err0_reg,
fw_loader->static_loader.boot_err1_reg,
cpu_boot_dev_status0_reg,
cpu_boot_dev_status1_reg);
return rc;
}