aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/drivers/misc/habanalabs/goya/goya.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc/habanalabs/goya/goya.c')
-rw-r--r--drivers/misc/habanalabs/goya/goya.c345
1 files changed, 141 insertions, 204 deletions
diff --git a/drivers/misc/habanalabs/goya/goya.c b/drivers/misc/habanalabs/goya/goya.c
index 68f065607544..0d2952bb58df 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
@@ -531,7 +532,7 @@ static int goya_early_init(struct hl_device *hdev)
prop->dram_pci_bar_size = pci_resource_len(pdev, DDR_BAR_ID);
- rc = hl_pci_init(hdev, 48);
+ rc = hl_pci_init(hdev);
if (rc)
return rc;
@@ -750,6 +751,8 @@ static int goya_sw_init(struct hl_device *hdev)
}
spin_lock_init(&goya->hw_queues_lock);
+ hdev->supports_coresight = true;
+ hdev->supports_soft_reset = true;
return 0;
@@ -800,6 +803,7 @@ static void goya_init_dma_qman(struct hl_device *hdev, int dma_id,
u32 so_base_lo, so_base_hi;
u32 gic_base_lo, gic_base_hi;
u32 reg_off = dma_id * (mmDMA_QM_1_PQ_PI - mmDMA_QM_0_PQ_PI);
+ u32 dma_err_cfg = QMAN_DMA_ERR_MSG_EN;
mtr_base_lo = lower_32_bits(CFG_BASE + mmSYNC_MNGR_MON_PAY_ADDRL_0);
mtr_base_hi = upper_32_bits(CFG_BASE + mmSYNC_MNGR_MON_PAY_ADDRL_0);
@@ -836,7 +840,10 @@ static void goya_init_dma_qman(struct hl_device *hdev, int dma_id,
else
WREG32(mmDMA_QM_0_GLBL_PROT + reg_off, QMAN_DMA_FULLY_TRUSTED);
- WREG32(mmDMA_QM_0_GLBL_ERR_CFG + reg_off, QMAN_DMA_ERR_MSG_EN);
+ if (hdev->stop_on_err)
+ dma_err_cfg |= 1 << DMA_QM_0_GLBL_ERR_CFG_DMA_STOP_ON_ERR_SHIFT;
+
+ WREG32(mmDMA_QM_0_GLBL_ERR_CFG + reg_off, dma_err_cfg);
WREG32(mmDMA_QM_0_GLBL_CFG0 + reg_off, QMAN_DMA_ENABLE);
}
@@ -886,6 +893,7 @@ void goya_init_dma_qmans(struct hl_device *hdev)
q = &hdev->kernel_queues[0];
for (i = 0 ; i < NUMBER_OF_EXT_HW_QUEUES ; i++, q++) {
+ q->cq_id = q->msi_vec = i;
goya_init_dma_qman(hdev, i, q->bus_address);
goya_init_dma_ch(hdev, i);
}
@@ -2205,80 +2213,37 @@ static void goya_halt_engines(struct hl_device *hdev, bool hard_reset)
}
/*
- * goya_push_uboot_to_device() - Push u-boot FW code to device.
+ * goya_load_firmware_to_device() - Load LINUX FW code to device.
* @hdev: Pointer to hl_device structure.
*
- * Copy u-boot fw code from firmware file to SRAM BAR.
+ * Copy LINUX fw code from firmware file to HBM BAR.
*
* Return: 0 on success, non-zero for failure.
*/
-static int goya_push_uboot_to_device(struct hl_device *hdev)
+static int goya_load_firmware_to_device(struct hl_device *hdev)
{
void __iomem *dst;
- dst = hdev->pcie_bar[SRAM_CFG_BAR_ID] + UBOOT_FW_OFFSET;
+ dst = hdev->pcie_bar[DDR_BAR_ID] + LINUX_FW_OFFSET;
- return hl_fw_push_fw_to_device(hdev, GOYA_UBOOT_FW_FILE, dst);
+ return hl_fw_load_fw_to_device(hdev, GOYA_LINUX_FW_FILE, dst);
}
/*
- * goya_push_linux_to_device() - Push LINUX FW code to device.
+ * goya_load_boot_fit_to_device() - Load boot fit to device.
* @hdev: Pointer to hl_device structure.
*
- * Copy LINUX fw code from firmware file to HBM BAR.
+ * Copy boot fit file to SRAM BAR.
*
* Return: 0 on success, non-zero for failure.
*/
-static int goya_push_linux_to_device(struct hl_device *hdev)
+static int goya_load_boot_fit_to_device(struct hl_device *hdev)
{
void __iomem *dst;
- dst = hdev->pcie_bar[DDR_BAR_ID] + LINUX_FW_OFFSET;
+ dst = hdev->pcie_bar[SRAM_CFG_BAR_ID] + BOOT_FIT_SRAM_OFFSET;
- return hl_fw_push_fw_to_device(hdev, GOYA_LINUX_FW_FILE, dst);
-}
-
-static int goya_pldm_init_cpu(struct hl_device *hdev)
-{
- u32 unit_rst_val;
- int rc;
-
- /* Must initialize SRAM scrambler before pushing u-boot to SRAM */
- goya_init_golden_registers(hdev);
-
- /* 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_push_linux_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);
}
/*
@@ -2286,7 +2251,7 @@ static int goya_pldm_init_cpu(struct hl_device *hdev)
* The version string should be located by that offset.
*/
static void goya_read_device_fw_version(struct hl_device *hdev,
- enum goya_fw_component fwc)
+ enum hl_fw_component fwc)
{
const char *name;
u32 ver_off;
@@ -2320,10 +2285,9 @@ 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;
- u32 status;
int rc;
if (!hdev->cpu_enable)
@@ -2342,115 +2306,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;
- }
-
- /* Make sure CPU boot-loader is running */
- rc = hl_poll_timeout(
- hdev,
- mmPSOC_GLOBAL_CONF_WARM_REBOOT,
- status,
- (status == CPU_BOOT_STATUS_DRAM_RDY) ||
- (status == CPU_BOOT_STATUS_SRAM_AVAIL),
- 10000,
- cpu_timeout);
+ rc = hl_fw_init_cpu(hdev, mmPSOC_GLOBAL_CONF_CPU_BOOT_STATUS,
+ mmPSOC_GLOBAL_CONF_UBOOT_MAGIC,
+ mmCPU_CMD_STATUS_TO_HOST, mmCPU_BOOT_ERR0,
+ false, GOYA_CPU_TIMEOUT_USEC,
+ GOYA_BOOT_FIT_REQ_TIMEOUT_USEC);
- /* Read U-Boot version now in case we will later fail */
- goya_read_device_fw_version(hdev, FW_COMP_UBOOT);
- goya_read_device_fw_version(hdev, FW_COMP_PREBOOT);
-
- if (rc) {
- dev_err(hdev->dev, "Error in ARM u-boot!");
- switch (status) {
- case CPU_BOOT_STATUS_NA:
- dev_err(hdev->dev,
- "ARM status %d - BTL did NOT run\n", status);
- break;
- case CPU_BOOT_STATUS_IN_WFE:
- dev_err(hdev->dev,
- "ARM status %d - Inside WFE loop\n", status);
- break;
- case CPU_BOOT_STATUS_IN_BTL:
- dev_err(hdev->dev,
- "ARM status %d - Stuck in BTL\n", status);
- break;
- case CPU_BOOT_STATUS_IN_PREBOOT:
- dev_err(hdev->dev,
- "ARM status %d - Stuck in Preboot\n", status);
- break;
- case CPU_BOOT_STATUS_IN_SPL:
- dev_err(hdev->dev,
- "ARM status %d - Stuck in SPL\n", status);
- break;
- case CPU_BOOT_STATUS_IN_UBOOT:
- dev_err(hdev->dev,
- "ARM status %d - Stuck in u-boot\n", status);
- break;
- case CPU_BOOT_STATUS_DRAM_INIT_FAIL:
- dev_err(hdev->dev,
- "ARM status %d - DDR initialization failed\n",
- status);
- break;
- case CPU_BOOT_STATUS_UBOOT_NOT_READY:
- dev_err(hdev->dev,
- "ARM status %d - u-boot stopped by user\n",
- status);
- break;
- case CPU_BOOT_STATUS_TS_INIT_FAIL:
- dev_err(hdev->dev,
- "ARM status %d - Thermal Sensor initialization failed\n",
- status);
- break;
- default:
- dev_err(hdev->dev,
- "ARM status %d - Invalid status code\n",
- status);
- break;
- }
- return -EIO;
- }
-
- if (!hdev->fw_loading) {
- dev_info(hdev->dev, "Skip loading FW\n");
- goto out;
- }
-
- if (status == CPU_BOOT_STATUS_SRAM_AVAIL)
- goto out;
-
- rc = goya_push_linux_to_device(hdev);
if (rc)
return rc;
- WREG32(mmPSOC_GLOBAL_CONF_UBOOT_MAGIC, KMD_MSG_FIT_RDY);
-
- rc = hl_poll_timeout(
- hdev,
- mmPSOC_GLOBAL_CONF_WARM_REBOOT,
- status,
- (status == CPU_BOOT_STATUS_SRAM_AVAIL),
- 10000,
- cpu_timeout);
-
- if (rc) {
- if (status == CPU_BOOT_STATUS_FIT_CORRUPTED)
- dev_err(hdev->dev,
- "ARM u-boot reports FIT image is corrupted\n");
- else
- dev_err(hdev->dev,
- "ARM Linux failed to load, %d\n", status);
- WREG32(mmPSOC_GLOBAL_CONF_UBOOT_MAGIC, KMD_MSG_NA);
- return -EIO;
- }
-
- dev_info(hdev->dev, "Successfully loaded firmware to device\n");
-
-out:
goya->hw_cap_initialized |= HW_CAP_CPU;
return 0;
@@ -2565,7 +2429,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;
@@ -2684,30 +2548,6 @@ static void goya_hw_fini(struct hl_device *hdev, bool hard_reset)
HW_CAP_MMU | HW_CAP_TPC_MBIST |
HW_CAP_GOLDEN | HW_CAP_TPC);
memset(goya->events_stat, 0, sizeof(goya->events_stat));
-
- if (!hdev->pldm) {
- int rc;
- /* In case we are running inside VM and the VM is
- * shutting down, we need to make sure CPU boot-loader
- * is running before we can continue the VM shutdown.
- * That is because the VM will send an FLR signal that
- * we must answer
- */
- dev_info(hdev->dev,
- "Going to wait up to %ds for CPU boot loader\n",
- GOYA_CPU_TIMEOUT_USEC / 1000 / 1000);
-
- rc = hl_poll_timeout(
- hdev,
- mmPSOC_GLOBAL_CONF_WARM_REBOOT,
- status,
- (status == CPU_BOOT_STATUS_DRAM_RDY),
- 10000,
- GOYA_CPU_TIMEOUT_USEC);
- if (rc)
- dev_err(hdev->dev,
- "failed to wait for CPU boot loader\n");
- }
}
int goya_suspend(struct hl_device *hdev)
@@ -3555,6 +3395,7 @@ static int goya_validate_cb(struct hl_device *hdev,
*/
rc = goya_validate_wreg32(hdev,
parser, (struct packet_wreg32 *) user_pkt);
+ parser->patched_cb_size += pkt_size;
break;
case PACKET_WREG_BULK:
@@ -4016,7 +3857,8 @@ int goya_cs_parser(struct hl_device *hdev, struct hl_cs_parser *parser)
}
void goya_add_end_of_cb_packets(struct hl_device *hdev, u64 kernel_address,
- u32 len, u64 cq_addr, u32 cq_val, u32 msix_vec)
+ u32 len, u64 cq_addr, u32 cq_val, u32 msix_vec,
+ bool eb)
{
struct packet_msg_prot *cq_pkt;
u32 tmp;
@@ -5042,7 +4884,7 @@ static void goya_mmu_prepare(struct hl_device *hdev, u32 asid)
goya_mmu_prepare_reg(hdev, goya_mmu_regs[i], asid);
}
-static void goya_mmu_invalidate_cache(struct hl_device *hdev, bool is_hard,
+static int goya_mmu_invalidate_cache(struct hl_device *hdev, bool is_hard,
u32 flags)
{
struct goya_device *goya = hdev->asic_specific;
@@ -5051,11 +4893,11 @@ static void goya_mmu_invalidate_cache(struct hl_device *hdev, bool is_hard,
if (!(goya->hw_cap_initialized & HW_CAP_MMU) ||
hdev->hard_reset_pending)
- return;
+ return 0;
/* no need in L1 only invalidation in Goya */
if (!is_hard)
- return;
+ return 0;
if (hdev->pldm)
timeout_usec = GOYA_PLDM_MMU_TIMEOUT_USEC;
@@ -5077,13 +4919,17 @@ static void goya_mmu_invalidate_cache(struct hl_device *hdev, bool is_hard,
mutex_unlock(&hdev->mmu_cache_lock);
- if (rc)
- dev_notice_ratelimited(hdev->dev,
- "Timeout when waiting for MMU cache invalidation\n");
+ if (rc) {
+ dev_err_ratelimited(hdev->dev,
+ "MMU cache invalidation timeout\n");
+ hl_device_reset(hdev, true, false);
+ }
+
+ return rc;
}
-static void goya_mmu_invalidate_cache_range(struct hl_device *hdev,
- bool is_hard, u32 asid, u64 va, u64 size)
+static int goya_mmu_invalidate_cache_range(struct hl_device *hdev,
+ bool is_hard, u32 asid, u64 va, u64 size)
{
struct goya_device *goya = hdev->asic_specific;
u32 status, timeout_usec, inv_data, pi;
@@ -5091,11 +4937,11 @@ static void goya_mmu_invalidate_cache_range(struct hl_device *hdev,
if (!(goya->hw_cap_initialized & HW_CAP_MMU) ||
hdev->hard_reset_pending)
- return;
+ return 0;
/* no need in L1 only invalidation in Goya */
if (!is_hard)
- return;
+ return 0;
if (hdev->pldm)
timeout_usec = GOYA_PLDM_MMU_TIMEOUT_USEC;
@@ -5128,9 +4974,13 @@ static void goya_mmu_invalidate_cache_range(struct hl_device *hdev,
mutex_unlock(&hdev->mmu_cache_lock);
- if (rc)
- dev_notice_ratelimited(hdev->dev,
- "Timeout when waiting for MMU cache invalidation\n");
+ if (rc) {
+ dev_err_ratelimited(hdev->dev,
+ "MMU cache invalidation timeout\n");
+ hl_device_reset(hdev, true, false);
+ }
+
+ return rc;
}
int goya_send_heartbeat(struct hl_device *hdev)
@@ -5178,6 +5028,16 @@ int goya_armcp_info_get(struct hl_device *hdev)
return 0;
}
+static void goya_enable_clock_gating(struct hl_device *hdev)
+{
+
+}
+
+static void goya_disable_clock_gating(struct hl_device *hdev)
+{
+
+}
+
static bool goya_is_device_idle(struct hl_device *hdev, u32 *mask,
struct seq_file *s)
{
@@ -5293,6 +5153,68 @@ static enum hl_device_hw_state goya_get_hw_state(struct hl_device *hdev)
return RREG32(mmHW_STATE);
}
+u32 goya_get_queue_id_for_cq(struct hl_device *hdev, u32 cq_idx)
+{
+ return cq_idx;
+}
+
+static void goya_ext_queue_init(struct hl_device *hdev, u32 q_idx)
+{
+
+}
+
+static void goya_ext_queue_reset(struct hl_device *hdev, u32 q_idx)
+{
+
+}
+
+static u32 goya_get_signal_cb_size(struct hl_device *hdev)
+{
+ return 0;
+}
+
+static u32 goya_get_wait_cb_size(struct hl_device *hdev)
+{
+ return 0;
+}
+
+static void goya_gen_signal_cb(struct hl_device *hdev, void *data, u16 sob_id)
+{
+
+}
+
+static void goya_gen_wait_cb(struct hl_device *hdev, void *data, u16 sob_id,
+ u16 sob_val, u16 mon_id, u32 q_idx)
+{
+
+}
+
+static void goya_reset_sob(struct hl_device *hdev, void *data)
+{
+
+}
+
+static void goya_set_dma_mask_from_fw(struct hl_device *hdev)
+{
+ if (RREG32(mmPSOC_GLOBAL_CONF_NON_RST_FLOPS_0) ==
+ HL_POWER9_HOST_MAGIC) {
+ dev_dbg(hdev->dev, "Working in 64-bit DMA mode\n");
+ hdev->power9_64bit_dma_enable = 1;
+ hdev->dma_mask = 64;
+ } else {
+ dev_dbg(hdev->dev, "Working in 48-bit DMA mode\n");
+ hdev->power9_64bit_dma_enable = 0;
+ hdev->dma_mask = 48;
+ }
+}
+
+u64 goya_get_device_time(struct hl_device *hdev)
+{
+ u64 device_time = ((u64) RREG32(mmPSOC_TIMESTAMP_CNTCVU)) << 32;
+
+ return device_time | RREG32(mmPSOC_TIMESTAMP_CNTCVL);
+}
+
static const struct hl_asic_funcs goya_funcs = {
.early_init = goya_early_init,
.early_fini = goya_early_fini,
@@ -5337,6 +5259,8 @@ static const struct hl_asic_funcs goya_funcs = {
.mmu_invalidate_cache = goya_mmu_invalidate_cache,
.mmu_invalidate_cache_range = goya_mmu_invalidate_cache_range,
.send_heartbeat = goya_send_heartbeat,
+ .enable_clock_gating = goya_enable_clock_gating,
+ .disable_clock_gating = goya_disable_clock_gating,
.debug_coresight = goya_debug_coresight,
.is_device_idle = goya_is_device_idle,
.soft_reset_late_init = goya_soft_reset_late_init,
@@ -5352,7 +5276,20 @@ static const struct hl_asic_funcs goya_funcs = {
.rreg = hl_rreg,
.wreg = hl_wreg,
.halt_coresight = goya_halt_coresight,
- .get_clk_rate = goya_get_clk_rate
+ .get_clk_rate = goya_get_clk_rate,
+ .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,
+ .ext_queue_init = goya_ext_queue_init,
+ .ext_queue_reset = goya_ext_queue_reset,
+ .get_signal_cb_size = goya_get_signal_cb_size,
+ .get_wait_cb_size = goya_get_wait_cb_size,
+ .gen_signal_cb = goya_gen_signal_cb,
+ .gen_wait_cb = goya_gen_wait_cb,
+ .reset_sob = goya_reset_sob,
+ .set_dma_mask_from_fw = goya_set_dma_mask_from_fw,
+ .get_device_time = goya_get_device_time
};
/*