From: Pratik Vishwakarma <[email protected]> Add support for PSP v 15.0.0.
Signed-off-by: Pratik Vishwakarma <[email protected]> Signed-off-by: Alex Deucher <[email protected]> --- drivers/gpu/drm/amd/amdgpu/Makefile | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c | 3 + drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 18 +- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h | 1 + drivers/gpu/drm/amd/amdgpu/psp_v15_0.c | 202 ++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/psp_v15_0.h | 30 +++ 6 files changed, 254 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/amd/amdgpu/psp_v15_0.c create mode 100644 drivers/gpu/drm/amd/amdgpu/psp_v15_0.h diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile index 4b9cb9b681b65..a17b0c3efd4f2 100644 --- a/drivers/gpu/drm/amd/amdgpu/Makefile +++ b/drivers/gpu/drm/amd/amdgpu/Makefile @@ -136,6 +136,7 @@ amdgpu-y += \ psp_v13_0.o \ psp_v13_0_4.o \ psp_v14_0.o \ + psp_v15_0.o \ psp_v15_0_8.o # add DCE block diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c index 43e6216ca30f7..43fde853a3989 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c @@ -2168,6 +2168,9 @@ static int amdgpu_discovery_set_psp_ip_blocks(struct amdgpu_device *adev) case IP_VERSION(14, 0, 5): amdgpu_device_ip_block_add(adev, &psp_v14_0_ip_block); break; + case IP_VERSION(15, 0, 0): + amdgpu_device_ip_block_add(adev, &psp_v15_0_ip_block); + break; case IP_VERSION(15, 0, 8): amdgpu_device_ip_block_add(adev, &psp_v15_0_8_ip_block); break; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index 4522fd77bbc36..08fb72adc9e9e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -39,6 +39,7 @@ #include "psp_v13_0.h" #include "psp_v13_0_4.h" #include "psp_v14_0.h" +#include "psp_v15_0.h" #include "psp_v15_0_8.h" #include "amdgpu_ras.h" @@ -260,6 +261,10 @@ static int psp_early_init(struct amdgpu_ip_block *ip_block) psp_v14_0_set_psp_funcs(psp); psp->boot_time_tmr = false; break; + case IP_VERSION(15, 0, 0): + psp_v15_0_0_set_psp_funcs(psp); + psp->boot_time_tmr = false; + break; case IP_VERSION(15, 0, 8): psp_v15_0_8_set_psp_funcs(psp); break; @@ -905,6 +910,7 @@ static bool psp_skip_tmr(struct psp_context *psp) case IP_VERSION(13, 0, 10): case IP_VERSION(13, 0, 12): case IP_VERSION(13, 0, 14): + case IP_VERSION(15, 0, 0): case IP_VERSION(15, 0, 8): return true; default: @@ -2927,7 +2933,7 @@ static int psp_prep_load_ip_fw_cmd_buf(struct psp_context *psp, ret = psp_get_fw_type(psp, ucode, &cmd->cmd.cmd_load_ip_fw.fw_type); if (ret) - dev_err(psp->adev->dev, "Unknown firmware type\n"); + dev_err(psp->adev->dev, "Unknown firmware type %d\n", ucode->ucode_id); return ret; } @@ -3091,6 +3097,8 @@ static int psp_load_non_psp_fw(struct psp_context *psp) IP_VERSION(11, 0, 11) || amdgpu_ip_version(adev, MP0_HWIP, 0) == IP_VERSION(11, 0, 12) || + amdgpu_ip_version(adev, MP0_HWIP, 0) == + IP_VERSION(15, 0, 0) || amdgpu_ip_version(adev, MP0_HWIP, 0) == IP_VERSION(15, 0, 8)) && (ucode->ucode_id == AMDGPU_UCODE_ID_SDMA1 || @@ -4547,6 +4555,14 @@ const struct amdgpu_ip_block_version psp_v14_0_ip_block = { .funcs = &psp_ip_funcs, }; +const struct amdgpu_ip_block_version psp_v15_0_ip_block = { + .type = AMD_IP_BLOCK_TYPE_PSP, + .major = 15, + .minor = 0, + .rev = 0, + .funcs = &psp_ip_funcs, +}; + const struct amdgpu_ip_block_version psp_v15_0_8_ip_block = { .type = AMD_IP_BLOCK_TYPE_PSP, .major = 15, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h index 973998a2dc95e..79a49cba8d406 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h @@ -540,6 +540,7 @@ extern const struct amdgpu_ip_block_version psp_v12_0_ip_block; extern const struct amdgpu_ip_block_version psp_v13_0_ip_block; extern const struct amdgpu_ip_block_version psp_v13_0_4_ip_block; extern const struct amdgpu_ip_block_version psp_v14_0_ip_block; +extern const struct amdgpu_ip_block_version psp_v15_0_ip_block; extern const struct amdgpu_ip_block_version psp_v15_0_8_ip_block; int psp_wait_for(struct psp_context *psp, uint32_t reg_index, diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v15_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v15_0.c new file mode 100644 index 0000000000000..3aca293e2f0c4 --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/psp_v15_0.c @@ -0,0 +1,202 @@ +/* + * Copyright 2025 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ +#include <drm/drm_drv.h> +#include <linux/vmalloc.h> +#include "amdgpu.h" +#include "amdgpu_psp.h" +#include "amdgpu_ucode.h" +#include "soc15_common.h" +#include "psp_v15_0.h" + +#include "mp/mp_15_0_0_offset.h" +#include "mp/mp_15_0_0_sh_mask.h" + +MODULE_FIRMWARE("amdgpu/psp_15_0_0_toc.bin"); + +static int psp_v15_0_0_init_microcode(struct psp_context *psp) +{ + struct amdgpu_device *adev = psp->adev; + char ucode_prefix[30]; + int err = 0; + + amdgpu_ucode_ip_version_decode(adev, MP0_HWIP, ucode_prefix, sizeof(ucode_prefix)); + + err = psp_init_toc_microcode(psp, ucode_prefix); + if (err) + return err; + + return 0; +} + +static int psp_v15_0_0_ring_stop(struct psp_context *psp, + enum psp_ring_type ring_type) +{ + int ret = 0; + struct amdgpu_device *adev = psp->adev; + + if (amdgpu_sriov_vf(adev)) { + /* Write the ring destroy command*/ + WREG32_SOC15(MP0, 0, regMPASP_SMN_C2PMSG_101, + GFX_CTRL_CMD_ID_DESTROY_GPCOM_RING); + /* there might be handshake issue with hardware which needs delay */ + mdelay(20); + /* Wait for response flag (bit 31) */ + ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, regMPASP_SMN_C2PMSG_101), + 0x80000000, 0x80000000, false); + } else { + /* Write the ring destroy command*/ + WREG32_SOC15(MP0, 0, regMPASP_SMN_C2PMSG_64, + GFX_CTRL_CMD_ID_DESTROY_RINGS); + /* there might be handshake issue with hardware which needs delay */ + mdelay(20); + /* Wait for response flag (bit 31) */ + ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, regMPASP_SMN_C2PMSG_64), + 0x80000000, 0x80000000, false); + } + + return ret; +} + +static int psp_v15_0_0_ring_create(struct psp_context *psp, + enum psp_ring_type ring_type) +{ + int ret = 0; + unsigned int psp_ring_reg = 0; + struct psp_ring *ring = &psp->km_ring; + struct amdgpu_device *adev = psp->adev; + + if (amdgpu_sriov_vf(adev)) { + ret = psp_v15_0_0_ring_stop(psp, ring_type); + if (ret) { + DRM_ERROR("psp_v14_0_ring_stop_sriov failed!\n"); + return ret; + } + + /* Write low address of the ring to C2PMSG_102 */ + psp_ring_reg = lower_32_bits(ring->ring_mem_mc_addr); + WREG32_SOC15(MP0, 0, regMPASP_SMN_C2PMSG_102, psp_ring_reg); + /* Write high address of the ring to C2PMSG_103 */ + psp_ring_reg = upper_32_bits(ring->ring_mem_mc_addr); + WREG32_SOC15(MP0, 0, regMPASP_SMN_C2PMSG_103, psp_ring_reg); + + /* Write the ring initialization command to C2PMSG_101 */ + WREG32_SOC15(MP0, 0, regMPASP_SMN_C2PMSG_101, + GFX_CTRL_CMD_ID_INIT_GPCOM_RING); + + /* there might be handshake issue with hardware which needs delay */ + mdelay(20); + + /* Wait for response flag (bit 31) in C2PMSG_101 */ + ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, regMPASP_SMN_C2PMSG_101), + 0x80000000, 0x8000FFFF, false); + + } else { + /* Wait for sOS ready for ring creation */ + ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, regMPASP_SMN_C2PMSG_64), + 0x80000000, 0x80000000, false); + if (ret) { + DRM_ERROR("Failed to wait for trust OS ready for ring creation\n"); + return ret; + } + + /* Write low address of the ring to C2PMSG_69 */ + psp_ring_reg = lower_32_bits(ring->ring_mem_mc_addr); + WREG32_SOC15(MP0, 0, regMPASP_SMN_C2PMSG_69, psp_ring_reg); + /* Write high address of the ring to C2PMSG_70 */ + psp_ring_reg = upper_32_bits(ring->ring_mem_mc_addr); + WREG32_SOC15(MP0, 0, regMPASP_SMN_C2PMSG_70, psp_ring_reg); + /* Write size of ring to C2PMSG_71 */ + psp_ring_reg = ring->ring_size; + WREG32_SOC15(MP0, 0, regMPASP_SMN_C2PMSG_71, psp_ring_reg); + /* Write the ring initialization command to C2PMSG_64 */ + psp_ring_reg = ring_type; + psp_ring_reg = psp_ring_reg << 16; + WREG32_SOC15(MP0, 0, regMPASP_SMN_C2PMSG_64, psp_ring_reg); + + /* there might be handshake issue with hardware which needs delay */ + mdelay(20); + + /* Wait for response flag (bit 31) in C2PMSG_64 */ + ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, regMPASP_SMN_C2PMSG_64), + 0x80000000, 0x8000FFFF, false); + } + + return ret; +} + +static int psp_v15_0_0_ring_destroy(struct psp_context *psp, + enum psp_ring_type ring_type) +{ + int ret = 0; + struct psp_ring *ring = &psp->km_ring; + struct amdgpu_device *adev = psp->adev; + + ret = psp_v15_0_0_ring_stop(psp, ring_type); + if (ret) + DRM_ERROR("Fail to stop psp ring\n"); + + amdgpu_bo_free_kernel(&adev->firmware.rbuf, + &ring->ring_mem_mc_addr, + (void **)&ring->ring_mem); + + return ret; +} + +static uint32_t psp_v15_0_0_ring_get_wptr(struct psp_context *psp) +{ + uint32_t data; + struct amdgpu_device *adev = psp->adev; + + if (amdgpu_sriov_vf(adev)) + data = RREG32_SOC15(MP0, 0, regMPASP_SMN_C2PMSG_102); + else + data = RREG32_SOC15(MP0, 0, regMPASP_SMN_C2PMSG_67); + + return data; +} + +static void psp_v15_0_0_ring_set_wptr(struct psp_context *psp, uint32_t value) +{ + struct amdgpu_device *adev = psp->adev; + + if (amdgpu_sriov_vf(adev)) { + WREG32_SOC15(MP0, 0, regMPASP_SMN_C2PMSG_102, value); + WREG32_SOC15(MP0, 0, regMPASP_SMN_C2PMSG_101, + GFX_CTRL_CMD_ID_CONSUME_CMD); + } else + WREG32_SOC15(MP0, 0, regMPASP_SMN_C2PMSG_67, value); +} + +static const struct psp_funcs psp_v15_0_0_funcs = { + .init_microcode = psp_v15_0_0_init_microcode, + .ring_create = psp_v15_0_0_ring_create, + .ring_stop = psp_v15_0_0_ring_stop, + .ring_destroy = psp_v15_0_0_ring_destroy, + .ring_get_wptr = psp_v15_0_0_ring_get_wptr, + .ring_set_wptr = psp_v15_0_0_ring_set_wptr, +}; + +void psp_v15_0_0_set_psp_funcs(struct psp_context *psp) +{ + psp->funcs = &psp_v15_0_0_funcs; +} diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v15_0.h b/drivers/gpu/drm/amd/amdgpu/psp_v15_0.h new file mode 100644 index 0000000000000..ebd612103526f --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/psp_v15_0.h @@ -0,0 +1,30 @@ +/* + * Copyright 2025 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ +#ifndef __PSP_V15_0_0_H__ +#define __PSP_V15_0_0_H__ + +#include "amdgpu_psp.h" + +void psp_v15_0_0_set_psp_funcs(struct psp_context *psp); + +#endif -- 2.52.0
