1*e65e175bSOded Gabbay // SPDX-License-Identifier: GPL-2.0 2*e65e175bSOded Gabbay 3*e65e175bSOded Gabbay /* 4*e65e175bSOded Gabbay * Copyright 2016-2022 HabanaLabs, Ltd. 5*e65e175bSOded Gabbay * All Rights Reserved. 6*e65e175bSOded Gabbay */ 7*e65e175bSOded Gabbay 8*e65e175bSOded Gabbay #include "habanalabs.h" 9*e65e175bSOded Gabbay #include "../include/common/hl_boot_if.h" 10*e65e175bSOded Gabbay 11*e65e175bSOded Gabbay #include <linux/firmware.h> 12*e65e175bSOded Gabbay #include <linux/crc32.h> 13*e65e175bSOded Gabbay #include <linux/slab.h> 14*e65e175bSOded Gabbay #include <linux/ctype.h> 15*e65e175bSOded Gabbay #include <linux/vmalloc.h> 16*e65e175bSOded Gabbay 17*e65e175bSOded Gabbay #include <trace/events/habanalabs.h> 18*e65e175bSOded Gabbay 19*e65e175bSOded Gabbay #define FW_FILE_MAX_SIZE 0x1400000 /* maximum size of 20MB */ 20*e65e175bSOded Gabbay 21*e65e175bSOded Gabbay static char *comms_cmd_str_arr[COMMS_INVLD_LAST] = { 22*e65e175bSOded Gabbay [COMMS_NOOP] = __stringify(COMMS_NOOP), 23*e65e175bSOded Gabbay [COMMS_CLR_STS] = __stringify(COMMS_CLR_STS), 24*e65e175bSOded Gabbay [COMMS_RST_STATE] = __stringify(COMMS_RST_STATE), 25*e65e175bSOded Gabbay [COMMS_PREP_DESC] = __stringify(COMMS_PREP_DESC), 26*e65e175bSOded Gabbay [COMMS_DATA_RDY] = __stringify(COMMS_DATA_RDY), 27*e65e175bSOded Gabbay [COMMS_EXEC] = __stringify(COMMS_EXEC), 28*e65e175bSOded Gabbay [COMMS_RST_DEV] = __stringify(COMMS_RST_DEV), 29*e65e175bSOded Gabbay [COMMS_GOTO_WFE] = __stringify(COMMS_GOTO_WFE), 30*e65e175bSOded Gabbay [COMMS_SKIP_BMC] = __stringify(COMMS_SKIP_BMC), 31*e65e175bSOded Gabbay [COMMS_PREP_DESC_ELBI] = __stringify(COMMS_PREP_DESC_ELBI), 32*e65e175bSOded Gabbay }; 33*e65e175bSOded Gabbay 34*e65e175bSOded Gabbay static char *comms_sts_str_arr[COMMS_STS_INVLD_LAST] = { 35*e65e175bSOded Gabbay [COMMS_STS_NOOP] = __stringify(COMMS_STS_NOOP), 36*e65e175bSOded Gabbay [COMMS_STS_ACK] = __stringify(COMMS_STS_ACK), 37*e65e175bSOded Gabbay [COMMS_STS_OK] = __stringify(COMMS_STS_OK), 38*e65e175bSOded Gabbay [COMMS_STS_ERR] = __stringify(COMMS_STS_ERR), 39*e65e175bSOded Gabbay [COMMS_STS_VALID_ERR] = __stringify(COMMS_STS_VALID_ERR), 40*e65e175bSOded Gabbay [COMMS_STS_TIMEOUT_ERR] = __stringify(COMMS_STS_TIMEOUT_ERR), 41*e65e175bSOded Gabbay }; 42*e65e175bSOded Gabbay 43*e65e175bSOded Gabbay static char *extract_fw_ver_from_str(const char *fw_str) 44*e65e175bSOded Gabbay { 45*e65e175bSOded Gabbay char *str, *fw_ver, *whitespace; 46*e65e175bSOded Gabbay u32 ver_offset; 47*e65e175bSOded Gabbay 48*e65e175bSOded Gabbay fw_ver = kmalloc(VERSION_MAX_LEN, GFP_KERNEL); 49*e65e175bSOded Gabbay if (!fw_ver) 50*e65e175bSOded Gabbay return NULL; 51*e65e175bSOded Gabbay 52*e65e175bSOded Gabbay str = strnstr(fw_str, "fw-", VERSION_MAX_LEN); 53*e65e175bSOded Gabbay if (!str) 54*e65e175bSOded Gabbay goto free_fw_ver; 55*e65e175bSOded Gabbay 56*e65e175bSOded Gabbay /* Skip the fw- part */ 57*e65e175bSOded Gabbay str += 3; 58*e65e175bSOded Gabbay ver_offset = str - fw_str; 59*e65e175bSOded Gabbay 60*e65e175bSOded Gabbay /* Copy until the next whitespace */ 61*e65e175bSOded Gabbay whitespace = strnstr(str, " ", VERSION_MAX_LEN - ver_offset); 62*e65e175bSOded Gabbay if (!whitespace) 63*e65e175bSOded Gabbay goto free_fw_ver; 64*e65e175bSOded Gabbay 65*e65e175bSOded Gabbay strscpy(fw_ver, str, whitespace - str + 1); 66*e65e175bSOded Gabbay 67*e65e175bSOded Gabbay return fw_ver; 68*e65e175bSOded Gabbay 69*e65e175bSOded Gabbay free_fw_ver: 70*e65e175bSOded Gabbay kfree(fw_ver); 71*e65e175bSOded Gabbay return NULL; 72*e65e175bSOded Gabbay } 73*e65e175bSOded Gabbay 74*e65e175bSOded Gabbay static int extract_fw_sub_versions(struct hl_device *hdev, char *preboot_ver) 75*e65e175bSOded Gabbay { 76*e65e175bSOded Gabbay char major[8], minor[8], *first_dot, *second_dot; 77*e65e175bSOded Gabbay int rc; 78*e65e175bSOded Gabbay 79*e65e175bSOded Gabbay first_dot = strnstr(preboot_ver, ".", 10); 80*e65e175bSOded Gabbay if (first_dot) { 81*e65e175bSOded Gabbay strscpy(major, preboot_ver, first_dot - preboot_ver + 1); 82*e65e175bSOded Gabbay rc = kstrtou32(major, 10, &hdev->fw_major_version); 83*e65e175bSOded Gabbay } else { 84*e65e175bSOded Gabbay rc = -EINVAL; 85*e65e175bSOded Gabbay } 86*e65e175bSOded Gabbay 87*e65e175bSOded Gabbay if (rc) { 88*e65e175bSOded Gabbay dev_err(hdev->dev, "Error %d parsing preboot major version\n", rc); 89*e65e175bSOded Gabbay goto out; 90*e65e175bSOded Gabbay } 91*e65e175bSOded Gabbay 92*e65e175bSOded Gabbay /* skip the first dot */ 93*e65e175bSOded Gabbay first_dot++; 94*e65e175bSOded Gabbay 95*e65e175bSOded Gabbay second_dot = strnstr(first_dot, ".", 10); 96*e65e175bSOded Gabbay if (second_dot) { 97*e65e175bSOded Gabbay strscpy(minor, first_dot, second_dot - first_dot + 1); 98*e65e175bSOded Gabbay rc = kstrtou32(minor, 10, &hdev->fw_minor_version); 99*e65e175bSOded Gabbay } else { 100*e65e175bSOded Gabbay rc = -EINVAL; 101*e65e175bSOded Gabbay } 102*e65e175bSOded Gabbay 103*e65e175bSOded Gabbay if (rc) 104*e65e175bSOded Gabbay dev_err(hdev->dev, "Error %d parsing preboot minor version\n", rc); 105*e65e175bSOded Gabbay 106*e65e175bSOded Gabbay out: 107*e65e175bSOded Gabbay kfree(preboot_ver); 108*e65e175bSOded Gabbay return rc; 109*e65e175bSOded Gabbay } 110*e65e175bSOded Gabbay 111*e65e175bSOded Gabbay static int hl_request_fw(struct hl_device *hdev, 112*e65e175bSOded Gabbay const struct firmware **firmware_p, 113*e65e175bSOded Gabbay const char *fw_name) 114*e65e175bSOded Gabbay { 115*e65e175bSOded Gabbay size_t fw_size; 116*e65e175bSOded Gabbay int rc; 117*e65e175bSOded Gabbay 118*e65e175bSOded Gabbay rc = request_firmware(firmware_p, fw_name, hdev->dev); 119*e65e175bSOded Gabbay if (rc) { 120*e65e175bSOded Gabbay dev_err(hdev->dev, "Firmware file %s is not found! (error %d)\n", 121*e65e175bSOded Gabbay fw_name, rc); 122*e65e175bSOded Gabbay goto out; 123*e65e175bSOded Gabbay } 124*e65e175bSOded Gabbay 125*e65e175bSOded Gabbay fw_size = (*firmware_p)->size; 126*e65e175bSOded Gabbay if ((fw_size % 4) != 0) { 127*e65e175bSOded Gabbay dev_err(hdev->dev, "Illegal %s firmware size %zu\n", 128*e65e175bSOded Gabbay fw_name, fw_size); 129*e65e175bSOded Gabbay rc = -EINVAL; 130*e65e175bSOded Gabbay goto release_fw; 131*e65e175bSOded Gabbay } 132*e65e175bSOded Gabbay 133*e65e175bSOded Gabbay dev_dbg(hdev->dev, "%s firmware size == %zu\n", fw_name, fw_size); 134*e65e175bSOded Gabbay 135*e65e175bSOded Gabbay if (fw_size > FW_FILE_MAX_SIZE) { 136*e65e175bSOded Gabbay dev_err(hdev->dev, 137*e65e175bSOded Gabbay "FW file size %zu exceeds maximum of %u bytes\n", 138*e65e175bSOded Gabbay fw_size, FW_FILE_MAX_SIZE); 139*e65e175bSOded Gabbay rc = -EINVAL; 140*e65e175bSOded Gabbay goto release_fw; 141*e65e175bSOded Gabbay } 142*e65e175bSOded Gabbay 143*e65e175bSOded Gabbay return 0; 144*e65e175bSOded Gabbay 145*e65e175bSOded Gabbay release_fw: 146*e65e175bSOded Gabbay release_firmware(*firmware_p); 147*e65e175bSOded Gabbay out: 148*e65e175bSOded Gabbay return rc; 149*e65e175bSOded Gabbay } 150*e65e175bSOded Gabbay 151*e65e175bSOded Gabbay /** 152*e65e175bSOded Gabbay * hl_release_firmware() - release FW 153*e65e175bSOded Gabbay * 154*e65e175bSOded Gabbay * @fw: fw descriptor 155*e65e175bSOded Gabbay * 156*e65e175bSOded Gabbay * note: this inline function added to serve as a comprehensive mirror for the 157*e65e175bSOded Gabbay * hl_request_fw function. 158*e65e175bSOded Gabbay */ 159*e65e175bSOded Gabbay static inline void hl_release_firmware(const struct firmware *fw) 160*e65e175bSOded Gabbay { 161*e65e175bSOded Gabbay release_firmware(fw); 162*e65e175bSOded Gabbay } 163*e65e175bSOded Gabbay 164*e65e175bSOded Gabbay /** 165*e65e175bSOded Gabbay * hl_fw_copy_fw_to_device() - copy FW to device 166*e65e175bSOded Gabbay * 167*e65e175bSOded Gabbay * @hdev: pointer to hl_device structure. 168*e65e175bSOded Gabbay * @fw: fw descriptor 169*e65e175bSOded Gabbay * @dst: IO memory mapped address space to copy firmware to 170*e65e175bSOded Gabbay * @src_offset: offset in src FW to copy from 171*e65e175bSOded Gabbay * @size: amount of bytes to copy (0 to copy the whole binary) 172*e65e175bSOded Gabbay * 173*e65e175bSOded Gabbay * actual copy of FW binary data to device, shared by static and dynamic loaders 174*e65e175bSOded Gabbay */ 175*e65e175bSOded Gabbay static int hl_fw_copy_fw_to_device(struct hl_device *hdev, 176*e65e175bSOded Gabbay const struct firmware *fw, void __iomem *dst, 177*e65e175bSOded Gabbay u32 src_offset, u32 size) 178*e65e175bSOded Gabbay { 179*e65e175bSOded Gabbay const void *fw_data; 180*e65e175bSOded Gabbay 181*e65e175bSOded Gabbay /* size 0 indicates to copy the whole file */ 182*e65e175bSOded Gabbay if (!size) 183*e65e175bSOded Gabbay size = fw->size; 184*e65e175bSOded Gabbay 185*e65e175bSOded Gabbay if (src_offset + size > fw->size) { 186*e65e175bSOded Gabbay dev_err(hdev->dev, 187*e65e175bSOded Gabbay "size to copy(%u) and offset(%u) are invalid\n", 188*e65e175bSOded Gabbay size, src_offset); 189*e65e175bSOded Gabbay return -EINVAL; 190*e65e175bSOded Gabbay } 191*e65e175bSOded Gabbay 192*e65e175bSOded Gabbay fw_data = (const void *) fw->data; 193*e65e175bSOded Gabbay 194*e65e175bSOded Gabbay memcpy_toio(dst, fw_data + src_offset, size); 195*e65e175bSOded Gabbay return 0; 196*e65e175bSOded Gabbay } 197*e65e175bSOded Gabbay 198*e65e175bSOded Gabbay /** 199*e65e175bSOded Gabbay * hl_fw_copy_msg_to_device() - copy message to device 200*e65e175bSOded Gabbay * 201*e65e175bSOded Gabbay * @hdev: pointer to hl_device structure. 202*e65e175bSOded Gabbay * @msg: message 203*e65e175bSOded Gabbay * @dst: IO memory mapped address space to copy firmware to 204*e65e175bSOded Gabbay * @src_offset: offset in src message to copy from 205*e65e175bSOded Gabbay * @size: amount of bytes to copy (0 to copy the whole binary) 206*e65e175bSOded Gabbay * 207*e65e175bSOded Gabbay * actual copy of message data to device. 208*e65e175bSOded Gabbay */ 209*e65e175bSOded Gabbay static int hl_fw_copy_msg_to_device(struct hl_device *hdev, 210*e65e175bSOded Gabbay struct lkd_msg_comms *msg, void __iomem *dst, 211*e65e175bSOded Gabbay u32 src_offset, u32 size) 212*e65e175bSOded Gabbay { 213*e65e175bSOded Gabbay void *msg_data; 214*e65e175bSOded Gabbay 215*e65e175bSOded Gabbay /* size 0 indicates to copy the whole file */ 216*e65e175bSOded Gabbay if (!size) 217*e65e175bSOded Gabbay size = sizeof(struct lkd_msg_comms); 218*e65e175bSOded Gabbay 219*e65e175bSOded Gabbay if (src_offset + size > sizeof(struct lkd_msg_comms)) { 220*e65e175bSOded Gabbay dev_err(hdev->dev, 221*e65e175bSOded Gabbay "size to copy(%u) and offset(%u) are invalid\n", 222*e65e175bSOded Gabbay size, src_offset); 223*e65e175bSOded Gabbay return -EINVAL; 224*e65e175bSOded Gabbay } 225*e65e175bSOded Gabbay 226*e65e175bSOded Gabbay msg_data = (void *) msg; 227*e65e175bSOded Gabbay 228*e65e175bSOded Gabbay memcpy_toio(dst, msg_data + src_offset, size); 229*e65e175bSOded Gabbay 230*e65e175bSOded Gabbay return 0; 231*e65e175bSOded Gabbay } 232*e65e175bSOded Gabbay 233*e65e175bSOded Gabbay /** 234*e65e175bSOded Gabbay * hl_fw_load_fw_to_device() - Load F/W code to device's memory. 235*e65e175bSOded Gabbay * 236*e65e175bSOded Gabbay * @hdev: pointer to hl_device structure. 237*e65e175bSOded Gabbay * @fw_name: the firmware image name 238*e65e175bSOded Gabbay * @dst: IO memory mapped address space to copy firmware to 239*e65e175bSOded Gabbay * @src_offset: offset in src FW to copy from 240*e65e175bSOded Gabbay * @size: amount of bytes to copy (0 to copy the whole binary) 241*e65e175bSOded Gabbay * 242*e65e175bSOded Gabbay * Copy fw code from firmware file to device memory. 243*e65e175bSOded Gabbay * 244*e65e175bSOded Gabbay * Return: 0 on success, non-zero for failure. 245*e65e175bSOded Gabbay */ 246*e65e175bSOded Gabbay int hl_fw_load_fw_to_device(struct hl_device *hdev, const char *fw_name, 247*e65e175bSOded Gabbay void __iomem *dst, u32 src_offset, u32 size) 248*e65e175bSOded Gabbay { 249*e65e175bSOded Gabbay const struct firmware *fw; 250*e65e175bSOded Gabbay int rc; 251*e65e175bSOded Gabbay 252*e65e175bSOded Gabbay rc = hl_request_fw(hdev, &fw, fw_name); 253*e65e175bSOded Gabbay if (rc) 254*e65e175bSOded Gabbay return rc; 255*e65e175bSOded Gabbay 256*e65e175bSOded Gabbay rc = hl_fw_copy_fw_to_device(hdev, fw, dst, src_offset, size); 257*e65e175bSOded Gabbay 258*e65e175bSOded Gabbay hl_release_firmware(fw); 259*e65e175bSOded Gabbay return rc; 260*e65e175bSOded Gabbay } 261*e65e175bSOded Gabbay 262*e65e175bSOded Gabbay int hl_fw_send_pci_access_msg(struct hl_device *hdev, u32 opcode, u64 value) 263*e65e175bSOded Gabbay { 264*e65e175bSOded Gabbay struct cpucp_packet pkt = {}; 265*e65e175bSOded Gabbay 266*e65e175bSOded Gabbay pkt.ctl = cpu_to_le32(opcode << CPUCP_PKT_CTL_OPCODE_SHIFT); 267*e65e175bSOded Gabbay pkt.value = cpu_to_le64(value); 268*e65e175bSOded Gabbay 269*e65e175bSOded Gabbay return hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt), 0, NULL); 270*e65e175bSOded Gabbay } 271*e65e175bSOded Gabbay 272*e65e175bSOded Gabbay int hl_fw_send_cpu_message(struct hl_device *hdev, u32 hw_queue_id, u32 *msg, 273*e65e175bSOded Gabbay u16 len, u32 timeout, u64 *result) 274*e65e175bSOded Gabbay { 275*e65e175bSOded Gabbay struct hl_hw_queue *queue = &hdev->kernel_queues[hw_queue_id]; 276*e65e175bSOded Gabbay struct asic_fixed_properties *prop = &hdev->asic_prop; 277*e65e175bSOded Gabbay struct cpucp_packet *pkt; 278*e65e175bSOded Gabbay dma_addr_t pkt_dma_addr; 279*e65e175bSOded Gabbay struct hl_bd *sent_bd; 280*e65e175bSOded Gabbay u32 tmp, expected_ack_val, pi, opcode; 281*e65e175bSOded Gabbay int rc; 282*e65e175bSOded Gabbay 283*e65e175bSOded Gabbay pkt = hl_cpu_accessible_dma_pool_alloc(hdev, len, &pkt_dma_addr); 284*e65e175bSOded Gabbay if (!pkt) { 285*e65e175bSOded Gabbay dev_err(hdev->dev, 286*e65e175bSOded Gabbay "Failed to allocate DMA memory for packet to CPU\n"); 287*e65e175bSOded Gabbay return -ENOMEM; 288*e65e175bSOded Gabbay } 289*e65e175bSOded Gabbay 290*e65e175bSOded Gabbay memcpy(pkt, msg, len); 291*e65e175bSOded Gabbay 292*e65e175bSOded Gabbay mutex_lock(&hdev->send_cpu_message_lock); 293*e65e175bSOded Gabbay 294*e65e175bSOded Gabbay /* CPU-CP messages can be sent during soft-reset */ 295*e65e175bSOded Gabbay if (hdev->disabled && !hdev->reset_info.in_compute_reset) { 296*e65e175bSOded Gabbay rc = 0; 297*e65e175bSOded Gabbay goto out; 298*e65e175bSOded Gabbay } 299*e65e175bSOded Gabbay 300*e65e175bSOded Gabbay if (hdev->device_cpu_disabled) { 301*e65e175bSOded Gabbay rc = -EIO; 302*e65e175bSOded Gabbay goto out; 303*e65e175bSOded Gabbay } 304*e65e175bSOded Gabbay 305*e65e175bSOded Gabbay /* set fence to a non valid value */ 306*e65e175bSOded Gabbay pkt->fence = cpu_to_le32(UINT_MAX); 307*e65e175bSOded Gabbay pi = queue->pi; 308*e65e175bSOded Gabbay 309*e65e175bSOded Gabbay /* 310*e65e175bSOded Gabbay * The CPU queue is a synchronous queue with an effective depth of 311*e65e175bSOded Gabbay * a single entry (although it is allocated with room for multiple 312*e65e175bSOded Gabbay * entries). We lock on it using 'send_cpu_message_lock' which 313*e65e175bSOded Gabbay * serializes accesses to the CPU queue. 314*e65e175bSOded Gabbay * Which means that we don't need to lock the access to the entire H/W 315*e65e175bSOded Gabbay * queues module when submitting a JOB to the CPU queue. 316*e65e175bSOded Gabbay */ 317*e65e175bSOded Gabbay hl_hw_queue_submit_bd(hdev, queue, hl_queue_inc_ptr(queue->pi), len, pkt_dma_addr); 318*e65e175bSOded Gabbay 319*e65e175bSOded Gabbay if (prop->fw_app_cpu_boot_dev_sts0 & CPU_BOOT_DEV_STS0_PKT_PI_ACK_EN) 320*e65e175bSOded Gabbay expected_ack_val = queue->pi; 321*e65e175bSOded Gabbay else 322*e65e175bSOded Gabbay expected_ack_val = CPUCP_PACKET_FENCE_VAL; 323*e65e175bSOded Gabbay 324*e65e175bSOded Gabbay rc = hl_poll_timeout_memory(hdev, &pkt->fence, tmp, 325*e65e175bSOded Gabbay (tmp == expected_ack_val), 1000, 326*e65e175bSOded Gabbay timeout, true); 327*e65e175bSOded Gabbay 328*e65e175bSOded Gabbay hl_hw_queue_inc_ci_kernel(hdev, hw_queue_id); 329*e65e175bSOded Gabbay 330*e65e175bSOded Gabbay if (rc == -ETIMEDOUT) { 331*e65e175bSOded Gabbay /* If FW performed reset just before sending it a packet, we will get a timeout. 332*e65e175bSOded Gabbay * This is expected behavior, hence no need for error message. 333*e65e175bSOded Gabbay */ 334*e65e175bSOded Gabbay if (!hl_device_operational(hdev, NULL) && !hdev->reset_info.in_compute_reset) 335*e65e175bSOded Gabbay dev_dbg(hdev->dev, "Device CPU packet timeout (0x%x) due to FW reset\n", 336*e65e175bSOded Gabbay tmp); 337*e65e175bSOded Gabbay else 338*e65e175bSOded Gabbay dev_err(hdev->dev, "Device CPU packet timeout (0x%x)\n", tmp); 339*e65e175bSOded Gabbay hdev->device_cpu_disabled = true; 340*e65e175bSOded Gabbay goto out; 341*e65e175bSOded Gabbay } 342*e65e175bSOded Gabbay 343*e65e175bSOded Gabbay tmp = le32_to_cpu(pkt->ctl); 344*e65e175bSOded Gabbay 345*e65e175bSOded Gabbay rc = (tmp & CPUCP_PKT_CTL_RC_MASK) >> CPUCP_PKT_CTL_RC_SHIFT; 346*e65e175bSOded Gabbay if (rc) { 347*e65e175bSOded Gabbay opcode = (tmp & CPUCP_PKT_CTL_OPCODE_MASK) >> CPUCP_PKT_CTL_OPCODE_SHIFT; 348*e65e175bSOded Gabbay 349*e65e175bSOded Gabbay if (!prop->supports_advanced_cpucp_rc) { 350*e65e175bSOded Gabbay dev_dbg(hdev->dev, "F/W ERROR %d for CPU packet %d\n", rc, opcode); 351*e65e175bSOded Gabbay rc = -EIO; 352*e65e175bSOded Gabbay goto scrub_descriptor; 353*e65e175bSOded Gabbay } 354*e65e175bSOded Gabbay 355*e65e175bSOded Gabbay switch (rc) { 356*e65e175bSOded Gabbay case cpucp_packet_invalid: 357*e65e175bSOded Gabbay dev_err(hdev->dev, 358*e65e175bSOded Gabbay "CPU packet %d is not supported by F/W\n", opcode); 359*e65e175bSOded Gabbay break; 360*e65e175bSOded Gabbay case cpucp_packet_fault: 361*e65e175bSOded Gabbay dev_err(hdev->dev, 362*e65e175bSOded Gabbay "F/W failed processing CPU packet %d\n", opcode); 363*e65e175bSOded Gabbay break; 364*e65e175bSOded Gabbay case cpucp_packet_invalid_pkt: 365*e65e175bSOded Gabbay dev_dbg(hdev->dev, 366*e65e175bSOded Gabbay "CPU packet %d is not supported by F/W\n", opcode); 367*e65e175bSOded Gabbay break; 368*e65e175bSOded Gabbay case cpucp_packet_invalid_params: 369*e65e175bSOded Gabbay dev_err(hdev->dev, 370*e65e175bSOded Gabbay "F/W reports invalid parameters for CPU packet %d\n", opcode); 371*e65e175bSOded Gabbay break; 372*e65e175bSOded Gabbay 373*e65e175bSOded Gabbay default: 374*e65e175bSOded Gabbay dev_err(hdev->dev, 375*e65e175bSOded Gabbay "Unknown F/W ERROR %d for CPU packet %d\n", rc, opcode); 376*e65e175bSOded Gabbay } 377*e65e175bSOded Gabbay 378*e65e175bSOded Gabbay /* propagate the return code from the f/w to the callers who want to check it */ 379*e65e175bSOded Gabbay if (result) 380*e65e175bSOded Gabbay *result = rc; 381*e65e175bSOded Gabbay 382*e65e175bSOded Gabbay rc = -EIO; 383*e65e175bSOded Gabbay 384*e65e175bSOded Gabbay } else if (result) { 385*e65e175bSOded Gabbay *result = le64_to_cpu(pkt->result); 386*e65e175bSOded Gabbay } 387*e65e175bSOded Gabbay 388*e65e175bSOded Gabbay scrub_descriptor: 389*e65e175bSOded Gabbay /* Scrub previous buffer descriptor 'ctl' field which contains the 390*e65e175bSOded Gabbay * previous PI value written during packet submission. 391*e65e175bSOded Gabbay * We must do this or else F/W can read an old value upon queue wraparound. 392*e65e175bSOded Gabbay */ 393*e65e175bSOded Gabbay sent_bd = queue->kernel_address; 394*e65e175bSOded Gabbay sent_bd += hl_pi_2_offset(pi); 395*e65e175bSOded Gabbay sent_bd->ctl = cpu_to_le32(UINT_MAX); 396*e65e175bSOded Gabbay 397*e65e175bSOded Gabbay out: 398*e65e175bSOded Gabbay mutex_unlock(&hdev->send_cpu_message_lock); 399*e65e175bSOded Gabbay 400*e65e175bSOded Gabbay hl_cpu_accessible_dma_pool_free(hdev, len, pkt); 401*e65e175bSOded Gabbay 402*e65e175bSOded Gabbay return rc; 403*e65e175bSOded Gabbay } 404*e65e175bSOded Gabbay 405*e65e175bSOded Gabbay int hl_fw_unmask_irq(struct hl_device *hdev, u16 event_type) 406*e65e175bSOded Gabbay { 407*e65e175bSOded Gabbay struct cpucp_packet pkt; 408*e65e175bSOded Gabbay u64 result; 409*e65e175bSOded Gabbay int rc; 410*e65e175bSOded Gabbay 411*e65e175bSOded Gabbay memset(&pkt, 0, sizeof(pkt)); 412*e65e175bSOded Gabbay 413*e65e175bSOded Gabbay pkt.ctl = cpu_to_le32(CPUCP_PACKET_UNMASK_RAZWI_IRQ << 414*e65e175bSOded Gabbay CPUCP_PKT_CTL_OPCODE_SHIFT); 415*e65e175bSOded Gabbay pkt.value = cpu_to_le64(event_type); 416*e65e175bSOded Gabbay 417*e65e175bSOded Gabbay rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt), 418*e65e175bSOded Gabbay 0, &result); 419*e65e175bSOded Gabbay 420*e65e175bSOded Gabbay if (rc) 421*e65e175bSOded Gabbay dev_err(hdev->dev, "failed to unmask RAZWI IRQ %d", event_type); 422*e65e175bSOded Gabbay 423*e65e175bSOded Gabbay return rc; 424*e65e175bSOded Gabbay } 425*e65e175bSOded Gabbay 426*e65e175bSOded Gabbay int hl_fw_unmask_irq_arr(struct hl_device *hdev, const u32 *irq_arr, 427*e65e175bSOded Gabbay size_t irq_arr_size) 428*e65e175bSOded Gabbay { 429*e65e175bSOded Gabbay struct cpucp_unmask_irq_arr_packet *pkt; 430*e65e175bSOded Gabbay size_t total_pkt_size; 431*e65e175bSOded Gabbay u64 result; 432*e65e175bSOded Gabbay int rc; 433*e65e175bSOded Gabbay 434*e65e175bSOded Gabbay total_pkt_size = sizeof(struct cpucp_unmask_irq_arr_packet) + 435*e65e175bSOded Gabbay irq_arr_size; 436*e65e175bSOded Gabbay 437*e65e175bSOded Gabbay /* data should be aligned to 8 bytes in order to CPU-CP to copy it */ 438*e65e175bSOded Gabbay total_pkt_size = (total_pkt_size + 0x7) & ~0x7; 439*e65e175bSOded Gabbay 440*e65e175bSOded Gabbay /* total_pkt_size is casted to u16 later on */ 441*e65e175bSOded Gabbay if (total_pkt_size > USHRT_MAX) { 442*e65e175bSOded Gabbay dev_err(hdev->dev, "too many elements in IRQ array\n"); 443*e65e175bSOded Gabbay return -EINVAL; 444*e65e175bSOded Gabbay } 445*e65e175bSOded Gabbay 446*e65e175bSOded Gabbay pkt = kzalloc(total_pkt_size, GFP_KERNEL); 447*e65e175bSOded Gabbay if (!pkt) 448*e65e175bSOded Gabbay return -ENOMEM; 449*e65e175bSOded Gabbay 450*e65e175bSOded Gabbay pkt->length = cpu_to_le32(irq_arr_size / sizeof(irq_arr[0])); 451*e65e175bSOded Gabbay memcpy(&pkt->irqs, irq_arr, irq_arr_size); 452*e65e175bSOded Gabbay 453*e65e175bSOded Gabbay pkt->cpucp_pkt.ctl = cpu_to_le32(CPUCP_PACKET_UNMASK_RAZWI_IRQ_ARRAY << 454*e65e175bSOded Gabbay CPUCP_PKT_CTL_OPCODE_SHIFT); 455*e65e175bSOded Gabbay 456*e65e175bSOded Gabbay rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) pkt, 457*e65e175bSOded Gabbay total_pkt_size, 0, &result); 458*e65e175bSOded Gabbay 459*e65e175bSOded Gabbay if (rc) 460*e65e175bSOded Gabbay dev_err(hdev->dev, "failed to unmask IRQ array\n"); 461*e65e175bSOded Gabbay 462*e65e175bSOded Gabbay kfree(pkt); 463*e65e175bSOded Gabbay 464*e65e175bSOded Gabbay return rc; 465*e65e175bSOded Gabbay } 466*e65e175bSOded Gabbay 467*e65e175bSOded Gabbay int hl_fw_test_cpu_queue(struct hl_device *hdev) 468*e65e175bSOded Gabbay { 469*e65e175bSOded Gabbay struct cpucp_packet test_pkt = {}; 470*e65e175bSOded Gabbay u64 result; 471*e65e175bSOded Gabbay int rc; 472*e65e175bSOded Gabbay 473*e65e175bSOded Gabbay test_pkt.ctl = cpu_to_le32(CPUCP_PACKET_TEST << 474*e65e175bSOded Gabbay CPUCP_PKT_CTL_OPCODE_SHIFT); 475*e65e175bSOded Gabbay test_pkt.value = cpu_to_le64(CPUCP_PACKET_FENCE_VAL); 476*e65e175bSOded Gabbay 477*e65e175bSOded Gabbay rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &test_pkt, 478*e65e175bSOded Gabbay sizeof(test_pkt), 0, &result); 479*e65e175bSOded Gabbay 480*e65e175bSOded Gabbay if (!rc) { 481*e65e175bSOded Gabbay if (result != CPUCP_PACKET_FENCE_VAL) 482*e65e175bSOded Gabbay dev_err(hdev->dev, 483*e65e175bSOded Gabbay "CPU queue test failed (%#08llx)\n", result); 484*e65e175bSOded Gabbay } else { 485*e65e175bSOded Gabbay dev_err(hdev->dev, "CPU queue test failed, error %d\n", rc); 486*e65e175bSOded Gabbay } 487*e65e175bSOded Gabbay 488*e65e175bSOded Gabbay return rc; 489*e65e175bSOded Gabbay } 490*e65e175bSOded Gabbay 491*e65e175bSOded Gabbay void *hl_fw_cpu_accessible_dma_pool_alloc(struct hl_device *hdev, size_t size, 492*e65e175bSOded Gabbay dma_addr_t *dma_handle) 493*e65e175bSOded Gabbay { 494*e65e175bSOded Gabbay u64 kernel_addr; 495*e65e175bSOded Gabbay 496*e65e175bSOded Gabbay kernel_addr = gen_pool_alloc(hdev->cpu_accessible_dma_pool, size); 497*e65e175bSOded Gabbay 498*e65e175bSOded Gabbay *dma_handle = hdev->cpu_accessible_dma_address + 499*e65e175bSOded Gabbay (kernel_addr - (u64) (uintptr_t) hdev->cpu_accessible_dma_mem); 500*e65e175bSOded Gabbay 501*e65e175bSOded Gabbay return (void *) (uintptr_t) kernel_addr; 502*e65e175bSOded Gabbay } 503*e65e175bSOded Gabbay 504*e65e175bSOded Gabbay void hl_fw_cpu_accessible_dma_pool_free(struct hl_device *hdev, size_t size, 505*e65e175bSOded Gabbay void *vaddr) 506*e65e175bSOded Gabbay { 507*e65e175bSOded Gabbay gen_pool_free(hdev->cpu_accessible_dma_pool, (u64) (uintptr_t) vaddr, 508*e65e175bSOded Gabbay size); 509*e65e175bSOded Gabbay } 510*e65e175bSOded Gabbay 511*e65e175bSOded Gabbay int hl_fw_send_device_activity(struct hl_device *hdev, bool open) 512*e65e175bSOded Gabbay { 513*e65e175bSOded Gabbay struct cpucp_packet pkt; 514*e65e175bSOded Gabbay int rc; 515*e65e175bSOded Gabbay 516*e65e175bSOded Gabbay memset(&pkt, 0, sizeof(pkt)); 517*e65e175bSOded Gabbay pkt.ctl = cpu_to_le32(CPUCP_PACKET_ACTIVE_STATUS_SET << CPUCP_PKT_CTL_OPCODE_SHIFT); 518*e65e175bSOded Gabbay pkt.value = cpu_to_le64(open); 519*e65e175bSOded Gabbay rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt), 0, NULL); 520*e65e175bSOded Gabbay if (rc) 521*e65e175bSOded Gabbay dev_err(hdev->dev, "failed to send device activity msg(%u)\n", open); 522*e65e175bSOded Gabbay 523*e65e175bSOded Gabbay return rc; 524*e65e175bSOded Gabbay } 525*e65e175bSOded Gabbay 526*e65e175bSOded Gabbay int hl_fw_send_heartbeat(struct hl_device *hdev) 527*e65e175bSOded Gabbay { 528*e65e175bSOded Gabbay struct cpucp_packet hb_pkt; 529*e65e175bSOded Gabbay u64 result; 530*e65e175bSOded Gabbay int rc; 531*e65e175bSOded Gabbay 532*e65e175bSOded Gabbay memset(&hb_pkt, 0, sizeof(hb_pkt)); 533*e65e175bSOded Gabbay hb_pkt.ctl = cpu_to_le32(CPUCP_PACKET_TEST << 534*e65e175bSOded Gabbay CPUCP_PKT_CTL_OPCODE_SHIFT); 535*e65e175bSOded Gabbay hb_pkt.value = cpu_to_le64(CPUCP_PACKET_FENCE_VAL); 536*e65e175bSOded Gabbay 537*e65e175bSOded Gabbay rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &hb_pkt, 538*e65e175bSOded Gabbay sizeof(hb_pkt), 0, &result); 539*e65e175bSOded Gabbay 540*e65e175bSOded Gabbay if ((rc) || (result != CPUCP_PACKET_FENCE_VAL)) 541*e65e175bSOded Gabbay return -EIO; 542*e65e175bSOded Gabbay 543*e65e175bSOded Gabbay if (le32_to_cpu(hb_pkt.status_mask) & 544*e65e175bSOded Gabbay CPUCP_PKT_HB_STATUS_EQ_FAULT_MASK) { 545*e65e175bSOded Gabbay dev_warn(hdev->dev, "FW reported EQ fault during heartbeat\n"); 546*e65e175bSOded Gabbay rc = -EIO; 547*e65e175bSOded Gabbay } 548*e65e175bSOded Gabbay 549*e65e175bSOded Gabbay return rc; 550*e65e175bSOded Gabbay } 551*e65e175bSOded Gabbay 552*e65e175bSOded Gabbay static bool fw_report_boot_dev0(struct hl_device *hdev, u32 err_val, 553*e65e175bSOded Gabbay u32 sts_val) 554*e65e175bSOded Gabbay { 555*e65e175bSOded Gabbay bool err_exists = false; 556*e65e175bSOded Gabbay 557*e65e175bSOded Gabbay if (!(err_val & CPU_BOOT_ERR0_ENABLED)) 558*e65e175bSOded Gabbay return false; 559*e65e175bSOded Gabbay 560*e65e175bSOded Gabbay if (err_val & CPU_BOOT_ERR0_DRAM_INIT_FAIL) { 561*e65e175bSOded Gabbay dev_err(hdev->dev, 562*e65e175bSOded Gabbay "Device boot error - DRAM initialization failed\n"); 563*e65e175bSOded Gabbay err_exists = true; 564*e65e175bSOded Gabbay } 565*e65e175bSOded Gabbay 566*e65e175bSOded Gabbay if (err_val & CPU_BOOT_ERR0_FIT_CORRUPTED) { 567*e65e175bSOded Gabbay dev_err(hdev->dev, "Device boot error - FIT image corrupted\n"); 568*e65e175bSOded Gabbay err_exists = true; 569*e65e175bSOded Gabbay } 570*e65e175bSOded Gabbay 571*e65e175bSOded Gabbay if (err_val & CPU_BOOT_ERR0_TS_INIT_FAIL) { 572*e65e175bSOded Gabbay dev_err(hdev->dev, 573*e65e175bSOded Gabbay "Device boot error - Thermal Sensor initialization failed\n"); 574*e65e175bSOded Gabbay err_exists = true; 575*e65e175bSOded Gabbay } 576*e65e175bSOded Gabbay 577*e65e175bSOded Gabbay if (err_val & CPU_BOOT_ERR0_BMC_WAIT_SKIPPED) { 578*e65e175bSOded Gabbay if (hdev->bmc_enable) { 579*e65e175bSOded Gabbay dev_err(hdev->dev, 580*e65e175bSOded Gabbay "Device boot error - Skipped waiting for BMC\n"); 581*e65e175bSOded Gabbay err_exists = true; 582*e65e175bSOded Gabbay } else { 583*e65e175bSOded Gabbay dev_info(hdev->dev, 584*e65e175bSOded Gabbay "Device boot message - Skipped waiting for BMC\n"); 585*e65e175bSOded Gabbay /* This is an info so we don't want it to disable the 586*e65e175bSOded Gabbay * device 587*e65e175bSOded Gabbay */ 588*e65e175bSOded Gabbay err_val &= ~CPU_BOOT_ERR0_BMC_WAIT_SKIPPED; 589*e65e175bSOded Gabbay } 590*e65e175bSOded Gabbay } 591*e65e175bSOded Gabbay 592*e65e175bSOded Gabbay if (err_val & CPU_BOOT_ERR0_NIC_DATA_NOT_RDY) { 593*e65e175bSOded Gabbay dev_err(hdev->dev, 594*e65e175bSOded Gabbay "Device boot error - Serdes data from BMC not available\n"); 595*e65e175bSOded Gabbay err_exists = true; 596*e65e175bSOded Gabbay } 597*e65e175bSOded Gabbay 598*e65e175bSOded Gabbay if (err_val & CPU_BOOT_ERR0_NIC_FW_FAIL) { 599*e65e175bSOded Gabbay dev_err(hdev->dev, 600*e65e175bSOded Gabbay "Device boot error - NIC F/W initialization failed\n"); 601*e65e175bSOded Gabbay err_exists = true; 602*e65e175bSOded Gabbay } 603*e65e175bSOded Gabbay 604*e65e175bSOded Gabbay if (err_val & CPU_BOOT_ERR0_SECURITY_NOT_RDY) { 605*e65e175bSOded Gabbay dev_err(hdev->dev, 606*e65e175bSOded Gabbay "Device boot warning - security not ready\n"); 607*e65e175bSOded Gabbay err_exists = true; 608*e65e175bSOded Gabbay } 609*e65e175bSOded Gabbay 610*e65e175bSOded Gabbay if (err_val & CPU_BOOT_ERR0_SECURITY_FAIL) { 611*e65e175bSOded Gabbay dev_err(hdev->dev, "Device boot error - security failure\n"); 612*e65e175bSOded Gabbay err_exists = true; 613*e65e175bSOded Gabbay } 614*e65e175bSOded Gabbay 615*e65e175bSOded Gabbay if (err_val & CPU_BOOT_ERR0_EFUSE_FAIL) { 616*e65e175bSOded Gabbay dev_err(hdev->dev, "Device boot error - eFuse failure\n"); 617*e65e175bSOded Gabbay err_exists = true; 618*e65e175bSOded Gabbay } 619*e65e175bSOded Gabbay 620*e65e175bSOded Gabbay if (err_val & CPU_BOOT_ERR0_SEC_IMG_VER_FAIL) { 621*e65e175bSOded Gabbay dev_err(hdev->dev, "Device boot error - Failed to load preboot secondary image\n"); 622*e65e175bSOded Gabbay err_exists = true; 623*e65e175bSOded Gabbay } 624*e65e175bSOded Gabbay 625*e65e175bSOded Gabbay if (err_val & CPU_BOOT_ERR0_PLL_FAIL) { 626*e65e175bSOded Gabbay dev_err(hdev->dev, "Device boot error - PLL failure\n"); 627*e65e175bSOded Gabbay err_exists = true; 628*e65e175bSOded Gabbay } 629*e65e175bSOded Gabbay 630*e65e175bSOded Gabbay if (err_val & CPU_BOOT_ERR0_DEVICE_UNUSABLE_FAIL) { 631*e65e175bSOded Gabbay /* Ignore this bit, don't prevent driver loading */ 632*e65e175bSOded Gabbay dev_dbg(hdev->dev, "device unusable status is set\n"); 633*e65e175bSOded Gabbay err_val &= ~CPU_BOOT_ERR0_DEVICE_UNUSABLE_FAIL; 634*e65e175bSOded Gabbay } 635*e65e175bSOded Gabbay 636*e65e175bSOded Gabbay if (err_val & CPU_BOOT_ERR0_BINNING_FAIL) { 637*e65e175bSOded Gabbay dev_err(hdev->dev, "Device boot error - binning failure\n"); 638*e65e175bSOded Gabbay err_exists = true; 639*e65e175bSOded Gabbay } 640*e65e175bSOded Gabbay 641*e65e175bSOded Gabbay if (sts_val & CPU_BOOT_DEV_STS0_ENABLED) 642*e65e175bSOded Gabbay dev_dbg(hdev->dev, "Device status0 %#x\n", sts_val); 643*e65e175bSOded Gabbay 644*e65e175bSOded Gabbay if (err_val & CPU_BOOT_ERR0_EEPROM_FAIL) { 645*e65e175bSOded Gabbay dev_err(hdev->dev, "Device boot error - EEPROM failure detected\n"); 646*e65e175bSOded Gabbay err_exists = true; 647*e65e175bSOded Gabbay } 648*e65e175bSOded Gabbay 649*e65e175bSOded Gabbay /* All warnings should go here in order not to reach the unknown error validation */ 650*e65e175bSOded Gabbay if (err_val & CPU_BOOT_ERR0_DRAM_SKIPPED) { 651*e65e175bSOded Gabbay dev_warn(hdev->dev, 652*e65e175bSOded Gabbay "Device boot warning - Skipped DRAM initialization\n"); 653*e65e175bSOded Gabbay /* This is a warning so we don't want it to disable the 654*e65e175bSOded Gabbay * device 655*e65e175bSOded Gabbay */ 656*e65e175bSOded Gabbay err_val &= ~CPU_BOOT_ERR0_DRAM_SKIPPED; 657*e65e175bSOded Gabbay } 658*e65e175bSOded Gabbay 659*e65e175bSOded Gabbay if (err_val & CPU_BOOT_ERR0_PRI_IMG_VER_FAIL) { 660*e65e175bSOded Gabbay dev_warn(hdev->dev, 661*e65e175bSOded Gabbay "Device boot warning - Failed to load preboot primary image\n"); 662*e65e175bSOded Gabbay /* This is a warning so we don't want it to disable the 663*e65e175bSOded Gabbay * device as we have a secondary preboot image 664*e65e175bSOded Gabbay */ 665*e65e175bSOded Gabbay err_val &= ~CPU_BOOT_ERR0_PRI_IMG_VER_FAIL; 666*e65e175bSOded Gabbay } 667*e65e175bSOded Gabbay 668*e65e175bSOded Gabbay if (err_val & CPU_BOOT_ERR0_TPM_FAIL) { 669*e65e175bSOded Gabbay dev_warn(hdev->dev, 670*e65e175bSOded Gabbay "Device boot warning - TPM failure\n"); 671*e65e175bSOded Gabbay /* This is a warning so we don't want it to disable the 672*e65e175bSOded Gabbay * device 673*e65e175bSOded Gabbay */ 674*e65e175bSOded Gabbay err_val &= ~CPU_BOOT_ERR0_TPM_FAIL; 675*e65e175bSOded Gabbay } 676*e65e175bSOded Gabbay 677*e65e175bSOded Gabbay if (!err_exists && (err_val & ~CPU_BOOT_ERR0_ENABLED)) { 678*e65e175bSOded Gabbay dev_err(hdev->dev, 679*e65e175bSOded Gabbay "Device boot error - unknown ERR0 error 0x%08x\n", err_val); 680*e65e175bSOded Gabbay err_exists = true; 681*e65e175bSOded Gabbay } 682*e65e175bSOded Gabbay 683*e65e175bSOded Gabbay /* return error only if it's in the predefined mask */ 684*e65e175bSOded Gabbay if (err_exists && ((err_val & ~CPU_BOOT_ERR0_ENABLED) & 685*e65e175bSOded Gabbay lower_32_bits(hdev->boot_error_status_mask))) 686*e65e175bSOded Gabbay return true; 687*e65e175bSOded Gabbay 688*e65e175bSOded Gabbay return false; 689*e65e175bSOded Gabbay } 690*e65e175bSOded Gabbay 691*e65e175bSOded Gabbay /* placeholder for ERR1 as no errors defined there yet */ 692*e65e175bSOded Gabbay static bool fw_report_boot_dev1(struct hl_device *hdev, u32 err_val, 693*e65e175bSOded Gabbay u32 sts_val) 694*e65e175bSOded Gabbay { 695*e65e175bSOded Gabbay /* 696*e65e175bSOded Gabbay * keep this variable to preserve the logic of the function. 697*e65e175bSOded Gabbay * this way it would require less modifications when error will be 698*e65e175bSOded Gabbay * added to DEV_ERR1 699*e65e175bSOded Gabbay */ 700*e65e175bSOded Gabbay bool err_exists = false; 701*e65e175bSOded Gabbay 702*e65e175bSOded Gabbay if (!(err_val & CPU_BOOT_ERR1_ENABLED)) 703*e65e175bSOded Gabbay return false; 704*e65e175bSOded Gabbay 705*e65e175bSOded Gabbay if (sts_val & CPU_BOOT_DEV_STS1_ENABLED) 706*e65e175bSOded Gabbay dev_dbg(hdev->dev, "Device status1 %#x\n", sts_val); 707*e65e175bSOded Gabbay 708*e65e175bSOded Gabbay if (!err_exists && (err_val & ~CPU_BOOT_ERR1_ENABLED)) { 709*e65e175bSOded Gabbay dev_err(hdev->dev, 710*e65e175bSOded Gabbay "Device boot error - unknown ERR1 error 0x%08x\n", 711*e65e175bSOded Gabbay err_val); 712*e65e175bSOded Gabbay err_exists = true; 713*e65e175bSOded Gabbay } 714*e65e175bSOded Gabbay 715*e65e175bSOded Gabbay /* return error only if it's in the predefined mask */ 716*e65e175bSOded Gabbay if (err_exists && ((err_val & ~CPU_BOOT_ERR1_ENABLED) & 717*e65e175bSOded Gabbay upper_32_bits(hdev->boot_error_status_mask))) 718*e65e175bSOded Gabbay return true; 719*e65e175bSOded Gabbay 720*e65e175bSOded Gabbay return false; 721*e65e175bSOded Gabbay } 722*e65e175bSOded Gabbay 723*e65e175bSOded Gabbay static int fw_read_errors(struct hl_device *hdev, u32 boot_err0_reg, 724*e65e175bSOded Gabbay u32 boot_err1_reg, u32 cpu_boot_dev_status0_reg, 725*e65e175bSOded Gabbay u32 cpu_boot_dev_status1_reg) 726*e65e175bSOded Gabbay { 727*e65e175bSOded Gabbay u32 err_val, status_val; 728*e65e175bSOded Gabbay bool err_exists = false; 729*e65e175bSOded Gabbay 730*e65e175bSOded Gabbay /* Some of the firmware status codes are deprecated in newer f/w 731*e65e175bSOded Gabbay * versions. In those versions, the errors are reported 732*e65e175bSOded Gabbay * in different registers. Therefore, we need to check those 733*e65e175bSOded Gabbay * registers and print the exact errors. Moreover, there 734*e65e175bSOded Gabbay * may be multiple errors, so we need to report on each error 735*e65e175bSOded Gabbay * separately. Some of the error codes might indicate a state 736*e65e175bSOded Gabbay * that is not an error per-se, but it is an error in production 737*e65e175bSOded Gabbay * environment 738*e65e175bSOded Gabbay */ 739*e65e175bSOded Gabbay err_val = RREG32(boot_err0_reg); 740*e65e175bSOded Gabbay status_val = RREG32(cpu_boot_dev_status0_reg); 741*e65e175bSOded Gabbay err_exists = fw_report_boot_dev0(hdev, err_val, status_val); 742*e65e175bSOded Gabbay 743*e65e175bSOded Gabbay err_val = RREG32(boot_err1_reg); 744*e65e175bSOded Gabbay status_val = RREG32(cpu_boot_dev_status1_reg); 745*e65e175bSOded Gabbay err_exists |= fw_report_boot_dev1(hdev, err_val, status_val); 746*e65e175bSOded Gabbay 747*e65e175bSOded Gabbay if (err_exists) 748*e65e175bSOded Gabbay return -EIO; 749*e65e175bSOded Gabbay 750*e65e175bSOded Gabbay return 0; 751*e65e175bSOded Gabbay } 752*e65e175bSOded Gabbay 753*e65e175bSOded Gabbay int hl_fw_cpucp_info_get(struct hl_device *hdev, 754*e65e175bSOded Gabbay u32 sts_boot_dev_sts0_reg, 755*e65e175bSOded Gabbay u32 sts_boot_dev_sts1_reg, u32 boot_err0_reg, 756*e65e175bSOded Gabbay u32 boot_err1_reg) 757*e65e175bSOded Gabbay { 758*e65e175bSOded Gabbay struct asic_fixed_properties *prop = &hdev->asic_prop; 759*e65e175bSOded Gabbay struct cpucp_packet pkt = {}; 760*e65e175bSOded Gabbay dma_addr_t cpucp_info_dma_addr; 761*e65e175bSOded Gabbay void *cpucp_info_cpu_addr; 762*e65e175bSOded Gabbay char *kernel_ver; 763*e65e175bSOded Gabbay u64 result; 764*e65e175bSOded Gabbay int rc; 765*e65e175bSOded Gabbay 766*e65e175bSOded Gabbay cpucp_info_cpu_addr = hl_cpu_accessible_dma_pool_alloc(hdev, sizeof(struct cpucp_info), 767*e65e175bSOded Gabbay &cpucp_info_dma_addr); 768*e65e175bSOded Gabbay if (!cpucp_info_cpu_addr) { 769*e65e175bSOded Gabbay dev_err(hdev->dev, 770*e65e175bSOded Gabbay "Failed to allocate DMA memory for CPU-CP info packet\n"); 771*e65e175bSOded Gabbay return -ENOMEM; 772*e65e175bSOded Gabbay } 773*e65e175bSOded Gabbay 774*e65e175bSOded Gabbay memset(cpucp_info_cpu_addr, 0, sizeof(struct cpucp_info)); 775*e65e175bSOded Gabbay 776*e65e175bSOded Gabbay pkt.ctl = cpu_to_le32(CPUCP_PACKET_INFO_GET << 777*e65e175bSOded Gabbay CPUCP_PKT_CTL_OPCODE_SHIFT); 778*e65e175bSOded Gabbay pkt.addr = cpu_to_le64(cpucp_info_dma_addr); 779*e65e175bSOded Gabbay pkt.data_max_size = cpu_to_le32(sizeof(struct cpucp_info)); 780*e65e175bSOded Gabbay 781*e65e175bSOded Gabbay rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt), 782*e65e175bSOded Gabbay HL_CPUCP_INFO_TIMEOUT_USEC, &result); 783*e65e175bSOded Gabbay if (rc) { 784*e65e175bSOded Gabbay dev_err(hdev->dev, 785*e65e175bSOded Gabbay "Failed to handle CPU-CP info pkt, error %d\n", rc); 786*e65e175bSOded Gabbay goto out; 787*e65e175bSOded Gabbay } 788*e65e175bSOded Gabbay 789*e65e175bSOded Gabbay rc = fw_read_errors(hdev, boot_err0_reg, boot_err1_reg, 790*e65e175bSOded Gabbay sts_boot_dev_sts0_reg, sts_boot_dev_sts1_reg); 791*e65e175bSOded Gabbay if (rc) { 792*e65e175bSOded Gabbay dev_err(hdev->dev, "Errors in device boot\n"); 793*e65e175bSOded Gabbay goto out; 794*e65e175bSOded Gabbay } 795*e65e175bSOded Gabbay 796*e65e175bSOded Gabbay memcpy(&prop->cpucp_info, cpucp_info_cpu_addr, 797*e65e175bSOded Gabbay sizeof(prop->cpucp_info)); 798*e65e175bSOded Gabbay 799*e65e175bSOded Gabbay rc = hl_build_hwmon_channel_info(hdev, prop->cpucp_info.sensors); 800*e65e175bSOded Gabbay if (rc) { 801*e65e175bSOded Gabbay dev_err(hdev->dev, 802*e65e175bSOded Gabbay "Failed to build hwmon channel info, error %d\n", rc); 803*e65e175bSOded Gabbay rc = -EFAULT; 804*e65e175bSOded Gabbay goto out; 805*e65e175bSOded Gabbay } 806*e65e175bSOded Gabbay 807*e65e175bSOded Gabbay kernel_ver = extract_fw_ver_from_str(prop->cpucp_info.kernel_version); 808*e65e175bSOded Gabbay if (kernel_ver) { 809*e65e175bSOded Gabbay dev_info(hdev->dev, "Linux version %s", kernel_ver); 810*e65e175bSOded Gabbay kfree(kernel_ver); 811*e65e175bSOded Gabbay } 812*e65e175bSOded Gabbay 813*e65e175bSOded Gabbay /* assume EQ code doesn't need to check eqe index */ 814*e65e175bSOded Gabbay hdev->event_queue.check_eqe_index = false; 815*e65e175bSOded Gabbay 816*e65e175bSOded Gabbay /* Read FW application security bits again */ 817*e65e175bSOded Gabbay if (prop->fw_cpu_boot_dev_sts0_valid) { 818*e65e175bSOded Gabbay prop->fw_app_cpu_boot_dev_sts0 = RREG32(sts_boot_dev_sts0_reg); 819*e65e175bSOded Gabbay if (prop->fw_app_cpu_boot_dev_sts0 & 820*e65e175bSOded Gabbay CPU_BOOT_DEV_STS0_EQ_INDEX_EN) 821*e65e175bSOded Gabbay hdev->event_queue.check_eqe_index = true; 822*e65e175bSOded Gabbay } 823*e65e175bSOded Gabbay 824*e65e175bSOded Gabbay if (prop->fw_cpu_boot_dev_sts1_valid) 825*e65e175bSOded Gabbay prop->fw_app_cpu_boot_dev_sts1 = RREG32(sts_boot_dev_sts1_reg); 826*e65e175bSOded Gabbay 827*e65e175bSOded Gabbay out: 828*e65e175bSOded Gabbay hl_cpu_accessible_dma_pool_free(hdev, sizeof(struct cpucp_info), cpucp_info_cpu_addr); 829*e65e175bSOded Gabbay 830*e65e175bSOded Gabbay return rc; 831*e65e175bSOded Gabbay } 832*e65e175bSOded Gabbay 833*e65e175bSOded Gabbay static int hl_fw_send_msi_info_msg(struct hl_device *hdev) 834*e65e175bSOded Gabbay { 835*e65e175bSOded Gabbay struct cpucp_array_data_packet *pkt; 836*e65e175bSOded Gabbay size_t total_pkt_size, data_size; 837*e65e175bSOded Gabbay u64 result; 838*e65e175bSOded Gabbay int rc; 839*e65e175bSOded Gabbay 840*e65e175bSOded Gabbay /* skip sending this info for unsupported ASICs */ 841*e65e175bSOded Gabbay if (!hdev->asic_funcs->get_msi_info) 842*e65e175bSOded Gabbay return 0; 843*e65e175bSOded Gabbay 844*e65e175bSOded Gabbay data_size = CPUCP_NUM_OF_MSI_TYPES * sizeof(u32); 845*e65e175bSOded Gabbay total_pkt_size = sizeof(struct cpucp_array_data_packet) + data_size; 846*e65e175bSOded Gabbay 847*e65e175bSOded Gabbay /* data should be aligned to 8 bytes in order to CPU-CP to copy it */ 848*e65e175bSOded Gabbay total_pkt_size = (total_pkt_size + 0x7) & ~0x7; 849*e65e175bSOded Gabbay 850*e65e175bSOded Gabbay /* total_pkt_size is casted to u16 later on */ 851*e65e175bSOded Gabbay if (total_pkt_size > USHRT_MAX) { 852*e65e175bSOded Gabbay dev_err(hdev->dev, "CPUCP array data is too big\n"); 853*e65e175bSOded Gabbay return -EINVAL; 854*e65e175bSOded Gabbay } 855*e65e175bSOded Gabbay 856*e65e175bSOded Gabbay pkt = kzalloc(total_pkt_size, GFP_KERNEL); 857*e65e175bSOded Gabbay if (!pkt) 858*e65e175bSOded Gabbay return -ENOMEM; 859*e65e175bSOded Gabbay 860*e65e175bSOded Gabbay pkt->length = cpu_to_le32(CPUCP_NUM_OF_MSI_TYPES); 861*e65e175bSOded Gabbay 862*e65e175bSOded Gabbay memset((void *) &pkt->data, 0xFF, data_size); 863*e65e175bSOded Gabbay hdev->asic_funcs->get_msi_info(pkt->data); 864*e65e175bSOded Gabbay 865*e65e175bSOded Gabbay pkt->cpucp_pkt.ctl = cpu_to_le32(CPUCP_PACKET_MSI_INFO_SET << 866*e65e175bSOded Gabbay CPUCP_PKT_CTL_OPCODE_SHIFT); 867*e65e175bSOded Gabbay 868*e65e175bSOded Gabbay rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *)pkt, 869*e65e175bSOded Gabbay total_pkt_size, 0, &result); 870*e65e175bSOded Gabbay 871*e65e175bSOded Gabbay /* 872*e65e175bSOded Gabbay * in case packet result is invalid it means that FW does not support 873*e65e175bSOded Gabbay * this feature and will use default/hard coded MSI values. no reason 874*e65e175bSOded Gabbay * to stop the boot 875*e65e175bSOded Gabbay */ 876*e65e175bSOded Gabbay if (rc && result == cpucp_packet_invalid) 877*e65e175bSOded Gabbay rc = 0; 878*e65e175bSOded Gabbay 879*e65e175bSOded Gabbay if (rc) 880*e65e175bSOded Gabbay dev_err(hdev->dev, "failed to send CPUCP array data\n"); 881*e65e175bSOded Gabbay 882*e65e175bSOded Gabbay kfree(pkt); 883*e65e175bSOded Gabbay 884*e65e175bSOded Gabbay return rc; 885*e65e175bSOded Gabbay } 886*e65e175bSOded Gabbay 887*e65e175bSOded Gabbay int hl_fw_cpucp_handshake(struct hl_device *hdev, 888*e65e175bSOded Gabbay u32 sts_boot_dev_sts0_reg, 889*e65e175bSOded Gabbay u32 sts_boot_dev_sts1_reg, u32 boot_err0_reg, 890*e65e175bSOded Gabbay u32 boot_err1_reg) 891*e65e175bSOded Gabbay { 892*e65e175bSOded Gabbay int rc; 893*e65e175bSOded Gabbay 894*e65e175bSOded Gabbay rc = hl_fw_cpucp_info_get(hdev, sts_boot_dev_sts0_reg, 895*e65e175bSOded Gabbay sts_boot_dev_sts1_reg, boot_err0_reg, 896*e65e175bSOded Gabbay boot_err1_reg); 897*e65e175bSOded Gabbay if (rc) 898*e65e175bSOded Gabbay return rc; 899*e65e175bSOded Gabbay 900*e65e175bSOded Gabbay return hl_fw_send_msi_info_msg(hdev); 901*e65e175bSOded Gabbay } 902*e65e175bSOded Gabbay 903*e65e175bSOded Gabbay int hl_fw_get_eeprom_data(struct hl_device *hdev, void *data, size_t max_size) 904*e65e175bSOded Gabbay { 905*e65e175bSOded Gabbay struct cpucp_packet pkt = {}; 906*e65e175bSOded Gabbay void *eeprom_info_cpu_addr; 907*e65e175bSOded Gabbay dma_addr_t eeprom_info_dma_addr; 908*e65e175bSOded Gabbay u64 result; 909*e65e175bSOded Gabbay int rc; 910*e65e175bSOded Gabbay 911*e65e175bSOded Gabbay eeprom_info_cpu_addr = hl_cpu_accessible_dma_pool_alloc(hdev, max_size, 912*e65e175bSOded Gabbay &eeprom_info_dma_addr); 913*e65e175bSOded Gabbay if (!eeprom_info_cpu_addr) { 914*e65e175bSOded Gabbay dev_err(hdev->dev, 915*e65e175bSOded Gabbay "Failed to allocate DMA memory for CPU-CP EEPROM packet\n"); 916*e65e175bSOded Gabbay return -ENOMEM; 917*e65e175bSOded Gabbay } 918*e65e175bSOded Gabbay 919*e65e175bSOded Gabbay memset(eeprom_info_cpu_addr, 0, max_size); 920*e65e175bSOded Gabbay 921*e65e175bSOded Gabbay pkt.ctl = cpu_to_le32(CPUCP_PACKET_EEPROM_DATA_GET << 922*e65e175bSOded Gabbay CPUCP_PKT_CTL_OPCODE_SHIFT); 923*e65e175bSOded Gabbay pkt.addr = cpu_to_le64(eeprom_info_dma_addr); 924*e65e175bSOded Gabbay pkt.data_max_size = cpu_to_le32(max_size); 925*e65e175bSOded Gabbay 926*e65e175bSOded Gabbay rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt), 927*e65e175bSOded Gabbay HL_CPUCP_EEPROM_TIMEOUT_USEC, &result); 928*e65e175bSOded Gabbay 929*e65e175bSOded Gabbay if (rc) { 930*e65e175bSOded Gabbay dev_err(hdev->dev, 931*e65e175bSOded Gabbay "Failed to handle CPU-CP EEPROM packet, error %d\n", 932*e65e175bSOded Gabbay rc); 933*e65e175bSOded Gabbay goto out; 934*e65e175bSOded Gabbay } 935*e65e175bSOded Gabbay 936*e65e175bSOded Gabbay /* result contains the actual size */ 937*e65e175bSOded Gabbay memcpy(data, eeprom_info_cpu_addr, min((size_t)result, max_size)); 938*e65e175bSOded Gabbay 939*e65e175bSOded Gabbay out: 940*e65e175bSOded Gabbay hl_cpu_accessible_dma_pool_free(hdev, max_size, eeprom_info_cpu_addr); 941*e65e175bSOded Gabbay 942*e65e175bSOded Gabbay return rc; 943*e65e175bSOded Gabbay } 944*e65e175bSOded Gabbay 945*e65e175bSOded Gabbay int hl_fw_get_monitor_dump(struct hl_device *hdev, void *data) 946*e65e175bSOded Gabbay { 947*e65e175bSOded Gabbay struct cpucp_monitor_dump *mon_dump_cpu_addr; 948*e65e175bSOded Gabbay dma_addr_t mon_dump_dma_addr; 949*e65e175bSOded Gabbay struct cpucp_packet pkt = {}; 950*e65e175bSOded Gabbay size_t data_size; 951*e65e175bSOded Gabbay __le32 *src_ptr; 952*e65e175bSOded Gabbay u32 *dst_ptr; 953*e65e175bSOded Gabbay u64 result; 954*e65e175bSOded Gabbay int i, rc; 955*e65e175bSOded Gabbay 956*e65e175bSOded Gabbay data_size = sizeof(struct cpucp_monitor_dump); 957*e65e175bSOded Gabbay mon_dump_cpu_addr = hl_cpu_accessible_dma_pool_alloc(hdev, data_size, &mon_dump_dma_addr); 958*e65e175bSOded Gabbay if (!mon_dump_cpu_addr) { 959*e65e175bSOded Gabbay dev_err(hdev->dev, 960*e65e175bSOded Gabbay "Failed to allocate DMA memory for CPU-CP monitor-dump packet\n"); 961*e65e175bSOded Gabbay return -ENOMEM; 962*e65e175bSOded Gabbay } 963*e65e175bSOded Gabbay 964*e65e175bSOded Gabbay memset(mon_dump_cpu_addr, 0, data_size); 965*e65e175bSOded Gabbay 966*e65e175bSOded Gabbay pkt.ctl = cpu_to_le32(CPUCP_PACKET_MONITOR_DUMP_GET << CPUCP_PKT_CTL_OPCODE_SHIFT); 967*e65e175bSOded Gabbay pkt.addr = cpu_to_le64(mon_dump_dma_addr); 968*e65e175bSOded Gabbay pkt.data_max_size = cpu_to_le32(data_size); 969*e65e175bSOded Gabbay 970*e65e175bSOded Gabbay rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt), 971*e65e175bSOded Gabbay HL_CPUCP_MON_DUMP_TIMEOUT_USEC, &result); 972*e65e175bSOded Gabbay if (rc) { 973*e65e175bSOded Gabbay dev_err(hdev->dev, "Failed to handle CPU-CP monitor-dump packet, error %d\n", rc); 974*e65e175bSOded Gabbay goto out; 975*e65e175bSOded Gabbay } 976*e65e175bSOded Gabbay 977*e65e175bSOded Gabbay /* result contains the actual size */ 978*e65e175bSOded Gabbay src_ptr = (__le32 *) mon_dump_cpu_addr; 979*e65e175bSOded Gabbay dst_ptr = data; 980*e65e175bSOded Gabbay for (i = 0; i < (data_size / sizeof(u32)); i++) { 981*e65e175bSOded Gabbay *dst_ptr = le32_to_cpu(*src_ptr); 982*e65e175bSOded Gabbay src_ptr++; 983*e65e175bSOded Gabbay dst_ptr++; 984*e65e175bSOded Gabbay } 985*e65e175bSOded Gabbay 986*e65e175bSOded Gabbay out: 987*e65e175bSOded Gabbay hl_cpu_accessible_dma_pool_free(hdev, data_size, mon_dump_cpu_addr); 988*e65e175bSOded Gabbay 989*e65e175bSOded Gabbay return rc; 990*e65e175bSOded Gabbay } 991*e65e175bSOded Gabbay 992*e65e175bSOded Gabbay int hl_fw_cpucp_pci_counters_get(struct hl_device *hdev, 993*e65e175bSOded Gabbay struct hl_info_pci_counters *counters) 994*e65e175bSOded Gabbay { 995*e65e175bSOded Gabbay struct cpucp_packet pkt = {}; 996*e65e175bSOded Gabbay u64 result; 997*e65e175bSOded Gabbay int rc; 998*e65e175bSOded Gabbay 999*e65e175bSOded Gabbay pkt.ctl = cpu_to_le32(CPUCP_PACKET_PCIE_THROUGHPUT_GET << 1000*e65e175bSOded Gabbay CPUCP_PKT_CTL_OPCODE_SHIFT); 1001*e65e175bSOded Gabbay 1002*e65e175bSOded Gabbay /* Fetch PCI rx counter */ 1003*e65e175bSOded Gabbay pkt.index = cpu_to_le32(cpucp_pcie_throughput_rx); 1004*e65e175bSOded Gabbay rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt), 1005*e65e175bSOded Gabbay HL_CPUCP_INFO_TIMEOUT_USEC, &result); 1006*e65e175bSOded Gabbay if (rc) { 1007*e65e175bSOded Gabbay dev_err(hdev->dev, 1008*e65e175bSOded Gabbay "Failed to handle CPU-CP PCI info pkt, error %d\n", rc); 1009*e65e175bSOded Gabbay return rc; 1010*e65e175bSOded Gabbay } 1011*e65e175bSOded Gabbay counters->rx_throughput = result; 1012*e65e175bSOded Gabbay 1013*e65e175bSOded Gabbay memset(&pkt, 0, sizeof(pkt)); 1014*e65e175bSOded Gabbay pkt.ctl = cpu_to_le32(CPUCP_PACKET_PCIE_THROUGHPUT_GET << 1015*e65e175bSOded Gabbay CPUCP_PKT_CTL_OPCODE_SHIFT); 1016*e65e175bSOded Gabbay 1017*e65e175bSOded Gabbay /* Fetch PCI tx counter */ 1018*e65e175bSOded Gabbay pkt.index = cpu_to_le32(cpucp_pcie_throughput_tx); 1019*e65e175bSOded Gabbay rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt), 1020*e65e175bSOded Gabbay HL_CPUCP_INFO_TIMEOUT_USEC, &result); 1021*e65e175bSOded Gabbay if (rc) { 1022*e65e175bSOded Gabbay dev_err(hdev->dev, 1023*e65e175bSOded Gabbay "Failed to handle CPU-CP PCI info pkt, error %d\n", rc); 1024*e65e175bSOded Gabbay return rc; 1025*e65e175bSOded Gabbay } 1026*e65e175bSOded Gabbay counters->tx_throughput = result; 1027*e65e175bSOded Gabbay 1028*e65e175bSOded Gabbay /* Fetch PCI replay counter */ 1029*e65e175bSOded Gabbay memset(&pkt, 0, sizeof(pkt)); 1030*e65e175bSOded Gabbay pkt.ctl = cpu_to_le32(CPUCP_PACKET_PCIE_REPLAY_CNT_GET << 1031*e65e175bSOded Gabbay CPUCP_PKT_CTL_OPCODE_SHIFT); 1032*e65e175bSOded Gabbay 1033*e65e175bSOded Gabbay rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt), 1034*e65e175bSOded Gabbay HL_CPUCP_INFO_TIMEOUT_USEC, &result); 1035*e65e175bSOded Gabbay if (rc) { 1036*e65e175bSOded Gabbay dev_err(hdev->dev, 1037*e65e175bSOded Gabbay "Failed to handle CPU-CP PCI info pkt, error %d\n", rc); 1038*e65e175bSOded Gabbay return rc; 1039*e65e175bSOded Gabbay } 1040*e65e175bSOded Gabbay counters->replay_cnt = (u32) result; 1041*e65e175bSOded Gabbay 1042*e65e175bSOded Gabbay return rc; 1043*e65e175bSOded Gabbay } 1044*e65e175bSOded Gabbay 1045*e65e175bSOded Gabbay int hl_fw_cpucp_total_energy_get(struct hl_device *hdev, u64 *total_energy) 1046*e65e175bSOded Gabbay { 1047*e65e175bSOded Gabbay struct cpucp_packet pkt = {}; 1048*e65e175bSOded Gabbay u64 result; 1049*e65e175bSOded Gabbay int rc; 1050*e65e175bSOded Gabbay 1051*e65e175bSOded Gabbay pkt.ctl = cpu_to_le32(CPUCP_PACKET_TOTAL_ENERGY_GET << 1052*e65e175bSOded Gabbay CPUCP_PKT_CTL_OPCODE_SHIFT); 1053*e65e175bSOded Gabbay 1054*e65e175bSOded Gabbay rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt), 1055*e65e175bSOded Gabbay HL_CPUCP_INFO_TIMEOUT_USEC, &result); 1056*e65e175bSOded Gabbay if (rc) { 1057*e65e175bSOded Gabbay dev_err(hdev->dev, 1058*e65e175bSOded Gabbay "Failed to handle CpuCP total energy pkt, error %d\n", 1059*e65e175bSOded Gabbay rc); 1060*e65e175bSOded Gabbay return rc; 1061*e65e175bSOded Gabbay } 1062*e65e175bSOded Gabbay 1063*e65e175bSOded Gabbay *total_energy = result; 1064*e65e175bSOded Gabbay 1065*e65e175bSOded Gabbay return rc; 1066*e65e175bSOded Gabbay } 1067*e65e175bSOded Gabbay 1068*e65e175bSOded Gabbay int get_used_pll_index(struct hl_device *hdev, u32 input_pll_index, 1069*e65e175bSOded Gabbay enum pll_index *pll_index) 1070*e65e175bSOded Gabbay { 1071*e65e175bSOded Gabbay struct asic_fixed_properties *prop = &hdev->asic_prop; 1072*e65e175bSOded Gabbay u8 pll_byte, pll_bit_off; 1073*e65e175bSOded Gabbay bool dynamic_pll; 1074*e65e175bSOded Gabbay int fw_pll_idx; 1075*e65e175bSOded Gabbay 1076*e65e175bSOded Gabbay dynamic_pll = !!(prop->fw_app_cpu_boot_dev_sts0 & 1077*e65e175bSOded Gabbay CPU_BOOT_DEV_STS0_DYN_PLL_EN); 1078*e65e175bSOded Gabbay 1079*e65e175bSOded Gabbay if (!dynamic_pll) { 1080*e65e175bSOded Gabbay /* 1081*e65e175bSOded Gabbay * in case we are working with legacy FW (each asic has unique 1082*e65e175bSOded Gabbay * PLL numbering) use the driver based index as they are 1083*e65e175bSOded Gabbay * aligned with fw legacy numbering 1084*e65e175bSOded Gabbay */ 1085*e65e175bSOded Gabbay *pll_index = input_pll_index; 1086*e65e175bSOded Gabbay return 0; 1087*e65e175bSOded Gabbay } 1088*e65e175bSOded Gabbay 1089*e65e175bSOded Gabbay /* retrieve a FW compatible PLL index based on 1090*e65e175bSOded Gabbay * ASIC specific user request 1091*e65e175bSOded Gabbay */ 1092*e65e175bSOded Gabbay fw_pll_idx = hdev->asic_funcs->map_pll_idx_to_fw_idx(input_pll_index); 1093*e65e175bSOded Gabbay if (fw_pll_idx < 0) { 1094*e65e175bSOded Gabbay dev_err(hdev->dev, "Invalid PLL index (%u) error %d\n", 1095*e65e175bSOded Gabbay input_pll_index, fw_pll_idx); 1096*e65e175bSOded Gabbay return -EINVAL; 1097*e65e175bSOded Gabbay } 1098*e65e175bSOded Gabbay 1099*e65e175bSOded Gabbay /* PLL map is a u8 array */ 1100*e65e175bSOded Gabbay pll_byte = prop->cpucp_info.pll_map[fw_pll_idx >> 3]; 1101*e65e175bSOded Gabbay pll_bit_off = fw_pll_idx & 0x7; 1102*e65e175bSOded Gabbay 1103*e65e175bSOded Gabbay if (!(pll_byte & BIT(pll_bit_off))) { 1104*e65e175bSOded Gabbay dev_err(hdev->dev, "PLL index %d is not supported\n", 1105*e65e175bSOded Gabbay fw_pll_idx); 1106*e65e175bSOded Gabbay return -EINVAL; 1107*e65e175bSOded Gabbay } 1108*e65e175bSOded Gabbay 1109*e65e175bSOded Gabbay *pll_index = fw_pll_idx; 1110*e65e175bSOded Gabbay 1111*e65e175bSOded Gabbay return 0; 1112*e65e175bSOded Gabbay } 1113*e65e175bSOded Gabbay 1114*e65e175bSOded Gabbay int hl_fw_cpucp_pll_info_get(struct hl_device *hdev, u32 pll_index, 1115*e65e175bSOded Gabbay u16 *pll_freq_arr) 1116*e65e175bSOded Gabbay { 1117*e65e175bSOded Gabbay struct cpucp_packet pkt; 1118*e65e175bSOded Gabbay enum pll_index used_pll_idx; 1119*e65e175bSOded Gabbay u64 result; 1120*e65e175bSOded Gabbay int rc; 1121*e65e175bSOded Gabbay 1122*e65e175bSOded Gabbay rc = get_used_pll_index(hdev, pll_index, &used_pll_idx); 1123*e65e175bSOded Gabbay if (rc) 1124*e65e175bSOded Gabbay return rc; 1125*e65e175bSOded Gabbay 1126*e65e175bSOded Gabbay memset(&pkt, 0, sizeof(pkt)); 1127*e65e175bSOded Gabbay 1128*e65e175bSOded Gabbay pkt.ctl = cpu_to_le32(CPUCP_PACKET_PLL_INFO_GET << 1129*e65e175bSOded Gabbay CPUCP_PKT_CTL_OPCODE_SHIFT); 1130*e65e175bSOded Gabbay pkt.pll_type = __cpu_to_le16((u16)used_pll_idx); 1131*e65e175bSOded Gabbay 1132*e65e175bSOded Gabbay rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt), 1133*e65e175bSOded Gabbay HL_CPUCP_INFO_TIMEOUT_USEC, &result); 1134*e65e175bSOded Gabbay if (rc) { 1135*e65e175bSOded Gabbay dev_err(hdev->dev, "Failed to read PLL info, error %d\n", rc); 1136*e65e175bSOded Gabbay return rc; 1137*e65e175bSOded Gabbay } 1138*e65e175bSOded Gabbay 1139*e65e175bSOded Gabbay pll_freq_arr[0] = FIELD_GET(CPUCP_PKT_RES_PLL_OUT0_MASK, result); 1140*e65e175bSOded Gabbay pll_freq_arr[1] = FIELD_GET(CPUCP_PKT_RES_PLL_OUT1_MASK, result); 1141*e65e175bSOded Gabbay pll_freq_arr[2] = FIELD_GET(CPUCP_PKT_RES_PLL_OUT2_MASK, result); 1142*e65e175bSOded Gabbay pll_freq_arr[3] = FIELD_GET(CPUCP_PKT_RES_PLL_OUT3_MASK, result); 1143*e65e175bSOded Gabbay 1144*e65e175bSOded Gabbay return 0; 1145*e65e175bSOded Gabbay } 1146*e65e175bSOded Gabbay 1147*e65e175bSOded Gabbay int hl_fw_cpucp_power_get(struct hl_device *hdev, u64 *power) 1148*e65e175bSOded Gabbay { 1149*e65e175bSOded Gabbay struct cpucp_packet pkt; 1150*e65e175bSOded Gabbay u64 result; 1151*e65e175bSOded Gabbay int rc; 1152*e65e175bSOded Gabbay 1153*e65e175bSOded Gabbay memset(&pkt, 0, sizeof(pkt)); 1154*e65e175bSOded Gabbay 1155*e65e175bSOded Gabbay pkt.ctl = cpu_to_le32(CPUCP_PACKET_POWER_GET << 1156*e65e175bSOded Gabbay CPUCP_PKT_CTL_OPCODE_SHIFT); 1157*e65e175bSOded Gabbay pkt.type = cpu_to_le16(CPUCP_POWER_INPUT); 1158*e65e175bSOded Gabbay 1159*e65e175bSOded Gabbay rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt), 1160*e65e175bSOded Gabbay HL_CPUCP_INFO_TIMEOUT_USEC, &result); 1161*e65e175bSOded Gabbay if (rc) { 1162*e65e175bSOded Gabbay dev_err(hdev->dev, "Failed to read power, error %d\n", rc); 1163*e65e175bSOded Gabbay return rc; 1164*e65e175bSOded Gabbay } 1165*e65e175bSOded Gabbay 1166*e65e175bSOded Gabbay *power = result; 1167*e65e175bSOded Gabbay 1168*e65e175bSOded Gabbay return rc; 1169*e65e175bSOded Gabbay } 1170*e65e175bSOded Gabbay 1171*e65e175bSOded Gabbay int hl_fw_dram_replaced_row_get(struct hl_device *hdev, 1172*e65e175bSOded Gabbay struct cpucp_hbm_row_info *info) 1173*e65e175bSOded Gabbay { 1174*e65e175bSOded Gabbay struct cpucp_hbm_row_info *cpucp_repl_rows_info_cpu_addr; 1175*e65e175bSOded Gabbay dma_addr_t cpucp_repl_rows_info_dma_addr; 1176*e65e175bSOded Gabbay struct cpucp_packet pkt = {}; 1177*e65e175bSOded Gabbay u64 result; 1178*e65e175bSOded Gabbay int rc; 1179*e65e175bSOded Gabbay 1180*e65e175bSOded Gabbay cpucp_repl_rows_info_cpu_addr = hl_cpu_accessible_dma_pool_alloc(hdev, 1181*e65e175bSOded Gabbay sizeof(struct cpucp_hbm_row_info), 1182*e65e175bSOded Gabbay &cpucp_repl_rows_info_dma_addr); 1183*e65e175bSOded Gabbay if (!cpucp_repl_rows_info_cpu_addr) { 1184*e65e175bSOded Gabbay dev_err(hdev->dev, 1185*e65e175bSOded Gabbay "Failed to allocate DMA memory for CPU-CP replaced rows info packet\n"); 1186*e65e175bSOded Gabbay return -ENOMEM; 1187*e65e175bSOded Gabbay } 1188*e65e175bSOded Gabbay 1189*e65e175bSOded Gabbay memset(cpucp_repl_rows_info_cpu_addr, 0, sizeof(struct cpucp_hbm_row_info)); 1190*e65e175bSOded Gabbay 1191*e65e175bSOded Gabbay pkt.ctl = cpu_to_le32(CPUCP_PACKET_HBM_REPLACED_ROWS_INFO_GET << 1192*e65e175bSOded Gabbay CPUCP_PKT_CTL_OPCODE_SHIFT); 1193*e65e175bSOded Gabbay pkt.addr = cpu_to_le64(cpucp_repl_rows_info_dma_addr); 1194*e65e175bSOded Gabbay pkt.data_max_size = cpu_to_le32(sizeof(struct cpucp_hbm_row_info)); 1195*e65e175bSOded Gabbay 1196*e65e175bSOded Gabbay rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt), 1197*e65e175bSOded Gabbay HL_CPUCP_INFO_TIMEOUT_USEC, &result); 1198*e65e175bSOded Gabbay if (rc) { 1199*e65e175bSOded Gabbay dev_err(hdev->dev, 1200*e65e175bSOded Gabbay "Failed to handle CPU-CP replaced rows info pkt, error %d\n", rc); 1201*e65e175bSOded Gabbay goto out; 1202*e65e175bSOded Gabbay } 1203*e65e175bSOded Gabbay 1204*e65e175bSOded Gabbay memcpy(info, cpucp_repl_rows_info_cpu_addr, sizeof(*info)); 1205*e65e175bSOded Gabbay 1206*e65e175bSOded Gabbay out: 1207*e65e175bSOded Gabbay hl_cpu_accessible_dma_pool_free(hdev, sizeof(struct cpucp_hbm_row_info), 1208*e65e175bSOded Gabbay cpucp_repl_rows_info_cpu_addr); 1209*e65e175bSOded Gabbay 1210*e65e175bSOded Gabbay return rc; 1211*e65e175bSOded Gabbay } 1212*e65e175bSOded Gabbay 1213*e65e175bSOded Gabbay int hl_fw_dram_pending_row_get(struct hl_device *hdev, u32 *pend_rows_num) 1214*e65e175bSOded Gabbay { 1215*e65e175bSOded Gabbay struct cpucp_packet pkt; 1216*e65e175bSOded Gabbay u64 result; 1217*e65e175bSOded Gabbay int rc; 1218*e65e175bSOded Gabbay 1219*e65e175bSOded Gabbay memset(&pkt, 0, sizeof(pkt)); 1220*e65e175bSOded Gabbay 1221*e65e175bSOded Gabbay pkt.ctl = cpu_to_le32(CPUCP_PACKET_HBM_PENDING_ROWS_STATUS << CPUCP_PKT_CTL_OPCODE_SHIFT); 1222*e65e175bSOded Gabbay 1223*e65e175bSOded Gabbay rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt), 0, &result); 1224*e65e175bSOded Gabbay if (rc) { 1225*e65e175bSOded Gabbay dev_err(hdev->dev, 1226*e65e175bSOded Gabbay "Failed to handle CPU-CP pending rows info pkt, error %d\n", rc); 1227*e65e175bSOded Gabbay goto out; 1228*e65e175bSOded Gabbay } 1229*e65e175bSOded Gabbay 1230*e65e175bSOded Gabbay *pend_rows_num = (u32) result; 1231*e65e175bSOded Gabbay out: 1232*e65e175bSOded Gabbay return rc; 1233*e65e175bSOded Gabbay } 1234*e65e175bSOded Gabbay 1235*e65e175bSOded Gabbay int hl_fw_cpucp_engine_core_asid_set(struct hl_device *hdev, u32 asid) 1236*e65e175bSOded Gabbay { 1237*e65e175bSOded Gabbay struct cpucp_packet pkt; 1238*e65e175bSOded Gabbay int rc; 1239*e65e175bSOded Gabbay 1240*e65e175bSOded Gabbay memset(&pkt, 0, sizeof(pkt)); 1241*e65e175bSOded Gabbay 1242*e65e175bSOded Gabbay pkt.ctl = cpu_to_le32(CPUCP_PACKET_ENGINE_CORE_ASID_SET << CPUCP_PKT_CTL_OPCODE_SHIFT); 1243*e65e175bSOded Gabbay pkt.value = cpu_to_le64(asid); 1244*e65e175bSOded Gabbay 1245*e65e175bSOded Gabbay rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt), 1246*e65e175bSOded Gabbay HL_CPUCP_INFO_TIMEOUT_USEC, NULL); 1247*e65e175bSOded Gabbay if (rc) 1248*e65e175bSOded Gabbay dev_err(hdev->dev, 1249*e65e175bSOded Gabbay "Failed on ASID configuration request for engine core, error %d\n", 1250*e65e175bSOded Gabbay rc); 1251*e65e175bSOded Gabbay 1252*e65e175bSOded Gabbay return rc; 1253*e65e175bSOded Gabbay } 1254*e65e175bSOded Gabbay 1255*e65e175bSOded Gabbay void hl_fw_ask_hard_reset_without_linux(struct hl_device *hdev) 1256*e65e175bSOded Gabbay { 1257*e65e175bSOded Gabbay struct static_fw_load_mgr *static_loader = 1258*e65e175bSOded Gabbay &hdev->fw_loader.static_loader; 1259*e65e175bSOded Gabbay int rc; 1260*e65e175bSOded Gabbay 1261*e65e175bSOded Gabbay if (hdev->asic_prop.dynamic_fw_load) { 1262*e65e175bSOded Gabbay rc = hl_fw_dynamic_send_protocol_cmd(hdev, &hdev->fw_loader, 1263*e65e175bSOded Gabbay COMMS_RST_DEV, 0, false, 1264*e65e175bSOded Gabbay hdev->fw_loader.cpu_timeout); 1265*e65e175bSOded Gabbay if (rc) 1266*e65e175bSOded Gabbay dev_warn(hdev->dev, "Failed sending COMMS_RST_DEV\n"); 1267*e65e175bSOded Gabbay } else { 1268*e65e175bSOded Gabbay WREG32(static_loader->kmd_msg_to_cpu_reg, KMD_MSG_RST_DEV); 1269*e65e175bSOded Gabbay } 1270*e65e175bSOded Gabbay } 1271*e65e175bSOded Gabbay 1272*e65e175bSOded Gabbay void hl_fw_ask_halt_machine_without_linux(struct hl_device *hdev) 1273*e65e175bSOded Gabbay { 1274*e65e175bSOded Gabbay struct static_fw_load_mgr *static_loader = 1275*e65e175bSOded Gabbay &hdev->fw_loader.static_loader; 1276*e65e175bSOded Gabbay int rc; 1277*e65e175bSOded Gabbay 1278*e65e175bSOded Gabbay if (hdev->device_cpu_is_halted) 1279*e65e175bSOded Gabbay return; 1280*e65e175bSOded Gabbay 1281*e65e175bSOded Gabbay /* Stop device CPU to make sure nothing bad happens */ 1282*e65e175bSOded Gabbay if (hdev->asic_prop.dynamic_fw_load) { 1283*e65e175bSOded Gabbay rc = hl_fw_dynamic_send_protocol_cmd(hdev, &hdev->fw_loader, 1284*e65e175bSOded Gabbay COMMS_GOTO_WFE, 0, true, 1285*e65e175bSOded Gabbay hdev->fw_loader.cpu_timeout); 1286*e65e175bSOded Gabbay if (rc) 1287*e65e175bSOded Gabbay dev_warn(hdev->dev, "Failed sending COMMS_GOTO_WFE\n"); 1288*e65e175bSOded Gabbay } else { 1289*e65e175bSOded Gabbay WREG32(static_loader->kmd_msg_to_cpu_reg, KMD_MSG_GOTO_WFE); 1290*e65e175bSOded Gabbay msleep(static_loader->cpu_reset_wait_msec); 1291*e65e175bSOded Gabbay 1292*e65e175bSOded Gabbay /* Must clear this register in order to prevent preboot 1293*e65e175bSOded Gabbay * from reading WFE after reboot 1294*e65e175bSOded Gabbay */ 1295*e65e175bSOded Gabbay WREG32(static_loader->kmd_msg_to_cpu_reg, KMD_MSG_NA); 1296*e65e175bSOded Gabbay } 1297*e65e175bSOded Gabbay 1298*e65e175bSOded Gabbay hdev->device_cpu_is_halted = true; 1299*e65e175bSOded Gabbay } 1300*e65e175bSOded Gabbay 1301*e65e175bSOded Gabbay static void detect_cpu_boot_status(struct hl_device *hdev, u32 status) 1302*e65e175bSOded Gabbay { 1303*e65e175bSOded Gabbay /* Some of the status codes below are deprecated in newer f/w 1304*e65e175bSOded Gabbay * versions but we keep them here for backward compatibility 1305*e65e175bSOded Gabbay */ 1306*e65e175bSOded Gabbay switch (status) { 1307*e65e175bSOded Gabbay case CPU_BOOT_STATUS_NA: 1308*e65e175bSOded Gabbay dev_err(hdev->dev, 1309*e65e175bSOded Gabbay "Device boot progress - BTL/ROM did NOT run\n"); 1310*e65e175bSOded Gabbay break; 1311*e65e175bSOded Gabbay case CPU_BOOT_STATUS_IN_WFE: 1312*e65e175bSOded Gabbay dev_err(hdev->dev, 1313*e65e175bSOded Gabbay "Device boot progress - Stuck inside WFE loop\n"); 1314*e65e175bSOded Gabbay break; 1315*e65e175bSOded Gabbay case CPU_BOOT_STATUS_IN_BTL: 1316*e65e175bSOded Gabbay dev_err(hdev->dev, 1317*e65e175bSOded Gabbay "Device boot progress - Stuck in BTL\n"); 1318*e65e175bSOded Gabbay break; 1319*e65e175bSOded Gabbay case CPU_BOOT_STATUS_IN_PREBOOT: 1320*e65e175bSOded Gabbay dev_err(hdev->dev, 1321*e65e175bSOded Gabbay "Device boot progress - Stuck in Preboot\n"); 1322*e65e175bSOded Gabbay break; 1323*e65e175bSOded Gabbay case CPU_BOOT_STATUS_IN_SPL: 1324*e65e175bSOded Gabbay dev_err(hdev->dev, 1325*e65e175bSOded Gabbay "Device boot progress - Stuck in SPL\n"); 1326*e65e175bSOded Gabbay break; 1327*e65e175bSOded Gabbay case CPU_BOOT_STATUS_IN_UBOOT: 1328*e65e175bSOded Gabbay dev_err(hdev->dev, 1329*e65e175bSOded Gabbay "Device boot progress - Stuck in u-boot\n"); 1330*e65e175bSOded Gabbay break; 1331*e65e175bSOded Gabbay case CPU_BOOT_STATUS_DRAM_INIT_FAIL: 1332*e65e175bSOded Gabbay dev_err(hdev->dev, 1333*e65e175bSOded Gabbay "Device boot progress - DRAM initialization failed\n"); 1334*e65e175bSOded Gabbay break; 1335*e65e175bSOded Gabbay case CPU_BOOT_STATUS_UBOOT_NOT_READY: 1336*e65e175bSOded Gabbay dev_err(hdev->dev, 1337*e65e175bSOded Gabbay "Device boot progress - Cannot boot\n"); 1338*e65e175bSOded Gabbay break; 1339*e65e175bSOded Gabbay case CPU_BOOT_STATUS_TS_INIT_FAIL: 1340*e65e175bSOded Gabbay dev_err(hdev->dev, 1341*e65e175bSOded Gabbay "Device boot progress - Thermal Sensor initialization failed\n"); 1342*e65e175bSOded Gabbay break; 1343*e65e175bSOded Gabbay case CPU_BOOT_STATUS_SECURITY_READY: 1344*e65e175bSOded Gabbay dev_err(hdev->dev, 1345*e65e175bSOded Gabbay "Device boot progress - Stuck in preboot after security initialization\n"); 1346*e65e175bSOded Gabbay break; 1347*e65e175bSOded Gabbay default: 1348*e65e175bSOded Gabbay dev_err(hdev->dev, 1349*e65e175bSOded Gabbay "Device boot progress - Invalid status code %d\n", 1350*e65e175bSOded Gabbay status); 1351*e65e175bSOded Gabbay break; 1352*e65e175bSOded Gabbay } 1353*e65e175bSOded Gabbay } 1354*e65e175bSOded Gabbay 1355*e65e175bSOded Gabbay int hl_fw_wait_preboot_ready(struct hl_device *hdev) 1356*e65e175bSOded Gabbay { 1357*e65e175bSOded Gabbay struct pre_fw_load_props *pre_fw_load = &hdev->fw_loader.pre_fw_load; 1358*e65e175bSOded Gabbay u32 status; 1359*e65e175bSOded Gabbay int rc; 1360*e65e175bSOded Gabbay 1361*e65e175bSOded Gabbay /* Need to check two possible scenarios: 1362*e65e175bSOded Gabbay * 1363*e65e175bSOded Gabbay * CPU_BOOT_STATUS_WAITING_FOR_BOOT_FIT - for newer firmwares where 1364*e65e175bSOded Gabbay * the preboot is waiting for the boot fit 1365*e65e175bSOded Gabbay * 1366*e65e175bSOded Gabbay * All other status values - for older firmwares where the uboot was 1367*e65e175bSOded Gabbay * loaded from the FLASH 1368*e65e175bSOded Gabbay */ 1369*e65e175bSOded Gabbay rc = hl_poll_timeout( 1370*e65e175bSOded Gabbay hdev, 1371*e65e175bSOded Gabbay pre_fw_load->cpu_boot_status_reg, 1372*e65e175bSOded Gabbay status, 1373*e65e175bSOded Gabbay (status == CPU_BOOT_STATUS_NIC_FW_RDY) || 1374*e65e175bSOded Gabbay (status == CPU_BOOT_STATUS_READY_TO_BOOT) || 1375*e65e175bSOded Gabbay (status == CPU_BOOT_STATUS_WAITING_FOR_BOOT_FIT), 1376*e65e175bSOded Gabbay hdev->fw_poll_interval_usec, 1377*e65e175bSOded Gabbay pre_fw_load->wait_for_preboot_timeout); 1378*e65e175bSOded Gabbay 1379*e65e175bSOded Gabbay if (rc) { 1380*e65e175bSOded Gabbay dev_err(hdev->dev, "CPU boot ready status timeout\n"); 1381*e65e175bSOded Gabbay detect_cpu_boot_status(hdev, status); 1382*e65e175bSOded Gabbay 1383*e65e175bSOded Gabbay /* If we read all FF, then something is totally wrong, no point 1384*e65e175bSOded Gabbay * of reading specific errors 1385*e65e175bSOded Gabbay */ 1386*e65e175bSOded Gabbay if (status != -1) 1387*e65e175bSOded Gabbay fw_read_errors(hdev, pre_fw_load->boot_err0_reg, 1388*e65e175bSOded Gabbay pre_fw_load->boot_err1_reg, 1389*e65e175bSOded Gabbay pre_fw_load->sts_boot_dev_sts0_reg, 1390*e65e175bSOded Gabbay pre_fw_load->sts_boot_dev_sts1_reg); 1391*e65e175bSOded Gabbay return -EIO; 1392*e65e175bSOded Gabbay } 1393*e65e175bSOded Gabbay 1394*e65e175bSOded Gabbay hdev->fw_loader.fw_comp_loaded |= FW_TYPE_PREBOOT_CPU; 1395*e65e175bSOded Gabbay 1396*e65e175bSOded Gabbay return 0; 1397*e65e175bSOded Gabbay } 1398*e65e175bSOded Gabbay 1399*e65e175bSOded Gabbay static int hl_fw_read_preboot_caps(struct hl_device *hdev) 1400*e65e175bSOded Gabbay { 1401*e65e175bSOded Gabbay struct pre_fw_load_props *pre_fw_load; 1402*e65e175bSOded Gabbay struct asic_fixed_properties *prop; 1403*e65e175bSOded Gabbay u32 reg_val; 1404*e65e175bSOded Gabbay int rc; 1405*e65e175bSOded Gabbay 1406*e65e175bSOded Gabbay prop = &hdev->asic_prop; 1407*e65e175bSOded Gabbay pre_fw_load = &hdev->fw_loader.pre_fw_load; 1408*e65e175bSOded Gabbay 1409*e65e175bSOded Gabbay rc = hl_fw_wait_preboot_ready(hdev); 1410*e65e175bSOded Gabbay if (rc) 1411*e65e175bSOded Gabbay return rc; 1412*e65e175bSOded Gabbay 1413*e65e175bSOded Gabbay /* 1414*e65e175bSOded Gabbay * the registers DEV_STS* contain FW capabilities/features. 1415*e65e175bSOded Gabbay * We can rely on this registers only if bit CPU_BOOT_DEV_STS*_ENABLED 1416*e65e175bSOded Gabbay * is set. 1417*e65e175bSOded Gabbay * In the first read of this register we store the value of this 1418*e65e175bSOded Gabbay * register ONLY if the register is enabled (which will be propagated 1419*e65e175bSOded Gabbay * to next stages) and also mark the register as valid. 1420*e65e175bSOded Gabbay * In case it is not enabled the stored value will be left 0- all 1421*e65e175bSOded Gabbay * caps/features are off 1422*e65e175bSOded Gabbay */ 1423*e65e175bSOded Gabbay reg_val = RREG32(pre_fw_load->sts_boot_dev_sts0_reg); 1424*e65e175bSOded Gabbay if (reg_val & CPU_BOOT_DEV_STS0_ENABLED) { 1425*e65e175bSOded Gabbay prop->fw_cpu_boot_dev_sts0_valid = true; 1426*e65e175bSOded Gabbay prop->fw_preboot_cpu_boot_dev_sts0 = reg_val; 1427*e65e175bSOded Gabbay } 1428*e65e175bSOded Gabbay 1429*e65e175bSOded Gabbay reg_val = RREG32(pre_fw_load->sts_boot_dev_sts1_reg); 1430*e65e175bSOded Gabbay if (reg_val & CPU_BOOT_DEV_STS1_ENABLED) { 1431*e65e175bSOded Gabbay prop->fw_cpu_boot_dev_sts1_valid = true; 1432*e65e175bSOded Gabbay prop->fw_preboot_cpu_boot_dev_sts1 = reg_val; 1433*e65e175bSOded Gabbay } 1434*e65e175bSOded Gabbay 1435*e65e175bSOded Gabbay prop->dynamic_fw_load = !!(prop->fw_preboot_cpu_boot_dev_sts0 & 1436*e65e175bSOded Gabbay CPU_BOOT_DEV_STS0_FW_LD_COM_EN); 1437*e65e175bSOded Gabbay 1438*e65e175bSOded Gabbay /* initialize FW loader once we know what load protocol is used */ 1439*e65e175bSOded Gabbay hdev->asic_funcs->init_firmware_loader(hdev); 1440*e65e175bSOded Gabbay 1441*e65e175bSOded Gabbay dev_dbg(hdev->dev, "Attempting %s FW load\n", 1442*e65e175bSOded Gabbay prop->dynamic_fw_load ? "dynamic" : "legacy"); 1443*e65e175bSOded Gabbay return 0; 1444*e65e175bSOded Gabbay } 1445*e65e175bSOded Gabbay 1446*e65e175bSOded Gabbay static int hl_fw_static_read_device_fw_version(struct hl_device *hdev, 1447*e65e175bSOded Gabbay enum hl_fw_component fwc) 1448*e65e175bSOded Gabbay { 1449*e65e175bSOded Gabbay struct asic_fixed_properties *prop = &hdev->asic_prop; 1450*e65e175bSOded Gabbay struct fw_load_mgr *fw_loader = &hdev->fw_loader; 1451*e65e175bSOded Gabbay struct static_fw_load_mgr *static_loader; 1452*e65e175bSOded Gabbay char *dest, *boot_ver, *preboot_ver; 1453*e65e175bSOded Gabbay u32 ver_off, limit; 1454*e65e175bSOded Gabbay const char *name; 1455*e65e175bSOded Gabbay char btl_ver[32]; 1456*e65e175bSOded Gabbay 1457*e65e175bSOded Gabbay static_loader = &hdev->fw_loader.static_loader; 1458*e65e175bSOded Gabbay 1459*e65e175bSOded Gabbay switch (fwc) { 1460*e65e175bSOded Gabbay case FW_COMP_BOOT_FIT: 1461*e65e175bSOded Gabbay ver_off = RREG32(static_loader->boot_fit_version_offset_reg); 1462*e65e175bSOded Gabbay dest = prop->uboot_ver; 1463*e65e175bSOded Gabbay name = "Boot-fit"; 1464*e65e175bSOded Gabbay limit = static_loader->boot_fit_version_max_off; 1465*e65e175bSOded Gabbay break; 1466*e65e175bSOded Gabbay case FW_COMP_PREBOOT: 1467*e65e175bSOded Gabbay ver_off = RREG32(static_loader->preboot_version_offset_reg); 1468*e65e175bSOded Gabbay dest = prop->preboot_ver; 1469*e65e175bSOded Gabbay name = "Preboot"; 1470*e65e175bSOded Gabbay limit = static_loader->preboot_version_max_off; 1471*e65e175bSOded Gabbay break; 1472*e65e175bSOded Gabbay default: 1473*e65e175bSOded Gabbay dev_warn(hdev->dev, "Undefined FW component: %d\n", fwc); 1474*e65e175bSOded Gabbay return -EIO; 1475*e65e175bSOded Gabbay } 1476*e65e175bSOded Gabbay 1477*e65e175bSOded Gabbay ver_off &= static_loader->sram_offset_mask; 1478*e65e175bSOded Gabbay 1479*e65e175bSOded Gabbay if (ver_off < limit) { 1480*e65e175bSOded Gabbay memcpy_fromio(dest, 1481*e65e175bSOded Gabbay hdev->pcie_bar[fw_loader->sram_bar_id] + ver_off, 1482*e65e175bSOded Gabbay VERSION_MAX_LEN); 1483*e65e175bSOded Gabbay } else { 1484*e65e175bSOded Gabbay dev_err(hdev->dev, "%s version offset (0x%x) is above SRAM\n", 1485*e65e175bSOded Gabbay name, ver_off); 1486*e65e175bSOded Gabbay strscpy(dest, "unavailable", VERSION_MAX_LEN); 1487*e65e175bSOded Gabbay return -EIO; 1488*e65e175bSOded Gabbay } 1489*e65e175bSOded Gabbay 1490*e65e175bSOded Gabbay if (fwc == FW_COMP_BOOT_FIT) { 1491*e65e175bSOded Gabbay boot_ver = extract_fw_ver_from_str(prop->uboot_ver); 1492*e65e175bSOded Gabbay if (boot_ver) { 1493*e65e175bSOded Gabbay dev_info(hdev->dev, "boot-fit version %s\n", boot_ver); 1494*e65e175bSOded Gabbay kfree(boot_ver); 1495*e65e175bSOded Gabbay } 1496*e65e175bSOded Gabbay } else if (fwc == FW_COMP_PREBOOT) { 1497*e65e175bSOded Gabbay preboot_ver = strnstr(prop->preboot_ver, "Preboot", 1498*e65e175bSOded Gabbay VERSION_MAX_LEN); 1499*e65e175bSOded Gabbay if (preboot_ver && preboot_ver != prop->preboot_ver) { 1500*e65e175bSOded Gabbay strscpy(btl_ver, prop->preboot_ver, 1501*e65e175bSOded Gabbay min((int) (preboot_ver - prop->preboot_ver), 1502*e65e175bSOded Gabbay 31)); 1503*e65e175bSOded Gabbay dev_info(hdev->dev, "%s\n", btl_ver); 1504*e65e175bSOded Gabbay } 1505*e65e175bSOded Gabbay 1506*e65e175bSOded Gabbay preboot_ver = extract_fw_ver_from_str(prop->preboot_ver); 1507*e65e175bSOded Gabbay if (preboot_ver) { 1508*e65e175bSOded Gabbay dev_info(hdev->dev, "preboot version %s\n", 1509*e65e175bSOded Gabbay preboot_ver); 1510*e65e175bSOded Gabbay kfree(preboot_ver); 1511*e65e175bSOded Gabbay } 1512*e65e175bSOded Gabbay } 1513*e65e175bSOded Gabbay 1514*e65e175bSOded Gabbay return 0; 1515*e65e175bSOded Gabbay } 1516*e65e175bSOded Gabbay 1517*e65e175bSOded Gabbay /** 1518*e65e175bSOded Gabbay * hl_fw_preboot_update_state - update internal data structures during 1519*e65e175bSOded Gabbay * handshake with preboot 1520*e65e175bSOded Gabbay * 1521*e65e175bSOded Gabbay * 1522*e65e175bSOded Gabbay * @hdev: pointer to the habanalabs device structure 1523*e65e175bSOded Gabbay * 1524*e65e175bSOded Gabbay * @return 0 on success, otherwise non-zero error code 1525*e65e175bSOded Gabbay */ 1526*e65e175bSOded Gabbay static void hl_fw_preboot_update_state(struct hl_device *hdev) 1527*e65e175bSOded Gabbay { 1528*e65e175bSOded Gabbay struct asic_fixed_properties *prop = &hdev->asic_prop; 1529*e65e175bSOded Gabbay u32 cpu_boot_dev_sts0, cpu_boot_dev_sts1; 1530*e65e175bSOded Gabbay 1531*e65e175bSOded Gabbay cpu_boot_dev_sts0 = prop->fw_preboot_cpu_boot_dev_sts0; 1532*e65e175bSOded Gabbay cpu_boot_dev_sts1 = prop->fw_preboot_cpu_boot_dev_sts1; 1533*e65e175bSOded Gabbay 1534*e65e175bSOded Gabbay /* We read boot_dev_sts registers multiple times during boot: 1535*e65e175bSOded Gabbay * 1. preboot - a. Check whether the security status bits are valid 1536*e65e175bSOded Gabbay * b. Check whether fw security is enabled 1537*e65e175bSOded Gabbay * c. Check whether hard reset is done by preboot 1538*e65e175bSOded Gabbay * 2. boot cpu - a. Fetch boot cpu security status 1539*e65e175bSOded Gabbay * b. Check whether hard reset is done by boot cpu 1540*e65e175bSOded Gabbay * 3. FW application - a. Fetch fw application security status 1541*e65e175bSOded Gabbay * b. Check whether hard reset is done by fw app 1542*e65e175bSOded Gabbay */ 1543*e65e175bSOded Gabbay prop->hard_reset_done_by_fw = !!(cpu_boot_dev_sts0 & CPU_BOOT_DEV_STS0_FW_HARD_RST_EN); 1544*e65e175bSOded Gabbay 1545*e65e175bSOded Gabbay prop->fw_security_enabled = !!(cpu_boot_dev_sts0 & CPU_BOOT_DEV_STS0_SECURITY_EN); 1546*e65e175bSOded Gabbay 1547*e65e175bSOded Gabbay dev_dbg(hdev->dev, "Firmware preboot boot device status0 %#x\n", 1548*e65e175bSOded Gabbay cpu_boot_dev_sts0); 1549*e65e175bSOded Gabbay 1550*e65e175bSOded Gabbay dev_dbg(hdev->dev, "Firmware preboot boot device status1 %#x\n", 1551*e65e175bSOded Gabbay cpu_boot_dev_sts1); 1552*e65e175bSOded Gabbay 1553*e65e175bSOded Gabbay dev_dbg(hdev->dev, "Firmware preboot hard-reset is %s\n", 1554*e65e175bSOded Gabbay prop->hard_reset_done_by_fw ? "enabled" : "disabled"); 1555*e65e175bSOded Gabbay 1556*e65e175bSOded Gabbay dev_dbg(hdev->dev, "firmware-level security is %s\n", 1557*e65e175bSOded Gabbay prop->fw_security_enabled ? "enabled" : "disabled"); 1558*e65e175bSOded Gabbay 1559*e65e175bSOded Gabbay dev_dbg(hdev->dev, "GIC controller is %s\n", 1560*e65e175bSOded Gabbay prop->gic_interrupts_enable ? "enabled" : "disabled"); 1561*e65e175bSOded Gabbay } 1562*e65e175bSOded Gabbay 1563*e65e175bSOded Gabbay static int hl_fw_static_read_preboot_status(struct hl_device *hdev) 1564*e65e175bSOded Gabbay { 1565*e65e175bSOded Gabbay int rc; 1566*e65e175bSOded Gabbay 1567*e65e175bSOded Gabbay rc = hl_fw_static_read_device_fw_version(hdev, FW_COMP_PREBOOT); 1568*e65e175bSOded Gabbay if (rc) 1569*e65e175bSOded Gabbay return rc; 1570*e65e175bSOded Gabbay 1571*e65e175bSOded Gabbay return 0; 1572*e65e175bSOded Gabbay } 1573*e65e175bSOded Gabbay 1574*e65e175bSOded Gabbay int hl_fw_read_preboot_status(struct hl_device *hdev) 1575*e65e175bSOded Gabbay { 1576*e65e175bSOded Gabbay int rc; 1577*e65e175bSOded Gabbay 1578*e65e175bSOded Gabbay if (!(hdev->fw_components & FW_TYPE_PREBOOT_CPU)) 1579*e65e175bSOded Gabbay return 0; 1580*e65e175bSOded Gabbay 1581*e65e175bSOded Gabbay /* get FW pre-load parameters */ 1582*e65e175bSOded Gabbay hdev->asic_funcs->init_firmware_preload_params(hdev); 1583*e65e175bSOded Gabbay 1584*e65e175bSOded Gabbay /* 1585*e65e175bSOded Gabbay * In order to determine boot method (static VS dynamic) we need to 1586*e65e175bSOded Gabbay * read the boot caps register 1587*e65e175bSOded Gabbay */ 1588*e65e175bSOded Gabbay rc = hl_fw_read_preboot_caps(hdev); 1589*e65e175bSOded Gabbay if (rc) 1590*e65e175bSOded Gabbay return rc; 1591*e65e175bSOded Gabbay 1592*e65e175bSOded Gabbay hl_fw_preboot_update_state(hdev); 1593*e65e175bSOded Gabbay 1594*e65e175bSOded Gabbay /* no need to read preboot status in dynamic load */ 1595*e65e175bSOded Gabbay if (hdev->asic_prop.dynamic_fw_load) 1596*e65e175bSOded Gabbay return 0; 1597*e65e175bSOded Gabbay 1598*e65e175bSOded Gabbay return hl_fw_static_read_preboot_status(hdev); 1599*e65e175bSOded Gabbay } 1600*e65e175bSOded Gabbay 1601*e65e175bSOded Gabbay /* associate string with COMM status */ 1602*e65e175bSOded Gabbay static char *hl_dynamic_fw_status_str[COMMS_STS_INVLD_LAST] = { 1603*e65e175bSOded Gabbay [COMMS_STS_NOOP] = "NOOP", 1604*e65e175bSOded Gabbay [COMMS_STS_ACK] = "ACK", 1605*e65e175bSOded Gabbay [COMMS_STS_OK] = "OK", 1606*e65e175bSOded Gabbay [COMMS_STS_ERR] = "ERR", 1607*e65e175bSOded Gabbay [COMMS_STS_VALID_ERR] = "VALID_ERR", 1608*e65e175bSOded Gabbay [COMMS_STS_TIMEOUT_ERR] = "TIMEOUT_ERR", 1609*e65e175bSOded Gabbay }; 1610*e65e175bSOded Gabbay 1611*e65e175bSOded Gabbay /** 1612*e65e175bSOded Gabbay * hl_fw_dynamic_report_error_status - report error status 1613*e65e175bSOded Gabbay * 1614*e65e175bSOded Gabbay * @hdev: pointer to the habanalabs device structure 1615*e65e175bSOded Gabbay * @status: value of FW status register 1616*e65e175bSOded Gabbay * @expected_status: the expected status 1617*e65e175bSOded Gabbay */ 1618*e65e175bSOded Gabbay static void hl_fw_dynamic_report_error_status(struct hl_device *hdev, 1619*e65e175bSOded Gabbay u32 status, 1620*e65e175bSOded Gabbay enum comms_sts expected_status) 1621*e65e175bSOded Gabbay { 1622*e65e175bSOded Gabbay enum comms_sts comm_status = 1623*e65e175bSOded Gabbay FIELD_GET(COMMS_STATUS_STATUS_MASK, status); 1624*e65e175bSOded Gabbay 1625*e65e175bSOded Gabbay if (comm_status < COMMS_STS_INVLD_LAST) 1626*e65e175bSOded Gabbay dev_err(hdev->dev, "Device status %s, expected status: %s\n", 1627*e65e175bSOded Gabbay hl_dynamic_fw_status_str[comm_status], 1628*e65e175bSOded Gabbay hl_dynamic_fw_status_str[expected_status]); 1629*e65e175bSOded Gabbay else 1630*e65e175bSOded Gabbay dev_err(hdev->dev, "Device status unknown %d, expected status: %s\n", 1631*e65e175bSOded Gabbay comm_status, 1632*e65e175bSOded Gabbay hl_dynamic_fw_status_str[expected_status]); 1633*e65e175bSOded Gabbay } 1634*e65e175bSOded Gabbay 1635*e65e175bSOded Gabbay /** 1636*e65e175bSOded Gabbay * hl_fw_dynamic_send_cmd - send LKD to FW cmd 1637*e65e175bSOded Gabbay * 1638*e65e175bSOded Gabbay * @hdev: pointer to the habanalabs device structure 1639*e65e175bSOded Gabbay * @fw_loader: managing structure for loading device's FW 1640*e65e175bSOded Gabbay * @cmd: LKD to FW cmd code 1641*e65e175bSOded Gabbay * @size: size of next FW component to be loaded (0 if not necessary) 1642*e65e175bSOded Gabbay * 1643*e65e175bSOded Gabbay * LDK to FW exact command layout is defined at struct comms_command. 1644*e65e175bSOded Gabbay * note: the size argument is used only when the next FW component should be 1645*e65e175bSOded Gabbay * loaded, otherwise it shall be 0. the size is used by the FW in later 1646*e65e175bSOded Gabbay * protocol stages and when sending only indicating the amount of memory 1647*e65e175bSOded Gabbay * to be allocated by the FW to receive the next boot component. 1648*e65e175bSOded Gabbay */ 1649*e65e175bSOded Gabbay static void hl_fw_dynamic_send_cmd(struct hl_device *hdev, 1650*e65e175bSOded Gabbay struct fw_load_mgr *fw_loader, 1651*e65e175bSOded Gabbay enum comms_cmd cmd, unsigned int size) 1652*e65e175bSOded Gabbay { 1653*e65e175bSOded Gabbay struct cpu_dyn_regs *dyn_regs; 1654*e65e175bSOded Gabbay u32 val; 1655*e65e175bSOded Gabbay 1656*e65e175bSOded Gabbay dyn_regs = &fw_loader->dynamic_loader.comm_desc.cpu_dyn_regs; 1657*e65e175bSOded Gabbay 1658*e65e175bSOded Gabbay val = FIELD_PREP(COMMS_COMMAND_CMD_MASK, cmd); 1659*e65e175bSOded Gabbay val |= FIELD_PREP(COMMS_COMMAND_SIZE_MASK, size); 1660*e65e175bSOded Gabbay 1661*e65e175bSOded Gabbay trace_habanalabs_comms_send_cmd(hdev->dev, comms_cmd_str_arr[cmd]); 1662*e65e175bSOded Gabbay WREG32(le32_to_cpu(dyn_regs->kmd_msg_to_cpu), val); 1663*e65e175bSOded Gabbay } 1664*e65e175bSOded Gabbay 1665*e65e175bSOded Gabbay /** 1666*e65e175bSOded Gabbay * hl_fw_dynamic_extract_fw_response - update the FW response 1667*e65e175bSOded Gabbay * 1668*e65e175bSOded Gabbay * @hdev: pointer to the habanalabs device structure 1669*e65e175bSOded Gabbay * @fw_loader: managing structure for loading device's FW 1670*e65e175bSOded Gabbay * @response: FW response 1671*e65e175bSOded Gabbay * @status: the status read from CPU status register 1672*e65e175bSOded Gabbay * 1673*e65e175bSOded Gabbay * @return 0 on success, otherwise non-zero error code 1674*e65e175bSOded Gabbay */ 1675*e65e175bSOded Gabbay static int hl_fw_dynamic_extract_fw_response(struct hl_device *hdev, 1676*e65e175bSOded Gabbay struct fw_load_mgr *fw_loader, 1677*e65e175bSOded Gabbay struct fw_response *response, 1678*e65e175bSOded Gabbay u32 status) 1679*e65e175bSOded Gabbay { 1680*e65e175bSOded Gabbay response->status = FIELD_GET(COMMS_STATUS_STATUS_MASK, status); 1681*e65e175bSOded Gabbay response->ram_offset = FIELD_GET(COMMS_STATUS_OFFSET_MASK, status) << 1682*e65e175bSOded Gabbay COMMS_STATUS_OFFSET_ALIGN_SHIFT; 1683*e65e175bSOded Gabbay response->ram_type = FIELD_GET(COMMS_STATUS_RAM_TYPE_MASK, status); 1684*e65e175bSOded Gabbay 1685*e65e175bSOded Gabbay if ((response->ram_type != COMMS_SRAM) && 1686*e65e175bSOded Gabbay (response->ram_type != COMMS_DRAM)) { 1687*e65e175bSOded Gabbay dev_err(hdev->dev, "FW status: invalid RAM type %u\n", 1688*e65e175bSOded Gabbay response->ram_type); 1689*e65e175bSOded Gabbay return -EIO; 1690*e65e175bSOded Gabbay } 1691*e65e175bSOded Gabbay 1692*e65e175bSOded Gabbay return 0; 1693*e65e175bSOded Gabbay } 1694*e65e175bSOded Gabbay 1695*e65e175bSOded Gabbay /** 1696*e65e175bSOded Gabbay * hl_fw_dynamic_wait_for_status - wait for status in dynamic FW load 1697*e65e175bSOded Gabbay * 1698*e65e175bSOded Gabbay * @hdev: pointer to the habanalabs device structure 1699*e65e175bSOded Gabbay * @fw_loader: managing structure for loading device's FW 1700*e65e175bSOded Gabbay * @expected_status: expected status to wait for 1701*e65e175bSOded Gabbay * @timeout: timeout for status wait 1702*e65e175bSOded Gabbay * 1703*e65e175bSOded Gabbay * @return 0 on success, otherwise non-zero error code 1704*e65e175bSOded Gabbay * 1705*e65e175bSOded Gabbay * waiting for status from FW include polling the FW status register until 1706*e65e175bSOded Gabbay * expected status is received or timeout occurs (whatever occurs first). 1707*e65e175bSOded Gabbay */ 1708*e65e175bSOded Gabbay static int hl_fw_dynamic_wait_for_status(struct hl_device *hdev, 1709*e65e175bSOded Gabbay struct fw_load_mgr *fw_loader, 1710*e65e175bSOded Gabbay enum comms_sts expected_status, 1711*e65e175bSOded Gabbay u32 timeout) 1712*e65e175bSOded Gabbay { 1713*e65e175bSOded Gabbay struct cpu_dyn_regs *dyn_regs; 1714*e65e175bSOded Gabbay u32 status; 1715*e65e175bSOded Gabbay int rc; 1716*e65e175bSOded Gabbay 1717*e65e175bSOded Gabbay dyn_regs = &fw_loader->dynamic_loader.comm_desc.cpu_dyn_regs; 1718*e65e175bSOded Gabbay 1719*e65e175bSOded Gabbay trace_habanalabs_comms_wait_status(hdev->dev, comms_sts_str_arr[expected_status]); 1720*e65e175bSOded Gabbay 1721*e65e175bSOded Gabbay /* Wait for expected status */ 1722*e65e175bSOded Gabbay rc = hl_poll_timeout( 1723*e65e175bSOded Gabbay hdev, 1724*e65e175bSOded Gabbay le32_to_cpu(dyn_regs->cpu_cmd_status_to_host), 1725*e65e175bSOded Gabbay status, 1726*e65e175bSOded Gabbay FIELD_GET(COMMS_STATUS_STATUS_MASK, status) == expected_status, 1727*e65e175bSOded Gabbay hdev->fw_comms_poll_interval_usec, 1728*e65e175bSOded Gabbay timeout); 1729*e65e175bSOded Gabbay 1730*e65e175bSOded Gabbay if (rc) { 1731*e65e175bSOded Gabbay hl_fw_dynamic_report_error_status(hdev, status, 1732*e65e175bSOded Gabbay expected_status); 1733*e65e175bSOded Gabbay return -EIO; 1734*e65e175bSOded Gabbay } 1735*e65e175bSOded Gabbay 1736*e65e175bSOded Gabbay trace_habanalabs_comms_wait_status_done(hdev->dev, comms_sts_str_arr[expected_status]); 1737*e65e175bSOded Gabbay 1738*e65e175bSOded Gabbay /* 1739*e65e175bSOded Gabbay * skip storing FW response for NOOP to preserve the actual desired 1740*e65e175bSOded Gabbay * FW status 1741*e65e175bSOded Gabbay */ 1742*e65e175bSOded Gabbay if (expected_status == COMMS_STS_NOOP) 1743*e65e175bSOded Gabbay return 0; 1744*e65e175bSOded Gabbay 1745*e65e175bSOded Gabbay rc = hl_fw_dynamic_extract_fw_response(hdev, fw_loader, 1746*e65e175bSOded Gabbay &fw_loader->dynamic_loader.response, 1747*e65e175bSOded Gabbay status); 1748*e65e175bSOded Gabbay return rc; 1749*e65e175bSOded Gabbay } 1750*e65e175bSOded Gabbay 1751*e65e175bSOded Gabbay /** 1752*e65e175bSOded Gabbay * hl_fw_dynamic_send_clear_cmd - send clear command to FW 1753*e65e175bSOded Gabbay * 1754*e65e175bSOded Gabbay * @hdev: pointer to the habanalabs device structure 1755*e65e175bSOded Gabbay * @fw_loader: managing structure for loading device's FW 1756*e65e175bSOded Gabbay * 1757*e65e175bSOded Gabbay * @return 0 on success, otherwise non-zero error code 1758*e65e175bSOded Gabbay * 1759*e65e175bSOded Gabbay * after command cycle between LKD to FW CPU (i.e. LKD got an expected status 1760*e65e175bSOded Gabbay * from FW) we need to clear the CPU status register in order to avoid garbage 1761*e65e175bSOded Gabbay * between command cycles. 1762*e65e175bSOded Gabbay * This is done by sending clear command and polling the CPU to LKD status 1763*e65e175bSOded Gabbay * register to hold the status NOOP 1764*e65e175bSOded Gabbay */ 1765*e65e175bSOded Gabbay static int hl_fw_dynamic_send_clear_cmd(struct hl_device *hdev, 1766*e65e175bSOded Gabbay struct fw_load_mgr *fw_loader) 1767*e65e175bSOded Gabbay { 1768*e65e175bSOded Gabbay hl_fw_dynamic_send_cmd(hdev, fw_loader, COMMS_CLR_STS, 0); 1769*e65e175bSOded Gabbay 1770*e65e175bSOded Gabbay return hl_fw_dynamic_wait_for_status(hdev, fw_loader, COMMS_STS_NOOP, 1771*e65e175bSOded Gabbay fw_loader->cpu_timeout); 1772*e65e175bSOded Gabbay } 1773*e65e175bSOded Gabbay 1774*e65e175bSOded Gabbay /** 1775*e65e175bSOded Gabbay * hl_fw_dynamic_send_protocol_cmd - send LKD to FW cmd and wait for ACK 1776*e65e175bSOded Gabbay * 1777*e65e175bSOded Gabbay * @hdev: pointer to the habanalabs device structure 1778*e65e175bSOded Gabbay * @fw_loader: managing structure for loading device's FW 1779*e65e175bSOded Gabbay * @cmd: LKD to FW cmd code 1780*e65e175bSOded Gabbay * @size: size of next FW component to be loaded (0 if not necessary) 1781*e65e175bSOded Gabbay * @wait_ok: if true also wait for OK response from FW 1782*e65e175bSOded Gabbay * @timeout: timeout for status wait 1783*e65e175bSOded Gabbay * 1784*e65e175bSOded Gabbay * @return 0 on success, otherwise non-zero error code 1785*e65e175bSOded Gabbay * 1786*e65e175bSOded Gabbay * brief: 1787*e65e175bSOded Gabbay * when sending protocol command we have the following steps: 1788*e65e175bSOded Gabbay * - send clear (clear command and verify clear status register) 1789*e65e175bSOded Gabbay * - send the actual protocol command 1790*e65e175bSOded Gabbay * - wait for ACK on the protocol command 1791*e65e175bSOded Gabbay * - send clear 1792*e65e175bSOded Gabbay * - send NOOP 1793*e65e175bSOded Gabbay * if, in addition, the specific protocol command should wait for OK then: 1794*e65e175bSOded Gabbay * - wait for OK 1795*e65e175bSOded Gabbay * - send clear 1796*e65e175bSOded Gabbay * - send NOOP 1797*e65e175bSOded Gabbay * 1798*e65e175bSOded Gabbay * NOTES: 1799*e65e175bSOded Gabbay * send clear: this is necessary in order to clear the status register to avoid 1800*e65e175bSOded Gabbay * leftovers between command 1801*e65e175bSOded Gabbay * NOOP command: necessary to avoid loop on the clear command by the FW 1802*e65e175bSOded Gabbay */ 1803*e65e175bSOded Gabbay int hl_fw_dynamic_send_protocol_cmd(struct hl_device *hdev, 1804*e65e175bSOded Gabbay struct fw_load_mgr *fw_loader, 1805*e65e175bSOded Gabbay enum comms_cmd cmd, unsigned int size, 1806*e65e175bSOded Gabbay bool wait_ok, u32 timeout) 1807*e65e175bSOded Gabbay { 1808*e65e175bSOded Gabbay int rc; 1809*e65e175bSOded Gabbay 1810*e65e175bSOded Gabbay trace_habanalabs_comms_protocol_cmd(hdev->dev, comms_cmd_str_arr[cmd]); 1811*e65e175bSOded Gabbay 1812*e65e175bSOded Gabbay /* first send clear command to clean former commands */ 1813*e65e175bSOded Gabbay rc = hl_fw_dynamic_send_clear_cmd(hdev, fw_loader); 1814*e65e175bSOded Gabbay if (rc) 1815*e65e175bSOded Gabbay return rc; 1816*e65e175bSOded Gabbay 1817*e65e175bSOded Gabbay /* send the actual command */ 1818*e65e175bSOded Gabbay hl_fw_dynamic_send_cmd(hdev, fw_loader, cmd, size); 1819*e65e175bSOded Gabbay 1820*e65e175bSOded Gabbay /* wait for ACK for the command */ 1821*e65e175bSOded Gabbay rc = hl_fw_dynamic_wait_for_status(hdev, fw_loader, COMMS_STS_ACK, 1822*e65e175bSOded Gabbay timeout); 1823*e65e175bSOded Gabbay if (rc) 1824*e65e175bSOded Gabbay return rc; 1825*e65e175bSOded Gabbay 1826*e65e175bSOded Gabbay /* clear command to prepare for NOOP command */ 1827*e65e175bSOded Gabbay rc = hl_fw_dynamic_send_clear_cmd(hdev, fw_loader); 1828*e65e175bSOded Gabbay if (rc) 1829*e65e175bSOded Gabbay return rc; 1830*e65e175bSOded Gabbay 1831*e65e175bSOded Gabbay /* send the actual NOOP command */ 1832*e65e175bSOded Gabbay hl_fw_dynamic_send_cmd(hdev, fw_loader, COMMS_NOOP, 0); 1833*e65e175bSOded Gabbay 1834*e65e175bSOded Gabbay if (!wait_ok) 1835*e65e175bSOded Gabbay return 0; 1836*e65e175bSOded Gabbay 1837*e65e175bSOded Gabbay rc = hl_fw_dynamic_wait_for_status(hdev, fw_loader, COMMS_STS_OK, 1838*e65e175bSOded Gabbay timeout); 1839*e65e175bSOded Gabbay if (rc) 1840*e65e175bSOded Gabbay return rc; 1841*e65e175bSOded Gabbay 1842*e65e175bSOded Gabbay /* clear command to prepare for NOOP command */ 1843*e65e175bSOded Gabbay rc = hl_fw_dynamic_send_clear_cmd(hdev, fw_loader); 1844*e65e175bSOded Gabbay if (rc) 1845*e65e175bSOded Gabbay return rc; 1846*e65e175bSOded Gabbay 1847*e65e175bSOded Gabbay /* send the actual NOOP command */ 1848*e65e175bSOded Gabbay hl_fw_dynamic_send_cmd(hdev, fw_loader, COMMS_NOOP, 0); 1849*e65e175bSOded Gabbay 1850*e65e175bSOded Gabbay return 0; 1851*e65e175bSOded Gabbay } 1852*e65e175bSOded Gabbay 1853*e65e175bSOded Gabbay /** 1854*e65e175bSOded Gabbay * hl_fw_compat_crc32 - CRC compatible with FW 1855*e65e175bSOded Gabbay * 1856*e65e175bSOded Gabbay * @data: pointer to the data 1857*e65e175bSOded Gabbay * @size: size of the data 1858*e65e175bSOded Gabbay * 1859*e65e175bSOded Gabbay * @return the CRC32 result 1860*e65e175bSOded Gabbay * 1861*e65e175bSOded Gabbay * NOTE: kernel's CRC32 differs from standard CRC32 calculation. 1862*e65e175bSOded Gabbay * in order to be aligned we need to flip the bits of both the input 1863*e65e175bSOded Gabbay * initial CRC and kernel's CRC32 result. 1864*e65e175bSOded Gabbay * in addition both sides use initial CRC of 0, 1865*e65e175bSOded Gabbay */ 1866*e65e175bSOded Gabbay static u32 hl_fw_compat_crc32(u8 *data, size_t size) 1867*e65e175bSOded Gabbay { 1868*e65e175bSOded Gabbay return ~crc32_le(~((u32)0), data, size); 1869*e65e175bSOded Gabbay } 1870*e65e175bSOded Gabbay 1871*e65e175bSOded Gabbay /** 1872*e65e175bSOded Gabbay * hl_fw_dynamic_validate_memory_bound - validate memory bounds for memory 1873*e65e175bSOded Gabbay * transfer (image or descriptor) between 1874*e65e175bSOded Gabbay * host and FW 1875*e65e175bSOded Gabbay * 1876*e65e175bSOded Gabbay * @hdev: pointer to the habanalabs device structure 1877*e65e175bSOded Gabbay * @addr: device address of memory transfer 1878*e65e175bSOded Gabbay * @size: memory transfer size 1879*e65e175bSOded Gabbay * @region: PCI memory region 1880*e65e175bSOded Gabbay * 1881*e65e175bSOded Gabbay * @return 0 on success, otherwise non-zero error code 1882*e65e175bSOded Gabbay */ 1883*e65e175bSOded Gabbay static int hl_fw_dynamic_validate_memory_bound(struct hl_device *hdev, 1884*e65e175bSOded Gabbay u64 addr, size_t size, 1885*e65e175bSOded Gabbay struct pci_mem_region *region) 1886*e65e175bSOded Gabbay { 1887*e65e175bSOded Gabbay u64 end_addr; 1888*e65e175bSOded Gabbay 1889*e65e175bSOded Gabbay /* now make sure that the memory transfer is within region's bounds */ 1890*e65e175bSOded Gabbay end_addr = addr + size; 1891*e65e175bSOded Gabbay if (end_addr >= region->region_base + region->region_size) { 1892*e65e175bSOded Gabbay dev_err(hdev->dev, 1893*e65e175bSOded Gabbay "dynamic FW load: memory transfer end address out of memory region bounds. addr: %llx\n", 1894*e65e175bSOded Gabbay end_addr); 1895*e65e175bSOded Gabbay return -EIO; 1896*e65e175bSOded Gabbay } 1897*e65e175bSOded Gabbay 1898*e65e175bSOded Gabbay /* 1899*e65e175bSOded Gabbay * now make sure memory transfer is within predefined BAR bounds. 1900*e65e175bSOded Gabbay * this is to make sure we do not need to set the bar (e.g. for DRAM 1901*e65e175bSOded Gabbay * memory transfers) 1902*e65e175bSOded Gabbay */ 1903*e65e175bSOded Gabbay if (end_addr >= region->region_base - region->offset_in_bar + 1904*e65e175bSOded Gabbay region->bar_size) { 1905*e65e175bSOded Gabbay dev_err(hdev->dev, 1906*e65e175bSOded Gabbay "FW image beyond PCI BAR bounds\n"); 1907*e65e175bSOded Gabbay return -EIO; 1908*e65e175bSOded Gabbay } 1909*e65e175bSOded Gabbay 1910*e65e175bSOded Gabbay return 0; 1911*e65e175bSOded Gabbay } 1912*e65e175bSOded Gabbay 1913*e65e175bSOded Gabbay /** 1914*e65e175bSOded Gabbay * hl_fw_dynamic_validate_descriptor - validate FW descriptor 1915*e65e175bSOded Gabbay * 1916*e65e175bSOded Gabbay * @hdev: pointer to the habanalabs device structure 1917*e65e175bSOded Gabbay * @fw_loader: managing structure for loading device's FW 1918*e65e175bSOded Gabbay * @fw_desc: the descriptor from FW 1919*e65e175bSOded Gabbay * 1920*e65e175bSOded Gabbay * @return 0 on success, otherwise non-zero error code 1921*e65e175bSOded Gabbay */ 1922*e65e175bSOded Gabbay static int hl_fw_dynamic_validate_descriptor(struct hl_device *hdev, 1923*e65e175bSOded Gabbay struct fw_load_mgr *fw_loader, 1924*e65e175bSOded Gabbay struct lkd_fw_comms_desc *fw_desc) 1925*e65e175bSOded Gabbay { 1926*e65e175bSOded Gabbay struct pci_mem_region *region; 1927*e65e175bSOded Gabbay enum pci_region region_id; 1928*e65e175bSOded Gabbay size_t data_size; 1929*e65e175bSOded Gabbay u32 data_crc32; 1930*e65e175bSOded Gabbay u8 *data_ptr; 1931*e65e175bSOded Gabbay u64 addr; 1932*e65e175bSOded Gabbay int rc; 1933*e65e175bSOded Gabbay 1934*e65e175bSOded Gabbay if (le32_to_cpu(fw_desc->header.magic) != HL_COMMS_DESC_MAGIC) 1935*e65e175bSOded Gabbay dev_dbg(hdev->dev, "Invalid magic for dynamic FW descriptor (%x)\n", 1936*e65e175bSOded Gabbay fw_desc->header.magic); 1937*e65e175bSOded Gabbay 1938*e65e175bSOded Gabbay if (fw_desc->header.version != HL_COMMS_DESC_VER) 1939*e65e175bSOded Gabbay dev_dbg(hdev->dev, "Invalid version for dynamic FW descriptor (%x)\n", 1940*e65e175bSOded Gabbay fw_desc->header.version); 1941*e65e175bSOded Gabbay 1942*e65e175bSOded Gabbay /* 1943*e65e175bSOded Gabbay * Calc CRC32 of data without header. use the size of the descriptor 1944*e65e175bSOded Gabbay * reported by firmware, without calculating it ourself, to allow adding 1945*e65e175bSOded Gabbay * more fields to the lkd_fw_comms_desc structure. 1946*e65e175bSOded Gabbay * note that no alignment/stride address issues here as all structures 1947*e65e175bSOded Gabbay * are 64 bit padded. 1948*e65e175bSOded Gabbay */ 1949*e65e175bSOded Gabbay data_ptr = (u8 *)fw_desc + sizeof(struct comms_desc_header); 1950*e65e175bSOded Gabbay data_size = le16_to_cpu(fw_desc->header.size); 1951*e65e175bSOded Gabbay 1952*e65e175bSOded Gabbay data_crc32 = hl_fw_compat_crc32(data_ptr, data_size); 1953*e65e175bSOded Gabbay if (data_crc32 != le32_to_cpu(fw_desc->header.crc32)) { 1954*e65e175bSOded Gabbay dev_err(hdev->dev, "CRC32 mismatch for dynamic FW descriptor (%x:%x)\n", 1955*e65e175bSOded Gabbay data_crc32, fw_desc->header.crc32); 1956*e65e175bSOded Gabbay return -EIO; 1957*e65e175bSOded Gabbay } 1958*e65e175bSOded Gabbay 1959*e65e175bSOded Gabbay /* find memory region to which to copy the image */ 1960*e65e175bSOded Gabbay addr = le64_to_cpu(fw_desc->img_addr); 1961*e65e175bSOded Gabbay region_id = hl_get_pci_memory_region(hdev, addr); 1962*e65e175bSOded Gabbay if ((region_id != PCI_REGION_SRAM) && ((region_id != PCI_REGION_DRAM))) { 1963*e65e175bSOded Gabbay dev_err(hdev->dev, "Invalid region to copy FW image address=%llx\n", addr); 1964*e65e175bSOded Gabbay return -EIO; 1965*e65e175bSOded Gabbay } 1966*e65e175bSOded Gabbay 1967*e65e175bSOded Gabbay region = &hdev->pci_mem_region[region_id]; 1968*e65e175bSOded Gabbay 1969*e65e175bSOded Gabbay /* store the region for the copy stage */ 1970*e65e175bSOded Gabbay fw_loader->dynamic_loader.image_region = region; 1971*e65e175bSOded Gabbay 1972*e65e175bSOded Gabbay /* 1973*e65e175bSOded Gabbay * here we know that the start address is valid, now make sure that the 1974*e65e175bSOded Gabbay * image is within region's bounds 1975*e65e175bSOded Gabbay */ 1976*e65e175bSOded Gabbay rc = hl_fw_dynamic_validate_memory_bound(hdev, addr, 1977*e65e175bSOded Gabbay fw_loader->dynamic_loader.fw_image_size, 1978*e65e175bSOded Gabbay region); 1979*e65e175bSOded Gabbay if (rc) { 1980*e65e175bSOded Gabbay dev_err(hdev->dev, "invalid mem transfer request for FW image\n"); 1981*e65e175bSOded Gabbay return rc; 1982*e65e175bSOded Gabbay } 1983*e65e175bSOded Gabbay 1984*e65e175bSOded Gabbay /* here we can mark the descriptor as valid as the content has been validated */ 1985*e65e175bSOded Gabbay fw_loader->dynamic_loader.fw_desc_valid = true; 1986*e65e175bSOded Gabbay 1987*e65e175bSOded Gabbay return 0; 1988*e65e175bSOded Gabbay } 1989*e65e175bSOded Gabbay 1990*e65e175bSOded Gabbay static int hl_fw_dynamic_validate_response(struct hl_device *hdev, 1991*e65e175bSOded Gabbay struct fw_response *response, 1992*e65e175bSOded Gabbay struct pci_mem_region *region) 1993*e65e175bSOded Gabbay { 1994*e65e175bSOded Gabbay u64 device_addr; 1995*e65e175bSOded Gabbay int rc; 1996*e65e175bSOded Gabbay 1997*e65e175bSOded Gabbay device_addr = region->region_base + response->ram_offset; 1998*e65e175bSOded Gabbay 1999*e65e175bSOded Gabbay /* 2000*e65e175bSOded Gabbay * validate that the descriptor is within region's bounds 2001*e65e175bSOded Gabbay * Note that as the start address was supplied according to the RAM 2002*e65e175bSOded Gabbay * type- testing only the end address is enough 2003*e65e175bSOded Gabbay */ 2004*e65e175bSOded Gabbay rc = hl_fw_dynamic_validate_memory_bound(hdev, device_addr, 2005*e65e175bSOded Gabbay sizeof(struct lkd_fw_comms_desc), 2006*e65e175bSOded Gabbay region); 2007*e65e175bSOded Gabbay return rc; 2008*e65e175bSOded Gabbay } 2009*e65e175bSOded Gabbay 2010*e65e175bSOded Gabbay /* 2011*e65e175bSOded Gabbay * hl_fw_dynamic_read_descriptor_msg - read and show the ascii msg that sent by fw 2012*e65e175bSOded Gabbay * 2013*e65e175bSOded Gabbay * @hdev: pointer to the habanalabs device structure 2014*e65e175bSOded Gabbay * @fw_desc: the descriptor from FW 2015*e65e175bSOded Gabbay */ 2016*e65e175bSOded Gabbay static void hl_fw_dynamic_read_descriptor_msg(struct hl_device *hdev, 2017*e65e175bSOded Gabbay struct lkd_fw_comms_desc *fw_desc) 2018*e65e175bSOded Gabbay { 2019*e65e175bSOded Gabbay int i; 2020*e65e175bSOded Gabbay char *msg; 2021*e65e175bSOded Gabbay 2022*e65e175bSOded Gabbay for (i = 0 ; i < LKD_FW_ASCII_MSG_MAX ; i++) { 2023*e65e175bSOded Gabbay if (!fw_desc->ascii_msg[i].valid) 2024*e65e175bSOded Gabbay return; 2025*e65e175bSOded Gabbay 2026*e65e175bSOded Gabbay /* force NULL termination */ 2027*e65e175bSOded Gabbay msg = fw_desc->ascii_msg[i].msg; 2028*e65e175bSOded Gabbay msg[LKD_FW_ASCII_MSG_MAX_LEN - 1] = '\0'; 2029*e65e175bSOded Gabbay 2030*e65e175bSOded Gabbay switch (fw_desc->ascii_msg[i].msg_lvl) { 2031*e65e175bSOded Gabbay case LKD_FW_ASCII_MSG_ERR: 2032*e65e175bSOded Gabbay dev_err(hdev->dev, "fw: %s", fw_desc->ascii_msg[i].msg); 2033*e65e175bSOded Gabbay break; 2034*e65e175bSOded Gabbay case LKD_FW_ASCII_MSG_WRN: 2035*e65e175bSOded Gabbay dev_warn(hdev->dev, "fw: %s", fw_desc->ascii_msg[i].msg); 2036*e65e175bSOded Gabbay break; 2037*e65e175bSOded Gabbay case LKD_FW_ASCII_MSG_INF: 2038*e65e175bSOded Gabbay dev_info(hdev->dev, "fw: %s", fw_desc->ascii_msg[i].msg); 2039*e65e175bSOded Gabbay break; 2040*e65e175bSOded Gabbay default: 2041*e65e175bSOded Gabbay dev_dbg(hdev->dev, "fw: %s", fw_desc->ascii_msg[i].msg); 2042*e65e175bSOded Gabbay break; 2043*e65e175bSOded Gabbay } 2044*e65e175bSOded Gabbay } 2045*e65e175bSOded Gabbay } 2046*e65e175bSOded Gabbay 2047*e65e175bSOded Gabbay /** 2048*e65e175bSOded Gabbay * hl_fw_dynamic_read_and_validate_descriptor - read and validate FW descriptor 2049*e65e175bSOded Gabbay * 2050*e65e175bSOded Gabbay * @hdev: pointer to the habanalabs device structure 2051*e65e175bSOded Gabbay * @fw_loader: managing structure for loading device's FW 2052*e65e175bSOded Gabbay * 2053*e65e175bSOded Gabbay * @return 0 on success, otherwise non-zero error code 2054*e65e175bSOded Gabbay */ 2055*e65e175bSOded Gabbay static int hl_fw_dynamic_read_and_validate_descriptor(struct hl_device *hdev, 2056*e65e175bSOded Gabbay struct fw_load_mgr *fw_loader) 2057*e65e175bSOded Gabbay { 2058*e65e175bSOded Gabbay struct lkd_fw_comms_desc *fw_desc; 2059*e65e175bSOded Gabbay struct pci_mem_region *region; 2060*e65e175bSOded Gabbay struct fw_response *response; 2061*e65e175bSOded Gabbay void *temp_fw_desc; 2062*e65e175bSOded Gabbay void __iomem *src; 2063*e65e175bSOded Gabbay u16 fw_data_size; 2064*e65e175bSOded Gabbay enum pci_region region_id; 2065*e65e175bSOded Gabbay int rc; 2066*e65e175bSOded Gabbay 2067*e65e175bSOded Gabbay fw_desc = &fw_loader->dynamic_loader.comm_desc; 2068*e65e175bSOded Gabbay response = &fw_loader->dynamic_loader.response; 2069*e65e175bSOded Gabbay 2070*e65e175bSOded Gabbay region_id = (response->ram_type == COMMS_SRAM) ? 2071*e65e175bSOded Gabbay PCI_REGION_SRAM : PCI_REGION_DRAM; 2072*e65e175bSOded Gabbay 2073*e65e175bSOded Gabbay region = &hdev->pci_mem_region[region_id]; 2074*e65e175bSOded Gabbay 2075*e65e175bSOded Gabbay rc = hl_fw_dynamic_validate_response(hdev, response, region); 2076*e65e175bSOded Gabbay if (rc) { 2077*e65e175bSOded Gabbay dev_err(hdev->dev, 2078*e65e175bSOded Gabbay "invalid mem transfer request for FW descriptor\n"); 2079*e65e175bSOded Gabbay return rc; 2080*e65e175bSOded Gabbay } 2081*e65e175bSOded Gabbay 2082*e65e175bSOded Gabbay /* 2083*e65e175bSOded Gabbay * extract address to copy the descriptor from 2084*e65e175bSOded Gabbay * in addition, as the descriptor value is going to be over-ridden by new data- we mark it 2085*e65e175bSOded Gabbay * as invalid. 2086*e65e175bSOded Gabbay * it will be marked again as valid once validated 2087*e65e175bSOded Gabbay */ 2088*e65e175bSOded Gabbay fw_loader->dynamic_loader.fw_desc_valid = false; 2089*e65e175bSOded Gabbay src = hdev->pcie_bar[region->bar_id] + region->offset_in_bar + 2090*e65e175bSOded Gabbay response->ram_offset; 2091*e65e175bSOded Gabbay 2092*e65e175bSOded Gabbay /* 2093*e65e175bSOded Gabbay * We do the copy of the fw descriptor in 2 phases: 2094*e65e175bSOded Gabbay * 1. copy the header + data info according to our lkd_fw_comms_desc definition. 2095*e65e175bSOded Gabbay * then we're able to read the actual data size provided by fw. 2096*e65e175bSOded Gabbay * this is needed for cases where data in descriptor was changed(add/remove) 2097*e65e175bSOded Gabbay * in embedded specs header file before updating lkd copy of the header file 2098*e65e175bSOded Gabbay * 2. copy descriptor to temporary buffer with aligned size and send it to validation 2099*e65e175bSOded Gabbay */ 2100*e65e175bSOded Gabbay memcpy_fromio(fw_desc, src, sizeof(struct lkd_fw_comms_desc)); 2101*e65e175bSOded Gabbay fw_data_size = le16_to_cpu(fw_desc->header.size); 2102*e65e175bSOded Gabbay 2103*e65e175bSOded Gabbay temp_fw_desc = vzalloc(sizeof(struct comms_desc_header) + fw_data_size); 2104*e65e175bSOded Gabbay if (!temp_fw_desc) 2105*e65e175bSOded Gabbay return -ENOMEM; 2106*e65e175bSOded Gabbay 2107*e65e175bSOded Gabbay memcpy_fromio(temp_fw_desc, src, sizeof(struct comms_desc_header) + fw_data_size); 2108*e65e175bSOded Gabbay 2109*e65e175bSOded Gabbay rc = hl_fw_dynamic_validate_descriptor(hdev, fw_loader, 2110*e65e175bSOded Gabbay (struct lkd_fw_comms_desc *) temp_fw_desc); 2111*e65e175bSOded Gabbay 2112*e65e175bSOded Gabbay if (!rc) 2113*e65e175bSOded Gabbay hl_fw_dynamic_read_descriptor_msg(hdev, temp_fw_desc); 2114*e65e175bSOded Gabbay 2115*e65e175bSOded Gabbay vfree(temp_fw_desc); 2116*e65e175bSOded Gabbay 2117*e65e175bSOded Gabbay return rc; 2118*e65e175bSOded Gabbay } 2119*e65e175bSOded Gabbay 2120*e65e175bSOded Gabbay /** 2121*e65e175bSOded Gabbay * hl_fw_dynamic_request_descriptor - handshake with CPU to get FW descriptor 2122*e65e175bSOded Gabbay * 2123*e65e175bSOded Gabbay * @hdev: pointer to the habanalabs device structure 2124*e65e175bSOded Gabbay * @fw_loader: managing structure for loading device's FW 2125*e65e175bSOded Gabbay * @next_image_size: size to allocate for next FW component 2126*e65e175bSOded Gabbay * 2127*e65e175bSOded Gabbay * @return 0 on success, otherwise non-zero error code 2128*e65e175bSOded Gabbay */ 2129*e65e175bSOded Gabbay static int hl_fw_dynamic_request_descriptor(struct hl_device *hdev, 2130*e65e175bSOded Gabbay struct fw_load_mgr *fw_loader, 2131*e65e175bSOded Gabbay size_t next_image_size) 2132*e65e175bSOded Gabbay { 2133*e65e175bSOded Gabbay int rc; 2134*e65e175bSOded Gabbay 2135*e65e175bSOded Gabbay rc = hl_fw_dynamic_send_protocol_cmd(hdev, fw_loader, COMMS_PREP_DESC, 2136*e65e175bSOded Gabbay next_image_size, true, 2137*e65e175bSOded Gabbay fw_loader->cpu_timeout); 2138*e65e175bSOded Gabbay if (rc) 2139*e65e175bSOded Gabbay return rc; 2140*e65e175bSOded Gabbay 2141*e65e175bSOded Gabbay return hl_fw_dynamic_read_and_validate_descriptor(hdev, fw_loader); 2142*e65e175bSOded Gabbay } 2143*e65e175bSOded Gabbay 2144*e65e175bSOded Gabbay /** 2145*e65e175bSOded Gabbay * hl_fw_dynamic_read_device_fw_version - read FW version to exposed properties 2146*e65e175bSOded Gabbay * 2147*e65e175bSOded Gabbay * @hdev: pointer to the habanalabs device structure 2148*e65e175bSOded Gabbay * @fwc: the firmware component 2149*e65e175bSOded Gabbay * @fw_version: fw component's version string 2150*e65e175bSOded Gabbay */ 2151*e65e175bSOded Gabbay static int hl_fw_dynamic_read_device_fw_version(struct hl_device *hdev, 2152*e65e175bSOded Gabbay enum hl_fw_component fwc, 2153*e65e175bSOded Gabbay const char *fw_version) 2154*e65e175bSOded Gabbay { 2155*e65e175bSOded Gabbay struct asic_fixed_properties *prop = &hdev->asic_prop; 2156*e65e175bSOded Gabbay char *preboot_ver, *boot_ver; 2157*e65e175bSOded Gabbay char btl_ver[32]; 2158*e65e175bSOded Gabbay 2159*e65e175bSOded Gabbay switch (fwc) { 2160*e65e175bSOded Gabbay case FW_COMP_BOOT_FIT: 2161*e65e175bSOded Gabbay strscpy(prop->uboot_ver, fw_version, VERSION_MAX_LEN); 2162*e65e175bSOded Gabbay boot_ver = extract_fw_ver_from_str(prop->uboot_ver); 2163*e65e175bSOded Gabbay if (boot_ver) { 2164*e65e175bSOded Gabbay dev_info(hdev->dev, "boot-fit version %s\n", boot_ver); 2165*e65e175bSOded Gabbay kfree(boot_ver); 2166*e65e175bSOded Gabbay } 2167*e65e175bSOded Gabbay 2168*e65e175bSOded Gabbay break; 2169*e65e175bSOded Gabbay case FW_COMP_PREBOOT: 2170*e65e175bSOded Gabbay strscpy(prop->preboot_ver, fw_version, VERSION_MAX_LEN); 2171*e65e175bSOded Gabbay preboot_ver = strnstr(prop->preboot_ver, "Preboot", 2172*e65e175bSOded Gabbay VERSION_MAX_LEN); 2173*e65e175bSOded Gabbay if (preboot_ver && preboot_ver != prop->preboot_ver) { 2174*e65e175bSOded Gabbay strscpy(btl_ver, prop->preboot_ver, 2175*e65e175bSOded Gabbay min((int) (preboot_ver - prop->preboot_ver), 31)); 2176*e65e175bSOded Gabbay dev_info(hdev->dev, "%s\n", btl_ver); 2177*e65e175bSOded Gabbay } 2178*e65e175bSOded Gabbay 2179*e65e175bSOded Gabbay preboot_ver = extract_fw_ver_from_str(prop->preboot_ver); 2180*e65e175bSOded Gabbay if (preboot_ver) { 2181*e65e175bSOded Gabbay int rc; 2182*e65e175bSOded Gabbay 2183*e65e175bSOded Gabbay dev_info(hdev->dev, "preboot version %s\n", preboot_ver); 2184*e65e175bSOded Gabbay 2185*e65e175bSOded Gabbay /* This function takes care of freeing preboot_ver */ 2186*e65e175bSOded Gabbay rc = extract_fw_sub_versions(hdev, preboot_ver); 2187*e65e175bSOded Gabbay if (rc) 2188*e65e175bSOded Gabbay return rc; 2189*e65e175bSOded Gabbay } 2190*e65e175bSOded Gabbay 2191*e65e175bSOded Gabbay break; 2192*e65e175bSOded Gabbay default: 2193*e65e175bSOded Gabbay dev_warn(hdev->dev, "Undefined FW component: %d\n", fwc); 2194*e65e175bSOded Gabbay return -EINVAL; 2195*e65e175bSOded Gabbay } 2196*e65e175bSOded Gabbay 2197*e65e175bSOded Gabbay return 0; 2198*e65e175bSOded Gabbay } 2199*e65e175bSOded Gabbay 2200*e65e175bSOded Gabbay /** 2201*e65e175bSOded Gabbay * hl_fw_dynamic_copy_image - copy image to memory allocated by the FW 2202*e65e175bSOded Gabbay * 2203*e65e175bSOded Gabbay * @hdev: pointer to the habanalabs device structure 2204*e65e175bSOded Gabbay * @fw: fw descriptor 2205*e65e175bSOded Gabbay * @fw_loader: managing structure for loading device's FW 2206*e65e175bSOded Gabbay */ 2207*e65e175bSOded Gabbay static int hl_fw_dynamic_copy_image(struct hl_device *hdev, 2208*e65e175bSOded Gabbay const struct firmware *fw, 2209*e65e175bSOded Gabbay struct fw_load_mgr *fw_loader) 2210*e65e175bSOded Gabbay { 2211*e65e175bSOded Gabbay struct lkd_fw_comms_desc *fw_desc; 2212*e65e175bSOded Gabbay struct pci_mem_region *region; 2213*e65e175bSOded Gabbay void __iomem *dest; 2214*e65e175bSOded Gabbay u64 addr; 2215*e65e175bSOded Gabbay int rc; 2216*e65e175bSOded Gabbay 2217*e65e175bSOded Gabbay fw_desc = &fw_loader->dynamic_loader.comm_desc; 2218*e65e175bSOded Gabbay addr = le64_to_cpu(fw_desc->img_addr); 2219*e65e175bSOded Gabbay 2220*e65e175bSOded Gabbay /* find memory region to which to copy the image */ 2221*e65e175bSOded Gabbay region = fw_loader->dynamic_loader.image_region; 2222*e65e175bSOded Gabbay 2223*e65e175bSOded Gabbay dest = hdev->pcie_bar[region->bar_id] + region->offset_in_bar + 2224*e65e175bSOded Gabbay (addr - region->region_base); 2225*e65e175bSOded Gabbay 2226*e65e175bSOded Gabbay rc = hl_fw_copy_fw_to_device(hdev, fw, dest, 2227*e65e175bSOded Gabbay fw_loader->boot_fit_img.src_off, 2228*e65e175bSOded Gabbay fw_loader->boot_fit_img.copy_size); 2229*e65e175bSOded Gabbay 2230*e65e175bSOded Gabbay return rc; 2231*e65e175bSOded Gabbay } 2232*e65e175bSOded Gabbay 2233*e65e175bSOded Gabbay /** 2234*e65e175bSOded Gabbay * hl_fw_dynamic_copy_msg - copy msg to memory allocated by the FW 2235*e65e175bSOded Gabbay * 2236*e65e175bSOded Gabbay * @hdev: pointer to the habanalabs device structure 2237*e65e175bSOded Gabbay * @msg: message 2238*e65e175bSOded Gabbay * @fw_loader: managing structure for loading device's FW 2239*e65e175bSOded Gabbay */ 2240*e65e175bSOded Gabbay static int hl_fw_dynamic_copy_msg(struct hl_device *hdev, 2241*e65e175bSOded Gabbay struct lkd_msg_comms *msg, struct fw_load_mgr *fw_loader) 2242*e65e175bSOded Gabbay { 2243*e65e175bSOded Gabbay struct lkd_fw_comms_desc *fw_desc; 2244*e65e175bSOded Gabbay struct pci_mem_region *region; 2245*e65e175bSOded Gabbay void __iomem *dest; 2246*e65e175bSOded Gabbay u64 addr; 2247*e65e175bSOded Gabbay int rc; 2248*e65e175bSOded Gabbay 2249*e65e175bSOded Gabbay fw_desc = &fw_loader->dynamic_loader.comm_desc; 2250*e65e175bSOded Gabbay addr = le64_to_cpu(fw_desc->img_addr); 2251*e65e175bSOded Gabbay 2252*e65e175bSOded Gabbay /* find memory region to which to copy the image */ 2253*e65e175bSOded Gabbay region = fw_loader->dynamic_loader.image_region; 2254*e65e175bSOded Gabbay 2255*e65e175bSOded Gabbay dest = hdev->pcie_bar[region->bar_id] + region->offset_in_bar + 2256*e65e175bSOded Gabbay (addr - region->region_base); 2257*e65e175bSOded Gabbay 2258*e65e175bSOded Gabbay rc = hl_fw_copy_msg_to_device(hdev, msg, dest, 0, 0); 2259*e65e175bSOded Gabbay 2260*e65e175bSOded Gabbay return rc; 2261*e65e175bSOded Gabbay } 2262*e65e175bSOded Gabbay 2263*e65e175bSOded Gabbay /** 2264*e65e175bSOded Gabbay * hl_fw_boot_fit_update_state - update internal data structures after boot-fit 2265*e65e175bSOded Gabbay * is loaded 2266*e65e175bSOded Gabbay * 2267*e65e175bSOded Gabbay * @hdev: pointer to the habanalabs device structure 2268*e65e175bSOded Gabbay * @cpu_boot_dev_sts0_reg: register holding CPU boot dev status 0 2269*e65e175bSOded Gabbay * @cpu_boot_dev_sts1_reg: register holding CPU boot dev status 1 2270*e65e175bSOded Gabbay * 2271*e65e175bSOded Gabbay * @return 0 on success, otherwise non-zero error code 2272*e65e175bSOded Gabbay */ 2273*e65e175bSOded Gabbay static void hl_fw_boot_fit_update_state(struct hl_device *hdev, 2274*e65e175bSOded Gabbay u32 cpu_boot_dev_sts0_reg, 2275*e65e175bSOded Gabbay u32 cpu_boot_dev_sts1_reg) 2276*e65e175bSOded Gabbay { 2277*e65e175bSOded Gabbay struct asic_fixed_properties *prop = &hdev->asic_prop; 2278*e65e175bSOded Gabbay 2279*e65e175bSOded Gabbay hdev->fw_loader.fw_comp_loaded |= FW_TYPE_BOOT_CPU; 2280*e65e175bSOded Gabbay 2281*e65e175bSOded Gabbay /* Read boot_cpu status bits */ 2282*e65e175bSOded Gabbay if (prop->fw_preboot_cpu_boot_dev_sts0 & CPU_BOOT_DEV_STS0_ENABLED) { 2283*e65e175bSOded Gabbay prop->fw_bootfit_cpu_boot_dev_sts0 = 2284*e65e175bSOded Gabbay RREG32(cpu_boot_dev_sts0_reg); 2285*e65e175bSOded Gabbay 2286*e65e175bSOded Gabbay prop->hard_reset_done_by_fw = !!(prop->fw_bootfit_cpu_boot_dev_sts0 & 2287*e65e175bSOded Gabbay CPU_BOOT_DEV_STS0_FW_HARD_RST_EN); 2288*e65e175bSOded Gabbay 2289*e65e175bSOded Gabbay dev_dbg(hdev->dev, "Firmware boot CPU status0 %#x\n", 2290*e65e175bSOded Gabbay prop->fw_bootfit_cpu_boot_dev_sts0); 2291*e65e175bSOded Gabbay } 2292*e65e175bSOded Gabbay 2293*e65e175bSOded Gabbay if (prop->fw_cpu_boot_dev_sts1_valid) { 2294*e65e175bSOded Gabbay prop->fw_bootfit_cpu_boot_dev_sts1 = 2295*e65e175bSOded Gabbay RREG32(cpu_boot_dev_sts1_reg); 2296*e65e175bSOded Gabbay 2297*e65e175bSOded Gabbay dev_dbg(hdev->dev, "Firmware boot CPU status1 %#x\n", 2298*e65e175bSOded Gabbay prop->fw_bootfit_cpu_boot_dev_sts1); 2299*e65e175bSOded Gabbay } 2300*e65e175bSOded Gabbay 2301*e65e175bSOded Gabbay dev_dbg(hdev->dev, "Firmware boot CPU hard-reset is %s\n", 2302*e65e175bSOded Gabbay prop->hard_reset_done_by_fw ? "enabled" : "disabled"); 2303*e65e175bSOded Gabbay } 2304*e65e175bSOded Gabbay 2305*e65e175bSOded Gabbay static void hl_fw_dynamic_update_linux_interrupt_if(struct hl_device *hdev) 2306*e65e175bSOded Gabbay { 2307*e65e175bSOded Gabbay struct cpu_dyn_regs *dyn_regs = 2308*e65e175bSOded Gabbay &hdev->fw_loader.dynamic_loader.comm_desc.cpu_dyn_regs; 2309*e65e175bSOded Gabbay 2310*e65e175bSOded Gabbay /* Check whether all 3 interrupt interfaces are set, if not use a 2311*e65e175bSOded Gabbay * single interface 2312*e65e175bSOded Gabbay */ 2313*e65e175bSOded Gabbay if (!hdev->asic_prop.gic_interrupts_enable && 2314*e65e175bSOded Gabbay !(hdev->asic_prop.fw_app_cpu_boot_dev_sts0 & 2315*e65e175bSOded Gabbay CPU_BOOT_DEV_STS0_MULTI_IRQ_POLL_EN)) { 2316*e65e175bSOded Gabbay dyn_regs->gic_host_halt_irq = dyn_regs->gic_host_pi_upd_irq; 2317*e65e175bSOded Gabbay dyn_regs->gic_host_ints_irq = dyn_regs->gic_host_pi_upd_irq; 2318*e65e175bSOded Gabbay 2319*e65e175bSOded Gabbay dev_warn(hdev->dev, 2320*e65e175bSOded Gabbay "Using a single interrupt interface towards cpucp"); 2321*e65e175bSOded Gabbay } 2322*e65e175bSOded Gabbay } 2323*e65e175bSOded Gabbay /** 2324*e65e175bSOded Gabbay * hl_fw_dynamic_load_image - load FW image using dynamic protocol 2325*e65e175bSOded Gabbay * 2326*e65e175bSOded Gabbay * @hdev: pointer to the habanalabs device structure 2327*e65e175bSOded Gabbay * @fw_loader: managing structure for loading device's FW 2328*e65e175bSOded Gabbay * @load_fwc: the FW component to be loaded 2329*e65e175bSOded Gabbay * @img_ld_timeout: image load timeout 2330*e65e175bSOded Gabbay * 2331*e65e175bSOded Gabbay * @return 0 on success, otherwise non-zero error code 2332*e65e175bSOded Gabbay */ 2333*e65e175bSOded Gabbay static int hl_fw_dynamic_load_image(struct hl_device *hdev, 2334*e65e175bSOded Gabbay struct fw_load_mgr *fw_loader, 2335*e65e175bSOded Gabbay enum hl_fw_component load_fwc, 2336*e65e175bSOded Gabbay u32 img_ld_timeout) 2337*e65e175bSOded Gabbay { 2338*e65e175bSOded Gabbay enum hl_fw_component cur_fwc; 2339*e65e175bSOded Gabbay const struct firmware *fw; 2340*e65e175bSOded Gabbay char *fw_name; 2341*e65e175bSOded Gabbay int rc = 0; 2342*e65e175bSOded Gabbay 2343*e65e175bSOded Gabbay /* 2344*e65e175bSOded Gabbay * when loading image we have one of 2 scenarios: 2345*e65e175bSOded Gabbay * 1. current FW component is preboot and we want to load boot-fit 2346*e65e175bSOded Gabbay * 2. current FW component is boot-fit and we want to load linux 2347*e65e175bSOded Gabbay */ 2348*e65e175bSOded Gabbay if (load_fwc == FW_COMP_BOOT_FIT) { 2349*e65e175bSOded Gabbay cur_fwc = FW_COMP_PREBOOT; 2350*e65e175bSOded Gabbay fw_name = fw_loader->boot_fit_img.image_name; 2351*e65e175bSOded Gabbay } else { 2352*e65e175bSOded Gabbay cur_fwc = FW_COMP_BOOT_FIT; 2353*e65e175bSOded Gabbay fw_name = fw_loader->linux_img.image_name; 2354*e65e175bSOded Gabbay } 2355*e65e175bSOded Gabbay 2356*e65e175bSOded Gabbay /* request FW in order to communicate to FW the size to be allocated */ 2357*e65e175bSOded Gabbay rc = hl_request_fw(hdev, &fw, fw_name); 2358*e65e175bSOded Gabbay if (rc) 2359*e65e175bSOded Gabbay return rc; 2360*e65e175bSOded Gabbay 2361*e65e175bSOded Gabbay /* store the image size for future validation */ 2362*e65e175bSOded Gabbay fw_loader->dynamic_loader.fw_image_size = fw->size; 2363*e65e175bSOded Gabbay 2364*e65e175bSOded Gabbay rc = hl_fw_dynamic_request_descriptor(hdev, fw_loader, fw->size); 2365*e65e175bSOded Gabbay if (rc) 2366*e65e175bSOded Gabbay goto release_fw; 2367*e65e175bSOded Gabbay 2368*e65e175bSOded Gabbay /* read preboot version */ 2369*e65e175bSOded Gabbay rc = hl_fw_dynamic_read_device_fw_version(hdev, cur_fwc, 2370*e65e175bSOded Gabbay fw_loader->dynamic_loader.comm_desc.cur_fw_ver); 2371*e65e175bSOded Gabbay if (rc) 2372*e65e175bSOded Gabbay goto release_fw; 2373*e65e175bSOded Gabbay 2374*e65e175bSOded Gabbay /* update state according to boot stage */ 2375*e65e175bSOded Gabbay if (cur_fwc == FW_COMP_BOOT_FIT) { 2376*e65e175bSOded Gabbay struct cpu_dyn_regs *dyn_regs; 2377*e65e175bSOded Gabbay 2378*e65e175bSOded Gabbay dyn_regs = &fw_loader->dynamic_loader.comm_desc.cpu_dyn_regs; 2379*e65e175bSOded Gabbay hl_fw_boot_fit_update_state(hdev, 2380*e65e175bSOded Gabbay le32_to_cpu(dyn_regs->cpu_boot_dev_sts0), 2381*e65e175bSOded Gabbay le32_to_cpu(dyn_regs->cpu_boot_dev_sts1)); 2382*e65e175bSOded Gabbay } 2383*e65e175bSOded Gabbay 2384*e65e175bSOded Gabbay /* copy boot fit to space allocated by FW */ 2385*e65e175bSOded Gabbay rc = hl_fw_dynamic_copy_image(hdev, fw, fw_loader); 2386*e65e175bSOded Gabbay if (rc) 2387*e65e175bSOded Gabbay goto release_fw; 2388*e65e175bSOded Gabbay 2389*e65e175bSOded Gabbay rc = hl_fw_dynamic_send_protocol_cmd(hdev, fw_loader, COMMS_DATA_RDY, 2390*e65e175bSOded Gabbay 0, true, 2391*e65e175bSOded Gabbay fw_loader->cpu_timeout); 2392*e65e175bSOded Gabbay if (rc) 2393*e65e175bSOded Gabbay goto release_fw; 2394*e65e175bSOded Gabbay 2395*e65e175bSOded Gabbay rc = hl_fw_dynamic_send_protocol_cmd(hdev, fw_loader, COMMS_EXEC, 2396*e65e175bSOded Gabbay 0, false, 2397*e65e175bSOded Gabbay img_ld_timeout); 2398*e65e175bSOded Gabbay 2399*e65e175bSOded Gabbay release_fw: 2400*e65e175bSOded Gabbay hl_release_firmware(fw); 2401*e65e175bSOded Gabbay return rc; 2402*e65e175bSOded Gabbay } 2403*e65e175bSOded Gabbay 2404*e65e175bSOded Gabbay static int hl_fw_dynamic_wait_for_boot_fit_active(struct hl_device *hdev, 2405*e65e175bSOded Gabbay struct fw_load_mgr *fw_loader) 2406*e65e175bSOded Gabbay { 2407*e65e175bSOded Gabbay struct dynamic_fw_load_mgr *dyn_loader; 2408*e65e175bSOded Gabbay u32 status; 2409*e65e175bSOded Gabbay int rc; 2410*e65e175bSOded Gabbay 2411*e65e175bSOded Gabbay dyn_loader = &fw_loader->dynamic_loader; 2412*e65e175bSOded Gabbay 2413*e65e175bSOded Gabbay /* 2414*e65e175bSOded Gabbay * Make sure CPU boot-loader is running 2415*e65e175bSOded Gabbay * Note that the CPU_BOOT_STATUS_SRAM_AVAIL is generally set by Linux 2416*e65e175bSOded Gabbay * yet there is a debug scenario in which we loading uboot (without Linux) 2417*e65e175bSOded Gabbay * which at later stage is relocated to DRAM. In this case we expect 2418*e65e175bSOded Gabbay * uboot to set the CPU_BOOT_STATUS_SRAM_AVAIL and so we add it to the 2419*e65e175bSOded Gabbay * poll flags 2420*e65e175bSOded Gabbay */ 2421*e65e175bSOded Gabbay rc = hl_poll_timeout( 2422*e65e175bSOded Gabbay hdev, 2423*e65e175bSOded Gabbay le32_to_cpu(dyn_loader->comm_desc.cpu_dyn_regs.cpu_boot_status), 2424*e65e175bSOded Gabbay status, 2425*e65e175bSOded Gabbay (status == CPU_BOOT_STATUS_READY_TO_BOOT) || 2426*e65e175bSOded Gabbay (status == CPU_BOOT_STATUS_SRAM_AVAIL), 2427*e65e175bSOded Gabbay hdev->fw_poll_interval_usec, 2428*e65e175bSOded Gabbay dyn_loader->wait_for_bl_timeout); 2429*e65e175bSOded Gabbay if (rc) { 2430*e65e175bSOded Gabbay dev_err(hdev->dev, "failed to wait for boot\n"); 2431*e65e175bSOded Gabbay return rc; 2432*e65e175bSOded Gabbay } 2433*e65e175bSOded Gabbay 2434*e65e175bSOded Gabbay dev_dbg(hdev->dev, "uboot status = %d\n", status); 2435*e65e175bSOded Gabbay return 0; 2436*e65e175bSOded Gabbay } 2437*e65e175bSOded Gabbay 2438*e65e175bSOded Gabbay static int hl_fw_dynamic_wait_for_linux_active(struct hl_device *hdev, 2439*e65e175bSOded Gabbay struct fw_load_mgr *fw_loader) 2440*e65e175bSOded Gabbay { 2441*e65e175bSOded Gabbay struct dynamic_fw_load_mgr *dyn_loader; 2442*e65e175bSOded Gabbay u32 status; 2443*e65e175bSOded Gabbay int rc; 2444*e65e175bSOded Gabbay 2445*e65e175bSOded Gabbay dyn_loader = &fw_loader->dynamic_loader; 2446*e65e175bSOded Gabbay 2447*e65e175bSOded Gabbay /* Make sure CPU linux is running */ 2448*e65e175bSOded Gabbay 2449*e65e175bSOded Gabbay rc = hl_poll_timeout( 2450*e65e175bSOded Gabbay hdev, 2451*e65e175bSOded Gabbay le32_to_cpu(dyn_loader->comm_desc.cpu_dyn_regs.cpu_boot_status), 2452*e65e175bSOded Gabbay status, 2453*e65e175bSOded Gabbay (status == CPU_BOOT_STATUS_SRAM_AVAIL), 2454*e65e175bSOded Gabbay hdev->fw_poll_interval_usec, 2455*e65e175bSOded Gabbay fw_loader->cpu_timeout); 2456*e65e175bSOded Gabbay if (rc) { 2457*e65e175bSOded Gabbay dev_err(hdev->dev, "failed to wait for Linux\n"); 2458*e65e175bSOded Gabbay return rc; 2459*e65e175bSOded Gabbay } 2460*e65e175bSOded Gabbay 2461*e65e175bSOded Gabbay dev_dbg(hdev->dev, "Boot status = %d\n", status); 2462*e65e175bSOded Gabbay return 0; 2463*e65e175bSOded Gabbay } 2464*e65e175bSOded Gabbay 2465*e65e175bSOded Gabbay /** 2466*e65e175bSOded Gabbay * hl_fw_linux_update_state - update internal data structures after Linux 2467*e65e175bSOded Gabbay * is loaded. 2468*e65e175bSOded Gabbay * Note: Linux initialization is comprised mainly 2469*e65e175bSOded Gabbay * of two stages - loading kernel (SRAM_AVAIL) 2470*e65e175bSOded Gabbay * & loading ARMCP. 2471*e65e175bSOded Gabbay * Therefore reading boot device status in any of 2472*e65e175bSOded Gabbay * these stages might result in different values. 2473*e65e175bSOded Gabbay * 2474*e65e175bSOded Gabbay * @hdev: pointer to the habanalabs device structure 2475*e65e175bSOded Gabbay * @cpu_boot_dev_sts0_reg: register holding CPU boot dev status 0 2476*e65e175bSOded Gabbay * @cpu_boot_dev_sts1_reg: register holding CPU boot dev status 1 2477*e65e175bSOded Gabbay * 2478*e65e175bSOded Gabbay * @return 0 on success, otherwise non-zero error code 2479*e65e175bSOded Gabbay */ 2480*e65e175bSOded Gabbay static void hl_fw_linux_update_state(struct hl_device *hdev, 2481*e65e175bSOded Gabbay u32 cpu_boot_dev_sts0_reg, 2482*e65e175bSOded Gabbay u32 cpu_boot_dev_sts1_reg) 2483*e65e175bSOded Gabbay { 2484*e65e175bSOded Gabbay struct asic_fixed_properties *prop = &hdev->asic_prop; 2485*e65e175bSOded Gabbay 2486*e65e175bSOded Gabbay hdev->fw_loader.fw_comp_loaded |= FW_TYPE_LINUX; 2487*e65e175bSOded Gabbay 2488*e65e175bSOded Gabbay /* Read FW application security bits */ 2489*e65e175bSOded Gabbay if (prop->fw_cpu_boot_dev_sts0_valid) { 2490*e65e175bSOded Gabbay prop->fw_app_cpu_boot_dev_sts0 = RREG32(cpu_boot_dev_sts0_reg); 2491*e65e175bSOded Gabbay 2492*e65e175bSOded Gabbay prop->hard_reset_done_by_fw = !!(prop->fw_app_cpu_boot_dev_sts0 & 2493*e65e175bSOded Gabbay CPU_BOOT_DEV_STS0_FW_HARD_RST_EN); 2494*e65e175bSOded Gabbay 2495*e65e175bSOded Gabbay if (prop->fw_app_cpu_boot_dev_sts0 & 2496*e65e175bSOded Gabbay CPU_BOOT_DEV_STS0_GIC_PRIVILEGED_EN) 2497*e65e175bSOded Gabbay prop->gic_interrupts_enable = false; 2498*e65e175bSOded Gabbay 2499*e65e175bSOded Gabbay dev_dbg(hdev->dev, 2500*e65e175bSOded Gabbay "Firmware application CPU status0 %#x\n", 2501*e65e175bSOded Gabbay prop->fw_app_cpu_boot_dev_sts0); 2502*e65e175bSOded Gabbay 2503*e65e175bSOded Gabbay dev_dbg(hdev->dev, "GIC controller is %s\n", 2504*e65e175bSOded Gabbay prop->gic_interrupts_enable ? 2505*e65e175bSOded Gabbay "enabled" : "disabled"); 2506*e65e175bSOded Gabbay } 2507*e65e175bSOded Gabbay 2508*e65e175bSOded Gabbay if (prop->fw_cpu_boot_dev_sts1_valid) { 2509*e65e175bSOded Gabbay prop->fw_app_cpu_boot_dev_sts1 = RREG32(cpu_boot_dev_sts1_reg); 2510*e65e175bSOded Gabbay 2511*e65e175bSOded Gabbay dev_dbg(hdev->dev, 2512*e65e175bSOded Gabbay "Firmware application CPU status1 %#x\n", 2513*e65e175bSOded Gabbay prop->fw_app_cpu_boot_dev_sts1); 2514*e65e175bSOded Gabbay } 2515*e65e175bSOded Gabbay 2516*e65e175bSOded Gabbay dev_dbg(hdev->dev, "Firmware application CPU hard-reset is %s\n", 2517*e65e175bSOded Gabbay prop->hard_reset_done_by_fw ? "enabled" : "disabled"); 2518*e65e175bSOded Gabbay 2519*e65e175bSOded Gabbay dev_info(hdev->dev, "Successfully loaded firmware to device\n"); 2520*e65e175bSOded Gabbay } 2521*e65e175bSOded Gabbay 2522*e65e175bSOded Gabbay /** 2523*e65e175bSOded Gabbay * hl_fw_dynamic_send_msg - send a COMMS message with attached data 2524*e65e175bSOded Gabbay * 2525*e65e175bSOded Gabbay * @hdev: pointer to the habanalabs device structure 2526*e65e175bSOded Gabbay * @fw_loader: managing structure for loading device's FW 2527*e65e175bSOded Gabbay * @msg_type: message type 2528*e65e175bSOded Gabbay * @data: data to be sent 2529*e65e175bSOded Gabbay * 2530*e65e175bSOded Gabbay * @return 0 on success, otherwise non-zero error code 2531*e65e175bSOded Gabbay */ 2532*e65e175bSOded Gabbay static int hl_fw_dynamic_send_msg(struct hl_device *hdev, 2533*e65e175bSOded Gabbay struct fw_load_mgr *fw_loader, u8 msg_type, void *data) 2534*e65e175bSOded Gabbay { 2535*e65e175bSOded Gabbay struct lkd_msg_comms *msg; 2536*e65e175bSOded Gabbay int rc; 2537*e65e175bSOded Gabbay 2538*e65e175bSOded Gabbay msg = kzalloc(sizeof(*msg), GFP_KERNEL); 2539*e65e175bSOded Gabbay if (!msg) 2540*e65e175bSOded Gabbay return -ENOMEM; 2541*e65e175bSOded Gabbay 2542*e65e175bSOded Gabbay /* create message to be sent */ 2543*e65e175bSOded Gabbay msg->header.type = msg_type; 2544*e65e175bSOded Gabbay msg->header.size = cpu_to_le16(sizeof(struct comms_msg_header)); 2545*e65e175bSOded Gabbay msg->header.magic = cpu_to_le32(HL_COMMS_MSG_MAGIC); 2546*e65e175bSOded Gabbay 2547*e65e175bSOded Gabbay switch (msg_type) { 2548*e65e175bSOded Gabbay case HL_COMMS_RESET_CAUSE_TYPE: 2549*e65e175bSOded Gabbay msg->reset_cause = *(__u8 *) data; 2550*e65e175bSOded Gabbay break; 2551*e65e175bSOded Gabbay 2552*e65e175bSOded Gabbay default: 2553*e65e175bSOded Gabbay dev_err(hdev->dev, 2554*e65e175bSOded Gabbay "Send COMMS message - invalid message type %u\n", 2555*e65e175bSOded Gabbay msg_type); 2556*e65e175bSOded Gabbay rc = -EINVAL; 2557*e65e175bSOded Gabbay goto out; 2558*e65e175bSOded Gabbay } 2559*e65e175bSOded Gabbay 2560*e65e175bSOded Gabbay rc = hl_fw_dynamic_request_descriptor(hdev, fw_loader, 2561*e65e175bSOded Gabbay sizeof(struct lkd_msg_comms)); 2562*e65e175bSOded Gabbay if (rc) 2563*e65e175bSOded Gabbay goto out; 2564*e65e175bSOded Gabbay 2565*e65e175bSOded Gabbay /* copy message to space allocated by FW */ 2566*e65e175bSOded Gabbay rc = hl_fw_dynamic_copy_msg(hdev, msg, fw_loader); 2567*e65e175bSOded Gabbay if (rc) 2568*e65e175bSOded Gabbay goto out; 2569*e65e175bSOded Gabbay 2570*e65e175bSOded Gabbay rc = hl_fw_dynamic_send_protocol_cmd(hdev, fw_loader, COMMS_DATA_RDY, 2571*e65e175bSOded Gabbay 0, true, 2572*e65e175bSOded Gabbay fw_loader->cpu_timeout); 2573*e65e175bSOded Gabbay if (rc) 2574*e65e175bSOded Gabbay goto out; 2575*e65e175bSOded Gabbay 2576*e65e175bSOded Gabbay rc = hl_fw_dynamic_send_protocol_cmd(hdev, fw_loader, COMMS_EXEC, 2577*e65e175bSOded Gabbay 0, true, 2578*e65e175bSOded Gabbay fw_loader->cpu_timeout); 2579*e65e175bSOded Gabbay 2580*e65e175bSOded Gabbay out: 2581*e65e175bSOded Gabbay kfree(msg); 2582*e65e175bSOded Gabbay return rc; 2583*e65e175bSOded Gabbay } 2584*e65e175bSOded Gabbay 2585*e65e175bSOded Gabbay /** 2586*e65e175bSOded Gabbay * hl_fw_dynamic_init_cpu - initialize the device CPU using dynamic protocol 2587*e65e175bSOded Gabbay * 2588*e65e175bSOded Gabbay * @hdev: pointer to the habanalabs device structure 2589*e65e175bSOded Gabbay * @fw_loader: managing structure for loading device's FW 2590*e65e175bSOded Gabbay * 2591*e65e175bSOded Gabbay * @return 0 on success, otherwise non-zero error code 2592*e65e175bSOded Gabbay * 2593*e65e175bSOded Gabbay * brief: the dynamic protocol is master (LKD) slave (FW CPU) protocol. 2594*e65e175bSOded Gabbay * the communication is done using registers: 2595*e65e175bSOded Gabbay * - LKD command register 2596*e65e175bSOded Gabbay * - FW status register 2597*e65e175bSOded Gabbay * the protocol is race free. this goal is achieved by splitting the requests 2598*e65e175bSOded Gabbay * and response to known synchronization points between the LKD and the FW. 2599*e65e175bSOded Gabbay * each response to LKD request is known and bound to a predefined timeout. 2600*e65e175bSOded Gabbay * in case of timeout expiration without the desired status from FW- the 2601*e65e175bSOded Gabbay * protocol (and hence the boot) will fail. 2602*e65e175bSOded Gabbay */ 2603*e65e175bSOded Gabbay static int hl_fw_dynamic_init_cpu(struct hl_device *hdev, 2604*e65e175bSOded Gabbay struct fw_load_mgr *fw_loader) 2605*e65e175bSOded Gabbay { 2606*e65e175bSOded Gabbay struct cpu_dyn_regs *dyn_regs; 2607*e65e175bSOded Gabbay int rc, fw_error_rc; 2608*e65e175bSOded Gabbay 2609*e65e175bSOded Gabbay dev_info(hdev->dev, 2610*e65e175bSOded Gabbay "Loading %sfirmware to device, may take some time...\n", 2611*e65e175bSOded Gabbay hdev->asic_prop.fw_security_enabled ? "secured " : ""); 2612*e65e175bSOded Gabbay 2613*e65e175bSOded Gabbay /* initialize FW descriptor as invalid */ 2614*e65e175bSOded Gabbay fw_loader->dynamic_loader.fw_desc_valid = false; 2615*e65e175bSOded Gabbay 2616*e65e175bSOded Gabbay /* 2617*e65e175bSOded Gabbay * In this stage, "cpu_dyn_regs" contains only LKD's hard coded values! 2618*e65e175bSOded Gabbay * It will be updated from FW after hl_fw_dynamic_request_descriptor(). 2619*e65e175bSOded Gabbay */ 2620*e65e175bSOded Gabbay dyn_regs = &fw_loader->dynamic_loader.comm_desc.cpu_dyn_regs; 2621*e65e175bSOded Gabbay 2622*e65e175bSOded Gabbay rc = hl_fw_dynamic_send_protocol_cmd(hdev, fw_loader, COMMS_RST_STATE, 2623*e65e175bSOded Gabbay 0, true, 2624*e65e175bSOded Gabbay fw_loader->cpu_timeout); 2625*e65e175bSOded Gabbay if (rc) 2626*e65e175bSOded Gabbay goto protocol_err; 2627*e65e175bSOded Gabbay 2628*e65e175bSOded Gabbay if (hdev->reset_info.curr_reset_cause) { 2629*e65e175bSOded Gabbay rc = hl_fw_dynamic_send_msg(hdev, fw_loader, 2630*e65e175bSOded Gabbay HL_COMMS_RESET_CAUSE_TYPE, &hdev->reset_info.curr_reset_cause); 2631*e65e175bSOded Gabbay if (rc) 2632*e65e175bSOded Gabbay goto protocol_err; 2633*e65e175bSOded Gabbay 2634*e65e175bSOded Gabbay /* Clear current reset cause */ 2635*e65e175bSOded Gabbay hdev->reset_info.curr_reset_cause = HL_RESET_CAUSE_UNKNOWN; 2636*e65e175bSOded Gabbay } 2637*e65e175bSOded Gabbay 2638*e65e175bSOded Gabbay if (!(hdev->fw_components & FW_TYPE_BOOT_CPU)) { 2639*e65e175bSOded Gabbay struct lkd_fw_binning_info *binning_info; 2640*e65e175bSOded Gabbay 2641*e65e175bSOded Gabbay rc = hl_fw_dynamic_request_descriptor(hdev, fw_loader, 0); 2642*e65e175bSOded Gabbay if (rc) 2643*e65e175bSOded Gabbay goto protocol_err; 2644*e65e175bSOded Gabbay 2645*e65e175bSOded Gabbay /* read preboot version */ 2646*e65e175bSOded Gabbay rc = hl_fw_dynamic_read_device_fw_version(hdev, FW_COMP_PREBOOT, 2647*e65e175bSOded Gabbay fw_loader->dynamic_loader.comm_desc.cur_fw_ver); 2648*e65e175bSOded Gabbay 2649*e65e175bSOded Gabbay if (rc) 2650*e65e175bSOded Gabbay goto out; 2651*e65e175bSOded Gabbay 2652*e65e175bSOded Gabbay /* read binning info from preboot */ 2653*e65e175bSOded Gabbay if (hdev->support_preboot_binning) { 2654*e65e175bSOded Gabbay binning_info = &fw_loader->dynamic_loader.comm_desc.binning_info; 2655*e65e175bSOded Gabbay hdev->tpc_binning = le64_to_cpu(binning_info->tpc_mask_l); 2656*e65e175bSOded Gabbay hdev->dram_binning = le32_to_cpu(binning_info->dram_mask); 2657*e65e175bSOded Gabbay hdev->edma_binning = le32_to_cpu(binning_info->edma_mask); 2658*e65e175bSOded Gabbay hdev->decoder_binning = le32_to_cpu(binning_info->dec_mask); 2659*e65e175bSOded Gabbay hdev->rotator_binning = le32_to_cpu(binning_info->rot_mask); 2660*e65e175bSOded Gabbay 2661*e65e175bSOded Gabbay rc = hdev->asic_funcs->set_dram_properties(hdev); 2662*e65e175bSOded Gabbay if (rc) 2663*e65e175bSOded Gabbay goto out; 2664*e65e175bSOded Gabbay 2665*e65e175bSOded Gabbay dev_dbg(hdev->dev, 2666*e65e175bSOded Gabbay "Read binning masks: tpc: 0x%llx, dram: 0x%llx, edma: 0x%x, dec: 0x%x, rot:0x%x\n", 2667*e65e175bSOded Gabbay hdev->tpc_binning, hdev->dram_binning, hdev->edma_binning, 2668*e65e175bSOded Gabbay hdev->decoder_binning, hdev->rotator_binning); 2669*e65e175bSOded Gabbay } 2670*e65e175bSOded Gabbay out: 2671*e65e175bSOded Gabbay return rc; 2672*e65e175bSOded Gabbay } 2673*e65e175bSOded Gabbay 2674*e65e175bSOded Gabbay /* load boot fit to FW */ 2675*e65e175bSOded Gabbay rc = hl_fw_dynamic_load_image(hdev, fw_loader, FW_COMP_BOOT_FIT, 2676*e65e175bSOded Gabbay fw_loader->boot_fit_timeout); 2677*e65e175bSOded Gabbay if (rc) { 2678*e65e175bSOded Gabbay dev_err(hdev->dev, "failed to load boot fit\n"); 2679*e65e175bSOded Gabbay goto protocol_err; 2680*e65e175bSOded Gabbay } 2681*e65e175bSOded Gabbay 2682*e65e175bSOded Gabbay /* 2683*e65e175bSOded Gabbay * when testing FW load (without Linux) on PLDM we don't want to 2684*e65e175bSOded Gabbay * wait until boot fit is active as it may take several hours. 2685*e65e175bSOded Gabbay * instead, we load the bootfit and let it do all initialization in 2686*e65e175bSOded Gabbay * the background. 2687*e65e175bSOded Gabbay */ 2688*e65e175bSOded Gabbay if (hdev->pldm && !(hdev->fw_components & FW_TYPE_LINUX)) 2689*e65e175bSOded Gabbay return 0; 2690*e65e175bSOded Gabbay 2691*e65e175bSOded Gabbay rc = hl_fw_dynamic_wait_for_boot_fit_active(hdev, fw_loader); 2692*e65e175bSOded Gabbay if (rc) 2693*e65e175bSOded Gabbay goto protocol_err; 2694*e65e175bSOded Gabbay 2695*e65e175bSOded Gabbay /* Enable DRAM scrambling before Linux boot and after successful 2696*e65e175bSOded Gabbay * UBoot 2697*e65e175bSOded Gabbay */ 2698*e65e175bSOded Gabbay hdev->asic_funcs->init_cpu_scrambler_dram(hdev); 2699*e65e175bSOded Gabbay 2700*e65e175bSOded Gabbay if (!(hdev->fw_components & FW_TYPE_LINUX)) { 2701*e65e175bSOded Gabbay dev_info(hdev->dev, "Skip loading Linux F/W\n"); 2702*e65e175bSOded Gabbay return 0; 2703*e65e175bSOded Gabbay } 2704*e65e175bSOded Gabbay 2705*e65e175bSOded Gabbay if (fw_loader->skip_bmc) { 2706*e65e175bSOded Gabbay rc = hl_fw_dynamic_send_protocol_cmd(hdev, fw_loader, 2707*e65e175bSOded Gabbay COMMS_SKIP_BMC, 0, 2708*e65e175bSOded Gabbay true, 2709*e65e175bSOded Gabbay fw_loader->cpu_timeout); 2710*e65e175bSOded Gabbay if (rc) { 2711*e65e175bSOded Gabbay dev_err(hdev->dev, "failed to load boot fit\n"); 2712*e65e175bSOded Gabbay goto protocol_err; 2713*e65e175bSOded Gabbay } 2714*e65e175bSOded Gabbay } 2715*e65e175bSOded Gabbay 2716*e65e175bSOded Gabbay /* load Linux image to FW */ 2717*e65e175bSOded Gabbay rc = hl_fw_dynamic_load_image(hdev, fw_loader, FW_COMP_LINUX, 2718*e65e175bSOded Gabbay fw_loader->cpu_timeout); 2719*e65e175bSOded Gabbay if (rc) { 2720*e65e175bSOded Gabbay dev_err(hdev->dev, "failed to load Linux\n"); 2721*e65e175bSOded Gabbay goto protocol_err; 2722*e65e175bSOded Gabbay } 2723*e65e175bSOded Gabbay 2724*e65e175bSOded Gabbay rc = hl_fw_dynamic_wait_for_linux_active(hdev, fw_loader); 2725*e65e175bSOded Gabbay if (rc) 2726*e65e175bSOded Gabbay goto protocol_err; 2727*e65e175bSOded Gabbay 2728*e65e175bSOded Gabbay hl_fw_linux_update_state(hdev, le32_to_cpu(dyn_regs->cpu_boot_dev_sts0), 2729*e65e175bSOded Gabbay le32_to_cpu(dyn_regs->cpu_boot_dev_sts1)); 2730*e65e175bSOded Gabbay 2731*e65e175bSOded Gabbay hl_fw_dynamic_update_linux_interrupt_if(hdev); 2732*e65e175bSOded Gabbay 2733*e65e175bSOded Gabbay protocol_err: 2734*e65e175bSOded Gabbay if (fw_loader->dynamic_loader.fw_desc_valid) { 2735*e65e175bSOded Gabbay fw_error_rc = fw_read_errors(hdev, le32_to_cpu(dyn_regs->cpu_boot_err0), 2736*e65e175bSOded Gabbay le32_to_cpu(dyn_regs->cpu_boot_err1), 2737*e65e175bSOded Gabbay le32_to_cpu(dyn_regs->cpu_boot_dev_sts0), 2738*e65e175bSOded Gabbay le32_to_cpu(dyn_regs->cpu_boot_dev_sts1)); 2739*e65e175bSOded Gabbay 2740*e65e175bSOded Gabbay if (fw_error_rc) 2741*e65e175bSOded Gabbay return fw_error_rc; 2742*e65e175bSOded Gabbay } 2743*e65e175bSOded Gabbay 2744*e65e175bSOded Gabbay return rc; 2745*e65e175bSOded Gabbay } 2746*e65e175bSOded Gabbay 2747*e65e175bSOded Gabbay /** 2748*e65e175bSOded Gabbay * hl_fw_static_init_cpu - initialize the device CPU using static protocol 2749*e65e175bSOded Gabbay * 2750*e65e175bSOded Gabbay * @hdev: pointer to the habanalabs device structure 2751*e65e175bSOded Gabbay * @fw_loader: managing structure for loading device's FW 2752*e65e175bSOded Gabbay * 2753*e65e175bSOded Gabbay * @return 0 on success, otherwise non-zero error code 2754*e65e175bSOded Gabbay */ 2755*e65e175bSOded Gabbay static int hl_fw_static_init_cpu(struct hl_device *hdev, 2756*e65e175bSOded Gabbay struct fw_load_mgr *fw_loader) 2757*e65e175bSOded Gabbay { 2758*e65e175bSOded Gabbay u32 cpu_msg_status_reg, cpu_timeout, msg_to_cpu_reg, status; 2759*e65e175bSOded Gabbay u32 cpu_boot_dev_status0_reg, cpu_boot_dev_status1_reg; 2760*e65e175bSOded Gabbay struct static_fw_load_mgr *static_loader; 2761*e65e175bSOded Gabbay u32 cpu_boot_status_reg; 2762*e65e175bSOded Gabbay int rc; 2763*e65e175bSOded Gabbay 2764*e65e175bSOded Gabbay if (!(hdev->fw_components & FW_TYPE_BOOT_CPU)) 2765*e65e175bSOded Gabbay return 0; 2766*e65e175bSOded Gabbay 2767*e65e175bSOded Gabbay /* init common loader parameters */ 2768*e65e175bSOded Gabbay cpu_timeout = fw_loader->cpu_timeout; 2769*e65e175bSOded Gabbay 2770*e65e175bSOded Gabbay /* init static loader parameters */ 2771*e65e175bSOded Gabbay static_loader = &fw_loader->static_loader; 2772*e65e175bSOded Gabbay cpu_msg_status_reg = static_loader->cpu_cmd_status_to_host_reg; 2773*e65e175bSOded Gabbay msg_to_cpu_reg = static_loader->kmd_msg_to_cpu_reg; 2774*e65e175bSOded Gabbay cpu_boot_dev_status0_reg = static_loader->cpu_boot_dev_status0_reg; 2775*e65e175bSOded Gabbay cpu_boot_dev_status1_reg = static_loader->cpu_boot_dev_status1_reg; 2776*e65e175bSOded Gabbay cpu_boot_status_reg = static_loader->cpu_boot_status_reg; 2777*e65e175bSOded Gabbay 2778*e65e175bSOded Gabbay dev_info(hdev->dev, "Going to wait for device boot (up to %lds)\n", 2779*e65e175bSOded Gabbay cpu_timeout / USEC_PER_SEC); 2780*e65e175bSOded Gabbay 2781*e65e175bSOded Gabbay /* Wait for boot FIT request */ 2782*e65e175bSOded Gabbay rc = hl_poll_timeout( 2783*e65e175bSOded Gabbay hdev, 2784*e65e175bSOded Gabbay cpu_boot_status_reg, 2785*e65e175bSOded Gabbay status, 2786*e65e175bSOded Gabbay status == CPU_BOOT_STATUS_WAITING_FOR_BOOT_FIT, 2787*e65e175bSOded Gabbay hdev->fw_poll_interval_usec, 2788*e65e175bSOded Gabbay fw_loader->boot_fit_timeout); 2789*e65e175bSOded Gabbay 2790*e65e175bSOded Gabbay if (rc) { 2791*e65e175bSOded Gabbay dev_dbg(hdev->dev, 2792*e65e175bSOded Gabbay "No boot fit request received, resuming boot\n"); 2793*e65e175bSOded Gabbay } else { 2794*e65e175bSOded Gabbay rc = hdev->asic_funcs->load_boot_fit_to_device(hdev); 2795*e65e175bSOded Gabbay if (rc) 2796*e65e175bSOded Gabbay goto out; 2797*e65e175bSOded Gabbay 2798*e65e175bSOded Gabbay /* Clear device CPU message status */ 2799*e65e175bSOded Gabbay WREG32(cpu_msg_status_reg, CPU_MSG_CLR); 2800*e65e175bSOded Gabbay 2801*e65e175bSOded Gabbay /* Signal device CPU that boot loader is ready */ 2802*e65e175bSOded Gabbay WREG32(msg_to_cpu_reg, KMD_MSG_FIT_RDY); 2803*e65e175bSOded Gabbay 2804*e65e175bSOded Gabbay /* Poll for CPU device ack */ 2805*e65e175bSOded Gabbay rc = hl_poll_timeout( 2806*e65e175bSOded Gabbay hdev, 2807*e65e175bSOded Gabbay cpu_msg_status_reg, 2808*e65e175bSOded Gabbay status, 2809*e65e175bSOded Gabbay status == CPU_MSG_OK, 2810*e65e175bSOded Gabbay hdev->fw_poll_interval_usec, 2811*e65e175bSOded Gabbay fw_loader->boot_fit_timeout); 2812*e65e175bSOded Gabbay 2813*e65e175bSOded Gabbay if (rc) { 2814*e65e175bSOded Gabbay dev_err(hdev->dev, 2815*e65e175bSOded Gabbay "Timeout waiting for boot fit load ack\n"); 2816*e65e175bSOded Gabbay goto out; 2817*e65e175bSOded Gabbay } 2818*e65e175bSOded Gabbay 2819*e65e175bSOded Gabbay /* Clear message */ 2820*e65e175bSOded Gabbay WREG32(msg_to_cpu_reg, KMD_MSG_NA); 2821*e65e175bSOded Gabbay } 2822*e65e175bSOded Gabbay 2823*e65e175bSOded Gabbay /* 2824*e65e175bSOded Gabbay * Make sure CPU boot-loader is running 2825*e65e175bSOded Gabbay * Note that the CPU_BOOT_STATUS_SRAM_AVAIL is generally set by Linux 2826*e65e175bSOded Gabbay * yet there is a debug scenario in which we loading uboot (without Linux) 2827*e65e175bSOded Gabbay * which at later stage is relocated to DRAM. In this case we expect 2828*e65e175bSOded Gabbay * uboot to set the CPU_BOOT_STATUS_SRAM_AVAIL and so we add it to the 2829*e65e175bSOded Gabbay * poll flags 2830*e65e175bSOded Gabbay */ 2831*e65e175bSOded Gabbay rc = hl_poll_timeout( 2832*e65e175bSOded Gabbay hdev, 2833*e65e175bSOded Gabbay cpu_boot_status_reg, 2834*e65e175bSOded Gabbay status, 2835*e65e175bSOded Gabbay (status == CPU_BOOT_STATUS_DRAM_RDY) || 2836*e65e175bSOded Gabbay (status == CPU_BOOT_STATUS_NIC_FW_RDY) || 2837*e65e175bSOded Gabbay (status == CPU_BOOT_STATUS_READY_TO_BOOT) || 2838*e65e175bSOded Gabbay (status == CPU_BOOT_STATUS_SRAM_AVAIL), 2839*e65e175bSOded Gabbay hdev->fw_poll_interval_usec, 2840*e65e175bSOded Gabbay cpu_timeout); 2841*e65e175bSOded Gabbay 2842*e65e175bSOded Gabbay dev_dbg(hdev->dev, "uboot status = %d\n", status); 2843*e65e175bSOded Gabbay 2844*e65e175bSOded Gabbay /* Read U-Boot version now in case we will later fail */ 2845*e65e175bSOded Gabbay hl_fw_static_read_device_fw_version(hdev, FW_COMP_BOOT_FIT); 2846*e65e175bSOded Gabbay 2847*e65e175bSOded Gabbay /* update state according to boot stage */ 2848*e65e175bSOded Gabbay hl_fw_boot_fit_update_state(hdev, cpu_boot_dev_status0_reg, 2849*e65e175bSOded Gabbay cpu_boot_dev_status1_reg); 2850*e65e175bSOded Gabbay 2851*e65e175bSOded Gabbay if (rc) { 2852*e65e175bSOded Gabbay detect_cpu_boot_status(hdev, status); 2853*e65e175bSOded Gabbay rc = -EIO; 2854*e65e175bSOded Gabbay goto out; 2855*e65e175bSOded Gabbay } 2856*e65e175bSOded Gabbay 2857*e65e175bSOded Gabbay /* Enable DRAM scrambling before Linux boot and after successful 2858*e65e175bSOded Gabbay * UBoot 2859*e65e175bSOded Gabbay */ 2860*e65e175bSOded Gabbay hdev->asic_funcs->init_cpu_scrambler_dram(hdev); 2861*e65e175bSOded Gabbay 2862*e65e175bSOded Gabbay if (!(hdev->fw_components & FW_TYPE_LINUX)) { 2863*e65e175bSOded Gabbay dev_info(hdev->dev, "Skip loading Linux F/W\n"); 2864*e65e175bSOded Gabbay rc = 0; 2865*e65e175bSOded Gabbay goto out; 2866*e65e175bSOded Gabbay } 2867*e65e175bSOded Gabbay 2868*e65e175bSOded Gabbay if (status == CPU_BOOT_STATUS_SRAM_AVAIL) { 2869*e65e175bSOded Gabbay rc = 0; 2870*e65e175bSOded Gabbay goto out; 2871*e65e175bSOded Gabbay } 2872*e65e175bSOded Gabbay 2873*e65e175bSOded Gabbay dev_info(hdev->dev, 2874*e65e175bSOded Gabbay "Loading firmware to device, may take some time...\n"); 2875*e65e175bSOded Gabbay 2876*e65e175bSOded Gabbay rc = hdev->asic_funcs->load_firmware_to_device(hdev); 2877*e65e175bSOded Gabbay if (rc) 2878*e65e175bSOded Gabbay goto out; 2879*e65e175bSOded Gabbay 2880*e65e175bSOded Gabbay if (fw_loader->skip_bmc) { 2881*e65e175bSOded Gabbay WREG32(msg_to_cpu_reg, KMD_MSG_SKIP_BMC); 2882*e65e175bSOded Gabbay 2883*e65e175bSOded Gabbay rc = hl_poll_timeout( 2884*e65e175bSOded Gabbay hdev, 2885*e65e175bSOded Gabbay cpu_boot_status_reg, 2886*e65e175bSOded Gabbay status, 2887*e65e175bSOded Gabbay (status == CPU_BOOT_STATUS_BMC_WAITING_SKIPPED), 2888*e65e175bSOded Gabbay hdev->fw_poll_interval_usec, 2889*e65e175bSOded Gabbay cpu_timeout); 2890*e65e175bSOded Gabbay 2891*e65e175bSOded Gabbay if (rc) { 2892*e65e175bSOded Gabbay dev_err(hdev->dev, 2893*e65e175bSOded Gabbay "Failed to get ACK on skipping BMC, %d\n", 2894*e65e175bSOded Gabbay status); 2895*e65e175bSOded Gabbay WREG32(msg_to_cpu_reg, KMD_MSG_NA); 2896*e65e175bSOded Gabbay rc = -EIO; 2897*e65e175bSOded Gabbay goto out; 2898*e65e175bSOded Gabbay } 2899*e65e175bSOded Gabbay } 2900*e65e175bSOded Gabbay 2901*e65e175bSOded Gabbay WREG32(msg_to_cpu_reg, KMD_MSG_FIT_RDY); 2902*e65e175bSOded Gabbay 2903*e65e175bSOded Gabbay rc = hl_poll_timeout( 2904*e65e175bSOded Gabbay hdev, 2905*e65e175bSOded Gabbay cpu_boot_status_reg, 2906*e65e175bSOded Gabbay status, 2907*e65e175bSOded Gabbay (status == CPU_BOOT_STATUS_SRAM_AVAIL), 2908*e65e175bSOded Gabbay hdev->fw_poll_interval_usec, 2909*e65e175bSOded Gabbay cpu_timeout); 2910*e65e175bSOded Gabbay 2911*e65e175bSOded Gabbay /* Clear message */ 2912*e65e175bSOded Gabbay WREG32(msg_to_cpu_reg, KMD_MSG_NA); 2913*e65e175bSOded Gabbay 2914*e65e175bSOded Gabbay if (rc) { 2915*e65e175bSOded Gabbay if (status == CPU_BOOT_STATUS_FIT_CORRUPTED) 2916*e65e175bSOded Gabbay dev_err(hdev->dev, 2917*e65e175bSOded Gabbay "Device reports FIT image is corrupted\n"); 2918*e65e175bSOded Gabbay else 2919*e65e175bSOded Gabbay dev_err(hdev->dev, 2920*e65e175bSOded Gabbay "Failed to load firmware to device, %d\n", 2921*e65e175bSOded Gabbay status); 2922*e65e175bSOded Gabbay 2923*e65e175bSOded Gabbay rc = -EIO; 2924*e65e175bSOded Gabbay goto out; 2925*e65e175bSOded Gabbay } 2926*e65e175bSOded Gabbay 2927*e65e175bSOded Gabbay rc = fw_read_errors(hdev, fw_loader->static_loader.boot_err0_reg, 2928*e65e175bSOded Gabbay fw_loader->static_loader.boot_err1_reg, 2929*e65e175bSOded Gabbay cpu_boot_dev_status0_reg, 2930*e65e175bSOded Gabbay cpu_boot_dev_status1_reg); 2931*e65e175bSOded Gabbay if (rc) 2932*e65e175bSOded Gabbay return rc; 2933*e65e175bSOded Gabbay 2934*e65e175bSOded Gabbay hl_fw_linux_update_state(hdev, cpu_boot_dev_status0_reg, 2935*e65e175bSOded Gabbay cpu_boot_dev_status1_reg); 2936*e65e175bSOded Gabbay 2937*e65e175bSOded Gabbay return 0; 2938*e65e175bSOded Gabbay 2939*e65e175bSOded Gabbay out: 2940*e65e175bSOded Gabbay fw_read_errors(hdev, fw_loader->static_loader.boot_err0_reg, 2941*e65e175bSOded Gabbay fw_loader->static_loader.boot_err1_reg, 2942*e65e175bSOded Gabbay cpu_boot_dev_status0_reg, 2943*e65e175bSOded Gabbay cpu_boot_dev_status1_reg); 2944*e65e175bSOded Gabbay 2945*e65e175bSOded Gabbay return rc; 2946*e65e175bSOded Gabbay } 2947*e65e175bSOded Gabbay 2948*e65e175bSOded Gabbay /** 2949*e65e175bSOded Gabbay * hl_fw_init_cpu - initialize the device CPU 2950*e65e175bSOded Gabbay * 2951*e65e175bSOded Gabbay * @hdev: pointer to the habanalabs device structure 2952*e65e175bSOded Gabbay * 2953*e65e175bSOded Gabbay * @return 0 on success, otherwise non-zero error code 2954*e65e175bSOded Gabbay * 2955*e65e175bSOded Gabbay * perform necessary initializations for device's CPU. takes into account if 2956*e65e175bSOded Gabbay * init protocol is static or dynamic. 2957*e65e175bSOded Gabbay */ 2958*e65e175bSOded Gabbay int hl_fw_init_cpu(struct hl_device *hdev) 2959*e65e175bSOded Gabbay { 2960*e65e175bSOded Gabbay struct asic_fixed_properties *prop = &hdev->asic_prop; 2961*e65e175bSOded Gabbay struct fw_load_mgr *fw_loader = &hdev->fw_loader; 2962*e65e175bSOded Gabbay 2963*e65e175bSOded Gabbay return prop->dynamic_fw_load ? 2964*e65e175bSOded Gabbay hl_fw_dynamic_init_cpu(hdev, fw_loader) : 2965*e65e175bSOded Gabbay hl_fw_static_init_cpu(hdev, fw_loader); 2966*e65e175bSOded Gabbay } 2967*e65e175bSOded Gabbay 2968*e65e175bSOded Gabbay void hl_fw_set_pll_profile(struct hl_device *hdev) 2969*e65e175bSOded Gabbay { 2970*e65e175bSOded Gabbay hl_fw_set_frequency(hdev, hdev->asic_prop.clk_pll_index, 2971*e65e175bSOded Gabbay hdev->asic_prop.max_freq_value); 2972*e65e175bSOded Gabbay } 2973*e65e175bSOded Gabbay 2974*e65e175bSOded Gabbay int hl_fw_get_clk_rate(struct hl_device *hdev, u32 *cur_clk, u32 *max_clk) 2975*e65e175bSOded Gabbay { 2976*e65e175bSOded Gabbay long value; 2977*e65e175bSOded Gabbay 2978*e65e175bSOded Gabbay if (!hl_device_operational(hdev, NULL)) 2979*e65e175bSOded Gabbay return -ENODEV; 2980*e65e175bSOded Gabbay 2981*e65e175bSOded Gabbay if (!hdev->pdev) { 2982*e65e175bSOded Gabbay *cur_clk = 0; 2983*e65e175bSOded Gabbay *max_clk = 0; 2984*e65e175bSOded Gabbay return 0; 2985*e65e175bSOded Gabbay } 2986*e65e175bSOded Gabbay 2987*e65e175bSOded Gabbay value = hl_fw_get_frequency(hdev, hdev->asic_prop.clk_pll_index, false); 2988*e65e175bSOded Gabbay 2989*e65e175bSOded Gabbay if (value < 0) { 2990*e65e175bSOded Gabbay dev_err(hdev->dev, "Failed to retrieve device max clock %ld\n", value); 2991*e65e175bSOded Gabbay return value; 2992*e65e175bSOded Gabbay } 2993*e65e175bSOded Gabbay 2994*e65e175bSOded Gabbay *max_clk = (value / 1000 / 1000); 2995*e65e175bSOded Gabbay 2996*e65e175bSOded Gabbay value = hl_fw_get_frequency(hdev, hdev->asic_prop.clk_pll_index, true); 2997*e65e175bSOded Gabbay 2998*e65e175bSOded Gabbay if (value < 0) { 2999*e65e175bSOded Gabbay dev_err(hdev->dev, "Failed to retrieve device current clock %ld\n", value); 3000*e65e175bSOded Gabbay return value; 3001*e65e175bSOded Gabbay } 3002*e65e175bSOded Gabbay 3003*e65e175bSOded Gabbay *cur_clk = (value / 1000 / 1000); 3004*e65e175bSOded Gabbay 3005*e65e175bSOded Gabbay return 0; 3006*e65e175bSOded Gabbay } 3007*e65e175bSOded Gabbay 3008*e65e175bSOded Gabbay long hl_fw_get_frequency(struct hl_device *hdev, u32 pll_index, bool curr) 3009*e65e175bSOded Gabbay { 3010*e65e175bSOded Gabbay struct cpucp_packet pkt; 3011*e65e175bSOded Gabbay u32 used_pll_idx; 3012*e65e175bSOded Gabbay u64 result; 3013*e65e175bSOded Gabbay int rc; 3014*e65e175bSOded Gabbay 3015*e65e175bSOded Gabbay rc = get_used_pll_index(hdev, pll_index, &used_pll_idx); 3016*e65e175bSOded Gabbay if (rc) 3017*e65e175bSOded Gabbay return rc; 3018*e65e175bSOded Gabbay 3019*e65e175bSOded Gabbay memset(&pkt, 0, sizeof(pkt)); 3020*e65e175bSOded Gabbay 3021*e65e175bSOded Gabbay if (curr) 3022*e65e175bSOded Gabbay pkt.ctl = cpu_to_le32(CPUCP_PACKET_FREQUENCY_CURR_GET << 3023*e65e175bSOded Gabbay CPUCP_PKT_CTL_OPCODE_SHIFT); 3024*e65e175bSOded Gabbay else 3025*e65e175bSOded Gabbay pkt.ctl = cpu_to_le32(CPUCP_PACKET_FREQUENCY_GET << CPUCP_PKT_CTL_OPCODE_SHIFT); 3026*e65e175bSOded Gabbay 3027*e65e175bSOded Gabbay pkt.pll_index = cpu_to_le32((u32)used_pll_idx); 3028*e65e175bSOded Gabbay 3029*e65e175bSOded Gabbay rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt), 0, &result); 3030*e65e175bSOded Gabbay 3031*e65e175bSOded Gabbay if (rc) { 3032*e65e175bSOded Gabbay dev_err(hdev->dev, "Failed to get frequency of PLL %d, error %d\n", 3033*e65e175bSOded Gabbay used_pll_idx, rc); 3034*e65e175bSOded Gabbay return rc; 3035*e65e175bSOded Gabbay } 3036*e65e175bSOded Gabbay 3037*e65e175bSOded Gabbay return (long) result; 3038*e65e175bSOded Gabbay } 3039*e65e175bSOded Gabbay 3040*e65e175bSOded Gabbay void hl_fw_set_frequency(struct hl_device *hdev, u32 pll_index, u64 freq) 3041*e65e175bSOded Gabbay { 3042*e65e175bSOded Gabbay struct cpucp_packet pkt; 3043*e65e175bSOded Gabbay u32 used_pll_idx; 3044*e65e175bSOded Gabbay int rc; 3045*e65e175bSOded Gabbay 3046*e65e175bSOded Gabbay rc = get_used_pll_index(hdev, pll_index, &used_pll_idx); 3047*e65e175bSOded Gabbay if (rc) 3048*e65e175bSOded Gabbay return; 3049*e65e175bSOded Gabbay 3050*e65e175bSOded Gabbay memset(&pkt, 0, sizeof(pkt)); 3051*e65e175bSOded Gabbay 3052*e65e175bSOded Gabbay pkt.ctl = cpu_to_le32(CPUCP_PACKET_FREQUENCY_SET << CPUCP_PKT_CTL_OPCODE_SHIFT); 3053*e65e175bSOded Gabbay pkt.pll_index = cpu_to_le32((u32)used_pll_idx); 3054*e65e175bSOded Gabbay pkt.value = cpu_to_le64(freq); 3055*e65e175bSOded Gabbay 3056*e65e175bSOded Gabbay rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt), 0, NULL); 3057*e65e175bSOded Gabbay 3058*e65e175bSOded Gabbay if (rc) 3059*e65e175bSOded Gabbay dev_err(hdev->dev, "Failed to set frequency to PLL %d, error %d\n", 3060*e65e175bSOded Gabbay used_pll_idx, rc); 3061*e65e175bSOded Gabbay } 3062*e65e175bSOded Gabbay 3063*e65e175bSOded Gabbay long hl_fw_get_max_power(struct hl_device *hdev) 3064*e65e175bSOded Gabbay { 3065*e65e175bSOded Gabbay struct cpucp_packet pkt; 3066*e65e175bSOded Gabbay u64 result; 3067*e65e175bSOded Gabbay int rc; 3068*e65e175bSOded Gabbay 3069*e65e175bSOded Gabbay memset(&pkt, 0, sizeof(pkt)); 3070*e65e175bSOded Gabbay 3071*e65e175bSOded Gabbay pkt.ctl = cpu_to_le32(CPUCP_PACKET_MAX_POWER_GET << CPUCP_PKT_CTL_OPCODE_SHIFT); 3072*e65e175bSOded Gabbay 3073*e65e175bSOded Gabbay rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt), 0, &result); 3074*e65e175bSOded Gabbay 3075*e65e175bSOded Gabbay if (rc) { 3076*e65e175bSOded Gabbay dev_err(hdev->dev, "Failed to get max power, error %d\n", rc); 3077*e65e175bSOded Gabbay return rc; 3078*e65e175bSOded Gabbay } 3079*e65e175bSOded Gabbay 3080*e65e175bSOded Gabbay return result; 3081*e65e175bSOded Gabbay } 3082*e65e175bSOded Gabbay 3083*e65e175bSOded Gabbay void hl_fw_set_max_power(struct hl_device *hdev) 3084*e65e175bSOded Gabbay { 3085*e65e175bSOded Gabbay struct cpucp_packet pkt; 3086*e65e175bSOded Gabbay int rc; 3087*e65e175bSOded Gabbay 3088*e65e175bSOded Gabbay /* TODO: remove this after simulator supports this packet */ 3089*e65e175bSOded Gabbay if (!hdev->pdev) 3090*e65e175bSOded Gabbay return; 3091*e65e175bSOded Gabbay 3092*e65e175bSOded Gabbay memset(&pkt, 0, sizeof(pkt)); 3093*e65e175bSOded Gabbay 3094*e65e175bSOded Gabbay pkt.ctl = cpu_to_le32(CPUCP_PACKET_MAX_POWER_SET << CPUCP_PKT_CTL_OPCODE_SHIFT); 3095*e65e175bSOded Gabbay pkt.value = cpu_to_le64(hdev->max_power); 3096*e65e175bSOded Gabbay 3097*e65e175bSOded Gabbay rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt), 0, NULL); 3098*e65e175bSOded Gabbay 3099*e65e175bSOded Gabbay if (rc) 3100*e65e175bSOded Gabbay dev_err(hdev->dev, "Failed to set max power, error %d\n", rc); 3101*e65e175bSOded Gabbay } 3102*e65e175bSOded Gabbay 3103*e65e175bSOded Gabbay static int hl_fw_get_sec_attest_data(struct hl_device *hdev, u32 packet_id, void *data, u32 size, 3104*e65e175bSOded Gabbay u32 nonce, u32 timeout) 3105*e65e175bSOded Gabbay { 3106*e65e175bSOded Gabbay struct cpucp_packet pkt = {}; 3107*e65e175bSOded Gabbay dma_addr_t req_dma_addr; 3108*e65e175bSOded Gabbay void *req_cpu_addr; 3109*e65e175bSOded Gabbay int rc; 3110*e65e175bSOded Gabbay 3111*e65e175bSOded Gabbay req_cpu_addr = hl_cpu_accessible_dma_pool_alloc(hdev, size, &req_dma_addr); 3112*e65e175bSOded Gabbay if (!req_cpu_addr) { 3113*e65e175bSOded Gabbay dev_err(hdev->dev, 3114*e65e175bSOded Gabbay "Failed to allocate DMA memory for CPU-CP packet %u\n", packet_id); 3115*e65e175bSOded Gabbay return -ENOMEM; 3116*e65e175bSOded Gabbay } 3117*e65e175bSOded Gabbay 3118*e65e175bSOded Gabbay memset(data, 0, size); 3119*e65e175bSOded Gabbay 3120*e65e175bSOded Gabbay pkt.ctl = cpu_to_le32(packet_id << CPUCP_PKT_CTL_OPCODE_SHIFT); 3121*e65e175bSOded Gabbay pkt.addr = cpu_to_le64(req_dma_addr); 3122*e65e175bSOded Gabbay pkt.data_max_size = cpu_to_le32(size); 3123*e65e175bSOded Gabbay pkt.nonce = cpu_to_le32(nonce); 3124*e65e175bSOded Gabbay 3125*e65e175bSOded Gabbay rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt), 3126*e65e175bSOded Gabbay timeout, NULL); 3127*e65e175bSOded Gabbay if (rc) { 3128*e65e175bSOded Gabbay dev_err(hdev->dev, 3129*e65e175bSOded Gabbay "Failed to handle CPU-CP pkt %u, error %d\n", packet_id, rc); 3130*e65e175bSOded Gabbay goto out; 3131*e65e175bSOded Gabbay } 3132*e65e175bSOded Gabbay 3133*e65e175bSOded Gabbay memcpy(data, req_cpu_addr, size); 3134*e65e175bSOded Gabbay 3135*e65e175bSOded Gabbay out: 3136*e65e175bSOded Gabbay hl_cpu_accessible_dma_pool_free(hdev, size, req_cpu_addr); 3137*e65e175bSOded Gabbay 3138*e65e175bSOded Gabbay return rc; 3139*e65e175bSOded Gabbay } 3140*e65e175bSOded Gabbay 3141*e65e175bSOded Gabbay int hl_fw_get_sec_attest_info(struct hl_device *hdev, struct cpucp_sec_attest_info *sec_attest_info, 3142*e65e175bSOded Gabbay u32 nonce) 3143*e65e175bSOded Gabbay { 3144*e65e175bSOded Gabbay return hl_fw_get_sec_attest_data(hdev, CPUCP_PACKET_SEC_ATTEST_GET, sec_attest_info, 3145*e65e175bSOded Gabbay sizeof(struct cpucp_sec_attest_info), nonce, 3146*e65e175bSOded Gabbay HL_CPUCP_SEC_ATTEST_INFO_TINEOUT_USEC); 3147*e65e175bSOded Gabbay } 3148*e65e175bSOded Gabbay 3149*e65e175bSOded Gabbay int hl_fw_send_generic_request(struct hl_device *hdev, enum hl_passthrough_type sub_opcode, 3150*e65e175bSOded Gabbay dma_addr_t buff, u32 *size) 3151*e65e175bSOded Gabbay { 3152*e65e175bSOded Gabbay struct cpucp_packet pkt = {0}; 3153*e65e175bSOded Gabbay u64 result; 3154*e65e175bSOded Gabbay int rc = 0; 3155*e65e175bSOded Gabbay 3156*e65e175bSOded Gabbay pkt.ctl = cpu_to_le32(CPUCP_PACKET_GENERIC_PASSTHROUGH << CPUCP_PKT_CTL_OPCODE_SHIFT); 3157*e65e175bSOded Gabbay pkt.addr = cpu_to_le64(buff); 3158*e65e175bSOded Gabbay pkt.data_max_size = cpu_to_le32(*size); 3159*e65e175bSOded Gabbay pkt.pkt_subidx = cpu_to_le32(sub_opcode); 3160*e65e175bSOded Gabbay 3161*e65e175bSOded Gabbay rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *)&pkt, sizeof(pkt), 3162*e65e175bSOded Gabbay HL_CPUCP_INFO_TIMEOUT_USEC, &result); 3163*e65e175bSOded Gabbay if (rc) 3164*e65e175bSOded Gabbay dev_err(hdev->dev, "failed to send CPUCP data of generic fw pkt\n"); 3165*e65e175bSOded Gabbay else 3166*e65e175bSOded Gabbay dev_dbg(hdev->dev, "generic pkt was successful, result: 0x%llx\n", result); 3167*e65e175bSOded Gabbay 3168*e65e175bSOded Gabbay *size = (u32)result; 3169*e65e175bSOded Gabbay 3170*e65e175bSOded Gabbay return rc; 3171*e65e175bSOded Gabbay } 3172