1b3490673SHuang Rui /*
2b3490673SHuang Rui * Copyright 2019 Advanced Micro Devices, Inc.
3b3490673SHuang Rui *
4b3490673SHuang Rui * Permission is hereby granted, free of charge, to any person obtaining a
5b3490673SHuang Rui * copy of this software and associated documentation files (the "Software"),
6b3490673SHuang Rui * to deal in the Software without restriction, including without limitation
7b3490673SHuang Rui * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8b3490673SHuang Rui * and/or sell copies of the Software, and to permit persons to whom the
9b3490673SHuang Rui * Software is furnished to do so, subject to the following conditions:
10b3490673SHuang Rui *
11b3490673SHuang Rui * The above copyright notice and this permission notice shall be included in
12b3490673SHuang Rui * all copies or substantial portions of the Software.
13b3490673SHuang Rui *
14b3490673SHuang Rui * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15b3490673SHuang Rui * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16b3490673SHuang Rui * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17b3490673SHuang Rui * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18b3490673SHuang Rui * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19b3490673SHuang Rui * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20b3490673SHuang Rui * OTHER DEALINGS IN THE SOFTWARE.
21b3490673SHuang Rui *
22b3490673SHuang Rui */
23b3490673SHuang Rui
24d8e0b16dSEvan Quan #define SWSMU_CODE_LAYER_L2
25d8e0b16dSEvan Quan
26b3490673SHuang Rui #include <linux/firmware.h>
27354e6e14SAlex Deucher #include <linux/pci.h>
281bc73475SAlex Deucher #include <linux/i2c.h>
29b3490673SHuang Rui #include "amdgpu.h"
302f60dd50SLuben Tuikov #include "amdgpu_dpm.h"
31b3490673SHuang Rui #include "amdgpu_smu.h"
32b3490673SHuang Rui #include "atomfirmware.h"
33b3490673SHuang Rui #include "amdgpu_atomfirmware.h"
3422f2447cSEvan Quan #include "amdgpu_atombios.h"
3549e78c82SEvan Quan #include "soc15_common.h"
36b3490673SHuang Rui #include "smu_v11_0.h"
37013fd3a6SHuang Rui #include "smu11_driver_if_navi10.h"
38b3490673SHuang Rui #include "atom.h"
39b3490673SHuang Rui #include "navi10_ppt.h"
40b3490673SHuang Rui #include "smu_v11_0_pptable.h"
41b3490673SHuang Rui #include "smu_v11_0_ppsmc.h"
4249e78c82SEvan Quan #include "nbio/nbio_2_3_offset.h"
4349e78c82SEvan Quan #include "nbio/nbio_2_3_sh_mask.h"
44947c127bSLikun Gao #include "thm/thm_11_0_2_offset.h"
45947c127bSLikun Gao #include "thm/thm_11_0_2_sh_mask.h"
46b3490673SHuang Rui
47fc419158STao Zhou #include "asic_reg/mp/mp_11_0_sh_mask.h"
486c339f37SEvan Quan #include "smu_cmn.h"
49665945ebSEvan Quan #include "smu_11_0_cdr_table.h"
50fc419158STao Zhou
5155084d7fSEvan Quan /*
5255084d7fSEvan Quan * DO NOT use these for err/warn/info/debug messages.
5355084d7fSEvan Quan * Use dev_err, dev_warn, dev_info and dev_dbg instead.
5455084d7fSEvan Quan * They are more MGPU friendly.
5555084d7fSEvan Quan */
5655084d7fSEvan Quan #undef pr_err
5755084d7fSEvan Quan #undef pr_warn
5855084d7fSEvan Quan #undef pr_info
5955084d7fSEvan Quan #undef pr_debug
6055084d7fSEvan Quan
6144ff0ae6SAlex Deucher #define FEATURE_MASK(feature) (1ULL << feature)
624228b601SKevin Wang #define SMC_DPM_FEATURE ( \
634228b601SKevin Wang FEATURE_MASK(FEATURE_DPM_PREFETCHER_BIT) | \
644228b601SKevin Wang FEATURE_MASK(FEATURE_DPM_GFXCLK_BIT) | \
654228b601SKevin Wang FEATURE_MASK(FEATURE_DPM_GFX_PACE_BIT) | \
664228b601SKevin Wang FEATURE_MASK(FEATURE_DPM_UCLK_BIT) | \
674228b601SKevin Wang FEATURE_MASK(FEATURE_DPM_SOCCLK_BIT) | \
684228b601SKevin Wang FEATURE_MASK(FEATURE_DPM_MP0CLK_BIT) | \
694228b601SKevin Wang FEATURE_MASK(FEATURE_DPM_LINK_BIT) | \
704228b601SKevin Wang FEATURE_MASK(FEATURE_DPM_DCEFCLK_BIT))
714228b601SKevin Wang
727d6c13efSEvan Quan #define SMU_11_0_GFX_BUSY_THRESHOLD 15
737d6c13efSEvan Quan
746c339f37SEvan Quan static struct cmn2asic_msg_mapping navi10_message_map[SMU_MSG_MAX_COUNT] = {
75d4f3c0b3SWenhui Sheng MSG_MAP(TestMessage, PPSMC_MSG_TestMessage, 1),
76d4f3c0b3SWenhui Sheng MSG_MAP(GetSmuVersion, PPSMC_MSG_GetSmuVersion, 1),
77d4f3c0b3SWenhui Sheng MSG_MAP(GetDriverIfVersion, PPSMC_MSG_GetDriverIfVersion, 1),
78d4f3c0b3SWenhui Sheng MSG_MAP(SetAllowedFeaturesMaskLow, PPSMC_MSG_SetAllowedFeaturesMaskLow, 0),
79d4f3c0b3SWenhui Sheng MSG_MAP(SetAllowedFeaturesMaskHigh, PPSMC_MSG_SetAllowedFeaturesMaskHigh, 0),
80d4f3c0b3SWenhui Sheng MSG_MAP(EnableAllSmuFeatures, PPSMC_MSG_EnableAllSmuFeatures, 0),
81d4f3c0b3SWenhui Sheng MSG_MAP(DisableAllSmuFeatures, PPSMC_MSG_DisableAllSmuFeatures, 0),
82f1802aa7SYifan Zha MSG_MAP(EnableSmuFeaturesLow, PPSMC_MSG_EnableSmuFeaturesLow, 0),
83f1802aa7SYifan Zha MSG_MAP(EnableSmuFeaturesHigh, PPSMC_MSG_EnableSmuFeaturesHigh, 0),
84f1802aa7SYifan Zha MSG_MAP(DisableSmuFeaturesLow, PPSMC_MSG_DisableSmuFeaturesLow, 0),
85f1802aa7SYifan Zha MSG_MAP(DisableSmuFeaturesHigh, PPSMC_MSG_DisableSmuFeaturesHigh, 0),
86d4f3c0b3SWenhui Sheng MSG_MAP(GetEnabledSmuFeaturesLow, PPSMC_MSG_GetEnabledSmuFeaturesLow, 1),
87d4f3c0b3SWenhui Sheng MSG_MAP(GetEnabledSmuFeaturesHigh, PPSMC_MSG_GetEnabledSmuFeaturesHigh, 1),
88fd30b7d9SYifan Zha MSG_MAP(SetWorkloadMask, PPSMC_MSG_SetWorkloadMask, 0),
89d4f3c0b3SWenhui Sheng MSG_MAP(SetPptLimit, PPSMC_MSG_SetPptLimit, 0),
90fd30b7d9SYifan Zha MSG_MAP(SetDriverDramAddrHigh, PPSMC_MSG_SetDriverDramAddrHigh, 1),
91fd30b7d9SYifan Zha MSG_MAP(SetDriverDramAddrLow, PPSMC_MSG_SetDriverDramAddrLow, 1),
92d4f3c0b3SWenhui Sheng MSG_MAP(SetToolsDramAddrHigh, PPSMC_MSG_SetToolsDramAddrHigh, 0),
93d4f3c0b3SWenhui Sheng MSG_MAP(SetToolsDramAddrLow, PPSMC_MSG_SetToolsDramAddrLow, 0),
94fd30b7d9SYifan Zha MSG_MAP(TransferTableSmu2Dram, PPSMC_MSG_TransferTableSmu2Dram, 1),
95d4f3c0b3SWenhui Sheng MSG_MAP(TransferTableDram2Smu, PPSMC_MSG_TransferTableDram2Smu, 0),
96d4f3c0b3SWenhui Sheng MSG_MAP(UseDefaultPPTable, PPSMC_MSG_UseDefaultPPTable, 0),
97d4f3c0b3SWenhui Sheng MSG_MAP(UseBackupPPTable, PPSMC_MSG_UseBackupPPTable, 0),
98d4f3c0b3SWenhui Sheng MSG_MAP(RunBtc, PPSMC_MSG_RunBtc, 0),
99d4f3c0b3SWenhui Sheng MSG_MAP(EnterBaco, PPSMC_MSG_EnterBaco, 0),
100fd30b7d9SYifan Zha MSG_MAP(SetSoftMinByFreq, PPSMC_MSG_SetSoftMinByFreq, 1),
101fd30b7d9SYifan Zha MSG_MAP(SetSoftMaxByFreq, PPSMC_MSG_SetSoftMaxByFreq, 1),
102fd30b7d9SYifan Zha MSG_MAP(SetHardMinByFreq, PPSMC_MSG_SetHardMinByFreq, 0),
103d4f3c0b3SWenhui Sheng MSG_MAP(SetHardMaxByFreq, PPSMC_MSG_SetHardMaxByFreq, 0),
104d4f3c0b3SWenhui Sheng MSG_MAP(GetMinDpmFreq, PPSMC_MSG_GetMinDpmFreq, 1),
105d4f3c0b3SWenhui Sheng MSG_MAP(GetMaxDpmFreq, PPSMC_MSG_GetMaxDpmFreq, 1),
106d4f3c0b3SWenhui Sheng MSG_MAP(GetDpmFreqByIndex, PPSMC_MSG_GetDpmFreqByIndex, 1),
107d4f3c0b3SWenhui Sheng MSG_MAP(SetMemoryChannelConfig, PPSMC_MSG_SetMemoryChannelConfig, 0),
108d4f3c0b3SWenhui Sheng MSG_MAP(SetGeminiMode, PPSMC_MSG_SetGeminiMode, 0),
109d4f3c0b3SWenhui Sheng MSG_MAP(SetGeminiApertureHigh, PPSMC_MSG_SetGeminiApertureHigh, 0),
110d4f3c0b3SWenhui Sheng MSG_MAP(SetGeminiApertureLow, PPSMC_MSG_SetGeminiApertureLow, 0),
111d4f3c0b3SWenhui Sheng MSG_MAP(OverridePcieParameters, PPSMC_MSG_OverridePcieParameters, 0),
112d4f3c0b3SWenhui Sheng MSG_MAP(SetMinDeepSleepDcefclk, PPSMC_MSG_SetMinDeepSleepDcefclk, 0),
113d4f3c0b3SWenhui Sheng MSG_MAP(ReenableAcDcInterrupt, PPSMC_MSG_ReenableAcDcInterrupt, 0),
114d4f3c0b3SWenhui Sheng MSG_MAP(NotifyPowerSource, PPSMC_MSG_NotifyPowerSource, 0),
115d4f3c0b3SWenhui Sheng MSG_MAP(SetUclkFastSwitch, PPSMC_MSG_SetUclkFastSwitch, 0),
116d4f3c0b3SWenhui Sheng MSG_MAP(SetVideoFps, PPSMC_MSG_SetVideoFps, 0),
117d4f3c0b3SWenhui Sheng MSG_MAP(PrepareMp1ForUnload, PPSMC_MSG_PrepareMp1ForUnload, 1),
118d4f3c0b3SWenhui Sheng MSG_MAP(DramLogSetDramAddrHigh, PPSMC_MSG_DramLogSetDramAddrHigh, 0),
119d4f3c0b3SWenhui Sheng MSG_MAP(DramLogSetDramAddrLow, PPSMC_MSG_DramLogSetDramAddrLow, 0),
120d4f3c0b3SWenhui Sheng MSG_MAP(DramLogSetDramSize, PPSMC_MSG_DramLogSetDramSize, 0),
121d4f3c0b3SWenhui Sheng MSG_MAP(ConfigureGfxDidt, PPSMC_MSG_ConfigureGfxDidt, 0),
122d4f3c0b3SWenhui Sheng MSG_MAP(NumOfDisplays, PPSMC_MSG_NumOfDisplays, 0),
123d4f3c0b3SWenhui Sheng MSG_MAP(SetSystemVirtualDramAddrHigh, PPSMC_MSG_SetSystemVirtualDramAddrHigh, 0),
124d4f3c0b3SWenhui Sheng MSG_MAP(SetSystemVirtualDramAddrLow, PPSMC_MSG_SetSystemVirtualDramAddrLow, 0),
125d4f3c0b3SWenhui Sheng MSG_MAP(AllowGfxOff, PPSMC_MSG_AllowGfxOff, 0),
126d4f3c0b3SWenhui Sheng MSG_MAP(DisallowGfxOff, PPSMC_MSG_DisallowGfxOff, 0),
127d4f3c0b3SWenhui Sheng MSG_MAP(GetPptLimit, PPSMC_MSG_GetPptLimit, 0),
128d4f3c0b3SWenhui Sheng MSG_MAP(GetDcModeMaxDpmFreq, PPSMC_MSG_GetDcModeMaxDpmFreq, 1),
129d4f3c0b3SWenhui Sheng MSG_MAP(GetDebugData, PPSMC_MSG_GetDebugData, 0),
130d4f3c0b3SWenhui Sheng MSG_MAP(ExitBaco, PPSMC_MSG_ExitBaco, 0),
131d4f3c0b3SWenhui Sheng MSG_MAP(PrepareMp1ForReset, PPSMC_MSG_PrepareMp1ForReset, 0),
132d4f3c0b3SWenhui Sheng MSG_MAP(PrepareMp1ForShutdown, PPSMC_MSG_PrepareMp1ForShutdown, 0),
133d4f3c0b3SWenhui Sheng MSG_MAP(PowerUpVcn, PPSMC_MSG_PowerUpVcn, 0),
134d4f3c0b3SWenhui Sheng MSG_MAP(PowerDownVcn, PPSMC_MSG_PowerDownVcn, 0),
135d4f3c0b3SWenhui Sheng MSG_MAP(PowerUpJpeg, PPSMC_MSG_PowerUpJpeg, 0),
136d4f3c0b3SWenhui Sheng MSG_MAP(PowerDownJpeg, PPSMC_MSG_PowerDownJpeg, 0),
137d4f3c0b3SWenhui Sheng MSG_MAP(BacoAudioD3PME, PPSMC_MSG_BacoAudioD3PME, 0),
138d4f3c0b3SWenhui Sheng MSG_MAP(ArmD3, PPSMC_MSG_ArmD3, 0),
139d4f3c0b3SWenhui Sheng MSG_MAP(DAL_DISABLE_DUMMY_PSTATE_CHANGE, PPSMC_MSG_DALDisableDummyPstateChange, 0),
140d4f3c0b3SWenhui Sheng MSG_MAP(DAL_ENABLE_DUMMY_PSTATE_CHANGE, PPSMC_MSG_DALEnableDummyPstateChange, 0),
141d4f3c0b3SWenhui Sheng MSG_MAP(GetVoltageByDpm, PPSMC_MSG_GetVoltageByDpm, 0),
142d4f3c0b3SWenhui Sheng MSG_MAP(GetVoltageByDpmOverdrive, PPSMC_MSG_GetVoltageByDpmOverdrive, 0),
14394a670d5SEvan Quan MSG_MAP(SetMGpuFanBoostLimitRpm, PPSMC_MSG_SetMGpuFanBoostLimitRpm, 0),
144665945ebSEvan Quan MSG_MAP(SET_DRIVER_DUMMY_TABLE_DRAM_ADDR_HIGH, PPSMC_MSG_SetDriverDummyTableDramAddrHigh, 0),
145665945ebSEvan Quan MSG_MAP(SET_DRIVER_DUMMY_TABLE_DRAM_ADDR_LOW, PPSMC_MSG_SetDriverDummyTableDramAddrLow, 0),
146bb7257b5SEvan Quan MSG_MAP(GET_UMC_FW_WA, PPSMC_MSG_GetUMCFWWA, 0),
147b3490673SHuang Rui };
148b3490673SHuang Rui
1496c339f37SEvan Quan static struct cmn2asic_mapping navi10_clk_map[SMU_CLK_COUNT] = {
1500de94acfSHuang Rui CLK_MAP(GFXCLK, PPCLK_GFXCLK),
151b1e7e224SKevin Wang CLK_MAP(SCLK, PPCLK_GFXCLK),
1520de94acfSHuang Rui CLK_MAP(SOCCLK, PPCLK_SOCCLK),
153b1e7e224SKevin Wang CLK_MAP(FCLK, PPCLK_SOCCLK),
1540de94acfSHuang Rui CLK_MAP(UCLK, PPCLK_UCLK),
155b1e7e224SKevin Wang CLK_MAP(MCLK, PPCLK_UCLK),
1560de94acfSHuang Rui CLK_MAP(DCLK, PPCLK_DCLK),
1570de94acfSHuang Rui CLK_MAP(VCLK, PPCLK_VCLK),
1580de94acfSHuang Rui CLK_MAP(DCEFCLK, PPCLK_DCEFCLK),
1590de94acfSHuang Rui CLK_MAP(DISPCLK, PPCLK_DISPCLK),
1600de94acfSHuang Rui CLK_MAP(PIXCLK, PPCLK_PIXCLK),
1610de94acfSHuang Rui CLK_MAP(PHYCLK, PPCLK_PHYCLK),
1620de94acfSHuang Rui };
1630de94acfSHuang Rui
1646c339f37SEvan Quan static struct cmn2asic_mapping navi10_feature_mask_map[SMU_FEATURE_COUNT] = {
165ffcb08dfSHuang Rui FEA_MAP(DPM_PREFETCHER),
166ffcb08dfSHuang Rui FEA_MAP(DPM_GFXCLK),
167ffcb08dfSHuang Rui FEA_MAP(DPM_GFX_PACE),
168ffcb08dfSHuang Rui FEA_MAP(DPM_UCLK),
169ffcb08dfSHuang Rui FEA_MAP(DPM_SOCCLK),
170ffcb08dfSHuang Rui FEA_MAP(DPM_MP0CLK),
171ffcb08dfSHuang Rui FEA_MAP(DPM_LINK),
172ffcb08dfSHuang Rui FEA_MAP(DPM_DCEFCLK),
173ffcb08dfSHuang Rui FEA_MAP(MEM_VDDCI_SCALING),
174ffcb08dfSHuang Rui FEA_MAP(MEM_MVDD_SCALING),
175ffcb08dfSHuang Rui FEA_MAP(DS_GFXCLK),
176ffcb08dfSHuang Rui FEA_MAP(DS_SOCCLK),
177ffcb08dfSHuang Rui FEA_MAP(DS_LCLK),
178ffcb08dfSHuang Rui FEA_MAP(DS_DCEFCLK),
179ffcb08dfSHuang Rui FEA_MAP(DS_UCLK),
180ffcb08dfSHuang Rui FEA_MAP(GFX_ULV),
181ffcb08dfSHuang Rui FEA_MAP(FW_DSTATE),
182ffcb08dfSHuang Rui FEA_MAP(GFXOFF),
183ffcb08dfSHuang Rui FEA_MAP(BACO),
184ffcb08dfSHuang Rui FEA_MAP(VCN_PG),
185ffcb08dfSHuang Rui FEA_MAP(JPEG_PG),
186ffcb08dfSHuang Rui FEA_MAP(USB_PG),
187ffcb08dfSHuang Rui FEA_MAP(RSMU_SMN_CG),
188ffcb08dfSHuang Rui FEA_MAP(PPT),
189ffcb08dfSHuang Rui FEA_MAP(TDC),
190ffcb08dfSHuang Rui FEA_MAP(GFX_EDC),
191ffcb08dfSHuang Rui FEA_MAP(APCC_PLUS),
192ffcb08dfSHuang Rui FEA_MAP(GTHR),
193ffcb08dfSHuang Rui FEA_MAP(ACDC),
194ffcb08dfSHuang Rui FEA_MAP(VR0HOT),
195ffcb08dfSHuang Rui FEA_MAP(VR1HOT),
196ffcb08dfSHuang Rui FEA_MAP(FW_CTF),
197ffcb08dfSHuang Rui FEA_MAP(FAN_CONTROL),
198ffcb08dfSHuang Rui FEA_MAP(THERMAL),
199ffcb08dfSHuang Rui FEA_MAP(GFX_DCS),
200ffcb08dfSHuang Rui FEA_MAP(RM),
201ffcb08dfSHuang Rui FEA_MAP(LED_DISPLAY),
202ffcb08dfSHuang Rui FEA_MAP(GFX_SS),
203ffcb08dfSHuang Rui FEA_MAP(OUT_OF_BAND_MONITOR),
204ffcb08dfSHuang Rui FEA_MAP(TEMP_DEPENDENT_VMIN),
205ffcb08dfSHuang Rui FEA_MAP(MMHUB_PG),
206ffcb08dfSHuang Rui FEA_MAP(ATHUB_PG),
207f256ba47SXiaojie Yuan FEA_MAP(APCC_DFLL),
208ffcb08dfSHuang Rui };
209ffcb08dfSHuang Rui
2106c339f37SEvan Quan static struct cmn2asic_mapping navi10_table_map[SMU_TABLE_COUNT] = {
2112436911bSHuang Rui TAB_MAP(PPTABLE),
2122436911bSHuang Rui TAB_MAP(WATERMARKS),
2132436911bSHuang Rui TAB_MAP(AVFS),
2142436911bSHuang Rui TAB_MAP(AVFS_PSM_DEBUG),
2152436911bSHuang Rui TAB_MAP(AVFS_FUSE_OVERRIDE),
2162436911bSHuang Rui TAB_MAP(PMSTATUSLOG),
2172436911bSHuang Rui TAB_MAP(SMU_METRICS),
2182436911bSHuang Rui TAB_MAP(DRIVER_SMU_CONFIG),
2192436911bSHuang Rui TAB_MAP(ACTIVITY_MONITOR_COEFF),
2202436911bSHuang Rui TAB_MAP(OVERDRIVE),
2212436911bSHuang Rui TAB_MAP(I2C_COMMANDS),
2222436911bSHuang Rui TAB_MAP(PACE),
2232436911bSHuang Rui };
2242436911bSHuang Rui
2256c339f37SEvan Quan static struct cmn2asic_mapping navi10_pwr_src_map[SMU_POWER_SOURCE_COUNT] = {
2268890fe5fSHuang Rui PWR_MAP(AC),
2278890fe5fSHuang Rui PWR_MAP(DC),
2288890fe5fSHuang Rui };
2298890fe5fSHuang Rui
2306c339f37SEvan Quan static struct cmn2asic_mapping navi10_workload_map[PP_SMC_POWER_PROFILE_COUNT] = {
2316c6187ecSKevin Wang WORKLOAD_MAP(PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT, WORKLOAD_PPLIB_DEFAULT_BIT),
2326c6187ecSKevin Wang WORKLOAD_MAP(PP_SMC_POWER_PROFILE_FULLSCREEN3D, WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT),
2336c6187ecSKevin Wang WORKLOAD_MAP(PP_SMC_POWER_PROFILE_POWERSAVING, WORKLOAD_PPLIB_POWER_SAVING_BIT),
2346c6187ecSKevin Wang WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VIDEO, WORKLOAD_PPLIB_VIDEO_BIT),
2356c6187ecSKevin Wang WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VR, WORKLOAD_PPLIB_VR_BIT),
2362c874ad9SKevin Wang WORKLOAD_MAP(PP_SMC_POWER_PROFILE_COMPUTE, WORKLOAD_PPLIB_COMPUTE_BIT),
2376c6187ecSKevin Wang WORKLOAD_MAP(PP_SMC_POWER_PROFILE_CUSTOM, WORKLOAD_PPLIB_CUSTOM_BIT),
2386c6187ecSKevin Wang };
2396c6187ecSKevin Wang
24064cdee43SGraham Sider static const uint8_t navi1x_throttler_map[] = {
24164cdee43SGraham Sider [THROTTLER_TEMP_EDGE_BIT] = (SMU_THROTTLER_TEMP_EDGE_BIT),
24264cdee43SGraham Sider [THROTTLER_TEMP_HOTSPOT_BIT] = (SMU_THROTTLER_TEMP_HOTSPOT_BIT),
24364cdee43SGraham Sider [THROTTLER_TEMP_MEM_BIT] = (SMU_THROTTLER_TEMP_MEM_BIT),
24464cdee43SGraham Sider [THROTTLER_TEMP_VR_GFX_BIT] = (SMU_THROTTLER_TEMP_VR_GFX_BIT),
24564cdee43SGraham Sider [THROTTLER_TEMP_VR_MEM0_BIT] = (SMU_THROTTLER_TEMP_VR_MEM0_BIT),
24664cdee43SGraham Sider [THROTTLER_TEMP_VR_MEM1_BIT] = (SMU_THROTTLER_TEMP_VR_MEM1_BIT),
24764cdee43SGraham Sider [THROTTLER_TEMP_VR_SOC_BIT] = (SMU_THROTTLER_TEMP_VR_SOC_BIT),
24864cdee43SGraham Sider [THROTTLER_TEMP_LIQUID0_BIT] = (SMU_THROTTLER_TEMP_LIQUID0_BIT),
24964cdee43SGraham Sider [THROTTLER_TEMP_LIQUID1_BIT] = (SMU_THROTTLER_TEMP_LIQUID1_BIT),
25064cdee43SGraham Sider [THROTTLER_TDC_GFX_BIT] = (SMU_THROTTLER_TDC_GFX_BIT),
25164cdee43SGraham Sider [THROTTLER_TDC_SOC_BIT] = (SMU_THROTTLER_TDC_SOC_BIT),
25264cdee43SGraham Sider [THROTTLER_PPT0_BIT] = (SMU_THROTTLER_PPT0_BIT),
25364cdee43SGraham Sider [THROTTLER_PPT1_BIT] = (SMU_THROTTLER_PPT1_BIT),
25464cdee43SGraham Sider [THROTTLER_PPT2_BIT] = (SMU_THROTTLER_PPT2_BIT),
25564cdee43SGraham Sider [THROTTLER_PPT3_BIT] = (SMU_THROTTLER_PPT3_BIT),
25664cdee43SGraham Sider [THROTTLER_FIT_BIT] = (SMU_THROTTLER_FIT_BIT),
25764cdee43SGraham Sider [THROTTLER_PPM_BIT] = (SMU_THROTTLER_PPM_BIT),
25864cdee43SGraham Sider [THROTTLER_APCC_BIT] = (SMU_THROTTLER_APCC_BIT),
25964cdee43SGraham Sider };
26064cdee43SGraham Sider
26164cdee43SGraham Sider
is_asic_secure(struct smu_context * smu)262fc419158STao Zhou static bool is_asic_secure(struct smu_context *smu)
263fc419158STao Zhou {
264fc419158STao Zhou struct amdgpu_device *adev = smu->adev;
265fc419158STao Zhou bool is_secure = true;
266fc419158STao Zhou uint32_t mp0_fw_intf;
267fc419158STao Zhou
268fc419158STao Zhou mp0_fw_intf = RREG32_PCIE(MP0_Public |
269fc419158STao Zhou (smnMP0_FW_INTF & 0xffffffff));
270fc419158STao Zhou
271fc419158STao Zhou if (!(mp0_fw_intf & (1 << 19)))
272fc419158STao Zhou is_secure = false;
273fc419158STao Zhou
274fc419158STao Zhou return is_secure;
275fc419158STao Zhou }
276fc419158STao Zhou
277b3490673SHuang Rui static int
navi10_get_allowed_feature_mask(struct smu_context * smu,uint32_t * feature_mask,uint32_t num)27874c958a3SKevin Wang navi10_get_allowed_feature_mask(struct smu_context *smu,
279b3490673SHuang Rui uint32_t *feature_mask, uint32_t num)
280b3490673SHuang Rui {
2819e040216SKenneth Feng struct amdgpu_device *adev = smu->adev;
2829e040216SKenneth Feng
283b3490673SHuang Rui if (num > 2)
284b3490673SHuang Rui return -EINVAL;
285b3490673SHuang Rui
28674c958a3SKevin Wang memset(feature_mask, 0, sizeof(uint32_t) * num);
28774c958a3SKevin Wang
28877ee9cafSKevin Wang *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_PREFETCHER_BIT)
28974c958a3SKevin Wang | FEATURE_MASK(FEATURE_DPM_MP0CLK_BIT)
29074c958a3SKevin Wang | FEATURE_MASK(FEATURE_RSMU_SMN_CG_BIT)
291d7a8efa5STao Zhou | FEATURE_MASK(FEATURE_DS_SOCCLK_BIT)
29274c958a3SKevin Wang | FEATURE_MASK(FEATURE_PPT_BIT)
29374c958a3SKevin Wang | FEATURE_MASK(FEATURE_TDC_BIT)
29474c958a3SKevin Wang | FEATURE_MASK(FEATURE_GFX_EDC_BIT)
295c1972a56SXiaojie Yuan | FEATURE_MASK(FEATURE_APCC_PLUS_BIT)
29674c958a3SKevin Wang | FEATURE_MASK(FEATURE_VR0HOT_BIT)
29774c958a3SKevin Wang | FEATURE_MASK(FEATURE_FAN_CONTROL_BIT)
29874c958a3SKevin Wang | FEATURE_MASK(FEATURE_THERMAL_BIT)
29974c958a3SKevin Wang | FEATURE_MASK(FEATURE_LED_DISPLAY_BIT)
300c1972a56SXiaojie Yuan | FEATURE_MASK(FEATURE_DS_LCLK_BIT)
3013a3c51ddSKenneth Feng | FEATURE_MASK(FEATURE_DS_DCEFCLK_BIT)
302d8ceb192SKenneth Feng | FEATURE_MASK(FEATURE_FW_DSTATE_BIT)
3037c6fe84cSJack Xiao | FEATURE_MASK(FEATURE_BACO_BIT)
304597292ebSKenneth Feng | FEATURE_MASK(FEATURE_GFX_SS_BIT)
305597292ebSKenneth Feng | FEATURE_MASK(FEATURE_APCC_DFLL_BIT)
306c1972a56SXiaojie Yuan | FEATURE_MASK(FEATURE_FW_CTF_BIT)
3073043d13fSAlex Deucher | FEATURE_MASK(FEATURE_OUT_OF_BAND_MONITOR_BIT)
3083043d13fSAlex Deucher | FEATURE_MASK(FEATURE_TEMP_DEPENDENT_VMIN_BIT);
3098c3b2d1bStiancyin
310bc7ef865SAlex Deucher if (adev->pm.pp_feature & PP_SCLK_DPM_MASK)
311bc7ef865SAlex Deucher *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_GFXCLK_BIT);
312bc7ef865SAlex Deucher
313bc7ef865SAlex Deucher if (adev->pm.pp_feature & PP_PCIE_DPM_MASK)
314bc7ef865SAlex Deucher *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_LINK_BIT);
315bc7ef865SAlex Deucher
316bc7ef865SAlex Deucher if (adev->pm.pp_feature & PP_DCEFCLK_DPM_MASK)
317bc7ef865SAlex Deucher *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_DCEFCLK_BIT);
318bc7ef865SAlex Deucher
319bc7ef865SAlex Deucher if (adev->pm.pp_feature & PP_ULV_MASK)
320bc7ef865SAlex Deucher *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_GFX_ULV_BIT);
321bc7ef865SAlex Deucher
322bc7ef865SAlex Deucher if (adev->pm.pp_feature & PP_SCLK_DEEP_SLEEP_MASK)
323bc7ef865SAlex Deucher *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DS_GFXCLK_BIT);
324bc7ef865SAlex Deucher
325bb3d7d32SXiaojie Yuan if (adev->pm.pp_feature & PP_GFXOFF_MASK)
326597292ebSKenneth Feng *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_GFXOFF_BIT);
3279e040216SKenneth Feng
328c12d410fSHuang Rui if (smu->adev->pg_flags & AMD_PG_SUPPORT_MMHUB)
329c12d410fSHuang Rui *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_MMHUB_PG_BIT);
330c12d410fSHuang Rui
331a201b6acSHuang Rui if (smu->adev->pg_flags & AMD_PG_SUPPORT_ATHUB)
332a201b6acSHuang Rui *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_ATHUB_PG_BIT);
333a201b6acSHuang Rui
334c4b76d23SKenneth Feng if (smu->adev->pg_flags & AMD_PG_SUPPORT_VCN)
33543717ff6SLeo Liu *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_VCN_PG_BIT);
33643717ff6SLeo Liu
33743717ff6SLeo Liu if (smu->adev->pg_flags & AMD_PG_SUPPORT_JPEG)
33843717ff6SLeo Liu *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_JPEG_PG_BIT);
339c4b76d23SKenneth Feng
340f5cdd2bdSAlex Deucher if (smu->dc_controlled_by_gpio)
341f5cdd2bdSAlex Deucher *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_ACDC_BIT);
342f5cdd2bdSAlex Deucher
343c220ba6fSEvan Quan if (adev->pm.pp_feature & PP_SOCCLK_DPM_MASK)
344c220ba6fSEvan Quan *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_SOCCLK_BIT);
345c220ba6fSEvan Quan
346c220ba6fSEvan Quan /* DPM UCLK enablement should be skipped for navi10 A0 secure board */
347c220ba6fSEvan Quan if (!(is_asic_secure(smu) &&
3484e8303cfSLijo Lazar (amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(11, 0, 0)) &&
349c220ba6fSEvan Quan (adev->rev_id == 0)) &&
350c220ba6fSEvan Quan (adev->pm.pp_feature & PP_MCLK_DPM_MASK))
351c220ba6fSEvan Quan *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_UCLK_BIT)
352c220ba6fSEvan Quan | FEATURE_MASK(FEATURE_MEM_VDDCI_SCALING_BIT)
353c220ba6fSEvan Quan | FEATURE_MASK(FEATURE_MEM_MVDD_SCALING_BIT);
354c220ba6fSEvan Quan
35510144762SEvan Quan /* DS SOCCLK enablement should be skipped for navi10 A0 secure board */
35610144762SEvan Quan if (is_asic_secure(smu) &&
3574e8303cfSLijo Lazar (amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(11, 0, 0)) &&
35810144762SEvan Quan (adev->rev_id == 0))
359c877dff7STao Zhou *(uint64_t *)feature_mask &=
360c877dff7STao Zhou ~FEATURE_MASK(FEATURE_DS_SOCCLK_BIT);
361c877dff7STao Zhou
362b3490673SHuang Rui return 0;
363b3490673SHuang Rui }
364b3490673SHuang Rui
navi10_check_bxco_support(struct smu_context * smu)365458020ddSLijo Lazar static void navi10_check_bxco_support(struct smu_context *smu)
366b3490673SHuang Rui {
3674a13b4ceSEvan Quan struct smu_table_context *table_context = &smu->smu_table;
3684a13b4ceSEvan Quan struct smu_11_0_powerplay_table *powerplay_table =
3694a13b4ceSEvan Quan table_context->power_play_table;
3704a13b4ceSEvan Quan struct smu_baco_context *smu_baco = &smu->smu_baco;
371458020ddSLijo Lazar struct amdgpu_device *adev = smu->adev;
372458020ddSLijo Lazar uint32_t val;
373458020ddSLijo Lazar
374458020ddSLijo Lazar if (powerplay_table->platform_caps & SMU_11_0_PP_PLATFORM_CAP_BACO ||
375458020ddSLijo Lazar powerplay_table->platform_caps & SMU_11_0_PP_PLATFORM_CAP_MACO) {
376458020ddSLijo Lazar val = RREG32_SOC15(NBIO, 0, mmRCC_BIF_STRAP0);
377458020ddSLijo Lazar smu_baco->platform_support =
378458020ddSLijo Lazar (val & RCC_BIF_STRAP0__STRAP_PX_CAPABLE_MASK) ? true :
379458020ddSLijo Lazar false;
380458020ddSLijo Lazar }
381458020ddSLijo Lazar }
382458020ddSLijo Lazar
navi10_check_powerplay_table(struct smu_context * smu)383458020ddSLijo Lazar static int navi10_check_powerplay_table(struct smu_context *smu)
384458020ddSLijo Lazar {
385458020ddSLijo Lazar struct smu_table_context *table_context = &smu->smu_table;
386458020ddSLijo Lazar struct smu_11_0_powerplay_table *powerplay_table =
387458020ddSLijo Lazar table_context->power_play_table;
3884a13b4ceSEvan Quan
3894a13b4ceSEvan Quan if (powerplay_table->platform_caps & SMU_11_0_PP_PLATFORM_CAP_HARDWAREDC)
3904a13b4ceSEvan Quan smu->dc_controlled_by_gpio = true;
3914a13b4ceSEvan Quan
392458020ddSLijo Lazar navi10_check_bxco_support(smu);
3934a13b4ceSEvan Quan
3944a13b4ceSEvan Quan table_context->thermal_controller_type =
3954a13b4ceSEvan Quan powerplay_table->thermal_controller_type;
3964a13b4ceSEvan Quan
3974a13b4ceSEvan Quan /*
3984a13b4ceSEvan Quan * Instead of having its own buffer space and get overdrive_table copied,
3994a13b4ceSEvan Quan * smu->od_settings just points to the actual overdrive_table
4004a13b4ceSEvan Quan */
4014a13b4ceSEvan Quan smu->od_settings = &powerplay_table->overdrive_table;
4024a13b4ceSEvan Quan
403b3490673SHuang Rui return 0;
404b3490673SHuang Rui }
405b3490673SHuang Rui
navi10_append_powerplay_table(struct smu_context * smu)406b3490673SHuang Rui static int navi10_append_powerplay_table(struct smu_context *smu)
407b3490673SHuang Rui {
4089e040216SKenneth Feng struct amdgpu_device *adev = smu->adev;
409b3490673SHuang Rui struct smu_table_context *table_context = &smu->smu_table;
410b3490673SHuang Rui PPTable_t *smc_pptable = table_context->driver_pptable;
411b3490673SHuang Rui struct atom_smc_dpm_info_v4_5 *smc_dpm_table;
41202c0bb4eSEvan Quan struct atom_smc_dpm_info_v4_7 *smc_dpm_table_v4_7;
413b3490673SHuang Rui int index, ret;
414b3490673SHuang Rui
415b3490673SHuang Rui index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
416b3490673SHuang Rui smc_dpm_info);
417b3490673SHuang Rui
41822f2447cSEvan Quan ret = amdgpu_atombios_get_data_table(adev, index, NULL, NULL, NULL,
419b3490673SHuang Rui (uint8_t **)&smc_dpm_table);
420b3490673SHuang Rui if (ret)
421b3490673SHuang Rui return ret;
422b3490673SHuang Rui
423d9811cfcSEvan Quan dev_info(adev->dev, "smc_dpm_info table revision(format.content): %d.%d\n",
42402c0bb4eSEvan Quan smc_dpm_table->table_header.format_revision,
42502c0bb4eSEvan Quan smc_dpm_table->table_header.content_revision);
42602c0bb4eSEvan Quan
42702c0bb4eSEvan Quan if (smc_dpm_table->table_header.format_revision != 4) {
428d9811cfcSEvan Quan dev_err(adev->dev, "smc_dpm_info table format revision is not 4!\n");
42902c0bb4eSEvan Quan return -EINVAL;
43002c0bb4eSEvan Quan }
43102c0bb4eSEvan Quan
43202c0bb4eSEvan Quan switch (smc_dpm_table->table_header.content_revision) {
43302c0bb4eSEvan Quan case 5: /* nv10 and nv14 */
4344a9bd6dbSKees Cook smu_memcpy_trailing(smc_pptable, I2cControllers, BoardReserved,
4354a9bd6dbSKees Cook smc_dpm_table, I2cControllers);
43602c0bb4eSEvan Quan break;
43702c0bb4eSEvan Quan case 7: /* nv12 */
43822f2447cSEvan Quan ret = amdgpu_atombios_get_data_table(adev, index, NULL, NULL, NULL,
43902c0bb4eSEvan Quan (uint8_t **)&smc_dpm_table_v4_7);
44002c0bb4eSEvan Quan if (ret)
44102c0bb4eSEvan Quan return ret;
4424a9bd6dbSKees Cook smu_memcpy_trailing(smc_pptable, I2cControllers, BoardReserved,
4434a9bd6dbSKees Cook smc_dpm_table_v4_7, I2cControllers);
44402c0bb4eSEvan Quan break;
44502c0bb4eSEvan Quan default:
446d9811cfcSEvan Quan dev_err(smu->adev->dev, "smc_dpm_info with unsupported content revision %d!\n",
44702c0bb4eSEvan Quan smc_dpm_table->table_header.content_revision);
44802c0bb4eSEvan Quan return -EINVAL;
44902c0bb4eSEvan Quan }
450b3490673SHuang Rui
4512a8bfa13SJack Xiao if (adev->pm.pp_feature & PP_GFXOFF_MASK) {
4522a8bfa13SJack Xiao /* TODO: remove it once SMU fw fix it */
4532a8bfa13SJack Xiao smc_pptable->DebugOverrides |= DPM_OVERRIDE_DISABLE_DFLL_PLL_SHUTDOWN;
4542a8bfa13SJack Xiao }
4552a8bfa13SJack Xiao
456b3490673SHuang Rui return 0;
457b3490673SHuang Rui }
458b3490673SHuang Rui
navi10_store_powerplay_table(struct smu_context * smu)459b3490673SHuang Rui static int navi10_store_powerplay_table(struct smu_context *smu)
460b3490673SHuang Rui {
461b3490673SHuang Rui struct smu_table_context *table_context = &smu->smu_table;
4624a13b4ceSEvan Quan struct smu_11_0_powerplay_table *powerplay_table =
4634a13b4ceSEvan Quan table_context->power_play_table;
464b3490673SHuang Rui
465b3490673SHuang Rui memcpy(table_context->driver_pptable, &powerplay_table->smc_pptable,
466b3490673SHuang Rui sizeof(PPTable_t));
467b3490673SHuang Rui
468b3490673SHuang Rui return 0;
469b3490673SHuang Rui }
470b3490673SHuang Rui
navi10_setup_pptable(struct smu_context * smu)4714a13b4ceSEvan Quan static int navi10_setup_pptable(struct smu_context *smu)
4724a13b4ceSEvan Quan {
4734a13b4ceSEvan Quan int ret = 0;
4744a13b4ceSEvan Quan
4754a13b4ceSEvan Quan ret = smu_v11_0_setup_pptable(smu);
4764a13b4ceSEvan Quan if (ret)
4774a13b4ceSEvan Quan return ret;
4784a13b4ceSEvan Quan
4794a13b4ceSEvan Quan ret = navi10_store_powerplay_table(smu);
4804a13b4ceSEvan Quan if (ret)
4814a13b4ceSEvan Quan return ret;
4824a13b4ceSEvan Quan
4834a13b4ceSEvan Quan ret = navi10_append_powerplay_table(smu);
4844a13b4ceSEvan Quan if (ret)
4854a13b4ceSEvan Quan return ret;
4864a13b4ceSEvan Quan
4874a13b4ceSEvan Quan ret = navi10_check_powerplay_table(smu);
4884a13b4ceSEvan Quan if (ret)
4894a13b4ceSEvan Quan return ret;
4904a13b4ceSEvan Quan
4914a13b4ceSEvan Quan return ret;
4924a13b4ceSEvan Quan }
4934a13b4ceSEvan Quan
navi10_tables_init(struct smu_context * smu)494c1b353b7SEvan Quan static int navi10_tables_init(struct smu_context *smu)
49522c9c6caSHuang Rui {
496b94afb61SKevin Wang struct smu_table_context *smu_table = &smu->smu_table;
497c1b353b7SEvan Quan struct smu_table *tables = smu_table->tables;
49818c4e319SLijo Lazar struct smu_table *dummy_read_1_table =
49918c4e319SLijo Lazar &smu_table->dummy_read_1_table;
500b94afb61SKevin Wang
50122c9c6caSHuang Rui SMU_TABLE_INIT(tables, SMU_TABLE_PPTABLE, sizeof(PPTable_t),
50222c9c6caSHuang Rui PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
50322c9c6caSHuang Rui SMU_TABLE_INIT(tables, SMU_TABLE_WATERMARKS, sizeof(Watermarks_t),
50422c9c6caSHuang Rui PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
5057d6c13efSEvan Quan SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetrics_NV1X_t),
50622c9c6caSHuang Rui PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
5071bc73475SAlex Deucher SMU_TABLE_INIT(tables, SMU_TABLE_I2C_COMMANDS, sizeof(SwI2cRequest_t),
5081bc73475SAlex Deucher PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
50922c9c6caSHuang Rui SMU_TABLE_INIT(tables, SMU_TABLE_OVERDRIVE, sizeof(OverDriveTable_t),
51022c9c6caSHuang Rui PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
51122c9c6caSHuang Rui SMU_TABLE_INIT(tables, SMU_TABLE_PMSTATUSLOG, SMU11_TOOL_SIZE,
51222c9c6caSHuang Rui PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
51322c9c6caSHuang Rui SMU_TABLE_INIT(tables, SMU_TABLE_ACTIVITY_MONITOR_COEFF,
51422c9c6caSHuang Rui sizeof(DpmActivityMonitorCoeffInt_t), PAGE_SIZE,
51522c9c6caSHuang Rui AMDGPU_GEM_DOMAIN_VRAM);
516816d61d5SEvan Quan SMU_TABLE_INIT(tables, SMU_TABLE_DRIVER_SMU_CONFIG, sizeof(DriverSmuConfig_t),
517816d61d5SEvan Quan PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
5189634de27SHawking Zhang
51918c4e319SLijo Lazar dummy_read_1_table->size = 0x40000;
52018c4e319SLijo Lazar dummy_read_1_table->align = PAGE_SIZE;
52118c4e319SLijo Lazar dummy_read_1_table->domain = AMDGPU_GEM_DOMAIN_VRAM;
52218c4e319SLijo Lazar
5237d6c13efSEvan Quan smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_NV1X_t),
5247d6c13efSEvan Quan GFP_KERNEL);
525b94afb61SKevin Wang if (!smu_table->metrics_table)
5266d4ff50aSEvan Quan goto err0_out;
527b94afb61SKevin Wang smu_table->metrics_time = 0;
528b94afb61SKevin Wang
52961e2d322SDavid M Nieto smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v1_3);
5306d4ff50aSEvan Quan smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL);
5316d4ff50aSEvan Quan if (!smu_table->gpu_metrics_table)
5326d4ff50aSEvan Quan goto err1_out;
5336d4ff50aSEvan Quan
5349fa1ed5bSEvan Quan smu_table->watermarks_table = kzalloc(sizeof(Watermarks_t), GFP_KERNEL);
5359fa1ed5bSEvan Quan if (!smu_table->watermarks_table)
5366d4ff50aSEvan Quan goto err2_out;
5379fa1ed5bSEvan Quan
538816d61d5SEvan Quan smu_table->driver_smu_config_table =
539816d61d5SEvan Quan kzalloc(tables[SMU_TABLE_DRIVER_SMU_CONFIG].size, GFP_KERNEL);
540816d61d5SEvan Quan if (!smu_table->driver_smu_config_table)
541816d61d5SEvan Quan goto err3_out;
542816d61d5SEvan Quan
5439634de27SHawking Zhang return 0;
5446d4ff50aSEvan Quan
545816d61d5SEvan Quan err3_out:
546816d61d5SEvan Quan kfree(smu_table->watermarks_table);
5476d4ff50aSEvan Quan err2_out:
5486d4ff50aSEvan Quan kfree(smu_table->gpu_metrics_table);
5496d4ff50aSEvan Quan err1_out:
5506d4ff50aSEvan Quan kfree(smu_table->metrics_table);
5516d4ff50aSEvan Quan err0_out:
5526d4ff50aSEvan Quan return -ENOMEM;
55322c9c6caSHuang Rui }
55422c9c6caSHuang Rui
navi10_get_legacy_smu_metrics_data(struct smu_context * smu,MetricsMember_t member,uint32_t * value)5557d6c13efSEvan Quan static int navi10_get_legacy_smu_metrics_data(struct smu_context *smu,
556cf24dd27SEvan Quan MetricsMember_t member,
557cf24dd27SEvan Quan uint32_t *value)
558b94afb61SKevin Wang {
559b94afb61SKevin Wang struct smu_table_context *smu_table = &smu->smu_table;
5607d6c13efSEvan Quan SmuMetrics_legacy_t *metrics =
5617d6c13efSEvan Quan (SmuMetrics_legacy_t *)smu_table->metrics_table;
562b94afb61SKevin Wang int ret = 0;
563b94afb61SKevin Wang
564da11407fSEvan Quan ret = smu_cmn_get_metrics_table(smu,
56562d35163SEvan Quan NULL,
566cf24dd27SEvan Quan false);
567da11407fSEvan Quan if (ret)
568b94afb61SKevin Wang return ret;
569b94afb61SKevin Wang
570cf24dd27SEvan Quan switch (member) {
571cf24dd27SEvan Quan case METRICS_CURR_GFXCLK:
572cf24dd27SEvan Quan *value = metrics->CurrClock[PPCLK_GFXCLK];
573cf24dd27SEvan Quan break;
574cf24dd27SEvan Quan case METRICS_CURR_SOCCLK:
575cf24dd27SEvan Quan *value = metrics->CurrClock[PPCLK_SOCCLK];
576cf24dd27SEvan Quan break;
577cf24dd27SEvan Quan case METRICS_CURR_UCLK:
578cf24dd27SEvan Quan *value = metrics->CurrClock[PPCLK_UCLK];
579cf24dd27SEvan Quan break;
580cf24dd27SEvan Quan case METRICS_CURR_VCLK:
581cf24dd27SEvan Quan *value = metrics->CurrClock[PPCLK_VCLK];
582cf24dd27SEvan Quan break;
583cf24dd27SEvan Quan case METRICS_CURR_DCLK:
584cf24dd27SEvan Quan *value = metrics->CurrClock[PPCLK_DCLK];
585cf24dd27SEvan Quan break;
5869d09fa6fSNirmoy Das case METRICS_CURR_DCEFCLK:
5879d09fa6fSNirmoy Das *value = metrics->CurrClock[PPCLK_DCEFCLK];
5889d09fa6fSNirmoy Das break;
589cf24dd27SEvan Quan case METRICS_AVERAGE_GFXCLK:
590cf24dd27SEvan Quan *value = metrics->AverageGfxclkFrequency;
591cf24dd27SEvan Quan break;
592cf24dd27SEvan Quan case METRICS_AVERAGE_SOCCLK:
593cf24dd27SEvan Quan *value = metrics->AverageSocclkFrequency;
594cf24dd27SEvan Quan break;
595cf24dd27SEvan Quan case METRICS_AVERAGE_UCLK:
596cf24dd27SEvan Quan *value = metrics->AverageUclkFrequency;
597cf24dd27SEvan Quan break;
598cf24dd27SEvan Quan case METRICS_AVERAGE_GFXACTIVITY:
599cf24dd27SEvan Quan *value = metrics->AverageGfxActivity;
600cf24dd27SEvan Quan break;
601cf24dd27SEvan Quan case METRICS_AVERAGE_MEMACTIVITY:
602cf24dd27SEvan Quan *value = metrics->AverageUclkActivity;
603cf24dd27SEvan Quan break;
604cf24dd27SEvan Quan case METRICS_AVERAGE_SOCKETPOWER:
605cf24dd27SEvan Quan *value = metrics->AverageSocketPower << 8;
606cf24dd27SEvan Quan break;
607cf24dd27SEvan Quan case METRICS_TEMPERATURE_EDGE:
608cf24dd27SEvan Quan *value = metrics->TemperatureEdge *
609cf24dd27SEvan Quan SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
610cf24dd27SEvan Quan break;
611cf24dd27SEvan Quan case METRICS_TEMPERATURE_HOTSPOT:
612cf24dd27SEvan Quan *value = metrics->TemperatureHotspot *
613cf24dd27SEvan Quan SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
614cf24dd27SEvan Quan break;
615cf24dd27SEvan Quan case METRICS_TEMPERATURE_MEM:
616cf24dd27SEvan Quan *value = metrics->TemperatureMem *
617cf24dd27SEvan Quan SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
618cf24dd27SEvan Quan break;
619cf24dd27SEvan Quan case METRICS_TEMPERATURE_VRGFX:
620cf24dd27SEvan Quan *value = metrics->TemperatureVrGfx *
621cf24dd27SEvan Quan SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
622cf24dd27SEvan Quan break;
623cf24dd27SEvan Quan case METRICS_TEMPERATURE_VRSOC:
624cf24dd27SEvan Quan *value = metrics->TemperatureVrSoc *
625cf24dd27SEvan Quan SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
626cf24dd27SEvan Quan break;
627cf24dd27SEvan Quan case METRICS_THROTTLER_STATUS:
628cf24dd27SEvan Quan *value = metrics->ThrottlerStatus;
629cf24dd27SEvan Quan break;
630cf24dd27SEvan Quan case METRICS_CURR_FANSPEED:
631cf24dd27SEvan Quan *value = metrics->CurrFanSpeed;
632cf24dd27SEvan Quan break;
633cf24dd27SEvan Quan default:
634cf24dd27SEvan Quan *value = UINT_MAX;
635cf24dd27SEvan Quan break;
636cf24dd27SEvan Quan }
637cf24dd27SEvan Quan
638b94afb61SKevin Wang return ret;
639b94afb61SKevin Wang }
640b94afb61SKevin Wang
navi10_get_smu_metrics_data(struct smu_context * smu,MetricsMember_t member,uint32_t * value)6417d6c13efSEvan Quan static int navi10_get_smu_metrics_data(struct smu_context *smu,
6427d6c13efSEvan Quan MetricsMember_t member,
6437d6c13efSEvan Quan uint32_t *value)
6447d6c13efSEvan Quan {
6457d6c13efSEvan Quan struct smu_table_context *smu_table = &smu->smu_table;
6467d6c13efSEvan Quan SmuMetrics_t *metrics =
6477d6c13efSEvan Quan (SmuMetrics_t *)smu_table->metrics_table;
6487d6c13efSEvan Quan int ret = 0;
6497d6c13efSEvan Quan
650da11407fSEvan Quan ret = smu_cmn_get_metrics_table(smu,
6517d6c13efSEvan Quan NULL,
6527d6c13efSEvan Quan false);
653da11407fSEvan Quan if (ret)
6547d6c13efSEvan Quan return ret;
6557d6c13efSEvan Quan
6567d6c13efSEvan Quan switch (member) {
6577d6c13efSEvan Quan case METRICS_CURR_GFXCLK:
6587d6c13efSEvan Quan *value = metrics->CurrClock[PPCLK_GFXCLK];
6597d6c13efSEvan Quan break;
6607d6c13efSEvan Quan case METRICS_CURR_SOCCLK:
6617d6c13efSEvan Quan *value = metrics->CurrClock[PPCLK_SOCCLK];
6627d6c13efSEvan Quan break;
6637d6c13efSEvan Quan case METRICS_CURR_UCLK:
6647d6c13efSEvan Quan *value = metrics->CurrClock[PPCLK_UCLK];
6657d6c13efSEvan Quan break;
6667d6c13efSEvan Quan case METRICS_CURR_VCLK:
6677d6c13efSEvan Quan *value = metrics->CurrClock[PPCLK_VCLK];
6687d6c13efSEvan Quan break;
6697d6c13efSEvan Quan case METRICS_CURR_DCLK:
6707d6c13efSEvan Quan *value = metrics->CurrClock[PPCLK_DCLK];
6717d6c13efSEvan Quan break;
6727d6c13efSEvan Quan case METRICS_CURR_DCEFCLK:
6737d6c13efSEvan Quan *value = metrics->CurrClock[PPCLK_DCEFCLK];
6747d6c13efSEvan Quan break;
6757d6c13efSEvan Quan case METRICS_AVERAGE_GFXCLK:
6767d6c13efSEvan Quan if (metrics->AverageGfxActivity > SMU_11_0_GFX_BUSY_THRESHOLD)
6777d6c13efSEvan Quan *value = metrics->AverageGfxclkFrequencyPreDs;
6787d6c13efSEvan Quan else
6797d6c13efSEvan Quan *value = metrics->AverageGfxclkFrequencyPostDs;
6807d6c13efSEvan Quan break;
6817d6c13efSEvan Quan case METRICS_AVERAGE_SOCCLK:
6827d6c13efSEvan Quan *value = metrics->AverageSocclkFrequency;
6837d6c13efSEvan Quan break;
6847d6c13efSEvan Quan case METRICS_AVERAGE_UCLK:
6857d6c13efSEvan Quan *value = metrics->AverageUclkFrequencyPostDs;
6867d6c13efSEvan Quan break;
6877d6c13efSEvan Quan case METRICS_AVERAGE_GFXACTIVITY:
6887d6c13efSEvan Quan *value = metrics->AverageGfxActivity;
6897d6c13efSEvan Quan break;
6907d6c13efSEvan Quan case METRICS_AVERAGE_MEMACTIVITY:
6917d6c13efSEvan Quan *value = metrics->AverageUclkActivity;
6927d6c13efSEvan Quan break;
6937d6c13efSEvan Quan case METRICS_AVERAGE_SOCKETPOWER:
6947d6c13efSEvan Quan *value = metrics->AverageSocketPower << 8;
6957d6c13efSEvan Quan break;
6967d6c13efSEvan Quan case METRICS_TEMPERATURE_EDGE:
6977d6c13efSEvan Quan *value = metrics->TemperatureEdge *
6987d6c13efSEvan Quan SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
6997d6c13efSEvan Quan break;
7007d6c13efSEvan Quan case METRICS_TEMPERATURE_HOTSPOT:
7017d6c13efSEvan Quan *value = metrics->TemperatureHotspot *
7027d6c13efSEvan Quan SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
7037d6c13efSEvan Quan break;
7047d6c13efSEvan Quan case METRICS_TEMPERATURE_MEM:
7057d6c13efSEvan Quan *value = metrics->TemperatureMem *
7067d6c13efSEvan Quan SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
7077d6c13efSEvan Quan break;
7087d6c13efSEvan Quan case METRICS_TEMPERATURE_VRGFX:
7097d6c13efSEvan Quan *value = metrics->TemperatureVrGfx *
7107d6c13efSEvan Quan SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
7117d6c13efSEvan Quan break;
7127d6c13efSEvan Quan case METRICS_TEMPERATURE_VRSOC:
7137d6c13efSEvan Quan *value = metrics->TemperatureVrSoc *
7147d6c13efSEvan Quan SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
7157d6c13efSEvan Quan break;
7167d6c13efSEvan Quan case METRICS_THROTTLER_STATUS:
7177d6c13efSEvan Quan *value = metrics->ThrottlerStatus;
7187d6c13efSEvan Quan break;
7197d6c13efSEvan Quan case METRICS_CURR_FANSPEED:
7207d6c13efSEvan Quan *value = metrics->CurrFanSpeed;
7217d6c13efSEvan Quan break;
7227d6c13efSEvan Quan default:
7237d6c13efSEvan Quan *value = UINT_MAX;
7247d6c13efSEvan Quan break;
7257d6c13efSEvan Quan }
7267d6c13efSEvan Quan
7277d6c13efSEvan Quan return ret;
7287d6c13efSEvan Quan }
7297d6c13efSEvan Quan
navi12_get_legacy_smu_metrics_data(struct smu_context * smu,MetricsMember_t member,uint32_t * value)7307d6c13efSEvan Quan static int navi12_get_legacy_smu_metrics_data(struct smu_context *smu,
7317d6c13efSEvan Quan MetricsMember_t member,
7327d6c13efSEvan Quan uint32_t *value)
7337d6c13efSEvan Quan {
7347d6c13efSEvan Quan struct smu_table_context *smu_table = &smu->smu_table;
7357d6c13efSEvan Quan SmuMetrics_NV12_legacy_t *metrics =
7367d6c13efSEvan Quan (SmuMetrics_NV12_legacy_t *)smu_table->metrics_table;
7377d6c13efSEvan Quan int ret = 0;
7387d6c13efSEvan Quan
739da11407fSEvan Quan ret = smu_cmn_get_metrics_table(smu,
7407d6c13efSEvan Quan NULL,
7417d6c13efSEvan Quan false);
742da11407fSEvan Quan if (ret)
7437d6c13efSEvan Quan return ret;
7447d6c13efSEvan Quan
7457d6c13efSEvan Quan switch (member) {
7467d6c13efSEvan Quan case METRICS_CURR_GFXCLK:
7477d6c13efSEvan Quan *value = metrics->CurrClock[PPCLK_GFXCLK];
7487d6c13efSEvan Quan break;
7497d6c13efSEvan Quan case METRICS_CURR_SOCCLK:
7507d6c13efSEvan Quan *value = metrics->CurrClock[PPCLK_SOCCLK];
7517d6c13efSEvan Quan break;
7527d6c13efSEvan Quan case METRICS_CURR_UCLK:
7537d6c13efSEvan Quan *value = metrics->CurrClock[PPCLK_UCLK];
7547d6c13efSEvan Quan break;
7557d6c13efSEvan Quan case METRICS_CURR_VCLK:
7567d6c13efSEvan Quan *value = metrics->CurrClock[PPCLK_VCLK];
7577d6c13efSEvan Quan break;
7587d6c13efSEvan Quan case METRICS_CURR_DCLK:
7597d6c13efSEvan Quan *value = metrics->CurrClock[PPCLK_DCLK];
7607d6c13efSEvan Quan break;
7617d6c13efSEvan Quan case METRICS_CURR_DCEFCLK:
7627d6c13efSEvan Quan *value = metrics->CurrClock[PPCLK_DCEFCLK];
7637d6c13efSEvan Quan break;
7647d6c13efSEvan Quan case METRICS_AVERAGE_GFXCLK:
7657d6c13efSEvan Quan *value = metrics->AverageGfxclkFrequency;
7667d6c13efSEvan Quan break;
7677d6c13efSEvan Quan case METRICS_AVERAGE_SOCCLK:
7687d6c13efSEvan Quan *value = metrics->AverageSocclkFrequency;
7697d6c13efSEvan Quan break;
7707d6c13efSEvan Quan case METRICS_AVERAGE_UCLK:
7717d6c13efSEvan Quan *value = metrics->AverageUclkFrequency;
7727d6c13efSEvan Quan break;
7737d6c13efSEvan Quan case METRICS_AVERAGE_GFXACTIVITY:
7747d6c13efSEvan Quan *value = metrics->AverageGfxActivity;
7757d6c13efSEvan Quan break;
7767d6c13efSEvan Quan case METRICS_AVERAGE_MEMACTIVITY:
7777d6c13efSEvan Quan *value = metrics->AverageUclkActivity;
7787d6c13efSEvan Quan break;
7797d6c13efSEvan Quan case METRICS_AVERAGE_SOCKETPOWER:
7807d6c13efSEvan Quan *value = metrics->AverageSocketPower << 8;
7817d6c13efSEvan Quan break;
7827d6c13efSEvan Quan case METRICS_TEMPERATURE_EDGE:
7837d6c13efSEvan Quan *value = metrics->TemperatureEdge *
7847d6c13efSEvan Quan SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
7857d6c13efSEvan Quan break;
7867d6c13efSEvan Quan case METRICS_TEMPERATURE_HOTSPOT:
7877d6c13efSEvan Quan *value = metrics->TemperatureHotspot *
7887d6c13efSEvan Quan SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
7897d6c13efSEvan Quan break;
7907d6c13efSEvan Quan case METRICS_TEMPERATURE_MEM:
7917d6c13efSEvan Quan *value = metrics->TemperatureMem *
7927d6c13efSEvan Quan SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
7937d6c13efSEvan Quan break;
7947d6c13efSEvan Quan case METRICS_TEMPERATURE_VRGFX:
7957d6c13efSEvan Quan *value = metrics->TemperatureVrGfx *
7967d6c13efSEvan Quan SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
7977d6c13efSEvan Quan break;
7987d6c13efSEvan Quan case METRICS_TEMPERATURE_VRSOC:
7997d6c13efSEvan Quan *value = metrics->TemperatureVrSoc *
8007d6c13efSEvan Quan SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
8017d6c13efSEvan Quan break;
8027d6c13efSEvan Quan case METRICS_THROTTLER_STATUS:
8037d6c13efSEvan Quan *value = metrics->ThrottlerStatus;
8047d6c13efSEvan Quan break;
8057d6c13efSEvan Quan case METRICS_CURR_FANSPEED:
8067d6c13efSEvan Quan *value = metrics->CurrFanSpeed;
8077d6c13efSEvan Quan break;
8087d6c13efSEvan Quan default:
8097d6c13efSEvan Quan *value = UINT_MAX;
8107d6c13efSEvan Quan break;
8117d6c13efSEvan Quan }
8127d6c13efSEvan Quan
8137d6c13efSEvan Quan return ret;
8147d6c13efSEvan Quan }
8157d6c13efSEvan Quan
navi12_get_smu_metrics_data(struct smu_context * smu,MetricsMember_t member,uint32_t * value)8167d6c13efSEvan Quan static int navi12_get_smu_metrics_data(struct smu_context *smu,
8177d6c13efSEvan Quan MetricsMember_t member,
8187d6c13efSEvan Quan uint32_t *value)
8197d6c13efSEvan Quan {
8207d6c13efSEvan Quan struct smu_table_context *smu_table = &smu->smu_table;
8217d6c13efSEvan Quan SmuMetrics_NV12_t *metrics =
8227d6c13efSEvan Quan (SmuMetrics_NV12_t *)smu_table->metrics_table;
8237d6c13efSEvan Quan int ret = 0;
8247d6c13efSEvan Quan
825da11407fSEvan Quan ret = smu_cmn_get_metrics_table(smu,
8267d6c13efSEvan Quan NULL,
8277d6c13efSEvan Quan false);
828da11407fSEvan Quan if (ret)
8297d6c13efSEvan Quan return ret;
8307d6c13efSEvan Quan
8317d6c13efSEvan Quan switch (member) {
8327d6c13efSEvan Quan case METRICS_CURR_GFXCLK:
8337d6c13efSEvan Quan *value = metrics->CurrClock[PPCLK_GFXCLK];
8347d6c13efSEvan Quan break;
8357d6c13efSEvan Quan case METRICS_CURR_SOCCLK:
8367d6c13efSEvan Quan *value = metrics->CurrClock[PPCLK_SOCCLK];
8377d6c13efSEvan Quan break;
8387d6c13efSEvan Quan case METRICS_CURR_UCLK:
8397d6c13efSEvan Quan *value = metrics->CurrClock[PPCLK_UCLK];
8407d6c13efSEvan Quan break;
8417d6c13efSEvan Quan case METRICS_CURR_VCLK:
8427d6c13efSEvan Quan *value = metrics->CurrClock[PPCLK_VCLK];
8437d6c13efSEvan Quan break;
8447d6c13efSEvan Quan case METRICS_CURR_DCLK:
8457d6c13efSEvan Quan *value = metrics->CurrClock[PPCLK_DCLK];
8467d6c13efSEvan Quan break;
8477d6c13efSEvan Quan case METRICS_CURR_DCEFCLK:
8487d6c13efSEvan Quan *value = metrics->CurrClock[PPCLK_DCEFCLK];
8497d6c13efSEvan Quan break;
8507d6c13efSEvan Quan case METRICS_AVERAGE_GFXCLK:
8517d6c13efSEvan Quan if (metrics->AverageGfxActivity > SMU_11_0_GFX_BUSY_THRESHOLD)
8527d6c13efSEvan Quan *value = metrics->AverageGfxclkFrequencyPreDs;
8537d6c13efSEvan Quan else
8547d6c13efSEvan Quan *value = metrics->AverageGfxclkFrequencyPostDs;
8557d6c13efSEvan Quan break;
8567d6c13efSEvan Quan case METRICS_AVERAGE_SOCCLK:
8577d6c13efSEvan Quan *value = metrics->AverageSocclkFrequency;
8587d6c13efSEvan Quan break;
8597d6c13efSEvan Quan case METRICS_AVERAGE_UCLK:
8607d6c13efSEvan Quan *value = metrics->AverageUclkFrequencyPostDs;
8617d6c13efSEvan Quan break;
8627d6c13efSEvan Quan case METRICS_AVERAGE_GFXACTIVITY:
8637d6c13efSEvan Quan *value = metrics->AverageGfxActivity;
8647d6c13efSEvan Quan break;
8657d6c13efSEvan Quan case METRICS_AVERAGE_MEMACTIVITY:
8667d6c13efSEvan Quan *value = metrics->AverageUclkActivity;
8677d6c13efSEvan Quan break;
8687d6c13efSEvan Quan case METRICS_AVERAGE_SOCKETPOWER:
8697d6c13efSEvan Quan *value = metrics->AverageSocketPower << 8;
8707d6c13efSEvan Quan break;
8717d6c13efSEvan Quan case METRICS_TEMPERATURE_EDGE:
8727d6c13efSEvan Quan *value = metrics->TemperatureEdge *
8737d6c13efSEvan Quan SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
8747d6c13efSEvan Quan break;
8757d6c13efSEvan Quan case METRICS_TEMPERATURE_HOTSPOT:
8767d6c13efSEvan Quan *value = metrics->TemperatureHotspot *
8777d6c13efSEvan Quan SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
8787d6c13efSEvan Quan break;
8797d6c13efSEvan Quan case METRICS_TEMPERATURE_MEM:
8807d6c13efSEvan Quan *value = metrics->TemperatureMem *
8817d6c13efSEvan Quan SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
8827d6c13efSEvan Quan break;
8837d6c13efSEvan Quan case METRICS_TEMPERATURE_VRGFX:
8847d6c13efSEvan Quan *value = metrics->TemperatureVrGfx *
8857d6c13efSEvan Quan SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
8867d6c13efSEvan Quan break;
8877d6c13efSEvan Quan case METRICS_TEMPERATURE_VRSOC:
8887d6c13efSEvan Quan *value = metrics->TemperatureVrSoc *
8897d6c13efSEvan Quan SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
8907d6c13efSEvan Quan break;
8917d6c13efSEvan Quan case METRICS_THROTTLER_STATUS:
8927d6c13efSEvan Quan *value = metrics->ThrottlerStatus;
8937d6c13efSEvan Quan break;
8947d6c13efSEvan Quan case METRICS_CURR_FANSPEED:
8957d6c13efSEvan Quan *value = metrics->CurrFanSpeed;
8967d6c13efSEvan Quan break;
8977d6c13efSEvan Quan default:
8987d6c13efSEvan Quan *value = UINT_MAX;
8997d6c13efSEvan Quan break;
9007d6c13efSEvan Quan }
9017d6c13efSEvan Quan
9027d6c13efSEvan Quan return ret;
9037d6c13efSEvan Quan }
9047d6c13efSEvan Quan
navi1x_get_smu_metrics_data(struct smu_context * smu,MetricsMember_t member,uint32_t * value)9057d6c13efSEvan Quan static int navi1x_get_smu_metrics_data(struct smu_context *smu,
9067d6c13efSEvan Quan MetricsMember_t member,
9077d6c13efSEvan Quan uint32_t *value)
9087d6c13efSEvan Quan {
9097d6c13efSEvan Quan struct amdgpu_device *adev = smu->adev;
9107d6c13efSEvan Quan int ret = 0;
9117d6c13efSEvan Quan
9124e8303cfSLijo Lazar switch (amdgpu_ip_version(adev, MP1_HWIP, 0)) {
913ea0d730aSAlex Deucher case IP_VERSION(11, 0, 9):
914710d9caeSYifan Zhang if (smu->smc_fw_version > 0x00341C00)
9157d6c13efSEvan Quan ret = navi12_get_smu_metrics_data(smu, member, value);
9167d6c13efSEvan Quan else
9177d6c13efSEvan Quan ret = navi12_get_legacy_smu_metrics_data(smu, member, value);
9187d6c13efSEvan Quan break;
919ea0d730aSAlex Deucher case IP_VERSION(11, 0, 0):
920ea0d730aSAlex Deucher case IP_VERSION(11, 0, 5):
9217d6c13efSEvan Quan default:
9224e8303cfSLijo Lazar if (((amdgpu_ip_version(adev, MP1_HWIP, 0) ==
9234e8303cfSLijo Lazar IP_VERSION(11, 0, 5)) &&
924710d9caeSYifan Zhang smu->smc_fw_version > 0x00351F00) ||
9254e8303cfSLijo Lazar ((amdgpu_ip_version(adev, MP1_HWIP, 0) ==
9264e8303cfSLijo Lazar IP_VERSION(11, 0, 0)) &&
927710d9caeSYifan Zhang smu->smc_fw_version > 0x002A3B00))
9287d6c13efSEvan Quan ret = navi10_get_smu_metrics_data(smu, member, value);
9297d6c13efSEvan Quan else
9307d6c13efSEvan Quan ret = navi10_get_legacy_smu_metrics_data(smu, member, value);
9317d6c13efSEvan Quan break;
9327d6c13efSEvan Quan }
9337d6c13efSEvan Quan
9347d6c13efSEvan Quan return ret;
9357d6c13efSEvan Quan }
9367d6c13efSEvan Quan
navi10_allocate_dpm_context(struct smu_context * smu)937b3490673SHuang Rui static int navi10_allocate_dpm_context(struct smu_context *smu)
938b3490673SHuang Rui {
939b3490673SHuang Rui struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
940b3490673SHuang Rui
941b3490673SHuang Rui smu_dpm->dpm_context = kzalloc(sizeof(struct smu_11_0_dpm_context),
942b3490673SHuang Rui GFP_KERNEL);
943b3490673SHuang Rui if (!smu_dpm->dpm_context)
944b3490673SHuang Rui return -ENOMEM;
945b3490673SHuang Rui
946b3490673SHuang Rui smu_dpm->dpm_context_size = sizeof(struct smu_11_0_dpm_context);
947b3490673SHuang Rui
948b3490673SHuang Rui return 0;
949b3490673SHuang Rui }
950b3490673SHuang Rui
navi10_init_smc_tables(struct smu_context * smu)951c1b353b7SEvan Quan static int navi10_init_smc_tables(struct smu_context *smu)
952c1b353b7SEvan Quan {
953c1b353b7SEvan Quan int ret = 0;
954c1b353b7SEvan Quan
955c1b353b7SEvan Quan ret = navi10_tables_init(smu);
956c1b353b7SEvan Quan if (ret)
957c1b353b7SEvan Quan return ret;
958c1b353b7SEvan Quan
959c1b353b7SEvan Quan ret = navi10_allocate_dpm_context(smu);
960c1b353b7SEvan Quan if (ret)
961c1b353b7SEvan Quan return ret;
962c1b353b7SEvan Quan
963c1b353b7SEvan Quan return smu_v11_0_init_smc_tables(smu);
964c1b353b7SEvan Quan }
965c1b353b7SEvan Quan
navi10_set_default_dpm_table(struct smu_context * smu)966b3490673SHuang Rui static int navi10_set_default_dpm_table(struct smu_context *smu)
967b3490673SHuang Rui {
9683afb244bSEvan Quan struct smu_11_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context;
9693afb244bSEvan Quan PPTable_t *driver_ppt = smu->smu_table.driver_pptable;
9703afb244bSEvan Quan struct smu_11_0_dpm_table *dpm_table;
9713afb244bSEvan Quan int ret = 0;
972b3490673SHuang Rui
9733afb244bSEvan Quan /* socclk dpm table setup */
9743afb244bSEvan Quan dpm_table = &dpm_context->dpm_tables.soc_table;
975b4bb3aafSEvan Quan if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) {
9763afb244bSEvan Quan ret = smu_v11_0_set_single_dpm_table(smu,
9773afb244bSEvan Quan SMU_SOCCLK,
9783afb244bSEvan Quan dpm_table);
9793afb244bSEvan Quan if (ret)
9803afb244bSEvan Quan return ret;
9813afb244bSEvan Quan dpm_table->is_fine_grained =
9823afb244bSEvan Quan !driver_ppt->DpmDescriptor[PPCLK_SOCCLK].SnapToDiscrete;
9833afb244bSEvan Quan } else {
9843afb244bSEvan Quan dpm_table->count = 1;
9853afb244bSEvan Quan dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.socclk / 100;
9863afb244bSEvan Quan dpm_table->dpm_levels[0].enabled = true;
9873afb244bSEvan Quan dpm_table->min = dpm_table->dpm_levels[0].value;
9883afb244bSEvan Quan dpm_table->max = dpm_table->dpm_levels[0].value;
9893afb244bSEvan Quan }
990b3490673SHuang Rui
9913afb244bSEvan Quan /* gfxclk dpm table setup */
9923afb244bSEvan Quan dpm_table = &dpm_context->dpm_tables.gfx_table;
993b4bb3aafSEvan Quan if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT)) {
9943afb244bSEvan Quan ret = smu_v11_0_set_single_dpm_table(smu,
9953afb244bSEvan Quan SMU_GFXCLK,
9963afb244bSEvan Quan dpm_table);
9973afb244bSEvan Quan if (ret)
9983afb244bSEvan Quan return ret;
9993afb244bSEvan Quan dpm_table->is_fine_grained =
10003afb244bSEvan Quan !driver_ppt->DpmDescriptor[PPCLK_GFXCLK].SnapToDiscrete;
10013afb244bSEvan Quan } else {
10023afb244bSEvan Quan dpm_table->count = 1;
10033afb244bSEvan Quan dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.gfxclk / 100;
10043afb244bSEvan Quan dpm_table->dpm_levels[0].enabled = true;
10053afb244bSEvan Quan dpm_table->min = dpm_table->dpm_levels[0].value;
10063afb244bSEvan Quan dpm_table->max = dpm_table->dpm_levels[0].value;
10073afb244bSEvan Quan }
1008b3490673SHuang Rui
10093afb244bSEvan Quan /* uclk dpm table setup */
10103afb244bSEvan Quan dpm_table = &dpm_context->dpm_tables.uclk_table;
1011b4bb3aafSEvan Quan if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) {
10123afb244bSEvan Quan ret = smu_v11_0_set_single_dpm_table(smu,
10133afb244bSEvan Quan SMU_UCLK,
10143afb244bSEvan Quan dpm_table);
10153afb244bSEvan Quan if (ret)
10163afb244bSEvan Quan return ret;
10173afb244bSEvan Quan dpm_table->is_fine_grained =
10183afb244bSEvan Quan !driver_ppt->DpmDescriptor[PPCLK_UCLK].SnapToDiscrete;
10193afb244bSEvan Quan } else {
10203afb244bSEvan Quan dpm_table->count = 1;
10213afb244bSEvan Quan dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.uclk / 100;
10223afb244bSEvan Quan dpm_table->dpm_levels[0].enabled = true;
10233afb244bSEvan Quan dpm_table->min = dpm_table->dpm_levels[0].value;
10243afb244bSEvan Quan dpm_table->max = dpm_table->dpm_levels[0].value;
10253afb244bSEvan Quan }
1026b3490673SHuang Rui
10273afb244bSEvan Quan /* vclk dpm table setup */
10283afb244bSEvan Quan dpm_table = &dpm_context->dpm_tables.vclk_table;
1029b4bb3aafSEvan Quan if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) {
10303afb244bSEvan Quan ret = smu_v11_0_set_single_dpm_table(smu,
10313afb244bSEvan Quan SMU_VCLK,
10323afb244bSEvan Quan dpm_table);
10333afb244bSEvan Quan if (ret)
10343afb244bSEvan Quan return ret;
10353afb244bSEvan Quan dpm_table->is_fine_grained =
10363afb244bSEvan Quan !driver_ppt->DpmDescriptor[PPCLK_VCLK].SnapToDiscrete;
10373afb244bSEvan Quan } else {
10383afb244bSEvan Quan dpm_table->count = 1;
10393afb244bSEvan Quan dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.vclk / 100;
10403afb244bSEvan Quan dpm_table->dpm_levels[0].enabled = true;
10413afb244bSEvan Quan dpm_table->min = dpm_table->dpm_levels[0].value;
10423afb244bSEvan Quan dpm_table->max = dpm_table->dpm_levels[0].value;
10433afb244bSEvan Quan }
1044b3490673SHuang Rui
10453afb244bSEvan Quan /* dclk dpm table setup */
10463afb244bSEvan Quan dpm_table = &dpm_context->dpm_tables.dclk_table;
1047b4bb3aafSEvan Quan if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) {
10483afb244bSEvan Quan ret = smu_v11_0_set_single_dpm_table(smu,
10493afb244bSEvan Quan SMU_DCLK,
10503afb244bSEvan Quan dpm_table);
10513afb244bSEvan Quan if (ret)
10523afb244bSEvan Quan return ret;
10533afb244bSEvan Quan dpm_table->is_fine_grained =
10543afb244bSEvan Quan !driver_ppt->DpmDescriptor[PPCLK_DCLK].SnapToDiscrete;
10553afb244bSEvan Quan } else {
10563afb244bSEvan Quan dpm_table->count = 1;
10573afb244bSEvan Quan dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dclk / 100;
10583afb244bSEvan Quan dpm_table->dpm_levels[0].enabled = true;
10593afb244bSEvan Quan dpm_table->min = dpm_table->dpm_levels[0].value;
10603afb244bSEvan Quan dpm_table->max = dpm_table->dpm_levels[0].value;
10613afb244bSEvan Quan }
1062b3490673SHuang Rui
10633afb244bSEvan Quan /* dcefclk dpm table setup */
10643afb244bSEvan Quan dpm_table = &dpm_context->dpm_tables.dcef_table;
1065b4bb3aafSEvan Quan if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) {
10663afb244bSEvan Quan ret = smu_v11_0_set_single_dpm_table(smu,
10673afb244bSEvan Quan SMU_DCEFCLK,
10683afb244bSEvan Quan dpm_table);
10693afb244bSEvan Quan if (ret)
10703afb244bSEvan Quan return ret;
10713afb244bSEvan Quan dpm_table->is_fine_grained =
10723afb244bSEvan Quan !driver_ppt->DpmDescriptor[PPCLK_DCEFCLK].SnapToDiscrete;
10733afb244bSEvan Quan } else {
10743afb244bSEvan Quan dpm_table->count = 1;
10753afb244bSEvan Quan dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dcefclk / 100;
10763afb244bSEvan Quan dpm_table->dpm_levels[0].enabled = true;
10773afb244bSEvan Quan dpm_table->min = dpm_table->dpm_levels[0].value;
10783afb244bSEvan Quan dpm_table->max = dpm_table->dpm_levels[0].value;
10793afb244bSEvan Quan }
1080b3490673SHuang Rui
10813afb244bSEvan Quan /* pixelclk dpm table setup */
10823afb244bSEvan Quan dpm_table = &dpm_context->dpm_tables.pixel_table;
1083b4bb3aafSEvan Quan if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) {
10843afb244bSEvan Quan ret = smu_v11_0_set_single_dpm_table(smu,
10853afb244bSEvan Quan SMU_PIXCLK,
10863afb244bSEvan Quan dpm_table);
10873afb244bSEvan Quan if (ret)
10883afb244bSEvan Quan return ret;
10893afb244bSEvan Quan dpm_table->is_fine_grained =
10903afb244bSEvan Quan !driver_ppt->DpmDescriptor[PPCLK_PIXCLK].SnapToDiscrete;
10913afb244bSEvan Quan } else {
10923afb244bSEvan Quan dpm_table->count = 1;
10933afb244bSEvan Quan dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dcefclk / 100;
10943afb244bSEvan Quan dpm_table->dpm_levels[0].enabled = true;
10953afb244bSEvan Quan dpm_table->min = dpm_table->dpm_levels[0].value;
10963afb244bSEvan Quan dpm_table->max = dpm_table->dpm_levels[0].value;
10973afb244bSEvan Quan }
1098b3490673SHuang Rui
10993afb244bSEvan Quan /* displayclk dpm table setup */
11003afb244bSEvan Quan dpm_table = &dpm_context->dpm_tables.display_table;
1101b4bb3aafSEvan Quan if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) {
11023afb244bSEvan Quan ret = smu_v11_0_set_single_dpm_table(smu,
11033afb244bSEvan Quan SMU_DISPCLK,
11043afb244bSEvan Quan dpm_table);
11053afb244bSEvan Quan if (ret)
11063afb244bSEvan Quan return ret;
11073afb244bSEvan Quan dpm_table->is_fine_grained =
11083afb244bSEvan Quan !driver_ppt->DpmDescriptor[PPCLK_DISPCLK].SnapToDiscrete;
11093afb244bSEvan Quan } else {
11103afb244bSEvan Quan dpm_table->count = 1;
11113afb244bSEvan Quan dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dcefclk / 100;
11123afb244bSEvan Quan dpm_table->dpm_levels[0].enabled = true;
11133afb244bSEvan Quan dpm_table->min = dpm_table->dpm_levels[0].value;
11143afb244bSEvan Quan dpm_table->max = dpm_table->dpm_levels[0].value;
11153afb244bSEvan Quan }
1116b3490673SHuang Rui
11173afb244bSEvan Quan /* phyclk dpm table setup */
11183afb244bSEvan Quan dpm_table = &dpm_context->dpm_tables.phy_table;
1119b4bb3aafSEvan Quan if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) {
11203afb244bSEvan Quan ret = smu_v11_0_set_single_dpm_table(smu,
11213afb244bSEvan Quan SMU_PHYCLK,
11223afb244bSEvan Quan dpm_table);
11233afb244bSEvan Quan if (ret)
11243afb244bSEvan Quan return ret;
11253afb244bSEvan Quan dpm_table->is_fine_grained =
11263afb244bSEvan Quan !driver_ppt->DpmDescriptor[PPCLK_PHYCLK].SnapToDiscrete;
11273afb244bSEvan Quan } else {
11283afb244bSEvan Quan dpm_table->count = 1;
11293afb244bSEvan Quan dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dcefclk / 100;
11303afb244bSEvan Quan dpm_table->dpm_levels[0].enabled = true;
11313afb244bSEvan Quan dpm_table->min = dpm_table->dpm_levels[0].value;
11323afb244bSEvan Quan dpm_table->max = dpm_table->dpm_levels[0].value;
11333afb244bSEvan Quan }
1134b3490673SHuang Rui
1135b3490673SHuang Rui return 0;
1136b3490673SHuang Rui }
1137b3490673SHuang Rui
navi10_dpm_set_vcn_enable(struct smu_context * smu,bool enable,int inst)11388b7f3529SBoyuan Zhang static int navi10_dpm_set_vcn_enable(struct smu_context *smu,
11398b7f3529SBoyuan Zhang bool enable,
11408b7f3529SBoyuan Zhang int inst)
1141a8179d62SKenneth Feng {
1142a8179d62SKenneth Feng int ret = 0;
1143a8179d62SKenneth Feng
11445fa790f6SEvan Quan if (enable) {
1145706e5082SEvan Quan /* vcn dpm on is a prerequisite for vcn power gate messages */
1146b4bb3aafSEvan Quan if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) {
114766c86828SEvan Quan ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerUpVcn, 1, NULL);
1148a8179d62SKenneth Feng if (ret)
1149a8179d62SKenneth Feng return ret;
1150706e5082SEvan Quan }
1151a8179d62SKenneth Feng } else {
1152b4bb3aafSEvan Quan if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) {
115366c86828SEvan Quan ret = smu_cmn_send_smc_msg(smu, SMU_MSG_PowerDownVcn, NULL);
1154a8179d62SKenneth Feng if (ret)
1155a8179d62SKenneth Feng return ret;
1156b2136465SEvan Quan }
1157706e5082SEvan Quan }
11585fa790f6SEvan Quan
11595fa790f6SEvan Quan return ret;
1160a8179d62SKenneth Feng }
1161a8179d62SKenneth Feng
navi10_dpm_set_jpeg_enable(struct smu_context * smu,bool enable)116243717ff6SLeo Liu static int navi10_dpm_set_jpeg_enable(struct smu_context *smu, bool enable)
116343717ff6SLeo Liu {
116443717ff6SLeo Liu int ret = 0;
116543717ff6SLeo Liu
116643717ff6SLeo Liu if (enable) {
1167b4bb3aafSEvan Quan if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_JPEG_PG_BIT)) {
116866c86828SEvan Quan ret = smu_cmn_send_smc_msg(smu, SMU_MSG_PowerUpJpeg, NULL);
116943717ff6SLeo Liu if (ret)
117043717ff6SLeo Liu return ret;
117143717ff6SLeo Liu }
117243717ff6SLeo Liu } else {
1173b4bb3aafSEvan Quan if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_JPEG_PG_BIT)) {
117466c86828SEvan Quan ret = smu_cmn_send_smc_msg(smu, SMU_MSG_PowerDownJpeg, NULL);
117543717ff6SLeo Liu if (ret)
117643717ff6SLeo Liu return ret;
117743717ff6SLeo Liu }
117843717ff6SLeo Liu }
117943717ff6SLeo Liu
118043717ff6SLeo Liu return ret;
118143717ff6SLeo Liu }
118243717ff6SLeo Liu
navi10_get_current_clk_freq_by_table(struct smu_context * smu,enum smu_clk_type clk_type,uint32_t * value)118398e1a543SKevin Wang static int navi10_get_current_clk_freq_by_table(struct smu_context *smu,
118498e1a543SKevin Wang enum smu_clk_type clk_type,
118598e1a543SKevin Wang uint32_t *value)
118698e1a543SKevin Wang {
1187cf24dd27SEvan Quan MetricsMember_t member_type;
1188cf24dd27SEvan Quan int clk_id = 0;
118998e1a543SKevin Wang
11906c339f37SEvan Quan clk_id = smu_cmn_to_asic_specific_index(smu,
11916c339f37SEvan Quan CMN2ASIC_MAPPING_CLK,
11926c339f37SEvan Quan clk_type);
119398e1a543SKevin Wang if (clk_id < 0)
119498e1a543SKevin Wang return clk_id;
119598e1a543SKevin Wang
1196cf24dd27SEvan Quan switch (clk_id) {
1197cf24dd27SEvan Quan case PPCLK_GFXCLK:
1198cf24dd27SEvan Quan member_type = METRICS_CURR_GFXCLK;
1199cf24dd27SEvan Quan break;
1200cf24dd27SEvan Quan case PPCLK_UCLK:
1201cf24dd27SEvan Quan member_type = METRICS_CURR_UCLK;
1202cf24dd27SEvan Quan break;
1203cf24dd27SEvan Quan case PPCLK_SOCCLK:
1204cf24dd27SEvan Quan member_type = METRICS_CURR_SOCCLK;
1205cf24dd27SEvan Quan break;
1206cf24dd27SEvan Quan case PPCLK_VCLK:
1207cf24dd27SEvan Quan member_type = METRICS_CURR_VCLK;
1208cf24dd27SEvan Quan break;
1209cf24dd27SEvan Quan case PPCLK_DCLK:
1210cf24dd27SEvan Quan member_type = METRICS_CURR_DCLK;
1211cf24dd27SEvan Quan break;
1212cf24dd27SEvan Quan case PPCLK_DCEFCLK:
1213cf24dd27SEvan Quan member_type = METRICS_CURR_DCEFCLK;
1214cf24dd27SEvan Quan break;
1215cf24dd27SEvan Quan default:
1216cf24dd27SEvan Quan return -EINVAL;
1217cf24dd27SEvan Quan }
121898e1a543SKevin Wang
12197d6c13efSEvan Quan return navi1x_get_smu_metrics_data(smu,
1220cf24dd27SEvan Quan member_type,
1221cf24dd27SEvan Quan value);
122298e1a543SKevin Wang }
122398e1a543SKevin Wang
navi10_is_support_fine_grained_dpm(struct smu_context * smu,enum smu_clk_type clk_type)1224c8c19ebfSJesse Zhang static int navi10_is_support_fine_grained_dpm(struct smu_context *smu, enum smu_clk_type clk_type)
1225c49b1b59SKevin Wang {
1226c49b1b59SKevin Wang PPTable_t *pptable = smu->smu_table.driver_pptable;
1227c49b1b59SKevin Wang DpmDescriptor_t *dpm_desc = NULL;
1228c8c19ebfSJesse Zhang int clk_index = 0;
1229c49b1b59SKevin Wang
12306c339f37SEvan Quan clk_index = smu_cmn_to_asic_specific_index(smu,
12316c339f37SEvan Quan CMN2ASIC_MAPPING_CLK,
12326c339f37SEvan Quan clk_type);
1233c8c19ebfSJesse Zhang if (clk_index < 0)
1234c8c19ebfSJesse Zhang return clk_index;
1235c8c19ebfSJesse Zhang
1236c49b1b59SKevin Wang dpm_desc = &pptable->DpmDescriptor[clk_index];
1237c49b1b59SKevin Wang
1238c49b1b59SKevin Wang /* 0 - Fine grained DPM, 1 - Discrete DPM */
1239c8c19ebfSJesse Zhang return dpm_desc->SnapToDiscrete == 0 ? 1 : 0;
1240c49b1b59SKevin Wang }
1241c49b1b59SKevin Wang
navi10_od_feature_is_supported(struct smu_11_0_overdrive_table * od_table,enum SMU_11_0_ODFEATURE_CAP cap)1242e33a8cfdSAlex Deucher static inline bool navi10_od_feature_is_supported(struct smu_11_0_overdrive_table *od_table, enum SMU_11_0_ODFEATURE_CAP cap)
12437f3353f6SMatt Coffin {
1244e33a8cfdSAlex Deucher return od_table->cap[cap];
12457f3353f6SMatt Coffin }
12467f3353f6SMatt Coffin
navi10_od_setting_get_range(struct smu_11_0_overdrive_table * od_table,enum SMU_11_0_ODSETTING_ID setting,uint32_t * min,uint32_t * max)1247ee23a518SAlex Deucher static void navi10_od_setting_get_range(struct smu_11_0_overdrive_table *od_table,
1248ee23a518SAlex Deucher enum SMU_11_0_ODSETTING_ID setting,
1249ee23a518SAlex Deucher uint32_t *min, uint32_t *max)
1250ee23a518SAlex Deucher {
1251ee23a518SAlex Deucher if (min)
1252ee23a518SAlex Deucher *min = od_table->min[setting];
1253ee23a518SAlex Deucher if (max)
1254ee23a518SAlex Deucher *max = od_table->max[setting];
1255ee23a518SAlex Deucher }
12567f3353f6SMatt Coffin
navi10_emit_clk_levels(struct smu_context * smu,enum smu_clk_type clk_type,char * buf,int * offset)1257b06b48d7SDarren Powell static int navi10_emit_clk_levels(struct smu_context *smu,
1258b06b48d7SDarren Powell enum smu_clk_type clk_type,
1259b06b48d7SDarren Powell char *buf,
1260b06b48d7SDarren Powell int *offset)
1261b06b48d7SDarren Powell {
1262b06b48d7SDarren Powell uint16_t *curve_settings;
1263b06b48d7SDarren Powell int ret = 0;
1264b06b48d7SDarren Powell uint32_t cur_value = 0, value = 0;
1265b06b48d7SDarren Powell uint32_t freq_values[3] = {0};
1266b06b48d7SDarren Powell uint32_t i, levels, mark_index = 0, count = 0;
1267b06b48d7SDarren Powell struct smu_table_context *table_context = &smu->smu_table;
1268b06b48d7SDarren Powell uint32_t gen_speed, lane_width;
1269b06b48d7SDarren Powell struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
1270b06b48d7SDarren Powell struct smu_11_0_dpm_context *dpm_context = smu_dpm->dpm_context;
1271b06b48d7SDarren Powell PPTable_t *pptable = (PPTable_t *)table_context->driver_pptable;
1272b06b48d7SDarren Powell OverDriveTable_t *od_table =
1273b06b48d7SDarren Powell (OverDriveTable_t *)table_context->overdrive_table;
1274b06b48d7SDarren Powell struct smu_11_0_overdrive_table *od_settings = smu->od_settings;
1275b06b48d7SDarren Powell uint32_t min_value, max_value;
1276b06b48d7SDarren Powell
1277b06b48d7SDarren Powell switch (clk_type) {
1278b06b48d7SDarren Powell case SMU_GFXCLK:
1279b06b48d7SDarren Powell case SMU_SCLK:
1280b06b48d7SDarren Powell case SMU_SOCCLK:
1281b06b48d7SDarren Powell case SMU_MCLK:
1282b06b48d7SDarren Powell case SMU_UCLK:
1283b06b48d7SDarren Powell case SMU_FCLK:
1284b06b48d7SDarren Powell case SMU_VCLK:
1285b06b48d7SDarren Powell case SMU_DCLK:
1286b06b48d7SDarren Powell case SMU_DCEFCLK:
1287b06b48d7SDarren Powell ret = navi10_get_current_clk_freq_by_table(smu, clk_type, &cur_value);
1288b06b48d7SDarren Powell if (ret)
1289b06b48d7SDarren Powell return ret;
1290b06b48d7SDarren Powell
1291b06b48d7SDarren Powell ret = smu_v11_0_get_dpm_level_count(smu, clk_type, &count);
1292b06b48d7SDarren Powell if (ret)
1293b06b48d7SDarren Powell return ret;
1294b06b48d7SDarren Powell
1295c8c19ebfSJesse Zhang ret = navi10_is_support_fine_grained_dpm(smu, clk_type);
1296c8c19ebfSJesse Zhang if (ret < 0)
1297c8c19ebfSJesse Zhang return ret;
1298c8c19ebfSJesse Zhang
1299c8c19ebfSJesse Zhang if (!ret) {
1300b06b48d7SDarren Powell for (i = 0; i < count; i++) {
1301b06b48d7SDarren Powell ret = smu_v11_0_get_dpm_freq_by_index(smu,
1302b06b48d7SDarren Powell clk_type, i, &value);
1303b06b48d7SDarren Powell if (ret)
1304b06b48d7SDarren Powell return ret;
1305b06b48d7SDarren Powell
1306b06b48d7SDarren Powell *offset += sysfs_emit_at(buf, *offset,
1307b06b48d7SDarren Powell "%d: %uMhz %s\n",
1308b06b48d7SDarren Powell i, value,
1309b06b48d7SDarren Powell cur_value == value ? "*" : "");
1310b06b48d7SDarren Powell }
1311b06b48d7SDarren Powell } else {
1312b06b48d7SDarren Powell ret = smu_v11_0_get_dpm_freq_by_index(smu,
1313b06b48d7SDarren Powell clk_type, 0, &freq_values[0]);
1314b06b48d7SDarren Powell if (ret)
1315b06b48d7SDarren Powell return ret;
1316b06b48d7SDarren Powell ret = smu_v11_0_get_dpm_freq_by_index(smu,
1317b06b48d7SDarren Powell clk_type,
1318b06b48d7SDarren Powell count - 1,
1319b06b48d7SDarren Powell &freq_values[2]);
1320b06b48d7SDarren Powell if (ret)
1321b06b48d7SDarren Powell return ret;
1322b06b48d7SDarren Powell
1323b06b48d7SDarren Powell freq_values[1] = cur_value;
1324b06b48d7SDarren Powell mark_index = cur_value == freq_values[0] ? 0 :
1325b06b48d7SDarren Powell cur_value == freq_values[2] ? 2 : 1;
1326b06b48d7SDarren Powell
1327b06b48d7SDarren Powell levels = 3;
1328b06b48d7SDarren Powell if (mark_index != 1) {
1329b06b48d7SDarren Powell levels = 2;
1330b06b48d7SDarren Powell freq_values[1] = freq_values[2];
1331b06b48d7SDarren Powell }
1332b06b48d7SDarren Powell
1333b06b48d7SDarren Powell for (i = 0; i < levels; i++) {
1334b06b48d7SDarren Powell *offset += sysfs_emit_at(buf, *offset,
1335b06b48d7SDarren Powell "%d: %uMhz %s\n",
1336b06b48d7SDarren Powell i, freq_values[i],
1337b06b48d7SDarren Powell i == mark_index ? "*" : "");
1338b06b48d7SDarren Powell }
1339b06b48d7SDarren Powell }
1340b06b48d7SDarren Powell break;
1341b06b48d7SDarren Powell case SMU_PCIE:
1342b06b48d7SDarren Powell gen_speed = smu_v11_0_get_current_pcie_link_speed_level(smu);
1343b06b48d7SDarren Powell lane_width = smu_v11_0_get_current_pcie_link_width_level(smu);
1344b06b48d7SDarren Powell for (i = 0; i < NUM_LINK_LEVELS; i++) {
1345b06b48d7SDarren Powell *offset += sysfs_emit_at(buf, *offset, "%d: %s %s %dMhz %s\n", i,
1346b06b48d7SDarren Powell (dpm_context->dpm_tables.pcie_table.pcie_gen[i] == 0) ? "2.5GT/s," :
1347b06b48d7SDarren Powell (dpm_context->dpm_tables.pcie_table.pcie_gen[i] == 1) ? "5.0GT/s," :
1348b06b48d7SDarren Powell (dpm_context->dpm_tables.pcie_table.pcie_gen[i] == 2) ? "8.0GT/s," :
1349b06b48d7SDarren Powell (dpm_context->dpm_tables.pcie_table.pcie_gen[i] == 3) ? "16.0GT/s," : "",
1350b06b48d7SDarren Powell (dpm_context->dpm_tables.pcie_table.pcie_lane[i] == 1) ? "x1" :
1351b06b48d7SDarren Powell (dpm_context->dpm_tables.pcie_table.pcie_lane[i] == 2) ? "x2" :
1352b06b48d7SDarren Powell (dpm_context->dpm_tables.pcie_table.pcie_lane[i] == 3) ? "x4" :
1353b06b48d7SDarren Powell (dpm_context->dpm_tables.pcie_table.pcie_lane[i] == 4) ? "x8" :
1354b06b48d7SDarren Powell (dpm_context->dpm_tables.pcie_table.pcie_lane[i] == 5) ? "x12" :
1355b06b48d7SDarren Powell (dpm_context->dpm_tables.pcie_table.pcie_lane[i] == 6) ? "x16" : "",
1356b06b48d7SDarren Powell pptable->LclkFreq[i],
1357b06b48d7SDarren Powell (gen_speed == dpm_context->dpm_tables.pcie_table.pcie_gen[i]) &&
1358b06b48d7SDarren Powell (lane_width == dpm_context->dpm_tables.pcie_table.pcie_lane[i]) ?
1359b06b48d7SDarren Powell "*" : "");
1360b06b48d7SDarren Powell }
1361b06b48d7SDarren Powell break;
1362b06b48d7SDarren Powell case SMU_OD_SCLK:
1363b06b48d7SDarren Powell if (!smu->od_enabled || !od_table || !od_settings)
1364b06b48d7SDarren Powell return -EOPNOTSUPP;
1365b06b48d7SDarren Powell if (!navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_GFXCLK_LIMITS))
1366b06b48d7SDarren Powell break;
1367b06b48d7SDarren Powell *offset += sysfs_emit_at(buf, *offset, "OD_SCLK:\n0: %uMhz\n1: %uMhz\n",
1368b06b48d7SDarren Powell od_table->GfxclkFmin, od_table->GfxclkFmax);
1369b06b48d7SDarren Powell break;
1370b06b48d7SDarren Powell case SMU_OD_MCLK:
1371b06b48d7SDarren Powell if (!smu->od_enabled || !od_table || !od_settings)
1372b06b48d7SDarren Powell return -EOPNOTSUPP;
1373b06b48d7SDarren Powell if (!navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_UCLK_MAX))
1374b06b48d7SDarren Powell break;
1375b06b48d7SDarren Powell *offset += sysfs_emit_at(buf, *offset, "OD_MCLK:\n1: %uMHz\n", od_table->UclkFmax);
1376b06b48d7SDarren Powell break;
1377b06b48d7SDarren Powell case SMU_OD_VDDC_CURVE:
1378b06b48d7SDarren Powell if (!smu->od_enabled || !od_table || !od_settings)
1379b06b48d7SDarren Powell return -EOPNOTSUPP;
1380b06b48d7SDarren Powell if (!navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_GFXCLK_CURVE))
1381b06b48d7SDarren Powell break;
1382b06b48d7SDarren Powell *offset += sysfs_emit_at(buf, *offset, "OD_VDDC_CURVE:\n");
1383b06b48d7SDarren Powell for (i = 0; i < 3; i++) {
1384b06b48d7SDarren Powell switch (i) {
1385b06b48d7SDarren Powell case 0:
1386b06b48d7SDarren Powell curve_settings = &od_table->GfxclkFreq1;
1387b06b48d7SDarren Powell break;
1388b06b48d7SDarren Powell case 1:
1389b06b48d7SDarren Powell curve_settings = &od_table->GfxclkFreq2;
1390b06b48d7SDarren Powell break;
1391b06b48d7SDarren Powell case 2:
1392b06b48d7SDarren Powell curve_settings = &od_table->GfxclkFreq3;
1393b06b48d7SDarren Powell break;
1394b06b48d7SDarren Powell }
1395b06b48d7SDarren Powell *offset += sysfs_emit_at(buf, *offset, "%d: %uMHz %umV\n",
1396b06b48d7SDarren Powell i, curve_settings[0],
1397b06b48d7SDarren Powell curve_settings[1] / NAVI10_VOLTAGE_SCALE);
1398b06b48d7SDarren Powell }
1399b06b48d7SDarren Powell break;
1400b06b48d7SDarren Powell case SMU_OD_RANGE:
1401b06b48d7SDarren Powell if (!smu->od_enabled || !od_table || !od_settings)
1402b06b48d7SDarren Powell return -EOPNOTSUPP;
1403b06b48d7SDarren Powell *offset += sysfs_emit_at(buf, *offset, "%s:\n", "OD_RANGE");
1404b06b48d7SDarren Powell
1405b06b48d7SDarren Powell if (navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_GFXCLK_LIMITS)) {
1406b06b48d7SDarren Powell navi10_od_setting_get_range(od_settings, SMU_11_0_ODSETTING_GFXCLKFMIN,
1407b06b48d7SDarren Powell &min_value, NULL);
1408b06b48d7SDarren Powell navi10_od_setting_get_range(od_settings, SMU_11_0_ODSETTING_GFXCLKFMAX,
1409b06b48d7SDarren Powell NULL, &max_value);
1410b06b48d7SDarren Powell *offset += sysfs_emit_at(buf, *offset, "SCLK: %7uMhz %10uMhz\n",
1411b06b48d7SDarren Powell min_value, max_value);
1412b06b48d7SDarren Powell }
1413b06b48d7SDarren Powell
1414b06b48d7SDarren Powell if (navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_UCLK_MAX)) {
1415b06b48d7SDarren Powell navi10_od_setting_get_range(od_settings, SMU_11_0_ODSETTING_UCLKFMAX,
1416b06b48d7SDarren Powell &min_value, &max_value);
1417b06b48d7SDarren Powell *offset += sysfs_emit_at(buf, *offset, "MCLK: %7uMhz %10uMhz\n",
1418b06b48d7SDarren Powell min_value, max_value);
1419b06b48d7SDarren Powell }
1420b06b48d7SDarren Powell
1421b06b48d7SDarren Powell if (navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_GFXCLK_CURVE)) {
1422b06b48d7SDarren Powell navi10_od_setting_get_range(od_settings,
1423b06b48d7SDarren Powell SMU_11_0_ODSETTING_VDDGFXCURVEFREQ_P1,
1424b06b48d7SDarren Powell &min_value, &max_value);
1425b06b48d7SDarren Powell *offset += sysfs_emit_at(buf, *offset,
1426b06b48d7SDarren Powell "VDDC_CURVE_SCLK[0]: %7uMhz %10uMhz\n",
1427b06b48d7SDarren Powell min_value, max_value);
1428b06b48d7SDarren Powell navi10_od_setting_get_range(od_settings,
1429b06b48d7SDarren Powell SMU_11_0_ODSETTING_VDDGFXCURVEVOLTAGE_P1,
1430b06b48d7SDarren Powell &min_value, &max_value);
1431b06b48d7SDarren Powell *offset += sysfs_emit_at(buf, *offset,
1432b06b48d7SDarren Powell "VDDC_CURVE_VOLT[0]: %7dmV %11dmV\n",
1433b06b48d7SDarren Powell min_value, max_value);
1434b06b48d7SDarren Powell navi10_od_setting_get_range(od_settings,
1435b06b48d7SDarren Powell SMU_11_0_ODSETTING_VDDGFXCURVEFREQ_P2,
1436b06b48d7SDarren Powell &min_value, &max_value);
1437b06b48d7SDarren Powell *offset += sysfs_emit_at(buf, *offset,
1438b06b48d7SDarren Powell "VDDC_CURVE_SCLK[1]: %7uMhz %10uMhz\n",
1439b06b48d7SDarren Powell min_value, max_value);
1440b06b48d7SDarren Powell navi10_od_setting_get_range(od_settings,
1441b06b48d7SDarren Powell SMU_11_0_ODSETTING_VDDGFXCURVEVOLTAGE_P2,
1442b06b48d7SDarren Powell &min_value, &max_value);
1443b06b48d7SDarren Powell *offset += sysfs_emit_at(buf, *offset,
1444b06b48d7SDarren Powell "VDDC_CURVE_VOLT[1]: %7dmV %11dmV\n",
1445b06b48d7SDarren Powell min_value, max_value);
1446b06b48d7SDarren Powell navi10_od_setting_get_range(od_settings,
1447b06b48d7SDarren Powell SMU_11_0_ODSETTING_VDDGFXCURVEFREQ_P3,
1448b06b48d7SDarren Powell &min_value, &max_value);
1449b06b48d7SDarren Powell *offset += sysfs_emit_at(buf, *offset,
1450b06b48d7SDarren Powell "VDDC_CURVE_SCLK[2]: %7uMhz %10uMhz\n",
1451b06b48d7SDarren Powell min_value, max_value);
1452b06b48d7SDarren Powell navi10_od_setting_get_range(od_settings,
1453b06b48d7SDarren Powell SMU_11_0_ODSETTING_VDDGFXCURVEVOLTAGE_P3,
1454b06b48d7SDarren Powell &min_value, &max_value);
1455b06b48d7SDarren Powell *offset += sysfs_emit_at(buf, *offset,
1456b06b48d7SDarren Powell "VDDC_CURVE_VOLT[2]: %7dmV %11dmV\n",
1457b06b48d7SDarren Powell min_value, max_value);
1458b06b48d7SDarren Powell }
1459b06b48d7SDarren Powell
1460b06b48d7SDarren Powell break;
1461b06b48d7SDarren Powell default:
1462b06b48d7SDarren Powell break;
1463b06b48d7SDarren Powell }
1464b06b48d7SDarren Powell
1465b06b48d7SDarren Powell return 0;
1466b06b48d7SDarren Powell }
1467b06b48d7SDarren Powell
navi10_print_clk_levels(struct smu_context * smu,enum smu_clk_type clk_type,char * buf)1468b1e7e224SKevin Wang static int navi10_print_clk_levels(struct smu_context *smu,
1469b1e7e224SKevin Wang enum smu_clk_type clk_type, char *buf)
1470b1e7e224SKevin Wang {
14717f3353f6SMatt Coffin uint16_t *curve_settings;
147233155ce6SLijo Lazar int i, levels, size = 0, ret = 0;
1473b1e7e224SKevin Wang uint32_t cur_value = 0, value = 0, count = 0;
1474c49b1b59SKevin Wang uint32_t freq_values[3] = {0};
1475c49b1b59SKevin Wang uint32_t mark_index = 0;
14767f3353f6SMatt Coffin struct smu_table_context *table_context = &smu->smu_table;
1477fddbfb1cSKenneth Feng uint32_t gen_speed, lane_width;
1478fddbfb1cSKenneth Feng struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
1479fddbfb1cSKenneth Feng struct smu_11_0_dpm_context *dpm_context = smu_dpm->dpm_context;
1480fddbfb1cSKenneth Feng PPTable_t *pptable = (PPTable_t *)table_context->driver_pptable;
1481fddbfb1cSKenneth Feng OverDriveTable_t *od_table =
1482fddbfb1cSKenneth Feng (OverDriveTable_t *)table_context->overdrive_table;
1483fddbfb1cSKenneth Feng struct smu_11_0_overdrive_table *od_settings = smu->od_settings;
1484ee23a518SAlex Deucher uint32_t min_value, max_value;
1485b1e7e224SKevin Wang
1486ee121f7eSLang Yu smu_cmn_get_sysfs_buf(&buf, &size);
1487ee121f7eSLang Yu
1488b1e7e224SKevin Wang switch (clk_type) {
1489b1e7e224SKevin Wang case SMU_GFXCLK:
1490b1e7e224SKevin Wang case SMU_SCLK:
1491b1e7e224SKevin Wang case SMU_SOCCLK:
1492b1e7e224SKevin Wang case SMU_MCLK:
1493b1e7e224SKevin Wang case SMU_UCLK:
1494b1e7e224SKevin Wang case SMU_FCLK:
149578842457SDavid M Nieto case SMU_VCLK:
149678842457SDavid M Nieto case SMU_DCLK:
1497b1e7e224SKevin Wang case SMU_DCEFCLK:
14985e6dc8feSEvan Quan ret = navi10_get_current_clk_freq_by_table(smu, clk_type, &cur_value);
1499b1e7e224SKevin Wang if (ret)
1500b1e7e224SKevin Wang return size;
1501c49b1b59SKevin Wang
1502d8d3493aSEvan Quan ret = smu_v11_0_get_dpm_level_count(smu, clk_type, &count);
1503b1e7e224SKevin Wang if (ret)
1504b1e7e224SKevin Wang return size;
1505b1e7e224SKevin Wang
1506c8c19ebfSJesse Zhang ret = navi10_is_support_fine_grained_dpm(smu, clk_type);
1507c8c19ebfSJesse Zhang if (ret < 0)
1508c8c19ebfSJesse Zhang return ret;
1509c8c19ebfSJesse Zhang
1510c8c19ebfSJesse Zhang if (!ret) {
1511b1e7e224SKevin Wang for (i = 0; i < count; i++) {
1512d8d3493aSEvan Quan ret = smu_v11_0_get_dpm_freq_by_index(smu, clk_type, i, &value);
1513b1e7e224SKevin Wang if (ret)
1514b1e7e224SKevin Wang return size;
1515b1e7e224SKevin Wang
1516828db598SDarren Powell size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", i, value,
1517b1e7e224SKevin Wang cur_value == value ? "*" : "");
1518b1e7e224SKevin Wang }
1519c49b1b59SKevin Wang } else {
1520d8d3493aSEvan Quan ret = smu_v11_0_get_dpm_freq_by_index(smu, clk_type, 0, &freq_values[0]);
1521c49b1b59SKevin Wang if (ret)
1522c49b1b59SKevin Wang return size;
1523d8d3493aSEvan Quan ret = smu_v11_0_get_dpm_freq_by_index(smu, clk_type, count - 1, &freq_values[2]);
1524c49b1b59SKevin Wang if (ret)
1525c49b1b59SKevin Wang return size;
1526c49b1b59SKevin Wang
1527c49b1b59SKevin Wang freq_values[1] = cur_value;
1528c49b1b59SKevin Wang mark_index = cur_value == freq_values[0] ? 0 :
1529c49b1b59SKevin Wang cur_value == freq_values[2] ? 2 : 1;
1530c49b1b59SKevin Wang
153133155ce6SLijo Lazar levels = 3;
153233155ce6SLijo Lazar if (mark_index != 1) {
153333155ce6SLijo Lazar levels = 2;
153433155ce6SLijo Lazar freq_values[1] = freq_values[2];
153533155ce6SLijo Lazar }
153633155ce6SLijo Lazar
153733155ce6SLijo Lazar for (i = 0; i < levels; i++) {
1538828db598SDarren Powell size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", i, freq_values[i],
1539c49b1b59SKevin Wang i == mark_index ? "*" : "");
1540c49b1b59SKevin Wang }
1541c49b1b59SKevin Wang }
1542b1e7e224SKevin Wang break;
1543fddbfb1cSKenneth Feng case SMU_PCIE:
1544e4c9200dSEvan Quan gen_speed = smu_v11_0_get_current_pcie_link_speed_level(smu);
1545e4c9200dSEvan Quan lane_width = smu_v11_0_get_current_pcie_link_width_level(smu);
1546fddbfb1cSKenneth Feng for (i = 0; i < NUM_LINK_LEVELS; i++)
1547828db598SDarren Powell size += sysfs_emit_at(buf, size, "%d: %s %s %dMhz %s\n", i,
1548fddbfb1cSKenneth Feng (dpm_context->dpm_tables.pcie_table.pcie_gen[i] == 0) ? "2.5GT/s," :
1549fddbfb1cSKenneth Feng (dpm_context->dpm_tables.pcie_table.pcie_gen[i] == 1) ? "5.0GT/s," :
1550fddbfb1cSKenneth Feng (dpm_context->dpm_tables.pcie_table.pcie_gen[i] == 2) ? "8.0GT/s," :
1551fddbfb1cSKenneth Feng (dpm_context->dpm_tables.pcie_table.pcie_gen[i] == 3) ? "16.0GT/s," : "",
1552fddbfb1cSKenneth Feng (dpm_context->dpm_tables.pcie_table.pcie_lane[i] == 1) ? "x1" :
1553fddbfb1cSKenneth Feng (dpm_context->dpm_tables.pcie_table.pcie_lane[i] == 2) ? "x2" :
1554fddbfb1cSKenneth Feng (dpm_context->dpm_tables.pcie_table.pcie_lane[i] == 3) ? "x4" :
1555fddbfb1cSKenneth Feng (dpm_context->dpm_tables.pcie_table.pcie_lane[i] == 4) ? "x8" :
1556fddbfb1cSKenneth Feng (dpm_context->dpm_tables.pcie_table.pcie_lane[i] == 5) ? "x12" :
1557fddbfb1cSKenneth Feng (dpm_context->dpm_tables.pcie_table.pcie_lane[i] == 6) ? "x16" : "",
1558fddbfb1cSKenneth Feng pptable->LclkFreq[i],
1559fddbfb1cSKenneth Feng (gen_speed == dpm_context->dpm_tables.pcie_table.pcie_gen[i]) &&
1560fddbfb1cSKenneth Feng (lane_width == dpm_context->dpm_tables.pcie_table.pcie_lane[i]) ?
1561fddbfb1cSKenneth Feng "*" : "");
1562fddbfb1cSKenneth Feng break;
15637f3353f6SMatt Coffin case SMU_OD_SCLK:
15647f3353f6SMatt Coffin if (!smu->od_enabled || !od_table || !od_settings)
15657f3353f6SMatt Coffin break;
1566e33a8cfdSAlex Deucher if (!navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_GFXCLK_LIMITS))
15677f3353f6SMatt Coffin break;
1568828db598SDarren Powell size += sysfs_emit_at(buf, size, "OD_SCLK:\n");
1569828db598SDarren Powell size += sysfs_emit_at(buf, size, "0: %uMhz\n1: %uMhz\n",
1570828db598SDarren Powell od_table->GfxclkFmin, od_table->GfxclkFmax);
15717f3353f6SMatt Coffin break;
15727f3353f6SMatt Coffin case SMU_OD_MCLK:
15737f3353f6SMatt Coffin if (!smu->od_enabled || !od_table || !od_settings)
15747f3353f6SMatt Coffin break;
1575e33a8cfdSAlex Deucher if (!navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_UCLK_MAX))
15767f3353f6SMatt Coffin break;
1577828db598SDarren Powell size += sysfs_emit_at(buf, size, "OD_MCLK:\n");
1578828db598SDarren Powell size += sysfs_emit_at(buf, size, "1: %uMHz\n", od_table->UclkFmax);
15797f3353f6SMatt Coffin break;
15807f3353f6SMatt Coffin case SMU_OD_VDDC_CURVE:
15817f3353f6SMatt Coffin if (!smu->od_enabled || !od_table || !od_settings)
15827f3353f6SMatt Coffin break;
1583e33a8cfdSAlex Deucher if (!navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_GFXCLK_CURVE))
15847f3353f6SMatt Coffin break;
1585828db598SDarren Powell size += sysfs_emit_at(buf, size, "OD_VDDC_CURVE:\n");
15867f3353f6SMatt Coffin for (i = 0; i < 3; i++) {
15877f3353f6SMatt Coffin switch (i) {
15887f3353f6SMatt Coffin case 0:
15897f3353f6SMatt Coffin curve_settings = &od_table->GfxclkFreq1;
15907f3353f6SMatt Coffin break;
15917f3353f6SMatt Coffin case 1:
15927f3353f6SMatt Coffin curve_settings = &od_table->GfxclkFreq2;
15937f3353f6SMatt Coffin break;
15947f3353f6SMatt Coffin case 2:
15957f3353f6SMatt Coffin curve_settings = &od_table->GfxclkFreq3;
15967f3353f6SMatt Coffin break;
15977f3353f6SMatt Coffin }
1598828db598SDarren Powell size += sysfs_emit_at(buf, size, "%d: %uMHz %umV\n",
1599828db598SDarren Powell i, curve_settings[0],
1600828db598SDarren Powell curve_settings[1] / NAVI10_VOLTAGE_SCALE);
16017f3353f6SMatt Coffin }
16027f3353f6SMatt Coffin break;
1603ee23a518SAlex Deucher case SMU_OD_RANGE:
1604ee23a518SAlex Deucher if (!smu->od_enabled || !od_table || !od_settings)
1605ee23a518SAlex Deucher break;
1606ee121f7eSLang Yu size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE");
1607ee23a518SAlex Deucher
1608e33a8cfdSAlex Deucher if (navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_GFXCLK_LIMITS)) {
1609ee23a518SAlex Deucher navi10_od_setting_get_range(od_settings, SMU_11_0_ODSETTING_GFXCLKFMIN,
1610ee23a518SAlex Deucher &min_value, NULL);
1611ee23a518SAlex Deucher navi10_od_setting_get_range(od_settings, SMU_11_0_ODSETTING_GFXCLKFMAX,
1612ee23a518SAlex Deucher NULL, &max_value);
1613828db598SDarren Powell size += sysfs_emit_at(buf, size, "SCLK: %7uMhz %10uMhz\n",
1614ee23a518SAlex Deucher min_value, max_value);
1615ee23a518SAlex Deucher }
1616ee23a518SAlex Deucher
1617e33a8cfdSAlex Deucher if (navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_UCLK_MAX)) {
1618ee23a518SAlex Deucher navi10_od_setting_get_range(od_settings, SMU_11_0_ODSETTING_UCLKFMAX,
1619ee23a518SAlex Deucher &min_value, &max_value);
1620828db598SDarren Powell size += sysfs_emit_at(buf, size, "MCLK: %7uMhz %10uMhz\n",
1621ee23a518SAlex Deucher min_value, max_value);
1622ee23a518SAlex Deucher }
1623ee23a518SAlex Deucher
1624e33a8cfdSAlex Deucher if (navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_GFXCLK_CURVE)) {
1625ee23a518SAlex Deucher navi10_od_setting_get_range(od_settings, SMU_11_0_ODSETTING_VDDGFXCURVEFREQ_P1,
1626ee23a518SAlex Deucher &min_value, &max_value);
1627828db598SDarren Powell size += sysfs_emit_at(buf, size, "VDDC_CURVE_SCLK[0]: %7uMhz %10uMhz\n",
1628ee23a518SAlex Deucher min_value, max_value);
1629ee23a518SAlex Deucher navi10_od_setting_get_range(od_settings, SMU_11_0_ODSETTING_VDDGFXCURVEVOLTAGE_P1,
1630ee23a518SAlex Deucher &min_value, &max_value);
1631828db598SDarren Powell size += sysfs_emit_at(buf, size, "VDDC_CURVE_VOLT[0]: %7dmV %11dmV\n",
1632ee23a518SAlex Deucher min_value, max_value);
1633ee23a518SAlex Deucher navi10_od_setting_get_range(od_settings, SMU_11_0_ODSETTING_VDDGFXCURVEFREQ_P2,
1634ee23a518SAlex Deucher &min_value, &max_value);
1635828db598SDarren Powell size += sysfs_emit_at(buf, size, "VDDC_CURVE_SCLK[1]: %7uMhz %10uMhz\n",
1636ee23a518SAlex Deucher min_value, max_value);
1637ee23a518SAlex Deucher navi10_od_setting_get_range(od_settings, SMU_11_0_ODSETTING_VDDGFXCURVEVOLTAGE_P2,
1638ee23a518SAlex Deucher &min_value, &max_value);
1639828db598SDarren Powell size += sysfs_emit_at(buf, size, "VDDC_CURVE_VOLT[1]: %7dmV %11dmV\n",
1640ee23a518SAlex Deucher min_value, max_value);
1641ee23a518SAlex Deucher navi10_od_setting_get_range(od_settings, SMU_11_0_ODSETTING_VDDGFXCURVEFREQ_P3,
1642ee23a518SAlex Deucher &min_value, &max_value);
1643828db598SDarren Powell size += sysfs_emit_at(buf, size, "VDDC_CURVE_SCLK[2]: %7uMhz %10uMhz\n",
1644ee23a518SAlex Deucher min_value, max_value);
1645ee23a518SAlex Deucher navi10_od_setting_get_range(od_settings, SMU_11_0_ODSETTING_VDDGFXCURVEVOLTAGE_P3,
1646ee23a518SAlex Deucher &min_value, &max_value);
1647828db598SDarren Powell size += sysfs_emit_at(buf, size, "VDDC_CURVE_VOLT[2]: %7dmV %11dmV\n",
1648ee23a518SAlex Deucher min_value, max_value);
1649ee23a518SAlex Deucher }
1650ee23a518SAlex Deucher
1651ee23a518SAlex Deucher break;
1652b1e7e224SKevin Wang default:
1653b1e7e224SKevin Wang break;
1654b1e7e224SKevin Wang }
1655b1e7e224SKevin Wang
1656b1e7e224SKevin Wang return size;
1657b1e7e224SKevin Wang }
1658b1e7e224SKevin Wang
navi10_force_clk_levels(struct smu_context * smu,enum smu_clk_type clk_type,uint32_t mask)1659db439ca2SKevin Wang static int navi10_force_clk_levels(struct smu_context *smu,
1660db439ca2SKevin Wang enum smu_clk_type clk_type, uint32_t mask)
1661db439ca2SKevin Wang {
1662db439ca2SKevin Wang
16633ec61983SMingtong Bao int ret = 0;
1664db439ca2SKevin Wang uint32_t soft_min_level = 0, soft_max_level = 0, min_freq = 0, max_freq = 0;
1665db439ca2SKevin Wang
1666db439ca2SKevin Wang soft_min_level = mask ? (ffs(mask) - 1) : 0;
1667db439ca2SKevin Wang soft_max_level = mask ? (fls(mask) - 1) : 0;
1668db439ca2SKevin Wang
1669db439ca2SKevin Wang switch (clk_type) {
1670db439ca2SKevin Wang case SMU_GFXCLK:
1671c0b9d6d2SKevin Wang case SMU_SCLK:
1672db439ca2SKevin Wang case SMU_SOCCLK:
1673db439ca2SKevin Wang case SMU_MCLK:
1674db439ca2SKevin Wang case SMU_UCLK:
1675db439ca2SKevin Wang case SMU_FCLK:
167609ba2e7dSEvan Quan /* There is only 2 levels for fine grained DPM */
1677c8c19ebfSJesse Zhang ret = navi10_is_support_fine_grained_dpm(smu, clk_type);
1678c8c19ebfSJesse Zhang if (ret < 0)
1679c8c19ebfSJesse Zhang return ret;
1680c8c19ebfSJesse Zhang
1681c8c19ebfSJesse Zhang if (ret) {
168209ba2e7dSEvan Quan soft_max_level = (soft_max_level >= 1 ? 1 : 0);
168309ba2e7dSEvan Quan soft_min_level = (soft_min_level >= 1 ? 1 : 0);
168409ba2e7dSEvan Quan }
168509ba2e7dSEvan Quan
1686d8d3493aSEvan Quan ret = smu_v11_0_get_dpm_freq_by_index(smu, clk_type, soft_min_level, &min_freq);
1687db439ca2SKevin Wang if (ret)
16883ec61983SMingtong Bao return 0;
1689db439ca2SKevin Wang
1690d8d3493aSEvan Quan ret = smu_v11_0_get_dpm_freq_by_index(smu, clk_type, soft_max_level, &max_freq);
1691db439ca2SKevin Wang if (ret)
16923ec61983SMingtong Bao return 0;
1693db439ca2SKevin Wang
16943d73327bSAlex Deucher ret = smu_v11_0_set_soft_freq_limited_range(smu, clk_type, min_freq, max_freq, false);
1695db439ca2SKevin Wang if (ret)
16963ec61983SMingtong Bao return 0;
1697db439ca2SKevin Wang break;
1698b117b396SDarren Powell case SMU_DCEFCLK:
1699b117b396SDarren Powell dev_info(smu->adev->dev, "Setting DCEFCLK min/max dpm level is not supported!\n");
1700b117b396SDarren Powell break;
1701b117b396SDarren Powell
1702db439ca2SKevin Wang default:
1703db439ca2SKevin Wang break;
1704db439ca2SKevin Wang }
1705db439ca2SKevin Wang
17063ec61983SMingtong Bao return 0;
1707db439ca2SKevin Wang }
1708db439ca2SKevin Wang
navi10_populate_umd_state_clk(struct smu_context * smu)1709fa51bfc2SKevin Wang static int navi10_populate_umd_state_clk(struct smu_context *smu)
1710fa51bfc2SKevin Wang {
171162cc9dd1SEvan Quan struct smu_11_0_dpm_context *dpm_context =
171262cc9dd1SEvan Quan smu->smu_dpm.dpm_context;
171362cc9dd1SEvan Quan struct smu_11_0_dpm_table *gfx_table =
171462cc9dd1SEvan Quan &dpm_context->dpm_tables.gfx_table;
171562cc9dd1SEvan Quan struct smu_11_0_dpm_table *mem_table =
171662cc9dd1SEvan Quan &dpm_context->dpm_tables.uclk_table;
171762cc9dd1SEvan Quan struct smu_11_0_dpm_table *soc_table =
171862cc9dd1SEvan Quan &dpm_context->dpm_tables.soc_table;
171962cc9dd1SEvan Quan struct smu_umd_pstate_table *pstate_table =
172062cc9dd1SEvan Quan &smu->pstate_table;
172162cc9dd1SEvan Quan struct amdgpu_device *adev = smu->adev;
172262cc9dd1SEvan Quan uint32_t sclk_freq;
1723fa51bfc2SKevin Wang
172462cc9dd1SEvan Quan pstate_table->gfxclk_pstate.min = gfx_table->min;
17254e8303cfSLijo Lazar switch (amdgpu_ip_version(adev, MP1_HWIP, 0)) {
1726ea0d730aSAlex Deucher case IP_VERSION(11, 0, 0):
172762cc9dd1SEvan Quan switch (adev->pdev->revision) {
172862cc9dd1SEvan Quan case 0xf0: /* XTX */
172962cc9dd1SEvan Quan case 0xc0:
173062cc9dd1SEvan Quan sclk_freq = NAVI10_PEAK_SCLK_XTX;
173162cc9dd1SEvan Quan break;
173262cc9dd1SEvan Quan case 0xf1: /* XT */
173362cc9dd1SEvan Quan case 0xc1:
173462cc9dd1SEvan Quan sclk_freq = NAVI10_PEAK_SCLK_XT;
173562cc9dd1SEvan Quan break;
173662cc9dd1SEvan Quan default: /* XL */
173762cc9dd1SEvan Quan sclk_freq = NAVI10_PEAK_SCLK_XL;
173862cc9dd1SEvan Quan break;
173962cc9dd1SEvan Quan }
174062cc9dd1SEvan Quan break;
1741ea0d730aSAlex Deucher case IP_VERSION(11, 0, 5):
174262cc9dd1SEvan Quan switch (adev->pdev->revision) {
174362cc9dd1SEvan Quan case 0xc7: /* XT */
174462cc9dd1SEvan Quan case 0xf4:
174562cc9dd1SEvan Quan sclk_freq = NAVI14_UMD_PSTATE_PEAK_XT_GFXCLK;
174662cc9dd1SEvan Quan break;
174762cc9dd1SEvan Quan case 0xc1: /* XTM */
174862cc9dd1SEvan Quan case 0xf2:
174962cc9dd1SEvan Quan sclk_freq = NAVI14_UMD_PSTATE_PEAK_XTM_GFXCLK;
175062cc9dd1SEvan Quan break;
175162cc9dd1SEvan Quan case 0xc3: /* XLM */
175262cc9dd1SEvan Quan case 0xf3:
175362cc9dd1SEvan Quan sclk_freq = NAVI14_UMD_PSTATE_PEAK_XLM_GFXCLK;
175462cc9dd1SEvan Quan break;
175562cc9dd1SEvan Quan case 0xc5: /* XTX */
175662cc9dd1SEvan Quan case 0xf6:
175762cc9dd1SEvan Quan sclk_freq = NAVI14_UMD_PSTATE_PEAK_XLM_GFXCLK;
175862cc9dd1SEvan Quan break;
175962cc9dd1SEvan Quan default: /* XL */
176062cc9dd1SEvan Quan sclk_freq = NAVI14_UMD_PSTATE_PEAK_XL_GFXCLK;
176162cc9dd1SEvan Quan break;
176262cc9dd1SEvan Quan }
176362cc9dd1SEvan Quan break;
1764ea0d730aSAlex Deucher case IP_VERSION(11, 0, 9):
176562cc9dd1SEvan Quan sclk_freq = NAVI12_UMD_PSTATE_PEAK_GFXCLK;
176662cc9dd1SEvan Quan break;
176762cc9dd1SEvan Quan default:
176862cc9dd1SEvan Quan sclk_freq = gfx_table->dpm_levels[gfx_table->count - 1].value;
176962cc9dd1SEvan Quan break;
177062cc9dd1SEvan Quan }
177162cc9dd1SEvan Quan pstate_table->gfxclk_pstate.peak = sclk_freq;
1772fa51bfc2SKevin Wang
177362cc9dd1SEvan Quan pstate_table->uclk_pstate.min = mem_table->min;
177462cc9dd1SEvan Quan pstate_table->uclk_pstate.peak = mem_table->max;
1775fa51bfc2SKevin Wang
177662cc9dd1SEvan Quan pstate_table->socclk_pstate.min = soc_table->min;
177762cc9dd1SEvan Quan pstate_table->socclk_pstate.peak = soc_table->max;
177864974ab2SKevin Wang
177962cc9dd1SEvan Quan if (gfx_table->max > NAVI10_UMD_PSTATE_PROFILING_GFXCLK &&
178062cc9dd1SEvan Quan mem_table->max > NAVI10_UMD_PSTATE_PROFILING_MEMCLK &&
178162cc9dd1SEvan Quan soc_table->max > NAVI10_UMD_PSTATE_PROFILING_SOCCLK) {
178262cc9dd1SEvan Quan pstate_table->gfxclk_pstate.standard =
178362cc9dd1SEvan Quan NAVI10_UMD_PSTATE_PROFILING_GFXCLK;
178462cc9dd1SEvan Quan pstate_table->uclk_pstate.standard =
178562cc9dd1SEvan Quan NAVI10_UMD_PSTATE_PROFILING_MEMCLK;
178662cc9dd1SEvan Quan pstate_table->socclk_pstate.standard =
178762cc9dd1SEvan Quan NAVI10_UMD_PSTATE_PROFILING_SOCCLK;
178862cc9dd1SEvan Quan } else {
178962cc9dd1SEvan Quan pstate_table->gfxclk_pstate.standard =
179062cc9dd1SEvan Quan pstate_table->gfxclk_pstate.min;
179162cc9dd1SEvan Quan pstate_table->uclk_pstate.standard =
179262cc9dd1SEvan Quan pstate_table->uclk_pstate.min;
179362cc9dd1SEvan Quan pstate_table->socclk_pstate.standard =
179462cc9dd1SEvan Quan pstate_table->socclk_pstate.min;
179562cc9dd1SEvan Quan }
179664974ab2SKevin Wang
179762cc9dd1SEvan Quan return 0;
1798fa51bfc2SKevin Wang }
1799fa51bfc2SKevin Wang
navi10_get_clock_by_type_with_latency(struct smu_context * smu,enum smu_clk_type clk_type,struct pp_clock_levels_with_latency * clocks)1800a43913eaSKevin Wang static int navi10_get_clock_by_type_with_latency(struct smu_context *smu,
1801a43913eaSKevin Wang enum smu_clk_type clk_type,
1802a43913eaSKevin Wang struct pp_clock_levels_with_latency *clocks)
1803a43913eaSKevin Wang {
1804a43913eaSKevin Wang int ret = 0, i = 0;
1805a43913eaSKevin Wang uint32_t level_count = 0, freq = 0;
1806a43913eaSKevin Wang
1807a43913eaSKevin Wang switch (clk_type) {
1808a43913eaSKevin Wang case SMU_GFXCLK:
1809a43913eaSKevin Wang case SMU_DCEFCLK:
1810a43913eaSKevin Wang case SMU_SOCCLK:
1811e0d5322cSAlex Deucher case SMU_MCLK:
1812e0d5322cSAlex Deucher case SMU_UCLK:
1813d8d3493aSEvan Quan ret = smu_v11_0_get_dpm_level_count(smu, clk_type, &level_count);
1814a43913eaSKevin Wang if (ret)
1815a43913eaSKevin Wang return ret;
1816a43913eaSKevin Wang
1817a43913eaSKevin Wang level_count = min(level_count, (uint32_t)MAX_NUM_CLOCKS);
1818a43913eaSKevin Wang clocks->num_levels = level_count;
1819a43913eaSKevin Wang
1820a43913eaSKevin Wang for (i = 0; i < level_count; i++) {
1821d8d3493aSEvan Quan ret = smu_v11_0_get_dpm_freq_by_index(smu, clk_type, i, &freq);
1822a43913eaSKevin Wang if (ret)
1823a43913eaSKevin Wang return ret;
1824a43913eaSKevin Wang
1825a43913eaSKevin Wang clocks->data[i].clocks_in_khz = freq * 1000;
1826a43913eaSKevin Wang clocks->data[i].latency_in_us = 0;
1827a43913eaSKevin Wang }
1828a43913eaSKevin Wang break;
1829a43913eaSKevin Wang default:
1830a43913eaSKevin Wang break;
1831a43913eaSKevin Wang }
1832a43913eaSKevin Wang
1833a43913eaSKevin Wang return ret;
1834a43913eaSKevin Wang }
1835a43913eaSKevin Wang
navi10_pre_display_config_changed(struct smu_context * smu)183628430544SKevin Wang static int navi10_pre_display_config_changed(struct smu_context *smu)
183728430544SKevin Wang {
183828430544SKevin Wang int ret = 0;
183928430544SKevin Wang uint32_t max_freq = 0;
184028430544SKevin Wang
184166c86828SEvan Quan ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_NumOfDisplays, 0, NULL);
184228430544SKevin Wang if (ret)
184328430544SKevin Wang return ret;
184428430544SKevin Wang
1845b4bb3aafSEvan Quan if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) {
1846e5ef784bSEvan Quan ret = smu_v11_0_get_dpm_ultimate_freq(smu, SMU_UCLK, NULL, &max_freq);
184728430544SKevin Wang if (ret)
184828430544SKevin Wang return ret;
1849661b94f5SEvan Quan ret = smu_v11_0_set_hard_freq_limited_range(smu, SMU_UCLK, 0, max_freq);
185028430544SKevin Wang if (ret)
185128430544SKevin Wang return ret;
185228430544SKevin Wang }
185328430544SKevin Wang
185428430544SKevin Wang return ret;
185528430544SKevin Wang }
185628430544SKevin Wang
navi10_display_config_changed(struct smu_context * smu)18570a6430daSKevin Wang static int navi10_display_config_changed(struct smu_context *smu)
18580a6430daSKevin Wang {
18590a6430daSKevin Wang int ret = 0;
18600a6430daSKevin Wang
18610a6430daSKevin Wang if ((smu->watermarks_bitmap & WATERMARKS_EXIST) &&
18627ade3ca9SEvan Quan smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT) &&
18637ade3ca9SEvan Quan smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) {
186466c86828SEvan Quan ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_NumOfDisplays,
18651c58267cSMatt Coffin smu->display_config->num_display,
18661c58267cSMatt Coffin NULL);
18670a6430daSKevin Wang if (ret)
18680a6430daSKevin Wang return ret;
18690a6430daSKevin Wang }
18700a6430daSKevin Wang
18710a6430daSKevin Wang return ret;
18720a6430daSKevin Wang }
187350add63bSKevin Wang
navi10_is_dpm_running(struct smu_context * smu)18744228b601SKevin Wang static bool navi10_is_dpm_running(struct smu_context *smu)
18754228b601SKevin Wang {
18764228b601SKevin Wang int ret = 0;
18773d14a79bSKevin Wang uint64_t feature_enabled;
18783d14a79bSKevin Wang
18792d282665SEvan Quan ret = smu_cmn_get_enabled_mask(smu, &feature_enabled);
18803d14a79bSKevin Wang if (ret)
18813d14a79bSKevin Wang return false;
18823d14a79bSKevin Wang
18834228b601SKevin Wang return !!(feature_enabled & SMC_DPM_FEATURE);
18844228b601SKevin Wang }
18854228b601SKevin Wang
navi10_get_fan_speed_rpm(struct smu_context * smu,uint32_t * speed)1886d9ca7567SEvan Quan static int navi10_get_fan_speed_rpm(struct smu_context *smu,
1887d9ca7567SEvan Quan uint32_t *speed)
1888d9ca7567SEvan Quan {
1889d9ca7567SEvan Quan int ret = 0;
1890d9ca7567SEvan Quan
1891d9ca7567SEvan Quan if (!speed)
1892d9ca7567SEvan Quan return -EINVAL;
1893d9ca7567SEvan Quan
1894d9ca7567SEvan Quan switch (smu_v11_0_get_fan_control_mode(smu)) {
1895d9ca7567SEvan Quan case AMD_FAN_CTRL_AUTO:
1896d9ca7567SEvan Quan ret = navi10_get_smu_metrics_data(smu,
1897d9ca7567SEvan Quan METRICS_CURR_FANSPEED,
1898d9ca7567SEvan Quan speed);
1899d9ca7567SEvan Quan break;
1900d9ca7567SEvan Quan default:
1901d9ca7567SEvan Quan ret = smu_v11_0_get_fan_speed_rpm(smu,
1902d9ca7567SEvan Quan speed);
1903d9ca7567SEvan Quan break;
1904d9ca7567SEvan Quan }
1905d9ca7567SEvan Quan
1906d9ca7567SEvan Quan return ret;
1907d9ca7567SEvan Quan }
1908d9ca7567SEvan Quan
navi10_get_fan_parameters(struct smu_context * smu)19093204ff3eSAlex Deucher static int navi10_get_fan_parameters(struct smu_context *smu)
19103204ff3eSAlex Deucher {
19113204ff3eSAlex Deucher PPTable_t *pptable = smu->smu_table.driver_pptable;
19123204ff3eSAlex Deucher
19133204ff3eSAlex Deucher smu->fan_max_rpm = pptable->FanMaximumRpm;
19143204ff3eSAlex Deucher
19153204ff3eSAlex Deucher return 0;
19163204ff3eSAlex Deucher }
19173204ff3eSAlex Deucher
navi10_get_power_profile_mode(struct smu_context * smu,char * buf)1918b45dc20bSKevin Wang static int navi10_get_power_profile_mode(struct smu_context *smu, char *buf)
1919b45dc20bSKevin Wang {
1920b45dc20bSKevin Wang DpmActivityMonitorCoeffInt_t activity_monitor;
1921b45dc20bSKevin Wang uint32_t i, size = 0;
1922c0640304SEvan Quan int16_t workload_type = 0;
1923b45dc20bSKevin Wang static const char *title[] = {
1924b45dc20bSKevin Wang "PROFILE_INDEX(NAME)",
1925b45dc20bSKevin Wang "CLOCK_TYPE(NAME)",
1926b45dc20bSKevin Wang "FPS",
1927b45dc20bSKevin Wang "MinFreqType",
1928b45dc20bSKevin Wang "MinActiveFreqType",
1929b45dc20bSKevin Wang "MinActiveFreq",
1930b45dc20bSKevin Wang "BoosterFreqType",
1931b45dc20bSKevin Wang "BoosterFreq",
1932b45dc20bSKevin Wang "PD_Data_limit_c",
1933b45dc20bSKevin Wang "PD_Data_error_coeff",
1934b45dc20bSKevin Wang "PD_Data_error_rate_coeff"};
1935b45dc20bSKevin Wang int result = 0;
1936b45dc20bSKevin Wang
1937b45dc20bSKevin Wang if (!buf)
1938b45dc20bSKevin Wang return -EINVAL;
1939b45dc20bSKevin Wang
1940828db598SDarren Powell size += sysfs_emit_at(buf, size, "%16s %s %s %s %s %s %s %s %s %s %s\n",
1941b45dc20bSKevin Wang title[0], title[1], title[2], title[3], title[4], title[5],
1942b45dc20bSKevin Wang title[6], title[7], title[8], title[9], title[10]);
1943b45dc20bSKevin Wang
1944b45dc20bSKevin Wang for (i = 0; i <= PP_SMC_POWER_PROFILE_CUSTOM; i++) {
1945b45dc20bSKevin Wang /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
19466c339f37SEvan Quan workload_type = smu_cmn_to_asic_specific_index(smu,
19476c339f37SEvan Quan CMN2ASIC_MAPPING_WORKLOAD,
19486c339f37SEvan Quan i);
1949c0640304SEvan Quan if (workload_type < 0)
1950c0640304SEvan Quan return -EINVAL;
1951c0640304SEvan Quan
1952caad2613SEvan Quan result = smu_cmn_update_table(smu,
19530d9d78b5SEvan Quan SMU_TABLE_ACTIVITY_MONITOR_COEFF, workload_type,
1954b45dc20bSKevin Wang (void *)(&activity_monitor), false);
1955b45dc20bSKevin Wang if (result) {
1956d9811cfcSEvan Quan dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__);
1957b45dc20bSKevin Wang return result;
1958b45dc20bSKevin Wang }
1959b45dc20bSKevin Wang
1960828db598SDarren Powell size += sysfs_emit_at(buf, size, "%2d %14s%s:\n",
19613867e370SDarren Powell i, amdgpu_pp_profile_name[i], (i == smu->power_profile_mode) ? "*" : " ");
1962b45dc20bSKevin Wang
1963828db598SDarren Powell size += sysfs_emit_at(buf, size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
1964b45dc20bSKevin Wang " ",
1965b45dc20bSKevin Wang 0,
1966b45dc20bSKevin Wang "GFXCLK",
1967b45dc20bSKevin Wang activity_monitor.Gfx_FPS,
1968b45dc20bSKevin Wang activity_monitor.Gfx_MinFreqStep,
1969b45dc20bSKevin Wang activity_monitor.Gfx_MinActiveFreqType,
1970b45dc20bSKevin Wang activity_monitor.Gfx_MinActiveFreq,
1971b45dc20bSKevin Wang activity_monitor.Gfx_BoosterFreqType,
1972b45dc20bSKevin Wang activity_monitor.Gfx_BoosterFreq,
1973b45dc20bSKevin Wang activity_monitor.Gfx_PD_Data_limit_c,
1974b45dc20bSKevin Wang activity_monitor.Gfx_PD_Data_error_coeff,
1975b45dc20bSKevin Wang activity_monitor.Gfx_PD_Data_error_rate_coeff);
1976b45dc20bSKevin Wang
1977828db598SDarren Powell size += sysfs_emit_at(buf, size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
1978b45dc20bSKevin Wang " ",
1979b45dc20bSKevin Wang 1,
1980b45dc20bSKevin Wang "SOCCLK",
1981b45dc20bSKevin Wang activity_monitor.Soc_FPS,
1982b45dc20bSKevin Wang activity_monitor.Soc_MinFreqStep,
1983b45dc20bSKevin Wang activity_monitor.Soc_MinActiveFreqType,
1984b45dc20bSKevin Wang activity_monitor.Soc_MinActiveFreq,
1985b45dc20bSKevin Wang activity_monitor.Soc_BoosterFreqType,
1986b45dc20bSKevin Wang activity_monitor.Soc_BoosterFreq,
1987b45dc20bSKevin Wang activity_monitor.Soc_PD_Data_limit_c,
1988b45dc20bSKevin Wang activity_monitor.Soc_PD_Data_error_coeff,
1989b45dc20bSKevin Wang activity_monitor.Soc_PD_Data_error_rate_coeff);
1990b45dc20bSKevin Wang
1991828db598SDarren Powell size += sysfs_emit_at(buf, size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
1992b45dc20bSKevin Wang " ",
1993b45dc20bSKevin Wang 2,
199417d30ed3STobias Jakobi "MEMCLK",
1995b45dc20bSKevin Wang activity_monitor.Mem_FPS,
1996b45dc20bSKevin Wang activity_monitor.Mem_MinFreqStep,
1997b45dc20bSKevin Wang activity_monitor.Mem_MinActiveFreqType,
1998b45dc20bSKevin Wang activity_monitor.Mem_MinActiveFreq,
1999b45dc20bSKevin Wang activity_monitor.Mem_BoosterFreqType,
2000b45dc20bSKevin Wang activity_monitor.Mem_BoosterFreq,
2001b45dc20bSKevin Wang activity_monitor.Mem_PD_Data_limit_c,
2002b45dc20bSKevin Wang activity_monitor.Mem_PD_Data_error_coeff,
2003b45dc20bSKevin Wang activity_monitor.Mem_PD_Data_error_rate_coeff);
2004b45dc20bSKevin Wang }
2005b45dc20bSKevin Wang
2006b45dc20bSKevin Wang return size;
2007b45dc20bSKevin Wang }
2008b45dc20bSKevin Wang
20091443dd3cSAlex Deucher #define NAVI10_CUSTOM_PARAMS_COUNT 10
20101443dd3cSAlex Deucher #define NAVI10_CUSTOM_PARAMS_CLOCKS_COUNT 3
20111443dd3cSAlex Deucher #define NAVI10_CUSTOM_PARAMS_SIZE (NAVI10_CUSTOM_PARAMS_CLOCKS_COUNT * NAVI10_CUSTOM_PARAMS_COUNT * sizeof(long))
20121443dd3cSAlex Deucher
navi10_set_power_profile_mode_coeff(struct smu_context * smu,long * input)20131443dd3cSAlex Deucher static int navi10_set_power_profile_mode_coeff(struct smu_context *smu,
20141443dd3cSAlex Deucher long *input)
2015b45dc20bSKevin Wang {
2016b45dc20bSKevin Wang DpmActivityMonitorCoeffInt_t activity_monitor;
20171443dd3cSAlex Deucher int ret, idx;
2018b45dc20bSKevin Wang
2019caad2613SEvan Quan ret = smu_cmn_update_table(smu,
20200d9d78b5SEvan Quan SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT,
2021b45dc20bSKevin Wang (void *)(&activity_monitor), false);
2022b45dc20bSKevin Wang if (ret) {
2023d9811cfcSEvan Quan dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__);
2024b45dc20bSKevin Wang return ret;
2025b45dc20bSKevin Wang }
2026b45dc20bSKevin Wang
20271443dd3cSAlex Deucher idx = 0 * NAVI10_CUSTOM_PARAMS_COUNT;
20281443dd3cSAlex Deucher if (input[idx]) {
20291443dd3cSAlex Deucher /* Gfxclk */
20301443dd3cSAlex Deucher activity_monitor.Gfx_FPS = input[idx + 1];
20311443dd3cSAlex Deucher activity_monitor.Gfx_MinFreqStep = input[idx + 2];
20321443dd3cSAlex Deucher activity_monitor.Gfx_MinActiveFreqType = input[idx + 3];
20331443dd3cSAlex Deucher activity_monitor.Gfx_MinActiveFreq = input[idx + 4];
20341443dd3cSAlex Deucher activity_monitor.Gfx_BoosterFreqType = input[idx + 5];
20351443dd3cSAlex Deucher activity_monitor.Gfx_BoosterFreq = input[idx + 6];
20361443dd3cSAlex Deucher activity_monitor.Gfx_PD_Data_limit_c = input[idx + 7];
20371443dd3cSAlex Deucher activity_monitor.Gfx_PD_Data_error_coeff = input[idx + 8];
20381443dd3cSAlex Deucher activity_monitor.Gfx_PD_Data_error_rate_coeff = input[idx + 9];
20391443dd3cSAlex Deucher }
20401443dd3cSAlex Deucher idx = 1 * NAVI10_CUSTOM_PARAMS_COUNT;
20411443dd3cSAlex Deucher if (input[idx]) {
20421443dd3cSAlex Deucher /* Socclk */
20431443dd3cSAlex Deucher activity_monitor.Soc_FPS = input[idx + 1];
20441443dd3cSAlex Deucher activity_monitor.Soc_MinFreqStep = input[idx + 2];
20451443dd3cSAlex Deucher activity_monitor.Soc_MinActiveFreqType = input[idx + 3];
20461443dd3cSAlex Deucher activity_monitor.Soc_MinActiveFreq = input[idx + 4];
20471443dd3cSAlex Deucher activity_monitor.Soc_BoosterFreqType = input[idx + 5];
20481443dd3cSAlex Deucher activity_monitor.Soc_BoosterFreq = input[idx + 6];
20491443dd3cSAlex Deucher activity_monitor.Soc_PD_Data_limit_c = input[idx + 7];
20501443dd3cSAlex Deucher activity_monitor.Soc_PD_Data_error_coeff = input[idx + 8];
20511443dd3cSAlex Deucher activity_monitor.Soc_PD_Data_error_rate_coeff = input[idx + 9];
20521443dd3cSAlex Deucher }
20531443dd3cSAlex Deucher idx = 2 * NAVI10_CUSTOM_PARAMS_COUNT;
20541443dd3cSAlex Deucher if (input[idx]) {
20551443dd3cSAlex Deucher /* Memclk */
20561443dd3cSAlex Deucher activity_monitor.Mem_FPS = input[idx + 1];
20571443dd3cSAlex Deucher activity_monitor.Mem_MinFreqStep = input[idx + 2];
20581443dd3cSAlex Deucher activity_monitor.Mem_MinActiveFreqType = input[idx + 3];
20591443dd3cSAlex Deucher activity_monitor.Mem_MinActiveFreq = input[idx + 4];
20601443dd3cSAlex Deucher activity_monitor.Mem_BoosterFreqType = input[idx + 5];
20611443dd3cSAlex Deucher activity_monitor.Mem_BoosterFreq = input[idx + 6];
20621443dd3cSAlex Deucher activity_monitor.Mem_PD_Data_limit_c = input[idx + 7];
20631443dd3cSAlex Deucher activity_monitor.Mem_PD_Data_error_coeff = input[idx + 8];
20641443dd3cSAlex Deucher activity_monitor.Mem_PD_Data_error_rate_coeff = input[idx + 9];
2065b45dc20bSKevin Wang }
2066b45dc20bSKevin Wang
2067caad2613SEvan Quan ret = smu_cmn_update_table(smu,
20680d9d78b5SEvan Quan SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT,
2069b45dc20bSKevin Wang (void *)(&activity_monitor), true);
2070b45dc20bSKevin Wang if (ret) {
2071d9811cfcSEvan Quan dev_err(smu->adev->dev, "[%s] Failed to set activity monitor!", __func__);
2072b45dc20bSKevin Wang return ret;
2073b45dc20bSKevin Wang }
20741443dd3cSAlex Deucher
20751443dd3cSAlex Deucher return ret;
2076b45dc20bSKevin Wang }
2077b45dc20bSKevin Wang
navi10_set_power_profile_mode(struct smu_context * smu,u32 workload_mask,long * custom_params,u32 custom_params_max_idx)20781443dd3cSAlex Deucher static int navi10_set_power_profile_mode(struct smu_context *smu,
20791443dd3cSAlex Deucher u32 workload_mask,
20801443dd3cSAlex Deucher long *custom_params,
20811443dd3cSAlex Deucher u32 custom_params_max_idx)
20821443dd3cSAlex Deucher {
20831443dd3cSAlex Deucher u32 backend_workload_mask = 0;
20841443dd3cSAlex Deucher int ret, idx = -1, i;
20851443dd3cSAlex Deucher
20861443dd3cSAlex Deucher smu_cmn_get_backend_workload_mask(smu, workload_mask,
20871443dd3cSAlex Deucher &backend_workload_mask);
20881443dd3cSAlex Deucher
20891443dd3cSAlex Deucher if (workload_mask & (1 << PP_SMC_POWER_PROFILE_CUSTOM)) {
20901443dd3cSAlex Deucher if (!smu->custom_profile_params) {
20911443dd3cSAlex Deucher smu->custom_profile_params = kzalloc(NAVI10_CUSTOM_PARAMS_SIZE, GFP_KERNEL);
20921443dd3cSAlex Deucher if (!smu->custom_profile_params)
20931443dd3cSAlex Deucher return -ENOMEM;
20941443dd3cSAlex Deucher }
20951443dd3cSAlex Deucher if (custom_params && custom_params_max_idx) {
20961443dd3cSAlex Deucher if (custom_params_max_idx != NAVI10_CUSTOM_PARAMS_COUNT)
2097c0640304SEvan Quan return -EINVAL;
20981443dd3cSAlex Deucher if (custom_params[0] >= NAVI10_CUSTOM_PARAMS_CLOCKS_COUNT)
20991443dd3cSAlex Deucher return -EINVAL;
21001443dd3cSAlex Deucher idx = custom_params[0] * NAVI10_CUSTOM_PARAMS_COUNT;
21011443dd3cSAlex Deucher smu->custom_profile_params[idx] = 1;
21021443dd3cSAlex Deucher for (i = 1; i < custom_params_max_idx; i++)
21031443dd3cSAlex Deucher smu->custom_profile_params[idx + i] = custom_params[i];
21041443dd3cSAlex Deucher }
21051443dd3cSAlex Deucher ret = navi10_set_power_profile_mode_coeff(smu,
21061443dd3cSAlex Deucher smu->custom_profile_params);
21071443dd3cSAlex Deucher if (ret) {
21081443dd3cSAlex Deucher if (idx != -1)
21091443dd3cSAlex Deucher smu->custom_profile_params[idx] = 0;
21101443dd3cSAlex Deucher return ret;
21111443dd3cSAlex Deucher }
21121443dd3cSAlex Deucher } else if (smu->custom_profile_params) {
21131443dd3cSAlex Deucher memset(smu->custom_profile_params, 0, NAVI10_CUSTOM_PARAMS_SIZE);
21141443dd3cSAlex Deucher }
21151443dd3cSAlex Deucher
2116ff284ecaSJesse Zhang ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask,
21171443dd3cSAlex Deucher backend_workload_mask, NULL);
21181443dd3cSAlex Deucher if (ret) {
21191443dd3cSAlex Deucher dev_err(smu->adev->dev, "Failed to set workload mask 0x%08x\n",
21201443dd3cSAlex Deucher workload_mask);
21211443dd3cSAlex Deucher if (idx != -1)
21221443dd3cSAlex Deucher smu->custom_profile_params[idx] = 0;
21231443dd3cSAlex Deucher return ret;
21241443dd3cSAlex Deucher }
2125b45dc20bSKevin Wang
2126b45dc20bSKevin Wang return ret;
2127b45dc20bSKevin Wang }
2128b45dc20bSKevin Wang
navi10_notify_smc_display_config(struct smu_context * smu)212919796597SAlex Deucher static int navi10_notify_smc_display_config(struct smu_context *smu)
21304f963b01SKevin Wang {
21314f963b01SKevin Wang struct smu_clocks min_clocks = {0};
21324f963b01SKevin Wang struct pp_display_clock_request clock_req;
21334f963b01SKevin Wang int ret = 0;
21344f963b01SKevin Wang
21354f963b01SKevin Wang min_clocks.dcef_clock = smu->display_config->min_dcef_set_clk;
21364f963b01SKevin Wang min_clocks.dcef_clock_in_sr = smu->display_config->min_dcef_deep_sleep_set_clk;
21374f963b01SKevin Wang min_clocks.memory_clock = smu->display_config->min_mem_set_clock;
21384f963b01SKevin Wang
21397ade3ca9SEvan Quan if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) {
21404f963b01SKevin Wang clock_req.clock_type = amd_pp_dcef_clock;
21414f963b01SKevin Wang clock_req.clock_freq_in_khz = min_clocks.dcef_clock * 10;
21423697b339SEvan Quan
21436c45e480SEvan Quan ret = smu_v11_0_display_clock_voltage_request(smu, &clock_req);
21443697b339SEvan Quan if (!ret) {
21457ade3ca9SEvan Quan if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DS_DCEFCLK_BIT)) {
214666c86828SEvan Quan ret = smu_cmn_send_smc_msg_with_param(smu,
21474f963b01SKevin Wang SMU_MSG_SetMinDeepSleepDcefclk,
21481c58267cSMatt Coffin min_clocks.dcef_clock_in_sr/100,
21491c58267cSMatt Coffin NULL);
21504f963b01SKevin Wang if (ret) {
2151d9811cfcSEvan Quan dev_err(smu->adev->dev, "Attempt to set divider for DCEFCLK Failed!");
21524f963b01SKevin Wang return ret;
21534f963b01SKevin Wang }
21544f963b01SKevin Wang }
21554f963b01SKevin Wang } else {
2156d9811cfcSEvan Quan dev_info(smu->adev->dev, "Attempt to set Hard Min for DCEFCLK Failed!");
21574f963b01SKevin Wang }
21584f963b01SKevin Wang }
21594f963b01SKevin Wang
2160b4bb3aafSEvan Quan if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) {
2161661b94f5SEvan Quan ret = smu_v11_0_set_hard_freq_limited_range(smu, SMU_UCLK, min_clocks.memory_clock/100, 0);
21624f963b01SKevin Wang if (ret) {
2163d9811cfcSEvan Quan dev_err(smu->adev->dev, "[%s] Set hard min uclk failed!", __func__);
21644f963b01SKevin Wang return ret;
21654f963b01SKevin Wang }
21664f963b01SKevin Wang }
21674f963b01SKevin Wang
21684f963b01SKevin Wang return 0;
21694f963b01SKevin Wang }
21704f963b01SKevin Wang
navi10_set_watermarks_table(struct smu_context * smu,struct pp_smu_wm_range_sets * clock_ranges)21715bbb0994SKevin Wang static int navi10_set_watermarks_table(struct smu_context *smu,
21727b9c7e30SEvan Quan struct pp_smu_wm_range_sets *clock_ranges)
21735bbb0994SKevin Wang {
2174e7a95eeaSEvan Quan Watermarks_t *table = smu->smu_table.watermarks_table;
21752622e2aeSHersen Wu int ret = 0;
2176e7a95eeaSEvan Quan int i;
21775bbb0994SKevin Wang
2178e7a95eeaSEvan Quan if (clock_ranges) {
21797b9c7e30SEvan Quan if (clock_ranges->num_reader_wm_sets > NUM_WM_RANGES ||
21807b9c7e30SEvan Quan clock_ranges->num_writer_wm_sets > NUM_WM_RANGES)
21815bbb0994SKevin Wang return -EINVAL;
21825bbb0994SKevin Wang
21837b9c7e30SEvan Quan for (i = 0; i < clock_ranges->num_reader_wm_sets; i++) {
21847b9c7e30SEvan Quan table->WatermarkRow[WM_DCEFCLK][i].MinClock =
21857b9c7e30SEvan Quan clock_ranges->reader_wm_sets[i].min_drain_clk_mhz;
21867b9c7e30SEvan Quan table->WatermarkRow[WM_DCEFCLK][i].MaxClock =
21877b9c7e30SEvan Quan clock_ranges->reader_wm_sets[i].max_drain_clk_mhz;
21887b9c7e30SEvan Quan table->WatermarkRow[WM_DCEFCLK][i].MinUclk =
21897b9c7e30SEvan Quan clock_ranges->reader_wm_sets[i].min_fill_clk_mhz;
21907b9c7e30SEvan Quan table->WatermarkRow[WM_DCEFCLK][i].MaxUclk =
21917b9c7e30SEvan Quan clock_ranges->reader_wm_sets[i].max_fill_clk_mhz;
21927b9c7e30SEvan Quan
21937b9c7e30SEvan Quan table->WatermarkRow[WM_DCEFCLK][i].WmSetting =
21947b9c7e30SEvan Quan clock_ranges->reader_wm_sets[i].wm_inst;
21955bbb0994SKevin Wang }
21965bbb0994SKevin Wang
21977b9c7e30SEvan Quan for (i = 0; i < clock_ranges->num_writer_wm_sets; i++) {
21987b9c7e30SEvan Quan table->WatermarkRow[WM_SOCCLK][i].MinClock =
21997b9c7e30SEvan Quan clock_ranges->writer_wm_sets[i].min_fill_clk_mhz;
22007b9c7e30SEvan Quan table->WatermarkRow[WM_SOCCLK][i].MaxClock =
22017b9c7e30SEvan Quan clock_ranges->writer_wm_sets[i].max_fill_clk_mhz;
22027b9c7e30SEvan Quan table->WatermarkRow[WM_SOCCLK][i].MinUclk =
22037b9c7e30SEvan Quan clock_ranges->writer_wm_sets[i].min_drain_clk_mhz;
22047b9c7e30SEvan Quan table->WatermarkRow[WM_SOCCLK][i].MaxUclk =
22057b9c7e30SEvan Quan clock_ranges->writer_wm_sets[i].max_drain_clk_mhz;
22067b9c7e30SEvan Quan
22077b9c7e30SEvan Quan table->WatermarkRow[WM_SOCCLK][i].WmSetting =
22087b9c7e30SEvan Quan clock_ranges->writer_wm_sets[i].wm_inst;
22095bbb0994SKevin Wang }
22105bbb0994SKevin Wang
22112622e2aeSHersen Wu smu->watermarks_bitmap |= WATERMARKS_EXIST;
2212e7a95eeaSEvan Quan }
22132622e2aeSHersen Wu
22142622e2aeSHersen Wu /* pass data to smu controller */
2215e7a95eeaSEvan Quan if ((smu->watermarks_bitmap & WATERMARKS_EXIST) &&
2216e7a95eeaSEvan Quan !(smu->watermarks_bitmap & WATERMARKS_LOADED)) {
2217caad2613SEvan Quan ret = smu_cmn_write_watermarks_table(smu);
22182622e2aeSHersen Wu if (ret) {
2219d9811cfcSEvan Quan dev_err(smu->adev->dev, "Failed to update WMTABLE!");
22202622e2aeSHersen Wu return ret;
22212622e2aeSHersen Wu }
22222622e2aeSHersen Wu smu->watermarks_bitmap |= WATERMARKS_LOADED;
22232622e2aeSHersen Wu }
22242622e2aeSHersen Wu
22255bbb0994SKevin Wang return 0;
22265bbb0994SKevin Wang }
22275bbb0994SKevin Wang
navi10_read_sensor(struct smu_context * smu,enum amd_pp_sensors sensor,void * data,uint32_t * size)22289c62f993SKevin Wang static int navi10_read_sensor(struct smu_context *smu,
22299c62f993SKevin Wang enum amd_pp_sensors sensor,
22309c62f993SKevin Wang void *data, uint32_t *size)
22319c62f993SKevin Wang {
22329c62f993SKevin Wang int ret = 0;
22339c62f993SKevin Wang struct smu_table_context *table_context = &smu->smu_table;
22349c62f993SKevin Wang PPTable_t *pptable = table_context->driver_pptable;
22359c62f993SKevin Wang
22369b4e63f4SKenneth Feng if (!data || !size)
22379b4e63f4SKenneth Feng return -EINVAL;
22389b4e63f4SKenneth Feng
22399c62f993SKevin Wang switch (sensor) {
22409c62f993SKevin Wang case AMDGPU_PP_SENSOR_MAX_FAN_RPM:
22419c62f993SKevin Wang *(uint32_t *)data = pptable->FanMaximumRpm;
22429c62f993SKevin Wang *size = 4;
22439c62f993SKevin Wang break;
22447f963d9fSAlex Deucher case AMDGPU_PP_SENSOR_MEM_LOAD:
22457d6c13efSEvan Quan ret = navi1x_get_smu_metrics_data(smu,
2246fae3a572SAlex Deucher METRICS_AVERAGE_MEMACTIVITY,
2247fae3a572SAlex Deucher (uint32_t *)data);
2248fae3a572SAlex Deucher *size = 4;
2249fae3a572SAlex Deucher break;
2250d573bb21SKevin Wang case AMDGPU_PP_SENSOR_GPU_LOAD:
22517d6c13efSEvan Quan ret = navi1x_get_smu_metrics_data(smu,
2252fae3a572SAlex Deucher METRICS_AVERAGE_GFXACTIVITY,
2253fae3a572SAlex Deucher (uint32_t *)data);
2254d573bb21SKevin Wang *size = 4;
2255d573bb21SKevin Wang break;
22569366c2e8SMario Limonciello case AMDGPU_PP_SENSOR_GPU_AVG_POWER:
22577d6c13efSEvan Quan ret = navi1x_get_smu_metrics_data(smu,
2258fae3a572SAlex Deucher METRICS_AVERAGE_SOCKETPOWER,
2259fae3a572SAlex Deucher (uint32_t *)data);
2260564c4c7fSKevin Wang *size = 4;
2261564c4c7fSKevin Wang break;
2262e5aa29ceSKevin Wang case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
22637d6c13efSEvan Quan ret = navi1x_get_smu_metrics_data(smu,
2264fae3a572SAlex Deucher METRICS_TEMPERATURE_HOTSPOT,
2265fae3a572SAlex Deucher (uint32_t *)data);
2266fae3a572SAlex Deucher *size = 4;
2267fae3a572SAlex Deucher break;
2268e5aa29ceSKevin Wang case AMDGPU_PP_SENSOR_EDGE_TEMP:
22697d6c13efSEvan Quan ret = navi1x_get_smu_metrics_data(smu,
2270fae3a572SAlex Deucher METRICS_TEMPERATURE_EDGE,
2271fae3a572SAlex Deucher (uint32_t *)data);
2272fae3a572SAlex Deucher *size = 4;
2273fae3a572SAlex Deucher break;
2274e5aa29ceSKevin Wang case AMDGPU_PP_SENSOR_MEM_TEMP:
22757d6c13efSEvan Quan ret = navi1x_get_smu_metrics_data(smu,
2276fae3a572SAlex Deucher METRICS_TEMPERATURE_MEM,
2277fae3a572SAlex Deucher (uint32_t *)data);
2278e5aa29ceSKevin Wang *size = 4;
2279e5aa29ceSKevin Wang break;
2280e0f9e936SEvan Quan case AMDGPU_PP_SENSOR_GFX_MCLK:
2281e0f9e936SEvan Quan ret = navi10_get_current_clk_freq_by_table(smu, SMU_UCLK, (uint32_t *)data);
2282e0f9e936SEvan Quan *(uint32_t *)data *= 100;
2283e0f9e936SEvan Quan *size = 4;
2284e0f9e936SEvan Quan break;
2285e0f9e936SEvan Quan case AMDGPU_PP_SENSOR_GFX_SCLK:
22867d6c13efSEvan Quan ret = navi1x_get_smu_metrics_data(smu, METRICS_AVERAGE_GFXCLK, (uint32_t *)data);
2287e0f9e936SEvan Quan *(uint32_t *)data *= 100;
2288e0f9e936SEvan Quan *size = 4;
2289e0f9e936SEvan Quan break;
2290b2febc99SEvan Quan case AMDGPU_PP_SENSOR_VDDGFX:
2291b2febc99SEvan Quan ret = smu_v11_0_get_gfx_vdd(smu, (uint32_t *)data);
2292b2febc99SEvan Quan *size = 4;
2293b2febc99SEvan Quan break;
229447f1724dSMario Limonciello case AMDGPU_PP_SENSOR_GPU_INPUT_POWER:
22959c62f993SKevin Wang default:
2296b2febc99SEvan Quan ret = -EOPNOTSUPP;
2297b2febc99SEvan Quan break;
22989c62f993SKevin Wang }
22999c62f993SKevin Wang
23009c62f993SKevin Wang return ret;
23019c62f993SKevin Wang }
23029c62f993SKevin Wang
navi10_get_uclk_dpm_states(struct smu_context * smu,uint32_t * clocks_in_khz,uint32_t * num_states)2303f4b3295fShersen wu static int navi10_get_uclk_dpm_states(struct smu_context *smu, uint32_t *clocks_in_khz, uint32_t *num_states)
2304f4b3295fShersen wu {
2305f4b3295fShersen wu uint32_t num_discrete_levels = 0;
2306f4b3295fShersen wu uint16_t *dpm_levels = NULL;
2307f4b3295fShersen wu uint16_t i = 0;
2308f4b3295fShersen wu struct smu_table_context *table_context = &smu->smu_table;
2309f4b3295fShersen wu PPTable_t *driver_ppt = NULL;
2310f4b3295fShersen wu
2311f4b3295fShersen wu if (!clocks_in_khz || !num_states || !table_context->driver_pptable)
2312f4b3295fShersen wu return -EINVAL;
2313f4b3295fShersen wu
2314f4b3295fShersen wu driver_ppt = table_context->driver_pptable;
2315f4b3295fShersen wu num_discrete_levels = driver_ppt->DpmDescriptor[PPCLK_UCLK].NumDiscreteLevels;
2316f4b3295fShersen wu dpm_levels = driver_ppt->FreqTableUclk;
2317f4b3295fShersen wu
2318f4b3295fShersen wu if (num_discrete_levels == 0 || dpm_levels == NULL)
2319f4b3295fShersen wu return -EINVAL;
2320f4b3295fShersen wu
2321f4b3295fShersen wu *num_states = num_discrete_levels;
2322f4b3295fShersen wu for (i = 0; i < num_discrete_levels; i++) {
2323f4b3295fShersen wu /* convert to khz */
2324f4b3295fShersen wu *clocks_in_khz = (*dpm_levels) * 1000;
2325f4b3295fShersen wu clocks_in_khz++;
2326f4b3295fShersen wu dpm_levels++;
2327f4b3295fShersen wu }
2328f4b3295fShersen wu
2329f4b3295fShersen wu return 0;
2330f4b3295fShersen wu }
2331f4b3295fShersen wu
navi10_get_thermal_temperature_range(struct smu_context * smu,struct smu_temperature_range * range)23327a816371SKevin Wang static int navi10_get_thermal_temperature_range(struct smu_context *smu,
23337a816371SKevin Wang struct smu_temperature_range *range)
23347a816371SKevin Wang {
2335e02e4d51SEvan Quan struct smu_table_context *table_context = &smu->smu_table;
2336e02e4d51SEvan Quan struct smu_11_0_powerplay_table *powerplay_table =
2337e02e4d51SEvan Quan table_context->power_play_table;
2338cbf3f132SEvan Quan PPTable_t *pptable = smu->smu_table.driver_pptable;
23397a816371SKevin Wang
2340cbf3f132SEvan Quan if (!range)
23417a816371SKevin Wang return -EINVAL;
23427a816371SKevin Wang
23430540ecedSEvan Quan memcpy(range, &smu11_thermal_policy[0], sizeof(struct smu_temperature_range));
23440540ecedSEvan Quan
2345cbf3f132SEvan Quan range->max = pptable->TedgeLimit *
2346cbf3f132SEvan Quan SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
2347cbf3f132SEvan Quan range->edge_emergency_max = (pptable->TedgeLimit + CTF_OFFSET_EDGE) *
2348cbf3f132SEvan Quan SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
2349cbf3f132SEvan Quan range->hotspot_crit_max = pptable->ThotspotLimit *
2350cbf3f132SEvan Quan SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
2351cbf3f132SEvan Quan range->hotspot_emergency_max = (pptable->ThotspotLimit + CTF_OFFSET_HOTSPOT) *
2352cbf3f132SEvan Quan SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
2353cbf3f132SEvan Quan range->mem_crit_max = pptable->TmemLimit *
2354cbf3f132SEvan Quan SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
2355cbf3f132SEvan Quan range->mem_emergency_max = (pptable->TmemLimit + CTF_OFFSET_MEM)*
2356a056ddceSEvan Quan SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
2357e02e4d51SEvan Quan range->software_shutdown_temp = powerplay_table->software_shutdown_temp;
23587a816371SKevin Wang
23597a816371SKevin Wang return 0;
23607a816371SKevin Wang }
23617a816371SKevin Wang
navi10_display_disable_memory_clock_switch(struct smu_context * smu,bool disable_memory_clock_switch)23626e92e156SKenneth Feng static int navi10_display_disable_memory_clock_switch(struct smu_context *smu,
23636e92e156SKenneth Feng bool disable_memory_clock_switch)
23646e92e156SKenneth Feng {
23656e92e156SKenneth Feng int ret = 0;
23666e92e156SKenneth Feng struct smu_11_0_max_sustainable_clocks *max_sustainable_clocks =
23676e92e156SKenneth Feng (struct smu_11_0_max_sustainable_clocks *)
23686e92e156SKenneth Feng smu->smu_table.max_sustainable_clocks;
23696e92e156SKenneth Feng uint32_t min_memory_clock = smu->hard_min_uclk_req_from_dal;
23706e92e156SKenneth Feng uint32_t max_memory_clock = max_sustainable_clocks->uclock;
23716e92e156SKenneth Feng
23726e92e156SKenneth Feng if (smu->disable_uclk_switch == disable_memory_clock_switch)
23736e92e156SKenneth Feng return 0;
23746e92e156SKenneth Feng
23756e92e156SKenneth Feng if (disable_memory_clock_switch)
2376661b94f5SEvan Quan ret = smu_v11_0_set_hard_freq_limited_range(smu, SMU_UCLK, max_memory_clock, 0);
23776e92e156SKenneth Feng else
2378661b94f5SEvan Quan ret = smu_v11_0_set_hard_freq_limited_range(smu, SMU_UCLK, min_memory_clock, 0);
23796e92e156SKenneth Feng
23806e92e156SKenneth Feng if (!ret)
23816e92e156SKenneth Feng smu->disable_uclk_switch = disable_memory_clock_switch;
23826e92e156SKenneth Feng
23836e92e156SKenneth Feng return ret;
23846e92e156SKenneth Feng }
23856e92e156SKenneth Feng
navi10_get_power_limit(struct smu_context * smu,uint32_t * current_power_limit,uint32_t * default_power_limit,uint32_t * max_power_limit,uint32_t * min_power_limit)2386488f211dSEvan Quan static int navi10_get_power_limit(struct smu_context *smu,
2387488f211dSEvan Quan uint32_t *current_power_limit,
2388488f211dSEvan Quan uint32_t *default_power_limit,
238919589468SMa Jun uint32_t *max_power_limit,
239019589468SMa Jun uint32_t *min_power_limit)
2391b4af964eSEvan Quan {
23921e239fddSEvan Quan struct smu_11_0_powerplay_table *powerplay_table =
23931e239fddSEvan Quan (struct smu_11_0_powerplay_table *)smu->smu_table.power_play_table;
2394549db526SEvan Quan struct smu_11_0_overdrive_table *od_settings = smu->od_settings;
2395b4af964eSEvan Quan PPTable_t *pptable = smu->smu_table.driver_pptable;
239608ae9ef8SMa Jun uint32_t power_limit, od_percent_upper = 0, od_percent_lower = 0;
2397b4af964eSEvan Quan
23981e239fddSEvan Quan if (smu_v11_0_get_current_power_limit(smu, &power_limit)) {
2399b4af964eSEvan Quan /* the last hope to figure out the ppt limit */
2400b4af964eSEvan Quan if (!pptable) {
2401d9811cfcSEvan Quan dev_err(smu->adev->dev, "Cannot get PPT limit due to pptable missing!");
2402b4af964eSEvan Quan return -EINVAL;
2403b4af964eSEvan Quan }
24041e239fddSEvan Quan power_limit =
2405b4af964eSEvan Quan pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0];
2406b4af964eSEvan Quan }
2407b4af964eSEvan Quan
2408488f211dSEvan Quan if (current_power_limit)
2409488f211dSEvan Quan *current_power_limit = power_limit;
2410488f211dSEvan Quan if (default_power_limit)
2411488f211dSEvan Quan *default_power_limit = power_limit;
2412488f211dSEvan Quan
241308ae9ef8SMa Jun if (powerplay_table) {
2414549db526SEvan Quan if (smu->od_enabled &&
2415e1771825SMa Jun navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_POWER_LIMIT)) {
241619589468SMa Jun od_percent_upper = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_11_0_ODSETTING_POWERPERCENTAGE]);
2417f9e90b1aSMa Jun od_percent_lower = le32_to_cpu(powerplay_table->overdrive_table.min[SMU_11_0_ODSETTING_POWERPERCENTAGE]);
2418e1771825SMa Jun } else if (navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_POWER_LIMIT)) {
2419e1771825SMa Jun od_percent_upper = 0;
2420e1771825SMa Jun od_percent_lower = le32_to_cpu(powerplay_table->overdrive_table.min[SMU_11_0_ODSETTING_POWERPERCENTAGE]);
2421e1771825SMa Jun }
242208ae9ef8SMa Jun }
2423488f211dSEvan Quan
242419589468SMa Jun dev_dbg(smu->adev->dev, "od percent upper:%d, od percent lower:%d (default power: %d)\n",
242519589468SMa Jun od_percent_upper, od_percent_lower, power_limit);
242619589468SMa Jun
242719589468SMa Jun if (max_power_limit) {
242819589468SMa Jun *max_power_limit = power_limit * (100 + od_percent_upper);
242919589468SMa Jun *max_power_limit /= 100;
243019589468SMa Jun }
243119589468SMa Jun
243219589468SMa Jun if (min_power_limit) {
243319589468SMa Jun *min_power_limit = power_limit * (100 - od_percent_lower);
243419589468SMa Jun *min_power_limit /= 100;
2435488f211dSEvan Quan }
2436b4af964eSEvan Quan
2437b4af964eSEvan Quan return 0;
2438b4af964eSEvan Quan }
2439b4af964eSEvan Quan
navi10_update_pcie_parameters(struct smu_context * smu,uint8_t pcie_gen_cap,uint8_t pcie_width_cap)2440372120f0SKenneth Feng static int navi10_update_pcie_parameters(struct smu_context *smu,
24417752ccf8SMario Limonciello uint8_t pcie_gen_cap,
24427752ccf8SMario Limonciello uint8_t pcie_width_cap)
2443372120f0SKenneth Feng {
24440b590970SEvan Quan struct smu_11_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context;
2445372120f0SKenneth Feng PPTable_t *pptable = smu->smu_table.driver_pptable;
2446372120f0SKenneth Feng uint32_t smu_pcie_arg;
24471a18607cSKenneth Feng int ret = 0;
24481a18607cSKenneth Feng int i;
2449372120f0SKenneth Feng
24500b590970SEvan Quan /* lclk dpm table setup */
24510b590970SEvan Quan for (i = 0; i < MAX_PCIE_CONF; i++) {
24520b590970SEvan Quan dpm_context->dpm_tables.pcie_table.pcie_gen[i] = pptable->PcieGenSpeed[i];
24530b590970SEvan Quan dpm_context->dpm_tables.pcie_table.pcie_lane[i] = pptable->PcieLaneCount[i];
24540b590970SEvan Quan }
2455fddbfb1cSKenneth Feng
2456372120f0SKenneth Feng for (i = 0; i < NUM_LINK_LEVELS; i++) {
24571a18607cSKenneth Feng if (pptable->PcieGenSpeed[i] > pcie_gen_cap ||
24581a18607cSKenneth Feng pptable->PcieLaneCount[i] > pcie_width_cap) {
2459*1b92cb40SKenneth Feng dpm_context->dpm_tables.pcie_table.pcie_gen[i] =
2460*1b92cb40SKenneth Feng pptable->PcieGenSpeed[i] > pcie_gen_cap ?
2461*1b92cb40SKenneth Feng pcie_gen_cap : pptable->PcieGenSpeed[i];
2462*1b92cb40SKenneth Feng dpm_context->dpm_tables.pcie_table.pcie_lane[i] =
2463*1b92cb40SKenneth Feng pptable->PcieLaneCount[i] > pcie_width_cap ?
2464*1b92cb40SKenneth Feng pcie_width_cap : pptable->PcieLaneCount[i];
24651a18607cSKenneth Feng smu_pcie_arg = i << 16;
24661a18607cSKenneth Feng smu_pcie_arg |= pcie_gen_cap << 8;
24671a18607cSKenneth Feng smu_pcie_arg |= pcie_width_cap;
246866c86828SEvan Quan ret = smu_cmn_send_smc_msg_with_param(smu,
2469372120f0SKenneth Feng SMU_MSG_OverridePcieParameters,
24701c58267cSMatt Coffin smu_pcie_arg,
24711c58267cSMatt Coffin NULL);
2472fddbfb1cSKenneth Feng if (ret)
24731a18607cSKenneth Feng break;
24741a18607cSKenneth Feng }
2475fddbfb1cSKenneth Feng }
2476fddbfb1cSKenneth Feng
24771a18607cSKenneth Feng return ret;
247821677d08SMatt Coffin }
247921677d08SMatt Coffin
navi10_dump_od_table(struct smu_context * smu,OverDriveTable_t * od_table)2480d9811cfcSEvan Quan static inline void navi10_dump_od_table(struct smu_context *smu,
2481d9811cfcSEvan Quan OverDriveTable_t *od_table)
2482d9811cfcSEvan Quan {
2483d9811cfcSEvan Quan dev_dbg(smu->adev->dev, "OD: Gfxclk: (%d, %d)\n", od_table->GfxclkFmin, od_table->GfxclkFmax);
2484d9811cfcSEvan Quan dev_dbg(smu->adev->dev, "OD: Gfx1: (%d, %d)\n", od_table->GfxclkFreq1, od_table->GfxclkVolt1);
2485d9811cfcSEvan Quan dev_dbg(smu->adev->dev, "OD: Gfx2: (%d, %d)\n", od_table->GfxclkFreq2, od_table->GfxclkVolt2);
2486d9811cfcSEvan Quan dev_dbg(smu->adev->dev, "OD: Gfx3: (%d, %d)\n", od_table->GfxclkFreq3, od_table->GfxclkVolt3);
2487d9811cfcSEvan Quan dev_dbg(smu->adev->dev, "OD: UclkFmax: %d\n", od_table->UclkFmax);
2488d9811cfcSEvan Quan dev_dbg(smu->adev->dev, "OD: OverDrivePct: %d\n", od_table->OverDrivePct);
248921677d08SMatt Coffin }
249021677d08SMatt Coffin
navi10_od_setting_check_range(struct smu_context * smu,struct smu_11_0_overdrive_table * od_table,enum SMU_11_0_ODSETTING_ID setting,uint32_t value)2491d9811cfcSEvan Quan static int navi10_od_setting_check_range(struct smu_context *smu,
2492d9811cfcSEvan Quan struct smu_11_0_overdrive_table *od_table,
2493d9811cfcSEvan Quan enum SMU_11_0_ODSETTING_ID setting,
2494d9811cfcSEvan Quan uint32_t value)
249521677d08SMatt Coffin {
249621677d08SMatt Coffin if (value < od_table->min[setting]) {
2497d9811cfcSEvan Quan dev_warn(smu->adev->dev, "OD setting (%d, %d) is less than the minimum allowed (%d)\n", setting, value, od_table->min[setting]);
249821677d08SMatt Coffin return -EINVAL;
249921677d08SMatt Coffin }
250021677d08SMatt Coffin if (value > od_table->max[setting]) {
2501d9811cfcSEvan Quan dev_warn(smu->adev->dev, "OD setting (%d, %d) is greater than the maximum allowed (%d)\n", setting, value, od_table->max[setting]);
250221677d08SMatt Coffin return -EINVAL;
250321677d08SMatt Coffin }
250421677d08SMatt Coffin return 0;
250521677d08SMatt Coffin }
250621677d08SMatt Coffin
navi10_overdrive_get_gfx_clk_base_voltage(struct smu_context * smu,uint16_t * voltage,uint32_t freq)25070531aa6eSAlex Deucher static int navi10_overdrive_get_gfx_clk_base_voltage(struct smu_context *smu,
25080531aa6eSAlex Deucher uint16_t *voltage,
25090531aa6eSAlex Deucher uint32_t freq)
25100531aa6eSAlex Deucher {
25110531aa6eSAlex Deucher uint32_t param = (freq & 0xFFFF) | (PPCLK_GFXCLK << 16);
25120531aa6eSAlex Deucher uint32_t value = 0;
25130531aa6eSAlex Deucher int ret;
25140531aa6eSAlex Deucher
251566c86828SEvan Quan ret = smu_cmn_send_smc_msg_with_param(smu,
25160531aa6eSAlex Deucher SMU_MSG_GetVoltageByDpm,
25171c58267cSMatt Coffin param,
25181c58267cSMatt Coffin &value);
25190531aa6eSAlex Deucher if (ret) {
2520d9811cfcSEvan Quan dev_err(smu->adev->dev, "[GetBaseVoltage] failed to get GFXCLK AVFS voltage from SMU!");
25210531aa6eSAlex Deucher return ret;
25220531aa6eSAlex Deucher }
25230531aa6eSAlex Deucher
25240531aa6eSAlex Deucher *voltage = (uint16_t)value;
25250531aa6eSAlex Deucher
25260531aa6eSAlex Deucher return 0;
25270531aa6eSAlex Deucher }
25280531aa6eSAlex Deucher
navi10_baco_enter(struct smu_context * smu)252913d75eadSEvan Quan static int navi10_baco_enter(struct smu_context *smu)
253013d75eadSEvan Quan {
253113d75eadSEvan Quan struct amdgpu_device *adev = smu->adev;
253213d75eadSEvan Quan
2533be68d44bSEvan Quan /*
2534be68d44bSEvan Quan * This aims the case below:
2535be68d44bSEvan Quan * amdgpu driver loaded -> runpm suspend kicked -> sound driver loaded
2536be68d44bSEvan Quan *
2537be68d44bSEvan Quan * For NAVI10 and later ASICs, we rely on PMFW to handle the runpm. To
2538be68d44bSEvan Quan * make that possible, PMFW needs to acknowledge the dstate transition
2539be68d44bSEvan Quan * process for both gfx(function 0) and audio(function 1) function of
2540be68d44bSEvan Quan * the ASIC.
2541be68d44bSEvan Quan *
2542be68d44bSEvan Quan * The PCI device's initial runpm status is RUNPM_SUSPENDED. So as the
2543be68d44bSEvan Quan * device representing the audio function of the ASIC. And that means
2544be68d44bSEvan Quan * even if the sound driver(snd_hda_intel) was not loaded yet, it's still
2545be68d44bSEvan Quan * possible runpm suspend kicked on the ASIC. However without the dstate
2546be68d44bSEvan Quan * transition notification from audio function, pmfw cannot handle the
2547be68d44bSEvan Quan * BACO in/exit correctly. And that will cause driver hang on runpm
2548be68d44bSEvan Quan * resuming.
2549be68d44bSEvan Quan *
2550be68d44bSEvan Quan * To address this, we revert to legacy message way(driver masters the
2551be68d44bSEvan Quan * timing for BACO in/exit) on sound driver missing.
2552be68d44bSEvan Quan */
2553be68d44bSEvan Quan if (adev->in_runpm && smu_cmn_is_audio_func_enabled(adev))
255413d75eadSEvan Quan return smu_v11_0_baco_set_armd3_sequence(smu, BACO_SEQ_BACO);
255513d75eadSEvan Quan else
255613d75eadSEvan Quan return smu_v11_0_baco_enter(smu);
255713d75eadSEvan Quan }
255813d75eadSEvan Quan
navi10_baco_exit(struct smu_context * smu)255913d75eadSEvan Quan static int navi10_baco_exit(struct smu_context *smu)
256013d75eadSEvan Quan {
256113d75eadSEvan Quan struct amdgpu_device *adev = smu->adev;
256213d75eadSEvan Quan
2563be68d44bSEvan Quan if (adev->in_runpm && smu_cmn_is_audio_func_enabled(adev)) {
256413d75eadSEvan Quan /* Wait for PMFW handling for the Dstate change */
256513d75eadSEvan Quan msleep(10);
256613d75eadSEvan Quan return smu_v11_0_baco_set_armd3_sequence(smu, BACO_SEQ_ULPS);
256713d75eadSEvan Quan } else {
256813d75eadSEvan Quan return smu_v11_0_baco_exit(smu);
256913d75eadSEvan Quan }
257013d75eadSEvan Quan }
257113d75eadSEvan Quan
navi10_set_default_od_settings(struct smu_context * smu)2572792f80d1SEvan Quan static int navi10_set_default_od_settings(struct smu_context *smu)
2573792f80d1SEvan Quan {
2574792f80d1SEvan Quan OverDriveTable_t *od_table =
2575792f80d1SEvan Quan (OverDriveTable_t *)smu->smu_table.overdrive_table;
2576792f80d1SEvan Quan OverDriveTable_t *boot_od_table =
2577792f80d1SEvan Quan (OverDriveTable_t *)smu->smu_table.boot_overdrive_table;
257892cf0508SEvan Quan OverDriveTable_t *user_od_table =
257992cf0508SEvan Quan (OverDriveTable_t *)smu->smu_table.user_overdrive_table;
258021677d08SMatt Coffin int ret = 0;
258121677d08SMatt Coffin
258292cf0508SEvan Quan /*
258392cf0508SEvan Quan * For S3/S4/Runpm resume, no need to setup those overdrive tables again as
258492cf0508SEvan Quan * - either they already have the default OD settings got during cold bootup
258592cf0508SEvan Quan * - or they have some user customized OD settings which cannot be overwritten
258692cf0508SEvan Quan */
258792cf0508SEvan Quan if (smu->adev->in_suspend)
258892cf0508SEvan Quan return 0;
258992cf0508SEvan Quan
259092cf0508SEvan Quan ret = smu_cmn_update_table(smu, SMU_TABLE_OVERDRIVE, 0, (void *)boot_od_table, false);
2591792f80d1SEvan Quan if (ret) {
2592d9811cfcSEvan Quan dev_err(smu->adev->dev, "Failed to get overdrive table!\n");
259321677d08SMatt Coffin return ret;
2594792f80d1SEvan Quan }
259521677d08SMatt Coffin
259692cf0508SEvan Quan if (!boot_od_table->GfxclkVolt1) {
25970531aa6eSAlex Deucher ret = navi10_overdrive_get_gfx_clk_base_voltage(smu,
259892cf0508SEvan Quan &boot_od_table->GfxclkVolt1,
259992cf0508SEvan Quan boot_od_table->GfxclkFreq1);
26000531aa6eSAlex Deucher if (ret)
2601792f80d1SEvan Quan return ret;
260221677d08SMatt Coffin }
260321677d08SMatt Coffin
260492cf0508SEvan Quan if (!boot_od_table->GfxclkVolt2) {
26050531aa6eSAlex Deucher ret = navi10_overdrive_get_gfx_clk_base_voltage(smu,
260692cf0508SEvan Quan &boot_od_table->GfxclkVolt2,
260792cf0508SEvan Quan boot_od_table->GfxclkFreq2);
26080531aa6eSAlex Deucher if (ret)
2609792f80d1SEvan Quan return ret;
26100531aa6eSAlex Deucher }
26110531aa6eSAlex Deucher
261292cf0508SEvan Quan if (!boot_od_table->GfxclkVolt3) {
26130531aa6eSAlex Deucher ret = navi10_overdrive_get_gfx_clk_base_voltage(smu,
261492cf0508SEvan Quan &boot_od_table->GfxclkVolt3,
261592cf0508SEvan Quan boot_od_table->GfxclkFreq3);
26160531aa6eSAlex Deucher if (ret)
2617372120f0SKenneth Feng return ret;
2618372120f0SKenneth Feng }
2619372120f0SKenneth Feng
262092cf0508SEvan Quan navi10_dump_od_table(smu, boot_od_table);
2621792f80d1SEvan Quan
262292cf0508SEvan Quan memcpy(od_table, boot_od_table, sizeof(OverDriveTable_t));
262392cf0508SEvan Quan memcpy(user_od_table, boot_od_table, sizeof(OverDriveTable_t));
2624792f80d1SEvan Quan
2625792f80d1SEvan Quan return 0;
2626792f80d1SEvan Quan }
2627792f80d1SEvan Quan
navi10_od_edit_dpm_table(struct smu_context * smu,enum PP_OD_DPM_TABLE_COMMAND type,long input[],uint32_t size)26281e3a58dfSRan Sun static int navi10_od_edit_dpm_table(struct smu_context *smu, enum PP_OD_DPM_TABLE_COMMAND type, long input[], uint32_t size)
26291e3a58dfSRan Sun {
263021677d08SMatt Coffin int i;
263121677d08SMatt Coffin int ret = 0;
263221677d08SMatt Coffin struct smu_table_context *table_context = &smu->smu_table;
263321677d08SMatt Coffin OverDriveTable_t *od_table;
263421677d08SMatt Coffin struct smu_11_0_overdrive_table *od_settings;
263566107132SMatt Coffin enum SMU_11_0_ODSETTING_ID freq_setting, voltage_setting;
263666107132SMatt Coffin uint16_t *freq_ptr, *voltage_ptr;
263721677d08SMatt Coffin od_table = (OverDriveTable_t *)table_context->overdrive_table;
263821677d08SMatt Coffin
263921677d08SMatt Coffin if (!smu->od_enabled) {
2640d9811cfcSEvan Quan dev_warn(smu->adev->dev, "OverDrive is not enabled!\n");
264121677d08SMatt Coffin return -EINVAL;
264221677d08SMatt Coffin }
264321677d08SMatt Coffin
264421677d08SMatt Coffin if (!smu->od_settings) {
2645d9811cfcSEvan Quan dev_err(smu->adev->dev, "OD board limits are not set!\n");
264621677d08SMatt Coffin return -ENOENT;
264721677d08SMatt Coffin }
264821677d08SMatt Coffin
264921677d08SMatt Coffin od_settings = smu->od_settings;
265021677d08SMatt Coffin
265121677d08SMatt Coffin switch (type) {
265221677d08SMatt Coffin case PP_OD_EDIT_SCLK_VDDC_TABLE:
2653e33a8cfdSAlex Deucher if (!navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_GFXCLK_LIMITS)) {
2654d9811cfcSEvan Quan dev_warn(smu->adev->dev, "GFXCLK_LIMITS not supported!\n");
265521677d08SMatt Coffin return -ENOTSUPP;
265621677d08SMatt Coffin }
265721677d08SMatt Coffin if (!table_context->overdrive_table) {
2658d9811cfcSEvan Quan dev_err(smu->adev->dev, "Overdrive is not initialized\n");
265921677d08SMatt Coffin return -EINVAL;
266021677d08SMatt Coffin }
266121677d08SMatt Coffin for (i = 0; i < size; i += 2) {
266221677d08SMatt Coffin if (i + 2 > size) {
2663d9811cfcSEvan Quan dev_info(smu->adev->dev, "invalid number of input parameters %d\n", size);
266421677d08SMatt Coffin return -EINVAL;
266521677d08SMatt Coffin }
266621677d08SMatt Coffin switch (input[i]) {
266721677d08SMatt Coffin case 0:
266821677d08SMatt Coffin freq_setting = SMU_11_0_ODSETTING_GFXCLKFMIN;
266921677d08SMatt Coffin freq_ptr = &od_table->GfxclkFmin;
267021677d08SMatt Coffin if (input[i + 1] > od_table->GfxclkFmax) {
2671d9811cfcSEvan Quan dev_info(smu->adev->dev, "GfxclkFmin (%ld) must be <= GfxclkFmax (%u)!\n",
267221677d08SMatt Coffin input[i + 1],
267321677d08SMatt Coffin od_table->GfxclkFmin);
267421677d08SMatt Coffin return -EINVAL;
267521677d08SMatt Coffin }
267621677d08SMatt Coffin break;
267721677d08SMatt Coffin case 1:
267821677d08SMatt Coffin freq_setting = SMU_11_0_ODSETTING_GFXCLKFMAX;
267921677d08SMatt Coffin freq_ptr = &od_table->GfxclkFmax;
268021677d08SMatt Coffin if (input[i + 1] < od_table->GfxclkFmin) {
2681d9811cfcSEvan Quan dev_info(smu->adev->dev, "GfxclkFmax (%ld) must be >= GfxclkFmin (%u)!\n",
268221677d08SMatt Coffin input[i + 1],
268321677d08SMatt Coffin od_table->GfxclkFmax);
268421677d08SMatt Coffin return -EINVAL;
268521677d08SMatt Coffin }
268621677d08SMatt Coffin break;
268721677d08SMatt Coffin default:
2688d9811cfcSEvan Quan dev_info(smu->adev->dev, "Invalid SCLK_VDDC_TABLE index: %ld\n", input[i]);
2689d9811cfcSEvan Quan dev_info(smu->adev->dev, "Supported indices: [0:min,1:max]\n");
269021677d08SMatt Coffin return -EINVAL;
269121677d08SMatt Coffin }
2692d9811cfcSEvan Quan ret = navi10_od_setting_check_range(smu, od_settings, freq_setting, input[i + 1]);
269321677d08SMatt Coffin if (ret)
269421677d08SMatt Coffin return ret;
269521677d08SMatt Coffin *freq_ptr = input[i + 1];
269621677d08SMatt Coffin }
269721677d08SMatt Coffin break;
269821677d08SMatt Coffin case PP_OD_EDIT_MCLK_VDDC_TABLE:
2699e33a8cfdSAlex Deucher if (!navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_UCLK_MAX)) {
2700d9811cfcSEvan Quan dev_warn(smu->adev->dev, "UCLK_MAX not supported!\n");
270121677d08SMatt Coffin return -ENOTSUPP;
270221677d08SMatt Coffin }
270321677d08SMatt Coffin if (size < 2) {
2704d9811cfcSEvan Quan dev_info(smu->adev->dev, "invalid number of parameters: %d\n", size);
270521677d08SMatt Coffin return -EINVAL;
270621677d08SMatt Coffin }
270721677d08SMatt Coffin if (input[0] != 1) {
2708d9811cfcSEvan Quan dev_info(smu->adev->dev, "Invalid MCLK_VDDC_TABLE index: %ld\n", input[0]);
2709d9811cfcSEvan Quan dev_info(smu->adev->dev, "Supported indices: [1:max]\n");
271021677d08SMatt Coffin return -EINVAL;
271121677d08SMatt Coffin }
2712d9811cfcSEvan Quan ret = navi10_od_setting_check_range(smu, od_settings, SMU_11_0_ODSETTING_UCLKFMAX, input[1]);
271321677d08SMatt Coffin if (ret)
271421677d08SMatt Coffin return ret;
271521677d08SMatt Coffin od_table->UclkFmax = input[1];
271621677d08SMatt Coffin break;
271793c5f1f6SMatt Coffin case PP_OD_RESTORE_DEFAULT_TABLE:
271893c5f1f6SMatt Coffin if (!(table_context->overdrive_table && table_context->boot_overdrive_table)) {
2719d9811cfcSEvan Quan dev_err(smu->adev->dev, "Overdrive table was not initialized!\n");
272093c5f1f6SMatt Coffin return -EINVAL;
272193c5f1f6SMatt Coffin }
272293c5f1f6SMatt Coffin memcpy(table_context->overdrive_table, table_context->boot_overdrive_table, sizeof(OverDriveTable_t));
272393c5f1f6SMatt Coffin break;
272421677d08SMatt Coffin case PP_OD_COMMIT_DPM_TABLE:
272592cf0508SEvan Quan if (memcmp(od_table, table_context->user_overdrive_table, sizeof(OverDriveTable_t))) {
2726d9811cfcSEvan Quan navi10_dump_od_table(smu, od_table);
2727caad2613SEvan Quan ret = smu_cmn_update_table(smu, SMU_TABLE_OVERDRIVE, 0, (void *)od_table, true);
272821677d08SMatt Coffin if (ret) {
2729d9811cfcSEvan Quan dev_err(smu->adev->dev, "Failed to import overdrive table!\n");
273021677d08SMatt Coffin return ret;
273121677d08SMatt Coffin }
273292cf0508SEvan Quan memcpy(table_context->user_overdrive_table, od_table, sizeof(OverDriveTable_t));
273392cf0508SEvan Quan smu->user_dpm_profile.user_od = true;
273492cf0508SEvan Quan
273592cf0508SEvan Quan if (!memcmp(table_context->user_overdrive_table,
273692cf0508SEvan Quan table_context->boot_overdrive_table,
273792cf0508SEvan Quan sizeof(OverDriveTable_t)))
273892cf0508SEvan Quan smu->user_dpm_profile.user_od = false;
273992cf0508SEvan Quan }
274021677d08SMatt Coffin break;
274121677d08SMatt Coffin case PP_OD_EDIT_VDDC_CURVE:
2742e33a8cfdSAlex Deucher if (!navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_GFXCLK_CURVE)) {
2743d9811cfcSEvan Quan dev_warn(smu->adev->dev, "GFXCLK_CURVE not supported!\n");
274466107132SMatt Coffin return -ENOTSUPP;
274566107132SMatt Coffin }
274666107132SMatt Coffin if (size < 3) {
2747d9811cfcSEvan Quan dev_info(smu->adev->dev, "invalid number of parameters: %d\n", size);
274866107132SMatt Coffin return -EINVAL;
274966107132SMatt Coffin }
275066107132SMatt Coffin if (!od_table) {
2751d9811cfcSEvan Quan dev_info(smu->adev->dev, "Overdrive is not initialized\n");
275266107132SMatt Coffin return -EINVAL;
275366107132SMatt Coffin }
275466107132SMatt Coffin
275566107132SMatt Coffin switch (input[0]) {
275666107132SMatt Coffin case 0:
275766107132SMatt Coffin freq_setting = SMU_11_0_ODSETTING_VDDGFXCURVEFREQ_P1;
275866107132SMatt Coffin voltage_setting = SMU_11_0_ODSETTING_VDDGFXCURVEVOLTAGE_P1;
275966107132SMatt Coffin freq_ptr = &od_table->GfxclkFreq1;
276066107132SMatt Coffin voltage_ptr = &od_table->GfxclkVolt1;
276166107132SMatt Coffin break;
276266107132SMatt Coffin case 1:
276366107132SMatt Coffin freq_setting = SMU_11_0_ODSETTING_VDDGFXCURVEFREQ_P2;
276466107132SMatt Coffin voltage_setting = SMU_11_0_ODSETTING_VDDGFXCURVEVOLTAGE_P2;
276566107132SMatt Coffin freq_ptr = &od_table->GfxclkFreq2;
276666107132SMatt Coffin voltage_ptr = &od_table->GfxclkVolt2;
276766107132SMatt Coffin break;
276866107132SMatt Coffin case 2:
276966107132SMatt Coffin freq_setting = SMU_11_0_ODSETTING_VDDGFXCURVEFREQ_P3;
277066107132SMatt Coffin voltage_setting = SMU_11_0_ODSETTING_VDDGFXCURVEVOLTAGE_P3;
277166107132SMatt Coffin freq_ptr = &od_table->GfxclkFreq3;
277266107132SMatt Coffin voltage_ptr = &od_table->GfxclkVolt3;
277366107132SMatt Coffin break;
277466107132SMatt Coffin default:
2775d9811cfcSEvan Quan dev_info(smu->adev->dev, "Invalid VDDC_CURVE index: %ld\n", input[0]);
2776d9811cfcSEvan Quan dev_info(smu->adev->dev, "Supported indices: [0, 1, 2]\n");
277766107132SMatt Coffin return -EINVAL;
277866107132SMatt Coffin }
2779d9811cfcSEvan Quan ret = navi10_od_setting_check_range(smu, od_settings, freq_setting, input[1]);
278066107132SMatt Coffin if (ret)
278166107132SMatt Coffin return ret;
278266107132SMatt Coffin // Allow setting zero to disable the OverDrive VDDC curve
278366107132SMatt Coffin if (input[2] != 0) {
2784d9811cfcSEvan Quan ret = navi10_od_setting_check_range(smu, od_settings, voltage_setting, input[2]);
278566107132SMatt Coffin if (ret)
278666107132SMatt Coffin return ret;
278766107132SMatt Coffin *freq_ptr = input[1];
278866107132SMatt Coffin *voltage_ptr = ((uint16_t)input[2]) * NAVI10_VOLTAGE_SCALE;
2789d9811cfcSEvan Quan dev_dbg(smu->adev->dev, "OD: set curve %ld: (%d, %d)\n", input[0], *freq_ptr, *voltage_ptr);
279066107132SMatt Coffin } else {
279166107132SMatt Coffin // If setting 0, disable all voltage curve settings
279266107132SMatt Coffin od_table->GfxclkVolt1 = 0;
279366107132SMatt Coffin od_table->GfxclkVolt2 = 0;
279466107132SMatt Coffin od_table->GfxclkVolt3 = 0;
279566107132SMatt Coffin }
2796d9811cfcSEvan Quan navi10_dump_od_table(smu, od_table);
279766107132SMatt Coffin break;
279821677d08SMatt Coffin default:
279921677d08SMatt Coffin return -ENOSYS;
280021677d08SMatt Coffin }
280121677d08SMatt Coffin return ret;
280221677d08SMatt Coffin }
2803372120f0SKenneth Feng
navi10_run_btc(struct smu_context * smu)28040eeaa899SEvan Quan static int navi10_run_btc(struct smu_context *smu)
28050eeaa899SEvan Quan {
28060eeaa899SEvan Quan int ret = 0;
28070eeaa899SEvan Quan
280866c86828SEvan Quan ret = smu_cmn_send_smc_msg(smu, SMU_MSG_RunBtc, NULL);
28090eeaa899SEvan Quan if (ret)
2810d9811cfcSEvan Quan dev_err(smu->adev->dev, "RunBtc failed!\n");
28110eeaa899SEvan Quan
28120eeaa899SEvan Quan return ret;
28130eeaa899SEvan Quan }
28140eeaa899SEvan Quan
navi10_need_umc_cdr_workaround(struct smu_context * smu)281512f04120SEvan Quan static bool navi10_need_umc_cdr_workaround(struct smu_context *smu)
281631157341SEvan Quan {
2817eb5f69e7SEvan Quan struct amdgpu_device *adev = smu->adev;
2818eb5f69e7SEvan Quan
2819eb5f69e7SEvan Quan if (!smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT))
282031157341SEvan Quan return false;
282131157341SEvan Quan
28224e8303cfSLijo Lazar if (amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(11, 0, 0) ||
28234e8303cfSLijo Lazar amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(11, 0, 5))
282431157341SEvan Quan return true;
2825eb5f69e7SEvan Quan
282631157341SEvan Quan return false;
282731157341SEvan Quan }
282831157341SEvan Quan
navi10_umc_hybrid_cdr_workaround(struct smu_context * smu)28293646c00eSEvan Quan static int navi10_umc_hybrid_cdr_workaround(struct smu_context *smu)
28301cf8c930SEvan Quan {
28311cf8c930SEvan Quan uint32_t uclk_count, uclk_min, uclk_max;
28321cf8c930SEvan Quan int ret = 0;
28331cf8c930SEvan Quan
28343646c00eSEvan Quan /* This workaround can be applied only with uclk dpm enabled */
28353646c00eSEvan Quan if (!smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT))
28361cf8c930SEvan Quan return 0;
28371cf8c930SEvan Quan
2838d8d3493aSEvan Quan ret = smu_v11_0_get_dpm_level_count(smu, SMU_UCLK, &uclk_count);
28391cf8c930SEvan Quan if (ret)
28401cf8c930SEvan Quan return ret;
28411cf8c930SEvan Quan
28423646c00eSEvan Quan ret = smu_v11_0_get_dpm_freq_by_index(smu, SMU_UCLK, (uint16_t)(uclk_count - 1), &uclk_max);
28431cf8c930SEvan Quan if (ret)
28441cf8c930SEvan Quan return ret;
28451cf8c930SEvan Quan
28463646c00eSEvan Quan /*
28473646c00eSEvan Quan * The NAVI10_UMC_HYBRID_CDR_WORKAROUND_UCLK_THRESHOLD is 750Mhz.
28483646c00eSEvan Quan * This workaround is needed only when the max uclk frequency
28493646c00eSEvan Quan * not greater than that.
28503646c00eSEvan Quan */
28513646c00eSEvan Quan if (uclk_max > 0x2EE)
28523646c00eSEvan Quan return 0;
28533646c00eSEvan Quan
28543646c00eSEvan Quan ret = smu_v11_0_get_dpm_freq_by_index(smu, SMU_UCLK, (uint16_t)0, &uclk_min);
28551cf8c930SEvan Quan if (ret)
28561cf8c930SEvan Quan return ret;
28571cf8c930SEvan Quan
28581cf8c930SEvan Quan /* Force UCLK out of the highest DPM */
2859661b94f5SEvan Quan ret = smu_v11_0_set_hard_freq_limited_range(smu, SMU_UCLK, 0, uclk_min);
28601cf8c930SEvan Quan if (ret)
28611cf8c930SEvan Quan return ret;
28621cf8c930SEvan Quan
28631cf8c930SEvan Quan /* Revert the UCLK Hardmax */
2864661b94f5SEvan Quan ret = smu_v11_0_set_hard_freq_limited_range(smu, SMU_UCLK, 0, uclk_max);
28651cf8c930SEvan Quan if (ret)
28661cf8c930SEvan Quan return ret;
28671cf8c930SEvan Quan
28681cf8c930SEvan Quan /*
28691cf8c930SEvan Quan * In this case, SMU already disabled dummy pstate during enablement
28701cf8c930SEvan Quan * of UCLK DPM, we have to re-enabled it.
28713646c00eSEvan Quan */
28723646c00eSEvan Quan return smu_cmn_send_smc_msg(smu, SMU_MSG_DAL_ENABLE_DUMMY_PSTATE_CHANGE, NULL);
28733646c00eSEvan Quan }
28743646c00eSEvan Quan
navi10_set_dummy_pstates_table_location(struct smu_context * smu)2875665945ebSEvan Quan static int navi10_set_dummy_pstates_table_location(struct smu_context *smu)
2876665945ebSEvan Quan {
2877665945ebSEvan Quan struct smu_table_context *smu_table = &smu->smu_table;
2878665945ebSEvan Quan struct smu_table *dummy_read_table =
2879665945ebSEvan Quan &smu_table->dummy_read_1_table;
2880665945ebSEvan Quan char *dummy_table = dummy_read_table->cpu_addr;
2881665945ebSEvan Quan int ret = 0;
2882665945ebSEvan Quan uint32_t i;
2883665945ebSEvan Quan
2884665945ebSEvan Quan for (i = 0; i < 0x40000; i += 0x1000 * 2) {
2885665945ebSEvan Quan memcpy(dummy_table, &NoDbiPrbs7[0], 0x1000);
2886665945ebSEvan Quan dummy_table += 0x1000;
2887665945ebSEvan Quan memcpy(dummy_table, &DbiPrbs7[0], 0x1000);
2888665945ebSEvan Quan dummy_table += 0x1000;
2889665945ebSEvan Quan }
2890665945ebSEvan Quan
2891665945ebSEvan Quan amdgpu_asic_flush_hdp(smu->adev, NULL);
2892665945ebSEvan Quan
2893665945ebSEvan Quan ret = smu_cmn_send_smc_msg_with_param(smu,
2894665945ebSEvan Quan SMU_MSG_SET_DRIVER_DUMMY_TABLE_DRAM_ADDR_HIGH,
2895665945ebSEvan Quan upper_32_bits(dummy_read_table->mc_address),
2896665945ebSEvan Quan NULL);
2897665945ebSEvan Quan if (ret)
2898665945ebSEvan Quan return ret;
2899665945ebSEvan Quan
2900665945ebSEvan Quan return smu_cmn_send_smc_msg_with_param(smu,
2901665945ebSEvan Quan SMU_MSG_SET_DRIVER_DUMMY_TABLE_DRAM_ADDR_LOW,
2902665945ebSEvan Quan lower_32_bits(dummy_read_table->mc_address),
2903665945ebSEvan Quan NULL);
2904665945ebSEvan Quan }
2905665945ebSEvan Quan
navi10_run_umc_cdr_workaround(struct smu_context * smu)290612f04120SEvan Quan static int navi10_run_umc_cdr_workaround(struct smu_context *smu)
29073646c00eSEvan Quan {
2908bb7257b5SEvan Quan struct amdgpu_device *adev = smu->adev;
2909bb7257b5SEvan Quan uint8_t umc_fw_greater_than_v136 = false;
2910bb7257b5SEvan Quan uint8_t umc_fw_disable_cdr = false;
2911bb7257b5SEvan Quan uint32_t param;
29123646c00eSEvan Quan int ret = 0;
29133646c00eSEvan Quan
291412f04120SEvan Quan if (!navi10_need_umc_cdr_workaround(smu))
29153646c00eSEvan Quan return 0;
29163646c00eSEvan Quan
2917bb7257b5SEvan Quan /*
2918b226ef95SEvan Quan * The messages below are only supported by Navi10 42.53.0 and later
2919b226ef95SEvan Quan * PMFWs and Navi14 53.29.0 and later PMFWs.
2920bb7257b5SEvan Quan * - PPSMC_MSG_SetDriverDummyTableDramAddrHigh
2921bb7257b5SEvan Quan * - PPSMC_MSG_SetDriverDummyTableDramAddrLow
2922bb7257b5SEvan Quan * - PPSMC_MSG_GetUMCFWWA
2923bb7257b5SEvan Quan */
29244e8303cfSLijo Lazar if (((amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(11, 0, 0)) &&
2925710d9caeSYifan Zhang (smu->smc_fw_version >= 0x2a3500)) ||
29264e8303cfSLijo Lazar ((amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(11, 0, 5)) &&
2927710d9caeSYifan Zhang (smu->smc_fw_version >= 0x351D00))) {
2928bb7257b5SEvan Quan ret = smu_cmn_send_smc_msg_with_param(smu,
2929bb7257b5SEvan Quan SMU_MSG_GET_UMC_FW_WA,
2930bb7257b5SEvan Quan 0,
2931bb7257b5SEvan Quan ¶m);
29323646c00eSEvan Quan if (ret)
29333646c00eSEvan Quan return ret;
29343646c00eSEvan Quan
2935bb7257b5SEvan Quan /* First bit indicates if the UMC f/w is above v137 */
2936bb7257b5SEvan Quan umc_fw_greater_than_v136 = param & 0x1;
2937bb7257b5SEvan Quan
2938bb7257b5SEvan Quan /* Second bit indicates if hybrid-cdr is disabled */
2939bb7257b5SEvan Quan umc_fw_disable_cdr = param & 0x2;
2940bb7257b5SEvan Quan
2941bb7257b5SEvan Quan /* w/a only allowed if UMC f/w is <= 136 */
2942bb7257b5SEvan Quan if (umc_fw_greater_than_v136)
29433646c00eSEvan Quan return 0;
29443646c00eSEvan Quan
2945e4912146SEvan Quan if (umc_fw_disable_cdr) {
29464e8303cfSLijo Lazar if (amdgpu_ip_version(adev, MP1_HWIP, 0) ==
29474e8303cfSLijo Lazar IP_VERSION(11, 0, 0))
29483646c00eSEvan Quan return navi10_umc_hybrid_cdr_workaround(smu);
2949e4912146SEvan Quan } else {
2950bb7257b5SEvan Quan return navi10_set_dummy_pstates_table_location(smu);
2951e4912146SEvan Quan }
2952bb7257b5SEvan Quan } else {
29534e8303cfSLijo Lazar if (amdgpu_ip_version(adev, MP1_HWIP, 0) ==
29544e8303cfSLijo Lazar IP_VERSION(11, 0, 0))
2955bb7257b5SEvan Quan return navi10_umc_hybrid_cdr_workaround(smu);
2956bb7257b5SEvan Quan }
2957bb7257b5SEvan Quan
2958bb7257b5SEvan Quan return 0;
29591cf8c930SEvan Quan }
29601cf8c930SEvan Quan
navi10_get_legacy_gpu_metrics(struct smu_context * smu,void ** table)29617d6c13efSEvan Quan static ssize_t navi10_get_legacy_gpu_metrics(struct smu_context *smu,
29626d4ff50aSEvan Quan void **table)
29636d4ff50aSEvan Quan {
29646d4ff50aSEvan Quan struct smu_table_context *smu_table = &smu->smu_table;
296561e2d322SDavid M Nieto struct gpu_metrics_v1_3 *gpu_metrics =
296661e2d322SDavid M Nieto (struct gpu_metrics_v1_3 *)smu_table->gpu_metrics_table;
29677d6c13efSEvan Quan SmuMetrics_legacy_t metrics;
29686d4ff50aSEvan Quan int ret = 0;
29696d4ff50aSEvan Quan
2970da11407fSEvan Quan ret = smu_cmn_get_metrics_table(smu,
2971fceafc9bSEvan Quan NULL,
297262d35163SEvan Quan true);
2973da11407fSEvan Quan if (ret)
29746d4ff50aSEvan Quan return ret;
29756d4ff50aSEvan Quan
29767d6c13efSEvan Quan memcpy(&metrics, smu_table->metrics_table, sizeof(SmuMetrics_legacy_t));
29776d4ff50aSEvan Quan
297861e2d322SDavid M Nieto smu_cmn_init_soft_gpu_metrics(gpu_metrics, 1, 3);
29796d4ff50aSEvan Quan
29806d4ff50aSEvan Quan gpu_metrics->temperature_edge = metrics.TemperatureEdge;
29816d4ff50aSEvan Quan gpu_metrics->temperature_hotspot = metrics.TemperatureHotspot;
29826d4ff50aSEvan Quan gpu_metrics->temperature_mem = metrics.TemperatureMem;
29836d4ff50aSEvan Quan gpu_metrics->temperature_vrgfx = metrics.TemperatureVrGfx;
29846d4ff50aSEvan Quan gpu_metrics->temperature_vrsoc = metrics.TemperatureVrSoc;
29856d4ff50aSEvan Quan gpu_metrics->temperature_vrmem = metrics.TemperatureVrMem0;
29866d4ff50aSEvan Quan
29876d4ff50aSEvan Quan gpu_metrics->average_gfx_activity = metrics.AverageGfxActivity;
29886d4ff50aSEvan Quan gpu_metrics->average_umc_activity = metrics.AverageUclkActivity;
29896d4ff50aSEvan Quan
29906d4ff50aSEvan Quan gpu_metrics->average_socket_power = metrics.AverageSocketPower;
29916d4ff50aSEvan Quan
29926d4ff50aSEvan Quan gpu_metrics->average_gfxclk_frequency = metrics.AverageGfxclkFrequency;
29936d4ff50aSEvan Quan gpu_metrics->average_socclk_frequency = metrics.AverageSocclkFrequency;
29946d4ff50aSEvan Quan gpu_metrics->average_uclk_frequency = metrics.AverageUclkFrequency;
29956d4ff50aSEvan Quan
29967d6c13efSEvan Quan gpu_metrics->current_gfxclk = metrics.CurrClock[PPCLK_GFXCLK];
29977d6c13efSEvan Quan gpu_metrics->current_socclk = metrics.CurrClock[PPCLK_SOCCLK];
29987d6c13efSEvan Quan gpu_metrics->current_uclk = metrics.CurrClock[PPCLK_UCLK];
29997d6c13efSEvan Quan gpu_metrics->current_vclk0 = metrics.CurrClock[PPCLK_VCLK];
30007d6c13efSEvan Quan gpu_metrics->current_dclk0 = metrics.CurrClock[PPCLK_DCLK];
30017d6c13efSEvan Quan
30027d6c13efSEvan Quan gpu_metrics->throttle_status = metrics.ThrottlerStatus;
300364cdee43SGraham Sider gpu_metrics->indep_throttle_status =
300464cdee43SGraham Sider smu_cmn_get_indep_throttler_status(metrics.ThrottlerStatus,
300564cdee43SGraham Sider navi1x_throttler_map);
30067d6c13efSEvan Quan
30077d6c13efSEvan Quan gpu_metrics->current_fan_speed = metrics.CurrFanSpeed;
30087d6c13efSEvan Quan
30097d6c13efSEvan Quan gpu_metrics->pcie_link_width =
30107d6c13efSEvan Quan smu_v11_0_get_current_pcie_link_width(smu);
30117d6c13efSEvan Quan gpu_metrics->pcie_link_speed =
30127d6c13efSEvan Quan smu_v11_0_get_current_pcie_link_speed(smu);
30137d6c13efSEvan Quan
30147d6c13efSEvan Quan gpu_metrics->system_clock_counter = ktime_get_boottime_ns();
30157d6c13efSEvan Quan
301661e2d322SDavid M Nieto if (metrics.CurrGfxVoltageOffset)
301761e2d322SDavid M Nieto gpu_metrics->voltage_gfx =
301861e2d322SDavid M Nieto (155000 - 625 * metrics.CurrGfxVoltageOffset) / 100;
301961e2d322SDavid M Nieto if (metrics.CurrMemVidOffset)
302061e2d322SDavid M Nieto gpu_metrics->voltage_mem =
302161e2d322SDavid M Nieto (155000 - 625 * metrics.CurrMemVidOffset) / 100;
302261e2d322SDavid M Nieto if (metrics.CurrSocVoltageOffset)
302361e2d322SDavid M Nieto gpu_metrics->voltage_soc =
302461e2d322SDavid M Nieto (155000 - 625 * metrics.CurrSocVoltageOffset) / 100;
302561e2d322SDavid M Nieto
30267d6c13efSEvan Quan *table = (void *)gpu_metrics;
30277d6c13efSEvan Quan
302861e2d322SDavid M Nieto return sizeof(struct gpu_metrics_v1_3);
30296d4ff50aSEvan Quan }
30306d4ff50aSEvan Quan
navi10_i2c_xfer(struct i2c_adapter * i2c_adap,struct i2c_msg * msg,int num_msgs)3031af01340bSAlex Deucher static int navi10_i2c_xfer(struct i2c_adapter *i2c_adap,
3032ebe57d0cSLuben Tuikov struct i2c_msg *msg, int num_msgs)
3033af01340bSAlex Deucher {
30342f60dd50SLuben Tuikov struct amdgpu_smu_i2c_bus *smu_i2c = i2c_get_adapdata(i2c_adap);
30352f60dd50SLuben Tuikov struct amdgpu_device *adev = smu_i2c->adev;
3036ebfc2533SEvan Quan struct smu_context *smu = adev->powerplay.pp_handle;
3037ebfc2533SEvan Quan struct smu_table_context *smu_table = &smu->smu_table;
3038af01340bSAlex Deucher struct smu_table *table = &smu_table->driver_table;
3039af01340bSAlex Deucher SwI2cRequest_t *req, *res = (SwI2cRequest_t *)table->cpu_addr;
3040ebe57d0cSLuben Tuikov int i, j, r, c;
3041ebe57d0cSLuben Tuikov u16 dir;
3042af01340bSAlex Deucher
3043e281d594SAlex Deucher if (!adev->pm.dpm_enabled)
3044e281d594SAlex Deucher return -EBUSY;
3045e281d594SAlex Deucher
3046af01340bSAlex Deucher req = kzalloc(sizeof(*req), GFP_KERNEL);
3047af01340bSAlex Deucher if (!req)
3048af01340bSAlex Deucher return -ENOMEM;
3049af01340bSAlex Deucher
30502f60dd50SLuben Tuikov req->I2CcontrollerPort = smu_i2c->port;
3051af01340bSAlex Deucher req->I2CSpeed = I2C_SPEED_FAST_400K;
3052ebe57d0cSLuben Tuikov req->SlaveAddress = msg[0].addr << 1; /* wants an 8-bit address */
3053ebe57d0cSLuben Tuikov dir = msg[0].flags & I2C_M_RD;
3054af01340bSAlex Deucher
3055ebe57d0cSLuben Tuikov for (c = i = 0; i < num_msgs; i++) {
3056ebe57d0cSLuben Tuikov for (j = 0; j < msg[i].len; j++, c++) {
3057ebe57d0cSLuben Tuikov SwI2cCmd_t *cmd = &req->SwI2cCmds[c];
3058af01340bSAlex Deucher
3059af01340bSAlex Deucher if (!(msg[i].flags & I2C_M_RD)) {
3060af01340bSAlex Deucher /* write */
3061ebe57d0cSLuben Tuikov cmd->Cmd = I2C_CMD_WRITE;
3062ebe57d0cSLuben Tuikov cmd->RegisterAddr = msg[i].buf[j];
3063af01340bSAlex Deucher }
306414df5650SAndrey Grodzovsky
3065ebe57d0cSLuben Tuikov if ((dir ^ msg[i].flags) & I2C_M_RD) {
3066ebe57d0cSLuben Tuikov /* The direction changes.
3067ebe57d0cSLuben Tuikov */
3068ebe57d0cSLuben Tuikov dir = msg[i].flags & I2C_M_RD;
3069ebe57d0cSLuben Tuikov cmd->CmdConfig |= CMDCONFIG_RESTART_MASK;
3070ebe57d0cSLuben Tuikov }
3071ebe57d0cSLuben Tuikov
3072ebe57d0cSLuben Tuikov req->NumCmds++;
3073ebe57d0cSLuben Tuikov
307414df5650SAndrey Grodzovsky /*
307514df5650SAndrey Grodzovsky * Insert STOP if we are at the last byte of either last
307614df5650SAndrey Grodzovsky * message for the transaction or the client explicitly
307714df5650SAndrey Grodzovsky * requires a STOP at this particular message.
307814df5650SAndrey Grodzovsky */
3079ebe57d0cSLuben Tuikov if ((j == msg[i].len - 1) &&
3080ebe57d0cSLuben Tuikov ((i == num_msgs - 1) || (msg[i].flags & I2C_M_STOP))) {
3081ebe57d0cSLuben Tuikov cmd->CmdConfig &= ~CMDCONFIG_RESTART_MASK;
3082af01340bSAlex Deucher cmd->CmdConfig |= CMDCONFIG_STOP_MASK;
3083ebe57d0cSLuben Tuikov }
3084af01340bSAlex Deucher }
3085af01340bSAlex Deucher }
3086e0638c7aSEvan Quan mutex_lock(&adev->pm.mutex);
3087ebfc2533SEvan Quan r = smu_cmn_update_table(smu, SMU_TABLE_I2C_COMMANDS, 0, req, true);
3088af01340bSAlex Deucher if (r)
3089af01340bSAlex Deucher goto fail;
3090af01340bSAlex Deucher
3091ebe57d0cSLuben Tuikov for (c = i = 0; i < num_msgs; i++) {
3092ebe57d0cSLuben Tuikov if (!(msg[i].flags & I2C_M_RD)) {
3093ebe57d0cSLuben Tuikov c += msg[i].len;
3094ebe57d0cSLuben Tuikov continue;
3095ebe57d0cSLuben Tuikov }
3096ebe57d0cSLuben Tuikov for (j = 0; j < msg[i].len; j++, c++) {
3097ebe57d0cSLuben Tuikov SwI2cCmd_t *cmd = &res->SwI2cCmds[c];
3098af01340bSAlex Deucher
3099ebe57d0cSLuben Tuikov msg[i].buf[j] = cmd->Data;
3100af01340bSAlex Deucher }
3101af01340bSAlex Deucher }
3102ebe57d0cSLuben Tuikov r = num_msgs;
3103af01340bSAlex Deucher fail:
310462b73bd5SYang Wang mutex_unlock(&adev->pm.mutex);
3105af01340bSAlex Deucher kfree(req);
3106af01340bSAlex Deucher return r;
3107af01340bSAlex Deucher }
3108af01340bSAlex Deucher
navi10_i2c_func(struct i2c_adapter * adap)3109af01340bSAlex Deucher static u32 navi10_i2c_func(struct i2c_adapter *adap)
3110af01340bSAlex Deucher {
3111af01340bSAlex Deucher return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
3112af01340bSAlex Deucher }
3113af01340bSAlex Deucher
3114af01340bSAlex Deucher
3115af01340bSAlex Deucher static const struct i2c_algorithm navi10_i2c_algo = {
3116af01340bSAlex Deucher .master_xfer = navi10_i2c_xfer,
3117af01340bSAlex Deucher .functionality = navi10_i2c_func,
3118af01340bSAlex Deucher };
3119af01340bSAlex Deucher
312035ed2703SAndrey Grodzovsky static const struct i2c_adapter_quirks navi10_i2c_control_quirks = {
3121c0838d3aSLuben Tuikov .flags = I2C_AQ_COMB | I2C_AQ_COMB_SAME_ADDR | I2C_AQ_NO_ZERO_LEN,
312235ed2703SAndrey Grodzovsky .max_read_len = MAX_SW_I2C_COMMANDS,
312335ed2703SAndrey Grodzovsky .max_write_len = MAX_SW_I2C_COMMANDS,
312416736627SLuben Tuikov .max_comb_1st_msg_len = 2,
312516736627SLuben Tuikov .max_comb_2nd_msg_len = MAX_SW_I2C_COMMANDS - 2,
312635ed2703SAndrey Grodzovsky };
312735ed2703SAndrey Grodzovsky
navi10_i2c_control_init(struct smu_context * smu)31282f60dd50SLuben Tuikov static int navi10_i2c_control_init(struct smu_context *smu)
3129af01340bSAlex Deucher {
31302f60dd50SLuben Tuikov struct amdgpu_device *adev = smu->adev;
31312f60dd50SLuben Tuikov int res, i;
3132af01340bSAlex Deucher
31332f60dd50SLuben Tuikov for (i = 0; i < MAX_SMU_I2C_BUSES; i++) {
31342f60dd50SLuben Tuikov struct amdgpu_smu_i2c_bus *smu_i2c = &adev->pm.smu_i2c[i];
31352f60dd50SLuben Tuikov struct i2c_adapter *control = &smu_i2c->adapter;
31362f60dd50SLuben Tuikov
31372f60dd50SLuben Tuikov smu_i2c->adev = adev;
31382f60dd50SLuben Tuikov smu_i2c->port = i;
31392f60dd50SLuben Tuikov mutex_init(&smu_i2c->mutex);
3140af01340bSAlex Deucher control->owner = THIS_MODULE;
3141f4322d80SLuben Tuikov control->class = I2C_CLASS_HWMON;
3142af01340bSAlex Deucher control->dev.parent = &adev->pdev->dev;
3143af01340bSAlex Deucher control->algo = &navi10_i2c_algo;
31442f60dd50SLuben Tuikov snprintf(control->name, sizeof(control->name), "AMDGPU SMU %d", i);
314535ed2703SAndrey Grodzovsky control->quirks = &navi10_i2c_control_quirks;
31462f60dd50SLuben Tuikov i2c_set_adapdata(control, smu_i2c);
3147af01340bSAlex Deucher
3148af01340bSAlex Deucher res = i2c_add_adapter(control);
31492f60dd50SLuben Tuikov if (res) {
3150af01340bSAlex Deucher DRM_ERROR("Failed to register hw i2c, err: %d\n", res);
31512f60dd50SLuben Tuikov goto Out_err;
31522f60dd50SLuben Tuikov }
31532f60dd50SLuben Tuikov }
3154af01340bSAlex Deucher
31552f60dd50SLuben Tuikov adev->pm.ras_eeprom_i2c_bus = &adev->pm.smu_i2c[0].adapter;
31562f60dd50SLuben Tuikov adev->pm.fru_eeprom_i2c_bus = &adev->pm.smu_i2c[1].adapter;
31572f60dd50SLuben Tuikov
31582f60dd50SLuben Tuikov return 0;
31592f60dd50SLuben Tuikov Out_err:
31602f60dd50SLuben Tuikov for ( ; i >= 0; i--) {
31612f60dd50SLuben Tuikov struct amdgpu_smu_i2c_bus *smu_i2c = &adev->pm.smu_i2c[i];
31622f60dd50SLuben Tuikov struct i2c_adapter *control = &smu_i2c->adapter;
31632f60dd50SLuben Tuikov
31642f60dd50SLuben Tuikov i2c_del_adapter(control);
31652f60dd50SLuben Tuikov }
3166af01340bSAlex Deucher return res;
3167af01340bSAlex Deucher }
3168af01340bSAlex Deucher
navi10_i2c_control_fini(struct smu_context * smu)31692f60dd50SLuben Tuikov static void navi10_i2c_control_fini(struct smu_context *smu)
3170af01340bSAlex Deucher {
31712f60dd50SLuben Tuikov struct amdgpu_device *adev = smu->adev;
31722f60dd50SLuben Tuikov int i;
31732f60dd50SLuben Tuikov
31742f60dd50SLuben Tuikov for (i = 0; i < MAX_SMU_I2C_BUSES; i++) {
31752f60dd50SLuben Tuikov struct amdgpu_smu_i2c_bus *smu_i2c = &adev->pm.smu_i2c[i];
31762f60dd50SLuben Tuikov struct i2c_adapter *control = &smu_i2c->adapter;
31772f60dd50SLuben Tuikov
3178af01340bSAlex Deucher i2c_del_adapter(control);
3179af01340bSAlex Deucher }
31802f60dd50SLuben Tuikov adev->pm.ras_eeprom_i2c_bus = NULL;
31812f60dd50SLuben Tuikov adev->pm.fru_eeprom_i2c_bus = NULL;
31822f60dd50SLuben Tuikov }
3183af01340bSAlex Deucher
navi10_get_gpu_metrics(struct smu_context * smu,void ** table)31847d6c13efSEvan Quan static ssize_t navi10_get_gpu_metrics(struct smu_context *smu,
31857d6c13efSEvan Quan void **table)
31867d6c13efSEvan Quan {
31877d6c13efSEvan Quan struct smu_table_context *smu_table = &smu->smu_table;
318861e2d322SDavid M Nieto struct gpu_metrics_v1_3 *gpu_metrics =
318961e2d322SDavid M Nieto (struct gpu_metrics_v1_3 *)smu_table->gpu_metrics_table;
31907d6c13efSEvan Quan SmuMetrics_t metrics;
31917d6c13efSEvan Quan int ret = 0;
31927d6c13efSEvan Quan
3193da11407fSEvan Quan ret = smu_cmn_get_metrics_table(smu,
31947d6c13efSEvan Quan NULL,
31957d6c13efSEvan Quan true);
3196da11407fSEvan Quan if (ret)
31977d6c13efSEvan Quan return ret;
31987d6c13efSEvan Quan
31997d6c13efSEvan Quan memcpy(&metrics, smu_table->metrics_table, sizeof(SmuMetrics_t));
32007d6c13efSEvan Quan
320161e2d322SDavid M Nieto smu_cmn_init_soft_gpu_metrics(gpu_metrics, 1, 3);
32027d6c13efSEvan Quan
32037d6c13efSEvan Quan gpu_metrics->temperature_edge = metrics.TemperatureEdge;
32047d6c13efSEvan Quan gpu_metrics->temperature_hotspot = metrics.TemperatureHotspot;
32057d6c13efSEvan Quan gpu_metrics->temperature_mem = metrics.TemperatureMem;
32067d6c13efSEvan Quan gpu_metrics->temperature_vrgfx = metrics.TemperatureVrGfx;
32077d6c13efSEvan Quan gpu_metrics->temperature_vrsoc = metrics.TemperatureVrSoc;
32087d6c13efSEvan Quan gpu_metrics->temperature_vrmem = metrics.TemperatureVrMem0;
32097d6c13efSEvan Quan
32107d6c13efSEvan Quan gpu_metrics->average_gfx_activity = metrics.AverageGfxActivity;
32117d6c13efSEvan Quan gpu_metrics->average_umc_activity = metrics.AverageUclkActivity;
32127d6c13efSEvan Quan
32137d6c13efSEvan Quan gpu_metrics->average_socket_power = metrics.AverageSocketPower;
32147d6c13efSEvan Quan
32157d6c13efSEvan Quan if (metrics.AverageGfxActivity > SMU_11_0_GFX_BUSY_THRESHOLD)
32167d6c13efSEvan Quan gpu_metrics->average_gfxclk_frequency = metrics.AverageGfxclkFrequencyPreDs;
32177d6c13efSEvan Quan else
32187d6c13efSEvan Quan gpu_metrics->average_gfxclk_frequency = metrics.AverageGfxclkFrequencyPostDs;
32197d6c13efSEvan Quan
32207d6c13efSEvan Quan gpu_metrics->average_socclk_frequency = metrics.AverageSocclkFrequency;
32217d6c13efSEvan Quan gpu_metrics->average_uclk_frequency = metrics.AverageUclkFrequencyPostDs;
32227d6c13efSEvan Quan
32236d4ff50aSEvan Quan gpu_metrics->current_gfxclk = metrics.CurrClock[PPCLK_GFXCLK];
32246d4ff50aSEvan Quan gpu_metrics->current_socclk = metrics.CurrClock[PPCLK_SOCCLK];
32256d4ff50aSEvan Quan gpu_metrics->current_uclk = metrics.CurrClock[PPCLK_UCLK];
32266d4ff50aSEvan Quan gpu_metrics->current_vclk0 = metrics.CurrClock[PPCLK_VCLK];
32276d4ff50aSEvan Quan gpu_metrics->current_dclk0 = metrics.CurrClock[PPCLK_DCLK];
32286d4ff50aSEvan Quan
32296d4ff50aSEvan Quan gpu_metrics->throttle_status = metrics.ThrottlerStatus;
323064cdee43SGraham Sider gpu_metrics->indep_throttle_status =
323164cdee43SGraham Sider smu_cmn_get_indep_throttler_status(metrics.ThrottlerStatus,
323264cdee43SGraham Sider navi1x_throttler_map);
32336d4ff50aSEvan Quan
32346d4ff50aSEvan Quan gpu_metrics->current_fan_speed = metrics.CurrFanSpeed;
32356d4ff50aSEvan Quan
3236c524c1c9SEvan Quan gpu_metrics->pcie_link_width = metrics.PcieWidth;
3237c524c1c9SEvan Quan gpu_metrics->pcie_link_speed = link_speed[metrics.PcieRate];
32386d4ff50aSEvan Quan
3239de4b7cd8SKevin Wang gpu_metrics->system_clock_counter = ktime_get_boottime_ns();
3240de4b7cd8SKevin Wang
324161e2d322SDavid M Nieto if (metrics.CurrGfxVoltageOffset)
324261e2d322SDavid M Nieto gpu_metrics->voltage_gfx =
324361e2d322SDavid M Nieto (155000 - 625 * metrics.CurrGfxVoltageOffset) / 100;
324461e2d322SDavid M Nieto if (metrics.CurrMemVidOffset)
324561e2d322SDavid M Nieto gpu_metrics->voltage_mem =
324661e2d322SDavid M Nieto (155000 - 625 * metrics.CurrMemVidOffset) / 100;
324761e2d322SDavid M Nieto if (metrics.CurrSocVoltageOffset)
324861e2d322SDavid M Nieto gpu_metrics->voltage_soc =
324961e2d322SDavid M Nieto (155000 - 625 * metrics.CurrSocVoltageOffset) / 100;
325061e2d322SDavid M Nieto
32516d4ff50aSEvan Quan *table = (void *)gpu_metrics;
32526d4ff50aSEvan Quan
325361e2d322SDavid M Nieto return sizeof(struct gpu_metrics_v1_3);
32546d4ff50aSEvan Quan }
32551bc73475SAlex Deucher
navi12_get_legacy_gpu_metrics(struct smu_context * smu,void ** table)32567d6c13efSEvan Quan static ssize_t navi12_get_legacy_gpu_metrics(struct smu_context *smu,
32577d6c13efSEvan Quan void **table)
32587d6c13efSEvan Quan {
32597d6c13efSEvan Quan struct smu_table_context *smu_table = &smu->smu_table;
326061e2d322SDavid M Nieto struct gpu_metrics_v1_3 *gpu_metrics =
326161e2d322SDavid M Nieto (struct gpu_metrics_v1_3 *)smu_table->gpu_metrics_table;
32627d6c13efSEvan Quan SmuMetrics_NV12_legacy_t metrics;
32637d6c13efSEvan Quan int ret = 0;
32647d6c13efSEvan Quan
3265da11407fSEvan Quan ret = smu_cmn_get_metrics_table(smu,
32667d6c13efSEvan Quan NULL,
32677d6c13efSEvan Quan true);
3268da11407fSEvan Quan if (ret)
32697d6c13efSEvan Quan return ret;
32707d6c13efSEvan Quan
32717d6c13efSEvan Quan memcpy(&metrics, smu_table->metrics_table, sizeof(SmuMetrics_NV12_legacy_t));
32727d6c13efSEvan Quan
327361e2d322SDavid M Nieto smu_cmn_init_soft_gpu_metrics(gpu_metrics, 1, 3);
32747d6c13efSEvan Quan
32757d6c13efSEvan Quan gpu_metrics->temperature_edge = metrics.TemperatureEdge;
32767d6c13efSEvan Quan gpu_metrics->temperature_hotspot = metrics.TemperatureHotspot;
32777d6c13efSEvan Quan gpu_metrics->temperature_mem = metrics.TemperatureMem;
32787d6c13efSEvan Quan gpu_metrics->temperature_vrgfx = metrics.TemperatureVrGfx;
32797d6c13efSEvan Quan gpu_metrics->temperature_vrsoc = metrics.TemperatureVrSoc;
32807d6c13efSEvan Quan gpu_metrics->temperature_vrmem = metrics.TemperatureVrMem0;
32817d6c13efSEvan Quan
32827d6c13efSEvan Quan gpu_metrics->average_gfx_activity = metrics.AverageGfxActivity;
32837d6c13efSEvan Quan gpu_metrics->average_umc_activity = metrics.AverageUclkActivity;
32847d6c13efSEvan Quan
32857d6c13efSEvan Quan gpu_metrics->average_socket_power = metrics.AverageSocketPower;
32867d6c13efSEvan Quan
32877d6c13efSEvan Quan gpu_metrics->average_gfxclk_frequency = metrics.AverageGfxclkFrequency;
32887d6c13efSEvan Quan gpu_metrics->average_socclk_frequency = metrics.AverageSocclkFrequency;
32897d6c13efSEvan Quan gpu_metrics->average_uclk_frequency = metrics.AverageUclkFrequency;
32907d6c13efSEvan Quan
32917d6c13efSEvan Quan gpu_metrics->energy_accumulator = metrics.EnergyAccumulator;
32927d6c13efSEvan Quan gpu_metrics->average_vclk0_frequency = metrics.AverageVclkFrequency;
32937d6c13efSEvan Quan gpu_metrics->average_dclk0_frequency = metrics.AverageDclkFrequency;
32947d6c13efSEvan Quan gpu_metrics->average_mm_activity = metrics.VcnActivityPercentage;
32957d6c13efSEvan Quan
32967d6c13efSEvan Quan gpu_metrics->current_gfxclk = metrics.CurrClock[PPCLK_GFXCLK];
32977d6c13efSEvan Quan gpu_metrics->current_socclk = metrics.CurrClock[PPCLK_SOCCLK];
32987d6c13efSEvan Quan gpu_metrics->current_uclk = metrics.CurrClock[PPCLK_UCLK];
32997d6c13efSEvan Quan gpu_metrics->current_vclk0 = metrics.CurrClock[PPCLK_VCLK];
33007d6c13efSEvan Quan gpu_metrics->current_dclk0 = metrics.CurrClock[PPCLK_DCLK];
33017d6c13efSEvan Quan
33027d6c13efSEvan Quan gpu_metrics->throttle_status = metrics.ThrottlerStatus;
330364cdee43SGraham Sider gpu_metrics->indep_throttle_status =
330464cdee43SGraham Sider smu_cmn_get_indep_throttler_status(metrics.ThrottlerStatus,
330564cdee43SGraham Sider navi1x_throttler_map);
33067d6c13efSEvan Quan
33077d6c13efSEvan Quan gpu_metrics->current_fan_speed = metrics.CurrFanSpeed;
33087d6c13efSEvan Quan
33097d6c13efSEvan Quan gpu_metrics->pcie_link_width =
33107d6c13efSEvan Quan smu_v11_0_get_current_pcie_link_width(smu);
33117d6c13efSEvan Quan gpu_metrics->pcie_link_speed =
33127d6c13efSEvan Quan smu_v11_0_get_current_pcie_link_speed(smu);
33137d6c13efSEvan Quan
33147d6c13efSEvan Quan gpu_metrics->system_clock_counter = ktime_get_boottime_ns();
33157d6c13efSEvan Quan
331661e2d322SDavid M Nieto if (metrics.CurrGfxVoltageOffset)
331761e2d322SDavid M Nieto gpu_metrics->voltage_gfx =
331861e2d322SDavid M Nieto (155000 - 625 * metrics.CurrGfxVoltageOffset) / 100;
331961e2d322SDavid M Nieto if (metrics.CurrMemVidOffset)
332061e2d322SDavid M Nieto gpu_metrics->voltage_mem =
332161e2d322SDavid M Nieto (155000 - 625 * metrics.CurrMemVidOffset) / 100;
332261e2d322SDavid M Nieto if (metrics.CurrSocVoltageOffset)
332361e2d322SDavid M Nieto gpu_metrics->voltage_soc =
332461e2d322SDavid M Nieto (155000 - 625 * metrics.CurrSocVoltageOffset) / 100;
332561e2d322SDavid M Nieto
33267d6c13efSEvan Quan *table = (void *)gpu_metrics;
33277d6c13efSEvan Quan
332861e2d322SDavid M Nieto return sizeof(struct gpu_metrics_v1_3);
33297d6c13efSEvan Quan }
33307d6c13efSEvan Quan
navi12_get_gpu_metrics(struct smu_context * smu,void ** table)33317d6c13efSEvan Quan static ssize_t navi12_get_gpu_metrics(struct smu_context *smu,
33327d6c13efSEvan Quan void **table)
33337d6c13efSEvan Quan {
33347d6c13efSEvan Quan struct smu_table_context *smu_table = &smu->smu_table;
333561e2d322SDavid M Nieto struct gpu_metrics_v1_3 *gpu_metrics =
333661e2d322SDavid M Nieto (struct gpu_metrics_v1_3 *)smu_table->gpu_metrics_table;
33377d6c13efSEvan Quan SmuMetrics_NV12_t metrics;
33387d6c13efSEvan Quan int ret = 0;
33397d6c13efSEvan Quan
3340da11407fSEvan Quan ret = smu_cmn_get_metrics_table(smu,
33417d6c13efSEvan Quan NULL,
33427d6c13efSEvan Quan true);
3343da11407fSEvan Quan if (ret)
33447d6c13efSEvan Quan return ret;
33457d6c13efSEvan Quan
33467d6c13efSEvan Quan memcpy(&metrics, smu_table->metrics_table, sizeof(SmuMetrics_NV12_t));
33477d6c13efSEvan Quan
334861e2d322SDavid M Nieto smu_cmn_init_soft_gpu_metrics(gpu_metrics, 1, 3);
33497d6c13efSEvan Quan
33507d6c13efSEvan Quan gpu_metrics->temperature_edge = metrics.TemperatureEdge;
33517d6c13efSEvan Quan gpu_metrics->temperature_hotspot = metrics.TemperatureHotspot;
33527d6c13efSEvan Quan gpu_metrics->temperature_mem = metrics.TemperatureMem;
33537d6c13efSEvan Quan gpu_metrics->temperature_vrgfx = metrics.TemperatureVrGfx;
33547d6c13efSEvan Quan gpu_metrics->temperature_vrsoc = metrics.TemperatureVrSoc;
33557d6c13efSEvan Quan gpu_metrics->temperature_vrmem = metrics.TemperatureVrMem0;
33567d6c13efSEvan Quan
33577d6c13efSEvan Quan gpu_metrics->average_gfx_activity = metrics.AverageGfxActivity;
33587d6c13efSEvan Quan gpu_metrics->average_umc_activity = metrics.AverageUclkActivity;
33597d6c13efSEvan Quan
33607d6c13efSEvan Quan gpu_metrics->average_socket_power = metrics.AverageSocketPower;
33617d6c13efSEvan Quan
33627d6c13efSEvan Quan if (metrics.AverageGfxActivity > SMU_11_0_GFX_BUSY_THRESHOLD)
33637d6c13efSEvan Quan gpu_metrics->average_gfxclk_frequency = metrics.AverageGfxclkFrequencyPreDs;
33647d6c13efSEvan Quan else
33657d6c13efSEvan Quan gpu_metrics->average_gfxclk_frequency = metrics.AverageGfxclkFrequencyPostDs;
33667d6c13efSEvan Quan
33677d6c13efSEvan Quan gpu_metrics->average_socclk_frequency = metrics.AverageSocclkFrequency;
33687d6c13efSEvan Quan gpu_metrics->average_uclk_frequency = metrics.AverageUclkFrequencyPostDs;
33697d6c13efSEvan Quan
33707d6c13efSEvan Quan gpu_metrics->energy_accumulator = metrics.EnergyAccumulator;
33717d6c13efSEvan Quan gpu_metrics->average_vclk0_frequency = metrics.AverageVclkFrequency;
33727d6c13efSEvan Quan gpu_metrics->average_dclk0_frequency = metrics.AverageDclkFrequency;
33737d6c13efSEvan Quan gpu_metrics->average_mm_activity = metrics.VcnActivityPercentage;
33747d6c13efSEvan Quan
33757d6c13efSEvan Quan gpu_metrics->current_gfxclk = metrics.CurrClock[PPCLK_GFXCLK];
33767d6c13efSEvan Quan gpu_metrics->current_socclk = metrics.CurrClock[PPCLK_SOCCLK];
33777d6c13efSEvan Quan gpu_metrics->current_uclk = metrics.CurrClock[PPCLK_UCLK];
33787d6c13efSEvan Quan gpu_metrics->current_vclk0 = metrics.CurrClock[PPCLK_VCLK];
33797d6c13efSEvan Quan gpu_metrics->current_dclk0 = metrics.CurrClock[PPCLK_DCLK];
33807d6c13efSEvan Quan
33817d6c13efSEvan Quan gpu_metrics->throttle_status = metrics.ThrottlerStatus;
338264cdee43SGraham Sider gpu_metrics->indep_throttle_status =
338364cdee43SGraham Sider smu_cmn_get_indep_throttler_status(metrics.ThrottlerStatus,
338464cdee43SGraham Sider navi1x_throttler_map);
33857d6c13efSEvan Quan
33867d6c13efSEvan Quan gpu_metrics->current_fan_speed = metrics.CurrFanSpeed;
33877d6c13efSEvan Quan
3388c524c1c9SEvan Quan gpu_metrics->pcie_link_width = metrics.PcieWidth;
3389c524c1c9SEvan Quan gpu_metrics->pcie_link_speed = link_speed[metrics.PcieRate];
33907d6c13efSEvan Quan
33917d6c13efSEvan Quan gpu_metrics->system_clock_counter = ktime_get_boottime_ns();
33927d6c13efSEvan Quan
339361e2d322SDavid M Nieto if (metrics.CurrGfxVoltageOffset)
339461e2d322SDavid M Nieto gpu_metrics->voltage_gfx =
339561e2d322SDavid M Nieto (155000 - 625 * metrics.CurrGfxVoltageOffset) / 100;
339661e2d322SDavid M Nieto if (metrics.CurrMemVidOffset)
339761e2d322SDavid M Nieto gpu_metrics->voltage_mem =
339861e2d322SDavid M Nieto (155000 - 625 * metrics.CurrMemVidOffset) / 100;
339961e2d322SDavid M Nieto if (metrics.CurrSocVoltageOffset)
340061e2d322SDavid M Nieto gpu_metrics->voltage_soc =
340161e2d322SDavid M Nieto (155000 - 625 * metrics.CurrSocVoltageOffset) / 100;
340261e2d322SDavid M Nieto
34037d6c13efSEvan Quan *table = (void *)gpu_metrics;
34047d6c13efSEvan Quan
340561e2d322SDavid M Nieto return sizeof(struct gpu_metrics_v1_3);
34067d6c13efSEvan Quan }
34077d6c13efSEvan Quan
navi1x_get_gpu_metrics(struct smu_context * smu,void ** table)34087d6c13efSEvan Quan static ssize_t navi1x_get_gpu_metrics(struct smu_context *smu,
34097d6c13efSEvan Quan void **table)
34107d6c13efSEvan Quan {
34117d6c13efSEvan Quan struct amdgpu_device *adev = smu->adev;
34127d6c13efSEvan Quan int ret = 0;
34137d6c13efSEvan Quan
34144e8303cfSLijo Lazar switch (amdgpu_ip_version(adev, MP1_HWIP, 0)) {
3415ea0d730aSAlex Deucher case IP_VERSION(11, 0, 9):
3416710d9caeSYifan Zhang if (smu->smc_fw_version > 0x00341C00)
34177d6c13efSEvan Quan ret = navi12_get_gpu_metrics(smu, table);
34187d6c13efSEvan Quan else
34197d6c13efSEvan Quan ret = navi12_get_legacy_gpu_metrics(smu, table);
34207d6c13efSEvan Quan break;
3421ea0d730aSAlex Deucher case IP_VERSION(11, 0, 0):
3422ea0d730aSAlex Deucher case IP_VERSION(11, 0, 5):
34237d6c13efSEvan Quan default:
34244e8303cfSLijo Lazar if (((amdgpu_ip_version(adev, MP1_HWIP, 0) ==
34254e8303cfSLijo Lazar IP_VERSION(11, 0, 5)) &&
3426710d9caeSYifan Zhang smu->smc_fw_version > 0x00351F00) ||
34274e8303cfSLijo Lazar ((amdgpu_ip_version(adev, MP1_HWIP, 0) ==
34284e8303cfSLijo Lazar IP_VERSION(11, 0, 0)) &&
3429710d9caeSYifan Zhang smu->smc_fw_version > 0x002A3B00))
34307d6c13efSEvan Quan ret = navi10_get_gpu_metrics(smu, table);
34317d6c13efSEvan Quan else
34327d6c13efSEvan Quan ret = navi10_get_legacy_gpu_metrics(smu, table);
34337d6c13efSEvan Quan break;
34347d6c13efSEvan Quan }
34357d6c13efSEvan Quan
34367d6c13efSEvan Quan return ret;
34377d6c13efSEvan Quan }
34387d6c13efSEvan Quan
navi10_enable_mgpu_fan_boost(struct smu_context * smu)343994a670d5SEvan Quan static int navi10_enable_mgpu_fan_boost(struct smu_context *smu)
344094a670d5SEvan Quan {
3441b804a75dSEvan Quan struct smu_table_context *table_context = &smu->smu_table;
3442b804a75dSEvan Quan PPTable_t *smc_pptable = table_context->driver_pptable;
344394a670d5SEvan Quan struct amdgpu_device *adev = smu->adev;
344494a670d5SEvan Quan uint32_t param = 0;
344594a670d5SEvan Quan
344694a670d5SEvan Quan /* Navi12 does not support this */
34474e8303cfSLijo Lazar if (amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(11, 0, 9))
344894a670d5SEvan Quan return 0;
344994a670d5SEvan Quan
3450b804a75dSEvan Quan /*
3451b804a75dSEvan Quan * Skip the MGpuFanBoost setting for those ASICs
3452b804a75dSEvan Quan * which do not support it
3453b804a75dSEvan Quan */
3454b804a75dSEvan Quan if (!smc_pptable->MGpuFanBoostLimitRpm)
3455b804a75dSEvan Quan return 0;
3456b804a75dSEvan Quan
345794a670d5SEvan Quan /* Workaround for WS SKU */
345894a670d5SEvan Quan if (adev->pdev->device == 0x7312 &&
345994a670d5SEvan Quan adev->pdev->revision == 0)
346094a670d5SEvan Quan param = 0xD188;
346194a670d5SEvan Quan
346294a670d5SEvan Quan return smu_cmn_send_smc_msg_with_param(smu,
346394a670d5SEvan Quan SMU_MSG_SetMGpuFanBoostLimitRpm,
346494a670d5SEvan Quan param,
346594a670d5SEvan Quan NULL);
346694a670d5SEvan Quan }
346794a670d5SEvan Quan
navi10_post_smu_init(struct smu_context * smu)346810144762SEvan Quan static int navi10_post_smu_init(struct smu_context *smu)
346910144762SEvan Quan {
347010144762SEvan Quan struct amdgpu_device *adev = smu->adev;
347182cac71cSEvan Quan int ret = 0;
347210144762SEvan Quan
3473911d5bd5SJingwen Chen if (amdgpu_sriov_vf(adev))
3474911d5bd5SJingwen Chen return 0;
3475911d5bd5SJingwen Chen
347612f04120SEvan Quan ret = navi10_run_umc_cdr_workaround(smu);
347757277399SEvan Quan if (ret)
347882cac71cSEvan Quan dev_err(adev->dev, "Failed to apply umc cdr workaround!\n");
347982cac71cSEvan Quan
348082cac71cSEvan Quan return ret;
348110144762SEvan Quan }
348210144762SEvan Quan
navi10_get_default_config_table_settings(struct smu_context * smu,struct config_table_setting * table)34837e2a4cfcSEvan Quan static int navi10_get_default_config_table_settings(struct smu_context *smu,
34847e2a4cfcSEvan Quan struct config_table_setting *table)
34857e2a4cfcSEvan Quan {
34867e2a4cfcSEvan Quan if (!table)
34877e2a4cfcSEvan Quan return -EINVAL;
34887e2a4cfcSEvan Quan
34897e2a4cfcSEvan Quan table->gfxclk_average_tau = 10;
34907e2a4cfcSEvan Quan table->socclk_average_tau = 10;
34917e2a4cfcSEvan Quan table->uclk_average_tau = 10;
34927e2a4cfcSEvan Quan table->gfx_activity_average_tau = 10;
34937e2a4cfcSEvan Quan table->mem_activity_average_tau = 10;
34947e2a4cfcSEvan Quan table->socket_power_average_tau = 10;
34957e2a4cfcSEvan Quan
34967e2a4cfcSEvan Quan return 0;
34977e2a4cfcSEvan Quan }
34987e2a4cfcSEvan Quan
navi10_set_config_table(struct smu_context * smu,struct config_table_setting * table)34997e2a4cfcSEvan Quan static int navi10_set_config_table(struct smu_context *smu,
35007e2a4cfcSEvan Quan struct config_table_setting *table)
35017e2a4cfcSEvan Quan {
35027e2a4cfcSEvan Quan DriverSmuConfig_t driver_smu_config_table;
35037e2a4cfcSEvan Quan
35047e2a4cfcSEvan Quan if (!table)
35057e2a4cfcSEvan Quan return -EINVAL;
35067e2a4cfcSEvan Quan
35077e2a4cfcSEvan Quan memset(&driver_smu_config_table,
35087e2a4cfcSEvan Quan 0,
35097e2a4cfcSEvan Quan sizeof(driver_smu_config_table));
35107e2a4cfcSEvan Quan
35117e2a4cfcSEvan Quan driver_smu_config_table.GfxclkAverageLpfTau =
35127e2a4cfcSEvan Quan table->gfxclk_average_tau;
35137e2a4cfcSEvan Quan driver_smu_config_table.SocclkAverageLpfTau =
35147e2a4cfcSEvan Quan table->socclk_average_tau;
35157e2a4cfcSEvan Quan driver_smu_config_table.UclkAverageLpfTau =
35167e2a4cfcSEvan Quan table->uclk_average_tau;
35177e2a4cfcSEvan Quan driver_smu_config_table.GfxActivityLpfTau =
35187e2a4cfcSEvan Quan table->gfx_activity_average_tau;
35197e2a4cfcSEvan Quan driver_smu_config_table.UclkActivityLpfTau =
35207e2a4cfcSEvan Quan table->mem_activity_average_tau;
35217e2a4cfcSEvan Quan driver_smu_config_table.SocketPowerLpfTau =
35227e2a4cfcSEvan Quan table->socket_power_average_tau;
35237e2a4cfcSEvan Quan
35247e2a4cfcSEvan Quan return smu_cmn_update_table(smu,
35257e2a4cfcSEvan Quan SMU_TABLE_DRIVER_SMU_CONFIG,
35267e2a4cfcSEvan Quan 0,
35277e2a4cfcSEvan Quan (void *)&driver_smu_config_table,
35287e2a4cfcSEvan Quan true);
35297e2a4cfcSEvan Quan }
35307e2a4cfcSEvan Quan
3531b3490673SHuang Rui static const struct pptable_funcs navi10_ppt_funcs = {
353274c958a3SKevin Wang .get_allowed_feature_mask = navi10_get_allowed_feature_mask,
3533b3490673SHuang Rui .set_default_dpm_table = navi10_set_default_dpm_table,
3534f6b4b4a1SEvan Quan .dpm_set_vcn_enable = navi10_dpm_set_vcn_enable,
353543717ff6SLeo Liu .dpm_set_jpeg_enable = navi10_dpm_set_jpeg_enable,
3536af01340bSAlex Deucher .i2c_init = navi10_i2c_control_init,
3537af01340bSAlex Deucher .i2c_fini = navi10_i2c_control_fini,
3538b1e7e224SKevin Wang .print_clk_levels = navi10_print_clk_levels,
3539b06b48d7SDarren Powell .emit_clk_levels = navi10_emit_clk_levels,
3540db439ca2SKevin Wang .force_clk_levels = navi10_force_clk_levels,
3541fa51bfc2SKevin Wang .populate_umd_state_clk = navi10_populate_umd_state_clk,
3542a43913eaSKevin Wang .get_clock_by_type_with_latency = navi10_get_clock_by_type_with_latency,
354328430544SKevin Wang .pre_display_config_changed = navi10_pre_display_config_changed,
35440a6430daSKevin Wang .display_config_changed = navi10_display_config_changed,
354519796597SAlex Deucher .notify_smc_display_config = navi10_notify_smc_display_config,
35464228b601SKevin Wang .is_dpm_running = navi10_is_dpm_running,
35470d8318e1SEvan Quan .get_fan_speed_pwm = smu_v11_0_get_fan_speed_pwm,
3548d9ca7567SEvan Quan .get_fan_speed_rpm = navi10_get_fan_speed_rpm,
3549b45dc20bSKevin Wang .get_power_profile_mode = navi10_get_power_profile_mode,
3550b45dc20bSKevin Wang .set_power_profile_mode = navi10_set_power_profile_mode,
35515bbb0994SKevin Wang .set_watermarks_table = navi10_set_watermarks_table,
35529c62f993SKevin Wang .read_sensor = navi10_read_sensor,
3553f4b3295fShersen wu .get_uclk_dpm_states = navi10_get_uclk_dpm_states,
355446a301e1SEvan Quan .set_performance_level = smu_v11_0_set_performance_level,
35557a816371SKevin Wang .get_thermal_temperature_range = navi10_get_thermal_temperature_range,
35566e92e156SKenneth Feng .display_disable_memory_clock_switch = navi10_display_disable_memory_clock_switch,
3557b4af964eSEvan Quan .get_power_limit = navi10_get_power_limit,
3558372120f0SKenneth Feng .update_pcie_parameters = navi10_update_pcie_parameters,
35596c45e480SEvan Quan .init_microcode = smu_v11_0_init_microcode,
35606c45e480SEvan Quan .load_microcode = smu_v11_0_load_microcode,
35616f47116eSEvan Quan .fini_microcode = smu_v11_0_fini_microcode,
3562c1b353b7SEvan Quan .init_smc_tables = navi10_init_smc_tables,
35636c45e480SEvan Quan .fini_smc_tables = smu_v11_0_fini_smc_tables,
35646c45e480SEvan Quan .init_power = smu_v11_0_init_power,
35656c45e480SEvan Quan .fini_power = smu_v11_0_fini_power,
35666c45e480SEvan Quan .check_fw_status = smu_v11_0_check_fw_status,
35674a13b4ceSEvan Quan .setup_pptable = navi10_setup_pptable,
35686c45e480SEvan Quan .get_vbios_bootup_values = smu_v11_0_get_vbios_bootup_values,
35696c45e480SEvan Quan .check_fw_version = smu_v11_0_check_fw_version,
3570caad2613SEvan Quan .write_pptable = smu_cmn_write_pptable,
3571ce0d0ec3SEvan Quan .set_driver_table_location = smu_v11_0_set_driver_table_location,
35726c45e480SEvan Quan .set_tool_table_location = smu_v11_0_set_tool_table_location,
35736c45e480SEvan Quan .notify_memory_pool_location = smu_v11_0_notify_memory_pool_location,
35746c45e480SEvan Quan .system_features_control = smu_v11_0_system_features_control,
357566c86828SEvan Quan .send_smc_msg_with_param = smu_cmn_send_smc_msg_with_param,
357666c86828SEvan Quan .send_smc_msg = smu_cmn_send_smc_msg,
35776c45e480SEvan Quan .init_display_count = smu_v11_0_init_display_count,
35786c45e480SEvan Quan .set_allowed_mask = smu_v11_0_set_allowed_mask,
357928251d72SEvan Quan .get_enabled_mask = smu_cmn_get_enabled_mask,
3580b4bb3aafSEvan Quan .feature_is_enabled = smu_cmn_feature_is_enabled,
3581af5ba6d2SEvan Quan .disable_all_features_with_exception = smu_cmn_disable_all_features_with_exception,
35826c45e480SEvan Quan .notify_display_change = smu_v11_0_notify_display_change,
35836c45e480SEvan Quan .set_power_limit = smu_v11_0_set_power_limit,
35846c45e480SEvan Quan .init_max_sustainable_clocks = smu_v11_0_init_max_sustainable_clocks,
358522f1e0e8SEvan Quan .enable_thermal_alert = smu_v11_0_enable_thermal_alert,
358622f1e0e8SEvan Quan .disable_thermal_alert = smu_v11_0_disable_thermal_alert,
3587ce63d8f8SEvan Quan .set_min_dcef_deep_sleep = smu_v11_0_set_min_deep_sleep_dcefclk,
35886c45e480SEvan Quan .display_clock_voltage_request = smu_v11_0_display_clock_voltage_request,
35896c45e480SEvan Quan .get_fan_control_mode = smu_v11_0_get_fan_control_mode,
35906c45e480SEvan Quan .set_fan_control_mode = smu_v11_0_set_fan_control_mode,
35910d8318e1SEvan Quan .set_fan_speed_pwm = smu_v11_0_set_fan_speed_pwm,
3592f3289d04SEvan Quan .set_fan_speed_rpm = smu_v11_0_set_fan_speed_rpm,
35936c45e480SEvan Quan .set_xgmi_pstate = smu_v11_0_set_xgmi_pstate,
35946c45e480SEvan Quan .gfx_off_control = smu_v11_0_gfx_off_control,
35956c45e480SEvan Quan .register_irq_handler = smu_v11_0_register_irq_handler,
35966c45e480SEvan Quan .set_azalia_d3_pme = smu_v11_0_set_azalia_d3_pme,
35976c45e480SEvan Quan .get_max_sustainable_clocks_by_dc = smu_v11_0_get_max_sustainable_clocks_by_dc,
35981b199594SMa Jun .get_bamaco_support = smu_v11_0_get_bamaco_support,
359913d75eadSEvan Quan .baco_enter = navi10_baco_enter,
360013d75eadSEvan Quan .baco_exit = navi10_baco_exit,
36016c45e480SEvan Quan .get_dpm_ultimate_freq = smu_v11_0_get_dpm_ultimate_freq,
36026c45e480SEvan Quan .set_soft_freq_limited_range = smu_v11_0_set_soft_freq_limited_range,
360321677d08SMatt Coffin .set_default_od_settings = navi10_set_default_od_settings,
360421677d08SMatt Coffin .od_edit_dpm_table = navi10_od_edit_dpm_table,
360592cf0508SEvan Quan .restore_user_od_settings = smu_v11_0_restore_user_od_settings,
36060eeaa899SEvan Quan .run_btc = navi10_run_btc,
3607fa34520cSAlex Deucher .set_power_source = smu_v11_0_set_power_source,
36087dbf7805SEvan Quan .get_pp_feature_mask = smu_cmn_get_pp_feature_mask,
36097dbf7805SEvan Quan .set_pp_feature_mask = smu_cmn_set_pp_feature_mask,
36107d6c13efSEvan Quan .get_gpu_metrics = navi1x_get_gpu_metrics,
361194a670d5SEvan Quan .enable_mgpu_fan_boost = navi10_enable_mgpu_fan_boost,
3612e988026fSEvan Quan .gfx_ulv_control = smu_v11_0_gfx_ulv_control,
36135ce99853SEvan Quan .deep_sleep_control = smu_v11_0_deep_sleep_control,
36143204ff3eSAlex Deucher .get_fan_parameters = navi10_get_fan_parameters,
361510144762SEvan Quan .post_init = navi10_post_smu_init,
3616234676d6SAlex Deucher .interrupt_work = smu_v11_0_interrupt_work,
36175f0f1727SEvan Quan .set_mp1_state = smu_cmn_set_mp1_state,
36187e2a4cfcSEvan Quan .get_default_config_table_settings = navi10_get_default_config_table_settings,
36197e2a4cfcSEvan Quan .set_config_table = navi10_set_config_table,
3620b3490673SHuang Rui };
3621b3490673SHuang Rui
navi10_set_ppt_funcs(struct smu_context * smu)3622b3490673SHuang Rui void navi10_set_ppt_funcs(struct smu_context *smu)
3623b3490673SHuang Rui {
3624b3490673SHuang Rui smu->ppt_funcs = &navi10_ppt_funcs;
36256c339f37SEvan Quan smu->message_map = navi10_message_map;
36266c339f37SEvan Quan smu->clock_map = navi10_clk_map;
36276c339f37SEvan Quan smu->feature_map = navi10_feature_mask_map;
36286c339f37SEvan Quan smu->table_map = navi10_table_map;
36296c339f37SEvan Quan smu->pwr_src_map = navi10_pwr_src_map;
36306c339f37SEvan Quan smu->workload_map = navi10_workload_map;
3631da1db031SAlex Deucher smu_v11_0_set_smu_mailbox_registers(smu);
3632b3490673SHuang Rui }
3633