1fb4d8502Sjsg /* 2fb4d8502Sjsg * Copyright 2016 Advanced Micro Devices, Inc. 3fb4d8502Sjsg * 4fb4d8502Sjsg * Permission is hereby granted, free of charge, to any person obtaining a 5fb4d8502Sjsg * copy of this software and associated documentation files (the "Software"), 6fb4d8502Sjsg * to deal in the Software without restriction, including without limitation 7fb4d8502Sjsg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8fb4d8502Sjsg * and/or sell copies of the Software, and to permit persons to whom the 9fb4d8502Sjsg * Software is furnished to do so, subject to the following conditions: 10fb4d8502Sjsg * 11fb4d8502Sjsg * The above copyright notice and this permission notice shall be included in 12fb4d8502Sjsg * all copies or substantial portions of the Software. 13fb4d8502Sjsg * 14fb4d8502Sjsg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15fb4d8502Sjsg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16fb4d8502Sjsg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17fb4d8502Sjsg * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18fb4d8502Sjsg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19fb4d8502Sjsg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20fb4d8502Sjsg * OTHER DEALINGS IN THE SOFTWARE. 21fb4d8502Sjsg * 22fb4d8502Sjsg * Author: Huang Rui 23fb4d8502Sjsg * 24fb4d8502Sjsg */ 25fb4d8502Sjsg 26fb4d8502Sjsg #include <linux/firmware.h> 275ca02815Sjsg #include <drm/drm_drv.h> 28c349dbc7Sjsg 29fb4d8502Sjsg #include "amdgpu.h" 30fb4d8502Sjsg #include "amdgpu_psp.h" 31fb4d8502Sjsg #include "amdgpu_ucode.h" 325ca02815Sjsg #include "amdgpu_xgmi.h" 33fb4d8502Sjsg #include "soc15_common.h" 34fb4d8502Sjsg #include "psp_v3_1.h" 35fb4d8502Sjsg #include "psp_v10_0.h" 36c349dbc7Sjsg #include "psp_v11_0.h" 375ca02815Sjsg #include "psp_v11_0_8.h" 38c349dbc7Sjsg #include "psp_v12_0.h" 395ca02815Sjsg #include "psp_v13_0.h" 401bb76ff1Sjsg #include "psp_v13_0_4.h" 41c349dbc7Sjsg 42c349dbc7Sjsg #include "amdgpu_ras.h" 435ca02815Sjsg #include "amdgpu_securedisplay.h" 445ca02815Sjsg #include "amdgpu_atomfirmware.h" 45fb4d8502Sjsg 461bb76ff1Sjsg #define AMD_VBIOS_FILE_MAX_SIZE_B (1024*1024*3) 471bb76ff1Sjsg 48ad8b1aafSjsg static int psp_load_smu_fw(struct psp_context *psp); 491bb76ff1Sjsg static int psp_rap_terminate(struct psp_context *psp); 501bb76ff1Sjsg static int psp_securedisplay_terminate(struct psp_context *psp); 51ad8b1aafSjsg 52f005ef32Sjsg static int psp_ring_init(struct psp_context *psp, 53f005ef32Sjsg enum psp_ring_type ring_type) 54f005ef32Sjsg { 55f005ef32Sjsg int ret = 0; 56f005ef32Sjsg struct psp_ring *ring; 57f005ef32Sjsg struct amdgpu_device *adev = psp->adev; 58f005ef32Sjsg 59f005ef32Sjsg ring = &psp->km_ring; 60f005ef32Sjsg 61f005ef32Sjsg ring->ring_type = ring_type; 62f005ef32Sjsg 63f005ef32Sjsg /* allocate 4k Page of Local Frame Buffer memory for ring */ 64f005ef32Sjsg ring->ring_size = 0x1000; 65f005ef32Sjsg ret = amdgpu_bo_create_kernel(adev, ring->ring_size, PAGE_SIZE, 66f005ef32Sjsg AMDGPU_GEM_DOMAIN_VRAM | 67f005ef32Sjsg AMDGPU_GEM_DOMAIN_GTT, 68f005ef32Sjsg &adev->firmware.rbuf, 69f005ef32Sjsg &ring->ring_mem_mc_addr, 70f005ef32Sjsg (void **)&ring->ring_mem); 71f005ef32Sjsg if (ret) { 72f005ef32Sjsg ring->ring_size = 0; 73f005ef32Sjsg return ret; 74f005ef32Sjsg } 75f005ef32Sjsg 76f005ef32Sjsg return 0; 77f005ef32Sjsg } 78f005ef32Sjsg 79c349dbc7Sjsg /* 80c349dbc7Sjsg * Due to DF Cstate management centralized to PMFW, the firmware 81c349dbc7Sjsg * loading sequence will be updated as below: 82c349dbc7Sjsg * - Load KDB 83c349dbc7Sjsg * - Load SYS_DRV 84c349dbc7Sjsg * - Load tOS 85c349dbc7Sjsg * - Load PMFW 86c349dbc7Sjsg * - Setup TMR 87c349dbc7Sjsg * - Load other non-psp fw 88c349dbc7Sjsg * - Load ASD 89c349dbc7Sjsg * - Load XGMI/RAS/HDCP/DTM TA if any 90c349dbc7Sjsg * 91c349dbc7Sjsg * This new sequence is required for 925ca02815Sjsg * - Arcturus and onwards 93c349dbc7Sjsg */ 94c349dbc7Sjsg static void psp_check_pmfw_centralized_cstate_management(struct psp_context *psp) 95c349dbc7Sjsg { 96c349dbc7Sjsg struct amdgpu_device *adev = psp->adev; 97c349dbc7Sjsg 981bb76ff1Sjsg if (amdgpu_sriov_vf(adev)) { 99c349dbc7Sjsg psp->pmfw_centralized_cstate_management = false; 100c349dbc7Sjsg return; 1011bb76ff1Sjsg } 102c349dbc7Sjsg 1031bb76ff1Sjsg switch (adev->ip_versions[MP0_HWIP][0]) { 1041bb76ff1Sjsg case IP_VERSION(11, 0, 0): 1051bb76ff1Sjsg case IP_VERSION(11, 0, 4): 1061bb76ff1Sjsg case IP_VERSION(11, 0, 5): 1071bb76ff1Sjsg case IP_VERSION(11, 0, 7): 1081bb76ff1Sjsg case IP_VERSION(11, 0, 9): 1091bb76ff1Sjsg case IP_VERSION(11, 0, 11): 1101bb76ff1Sjsg case IP_VERSION(11, 0, 12): 1111bb76ff1Sjsg case IP_VERSION(11, 0, 13): 1121bb76ff1Sjsg case IP_VERSION(13, 0, 0): 1131bb76ff1Sjsg case IP_VERSION(13, 0, 2): 1141bb76ff1Sjsg case IP_VERSION(13, 0, 7): 115c349dbc7Sjsg psp->pmfw_centralized_cstate_management = true; 1161bb76ff1Sjsg break; 1171bb76ff1Sjsg default: 1181bb76ff1Sjsg psp->pmfw_centralized_cstate_management = false; 1191bb76ff1Sjsg break; 1201bb76ff1Sjsg } 121c349dbc7Sjsg } 122c349dbc7Sjsg 123f005ef32Sjsg static int psp_init_sriov_microcode(struct psp_context *psp) 124f005ef32Sjsg { 125f005ef32Sjsg struct amdgpu_device *adev = psp->adev; 126f005ef32Sjsg char ucode_prefix[30]; 127f005ef32Sjsg int ret = 0; 128f005ef32Sjsg 129f005ef32Sjsg amdgpu_ucode_ip_version_decode(adev, MP0_HWIP, ucode_prefix, sizeof(ucode_prefix)); 130f005ef32Sjsg 131f005ef32Sjsg switch (adev->ip_versions[MP0_HWIP][0]) { 132f005ef32Sjsg case IP_VERSION(9, 0, 0): 133f005ef32Sjsg case IP_VERSION(11, 0, 7): 134f005ef32Sjsg case IP_VERSION(11, 0, 9): 135f005ef32Sjsg adev->virt.autoload_ucode_id = AMDGPU_UCODE_ID_CP_MEC2; 136f005ef32Sjsg ret = psp_init_cap_microcode(psp, ucode_prefix); 137f005ef32Sjsg break; 138f005ef32Sjsg case IP_VERSION(13, 0, 2): 139f005ef32Sjsg adev->virt.autoload_ucode_id = AMDGPU_UCODE_ID_CP_MEC2; 140f005ef32Sjsg ret = psp_init_cap_microcode(psp, ucode_prefix); 141f005ef32Sjsg ret &= psp_init_ta_microcode(psp, ucode_prefix); 142f005ef32Sjsg break; 143f005ef32Sjsg case IP_VERSION(13, 0, 0): 144f005ef32Sjsg adev->virt.autoload_ucode_id = 0; 145f005ef32Sjsg break; 146f005ef32Sjsg case IP_VERSION(13, 0, 6): 147f005ef32Sjsg ret = psp_init_cap_microcode(psp, ucode_prefix); 148f005ef32Sjsg ret &= psp_init_ta_microcode(psp, ucode_prefix); 149f005ef32Sjsg break; 150f005ef32Sjsg case IP_VERSION(13, 0, 10): 151f005ef32Sjsg adev->virt.autoload_ucode_id = AMDGPU_UCODE_ID_CP_MES1_DATA; 152f005ef32Sjsg ret = psp_init_cap_microcode(psp, ucode_prefix); 153f005ef32Sjsg break; 154f005ef32Sjsg default: 155f005ef32Sjsg return -EINVAL; 156f005ef32Sjsg } 157f005ef32Sjsg return ret; 158f005ef32Sjsg } 159f005ef32Sjsg 160fb4d8502Sjsg static int psp_early_init(void *handle) 161fb4d8502Sjsg { 162fb4d8502Sjsg struct amdgpu_device *adev = (struct amdgpu_device *)handle; 163c8a1e887Sjsg struct psp_context *psp = &adev->psp; 164fb4d8502Sjsg 1651bb76ff1Sjsg switch (adev->ip_versions[MP0_HWIP][0]) { 1661bb76ff1Sjsg case IP_VERSION(9, 0, 0): 167fb4d8502Sjsg psp_v3_1_set_psp_funcs(psp); 168c349dbc7Sjsg psp->autoload_supported = false; 169fb4d8502Sjsg break; 1701bb76ff1Sjsg case IP_VERSION(10, 0, 0): 1711bb76ff1Sjsg case IP_VERSION(10, 0, 1): 172fb4d8502Sjsg psp_v10_0_set_psp_funcs(psp); 173c349dbc7Sjsg psp->autoload_supported = false; 174c349dbc7Sjsg break; 1751bb76ff1Sjsg case IP_VERSION(11, 0, 2): 1761bb76ff1Sjsg case IP_VERSION(11, 0, 4): 177c349dbc7Sjsg psp_v11_0_set_psp_funcs(psp); 178c349dbc7Sjsg psp->autoload_supported = false; 179c349dbc7Sjsg break; 1801bb76ff1Sjsg case IP_VERSION(11, 0, 0): 181f005ef32Sjsg case IP_VERSION(11, 0, 7): 182f005ef32Sjsg adev->psp.sup_pd_fw_up = !amdgpu_sriov_vf(adev); 183f005ef32Sjsg fallthrough; 1841bb76ff1Sjsg case IP_VERSION(11, 0, 5): 1851bb76ff1Sjsg case IP_VERSION(11, 0, 9): 1861bb76ff1Sjsg case IP_VERSION(11, 0, 11): 1871bb76ff1Sjsg case IP_VERSION(11, 5, 0): 1881bb76ff1Sjsg case IP_VERSION(11, 0, 12): 1891bb76ff1Sjsg case IP_VERSION(11, 0, 13): 190c349dbc7Sjsg psp_v11_0_set_psp_funcs(psp); 191c349dbc7Sjsg psp->autoload_supported = true; 192c349dbc7Sjsg break; 1931bb76ff1Sjsg case IP_VERSION(11, 0, 3): 1941bb76ff1Sjsg case IP_VERSION(12, 0, 1): 195c349dbc7Sjsg psp_v12_0_set_psp_funcs(psp); 196fb4d8502Sjsg break; 1971bb76ff1Sjsg case IP_VERSION(13, 0, 2): 198f005ef32Sjsg case IP_VERSION(13, 0, 6): 1995ca02815Sjsg psp_v13_0_set_psp_funcs(psp); 2005ca02815Sjsg break; 2011bb76ff1Sjsg case IP_VERSION(13, 0, 1): 2021bb76ff1Sjsg case IP_VERSION(13, 0, 3): 2031bb76ff1Sjsg case IP_VERSION(13, 0, 5): 2041bb76ff1Sjsg case IP_VERSION(13, 0, 8): 205d424a9b5Sjsg case IP_VERSION(13, 0, 11): 206f005ef32Sjsg case IP_VERSION(14, 0, 0): 2075ca02815Sjsg psp_v13_0_set_psp_funcs(psp); 2085ca02815Sjsg psp->autoload_supported = true; 2095ca02815Sjsg break; 2101bb76ff1Sjsg case IP_VERSION(11, 0, 8): 2115ca02815Sjsg if (adev->apu_flags & AMD_APU_IS_CYAN_SKILLFISH2) { 2125ca02815Sjsg psp_v11_0_8_set_psp_funcs(psp); 2135ca02815Sjsg psp->autoload_supported = false; 2145ca02815Sjsg } 2155ca02815Sjsg break; 2161bb76ff1Sjsg case IP_VERSION(13, 0, 0): 2171bb76ff1Sjsg case IP_VERSION(13, 0, 7): 218f005ef32Sjsg case IP_VERSION(13, 0, 10): 2191bb76ff1Sjsg psp_v13_0_set_psp_funcs(psp); 2201bb76ff1Sjsg psp->autoload_supported = true; 221f005ef32Sjsg adev->psp.sup_ifwi_up = !amdgpu_sriov_vf(adev); 2221bb76ff1Sjsg break; 2231bb76ff1Sjsg case IP_VERSION(13, 0, 4): 2241bb76ff1Sjsg psp_v13_0_4_set_psp_funcs(psp); 2251bb76ff1Sjsg psp->autoload_supported = true; 2261bb76ff1Sjsg break; 227fb4d8502Sjsg default: 228fb4d8502Sjsg return -EINVAL; 229fb4d8502Sjsg } 230fb4d8502Sjsg 231fb4d8502Sjsg psp->adev = adev; 232fb4d8502Sjsg 233c349dbc7Sjsg psp_check_pmfw_centralized_cstate_management(psp); 234fb4d8502Sjsg 235f005ef32Sjsg if (amdgpu_sriov_vf(adev)) 236f005ef32Sjsg return psp_init_sriov_microcode(psp); 237f005ef32Sjsg else 238f005ef32Sjsg return psp_init_microcode(psp); 239c8a1e887Sjsg } 240c8a1e887Sjsg 2411bb76ff1Sjsg void psp_ta_free_shared_buf(struct ta_mem_context *mem_ctx) 2421bb76ff1Sjsg { 2431bb76ff1Sjsg amdgpu_bo_free_kernel(&mem_ctx->shared_bo, &mem_ctx->shared_mc_addr, 2441bb76ff1Sjsg &mem_ctx->shared_buf); 2451bb76ff1Sjsg mem_ctx->shared_bo = NULL; 2461bb76ff1Sjsg } 2471bb76ff1Sjsg 2481bb76ff1Sjsg static void psp_free_shared_bufs(struct psp_context *psp) 2491bb76ff1Sjsg { 2501bb76ff1Sjsg void *tmr_buf; 2511bb76ff1Sjsg void **pptr; 2521bb76ff1Sjsg 2531bb76ff1Sjsg /* free TMR memory buffer */ 2541bb76ff1Sjsg pptr = amdgpu_sriov_vf(psp->adev) ? &tmr_buf : NULL; 2551bb76ff1Sjsg amdgpu_bo_free_kernel(&psp->tmr_bo, &psp->tmr_mc_addr, pptr); 2561bb76ff1Sjsg psp->tmr_bo = NULL; 2571bb76ff1Sjsg 2581bb76ff1Sjsg /* free xgmi shared memory */ 2591bb76ff1Sjsg psp_ta_free_shared_buf(&psp->xgmi_context.context.mem_context); 2601bb76ff1Sjsg 2611bb76ff1Sjsg /* free ras shared memory */ 2621bb76ff1Sjsg psp_ta_free_shared_buf(&psp->ras_context.context.mem_context); 2631bb76ff1Sjsg 2641bb76ff1Sjsg /* free hdcp shared memory */ 2651bb76ff1Sjsg psp_ta_free_shared_buf(&psp->hdcp_context.context.mem_context); 2661bb76ff1Sjsg 2671bb76ff1Sjsg /* free dtm shared memory */ 2681bb76ff1Sjsg psp_ta_free_shared_buf(&psp->dtm_context.context.mem_context); 2691bb76ff1Sjsg 2701bb76ff1Sjsg /* free rap shared memory */ 2711bb76ff1Sjsg psp_ta_free_shared_buf(&psp->rap_context.context.mem_context); 2721bb76ff1Sjsg 2731bb76ff1Sjsg /* free securedisplay shared memory */ 2741bb76ff1Sjsg psp_ta_free_shared_buf(&psp->securedisplay_context.context.mem_context); 2751bb76ff1Sjsg 2761bb76ff1Sjsg 2771bb76ff1Sjsg } 2781bb76ff1Sjsg 279ad8b1aafSjsg static void psp_memory_training_fini(struct psp_context *psp) 280ad8b1aafSjsg { 281ad8b1aafSjsg struct psp_memory_training_context *ctx = &psp->mem_train_ctx; 282ad8b1aafSjsg 283ad8b1aafSjsg ctx->init = PSP_MEM_TRAIN_NOT_SUPPORT; 284ad8b1aafSjsg kfree(ctx->sys_cache); 285ad8b1aafSjsg ctx->sys_cache = NULL; 286ad8b1aafSjsg } 287ad8b1aafSjsg 288ad8b1aafSjsg static int psp_memory_training_init(struct psp_context *psp) 289ad8b1aafSjsg { 290ad8b1aafSjsg int ret; 291ad8b1aafSjsg struct psp_memory_training_context *ctx = &psp->mem_train_ctx; 292ad8b1aafSjsg 293ad8b1aafSjsg if (ctx->init != PSP_MEM_TRAIN_RESERVE_SUCCESS) { 294ad8b1aafSjsg DRM_DEBUG("memory training is not supported!\n"); 295ad8b1aafSjsg return 0; 296ad8b1aafSjsg } 297ad8b1aafSjsg 298ad8b1aafSjsg ctx->sys_cache = kzalloc(ctx->train_data_size, GFP_KERNEL); 299ad8b1aafSjsg if (ctx->sys_cache == NULL) { 300ad8b1aafSjsg DRM_ERROR("alloc mem_train_ctx.sys_cache failed!\n"); 301ad8b1aafSjsg ret = -ENOMEM; 302ad8b1aafSjsg goto Err_out; 303ad8b1aafSjsg } 304ad8b1aafSjsg 305ad8b1aafSjsg DRM_DEBUG("train_data_size:%llx,p2c_train_data_offset:%llx,c2p_train_data_offset:%llx.\n", 306ad8b1aafSjsg ctx->train_data_size, 307ad8b1aafSjsg ctx->p2c_train_data_offset, 308ad8b1aafSjsg ctx->c2p_train_data_offset); 309ad8b1aafSjsg ctx->init = PSP_MEM_TRAIN_INIT_SUCCESS; 310ad8b1aafSjsg return 0; 311ad8b1aafSjsg 312ad8b1aafSjsg Err_out: 313ad8b1aafSjsg psp_memory_training_fini(psp); 314ad8b1aafSjsg return ret; 315ad8b1aafSjsg } 316ad8b1aafSjsg 3175ca02815Sjsg /* 3185ca02815Sjsg * Helper funciton to query psp runtime database entry 3195ca02815Sjsg * 3205ca02815Sjsg * @adev: amdgpu_device pointer 3215ca02815Sjsg * @entry_type: the type of psp runtime database entry 3225ca02815Sjsg * @db_entry: runtime database entry pointer 3235ca02815Sjsg * 3245ca02815Sjsg * Return false if runtime database doesn't exit or entry is invalid 3255ca02815Sjsg * or true if the specific database entry is found, and copy to @db_entry 3265ca02815Sjsg */ 3275ca02815Sjsg static bool psp_get_runtime_db_entry(struct amdgpu_device *adev, 3285ca02815Sjsg enum psp_runtime_entry_type entry_type, 3295ca02815Sjsg void *db_entry) 3305ca02815Sjsg { 3315ca02815Sjsg uint64_t db_header_pos, db_dir_pos; 3325ca02815Sjsg struct psp_runtime_data_header db_header = {0}; 3335ca02815Sjsg struct psp_runtime_data_directory db_dir = {0}; 3345ca02815Sjsg bool ret = false; 3355ca02815Sjsg int i; 3365ca02815Sjsg 337f005ef32Sjsg if (adev->ip_versions[MP0_HWIP][0] == IP_VERSION(13, 0, 6)) 338f005ef32Sjsg return false; 339f005ef32Sjsg 3405ca02815Sjsg db_header_pos = adev->gmc.mc_vram_size - PSP_RUNTIME_DB_OFFSET; 3415ca02815Sjsg db_dir_pos = db_header_pos + sizeof(struct psp_runtime_data_header); 3425ca02815Sjsg 3435ca02815Sjsg /* read runtime db header from vram */ 3445ca02815Sjsg amdgpu_device_vram_access(adev, db_header_pos, (uint32_t *)&db_header, 3455ca02815Sjsg sizeof(struct psp_runtime_data_header), false); 3465ca02815Sjsg 3475ca02815Sjsg if (db_header.cookie != PSP_RUNTIME_DB_COOKIE_ID) { 3485ca02815Sjsg /* runtime db doesn't exist, exit */ 349f005ef32Sjsg dev_dbg(adev->dev, "PSP runtime database doesn't exist\n"); 3505ca02815Sjsg return false; 3515ca02815Sjsg } 3525ca02815Sjsg 3535ca02815Sjsg /* read runtime database entry from vram */ 3545ca02815Sjsg amdgpu_device_vram_access(adev, db_dir_pos, (uint32_t *)&db_dir, 3555ca02815Sjsg sizeof(struct psp_runtime_data_directory), false); 3565ca02815Sjsg 3575ca02815Sjsg if (db_dir.entry_count >= PSP_RUNTIME_DB_DIAG_ENTRY_MAX_COUNT) { 3585ca02815Sjsg /* invalid db entry count, exit */ 3595ca02815Sjsg dev_warn(adev->dev, "Invalid PSP runtime database entry count\n"); 3605ca02815Sjsg return false; 3615ca02815Sjsg } 3625ca02815Sjsg 3635ca02815Sjsg /* look up for requested entry type */ 3645ca02815Sjsg for (i = 0; i < db_dir.entry_count && !ret; i++) { 3655ca02815Sjsg if (db_dir.entry_list[i].entry_type == entry_type) { 3665ca02815Sjsg switch (entry_type) { 3675ca02815Sjsg case PSP_RUNTIME_ENTRY_TYPE_BOOT_CONFIG: 3685ca02815Sjsg if (db_dir.entry_list[i].size < sizeof(struct psp_runtime_boot_cfg_entry)) { 3695ca02815Sjsg /* invalid db entry size */ 3701bb76ff1Sjsg dev_warn(adev->dev, "Invalid PSP runtime database boot cfg entry size\n"); 3715ca02815Sjsg return false; 3725ca02815Sjsg } 3735ca02815Sjsg /* read runtime database entry */ 3745ca02815Sjsg amdgpu_device_vram_access(adev, db_header_pos + db_dir.entry_list[i].offset, 3755ca02815Sjsg (uint32_t *)db_entry, sizeof(struct psp_runtime_boot_cfg_entry), false); 3765ca02815Sjsg ret = true; 3775ca02815Sjsg break; 3781bb76ff1Sjsg case PSP_RUNTIME_ENTRY_TYPE_PPTABLE_ERR_STATUS: 3791bb76ff1Sjsg if (db_dir.entry_list[i].size < sizeof(struct psp_runtime_scpm_entry)) { 3801bb76ff1Sjsg /* invalid db entry size */ 3811bb76ff1Sjsg dev_warn(adev->dev, "Invalid PSP runtime database scpm entry size\n"); 3821bb76ff1Sjsg return false; 3831bb76ff1Sjsg } 3841bb76ff1Sjsg /* read runtime database entry */ 3851bb76ff1Sjsg amdgpu_device_vram_access(adev, db_header_pos + db_dir.entry_list[i].offset, 3861bb76ff1Sjsg (uint32_t *)db_entry, sizeof(struct psp_runtime_scpm_entry), false); 3871bb76ff1Sjsg ret = true; 3881bb76ff1Sjsg break; 3895ca02815Sjsg default: 3905ca02815Sjsg ret = false; 3915ca02815Sjsg break; 3925ca02815Sjsg } 3935ca02815Sjsg } 3945ca02815Sjsg } 3955ca02815Sjsg 3965ca02815Sjsg return ret; 3975ca02815Sjsg } 3985ca02815Sjsg 399c8a1e887Sjsg static int psp_sw_init(void *handle) 400c8a1e887Sjsg { 401c8a1e887Sjsg struct amdgpu_device *adev = (struct amdgpu_device *)handle; 402c8a1e887Sjsg struct psp_context *psp = &adev->psp; 403c8a1e887Sjsg int ret; 4045ca02815Sjsg struct psp_runtime_boot_cfg_entry boot_cfg_entry; 4055ca02815Sjsg struct psp_memory_training_context *mem_training_ctx = &psp->mem_train_ctx; 4061bb76ff1Sjsg struct psp_runtime_scpm_entry scpm_entry; 4075ca02815Sjsg 4085ca02815Sjsg psp->cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); 4095ca02815Sjsg if (!psp->cmd) { 4105ca02815Sjsg DRM_ERROR("Failed to allocate memory to command buffer!\n"); 4115ca02815Sjsg ret = -ENOMEM; 4125ca02815Sjsg } 413c8a1e887Sjsg 4141bb76ff1Sjsg adev->psp.xgmi_context.supports_extended_data = 4151bb76ff1Sjsg !adev->gmc.xgmi.connected_to_cpu && 4161bb76ff1Sjsg adev->ip_versions[MP0_HWIP][0] == IP_VERSION(13, 0, 2); 4171bb76ff1Sjsg 4181bb76ff1Sjsg memset(&scpm_entry, 0, sizeof(scpm_entry)); 4191bb76ff1Sjsg if ((psp_get_runtime_db_entry(adev, 4201bb76ff1Sjsg PSP_RUNTIME_ENTRY_TYPE_PPTABLE_ERR_STATUS, 4211bb76ff1Sjsg &scpm_entry)) && 422f005ef32Sjsg (scpm_entry.scpm_status != SCPM_DISABLE)) { 4231bb76ff1Sjsg adev->scpm_enabled = true; 4241bb76ff1Sjsg adev->scpm_status = scpm_entry.scpm_status; 4251bb76ff1Sjsg } else { 4261bb76ff1Sjsg adev->scpm_enabled = false; 4271bb76ff1Sjsg adev->scpm_status = SCPM_DISABLE; 4285ca02815Sjsg } 4291bb76ff1Sjsg 4301bb76ff1Sjsg /* TODO: stop gpu driver services and print alarm if scpm is enabled with error status */ 431fb4d8502Sjsg 4325ca02815Sjsg memset(&boot_cfg_entry, 0, sizeof(boot_cfg_entry)); 4335ca02815Sjsg if (psp_get_runtime_db_entry(adev, 4345ca02815Sjsg PSP_RUNTIME_ENTRY_TYPE_BOOT_CONFIG, 4355ca02815Sjsg &boot_cfg_entry)) { 4365ca02815Sjsg psp->boot_cfg_bitmask = boot_cfg_entry.boot_cfg_bitmask; 4375ca02815Sjsg if ((psp->boot_cfg_bitmask) & 4385ca02815Sjsg BOOT_CFG_FEATURE_TWO_STAGE_DRAM_TRAINING) { 4395ca02815Sjsg /* If psp runtime database exists, then 4405ca02815Sjsg * only enable two stage memory training 4415ca02815Sjsg * when TWO_STAGE_DRAM_TRAINING bit is set 442f005ef32Sjsg * in runtime database 443f005ef32Sjsg */ 4445ca02815Sjsg mem_training_ctx->enable_mem_training = true; 4455ca02815Sjsg } 4465ca02815Sjsg 4475ca02815Sjsg } else { 448f005ef32Sjsg /* If psp runtime database doesn't exist or is 449f005ef32Sjsg * invalid, force enable two stage memory training 450f005ef32Sjsg */ 4515ca02815Sjsg mem_training_ctx->enable_mem_training = true; 4525ca02815Sjsg } 4535ca02815Sjsg 4545ca02815Sjsg if (mem_training_ctx->enable_mem_training) { 455ad8b1aafSjsg ret = psp_memory_training_init(psp); 456c349dbc7Sjsg if (ret) { 457c349dbc7Sjsg DRM_ERROR("Failed to initialize memory training!\n"); 458c349dbc7Sjsg return ret; 459c349dbc7Sjsg } 4605ca02815Sjsg 461c349dbc7Sjsg ret = psp_mem_training(psp, PSP_MEM_TRAIN_COLD_BOOT); 462c349dbc7Sjsg if (ret) { 463c349dbc7Sjsg DRM_ERROR("Failed to process memory training!\n"); 464c349dbc7Sjsg return ret; 465c349dbc7Sjsg } 4665ca02815Sjsg } 467c349dbc7Sjsg 4680ae6e948Sjsg ret = amdgpu_bo_create_kernel(adev, PSP_1_MEG, PSP_1_MEG, 4690ae6e948Sjsg amdgpu_sriov_vf(adev) ? 4700ae6e948Sjsg AMDGPU_GEM_DOMAIN_VRAM : AMDGPU_GEM_DOMAIN_GTT, 4710ae6e948Sjsg &psp->fw_pri_bo, 4720ae6e948Sjsg &psp->fw_pri_mc_addr, 4730ae6e948Sjsg &psp->fw_pri_buf); 4740ae6e948Sjsg if (ret) 4750ae6e948Sjsg return ret; 4760ae6e948Sjsg 4770ae6e948Sjsg ret = amdgpu_bo_create_kernel(adev, PSP_FENCE_BUFFER_SIZE, PAGE_SIZE, 478f005ef32Sjsg AMDGPU_GEM_DOMAIN_VRAM | 479f005ef32Sjsg AMDGPU_GEM_DOMAIN_GTT, 4800ae6e948Sjsg &psp->fence_buf_bo, 4810ae6e948Sjsg &psp->fence_buf_mc_addr, 4820ae6e948Sjsg &psp->fence_buf); 4830ae6e948Sjsg if (ret) 4840ae6e948Sjsg goto failed1; 4850ae6e948Sjsg 4860ae6e948Sjsg ret = amdgpu_bo_create_kernel(adev, PSP_CMD_BUFFER_SIZE, PAGE_SIZE, 487f005ef32Sjsg AMDGPU_GEM_DOMAIN_VRAM | 488f005ef32Sjsg AMDGPU_GEM_DOMAIN_GTT, 4890ae6e948Sjsg &psp->cmd_buf_bo, &psp->cmd_buf_mc_addr, 4900ae6e948Sjsg (void **)&psp->cmd_buf_mem); 4910ae6e948Sjsg if (ret) 4920ae6e948Sjsg goto failed2; 4930ae6e948Sjsg 494fb4d8502Sjsg return 0; 4950ae6e948Sjsg 4960ae6e948Sjsg failed2: 4970ae6e948Sjsg amdgpu_bo_free_kernel(&psp->fence_buf_bo, 4980ae6e948Sjsg &psp->fence_buf_mc_addr, &psp->fence_buf); 499c000984bSjsg failed1: 500c000984bSjsg amdgpu_bo_free_kernel(&psp->fw_pri_bo, 501c000984bSjsg &psp->fw_pri_mc_addr, &psp->fw_pri_buf); 5020ae6e948Sjsg return ret; 503fb4d8502Sjsg } 504fb4d8502Sjsg 505fb4d8502Sjsg static int psp_sw_fini(void *handle) 506fb4d8502Sjsg { 507fb4d8502Sjsg struct amdgpu_device *adev = (struct amdgpu_device *)handle; 5085ca02815Sjsg struct psp_context *psp = &adev->psp; 5095ca02815Sjsg struct psp_gfx_cmd_resp *cmd = psp->cmd; 510fb4d8502Sjsg 5115ca02815Sjsg psp_memory_training_fini(psp); 512f005ef32Sjsg 513f005ef32Sjsg amdgpu_ucode_release(&psp->sos_fw); 514f005ef32Sjsg amdgpu_ucode_release(&psp->asd_fw); 515f005ef32Sjsg amdgpu_ucode_release(&psp->ta_fw); 516f005ef32Sjsg amdgpu_ucode_release(&psp->cap_fw); 517f005ef32Sjsg amdgpu_ucode_release(&psp->toc_fw); 518c349dbc7Sjsg 5195ca02815Sjsg kfree(cmd); 5205ca02815Sjsg cmd = NULL; 5215ca02815Sjsg 5225711e8cdSjsg psp_free_shared_bufs(psp); 5235711e8cdSjsg 5241bb76ff1Sjsg if (psp->km_ring.ring_mem) 5251bb76ff1Sjsg amdgpu_bo_free_kernel(&adev->firmware.rbuf, 5261bb76ff1Sjsg &psp->km_ring.ring_mem_mc_addr, 5271bb76ff1Sjsg (void **)&psp->km_ring.ring_mem); 5281bb76ff1Sjsg 5290ae6e948Sjsg amdgpu_bo_free_kernel(&psp->fw_pri_bo, 5300ae6e948Sjsg &psp->fw_pri_mc_addr, &psp->fw_pri_buf); 5310ae6e948Sjsg amdgpu_bo_free_kernel(&psp->fence_buf_bo, 5320ae6e948Sjsg &psp->fence_buf_mc_addr, &psp->fence_buf); 5330ae6e948Sjsg amdgpu_bo_free_kernel(&psp->cmd_buf_bo, &psp->cmd_buf_mc_addr, 5340ae6e948Sjsg (void **)&psp->cmd_buf_mem); 5350ae6e948Sjsg 536fb4d8502Sjsg return 0; 537fb4d8502Sjsg } 538fb4d8502Sjsg 539fb4d8502Sjsg int psp_wait_for(struct psp_context *psp, uint32_t reg_index, 540fb4d8502Sjsg uint32_t reg_val, uint32_t mask, bool check_changed) 541fb4d8502Sjsg { 542fb4d8502Sjsg uint32_t val; 543fb4d8502Sjsg int i; 544fb4d8502Sjsg struct amdgpu_device *adev = psp->adev; 545fb4d8502Sjsg 5465ca02815Sjsg if (psp->adev->no_hw_access) 547ad8b1aafSjsg return 0; 548ad8b1aafSjsg 549fb4d8502Sjsg for (i = 0; i < adev->usec_timeout; i++) { 550fb4d8502Sjsg val = RREG32(reg_index); 551fb4d8502Sjsg if (check_changed) { 552fb4d8502Sjsg if (val != reg_val) 553fb4d8502Sjsg return 0; 554fb4d8502Sjsg } else { 555fb4d8502Sjsg if ((val & mask) == reg_val) 556fb4d8502Sjsg return 0; 557fb4d8502Sjsg } 558fb4d8502Sjsg udelay(1); 559fb4d8502Sjsg } 560fb4d8502Sjsg 561fb4d8502Sjsg return -ETIME; 562fb4d8502Sjsg } 563fb4d8502Sjsg 564f005ef32Sjsg int psp_wait_for_spirom_update(struct psp_context *psp, uint32_t reg_index, 565f005ef32Sjsg uint32_t reg_val, uint32_t mask, uint32_t msec_timeout) 566f005ef32Sjsg { 567f005ef32Sjsg uint32_t val; 568f005ef32Sjsg int i; 569f005ef32Sjsg struct amdgpu_device *adev = psp->adev; 570f005ef32Sjsg 571f005ef32Sjsg if (psp->adev->no_hw_access) 572f005ef32Sjsg return 0; 573f005ef32Sjsg 574f005ef32Sjsg for (i = 0; i < msec_timeout; i++) { 575f005ef32Sjsg val = RREG32(reg_index); 576f005ef32Sjsg if ((val & mask) == reg_val) 577f005ef32Sjsg return 0; 578f005ef32Sjsg drm_msleep(1); 579f005ef32Sjsg } 580f005ef32Sjsg 581f005ef32Sjsg return -ETIME; 582f005ef32Sjsg } 583f005ef32Sjsg 5845ca02815Sjsg static const char *psp_gfx_cmd_name(enum psp_gfx_cmd_id cmd_id) 5855ca02815Sjsg { 5865ca02815Sjsg switch (cmd_id) { 5875ca02815Sjsg case GFX_CMD_ID_LOAD_TA: 5885ca02815Sjsg return "LOAD_TA"; 5895ca02815Sjsg case GFX_CMD_ID_UNLOAD_TA: 5905ca02815Sjsg return "UNLOAD_TA"; 5915ca02815Sjsg case GFX_CMD_ID_INVOKE_CMD: 5925ca02815Sjsg return "INVOKE_CMD"; 5935ca02815Sjsg case GFX_CMD_ID_LOAD_ASD: 5945ca02815Sjsg return "LOAD_ASD"; 5955ca02815Sjsg case GFX_CMD_ID_SETUP_TMR: 5965ca02815Sjsg return "SETUP_TMR"; 5975ca02815Sjsg case GFX_CMD_ID_LOAD_IP_FW: 5985ca02815Sjsg return "LOAD_IP_FW"; 5995ca02815Sjsg case GFX_CMD_ID_DESTROY_TMR: 6005ca02815Sjsg return "DESTROY_TMR"; 6015ca02815Sjsg case GFX_CMD_ID_SAVE_RESTORE: 6025ca02815Sjsg return "SAVE_RESTORE_IP_FW"; 6035ca02815Sjsg case GFX_CMD_ID_SETUP_VMR: 6045ca02815Sjsg return "SETUP_VMR"; 6055ca02815Sjsg case GFX_CMD_ID_DESTROY_VMR: 6065ca02815Sjsg return "DESTROY_VMR"; 6075ca02815Sjsg case GFX_CMD_ID_PROG_REG: 6085ca02815Sjsg return "PROG_REG"; 6095ca02815Sjsg case GFX_CMD_ID_GET_FW_ATTESTATION: 6105ca02815Sjsg return "GET_FW_ATTESTATION"; 6115ca02815Sjsg case GFX_CMD_ID_LOAD_TOC: 6125ca02815Sjsg return "ID_LOAD_TOC"; 6135ca02815Sjsg case GFX_CMD_ID_AUTOLOAD_RLC: 6145ca02815Sjsg return "AUTOLOAD_RLC"; 6155ca02815Sjsg case GFX_CMD_ID_BOOT_CFG: 6165ca02815Sjsg return "BOOT_CFG"; 6175ca02815Sjsg default: 6185ca02815Sjsg return "UNKNOWN CMD"; 6195ca02815Sjsg } 6205ca02815Sjsg } 6215ca02815Sjsg 622fb4d8502Sjsg static int 623fb4d8502Sjsg psp_cmd_submit_buf(struct psp_context *psp, 624fb4d8502Sjsg struct amdgpu_firmware_info *ucode, 625c349dbc7Sjsg struct psp_gfx_cmd_resp *cmd, uint64_t fence_mc_addr) 626fb4d8502Sjsg { 627fb4d8502Sjsg int ret; 628f005ef32Sjsg int index; 6295ca02815Sjsg int timeout = 20000; 630c349dbc7Sjsg bool ras_intr = false; 631ad8b1aafSjsg bool skip_unsupport = false; 632ad8b1aafSjsg 6335ca02815Sjsg if (psp->adev->no_hw_access) 634ad8b1aafSjsg return 0; 635c349dbc7Sjsg 636fb4d8502Sjsg memset(psp->cmd_buf_mem, 0, PSP_CMD_BUFFER_SIZE); 637fb4d8502Sjsg 638fb4d8502Sjsg memcpy(psp->cmd_buf_mem, cmd, sizeof(struct psp_gfx_cmd_resp)); 639fb4d8502Sjsg 640c349dbc7Sjsg index = atomic_inc_return(&psp->fence_value); 641c349dbc7Sjsg ret = psp_ring_cmd_submit(psp, psp->cmd_buf_mc_addr, fence_mc_addr, index); 642c349dbc7Sjsg if (ret) { 643c349dbc7Sjsg atomic_dec(&psp->fence_value); 6445ca02815Sjsg goto exit; 645fb4d8502Sjsg } 646fb4d8502Sjsg 6475ca02815Sjsg amdgpu_device_invalidate_hdp(psp->adev, NULL); 648c349dbc7Sjsg while (*((unsigned int *)psp->fence_buf) != index) { 649c349dbc7Sjsg if (--timeout == 0) 650c349dbc7Sjsg break; 651c349dbc7Sjsg /* 652c349dbc7Sjsg * Shouldn't wait for timeout when err_event_athub occurs, 653c349dbc7Sjsg * because gpu reset thread triggered and lock resource should 654c349dbc7Sjsg * be released for psp resume sequence. 655c349dbc7Sjsg */ 656c349dbc7Sjsg ras_intr = amdgpu_ras_intr_triggered(); 657c349dbc7Sjsg if (ras_intr) 658c349dbc7Sjsg break; 6595ca02815Sjsg usleep_range(10, 100); 6605ca02815Sjsg amdgpu_device_invalidate_hdp(psp->adev, NULL); 661c349dbc7Sjsg } 662c349dbc7Sjsg 663ad8b1aafSjsg /* We allow TEE_ERROR_NOT_SUPPORTED for VMR command and PSP_ERR_UNKNOWN_COMMAND in SRIOV */ 664ad8b1aafSjsg skip_unsupport = (psp->cmd_buf_mem->resp.status == TEE_ERROR_NOT_SUPPORTED || 665ad8b1aafSjsg psp->cmd_buf_mem->resp.status == PSP_ERR_UNKNOWN_COMMAND) && amdgpu_sriov_vf(psp->adev); 666ad8b1aafSjsg 667f005ef32Sjsg memcpy(&cmd->resp, &psp->cmd_buf_mem->resp, sizeof(struct psp_gfx_resp)); 6685ca02815Sjsg 669c349dbc7Sjsg /* In some cases, psp response status is not 0 even there is no 670c349dbc7Sjsg * problem while the command is submitted. Some version of PSP FW 671c349dbc7Sjsg * doesn't write 0 to that field. 672c349dbc7Sjsg * So here we would like to only print a warning instead of an error 673c349dbc7Sjsg * during psp initialization to avoid breaking hw_init and it doesn't 674c349dbc7Sjsg * return -EINVAL. 675c349dbc7Sjsg */ 676ad8b1aafSjsg if (!skip_unsupport && (psp->cmd_buf_mem->resp.status || !timeout) && !ras_intr) { 677c349dbc7Sjsg if (ucode) 6785ca02815Sjsg DRM_WARN("failed to load ucode %s(0x%X) ", 6795ca02815Sjsg amdgpu_ucode_name(ucode->ucode_id), ucode->ucode_id); 6805ca02815Sjsg DRM_WARN("psp gfx command %s(0x%X) failed and response status is (0x%X)\n", 6815ca02815Sjsg psp_gfx_cmd_name(psp->cmd_buf_mem->cmd_id), psp->cmd_buf_mem->cmd_id, 682c349dbc7Sjsg psp->cmd_buf_mem->resp.status); 6831bb76ff1Sjsg /* If any firmware (including CAP) load fails under SRIOV, it should 6841bb76ff1Sjsg * return failure to stop the VF from initializing. 6851bb76ff1Sjsg * Also return failure in case of timeout 6861bb76ff1Sjsg */ 6871bb76ff1Sjsg if ((ucode && amdgpu_sriov_vf(psp->adev)) || !timeout) { 6885ca02815Sjsg ret = -EINVAL; 6895ca02815Sjsg goto exit; 690c349dbc7Sjsg } 691c349dbc7Sjsg } 692c349dbc7Sjsg 693fb4d8502Sjsg if (ucode) { 694fb4d8502Sjsg ucode->tmr_mc_addr_lo = psp->cmd_buf_mem->resp.fw_addr_lo; 695fb4d8502Sjsg ucode->tmr_mc_addr_hi = psp->cmd_buf_mem->resp.fw_addr_hi; 696fb4d8502Sjsg } 697fb4d8502Sjsg 6985ca02815Sjsg exit: 699fb4d8502Sjsg return ret; 700fb4d8502Sjsg } 701fb4d8502Sjsg 7025ca02815Sjsg static struct psp_gfx_cmd_resp *acquire_psp_cmd_buf(struct psp_context *psp) 7035ca02815Sjsg { 7045ca02815Sjsg struct psp_gfx_cmd_resp *cmd = psp->cmd; 7055ca02815Sjsg 7065ca02815Sjsg mutex_lock(&psp->mutex); 7075ca02815Sjsg 7085ca02815Sjsg memset(cmd, 0, sizeof(struct psp_gfx_cmd_resp)); 7095ca02815Sjsg 7105ca02815Sjsg return cmd; 7115ca02815Sjsg } 7125ca02815Sjsg 7131bb76ff1Sjsg static void release_psp_cmd_buf(struct psp_context *psp) 7145ca02815Sjsg { 7155ca02815Sjsg mutex_unlock(&psp->mutex); 7165ca02815Sjsg } 7175ca02815Sjsg 718c349dbc7Sjsg static void psp_prep_tmr_cmd_buf(struct psp_context *psp, 719c349dbc7Sjsg struct psp_gfx_cmd_resp *cmd, 7205ca02815Sjsg uint64_t tmr_mc, struct amdgpu_bo *tmr_bo) 721fb4d8502Sjsg { 7225ca02815Sjsg struct amdgpu_device *adev = psp->adev; 723f005ef32Sjsg uint32_t size = 0; 724f005ef32Sjsg uint64_t tmr_pa = 0; 725f005ef32Sjsg 726f005ef32Sjsg if (tmr_bo) { 727f005ef32Sjsg size = amdgpu_bo_size(tmr_bo); 728f005ef32Sjsg tmr_pa = amdgpu_gmc_vram_pa(adev, tmr_bo); 729f005ef32Sjsg } 7305ca02815Sjsg 731ad8b1aafSjsg if (amdgpu_sriov_vf(psp->adev)) 732c349dbc7Sjsg cmd->cmd_id = GFX_CMD_ID_SETUP_VMR; 733c349dbc7Sjsg else 734fb4d8502Sjsg cmd->cmd_id = GFX_CMD_ID_SETUP_TMR; 735fb4d8502Sjsg cmd->cmd.cmd_setup_tmr.buf_phy_addr_lo = lower_32_bits(tmr_mc); 736fb4d8502Sjsg cmd->cmd.cmd_setup_tmr.buf_phy_addr_hi = upper_32_bits(tmr_mc); 737fb4d8502Sjsg cmd->cmd.cmd_setup_tmr.buf_size = size; 7385ca02815Sjsg cmd->cmd.cmd_setup_tmr.bitfield.virt_phy_addr = 1; 7395ca02815Sjsg cmd->cmd.cmd_setup_tmr.system_phy_addr_lo = lower_32_bits(tmr_pa); 7405ca02815Sjsg cmd->cmd.cmd_setup_tmr.system_phy_addr_hi = upper_32_bits(tmr_pa); 741fb4d8502Sjsg } 742fb4d8502Sjsg 743c349dbc7Sjsg static void psp_prep_load_toc_cmd_buf(struct psp_gfx_cmd_resp *cmd, 744c349dbc7Sjsg uint64_t pri_buf_mc, uint32_t size) 745c349dbc7Sjsg { 746c349dbc7Sjsg cmd->cmd_id = GFX_CMD_ID_LOAD_TOC; 747c349dbc7Sjsg cmd->cmd.cmd_load_toc.toc_phy_addr_lo = lower_32_bits(pri_buf_mc); 748c349dbc7Sjsg cmd->cmd.cmd_load_toc.toc_phy_addr_hi = upper_32_bits(pri_buf_mc); 749c349dbc7Sjsg cmd->cmd.cmd_load_toc.toc_size = size; 750c349dbc7Sjsg } 751c349dbc7Sjsg 752c349dbc7Sjsg /* Issue LOAD TOC cmd to PSP to part toc and calculate tmr size needed */ 753c349dbc7Sjsg static int psp_load_toc(struct psp_context *psp, 754c349dbc7Sjsg uint32_t *tmr_size) 755c349dbc7Sjsg { 756c349dbc7Sjsg int ret; 7575ca02815Sjsg struct psp_gfx_cmd_resp *cmd = acquire_psp_cmd_buf(psp); 758c349dbc7Sjsg 759c349dbc7Sjsg /* Copy toc to psp firmware private buffer */ 7605ca02815Sjsg psp_copy_fw(psp, psp->toc.start_addr, psp->toc.size_bytes); 761c349dbc7Sjsg 7625ca02815Sjsg psp_prep_load_toc_cmd_buf(cmd, psp->fw_pri_mc_addr, psp->toc.size_bytes); 763c349dbc7Sjsg 764c349dbc7Sjsg ret = psp_cmd_submit_buf(psp, NULL, cmd, 765c349dbc7Sjsg psp->fence_buf_mc_addr); 766c349dbc7Sjsg if (!ret) 767c349dbc7Sjsg *tmr_size = psp->cmd_buf_mem->resp.tmr_size; 7685ca02815Sjsg 7695ca02815Sjsg release_psp_cmd_buf(psp); 7705ca02815Sjsg 771c349dbc7Sjsg return ret; 772c349dbc7Sjsg } 773c349dbc7Sjsg 774f005ef32Sjsg static bool psp_boottime_tmr(struct psp_context *psp) 775f005ef32Sjsg { 776f005ef32Sjsg switch (psp->adev->ip_versions[MP0_HWIP][0]) { 777f005ef32Sjsg case IP_VERSION(13, 0, 6): 778f005ef32Sjsg return true; 779f005ef32Sjsg default: 780f005ef32Sjsg return false; 781f005ef32Sjsg } 782f005ef32Sjsg } 783f005ef32Sjsg 784fb4d8502Sjsg /* Set up Trusted Memory Region */ 785fb4d8502Sjsg static int psp_tmr_init(struct psp_context *psp) 786fb4d8502Sjsg { 7871bb76ff1Sjsg int ret = 0; 788c349dbc7Sjsg int tmr_size; 789c349dbc7Sjsg void *tmr_buf; 790c349dbc7Sjsg void **pptr; 791fb4d8502Sjsg 792fb4d8502Sjsg /* 793c349dbc7Sjsg * According to HW engineer, they prefer the TMR address be "naturally 794c349dbc7Sjsg * aligned" , e.g. the start address be an integer divide of TMR size. 795fb4d8502Sjsg * 796fb4d8502Sjsg * Note: this memory need be reserved till the driver 797fb4d8502Sjsg * uninitializes. 798fb4d8502Sjsg */ 7995ca02815Sjsg tmr_size = PSP_TMR_SIZE(psp->adev); 800c349dbc7Sjsg 801c349dbc7Sjsg /* For ASICs support RLC autoload, psp will parse the toc 802f005ef32Sjsg * and calculate the total size of TMR needed 803f005ef32Sjsg */ 804c349dbc7Sjsg if (!amdgpu_sriov_vf(psp->adev) && 8055ca02815Sjsg psp->toc.start_addr && 8065ca02815Sjsg psp->toc.size_bytes && 807c349dbc7Sjsg psp->fw_pri_buf) { 808c349dbc7Sjsg ret = psp_load_toc(psp, &tmr_size); 809c349dbc7Sjsg if (ret) { 810c349dbc7Sjsg DRM_ERROR("Failed to load toc\n"); 811c349dbc7Sjsg return ret; 812c349dbc7Sjsg } 813c349dbc7Sjsg } 814c349dbc7Sjsg 8151bb76ff1Sjsg if (!psp->tmr_bo) { 816c349dbc7Sjsg pptr = amdgpu_sriov_vf(psp->adev) ? &tmr_buf : NULL; 817f005ef32Sjsg ret = amdgpu_bo_create_kernel(psp->adev, tmr_size, 818f005ef32Sjsg PSP_TMR_ALIGNMENT, 819f005ef32Sjsg AMDGPU_HAS_VRAM(psp->adev) ? 820f005ef32Sjsg AMDGPU_GEM_DOMAIN_VRAM : 821f005ef32Sjsg AMDGPU_GEM_DOMAIN_GTT, 822f005ef32Sjsg &psp->tmr_bo, &psp->tmr_mc_addr, 823f005ef32Sjsg pptr); 8241bb76ff1Sjsg } 825fb4d8502Sjsg 826fb4d8502Sjsg return ret; 827fb4d8502Sjsg } 828fb4d8502Sjsg 829ad8b1aafSjsg static bool psp_skip_tmr(struct psp_context *psp) 830ad8b1aafSjsg { 8311bb76ff1Sjsg switch (psp->adev->ip_versions[MP0_HWIP][0]) { 8321bb76ff1Sjsg case IP_VERSION(11, 0, 9): 8331bb76ff1Sjsg case IP_VERSION(11, 0, 7): 8341bb76ff1Sjsg case IP_VERSION(13, 0, 2): 835f005ef32Sjsg case IP_VERSION(13, 0, 6): 8361bb76ff1Sjsg case IP_VERSION(13, 0, 10): 837ad8b1aafSjsg return true; 838ad8b1aafSjsg default: 839ad8b1aafSjsg return false; 840ad8b1aafSjsg } 841ad8b1aafSjsg } 842ad8b1aafSjsg 843fb4d8502Sjsg static int psp_tmr_load(struct psp_context *psp) 844fb4d8502Sjsg { 845fb4d8502Sjsg int ret; 846fb4d8502Sjsg struct psp_gfx_cmd_resp *cmd; 847fb4d8502Sjsg 848ad8b1aafSjsg /* For Navi12 and CHIP_SIENNA_CICHLID SRIOV, do not set up TMR. 849ad8b1aafSjsg * Already set up by host driver. 850ad8b1aafSjsg */ 851ad8b1aafSjsg if (amdgpu_sriov_vf(psp->adev) && psp_skip_tmr(psp)) 852ad8b1aafSjsg return 0; 853ad8b1aafSjsg 8545ca02815Sjsg cmd = acquire_psp_cmd_buf(psp); 855fb4d8502Sjsg 8565ca02815Sjsg psp_prep_tmr_cmd_buf(psp, cmd, psp->tmr_mc_addr, psp->tmr_bo); 857f005ef32Sjsg if (psp->tmr_bo) 858c349dbc7Sjsg DRM_INFO("reserve 0x%lx from 0x%llx for PSP TMR\n", 859c349dbc7Sjsg amdgpu_bo_size(psp->tmr_bo), psp->tmr_mc_addr); 860fb4d8502Sjsg 861fb4d8502Sjsg ret = psp_cmd_submit_buf(psp, NULL, cmd, 862c349dbc7Sjsg psp->fence_buf_mc_addr); 863fb4d8502Sjsg 8645ca02815Sjsg release_psp_cmd_buf(psp); 865fb4d8502Sjsg 866fb4d8502Sjsg return ret; 867fb4d8502Sjsg } 868fb4d8502Sjsg 8696bd9a77dSjsg static void psp_prep_tmr_unload_cmd_buf(struct psp_context *psp, 8706bd9a77dSjsg struct psp_gfx_cmd_resp *cmd) 8716bd9a77dSjsg { 8726bd9a77dSjsg if (amdgpu_sriov_vf(psp->adev)) 8736bd9a77dSjsg cmd->cmd_id = GFX_CMD_ID_DESTROY_VMR; 8746bd9a77dSjsg else 8756bd9a77dSjsg cmd->cmd_id = GFX_CMD_ID_DESTROY_TMR; 8766bd9a77dSjsg } 8776bd9a77dSjsg 8786bd9a77dSjsg static int psp_tmr_unload(struct psp_context *psp) 8796bd9a77dSjsg { 8806bd9a77dSjsg int ret; 881f005ef32Sjsg struct psp_gfx_cmd_resp *cmd; 882f005ef32Sjsg 883f005ef32Sjsg /* skip TMR unload for Navi12 and CHIP_SIENNA_CICHLID SRIOV, 884f005ef32Sjsg * as TMR is not loaded at all 885f005ef32Sjsg */ 886f005ef32Sjsg if (amdgpu_sriov_vf(psp->adev) && psp_skip_tmr(psp)) 887f005ef32Sjsg return 0; 888f005ef32Sjsg 889f005ef32Sjsg cmd = acquire_psp_cmd_buf(psp); 8906bd9a77dSjsg 8916bd9a77dSjsg psp_prep_tmr_unload_cmd_buf(psp, cmd); 892f005ef32Sjsg dev_dbg(psp->adev->dev, "free PSP TMR buffer\n"); 8936bd9a77dSjsg 8946bd9a77dSjsg ret = psp_cmd_submit_buf(psp, NULL, cmd, 8956bd9a77dSjsg psp->fence_buf_mc_addr); 8966bd9a77dSjsg 8975ca02815Sjsg release_psp_cmd_buf(psp); 8986bd9a77dSjsg 8996bd9a77dSjsg return ret; 9006bd9a77dSjsg } 9016bd9a77dSjsg 9026bd9a77dSjsg static int psp_tmr_terminate(struct psp_context *psp) 9036bd9a77dSjsg { 9041bb76ff1Sjsg return psp_tmr_unload(psp); 9056bd9a77dSjsg } 9066bd9a77dSjsg 9075ca02815Sjsg int psp_get_fw_attestation_records_addr(struct psp_context *psp, 9085ca02815Sjsg uint64_t *output_ptr) 9095ca02815Sjsg { 9105ca02815Sjsg int ret; 9115ca02815Sjsg struct psp_gfx_cmd_resp *cmd; 9125ca02815Sjsg 9135ca02815Sjsg if (!output_ptr) 9145ca02815Sjsg return -EINVAL; 9155ca02815Sjsg 9165ca02815Sjsg if (amdgpu_sriov_vf(psp->adev)) 9175ca02815Sjsg return 0; 9185ca02815Sjsg 9195ca02815Sjsg cmd = acquire_psp_cmd_buf(psp); 9205ca02815Sjsg 9215ca02815Sjsg cmd->cmd_id = GFX_CMD_ID_GET_FW_ATTESTATION; 9225ca02815Sjsg 9235ca02815Sjsg ret = psp_cmd_submit_buf(psp, NULL, cmd, 9245ca02815Sjsg psp->fence_buf_mc_addr); 9255ca02815Sjsg 9265ca02815Sjsg if (!ret) { 9275ca02815Sjsg *output_ptr = ((uint64_t)cmd->resp.uresp.fwar_db_info.fwar_db_addr_lo) + 9285ca02815Sjsg ((uint64_t)cmd->resp.uresp.fwar_db_info.fwar_db_addr_hi << 32); 9295ca02815Sjsg } 9305ca02815Sjsg 9315ca02815Sjsg release_psp_cmd_buf(psp); 9325ca02815Sjsg 9335ca02815Sjsg return ret; 9345ca02815Sjsg } 9355ca02815Sjsg 9365ca02815Sjsg static int psp_boot_config_get(struct amdgpu_device *adev, uint32_t *boot_cfg) 9375ca02815Sjsg { 9385ca02815Sjsg struct psp_context *psp = &adev->psp; 9395ca02815Sjsg struct psp_gfx_cmd_resp *cmd; 9405ca02815Sjsg int ret; 9415ca02815Sjsg 9425ca02815Sjsg if (amdgpu_sriov_vf(adev)) 9435ca02815Sjsg return 0; 9445ca02815Sjsg 9455ca02815Sjsg cmd = acquire_psp_cmd_buf(psp); 9465ca02815Sjsg 9475ca02815Sjsg cmd->cmd_id = GFX_CMD_ID_BOOT_CFG; 9485ca02815Sjsg cmd->cmd.boot_cfg.sub_cmd = BOOTCFG_CMD_GET; 9495ca02815Sjsg 9505ca02815Sjsg ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); 9515ca02815Sjsg if (!ret) { 9525ca02815Sjsg *boot_cfg = 9535ca02815Sjsg (cmd->resp.uresp.boot_cfg.boot_cfg & BOOT_CONFIG_GECC) ? 1 : 0; 9545ca02815Sjsg } 9555ca02815Sjsg 9565ca02815Sjsg release_psp_cmd_buf(psp); 9575ca02815Sjsg 9585ca02815Sjsg return ret; 9595ca02815Sjsg } 9605ca02815Sjsg 9615ca02815Sjsg static int psp_boot_config_set(struct amdgpu_device *adev, uint32_t boot_cfg) 9625ca02815Sjsg { 9635ca02815Sjsg int ret; 9645ca02815Sjsg struct psp_context *psp = &adev->psp; 9655ca02815Sjsg struct psp_gfx_cmd_resp *cmd; 9665ca02815Sjsg 9675ca02815Sjsg if (amdgpu_sriov_vf(adev)) 9685ca02815Sjsg return 0; 9695ca02815Sjsg 9705ca02815Sjsg cmd = acquire_psp_cmd_buf(psp); 9715ca02815Sjsg 9725ca02815Sjsg cmd->cmd_id = GFX_CMD_ID_BOOT_CFG; 9735ca02815Sjsg cmd->cmd.boot_cfg.sub_cmd = BOOTCFG_CMD_SET; 9745ca02815Sjsg cmd->cmd.boot_cfg.boot_config = boot_cfg; 9755ca02815Sjsg cmd->cmd.boot_cfg.boot_config_valid = boot_cfg; 9765ca02815Sjsg 9775ca02815Sjsg ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); 9785ca02815Sjsg 9795ca02815Sjsg release_psp_cmd_buf(psp); 9805ca02815Sjsg 9815ca02815Sjsg return ret; 9825ca02815Sjsg } 9835ca02815Sjsg 9845ca02815Sjsg static int psp_rl_load(struct amdgpu_device *adev) 9855ca02815Sjsg { 9865ca02815Sjsg int ret; 9875ca02815Sjsg struct psp_context *psp = &adev->psp; 9885ca02815Sjsg struct psp_gfx_cmd_resp *cmd; 9895ca02815Sjsg 9905ca02815Sjsg if (!is_psp_fw_valid(psp->rl)) 9915ca02815Sjsg return 0; 9925ca02815Sjsg 9935ca02815Sjsg cmd = acquire_psp_cmd_buf(psp); 9945ca02815Sjsg 9955ca02815Sjsg memset(psp->fw_pri_buf, 0, PSP_1_MEG); 9965ca02815Sjsg memcpy(psp->fw_pri_buf, psp->rl.start_addr, psp->rl.size_bytes); 9975ca02815Sjsg 9985ca02815Sjsg cmd->cmd_id = GFX_CMD_ID_LOAD_IP_FW; 9995ca02815Sjsg cmd->cmd.cmd_load_ip_fw.fw_phy_addr_lo = lower_32_bits(psp->fw_pri_mc_addr); 10005ca02815Sjsg cmd->cmd.cmd_load_ip_fw.fw_phy_addr_hi = upper_32_bits(psp->fw_pri_mc_addr); 10015ca02815Sjsg cmd->cmd.cmd_load_ip_fw.fw_size = psp->rl.size_bytes; 10025ca02815Sjsg cmd->cmd.cmd_load_ip_fw.fw_type = GFX_FW_TYPE_REG_LIST; 10035ca02815Sjsg 10045ca02815Sjsg ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); 10055ca02815Sjsg 10065ca02815Sjsg release_psp_cmd_buf(psp); 10075ca02815Sjsg 10085ca02815Sjsg return ret; 10095ca02815Sjsg } 10105ca02815Sjsg 1011f005ef32Sjsg int psp_spatial_partition(struct psp_context *psp, int mode) 1012f005ef32Sjsg { 1013f005ef32Sjsg struct psp_gfx_cmd_resp *cmd; 1014f005ef32Sjsg int ret; 1015f005ef32Sjsg 1016f005ef32Sjsg if (amdgpu_sriov_vf(psp->adev)) 1017f005ef32Sjsg return 0; 1018f005ef32Sjsg 1019f005ef32Sjsg cmd = acquire_psp_cmd_buf(psp); 1020f005ef32Sjsg 1021f005ef32Sjsg cmd->cmd_id = GFX_CMD_ID_SRIOV_SPATIAL_PART; 1022f005ef32Sjsg cmd->cmd.cmd_spatial_part.mode = mode; 1023f005ef32Sjsg 1024f005ef32Sjsg dev_info(psp->adev->dev, "Requesting %d partitions through PSP", mode); 1025f005ef32Sjsg ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); 1026f005ef32Sjsg 1027f005ef32Sjsg release_psp_cmd_buf(psp); 1028f005ef32Sjsg 1029f005ef32Sjsg return ret; 1030f005ef32Sjsg } 1031f005ef32Sjsg 10321bb76ff1Sjsg static int psp_asd_initialize(struct psp_context *psp) 1033fb4d8502Sjsg { 1034fb4d8502Sjsg int ret; 1035fb4d8502Sjsg 1036fb4d8502Sjsg /* If PSP version doesn't match ASD version, asd loading will be failed. 1037fb4d8502Sjsg * add workaround to bypass it for sriov now. 1038fb4d8502Sjsg * TODO: add version check to make it common 1039fb4d8502Sjsg */ 10401bb76ff1Sjsg if (amdgpu_sriov_vf(psp->adev) || !psp->asd_context.bin_desc.size_bytes) 1041fb4d8502Sjsg return 0; 1042fb4d8502Sjsg 10431bb76ff1Sjsg psp->asd_context.mem_context.shared_mc_addr = 0; 10441bb76ff1Sjsg psp->asd_context.mem_context.shared_mem_size = PSP_ASD_SHARED_MEM_SIZE; 10451bb76ff1Sjsg psp->asd_context.ta_load_type = GFX_CMD_ID_LOAD_ASD; 1046fb4d8502Sjsg 10471bb76ff1Sjsg ret = psp_ta_load(psp, &psp->asd_context); 10481bb76ff1Sjsg if (!ret) 10491bb76ff1Sjsg psp->asd_context.initialized = true; 1050fb4d8502Sjsg 1051fb4d8502Sjsg return ret; 1052fb4d8502Sjsg } 1053fb4d8502Sjsg 1054c349dbc7Sjsg static void psp_prep_ta_unload_cmd_buf(struct psp_gfx_cmd_resp *cmd, 1055c349dbc7Sjsg uint32_t session_id) 1056c349dbc7Sjsg { 1057c349dbc7Sjsg cmd->cmd_id = GFX_CMD_ID_UNLOAD_TA; 1058c349dbc7Sjsg cmd->cmd.cmd_unload_ta.session_id = session_id; 1059c349dbc7Sjsg } 1060c349dbc7Sjsg 10611bb76ff1Sjsg int psp_ta_unload(struct psp_context *psp, struct ta_context *context) 1062c349dbc7Sjsg { 1063c349dbc7Sjsg int ret; 10641bb76ff1Sjsg struct psp_gfx_cmd_resp *cmd = acquire_psp_cmd_buf(psp); 10651bb76ff1Sjsg 10661bb76ff1Sjsg psp_prep_ta_unload_cmd_buf(cmd, context->session_id); 10671bb76ff1Sjsg 10681bb76ff1Sjsg ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); 10691bb76ff1Sjsg 1070f005ef32Sjsg context->resp_status = cmd->resp.status; 1071f005ef32Sjsg 10721bb76ff1Sjsg release_psp_cmd_buf(psp); 10731bb76ff1Sjsg 10741bb76ff1Sjsg return ret; 10751bb76ff1Sjsg } 10761bb76ff1Sjsg 10771bb76ff1Sjsg static int psp_asd_terminate(struct psp_context *psp) 10781bb76ff1Sjsg { 10791bb76ff1Sjsg int ret; 1080c349dbc7Sjsg 1081c349dbc7Sjsg if (amdgpu_sriov_vf(psp->adev)) 1082c349dbc7Sjsg return 0; 1083c349dbc7Sjsg 10841bb76ff1Sjsg if (!psp->asd_context.initialized) 1085c349dbc7Sjsg return 0; 1086c349dbc7Sjsg 10871bb76ff1Sjsg ret = psp_ta_unload(psp, &psp->asd_context); 1088c349dbc7Sjsg if (!ret) 10891bb76ff1Sjsg psp->asd_context.initialized = false; 1090c349dbc7Sjsg 1091c349dbc7Sjsg return ret; 1092c349dbc7Sjsg } 1093c349dbc7Sjsg 1094c349dbc7Sjsg static void psp_prep_reg_prog_cmd_buf(struct psp_gfx_cmd_resp *cmd, 1095c349dbc7Sjsg uint32_t id, uint32_t value) 1096c349dbc7Sjsg { 1097c349dbc7Sjsg cmd->cmd_id = GFX_CMD_ID_PROG_REG; 1098c349dbc7Sjsg cmd->cmd.cmd_setup_reg_prog.reg_value = value; 1099c349dbc7Sjsg cmd->cmd.cmd_setup_reg_prog.reg_id = id; 1100c349dbc7Sjsg } 1101c349dbc7Sjsg 1102c349dbc7Sjsg int psp_reg_program(struct psp_context *psp, enum psp_reg_prog_id reg, 1103c349dbc7Sjsg uint32_t value) 1104c349dbc7Sjsg { 11055ca02815Sjsg struct psp_gfx_cmd_resp *cmd; 1106c349dbc7Sjsg int ret = 0; 1107c349dbc7Sjsg 1108c349dbc7Sjsg if (reg >= PSP_REG_LAST) 1109c349dbc7Sjsg return -EINVAL; 1110c349dbc7Sjsg 11115ca02815Sjsg cmd = acquire_psp_cmd_buf(psp); 1112c349dbc7Sjsg 1113c349dbc7Sjsg psp_prep_reg_prog_cmd_buf(cmd, reg, value); 1114c349dbc7Sjsg ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); 11155ca02815Sjsg if (ret) 11165ca02815Sjsg DRM_ERROR("PSP failed to program reg id %d", reg); 1117c349dbc7Sjsg 11185ca02815Sjsg release_psp_cmd_buf(psp); 11195ca02815Sjsg 1120c349dbc7Sjsg return ret; 1121c349dbc7Sjsg } 1122c349dbc7Sjsg 1123c349dbc7Sjsg static void psp_prep_ta_load_cmd_buf(struct psp_gfx_cmd_resp *cmd, 1124c349dbc7Sjsg uint64_t ta_bin_mc, 11251bb76ff1Sjsg struct ta_context *context) 1126c349dbc7Sjsg { 11271bb76ff1Sjsg cmd->cmd_id = context->ta_load_type; 1128c349dbc7Sjsg cmd->cmd.cmd_load_ta.app_phy_addr_lo = lower_32_bits(ta_bin_mc); 1129c349dbc7Sjsg cmd->cmd.cmd_load_ta.app_phy_addr_hi = upper_32_bits(ta_bin_mc); 11301bb76ff1Sjsg cmd->cmd.cmd_load_ta.app_len = context->bin_desc.size_bytes; 1131c349dbc7Sjsg 11321bb76ff1Sjsg cmd->cmd.cmd_load_ta.cmd_buf_phy_addr_lo = 11331bb76ff1Sjsg lower_32_bits(context->mem_context.shared_mc_addr); 11341bb76ff1Sjsg cmd->cmd.cmd_load_ta.cmd_buf_phy_addr_hi = 11351bb76ff1Sjsg upper_32_bits(context->mem_context.shared_mc_addr); 11361bb76ff1Sjsg cmd->cmd.cmd_load_ta.cmd_buf_len = context->mem_context.shared_mem_size; 1137c349dbc7Sjsg } 1138c349dbc7Sjsg 11391bb76ff1Sjsg int psp_ta_init_shared_buf(struct psp_context *psp, 11401bb76ff1Sjsg struct ta_mem_context *mem_ctx) 1141c349dbc7Sjsg { 1142c349dbc7Sjsg /* 1143c349dbc7Sjsg * Allocate 16k memory aligned to 4k from Frame Buffer (local 11445ca02815Sjsg * physical) for ta to host memory 1145c349dbc7Sjsg */ 11461bb76ff1Sjsg return amdgpu_bo_create_kernel(psp->adev, mem_ctx->shared_mem_size, 1147f005ef32Sjsg PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM | 1148f005ef32Sjsg AMDGPU_GEM_DOMAIN_GTT, 11495ca02815Sjsg &mem_ctx->shared_bo, 11505ca02815Sjsg &mem_ctx->shared_mc_addr, 11515ca02815Sjsg &mem_ctx->shared_buf); 11521bb76ff1Sjsg } 11531bb76ff1Sjsg 1154c349dbc7Sjsg static void psp_prep_ta_invoke_cmd_buf(struct psp_gfx_cmd_resp *cmd, 1155c349dbc7Sjsg uint32_t ta_cmd_id, 1156c349dbc7Sjsg uint32_t session_id) 1157c349dbc7Sjsg { 1158c349dbc7Sjsg cmd->cmd_id = GFX_CMD_ID_INVOKE_CMD; 1159c349dbc7Sjsg cmd->cmd.cmd_invoke_cmd.session_id = session_id; 1160c349dbc7Sjsg cmd->cmd.cmd_invoke_cmd.ta_cmd_id = ta_cmd_id; 1161c349dbc7Sjsg } 1162c349dbc7Sjsg 11631bb76ff1Sjsg int psp_ta_invoke(struct psp_context *psp, 1164c349dbc7Sjsg uint32_t ta_cmd_id, 11651bb76ff1Sjsg struct ta_context *context) 1166c349dbc7Sjsg { 1167c349dbc7Sjsg int ret; 11685ca02815Sjsg struct psp_gfx_cmd_resp *cmd = acquire_psp_cmd_buf(psp); 1169c349dbc7Sjsg 11701bb76ff1Sjsg psp_prep_ta_invoke_cmd_buf(cmd, ta_cmd_id, context->session_id); 1171c349dbc7Sjsg 1172c349dbc7Sjsg ret = psp_cmd_submit_buf(psp, NULL, cmd, 1173c349dbc7Sjsg psp->fence_buf_mc_addr); 1174c349dbc7Sjsg 11751bb76ff1Sjsg context->resp_status = cmd->resp.status; 11761bb76ff1Sjsg 11775ca02815Sjsg release_psp_cmd_buf(psp); 1178c349dbc7Sjsg 1179c349dbc7Sjsg return ret; 1180c349dbc7Sjsg } 1181c349dbc7Sjsg 11821bb76ff1Sjsg int psp_ta_load(struct psp_context *psp, struct ta_context *context) 1183c349dbc7Sjsg { 1184c349dbc7Sjsg int ret; 1185c349dbc7Sjsg struct psp_gfx_cmd_resp *cmd; 1186c349dbc7Sjsg 11875ca02815Sjsg cmd = acquire_psp_cmd_buf(psp); 1188c349dbc7Sjsg 11891bb76ff1Sjsg psp_copy_fw(psp, context->bin_desc.start_addr, 11901bb76ff1Sjsg context->bin_desc.size_bytes); 1191c349dbc7Sjsg 11921bb76ff1Sjsg psp_prep_ta_load_cmd_buf(cmd, psp->fw_pri_mc_addr, context); 1193c349dbc7Sjsg 1194c349dbc7Sjsg ret = psp_cmd_submit_buf(psp, NULL, cmd, 1195c349dbc7Sjsg psp->fence_buf_mc_addr); 1196c349dbc7Sjsg 11971bb76ff1Sjsg context->resp_status = cmd->resp.status; 11981bb76ff1Sjsg 1199f005ef32Sjsg if (!ret) 12001bb76ff1Sjsg context->session_id = cmd->resp.session_id; 1201c349dbc7Sjsg 12025ca02815Sjsg release_psp_cmd_buf(psp); 1203c349dbc7Sjsg 1204c349dbc7Sjsg return ret; 1205c349dbc7Sjsg } 1206c349dbc7Sjsg 1207c349dbc7Sjsg int psp_xgmi_invoke(struct psp_context *psp, uint32_t ta_cmd_id) 1208c349dbc7Sjsg { 12091bb76ff1Sjsg return psp_ta_invoke(psp, ta_cmd_id, &psp->xgmi_context.context); 1210c349dbc7Sjsg } 1211c349dbc7Sjsg 1212c349dbc7Sjsg int psp_xgmi_terminate(struct psp_context *psp) 1213c349dbc7Sjsg { 1214c349dbc7Sjsg int ret; 12151bb76ff1Sjsg struct amdgpu_device *adev = psp->adev; 12161bb76ff1Sjsg 12171bb76ff1Sjsg /* XGMI TA unload currently is not supported on Arcturus/Aldebaran A+A */ 12181bb76ff1Sjsg if (adev->ip_versions[MP0_HWIP][0] == IP_VERSION(11, 0, 4) || 12191bb76ff1Sjsg (adev->ip_versions[MP0_HWIP][0] == IP_VERSION(13, 0, 2) && 12201bb76ff1Sjsg adev->gmc.xgmi.connected_to_cpu)) 12211bb76ff1Sjsg return 0; 1222c349dbc7Sjsg 12235ca02815Sjsg if (!psp->xgmi_context.context.initialized) 1224c349dbc7Sjsg return 0; 1225c349dbc7Sjsg 12261bb76ff1Sjsg ret = psp_ta_unload(psp, &psp->xgmi_context.context); 1227c349dbc7Sjsg 12285ca02815Sjsg psp->xgmi_context.context.initialized = false; 1229c349dbc7Sjsg 12301bb76ff1Sjsg return ret; 1231c349dbc7Sjsg } 1232c349dbc7Sjsg 12335ca02815Sjsg int psp_xgmi_initialize(struct psp_context *psp, bool set_extended_data, bool load_ta) 1234c349dbc7Sjsg { 1235c349dbc7Sjsg struct ta_xgmi_shared_memory *xgmi_cmd; 1236c349dbc7Sjsg int ret; 1237c349dbc7Sjsg 12385ca02815Sjsg if (!psp->ta_fw || 12391bb76ff1Sjsg !psp->xgmi_context.context.bin_desc.size_bytes || 12401bb76ff1Sjsg !psp->xgmi_context.context.bin_desc.start_addr) 1241c349dbc7Sjsg return -ENOENT; 1242c349dbc7Sjsg 12435ca02815Sjsg if (!load_ta) 12445ca02815Sjsg goto invoke; 12455ca02815Sjsg 12461bb76ff1Sjsg psp->xgmi_context.context.mem_context.shared_mem_size = PSP_XGMI_SHARED_MEM_SIZE; 12471bb76ff1Sjsg psp->xgmi_context.context.ta_load_type = GFX_CMD_ID_LOAD_TA; 12481bb76ff1Sjsg 12491bb76ff1Sjsg if (!psp->xgmi_context.context.mem_context.shared_buf) { 12501bb76ff1Sjsg ret = psp_ta_init_shared_buf(psp, &psp->xgmi_context.context.mem_context); 1251c349dbc7Sjsg if (ret) 1252c349dbc7Sjsg return ret; 1253c349dbc7Sjsg } 1254c349dbc7Sjsg 1255c349dbc7Sjsg /* Load XGMI TA */ 12561bb76ff1Sjsg ret = psp_ta_load(psp, &psp->xgmi_context.context); 12571bb76ff1Sjsg if (!ret) 12581bb76ff1Sjsg psp->xgmi_context.context.initialized = true; 12591bb76ff1Sjsg else 1260c349dbc7Sjsg return ret; 1261c349dbc7Sjsg 12625ca02815Sjsg invoke: 1263c349dbc7Sjsg /* Initialize XGMI session */ 12645ca02815Sjsg xgmi_cmd = (struct ta_xgmi_shared_memory *)(psp->xgmi_context.context.mem_context.shared_buf); 1265c349dbc7Sjsg memset(xgmi_cmd, 0, sizeof(struct ta_xgmi_shared_memory)); 12665ca02815Sjsg xgmi_cmd->flag_extend_link_record = set_extended_data; 1267c349dbc7Sjsg xgmi_cmd->cmd_id = TA_COMMAND_XGMI__INITIALIZE; 1268c349dbc7Sjsg 1269c349dbc7Sjsg ret = psp_xgmi_invoke(psp, xgmi_cmd->cmd_id); 1270c349dbc7Sjsg 1271c349dbc7Sjsg return ret; 1272c349dbc7Sjsg } 1273c349dbc7Sjsg 1274ad8b1aafSjsg int psp_xgmi_get_hive_id(struct psp_context *psp, uint64_t *hive_id) 1275ad8b1aafSjsg { 1276ad8b1aafSjsg struct ta_xgmi_shared_memory *xgmi_cmd; 1277ad8b1aafSjsg int ret; 1278ad8b1aafSjsg 12795ca02815Sjsg xgmi_cmd = (struct ta_xgmi_shared_memory *)psp->xgmi_context.context.mem_context.shared_buf; 1280ad8b1aafSjsg memset(xgmi_cmd, 0, sizeof(struct ta_xgmi_shared_memory)); 1281ad8b1aafSjsg 1282ad8b1aafSjsg xgmi_cmd->cmd_id = TA_COMMAND_XGMI__GET_HIVE_ID; 1283ad8b1aafSjsg 1284ad8b1aafSjsg /* Invoke xgmi ta to get hive id */ 1285ad8b1aafSjsg ret = psp_xgmi_invoke(psp, xgmi_cmd->cmd_id); 1286ad8b1aafSjsg if (ret) 1287ad8b1aafSjsg return ret; 1288ad8b1aafSjsg 1289ad8b1aafSjsg *hive_id = xgmi_cmd->xgmi_out_message.get_hive_id.hive_id; 1290ad8b1aafSjsg 1291ad8b1aafSjsg return 0; 1292ad8b1aafSjsg } 1293ad8b1aafSjsg 1294ad8b1aafSjsg int psp_xgmi_get_node_id(struct psp_context *psp, uint64_t *node_id) 1295ad8b1aafSjsg { 1296ad8b1aafSjsg struct ta_xgmi_shared_memory *xgmi_cmd; 1297ad8b1aafSjsg int ret; 1298ad8b1aafSjsg 12995ca02815Sjsg xgmi_cmd = (struct ta_xgmi_shared_memory *)psp->xgmi_context.context.mem_context.shared_buf; 1300ad8b1aafSjsg memset(xgmi_cmd, 0, sizeof(struct ta_xgmi_shared_memory)); 1301ad8b1aafSjsg 1302ad8b1aafSjsg xgmi_cmd->cmd_id = TA_COMMAND_XGMI__GET_NODE_ID; 1303ad8b1aafSjsg 1304ad8b1aafSjsg /* Invoke xgmi ta to get the node id */ 1305ad8b1aafSjsg ret = psp_xgmi_invoke(psp, xgmi_cmd->cmd_id); 1306ad8b1aafSjsg if (ret) 1307ad8b1aafSjsg return ret; 1308ad8b1aafSjsg 1309ad8b1aafSjsg *node_id = xgmi_cmd->xgmi_out_message.get_node_id.node_id; 1310ad8b1aafSjsg 1311ad8b1aafSjsg return 0; 1312ad8b1aafSjsg } 1313ad8b1aafSjsg 13145ca02815Sjsg static bool psp_xgmi_peer_link_info_supported(struct psp_context *psp) 13155ca02815Sjsg { 1316f005ef32Sjsg return (psp->adev->ip_versions[MP0_HWIP][0] == IP_VERSION(13, 0, 2) && 1317f005ef32Sjsg psp->xgmi_context.context.bin_desc.fw_version >= 0x2000000b) || 1318f005ef32Sjsg psp->adev->ip_versions[MP0_HWIP][0] >= IP_VERSION(13, 0, 6); 13195ca02815Sjsg } 13205ca02815Sjsg 13215ca02815Sjsg /* 13225ca02815Sjsg * Chips that support extended topology information require the driver to 13235ca02815Sjsg * reflect topology information in the opposite direction. This is 13245ca02815Sjsg * because the TA has already exceeded its link record limit and if the 13255ca02815Sjsg * TA holds bi-directional information, the driver would have to do 13265ca02815Sjsg * multiple fetches instead of just two. 13275ca02815Sjsg */ 13285ca02815Sjsg static void psp_xgmi_reflect_topology_info(struct psp_context *psp, 13295ca02815Sjsg struct psp_xgmi_node_info node_info) 13305ca02815Sjsg { 13315ca02815Sjsg struct amdgpu_device *mirror_adev; 13325ca02815Sjsg struct amdgpu_hive_info *hive; 13335ca02815Sjsg uint64_t src_node_id = psp->adev->gmc.xgmi.node_id; 13345ca02815Sjsg uint64_t dst_node_id = node_info.node_id; 13355ca02815Sjsg uint8_t dst_num_hops = node_info.num_hops; 13365ca02815Sjsg uint8_t dst_num_links = node_info.num_links; 13375ca02815Sjsg 13385ca02815Sjsg hive = amdgpu_get_xgmi_hive(psp->adev); 1339*99dcd02bSjsg if (WARN_ON(!hive)) 1340*99dcd02bSjsg return; 1341*99dcd02bSjsg 13425ca02815Sjsg list_for_each_entry(mirror_adev, &hive->device_list, gmc.xgmi.head) { 13435ca02815Sjsg struct psp_xgmi_topology_info *mirror_top_info; 13445ca02815Sjsg int j; 13455ca02815Sjsg 13465ca02815Sjsg if (mirror_adev->gmc.xgmi.node_id != dst_node_id) 13475ca02815Sjsg continue; 13485ca02815Sjsg 13495ca02815Sjsg mirror_top_info = &mirror_adev->psp.xgmi_context.top_info; 13505ca02815Sjsg for (j = 0; j < mirror_top_info->num_nodes; j++) { 13515ca02815Sjsg if (mirror_top_info->nodes[j].node_id != src_node_id) 13525ca02815Sjsg continue; 13535ca02815Sjsg 13545ca02815Sjsg mirror_top_info->nodes[j].num_hops = dst_num_hops; 13555ca02815Sjsg /* 13565ca02815Sjsg * prevent 0 num_links value re-reflection since reflection 13575ca02815Sjsg * criteria is based on num_hops (direct or indirect). 13585ca02815Sjsg * 13595ca02815Sjsg */ 13605ca02815Sjsg if (dst_num_links) 13615ca02815Sjsg mirror_top_info->nodes[j].num_links = dst_num_links; 13625ca02815Sjsg 13635ca02815Sjsg break; 13645ca02815Sjsg } 13655ca02815Sjsg 13665ca02815Sjsg break; 13675ca02815Sjsg } 13681bb76ff1Sjsg 13691bb76ff1Sjsg amdgpu_put_xgmi_hive(hive); 13705ca02815Sjsg } 13715ca02815Sjsg 1372ad8b1aafSjsg int psp_xgmi_get_topology_info(struct psp_context *psp, 1373ad8b1aafSjsg int number_devices, 13745ca02815Sjsg struct psp_xgmi_topology_info *topology, 13755ca02815Sjsg bool get_extended_data) 1376ad8b1aafSjsg { 1377ad8b1aafSjsg struct ta_xgmi_shared_memory *xgmi_cmd; 1378ad8b1aafSjsg struct ta_xgmi_cmd_get_topology_info_input *topology_info_input; 1379ad8b1aafSjsg struct ta_xgmi_cmd_get_topology_info_output *topology_info_output; 1380ad8b1aafSjsg int i; 1381ad8b1aafSjsg int ret; 1382ad8b1aafSjsg 1383ad8b1aafSjsg if (!topology || topology->num_nodes > TA_XGMI__MAX_CONNECTED_NODES) 1384ad8b1aafSjsg return -EINVAL; 1385ad8b1aafSjsg 13865ca02815Sjsg xgmi_cmd = (struct ta_xgmi_shared_memory *)psp->xgmi_context.context.mem_context.shared_buf; 1387ad8b1aafSjsg memset(xgmi_cmd, 0, sizeof(struct ta_xgmi_shared_memory)); 13885ca02815Sjsg xgmi_cmd->flag_extend_link_record = get_extended_data; 1389ad8b1aafSjsg 1390ad8b1aafSjsg /* Fill in the shared memory with topology information as input */ 1391ad8b1aafSjsg topology_info_input = &xgmi_cmd->xgmi_in_message.get_topology_info; 1392ad8b1aafSjsg xgmi_cmd->cmd_id = TA_COMMAND_XGMI__GET_GET_TOPOLOGY_INFO; 1393ad8b1aafSjsg topology_info_input->num_nodes = number_devices; 1394ad8b1aafSjsg 1395ad8b1aafSjsg for (i = 0; i < topology_info_input->num_nodes; i++) { 1396ad8b1aafSjsg topology_info_input->nodes[i].node_id = topology->nodes[i].node_id; 1397ad8b1aafSjsg topology_info_input->nodes[i].num_hops = topology->nodes[i].num_hops; 1398ad8b1aafSjsg topology_info_input->nodes[i].is_sharing_enabled = topology->nodes[i].is_sharing_enabled; 1399ad8b1aafSjsg topology_info_input->nodes[i].sdma_engine = topology->nodes[i].sdma_engine; 1400ad8b1aafSjsg } 1401ad8b1aafSjsg 1402ad8b1aafSjsg /* Invoke xgmi ta to get the topology information */ 1403ad8b1aafSjsg ret = psp_xgmi_invoke(psp, TA_COMMAND_XGMI__GET_GET_TOPOLOGY_INFO); 1404ad8b1aafSjsg if (ret) 1405ad8b1aafSjsg return ret; 1406ad8b1aafSjsg 1407ad8b1aafSjsg /* Read the output topology information from the shared memory */ 1408ad8b1aafSjsg topology_info_output = &xgmi_cmd->xgmi_out_message.get_topology_info; 1409ad8b1aafSjsg topology->num_nodes = xgmi_cmd->xgmi_out_message.get_topology_info.num_nodes; 1410ad8b1aafSjsg for (i = 0; i < topology->num_nodes; i++) { 14115ca02815Sjsg /* extended data will either be 0 or equal to non-extended data */ 14125ca02815Sjsg if (topology_info_output->nodes[i].num_hops) 1413ad8b1aafSjsg topology->nodes[i].num_hops = topology_info_output->nodes[i].num_hops; 14145ca02815Sjsg 14155ca02815Sjsg /* non-extended data gets everything here so no need to update */ 14165ca02815Sjsg if (!get_extended_data) { 14175ca02815Sjsg topology->nodes[i].node_id = topology_info_output->nodes[i].node_id; 14185ca02815Sjsg topology->nodes[i].is_sharing_enabled = 14195ca02815Sjsg topology_info_output->nodes[i].is_sharing_enabled; 14205ca02815Sjsg topology->nodes[i].sdma_engine = 14215ca02815Sjsg topology_info_output->nodes[i].sdma_engine; 14225ca02815Sjsg } 14235ca02815Sjsg 14245ca02815Sjsg } 14255ca02815Sjsg 14265ca02815Sjsg /* Invoke xgmi ta again to get the link information */ 14275ca02815Sjsg if (psp_xgmi_peer_link_info_supported(psp)) { 14285ca02815Sjsg struct ta_xgmi_cmd_get_peer_link_info_output *link_info_output; 1429f005ef32Sjsg bool requires_reflection = 1430f005ef32Sjsg (psp->xgmi_context.supports_extended_data && get_extended_data) || 1431f005ef32Sjsg psp->adev->ip_versions[MP0_HWIP][0] == IP_VERSION(13, 0, 6); 14325ca02815Sjsg 14335ca02815Sjsg xgmi_cmd->cmd_id = TA_COMMAND_XGMI__GET_PEER_LINKS; 14345ca02815Sjsg 14355ca02815Sjsg ret = psp_xgmi_invoke(psp, TA_COMMAND_XGMI__GET_PEER_LINKS); 14365ca02815Sjsg 14375ca02815Sjsg if (ret) 14385ca02815Sjsg return ret; 14395ca02815Sjsg 14405ca02815Sjsg link_info_output = &xgmi_cmd->xgmi_out_message.get_link_info; 14415ca02815Sjsg for (i = 0; i < topology->num_nodes; i++) { 14425ca02815Sjsg /* accumulate num_links on extended data */ 14435ca02815Sjsg topology->nodes[i].num_links = get_extended_data ? 14445ca02815Sjsg topology->nodes[i].num_links + 14455ca02815Sjsg link_info_output->nodes[i].num_links : 1446f005ef32Sjsg ((requires_reflection && topology->nodes[i].num_links) ? topology->nodes[i].num_links : 1447f005ef32Sjsg link_info_output->nodes[i].num_links); 14485ca02815Sjsg 14495ca02815Sjsg /* reflect the topology information for bi-directionality */ 1450f005ef32Sjsg if (requires_reflection && topology->nodes[i].num_hops) 14515ca02815Sjsg psp_xgmi_reflect_topology_info(psp, topology->nodes[i]); 14525ca02815Sjsg } 1453ad8b1aafSjsg } 1454ad8b1aafSjsg 1455ad8b1aafSjsg return 0; 1456ad8b1aafSjsg } 1457ad8b1aafSjsg 1458ad8b1aafSjsg int psp_xgmi_set_topology_info(struct psp_context *psp, 1459ad8b1aafSjsg int number_devices, 1460ad8b1aafSjsg struct psp_xgmi_topology_info *topology) 1461ad8b1aafSjsg { 1462ad8b1aafSjsg struct ta_xgmi_shared_memory *xgmi_cmd; 1463ad8b1aafSjsg struct ta_xgmi_cmd_get_topology_info_input *topology_info_input; 1464ad8b1aafSjsg int i; 1465ad8b1aafSjsg 1466ad8b1aafSjsg if (!topology || topology->num_nodes > TA_XGMI__MAX_CONNECTED_NODES) 1467ad8b1aafSjsg return -EINVAL; 1468ad8b1aafSjsg 14695ca02815Sjsg xgmi_cmd = (struct ta_xgmi_shared_memory *)psp->xgmi_context.context.mem_context.shared_buf; 1470ad8b1aafSjsg memset(xgmi_cmd, 0, sizeof(struct ta_xgmi_shared_memory)); 1471ad8b1aafSjsg 1472ad8b1aafSjsg topology_info_input = &xgmi_cmd->xgmi_in_message.get_topology_info; 1473ad8b1aafSjsg xgmi_cmd->cmd_id = TA_COMMAND_XGMI__SET_TOPOLOGY_INFO; 1474ad8b1aafSjsg topology_info_input->num_nodes = number_devices; 1475ad8b1aafSjsg 1476ad8b1aafSjsg for (i = 0; i < topology_info_input->num_nodes; i++) { 1477ad8b1aafSjsg topology_info_input->nodes[i].node_id = topology->nodes[i].node_id; 1478ad8b1aafSjsg topology_info_input->nodes[i].num_hops = topology->nodes[i].num_hops; 1479ad8b1aafSjsg topology_info_input->nodes[i].is_sharing_enabled = 1; 1480ad8b1aafSjsg topology_info_input->nodes[i].sdma_engine = topology->nodes[i].sdma_engine; 1481ad8b1aafSjsg } 1482ad8b1aafSjsg 1483ad8b1aafSjsg /* Invoke xgmi ta to set topology information */ 1484ad8b1aafSjsg return psp_xgmi_invoke(psp, TA_COMMAND_XGMI__SET_TOPOLOGY_INFO); 1485ad8b1aafSjsg } 1486ad8b1aafSjsg 1487c349dbc7Sjsg // ras begin 14881bb76ff1Sjsg static void psp_ras_ta_check_status(struct psp_context *psp) 1489c349dbc7Sjsg { 14901bb76ff1Sjsg struct ta_ras_shared_memory *ras_cmd = 14911bb76ff1Sjsg (struct ta_ras_shared_memory *)psp->ras_context.context.mem_context.shared_buf; 14921bb76ff1Sjsg 14931bb76ff1Sjsg switch (ras_cmd->ras_status) { 14941bb76ff1Sjsg case TA_RAS_STATUS__ERROR_UNSUPPORTED_IP: 14951bb76ff1Sjsg dev_warn(psp->adev->dev, 14961bb76ff1Sjsg "RAS WARNING: cmd failed due to unsupported ip\n"); 14971bb76ff1Sjsg break; 14981bb76ff1Sjsg case TA_RAS_STATUS__ERROR_UNSUPPORTED_ERROR_INJ: 14991bb76ff1Sjsg dev_warn(psp->adev->dev, 15001bb76ff1Sjsg "RAS WARNING: cmd failed due to unsupported error injection\n"); 15011bb76ff1Sjsg break; 15021bb76ff1Sjsg case TA_RAS_STATUS__SUCCESS: 15031bb76ff1Sjsg break; 15041bb76ff1Sjsg case TA_RAS_STATUS__TEE_ERROR_ACCESS_DENIED: 15051bb76ff1Sjsg if (ras_cmd->cmd_id == TA_RAS_COMMAND__TRIGGER_ERROR) 15061bb76ff1Sjsg dev_warn(psp->adev->dev, 15071bb76ff1Sjsg "RAS WARNING: Inject error to critical region is not allowed\n"); 15081bb76ff1Sjsg break; 15091bb76ff1Sjsg default: 15101bb76ff1Sjsg dev_warn(psp->adev->dev, 15111bb76ff1Sjsg "RAS WARNING: ras status = 0x%X\n", ras_cmd->ras_status); 15121bb76ff1Sjsg break; 1513c349dbc7Sjsg } 1514c349dbc7Sjsg } 1515c349dbc7Sjsg 1516c349dbc7Sjsg int psp_ras_invoke(struct psp_context *psp, uint32_t ta_cmd_id) 1517c349dbc7Sjsg { 1518ad8b1aafSjsg struct ta_ras_shared_memory *ras_cmd; 1519ad8b1aafSjsg int ret; 1520ad8b1aafSjsg 15215ca02815Sjsg ras_cmd = (struct ta_ras_shared_memory *)psp->ras_context.context.mem_context.shared_buf; 1522ad8b1aafSjsg 1523c349dbc7Sjsg /* 1524c349dbc7Sjsg * TODO: bypass the loading in sriov for now 1525c349dbc7Sjsg */ 1526c349dbc7Sjsg if (amdgpu_sriov_vf(psp->adev)) 1527c349dbc7Sjsg return 0; 1528c349dbc7Sjsg 15291bb76ff1Sjsg ret = psp_ta_invoke(psp, ta_cmd_id, &psp->ras_context.context); 1530ad8b1aafSjsg 1531ad8b1aafSjsg if (amdgpu_ras_intr_triggered()) 1532ad8b1aafSjsg return ret; 1533ad8b1aafSjsg 1534f005ef32Sjsg if (ras_cmd->if_version > RAS_TA_HOST_IF_VER) { 1535ad8b1aafSjsg DRM_WARN("RAS: Unsupported Interface"); 1536ad8b1aafSjsg return -EINVAL; 1537ad8b1aafSjsg } 1538ad8b1aafSjsg 1539ad8b1aafSjsg if (!ret) { 1540ad8b1aafSjsg if (ras_cmd->ras_out_message.flags.err_inject_switch_disable_flag) { 1541ad8b1aafSjsg dev_warn(psp->adev->dev, "ECC switch disabled\n"); 1542ad8b1aafSjsg 1543ad8b1aafSjsg ras_cmd->ras_status = TA_RAS_STATUS__ERROR_RAS_NOT_AVAILABLE; 1544f005ef32Sjsg } else if (ras_cmd->ras_out_message.flags.reg_access_failure_flag) 1545ad8b1aafSjsg dev_warn(psp->adev->dev, 1546ad8b1aafSjsg "RAS internal register access blocked\n"); 1547ad8b1aafSjsg 15481bb76ff1Sjsg psp_ras_ta_check_status(psp); 15495ca02815Sjsg } 15505ca02815Sjsg 15515ca02815Sjsg return ret; 15525ca02815Sjsg } 15535ca02815Sjsg 1554c349dbc7Sjsg int psp_ras_enable_features(struct psp_context *psp, 1555c349dbc7Sjsg union ta_ras_cmd_input *info, bool enable) 1556c349dbc7Sjsg { 1557c349dbc7Sjsg struct ta_ras_shared_memory *ras_cmd; 1558c349dbc7Sjsg int ret; 1559c349dbc7Sjsg 15605ca02815Sjsg if (!psp->ras_context.context.initialized) 1561c349dbc7Sjsg return -EINVAL; 1562c349dbc7Sjsg 15635ca02815Sjsg ras_cmd = (struct ta_ras_shared_memory *)psp->ras_context.context.mem_context.shared_buf; 1564c349dbc7Sjsg memset(ras_cmd, 0, sizeof(struct ta_ras_shared_memory)); 1565c349dbc7Sjsg 1566c349dbc7Sjsg if (enable) 1567c349dbc7Sjsg ras_cmd->cmd_id = TA_RAS_COMMAND__ENABLE_FEATURES; 1568c349dbc7Sjsg else 1569c349dbc7Sjsg ras_cmd->cmd_id = TA_RAS_COMMAND__DISABLE_FEATURES; 1570c349dbc7Sjsg 1571c349dbc7Sjsg ras_cmd->ras_in_message = *info; 1572c349dbc7Sjsg 1573c349dbc7Sjsg ret = psp_ras_invoke(psp, ras_cmd->cmd_id); 1574c349dbc7Sjsg if (ret) 1575c349dbc7Sjsg return -EINVAL; 1576c349dbc7Sjsg 15771bb76ff1Sjsg return 0; 1578c349dbc7Sjsg } 1579c349dbc7Sjsg 15801bb76ff1Sjsg int psp_ras_terminate(struct psp_context *psp) 1581c349dbc7Sjsg { 1582c349dbc7Sjsg int ret; 1583c349dbc7Sjsg 1584c349dbc7Sjsg /* 1585c349dbc7Sjsg * TODO: bypass the terminate in sriov for now 1586c349dbc7Sjsg */ 1587c349dbc7Sjsg if (amdgpu_sriov_vf(psp->adev)) 1588c349dbc7Sjsg return 0; 1589c349dbc7Sjsg 15905ca02815Sjsg if (!psp->ras_context.context.initialized) 1591c349dbc7Sjsg return 0; 1592c349dbc7Sjsg 15931bb76ff1Sjsg ret = psp_ta_unload(psp, &psp->ras_context.context); 1594c349dbc7Sjsg 15955ca02815Sjsg psp->ras_context.context.initialized = false; 1596c349dbc7Sjsg 15971bb76ff1Sjsg return ret; 1598c349dbc7Sjsg } 1599c349dbc7Sjsg 1600f005ef32Sjsg int psp_ras_initialize(struct psp_context *psp) 1601c349dbc7Sjsg { 1602c349dbc7Sjsg int ret; 16035ca02815Sjsg uint32_t boot_cfg = 0xFF; 16045ca02815Sjsg struct amdgpu_device *adev = psp->adev; 16051bb76ff1Sjsg struct ta_ras_shared_memory *ras_cmd; 1606c349dbc7Sjsg 1607c349dbc7Sjsg /* 1608c349dbc7Sjsg * TODO: bypass the initialize in sriov for now 1609c349dbc7Sjsg */ 16105ca02815Sjsg if (amdgpu_sriov_vf(adev)) 1611c349dbc7Sjsg return 0; 1612c349dbc7Sjsg 16131bb76ff1Sjsg if (!adev->psp.ras_context.context.bin_desc.size_bytes || 16141bb76ff1Sjsg !adev->psp.ras_context.context.bin_desc.start_addr) { 16155ca02815Sjsg dev_info(adev->dev, "RAS: optional ras ta ucode is not available\n"); 1616c349dbc7Sjsg return 0; 1617c349dbc7Sjsg } 1618c349dbc7Sjsg 16195ca02815Sjsg if (amdgpu_atomfirmware_dynamic_boot_config_supported(adev)) { 16205ca02815Sjsg /* query GECC enablement status from boot config 16215ca02815Sjsg * boot_cfg: 1: GECC is enabled or 0: GECC is disabled 16225ca02815Sjsg */ 16235ca02815Sjsg ret = psp_boot_config_get(adev, &boot_cfg); 16245ca02815Sjsg if (ret) 16255ca02815Sjsg dev_warn(adev->dev, "PSP get boot config failed\n"); 16265ca02815Sjsg 16275ca02815Sjsg if (!amdgpu_ras_is_supported(psp->adev, AMDGPU_RAS_BLOCK__UMC)) { 16285ca02815Sjsg if (!boot_cfg) { 16295ca02815Sjsg dev_info(adev->dev, "GECC is disabled\n"); 16305ca02815Sjsg } else { 16315ca02815Sjsg /* disable GECC in next boot cycle if ras is 16325ca02815Sjsg * disabled by module parameter amdgpu_ras_enable 16335ca02815Sjsg * and/or amdgpu_ras_mask, or boot_config_get call 16345ca02815Sjsg * is failed 16355ca02815Sjsg */ 16365ca02815Sjsg ret = psp_boot_config_set(adev, 0); 16375ca02815Sjsg if (ret) 16385ca02815Sjsg dev_warn(adev->dev, "PSP set boot config failed\n"); 16395ca02815Sjsg else 1640f005ef32Sjsg dev_warn(adev->dev, "GECC will be disabled in next boot cycle if set amdgpu_ras_enable and/or amdgpu_ras_mask to 0x0\n"); 16415ca02815Sjsg } 16425ca02815Sjsg } else { 1643f005ef32Sjsg if (boot_cfg == 1) { 16445ca02815Sjsg dev_info(adev->dev, "GECC is enabled\n"); 16455ca02815Sjsg } else { 16465ca02815Sjsg /* enable GECC in next boot cycle if it is disabled 16475ca02815Sjsg * in boot config, or force enable GECC if failed to 16485ca02815Sjsg * get boot configuration 16495ca02815Sjsg */ 16505ca02815Sjsg ret = psp_boot_config_set(adev, BOOT_CONFIG_GECC); 16515ca02815Sjsg if (ret) 16525ca02815Sjsg dev_warn(adev->dev, "PSP set boot config failed\n"); 16535ca02815Sjsg else 16545ca02815Sjsg dev_warn(adev->dev, "GECC will be enabled in next boot cycle\n"); 16555ca02815Sjsg } 16565ca02815Sjsg } 16575ca02815Sjsg } 16585ca02815Sjsg 16591bb76ff1Sjsg psp->ras_context.context.mem_context.shared_mem_size = PSP_RAS_SHARED_MEM_SIZE; 16601bb76ff1Sjsg psp->ras_context.context.ta_load_type = GFX_CMD_ID_LOAD_TA; 16611bb76ff1Sjsg 1662f005ef32Sjsg if (!psp->ras_context.context.mem_context.shared_buf) { 16631bb76ff1Sjsg ret = psp_ta_init_shared_buf(psp, &psp->ras_context.context.mem_context); 1664c349dbc7Sjsg if (ret) 1665c349dbc7Sjsg return ret; 1666c349dbc7Sjsg } 1667c349dbc7Sjsg 16681bb76ff1Sjsg ras_cmd = (struct ta_ras_shared_memory *)psp->ras_context.context.mem_context.shared_buf; 16691bb76ff1Sjsg memset(ras_cmd, 0, sizeof(struct ta_ras_shared_memory)); 1670c349dbc7Sjsg 16711bb76ff1Sjsg if (amdgpu_ras_is_poison_mode_supported(adev)) 16721bb76ff1Sjsg ras_cmd->ras_in_message.init_flags.poison_mode_en = 1; 1673f005ef32Sjsg if (!adev->gmc.xgmi.connected_to_cpu && !adev->gmc.is_app_apu) 16741bb76ff1Sjsg ras_cmd->ras_in_message.init_flags.dgpu_mode = 1; 1675f005ef32Sjsg ras_cmd->ras_in_message.init_flags.xcc_mask = 1676f005ef32Sjsg adev->gfx.xcc_mask; 1677f005ef32Sjsg ras_cmd->ras_in_message.init_flags.channel_dis_num = hweight32(adev->gmc.m_half_use) * 2; 16781bb76ff1Sjsg 16791bb76ff1Sjsg ret = psp_ta_load(psp, &psp->ras_context.context); 16801bb76ff1Sjsg 16811bb76ff1Sjsg if (!ret && !ras_cmd->ras_status) 16821bb76ff1Sjsg psp->ras_context.context.initialized = true; 16831bb76ff1Sjsg else { 16841bb76ff1Sjsg if (ras_cmd->ras_status) 16851bb76ff1Sjsg dev_warn(psp->adev->dev, "RAS Init Status: 0x%X\n", ras_cmd->ras_status); 1686f005ef32Sjsg 1687f005ef32Sjsg /* fail to load RAS TA */ 1688f005ef32Sjsg psp->ras_context.context.initialized = false; 16891bb76ff1Sjsg } 16901bb76ff1Sjsg 16911bb76ff1Sjsg return ret; 1692c349dbc7Sjsg } 1693ad8b1aafSjsg 1694ad8b1aafSjsg int psp_ras_trigger_error(struct psp_context *psp, 1695f005ef32Sjsg struct ta_ras_trigger_error_input *info, uint32_t instance_mask) 1696ad8b1aafSjsg { 1697ad8b1aafSjsg struct ta_ras_shared_memory *ras_cmd; 1698f005ef32Sjsg struct amdgpu_device *adev = psp->adev; 1699ad8b1aafSjsg int ret; 1700f005ef32Sjsg uint32_t dev_mask; 1701ad8b1aafSjsg 17025ca02815Sjsg if (!psp->ras_context.context.initialized) 1703ad8b1aafSjsg return -EINVAL; 1704ad8b1aafSjsg 1705f005ef32Sjsg switch (info->block_id) { 1706f005ef32Sjsg case TA_RAS_BLOCK__GFX: 1707f005ef32Sjsg dev_mask = GET_MASK(GC, instance_mask); 1708f005ef32Sjsg break; 1709f005ef32Sjsg case TA_RAS_BLOCK__SDMA: 1710f005ef32Sjsg dev_mask = GET_MASK(SDMA0, instance_mask); 1711f005ef32Sjsg break; 1712f005ef32Sjsg case TA_RAS_BLOCK__VCN: 1713f005ef32Sjsg case TA_RAS_BLOCK__JPEG: 1714f005ef32Sjsg dev_mask = GET_MASK(VCN, instance_mask); 1715f005ef32Sjsg break; 1716f005ef32Sjsg default: 1717f005ef32Sjsg dev_mask = instance_mask; 1718f005ef32Sjsg break; 1719f005ef32Sjsg } 1720f005ef32Sjsg 1721f005ef32Sjsg /* reuse sub_block_index for backward compatibility */ 1722f005ef32Sjsg dev_mask <<= AMDGPU_RAS_INST_SHIFT; 1723f005ef32Sjsg dev_mask &= AMDGPU_RAS_INST_MASK; 1724f005ef32Sjsg info->sub_block_index |= dev_mask; 1725f005ef32Sjsg 17265ca02815Sjsg ras_cmd = (struct ta_ras_shared_memory *)psp->ras_context.context.mem_context.shared_buf; 1727ad8b1aafSjsg memset(ras_cmd, 0, sizeof(struct ta_ras_shared_memory)); 1728ad8b1aafSjsg 1729ad8b1aafSjsg ras_cmd->cmd_id = TA_RAS_COMMAND__TRIGGER_ERROR; 1730ad8b1aafSjsg ras_cmd->ras_in_message.trigger_error = *info; 1731ad8b1aafSjsg 1732ad8b1aafSjsg ret = psp_ras_invoke(psp, ras_cmd->cmd_id); 1733ad8b1aafSjsg if (ret) 1734ad8b1aafSjsg return -EINVAL; 1735ad8b1aafSjsg 1736ad8b1aafSjsg /* If err_event_athub occurs error inject was successful, however 1737f005ef32Sjsg * return status from TA is no long reliable 1738f005ef32Sjsg */ 1739ad8b1aafSjsg if (amdgpu_ras_intr_triggered()) 1740ad8b1aafSjsg return 0; 1741ad8b1aafSjsg 17421bb76ff1Sjsg if (ras_cmd->ras_status == TA_RAS_STATUS__TEE_ERROR_ACCESS_DENIED) 17431bb76ff1Sjsg return -EACCES; 17441bb76ff1Sjsg else if (ras_cmd->ras_status) 17451bb76ff1Sjsg return -EINVAL; 17461bb76ff1Sjsg 17471bb76ff1Sjsg return 0; 1748ad8b1aafSjsg } 1749c349dbc7Sjsg // ras end 1750c349dbc7Sjsg 1751c349dbc7Sjsg // HDCP start 1752c349dbc7Sjsg static int psp_hdcp_initialize(struct psp_context *psp) 1753c349dbc7Sjsg { 1754c349dbc7Sjsg int ret; 1755c349dbc7Sjsg 1756c349dbc7Sjsg /* 1757c349dbc7Sjsg * TODO: bypass the initialize in sriov for now 1758c349dbc7Sjsg */ 1759c349dbc7Sjsg if (amdgpu_sriov_vf(psp->adev)) 1760c349dbc7Sjsg return 0; 1761c349dbc7Sjsg 17621bb76ff1Sjsg if (!psp->hdcp_context.context.bin_desc.size_bytes || 17631bb76ff1Sjsg !psp->hdcp_context.context.bin_desc.start_addr) { 1764c349dbc7Sjsg dev_info(psp->adev->dev, "HDCP: optional hdcp ta ucode is not available\n"); 1765c349dbc7Sjsg return 0; 1766c349dbc7Sjsg } 1767c349dbc7Sjsg 17681bb76ff1Sjsg psp->hdcp_context.context.mem_context.shared_mem_size = PSP_HDCP_SHARED_MEM_SIZE; 17691bb76ff1Sjsg psp->hdcp_context.context.ta_load_type = GFX_CMD_ID_LOAD_TA; 17701bb76ff1Sjsg 177155121f49Sjsg if (!psp->hdcp_context.context.mem_context.shared_buf) { 17721bb76ff1Sjsg ret = psp_ta_init_shared_buf(psp, &psp->hdcp_context.context.mem_context); 1773c349dbc7Sjsg if (ret) 1774c349dbc7Sjsg return ret; 1775c349dbc7Sjsg } 1776c349dbc7Sjsg 17771bb76ff1Sjsg ret = psp_ta_load(psp, &psp->hdcp_context.context); 17781bb76ff1Sjsg if (!ret) { 17791bb76ff1Sjsg psp->hdcp_context.context.initialized = true; 17801bb76ff1Sjsg rw_init(&psp->hdcp_context.mutex, "pspcp"); 1781c349dbc7Sjsg } 1782c349dbc7Sjsg 1783c349dbc7Sjsg return ret; 1784c349dbc7Sjsg } 1785c349dbc7Sjsg 1786c349dbc7Sjsg int psp_hdcp_invoke(struct psp_context *psp, uint32_t ta_cmd_id) 1787c349dbc7Sjsg { 1788c349dbc7Sjsg /* 1789c349dbc7Sjsg * TODO: bypass the loading in sriov for now 1790c349dbc7Sjsg */ 1791c349dbc7Sjsg if (amdgpu_sriov_vf(psp->adev)) 1792c349dbc7Sjsg return 0; 1793c349dbc7Sjsg 17941bb76ff1Sjsg return psp_ta_invoke(psp, ta_cmd_id, &psp->hdcp_context.context); 1795c349dbc7Sjsg } 1796c349dbc7Sjsg 1797c349dbc7Sjsg static int psp_hdcp_terminate(struct psp_context *psp) 1798c349dbc7Sjsg { 1799c349dbc7Sjsg int ret; 1800c349dbc7Sjsg 1801c349dbc7Sjsg /* 1802c349dbc7Sjsg * TODO: bypass the terminate in sriov for now 1803c349dbc7Sjsg */ 1804c349dbc7Sjsg if (amdgpu_sriov_vf(psp->adev)) 1805c349dbc7Sjsg return 0; 1806c349dbc7Sjsg 18071bb76ff1Sjsg if (!psp->hdcp_context.context.initialized) 1808c349dbc7Sjsg return 0; 1809c349dbc7Sjsg 18101bb76ff1Sjsg ret = psp_ta_unload(psp, &psp->hdcp_context.context); 1811c349dbc7Sjsg 18125ca02815Sjsg psp->hdcp_context.context.initialized = false; 1813c349dbc7Sjsg 18141bb76ff1Sjsg return ret; 1815c349dbc7Sjsg } 1816c349dbc7Sjsg // HDCP end 1817c349dbc7Sjsg 1818c349dbc7Sjsg // DTM start 1819c349dbc7Sjsg static int psp_dtm_initialize(struct psp_context *psp) 1820c349dbc7Sjsg { 1821c349dbc7Sjsg int ret; 1822c349dbc7Sjsg 1823c349dbc7Sjsg /* 1824c349dbc7Sjsg * TODO: bypass the initialize in sriov for now 1825c349dbc7Sjsg */ 1826c349dbc7Sjsg if (amdgpu_sriov_vf(psp->adev)) 1827c349dbc7Sjsg return 0; 1828c349dbc7Sjsg 18291bb76ff1Sjsg if (!psp->dtm_context.context.bin_desc.size_bytes || 18301bb76ff1Sjsg !psp->dtm_context.context.bin_desc.start_addr) { 1831c349dbc7Sjsg dev_info(psp->adev->dev, "DTM: optional dtm ta ucode is not available\n"); 1832c349dbc7Sjsg return 0; 1833c349dbc7Sjsg } 1834c349dbc7Sjsg 18351bb76ff1Sjsg psp->dtm_context.context.mem_context.shared_mem_size = PSP_DTM_SHARED_MEM_SIZE; 18361bb76ff1Sjsg psp->dtm_context.context.ta_load_type = GFX_CMD_ID_LOAD_TA; 18371bb76ff1Sjsg 183855121f49Sjsg if (!psp->dtm_context.context.mem_context.shared_buf) { 18391bb76ff1Sjsg ret = psp_ta_init_shared_buf(psp, &psp->dtm_context.context.mem_context); 1840c349dbc7Sjsg if (ret) 1841c349dbc7Sjsg return ret; 1842c349dbc7Sjsg } 1843c349dbc7Sjsg 18441bb76ff1Sjsg ret = psp_ta_load(psp, &psp->dtm_context.context); 18451bb76ff1Sjsg if (!ret) { 18461bb76ff1Sjsg psp->dtm_context.context.initialized = true; 18471bb76ff1Sjsg rw_init(&psp->dtm_context.mutex, "pspdtm"); 1848c349dbc7Sjsg } 1849c349dbc7Sjsg 1850c349dbc7Sjsg return ret; 1851c349dbc7Sjsg } 1852c349dbc7Sjsg 1853c349dbc7Sjsg int psp_dtm_invoke(struct psp_context *psp, uint32_t ta_cmd_id) 1854c349dbc7Sjsg { 1855c349dbc7Sjsg /* 1856c349dbc7Sjsg * TODO: bypass the loading in sriov for now 1857c349dbc7Sjsg */ 1858c349dbc7Sjsg if (amdgpu_sriov_vf(psp->adev)) 1859c349dbc7Sjsg return 0; 1860c349dbc7Sjsg 18611bb76ff1Sjsg return psp_ta_invoke(psp, ta_cmd_id, &psp->dtm_context.context); 1862c349dbc7Sjsg } 1863c349dbc7Sjsg 1864c349dbc7Sjsg static int psp_dtm_terminate(struct psp_context *psp) 1865c349dbc7Sjsg { 1866c349dbc7Sjsg int ret; 1867c349dbc7Sjsg 1868c349dbc7Sjsg /* 1869c349dbc7Sjsg * TODO: bypass the terminate in sriov for now 1870c349dbc7Sjsg */ 1871c349dbc7Sjsg if (amdgpu_sriov_vf(psp->adev)) 1872c349dbc7Sjsg return 0; 1873c349dbc7Sjsg 18741bb76ff1Sjsg if (!psp->dtm_context.context.initialized) 1875c349dbc7Sjsg return 0; 1876c349dbc7Sjsg 18771bb76ff1Sjsg ret = psp_ta_unload(psp, &psp->dtm_context.context); 1878c349dbc7Sjsg 18795ca02815Sjsg psp->dtm_context.context.initialized = false; 1880c349dbc7Sjsg 18811bb76ff1Sjsg return ret; 1882c349dbc7Sjsg } 1883c349dbc7Sjsg // DTM end 1884c349dbc7Sjsg 1885ad8b1aafSjsg // RAP start 1886ad8b1aafSjsg static int psp_rap_initialize(struct psp_context *psp) 1887ad8b1aafSjsg { 1888ad8b1aafSjsg int ret; 18895ca02815Sjsg enum ta_rap_status status = TA_RAP_STATUS__SUCCESS; 1890ad8b1aafSjsg 1891ad8b1aafSjsg /* 1892ad8b1aafSjsg * TODO: bypass the initialize in sriov for now 1893ad8b1aafSjsg */ 1894ad8b1aafSjsg if (amdgpu_sriov_vf(psp->adev)) 1895ad8b1aafSjsg return 0; 1896ad8b1aafSjsg 18971bb76ff1Sjsg if (!psp->rap_context.context.bin_desc.size_bytes || 18981bb76ff1Sjsg !psp->rap_context.context.bin_desc.start_addr) { 1899ad8b1aafSjsg dev_info(psp->adev->dev, "RAP: optional rap ta ucode is not available\n"); 1900ad8b1aafSjsg return 0; 1901ad8b1aafSjsg } 1902ad8b1aafSjsg 19031bb76ff1Sjsg psp->rap_context.context.mem_context.shared_mem_size = PSP_RAP_SHARED_MEM_SIZE; 19041bb76ff1Sjsg psp->rap_context.context.ta_load_type = GFX_CMD_ID_LOAD_TA; 19051bb76ff1Sjsg 190655121f49Sjsg if (!psp->rap_context.context.mem_context.shared_buf) { 19071bb76ff1Sjsg ret = psp_ta_init_shared_buf(psp, &psp->rap_context.context.mem_context); 1908ad8b1aafSjsg if (ret) 1909ad8b1aafSjsg return ret; 1910ad8b1aafSjsg } 1911ad8b1aafSjsg 19121bb76ff1Sjsg ret = psp_ta_load(psp, &psp->rap_context.context); 19131bb76ff1Sjsg if (!ret) { 19141bb76ff1Sjsg psp->rap_context.context.initialized = true; 19151bb76ff1Sjsg rw_init(&psp->rap_context.mutex, "psprap"); 19161bb76ff1Sjsg } else 1917ad8b1aafSjsg return ret; 1918ad8b1aafSjsg 19195ca02815Sjsg ret = psp_rap_invoke(psp, TA_CMD_RAP__INITIALIZE, &status); 19205ca02815Sjsg if (ret || status != TA_RAP_STATUS__SUCCESS) { 19211bb76ff1Sjsg psp_rap_terminate(psp); 19221bb76ff1Sjsg /* free rap shared memory */ 19235ca02815Sjsg psp_ta_free_shared_buf(&psp->rap_context.context.mem_context); 1924ad8b1aafSjsg 19255ca02815Sjsg dev_warn(psp->adev->dev, "RAP TA initialize fail (%d) status %d.\n", 19265ca02815Sjsg ret, status); 19275ca02815Sjsg 19285ca02815Sjsg return ret; 1929ad8b1aafSjsg } 1930ad8b1aafSjsg 1931ad8b1aafSjsg return 0; 1932ad8b1aafSjsg } 1933ad8b1aafSjsg 1934ad8b1aafSjsg static int psp_rap_terminate(struct psp_context *psp) 1935ad8b1aafSjsg { 1936ad8b1aafSjsg int ret; 1937ad8b1aafSjsg 19385ca02815Sjsg if (!psp->rap_context.context.initialized) 1939ad8b1aafSjsg return 0; 1940ad8b1aafSjsg 19411bb76ff1Sjsg ret = psp_ta_unload(psp, &psp->rap_context.context); 1942ad8b1aafSjsg 19435ca02815Sjsg psp->rap_context.context.initialized = false; 1944ad8b1aafSjsg 1945ad8b1aafSjsg return ret; 1946ad8b1aafSjsg } 1947ad8b1aafSjsg 19485ca02815Sjsg int psp_rap_invoke(struct psp_context *psp, uint32_t ta_cmd_id, enum ta_rap_status *status) 1949ad8b1aafSjsg { 1950ad8b1aafSjsg struct ta_rap_shared_memory *rap_cmd; 19515ca02815Sjsg int ret = 0; 1952ad8b1aafSjsg 19535ca02815Sjsg if (!psp->rap_context.context.initialized) 19545ca02815Sjsg return 0; 1955ad8b1aafSjsg 1956ad8b1aafSjsg if (ta_cmd_id != TA_CMD_RAP__INITIALIZE && 1957ad8b1aafSjsg ta_cmd_id != TA_CMD_RAP__VALIDATE_L0) 1958ad8b1aafSjsg return -EINVAL; 1959ad8b1aafSjsg 1960ad8b1aafSjsg mutex_lock(&psp->rap_context.mutex); 1961ad8b1aafSjsg 1962ad8b1aafSjsg rap_cmd = (struct ta_rap_shared_memory *) 19635ca02815Sjsg psp->rap_context.context.mem_context.shared_buf; 1964ad8b1aafSjsg memset(rap_cmd, 0, sizeof(struct ta_rap_shared_memory)); 1965ad8b1aafSjsg 1966ad8b1aafSjsg rap_cmd->cmd_id = ta_cmd_id; 1967ad8b1aafSjsg rap_cmd->validation_method_id = METHOD_A; 1968ad8b1aafSjsg 19691bb76ff1Sjsg ret = psp_ta_invoke(psp, rap_cmd->cmd_id, &psp->rap_context.context); 19705ca02815Sjsg if (ret) 19715ca02815Sjsg goto out_unlock; 19725ca02815Sjsg 19735ca02815Sjsg if (status) 19745ca02815Sjsg *status = rap_cmd->rap_status; 19755ca02815Sjsg 19765ca02815Sjsg out_unlock: 1977ad8b1aafSjsg mutex_unlock(&psp->rap_context.mutex); 19785ca02815Sjsg 19795ca02815Sjsg return ret; 19805ca02815Sjsg } 19815ca02815Sjsg // RAP end 19825ca02815Sjsg 19835ca02815Sjsg /* securedisplay start */ 19845ca02815Sjsg static int psp_securedisplay_initialize(struct psp_context *psp) 19855ca02815Sjsg { 19865ca02815Sjsg int ret; 1987f005ef32Sjsg struct ta_securedisplay_cmd *securedisplay_cmd; 19885ca02815Sjsg 19895ca02815Sjsg /* 19905ca02815Sjsg * TODO: bypass the initialize in sriov for now 19915ca02815Sjsg */ 19925ca02815Sjsg if (amdgpu_sriov_vf(psp->adev)) 19935ca02815Sjsg return 0; 19945ca02815Sjsg 19951bb76ff1Sjsg if (!psp->securedisplay_context.context.bin_desc.size_bytes || 19961bb76ff1Sjsg !psp->securedisplay_context.context.bin_desc.start_addr) { 19975ca02815Sjsg dev_info(psp->adev->dev, "SECUREDISPLAY: securedisplay ta ucode is not available\n"); 19985ca02815Sjsg return 0; 19995ca02815Sjsg } 20005ca02815Sjsg 20016d5481daSjsg #ifdef __OpenBSD__ 20026d5481daSjsg /* 20036d5481daSjsg * with 20230117 or later firmware or later on renoir: 20046d5481daSjsg * 20056d5481daSjsg * [drm] psp gfx command LOAD_TA(0x1) failed and response status is (0x7) 20066d5481daSjsg * [drm] psp gfx command INVOKE_CMD(0x3) failed and response status is (0x4) 20076d5481daSjsg * psp_securedisplay_parse_resp_status *ERROR* Secure display: Generic Failure 20086d5481daSjsg * psp_securedisplay_initialize *ERROR* SECUREDISPLAY: query 20096d5481daSjsg * securedisplay TA failed. ret 0x0 20106d5481daSjsg */ 20116d5481daSjsg return 0; 20126d5481daSjsg #endif 20136d5481daSjsg 20141bb76ff1Sjsg psp->securedisplay_context.context.mem_context.shared_mem_size = 20151bb76ff1Sjsg PSP_SECUREDISPLAY_SHARED_MEM_SIZE; 20161bb76ff1Sjsg psp->securedisplay_context.context.ta_load_type = GFX_CMD_ID_LOAD_TA; 20171bb76ff1Sjsg 20185ca02815Sjsg if (!psp->securedisplay_context.context.initialized) { 20191bb76ff1Sjsg ret = psp_ta_init_shared_buf(psp, 20201bb76ff1Sjsg &psp->securedisplay_context.context.mem_context); 20215ca02815Sjsg if (ret) 20225ca02815Sjsg return ret; 20235ca02815Sjsg } 20245ca02815Sjsg 20251bb76ff1Sjsg ret = psp_ta_load(psp, &psp->securedisplay_context.context); 20261bb76ff1Sjsg if (!ret) { 20271bb76ff1Sjsg psp->securedisplay_context.context.initialized = true; 20281bb76ff1Sjsg rw_init(&psp->securedisplay_context.mutex, "pscm"); 20291bb76ff1Sjsg } else 20305ca02815Sjsg return ret; 20315ca02815Sjsg 2032f005ef32Sjsg mutex_lock(&psp->securedisplay_context.mutex); 2033f005ef32Sjsg 20345ca02815Sjsg psp_prep_securedisplay_cmd_buf(psp, &securedisplay_cmd, 20355ca02815Sjsg TA_SECUREDISPLAY_COMMAND__QUERY_TA); 20365ca02815Sjsg 20375ca02815Sjsg ret = psp_securedisplay_invoke(psp, TA_SECUREDISPLAY_COMMAND__QUERY_TA); 2038f005ef32Sjsg 2039f005ef32Sjsg mutex_unlock(&psp->securedisplay_context.mutex); 2040f005ef32Sjsg 20415ca02815Sjsg if (ret) { 20421bb76ff1Sjsg psp_securedisplay_terminate(psp); 20431bb76ff1Sjsg /* free securedisplay shared memory */ 20445ca02815Sjsg psp_ta_free_shared_buf(&psp->securedisplay_context.context.mem_context); 20455ca02815Sjsg dev_err(psp->adev->dev, "SECUREDISPLAY TA initialize fail.\n"); 20465ca02815Sjsg return -EINVAL; 20475ca02815Sjsg } 20485ca02815Sjsg 20495ca02815Sjsg if (securedisplay_cmd->status != TA_SECUREDISPLAY_STATUS__SUCCESS) { 20505ca02815Sjsg psp_securedisplay_parse_resp_status(psp, securedisplay_cmd->status); 20515ca02815Sjsg dev_err(psp->adev->dev, "SECUREDISPLAY: query securedisplay TA failed. ret 0x%x\n", 20525ca02815Sjsg securedisplay_cmd->securedisplay_out_message.query_ta.query_cmd_ret); 20539ee584c9Sjsg /* don't try again */ 20549ee584c9Sjsg psp->securedisplay_context.context.bin_desc.size_bytes = 0; 20555ca02815Sjsg } 20565ca02815Sjsg 20575ca02815Sjsg return 0; 20585ca02815Sjsg } 20595ca02815Sjsg 20605ca02815Sjsg static int psp_securedisplay_terminate(struct psp_context *psp) 20615ca02815Sjsg { 20625ca02815Sjsg int ret; 20635ca02815Sjsg 20645ca02815Sjsg /* 20655ca02815Sjsg * TODO:bypass the terminate in sriov for now 20665ca02815Sjsg */ 20675ca02815Sjsg if (amdgpu_sriov_vf(psp->adev)) 20685ca02815Sjsg return 0; 20695ca02815Sjsg 20705ca02815Sjsg if (!psp->securedisplay_context.context.initialized) 20715ca02815Sjsg return 0; 20725ca02815Sjsg 20731bb76ff1Sjsg ret = psp_ta_unload(psp, &psp->securedisplay_context.context); 20745ca02815Sjsg 20755ca02815Sjsg psp->securedisplay_context.context.initialized = false; 20765ca02815Sjsg 20775ca02815Sjsg return ret; 20785ca02815Sjsg } 20795ca02815Sjsg 20805ca02815Sjsg int psp_securedisplay_invoke(struct psp_context *psp, uint32_t ta_cmd_id) 20815ca02815Sjsg { 20825ca02815Sjsg int ret; 20835ca02815Sjsg 20845ca02815Sjsg if (!psp->securedisplay_context.context.initialized) 20855ca02815Sjsg return -EINVAL; 20865ca02815Sjsg 20875ca02815Sjsg if (ta_cmd_id != TA_SECUREDISPLAY_COMMAND__QUERY_TA && 20885ca02815Sjsg ta_cmd_id != TA_SECUREDISPLAY_COMMAND__SEND_ROI_CRC) 20895ca02815Sjsg return -EINVAL; 20905ca02815Sjsg 20911bb76ff1Sjsg ret = psp_ta_invoke(psp, ta_cmd_id, &psp->securedisplay_context.context); 20925ca02815Sjsg 20935ca02815Sjsg return ret; 20945ca02815Sjsg } 20955ca02815Sjsg /* SECUREDISPLAY end */ 2096ad8b1aafSjsg 2097f005ef32Sjsg int amdgpu_psp_wait_for_bootloader(struct amdgpu_device *adev) 2098f005ef32Sjsg { 2099f005ef32Sjsg struct psp_context *psp = &adev->psp; 2100f005ef32Sjsg int ret = 0; 2101f005ef32Sjsg 2102f005ef32Sjsg if (!amdgpu_sriov_vf(adev) && psp->funcs && psp->funcs->wait_for_bootloader != NULL) 2103f005ef32Sjsg ret = psp->funcs->wait_for_bootloader(psp); 2104f005ef32Sjsg 2105f005ef32Sjsg return ret; 2106f005ef32Sjsg } 2107f005ef32Sjsg 2108fb4d8502Sjsg static int psp_hw_start(struct psp_context *psp) 2109fb4d8502Sjsg { 2110fb4d8502Sjsg struct amdgpu_device *adev = psp->adev; 2111fb4d8502Sjsg int ret; 2112fb4d8502Sjsg 2113c349dbc7Sjsg if (!amdgpu_sriov_vf(adev)) { 21145ca02815Sjsg if ((is_psp_fw_valid(psp->kdb)) && 2115c349dbc7Sjsg (psp->funcs->bootloader_load_kdb != NULL)) { 2116c349dbc7Sjsg ret = psp_bootloader_load_kdb(psp); 2117c349dbc7Sjsg if (ret) { 2118c349dbc7Sjsg DRM_ERROR("PSP load kdb failed!\n"); 2119fb4d8502Sjsg return ret; 2120c349dbc7Sjsg } 2121c349dbc7Sjsg } 2122fb4d8502Sjsg 21235ca02815Sjsg if ((is_psp_fw_valid(psp->spl)) && 21245ca02815Sjsg (psp->funcs->bootloader_load_spl != NULL)) { 2125ad8b1aafSjsg ret = psp_bootloader_load_spl(psp); 2126ad8b1aafSjsg if (ret) { 2127ad8b1aafSjsg DRM_ERROR("PSP load spl failed!\n"); 2128ad8b1aafSjsg return ret; 2129ad8b1aafSjsg } 2130ad8b1aafSjsg } 2131ad8b1aafSjsg 21325ca02815Sjsg if ((is_psp_fw_valid(psp->sys)) && 21335ca02815Sjsg (psp->funcs->bootloader_load_sysdrv != NULL)) { 2134c349dbc7Sjsg ret = psp_bootloader_load_sysdrv(psp); 2135c349dbc7Sjsg if (ret) { 2136c349dbc7Sjsg DRM_ERROR("PSP load sys drv failed!\n"); 2137fb4d8502Sjsg return ret; 2138fb4d8502Sjsg } 21395ca02815Sjsg } 2140fb4d8502Sjsg 21415ca02815Sjsg if ((is_psp_fw_valid(psp->soc_drv)) && 21425ca02815Sjsg (psp->funcs->bootloader_load_soc_drv != NULL)) { 21435ca02815Sjsg ret = psp_bootloader_load_soc_drv(psp); 21445ca02815Sjsg if (ret) { 21455ca02815Sjsg DRM_ERROR("PSP load soc drv failed!\n"); 21465ca02815Sjsg return ret; 21475ca02815Sjsg } 21485ca02815Sjsg } 21495ca02815Sjsg 21505ca02815Sjsg if ((is_psp_fw_valid(psp->intf_drv)) && 21515ca02815Sjsg (psp->funcs->bootloader_load_intf_drv != NULL)) { 21525ca02815Sjsg ret = psp_bootloader_load_intf_drv(psp); 21535ca02815Sjsg if (ret) { 21545ca02815Sjsg DRM_ERROR("PSP load intf drv failed!\n"); 21555ca02815Sjsg return ret; 21565ca02815Sjsg } 21575ca02815Sjsg } 21585ca02815Sjsg 21595ca02815Sjsg if ((is_psp_fw_valid(psp->dbg_drv)) && 21605ca02815Sjsg (psp->funcs->bootloader_load_dbg_drv != NULL)) { 21615ca02815Sjsg ret = psp_bootloader_load_dbg_drv(psp); 21625ca02815Sjsg if (ret) { 21635ca02815Sjsg DRM_ERROR("PSP load dbg drv failed!\n"); 21645ca02815Sjsg return ret; 21655ca02815Sjsg } 21665ca02815Sjsg } 21675ca02815Sjsg 21681bb76ff1Sjsg if ((is_psp_fw_valid(psp->ras_drv)) && 21691bb76ff1Sjsg (psp->funcs->bootloader_load_ras_drv != NULL)) { 21701bb76ff1Sjsg ret = psp_bootloader_load_ras_drv(psp); 21711bb76ff1Sjsg if (ret) { 21721bb76ff1Sjsg DRM_ERROR("PSP load ras_drv failed!\n"); 21731bb76ff1Sjsg return ret; 21741bb76ff1Sjsg } 21751bb76ff1Sjsg } 21761bb76ff1Sjsg 21775ca02815Sjsg if ((is_psp_fw_valid(psp->sos)) && 21785ca02815Sjsg (psp->funcs->bootloader_load_sos != NULL)) { 2179c349dbc7Sjsg ret = psp_bootloader_load_sos(psp); 2180c349dbc7Sjsg if (ret) { 2181c349dbc7Sjsg DRM_ERROR("PSP load sos failed!\n"); 2182c349dbc7Sjsg return ret; 2183c349dbc7Sjsg } 2184c349dbc7Sjsg } 21855ca02815Sjsg } 2186c349dbc7Sjsg 2187fb4d8502Sjsg ret = psp_ring_create(psp, PSP_RING_TYPE__KM); 2188c349dbc7Sjsg if (ret) { 2189c349dbc7Sjsg DRM_ERROR("PSP create ring failed!\n"); 2190fb4d8502Sjsg return ret; 2191c349dbc7Sjsg } 2192fb4d8502Sjsg 21937ec34d6bSjsg if (amdgpu_sriov_vf(adev) && amdgpu_in_reset(adev)) 21947ec34d6bSjsg goto skip_pin_bo; 21957ec34d6bSjsg 2196f005ef32Sjsg if (!psp_boottime_tmr(psp)) { 2197c349dbc7Sjsg ret = psp_tmr_init(psp); 2198c349dbc7Sjsg if (ret) { 2199c349dbc7Sjsg DRM_ERROR("PSP tmr init failed!\n"); 2200c349dbc7Sjsg return ret; 2201c349dbc7Sjsg } 2202f005ef32Sjsg } 2203c349dbc7Sjsg 22047ec34d6bSjsg skip_pin_bo: 2205c349dbc7Sjsg /* 2206ad8b1aafSjsg * For ASICs with DF Cstate management centralized 2207c349dbc7Sjsg * to PMFW, TMR setup should be performed after PMFW 2208c349dbc7Sjsg * loaded and before other non-psp firmware loaded. 2209c349dbc7Sjsg */ 2210ad8b1aafSjsg if (psp->pmfw_centralized_cstate_management) { 2211ad8b1aafSjsg ret = psp_load_smu_fw(psp); 2212ad8b1aafSjsg if (ret) 2213ad8b1aafSjsg return ret; 2214ad8b1aafSjsg } 2215ad8b1aafSjsg 2216fb4d8502Sjsg ret = psp_tmr_load(psp); 2217c349dbc7Sjsg if (ret) { 2218c349dbc7Sjsg DRM_ERROR("PSP load tmr failed!\n"); 2219fb4d8502Sjsg return ret; 2220c349dbc7Sjsg } 2221fb4d8502Sjsg 2222fb4d8502Sjsg return 0; 2223fb4d8502Sjsg } 2224fb4d8502Sjsg 2225c349dbc7Sjsg static int psp_get_fw_type(struct amdgpu_firmware_info *ucode, 2226c349dbc7Sjsg enum psp_gfx_fw_type *type) 2227c349dbc7Sjsg { 2228c349dbc7Sjsg switch (ucode->ucode_id) { 22291bb76ff1Sjsg case AMDGPU_UCODE_ID_CAP: 22301bb76ff1Sjsg *type = GFX_FW_TYPE_CAP; 22311bb76ff1Sjsg break; 2232c349dbc7Sjsg case AMDGPU_UCODE_ID_SDMA0: 2233c349dbc7Sjsg *type = GFX_FW_TYPE_SDMA0; 2234c349dbc7Sjsg break; 2235c349dbc7Sjsg case AMDGPU_UCODE_ID_SDMA1: 2236c349dbc7Sjsg *type = GFX_FW_TYPE_SDMA1; 2237c349dbc7Sjsg break; 2238c349dbc7Sjsg case AMDGPU_UCODE_ID_SDMA2: 2239c349dbc7Sjsg *type = GFX_FW_TYPE_SDMA2; 2240c349dbc7Sjsg break; 2241c349dbc7Sjsg case AMDGPU_UCODE_ID_SDMA3: 2242c349dbc7Sjsg *type = GFX_FW_TYPE_SDMA3; 2243c349dbc7Sjsg break; 2244c349dbc7Sjsg case AMDGPU_UCODE_ID_SDMA4: 2245c349dbc7Sjsg *type = GFX_FW_TYPE_SDMA4; 2246c349dbc7Sjsg break; 2247c349dbc7Sjsg case AMDGPU_UCODE_ID_SDMA5: 2248c349dbc7Sjsg *type = GFX_FW_TYPE_SDMA5; 2249c349dbc7Sjsg break; 2250c349dbc7Sjsg case AMDGPU_UCODE_ID_SDMA6: 2251c349dbc7Sjsg *type = GFX_FW_TYPE_SDMA6; 2252c349dbc7Sjsg break; 2253c349dbc7Sjsg case AMDGPU_UCODE_ID_SDMA7: 2254c349dbc7Sjsg *type = GFX_FW_TYPE_SDMA7; 2255c349dbc7Sjsg break; 2256ad8b1aafSjsg case AMDGPU_UCODE_ID_CP_MES: 2257ad8b1aafSjsg *type = GFX_FW_TYPE_CP_MES; 2258ad8b1aafSjsg break; 2259ad8b1aafSjsg case AMDGPU_UCODE_ID_CP_MES_DATA: 2260ad8b1aafSjsg *type = GFX_FW_TYPE_MES_STACK; 2261ad8b1aafSjsg break; 22621bb76ff1Sjsg case AMDGPU_UCODE_ID_CP_MES1: 22631bb76ff1Sjsg *type = GFX_FW_TYPE_CP_MES_KIQ; 22641bb76ff1Sjsg break; 22651bb76ff1Sjsg case AMDGPU_UCODE_ID_CP_MES1_DATA: 22661bb76ff1Sjsg *type = GFX_FW_TYPE_MES_KIQ_STACK; 22671bb76ff1Sjsg break; 2268c349dbc7Sjsg case AMDGPU_UCODE_ID_CP_CE: 2269c349dbc7Sjsg *type = GFX_FW_TYPE_CP_CE; 2270c349dbc7Sjsg break; 2271c349dbc7Sjsg case AMDGPU_UCODE_ID_CP_PFP: 2272c349dbc7Sjsg *type = GFX_FW_TYPE_CP_PFP; 2273c349dbc7Sjsg break; 2274c349dbc7Sjsg case AMDGPU_UCODE_ID_CP_ME: 2275c349dbc7Sjsg *type = GFX_FW_TYPE_CP_ME; 2276c349dbc7Sjsg break; 2277c349dbc7Sjsg case AMDGPU_UCODE_ID_CP_MEC1: 2278c349dbc7Sjsg *type = GFX_FW_TYPE_CP_MEC; 2279c349dbc7Sjsg break; 2280c349dbc7Sjsg case AMDGPU_UCODE_ID_CP_MEC1_JT: 2281c349dbc7Sjsg *type = GFX_FW_TYPE_CP_MEC_ME1; 2282c349dbc7Sjsg break; 2283c349dbc7Sjsg case AMDGPU_UCODE_ID_CP_MEC2: 2284c349dbc7Sjsg *type = GFX_FW_TYPE_CP_MEC; 2285c349dbc7Sjsg break; 2286c349dbc7Sjsg case AMDGPU_UCODE_ID_CP_MEC2_JT: 2287c349dbc7Sjsg *type = GFX_FW_TYPE_CP_MEC_ME2; 2288c349dbc7Sjsg break; 22891bb76ff1Sjsg case AMDGPU_UCODE_ID_RLC_P: 22901bb76ff1Sjsg *type = GFX_FW_TYPE_RLC_P; 22911bb76ff1Sjsg break; 22921bb76ff1Sjsg case AMDGPU_UCODE_ID_RLC_V: 22931bb76ff1Sjsg *type = GFX_FW_TYPE_RLC_V; 22941bb76ff1Sjsg break; 2295c349dbc7Sjsg case AMDGPU_UCODE_ID_RLC_G: 2296c349dbc7Sjsg *type = GFX_FW_TYPE_RLC_G; 2297c349dbc7Sjsg break; 2298c349dbc7Sjsg case AMDGPU_UCODE_ID_RLC_RESTORE_LIST_CNTL: 2299c349dbc7Sjsg *type = GFX_FW_TYPE_RLC_RESTORE_LIST_SRM_CNTL; 2300c349dbc7Sjsg break; 2301c349dbc7Sjsg case AMDGPU_UCODE_ID_RLC_RESTORE_LIST_GPM_MEM: 2302c349dbc7Sjsg *type = GFX_FW_TYPE_RLC_RESTORE_LIST_GPM_MEM; 2303c349dbc7Sjsg break; 2304c349dbc7Sjsg case AMDGPU_UCODE_ID_RLC_RESTORE_LIST_SRM_MEM: 2305c349dbc7Sjsg *type = GFX_FW_TYPE_RLC_RESTORE_LIST_SRM_MEM; 2306c349dbc7Sjsg break; 2307ad8b1aafSjsg case AMDGPU_UCODE_ID_RLC_IRAM: 2308ad8b1aafSjsg *type = GFX_FW_TYPE_RLC_IRAM; 2309ad8b1aafSjsg break; 2310ad8b1aafSjsg case AMDGPU_UCODE_ID_RLC_DRAM: 2311ad8b1aafSjsg *type = GFX_FW_TYPE_RLC_DRAM_BOOT; 2312ad8b1aafSjsg break; 23131bb76ff1Sjsg case AMDGPU_UCODE_ID_GLOBAL_TAP_DELAYS: 23141bb76ff1Sjsg *type = GFX_FW_TYPE_GLOBAL_TAP_DELAYS; 23151bb76ff1Sjsg break; 23161bb76ff1Sjsg case AMDGPU_UCODE_ID_SE0_TAP_DELAYS: 23171bb76ff1Sjsg *type = GFX_FW_TYPE_SE0_TAP_DELAYS; 23181bb76ff1Sjsg break; 23191bb76ff1Sjsg case AMDGPU_UCODE_ID_SE1_TAP_DELAYS: 23201bb76ff1Sjsg *type = GFX_FW_TYPE_SE1_TAP_DELAYS; 23211bb76ff1Sjsg break; 23221bb76ff1Sjsg case AMDGPU_UCODE_ID_SE2_TAP_DELAYS: 23231bb76ff1Sjsg *type = GFX_FW_TYPE_SE2_TAP_DELAYS; 23241bb76ff1Sjsg break; 23251bb76ff1Sjsg case AMDGPU_UCODE_ID_SE3_TAP_DELAYS: 23261bb76ff1Sjsg *type = GFX_FW_TYPE_SE3_TAP_DELAYS; 23271bb76ff1Sjsg break; 2328c349dbc7Sjsg case AMDGPU_UCODE_ID_SMC: 2329c349dbc7Sjsg *type = GFX_FW_TYPE_SMU; 2330c349dbc7Sjsg break; 23311bb76ff1Sjsg case AMDGPU_UCODE_ID_PPTABLE: 23321bb76ff1Sjsg *type = GFX_FW_TYPE_PPTABLE; 23331bb76ff1Sjsg break; 2334c349dbc7Sjsg case AMDGPU_UCODE_ID_UVD: 2335c349dbc7Sjsg *type = GFX_FW_TYPE_UVD; 2336c349dbc7Sjsg break; 2337c349dbc7Sjsg case AMDGPU_UCODE_ID_UVD1: 2338c349dbc7Sjsg *type = GFX_FW_TYPE_UVD1; 2339c349dbc7Sjsg break; 2340c349dbc7Sjsg case AMDGPU_UCODE_ID_VCE: 2341c349dbc7Sjsg *type = GFX_FW_TYPE_VCE; 2342c349dbc7Sjsg break; 2343c349dbc7Sjsg case AMDGPU_UCODE_ID_VCN: 2344c349dbc7Sjsg *type = GFX_FW_TYPE_VCN; 2345c349dbc7Sjsg break; 2346c349dbc7Sjsg case AMDGPU_UCODE_ID_VCN1: 2347c349dbc7Sjsg *type = GFX_FW_TYPE_VCN1; 2348c349dbc7Sjsg break; 2349c349dbc7Sjsg case AMDGPU_UCODE_ID_DMCU_ERAM: 2350c349dbc7Sjsg *type = GFX_FW_TYPE_DMCU_ERAM; 2351c349dbc7Sjsg break; 2352c349dbc7Sjsg case AMDGPU_UCODE_ID_DMCU_INTV: 2353c349dbc7Sjsg *type = GFX_FW_TYPE_DMCU_ISR; 2354c349dbc7Sjsg break; 2355c349dbc7Sjsg case AMDGPU_UCODE_ID_VCN0_RAM: 2356c349dbc7Sjsg *type = GFX_FW_TYPE_VCN0_RAM; 2357c349dbc7Sjsg break; 2358c349dbc7Sjsg case AMDGPU_UCODE_ID_VCN1_RAM: 2359c349dbc7Sjsg *type = GFX_FW_TYPE_VCN1_RAM; 2360c349dbc7Sjsg break; 2361c349dbc7Sjsg case AMDGPU_UCODE_ID_DMCUB: 2362c349dbc7Sjsg *type = GFX_FW_TYPE_DMUB; 2363c349dbc7Sjsg break; 23641bb76ff1Sjsg case AMDGPU_UCODE_ID_SDMA_UCODE_TH0: 23651bb76ff1Sjsg *type = GFX_FW_TYPE_SDMA_UCODE_TH0; 23661bb76ff1Sjsg break; 23671bb76ff1Sjsg case AMDGPU_UCODE_ID_SDMA_UCODE_TH1: 23681bb76ff1Sjsg *type = GFX_FW_TYPE_SDMA_UCODE_TH1; 23691bb76ff1Sjsg break; 23701bb76ff1Sjsg case AMDGPU_UCODE_ID_IMU_I: 23711bb76ff1Sjsg *type = GFX_FW_TYPE_IMU_I; 23721bb76ff1Sjsg break; 23731bb76ff1Sjsg case AMDGPU_UCODE_ID_IMU_D: 23741bb76ff1Sjsg *type = GFX_FW_TYPE_IMU_D; 23751bb76ff1Sjsg break; 23761bb76ff1Sjsg case AMDGPU_UCODE_ID_CP_RS64_PFP: 23771bb76ff1Sjsg *type = GFX_FW_TYPE_RS64_PFP; 23781bb76ff1Sjsg break; 23791bb76ff1Sjsg case AMDGPU_UCODE_ID_CP_RS64_ME: 23801bb76ff1Sjsg *type = GFX_FW_TYPE_RS64_ME; 23811bb76ff1Sjsg break; 23821bb76ff1Sjsg case AMDGPU_UCODE_ID_CP_RS64_MEC: 23831bb76ff1Sjsg *type = GFX_FW_TYPE_RS64_MEC; 23841bb76ff1Sjsg break; 23851bb76ff1Sjsg case AMDGPU_UCODE_ID_CP_RS64_PFP_P0_STACK: 23861bb76ff1Sjsg *type = GFX_FW_TYPE_RS64_PFP_P0_STACK; 23871bb76ff1Sjsg break; 23881bb76ff1Sjsg case AMDGPU_UCODE_ID_CP_RS64_PFP_P1_STACK: 23891bb76ff1Sjsg *type = GFX_FW_TYPE_RS64_PFP_P1_STACK; 23901bb76ff1Sjsg break; 23911bb76ff1Sjsg case AMDGPU_UCODE_ID_CP_RS64_ME_P0_STACK: 23921bb76ff1Sjsg *type = GFX_FW_TYPE_RS64_ME_P0_STACK; 23931bb76ff1Sjsg break; 23941bb76ff1Sjsg case AMDGPU_UCODE_ID_CP_RS64_ME_P1_STACK: 23951bb76ff1Sjsg *type = GFX_FW_TYPE_RS64_ME_P1_STACK; 23961bb76ff1Sjsg break; 23971bb76ff1Sjsg case AMDGPU_UCODE_ID_CP_RS64_MEC_P0_STACK: 23981bb76ff1Sjsg *type = GFX_FW_TYPE_RS64_MEC_P0_STACK; 23991bb76ff1Sjsg break; 24001bb76ff1Sjsg case AMDGPU_UCODE_ID_CP_RS64_MEC_P1_STACK: 24011bb76ff1Sjsg *type = GFX_FW_TYPE_RS64_MEC_P1_STACK; 24021bb76ff1Sjsg break; 24031bb76ff1Sjsg case AMDGPU_UCODE_ID_CP_RS64_MEC_P2_STACK: 24041bb76ff1Sjsg *type = GFX_FW_TYPE_RS64_MEC_P2_STACK; 24051bb76ff1Sjsg break; 24061bb76ff1Sjsg case AMDGPU_UCODE_ID_CP_RS64_MEC_P3_STACK: 24071bb76ff1Sjsg *type = GFX_FW_TYPE_RS64_MEC_P3_STACK; 24081bb76ff1Sjsg break; 2409c349dbc7Sjsg case AMDGPU_UCODE_ID_MAXIMUM: 2410c349dbc7Sjsg default: 2411c349dbc7Sjsg return -EINVAL; 2412c349dbc7Sjsg } 2413c349dbc7Sjsg 2414c349dbc7Sjsg return 0; 2415c349dbc7Sjsg } 2416c349dbc7Sjsg 2417c349dbc7Sjsg static void psp_print_fw_hdr(struct psp_context *psp, 2418c349dbc7Sjsg struct amdgpu_firmware_info *ucode) 2419c349dbc7Sjsg { 2420c349dbc7Sjsg struct amdgpu_device *adev = psp->adev; 2421c349dbc7Sjsg struct common_firmware_header *hdr; 2422c349dbc7Sjsg 2423c349dbc7Sjsg switch (ucode->ucode_id) { 2424c349dbc7Sjsg case AMDGPU_UCODE_ID_SDMA0: 2425c349dbc7Sjsg case AMDGPU_UCODE_ID_SDMA1: 2426c349dbc7Sjsg case AMDGPU_UCODE_ID_SDMA2: 2427c349dbc7Sjsg case AMDGPU_UCODE_ID_SDMA3: 2428c349dbc7Sjsg case AMDGPU_UCODE_ID_SDMA4: 2429c349dbc7Sjsg case AMDGPU_UCODE_ID_SDMA5: 2430c349dbc7Sjsg case AMDGPU_UCODE_ID_SDMA6: 2431c349dbc7Sjsg case AMDGPU_UCODE_ID_SDMA7: 2432c349dbc7Sjsg hdr = (struct common_firmware_header *) 2433c349dbc7Sjsg adev->sdma.instance[ucode->ucode_id - AMDGPU_UCODE_ID_SDMA0].fw->data; 2434c349dbc7Sjsg amdgpu_ucode_print_sdma_hdr(hdr); 2435c349dbc7Sjsg break; 2436c349dbc7Sjsg case AMDGPU_UCODE_ID_CP_CE: 2437c349dbc7Sjsg hdr = (struct common_firmware_header *)adev->gfx.ce_fw->data; 2438c349dbc7Sjsg amdgpu_ucode_print_gfx_hdr(hdr); 2439c349dbc7Sjsg break; 2440c349dbc7Sjsg case AMDGPU_UCODE_ID_CP_PFP: 2441c349dbc7Sjsg hdr = (struct common_firmware_header *)adev->gfx.pfp_fw->data; 2442c349dbc7Sjsg amdgpu_ucode_print_gfx_hdr(hdr); 2443c349dbc7Sjsg break; 2444c349dbc7Sjsg case AMDGPU_UCODE_ID_CP_ME: 2445c349dbc7Sjsg hdr = (struct common_firmware_header *)adev->gfx.me_fw->data; 2446c349dbc7Sjsg amdgpu_ucode_print_gfx_hdr(hdr); 2447c349dbc7Sjsg break; 2448c349dbc7Sjsg case AMDGPU_UCODE_ID_CP_MEC1: 2449c349dbc7Sjsg hdr = (struct common_firmware_header *)adev->gfx.mec_fw->data; 2450c349dbc7Sjsg amdgpu_ucode_print_gfx_hdr(hdr); 2451c349dbc7Sjsg break; 2452c349dbc7Sjsg case AMDGPU_UCODE_ID_RLC_G: 2453c349dbc7Sjsg hdr = (struct common_firmware_header *)adev->gfx.rlc_fw->data; 2454c349dbc7Sjsg amdgpu_ucode_print_rlc_hdr(hdr); 2455c349dbc7Sjsg break; 2456c349dbc7Sjsg case AMDGPU_UCODE_ID_SMC: 2457c349dbc7Sjsg hdr = (struct common_firmware_header *)adev->pm.fw->data; 2458c349dbc7Sjsg amdgpu_ucode_print_smc_hdr(hdr); 2459c349dbc7Sjsg break; 2460c349dbc7Sjsg default: 2461c349dbc7Sjsg break; 2462c349dbc7Sjsg } 2463c349dbc7Sjsg } 2464c349dbc7Sjsg 2465c349dbc7Sjsg static int psp_prep_load_ip_fw_cmd_buf(struct amdgpu_firmware_info *ucode, 2466c349dbc7Sjsg struct psp_gfx_cmd_resp *cmd) 2467c349dbc7Sjsg { 2468c349dbc7Sjsg int ret; 2469c349dbc7Sjsg uint64_t fw_mem_mc_addr = ucode->mc_addr; 2470c349dbc7Sjsg 2471c349dbc7Sjsg cmd->cmd_id = GFX_CMD_ID_LOAD_IP_FW; 2472c349dbc7Sjsg cmd->cmd.cmd_load_ip_fw.fw_phy_addr_lo = lower_32_bits(fw_mem_mc_addr); 2473c349dbc7Sjsg cmd->cmd.cmd_load_ip_fw.fw_phy_addr_hi = upper_32_bits(fw_mem_mc_addr); 2474c349dbc7Sjsg cmd->cmd.cmd_load_ip_fw.fw_size = ucode->ucode_size; 2475c349dbc7Sjsg 2476c349dbc7Sjsg ret = psp_get_fw_type(ucode, &cmd->cmd.cmd_load_ip_fw.fw_type); 2477c349dbc7Sjsg if (ret) 2478c349dbc7Sjsg DRM_ERROR("Unknown firmware type\n"); 2479c349dbc7Sjsg 2480c349dbc7Sjsg return ret; 2481c349dbc7Sjsg } 2482c349dbc7Sjsg 2483f005ef32Sjsg int psp_execute_ip_fw_load(struct psp_context *psp, 2484c349dbc7Sjsg struct amdgpu_firmware_info *ucode) 2485c349dbc7Sjsg { 2486c349dbc7Sjsg int ret = 0; 24875ca02815Sjsg struct psp_gfx_cmd_resp *cmd = acquire_psp_cmd_buf(psp); 2488c349dbc7Sjsg 24895ca02815Sjsg ret = psp_prep_load_ip_fw_cmd_buf(ucode, cmd); 24905ca02815Sjsg if (!ret) { 24915ca02815Sjsg ret = psp_cmd_submit_buf(psp, ucode, cmd, 2492c349dbc7Sjsg psp->fence_buf_mc_addr); 24935ca02815Sjsg } 24945ca02815Sjsg 24955ca02815Sjsg release_psp_cmd_buf(psp); 2496c349dbc7Sjsg 2497c349dbc7Sjsg return ret; 2498c349dbc7Sjsg } 2499c349dbc7Sjsg 2500ad8b1aafSjsg static int psp_load_smu_fw(struct psp_context *psp) 2501fb4d8502Sjsg { 2502ad8b1aafSjsg int ret; 2503fb4d8502Sjsg struct amdgpu_device *adev = psp->adev; 2504ad8b1aafSjsg struct amdgpu_firmware_info *ucode = 2505ad8b1aafSjsg &adev->firmware.ucode[AMDGPU_UCODE_ID_SMC]; 25065ca02815Sjsg struct amdgpu_ras *ras = psp->ras_context.ras; 2507fb4d8502Sjsg 25081bb76ff1Sjsg /* 25091bb76ff1Sjsg * Skip SMU FW reloading in case of using BACO for runpm only, 25101bb76ff1Sjsg * as SMU is always alive. 25111bb76ff1Sjsg */ 25121bb76ff1Sjsg if (adev->in_runpm && (adev->pm.rpm_mode == AMDGPU_RUNPM_BACO)) 25131bb76ff1Sjsg return 0; 25141bb76ff1Sjsg 2515ad8b1aafSjsg if (!ucode->fw || amdgpu_sriov_vf(psp->adev)) 2516ad8b1aafSjsg return 0; 2517ad8b1aafSjsg 25185ca02815Sjsg if ((amdgpu_in_reset(adev) && 25195ca02815Sjsg ras && adev->ras_enabled && 25201bb76ff1Sjsg (adev->ip_versions[MP0_HWIP][0] == IP_VERSION(11, 0, 4) || 25211bb76ff1Sjsg adev->ip_versions[MP0_HWIP][0] == IP_VERSION(11, 0, 2)))) { 2522ad8b1aafSjsg ret = amdgpu_dpm_set_mp1_state(adev, PP_MP1_STATE_UNLOAD); 2523f005ef32Sjsg if (ret) 2524ad8b1aafSjsg DRM_WARN("Failed to set MP1 state prepare for reload\n"); 2525ad8b1aafSjsg } 2526c349dbc7Sjsg 2527f005ef32Sjsg ret = psp_execute_ip_fw_load(psp, ucode); 2528ad8b1aafSjsg 2529c349dbc7Sjsg if (ret) 2530ad8b1aafSjsg DRM_ERROR("PSP load smu failed!\n"); 2531ad8b1aafSjsg 2532c349dbc7Sjsg return ret; 2533c349dbc7Sjsg } 2534c349dbc7Sjsg 2535ad8b1aafSjsg static bool fw_load_skip_check(struct psp_context *psp, 2536ad8b1aafSjsg struct amdgpu_firmware_info *ucode) 2537ad8b1aafSjsg { 2538eb9d8ed0Sjsg if (!ucode->fw || !ucode->ucode_size) 2539ad8b1aafSjsg return true; 2540fb4d8502Sjsg 2541fb4d8502Sjsg if (ucode->ucode_id == AMDGPU_UCODE_ID_SMC && 2542c349dbc7Sjsg (psp_smu_reload_quirk(psp) || 2543c349dbc7Sjsg psp->autoload_supported || 2544c349dbc7Sjsg psp->pmfw_centralized_cstate_management)) 2545ad8b1aafSjsg return true; 2546c349dbc7Sjsg 2547ad8b1aafSjsg if (amdgpu_sriov_vf(psp->adev) && 25481bb76ff1Sjsg amdgpu_virt_fw_load_skip_check(psp->adev, ucode->ucode_id)) 2549ad8b1aafSjsg return true; 2550fb4d8502Sjsg 2551c349dbc7Sjsg if (psp->autoload_supported && 2552c349dbc7Sjsg (ucode->ucode_id == AMDGPU_UCODE_ID_CP_MEC1_JT || 2553c349dbc7Sjsg ucode->ucode_id == AMDGPU_UCODE_ID_CP_MEC2_JT)) 2554c349dbc7Sjsg /* skip mec JT when autoload is enabled */ 2555ad8b1aafSjsg return true; 2556ad8b1aafSjsg 2557ad8b1aafSjsg return false; 2558ad8b1aafSjsg } 2559ad8b1aafSjsg 25605ca02815Sjsg int psp_load_fw_list(struct psp_context *psp, 25615ca02815Sjsg struct amdgpu_firmware_info **ucode_list, int ucode_count) 25625ca02815Sjsg { 25635ca02815Sjsg int ret = 0, i; 25645ca02815Sjsg struct amdgpu_firmware_info *ucode; 25655ca02815Sjsg 25665ca02815Sjsg for (i = 0; i < ucode_count; ++i) { 25675ca02815Sjsg ucode = ucode_list[i]; 25685ca02815Sjsg psp_print_fw_hdr(psp, ucode); 2569f005ef32Sjsg ret = psp_execute_ip_fw_load(psp, ucode); 25705ca02815Sjsg if (ret) 25715ca02815Sjsg return ret; 25725ca02815Sjsg } 25735ca02815Sjsg return ret; 25745ca02815Sjsg } 25755ca02815Sjsg 25765ca02815Sjsg static int psp_load_non_psp_fw(struct psp_context *psp) 2577ad8b1aafSjsg { 2578ad8b1aafSjsg int i, ret; 2579ad8b1aafSjsg struct amdgpu_firmware_info *ucode; 2580ad8b1aafSjsg struct amdgpu_device *adev = psp->adev; 2581ad8b1aafSjsg 2582ad8b1aafSjsg if (psp->autoload_supported && 2583ad8b1aafSjsg !psp->pmfw_centralized_cstate_management) { 2584ad8b1aafSjsg ret = psp_load_smu_fw(psp); 2585ad8b1aafSjsg if (ret) 2586ad8b1aafSjsg return ret; 2587ad8b1aafSjsg } 2588ad8b1aafSjsg 2589ad8b1aafSjsg for (i = 0; i < adev->firmware.max_ucodes; i++) { 2590ad8b1aafSjsg ucode = &adev->firmware.ucode[i]; 2591ad8b1aafSjsg 2592ad8b1aafSjsg if (ucode->ucode_id == AMDGPU_UCODE_ID_SMC && 2593ad8b1aafSjsg !fw_load_skip_check(psp, ucode)) { 2594ad8b1aafSjsg ret = psp_load_smu_fw(psp); 2595ad8b1aafSjsg if (ret) 2596ad8b1aafSjsg return ret; 2597ad8b1aafSjsg continue; 2598ad8b1aafSjsg } 2599ad8b1aafSjsg 2600ad8b1aafSjsg if (fw_load_skip_check(psp, ucode)) 2601ad8b1aafSjsg continue; 2602ad8b1aafSjsg 2603ad8b1aafSjsg if (psp->autoload_supported && 26041bb76ff1Sjsg (adev->ip_versions[MP0_HWIP][0] == IP_VERSION(11, 0, 7) || 26051bb76ff1Sjsg adev->ip_versions[MP0_HWIP][0] == IP_VERSION(11, 0, 11) || 26061bb76ff1Sjsg adev->ip_versions[MP0_HWIP][0] == IP_VERSION(11, 0, 12)) && 2607ad8b1aafSjsg (ucode->ucode_id == AMDGPU_UCODE_ID_SDMA1 || 2608ad8b1aafSjsg ucode->ucode_id == AMDGPU_UCODE_ID_SDMA2 || 2609ad8b1aafSjsg ucode->ucode_id == AMDGPU_UCODE_ID_SDMA3)) 2610ad8b1aafSjsg /* PSP only receive one SDMA fw for sienna_cichlid, 2611f005ef32Sjsg * as all four sdma fw are same 2612f005ef32Sjsg */ 2613c349dbc7Sjsg continue; 2614c349dbc7Sjsg 2615c349dbc7Sjsg psp_print_fw_hdr(psp, ucode); 2616c349dbc7Sjsg 2617f005ef32Sjsg ret = psp_execute_ip_fw_load(psp, ucode); 2618fb4d8502Sjsg if (ret) 2619fb4d8502Sjsg return ret; 2620fb4d8502Sjsg 2621c349dbc7Sjsg /* Start rlc autoload after psp recieved all the gfx firmware */ 2622c349dbc7Sjsg if (psp->autoload_supported && ucode->ucode_id == (amdgpu_sriov_vf(adev) ? 26231bb76ff1Sjsg adev->virt.autoload_ucode_id : AMDGPU_UCODE_ID_RLC_G)) { 2624ad8b1aafSjsg ret = psp_rlc_autoload_start(psp); 2625c349dbc7Sjsg if (ret) { 2626c349dbc7Sjsg DRM_ERROR("Failed to start rlc autoload\n"); 2627fb4d8502Sjsg return ret; 2628c349dbc7Sjsg } 2629c349dbc7Sjsg } 2630fb4d8502Sjsg } 2631fb4d8502Sjsg 2632fb4d8502Sjsg return 0; 2633fb4d8502Sjsg } 2634fb4d8502Sjsg 2635fb4d8502Sjsg static int psp_load_fw(struct amdgpu_device *adev) 2636fb4d8502Sjsg { 2637fb4d8502Sjsg int ret; 2638fb4d8502Sjsg struct psp_context *psp = &adev->psp; 2639fb4d8502Sjsg 2640ad8b1aafSjsg if (amdgpu_sriov_vf(adev) && amdgpu_in_reset(adev)) { 26410ae6e948Sjsg /* should not destroy ring, only stop */ 26420ae6e948Sjsg psp_ring_stop(psp, PSP_RING_TYPE__KM); 26435ca02815Sjsg } else { 2644fb4d8502Sjsg memset(psp->fence_buf, 0, PSP_FENCE_BUFFER_SIZE); 2645fb4d8502Sjsg 2646fb4d8502Sjsg ret = psp_ring_init(psp, PSP_RING_TYPE__KM); 2647c349dbc7Sjsg if (ret) { 2648c349dbc7Sjsg DRM_ERROR("PSP ring init failed!\n"); 2649c349dbc7Sjsg goto failed; 2650c349dbc7Sjsg } 26510ae6e948Sjsg } 2652fb4d8502Sjsg 2653fb4d8502Sjsg ret = psp_hw_start(psp); 2654fb4d8502Sjsg if (ret) 2655c349dbc7Sjsg goto failed; 2656fb4d8502Sjsg 26575ca02815Sjsg ret = psp_load_non_psp_fw(psp); 2658fb4d8502Sjsg if (ret) 26591bb76ff1Sjsg goto failed1; 2660c349dbc7Sjsg 26611bb76ff1Sjsg ret = psp_asd_initialize(psp); 2662c349dbc7Sjsg if (ret) { 2663c349dbc7Sjsg DRM_ERROR("PSP load asd failed!\n"); 26641bb76ff1Sjsg goto failed1; 2665c349dbc7Sjsg } 2666c349dbc7Sjsg 26675ca02815Sjsg ret = psp_rl_load(adev); 26685ca02815Sjsg if (ret) { 26695ca02815Sjsg DRM_ERROR("PSP load RL failed!\n"); 26701bb76ff1Sjsg goto failed1; 26711bb76ff1Sjsg } 26721bb76ff1Sjsg 26731bb76ff1Sjsg if (amdgpu_sriov_vf(adev) && amdgpu_in_reset(adev)) { 26741bb76ff1Sjsg if (adev->gmc.xgmi.num_physical_nodes > 1) { 26751bb76ff1Sjsg ret = psp_xgmi_initialize(psp, false, true); 26761bb76ff1Sjsg /* Warning the XGMI seesion initialize failure 26771bb76ff1Sjsg * Instead of stop driver initialization 26781bb76ff1Sjsg */ 26791bb76ff1Sjsg if (ret) 26801bb76ff1Sjsg dev_err(psp->adev->dev, 26811bb76ff1Sjsg "XGMI: Failed to initialize XGMI session\n"); 26821bb76ff1Sjsg } 26835ca02815Sjsg } 26845ca02815Sjsg 26855ca02815Sjsg if (psp->ta_fw) { 2686c349dbc7Sjsg ret = psp_ras_initialize(psp); 2687c349dbc7Sjsg if (ret) 2688c349dbc7Sjsg dev_err(psp->adev->dev, 2689c349dbc7Sjsg "RAS: Failed to initialize RAS\n"); 2690c349dbc7Sjsg 2691c349dbc7Sjsg ret = psp_hdcp_initialize(psp); 2692c349dbc7Sjsg if (ret) 2693c349dbc7Sjsg dev_err(psp->adev->dev, 2694c349dbc7Sjsg "HDCP: Failed to initialize HDCP\n"); 2695c349dbc7Sjsg 2696c349dbc7Sjsg ret = psp_dtm_initialize(psp); 2697c349dbc7Sjsg if (ret) 2698c349dbc7Sjsg dev_err(psp->adev->dev, 2699c349dbc7Sjsg "DTM: Failed to initialize DTM\n"); 2700ad8b1aafSjsg 2701ad8b1aafSjsg ret = psp_rap_initialize(psp); 2702ad8b1aafSjsg if (ret) 2703ad8b1aafSjsg dev_err(psp->adev->dev, 2704ad8b1aafSjsg "RAP: Failed to initialize RAP\n"); 27055ca02815Sjsg 27065ca02815Sjsg ret = psp_securedisplay_initialize(psp); 27075ca02815Sjsg if (ret) 27085ca02815Sjsg dev_err(psp->adev->dev, 27095ca02815Sjsg "SECUREDISPLAY: Failed to initialize SECUREDISPLAY\n"); 2710c349dbc7Sjsg } 2711fb4d8502Sjsg 2712fb4d8502Sjsg return 0; 2713fb4d8502Sjsg 27141bb76ff1Sjsg failed1: 27151bb76ff1Sjsg psp_free_shared_bufs(psp); 2716fb4d8502Sjsg failed: 2717c349dbc7Sjsg /* 2718c349dbc7Sjsg * all cleanup jobs (xgmi terminate, ras terminate, 2719c349dbc7Sjsg * ring destroy, cmd/fence/fw buffers destory, 2720c349dbc7Sjsg * psp->cmd destory) are delayed to psp_hw_fini 2721c349dbc7Sjsg */ 27221bb76ff1Sjsg psp_ring_destroy(psp, PSP_RING_TYPE__KM); 2723fb4d8502Sjsg return ret; 2724fb4d8502Sjsg } 2725fb4d8502Sjsg 2726fb4d8502Sjsg static int psp_hw_init(void *handle) 2727fb4d8502Sjsg { 2728fb4d8502Sjsg int ret; 2729fb4d8502Sjsg struct amdgpu_device *adev = (struct amdgpu_device *)handle; 2730fb4d8502Sjsg 2731fb4d8502Sjsg mutex_lock(&adev->firmware.mutex); 2732fb4d8502Sjsg /* 2733fb4d8502Sjsg * This sequence is just used on hw_init only once, no need on 2734fb4d8502Sjsg * resume. 2735fb4d8502Sjsg */ 2736fb4d8502Sjsg ret = amdgpu_ucode_init_bo(adev); 2737fb4d8502Sjsg if (ret) 2738fb4d8502Sjsg goto failed; 2739fb4d8502Sjsg 2740fb4d8502Sjsg ret = psp_load_fw(adev); 2741fb4d8502Sjsg if (ret) { 2742fb4d8502Sjsg DRM_ERROR("PSP firmware loading failed\n"); 2743fb4d8502Sjsg goto failed; 2744fb4d8502Sjsg } 2745fb4d8502Sjsg 2746fb4d8502Sjsg mutex_unlock(&adev->firmware.mutex); 2747fb4d8502Sjsg return 0; 2748fb4d8502Sjsg 2749fb4d8502Sjsg failed: 2750fb4d8502Sjsg adev->firmware.load_type = AMDGPU_FW_LOAD_DIRECT; 2751fb4d8502Sjsg mutex_unlock(&adev->firmware.mutex); 2752fb4d8502Sjsg return -EINVAL; 2753fb4d8502Sjsg } 2754fb4d8502Sjsg 2755fb4d8502Sjsg static int psp_hw_fini(void *handle) 2756fb4d8502Sjsg { 2757fb4d8502Sjsg struct amdgpu_device *adev = (struct amdgpu_device *)handle; 2758fb4d8502Sjsg struct psp_context *psp = &adev->psp; 2759fb4d8502Sjsg 27605ca02815Sjsg if (psp->ta_fw) { 2761c349dbc7Sjsg psp_ras_terminate(psp); 27625ca02815Sjsg psp_securedisplay_terminate(psp); 2763ad8b1aafSjsg psp_rap_terminate(psp); 2764c349dbc7Sjsg psp_dtm_terminate(psp); 2765c349dbc7Sjsg psp_hdcp_terminate(psp); 2766f8d078a0Sjsg 2767f8d078a0Sjsg if (adev->gmc.xgmi.num_physical_nodes > 1) 2768f8d078a0Sjsg psp_xgmi_terminate(psp); 2769c349dbc7Sjsg } 2770fb4d8502Sjsg 27711bb76ff1Sjsg psp_asd_terminate(psp); 27726bd9a77dSjsg psp_tmr_terminate(psp); 27731bb76ff1Sjsg 2774fb4d8502Sjsg psp_ring_destroy(psp, PSP_RING_TYPE__KM); 2775fb4d8502Sjsg 2776fb4d8502Sjsg return 0; 2777fb4d8502Sjsg } 2778fb4d8502Sjsg 2779fb4d8502Sjsg static int psp_suspend(void *handle) 2780fb4d8502Sjsg { 27811bb76ff1Sjsg int ret = 0; 2782fb4d8502Sjsg struct amdgpu_device *adev = (struct amdgpu_device *)handle; 2783fb4d8502Sjsg struct psp_context *psp = &adev->psp; 2784fb4d8502Sjsg 2785c349dbc7Sjsg if (adev->gmc.xgmi.num_physical_nodes > 1 && 27865ca02815Sjsg psp->xgmi_context.context.initialized) { 2787c349dbc7Sjsg ret = psp_xgmi_terminate(psp); 2788c349dbc7Sjsg if (ret) { 2789c349dbc7Sjsg DRM_ERROR("Failed to terminate xgmi ta\n"); 27901bb76ff1Sjsg goto out; 2791c349dbc7Sjsg } 2792c349dbc7Sjsg } 2793c349dbc7Sjsg 27945ca02815Sjsg if (psp->ta_fw) { 2795c349dbc7Sjsg ret = psp_ras_terminate(psp); 2796c349dbc7Sjsg if (ret) { 2797c349dbc7Sjsg DRM_ERROR("Failed to terminate ras ta\n"); 27981bb76ff1Sjsg goto out; 2799c349dbc7Sjsg } 2800c349dbc7Sjsg ret = psp_hdcp_terminate(psp); 2801c349dbc7Sjsg if (ret) { 2802c349dbc7Sjsg DRM_ERROR("Failed to terminate hdcp ta\n"); 28031bb76ff1Sjsg goto out; 2804c349dbc7Sjsg } 2805c349dbc7Sjsg ret = psp_dtm_terminate(psp); 2806c349dbc7Sjsg if (ret) { 2807c349dbc7Sjsg DRM_ERROR("Failed to terminate dtm ta\n"); 28081bb76ff1Sjsg goto out; 2809c349dbc7Sjsg } 2810ad8b1aafSjsg ret = psp_rap_terminate(psp); 2811ad8b1aafSjsg if (ret) { 2812ad8b1aafSjsg DRM_ERROR("Failed to terminate rap ta\n"); 28131bb76ff1Sjsg goto out; 2814ad8b1aafSjsg } 28155ca02815Sjsg ret = psp_securedisplay_terminate(psp); 28165ca02815Sjsg if (ret) { 28175ca02815Sjsg DRM_ERROR("Failed to terminate securedisplay ta\n"); 28181bb76ff1Sjsg goto out; 28195ca02815Sjsg } 2820c349dbc7Sjsg } 2821fb4d8502Sjsg 28221bb76ff1Sjsg ret = psp_asd_terminate(psp); 282328304a26Sjsg if (ret) { 28241bb76ff1Sjsg DRM_ERROR("Failed to terminate asd\n"); 28251bb76ff1Sjsg goto out; 282628304a26Sjsg } 282728304a26Sjsg 28284aa0689aSjsg ret = psp_tmr_terminate(psp); 28294aa0689aSjsg if (ret) { 2830ad8b1aafSjsg DRM_ERROR("Failed to terminate tmr\n"); 28311bb76ff1Sjsg goto out; 28324aa0689aSjsg } 28334aa0689aSjsg 2834fb4d8502Sjsg ret = psp_ring_stop(psp, PSP_RING_TYPE__KM); 2835f005ef32Sjsg if (ret) 2836fb4d8502Sjsg DRM_ERROR("PSP ring stop failed\n"); 2837fb4d8502Sjsg 28381bb76ff1Sjsg out: 28391bb76ff1Sjsg return ret; 2840fb4d8502Sjsg } 2841fb4d8502Sjsg 2842fb4d8502Sjsg static int psp_resume(void *handle) 2843fb4d8502Sjsg { 2844fb4d8502Sjsg int ret; 2845fb4d8502Sjsg struct amdgpu_device *adev = (struct amdgpu_device *)handle; 2846fb4d8502Sjsg struct psp_context *psp = &adev->psp; 2847fb4d8502Sjsg 2848fb4d8502Sjsg DRM_INFO("PSP is resuming...\n"); 2849fb4d8502Sjsg 28505ca02815Sjsg if (psp->mem_train_ctx.enable_mem_training) { 2851c349dbc7Sjsg ret = psp_mem_training(psp, PSP_MEM_TRAIN_RESUME); 2852c349dbc7Sjsg if (ret) { 2853c349dbc7Sjsg DRM_ERROR("Failed to process memory training!\n"); 2854c349dbc7Sjsg return ret; 2855c349dbc7Sjsg } 28565ca02815Sjsg } 2857c349dbc7Sjsg 2858fb4d8502Sjsg mutex_lock(&adev->firmware.mutex); 2859fb4d8502Sjsg 2860fb4d8502Sjsg ret = psp_hw_start(psp); 2861fb4d8502Sjsg if (ret) 2862fb4d8502Sjsg goto failed; 2863fb4d8502Sjsg 28645ca02815Sjsg ret = psp_load_non_psp_fw(psp); 2865fb4d8502Sjsg if (ret) 2866fb4d8502Sjsg goto failed; 2867fb4d8502Sjsg 28681bb76ff1Sjsg ret = psp_asd_initialize(psp); 2869c349dbc7Sjsg if (ret) { 2870c349dbc7Sjsg DRM_ERROR("PSP load asd failed!\n"); 2871c349dbc7Sjsg goto failed; 2872c349dbc7Sjsg } 2873c349dbc7Sjsg 28741bb76ff1Sjsg ret = psp_rl_load(adev); 28751bb76ff1Sjsg if (ret) { 28761bb76ff1Sjsg dev_err(adev->dev, "PSP load RL failed!\n"); 28771bb76ff1Sjsg goto failed; 28781bb76ff1Sjsg } 28791bb76ff1Sjsg 2880c349dbc7Sjsg if (adev->gmc.xgmi.num_physical_nodes > 1) { 28815ca02815Sjsg ret = psp_xgmi_initialize(psp, false, true); 2882c349dbc7Sjsg /* Warning the XGMI seesion initialize failure 2883c349dbc7Sjsg * Instead of stop driver initialization 2884c349dbc7Sjsg */ 2885c349dbc7Sjsg if (ret) 2886c349dbc7Sjsg dev_err(psp->adev->dev, 2887c349dbc7Sjsg "XGMI: Failed to initialize XGMI session\n"); 2888c349dbc7Sjsg } 2889c349dbc7Sjsg 28905ca02815Sjsg if (psp->ta_fw) { 2891c349dbc7Sjsg ret = psp_ras_initialize(psp); 2892c349dbc7Sjsg if (ret) 2893c349dbc7Sjsg dev_err(psp->adev->dev, 2894c349dbc7Sjsg "RAS: Failed to initialize RAS\n"); 2895c349dbc7Sjsg 2896c349dbc7Sjsg ret = psp_hdcp_initialize(psp); 2897c349dbc7Sjsg if (ret) 2898c349dbc7Sjsg dev_err(psp->adev->dev, 2899c349dbc7Sjsg "HDCP: Failed to initialize HDCP\n"); 2900c349dbc7Sjsg 2901c349dbc7Sjsg ret = psp_dtm_initialize(psp); 2902c349dbc7Sjsg if (ret) 2903c349dbc7Sjsg dev_err(psp->adev->dev, 2904c349dbc7Sjsg "DTM: Failed to initialize DTM\n"); 2905ad8b1aafSjsg 2906ad8b1aafSjsg ret = psp_rap_initialize(psp); 2907ad8b1aafSjsg if (ret) 2908ad8b1aafSjsg dev_err(psp->adev->dev, 2909ad8b1aafSjsg "RAP: Failed to initialize RAP\n"); 29105ca02815Sjsg 29115ca02815Sjsg ret = psp_securedisplay_initialize(psp); 29125ca02815Sjsg if (ret) 29135ca02815Sjsg dev_err(psp->adev->dev, 29145ca02815Sjsg "SECUREDISPLAY: Failed to initialize SECUREDISPLAY\n"); 2915c349dbc7Sjsg } 2916c349dbc7Sjsg 2917fb4d8502Sjsg mutex_unlock(&adev->firmware.mutex); 2918fb4d8502Sjsg 2919fb4d8502Sjsg return 0; 2920fb4d8502Sjsg 2921fb4d8502Sjsg failed: 2922fb4d8502Sjsg DRM_ERROR("PSP resume failed\n"); 2923fb4d8502Sjsg mutex_unlock(&adev->firmware.mutex); 2924fb4d8502Sjsg return ret; 2925fb4d8502Sjsg } 2926fb4d8502Sjsg 2927fb4d8502Sjsg int psp_gpu_reset(struct amdgpu_device *adev) 2928fb4d8502Sjsg { 2929c349dbc7Sjsg int ret; 2930c349dbc7Sjsg 2931fb4d8502Sjsg if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) 2932fb4d8502Sjsg return 0; 2933fb4d8502Sjsg 2934c349dbc7Sjsg mutex_lock(&adev->psp.mutex); 2935c349dbc7Sjsg ret = psp_mode1_reset(&adev->psp); 2936c349dbc7Sjsg mutex_unlock(&adev->psp.mutex); 2937c349dbc7Sjsg 2938c349dbc7Sjsg return ret; 2939c349dbc7Sjsg } 2940c349dbc7Sjsg 2941c349dbc7Sjsg int psp_rlc_autoload_start(struct psp_context *psp) 2942c349dbc7Sjsg { 2943c349dbc7Sjsg int ret; 29445ca02815Sjsg struct psp_gfx_cmd_resp *cmd = acquire_psp_cmd_buf(psp); 2945c349dbc7Sjsg 2946c349dbc7Sjsg cmd->cmd_id = GFX_CMD_ID_AUTOLOAD_RLC; 2947c349dbc7Sjsg 2948c349dbc7Sjsg ret = psp_cmd_submit_buf(psp, NULL, cmd, 2949c349dbc7Sjsg psp->fence_buf_mc_addr); 29505ca02815Sjsg 29515ca02815Sjsg release_psp_cmd_buf(psp); 29525ca02815Sjsg 2953c349dbc7Sjsg return ret; 2954c349dbc7Sjsg } 2955c349dbc7Sjsg 2956c349dbc7Sjsg int psp_ring_cmd_submit(struct psp_context *psp, 2957c349dbc7Sjsg uint64_t cmd_buf_mc_addr, 2958c349dbc7Sjsg uint64_t fence_mc_addr, 2959c349dbc7Sjsg int index) 2960c349dbc7Sjsg { 2961c349dbc7Sjsg unsigned int psp_write_ptr_reg = 0; 2962c349dbc7Sjsg struct psp_gfx_rb_frame *write_frame; 2963c349dbc7Sjsg struct psp_ring *ring = &psp->km_ring; 2964c349dbc7Sjsg struct psp_gfx_rb_frame *ring_buffer_start = ring->ring_mem; 2965c349dbc7Sjsg struct psp_gfx_rb_frame *ring_buffer_end = ring_buffer_start + 2966c349dbc7Sjsg ring->ring_size / sizeof(struct psp_gfx_rb_frame) - 1; 2967c349dbc7Sjsg struct amdgpu_device *adev = psp->adev; 2968c349dbc7Sjsg uint32_t ring_size_dw = ring->ring_size / 4; 2969c349dbc7Sjsg uint32_t rb_frame_size_dw = sizeof(struct psp_gfx_rb_frame) / 4; 2970c349dbc7Sjsg 2971c349dbc7Sjsg /* KM (GPCOM) prepare write pointer */ 2972c349dbc7Sjsg psp_write_ptr_reg = psp_ring_get_wptr(psp); 2973c349dbc7Sjsg 2974c349dbc7Sjsg /* Update KM RB frame pointer to new frame */ 2975c349dbc7Sjsg /* write_frame ptr increments by size of rb_frame in bytes */ 2976c349dbc7Sjsg /* psp_write_ptr_reg increments by size of rb_frame in DWORDs */ 2977c349dbc7Sjsg if ((psp_write_ptr_reg % ring_size_dw) == 0) 2978c349dbc7Sjsg write_frame = ring_buffer_start; 2979c349dbc7Sjsg else 2980c349dbc7Sjsg write_frame = ring_buffer_start + (psp_write_ptr_reg / rb_frame_size_dw); 2981c349dbc7Sjsg /* Check invalid write_frame ptr address */ 2982c349dbc7Sjsg if ((write_frame < ring_buffer_start) || (ring_buffer_end < write_frame)) { 2983c349dbc7Sjsg DRM_ERROR("ring_buffer_start = %p; ring_buffer_end = %p; write_frame = %p\n", 2984c349dbc7Sjsg ring_buffer_start, ring_buffer_end, write_frame); 2985c349dbc7Sjsg DRM_ERROR("write_frame is pointing to address out of bounds\n"); 2986c349dbc7Sjsg return -EINVAL; 2987c349dbc7Sjsg } 2988c349dbc7Sjsg 2989c349dbc7Sjsg /* Initialize KM RB frame */ 2990c349dbc7Sjsg memset(write_frame, 0, sizeof(struct psp_gfx_rb_frame)); 2991c349dbc7Sjsg 2992c349dbc7Sjsg /* Update KM RB frame */ 2993c349dbc7Sjsg write_frame->cmd_buf_addr_hi = upper_32_bits(cmd_buf_mc_addr); 2994c349dbc7Sjsg write_frame->cmd_buf_addr_lo = lower_32_bits(cmd_buf_mc_addr); 2995c349dbc7Sjsg write_frame->fence_addr_hi = upper_32_bits(fence_mc_addr); 2996c349dbc7Sjsg write_frame->fence_addr_lo = lower_32_bits(fence_mc_addr); 2997c349dbc7Sjsg write_frame->fence_value = index; 29985ca02815Sjsg amdgpu_device_flush_hdp(adev, NULL); 2999c349dbc7Sjsg 3000c349dbc7Sjsg /* Update the write Pointer in DWORDs */ 3001c349dbc7Sjsg psp_write_ptr_reg = (psp_write_ptr_reg + rb_frame_size_dw) % ring_size_dw; 3002c349dbc7Sjsg psp_ring_set_wptr(psp, psp_write_ptr_reg); 3003c349dbc7Sjsg return 0; 3004fb4d8502Sjsg } 3005fb4d8502Sjsg 3006f005ef32Sjsg int psp_init_asd_microcode(struct psp_context *psp, const char *chip_name) 3007fb4d8502Sjsg { 3008ad8b1aafSjsg struct amdgpu_device *adev = psp->adev; 30095ca02815Sjsg char fw_name[PSP_FW_NAME_LEN]; 3010ad8b1aafSjsg const struct psp_firmware_header_v1_0 *asd_hdr; 3011ad8b1aafSjsg int err = 0; 3012fb4d8502Sjsg 3013ad8b1aafSjsg snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_asd.bin", chip_name); 3014f005ef32Sjsg err = amdgpu_ucode_request(adev, &adev->psp.asd_fw, fw_name); 3015ad8b1aafSjsg if (err) 3016ad8b1aafSjsg goto out; 3017ad8b1aafSjsg 3018ad8b1aafSjsg asd_hdr = (const struct psp_firmware_header_v1_0 *)adev->psp.asd_fw->data; 30191bb76ff1Sjsg adev->psp.asd_context.bin_desc.fw_version = le32_to_cpu(asd_hdr->header.ucode_version); 30201bb76ff1Sjsg adev->psp.asd_context.bin_desc.feature_version = le32_to_cpu(asd_hdr->sos.fw_version); 30211bb76ff1Sjsg adev->psp.asd_context.bin_desc.size_bytes = le32_to_cpu(asd_hdr->header.ucode_size_bytes); 30221bb76ff1Sjsg adev->psp.asd_context.bin_desc.start_addr = (uint8_t *)asd_hdr + 3023ad8b1aafSjsg le32_to_cpu(asd_hdr->header.ucode_array_offset_bytes); 3024ad8b1aafSjsg return 0; 3025ad8b1aafSjsg out: 3026f005ef32Sjsg amdgpu_ucode_release(&adev->psp.asd_fw); 3027ad8b1aafSjsg return err; 3028ad8b1aafSjsg } 3029ad8b1aafSjsg 3030f005ef32Sjsg int psp_init_toc_microcode(struct psp_context *psp, const char *chip_name) 30315ca02815Sjsg { 30325ca02815Sjsg struct amdgpu_device *adev = psp->adev; 30335ca02815Sjsg char fw_name[PSP_FW_NAME_LEN]; 30345ca02815Sjsg const struct psp_firmware_header_v1_0 *toc_hdr; 30355ca02815Sjsg int err = 0; 30365ca02815Sjsg 30375ca02815Sjsg snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_toc.bin", chip_name); 3038f005ef32Sjsg err = amdgpu_ucode_request(adev, &adev->psp.toc_fw, fw_name); 30395ca02815Sjsg if (err) 30405ca02815Sjsg goto out; 30415ca02815Sjsg 30425ca02815Sjsg toc_hdr = (const struct psp_firmware_header_v1_0 *)adev->psp.toc_fw->data; 30435ca02815Sjsg adev->psp.toc.fw_version = le32_to_cpu(toc_hdr->header.ucode_version); 30445ca02815Sjsg adev->psp.toc.feature_version = le32_to_cpu(toc_hdr->sos.fw_version); 30455ca02815Sjsg adev->psp.toc.size_bytes = le32_to_cpu(toc_hdr->header.ucode_size_bytes); 30465ca02815Sjsg adev->psp.toc.start_addr = (uint8_t *)toc_hdr + 30475ca02815Sjsg le32_to_cpu(toc_hdr->header.ucode_array_offset_bytes); 30485ca02815Sjsg return 0; 30495ca02815Sjsg out: 3050f005ef32Sjsg amdgpu_ucode_release(&adev->psp.toc_fw); 30515ca02815Sjsg return err; 30525ca02815Sjsg } 30535ca02815Sjsg 30545ca02815Sjsg static int parse_sos_bin_descriptor(struct psp_context *psp, 30555ca02815Sjsg const struct psp_fw_bin_desc *desc, 30565ca02815Sjsg const struct psp_firmware_header_v2_0 *sos_hdr) 30575ca02815Sjsg { 30585ca02815Sjsg uint8_t *ucode_start_addr = NULL; 30595ca02815Sjsg 30605ca02815Sjsg if (!psp || !desc || !sos_hdr) 30615ca02815Sjsg return -EINVAL; 30625ca02815Sjsg 30635ca02815Sjsg ucode_start_addr = (uint8_t *)sos_hdr + 30645ca02815Sjsg le32_to_cpu(desc->offset_bytes) + 30655ca02815Sjsg le32_to_cpu(sos_hdr->header.ucode_array_offset_bytes); 30665ca02815Sjsg 30675ca02815Sjsg switch (desc->fw_type) { 30685ca02815Sjsg case PSP_FW_TYPE_PSP_SOS: 30695ca02815Sjsg psp->sos.fw_version = le32_to_cpu(desc->fw_version); 30705ca02815Sjsg psp->sos.feature_version = le32_to_cpu(desc->fw_version); 30715ca02815Sjsg psp->sos.size_bytes = le32_to_cpu(desc->size_bytes); 30725ca02815Sjsg psp->sos.start_addr = ucode_start_addr; 30735ca02815Sjsg break; 30745ca02815Sjsg case PSP_FW_TYPE_PSP_SYS_DRV: 30755ca02815Sjsg psp->sys.fw_version = le32_to_cpu(desc->fw_version); 30765ca02815Sjsg psp->sys.feature_version = le32_to_cpu(desc->fw_version); 30775ca02815Sjsg psp->sys.size_bytes = le32_to_cpu(desc->size_bytes); 30785ca02815Sjsg psp->sys.start_addr = ucode_start_addr; 30795ca02815Sjsg break; 30805ca02815Sjsg case PSP_FW_TYPE_PSP_KDB: 30815ca02815Sjsg psp->kdb.fw_version = le32_to_cpu(desc->fw_version); 30825ca02815Sjsg psp->kdb.feature_version = le32_to_cpu(desc->fw_version); 30835ca02815Sjsg psp->kdb.size_bytes = le32_to_cpu(desc->size_bytes); 30845ca02815Sjsg psp->kdb.start_addr = ucode_start_addr; 30855ca02815Sjsg break; 30865ca02815Sjsg case PSP_FW_TYPE_PSP_TOC: 30875ca02815Sjsg psp->toc.fw_version = le32_to_cpu(desc->fw_version); 30885ca02815Sjsg psp->toc.feature_version = le32_to_cpu(desc->fw_version); 30895ca02815Sjsg psp->toc.size_bytes = le32_to_cpu(desc->size_bytes); 30905ca02815Sjsg psp->toc.start_addr = ucode_start_addr; 30915ca02815Sjsg break; 30925ca02815Sjsg case PSP_FW_TYPE_PSP_SPL: 30935ca02815Sjsg psp->spl.fw_version = le32_to_cpu(desc->fw_version); 30945ca02815Sjsg psp->spl.feature_version = le32_to_cpu(desc->fw_version); 30955ca02815Sjsg psp->spl.size_bytes = le32_to_cpu(desc->size_bytes); 30965ca02815Sjsg psp->spl.start_addr = ucode_start_addr; 30975ca02815Sjsg break; 30985ca02815Sjsg case PSP_FW_TYPE_PSP_RL: 30995ca02815Sjsg psp->rl.fw_version = le32_to_cpu(desc->fw_version); 31005ca02815Sjsg psp->rl.feature_version = le32_to_cpu(desc->fw_version); 31015ca02815Sjsg psp->rl.size_bytes = le32_to_cpu(desc->size_bytes); 31025ca02815Sjsg psp->rl.start_addr = ucode_start_addr; 31035ca02815Sjsg break; 31045ca02815Sjsg case PSP_FW_TYPE_PSP_SOC_DRV: 31055ca02815Sjsg psp->soc_drv.fw_version = le32_to_cpu(desc->fw_version); 31065ca02815Sjsg psp->soc_drv.feature_version = le32_to_cpu(desc->fw_version); 31075ca02815Sjsg psp->soc_drv.size_bytes = le32_to_cpu(desc->size_bytes); 31085ca02815Sjsg psp->soc_drv.start_addr = ucode_start_addr; 31095ca02815Sjsg break; 31105ca02815Sjsg case PSP_FW_TYPE_PSP_INTF_DRV: 31115ca02815Sjsg psp->intf_drv.fw_version = le32_to_cpu(desc->fw_version); 31125ca02815Sjsg psp->intf_drv.feature_version = le32_to_cpu(desc->fw_version); 31135ca02815Sjsg psp->intf_drv.size_bytes = le32_to_cpu(desc->size_bytes); 31145ca02815Sjsg psp->intf_drv.start_addr = ucode_start_addr; 31155ca02815Sjsg break; 31165ca02815Sjsg case PSP_FW_TYPE_PSP_DBG_DRV: 31175ca02815Sjsg psp->dbg_drv.fw_version = le32_to_cpu(desc->fw_version); 31185ca02815Sjsg psp->dbg_drv.feature_version = le32_to_cpu(desc->fw_version); 31195ca02815Sjsg psp->dbg_drv.size_bytes = le32_to_cpu(desc->size_bytes); 31205ca02815Sjsg psp->dbg_drv.start_addr = ucode_start_addr; 31215ca02815Sjsg break; 31221bb76ff1Sjsg case PSP_FW_TYPE_PSP_RAS_DRV: 31231bb76ff1Sjsg psp->ras_drv.fw_version = le32_to_cpu(desc->fw_version); 31241bb76ff1Sjsg psp->ras_drv.feature_version = le32_to_cpu(desc->fw_version); 31251bb76ff1Sjsg psp->ras_drv.size_bytes = le32_to_cpu(desc->size_bytes); 31261bb76ff1Sjsg psp->ras_drv.start_addr = ucode_start_addr; 31271bb76ff1Sjsg break; 31285ca02815Sjsg default: 31295ca02815Sjsg dev_warn(psp->adev->dev, "Unsupported PSP FW type: %d\n", desc->fw_type); 31305ca02815Sjsg break; 31315ca02815Sjsg } 31325ca02815Sjsg 31335ca02815Sjsg return 0; 31345ca02815Sjsg } 31355ca02815Sjsg 31365ca02815Sjsg static int psp_init_sos_base_fw(struct amdgpu_device *adev) 31375ca02815Sjsg { 31385ca02815Sjsg const struct psp_firmware_header_v1_0 *sos_hdr; 31395ca02815Sjsg const struct psp_firmware_header_v1_3 *sos_hdr_v1_3; 31405ca02815Sjsg uint8_t *ucode_array_start_addr; 31415ca02815Sjsg 31425ca02815Sjsg sos_hdr = (const struct psp_firmware_header_v1_0 *)adev->psp.sos_fw->data; 31435ca02815Sjsg ucode_array_start_addr = (uint8_t *)sos_hdr + 31445ca02815Sjsg le32_to_cpu(sos_hdr->header.ucode_array_offset_bytes); 31455ca02815Sjsg 31461bb76ff1Sjsg if (adev->gmc.xgmi.connected_to_cpu || 31471bb76ff1Sjsg (adev->ip_versions[MP0_HWIP][0] != IP_VERSION(13, 0, 2))) { 31485ca02815Sjsg adev->psp.sos.fw_version = le32_to_cpu(sos_hdr->header.ucode_version); 31495ca02815Sjsg adev->psp.sos.feature_version = le32_to_cpu(sos_hdr->sos.fw_version); 31505ca02815Sjsg 31515ca02815Sjsg adev->psp.sys.size_bytes = le32_to_cpu(sos_hdr->sos.offset_bytes); 31525ca02815Sjsg adev->psp.sys.start_addr = ucode_array_start_addr; 31535ca02815Sjsg 31545ca02815Sjsg adev->psp.sos.size_bytes = le32_to_cpu(sos_hdr->sos.size_bytes); 31555ca02815Sjsg adev->psp.sos.start_addr = ucode_array_start_addr + 31565ca02815Sjsg le32_to_cpu(sos_hdr->sos.offset_bytes); 31575ca02815Sjsg } else { 31585ca02815Sjsg /* Load alternate PSP SOS FW */ 31595ca02815Sjsg sos_hdr_v1_3 = (const struct psp_firmware_header_v1_3 *)adev->psp.sos_fw->data; 31605ca02815Sjsg 31615ca02815Sjsg adev->psp.sos.fw_version = le32_to_cpu(sos_hdr_v1_3->sos_aux.fw_version); 31625ca02815Sjsg adev->psp.sos.feature_version = le32_to_cpu(sos_hdr_v1_3->sos_aux.fw_version); 31635ca02815Sjsg 31645ca02815Sjsg adev->psp.sys.size_bytes = le32_to_cpu(sos_hdr_v1_3->sys_drv_aux.size_bytes); 31655ca02815Sjsg adev->psp.sys.start_addr = ucode_array_start_addr + 31665ca02815Sjsg le32_to_cpu(sos_hdr_v1_3->sys_drv_aux.offset_bytes); 31675ca02815Sjsg 31685ca02815Sjsg adev->psp.sos.size_bytes = le32_to_cpu(sos_hdr_v1_3->sos_aux.size_bytes); 31695ca02815Sjsg adev->psp.sos.start_addr = ucode_array_start_addr + 31705ca02815Sjsg le32_to_cpu(sos_hdr_v1_3->sos_aux.offset_bytes); 31715ca02815Sjsg } 31725ca02815Sjsg 31735ca02815Sjsg if ((adev->psp.sys.size_bytes == 0) || (adev->psp.sos.size_bytes == 0)) { 31745ca02815Sjsg dev_warn(adev->dev, "PSP SOS FW not available"); 31755ca02815Sjsg return -EINVAL; 31765ca02815Sjsg } 31775ca02815Sjsg 31785ca02815Sjsg return 0; 31795ca02815Sjsg } 31805ca02815Sjsg 3181f005ef32Sjsg int psp_init_sos_microcode(struct psp_context *psp, const char *chip_name) 3182ad8b1aafSjsg { 3183ad8b1aafSjsg struct amdgpu_device *adev = psp->adev; 31845ca02815Sjsg char fw_name[PSP_FW_NAME_LEN]; 3185ad8b1aafSjsg const struct psp_firmware_header_v1_0 *sos_hdr; 3186ad8b1aafSjsg const struct psp_firmware_header_v1_1 *sos_hdr_v1_1; 3187ad8b1aafSjsg const struct psp_firmware_header_v1_2 *sos_hdr_v1_2; 3188ad8b1aafSjsg const struct psp_firmware_header_v1_3 *sos_hdr_v1_3; 31895ca02815Sjsg const struct psp_firmware_header_v2_0 *sos_hdr_v2_0; 3190ad8b1aafSjsg int err = 0; 31915ca02815Sjsg uint8_t *ucode_array_start_addr; 31925ca02815Sjsg int fw_index = 0; 3193ad8b1aafSjsg 3194ad8b1aafSjsg snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_sos.bin", chip_name); 3195f005ef32Sjsg err = amdgpu_ucode_request(adev, &adev->psp.sos_fw, fw_name); 3196ad8b1aafSjsg if (err) 3197ad8b1aafSjsg goto out; 3198ad8b1aafSjsg 3199ad8b1aafSjsg sos_hdr = (const struct psp_firmware_header_v1_0 *)adev->psp.sos_fw->data; 32005ca02815Sjsg ucode_array_start_addr = (uint8_t *)sos_hdr + 32015ca02815Sjsg le32_to_cpu(sos_hdr->header.ucode_array_offset_bytes); 3202ad8b1aafSjsg amdgpu_ucode_print_psp_hdr(&sos_hdr->header); 3203ad8b1aafSjsg 3204ad8b1aafSjsg switch (sos_hdr->header.header_version_major) { 3205ad8b1aafSjsg case 1: 32065ca02815Sjsg err = psp_init_sos_base_fw(adev); 32075ca02815Sjsg if (err) 32085ca02815Sjsg goto out; 32095ca02815Sjsg 3210ad8b1aafSjsg if (sos_hdr->header.header_version_minor == 1) { 3211ad8b1aafSjsg sos_hdr_v1_1 = (const struct psp_firmware_header_v1_1 *)adev->psp.sos_fw->data; 32125ca02815Sjsg adev->psp.toc.size_bytes = le32_to_cpu(sos_hdr_v1_1->toc.size_bytes); 32135ca02815Sjsg adev->psp.toc.start_addr = (uint8_t *)adev->psp.sys.start_addr + 32145ca02815Sjsg le32_to_cpu(sos_hdr_v1_1->toc.offset_bytes); 32155ca02815Sjsg adev->psp.kdb.size_bytes = le32_to_cpu(sos_hdr_v1_1->kdb.size_bytes); 32165ca02815Sjsg adev->psp.kdb.start_addr = (uint8_t *)adev->psp.sys.start_addr + 32175ca02815Sjsg le32_to_cpu(sos_hdr_v1_1->kdb.offset_bytes); 3218ad8b1aafSjsg } 3219ad8b1aafSjsg if (sos_hdr->header.header_version_minor == 2) { 3220ad8b1aafSjsg sos_hdr_v1_2 = (const struct psp_firmware_header_v1_2 *)adev->psp.sos_fw->data; 32215ca02815Sjsg adev->psp.kdb.size_bytes = le32_to_cpu(sos_hdr_v1_2->kdb.size_bytes); 32225ca02815Sjsg adev->psp.kdb.start_addr = (uint8_t *)adev->psp.sys.start_addr + 32235ca02815Sjsg le32_to_cpu(sos_hdr_v1_2->kdb.offset_bytes); 3224ad8b1aafSjsg } 3225ad8b1aafSjsg if (sos_hdr->header.header_version_minor == 3) { 3226ad8b1aafSjsg sos_hdr_v1_3 = (const struct psp_firmware_header_v1_3 *)adev->psp.sos_fw->data; 32275ca02815Sjsg adev->psp.toc.size_bytes = le32_to_cpu(sos_hdr_v1_3->v1_1.toc.size_bytes); 32285ca02815Sjsg adev->psp.toc.start_addr = ucode_array_start_addr + 32295ca02815Sjsg le32_to_cpu(sos_hdr_v1_3->v1_1.toc.offset_bytes); 32305ca02815Sjsg adev->psp.kdb.size_bytes = le32_to_cpu(sos_hdr_v1_3->v1_1.kdb.size_bytes); 32315ca02815Sjsg adev->psp.kdb.start_addr = ucode_array_start_addr + 32325ca02815Sjsg le32_to_cpu(sos_hdr_v1_3->v1_1.kdb.offset_bytes); 32335ca02815Sjsg adev->psp.spl.size_bytes = le32_to_cpu(sos_hdr_v1_3->spl.size_bytes); 32345ca02815Sjsg adev->psp.spl.start_addr = ucode_array_start_addr + 32355ca02815Sjsg le32_to_cpu(sos_hdr_v1_3->spl.offset_bytes); 32365ca02815Sjsg adev->psp.rl.size_bytes = le32_to_cpu(sos_hdr_v1_3->rl.size_bytes); 32375ca02815Sjsg adev->psp.rl.start_addr = ucode_array_start_addr + 32385ca02815Sjsg le32_to_cpu(sos_hdr_v1_3->rl.offset_bytes); 32395ca02815Sjsg } 32405ca02815Sjsg break; 32415ca02815Sjsg case 2: 32425ca02815Sjsg sos_hdr_v2_0 = (const struct psp_firmware_header_v2_0 *)adev->psp.sos_fw->data; 32435ca02815Sjsg 32445ca02815Sjsg if (le32_to_cpu(sos_hdr_v2_0->psp_fw_bin_count) >= UCODE_MAX_PSP_PACKAGING) { 32455ca02815Sjsg dev_err(adev->dev, "packed SOS count exceeds maximum limit\n"); 32465ca02815Sjsg err = -EINVAL; 32475ca02815Sjsg goto out; 32485ca02815Sjsg } 32495ca02815Sjsg 32505ca02815Sjsg for (fw_index = 0; fw_index < le32_to_cpu(sos_hdr_v2_0->psp_fw_bin_count); fw_index++) { 32515ca02815Sjsg err = parse_sos_bin_descriptor(psp, 32525ca02815Sjsg &sos_hdr_v2_0->psp_fw_bin[fw_index], 32535ca02815Sjsg sos_hdr_v2_0); 32545ca02815Sjsg if (err) 32555ca02815Sjsg goto out; 3256ad8b1aafSjsg } 3257ad8b1aafSjsg break; 3258ad8b1aafSjsg default: 3259ad8b1aafSjsg dev_err(adev->dev, 3260ad8b1aafSjsg "unsupported psp sos firmware\n"); 3261ad8b1aafSjsg err = -EINVAL; 3262ad8b1aafSjsg goto out; 3263ad8b1aafSjsg } 3264ad8b1aafSjsg 3265ad8b1aafSjsg return 0; 3266ad8b1aafSjsg out: 3267f005ef32Sjsg amdgpu_ucode_release(&adev->psp.sos_fw); 3268ad8b1aafSjsg 3269ad8b1aafSjsg return err; 3270ad8b1aafSjsg } 3271ad8b1aafSjsg 32725ca02815Sjsg static int parse_ta_bin_descriptor(struct psp_context *psp, 32735ca02815Sjsg const struct psp_fw_bin_desc *desc, 3274ad8b1aafSjsg const struct ta_firmware_header_v2_0 *ta_hdr) 3275ad8b1aafSjsg { 3276ad8b1aafSjsg uint8_t *ucode_start_addr = NULL; 3277ad8b1aafSjsg 3278ad8b1aafSjsg if (!psp || !desc || !ta_hdr) 3279ad8b1aafSjsg return -EINVAL; 3280ad8b1aafSjsg 3281ad8b1aafSjsg ucode_start_addr = (uint8_t *)ta_hdr + 3282ad8b1aafSjsg le32_to_cpu(desc->offset_bytes) + 3283ad8b1aafSjsg le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes); 3284ad8b1aafSjsg 3285ad8b1aafSjsg switch (desc->fw_type) { 3286ad8b1aafSjsg case TA_FW_TYPE_PSP_ASD: 32871bb76ff1Sjsg psp->asd_context.bin_desc.fw_version = le32_to_cpu(desc->fw_version); 32881bb76ff1Sjsg psp->asd_context.bin_desc.feature_version = le32_to_cpu(desc->fw_version); 32891bb76ff1Sjsg psp->asd_context.bin_desc.size_bytes = le32_to_cpu(desc->size_bytes); 32901bb76ff1Sjsg psp->asd_context.bin_desc.start_addr = ucode_start_addr; 3291ad8b1aafSjsg break; 3292ad8b1aafSjsg case TA_FW_TYPE_PSP_XGMI: 32931bb76ff1Sjsg psp->xgmi_context.context.bin_desc.fw_version = le32_to_cpu(desc->fw_version); 32941bb76ff1Sjsg psp->xgmi_context.context.bin_desc.size_bytes = le32_to_cpu(desc->size_bytes); 32951bb76ff1Sjsg psp->xgmi_context.context.bin_desc.start_addr = ucode_start_addr; 3296ad8b1aafSjsg break; 3297ad8b1aafSjsg case TA_FW_TYPE_PSP_RAS: 32981bb76ff1Sjsg psp->ras_context.context.bin_desc.fw_version = le32_to_cpu(desc->fw_version); 32991bb76ff1Sjsg psp->ras_context.context.bin_desc.size_bytes = le32_to_cpu(desc->size_bytes); 33001bb76ff1Sjsg psp->ras_context.context.bin_desc.start_addr = ucode_start_addr; 3301ad8b1aafSjsg break; 3302ad8b1aafSjsg case TA_FW_TYPE_PSP_HDCP: 33031bb76ff1Sjsg psp->hdcp_context.context.bin_desc.fw_version = le32_to_cpu(desc->fw_version); 33041bb76ff1Sjsg psp->hdcp_context.context.bin_desc.size_bytes = le32_to_cpu(desc->size_bytes); 33051bb76ff1Sjsg psp->hdcp_context.context.bin_desc.start_addr = ucode_start_addr; 3306ad8b1aafSjsg break; 3307ad8b1aafSjsg case TA_FW_TYPE_PSP_DTM: 33081bb76ff1Sjsg psp->dtm_context.context.bin_desc.fw_version = le32_to_cpu(desc->fw_version); 33091bb76ff1Sjsg psp->dtm_context.context.bin_desc.size_bytes = le32_to_cpu(desc->size_bytes); 33101bb76ff1Sjsg psp->dtm_context.context.bin_desc.start_addr = ucode_start_addr; 3311ad8b1aafSjsg break; 3312ad8b1aafSjsg case TA_FW_TYPE_PSP_RAP: 33131bb76ff1Sjsg psp->rap_context.context.bin_desc.fw_version = le32_to_cpu(desc->fw_version); 33141bb76ff1Sjsg psp->rap_context.context.bin_desc.size_bytes = le32_to_cpu(desc->size_bytes); 33151bb76ff1Sjsg psp->rap_context.context.bin_desc.start_addr = ucode_start_addr; 33165ca02815Sjsg break; 33175ca02815Sjsg case TA_FW_TYPE_PSP_SECUREDISPLAY: 33181bb76ff1Sjsg psp->securedisplay_context.context.bin_desc.fw_version = 33191bb76ff1Sjsg le32_to_cpu(desc->fw_version); 33201bb76ff1Sjsg psp->securedisplay_context.context.bin_desc.size_bytes = 33211bb76ff1Sjsg le32_to_cpu(desc->size_bytes); 33221bb76ff1Sjsg psp->securedisplay_context.context.bin_desc.start_addr = 33231bb76ff1Sjsg ucode_start_addr; 3324ad8b1aafSjsg break; 3325ad8b1aafSjsg default: 3326ad8b1aafSjsg dev_warn(psp->adev->dev, "Unsupported TA type: %d\n", desc->fw_type); 3327ad8b1aafSjsg break; 3328ad8b1aafSjsg } 3329ad8b1aafSjsg 3330ad8b1aafSjsg return 0; 3331ad8b1aafSjsg } 3332ad8b1aafSjsg 3333f005ef32Sjsg static int parse_ta_v1_microcode(struct psp_context *psp) 3334ad8b1aafSjsg { 3335f005ef32Sjsg const struct ta_firmware_header_v1_0 *ta_hdr; 3336ad8b1aafSjsg struct amdgpu_device *adev = psp->adev; 3337f005ef32Sjsg 3338f005ef32Sjsg ta_hdr = (const struct ta_firmware_header_v1_0 *) adev->psp.ta_fw->data; 3339f005ef32Sjsg 3340f005ef32Sjsg if (le16_to_cpu(ta_hdr->header.header_version_major) != 1) 3341f005ef32Sjsg return -EINVAL; 3342f005ef32Sjsg 3343f005ef32Sjsg adev->psp.xgmi_context.context.bin_desc.fw_version = 3344f005ef32Sjsg le32_to_cpu(ta_hdr->xgmi.fw_version); 3345f005ef32Sjsg adev->psp.xgmi_context.context.bin_desc.size_bytes = 3346f005ef32Sjsg le32_to_cpu(ta_hdr->xgmi.size_bytes); 3347f005ef32Sjsg adev->psp.xgmi_context.context.bin_desc.start_addr = 3348f005ef32Sjsg (uint8_t *)ta_hdr + 3349f005ef32Sjsg le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes); 3350f005ef32Sjsg 3351f005ef32Sjsg adev->psp.ras_context.context.bin_desc.fw_version = 3352f005ef32Sjsg le32_to_cpu(ta_hdr->ras.fw_version); 3353f005ef32Sjsg adev->psp.ras_context.context.bin_desc.size_bytes = 3354f005ef32Sjsg le32_to_cpu(ta_hdr->ras.size_bytes); 3355f005ef32Sjsg adev->psp.ras_context.context.bin_desc.start_addr = 3356f005ef32Sjsg (uint8_t *)adev->psp.xgmi_context.context.bin_desc.start_addr + 3357f005ef32Sjsg le32_to_cpu(ta_hdr->ras.offset_bytes); 3358f005ef32Sjsg 3359f005ef32Sjsg adev->psp.hdcp_context.context.bin_desc.fw_version = 3360f005ef32Sjsg le32_to_cpu(ta_hdr->hdcp.fw_version); 3361f005ef32Sjsg adev->psp.hdcp_context.context.bin_desc.size_bytes = 3362f005ef32Sjsg le32_to_cpu(ta_hdr->hdcp.size_bytes); 3363f005ef32Sjsg adev->psp.hdcp_context.context.bin_desc.start_addr = 3364f005ef32Sjsg (uint8_t *)ta_hdr + 3365f005ef32Sjsg le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes); 3366f005ef32Sjsg 3367f005ef32Sjsg adev->psp.dtm_context.context.bin_desc.fw_version = 3368f005ef32Sjsg le32_to_cpu(ta_hdr->dtm.fw_version); 3369f005ef32Sjsg adev->psp.dtm_context.context.bin_desc.size_bytes = 3370f005ef32Sjsg le32_to_cpu(ta_hdr->dtm.size_bytes); 3371f005ef32Sjsg adev->psp.dtm_context.context.bin_desc.start_addr = 3372f005ef32Sjsg (uint8_t *)adev->psp.hdcp_context.context.bin_desc.start_addr + 3373f005ef32Sjsg le32_to_cpu(ta_hdr->dtm.offset_bytes); 3374f005ef32Sjsg 3375f005ef32Sjsg adev->psp.securedisplay_context.context.bin_desc.fw_version = 3376f005ef32Sjsg le32_to_cpu(ta_hdr->securedisplay.fw_version); 3377f005ef32Sjsg adev->psp.securedisplay_context.context.bin_desc.size_bytes = 3378f005ef32Sjsg le32_to_cpu(ta_hdr->securedisplay.size_bytes); 3379f005ef32Sjsg adev->psp.securedisplay_context.context.bin_desc.start_addr = 3380f005ef32Sjsg (uint8_t *)adev->psp.hdcp_context.context.bin_desc.start_addr + 3381f005ef32Sjsg le32_to_cpu(ta_hdr->securedisplay.offset_bytes); 3382f005ef32Sjsg 3383f005ef32Sjsg adev->psp.ta_fw_version = le32_to_cpu(ta_hdr->header.ucode_version); 3384f005ef32Sjsg 3385f005ef32Sjsg return 0; 3386f005ef32Sjsg } 3387f005ef32Sjsg 3388f005ef32Sjsg static int parse_ta_v2_microcode(struct psp_context *psp) 3389f005ef32Sjsg { 3390ad8b1aafSjsg const struct ta_firmware_header_v2_0 *ta_hdr; 3391f005ef32Sjsg struct amdgpu_device *adev = psp->adev; 3392ad8b1aafSjsg int err = 0; 3393ad8b1aafSjsg int ta_index = 0; 3394ad8b1aafSjsg 3395ad8b1aafSjsg ta_hdr = (const struct ta_firmware_header_v2_0 *)adev->psp.ta_fw->data; 3396ad8b1aafSjsg 3397f005ef32Sjsg if (le16_to_cpu(ta_hdr->header.header_version_major) != 2) 3398f005ef32Sjsg return -EINVAL; 3399ad8b1aafSjsg 34005ca02815Sjsg if (le32_to_cpu(ta_hdr->ta_fw_bin_count) >= UCODE_MAX_PSP_PACKAGING) { 3401ad8b1aafSjsg dev_err(adev->dev, "packed TA count exceeds maximum limit\n"); 3402f005ef32Sjsg return -EINVAL; 3403ad8b1aafSjsg } 3404ad8b1aafSjsg 3405ad8b1aafSjsg for (ta_index = 0; ta_index < le32_to_cpu(ta_hdr->ta_fw_bin_count); ta_index++) { 3406ad8b1aafSjsg err = parse_ta_bin_descriptor(psp, 3407ad8b1aafSjsg &ta_hdr->ta_fw_bin[ta_index], 3408ad8b1aafSjsg ta_hdr); 3409ad8b1aafSjsg if (err) 3410ad8b1aafSjsg return err; 3411fb4d8502Sjsg } 3412fb4d8502Sjsg 3413f005ef32Sjsg return 0; 3414f005ef32Sjsg } 3415f005ef32Sjsg 3416f005ef32Sjsg int psp_init_ta_microcode(struct psp_context *psp, const char *chip_name) 3417f005ef32Sjsg { 3418f005ef32Sjsg const struct common_firmware_header *hdr; 3419f005ef32Sjsg struct amdgpu_device *adev = psp->adev; 3420f005ef32Sjsg char fw_name[PSP_FW_NAME_LEN]; 3421f005ef32Sjsg int err; 3422f005ef32Sjsg 3423f005ef32Sjsg snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ta.bin", chip_name); 3424f005ef32Sjsg err = amdgpu_ucode_request(adev, &adev->psp.ta_fw, fw_name); 3425f005ef32Sjsg if (err) 3426f005ef32Sjsg return err; 3427f005ef32Sjsg 3428f005ef32Sjsg hdr = (const struct common_firmware_header *)adev->psp.ta_fw->data; 3429f005ef32Sjsg switch (le16_to_cpu(hdr->header_version_major)) { 3430f005ef32Sjsg case 1: 3431f005ef32Sjsg err = parse_ta_v1_microcode(psp); 3432f005ef32Sjsg break; 3433f005ef32Sjsg case 2: 3434f005ef32Sjsg err = parse_ta_v2_microcode(psp); 3435f005ef32Sjsg break; 3436f005ef32Sjsg default: 3437f005ef32Sjsg dev_err(adev->dev, "unsupported TA header version\n"); 3438f005ef32Sjsg err = -EINVAL; 3439f005ef32Sjsg } 3440f005ef32Sjsg 3441f005ef32Sjsg if (err) 3442f005ef32Sjsg amdgpu_ucode_release(&adev->psp.ta_fw); 3443f005ef32Sjsg 3444f005ef32Sjsg return err; 3445f005ef32Sjsg } 3446f005ef32Sjsg 3447f005ef32Sjsg int psp_init_cap_microcode(struct psp_context *psp, const char *chip_name) 34481bb76ff1Sjsg { 34491bb76ff1Sjsg struct amdgpu_device *adev = psp->adev; 34501bb76ff1Sjsg char fw_name[PSP_FW_NAME_LEN]; 34511bb76ff1Sjsg const struct psp_firmware_header_v1_0 *cap_hdr_v1_0; 34521bb76ff1Sjsg struct amdgpu_firmware_info *info = NULL; 34531bb76ff1Sjsg int err = 0; 34541bb76ff1Sjsg 34551bb76ff1Sjsg if (!amdgpu_sriov_vf(adev)) { 34561bb76ff1Sjsg dev_err(adev->dev, "cap microcode should only be loaded under SRIOV\n"); 34571bb76ff1Sjsg return -EINVAL; 34581bb76ff1Sjsg } 34591bb76ff1Sjsg 34601bb76ff1Sjsg snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_cap.bin", chip_name); 3461f005ef32Sjsg err = amdgpu_ucode_request(adev, &adev->psp.cap_fw, fw_name); 34621bb76ff1Sjsg if (err) { 3463f005ef32Sjsg if (err == -ENODEV) { 34641bb76ff1Sjsg dev_warn(adev->dev, "cap microcode does not exist, skip\n"); 34651bb76ff1Sjsg err = 0; 34661bb76ff1Sjsg goto out; 34671bb76ff1Sjsg } 34681bb76ff1Sjsg dev_err(adev->dev, "fail to initialize cap microcode\n"); 34691bb76ff1Sjsg } 34701bb76ff1Sjsg 34711bb76ff1Sjsg info = &adev->firmware.ucode[AMDGPU_UCODE_ID_CAP]; 34721bb76ff1Sjsg info->ucode_id = AMDGPU_UCODE_ID_CAP; 34731bb76ff1Sjsg info->fw = adev->psp.cap_fw; 34741bb76ff1Sjsg cap_hdr_v1_0 = (const struct psp_firmware_header_v1_0 *) 34751bb76ff1Sjsg adev->psp.cap_fw->data; 3476f005ef32Sjsg adev->firmware.fw_size += ALIGN( 34771bb76ff1Sjsg le32_to_cpu(cap_hdr_v1_0->header.ucode_size_bytes), PAGE_SIZE); 34781bb76ff1Sjsg adev->psp.cap_fw_version = le32_to_cpu(cap_hdr_v1_0->header.ucode_version); 34791bb76ff1Sjsg adev->psp.cap_feature_version = le32_to_cpu(cap_hdr_v1_0->sos.fw_version); 34801bb76ff1Sjsg adev->psp.cap_ucode_size = le32_to_cpu(cap_hdr_v1_0->header.ucode_size_bytes); 34811bb76ff1Sjsg 34821bb76ff1Sjsg return 0; 34831bb76ff1Sjsg 34841bb76ff1Sjsg out: 3485f005ef32Sjsg amdgpu_ucode_release(&adev->psp.cap_fw); 34861bb76ff1Sjsg return err; 34871bb76ff1Sjsg } 34881bb76ff1Sjsg 3489fb4d8502Sjsg static int psp_set_clockgating_state(void *handle, 3490fb4d8502Sjsg enum amd_clockgating_state state) 3491fb4d8502Sjsg { 3492fb4d8502Sjsg return 0; 3493fb4d8502Sjsg } 3494fb4d8502Sjsg 3495fb4d8502Sjsg static int psp_set_powergating_state(void *handle, 3496fb4d8502Sjsg enum amd_powergating_state state) 3497fb4d8502Sjsg { 3498fb4d8502Sjsg return 0; 3499fb4d8502Sjsg } 3500fb4d8502Sjsg 3501c349dbc7Sjsg static ssize_t psp_usbc_pd_fw_sysfs_read(struct device *dev, 3502c349dbc7Sjsg struct device_attribute *attr, 3503c349dbc7Sjsg char *buf) 3504c349dbc7Sjsg { 3505c349dbc7Sjsg struct drm_device *ddev = dev_get_drvdata(dev); 3506ad8b1aafSjsg struct amdgpu_device *adev = drm_to_adev(ddev); 3507c349dbc7Sjsg uint32_t fw_ver; 3508c349dbc7Sjsg int ret; 3509c349dbc7Sjsg 3510c349dbc7Sjsg if (!adev->ip_blocks[AMD_IP_BLOCK_TYPE_PSP].status.late_initialized) { 3511c349dbc7Sjsg DRM_INFO("PSP block is not ready yet."); 3512c349dbc7Sjsg return -EBUSY; 3513c349dbc7Sjsg } 3514c349dbc7Sjsg 3515c349dbc7Sjsg mutex_lock(&adev->psp.mutex); 3516c349dbc7Sjsg ret = psp_read_usbc_pd_fw(&adev->psp, &fw_ver); 3517c349dbc7Sjsg mutex_unlock(&adev->psp.mutex); 3518c349dbc7Sjsg 3519c349dbc7Sjsg if (ret) { 3520c349dbc7Sjsg DRM_ERROR("Failed to read USBC PD FW, err = %d", ret); 3521c349dbc7Sjsg return ret; 3522c349dbc7Sjsg } 3523c349dbc7Sjsg 35245ca02815Sjsg return sysfs_emit(buf, "%x\n", fw_ver); 3525c349dbc7Sjsg } 3526c349dbc7Sjsg 3527c349dbc7Sjsg static ssize_t psp_usbc_pd_fw_sysfs_write(struct device *dev, 3528c349dbc7Sjsg struct device_attribute *attr, 3529c349dbc7Sjsg const char *buf, 3530c349dbc7Sjsg size_t count) 3531c349dbc7Sjsg { 3532c349dbc7Sjsg struct drm_device *ddev = dev_get_drvdata(dev); 3533ad8b1aafSjsg struct amdgpu_device *adev = drm_to_adev(ddev); 35345ca02815Sjsg int ret, idx; 3535c349dbc7Sjsg char fw_name[100]; 3536c349dbc7Sjsg const struct firmware *usbc_pd_fw; 35375ca02815Sjsg struct amdgpu_bo *fw_buf_bo = NULL; 35385ca02815Sjsg uint64_t fw_pri_mc_addr; 35395ca02815Sjsg void *fw_pri_cpu_addr; 3540c349dbc7Sjsg 3541c349dbc7Sjsg if (!adev->ip_blocks[AMD_IP_BLOCK_TYPE_PSP].status.late_initialized) { 3542c349dbc7Sjsg DRM_INFO("PSP block is not ready yet."); 3543c349dbc7Sjsg return -EBUSY; 3544c349dbc7Sjsg } 3545c349dbc7Sjsg 35465ca02815Sjsg if (!drm_dev_enter(ddev, &idx)) 35475ca02815Sjsg return -ENODEV; 35485ca02815Sjsg 3549c349dbc7Sjsg snprintf(fw_name, sizeof(fw_name), "amdgpu/%s", buf); 3550c349dbc7Sjsg ret = request_firmware(&usbc_pd_fw, fw_name, adev->dev); 3551c349dbc7Sjsg if (ret) 3552c349dbc7Sjsg goto fail; 3553c349dbc7Sjsg 35545ca02815Sjsg /* LFB address which is aligned to 1MB boundary per PSP request */ 35555ca02815Sjsg ret = amdgpu_bo_create_kernel(adev, usbc_pd_fw->size, 0x100000, 3556f005ef32Sjsg AMDGPU_GEM_DOMAIN_VRAM | 3557f005ef32Sjsg AMDGPU_GEM_DOMAIN_GTT, 3558f005ef32Sjsg &fw_buf_bo, &fw_pri_mc_addr, 35595ca02815Sjsg &fw_pri_cpu_addr); 3560c349dbc7Sjsg if (ret) 3561c349dbc7Sjsg goto rel_buf; 3562c349dbc7Sjsg 35635ca02815Sjsg memcpy_toio(fw_pri_cpu_addr, usbc_pd_fw->data, usbc_pd_fw->size); 3564c349dbc7Sjsg 3565c349dbc7Sjsg mutex_lock(&adev->psp.mutex); 35665ca02815Sjsg ret = psp_load_usbc_pd_fw(&adev->psp, fw_pri_mc_addr); 3567c349dbc7Sjsg mutex_unlock(&adev->psp.mutex); 3568c349dbc7Sjsg 35695ca02815Sjsg amdgpu_bo_free_kernel(&fw_buf_bo, &fw_pri_mc_addr, &fw_pri_cpu_addr); 3570c349dbc7Sjsg 35715ca02815Sjsg rel_buf: 35725ca02815Sjsg release_firmware(usbc_pd_fw); 3573c349dbc7Sjsg fail: 3574c349dbc7Sjsg if (ret) { 3575c349dbc7Sjsg DRM_ERROR("Failed to load USBC PD FW, err = %d", ret); 35765ca02815Sjsg count = ret; 3577c349dbc7Sjsg } 3578c349dbc7Sjsg 35795ca02815Sjsg drm_dev_exit(idx); 3580c349dbc7Sjsg return count; 3581c349dbc7Sjsg } 3582c349dbc7Sjsg 35835ca02815Sjsg void psp_copy_fw(struct psp_context *psp, uint8_t *start_addr, uint32_t bin_size) 35845ca02815Sjsg { 35855ca02815Sjsg int idx; 35865ca02815Sjsg 35871bb76ff1Sjsg if (!drm_dev_enter(adev_to_drm(psp->adev), &idx)) 35885ca02815Sjsg return; 35895ca02815Sjsg 35905ca02815Sjsg memset(psp->fw_pri_buf, 0, PSP_1_MEG); 35915ca02815Sjsg memcpy(psp->fw_pri_buf, start_addr, bin_size); 35925ca02815Sjsg 35935ca02815Sjsg drm_dev_exit(idx); 35945ca02815Sjsg } 35955ca02815Sjsg 3596f005ef32Sjsg /** 3597f005ef32Sjsg * DOC: usbc_pd_fw 3598f005ef32Sjsg * Reading from this file will retrieve the USB-C PD firmware version. Writing to 3599f005ef32Sjsg * this file will trigger the update process. 3600f005ef32Sjsg */ 3601f005ef32Sjsg static DEVICE_ATTR(usbc_pd_fw, 0644, 3602c349dbc7Sjsg psp_usbc_pd_fw_sysfs_read, 3603c349dbc7Sjsg psp_usbc_pd_fw_sysfs_write); 3604c349dbc7Sjsg 36055ca02815Sjsg int is_psp_fw_valid(struct psp_bin_desc bin) 36065ca02815Sjsg { 36075ca02815Sjsg return bin.size_bytes; 36085ca02815Sjsg } 3609c349dbc7Sjsg 36101bb76ff1Sjsg static ssize_t amdgpu_psp_vbflash_write(struct file *filp, struct kobject *kobj, 36111bb76ff1Sjsg struct bin_attribute *bin_attr, 36121bb76ff1Sjsg char *buffer, loff_t pos, size_t count) 36131bb76ff1Sjsg { 36141bb76ff1Sjsg STUB(); 36151bb76ff1Sjsg return -ENOSYS; 36161bb76ff1Sjsg #ifdef notyet 36171bb76ff1Sjsg struct device *dev = kobj_to_dev(kobj); 36181bb76ff1Sjsg struct drm_device *ddev = dev_get_drvdata(dev); 36191bb76ff1Sjsg struct amdgpu_device *adev = drm_to_adev(ddev); 36201bb76ff1Sjsg 36211bb76ff1Sjsg adev->psp.vbflash_done = false; 36221bb76ff1Sjsg 36231bb76ff1Sjsg /* Safeguard against memory drain */ 36241bb76ff1Sjsg if (adev->psp.vbflash_image_size > AMD_VBIOS_FILE_MAX_SIZE_B) { 36251bb76ff1Sjsg dev_err(adev->dev, "File size cannot exceed %u", AMD_VBIOS_FILE_MAX_SIZE_B); 36261bb76ff1Sjsg kvfree(adev->psp.vbflash_tmp_buf); 36271bb76ff1Sjsg adev->psp.vbflash_tmp_buf = NULL; 36281bb76ff1Sjsg adev->psp.vbflash_image_size = 0; 36291bb76ff1Sjsg return -ENOMEM; 36301bb76ff1Sjsg } 36311bb76ff1Sjsg 36321bb76ff1Sjsg /* TODO Just allocate max for now and optimize to realloc later if needed */ 36331bb76ff1Sjsg if (!adev->psp.vbflash_tmp_buf) { 36341bb76ff1Sjsg adev->psp.vbflash_tmp_buf = kvmalloc(AMD_VBIOS_FILE_MAX_SIZE_B, GFP_KERNEL); 36351bb76ff1Sjsg if (!adev->psp.vbflash_tmp_buf) 36361bb76ff1Sjsg return -ENOMEM; 36371bb76ff1Sjsg } 36381bb76ff1Sjsg 36391bb76ff1Sjsg mutex_lock(&adev->psp.mutex); 36401bb76ff1Sjsg memcpy(adev->psp.vbflash_tmp_buf + pos, buffer, count); 36411bb76ff1Sjsg adev->psp.vbflash_image_size += count; 36421bb76ff1Sjsg mutex_unlock(&adev->psp.mutex); 36431bb76ff1Sjsg 3644f005ef32Sjsg dev_dbg(adev->dev, "IFWI staged for update"); 36451bb76ff1Sjsg 36461bb76ff1Sjsg return count; 36471bb76ff1Sjsg #endif 36481bb76ff1Sjsg } 36491bb76ff1Sjsg 36501bb76ff1Sjsg static ssize_t amdgpu_psp_vbflash_read(struct file *filp, struct kobject *kobj, 36511bb76ff1Sjsg struct bin_attribute *bin_attr, char *buffer, 36521bb76ff1Sjsg loff_t pos, size_t count) 36531bb76ff1Sjsg { 36541bb76ff1Sjsg STUB(); 36551bb76ff1Sjsg return -ENOSYS; 36561bb76ff1Sjsg #ifdef notyet 36571bb76ff1Sjsg struct device *dev = kobj_to_dev(kobj); 36581bb76ff1Sjsg struct drm_device *ddev = dev_get_drvdata(dev); 36591bb76ff1Sjsg struct amdgpu_device *adev = drm_to_adev(ddev); 36601bb76ff1Sjsg struct amdgpu_bo *fw_buf_bo = NULL; 36611bb76ff1Sjsg uint64_t fw_pri_mc_addr; 36621bb76ff1Sjsg void *fw_pri_cpu_addr; 36631bb76ff1Sjsg int ret; 36641bb76ff1Sjsg 3665e60282a8Sjsg if (adev->psp.vbflash_image_size == 0) 3666e60282a8Sjsg return -EINVAL; 3667e60282a8Sjsg 3668f005ef32Sjsg dev_dbg(adev->dev, "PSP IFWI flash process initiated"); 36691bb76ff1Sjsg 36701bb76ff1Sjsg ret = amdgpu_bo_create_kernel(adev, adev->psp.vbflash_image_size, 36711bb76ff1Sjsg AMDGPU_GPU_PAGE_SIZE, 36721bb76ff1Sjsg AMDGPU_GEM_DOMAIN_VRAM, 36731bb76ff1Sjsg &fw_buf_bo, 36741bb76ff1Sjsg &fw_pri_mc_addr, 36751bb76ff1Sjsg &fw_pri_cpu_addr); 36761bb76ff1Sjsg if (ret) 36771bb76ff1Sjsg goto rel_buf; 36781bb76ff1Sjsg 36791bb76ff1Sjsg memcpy_toio(fw_pri_cpu_addr, adev->psp.vbflash_tmp_buf, adev->psp.vbflash_image_size); 36801bb76ff1Sjsg 36811bb76ff1Sjsg mutex_lock(&adev->psp.mutex); 36821bb76ff1Sjsg ret = psp_update_spirom(&adev->psp, fw_pri_mc_addr); 36831bb76ff1Sjsg mutex_unlock(&adev->psp.mutex); 36841bb76ff1Sjsg 36851bb76ff1Sjsg amdgpu_bo_free_kernel(&fw_buf_bo, &fw_pri_mc_addr, &fw_pri_cpu_addr); 36861bb76ff1Sjsg 36871bb76ff1Sjsg rel_buf: 36881bb76ff1Sjsg kvfree(adev->psp.vbflash_tmp_buf); 36891bb76ff1Sjsg adev->psp.vbflash_tmp_buf = NULL; 36901bb76ff1Sjsg adev->psp.vbflash_image_size = 0; 36911bb76ff1Sjsg 36921bb76ff1Sjsg if (ret) { 3693f005ef32Sjsg dev_err(adev->dev, "Failed to load IFWI, err = %d", ret); 36941bb76ff1Sjsg return ret; 36951bb76ff1Sjsg } 36961bb76ff1Sjsg 3697f005ef32Sjsg dev_dbg(adev->dev, "PSP IFWI flash process done"); 36981bb76ff1Sjsg return 0; 36991bb76ff1Sjsg #endif 37001bb76ff1Sjsg } 37011bb76ff1Sjsg 3702f005ef32Sjsg /** 3703f005ef32Sjsg * DOC: psp_vbflash 3704f005ef32Sjsg * Writing to this file will stage an IFWI for update. Reading from this file 3705f005ef32Sjsg * will trigger the update process. 3706f005ef32Sjsg */ 3707f005ef32Sjsg #ifdef notyet 3708f005ef32Sjsg static struct bin_attribute psp_vbflash_bin_attr = { 3709f005ef32Sjsg .attr = {.name = "psp_vbflash", .mode = 0660}, 3710f005ef32Sjsg .size = 0, 3711f005ef32Sjsg .write = amdgpu_psp_vbflash_write, 3712f005ef32Sjsg .read = amdgpu_psp_vbflash_read, 3713f005ef32Sjsg }; 3714f005ef32Sjsg #endif 3715f005ef32Sjsg 3716f005ef32Sjsg /** 3717f005ef32Sjsg * DOC: psp_vbflash_status 3718f005ef32Sjsg * The status of the flash process. 3719f005ef32Sjsg * 0: IFWI flash not complete. 3720f005ef32Sjsg * 1: IFWI flash complete. 3721f005ef32Sjsg */ 37221bb76ff1Sjsg static ssize_t amdgpu_psp_vbflash_status(struct device *dev, 37231bb76ff1Sjsg struct device_attribute *attr, 37241bb76ff1Sjsg char *buf) 37251bb76ff1Sjsg { 37261bb76ff1Sjsg struct drm_device *ddev = dev_get_drvdata(dev); 37271bb76ff1Sjsg struct amdgpu_device *adev = drm_to_adev(ddev); 37281bb76ff1Sjsg uint32_t vbflash_status; 37291bb76ff1Sjsg 37301bb76ff1Sjsg vbflash_status = psp_vbflash_status(&adev->psp); 37311bb76ff1Sjsg if (!adev->psp.vbflash_done) 37321bb76ff1Sjsg vbflash_status = 0; 37331bb76ff1Sjsg else if (adev->psp.vbflash_done && !(vbflash_status & 0x80000000)) 37341bb76ff1Sjsg vbflash_status = 1; 37351bb76ff1Sjsg 37361bb76ff1Sjsg return sysfs_emit(buf, "0x%x\n", vbflash_status); 37371bb76ff1Sjsg } 3738f005ef32Sjsg static DEVICE_ATTR(psp_vbflash_status, 0440, amdgpu_psp_vbflash_status, NULL); 37391bb76ff1Sjsg 37401bb76ff1Sjsg #ifdef notyet 3741f005ef32Sjsg static struct bin_attribute *bin_flash_attrs[] = { 3742f005ef32Sjsg &psp_vbflash_bin_attr, 3743f005ef32Sjsg NULL 37441bb76ff1Sjsg }; 37451bb76ff1Sjsg #endif 37461bb76ff1Sjsg 3747f005ef32Sjsg static struct attribute *flash_attrs[] = { 3748f005ef32Sjsg &dev_attr_psp_vbflash_status.attr, 3749f005ef32Sjsg &dev_attr_usbc_pd_fw.attr, 3750f005ef32Sjsg NULL 3751f005ef32Sjsg }; 37521bb76ff1Sjsg 3753f005ef32Sjsg #ifdef notyet 3754f005ef32Sjsg 3755f005ef32Sjsg static umode_t amdgpu_flash_attr_is_visible(struct kobject *kobj, struct attribute *attr, int idx) 37561bb76ff1Sjsg { 3757f005ef32Sjsg struct device *dev = kobj_to_dev(kobj); 3758f005ef32Sjsg struct drm_device *ddev = dev_get_drvdata(dev); 3759f005ef32Sjsg struct amdgpu_device *adev = drm_to_adev(ddev); 37601bb76ff1Sjsg 3761f005ef32Sjsg if (attr == &dev_attr_usbc_pd_fw.attr) 3762f005ef32Sjsg return adev->psp.sup_pd_fw_up ? 0660 : 0; 37631bb76ff1Sjsg 3764f005ef32Sjsg return adev->psp.sup_ifwi_up ? 0440 : 0; 37651bb76ff1Sjsg } 3766f005ef32Sjsg 3767f005ef32Sjsg static umode_t amdgpu_bin_flash_attr_is_visible(struct kobject *kobj, 3768f005ef32Sjsg struct bin_attribute *attr, 3769f005ef32Sjsg int idx) 3770f005ef32Sjsg { 3771f005ef32Sjsg struct device *dev = kobj_to_dev(kobj); 3772f005ef32Sjsg struct drm_device *ddev = dev_get_drvdata(dev); 3773f005ef32Sjsg struct amdgpu_device *adev = drm_to_adev(ddev); 3774f005ef32Sjsg 3775f005ef32Sjsg return adev->psp.sup_ifwi_up ? 0660 : 0; 37761bb76ff1Sjsg } 3777f005ef32Sjsg 3778f005ef32Sjsg const struct attribute_group amdgpu_flash_attr_group = { 3779f005ef32Sjsg .attrs = flash_attrs, 3780f005ef32Sjsg .bin_attrs = bin_flash_attrs, 3781f005ef32Sjsg .is_bin_visible = amdgpu_bin_flash_attr_is_visible, 3782f005ef32Sjsg .is_visible = amdgpu_flash_attr_is_visible, 3783f005ef32Sjsg }; 3784f005ef32Sjsg 3785f005ef32Sjsg #endif /* notyet */ 37861bb76ff1Sjsg 3787fb4d8502Sjsg const struct amd_ip_funcs psp_ip_funcs = { 3788fb4d8502Sjsg .name = "psp", 3789fb4d8502Sjsg .early_init = psp_early_init, 3790fb4d8502Sjsg .late_init = NULL, 3791fb4d8502Sjsg .sw_init = psp_sw_init, 3792fb4d8502Sjsg .sw_fini = psp_sw_fini, 3793fb4d8502Sjsg .hw_init = psp_hw_init, 3794fb4d8502Sjsg .hw_fini = psp_hw_fini, 3795fb4d8502Sjsg .suspend = psp_suspend, 3796fb4d8502Sjsg .resume = psp_resume, 3797fb4d8502Sjsg .is_idle = NULL, 3798fb4d8502Sjsg .check_soft_reset = NULL, 3799fb4d8502Sjsg .wait_for_idle = NULL, 3800fb4d8502Sjsg .soft_reset = NULL, 3801fb4d8502Sjsg .set_clockgating_state = psp_set_clockgating_state, 3802fb4d8502Sjsg .set_powergating_state = psp_set_powergating_state, 3803fb4d8502Sjsg }; 3804fb4d8502Sjsg 3805f005ef32Sjsg const struct amdgpu_ip_block_version psp_v3_1_ip_block = { 3806fb4d8502Sjsg .type = AMD_IP_BLOCK_TYPE_PSP, 3807fb4d8502Sjsg .major = 3, 3808fb4d8502Sjsg .minor = 1, 3809fb4d8502Sjsg .rev = 0, 3810fb4d8502Sjsg .funcs = &psp_ip_funcs, 3811fb4d8502Sjsg }; 3812fb4d8502Sjsg 3813f005ef32Sjsg const struct amdgpu_ip_block_version psp_v10_0_ip_block = { 3814fb4d8502Sjsg .type = AMD_IP_BLOCK_TYPE_PSP, 3815fb4d8502Sjsg .major = 10, 3816fb4d8502Sjsg .minor = 0, 3817fb4d8502Sjsg .rev = 0, 3818fb4d8502Sjsg .funcs = &psp_ip_funcs, 3819fb4d8502Sjsg }; 3820c349dbc7Sjsg 3821f005ef32Sjsg const struct amdgpu_ip_block_version psp_v11_0_ip_block = { 3822c349dbc7Sjsg .type = AMD_IP_BLOCK_TYPE_PSP, 3823c349dbc7Sjsg .major = 11, 3824c349dbc7Sjsg .minor = 0, 3825c349dbc7Sjsg .rev = 0, 3826c349dbc7Sjsg .funcs = &psp_ip_funcs, 3827c349dbc7Sjsg }; 3828c349dbc7Sjsg 38295ca02815Sjsg const struct amdgpu_ip_block_version psp_v11_0_8_ip_block = { 38305ca02815Sjsg .type = AMD_IP_BLOCK_TYPE_PSP, 38315ca02815Sjsg .major = 11, 38325ca02815Sjsg .minor = 0, 38335ca02815Sjsg .rev = 8, 38345ca02815Sjsg .funcs = &psp_ip_funcs, 38355ca02815Sjsg }; 38365ca02815Sjsg 3837f005ef32Sjsg const struct amdgpu_ip_block_version psp_v12_0_ip_block = { 3838c349dbc7Sjsg .type = AMD_IP_BLOCK_TYPE_PSP, 3839c349dbc7Sjsg .major = 12, 3840c349dbc7Sjsg .minor = 0, 3841c349dbc7Sjsg .rev = 0, 3842c349dbc7Sjsg .funcs = &psp_ip_funcs, 3843c349dbc7Sjsg }; 38445ca02815Sjsg 38455ca02815Sjsg const struct amdgpu_ip_block_version psp_v13_0_ip_block = { 38465ca02815Sjsg .type = AMD_IP_BLOCK_TYPE_PSP, 38475ca02815Sjsg .major = 13, 38485ca02815Sjsg .minor = 0, 38495ca02815Sjsg .rev = 0, 38505ca02815Sjsg .funcs = &psp_ip_funcs, 38515ca02815Sjsg }; 38521bb76ff1Sjsg 38531bb76ff1Sjsg const struct amdgpu_ip_block_version psp_v13_0_4_ip_block = { 38541bb76ff1Sjsg .type = AMD_IP_BLOCK_TYPE_PSP, 38551bb76ff1Sjsg .major = 13, 38561bb76ff1Sjsg .minor = 0, 38571bb76ff1Sjsg .rev = 4, 38581bb76ff1Sjsg .funcs = &psp_ip_funcs, 38591bb76ff1Sjsg }; 3860