Path: blob/master/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c
51589 views
/*1* Copyright 2013 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 <linux/module.h>24#include <linux/pci.h>2526#include "amdgpu.h"27#include "amdgpu_pm.h"28#include "amdgpu_dpm.h"29#include "amdgpu_atombios.h"30#include "amdgpu_dpm_internal.h"31#include "amd_pcie.h"32#include "atom.h"33#include "gfx_v6_0.h"34#include "r600_dpm.h"35#include "sid.h"36#include "si_dpm.h"37#include "../include/pptable.h"38#include <linux/math64.h>39#include <linux/seq_file.h>40#include <linux/firmware.h>41#include <legacy_dpm.h>4243#include "bif/bif_3_0_d.h"44#include "bif/bif_3_0_sh_mask.h"4546#include "dce/dce_6_0_d.h"47#include "dce/dce_6_0_sh_mask.h"4849#include "gca/gfx_6_0_d.h"50#include "gca/gfx_6_0_sh_mask.h"5152#include"gmc/gmc_6_0_d.h"53#include"gmc/gmc_6_0_sh_mask.h"5455#include "smu/smu_6_0_d.h"56#include "smu/smu_6_0_sh_mask.h"5758#define MC_CG_ARB_FREQ_F0 0x0a59#define MC_CG_ARB_FREQ_F1 0x0b60#define MC_CG_ARB_FREQ_F2 0x0c61#define MC_CG_ARB_FREQ_F3 0x0d6263#define SMC_RAM_END 0x200006465#define SCLK_MIN_DEEPSLEEP_FREQ 1350666768/* sizeof(ATOM_PPLIB_EXTENDEDHEADER) */69#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2 1270#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3 1471#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4 1672#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5 1873#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6 2074#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7 227576#define BIOS_SCRATCH_4 0x5cd7778MODULE_FIRMWARE("amdgpu/tahiti_smc.bin");79MODULE_FIRMWARE("amdgpu/pitcairn_smc.bin");80MODULE_FIRMWARE("amdgpu/pitcairn_k_smc.bin");81MODULE_FIRMWARE("amdgpu/verde_smc.bin");82MODULE_FIRMWARE("amdgpu/verde_k_smc.bin");83MODULE_FIRMWARE("amdgpu/oland_smc.bin");84MODULE_FIRMWARE("amdgpu/oland_k_smc.bin");85MODULE_FIRMWARE("amdgpu/hainan_smc.bin");86MODULE_FIRMWARE("amdgpu/hainan_k_smc.bin");87MODULE_FIRMWARE("amdgpu/banks_k_2_smc.bin");8889static const struct amd_pm_funcs si_dpm_funcs;9091union power_info {92struct _ATOM_POWERPLAY_INFO info;93struct _ATOM_POWERPLAY_INFO_V2 info_2;94struct _ATOM_POWERPLAY_INFO_V3 info_3;95struct _ATOM_PPLIB_POWERPLAYTABLE pplib;96struct _ATOM_PPLIB_POWERPLAYTABLE2 pplib2;97struct _ATOM_PPLIB_POWERPLAYTABLE3 pplib3;98struct _ATOM_PPLIB_POWERPLAYTABLE4 pplib4;99struct _ATOM_PPLIB_POWERPLAYTABLE5 pplib5;100};101102union fan_info {103struct _ATOM_PPLIB_FANTABLE fan;104struct _ATOM_PPLIB_FANTABLE2 fan2;105struct _ATOM_PPLIB_FANTABLE3 fan3;106};107108union pplib_clock_info {109struct _ATOM_PPLIB_R600_CLOCK_INFO r600;110struct _ATOM_PPLIB_RS780_CLOCK_INFO rs780;111struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO evergreen;112struct _ATOM_PPLIB_SUMO_CLOCK_INFO sumo;113struct _ATOM_PPLIB_SI_CLOCK_INFO si;114};115116enum si_dpm_auto_throttle_src {117SI_DPM_AUTO_THROTTLE_SRC_THERMAL,118SI_DPM_AUTO_THROTTLE_SRC_EXTERNAL119};120121enum si_dpm_event_src {122SI_DPM_EVENT_SRC_ANALOG = 0,123SI_DPM_EVENT_SRC_EXTERNAL = 1,124SI_DPM_EVENT_SRC_DIGITAL = 2,125SI_DPM_EVENT_SRC_ANALOG_OR_EXTERNAL = 3,126SI_DPM_EVENT_SRC_DIGIAL_OR_EXTERNAL = 4127};128129static const u32 r600_utc[R600_PM_NUMBER_OF_TC] =130{131R600_UTC_DFLT_00,132R600_UTC_DFLT_01,133R600_UTC_DFLT_02,134R600_UTC_DFLT_03,135R600_UTC_DFLT_04,136R600_UTC_DFLT_05,137R600_UTC_DFLT_06,138R600_UTC_DFLT_07,139R600_UTC_DFLT_08,140R600_UTC_DFLT_09,141R600_UTC_DFLT_10,142R600_UTC_DFLT_11,143R600_UTC_DFLT_12,144R600_UTC_DFLT_13,145R600_UTC_DFLT_14,146};147148static const u32 r600_dtc[R600_PM_NUMBER_OF_TC] =149{150R600_DTC_DFLT_00,151R600_DTC_DFLT_01,152R600_DTC_DFLT_02,153R600_DTC_DFLT_03,154R600_DTC_DFLT_04,155R600_DTC_DFLT_05,156R600_DTC_DFLT_06,157R600_DTC_DFLT_07,158R600_DTC_DFLT_08,159R600_DTC_DFLT_09,160R600_DTC_DFLT_10,161R600_DTC_DFLT_11,162R600_DTC_DFLT_12,163R600_DTC_DFLT_13,164R600_DTC_DFLT_14,165};166167static const struct si_cac_config_reg cac_weights_tahiti[] =168{169{ 0x0, 0x0000ffff, 0, 0xc, SISLANDS_CACCONFIG_CGIND },170{ 0x0, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },171{ 0x1, 0x0000ffff, 0, 0x101, SISLANDS_CACCONFIG_CGIND },172{ 0x1, 0xffff0000, 16, 0xc, SISLANDS_CACCONFIG_CGIND },173{ 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },174{ 0x3, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },175{ 0x3, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },176{ 0x4, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },177{ 0x4, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },178{ 0x5, 0x0000ffff, 0, 0x8fc, SISLANDS_CACCONFIG_CGIND },179{ 0x5, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },180{ 0x6, 0x0000ffff, 0, 0x95, SISLANDS_CACCONFIG_CGIND },181{ 0x6, 0xffff0000, 16, 0x34e, SISLANDS_CACCONFIG_CGIND },182{ 0x18f, 0x0000ffff, 0, 0x1a1, SISLANDS_CACCONFIG_CGIND },183{ 0x7, 0x0000ffff, 0, 0xda, SISLANDS_CACCONFIG_CGIND },184{ 0x7, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },185{ 0x8, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },186{ 0x8, 0xffff0000, 16, 0x46, SISLANDS_CACCONFIG_CGIND },187{ 0x9, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },188{ 0xa, 0x0000ffff, 0, 0x208, SISLANDS_CACCONFIG_CGIND },189{ 0xb, 0x0000ffff, 0, 0xe7, SISLANDS_CACCONFIG_CGIND },190{ 0xb, 0xffff0000, 16, 0x948, SISLANDS_CACCONFIG_CGIND },191{ 0xc, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },192{ 0xd, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },193{ 0xd, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },194{ 0xe, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },195{ 0xf, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },196{ 0xf, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },197{ 0x10, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },198{ 0x10, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },199{ 0x11, 0x0000ffff, 0, 0x167, SISLANDS_CACCONFIG_CGIND },200{ 0x11, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },201{ 0x12, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },202{ 0x13, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },203{ 0x13, 0xffff0000, 16, 0x35, SISLANDS_CACCONFIG_CGIND },204{ 0x14, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },205{ 0x15, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },206{ 0x15, 0xffff0000, 16, 0x2, SISLANDS_CACCONFIG_CGIND },207{ 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },208{ 0x16, 0x0000ffff, 0, 0x31, SISLANDS_CACCONFIG_CGIND },209{ 0x16, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },210{ 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },211{ 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },212{ 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },213{ 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },214{ 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },215{ 0x1a, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },216{ 0x1a, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },217{ 0x1b, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },218{ 0x1b, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },219{ 0x1c, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },220{ 0x1c, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },221{ 0x1d, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },222{ 0x1d, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },223{ 0x1e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },224{ 0x1e, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },225{ 0x1f, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },226{ 0x1f, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },227{ 0x20, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },228{ 0x6d, 0x0000ffff, 0, 0x18e, SISLANDS_CACCONFIG_CGIND },229{ 0xFFFFFFFF }230};231232static const struct si_cac_config_reg lcac_tahiti[] =233{234{ 0x143, 0x0001fffe, 1, 0x3, SISLANDS_CACCONFIG_CGIND },235{ 0x143, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },236{ 0x146, 0x0001fffe, 1, 0x3, SISLANDS_CACCONFIG_CGIND },237{ 0x146, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },238{ 0x149, 0x0001fffe, 1, 0x3, SISLANDS_CACCONFIG_CGIND },239{ 0x149, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },240{ 0x14c, 0x0001fffe, 1, 0x3, SISLANDS_CACCONFIG_CGIND },241{ 0x14c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },242{ 0x98, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },243{ 0x98, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },244{ 0x9b, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },245{ 0x9b, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },246{ 0x9e, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },247{ 0x9e, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },248{ 0x101, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },249{ 0x101, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },250{ 0x104, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },251{ 0x104, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },252{ 0x107, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },253{ 0x107, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },254{ 0x10a, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },255{ 0x10a, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },256{ 0x10d, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },257{ 0x10d, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },258{ 0x8c, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND },259{ 0x8c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },260{ 0x8f, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND },261{ 0x8f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },262{ 0x92, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND },263{ 0x92, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },264{ 0x95, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND },265{ 0x95, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },266{ 0x14f, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND },267{ 0x14f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },268{ 0x152, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND },269{ 0x152, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },270{ 0x155, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND },271{ 0x155, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },272{ 0x158, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND },273{ 0x158, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },274{ 0x110, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND },275{ 0x110, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },276{ 0x113, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND },277{ 0x113, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },278{ 0x116, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND },279{ 0x116, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },280{ 0x119, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND },281{ 0x119, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },282{ 0x11c, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },283{ 0x11c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },284{ 0x11f, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },285{ 0x11f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },286{ 0x122, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },287{ 0x122, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },288{ 0x125, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },289{ 0x125, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },290{ 0x128, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },291{ 0x128, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },292{ 0x12b, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },293{ 0x12b, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },294{ 0x15b, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND },295{ 0x15b, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },296{ 0x15e, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND },297{ 0x15e, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },298{ 0x161, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND },299{ 0x161, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },300{ 0x164, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND },301{ 0x164, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },302{ 0x167, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND },303{ 0x167, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },304{ 0x16a, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND },305{ 0x16a, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },306{ 0x16d, 0x0001fffe, 1, 0x6, SISLANDS_CACCONFIG_CGIND },307{ 0x16d, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },308{ 0x170, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },309{ 0x170, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },310{ 0x173, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },311{ 0x173, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },312{ 0x176, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },313{ 0x176, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },314{ 0x179, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },315{ 0x179, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },316{ 0x17c, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },317{ 0x17c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },318{ 0x17f, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },319{ 0x17f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },320{ 0xFFFFFFFF }321322};323324static const struct si_cac_config_reg cac_override_tahiti[] =325{326{ 0xFFFFFFFF }327};328329static const struct si_powertune_data powertune_data_tahiti =330{331((1 << 16) | 27027),3326,3330,3344,33595,336{3370UL,3380UL,3394521550UL,340309631529UL,341-1270850L,3424513710L,34340344},345595000000UL,34612,347{3480,3490,3500,3510,3520,3530,3540,3550356},357true358};359360static const struct si_dte_data dte_data_tahiti =361{362{ 1159409, 0, 0, 0, 0 },363{ 777, 0, 0, 0, 0 },3642,36554000,366127000,36725,3682,36910,37013,371{ 27, 31, 35, 39, 43, 47, 54, 61, 67, 74, 81, 88, 95, 0, 0, 0 },372{ 240888759, 221057860, 235370597, 162287531, 158510299, 131423027, 116673180, 103067515, 87941937, 76209048, 68209175, 64090048, 58301890, 0, 0, 0 },373{ 12024, 11189, 11451, 8411, 7939, 6666, 5681, 4905, 4241, 3720, 3354, 3122, 2890, 0, 0, 0 },37485,375false376};377378static const struct si_dte_data dte_data_tahiti_pro =379{380{ 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0x0 },381{ 0x0, 0x0, 0x0, 0x0, 0x0 },3825,38345000,384100,3850xA,3861,3870,3880x10,389{ 0x96, 0xB4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF },390{ 0x895440, 0x3D0900, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680 },391{ 0x7D0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 },39290,393true394};395396static const struct si_dte_data dte_data_new_zealand =397{398{ 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0 },399{ 0x29B, 0x3E9, 0x537, 0x7D2, 0 },4000x5,4010xAFC8,4020x69,4030x32,4041,4050,4060x10,407{ 0x82, 0xA0, 0xB4, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE },408{ 0x895440, 0x3D0900, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680 },409{ 0xDAC, 0x1388, 0x685, 0x685, 0x685, 0x685, 0x685, 0x685, 0x685, 0x685, 0x685, 0x685, 0x685, 0x685, 0x685, 0x685 },41085,411true412};413414static const struct si_dte_data dte_data_aruba_pro =415{416{ 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0x0 },417{ 0x0, 0x0, 0x0, 0x0, 0x0 },4185,41945000,420100,4210xA,4221,4230,4240x10,425{ 0x96, 0xB4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF },426{ 0x895440, 0x3D0900, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680 },427{ 0x1000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 },42890,429true430};431432static const struct si_dte_data dte_data_malta =433{434{ 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0x0 },435{ 0x0, 0x0, 0x0, 0x0, 0x0 },4365,43745000,438100,4390xA,4401,4410,4420x10,443{ 0x96, 0xB4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF },444{ 0x895440, 0x3D0900, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680 },445{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 },44690,447true448};449450static const struct si_cac_config_reg cac_weights_pitcairn[] =451{452{ 0x0, 0x0000ffff, 0, 0x8a, SISLANDS_CACCONFIG_CGIND },453{ 0x0, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },454{ 0x1, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },455{ 0x1, 0xffff0000, 16, 0x24d, SISLANDS_CACCONFIG_CGIND },456{ 0x2, 0x0000ffff, 0, 0x19, SISLANDS_CACCONFIG_CGIND },457{ 0x3, 0x0000ffff, 0, 0x118, SISLANDS_CACCONFIG_CGIND },458{ 0x3, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },459{ 0x4, 0x0000ffff, 0, 0x76, SISLANDS_CACCONFIG_CGIND },460{ 0x4, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },461{ 0x5, 0x0000ffff, 0, 0xc11, SISLANDS_CACCONFIG_CGIND },462{ 0x5, 0xffff0000, 16, 0x7f3, SISLANDS_CACCONFIG_CGIND },463{ 0x6, 0x0000ffff, 0, 0x403, SISLANDS_CACCONFIG_CGIND },464{ 0x6, 0xffff0000, 16, 0x367, SISLANDS_CACCONFIG_CGIND },465{ 0x18f, 0x0000ffff, 0, 0x4c9, SISLANDS_CACCONFIG_CGIND },466{ 0x7, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },467{ 0x7, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },468{ 0x8, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },469{ 0x8, 0xffff0000, 16, 0x45d, SISLANDS_CACCONFIG_CGIND },470{ 0x9, 0x0000ffff, 0, 0x36d, SISLANDS_CACCONFIG_CGIND },471{ 0xa, 0x0000ffff, 0, 0x534, SISLANDS_CACCONFIG_CGIND },472{ 0xb, 0x0000ffff, 0, 0x5da, SISLANDS_CACCONFIG_CGIND },473{ 0xb, 0xffff0000, 16, 0x880, SISLANDS_CACCONFIG_CGIND },474{ 0xc, 0x0000ffff, 0, 0x201, SISLANDS_CACCONFIG_CGIND },475{ 0xd, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },476{ 0xd, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },477{ 0xe, 0x0000ffff, 0, 0x9f, SISLANDS_CACCONFIG_CGIND },478{ 0xf, 0x0000ffff, 0, 0x1f, SISLANDS_CACCONFIG_CGIND },479{ 0xf, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },480{ 0x10, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },481{ 0x10, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },482{ 0x11, 0x0000ffff, 0, 0x5de, SISLANDS_CACCONFIG_CGIND },483{ 0x11, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },484{ 0x12, 0x0000ffff, 0, 0x7b, SISLANDS_CACCONFIG_CGIND },485{ 0x13, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },486{ 0x13, 0xffff0000, 16, 0x13, SISLANDS_CACCONFIG_CGIND },487{ 0x14, 0x0000ffff, 0, 0xf9, SISLANDS_CACCONFIG_CGIND },488{ 0x15, 0x0000ffff, 0, 0x66, SISLANDS_CACCONFIG_CGIND },489{ 0x15, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },490{ 0x4e, 0x0000ffff, 0, 0x13, SISLANDS_CACCONFIG_CGIND },491{ 0x16, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },492{ 0x16, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },493{ 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },494{ 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },495{ 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },496{ 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },497{ 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },498{ 0x1a, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },499{ 0x1a, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },500{ 0x1b, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },501{ 0x1b, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },502{ 0x1c, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },503{ 0x1c, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },504{ 0x1d, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },505{ 0x1d, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },506{ 0x1e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },507{ 0x1e, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },508{ 0x1f, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },509{ 0x1f, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },510{ 0x20, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },511{ 0x6d, 0x0000ffff, 0, 0x186, SISLANDS_CACCONFIG_CGIND },512{ 0xFFFFFFFF }513};514515static const struct si_cac_config_reg lcac_pitcairn[] =516{517{ 0x98, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },518{ 0x98, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },519{ 0x104, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },520{ 0x104, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },521{ 0x110, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND },522{ 0x110, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },523{ 0x14f, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND },524{ 0x14f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },525{ 0x8c, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND },526{ 0x8c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },527{ 0x143, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },528{ 0x143, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },529{ 0x9b, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },530{ 0x9b, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },531{ 0x107, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },532{ 0x107, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },533{ 0x113, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND },534{ 0x113, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },535{ 0x152, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND },536{ 0x152, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },537{ 0x8f, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND },538{ 0x8f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },539{ 0x146, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },540{ 0x146, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },541{ 0x9e, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },542{ 0x9e, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },543{ 0x10a, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },544{ 0x10a, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },545{ 0x116, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND },546{ 0x116, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },547{ 0x155, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND },548{ 0x155, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },549{ 0x92, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND },550{ 0x92, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },551{ 0x149, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },552{ 0x149, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },553{ 0x101, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },554{ 0x101, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },555{ 0x10d, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },556{ 0x10d, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },557{ 0x119, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND },558{ 0x119, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },559{ 0x158, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND },560{ 0x158, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },561{ 0x95, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND },562{ 0x95, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },563{ 0x14c, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },564{ 0x14c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },565{ 0x11c, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },566{ 0x11c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },567{ 0x11f, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },568{ 0x11f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },569{ 0x122, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },570{ 0x122, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },571{ 0x125, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },572{ 0x125, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },573{ 0x128, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },574{ 0x128, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },575{ 0x12b, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },576{ 0x12b, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },577{ 0x164, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND },578{ 0x164, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },579{ 0x167, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND },580{ 0x167, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },581{ 0x16a, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND },582{ 0x16a, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },583{ 0x15e, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND },584{ 0x15e, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },585{ 0x161, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND },586{ 0x161, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },587{ 0x15b, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND },588{ 0x15b, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },589{ 0x16d, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND },590{ 0x16d, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },591{ 0x170, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },592{ 0x170, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },593{ 0x173, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },594{ 0x173, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },595{ 0x176, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },596{ 0x176, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },597{ 0x179, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },598{ 0x179, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },599{ 0x17c, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },600{ 0x17c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },601{ 0x17f, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },602{ 0x17f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },603{ 0xFFFFFFFF }604};605606static const struct si_cac_config_reg cac_override_pitcairn[] =607{608{ 0xFFFFFFFF }609};610611static const struct si_powertune_data powertune_data_pitcairn =612{613((1 << 16) | 27027),6145,6150,6166,617100,618{61951600000UL,6201800000UL,6217194395UL,622309631529UL,623-1270850L,6244513710L,625100626},627117830498UL,62812,629{6300,6310,6320,6330,6340,6350,6360,6370638},639true640};641642static const struct si_dte_data dte_data_pitcairn =643{644{ 0, 0, 0, 0, 0 },645{ 0, 0, 0, 0, 0 },6460,6470,6480,6490,6500,6510,6520,653{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },654{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },655{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },6560,657false658};659660static const struct si_dte_data dte_data_curacao_xt =661{662{ 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0x0 },663{ 0x0, 0x0, 0x0, 0x0, 0x0 },6645,66545000,666100,6670xA,6681,6690,6700x10,671{ 0x96, 0xB4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF },672{ 0x895440, 0x3D0900, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680 },673{ 0x1D17, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 },67490,675true676};677678static const struct si_dte_data dte_data_curacao_pro =679{680{ 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0x0 },681{ 0x0, 0x0, 0x0, 0x0, 0x0 },6825,68345000,684100,6850xA,6861,6870,6880x10,689{ 0x96, 0xB4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF },690{ 0x895440, 0x3D0900, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680 },691{ 0x1D17, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 },69290,693true694};695696static const struct si_dte_data dte_data_neptune_xt =697{698{ 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0x0 },699{ 0x0, 0x0, 0x0, 0x0, 0x0 },7005,70145000,702100,7030xA,7041,7050,7060x10,707{ 0x96, 0xB4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF },708{ 0x895440, 0x3D0900, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680 },709{ 0x3A2F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 },71090,711true712};713714static const struct si_cac_config_reg cac_weights_chelsea_pro[] =715{716{ 0x0, 0x0000ffff, 0, 0x82, SISLANDS_CACCONFIG_CGIND },717{ 0x0, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND },718{ 0x1, 0x0000ffff, 0, 0x153, SISLANDS_CACCONFIG_CGIND },719{ 0x1, 0xffff0000, 16, 0x52, SISLANDS_CACCONFIG_CGIND },720{ 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },721{ 0x3, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND },722{ 0x3, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND },723{ 0x4, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND },724{ 0x4, 0xffff0000, 16, 0xAC, SISLANDS_CACCONFIG_CGIND },725{ 0x5, 0x0000ffff, 0, 0x118, SISLANDS_CACCONFIG_CGIND },726{ 0x5, 0xffff0000, 16, 0xBE, SISLANDS_CACCONFIG_CGIND },727{ 0x6, 0x0000ffff, 0, 0x110, SISLANDS_CACCONFIG_CGIND },728{ 0x6, 0xffff0000, 16, 0x4CD, SISLANDS_CACCONFIG_CGIND },729{ 0x18f, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND },730{ 0x7, 0x0000ffff, 0, 0x37, SISLANDS_CACCONFIG_CGIND },731{ 0x7, 0xffff0000, 16, 0x27, SISLANDS_CACCONFIG_CGIND },732{ 0x8, 0x0000ffff, 0, 0xC3, SISLANDS_CACCONFIG_CGIND },733{ 0x8, 0xffff0000, 16, 0x35, SISLANDS_CACCONFIG_CGIND },734{ 0x9, 0x0000ffff, 0, 0x28, SISLANDS_CACCONFIG_CGIND },735{ 0xa, 0x0000ffff, 0, 0x26C, SISLANDS_CACCONFIG_CGIND },736{ 0xb, 0x0000ffff, 0, 0x3B2, SISLANDS_CACCONFIG_CGIND },737{ 0xb, 0xffff0000, 16, 0x99D, SISLANDS_CACCONFIG_CGIND },738{ 0xc, 0x0000ffff, 0, 0xA3F, SISLANDS_CACCONFIG_CGIND },739{ 0xd, 0x0000ffff, 0, 0xA, SISLANDS_CACCONFIG_CGIND },740{ 0xd, 0xffff0000, 16, 0xA, SISLANDS_CACCONFIG_CGIND },741{ 0xe, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND },742{ 0xf, 0x0000ffff, 0, 0x3, SISLANDS_CACCONFIG_CGIND },743{ 0xf, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },744{ 0x10, 0x0000ffff, 0, 0x1, SISLANDS_CACCONFIG_CGIND },745{ 0x10, 0xffff0000, 16, 0x1, SISLANDS_CACCONFIG_CGIND },746{ 0x11, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND },747{ 0x11, 0xffff0000, 16, 0x15, SISLANDS_CACCONFIG_CGIND },748{ 0x12, 0x0000ffff, 0, 0x34, SISLANDS_CACCONFIG_CGIND },749{ 0x13, 0x0000ffff, 0, 0x4, SISLANDS_CACCONFIG_CGIND },750{ 0x13, 0xffff0000, 16, 0x4, SISLANDS_CACCONFIG_CGIND },751{ 0x14, 0x0000ffff, 0, 0x2BD, SISLANDS_CACCONFIG_CGIND },752{ 0x15, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },753{ 0x15, 0xffff0000, 16, 0x6, SISLANDS_CACCONFIG_CGIND },754{ 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },755{ 0x16, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND },756{ 0x16, 0xffff0000, 16, 0x7A, SISLANDS_CACCONFIG_CGIND },757{ 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },758{ 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },759{ 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },760{ 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },761{ 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },762{ 0x1a, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },763{ 0x1a, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },764{ 0x1b, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },765{ 0x1b, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },766{ 0x1c, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },767{ 0x1c, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },768{ 0x1d, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },769{ 0x1d, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },770{ 0x1e, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },771{ 0x1e, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },772{ 0x1f, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },773{ 0x1f, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },774{ 0x20, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },775{ 0x6d, 0x0000ffff, 0, 0x100, SISLANDS_CACCONFIG_CGIND },776{ 0xFFFFFFFF }777};778779static const struct si_cac_config_reg cac_weights_chelsea_xt[] =780{781{ 0x0, 0x0000ffff, 0, 0x82, SISLANDS_CACCONFIG_CGIND },782{ 0x0, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND },783{ 0x1, 0x0000ffff, 0, 0x153, SISLANDS_CACCONFIG_CGIND },784{ 0x1, 0xffff0000, 16, 0x52, SISLANDS_CACCONFIG_CGIND },785{ 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },786{ 0x3, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND },787{ 0x3, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND },788{ 0x4, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND },789{ 0x4, 0xffff0000, 16, 0xAC, SISLANDS_CACCONFIG_CGIND },790{ 0x5, 0x0000ffff, 0, 0x118, SISLANDS_CACCONFIG_CGIND },791{ 0x5, 0xffff0000, 16, 0xBE, SISLANDS_CACCONFIG_CGIND },792{ 0x6, 0x0000ffff, 0, 0x110, SISLANDS_CACCONFIG_CGIND },793{ 0x6, 0xffff0000, 16, 0x4CD, SISLANDS_CACCONFIG_CGIND },794{ 0x18f, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND },795{ 0x7, 0x0000ffff, 0, 0x37, SISLANDS_CACCONFIG_CGIND },796{ 0x7, 0xffff0000, 16, 0x27, SISLANDS_CACCONFIG_CGIND },797{ 0x8, 0x0000ffff, 0, 0xC3, SISLANDS_CACCONFIG_CGIND },798{ 0x8, 0xffff0000, 16, 0x35, SISLANDS_CACCONFIG_CGIND },799{ 0x9, 0x0000ffff, 0, 0x28, SISLANDS_CACCONFIG_CGIND },800{ 0xa, 0x0000ffff, 0, 0x26C, SISLANDS_CACCONFIG_CGIND },801{ 0xb, 0x0000ffff, 0, 0x3B2, SISLANDS_CACCONFIG_CGIND },802{ 0xb, 0xffff0000, 16, 0x99D, SISLANDS_CACCONFIG_CGIND },803{ 0xc, 0x0000ffff, 0, 0xA3F, SISLANDS_CACCONFIG_CGIND },804{ 0xd, 0x0000ffff, 0, 0xA, SISLANDS_CACCONFIG_CGIND },805{ 0xd, 0xffff0000, 16, 0xA, SISLANDS_CACCONFIG_CGIND },806{ 0xe, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND },807{ 0xf, 0x0000ffff, 0, 0x3, SISLANDS_CACCONFIG_CGIND },808{ 0xf, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },809{ 0x10, 0x0000ffff, 0, 0x1, SISLANDS_CACCONFIG_CGIND },810{ 0x10, 0xffff0000, 16, 0x1, SISLANDS_CACCONFIG_CGIND },811{ 0x11, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND },812{ 0x11, 0xffff0000, 16, 0x15, SISLANDS_CACCONFIG_CGIND },813{ 0x12, 0x0000ffff, 0, 0x34, SISLANDS_CACCONFIG_CGIND },814{ 0x13, 0x0000ffff, 0, 0x4, SISLANDS_CACCONFIG_CGIND },815{ 0x13, 0xffff0000, 16, 0x4, SISLANDS_CACCONFIG_CGIND },816{ 0x14, 0x0000ffff, 0, 0x30A, SISLANDS_CACCONFIG_CGIND },817{ 0x15, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },818{ 0x15, 0xffff0000, 16, 0x6, SISLANDS_CACCONFIG_CGIND },819{ 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },820{ 0x16, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND },821{ 0x16, 0xffff0000, 16, 0x7A, SISLANDS_CACCONFIG_CGIND },822{ 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },823{ 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },824{ 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },825{ 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },826{ 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },827{ 0x1a, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },828{ 0x1a, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },829{ 0x1b, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },830{ 0x1b, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },831{ 0x1c, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },832{ 0x1c, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },833{ 0x1d, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },834{ 0x1d, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },835{ 0x1e, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },836{ 0x1e, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },837{ 0x1f, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },838{ 0x1f, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },839{ 0x20, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },840{ 0x6d, 0x0000ffff, 0, 0x100, SISLANDS_CACCONFIG_CGIND },841{ 0xFFFFFFFF }842};843844static const struct si_cac_config_reg cac_weights_heathrow[] =845{846{ 0x0, 0x0000ffff, 0, 0x82, SISLANDS_CACCONFIG_CGIND },847{ 0x0, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND },848{ 0x1, 0x0000ffff, 0, 0x153, SISLANDS_CACCONFIG_CGIND },849{ 0x1, 0xffff0000, 16, 0x52, SISLANDS_CACCONFIG_CGIND },850{ 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },851{ 0x3, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND },852{ 0x3, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND },853{ 0x4, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND },854{ 0x4, 0xffff0000, 16, 0xAC, SISLANDS_CACCONFIG_CGIND },855{ 0x5, 0x0000ffff, 0, 0x118, SISLANDS_CACCONFIG_CGIND },856{ 0x5, 0xffff0000, 16, 0xBE, SISLANDS_CACCONFIG_CGIND },857{ 0x6, 0x0000ffff, 0, 0x110, SISLANDS_CACCONFIG_CGIND },858{ 0x6, 0xffff0000, 16, 0x4CD, SISLANDS_CACCONFIG_CGIND },859{ 0x18f, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND },860{ 0x7, 0x0000ffff, 0, 0x37, SISLANDS_CACCONFIG_CGIND },861{ 0x7, 0xffff0000, 16, 0x27, SISLANDS_CACCONFIG_CGIND },862{ 0x8, 0x0000ffff, 0, 0xC3, SISLANDS_CACCONFIG_CGIND },863{ 0x8, 0xffff0000, 16, 0x35, SISLANDS_CACCONFIG_CGIND },864{ 0x9, 0x0000ffff, 0, 0x28, SISLANDS_CACCONFIG_CGIND },865{ 0xa, 0x0000ffff, 0, 0x26C, SISLANDS_CACCONFIG_CGIND },866{ 0xb, 0x0000ffff, 0, 0x3B2, SISLANDS_CACCONFIG_CGIND },867{ 0xb, 0xffff0000, 16, 0x99D, SISLANDS_CACCONFIG_CGIND },868{ 0xc, 0x0000ffff, 0, 0xA3F, SISLANDS_CACCONFIG_CGIND },869{ 0xd, 0x0000ffff, 0, 0xA, SISLANDS_CACCONFIG_CGIND },870{ 0xd, 0xffff0000, 16, 0xA, SISLANDS_CACCONFIG_CGIND },871{ 0xe, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND },872{ 0xf, 0x0000ffff, 0, 0x3, SISLANDS_CACCONFIG_CGIND },873{ 0xf, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },874{ 0x10, 0x0000ffff, 0, 0x1, SISLANDS_CACCONFIG_CGIND },875{ 0x10, 0xffff0000, 16, 0x1, SISLANDS_CACCONFIG_CGIND },876{ 0x11, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND },877{ 0x11, 0xffff0000, 16, 0x15, SISLANDS_CACCONFIG_CGIND },878{ 0x12, 0x0000ffff, 0, 0x34, SISLANDS_CACCONFIG_CGIND },879{ 0x13, 0x0000ffff, 0, 0x4, SISLANDS_CACCONFIG_CGIND },880{ 0x13, 0xffff0000, 16, 0x4, SISLANDS_CACCONFIG_CGIND },881{ 0x14, 0x0000ffff, 0, 0x362, SISLANDS_CACCONFIG_CGIND },882{ 0x15, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },883{ 0x15, 0xffff0000, 16, 0x6, SISLANDS_CACCONFIG_CGIND },884{ 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },885{ 0x16, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND },886{ 0x16, 0xffff0000, 16, 0x7A, SISLANDS_CACCONFIG_CGIND },887{ 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },888{ 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },889{ 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },890{ 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },891{ 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },892{ 0x1a, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },893{ 0x1a, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },894{ 0x1b, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },895{ 0x1b, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },896{ 0x1c, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },897{ 0x1c, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },898{ 0x1d, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },899{ 0x1d, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },900{ 0x1e, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },901{ 0x1e, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },902{ 0x1f, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },903{ 0x1f, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },904{ 0x20, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },905{ 0x6d, 0x0000ffff, 0, 0x100, SISLANDS_CACCONFIG_CGIND },906{ 0xFFFFFFFF }907};908909static const struct si_cac_config_reg cac_weights_cape_verde_pro[] =910{911{ 0x0, 0x0000ffff, 0, 0x82, SISLANDS_CACCONFIG_CGIND },912{ 0x0, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND },913{ 0x1, 0x0000ffff, 0, 0x153, SISLANDS_CACCONFIG_CGIND },914{ 0x1, 0xffff0000, 16, 0x52, SISLANDS_CACCONFIG_CGIND },915{ 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },916{ 0x3, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND },917{ 0x3, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND },918{ 0x4, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND },919{ 0x4, 0xffff0000, 16, 0xAC, SISLANDS_CACCONFIG_CGIND },920{ 0x5, 0x0000ffff, 0, 0x118, SISLANDS_CACCONFIG_CGIND },921{ 0x5, 0xffff0000, 16, 0xBE, SISLANDS_CACCONFIG_CGIND },922{ 0x6, 0x0000ffff, 0, 0x110, SISLANDS_CACCONFIG_CGIND },923{ 0x6, 0xffff0000, 16, 0x4CD, SISLANDS_CACCONFIG_CGIND },924{ 0x18f, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND },925{ 0x7, 0x0000ffff, 0, 0x37, SISLANDS_CACCONFIG_CGIND },926{ 0x7, 0xffff0000, 16, 0x27, SISLANDS_CACCONFIG_CGIND },927{ 0x8, 0x0000ffff, 0, 0xC3, SISLANDS_CACCONFIG_CGIND },928{ 0x8, 0xffff0000, 16, 0x35, SISLANDS_CACCONFIG_CGIND },929{ 0x9, 0x0000ffff, 0, 0x28, SISLANDS_CACCONFIG_CGIND },930{ 0xa, 0x0000ffff, 0, 0x26C, SISLANDS_CACCONFIG_CGIND },931{ 0xb, 0x0000ffff, 0, 0x3B2, SISLANDS_CACCONFIG_CGIND },932{ 0xb, 0xffff0000, 16, 0x99D, SISLANDS_CACCONFIG_CGIND },933{ 0xc, 0x0000ffff, 0, 0xA3F, SISLANDS_CACCONFIG_CGIND },934{ 0xd, 0x0000ffff, 0, 0xA, SISLANDS_CACCONFIG_CGIND },935{ 0xd, 0xffff0000, 16, 0xA, SISLANDS_CACCONFIG_CGIND },936{ 0xe, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND },937{ 0xf, 0x0000ffff, 0, 0x3, SISLANDS_CACCONFIG_CGIND },938{ 0xf, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },939{ 0x10, 0x0000ffff, 0, 0x1, SISLANDS_CACCONFIG_CGIND },940{ 0x10, 0xffff0000, 16, 0x1, SISLANDS_CACCONFIG_CGIND },941{ 0x11, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND },942{ 0x11, 0xffff0000, 16, 0x15, SISLANDS_CACCONFIG_CGIND },943{ 0x12, 0x0000ffff, 0, 0x34, SISLANDS_CACCONFIG_CGIND },944{ 0x13, 0x0000ffff, 0, 0x4, SISLANDS_CACCONFIG_CGIND },945{ 0x13, 0xffff0000, 16, 0x4, SISLANDS_CACCONFIG_CGIND },946{ 0x14, 0x0000ffff, 0, 0x315, SISLANDS_CACCONFIG_CGIND },947{ 0x15, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },948{ 0x15, 0xffff0000, 16, 0x6, SISLANDS_CACCONFIG_CGIND },949{ 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },950{ 0x16, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND },951{ 0x16, 0xffff0000, 16, 0x7A, SISLANDS_CACCONFIG_CGIND },952{ 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },953{ 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },954{ 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },955{ 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },956{ 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },957{ 0x1a, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },958{ 0x1a, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },959{ 0x1b, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },960{ 0x1b, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },961{ 0x1c, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },962{ 0x1c, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },963{ 0x1d, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },964{ 0x1d, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },965{ 0x1e, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },966{ 0x1e, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },967{ 0x1f, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },968{ 0x1f, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },969{ 0x20, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },970{ 0x6d, 0x0000ffff, 0, 0x100, SISLANDS_CACCONFIG_CGIND },971{ 0xFFFFFFFF }972};973974static const struct si_cac_config_reg cac_weights_cape_verde[] =975{976{ 0x0, 0x0000ffff, 0, 0x82, SISLANDS_CACCONFIG_CGIND },977{ 0x0, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND },978{ 0x1, 0x0000ffff, 0, 0x153, SISLANDS_CACCONFIG_CGIND },979{ 0x1, 0xffff0000, 16, 0x52, SISLANDS_CACCONFIG_CGIND },980{ 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },981{ 0x3, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND },982{ 0x3, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND },983{ 0x4, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND },984{ 0x4, 0xffff0000, 16, 0xAC, SISLANDS_CACCONFIG_CGIND },985{ 0x5, 0x0000ffff, 0, 0x118, SISLANDS_CACCONFIG_CGIND },986{ 0x5, 0xffff0000, 16, 0xBE, SISLANDS_CACCONFIG_CGIND },987{ 0x6, 0x0000ffff, 0, 0x110, SISLANDS_CACCONFIG_CGIND },988{ 0x6, 0xffff0000, 16, 0x4CD, SISLANDS_CACCONFIG_CGIND },989{ 0x18f, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND },990{ 0x7, 0x0000ffff, 0, 0x37, SISLANDS_CACCONFIG_CGIND },991{ 0x7, 0xffff0000, 16, 0x27, SISLANDS_CACCONFIG_CGIND },992{ 0x8, 0x0000ffff, 0, 0xC3, SISLANDS_CACCONFIG_CGIND },993{ 0x8, 0xffff0000, 16, 0x35, SISLANDS_CACCONFIG_CGIND },994{ 0x9, 0x0000ffff, 0, 0x28, SISLANDS_CACCONFIG_CGIND },995{ 0xa, 0x0000ffff, 0, 0x26C, SISLANDS_CACCONFIG_CGIND },996{ 0xb, 0x0000ffff, 0, 0x3B2, SISLANDS_CACCONFIG_CGIND },997{ 0xb, 0xffff0000, 16, 0x99D, SISLANDS_CACCONFIG_CGIND },998{ 0xc, 0x0000ffff, 0, 0xA3F, SISLANDS_CACCONFIG_CGIND },999{ 0xd, 0x0000ffff, 0, 0xA, SISLANDS_CACCONFIG_CGIND },1000{ 0xd, 0xffff0000, 16, 0xA, SISLANDS_CACCONFIG_CGIND },1001{ 0xe, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND },1002{ 0xf, 0x0000ffff, 0, 0x3, SISLANDS_CACCONFIG_CGIND },1003{ 0xf, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },1004{ 0x10, 0x0000ffff, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1005{ 0x10, 0xffff0000, 16, 0x1, SISLANDS_CACCONFIG_CGIND },1006{ 0x11, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND },1007{ 0x11, 0xffff0000, 16, 0x15, SISLANDS_CACCONFIG_CGIND },1008{ 0x12, 0x0000ffff, 0, 0x34, SISLANDS_CACCONFIG_CGIND },1009{ 0x13, 0x0000ffff, 0, 0x4, SISLANDS_CACCONFIG_CGIND },1010{ 0x13, 0xffff0000, 16, 0x4, SISLANDS_CACCONFIG_CGIND },1011{ 0x14, 0x0000ffff, 0, 0x3BA, SISLANDS_CACCONFIG_CGIND },1012{ 0x15, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },1013{ 0x15, 0xffff0000, 16, 0x6, SISLANDS_CACCONFIG_CGIND },1014{ 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },1015{ 0x16, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND },1016{ 0x16, 0xffff0000, 16, 0x7A, SISLANDS_CACCONFIG_CGIND },1017{ 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },1018{ 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },1019{ 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },1020{ 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },1021{ 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },1022{ 0x1a, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },1023{ 0x1a, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },1024{ 0x1b, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },1025{ 0x1b, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },1026{ 0x1c, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },1027{ 0x1c, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },1028{ 0x1d, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },1029{ 0x1d, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },1030{ 0x1e, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },1031{ 0x1e, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },1032{ 0x1f, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },1033{ 0x1f, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },1034{ 0x20, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },1035{ 0x6d, 0x0000ffff, 0, 0x100, SISLANDS_CACCONFIG_CGIND },1036{ 0xFFFFFFFF }1037};10381039static const struct si_cac_config_reg lcac_cape_verde[] =1040{1041{ 0x98, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },1042{ 0x98, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1043{ 0x104, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },1044{ 0x104, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1045{ 0x110, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND },1046{ 0x110, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1047{ 0x14f, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND },1048{ 0x14f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1049{ 0x8c, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND },1050{ 0x8c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1051{ 0x143, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },1052{ 0x143, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1053{ 0x9b, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },1054{ 0x9b, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1055{ 0x107, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },1056{ 0x107, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1057{ 0x113, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND },1058{ 0x113, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1059{ 0x152, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND },1060{ 0x152, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1061{ 0x8f, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },1062{ 0x8f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1063{ 0x146, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },1064{ 0x146, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1065{ 0x11c, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },1066{ 0x11c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1067{ 0x11f, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },1068{ 0x11f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1069{ 0x164, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },1070{ 0x164, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1071{ 0x167, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },1072{ 0x167, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1073{ 0x16a, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },1074{ 0x16a, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1075{ 0x15e, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },1076{ 0x15e, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1077{ 0x161, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },1078{ 0x161, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1079{ 0x15b, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },1080{ 0x15b, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1081{ 0x16d, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },1082{ 0x16d, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1083{ 0x170, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },1084{ 0x170, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1085{ 0x173, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },1086{ 0x173, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1087{ 0x176, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },1088{ 0x176, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1089{ 0x179, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },1090{ 0x179, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1091{ 0x17c, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },1092{ 0x17c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1093{ 0x17f, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },1094{ 0x17f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1095{ 0xFFFFFFFF }1096};10971098static const struct si_cac_config_reg cac_override_cape_verde[] =1099{1100{ 0xFFFFFFFF }1101};11021103static const struct si_powertune_data powertune_data_cape_verde =1104{1105((1 << 16) | 0x6993),11065,11070,11087,1109105,1110{11110UL,11120UL,11137194395UL,1114309631529UL,1115-1270850L,11164513710L,11171001118},1119117830498UL,112012,1121{11220,11230,11240,11250,11260,11270,11280,112901130},1131true1132};11331134static const struct si_dte_data dte_data_cape_verde =1135{1136{ 0, 0, 0, 0, 0 },1137{ 0, 0, 0, 0, 0 },11380,11390,11400,11410,11420,11430,11440,1145{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },1146{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },1147{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },11480,1149false1150};11511152static const struct si_dte_data dte_data_venus_xtx =1153{1154{ 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0x0 },1155{ 0x71C, 0xAAB, 0xE39, 0x11C7, 0x0 },11565,115755000,11580x69,11590xA,11601,11610,11620x3,1163{ 0x96, 0xB4, 0xFF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 },1164{ 0x895440, 0x3D0900, 0x989680, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 },1165{ 0xD6D8, 0x88B8, 0x1555, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 },116690,1167true1168};11691170static const struct si_dte_data dte_data_venus_xt =1171{1172{ 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0x0 },1173{ 0xBDA, 0x11C7, 0x17B4, 0x1DA1, 0x0 },11745,117555000,11760x69,11770xA,11781,11790,11800x3,1181{ 0x96, 0xB4, 0xFF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 },1182{ 0x895440, 0x3D0900, 0x989680, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 },1183{ 0xAFC8, 0x88B8, 0x238E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 },118490,1185true1186};11871188static const struct si_dte_data dte_data_venus_pro =1189{1190{ 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0x0 },1191{ 0x11C7, 0x1AAB, 0x238E, 0x2C72, 0x0 },11925,119355000,11940x69,11950xA,11961,11970,11980x3,1199{ 0x96, 0xB4, 0xFF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 },1200{ 0x895440, 0x3D0900, 0x989680, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 },1201{ 0x88B8, 0x88B8, 0x3555, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 },120290,1203true1204};12051206static const struct si_cac_config_reg cac_weights_oland[] =1207{1208{ 0x0, 0x0000ffff, 0, 0x82, SISLANDS_CACCONFIG_CGIND },1209{ 0x0, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND },1210{ 0x1, 0x0000ffff, 0, 0x153, SISLANDS_CACCONFIG_CGIND },1211{ 0x1, 0xffff0000, 16, 0x52, SISLANDS_CACCONFIG_CGIND },1212{ 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },1213{ 0x3, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND },1214{ 0x3, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND },1215{ 0x4, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND },1216{ 0x4, 0xffff0000, 16, 0xAC, SISLANDS_CACCONFIG_CGIND },1217{ 0x5, 0x0000ffff, 0, 0x118, SISLANDS_CACCONFIG_CGIND },1218{ 0x5, 0xffff0000, 16, 0xBE, SISLANDS_CACCONFIG_CGIND },1219{ 0x6, 0x0000ffff, 0, 0x110, SISLANDS_CACCONFIG_CGIND },1220{ 0x6, 0xffff0000, 16, 0x4CD, SISLANDS_CACCONFIG_CGIND },1221{ 0x18f, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND },1222{ 0x7, 0x0000ffff, 0, 0x37, SISLANDS_CACCONFIG_CGIND },1223{ 0x7, 0xffff0000, 16, 0x27, SISLANDS_CACCONFIG_CGIND },1224{ 0x8, 0x0000ffff, 0, 0xC3, SISLANDS_CACCONFIG_CGIND },1225{ 0x8, 0xffff0000, 16, 0x35, SISLANDS_CACCONFIG_CGIND },1226{ 0x9, 0x0000ffff, 0, 0x28, SISLANDS_CACCONFIG_CGIND },1227{ 0xa, 0x0000ffff, 0, 0x26C, SISLANDS_CACCONFIG_CGIND },1228{ 0xb, 0x0000ffff, 0, 0x3B2, SISLANDS_CACCONFIG_CGIND },1229{ 0xb, 0xffff0000, 16, 0x99D, SISLANDS_CACCONFIG_CGIND },1230{ 0xc, 0x0000ffff, 0, 0xA3F, SISLANDS_CACCONFIG_CGIND },1231{ 0xd, 0x0000ffff, 0, 0xA, SISLANDS_CACCONFIG_CGIND },1232{ 0xd, 0xffff0000, 16, 0xA, SISLANDS_CACCONFIG_CGIND },1233{ 0xe, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND },1234{ 0xf, 0x0000ffff, 0, 0x3, SISLANDS_CACCONFIG_CGIND },1235{ 0xf, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },1236{ 0x10, 0x0000ffff, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1237{ 0x10, 0xffff0000, 16, 0x1, SISLANDS_CACCONFIG_CGIND },1238{ 0x11, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND },1239{ 0x11, 0xffff0000, 16, 0x15, SISLANDS_CACCONFIG_CGIND },1240{ 0x12, 0x0000ffff, 0, 0x34, SISLANDS_CACCONFIG_CGIND },1241{ 0x13, 0x0000ffff, 0, 0x4, SISLANDS_CACCONFIG_CGIND },1242{ 0x13, 0xffff0000, 16, 0x4, SISLANDS_CACCONFIG_CGIND },1243{ 0x14, 0x0000ffff, 0, 0x3BA, SISLANDS_CACCONFIG_CGIND },1244{ 0x15, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },1245{ 0x15, 0xffff0000, 16, 0x6, SISLANDS_CACCONFIG_CGIND },1246{ 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },1247{ 0x16, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND },1248{ 0x16, 0xffff0000, 16, 0x7A, SISLANDS_CACCONFIG_CGIND },1249{ 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },1250{ 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },1251{ 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },1252{ 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },1253{ 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },1254{ 0x1a, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },1255{ 0x1a, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },1256{ 0x1b, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },1257{ 0x1b, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },1258{ 0x1c, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },1259{ 0x1c, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },1260{ 0x1d, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },1261{ 0x1d, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },1262{ 0x1e, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },1263{ 0x1e, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },1264{ 0x1f, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },1265{ 0x1f, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },1266{ 0x20, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },1267{ 0x6d, 0x0000ffff, 0, 0x100, SISLANDS_CACCONFIG_CGIND },1268{ 0xFFFFFFFF }1269};12701271static const struct si_cac_config_reg cac_weights_mars_pro[] =1272{1273{ 0x0, 0x0000ffff, 0, 0x43, SISLANDS_CACCONFIG_CGIND },1274{ 0x0, 0xffff0000, 16, 0x29, SISLANDS_CACCONFIG_CGIND },1275{ 0x1, 0x0000ffff, 0, 0xAF, SISLANDS_CACCONFIG_CGIND },1276{ 0x1, 0xffff0000, 16, 0x2A, SISLANDS_CACCONFIG_CGIND },1277{ 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },1278{ 0x3, 0x0000ffff, 0, 0xA0, SISLANDS_CACCONFIG_CGIND },1279{ 0x3, 0xffff0000, 16, 0x29, SISLANDS_CACCONFIG_CGIND },1280{ 0x4, 0x0000ffff, 0, 0xA0, SISLANDS_CACCONFIG_CGIND },1281{ 0x4, 0xffff0000, 16, 0x59, SISLANDS_CACCONFIG_CGIND },1282{ 0x5, 0x0000ffff, 0, 0x1A5, SISLANDS_CACCONFIG_CGIND },1283{ 0x5, 0xffff0000, 16, 0x1D6, SISLANDS_CACCONFIG_CGIND },1284{ 0x6, 0x0000ffff, 0, 0x2A3, SISLANDS_CACCONFIG_CGIND },1285{ 0x6, 0xffff0000, 16, 0x8FD, SISLANDS_CACCONFIG_CGIND },1286{ 0x18f, 0x0000ffff, 0, 0x76, SISLANDS_CACCONFIG_CGIND },1287{ 0x7, 0x0000ffff, 0, 0x8A, SISLANDS_CACCONFIG_CGIND },1288{ 0x7, 0xffff0000, 16, 0xA3, SISLANDS_CACCONFIG_CGIND },1289{ 0x8, 0x0000ffff, 0, 0x71, SISLANDS_CACCONFIG_CGIND },1290{ 0x8, 0xffff0000, 16, 0x36, SISLANDS_CACCONFIG_CGIND },1291{ 0x9, 0x0000ffff, 0, 0xA6, SISLANDS_CACCONFIG_CGIND },1292{ 0xa, 0x0000ffff, 0, 0x81, SISLANDS_CACCONFIG_CGIND },1293{ 0xb, 0x0000ffff, 0, 0x3D2, SISLANDS_CACCONFIG_CGIND },1294{ 0xb, 0xffff0000, 16, 0x27C, SISLANDS_CACCONFIG_CGIND },1295{ 0xc, 0x0000ffff, 0, 0xA96, SISLANDS_CACCONFIG_CGIND },1296{ 0xd, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND },1297{ 0xd, 0xffff0000, 16, 0x5, SISLANDS_CACCONFIG_CGIND },1298{ 0xe, 0x0000ffff, 0, 0xB, SISLANDS_CACCONFIG_CGIND },1299{ 0xf, 0x0000ffff, 0, 0x3, SISLANDS_CACCONFIG_CGIND },1300{ 0xf, 0xffff0000, 16, 0x2, SISLANDS_CACCONFIG_CGIND },1301{ 0x10, 0x0000ffff, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1302{ 0x10, 0xffff0000, 16, 0x4, SISLANDS_CACCONFIG_CGIND },1303{ 0x11, 0x0000ffff, 0, 0x15, SISLANDS_CACCONFIG_CGIND },1304{ 0x11, 0xffff0000, 16, 0x7, SISLANDS_CACCONFIG_CGIND },1305{ 0x12, 0x0000ffff, 0, 0x36, SISLANDS_CACCONFIG_CGIND },1306{ 0x13, 0x0000ffff, 0, 0x10, SISLANDS_CACCONFIG_CGIND },1307{ 0x13, 0xffff0000, 16, 0x10, SISLANDS_CACCONFIG_CGIND },1308{ 0x14, 0x0000ffff, 0, 0x2, SISLANDS_CACCONFIG_CGIND },1309{ 0x15, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },1310{ 0x15, 0xffff0000, 16, 0x6, SISLANDS_CACCONFIG_CGIND },1311{ 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },1312{ 0x16, 0x0000ffff, 0, 0x32, SISLANDS_CACCONFIG_CGIND },1313{ 0x16, 0xffff0000, 16, 0x7E, SISLANDS_CACCONFIG_CGIND },1314{ 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },1315{ 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },1316{ 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },1317{ 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },1318{ 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },1319{ 0x1a, 0x0000ffff, 0, 0x280, SISLANDS_CACCONFIG_CGIND },1320{ 0x1a, 0xffff0000, 16, 0x7, SISLANDS_CACCONFIG_CGIND },1321{ 0x1b, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },1322{ 0x1b, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },1323{ 0x1c, 0x0000ffff, 0, 0x3C, SISLANDS_CACCONFIG_CGIND },1324{ 0x1c, 0xffff0000, 16, 0x203, SISLANDS_CACCONFIG_CGIND },1325{ 0x1d, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },1326{ 0x1d, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },1327{ 0x1e, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },1328{ 0x1e, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },1329{ 0x1f, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },1330{ 0x1f, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },1331{ 0x20, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },1332{ 0x6d, 0x0000ffff, 0, 0xB4, SISLANDS_CACCONFIG_CGIND },1333{ 0xFFFFFFFF }1334};13351336static const struct si_cac_config_reg cac_weights_mars_xt[] =1337{1338{ 0x0, 0x0000ffff, 0, 0x43, SISLANDS_CACCONFIG_CGIND },1339{ 0x0, 0xffff0000, 16, 0x29, SISLANDS_CACCONFIG_CGIND },1340{ 0x1, 0x0000ffff, 0, 0xAF, SISLANDS_CACCONFIG_CGIND },1341{ 0x1, 0xffff0000, 16, 0x2A, SISLANDS_CACCONFIG_CGIND },1342{ 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },1343{ 0x3, 0x0000ffff, 0, 0xA0, SISLANDS_CACCONFIG_CGIND },1344{ 0x3, 0xffff0000, 16, 0x29, SISLANDS_CACCONFIG_CGIND },1345{ 0x4, 0x0000ffff, 0, 0xA0, SISLANDS_CACCONFIG_CGIND },1346{ 0x4, 0xffff0000, 16, 0x59, SISLANDS_CACCONFIG_CGIND },1347{ 0x5, 0x0000ffff, 0, 0x1A5, SISLANDS_CACCONFIG_CGIND },1348{ 0x5, 0xffff0000, 16, 0x1D6, SISLANDS_CACCONFIG_CGIND },1349{ 0x6, 0x0000ffff, 0, 0x2A3, SISLANDS_CACCONFIG_CGIND },1350{ 0x6, 0xffff0000, 16, 0x8FD, SISLANDS_CACCONFIG_CGIND },1351{ 0x18f, 0x0000ffff, 0, 0x76, SISLANDS_CACCONFIG_CGIND },1352{ 0x7, 0x0000ffff, 0, 0x8A, SISLANDS_CACCONFIG_CGIND },1353{ 0x7, 0xffff0000, 16, 0xA3, SISLANDS_CACCONFIG_CGIND },1354{ 0x8, 0x0000ffff, 0, 0x71, SISLANDS_CACCONFIG_CGIND },1355{ 0x8, 0xffff0000, 16, 0x36, SISLANDS_CACCONFIG_CGIND },1356{ 0x9, 0x0000ffff, 0, 0xA6, SISLANDS_CACCONFIG_CGIND },1357{ 0xa, 0x0000ffff, 0, 0x81, SISLANDS_CACCONFIG_CGIND },1358{ 0xb, 0x0000ffff, 0, 0x3D2, SISLANDS_CACCONFIG_CGIND },1359{ 0xb, 0xffff0000, 16, 0x27C, SISLANDS_CACCONFIG_CGIND },1360{ 0xc, 0x0000ffff, 0, 0xA96, SISLANDS_CACCONFIG_CGIND },1361{ 0xd, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND },1362{ 0xd, 0xffff0000, 16, 0x5, SISLANDS_CACCONFIG_CGIND },1363{ 0xe, 0x0000ffff, 0, 0xB, SISLANDS_CACCONFIG_CGIND },1364{ 0xf, 0x0000ffff, 0, 0x3, SISLANDS_CACCONFIG_CGIND },1365{ 0xf, 0xffff0000, 16, 0x2, SISLANDS_CACCONFIG_CGIND },1366{ 0x10, 0x0000ffff, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1367{ 0x10, 0xffff0000, 16, 0x4, SISLANDS_CACCONFIG_CGIND },1368{ 0x11, 0x0000ffff, 0, 0x15, SISLANDS_CACCONFIG_CGIND },1369{ 0x11, 0xffff0000, 16, 0x7, SISLANDS_CACCONFIG_CGIND },1370{ 0x12, 0x0000ffff, 0, 0x36, SISLANDS_CACCONFIG_CGIND },1371{ 0x13, 0x0000ffff, 0, 0x10, SISLANDS_CACCONFIG_CGIND },1372{ 0x13, 0xffff0000, 16, 0x10, SISLANDS_CACCONFIG_CGIND },1373{ 0x14, 0x0000ffff, 0, 0x60, SISLANDS_CACCONFIG_CGIND },1374{ 0x15, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },1375{ 0x15, 0xffff0000, 16, 0x6, SISLANDS_CACCONFIG_CGIND },1376{ 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },1377{ 0x16, 0x0000ffff, 0, 0x32, SISLANDS_CACCONFIG_CGIND },1378{ 0x16, 0xffff0000, 16, 0x7E, SISLANDS_CACCONFIG_CGIND },1379{ 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },1380{ 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },1381{ 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },1382{ 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },1383{ 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },1384{ 0x1a, 0x0000ffff, 0, 0x280, SISLANDS_CACCONFIG_CGIND },1385{ 0x1a, 0xffff0000, 16, 0x7, SISLANDS_CACCONFIG_CGIND },1386{ 0x1b, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },1387{ 0x1b, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },1388{ 0x1c, 0x0000ffff, 0, 0x3C, SISLANDS_CACCONFIG_CGIND },1389{ 0x1c, 0xffff0000, 16, 0x203, SISLANDS_CACCONFIG_CGIND },1390{ 0x1d, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },1391{ 0x1d, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },1392{ 0x1e, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },1393{ 0x1e, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },1394{ 0x1f, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },1395{ 0x1f, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },1396{ 0x20, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },1397{ 0x6d, 0x0000ffff, 0, 0xB4, SISLANDS_CACCONFIG_CGIND },1398{ 0xFFFFFFFF }1399};14001401static const struct si_cac_config_reg cac_weights_oland_pro[] =1402{1403{ 0x0, 0x0000ffff, 0, 0x43, SISLANDS_CACCONFIG_CGIND },1404{ 0x0, 0xffff0000, 16, 0x29, SISLANDS_CACCONFIG_CGIND },1405{ 0x1, 0x0000ffff, 0, 0xAF, SISLANDS_CACCONFIG_CGIND },1406{ 0x1, 0xffff0000, 16, 0x2A, SISLANDS_CACCONFIG_CGIND },1407{ 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },1408{ 0x3, 0x0000ffff, 0, 0xA0, SISLANDS_CACCONFIG_CGIND },1409{ 0x3, 0xffff0000, 16, 0x29, SISLANDS_CACCONFIG_CGIND },1410{ 0x4, 0x0000ffff, 0, 0xA0, SISLANDS_CACCONFIG_CGIND },1411{ 0x4, 0xffff0000, 16, 0x59, SISLANDS_CACCONFIG_CGIND },1412{ 0x5, 0x0000ffff, 0, 0x1A5, SISLANDS_CACCONFIG_CGIND },1413{ 0x5, 0xffff0000, 16, 0x1D6, SISLANDS_CACCONFIG_CGIND },1414{ 0x6, 0x0000ffff, 0, 0x2A3, SISLANDS_CACCONFIG_CGIND },1415{ 0x6, 0xffff0000, 16, 0x8FD, SISLANDS_CACCONFIG_CGIND },1416{ 0x18f, 0x0000ffff, 0, 0x76, SISLANDS_CACCONFIG_CGIND },1417{ 0x7, 0x0000ffff, 0, 0x8A, SISLANDS_CACCONFIG_CGIND },1418{ 0x7, 0xffff0000, 16, 0xA3, SISLANDS_CACCONFIG_CGIND },1419{ 0x8, 0x0000ffff, 0, 0x71, SISLANDS_CACCONFIG_CGIND },1420{ 0x8, 0xffff0000, 16, 0x36, SISLANDS_CACCONFIG_CGIND },1421{ 0x9, 0x0000ffff, 0, 0xA6, SISLANDS_CACCONFIG_CGIND },1422{ 0xa, 0x0000ffff, 0, 0x81, SISLANDS_CACCONFIG_CGIND },1423{ 0xb, 0x0000ffff, 0, 0x3D2, SISLANDS_CACCONFIG_CGIND },1424{ 0xb, 0xffff0000, 16, 0x27C, SISLANDS_CACCONFIG_CGIND },1425{ 0xc, 0x0000ffff, 0, 0xA96, SISLANDS_CACCONFIG_CGIND },1426{ 0xd, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND },1427{ 0xd, 0xffff0000, 16, 0x5, SISLANDS_CACCONFIG_CGIND },1428{ 0xe, 0x0000ffff, 0, 0xB, SISLANDS_CACCONFIG_CGIND },1429{ 0xf, 0x0000ffff, 0, 0x3, SISLANDS_CACCONFIG_CGIND },1430{ 0xf, 0xffff0000, 16, 0x2, SISLANDS_CACCONFIG_CGIND },1431{ 0x10, 0x0000ffff, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1432{ 0x10, 0xffff0000, 16, 0x4, SISLANDS_CACCONFIG_CGIND },1433{ 0x11, 0x0000ffff, 0, 0x15, SISLANDS_CACCONFIG_CGIND },1434{ 0x11, 0xffff0000, 16, 0x7, SISLANDS_CACCONFIG_CGIND },1435{ 0x12, 0x0000ffff, 0, 0x36, SISLANDS_CACCONFIG_CGIND },1436{ 0x13, 0x0000ffff, 0, 0x10, SISLANDS_CACCONFIG_CGIND },1437{ 0x13, 0xffff0000, 16, 0x10, SISLANDS_CACCONFIG_CGIND },1438{ 0x14, 0x0000ffff, 0, 0x90, SISLANDS_CACCONFIG_CGIND },1439{ 0x15, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },1440{ 0x15, 0xffff0000, 16, 0x6, SISLANDS_CACCONFIG_CGIND },1441{ 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },1442{ 0x16, 0x0000ffff, 0, 0x32, SISLANDS_CACCONFIG_CGIND },1443{ 0x16, 0xffff0000, 16, 0x7E, SISLANDS_CACCONFIG_CGIND },1444{ 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },1445{ 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },1446{ 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },1447{ 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },1448{ 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },1449{ 0x1a, 0x0000ffff, 0, 0x280, SISLANDS_CACCONFIG_CGIND },1450{ 0x1a, 0xffff0000, 16, 0x7, SISLANDS_CACCONFIG_CGIND },1451{ 0x1b, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },1452{ 0x1b, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },1453{ 0x1c, 0x0000ffff, 0, 0x3C, SISLANDS_CACCONFIG_CGIND },1454{ 0x1c, 0xffff0000, 16, 0x203, SISLANDS_CACCONFIG_CGIND },1455{ 0x1d, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },1456{ 0x1d, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },1457{ 0x1e, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },1458{ 0x1e, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },1459{ 0x1f, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },1460{ 0x1f, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },1461{ 0x20, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },1462{ 0x6d, 0x0000ffff, 0, 0xB4, SISLANDS_CACCONFIG_CGIND },1463{ 0xFFFFFFFF }1464};14651466static const struct si_cac_config_reg cac_weights_oland_xt[] =1467{1468{ 0x0, 0x0000ffff, 0, 0x43, SISLANDS_CACCONFIG_CGIND },1469{ 0x0, 0xffff0000, 16, 0x29, SISLANDS_CACCONFIG_CGIND },1470{ 0x1, 0x0000ffff, 0, 0xAF, SISLANDS_CACCONFIG_CGIND },1471{ 0x1, 0xffff0000, 16, 0x2A, SISLANDS_CACCONFIG_CGIND },1472{ 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },1473{ 0x3, 0x0000ffff, 0, 0xA0, SISLANDS_CACCONFIG_CGIND },1474{ 0x3, 0xffff0000, 16, 0x29, SISLANDS_CACCONFIG_CGIND },1475{ 0x4, 0x0000ffff, 0, 0xA0, SISLANDS_CACCONFIG_CGIND },1476{ 0x4, 0xffff0000, 16, 0x59, SISLANDS_CACCONFIG_CGIND },1477{ 0x5, 0x0000ffff, 0, 0x1A5, SISLANDS_CACCONFIG_CGIND },1478{ 0x5, 0xffff0000, 16, 0x1D6, SISLANDS_CACCONFIG_CGIND },1479{ 0x6, 0x0000ffff, 0, 0x2A3, SISLANDS_CACCONFIG_CGIND },1480{ 0x6, 0xffff0000, 16, 0x8FD, SISLANDS_CACCONFIG_CGIND },1481{ 0x18f, 0x0000ffff, 0, 0x76, SISLANDS_CACCONFIG_CGIND },1482{ 0x7, 0x0000ffff, 0, 0x8A, SISLANDS_CACCONFIG_CGIND },1483{ 0x7, 0xffff0000, 16, 0xA3, SISLANDS_CACCONFIG_CGIND },1484{ 0x8, 0x0000ffff, 0, 0x71, SISLANDS_CACCONFIG_CGIND },1485{ 0x8, 0xffff0000, 16, 0x36, SISLANDS_CACCONFIG_CGIND },1486{ 0x9, 0x0000ffff, 0, 0xA6, SISLANDS_CACCONFIG_CGIND },1487{ 0xa, 0x0000ffff, 0, 0x81, SISLANDS_CACCONFIG_CGIND },1488{ 0xb, 0x0000ffff, 0, 0x3D2, SISLANDS_CACCONFIG_CGIND },1489{ 0xb, 0xffff0000, 16, 0x27C, SISLANDS_CACCONFIG_CGIND },1490{ 0xc, 0x0000ffff, 0, 0xA96, SISLANDS_CACCONFIG_CGIND },1491{ 0xd, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND },1492{ 0xd, 0xffff0000, 16, 0x5, SISLANDS_CACCONFIG_CGIND },1493{ 0xe, 0x0000ffff, 0, 0xB, SISLANDS_CACCONFIG_CGIND },1494{ 0xf, 0x0000ffff, 0, 0x3, SISLANDS_CACCONFIG_CGIND },1495{ 0xf, 0xffff0000, 16, 0x2, SISLANDS_CACCONFIG_CGIND },1496{ 0x10, 0x0000ffff, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1497{ 0x10, 0xffff0000, 16, 0x4, SISLANDS_CACCONFIG_CGIND },1498{ 0x11, 0x0000ffff, 0, 0x15, SISLANDS_CACCONFIG_CGIND },1499{ 0x11, 0xffff0000, 16, 0x7, SISLANDS_CACCONFIG_CGIND },1500{ 0x12, 0x0000ffff, 0, 0x36, SISLANDS_CACCONFIG_CGIND },1501{ 0x13, 0x0000ffff, 0, 0x10, SISLANDS_CACCONFIG_CGIND },1502{ 0x13, 0xffff0000, 16, 0x10, SISLANDS_CACCONFIG_CGIND },1503{ 0x14, 0x0000ffff, 0, 0x120, SISLANDS_CACCONFIG_CGIND },1504{ 0x15, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },1505{ 0x15, 0xffff0000, 16, 0x6, SISLANDS_CACCONFIG_CGIND },1506{ 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },1507{ 0x16, 0x0000ffff, 0, 0x32, SISLANDS_CACCONFIG_CGIND },1508{ 0x16, 0xffff0000, 16, 0x7E, SISLANDS_CACCONFIG_CGIND },1509{ 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },1510{ 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },1511{ 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },1512{ 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },1513{ 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },1514{ 0x1a, 0x0000ffff, 0, 0x280, SISLANDS_CACCONFIG_CGIND },1515{ 0x1a, 0xffff0000, 16, 0x7, SISLANDS_CACCONFIG_CGIND },1516{ 0x1b, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },1517{ 0x1b, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },1518{ 0x1c, 0x0000ffff, 0, 0x3C, SISLANDS_CACCONFIG_CGIND },1519{ 0x1c, 0xffff0000, 16, 0x203, SISLANDS_CACCONFIG_CGIND },1520{ 0x1d, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },1521{ 0x1d, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },1522{ 0x1e, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },1523{ 0x1e, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },1524{ 0x1f, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },1525{ 0x1f, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },1526{ 0x20, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },1527{ 0x6d, 0x0000ffff, 0, 0xB4, SISLANDS_CACCONFIG_CGIND },1528{ 0xFFFFFFFF }1529};15301531static const struct si_cac_config_reg lcac_oland[] =1532{1533{ 0x98, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },1534{ 0x98, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1535{ 0x104, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },1536{ 0x104, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1537{ 0x110, 0x0001fffe, 1, 0x6, SISLANDS_CACCONFIG_CGIND },1538{ 0x110, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1539{ 0x14f, 0x0001fffe, 1, 0x6, SISLANDS_CACCONFIG_CGIND },1540{ 0x14f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1541{ 0x8c, 0x0001fffe, 1, 0x6, SISLANDS_CACCONFIG_CGIND },1542{ 0x8c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1543{ 0x143, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND },1544{ 0x143, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1545{ 0x11c, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },1546{ 0x11c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1547{ 0x11f, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },1548{ 0x11f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1549{ 0x164, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },1550{ 0x164, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1551{ 0x167, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },1552{ 0x167, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1553{ 0x16a, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },1554{ 0x16a, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1555{ 0x15e, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },1556{ 0x15e, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1557{ 0x161, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },1558{ 0x161, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1559{ 0x15b, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },1560{ 0x15b, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1561{ 0x16d, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },1562{ 0x16d, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1563{ 0x170, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },1564{ 0x170, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1565{ 0x173, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },1566{ 0x173, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1567{ 0x176, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },1568{ 0x176, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1569{ 0x179, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },1570{ 0x179, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1571{ 0x17c, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },1572{ 0x17c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1573{ 0x17f, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },1574{ 0x17f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1575{ 0xFFFFFFFF }1576};15771578static const struct si_cac_config_reg lcac_mars_pro[] =1579{1580{ 0x98, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },1581{ 0x98, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1582{ 0x104, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },1583{ 0x104, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1584{ 0x110, 0x0001fffe, 1, 0x6, SISLANDS_CACCONFIG_CGIND },1585{ 0x110, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1586{ 0x14f, 0x0001fffe, 1, 0x6, SISLANDS_CACCONFIG_CGIND },1587{ 0x14f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1588{ 0x8c, 0x0001fffe, 1, 0x6, SISLANDS_CACCONFIG_CGIND },1589{ 0x8c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1590{ 0x143, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },1591{ 0x143, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1592{ 0x11c, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },1593{ 0x11c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1594{ 0x11f, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },1595{ 0x11f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1596{ 0x164, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },1597{ 0x164, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1598{ 0x167, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },1599{ 0x167, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1600{ 0x16a, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },1601{ 0x16a, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1602{ 0x15e, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },1603{ 0x15e, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1604{ 0x161, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },1605{ 0x161, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1606{ 0x15b, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },1607{ 0x15b, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1608{ 0x16d, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },1609{ 0x16d, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1610{ 0x170, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },1611{ 0x170, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1612{ 0x173, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },1613{ 0x173, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1614{ 0x176, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },1615{ 0x176, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1616{ 0x179, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },1617{ 0x179, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1618{ 0x17c, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },1619{ 0x17c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1620{ 0x17f, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },1621{ 0x17f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },1622{ 0xFFFFFFFF }1623};16241625static const struct si_cac_config_reg cac_override_oland[] =1626{1627{ 0xFFFFFFFF }1628};16291630static const struct si_powertune_data powertune_data_oland =1631{1632((1 << 16) | 0x6993),16335,16340,16357,1636105,1637{16380UL,16390UL,16407194395UL,1641309631529UL,1642-1270850L,16434513710L,16441001645},1646117830498UL,164712,1648{16490,16500,16510,16520,16530,16540,16550,165601657},1658true1659};16601661static const struct si_powertune_data powertune_data_mars_pro =1662{1663((1 << 16) | 0x6993),16645,16650,16667,1667105,1668{16690UL,16700UL,16717194395UL,1672309631529UL,1673-1270850L,16744513710L,16751001676},1677117830498UL,167812,1679{16800,16810,16820,16830,16840,16850,16860,168701688},1689true1690};16911692static const struct si_dte_data dte_data_oland =1693{1694{ 0, 0, 0, 0, 0 },1695{ 0, 0, 0, 0, 0 },16960,16970,16980,16990,17000,17010,17020,1703{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },1704{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },1705{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },17060,1707false1708};17091710static const struct si_dte_data dte_data_mars_pro =1711{1712{ 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0x0 },1713{ 0x0, 0x0, 0x0, 0x0, 0x0 },17145,171555000,1716105,17170xA,17181,17190,17200x10,1721{ 0x96, 0xB4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF },1722{ 0x895440, 0x3D0900, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680 },1723{ 0xF627, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 },172490,1725true1726};17271728static const struct si_dte_data dte_data_sun_xt =1729{1730{ 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0x0 },1731{ 0x0, 0x0, 0x0, 0x0, 0x0 },17325,173355000,1734105,17350xA,17361,17370,17380x10,1739{ 0x96, 0xB4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF },1740{ 0x895440, 0x3D0900, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680 },1741{ 0xD555, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 },174290,1743true1744};174517461747static const struct si_cac_config_reg cac_weights_hainan[] =1748{1749{ 0x0, 0x0000ffff, 0, 0x2d9, SISLANDS_CACCONFIG_CGIND },1750{ 0x0, 0xffff0000, 16, 0x22b, SISLANDS_CACCONFIG_CGIND },1751{ 0x1, 0x0000ffff, 0, 0x21c, SISLANDS_CACCONFIG_CGIND },1752{ 0x1, 0xffff0000, 16, 0x1dc, SISLANDS_CACCONFIG_CGIND },1753{ 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },1754{ 0x3, 0x0000ffff, 0, 0x24e, SISLANDS_CACCONFIG_CGIND },1755{ 0x3, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },1756{ 0x4, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },1757{ 0x4, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },1758{ 0x5, 0x0000ffff, 0, 0x35e, SISLANDS_CACCONFIG_CGIND },1759{ 0x5, 0xffff0000, 16, 0x1143, SISLANDS_CACCONFIG_CGIND },1760{ 0x6, 0x0000ffff, 0, 0xe17, SISLANDS_CACCONFIG_CGIND },1761{ 0x6, 0xffff0000, 16, 0x441, SISLANDS_CACCONFIG_CGIND },1762{ 0x18f, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },1763{ 0x7, 0x0000ffff, 0, 0x28b, SISLANDS_CACCONFIG_CGIND },1764{ 0x7, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },1765{ 0x8, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },1766{ 0x8, 0xffff0000, 16, 0xabe, SISLANDS_CACCONFIG_CGIND },1767{ 0x9, 0x0000ffff, 0, 0xf11, SISLANDS_CACCONFIG_CGIND },1768{ 0xa, 0x0000ffff, 0, 0x907, SISLANDS_CACCONFIG_CGIND },1769{ 0xb, 0x0000ffff, 0, 0xb45, SISLANDS_CACCONFIG_CGIND },1770{ 0xb, 0xffff0000, 16, 0xd1e, SISLANDS_CACCONFIG_CGIND },1771{ 0xc, 0x0000ffff, 0, 0xa2c, SISLANDS_CACCONFIG_CGIND },1772{ 0xd, 0x0000ffff, 0, 0x62, SISLANDS_CACCONFIG_CGIND },1773{ 0xd, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },1774{ 0xe, 0x0000ffff, 0, 0x1f3, SISLANDS_CACCONFIG_CGIND },1775{ 0xf, 0x0000ffff, 0, 0x42, SISLANDS_CACCONFIG_CGIND },1776{ 0xf, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },1777{ 0x10, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },1778{ 0x10, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },1779{ 0x11, 0x0000ffff, 0, 0x709, SISLANDS_CACCONFIG_CGIND },1780{ 0x11, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },1781{ 0x12, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },1782{ 0x13, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },1783{ 0x13, 0xffff0000, 16, 0x3a, SISLANDS_CACCONFIG_CGIND },1784{ 0x14, 0x0000ffff, 0, 0x357, SISLANDS_CACCONFIG_CGIND },1785{ 0x15, 0x0000ffff, 0, 0x9f, SISLANDS_CACCONFIG_CGIND },1786{ 0x15, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },1787{ 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },1788{ 0x16, 0x0000ffff, 0, 0x314, SISLANDS_CACCONFIG_CGIND },1789{ 0x16, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },1790{ 0x17, 0x0000ffff, 0, 0x6d, SISLANDS_CACCONFIG_CGIND },1791{ 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },1792{ 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },1793{ 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },1794{ 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },1795{ 0x1a, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },1796{ 0x1a, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },1797{ 0x1b, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },1798{ 0x1b, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },1799{ 0x1c, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },1800{ 0x1c, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },1801{ 0x1d, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },1802{ 0x1d, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },1803{ 0x1e, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },1804{ 0x1e, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },1805{ 0x1f, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },1806{ 0x1f, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },1807{ 0x20, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },1808{ 0x6d, 0x0000ffff, 0, 0x1b9, SISLANDS_CACCONFIG_CGIND },1809{ 0xFFFFFFFF }1810};18111812static const struct si_powertune_data powertune_data_hainan =1813{1814((1 << 16) | 0x6993),18155,18160,18179,1818105,1819{18200UL,18210UL,18227194395UL,1823309631529UL,1824-1270850L,18254513710L,18261001827},1828117830498UL,182912,1830{18310,18320,18330,18340,18350,18360,18370,183801839},1840true1841};18421843static struct rv7xx_power_info *rv770_get_pi(struct amdgpu_device *adev);1844static struct evergreen_power_info *evergreen_get_pi(struct amdgpu_device *adev);1845static struct ni_power_info *ni_get_pi(struct amdgpu_device *adev);1846static struct si_ps *si_get_ps(struct amdgpu_ps *rps);18471848static int si_populate_voltage_value(struct amdgpu_device *adev,1849const struct atom_voltage_table *table,1850u16 value, SISLANDS_SMC_VOLTAGE_VALUE *voltage);1851static int si_get_std_voltage_value(struct amdgpu_device *adev,1852SISLANDS_SMC_VOLTAGE_VALUE *voltage,1853u16 *std_voltage);1854static int si_write_smc_soft_register(struct amdgpu_device *adev,1855u16 reg_offset, u32 value);1856static int si_convert_power_level_to_smc(struct amdgpu_device *adev,1857struct rv7xx_pl *pl,1858SISLANDS_SMC_HW_PERFORMANCE_LEVEL *level);1859static int si_calculate_sclk_params(struct amdgpu_device *adev,1860u32 engine_clock,1861SISLANDS_SMC_SCLK_VALUE *sclk);18621863static void si_thermal_start_smc_fan_control(struct amdgpu_device *adev);1864static void si_fan_ctrl_set_default_mode(struct amdgpu_device *adev);1865static void si_dpm_set_irq_funcs(struct amdgpu_device *adev);18661867static struct si_power_info *si_get_pi(struct amdgpu_device *adev)1868{1869struct si_power_info *pi = adev->pm.dpm.priv;1870return pi;1871}18721873static void si_calculate_leakage_for_v_and_t_formula(const struct ni_leakage_coeffients *coeff,1874u16 v, s32 t, u32 ileakage, u32 *leakage)1875{1876s64 kt, kv, leakage_w, i_leakage, vddc;1877s64 temperature, t_slope, t_intercept, av, bv, t_ref;1878s64 tmp;18791880i_leakage = div64_s64(drm_int2fixp(ileakage), 100);1881vddc = div64_s64(drm_int2fixp(v), 1000);1882temperature = div64_s64(drm_int2fixp(t), 1000);18831884t_slope = div64_s64(drm_int2fixp(coeff->t_slope), 100000000);1885t_intercept = div64_s64(drm_int2fixp(coeff->t_intercept), 100000000);1886av = div64_s64(drm_int2fixp(coeff->av), 100000000);1887bv = div64_s64(drm_int2fixp(coeff->bv), 100000000);1888t_ref = drm_int2fixp(coeff->t_ref);18891890tmp = drm_fixp_mul(t_slope, vddc) + t_intercept;1891kt = drm_fixp_exp(drm_fixp_mul(tmp, temperature));1892kt = drm_fixp_div(kt, drm_fixp_exp(drm_fixp_mul(tmp, t_ref)));1893kv = drm_fixp_mul(av, drm_fixp_exp(drm_fixp_mul(bv, vddc)));18941895leakage_w = drm_fixp_mul(drm_fixp_mul(drm_fixp_mul(i_leakage, kt), kv), vddc);18961897*leakage = drm_fixp2int(leakage_w * 1000);1898}18991900static void si_calculate_leakage_for_v_and_t(struct amdgpu_device *adev,1901const struct ni_leakage_coeffients *coeff,1902u16 v,1903s32 t,1904u32 i_leakage,1905u32 *leakage)1906{1907si_calculate_leakage_for_v_and_t_formula(coeff, v, t, i_leakage, leakage);1908}19091910static void si_calculate_leakage_for_v_formula(const struct ni_leakage_coeffients *coeff,1911const u32 fixed_kt, u16 v,1912u32 ileakage, u32 *leakage)1913{1914s64 kt, kv, leakage_w, i_leakage, vddc;19151916i_leakage = div64_s64(drm_int2fixp(ileakage), 100);1917vddc = div64_s64(drm_int2fixp(v), 1000);19181919kt = div64_s64(drm_int2fixp(fixed_kt), 100000000);1920kv = drm_fixp_mul(div64_s64(drm_int2fixp(coeff->av), 100000000),1921drm_fixp_exp(drm_fixp_mul(div64_s64(drm_int2fixp(coeff->bv), 100000000), vddc)));19221923leakage_w = drm_fixp_mul(drm_fixp_mul(drm_fixp_mul(i_leakage, kt), kv), vddc);19241925*leakage = drm_fixp2int(leakage_w * 1000);1926}19271928static void si_calculate_leakage_for_v(struct amdgpu_device *adev,1929const struct ni_leakage_coeffients *coeff,1930const u32 fixed_kt,1931u16 v,1932u32 i_leakage,1933u32 *leakage)1934{1935si_calculate_leakage_for_v_formula(coeff, fixed_kt, v, i_leakage, leakage);1936}193719381939static void si_update_dte_from_pl2(struct amdgpu_device *adev,1940struct si_dte_data *dte_data)1941{1942u32 p_limit1 = adev->pm.dpm.tdp_limit;1943u32 p_limit2 = adev->pm.dpm.near_tdp_limit;1944u32 k = dte_data->k;1945u32 t_max = dte_data->max_t;1946u32 t_split[5] = { 10, 15, 20, 25, 30 };1947u32 t_0 = dte_data->t0;1948u32 i;19491950if (p_limit2 != 0 && p_limit2 <= p_limit1) {1951dte_data->tdep_count = 3;19521953for (i = 0; i < k; i++) {1954dte_data->r[i] =1955(t_split[i] * (t_max - t_0/(u32)1000) * (1 << 14)) /1956(p_limit2 * (u32)100);1957}19581959dte_data->tdep_r[1] = dte_data->r[4] * 2;19601961for (i = 2; i < SMC_SISLANDS_DTE_MAX_TEMPERATURE_DEPENDENT_ARRAY_SIZE; i++) {1962dte_data->tdep_r[i] = dte_data->r[4];1963}1964} else {1965DRM_ERROR("Invalid PL2! DTE will not be updated.\n");1966}1967}19681969static struct rv7xx_power_info *rv770_get_pi(struct amdgpu_device *adev)1970{1971struct rv7xx_power_info *pi = adev->pm.dpm.priv;19721973return pi;1974}19751976static struct ni_power_info *ni_get_pi(struct amdgpu_device *adev)1977{1978struct ni_power_info *pi = adev->pm.dpm.priv;19791980return pi;1981}19821983static struct si_ps *si_get_ps(struct amdgpu_ps *aps)1984{1985struct si_ps *ps = aps->ps_priv;19861987return ps;1988}19891990static void si_initialize_powertune_defaults(struct amdgpu_device *adev)1991{1992struct ni_power_info *ni_pi = ni_get_pi(adev);1993struct si_power_info *si_pi = si_get_pi(adev);1994bool update_dte_from_pl2 = false;19951996if (adev->asic_type == CHIP_TAHITI) {1997si_pi->cac_weights = cac_weights_tahiti;1998si_pi->lcac_config = lcac_tahiti;1999si_pi->cac_override = cac_override_tahiti;2000si_pi->powertune_data = &powertune_data_tahiti;2001si_pi->dte_data = dte_data_tahiti;20022003switch (adev->pdev->device) {2004case 0x6798:2005si_pi->dte_data.enable_dte_by_default = true;2006break;2007case 0x6799:2008si_pi->dte_data = dte_data_new_zealand;2009break;2010case 0x6790:2011case 0x6791:2012case 0x6792:2013case 0x679E:2014si_pi->dte_data = dte_data_aruba_pro;2015update_dte_from_pl2 = true;2016break;2017case 0x679B:2018si_pi->dte_data = dte_data_malta;2019update_dte_from_pl2 = true;2020break;2021case 0x679A:2022si_pi->dte_data = dte_data_tahiti_pro;2023update_dte_from_pl2 = true;2024break;2025default:2026if (si_pi->dte_data.enable_dte_by_default == true)2027DRM_ERROR("DTE is not enabled!\n");2028break;2029}2030} else if (adev->asic_type == CHIP_PITCAIRN) {2031si_pi->cac_weights = cac_weights_pitcairn;2032si_pi->lcac_config = lcac_pitcairn;2033si_pi->cac_override = cac_override_pitcairn;2034si_pi->powertune_data = &powertune_data_pitcairn;20352036switch (adev->pdev->device) {2037case 0x6810:2038case 0x6818:2039si_pi->dte_data = dte_data_curacao_xt;2040update_dte_from_pl2 = true;2041break;2042case 0x6819:2043case 0x6811:2044si_pi->dte_data = dte_data_curacao_pro;2045update_dte_from_pl2 = true;2046break;2047case 0x6800:2048case 0x6806:2049si_pi->dte_data = dte_data_neptune_xt;2050update_dte_from_pl2 = true;2051break;2052default:2053si_pi->dte_data = dte_data_pitcairn;2054break;2055}2056} else if (adev->asic_type == CHIP_VERDE) {2057si_pi->lcac_config = lcac_cape_verde;2058si_pi->cac_override = cac_override_cape_verde;2059si_pi->powertune_data = &powertune_data_cape_verde;20602061switch (adev->pdev->device) {2062case 0x683B:2063case 0x683F:2064case 0x6829:2065case 0x6835:2066si_pi->cac_weights = cac_weights_cape_verde_pro;2067si_pi->dte_data = dte_data_cape_verde;2068break;2069case 0x682C:2070si_pi->cac_weights = cac_weights_cape_verde_pro;2071si_pi->dte_data = dte_data_sun_xt;2072update_dte_from_pl2 = true;2073break;2074case 0x6825:2075case 0x6827:2076si_pi->cac_weights = cac_weights_heathrow;2077si_pi->dte_data = dte_data_cape_verde;2078break;2079case 0x6824:2080case 0x682D:2081si_pi->cac_weights = cac_weights_chelsea_xt;2082si_pi->dte_data = dte_data_cape_verde;2083break;2084case 0x682F:2085si_pi->cac_weights = cac_weights_chelsea_pro;2086si_pi->dte_data = dte_data_cape_verde;2087break;2088case 0x6820:2089si_pi->cac_weights = cac_weights_heathrow;2090si_pi->dte_data = dte_data_venus_xtx;2091break;2092case 0x6821:2093si_pi->cac_weights = cac_weights_heathrow;2094si_pi->dte_data = dte_data_venus_xt;2095break;2096case 0x6823:2097case 0x682B:2098case 0x6822:2099case 0x682A:2100si_pi->cac_weights = cac_weights_chelsea_pro;2101si_pi->dte_data = dte_data_venus_pro;2102break;2103default:2104si_pi->cac_weights = cac_weights_cape_verde;2105si_pi->dte_data = dte_data_cape_verde;2106break;2107}2108} else if (adev->asic_type == CHIP_OLAND) {2109si_pi->lcac_config = lcac_mars_pro;2110si_pi->cac_override = cac_override_oland;2111si_pi->powertune_data = &powertune_data_mars_pro;2112si_pi->dte_data = dte_data_mars_pro;21132114switch (adev->pdev->device) {2115case 0x6601:2116case 0x6621:2117case 0x6603:2118case 0x6605:2119si_pi->cac_weights = cac_weights_mars_pro;2120update_dte_from_pl2 = true;2121break;2122case 0x6600:2123case 0x6606:2124case 0x6620:2125case 0x6604:2126si_pi->cac_weights = cac_weights_mars_xt;2127update_dte_from_pl2 = true;2128break;2129case 0x6611:2130case 0x6613:2131case 0x6608:2132si_pi->cac_weights = cac_weights_oland_pro;2133update_dte_from_pl2 = true;2134break;2135case 0x6610:2136si_pi->cac_weights = cac_weights_oland_xt;2137update_dte_from_pl2 = true;2138break;2139default:2140si_pi->cac_weights = cac_weights_oland;2141si_pi->lcac_config = lcac_oland;2142si_pi->cac_override = cac_override_oland;2143si_pi->powertune_data = &powertune_data_oland;2144si_pi->dte_data = dte_data_oland;2145break;2146}2147} else if (adev->asic_type == CHIP_HAINAN) {2148si_pi->cac_weights = cac_weights_hainan;2149si_pi->lcac_config = lcac_oland;2150si_pi->cac_override = cac_override_oland;2151si_pi->powertune_data = &powertune_data_hainan;2152si_pi->dte_data = dte_data_sun_xt;2153update_dte_from_pl2 = true;2154} else {2155DRM_ERROR("Unknown SI asic revision, failed to initialize PowerTune!\n");2156return;2157}21582159ni_pi->enable_power_containment = false;2160ni_pi->enable_cac = false;2161ni_pi->enable_sq_ramping = false;2162si_pi->enable_dte = false;21632164if (si_pi->powertune_data->enable_powertune_by_default) {2165ni_pi->enable_power_containment = true;2166ni_pi->enable_cac = true;2167if (si_pi->dte_data.enable_dte_by_default) {2168si_pi->enable_dte = true;2169if (update_dte_from_pl2)2170si_update_dte_from_pl2(adev, &si_pi->dte_data);21712172}2173ni_pi->enable_sq_ramping = true;2174}21752176ni_pi->driver_calculate_cac_leakage = true;2177ni_pi->cac_configuration_required = true;21782179if (ni_pi->cac_configuration_required) {2180ni_pi->support_cac_long_term_average = true;2181si_pi->dyn_powertune_data.l2_lta_window_size =2182si_pi->powertune_data->l2_lta_window_size_default;2183si_pi->dyn_powertune_data.lts_truncate =2184si_pi->powertune_data->lts_truncate_default;2185} else {2186ni_pi->support_cac_long_term_average = false;2187si_pi->dyn_powertune_data.l2_lta_window_size = 0;2188si_pi->dyn_powertune_data.lts_truncate = 0;2189}21902191si_pi->dyn_powertune_data.disable_uvd_powertune = false;2192}21932194static u32 si_get_smc_power_scaling_factor(struct amdgpu_device *adev)2195{2196return 1;2197}21982199static u32 si_calculate_cac_wintime(struct amdgpu_device *adev)2200{2201u32 xclk;2202u32 wintime;2203u32 cac_window;2204u32 cac_window_size;22052206xclk = amdgpu_asic_get_xclk(adev);22072208if (xclk == 0)2209return 0;22102211cac_window = RREG32(mmCG_CAC_CTRL) & CG_CAC_CTRL__CAC_WINDOW_MASK;2212cac_window_size = ((cac_window & 0xFFFF0000) >> 16) * (cac_window & 0x0000FFFF);22132214wintime = (cac_window_size * 100) / xclk;22152216return wintime;2217}22182219static u32 si_scale_power_for_smc(u32 power_in_watts, u32 scaling_factor)2220{2221return power_in_watts;2222}22232224static int si_calculate_adjusted_tdp_limits(struct amdgpu_device *adev,2225bool adjust_polarity,2226u32 tdp_adjustment,2227u32 *tdp_limit,2228u32 *near_tdp_limit)2229{2230u32 adjustment_delta, max_tdp_limit;22312232if (tdp_adjustment > (u32)adev->pm.dpm.tdp_od_limit)2233return -EINVAL;22342235max_tdp_limit = ((100 + 100) * adev->pm.dpm.tdp_limit) / 100;22362237if (adjust_polarity) {2238*tdp_limit = ((100 + tdp_adjustment) * adev->pm.dpm.tdp_limit) / 100;2239*near_tdp_limit = adev->pm.dpm.near_tdp_limit_adjusted + (*tdp_limit - adev->pm.dpm.tdp_limit);2240} else {2241*tdp_limit = ((100 - tdp_adjustment) * adev->pm.dpm.tdp_limit) / 100;2242adjustment_delta = adev->pm.dpm.tdp_limit - *tdp_limit;2243if (adjustment_delta < adev->pm.dpm.near_tdp_limit_adjusted)2244*near_tdp_limit = adev->pm.dpm.near_tdp_limit_adjusted - adjustment_delta;2245else2246*near_tdp_limit = 0;2247}22482249if ((*tdp_limit <= 0) || (*tdp_limit > max_tdp_limit))2250return -EINVAL;2251if ((*near_tdp_limit <= 0) || (*near_tdp_limit > *tdp_limit))2252return -EINVAL;22532254return 0;2255}22562257static int si_populate_smc_tdp_limits(struct amdgpu_device *adev,2258struct amdgpu_ps *amdgpu_state)2259{2260struct ni_power_info *ni_pi = ni_get_pi(adev);2261struct si_power_info *si_pi = si_get_pi(adev);22622263if (ni_pi->enable_power_containment) {2264SISLANDS_SMC_STATETABLE *smc_table = &si_pi->smc_statetable;2265PP_SIslands_PAPMParameters *papm_parm;2266struct amdgpu_ppm_table *ppm = adev->pm.dpm.dyn_state.ppm_table;2267u32 scaling_factor = si_get_smc_power_scaling_factor(adev);2268u32 tdp_limit;2269u32 near_tdp_limit;2270int ret;22712272if (scaling_factor == 0)2273return -EINVAL;22742275ret = si_calculate_adjusted_tdp_limits(adev,2276false, /* ??? */2277adev->pm.dpm.tdp_adjustment,2278&tdp_limit,2279&near_tdp_limit);2280if (ret)2281return ret;22822283if (adev->pdev->device == 0x6611 && adev->pdev->revision == 0x87) {2284/* Workaround buggy powertune on Radeon 430 and 520. */2285tdp_limit = 32;2286near_tdp_limit = 28;2287}22882289smc_table->dpm2Params.TDPLimit =2290cpu_to_be32(si_scale_power_for_smc(tdp_limit, scaling_factor) * 1000);2291smc_table->dpm2Params.NearTDPLimit =2292cpu_to_be32(si_scale_power_for_smc(near_tdp_limit, scaling_factor) * 1000);2293smc_table->dpm2Params.SafePowerLimit =2294cpu_to_be32(si_scale_power_for_smc((near_tdp_limit * SISLANDS_DPM2_TDP_SAFE_LIMIT_PERCENT) / 100, scaling_factor) * 1000);22952296ret = amdgpu_si_copy_bytes_to_smc(adev,2297(si_pi->state_table_start + offsetof(SISLANDS_SMC_STATETABLE, dpm2Params) +2298offsetof(PP_SIslands_DPM2Parameters, TDPLimit)),2299(u8 *)(&(smc_table->dpm2Params.TDPLimit)),2300sizeof(u32) * 3,2301si_pi->sram_end);2302if (ret)2303return ret;23042305if (si_pi->enable_ppm) {2306papm_parm = &si_pi->papm_parm;2307memset(papm_parm, 0, sizeof(PP_SIslands_PAPMParameters));2308papm_parm->NearTDPLimitTherm = cpu_to_be32(ppm->dgpu_tdp);2309papm_parm->dGPU_T_Limit = cpu_to_be32(ppm->tj_max);2310papm_parm->dGPU_T_Warning = cpu_to_be32(95);2311papm_parm->dGPU_T_Hysteresis = cpu_to_be32(5);2312papm_parm->PlatformPowerLimit = 0xffffffff;2313papm_parm->NearTDPLimitPAPM = 0xffffffff;23142315ret = amdgpu_si_copy_bytes_to_smc(adev, si_pi->papm_cfg_table_start,2316(u8 *)papm_parm,2317sizeof(PP_SIslands_PAPMParameters),2318si_pi->sram_end);2319if (ret)2320return ret;2321}2322}2323return 0;2324}23252326static int si_populate_smc_tdp_limits_2(struct amdgpu_device *adev,2327struct amdgpu_ps *amdgpu_state)2328{2329struct ni_power_info *ni_pi = ni_get_pi(adev);2330struct si_power_info *si_pi = si_get_pi(adev);23312332if (ni_pi->enable_power_containment) {2333SISLANDS_SMC_STATETABLE *smc_table = &si_pi->smc_statetable;2334int ret;23352336ret = amdgpu_si_copy_bytes_to_smc(adev,2337(si_pi->state_table_start +2338offsetof(SISLANDS_SMC_STATETABLE, dpm2Params) +2339offsetof(PP_SIslands_DPM2Parameters, NearTDPLimit)),2340(u8 *)(&(smc_table->dpm2Params.NearTDPLimit)),2341sizeof(u32) * 2,2342si_pi->sram_end);2343if (ret)2344return ret;2345}23462347return 0;2348}23492350static u16 si_calculate_power_efficiency_ratio(struct amdgpu_device *adev,2351const u16 prev_std_vddc,2352const u16 curr_std_vddc)2353{2354u64 margin = (u64)SISLANDS_DPM2_PWREFFICIENCYRATIO_MARGIN;2355u64 prev_vddc = (u64)prev_std_vddc;2356u64 curr_vddc = (u64)curr_std_vddc;2357u64 pwr_efficiency_ratio, n, d;23582359if ((prev_vddc == 0) || (curr_vddc == 0))2360return 0;23612362n = div64_u64((u64)1024 * curr_vddc * curr_vddc * ((u64)1000 + margin), (u64)1000);2363d = prev_vddc * prev_vddc;2364pwr_efficiency_ratio = div64_u64(n, d);23652366if (pwr_efficiency_ratio > (u64)0xFFFF)2367return 0;23682369return (u16)pwr_efficiency_ratio;2370}23712372static bool si_should_disable_uvd_powertune(struct amdgpu_device *adev,2373struct amdgpu_ps *amdgpu_state)2374{2375struct si_power_info *si_pi = si_get_pi(adev);23762377if (si_pi->dyn_powertune_data.disable_uvd_powertune &&2378amdgpu_state->vclk && amdgpu_state->dclk)2379return true;23802381return false;2382}23832384struct evergreen_power_info *evergreen_get_pi(struct amdgpu_device *adev)2385{2386struct evergreen_power_info *pi = adev->pm.dpm.priv;23872388return pi;2389}23902391static int si_populate_power_containment_values(struct amdgpu_device *adev,2392struct amdgpu_ps *amdgpu_state,2393SISLANDS_SMC_SWSTATE *smc_state)2394{2395struct evergreen_power_info *eg_pi = evergreen_get_pi(adev);2396struct ni_power_info *ni_pi = ni_get_pi(adev);2397struct si_ps *state = si_get_ps(amdgpu_state);2398SISLANDS_SMC_VOLTAGE_VALUE vddc;2399u32 prev_sclk;2400u32 max_sclk;2401u32 min_sclk;2402u16 prev_std_vddc;2403u16 curr_std_vddc;2404int i;2405u16 pwr_efficiency_ratio;2406u8 max_ps_percent;2407bool disable_uvd_power_tune;2408int ret;24092410if (ni_pi->enable_power_containment == false)2411return 0;24122413if (state->performance_level_count == 0)2414return -EINVAL;24152416if (smc_state->levelCount != state->performance_level_count)2417return -EINVAL;24182419disable_uvd_power_tune = si_should_disable_uvd_powertune(adev, amdgpu_state);24202421smc_state->levels[0].dpm2.MaxPS = 0;2422smc_state->levels[0].dpm2.NearTDPDec = 0;2423smc_state->levels[0].dpm2.AboveSafeInc = 0;2424smc_state->levels[0].dpm2.BelowSafeInc = 0;2425smc_state->levels[0].dpm2.PwrEfficiencyRatio = 0;24262427for (i = 1; i < state->performance_level_count; i++) {2428prev_sclk = state->performance_levels[i-1].sclk;2429max_sclk = state->performance_levels[i].sclk;2430if (i == 1)2431max_ps_percent = SISLANDS_DPM2_MAXPS_PERCENT_M;2432else2433max_ps_percent = SISLANDS_DPM2_MAXPS_PERCENT_H;24342435if (prev_sclk > max_sclk)2436return -EINVAL;24372438if ((max_ps_percent == 0) ||2439(prev_sclk == max_sclk) ||2440disable_uvd_power_tune)2441min_sclk = max_sclk;2442else if (i == 1)2443min_sclk = prev_sclk;2444else2445min_sclk = (prev_sclk * (u32)max_ps_percent) / 100;24462447if (min_sclk < state->performance_levels[0].sclk)2448min_sclk = state->performance_levels[0].sclk;24492450if (min_sclk == 0)2451return -EINVAL;24522453ret = si_populate_voltage_value(adev, &eg_pi->vddc_voltage_table,2454state->performance_levels[i-1].vddc, &vddc);2455if (ret)2456return ret;24572458ret = si_get_std_voltage_value(adev, &vddc, &prev_std_vddc);2459if (ret)2460return ret;24612462ret = si_populate_voltage_value(adev, &eg_pi->vddc_voltage_table,2463state->performance_levels[i].vddc, &vddc);2464if (ret)2465return ret;24662467ret = si_get_std_voltage_value(adev, &vddc, &curr_std_vddc);2468if (ret)2469return ret;24702471pwr_efficiency_ratio = si_calculate_power_efficiency_ratio(adev,2472prev_std_vddc, curr_std_vddc);24732474smc_state->levels[i].dpm2.MaxPS = (u8)((SISLANDS_DPM2_MAX_PULSE_SKIP * (max_sclk - min_sclk)) / max_sclk);2475smc_state->levels[i].dpm2.NearTDPDec = SISLANDS_DPM2_NEAR_TDP_DEC;2476smc_state->levels[i].dpm2.AboveSafeInc = SISLANDS_DPM2_ABOVE_SAFE_INC;2477smc_state->levels[i].dpm2.BelowSafeInc = SISLANDS_DPM2_BELOW_SAFE_INC;2478smc_state->levels[i].dpm2.PwrEfficiencyRatio = cpu_to_be16(pwr_efficiency_ratio);2479}24802481return 0;2482}24832484static int si_populate_sq_ramping_values(struct amdgpu_device *adev,2485struct amdgpu_ps *amdgpu_state,2486SISLANDS_SMC_SWSTATE *smc_state)2487{2488struct ni_power_info *ni_pi = ni_get_pi(adev);2489struct si_ps *state = si_get_ps(amdgpu_state);2490u32 sq_power_throttle, sq_power_throttle2;2491bool enable_sq_ramping = ni_pi->enable_sq_ramping;2492int i;24932494if (state->performance_level_count == 0)2495return -EINVAL;24962497if (smc_state->levelCount != state->performance_level_count)2498return -EINVAL;24992500if (adev->pm.dpm.sq_ramping_threshold == 0)2501return -EINVAL;25022503if (SISLANDS_DPM2_SQ_RAMP_MAX_POWER > (SQ_POWER_THROTTLE__MAX_POWER_MASK >> SQ_POWER_THROTTLE__MAX_POWER__SHIFT))2504enable_sq_ramping = false;25052506if (SISLANDS_DPM2_SQ_RAMP_MIN_POWER > (SQ_POWER_THROTTLE__MIN_POWER_MASK >> SQ_POWER_THROTTLE__MIN_POWER__SHIFT))2507enable_sq_ramping = false;25082509if (SISLANDS_DPM2_SQ_RAMP_MAX_POWER_DELTA > (SQ_POWER_THROTTLE2__MAX_POWER_DELTA_MASK >> SQ_POWER_THROTTLE2__MAX_POWER_DELTA__SHIFT))2510enable_sq_ramping = false;25112512if (SISLANDS_DPM2_SQ_RAMP_STI_SIZE > (SQ_POWER_THROTTLE2__SHORT_TERM_INTERVAL_SIZE_MASK >> SQ_POWER_THROTTLE2__SHORT_TERM_INTERVAL_SIZE__SHIFT))2513enable_sq_ramping = false;25142515if (SISLANDS_DPM2_SQ_RAMP_LTI_RATIO > (SQ_POWER_THROTTLE2__LONG_TERM_INTERVAL_RATIO_MASK >> SQ_POWER_THROTTLE2__LONG_TERM_INTERVAL_RATIO__SHIFT))2516enable_sq_ramping = false;25172518for (i = 0; i < state->performance_level_count; i++) {2519sq_power_throttle = 0;2520sq_power_throttle2 = 0;25212522if ((state->performance_levels[i].sclk >= adev->pm.dpm.sq_ramping_threshold) &&2523enable_sq_ramping) {2524sq_power_throttle |= SISLANDS_DPM2_SQ_RAMP_MAX_POWER << SQ_POWER_THROTTLE__MAX_POWER__SHIFT;2525sq_power_throttle |= SISLANDS_DPM2_SQ_RAMP_MIN_POWER << SQ_POWER_THROTTLE__MIN_POWER__SHIFT;2526sq_power_throttle2 |= SISLANDS_DPM2_SQ_RAMP_MAX_POWER_DELTA << SQ_POWER_THROTTLE2__MAX_POWER_DELTA__SHIFT;2527sq_power_throttle2 |= SISLANDS_DPM2_SQ_RAMP_STI_SIZE << SQ_POWER_THROTTLE2__SHORT_TERM_INTERVAL_SIZE__SHIFT;2528sq_power_throttle2 |= SISLANDS_DPM2_SQ_RAMP_LTI_RATIO << SQ_POWER_THROTTLE2__LONG_TERM_INTERVAL_RATIO__SHIFT;2529} else {2530sq_power_throttle |= SQ_POWER_THROTTLE__MAX_POWER_MASK |2531SQ_POWER_THROTTLE__MIN_POWER_MASK;2532sq_power_throttle2 |= SQ_POWER_THROTTLE2__MAX_POWER_DELTA_MASK |2533SQ_POWER_THROTTLE2__SHORT_TERM_INTERVAL_SIZE_MASK |2534SQ_POWER_THROTTLE2__LONG_TERM_INTERVAL_RATIO_MASK;2535}25362537smc_state->levels[i].SQPowerThrottle = cpu_to_be32(sq_power_throttle);2538smc_state->levels[i].SQPowerThrottle_2 = cpu_to_be32(sq_power_throttle2);2539}25402541return 0;2542}25432544static int si_enable_power_containment(struct amdgpu_device *adev,2545struct amdgpu_ps *amdgpu_new_state,2546bool enable)2547{2548struct ni_power_info *ni_pi = ni_get_pi(adev);2549PPSMC_Result smc_result;2550int ret = 0;25512552if (ni_pi->enable_power_containment) {2553if (enable) {2554if (!si_should_disable_uvd_powertune(adev, amdgpu_new_state)) {2555smc_result = amdgpu_si_send_msg_to_smc(adev, PPSMC_TDPClampingActive);2556if (smc_result != PPSMC_Result_OK)2557ret = -EINVAL;2558}2559} else {2560smc_result = amdgpu_si_send_msg_to_smc(adev, PPSMC_TDPClampingInactive);2561if (smc_result != PPSMC_Result_OK)2562ret = -EINVAL;2563}2564}25652566return ret;2567}25682569static int si_initialize_smc_dte_tables(struct amdgpu_device *adev)2570{2571struct si_power_info *si_pi = si_get_pi(adev);2572int ret = 0;2573struct si_dte_data *dte_data = &si_pi->dte_data;2574Smc_SIslands_DTE_Configuration *dte_tables = NULL;2575u32 table_size;2576u8 tdep_count;2577u32 i;25782579if (dte_data == NULL)2580si_pi->enable_dte = false;25812582if (si_pi->enable_dte == false)2583return 0;25842585if (dte_data->k <= 0)2586return -EINVAL;25872588dte_tables = kzalloc(sizeof(Smc_SIslands_DTE_Configuration), GFP_KERNEL);2589if (dte_tables == NULL) {2590si_pi->enable_dte = false;2591return -ENOMEM;2592}25932594table_size = dte_data->k;25952596if (table_size > SMC_SISLANDS_DTE_MAX_FILTER_STAGES)2597table_size = SMC_SISLANDS_DTE_MAX_FILTER_STAGES;25982599tdep_count = dte_data->tdep_count;2600if (tdep_count > SMC_SISLANDS_DTE_MAX_TEMPERATURE_DEPENDENT_ARRAY_SIZE)2601tdep_count = SMC_SISLANDS_DTE_MAX_TEMPERATURE_DEPENDENT_ARRAY_SIZE;26022603dte_tables->K = cpu_to_be32(table_size);2604dte_tables->T0 = cpu_to_be32(dte_data->t0);2605dte_tables->MaxT = cpu_to_be32(dte_data->max_t);2606dte_tables->WindowSize = dte_data->window_size;2607dte_tables->temp_select = dte_data->temp_select;2608dte_tables->DTE_mode = dte_data->dte_mode;2609dte_tables->Tthreshold = cpu_to_be32(dte_data->t_threshold);26102611if (tdep_count > 0)2612table_size--;26132614for (i = 0; i < table_size; i++) {2615dte_tables->tau[i] = cpu_to_be32(dte_data->tau[i]);2616dte_tables->R[i] = cpu_to_be32(dte_data->r[i]);2617}26182619dte_tables->Tdep_count = tdep_count;26202621for (i = 0; i < (u32)tdep_count; i++) {2622dte_tables->T_limits[i] = dte_data->t_limits[i];2623dte_tables->Tdep_tau[i] = cpu_to_be32(dte_data->tdep_tau[i]);2624dte_tables->Tdep_R[i] = cpu_to_be32(dte_data->tdep_r[i]);2625}26262627ret = amdgpu_si_copy_bytes_to_smc(adev, si_pi->dte_table_start,2628(u8 *)dte_tables,2629sizeof(Smc_SIslands_DTE_Configuration),2630si_pi->sram_end);2631kfree(dte_tables);26322633return ret;2634}26352636static int si_get_cac_std_voltage_max_min(struct amdgpu_device *adev,2637u16 *max, u16 *min)2638{2639struct si_power_info *si_pi = si_get_pi(adev);2640struct amdgpu_cac_leakage_table *table =2641&adev->pm.dpm.dyn_state.cac_leakage_table;2642u32 i;2643u32 v0_loadline;26442645if (table == NULL)2646return -EINVAL;26472648*max = 0;2649*min = 0xFFFF;26502651for (i = 0; i < table->count; i++) {2652if (table->entries[i].vddc > *max)2653*max = table->entries[i].vddc;2654if (table->entries[i].vddc < *min)2655*min = table->entries[i].vddc;2656}26572658if (si_pi->powertune_data->lkge_lut_v0_percent > 100)2659return -EINVAL;26602661v0_loadline = (*min) * (100 - si_pi->powertune_data->lkge_lut_v0_percent) / 100;26622663if (v0_loadline > 0xFFFFUL)2664return -EINVAL;26652666*min = (u16)v0_loadline;26672668if ((*min > *max) || (*max == 0) || (*min == 0))2669return -EINVAL;26702671return 0;2672}26732674static u16 si_get_cac_std_voltage_step(u16 max, u16 min)2675{2676return ((max - min) + (SMC_SISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES - 1)) /2677SMC_SISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES;2678}26792680static int si_init_dte_leakage_table(struct amdgpu_device *adev,2681PP_SIslands_CacConfig *cac_tables,2682u16 vddc_max, u16 vddc_min, u16 vddc_step,2683u16 t0, u16 t_step)2684{2685struct si_power_info *si_pi = si_get_pi(adev);2686u32 leakage;2687unsigned int i, j;2688s32 t;2689u32 smc_leakage;2690u32 scaling_factor;2691u16 voltage;26922693scaling_factor = si_get_smc_power_scaling_factor(adev);26942695for (i = 0; i < SMC_SISLANDS_LKGE_LUT_NUM_OF_TEMP_ENTRIES ; i++) {2696t = (1000 * (i * t_step + t0));26972698for (j = 0; j < SMC_SISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES; j++) {2699voltage = vddc_max - (vddc_step * j);27002701si_calculate_leakage_for_v_and_t(adev,2702&si_pi->powertune_data->leakage_coefficients,2703voltage,2704t,2705si_pi->dyn_powertune_data.cac_leakage,2706&leakage);27072708smc_leakage = si_scale_power_for_smc(leakage, scaling_factor) / 4;27092710if (smc_leakage > 0xFFFF)2711smc_leakage = 0xFFFF;27122713cac_tables->cac_lkge_lut[i][SMC_SISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES-1-j] =2714cpu_to_be16((u16)smc_leakage);2715}2716}2717return 0;2718}27192720static int si_init_simplified_leakage_table(struct amdgpu_device *adev,2721PP_SIslands_CacConfig *cac_tables,2722u16 vddc_max, u16 vddc_min, u16 vddc_step)2723{2724struct si_power_info *si_pi = si_get_pi(adev);2725u32 leakage;2726unsigned int i, j;2727u32 smc_leakage;2728u32 scaling_factor;2729u16 voltage;27302731scaling_factor = si_get_smc_power_scaling_factor(adev);27322733for (j = 0; j < SMC_SISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES; j++) {2734voltage = vddc_max - (vddc_step * j);27352736si_calculate_leakage_for_v(adev,2737&si_pi->powertune_data->leakage_coefficients,2738si_pi->powertune_data->fixed_kt,2739voltage,2740si_pi->dyn_powertune_data.cac_leakage,2741&leakage);27422743smc_leakage = si_scale_power_for_smc(leakage, scaling_factor) / 4;27442745if (smc_leakage > 0xFFFF)2746smc_leakage = 0xFFFF;27472748for (i = 0; i < SMC_SISLANDS_LKGE_LUT_NUM_OF_TEMP_ENTRIES ; i++)2749cac_tables->cac_lkge_lut[i][SMC_SISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES-1-j] =2750cpu_to_be16((u16)smc_leakage);2751}2752return 0;2753}27542755static int si_initialize_smc_cac_tables(struct amdgpu_device *adev)2756{2757struct ni_power_info *ni_pi = ni_get_pi(adev);2758struct si_power_info *si_pi = si_get_pi(adev);2759PP_SIslands_CacConfig *cac_tables = NULL;2760u16 vddc_max, vddc_min, vddc_step;2761u16 t0, t_step;2762u32 load_line_slope, reg;2763int ret = 0;2764u32 ticks_per_us = amdgpu_asic_get_xclk(adev) / 100;27652766if (ni_pi->enable_cac == false)2767return 0;27682769cac_tables = kzalloc(sizeof(PP_SIslands_CacConfig), GFP_KERNEL);2770if (!cac_tables)2771return -ENOMEM;27722773reg = RREG32(mmCG_CAC_CTRL) & ~CG_CAC_CTRL__CAC_WINDOW_MASK;2774reg |= (si_pi->powertune_data->cac_window << CG_CAC_CTRL__CAC_WINDOW__SHIFT);2775WREG32(mmCG_CAC_CTRL, reg);27762777si_pi->dyn_powertune_data.cac_leakage = adev->pm.dpm.cac_leakage;2778si_pi->dyn_powertune_data.dc_pwr_value =2779si_pi->powertune_data->dc_cac[NISLANDS_DCCAC_LEVEL_0];2780si_pi->dyn_powertune_data.wintime = si_calculate_cac_wintime(adev);2781si_pi->dyn_powertune_data.shift_n = si_pi->powertune_data->shift_n_default;27822783si_pi->dyn_powertune_data.leakage_minimum_temperature = 80 * 1000;27842785ret = si_get_cac_std_voltage_max_min(adev, &vddc_max, &vddc_min);2786if (ret)2787goto done_free;27882789vddc_step = si_get_cac_std_voltage_step(vddc_max, vddc_min);2790vddc_min = vddc_max - (vddc_step * (SMC_SISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES - 1));2791t_step = 4;2792t0 = 60;27932794if (si_pi->enable_dte || ni_pi->driver_calculate_cac_leakage)2795ret = si_init_dte_leakage_table(adev, cac_tables,2796vddc_max, vddc_min, vddc_step,2797t0, t_step);2798else2799ret = si_init_simplified_leakage_table(adev, cac_tables,2800vddc_max, vddc_min, vddc_step);2801if (ret)2802goto done_free;28032804load_line_slope = ((u32)adev->pm.dpm.load_line_slope << SMC_SISLANDS_SCALE_R) / 100;28052806cac_tables->l2numWin_TDP = cpu_to_be32(si_pi->dyn_powertune_data.l2_lta_window_size);2807cac_tables->lts_truncate_n = si_pi->dyn_powertune_data.lts_truncate;2808cac_tables->SHIFT_N = si_pi->dyn_powertune_data.shift_n;2809cac_tables->lkge_lut_V0 = cpu_to_be32((u32)vddc_min);2810cac_tables->lkge_lut_Vstep = cpu_to_be32((u32)vddc_step);2811cac_tables->R_LL = cpu_to_be32(load_line_slope);2812cac_tables->WinTime = cpu_to_be32(si_pi->dyn_powertune_data.wintime);2813cac_tables->calculation_repeats = cpu_to_be32(2);2814cac_tables->dc_cac = cpu_to_be32(0);2815cac_tables->log2_PG_LKG_SCALE = 12;2816cac_tables->cac_temp = si_pi->powertune_data->operating_temp;2817cac_tables->lkge_lut_T0 = cpu_to_be32((u32)t0);2818cac_tables->lkge_lut_Tstep = cpu_to_be32((u32)t_step);28192820ret = amdgpu_si_copy_bytes_to_smc(adev, si_pi->cac_table_start,2821(u8 *)cac_tables,2822sizeof(PP_SIslands_CacConfig),2823si_pi->sram_end);28242825if (ret)2826goto done_free;28272828ret = si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_ticks_per_us, ticks_per_us);28292830done_free:2831if (ret) {2832ni_pi->enable_cac = false;2833ni_pi->enable_power_containment = false;2834}28352836kfree(cac_tables);28372838return ret;2839}28402841static int si_program_cac_config_registers(struct amdgpu_device *adev,2842const struct si_cac_config_reg *cac_config_regs)2843{2844const struct si_cac_config_reg *config_regs = cac_config_regs;2845u32 data = 0, offset;28462847if (!config_regs)2848return -EINVAL;28492850while (config_regs->offset != 0xFFFFFFFF) {2851switch (config_regs->type) {2852case SISLANDS_CACCONFIG_CGIND:2853offset = SMC_CG_IND_START + config_regs->offset;2854if (offset < SMC_CG_IND_END)2855data = RREG32_SMC(offset);2856break;2857default:2858data = RREG32(config_regs->offset);2859break;2860}28612862data &= ~config_regs->mask;2863data |= ((config_regs->value << config_regs->shift) & config_regs->mask);28642865switch (config_regs->type) {2866case SISLANDS_CACCONFIG_CGIND:2867offset = SMC_CG_IND_START + config_regs->offset;2868if (offset < SMC_CG_IND_END)2869WREG32_SMC(offset, data);2870break;2871default:2872WREG32(config_regs->offset, data);2873break;2874}2875config_regs++;2876}2877return 0;2878}28792880static int si_initialize_hardware_cac_manager(struct amdgpu_device *adev)2881{2882struct ni_power_info *ni_pi = ni_get_pi(adev);2883struct si_power_info *si_pi = si_get_pi(adev);2884int ret;28852886if ((ni_pi->enable_cac == false) ||2887(ni_pi->cac_configuration_required == false))2888return 0;28892890ret = si_program_cac_config_registers(adev, si_pi->lcac_config);2891if (ret)2892return ret;2893ret = si_program_cac_config_registers(adev, si_pi->cac_override);2894if (ret)2895return ret;2896ret = si_program_cac_config_registers(adev, si_pi->cac_weights);2897if (ret)2898return ret;28992900return 0;2901}29022903static int si_enable_smc_cac(struct amdgpu_device *adev,2904struct amdgpu_ps *amdgpu_new_state,2905bool enable)2906{2907struct ni_power_info *ni_pi = ni_get_pi(adev);2908struct si_power_info *si_pi = si_get_pi(adev);2909PPSMC_Result smc_result;2910int ret = 0;29112912if (ni_pi->enable_cac) {2913if (enable) {2914if (!si_should_disable_uvd_powertune(adev, amdgpu_new_state)) {2915if (ni_pi->support_cac_long_term_average) {2916smc_result = amdgpu_si_send_msg_to_smc(adev, PPSMC_CACLongTermAvgEnable);2917if (smc_result != PPSMC_Result_OK)2918ni_pi->support_cac_long_term_average = false;2919}29202921smc_result = amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_EnableCac);2922if (smc_result != PPSMC_Result_OK) {2923ret = -EINVAL;2924ni_pi->cac_enabled = false;2925} else {2926ni_pi->cac_enabled = true;2927}29282929if (si_pi->enable_dte) {2930smc_result = amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_EnableDTE);2931if (smc_result != PPSMC_Result_OK)2932ret = -EINVAL;2933}2934}2935} else if (ni_pi->cac_enabled) {2936if (si_pi->enable_dte)2937smc_result = amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_DisableDTE);29382939smc_result = amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_DisableCac);29402941ni_pi->cac_enabled = false;29422943if (ni_pi->support_cac_long_term_average)2944smc_result = amdgpu_si_send_msg_to_smc(adev, PPSMC_CACLongTermAvgDisable);2945}2946}2947return ret;2948}29492950static int si_init_smc_spll_table(struct amdgpu_device *adev)2951{2952struct ni_power_info *ni_pi = ni_get_pi(adev);2953struct si_power_info *si_pi = si_get_pi(adev);2954SMC_SISLANDS_SPLL_DIV_TABLE *spll_table;2955SISLANDS_SMC_SCLK_VALUE sclk_params;2956u32 fb_div, p_div;2957u32 clk_s, clk_v;2958u32 sclk = 0;2959int ret = 0;2960u32 tmp;2961int i;29622963if (si_pi->spll_table_start == 0)2964return -EINVAL;29652966spll_table = kzalloc(sizeof(SMC_SISLANDS_SPLL_DIV_TABLE), GFP_KERNEL);2967if (spll_table == NULL)2968return -ENOMEM;29692970for (i = 0; i < 256; i++) {2971ret = si_calculate_sclk_params(adev, sclk, &sclk_params);2972if (ret)2973break;2974p_div = (sclk_params.vCG_SPLL_FUNC_CNTL & CG_SPLL_FUNC_CNTL__SPLL_PDIV_A_MASK) >> CG_SPLL_FUNC_CNTL__SPLL_PDIV_A__SHIFT;2975fb_div = (sclk_params.vCG_SPLL_FUNC_CNTL_3 & CG_SPLL_FUNC_CNTL_3__SPLL_FB_DIV_MASK) >> CG_SPLL_FUNC_CNTL_3__SPLL_FB_DIV__SHIFT;2976clk_s = (sclk_params.vCG_SPLL_SPREAD_SPECTRUM & CG_SPLL_SPREAD_SPECTRUM__CLK_S_MASK) >> CG_SPLL_SPREAD_SPECTRUM__CLK_S__SHIFT;2977clk_v = (sclk_params.vCG_SPLL_SPREAD_SPECTRUM_2 & CG_SPLL_SPREAD_SPECTRUM_2__CLK_V_MASK) >> CG_SPLL_SPREAD_SPECTRUM_2__CLK_V__SHIFT;29782979fb_div &= ~0x00001FFF;2980fb_div >>= 1;2981clk_v >>= 6;29822983if (p_div & ~(SMC_SISLANDS_SPLL_DIV_TABLE_PDIV_MASK >> SMC_SISLANDS_SPLL_DIV_TABLE_PDIV_SHIFT))2984ret = -EINVAL;2985if (fb_div & ~(SMC_SISLANDS_SPLL_DIV_TABLE_FBDIV_MASK >> SMC_SISLANDS_SPLL_DIV_TABLE_FBDIV_SHIFT))2986ret = -EINVAL;2987if (clk_s & ~(SMC_SISLANDS_SPLL_DIV_TABLE_CLKS_MASK >> SMC_SISLANDS_SPLL_DIV_TABLE_CLKS_SHIFT))2988ret = -EINVAL;2989if (clk_v & ~(SMC_SISLANDS_SPLL_DIV_TABLE_CLKV_MASK >> SMC_SISLANDS_SPLL_DIV_TABLE_CLKV_SHIFT))2990ret = -EINVAL;29912992if (ret)2993break;29942995tmp = ((fb_div << SMC_SISLANDS_SPLL_DIV_TABLE_FBDIV_SHIFT) & SMC_SISLANDS_SPLL_DIV_TABLE_FBDIV_MASK) |2996((p_div << SMC_SISLANDS_SPLL_DIV_TABLE_PDIV_SHIFT) & SMC_SISLANDS_SPLL_DIV_TABLE_PDIV_MASK);2997spll_table->freq[i] = cpu_to_be32(tmp);29982999tmp = ((clk_v << SMC_SISLANDS_SPLL_DIV_TABLE_CLKV_SHIFT) & SMC_SISLANDS_SPLL_DIV_TABLE_CLKV_MASK) |3000((clk_s << SMC_SISLANDS_SPLL_DIV_TABLE_CLKS_SHIFT) & SMC_SISLANDS_SPLL_DIV_TABLE_CLKS_MASK);3001spll_table->ss[i] = cpu_to_be32(tmp);30023003sclk += 512;3004}300530063007if (!ret)3008ret = amdgpu_si_copy_bytes_to_smc(adev, si_pi->spll_table_start,3009(u8 *)spll_table,3010sizeof(SMC_SISLANDS_SPLL_DIV_TABLE),3011si_pi->sram_end);30123013if (ret)3014ni_pi->enable_power_containment = false;30153016kfree(spll_table);30173018return ret;3019}30203021static u16 si_get_lower_of_leakage_and_vce_voltage(struct amdgpu_device *adev,3022u16 vce_voltage)3023{3024u16 highest_leakage = 0;3025struct si_power_info *si_pi = si_get_pi(adev);3026int i;30273028for (i = 0; i < si_pi->leakage_voltage.count; i++){3029if (highest_leakage < si_pi->leakage_voltage.entries[i].voltage)3030highest_leakage = si_pi->leakage_voltage.entries[i].voltage;3031}30323033if (si_pi->leakage_voltage.count && (highest_leakage < vce_voltage))3034return highest_leakage;30353036return vce_voltage;3037}30383039static int si_get_vce_clock_voltage(struct amdgpu_device *adev,3040u32 evclk, u32 ecclk, u16 *voltage)3041{3042u32 i;3043int ret = -EINVAL;3044struct amdgpu_vce_clock_voltage_dependency_table *table =3045&adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table;30463047if (((evclk == 0) && (ecclk == 0)) ||3048(table && (table->count == 0))) {3049*voltage = 0;3050return 0;3051}30523053for (i = 0; i < table->count; i++) {3054if ((evclk <= table->entries[i].evclk) &&3055(ecclk <= table->entries[i].ecclk)) {3056*voltage = table->entries[i].v;3057ret = 0;3058break;3059}3060}30613062/* if no match return the highest voltage */3063if (ret)3064*voltage = table->entries[table->count - 1].v;30653066*voltage = si_get_lower_of_leakage_and_vce_voltage(adev, *voltage);30673068return ret;3069}30703071static bool si_dpm_vblank_too_short(void *handle)3072{3073struct amdgpu_device *adev = (struct amdgpu_device *)handle;3074u32 vblank_time = adev->pm.pm_display_cfg.min_vblank_time;3075/* we never hit the non-gddr5 limit so disable it */3076u32 switch_limit = adev->gmc.vram_type == AMDGPU_VRAM_TYPE_GDDR5 ? 450 : 0;30773078/* Consider zero vblank time too short and disable MCLK switching.3079* Note that the vblank time is set to maximum when no displays are attached,3080* so we'll still enable MCLK switching in that case.3081*/3082if (vblank_time == 0)3083return true;3084else if (vblank_time < switch_limit)3085return true;3086else3087return false;30883089}30903091static int ni_copy_and_switch_arb_sets(struct amdgpu_device *adev,3092u32 arb_freq_src, u32 arb_freq_dest)3093{3094u32 mc_arb_dram_timing;3095u32 mc_arb_dram_timing2;3096u32 burst_time;3097u32 mc_cg_config;30983099switch (arb_freq_src) {3100case MC_CG_ARB_FREQ_F0:3101mc_arb_dram_timing = RREG32(MC_ARB_DRAM_TIMING);3102mc_arb_dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2);3103burst_time = (RREG32(MC_ARB_BURST_TIME) & STATE0_MASK) >> STATE0_SHIFT;3104break;3105case MC_CG_ARB_FREQ_F1:3106mc_arb_dram_timing = RREG32(MC_ARB_DRAM_TIMING_1);3107mc_arb_dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2_1);3108burst_time = (RREG32(MC_ARB_BURST_TIME) & STATE1_MASK) >> STATE1_SHIFT;3109break;3110case MC_CG_ARB_FREQ_F2:3111mc_arb_dram_timing = RREG32(MC_ARB_DRAM_TIMING_2);3112mc_arb_dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2_2);3113burst_time = (RREG32(MC_ARB_BURST_TIME) & STATE2_MASK) >> STATE2_SHIFT;3114break;3115case MC_CG_ARB_FREQ_F3:3116mc_arb_dram_timing = RREG32(MC_ARB_DRAM_TIMING_3);3117mc_arb_dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2_3);3118burst_time = (RREG32(MC_ARB_BURST_TIME) & STATE3_MASK) >> STATE3_SHIFT;3119break;3120default:3121return -EINVAL;3122}31233124switch (arb_freq_dest) {3125case MC_CG_ARB_FREQ_F0:3126WREG32(MC_ARB_DRAM_TIMING, mc_arb_dram_timing);3127WREG32(MC_ARB_DRAM_TIMING2, mc_arb_dram_timing2);3128WREG32_P(MC_ARB_BURST_TIME, STATE0(burst_time), ~STATE0_MASK);3129break;3130case MC_CG_ARB_FREQ_F1:3131WREG32(MC_ARB_DRAM_TIMING_1, mc_arb_dram_timing);3132WREG32(MC_ARB_DRAM_TIMING2_1, mc_arb_dram_timing2);3133WREG32_P(MC_ARB_BURST_TIME, STATE1(burst_time), ~STATE1_MASK);3134break;3135case MC_CG_ARB_FREQ_F2:3136WREG32(MC_ARB_DRAM_TIMING_2, mc_arb_dram_timing);3137WREG32(MC_ARB_DRAM_TIMING2_2, mc_arb_dram_timing2);3138WREG32_P(MC_ARB_BURST_TIME, STATE2(burst_time), ~STATE2_MASK);3139break;3140case MC_CG_ARB_FREQ_F3:3141WREG32(MC_ARB_DRAM_TIMING_3, mc_arb_dram_timing);3142WREG32(MC_ARB_DRAM_TIMING2_3, mc_arb_dram_timing2);3143WREG32_P(MC_ARB_BURST_TIME, STATE3(burst_time), ~STATE3_MASK);3144break;3145default:3146return -EINVAL;3147}31483149mc_cg_config = RREG32(MC_CG_CONFIG) | 0x0000000F;3150WREG32(MC_CG_CONFIG, mc_cg_config);3151WREG32_P(MC_ARB_CG, CG_ARB_REQ(arb_freq_dest), ~CG_ARB_REQ_MASK);31523153return 0;3154}31553156static void ni_update_current_ps(struct amdgpu_device *adev,3157struct amdgpu_ps *rps)3158{3159struct si_ps *new_ps = si_get_ps(rps);3160struct evergreen_power_info *eg_pi = evergreen_get_pi(adev);3161struct ni_power_info *ni_pi = ni_get_pi(adev);31623163eg_pi->current_rps = *rps;3164ni_pi->current_ps = *new_ps;3165eg_pi->current_rps.ps_priv = &ni_pi->current_ps;3166adev->pm.dpm.current_ps = &eg_pi->current_rps;3167}31683169static void ni_update_requested_ps(struct amdgpu_device *adev,3170struct amdgpu_ps *rps)3171{3172struct si_ps *new_ps = si_get_ps(rps);3173struct evergreen_power_info *eg_pi = evergreen_get_pi(adev);3174struct ni_power_info *ni_pi = ni_get_pi(adev);31753176eg_pi->requested_rps = *rps;3177ni_pi->requested_ps = *new_ps;3178eg_pi->requested_rps.ps_priv = &ni_pi->requested_ps;3179adev->pm.dpm.requested_ps = &eg_pi->requested_rps;3180}31813182static void ni_set_uvd_clock_before_set_eng_clock(struct amdgpu_device *adev,3183struct amdgpu_ps *new_ps,3184struct amdgpu_ps *old_ps)3185{3186struct si_ps *new_state = si_get_ps(new_ps);3187struct si_ps *current_state = si_get_ps(old_ps);31883189if ((new_ps->vclk == old_ps->vclk) &&3190(new_ps->dclk == old_ps->dclk))3191return;31923193if (new_state->performance_levels[new_state->performance_level_count - 1].sclk >=3194current_state->performance_levels[current_state->performance_level_count - 1].sclk)3195return;31963197amdgpu_asic_set_uvd_clocks(adev, new_ps->vclk, new_ps->dclk);3198}31993200static void ni_set_uvd_clock_after_set_eng_clock(struct amdgpu_device *adev,3201struct amdgpu_ps *new_ps,3202struct amdgpu_ps *old_ps)3203{3204struct si_ps *new_state = si_get_ps(new_ps);3205struct si_ps *current_state = si_get_ps(old_ps);32063207if ((new_ps->vclk == old_ps->vclk) &&3208(new_ps->dclk == old_ps->dclk))3209return;32103211if (new_state->performance_levels[new_state->performance_level_count - 1].sclk <3212current_state->performance_levels[current_state->performance_level_count - 1].sclk)3213return;32143215amdgpu_asic_set_uvd_clocks(adev, new_ps->vclk, new_ps->dclk);3216}32173218static u16 btc_find_voltage(struct atom_voltage_table *table, u16 voltage)3219{3220unsigned int i;32213222for (i = 0; i < table->count; i++)3223if (voltage <= table->entries[i].value)3224return table->entries[i].value;32253226return table->entries[table->count - 1].value;3227}32283229static u32 btc_find_valid_clock(struct amdgpu_clock_array *clocks,3230u32 max_clock, u32 requested_clock)3231{3232unsigned int i;32333234if ((clocks == NULL) || (clocks->count == 0))3235return (requested_clock < max_clock) ? requested_clock : max_clock;32363237for (i = 0; i < clocks->count; i++) {3238if (clocks->values[i] >= requested_clock)3239return (clocks->values[i] < max_clock) ? clocks->values[i] : max_clock;3240}32413242return (clocks->values[clocks->count - 1] < max_clock) ?3243clocks->values[clocks->count - 1] : max_clock;3244}32453246static u32 btc_get_valid_mclk(struct amdgpu_device *adev,3247u32 max_mclk, u32 requested_mclk)3248{3249return btc_find_valid_clock(&adev->pm.dpm.dyn_state.valid_mclk_values,3250max_mclk, requested_mclk);3251}32523253static u32 btc_get_valid_sclk(struct amdgpu_device *adev,3254u32 max_sclk, u32 requested_sclk)3255{3256return btc_find_valid_clock(&adev->pm.dpm.dyn_state.valid_sclk_values,3257max_sclk, requested_sclk);3258}32593260static void btc_get_max_clock_from_voltage_dependency_table(struct amdgpu_clock_voltage_dependency_table *table,3261u32 *max_clock)3262{3263u32 i, clock = 0;32643265if ((table == NULL) || (table->count == 0)) {3266*max_clock = clock;3267return;3268}32693270for (i = 0; i < table->count; i++) {3271if (clock < table->entries[i].clk)3272clock = table->entries[i].clk;3273}3274*max_clock = clock;3275}32763277static void btc_apply_voltage_dependency_rules(struct amdgpu_clock_voltage_dependency_table *table,3278u32 clock, u16 max_voltage, u16 *voltage)3279{3280u32 i;32813282if ((table == NULL) || (table->count == 0))3283return;32843285for (i= 0; i < table->count; i++) {3286if (clock <= table->entries[i].clk) {3287if (*voltage < table->entries[i].v)3288*voltage = (u16)((table->entries[i].v < max_voltage) ?3289table->entries[i].v : max_voltage);3290return;3291}3292}32933294*voltage = (*voltage > max_voltage) ? *voltage : max_voltage;3295}32963297static void btc_adjust_clock_combinations(struct amdgpu_device *adev,3298const struct amdgpu_clock_and_voltage_limits *max_limits,3299struct rv7xx_pl *pl)3300{33013302if ((pl->mclk == 0) || (pl->sclk == 0))3303return;33043305if (pl->mclk == pl->sclk)3306return;33073308if (pl->mclk > pl->sclk) {3309if (((pl->mclk + (pl->sclk - 1)) / pl->sclk) > adev->pm.dpm.dyn_state.mclk_sclk_ratio)3310pl->sclk = btc_get_valid_sclk(adev,3311max_limits->sclk,3312(pl->mclk +3313(adev->pm.dpm.dyn_state.mclk_sclk_ratio - 1)) /3314adev->pm.dpm.dyn_state.mclk_sclk_ratio);3315} else {3316if ((pl->sclk - pl->mclk) > adev->pm.dpm.dyn_state.sclk_mclk_delta)3317pl->mclk = btc_get_valid_mclk(adev,3318max_limits->mclk,3319pl->sclk -3320adev->pm.dpm.dyn_state.sclk_mclk_delta);3321}3322}33233324static void btc_apply_voltage_delta_rules(struct amdgpu_device *adev,3325u16 max_vddc, u16 max_vddci,3326u16 *vddc, u16 *vddci)3327{3328struct evergreen_power_info *eg_pi = evergreen_get_pi(adev);3329u16 new_voltage;33303331if ((0 == *vddc) || (0 == *vddci))3332return;33333334if (*vddc > *vddci) {3335if ((*vddc - *vddci) > adev->pm.dpm.dyn_state.vddc_vddci_delta) {3336new_voltage = btc_find_voltage(&eg_pi->vddci_voltage_table,3337(*vddc - adev->pm.dpm.dyn_state.vddc_vddci_delta));3338*vddci = (new_voltage < max_vddci) ? new_voltage : max_vddci;3339}3340} else {3341if ((*vddci - *vddc) > adev->pm.dpm.dyn_state.vddc_vddci_delta) {3342new_voltage = btc_find_voltage(&eg_pi->vddc_voltage_table,3343(*vddci - adev->pm.dpm.dyn_state.vddc_vddci_delta));3344*vddc = (new_voltage < max_vddc) ? new_voltage : max_vddc;3345}3346}3347}33483349static void r600_calculate_u_and_p(u32 i, u32 r_c, u32 p_b,3350u32 *p, u32 *u)3351{3352u32 b_c = 0;3353u32 i_c;3354u32 tmp;33553356i_c = (i * r_c) / 100;3357tmp = i_c >> p_b;33583359while (tmp) {3360b_c++;3361tmp >>= 1;3362}33633364*u = (b_c + 1) / 2;3365*p = i_c / (1 << (2 * (*u)));3366}33673368static int r600_calculate_at(u32 t, u32 h, u32 fh, u32 fl, u32 *tl, u32 *th)3369{3370u32 k, a, ah, al;3371u32 t1;33723373if ((fl == 0) || (fh == 0) || (fl > fh))3374return -EINVAL;33753376k = (100 * fh) / fl;3377t1 = (t * (k - 100));3378a = (1000 * (100 * h + t1)) / (10000 + (t1 / 100));3379a = (a + 5) / 10;3380ah = ((a * t) + 5000) / 10000;3381al = a - ah;33823383*th = t - ah;3384*tl = t + al;33853386return 0;3387}33883389static bool r600_is_uvd_state(u32 class, u32 class2)3390{3391if (class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE)3392return true;3393if (class & ATOM_PPLIB_CLASSIFICATION_HD2STATE)3394return true;3395if (class & ATOM_PPLIB_CLASSIFICATION_HDSTATE)3396return true;3397if (class & ATOM_PPLIB_CLASSIFICATION_SDSTATE)3398return true;3399if (class2 & ATOM_PPLIB_CLASSIFICATION2_MVC)3400return true;3401return false;3402}34033404static u8 rv770_get_memory_module_index(struct amdgpu_device *adev)3405{3406return (u8) ((RREG32(BIOS_SCRATCH_4) >> 16) & 0xff);3407}34083409static void rv770_get_max_vddc(struct amdgpu_device *adev)3410{3411struct rv7xx_power_info *pi = rv770_get_pi(adev);3412u16 vddc;34133414if (amdgpu_atombios_get_max_vddc(adev, 0, 0, &vddc))3415pi->max_vddc = 0;3416else3417pi->max_vddc = vddc;3418}34193420static void rv770_get_engine_memory_ss(struct amdgpu_device *adev)3421{3422struct rv7xx_power_info *pi = rv770_get_pi(adev);3423struct amdgpu_atom_ss ss;34243425pi->sclk_ss = amdgpu_atombios_get_asic_ss_info(adev, &ss,3426ASIC_INTERNAL_ENGINE_SS, 0);3427pi->mclk_ss = amdgpu_atombios_get_asic_ss_info(adev, &ss,3428ASIC_INTERNAL_MEMORY_SS, 0);34293430if (pi->sclk_ss || pi->mclk_ss)3431pi->dynamic_ss = true;3432else3433pi->dynamic_ss = false;3434}343534363437static void si_apply_state_adjust_rules(struct amdgpu_device *adev,3438struct amdgpu_ps *rps)3439{3440const struct amd_pp_display_configuration *display_cfg =3441&adev->pm.pm_display_cfg;3442struct si_ps *ps = si_get_ps(rps);3443struct amdgpu_clock_and_voltage_limits *max_limits;3444bool disable_mclk_switching = false;3445bool disable_sclk_switching = false;3446u32 mclk, sclk;3447u16 vddc, vddci, min_vce_voltage = 0;3448u32 max_sclk_vddc, max_mclk_vddci, max_mclk_vddc;3449u32 max_sclk = 0, max_mclk = 0;3450u32 high_pixelclock_count = 0;3451int i;34523453if (adev->asic_type == CHIP_HAINAN) {3454if ((adev->pdev->revision == 0x81) ||3455(adev->pdev->revision == 0xC3) ||3456(adev->pdev->device == 0x6664) ||3457(adev->pdev->device == 0x6665) ||3458(adev->pdev->device == 0x6667)) {3459max_sclk = 75000;3460}3461if ((adev->pdev->revision == 0xC3) ||3462(adev->pdev->device == 0x6665)) {3463max_sclk = 60000;3464max_mclk = 80000;3465}3466} else if (adev->asic_type == CHIP_OLAND) {3467if ((adev->pdev->revision == 0xC7) ||3468(adev->pdev->revision == 0x80) ||3469(adev->pdev->revision == 0x81) ||3470(adev->pdev->revision == 0x83) ||3471(adev->pdev->revision == 0x87 &&3472adev->pdev->device != 0x6611) ||3473(adev->pdev->device == 0x6604) ||3474(adev->pdev->device == 0x6605)) {3475max_sclk = 75000;3476} else if (adev->pdev->revision == 0x87 &&3477adev->pdev->device == 0x6611) {3478/* Radeon 430 and 520 */3479max_sclk = 78000;3480}3481}34823483/* We define "high pixelclock" for SI as higher than necessary for 4K 30Hz.3484* For example, 4K 60Hz and 1080p 144Hz fall into this category.3485* Find number of such displays connected.3486*/3487for (i = 0; i < display_cfg->num_display; i++) {3488/* The array only contains active displays. */3489if (display_cfg->displays[i].pixel_clock > 297000)3490high_pixelclock_count++;3491}34923493/* These are some ad-hoc fixes to some issues observed with SI GPUs.3494* They are necessary because we don't have something like dce_calcs3495* for these GPUs to calculate bandwidth requirements.3496*/3497if (high_pixelclock_count) {3498/* Work around flickering lines at the bottom edge3499* of the screen when using a single 4K 60Hz monitor.3500*/3501disable_mclk_switching = true;35023503/* On Oland, we observe some flickering when two 4K 60Hz3504* displays are connected, possibly because voltage is too low.3505* Raise the voltage by requiring a higher SCLK.3506* (Voltage cannot be adjusted independently without also SCLK.)3507*/3508if (high_pixelclock_count > 1 && adev->asic_type == CHIP_OLAND)3509disable_sclk_switching = true;3510}35113512if (rps->vce_active) {3513rps->evclk = adev->pm.dpm.vce_states[adev->pm.dpm.vce_level].evclk;3514rps->ecclk = adev->pm.dpm.vce_states[adev->pm.dpm.vce_level].ecclk;3515si_get_vce_clock_voltage(adev, rps->evclk, rps->ecclk,3516&min_vce_voltage);3517} else {3518rps->evclk = 0;3519rps->ecclk = 0;3520}35213522if ((adev->pm.pm_display_cfg.num_display > 1) ||3523si_dpm_vblank_too_short(adev))3524disable_mclk_switching = true;35253526if (rps->vclk || rps->dclk) {3527disable_mclk_switching = true;3528disable_sclk_switching = true;3529}35303531if (adev->pm.ac_power)3532max_limits = &adev->pm.dpm.dyn_state.max_clock_voltage_on_ac;3533else3534max_limits = &adev->pm.dpm.dyn_state.max_clock_voltage_on_dc;35353536for (i = ps->performance_level_count - 2; i >= 0; i--) {3537if (ps->performance_levels[i].vddc > ps->performance_levels[i+1].vddc)3538ps->performance_levels[i].vddc = ps->performance_levels[i+1].vddc;3539}3540if (adev->pm.ac_power == false) {3541for (i = 0; i < ps->performance_level_count; i++) {3542if (ps->performance_levels[i].mclk > max_limits->mclk)3543ps->performance_levels[i].mclk = max_limits->mclk;3544if (ps->performance_levels[i].sclk > max_limits->sclk)3545ps->performance_levels[i].sclk = max_limits->sclk;3546if (ps->performance_levels[i].vddc > max_limits->vddc)3547ps->performance_levels[i].vddc = max_limits->vddc;3548if (ps->performance_levels[i].vddci > max_limits->vddci)3549ps->performance_levels[i].vddci = max_limits->vddci;3550}3551}35523553/* limit clocks to max supported clocks based on voltage dependency tables */3554btc_get_max_clock_from_voltage_dependency_table(&adev->pm.dpm.dyn_state.vddc_dependency_on_sclk,3555&max_sclk_vddc);3556btc_get_max_clock_from_voltage_dependency_table(&adev->pm.dpm.dyn_state.vddci_dependency_on_mclk,3557&max_mclk_vddci);3558btc_get_max_clock_from_voltage_dependency_table(&adev->pm.dpm.dyn_state.vddc_dependency_on_mclk,3559&max_mclk_vddc);35603561for (i = 0; i < ps->performance_level_count; i++) {3562if (max_sclk_vddc) {3563if (ps->performance_levels[i].sclk > max_sclk_vddc)3564ps->performance_levels[i].sclk = max_sclk_vddc;3565}3566if (max_mclk_vddci) {3567if (ps->performance_levels[i].mclk > max_mclk_vddci)3568ps->performance_levels[i].mclk = max_mclk_vddci;3569}3570if (max_mclk_vddc) {3571if (ps->performance_levels[i].mclk > max_mclk_vddc)3572ps->performance_levels[i].mclk = max_mclk_vddc;3573}3574if (max_mclk) {3575if (ps->performance_levels[i].mclk > max_mclk)3576ps->performance_levels[i].mclk = max_mclk;3577}3578if (max_sclk) {3579if (ps->performance_levels[i].sclk > max_sclk)3580ps->performance_levels[i].sclk = max_sclk;3581}3582}35833584/* XXX validate the min clocks required for display */35853586if (disable_mclk_switching) {3587mclk = ps->performance_levels[ps->performance_level_count - 1].mclk;3588vddci = ps->performance_levels[ps->performance_level_count - 1].vddci;3589} else {3590mclk = ps->performance_levels[0].mclk;3591vddci = ps->performance_levels[0].vddci;3592}35933594if (disable_sclk_switching) {3595sclk = ps->performance_levels[ps->performance_level_count - 1].sclk;3596vddc = ps->performance_levels[ps->performance_level_count - 1].vddc;3597} else {3598sclk = ps->performance_levels[0].sclk;3599vddc = ps->performance_levels[0].vddc;3600}36013602if (rps->vce_active) {3603if (sclk < adev->pm.dpm.vce_states[adev->pm.dpm.vce_level].sclk)3604sclk = adev->pm.dpm.vce_states[adev->pm.dpm.vce_level].sclk;3605if (mclk < adev->pm.dpm.vce_states[adev->pm.dpm.vce_level].mclk)3606mclk = adev->pm.dpm.vce_states[adev->pm.dpm.vce_level].mclk;3607}36083609/* adjusted low state */3610ps->performance_levels[0].sclk = sclk;3611ps->performance_levels[0].mclk = mclk;3612ps->performance_levels[0].vddc = vddc;3613ps->performance_levels[0].vddci = vddci;36143615if (disable_sclk_switching) {3616sclk = ps->performance_levels[0].sclk;3617for (i = 1; i < ps->performance_level_count; i++) {3618if (sclk < ps->performance_levels[i].sclk)3619sclk = ps->performance_levels[i].sclk;3620}3621for (i = 0; i < ps->performance_level_count; i++) {3622ps->performance_levels[i].sclk = sclk;3623ps->performance_levels[i].vddc = vddc;3624}3625} else {3626for (i = 1; i < ps->performance_level_count; i++) {3627if (ps->performance_levels[i].sclk < ps->performance_levels[i - 1].sclk)3628ps->performance_levels[i].sclk = ps->performance_levels[i - 1].sclk;3629if (ps->performance_levels[i].vddc < ps->performance_levels[i - 1].vddc)3630ps->performance_levels[i].vddc = ps->performance_levels[i - 1].vddc;3631}3632}36333634if (disable_mclk_switching) {3635mclk = ps->performance_levels[0].mclk;3636for (i = 1; i < ps->performance_level_count; i++) {3637if (mclk < ps->performance_levels[i].mclk)3638mclk = ps->performance_levels[i].mclk;3639}3640for (i = 0; i < ps->performance_level_count; i++) {3641ps->performance_levels[i].mclk = mclk;3642ps->performance_levels[i].vddci = vddci;3643}3644} else {3645for (i = 1; i < ps->performance_level_count; i++) {3646if (ps->performance_levels[i].mclk < ps->performance_levels[i - 1].mclk)3647ps->performance_levels[i].mclk = ps->performance_levels[i - 1].mclk;3648if (ps->performance_levels[i].vddci < ps->performance_levels[i - 1].vddci)3649ps->performance_levels[i].vddci = ps->performance_levels[i - 1].vddci;3650}3651}36523653for (i = 0; i < ps->performance_level_count; i++)3654btc_adjust_clock_combinations(adev, max_limits,3655&ps->performance_levels[i]);36563657for (i = 0; i < ps->performance_level_count; i++) {3658if (ps->performance_levels[i].vddc < min_vce_voltage)3659ps->performance_levels[i].vddc = min_vce_voltage;3660btc_apply_voltage_dependency_rules(&adev->pm.dpm.dyn_state.vddc_dependency_on_sclk,3661ps->performance_levels[i].sclk,3662max_limits->vddc, &ps->performance_levels[i].vddc);3663btc_apply_voltage_dependency_rules(&adev->pm.dpm.dyn_state.vddci_dependency_on_mclk,3664ps->performance_levels[i].mclk,3665max_limits->vddci, &ps->performance_levels[i].vddci);3666btc_apply_voltage_dependency_rules(&adev->pm.dpm.dyn_state.vddc_dependency_on_mclk,3667ps->performance_levels[i].mclk,3668max_limits->vddc, &ps->performance_levels[i].vddc);3669btc_apply_voltage_dependency_rules(&adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk,3670display_cfg->display_clk,3671max_limits->vddc, &ps->performance_levels[i].vddc);3672}36733674for (i = 0; i < ps->performance_level_count; i++) {3675btc_apply_voltage_delta_rules(adev,3676max_limits->vddc, max_limits->vddci,3677&ps->performance_levels[i].vddc,3678&ps->performance_levels[i].vddci);3679}36803681ps->dc_compatible = true;3682for (i = 0; i < ps->performance_level_count; i++) {3683if (ps->performance_levels[i].vddc > adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.vddc)3684ps->dc_compatible = false;3685}3686}36873688#if 03689static int si_read_smc_soft_register(struct amdgpu_device *adev,3690u16 reg_offset, u32 *value)3691{3692struct si_power_info *si_pi = si_get_pi(adev);36933694return amdgpu_si_read_smc_sram_dword(adev,3695si_pi->soft_regs_start + reg_offset, value,3696si_pi->sram_end);3697}3698#endif36993700static int si_write_smc_soft_register(struct amdgpu_device *adev,3701u16 reg_offset, u32 value)3702{3703struct si_power_info *si_pi = si_get_pi(adev);37043705return amdgpu_si_write_smc_sram_dword(adev,3706si_pi->soft_regs_start + reg_offset,3707value, si_pi->sram_end);3708}37093710static bool si_is_special_1gb_platform(struct amdgpu_device *adev)3711{3712bool ret = false;3713u32 tmp, width, row, column, bank, density;3714bool is_memory_gddr5, is_special;37153716tmp = RREG32(MC_SEQ_MISC0);3717is_memory_gddr5 = (MC_SEQ_MISC0_GDDR5_VALUE == ((tmp & MC_SEQ_MISC0_GDDR5_MASK) >> MC_SEQ_MISC0_GDDR5_SHIFT));3718is_special = (MC_SEQ_MISC0_REV_ID_VALUE == ((tmp & MC_SEQ_MISC0_REV_ID_MASK) >> MC_SEQ_MISC0_REV_ID_SHIFT))3719& (MC_SEQ_MISC0_VEN_ID_VALUE == ((tmp & MC_SEQ_MISC0_VEN_ID_MASK) >> MC_SEQ_MISC0_VEN_ID_SHIFT));37203721WREG32(MC_SEQ_IO_DEBUG_INDEX, 0xb);3722width = ((RREG32(MC_SEQ_IO_DEBUG_DATA) >> 1) & 1) ? 16 : 32;37233724tmp = RREG32(mmMC_ARB_RAMCFG);3725row = ((tmp & MC_ARB_RAMCFG__NOOFROWS_MASK) >> MC_ARB_RAMCFG__NOOFROWS__SHIFT) + 10;3726column = ((tmp & MC_ARB_RAMCFG__NOOFCOLS_MASK) >> MC_ARB_RAMCFG__NOOFCOLS__SHIFT) + 8;3727bank = ((tmp & MC_ARB_RAMCFG__NOOFBANK_MASK) >> MC_ARB_RAMCFG__NOOFBANK__SHIFT) + 2;37283729density = (1 << (row + column - 20 + bank)) * width;37303731if ((adev->pdev->device == 0x6819) &&3732is_memory_gddr5 && is_special && (density == 0x400))3733ret = true;37343735return ret;3736}37373738static void si_get_leakage_vddc(struct amdgpu_device *adev)3739{3740struct si_power_info *si_pi = si_get_pi(adev);3741u16 vddc, count = 0;3742int i, ret;37433744for (i = 0; i < SISLANDS_MAX_LEAKAGE_COUNT; i++) {3745ret = amdgpu_atombios_get_leakage_vddc_based_on_leakage_idx(adev, &vddc, SISLANDS_LEAKAGE_INDEX0 + i);37463747if (!ret && (vddc > 0) && (vddc != (SISLANDS_LEAKAGE_INDEX0 + i))) {3748si_pi->leakage_voltage.entries[count].voltage = vddc;3749si_pi->leakage_voltage.entries[count].leakage_index =3750SISLANDS_LEAKAGE_INDEX0 + i;3751count++;3752}3753}3754si_pi->leakage_voltage.count = count;3755}37563757static int si_get_leakage_voltage_from_leakage_index(struct amdgpu_device *adev,3758u32 index, u16 *leakage_voltage)3759{3760struct si_power_info *si_pi = si_get_pi(adev);3761int i;37623763if (leakage_voltage == NULL)3764return -EINVAL;37653766if ((index & 0xff00) != 0xff00)3767return -EINVAL;37683769if ((index & 0xff) > SISLANDS_MAX_LEAKAGE_COUNT + 1)3770return -EINVAL;37713772if (index < SISLANDS_LEAKAGE_INDEX0)3773return -EINVAL;37743775for (i = 0; i < si_pi->leakage_voltage.count; i++) {3776if (si_pi->leakage_voltage.entries[i].leakage_index == index) {3777*leakage_voltage = si_pi->leakage_voltage.entries[i].voltage;3778return 0;3779}3780}3781return -EAGAIN;3782}37833784static void si_set_dpm_event_sources(struct amdgpu_device *adev, u32 sources)3785{3786struct rv7xx_power_info *pi = rv770_get_pi(adev);3787bool want_thermal_protection;3788enum si_dpm_event_src dpm_event_src;37893790switch (sources) {3791case 0:3792default:3793want_thermal_protection = false;3794break;3795case (1 << SI_DPM_AUTO_THROTTLE_SRC_THERMAL):3796want_thermal_protection = true;3797dpm_event_src = SI_DPM_EVENT_SRC_DIGITAL;3798break;3799case (1 << SI_DPM_AUTO_THROTTLE_SRC_EXTERNAL):3800want_thermal_protection = true;3801dpm_event_src = SI_DPM_EVENT_SRC_EXTERNAL;3802break;3803case ((1 << SI_DPM_AUTO_THROTTLE_SRC_EXTERNAL) |3804(1 << SI_DPM_AUTO_THROTTLE_SRC_THERMAL)):3805want_thermal_protection = true;3806dpm_event_src = SI_DPM_EVENT_SRC_DIGIAL_OR_EXTERNAL;3807break;3808}38093810if (want_thermal_protection) {3811WREG32_P(mmCG_THERMAL_CTRL, dpm_event_src << CG_THERMAL_CTRL__DPM_EVENT_SRC__SHIFT, ~CG_THERMAL_CTRL__DPM_EVENT_SRC_MASK);3812if (pi->thermal_protection)3813WREG32_P(mmGENERAL_PWRMGT, 0, ~GENERAL_PWRMGT__THERMAL_PROTECTION_DIS_MASK);3814} else {3815WREG32_P(mmGENERAL_PWRMGT, GENERAL_PWRMGT__THERMAL_PROTECTION_DIS_MASK, ~GENERAL_PWRMGT__THERMAL_PROTECTION_DIS_MASK);3816}3817}38183819static void si_enable_auto_throttle_source(struct amdgpu_device *adev,3820enum si_dpm_auto_throttle_src source,3821bool enable)3822{3823struct rv7xx_power_info *pi = rv770_get_pi(adev);38243825if (enable) {3826if (!(pi->active_auto_throttle_sources & (1 << source))) {3827pi->active_auto_throttle_sources |= 1 << source;3828si_set_dpm_event_sources(adev, pi->active_auto_throttle_sources);3829}3830} else {3831if (pi->active_auto_throttle_sources & (1 << source)) {3832pi->active_auto_throttle_sources &= ~(1 << source);3833si_set_dpm_event_sources(adev, pi->active_auto_throttle_sources);3834}3835}3836}38373838static void si_start_dpm(struct amdgpu_device *adev)3839{3840WREG32_P(mmGENERAL_PWRMGT, GENERAL_PWRMGT__GLOBAL_PWRMGT_EN_MASK, ~GENERAL_PWRMGT__GLOBAL_PWRMGT_EN_MASK);3841}38423843static void si_stop_dpm(struct amdgpu_device *adev)3844{3845WREG32_P(mmGENERAL_PWRMGT, 0, ~GENERAL_PWRMGT__GLOBAL_PWRMGT_EN_MASK);3846}38473848static void si_enable_sclk_control(struct amdgpu_device *adev, bool enable)3849{3850if (enable)3851WREG32_P(mmSCLK_PWRMGT_CNTL, 0, ~SCLK_PWRMGT_CNTL__SCLK_PWRMGT_OFF_MASK);3852else3853WREG32_P(mmSCLK_PWRMGT_CNTL, SCLK_PWRMGT_CNTL__SCLK_PWRMGT_OFF_MASK, ~SCLK_PWRMGT_CNTL__SCLK_PWRMGT_OFF_MASK);38543855}38563857#if 03858static int si_notify_hardware_of_thermal_state(struct amdgpu_device *adev,3859u32 thermal_level)3860{3861PPSMC_Result ret;38623863if (thermal_level == 0) {3864ret = amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_EnableThermalInterrupt);3865if (ret == PPSMC_Result_OK)3866return 0;3867else3868return -EINVAL;3869}3870return 0;3871}38723873static void si_notify_hardware_vpu_recovery_event(struct amdgpu_device *adev)3874{3875si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_tdr_is_about_to_happen, true);3876}3877#endif38783879#if 03880static int si_notify_hw_of_powersource(struct amdgpu_device *adev, bool ac_power)3881{3882if (ac_power)3883return (amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_RunningOnAC) == PPSMC_Result_OK) ?38840 : -EINVAL;38853886return 0;3887}3888#endif38893890static PPSMC_Result si_send_msg_to_smc_with_parameter(struct amdgpu_device *adev,3891PPSMC_Msg msg, u32 parameter)3892{3893WREG32(mmSMC_SCRATCH0, parameter);3894return amdgpu_si_send_msg_to_smc(adev, msg);3895}38963897static int si_restrict_performance_levels_before_switch(struct amdgpu_device *adev)3898{3899if (amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_NoForcedLevel) != PPSMC_Result_OK)3900return -EINVAL;39013902return (si_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_SetEnabledLevels, 1) == PPSMC_Result_OK) ?39030 : -EINVAL;3904}39053906static int si_dpm_force_performance_level(void *handle,3907enum amd_dpm_forced_level level)3908{3909struct amdgpu_device *adev = (struct amdgpu_device *)handle;3910struct amdgpu_ps *rps = adev->pm.dpm.current_ps;3911struct si_ps *ps = si_get_ps(rps);3912u32 levels = ps->performance_level_count;39133914if (level == AMD_DPM_FORCED_LEVEL_HIGH) {3915if (si_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_SetEnabledLevels, levels) != PPSMC_Result_OK)3916return -EINVAL;39173918if (si_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_SetForcedLevels, 1) != PPSMC_Result_OK)3919return -EINVAL;3920} else if (level == AMD_DPM_FORCED_LEVEL_LOW) {3921if (si_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_SetForcedLevels, 0) != PPSMC_Result_OK)3922return -EINVAL;39233924if (si_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_SetEnabledLevels, 1) != PPSMC_Result_OK)3925return -EINVAL;3926} else if (level == AMD_DPM_FORCED_LEVEL_AUTO) {3927if (si_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_SetForcedLevels, 0) != PPSMC_Result_OK)3928return -EINVAL;39293930if (si_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_SetEnabledLevels, levels) != PPSMC_Result_OK)3931return -EINVAL;3932}39333934adev->pm.dpm.forced_level = level;39353936return 0;3937}39383939#if 03940static int si_set_boot_state(struct amdgpu_device *adev)3941{3942return (amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_SwitchToInitialState) == PPSMC_Result_OK) ?39430 : -EINVAL;3944}3945#endif39463947static int si_set_sw_state(struct amdgpu_device *adev)3948{3949return (amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_SwitchToSwState) == PPSMC_Result_OK) ?39500 : -EINVAL;3951}39523953static int si_halt_smc(struct amdgpu_device *adev)3954{3955if (amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_Halt) != PPSMC_Result_OK)3956return -EINVAL;39573958return (amdgpu_si_wait_for_smc_inactive(adev) == PPSMC_Result_OK) ?39590 : -EINVAL;3960}39613962static int si_resume_smc(struct amdgpu_device *adev)3963{3964if (amdgpu_si_send_msg_to_smc(adev, PPSMC_FlushDataCache) != PPSMC_Result_OK)3965return -EINVAL;39663967return (amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_Resume) == PPSMC_Result_OK) ?39680 : -EINVAL;3969}39703971static void si_dpm_start_smc(struct amdgpu_device *adev)3972{3973amdgpu_si_program_jump_on_start(adev);3974amdgpu_si_start_smc(adev);3975amdgpu_si_smc_clock(adev, true);3976}39773978static void si_dpm_stop_smc(struct amdgpu_device *adev)3979{3980amdgpu_si_reset_smc(adev);3981amdgpu_si_smc_clock(adev, false);3982}39833984static int si_process_firmware_header(struct amdgpu_device *adev)3985{3986struct si_power_info *si_pi = si_get_pi(adev);3987u32 tmp;3988int ret;39893990ret = amdgpu_si_read_smc_sram_dword(adev,3991SISLANDS_SMC_FIRMWARE_HEADER_LOCATION +3992SISLANDS_SMC_FIRMWARE_HEADER_stateTable,3993&tmp, si_pi->sram_end);3994if (ret)3995return ret;39963997si_pi->state_table_start = tmp;39983999ret = amdgpu_si_read_smc_sram_dword(adev,4000SISLANDS_SMC_FIRMWARE_HEADER_LOCATION +4001SISLANDS_SMC_FIRMWARE_HEADER_softRegisters,4002&tmp, si_pi->sram_end);4003if (ret)4004return ret;40054006si_pi->soft_regs_start = tmp;40074008ret = amdgpu_si_read_smc_sram_dword(adev,4009SISLANDS_SMC_FIRMWARE_HEADER_LOCATION +4010SISLANDS_SMC_FIRMWARE_HEADER_mcRegisterTable,4011&tmp, si_pi->sram_end);4012if (ret)4013return ret;40144015si_pi->mc_reg_table_start = tmp;40164017ret = amdgpu_si_read_smc_sram_dword(adev,4018SISLANDS_SMC_FIRMWARE_HEADER_LOCATION +4019SISLANDS_SMC_FIRMWARE_HEADER_fanTable,4020&tmp, si_pi->sram_end);4021if (ret)4022return ret;40234024si_pi->fan_table_start = tmp;40254026ret = amdgpu_si_read_smc_sram_dword(adev,4027SISLANDS_SMC_FIRMWARE_HEADER_LOCATION +4028SISLANDS_SMC_FIRMWARE_HEADER_mcArbDramAutoRefreshTable,4029&tmp, si_pi->sram_end);4030if (ret)4031return ret;40324033si_pi->arb_table_start = tmp;40344035ret = amdgpu_si_read_smc_sram_dword(adev,4036SISLANDS_SMC_FIRMWARE_HEADER_LOCATION +4037SISLANDS_SMC_FIRMWARE_HEADER_CacConfigTable,4038&tmp, si_pi->sram_end);4039if (ret)4040return ret;40414042si_pi->cac_table_start = tmp;40434044ret = amdgpu_si_read_smc_sram_dword(adev,4045SISLANDS_SMC_FIRMWARE_HEADER_LOCATION +4046SISLANDS_SMC_FIRMWARE_HEADER_DteConfiguration,4047&tmp, si_pi->sram_end);4048if (ret)4049return ret;40504051si_pi->dte_table_start = tmp;40524053ret = amdgpu_si_read_smc_sram_dword(adev,4054SISLANDS_SMC_FIRMWARE_HEADER_LOCATION +4055SISLANDS_SMC_FIRMWARE_HEADER_spllTable,4056&tmp, si_pi->sram_end);4057if (ret)4058return ret;40594060si_pi->spll_table_start = tmp;40614062ret = amdgpu_si_read_smc_sram_dword(adev,4063SISLANDS_SMC_FIRMWARE_HEADER_LOCATION +4064SISLANDS_SMC_FIRMWARE_HEADER_PAPMParameters,4065&tmp, si_pi->sram_end);4066if (ret)4067return ret;40684069si_pi->papm_cfg_table_start = tmp;40704071return ret;4072}40734074static void si_read_clock_registers(struct amdgpu_device *adev)4075{4076struct si_power_info *si_pi = si_get_pi(adev);40774078si_pi->clock_registers.cg_spll_func_cntl = RREG32(mmCG_SPLL_FUNC_CNTL);4079si_pi->clock_registers.cg_spll_func_cntl_2 = RREG32(mmCG_SPLL_FUNC_CNTL_2);4080si_pi->clock_registers.cg_spll_func_cntl_3 = RREG32(mmCG_SPLL_FUNC_CNTL_3);4081si_pi->clock_registers.cg_spll_func_cntl_4 = RREG32(mmCG_SPLL_FUNC_CNTL_4);4082si_pi->clock_registers.cg_spll_spread_spectrum = RREG32(mmCG_SPLL_SPREAD_SPECTRUM);4083si_pi->clock_registers.cg_spll_spread_spectrum_2 = RREG32(mmCG_SPLL_SPREAD_SPECTRUM_2);4084si_pi->clock_registers.dll_cntl = RREG32(DLL_CNTL);4085si_pi->clock_registers.mclk_pwrmgt_cntl = RREG32(MCLK_PWRMGT_CNTL);4086si_pi->clock_registers.mpll_ad_func_cntl = RREG32(MPLL_AD_FUNC_CNTL);4087si_pi->clock_registers.mpll_dq_func_cntl = RREG32(MPLL_DQ_FUNC_CNTL);4088si_pi->clock_registers.mpll_func_cntl = RREG32(MPLL_FUNC_CNTL);4089si_pi->clock_registers.mpll_func_cntl_1 = RREG32(MPLL_FUNC_CNTL_1);4090si_pi->clock_registers.mpll_func_cntl_2 = RREG32(MPLL_FUNC_CNTL_2);4091si_pi->clock_registers.mpll_ss1 = RREG32(MPLL_SS1);4092si_pi->clock_registers.mpll_ss2 = RREG32(MPLL_SS2);4093}40944095static void si_enable_thermal_protection(struct amdgpu_device *adev,4096bool enable)4097{4098if (enable)4099WREG32_P(mmGENERAL_PWRMGT, 0, ~GENERAL_PWRMGT__THERMAL_PROTECTION_DIS_MASK);4100else4101WREG32_P(mmGENERAL_PWRMGT, GENERAL_PWRMGT__THERMAL_PROTECTION_DIS_MASK, ~GENERAL_PWRMGT__THERMAL_PROTECTION_DIS_MASK);4102}41034104static void si_enable_acpi_power_management(struct amdgpu_device *adev)4105{4106WREG32_P(mmGENERAL_PWRMGT, GENERAL_PWRMGT__STATIC_PM_EN_MASK, ~GENERAL_PWRMGT__STATIC_PM_EN_MASK);4107}41084109#if 04110static int si_enter_ulp_state(struct amdgpu_device *adev)4111{4112WREG32(SMC_MESSAGE_0, PPSMC_MSG_SwitchToMinimumPower);41134114udelay(25000);41154116return 0;4117}41184119static int si_exit_ulp_state(struct amdgpu_device *adev)4120{4121int i;41224123WREG32(SMC_MESSAGE_0, PPSMC_MSG_ResumeFromMinimumPower);41244125udelay(7000);41264127for (i = 0; i < adev->usec_timeout; i++) {4128if (RREG32(SMC_RESP_0) == 1)4129break;4130udelay(1000);4131}41324133return 0;4134}4135#endif41364137static int si_notify_smc_display_change(struct amdgpu_device *adev,4138bool has_display)4139{4140PPSMC_Msg msg = has_display ?4141PPSMC_MSG_HasDisplay : PPSMC_MSG_NoDisplay;41424143return (amdgpu_si_send_msg_to_smc(adev, msg) == PPSMC_Result_OK) ?41440 : -EINVAL;4145}41464147static void si_program_response_times(struct amdgpu_device *adev)4148{4149u32 voltage_response_time, acpi_delay_time, vbi_time_out;4150u32 vddc_dly, acpi_dly, vbi_dly;4151u32 reference_clock;41524153si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_mvdd_chg_time, 1);41544155voltage_response_time = (u32)adev->pm.dpm.voltage_response_time;41564157if (voltage_response_time == 0)4158voltage_response_time = 1000;41594160acpi_delay_time = 15000;4161vbi_time_out = 100000;41624163reference_clock = amdgpu_asic_get_xclk(adev);41644165vddc_dly = (voltage_response_time * reference_clock) / 100;4166acpi_dly = (acpi_delay_time * reference_clock) / 100;4167vbi_dly = (vbi_time_out * reference_clock) / 100;41684169si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_delay_vreg, vddc_dly);4170si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_delay_acpi, acpi_dly);4171si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_mclk_chg_timeout, vbi_dly);4172si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_mc_block_delay, 0xAA);4173}41744175static void si_program_ds_registers(struct amdgpu_device *adev)4176{4177struct evergreen_power_info *eg_pi = evergreen_get_pi(adev);4178u32 tmp;41794180/* DEEP_SLEEP_CLK_SEL field should be 0x10 on tahiti A0 */4181if (adev->asic_type == CHIP_TAHITI && adev->rev_id == 0x0)4182tmp = 0x10;4183else4184tmp = 0x1;41854186if (eg_pi->sclk_deep_sleep) {4187WREG32_P(mmMISC_CLK_CNTL, (tmp << MISC_CLK_CNTL__DEEP_SLEEP_CLK_SEL__SHIFT), ~MISC_CLK_CNTL__DEEP_SLEEP_CLK_SEL_MASK);4188WREG32_P(mmCG_SPLL_AUTOSCALE_CNTL, CG_SPLL_AUTOSCALE_CNTL__AUTOSCALE_ON_SS_CLEAR_MASK,4189~CG_SPLL_AUTOSCALE_CNTL__AUTOSCALE_ON_SS_CLEAR_MASK);4190}4191}41924193static void si_program_display_gap(struct amdgpu_device *adev)4194{4195const struct amd_pp_display_configuration *cfg = &adev->pm.pm_display_cfg;4196u32 tmp, pipe;41974198tmp = RREG32(mmCG_DISPLAY_GAP_CNTL) & ~(CG_DISPLAY_GAP_CNTL__DISP1_GAP_MASK | CG_DISPLAY_GAP_CNTL__DISP2_GAP_MASK);4199if (cfg->num_display > 0)4200tmp |= R600_PM_DISPLAY_GAP_VBLANK_OR_WM << CG_DISPLAY_GAP_CNTL__DISP1_GAP__SHIFT;4201else4202tmp |= R600_PM_DISPLAY_GAP_IGNORE << CG_DISPLAY_GAP_CNTL__DISP1_GAP__SHIFT;42034204if (cfg->num_display > 1)4205tmp |= R600_PM_DISPLAY_GAP_VBLANK_OR_WM << CG_DISPLAY_GAP_CNTL__DISP2_GAP__SHIFT;4206else4207tmp |= R600_PM_DISPLAY_GAP_IGNORE << CG_DISPLAY_GAP_CNTL__DISP2_GAP__SHIFT;42084209WREG32(mmCG_DISPLAY_GAP_CNTL, tmp);42104211tmp = RREG32(DCCG_DISP_SLOW_SELECT_REG);4212pipe = (tmp & DCCG_DISP1_SLOW_SELECT_MASK) >> DCCG_DISP1_SLOW_SELECT_SHIFT;42134214if (cfg->num_display > 0 && pipe != cfg->crtc_index) {4215pipe = cfg->crtc_index;42164217tmp &= ~DCCG_DISP1_SLOW_SELECT_MASK;4218tmp |= DCCG_DISP1_SLOW_SELECT(pipe);4219WREG32(DCCG_DISP_SLOW_SELECT_REG, tmp);4220}42214222/* Setting this to false forces the performance state to low if the crtcs are disabled.4223* This can be a problem on PowerXpress systems or if you want to use the card4224* for offscreen rendering or compute if there are no crtcs enabled.4225*/4226si_notify_smc_display_change(adev, cfg->num_display > 0);4227}42284229static void si_enable_spread_spectrum(struct amdgpu_device *adev, bool enable)4230{4231struct rv7xx_power_info *pi = rv770_get_pi(adev);42324233if (enable) {4234if (pi->sclk_ss)4235WREG32_P(mmGENERAL_PWRMGT, GENERAL_PWRMGT__DYN_SPREAD_SPECTRUM_EN_MASK, ~GENERAL_PWRMGT__DYN_SPREAD_SPECTRUM_EN_MASK);4236} else {4237WREG32_P(mmCG_SPLL_SPREAD_SPECTRUM, 0, ~CG_SPLL_SPREAD_SPECTRUM__SSEN_MASK);4238WREG32_P(mmGENERAL_PWRMGT, 0, ~GENERAL_PWRMGT__DYN_SPREAD_SPECTRUM_EN_MASK);4239}4240}42414242static void si_setup_bsp(struct amdgpu_device *adev)4243{4244struct rv7xx_power_info *pi = rv770_get_pi(adev);4245u32 xclk = amdgpu_asic_get_xclk(adev);42464247r600_calculate_u_and_p(pi->asi,4248xclk,424916,4250&pi->bsp,4251&pi->bsu);42524253r600_calculate_u_and_p(pi->pasi,4254xclk,425516,4256&pi->pbsp,4257&pi->pbsu);425842594260pi->dsp = (pi->bsp << CG_BSP__BSP__SHIFT) | (pi->bsu << CG_BSP__BSU__SHIFT);4261pi->psp = (pi->pbsp << CG_BSP__BSP__SHIFT) | (pi->pbsu << CG_BSP__BSU__SHIFT);42624263WREG32(mmCG_BSP, pi->dsp);4264}42654266static void si_program_git(struct amdgpu_device *adev)4267{4268WREG32_P(mmCG_GIT, R600_GICST_DFLT << CG_GIT__CG_GICST__SHIFT, ~CG_GIT__CG_GICST_MASK);4269}42704271static void si_program_tp(struct amdgpu_device *adev)4272{4273int i;4274enum r600_td td = R600_TD_DFLT;42754276for (i = 0; i < R600_PM_NUMBER_OF_TC; i++)4277WREG32(mmCG_FFCT_0 + i, (r600_utc[i] << CG_FFCT_0__UTC_0__SHIFT | r600_dtc[i] << CG_FFCT_0__DTC_0__SHIFT));42784279if (td == R600_TD_AUTO)4280WREG32_P(mmSCLK_PWRMGT_CNTL, 0, ~SCLK_PWRMGT_CNTL__FIR_FORCE_TREND_SEL_MASK);4281else4282WREG32_P(mmSCLK_PWRMGT_CNTL, SCLK_PWRMGT_CNTL__FIR_FORCE_TREND_SEL_MASK, ~SCLK_PWRMGT_CNTL__FIR_FORCE_TREND_SEL_MASK);42834284if (td == R600_TD_UP)4285WREG32_P(mmSCLK_PWRMGT_CNTL, 0, ~SCLK_PWRMGT_CNTL__FIR_TREND_MODE_MASK);42864287if (td == R600_TD_DOWN)4288WREG32_P(mmSCLK_PWRMGT_CNTL, SCLK_PWRMGT_CNTL__FIR_TREND_MODE_MASK, ~SCLK_PWRMGT_CNTL__FIR_TREND_MODE_MASK);4289}42904291static void si_program_tpp(struct amdgpu_device *adev)4292{4293WREG32(mmCG_TPC, R600_TPC_DFLT);4294}42954296static void si_program_sstp(struct amdgpu_device *adev)4297{4298WREG32(mmCG_SSP, (R600_SSTU_DFLT << CG_SSP__SSTU__SHIFT| R600_SST_DFLT << CG_SSP__SST__SHIFT));4299}43004301static void si_enable_display_gap(struct amdgpu_device *adev)4302{4303u32 tmp = RREG32(mmCG_DISPLAY_GAP_CNTL);43044305tmp &= ~(CG_DISPLAY_GAP_CNTL__DISP1_GAP_MASK | CG_DISPLAY_GAP_CNTL__DISP2_GAP_MASK);4306tmp |= (R600_PM_DISPLAY_GAP_IGNORE << CG_DISPLAY_GAP_CNTL__DISP1_GAP__SHIFT |4307R600_PM_DISPLAY_GAP_IGNORE << CG_DISPLAY_GAP_CNTL__DISP2_GAP__SHIFT);43084309tmp &= ~(CG_DISPLAY_GAP_CNTL__DISP1_GAP_MCHG_MASK | CG_DISPLAY_GAP_CNTL__DISP2_GAP_MCHG_MASK);4310tmp |= (R600_PM_DISPLAY_GAP_VBLANK << CG_DISPLAY_GAP_CNTL__DISP1_GAP_MCHG__SHIFT |4311R600_PM_DISPLAY_GAP_IGNORE << CG_DISPLAY_GAP_CNTL__DISP2_GAP_MCHG__SHIFT);4312WREG32(mmCG_DISPLAY_GAP_CNTL, tmp);4313}43144315static void si_program_vc(struct amdgpu_device *adev)4316{4317struct rv7xx_power_info *pi = rv770_get_pi(adev);43184319WREG32(mmCG_FTV, pi->vrc);4320}43214322static void si_clear_vc(struct amdgpu_device *adev)4323{4324WREG32(mmCG_FTV, 0);4325}43264327static u8 si_get_ddr3_mclk_frequency_ratio(u32 memory_clock)4328{4329u8 mc_para_index;43304331if (memory_clock < 10000)4332mc_para_index = 0;4333else if (memory_clock >= 80000)4334mc_para_index = 0x0f;4335else4336mc_para_index = (u8)((memory_clock - 10000) / 5000 + 1);4337return mc_para_index;4338}43394340static u8 si_get_mclk_frequency_ratio(u32 memory_clock, bool strobe_mode)4341{4342u8 mc_para_index;43434344if (strobe_mode) {4345if (memory_clock < 12500)4346mc_para_index = 0x00;4347else if (memory_clock > 47500)4348mc_para_index = 0x0f;4349else4350mc_para_index = (u8)((memory_clock - 10000) / 2500);4351} else {4352if (memory_clock < 65000)4353mc_para_index = 0x00;4354else if (memory_clock > 135000)4355mc_para_index = 0x0f;4356else4357mc_para_index = (u8)((memory_clock - 60000) / 5000);4358}4359return mc_para_index;4360}43614362static u8 si_get_strobe_mode_settings(struct amdgpu_device *adev, u32 mclk)4363{4364struct rv7xx_power_info *pi = rv770_get_pi(adev);4365bool strobe_mode = false;4366u8 result = 0;43674368if (mclk <= pi->mclk_strobe_mode_threshold)4369strobe_mode = true;43704371if (adev->gmc.vram_type == AMDGPU_VRAM_TYPE_GDDR5)4372result = si_get_mclk_frequency_ratio(mclk, strobe_mode);4373else4374result = si_get_ddr3_mclk_frequency_ratio(mclk);43754376if (strobe_mode)4377result |= SISLANDS_SMC_STROBE_ENABLE;43784379return result;4380}43814382static int si_upload_firmware(struct amdgpu_device *adev)4383{4384struct si_power_info *si_pi = si_get_pi(adev);43854386amdgpu_si_reset_smc(adev);4387amdgpu_si_smc_clock(adev, false);43884389return amdgpu_si_load_smc_ucode(adev, si_pi->sram_end);4390}43914392static bool si_validate_phase_shedding_tables(struct amdgpu_device *adev,4393const struct atom_voltage_table *table,4394const struct amdgpu_phase_shedding_limits_table *limits)4395{4396u32 data, num_bits, num_levels;43974398if ((table == NULL) || (limits == NULL))4399return false;44004401data = table->mask_low;44024403num_bits = hweight32(data);44044405if (num_bits == 0)4406return false;44074408num_levels = (1 << num_bits);44094410if (table->count != num_levels)4411return false;44124413if (limits->count != (num_levels - 1))4414return false;44154416return true;4417}44184419static void si_trim_voltage_table_to_fit_state_table(struct amdgpu_device *adev,4420u32 max_voltage_steps,4421struct atom_voltage_table *voltage_table)4422{4423unsigned int i, diff;44244425if (voltage_table->count <= max_voltage_steps)4426return;44274428diff = voltage_table->count - max_voltage_steps;44294430for (i= 0; i < max_voltage_steps; i++)4431voltage_table->entries[i] = voltage_table->entries[i + diff];44324433voltage_table->count = max_voltage_steps;4434}44354436static int si_get_svi2_voltage_table(struct amdgpu_device *adev,4437struct amdgpu_clock_voltage_dependency_table *voltage_dependency_table,4438struct atom_voltage_table *voltage_table)4439{4440u32 i;44414442if (voltage_dependency_table == NULL)4443return -EINVAL;44444445voltage_table->mask_low = 0;4446voltage_table->phase_delay = 0;44474448voltage_table->count = voltage_dependency_table->count;4449for (i = 0; i < voltage_table->count; i++) {4450voltage_table->entries[i].value = voltage_dependency_table->entries[i].v;4451voltage_table->entries[i].smio_low = 0;4452}44534454return 0;4455}44564457static int si_construct_voltage_tables(struct amdgpu_device *adev)4458{4459struct rv7xx_power_info *pi = rv770_get_pi(adev);4460struct evergreen_power_info *eg_pi = evergreen_get_pi(adev);4461struct si_power_info *si_pi = si_get_pi(adev);4462int ret;44634464if (pi->voltage_control) {4465ret = amdgpu_atombios_get_voltage_table(adev, VOLTAGE_TYPE_VDDC,4466VOLTAGE_OBJ_GPIO_LUT, &eg_pi->vddc_voltage_table);4467if (ret)4468return ret;44694470if (eg_pi->vddc_voltage_table.count > SISLANDS_MAX_NO_VREG_STEPS)4471si_trim_voltage_table_to_fit_state_table(adev,4472SISLANDS_MAX_NO_VREG_STEPS,4473&eg_pi->vddc_voltage_table);4474} else if (si_pi->voltage_control_svi2) {4475ret = si_get_svi2_voltage_table(adev,4476&adev->pm.dpm.dyn_state.vddc_dependency_on_mclk,4477&eg_pi->vddc_voltage_table);4478if (ret)4479return ret;4480} else {4481return -EINVAL;4482}44834484if (eg_pi->vddci_control) {4485ret = amdgpu_atombios_get_voltage_table(adev, VOLTAGE_TYPE_VDDCI,4486VOLTAGE_OBJ_GPIO_LUT, &eg_pi->vddci_voltage_table);4487if (ret)4488return ret;44894490if (eg_pi->vddci_voltage_table.count > SISLANDS_MAX_NO_VREG_STEPS)4491si_trim_voltage_table_to_fit_state_table(adev,4492SISLANDS_MAX_NO_VREG_STEPS,4493&eg_pi->vddci_voltage_table);4494}4495if (si_pi->vddci_control_svi2) {4496ret = si_get_svi2_voltage_table(adev,4497&adev->pm.dpm.dyn_state.vddci_dependency_on_mclk,4498&eg_pi->vddci_voltage_table);4499if (ret)4500return ret;4501}45024503if (pi->mvdd_control) {4504ret = amdgpu_atombios_get_voltage_table(adev, VOLTAGE_TYPE_MVDDC,4505VOLTAGE_OBJ_GPIO_LUT, &si_pi->mvdd_voltage_table);45064507if (ret) {4508pi->mvdd_control = false;4509return ret;4510}45114512if (si_pi->mvdd_voltage_table.count == 0) {4513pi->mvdd_control = false;4514return -EINVAL;4515}45164517if (si_pi->mvdd_voltage_table.count > SISLANDS_MAX_NO_VREG_STEPS)4518si_trim_voltage_table_to_fit_state_table(adev,4519SISLANDS_MAX_NO_VREG_STEPS,4520&si_pi->mvdd_voltage_table);4521}45224523if (si_pi->vddc_phase_shed_control) {4524ret = amdgpu_atombios_get_voltage_table(adev, VOLTAGE_TYPE_VDDC,4525VOLTAGE_OBJ_PHASE_LUT, &si_pi->vddc_phase_shed_table);4526if (ret)4527si_pi->vddc_phase_shed_control = false;45284529if ((si_pi->vddc_phase_shed_table.count == 0) ||4530(si_pi->vddc_phase_shed_table.count > SISLANDS_MAX_NO_VREG_STEPS))4531si_pi->vddc_phase_shed_control = false;4532}45334534return 0;4535}45364537static void si_populate_smc_voltage_table(struct amdgpu_device *adev,4538const struct atom_voltage_table *voltage_table,4539SISLANDS_SMC_STATETABLE *table)4540{4541unsigned int i;45424543for (i = 0; i < voltage_table->count; i++)4544table->lowSMIO[i] |= cpu_to_be32(voltage_table->entries[i].smio_low);4545}45464547static int si_populate_smc_voltage_tables(struct amdgpu_device *adev,4548SISLANDS_SMC_STATETABLE *table)4549{4550struct rv7xx_power_info *pi = rv770_get_pi(adev);4551struct evergreen_power_info *eg_pi = evergreen_get_pi(adev);4552struct si_power_info *si_pi = si_get_pi(adev);4553u8 i;45544555if (si_pi->voltage_control_svi2) {4556si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_svi_rework_gpio_id_svc,4557si_pi->svc_gpio_id);4558si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_svi_rework_gpio_id_svd,4559si_pi->svd_gpio_id);4560si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_svi_rework_plat_type,45612);4562} else {4563if (eg_pi->vddc_voltage_table.count) {4564si_populate_smc_voltage_table(adev, &eg_pi->vddc_voltage_table, table);4565table->voltageMaskTable.lowMask[SISLANDS_SMC_VOLTAGEMASK_VDDC] =4566cpu_to_be32(eg_pi->vddc_voltage_table.mask_low);45674568for (i = 0; i < eg_pi->vddc_voltage_table.count; i++) {4569if (pi->max_vddc_in_table <= eg_pi->vddc_voltage_table.entries[i].value) {4570table->maxVDDCIndexInPPTable = i;4571break;4572}4573}4574}45754576if (eg_pi->vddci_voltage_table.count) {4577si_populate_smc_voltage_table(adev, &eg_pi->vddci_voltage_table, table);45784579table->voltageMaskTable.lowMask[SISLANDS_SMC_VOLTAGEMASK_VDDCI] =4580cpu_to_be32(eg_pi->vddci_voltage_table.mask_low);4581}458245834584if (si_pi->mvdd_voltage_table.count) {4585si_populate_smc_voltage_table(adev, &si_pi->mvdd_voltage_table, table);45864587table->voltageMaskTable.lowMask[SISLANDS_SMC_VOLTAGEMASK_MVDD] =4588cpu_to_be32(si_pi->mvdd_voltage_table.mask_low);4589}45904591if (si_pi->vddc_phase_shed_control) {4592if (si_validate_phase_shedding_tables(adev, &si_pi->vddc_phase_shed_table,4593&adev->pm.dpm.dyn_state.phase_shedding_limits_table)) {4594si_populate_smc_voltage_table(adev, &si_pi->vddc_phase_shed_table, table);45954596table->phaseMaskTable.lowMask[SISLANDS_SMC_VOLTAGEMASK_VDDC_PHASE_SHEDDING] =4597cpu_to_be32(si_pi->vddc_phase_shed_table.mask_low);45984599si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_phase_shedding_delay,4600(u32)si_pi->vddc_phase_shed_table.phase_delay);4601} else {4602si_pi->vddc_phase_shed_control = false;4603}4604}4605}46064607return 0;4608}46094610static int si_populate_voltage_value(struct amdgpu_device *adev,4611const struct atom_voltage_table *table,4612u16 value, SISLANDS_SMC_VOLTAGE_VALUE *voltage)4613{4614unsigned int i;46154616for (i = 0; i < table->count; i++) {4617if (value <= table->entries[i].value) {4618voltage->index = (u8)i;4619voltage->value = cpu_to_be16(table->entries[i].value);4620break;4621}4622}46234624if (i >= table->count)4625return -EINVAL;46264627return 0;4628}46294630static int si_populate_mvdd_value(struct amdgpu_device *adev, u32 mclk,4631SISLANDS_SMC_VOLTAGE_VALUE *voltage)4632{4633struct rv7xx_power_info *pi = rv770_get_pi(adev);4634struct si_power_info *si_pi = si_get_pi(adev);46354636if (pi->mvdd_control) {4637if (mclk <= pi->mvdd_split_frequency)4638voltage->index = 0;4639else4640voltage->index = (u8)(si_pi->mvdd_voltage_table.count) - 1;46414642voltage->value = cpu_to_be16(si_pi->mvdd_voltage_table.entries[voltage->index].value);4643}4644return 0;4645}46464647static int si_get_std_voltage_value(struct amdgpu_device *adev,4648SISLANDS_SMC_VOLTAGE_VALUE *voltage,4649u16 *std_voltage)4650{4651u16 v_index;4652bool voltage_found = false;4653*std_voltage = be16_to_cpu(voltage->value);46544655if (adev->pm.dpm.dyn_state.cac_leakage_table.entries) {4656if (adev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_NEW_CAC_VOLTAGE) {4657if (adev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries == NULL)4658return -EINVAL;46594660for (v_index = 0; (u32)v_index < adev->pm.dpm.dyn_state.vddc_dependency_on_sclk.count; v_index++) {4661if (be16_to_cpu(voltage->value) ==4662(u16)adev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries[v_index].v) {4663voltage_found = true;4664if ((u32)v_index < adev->pm.dpm.dyn_state.cac_leakage_table.count)4665*std_voltage =4666adev->pm.dpm.dyn_state.cac_leakage_table.entries[v_index].vddc;4667else4668*std_voltage =4669adev->pm.dpm.dyn_state.cac_leakage_table.entries[adev->pm.dpm.dyn_state.cac_leakage_table.count-1].vddc;4670break;4671}4672}46734674if (!voltage_found) {4675for (v_index = 0; (u32)v_index < adev->pm.dpm.dyn_state.vddc_dependency_on_sclk.count; v_index++) {4676if (be16_to_cpu(voltage->value) <=4677(u16)adev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries[v_index].v) {4678voltage_found = true;4679if ((u32)v_index < adev->pm.dpm.dyn_state.cac_leakage_table.count)4680*std_voltage =4681adev->pm.dpm.dyn_state.cac_leakage_table.entries[v_index].vddc;4682else4683*std_voltage =4684adev->pm.dpm.dyn_state.cac_leakage_table.entries[adev->pm.dpm.dyn_state.cac_leakage_table.count-1].vddc;4685break;4686}4687}4688}4689} else {4690if ((u32)voltage->index < adev->pm.dpm.dyn_state.cac_leakage_table.count)4691*std_voltage = adev->pm.dpm.dyn_state.cac_leakage_table.entries[voltage->index].vddc;4692}4693}46944695return 0;4696}46974698static int si_populate_std_voltage_value(struct amdgpu_device *adev,4699u16 value, u8 index,4700SISLANDS_SMC_VOLTAGE_VALUE *voltage)4701{4702voltage->index = index;4703voltage->value = cpu_to_be16(value);47044705return 0;4706}47074708static int si_populate_phase_shedding_value(struct amdgpu_device *adev,4709const struct amdgpu_phase_shedding_limits_table *limits,4710u16 voltage, u32 sclk, u32 mclk,4711SISLANDS_SMC_VOLTAGE_VALUE *smc_voltage)4712{4713unsigned int i;47144715for (i = 0; i < limits->count; i++) {4716if ((voltage <= limits->entries[i].voltage) &&4717(sclk <= limits->entries[i].sclk) &&4718(mclk <= limits->entries[i].mclk))4719break;4720}47214722smc_voltage->phase_settings = (u8)i;47234724return 0;4725}47264727static int si_init_arb_table_index(struct amdgpu_device *adev)4728{4729struct si_power_info *si_pi = si_get_pi(adev);4730u32 tmp;4731int ret;47324733ret = amdgpu_si_read_smc_sram_dword(adev, si_pi->arb_table_start,4734&tmp, si_pi->sram_end);4735if (ret)4736return ret;47374738tmp &= 0x00FFFFFF;4739tmp |= MC_CG_ARB_FREQ_F1 << 24;47404741return amdgpu_si_write_smc_sram_dword(adev, si_pi->arb_table_start,4742tmp, si_pi->sram_end);4743}47444745static int si_initial_switch_from_arb_f0_to_f1(struct amdgpu_device *adev)4746{4747return ni_copy_and_switch_arb_sets(adev, MC_CG_ARB_FREQ_F0, MC_CG_ARB_FREQ_F1);4748}47494750static int si_reset_to_default(struct amdgpu_device *adev)4751{4752return (amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_ResetToDefaults) == PPSMC_Result_OK) ?47530 : -EINVAL;4754}47554756static int si_force_switch_to_arb_f0(struct amdgpu_device *adev)4757{4758struct si_power_info *si_pi = si_get_pi(adev);4759u32 tmp;4760int ret;47614762ret = amdgpu_si_read_smc_sram_dword(adev, si_pi->arb_table_start,4763&tmp, si_pi->sram_end);4764if (ret)4765return ret;47664767tmp = (tmp >> 24) & 0xff;47684769if (tmp == MC_CG_ARB_FREQ_F0)4770return 0;47714772return ni_copy_and_switch_arb_sets(adev, tmp, MC_CG_ARB_FREQ_F0);4773}47744775static u32 si_calculate_memory_refresh_rate(struct amdgpu_device *adev,4776u32 engine_clock)4777{4778u32 dram_rows;4779u32 dram_refresh_rate;4780u32 mc_arb_rfsh_rate;4781u32 tmp = (RREG32(mmMC_ARB_RAMCFG) & MC_ARB_RAMCFG__NOOFROWS_MASK) >> MC_ARB_RAMCFG__NOOFROWS__SHIFT;47824783if (tmp >= 4)4784dram_rows = 16384;4785else4786dram_rows = 1 << (tmp + 10);47874788dram_refresh_rate = 1 << ((RREG32(MC_SEQ_MISC0) & 0x3) + 3);4789mc_arb_rfsh_rate = ((engine_clock * 10) * dram_refresh_rate / dram_rows - 32) / 64;47904791return mc_arb_rfsh_rate;4792}47934794static int si_populate_memory_timing_parameters(struct amdgpu_device *adev,4795struct rv7xx_pl *pl,4796SMC_SIslands_MCArbDramTimingRegisterSet *arb_regs)4797{4798u32 dram_timing;4799u32 dram_timing2;4800u32 burst_time;4801int ret;48024803arb_regs->mc_arb_rfsh_rate =4804(u8)si_calculate_memory_refresh_rate(adev, pl->sclk);48054806ret = amdgpu_atombios_set_engine_dram_timings(adev, pl->sclk,4807pl->mclk);4808if (ret)4809return ret;48104811dram_timing = RREG32(MC_ARB_DRAM_TIMING);4812dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2);4813burst_time = RREG32(MC_ARB_BURST_TIME) & STATE0_MASK;48144815arb_regs->mc_arb_dram_timing = cpu_to_be32(dram_timing);4816arb_regs->mc_arb_dram_timing2 = cpu_to_be32(dram_timing2);4817arb_regs->mc_arb_burst_time = (u8)burst_time;48184819return 0;4820}48214822static int si_do_program_memory_timing_parameters(struct amdgpu_device *adev,4823struct amdgpu_ps *amdgpu_state,4824unsigned int first_arb_set)4825{4826struct si_power_info *si_pi = si_get_pi(adev);4827struct si_ps *state = si_get_ps(amdgpu_state);4828SMC_SIslands_MCArbDramTimingRegisterSet arb_regs = { 0 };4829int i, ret = 0;48304831for (i = 0; i < state->performance_level_count; i++) {4832ret = si_populate_memory_timing_parameters(adev, &state->performance_levels[i], &arb_regs);4833if (ret)4834break;4835ret = amdgpu_si_copy_bytes_to_smc(adev,4836si_pi->arb_table_start +4837offsetof(SMC_SIslands_MCArbDramTimingRegisters, data) +4838sizeof(SMC_SIslands_MCArbDramTimingRegisterSet) * (first_arb_set + i),4839(u8 *)&arb_regs,4840sizeof(SMC_SIslands_MCArbDramTimingRegisterSet),4841si_pi->sram_end);4842if (ret)4843break;4844}48454846return ret;4847}48484849static int si_program_memory_timing_parameters(struct amdgpu_device *adev,4850struct amdgpu_ps *amdgpu_new_state)4851{4852return si_do_program_memory_timing_parameters(adev, amdgpu_new_state,4853SISLANDS_DRIVER_STATE_ARB_INDEX);4854}48554856static int si_populate_initial_mvdd_value(struct amdgpu_device *adev,4857struct SISLANDS_SMC_VOLTAGE_VALUE *voltage)4858{4859struct rv7xx_power_info *pi = rv770_get_pi(adev);4860struct si_power_info *si_pi = si_get_pi(adev);48614862if (pi->mvdd_control)4863return si_populate_voltage_value(adev, &si_pi->mvdd_voltage_table,4864si_pi->mvdd_bootup_value, voltage);48654866return 0;4867}48684869static int si_populate_smc_initial_state(struct amdgpu_device *adev,4870struct amdgpu_ps *amdgpu_initial_state,4871SISLANDS_SMC_STATETABLE *table)4872{4873struct si_ps *initial_state = si_get_ps(amdgpu_initial_state);4874struct rv7xx_power_info *pi = rv770_get_pi(adev);4875struct evergreen_power_info *eg_pi = evergreen_get_pi(adev);4876struct si_power_info *si_pi = si_get_pi(adev);4877u32 reg;4878int ret;48794880table->initialState.level.mclk.vDLL_CNTL =4881cpu_to_be32(si_pi->clock_registers.dll_cntl);4882table->initialState.level.mclk.vMCLK_PWRMGT_CNTL =4883cpu_to_be32(si_pi->clock_registers.mclk_pwrmgt_cntl);4884table->initialState.level.mclk.vMPLL_AD_FUNC_CNTL =4885cpu_to_be32(si_pi->clock_registers.mpll_ad_func_cntl);4886table->initialState.level.mclk.vMPLL_DQ_FUNC_CNTL =4887cpu_to_be32(si_pi->clock_registers.mpll_dq_func_cntl);4888table->initialState.level.mclk.vMPLL_FUNC_CNTL =4889cpu_to_be32(si_pi->clock_registers.mpll_func_cntl);4890table->initialState.level.mclk.vMPLL_FUNC_CNTL_1 =4891cpu_to_be32(si_pi->clock_registers.mpll_func_cntl_1);4892table->initialState.level.mclk.vMPLL_FUNC_CNTL_2 =4893cpu_to_be32(si_pi->clock_registers.mpll_func_cntl_2);4894table->initialState.level.mclk.vMPLL_SS =4895cpu_to_be32(si_pi->clock_registers.mpll_ss1);4896table->initialState.level.mclk.vMPLL_SS2 =4897cpu_to_be32(si_pi->clock_registers.mpll_ss2);48984899table->initialState.level.mclk.mclk_value =4900cpu_to_be32(initial_state->performance_levels[0].mclk);49014902table->initialState.level.sclk.vCG_SPLL_FUNC_CNTL =4903cpu_to_be32(si_pi->clock_registers.cg_spll_func_cntl);4904table->initialState.level.sclk.vCG_SPLL_FUNC_CNTL_2 =4905cpu_to_be32(si_pi->clock_registers.cg_spll_func_cntl_2);4906table->initialState.level.sclk.vCG_SPLL_FUNC_CNTL_3 =4907cpu_to_be32(si_pi->clock_registers.cg_spll_func_cntl_3);4908table->initialState.level.sclk.vCG_SPLL_FUNC_CNTL_4 =4909cpu_to_be32(si_pi->clock_registers.cg_spll_func_cntl_4);4910table->initialState.level.sclk.vCG_SPLL_SPREAD_SPECTRUM =4911cpu_to_be32(si_pi->clock_registers.cg_spll_spread_spectrum);4912table->initialState.level.sclk.vCG_SPLL_SPREAD_SPECTRUM_2 =4913cpu_to_be32(si_pi->clock_registers.cg_spll_spread_spectrum_2);49144915table->initialState.level.sclk.sclk_value =4916cpu_to_be32(initial_state->performance_levels[0].sclk);49174918table->initialState.level.arbRefreshState =4919SISLANDS_INITIAL_STATE_ARB_INDEX;49204921table->initialState.level.ACIndex = 0;49224923ret = si_populate_voltage_value(adev, &eg_pi->vddc_voltage_table,4924initial_state->performance_levels[0].vddc,4925&table->initialState.level.vddc);49264927if (!ret) {4928u16 std_vddc;49294930ret = si_get_std_voltage_value(adev,4931&table->initialState.level.vddc,4932&std_vddc);4933if (!ret)4934si_populate_std_voltage_value(adev, std_vddc,4935table->initialState.level.vddc.index,4936&table->initialState.level.std_vddc);4937}49384939if (eg_pi->vddci_control)4940si_populate_voltage_value(adev,4941&eg_pi->vddci_voltage_table,4942initial_state->performance_levels[0].vddci,4943&table->initialState.level.vddci);49444945if (si_pi->vddc_phase_shed_control)4946si_populate_phase_shedding_value(adev,4947&adev->pm.dpm.dyn_state.phase_shedding_limits_table,4948initial_state->performance_levels[0].vddc,4949initial_state->performance_levels[0].sclk,4950initial_state->performance_levels[0].mclk,4951&table->initialState.level.vddc);49524953si_populate_initial_mvdd_value(adev, &table->initialState.level.mvdd);49544955reg = 0xffff << CG_AT__CG_R__SHIFT | 0 << CG_AT__CG_L__SHIFT;4956table->initialState.level.aT = cpu_to_be32(reg);4957table->initialState.level.bSP = cpu_to_be32(pi->dsp);4958table->initialState.level.gen2PCIE = (u8)si_pi->boot_pcie_gen;49594960if (adev->gmc.vram_type == AMDGPU_VRAM_TYPE_GDDR5) {4961table->initialState.level.strobeMode =4962si_get_strobe_mode_settings(adev,4963initial_state->performance_levels[0].mclk);49644965if (initial_state->performance_levels[0].mclk > pi->mclk_edc_enable_threshold)4966table->initialState.level.mcFlags = SISLANDS_SMC_MC_EDC_RD_FLAG | SISLANDS_SMC_MC_EDC_WR_FLAG;4967else4968table->initialState.level.mcFlags = 0;4969}49704971table->initialState.levelCount = 1;49724973table->initialState.flags |= PPSMC_SWSTATE_FLAG_DC;49744975table->initialState.level.dpm2.MaxPS = 0;4976table->initialState.level.dpm2.NearTDPDec = 0;4977table->initialState.level.dpm2.AboveSafeInc = 0;4978table->initialState.level.dpm2.BelowSafeInc = 0;4979table->initialState.level.dpm2.PwrEfficiencyRatio = 0;49804981reg = SQ_POWER_THROTTLE__MIN_POWER_MASK |4982SQ_POWER_THROTTLE__MAX_POWER_MASK;4983table->initialState.level.SQPowerThrottle = cpu_to_be32(reg);49844985reg = SQ_POWER_THROTTLE2__MAX_POWER_DELTA_MASK |4986SQ_POWER_THROTTLE2__SHORT_TERM_INTERVAL_SIZE_MASK |4987SQ_POWER_THROTTLE2__LONG_TERM_INTERVAL_RATIO_MASK;4988table->initialState.level.SQPowerThrottle_2 = cpu_to_be32(reg);49894990return 0;4991}49924993static enum si_pcie_gen si_gen_pcie_gen_support(struct amdgpu_device *adev,4994u32 sys_mask,4995enum si_pcie_gen asic_gen,4996enum si_pcie_gen default_gen)4997{4998switch (asic_gen) {4999case SI_PCIE_GEN1:5000return SI_PCIE_GEN1;5001case SI_PCIE_GEN2:5002return SI_PCIE_GEN2;5003case SI_PCIE_GEN3:5004return SI_PCIE_GEN3;5005default:5006if ((sys_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3) &&5007(default_gen == SI_PCIE_GEN3))5008return SI_PCIE_GEN3;5009else if ((sys_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2) &&5010(default_gen == SI_PCIE_GEN2))5011return SI_PCIE_GEN2;5012else5013return SI_PCIE_GEN1;5014}5015return SI_PCIE_GEN1;5016}50175018static int si_populate_smc_acpi_state(struct amdgpu_device *adev,5019SISLANDS_SMC_STATETABLE *table)5020{5021struct rv7xx_power_info *pi = rv770_get_pi(adev);5022struct evergreen_power_info *eg_pi = evergreen_get_pi(adev);5023struct si_power_info *si_pi = si_get_pi(adev);5024u32 spll_func_cntl = si_pi->clock_registers.cg_spll_func_cntl;5025u32 spll_func_cntl_2 = si_pi->clock_registers.cg_spll_func_cntl_2;5026u32 spll_func_cntl_3 = si_pi->clock_registers.cg_spll_func_cntl_3;5027u32 spll_func_cntl_4 = si_pi->clock_registers.cg_spll_func_cntl_4;5028u32 dll_cntl = si_pi->clock_registers.dll_cntl;5029u32 mclk_pwrmgt_cntl = si_pi->clock_registers.mclk_pwrmgt_cntl;5030u32 mpll_ad_func_cntl = si_pi->clock_registers.mpll_ad_func_cntl;5031u32 mpll_dq_func_cntl = si_pi->clock_registers.mpll_dq_func_cntl;5032u32 mpll_func_cntl = si_pi->clock_registers.mpll_func_cntl;5033u32 mpll_func_cntl_1 = si_pi->clock_registers.mpll_func_cntl_1;5034u32 mpll_func_cntl_2 = si_pi->clock_registers.mpll_func_cntl_2;5035u32 reg;5036int ret;50375038table->ACPIState = table->initialState;50395040table->ACPIState.flags &= ~PPSMC_SWSTATE_FLAG_DC;50415042if (pi->acpi_vddc) {5043ret = si_populate_voltage_value(adev, &eg_pi->vddc_voltage_table,5044pi->acpi_vddc, &table->ACPIState.level.vddc);5045if (!ret) {5046u16 std_vddc;50475048ret = si_get_std_voltage_value(adev,5049&table->ACPIState.level.vddc, &std_vddc);5050if (!ret)5051si_populate_std_voltage_value(adev, std_vddc,5052table->ACPIState.level.vddc.index,5053&table->ACPIState.level.std_vddc);5054}5055table->ACPIState.level.gen2PCIE = si_pi->acpi_pcie_gen;50565057if (si_pi->vddc_phase_shed_control) {5058si_populate_phase_shedding_value(adev,5059&adev->pm.dpm.dyn_state.phase_shedding_limits_table,5060pi->acpi_vddc,50610,50620,5063&table->ACPIState.level.vddc);5064}5065} else {5066ret = si_populate_voltage_value(adev, &eg_pi->vddc_voltage_table,5067pi->min_vddc_in_table, &table->ACPIState.level.vddc);5068if (!ret) {5069u16 std_vddc;50705071ret = si_get_std_voltage_value(adev,5072&table->ACPIState.level.vddc, &std_vddc);50735074if (!ret)5075si_populate_std_voltage_value(adev, std_vddc,5076table->ACPIState.level.vddc.index,5077&table->ACPIState.level.std_vddc);5078}5079table->ACPIState.level.gen2PCIE =5080(u8)si_gen_pcie_gen_support(adev,5081si_pi->sys_pcie_mask,5082si_pi->boot_pcie_gen,5083SI_PCIE_GEN1);50845085if (si_pi->vddc_phase_shed_control)5086si_populate_phase_shedding_value(adev,5087&adev->pm.dpm.dyn_state.phase_shedding_limits_table,5088pi->min_vddc_in_table,50890,50900,5091&table->ACPIState.level.vddc);5092}50935094if (pi->acpi_vddc) {5095if (eg_pi->acpi_vddci)5096si_populate_voltage_value(adev, &eg_pi->vddci_voltage_table,5097eg_pi->acpi_vddci,5098&table->ACPIState.level.vddci);5099}51005101mclk_pwrmgt_cntl |= MRDCK0_RESET | MRDCK1_RESET;5102mclk_pwrmgt_cntl &= ~(MRDCK0_PDNB | MRDCK1_PDNB);51035104dll_cntl &= ~(MRDCK0_BYPASS | MRDCK1_BYPASS);51055106spll_func_cntl_2 &= ~CG_SPLL_FUNC_CNTL_2__SCLK_MUX_SEL_MASK;5107spll_func_cntl_2 |= 4 << CG_SPLL_FUNC_CNTL_2__SCLK_MUX_SEL__SHIFT;51085109table->ACPIState.level.mclk.vDLL_CNTL =5110cpu_to_be32(dll_cntl);5111table->ACPIState.level.mclk.vMCLK_PWRMGT_CNTL =5112cpu_to_be32(mclk_pwrmgt_cntl);5113table->ACPIState.level.mclk.vMPLL_AD_FUNC_CNTL =5114cpu_to_be32(mpll_ad_func_cntl);5115table->ACPIState.level.mclk.vMPLL_DQ_FUNC_CNTL =5116cpu_to_be32(mpll_dq_func_cntl);5117table->ACPIState.level.mclk.vMPLL_FUNC_CNTL =5118cpu_to_be32(mpll_func_cntl);5119table->ACPIState.level.mclk.vMPLL_FUNC_CNTL_1 =5120cpu_to_be32(mpll_func_cntl_1);5121table->ACPIState.level.mclk.vMPLL_FUNC_CNTL_2 =5122cpu_to_be32(mpll_func_cntl_2);5123table->ACPIState.level.mclk.vMPLL_SS =5124cpu_to_be32(si_pi->clock_registers.mpll_ss1);5125table->ACPIState.level.mclk.vMPLL_SS2 =5126cpu_to_be32(si_pi->clock_registers.mpll_ss2);51275128table->ACPIState.level.sclk.vCG_SPLL_FUNC_CNTL =5129cpu_to_be32(spll_func_cntl);5130table->ACPIState.level.sclk.vCG_SPLL_FUNC_CNTL_2 =5131cpu_to_be32(spll_func_cntl_2);5132table->ACPIState.level.sclk.vCG_SPLL_FUNC_CNTL_3 =5133cpu_to_be32(spll_func_cntl_3);5134table->ACPIState.level.sclk.vCG_SPLL_FUNC_CNTL_4 =5135cpu_to_be32(spll_func_cntl_4);51365137table->ACPIState.level.mclk.mclk_value = 0;5138table->ACPIState.level.sclk.sclk_value = 0;51395140si_populate_mvdd_value(adev, 0, &table->ACPIState.level.mvdd);51415142if (eg_pi->dynamic_ac_timing)5143table->ACPIState.level.ACIndex = 0;51445145table->ACPIState.level.dpm2.MaxPS = 0;5146table->ACPIState.level.dpm2.NearTDPDec = 0;5147table->ACPIState.level.dpm2.AboveSafeInc = 0;5148table->ACPIState.level.dpm2.BelowSafeInc = 0;5149table->ACPIState.level.dpm2.PwrEfficiencyRatio = 0;51505151reg = SQ_POWER_THROTTLE__MIN_POWER_MASK | SQ_POWER_THROTTLE__MAX_POWER_MASK;5152table->ACPIState.level.SQPowerThrottle = cpu_to_be32(reg);51535154reg = SQ_POWER_THROTTLE2__MAX_POWER_DELTA_MASK | SQ_POWER_THROTTLE2__SHORT_TERM_INTERVAL_SIZE_MASK | SQ_POWER_THROTTLE2__LONG_TERM_INTERVAL_RATIO_MASK;5155table->ACPIState.level.SQPowerThrottle_2 = cpu_to_be32(reg);51565157return 0;5158}51595160static int si_populate_ulv_state(struct amdgpu_device *adev,5161struct SISLANDS_SMC_SWSTATE_SINGLE *state)5162{5163struct evergreen_power_info *eg_pi = evergreen_get_pi(adev);5164struct si_power_info *si_pi = si_get_pi(adev);5165struct si_ulv_param *ulv = &si_pi->ulv;5166u32 sclk_in_sr = 1350; /* ??? */5167int ret;51685169ret = si_convert_power_level_to_smc(adev, &ulv->pl,5170&state->level);5171if (!ret) {5172if (eg_pi->sclk_deep_sleep) {5173if (sclk_in_sr <= SCLK_MIN_DEEPSLEEP_FREQ)5174state->level.stateFlags |= PPSMC_STATEFLAG_DEEPSLEEP_BYPASS;5175else5176state->level.stateFlags |= PPSMC_STATEFLAG_DEEPSLEEP_THROTTLE;5177}5178if (ulv->one_pcie_lane_in_ulv)5179state->flags |= PPSMC_SWSTATE_FLAG_PCIE_X1;5180state->level.arbRefreshState = (u8)(SISLANDS_ULV_STATE_ARB_INDEX);5181state->level.ACIndex = 1;5182state->level.std_vddc = state->level.vddc;5183state->levelCount = 1;51845185state->flags |= PPSMC_SWSTATE_FLAG_DC;5186}51875188return ret;5189}51905191static int si_program_ulv_memory_timing_parameters(struct amdgpu_device *adev)5192{5193struct si_power_info *si_pi = si_get_pi(adev);5194struct si_ulv_param *ulv = &si_pi->ulv;5195SMC_SIslands_MCArbDramTimingRegisterSet arb_regs = { 0 };5196int ret;51975198ret = si_populate_memory_timing_parameters(adev, &ulv->pl,5199&arb_regs);5200if (ret)5201return ret;52025203si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_ulv_volt_change_delay,5204ulv->volt_change_delay);52055206ret = amdgpu_si_copy_bytes_to_smc(adev,5207si_pi->arb_table_start +5208offsetof(SMC_SIslands_MCArbDramTimingRegisters, data) +5209sizeof(SMC_SIslands_MCArbDramTimingRegisterSet) * SISLANDS_ULV_STATE_ARB_INDEX,5210(u8 *)&arb_regs,5211sizeof(SMC_SIslands_MCArbDramTimingRegisterSet),5212si_pi->sram_end);52135214return ret;5215}52165217static void si_get_mvdd_configuration(struct amdgpu_device *adev)5218{5219struct rv7xx_power_info *pi = rv770_get_pi(adev);52205221pi->mvdd_split_frequency = 30000;5222}52235224static int si_init_smc_table(struct amdgpu_device *adev)5225{5226struct si_power_info *si_pi = si_get_pi(adev);5227struct amdgpu_ps *amdgpu_boot_state = adev->pm.dpm.boot_ps;5228const struct si_ulv_param *ulv = &si_pi->ulv;5229SISLANDS_SMC_STATETABLE *table = &si_pi->smc_statetable;5230int ret;5231u32 lane_width;5232u32 vr_hot_gpio;52335234si_populate_smc_voltage_tables(adev, table);52355236switch (adev->pm.int_thermal_type) {5237case THERMAL_TYPE_SI:5238case THERMAL_TYPE_EMC2103_WITH_INTERNAL:5239table->thermalProtectType = PPSMC_THERMAL_PROTECT_TYPE_INTERNAL;5240break;5241case THERMAL_TYPE_NONE:5242table->thermalProtectType = PPSMC_THERMAL_PROTECT_TYPE_NONE;5243break;5244default:5245table->thermalProtectType = PPSMC_THERMAL_PROTECT_TYPE_EXTERNAL;5246break;5247}52485249if (adev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_HARDWAREDC)5250table->systemFlags |= PPSMC_SYSTEMFLAG_GPIO_DC;52515252if (adev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_REGULATOR_HOT) {5253if ((adev->pdev->device != 0x6818) && (adev->pdev->device != 0x6819))5254table->systemFlags |= PPSMC_SYSTEMFLAG_REGULATOR_HOT;5255}52565257if (adev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_STEPVDDC)5258table->systemFlags |= PPSMC_SYSTEMFLAG_STEPVDDC;52595260if (adev->gmc.vram_type == AMDGPU_VRAM_TYPE_GDDR5)5261table->systemFlags |= PPSMC_SYSTEMFLAG_GDDR5;52625263if (adev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_REVERT_GPIO5_POLARITY)5264table->extraFlags |= PPSMC_EXTRAFLAGS_AC2DC_GPIO5_POLARITY_HIGH;52655266if (adev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_VRHOT_GPIO_CONFIGURABLE) {5267table->systemFlags |= PPSMC_SYSTEMFLAG_REGULATOR_HOT_PROG_GPIO;5268vr_hot_gpio = adev->pm.dpm.backbias_response_time;5269si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_vr_hot_gpio,5270vr_hot_gpio);5271}52725273ret = si_populate_smc_initial_state(adev, amdgpu_boot_state, table);5274if (ret)5275return ret;52765277ret = si_populate_smc_acpi_state(adev, table);5278if (ret)5279return ret;52805281table->driverState.flags = table->initialState.flags;5282table->driverState.levelCount = table->initialState.levelCount;5283table->driverState.levels[0] = table->initialState.level;52845285ret = si_do_program_memory_timing_parameters(adev, amdgpu_boot_state,5286SISLANDS_INITIAL_STATE_ARB_INDEX);5287if (ret)5288return ret;52895290if (ulv->supported && ulv->pl.vddc) {5291ret = si_populate_ulv_state(adev, &table->ULVState);5292if (ret)5293return ret;52945295ret = si_program_ulv_memory_timing_parameters(adev);5296if (ret)5297return ret;52985299WREG32(mmCG_ULV_CONTROL, ulv->cg_ulv_control);5300WREG32(mmCG_ULV_PARAMETER, ulv->cg_ulv_parameter);53015302lane_width = amdgpu_get_pcie_lanes(adev);5303si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_non_ulv_pcie_link_width, lane_width);5304} else {5305table->ULVState = table->initialState;5306}53075308return amdgpu_si_copy_bytes_to_smc(adev, si_pi->state_table_start,5309(u8 *)table, sizeof(SISLANDS_SMC_STATETABLE),5310si_pi->sram_end);5311}53125313static int si_calculate_sclk_params(struct amdgpu_device *adev,5314u32 engine_clock,5315SISLANDS_SMC_SCLK_VALUE *sclk)5316{5317struct rv7xx_power_info *pi = rv770_get_pi(adev);5318struct si_power_info *si_pi = si_get_pi(adev);5319struct atom_clock_dividers dividers;5320u32 spll_func_cntl = si_pi->clock_registers.cg_spll_func_cntl;5321u32 spll_func_cntl_2 = si_pi->clock_registers.cg_spll_func_cntl_2;5322u32 spll_func_cntl_3 = si_pi->clock_registers.cg_spll_func_cntl_3;5323u32 spll_func_cntl_4 = si_pi->clock_registers.cg_spll_func_cntl_4;5324u32 cg_spll_spread_spectrum = si_pi->clock_registers.cg_spll_spread_spectrum;5325u32 cg_spll_spread_spectrum_2 = si_pi->clock_registers.cg_spll_spread_spectrum_2;5326u64 tmp;5327u32 reference_clock = adev->clock.spll.reference_freq;5328u32 reference_divider;5329u32 fbdiv;5330int ret;53315332ret = amdgpu_atombios_get_clock_dividers(adev, COMPUTE_ENGINE_PLL_PARAM,5333engine_clock, false, ÷rs);5334if (ret)5335return ret;53365337reference_divider = 1 + dividers.ref_div;53385339tmp = (u64) engine_clock * reference_divider * dividers.post_div * 16384;5340do_div(tmp, reference_clock);5341fbdiv = (u32) tmp;53425343spll_func_cntl &= ~(CG_SPLL_FUNC_CNTL__SPLL_PDIV_A_MASK | CG_SPLL_FUNC_CNTL__SPLL_REF_DIV_MASK);5344spll_func_cntl |= dividers.ref_div << CG_SPLL_FUNC_CNTL__SPLL_REF_DIV__SHIFT;5345spll_func_cntl |= dividers.post_div << CG_SPLL_FUNC_CNTL__SPLL_PDIV_A__SHIFT;53465347spll_func_cntl_2 &= ~CG_SPLL_FUNC_CNTL_2__SCLK_MUX_SEL_MASK;5348spll_func_cntl_2 |= 2 << CG_SPLL_FUNC_CNTL_2__SCLK_MUX_SEL__SHIFT;53495350spll_func_cntl_3 &= ~CG_SPLL_FUNC_CNTL_3__SPLL_FB_DIV_MASK;5351spll_func_cntl_3 |= fbdiv << CG_SPLL_FUNC_CNTL_3__SPLL_FB_DIV__SHIFT;5352spll_func_cntl_3 |= CG_SPLL_FUNC_CNTL_3__SPLL_DITHEN_MASK;53535354if (pi->sclk_ss) {5355struct amdgpu_atom_ss ss;5356u32 vco_freq = engine_clock * dividers.post_div;53575358if (amdgpu_atombios_get_asic_ss_info(adev, &ss,5359ASIC_INTERNAL_ENGINE_SS, vco_freq)) {5360u32 clk_s = reference_clock * 5 / (reference_divider * ss.rate);5361u32 clk_v = 4 * ss.percentage * fbdiv / (clk_s * 10000);53625363cg_spll_spread_spectrum &= ~CG_SPLL_SPREAD_SPECTRUM__CLK_S_MASK;5364cg_spll_spread_spectrum |= clk_s << CG_SPLL_SPREAD_SPECTRUM__CLK_S__SHIFT;5365cg_spll_spread_spectrum |= CG_SPLL_SPREAD_SPECTRUM__SSEN_MASK;53665367cg_spll_spread_spectrum_2 &= ~CG_SPLL_SPREAD_SPECTRUM_2__CLK_V_MASK;5368cg_spll_spread_spectrum_2 |= clk_v << CG_SPLL_SPREAD_SPECTRUM_2__CLK_V__SHIFT;5369}5370}53715372sclk->sclk_value = engine_clock;5373sclk->vCG_SPLL_FUNC_CNTL = spll_func_cntl;5374sclk->vCG_SPLL_FUNC_CNTL_2 = spll_func_cntl_2;5375sclk->vCG_SPLL_FUNC_CNTL_3 = spll_func_cntl_3;5376sclk->vCG_SPLL_FUNC_CNTL_4 = spll_func_cntl_4;5377sclk->vCG_SPLL_SPREAD_SPECTRUM = cg_spll_spread_spectrum;5378sclk->vCG_SPLL_SPREAD_SPECTRUM_2 = cg_spll_spread_spectrum_2;53795380return 0;5381}53825383static int si_populate_sclk_value(struct amdgpu_device *adev,5384u32 engine_clock,5385SISLANDS_SMC_SCLK_VALUE *sclk)5386{5387SISLANDS_SMC_SCLK_VALUE sclk_tmp;5388int ret;53895390ret = si_calculate_sclk_params(adev, engine_clock, &sclk_tmp);5391if (!ret) {5392sclk->sclk_value = cpu_to_be32(sclk_tmp.sclk_value);5393sclk->vCG_SPLL_FUNC_CNTL = cpu_to_be32(sclk_tmp.vCG_SPLL_FUNC_CNTL);5394sclk->vCG_SPLL_FUNC_CNTL_2 = cpu_to_be32(sclk_tmp.vCG_SPLL_FUNC_CNTL_2);5395sclk->vCG_SPLL_FUNC_CNTL_3 = cpu_to_be32(sclk_tmp.vCG_SPLL_FUNC_CNTL_3);5396sclk->vCG_SPLL_FUNC_CNTL_4 = cpu_to_be32(sclk_tmp.vCG_SPLL_FUNC_CNTL_4);5397sclk->vCG_SPLL_SPREAD_SPECTRUM = cpu_to_be32(sclk_tmp.vCG_SPLL_SPREAD_SPECTRUM);5398sclk->vCG_SPLL_SPREAD_SPECTRUM_2 = cpu_to_be32(sclk_tmp.vCG_SPLL_SPREAD_SPECTRUM_2);5399}54005401return ret;5402}54035404static int si_populate_mclk_value(struct amdgpu_device *adev,5405u32 engine_clock,5406u32 memory_clock,5407SISLANDS_SMC_MCLK_VALUE *mclk,5408bool strobe_mode,5409bool dll_state_on)5410{5411struct rv7xx_power_info *pi = rv770_get_pi(adev);5412struct si_power_info *si_pi = si_get_pi(adev);5413u32 dll_cntl = si_pi->clock_registers.dll_cntl;5414u32 mclk_pwrmgt_cntl = si_pi->clock_registers.mclk_pwrmgt_cntl;5415u32 mpll_ad_func_cntl = si_pi->clock_registers.mpll_ad_func_cntl;5416u32 mpll_dq_func_cntl = si_pi->clock_registers.mpll_dq_func_cntl;5417u32 mpll_func_cntl = si_pi->clock_registers.mpll_func_cntl;5418u32 mpll_func_cntl_1 = si_pi->clock_registers.mpll_func_cntl_1;5419u32 mpll_func_cntl_2 = si_pi->clock_registers.mpll_func_cntl_2;5420u32 mpll_ss1 = si_pi->clock_registers.mpll_ss1;5421u32 mpll_ss2 = si_pi->clock_registers.mpll_ss2;5422struct atom_mpll_param mpll_param;5423int ret;54245425ret = amdgpu_atombios_get_memory_pll_dividers(adev, memory_clock, strobe_mode, &mpll_param);5426if (ret)5427return ret;54285429mpll_func_cntl &= ~BWCTRL_MASK;5430mpll_func_cntl |= BWCTRL(mpll_param.bwcntl);54315432mpll_func_cntl_1 &= ~(CLKF_MASK | CLKFRAC_MASK | VCO_MODE_MASK);5433mpll_func_cntl_1 |= CLKF(mpll_param.clkf) |5434CLKFRAC(mpll_param.clkfrac) | VCO_MODE(mpll_param.vco_mode);54355436mpll_ad_func_cntl &= ~YCLK_POST_DIV_MASK;5437mpll_ad_func_cntl |= YCLK_POST_DIV(mpll_param.post_div);54385439if (adev->gmc.vram_type == AMDGPU_VRAM_TYPE_GDDR5) {5440mpll_dq_func_cntl &= ~(YCLK_SEL_MASK | YCLK_POST_DIV_MASK);5441mpll_dq_func_cntl |= YCLK_SEL(mpll_param.yclk_sel) |5442YCLK_POST_DIV(mpll_param.post_div);5443}54445445if (pi->mclk_ss) {5446struct amdgpu_atom_ss ss;5447u32 freq_nom;5448u32 tmp;5449u32 reference_clock = adev->clock.mpll.reference_freq;54505451if (adev->gmc.vram_type == AMDGPU_VRAM_TYPE_GDDR5)5452freq_nom = memory_clock * 4;5453else5454freq_nom = memory_clock * 2;54555456tmp = freq_nom / reference_clock;5457tmp = tmp * tmp;5458if (amdgpu_atombios_get_asic_ss_info(adev, &ss,5459ASIC_INTERNAL_MEMORY_SS, freq_nom)) {5460u32 clks = reference_clock * 5 / ss.rate;5461u32 clkv = (u32)((((131 * ss.percentage * ss.rate) / 100) * tmp) / freq_nom);54625463mpll_ss1 &= ~CLKV_MASK;5464mpll_ss1 |= CLKV(clkv);54655466mpll_ss2 &= ~CLKS_MASK;5467mpll_ss2 |= CLKS(clks);5468}5469}54705471mclk_pwrmgt_cntl &= ~DLL_SPEED_MASK;5472mclk_pwrmgt_cntl |= DLL_SPEED(mpll_param.dll_speed);54735474if (dll_state_on)5475mclk_pwrmgt_cntl |= MRDCK0_PDNB | MRDCK1_PDNB;5476else5477mclk_pwrmgt_cntl &= ~(MRDCK0_PDNB | MRDCK1_PDNB);54785479mclk->mclk_value = cpu_to_be32(memory_clock);5480mclk->vMPLL_FUNC_CNTL = cpu_to_be32(mpll_func_cntl);5481mclk->vMPLL_FUNC_CNTL_1 = cpu_to_be32(mpll_func_cntl_1);5482mclk->vMPLL_FUNC_CNTL_2 = cpu_to_be32(mpll_func_cntl_2);5483mclk->vMPLL_AD_FUNC_CNTL = cpu_to_be32(mpll_ad_func_cntl);5484mclk->vMPLL_DQ_FUNC_CNTL = cpu_to_be32(mpll_dq_func_cntl);5485mclk->vMCLK_PWRMGT_CNTL = cpu_to_be32(mclk_pwrmgt_cntl);5486mclk->vDLL_CNTL = cpu_to_be32(dll_cntl);5487mclk->vMPLL_SS = cpu_to_be32(mpll_ss1);5488mclk->vMPLL_SS2 = cpu_to_be32(mpll_ss2);54895490return 0;5491}54925493static void si_populate_smc_sp(struct amdgpu_device *adev,5494struct amdgpu_ps *amdgpu_state,5495SISLANDS_SMC_SWSTATE *smc_state)5496{5497struct si_ps *ps = si_get_ps(amdgpu_state);5498struct rv7xx_power_info *pi = rv770_get_pi(adev);5499int i;55005501for (i = 0; i < ps->performance_level_count - 1; i++)5502smc_state->levels[i].bSP = cpu_to_be32(pi->dsp);55035504smc_state->levels[ps->performance_level_count - 1].bSP =5505cpu_to_be32(pi->psp);5506}55075508static int si_convert_power_level_to_smc(struct amdgpu_device *adev,5509struct rv7xx_pl *pl,5510SISLANDS_SMC_HW_PERFORMANCE_LEVEL *level)5511{5512struct rv7xx_power_info *pi = rv770_get_pi(adev);5513struct evergreen_power_info *eg_pi = evergreen_get_pi(adev);5514struct si_power_info *si_pi = si_get_pi(adev);5515int ret;5516bool dll_state_on;5517u16 std_vddc;55185519if (eg_pi->pcie_performance_request &&5520(si_pi->force_pcie_gen != SI_PCIE_GEN_INVALID))5521level->gen2PCIE = (u8)si_pi->force_pcie_gen;5522else5523level->gen2PCIE = (u8)pl->pcie_gen;55245525ret = si_populate_sclk_value(adev, pl->sclk, &level->sclk);5526if (ret)5527return ret;55285529level->mcFlags = 0;55305531if (pi->mclk_stutter_mode_threshold &&5532(pl->mclk <= pi->mclk_stutter_mode_threshold) &&5533!eg_pi->uvd_enabled &&5534(RREG32(mmDPG_PIPE_STUTTER_CONTROL) & DPG_PIPE_STUTTER_CONTROL__STUTTER_ENABLE_MASK) &&5535(adev->pm.pm_display_cfg.num_display <= 2)) {5536level->mcFlags |= SISLANDS_SMC_MC_STUTTER_EN;5537}55385539if (adev->gmc.vram_type == AMDGPU_VRAM_TYPE_GDDR5) {5540if (pl->mclk > pi->mclk_edc_enable_threshold)5541level->mcFlags |= SISLANDS_SMC_MC_EDC_RD_FLAG;55425543if (pl->mclk > eg_pi->mclk_edc_wr_enable_threshold)5544level->mcFlags |= SISLANDS_SMC_MC_EDC_WR_FLAG;55455546level->strobeMode = si_get_strobe_mode_settings(adev, pl->mclk);55475548if (level->strobeMode & SISLANDS_SMC_STROBE_ENABLE) {5549if (si_get_mclk_frequency_ratio(pl->mclk, true) >=5550((RREG32(MC_SEQ_MISC7) >> 16) & 0xf))5551dll_state_on = ((RREG32(MC_SEQ_MISC5) >> 1) & 0x1) ? true : false;5552else5553dll_state_on = ((RREG32(MC_SEQ_MISC6) >> 1) & 0x1) ? true : false;5554} else {5555dll_state_on = false;5556}5557} else {5558level->strobeMode = si_get_strobe_mode_settings(adev,5559pl->mclk);55605561dll_state_on = ((RREG32(MC_SEQ_MISC5) >> 1) & 0x1) ? true : false;5562}55635564ret = si_populate_mclk_value(adev,5565pl->sclk,5566pl->mclk,5567&level->mclk,5568(level->strobeMode & SISLANDS_SMC_STROBE_ENABLE) != 0, dll_state_on);5569if (ret)5570return ret;55715572ret = si_populate_voltage_value(adev,5573&eg_pi->vddc_voltage_table,5574pl->vddc, &level->vddc);5575if (ret)5576return ret;557755785579ret = si_get_std_voltage_value(adev, &level->vddc, &std_vddc);5580if (ret)5581return ret;55825583ret = si_populate_std_voltage_value(adev, std_vddc,5584level->vddc.index, &level->std_vddc);5585if (ret)5586return ret;55875588if (eg_pi->vddci_control) {5589ret = si_populate_voltage_value(adev, &eg_pi->vddci_voltage_table,5590pl->vddci, &level->vddci);5591if (ret)5592return ret;5593}55945595if (si_pi->vddc_phase_shed_control) {5596ret = si_populate_phase_shedding_value(adev,5597&adev->pm.dpm.dyn_state.phase_shedding_limits_table,5598pl->vddc,5599pl->sclk,5600pl->mclk,5601&level->vddc);5602if (ret)5603return ret;5604}56055606level->MaxPoweredUpCU = si_pi->max_cu;56075608ret = si_populate_mvdd_value(adev, pl->mclk, &level->mvdd);56095610return ret;5611}56125613static int si_populate_smc_t(struct amdgpu_device *adev,5614struct amdgpu_ps *amdgpu_state,5615SISLANDS_SMC_SWSTATE *smc_state)5616{5617struct rv7xx_power_info *pi = rv770_get_pi(adev);5618struct si_ps *state = si_get_ps(amdgpu_state);5619u32 a_t;5620u32 t_l, t_h;5621u32 high_bsp;5622int i, ret;56235624if (state->performance_level_count >= 9)5625return -EINVAL;56265627if (state->performance_level_count < 2) {5628a_t = 0xffff << CG_AT__CG_R__SHIFT | 0 << CG_AT__CG_L__SHIFT;5629smc_state->levels[0].aT = cpu_to_be32(a_t);5630return 0;5631}56325633smc_state->levels[0].aT = cpu_to_be32(0);56345635for (i = 0; i <= state->performance_level_count - 2; i++) {5636ret = r600_calculate_at(5637(50 / SISLANDS_MAX_HARDWARE_POWERLEVELS) * 100 * (i + 1),5638100 * R600_AH_DFLT,5639state->performance_levels[i + 1].sclk,5640state->performance_levels[i].sclk,5641&t_l,5642&t_h);56435644if (ret) {5645t_h = (i + 1) * 1000 - 50 * R600_AH_DFLT;5646t_l = (i + 1) * 1000 + 50 * R600_AH_DFLT;5647}56485649a_t = be32_to_cpu(smc_state->levels[i].aT) & ~CG_AT__CG_R_MASK;5650a_t |= (t_l * pi->bsp / 20000) << CG_AT__CG_R__SHIFT;5651smc_state->levels[i].aT = cpu_to_be32(a_t);56525653high_bsp = (i == state->performance_level_count - 2) ?5654pi->pbsp : pi->bsp;5655a_t = (0xffff) << CG_AT__CG_R__SHIFT | (t_h * high_bsp / 20000) << CG_AT__CG_L__SHIFT;5656smc_state->levels[i + 1].aT = cpu_to_be32(a_t);5657}56585659return 0;5660}56615662static int si_disable_ulv(struct amdgpu_device *adev)5663{5664PPSMC_Result r;56655666r = amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_DisableULV);5667return (r == PPSMC_Result_OK) ? 0 : -EINVAL;5668}56695670static bool si_is_state_ulv_compatible(struct amdgpu_device *adev,5671struct amdgpu_ps *amdgpu_state)5672{5673const struct si_power_info *si_pi = si_get_pi(adev);5674const struct si_ulv_param *ulv = &si_pi->ulv;5675const struct si_ps *state = si_get_ps(amdgpu_state);5676int i;56775678if (state->performance_levels[0].mclk != ulv->pl.mclk)5679return false;56805681/* XXX validate against display requirements! */56825683for (i = 0; i < adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.count; i++) {5684if (adev->pm.pm_display_cfg.display_clk <=5685adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[i].clk) {5686if (ulv->pl.vddc <5687adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[i].v)5688return false;5689}5690}56915692if ((amdgpu_state->vclk != 0) || (amdgpu_state->dclk != 0))5693return false;56945695return true;5696}56975698static int si_set_power_state_conditionally_enable_ulv(struct amdgpu_device *adev,5699struct amdgpu_ps *amdgpu_new_state)5700{5701const struct si_power_info *si_pi = si_get_pi(adev);5702const struct si_ulv_param *ulv = &si_pi->ulv;57035704if (ulv->supported) {5705if (si_is_state_ulv_compatible(adev, amdgpu_new_state))5706return (amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_EnableULV) == PPSMC_Result_OK) ?57070 : -EINVAL;5708}5709return 0;5710}57115712static int si_convert_power_state_to_smc(struct amdgpu_device *adev,5713struct amdgpu_ps *amdgpu_state,5714SISLANDS_SMC_SWSTATE *smc_state)5715{5716struct evergreen_power_info *eg_pi = evergreen_get_pi(adev);5717struct ni_power_info *ni_pi = ni_get_pi(adev);5718struct si_power_info *si_pi = si_get_pi(adev);5719struct si_ps *state = si_get_ps(amdgpu_state);5720int i, ret;5721u32 threshold;5722u32 sclk_in_sr = 1350; /* ??? */57235724if (state->performance_level_count > SISLANDS_MAX_HARDWARE_POWERLEVELS)5725return -EINVAL;57265727threshold = state->performance_levels[state->performance_level_count-1].sclk * 100 / 100;57285729if (amdgpu_state->vclk && amdgpu_state->dclk) {5730eg_pi->uvd_enabled = true;5731if (eg_pi->smu_uvd_hs)5732smc_state->flags |= PPSMC_SWSTATE_FLAG_UVD;5733} else {5734eg_pi->uvd_enabled = false;5735}57365737if (state->dc_compatible)5738smc_state->flags |= PPSMC_SWSTATE_FLAG_DC;57395740smc_state->levelCount = 0;5741for (i = 0; i < state->performance_level_count; i++) {5742if (eg_pi->sclk_deep_sleep) {5743if ((i == 0) || si_pi->sclk_deep_sleep_above_low) {5744if (sclk_in_sr <= SCLK_MIN_DEEPSLEEP_FREQ)5745smc_state->levels[i].stateFlags |= PPSMC_STATEFLAG_DEEPSLEEP_BYPASS;5746else5747smc_state->levels[i].stateFlags |= PPSMC_STATEFLAG_DEEPSLEEP_THROTTLE;5748}5749}57505751ret = si_convert_power_level_to_smc(adev, &state->performance_levels[i],5752&smc_state->levels[i]);5753smc_state->levels[i].arbRefreshState =5754(u8)(SISLANDS_DRIVER_STATE_ARB_INDEX + i);57555756if (ret)5757return ret;57585759if (ni_pi->enable_power_containment)5760smc_state->levels[i].displayWatermark =5761(state->performance_levels[i].sclk < threshold) ?5762PPSMC_DISPLAY_WATERMARK_LOW : PPSMC_DISPLAY_WATERMARK_HIGH;5763else5764smc_state->levels[i].displayWatermark = (i < 2) ?5765PPSMC_DISPLAY_WATERMARK_LOW : PPSMC_DISPLAY_WATERMARK_HIGH;57665767if (eg_pi->dynamic_ac_timing)5768smc_state->levels[i].ACIndex = SISLANDS_MCREGISTERTABLE_FIRST_DRIVERSTATE_SLOT + i;5769else5770smc_state->levels[i].ACIndex = 0;57715772smc_state->levelCount++;5773}57745775si_write_smc_soft_register(adev,5776SI_SMC_SOFT_REGISTER_watermark_threshold,5777threshold / 512);57785779si_populate_smc_sp(adev, amdgpu_state, smc_state);57805781ret = si_populate_power_containment_values(adev, amdgpu_state, smc_state);5782if (ret)5783ni_pi->enable_power_containment = false;57845785ret = si_populate_sq_ramping_values(adev, amdgpu_state, smc_state);5786if (ret)5787ni_pi->enable_sq_ramping = false;57885789return si_populate_smc_t(adev, amdgpu_state, smc_state);5790}57915792static int si_upload_sw_state(struct amdgpu_device *adev,5793struct amdgpu_ps *amdgpu_new_state)5794{5795struct si_power_info *si_pi = si_get_pi(adev);5796struct si_ps *new_state = si_get_ps(amdgpu_new_state);5797int ret;5798u32 address = si_pi->state_table_start +5799offsetof(SISLANDS_SMC_STATETABLE, driverState);5800SISLANDS_SMC_SWSTATE *smc_state = &si_pi->smc_statetable.driverState;5801size_t state_size = struct_size(smc_state, levels,5802new_state->performance_level_count);5803memset(smc_state, 0, state_size);58045805ret = si_convert_power_state_to_smc(adev, amdgpu_new_state, smc_state);5806if (ret)5807return ret;58085809return amdgpu_si_copy_bytes_to_smc(adev, address, (u8 *)smc_state,5810state_size, si_pi->sram_end);5811}58125813static int si_upload_ulv_state(struct amdgpu_device *adev)5814{5815struct si_power_info *si_pi = si_get_pi(adev);5816struct si_ulv_param *ulv = &si_pi->ulv;5817int ret = 0;58185819if (ulv->supported && ulv->pl.vddc) {5820u32 address = si_pi->state_table_start +5821offsetof(SISLANDS_SMC_STATETABLE, ULVState);5822struct SISLANDS_SMC_SWSTATE_SINGLE *smc_state = &si_pi->smc_statetable.ULVState;5823u32 state_size = sizeof(struct SISLANDS_SMC_SWSTATE_SINGLE);58245825memset(smc_state, 0, state_size);58265827ret = si_populate_ulv_state(adev, smc_state);5828if (!ret)5829ret = amdgpu_si_copy_bytes_to_smc(adev, address, (u8 *)smc_state,5830state_size, si_pi->sram_end);5831}58325833return ret;5834}58355836static int si_upload_smc_data(struct amdgpu_device *adev)5837{5838const struct amd_pp_display_configuration *cfg = &adev->pm.pm_display_cfg;5839u32 crtc_index = 0;5840u32 mclk_change_block_cp_min = 0;5841u32 mclk_change_block_cp_max = 0;58425843/* When a display is plugged in, program these so that the SMC5844* performs MCLK switching when it doesn't cause flickering.5845* When no display is plugged in, there is no need to restrict5846* MCLK switching, so program them to zero.5847*/5848if (cfg->num_display) {5849crtc_index = cfg->crtc_index;58505851if (cfg->line_time_in_us) {5852mclk_change_block_cp_min = 200 / cfg->line_time_in_us;5853mclk_change_block_cp_max = 100 / cfg->line_time_in_us;5854}5855}58565857si_write_smc_soft_register(adev,5858SI_SMC_SOFT_REGISTER_crtc_index,5859crtc_index);58605861si_write_smc_soft_register(adev,5862SI_SMC_SOFT_REGISTER_mclk_change_block_cp_min,5863mclk_change_block_cp_min);58645865si_write_smc_soft_register(adev,5866SI_SMC_SOFT_REGISTER_mclk_change_block_cp_max,5867mclk_change_block_cp_max);58685869return 0;5870}58715872static int si_set_mc_special_registers(struct amdgpu_device *adev,5873struct si_mc_reg_table *table)5874{5875u8 i, j, k;5876u32 temp_reg;58775878for (i = 0, j = table->last; i < table->last; i++) {5879if (j >= SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE)5880return -EINVAL;5881switch (table->mc_reg_address[i].s1) {5882case MC_SEQ_MISC1:5883temp_reg = RREG32(MC_PMG_CMD_EMRS);5884table->mc_reg_address[j].s1 = MC_PMG_CMD_EMRS;5885table->mc_reg_address[j].s0 = MC_SEQ_PMG_CMD_EMRS_LP;5886for (k = 0; k < table->num_entries; k++)5887table->mc_reg_table_entry[k].mc_data[j] =5888((temp_reg & 0xffff0000)) |5889((table->mc_reg_table_entry[k].mc_data[i] & 0xffff0000) >> 16);5890j++;58915892if (j >= SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE)5893return -EINVAL;5894temp_reg = RREG32(MC_PMG_CMD_MRS);5895table->mc_reg_address[j].s1 = MC_PMG_CMD_MRS;5896table->mc_reg_address[j].s0 = MC_SEQ_PMG_CMD_MRS_LP;5897for (k = 0; k < table->num_entries; k++) {5898table->mc_reg_table_entry[k].mc_data[j] =5899(temp_reg & 0xffff0000) |5900(table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff);5901if (adev->gmc.vram_type != AMDGPU_VRAM_TYPE_GDDR5)5902table->mc_reg_table_entry[k].mc_data[j] |= 0x100;5903}5904j++;59055906if (adev->gmc.vram_type != AMDGPU_VRAM_TYPE_GDDR5) {5907if (j >= SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE)5908return -EINVAL;5909table->mc_reg_address[j].s1 = MC_PMG_AUTO_CMD;5910table->mc_reg_address[j].s0 = MC_PMG_AUTO_CMD;5911for (k = 0; k < table->num_entries; k++)5912table->mc_reg_table_entry[k].mc_data[j] =5913(table->mc_reg_table_entry[k].mc_data[i] & 0xffff0000) >> 16;5914j++;5915}5916break;5917case MC_SEQ_RESERVE_M:5918temp_reg = RREG32(MC_PMG_CMD_MRS1);5919table->mc_reg_address[j].s1 = MC_PMG_CMD_MRS1;5920table->mc_reg_address[j].s0 = MC_SEQ_PMG_CMD_MRS1_LP;5921for(k = 0; k < table->num_entries; k++)5922table->mc_reg_table_entry[k].mc_data[j] =5923(temp_reg & 0xffff0000) |5924(table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff);5925j++;5926break;5927default:5928break;5929}5930}59315932table->last = j;59335934return 0;5935}59365937static bool si_check_s0_mc_reg_index(u16 in_reg, u16 *out_reg)5938{5939bool result = true;5940switch (in_reg) {5941case MC_SEQ_RAS_TIMING:5942*out_reg = MC_SEQ_RAS_TIMING_LP;5943break;5944case MC_SEQ_CAS_TIMING:5945*out_reg = MC_SEQ_CAS_TIMING_LP;5946break;5947case MC_SEQ_MISC_TIMING:5948*out_reg = MC_SEQ_MISC_TIMING_LP;5949break;5950case MC_SEQ_MISC_TIMING2:5951*out_reg = MC_SEQ_MISC_TIMING2_LP;5952break;5953case MC_SEQ_RD_CTL_D0:5954*out_reg = MC_SEQ_RD_CTL_D0_LP;5955break;5956case MC_SEQ_RD_CTL_D1:5957*out_reg = MC_SEQ_RD_CTL_D1_LP;5958break;5959case MC_SEQ_WR_CTL_D0:5960*out_reg = MC_SEQ_WR_CTL_D0_LP;5961break;5962case MC_SEQ_WR_CTL_D1:5963*out_reg = MC_SEQ_WR_CTL_D1_LP;5964break;5965case MC_PMG_CMD_EMRS:5966*out_reg = MC_SEQ_PMG_CMD_EMRS_LP;5967break;5968case MC_PMG_CMD_MRS:5969*out_reg = MC_SEQ_PMG_CMD_MRS_LP;5970break;5971case MC_PMG_CMD_MRS1:5972*out_reg = MC_SEQ_PMG_CMD_MRS1_LP;5973break;5974case MC_SEQ_PMG_TIMING:5975*out_reg = MC_SEQ_PMG_TIMING_LP;5976break;5977case MC_PMG_CMD_MRS2:5978*out_reg = MC_SEQ_PMG_CMD_MRS2_LP;5979break;5980case MC_SEQ_WR_CTL_2:5981*out_reg = MC_SEQ_WR_CTL_2_LP;5982break;5983default:5984result = false;5985break;5986}59875988return result;5989}59905991static void si_set_valid_flag(struct si_mc_reg_table *table)5992{5993u8 i, j;59945995for (i = 0; i < table->last; i++) {5996for (j = 1; j < table->num_entries; j++) {5997if (table->mc_reg_table_entry[j-1].mc_data[i] != table->mc_reg_table_entry[j].mc_data[i]) {5998table->valid_flag |= 1 << i;5999break;6000}6001}6002}6003}60046005static void si_set_s0_mc_reg_index(struct si_mc_reg_table *table)6006{6007u32 i;6008u16 address;60096010for (i = 0; i < table->last; i++)6011table->mc_reg_address[i].s0 = si_check_s0_mc_reg_index(table->mc_reg_address[i].s1, &address) ?6012address : table->mc_reg_address[i].s1;60136014}60156016static int si_copy_vbios_mc_reg_table(struct atom_mc_reg_table *table,6017struct si_mc_reg_table *si_table)6018{6019u8 i, j;60206021if (table->last > SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE)6022return -EINVAL;6023if (table->num_entries > MAX_AC_TIMING_ENTRIES)6024return -EINVAL;60256026for (i = 0; i < table->last; i++)6027si_table->mc_reg_address[i].s1 = table->mc_reg_address[i].s1;6028si_table->last = table->last;60296030for (i = 0; i < table->num_entries; i++) {6031si_table->mc_reg_table_entry[i].mclk_max =6032table->mc_reg_table_entry[i].mclk_max;6033for (j = 0; j < table->last; j++) {6034si_table->mc_reg_table_entry[i].mc_data[j] =6035table->mc_reg_table_entry[i].mc_data[j];6036}6037}6038si_table->num_entries = table->num_entries;60396040return 0;6041}60426043static int si_initialize_mc_reg_table(struct amdgpu_device *adev)6044{6045struct si_power_info *si_pi = si_get_pi(adev);6046struct atom_mc_reg_table *table;6047struct si_mc_reg_table *si_table = &si_pi->mc_reg_table;6048u8 module_index = rv770_get_memory_module_index(adev);6049int ret;60506051table = kzalloc(sizeof(struct atom_mc_reg_table), GFP_KERNEL);6052if (!table)6053return -ENOMEM;60546055WREG32(MC_SEQ_RAS_TIMING_LP, RREG32(MC_SEQ_RAS_TIMING));6056WREG32(MC_SEQ_CAS_TIMING_LP, RREG32(MC_SEQ_CAS_TIMING));6057WREG32(MC_SEQ_MISC_TIMING_LP, RREG32(MC_SEQ_MISC_TIMING));6058WREG32(MC_SEQ_MISC_TIMING2_LP, RREG32(MC_SEQ_MISC_TIMING2));6059WREG32(MC_SEQ_PMG_CMD_EMRS_LP, RREG32(MC_PMG_CMD_EMRS));6060WREG32(MC_SEQ_PMG_CMD_MRS_LP, RREG32(MC_PMG_CMD_MRS));6061WREG32(MC_SEQ_PMG_CMD_MRS1_LP, RREG32(MC_PMG_CMD_MRS1));6062WREG32(MC_SEQ_WR_CTL_D0_LP, RREG32(MC_SEQ_WR_CTL_D0));6063WREG32(MC_SEQ_WR_CTL_D1_LP, RREG32(MC_SEQ_WR_CTL_D1));6064WREG32(MC_SEQ_RD_CTL_D0_LP, RREG32(MC_SEQ_RD_CTL_D0));6065WREG32(MC_SEQ_RD_CTL_D1_LP, RREG32(MC_SEQ_RD_CTL_D1));6066WREG32(MC_SEQ_PMG_TIMING_LP, RREG32(MC_SEQ_PMG_TIMING));6067WREG32(MC_SEQ_PMG_CMD_MRS2_LP, RREG32(MC_PMG_CMD_MRS2));6068WREG32(MC_SEQ_WR_CTL_2_LP, RREG32(MC_SEQ_WR_CTL_2));60696070ret = amdgpu_atombios_init_mc_reg_table(adev, module_index, table);6071if (ret)6072goto init_mc_done;60736074ret = si_copy_vbios_mc_reg_table(table, si_table);6075if (ret)6076goto init_mc_done;60776078si_set_s0_mc_reg_index(si_table);60796080ret = si_set_mc_special_registers(adev, si_table);6081if (ret)6082goto init_mc_done;60836084si_set_valid_flag(si_table);60856086init_mc_done:6087kfree(table);60886089return ret;60906091}60926093static void si_populate_mc_reg_addresses(struct amdgpu_device *adev,6094SMC_SIslands_MCRegisters *mc_reg_table)6095{6096struct si_power_info *si_pi = si_get_pi(adev);6097u32 i, j;60986099for (i = 0, j = 0; j < si_pi->mc_reg_table.last; j++) {6100if (si_pi->mc_reg_table.valid_flag & (1 << j)) {6101if (i >= SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE)6102break;6103mc_reg_table->address[i].s0 =6104cpu_to_be16(si_pi->mc_reg_table.mc_reg_address[j].s0);6105mc_reg_table->address[i].s1 =6106cpu_to_be16(si_pi->mc_reg_table.mc_reg_address[j].s1);6107i++;6108}6109}6110mc_reg_table->last = (u8)i;6111}61126113static void si_convert_mc_registers(const struct si_mc_reg_entry *entry,6114SMC_SIslands_MCRegisterSet *data,6115u32 num_entries, u32 valid_flag)6116{6117u32 i, j;61186119for(i = 0, j = 0; j < num_entries; j++) {6120if (valid_flag & (1 << j)) {6121data->value[i] = cpu_to_be32(entry->mc_data[j]);6122i++;6123}6124}6125}61266127static void si_convert_mc_reg_table_entry_to_smc(struct amdgpu_device *adev,6128struct rv7xx_pl *pl,6129SMC_SIslands_MCRegisterSet *mc_reg_table_data)6130{6131struct si_power_info *si_pi = si_get_pi(adev);6132u32 i = 0;61336134for (i = 0; i < si_pi->mc_reg_table.num_entries; i++) {6135if (pl->mclk <= si_pi->mc_reg_table.mc_reg_table_entry[i].mclk_max)6136break;6137}61386139if ((i == si_pi->mc_reg_table.num_entries) && (i > 0))6140--i;61416142si_convert_mc_registers(&si_pi->mc_reg_table.mc_reg_table_entry[i],6143mc_reg_table_data, si_pi->mc_reg_table.last,6144si_pi->mc_reg_table.valid_flag);6145}61466147static void si_convert_mc_reg_table_to_smc(struct amdgpu_device *adev,6148struct amdgpu_ps *amdgpu_state,6149SMC_SIslands_MCRegisters *mc_reg_table)6150{6151struct si_ps *state = si_get_ps(amdgpu_state);6152int i;61536154for (i = 0; i < state->performance_level_count; i++) {6155si_convert_mc_reg_table_entry_to_smc(adev,6156&state->performance_levels[i],6157&mc_reg_table->data[SISLANDS_MCREGISTERTABLE_FIRST_DRIVERSTATE_SLOT + i]);6158}6159}61606161static int si_populate_mc_reg_table(struct amdgpu_device *adev,6162struct amdgpu_ps *amdgpu_boot_state)6163{6164struct si_ps *boot_state = si_get_ps(amdgpu_boot_state);6165struct si_power_info *si_pi = si_get_pi(adev);6166struct si_ulv_param *ulv = &si_pi->ulv;6167SMC_SIslands_MCRegisters *smc_mc_reg_table = &si_pi->smc_mc_reg_table;61686169memset(smc_mc_reg_table, 0, sizeof(SMC_SIslands_MCRegisters));61706171si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_seq_index, 1);61726173si_populate_mc_reg_addresses(adev, smc_mc_reg_table);61746175si_convert_mc_reg_table_entry_to_smc(adev, &boot_state->performance_levels[0],6176&smc_mc_reg_table->data[SISLANDS_MCREGISTERTABLE_INITIAL_SLOT]);61776178si_convert_mc_registers(&si_pi->mc_reg_table.mc_reg_table_entry[0],6179&smc_mc_reg_table->data[SISLANDS_MCREGISTERTABLE_ACPI_SLOT],6180si_pi->mc_reg_table.last,6181si_pi->mc_reg_table.valid_flag);61826183if (ulv->supported && ulv->pl.vddc != 0)6184si_convert_mc_reg_table_entry_to_smc(adev, &ulv->pl,6185&smc_mc_reg_table->data[SISLANDS_MCREGISTERTABLE_ULV_SLOT]);6186else6187si_convert_mc_registers(&si_pi->mc_reg_table.mc_reg_table_entry[0],6188&smc_mc_reg_table->data[SISLANDS_MCREGISTERTABLE_ULV_SLOT],6189si_pi->mc_reg_table.last,6190si_pi->mc_reg_table.valid_flag);61916192si_convert_mc_reg_table_to_smc(adev, amdgpu_boot_state, smc_mc_reg_table);61936194return amdgpu_si_copy_bytes_to_smc(adev, si_pi->mc_reg_table_start,6195(u8 *)smc_mc_reg_table,6196sizeof(SMC_SIslands_MCRegisters), si_pi->sram_end);6197}61986199static int si_upload_mc_reg_table(struct amdgpu_device *adev,6200struct amdgpu_ps *amdgpu_new_state)6201{6202struct si_ps *new_state = si_get_ps(amdgpu_new_state);6203struct si_power_info *si_pi = si_get_pi(adev);6204u32 address = si_pi->mc_reg_table_start +6205offsetof(SMC_SIslands_MCRegisters,6206data[SISLANDS_MCREGISTERTABLE_FIRST_DRIVERSTATE_SLOT]);6207SMC_SIslands_MCRegisters *smc_mc_reg_table = &si_pi->smc_mc_reg_table;62086209memset(smc_mc_reg_table, 0, sizeof(SMC_SIslands_MCRegisters));62106211si_convert_mc_reg_table_to_smc(adev, amdgpu_new_state, smc_mc_reg_table);62126213return amdgpu_si_copy_bytes_to_smc(adev, address,6214(u8 *)&smc_mc_reg_table->data[SISLANDS_MCREGISTERTABLE_FIRST_DRIVERSTATE_SLOT],6215sizeof(SMC_SIslands_MCRegisterSet) * new_state->performance_level_count,6216si_pi->sram_end);6217}62186219static void si_enable_voltage_control(struct amdgpu_device *adev, bool enable)6220{6221if (enable)6222WREG32_P(mmGENERAL_PWRMGT, GENERAL_PWRMGT__VOLT_PWRMGT_EN_MASK, ~GENERAL_PWRMGT__VOLT_PWRMGT_EN_MASK);6223else6224WREG32_P(mmGENERAL_PWRMGT, 0, ~GENERAL_PWRMGT__VOLT_PWRMGT_EN_MASK);6225}62266227static enum si_pcie_gen si_get_maximum_link_speed(struct amdgpu_device *adev,6228struct amdgpu_ps *amdgpu_state)6229{6230struct si_ps *state = si_get_ps(amdgpu_state);6231int i;6232u16 pcie_speed, max_speed = 0;62336234for (i = 0; i < state->performance_level_count; i++) {6235pcie_speed = state->performance_levels[i].pcie_gen;6236if (max_speed < pcie_speed)6237max_speed = pcie_speed;6238}6239return max_speed;6240}62416242static u16 si_get_current_pcie_speed(struct amdgpu_device *adev)6243{6244u32 speed_cntl;62456246speed_cntl = RREG32_PCIE_PORT(ixPCIE_LC_SPEED_CNTL) & PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK;6247speed_cntl >>= PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE__SHIFT;62486249return (u16)speed_cntl;6250}62516252static void si_request_link_speed_change_before_state_change(struct amdgpu_device *adev,6253struct amdgpu_ps *amdgpu_new_state,6254struct amdgpu_ps *amdgpu_current_state)6255{6256struct si_power_info *si_pi = si_get_pi(adev);6257enum si_pcie_gen target_link_speed = si_get_maximum_link_speed(adev, amdgpu_new_state);6258enum si_pcie_gen current_link_speed;62596260if (si_pi->force_pcie_gen == SI_PCIE_GEN_INVALID)6261current_link_speed = si_get_maximum_link_speed(adev, amdgpu_current_state);6262else6263current_link_speed = si_pi->force_pcie_gen;62646265si_pi->force_pcie_gen = SI_PCIE_GEN_INVALID;6266si_pi->pspp_notify_required = false;6267if (target_link_speed > current_link_speed) {6268switch (target_link_speed) {6269#if defined(CONFIG_ACPI)6270case SI_PCIE_GEN3:6271if (amdgpu_acpi_pcie_performance_request(adev, PCIE_PERF_REQ_PECI_GEN3, false) == 0)6272break;6273si_pi->force_pcie_gen = SI_PCIE_GEN2;6274if (current_link_speed == SI_PCIE_GEN2)6275break;6276fallthrough;6277case SI_PCIE_GEN2:6278if (amdgpu_acpi_pcie_performance_request(adev, PCIE_PERF_REQ_PECI_GEN2, false) == 0)6279break;6280fallthrough;6281#endif6282default:6283si_pi->force_pcie_gen = si_get_current_pcie_speed(adev);6284break;6285}6286} else {6287if (target_link_speed < current_link_speed)6288si_pi->pspp_notify_required = true;6289}6290}62916292static void si_notify_link_speed_change_after_state_change(struct amdgpu_device *adev,6293struct amdgpu_ps *amdgpu_new_state,6294struct amdgpu_ps *amdgpu_current_state)6295{6296struct si_power_info *si_pi = si_get_pi(adev);6297enum si_pcie_gen target_link_speed = si_get_maximum_link_speed(adev, amdgpu_new_state);6298u8 request;62996300if (si_pi->pspp_notify_required) {6301if (target_link_speed == SI_PCIE_GEN3)6302request = PCIE_PERF_REQ_PECI_GEN3;6303else if (target_link_speed == SI_PCIE_GEN2)6304request = PCIE_PERF_REQ_PECI_GEN2;6305else6306request = PCIE_PERF_REQ_PECI_GEN1;63076308if ((request == PCIE_PERF_REQ_PECI_GEN1) &&6309(si_get_current_pcie_speed(adev) > 0))6310return;63116312#if defined(CONFIG_ACPI)6313amdgpu_acpi_pcie_performance_request(adev, request, false);6314#endif6315}6316}63176318#if 06319static int si_ds_request(struct amdgpu_device *adev,6320bool ds_status_on, u32 count_write)6321{6322struct evergreen_power_info *eg_pi = evergreen_get_pi(adev);63236324if (eg_pi->sclk_deep_sleep) {6325if (ds_status_on)6326return (amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_CancelThrottleOVRDSCLKDS) ==6327PPSMC_Result_OK) ?63280 : -EINVAL;6329else6330return (amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_ThrottleOVRDSCLKDS) ==6331PPSMC_Result_OK) ? 0 : -EINVAL;6332}6333return 0;6334}6335#endif63366337static void si_set_max_cu_value(struct amdgpu_device *adev)6338{6339struct si_power_info *si_pi = si_get_pi(adev);63406341if (adev->asic_type == CHIP_VERDE) {6342switch (adev->pdev->device) {6343case 0x6820:6344case 0x6825:6345case 0x6821:6346case 0x6823:6347case 0x6827:6348si_pi->max_cu = 10;6349break;6350case 0x682D:6351case 0x6824:6352case 0x682F:6353case 0x6826:6354si_pi->max_cu = 8;6355break;6356case 0x6828:6357case 0x6830:6358case 0x6831:6359case 0x6838:6360case 0x6839:6361case 0x683D:6362si_pi->max_cu = 10;6363break;6364case 0x683B:6365case 0x683F:6366case 0x6829:6367si_pi->max_cu = 8;6368break;6369default:6370si_pi->max_cu = 0;6371break;6372}6373} else {6374si_pi->max_cu = 0;6375}6376}63776378static int si_patch_single_dependency_table_based_on_leakage(struct amdgpu_device *adev,6379struct amdgpu_clock_voltage_dependency_table *table)6380{6381u32 i;6382int j;6383u16 leakage_voltage;63846385if (table) {6386for (i = 0; i < table->count; i++) {6387switch (si_get_leakage_voltage_from_leakage_index(adev,6388table->entries[i].v,6389&leakage_voltage)) {6390case 0:6391table->entries[i].v = leakage_voltage;6392break;6393case -EAGAIN:6394return -EINVAL;6395case -EINVAL:6396default:6397break;6398}6399}64006401for (j = (table->count - 2); j >= 0; j--) {6402table->entries[j].v = (table->entries[j].v <= table->entries[j + 1].v) ?6403table->entries[j].v : table->entries[j + 1].v;6404}6405}6406return 0;6407}64086409static int si_patch_dependency_tables_based_on_leakage(struct amdgpu_device *adev)6410{6411int ret = 0;64126413ret = si_patch_single_dependency_table_based_on_leakage(adev,6414&adev->pm.dpm.dyn_state.vddc_dependency_on_sclk);6415if (ret)6416DRM_ERROR("Could not patch vddc_on_sclk leakage table\n");6417ret = si_patch_single_dependency_table_based_on_leakage(adev,6418&adev->pm.dpm.dyn_state.vddc_dependency_on_mclk);6419if (ret)6420DRM_ERROR("Could not patch vddc_on_mclk leakage table\n");6421ret = si_patch_single_dependency_table_based_on_leakage(adev,6422&adev->pm.dpm.dyn_state.vddci_dependency_on_mclk);6423if (ret)6424DRM_ERROR("Could not patch vddci_on_mclk leakage table\n");6425return ret;6426}64276428static void si_set_pcie_lane_width_in_smc(struct amdgpu_device *adev,6429struct amdgpu_ps *amdgpu_new_state,6430struct amdgpu_ps *amdgpu_current_state)6431{6432u32 lane_width;6433u32 new_lane_width =6434((amdgpu_new_state->caps & ATOM_PPLIB_PCIE_LINK_WIDTH_MASK) >> ATOM_PPLIB_PCIE_LINK_WIDTH_SHIFT) + 1;6435u32 current_lane_width =6436((amdgpu_current_state->caps & ATOM_PPLIB_PCIE_LINK_WIDTH_MASK) >> ATOM_PPLIB_PCIE_LINK_WIDTH_SHIFT) + 1;64376438if (new_lane_width != current_lane_width) {6439amdgpu_set_pcie_lanes(adev, new_lane_width);6440lane_width = amdgpu_get_pcie_lanes(adev);6441si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_non_ulv_pcie_link_width, lane_width);6442}6443}64446445static void si_dpm_setup_asic(struct amdgpu_device *adev)6446{6447si_read_clock_registers(adev);6448si_enable_acpi_power_management(adev);6449}64506451static int si_thermal_enable_alert(struct amdgpu_device *adev,6452bool enable)6453{6454u32 thermal_int = RREG32(mmCG_THERMAL_INT);64556456if (enable) {6457PPSMC_Result result;64586459thermal_int &= ~(CG_THERMAL_INT__THERM_INT_MASK_HIGH_MASK | CG_THERMAL_INT__THERM_INT_MASK_LOW_MASK);6460WREG32(mmCG_THERMAL_INT, thermal_int);6461result = amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_EnableThermalInterrupt);6462if (result != PPSMC_Result_OK) {6463DRM_DEBUG_KMS("Could not enable thermal interrupts.\n");6464return -EINVAL;6465}6466} else {6467thermal_int |= CG_THERMAL_INT__THERM_INT_MASK_HIGH_MASK | CG_THERMAL_INT__THERM_INT_MASK_LOW_MASK;6468WREG32(mmCG_THERMAL_INT, thermal_int);6469}64706471return 0;6472}64736474static int si_thermal_set_temperature_range(struct amdgpu_device *adev,6475int min_temp, int max_temp)6476{6477int low_temp = 0 * 1000;6478int high_temp = 255 * 1000;64796480if (low_temp < min_temp)6481low_temp = min_temp;6482if (high_temp > max_temp)6483high_temp = max_temp;6484if (high_temp < low_temp) {6485DRM_ERROR("invalid thermal range: %d - %d\n", low_temp, high_temp);6486return -EINVAL;6487}64886489WREG32_P(mmCG_THERMAL_INT, (high_temp / 1000) << CG_THERMAL_INT__DIG_THERM_INTH__SHIFT, ~CG_THERMAL_INT__DIG_THERM_INTH_MASK);6490WREG32_P(mmCG_THERMAL_INT, (low_temp / 1000) << CG_THERMAL_INT__DIG_THERM_INTL__SHIFT, ~CG_THERMAL_INT__DIG_THERM_INTL_MASK);6491WREG32_P(mmCG_THERMAL_CTRL, (high_temp / 1000) << CG_THERMAL_CTRL__DIG_THERM_DPM__SHIFT, ~CG_THERMAL_CTRL__DIG_THERM_DPM_MASK);64926493adev->pm.dpm.thermal.min_temp = low_temp;6494adev->pm.dpm.thermal.max_temp = high_temp;64956496return 0;6497}64986499static void si_fan_ctrl_set_static_mode(struct amdgpu_device *adev, u32 mode)6500{6501struct si_power_info *si_pi = si_get_pi(adev);6502u32 tmp;65036504if (si_pi->fan_ctrl_is_in_default_mode) {6505tmp = (RREG32(mmCG_FDO_CTRL2) & CG_FDO_CTRL2__FDO_PWM_MODE_MASK) >> CG_FDO_CTRL2__FDO_PWM_MODE__SHIFT;6506si_pi->fan_ctrl_default_mode = tmp;6507tmp = (RREG32(mmCG_FDO_CTRL2) & CG_FDO_CTRL2__TMIN_MASK) >> CG_FDO_CTRL2__TMIN__SHIFT;6508si_pi->t_min = tmp;6509si_pi->fan_ctrl_is_in_default_mode = false;6510}65116512tmp = RREG32(mmCG_FDO_CTRL2) & ~CG_FDO_CTRL2__TMIN_MASK;6513tmp |= 0 << CG_FDO_CTRL2__TMIN__SHIFT;6514WREG32(mmCG_FDO_CTRL2, tmp);65156516tmp = RREG32(mmCG_FDO_CTRL2) & ~CG_FDO_CTRL2__FDO_PWM_MODE_MASK;6517tmp |= mode << CG_FDO_CTRL2__FDO_PWM_MODE__SHIFT;6518WREG32(mmCG_FDO_CTRL2, tmp);6519}65206521static int si_thermal_setup_fan_table(struct amdgpu_device *adev)6522{6523struct si_power_info *si_pi = si_get_pi(adev);6524PP_SIslands_FanTable fan_table = { FDO_MODE_HARDWARE };6525u32 duty100;6526u32 t_diff1, t_diff2, pwm_diff1, pwm_diff2;6527u16 fdo_min, slope1, slope2;6528u32 reference_clock, tmp;6529int ret;6530u64 tmp64;65316532if (!si_pi->fan_table_start) {6533adev->pm.dpm.fan.ucode_fan_control = false;6534return 0;6535}65366537duty100 = (RREG32(mmCG_FDO_CTRL1) & CG_FDO_CTRL1__FMAX_DUTY100_MASK) >> CG_FDO_CTRL1__FMAX_DUTY100__SHIFT;65386539if (duty100 == 0) {6540adev->pm.dpm.fan.ucode_fan_control = false;6541return 0;6542}65436544tmp64 = (u64)adev->pm.dpm.fan.pwm_min * duty100;6545do_div(tmp64, 10000);6546fdo_min = (u16)tmp64;65476548t_diff1 = adev->pm.dpm.fan.t_med - adev->pm.dpm.fan.t_min;6549t_diff2 = adev->pm.dpm.fan.t_high - adev->pm.dpm.fan.t_med;65506551pwm_diff1 = adev->pm.dpm.fan.pwm_med - adev->pm.dpm.fan.pwm_min;6552pwm_diff2 = adev->pm.dpm.fan.pwm_high - adev->pm.dpm.fan.pwm_med;65536554slope1 = (u16)((50 + ((16 * duty100 * pwm_diff1) / t_diff1)) / 100);6555slope2 = (u16)((50 + ((16 * duty100 * pwm_diff2) / t_diff2)) / 100);65566557fan_table.temp_min = cpu_to_be16((50 + adev->pm.dpm.fan.t_min) / 100);6558fan_table.temp_med = cpu_to_be16((50 + adev->pm.dpm.fan.t_med) / 100);6559fan_table.temp_max = cpu_to_be16((50 + adev->pm.dpm.fan.t_max) / 100);6560fan_table.slope1 = cpu_to_be16(slope1);6561fan_table.slope2 = cpu_to_be16(slope2);6562fan_table.fdo_min = cpu_to_be16(fdo_min);6563fan_table.hys_down = cpu_to_be16(adev->pm.dpm.fan.t_hyst);6564fan_table.hys_up = cpu_to_be16(1);6565fan_table.hys_slope = cpu_to_be16(1);6566fan_table.temp_resp_lim = cpu_to_be16(5);6567reference_clock = amdgpu_asic_get_xclk(adev);65686569fan_table.refresh_period = cpu_to_be32((adev->pm.dpm.fan.cycle_delay *6570reference_clock) / 1600);6571fan_table.fdo_max = cpu_to_be16((u16)duty100);65726573tmp = (RREG32(mmCG_MULT_THERMAL_CTRL) & CG_MULT_THERMAL_CTRL__TEMP_SEL_MASK) >> CG_MULT_THERMAL_CTRL__TEMP_SEL__SHIFT;6574fan_table.temp_src = (uint8_t)tmp;65756576ret = amdgpu_si_copy_bytes_to_smc(adev,6577si_pi->fan_table_start,6578(u8 *)(&fan_table),6579sizeof(fan_table),6580si_pi->sram_end);65816582if (ret) {6583DRM_ERROR("Failed to load fan table to the SMC.");6584adev->pm.dpm.fan.ucode_fan_control = false;6585}65866587return ret;6588}65896590static int si_fan_ctrl_start_smc_fan_control(struct amdgpu_device *adev)6591{6592struct si_power_info *si_pi = si_get_pi(adev);6593PPSMC_Result ret;65946595ret = amdgpu_si_send_msg_to_smc(adev, PPSMC_StartFanControl);6596if (ret == PPSMC_Result_OK) {6597si_pi->fan_is_controlled_by_smc = true;6598return 0;6599} else {6600return -EINVAL;6601}6602}66036604static int si_fan_ctrl_stop_smc_fan_control(struct amdgpu_device *adev)6605{6606struct si_power_info *si_pi = si_get_pi(adev);6607PPSMC_Result ret;66086609ret = amdgpu_si_send_msg_to_smc(adev, PPSMC_StopFanControl);66106611if (ret == PPSMC_Result_OK) {6612si_pi->fan_is_controlled_by_smc = false;6613return 0;6614} else {6615return -EINVAL;6616}6617}66186619static int si_dpm_get_fan_speed_pwm(void *handle,6620u32 *speed)6621{6622u32 duty, duty100;6623u64 tmp64;6624struct amdgpu_device *adev = (struct amdgpu_device *)handle;66256626if (!speed)6627return -EINVAL;66286629if (adev->pm.no_fan)6630return -ENOENT;66316632duty100 = (RREG32(mmCG_FDO_CTRL1) & CG_FDO_CTRL1__FMAX_DUTY100_MASK) >> CG_FDO_CTRL1__FMAX_DUTY100__SHIFT;6633duty = (RREG32(mmCG_THERMAL_STATUS) & CG_THERMAL_STATUS__FDO_PWM_DUTY_MASK) >> CG_THERMAL_STATUS__FDO_PWM_DUTY__SHIFT;66346635if (duty100 == 0)6636return -EINVAL;66376638tmp64 = (u64)duty * 255;6639do_div(tmp64, duty100);6640*speed = min_t(u32, tmp64, 255);66416642return 0;6643}66446645static int si_dpm_set_fan_speed_pwm(void *handle,6646u32 speed)6647{6648struct amdgpu_device *adev = (struct amdgpu_device *)handle;6649struct si_power_info *si_pi = si_get_pi(adev);6650u32 tmp;6651u32 duty, duty100;6652u64 tmp64;66536654if (adev->pm.no_fan)6655return -ENOENT;66566657if (si_pi->fan_is_controlled_by_smc)6658return -EINVAL;66596660if (speed > 255)6661return -EINVAL;66626663duty100 = (RREG32(mmCG_FDO_CTRL1) & CG_FDO_CTRL1__FMAX_DUTY100_MASK) >> CG_FDO_CTRL1__FMAX_DUTY100__SHIFT;66646665if (duty100 == 0)6666return -EINVAL;66676668tmp64 = (u64)speed * duty100;6669do_div(tmp64, 255);6670duty = (u32)tmp64;66716672tmp = RREG32(mmCG_FDO_CTRL0) & ~CG_FDO_CTRL0__FDO_STATIC_DUTY_MASK;6673tmp |= duty << CG_FDO_CTRL0__FDO_STATIC_DUTY__SHIFT;6674WREG32(mmCG_FDO_CTRL0, tmp);66756676return 0;6677}66786679static int si_dpm_set_fan_control_mode(void *handle, u32 mode)6680{6681struct amdgpu_device *adev = (struct amdgpu_device *)handle;66826683if (mode == U32_MAX)6684return -EINVAL;66856686if (mode) {6687/* stop auto-manage */6688if (adev->pm.dpm.fan.ucode_fan_control)6689si_fan_ctrl_stop_smc_fan_control(adev);6690si_fan_ctrl_set_static_mode(adev, mode);6691} else {6692/* restart auto-manage */6693if (adev->pm.dpm.fan.ucode_fan_control)6694si_thermal_start_smc_fan_control(adev);6695else6696si_fan_ctrl_set_default_mode(adev);6697}66986699return 0;6700}67016702static int si_dpm_get_fan_control_mode(void *handle, u32 *fan_mode)6703{6704struct amdgpu_device *adev = (struct amdgpu_device *)handle;6705struct si_power_info *si_pi = si_get_pi(adev);6706u32 tmp;67076708if (!fan_mode)6709return -EINVAL;67106711if (si_pi->fan_is_controlled_by_smc)6712return 0;67136714tmp = RREG32(mmCG_FDO_CTRL2) & CG_FDO_CTRL2__FDO_PWM_MODE_MASK;6715*fan_mode = (tmp >> CG_FDO_CTRL2__FDO_PWM_MODE__SHIFT);67166717return 0;6718}67196720#if 06721static int si_fan_ctrl_get_fan_speed_rpm(struct amdgpu_device *adev,6722u32 *speed)6723{6724u32 tach_period;6725u32 xclk = amdgpu_asic_get_xclk(adev);67266727if (adev->pm.no_fan)6728return -ENOENT;67296730if (adev->pm.fan_pulses_per_revolution == 0)6731return -ENOENT;67326733tach_period = (RREG32(mmCG_TACH_STATUS) & CG_TACH_STATUS__TACH_PERIOD_MASK) >> CG_TACH_STATUS__TACH_PERIOD__SHIFT;6734if (tach_period == 0)6735return -ENOENT;67366737*speed = 60 * xclk * 10000 / tach_period;67386739return 0;6740}67416742static int si_fan_ctrl_set_fan_speed_rpm(struct amdgpu_device *adev,6743u32 speed)6744{6745u32 tach_period, tmp;6746u32 xclk = amdgpu_asic_get_xclk(adev);67476748if (adev->pm.no_fan)6749return -ENOENT;67506751if (adev->pm.fan_pulses_per_revolution == 0)6752return -ENOENT;67536754if ((speed < adev->pm.fan_min_rpm) ||6755(speed > adev->pm.fan_max_rpm))6756return -EINVAL;67576758if (adev->pm.dpm.fan.ucode_fan_control)6759si_fan_ctrl_stop_smc_fan_control(adev);67606761tach_period = 60 * xclk * 10000 / (8 * speed);6762tmp = RREG32(mmCG_TACH_CTRL) & ~CG_TACH_CTRL__TARGET_PERIOD_MASK;6763tmp |= tach_period << CG_TACH_CTRL__TARGET_PERIOD__SHIFT;6764WREG32(mmCG_TACH_CTRL, tmp);67656766si_fan_ctrl_set_static_mode(adev, FDO_PWM_MODE_STATIC_RPM);67676768return 0;6769}6770#endif67716772static void si_fan_ctrl_set_default_mode(struct amdgpu_device *adev)6773{6774struct si_power_info *si_pi = si_get_pi(adev);6775u32 tmp;67766777if (!si_pi->fan_ctrl_is_in_default_mode) {6778tmp = RREG32(mmCG_FDO_CTRL2) & ~CG_FDO_CTRL2__FDO_PWM_MODE_MASK;6779tmp |= si_pi->fan_ctrl_default_mode << CG_FDO_CTRL2__FDO_PWM_MODE__SHIFT;6780WREG32(mmCG_FDO_CTRL2, tmp);67816782tmp = RREG32(mmCG_FDO_CTRL2) & ~CG_FDO_CTRL2__TMIN_MASK;6783tmp |= si_pi->t_min << CG_FDO_CTRL2__TMIN__SHIFT;6784WREG32(mmCG_FDO_CTRL2, tmp);6785si_pi->fan_ctrl_is_in_default_mode = true;6786}6787}67886789static void si_thermal_start_smc_fan_control(struct amdgpu_device *adev)6790{6791if (adev->pm.dpm.fan.ucode_fan_control) {6792si_fan_ctrl_start_smc_fan_control(adev);6793si_fan_ctrl_set_static_mode(adev, FDO_PWM_MODE_STATIC);6794}6795}67966797static void si_thermal_initialize(struct amdgpu_device *adev)6798{6799u32 tmp;68006801if (adev->pm.fan_pulses_per_revolution) {6802tmp = RREG32(mmCG_TACH_CTRL) & ~CG_TACH_CTRL__EDGE_PER_REV_MASK;6803tmp |= (adev->pm.fan_pulses_per_revolution -1) << CG_TACH_CTRL__EDGE_PER_REV__SHIFT;6804WREG32(mmCG_TACH_CTRL, tmp);6805}68066807tmp = RREG32(mmCG_FDO_CTRL2) & ~CG_FDO_CTRL2__TACH_PWM_RESP_RATE_MASK;6808tmp |= 0x28 << CG_FDO_CTRL2__TACH_PWM_RESP_RATE__SHIFT;6809WREG32(mmCG_FDO_CTRL2, tmp);6810}68116812static int si_thermal_start_thermal_controller(struct amdgpu_device *adev)6813{6814int ret;68156816si_thermal_initialize(adev);6817ret = si_thermal_set_temperature_range(adev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX);6818if (ret)6819return ret;6820ret = si_thermal_enable_alert(adev, true);6821if (ret)6822return ret;6823if (adev->pm.dpm.fan.ucode_fan_control) {6824ret = si_halt_smc(adev);6825if (ret)6826return ret;6827ret = si_thermal_setup_fan_table(adev);6828if (ret)6829return ret;6830ret = si_resume_smc(adev);6831if (ret)6832return ret;6833si_thermal_start_smc_fan_control(adev);6834}68356836return 0;6837}68386839static void si_thermal_stop_thermal_controller(struct amdgpu_device *adev)6840{6841if (!adev->pm.no_fan) {6842si_fan_ctrl_set_default_mode(adev);6843si_fan_ctrl_stop_smc_fan_control(adev);6844}6845}68466847static int si_dpm_enable(struct amdgpu_device *adev)6848{6849struct rv7xx_power_info *pi = rv770_get_pi(adev);6850struct evergreen_power_info *eg_pi = evergreen_get_pi(adev);6851struct si_power_info *si_pi = si_get_pi(adev);6852struct amdgpu_ps *boot_ps = adev->pm.dpm.boot_ps;6853int ret;68546855if (amdgpu_si_is_smc_running(adev))6856return -EINVAL;6857if (pi->voltage_control || si_pi->voltage_control_svi2)6858si_enable_voltage_control(adev, true);6859if (pi->mvdd_control)6860si_get_mvdd_configuration(adev);6861if (pi->voltage_control || si_pi->voltage_control_svi2) {6862ret = si_construct_voltage_tables(adev);6863if (ret) {6864DRM_ERROR("si_construct_voltage_tables failed\n");6865return ret;6866}6867}6868if (eg_pi->dynamic_ac_timing) {6869ret = si_initialize_mc_reg_table(adev);6870if (ret)6871eg_pi->dynamic_ac_timing = false;6872}6873if (pi->dynamic_ss)6874si_enable_spread_spectrum(adev, true);6875if (pi->thermal_protection)6876si_enable_thermal_protection(adev, true);6877si_setup_bsp(adev);6878si_program_git(adev);6879si_program_tp(adev);6880si_program_tpp(adev);6881si_program_sstp(adev);6882si_enable_display_gap(adev);6883si_program_vc(adev);6884ret = si_upload_firmware(adev);6885if (ret) {6886DRM_ERROR("si_upload_firmware failed\n");6887return ret;6888}6889ret = si_process_firmware_header(adev);6890if (ret) {6891DRM_ERROR("si_process_firmware_header failed\n");6892return ret;6893}6894ret = si_initial_switch_from_arb_f0_to_f1(adev);6895if (ret) {6896DRM_ERROR("si_initial_switch_from_arb_f0_to_f1 failed\n");6897return ret;6898}6899ret = si_init_smc_table(adev);6900if (ret) {6901DRM_ERROR("si_init_smc_table failed\n");6902return ret;6903}6904ret = si_init_smc_spll_table(adev);6905if (ret) {6906DRM_ERROR("si_init_smc_spll_table failed\n");6907return ret;6908}6909ret = si_init_arb_table_index(adev);6910if (ret) {6911DRM_ERROR("si_init_arb_table_index failed\n");6912return ret;6913}6914if (eg_pi->dynamic_ac_timing) {6915ret = si_populate_mc_reg_table(adev, boot_ps);6916if (ret) {6917DRM_ERROR("si_populate_mc_reg_table failed\n");6918return ret;6919}6920}6921ret = si_initialize_smc_cac_tables(adev);6922if (ret) {6923DRM_ERROR("si_initialize_smc_cac_tables failed\n");6924return ret;6925}6926ret = si_initialize_hardware_cac_manager(adev);6927if (ret) {6928DRM_ERROR("si_initialize_hardware_cac_manager failed\n");6929return ret;6930}6931ret = si_initialize_smc_dte_tables(adev);6932if (ret) {6933DRM_ERROR("si_initialize_smc_dte_tables failed\n");6934return ret;6935}6936ret = si_populate_smc_tdp_limits(adev, boot_ps);6937if (ret) {6938DRM_ERROR("si_populate_smc_tdp_limits failed\n");6939return ret;6940}6941ret = si_populate_smc_tdp_limits_2(adev, boot_ps);6942if (ret) {6943DRM_ERROR("si_populate_smc_tdp_limits_2 failed\n");6944return ret;6945}6946si_program_response_times(adev);6947si_program_ds_registers(adev);6948si_dpm_start_smc(adev);6949ret = si_notify_smc_display_change(adev, false);6950if (ret) {6951DRM_ERROR("si_notify_smc_display_change failed\n");6952return ret;6953}6954si_enable_sclk_control(adev, true);6955si_start_dpm(adev);69566957si_enable_auto_throttle_source(adev, SI_DPM_AUTO_THROTTLE_SRC_THERMAL, true);6958si_thermal_start_thermal_controller(adev);69596960ni_update_current_ps(adev, boot_ps);69616962return 0;6963}69646965static int si_set_temperature_range(struct amdgpu_device *adev)6966{6967int ret;69686969ret = si_thermal_enable_alert(adev, false);6970if (ret)6971return ret;6972ret = si_thermal_set_temperature_range(adev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX);6973if (ret)6974return ret;6975ret = si_thermal_enable_alert(adev, true);6976if (ret)6977return ret;69786979return ret;6980}69816982static void si_dpm_disable(struct amdgpu_device *adev)6983{6984struct rv7xx_power_info *pi = rv770_get_pi(adev);6985struct amdgpu_ps *boot_ps = adev->pm.dpm.boot_ps;69866987if (!amdgpu_si_is_smc_running(adev))6988return;6989si_thermal_stop_thermal_controller(adev);6990si_disable_ulv(adev);6991si_clear_vc(adev);6992if (pi->thermal_protection)6993si_enable_thermal_protection(adev, false);6994si_enable_power_containment(adev, boot_ps, false);6995si_enable_smc_cac(adev, boot_ps, false);6996si_enable_spread_spectrum(adev, false);6997si_enable_auto_throttle_source(adev, SI_DPM_AUTO_THROTTLE_SRC_THERMAL, false);6998si_stop_dpm(adev);6999si_reset_to_default(adev);7000si_dpm_stop_smc(adev);7001si_force_switch_to_arb_f0(adev);70027003ni_update_current_ps(adev, boot_ps);7004}70057006static int si_dpm_pre_set_power_state(void *handle)7007{7008struct amdgpu_device *adev = (struct amdgpu_device *)handle;7009struct evergreen_power_info *eg_pi = evergreen_get_pi(adev);7010struct amdgpu_ps requested_ps = *adev->pm.dpm.requested_ps;7011struct amdgpu_ps *new_ps = &requested_ps;70127013ni_update_requested_ps(adev, new_ps);7014si_apply_state_adjust_rules(adev, &eg_pi->requested_rps);70157016return 0;7017}70187019static int si_power_control_set_level(struct amdgpu_device *adev)7020{7021struct amdgpu_ps *new_ps = adev->pm.dpm.requested_ps;7022int ret;70237024ret = si_restrict_performance_levels_before_switch(adev);7025if (ret)7026return ret;7027ret = si_halt_smc(adev);7028if (ret)7029return ret;7030ret = si_populate_smc_tdp_limits(adev, new_ps);7031if (ret)7032return ret;7033ret = si_populate_smc_tdp_limits_2(adev, new_ps);7034if (ret)7035return ret;7036ret = si_resume_smc(adev);7037if (ret)7038return ret;7039return si_set_sw_state(adev);7040}70417042static void si_set_vce_clock(struct amdgpu_device *adev,7043struct amdgpu_ps *new_rps,7044struct amdgpu_ps *old_rps)7045{7046if ((old_rps->evclk != new_rps->evclk) ||7047(old_rps->ecclk != new_rps->ecclk)) {7048/* Turn the clocks on when encoding, off otherwise */7049dev_dbg(adev->dev, "set VCE clocks: %u, %u\n", new_rps->evclk, new_rps->ecclk);70507051if (new_rps->evclk || new_rps->ecclk) {7052amdgpu_asic_set_vce_clocks(adev, new_rps->evclk, new_rps->ecclk);7053amdgpu_device_ip_set_clockgating_state(7054adev, AMD_IP_BLOCK_TYPE_VCE, AMD_CG_STATE_UNGATE);7055amdgpu_device_ip_set_powergating_state(7056adev, AMD_IP_BLOCK_TYPE_VCE, AMD_PG_STATE_UNGATE);7057} else {7058amdgpu_device_ip_set_powergating_state(7059adev, AMD_IP_BLOCK_TYPE_VCE, AMD_PG_STATE_GATE);7060amdgpu_device_ip_set_clockgating_state(7061adev, AMD_IP_BLOCK_TYPE_VCE, AMD_CG_STATE_GATE);7062amdgpu_asic_set_vce_clocks(adev, 0, 0);7063}7064}7065}70667067static int si_dpm_set_power_state(void *handle)7068{7069struct amdgpu_device *adev = (struct amdgpu_device *)handle;7070struct evergreen_power_info *eg_pi = evergreen_get_pi(adev);7071struct amdgpu_ps *new_ps = &eg_pi->requested_rps;7072struct amdgpu_ps *old_ps = &eg_pi->current_rps;7073int ret;70747075ret = si_disable_ulv(adev);7076if (ret) {7077DRM_ERROR("si_disable_ulv failed\n");7078return ret;7079}7080ret = si_restrict_performance_levels_before_switch(adev);7081if (ret) {7082DRM_ERROR("si_restrict_performance_levels_before_switch failed\n");7083return ret;7084}7085if (eg_pi->pcie_performance_request)7086si_request_link_speed_change_before_state_change(adev, new_ps, old_ps);7087ni_set_uvd_clock_before_set_eng_clock(adev, new_ps, old_ps);7088ret = si_enable_power_containment(adev, new_ps, false);7089if (ret) {7090DRM_ERROR("si_enable_power_containment failed\n");7091return ret;7092}7093ret = si_enable_smc_cac(adev, new_ps, false);7094if (ret) {7095DRM_ERROR("si_enable_smc_cac failed\n");7096return ret;7097}7098ret = si_halt_smc(adev);7099if (ret) {7100DRM_ERROR("si_halt_smc failed\n");7101return ret;7102}7103ret = si_upload_sw_state(adev, new_ps);7104if (ret) {7105DRM_ERROR("si_upload_sw_state failed\n");7106return ret;7107}7108ret = si_upload_smc_data(adev);7109if (ret) {7110DRM_ERROR("si_upload_smc_data failed\n");7111return ret;7112}7113ret = si_upload_ulv_state(adev);7114if (ret) {7115DRM_ERROR("si_upload_ulv_state failed\n");7116return ret;7117}7118if (eg_pi->dynamic_ac_timing) {7119ret = si_upload_mc_reg_table(adev, new_ps);7120if (ret) {7121DRM_ERROR("si_upload_mc_reg_table failed\n");7122return ret;7123}7124}7125ret = si_program_memory_timing_parameters(adev, new_ps);7126if (ret) {7127DRM_ERROR("si_program_memory_timing_parameters failed\n");7128return ret;7129}7130si_set_pcie_lane_width_in_smc(adev, new_ps, old_ps);71317132ret = si_resume_smc(adev);7133if (ret) {7134DRM_ERROR("si_resume_smc failed\n");7135return ret;7136}7137ret = si_set_sw_state(adev);7138if (ret) {7139DRM_ERROR("si_set_sw_state failed\n");7140return ret;7141}7142ni_set_uvd_clock_after_set_eng_clock(adev, new_ps, old_ps);7143si_set_vce_clock(adev, new_ps, old_ps);7144if (eg_pi->pcie_performance_request)7145si_notify_link_speed_change_after_state_change(adev, new_ps, old_ps);7146ret = si_set_power_state_conditionally_enable_ulv(adev, new_ps);7147if (ret) {7148DRM_ERROR("si_set_power_state_conditionally_enable_ulv failed\n");7149return ret;7150}7151ret = si_enable_smc_cac(adev, new_ps, true);7152if (ret) {7153DRM_ERROR("si_enable_smc_cac failed\n");7154return ret;7155}7156ret = si_enable_power_containment(adev, new_ps, true);7157if (ret) {7158DRM_ERROR("si_enable_power_containment failed\n");7159return ret;7160}71617162ret = si_power_control_set_level(adev);7163if (ret) {7164DRM_ERROR("si_power_control_set_level failed\n");7165return ret;7166}71677168return 0;7169}71707171static void si_dpm_post_set_power_state(void *handle)7172{7173struct amdgpu_device *adev = (struct amdgpu_device *)handle;7174struct evergreen_power_info *eg_pi = evergreen_get_pi(adev);7175struct amdgpu_ps *new_ps = &eg_pi->requested_rps;71767177ni_update_current_ps(adev, new_ps);7178}71797180#if 07181void si_dpm_reset_asic(struct amdgpu_device *adev)7182{7183si_restrict_performance_levels_before_switch(adev);7184si_disable_ulv(adev);7185si_set_boot_state(adev);7186}7187#endif71887189static void si_dpm_display_configuration_changed(void *handle)7190{7191struct amdgpu_device *adev = (struct amdgpu_device *)handle;71927193si_program_display_gap(adev);7194}719571967197static void si_parse_pplib_non_clock_info(struct amdgpu_device *adev,7198struct amdgpu_ps *rps,7199struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info,7200u8 table_rev)7201{7202rps->caps = le32_to_cpu(non_clock_info->ulCapsAndSettings);7203rps->class = le16_to_cpu(non_clock_info->usClassification);7204rps->class2 = le16_to_cpu(non_clock_info->usClassification2);72057206if (ATOM_PPLIB_NONCLOCKINFO_VER1 < table_rev) {7207rps->vclk = le32_to_cpu(non_clock_info->ulVCLK);7208rps->dclk = le32_to_cpu(non_clock_info->ulDCLK);7209} else if (r600_is_uvd_state(rps->class, rps->class2)) {7210rps->vclk = RV770_DEFAULT_VCLK_FREQ;7211rps->dclk = RV770_DEFAULT_DCLK_FREQ;7212} else {7213rps->vclk = 0;7214rps->dclk = 0;7215}72167217if (rps->class & ATOM_PPLIB_CLASSIFICATION_BOOT)7218adev->pm.dpm.boot_ps = rps;7219if (rps->class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE)7220adev->pm.dpm.uvd_ps = rps;7221}72227223static void si_parse_pplib_clock_info(struct amdgpu_device *adev,7224struct amdgpu_ps *rps, int index,7225union pplib_clock_info *clock_info)7226{7227struct rv7xx_power_info *pi = rv770_get_pi(adev);7228struct evergreen_power_info *eg_pi = evergreen_get_pi(adev);7229struct si_power_info *si_pi = si_get_pi(adev);7230struct si_ps *ps = si_get_ps(rps);7231u16 leakage_voltage;7232struct rv7xx_pl *pl = &ps->performance_levels[index];7233int ret;72347235ps->performance_level_count = index + 1;72367237pl->sclk = le16_to_cpu(clock_info->si.usEngineClockLow);7238pl->sclk |= clock_info->si.ucEngineClockHigh << 16;7239pl->mclk = le16_to_cpu(clock_info->si.usMemoryClockLow);7240pl->mclk |= clock_info->si.ucMemoryClockHigh << 16;72417242pl->vddc = le16_to_cpu(clock_info->si.usVDDC);7243pl->vddci = le16_to_cpu(clock_info->si.usVDDCI);7244pl->flags = le32_to_cpu(clock_info->si.ulFlags);7245pl->pcie_gen = si_gen_pcie_gen_support(adev,7246si_pi->sys_pcie_mask,7247si_pi->boot_pcie_gen,7248clock_info->si.ucPCIEGen);72497250/* patch up vddc if necessary */7251ret = si_get_leakage_voltage_from_leakage_index(adev, pl->vddc,7252&leakage_voltage);7253if (ret == 0)7254pl->vddc = leakage_voltage;72557256if (rps->class & ATOM_PPLIB_CLASSIFICATION_ACPI) {7257pi->acpi_vddc = pl->vddc;7258eg_pi->acpi_vddci = pl->vddci;7259si_pi->acpi_pcie_gen = pl->pcie_gen;7260}72617262if ((rps->class2 & ATOM_PPLIB_CLASSIFICATION2_ULV) &&7263index == 0) {7264/* XXX disable for A0 tahiti */7265si_pi->ulv.supported = false;7266si_pi->ulv.pl = *pl;7267si_pi->ulv.one_pcie_lane_in_ulv = false;7268si_pi->ulv.volt_change_delay = SISLANDS_ULVVOLTAGECHANGEDELAY_DFLT;7269si_pi->ulv.cg_ulv_parameter = SISLANDS_CGULVPARAMETER_DFLT;7270si_pi->ulv.cg_ulv_control = SISLANDS_CGULVCONTROL_DFLT;7271}72727273if (pi->min_vddc_in_table > pl->vddc)7274pi->min_vddc_in_table = pl->vddc;72757276if (pi->max_vddc_in_table < pl->vddc)7277pi->max_vddc_in_table = pl->vddc;72787279/* patch up boot state */7280if (rps->class & ATOM_PPLIB_CLASSIFICATION_BOOT) {7281u16 vddc, vddci, mvdd;7282amdgpu_atombios_get_default_voltages(adev, &vddc, &vddci, &mvdd);7283pl->mclk = adev->clock.default_mclk;7284pl->sclk = adev->clock.default_sclk;7285pl->vddc = vddc;7286pl->vddci = vddci;7287si_pi->mvdd_bootup_value = mvdd;7288}72897290if ((rps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) ==7291ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE) {7292adev->pm.dpm.dyn_state.max_clock_voltage_on_ac.sclk = pl->sclk;7293adev->pm.dpm.dyn_state.max_clock_voltage_on_ac.mclk = pl->mclk;7294adev->pm.dpm.dyn_state.max_clock_voltage_on_ac.vddc = pl->vddc;7295adev->pm.dpm.dyn_state.max_clock_voltage_on_ac.vddci = pl->vddci;7296}7297}72987299union pplib_power_state {7300struct _ATOM_PPLIB_STATE v1;7301struct _ATOM_PPLIB_STATE_V2 v2;7302};73037304static int si_parse_power_table(struct amdgpu_device *adev)7305{7306struct amdgpu_mode_info *mode_info = &adev->mode_info;7307struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info;7308union pplib_power_state *power_state;7309int i, j, k, non_clock_array_index, clock_array_index;7310union pplib_clock_info *clock_info;7311struct _StateArray *state_array;7312struct _ClockInfoArray *clock_info_array;7313struct _NonClockInfoArray *non_clock_info_array;7314union power_info *power_info;7315int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);7316u16 data_offset;7317u8 frev, crev;7318u8 *power_state_offset;7319struct si_ps *ps;73207321if (!amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL,7322&frev, &crev, &data_offset))7323return -EINVAL;7324power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);73257326amdgpu_add_thermal_controller(adev);73277328state_array = (struct _StateArray *)7329(mode_info->atom_context->bios + data_offset +7330le16_to_cpu(power_info->pplib.usStateArrayOffset));7331clock_info_array = (struct _ClockInfoArray *)7332(mode_info->atom_context->bios + data_offset +7333le16_to_cpu(power_info->pplib.usClockInfoArrayOffset));7334non_clock_info_array = (struct _NonClockInfoArray *)7335(mode_info->atom_context->bios + data_offset +7336le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset));73377338adev->pm.dpm.ps = kcalloc(state_array->ucNumEntries,7339sizeof(struct amdgpu_ps),7340GFP_KERNEL);7341if (!adev->pm.dpm.ps)7342return -ENOMEM;7343power_state_offset = (u8 *)state_array->states;7344for (adev->pm.dpm.num_ps = 0, i = 0; i < state_array->ucNumEntries; i++) {7345u8 *idx;7346power_state = (union pplib_power_state *)power_state_offset;7347non_clock_array_index = power_state->v2.nonClockInfoIndex;7348non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *)7349&non_clock_info_array->nonClockInfo[non_clock_array_index];7350ps = kzalloc(sizeof(struct si_ps), GFP_KERNEL);7351if (ps == NULL)7352return -ENOMEM;7353adev->pm.dpm.ps[i].ps_priv = ps;7354si_parse_pplib_non_clock_info(adev, &adev->pm.dpm.ps[i],7355non_clock_info,7356non_clock_info_array->ucEntrySize);7357k = 0;7358idx = (u8 *)&power_state->v2.clockInfoIndex[0];7359for (j = 0; j < power_state->v2.ucNumDPMLevels; j++) {7360clock_array_index = idx[j];7361if (clock_array_index >= clock_info_array->ucNumEntries)7362continue;7363if (k >= SISLANDS_MAX_HARDWARE_POWERLEVELS)7364break;7365clock_info = (union pplib_clock_info *)7366((u8 *)&clock_info_array->clockInfo[0] +7367(clock_array_index * clock_info_array->ucEntrySize));7368si_parse_pplib_clock_info(adev,7369&adev->pm.dpm.ps[i], k,7370clock_info);7371k++;7372}7373power_state_offset += 2 + power_state->v2.ucNumDPMLevels;7374adev->pm.dpm.num_ps++;7375}73767377/* fill in the vce power states */7378for (i = 0; i < adev->pm.dpm.num_of_vce_states; i++) {7379u32 sclk, mclk;7380clock_array_index = adev->pm.dpm.vce_states[i].clk_idx;7381clock_info = (union pplib_clock_info *)7382&clock_info_array->clockInfo[clock_array_index * clock_info_array->ucEntrySize];7383sclk = le16_to_cpu(clock_info->si.usEngineClockLow);7384sclk |= clock_info->si.ucEngineClockHigh << 16;7385mclk = le16_to_cpu(clock_info->si.usMemoryClockLow);7386mclk |= clock_info->si.ucMemoryClockHigh << 16;7387adev->pm.dpm.vce_states[i].sclk = sclk;7388adev->pm.dpm.vce_states[i].mclk = mclk;7389}73907391return 0;7392}73937394static int si_dpm_init(struct amdgpu_device *adev)7395{7396struct rv7xx_power_info *pi;7397struct evergreen_power_info *eg_pi;7398struct ni_power_info *ni_pi;7399struct si_power_info *si_pi;7400struct atom_clock_dividers dividers;7401int ret;74027403si_pi = kzalloc(sizeof(struct si_power_info), GFP_KERNEL);7404if (si_pi == NULL)7405return -ENOMEM;7406adev->pm.dpm.priv = si_pi;7407ni_pi = &si_pi->ni;7408eg_pi = &ni_pi->eg;7409pi = &eg_pi->rv7xx;74107411si_pi->sys_pcie_mask =7412adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_MASK;7413si_pi->force_pcie_gen = SI_PCIE_GEN_INVALID;7414si_pi->boot_pcie_gen = si_get_current_pcie_speed(adev);74157416si_set_max_cu_value(adev);74177418rv770_get_max_vddc(adev);7419si_get_leakage_vddc(adev);7420si_patch_dependency_tables_based_on_leakage(adev);74217422pi->acpi_vddc = 0;7423eg_pi->acpi_vddci = 0;7424pi->min_vddc_in_table = 0;7425pi->max_vddc_in_table = 0;74267427ret = amdgpu_get_platform_caps(adev);7428if (ret)7429return ret;74307431ret = amdgpu_parse_extended_power_table(adev);7432if (ret)7433return ret;74347435ret = si_parse_power_table(adev);7436if (ret)7437return ret;74387439adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries =7440kcalloc(4,7441sizeof(struct amdgpu_clock_voltage_dependency_entry),7442GFP_KERNEL);7443if (!adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries)7444return -ENOMEM;74457446adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.count = 4;7447adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[0].clk = 0;7448adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[0].v = 0;7449adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[1].clk = 36000;7450adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[1].v = 720;7451adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[2].clk = 54000;7452adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[2].v = 810;7453adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[3].clk = 72000;7454adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[3].v = 900;74557456if (adev->pm.dpm.voltage_response_time == 0)7457adev->pm.dpm.voltage_response_time = R600_VOLTAGERESPONSETIME_DFLT;7458if (adev->pm.dpm.backbias_response_time == 0)7459adev->pm.dpm.backbias_response_time = R600_BACKBIASRESPONSETIME_DFLT;74607461ret = amdgpu_atombios_get_clock_dividers(adev, COMPUTE_ENGINE_PLL_PARAM,74620, false, ÷rs);7463if (ret)7464pi->ref_div = dividers.ref_div + 1;7465else7466pi->ref_div = R600_REFERENCEDIVIDER_DFLT;74677468eg_pi->smu_uvd_hs = false;74697470pi->mclk_strobe_mode_threshold = 40000;7471if (si_is_special_1gb_platform(adev))7472pi->mclk_stutter_mode_threshold = 0;7473else7474pi->mclk_stutter_mode_threshold = pi->mclk_strobe_mode_threshold;7475pi->mclk_edc_enable_threshold = 40000;7476eg_pi->mclk_edc_wr_enable_threshold = 40000;74777478ni_pi->mclk_rtt_mode_threshold = eg_pi->mclk_edc_wr_enable_threshold;74797480pi->voltage_control =7481amdgpu_atombios_is_voltage_gpio(adev, SET_VOLTAGE_TYPE_ASIC_VDDC,7482VOLTAGE_OBJ_GPIO_LUT);7483if (!pi->voltage_control) {7484si_pi->voltage_control_svi2 =7485amdgpu_atombios_is_voltage_gpio(adev, SET_VOLTAGE_TYPE_ASIC_VDDC,7486VOLTAGE_OBJ_SVID2);7487if (si_pi->voltage_control_svi2)7488amdgpu_atombios_get_svi2_info(adev, SET_VOLTAGE_TYPE_ASIC_VDDC,7489&si_pi->svd_gpio_id, &si_pi->svc_gpio_id);7490}74917492pi->mvdd_control =7493amdgpu_atombios_is_voltage_gpio(adev, SET_VOLTAGE_TYPE_ASIC_MVDDC,7494VOLTAGE_OBJ_GPIO_LUT);74957496eg_pi->vddci_control =7497amdgpu_atombios_is_voltage_gpio(adev, SET_VOLTAGE_TYPE_ASIC_VDDCI,7498VOLTAGE_OBJ_GPIO_LUT);7499if (!eg_pi->vddci_control)7500si_pi->vddci_control_svi2 =7501amdgpu_atombios_is_voltage_gpio(adev, SET_VOLTAGE_TYPE_ASIC_VDDCI,7502VOLTAGE_OBJ_SVID2);75037504si_pi->vddc_phase_shed_control =7505amdgpu_atombios_is_voltage_gpio(adev, SET_VOLTAGE_TYPE_ASIC_VDDC,7506VOLTAGE_OBJ_PHASE_LUT);75077508rv770_get_engine_memory_ss(adev);75097510pi->asi = RV770_ASI_DFLT;7511pi->pasi = CYPRESS_HASI_DFLT;7512pi->vrc = SISLANDS_VRC_DFLT;75137514eg_pi->sclk_deep_sleep = true;7515si_pi->sclk_deep_sleep_above_low = false;75167517if (adev->pm.int_thermal_type != THERMAL_TYPE_NONE)7518pi->thermal_protection = true;7519else7520pi->thermal_protection = false;75217522eg_pi->dynamic_ac_timing = true;75237524#if defined(CONFIG_ACPI)7525eg_pi->pcie_performance_request =7526amdgpu_acpi_is_pcie_performance_request_supported(adev);7527#else7528eg_pi->pcie_performance_request = false;7529#endif75307531si_pi->sram_end = SMC_RAM_END;75327533adev->pm.dpm.dyn_state.mclk_sclk_ratio = 4;7534adev->pm.dpm.dyn_state.sclk_mclk_delta = 15000;7535adev->pm.dpm.dyn_state.vddc_vddci_delta = 200;7536adev->pm.dpm.dyn_state.valid_sclk_values.count = 0;7537adev->pm.dpm.dyn_state.valid_sclk_values.values = NULL;7538adev->pm.dpm.dyn_state.valid_mclk_values.count = 0;7539adev->pm.dpm.dyn_state.valid_mclk_values.values = NULL;75407541si_initialize_powertune_defaults(adev);75427543/* make sure dc limits are valid */7544if ((adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.sclk == 0) ||7545(adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.mclk == 0))7546adev->pm.dpm.dyn_state.max_clock_voltage_on_dc =7547adev->pm.dpm.dyn_state.max_clock_voltage_on_ac;75487549si_pi->fan_ctrl_is_in_default_mode = true;75507551return 0;7552}75537554static void si_dpm_fini(struct amdgpu_device *adev)7555{7556int i;75577558if (adev->pm.dpm.ps)7559for (i = 0; i < adev->pm.dpm.num_ps; i++)7560kfree(adev->pm.dpm.ps[i].ps_priv);7561kfree(adev->pm.dpm.ps);7562kfree(adev->pm.dpm.priv);7563kfree(adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries);7564amdgpu_free_extended_power_table(adev);7565}75667567static void si_dpm_debugfs_print_current_performance_level(void *handle,7568struct seq_file *m)7569{7570struct amdgpu_device *adev = (struct amdgpu_device *)handle;7571struct evergreen_power_info *eg_pi = evergreen_get_pi(adev);7572struct amdgpu_ps *rps = &eg_pi->current_rps;7573struct si_ps *ps = si_get_ps(rps);7574struct rv7xx_pl *pl;7575u32 current_index =7576(RREG32(mmTARGET_AND_CURRENT_PROFILE_INDEX) & TARGET_AND_CURRENT_PROFILE_INDEX__CURRENT_STATE_INDEX_MASK) >>7577TARGET_AND_CURRENT_PROFILE_INDEX__CURRENT_STATE_INDEX__SHIFT;75787579if (current_index >= ps->performance_level_count) {7580seq_printf(m, "invalid dpm profile %d\n", current_index);7581} else {7582pl = &ps->performance_levels[current_index];7583seq_printf(m, "uvd vclk: %d dclk: %d\n", rps->vclk, rps->dclk);7584seq_printf(m, "vce evclk: %d ecclk: %d\n", rps->evclk, rps->ecclk);7585seq_printf(m, "power level %d sclk: %u mclk: %u vddc: %u vddci: %u pcie gen: %u\n",7586current_index, pl->sclk, pl->mclk, pl->vddc, pl->vddci, pl->pcie_gen + 1);7587}7588}75897590static int si_dpm_set_interrupt_state(struct amdgpu_device *adev,7591struct amdgpu_irq_src *source,7592unsigned type,7593enum amdgpu_interrupt_state state)7594{7595u32 cg_thermal_int;75967597switch (type) {7598case AMDGPU_THERMAL_IRQ_LOW_TO_HIGH:7599switch (state) {7600case AMDGPU_IRQ_STATE_DISABLE:7601cg_thermal_int = RREG32_SMC(mmCG_THERMAL_INT);7602cg_thermal_int |= CG_THERMAL_INT__THERM_INT_MASK_HIGH_MASK;7603WREG32(mmCG_THERMAL_INT, cg_thermal_int);7604break;7605case AMDGPU_IRQ_STATE_ENABLE:7606cg_thermal_int = RREG32_SMC(mmCG_THERMAL_INT);7607cg_thermal_int &= ~CG_THERMAL_INT__THERM_INT_MASK_HIGH_MASK;7608WREG32(mmCG_THERMAL_INT, cg_thermal_int);7609break;7610default:7611break;7612}7613break;76147615case AMDGPU_THERMAL_IRQ_HIGH_TO_LOW:7616switch (state) {7617case AMDGPU_IRQ_STATE_DISABLE:7618cg_thermal_int = RREG32_SMC(mmCG_THERMAL_INT);7619cg_thermal_int |= CG_THERMAL_INT__THERM_INT_MASK_LOW_MASK;7620WREG32(mmCG_THERMAL_INT, cg_thermal_int);7621break;7622case AMDGPU_IRQ_STATE_ENABLE:7623cg_thermal_int = RREG32_SMC(mmCG_THERMAL_INT);7624cg_thermal_int &= ~CG_THERMAL_INT__THERM_INT_MASK_LOW_MASK;7625WREG32(mmCG_THERMAL_INT, cg_thermal_int);7626break;7627default:7628break;7629}7630break;76317632default:7633break;7634}7635return 0;7636}76377638static int si_dpm_process_interrupt(struct amdgpu_device *adev,7639struct amdgpu_irq_src *source,7640struct amdgpu_iv_entry *entry)7641{7642bool queue_thermal = false;76437644if (entry == NULL)7645return -EINVAL;76467647switch (entry->src_id) {7648case 230: /* thermal low to high */7649DRM_DEBUG("IH: thermal low to high\n");7650adev->pm.dpm.thermal.high_to_low = false;7651queue_thermal = true;7652break;7653case 231: /* thermal high to low */7654DRM_DEBUG("IH: thermal high to low\n");7655adev->pm.dpm.thermal.high_to_low = true;7656queue_thermal = true;7657break;7658default:7659break;7660}76617662if (queue_thermal)7663schedule_work(&adev->pm.dpm.thermal.work);76647665return 0;7666}76677668static int si_dpm_late_init(struct amdgpu_ip_block *ip_block)7669{7670int ret;7671struct amdgpu_device *adev = ip_block->adev;76727673if (!adev->pm.dpm_enabled)7674return 0;76757676ret = si_set_temperature_range(adev);7677if (ret)7678return ret;7679#if 0 //TODO ?7680si_dpm_powergate_uvd(adev, true);7681#endif7682return 0;7683}76847685/**7686* si_dpm_init_microcode - load ucode images from disk7687*7688* @adev: amdgpu_device pointer7689*7690* Use the firmware interface to load the ucode images into7691* the driver (not loaded into hw).7692* Returns 0 on success, error on failure.7693*/7694static int si_dpm_init_microcode(struct amdgpu_device *adev)7695{7696const char *chip_name;7697int err;76987699DRM_DEBUG("\n");7700switch (adev->asic_type) {7701case CHIP_TAHITI:7702chip_name = "tahiti";7703break;7704case CHIP_PITCAIRN:7705if ((adev->pdev->revision == 0x81) &&7706((adev->pdev->device == 0x6810) ||7707(adev->pdev->device == 0x6811)))7708chip_name = "pitcairn_k";7709else7710chip_name = "pitcairn";7711break;7712case CHIP_VERDE:7713if (((adev->pdev->device == 0x6820) &&7714((adev->pdev->revision == 0x81) ||7715(adev->pdev->revision == 0x83))) ||7716((adev->pdev->device == 0x6821) &&7717((adev->pdev->revision == 0x83) ||7718(adev->pdev->revision == 0x87))) ||7719((adev->pdev->revision == 0x87) &&7720((adev->pdev->device == 0x6823) ||7721(adev->pdev->device == 0x682b))))7722chip_name = "verde_k";7723else7724chip_name = "verde";7725break;7726case CHIP_OLAND:7727if (((adev->pdev->revision == 0x81) &&7728((adev->pdev->device == 0x6600) ||7729(adev->pdev->device == 0x6604) ||7730(adev->pdev->device == 0x6605) ||7731(adev->pdev->device == 0x6610))) ||7732((adev->pdev->revision == 0x83) &&7733(adev->pdev->device == 0x6610)))7734chip_name = "oland_k";7735else7736chip_name = "oland";7737break;7738case CHIP_HAINAN:7739if (((adev->pdev->revision == 0x81) &&7740(adev->pdev->device == 0x6660)) ||7741((adev->pdev->revision == 0x83) &&7742((adev->pdev->device == 0x6660) ||7743(adev->pdev->device == 0x6663) ||7744(adev->pdev->device == 0x6665) ||7745(adev->pdev->device == 0x6667))))7746chip_name = "hainan_k";7747else if ((adev->pdev->revision == 0xc3) &&7748(adev->pdev->device == 0x6665))7749chip_name = "banks_k_2";7750else7751chip_name = "hainan";7752break;7753default: BUG();7754}77557756err = amdgpu_ucode_request(adev, &adev->pm.fw, AMDGPU_UCODE_REQUIRED,7757"amdgpu/%s_smc.bin", chip_name);7758if (err) {7759DRM_ERROR("si_smc: Failed to load firmware. err = %d\"%s_smc.bin\"\n",7760err, chip_name);7761amdgpu_ucode_release(&adev->pm.fw);7762}7763return err;7764}77657766static int si_dpm_sw_init(struct amdgpu_ip_block *ip_block)7767{7768int ret;7769struct amdgpu_device *adev = ip_block->adev;77707771ret = amdgpu_irq_add_id(adev, AMDGPU_IRQ_CLIENTID_LEGACY, 230, &adev->pm.dpm.thermal.irq);7772if (ret)7773return ret;77747775ret = amdgpu_irq_add_id(adev, AMDGPU_IRQ_CLIENTID_LEGACY, 231, &adev->pm.dpm.thermal.irq);7776if (ret)7777return ret;77787779/* default to balanced state */7780adev->pm.dpm.state = POWER_STATE_TYPE_BALANCED;7781adev->pm.dpm.user_state = POWER_STATE_TYPE_BALANCED;7782adev->pm.dpm.forced_level = AMD_DPM_FORCED_LEVEL_AUTO;7783adev->pm.default_sclk = adev->clock.default_sclk;7784adev->pm.default_mclk = adev->clock.default_mclk;7785adev->pm.current_sclk = adev->clock.default_sclk;7786adev->pm.current_mclk = adev->clock.default_mclk;7787adev->pm.int_thermal_type = THERMAL_TYPE_NONE;77887789if (amdgpu_dpm == 0)7790return 0;77917792ret = si_dpm_init_microcode(adev);7793if (ret)7794return ret;77957796INIT_WORK(&adev->pm.dpm.thermal.work, amdgpu_dpm_thermal_work_handler);7797ret = si_dpm_init(adev);7798if (ret)7799goto dpm_failed;7800adev->pm.dpm.current_ps = adev->pm.dpm.requested_ps = adev->pm.dpm.boot_ps;7801if (amdgpu_dpm == 1)7802amdgpu_pm_print_power_states(adev);7803drm_info(adev_to_drm(adev), "si dpm initialized\n");7804return 0;78057806dpm_failed:7807si_dpm_fini(adev);7808drm_err(adev_to_drm(adev), "dpm initialization failed\n");7809return ret;7810}78117812static int si_dpm_sw_fini(struct amdgpu_ip_block *ip_block)7813{7814struct amdgpu_device *adev = ip_block->adev;78157816flush_work(&adev->pm.dpm.thermal.work);78177818si_dpm_fini(adev);78197820return 0;7821}78227823static int si_dpm_hw_init(struct amdgpu_ip_block *ip_block)7824{7825int ret;78267827struct amdgpu_device *adev = ip_block->adev;78287829if (!amdgpu_dpm)7830return 0;78317832mutex_lock(&adev->pm.mutex);7833si_dpm_setup_asic(adev);7834ret = si_dpm_enable(adev);7835if (ret)7836adev->pm.dpm_enabled = false;7837else7838adev->pm.dpm_enabled = true;7839amdgpu_legacy_dpm_compute_clocks(adev);7840mutex_unlock(&adev->pm.mutex);7841return ret;7842}78437844static int si_dpm_hw_fini(struct amdgpu_ip_block *ip_block)7845{7846struct amdgpu_device *adev = ip_block->adev;78477848if (adev->pm.dpm_enabled)7849si_dpm_disable(adev);78507851return 0;7852}78537854static int si_dpm_suspend(struct amdgpu_ip_block *ip_block)7855{7856struct amdgpu_device *adev = ip_block->adev;78577858cancel_work_sync(&adev->pm.dpm.thermal.work);78597860if (adev->pm.dpm_enabled) {7861mutex_lock(&adev->pm.mutex);7862adev->pm.dpm_enabled = false;7863/* disable dpm */7864si_dpm_disable(adev);7865/* reset the power state */7866adev->pm.dpm.current_ps = adev->pm.dpm.requested_ps = adev->pm.dpm.boot_ps;7867mutex_unlock(&adev->pm.mutex);7868}78697870return 0;7871}78727873static int si_dpm_resume(struct amdgpu_ip_block *ip_block)7874{7875int ret = 0;7876struct amdgpu_device *adev = ip_block->adev;78777878if (!amdgpu_dpm)7879return 0;78807881if (!adev->pm.dpm_enabled) {7882/* asic init will reset to the boot state */7883mutex_lock(&adev->pm.mutex);7884si_dpm_setup_asic(adev);7885ret = si_dpm_enable(adev);7886if (ret) {7887adev->pm.dpm_enabled = false;7888} else {7889adev->pm.dpm_enabled = true;7890amdgpu_legacy_dpm_compute_clocks(adev);7891}7892mutex_unlock(&adev->pm.mutex);7893}78947895return ret;7896}78977898static bool si_dpm_is_idle(struct amdgpu_ip_block *ip_block)7899{7900/* XXX */7901return true;7902}79037904static int si_dpm_wait_for_idle(struct amdgpu_ip_block *ip_block)7905{7906/* XXX */7907return 0;7908}79097910static int si_dpm_set_clockgating_state(struct amdgpu_ip_block *ip_block,7911enum amd_clockgating_state state)7912{7913return 0;7914}79157916static int si_dpm_set_powergating_state(struct amdgpu_ip_block *ip_block,7917enum amd_powergating_state state)7918{7919return 0;7920}79217922/* get temperature in millidegrees */7923static int si_dpm_get_temp(void *handle)7924{7925u32 temp;7926int actual_temp = 0;7927struct amdgpu_device *adev = (struct amdgpu_device *)handle;79287929temp = (RREG32(mmCG_MULT_THERMAL_STATUS) & CG_MULT_THERMAL_STATUS__CTF_TEMP_MASK) >>7930CG_MULT_THERMAL_STATUS__CTF_TEMP__SHIFT;79317932if (temp & 0x200)7933actual_temp = 255;7934else7935actual_temp = temp & 0x1ff;79367937actual_temp = (actual_temp * 1000);79387939return actual_temp;7940}79417942static u32 si_dpm_get_sclk(void *handle, bool low)7943{7944struct amdgpu_device *adev = (struct amdgpu_device *)handle;7945struct evergreen_power_info *eg_pi = evergreen_get_pi(adev);7946struct si_ps *requested_state = si_get_ps(&eg_pi->requested_rps);79477948if (low)7949return requested_state->performance_levels[0].sclk;7950else7951return requested_state->performance_levels[requested_state->performance_level_count - 1].sclk;7952}79537954static u32 si_dpm_get_mclk(void *handle, bool low)7955{7956struct amdgpu_device *adev = (struct amdgpu_device *)handle;7957struct evergreen_power_info *eg_pi = evergreen_get_pi(adev);7958struct si_ps *requested_state = si_get_ps(&eg_pi->requested_rps);79597960if (low)7961return requested_state->performance_levels[0].mclk;7962else7963return requested_state->performance_levels[requested_state->performance_level_count - 1].mclk;7964}79657966static void si_dpm_print_power_state(void *handle,7967void *current_ps)7968{7969struct amdgpu_device *adev = (struct amdgpu_device *)handle;7970struct amdgpu_ps *rps = (struct amdgpu_ps *)current_ps;7971struct si_ps *ps = si_get_ps(rps);7972struct rv7xx_pl *pl;7973int i;79747975amdgpu_dpm_dbg_print_class_info(adev, rps->class, rps->class2);7976amdgpu_dpm_dbg_print_cap_info(adev, rps->caps);7977drm_dbg(adev_to_drm(adev), "\tuvd vclk: %d dclk: %d\n", rps->vclk, rps->dclk);7978drm_dbg(adev_to_drm(adev), "\tvce evclk: %d ecclk: %d\n", rps->evclk, rps->ecclk);7979for (i = 0; i < ps->performance_level_count; i++) {7980pl = &ps->performance_levels[i];7981drm_dbg(adev_to_drm(adev), "\t\tpower level %d sclk: %u mclk: %u vddc: %u vddci: %u pcie gen: %u\n",7982i, pl->sclk, pl->mclk, pl->vddc, pl->vddci, pl->pcie_gen + 1);7983}7984amdgpu_dpm_dbg_print_ps_status(adev, rps);7985}79867987static int si_dpm_early_init(struct amdgpu_ip_block *ip_block)7988{79897990struct amdgpu_device *adev = ip_block->adev;79917992adev->powerplay.pp_funcs = &si_dpm_funcs;7993adev->powerplay.pp_handle = adev;7994si_dpm_set_irq_funcs(adev);7995return 0;7996}79977998static inline bool si_are_power_levels_equal(const struct rv7xx_pl *si_cpl1,7999const struct rv7xx_pl *si_cpl2)8000{8001return ((si_cpl1->mclk == si_cpl2->mclk) &&8002(si_cpl1->sclk == si_cpl2->sclk) &&8003(si_cpl1->pcie_gen == si_cpl2->pcie_gen) &&8004(si_cpl1->vddc == si_cpl2->vddc) &&8005(si_cpl1->vddci == si_cpl2->vddci));8006}80078008static int si_check_state_equal(void *handle,8009void *current_ps,8010void *request_ps,8011bool *equal)8012{8013struct si_ps *si_cps;8014struct si_ps *si_rps;8015int i;8016struct amdgpu_ps *cps = (struct amdgpu_ps *)current_ps;8017struct amdgpu_ps *rps = (struct amdgpu_ps *)request_ps;8018struct amdgpu_device *adev = (struct amdgpu_device *)handle;80198020if (adev == NULL || cps == NULL || rps == NULL || equal == NULL)8021return -EINVAL;80228023si_cps = si_get_ps((struct amdgpu_ps *)cps);8024si_rps = si_get_ps((struct amdgpu_ps *)rps);80258026if (si_cps == NULL) {8027printk("si_cps is NULL\n");8028*equal = false;8029return 0;8030}80318032if (si_cps->performance_level_count != si_rps->performance_level_count) {8033*equal = false;8034return 0;8035}80368037for (i = 0; i < si_cps->performance_level_count; i++) {8038if (!si_are_power_levels_equal(&(si_cps->performance_levels[i]),8039&(si_rps->performance_levels[i]))) {8040*equal = false;8041return 0;8042}8043}80448045/* If all performance levels are the same try to use the UVD clocks to break the tie.*/8046*equal = ((cps->vclk == rps->vclk) && (cps->dclk == rps->dclk));8047*equal &= ((cps->evclk == rps->evclk) && (cps->ecclk == rps->ecclk));80488049return 0;8050}80518052static int si_dpm_read_sensor(void *handle, int idx,8053void *value, int *size)8054{8055struct amdgpu_device *adev = (struct amdgpu_device *)handle;8056struct evergreen_power_info *eg_pi = evergreen_get_pi(adev);8057struct amdgpu_ps *rps = &eg_pi->current_rps;8058struct si_ps *ps = si_get_ps(rps);8059uint32_t sclk, mclk;8060u32 pl_index =8061(RREG32(mmTARGET_AND_CURRENT_PROFILE_INDEX) & TARGET_AND_CURRENT_PROFILE_INDEX__CURRENT_STATE_INDEX_MASK) >>8062TARGET_AND_CURRENT_PROFILE_INDEX__CURRENT_STATE_INDEX__SHIFT;80638064/* size must be at least 4 bytes for all sensors */8065if (*size < 4)8066return -EINVAL;80678068switch (idx) {8069case AMDGPU_PP_SENSOR_GFX_SCLK:8070if (pl_index < ps->performance_level_count) {8071sclk = ps->performance_levels[pl_index].sclk;8072*((uint32_t *)value) = sclk;8073*size = 4;8074return 0;8075}8076return -EINVAL;8077case AMDGPU_PP_SENSOR_GFX_MCLK:8078if (pl_index < ps->performance_level_count) {8079mclk = ps->performance_levels[pl_index].mclk;8080*((uint32_t *)value) = mclk;8081*size = 4;8082return 0;8083}8084return -EINVAL;8085case AMDGPU_PP_SENSOR_GPU_TEMP:8086*((uint32_t *)value) = si_dpm_get_temp(adev);8087*size = 4;8088return 0;8089default:8090return -EOPNOTSUPP;8091}8092}80938094static const struct amd_ip_funcs si_dpm_ip_funcs = {8095.name = "si_dpm",8096.early_init = si_dpm_early_init,8097.late_init = si_dpm_late_init,8098.sw_init = si_dpm_sw_init,8099.sw_fini = si_dpm_sw_fini,8100.hw_init = si_dpm_hw_init,8101.hw_fini = si_dpm_hw_fini,8102.suspend = si_dpm_suspend,8103.resume = si_dpm_resume,8104.is_idle = si_dpm_is_idle,8105.wait_for_idle = si_dpm_wait_for_idle,8106.set_clockgating_state = si_dpm_set_clockgating_state,8107.set_powergating_state = si_dpm_set_powergating_state,8108};81098110const struct amdgpu_ip_block_version si_smu_ip_block =8111{8112.type = AMD_IP_BLOCK_TYPE_SMC,8113.major = 6,8114.minor = 0,8115.rev = 0,8116.funcs = &si_dpm_ip_funcs,8117};81188119static const struct amd_pm_funcs si_dpm_funcs = {8120.pre_set_power_state = &si_dpm_pre_set_power_state,8121.set_power_state = &si_dpm_set_power_state,8122.post_set_power_state = &si_dpm_post_set_power_state,8123.display_configuration_changed = &si_dpm_display_configuration_changed,8124.get_sclk = &si_dpm_get_sclk,8125.get_mclk = &si_dpm_get_mclk,8126.print_power_state = &si_dpm_print_power_state,8127.debugfs_print_current_performance_level = &si_dpm_debugfs_print_current_performance_level,8128.force_performance_level = &si_dpm_force_performance_level,8129.vblank_too_short = &si_dpm_vblank_too_short,8130.set_fan_control_mode = &si_dpm_set_fan_control_mode,8131.get_fan_control_mode = &si_dpm_get_fan_control_mode,8132.set_fan_speed_pwm = &si_dpm_set_fan_speed_pwm,8133.get_fan_speed_pwm = &si_dpm_get_fan_speed_pwm,8134.check_state_equal = &si_check_state_equal,8135.get_vce_clock_state = amdgpu_get_vce_clock_state,8136.read_sensor = &si_dpm_read_sensor,8137.pm_compute_clocks = amdgpu_legacy_dpm_compute_clocks,8138};81398140static const struct amdgpu_irq_src_funcs si_dpm_irq_funcs = {8141.set = si_dpm_set_interrupt_state,8142.process = si_dpm_process_interrupt,8143};81448145static void si_dpm_set_irq_funcs(struct amdgpu_device *adev)8146{8147adev->pm.dpm.thermal.irq.num_types = AMDGPU_THERMAL_IRQ_LAST;8148adev->pm.dpm.thermal.irq.funcs = &si_dpm_irq_funcs;8149}8150815181528153