From: Likun Gao <[email protected]> Add IMU support for gc version 12.1.0. Only support imu fw loading for imu 12.1.0.
Signed-off-by: Likun Gao <[email protected]> Reviewed-by: Hawking Zhang <[email protected]> Signed-off-by: Alex Deucher <[email protected]> --- drivers/gpu/drm/amd/amdgpu/Makefile | 3 +- drivers/gpu/drm/amd/amdgpu/gfx_v12_1.c | 49 +++------ drivers/gpu/drm/amd/amdgpu/imu_v12_1.c | 139 +++++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/imu_v12_1.h | 30 ++++++ 4 files changed, 186 insertions(+), 35 deletions(-) create mode 100644 drivers/gpu/drm/amd/amdgpu/imu_v12_1.c create mode 100644 drivers/gpu/drm/amd/amdgpu/imu_v12_1.h diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile index f65021678fc07..d0c506a445695 100644 --- a/drivers/gpu/drm/amd/amdgpu/Makefile +++ b/drivers/gpu/drm/amd/amdgpu/Makefile @@ -159,7 +159,8 @@ amdgpu-y += \ imu_v11_0_3.o \ gfx_v12_0.o \ gfx_v12_1.o \ - imu_v12_0.o + imu_v12_0.o \ + imu_v12_1.o # add async DMA block amdgpu-y += \ diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v12_1.c b/drivers/gpu/drm/amd/amdgpu/gfx_v12_1.c index a4886313d57d5..a1f9befc0841d 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v12_1.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v12_1.c @@ -30,7 +30,7 @@ #include "amdgpu_psp.h" #include "amdgpu_smu.h" #include "amdgpu_atomfirmware.h" -#include "imu_v12_0.h" +#include "imu_v12_1.h" #include "soc_v1_0.h" #include "gfx_v12_1_pkt.h" @@ -1065,27 +1065,19 @@ static int gfx_v12_1_rlc_backdoor_autoload_enable(struct amdgpu_device *adev) WREG32_SOC15(GC, GET_INST(GC, 0), regGFX_IMU_RLC_BOOTLOADER_SIZE, rlc_g_size); - if (adev->gfx.imu.funcs && (amdgpu_dpm > 0)) { + if (adev->gfx.imu.funcs) { /* RLC autoload sequence 3: load IMU fw */ if (adev->gfx.imu.funcs->load_microcode) adev->gfx.imu.funcs->load_microcode(adev); - /* RLC autoload sequence 4 init IMU fw */ - if (adev->gfx.imu.funcs->setup_imu) - adev->gfx.imu.funcs->setup_imu(adev); - if (adev->gfx.imu.funcs->start_imu) - adev->gfx.imu.funcs->start_imu(adev); - - /* RLC autoload sequence 5 disable gpa mode */ - gfx_v12_1_xcc_disable_gpa_mode(adev, 0); - } else { - /* unhalt rlc to start autoload without imu */ - data = RREG32_SOC15(GC, GET_INST(GC, 0), regRLC_GPM_THREAD_ENABLE); - data = REG_SET_FIELD(data, RLC_GPM_THREAD_ENABLE, THREAD0_ENABLE, 1); - data = REG_SET_FIELD(data, RLC_GPM_THREAD_ENABLE, THREAD1_ENABLE, 1); - WREG32_SOC15(GC, GET_INST(GC, 0), regRLC_GPM_THREAD_ENABLE, data); - WREG32_SOC15(GC, GET_INST(GC, 0), regRLC_CNTL, RLC_CNTL__RLC_ENABLE_F32_MASK); } + /* unhalt rlc to start autoload */ + data = RREG32_SOC15(GC, GET_INST(GC, 0), regRLC_GPM_THREAD_ENABLE); + data = REG_SET_FIELD(data, RLC_GPM_THREAD_ENABLE, THREAD0_ENABLE, 1); + data = REG_SET_FIELD(data, RLC_GPM_THREAD_ENABLE, THREAD1_ENABLE, 1); + WREG32_SOC15(GC, GET_INST(GC, 0), regRLC_GPM_THREAD_ENABLE, data); + WREG32_SOC15(GC, GET_INST(GC, 0), regRLC_CNTL, RLC_CNTL__RLC_ENABLE_F32_MASK); + return 0; } @@ -2526,11 +2518,6 @@ static int gfx_v12_1_hw_init(struct amdgpu_ip_block *ip_block) struct amdgpu_device *adev = ip_block->adev; if (adev->firmware.load_type == AMDGPU_FW_LOAD_RLC_BACKDOOR_AUTO) { - if (adev->gfx.imu.funcs && (amdgpu_dpm > 0)) { - /* RLC autoload sequence 1: Program rlc ram */ - if (adev->gfx.imu.funcs->program_rlc_ram) - adev->gfx.imu.funcs->program_rlc_ram(adev); - } /* rlc autoload firmware */ r = gfx_v12_1_rlc_backdoor_autoload_enable(adev); if (r) @@ -2539,16 +2526,12 @@ static int gfx_v12_1_hw_init(struct amdgpu_ip_block *ip_block) if (adev->firmware.load_type == AMDGPU_FW_LOAD_DIRECT) { num_xcc = NUM_XCC(adev->gfx.xcc_mask); - for (i = 0; i < num_xcc; i++) { - if (adev->gfx.imu.funcs && (amdgpu_dpm > 0)) { - if (adev->gfx.imu.funcs->load_microcode) - adev->gfx.imu.funcs->load_microcode(adev); - if (adev->gfx.imu.funcs->setup_imu) - adev->gfx.imu.funcs->setup_imu(adev); - if (adev->gfx.imu.funcs->start_imu) - adev->gfx.imu.funcs->start_imu(adev); - } + if (adev->gfx.imu.funcs) { + if (adev->gfx.imu.funcs->load_microcode) + adev->gfx.imu.funcs->load_microcode(adev); + } + for (i = 0; i < num_xcc; i++) { /* disable gpa mode in backdoor loading */ gfx_v12_1_xcc_disable_gpa_mode(adev, i); } @@ -3730,14 +3713,12 @@ static void gfx_v12_1_set_irq_funcs(struct amdgpu_device *adev) static void gfx_v12_1_set_imu_funcs(struct amdgpu_device *adev) { -#if 0 if (adev->flags & AMD_IS_APU) adev->gfx.imu.mode = MISSION_MODE; else adev->gfx.imu.mode = DEBUG_MODE; - adev->gfx.imu.funcs = &gfx_v12_0_imu_funcs; -#endif + adev->gfx.imu.funcs = &gfx_v12_1_imu_funcs; } static void gfx_v12_1_set_rlc_funcs(struct amdgpu_device *adev) diff --git a/drivers/gpu/drm/amd/amdgpu/imu_v12_1.c b/drivers/gpu/drm/amd/amdgpu/imu_v12_1.c new file mode 100644 index 0000000000000..28932604d986d --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/imu_v12_1.c @@ -0,0 +1,139 @@ +/* + * 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 <linux/firmware.h> +#include "amdgpu.h" +#include "amdgpu_imu.h" +#include "amdgpu_dpm.h" + +#include "imu_v12_1.h" + +#include "gc/gc_12_1_0_offset.h" +#include "gc/gc_12_1_0_sh_mask.h" +#include "mmhub/mmhub_4_2_0_offset.h" + +MODULE_FIRMWARE("amdgpu/gc_12_1_0_imu.bin"); + +#define TRANSFER_RAM_MASK 0x001c0000 + +static int imu_v12_1_init_microcode(struct amdgpu_device *adev) +{ + char ucode_prefix[15]; + int err; + const struct imu_firmware_header_v1_0 *imu_hdr; + struct amdgpu_firmware_info *info = NULL; + + DRM_DEBUG("\n"); + + amdgpu_ucode_ip_version_decode(adev, GC_HWIP, ucode_prefix, sizeof(ucode_prefix)); + err = amdgpu_ucode_request(adev, &adev->gfx.imu_fw, AMDGPU_UCODE_REQUIRED, + "amdgpu/%s_imu.bin", ucode_prefix); + if (err) + goto out; + + imu_hdr = (const struct imu_firmware_header_v1_0 *)adev->gfx.imu_fw->data; + adev->gfx.imu_fw_version = le32_to_cpu(imu_hdr->header.ucode_version); + + if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) { + info = &adev->firmware.ucode[AMDGPU_UCODE_ID_IMU_I]; + info->ucode_id = AMDGPU_UCODE_ID_IMU_I; + info->fw = adev->gfx.imu_fw; + adev->firmware.fw_size += + ALIGN(le32_to_cpu(imu_hdr->imu_iram_ucode_size_bytes), PAGE_SIZE); + info = &adev->firmware.ucode[AMDGPU_UCODE_ID_IMU_D]; + info->ucode_id = AMDGPU_UCODE_ID_IMU_D; + info->fw = adev->gfx.imu_fw; + adev->firmware.fw_size += + ALIGN(le32_to_cpu(imu_hdr->imu_dram_ucode_size_bytes), PAGE_SIZE); + } + +out: + if (err) { + dev_err(adev->dev, + "gfx12: Failed to load firmware \"%s_imu.bin\"\n", + ucode_prefix); + amdgpu_ucode_release(&adev->gfx.imu_fw); + } + + return err; +} + +static void imu_v12_1_xcc_load_microcode(struct amdgpu_device *adev, + int xcc_id) +{ + const struct imu_firmware_header_v1_0 *hdr; + const __le32 *fw_data; + unsigned i, fw_size; + + hdr = (const struct imu_firmware_header_v1_0 *)adev->gfx.imu_fw->data; + fw_data = (const __le32 *)(adev->gfx.imu_fw->data + + le32_to_cpu(hdr->header.ucode_array_offset_bytes)); + fw_size = le32_to_cpu(hdr->imu_iram_ucode_size_bytes) / 4; + + WREG32_SOC15(GC, GET_INST(GC, xcc_id), regGFX_IMU_I_RAM_ADDR, 0); + + for (i = 0; i < fw_size; i++) + WREG32_SOC15(GC, GET_INST(GC, xcc_id), + regGFX_IMU_I_RAM_DATA, + le32_to_cpup(fw_data++)); + + WREG32_SOC15(GC, GET_INST(GC, xcc_id), + regGFX_IMU_I_RAM_ADDR, + adev->gfx.imu_fw_version); + + fw_data = (const __le32 *)(adev->gfx.imu_fw->data + + le32_to_cpu(hdr->header.ucode_array_offset_bytes) + + le32_to_cpu(hdr->imu_iram_ucode_size_bytes)); + fw_size = le32_to_cpu(hdr->imu_dram_ucode_size_bytes) / 4; + + WREG32_SOC15(GC, GET_INST(GC, xcc_id), regGFX_IMU_D_RAM_ADDR, 0); + + for (i = 0; i < fw_size; i++) + WREG32_SOC15(GC, GET_INST(GC, xcc_id), + regGFX_IMU_D_RAM_DATA, + le32_to_cpup(fw_data++)); + + WREG32_SOC15(GC, GET_INST(GC, xcc_id), + regGFX_IMU_D_RAM_ADDR, + adev->gfx.imu_fw_version); +} + +static int imu_v12_1_load_microcode(struct amdgpu_device *adev) +{ + int i, num_xcc; + + if (!adev->gfx.imu_fw) + return -EINVAL; + + num_xcc = NUM_XCC(adev->gfx.xcc_mask); + for (i = 0; i < num_xcc; i++) { + imu_v12_1_xcc_load_microcode(adev, i); + } + + return 0; +} + +const struct amdgpu_imu_funcs gfx_v12_1_imu_funcs = { + .init_microcode = imu_v12_1_init_microcode, + .load_microcode = imu_v12_1_load_microcode, +}; diff --git a/drivers/gpu/drm/amd/amdgpu/imu_v12_1.h b/drivers/gpu/drm/amd/amdgpu/imu_v12_1.h new file mode 100644 index 0000000000000..4a7c12bf7b0fb --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/imu_v12_1.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 __IMU_V12_1_H__ +#define __IMU_V12_1_H__ + +extern const struct amdgpu_imu_funcs gfx_v12_1_imu_funcs; + +#endif + -- 2.51.1
