Path: blob/master/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppatomctrl.c
26552 views
/*1* Copyright 2015 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*/22#include "pp_debug.h"23#include <linux/module.h>24#include <linux/slab.h>25#include <linux/delay.h>26#include "atom.h"27#include "ppatomctrl.h"28#include "atombios.h"29#include "cgs_common.h"3031#define MEM_ID_MASK 0xff00000032#define MEM_ID_SHIFT 2433#define CLOCK_RANGE_MASK 0x00ffffff34#define CLOCK_RANGE_SHIFT 035#define LOW_NIBBLE_MASK 0xf36#define DATA_EQU_PREV 037#define DATA_FROM_TABLE 43839union voltage_object_info {40struct _ATOM_VOLTAGE_OBJECT_INFO v1;41struct _ATOM_VOLTAGE_OBJECT_INFO_V2 v2;42struct _ATOM_VOLTAGE_OBJECT_INFO_V3_1 v3;43};4445static int atomctrl_retrieve_ac_timing(46uint8_t index,47ATOM_INIT_REG_BLOCK *reg_block,48pp_atomctrl_mc_reg_table *table)49{50uint32_t i, j;51uint8_t tmem_id;52ATOM_MEMORY_SETTING_DATA_BLOCK *reg_data = (ATOM_MEMORY_SETTING_DATA_BLOCK *)53((uint8_t *)reg_block + (2 * sizeof(uint16_t)) + le16_to_cpu(reg_block->usRegIndexTblSize));5455uint8_t num_ranges = 0;5657while (*(uint32_t *)reg_data != END_OF_REG_DATA_BLOCK &&58num_ranges < VBIOS_MAX_AC_TIMING_ENTRIES) {59tmem_id = (uint8_t)((*(uint32_t *)reg_data & MEM_ID_MASK) >> MEM_ID_SHIFT);6061if (index == tmem_id) {62table->mc_reg_table_entry[num_ranges].mclk_max =63(uint32_t)((*(uint32_t *)reg_data & CLOCK_RANGE_MASK) >>64CLOCK_RANGE_SHIFT);6566for (i = 0, j = 1; i < table->last; i++) {67if ((table->mc_reg_address[i].uc_pre_reg_data &68LOW_NIBBLE_MASK) == DATA_FROM_TABLE) {69table->mc_reg_table_entry[num_ranges].mc_data[i] =70(uint32_t)*((uint32_t *)reg_data + j);71j++;72} else if ((table->mc_reg_address[i].uc_pre_reg_data &73LOW_NIBBLE_MASK) == DATA_EQU_PREV) {74if (i)75table->mc_reg_table_entry[num_ranges].mc_data[i] =76table->mc_reg_table_entry[num_ranges].mc_data[i-1];77}78}79num_ranges++;80}8182reg_data = (ATOM_MEMORY_SETTING_DATA_BLOCK *)83((uint8_t *)reg_data + le16_to_cpu(reg_block->usRegDataBlkSize)) ;84}8586PP_ASSERT_WITH_CODE((*(uint32_t *)reg_data == END_OF_REG_DATA_BLOCK),87"Invalid VramInfo table.", return -1);88table->num_entries = num_ranges;8990return 0;91}9293/**94* atomctrl_set_mc_reg_address_table - Get memory clock AC timing registers index from VBIOS table95* VBIOS set end of memory clock AC timing registers by ucPreRegDataLength bit6 = 196* @reg_block: the address ATOM_INIT_REG_BLOCK97* @table: the address of MCRegTable98* Return: 099*/100static int atomctrl_set_mc_reg_address_table(101ATOM_INIT_REG_BLOCK *reg_block,102pp_atomctrl_mc_reg_table *table)103{104uint8_t i = 0;105uint8_t num_entries = (uint8_t)((le16_to_cpu(reg_block->usRegIndexTblSize))106/ sizeof(ATOM_INIT_REG_INDEX_FORMAT));107ATOM_INIT_REG_INDEX_FORMAT *format = ®_block->asRegIndexBuf[0];108109num_entries--; /* subtract 1 data end mark entry */110111PP_ASSERT_WITH_CODE((num_entries <= VBIOS_MC_REGISTER_ARRAY_SIZE),112"Invalid VramInfo table.", return -1);113114/* ucPreRegDataLength bit6 = 1 is the end of memory clock AC timing registers */115while ((!(format->ucPreRegDataLength & ACCESS_PLACEHOLDER)) &&116(i < num_entries)) {117table->mc_reg_address[i].s1 =118(uint16_t)(le16_to_cpu(format->usRegIndex));119table->mc_reg_address[i].uc_pre_reg_data =120format->ucPreRegDataLength;121122i++;123format = (ATOM_INIT_REG_INDEX_FORMAT *)124((uint8_t *)format + sizeof(ATOM_INIT_REG_INDEX_FORMAT));125}126127table->last = i;128return 0;129}130131int atomctrl_initialize_mc_reg_table(132struct pp_hwmgr *hwmgr,133uint8_t module_index,134pp_atomctrl_mc_reg_table *table)135{136ATOM_VRAM_INFO_HEADER_V2_1 *vram_info;137ATOM_INIT_REG_BLOCK *reg_block;138int result = 0;139u8 frev, crev;140u16 size;141142vram_info = (ATOM_VRAM_INFO_HEADER_V2_1 *)143smu_atom_get_data_table(hwmgr->adev,144GetIndexIntoMasterTable(DATA, VRAM_Info), &size, &frev, &crev);145if (!vram_info) {146pr_err("Could not retrieve the VramInfo table!");147return -EINVAL;148}149150if (module_index >= vram_info->ucNumOfVRAMModule) {151pr_err("Invalid VramInfo table.");152result = -1;153} else if (vram_info->sHeader.ucTableFormatRevision < 2) {154pr_err("Invalid VramInfo table.");155result = -1;156}157158if (0 == result) {159reg_block = (ATOM_INIT_REG_BLOCK *)160((uint8_t *)vram_info + le16_to_cpu(vram_info->usMemClkPatchTblOffset));161result = atomctrl_set_mc_reg_address_table(reg_block, table);162}163164if (0 == result) {165result = atomctrl_retrieve_ac_timing(module_index,166reg_block, table);167}168169return result;170}171172int atomctrl_initialize_mc_reg_table_v2_2(173struct pp_hwmgr *hwmgr,174uint8_t module_index,175pp_atomctrl_mc_reg_table *table)176{177ATOM_VRAM_INFO_HEADER_V2_2 *vram_info;178ATOM_INIT_REG_BLOCK *reg_block;179int result = 0;180u8 frev, crev;181u16 size;182183vram_info = (ATOM_VRAM_INFO_HEADER_V2_2 *)184smu_atom_get_data_table(hwmgr->adev,185GetIndexIntoMasterTable(DATA, VRAM_Info), &size, &frev, &crev);186if (!vram_info) {187pr_err("Could not retrieve the VramInfo table!");188return -EINVAL;189}190191if (module_index >= vram_info->ucNumOfVRAMModule) {192pr_err("Invalid VramInfo table.");193result = -1;194} else if (vram_info->sHeader.ucTableFormatRevision < 2) {195pr_err("Invalid VramInfo table.");196result = -1;197}198199if (0 == result) {200reg_block = (ATOM_INIT_REG_BLOCK *)201((uint8_t *)vram_info + le16_to_cpu(vram_info->usMemClkPatchTblOffset));202result = atomctrl_set_mc_reg_address_table(reg_block, table);203}204205if (0 == result) {206result = atomctrl_retrieve_ac_timing(module_index,207reg_block, table);208}209210return result;211}212213/*214* Set DRAM timings based on engine clock and memory clock.215*/216int atomctrl_set_engine_dram_timings_rv770(217struct pp_hwmgr *hwmgr,218uint32_t engine_clock,219uint32_t memory_clock)220{221struct amdgpu_device *adev = hwmgr->adev;222223SET_ENGINE_CLOCK_PS_ALLOCATION engine_clock_parameters;224225/* They are both in 10KHz Units. */226engine_clock_parameters.ulTargetEngineClock =227cpu_to_le32((engine_clock & SET_CLOCK_FREQ_MASK) |228((COMPUTE_ENGINE_PLL_PARAM << 24)));229230/* in 10 khz units.*/231engine_clock_parameters.sReserved.ulClock =232cpu_to_le32(memory_clock & SET_CLOCK_FREQ_MASK);233234return amdgpu_atom_execute_table(adev->mode_info.atom_context,235GetIndexIntoMasterTable(COMMAND, DynamicMemorySettings),236(uint32_t *)&engine_clock_parameters, sizeof(engine_clock_parameters));237}238239/*240* Private Function to get the PowerPlay Table Address.241* WARNING: The tabled returned by this function is in242* dynamically allocated memory.243* The caller has to release if by calling kfree.244*/245static ATOM_VOLTAGE_OBJECT_INFO *get_voltage_info_table(void *device)246{247int index = GetIndexIntoMasterTable(DATA, VoltageObjectInfo);248u8 frev, crev;249u16 size;250union voltage_object_info *voltage_info;251252voltage_info = (union voltage_object_info *)253smu_atom_get_data_table(device, index,254&size, &frev, &crev);255256if (voltage_info != NULL)257return (ATOM_VOLTAGE_OBJECT_INFO *) &(voltage_info->v3);258else259return NULL;260}261262static const ATOM_VOLTAGE_OBJECT_V3 *atomctrl_lookup_voltage_type_v3(263const ATOM_VOLTAGE_OBJECT_INFO_V3_1 * voltage_object_info_table,264uint8_t voltage_type, uint8_t voltage_mode)265{266unsigned int size = le16_to_cpu(voltage_object_info_table->sHeader.usStructureSize);267unsigned int offset = offsetof(ATOM_VOLTAGE_OBJECT_INFO_V3_1, asVoltageObj[0]);268uint8_t *start = (uint8_t *)voltage_object_info_table;269270while (offset < size) {271const ATOM_VOLTAGE_OBJECT_V3 *voltage_object =272(const ATOM_VOLTAGE_OBJECT_V3 *)(start + offset);273274if (voltage_type == voltage_object->asGpioVoltageObj.sHeader.ucVoltageType &&275voltage_mode == voltage_object->asGpioVoltageObj.sHeader.ucVoltageMode)276return voltage_object;277278offset += le16_to_cpu(voltage_object->asGpioVoltageObj.sHeader.usSize);279}280281return NULL;282}283284/**285* atomctrl_get_memory_pll_dividers_si286*287* @hwmgr: input parameter: pointer to HwMgr288* @clock_value: input parameter: memory clock289* @mpll_param: output parameter: memory clock parameters290* @strobe_mode: input parameter: 1 for strobe mode, 0 for performance mode291*/292int atomctrl_get_memory_pll_dividers_si(293struct pp_hwmgr *hwmgr,294uint32_t clock_value,295pp_atomctrl_memory_clock_param *mpll_param,296bool strobe_mode)297{298struct amdgpu_device *adev = hwmgr->adev;299COMPUTE_MEMORY_CLOCK_PARAM_PARAMETERS_V2_1 mpll_parameters;300int result;301302mpll_parameters.ulClock = cpu_to_le32(clock_value);303mpll_parameters.ucInputFlag = (uint8_t)((strobe_mode) ? 1 : 0);304305result = amdgpu_atom_execute_table(adev->mode_info.atom_context,306GetIndexIntoMasterTable(COMMAND, ComputeMemoryClockParam),307(uint32_t *)&mpll_parameters, sizeof(mpll_parameters));308309if (0 == result) {310mpll_param->mpll_fb_divider.clk_frac =311le16_to_cpu(mpll_parameters.ulFbDiv.usFbDivFrac);312mpll_param->mpll_fb_divider.cl_kf =313le16_to_cpu(mpll_parameters.ulFbDiv.usFbDiv);314mpll_param->mpll_post_divider =315(uint32_t)mpll_parameters.ucPostDiv;316mpll_param->vco_mode =317(uint32_t)(mpll_parameters.ucPllCntlFlag &318MPLL_CNTL_FLAG_VCO_MODE_MASK);319mpll_param->yclk_sel =320(uint32_t)((mpll_parameters.ucPllCntlFlag &321MPLL_CNTL_FLAG_BYPASS_DQ_PLL) ? 1 : 0);322mpll_param->qdr =323(uint32_t)((mpll_parameters.ucPllCntlFlag &324MPLL_CNTL_FLAG_QDR_ENABLE) ? 1 : 0);325mpll_param->half_rate =326(uint32_t)((mpll_parameters.ucPllCntlFlag &327MPLL_CNTL_FLAG_AD_HALF_RATE) ? 1 : 0);328mpll_param->dll_speed =329(uint32_t)(mpll_parameters.ucDllSpeed);330mpll_param->bw_ctrl =331(uint32_t)(mpll_parameters.ucBWCntl);332}333334return result;335}336337/**338* atomctrl_get_memory_pll_dividers_vi339*340* @hwmgr: input parameter: pointer to HwMgr341* @clock_value: input parameter: memory clock342* @mpll_param: output parameter: memory clock parameters343*/344int atomctrl_get_memory_pll_dividers_vi(struct pp_hwmgr *hwmgr,345uint32_t clock_value, pp_atomctrl_memory_clock_param *mpll_param)346{347struct amdgpu_device *adev = hwmgr->adev;348COMPUTE_MEMORY_CLOCK_PARAM_PARAMETERS_V2_2 mpll_parameters;349int result;350351mpll_parameters.ulClock.ulClock = cpu_to_le32(clock_value);352353result = amdgpu_atom_execute_table(adev->mode_info.atom_context,354GetIndexIntoMasterTable(COMMAND, ComputeMemoryClockParam),355(uint32_t *)&mpll_parameters, sizeof(mpll_parameters));356357if (!result)358mpll_param->mpll_post_divider =359(uint32_t)mpll_parameters.ulClock.ucPostDiv;360361return result;362}363364int atomctrl_get_memory_pll_dividers_ai(struct pp_hwmgr *hwmgr,365uint32_t clock_value,366pp_atomctrl_memory_clock_param_ai *mpll_param)367{368struct amdgpu_device *adev = hwmgr->adev;369COMPUTE_MEMORY_CLOCK_PARAM_PARAMETERS_V2_3 mpll_parameters = {{0}, 0, 0};370int result;371372mpll_parameters.ulClock.ulClock = cpu_to_le32(clock_value);373374result = amdgpu_atom_execute_table(adev->mode_info.atom_context,375GetIndexIntoMasterTable(COMMAND, ComputeMemoryClockParam),376(uint32_t *)&mpll_parameters, sizeof(mpll_parameters));377378/* VEGAM's mpll takes sometime to finish computing */379udelay(10);380381if (!result) {382mpll_param->ulMclk_fcw_int =383le16_to_cpu(mpll_parameters.usMclk_fcw_int);384mpll_param->ulMclk_fcw_frac =385le16_to_cpu(mpll_parameters.usMclk_fcw_frac);386mpll_param->ulClock =387le32_to_cpu(mpll_parameters.ulClock.ulClock);388mpll_param->ulPostDiv = mpll_parameters.ulClock.ucPostDiv;389}390391return result;392}393394int atomctrl_get_engine_pll_dividers_kong(struct pp_hwmgr *hwmgr,395uint32_t clock_value,396pp_atomctrl_clock_dividers_kong *dividers)397{398struct amdgpu_device *adev = hwmgr->adev;399COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V4 pll_parameters;400int result;401402pll_parameters.ulClock = cpu_to_le32(clock_value);403404result = amdgpu_atom_execute_table(adev->mode_info.atom_context,405GetIndexIntoMasterTable(COMMAND, ComputeMemoryEnginePLL),406(uint32_t *)&pll_parameters, sizeof(pll_parameters));407408if (0 == result) {409dividers->pll_post_divider = pll_parameters.ucPostDiv;410dividers->real_clock = le32_to_cpu(pll_parameters.ulClock);411}412413return result;414}415416int atomctrl_get_engine_pll_dividers_vi(417struct pp_hwmgr *hwmgr,418uint32_t clock_value,419pp_atomctrl_clock_dividers_vi *dividers)420{421struct amdgpu_device *adev = hwmgr->adev;422COMPUTE_GPU_CLOCK_OUTPUT_PARAMETERS_V1_6 pll_patameters;423int result;424425pll_patameters.ulClock.ulClock = cpu_to_le32(clock_value);426pll_patameters.ulClock.ucPostDiv = COMPUTE_GPUCLK_INPUT_FLAG_SCLK;427428result = amdgpu_atom_execute_table(adev->mode_info.atom_context,429GetIndexIntoMasterTable(COMMAND, ComputeMemoryEnginePLL),430(uint32_t *)&pll_patameters, sizeof(pll_patameters));431432if (0 == result) {433dividers->pll_post_divider =434pll_patameters.ulClock.ucPostDiv;435dividers->real_clock =436le32_to_cpu(pll_patameters.ulClock.ulClock);437438dividers->ul_fb_div.ul_fb_div_frac =439le16_to_cpu(pll_patameters.ulFbDiv.usFbDivFrac);440dividers->ul_fb_div.ul_fb_div =441le16_to_cpu(pll_patameters.ulFbDiv.usFbDiv);442443dividers->uc_pll_ref_div =444pll_patameters.ucPllRefDiv;445dividers->uc_pll_post_div =446pll_patameters.ucPllPostDiv;447dividers->uc_pll_cntl_flag =448pll_patameters.ucPllCntlFlag;449}450451return result;452}453454int atomctrl_get_engine_pll_dividers_ai(struct pp_hwmgr *hwmgr,455uint32_t clock_value,456pp_atomctrl_clock_dividers_ai *dividers)457{458struct amdgpu_device *adev = hwmgr->adev;459COMPUTE_GPU_CLOCK_OUTPUT_PARAMETERS_V1_7 pll_patameters;460int result;461462pll_patameters.ulClock.ulClock = cpu_to_le32(clock_value);463pll_patameters.ulClock.ucPostDiv = COMPUTE_GPUCLK_INPUT_FLAG_SCLK;464465result = amdgpu_atom_execute_table(adev->mode_info.atom_context,466GetIndexIntoMasterTable(COMMAND, ComputeMemoryEnginePLL),467(uint32_t *)&pll_patameters, sizeof(pll_patameters));468469if (0 == result) {470dividers->usSclk_fcw_frac = le16_to_cpu(pll_patameters.usSclk_fcw_frac);471dividers->usSclk_fcw_int = le16_to_cpu(pll_patameters.usSclk_fcw_int);472dividers->ucSclkPostDiv = pll_patameters.ucSclkPostDiv;473dividers->ucSclkVcoMode = pll_patameters.ucSclkVcoMode;474dividers->ucSclkPllRange = pll_patameters.ucSclkPllRange;475dividers->ucSscEnable = pll_patameters.ucSscEnable;476dividers->usSsc_fcw1_frac = le16_to_cpu(pll_patameters.usSsc_fcw1_frac);477dividers->usSsc_fcw1_int = le16_to_cpu(pll_patameters.usSsc_fcw1_int);478dividers->usPcc_fcw_int = le16_to_cpu(pll_patameters.usPcc_fcw_int);479dividers->usSsc_fcw_slew_frac = le16_to_cpu(pll_patameters.usSsc_fcw_slew_frac);480dividers->usPcc_fcw_slew_frac = le16_to_cpu(pll_patameters.usPcc_fcw_slew_frac);481}482return result;483}484485int atomctrl_get_dfs_pll_dividers_vi(486struct pp_hwmgr *hwmgr,487uint32_t clock_value,488pp_atomctrl_clock_dividers_vi *dividers)489{490struct amdgpu_device *adev = hwmgr->adev;491COMPUTE_GPU_CLOCK_OUTPUT_PARAMETERS_V1_6 pll_patameters;492int result;493494pll_patameters.ulClock.ulClock = cpu_to_le32(clock_value);495pll_patameters.ulClock.ucPostDiv =496COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK;497498result = amdgpu_atom_execute_table(adev->mode_info.atom_context,499GetIndexIntoMasterTable(COMMAND, ComputeMemoryEnginePLL),500(uint32_t *)&pll_patameters, sizeof(pll_patameters));501502if (0 == result) {503dividers->pll_post_divider =504pll_patameters.ulClock.ucPostDiv;505dividers->real_clock =506le32_to_cpu(pll_patameters.ulClock.ulClock);507508dividers->ul_fb_div.ul_fb_div_frac =509le16_to_cpu(pll_patameters.ulFbDiv.usFbDivFrac);510dividers->ul_fb_div.ul_fb_div =511le16_to_cpu(pll_patameters.ulFbDiv.usFbDiv);512513dividers->uc_pll_ref_div =514pll_patameters.ucPllRefDiv;515dividers->uc_pll_post_div =516pll_patameters.ucPllPostDiv;517dividers->uc_pll_cntl_flag =518pll_patameters.ucPllCntlFlag;519}520521return result;522}523524/*525* Get the reference clock in 10KHz526*/527uint32_t atomctrl_get_reference_clock(struct pp_hwmgr *hwmgr)528{529ATOM_FIRMWARE_INFO *fw_info;530u8 frev, crev;531u16 size;532uint32_t clock;533534fw_info = (ATOM_FIRMWARE_INFO *)535smu_atom_get_data_table(hwmgr->adev,536GetIndexIntoMasterTable(DATA, FirmwareInfo),537&size, &frev, &crev);538539if (fw_info == NULL)540clock = 2700;541else542clock = (uint32_t)(le16_to_cpu(fw_info->usReferenceClock));543544return clock;545}546547/*548* Returns true if the given voltage type is controlled by GPIO pins.549* voltage_type is one of SET_VOLTAGE_TYPE_ASIC_VDDC,550* SET_VOLTAGE_TYPE_ASIC_MVDDC, SET_VOLTAGE_TYPE_ASIC_MVDDQ.551* voltage_mode is one of ATOM_SET_VOLTAGE, ATOM_SET_VOLTAGE_PHASE552*/553bool atomctrl_is_voltage_controlled_by_gpio_v3(554struct pp_hwmgr *hwmgr,555uint8_t voltage_type,556uint8_t voltage_mode)557{558ATOM_VOLTAGE_OBJECT_INFO_V3_1 *voltage_info =559(ATOM_VOLTAGE_OBJECT_INFO_V3_1 *)get_voltage_info_table(hwmgr->adev);560bool ret;561562PP_ASSERT_WITH_CODE((NULL != voltage_info),563"Could not find Voltage Table in BIOS.", return false;);564565ret = (NULL != atomctrl_lookup_voltage_type_v3566(voltage_info, voltage_type, voltage_mode)) ? true : false;567568return ret;569}570571int atomctrl_get_voltage_table_v3(572struct pp_hwmgr *hwmgr,573uint8_t voltage_type,574uint8_t voltage_mode,575pp_atomctrl_voltage_table *voltage_table)576{577ATOM_VOLTAGE_OBJECT_INFO_V3_1 *voltage_info =578(ATOM_VOLTAGE_OBJECT_INFO_V3_1 *)get_voltage_info_table(hwmgr->adev);579const ATOM_VOLTAGE_OBJECT_V3 *voltage_object;580unsigned int i;581582PP_ASSERT_WITH_CODE((NULL != voltage_info),583"Could not find Voltage Table in BIOS.", return -1;);584585voltage_object = atomctrl_lookup_voltage_type_v3586(voltage_info, voltage_type, voltage_mode);587588if (voltage_object == NULL)589return -1;590591PP_ASSERT_WITH_CODE(592(voltage_object->asGpioVoltageObj.ucGpioEntryNum <=593PP_ATOMCTRL_MAX_VOLTAGE_ENTRIES),594"Too many voltage entries!",595return -1;596);597598for (i = 0; i < voltage_object->asGpioVoltageObj.ucGpioEntryNum; i++) {599voltage_table->entries[i].value =600le16_to_cpu(voltage_object->asGpioVoltageObj.asVolGpioLut[i].usVoltageValue);601voltage_table->entries[i].smio_low =602le32_to_cpu(voltage_object->asGpioVoltageObj.asVolGpioLut[i].ulVoltageId);603}604605voltage_table->mask_low =606le32_to_cpu(voltage_object->asGpioVoltageObj.ulGpioMaskVal);607voltage_table->count =608voltage_object->asGpioVoltageObj.ucGpioEntryNum;609voltage_table->phase_delay =610voltage_object->asGpioVoltageObj.ucPhaseDelay;611612return 0;613}614615static bool atomctrl_lookup_gpio_pin(616ATOM_GPIO_PIN_LUT * gpio_lookup_table,617const uint32_t pinId,618pp_atomctrl_gpio_pin_assignment *gpio_pin_assignment)619{620unsigned int size = le16_to_cpu(gpio_lookup_table->sHeader.usStructureSize);621unsigned int offset = offsetof(ATOM_GPIO_PIN_LUT, asGPIO_Pin[0]);622uint8_t *start = (uint8_t *)gpio_lookup_table;623624while (offset < size) {625const ATOM_GPIO_PIN_ASSIGNMENT *pin_assignment =626(const ATOM_GPIO_PIN_ASSIGNMENT *)(start + offset);627628if (pinId == pin_assignment->ucGPIO_ID) {629gpio_pin_assignment->uc_gpio_pin_bit_shift =630pin_assignment->ucGpioPinBitShift;631gpio_pin_assignment->us_gpio_pin_aindex =632le16_to_cpu(pin_assignment->usGpioPin_AIndex);633return true;634}635636offset += offsetof(ATOM_GPIO_PIN_ASSIGNMENT, ucGPIO_ID) + 1;637}638639return false;640}641642/*643* Private Function to get the PowerPlay Table Address.644* WARNING: The tabled returned by this function is in645* dynamically allocated memory.646* The caller has to release if by calling kfree.647*/648static ATOM_GPIO_PIN_LUT *get_gpio_lookup_table(void *device)649{650u8 frev, crev;651u16 size;652void *table_address;653654table_address = (ATOM_GPIO_PIN_LUT *)655smu_atom_get_data_table(device,656GetIndexIntoMasterTable(DATA, GPIO_Pin_LUT),657&size, &frev, &crev);658659PP_ASSERT_WITH_CODE((NULL != table_address),660"Error retrieving BIOS Table Address!", return NULL;);661662return (ATOM_GPIO_PIN_LUT *)table_address;663}664665/*666* Returns 1 if the given pin id find in lookup table.667*/668bool atomctrl_get_pp_assign_pin(669struct pp_hwmgr *hwmgr,670const uint32_t pinId,671pp_atomctrl_gpio_pin_assignment *gpio_pin_assignment)672{673bool bRet = false;674ATOM_GPIO_PIN_LUT *gpio_lookup_table =675get_gpio_lookup_table(hwmgr->adev);676677PP_ASSERT_WITH_CODE((NULL != gpio_lookup_table),678"Could not find GPIO lookup Table in BIOS.", return false);679680bRet = atomctrl_lookup_gpio_pin(gpio_lookup_table, pinId,681gpio_pin_assignment);682683return bRet;684}685686/**687* atomctrl_get_voltage_evv_on_sclk: gets voltage via call to ATOM COMMAND table.688* @hwmgr: input: pointer to hwManager689* @voltage_type: input: type of EVV voltage VDDC or VDDGFX690* @sclk: input: in 10Khz unit. DPM state SCLK frequency691* which is define in PPTable SCLK/VDDC dependence692* table associated with this virtual_voltage_Id693* @virtual_voltage_Id: input: voltage id which match per voltage DPM state: 0xff01, 0xff02.. 0xff08694* @voltage: output: real voltage level in unit of mv695*/696int atomctrl_get_voltage_evv_on_sclk(697struct pp_hwmgr *hwmgr,698uint8_t voltage_type,699uint32_t sclk, uint16_t virtual_voltage_Id,700uint16_t *voltage)701{702struct amdgpu_device *adev = hwmgr->adev;703GET_VOLTAGE_INFO_INPUT_PARAMETER_V1_2 get_voltage_info_param_space;704int result;705706get_voltage_info_param_space.ucVoltageType =707voltage_type;708get_voltage_info_param_space.ucVoltageMode =709ATOM_GET_VOLTAGE_EVV_VOLTAGE;710get_voltage_info_param_space.usVoltageLevel =711cpu_to_le16(virtual_voltage_Id);712get_voltage_info_param_space.ulSCLKFreq =713cpu_to_le32(sclk);714715result = amdgpu_atom_execute_table(adev->mode_info.atom_context,716GetIndexIntoMasterTable(COMMAND, GetVoltageInfo),717(uint32_t *)&get_voltage_info_param_space, sizeof(get_voltage_info_param_space));718719*voltage = result ? 0 :720le16_to_cpu(((GET_EVV_VOLTAGE_INFO_OUTPUT_PARAMETER_V1_2 *)721(&get_voltage_info_param_space))->usVoltageLevel);722723return result;724}725726/**727* atomctrl_get_voltage_evv: gets voltage via call to ATOM COMMAND table.728* @hwmgr: input: pointer to hwManager729* @virtual_voltage_id: input: voltage id which match per voltage DPM state: 0xff01, 0xff02.. 0xff08730* @voltage: output: real voltage level in unit of mv731*/732int atomctrl_get_voltage_evv(struct pp_hwmgr *hwmgr,733uint16_t virtual_voltage_id,734uint16_t *voltage)735{736struct amdgpu_device *adev = hwmgr->adev;737GET_VOLTAGE_INFO_INPUT_PARAMETER_V1_2 get_voltage_info_param_space;738int result;739int entry_id;740741/* search for leakage voltage ID 0xff01 ~ 0xff08 and sckl */742for (entry_id = 0; entry_id < hwmgr->dyn_state.vddc_dependency_on_sclk->count; entry_id++) {743if (hwmgr->dyn_state.vddc_dependency_on_sclk->entries[entry_id].v == virtual_voltage_id) {744/* found */745break;746}747}748749if (entry_id >= hwmgr->dyn_state.vddc_dependency_on_sclk->count) {750pr_debug("Can't find requested voltage id in vddc_dependency_on_sclk table!\n");751return -EINVAL;752}753754get_voltage_info_param_space.ucVoltageType = VOLTAGE_TYPE_VDDC;755get_voltage_info_param_space.ucVoltageMode = ATOM_GET_VOLTAGE_EVV_VOLTAGE;756get_voltage_info_param_space.usVoltageLevel = virtual_voltage_id;757get_voltage_info_param_space.ulSCLKFreq =758cpu_to_le32(hwmgr->dyn_state.vddc_dependency_on_sclk->entries[entry_id].clk);759760result = amdgpu_atom_execute_table(adev->mode_info.atom_context,761GetIndexIntoMasterTable(COMMAND, GetVoltageInfo),762(uint32_t *)&get_voltage_info_param_space, sizeof(get_voltage_info_param_space));763764if (0 != result)765return result;766767*voltage = le16_to_cpu(((GET_EVV_VOLTAGE_INFO_OUTPUT_PARAMETER_V1_2 *)768(&get_voltage_info_param_space))->usVoltageLevel);769770return result;771}772773/*774* Get the mpll reference clock in 10KHz775*/776uint32_t atomctrl_get_mpll_reference_clock(struct pp_hwmgr *hwmgr)777{778ATOM_COMMON_TABLE_HEADER *fw_info;779uint32_t clock;780u8 frev, crev;781u16 size;782783fw_info = (ATOM_COMMON_TABLE_HEADER *)784smu_atom_get_data_table(hwmgr->adev,785GetIndexIntoMasterTable(DATA, FirmwareInfo),786&size, &frev, &crev);787788if (fw_info == NULL)789clock = 2700;790else {791if ((fw_info->ucTableFormatRevision == 2) &&792(le16_to_cpu(fw_info->usStructureSize) >= sizeof(ATOM_FIRMWARE_INFO_V2_1))) {793ATOM_FIRMWARE_INFO_V2_1 *fwInfo_2_1 =794(ATOM_FIRMWARE_INFO_V2_1 *)fw_info;795clock = (uint32_t)(le16_to_cpu(fwInfo_2_1->usMemoryReferenceClock));796} else {797ATOM_FIRMWARE_INFO *fwInfo_0_0 =798(ATOM_FIRMWARE_INFO *)fw_info;799clock = (uint32_t)(le16_to_cpu(fwInfo_0_0->usReferenceClock));800}801}802803return clock;804}805806/*807* Get the asic internal spread spectrum table808*/809static ATOM_ASIC_INTERNAL_SS_INFO *asic_internal_ss_get_ss_table(void *device)810{811ATOM_ASIC_INTERNAL_SS_INFO *table = NULL;812u8 frev, crev;813u16 size;814815table = (ATOM_ASIC_INTERNAL_SS_INFO *)816smu_atom_get_data_table(device,817GetIndexIntoMasterTable(DATA, ASIC_InternalSS_Info),818&size, &frev, &crev);819820return table;821}822823bool atomctrl_is_asic_internal_ss_supported(struct pp_hwmgr *hwmgr)824{825ATOM_ASIC_INTERNAL_SS_INFO *table =826asic_internal_ss_get_ss_table(hwmgr->adev);827828if (table)829return true;830else831return false;832}833834/*835* Get the asic internal spread spectrum assignment836*/837static int asic_internal_ss_get_ss_asignment(struct pp_hwmgr *hwmgr,838const uint8_t clockSource,839const uint32_t clockSpeed,840pp_atomctrl_internal_ss_info *ssEntry)841{842ATOM_ASIC_INTERNAL_SS_INFO *table;843ATOM_ASIC_SS_ASSIGNMENT *ssInfo;844int entry_found = 0;845846memset(ssEntry, 0x00, sizeof(pp_atomctrl_internal_ss_info));847848table = asic_internal_ss_get_ss_table(hwmgr->adev);849850if (NULL == table)851return -1;852853ssInfo = &table->asSpreadSpectrum[0];854855while (((uint8_t *)ssInfo - (uint8_t *)table) <856le16_to_cpu(table->sHeader.usStructureSize)) {857if ((clockSource == ssInfo->ucClockIndication) &&858((uint32_t)clockSpeed <= le32_to_cpu(ssInfo->ulTargetClockRange))) {859entry_found = 1;860break;861}862863ssInfo = (ATOM_ASIC_SS_ASSIGNMENT *)((uint8_t *)ssInfo +864sizeof(ATOM_ASIC_SS_ASSIGNMENT));865}866867if (entry_found) {868ssEntry->speed_spectrum_percentage =869le16_to_cpu(ssInfo->usSpreadSpectrumPercentage);870ssEntry->speed_spectrum_rate = le16_to_cpu(ssInfo->usSpreadRateInKhz);871872if (((GET_DATA_TABLE_MAJOR_REVISION(table) == 2) &&873(GET_DATA_TABLE_MINOR_REVISION(table) >= 2)) ||874(GET_DATA_TABLE_MAJOR_REVISION(table) == 3)) {875ssEntry->speed_spectrum_rate /= 100;876}877878switch (ssInfo->ucSpreadSpectrumMode) {879case 0:880ssEntry->speed_spectrum_mode =881pp_atomctrl_spread_spectrum_mode_down;882break;883case 1:884ssEntry->speed_spectrum_mode =885pp_atomctrl_spread_spectrum_mode_center;886break;887default:888ssEntry->speed_spectrum_mode =889pp_atomctrl_spread_spectrum_mode_down;890break;891}892}893894return entry_found ? 0 : 1;895}896897/*898* Get the memory clock spread spectrum info899*/900int atomctrl_get_memory_clock_spread_spectrum(901struct pp_hwmgr *hwmgr,902const uint32_t memory_clock,903pp_atomctrl_internal_ss_info *ssInfo)904{905return asic_internal_ss_get_ss_asignment(hwmgr,906ASIC_INTERNAL_MEMORY_SS, memory_clock, ssInfo);907}908909/*910* Get the engine clock spread spectrum info911*/912int atomctrl_get_engine_clock_spread_spectrum(913struct pp_hwmgr *hwmgr,914const uint32_t engine_clock,915pp_atomctrl_internal_ss_info *ssInfo)916{917return asic_internal_ss_get_ss_asignment(hwmgr,918ASIC_INTERNAL_ENGINE_SS, engine_clock, ssInfo);919}920921int atomctrl_read_efuse(struct pp_hwmgr *hwmgr, uint16_t start_index,922uint16_t end_index, uint32_t *efuse)923{924struct amdgpu_device *adev = hwmgr->adev;925uint32_t mask;926int result;927READ_EFUSE_VALUE_PARAMETER efuse_param;928929if ((end_index - start_index) == 31)930mask = 0xFFFFFFFF;931else932mask = (1 << ((end_index - start_index) + 1)) - 1;933934efuse_param.sEfuse.usEfuseIndex = cpu_to_le16((start_index / 32) * 4);935efuse_param.sEfuse.ucBitShift = (uint8_t)936(start_index - ((start_index / 32) * 32));937efuse_param.sEfuse.ucBitLength = (uint8_t)938((end_index - start_index) + 1);939940result = amdgpu_atom_execute_table(adev->mode_info.atom_context,941GetIndexIntoMasterTable(COMMAND, ReadEfuseValue),942(uint32_t *)&efuse_param, sizeof(efuse_param));943*efuse = result ? 0 : le32_to_cpu(efuse_param.ulEfuseValue) & mask;944945return result;946}947948int atomctrl_set_ac_timing_ai(struct pp_hwmgr *hwmgr, uint32_t memory_clock,949uint8_t level)950{951struct amdgpu_device *adev = hwmgr->adev;952DYNAMICE_MEMORY_SETTINGS_PARAMETER_V2_1 memory_clock_parameters;953int result;954955memory_clock_parameters.asDPMMCReg.ulClock.ulClockFreq =956memory_clock & SET_CLOCK_FREQ_MASK;957memory_clock_parameters.asDPMMCReg.ulClock.ulComputeClockFlag =958ADJUST_MC_SETTING_PARAM;959memory_clock_parameters.asDPMMCReg.ucMclkDPMState = level;960961result = amdgpu_atom_execute_table(adev->mode_info.atom_context,962GetIndexIntoMasterTable(COMMAND, DynamicMemorySettings),963(uint32_t *)&memory_clock_parameters, sizeof(memory_clock_parameters));964965return result;966}967968int atomctrl_get_voltage_evv_on_sclk_ai(struct pp_hwmgr *hwmgr, uint8_t voltage_type,969uint32_t sclk, uint16_t virtual_voltage_Id, uint32_t *voltage)970{971struct amdgpu_device *adev = hwmgr->adev;972int result;973GET_VOLTAGE_INFO_INPUT_PARAMETER_V1_3 get_voltage_info_param_space;974975get_voltage_info_param_space.ucVoltageType = voltage_type;976get_voltage_info_param_space.ucVoltageMode = ATOM_GET_VOLTAGE_EVV_VOLTAGE;977get_voltage_info_param_space.usVoltageLevel = cpu_to_le16(virtual_voltage_Id);978get_voltage_info_param_space.ulSCLKFreq = cpu_to_le32(sclk);979980result = amdgpu_atom_execute_table(adev->mode_info.atom_context,981GetIndexIntoMasterTable(COMMAND, GetVoltageInfo),982(uint32_t *)&get_voltage_info_param_space, sizeof(get_voltage_info_param_space));983984*voltage = result ? 0 :985le32_to_cpu(((GET_EVV_VOLTAGE_INFO_OUTPUT_PARAMETER_V1_3 *)(&get_voltage_info_param_space))->ulVoltageLevel);986987return result;988}989990int atomctrl_get_smc_sclk_range_table(struct pp_hwmgr *hwmgr, struct pp_atom_ctrl_sclk_range_table *table)991{992993int i;994u8 frev, crev;995u16 size;996997ATOM_SMU_INFO_V2_1 *psmu_info =998(ATOM_SMU_INFO_V2_1 *)smu_atom_get_data_table(hwmgr->adev,999GetIndexIntoMasterTable(DATA, SMU_Info),1000&size, &frev, &crev);10011002if (!psmu_info)1003return -EINVAL;10041005for (i = 0; i < psmu_info->ucSclkEntryNum; i++) {1006table->entry[i].ucVco_setting = psmu_info->asSclkFcwRangeEntry[i].ucVco_setting;1007table->entry[i].ucPostdiv = psmu_info->asSclkFcwRangeEntry[i].ucPostdiv;1008table->entry[i].usFcw_pcc =1009le16_to_cpu(psmu_info->asSclkFcwRangeEntry[i].ucFcw_pcc);1010table->entry[i].usFcw_trans_upper =1011le16_to_cpu(psmu_info->asSclkFcwRangeEntry[i].ucFcw_trans_upper);1012table->entry[i].usRcw_trans_lower =1013le16_to_cpu(psmu_info->asSclkFcwRangeEntry[i].ucRcw_trans_lower);1014}10151016return 0;1017}10181019int atomctrl_get_vddc_shared_railinfo(struct pp_hwmgr *hwmgr, uint8_t *shared_rail)1020{1021ATOM_SMU_INFO_V2_1 *psmu_info =1022(ATOM_SMU_INFO_V2_1 *)smu_atom_get_data_table(hwmgr->adev,1023GetIndexIntoMasterTable(DATA, SMU_Info),1024NULL, NULL, NULL);1025if (!psmu_info)1026return -1;10271028*shared_rail = psmu_info->ucSharePowerSource;10291030return 0;1031}10321033int atomctrl_get_avfs_information(struct pp_hwmgr *hwmgr,1034struct pp_atom_ctrl__avfs_parameters *param)1035{1036ATOM_ASIC_PROFILING_INFO_V3_6 *profile = NULL;10371038if (param == NULL)1039return -EINVAL;10401041profile = (ATOM_ASIC_PROFILING_INFO_V3_6 *)1042smu_atom_get_data_table(hwmgr->adev,1043GetIndexIntoMasterTable(DATA, ASIC_ProfilingInfo),1044NULL, NULL, NULL);1045if (!profile)1046return -1;10471048param->ulAVFS_meanNsigma_Acontant0 = le32_to_cpu(profile->ulAVFS_meanNsigma_Acontant0);1049param->ulAVFS_meanNsigma_Acontant1 = le32_to_cpu(profile->ulAVFS_meanNsigma_Acontant1);1050param->ulAVFS_meanNsigma_Acontant2 = le32_to_cpu(profile->ulAVFS_meanNsigma_Acontant2);1051param->usAVFS_meanNsigma_DC_tol_sigma = le16_to_cpu(profile->usAVFS_meanNsigma_DC_tol_sigma);1052param->usAVFS_meanNsigma_Platform_mean = le16_to_cpu(profile->usAVFS_meanNsigma_Platform_mean);1053param->usAVFS_meanNsigma_Platform_sigma = le16_to_cpu(profile->usAVFS_meanNsigma_Platform_sigma);1054param->ulGB_VDROOP_TABLE_CKSOFF_a0 = le32_to_cpu(profile->ulGB_VDROOP_TABLE_CKSOFF_a0);1055param->ulGB_VDROOP_TABLE_CKSOFF_a1 = le32_to_cpu(profile->ulGB_VDROOP_TABLE_CKSOFF_a1);1056param->ulGB_VDROOP_TABLE_CKSOFF_a2 = le32_to_cpu(profile->ulGB_VDROOP_TABLE_CKSOFF_a2);1057param->ulGB_VDROOP_TABLE_CKSON_a0 = le32_to_cpu(profile->ulGB_VDROOP_TABLE_CKSON_a0);1058param->ulGB_VDROOP_TABLE_CKSON_a1 = le32_to_cpu(profile->ulGB_VDROOP_TABLE_CKSON_a1);1059param->ulGB_VDROOP_TABLE_CKSON_a2 = le32_to_cpu(profile->ulGB_VDROOP_TABLE_CKSON_a2);1060param->ulAVFSGB_FUSE_TABLE_CKSOFF_m1 = le32_to_cpu(profile->ulAVFSGB_FUSE_TABLE_CKSOFF_m1);1061param->usAVFSGB_FUSE_TABLE_CKSOFF_m2 = le16_to_cpu(profile->usAVFSGB_FUSE_TABLE_CKSOFF_m2);1062param->ulAVFSGB_FUSE_TABLE_CKSOFF_b = le32_to_cpu(profile->ulAVFSGB_FUSE_TABLE_CKSOFF_b);1063param->ulAVFSGB_FUSE_TABLE_CKSON_m1 = le32_to_cpu(profile->ulAVFSGB_FUSE_TABLE_CKSON_m1);1064param->usAVFSGB_FUSE_TABLE_CKSON_m2 = le16_to_cpu(profile->usAVFSGB_FUSE_TABLE_CKSON_m2);1065param->ulAVFSGB_FUSE_TABLE_CKSON_b = le32_to_cpu(profile->ulAVFSGB_FUSE_TABLE_CKSON_b);1066param->usMaxVoltage_0_25mv = le16_to_cpu(profile->usMaxVoltage_0_25mv);1067param->ucEnableGB_VDROOP_TABLE_CKSOFF = profile->ucEnableGB_VDROOP_TABLE_CKSOFF;1068param->ucEnableGB_VDROOP_TABLE_CKSON = profile->ucEnableGB_VDROOP_TABLE_CKSON;1069param->ucEnableGB_FUSE_TABLE_CKSOFF = profile->ucEnableGB_FUSE_TABLE_CKSOFF;1070param->ucEnableGB_FUSE_TABLE_CKSON = profile->ucEnableGB_FUSE_TABLE_CKSON;1071param->usPSM_Age_ComFactor = le16_to_cpu(profile->usPSM_Age_ComFactor);1072param->ucEnableApplyAVFS_CKS_OFF_Voltage = profile->ucEnableApplyAVFS_CKS_OFF_Voltage;10731074return 0;1075}10761077int atomctrl_get_svi2_info(struct pp_hwmgr *hwmgr, uint8_t voltage_type,1078uint8_t *svd_gpio_id, uint8_t *svc_gpio_id,1079uint16_t *load_line)1080{1081ATOM_VOLTAGE_OBJECT_INFO_V3_1 *voltage_info =1082(ATOM_VOLTAGE_OBJECT_INFO_V3_1 *)get_voltage_info_table(hwmgr->adev);10831084const ATOM_VOLTAGE_OBJECT_V3 *voltage_object;10851086PP_ASSERT_WITH_CODE((NULL != voltage_info),1087"Could not find Voltage Table in BIOS.", return -EINVAL);10881089voltage_object = atomctrl_lookup_voltage_type_v31090(voltage_info, voltage_type, VOLTAGE_OBJ_SVID2);10911092*svd_gpio_id = voltage_object->asSVID2Obj.ucSVDGpioId;1093*svc_gpio_id = voltage_object->asSVID2Obj.ucSVCGpioId;1094*load_line = voltage_object->asSVID2Obj.usLoadLine_PSI;10951096return 0;1097}10981099int atomctrl_get_leakage_id_from_efuse(struct pp_hwmgr *hwmgr, uint16_t *virtual_voltage_id)1100{1101struct amdgpu_device *adev = hwmgr->adev;1102SET_VOLTAGE_PS_ALLOCATION allocation;1103SET_VOLTAGE_PARAMETERS_V1_3 *voltage_parameters =1104(SET_VOLTAGE_PARAMETERS_V1_3 *)&allocation.sASICSetVoltage;1105int result;11061107voltage_parameters->ucVoltageMode = ATOM_GET_LEAKAGE_ID;11081109result = amdgpu_atom_execute_table(adev->mode_info.atom_context,1110GetIndexIntoMasterTable(COMMAND, SetVoltage),1111(uint32_t *)voltage_parameters, sizeof(*voltage_parameters));11121113*virtual_voltage_id = voltage_parameters->usVoltageLevel;11141115return result;1116}11171118int atomctrl_get_leakage_vddc_base_on_leakage(struct pp_hwmgr *hwmgr,1119uint16_t *vddc, uint16_t *vddci,1120uint16_t virtual_voltage_id,1121uint16_t efuse_voltage_id)1122{1123int i, j;1124int ix;1125u16 *leakage_bin, *vddc_id_buf, *vddc_buf, *vddci_id_buf, *vddci_buf;1126ATOM_ASIC_PROFILING_INFO_V2_1 *profile;11271128*vddc = 0;1129*vddci = 0;11301131ix = GetIndexIntoMasterTable(DATA, ASIC_ProfilingInfo);11321133profile = (ATOM_ASIC_PROFILING_INFO_V2_1 *)1134smu_atom_get_data_table(hwmgr->adev,1135ix,1136NULL, NULL, NULL);1137if (!profile)1138return -EINVAL;11391140if ((profile->asHeader.ucTableFormatRevision >= 2) &&1141(profile->asHeader.ucTableContentRevision >= 1) &&1142(profile->asHeader.usStructureSize >= sizeof(ATOM_ASIC_PROFILING_INFO_V2_1))) {1143leakage_bin = (u16 *)((char *)profile + profile->usLeakageBinArrayOffset);1144vddc_id_buf = (u16 *)((char *)profile + profile->usElbVDDC_IdArrayOffset);1145vddc_buf = (u16 *)((char *)profile + profile->usElbVDDC_LevelArrayOffset);1146if (profile->ucElbVDDC_Num > 0) {1147for (i = 0; i < profile->ucElbVDDC_Num; i++) {1148if (vddc_id_buf[i] == virtual_voltage_id) {1149for (j = 0; j < profile->ucLeakageBinNum; j++) {1150if (efuse_voltage_id <= leakage_bin[j]) {1151*vddc = vddc_buf[j * profile->ucElbVDDC_Num + i];1152break;1153}1154}1155break;1156}1157}1158}11591160vddci_id_buf = (u16 *)((char *)profile + profile->usElbVDDCI_IdArrayOffset);1161vddci_buf = (u16 *)((char *)profile + profile->usElbVDDCI_LevelArrayOffset);1162if (profile->ucElbVDDCI_Num > 0) {1163for (i = 0; i < profile->ucElbVDDCI_Num; i++) {1164if (vddci_id_buf[i] == virtual_voltage_id) {1165for (j = 0; j < profile->ucLeakageBinNum; j++) {1166if (efuse_voltage_id <= leakage_bin[j]) {1167*vddci = vddci_buf[j * profile->ucElbVDDCI_Num + i];1168break;1169}1170}1171break;1172}1173}1174}1175}11761177return 0;1178}11791180void atomctrl_get_voltage_range(struct pp_hwmgr *hwmgr, uint32_t *max_vddc,1181uint32_t *min_vddc)1182{1183void *profile;11841185profile = smu_atom_get_data_table(hwmgr->adev,1186GetIndexIntoMasterTable(DATA, ASIC_ProfilingInfo),1187NULL, NULL, NULL);11881189if (profile) {1190switch (hwmgr->chip_id) {1191case CHIP_TONGA:1192case CHIP_FIJI:1193*max_vddc = le32_to_cpu(((ATOM_ASIC_PROFILING_INFO_V3_3 *)profile)->ulMaxVddc) / 4;1194*min_vddc = le32_to_cpu(((ATOM_ASIC_PROFILING_INFO_V3_3 *)profile)->ulMinVddc) / 4;1195return;1196case CHIP_POLARIS11:1197case CHIP_POLARIS10:1198case CHIP_POLARIS12:1199*max_vddc = le32_to_cpu(((ATOM_ASIC_PROFILING_INFO_V3_6 *)profile)->ulMaxVddc) / 100;1200*min_vddc = le32_to_cpu(((ATOM_ASIC_PROFILING_INFO_V3_6 *)profile)->ulMinVddc) / 100;1201return;1202default:1203break;1204}1205}1206*max_vddc = 0;1207*min_vddc = 0;1208}12091210int atomctrl_get_edc_hilo_leakage_offset_table(struct pp_hwmgr *hwmgr,1211AtomCtrl_HiLoLeakageOffsetTable *table)1212{1213ATOM_GFX_INFO_V2_3 *gfxinfo = smu_atom_get_data_table(hwmgr->adev,1214GetIndexIntoMasterTable(DATA, GFX_Info),1215NULL, NULL, NULL);1216if (!gfxinfo)1217return -ENOENT;12181219table->usHiLoLeakageThreshold = gfxinfo->usHiLoLeakageThreshold;1220table->usEdcDidtLoDpm7TableOffset = gfxinfo->usEdcDidtLoDpm7TableOffset;1221table->usEdcDidtHiDpm7TableOffset = gfxinfo->usEdcDidtHiDpm7TableOffset;12221223return 0;1224}12251226static AtomCtrl_EDCLeakgeTable *get_edc_leakage_table(struct pp_hwmgr *hwmgr,1227uint16_t offset)1228{1229void *table_address;1230char *temp;12311232table_address = smu_atom_get_data_table(hwmgr->adev,1233GetIndexIntoMasterTable(DATA, GFX_Info),1234NULL, NULL, NULL);1235if (!table_address)1236return NULL;12371238temp = (char *)table_address;1239table_address += offset;12401241return (AtomCtrl_EDCLeakgeTable *)temp;1242}12431244int atomctrl_get_edc_leakage_table(struct pp_hwmgr *hwmgr,1245AtomCtrl_EDCLeakgeTable *table,1246uint16_t offset)1247{1248uint32_t length, i;1249AtomCtrl_EDCLeakgeTable *leakage_table =1250get_edc_leakage_table(hwmgr, offset);12511252if (!leakage_table)1253return -ENOENT;12541255length = sizeof(leakage_table->DIDT_REG) /1256sizeof(leakage_table->DIDT_REG[0]);1257for (i = 0; i < length; i++)1258table->DIDT_REG[i] = leakage_table->DIDT_REG[i];12591260return 0;1261}126212631264