Path: blob/master/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c
49187 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;182183/* Skip atomfirmware allocation for SRIOV VFs when dynamic crit regn is enabled */184if (!(amdgpu_sriov_vf(adev) && adev->virt.is_dynamic_crit_regn_enabled)) {185if (amdgpu_atom_parse_data_header(ctx, index, NULL, &frev, &crev, &data_offset)) {186if (frev == 2 && crev == 1) {187fw_usage_v2_1 =188(struct vram_usagebyfirmware_v2_1 *)(ctx->bios + data_offset);189amdgpu_atomfirmware_allocate_fb_v2_1(adev,190fw_usage_v2_1,191&usage_bytes);192} else if (frev >= 2 && crev >= 2) {193fw_usage_v2_2 =194(struct vram_usagebyfirmware_v2_2 *)(ctx->bios + data_offset);195amdgpu_atomfirmware_allocate_fb_v2_2(adev,196fw_usage_v2_2,197&usage_bytes);198}199}200}201202ctx->scratch_size_bytes = 0;203if (usage_bytes == 0)204usage_bytes = 20 * 1024;205/* allocate some scratch memory */206ctx->scratch = kzalloc(usage_bytes, GFP_KERNEL);207if (!ctx->scratch)208return -ENOMEM;209ctx->scratch_size_bytes = usage_bytes;210return 0;211}212213union igp_info {214struct atom_integrated_system_info_v1_11 v11;215struct atom_integrated_system_info_v1_12 v12;216struct atom_integrated_system_info_v2_1 v21;217struct atom_integrated_system_info_v2_3 v23;218};219220union umc_info {221struct atom_umc_info_v3_1 v31;222struct atom_umc_info_v3_2 v32;223struct atom_umc_info_v3_3 v33;224struct atom_umc_info_v4_0 v40;225};226227union vram_info {228struct atom_vram_info_header_v2_3 v23;229struct atom_vram_info_header_v2_4 v24;230struct atom_vram_info_header_v2_5 v25;231struct atom_vram_info_header_v2_6 v26;232struct atom_vram_info_header_v3_0 v30;233};234235union vram_module {236struct atom_vram_module_v9 v9;237struct atom_vram_module_v10 v10;238struct atom_vram_module_v11 v11;239struct atom_vram_module_v3_0 v30;240};241242static int convert_atom_mem_type_to_vram_type(struct amdgpu_device *adev,243int atom_mem_type)244{245int vram_type;246247if (adev->flags & AMD_IS_APU) {248switch (atom_mem_type) {249case Ddr2MemType:250case LpDdr2MemType:251vram_type = AMDGPU_VRAM_TYPE_DDR2;252break;253case Ddr3MemType:254case LpDdr3MemType:255vram_type = AMDGPU_VRAM_TYPE_DDR3;256break;257case Ddr4MemType:258vram_type = AMDGPU_VRAM_TYPE_DDR4;259break;260case LpDdr4MemType:261vram_type = AMDGPU_VRAM_TYPE_LPDDR4;262break;263case Ddr5MemType:264vram_type = AMDGPU_VRAM_TYPE_DDR5;265break;266case LpDdr5MemType:267vram_type = AMDGPU_VRAM_TYPE_LPDDR5;268break;269default:270vram_type = AMDGPU_VRAM_TYPE_UNKNOWN;271break;272}273} else {274switch (atom_mem_type) {275case ATOM_DGPU_VRAM_TYPE_GDDR5:276vram_type = AMDGPU_VRAM_TYPE_GDDR5;277break;278case ATOM_DGPU_VRAM_TYPE_HBM2:279case ATOM_DGPU_VRAM_TYPE_HBM2E:280case ATOM_DGPU_VRAM_TYPE_HBM3:281vram_type = AMDGPU_VRAM_TYPE_HBM;282break;283case ATOM_DGPU_VRAM_TYPE_GDDR6:284vram_type = AMDGPU_VRAM_TYPE_GDDR6;285break;286case ATOM_DGPU_VRAM_TYPE_HBM3E:287vram_type = AMDGPU_VRAM_TYPE_HBM3E;288break;289default:290vram_type = AMDGPU_VRAM_TYPE_UNKNOWN;291break;292}293}294295return vram_type;296}297298int299amdgpu_atomfirmware_get_vram_info(struct amdgpu_device *adev,300int *vram_width, int *vram_type,301int *vram_vendor)302{303struct amdgpu_mode_info *mode_info = &adev->mode_info;304int index, i = 0;305u16 data_offset, size;306union igp_info *igp_info;307union vram_info *vram_info;308union umc_info *umc_info;309union vram_module *vram_module;310u8 frev, crev;311u8 mem_type;312u8 mem_vendor;313u32 mem_channel_number;314u32 mem_channel_width;315u32 module_id;316317if (adev->flags & AMD_IS_APU)318index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,319integratedsysteminfo);320else {321switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {322case IP_VERSION(12, 0, 0):323case IP_VERSION(12, 0, 1):324index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1, umc_info);325break;326default:327index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1, vram_info);328}329}330if (amdgpu_atom_parse_data_header(mode_info->atom_context,331index, &size,332&frev, &crev, &data_offset)) {333if (adev->flags & AMD_IS_APU) {334igp_info = (union igp_info *)335(mode_info->atom_context->bios + data_offset);336switch (frev) {337case 1:338switch (crev) {339case 11:340case 12:341mem_channel_number = igp_info->v11.umachannelnumber;342if (!mem_channel_number)343mem_channel_number = 1;344mem_type = igp_info->v11.memorytype;345if (mem_type == LpDdr5MemType)346mem_channel_width = 32;347else348mem_channel_width = 64;349if (vram_width)350*vram_width = mem_channel_number * mem_channel_width;351if (vram_type)352*vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);353break;354default:355return -EINVAL;356}357break;358case 2:359switch (crev) {360case 1:361case 2:362mem_channel_number = igp_info->v21.umachannelnumber;363if (!mem_channel_number)364mem_channel_number = 1;365mem_type = igp_info->v21.memorytype;366if (mem_type == LpDdr5MemType)367mem_channel_width = 32;368else369mem_channel_width = 64;370if (vram_width)371*vram_width = mem_channel_number * mem_channel_width;372if (vram_type)373*vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);374break;375case 3:376mem_channel_number = igp_info->v23.umachannelnumber;377if (!mem_channel_number)378mem_channel_number = 1;379mem_type = igp_info->v23.memorytype;380if (mem_type == LpDdr5MemType)381mem_channel_width = 32;382else383mem_channel_width = 64;384if (vram_width)385*vram_width = mem_channel_number * mem_channel_width;386if (vram_type)387*vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);388break;389default:390return -EINVAL;391}392break;393default:394return -EINVAL;395}396} else {397switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {398case IP_VERSION(12, 0, 0):399case IP_VERSION(12, 0, 1):400umc_info = (union umc_info *)(mode_info->atom_context->bios + data_offset);401402if (frev == 4) {403switch (crev) {404case 0:405mem_channel_number = le32_to_cpu(umc_info->v40.channel_num);406mem_type = le32_to_cpu(umc_info->v40.vram_type);407mem_channel_width = le32_to_cpu(umc_info->v40.channel_width);408mem_vendor = RREG32(adev->bios_scratch_reg_offset + 4) & 0xF;409if (vram_vendor)410*vram_vendor = mem_vendor;411if (vram_type)412*vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);413if (vram_width)414*vram_width = mem_channel_number * (1 << mem_channel_width);415break;416default:417return -EINVAL;418}419} else420return -EINVAL;421break;422default:423vram_info = (union vram_info *)424(mode_info->atom_context->bios + data_offset);425426module_id = (RREG32(adev->bios_scratch_reg_offset + 4) & 0x00ff0000) >> 16;427if (frev == 3) {428switch (crev) {429/* v30 */430case 0:431vram_module = (union vram_module *)vram_info->v30.vram_module;432mem_vendor = (vram_module->v30.dram_vendor_id) & 0xF;433if (vram_vendor)434*vram_vendor = mem_vendor;435mem_type = vram_info->v30.memory_type;436if (vram_type)437*vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);438mem_channel_number = vram_info->v30.channel_num;439mem_channel_width = vram_info->v30.channel_width;440if (vram_width)441*vram_width = mem_channel_number * 16;442break;443default:444return -EINVAL;445}446} else if (frev == 2) {447switch (crev) {448/* v23 */449case 3:450if (module_id > vram_info->v23.vram_module_num)451module_id = 0;452vram_module = (union vram_module *)vram_info->v23.vram_module;453while (i < module_id) {454vram_module = (union vram_module *)455((u8 *)vram_module + vram_module->v9.vram_module_size);456i++;457}458mem_type = vram_module->v9.memory_type;459if (vram_type)460*vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);461mem_channel_number = vram_module->v9.channel_num;462mem_channel_width = vram_module->v9.channel_width;463if (vram_width)464*vram_width = mem_channel_number * (1 << mem_channel_width);465mem_vendor = (vram_module->v9.vender_rev_id) & 0xF;466if (vram_vendor)467*vram_vendor = mem_vendor;468break;469/* v24 */470case 4:471if (module_id > vram_info->v24.vram_module_num)472module_id = 0;473vram_module = (union vram_module *)vram_info->v24.vram_module;474while (i < module_id) {475vram_module = (union vram_module *)476((u8 *)vram_module + vram_module->v10.vram_module_size);477i++;478}479mem_type = vram_module->v10.memory_type;480if (vram_type)481*vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);482mem_channel_number = vram_module->v10.channel_num;483mem_channel_width = vram_module->v10.channel_width;484if (vram_width)485*vram_width = mem_channel_number * (1 << mem_channel_width);486mem_vendor = (vram_module->v10.vender_rev_id) & 0xF;487if (vram_vendor)488*vram_vendor = mem_vendor;489break;490/* v25 */491case 5:492if (module_id > vram_info->v25.vram_module_num)493module_id = 0;494vram_module = (union vram_module *)vram_info->v25.vram_module;495while (i < module_id) {496vram_module = (union vram_module *)497((u8 *)vram_module + vram_module->v11.vram_module_size);498i++;499}500mem_type = vram_module->v11.memory_type;501if (vram_type)502*vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);503mem_channel_number = vram_module->v11.channel_num;504mem_channel_width = vram_module->v11.channel_width;505if (vram_width)506*vram_width = mem_channel_number * (1 << mem_channel_width);507mem_vendor = (vram_module->v11.vender_rev_id) & 0xF;508if (vram_vendor)509*vram_vendor = mem_vendor;510break;511/* v26 */512case 6:513if (module_id > vram_info->v26.vram_module_num)514module_id = 0;515vram_module = (union vram_module *)vram_info->v26.vram_module;516while (i < module_id) {517vram_module = (union vram_module *)518((u8 *)vram_module + vram_module->v9.vram_module_size);519i++;520}521mem_type = vram_module->v9.memory_type;522if (vram_type)523*vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);524mem_channel_number = vram_module->v9.channel_num;525mem_channel_width = vram_module->v9.channel_width;526if (vram_width)527*vram_width = mem_channel_number * (1 << mem_channel_width);528mem_vendor = (vram_module->v9.vender_rev_id) & 0xF;529if (vram_vendor)530*vram_vendor = mem_vendor;531break;532default:533return -EINVAL;534}535} else {536/* invalid frev */537return -EINVAL;538}539}540}541}542543return 0;544}545546/*547* Return true if vbios enabled ecc by default, if umc info table is available548* or false if ecc is not enabled or umc info table is not available549*/550bool amdgpu_atomfirmware_mem_ecc_supported(struct amdgpu_device *adev)551{552struct amdgpu_mode_info *mode_info = &adev->mode_info;553int index;554u16 data_offset, size;555union umc_info *umc_info;556u8 frev, crev;557bool mem_ecc_enabled = false;558u8 umc_config;559u32 umc_config1;560adev->ras_default_ecc_enabled = false;561562index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,563umc_info);564565if (amdgpu_atom_parse_data_header(mode_info->atom_context,566index, &size, &frev, &crev, &data_offset)) {567umc_info = (union umc_info *)(mode_info->atom_context->bios + data_offset);568if (frev == 3) {569switch (crev) {570case 1:571umc_config = le32_to_cpu(umc_info->v31.umc_config);572mem_ecc_enabled =573(umc_config & UMC_CONFIG__DEFAULT_MEM_ECC_ENABLE) ? true : false;574break;575case 2:576umc_config = le32_to_cpu(umc_info->v32.umc_config);577mem_ecc_enabled =578(umc_config & UMC_CONFIG__DEFAULT_MEM_ECC_ENABLE) ? true : false;579break;580case 3:581umc_config = le32_to_cpu(umc_info->v33.umc_config);582umc_config1 = le32_to_cpu(umc_info->v33.umc_config1);583mem_ecc_enabled =584((umc_config & UMC_CONFIG__DEFAULT_MEM_ECC_ENABLE) ||585(umc_config1 & UMC_CONFIG1__ENABLE_ECC_CAPABLE)) ? true : false;586adev->ras_default_ecc_enabled =587(umc_config & UMC_CONFIG__DEFAULT_MEM_ECC_ENABLE) ? true : false;588break;589default:590/* unsupported crev */591return false;592}593} else if (frev == 4) {594switch (crev) {595case 0:596umc_config = le32_to_cpu(umc_info->v40.umc_config);597umc_config1 = le32_to_cpu(umc_info->v40.umc_config1);598mem_ecc_enabled =599(umc_config1 & UMC_CONFIG1__ENABLE_ECC_CAPABLE) ? true : false;600adev->ras_default_ecc_enabled =601(umc_config & UMC_CONFIG__DEFAULT_MEM_ECC_ENABLE) ? true : false;602break;603default:604/* unsupported crev */605return false;606}607} else {608/* unsupported frev */609return false;610}611}612613return mem_ecc_enabled;614}615616/*617* Helper function to query sram ecc capablity618*619* @adev: amdgpu_device pointer620*621* Return true if vbios supports sram ecc or false if not622*/623bool amdgpu_atomfirmware_sram_ecc_supported(struct amdgpu_device *adev)624{625u32 fw_cap;626627fw_cap = adev->mode_info.firmware_flags;628629return (fw_cap & ATOM_FIRMWARE_CAP_SRAM_ECC) ? true : false;630}631632/*633* Helper function to query dynamic boot config capability634*635* @adev: amdgpu_device pointer636*637* Return true if vbios supports dynamic boot config or false if not638*/639bool amdgpu_atomfirmware_dynamic_boot_config_supported(struct amdgpu_device *adev)640{641u32 fw_cap;642643fw_cap = adev->mode_info.firmware_flags;644645return (fw_cap & ATOM_FIRMWARE_CAP_DYNAMIC_BOOT_CFG_ENABLE) ? true : false;646}647648/**649* amdgpu_atomfirmware_ras_rom_addr -- Get the RAS EEPROM addr from VBIOS650* @adev: amdgpu_device pointer651* @i2c_address: pointer to u8; if not NULL, will contain652* the RAS EEPROM address if the function returns true653*654* Return true if VBIOS supports RAS EEPROM address reporting,655* else return false. If true and @i2c_address is not NULL,656* will contain the RAS ROM address.657*/658bool amdgpu_atomfirmware_ras_rom_addr(struct amdgpu_device *adev,659u8 *i2c_address)660{661struct amdgpu_mode_info *mode_info = &adev->mode_info;662int index;663u16 data_offset, size;664union firmware_info *firmware_info;665u8 frev, crev;666667index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,668firmwareinfo);669670if (amdgpu_atom_parse_data_header(adev->mode_info.atom_context,671index, &size, &frev, &crev,672&data_offset)) {673/* support firmware_info 3.4 + */674if ((frev == 3 && crev >= 4) || (frev > 3)) {675firmware_info = (union firmware_info *)676(mode_info->atom_context->bios + data_offset);677/* The ras_rom_i2c_slave_addr should ideally678* be a 19-bit EEPROM address, which would be679* used as is by the driver; see top of680* amdgpu_eeprom.c.681*682* When this is the case, 0 is of course a683* valid RAS EEPROM address, in which case,684* we'll drop the first "if (firm...)" and only685* leave the check for the pointer.686*687* The reason this works right now is because688* ras_rom_i2c_slave_addr contains the EEPROM689* device type qualifier 1010b in the top 4690* bits.691*/692if (firmware_info->v34.ras_rom_i2c_slave_addr) {693if (i2c_address)694*i2c_address = firmware_info->v34.ras_rom_i2c_slave_addr;695return true;696}697}698}699700return false;701}702703704union smu_info {705struct atom_smu_info_v3_1 v31;706struct atom_smu_info_v4_0 v40;707};708709union gfx_info {710struct atom_gfx_info_v2_2 v22;711struct atom_gfx_info_v2_4 v24;712struct atom_gfx_info_v2_7 v27;713struct atom_gfx_info_v3_0 v30;714};715716int amdgpu_atomfirmware_get_clock_info(struct amdgpu_device *adev)717{718struct amdgpu_mode_info *mode_info = &adev->mode_info;719struct amdgpu_pll *spll = &adev->clock.spll;720struct amdgpu_pll *mpll = &adev->clock.mpll;721uint8_t frev, crev;722uint16_t data_offset;723int ret = -EINVAL, index;724725index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,726firmwareinfo);727if (amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL,728&frev, &crev, &data_offset)) {729union firmware_info *firmware_info =730(union firmware_info *)(mode_info->atom_context->bios +731data_offset);732733adev->clock.default_sclk =734le32_to_cpu(firmware_info->v31.bootup_sclk_in10khz);735adev->clock.default_mclk =736le32_to_cpu(firmware_info->v31.bootup_mclk_in10khz);737738adev->pm.current_sclk = adev->clock.default_sclk;739adev->pm.current_mclk = adev->clock.default_mclk;740741ret = 0;742}743744index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,745smu_info);746if (amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL,747&frev, &crev, &data_offset)) {748union smu_info *smu_info =749(union smu_info *)(mode_info->atom_context->bios +750data_offset);751752/* system clock */753if (frev == 3)754spll->reference_freq = le32_to_cpu(smu_info->v31.core_refclk_10khz);755else if (frev == 4)756spll->reference_freq = le32_to_cpu(smu_info->v40.core_refclk_10khz);757758spll->reference_div = 0;759spll->min_post_div = 1;760spll->max_post_div = 1;761spll->min_ref_div = 2;762spll->max_ref_div = 0xff;763spll->min_feedback_div = 4;764spll->max_feedback_div = 0xff;765spll->best_vco = 0;766767ret = 0;768}769770index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,771umc_info);772if (amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL,773&frev, &crev, &data_offset)) {774union umc_info *umc_info =775(union umc_info *)(mode_info->atom_context->bios +776data_offset);777778/* memory clock */779mpll->reference_freq = le32_to_cpu(umc_info->v31.mem_refclk_10khz);780781mpll->reference_div = 0;782mpll->min_post_div = 1;783mpll->max_post_div = 1;784mpll->min_ref_div = 2;785mpll->max_ref_div = 0xff;786mpll->min_feedback_div = 4;787mpll->max_feedback_div = 0xff;788mpll->best_vco = 0;789790ret = 0;791}792793/* if asic is Navi+, the rlc reference clock is used for system clock794* from vbios gfx_info table */795if (adev->asic_type >= CHIP_NAVI10) {796index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,797gfx_info);798if (amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL,799&frev, &crev, &data_offset)) {800union gfx_info *gfx_info = (union gfx_info *)801(mode_info->atom_context->bios + data_offset);802if ((frev == 3) ||803(frev == 2 && crev == 6)) {804spll->reference_freq = le32_to_cpu(gfx_info->v30.golden_tsc_count_lower_refclk);805ret = 0;806} else if ((frev == 2) &&807(crev >= 2) &&808(crev != 6)) {809spll->reference_freq = le32_to_cpu(gfx_info->v22.rlc_gpu_timer_refclk);810ret = 0;811} else {812BUG();813}814}815}816817return ret;818}819820int amdgpu_atomfirmware_get_gfx_info(struct amdgpu_device *adev)821{822struct amdgpu_mode_info *mode_info = &adev->mode_info;823int index;824uint8_t frev, crev;825uint16_t data_offset;826827index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,828gfx_info);829if (amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL,830&frev, &crev, &data_offset)) {831union gfx_info *gfx_info = (union gfx_info *)832(mode_info->atom_context->bios + data_offset);833if (frev == 2) {834switch (crev) {835case 4:836adev->gfx.config.max_shader_engines = gfx_info->v24.max_shader_engines;837adev->gfx.config.max_cu_per_sh = gfx_info->v24.max_cu_per_sh;838adev->gfx.config.max_sh_per_se = gfx_info->v24.max_sh_per_se;839adev->gfx.config.max_backends_per_se = gfx_info->v24.max_backends_per_se;840adev->gfx.config.max_texture_channel_caches = gfx_info->v24.max_texture_channel_caches;841adev->gfx.config.max_gprs = le16_to_cpu(gfx_info->v24.gc_num_gprs);842adev->gfx.config.max_gs_threads = gfx_info->v24.gc_num_max_gs_thds;843adev->gfx.config.gs_vgt_table_depth = gfx_info->v24.gc_gs_table_depth;844adev->gfx.config.gs_prim_buffer_depth =845le16_to_cpu(gfx_info->v24.gc_gsprim_buff_depth);846adev->gfx.config.double_offchip_lds_buf =847gfx_info->v24.gc_double_offchip_lds_buffer;848adev->gfx.cu_info.wave_front_size = le16_to_cpu(gfx_info->v24.gc_wave_size);849adev->gfx.cu_info.max_waves_per_simd = le16_to_cpu(gfx_info->v24.gc_max_waves_per_simd);850adev->gfx.cu_info.max_scratch_slots_per_cu = gfx_info->v24.gc_max_scratch_slots_per_cu;851adev->gfx.cu_info.lds_size = le16_to_cpu(gfx_info->v24.gc_lds_size);852return 0;853case 7:854adev->gfx.config.max_shader_engines = gfx_info->v27.max_shader_engines;855adev->gfx.config.max_cu_per_sh = gfx_info->v27.max_cu_per_sh;856adev->gfx.config.max_sh_per_se = gfx_info->v27.max_sh_per_se;857adev->gfx.config.max_backends_per_se = gfx_info->v27.max_backends_per_se;858adev->gfx.config.max_texture_channel_caches = gfx_info->v27.max_texture_channel_caches;859adev->gfx.config.max_gprs = le16_to_cpu(gfx_info->v27.gc_num_gprs);860adev->gfx.config.max_gs_threads = gfx_info->v27.gc_num_max_gs_thds;861adev->gfx.config.gs_vgt_table_depth = gfx_info->v27.gc_gs_table_depth;862adev->gfx.config.gs_prim_buffer_depth = le16_to_cpu(gfx_info->v27.gc_gsprim_buff_depth);863adev->gfx.config.double_offchip_lds_buf = gfx_info->v27.gc_double_offchip_lds_buffer;864adev->gfx.cu_info.wave_front_size = le16_to_cpu(gfx_info->v27.gc_wave_size);865adev->gfx.cu_info.max_waves_per_simd = le16_to_cpu(gfx_info->v27.gc_max_waves_per_simd);866adev->gfx.cu_info.max_scratch_slots_per_cu = gfx_info->v27.gc_max_scratch_slots_per_cu;867adev->gfx.cu_info.lds_size = le16_to_cpu(gfx_info->v27.gc_lds_size);868return 0;869default:870return -EINVAL;871}872} else if (frev == 3) {873switch (crev) {874case 0:875adev->gfx.config.max_shader_engines = gfx_info->v30.max_shader_engines;876adev->gfx.config.max_cu_per_sh = gfx_info->v30.max_cu_per_sh;877adev->gfx.config.max_sh_per_se = gfx_info->v30.max_sh_per_se;878adev->gfx.config.max_backends_per_se = gfx_info->v30.max_backends_per_se;879adev->gfx.config.max_texture_channel_caches = gfx_info->v30.max_texture_channel_caches;880return 0;881default:882return -EINVAL;883}884} else {885return -EINVAL;886}887888}889return -EINVAL;890}891892/*893* Helper function to query two stage mem training capability894*895* @adev: amdgpu_device pointer896*897* Return true if two stage mem training is supported or false if not898*/899bool amdgpu_atomfirmware_mem_training_supported(struct amdgpu_device *adev)900{901u32 fw_cap;902903fw_cap = adev->mode_info.firmware_flags;904905return (fw_cap & ATOM_FIRMWARE_CAP_ENABLE_2STAGE_BIST_TRAINING) ? true : false;906}907908int amdgpu_atomfirmware_get_fw_reserved_fb_size(struct amdgpu_device *adev)909{910struct atom_context *ctx = adev->mode_info.atom_context;911union firmware_info *firmware_info;912int index;913u16 data_offset, size;914u8 frev, crev;915int fw_reserved_fb_size;916917index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,918firmwareinfo);919920if (!amdgpu_atom_parse_data_header(ctx, index, &size,921&frev, &crev, &data_offset))922/* fail to parse data_header */923return 0;924925firmware_info = (union firmware_info *)(ctx->bios + data_offset);926927if (frev != 3)928return -EINVAL;929930switch (crev) {931case 4:932fw_reserved_fb_size =933(firmware_info->v34.fw_reserved_size_in_kb << 10);934break;935case 5:936fw_reserved_fb_size =937(firmware_info->v35.fw_reserved_size_in_kb << 10);938break;939default:940fw_reserved_fb_size = 0;941break;942}943944return fw_reserved_fb_size;945}946947/*948* Helper function to execute asic_init table949*950* @adev: amdgpu_device pointer951* @fb_reset: flag to indicate whether fb is reset or not952*953* Return 0 if succeed, otherwise failed954*/955int amdgpu_atomfirmware_asic_init(struct amdgpu_device *adev, bool fb_reset)956{957struct amdgpu_mode_info *mode_info = &adev->mode_info;958struct atom_context *ctx;959uint8_t frev, crev;960uint16_t data_offset;961uint32_t bootup_sclk_in10khz, bootup_mclk_in10khz;962struct asic_init_ps_allocation_v2_1 asic_init_ps_v2_1;963int index;964965if (!mode_info)966return -EINVAL;967968ctx = mode_info->atom_context;969if (!ctx)970return -EINVAL;971972/* query bootup sclk/mclk from firmware_info table */973index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,974firmwareinfo);975if (amdgpu_atom_parse_data_header(ctx, index, NULL,976&frev, &crev, &data_offset)) {977union firmware_info *firmware_info =978(union firmware_info *)(ctx->bios +979data_offset);980981bootup_sclk_in10khz =982le32_to_cpu(firmware_info->v31.bootup_sclk_in10khz);983bootup_mclk_in10khz =984le32_to_cpu(firmware_info->v31.bootup_mclk_in10khz);985} else {986return -EINVAL;987}988989index = get_index_into_master_table(atom_master_list_of_command_functions_v2_1,990asic_init);991if (amdgpu_atom_parse_cmd_header(mode_info->atom_context, index, &frev, &crev)) {992if (frev == 2 && crev >= 1) {993memset(&asic_init_ps_v2_1, 0, sizeof(asic_init_ps_v2_1));994asic_init_ps_v2_1.param.engineparam.sclkfreqin10khz = bootup_sclk_in10khz;995asic_init_ps_v2_1.param.memparam.mclkfreqin10khz = bootup_mclk_in10khz;996asic_init_ps_v2_1.param.engineparam.engineflag = b3NORMAL_ENGINE_INIT;997if (!fb_reset)998asic_init_ps_v2_1.param.memparam.memflag = b3DRAM_SELF_REFRESH_EXIT;999else1000asic_init_ps_v2_1.param.memparam.memflag = 0;1001} else {1002return -EINVAL;1003}1004} else {1005return -EINVAL;1006}10071008return amdgpu_atom_execute_table(ctx, ATOM_CMD_INIT, (uint32_t *)&asic_init_ps_v2_1,1009sizeof(asic_init_ps_v2_1));1010}101110121013