From 47f6b41cddf8497e19bc7dc46ab2e56aa8e875c9 Mon Sep 17 00:00:00 2001 From: Ofir Bitton Date: Thu, 16 Apr 2020 13:47:15 +0300 Subject: [PATCH] habanalabs: load CPU device boot loader from host Load CPU device boot loader during driver boot time in order to avoid flash write for every boot loader update. To preserve backward-compatibility, skip the device boot load if the device doesn't request it. Signed-off-by: Ofir Bitton Reviewed-by: Oded Gabbay Signed-off-by: Oded Gabbay --- drivers/misc/habanalabs/firmware_if.c | 54 +++++++++++- drivers/misc/habanalabs/goya/goya.c | 90 +++++--------------- drivers/misc/habanalabs/habanalabs.h | 7 +- drivers/misc/habanalabs/include/hl_boot_if.h | 3 + 4 files changed, 79 insertions(+), 75 deletions(-) diff --git a/drivers/misc/habanalabs/firmware_if.c b/drivers/misc/habanalabs/firmware_if.c index 99983822feeb..ba3fbf136f15 100644 --- a/drivers/misc/habanalabs/firmware_if.c +++ b/drivers/misc/habanalabs/firmware_if.c @@ -328,8 +328,9 @@ static void fw_read_errors(struct hl_device *hdev, u32 boot_err0_reg) } int hl_fw_init_cpu(struct hl_device *hdev, u32 cpu_boot_status_reg, - u32 msg_to_cpu_reg, u32 boot_err0_reg, bool skip_bmc, - u32 cpu_timeout) + u32 msg_to_cpu_reg, u32 cpu_msg_status_reg, + u32 boot_err0_reg, bool skip_bmc, + u32 cpu_timeout, u32 boot_fit_timeout) { u32 status; int rc; @@ -337,6 +338,48 @@ int hl_fw_init_cpu(struct hl_device *hdev, u32 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, + 10000, + 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, + 10000, + 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 */ rc = hl_poll_timeout( hdev, @@ -396,7 +439,8 @@ int hl_fw_init_cpu(struct hl_device *hdev, u32 cpu_boot_status_reg, break; default: dev_err(hdev->dev, - "Device boot error - Invalid status code\n"); + "Device boot error - Invalid status code %d\n", + status); break; } @@ -450,6 +494,9 @@ int hl_fw_init_cpu(struct hl_device *hdev, u32 cpu_boot_status_reg, 10000, 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, @@ -458,7 +505,6 @@ int hl_fw_init_cpu(struct hl_device *hdev, u32 cpu_boot_status_reg, dev_err(hdev->dev, "Device failed to load, %d\n", status); - WREG32(msg_to_cpu_reg, KMD_MSG_NA); rc = -EIO; goto out; } diff --git a/drivers/misc/habanalabs/goya/goya.c b/drivers/misc/habanalabs/goya/goya.c index ddc506d74988..70fe00264f4a 100644 --- a/drivers/misc/habanalabs/goya/goya.c +++ b/drivers/misc/habanalabs/goya/goya.c @@ -72,7 +72,7 @@ * */ -#define GOYA_UBOOT_FW_FILE "habanalabs/goya/goya-u-boot.bin" +#define GOYA_BOOT_FIT_FILE "habanalabs/goya/goya-boot-fit.itb" #define GOYA_LINUX_FW_FILE "habanalabs/goya/goya-fit.itb" #define GOYA_MMU_REGS_NUM 63 @@ -87,6 +87,7 @@ #define GOYA_TEST_QUEUE_WAIT_USEC 100000 /* 100ms */ #define GOYA_PLDM_MMU_TIMEOUT_USEC (MMU_CONFIG_TIMEOUT_USEC * 100) #define GOYA_PLDM_QMAN0_TIMEOUT_USEC (HL_DEVICE_TIMEOUT_USEC * 30) +#define GOYA_BOOT_FIT_REQ_TIMEOUT_USEC 1000000 /* 1s */ #define GOYA_QMAN0_FENCE_VAL 0xD169B243 @@ -2209,23 +2210,6 @@ static void goya_halt_engines(struct hl_device *hdev, bool hard_reset) } } -/* - * goya_push_uboot_to_device() - Push u-boot FW code to device. - * @hdev: Pointer to hl_device structure. - * - * Copy u-boot fw code from firmware file to SRAM BAR. - * - * Return: 0 on success, non-zero for failure. - */ -static int goya_push_uboot_to_device(struct hl_device *hdev) -{ - void __iomem *dst; - - dst = hdev->pcie_bar[SRAM_CFG_BAR_ID] + UBOOT_FW_OFFSET; - - return hl_fw_load_fw_to_device(hdev, GOYA_UBOOT_FW_FILE, dst); -} - /* * goya_load_firmware_to_device() - Load LINUX FW code to device. * @hdev: Pointer to hl_device structure. @@ -2243,47 +2227,21 @@ static int goya_load_firmware_to_device(struct hl_device *hdev) return hl_fw_load_fw_to_device(hdev, GOYA_LINUX_FW_FILE, dst); } -static int goya_pldm_init_cpu(struct hl_device *hdev) +/* + * goya_load_boot_fit_to_device() - Load boot fit to device. + * @hdev: Pointer to hl_device structure. + * + * Copy boot fit file to SRAM BAR. + * + * Return: 0 on success, non-zero for failure. + */ +static int goya_load_boot_fit_to_device(struct hl_device *hdev) { - u32 unit_rst_val; - int rc; + void __iomem *dst; - /* Must initialize SRAM scrambler before pushing u-boot to SRAM */ - goya_init_golden_registers(hdev); + dst = hdev->pcie_bar[SRAM_CFG_BAR_ID] + BOOT_FIT_SRAM_OFFSET; - /* Put ARM cores into reset */ - WREG32(mmCPU_CA53_CFG_ARM_RST_CONTROL, CPU_RESET_ASSERT); - RREG32(mmCPU_CA53_CFG_ARM_RST_CONTROL); - - /* Reset the CA53 MACRO */ - unit_rst_val = RREG32(mmPSOC_GLOBAL_CONF_UNIT_RST_N); - WREG32(mmPSOC_GLOBAL_CONF_UNIT_RST_N, CA53_RESET); - RREG32(mmPSOC_GLOBAL_CONF_UNIT_RST_N); - WREG32(mmPSOC_GLOBAL_CONF_UNIT_RST_N, unit_rst_val); - RREG32(mmPSOC_GLOBAL_CONF_UNIT_RST_N); - - rc = goya_push_uboot_to_device(hdev); - if (rc) - return rc; - - rc = goya_load_firmware_to_device(hdev); - if (rc) - return rc; - - WREG32(mmPSOC_GLOBAL_CONF_UBOOT_MAGIC, KMD_MSG_FIT_RDY); - WREG32(mmPSOC_GLOBAL_CONF_WARM_REBOOT, CPU_BOOT_STATUS_NA); - - WREG32(mmCPU_CA53_CFG_RST_ADDR_LSB_0, - lower_32_bits(SRAM_BASE_ADDR + UBOOT_FW_OFFSET)); - WREG32(mmCPU_CA53_CFG_RST_ADDR_MSB_0, - upper_32_bits(SRAM_BASE_ADDR + UBOOT_FW_OFFSET)); - - /* Release ARM core 0 from reset */ - WREG32(mmCPU_CA53_CFG_ARM_RST_CONTROL, - CPU_RESET_CORE0_DEASSERT); - RREG32(mmCPU_CA53_CFG_ARM_RST_CONTROL); - - return 0; + return hl_fw_load_fw_to_device(hdev, GOYA_BOOT_FIT_FILE, dst); } /* @@ -2325,7 +2283,7 @@ static void goya_read_device_fw_version(struct hl_device *hdev, } } -static int goya_init_cpu(struct hl_device *hdev, u32 cpu_timeout) +static int goya_init_cpu(struct hl_device *hdev) { struct goya_device *goya = hdev->asic_specific; int rc; @@ -2346,22 +2304,15 @@ static int goya_init_cpu(struct hl_device *hdev, u32 cpu_timeout) return -EIO; } - if (hdev->pldm) { - rc = goya_pldm_init_cpu(hdev); - if (rc) - return rc; - - goto out; - } - rc = hl_fw_init_cpu(hdev, mmPSOC_GLOBAL_CONF_CPU_BOOT_STATUS, - mmPSOC_GLOBAL_CONF_UBOOT_MAGIC, mmCPU_BOOT_ERR0, - false, cpu_timeout); + mmPSOC_GLOBAL_CONF_UBOOT_MAGIC, + mmCPU_CMD_STATUS_TO_HOST, mmCPU_BOOT_ERR0, + false, GOYA_CPU_TIMEOUT_USEC, + GOYA_BOOT_FIT_REQ_TIMEOUT_USEC); if (rc) return rc; -out: goya->hw_cap_initialized |= HW_CAP_CPU; return 0; @@ -2476,7 +2427,7 @@ static int goya_hw_init(struct hl_device *hdev) */ WREG32(mmHW_STATE, HL_DEVICE_HW_STATE_DIRTY); - rc = goya_init_cpu(hdev, GOYA_CPU_TIMEOUT_USEC); + rc = goya_init_cpu(hdev); if (rc) { dev_err(hdev->dev, "failed to initialize CPU\n"); return rc; @@ -5270,6 +5221,7 @@ static const struct hl_asic_funcs goya_funcs = { .get_queue_id_for_cq = goya_get_queue_id_for_cq, .read_device_fw_version = goya_read_device_fw_version, .load_firmware_to_device = goya_load_firmware_to_device, + .load_boot_fit_to_device = goya_load_boot_fit_to_device, .set_dma_mask_from_fw = goya_set_dma_mask_from_fw, .get_device_time = goya_get_device_time }; diff --git a/drivers/misc/habanalabs/habanalabs.h b/drivers/misc/habanalabs/habanalabs.h index 0d3d3c59ae2b..b1dc6a22ba0d 100644 --- a/drivers/misc/habanalabs/habanalabs.h +++ b/drivers/misc/habanalabs/habanalabs.h @@ -552,6 +552,7 @@ enum hl_pll_frequency { * @read_device_fw_version: read the device's firmware versions that are * contained in registers * @load_firmware_to_device: load the firmware to the device's memory + * @load_boot_fit_to_device: load boot fit to device's memory * @set_dma_mask_from_fw: set the DMA mask in the driver according to the * firmware configuration * @get_device_time: Get the device time. @@ -646,6 +647,7 @@ struct hl_asic_funcs { void (*read_device_fw_version)(struct hl_device *hdev, enum hl_fw_component fwc); int (*load_firmware_to_device)(struct hl_device *hdev); + int (*load_boot_fit_to_device)(struct hl_device *hdev); void (*set_dma_mask_from_fw)(struct hl_device *hdev); u64 (*get_device_time)(struct hl_device *hdev); }; @@ -1644,8 +1646,9 @@ int hl_fw_send_heartbeat(struct hl_device *hdev); int hl_fw_armcp_info_get(struct hl_device *hdev); int hl_fw_get_eeprom_data(struct hl_device *hdev, void *data, size_t max_size); int hl_fw_init_cpu(struct hl_device *hdev, u32 cpu_boot_status_reg, - u32 msg_to_cpu_reg, u32 boot_err0_reg, bool skip_bmc, - u32 cpu_timeout); + u32 msg_to_cpu_reg, u32 cpu_msg_status_reg, + u32 boot_err0_reg, bool skip_bmc, + u32 cpu_timeout, u32 boot_fit_timeout); int hl_pci_bars_map(struct hl_device *hdev, const char * const name[3], bool is_wc[3]); diff --git a/drivers/misc/habanalabs/include/hl_boot_if.h b/drivers/misc/habanalabs/include/hl_boot_if.h index 7106315fc92e..c22d134e73af 100644 --- a/drivers/misc/habanalabs/include/hl_boot_if.h +++ b/drivers/misc/habanalabs/include/hl_boot_if.h @@ -11,6 +11,8 @@ #define LKD_HARD_RESET_MAGIC 0xED7BD694 #define HL_POWER9_HOST_MAGIC 0x1DA30009 +#define BOOT_FIT_SRAM_OFFSET 0x200000 + /* * CPU error bits in BOOT_ERROR registers * @@ -77,6 +79,7 @@ enum cpu_boot_status { CPU_BOOT_STATUS_BMC_WAITING_SKIPPED, /* deprecated - will be removed */ /* Last boot loader progress status, ready to receive commands */ CPU_BOOT_STATUS_READY_TO_BOOT = 15, + CPU_BOOT_STATUS_WAITING_FOR_BOOT_FIT = 16, }; enum kmd_msg {