/* * Copyright 2014 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. *
*/
enum amdgpu_firmware_load_type
amdgpu_ucode_get_load_type(struct amdgpu_device *adev, int load_type)
{ switch (adev->asic_type) { #ifdef CONFIG_DRM_AMDGPU_SI case CHIP_TAHITI: case CHIP_PITCAIRN: case CHIP_VERDE: case CHIP_OLAND: case CHIP_HAINAN: return AMDGPU_FW_LOAD_DIRECT; #endif #ifdef CONFIG_DRM_AMDGPU_CIK case CHIP_BONAIRE: case CHIP_KAVERI: case CHIP_KABINI: case CHIP_HAWAII: case CHIP_MULLINS: return AMDGPU_FW_LOAD_DIRECT; #endif case CHIP_TOPAZ: case CHIP_TONGA: case CHIP_FIJI: case CHIP_CARRIZO: case CHIP_STONEY: case CHIP_POLARIS10: case CHIP_POLARIS11: case CHIP_POLARIS12: case CHIP_VEGAM: return AMDGPU_FW_LOAD_SMU; case CHIP_CYAN_SKILLFISH: if (!(load_type &&
adev->apu_flags & AMD_APU_IS_CYAN_SKILLFISH2)) return AMDGPU_FW_LOAD_DIRECT; else return AMDGPU_FW_LOAD_PSP; default: if (!load_type) return AMDGPU_FW_LOAD_DIRECT; elseif (load_type == 3) return AMDGPU_FW_LOAD_RLC_BACKDOOR_AUTO; else return AMDGPU_FW_LOAD_PSP;
}
}
constchar *amdgpu_ucode_name(enum AMDGPU_UCODE_ID ucode_id)
{ switch (ucode_id) { case AMDGPU_UCODE_ID_SDMA0: return"SDMA0"; case AMDGPU_UCODE_ID_SDMA1: return"SDMA1"; case AMDGPU_UCODE_ID_SDMA2: return"SDMA2"; case AMDGPU_UCODE_ID_SDMA3: return"SDMA3"; case AMDGPU_UCODE_ID_SDMA4: return"SDMA4"; case AMDGPU_UCODE_ID_SDMA5: return"SDMA5"; case AMDGPU_UCODE_ID_SDMA6: return"SDMA6"; case AMDGPU_UCODE_ID_SDMA7: return"SDMA7"; case AMDGPU_UCODE_ID_SDMA_UCODE_TH0: return"SDMA_CTX"; case AMDGPU_UCODE_ID_SDMA_UCODE_TH1: return"SDMA_CTL"; case AMDGPU_UCODE_ID_CP_CE: return"CP_CE"; case AMDGPU_UCODE_ID_CP_PFP: return"CP_PFP"; case AMDGPU_UCODE_ID_CP_ME: return"CP_ME"; case AMDGPU_UCODE_ID_CP_MEC1: return"CP_MEC1"; case AMDGPU_UCODE_ID_CP_MEC1_JT: return"CP_MEC1_JT"; case AMDGPU_UCODE_ID_CP_MEC2: return"CP_MEC2"; case AMDGPU_UCODE_ID_CP_MEC2_JT: return"CP_MEC2_JT"; case AMDGPU_UCODE_ID_CP_MES: return"CP_MES"; case AMDGPU_UCODE_ID_CP_MES_DATA: return"CP_MES_DATA"; case AMDGPU_UCODE_ID_CP_MES1: return"CP_MES_KIQ"; case AMDGPU_UCODE_ID_CP_MES1_DATA: return"CP_MES_KIQ_DATA"; case AMDGPU_UCODE_ID_RLC_RESTORE_LIST_CNTL: return"RLC_RESTORE_LIST_CNTL"; case AMDGPU_UCODE_ID_RLC_RESTORE_LIST_GPM_MEM: return"RLC_RESTORE_LIST_GPM_MEM"; case AMDGPU_UCODE_ID_RLC_RESTORE_LIST_SRM_MEM: return"RLC_RESTORE_LIST_SRM_MEM"; case AMDGPU_UCODE_ID_RLC_IRAM: return"RLC_IRAM"; case AMDGPU_UCODE_ID_RLC_DRAM: return"RLC_DRAM"; case AMDGPU_UCODE_ID_RLC_G: return"RLC_G"; case AMDGPU_UCODE_ID_RLC_P: return"RLC_P"; case AMDGPU_UCODE_ID_RLC_V: return"RLC_V"; case AMDGPU_UCODE_ID_GLOBAL_TAP_DELAYS: return"GLOBAL_TAP_DELAYS"; case AMDGPU_UCODE_ID_SE0_TAP_DELAYS: return"SE0_TAP_DELAYS"; case AMDGPU_UCODE_ID_SE1_TAP_DELAYS: return"SE1_TAP_DELAYS"; case AMDGPU_UCODE_ID_SE2_TAP_DELAYS: return"SE2_TAP_DELAYS"; case AMDGPU_UCODE_ID_SE3_TAP_DELAYS: return"SE3_TAP_DELAYS"; case AMDGPU_UCODE_ID_IMU_I: return"IMU_I"; case AMDGPU_UCODE_ID_IMU_D: return"IMU_D"; case AMDGPU_UCODE_ID_STORAGE: return"STORAGE"; case AMDGPU_UCODE_ID_SMC: return"SMC"; case AMDGPU_UCODE_ID_PPTABLE: return"PPTABLE"; case AMDGPU_UCODE_ID_P2S_TABLE: return"P2STABLE"; case AMDGPU_UCODE_ID_UVD: return"UVD"; case AMDGPU_UCODE_ID_UVD1: return"UVD1"; case AMDGPU_UCODE_ID_VCE: return"VCE"; case AMDGPU_UCODE_ID_VCN: return"VCN"; case AMDGPU_UCODE_ID_VCN1: return"VCN1"; case AMDGPU_UCODE_ID_DMCU_ERAM: return"DMCU_ERAM"; case AMDGPU_UCODE_ID_DMCU_INTV: return"DMCU_INTV"; case AMDGPU_UCODE_ID_VCN0_RAM: return"VCN0_RAM"; case AMDGPU_UCODE_ID_VCN1_RAM: return"VCN1_RAM"; case AMDGPU_UCODE_ID_DMCUB: return"DMCUB"; case AMDGPU_UCODE_ID_CAP: return"CAP"; case AMDGPU_UCODE_ID_VPE_CTX: return"VPE_CTX"; case AMDGPU_UCODE_ID_VPE_CTL: return"VPE_CTL"; case AMDGPU_UCODE_ID_VPE: return"VPE"; case AMDGPU_UCODE_ID_UMSCH_MM_UCODE: return"UMSCH_MM_UCODE"; case AMDGPU_UCODE_ID_UMSCH_MM_DATA: return"UMSCH_MM_DATA"; case AMDGPU_UCODE_ID_UMSCH_MM_CMD_BUFFER: return"UMSCH_MM_CMD_BUFFER"; case AMDGPU_UCODE_ID_JPEG_RAM: return"JPEG"; case AMDGPU_UCODE_ID_SDMA_RS64: return"RS64_SDMA"; case AMDGPU_UCODE_ID_CP_RS64_PFP: return"RS64_PFP"; case AMDGPU_UCODE_ID_CP_RS64_ME: return"RS64_ME"; case AMDGPU_UCODE_ID_CP_RS64_MEC: return"RS64_MEC"; case AMDGPU_UCODE_ID_CP_RS64_PFP_P0_STACK: return"RS64_PFP_P0_STACK"; case AMDGPU_UCODE_ID_CP_RS64_PFP_P1_STACK: return"RS64_PFP_P1_STACK"; case AMDGPU_UCODE_ID_CP_RS64_ME_P0_STACK: return"RS64_ME_P0_STACK"; case AMDGPU_UCODE_ID_CP_RS64_ME_P1_STACK: return"RS64_ME_P1_STACK"; case AMDGPU_UCODE_ID_CP_RS64_MEC_P0_STACK: return"RS64_MEC_P0_STACK"; case AMDGPU_UCODE_ID_CP_RS64_MEC_P1_STACK: return"RS64_MEC_P1_STACK"; case AMDGPU_UCODE_ID_CP_RS64_MEC_P2_STACK: return"RS64_MEC_P2_STACK"; case AMDGPU_UCODE_ID_CP_RS64_MEC_P3_STACK: return"RS64_MEC_P3_STACK"; case AMDGPU_UCODE_ID_ISP: return"ISP"; default: return"UNKNOWN UCODE";
}
}
staticinlineint amdgpu_ucode_is_valid(uint32_t fw_version)
{ if (!fw_version) return -EINVAL;
int amdgpu_ucode_init_bo(struct amdgpu_device *adev)
{
uint64_t fw_offset = 0; int i; struct amdgpu_firmware_info *ucode = NULL;
/* for baremetal, the ucode is allocated in gtt, so don't need to fill the bo when reset/suspend */ if (!amdgpu_sriov_vf(adev) && (amdgpu_in_reset(adev) || adev->in_suspend)) return 0; /* * if SMU loaded firmware, it needn't add SMC, UVD, and VCE * ucode info here
*/ if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) { if (amdgpu_sriov_vf(adev))
adev->firmware.max_ucodes = AMDGPU_UCODE_ID_MAXIMUM - 3; else
adev->firmware.max_ucodes = AMDGPU_UCODE_ID_MAXIMUM - 4;
} else {
adev->firmware.max_ucodes = AMDGPU_UCODE_ID_MAXIMUM;
}
if (amdgpu_virt_xgmi_migrate_enabled(adev) && adev->firmware.fw_buf)
adev->firmware.fw_buf_mc = amdgpu_bo_fb_aper_addr(adev->firmware.fw_buf);
for (i = 0; i < adev->firmware.max_ucodes; i++) {
ucode = &adev->firmware.ucode[i]; if (ucode->fw) {
amdgpu_ucode_init_single_fw(adev, ucode, adev->firmware.fw_buf_mc + fw_offset,
adev->firmware.fw_buf_ptr + fw_offset); if (i == AMDGPU_UCODE_ID_CP_MEC1 &&
adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) { conststruct gfx_firmware_header_v1_0 *cp_hdr;
staticconstchar *amdgpu_ucode_legacy_naming(struct amdgpu_device *adev, int block_type)
{ if (block_type == MP0_HWIP) { switch (amdgpu_ip_version(adev, MP0_HWIP, 0)) { case IP_VERSION(9, 0, 0): switch (adev->asic_type) { case CHIP_VEGA10: return"vega10"; case CHIP_VEGA12: return"vega12"; default: return NULL;
} case IP_VERSION(10, 0, 0): case IP_VERSION(10, 0, 1): if (adev->asic_type == CHIP_RAVEN) { if (adev->apu_flags & AMD_APU_IS_RAVEN2) return"raven2"; elseif (adev->apu_flags & AMD_APU_IS_PICASSO) return"picasso"; return"raven";
} break; case IP_VERSION(11, 0, 0): return"navi10"; case IP_VERSION(11, 0, 2): return"vega20"; case IP_VERSION(11, 0, 3): return"renoir"; case IP_VERSION(11, 0, 4): return"arcturus"; case IP_VERSION(11, 0, 5): return"navi14"; case IP_VERSION(11, 0, 7): return"sienna_cichlid"; case IP_VERSION(11, 0, 9): return"navi12"; case IP_VERSION(11, 0, 11): return"navy_flounder"; case IP_VERSION(11, 0, 12): return"dimgrey_cavefish"; case IP_VERSION(11, 0, 13): return"beige_goby"; case IP_VERSION(11, 5, 0): case IP_VERSION(11, 5, 2): return"vangogh"; case IP_VERSION(12, 0, 1): return"green_sardine"; case IP_VERSION(13, 0, 2): return"aldebaran"; case IP_VERSION(13, 0, 1): case IP_VERSION(13, 0, 3): return"yellow_carp";
}
} elseif (block_type == MP1_HWIP) { switch (amdgpu_ip_version(adev, MP1_HWIP, 0)) { case IP_VERSION(9, 0, 0): case IP_VERSION(10, 0, 0): case IP_VERSION(10, 0, 1): case IP_VERSION(11, 0, 2): if (adev->asic_type == CHIP_ARCTURUS) return"arcturus_smc"; return NULL; case IP_VERSION(11, 0, 0): return"navi10_smc"; case IP_VERSION(11, 0, 5): return"navi14_smc"; case IP_VERSION(11, 0, 9): return"navi12_smc"; case IP_VERSION(11, 0, 7): return"sienna_cichlid_smc"; case IP_VERSION(11, 0, 11): return"navy_flounder_smc"; case IP_VERSION(11, 0, 12): return"dimgrey_cavefish_smc"; case IP_VERSION(11, 0, 13): return"beige_goby_smc"; case IP_VERSION(13, 0, 2): return"aldebaran_smc";
}
} elseif (block_type == SDMA0_HWIP) { switch (amdgpu_ip_version(adev, SDMA0_HWIP, 0)) { case IP_VERSION(4, 0, 0): return"vega10_sdma"; case IP_VERSION(4, 0, 1): return"vega12_sdma"; case IP_VERSION(4, 1, 0): case IP_VERSION(4, 1, 1): if (adev->apu_flags & AMD_APU_IS_RAVEN2) return"raven2_sdma"; elseif (adev->apu_flags & AMD_APU_IS_PICASSO) return"picasso_sdma"; return"raven_sdma"; case IP_VERSION(4, 1, 2): if (adev->apu_flags & AMD_APU_IS_RENOIR) return"renoir_sdma"; return"green_sardine_sdma"; case IP_VERSION(4, 2, 0): return"vega20_sdma"; case IP_VERSION(4, 2, 2): return"arcturus_sdma"; case IP_VERSION(4, 4, 0): return"aldebaran_sdma"; case IP_VERSION(5, 0, 0): return"navi10_sdma"; case IP_VERSION(5, 0, 1): return"cyan_skillfish2_sdma"; case IP_VERSION(5, 0, 2): return"navi14_sdma"; case IP_VERSION(5, 0, 5): return"navi12_sdma"; case IP_VERSION(5, 2, 0): return"sienna_cichlid_sdma"; case IP_VERSION(5, 2, 2): return"navy_flounder_sdma"; case IP_VERSION(5, 2, 4): return"dimgrey_cavefish_sdma"; case IP_VERSION(5, 2, 5): return"beige_goby_sdma"; case IP_VERSION(5, 2, 3): return"yellow_carp_sdma"; case IP_VERSION(5, 2, 1): return"vangogh_sdma";
}
} elseif (block_type == UVD_HWIP) { switch (amdgpu_ip_version(adev, UVD_HWIP, 0)) { case IP_VERSION(1, 0, 0): case IP_VERSION(1, 0, 1): if (adev->apu_flags & AMD_APU_IS_RAVEN2) return"raven2_vcn"; elseif (adev->apu_flags & AMD_APU_IS_PICASSO) return"picasso_vcn"; return"raven_vcn"; case IP_VERSION(2, 5, 0): return"arcturus_vcn"; case IP_VERSION(2, 2, 0): if (adev->apu_flags & AMD_APU_IS_RENOIR) return"renoir_vcn"; return"green_sardine_vcn"; case IP_VERSION(2, 6, 0): return"aldebaran_vcn"; case IP_VERSION(2, 0, 0): return"navi10_vcn"; case IP_VERSION(2, 0, 2): if (adev->asic_type == CHIP_NAVI12) return"navi12_vcn"; return"navi14_vcn"; case IP_VERSION(3, 0, 0): case IP_VERSION(3, 0, 64): case IP_VERSION(3, 0, 192): if (amdgpu_ip_version(adev, GC_HWIP, 0) ==
IP_VERSION(10, 3, 0)) return"sienna_cichlid_vcn"; return"navy_flounder_vcn"; case IP_VERSION(3, 0, 2): return"vangogh_vcn"; case IP_VERSION(3, 0, 16): return"dimgrey_cavefish_vcn"; case IP_VERSION(3, 0, 33): return"beige_goby_vcn"; case IP_VERSION(3, 1, 1): return"yellow_carp_vcn";
}
} elseif (block_type == GC_HWIP) { switch (amdgpu_ip_version(adev, GC_HWIP, 0)) { case IP_VERSION(9, 0, 1): return"vega10"; case IP_VERSION(9, 2, 1): return"vega12"; case IP_VERSION(9, 4, 0): return"vega20"; case IP_VERSION(9, 2, 2): case IP_VERSION(9, 1, 0): if (adev->apu_flags & AMD_APU_IS_RAVEN2) return"raven2"; elseif (adev->apu_flags & AMD_APU_IS_PICASSO) return"picasso"; return"raven"; case IP_VERSION(9, 4, 1): return"arcturus"; case IP_VERSION(9, 3, 0): if (adev->apu_flags & AMD_APU_IS_RENOIR) return"renoir"; return"green_sardine"; case IP_VERSION(9, 4, 2): return"aldebaran"; case IP_VERSION(10, 1, 10): return"navi10"; case IP_VERSION(10, 1, 1): return"navi14"; case IP_VERSION(10, 1, 2): return"navi12"; case IP_VERSION(10, 3, 0): return"sienna_cichlid"; case IP_VERSION(10, 3, 2): return"navy_flounder"; case IP_VERSION(10, 3, 1): return"vangogh"; case IP_VERSION(10, 3, 4): return"dimgrey_cavefish"; case IP_VERSION(10, 3, 5): return"beige_goby"; case IP_VERSION(10, 3, 3): return"yellow_carp"; case IP_VERSION(10, 1, 3): case IP_VERSION(10, 1, 4): return"cyan_skillfish2";
}
} return NULL;
}
bool amdgpu_is_kicker_fw(struct amdgpu_device *adev)
{ int i;
for (i = 0; i < ARRAY_SIZE(kicker_device_list); i++) { if (adev->pdev->device == kicker_device_list[i].device &&
adev->pdev->revision == kicker_device_list[i].revision) returntrue;
}
returnfalse;
}
void amdgpu_ucode_ip_version_decode(struct amdgpu_device *adev, int block_type, char *ucode_prefix, int len)
{ int maj, min, rev; char *ip_name; constchar *legacy;
uint32_t version = amdgpu_ip_version(adev, block_type, 0);
/* * amdgpu_ucode_request - Fetch and validate amdgpu microcode * * @adev: amdgpu device * @fw: pointer to load firmware to * @required: whether the firmware is required * @fmt: firmware name format string * @...: variable arguments * * This is a helper that will use request_firmware and amdgpu_ucode_validate * to load and run basic validation on firmware. If the load fails, remap * the error code to -ENODEV, so that early_init functions will fail to load.
*/ int amdgpu_ucode_request(struct amdgpu_device *adev, conststruct firmware **fw, enum amdgpu_ucode_required required, constchar *fmt, ...)
{ char fname[AMDGPU_UCODE_NAME_MAX];
va_list ap; int r;
va_start(ap, fmt);
r = vsnprintf(fname, sizeof(fname), fmt, ap);
va_end(ap); if (r == sizeof(fname)) {
dev_warn(adev->dev, "amdgpu firmware name buffer overflow\n"); return -EOVERFLOW;
}
if (required == AMDGPU_UCODE_REQUIRED)
r = request_firmware(fw, fname, adev->dev); else {
r = firmware_request_nowarn(fw, fname, adev->dev); if (r)
drm_info(&adev->ddev, "Optional firmware \"%s\" was not found\n", fname);
} if (r) return -ENODEV;
r = amdgpu_ucode_validate(*fw); if (r) /* * The amdgpu_ucode_request() should be paired with amdgpu_ucode_release() * regardless of success/failure, and the amdgpu_ucode_release() takes care of * firmware release and need to avoid redundant release FW operation here.
*/
dev_dbg(adev->dev, "\"%s\" failed to validate\n", fname);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.