/* * Copyright 2026 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 #include "amdgpu.h" #include "ivsrcid/mpnht/irqsrcs_mpnht_15_0.h" #include "amdgpu_ualink.h" #include "ualink_v1_0.h" /* nHT firmware mailbox registers via SMN, copy of MP1 */ #define mmMPNHT_SMN_C2PMSG_CMD 0xAE10958 #define mmMPNHT_SMN_C2PMSG_DATA 0xAE1095C #define mmMPNHT_SMN_C2PMSG_ADDR_LO 0xAE10960 #define mmMPNHT_SMN_C2PMSG_ADDR_HI 0xAE10964 #define mmMPNHT_SMN_C2PMSG_STATUS 0xAE10968 /* nHT firmware commands */ #define UALINK_V1_0_FW_CMD_LOAD_METADATA 0x1 #define UALINK_V1_0_FW_CMD_HALT_OPERATION 0x2 #define UALINK_V1_0_FW_POLL_COUNT 2000 static u32 ualink_v1_0_check_status(struct amdgpu_device *adev) { return RREG32_PCIE(mmMPNHT_SMN_C2PMSG_STATUS); } static int ualink_v1_0_send_metadata(struct amdgpu_device *adev, u64 metadata_gpu_addr, u32 accel_data) { u32 status; int i; dev_dbg(adev->dev, "nht load metadata addr 0x%llx accel_data 0x%x\n", metadata_gpu_addr, accel_data); WREG32_PCIE(mmMPNHT_SMN_C2PMSG_ADDR_HI, upper_32_bits(metadata_gpu_addr)); WREG32_PCIE(mmMPNHT_SMN_C2PMSG_ADDR_LO, lower_32_bits(metadata_gpu_addr)); WREG32_PCIE(mmMPNHT_SMN_C2PMSG_DATA, accel_data); WREG32_PCIE(mmMPNHT_SMN_C2PMSG_CMD, UALINK_V1_0_FW_CMD_LOAD_METADATA); for (i = 0; i < UALINK_V1_0_FW_POLL_COUNT; i++) { status = RREG32_PCIE(mmMPNHT_SMN_C2PMSG_STATUS); if (status == AMDGPU_NHT_FW_ST_READY) return 0; mdelay(1); } dev_dbg(adev->dev, "f/w load metadata failed 0x%x\n", status); return -ETIME; } static int ualink_v1_0_send_halt(struct amdgpu_device *adev) { u32 status; int i; dev_dbg(adev->dev, "nht halt cmd 0x%x\n", UALINK_V1_0_FW_CMD_HALT_OPERATION); WREG32_PCIE(mmMPNHT_SMN_C2PMSG_CMD, UALINK_V1_0_FW_CMD_HALT_OPERATION); for (i = 0; i < UALINK_V1_0_FW_POLL_COUNT; i++) { status = RREG32_PCIE(mmMPNHT_SMN_C2PMSG_STATUS); if (status == AMDGPU_NHT_FW_ST_HALT) return 0; mdelay(1); } dev_warn(adev->dev, "f/w halt failed status 0x%x\n", status); return -ETIME; } const struct amdgpu_ualink_msg_ctl ualink_v1_0_msg_ctl = { .check_status = ualink_v1_0_check_status, .send_metadata = ualink_v1_0_send_metadata, .send_halt = ualink_v1_0_send_halt, }; static int ualink_v1_0_early_init(struct amdgpu_ip_block *ip_block) { struct amdgpu_device *adev = ip_block->adev; adev->ualink.msg_ctl = &ualink_v1_0_msg_ctl; return 0; } static int ualink_v1_0_sw_init(struct amdgpu_ip_block *ip_block) { struct amdgpu_device *adev = ip_block->adev; int r; r = ualink_ip_sw_init(ip_block); if (r) return r; r = amdgpu_ualink_init_interrupt(adev, SOC_V1_0_IH_CLIENTID_nHT, MPNHT_15_0__SRCID__REMOTE_INTERRUPT); if (r) { dev_err(adev->dev, "Failed to add UALink irq: %d\n", r); return r; } return 0; } static const struct amd_ip_funcs ualink_v1_0_ip_funcs = { .name = "ualink", .early_init = ualink_v1_0_early_init, .late_init = ualink_ip_late_init, .sw_init = ualink_v1_0_sw_init, .sw_fini = ualink_ip_sw_fini, .hw_init = ualink_ip_hw_init, .hw_fini = ualink_ip_hw_fini, }; const struct amdgpu_ip_block_version ualink_v1_0_ip_block = { .type = AMD_IP_BLOCK_TYPE_UALINK, .major = 1, .minor = 0, .rev = 0, .funcs = &ualink_v1_0_ip_funcs, };