Path: blob/master/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c
26517 views
/*1* Copyright 2016 Advanced Micro Devices, Inc.2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* the rights to use, copy, modify, merge, publish, distribute, sublicense,7* and/or sell copies of the Software, and to permit persons to whom the8* Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice shall be included in11* all copies or substantial portions of the Software.12*13* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR14* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,15* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL16* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR17* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,18* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR19* OTHER DEALINGS IN THE SOFTWARE.20*21*/2223#include <drm/amdgpu_drm.h>24#include "amdgpu.h"25#include "atomfirmware.h"26#include "amdgpu_atomfirmware.h"27#include "atom.h"28#include "atombios.h"29#include "soc15_hw_ip.h"3031union firmware_info {32struct atom_firmware_info_v3_1 v31;33struct atom_firmware_info_v3_2 v32;34struct atom_firmware_info_v3_3 v33;35struct atom_firmware_info_v3_4 v34;36struct atom_firmware_info_v3_5 v35;37};3839/*40* Helper function to query firmware capability41*42* @adev: amdgpu_device pointer43*44* Return firmware_capability in firmwareinfo table on success or 0 if not45*/46uint32_t amdgpu_atomfirmware_query_firmware_capability(struct amdgpu_device *adev)47{48struct amdgpu_mode_info *mode_info = &adev->mode_info;49int index;50u16 data_offset, size;51union firmware_info *firmware_info;52u8 frev, crev;53u32 fw_cap = 0;5455index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,56firmwareinfo);5758if (amdgpu_atom_parse_data_header(adev->mode_info.atom_context,59index, &size, &frev, &crev, &data_offset)) {60/* support firmware_info 3.1 + */61if ((frev == 3 && crev >= 1) || (frev > 3)) {62firmware_info = (union firmware_info *)63(mode_info->atom_context->bios + data_offset);64fw_cap = le32_to_cpu(firmware_info->v31.firmware_capability);65}66}6768return fw_cap;69}7071/*72* Helper function to query gpu virtualizaiton capability73*74* @adev: amdgpu_device pointer75*76* Return true if gpu virtualization is supported or false if not77*/78bool amdgpu_atomfirmware_gpu_virtualization_supported(struct amdgpu_device *adev)79{80u32 fw_cap;8182fw_cap = adev->mode_info.firmware_flags;8384return (fw_cap & ATOM_FIRMWARE_CAP_GPU_VIRTUALIZATION) ? true : false;85}8687void amdgpu_atomfirmware_scratch_regs_init(struct amdgpu_device *adev)88{89int index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,90firmwareinfo);91uint16_t data_offset;9293if (amdgpu_atom_parse_data_header(adev->mode_info.atom_context, index, NULL,94NULL, NULL, &data_offset)) {95struct atom_firmware_info_v3_1 *firmware_info =96(struct atom_firmware_info_v3_1 *)(adev->mode_info.atom_context->bios +97data_offset);9899adev->bios_scratch_reg_offset =100le32_to_cpu(firmware_info->bios_scratch_reg_startaddr);101}102}103104static int amdgpu_atomfirmware_allocate_fb_v2_1(struct amdgpu_device *adev,105struct vram_usagebyfirmware_v2_1 *fw_usage, int *usage_bytes)106{107u32 start_addr, fw_size, drv_size;108109start_addr = le32_to_cpu(fw_usage->start_address_in_kb);110fw_size = le16_to_cpu(fw_usage->used_by_firmware_in_kb);111drv_size = le16_to_cpu(fw_usage->used_by_driver_in_kb);112113DRM_DEBUG("atom firmware v2_1 requested %08x %dkb fw %dkb drv\n",114start_addr,115fw_size,116drv_size);117118if ((start_addr & ATOM_VRAM_OPERATION_FLAGS_MASK) ==119(u32)(ATOM_VRAM_BLOCK_SRIOV_MSG_SHARE_RESERVATION <<120ATOM_VRAM_OPERATION_FLAGS_SHIFT)) {121/* Firmware request VRAM reservation for SR-IOV */122adev->mman.fw_vram_usage_start_offset = (start_addr &123(~ATOM_VRAM_OPERATION_FLAGS_MASK)) << 10;124adev->mman.fw_vram_usage_size = fw_size << 10;125/* Use the default scratch size */126*usage_bytes = 0;127} else {128*usage_bytes = drv_size << 10;129}130return 0;131}132133static int amdgpu_atomfirmware_allocate_fb_v2_2(struct amdgpu_device *adev,134struct vram_usagebyfirmware_v2_2 *fw_usage, int *usage_bytes)135{136u32 fw_start_addr, fw_size, drv_start_addr, drv_size;137138fw_start_addr = le32_to_cpu(fw_usage->fw_region_start_address_in_kb);139fw_size = le16_to_cpu(fw_usage->used_by_firmware_in_kb);140141drv_start_addr = le32_to_cpu(fw_usage->driver_region0_start_address_in_kb);142drv_size = le32_to_cpu(fw_usage->used_by_driver_region0_in_kb);143144DRM_DEBUG("atom requested fw start at %08x %dkb and drv start at %08x %dkb\n",145fw_start_addr,146fw_size,147drv_start_addr,148drv_size);149150if (amdgpu_sriov_vf(adev) &&151((fw_start_addr & (ATOM_VRAM_BLOCK_NEEDS_NO_RESERVATION <<152ATOM_VRAM_OPERATION_FLAGS_SHIFT)) == 0)) {153/* Firmware request VRAM reservation for SR-IOV */154adev->mman.fw_vram_usage_start_offset = (fw_start_addr &155(~ATOM_VRAM_OPERATION_FLAGS_MASK)) << 10;156adev->mman.fw_vram_usage_size = fw_size << 10;157}158159if (amdgpu_sriov_vf(adev) &&160((drv_start_addr & (ATOM_VRAM_BLOCK_NEEDS_NO_RESERVATION <<161ATOM_VRAM_OPERATION_FLAGS_SHIFT)) == 0)) {162/* driver request VRAM reservation for SR-IOV */163adev->mman.drv_vram_usage_start_offset = (drv_start_addr &164(~ATOM_VRAM_OPERATION_FLAGS_MASK)) << 10;165adev->mman.drv_vram_usage_size = drv_size << 10;166}167168*usage_bytes = 0;169return 0;170}171172int amdgpu_atomfirmware_allocate_fb_scratch(struct amdgpu_device *adev)173{174struct atom_context *ctx = adev->mode_info.atom_context;175int index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,176vram_usagebyfirmware);177struct vram_usagebyfirmware_v2_1 *fw_usage_v2_1;178struct vram_usagebyfirmware_v2_2 *fw_usage_v2_2;179u16 data_offset;180u8 frev, crev;181int usage_bytes = 0;182183if (amdgpu_atom_parse_data_header(ctx, index, NULL, &frev, &crev, &data_offset)) {184if (frev == 2 && crev == 1) {185fw_usage_v2_1 =186(struct vram_usagebyfirmware_v2_1 *)(ctx->bios + data_offset);187amdgpu_atomfirmware_allocate_fb_v2_1(adev,188fw_usage_v2_1,189&usage_bytes);190} else if (frev >= 2 && crev >= 2) {191fw_usage_v2_2 =192(struct vram_usagebyfirmware_v2_2 *)(ctx->bios + data_offset);193amdgpu_atomfirmware_allocate_fb_v2_2(adev,194fw_usage_v2_2,195&usage_bytes);196}197}198199ctx->scratch_size_bytes = 0;200if (usage_bytes == 0)201usage_bytes = 20 * 1024;202/* allocate some scratch memory */203ctx->scratch = kzalloc(usage_bytes, GFP_KERNEL);204if (!ctx->scratch)205return -ENOMEM;206ctx->scratch_size_bytes = usage_bytes;207return 0;208}209210union igp_info {211struct atom_integrated_system_info_v1_11 v11;212struct atom_integrated_system_info_v1_12 v12;213struct atom_integrated_system_info_v2_1 v21;214struct atom_integrated_system_info_v2_3 v23;215};216217union umc_info {218struct atom_umc_info_v3_1 v31;219struct atom_umc_info_v3_2 v32;220struct atom_umc_info_v3_3 v33;221struct atom_umc_info_v4_0 v40;222};223224union vram_info {225struct atom_vram_info_header_v2_3 v23;226struct atom_vram_info_header_v2_4 v24;227struct atom_vram_info_header_v2_5 v25;228struct atom_vram_info_header_v2_6 v26;229struct atom_vram_info_header_v3_0 v30;230};231232union vram_module {233struct atom_vram_module_v9 v9;234struct atom_vram_module_v10 v10;235struct atom_vram_module_v11 v11;236struct atom_vram_module_v3_0 v30;237};238239static int convert_atom_mem_type_to_vram_type(struct amdgpu_device *adev,240int atom_mem_type)241{242int vram_type;243244if (adev->flags & AMD_IS_APU) {245switch (atom_mem_type) {246case Ddr2MemType:247case LpDdr2MemType:248vram_type = AMDGPU_VRAM_TYPE_DDR2;249break;250case Ddr3MemType:251case LpDdr3MemType:252vram_type = AMDGPU_VRAM_TYPE_DDR3;253break;254case Ddr4MemType:255vram_type = AMDGPU_VRAM_TYPE_DDR4;256break;257case LpDdr4MemType:258vram_type = AMDGPU_VRAM_TYPE_LPDDR4;259break;260case Ddr5MemType:261vram_type = AMDGPU_VRAM_TYPE_DDR5;262break;263case LpDdr5MemType:264vram_type = AMDGPU_VRAM_TYPE_LPDDR5;265break;266default:267vram_type = AMDGPU_VRAM_TYPE_UNKNOWN;268break;269}270} else {271switch (atom_mem_type) {272case ATOM_DGPU_VRAM_TYPE_GDDR5:273vram_type = AMDGPU_VRAM_TYPE_GDDR5;274break;275case ATOM_DGPU_VRAM_TYPE_HBM2:276case ATOM_DGPU_VRAM_TYPE_HBM2E:277case ATOM_DGPU_VRAM_TYPE_HBM3:278vram_type = AMDGPU_VRAM_TYPE_HBM;279break;280case ATOM_DGPU_VRAM_TYPE_GDDR6:281vram_type = AMDGPU_VRAM_TYPE_GDDR6;282break;283case ATOM_DGPU_VRAM_TYPE_HBM3E:284vram_type = AMDGPU_VRAM_TYPE_HBM3E;285break;286default:287vram_type = AMDGPU_VRAM_TYPE_UNKNOWN;288break;289}290}291292return vram_type;293}294295int296amdgpu_atomfirmware_get_vram_info(struct amdgpu_device *adev,297int *vram_width, int *vram_type,298int *vram_vendor)299{300struct amdgpu_mode_info *mode_info = &adev->mode_info;301int index, i = 0;302u16 data_offset, size;303union igp_info *igp_info;304union vram_info *vram_info;305union umc_info *umc_info;306union vram_module *vram_module;307u8 frev, crev;308u8 mem_type;309u8 mem_vendor;310u32 mem_channel_number;311u32 mem_channel_width;312u32 module_id;313314if (adev->flags & AMD_IS_APU)315index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,316integratedsysteminfo);317else {318switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {319case IP_VERSION(12, 0, 0):320case IP_VERSION(12, 0, 1):321index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1, umc_info);322break;323default:324index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1, vram_info);325}326}327if (amdgpu_atom_parse_data_header(mode_info->atom_context,328index, &size,329&frev, &crev, &data_offset)) {330if (adev->flags & AMD_IS_APU) {331igp_info = (union igp_info *)332(mode_info->atom_context->bios + data_offset);333switch (frev) {334case 1:335switch (crev) {336case 11:337case 12:338mem_channel_number = igp_info->v11.umachannelnumber;339if (!mem_channel_number)340mem_channel_number = 1;341mem_type = igp_info->v11.memorytype;342if (mem_type == LpDdr5MemType)343mem_channel_width = 32;344else345mem_channel_width = 64;346if (vram_width)347*vram_width = mem_channel_number * mem_channel_width;348if (vram_type)349*vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);350break;351default:352return -EINVAL;353}354break;355case 2:356switch (crev) {357case 1:358case 2:359mem_channel_number = igp_info->v21.umachannelnumber;360if (!mem_channel_number)361mem_channel_number = 1;362mem_type = igp_info->v21.memorytype;363if (mem_type == LpDdr5MemType)364mem_channel_width = 32;365else366mem_channel_width = 64;367if (vram_width)368*vram_width = mem_channel_number * mem_channel_width;369if (vram_type)370*vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);371break;372case 3:373mem_channel_number = igp_info->v23.umachannelnumber;374if (!mem_channel_number)375mem_channel_number = 1;376mem_type = igp_info->v23.memorytype;377if (mem_type == LpDdr5MemType)378mem_channel_width = 32;379else380mem_channel_width = 64;381if (vram_width)382*vram_width = mem_channel_number * mem_channel_width;383if (vram_type)384*vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);385break;386default:387return -EINVAL;388}389break;390default:391return -EINVAL;392}393} else {394switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {395case IP_VERSION(12, 0, 0):396case IP_VERSION(12, 0, 1):397umc_info = (union umc_info *)(mode_info->atom_context->bios + data_offset);398399if (frev == 4) {400switch (crev) {401case 0:402mem_channel_number = le32_to_cpu(umc_info->v40.channel_num);403mem_type = le32_to_cpu(umc_info->v40.vram_type);404mem_channel_width = le32_to_cpu(umc_info->v40.channel_width);405mem_vendor = RREG32(adev->bios_scratch_reg_offset + 4) & 0xF;406if (vram_vendor)407*vram_vendor = mem_vendor;408if (vram_type)409*vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);410if (vram_width)411*vram_width = mem_channel_number * (1 << mem_channel_width);412break;413default:414return -EINVAL;415}416} else417return -EINVAL;418break;419default:420vram_info = (union vram_info *)421(mode_info->atom_context->bios + data_offset);422423module_id = (RREG32(adev->bios_scratch_reg_offset + 4) & 0x00ff0000) >> 16;424if (frev == 3) {425switch (crev) {426/* v30 */427case 0:428vram_module = (union vram_module *)vram_info->v30.vram_module;429mem_vendor = (vram_module->v30.dram_vendor_id) & 0xF;430if (vram_vendor)431*vram_vendor = mem_vendor;432mem_type = vram_info->v30.memory_type;433if (vram_type)434*vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);435mem_channel_number = vram_info->v30.channel_num;436mem_channel_width = vram_info->v30.channel_width;437if (vram_width)438*vram_width = mem_channel_number * 16;439break;440default:441return -EINVAL;442}443} else if (frev == 2) {444switch (crev) {445/* v23 */446case 3:447if (module_id > vram_info->v23.vram_module_num)448module_id = 0;449vram_module = (union vram_module *)vram_info->v23.vram_module;450while (i < module_id) {451vram_module = (union vram_module *)452((u8 *)vram_module + vram_module->v9.vram_module_size);453i++;454}455mem_type = vram_module->v9.memory_type;456if (vram_type)457*vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);458mem_channel_number = vram_module->v9.channel_num;459mem_channel_width = vram_module->v9.channel_width;460if (vram_width)461*vram_width = mem_channel_number * (1 << mem_channel_width);462mem_vendor = (vram_module->v9.vender_rev_id) & 0xF;463if (vram_vendor)464*vram_vendor = mem_vendor;465break;466/* v24 */467case 4:468if (module_id > vram_info->v24.vram_module_num)469module_id = 0;470vram_module = (union vram_module *)vram_info->v24.vram_module;471while (i < module_id) {472vram_module = (union vram_module *)473((u8 *)vram_module + vram_module->v10.vram_module_size);474i++;475}476mem_type = vram_module->v10.memory_type;477if (vram_type)478*vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);479mem_channel_number = vram_module->v10.channel_num;480mem_channel_width = vram_module->v10.channel_width;481if (vram_width)482*vram_width = mem_channel_number * (1 << mem_channel_width);483mem_vendor = (vram_module->v10.vender_rev_id) & 0xF;484if (vram_vendor)485*vram_vendor = mem_vendor;486break;487/* v25 */488case 5:489if (module_id > vram_info->v25.vram_module_num)490module_id = 0;491vram_module = (union vram_module *)vram_info->v25.vram_module;492while (i < module_id) {493vram_module = (union vram_module *)494((u8 *)vram_module + vram_module->v11.vram_module_size);495i++;496}497mem_type = vram_module->v11.memory_type;498if (vram_type)499*vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);500mem_channel_number = vram_module->v11.channel_num;501mem_channel_width = vram_module->v11.channel_width;502if (vram_width)503*vram_width = mem_channel_number * (1 << mem_channel_width);504mem_vendor = (vram_module->v11.vender_rev_id) & 0xF;505if (vram_vendor)506*vram_vendor = mem_vendor;507break;508/* v26 */509case 6:510if (module_id > vram_info->v26.vram_module_num)511module_id = 0;512vram_module = (union vram_module *)vram_info->v26.vram_module;513while (i < module_id) {514vram_module = (union vram_module *)515((u8 *)vram_module + vram_module->v9.vram_module_size);516i++;517}518mem_type = vram_module->v9.memory_type;519if (vram_type)520*vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);521mem_channel_number = vram_module->v9.channel_num;522mem_channel_width = vram_module->v9.channel_width;523if (vram_width)524*vram_width = mem_channel_number * (1 << mem_channel_width);525mem_vendor = (vram_module->v9.vender_rev_id) & 0xF;526if (vram_vendor)527*vram_vendor = mem_vendor;528break;529default:530return -EINVAL;531}532} else {533/* invalid frev */534return -EINVAL;535}536}537}538}539540return 0;541}542543/*544* Return true if vbios enabled ecc by default, if umc info table is available545* or false if ecc is not enabled or umc info table is not available546*/547bool amdgpu_atomfirmware_mem_ecc_supported(struct amdgpu_device *adev)548{549struct amdgpu_mode_info *mode_info = &adev->mode_info;550int index;551u16 data_offset, size;552union umc_info *umc_info;553u8 frev, crev;554bool mem_ecc_enabled = false;555u8 umc_config;556u32 umc_config1;557adev->ras_default_ecc_enabled = false;558559index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,560umc_info);561562if (amdgpu_atom_parse_data_header(mode_info->atom_context,563index, &size, &frev, &crev, &data_offset)) {564umc_info = (union umc_info *)(mode_info->atom_context->bios + data_offset);565if (frev == 3) {566switch (crev) {567case 1:568umc_config = le32_to_cpu(umc_info->v31.umc_config);569mem_ecc_enabled =570(umc_config & UMC_CONFIG__DEFAULT_MEM_ECC_ENABLE) ? true : false;571break;572case 2:573umc_config = le32_to_cpu(umc_info->v32.umc_config);574mem_ecc_enabled =575(umc_config & UMC_CONFIG__DEFAULT_MEM_ECC_ENABLE) ? true : false;576break;577case 3:578umc_config = le32_to_cpu(umc_info->v33.umc_config);579umc_config1 = le32_to_cpu(umc_info->v33.umc_config1);580mem_ecc_enabled =581((umc_config & UMC_CONFIG__DEFAULT_MEM_ECC_ENABLE) ||582(umc_config1 & UMC_CONFIG1__ENABLE_ECC_CAPABLE)) ? true : false;583adev->ras_default_ecc_enabled =584(umc_config & UMC_CONFIG__DEFAULT_MEM_ECC_ENABLE) ? true : false;585break;586default:587/* unsupported crev */588return false;589}590} else if (frev == 4) {591switch (crev) {592case 0:593umc_config = le32_to_cpu(umc_info->v40.umc_config);594umc_config1 = le32_to_cpu(umc_info->v40.umc_config1);595mem_ecc_enabled =596(umc_config1 & UMC_CONFIG1__ENABLE_ECC_CAPABLE) ? true : false;597adev->ras_default_ecc_enabled =598(umc_config & UMC_CONFIG__DEFAULT_MEM_ECC_ENABLE) ? true : false;599break;600default:601/* unsupported crev */602return false;603}604} else {605/* unsupported frev */606return false;607}608}609610return mem_ecc_enabled;611}612613/*614* Helper function to query sram ecc capablity615*616* @adev: amdgpu_device pointer617*618* Return true if vbios supports sram ecc or false if not619*/620bool amdgpu_atomfirmware_sram_ecc_supported(struct amdgpu_device *adev)621{622u32 fw_cap;623624fw_cap = adev->mode_info.firmware_flags;625626return (fw_cap & ATOM_FIRMWARE_CAP_SRAM_ECC) ? true : false;627}628629/*630* Helper function to query dynamic boot config capability631*632* @adev: amdgpu_device pointer633*634* Return true if vbios supports dynamic boot config or false if not635*/636bool amdgpu_atomfirmware_dynamic_boot_config_supported(struct amdgpu_device *adev)637{638u32 fw_cap;639640fw_cap = adev->mode_info.firmware_flags;641642return (fw_cap & ATOM_FIRMWARE_CAP_DYNAMIC_BOOT_CFG_ENABLE) ? true : false;643}644645/**646* amdgpu_atomfirmware_ras_rom_addr -- Get the RAS EEPROM addr from VBIOS647* @adev: amdgpu_device pointer648* @i2c_address: pointer to u8; if not NULL, will contain649* the RAS EEPROM address if the function returns true650*651* Return true if VBIOS supports RAS EEPROM address reporting,652* else return false. If true and @i2c_address is not NULL,653* will contain the RAS ROM address.654*/655bool amdgpu_atomfirmware_ras_rom_addr(struct amdgpu_device *adev,656u8 *i2c_address)657{658struct amdgpu_mode_info *mode_info = &adev->mode_info;659int index;660u16 data_offset, size;661union firmware_info *firmware_info;662u8 frev, crev;663664index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,665firmwareinfo);666667if (amdgpu_atom_parse_data_header(adev->mode_info.atom_context,668index, &size, &frev, &crev,669&data_offset)) {670/* support firmware_info 3.4 + */671if ((frev == 3 && crev >= 4) || (frev > 3)) {672firmware_info = (union firmware_info *)673(mode_info->atom_context->bios + data_offset);674/* The ras_rom_i2c_slave_addr should ideally675* be a 19-bit EEPROM address, which would be676* used as is by the driver; see top of677* amdgpu_eeprom.c.678*679* When this is the case, 0 is of course a680* valid RAS EEPROM address, in which case,681* we'll drop the first "if (firm...)" and only682* leave the check for the pointer.683*684* The reason this works right now is because685* ras_rom_i2c_slave_addr contains the EEPROM686* device type qualifier 1010b in the top 4687* bits.688*/689if (firmware_info->v34.ras_rom_i2c_slave_addr) {690if (i2c_address)691*i2c_address = firmware_info->v34.ras_rom_i2c_slave_addr;692return true;693}694}695}696697return false;698}699700701union smu_info {702struct atom_smu_info_v3_1 v31;703struct atom_smu_info_v4_0 v40;704};705706union gfx_info {707struct atom_gfx_info_v2_2 v22;708struct atom_gfx_info_v2_4 v24;709struct atom_gfx_info_v2_7 v27;710struct atom_gfx_info_v3_0 v30;711};712713int amdgpu_atomfirmware_get_clock_info(struct amdgpu_device *adev)714{715struct amdgpu_mode_info *mode_info = &adev->mode_info;716struct amdgpu_pll *spll = &adev->clock.spll;717struct amdgpu_pll *mpll = &adev->clock.mpll;718uint8_t frev, crev;719uint16_t data_offset;720int ret = -EINVAL, index;721722index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,723firmwareinfo);724if (amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL,725&frev, &crev, &data_offset)) {726union firmware_info *firmware_info =727(union firmware_info *)(mode_info->atom_context->bios +728data_offset);729730adev->clock.default_sclk =731le32_to_cpu(firmware_info->v31.bootup_sclk_in10khz);732adev->clock.default_mclk =733le32_to_cpu(firmware_info->v31.bootup_mclk_in10khz);734735adev->pm.current_sclk = adev->clock.default_sclk;736adev->pm.current_mclk = adev->clock.default_mclk;737738ret = 0;739}740741index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,742smu_info);743if (amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL,744&frev, &crev, &data_offset)) {745union smu_info *smu_info =746(union smu_info *)(mode_info->atom_context->bios +747data_offset);748749/* system clock */750if (frev == 3)751spll->reference_freq = le32_to_cpu(smu_info->v31.core_refclk_10khz);752else if (frev == 4)753spll->reference_freq = le32_to_cpu(smu_info->v40.core_refclk_10khz);754755spll->reference_div = 0;756spll->min_post_div = 1;757spll->max_post_div = 1;758spll->min_ref_div = 2;759spll->max_ref_div = 0xff;760spll->min_feedback_div = 4;761spll->max_feedback_div = 0xff;762spll->best_vco = 0;763764ret = 0;765}766767index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,768umc_info);769if (amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL,770&frev, &crev, &data_offset)) {771union umc_info *umc_info =772(union umc_info *)(mode_info->atom_context->bios +773data_offset);774775/* memory clock */776mpll->reference_freq = le32_to_cpu(umc_info->v31.mem_refclk_10khz);777778mpll->reference_div = 0;779mpll->min_post_div = 1;780mpll->max_post_div = 1;781mpll->min_ref_div = 2;782mpll->max_ref_div = 0xff;783mpll->min_feedback_div = 4;784mpll->max_feedback_div = 0xff;785mpll->best_vco = 0;786787ret = 0;788}789790/* if asic is Navi+, the rlc reference clock is used for system clock791* from vbios gfx_info table */792if (adev->asic_type >= CHIP_NAVI10) {793index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,794gfx_info);795if (amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL,796&frev, &crev, &data_offset)) {797union gfx_info *gfx_info = (union gfx_info *)798(mode_info->atom_context->bios + data_offset);799if ((frev == 3) ||800(frev == 2 && crev == 6)) {801spll->reference_freq = le32_to_cpu(gfx_info->v30.golden_tsc_count_lower_refclk);802ret = 0;803} else if ((frev == 2) &&804(crev >= 2) &&805(crev != 6)) {806spll->reference_freq = le32_to_cpu(gfx_info->v22.rlc_gpu_timer_refclk);807ret = 0;808} else {809BUG();810}811}812}813814return ret;815}816817int amdgpu_atomfirmware_get_gfx_info(struct amdgpu_device *adev)818{819struct amdgpu_mode_info *mode_info = &adev->mode_info;820int index;821uint8_t frev, crev;822uint16_t data_offset;823824index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,825gfx_info);826if (amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL,827&frev, &crev, &data_offset)) {828union gfx_info *gfx_info = (union gfx_info *)829(mode_info->atom_context->bios + data_offset);830if (frev == 2) {831switch (crev) {832case 4:833adev->gfx.config.max_shader_engines = gfx_info->v24.max_shader_engines;834adev->gfx.config.max_cu_per_sh = gfx_info->v24.max_cu_per_sh;835adev->gfx.config.max_sh_per_se = gfx_info->v24.max_sh_per_se;836adev->gfx.config.max_backends_per_se = gfx_info->v24.max_backends_per_se;837adev->gfx.config.max_texture_channel_caches = gfx_info->v24.max_texture_channel_caches;838adev->gfx.config.max_gprs = le16_to_cpu(gfx_info->v24.gc_num_gprs);839adev->gfx.config.max_gs_threads = gfx_info->v24.gc_num_max_gs_thds;840adev->gfx.config.gs_vgt_table_depth = gfx_info->v24.gc_gs_table_depth;841adev->gfx.config.gs_prim_buffer_depth =842le16_to_cpu(gfx_info->v24.gc_gsprim_buff_depth);843adev->gfx.config.double_offchip_lds_buf =844gfx_info->v24.gc_double_offchip_lds_buffer;845adev->gfx.cu_info.wave_front_size = le16_to_cpu(gfx_info->v24.gc_wave_size);846adev->gfx.cu_info.max_waves_per_simd = le16_to_cpu(gfx_info->v24.gc_max_waves_per_simd);847adev->gfx.cu_info.max_scratch_slots_per_cu = gfx_info->v24.gc_max_scratch_slots_per_cu;848adev->gfx.cu_info.lds_size = le16_to_cpu(gfx_info->v24.gc_lds_size);849return 0;850case 7:851adev->gfx.config.max_shader_engines = gfx_info->v27.max_shader_engines;852adev->gfx.config.max_cu_per_sh = gfx_info->v27.max_cu_per_sh;853adev->gfx.config.max_sh_per_se = gfx_info->v27.max_sh_per_se;854adev->gfx.config.max_backends_per_se = gfx_info->v27.max_backends_per_se;855adev->gfx.config.max_texture_channel_caches = gfx_info->v27.max_texture_channel_caches;856adev->gfx.config.max_gprs = le16_to_cpu(gfx_info->v27.gc_num_gprs);857adev->gfx.config.max_gs_threads = gfx_info->v27.gc_num_max_gs_thds;858adev->gfx.config.gs_vgt_table_depth = gfx_info->v27.gc_gs_table_depth;859adev->gfx.config.gs_prim_buffer_depth = le16_to_cpu(gfx_info->v27.gc_gsprim_buff_depth);860adev->gfx.config.double_offchip_lds_buf = gfx_info->v27.gc_double_offchip_lds_buffer;861adev->gfx.cu_info.wave_front_size = le16_to_cpu(gfx_info->v27.gc_wave_size);862adev->gfx.cu_info.max_waves_per_simd = le16_to_cpu(gfx_info->v27.gc_max_waves_per_simd);863adev->gfx.cu_info.max_scratch_slots_per_cu = gfx_info->v27.gc_max_scratch_slots_per_cu;864adev->gfx.cu_info.lds_size = le16_to_cpu(gfx_info->v27.gc_lds_size);865return 0;866default:867return -EINVAL;868}869} else if (frev == 3) {870switch (crev) {871case 0:872adev->gfx.config.max_shader_engines = gfx_info->v30.max_shader_engines;873adev->gfx.config.max_cu_per_sh = gfx_info->v30.max_cu_per_sh;874adev->gfx.config.max_sh_per_se = gfx_info->v30.max_sh_per_se;875adev->gfx.config.max_backends_per_se = gfx_info->v30.max_backends_per_se;876adev->gfx.config.max_texture_channel_caches = gfx_info->v30.max_texture_channel_caches;877return 0;878default:879return -EINVAL;880}881} else {882return -EINVAL;883}884885}886return -EINVAL;887}888889/*890* Helper function to query two stage mem training capability891*892* @adev: amdgpu_device pointer893*894* Return true if two stage mem training is supported or false if not895*/896bool amdgpu_atomfirmware_mem_training_supported(struct amdgpu_device *adev)897{898u32 fw_cap;899900fw_cap = adev->mode_info.firmware_flags;901902return (fw_cap & ATOM_FIRMWARE_CAP_ENABLE_2STAGE_BIST_TRAINING) ? true : false;903}904905int amdgpu_atomfirmware_get_fw_reserved_fb_size(struct amdgpu_device *adev)906{907struct atom_context *ctx = adev->mode_info.atom_context;908union firmware_info *firmware_info;909int index;910u16 data_offset, size;911u8 frev, crev;912int fw_reserved_fb_size;913914index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,915firmwareinfo);916917if (!amdgpu_atom_parse_data_header(ctx, index, &size,918&frev, &crev, &data_offset))919/* fail to parse data_header */920return 0;921922firmware_info = (union firmware_info *)(ctx->bios + data_offset);923924if (frev != 3)925return -EINVAL;926927switch (crev) {928case 4:929fw_reserved_fb_size =930(firmware_info->v34.fw_reserved_size_in_kb << 10);931break;932case 5:933fw_reserved_fb_size =934(firmware_info->v35.fw_reserved_size_in_kb << 10);935break;936default:937fw_reserved_fb_size = 0;938break;939}940941return fw_reserved_fb_size;942}943944/*945* Helper function to execute asic_init table946*947* @adev: amdgpu_device pointer948* @fb_reset: flag to indicate whether fb is reset or not949*950* Return 0 if succeed, otherwise failed951*/952int amdgpu_atomfirmware_asic_init(struct amdgpu_device *adev, bool fb_reset)953{954struct amdgpu_mode_info *mode_info = &adev->mode_info;955struct atom_context *ctx;956uint8_t frev, crev;957uint16_t data_offset;958uint32_t bootup_sclk_in10khz, bootup_mclk_in10khz;959struct asic_init_ps_allocation_v2_1 asic_init_ps_v2_1;960int index;961962if (!mode_info)963return -EINVAL;964965ctx = mode_info->atom_context;966if (!ctx)967return -EINVAL;968969/* query bootup sclk/mclk from firmware_info table */970index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,971firmwareinfo);972if (amdgpu_atom_parse_data_header(ctx, index, NULL,973&frev, &crev, &data_offset)) {974union firmware_info *firmware_info =975(union firmware_info *)(ctx->bios +976data_offset);977978bootup_sclk_in10khz =979le32_to_cpu(firmware_info->v31.bootup_sclk_in10khz);980bootup_mclk_in10khz =981le32_to_cpu(firmware_info->v31.bootup_mclk_in10khz);982} else {983return -EINVAL;984}985986index = get_index_into_master_table(atom_master_list_of_command_functions_v2_1,987asic_init);988if (amdgpu_atom_parse_cmd_header(mode_info->atom_context, index, &frev, &crev)) {989if (frev == 2 && crev >= 1) {990memset(&asic_init_ps_v2_1, 0, sizeof(asic_init_ps_v2_1));991asic_init_ps_v2_1.param.engineparam.sclkfreqin10khz = bootup_sclk_in10khz;992asic_init_ps_v2_1.param.memparam.mclkfreqin10khz = bootup_mclk_in10khz;993asic_init_ps_v2_1.param.engineparam.engineflag = b3NORMAL_ENGINE_INIT;994if (!fb_reset)995asic_init_ps_v2_1.param.memparam.memflag = b3DRAM_SELF_REFRESH_EXIT;996else997asic_init_ps_v2_1.param.memparam.memflag = 0;998} else {999return -EINVAL;1000}1001} else {1002return -EINVAL;1003}10041005return amdgpu_atom_execute_table(ctx, ATOM_CMD_INIT, (uint32_t *)&asic_init_ps_v2_1,1006sizeof(asic_init_ps_v2_1));1007}100810091010