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> 27248a1d6fSMasahiro Yamada #include <drm/drmP.h> 280e5ca0d1SHuang Rui #include "amdgpu.h" 290e5ca0d1SHuang Rui #include "amdgpu_psp.h" 300e5ca0d1SHuang Rui #include "amdgpu_ucode.h" 310e5ca0d1SHuang Rui #include "soc15_common.h" 320e5ca0d1SHuang Rui #include "psp_v3_1.h" 33c1798b54SHuang Rui #include "psp_v10_0.h" 34654f761cSFeifei Xu #include "psp_v11_0.h" 350e5ca0d1SHuang Rui 360e5ca0d1SHuang Rui static void psp_set_funcs(struct amdgpu_device *adev); 370e5ca0d1SHuang Rui 380e5ca0d1SHuang Rui static int psp_early_init(void *handle) 390e5ca0d1SHuang Rui { 400e5ca0d1SHuang Rui struct amdgpu_device *adev = (struct amdgpu_device *)handle; 410e5ca0d1SHuang Rui 420e5ca0d1SHuang Rui psp_set_funcs(adev); 430e5ca0d1SHuang Rui 440e5ca0d1SHuang Rui return 0; 450e5ca0d1SHuang Rui } 460e5ca0d1SHuang Rui 470e5ca0d1SHuang Rui static int psp_sw_init(void *handle) 480e5ca0d1SHuang Rui { 490e5ca0d1SHuang Rui struct amdgpu_device *adev = (struct amdgpu_device *)handle; 500e5ca0d1SHuang Rui struct psp_context *psp = &adev->psp; 510e5ca0d1SHuang Rui int ret; 520e5ca0d1SHuang Rui 530e5ca0d1SHuang Rui switch (adev->asic_type) { 540e5ca0d1SHuang Rui case CHIP_VEGA10: 55ff13dc67SAlex Deucher case CHIP_VEGA12: 56e7f9ccb4SAlex Deucher psp_v3_1_set_psp_funcs(psp); 570e5ca0d1SHuang Rui break; 58c1798b54SHuang Rui case CHIP_RAVEN: 59e7f9ccb4SAlex Deucher psp_v10_0_set_psp_funcs(psp); 60c1798b54SHuang Rui break; 61654f761cSFeifei Xu case CHIP_VEGA20: 62654f761cSFeifei Xu psp_v11_0_set_psp_funcs(psp); 63654f761cSFeifei Xu break; 640e5ca0d1SHuang Rui default: 650e5ca0d1SHuang Rui return -EINVAL; 660e5ca0d1SHuang Rui } 670e5ca0d1SHuang Rui 680e5ca0d1SHuang Rui psp->adev = adev; 690e5ca0d1SHuang Rui 700e5ca0d1SHuang Rui ret = psp_init_microcode(psp); 710e5ca0d1SHuang Rui if (ret) { 720e5ca0d1SHuang Rui DRM_ERROR("Failed to load psp firmware!\n"); 730e5ca0d1SHuang Rui return ret; 740e5ca0d1SHuang Rui } 750e5ca0d1SHuang Rui 760e5ca0d1SHuang Rui return 0; 770e5ca0d1SHuang Rui } 780e5ca0d1SHuang Rui 790e5ca0d1SHuang Rui static int psp_sw_fini(void *handle) 800e5ca0d1SHuang Rui { 81c833d8aaSMonk Liu struct amdgpu_device *adev = (struct amdgpu_device *)handle; 82c833d8aaSMonk Liu 83c833d8aaSMonk Liu release_firmware(adev->psp.sos_fw); 84c833d8aaSMonk Liu adev->psp.sos_fw = NULL; 85c833d8aaSMonk Liu release_firmware(adev->psp.asd_fw); 86c833d8aaSMonk Liu adev->psp.asd_fw = NULL; 871d69511eSAlex Deucher if (adev->psp.ta_fw) { 8851e7177fSHawking Zhang release_firmware(adev->psp.ta_fw); 8951e7177fSHawking Zhang adev->psp.ta_fw = NULL; 901d69511eSAlex Deucher } 910e5ca0d1SHuang Rui return 0; 920e5ca0d1SHuang Rui } 930e5ca0d1SHuang Rui 940e5ca0d1SHuang Rui int psp_wait_for(struct psp_context *psp, uint32_t reg_index, 950e5ca0d1SHuang Rui uint32_t reg_val, uint32_t mask, bool check_changed) 960e5ca0d1SHuang Rui { 970e5ca0d1SHuang Rui uint32_t val; 980e5ca0d1SHuang Rui int i; 990e5ca0d1SHuang Rui struct amdgpu_device *adev = psp->adev; 1000e5ca0d1SHuang Rui 1010e5ca0d1SHuang Rui for (i = 0; i < adev->usec_timeout; i++) { 1022890decfSZhang, Jerry val = RREG32(reg_index); 1030e5ca0d1SHuang Rui if (check_changed) { 1040e5ca0d1SHuang Rui if (val != reg_val) 1050e5ca0d1SHuang Rui return 0; 1060e5ca0d1SHuang Rui } else { 1070e5ca0d1SHuang Rui if ((val & mask) == reg_val) 1080e5ca0d1SHuang Rui return 0; 1090e5ca0d1SHuang Rui } 1100e5ca0d1SHuang Rui udelay(1); 1110e5ca0d1SHuang Rui } 1120e5ca0d1SHuang Rui 1130e5ca0d1SHuang Rui return -ETIME; 1140e5ca0d1SHuang Rui } 1150e5ca0d1SHuang Rui 1160e5ca0d1SHuang Rui static int 1170e5ca0d1SHuang Rui psp_cmd_submit_buf(struct psp_context *psp, 1180e5ca0d1SHuang Rui struct amdgpu_firmware_info *ucode, 1190b25cbf9SHawking Zhang struct psp_gfx_cmd_resp *cmd, uint64_t fence_mc_addr) 1200e5ca0d1SHuang Rui { 1210e5ca0d1SHuang Rui int ret; 1220b25cbf9SHawking Zhang int index; 1230e5ca0d1SHuang Rui 124a1952da7SHuang Rui memset(psp->cmd_buf_mem, 0, PSP_CMD_BUFFER_SIZE); 1250e5ca0d1SHuang Rui 126a1952da7SHuang Rui memcpy(psp->cmd_buf_mem, cmd, sizeof(struct psp_gfx_cmd_resp)); 1270e5ca0d1SHuang Rui 1280b25cbf9SHawking Zhang index = atomic_inc_return(&psp->fence_value); 129a1952da7SHuang Rui ret = psp_cmd_submit(psp, ucode, psp->cmd_buf_mc_addr, 1300e5ca0d1SHuang Rui fence_mc_addr, index); 1310b25cbf9SHawking Zhang if (ret) { 1320b25cbf9SHawking Zhang atomic_dec(&psp->fence_value); 1330b25cbf9SHawking Zhang return ret; 134ca7f65c7Skbuild test robot } 1350e5ca0d1SHuang Rui 1360b25cbf9SHawking Zhang while (*((unsigned int *)psp->fence_buf) != index) 1370b25cbf9SHawking Zhang msleep(1); 1380b25cbf9SHawking Zhang 139466bcb75SAaron Liu /* In some cases, psp response status is not 0 even there is no 140466bcb75SAaron Liu * problem while the command is submitted. Some version of PSP FW 141466bcb75SAaron Liu * doesn't write 0 to that field. 142466bcb75SAaron Liu * So here we would like to only print a warning instead of an error 143466bcb75SAaron Liu * during psp initialization to avoid breaking hw_init and it doesn't 144466bcb75SAaron Liu * return -EINVAL. 145466bcb75SAaron Liu */ 14676223c54SXiangliang Yu if (psp->cmd_buf_mem->resp.status) { 14776223c54SXiangliang Yu if (ucode) 148466bcb75SAaron Liu DRM_WARN("failed to load ucode id (%d) ", 14976223c54SXiangliang Yu ucode->ucode_id); 150466bcb75SAaron Liu DRM_WARN("psp command failed and response status is (%d)\n", 15176223c54SXiangliang Yu psp->cmd_buf_mem->resp.status); 15228a16027SHuang Rui } 15328a16027SHuang Rui 154a363553cSXiangliang Yu /* get xGMI session id from response buffer */ 155a363553cSXiangliang Yu cmd->resp.session_id = psp->cmd_buf_mem->resp.session_id; 156a363553cSXiangliang Yu 157435198f3SJames Zhu if (ucode) { 158435198f3SJames Zhu ucode->tmr_mc_addr_lo = psp->cmd_buf_mem->resp.fw_addr_lo; 159435198f3SJames Zhu ucode->tmr_mc_addr_hi = psp->cmd_buf_mem->resp.fw_addr_hi; 160435198f3SJames Zhu } 161435198f3SJames Zhu 1620e5ca0d1SHuang Rui return ret; 1630e5ca0d1SHuang Rui } 1640e5ca0d1SHuang Rui 1655ec996dfSXiangliang Yu static void psp_prep_tmr_cmd_buf(struct psp_context *psp, 1665ec996dfSXiangliang Yu struct psp_gfx_cmd_resp *cmd, 1670e5ca0d1SHuang Rui uint64_t tmr_mc, uint32_t size) 1680e5ca0d1SHuang Rui { 1695ec996dfSXiangliang Yu if (psp_support_vmr_ring(psp)) 1705ec996dfSXiangliang Yu cmd->cmd_id = GFX_CMD_ID_SETUP_VMR; 1715ec996dfSXiangliang Yu else 1720e5ca0d1SHuang Rui cmd->cmd_id = GFX_CMD_ID_SETUP_TMR; 173f03defe0SAlex Deucher cmd->cmd.cmd_setup_tmr.buf_phy_addr_lo = lower_32_bits(tmr_mc); 174f03defe0SAlex Deucher cmd->cmd.cmd_setup_tmr.buf_phy_addr_hi = upper_32_bits(tmr_mc); 1750e5ca0d1SHuang Rui cmd->cmd.cmd_setup_tmr.buf_size = size; 1760e5ca0d1SHuang Rui } 1770e5ca0d1SHuang Rui 1780e5ca0d1SHuang Rui /* Set up Trusted Memory Region */ 1790e5ca0d1SHuang Rui static int psp_tmr_init(struct psp_context *psp) 1800e5ca0d1SHuang Rui { 1810e5ca0d1SHuang Rui int ret; 1820e5ca0d1SHuang Rui 1830e5ca0d1SHuang Rui /* 1840e5ca0d1SHuang Rui * Allocate 3M memory aligned to 1M from Frame Buffer (local 1850e5ca0d1SHuang Rui * physical). 1860e5ca0d1SHuang Rui * 1870e5ca0d1SHuang Rui * Note: this memory need be reserved till the driver 1880e5ca0d1SHuang Rui * uninitializes. 1890e5ca0d1SHuang Rui */ 1903082be1aSFeifei Xu ret = amdgpu_bo_create_kernel(psp->adev, PSP_TMR_SIZE, 0x100000, 1910e5ca0d1SHuang Rui AMDGPU_GEM_DOMAIN_VRAM, 1920e5ca0d1SHuang Rui &psp->tmr_bo, &psp->tmr_mc_addr, &psp->tmr_buf); 1936f2b1fccSHuang Rui 1946f2b1fccSHuang Rui return ret; 1956f2b1fccSHuang Rui } 1966f2b1fccSHuang Rui 1976f2b1fccSHuang Rui static int psp_tmr_load(struct psp_context *psp) 1986f2b1fccSHuang Rui { 1996f2b1fccSHuang Rui int ret; 2006f2b1fccSHuang Rui struct psp_gfx_cmd_resp *cmd; 2016f2b1fccSHuang Rui 2026f2b1fccSHuang Rui cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); 2036f2b1fccSHuang Rui if (!cmd) 2046f2b1fccSHuang Rui return -ENOMEM; 2050e5ca0d1SHuang Rui 2065ec996dfSXiangliang Yu psp_prep_tmr_cmd_buf(psp, cmd, psp->tmr_mc_addr, PSP_TMR_SIZE); 2073082be1aSFeifei Xu DRM_INFO("reserve 0x%x from 0x%llx for PSP TMR SIZE\n", 2083082be1aSFeifei Xu PSP_TMR_SIZE, psp->tmr_mc_addr); 2090e5ca0d1SHuang Rui 2100e5ca0d1SHuang Rui ret = psp_cmd_submit_buf(psp, NULL, cmd, 2110b25cbf9SHawking Zhang psp->fence_buf_mc_addr); 2120e5ca0d1SHuang Rui if (ret) 2136f2b1fccSHuang Rui goto failed; 2140e5ca0d1SHuang Rui 2150e5ca0d1SHuang Rui kfree(cmd); 2160e5ca0d1SHuang Rui 2170e5ca0d1SHuang Rui return 0; 2180e5ca0d1SHuang Rui 2190e5ca0d1SHuang Rui failed: 2200e5ca0d1SHuang Rui kfree(cmd); 2210e5ca0d1SHuang Rui return ret; 2220e5ca0d1SHuang Rui } 2230e5ca0d1SHuang Rui 2240e5ca0d1SHuang Rui static void psp_prep_asd_cmd_buf(struct psp_gfx_cmd_resp *cmd, 2250e5ca0d1SHuang Rui uint64_t asd_mc, uint64_t asd_mc_shared, 2260e5ca0d1SHuang Rui uint32_t size, uint32_t shared_size) 2270e5ca0d1SHuang Rui { 2280e5ca0d1SHuang Rui cmd->cmd_id = GFX_CMD_ID_LOAD_ASD; 2290e5ca0d1SHuang Rui cmd->cmd.cmd_load_ta.app_phy_addr_lo = lower_32_bits(asd_mc); 2300e5ca0d1SHuang Rui cmd->cmd.cmd_load_ta.app_phy_addr_hi = upper_32_bits(asd_mc); 2310e5ca0d1SHuang Rui cmd->cmd.cmd_load_ta.app_len = size; 2320e5ca0d1SHuang Rui 2330e5ca0d1SHuang Rui cmd->cmd.cmd_load_ta.cmd_buf_phy_addr_lo = lower_32_bits(asd_mc_shared); 2340e5ca0d1SHuang Rui cmd->cmd.cmd_load_ta.cmd_buf_phy_addr_hi = upper_32_bits(asd_mc_shared); 2350e5ca0d1SHuang Rui cmd->cmd.cmd_load_ta.cmd_buf_len = shared_size; 2360e5ca0d1SHuang Rui } 2370e5ca0d1SHuang Rui 238f5cfef98SHuang Rui static int psp_asd_init(struct psp_context *psp) 2390e5ca0d1SHuang Rui { 2400e5ca0d1SHuang Rui int ret; 2410e5ca0d1SHuang Rui 2420e5ca0d1SHuang Rui /* 2430e5ca0d1SHuang Rui * Allocate 16k memory aligned to 4k from Frame Buffer (local 2440e5ca0d1SHuang Rui * physical) for shared ASD <-> Driver 2450e5ca0d1SHuang Rui */ 246f5cfef98SHuang Rui ret = amdgpu_bo_create_kernel(psp->adev, PSP_ASD_SHARED_MEM_SIZE, 247f5cfef98SHuang Rui PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM, 248f5cfef98SHuang Rui &psp->asd_shared_bo, 249f5cfef98SHuang Rui &psp->asd_shared_mc_addr, 250f5cfef98SHuang Rui &psp->asd_shared_buf); 2510e5ca0d1SHuang Rui 2520e5ca0d1SHuang Rui return ret; 2530e5ca0d1SHuang Rui } 2540e5ca0d1SHuang Rui 2550e5ca0d1SHuang Rui static int psp_asd_load(struct psp_context *psp) 2560e5ca0d1SHuang Rui { 2570e5ca0d1SHuang Rui int ret; 2580e5ca0d1SHuang Rui struct psp_gfx_cmd_resp *cmd; 2590e5ca0d1SHuang Rui 260943cafb8SXiangliang Yu /* If PSP version doesn't match ASD version, asd loading will be failed. 261943cafb8SXiangliang Yu * add workaround to bypass it for sriov now. 262943cafb8SXiangliang Yu * TODO: add version check to make it common 263943cafb8SXiangliang Yu */ 264943cafb8SXiangliang Yu if (amdgpu_sriov_vf(psp->adev)) 265943cafb8SXiangliang Yu return 0; 266943cafb8SXiangliang Yu 2670e5ca0d1SHuang Rui cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); 2680e5ca0d1SHuang Rui if (!cmd) 2690e5ca0d1SHuang Rui return -ENOMEM; 2700e5ca0d1SHuang Rui 2712b0c3aeeSHuang Rui memset(psp->fw_pri_buf, 0, PSP_1_MEG); 2722b0c3aeeSHuang Rui memcpy(psp->fw_pri_buf, psp->asd_start_addr, psp->asd_ucode_size); 2730e5ca0d1SHuang Rui 274f5cfef98SHuang Rui psp_prep_asd_cmd_buf(cmd, psp->fw_pri_mc_addr, psp->asd_shared_mc_addr, 2750e5ca0d1SHuang Rui psp->asd_ucode_size, PSP_ASD_SHARED_MEM_SIZE); 2760e5ca0d1SHuang Rui 2770e5ca0d1SHuang Rui ret = psp_cmd_submit_buf(psp, NULL, cmd, 2780b25cbf9SHawking Zhang psp->fence_buf_mc_addr); 2790e5ca0d1SHuang Rui 2800e5ca0d1SHuang Rui kfree(cmd); 2810e5ca0d1SHuang Rui 2820e5ca0d1SHuang Rui return ret; 2830e5ca0d1SHuang Rui } 2840e5ca0d1SHuang Rui 28597c8d171SHawking Zhang static void psp_prep_xgmi_ta_load_cmd_buf(struct psp_gfx_cmd_resp *cmd, 28697c8d171SHawking Zhang uint64_t xgmi_ta_mc, uint64_t xgmi_mc_shared, 28797c8d171SHawking Zhang uint32_t xgmi_ta_size, uint32_t shared_size) 28897c8d171SHawking Zhang { 28997c8d171SHawking Zhang cmd->cmd_id = GFX_CMD_ID_LOAD_TA; 29097c8d171SHawking Zhang cmd->cmd.cmd_load_ta.app_phy_addr_lo = lower_32_bits(xgmi_ta_mc); 29197c8d171SHawking Zhang cmd->cmd.cmd_load_ta.app_phy_addr_hi = upper_32_bits(xgmi_ta_mc); 29297c8d171SHawking Zhang cmd->cmd.cmd_load_ta.app_len = xgmi_ta_size; 29397c8d171SHawking Zhang 29497c8d171SHawking Zhang cmd->cmd.cmd_load_ta.cmd_buf_phy_addr_lo = lower_32_bits(xgmi_mc_shared); 29597c8d171SHawking Zhang cmd->cmd.cmd_load_ta.cmd_buf_phy_addr_hi = upper_32_bits(xgmi_mc_shared); 29697c8d171SHawking Zhang cmd->cmd.cmd_load_ta.cmd_buf_len = shared_size; 29797c8d171SHawking Zhang } 29897c8d171SHawking Zhang 29997c8d171SHawking Zhang static int psp_xgmi_init_shared_buf(struct psp_context *psp) 30097c8d171SHawking Zhang { 30197c8d171SHawking Zhang int ret; 30297c8d171SHawking Zhang 30397c8d171SHawking Zhang /* 30497c8d171SHawking Zhang * Allocate 16k memory aligned to 4k from Frame Buffer (local 30597c8d171SHawking Zhang * physical) for xgmi ta <-> Driver 30697c8d171SHawking Zhang */ 30797c8d171SHawking Zhang ret = amdgpu_bo_create_kernel(psp->adev, PSP_XGMI_SHARED_MEM_SIZE, 30897c8d171SHawking Zhang PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM, 30997c8d171SHawking Zhang &psp->xgmi_context.xgmi_shared_bo, 31097c8d171SHawking Zhang &psp->xgmi_context.xgmi_shared_mc_addr, 31197c8d171SHawking Zhang &psp->xgmi_context.xgmi_shared_buf); 31297c8d171SHawking Zhang 31397c8d171SHawking Zhang return ret; 31497c8d171SHawking Zhang } 31597c8d171SHawking Zhang 31697c8d171SHawking Zhang static int psp_xgmi_load(struct psp_context *psp) 31797c8d171SHawking Zhang { 31897c8d171SHawking Zhang int ret; 31997c8d171SHawking Zhang struct psp_gfx_cmd_resp *cmd; 32097c8d171SHawking Zhang 32197c8d171SHawking Zhang /* 32297c8d171SHawking Zhang * TODO: bypass the loading in sriov for now 32397c8d171SHawking Zhang */ 32497c8d171SHawking Zhang if (amdgpu_sriov_vf(psp->adev)) 32597c8d171SHawking Zhang return 0; 32697c8d171SHawking Zhang 32797c8d171SHawking Zhang cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); 32897c8d171SHawking Zhang if (!cmd) 32997c8d171SHawking Zhang return -ENOMEM; 33097c8d171SHawking Zhang 33197c8d171SHawking Zhang memset(psp->fw_pri_buf, 0, PSP_1_MEG); 33297c8d171SHawking Zhang memcpy(psp->fw_pri_buf, psp->ta_xgmi_start_addr, psp->ta_xgmi_ucode_size); 33397c8d171SHawking Zhang 33497c8d171SHawking Zhang psp_prep_xgmi_ta_load_cmd_buf(cmd, psp->fw_pri_mc_addr, 33597c8d171SHawking Zhang psp->xgmi_context.xgmi_shared_mc_addr, 33697c8d171SHawking Zhang psp->ta_xgmi_ucode_size, PSP_XGMI_SHARED_MEM_SIZE); 33797c8d171SHawking Zhang 33897c8d171SHawking Zhang ret = psp_cmd_submit_buf(psp, NULL, cmd, 33997c8d171SHawking Zhang psp->fence_buf_mc_addr); 34097c8d171SHawking Zhang 34197c8d171SHawking Zhang if (!ret) { 34297c8d171SHawking Zhang psp->xgmi_context.initialized = 1; 34397c8d171SHawking Zhang psp->xgmi_context.session_id = cmd->resp.session_id; 34497c8d171SHawking Zhang } 34597c8d171SHawking Zhang 34697c8d171SHawking Zhang kfree(cmd); 34797c8d171SHawking Zhang 34897c8d171SHawking Zhang return ret; 34997c8d171SHawking Zhang } 35097c8d171SHawking Zhang 35197c8d171SHawking Zhang static void psp_prep_xgmi_ta_unload_cmd_buf(struct psp_gfx_cmd_resp *cmd, 35297c8d171SHawking Zhang uint32_t xgmi_session_id) 35397c8d171SHawking Zhang { 35497c8d171SHawking Zhang cmd->cmd_id = GFX_CMD_ID_UNLOAD_TA; 35597c8d171SHawking Zhang cmd->cmd.cmd_unload_ta.session_id = xgmi_session_id; 35697c8d171SHawking Zhang } 35797c8d171SHawking Zhang 35897c8d171SHawking Zhang static int psp_xgmi_unload(struct psp_context *psp) 35997c8d171SHawking Zhang { 36097c8d171SHawking Zhang int ret; 36197c8d171SHawking Zhang struct psp_gfx_cmd_resp *cmd; 36297c8d171SHawking Zhang 36397c8d171SHawking Zhang /* 36497c8d171SHawking Zhang * TODO: bypass the unloading in sriov for now 36597c8d171SHawking Zhang */ 36697c8d171SHawking Zhang if (amdgpu_sriov_vf(psp->adev)) 36797c8d171SHawking Zhang return 0; 36897c8d171SHawking Zhang 36997c8d171SHawking Zhang cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); 37097c8d171SHawking Zhang if (!cmd) 37197c8d171SHawking Zhang return -ENOMEM; 37297c8d171SHawking Zhang 37397c8d171SHawking Zhang psp_prep_xgmi_ta_unload_cmd_buf(cmd, psp->xgmi_context.session_id); 37497c8d171SHawking Zhang 37597c8d171SHawking Zhang ret = psp_cmd_submit_buf(psp, NULL, cmd, 37697c8d171SHawking Zhang psp->fence_buf_mc_addr); 37797c8d171SHawking Zhang 37897c8d171SHawking Zhang kfree(cmd); 37997c8d171SHawking Zhang 38097c8d171SHawking Zhang return ret; 38197c8d171SHawking Zhang } 38297c8d171SHawking Zhang 383ca6e1e59SHawking Zhang static void psp_prep_xgmi_ta_invoke_cmd_buf(struct psp_gfx_cmd_resp *cmd, 384ca6e1e59SHawking Zhang uint32_t ta_cmd_id, 385ca6e1e59SHawking Zhang uint32_t xgmi_session_id) 386ca6e1e59SHawking Zhang { 387ca6e1e59SHawking Zhang cmd->cmd_id = GFX_CMD_ID_INVOKE_CMD; 388ca6e1e59SHawking Zhang cmd->cmd.cmd_invoke_cmd.session_id = xgmi_session_id; 389ca6e1e59SHawking Zhang cmd->cmd.cmd_invoke_cmd.ta_cmd_id = ta_cmd_id; 390ca6e1e59SHawking Zhang /* Note: cmd_invoke_cmd.buf is not used for now */ 391ca6e1e59SHawking Zhang } 392ca6e1e59SHawking Zhang 393ca6e1e59SHawking Zhang int psp_xgmi_invoke(struct psp_context *psp, uint32_t ta_cmd_id) 394ca6e1e59SHawking Zhang { 395ca6e1e59SHawking Zhang int ret; 396ca6e1e59SHawking Zhang struct psp_gfx_cmd_resp *cmd; 397ca6e1e59SHawking Zhang 398ca6e1e59SHawking Zhang /* 399ca6e1e59SHawking Zhang * TODO: bypass the loading in sriov for now 400ca6e1e59SHawking Zhang */ 401ca6e1e59SHawking Zhang if (amdgpu_sriov_vf(psp->adev)) 402ca6e1e59SHawking Zhang return 0; 403ca6e1e59SHawking Zhang 404ca6e1e59SHawking Zhang cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); 405ca6e1e59SHawking Zhang if (!cmd) 406ca6e1e59SHawking Zhang return -ENOMEM; 407ca6e1e59SHawking Zhang 408ca6e1e59SHawking Zhang psp_prep_xgmi_ta_invoke_cmd_buf(cmd, ta_cmd_id, 409ca6e1e59SHawking Zhang psp->xgmi_context.session_id); 410ca6e1e59SHawking Zhang 411ca6e1e59SHawking Zhang ret = psp_cmd_submit_buf(psp, NULL, cmd, 412ca6e1e59SHawking Zhang psp->fence_buf_mc_addr); 413ca6e1e59SHawking Zhang 414ca6e1e59SHawking Zhang kfree(cmd); 415ca6e1e59SHawking Zhang 416ca6e1e59SHawking Zhang return ret; 417ca6e1e59SHawking Zhang } 418ca6e1e59SHawking Zhang 4193e2e2ab5SHawking Zhang static int psp_xgmi_terminate(struct psp_context *psp) 4203e2e2ab5SHawking Zhang { 4213e2e2ab5SHawking Zhang int ret; 4223e2e2ab5SHawking Zhang 4233e2e2ab5SHawking Zhang if (!psp->xgmi_context.initialized) 4243e2e2ab5SHawking Zhang return 0; 4253e2e2ab5SHawking Zhang 4263e2e2ab5SHawking Zhang ret = psp_xgmi_unload(psp); 4273e2e2ab5SHawking Zhang if (ret) 4283e2e2ab5SHawking Zhang return ret; 4293e2e2ab5SHawking Zhang 4303e2e2ab5SHawking Zhang psp->xgmi_context.initialized = 0; 4313e2e2ab5SHawking Zhang 4323e2e2ab5SHawking Zhang /* free xgmi shared memory */ 4333e2e2ab5SHawking Zhang amdgpu_bo_free_kernel(&psp->xgmi_context.xgmi_shared_bo, 4343e2e2ab5SHawking Zhang &psp->xgmi_context.xgmi_shared_mc_addr, 4353e2e2ab5SHawking Zhang &psp->xgmi_context.xgmi_shared_buf); 4363e2e2ab5SHawking Zhang 4373e2e2ab5SHawking Zhang return 0; 4383e2e2ab5SHawking Zhang } 4393e2e2ab5SHawking Zhang 4403e2e2ab5SHawking Zhang static int psp_xgmi_initialize(struct psp_context *psp) 4413e2e2ab5SHawking Zhang { 4423e2e2ab5SHawking Zhang struct ta_xgmi_shared_memory *xgmi_cmd; 4433e2e2ab5SHawking Zhang int ret; 4443e2e2ab5SHawking Zhang 4451d69511eSAlex Deucher if (!psp->adev->psp.ta_fw) 4461d69511eSAlex Deucher return -ENOENT; 4471d69511eSAlex Deucher 4483e2e2ab5SHawking Zhang if (!psp->xgmi_context.initialized) { 4493e2e2ab5SHawking Zhang ret = psp_xgmi_init_shared_buf(psp); 4503e2e2ab5SHawking Zhang if (ret) 4513e2e2ab5SHawking Zhang return ret; 4523e2e2ab5SHawking Zhang } 4533e2e2ab5SHawking Zhang 4543e2e2ab5SHawking Zhang /* Load XGMI TA */ 4553e2e2ab5SHawking Zhang ret = psp_xgmi_load(psp); 4563e2e2ab5SHawking Zhang if (ret) 4573e2e2ab5SHawking Zhang return ret; 4583e2e2ab5SHawking Zhang 4593e2e2ab5SHawking Zhang /* Initialize XGMI session */ 4603e2e2ab5SHawking Zhang xgmi_cmd = (struct ta_xgmi_shared_memory *)(psp->xgmi_context.xgmi_shared_buf); 4613e2e2ab5SHawking Zhang memset(xgmi_cmd, 0, sizeof(struct ta_xgmi_shared_memory)); 4623e2e2ab5SHawking Zhang xgmi_cmd->cmd_id = TA_COMMAND_XGMI__INITIALIZE; 4633e2e2ab5SHawking Zhang 4643e2e2ab5SHawking Zhang ret = psp_xgmi_invoke(psp, xgmi_cmd->cmd_id); 4653e2e2ab5SHawking Zhang 4663e2e2ab5SHawking Zhang return ret; 4673e2e2ab5SHawking Zhang } 4683e2e2ab5SHawking Zhang 469*5e5d3154Sxinhui pan // ras begin 470*5e5d3154Sxinhui pan static void psp_prep_ras_ta_load_cmd_buf(struct psp_gfx_cmd_resp *cmd, 471*5e5d3154Sxinhui pan uint64_t ras_ta_mc, uint64_t ras_mc_shared, 472*5e5d3154Sxinhui pan uint32_t ras_ta_size, uint32_t shared_size) 473*5e5d3154Sxinhui pan { 474*5e5d3154Sxinhui pan cmd->cmd_id = GFX_CMD_ID_LOAD_TA; 475*5e5d3154Sxinhui pan cmd->cmd.cmd_load_ta.app_phy_addr_lo = lower_32_bits(ras_ta_mc); 476*5e5d3154Sxinhui pan cmd->cmd.cmd_load_ta.app_phy_addr_hi = upper_32_bits(ras_ta_mc); 477*5e5d3154Sxinhui pan cmd->cmd.cmd_load_ta.app_len = ras_ta_size; 478*5e5d3154Sxinhui pan 479*5e5d3154Sxinhui pan cmd->cmd.cmd_load_ta.cmd_buf_phy_addr_lo = lower_32_bits(ras_mc_shared); 480*5e5d3154Sxinhui pan cmd->cmd.cmd_load_ta.cmd_buf_phy_addr_hi = upper_32_bits(ras_mc_shared); 481*5e5d3154Sxinhui pan cmd->cmd.cmd_load_ta.cmd_buf_len = shared_size; 482*5e5d3154Sxinhui pan } 483*5e5d3154Sxinhui pan 484*5e5d3154Sxinhui pan static int psp_ras_init_shared_buf(struct psp_context *psp) 485*5e5d3154Sxinhui pan { 486*5e5d3154Sxinhui pan int ret; 487*5e5d3154Sxinhui pan 488*5e5d3154Sxinhui pan /* 489*5e5d3154Sxinhui pan * Allocate 16k memory aligned to 4k from Frame Buffer (local 490*5e5d3154Sxinhui pan * physical) for ras ta <-> Driver 491*5e5d3154Sxinhui pan */ 492*5e5d3154Sxinhui pan ret = amdgpu_bo_create_kernel(psp->adev, PSP_RAS_SHARED_MEM_SIZE, 493*5e5d3154Sxinhui pan PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM, 494*5e5d3154Sxinhui pan &psp->ras.ras_shared_bo, 495*5e5d3154Sxinhui pan &psp->ras.ras_shared_mc_addr, 496*5e5d3154Sxinhui pan &psp->ras.ras_shared_buf); 497*5e5d3154Sxinhui pan 498*5e5d3154Sxinhui pan return ret; 499*5e5d3154Sxinhui pan } 500*5e5d3154Sxinhui pan 501*5e5d3154Sxinhui pan static int psp_ras_load(struct psp_context *psp) 502*5e5d3154Sxinhui pan { 503*5e5d3154Sxinhui pan int ret; 504*5e5d3154Sxinhui pan struct psp_gfx_cmd_resp *cmd; 505*5e5d3154Sxinhui pan 506*5e5d3154Sxinhui pan /* 507*5e5d3154Sxinhui pan * TODO: bypass the loading in sriov for now 508*5e5d3154Sxinhui pan */ 509*5e5d3154Sxinhui pan if (amdgpu_sriov_vf(psp->adev)) 510*5e5d3154Sxinhui pan return 0; 511*5e5d3154Sxinhui pan 512*5e5d3154Sxinhui pan cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); 513*5e5d3154Sxinhui pan if (!cmd) 514*5e5d3154Sxinhui pan return -ENOMEM; 515*5e5d3154Sxinhui pan 516*5e5d3154Sxinhui pan memset(psp->fw_pri_buf, 0, PSP_1_MEG); 517*5e5d3154Sxinhui pan memcpy(psp->fw_pri_buf, psp->ta_ras_start_addr, psp->ta_ras_ucode_size); 518*5e5d3154Sxinhui pan 519*5e5d3154Sxinhui pan psp_prep_ras_ta_load_cmd_buf(cmd, psp->fw_pri_mc_addr, 520*5e5d3154Sxinhui pan psp->ras.ras_shared_mc_addr, 521*5e5d3154Sxinhui pan psp->ta_ras_ucode_size, PSP_RAS_SHARED_MEM_SIZE); 522*5e5d3154Sxinhui pan 523*5e5d3154Sxinhui pan ret = psp_cmd_submit_buf(psp, NULL, cmd, 524*5e5d3154Sxinhui pan psp->fence_buf_mc_addr); 525*5e5d3154Sxinhui pan 526*5e5d3154Sxinhui pan if (!ret) { 527*5e5d3154Sxinhui pan psp->ras.ras_initialized = 1; 528*5e5d3154Sxinhui pan psp->ras.session_id = cmd->resp.session_id; 529*5e5d3154Sxinhui pan } 530*5e5d3154Sxinhui pan 531*5e5d3154Sxinhui pan kfree(cmd); 532*5e5d3154Sxinhui pan 533*5e5d3154Sxinhui pan return ret; 534*5e5d3154Sxinhui pan } 535*5e5d3154Sxinhui pan 536*5e5d3154Sxinhui pan static void psp_prep_ras_ta_unload_cmd_buf(struct psp_gfx_cmd_resp *cmd, 537*5e5d3154Sxinhui pan uint32_t ras_session_id) 538*5e5d3154Sxinhui pan { 539*5e5d3154Sxinhui pan cmd->cmd_id = GFX_CMD_ID_UNLOAD_TA; 540*5e5d3154Sxinhui pan cmd->cmd.cmd_unload_ta.session_id = ras_session_id; 541*5e5d3154Sxinhui pan } 542*5e5d3154Sxinhui pan 543*5e5d3154Sxinhui pan static int psp_ras_unload(struct psp_context *psp) 544*5e5d3154Sxinhui pan { 545*5e5d3154Sxinhui pan int ret; 546*5e5d3154Sxinhui pan struct psp_gfx_cmd_resp *cmd; 547*5e5d3154Sxinhui pan 548*5e5d3154Sxinhui pan /* 549*5e5d3154Sxinhui pan * TODO: bypass the unloading in sriov for now 550*5e5d3154Sxinhui pan */ 551*5e5d3154Sxinhui pan if (amdgpu_sriov_vf(psp->adev)) 552*5e5d3154Sxinhui pan return 0; 553*5e5d3154Sxinhui pan 554*5e5d3154Sxinhui pan cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); 555*5e5d3154Sxinhui pan if (!cmd) 556*5e5d3154Sxinhui pan return -ENOMEM; 557*5e5d3154Sxinhui pan 558*5e5d3154Sxinhui pan psp_prep_ras_ta_unload_cmd_buf(cmd, psp->ras.session_id); 559*5e5d3154Sxinhui pan 560*5e5d3154Sxinhui pan ret = psp_cmd_submit_buf(psp, NULL, cmd, 561*5e5d3154Sxinhui pan psp->fence_buf_mc_addr); 562*5e5d3154Sxinhui pan 563*5e5d3154Sxinhui pan kfree(cmd); 564*5e5d3154Sxinhui pan 565*5e5d3154Sxinhui pan return ret; 566*5e5d3154Sxinhui pan } 567*5e5d3154Sxinhui pan 568*5e5d3154Sxinhui pan static void psp_prep_ras_ta_invoke_cmd_buf(struct psp_gfx_cmd_resp *cmd, 569*5e5d3154Sxinhui pan uint32_t ta_cmd_id, 570*5e5d3154Sxinhui pan uint32_t ras_session_id) 571*5e5d3154Sxinhui pan { 572*5e5d3154Sxinhui pan cmd->cmd_id = GFX_CMD_ID_INVOKE_CMD; 573*5e5d3154Sxinhui pan cmd->cmd.cmd_invoke_cmd.session_id = ras_session_id; 574*5e5d3154Sxinhui pan cmd->cmd.cmd_invoke_cmd.ta_cmd_id = ta_cmd_id; 575*5e5d3154Sxinhui pan /* Note: cmd_invoke_cmd.buf is not used for now */ 576*5e5d3154Sxinhui pan } 577*5e5d3154Sxinhui pan 578*5e5d3154Sxinhui pan int psp_ras_invoke(struct psp_context *psp, uint32_t ta_cmd_id) 579*5e5d3154Sxinhui pan { 580*5e5d3154Sxinhui pan int ret; 581*5e5d3154Sxinhui pan struct psp_gfx_cmd_resp *cmd; 582*5e5d3154Sxinhui pan 583*5e5d3154Sxinhui pan /* 584*5e5d3154Sxinhui pan * TODO: bypass the loading in sriov for now 585*5e5d3154Sxinhui pan */ 586*5e5d3154Sxinhui pan if (amdgpu_sriov_vf(psp->adev)) 587*5e5d3154Sxinhui pan return 0; 588*5e5d3154Sxinhui pan 589*5e5d3154Sxinhui pan cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); 590*5e5d3154Sxinhui pan if (!cmd) 591*5e5d3154Sxinhui pan return -ENOMEM; 592*5e5d3154Sxinhui pan 593*5e5d3154Sxinhui pan psp_prep_ras_ta_invoke_cmd_buf(cmd, ta_cmd_id, 594*5e5d3154Sxinhui pan psp->ras.session_id); 595*5e5d3154Sxinhui pan 596*5e5d3154Sxinhui pan ret = psp_cmd_submit_buf(psp, NULL, cmd, 597*5e5d3154Sxinhui pan psp->fence_buf_mc_addr); 598*5e5d3154Sxinhui pan 599*5e5d3154Sxinhui pan kfree(cmd); 600*5e5d3154Sxinhui pan 601*5e5d3154Sxinhui pan return ret; 602*5e5d3154Sxinhui pan } 603*5e5d3154Sxinhui pan 604*5e5d3154Sxinhui pan int psp_ras_enable_features(struct psp_context *psp, 605*5e5d3154Sxinhui pan union ta_ras_cmd_input *info, bool enable) 606*5e5d3154Sxinhui pan { 607*5e5d3154Sxinhui pan struct ta_ras_shared_memory *ras_cmd; 608*5e5d3154Sxinhui pan int ret; 609*5e5d3154Sxinhui pan 610*5e5d3154Sxinhui pan if (!psp->ras.ras_initialized) 611*5e5d3154Sxinhui pan return -EINVAL; 612*5e5d3154Sxinhui pan 613*5e5d3154Sxinhui pan ras_cmd = (struct ta_ras_shared_memory *)psp->ras.ras_shared_buf; 614*5e5d3154Sxinhui pan memset(ras_cmd, 0, sizeof(struct ta_ras_shared_memory)); 615*5e5d3154Sxinhui pan 616*5e5d3154Sxinhui pan if (enable) 617*5e5d3154Sxinhui pan ras_cmd->cmd_id = TA_RAS_COMMAND__ENABLE_FEATURES; 618*5e5d3154Sxinhui pan else 619*5e5d3154Sxinhui pan ras_cmd->cmd_id = TA_RAS_COMMAND__DISABLE_FEATURES; 620*5e5d3154Sxinhui pan 621*5e5d3154Sxinhui pan ras_cmd->ras_in_message = *info; 622*5e5d3154Sxinhui pan 623*5e5d3154Sxinhui pan ret = psp_ras_invoke(psp, ras_cmd->cmd_id); 624*5e5d3154Sxinhui pan if (ret) 625*5e5d3154Sxinhui pan return -EINVAL; 626*5e5d3154Sxinhui pan 627*5e5d3154Sxinhui pan return ras_cmd->ras_status; 628*5e5d3154Sxinhui pan } 629*5e5d3154Sxinhui pan 630*5e5d3154Sxinhui pan static int psp_ras_terminate(struct psp_context *psp) 631*5e5d3154Sxinhui pan { 632*5e5d3154Sxinhui pan int ret; 633*5e5d3154Sxinhui pan 634*5e5d3154Sxinhui pan if (!psp->ras.ras_initialized) 635*5e5d3154Sxinhui pan return 0; 636*5e5d3154Sxinhui pan 637*5e5d3154Sxinhui pan ret = psp_ras_unload(psp); 638*5e5d3154Sxinhui pan if (ret) 639*5e5d3154Sxinhui pan return ret; 640*5e5d3154Sxinhui pan 641*5e5d3154Sxinhui pan psp->ras.ras_initialized = 0; 642*5e5d3154Sxinhui pan 643*5e5d3154Sxinhui pan /* free ras shared memory */ 644*5e5d3154Sxinhui pan amdgpu_bo_free_kernel(&psp->ras.ras_shared_bo, 645*5e5d3154Sxinhui pan &psp->ras.ras_shared_mc_addr, 646*5e5d3154Sxinhui pan &psp->ras.ras_shared_buf); 647*5e5d3154Sxinhui pan 648*5e5d3154Sxinhui pan return 0; 649*5e5d3154Sxinhui pan } 650*5e5d3154Sxinhui pan 651*5e5d3154Sxinhui pan static int psp_ras_initialize(struct psp_context *psp) 652*5e5d3154Sxinhui pan { 653*5e5d3154Sxinhui pan int ret; 654*5e5d3154Sxinhui pan 655*5e5d3154Sxinhui pan if (!psp->ras.ras_initialized) { 656*5e5d3154Sxinhui pan ret = psp_ras_init_shared_buf(psp); 657*5e5d3154Sxinhui pan if (ret) 658*5e5d3154Sxinhui pan return ret; 659*5e5d3154Sxinhui pan } 660*5e5d3154Sxinhui pan 661*5e5d3154Sxinhui pan ret = psp_ras_load(psp); 662*5e5d3154Sxinhui pan if (ret) 663*5e5d3154Sxinhui pan return ret; 664*5e5d3154Sxinhui pan 665*5e5d3154Sxinhui pan return 0; 666*5e5d3154Sxinhui pan } 667*5e5d3154Sxinhui pan // ras end 668*5e5d3154Sxinhui pan 669be70bbdaSHuang Rui static int psp_hw_start(struct psp_context *psp) 670be70bbdaSHuang Rui { 67155981bd2SMonk Liu struct amdgpu_device *adev = psp->adev; 672be70bbdaSHuang Rui int ret; 673be70bbdaSHuang Rui 67413a752e3SMonk Liu if (!amdgpu_sriov_vf(adev) || !adev->in_gpu_reset) { 6750e5ca0d1SHuang Rui ret = psp_bootloader_load_sysdrv(psp); 6760e5ca0d1SHuang Rui if (ret) 677be70bbdaSHuang Rui return ret; 6780e5ca0d1SHuang Rui 6790e5ca0d1SHuang Rui ret = psp_bootloader_load_sos(psp); 6800e5ca0d1SHuang Rui if (ret) 681be70bbdaSHuang Rui return ret; 68255981bd2SMonk Liu } 6830e5ca0d1SHuang Rui 684be70bbdaSHuang Rui ret = psp_ring_create(psp, PSP_RING_TYPE__KM); 6850e5ca0d1SHuang Rui if (ret) 686be70bbdaSHuang Rui return ret; 6870e5ca0d1SHuang Rui 688be70bbdaSHuang Rui ret = psp_tmr_load(psp); 6890e5ca0d1SHuang Rui if (ret) 690be70bbdaSHuang Rui return ret; 6910e5ca0d1SHuang Rui 6920e5ca0d1SHuang Rui ret = psp_asd_load(psp); 6930e5ca0d1SHuang Rui if (ret) 694be70bbdaSHuang Rui return ret; 695be70bbdaSHuang Rui 6963e2e2ab5SHawking Zhang if (adev->gmc.xgmi.num_physical_nodes > 1) { 6973e2e2ab5SHawking Zhang ret = psp_xgmi_initialize(psp); 6983e2e2ab5SHawking Zhang /* Warning the XGMI seesion initialize failure 6993e2e2ab5SHawking Zhang * Instead of stop driver initialization 7003e2e2ab5SHawking Zhang */ 7013e2e2ab5SHawking Zhang if (ret) 7023e2e2ab5SHawking Zhang dev_err(psp->adev->dev, 7033e2e2ab5SHawking Zhang "XGMI: Failed to initialize XGMI session\n"); 7043e2e2ab5SHawking Zhang } 705*5e5d3154Sxinhui pan 706*5e5d3154Sxinhui pan ret = psp_ras_initialize(psp); 707*5e5d3154Sxinhui pan if (ret) 708*5e5d3154Sxinhui pan dev_err(psp->adev->dev, 709*5e5d3154Sxinhui pan "RAS: Failed to initialize RAS\n"); 710*5e5d3154Sxinhui pan 711be70bbdaSHuang Rui return 0; 712be70bbdaSHuang Rui } 713be70bbdaSHuang Rui 714be4630d9SHawking Zhang static int psp_get_fw_type(struct amdgpu_firmware_info *ucode, 715be4630d9SHawking Zhang enum psp_gfx_fw_type *type) 716be4630d9SHawking Zhang { 717be4630d9SHawking Zhang switch (ucode->ucode_id) { 718be4630d9SHawking Zhang case AMDGPU_UCODE_ID_SDMA0: 719be4630d9SHawking Zhang *type = GFX_FW_TYPE_SDMA0; 720be4630d9SHawking Zhang break; 721be4630d9SHawking Zhang case AMDGPU_UCODE_ID_SDMA1: 722be4630d9SHawking Zhang *type = GFX_FW_TYPE_SDMA1; 723be4630d9SHawking Zhang break; 724be4630d9SHawking Zhang case AMDGPU_UCODE_ID_CP_CE: 725be4630d9SHawking Zhang *type = GFX_FW_TYPE_CP_CE; 726be4630d9SHawking Zhang break; 727be4630d9SHawking Zhang case AMDGPU_UCODE_ID_CP_PFP: 728be4630d9SHawking Zhang *type = GFX_FW_TYPE_CP_PFP; 729be4630d9SHawking Zhang break; 730be4630d9SHawking Zhang case AMDGPU_UCODE_ID_CP_ME: 731be4630d9SHawking Zhang *type = GFX_FW_TYPE_CP_ME; 732be4630d9SHawking Zhang break; 733be4630d9SHawking Zhang case AMDGPU_UCODE_ID_CP_MEC1: 734be4630d9SHawking Zhang *type = GFX_FW_TYPE_CP_MEC; 735be4630d9SHawking Zhang break; 736be4630d9SHawking Zhang case AMDGPU_UCODE_ID_CP_MEC1_JT: 737be4630d9SHawking Zhang *type = GFX_FW_TYPE_CP_MEC_ME1; 738be4630d9SHawking Zhang break; 739be4630d9SHawking Zhang case AMDGPU_UCODE_ID_CP_MEC2: 740be4630d9SHawking Zhang *type = GFX_FW_TYPE_CP_MEC; 741be4630d9SHawking Zhang break; 742be4630d9SHawking Zhang case AMDGPU_UCODE_ID_CP_MEC2_JT: 743be4630d9SHawking Zhang *type = GFX_FW_TYPE_CP_MEC_ME2; 744be4630d9SHawking Zhang break; 745be4630d9SHawking Zhang case AMDGPU_UCODE_ID_RLC_G: 746be4630d9SHawking Zhang *type = GFX_FW_TYPE_RLC_G; 747be4630d9SHawking Zhang break; 748be4630d9SHawking Zhang case AMDGPU_UCODE_ID_RLC_RESTORE_LIST_CNTL: 749be4630d9SHawking Zhang *type = GFX_FW_TYPE_RLC_RESTORE_LIST_SRM_CNTL; 750be4630d9SHawking Zhang break; 751be4630d9SHawking Zhang case AMDGPU_UCODE_ID_RLC_RESTORE_LIST_GPM_MEM: 752be4630d9SHawking Zhang *type = GFX_FW_TYPE_RLC_RESTORE_LIST_GPM_MEM; 753be4630d9SHawking Zhang break; 754be4630d9SHawking Zhang case AMDGPU_UCODE_ID_RLC_RESTORE_LIST_SRM_MEM: 755be4630d9SHawking Zhang *type = GFX_FW_TYPE_RLC_RESTORE_LIST_SRM_MEM; 756be4630d9SHawking Zhang break; 757be4630d9SHawking Zhang case AMDGPU_UCODE_ID_SMC: 758be4630d9SHawking Zhang *type = GFX_FW_TYPE_SMU; 759be4630d9SHawking Zhang break; 760be4630d9SHawking Zhang case AMDGPU_UCODE_ID_UVD: 761be4630d9SHawking Zhang *type = GFX_FW_TYPE_UVD; 762be4630d9SHawking Zhang break; 763be4630d9SHawking Zhang case AMDGPU_UCODE_ID_UVD1: 764be4630d9SHawking Zhang *type = GFX_FW_TYPE_UVD1; 765be4630d9SHawking Zhang break; 766be4630d9SHawking Zhang case AMDGPU_UCODE_ID_VCE: 767be4630d9SHawking Zhang *type = GFX_FW_TYPE_VCE; 768be4630d9SHawking Zhang break; 769be4630d9SHawking Zhang case AMDGPU_UCODE_ID_VCN: 770be4630d9SHawking Zhang *type = GFX_FW_TYPE_VCN; 771be4630d9SHawking Zhang break; 772be4630d9SHawking Zhang case AMDGPU_UCODE_ID_DMCU_ERAM: 773be4630d9SHawking Zhang *type = GFX_FW_TYPE_DMCU_ERAM; 774be4630d9SHawking Zhang break; 775be4630d9SHawking Zhang case AMDGPU_UCODE_ID_DMCU_INTV: 776be4630d9SHawking Zhang *type = GFX_FW_TYPE_DMCU_ISR; 777be4630d9SHawking Zhang break; 778be4630d9SHawking Zhang case AMDGPU_UCODE_ID_MAXIMUM: 779be4630d9SHawking Zhang default: 780be4630d9SHawking Zhang return -EINVAL; 781be4630d9SHawking Zhang } 782be4630d9SHawking Zhang 783be4630d9SHawking Zhang return 0; 784be4630d9SHawking Zhang } 785be4630d9SHawking Zhang 786be4630d9SHawking Zhang static int psp_prep_load_ip_fw_cmd_buf(struct amdgpu_firmware_info *ucode, 787be4630d9SHawking Zhang struct psp_gfx_cmd_resp *cmd) 788be4630d9SHawking Zhang { 789be4630d9SHawking Zhang int ret; 790be4630d9SHawking Zhang uint64_t fw_mem_mc_addr = ucode->mc_addr; 791be4630d9SHawking Zhang 792be4630d9SHawking Zhang memset(cmd, 0, sizeof(struct psp_gfx_cmd_resp)); 793be4630d9SHawking Zhang 794be4630d9SHawking Zhang cmd->cmd_id = GFX_CMD_ID_LOAD_IP_FW; 795be4630d9SHawking Zhang cmd->cmd.cmd_load_ip_fw.fw_phy_addr_lo = lower_32_bits(fw_mem_mc_addr); 796be4630d9SHawking Zhang cmd->cmd.cmd_load_ip_fw.fw_phy_addr_hi = upper_32_bits(fw_mem_mc_addr); 797be4630d9SHawking Zhang cmd->cmd.cmd_load_ip_fw.fw_size = ucode->ucode_size; 798be4630d9SHawking Zhang 799be4630d9SHawking Zhang ret = psp_get_fw_type(ucode, &cmd->cmd.cmd_load_ip_fw.fw_type); 800be4630d9SHawking Zhang if (ret) 801be4630d9SHawking Zhang DRM_ERROR("Unknown firmware type\n"); 802be4630d9SHawking Zhang 803be4630d9SHawking Zhang return ret; 804be4630d9SHawking Zhang } 805be4630d9SHawking Zhang 806be70bbdaSHuang Rui static int psp_np_fw_load(struct psp_context *psp) 807be70bbdaSHuang Rui { 808be70bbdaSHuang Rui int i, ret; 809be70bbdaSHuang Rui struct amdgpu_firmware_info *ucode; 810be70bbdaSHuang Rui struct amdgpu_device* adev = psp->adev; 8110e5ca0d1SHuang Rui 8120e5ca0d1SHuang Rui for (i = 0; i < adev->firmware.max_ucodes; i++) { 8130e5ca0d1SHuang Rui ucode = &adev->firmware.ucode[i]; 8140e5ca0d1SHuang Rui if (!ucode->fw) 8150e5ca0d1SHuang Rui continue; 8160e5ca0d1SHuang Rui 8170e5ca0d1SHuang Rui if (ucode->ucode_id == AMDGPU_UCODE_ID_SMC && 8180e5ca0d1SHuang Rui psp_smu_reload_quirk(psp)) 8190e5ca0d1SHuang Rui continue; 820e993ca4fSDaniel Wang if (amdgpu_sriov_vf(adev) && 821e993ca4fSDaniel Wang (ucode->ucode_id == AMDGPU_UCODE_ID_SDMA0 822e993ca4fSDaniel Wang || ucode->ucode_id == AMDGPU_UCODE_ID_SDMA1 823e993ca4fSDaniel Wang || ucode->ucode_id == AMDGPU_UCODE_ID_RLC_G)) 824e993ca4fSDaniel Wang /*skip ucode loading in SRIOV VF */ 825e993ca4fSDaniel Wang continue; 8260e5ca0d1SHuang Rui 827be4630d9SHawking Zhang ret = psp_prep_load_ip_fw_cmd_buf(ucode, psp->cmd); 8280e5ca0d1SHuang Rui if (ret) 829be70bbdaSHuang Rui return ret; 8300e5ca0d1SHuang Rui 831be70bbdaSHuang Rui ret = psp_cmd_submit_buf(psp, ucode, psp->cmd, 8320b25cbf9SHawking Zhang psp->fence_buf_mc_addr); 8330e5ca0d1SHuang Rui if (ret) 834be70bbdaSHuang Rui return ret; 8350e5ca0d1SHuang Rui 8360e5ca0d1SHuang Rui #if 0 8370e5ca0d1SHuang Rui /* check if firmware loaded sucessfully */ 8380e5ca0d1SHuang Rui if (!amdgpu_psp_check_fw_loading_status(adev, i)) 8390e5ca0d1SHuang Rui return -EINVAL; 8400e5ca0d1SHuang Rui #endif 8410e5ca0d1SHuang Rui } 8420e5ca0d1SHuang Rui 843be70bbdaSHuang Rui return 0; 844be70bbdaSHuang Rui } 845be70bbdaSHuang Rui 8460e5ca0d1SHuang Rui static int psp_load_fw(struct amdgpu_device *adev) 8470e5ca0d1SHuang Rui { 8480e5ca0d1SHuang Rui int ret; 8490e5ca0d1SHuang Rui struct psp_context *psp = &adev->psp; 8500e5ca0d1SHuang Rui 85153450efdSXiangliang Yu if (amdgpu_sriov_vf(adev) && adev->in_gpu_reset) { 85214d20ec7Swentalou psp_ring_stop(psp, PSP_RING_TYPE__KM); /* should not destroy ring, only stop */ 85377a3c96bSMonk Liu goto skip_memalloc; 85453450efdSXiangliang Yu } 85577a3c96bSMonk Liu 85667bef0f7SHuang Rui psp->cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); 85767bef0f7SHuang Rui if (!psp->cmd) 8580e5ca0d1SHuang Rui return -ENOMEM; 8590e5ca0d1SHuang Rui 86053a5cf57SHuang Rui ret = amdgpu_bo_create_kernel(adev, PSP_1_MEG, PSP_1_MEG, 86153a5cf57SHuang Rui AMDGPU_GEM_DOMAIN_GTT, 86253a5cf57SHuang Rui &psp->fw_pri_bo, 86353a5cf57SHuang Rui &psp->fw_pri_mc_addr, 86453a5cf57SHuang Rui &psp->fw_pri_buf); 8650e5ca0d1SHuang Rui if (ret) 8660e5ca0d1SHuang Rui goto failed; 8670e5ca0d1SHuang Rui 8680e5ca0d1SHuang Rui ret = amdgpu_bo_create_kernel(adev, PSP_FENCE_BUFFER_SIZE, PAGE_SIZE, 8690e5ca0d1SHuang Rui AMDGPU_GEM_DOMAIN_VRAM, 8700e5ca0d1SHuang Rui &psp->fence_buf_bo, 8710e5ca0d1SHuang Rui &psp->fence_buf_mc_addr, 8720e5ca0d1SHuang Rui &psp->fence_buf); 8730e5ca0d1SHuang Rui if (ret) 874a1952da7SHuang Rui goto failed_mem2; 875a1952da7SHuang Rui 876a1952da7SHuang Rui ret = amdgpu_bo_create_kernel(adev, PSP_CMD_BUFFER_SIZE, PAGE_SIZE, 877a1952da7SHuang Rui AMDGPU_GEM_DOMAIN_VRAM, 878a1952da7SHuang Rui &psp->cmd_buf_bo, &psp->cmd_buf_mc_addr, 879a1952da7SHuang Rui (void **)&psp->cmd_buf_mem); 880a1952da7SHuang Rui if (ret) 88153a5cf57SHuang Rui goto failed_mem1; 8820e5ca0d1SHuang Rui 8830e5ca0d1SHuang Rui memset(psp->fence_buf, 0, PSP_FENCE_BUFFER_SIZE); 8840e5ca0d1SHuang Rui 885be70bbdaSHuang Rui ret = psp_ring_init(psp, PSP_RING_TYPE__KM); 8860e5ca0d1SHuang Rui if (ret) 887a1952da7SHuang Rui goto failed_mem; 8880e5ca0d1SHuang Rui 889be70bbdaSHuang Rui ret = psp_tmr_init(psp); 8906f2b1fccSHuang Rui if (ret) 8916f2b1fccSHuang Rui goto failed_mem; 8926f2b1fccSHuang Rui 893f5cfef98SHuang Rui ret = psp_asd_init(psp); 894f5cfef98SHuang Rui if (ret) 895f5cfef98SHuang Rui goto failed_mem; 896f5cfef98SHuang Rui 89777a3c96bSMonk Liu skip_memalloc: 898be70bbdaSHuang Rui ret = psp_hw_start(psp); 8990e5ca0d1SHuang Rui if (ret) 9000e5ca0d1SHuang Rui goto failed_mem; 9010e5ca0d1SHuang Rui 902be70bbdaSHuang Rui ret = psp_np_fw_load(psp); 9030e5ca0d1SHuang Rui if (ret) 9040e5ca0d1SHuang Rui goto failed_mem; 9050e5ca0d1SHuang Rui 9060e5ca0d1SHuang Rui return 0; 9070e5ca0d1SHuang Rui 9080e5ca0d1SHuang Rui failed_mem: 909a1952da7SHuang Rui amdgpu_bo_free_kernel(&psp->cmd_buf_bo, 910a1952da7SHuang Rui &psp->cmd_buf_mc_addr, 911a1952da7SHuang Rui (void **)&psp->cmd_buf_mem); 912a1952da7SHuang Rui failed_mem1: 9130e5ca0d1SHuang Rui amdgpu_bo_free_kernel(&psp->fence_buf_bo, 9140e5ca0d1SHuang Rui &psp->fence_buf_mc_addr, &psp->fence_buf); 915a1952da7SHuang Rui failed_mem2: 91653a5cf57SHuang Rui amdgpu_bo_free_kernel(&psp->fw_pri_bo, 91753a5cf57SHuang Rui &psp->fw_pri_mc_addr, &psp->fw_pri_buf); 9180e5ca0d1SHuang Rui failed: 91967bef0f7SHuang Rui kfree(psp->cmd); 92067bef0f7SHuang Rui psp->cmd = NULL; 9210e5ca0d1SHuang Rui return ret; 9220e5ca0d1SHuang Rui } 9230e5ca0d1SHuang Rui 9240e5ca0d1SHuang Rui static int psp_hw_init(void *handle) 9250e5ca0d1SHuang Rui { 9260e5ca0d1SHuang Rui int ret; 9270e5ca0d1SHuang Rui struct amdgpu_device *adev = (struct amdgpu_device *)handle; 9280e5ca0d1SHuang Rui 9290e5ca0d1SHuang Rui mutex_lock(&adev->firmware.mutex); 9306e13bdf6SRex Zhu /* 9316e13bdf6SRex Zhu * This sequence is just used on hw_init only once, no need on 9326e13bdf6SRex Zhu * resume. 9336e13bdf6SRex Zhu */ 9346e13bdf6SRex Zhu ret = amdgpu_ucode_init_bo(adev); 9356e13bdf6SRex Zhu if (ret) 9366e13bdf6SRex Zhu goto failed; 9370e5ca0d1SHuang Rui 9380e5ca0d1SHuang Rui ret = psp_load_fw(adev); 9390e5ca0d1SHuang Rui if (ret) { 9400e5ca0d1SHuang Rui DRM_ERROR("PSP firmware loading failed\n"); 9410e5ca0d1SHuang Rui goto failed; 9420e5ca0d1SHuang Rui } 9430e5ca0d1SHuang Rui 9440e5ca0d1SHuang Rui mutex_unlock(&adev->firmware.mutex); 9450e5ca0d1SHuang Rui return 0; 9460e5ca0d1SHuang Rui 9470e5ca0d1SHuang Rui failed: 9480e5ca0d1SHuang Rui adev->firmware.load_type = AMDGPU_FW_LOAD_DIRECT; 9490e5ca0d1SHuang Rui mutex_unlock(&adev->firmware.mutex); 9500e5ca0d1SHuang Rui return -EINVAL; 9510e5ca0d1SHuang Rui } 9520e5ca0d1SHuang Rui 9530e5ca0d1SHuang Rui static int psp_hw_fini(void *handle) 9540e5ca0d1SHuang Rui { 9550e5ca0d1SHuang Rui struct amdgpu_device *adev = (struct amdgpu_device *)handle; 9560e5ca0d1SHuang Rui struct psp_context *psp = &adev->psp; 9570e5ca0d1SHuang Rui 9583e2e2ab5SHawking Zhang if (adev->gmc.xgmi.num_physical_nodes > 1 && 9593e2e2ab5SHawking Zhang psp->xgmi_context.initialized == 1) 9603e2e2ab5SHawking Zhang psp_xgmi_terminate(psp); 9613e2e2ab5SHawking Zhang 962*5e5d3154Sxinhui pan psp_ras_terminate(psp); 963*5e5d3154Sxinhui pan 964e3c5e982STrigger Huang psp_ring_destroy(psp, PSP_RING_TYPE__KM); 965e3c5e982STrigger Huang 9660e5ca0d1SHuang Rui amdgpu_bo_free_kernel(&psp->tmr_bo, &psp->tmr_mc_addr, &psp->tmr_buf); 96753a5cf57SHuang Rui amdgpu_bo_free_kernel(&psp->fw_pri_bo, 96853a5cf57SHuang Rui &psp->fw_pri_mc_addr, &psp->fw_pri_buf); 969b4de2c5aSHuang Rui amdgpu_bo_free_kernel(&psp->fence_buf_bo, 970b4de2c5aSHuang Rui &psp->fence_buf_mc_addr, &psp->fence_buf); 971311146c9SHuang Rui amdgpu_bo_free_kernel(&psp->asd_shared_bo, &psp->asd_shared_mc_addr, 972311146c9SHuang Rui &psp->asd_shared_buf); 973a1952da7SHuang Rui amdgpu_bo_free_kernel(&psp->cmd_buf_bo, &psp->cmd_buf_mc_addr, 974a1952da7SHuang Rui (void **)&psp->cmd_buf_mem); 975b4de2c5aSHuang Rui 97667bef0f7SHuang Rui kfree(psp->cmd); 97767bef0f7SHuang Rui psp->cmd = NULL; 97867bef0f7SHuang Rui 9790e5ca0d1SHuang Rui return 0; 9800e5ca0d1SHuang Rui } 9810e5ca0d1SHuang Rui 9820e5ca0d1SHuang Rui static int psp_suspend(void *handle) 9830e5ca0d1SHuang Rui { 984bcd6eab8SEvan Quan int ret; 985bcd6eab8SEvan Quan struct amdgpu_device *adev = (struct amdgpu_device *)handle; 986bcd6eab8SEvan Quan struct psp_context *psp = &adev->psp; 987bcd6eab8SEvan Quan 9883e2e2ab5SHawking Zhang if (adev->gmc.xgmi.num_physical_nodes > 1 && 9893e2e2ab5SHawking Zhang psp->xgmi_context.initialized == 1) { 9903e2e2ab5SHawking Zhang ret = psp_xgmi_terminate(psp); 9913e2e2ab5SHawking Zhang if (ret) { 9923e2e2ab5SHawking Zhang DRM_ERROR("Failed to terminate xgmi ta\n"); 9933e2e2ab5SHawking Zhang return ret; 9943e2e2ab5SHawking Zhang } 9953e2e2ab5SHawking Zhang } 9963e2e2ab5SHawking Zhang 997*5e5d3154Sxinhui pan ret = psp_ras_terminate(psp); 998*5e5d3154Sxinhui pan if (ret) { 999*5e5d3154Sxinhui pan DRM_ERROR("Failed to terminate ras ta\n"); 1000*5e5d3154Sxinhui pan return ret; 1001*5e5d3154Sxinhui pan } 1002*5e5d3154Sxinhui pan 1003bcd6eab8SEvan Quan ret = psp_ring_stop(psp, PSP_RING_TYPE__KM); 1004bcd6eab8SEvan Quan if (ret) { 1005bcd6eab8SEvan Quan DRM_ERROR("PSP ring stop failed\n"); 1006bcd6eab8SEvan Quan return ret; 1007bcd6eab8SEvan Quan } 1008bcd6eab8SEvan Quan 10090e5ca0d1SHuang Rui return 0; 10100e5ca0d1SHuang Rui } 10110e5ca0d1SHuang Rui 10120e5ca0d1SHuang Rui static int psp_resume(void *handle) 10130e5ca0d1SHuang Rui { 10140e5ca0d1SHuang Rui int ret; 10150e5ca0d1SHuang Rui struct amdgpu_device *adev = (struct amdgpu_device *)handle; 101693ea9b9fSHuang Rui struct psp_context *psp = &adev->psp; 10170e5ca0d1SHuang Rui 101893ea9b9fSHuang Rui DRM_INFO("PSP is resuming...\n"); 101993ea9b9fSHuang Rui 10200e5ca0d1SHuang Rui mutex_lock(&adev->firmware.mutex); 10210e5ca0d1SHuang Rui 102293ea9b9fSHuang Rui ret = psp_hw_start(psp); 10230e5ca0d1SHuang Rui if (ret) 102493ea9b9fSHuang Rui goto failed; 102593ea9b9fSHuang Rui 102693ea9b9fSHuang Rui ret = psp_np_fw_load(psp); 102793ea9b9fSHuang Rui if (ret) 102893ea9b9fSHuang Rui goto failed; 10290e5ca0d1SHuang Rui 10300e5ca0d1SHuang Rui mutex_unlock(&adev->firmware.mutex); 10310e5ca0d1SHuang Rui 103293ea9b9fSHuang Rui return 0; 103393ea9b9fSHuang Rui 103493ea9b9fSHuang Rui failed: 103593ea9b9fSHuang Rui DRM_ERROR("PSP resume failed\n"); 103693ea9b9fSHuang Rui mutex_unlock(&adev->firmware.mutex); 10370e5ca0d1SHuang Rui return ret; 10380e5ca0d1SHuang Rui } 10390e5ca0d1SHuang Rui 1040f75a9a5dSAlex Deucher int psp_gpu_reset(struct amdgpu_device *adev) 104198512bb8SKen Wang { 10422d4f9020SHuang Rui if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) 10432d4f9020SHuang Rui return 0; 10442d4f9020SHuang Rui 104598512bb8SKen Wang return psp_mode1_reset(&adev->psp); 104698512bb8SKen Wang } 104798512bb8SKen Wang 10480e5ca0d1SHuang Rui static bool psp_check_fw_loading_status(struct amdgpu_device *adev, 10490e5ca0d1SHuang Rui enum AMDGPU_UCODE_ID ucode_type) 10500e5ca0d1SHuang Rui { 10510e5ca0d1SHuang Rui struct amdgpu_firmware_info *ucode = NULL; 10520e5ca0d1SHuang Rui 10530e5ca0d1SHuang Rui if (!adev->firmware.fw_size) 10540e5ca0d1SHuang Rui return false; 10550e5ca0d1SHuang Rui 10560e5ca0d1SHuang Rui ucode = &adev->firmware.ucode[ucode_type]; 10570e5ca0d1SHuang Rui if (!ucode->fw || !ucode->ucode_size) 10580e5ca0d1SHuang Rui return false; 10590e5ca0d1SHuang Rui 10600e5ca0d1SHuang Rui return psp_compare_sram_data(&adev->psp, ucode, ucode_type); 10610e5ca0d1SHuang Rui } 10620e5ca0d1SHuang Rui 10630e5ca0d1SHuang Rui static int psp_set_clockgating_state(void *handle, 10640e5ca0d1SHuang Rui enum amd_clockgating_state state) 10650e5ca0d1SHuang Rui { 10660e5ca0d1SHuang Rui return 0; 10670e5ca0d1SHuang Rui } 10680e5ca0d1SHuang Rui 10690e5ca0d1SHuang Rui static int psp_set_powergating_state(void *handle, 10700e5ca0d1SHuang Rui enum amd_powergating_state state) 10710e5ca0d1SHuang Rui { 10720e5ca0d1SHuang Rui return 0; 10730e5ca0d1SHuang Rui } 10740e5ca0d1SHuang Rui 10750e5ca0d1SHuang Rui const struct amd_ip_funcs psp_ip_funcs = { 10760e5ca0d1SHuang Rui .name = "psp", 10770e5ca0d1SHuang Rui .early_init = psp_early_init, 10780e5ca0d1SHuang Rui .late_init = NULL, 10790e5ca0d1SHuang Rui .sw_init = psp_sw_init, 10800e5ca0d1SHuang Rui .sw_fini = psp_sw_fini, 10810e5ca0d1SHuang Rui .hw_init = psp_hw_init, 10820e5ca0d1SHuang Rui .hw_fini = psp_hw_fini, 10830e5ca0d1SHuang Rui .suspend = psp_suspend, 10840e5ca0d1SHuang Rui .resume = psp_resume, 10850e5ca0d1SHuang Rui .is_idle = NULL, 1086f75a9a5dSAlex Deucher .check_soft_reset = NULL, 10870e5ca0d1SHuang Rui .wait_for_idle = NULL, 1088f75a9a5dSAlex Deucher .soft_reset = NULL, 10890e5ca0d1SHuang Rui .set_clockgating_state = psp_set_clockgating_state, 10900e5ca0d1SHuang Rui .set_powergating_state = psp_set_powergating_state, 10910e5ca0d1SHuang Rui }; 10920e5ca0d1SHuang Rui 10930e5ca0d1SHuang Rui static const struct amdgpu_psp_funcs psp_funcs = { 10940e5ca0d1SHuang Rui .check_fw_loading_status = psp_check_fw_loading_status, 10950e5ca0d1SHuang Rui }; 10960e5ca0d1SHuang Rui 10970e5ca0d1SHuang Rui static void psp_set_funcs(struct amdgpu_device *adev) 10980e5ca0d1SHuang Rui { 10990e5ca0d1SHuang Rui if (NULL == adev->firmware.funcs) 11000e5ca0d1SHuang Rui adev->firmware.funcs = &psp_funcs; 11010e5ca0d1SHuang Rui } 11020e5ca0d1SHuang Rui 11030e5ca0d1SHuang Rui const struct amdgpu_ip_block_version psp_v3_1_ip_block = 11040e5ca0d1SHuang Rui { 11050e5ca0d1SHuang Rui .type = AMD_IP_BLOCK_TYPE_PSP, 11060e5ca0d1SHuang Rui .major = 3, 11070e5ca0d1SHuang Rui .minor = 1, 11080e5ca0d1SHuang Rui .rev = 0, 11090e5ca0d1SHuang Rui .funcs = &psp_ip_funcs, 11100e5ca0d1SHuang Rui }; 1111dfbd6438SHuang Rui 1112dfbd6438SHuang Rui const struct amdgpu_ip_block_version psp_v10_0_ip_block = 1113dfbd6438SHuang Rui { 1114dfbd6438SHuang Rui .type = AMD_IP_BLOCK_TYPE_PSP, 1115dfbd6438SHuang Rui .major = 10, 1116dfbd6438SHuang Rui .minor = 0, 1117dfbd6438SHuang Rui .rev = 0, 1118dfbd6438SHuang Rui .funcs = &psp_ip_funcs, 1119dfbd6438SHuang Rui }; 1120654f761cSFeifei Xu 1121654f761cSFeifei Xu const struct amdgpu_ip_block_version psp_v11_0_ip_block = 1122654f761cSFeifei Xu { 1123654f761cSFeifei Xu .type = AMD_IP_BLOCK_TYPE_PSP, 1124654f761cSFeifei Xu .major = 11, 1125654f761cSFeifei Xu .minor = 0, 1126654f761cSFeifei Xu .rev = 0, 1127654f761cSFeifei Xu .funcs = &psp_ip_funcs, 1128654f761cSFeifei Xu }; 1129