10e5ca0d1SHuang Rui /* 20e5ca0d1SHuang Rui * Copyright 2016 Advanced Micro Devices, Inc. 30e5ca0d1SHuang Rui * 40e5ca0d1SHuang Rui * Permission is hereby granted, free of charge, to any person obtaining a 50e5ca0d1SHuang Rui * copy of this software and associated documentation files (the "Software"), 60e5ca0d1SHuang Rui * to deal in the Software without restriction, including without limitation 70e5ca0d1SHuang Rui * the rights to use, copy, modify, merge, publish, distribute, sublicense, 80e5ca0d1SHuang Rui * and/or sell copies of the Software, and to permit persons to whom the 90e5ca0d1SHuang Rui * Software is furnished to do so, subject to the following conditions: 100e5ca0d1SHuang Rui * 110e5ca0d1SHuang Rui * The above copyright notice and this permission notice shall be included in 120e5ca0d1SHuang Rui * all copies or substantial portions of the Software. 130e5ca0d1SHuang Rui * 140e5ca0d1SHuang Rui * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 150e5ca0d1SHuang Rui * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 160e5ca0d1SHuang Rui * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 170e5ca0d1SHuang Rui * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 180e5ca0d1SHuang Rui * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 190e5ca0d1SHuang Rui * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 200e5ca0d1SHuang Rui * OTHER DEALINGS IN THE SOFTWARE. 210e5ca0d1SHuang Rui * 220e5ca0d1SHuang Rui * Author: Huang Rui 230e5ca0d1SHuang Rui * 240e5ca0d1SHuang Rui */ 250e5ca0d1SHuang Rui 260e5ca0d1SHuang Rui #include <linux/firmware.h> 27f89f8c6bSAndrey Grodzovsky #include <drm/drm_drv.h> 28fdf2f6c5SSam Ravnborg 290e5ca0d1SHuang Rui #include "amdgpu.h" 300e5ca0d1SHuang Rui #include "amdgpu_psp.h" 310e5ca0d1SHuang Rui #include "amdgpu_ucode.h" 320e5ca0d1SHuang Rui #include "soc15_common.h" 330e5ca0d1SHuang Rui #include "psp_v3_1.h" 34c1798b54SHuang Rui #include "psp_v10_0.h" 35654f761cSFeifei Xu #include "psp_v11_0.h" 363188fd07SLang Yu #include "psp_v11_0_8.h" 376a7a0bdbSAaron Liu #include "psp_v12_0.h" 38ee821083SHawking Zhang #include "psp_v13_0.h" 390e5ca0d1SHuang Rui 40bff77e86SLe Ma #include "amdgpu_ras.h" 41ecaafb7bSJinzhou Su #include "amdgpu_securedisplay.h" 42c6a11133SHawking Zhang #include "amdgpu_atomfirmware.h" 43bff77e86SLe Ma 4457430471SAndrey Grodzovsky static int psp_sysfs_init(struct amdgpu_device *adev); 4557430471SAndrey Grodzovsky static void psp_sysfs_fini(struct amdgpu_device *adev); 4657430471SAndrey Grodzovsky 4740e611bdSJohn Clements static int psp_load_smu_fw(struct psp_context *psp); 4840e611bdSJohn Clements 49995da6ccSEvan Quan /* 50995da6ccSEvan Quan * Due to DF Cstate management centralized to PMFW, the firmware 51995da6ccSEvan Quan * loading sequence will be updated as below: 52995da6ccSEvan Quan * - Load KDB 53995da6ccSEvan Quan * - Load SYS_DRV 54995da6ccSEvan Quan * - Load tOS 55995da6ccSEvan Quan * - Load PMFW 56995da6ccSEvan Quan * - Setup TMR 57995da6ccSEvan Quan * - Load other non-psp fw 58995da6ccSEvan Quan * - Load ASD 59995da6ccSEvan Quan * - Load XGMI/RAS/HDCP/DTM TA if any 60995da6ccSEvan Quan * 61995da6ccSEvan Quan * This new sequence is required for 62b335f289SHawking Zhang * - Arcturus and onwards 63995da6ccSEvan Quan * - Navi12 and onwards 64995da6ccSEvan Quan */ 65995da6ccSEvan Quan static void psp_check_pmfw_centralized_cstate_management(struct psp_context *psp) 66995da6ccSEvan Quan { 67995da6ccSEvan Quan struct amdgpu_device *adev = psp->adev; 68995da6ccSEvan Quan 69995da6ccSEvan Quan psp->pmfw_centralized_cstate_management = false; 70995da6ccSEvan Quan 71995da6ccSEvan Quan if (amdgpu_sriov_vf(adev)) 72995da6ccSEvan Quan return; 73995da6ccSEvan Quan 74995da6ccSEvan Quan if (adev->flags & AMD_IS_APU) 75995da6ccSEvan Quan return; 76995da6ccSEvan Quan 77b335f289SHawking Zhang if ((adev->asic_type >= CHIP_ARCTURUS) || 78995da6ccSEvan Quan (adev->asic_type >= CHIP_NAVI12)) 79995da6ccSEvan Quan psp->pmfw_centralized_cstate_management = true; 80995da6ccSEvan Quan } 81995da6ccSEvan Quan 820e5ca0d1SHuang Rui static int psp_early_init(void *handle) 830e5ca0d1SHuang Rui { 840e5ca0d1SHuang Rui struct amdgpu_device *adev = (struct amdgpu_device *)handle; 859d6fea57SAlex Deucher struct psp_context *psp = &adev->psp; 860e5ca0d1SHuang Rui 870e5ca0d1SHuang Rui switch (adev->asic_type) { 880e5ca0d1SHuang Rui case CHIP_VEGA10: 89ff13dc67SAlex Deucher case CHIP_VEGA12: 90e7f9ccb4SAlex Deucher psp_v3_1_set_psp_funcs(psp); 911d1f41cfSHawking Zhang psp->autoload_supported = false; 920e5ca0d1SHuang Rui break; 93c1798b54SHuang Rui case CHIP_RAVEN: 94e7f9ccb4SAlex Deucher psp_v10_0_set_psp_funcs(psp); 951d1f41cfSHawking Zhang psp->autoload_supported = false; 96c1798b54SHuang Rui break; 97654f761cSFeifei Xu case CHIP_VEGA20: 98f36d9ab9SJohn Clements case CHIP_ARCTURUS: 991d1f41cfSHawking Zhang psp_v11_0_set_psp_funcs(psp); 1001d1f41cfSHawking Zhang psp->autoload_supported = false; 1011d1f41cfSHawking Zhang break; 102bc290fe5STao Zhou case CHIP_NAVI10: 10382522b2dSXiaojie Yuan case CHIP_NAVI14: 104739cdbd6SXiaojie Yuan case CHIP_NAVI12: 105344fed0bSLikun Gao case CHIP_SIENNA_CICHLID: 106c82b38ecSJiansong Chen case CHIP_NAVY_FLOUNDER: 107ed3b7353SHuang Rui case CHIP_VANGOGH: 108462c272bSTao Zhou case CHIP_DIMGREY_CAVEFISH: 109c0729819SChengming Gui case CHIP_BEIGE_GOBY: 110654f761cSFeifei Xu psp_v11_0_set_psp_funcs(psp); 1111d1f41cfSHawking Zhang psp->autoload_supported = true; 112654f761cSFeifei Xu break; 1136a7a0bdbSAaron Liu case CHIP_RENOIR: 1146a7a0bdbSAaron Liu psp_v12_0_set_psp_funcs(psp); 1156a7a0bdbSAaron Liu break; 116ee821083SHawking Zhang case CHIP_ALDEBARAN: 117ee821083SHawking Zhang psp_v13_0_set_psp_funcs(psp); 118ee821083SHawking Zhang break; 119903bb18bSAaron Liu case CHIP_YELLOW_CARP: 120903bb18bSAaron Liu psp_v13_0_set_psp_funcs(psp); 121903bb18bSAaron Liu psp->autoload_supported = true; 122903bb18bSAaron Liu break; 1233188fd07SLang Yu case CHIP_CYAN_SKILLFISH: 1243188fd07SLang Yu if (adev->apu_flags & AMD_APU_IS_CYAN_SKILLFISH2) { 1253188fd07SLang Yu psp_v11_0_8_set_psp_funcs(psp); 1263188fd07SLang Yu psp->autoload_supported = false; 1273188fd07SLang Yu } 1283188fd07SLang Yu break; 1290e5ca0d1SHuang Rui default: 1300e5ca0d1SHuang Rui return -EINVAL; 1310e5ca0d1SHuang Rui } 1320e5ca0d1SHuang Rui 1330e5ca0d1SHuang Rui psp->adev = adev; 1340e5ca0d1SHuang Rui 135995da6ccSEvan Quan psp_check_pmfw_centralized_cstate_management(psp); 136995da6ccSEvan Quan 1379d6fea57SAlex Deucher return 0; 1389d6fea57SAlex Deucher } 1399d6fea57SAlex Deucher 140963cee55SLikun Gao static void psp_memory_training_fini(struct psp_context *psp) 141963cee55SLikun Gao { 142963cee55SLikun Gao struct psp_memory_training_context *ctx = &psp->mem_train_ctx; 143963cee55SLikun Gao 144963cee55SLikun Gao ctx->init = PSP_MEM_TRAIN_NOT_SUPPORT; 145963cee55SLikun Gao kfree(ctx->sys_cache); 146963cee55SLikun Gao ctx->sys_cache = NULL; 147963cee55SLikun Gao } 148963cee55SLikun Gao 149963cee55SLikun Gao static int psp_memory_training_init(struct psp_context *psp) 150963cee55SLikun Gao { 151963cee55SLikun Gao int ret; 152963cee55SLikun Gao struct psp_memory_training_context *ctx = &psp->mem_train_ctx; 153963cee55SLikun Gao 154963cee55SLikun Gao if (ctx->init != PSP_MEM_TRAIN_RESERVE_SUCCESS) { 155963cee55SLikun Gao DRM_DEBUG("memory training is not supported!\n"); 156963cee55SLikun Gao return 0; 157963cee55SLikun Gao } 158963cee55SLikun Gao 159963cee55SLikun Gao ctx->sys_cache = kzalloc(ctx->train_data_size, GFP_KERNEL); 160963cee55SLikun Gao if (ctx->sys_cache == NULL) { 161963cee55SLikun Gao DRM_ERROR("alloc mem_train_ctx.sys_cache failed!\n"); 162963cee55SLikun Gao ret = -ENOMEM; 163963cee55SLikun Gao goto Err_out; 164963cee55SLikun Gao } 165963cee55SLikun Gao 166963cee55SLikun Gao DRM_DEBUG("train_data_size:%llx,p2c_train_data_offset:%llx,c2p_train_data_offset:%llx.\n", 167963cee55SLikun Gao ctx->train_data_size, 168963cee55SLikun Gao ctx->p2c_train_data_offset, 169963cee55SLikun Gao ctx->c2p_train_data_offset); 170963cee55SLikun Gao ctx->init = PSP_MEM_TRAIN_INIT_SUCCESS; 171963cee55SLikun Gao return 0; 172963cee55SLikun Gao 173963cee55SLikun Gao Err_out: 174963cee55SLikun Gao psp_memory_training_fini(psp); 175963cee55SLikun Gao return ret; 176963cee55SLikun Gao } 177963cee55SLikun Gao 1783d689ae4SHawking Zhang /* 1793d689ae4SHawking Zhang * Helper funciton to query psp runtime database entry 1803d689ae4SHawking Zhang * 1813d689ae4SHawking Zhang * @adev: amdgpu_device pointer 1823d689ae4SHawking Zhang * @entry_type: the type of psp runtime database entry 1833d689ae4SHawking Zhang * @db_entry: runtime database entry pointer 1843d689ae4SHawking Zhang * 1853d689ae4SHawking Zhang * Return false if runtime database doesn't exit or entry is invalid 1863d689ae4SHawking Zhang * or true if the specific database entry is found, and copy to @db_entry 1873d689ae4SHawking Zhang */ 1883d689ae4SHawking Zhang static bool psp_get_runtime_db_entry(struct amdgpu_device *adev, 1893d689ae4SHawking Zhang enum psp_runtime_entry_type entry_type, 1903d689ae4SHawking Zhang void *db_entry) 1913d689ae4SHawking Zhang { 1923d689ae4SHawking Zhang uint64_t db_header_pos, db_dir_pos; 1933d689ae4SHawking Zhang struct psp_runtime_data_header db_header = {0}; 1943d689ae4SHawking Zhang struct psp_runtime_data_directory db_dir = {0}; 1953d689ae4SHawking Zhang bool ret = false; 1963d689ae4SHawking Zhang int i; 1973d689ae4SHawking Zhang 1983d689ae4SHawking Zhang db_header_pos = adev->gmc.mc_vram_size - PSP_RUNTIME_DB_OFFSET; 1993d689ae4SHawking Zhang db_dir_pos = db_header_pos + sizeof(struct psp_runtime_data_header); 2003d689ae4SHawking Zhang 2013d689ae4SHawking Zhang /* read runtime db header from vram */ 2023d689ae4SHawking Zhang amdgpu_device_vram_access(adev, db_header_pos, (uint32_t *)&db_header, 2033d689ae4SHawking Zhang sizeof(struct psp_runtime_data_header), false); 2043d689ae4SHawking Zhang 2053d689ae4SHawking Zhang if (db_header.cookie != PSP_RUNTIME_DB_COOKIE_ID) { 2063d689ae4SHawking Zhang /* runtime db doesn't exist, exit */ 2073d689ae4SHawking Zhang dev_warn(adev->dev, "PSP runtime database doesn't exist\n"); 2083d689ae4SHawking Zhang return false; 2093d689ae4SHawking Zhang } 2103d689ae4SHawking Zhang 2113d689ae4SHawking Zhang /* read runtime database entry from vram */ 2123d689ae4SHawking Zhang amdgpu_device_vram_access(adev, db_dir_pos, (uint32_t *)&db_dir, 2133d689ae4SHawking Zhang sizeof(struct psp_runtime_data_directory), false); 2143d689ae4SHawking Zhang 2153d689ae4SHawking Zhang if (db_dir.entry_count >= PSP_RUNTIME_DB_DIAG_ENTRY_MAX_COUNT) { 2163d689ae4SHawking Zhang /* invalid db entry count, exit */ 2173d689ae4SHawking Zhang dev_warn(adev->dev, "Invalid PSP runtime database entry count\n"); 2183d689ae4SHawking Zhang return false; 2193d689ae4SHawking Zhang } 2203d689ae4SHawking Zhang 2213d689ae4SHawking Zhang /* look up for requested entry type */ 2223d689ae4SHawking Zhang for (i = 0; i < db_dir.entry_count && !ret; i++) { 2233d689ae4SHawking Zhang if (db_dir.entry_list[i].entry_type == entry_type) { 2243d689ae4SHawking Zhang switch (entry_type) { 2253d689ae4SHawking Zhang case PSP_RUNTIME_ENTRY_TYPE_BOOT_CONFIG: 2263d689ae4SHawking Zhang if (db_dir.entry_list[i].size < sizeof(struct psp_runtime_boot_cfg_entry)) { 2273d689ae4SHawking Zhang /* invalid db entry size */ 2283d689ae4SHawking Zhang dev_warn(adev->dev, "Invalid PSP runtime database entry size\n"); 2293d689ae4SHawking Zhang return false; 2303d689ae4SHawking Zhang } 2313d689ae4SHawking Zhang /* read runtime database entry */ 2323d689ae4SHawking Zhang amdgpu_device_vram_access(adev, db_header_pos + db_dir.entry_list[i].offset, 2333d689ae4SHawking Zhang (uint32_t *)db_entry, sizeof(struct psp_runtime_boot_cfg_entry), false); 2343d689ae4SHawking Zhang ret = true; 2353d689ae4SHawking Zhang break; 2363d689ae4SHawking Zhang default: 2373d689ae4SHawking Zhang ret = false; 2383d689ae4SHawking Zhang break; 2393d689ae4SHawking Zhang } 2403d689ae4SHawking Zhang } 2413d689ae4SHawking Zhang } 2423d689ae4SHawking Zhang 2433d689ae4SHawking Zhang return ret; 2443d689ae4SHawking Zhang } 2453d689ae4SHawking Zhang 2469d6fea57SAlex Deucher static int psp_sw_init(void *handle) 2479d6fea57SAlex Deucher { 2489d6fea57SAlex Deucher struct amdgpu_device *adev = (struct amdgpu_device *)handle; 2499d6fea57SAlex Deucher struct psp_context *psp = &adev->psp; 2509d6fea57SAlex Deucher int ret; 2518e6e054dSHawking Zhang struct psp_runtime_boot_cfg_entry boot_cfg_entry; 2523a07101bSHawking Zhang struct psp_memory_training_context *mem_training_ctx = &psp->mem_train_ctx; 2539d6fea57SAlex Deucher 254*4fb93071SCandice Li psp->cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); 255*4fb93071SCandice Li if (!psp->cmd) { 256*4fb93071SCandice Li DRM_ERROR("Failed to allocate memory to command buffer!\n"); 257*4fb93071SCandice Li ret = -ENOMEM; 258*4fb93071SCandice Li } 259*4fb93071SCandice Li 260162b786fSJingwen Chen if (!amdgpu_sriov_vf(adev)) { 2610e5ca0d1SHuang Rui ret = psp_init_microcode(psp); 2620e5ca0d1SHuang Rui if (ret) { 2630e5ca0d1SHuang Rui DRM_ERROR("Failed to load psp firmware!\n"); 2640e5ca0d1SHuang Rui return ret; 2650e5ca0d1SHuang Rui } 26693cdc175SZhigang Luo } else if (amdgpu_sriov_vf(adev) && adev->asic_type == CHIP_ALDEBARAN) { 26793cdc175SZhigang Luo ret = psp_init_ta_microcode(psp, "aldebaran"); 26893cdc175SZhigang Luo if (ret) { 26993cdc175SZhigang Luo DRM_ERROR("Failed to initialize ta microcode!\n"); 27093cdc175SZhigang Luo return ret; 27193cdc175SZhigang Luo } 272162b786fSJingwen Chen } 2730e5ca0d1SHuang Rui 2748e6e054dSHawking Zhang memset(&boot_cfg_entry, 0, sizeof(boot_cfg_entry)); 2758e6e054dSHawking Zhang if (psp_get_runtime_db_entry(adev, 2768e6e054dSHawking Zhang PSP_RUNTIME_ENTRY_TYPE_BOOT_CONFIG, 2773a07101bSHawking Zhang &boot_cfg_entry)) { 2788e6e054dSHawking Zhang psp->boot_cfg_bitmask = boot_cfg_entry.boot_cfg_bitmask; 2793a07101bSHawking Zhang if ((psp->boot_cfg_bitmask) & 2803a07101bSHawking Zhang BOOT_CFG_FEATURE_TWO_STAGE_DRAM_TRAINING) { 2813a07101bSHawking Zhang /* If psp runtime database exists, then 2823a07101bSHawking Zhang * only enable two stage memory training 2833a07101bSHawking Zhang * when TWO_STAGE_DRAM_TRAINING bit is set 2843a07101bSHawking Zhang * in runtime database */ 2853a07101bSHawking Zhang mem_training_ctx->enable_mem_training = true; 2863a07101bSHawking Zhang } 2878e6e054dSHawking Zhang 2883a07101bSHawking Zhang } else { 2893a07101bSHawking Zhang /* If psp runtime database doesn't exist or 2903a07101bSHawking Zhang * is invalid, force enable two stage memory 2913a07101bSHawking Zhang * training */ 2923a07101bSHawking Zhang mem_training_ctx->enable_mem_training = true; 2933a07101bSHawking Zhang } 2943a07101bSHawking Zhang 2953a07101bSHawking Zhang if (mem_training_ctx->enable_mem_training) { 296963cee55SLikun Gao ret = psp_memory_training_init(psp); 2970586a059STianci.Yin if (ret) { 298d5e5c1bcSColin Ian King DRM_ERROR("Failed to initialize memory training!\n"); 2990586a059STianci.Yin return ret; 3000586a059STianci.Yin } 3013a07101bSHawking Zhang 3020586a059STianci.Yin ret = psp_mem_training(psp, PSP_MEM_TRAIN_COLD_BOOT); 3030586a059STianci.Yin if (ret) { 3040586a059STianci.Yin DRM_ERROR("Failed to process memory training!\n"); 3050586a059STianci.Yin return ret; 3060586a059STianci.Yin } 3073a07101bSHawking Zhang } 3080586a059STianci.Yin 309ce87c98dSAndrey Grodzovsky if (adev->asic_type == CHIP_NAVI10 || adev->asic_type == CHIP_SIENNA_CICHLID) { 31090f88cddSAndrey Grodzovsky ret= psp_sysfs_init(adev); 31190f88cddSAndrey Grodzovsky if (ret) { 31290f88cddSAndrey Grodzovsky return ret; 31390f88cddSAndrey Grodzovsky } 31490f88cddSAndrey Grodzovsky } 31590f88cddSAndrey Grodzovsky 3160e5ca0d1SHuang Rui return 0; 3170e5ca0d1SHuang Rui } 3180e5ca0d1SHuang Rui 3190e5ca0d1SHuang Rui static int psp_sw_fini(void *handle) 3200e5ca0d1SHuang Rui { 321c833d8aaSMonk Liu struct amdgpu_device *adev = (struct amdgpu_device *)handle; 322*4fb93071SCandice Li struct psp_context *psp = &adev->psp; 323*4fb93071SCandice Li struct psp_gfx_cmd_resp *cmd = psp->cmd; 324c833d8aaSMonk Liu 325*4fb93071SCandice Li psp_memory_training_fini(psp); 326*4fb93071SCandice Li if (psp->sos_fw) { 327*4fb93071SCandice Li release_firmware(psp->sos_fw); 328*4fb93071SCandice Li psp->sos_fw = NULL; 329f61772cdSLiu ChengZhe } 330*4fb93071SCandice Li if (psp->asd_fw) { 331*4fb93071SCandice Li release_firmware(psp->asd_fw); 332*4fb93071SCandice Li psp->asd_fw = NULL; 333f61772cdSLiu ChengZhe } 334*4fb93071SCandice Li if (psp->ta_fw) { 335*4fb93071SCandice Li release_firmware(psp->ta_fw); 336*4fb93071SCandice Li psp->ta_fw = NULL; 337f61772cdSLiu ChengZhe } 33857430471SAndrey Grodzovsky 33923d9bd60SAndrey Grodzovsky if (adev->asic_type == CHIP_NAVI10 || 34023d9bd60SAndrey Grodzovsky adev->asic_type == CHIP_SIENNA_CICHLID) 34157430471SAndrey Grodzovsky psp_sysfs_fini(adev); 34257430471SAndrey Grodzovsky 343*4fb93071SCandice Li kfree(cmd); 344*4fb93071SCandice Li cmd = NULL; 345*4fb93071SCandice Li 3460e5ca0d1SHuang Rui return 0; 3470e5ca0d1SHuang Rui } 3480e5ca0d1SHuang Rui 3490e5ca0d1SHuang Rui int psp_wait_for(struct psp_context *psp, uint32_t reg_index, 3500e5ca0d1SHuang Rui uint32_t reg_val, uint32_t mask, bool check_changed) 3510e5ca0d1SHuang Rui { 3520e5ca0d1SHuang Rui uint32_t val; 3530e5ca0d1SHuang Rui int i; 3540e5ca0d1SHuang Rui struct amdgpu_device *adev = psp->adev; 3550e5ca0d1SHuang Rui 3567afefb81SAndrey Grodzovsky if (psp->adev->no_hw_access) 357bf36b52eSAndrey Grodzovsky return 0; 358bf36b52eSAndrey Grodzovsky 3590e5ca0d1SHuang Rui for (i = 0; i < adev->usec_timeout; i++) { 3602890decfSZhang, Jerry val = RREG32(reg_index); 3610e5ca0d1SHuang Rui if (check_changed) { 3620e5ca0d1SHuang Rui if (val != reg_val) 3630e5ca0d1SHuang Rui return 0; 3640e5ca0d1SHuang Rui } else { 3650e5ca0d1SHuang Rui if ((val & mask) == reg_val) 3660e5ca0d1SHuang Rui return 0; 3670e5ca0d1SHuang Rui } 3680e5ca0d1SHuang Rui udelay(1); 3690e5ca0d1SHuang Rui } 3700e5ca0d1SHuang Rui 3710e5ca0d1SHuang Rui return -ETIME; 3720e5ca0d1SHuang Rui } 3730e5ca0d1SHuang Rui 374dc739d18SLang Yu static const char *psp_gfx_cmd_name(enum psp_gfx_cmd_id cmd_id) 375dc739d18SLang Yu { 376dc739d18SLang Yu switch (cmd_id) { 377dc739d18SLang Yu case GFX_CMD_ID_LOAD_TA: 378dc739d18SLang Yu return "LOAD_TA"; 379dc739d18SLang Yu case GFX_CMD_ID_UNLOAD_TA: 380dc739d18SLang Yu return "UNLOAD_TA"; 381dc739d18SLang Yu case GFX_CMD_ID_INVOKE_CMD: 382dc739d18SLang Yu return "INVOKE_CMD"; 383dc739d18SLang Yu case GFX_CMD_ID_LOAD_ASD: 384dc739d18SLang Yu return "LOAD_ASD"; 385dc739d18SLang Yu case GFX_CMD_ID_SETUP_TMR: 386dc739d18SLang Yu return "SETUP_TMR"; 387dc739d18SLang Yu case GFX_CMD_ID_LOAD_IP_FW: 388dc739d18SLang Yu return "LOAD_IP_FW"; 389dc739d18SLang Yu case GFX_CMD_ID_DESTROY_TMR: 390dc739d18SLang Yu return "DESTROY_TMR"; 391dc739d18SLang Yu case GFX_CMD_ID_SAVE_RESTORE: 392dc739d18SLang Yu return "SAVE_RESTORE_IP_FW"; 393dc739d18SLang Yu case GFX_CMD_ID_SETUP_VMR: 394dc739d18SLang Yu return "SETUP_VMR"; 395dc739d18SLang Yu case GFX_CMD_ID_DESTROY_VMR: 396dc739d18SLang Yu return "DESTROY_VMR"; 397dc739d18SLang Yu case GFX_CMD_ID_PROG_REG: 398dc739d18SLang Yu return "PROG_REG"; 399dc739d18SLang Yu case GFX_CMD_ID_GET_FW_ATTESTATION: 400dc739d18SLang Yu return "GET_FW_ATTESTATION"; 401dc739d18SLang Yu case GFX_CMD_ID_LOAD_TOC: 402dc739d18SLang Yu return "ID_LOAD_TOC"; 403dc739d18SLang Yu case GFX_CMD_ID_AUTOLOAD_RLC: 404dc739d18SLang Yu return "AUTOLOAD_RLC"; 405dc739d18SLang Yu case GFX_CMD_ID_BOOT_CFG: 406dc739d18SLang Yu return "BOOT_CFG"; 407dc739d18SLang Yu default: 408dc739d18SLang Yu return "UNKNOWN CMD"; 409dc739d18SLang Yu } 410dc739d18SLang Yu } 411dc739d18SLang Yu 4120e5ca0d1SHuang Rui static int 4130e5ca0d1SHuang Rui psp_cmd_submit_buf(struct psp_context *psp, 4140e5ca0d1SHuang Rui struct amdgpu_firmware_info *ucode, 4150b25cbf9SHawking Zhang struct psp_gfx_cmd_resp *cmd, uint64_t fence_mc_addr) 4160e5ca0d1SHuang Rui { 4170e5ca0d1SHuang Rui int ret; 418f89f8c6bSAndrey Grodzovsky int index, idx; 41957995aa8Spengzhou int timeout = 20000; 420c2c6f816SJohn Clements bool ras_intr = false; 421d73cd701SEmily Deng bool skip_unsupport = false; 4220e5ca0d1SHuang Rui 4237afefb81SAndrey Grodzovsky if (psp->adev->no_hw_access) 424bf36b52eSAndrey Grodzovsky return 0; 425bf36b52eSAndrey Grodzovsky 426f89f8c6bSAndrey Grodzovsky if (!drm_dev_enter(&psp->adev->ddev, &idx)) 427f89f8c6bSAndrey Grodzovsky return 0; 428f89f8c6bSAndrey Grodzovsky 42932eaeae0SAlex Deucher mutex_lock(&psp->mutex); 43032eaeae0SAlex Deucher 431a1952da7SHuang Rui memset(psp->cmd_buf_mem, 0, PSP_CMD_BUFFER_SIZE); 4320e5ca0d1SHuang Rui 433a1952da7SHuang Rui memcpy(psp->cmd_buf_mem, cmd, sizeof(struct psp_gfx_cmd_resp)); 4340e5ca0d1SHuang Rui 4350b25cbf9SHawking Zhang index = atomic_inc_return(&psp->fence_value); 4365bdd0b72SHawking Zhang ret = psp_ring_cmd_submit(psp, psp->cmd_buf_mc_addr, fence_mc_addr, index); 4370b25cbf9SHawking Zhang if (ret) { 4380b25cbf9SHawking Zhang atomic_dec(&psp->fence_value); 439f89f8c6bSAndrey Grodzovsky goto exit; 440ca7f65c7Skbuild test robot } 4410e5ca0d1SHuang Rui 442810085ddSEric Huang amdgpu_device_invalidate_hdp(psp->adev, NULL); 443ea114213Sxinhui pan while (*((unsigned int *)psp->fence_buf) != index) { 444ea114213Sxinhui pan if (--timeout == 0) 4457a3d7bf6SEvan Quan break; 446bff77e86SLe Ma /* 447bff77e86SLe Ma * Shouldn't wait for timeout when err_event_athub occurs, 448bff77e86SLe Ma * because gpu reset thread triggered and lock resource should 449bff77e86SLe Ma * be released for psp resume sequence. 450bff77e86SLe Ma */ 451c2c6f816SJohn Clements ras_intr = amdgpu_ras_intr_triggered(); 452c2c6f816SJohn Clements if (ras_intr) 453bff77e86SLe Ma break; 45457995aa8Spengzhou usleep_range(10, 100); 455810085ddSEric Huang amdgpu_device_invalidate_hdp(psp->adev, NULL); 456ea114213Sxinhui pan } 4570b25cbf9SHawking Zhang 4583bda8acdSEmily Deng /* We allow TEE_ERROR_NOT_SUPPORTED for VMR command and PSP_ERR_UNKNOWN_COMMAND in SRIOV */ 4593bda8acdSEmily Deng skip_unsupport = (psp->cmd_buf_mem->resp.status == TEE_ERROR_NOT_SUPPORTED || 4603bda8acdSEmily Deng psp->cmd_buf_mem->resp.status == PSP_ERR_UNKNOWN_COMMAND) && amdgpu_sriov_vf(psp->adev); 461d73cd701SEmily Deng 46219ae3330SJohn Clements memcpy((void*)&cmd->resp, (void*)&psp->cmd_buf_mem->resp, sizeof(struct psp_gfx_resp)); 46319ae3330SJohn Clements 464466bcb75SAaron Liu /* In some cases, psp response status is not 0 even there is no 465466bcb75SAaron Liu * problem while the command is submitted. Some version of PSP FW 466466bcb75SAaron Liu * doesn't write 0 to that field. 467466bcb75SAaron Liu * So here we would like to only print a warning instead of an error 468466bcb75SAaron Liu * during psp initialization to avoid breaking hw_init and it doesn't 469466bcb75SAaron Liu * return -EINVAL. 470466bcb75SAaron Liu */ 471d73cd701SEmily Deng if (!skip_unsupport && (psp->cmd_buf_mem->resp.status || !timeout) && !ras_intr) { 47276223c54SXiangliang Yu if (ucode) 47363123332SLang Yu DRM_WARN("failed to load ucode (%s) ", 47463123332SLang Yu amdgpu_ucode_name(ucode->ucode_id)); 47563123332SLang Yu DRM_WARN("psp gfx command (%s) failed and response status is (0x%X)\n", 47663123332SLang Yu psp_gfx_cmd_name(psp->cmd_buf_mem->cmd_id), 477e6e193c0SJohn Clements psp->cmd_buf_mem->resp.status); 478728b3d05SZhigang Luo if (!timeout) { 479f89f8c6bSAndrey Grodzovsky ret = -EINVAL; 480f89f8c6bSAndrey Grodzovsky goto exit; 48128a16027SHuang Rui } 48232eaeae0SAlex Deucher } 48328a16027SHuang Rui 484435198f3SJames Zhu if (ucode) { 485435198f3SJames Zhu ucode->tmr_mc_addr_lo = psp->cmd_buf_mem->resp.fw_addr_lo; 486435198f3SJames Zhu ucode->tmr_mc_addr_hi = psp->cmd_buf_mem->resp.fw_addr_hi; 487435198f3SJames Zhu } 488435198f3SJames Zhu 489f89f8c6bSAndrey Grodzovsky exit: 490f89f8c6bSAndrey Grodzovsky mutex_unlock(&psp->mutex); 491f89f8c6bSAndrey Grodzovsky drm_dev_exit(idx); 4920e5ca0d1SHuang Rui return ret; 4930e5ca0d1SHuang Rui } 4940e5ca0d1SHuang Rui 4955ec996dfSXiangliang Yu static void psp_prep_tmr_cmd_buf(struct psp_context *psp, 4965ec996dfSXiangliang Yu struct psp_gfx_cmd_resp *cmd, 49736c08237SOak Zeng uint64_t tmr_mc, struct amdgpu_bo *tmr_bo) 4980e5ca0d1SHuang Rui { 49936c08237SOak Zeng struct amdgpu_device *adev = psp->adev; 50036c08237SOak Zeng uint32_t size = amdgpu_bo_size(tmr_bo); 50136c08237SOak Zeng uint64_t tmr_pa = amdgpu_gmc_vram_pa(adev, tmr_bo); 50236c08237SOak Zeng 503*4fb93071SCandice Li memset(cmd, 0, sizeof(struct psp_gfx_cmd_resp)); 504*4fb93071SCandice Li 505a2676149SHawking Zhang if (amdgpu_sriov_vf(psp->adev)) 5065ec996dfSXiangliang Yu cmd->cmd_id = GFX_CMD_ID_SETUP_VMR; 5075ec996dfSXiangliang Yu else 5080e5ca0d1SHuang Rui cmd->cmd_id = GFX_CMD_ID_SETUP_TMR; 509f03defe0SAlex Deucher cmd->cmd.cmd_setup_tmr.buf_phy_addr_lo = lower_32_bits(tmr_mc); 510f03defe0SAlex Deucher cmd->cmd.cmd_setup_tmr.buf_phy_addr_hi = upper_32_bits(tmr_mc); 5110e5ca0d1SHuang Rui cmd->cmd.cmd_setup_tmr.buf_size = size; 51236c08237SOak Zeng cmd->cmd.cmd_setup_tmr.bitfield.virt_phy_addr = 1; 51336c08237SOak Zeng cmd->cmd.cmd_setup_tmr.system_phy_addr_lo = lower_32_bits(tmr_pa); 51436c08237SOak Zeng cmd->cmd.cmd_setup_tmr.system_phy_addr_hi = upper_32_bits(tmr_pa); 5150e5ca0d1SHuang Rui } 5160e5ca0d1SHuang Rui 5177ea49e76SHawking Zhang static void psp_prep_load_toc_cmd_buf(struct psp_gfx_cmd_resp *cmd, 5187ea49e76SHawking Zhang uint64_t pri_buf_mc, uint32_t size) 5197ea49e76SHawking Zhang { 520*4fb93071SCandice Li memset(cmd, 0, sizeof(struct psp_gfx_cmd_resp)); 521*4fb93071SCandice Li 5227ea49e76SHawking Zhang cmd->cmd_id = GFX_CMD_ID_LOAD_TOC; 5237ea49e76SHawking Zhang cmd->cmd.cmd_load_toc.toc_phy_addr_lo = lower_32_bits(pri_buf_mc); 5247ea49e76SHawking Zhang cmd->cmd.cmd_load_toc.toc_phy_addr_hi = upper_32_bits(pri_buf_mc); 5257ea49e76SHawking Zhang cmd->cmd.cmd_load_toc.toc_size = size; 5267ea49e76SHawking Zhang } 5277ea49e76SHawking Zhang 5287ea49e76SHawking Zhang /* Issue LOAD TOC cmd to PSP to part toc and calculate tmr size needed */ 5297ea49e76SHawking Zhang static int psp_load_toc(struct psp_context *psp, 5307ea49e76SHawking Zhang uint32_t *tmr_size) 5317ea49e76SHawking Zhang { 5327ea49e76SHawking Zhang int ret; 533*4fb93071SCandice Li struct psp_gfx_cmd_resp *cmd = psp->cmd; 5347ea49e76SHawking Zhang 5357ea49e76SHawking Zhang /* Copy toc to psp firmware private buffer */ 536222e0a71SCandice Li psp_copy_fw(psp, psp->toc.start_addr, psp->toc.size_bytes); 5377ea49e76SHawking Zhang 538222e0a71SCandice Li psp_prep_load_toc_cmd_buf(cmd, psp->fw_pri_mc_addr, psp->toc.size_bytes); 5397ea49e76SHawking Zhang 5407ea49e76SHawking Zhang ret = psp_cmd_submit_buf(psp, NULL, cmd, 5417ea49e76SHawking Zhang psp->fence_buf_mc_addr); 5427ea49e76SHawking Zhang if (!ret) 5437ea49e76SHawking Zhang *tmr_size = psp->cmd_buf_mem->resp.tmr_size; 544*4fb93071SCandice Li 5457ea49e76SHawking Zhang return ret; 5467ea49e76SHawking Zhang } 5477ea49e76SHawking Zhang 5480e5ca0d1SHuang Rui /* Set up Trusted Memory Region */ 5490e5ca0d1SHuang Rui static int psp_tmr_init(struct psp_context *psp) 5500e5ca0d1SHuang Rui { 5510e5ca0d1SHuang Rui int ret; 5527ea49e76SHawking Zhang int tmr_size; 55312842d02STianci.Yin void *tmr_buf; 55412842d02STianci.Yin void **pptr; 5550e5ca0d1SHuang Rui 5560e5ca0d1SHuang Rui /* 557795c1b8dSshaoyunl * According to HW engineer, they prefer the TMR address be "naturally 558795c1b8dSshaoyunl * aligned" , e.g. the start address be an integer divide of TMR size. 5590e5ca0d1SHuang Rui * 5600e5ca0d1SHuang Rui * Note: this memory need be reserved till the driver 5610e5ca0d1SHuang Rui * uninitializes. 5620e5ca0d1SHuang Rui */ 56347bfa5f6SOak Zeng tmr_size = PSP_TMR_SIZE(psp->adev); 5647ea49e76SHawking Zhang 5657ea49e76SHawking Zhang /* For ASICs support RLC autoload, psp will parse the toc 5667ea49e76SHawking Zhang * and calculate the total size of TMR needed */ 5671b657824SJiange Zhao if (!amdgpu_sriov_vf(psp->adev) && 568222e0a71SCandice Li psp->toc.start_addr && 569222e0a71SCandice Li psp->toc.size_bytes && 5707ea49e76SHawking Zhang psp->fw_pri_buf) { 5717ea49e76SHawking Zhang ret = psp_load_toc(psp, &tmr_size); 5727ea49e76SHawking Zhang if (ret) { 5737ea49e76SHawking Zhang DRM_ERROR("Failed to load toc\n"); 5747ea49e76SHawking Zhang return ret; 5757ea49e76SHawking Zhang } 5767ea49e76SHawking Zhang } 5777ea49e76SHawking Zhang 57812842d02STianci.Yin pptr = amdgpu_sriov_vf(psp->adev) ? &tmr_buf : NULL; 57947bfa5f6SOak Zeng ret = amdgpu_bo_create_kernel(psp->adev, tmr_size, PSP_TMR_SIZE(psp->adev), 5800e5ca0d1SHuang Rui AMDGPU_GEM_DOMAIN_VRAM, 58112842d02STianci.Yin &psp->tmr_bo, &psp->tmr_mc_addr, pptr); 5826f2b1fccSHuang Rui 5836f2b1fccSHuang Rui return ret; 5846f2b1fccSHuang Rui } 5856f2b1fccSHuang Rui 586f61772cdSLiu ChengZhe static bool psp_skip_tmr(struct psp_context *psp) 587f61772cdSLiu ChengZhe { 588f61772cdSLiu ChengZhe switch (psp->adev->asic_type) { 589f61772cdSLiu ChengZhe case CHIP_NAVI12: 590f61772cdSLiu ChengZhe case CHIP_SIENNA_CICHLID: 591e7de0d84SZhigang Luo case CHIP_ALDEBARAN: 592f61772cdSLiu ChengZhe return true; 593f61772cdSLiu ChengZhe default: 594f61772cdSLiu ChengZhe return false; 595f61772cdSLiu ChengZhe } 596f61772cdSLiu ChengZhe } 597f61772cdSLiu ChengZhe 5986f2b1fccSHuang Rui static int psp_tmr_load(struct psp_context *psp) 5996f2b1fccSHuang Rui { 6006f2b1fccSHuang Rui int ret; 601*4fb93071SCandice Li struct psp_gfx_cmd_resp *cmd = psp->cmd; 6026f2b1fccSHuang Rui 603f61772cdSLiu ChengZhe /* For Navi12 and CHIP_SIENNA_CICHLID SRIOV, do not set up TMR. 604f61772cdSLiu ChengZhe * Already set up by host driver. 605f61772cdSLiu ChengZhe */ 606f61772cdSLiu ChengZhe if (amdgpu_sriov_vf(psp->adev) && psp_skip_tmr(psp)) 607f61772cdSLiu ChengZhe return 0; 608f61772cdSLiu ChengZhe 60936c08237SOak Zeng psp_prep_tmr_cmd_buf(psp, cmd, psp->tmr_mc_addr, psp->tmr_bo); 6107ea49e76SHawking Zhang DRM_INFO("reserve 0x%lx from 0x%llx for PSP TMR\n", 6117ea49e76SHawking Zhang amdgpu_bo_size(psp->tmr_bo), psp->tmr_mc_addr); 6120e5ca0d1SHuang Rui 6130e5ca0d1SHuang Rui ret = psp_cmd_submit_buf(psp, NULL, cmd, 6140b25cbf9SHawking Zhang psp->fence_buf_mc_addr); 6150e5ca0d1SHuang Rui 6160e5ca0d1SHuang Rui return ret; 6170e5ca0d1SHuang Rui } 6180e5ca0d1SHuang Rui 61990937420SHuang Rui static void psp_prep_tmr_unload_cmd_buf(struct psp_context *psp, 62090937420SHuang Rui struct psp_gfx_cmd_resp *cmd) 62190937420SHuang Rui { 622*4fb93071SCandice Li memset(cmd, 0, sizeof(struct psp_gfx_cmd_resp)); 623*4fb93071SCandice Li 62490937420SHuang Rui if (amdgpu_sriov_vf(psp->adev)) 62590937420SHuang Rui cmd->cmd_id = GFX_CMD_ID_DESTROY_VMR; 62690937420SHuang Rui else 62790937420SHuang Rui cmd->cmd_id = GFX_CMD_ID_DESTROY_TMR; 62890937420SHuang Rui } 62990937420SHuang Rui 63090937420SHuang Rui static int psp_tmr_unload(struct psp_context *psp) 63190937420SHuang Rui { 63290937420SHuang Rui int ret; 633*4fb93071SCandice Li struct psp_gfx_cmd_resp *cmd = psp->cmd; 63490937420SHuang Rui 63590937420SHuang Rui psp_prep_tmr_unload_cmd_buf(psp, cmd); 63690937420SHuang Rui DRM_INFO("free PSP TMR buffer\n"); 63790937420SHuang Rui 63890937420SHuang Rui ret = psp_cmd_submit_buf(psp, NULL, cmd, 63990937420SHuang Rui psp->fence_buf_mc_addr); 64090937420SHuang Rui 64190937420SHuang Rui return ret; 64290937420SHuang Rui } 64390937420SHuang Rui 64490937420SHuang Rui static int psp_tmr_terminate(struct psp_context *psp) 64590937420SHuang Rui { 64690937420SHuang Rui int ret; 64790937420SHuang Rui void *tmr_buf; 64890937420SHuang Rui void **pptr; 64990937420SHuang Rui 65090937420SHuang Rui ret = psp_tmr_unload(psp); 65190937420SHuang Rui if (ret) 65290937420SHuang Rui return ret; 65390937420SHuang Rui 65490937420SHuang Rui /* free TMR memory buffer */ 65590937420SHuang Rui pptr = amdgpu_sriov_vf(psp->adev) ? &tmr_buf : NULL; 65690937420SHuang Rui amdgpu_bo_free_kernel(&psp->tmr_bo, &psp->tmr_mc_addr, pptr); 65790937420SHuang Rui 65890937420SHuang Rui return 0; 65990937420SHuang Rui } 66090937420SHuang Rui 66119ae3330SJohn Clements int psp_get_fw_attestation_records_addr(struct psp_context *psp, 66219ae3330SJohn Clements uint64_t *output_ptr) 66319ae3330SJohn Clements { 66419ae3330SJohn Clements int ret; 665*4fb93071SCandice Li struct psp_gfx_cmd_resp *cmd = psp->cmd; 666*4fb93071SCandice Li 667*4fb93071SCandice Li memset(cmd, 0, sizeof(struct psp_gfx_cmd_resp)); 66819ae3330SJohn Clements 66919ae3330SJohn Clements if (!output_ptr) 67019ae3330SJohn Clements return -EINVAL; 67119ae3330SJohn Clements 67219ae3330SJohn Clements if (amdgpu_sriov_vf(psp->adev)) 67319ae3330SJohn Clements return 0; 67419ae3330SJohn Clements 67519ae3330SJohn Clements cmd->cmd_id = GFX_CMD_ID_GET_FW_ATTESTATION; 67619ae3330SJohn Clements 67719ae3330SJohn Clements ret = psp_cmd_submit_buf(psp, NULL, cmd, 67819ae3330SJohn Clements psp->fence_buf_mc_addr); 67919ae3330SJohn Clements 68019ae3330SJohn Clements if (!ret) { 68119ae3330SJohn Clements *output_ptr = ((uint64_t)cmd->resp.uresp.fwar_db_info.fwar_db_addr_lo) + 68219ae3330SJohn Clements ((uint64_t)cmd->resp.uresp.fwar_db_info.fwar_db_addr_hi << 32); 68319ae3330SJohn Clements } 68419ae3330SJohn Clements 68519ae3330SJohn Clements return ret; 68619ae3330SJohn Clements } 68719ae3330SJohn Clements 688c6642234SHawking Zhang static int psp_boot_config_get(struct amdgpu_device *adev, uint32_t *boot_cfg) 689c6642234SHawking Zhang { 690c6642234SHawking Zhang struct psp_context *psp = &adev->psp; 691c6642234SHawking Zhang struct psp_gfx_cmd_resp *cmd = psp->cmd; 692c6642234SHawking Zhang int ret; 693c6642234SHawking Zhang 694c6642234SHawking Zhang if (amdgpu_sriov_vf(adev)) 695c6642234SHawking Zhang return 0; 696c6642234SHawking Zhang 697c6642234SHawking Zhang memset(cmd, 0, sizeof(struct psp_gfx_cmd_resp)); 698c6642234SHawking Zhang 699c6642234SHawking Zhang cmd->cmd_id = GFX_CMD_ID_BOOT_CFG; 700c6642234SHawking Zhang cmd->cmd.boot_cfg.sub_cmd = BOOTCFG_CMD_GET; 701c6642234SHawking Zhang 702c6642234SHawking Zhang ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); 703c6642234SHawking Zhang if (!ret) { 704c6642234SHawking Zhang *boot_cfg = 705c6642234SHawking Zhang (cmd->resp.uresp.boot_cfg.boot_cfg & BOOT_CONFIG_GECC) ? 1 : 0; 706c6642234SHawking Zhang } 707c6642234SHawking Zhang 708c6642234SHawking Zhang return ret; 709c6642234SHawking Zhang } 710c6642234SHawking Zhang 71155188d64SHawking Zhang static int psp_boot_config_set(struct amdgpu_device *adev, uint32_t boot_cfg) 712cad7b751SJohn Clements { 713cad7b751SJohn Clements struct psp_context *psp = &adev->psp; 714cad7b751SJohn Clements struct psp_gfx_cmd_resp *cmd = psp->cmd; 715cad7b751SJohn Clements 716c6a11133SHawking Zhang if (amdgpu_sriov_vf(adev)) 717cad7b751SJohn Clements return 0; 718cad7b751SJohn Clements 719cad7b751SJohn Clements memset(cmd, 0, sizeof(struct psp_gfx_cmd_resp)); 720cad7b751SJohn Clements 721cad7b751SJohn Clements cmd->cmd_id = GFX_CMD_ID_BOOT_CFG; 722cad7b751SJohn Clements cmd->cmd.boot_cfg.sub_cmd = BOOTCFG_CMD_SET; 72355188d64SHawking Zhang cmd->cmd.boot_cfg.boot_config = boot_cfg; 72455188d64SHawking Zhang cmd->cmd.boot_cfg.boot_config_valid = boot_cfg; 725cad7b751SJohn Clements 726cad7b751SJohn Clements return psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); 727cad7b751SJohn Clements } 728cad7b751SJohn Clements 7290d2c1855SJohn Clements static int psp_rl_load(struct amdgpu_device *adev) 7300d2c1855SJohn Clements { 7310d2c1855SJohn Clements struct psp_context *psp = &adev->psp; 7320d2c1855SJohn Clements struct psp_gfx_cmd_resp *cmd = psp->cmd; 7330d2c1855SJohn Clements 734*4fb93071SCandice Li memset(cmd, 0, sizeof(struct psp_gfx_cmd_resp)); 735*4fb93071SCandice Li 736222e0a71SCandice Li if (!is_psp_fw_valid(psp->rl)) 7370d2c1855SJohn Clements return 0; 7380d2c1855SJohn Clements 7390d2c1855SJohn Clements memset(psp->fw_pri_buf, 0, PSP_1_MEG); 740222e0a71SCandice Li memcpy(psp->fw_pri_buf, psp->rl.start_addr, psp->rl.size_bytes); 7410d2c1855SJohn Clements 7420d2c1855SJohn Clements cmd->cmd_id = GFX_CMD_ID_LOAD_IP_FW; 7430d2c1855SJohn Clements cmd->cmd.cmd_load_ip_fw.fw_phy_addr_lo = lower_32_bits(psp->fw_pri_mc_addr); 7440d2c1855SJohn Clements cmd->cmd.cmd_load_ip_fw.fw_phy_addr_hi = upper_32_bits(psp->fw_pri_mc_addr); 745222e0a71SCandice Li cmd->cmd.cmd_load_ip_fw.fw_size = psp->rl.size_bytes; 7460d2c1855SJohn Clements cmd->cmd.cmd_load_ip_fw.fw_type = GFX_FW_TYPE_REG_LIST; 7470d2c1855SJohn Clements 7480d2c1855SJohn Clements return psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); 7490d2c1855SJohn Clements } 7500d2c1855SJohn Clements 751c64ab828SHawking Zhang static void psp_prep_asd_load_cmd_buf(struct psp_gfx_cmd_resp *cmd, 752c64ab828SHawking Zhang uint64_t asd_mc, uint32_t size) 7530e5ca0d1SHuang Rui { 754*4fb93071SCandice Li memset(cmd, 0, sizeof(struct psp_gfx_cmd_resp)); 755*4fb93071SCandice Li 7560e5ca0d1SHuang Rui cmd->cmd_id = GFX_CMD_ID_LOAD_ASD; 7570e5ca0d1SHuang Rui cmd->cmd.cmd_load_ta.app_phy_addr_lo = lower_32_bits(asd_mc); 7580e5ca0d1SHuang Rui cmd->cmd.cmd_load_ta.app_phy_addr_hi = upper_32_bits(asd_mc); 7590e5ca0d1SHuang Rui cmd->cmd.cmd_load_ta.app_len = size; 7600e5ca0d1SHuang Rui 761c64ab828SHawking Zhang cmd->cmd.cmd_load_ta.cmd_buf_phy_addr_lo = 0; 762c64ab828SHawking Zhang cmd->cmd.cmd_load_ta.cmd_buf_phy_addr_hi = 0; 763c64ab828SHawking Zhang cmd->cmd.cmd_load_ta.cmd_buf_len = 0; 7640e5ca0d1SHuang Rui } 7650e5ca0d1SHuang Rui 7660e5ca0d1SHuang Rui static int psp_asd_load(struct psp_context *psp) 7670e5ca0d1SHuang Rui { 7680e5ca0d1SHuang Rui int ret; 769*4fb93071SCandice Li struct psp_gfx_cmd_resp *cmd = psp->cmd; 7700e5ca0d1SHuang Rui 771943cafb8SXiangliang Yu /* If PSP version doesn't match ASD version, asd loading will be failed. 772943cafb8SXiangliang Yu * add workaround to bypass it for sriov now. 773943cafb8SXiangliang Yu * TODO: add version check to make it common 774943cafb8SXiangliang Yu */ 775eb5f4f46SDennis Li if (amdgpu_sriov_vf(psp->adev) || !psp->asd_ucode_size) 776943cafb8SXiangliang Yu return 0; 777943cafb8SXiangliang Yu 778f89f8c6bSAndrey Grodzovsky psp_copy_fw(psp, psp->asd_start_addr, psp->asd_ucode_size); 7790e5ca0d1SHuang Rui 780c64ab828SHawking Zhang psp_prep_asd_load_cmd_buf(cmd, psp->fw_pri_mc_addr, 781c64ab828SHawking Zhang psp->asd_ucode_size); 7820e5ca0d1SHuang Rui 7830e5ca0d1SHuang Rui ret = psp_cmd_submit_buf(psp, NULL, cmd, 7840b25cbf9SHawking Zhang psp->fence_buf_mc_addr); 785c64ab828SHawking Zhang if (!ret) { 786c64ab828SHawking Zhang psp->asd_context.asd_initialized = true; 787c64ab828SHawking Zhang psp->asd_context.session_id = cmd->resp.session_id; 788c64ab828SHawking Zhang } 7890e5ca0d1SHuang Rui 7900e5ca0d1SHuang Rui return ret; 7910e5ca0d1SHuang Rui } 7920e5ca0d1SHuang Rui 7931f455f25SJohn Clements static void psp_prep_ta_unload_cmd_buf(struct psp_gfx_cmd_resp *cmd, 7941f455f25SJohn Clements uint32_t session_id) 79571e5f0cbSHawking Zhang { 796*4fb93071SCandice Li memset(cmd, 0, sizeof(struct psp_gfx_cmd_resp)); 797*4fb93071SCandice Li 79871e5f0cbSHawking Zhang cmd->cmd_id = GFX_CMD_ID_UNLOAD_TA; 7991f455f25SJohn Clements cmd->cmd.cmd_unload_ta.session_id = session_id; 80071e5f0cbSHawking Zhang } 80171e5f0cbSHawking Zhang 80271e5f0cbSHawking Zhang static int psp_asd_unload(struct psp_context *psp) 80371e5f0cbSHawking Zhang { 80471e5f0cbSHawking Zhang int ret; 805*4fb93071SCandice Li struct psp_gfx_cmd_resp *cmd = psp->cmd; 80671e5f0cbSHawking Zhang 80771e5f0cbSHawking Zhang if (amdgpu_sriov_vf(psp->adev)) 80871e5f0cbSHawking Zhang return 0; 80971e5f0cbSHawking Zhang 81071e5f0cbSHawking Zhang if (!psp->asd_context.asd_initialized) 81171e5f0cbSHawking Zhang return 0; 81271e5f0cbSHawking Zhang 8131f455f25SJohn Clements psp_prep_ta_unload_cmd_buf(cmd, psp->asd_context.session_id); 81471e5f0cbSHawking Zhang 81571e5f0cbSHawking Zhang ret = psp_cmd_submit_buf(psp, NULL, cmd, 81671e5f0cbSHawking Zhang psp->fence_buf_mc_addr); 81771e5f0cbSHawking Zhang if (!ret) 81871e5f0cbSHawking Zhang psp->asd_context.asd_initialized = false; 81971e5f0cbSHawking Zhang 82071e5f0cbSHawking Zhang return ret; 82171e5f0cbSHawking Zhang } 82271e5f0cbSHawking Zhang 823c5d19419STrigger Huang static void psp_prep_reg_prog_cmd_buf(struct psp_gfx_cmd_resp *cmd, 824c5d19419STrigger Huang uint32_t id, uint32_t value) 825c5d19419STrigger Huang { 826*4fb93071SCandice Li memset(cmd, 0, sizeof(struct psp_gfx_cmd_resp)); 827*4fb93071SCandice Li 828c5d19419STrigger Huang cmd->cmd_id = GFX_CMD_ID_PROG_REG; 829c5d19419STrigger Huang cmd->cmd.cmd_setup_reg_prog.reg_value = value; 830c5d19419STrigger Huang cmd->cmd.cmd_setup_reg_prog.reg_id = id; 831c5d19419STrigger Huang } 832c5d19419STrigger Huang 833c5d19419STrigger Huang int psp_reg_program(struct psp_context *psp, enum psp_reg_prog_id reg, 834c5d19419STrigger Huang uint32_t value) 835c5d19419STrigger Huang { 836*4fb93071SCandice Li struct psp_gfx_cmd_resp *cmd = psp->cmd; 837c5d19419STrigger Huang int ret = 0; 838c5d19419STrigger Huang 839c5d19419STrigger Huang if (reg >= PSP_REG_LAST) 840c5d19419STrigger Huang return -EINVAL; 841c5d19419STrigger Huang 842c5d19419STrigger Huang psp_prep_reg_prog_cmd_buf(cmd, reg, value); 843c5d19419STrigger Huang ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); 8442b9ced5aSRohit Khaire if (ret) 8452b9ced5aSRohit Khaire DRM_ERROR("PSP failed to program reg id %d", reg); 846c5d19419STrigger Huang 847c5d19419STrigger Huang return ret; 848c5d19419STrigger Huang } 849c5d19419STrigger Huang 8501f455f25SJohn Clements static void psp_prep_ta_load_cmd_buf(struct psp_gfx_cmd_resp *cmd, 8511f455f25SJohn Clements uint64_t ta_bin_mc, 8521f455f25SJohn Clements uint32_t ta_bin_size, 8531f455f25SJohn Clements uint64_t ta_shared_mc, 8541f455f25SJohn Clements uint32_t ta_shared_size) 85597c8d171SHawking Zhang { 856*4fb93071SCandice Li memset(cmd, 0, sizeof(struct psp_gfx_cmd_resp)); 857*4fb93071SCandice Li 85897c8d171SHawking Zhang cmd->cmd_id = GFX_CMD_ID_LOAD_TA; 8591f455f25SJohn Clements cmd->cmd.cmd_load_ta.app_phy_addr_lo = lower_32_bits(ta_bin_mc); 8601f455f25SJohn Clements cmd->cmd.cmd_load_ta.app_phy_addr_hi = upper_32_bits(ta_bin_mc); 8611f455f25SJohn Clements cmd->cmd.cmd_load_ta.app_len = ta_bin_size; 86297c8d171SHawking Zhang 8631f455f25SJohn Clements cmd->cmd.cmd_load_ta.cmd_buf_phy_addr_lo = lower_32_bits(ta_shared_mc); 8641f455f25SJohn Clements cmd->cmd.cmd_load_ta.cmd_buf_phy_addr_hi = upper_32_bits(ta_shared_mc); 8651f455f25SJohn Clements cmd->cmd.cmd_load_ta.cmd_buf_len = ta_shared_size; 86697c8d171SHawking Zhang } 86797c8d171SHawking Zhang 86897c8d171SHawking Zhang static int psp_xgmi_init_shared_buf(struct psp_context *psp) 86997c8d171SHawking Zhang { 87097c8d171SHawking Zhang int ret; 87197c8d171SHawking Zhang 87297c8d171SHawking Zhang /* 87397c8d171SHawking Zhang * Allocate 16k memory aligned to 4k from Frame Buffer (local 87497c8d171SHawking Zhang * physical) for xgmi ta <-> Driver 87597c8d171SHawking Zhang */ 87697c8d171SHawking Zhang ret = amdgpu_bo_create_kernel(psp->adev, PSP_XGMI_SHARED_MEM_SIZE, 87797c8d171SHawking Zhang PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM, 87897c8d171SHawking Zhang &psp->xgmi_context.xgmi_shared_bo, 87997c8d171SHawking Zhang &psp->xgmi_context.xgmi_shared_mc_addr, 88097c8d171SHawking Zhang &psp->xgmi_context.xgmi_shared_buf); 88197c8d171SHawking Zhang 88297c8d171SHawking Zhang return ret; 88397c8d171SHawking Zhang } 88497c8d171SHawking Zhang 88534e48caeSJohn Clements static void psp_prep_ta_invoke_cmd_buf(struct psp_gfx_cmd_resp *cmd, 88634e48caeSJohn Clements uint32_t ta_cmd_id, 88734e48caeSJohn Clements uint32_t session_id) 88834e48caeSJohn Clements { 889*4fb93071SCandice Li memset(cmd, 0, sizeof(struct psp_gfx_cmd_resp)); 890*4fb93071SCandice Li 89134e48caeSJohn Clements cmd->cmd_id = GFX_CMD_ID_INVOKE_CMD; 89234e48caeSJohn Clements cmd->cmd.cmd_invoke_cmd.session_id = session_id; 89334e48caeSJohn Clements cmd->cmd.cmd_invoke_cmd.ta_cmd_id = ta_cmd_id; 89434e48caeSJohn Clements } 89534e48caeSJohn Clements 896f3167919SNirmoy Das static int psp_ta_invoke(struct psp_context *psp, 89734e48caeSJohn Clements uint32_t ta_cmd_id, 89834e48caeSJohn Clements uint32_t session_id) 89934e48caeSJohn Clements { 90034e48caeSJohn Clements int ret; 901*4fb93071SCandice Li struct psp_gfx_cmd_resp *cmd = psp->cmd; 90234e48caeSJohn Clements 90334e48caeSJohn Clements psp_prep_ta_invoke_cmd_buf(cmd, ta_cmd_id, session_id); 90434e48caeSJohn Clements 90534e48caeSJohn Clements ret = psp_cmd_submit_buf(psp, NULL, cmd, 90634e48caeSJohn Clements psp->fence_buf_mc_addr); 90734e48caeSJohn Clements 90834e48caeSJohn Clements return ret; 90934e48caeSJohn Clements } 91034e48caeSJohn Clements 91197c8d171SHawking Zhang static int psp_xgmi_load(struct psp_context *psp) 91297c8d171SHawking Zhang { 91397c8d171SHawking Zhang int ret; 914*4fb93071SCandice Li struct psp_gfx_cmd_resp *cmd = psp->cmd; 91597c8d171SHawking Zhang 91697c8d171SHawking Zhang /* 91797c8d171SHawking Zhang * TODO: bypass the loading in sriov for now 91897c8d171SHawking Zhang */ 91997c8d171SHawking Zhang 920f89f8c6bSAndrey Grodzovsky psp_copy_fw(psp, psp->ta_xgmi_start_addr, psp->ta_xgmi_ucode_size); 92197c8d171SHawking Zhang 9221f455f25SJohn Clements psp_prep_ta_load_cmd_buf(cmd, 9231f455f25SJohn Clements psp->fw_pri_mc_addr, 9241f455f25SJohn Clements psp->ta_xgmi_ucode_size, 92597c8d171SHawking Zhang psp->xgmi_context.xgmi_shared_mc_addr, 9261f455f25SJohn Clements PSP_XGMI_SHARED_MEM_SIZE); 92797c8d171SHawking Zhang 92897c8d171SHawking Zhang ret = psp_cmd_submit_buf(psp, NULL, cmd, 92997c8d171SHawking Zhang psp->fence_buf_mc_addr); 93097c8d171SHawking Zhang 93197c8d171SHawking Zhang if (!ret) { 93297c8d171SHawking Zhang psp->xgmi_context.initialized = 1; 93397c8d171SHawking Zhang psp->xgmi_context.session_id = cmd->resp.session_id; 93497c8d171SHawking Zhang } 93597c8d171SHawking Zhang 93697c8d171SHawking Zhang return ret; 93797c8d171SHawking Zhang } 93897c8d171SHawking Zhang 93997c8d171SHawking Zhang static int psp_xgmi_unload(struct psp_context *psp) 94097c8d171SHawking Zhang { 94197c8d171SHawking Zhang int ret; 942*4fb93071SCandice Li struct psp_gfx_cmd_resp *cmd = psp->cmd; 9439c8c81feSJohn Clements struct amdgpu_device *adev = psp->adev; 9449c8c81feSJohn Clements 94599d1da67SFeifei Xu /* XGMI TA unload currently is not supported on Arcturus/Aldebaran A+A */ 94699d1da67SFeifei Xu if (adev->asic_type == CHIP_ARCTURUS || 94799d1da67SFeifei Xu (adev->asic_type == CHIP_ALDEBARAN && adev->gmc.xgmi.connected_to_cpu)) 9489c8c81feSJohn Clements return 0; 94997c8d171SHawking Zhang 95097c8d171SHawking Zhang /* 95197c8d171SHawking Zhang * TODO: bypass the unloading in sriov for now 95297c8d171SHawking Zhang */ 95397c8d171SHawking Zhang 9541f455f25SJohn Clements psp_prep_ta_unload_cmd_buf(cmd, psp->xgmi_context.session_id); 95597c8d171SHawking Zhang 95697c8d171SHawking Zhang ret = psp_cmd_submit_buf(psp, NULL, cmd, 95797c8d171SHawking Zhang psp->fence_buf_mc_addr); 95897c8d171SHawking Zhang 95997c8d171SHawking Zhang return ret; 96097c8d171SHawking Zhang } 96197c8d171SHawking Zhang 962ca6e1e59SHawking Zhang int psp_xgmi_invoke(struct psp_context *psp, uint32_t ta_cmd_id) 963ca6e1e59SHawking Zhang { 96434e48caeSJohn Clements return psp_ta_invoke(psp, ta_cmd_id, psp->xgmi_context.session_id); 965ca6e1e59SHawking Zhang } 966ca6e1e59SHawking Zhang 9670b9d3760SHawking Zhang int psp_xgmi_terminate(struct psp_context *psp) 9683e2e2ab5SHawking Zhang { 9693e2e2ab5SHawking Zhang int ret; 9703e2e2ab5SHawking Zhang 9713e2e2ab5SHawking Zhang if (!psp->xgmi_context.initialized) 9723e2e2ab5SHawking Zhang return 0; 9733e2e2ab5SHawking Zhang 9743e2e2ab5SHawking Zhang ret = psp_xgmi_unload(psp); 9753e2e2ab5SHawking Zhang if (ret) 9763e2e2ab5SHawking Zhang return ret; 9773e2e2ab5SHawking Zhang 9783e2e2ab5SHawking Zhang psp->xgmi_context.initialized = 0; 9793e2e2ab5SHawking Zhang 9803e2e2ab5SHawking Zhang /* free xgmi shared memory */ 9813e2e2ab5SHawking Zhang amdgpu_bo_free_kernel(&psp->xgmi_context.xgmi_shared_bo, 9823e2e2ab5SHawking Zhang &psp->xgmi_context.xgmi_shared_mc_addr, 9833e2e2ab5SHawking Zhang &psp->xgmi_context.xgmi_shared_buf); 9843e2e2ab5SHawking Zhang 9853e2e2ab5SHawking Zhang return 0; 9863e2e2ab5SHawking Zhang } 9873e2e2ab5SHawking Zhang 9880b9d3760SHawking Zhang int psp_xgmi_initialize(struct psp_context *psp) 9893e2e2ab5SHawking Zhang { 9903e2e2ab5SHawking Zhang struct ta_xgmi_shared_memory *xgmi_cmd; 9913e2e2ab5SHawking Zhang int ret; 9923e2e2ab5SHawking Zhang 99351bd3638SHawking Zhang if (!psp->adev->psp.ta_fw || 99451bd3638SHawking Zhang !psp->adev->psp.ta_xgmi_ucode_size || 99551bd3638SHawking Zhang !psp->adev->psp.ta_xgmi_start_addr) 9961d69511eSAlex Deucher return -ENOENT; 9971d69511eSAlex Deucher 9983e2e2ab5SHawking Zhang if (!psp->xgmi_context.initialized) { 9993e2e2ab5SHawking Zhang ret = psp_xgmi_init_shared_buf(psp); 10003e2e2ab5SHawking Zhang if (ret) 10013e2e2ab5SHawking Zhang return ret; 10023e2e2ab5SHawking Zhang } 10033e2e2ab5SHawking Zhang 10043e2e2ab5SHawking Zhang /* Load XGMI TA */ 10053e2e2ab5SHawking Zhang ret = psp_xgmi_load(psp); 10063e2e2ab5SHawking Zhang if (ret) 10073e2e2ab5SHawking Zhang return ret; 10083e2e2ab5SHawking Zhang 10093e2e2ab5SHawking Zhang /* Initialize XGMI session */ 10103e2e2ab5SHawking Zhang xgmi_cmd = (struct ta_xgmi_shared_memory *)(psp->xgmi_context.xgmi_shared_buf); 10113e2e2ab5SHawking Zhang memset(xgmi_cmd, 0, sizeof(struct ta_xgmi_shared_memory)); 10123e2e2ab5SHawking Zhang xgmi_cmd->cmd_id = TA_COMMAND_XGMI__INITIALIZE; 10133e2e2ab5SHawking Zhang 10143e2e2ab5SHawking Zhang ret = psp_xgmi_invoke(psp, xgmi_cmd->cmd_id); 10153e2e2ab5SHawking Zhang 10163e2e2ab5SHawking Zhang return ret; 10173e2e2ab5SHawking Zhang } 10183e2e2ab5SHawking Zhang 101935ccba4eSHawking Zhang int psp_xgmi_get_hive_id(struct psp_context *psp, uint64_t *hive_id) 102035ccba4eSHawking Zhang { 102135ccba4eSHawking Zhang struct ta_xgmi_shared_memory *xgmi_cmd; 102235ccba4eSHawking Zhang int ret; 102335ccba4eSHawking Zhang 102435ccba4eSHawking Zhang xgmi_cmd = (struct ta_xgmi_shared_memory *)psp->xgmi_context.xgmi_shared_buf; 102535ccba4eSHawking Zhang memset(xgmi_cmd, 0, sizeof(struct ta_xgmi_shared_memory)); 102635ccba4eSHawking Zhang 102735ccba4eSHawking Zhang xgmi_cmd->cmd_id = TA_COMMAND_XGMI__GET_HIVE_ID; 102835ccba4eSHawking Zhang 102935ccba4eSHawking Zhang /* Invoke xgmi ta to get hive id */ 103035ccba4eSHawking Zhang ret = psp_xgmi_invoke(psp, xgmi_cmd->cmd_id); 103135ccba4eSHawking Zhang if (ret) 103235ccba4eSHawking Zhang return ret; 103335ccba4eSHawking Zhang 103435ccba4eSHawking Zhang *hive_id = xgmi_cmd->xgmi_out_message.get_hive_id.hive_id; 103535ccba4eSHawking Zhang 103635ccba4eSHawking Zhang return 0; 103735ccba4eSHawking Zhang } 103835ccba4eSHawking Zhang 103935ccba4eSHawking Zhang int psp_xgmi_get_node_id(struct psp_context *psp, uint64_t *node_id) 104035ccba4eSHawking Zhang { 104135ccba4eSHawking Zhang struct ta_xgmi_shared_memory *xgmi_cmd; 104235ccba4eSHawking Zhang int ret; 104335ccba4eSHawking Zhang 104435ccba4eSHawking Zhang xgmi_cmd = (struct ta_xgmi_shared_memory *)psp->xgmi_context.xgmi_shared_buf; 104535ccba4eSHawking Zhang memset(xgmi_cmd, 0, sizeof(struct ta_xgmi_shared_memory)); 104635ccba4eSHawking Zhang 104735ccba4eSHawking Zhang xgmi_cmd->cmd_id = TA_COMMAND_XGMI__GET_NODE_ID; 104835ccba4eSHawking Zhang 104935ccba4eSHawking Zhang /* Invoke xgmi ta to get the node id */ 105035ccba4eSHawking Zhang ret = psp_xgmi_invoke(psp, xgmi_cmd->cmd_id); 105135ccba4eSHawking Zhang if (ret) 105235ccba4eSHawking Zhang return ret; 105335ccba4eSHawking Zhang 105435ccba4eSHawking Zhang *node_id = xgmi_cmd->xgmi_out_message.get_node_id.node_id; 105535ccba4eSHawking Zhang 105635ccba4eSHawking Zhang return 0; 105735ccba4eSHawking Zhang } 105835ccba4eSHawking Zhang 1059331e7818SJonathan Kim static bool psp_xgmi_peer_link_info_supported(struct psp_context *psp) 1060331e7818SJonathan Kim { 1061331e7818SJonathan Kim return psp->adev->asic_type == CHIP_ALDEBARAN && 1062331e7818SJonathan Kim psp->ta_xgmi_ucode_version >= 0x2000000b; 1063331e7818SJonathan Kim } 1064331e7818SJonathan Kim 106535ccba4eSHawking Zhang int psp_xgmi_get_topology_info(struct psp_context *psp, 106635ccba4eSHawking Zhang int number_devices, 106735ccba4eSHawking Zhang struct psp_xgmi_topology_info *topology) 106835ccba4eSHawking Zhang { 106935ccba4eSHawking Zhang struct ta_xgmi_shared_memory *xgmi_cmd; 107035ccba4eSHawking Zhang struct ta_xgmi_cmd_get_topology_info_input *topology_info_input; 107135ccba4eSHawking Zhang struct ta_xgmi_cmd_get_topology_info_output *topology_info_output; 107235ccba4eSHawking Zhang int i; 107335ccba4eSHawking Zhang int ret; 107435ccba4eSHawking Zhang 107535ccba4eSHawking Zhang if (!topology || topology->num_nodes > TA_XGMI__MAX_CONNECTED_NODES) 107635ccba4eSHawking Zhang return -EINVAL; 107735ccba4eSHawking Zhang 107835ccba4eSHawking Zhang xgmi_cmd = (struct ta_xgmi_shared_memory *)psp->xgmi_context.xgmi_shared_buf; 107935ccba4eSHawking Zhang memset(xgmi_cmd, 0, sizeof(struct ta_xgmi_shared_memory)); 108035ccba4eSHawking Zhang 108135ccba4eSHawking Zhang /* Fill in the shared memory with topology information as input */ 108235ccba4eSHawking Zhang topology_info_input = &xgmi_cmd->xgmi_in_message.get_topology_info; 108335ccba4eSHawking Zhang xgmi_cmd->cmd_id = TA_COMMAND_XGMI__GET_GET_TOPOLOGY_INFO; 108435ccba4eSHawking Zhang topology_info_input->num_nodes = number_devices; 108535ccba4eSHawking Zhang 108635ccba4eSHawking Zhang for (i = 0; i < topology_info_input->num_nodes; i++) { 108735ccba4eSHawking Zhang topology_info_input->nodes[i].node_id = topology->nodes[i].node_id; 108835ccba4eSHawking Zhang topology_info_input->nodes[i].num_hops = topology->nodes[i].num_hops; 108935ccba4eSHawking Zhang topology_info_input->nodes[i].is_sharing_enabled = topology->nodes[i].is_sharing_enabled; 109035ccba4eSHawking Zhang topology_info_input->nodes[i].sdma_engine = topology->nodes[i].sdma_engine; 109135ccba4eSHawking Zhang } 109235ccba4eSHawking Zhang 109335ccba4eSHawking Zhang /* Invoke xgmi ta to get the topology information */ 109435ccba4eSHawking Zhang ret = psp_xgmi_invoke(psp, TA_COMMAND_XGMI__GET_GET_TOPOLOGY_INFO); 109535ccba4eSHawking Zhang if (ret) 109635ccba4eSHawking Zhang return ret; 109735ccba4eSHawking Zhang 109835ccba4eSHawking Zhang /* Read the output topology information from the shared memory */ 109935ccba4eSHawking Zhang topology_info_output = &xgmi_cmd->xgmi_out_message.get_topology_info; 110035ccba4eSHawking Zhang topology->num_nodes = xgmi_cmd->xgmi_out_message.get_topology_info.num_nodes; 110135ccba4eSHawking Zhang for (i = 0; i < topology->num_nodes; i++) { 110235ccba4eSHawking Zhang topology->nodes[i].node_id = topology_info_output->nodes[i].node_id; 110335ccba4eSHawking Zhang topology->nodes[i].num_hops = topology_info_output->nodes[i].num_hops; 110435ccba4eSHawking Zhang topology->nodes[i].is_sharing_enabled = topology_info_output->nodes[i].is_sharing_enabled; 110535ccba4eSHawking Zhang topology->nodes[i].sdma_engine = topology_info_output->nodes[i].sdma_engine; 110635ccba4eSHawking Zhang } 110735ccba4eSHawking Zhang 1108331e7818SJonathan Kim /* Invoke xgmi ta again to get the link information */ 1109331e7818SJonathan Kim if (psp_xgmi_peer_link_info_supported(psp)) { 1110331e7818SJonathan Kim struct ta_xgmi_cmd_get_peer_link_info_output *link_info_output; 1111331e7818SJonathan Kim 1112331e7818SJonathan Kim xgmi_cmd->cmd_id = TA_COMMAND_XGMI__GET_PEER_LINKS; 1113331e7818SJonathan Kim 1114331e7818SJonathan Kim ret = psp_xgmi_invoke(psp, TA_COMMAND_XGMI__GET_PEER_LINKS); 1115331e7818SJonathan Kim 1116331e7818SJonathan Kim if (ret) 1117331e7818SJonathan Kim return ret; 1118331e7818SJonathan Kim 1119331e7818SJonathan Kim link_info_output = &xgmi_cmd->xgmi_out_message.get_link_info; 1120331e7818SJonathan Kim for (i = 0; i < topology->num_nodes; i++) 1121331e7818SJonathan Kim topology->nodes[i].num_links = 1122331e7818SJonathan Kim link_info_output->nodes[i].num_links; 1123331e7818SJonathan Kim } 1124331e7818SJonathan Kim 112535ccba4eSHawking Zhang return 0; 112635ccba4eSHawking Zhang } 112735ccba4eSHawking Zhang 112835ccba4eSHawking Zhang int psp_xgmi_set_topology_info(struct psp_context *psp, 112935ccba4eSHawking Zhang int number_devices, 113035ccba4eSHawking Zhang struct psp_xgmi_topology_info *topology) 113135ccba4eSHawking Zhang { 113235ccba4eSHawking Zhang struct ta_xgmi_shared_memory *xgmi_cmd; 113335ccba4eSHawking Zhang struct ta_xgmi_cmd_get_topology_info_input *topology_info_input; 113435ccba4eSHawking Zhang int i; 113535ccba4eSHawking Zhang 113635ccba4eSHawking Zhang if (!topology || topology->num_nodes > TA_XGMI__MAX_CONNECTED_NODES) 113735ccba4eSHawking Zhang return -EINVAL; 113835ccba4eSHawking Zhang 113935ccba4eSHawking Zhang xgmi_cmd = (struct ta_xgmi_shared_memory *)psp->xgmi_context.xgmi_shared_buf; 114035ccba4eSHawking Zhang memset(xgmi_cmd, 0, sizeof(struct ta_xgmi_shared_memory)); 114135ccba4eSHawking Zhang 114235ccba4eSHawking Zhang topology_info_input = &xgmi_cmd->xgmi_in_message.get_topology_info; 114335ccba4eSHawking Zhang xgmi_cmd->cmd_id = TA_COMMAND_XGMI__SET_TOPOLOGY_INFO; 114435ccba4eSHawking Zhang topology_info_input->num_nodes = number_devices; 114535ccba4eSHawking Zhang 114635ccba4eSHawking Zhang for (i = 0; i < topology_info_input->num_nodes; i++) { 114735ccba4eSHawking Zhang topology_info_input->nodes[i].node_id = topology->nodes[i].node_id; 114835ccba4eSHawking Zhang topology_info_input->nodes[i].num_hops = topology->nodes[i].num_hops; 114935ccba4eSHawking Zhang topology_info_input->nodes[i].is_sharing_enabled = 1; 115035ccba4eSHawking Zhang topology_info_input->nodes[i].sdma_engine = topology->nodes[i].sdma_engine; 115135ccba4eSHawking Zhang } 115235ccba4eSHawking Zhang 115335ccba4eSHawking Zhang /* Invoke xgmi ta to set topology information */ 115435ccba4eSHawking Zhang return psp_xgmi_invoke(psp, TA_COMMAND_XGMI__SET_TOPOLOGY_INFO); 115535ccba4eSHawking Zhang } 115635ccba4eSHawking Zhang 11575e5d3154Sxinhui pan // ras begin 11585e5d3154Sxinhui pan static int psp_ras_init_shared_buf(struct psp_context *psp) 11595e5d3154Sxinhui pan { 11605e5d3154Sxinhui pan int ret; 11615e5d3154Sxinhui pan 11625e5d3154Sxinhui pan /* 11635e5d3154Sxinhui pan * Allocate 16k memory aligned to 4k from Frame Buffer (local 11645e5d3154Sxinhui pan * physical) for ras ta <-> Driver 11655e5d3154Sxinhui pan */ 11665e5d3154Sxinhui pan ret = amdgpu_bo_create_kernel(psp->adev, PSP_RAS_SHARED_MEM_SIZE, 11675e5d3154Sxinhui pan PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM, 11685e5d3154Sxinhui pan &psp->ras.ras_shared_bo, 11695e5d3154Sxinhui pan &psp->ras.ras_shared_mc_addr, 11705e5d3154Sxinhui pan &psp->ras.ras_shared_buf); 11715e5d3154Sxinhui pan 11725e5d3154Sxinhui pan return ret; 11735e5d3154Sxinhui pan } 11745e5d3154Sxinhui pan 11755e5d3154Sxinhui pan static int psp_ras_load(struct psp_context *psp) 11765e5d3154Sxinhui pan { 11775e5d3154Sxinhui pan int ret; 1178*4fb93071SCandice Li struct psp_gfx_cmd_resp *cmd = psp->cmd; 11799c7e2cebSJohn Clements struct ta_ras_shared_memory *ras_cmd; 11805e5d3154Sxinhui pan 11815e5d3154Sxinhui pan /* 11825e5d3154Sxinhui pan * TODO: bypass the loading in sriov for now 11835e5d3154Sxinhui pan */ 11845e5d3154Sxinhui pan if (amdgpu_sriov_vf(psp->adev)) 11855e5d3154Sxinhui pan return 0; 11865e5d3154Sxinhui pan 1187f89f8c6bSAndrey Grodzovsky psp_copy_fw(psp, psp->ta_ras_start_addr, psp->ta_ras_ucode_size); 11885e5d3154Sxinhui pan 11897e882aeeSJohn Clements ras_cmd = (struct ta_ras_shared_memory *)psp->ras.ras_shared_buf; 11907e882aeeSJohn Clements 11917e882aeeSJohn Clements if (psp->adev->gmc.xgmi.connected_to_cpu) 11927e882aeeSJohn Clements ras_cmd->ras_in_message.init_flags.poison_mode_en = 1; 11937e882aeeSJohn Clements else 11947e882aeeSJohn Clements ras_cmd->ras_in_message.init_flags.dgpu_mode = 1; 11957e882aeeSJohn Clements 11961f455f25SJohn Clements psp_prep_ta_load_cmd_buf(cmd, 11971f455f25SJohn Clements psp->fw_pri_mc_addr, 11981f455f25SJohn Clements psp->ta_ras_ucode_size, 11995e5d3154Sxinhui pan psp->ras.ras_shared_mc_addr, 12001f455f25SJohn Clements PSP_RAS_SHARED_MEM_SIZE); 12015e5d3154Sxinhui pan 12025e5d3154Sxinhui pan ret = psp_cmd_submit_buf(psp, NULL, cmd, 12035e5d3154Sxinhui pan psp->fence_buf_mc_addr); 12045e5d3154Sxinhui pan 12055e5d3154Sxinhui pan if (!ret) { 12065e5d3154Sxinhui pan psp->ras.session_id = cmd->resp.session_id; 12079c7e2cebSJohn Clements 12089c7e2cebSJohn Clements if (!ras_cmd->ras_status) 12099c7e2cebSJohn Clements psp->ras.ras_initialized = true; 12109c7e2cebSJohn Clements else 12119c7e2cebSJohn Clements dev_warn(psp->adev->dev, "RAS Init Status: 0x%X\n", ras_cmd->ras_status); 12125e5d3154Sxinhui pan } 12135e5d3154Sxinhui pan 12149c7e2cebSJohn Clements if (ret || ras_cmd->ras_status) 12159c7e2cebSJohn Clements amdgpu_ras_fini(psp->adev); 12169c7e2cebSJohn Clements 12175e5d3154Sxinhui pan return ret; 12185e5d3154Sxinhui pan } 12195e5d3154Sxinhui pan 12205e5d3154Sxinhui pan static int psp_ras_unload(struct psp_context *psp) 12215e5d3154Sxinhui pan { 12225e5d3154Sxinhui pan int ret; 1223*4fb93071SCandice Li struct psp_gfx_cmd_resp *cmd = psp->cmd; 12245e5d3154Sxinhui pan 12255e5d3154Sxinhui pan /* 12265e5d3154Sxinhui pan * TODO: bypass the unloading in sriov for now 12275e5d3154Sxinhui pan */ 12285e5d3154Sxinhui pan if (amdgpu_sriov_vf(psp->adev)) 12295e5d3154Sxinhui pan return 0; 12305e5d3154Sxinhui pan 12311f455f25SJohn Clements psp_prep_ta_unload_cmd_buf(cmd, psp->ras.session_id); 12325e5d3154Sxinhui pan 12335e5d3154Sxinhui pan ret = psp_cmd_submit_buf(psp, NULL, cmd, 12345e5d3154Sxinhui pan psp->fence_buf_mc_addr); 12355e5d3154Sxinhui pan 12365e5d3154Sxinhui pan return ret; 12375e5d3154Sxinhui pan } 12385e5d3154Sxinhui pan 12395e5d3154Sxinhui pan int psp_ras_invoke(struct psp_context *psp, uint32_t ta_cmd_id) 12405e5d3154Sxinhui pan { 124143965797SJohn Clements struct ta_ras_shared_memory *ras_cmd; 124243965797SJohn Clements int ret; 124343965797SJohn Clements 124443965797SJohn Clements ras_cmd = (struct ta_ras_shared_memory *)psp->ras.ras_shared_buf; 124543965797SJohn Clements 12465e5d3154Sxinhui pan /* 12475e5d3154Sxinhui pan * TODO: bypass the loading in sriov for now 12485e5d3154Sxinhui pan */ 12495e5d3154Sxinhui pan if (amdgpu_sriov_vf(psp->adev)) 12505e5d3154Sxinhui pan return 0; 12515e5d3154Sxinhui pan 125243965797SJohn Clements ret = psp_ta_invoke(psp, ta_cmd_id, psp->ras.session_id); 125343965797SJohn Clements 1254624e8c87SJohn Clements if (amdgpu_ras_intr_triggered()) 1255624e8c87SJohn Clements return ret; 1256624e8c87SJohn Clements 125743965797SJohn Clements if (ras_cmd->if_version > RAS_TA_HOST_IF_VER) 125843965797SJohn Clements { 125943965797SJohn Clements DRM_WARN("RAS: Unsupported Interface"); 126043965797SJohn Clements return -EINVAL; 126143965797SJohn Clements } 126243965797SJohn Clements 126343965797SJohn Clements if (!ret) { 126443965797SJohn Clements if (ras_cmd->ras_out_message.flags.err_inject_switch_disable_flag) { 126543965797SJohn Clements dev_warn(psp->adev->dev, "ECC switch disabled\n"); 126643965797SJohn Clements 126743965797SJohn Clements ras_cmd->ras_status = TA_RAS_STATUS__ERROR_RAS_NOT_AVAILABLE; 126843965797SJohn Clements } 126943965797SJohn Clements else if (ras_cmd->ras_out_message.flags.reg_access_failure_flag) 127043965797SJohn Clements dev_warn(psp->adev->dev, 127143965797SJohn Clements "RAS internal register access blocked\n"); 127243965797SJohn Clements } 127343965797SJohn Clements 127443965797SJohn Clements return ret; 12755e5d3154Sxinhui pan } 12765e5d3154Sxinhui pan 1277011907fdSDennis Li static int psp_ras_status_to_errno(struct amdgpu_device *adev, 1278011907fdSDennis Li enum ta_ras_status ras_status) 1279011907fdSDennis Li { 1280011907fdSDennis Li int ret = -EINVAL; 1281011907fdSDennis Li 1282011907fdSDennis Li switch (ras_status) { 1283011907fdSDennis Li case TA_RAS_STATUS__SUCCESS: 1284011907fdSDennis Li ret = 0; 1285011907fdSDennis Li break; 1286011907fdSDennis Li case TA_RAS_STATUS__RESET_NEEDED: 1287011907fdSDennis Li ret = -EAGAIN; 1288011907fdSDennis Li break; 1289011907fdSDennis Li case TA_RAS_STATUS__ERROR_RAS_NOT_AVAILABLE: 1290011907fdSDennis Li dev_warn(adev->dev, "RAS WARN: ras function unavailable\n"); 1291011907fdSDennis Li break; 1292011907fdSDennis Li case TA_RAS_STATUS__ERROR_ASD_READ_WRITE: 1293011907fdSDennis Li dev_warn(adev->dev, "RAS WARN: asd read or write failed\n"); 1294011907fdSDennis Li break; 1295011907fdSDennis Li default: 1296011907fdSDennis Li dev_err(adev->dev, "RAS ERROR: ras function failed ret 0x%X\n", ret); 1297011907fdSDennis Li } 1298011907fdSDennis Li 1299011907fdSDennis Li return ret; 1300011907fdSDennis Li } 1301011907fdSDennis Li 13025e5d3154Sxinhui pan int psp_ras_enable_features(struct psp_context *psp, 13035e5d3154Sxinhui pan union ta_ras_cmd_input *info, bool enable) 13045e5d3154Sxinhui pan { 13055e5d3154Sxinhui pan struct ta_ras_shared_memory *ras_cmd; 13065e5d3154Sxinhui pan int ret; 13075e5d3154Sxinhui pan 13085e5d3154Sxinhui pan if (!psp->ras.ras_initialized) 13095e5d3154Sxinhui pan return -EINVAL; 13105e5d3154Sxinhui pan 13115e5d3154Sxinhui pan ras_cmd = (struct ta_ras_shared_memory *)psp->ras.ras_shared_buf; 13125e5d3154Sxinhui pan memset(ras_cmd, 0, sizeof(struct ta_ras_shared_memory)); 13135e5d3154Sxinhui pan 13145e5d3154Sxinhui pan if (enable) 13155e5d3154Sxinhui pan ras_cmd->cmd_id = TA_RAS_COMMAND__ENABLE_FEATURES; 13165e5d3154Sxinhui pan else 13175e5d3154Sxinhui pan ras_cmd->cmd_id = TA_RAS_COMMAND__DISABLE_FEATURES; 13185e5d3154Sxinhui pan 13195e5d3154Sxinhui pan ras_cmd->ras_in_message = *info; 13205e5d3154Sxinhui pan 13215e5d3154Sxinhui pan ret = psp_ras_invoke(psp, ras_cmd->cmd_id); 13225e5d3154Sxinhui pan if (ret) 13235e5d3154Sxinhui pan return -EINVAL; 13245e5d3154Sxinhui pan 1325011907fdSDennis Li return psp_ras_status_to_errno(psp->adev, ras_cmd->ras_status); 13265e5d3154Sxinhui pan } 13275e5d3154Sxinhui pan 13285e5d3154Sxinhui pan static int psp_ras_terminate(struct psp_context *psp) 13295e5d3154Sxinhui pan { 13305e5d3154Sxinhui pan int ret; 13315e5d3154Sxinhui pan 1332edc2176dSJack Zhang /* 1333edc2176dSJack Zhang * TODO: bypass the terminate in sriov for now 1334edc2176dSJack Zhang */ 1335edc2176dSJack Zhang if (amdgpu_sriov_vf(psp->adev)) 1336edc2176dSJack Zhang return 0; 1337edc2176dSJack Zhang 13385e5d3154Sxinhui pan if (!psp->ras.ras_initialized) 13395e5d3154Sxinhui pan return 0; 13405e5d3154Sxinhui pan 13415e5d3154Sxinhui pan ret = psp_ras_unload(psp); 13425e5d3154Sxinhui pan if (ret) 13435e5d3154Sxinhui pan return ret; 13445e5d3154Sxinhui pan 1345e95cd6b2Szhengbin psp->ras.ras_initialized = false; 13465e5d3154Sxinhui pan 13475e5d3154Sxinhui pan /* free ras shared memory */ 13485e5d3154Sxinhui pan amdgpu_bo_free_kernel(&psp->ras.ras_shared_bo, 13495e5d3154Sxinhui pan &psp->ras.ras_shared_mc_addr, 13505e5d3154Sxinhui pan &psp->ras.ras_shared_buf); 13515e5d3154Sxinhui pan 13525e5d3154Sxinhui pan return 0; 13535e5d3154Sxinhui pan } 13545e5d3154Sxinhui pan 13555e5d3154Sxinhui pan static int psp_ras_initialize(struct psp_context *psp) 13565e5d3154Sxinhui pan { 13575e5d3154Sxinhui pan int ret; 13586246a416SHawking Zhang uint32_t boot_cfg = 0xFF; 13596246a416SHawking Zhang struct amdgpu_device *adev = psp->adev; 13605e5d3154Sxinhui pan 1361edc2176dSJack Zhang /* 1362edc2176dSJack Zhang * TODO: bypass the initialize in sriov for now 1363edc2176dSJack Zhang */ 13646246a416SHawking Zhang if (amdgpu_sriov_vf(adev)) 1365edc2176dSJack Zhang return 0; 1366edc2176dSJack Zhang 13676246a416SHawking Zhang if (!adev->psp.ta_ras_ucode_size || 13686246a416SHawking Zhang !adev->psp.ta_ras_start_addr) { 13696246a416SHawking Zhang dev_info(adev->dev, "RAS: optional ras ta ucode is not available\n"); 137051bd3638SHawking Zhang return 0; 137151bd3638SHawking Zhang } 137251bd3638SHawking Zhang 13736246a416SHawking Zhang if (amdgpu_atomfirmware_dynamic_boot_config_supported(adev)) { 13746246a416SHawking Zhang /* query GECC enablement status from boot config 13756246a416SHawking Zhang * boot_cfg: 1: GECC is enabled or 0: GECC is disabled 13766246a416SHawking Zhang */ 13776246a416SHawking Zhang ret = psp_boot_config_get(adev, &boot_cfg); 13786246a416SHawking Zhang if (ret) 13796246a416SHawking Zhang dev_warn(adev->dev, "PSP get boot config failed\n"); 13806246a416SHawking Zhang 13816246a416SHawking Zhang if (!amdgpu_ras_is_supported(psp->adev, AMDGPU_RAS_BLOCK__UMC)) { 13826246a416SHawking Zhang if (!boot_cfg) { 13836246a416SHawking Zhang dev_info(adev->dev, "GECC is disabled\n"); 13846246a416SHawking Zhang } else { 13856246a416SHawking Zhang /* disable GECC in next boot cycle if ras is 13866246a416SHawking Zhang * disabled by module parameter amdgpu_ras_enable 13876246a416SHawking Zhang * and/or amdgpu_ras_mask, or boot_config_get call 13886246a416SHawking Zhang * is failed 13896246a416SHawking Zhang */ 13906246a416SHawking Zhang ret = psp_boot_config_set(adev, 0); 13916246a416SHawking Zhang if (ret) 13926246a416SHawking Zhang dev_warn(adev->dev, "PSP set boot config failed\n"); 13936246a416SHawking Zhang else 13946246a416SHawking Zhang dev_warn(adev->dev, "GECC will be disabled in next boot cycle " 13956246a416SHawking Zhang "if set amdgpu_ras_enable and/or amdgpu_ras_mask to 0x0\n"); 13966246a416SHawking Zhang } 13976246a416SHawking Zhang } else { 13986246a416SHawking Zhang if (1 == boot_cfg) { 13996246a416SHawking Zhang dev_info(adev->dev, "GECC is enabled\n"); 14006246a416SHawking Zhang } else { 14016246a416SHawking Zhang /* enable GECC in next boot cycle if it is disabled 14026246a416SHawking Zhang * in boot config, or force enable GECC if failed to 14036246a416SHawking Zhang * get boot configuration 14046246a416SHawking Zhang */ 14056246a416SHawking Zhang ret = psp_boot_config_set(adev, BOOT_CONFIG_GECC); 14066246a416SHawking Zhang if (ret) 14076246a416SHawking Zhang dev_warn(adev->dev, "PSP set boot config failed\n"); 14086246a416SHawking Zhang else 14096246a416SHawking Zhang dev_warn(adev->dev, "GECC will be enabled in next boot cycle\n"); 14106246a416SHawking Zhang } 14116246a416SHawking Zhang } 14126246a416SHawking Zhang } 14136246a416SHawking Zhang 14145e5d3154Sxinhui pan if (!psp->ras.ras_initialized) { 14155e5d3154Sxinhui pan ret = psp_ras_init_shared_buf(psp); 14165e5d3154Sxinhui pan if (ret) 14175e5d3154Sxinhui pan return ret; 14185e5d3154Sxinhui pan } 14195e5d3154Sxinhui pan 14205e5d3154Sxinhui pan ret = psp_ras_load(psp); 14215e5d3154Sxinhui pan if (ret) 14225e5d3154Sxinhui pan return ret; 14235e5d3154Sxinhui pan 14245e5d3154Sxinhui pan return 0; 14255e5d3154Sxinhui pan } 1426001a0a95SHawking Zhang 1427001a0a95SHawking Zhang int psp_ras_trigger_error(struct psp_context *psp, 1428001a0a95SHawking Zhang struct ta_ras_trigger_error_input *info) 1429001a0a95SHawking Zhang { 1430001a0a95SHawking Zhang struct ta_ras_shared_memory *ras_cmd; 1431001a0a95SHawking Zhang int ret; 1432001a0a95SHawking Zhang 1433001a0a95SHawking Zhang if (!psp->ras.ras_initialized) 1434001a0a95SHawking Zhang return -EINVAL; 1435001a0a95SHawking Zhang 1436001a0a95SHawking Zhang ras_cmd = (struct ta_ras_shared_memory *)psp->ras.ras_shared_buf; 1437001a0a95SHawking Zhang memset(ras_cmd, 0, sizeof(struct ta_ras_shared_memory)); 1438001a0a95SHawking Zhang 1439001a0a95SHawking Zhang ras_cmd->cmd_id = TA_RAS_COMMAND__TRIGGER_ERROR; 1440001a0a95SHawking Zhang ras_cmd->ras_in_message.trigger_error = *info; 1441001a0a95SHawking Zhang 1442001a0a95SHawking Zhang ret = psp_ras_invoke(psp, ras_cmd->cmd_id); 1443001a0a95SHawking Zhang if (ret) 1444001a0a95SHawking Zhang return -EINVAL; 1445001a0a95SHawking Zhang 1446001a0a95SHawking Zhang /* If err_event_athub occurs error inject was successful, however 1447001a0a95SHawking Zhang return status from TA is no long reliable */ 1448001a0a95SHawking Zhang if (amdgpu_ras_intr_triggered()) 1449001a0a95SHawking Zhang return 0; 1450001a0a95SHawking Zhang 1451011907fdSDennis Li return psp_ras_status_to_errno(psp->adev, ras_cmd->ras_status); 1452001a0a95SHawking Zhang } 14535e5d3154Sxinhui pan // ras end 14545e5d3154Sxinhui pan 1455ed19a9a2SBhawanpreet Lakha // HDCP start 1456ed19a9a2SBhawanpreet Lakha static int psp_hdcp_init_shared_buf(struct psp_context *psp) 1457ed19a9a2SBhawanpreet Lakha { 1458ed19a9a2SBhawanpreet Lakha int ret; 1459ed19a9a2SBhawanpreet Lakha 1460ed19a9a2SBhawanpreet Lakha /* 1461ed19a9a2SBhawanpreet Lakha * Allocate 16k memory aligned to 4k from Frame Buffer (local 1462ed19a9a2SBhawanpreet Lakha * physical) for hdcp ta <-> Driver 1463ed19a9a2SBhawanpreet Lakha */ 1464ed19a9a2SBhawanpreet Lakha ret = amdgpu_bo_create_kernel(psp->adev, PSP_HDCP_SHARED_MEM_SIZE, 1465ed19a9a2SBhawanpreet Lakha PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM, 1466ed19a9a2SBhawanpreet Lakha &psp->hdcp_context.hdcp_shared_bo, 1467ed19a9a2SBhawanpreet Lakha &psp->hdcp_context.hdcp_shared_mc_addr, 1468ed19a9a2SBhawanpreet Lakha &psp->hdcp_context.hdcp_shared_buf); 1469ed19a9a2SBhawanpreet Lakha 1470ed19a9a2SBhawanpreet Lakha return ret; 1471ed19a9a2SBhawanpreet Lakha } 1472ed19a9a2SBhawanpreet Lakha 1473ed19a9a2SBhawanpreet Lakha static int psp_hdcp_load(struct psp_context *psp) 1474ed19a9a2SBhawanpreet Lakha { 1475ed19a9a2SBhawanpreet Lakha int ret; 1476*4fb93071SCandice Li struct psp_gfx_cmd_resp *cmd = psp->cmd; 1477ed19a9a2SBhawanpreet Lakha 1478ed19a9a2SBhawanpreet Lakha /* 1479ed19a9a2SBhawanpreet Lakha * TODO: bypass the loading in sriov for now 1480ed19a9a2SBhawanpreet Lakha */ 1481ed19a9a2SBhawanpreet Lakha if (amdgpu_sriov_vf(psp->adev)) 1482ed19a9a2SBhawanpreet Lakha return 0; 1483ed19a9a2SBhawanpreet Lakha 1484f89f8c6bSAndrey Grodzovsky psp_copy_fw(psp, psp->ta_hdcp_start_addr, 1485ed19a9a2SBhawanpreet Lakha psp->ta_hdcp_ucode_size); 1486ed19a9a2SBhawanpreet Lakha 14871f455f25SJohn Clements psp_prep_ta_load_cmd_buf(cmd, 14881f455f25SJohn Clements psp->fw_pri_mc_addr, 1489ed19a9a2SBhawanpreet Lakha psp->ta_hdcp_ucode_size, 14901f455f25SJohn Clements psp->hdcp_context.hdcp_shared_mc_addr, 1491ed19a9a2SBhawanpreet Lakha PSP_HDCP_SHARED_MEM_SIZE); 1492ed19a9a2SBhawanpreet Lakha 1493ed19a9a2SBhawanpreet Lakha ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); 1494ed19a9a2SBhawanpreet Lakha 1495ed19a9a2SBhawanpreet Lakha if (!ret) { 1496e95cd6b2Szhengbin psp->hdcp_context.hdcp_initialized = true; 1497ed19a9a2SBhawanpreet Lakha psp->hdcp_context.session_id = cmd->resp.session_id; 14988913f7ffSBhawanpreet Lakha mutex_init(&psp->hdcp_context.mutex); 1499ed19a9a2SBhawanpreet Lakha } 1500ed19a9a2SBhawanpreet Lakha 1501ed19a9a2SBhawanpreet Lakha return ret; 1502ed19a9a2SBhawanpreet Lakha } 1503ed19a9a2SBhawanpreet Lakha static int psp_hdcp_initialize(struct psp_context *psp) 1504ed19a9a2SBhawanpreet Lakha { 1505ed19a9a2SBhawanpreet Lakha int ret; 1506ed19a9a2SBhawanpreet Lakha 1507edc2176dSJack Zhang /* 1508edc2176dSJack Zhang * TODO: bypass the initialize in sriov for now 1509edc2176dSJack Zhang */ 1510edc2176dSJack Zhang if (amdgpu_sriov_vf(psp->adev)) 1511edc2176dSJack Zhang return 0; 1512edc2176dSJack Zhang 151351bd3638SHawking Zhang if (!psp->adev->psp.ta_hdcp_ucode_size || 151451bd3638SHawking Zhang !psp->adev->psp.ta_hdcp_start_addr) { 1515a45a9e5eSAlex Deucher dev_info(psp->adev->dev, "HDCP: optional hdcp ta ucode is not available\n"); 151651bd3638SHawking Zhang return 0; 151751bd3638SHawking Zhang } 151851bd3638SHawking Zhang 1519ed19a9a2SBhawanpreet Lakha if (!psp->hdcp_context.hdcp_initialized) { 1520ed19a9a2SBhawanpreet Lakha ret = psp_hdcp_init_shared_buf(psp); 1521ed19a9a2SBhawanpreet Lakha if (ret) 1522ed19a9a2SBhawanpreet Lakha return ret; 1523ed19a9a2SBhawanpreet Lakha } 1524ed19a9a2SBhawanpreet Lakha 1525ed19a9a2SBhawanpreet Lakha ret = psp_hdcp_load(psp); 1526ed19a9a2SBhawanpreet Lakha if (ret) 1527ed19a9a2SBhawanpreet Lakha return ret; 1528ed19a9a2SBhawanpreet Lakha 1529ed19a9a2SBhawanpreet Lakha return 0; 1530ed19a9a2SBhawanpreet Lakha } 1531ed19a9a2SBhawanpreet Lakha 1532ed19a9a2SBhawanpreet Lakha static int psp_hdcp_unload(struct psp_context *psp) 1533ed19a9a2SBhawanpreet Lakha { 1534ed19a9a2SBhawanpreet Lakha int ret; 1535*4fb93071SCandice Li struct psp_gfx_cmd_resp *cmd = psp->cmd; 1536ed19a9a2SBhawanpreet Lakha 1537ed19a9a2SBhawanpreet Lakha /* 1538ed19a9a2SBhawanpreet Lakha * TODO: bypass the unloading in sriov for now 1539ed19a9a2SBhawanpreet Lakha */ 1540ed19a9a2SBhawanpreet Lakha if (amdgpu_sriov_vf(psp->adev)) 1541ed19a9a2SBhawanpreet Lakha return 0; 1542ed19a9a2SBhawanpreet Lakha 15431f455f25SJohn Clements psp_prep_ta_unload_cmd_buf(cmd, psp->hdcp_context.session_id); 1544ed19a9a2SBhawanpreet Lakha 1545ed19a9a2SBhawanpreet Lakha ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); 1546ed19a9a2SBhawanpreet Lakha 1547ed19a9a2SBhawanpreet Lakha return ret; 1548ed19a9a2SBhawanpreet Lakha } 1549ed19a9a2SBhawanpreet Lakha 1550ed19a9a2SBhawanpreet Lakha int psp_hdcp_invoke(struct psp_context *psp, uint32_t ta_cmd_id) 1551ed19a9a2SBhawanpreet Lakha { 1552ed19a9a2SBhawanpreet Lakha /* 1553ed19a9a2SBhawanpreet Lakha * TODO: bypass the loading in sriov for now 1554ed19a9a2SBhawanpreet Lakha */ 1555ed19a9a2SBhawanpreet Lakha if (amdgpu_sriov_vf(psp->adev)) 1556ed19a9a2SBhawanpreet Lakha return 0; 1557ed19a9a2SBhawanpreet Lakha 155834e48caeSJohn Clements return psp_ta_invoke(psp, ta_cmd_id, psp->hdcp_context.session_id); 1559ed19a9a2SBhawanpreet Lakha } 1560ed19a9a2SBhawanpreet Lakha 1561ed19a9a2SBhawanpreet Lakha static int psp_hdcp_terminate(struct psp_context *psp) 1562ed19a9a2SBhawanpreet Lakha { 1563ed19a9a2SBhawanpreet Lakha int ret; 1564ed19a9a2SBhawanpreet Lakha 1565edc2176dSJack Zhang /* 1566edc2176dSJack Zhang * TODO: bypass the terminate in sriov for now 1567edc2176dSJack Zhang */ 1568edc2176dSJack Zhang if (amdgpu_sriov_vf(psp->adev)) 1569edc2176dSJack Zhang return 0; 1570edc2176dSJack Zhang 15710d232dadSJiawei Gu if (!psp->hdcp_context.hdcp_initialized) { 15720d232dadSJiawei Gu if (psp->hdcp_context.hdcp_shared_buf) 15730d232dadSJiawei Gu goto out; 15740d232dadSJiawei Gu else 1575ed19a9a2SBhawanpreet Lakha return 0; 15760d232dadSJiawei Gu } 1577ed19a9a2SBhawanpreet Lakha 1578ed19a9a2SBhawanpreet Lakha ret = psp_hdcp_unload(psp); 1579ed19a9a2SBhawanpreet Lakha if (ret) 1580ed19a9a2SBhawanpreet Lakha return ret; 1581ed19a9a2SBhawanpreet Lakha 1582e95cd6b2Szhengbin psp->hdcp_context.hdcp_initialized = false; 1583ed19a9a2SBhawanpreet Lakha 15840d232dadSJiawei Gu out: 1585ed19a9a2SBhawanpreet Lakha /* free hdcp shared memory */ 1586ed19a9a2SBhawanpreet Lakha amdgpu_bo_free_kernel(&psp->hdcp_context.hdcp_shared_bo, 1587ed19a9a2SBhawanpreet Lakha &psp->hdcp_context.hdcp_shared_mc_addr, 1588ed19a9a2SBhawanpreet Lakha &psp->hdcp_context.hdcp_shared_buf); 1589ed19a9a2SBhawanpreet Lakha 1590ed19a9a2SBhawanpreet Lakha return 0; 1591ed19a9a2SBhawanpreet Lakha } 1592ed19a9a2SBhawanpreet Lakha // HDCP end 1593ed19a9a2SBhawanpreet Lakha 1594143f2305SBhawanpreet Lakha // DTM start 1595143f2305SBhawanpreet Lakha static int psp_dtm_init_shared_buf(struct psp_context *psp) 1596143f2305SBhawanpreet Lakha { 1597143f2305SBhawanpreet Lakha int ret; 1598143f2305SBhawanpreet Lakha 1599143f2305SBhawanpreet Lakha /* 1600143f2305SBhawanpreet Lakha * Allocate 16k memory aligned to 4k from Frame Buffer (local 1601143f2305SBhawanpreet Lakha * physical) for dtm ta <-> Driver 1602143f2305SBhawanpreet Lakha */ 1603143f2305SBhawanpreet Lakha ret = amdgpu_bo_create_kernel(psp->adev, PSP_DTM_SHARED_MEM_SIZE, 1604143f2305SBhawanpreet Lakha PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM, 1605143f2305SBhawanpreet Lakha &psp->dtm_context.dtm_shared_bo, 1606143f2305SBhawanpreet Lakha &psp->dtm_context.dtm_shared_mc_addr, 1607143f2305SBhawanpreet Lakha &psp->dtm_context.dtm_shared_buf); 1608143f2305SBhawanpreet Lakha 1609143f2305SBhawanpreet Lakha return ret; 1610143f2305SBhawanpreet Lakha } 1611143f2305SBhawanpreet Lakha 1612143f2305SBhawanpreet Lakha static int psp_dtm_load(struct psp_context *psp) 1613143f2305SBhawanpreet Lakha { 1614143f2305SBhawanpreet Lakha int ret; 1615*4fb93071SCandice Li struct psp_gfx_cmd_resp *cmd = psp->cmd; 1616143f2305SBhawanpreet Lakha 1617143f2305SBhawanpreet Lakha /* 1618143f2305SBhawanpreet Lakha * TODO: bypass the loading in sriov for now 1619143f2305SBhawanpreet Lakha */ 1620143f2305SBhawanpreet Lakha if (amdgpu_sriov_vf(psp->adev)) 1621143f2305SBhawanpreet Lakha return 0; 1622143f2305SBhawanpreet Lakha 1623f89f8c6bSAndrey Grodzovsky psp_copy_fw(psp, psp->ta_dtm_start_addr, psp->ta_dtm_ucode_size); 1624143f2305SBhawanpreet Lakha 16251f455f25SJohn Clements psp_prep_ta_load_cmd_buf(cmd, 16261f455f25SJohn Clements psp->fw_pri_mc_addr, 1627143f2305SBhawanpreet Lakha psp->ta_dtm_ucode_size, 16281f455f25SJohn Clements psp->dtm_context.dtm_shared_mc_addr, 1629143f2305SBhawanpreet Lakha PSP_DTM_SHARED_MEM_SIZE); 1630143f2305SBhawanpreet Lakha 1631143f2305SBhawanpreet Lakha ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); 1632143f2305SBhawanpreet Lakha 1633143f2305SBhawanpreet Lakha if (!ret) { 1634e95cd6b2Szhengbin psp->dtm_context.dtm_initialized = true; 1635143f2305SBhawanpreet Lakha psp->dtm_context.session_id = cmd->resp.session_id; 16368913f7ffSBhawanpreet Lakha mutex_init(&psp->dtm_context.mutex); 1637143f2305SBhawanpreet Lakha } 1638143f2305SBhawanpreet Lakha 1639143f2305SBhawanpreet Lakha return ret; 1640143f2305SBhawanpreet Lakha } 1641143f2305SBhawanpreet Lakha 1642143f2305SBhawanpreet Lakha static int psp_dtm_initialize(struct psp_context *psp) 1643143f2305SBhawanpreet Lakha { 1644143f2305SBhawanpreet Lakha int ret; 1645143f2305SBhawanpreet Lakha 1646edc2176dSJack Zhang /* 1647edc2176dSJack Zhang * TODO: bypass the initialize in sriov for now 1648edc2176dSJack Zhang */ 1649edc2176dSJack Zhang if (amdgpu_sriov_vf(psp->adev)) 1650edc2176dSJack Zhang return 0; 1651edc2176dSJack Zhang 165251bd3638SHawking Zhang if (!psp->adev->psp.ta_dtm_ucode_size || 165351bd3638SHawking Zhang !psp->adev->psp.ta_dtm_start_addr) { 1654a45a9e5eSAlex Deucher dev_info(psp->adev->dev, "DTM: optional dtm ta ucode is not available\n"); 165551bd3638SHawking Zhang return 0; 165651bd3638SHawking Zhang } 165751bd3638SHawking Zhang 1658143f2305SBhawanpreet Lakha if (!psp->dtm_context.dtm_initialized) { 1659143f2305SBhawanpreet Lakha ret = psp_dtm_init_shared_buf(psp); 1660143f2305SBhawanpreet Lakha if (ret) 1661143f2305SBhawanpreet Lakha return ret; 1662143f2305SBhawanpreet Lakha } 1663143f2305SBhawanpreet Lakha 1664143f2305SBhawanpreet Lakha ret = psp_dtm_load(psp); 1665143f2305SBhawanpreet Lakha if (ret) 1666143f2305SBhawanpreet Lakha return ret; 1667143f2305SBhawanpreet Lakha 1668143f2305SBhawanpreet Lakha return 0; 1669143f2305SBhawanpreet Lakha } 1670143f2305SBhawanpreet Lakha 1671c786530bSBhawanpreet Lakha static int psp_dtm_unload(struct psp_context *psp) 1672c786530bSBhawanpreet Lakha { 1673c786530bSBhawanpreet Lakha int ret; 1674*4fb93071SCandice Li struct psp_gfx_cmd_resp *cmd = psp->cmd; 1675c786530bSBhawanpreet Lakha 1676c786530bSBhawanpreet Lakha /* 1677c786530bSBhawanpreet Lakha * TODO: bypass the unloading in sriov for now 1678c786530bSBhawanpreet Lakha */ 1679c786530bSBhawanpreet Lakha if (amdgpu_sriov_vf(psp->adev)) 1680c786530bSBhawanpreet Lakha return 0; 1681c786530bSBhawanpreet Lakha 1682c786530bSBhawanpreet Lakha psp_prep_ta_unload_cmd_buf(cmd, psp->dtm_context.session_id); 1683c786530bSBhawanpreet Lakha 1684c786530bSBhawanpreet Lakha ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); 1685c786530bSBhawanpreet Lakha 1686c786530bSBhawanpreet Lakha return ret; 1687c786530bSBhawanpreet Lakha } 1688c786530bSBhawanpreet Lakha 1689143f2305SBhawanpreet Lakha int psp_dtm_invoke(struct psp_context *psp, uint32_t ta_cmd_id) 1690143f2305SBhawanpreet Lakha { 1691143f2305SBhawanpreet Lakha /* 1692143f2305SBhawanpreet Lakha * TODO: bypass the loading in sriov for now 1693143f2305SBhawanpreet Lakha */ 1694143f2305SBhawanpreet Lakha if (amdgpu_sriov_vf(psp->adev)) 1695143f2305SBhawanpreet Lakha return 0; 1696143f2305SBhawanpreet Lakha 169734e48caeSJohn Clements return psp_ta_invoke(psp, ta_cmd_id, psp->dtm_context.session_id); 1698143f2305SBhawanpreet Lakha } 1699143f2305SBhawanpreet Lakha 1700143f2305SBhawanpreet Lakha static int psp_dtm_terminate(struct psp_context *psp) 1701143f2305SBhawanpreet Lakha { 1702143f2305SBhawanpreet Lakha int ret; 1703143f2305SBhawanpreet Lakha 1704edc2176dSJack Zhang /* 1705edc2176dSJack Zhang * TODO: bypass the terminate in sriov for now 1706edc2176dSJack Zhang */ 1707edc2176dSJack Zhang if (amdgpu_sriov_vf(psp->adev)) 1708edc2176dSJack Zhang return 0; 1709edc2176dSJack Zhang 17100d232dadSJiawei Gu if (!psp->dtm_context.dtm_initialized) { 17110d232dadSJiawei Gu if (psp->dtm_context.dtm_shared_buf) 17120d232dadSJiawei Gu goto out; 17130d232dadSJiawei Gu else 1714143f2305SBhawanpreet Lakha return 0; 17150d232dadSJiawei Gu } 1716143f2305SBhawanpreet Lakha 1717c786530bSBhawanpreet Lakha ret = psp_dtm_unload(psp); 1718143f2305SBhawanpreet Lakha if (ret) 1719143f2305SBhawanpreet Lakha return ret; 1720143f2305SBhawanpreet Lakha 1721e95cd6b2Szhengbin psp->dtm_context.dtm_initialized = false; 1722143f2305SBhawanpreet Lakha 17230d232dadSJiawei Gu out: 1724143f2305SBhawanpreet Lakha /* free hdcp shared memory */ 1725143f2305SBhawanpreet Lakha amdgpu_bo_free_kernel(&psp->dtm_context.dtm_shared_bo, 1726143f2305SBhawanpreet Lakha &psp->dtm_context.dtm_shared_mc_addr, 1727143f2305SBhawanpreet Lakha &psp->dtm_context.dtm_shared_buf); 1728143f2305SBhawanpreet Lakha 1729143f2305SBhawanpreet Lakha return 0; 1730143f2305SBhawanpreet Lakha } 1731143f2305SBhawanpreet Lakha // DTM end 1732143f2305SBhawanpreet Lakha 17338602692bSWenhui Sheng // RAP start 17348602692bSWenhui Sheng static int psp_rap_init_shared_buf(struct psp_context *psp) 17358602692bSWenhui Sheng { 17368602692bSWenhui Sheng int ret; 17378602692bSWenhui Sheng 17388602692bSWenhui Sheng /* 17398602692bSWenhui Sheng * Allocate 16k memory aligned to 4k from Frame Buffer (local 17408602692bSWenhui Sheng * physical) for rap ta <-> Driver 17418602692bSWenhui Sheng */ 17428602692bSWenhui Sheng ret = amdgpu_bo_create_kernel(psp->adev, PSP_RAP_SHARED_MEM_SIZE, 17438602692bSWenhui Sheng PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM, 17448602692bSWenhui Sheng &psp->rap_context.rap_shared_bo, 17458602692bSWenhui Sheng &psp->rap_context.rap_shared_mc_addr, 17468602692bSWenhui Sheng &psp->rap_context.rap_shared_buf); 17478602692bSWenhui Sheng 17488602692bSWenhui Sheng return ret; 17498602692bSWenhui Sheng } 17508602692bSWenhui Sheng 17518602692bSWenhui Sheng static int psp_rap_load(struct psp_context *psp) 17528602692bSWenhui Sheng { 17538602692bSWenhui Sheng int ret; 1754*4fb93071SCandice Li struct psp_gfx_cmd_resp *cmd = psp->cmd; 17558602692bSWenhui Sheng 1756f89f8c6bSAndrey Grodzovsky psp_copy_fw(psp, psp->ta_rap_start_addr, psp->ta_rap_ucode_size); 17578602692bSWenhui Sheng 17588602692bSWenhui Sheng psp_prep_ta_load_cmd_buf(cmd, 17598602692bSWenhui Sheng psp->fw_pri_mc_addr, 17608602692bSWenhui Sheng psp->ta_rap_ucode_size, 17618602692bSWenhui Sheng psp->rap_context.rap_shared_mc_addr, 17628602692bSWenhui Sheng PSP_RAP_SHARED_MEM_SIZE); 17638602692bSWenhui Sheng 17648602692bSWenhui Sheng ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); 17658602692bSWenhui Sheng 17668602692bSWenhui Sheng if (!ret) { 17678602692bSWenhui Sheng psp->rap_context.rap_initialized = true; 17688602692bSWenhui Sheng psp->rap_context.session_id = cmd->resp.session_id; 17698602692bSWenhui Sheng mutex_init(&psp->rap_context.mutex); 17708602692bSWenhui Sheng } 17718602692bSWenhui Sheng 17728602692bSWenhui Sheng return ret; 17738602692bSWenhui Sheng } 17748602692bSWenhui Sheng 17758602692bSWenhui Sheng static int psp_rap_unload(struct psp_context *psp) 17768602692bSWenhui Sheng { 17778602692bSWenhui Sheng int ret; 1778*4fb93071SCandice Li struct psp_gfx_cmd_resp *cmd = psp->cmd; 17798602692bSWenhui Sheng 17808602692bSWenhui Sheng psp_prep_ta_unload_cmd_buf(cmd, psp->rap_context.session_id); 17818602692bSWenhui Sheng 17828602692bSWenhui Sheng ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); 17838602692bSWenhui Sheng 17848602692bSWenhui Sheng return ret; 17858602692bSWenhui Sheng } 17868602692bSWenhui Sheng 17878602692bSWenhui Sheng static int psp_rap_initialize(struct psp_context *psp) 17888602692bSWenhui Sheng { 17898602692bSWenhui Sheng int ret; 17902fb3c5d0SKevin Wang enum ta_rap_status status = TA_RAP_STATUS__SUCCESS; 17918602692bSWenhui Sheng 17928602692bSWenhui Sheng /* 17938602692bSWenhui Sheng * TODO: bypass the initialize in sriov for now 17948602692bSWenhui Sheng */ 17958602692bSWenhui Sheng if (amdgpu_sriov_vf(psp->adev)) 17968602692bSWenhui Sheng return 0; 17978602692bSWenhui Sheng 17988602692bSWenhui Sheng if (!psp->adev->psp.ta_rap_ucode_size || 17998602692bSWenhui Sheng !psp->adev->psp.ta_rap_start_addr) { 18008602692bSWenhui Sheng dev_info(psp->adev->dev, "RAP: optional rap ta ucode is not available\n"); 18018602692bSWenhui Sheng return 0; 18028602692bSWenhui Sheng } 18038602692bSWenhui Sheng 18048602692bSWenhui Sheng if (!psp->rap_context.rap_initialized) { 18058602692bSWenhui Sheng ret = psp_rap_init_shared_buf(psp); 18068602692bSWenhui Sheng if (ret) 18078602692bSWenhui Sheng return ret; 18088602692bSWenhui Sheng } 18098602692bSWenhui Sheng 18108602692bSWenhui Sheng ret = psp_rap_load(psp); 18118602692bSWenhui Sheng if (ret) 18128602692bSWenhui Sheng return ret; 18138602692bSWenhui Sheng 18142fb3c5d0SKevin Wang ret = psp_rap_invoke(psp, TA_CMD_RAP__INITIALIZE, &status); 18152fb3c5d0SKevin Wang if (ret || status != TA_RAP_STATUS__SUCCESS) { 18168602692bSWenhui Sheng psp_rap_unload(psp); 18178602692bSWenhui Sheng 18188602692bSWenhui Sheng amdgpu_bo_free_kernel(&psp->rap_context.rap_shared_bo, 18198602692bSWenhui Sheng &psp->rap_context.rap_shared_mc_addr, 18208602692bSWenhui Sheng &psp->rap_context.rap_shared_buf); 18218602692bSWenhui Sheng 18228602692bSWenhui Sheng psp->rap_context.rap_initialized = false; 18238602692bSWenhui Sheng 18242fb3c5d0SKevin Wang dev_warn(psp->adev->dev, "RAP TA initialize fail (%d) status %d.\n", 18252fb3c5d0SKevin Wang ret, status); 18262fb3c5d0SKevin Wang 18272fb3c5d0SKevin Wang return ret; 18288602692bSWenhui Sheng } 18298602692bSWenhui Sheng 18308602692bSWenhui Sheng return 0; 18318602692bSWenhui Sheng } 18328602692bSWenhui Sheng 18338602692bSWenhui Sheng static int psp_rap_terminate(struct psp_context *psp) 18348602692bSWenhui Sheng { 18358602692bSWenhui Sheng int ret; 18368602692bSWenhui Sheng 18378602692bSWenhui Sheng if (!psp->rap_context.rap_initialized) 18388602692bSWenhui Sheng return 0; 18398602692bSWenhui Sheng 18408602692bSWenhui Sheng ret = psp_rap_unload(psp); 18418602692bSWenhui Sheng 18428602692bSWenhui Sheng psp->rap_context.rap_initialized = false; 18438602692bSWenhui Sheng 18448602692bSWenhui Sheng /* free rap shared memory */ 18458602692bSWenhui Sheng amdgpu_bo_free_kernel(&psp->rap_context.rap_shared_bo, 18468602692bSWenhui Sheng &psp->rap_context.rap_shared_mc_addr, 18478602692bSWenhui Sheng &psp->rap_context.rap_shared_buf); 18488602692bSWenhui Sheng 18498602692bSWenhui Sheng return ret; 18508602692bSWenhui Sheng } 18518602692bSWenhui Sheng 18522fb3c5d0SKevin Wang int psp_rap_invoke(struct psp_context *psp, uint32_t ta_cmd_id, enum ta_rap_status *status) 18538602692bSWenhui Sheng { 18548602692bSWenhui Sheng struct ta_rap_shared_memory *rap_cmd; 18552fb3c5d0SKevin Wang int ret = 0; 18568602692bSWenhui Sheng 18578602692bSWenhui Sheng if (!psp->rap_context.rap_initialized) 18582fb3c5d0SKevin Wang return 0; 18598602692bSWenhui Sheng 18608602692bSWenhui Sheng if (ta_cmd_id != TA_CMD_RAP__INITIALIZE && 18618602692bSWenhui Sheng ta_cmd_id != TA_CMD_RAP__VALIDATE_L0) 18628602692bSWenhui Sheng return -EINVAL; 18638602692bSWenhui Sheng 18648602692bSWenhui Sheng mutex_lock(&psp->rap_context.mutex); 18658602692bSWenhui Sheng 18668602692bSWenhui Sheng rap_cmd = (struct ta_rap_shared_memory *) 18678602692bSWenhui Sheng psp->rap_context.rap_shared_buf; 18688602692bSWenhui Sheng memset(rap_cmd, 0, sizeof(struct ta_rap_shared_memory)); 18698602692bSWenhui Sheng 18708602692bSWenhui Sheng rap_cmd->cmd_id = ta_cmd_id; 18718602692bSWenhui Sheng rap_cmd->validation_method_id = METHOD_A; 18728602692bSWenhui Sheng 18738602692bSWenhui Sheng ret = psp_ta_invoke(psp, rap_cmd->cmd_id, psp->rap_context.session_id); 18742fb3c5d0SKevin Wang if (ret) 18752fb3c5d0SKevin Wang goto out_unlock; 18762fb3c5d0SKevin Wang 18772fb3c5d0SKevin Wang if (status) 18782fb3c5d0SKevin Wang *status = rap_cmd->rap_status; 18792fb3c5d0SKevin Wang 18802fb3c5d0SKevin Wang out_unlock: 18818602692bSWenhui Sheng mutex_unlock(&psp->rap_context.mutex); 18822fb3c5d0SKevin Wang 18838602692bSWenhui Sheng return ret; 18848602692bSWenhui Sheng } 18858602692bSWenhui Sheng // RAP end 18868602692bSWenhui Sheng 1887ecaafb7bSJinzhou Su /* securedisplay start */ 1888ecaafb7bSJinzhou Su static int psp_securedisplay_init_shared_buf(struct psp_context *psp) 1889ecaafb7bSJinzhou Su { 1890ecaafb7bSJinzhou Su int ret; 1891ecaafb7bSJinzhou Su 1892ecaafb7bSJinzhou Su /* 1893ecaafb7bSJinzhou Su * Allocate 16k memory aligned to 4k from Frame Buffer (local 1894ecaafb7bSJinzhou Su * physical) for sa ta <-> Driver 1895ecaafb7bSJinzhou Su */ 1896ecaafb7bSJinzhou Su ret = amdgpu_bo_create_kernel(psp->adev, PSP_SECUREDISPLAY_SHARED_MEM_SIZE, 1897ecaafb7bSJinzhou Su PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM, 1898ecaafb7bSJinzhou Su &psp->securedisplay_context.securedisplay_shared_bo, 1899ecaafb7bSJinzhou Su &psp->securedisplay_context.securedisplay_shared_mc_addr, 1900ecaafb7bSJinzhou Su &psp->securedisplay_context.securedisplay_shared_buf); 1901ecaafb7bSJinzhou Su 1902ecaafb7bSJinzhou Su return ret; 1903ecaafb7bSJinzhou Su } 1904ecaafb7bSJinzhou Su 1905ecaafb7bSJinzhou Su static int psp_securedisplay_load(struct psp_context *psp) 1906ecaafb7bSJinzhou Su { 1907ecaafb7bSJinzhou Su int ret; 1908*4fb93071SCandice Li struct psp_gfx_cmd_resp *cmd = psp->cmd; 1909ecaafb7bSJinzhou Su 1910ecaafb7bSJinzhou Su memset(psp->fw_pri_buf, 0, PSP_1_MEG); 1911ecaafb7bSJinzhou Su memcpy(psp->fw_pri_buf, psp->ta_securedisplay_start_addr, psp->ta_securedisplay_ucode_size); 1912ecaafb7bSJinzhou Su 1913ecaafb7bSJinzhou Su psp_prep_ta_load_cmd_buf(cmd, 1914ecaafb7bSJinzhou Su psp->fw_pri_mc_addr, 1915ecaafb7bSJinzhou Su psp->ta_securedisplay_ucode_size, 1916ecaafb7bSJinzhou Su psp->securedisplay_context.securedisplay_shared_mc_addr, 1917ecaafb7bSJinzhou Su PSP_SECUREDISPLAY_SHARED_MEM_SIZE); 1918ecaafb7bSJinzhou Su 1919ecaafb7bSJinzhou Su ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); 1920ecaafb7bSJinzhou Su 1921ecaafb7bSJinzhou Su if (ret) 1922ecaafb7bSJinzhou Su goto failed; 1923ecaafb7bSJinzhou Su 1924ecaafb7bSJinzhou Su psp->securedisplay_context.securedisplay_initialized = true; 1925ecaafb7bSJinzhou Su psp->securedisplay_context.session_id = cmd->resp.session_id; 1926ecaafb7bSJinzhou Su mutex_init(&psp->securedisplay_context.mutex); 1927ecaafb7bSJinzhou Su 1928ecaafb7bSJinzhou Su failed: 1929ecaafb7bSJinzhou Su return ret; 1930ecaafb7bSJinzhou Su } 1931ecaafb7bSJinzhou Su 1932ecaafb7bSJinzhou Su static int psp_securedisplay_unload(struct psp_context *psp) 1933ecaafb7bSJinzhou Su { 1934ecaafb7bSJinzhou Su int ret; 1935*4fb93071SCandice Li struct psp_gfx_cmd_resp *cmd = psp->cmd; 1936ecaafb7bSJinzhou Su 1937ecaafb7bSJinzhou Su psp_prep_ta_unload_cmd_buf(cmd, psp->securedisplay_context.session_id); 1938ecaafb7bSJinzhou Su 1939ecaafb7bSJinzhou Su ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); 1940ecaafb7bSJinzhou Su 1941ecaafb7bSJinzhou Su return ret; 1942ecaafb7bSJinzhou Su } 1943ecaafb7bSJinzhou Su 1944ecaafb7bSJinzhou Su static int psp_securedisplay_initialize(struct psp_context *psp) 1945ecaafb7bSJinzhou Su { 1946ecaafb7bSJinzhou Su int ret; 1947ecaafb7bSJinzhou Su struct securedisplay_cmd *securedisplay_cmd; 1948ecaafb7bSJinzhou Su 1949ecaafb7bSJinzhou Su /* 1950ecaafb7bSJinzhou Su * TODO: bypass the initialize in sriov for now 1951ecaafb7bSJinzhou Su */ 1952ecaafb7bSJinzhou Su if (amdgpu_sriov_vf(psp->adev)) 1953ecaafb7bSJinzhou Su return 0; 1954ecaafb7bSJinzhou Su 1955ecaafb7bSJinzhou Su if (!psp->adev->psp.ta_securedisplay_ucode_size || 1956ecaafb7bSJinzhou Su !psp->adev->psp.ta_securedisplay_start_addr) { 1957ecaafb7bSJinzhou Su dev_info(psp->adev->dev, "SECUREDISPLAY: securedisplay ta ucode is not available\n"); 1958ecaafb7bSJinzhou Su return 0; 1959ecaafb7bSJinzhou Su } 1960ecaafb7bSJinzhou Su 1961ecaafb7bSJinzhou Su if (!psp->securedisplay_context.securedisplay_initialized) { 1962ecaafb7bSJinzhou Su ret = psp_securedisplay_init_shared_buf(psp); 1963ecaafb7bSJinzhou Su if (ret) 1964ecaafb7bSJinzhou Su return ret; 1965ecaafb7bSJinzhou Su } 1966ecaafb7bSJinzhou Su 1967ecaafb7bSJinzhou Su ret = psp_securedisplay_load(psp); 1968ecaafb7bSJinzhou Su if (ret) 1969ecaafb7bSJinzhou Su return ret; 1970ecaafb7bSJinzhou Su 1971ecaafb7bSJinzhou Su psp_prep_securedisplay_cmd_buf(psp, &securedisplay_cmd, 1972ecaafb7bSJinzhou Su TA_SECUREDISPLAY_COMMAND__QUERY_TA); 1973ecaafb7bSJinzhou Su 1974ecaafb7bSJinzhou Su ret = psp_securedisplay_invoke(psp, TA_SECUREDISPLAY_COMMAND__QUERY_TA); 1975ecaafb7bSJinzhou Su if (ret) { 1976ecaafb7bSJinzhou Su psp_securedisplay_unload(psp); 1977ecaafb7bSJinzhou Su 1978ecaafb7bSJinzhou Su amdgpu_bo_free_kernel(&psp->securedisplay_context.securedisplay_shared_bo, 1979ecaafb7bSJinzhou Su &psp->securedisplay_context.securedisplay_shared_mc_addr, 1980ecaafb7bSJinzhou Su &psp->securedisplay_context.securedisplay_shared_buf); 1981ecaafb7bSJinzhou Su 1982ecaafb7bSJinzhou Su psp->securedisplay_context.securedisplay_initialized = false; 1983ecaafb7bSJinzhou Su 1984ecaafb7bSJinzhou Su dev_err(psp->adev->dev, "SECUREDISPLAY TA initialize fail.\n"); 1985ecaafb7bSJinzhou Su return -EINVAL; 1986ecaafb7bSJinzhou Su } 1987ecaafb7bSJinzhou Su 1988ecaafb7bSJinzhou Su if (securedisplay_cmd->status != TA_SECUREDISPLAY_STATUS__SUCCESS) { 1989ecaafb7bSJinzhou Su psp_securedisplay_parse_resp_status(psp, securedisplay_cmd->status); 1990ecaafb7bSJinzhou Su dev_err(psp->adev->dev, "SECUREDISPLAY: query securedisplay TA failed. ret 0x%x\n", 1991ecaafb7bSJinzhou Su securedisplay_cmd->securedisplay_out_message.query_ta.query_cmd_ret); 1992ecaafb7bSJinzhou Su } 1993ecaafb7bSJinzhou Su 1994ecaafb7bSJinzhou Su return 0; 1995ecaafb7bSJinzhou Su } 1996ecaafb7bSJinzhou Su 1997ecaafb7bSJinzhou Su static int psp_securedisplay_terminate(struct psp_context *psp) 1998ecaafb7bSJinzhou Su { 1999ecaafb7bSJinzhou Su int ret; 2000ecaafb7bSJinzhou Su 2001ecaafb7bSJinzhou Su /* 2002ecaafb7bSJinzhou Su * TODO:bypass the terminate in sriov for now 2003ecaafb7bSJinzhou Su */ 2004ecaafb7bSJinzhou Su if (amdgpu_sriov_vf(psp->adev)) 2005ecaafb7bSJinzhou Su return 0; 2006ecaafb7bSJinzhou Su 2007ecaafb7bSJinzhou Su if (!psp->securedisplay_context.securedisplay_initialized) 2008ecaafb7bSJinzhou Su return 0; 2009ecaafb7bSJinzhou Su 2010ecaafb7bSJinzhou Su ret = psp_securedisplay_unload(psp); 2011ecaafb7bSJinzhou Su if (ret) 2012ecaafb7bSJinzhou Su return ret; 2013ecaafb7bSJinzhou Su 2014ecaafb7bSJinzhou Su psp->securedisplay_context.securedisplay_initialized = false; 2015ecaafb7bSJinzhou Su 2016ecaafb7bSJinzhou Su /* free securedisplay shared memory */ 2017ecaafb7bSJinzhou Su amdgpu_bo_free_kernel(&psp->securedisplay_context.securedisplay_shared_bo, 2018ecaafb7bSJinzhou Su &psp->securedisplay_context.securedisplay_shared_mc_addr, 2019ecaafb7bSJinzhou Su &psp->securedisplay_context.securedisplay_shared_buf); 2020ecaafb7bSJinzhou Su 2021ecaafb7bSJinzhou Su return ret; 2022ecaafb7bSJinzhou Su } 2023ecaafb7bSJinzhou Su 2024ecaafb7bSJinzhou Su int psp_securedisplay_invoke(struct psp_context *psp, uint32_t ta_cmd_id) 2025ecaafb7bSJinzhou Su { 2026ecaafb7bSJinzhou Su int ret; 2027ecaafb7bSJinzhou Su 2028ecaafb7bSJinzhou Su if (!psp->securedisplay_context.securedisplay_initialized) 2029ecaafb7bSJinzhou Su return -EINVAL; 2030ecaafb7bSJinzhou Su 2031ecaafb7bSJinzhou Su if (ta_cmd_id != TA_SECUREDISPLAY_COMMAND__QUERY_TA && 2032ecaafb7bSJinzhou Su ta_cmd_id != TA_SECUREDISPLAY_COMMAND__SEND_ROI_CRC) 2033ecaafb7bSJinzhou Su return -EINVAL; 2034ecaafb7bSJinzhou Su 2035ecaafb7bSJinzhou Su mutex_lock(&psp->securedisplay_context.mutex); 2036ecaafb7bSJinzhou Su 2037ecaafb7bSJinzhou Su ret = psp_ta_invoke(psp, ta_cmd_id, psp->securedisplay_context.session_id); 2038ecaafb7bSJinzhou Su 2039ecaafb7bSJinzhou Su mutex_unlock(&psp->securedisplay_context.mutex); 2040ecaafb7bSJinzhou Su 2041ecaafb7bSJinzhou Su return ret; 2042ecaafb7bSJinzhou Su } 2043ecaafb7bSJinzhou Su /* SECUREDISPLAY end */ 2044ecaafb7bSJinzhou Su 2045be70bbdaSHuang Rui static int psp_hw_start(struct psp_context *psp) 2046be70bbdaSHuang Rui { 204755981bd2SMonk Liu struct amdgpu_device *adev = psp->adev; 2048be70bbdaSHuang Rui int ret; 2049be70bbdaSHuang Rui 205082c4ebfaSMonk Liu if (!amdgpu_sriov_vf(adev)) { 2051222e0a71SCandice Li if ((is_psp_fw_valid(psp->kdb)) && 205242989359SHawking Zhang (psp->funcs->bootloader_load_kdb != NULL)) { 205342989359SHawking Zhang ret = psp_bootloader_load_kdb(psp); 205442989359SHawking Zhang if (ret) { 205542989359SHawking Zhang DRM_ERROR("PSP load kdb failed!\n"); 205642989359SHawking Zhang return ret; 205742989359SHawking Zhang } 205842989359SHawking Zhang } 205942989359SHawking Zhang 2060222e0a71SCandice Li if ((is_psp_fw_valid(psp->spl)) && 2061222e0a71SCandice Li (psp->funcs->bootloader_load_spl != NULL)) { 206270509057SLikun Gao ret = psp_bootloader_load_spl(psp); 206370509057SLikun Gao if (ret) { 206470509057SLikun Gao DRM_ERROR("PSP load spl failed!\n"); 206570509057SLikun Gao return ret; 206670509057SLikun Gao } 206770509057SLikun Gao } 206870509057SLikun Gao 2069222e0a71SCandice Li if ((is_psp_fw_valid(psp->sys)) && 2070222e0a71SCandice Li (psp->funcs->bootloader_load_sysdrv != NULL)) { 20710e5ca0d1SHuang Rui ret = psp_bootloader_load_sysdrv(psp); 20727a3d7bf6SEvan Quan if (ret) { 20737a3d7bf6SEvan Quan DRM_ERROR("PSP load sys drv failed!\n"); 2074be70bbdaSHuang Rui return ret; 207555981bd2SMonk Liu } 2076222e0a71SCandice Li } 20770e5ca0d1SHuang Rui 20786ff34fd6SJohn Clements if ((is_psp_fw_valid(psp->soc_drv)) && 20796ff34fd6SJohn Clements (psp->funcs->bootloader_load_soc_drv != NULL)) { 20806ff34fd6SJohn Clements ret = psp_bootloader_load_soc_drv(psp); 20816ff34fd6SJohn Clements if (ret) { 20826ff34fd6SJohn Clements DRM_ERROR("PSP load soc drv failed!\n"); 20836ff34fd6SJohn Clements return ret; 20846ff34fd6SJohn Clements } 20856ff34fd6SJohn Clements } 20866ff34fd6SJohn Clements 20876ff34fd6SJohn Clements if ((is_psp_fw_valid(psp->intf_drv)) && 20886ff34fd6SJohn Clements (psp->funcs->bootloader_load_intf_drv != NULL)) { 20896ff34fd6SJohn Clements ret = psp_bootloader_load_intf_drv(psp); 20906ff34fd6SJohn Clements if (ret) { 20916ff34fd6SJohn Clements DRM_ERROR("PSP load intf drv failed!\n"); 20926ff34fd6SJohn Clements return ret; 20936ff34fd6SJohn Clements } 20946ff34fd6SJohn Clements } 20956ff34fd6SJohn Clements 20966ff34fd6SJohn Clements if ((is_psp_fw_valid(psp->dbg_drv)) && 20976ff34fd6SJohn Clements (psp->funcs->bootloader_load_dbg_drv != NULL)) { 20986ff34fd6SJohn Clements ret = psp_bootloader_load_dbg_drv(psp); 20996ff34fd6SJohn Clements if (ret) { 21006ff34fd6SJohn Clements DRM_ERROR("PSP load dbg drv failed!\n"); 21016ff34fd6SJohn Clements return ret; 21026ff34fd6SJohn Clements } 21036ff34fd6SJohn Clements } 21046ff34fd6SJohn Clements 2105222e0a71SCandice Li if ((is_psp_fw_valid(psp->sos)) && 2106222e0a71SCandice Li (psp->funcs->bootloader_load_sos != NULL)) { 21077a3d7bf6SEvan Quan ret = psp_bootloader_load_sos(psp); 21087a3d7bf6SEvan Quan if (ret) { 21097a3d7bf6SEvan Quan DRM_ERROR("PSP load sos failed!\n"); 2110be70bbdaSHuang Rui return ret; 21117a3d7bf6SEvan Quan } 21127a3d7bf6SEvan Quan } 2113222e0a71SCandice Li } 21147a3d7bf6SEvan Quan 21157a3d7bf6SEvan Quan ret = psp_ring_create(psp, PSP_RING_TYPE__KM); 21167a3d7bf6SEvan Quan if (ret) { 21177a3d7bf6SEvan Quan DRM_ERROR("PSP create ring failed!\n"); 21187a3d7bf6SEvan Quan return ret; 21197a3d7bf6SEvan Quan } 21200e5ca0d1SHuang Rui 2121fba08a77SHawking Zhang ret = psp_tmr_init(psp); 2122fba08a77SHawking Zhang if (ret) { 2123fba08a77SHawking Zhang DRM_ERROR("PSP tmr init failed!\n"); 2124fba08a77SHawking Zhang return ret; 2125fba08a77SHawking Zhang } 2126fba08a77SHawking Zhang 2127995da6ccSEvan Quan /* 212840e611bdSJohn Clements * For ASICs with DF Cstate management centralized 2129995da6ccSEvan Quan * to PMFW, TMR setup should be performed after PMFW 2130995da6ccSEvan Quan * loaded and before other non-psp firmware loaded. 2131995da6ccSEvan Quan */ 213240e611bdSJohn Clements if (psp->pmfw_centralized_cstate_management) { 213340e611bdSJohn Clements ret = psp_load_smu_fw(psp); 213440e611bdSJohn Clements if (ret) 213540e611bdSJohn Clements return ret; 213640e611bdSJohn Clements } 213740e611bdSJohn Clements 2138be70bbdaSHuang Rui ret = psp_tmr_load(psp); 21397a3d7bf6SEvan Quan if (ret) { 21407a3d7bf6SEvan Quan DRM_ERROR("PSP load tmr failed!\n"); 2141be70bbdaSHuang Rui return ret; 21427a3d7bf6SEvan Quan } 21430e5ca0d1SHuang Rui 2144be70bbdaSHuang Rui return 0; 2145be70bbdaSHuang Rui } 2146be70bbdaSHuang Rui 2147be4630d9SHawking Zhang static int psp_get_fw_type(struct amdgpu_firmware_info *ucode, 2148be4630d9SHawking Zhang enum psp_gfx_fw_type *type) 2149be4630d9SHawking Zhang { 2150be4630d9SHawking Zhang switch (ucode->ucode_id) { 2151be4630d9SHawking Zhang case AMDGPU_UCODE_ID_SDMA0: 2152be4630d9SHawking Zhang *type = GFX_FW_TYPE_SDMA0; 2153be4630d9SHawking Zhang break; 2154be4630d9SHawking Zhang case AMDGPU_UCODE_ID_SDMA1: 2155be4630d9SHawking Zhang *type = GFX_FW_TYPE_SDMA1; 2156be4630d9SHawking Zhang break; 2157b86f8d8bSJohn Clements case AMDGPU_UCODE_ID_SDMA2: 2158b86f8d8bSJohn Clements *type = GFX_FW_TYPE_SDMA2; 2159b86f8d8bSJohn Clements break; 2160b86f8d8bSJohn Clements case AMDGPU_UCODE_ID_SDMA3: 2161b86f8d8bSJohn Clements *type = GFX_FW_TYPE_SDMA3; 2162b86f8d8bSJohn Clements break; 2163b86f8d8bSJohn Clements case AMDGPU_UCODE_ID_SDMA4: 2164b86f8d8bSJohn Clements *type = GFX_FW_TYPE_SDMA4; 2165b86f8d8bSJohn Clements break; 2166b86f8d8bSJohn Clements case AMDGPU_UCODE_ID_SDMA5: 2167b86f8d8bSJohn Clements *type = GFX_FW_TYPE_SDMA5; 2168b86f8d8bSJohn Clements break; 2169b86f8d8bSJohn Clements case AMDGPU_UCODE_ID_SDMA6: 2170b86f8d8bSJohn Clements *type = GFX_FW_TYPE_SDMA6; 2171b86f8d8bSJohn Clements break; 2172b86f8d8bSJohn Clements case AMDGPU_UCODE_ID_SDMA7: 2173b86f8d8bSJohn Clements *type = GFX_FW_TYPE_SDMA7; 2174b86f8d8bSJohn Clements break; 217593fd978bSJack Xiao case AMDGPU_UCODE_ID_CP_MES: 217693fd978bSJack Xiao *type = GFX_FW_TYPE_CP_MES; 217793fd978bSJack Xiao break; 217893fd978bSJack Xiao case AMDGPU_UCODE_ID_CP_MES_DATA: 217993fd978bSJack Xiao *type = GFX_FW_TYPE_MES_STACK; 218093fd978bSJack Xiao break; 2181be4630d9SHawking Zhang case AMDGPU_UCODE_ID_CP_CE: 2182be4630d9SHawking Zhang *type = GFX_FW_TYPE_CP_CE; 2183be4630d9SHawking Zhang break; 2184be4630d9SHawking Zhang case AMDGPU_UCODE_ID_CP_PFP: 2185be4630d9SHawking Zhang *type = GFX_FW_TYPE_CP_PFP; 2186be4630d9SHawking Zhang break; 2187be4630d9SHawking Zhang case AMDGPU_UCODE_ID_CP_ME: 2188be4630d9SHawking Zhang *type = GFX_FW_TYPE_CP_ME; 2189be4630d9SHawking Zhang break; 2190be4630d9SHawking Zhang case AMDGPU_UCODE_ID_CP_MEC1: 2191be4630d9SHawking Zhang *type = GFX_FW_TYPE_CP_MEC; 2192be4630d9SHawking Zhang break; 2193be4630d9SHawking Zhang case AMDGPU_UCODE_ID_CP_MEC1_JT: 2194be4630d9SHawking Zhang *type = GFX_FW_TYPE_CP_MEC_ME1; 2195be4630d9SHawking Zhang break; 2196be4630d9SHawking Zhang case AMDGPU_UCODE_ID_CP_MEC2: 2197be4630d9SHawking Zhang *type = GFX_FW_TYPE_CP_MEC; 2198be4630d9SHawking Zhang break; 2199be4630d9SHawking Zhang case AMDGPU_UCODE_ID_CP_MEC2_JT: 2200be4630d9SHawking Zhang *type = GFX_FW_TYPE_CP_MEC_ME2; 2201be4630d9SHawking Zhang break; 2202be4630d9SHawking Zhang case AMDGPU_UCODE_ID_RLC_G: 2203be4630d9SHawking Zhang *type = GFX_FW_TYPE_RLC_G; 2204be4630d9SHawking Zhang break; 2205be4630d9SHawking Zhang case AMDGPU_UCODE_ID_RLC_RESTORE_LIST_CNTL: 2206be4630d9SHawking Zhang *type = GFX_FW_TYPE_RLC_RESTORE_LIST_SRM_CNTL; 2207be4630d9SHawking Zhang break; 2208be4630d9SHawking Zhang case AMDGPU_UCODE_ID_RLC_RESTORE_LIST_GPM_MEM: 2209be4630d9SHawking Zhang *type = GFX_FW_TYPE_RLC_RESTORE_LIST_GPM_MEM; 2210be4630d9SHawking Zhang break; 2211be4630d9SHawking Zhang case AMDGPU_UCODE_ID_RLC_RESTORE_LIST_SRM_MEM: 2212be4630d9SHawking Zhang *type = GFX_FW_TYPE_RLC_RESTORE_LIST_SRM_MEM; 2213be4630d9SHawking Zhang break; 22145bab858eSLikun Gao case AMDGPU_UCODE_ID_RLC_IRAM: 22155bab858eSLikun Gao *type = GFX_FW_TYPE_RLC_IRAM; 22165bab858eSLikun Gao break; 22175bab858eSLikun Gao case AMDGPU_UCODE_ID_RLC_DRAM: 22185bab858eSLikun Gao *type = GFX_FW_TYPE_RLC_DRAM_BOOT; 22195bab858eSLikun Gao break; 2220be4630d9SHawking Zhang case AMDGPU_UCODE_ID_SMC: 2221be4630d9SHawking Zhang *type = GFX_FW_TYPE_SMU; 2222be4630d9SHawking Zhang break; 2223be4630d9SHawking Zhang case AMDGPU_UCODE_ID_UVD: 2224be4630d9SHawking Zhang *type = GFX_FW_TYPE_UVD; 2225be4630d9SHawking Zhang break; 2226be4630d9SHawking Zhang case AMDGPU_UCODE_ID_UVD1: 2227be4630d9SHawking Zhang *type = GFX_FW_TYPE_UVD1; 2228be4630d9SHawking Zhang break; 2229be4630d9SHawking Zhang case AMDGPU_UCODE_ID_VCE: 2230be4630d9SHawking Zhang *type = GFX_FW_TYPE_VCE; 2231be4630d9SHawking Zhang break; 2232be4630d9SHawking Zhang case AMDGPU_UCODE_ID_VCN: 2233be4630d9SHawking Zhang *type = GFX_FW_TYPE_VCN; 2234be4630d9SHawking Zhang break; 2235d83c7a07SJane Jian case AMDGPU_UCODE_ID_VCN1: 2236d83c7a07SJane Jian *type = GFX_FW_TYPE_VCN1; 2237d83c7a07SJane Jian break; 2238be4630d9SHawking Zhang case AMDGPU_UCODE_ID_DMCU_ERAM: 2239be4630d9SHawking Zhang *type = GFX_FW_TYPE_DMCU_ERAM; 2240be4630d9SHawking Zhang break; 2241be4630d9SHawking Zhang case AMDGPU_UCODE_ID_DMCU_INTV: 2242be4630d9SHawking Zhang *type = GFX_FW_TYPE_DMCU_ISR; 2243be4630d9SHawking Zhang break; 2244c76ff09bSJack Xiao case AMDGPU_UCODE_ID_VCN0_RAM: 2245c76ff09bSJack Xiao *type = GFX_FW_TYPE_VCN0_RAM; 2246c76ff09bSJack Xiao break; 2247c76ff09bSJack Xiao case AMDGPU_UCODE_ID_VCN1_RAM: 2248c76ff09bSJack Xiao *type = GFX_FW_TYPE_VCN1_RAM; 2249c76ff09bSJack Xiao break; 22502bd2a27fSNicholas Kazlauskas case AMDGPU_UCODE_ID_DMCUB: 22512bd2a27fSNicholas Kazlauskas *type = GFX_FW_TYPE_DMUB; 22522bd2a27fSNicholas Kazlauskas break; 2253be4630d9SHawking Zhang case AMDGPU_UCODE_ID_MAXIMUM: 2254be4630d9SHawking Zhang default: 2255be4630d9SHawking Zhang return -EINVAL; 2256be4630d9SHawking Zhang } 2257be4630d9SHawking Zhang 2258be4630d9SHawking Zhang return 0; 2259be4630d9SHawking Zhang } 2260be4630d9SHawking Zhang 2261c5fb9126SXiaojie Yuan static void psp_print_fw_hdr(struct psp_context *psp, 2262c5fb9126SXiaojie Yuan struct amdgpu_firmware_info *ucode) 2263c5fb9126SXiaojie Yuan { 2264c5fb9126SXiaojie Yuan struct amdgpu_device *adev = psp->adev; 2265bfa603aaSXiaojie Yuan struct common_firmware_header *hdr; 2266c5fb9126SXiaojie Yuan 2267c5fb9126SXiaojie Yuan switch (ucode->ucode_id) { 2268c5fb9126SXiaojie Yuan case AMDGPU_UCODE_ID_SDMA0: 2269c5fb9126SXiaojie Yuan case AMDGPU_UCODE_ID_SDMA1: 2270c5fb9126SXiaojie Yuan case AMDGPU_UCODE_ID_SDMA2: 2271c5fb9126SXiaojie Yuan case AMDGPU_UCODE_ID_SDMA3: 2272c5fb9126SXiaojie Yuan case AMDGPU_UCODE_ID_SDMA4: 2273c5fb9126SXiaojie Yuan case AMDGPU_UCODE_ID_SDMA5: 2274c5fb9126SXiaojie Yuan case AMDGPU_UCODE_ID_SDMA6: 2275c5fb9126SXiaojie Yuan case AMDGPU_UCODE_ID_SDMA7: 2276bfa603aaSXiaojie Yuan hdr = (struct common_firmware_header *) 2277bfa603aaSXiaojie Yuan adev->sdma.instance[ucode->ucode_id - AMDGPU_UCODE_ID_SDMA0].fw->data; 2278bfa603aaSXiaojie Yuan amdgpu_ucode_print_sdma_hdr(hdr); 2279c5fb9126SXiaojie Yuan break; 2280c5fb9126SXiaojie Yuan case AMDGPU_UCODE_ID_CP_CE: 2281bfa603aaSXiaojie Yuan hdr = (struct common_firmware_header *)adev->gfx.ce_fw->data; 2282bfa603aaSXiaojie Yuan amdgpu_ucode_print_gfx_hdr(hdr); 2283c5fb9126SXiaojie Yuan break; 2284c5fb9126SXiaojie Yuan case AMDGPU_UCODE_ID_CP_PFP: 2285bfa603aaSXiaojie Yuan hdr = (struct common_firmware_header *)adev->gfx.pfp_fw->data; 2286bfa603aaSXiaojie Yuan amdgpu_ucode_print_gfx_hdr(hdr); 2287c5fb9126SXiaojie Yuan break; 2288c5fb9126SXiaojie Yuan case AMDGPU_UCODE_ID_CP_ME: 2289bfa603aaSXiaojie Yuan hdr = (struct common_firmware_header *)adev->gfx.me_fw->data; 2290bfa603aaSXiaojie Yuan amdgpu_ucode_print_gfx_hdr(hdr); 2291c5fb9126SXiaojie Yuan break; 2292c5fb9126SXiaojie Yuan case AMDGPU_UCODE_ID_CP_MEC1: 2293bfa603aaSXiaojie Yuan hdr = (struct common_firmware_header *)adev->gfx.mec_fw->data; 2294bfa603aaSXiaojie Yuan amdgpu_ucode_print_gfx_hdr(hdr); 2295c5fb9126SXiaojie Yuan break; 2296c5fb9126SXiaojie Yuan case AMDGPU_UCODE_ID_RLC_G: 2297bfa603aaSXiaojie Yuan hdr = (struct common_firmware_header *)adev->gfx.rlc_fw->data; 2298bfa603aaSXiaojie Yuan amdgpu_ucode_print_rlc_hdr(hdr); 2299c5fb9126SXiaojie Yuan break; 2300c5fb9126SXiaojie Yuan case AMDGPU_UCODE_ID_SMC: 2301bfa603aaSXiaojie Yuan hdr = (struct common_firmware_header *)adev->pm.fw->data; 2302bfa603aaSXiaojie Yuan amdgpu_ucode_print_smc_hdr(hdr); 2303c5fb9126SXiaojie Yuan break; 2304c5fb9126SXiaojie Yuan default: 2305c5fb9126SXiaojie Yuan break; 2306c5fb9126SXiaojie Yuan } 2307c5fb9126SXiaojie Yuan } 2308c5fb9126SXiaojie Yuan 2309be4630d9SHawking Zhang static int psp_prep_load_ip_fw_cmd_buf(struct amdgpu_firmware_info *ucode, 2310be4630d9SHawking Zhang struct psp_gfx_cmd_resp *cmd) 2311be4630d9SHawking Zhang { 2312be4630d9SHawking Zhang int ret; 2313be4630d9SHawking Zhang uint64_t fw_mem_mc_addr = ucode->mc_addr; 2314be4630d9SHawking Zhang 2315be4630d9SHawking Zhang memset(cmd, 0, sizeof(struct psp_gfx_cmd_resp)); 2316be4630d9SHawking Zhang 2317be4630d9SHawking Zhang cmd->cmd_id = GFX_CMD_ID_LOAD_IP_FW; 2318be4630d9SHawking Zhang cmd->cmd.cmd_load_ip_fw.fw_phy_addr_lo = lower_32_bits(fw_mem_mc_addr); 2319be4630d9SHawking Zhang cmd->cmd.cmd_load_ip_fw.fw_phy_addr_hi = upper_32_bits(fw_mem_mc_addr); 2320be4630d9SHawking Zhang cmd->cmd.cmd_load_ip_fw.fw_size = ucode->ucode_size; 2321be4630d9SHawking Zhang 2322be4630d9SHawking Zhang ret = psp_get_fw_type(ucode, &cmd->cmd.cmd_load_ip_fw.fw_type); 2323be4630d9SHawking Zhang if (ret) 2324be4630d9SHawking Zhang DRM_ERROR("Unknown firmware type\n"); 2325be4630d9SHawking Zhang 2326be4630d9SHawking Zhang return ret; 2327be4630d9SHawking Zhang } 2328be4630d9SHawking Zhang 2329cd5955f4SOak Zeng static int psp_execute_non_psp_fw_load(struct psp_context *psp, 233013169562SHuang Rui struct amdgpu_firmware_info *ucode) 233113169562SHuang Rui { 233213169562SHuang Rui int ret = 0; 233313169562SHuang Rui 233413169562SHuang Rui ret = psp_prep_load_ip_fw_cmd_buf(ucode, psp->cmd); 233513169562SHuang Rui if (ret) 233613169562SHuang Rui return ret; 233713169562SHuang Rui 233813169562SHuang Rui ret = psp_cmd_submit_buf(psp, ucode, psp->cmd, 233913169562SHuang Rui psp->fence_buf_mc_addr); 234013169562SHuang Rui 234113169562SHuang Rui return ret; 234213169562SHuang Rui } 234313169562SHuang Rui 234440e611bdSJohn Clements static int psp_load_smu_fw(struct psp_context *psp) 2345be70bbdaSHuang Rui { 234640e611bdSJohn Clements int ret; 23477f70443fSJohn Clements struct amdgpu_device *adev = psp->adev; 234840e611bdSJohn Clements struct amdgpu_firmware_info *ucode = 23497f70443fSJohn Clements &adev->firmware.ucode[AMDGPU_UCODE_ID_SMC]; 23500bcfa78cSLikun Gao struct amdgpu_ras *ras = psp->ras.ras; 23510e5ca0d1SHuang Rui 235240e611bdSJohn Clements if (!ucode->fw || amdgpu_sriov_vf(psp->adev)) 235340e611bdSJohn Clements return 0; 235413169562SHuang Rui 23551689fca0SEvan Quan if ((amdgpu_in_reset(adev) && 23568ab0d6f0SLuben Tuikov ras && adev->ras_enabled && 23574a7ffbdbSChengming Gui (adev->asic_type == CHIP_ARCTURUS || 23585f0f1727SEvan Quan adev->asic_type == CHIP_VEGA20))) { 23597f70443fSJohn Clements ret = amdgpu_dpm_set_mp1_state(adev, PP_MP1_STATE_UNLOAD); 23607f70443fSJohn Clements if (ret) { 23617f70443fSJohn Clements DRM_WARN("Failed to set MP1 state prepare for reload\n"); 23627f70443fSJohn Clements } 23637f70443fSJohn Clements } 23647f70443fSJohn Clements 2365cd5955f4SOak Zeng ret = psp_execute_non_psp_fw_load(psp, ucode); 236640e611bdSJohn Clements 236713169562SHuang Rui if (ret) 236840e611bdSJohn Clements DRM_ERROR("PSP load smu failed!\n"); 236940e611bdSJohn Clements 237013169562SHuang Rui return ret; 237113169562SHuang Rui } 237213169562SHuang Rui 237340e611bdSJohn Clements static bool fw_load_skip_check(struct psp_context *psp, 237440e611bdSJohn Clements struct amdgpu_firmware_info *ucode) 237540e611bdSJohn Clements { 23760e5ca0d1SHuang Rui if (!ucode->fw) 237740e611bdSJohn Clements return true; 23780e5ca0d1SHuang Rui 23790e5ca0d1SHuang Rui if (ucode->ucode_id == AMDGPU_UCODE_ID_SMC && 2380995da6ccSEvan Quan (psp_smu_reload_quirk(psp) || 2381995da6ccSEvan Quan psp->autoload_supported || 2382995da6ccSEvan Quan psp->pmfw_centralized_cstate_management)) 238340e611bdSJohn Clements return true; 2384b86f8d8bSJohn Clements 238540e611bdSJohn Clements if (amdgpu_sriov_vf(psp->adev) && 2386e993ca4fSDaniel Wang (ucode->ucode_id == AMDGPU_UCODE_ID_SDMA0 2387e993ca4fSDaniel Wang || ucode->ucode_id == AMDGPU_UCODE_ID_SDMA1 2388b86f8d8bSJohn Clements || ucode->ucode_id == AMDGPU_UCODE_ID_SDMA2 2389b86f8d8bSJohn Clements || ucode->ucode_id == AMDGPU_UCODE_ID_SDMA3 2390b86f8d8bSJohn Clements || ucode->ucode_id == AMDGPU_UCODE_ID_SDMA4 2391b86f8d8bSJohn Clements || ucode->ucode_id == AMDGPU_UCODE_ID_SDMA5 2392b86f8d8bSJohn Clements || ucode->ucode_id == AMDGPU_UCODE_ID_SDMA6 2393b86f8d8bSJohn Clements || ucode->ucode_id == AMDGPU_UCODE_ID_SDMA7 2394c348ad46SJack Zhang || ucode->ucode_id == AMDGPU_UCODE_ID_RLC_G 2395c348ad46SJack Zhang || ucode->ucode_id == AMDGPU_UCODE_ID_RLC_RESTORE_LIST_CNTL 2396c348ad46SJack Zhang || ucode->ucode_id == AMDGPU_UCODE_ID_RLC_RESTORE_LIST_GPM_MEM 2397c2a801afSJack Zhang || ucode->ucode_id == AMDGPU_UCODE_ID_RLC_RESTORE_LIST_SRM_MEM 2398c2a801afSJack Zhang || ucode->ucode_id == AMDGPU_UCODE_ID_SMC)) 2399e993ca4fSDaniel Wang /*skip ucode loading in SRIOV VF */ 240040e611bdSJohn Clements return true; 2401b86f8d8bSJohn Clements 2402119eb6dbSHawking Zhang if (psp->autoload_supported && 2403119eb6dbSHawking Zhang (ucode->ucode_id == AMDGPU_UCODE_ID_CP_MEC1_JT || 2404119eb6dbSHawking Zhang ucode->ucode_id == AMDGPU_UCODE_ID_CP_MEC2_JT)) 2405119eb6dbSHawking Zhang /* skip mec JT when autoload is enabled */ 240640e611bdSJohn Clements return true; 240740e611bdSJohn Clements 240840e611bdSJohn Clements return false; 240940e611bdSJohn Clements } 241040e611bdSJohn Clements 2411a2052839SLijo Lazar int psp_load_fw_list(struct psp_context *psp, 2412a2052839SLijo Lazar struct amdgpu_firmware_info **ucode_list, int ucode_count) 2413a2052839SLijo Lazar { 2414a2052839SLijo Lazar int ret = 0, i; 2415a2052839SLijo Lazar struct amdgpu_firmware_info *ucode; 2416a2052839SLijo Lazar 2417a2052839SLijo Lazar for (i = 0; i < ucode_count; ++i) { 2418a2052839SLijo Lazar ucode = ucode_list[i]; 2419a2052839SLijo Lazar psp_print_fw_hdr(psp, ucode); 2420cd5955f4SOak Zeng ret = psp_execute_non_psp_fw_load(psp, ucode); 2421a2052839SLijo Lazar if (ret) 2422a2052839SLijo Lazar return ret; 2423a2052839SLijo Lazar } 2424a2052839SLijo Lazar return ret; 2425a2052839SLijo Lazar } 2426a2052839SLijo Lazar 2427cd5955f4SOak Zeng static int psp_load_non_psp_fw(struct psp_context *psp) 242840e611bdSJohn Clements { 242940e611bdSJohn Clements int i, ret; 243040e611bdSJohn Clements struct amdgpu_firmware_info *ucode; 243140e611bdSJohn Clements struct amdgpu_device *adev = psp->adev; 243240e611bdSJohn Clements 243340e611bdSJohn Clements if (psp->autoload_supported && 243440e611bdSJohn Clements !psp->pmfw_centralized_cstate_management) { 243540e611bdSJohn Clements ret = psp_load_smu_fw(psp); 243640e611bdSJohn Clements if (ret) 243740e611bdSJohn Clements return ret; 243840e611bdSJohn Clements } 243940e611bdSJohn Clements 244040e611bdSJohn Clements for (i = 0; i < adev->firmware.max_ucodes; i++) { 244140e611bdSJohn Clements ucode = &adev->firmware.ucode[i]; 244240e611bdSJohn Clements 244340e611bdSJohn Clements if (ucode->ucode_id == AMDGPU_UCODE_ID_SMC && 244440e611bdSJohn Clements !fw_load_skip_check(psp, ucode)) { 244540e611bdSJohn Clements ret = psp_load_smu_fw(psp); 244640e611bdSJohn Clements if (ret) 244740e611bdSJohn Clements return ret; 244840e611bdSJohn Clements continue; 244940e611bdSJohn Clements } 245040e611bdSJohn Clements 245140e611bdSJohn Clements if (fw_load_skip_check(psp, ucode)) 2452119eb6dbSHawking Zhang continue; 24530e5ca0d1SHuang Rui 2454738c822cSLikun Gao if (psp->autoload_supported && 2455462c272bSTao Zhou (adev->asic_type >= CHIP_SIENNA_CICHLID && 2456462c272bSTao Zhou adev->asic_type <= CHIP_DIMGREY_CAVEFISH) && 2457738c822cSLikun Gao (ucode->ucode_id == AMDGPU_UCODE_ID_SDMA1 || 2458738c822cSLikun Gao ucode->ucode_id == AMDGPU_UCODE_ID_SDMA2 || 2459738c822cSLikun Gao ucode->ucode_id == AMDGPU_UCODE_ID_SDMA3)) 2460738c822cSLikun Gao /* PSP only receive one SDMA fw for sienna_cichlid, 2461738c822cSLikun Gao * as all four sdma fw are same */ 2462738c822cSLikun Gao continue; 2463738c822cSLikun Gao 2464c5fb9126SXiaojie Yuan psp_print_fw_hdr(psp, ucode); 2465c5fb9126SXiaojie Yuan 2466cd5955f4SOak Zeng ret = psp_execute_non_psp_fw_load(psp, ucode); 24670e5ca0d1SHuang Rui if (ret) 2468be70bbdaSHuang Rui return ret; 24690e5ca0d1SHuang Rui 24701a5b4ccaSHawking Zhang /* Start rlc autoload after psp recieved all the gfx firmware */ 24716de40f02SMonk Liu if (psp->autoload_supported && ucode->ucode_id == (amdgpu_sriov_vf(adev) ? 24720753e56eSEvan Quan AMDGPU_UCODE_ID_CP_MEC2 : AMDGPU_UCODE_ID_RLC_G)) { 2473999a69e2SHawking Zhang ret = psp_rlc_autoload_start(psp); 24741a5b4ccaSHawking Zhang if (ret) { 24751a5b4ccaSHawking Zhang DRM_ERROR("Failed to start rlc autoload\n"); 24761a5b4ccaSHawking Zhang return ret; 24771a5b4ccaSHawking Zhang } 24781a5b4ccaSHawking Zhang } 24790e5ca0d1SHuang Rui } 24800e5ca0d1SHuang Rui 2481be70bbdaSHuang Rui return 0; 2482be70bbdaSHuang Rui } 2483be70bbdaSHuang Rui 24840e5ca0d1SHuang Rui static int psp_load_fw(struct amdgpu_device *adev) 24850e5ca0d1SHuang Rui { 24860e5ca0d1SHuang Rui int ret; 24870e5ca0d1SHuang Rui struct psp_context *psp = &adev->psp; 24880e5ca0d1SHuang Rui 248953b3f8f4SDennis Li if (amdgpu_sriov_vf(adev) && amdgpu_in_reset(adev)) { 249014d20ec7Swentalou psp_ring_stop(psp, PSP_RING_TYPE__KM); /* should not destroy ring, only stop */ 249177a3c96bSMonk Liu goto skip_memalloc; 249253450efdSXiangliang Yu } 249377a3c96bSMonk Liu 2494e1944debSZhigang Luo if (amdgpu_sriov_vf(adev)) { 2495e1944debSZhigang Luo ret = amdgpu_bo_create_kernel(adev, PSP_1_MEG, PSP_1_MEG, 2496e1944debSZhigang Luo AMDGPU_GEM_DOMAIN_VRAM, 2497e1944debSZhigang Luo &psp->fw_pri_bo, 2498e1944debSZhigang Luo &psp->fw_pri_mc_addr, 2499e1944debSZhigang Luo &psp->fw_pri_buf); 2500e1944debSZhigang Luo } else { 250153a5cf57SHuang Rui ret = amdgpu_bo_create_kernel(adev, PSP_1_MEG, PSP_1_MEG, 250253a5cf57SHuang Rui AMDGPU_GEM_DOMAIN_GTT, 250353a5cf57SHuang Rui &psp->fw_pri_bo, 250453a5cf57SHuang Rui &psp->fw_pri_mc_addr, 250553a5cf57SHuang Rui &psp->fw_pri_buf); 2506e1944debSZhigang Luo } 2507e1944debSZhigang Luo 25080e5ca0d1SHuang Rui if (ret) 25090e5ca0d1SHuang Rui goto failed; 25100e5ca0d1SHuang Rui 25110e5ca0d1SHuang Rui ret = amdgpu_bo_create_kernel(adev, PSP_FENCE_BUFFER_SIZE, PAGE_SIZE, 25120e5ca0d1SHuang Rui AMDGPU_GEM_DOMAIN_VRAM, 25130e5ca0d1SHuang Rui &psp->fence_buf_bo, 25140e5ca0d1SHuang Rui &psp->fence_buf_mc_addr, 25150e5ca0d1SHuang Rui &psp->fence_buf); 25160e5ca0d1SHuang Rui if (ret) 251737945a3aSEvan Quan goto failed; 2518a1952da7SHuang Rui 2519a1952da7SHuang Rui ret = amdgpu_bo_create_kernel(adev, PSP_CMD_BUFFER_SIZE, PAGE_SIZE, 2520a1952da7SHuang Rui AMDGPU_GEM_DOMAIN_VRAM, 2521a1952da7SHuang Rui &psp->cmd_buf_bo, &psp->cmd_buf_mc_addr, 2522a1952da7SHuang Rui (void **)&psp->cmd_buf_mem); 2523a1952da7SHuang Rui if (ret) 252437945a3aSEvan Quan goto failed; 25250e5ca0d1SHuang Rui 25260e5ca0d1SHuang Rui memset(psp->fence_buf, 0, PSP_FENCE_BUFFER_SIZE); 25270e5ca0d1SHuang Rui 2528be70bbdaSHuang Rui ret = psp_ring_init(psp, PSP_RING_TYPE__KM); 25297a3d7bf6SEvan Quan if (ret) { 25307a3d7bf6SEvan Quan DRM_ERROR("PSP ring init failed!\n"); 253137945a3aSEvan Quan goto failed; 25327a3d7bf6SEvan Quan } 25330e5ca0d1SHuang Rui 253477a3c96bSMonk Liu skip_memalloc: 2535be70bbdaSHuang Rui ret = psp_hw_start(psp); 25360e5ca0d1SHuang Rui if (ret) 253737945a3aSEvan Quan goto failed; 25380e5ca0d1SHuang Rui 2539cd5955f4SOak Zeng ret = psp_load_non_psp_fw(psp); 25400e5ca0d1SHuang Rui if (ret) 254137945a3aSEvan Quan goto failed; 25420e5ca0d1SHuang Rui 25437091b60cSHawking Zhang ret = psp_asd_load(psp); 25447091b60cSHawking Zhang if (ret) { 25457091b60cSHawking Zhang DRM_ERROR("PSP load asd failed!\n"); 25467091b60cSHawking Zhang return ret; 25477091b60cSHawking Zhang } 25487091b60cSHawking Zhang 25490d2c1855SJohn Clements ret = psp_rl_load(adev); 25500d2c1855SJohn Clements if (ret) { 25510d2c1855SJohn Clements DRM_ERROR("PSP load RL failed!\n"); 25520d2c1855SJohn Clements return ret; 25530d2c1855SJohn Clements } 25540d2c1855SJohn Clements 25557091b60cSHawking Zhang if (psp->adev->psp.ta_fw) { 25567091b60cSHawking Zhang ret = psp_ras_initialize(psp); 25577091b60cSHawking Zhang if (ret) 25587091b60cSHawking Zhang dev_err(psp->adev->dev, 25597091b60cSHawking Zhang "RAS: Failed to initialize RAS\n"); 25607091b60cSHawking Zhang 25617091b60cSHawking Zhang ret = psp_hdcp_initialize(psp); 25627091b60cSHawking Zhang if (ret) 25637091b60cSHawking Zhang dev_err(psp->adev->dev, 25647091b60cSHawking Zhang "HDCP: Failed to initialize HDCP\n"); 25657091b60cSHawking Zhang 25667091b60cSHawking Zhang ret = psp_dtm_initialize(psp); 25677091b60cSHawking Zhang if (ret) 25687091b60cSHawking Zhang dev_err(psp->adev->dev, 25697091b60cSHawking Zhang "DTM: Failed to initialize DTM\n"); 25708602692bSWenhui Sheng 25718602692bSWenhui Sheng ret = psp_rap_initialize(psp); 25728602692bSWenhui Sheng if (ret) 25738602692bSWenhui Sheng dev_err(psp->adev->dev, 25748602692bSWenhui Sheng "RAP: Failed to initialize RAP\n"); 2575ecaafb7bSJinzhou Su 2576ecaafb7bSJinzhou Su ret = psp_securedisplay_initialize(psp); 2577ecaafb7bSJinzhou Su if (ret) 2578ecaafb7bSJinzhou Su dev_err(psp->adev->dev, 2579ecaafb7bSJinzhou Su "SECUREDISPLAY: Failed to initialize SECUREDISPLAY\n"); 25807091b60cSHawking Zhang } 25817091b60cSHawking Zhang 25820e5ca0d1SHuang Rui return 0; 25830e5ca0d1SHuang Rui 25840e5ca0d1SHuang Rui failed: 258537945a3aSEvan Quan /* 258637945a3aSEvan Quan * all cleanup jobs (xgmi terminate, ras terminate, 258737945a3aSEvan Quan * ring destroy, cmd/fence/fw buffers destory, 258837945a3aSEvan Quan * psp->cmd destory) are delayed to psp_hw_fini 258937945a3aSEvan Quan */ 25900e5ca0d1SHuang Rui return ret; 25910e5ca0d1SHuang Rui } 25920e5ca0d1SHuang Rui 25930e5ca0d1SHuang Rui static int psp_hw_init(void *handle) 25940e5ca0d1SHuang Rui { 25950e5ca0d1SHuang Rui int ret; 25960e5ca0d1SHuang Rui struct amdgpu_device *adev = (struct amdgpu_device *)handle; 25970e5ca0d1SHuang Rui 25980e5ca0d1SHuang Rui mutex_lock(&adev->firmware.mutex); 25996e13bdf6SRex Zhu /* 26006e13bdf6SRex Zhu * This sequence is just used on hw_init only once, no need on 26016e13bdf6SRex Zhu * resume. 26026e13bdf6SRex Zhu */ 26036e13bdf6SRex Zhu ret = amdgpu_ucode_init_bo(adev); 26046e13bdf6SRex Zhu if (ret) 26056e13bdf6SRex Zhu goto failed; 26060e5ca0d1SHuang Rui 26070e5ca0d1SHuang Rui ret = psp_load_fw(adev); 26080e5ca0d1SHuang Rui if (ret) { 26090e5ca0d1SHuang Rui DRM_ERROR("PSP firmware loading failed\n"); 26100e5ca0d1SHuang Rui goto failed; 26110e5ca0d1SHuang Rui } 26120e5ca0d1SHuang Rui 26130e5ca0d1SHuang Rui mutex_unlock(&adev->firmware.mutex); 261403597b47SKevin Wang return 0; 26150e5ca0d1SHuang Rui 26160e5ca0d1SHuang Rui failed: 26170e5ca0d1SHuang Rui adev->firmware.load_type = AMDGPU_FW_LOAD_DIRECT; 26180e5ca0d1SHuang Rui mutex_unlock(&adev->firmware.mutex); 26190e5ca0d1SHuang Rui return -EINVAL; 26200e5ca0d1SHuang Rui } 26210e5ca0d1SHuang Rui 26220e5ca0d1SHuang Rui static int psp_hw_fini(void *handle) 26230e5ca0d1SHuang Rui { 26240e5ca0d1SHuang Rui struct amdgpu_device *adev = (struct amdgpu_device *)handle; 26250e5ca0d1SHuang Rui struct psp_context *psp = &adev->psp; 26260e5ca0d1SHuang Rui 2627ed19a9a2SBhawanpreet Lakha if (psp->adev->psp.ta_fw) { 26285e5d3154Sxinhui pan psp_ras_terminate(psp); 2629ecaafb7bSJinzhou Su psp_securedisplay_terminate(psp); 26308602692bSWenhui Sheng psp_rap_terminate(psp); 2631143f2305SBhawanpreet Lakha psp_dtm_terminate(psp); 2632ed19a9a2SBhawanpreet Lakha psp_hdcp_terminate(psp); 2633ed19a9a2SBhawanpreet Lakha } 26345e5d3154Sxinhui pan 263571e5f0cbSHawking Zhang psp_asd_unload(psp); 263671e5f0cbSHawking Zhang 263790937420SHuang Rui psp_tmr_terminate(psp); 2638e3c5e982STrigger Huang psp_ring_destroy(psp, PSP_RING_TYPE__KM); 2639e3c5e982STrigger Huang 264053a5cf57SHuang Rui amdgpu_bo_free_kernel(&psp->fw_pri_bo, 264153a5cf57SHuang Rui &psp->fw_pri_mc_addr, &psp->fw_pri_buf); 2642b4de2c5aSHuang Rui amdgpu_bo_free_kernel(&psp->fence_buf_bo, 2643b4de2c5aSHuang Rui &psp->fence_buf_mc_addr, &psp->fence_buf); 2644a1952da7SHuang Rui amdgpu_bo_free_kernel(&psp->cmd_buf_bo, &psp->cmd_buf_mc_addr, 2645a1952da7SHuang Rui (void **)&psp->cmd_buf_mem); 2646b4de2c5aSHuang Rui 26470e5ca0d1SHuang Rui return 0; 26480e5ca0d1SHuang Rui } 26490e5ca0d1SHuang Rui 26500e5ca0d1SHuang Rui static int psp_suspend(void *handle) 26510e5ca0d1SHuang Rui { 2652bcd6eab8SEvan Quan int ret; 2653bcd6eab8SEvan Quan struct amdgpu_device *adev = (struct amdgpu_device *)handle; 2654bcd6eab8SEvan Quan struct psp_context *psp = &adev->psp; 2655bcd6eab8SEvan Quan 26563e2e2ab5SHawking Zhang if (adev->gmc.xgmi.num_physical_nodes > 1 && 26573e2e2ab5SHawking Zhang psp->xgmi_context.initialized == 1) { 26583e2e2ab5SHawking Zhang ret = psp_xgmi_terminate(psp); 26593e2e2ab5SHawking Zhang if (ret) { 26603e2e2ab5SHawking Zhang DRM_ERROR("Failed to terminate xgmi ta\n"); 26613e2e2ab5SHawking Zhang return ret; 26623e2e2ab5SHawking Zhang } 26633e2e2ab5SHawking Zhang } 26643e2e2ab5SHawking Zhang 266554eb4ed6Sxinhui pan if (psp->adev->psp.ta_fw) { 26665e5d3154Sxinhui pan ret = psp_ras_terminate(psp); 26675e5d3154Sxinhui pan if (ret) { 26685e5d3154Sxinhui pan DRM_ERROR("Failed to terminate ras ta\n"); 26695e5d3154Sxinhui pan return ret; 26705e5d3154Sxinhui pan } 2671ed19a9a2SBhawanpreet Lakha ret = psp_hdcp_terminate(psp); 2672ed19a9a2SBhawanpreet Lakha if (ret) { 2673ed19a9a2SBhawanpreet Lakha DRM_ERROR("Failed to terminate hdcp ta\n"); 2674ed19a9a2SBhawanpreet Lakha return ret; 2675ed19a9a2SBhawanpreet Lakha } 2676143f2305SBhawanpreet Lakha ret = psp_dtm_terminate(psp); 2677143f2305SBhawanpreet Lakha if (ret) { 2678143f2305SBhawanpreet Lakha DRM_ERROR("Failed to terminate dtm ta\n"); 2679143f2305SBhawanpreet Lakha return ret; 2680143f2305SBhawanpreet Lakha } 26818602692bSWenhui Sheng ret = psp_rap_terminate(psp); 26828602692bSWenhui Sheng if (ret) { 26838602692bSWenhui Sheng DRM_ERROR("Failed to terminate rap ta\n"); 26848602692bSWenhui Sheng return ret; 26858602692bSWenhui Sheng } 2686ecaafb7bSJinzhou Su ret = psp_securedisplay_terminate(psp); 2687ecaafb7bSJinzhou Su if (ret) { 2688ecaafb7bSJinzhou Su DRM_ERROR("Failed to terminate securedisplay ta\n"); 2689ecaafb7bSJinzhou Su return ret; 2690ecaafb7bSJinzhou Su } 269154eb4ed6Sxinhui pan } 26925e5d3154Sxinhui pan 2693429f3d24SHuang Rui ret = psp_asd_unload(psp); 2694429f3d24SHuang Rui if (ret) { 2695429f3d24SHuang Rui DRM_ERROR("Failed to unload asd\n"); 2696429f3d24SHuang Rui return ret; 2697429f3d24SHuang Rui } 2698429f3d24SHuang Rui 269990937420SHuang Rui ret = psp_tmr_terminate(psp); 270090937420SHuang Rui if (ret) { 27014afaa61dSColin Ian King DRM_ERROR("Failed to terminate tmr\n"); 270290937420SHuang Rui return ret; 270390937420SHuang Rui } 270490937420SHuang Rui 2705bcd6eab8SEvan Quan ret = psp_ring_stop(psp, PSP_RING_TYPE__KM); 2706bcd6eab8SEvan Quan if (ret) { 2707bcd6eab8SEvan Quan DRM_ERROR("PSP ring stop failed\n"); 2708bcd6eab8SEvan Quan return ret; 2709bcd6eab8SEvan Quan } 2710bcd6eab8SEvan Quan 27110e5ca0d1SHuang Rui return 0; 27120e5ca0d1SHuang Rui } 27130e5ca0d1SHuang Rui 27140e5ca0d1SHuang Rui static int psp_resume(void *handle) 27150e5ca0d1SHuang Rui { 27160e5ca0d1SHuang Rui int ret; 27170e5ca0d1SHuang Rui struct amdgpu_device *adev = (struct amdgpu_device *)handle; 271893ea9b9fSHuang Rui struct psp_context *psp = &adev->psp; 27190e5ca0d1SHuang Rui 272093ea9b9fSHuang Rui DRM_INFO("PSP is resuming...\n"); 272193ea9b9fSHuang Rui 27223a07101bSHawking Zhang if (psp->mem_train_ctx.enable_mem_training) { 27230586a059STianci.Yin ret = psp_mem_training(psp, PSP_MEM_TRAIN_RESUME); 27240586a059STianci.Yin if (ret) { 27250586a059STianci.Yin DRM_ERROR("Failed to process memory training!\n"); 27260586a059STianci.Yin return ret; 27270586a059STianci.Yin } 27283a07101bSHawking Zhang } 27290586a059STianci.Yin 27300e5ca0d1SHuang Rui mutex_lock(&adev->firmware.mutex); 27310e5ca0d1SHuang Rui 273293ea9b9fSHuang Rui ret = psp_hw_start(psp); 27330e5ca0d1SHuang Rui if (ret) 273493ea9b9fSHuang Rui goto failed; 273593ea9b9fSHuang Rui 2736cd5955f4SOak Zeng ret = psp_load_non_psp_fw(psp); 273793ea9b9fSHuang Rui if (ret) 273893ea9b9fSHuang Rui goto failed; 27390e5ca0d1SHuang Rui 27400d6f39bbSHawking Zhang ret = psp_asd_load(psp); 27410d6f39bbSHawking Zhang if (ret) { 27420d6f39bbSHawking Zhang DRM_ERROR("PSP load asd failed!\n"); 27430d6f39bbSHawking Zhang goto failed; 27440d6f39bbSHawking Zhang } 27450d6f39bbSHawking Zhang 27460d6f39bbSHawking Zhang if (adev->gmc.xgmi.num_physical_nodes > 1) { 27470d6f39bbSHawking Zhang ret = psp_xgmi_initialize(psp); 27480d6f39bbSHawking Zhang /* Warning the XGMI seesion initialize failure 27490d6f39bbSHawking Zhang * Instead of stop driver initialization 27500d6f39bbSHawking Zhang */ 27510d6f39bbSHawking Zhang if (ret) 27520d6f39bbSHawking Zhang dev_err(psp->adev->dev, 27530d6f39bbSHawking Zhang "XGMI: Failed to initialize XGMI session\n"); 27540d6f39bbSHawking Zhang } 27550d6f39bbSHawking Zhang 27560d6f39bbSHawking Zhang if (psp->adev->psp.ta_fw) { 27570d6f39bbSHawking Zhang ret = psp_ras_initialize(psp); 27580d6f39bbSHawking Zhang if (ret) 27590d6f39bbSHawking Zhang dev_err(psp->adev->dev, 27600d6f39bbSHawking Zhang "RAS: Failed to initialize RAS\n"); 27610d6f39bbSHawking Zhang 27620d6f39bbSHawking Zhang ret = psp_hdcp_initialize(psp); 27630d6f39bbSHawking Zhang if (ret) 27640d6f39bbSHawking Zhang dev_err(psp->adev->dev, 27650d6f39bbSHawking Zhang "HDCP: Failed to initialize HDCP\n"); 27660d6f39bbSHawking Zhang 27670d6f39bbSHawking Zhang ret = psp_dtm_initialize(psp); 27680d6f39bbSHawking Zhang if (ret) 27690d6f39bbSHawking Zhang dev_err(psp->adev->dev, 27700d6f39bbSHawking Zhang "DTM: Failed to initialize DTM\n"); 27718602692bSWenhui Sheng 27728602692bSWenhui Sheng ret = psp_rap_initialize(psp); 27738602692bSWenhui Sheng if (ret) 27748602692bSWenhui Sheng dev_err(psp->adev->dev, 27758602692bSWenhui Sheng "RAP: Failed to initialize RAP\n"); 2776ecaafb7bSJinzhou Su 2777ecaafb7bSJinzhou Su ret = psp_securedisplay_initialize(psp); 2778ecaafb7bSJinzhou Su if (ret) 2779ecaafb7bSJinzhou Su dev_err(psp->adev->dev, 2780ecaafb7bSJinzhou Su "SECUREDISPLAY: Failed to initialize SECUREDISPLAY\n"); 27810d6f39bbSHawking Zhang } 27820d6f39bbSHawking Zhang 27830e5ca0d1SHuang Rui mutex_unlock(&adev->firmware.mutex); 27840e5ca0d1SHuang Rui 278593ea9b9fSHuang Rui return 0; 278693ea9b9fSHuang Rui 278793ea9b9fSHuang Rui failed: 278893ea9b9fSHuang Rui DRM_ERROR("PSP resume failed\n"); 278993ea9b9fSHuang Rui mutex_unlock(&adev->firmware.mutex); 27900e5ca0d1SHuang Rui return ret; 27910e5ca0d1SHuang Rui } 27920e5ca0d1SHuang Rui 2793f75a9a5dSAlex Deucher int psp_gpu_reset(struct amdgpu_device *adev) 279498512bb8SKen Wang { 279532eaeae0SAlex Deucher int ret; 279632eaeae0SAlex Deucher 27972d4f9020SHuang Rui if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) 27982d4f9020SHuang Rui return 0; 27992d4f9020SHuang Rui 280032eaeae0SAlex Deucher mutex_lock(&adev->psp.mutex); 280132eaeae0SAlex Deucher ret = psp_mode1_reset(&adev->psp); 280232eaeae0SAlex Deucher mutex_unlock(&adev->psp.mutex); 280332eaeae0SAlex Deucher 280432eaeae0SAlex Deucher return ret; 280598512bb8SKen Wang } 280698512bb8SKen Wang 28071a5b4ccaSHawking Zhang int psp_rlc_autoload_start(struct psp_context *psp) 28081a5b4ccaSHawking Zhang { 28091a5b4ccaSHawking Zhang int ret; 2810*4fb93071SCandice Li struct psp_gfx_cmd_resp *cmd = psp->cmd; 28111a5b4ccaSHawking Zhang 2812*4fb93071SCandice Li memset(cmd, 0, sizeof(struct psp_gfx_cmd_resp)); 28131a5b4ccaSHawking Zhang 28141a5b4ccaSHawking Zhang cmd->cmd_id = GFX_CMD_ID_AUTOLOAD_RLC; 28151a5b4ccaSHawking Zhang 28161a5b4ccaSHawking Zhang ret = psp_cmd_submit_buf(psp, NULL, cmd, 28171a5b4ccaSHawking Zhang psp->fence_buf_mc_addr); 2818*4fb93071SCandice Li 28191a5b4ccaSHawking Zhang return ret; 28201a5b4ccaSHawking Zhang } 28211a5b4ccaSHawking Zhang 282286ddf352SJack Xiao int psp_update_vcn_sram(struct amdgpu_device *adev, int inst_idx, 282386ddf352SJack Xiao uint64_t cmd_gpu_addr, int cmd_size) 282486ddf352SJack Xiao { 282586ddf352SJack Xiao struct amdgpu_firmware_info ucode = {0}; 282686ddf352SJack Xiao 282786ddf352SJack Xiao ucode.ucode_id = inst_idx ? AMDGPU_UCODE_ID_VCN1_RAM : 282886ddf352SJack Xiao AMDGPU_UCODE_ID_VCN0_RAM; 282986ddf352SJack Xiao ucode.mc_addr = cmd_gpu_addr; 283086ddf352SJack Xiao ucode.ucode_size = cmd_size; 283186ddf352SJack Xiao 2832cd5955f4SOak Zeng return psp_execute_non_psp_fw_load(&adev->psp, &ucode); 283386ddf352SJack Xiao } 283486ddf352SJack Xiao 2835cc65176eSHawking Zhang int psp_ring_cmd_submit(struct psp_context *psp, 2836cc65176eSHawking Zhang uint64_t cmd_buf_mc_addr, 2837cc65176eSHawking Zhang uint64_t fence_mc_addr, 2838cc65176eSHawking Zhang int index) 2839cc65176eSHawking Zhang { 2840cc65176eSHawking Zhang unsigned int psp_write_ptr_reg = 0; 28412e77541bSColin Ian King struct psp_gfx_rb_frame *write_frame; 2842cc65176eSHawking Zhang struct psp_ring *ring = &psp->km_ring; 2843cc65176eSHawking Zhang struct psp_gfx_rb_frame *ring_buffer_start = ring->ring_mem; 2844cc65176eSHawking Zhang struct psp_gfx_rb_frame *ring_buffer_end = ring_buffer_start + 2845cc65176eSHawking Zhang ring->ring_size / sizeof(struct psp_gfx_rb_frame) - 1; 2846cc65176eSHawking Zhang struct amdgpu_device *adev = psp->adev; 2847cc65176eSHawking Zhang uint32_t ring_size_dw = ring->ring_size / 4; 2848cc65176eSHawking Zhang uint32_t rb_frame_size_dw = sizeof(struct psp_gfx_rb_frame) / 4; 2849cc65176eSHawking Zhang 2850cc65176eSHawking Zhang /* KM (GPCOM) prepare write pointer */ 2851cc65176eSHawking Zhang psp_write_ptr_reg = psp_ring_get_wptr(psp); 2852cc65176eSHawking Zhang 2853cc65176eSHawking Zhang /* Update KM RB frame pointer to new frame */ 2854cc65176eSHawking Zhang /* write_frame ptr increments by size of rb_frame in bytes */ 2855cc65176eSHawking Zhang /* psp_write_ptr_reg increments by size of rb_frame in DWORDs */ 2856cc65176eSHawking Zhang if ((psp_write_ptr_reg % ring_size_dw) == 0) 2857cc65176eSHawking Zhang write_frame = ring_buffer_start; 2858cc65176eSHawking Zhang else 2859cc65176eSHawking Zhang write_frame = ring_buffer_start + (psp_write_ptr_reg / rb_frame_size_dw); 2860cc65176eSHawking Zhang /* Check invalid write_frame ptr address */ 2861cc65176eSHawking Zhang if ((write_frame < ring_buffer_start) || (ring_buffer_end < write_frame)) { 2862cc65176eSHawking Zhang DRM_ERROR("ring_buffer_start = %p; ring_buffer_end = %p; write_frame = %p\n", 2863cc65176eSHawking Zhang ring_buffer_start, ring_buffer_end, write_frame); 2864cc65176eSHawking Zhang DRM_ERROR("write_frame is pointing to address out of bounds\n"); 2865cc65176eSHawking Zhang return -EINVAL; 2866cc65176eSHawking Zhang } 2867cc65176eSHawking Zhang 2868cc65176eSHawking Zhang /* Initialize KM RB frame */ 2869cc65176eSHawking Zhang memset(write_frame, 0, sizeof(struct psp_gfx_rb_frame)); 2870cc65176eSHawking Zhang 2871cc65176eSHawking Zhang /* Update KM RB frame */ 2872cc65176eSHawking Zhang write_frame->cmd_buf_addr_hi = upper_32_bits(cmd_buf_mc_addr); 2873cc65176eSHawking Zhang write_frame->cmd_buf_addr_lo = lower_32_bits(cmd_buf_mc_addr); 2874cc65176eSHawking Zhang write_frame->fence_addr_hi = upper_32_bits(fence_mc_addr); 2875cc65176eSHawking Zhang write_frame->fence_addr_lo = lower_32_bits(fence_mc_addr); 2876cc65176eSHawking Zhang write_frame->fence_value = index; 2877810085ddSEric Huang amdgpu_device_flush_hdp(adev, NULL); 2878cc65176eSHawking Zhang 2879cc65176eSHawking Zhang /* Update the write Pointer in DWORDs */ 2880cc65176eSHawking Zhang psp_write_ptr_reg = (psp_write_ptr_reg + rb_frame_size_dw) % ring_size_dw; 2881cc65176eSHawking Zhang psp_ring_set_wptr(psp, psp_write_ptr_reg); 2882cc65176eSHawking Zhang return 0; 2883cc65176eSHawking Zhang } 2884cc65176eSHawking Zhang 2885dc7195f6SHawking Zhang int psp_init_asd_microcode(struct psp_context *psp, 2886dc7195f6SHawking Zhang const char *chip_name) 2887dc7195f6SHawking Zhang { 2888dc7195f6SHawking Zhang struct amdgpu_device *adev = psp->adev; 28890a305e34STao Zhou char fw_name[PSP_FW_NAME_LEN]; 2890dc7195f6SHawking Zhang const struct psp_firmware_header_v1_0 *asd_hdr; 2891dc7195f6SHawking Zhang int err = 0; 2892dc7195f6SHawking Zhang 2893dc7195f6SHawking Zhang if (!chip_name) { 2894dc7195f6SHawking Zhang dev_err(adev->dev, "invalid chip name for asd microcode\n"); 2895dc7195f6SHawking Zhang return -EINVAL; 2896dc7195f6SHawking Zhang } 2897dc7195f6SHawking Zhang 2898dc7195f6SHawking Zhang snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_asd.bin", chip_name); 2899dc7195f6SHawking Zhang err = request_firmware(&adev->psp.asd_fw, fw_name, adev->dev); 2900dc7195f6SHawking Zhang if (err) 2901dc7195f6SHawking Zhang goto out; 2902dc7195f6SHawking Zhang 2903dc7195f6SHawking Zhang err = amdgpu_ucode_validate(adev->psp.asd_fw); 2904dc7195f6SHawking Zhang if (err) 2905dc7195f6SHawking Zhang goto out; 2906dc7195f6SHawking Zhang 2907dc7195f6SHawking Zhang asd_hdr = (const struct psp_firmware_header_v1_0 *)adev->psp.asd_fw->data; 2908dc7195f6SHawking Zhang adev->psp.asd_fw_version = le32_to_cpu(asd_hdr->header.ucode_version); 290979a0f441SJohn Clements adev->psp.asd_feature_version = le32_to_cpu(asd_hdr->sos.fw_version); 2910dc7195f6SHawking Zhang adev->psp.asd_ucode_size = le32_to_cpu(asd_hdr->header.ucode_size_bytes); 2911dc7195f6SHawking Zhang adev->psp.asd_start_addr = (uint8_t *)asd_hdr + 2912dc7195f6SHawking Zhang le32_to_cpu(asd_hdr->header.ucode_array_offset_bytes); 2913dc7195f6SHawking Zhang return 0; 2914dc7195f6SHawking Zhang out: 2915dc7195f6SHawking Zhang dev_err(adev->dev, "fail to initialize asd microcode\n"); 2916dc7195f6SHawking Zhang release_firmware(adev->psp.asd_fw); 2917dc7195f6SHawking Zhang adev->psp.asd_fw = NULL; 2918dc7195f6SHawking Zhang return err; 2919dc7195f6SHawking Zhang } 2920dc7195f6SHawking Zhang 29215120cb54SHuang Rui int psp_init_toc_microcode(struct psp_context *psp, 29225120cb54SHuang Rui const char *chip_name) 29235120cb54SHuang Rui { 29245120cb54SHuang Rui struct amdgpu_device *adev = psp->adev; 292530ebc16aSLang Yu char fw_name[PSP_FW_NAME_LEN]; 29265120cb54SHuang Rui const struct psp_firmware_header_v1_0 *toc_hdr; 29275120cb54SHuang Rui int err = 0; 29285120cb54SHuang Rui 29295120cb54SHuang Rui if (!chip_name) { 29305120cb54SHuang Rui dev_err(adev->dev, "invalid chip name for toc microcode\n"); 29315120cb54SHuang Rui return -EINVAL; 29325120cb54SHuang Rui } 29335120cb54SHuang Rui 29345120cb54SHuang Rui snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_toc.bin", chip_name); 29355120cb54SHuang Rui err = request_firmware(&adev->psp.toc_fw, fw_name, adev->dev); 29365120cb54SHuang Rui if (err) 29375120cb54SHuang Rui goto out; 29385120cb54SHuang Rui 29395120cb54SHuang Rui err = amdgpu_ucode_validate(adev->psp.toc_fw); 29405120cb54SHuang Rui if (err) 29415120cb54SHuang Rui goto out; 29425120cb54SHuang Rui 29435120cb54SHuang Rui toc_hdr = (const struct psp_firmware_header_v1_0 *)adev->psp.toc_fw->data; 2944222e0a71SCandice Li adev->psp.toc.fw_version = le32_to_cpu(toc_hdr->header.ucode_version); 2945222e0a71SCandice Li adev->psp.toc.feature_version = le32_to_cpu(toc_hdr->sos.fw_version); 2946222e0a71SCandice Li adev->psp.toc.size_bytes = le32_to_cpu(toc_hdr->header.ucode_size_bytes); 2947222e0a71SCandice Li adev->psp.toc.start_addr = (uint8_t *)toc_hdr + 29485120cb54SHuang Rui le32_to_cpu(toc_hdr->header.ucode_array_offset_bytes); 29495120cb54SHuang Rui return 0; 29505120cb54SHuang Rui out: 29515120cb54SHuang Rui dev_err(adev->dev, "fail to request/validate toc microcode\n"); 29525120cb54SHuang Rui release_firmware(adev->psp.toc_fw); 29535120cb54SHuang Rui adev->psp.toc_fw = NULL; 29545120cb54SHuang Rui return err; 29555120cb54SHuang Rui } 29565120cb54SHuang Rui 2957f8e487ceSJohn Clements static int parse_sos_bin_descriptor(struct psp_context *psp, 2958f8e487ceSJohn Clements const struct psp_fw_bin_desc *desc, 2959f8e487ceSJohn Clements const struct psp_firmware_header_v2_0 *sos_hdr) 2960f8e487ceSJohn Clements { 2961f8e487ceSJohn Clements uint8_t *ucode_start_addr = NULL; 2962f8e487ceSJohn Clements 2963f8e487ceSJohn Clements if (!psp || !desc || !sos_hdr) 2964f8e487ceSJohn Clements return -EINVAL; 2965f8e487ceSJohn Clements 2966f8e487ceSJohn Clements ucode_start_addr = (uint8_t *)sos_hdr + 2967f8e487ceSJohn Clements le32_to_cpu(desc->offset_bytes) + 2968f8e487ceSJohn Clements le32_to_cpu(sos_hdr->header.ucode_array_offset_bytes); 2969f8e487ceSJohn Clements 2970f8e487ceSJohn Clements switch (desc->fw_type) { 2971f8e487ceSJohn Clements case PSP_FW_TYPE_PSP_SOS: 2972f8e487ceSJohn Clements psp->sos.fw_version = le32_to_cpu(desc->fw_version); 2973f8e487ceSJohn Clements psp->sos.feature_version = le32_to_cpu(desc->fw_version); 2974f8e487ceSJohn Clements psp->sos.size_bytes = le32_to_cpu(desc->size_bytes); 2975f8e487ceSJohn Clements psp->sos.start_addr = ucode_start_addr; 2976f8e487ceSJohn Clements break; 2977f8e487ceSJohn Clements case PSP_FW_TYPE_PSP_SYS_DRV: 2978f8e487ceSJohn Clements psp->sys.fw_version = le32_to_cpu(desc->fw_version); 2979f8e487ceSJohn Clements psp->sys.feature_version = le32_to_cpu(desc->fw_version); 2980f8e487ceSJohn Clements psp->sys.size_bytes = le32_to_cpu(desc->size_bytes); 2981f8e487ceSJohn Clements psp->sys.start_addr = ucode_start_addr; 2982f8e487ceSJohn Clements break; 2983f8e487ceSJohn Clements case PSP_FW_TYPE_PSP_KDB: 2984f8e487ceSJohn Clements psp->kdb.fw_version = le32_to_cpu(desc->fw_version); 2985f8e487ceSJohn Clements psp->kdb.feature_version = le32_to_cpu(desc->fw_version); 2986f8e487ceSJohn Clements psp->kdb.size_bytes = le32_to_cpu(desc->size_bytes); 2987f8e487ceSJohn Clements psp->kdb.start_addr = ucode_start_addr; 2988f8e487ceSJohn Clements break; 2989f8e487ceSJohn Clements case PSP_FW_TYPE_PSP_TOC: 2990f8e487ceSJohn Clements psp->toc.fw_version = le32_to_cpu(desc->fw_version); 2991f8e487ceSJohn Clements psp->toc.feature_version = le32_to_cpu(desc->fw_version); 2992f8e487ceSJohn Clements psp->toc.size_bytes = le32_to_cpu(desc->size_bytes); 2993f8e487ceSJohn Clements psp->toc.start_addr = ucode_start_addr; 2994f8e487ceSJohn Clements break; 2995f8e487ceSJohn Clements case PSP_FW_TYPE_PSP_SPL: 2996f8e487ceSJohn Clements psp->spl.fw_version = le32_to_cpu(desc->fw_version); 2997f8e487ceSJohn Clements psp->spl.feature_version = le32_to_cpu(desc->fw_version); 2998f8e487ceSJohn Clements psp->spl.size_bytes = le32_to_cpu(desc->size_bytes); 2999f8e487ceSJohn Clements psp->spl.start_addr = ucode_start_addr; 3000f8e487ceSJohn Clements break; 3001f8e487ceSJohn Clements case PSP_FW_TYPE_PSP_RL: 3002f8e487ceSJohn Clements psp->rl.fw_version = le32_to_cpu(desc->fw_version); 3003f8e487ceSJohn Clements psp->rl.feature_version = le32_to_cpu(desc->fw_version); 3004f8e487ceSJohn Clements psp->rl.size_bytes = le32_to_cpu(desc->size_bytes); 3005f8e487ceSJohn Clements psp->rl.start_addr = ucode_start_addr; 3006f8e487ceSJohn Clements break; 30076ff34fd6SJohn Clements case PSP_FW_TYPE_PSP_SOC_DRV: 30086ff34fd6SJohn Clements psp->soc_drv.fw_version = le32_to_cpu(desc->fw_version); 30096ff34fd6SJohn Clements psp->soc_drv.feature_version = le32_to_cpu(desc->fw_version); 30106ff34fd6SJohn Clements psp->soc_drv.size_bytes = le32_to_cpu(desc->size_bytes); 30116ff34fd6SJohn Clements psp->soc_drv.start_addr = ucode_start_addr; 30126ff34fd6SJohn Clements break; 30136ff34fd6SJohn Clements case PSP_FW_TYPE_PSP_INTF_DRV: 30146ff34fd6SJohn Clements psp->intf_drv.fw_version = le32_to_cpu(desc->fw_version); 30156ff34fd6SJohn Clements psp->intf_drv.feature_version = le32_to_cpu(desc->fw_version); 30166ff34fd6SJohn Clements psp->intf_drv.size_bytes = le32_to_cpu(desc->size_bytes); 30176ff34fd6SJohn Clements psp->intf_drv.start_addr = ucode_start_addr; 30186ff34fd6SJohn Clements break; 30196ff34fd6SJohn Clements case PSP_FW_TYPE_PSP_DBG_DRV: 30206ff34fd6SJohn Clements psp->dbg_drv.fw_version = le32_to_cpu(desc->fw_version); 30216ff34fd6SJohn Clements psp->dbg_drv.feature_version = le32_to_cpu(desc->fw_version); 30226ff34fd6SJohn Clements psp->dbg_drv.size_bytes = le32_to_cpu(desc->size_bytes); 30236ff34fd6SJohn Clements psp->dbg_drv.start_addr = ucode_start_addr; 30246ff34fd6SJohn Clements break; 3025f8e487ceSJohn Clements default: 3026f8e487ceSJohn Clements dev_warn(psp->adev->dev, "Unsupported PSP FW type: %d\n", desc->fw_type); 3027f8e487ceSJohn Clements break; 3028f8e487ceSJohn Clements } 3029f8e487ceSJohn Clements 3030f8e487ceSJohn Clements return 0; 3031f8e487ceSJohn Clements } 3032f8e487ceSJohn Clements 30332a9a151fSJohn Clements static int psp_init_sos_base_fw(struct amdgpu_device *adev) 30342a9a151fSJohn Clements { 30352a9a151fSJohn Clements const struct psp_firmware_header_v1_0 *sos_hdr; 30362a9a151fSJohn Clements const struct psp_firmware_header_v1_3 *sos_hdr_v1_3; 3037ed4454c3SHawking Zhang uint8_t *ucode_array_start_addr; 30382a9a151fSJohn Clements 30392a9a151fSJohn Clements sos_hdr = (const struct psp_firmware_header_v1_0 *)adev->psp.sos_fw->data; 3040ed4454c3SHawking Zhang ucode_array_start_addr = (uint8_t *)sos_hdr + 3041ed4454c3SHawking Zhang le32_to_cpu(sos_hdr->header.ucode_array_offset_bytes); 30422a9a151fSJohn Clements 30432a9a151fSJohn Clements if (adev->gmc.xgmi.connected_to_cpu || (adev->asic_type != CHIP_ALDEBARAN)) { 3044222e0a71SCandice Li adev->psp.sos.fw_version = le32_to_cpu(sos_hdr->header.ucode_version); 3045222e0a71SCandice Li adev->psp.sos.feature_version = le32_to_cpu(sos_hdr->sos.fw_version); 30462a9a151fSJohn Clements 3047222e0a71SCandice Li adev->psp.sys.size_bytes = le32_to_cpu(sos_hdr->sos.offset_bytes); 3048222e0a71SCandice Li adev->psp.sys.start_addr = ucode_array_start_addr; 30492a9a151fSJohn Clements 3050222e0a71SCandice Li adev->psp.sos.size_bytes = le32_to_cpu(sos_hdr->sos.size_bytes); 3051222e0a71SCandice Li adev->psp.sos.start_addr = ucode_array_start_addr + 30522a9a151fSJohn Clements le32_to_cpu(sos_hdr->sos.offset_bytes); 30532a9a151fSJohn Clements } else { 30542a9a151fSJohn Clements /* Load alternate PSP SOS FW */ 30552a9a151fSJohn Clements sos_hdr_v1_3 = (const struct psp_firmware_header_v1_3 *)adev->psp.sos_fw->data; 30562a9a151fSJohn Clements 3057222e0a71SCandice Li adev->psp.sos.fw_version = le32_to_cpu(sos_hdr_v1_3->sos_aux.fw_version); 3058222e0a71SCandice Li adev->psp.sos.feature_version = le32_to_cpu(sos_hdr_v1_3->sos_aux.fw_version); 30592a9a151fSJohn Clements 3060222e0a71SCandice Li adev->psp.sys.size_bytes = le32_to_cpu(sos_hdr_v1_3->sys_drv_aux.size_bytes); 3061222e0a71SCandice Li adev->psp.sys.start_addr = ucode_array_start_addr + 30622a9a151fSJohn Clements le32_to_cpu(sos_hdr_v1_3->sys_drv_aux.offset_bytes); 30632a9a151fSJohn Clements 3064222e0a71SCandice Li adev->psp.sos.size_bytes = le32_to_cpu(sos_hdr_v1_3->sos_aux.size_bytes); 3065222e0a71SCandice Li adev->psp.sos.start_addr = ucode_array_start_addr + 30662a9a151fSJohn Clements le32_to_cpu(sos_hdr_v1_3->sos_aux.offset_bytes); 30672a9a151fSJohn Clements } 30682a9a151fSJohn Clements 3069222e0a71SCandice Li if ((adev->psp.sys.size_bytes == 0) || (adev->psp.sos.size_bytes == 0)) { 30702a9a151fSJohn Clements dev_warn(adev->dev, "PSP SOS FW not available"); 30712a9a151fSJohn Clements return -EINVAL; 30722a9a151fSJohn Clements } 30732a9a151fSJohn Clements 30742a9a151fSJohn Clements return 0; 30752a9a151fSJohn Clements } 30762a9a151fSJohn Clements 30771c301f44SHawking Zhang int psp_init_sos_microcode(struct psp_context *psp, 30781c301f44SHawking Zhang const char *chip_name) 30791c301f44SHawking Zhang { 30801c301f44SHawking Zhang struct amdgpu_device *adev = psp->adev; 30810a305e34STao Zhou char fw_name[PSP_FW_NAME_LEN]; 30821c301f44SHawking Zhang const struct psp_firmware_header_v1_0 *sos_hdr; 30831c301f44SHawking Zhang const struct psp_firmware_header_v1_1 *sos_hdr_v1_1; 30841c301f44SHawking Zhang const struct psp_firmware_header_v1_2 *sos_hdr_v1_2; 308543a188e0SLikun Gao const struct psp_firmware_header_v1_3 *sos_hdr_v1_3; 3086f8e487ceSJohn Clements const struct psp_firmware_header_v2_0 *sos_hdr_v2_0; 30871c301f44SHawking Zhang int err = 0; 3088ed4454c3SHawking Zhang uint8_t *ucode_array_start_addr; 3089f8e487ceSJohn Clements int fw_index = 0; 30901c301f44SHawking Zhang 30911c301f44SHawking Zhang if (!chip_name) { 30921c301f44SHawking Zhang dev_err(adev->dev, "invalid chip name for sos microcode\n"); 30931c301f44SHawking Zhang return -EINVAL; 30941c301f44SHawking Zhang } 30951c301f44SHawking Zhang 30961c301f44SHawking Zhang snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_sos.bin", chip_name); 30971c301f44SHawking Zhang err = request_firmware(&adev->psp.sos_fw, fw_name, adev->dev); 30981c301f44SHawking Zhang if (err) 30991c301f44SHawking Zhang goto out; 31001c301f44SHawking Zhang 31011c301f44SHawking Zhang err = amdgpu_ucode_validate(adev->psp.sos_fw); 31021c301f44SHawking Zhang if (err) 31031c301f44SHawking Zhang goto out; 31041c301f44SHawking Zhang 31051c301f44SHawking Zhang sos_hdr = (const struct psp_firmware_header_v1_0 *)adev->psp.sos_fw->data; 3106ed4454c3SHawking Zhang ucode_array_start_addr = (uint8_t *)sos_hdr + 3107ed4454c3SHawking Zhang le32_to_cpu(sos_hdr->header.ucode_array_offset_bytes); 31081c301f44SHawking Zhang amdgpu_ucode_print_psp_hdr(&sos_hdr->header); 31091c301f44SHawking Zhang 31101c301f44SHawking Zhang switch (sos_hdr->header.header_version_major) { 31111c301f44SHawking Zhang case 1: 31122a9a151fSJohn Clements err = psp_init_sos_base_fw(adev); 31132a9a151fSJohn Clements if (err) 31142a9a151fSJohn Clements goto out; 31152a9a151fSJohn Clements 31161c301f44SHawking Zhang if (sos_hdr->header.header_version_minor == 1) { 31171c301f44SHawking Zhang sos_hdr_v1_1 = (const struct psp_firmware_header_v1_1 *)adev->psp.sos_fw->data; 3118222e0a71SCandice Li adev->psp.toc.size_bytes = le32_to_cpu(sos_hdr_v1_1->toc.size_bytes); 3119222e0a71SCandice Li adev->psp.toc.start_addr = (uint8_t *)adev->psp.sys.start_addr + 312079a0f441SJohn Clements le32_to_cpu(sos_hdr_v1_1->toc.offset_bytes); 3121222e0a71SCandice Li adev->psp.kdb.size_bytes = le32_to_cpu(sos_hdr_v1_1->kdb.size_bytes); 3122222e0a71SCandice Li adev->psp.kdb.start_addr = (uint8_t *)adev->psp.sys.start_addr + 312379a0f441SJohn Clements le32_to_cpu(sos_hdr_v1_1->kdb.offset_bytes); 31241c301f44SHawking Zhang } 31251c301f44SHawking Zhang if (sos_hdr->header.header_version_minor == 2) { 31261c301f44SHawking Zhang sos_hdr_v1_2 = (const struct psp_firmware_header_v1_2 *)adev->psp.sos_fw->data; 3127222e0a71SCandice Li adev->psp.kdb.size_bytes = le32_to_cpu(sos_hdr_v1_2->kdb.size_bytes); 3128222e0a71SCandice Li adev->psp.kdb.start_addr = (uint8_t *)adev->psp.sys.start_addr + 312979a0f441SJohn Clements le32_to_cpu(sos_hdr_v1_2->kdb.offset_bytes); 31301c301f44SHawking Zhang } 313143a188e0SLikun Gao if (sos_hdr->header.header_version_minor == 3) { 313243a188e0SLikun Gao sos_hdr_v1_3 = (const struct psp_firmware_header_v1_3 *)adev->psp.sos_fw->data; 3133222e0a71SCandice Li adev->psp.toc.size_bytes = le32_to_cpu(sos_hdr_v1_3->v1_1.toc.size_bytes); 3134222e0a71SCandice Li adev->psp.toc.start_addr = ucode_array_start_addr + 313579a0f441SJohn Clements le32_to_cpu(sos_hdr_v1_3->v1_1.toc.offset_bytes); 3136222e0a71SCandice Li adev->psp.kdb.size_bytes = le32_to_cpu(sos_hdr_v1_3->v1_1.kdb.size_bytes); 3137222e0a71SCandice Li adev->psp.kdb.start_addr = ucode_array_start_addr + 313879a0f441SJohn Clements le32_to_cpu(sos_hdr_v1_3->v1_1.kdb.offset_bytes); 3139222e0a71SCandice Li adev->psp.spl.size_bytes = le32_to_cpu(sos_hdr_v1_3->spl.size_bytes); 3140222e0a71SCandice Li adev->psp.spl.start_addr = ucode_array_start_addr + 314179a0f441SJohn Clements le32_to_cpu(sos_hdr_v1_3->spl.offset_bytes); 3142222e0a71SCandice Li adev->psp.rl.size_bytes = le32_to_cpu(sos_hdr_v1_3->rl.size_bytes); 3143222e0a71SCandice Li adev->psp.rl.start_addr = ucode_array_start_addr + 314479a0f441SJohn Clements le32_to_cpu(sos_hdr_v1_3->rl.offset_bytes); 314543a188e0SLikun Gao } 31461c301f44SHawking Zhang break; 3147f8e487ceSJohn Clements case 2: 3148f8e487ceSJohn Clements sos_hdr_v2_0 = (const struct psp_firmware_header_v2_0 *)adev->psp.sos_fw->data; 3149f8e487ceSJohn Clements 3150f8e487ceSJohn Clements if (le32_to_cpu(sos_hdr_v2_0->psp_fw_bin_count) >= UCODE_MAX_PSP_PACKAGING) { 3151f8e487ceSJohn Clements dev_err(adev->dev, "packed SOS count exceeds maximum limit\n"); 3152f8e487ceSJohn Clements err = -EINVAL; 3153f8e487ceSJohn Clements goto out; 3154f8e487ceSJohn Clements } 3155f8e487ceSJohn Clements 3156f8e487ceSJohn Clements for (fw_index = 0; fw_index < le32_to_cpu(sos_hdr_v2_0->psp_fw_bin_count); fw_index++) { 3157f8e487ceSJohn Clements err = parse_sos_bin_descriptor(psp, 3158f8e487ceSJohn Clements &sos_hdr_v2_0->psp_fw_bin[fw_index], 3159f8e487ceSJohn Clements sos_hdr_v2_0); 3160f8e487ceSJohn Clements if (err) 3161f8e487ceSJohn Clements goto out; 3162f8e487ceSJohn Clements } 3163f8e487ceSJohn Clements break; 31641c301f44SHawking Zhang default: 31651c301f44SHawking Zhang dev_err(adev->dev, 31661c301f44SHawking Zhang "unsupported psp sos firmware\n"); 31671c301f44SHawking Zhang err = -EINVAL; 31681c301f44SHawking Zhang goto out; 31691c301f44SHawking Zhang } 31701c301f44SHawking Zhang 31711c301f44SHawking Zhang return 0; 31721c301f44SHawking Zhang out: 31731c301f44SHawking Zhang dev_err(adev->dev, 31741c301f44SHawking Zhang "failed to init sos firmware\n"); 31751c301f44SHawking Zhang release_firmware(adev->psp.sos_fw); 31761c301f44SHawking Zhang adev->psp.sos_fw = NULL; 31771c301f44SHawking Zhang 31781c301f44SHawking Zhang return err; 31791c301f44SHawking Zhang } 31801c301f44SHawking Zhang 3181c18dd61aSLee Jones static int parse_ta_bin_descriptor(struct psp_context *psp, 3182f8e487ceSJohn Clements const struct psp_fw_bin_desc *desc, 3183dcf9864dSJohn Clements const struct ta_firmware_header_v2_0 *ta_hdr) 3184dcf9864dSJohn Clements { 3185dcf9864dSJohn Clements uint8_t *ucode_start_addr = NULL; 3186dcf9864dSJohn Clements 3187dcf9864dSJohn Clements if (!psp || !desc || !ta_hdr) 3188dcf9864dSJohn Clements return -EINVAL; 3189dcf9864dSJohn Clements 3190a3302729SJohn Clements ucode_start_addr = (uint8_t *)ta_hdr + 3191a3302729SJohn Clements le32_to_cpu(desc->offset_bytes) + 3192a3302729SJohn Clements le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes); 3193dcf9864dSJohn Clements 3194dcf9864dSJohn Clements switch (desc->fw_type) { 3195dcf9864dSJohn Clements case TA_FW_TYPE_PSP_ASD: 3196dcf9864dSJohn Clements psp->asd_fw_version = le32_to_cpu(desc->fw_version); 3197dcf9864dSJohn Clements psp->asd_feature_version = le32_to_cpu(desc->fw_version); 3198dcf9864dSJohn Clements psp->asd_ucode_size = le32_to_cpu(desc->size_bytes); 3199dcf9864dSJohn Clements psp->asd_start_addr = ucode_start_addr; 3200dcf9864dSJohn Clements break; 3201dcf9864dSJohn Clements case TA_FW_TYPE_PSP_XGMI: 3202dcf9864dSJohn Clements psp->ta_xgmi_ucode_version = le32_to_cpu(desc->fw_version); 3203dcf9864dSJohn Clements psp->ta_xgmi_ucode_size = le32_to_cpu(desc->size_bytes); 3204dcf9864dSJohn Clements psp->ta_xgmi_start_addr = ucode_start_addr; 3205dcf9864dSJohn Clements break; 3206dcf9864dSJohn Clements case TA_FW_TYPE_PSP_RAS: 3207dcf9864dSJohn Clements psp->ta_ras_ucode_version = le32_to_cpu(desc->fw_version); 3208dcf9864dSJohn Clements psp->ta_ras_ucode_size = le32_to_cpu(desc->size_bytes); 3209dcf9864dSJohn Clements psp->ta_ras_start_addr = ucode_start_addr; 3210dcf9864dSJohn Clements break; 3211dcf9864dSJohn Clements case TA_FW_TYPE_PSP_HDCP: 3212dcf9864dSJohn Clements psp->ta_hdcp_ucode_version = le32_to_cpu(desc->fw_version); 3213dcf9864dSJohn Clements psp->ta_hdcp_ucode_size = le32_to_cpu(desc->size_bytes); 3214dcf9864dSJohn Clements psp->ta_hdcp_start_addr = ucode_start_addr; 3215dcf9864dSJohn Clements break; 3216dcf9864dSJohn Clements case TA_FW_TYPE_PSP_DTM: 3217dcf9864dSJohn Clements psp->ta_dtm_ucode_version = le32_to_cpu(desc->fw_version); 3218dcf9864dSJohn Clements psp->ta_dtm_ucode_size = le32_to_cpu(desc->size_bytes); 3219dcf9864dSJohn Clements psp->ta_dtm_start_addr = ucode_start_addr; 3220dcf9864dSJohn Clements break; 32218602692bSWenhui Sheng case TA_FW_TYPE_PSP_RAP: 32228602692bSWenhui Sheng psp->ta_rap_ucode_version = le32_to_cpu(desc->fw_version); 32238602692bSWenhui Sheng psp->ta_rap_ucode_size = le32_to_cpu(desc->size_bytes); 32248602692bSWenhui Sheng psp->ta_rap_start_addr = ucode_start_addr; 32258602692bSWenhui Sheng break; 3226ecaafb7bSJinzhou Su case TA_FW_TYPE_PSP_SECUREDISPLAY: 3227ecaafb7bSJinzhou Su psp->ta_securedisplay_ucode_version = le32_to_cpu(desc->fw_version); 3228ecaafb7bSJinzhou Su psp->ta_securedisplay_ucode_size = le32_to_cpu(desc->size_bytes); 3229ecaafb7bSJinzhou Su psp->ta_securedisplay_start_addr = ucode_start_addr; 3230ecaafb7bSJinzhou Su break; 3231dcf9864dSJohn Clements default: 3232dcf9864dSJohn Clements dev_warn(psp->adev->dev, "Unsupported TA type: %d\n", desc->fw_type); 3233dcf9864dSJohn Clements break; 3234dcf9864dSJohn Clements } 3235dcf9864dSJohn Clements 3236dcf9864dSJohn Clements return 0; 3237dcf9864dSJohn Clements } 3238dcf9864dSJohn Clements 3239dcf9864dSJohn Clements int psp_init_ta_microcode(struct psp_context *psp, 3240dcf9864dSJohn Clements const char *chip_name) 3241dcf9864dSJohn Clements { 3242dcf9864dSJohn Clements struct amdgpu_device *adev = psp->adev; 32436cb445e8SBhawanpreet Lakha char fw_name[PSP_FW_NAME_LEN]; 3244dcf9864dSJohn Clements const struct ta_firmware_header_v2_0 *ta_hdr; 3245dcf9864dSJohn Clements int err = 0; 3246dcf9864dSJohn Clements int ta_index = 0; 3247dcf9864dSJohn Clements 3248dcf9864dSJohn Clements if (!chip_name) { 3249dcf9864dSJohn Clements dev_err(adev->dev, "invalid chip name for ta microcode\n"); 3250dcf9864dSJohn Clements return -EINVAL; 3251dcf9864dSJohn Clements } 3252dcf9864dSJohn Clements 3253dcf9864dSJohn Clements snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ta.bin", chip_name); 3254dcf9864dSJohn Clements err = request_firmware(&adev->psp.ta_fw, fw_name, adev->dev); 3255dcf9864dSJohn Clements if (err) 3256dcf9864dSJohn Clements goto out; 3257dcf9864dSJohn Clements 3258dcf9864dSJohn Clements err = amdgpu_ucode_validate(adev->psp.ta_fw); 3259dcf9864dSJohn Clements if (err) 3260dcf9864dSJohn Clements goto out; 3261dcf9864dSJohn Clements 3262dcf9864dSJohn Clements ta_hdr = (const struct ta_firmware_header_v2_0 *)adev->psp.ta_fw->data; 3263dcf9864dSJohn Clements 3264dcf9864dSJohn Clements if (le16_to_cpu(ta_hdr->header.header_version_major) != 2) { 3265dcf9864dSJohn Clements dev_err(adev->dev, "unsupported TA header version\n"); 3266dcf9864dSJohn Clements err = -EINVAL; 3267dcf9864dSJohn Clements goto out; 3268dcf9864dSJohn Clements } 3269dcf9864dSJohn Clements 3270f8e487ceSJohn Clements if (le32_to_cpu(ta_hdr->ta_fw_bin_count) >= UCODE_MAX_PSP_PACKAGING) { 3271dcf9864dSJohn Clements dev_err(adev->dev, "packed TA count exceeds maximum limit\n"); 3272dcf9864dSJohn Clements err = -EINVAL; 3273dcf9864dSJohn Clements goto out; 3274dcf9864dSJohn Clements } 3275dcf9864dSJohn Clements 3276dcf9864dSJohn Clements for (ta_index = 0; ta_index < le32_to_cpu(ta_hdr->ta_fw_bin_count); ta_index++) { 3277dcf9864dSJohn Clements err = parse_ta_bin_descriptor(psp, 3278dcf9864dSJohn Clements &ta_hdr->ta_fw_bin[ta_index], 3279dcf9864dSJohn Clements ta_hdr); 3280dcf9864dSJohn Clements if (err) 3281dcf9864dSJohn Clements goto out; 3282dcf9864dSJohn Clements } 3283dcf9864dSJohn Clements 3284dcf9864dSJohn Clements return 0; 3285dcf9864dSJohn Clements out: 3286dcf9864dSJohn Clements dev_err(adev->dev, "fail to initialize ta microcode\n"); 3287dcf9864dSJohn Clements release_firmware(adev->psp.ta_fw); 3288dcf9864dSJohn Clements adev->psp.ta_fw = NULL; 3289dcf9864dSJohn Clements return err; 3290dcf9864dSJohn Clements } 3291dcf9864dSJohn Clements 32920e5ca0d1SHuang Rui static int psp_set_clockgating_state(void *handle, 32930e5ca0d1SHuang Rui enum amd_clockgating_state state) 32940e5ca0d1SHuang Rui { 32950e5ca0d1SHuang Rui return 0; 32960e5ca0d1SHuang Rui } 32970e5ca0d1SHuang Rui 32980e5ca0d1SHuang Rui static int psp_set_powergating_state(void *handle, 32990e5ca0d1SHuang Rui enum amd_powergating_state state) 33000e5ca0d1SHuang Rui { 33010e5ca0d1SHuang Rui return 0; 33020e5ca0d1SHuang Rui } 33030e5ca0d1SHuang Rui 330457430471SAndrey Grodzovsky static ssize_t psp_usbc_pd_fw_sysfs_read(struct device *dev, 330557430471SAndrey Grodzovsky struct device_attribute *attr, 330657430471SAndrey Grodzovsky char *buf) 330757430471SAndrey Grodzovsky { 330857430471SAndrey Grodzovsky struct drm_device *ddev = dev_get_drvdata(dev); 33091348969aSLuben Tuikov struct amdgpu_device *adev = drm_to_adev(ddev); 331057430471SAndrey Grodzovsky uint32_t fw_ver; 331157430471SAndrey Grodzovsky int ret; 331257430471SAndrey Grodzovsky 331390f88cddSAndrey Grodzovsky if (!adev->ip_blocks[AMD_IP_BLOCK_TYPE_PSP].status.late_initialized) { 331490f88cddSAndrey Grodzovsky DRM_INFO("PSP block is not ready yet."); 331590f88cddSAndrey Grodzovsky return -EBUSY; 331690f88cddSAndrey Grodzovsky } 331790f88cddSAndrey Grodzovsky 331857430471SAndrey Grodzovsky mutex_lock(&adev->psp.mutex); 331957430471SAndrey Grodzovsky ret = psp_read_usbc_pd_fw(&adev->psp, &fw_ver); 332057430471SAndrey Grodzovsky mutex_unlock(&adev->psp.mutex); 332157430471SAndrey Grodzovsky 332257430471SAndrey Grodzovsky if (ret) { 332357430471SAndrey Grodzovsky DRM_ERROR("Failed to read USBC PD FW, err = %d", ret); 332457430471SAndrey Grodzovsky return ret; 332557430471SAndrey Grodzovsky } 332657430471SAndrey Grodzovsky 332736000c7aSTian Tao return sysfs_emit(buf, "%x\n", fw_ver); 332857430471SAndrey Grodzovsky } 332957430471SAndrey Grodzovsky 333057430471SAndrey Grodzovsky static ssize_t psp_usbc_pd_fw_sysfs_write(struct device *dev, 333157430471SAndrey Grodzovsky struct device_attribute *attr, 333257430471SAndrey Grodzovsky const char *buf, 333357430471SAndrey Grodzovsky size_t count) 333457430471SAndrey Grodzovsky { 333557430471SAndrey Grodzovsky struct drm_device *ddev = dev_get_drvdata(dev); 33361348969aSLuben Tuikov struct amdgpu_device *adev = drm_to_adev(ddev); 3337f89f8c6bSAndrey Grodzovsky int ret, idx; 333857430471SAndrey Grodzovsky char fw_name[100]; 333957430471SAndrey Grodzovsky const struct firmware *usbc_pd_fw; 334025a3e8acSAndrey Grodzovsky struct amdgpu_bo *fw_buf_bo = NULL; 334125a3e8acSAndrey Grodzovsky uint64_t fw_pri_mc_addr; 334225a3e8acSAndrey Grodzovsky void *fw_pri_cpu_addr; 334357430471SAndrey Grodzovsky 334490f88cddSAndrey Grodzovsky if (!adev->ip_blocks[AMD_IP_BLOCK_TYPE_PSP].status.late_initialized) { 334590f88cddSAndrey Grodzovsky DRM_INFO("PSP block is not ready yet."); 334690f88cddSAndrey Grodzovsky return -EBUSY; 334790f88cddSAndrey Grodzovsky } 334857430471SAndrey Grodzovsky 3349f89f8c6bSAndrey Grodzovsky if (!drm_dev_enter(ddev, &idx)) 3350f89f8c6bSAndrey Grodzovsky return -ENODEV; 3351f89f8c6bSAndrey Grodzovsky 335257430471SAndrey Grodzovsky snprintf(fw_name, sizeof(fw_name), "amdgpu/%s", buf); 335357430471SAndrey Grodzovsky ret = request_firmware(&usbc_pd_fw, fw_name, adev->dev); 335457430471SAndrey Grodzovsky if (ret) 335557430471SAndrey Grodzovsky goto fail; 335657430471SAndrey Grodzovsky 335725a3e8acSAndrey Grodzovsky /* LFB address which is aligned to 1MB boundary per PSP request */ 335825a3e8acSAndrey Grodzovsky ret = amdgpu_bo_create_kernel(adev, usbc_pd_fw->size, 0x100000, 335925a3e8acSAndrey Grodzovsky AMDGPU_GEM_DOMAIN_VRAM, 336025a3e8acSAndrey Grodzovsky &fw_buf_bo, 336125a3e8acSAndrey Grodzovsky &fw_pri_mc_addr, 336225a3e8acSAndrey Grodzovsky &fw_pri_cpu_addr); 336357430471SAndrey Grodzovsky if (ret) 336457430471SAndrey Grodzovsky goto rel_buf; 336557430471SAndrey Grodzovsky 336625a3e8acSAndrey Grodzovsky memcpy_toio(fw_pri_cpu_addr, usbc_pd_fw->data, usbc_pd_fw->size); 336757430471SAndrey Grodzovsky 336857430471SAndrey Grodzovsky mutex_lock(&adev->psp.mutex); 336925a3e8acSAndrey Grodzovsky ret = psp_load_usbc_pd_fw(&adev->psp, fw_pri_mc_addr); 337057430471SAndrey Grodzovsky mutex_unlock(&adev->psp.mutex); 337157430471SAndrey Grodzovsky 337225a3e8acSAndrey Grodzovsky amdgpu_bo_free_kernel(&fw_buf_bo, &fw_pri_mc_addr, &fw_pri_cpu_addr); 337325a3e8acSAndrey Grodzovsky 337457430471SAndrey Grodzovsky rel_buf: 337557430471SAndrey Grodzovsky release_firmware(usbc_pd_fw); 337657430471SAndrey Grodzovsky fail: 337757430471SAndrey Grodzovsky if (ret) { 337857430471SAndrey Grodzovsky DRM_ERROR("Failed to load USBC PD FW, err = %d", ret); 3379f89f8c6bSAndrey Grodzovsky count = ret; 338057430471SAndrey Grodzovsky } 338157430471SAndrey Grodzovsky 3382f89f8c6bSAndrey Grodzovsky drm_dev_exit(idx); 338357430471SAndrey Grodzovsky return count; 338457430471SAndrey Grodzovsky } 338557430471SAndrey Grodzovsky 3386f89f8c6bSAndrey Grodzovsky void psp_copy_fw(struct psp_context *psp, uint8_t *start_addr, uint32_t bin_size) 3387f89f8c6bSAndrey Grodzovsky { 3388f89f8c6bSAndrey Grodzovsky int idx; 3389f89f8c6bSAndrey Grodzovsky 3390f89f8c6bSAndrey Grodzovsky if (!drm_dev_enter(&psp->adev->ddev, &idx)) 3391f89f8c6bSAndrey Grodzovsky return; 3392f89f8c6bSAndrey Grodzovsky 3393f89f8c6bSAndrey Grodzovsky memset(psp->fw_pri_buf, 0, PSP_1_MEG); 3394f89f8c6bSAndrey Grodzovsky memcpy(psp->fw_pri_buf, start_addr, bin_size); 3395f89f8c6bSAndrey Grodzovsky 3396f89f8c6bSAndrey Grodzovsky drm_dev_exit(idx); 3397f89f8c6bSAndrey Grodzovsky } 3398f89f8c6bSAndrey Grodzovsky 339957430471SAndrey Grodzovsky static DEVICE_ATTR(usbc_pd_fw, S_IRUGO | S_IWUSR, 340057430471SAndrey Grodzovsky psp_usbc_pd_fw_sysfs_read, 340157430471SAndrey Grodzovsky psp_usbc_pd_fw_sysfs_write); 340257430471SAndrey Grodzovsky 3403222e0a71SCandice Li int is_psp_fw_valid(struct psp_bin_desc bin) 3404222e0a71SCandice Li { 3405222e0a71SCandice Li return bin.size_bytes; 3406222e0a71SCandice Li } 340757430471SAndrey Grodzovsky 34080e5ca0d1SHuang Rui const struct amd_ip_funcs psp_ip_funcs = { 34090e5ca0d1SHuang Rui .name = "psp", 34100e5ca0d1SHuang Rui .early_init = psp_early_init, 341190f88cddSAndrey Grodzovsky .late_init = NULL, 34120e5ca0d1SHuang Rui .sw_init = psp_sw_init, 34130e5ca0d1SHuang Rui .sw_fini = psp_sw_fini, 34140e5ca0d1SHuang Rui .hw_init = psp_hw_init, 34150e5ca0d1SHuang Rui .hw_fini = psp_hw_fini, 34160e5ca0d1SHuang Rui .suspend = psp_suspend, 34170e5ca0d1SHuang Rui .resume = psp_resume, 34180e5ca0d1SHuang Rui .is_idle = NULL, 3419f75a9a5dSAlex Deucher .check_soft_reset = NULL, 34200e5ca0d1SHuang Rui .wait_for_idle = NULL, 3421f75a9a5dSAlex Deucher .soft_reset = NULL, 34220e5ca0d1SHuang Rui .set_clockgating_state = psp_set_clockgating_state, 34230e5ca0d1SHuang Rui .set_powergating_state = psp_set_powergating_state, 34240e5ca0d1SHuang Rui }; 34250e5ca0d1SHuang Rui 342657430471SAndrey Grodzovsky static int psp_sysfs_init(struct amdgpu_device *adev) 342757430471SAndrey Grodzovsky { 342857430471SAndrey Grodzovsky int ret = device_create_file(adev->dev, &dev_attr_usbc_pd_fw); 342957430471SAndrey Grodzovsky 343057430471SAndrey Grodzovsky if (ret) 343157430471SAndrey Grodzovsky DRM_ERROR("Failed to create USBC PD FW control file!"); 343257430471SAndrey Grodzovsky 343357430471SAndrey Grodzovsky return ret; 343457430471SAndrey Grodzovsky } 343557430471SAndrey Grodzovsky 343657430471SAndrey Grodzovsky static void psp_sysfs_fini(struct amdgpu_device *adev) 343757430471SAndrey Grodzovsky { 343857430471SAndrey Grodzovsky device_remove_file(adev->dev, &dev_attr_usbc_pd_fw); 343957430471SAndrey Grodzovsky } 344057430471SAndrey Grodzovsky 34410e5ca0d1SHuang Rui const struct amdgpu_ip_block_version psp_v3_1_ip_block = 34420e5ca0d1SHuang Rui { 34430e5ca0d1SHuang Rui .type = AMD_IP_BLOCK_TYPE_PSP, 34440e5ca0d1SHuang Rui .major = 3, 34450e5ca0d1SHuang Rui .minor = 1, 34460e5ca0d1SHuang Rui .rev = 0, 34470e5ca0d1SHuang Rui .funcs = &psp_ip_funcs, 34480e5ca0d1SHuang Rui }; 3449dfbd6438SHuang Rui 3450dfbd6438SHuang Rui const struct amdgpu_ip_block_version psp_v10_0_ip_block = 3451dfbd6438SHuang Rui { 3452dfbd6438SHuang Rui .type = AMD_IP_BLOCK_TYPE_PSP, 3453dfbd6438SHuang Rui .major = 10, 3454dfbd6438SHuang Rui .minor = 0, 3455dfbd6438SHuang Rui .rev = 0, 3456dfbd6438SHuang Rui .funcs = &psp_ip_funcs, 3457dfbd6438SHuang Rui }; 3458654f761cSFeifei Xu 3459654f761cSFeifei Xu const struct amdgpu_ip_block_version psp_v11_0_ip_block = 3460654f761cSFeifei Xu { 3461654f761cSFeifei Xu .type = AMD_IP_BLOCK_TYPE_PSP, 3462654f761cSFeifei Xu .major = 11, 3463654f761cSFeifei Xu .minor = 0, 3464654f761cSFeifei Xu .rev = 0, 3465654f761cSFeifei Xu .funcs = &psp_ip_funcs, 3466654f761cSFeifei Xu }; 34676a7a0bdbSAaron Liu 34681c7916afSLang Yu const struct amdgpu_ip_block_version psp_v11_0_8_ip_block = { 34691c7916afSLang Yu .type = AMD_IP_BLOCK_TYPE_PSP, 34701c7916afSLang Yu .major = 11, 34711c7916afSLang Yu .minor = 0, 34721c7916afSLang Yu .rev = 8, 34731c7916afSLang Yu .funcs = &psp_ip_funcs, 34741c7916afSLang Yu }; 34751c7916afSLang Yu 34766a7a0bdbSAaron Liu const struct amdgpu_ip_block_version psp_v12_0_ip_block = 34776a7a0bdbSAaron Liu { 34786a7a0bdbSAaron Liu .type = AMD_IP_BLOCK_TYPE_PSP, 34796a7a0bdbSAaron Liu .major = 12, 34806a7a0bdbSAaron Liu .minor = 0, 34816a7a0bdbSAaron Liu .rev = 0, 34826a7a0bdbSAaron Liu .funcs = &psp_ip_funcs, 34836a7a0bdbSAaron Liu }; 34849fbd96a1SHawking Zhang 34859fbd96a1SHawking Zhang const struct amdgpu_ip_block_version psp_v13_0_ip_block = { 34869fbd96a1SHawking Zhang .type = AMD_IP_BLOCK_TYPE_PSP, 34879fbd96a1SHawking Zhang .major = 13, 34889fbd96a1SHawking Zhang .minor = 0, 34899fbd96a1SHawking Zhang .rev = 0, 34909fbd96a1SHawking Zhang .funcs = &psp_ip_funcs, 34919fbd96a1SHawking Zhang }; 3492