1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2022-2024, Advanced Micro Devices, Inc. 4 */ 5 6 #include <drm/drm_device.h> 7 #include <drm/drm_gem_shmem_helper.h> 8 #include <drm/drm_managed.h> 9 #include <drm/drm_print.h> 10 #include <drm/gpu_scheduler.h> 11 #include <linux/bitfield.h> 12 #include <linux/iopoll.h> 13 14 #include "aie2_pci.h" 15 #include "amdxdna_mailbox.h" 16 #include "amdxdna_pci_drv.h" 17 18 #define PSP_STATUS_READY BIT(31) 19 20 /* PSP commands */ 21 #define PSP_VALIDATE 1 22 #define PSP_START 2 23 #define PSP_RELEASE_TMR 3 24 25 /* PSP special arguments */ 26 #define PSP_START_COPY_FW 1 27 28 /* PSP response error code */ 29 #define PSP_ERROR_CANCEL 0xFFFF0002 30 #define PSP_ERROR_BAD_STATE 0xFFFF0007 31 32 #define PSP_FW_ALIGN 0x10000 33 #define PSP_POLL_INTERVAL 20000 /* us */ 34 #define PSP_POLL_TIMEOUT 1000000 /* us */ 35 36 #define PSP_REG(p, reg) ((p)->psp_regs[reg]) 37 38 struct psp_device { 39 struct drm_device *ddev; 40 struct psp_config conf; 41 u32 fw_buf_sz; 42 u64 fw_paddr; 43 void *fw_buffer; 44 void __iomem *psp_regs[PSP_MAX_REGS]; 45 }; 46 47 static int psp_exec(struct psp_device *psp, u32 *reg_vals) 48 { 49 u32 resp_code; 50 int ret, i; 51 u32 ready; 52 53 /* Write command and argument registers */ 54 for (i = 0; i < PSP_NUM_IN_REGS; i++) 55 writel(reg_vals[i], PSP_REG(psp, i)); 56 57 /* clear and set PSP INTR register to kick off */ 58 writel(0, PSP_REG(psp, PSP_INTR_REG)); 59 writel(1, PSP_REG(psp, PSP_INTR_REG)); 60 61 /* PSP should be busy. Wait for ready, so we know task is done. */ 62 ret = readx_poll_timeout(readl, PSP_REG(psp, PSP_STATUS_REG), ready, 63 FIELD_GET(PSP_STATUS_READY, ready), 64 PSP_POLL_INTERVAL, PSP_POLL_TIMEOUT); 65 if (ret) { 66 drm_err(psp->ddev, "PSP is not ready, ret 0x%x", ret); 67 return ret; 68 } 69 70 resp_code = readl(PSP_REG(psp, PSP_RESP_REG)); 71 if (resp_code) { 72 drm_err(psp->ddev, "fw return error 0x%x", resp_code); 73 return -EIO; 74 } 75 76 return 0; 77 } 78 79 void aie2_psp_stop(struct psp_device *psp) 80 { 81 u32 reg_vals[PSP_NUM_IN_REGS] = { PSP_RELEASE_TMR, }; 82 int ret; 83 84 ret = psp_exec(psp, reg_vals); 85 if (ret) 86 drm_err(psp->ddev, "release tmr failed, ret %d", ret); 87 } 88 89 int aie2_psp_start(struct psp_device *psp) 90 { 91 u32 reg_vals[PSP_NUM_IN_REGS]; 92 int ret; 93 94 reg_vals[0] = PSP_VALIDATE; 95 reg_vals[1] = lower_32_bits(psp->fw_paddr); 96 reg_vals[2] = upper_32_bits(psp->fw_paddr); 97 reg_vals[3] = psp->fw_buf_sz; 98 99 ret = psp_exec(psp, reg_vals); 100 if (ret) { 101 drm_err(psp->ddev, "failed to validate fw, ret %d", ret); 102 return ret; 103 } 104 105 memset(reg_vals, 0, sizeof(reg_vals)); 106 reg_vals[0] = PSP_START; 107 reg_vals[1] = PSP_START_COPY_FW; 108 ret = psp_exec(psp, reg_vals); 109 if (ret) { 110 drm_err(psp->ddev, "failed to start fw, ret %d", ret); 111 return ret; 112 } 113 114 return 0; 115 } 116 117 struct psp_device *aie2m_psp_create(struct drm_device *ddev, struct psp_config *conf) 118 { 119 struct psp_device *psp; 120 u64 offset; 121 122 psp = drmm_kzalloc(ddev, sizeof(*psp), GFP_KERNEL); 123 if (!psp) 124 return NULL; 125 126 psp->ddev = ddev; 127 memcpy(psp->psp_regs, conf->psp_regs, sizeof(psp->psp_regs)); 128 129 psp->fw_buf_sz = ALIGN(conf->fw_size, PSP_FW_ALIGN) + PSP_FW_ALIGN; 130 psp->fw_buffer = drmm_kmalloc(ddev, psp->fw_buf_sz, GFP_KERNEL); 131 if (!psp->fw_buffer) { 132 drm_err(ddev, "no memory for fw buffer"); 133 return NULL; 134 } 135 136 /* 137 * AMD Platform Security Processor(PSP) requires host physical 138 * address to load NPU firmware. 139 */ 140 psp->fw_paddr = virt_to_phys(psp->fw_buffer); 141 offset = ALIGN(psp->fw_paddr, PSP_FW_ALIGN) - psp->fw_paddr; 142 psp->fw_paddr += offset; 143 memcpy(psp->fw_buffer + offset, conf->fw_buf, conf->fw_size); 144 145 return psp; 146 } 147