1 /*
2 * Copyright 2019 Advanced Micro Devices, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 */
23
24 #define SWSMU_CODE_LAYER_L2
25
26 #include <linux/firmware.h>
27 #include <linux/pci.h>
28 #include <linux/i2c.h>
29 #include "amdgpu.h"
30 #include "amdgpu_smu.h"
31 #include "atomfirmware.h"
32 #include "amdgpu_atomfirmware.h"
33 #include "amdgpu_atombios.h"
34 #include "soc15_common.h"
35 #include "smu_v11_0.h"
36 #include "smu11_driver_if_navi10.h"
37 #include "atom.h"
38 #include "navi10_ppt.h"
39 #include "smu_v11_0_pptable.h"
40 #include "smu_v11_0_ppsmc.h"
41 #include "nbio/nbio_2_3_offset.h"
42 #include "nbio/nbio_2_3_sh_mask.h"
43 #include "thm/thm_11_0_2_offset.h"
44 #include "thm/thm_11_0_2_sh_mask.h"
45
46 #include "asic_reg/mp/mp_11_0_sh_mask.h"
47 #include "smu_cmn.h"
48 #include "smu_11_0_cdr_table.h"
49
50 /*
51 * DO NOT use these for err/warn/info/debug messages.
52 * Use dev_err, dev_warn, dev_info and dev_dbg instead.
53 * They are more MGPU friendly.
54 */
55 #undef pr_err
56 #undef pr_warn
57 #undef pr_info
58 #undef pr_debug
59
60 #define to_amdgpu_device(x) (container_of(x, struct amdgpu_device, pm.smu_i2c))
61
62 #define FEATURE_MASK(feature) (1ULL << feature)
63 #define SMC_DPM_FEATURE ( \
64 FEATURE_MASK(FEATURE_DPM_PREFETCHER_BIT) | \
65 FEATURE_MASK(FEATURE_DPM_GFXCLK_BIT) | \
66 FEATURE_MASK(FEATURE_DPM_GFX_PACE_BIT) | \
67 FEATURE_MASK(FEATURE_DPM_UCLK_BIT) | \
68 FEATURE_MASK(FEATURE_DPM_SOCCLK_BIT) | \
69 FEATURE_MASK(FEATURE_DPM_MP0CLK_BIT) | \
70 FEATURE_MASK(FEATURE_DPM_LINK_BIT) | \
71 FEATURE_MASK(FEATURE_DPM_DCEFCLK_BIT))
72
73 static struct cmn2asic_msg_mapping navi10_message_map[SMU_MSG_MAX_COUNT] = {
74 MSG_MAP(TestMessage, PPSMC_MSG_TestMessage, 1),
75 MSG_MAP(GetSmuVersion, PPSMC_MSG_GetSmuVersion, 1),
76 MSG_MAP(GetDriverIfVersion, PPSMC_MSG_GetDriverIfVersion, 1),
77 MSG_MAP(SetAllowedFeaturesMaskLow, PPSMC_MSG_SetAllowedFeaturesMaskLow, 0),
78 MSG_MAP(SetAllowedFeaturesMaskHigh, PPSMC_MSG_SetAllowedFeaturesMaskHigh, 0),
79 MSG_MAP(EnableAllSmuFeatures, PPSMC_MSG_EnableAllSmuFeatures, 0),
80 MSG_MAP(DisableAllSmuFeatures, PPSMC_MSG_DisableAllSmuFeatures, 0),
81 MSG_MAP(EnableSmuFeaturesLow, PPSMC_MSG_EnableSmuFeaturesLow, 1),
82 MSG_MAP(EnableSmuFeaturesHigh, PPSMC_MSG_EnableSmuFeaturesHigh, 1),
83 MSG_MAP(DisableSmuFeaturesLow, PPSMC_MSG_DisableSmuFeaturesLow, 1),
84 MSG_MAP(DisableSmuFeaturesHigh, PPSMC_MSG_DisableSmuFeaturesHigh, 1),
85 MSG_MAP(GetEnabledSmuFeaturesLow, PPSMC_MSG_GetEnabledSmuFeaturesLow, 1),
86 MSG_MAP(GetEnabledSmuFeaturesHigh, PPSMC_MSG_GetEnabledSmuFeaturesHigh, 1),
87 MSG_MAP(SetWorkloadMask, PPSMC_MSG_SetWorkloadMask, 1),
88 MSG_MAP(SetPptLimit, PPSMC_MSG_SetPptLimit, 0),
89 MSG_MAP(SetDriverDramAddrHigh, PPSMC_MSG_SetDriverDramAddrHigh, 0),
90 MSG_MAP(SetDriverDramAddrLow, PPSMC_MSG_SetDriverDramAddrLow, 0),
91 MSG_MAP(SetToolsDramAddrHigh, PPSMC_MSG_SetToolsDramAddrHigh, 0),
92 MSG_MAP(SetToolsDramAddrLow, PPSMC_MSG_SetToolsDramAddrLow, 0),
93 MSG_MAP(TransferTableSmu2Dram, PPSMC_MSG_TransferTableSmu2Dram, 0),
94 MSG_MAP(TransferTableDram2Smu, PPSMC_MSG_TransferTableDram2Smu, 0),
95 MSG_MAP(UseDefaultPPTable, PPSMC_MSG_UseDefaultPPTable, 0),
96 MSG_MAP(UseBackupPPTable, PPSMC_MSG_UseBackupPPTable, 0),
97 MSG_MAP(RunBtc, PPSMC_MSG_RunBtc, 0),
98 MSG_MAP(EnterBaco, PPSMC_MSG_EnterBaco, 0),
99 MSG_MAP(SetSoftMinByFreq, PPSMC_MSG_SetSoftMinByFreq, 0),
100 MSG_MAP(SetSoftMaxByFreq, PPSMC_MSG_SetSoftMaxByFreq, 0),
101 MSG_MAP(SetHardMinByFreq, PPSMC_MSG_SetHardMinByFreq, 1),
102 MSG_MAP(SetHardMaxByFreq, PPSMC_MSG_SetHardMaxByFreq, 0),
103 MSG_MAP(GetMinDpmFreq, PPSMC_MSG_GetMinDpmFreq, 1),
104 MSG_MAP(GetMaxDpmFreq, PPSMC_MSG_GetMaxDpmFreq, 1),
105 MSG_MAP(GetDpmFreqByIndex, PPSMC_MSG_GetDpmFreqByIndex, 1),
106 MSG_MAP(SetMemoryChannelConfig, PPSMC_MSG_SetMemoryChannelConfig, 0),
107 MSG_MAP(SetGeminiMode, PPSMC_MSG_SetGeminiMode, 0),
108 MSG_MAP(SetGeminiApertureHigh, PPSMC_MSG_SetGeminiApertureHigh, 0),
109 MSG_MAP(SetGeminiApertureLow, PPSMC_MSG_SetGeminiApertureLow, 0),
110 MSG_MAP(OverridePcieParameters, PPSMC_MSG_OverridePcieParameters, 0),
111 MSG_MAP(SetMinDeepSleepDcefclk, PPSMC_MSG_SetMinDeepSleepDcefclk, 0),
112 MSG_MAP(ReenableAcDcInterrupt, PPSMC_MSG_ReenableAcDcInterrupt, 0),
113 MSG_MAP(NotifyPowerSource, PPSMC_MSG_NotifyPowerSource, 0),
114 MSG_MAP(SetUclkFastSwitch, PPSMC_MSG_SetUclkFastSwitch, 0),
115 MSG_MAP(SetVideoFps, PPSMC_MSG_SetVideoFps, 0),
116 MSG_MAP(PrepareMp1ForUnload, PPSMC_MSG_PrepareMp1ForUnload, 1),
117 MSG_MAP(DramLogSetDramAddrHigh, PPSMC_MSG_DramLogSetDramAddrHigh, 0),
118 MSG_MAP(DramLogSetDramAddrLow, PPSMC_MSG_DramLogSetDramAddrLow, 0),
119 MSG_MAP(DramLogSetDramSize, PPSMC_MSG_DramLogSetDramSize, 0),
120 MSG_MAP(ConfigureGfxDidt, PPSMC_MSG_ConfigureGfxDidt, 0),
121 MSG_MAP(NumOfDisplays, PPSMC_MSG_NumOfDisplays, 0),
122 MSG_MAP(SetSystemVirtualDramAddrHigh, PPSMC_MSG_SetSystemVirtualDramAddrHigh, 0),
123 MSG_MAP(SetSystemVirtualDramAddrLow, PPSMC_MSG_SetSystemVirtualDramAddrLow, 0),
124 MSG_MAP(AllowGfxOff, PPSMC_MSG_AllowGfxOff, 0),
125 MSG_MAP(DisallowGfxOff, PPSMC_MSG_DisallowGfxOff, 0),
126 MSG_MAP(GetPptLimit, PPSMC_MSG_GetPptLimit, 0),
127 MSG_MAP(GetDcModeMaxDpmFreq, PPSMC_MSG_GetDcModeMaxDpmFreq, 1),
128 MSG_MAP(GetDebugData, PPSMC_MSG_GetDebugData, 0),
129 MSG_MAP(ExitBaco, PPSMC_MSG_ExitBaco, 0),
130 MSG_MAP(PrepareMp1ForReset, PPSMC_MSG_PrepareMp1ForReset, 0),
131 MSG_MAP(PrepareMp1ForShutdown, PPSMC_MSG_PrepareMp1ForShutdown, 0),
132 MSG_MAP(PowerUpVcn, PPSMC_MSG_PowerUpVcn, 0),
133 MSG_MAP(PowerDownVcn, PPSMC_MSG_PowerDownVcn, 0),
134 MSG_MAP(PowerUpJpeg, PPSMC_MSG_PowerUpJpeg, 0),
135 MSG_MAP(PowerDownJpeg, PPSMC_MSG_PowerDownJpeg, 0),
136 MSG_MAP(BacoAudioD3PME, PPSMC_MSG_BacoAudioD3PME, 0),
137 MSG_MAP(ArmD3, PPSMC_MSG_ArmD3, 0),
138 MSG_MAP(DAL_DISABLE_DUMMY_PSTATE_CHANGE,PPSMC_MSG_DALDisableDummyPstateChange, 0),
139 MSG_MAP(DAL_ENABLE_DUMMY_PSTATE_CHANGE, PPSMC_MSG_DALEnableDummyPstateChange, 0),
140 MSG_MAP(GetVoltageByDpm, PPSMC_MSG_GetVoltageByDpm, 0),
141 MSG_MAP(GetVoltageByDpmOverdrive, PPSMC_MSG_GetVoltageByDpmOverdrive, 0),
142 MSG_MAP(SetMGpuFanBoostLimitRpm, PPSMC_MSG_SetMGpuFanBoostLimitRpm, 0),
143 MSG_MAP(SET_DRIVER_DUMMY_TABLE_DRAM_ADDR_HIGH, PPSMC_MSG_SetDriverDummyTableDramAddrHigh, 0),
144 MSG_MAP(SET_DRIVER_DUMMY_TABLE_DRAM_ADDR_LOW, PPSMC_MSG_SetDriverDummyTableDramAddrLow, 0),
145 MSG_MAP(GET_UMC_FW_WA, PPSMC_MSG_GetUMCFWWA, 0),
146 };
147
148 static struct cmn2asic_mapping navi10_clk_map[SMU_CLK_COUNT] = {
149 CLK_MAP(GFXCLK, PPCLK_GFXCLK),
150 CLK_MAP(SCLK, PPCLK_GFXCLK),
151 CLK_MAP(SOCCLK, PPCLK_SOCCLK),
152 CLK_MAP(FCLK, PPCLK_SOCCLK),
153 CLK_MAP(UCLK, PPCLK_UCLK),
154 CLK_MAP(MCLK, PPCLK_UCLK),
155 CLK_MAP(DCLK, PPCLK_DCLK),
156 CLK_MAP(VCLK, PPCLK_VCLK),
157 CLK_MAP(DCEFCLK, PPCLK_DCEFCLK),
158 CLK_MAP(DISPCLK, PPCLK_DISPCLK),
159 CLK_MAP(PIXCLK, PPCLK_PIXCLK),
160 CLK_MAP(PHYCLK, PPCLK_PHYCLK),
161 };
162
163 static struct cmn2asic_mapping navi10_feature_mask_map[SMU_FEATURE_COUNT] = {
164 FEA_MAP(DPM_PREFETCHER),
165 FEA_MAP(DPM_GFXCLK),
166 FEA_MAP(DPM_GFX_PACE),
167 FEA_MAP(DPM_UCLK),
168 FEA_MAP(DPM_SOCCLK),
169 FEA_MAP(DPM_MP0CLK),
170 FEA_MAP(DPM_LINK),
171 FEA_MAP(DPM_DCEFCLK),
172 FEA_MAP(MEM_VDDCI_SCALING),
173 FEA_MAP(MEM_MVDD_SCALING),
174 FEA_MAP(DS_GFXCLK),
175 FEA_MAP(DS_SOCCLK),
176 FEA_MAP(DS_LCLK),
177 FEA_MAP(DS_DCEFCLK),
178 FEA_MAP(DS_UCLK),
179 FEA_MAP(GFX_ULV),
180 FEA_MAP(FW_DSTATE),
181 FEA_MAP(GFXOFF),
182 FEA_MAP(BACO),
183 FEA_MAP(VCN_PG),
184 FEA_MAP(JPEG_PG),
185 FEA_MAP(USB_PG),
186 FEA_MAP(RSMU_SMN_CG),
187 FEA_MAP(PPT),
188 FEA_MAP(TDC),
189 FEA_MAP(GFX_EDC),
190 FEA_MAP(APCC_PLUS),
191 FEA_MAP(GTHR),
192 FEA_MAP(ACDC),
193 FEA_MAP(VR0HOT),
194 FEA_MAP(VR1HOT),
195 FEA_MAP(FW_CTF),
196 FEA_MAP(FAN_CONTROL),
197 FEA_MAP(THERMAL),
198 FEA_MAP(GFX_DCS),
199 FEA_MAP(RM),
200 FEA_MAP(LED_DISPLAY),
201 FEA_MAP(GFX_SS),
202 FEA_MAP(OUT_OF_BAND_MONITOR),
203 FEA_MAP(TEMP_DEPENDENT_VMIN),
204 FEA_MAP(MMHUB_PG),
205 FEA_MAP(ATHUB_PG),
206 FEA_MAP(APCC_DFLL),
207 };
208
209 static struct cmn2asic_mapping navi10_table_map[SMU_TABLE_COUNT] = {
210 TAB_MAP(PPTABLE),
211 TAB_MAP(WATERMARKS),
212 TAB_MAP(AVFS),
213 TAB_MAP(AVFS_PSM_DEBUG),
214 TAB_MAP(AVFS_FUSE_OVERRIDE),
215 TAB_MAP(PMSTATUSLOG),
216 TAB_MAP(SMU_METRICS),
217 TAB_MAP(DRIVER_SMU_CONFIG),
218 TAB_MAP(ACTIVITY_MONITOR_COEFF),
219 TAB_MAP(OVERDRIVE),
220 TAB_MAP(I2C_COMMANDS),
221 TAB_MAP(PACE),
222 };
223
224 static struct cmn2asic_mapping navi10_pwr_src_map[SMU_POWER_SOURCE_COUNT] = {
225 PWR_MAP(AC),
226 PWR_MAP(DC),
227 };
228
229 static struct cmn2asic_mapping navi10_workload_map[PP_SMC_POWER_PROFILE_COUNT] = {
230 WORKLOAD_MAP(PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT, WORKLOAD_PPLIB_DEFAULT_BIT),
231 WORKLOAD_MAP(PP_SMC_POWER_PROFILE_FULLSCREEN3D, WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT),
232 WORKLOAD_MAP(PP_SMC_POWER_PROFILE_POWERSAVING, WORKLOAD_PPLIB_POWER_SAVING_BIT),
233 WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VIDEO, WORKLOAD_PPLIB_VIDEO_BIT),
234 WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VR, WORKLOAD_PPLIB_VR_BIT),
235 WORKLOAD_MAP(PP_SMC_POWER_PROFILE_COMPUTE, WORKLOAD_PPLIB_COMPUTE_BIT),
236 WORKLOAD_MAP(PP_SMC_POWER_PROFILE_CUSTOM, WORKLOAD_PPLIB_CUSTOM_BIT),
237 };
238
is_asic_secure(struct smu_context * smu)239 static bool is_asic_secure(struct smu_context *smu)
240 {
241 struct amdgpu_device *adev = smu->adev;
242 bool is_secure = true;
243 uint32_t mp0_fw_intf;
244
245 mp0_fw_intf = RREG32_PCIE(MP0_Public |
246 (smnMP0_FW_INTF & 0xffffffff));
247
248 if (!(mp0_fw_intf & (1 << 19)))
249 is_secure = false;
250
251 return is_secure;
252 }
253
254 static int
navi10_get_allowed_feature_mask(struct smu_context * smu,uint32_t * feature_mask,uint32_t num)255 navi10_get_allowed_feature_mask(struct smu_context *smu,
256 uint32_t *feature_mask, uint32_t num)
257 {
258 struct amdgpu_device *adev = smu->adev;
259
260 if (num > 2)
261 return -EINVAL;
262
263 memset(feature_mask, 0, sizeof(uint32_t) * num);
264
265 *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_PREFETCHER_BIT)
266 | FEATURE_MASK(FEATURE_DPM_MP0CLK_BIT)
267 | FEATURE_MASK(FEATURE_RSMU_SMN_CG_BIT)
268 | FEATURE_MASK(FEATURE_DS_SOCCLK_BIT)
269 | FEATURE_MASK(FEATURE_PPT_BIT)
270 | FEATURE_MASK(FEATURE_TDC_BIT)
271 | FEATURE_MASK(FEATURE_GFX_EDC_BIT)
272 | FEATURE_MASK(FEATURE_APCC_PLUS_BIT)
273 | FEATURE_MASK(FEATURE_VR0HOT_BIT)
274 | FEATURE_MASK(FEATURE_FAN_CONTROL_BIT)
275 | FEATURE_MASK(FEATURE_THERMAL_BIT)
276 | FEATURE_MASK(FEATURE_LED_DISPLAY_BIT)
277 | FEATURE_MASK(FEATURE_DS_LCLK_BIT)
278 | FEATURE_MASK(FEATURE_DS_DCEFCLK_BIT)
279 | FEATURE_MASK(FEATURE_FW_DSTATE_BIT)
280 | FEATURE_MASK(FEATURE_BACO_BIT)
281 | FEATURE_MASK(FEATURE_GFX_SS_BIT)
282 | FEATURE_MASK(FEATURE_APCC_DFLL_BIT)
283 | FEATURE_MASK(FEATURE_FW_CTF_BIT)
284 | FEATURE_MASK(FEATURE_OUT_OF_BAND_MONITOR_BIT);
285
286 if (adev->pm.pp_feature & PP_SCLK_DPM_MASK)
287 *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_GFXCLK_BIT);
288
289 if (adev->pm.pp_feature & PP_PCIE_DPM_MASK)
290 *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_LINK_BIT);
291
292 if (adev->pm.pp_feature & PP_DCEFCLK_DPM_MASK)
293 *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_DCEFCLK_BIT);
294
295 if (adev->pm.pp_feature & PP_ULV_MASK)
296 *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_GFX_ULV_BIT);
297
298 if (adev->pm.pp_feature & PP_SCLK_DEEP_SLEEP_MASK)
299 *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DS_GFXCLK_BIT);
300
301 if (adev->pm.pp_feature & PP_GFXOFF_MASK)
302 *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_GFXOFF_BIT);
303
304 if (smu->adev->pg_flags & AMD_PG_SUPPORT_MMHUB)
305 *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_MMHUB_PG_BIT);
306
307 if (smu->adev->pg_flags & AMD_PG_SUPPORT_ATHUB)
308 *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_ATHUB_PG_BIT);
309
310 if (smu->adev->pg_flags & AMD_PG_SUPPORT_VCN)
311 *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_VCN_PG_BIT);
312
313 if (smu->adev->pg_flags & AMD_PG_SUPPORT_JPEG)
314 *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_JPEG_PG_BIT);
315
316 if (smu->dc_controlled_by_gpio)
317 *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_ACDC_BIT);
318
319 if (adev->pm.pp_feature & PP_SOCCLK_DPM_MASK)
320 *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_SOCCLK_BIT);
321
322 /* DPM UCLK enablement should be skipped for navi10 A0 secure board */
323 if (!(is_asic_secure(smu) &&
324 (adev->asic_type == CHIP_NAVI10) &&
325 (adev->rev_id == 0)) &&
326 (adev->pm.pp_feature & PP_MCLK_DPM_MASK))
327 *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_UCLK_BIT)
328 | FEATURE_MASK(FEATURE_MEM_VDDCI_SCALING_BIT)
329 | FEATURE_MASK(FEATURE_MEM_MVDD_SCALING_BIT);
330
331 /* DS SOCCLK enablement should be skipped for navi10 A0 secure board */
332 if (is_asic_secure(smu) &&
333 (adev->asic_type == CHIP_NAVI10) &&
334 (adev->rev_id == 0))
335 *(uint64_t *)feature_mask &=
336 ~FEATURE_MASK(FEATURE_DS_SOCCLK_BIT);
337
338 return 0;
339 }
340
navi10_check_powerplay_table(struct smu_context * smu)341 static int navi10_check_powerplay_table(struct smu_context *smu)
342 {
343 struct smu_table_context *table_context = &smu->smu_table;
344 struct smu_11_0_powerplay_table *powerplay_table =
345 table_context->power_play_table;
346 struct smu_baco_context *smu_baco = &smu->smu_baco;
347
348 if (powerplay_table->platform_caps & SMU_11_0_PP_PLATFORM_CAP_HARDWAREDC)
349 smu->dc_controlled_by_gpio = true;
350
351 if (powerplay_table->platform_caps & SMU_11_0_PP_PLATFORM_CAP_BACO ||
352 powerplay_table->platform_caps & SMU_11_0_PP_PLATFORM_CAP_MACO)
353 smu_baco->platform_support = true;
354
355 table_context->thermal_controller_type =
356 powerplay_table->thermal_controller_type;
357
358 /*
359 * Instead of having its own buffer space and get overdrive_table copied,
360 * smu->od_settings just points to the actual overdrive_table
361 */
362 smu->od_settings = &powerplay_table->overdrive_table;
363
364 return 0;
365 }
366
navi10_append_powerplay_table(struct smu_context * smu)367 static int navi10_append_powerplay_table(struct smu_context *smu)
368 {
369 struct amdgpu_device *adev = smu->adev;
370 struct smu_table_context *table_context = &smu->smu_table;
371 PPTable_t *smc_pptable = table_context->driver_pptable;
372 struct atom_smc_dpm_info_v4_5 *smc_dpm_table;
373 struct atom_smc_dpm_info_v4_7 *smc_dpm_table_v4_7;
374 int index, ret;
375
376 index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
377 smc_dpm_info);
378
379 ret = amdgpu_atombios_get_data_table(adev, index, NULL, NULL, NULL,
380 (uint8_t **)&smc_dpm_table);
381 if (ret)
382 return ret;
383
384 dev_info(adev->dev, "smc_dpm_info table revision(format.content): %d.%d\n",
385 smc_dpm_table->table_header.format_revision,
386 smc_dpm_table->table_header.content_revision);
387
388 if (smc_dpm_table->table_header.format_revision != 4) {
389 dev_err(adev->dev, "smc_dpm_info table format revision is not 4!\n");
390 return -EINVAL;
391 }
392
393 switch (smc_dpm_table->table_header.content_revision) {
394 case 5: /* nv10 and nv14 */
395 memcpy(smc_pptable->I2cControllers, smc_dpm_table->I2cControllers,
396 sizeof(*smc_dpm_table) - sizeof(smc_dpm_table->table_header));
397 break;
398 case 7: /* nv12 */
399 ret = amdgpu_atombios_get_data_table(adev, index, NULL, NULL, NULL,
400 (uint8_t **)&smc_dpm_table_v4_7);
401 if (ret)
402 return ret;
403 memcpy(smc_pptable->I2cControllers, smc_dpm_table_v4_7->I2cControllers,
404 sizeof(*smc_dpm_table_v4_7) - sizeof(smc_dpm_table_v4_7->table_header));
405 break;
406 default:
407 dev_err(smu->adev->dev, "smc_dpm_info with unsupported content revision %d!\n",
408 smc_dpm_table->table_header.content_revision);
409 return -EINVAL;
410 }
411
412 if (adev->pm.pp_feature & PP_GFXOFF_MASK) {
413 /* TODO: remove it once SMU fw fix it */
414 smc_pptable->DebugOverrides |= DPM_OVERRIDE_DISABLE_DFLL_PLL_SHUTDOWN;
415 }
416
417 return 0;
418 }
419
navi10_store_powerplay_table(struct smu_context * smu)420 static int navi10_store_powerplay_table(struct smu_context *smu)
421 {
422 struct smu_table_context *table_context = &smu->smu_table;
423 struct smu_11_0_powerplay_table *powerplay_table =
424 table_context->power_play_table;
425
426 memcpy(table_context->driver_pptable, &powerplay_table->smc_pptable,
427 sizeof(PPTable_t));
428
429 return 0;
430 }
431
navi10_setup_pptable(struct smu_context * smu)432 static int navi10_setup_pptable(struct smu_context *smu)
433 {
434 int ret = 0;
435
436 ret = smu_v11_0_setup_pptable(smu);
437 if (ret)
438 return ret;
439
440 ret = navi10_store_powerplay_table(smu);
441 if (ret)
442 return ret;
443
444 ret = navi10_append_powerplay_table(smu);
445 if (ret)
446 return ret;
447
448 ret = navi10_check_powerplay_table(smu);
449 if (ret)
450 return ret;
451
452 return ret;
453 }
454
navi10_tables_init(struct smu_context * smu)455 static int navi10_tables_init(struct smu_context *smu)
456 {
457 struct smu_table_context *smu_table = &smu->smu_table;
458 struct smu_table *tables = smu_table->tables;
459 struct amdgpu_device *adev = smu->adev;
460
461 SMU_TABLE_INIT(tables, SMU_TABLE_PPTABLE, sizeof(PPTable_t),
462 PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
463 SMU_TABLE_INIT(tables, SMU_TABLE_WATERMARKS, sizeof(Watermarks_t),
464 PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
465 if (adev->asic_type == CHIP_NAVI12)
466 SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetrics_NV12_t),
467 PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
468 else
469 SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetrics_t),
470 PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
471 SMU_TABLE_INIT(tables, SMU_TABLE_I2C_COMMANDS, sizeof(SwI2cRequest_t),
472 PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
473 SMU_TABLE_INIT(tables, SMU_TABLE_OVERDRIVE, sizeof(OverDriveTable_t),
474 PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
475 SMU_TABLE_INIT(tables, SMU_TABLE_PMSTATUSLOG, SMU11_TOOL_SIZE,
476 PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
477 SMU_TABLE_INIT(tables, SMU_TABLE_ACTIVITY_MONITOR_COEFF,
478 sizeof(DpmActivityMonitorCoeffInt_t), PAGE_SIZE,
479 AMDGPU_GEM_DOMAIN_VRAM);
480
481 smu_table->metrics_table = kzalloc(adev->asic_type == CHIP_NAVI12 ?
482 sizeof(SmuMetrics_NV12_t) :
483 sizeof(SmuMetrics_t), GFP_KERNEL);
484 if (!smu_table->metrics_table)
485 goto err0_out;
486 smu_table->metrics_time = 0;
487
488 smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v1_0);
489 smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL);
490 if (!smu_table->gpu_metrics_table)
491 goto err1_out;
492
493 smu_table->watermarks_table = kzalloc(sizeof(Watermarks_t), GFP_KERNEL);
494 if (!smu_table->watermarks_table)
495 goto err2_out;
496
497 return 0;
498
499 err2_out:
500 kfree(smu_table->gpu_metrics_table);
501 err1_out:
502 kfree(smu_table->metrics_table);
503 err0_out:
504 return -ENOMEM;
505 }
506
navi10_get_smu_metrics_data(struct smu_context * smu,MetricsMember_t member,uint32_t * value)507 static int navi10_get_smu_metrics_data(struct smu_context *smu,
508 MetricsMember_t member,
509 uint32_t *value)
510 {
511 struct smu_table_context *smu_table= &smu->smu_table;
512 /*
513 * This works for NV12 also. As although NV12 uses a different
514 * SmuMetrics structure from other NV1X ASICs, they share the
515 * same offsets for the heading parts(those members used here).
516 */
517 SmuMetrics_t *metrics = (SmuMetrics_t *)smu_table->metrics_table;
518 int ret = 0;
519
520 mutex_lock(&smu->metrics_lock);
521
522 ret = smu_cmn_get_metrics_table_locked(smu,
523 NULL,
524 false);
525 if (ret) {
526 mutex_unlock(&smu->metrics_lock);
527 return ret;
528 }
529
530 switch (member) {
531 case METRICS_CURR_GFXCLK:
532 *value = metrics->CurrClock[PPCLK_GFXCLK];
533 break;
534 case METRICS_CURR_SOCCLK:
535 *value = metrics->CurrClock[PPCLK_SOCCLK];
536 break;
537 case METRICS_CURR_UCLK:
538 *value = metrics->CurrClock[PPCLK_UCLK];
539 break;
540 case METRICS_CURR_VCLK:
541 *value = metrics->CurrClock[PPCLK_VCLK];
542 break;
543 case METRICS_CURR_DCLK:
544 *value = metrics->CurrClock[PPCLK_DCLK];
545 break;
546 case METRICS_CURR_DCEFCLK:
547 *value = metrics->CurrClock[PPCLK_DCEFCLK];
548 break;
549 case METRICS_AVERAGE_GFXCLK:
550 *value = metrics->AverageGfxclkFrequency;
551 break;
552 case METRICS_AVERAGE_SOCCLK:
553 *value = metrics->AverageSocclkFrequency;
554 break;
555 case METRICS_AVERAGE_UCLK:
556 *value = metrics->AverageUclkFrequency;
557 break;
558 case METRICS_AVERAGE_GFXACTIVITY:
559 *value = metrics->AverageGfxActivity;
560 break;
561 case METRICS_AVERAGE_MEMACTIVITY:
562 *value = metrics->AverageUclkActivity;
563 break;
564 case METRICS_AVERAGE_SOCKETPOWER:
565 *value = metrics->AverageSocketPower << 8;
566 break;
567 case METRICS_TEMPERATURE_EDGE:
568 *value = metrics->TemperatureEdge *
569 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
570 break;
571 case METRICS_TEMPERATURE_HOTSPOT:
572 *value = metrics->TemperatureHotspot *
573 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
574 break;
575 case METRICS_TEMPERATURE_MEM:
576 *value = metrics->TemperatureMem *
577 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
578 break;
579 case METRICS_TEMPERATURE_VRGFX:
580 *value = metrics->TemperatureVrGfx *
581 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
582 break;
583 case METRICS_TEMPERATURE_VRSOC:
584 *value = metrics->TemperatureVrSoc *
585 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
586 break;
587 case METRICS_THROTTLER_STATUS:
588 *value = metrics->ThrottlerStatus;
589 break;
590 case METRICS_CURR_FANSPEED:
591 *value = metrics->CurrFanSpeed;
592 break;
593 default:
594 *value = UINT_MAX;
595 break;
596 }
597
598 mutex_unlock(&smu->metrics_lock);
599
600 return ret;
601 }
602
navi10_allocate_dpm_context(struct smu_context * smu)603 static int navi10_allocate_dpm_context(struct smu_context *smu)
604 {
605 struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
606
607 smu_dpm->dpm_context = kzalloc(sizeof(struct smu_11_0_dpm_context),
608 GFP_KERNEL);
609 if (!smu_dpm->dpm_context)
610 return -ENOMEM;
611
612 smu_dpm->dpm_context_size = sizeof(struct smu_11_0_dpm_context);
613
614 return 0;
615 }
616
navi10_init_smc_tables(struct smu_context * smu)617 static int navi10_init_smc_tables(struct smu_context *smu)
618 {
619 int ret = 0;
620
621 ret = navi10_tables_init(smu);
622 if (ret)
623 return ret;
624
625 ret = navi10_allocate_dpm_context(smu);
626 if (ret)
627 return ret;
628
629 return smu_v11_0_init_smc_tables(smu);
630 }
631
navi10_set_default_dpm_table(struct smu_context * smu)632 static int navi10_set_default_dpm_table(struct smu_context *smu)
633 {
634 struct smu_11_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context;
635 PPTable_t *driver_ppt = smu->smu_table.driver_pptable;
636 struct smu_11_0_dpm_table *dpm_table;
637 int ret = 0;
638
639 /* socclk dpm table setup */
640 dpm_table = &dpm_context->dpm_tables.soc_table;
641 if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) {
642 ret = smu_v11_0_set_single_dpm_table(smu,
643 SMU_SOCCLK,
644 dpm_table);
645 if (ret)
646 return ret;
647 dpm_table->is_fine_grained =
648 !driver_ppt->DpmDescriptor[PPCLK_SOCCLK].SnapToDiscrete;
649 } else {
650 dpm_table->count = 1;
651 dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.socclk / 100;
652 dpm_table->dpm_levels[0].enabled = true;
653 dpm_table->min = dpm_table->dpm_levels[0].value;
654 dpm_table->max = dpm_table->dpm_levels[0].value;
655 }
656
657 /* gfxclk dpm table setup */
658 dpm_table = &dpm_context->dpm_tables.gfx_table;
659 if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT)) {
660 ret = smu_v11_0_set_single_dpm_table(smu,
661 SMU_GFXCLK,
662 dpm_table);
663 if (ret)
664 return ret;
665 dpm_table->is_fine_grained =
666 !driver_ppt->DpmDescriptor[PPCLK_GFXCLK].SnapToDiscrete;
667 } else {
668 dpm_table->count = 1;
669 dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.gfxclk / 100;
670 dpm_table->dpm_levels[0].enabled = true;
671 dpm_table->min = dpm_table->dpm_levels[0].value;
672 dpm_table->max = dpm_table->dpm_levels[0].value;
673 }
674
675 /* uclk dpm table setup */
676 dpm_table = &dpm_context->dpm_tables.uclk_table;
677 if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) {
678 ret = smu_v11_0_set_single_dpm_table(smu,
679 SMU_UCLK,
680 dpm_table);
681 if (ret)
682 return ret;
683 dpm_table->is_fine_grained =
684 !driver_ppt->DpmDescriptor[PPCLK_UCLK].SnapToDiscrete;
685 } else {
686 dpm_table->count = 1;
687 dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.uclk / 100;
688 dpm_table->dpm_levels[0].enabled = true;
689 dpm_table->min = dpm_table->dpm_levels[0].value;
690 dpm_table->max = dpm_table->dpm_levels[0].value;
691 }
692
693 /* vclk dpm table setup */
694 dpm_table = &dpm_context->dpm_tables.vclk_table;
695 if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) {
696 ret = smu_v11_0_set_single_dpm_table(smu,
697 SMU_VCLK,
698 dpm_table);
699 if (ret)
700 return ret;
701 dpm_table->is_fine_grained =
702 !driver_ppt->DpmDescriptor[PPCLK_VCLK].SnapToDiscrete;
703 } else {
704 dpm_table->count = 1;
705 dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.vclk / 100;
706 dpm_table->dpm_levels[0].enabled = true;
707 dpm_table->min = dpm_table->dpm_levels[0].value;
708 dpm_table->max = dpm_table->dpm_levels[0].value;
709 }
710
711 /* dclk dpm table setup */
712 dpm_table = &dpm_context->dpm_tables.dclk_table;
713 if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) {
714 ret = smu_v11_0_set_single_dpm_table(smu,
715 SMU_DCLK,
716 dpm_table);
717 if (ret)
718 return ret;
719 dpm_table->is_fine_grained =
720 !driver_ppt->DpmDescriptor[PPCLK_DCLK].SnapToDiscrete;
721 } else {
722 dpm_table->count = 1;
723 dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dclk / 100;
724 dpm_table->dpm_levels[0].enabled = true;
725 dpm_table->min = dpm_table->dpm_levels[0].value;
726 dpm_table->max = dpm_table->dpm_levels[0].value;
727 }
728
729 /* dcefclk dpm table setup */
730 dpm_table = &dpm_context->dpm_tables.dcef_table;
731 if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) {
732 ret = smu_v11_0_set_single_dpm_table(smu,
733 SMU_DCEFCLK,
734 dpm_table);
735 if (ret)
736 return ret;
737 dpm_table->is_fine_grained =
738 !driver_ppt->DpmDescriptor[PPCLK_DCEFCLK].SnapToDiscrete;
739 } else {
740 dpm_table->count = 1;
741 dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dcefclk / 100;
742 dpm_table->dpm_levels[0].enabled = true;
743 dpm_table->min = dpm_table->dpm_levels[0].value;
744 dpm_table->max = dpm_table->dpm_levels[0].value;
745 }
746
747 /* pixelclk dpm table setup */
748 dpm_table = &dpm_context->dpm_tables.pixel_table;
749 if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) {
750 ret = smu_v11_0_set_single_dpm_table(smu,
751 SMU_PIXCLK,
752 dpm_table);
753 if (ret)
754 return ret;
755 dpm_table->is_fine_grained =
756 !driver_ppt->DpmDescriptor[PPCLK_PIXCLK].SnapToDiscrete;
757 } else {
758 dpm_table->count = 1;
759 dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dcefclk / 100;
760 dpm_table->dpm_levels[0].enabled = true;
761 dpm_table->min = dpm_table->dpm_levels[0].value;
762 dpm_table->max = dpm_table->dpm_levels[0].value;
763 }
764
765 /* displayclk dpm table setup */
766 dpm_table = &dpm_context->dpm_tables.display_table;
767 if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) {
768 ret = smu_v11_0_set_single_dpm_table(smu,
769 SMU_DISPCLK,
770 dpm_table);
771 if (ret)
772 return ret;
773 dpm_table->is_fine_grained =
774 !driver_ppt->DpmDescriptor[PPCLK_DISPCLK].SnapToDiscrete;
775 } else {
776 dpm_table->count = 1;
777 dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dcefclk / 100;
778 dpm_table->dpm_levels[0].enabled = true;
779 dpm_table->min = dpm_table->dpm_levels[0].value;
780 dpm_table->max = dpm_table->dpm_levels[0].value;
781 }
782
783 /* phyclk dpm table setup */
784 dpm_table = &dpm_context->dpm_tables.phy_table;
785 if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) {
786 ret = smu_v11_0_set_single_dpm_table(smu,
787 SMU_PHYCLK,
788 dpm_table);
789 if (ret)
790 return ret;
791 dpm_table->is_fine_grained =
792 !driver_ppt->DpmDescriptor[PPCLK_PHYCLK].SnapToDiscrete;
793 } else {
794 dpm_table->count = 1;
795 dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dcefclk / 100;
796 dpm_table->dpm_levels[0].enabled = true;
797 dpm_table->min = dpm_table->dpm_levels[0].value;
798 dpm_table->max = dpm_table->dpm_levels[0].value;
799 }
800
801 return 0;
802 }
803
navi10_dpm_set_vcn_enable(struct smu_context * smu,bool enable)804 static int navi10_dpm_set_vcn_enable(struct smu_context *smu, bool enable)
805 {
806 int ret = 0;
807
808 if (enable) {
809 /* vcn dpm on is a prerequisite for vcn power gate messages */
810 if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) {
811 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerUpVcn, 1, NULL);
812 if (ret)
813 return ret;
814 }
815 } else {
816 if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) {
817 ret = smu_cmn_send_smc_msg(smu, SMU_MSG_PowerDownVcn, NULL);
818 if (ret)
819 return ret;
820 }
821 }
822
823 return ret;
824 }
825
navi10_dpm_set_jpeg_enable(struct smu_context * smu,bool enable)826 static int navi10_dpm_set_jpeg_enable(struct smu_context *smu, bool enable)
827 {
828 int ret = 0;
829
830 if (enable) {
831 if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_JPEG_PG_BIT)) {
832 ret = smu_cmn_send_smc_msg(smu, SMU_MSG_PowerUpJpeg, NULL);
833 if (ret)
834 return ret;
835 }
836 } else {
837 if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_JPEG_PG_BIT)) {
838 ret = smu_cmn_send_smc_msg(smu, SMU_MSG_PowerDownJpeg, NULL);
839 if (ret)
840 return ret;
841 }
842 }
843
844 return ret;
845 }
846
navi10_get_current_clk_freq_by_table(struct smu_context * smu,enum smu_clk_type clk_type,uint32_t * value)847 static int navi10_get_current_clk_freq_by_table(struct smu_context *smu,
848 enum smu_clk_type clk_type,
849 uint32_t *value)
850 {
851 MetricsMember_t member_type;
852 int clk_id = 0;
853
854 clk_id = smu_cmn_to_asic_specific_index(smu,
855 CMN2ASIC_MAPPING_CLK,
856 clk_type);
857 if (clk_id < 0)
858 return clk_id;
859
860 switch (clk_id) {
861 case PPCLK_GFXCLK:
862 member_type = METRICS_CURR_GFXCLK;
863 break;
864 case PPCLK_UCLK:
865 member_type = METRICS_CURR_UCLK;
866 break;
867 case PPCLK_SOCCLK:
868 member_type = METRICS_CURR_SOCCLK;
869 break;
870 case PPCLK_VCLK:
871 member_type = METRICS_CURR_VCLK;
872 break;
873 case PPCLK_DCLK:
874 member_type = METRICS_CURR_DCLK;
875 break;
876 case PPCLK_DCEFCLK:
877 member_type = METRICS_CURR_DCEFCLK;
878 break;
879 default:
880 return -EINVAL;
881 }
882
883 return navi10_get_smu_metrics_data(smu,
884 member_type,
885 value);
886 }
887
navi10_is_support_fine_grained_dpm(struct smu_context * smu,enum smu_clk_type clk_type)888 static bool navi10_is_support_fine_grained_dpm(struct smu_context *smu, enum smu_clk_type clk_type)
889 {
890 PPTable_t *pptable = smu->smu_table.driver_pptable;
891 DpmDescriptor_t *dpm_desc = NULL;
892 uint32_t clk_index = 0;
893
894 clk_index = smu_cmn_to_asic_specific_index(smu,
895 CMN2ASIC_MAPPING_CLK,
896 clk_type);
897 dpm_desc = &pptable->DpmDescriptor[clk_index];
898
899 /* 0 - Fine grained DPM, 1 - Discrete DPM */
900 return dpm_desc->SnapToDiscrete == 0 ? true : false;
901 }
902
navi10_od_feature_is_supported(struct smu_11_0_overdrive_table * od_table,enum SMU_11_0_ODFEATURE_CAP cap)903 static inline bool navi10_od_feature_is_supported(struct smu_11_0_overdrive_table *od_table, enum SMU_11_0_ODFEATURE_CAP cap)
904 {
905 return od_table->cap[cap];
906 }
907
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)908 static void navi10_od_setting_get_range(struct smu_11_0_overdrive_table *od_table,
909 enum SMU_11_0_ODSETTING_ID setting,
910 uint32_t *min, uint32_t *max)
911 {
912 if (min)
913 *min = od_table->min[setting];
914 if (max)
915 *max = od_table->max[setting];
916 }
917
navi10_print_clk_levels(struct smu_context * smu,enum smu_clk_type clk_type,char * buf)918 static int navi10_print_clk_levels(struct smu_context *smu,
919 enum smu_clk_type clk_type, char *buf)
920 {
921 uint16_t *curve_settings;
922 int i, size = 0, ret = 0;
923 uint32_t cur_value = 0, value = 0, count = 0;
924 uint32_t freq_values[3] = {0};
925 uint32_t mark_index = 0;
926 struct smu_table_context *table_context = &smu->smu_table;
927 uint32_t gen_speed, lane_width;
928 struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
929 struct smu_11_0_dpm_context *dpm_context = smu_dpm->dpm_context;
930 PPTable_t *pptable = (PPTable_t *)table_context->driver_pptable;
931 OverDriveTable_t *od_table =
932 (OverDriveTable_t *)table_context->overdrive_table;
933 struct smu_11_0_overdrive_table *od_settings = smu->od_settings;
934 uint32_t min_value, max_value;
935
936 switch (clk_type) {
937 case SMU_GFXCLK:
938 case SMU_SCLK:
939 case SMU_SOCCLK:
940 case SMU_MCLK:
941 case SMU_UCLK:
942 case SMU_FCLK:
943 case SMU_DCEFCLK:
944 ret = navi10_get_current_clk_freq_by_table(smu, clk_type, &cur_value);
945 if (ret)
946 return size;
947
948 ret = smu_v11_0_get_dpm_level_count(smu, clk_type, &count);
949 if (ret)
950 return size;
951
952 if (!navi10_is_support_fine_grained_dpm(smu, clk_type)) {
953 for (i = 0; i < count; i++) {
954 ret = smu_v11_0_get_dpm_freq_by_index(smu, clk_type, i, &value);
955 if (ret)
956 return size;
957
958 size += sprintf(buf + size, "%d: %uMhz %s\n", i, value,
959 cur_value == value ? "*" : "");
960 }
961 } else {
962 ret = smu_v11_0_get_dpm_freq_by_index(smu, clk_type, 0, &freq_values[0]);
963 if (ret)
964 return size;
965 ret = smu_v11_0_get_dpm_freq_by_index(smu, clk_type, count - 1, &freq_values[2]);
966 if (ret)
967 return size;
968
969 freq_values[1] = cur_value;
970 mark_index = cur_value == freq_values[0] ? 0 :
971 cur_value == freq_values[2] ? 2 : 1;
972 if (mark_index != 1)
973 freq_values[1] = (freq_values[0] + freq_values[2]) / 2;
974
975 for (i = 0; i < 3; i++) {
976 size += sprintf(buf + size, "%d: %uMhz %s\n", i, freq_values[i],
977 i == mark_index ? "*" : "");
978 }
979
980 }
981 break;
982 case SMU_PCIE:
983 gen_speed = smu_v11_0_get_current_pcie_link_speed_level(smu);
984 lane_width = smu_v11_0_get_current_pcie_link_width_level(smu);
985 for (i = 0; i < NUM_LINK_LEVELS; i++)
986 size += sprintf(buf + size, "%d: %s %s %dMhz %s\n", i,
987 (dpm_context->dpm_tables.pcie_table.pcie_gen[i] == 0) ? "2.5GT/s," :
988 (dpm_context->dpm_tables.pcie_table.pcie_gen[i] == 1) ? "5.0GT/s," :
989 (dpm_context->dpm_tables.pcie_table.pcie_gen[i] == 2) ? "8.0GT/s," :
990 (dpm_context->dpm_tables.pcie_table.pcie_gen[i] == 3) ? "16.0GT/s," : "",
991 (dpm_context->dpm_tables.pcie_table.pcie_lane[i] == 1) ? "x1" :
992 (dpm_context->dpm_tables.pcie_table.pcie_lane[i] == 2) ? "x2" :
993 (dpm_context->dpm_tables.pcie_table.pcie_lane[i] == 3) ? "x4" :
994 (dpm_context->dpm_tables.pcie_table.pcie_lane[i] == 4) ? "x8" :
995 (dpm_context->dpm_tables.pcie_table.pcie_lane[i] == 5) ? "x12" :
996 (dpm_context->dpm_tables.pcie_table.pcie_lane[i] == 6) ? "x16" : "",
997 pptable->LclkFreq[i],
998 (gen_speed == dpm_context->dpm_tables.pcie_table.pcie_gen[i]) &&
999 (lane_width == dpm_context->dpm_tables.pcie_table.pcie_lane[i]) ?
1000 "*" : "");
1001 break;
1002 case SMU_OD_SCLK:
1003 if (!smu->od_enabled || !od_table || !od_settings)
1004 break;
1005 if (!navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_GFXCLK_LIMITS))
1006 break;
1007 size += sprintf(buf + size, "OD_SCLK:\n");
1008 size += sprintf(buf + size, "0: %uMhz\n1: %uMhz\n", od_table->GfxclkFmin, od_table->GfxclkFmax);
1009 break;
1010 case SMU_OD_MCLK:
1011 if (!smu->od_enabled || !od_table || !od_settings)
1012 break;
1013 if (!navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_UCLK_MAX))
1014 break;
1015 size += sprintf(buf + size, "OD_MCLK:\n");
1016 size += sprintf(buf + size, "1: %uMHz\n", od_table->UclkFmax);
1017 break;
1018 case SMU_OD_VDDC_CURVE:
1019 if (!smu->od_enabled || !od_table || !od_settings)
1020 break;
1021 if (!navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_GFXCLK_CURVE))
1022 break;
1023 size += sprintf(buf + size, "OD_VDDC_CURVE:\n");
1024 for (i = 0; i < 3; i++) {
1025 switch (i) {
1026 case 0:
1027 curve_settings = &od_table->GfxclkFreq1;
1028 break;
1029 case 1:
1030 curve_settings = &od_table->GfxclkFreq2;
1031 break;
1032 case 2:
1033 curve_settings = &od_table->GfxclkFreq3;
1034 break;
1035 default:
1036 break;
1037 }
1038 size += sprintf(buf + size, "%d: %uMHz %umV\n", i, curve_settings[0], curve_settings[1] / NAVI10_VOLTAGE_SCALE);
1039 }
1040 break;
1041 case SMU_OD_RANGE:
1042 if (!smu->od_enabled || !od_table || !od_settings)
1043 break;
1044 size = sprintf(buf, "%s:\n", "OD_RANGE");
1045
1046 if (navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_GFXCLK_LIMITS)) {
1047 navi10_od_setting_get_range(od_settings, SMU_11_0_ODSETTING_GFXCLKFMIN,
1048 &min_value, NULL);
1049 navi10_od_setting_get_range(od_settings, SMU_11_0_ODSETTING_GFXCLKFMAX,
1050 NULL, &max_value);
1051 size += sprintf(buf + size, "SCLK: %7uMhz %10uMhz\n",
1052 min_value, max_value);
1053 }
1054
1055 if (navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_UCLK_MAX)) {
1056 navi10_od_setting_get_range(od_settings, SMU_11_0_ODSETTING_UCLKFMAX,
1057 &min_value, &max_value);
1058 size += sprintf(buf + size, "MCLK: %7uMhz %10uMhz\n",
1059 min_value, max_value);
1060 }
1061
1062 if (navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_GFXCLK_CURVE)) {
1063 navi10_od_setting_get_range(od_settings, SMU_11_0_ODSETTING_VDDGFXCURVEFREQ_P1,
1064 &min_value, &max_value);
1065 size += sprintf(buf + size, "VDDC_CURVE_SCLK[0]: %7uMhz %10uMhz\n",
1066 min_value, max_value);
1067 navi10_od_setting_get_range(od_settings, SMU_11_0_ODSETTING_VDDGFXCURVEVOLTAGE_P1,
1068 &min_value, &max_value);
1069 size += sprintf(buf + size, "VDDC_CURVE_VOLT[0]: %7dmV %11dmV\n",
1070 min_value, max_value);
1071 navi10_od_setting_get_range(od_settings, SMU_11_0_ODSETTING_VDDGFXCURVEFREQ_P2,
1072 &min_value, &max_value);
1073 size += sprintf(buf + size, "VDDC_CURVE_SCLK[1]: %7uMhz %10uMhz\n",
1074 min_value, max_value);
1075 navi10_od_setting_get_range(od_settings, SMU_11_0_ODSETTING_VDDGFXCURVEVOLTAGE_P2,
1076 &min_value, &max_value);
1077 size += sprintf(buf + size, "VDDC_CURVE_VOLT[1]: %7dmV %11dmV\n",
1078 min_value, max_value);
1079 navi10_od_setting_get_range(od_settings, SMU_11_0_ODSETTING_VDDGFXCURVEFREQ_P3,
1080 &min_value, &max_value);
1081 size += sprintf(buf + size, "VDDC_CURVE_SCLK[2]: %7uMhz %10uMhz\n",
1082 min_value, max_value);
1083 navi10_od_setting_get_range(od_settings, SMU_11_0_ODSETTING_VDDGFXCURVEVOLTAGE_P3,
1084 &min_value, &max_value);
1085 size += sprintf(buf + size, "VDDC_CURVE_VOLT[2]: %7dmV %11dmV\n",
1086 min_value, max_value);
1087 }
1088
1089 break;
1090 default:
1091 break;
1092 }
1093
1094 return size;
1095 }
1096
navi10_force_clk_levels(struct smu_context * smu,enum smu_clk_type clk_type,uint32_t mask)1097 static int navi10_force_clk_levels(struct smu_context *smu,
1098 enum smu_clk_type clk_type, uint32_t mask)
1099 {
1100
1101 int ret = 0, size = 0;
1102 uint32_t soft_min_level = 0, soft_max_level = 0, min_freq = 0, max_freq = 0;
1103
1104 soft_min_level = mask ? (ffs(mask) - 1) : 0;
1105 soft_max_level = mask ? (fls(mask) - 1) : 0;
1106
1107 switch (clk_type) {
1108 case SMU_GFXCLK:
1109 case SMU_SCLK:
1110 case SMU_SOCCLK:
1111 case SMU_MCLK:
1112 case SMU_UCLK:
1113 case SMU_FCLK:
1114 /* There is only 2 levels for fine grained DPM */
1115 if (navi10_is_support_fine_grained_dpm(smu, clk_type)) {
1116 soft_max_level = (soft_max_level >= 1 ? 1 : 0);
1117 soft_min_level = (soft_min_level >= 1 ? 1 : 0);
1118 }
1119
1120 ret = smu_v11_0_get_dpm_freq_by_index(smu, clk_type, soft_min_level, &min_freq);
1121 if (ret)
1122 return size;
1123
1124 ret = smu_v11_0_get_dpm_freq_by_index(smu, clk_type, soft_max_level, &max_freq);
1125 if (ret)
1126 return size;
1127
1128 ret = smu_v11_0_set_soft_freq_limited_range(smu, clk_type, min_freq, max_freq);
1129 if (ret)
1130 return size;
1131 break;
1132 case SMU_DCEFCLK:
1133 dev_info(smu->adev->dev,"Setting DCEFCLK min/max dpm level is not supported!\n");
1134 break;
1135
1136 default:
1137 break;
1138 }
1139
1140 return size;
1141 }
1142
navi10_populate_umd_state_clk(struct smu_context * smu)1143 static int navi10_populate_umd_state_clk(struct smu_context *smu)
1144 {
1145 struct smu_11_0_dpm_context *dpm_context =
1146 smu->smu_dpm.dpm_context;
1147 struct smu_11_0_dpm_table *gfx_table =
1148 &dpm_context->dpm_tables.gfx_table;
1149 struct smu_11_0_dpm_table *mem_table =
1150 &dpm_context->dpm_tables.uclk_table;
1151 struct smu_11_0_dpm_table *soc_table =
1152 &dpm_context->dpm_tables.soc_table;
1153 struct smu_umd_pstate_table *pstate_table =
1154 &smu->pstate_table;
1155 struct amdgpu_device *adev = smu->adev;
1156 uint32_t sclk_freq;
1157
1158 pstate_table->gfxclk_pstate.min = gfx_table->min;
1159 switch (adev->asic_type) {
1160 case CHIP_NAVI10:
1161 switch (adev->pdev->revision) {
1162 case 0xf0: /* XTX */
1163 case 0xc0:
1164 sclk_freq = NAVI10_PEAK_SCLK_XTX;
1165 break;
1166 case 0xf1: /* XT */
1167 case 0xc1:
1168 sclk_freq = NAVI10_PEAK_SCLK_XT;
1169 break;
1170 default: /* XL */
1171 sclk_freq = NAVI10_PEAK_SCLK_XL;
1172 break;
1173 }
1174 break;
1175 case CHIP_NAVI14:
1176 switch (adev->pdev->revision) {
1177 case 0xc7: /* XT */
1178 case 0xf4:
1179 sclk_freq = NAVI14_UMD_PSTATE_PEAK_XT_GFXCLK;
1180 break;
1181 case 0xc1: /* XTM */
1182 case 0xf2:
1183 sclk_freq = NAVI14_UMD_PSTATE_PEAK_XTM_GFXCLK;
1184 break;
1185 case 0xc3: /* XLM */
1186 case 0xf3:
1187 sclk_freq = NAVI14_UMD_PSTATE_PEAK_XLM_GFXCLK;
1188 break;
1189 case 0xc5: /* XTX */
1190 case 0xf6:
1191 sclk_freq = NAVI14_UMD_PSTATE_PEAK_XLM_GFXCLK;
1192 break;
1193 default: /* XL */
1194 sclk_freq = NAVI14_UMD_PSTATE_PEAK_XL_GFXCLK;
1195 break;
1196 }
1197 break;
1198 case CHIP_NAVI12:
1199 sclk_freq = NAVI12_UMD_PSTATE_PEAK_GFXCLK;
1200 break;
1201 default:
1202 sclk_freq = gfx_table->dpm_levels[gfx_table->count - 1].value;
1203 break;
1204 }
1205 pstate_table->gfxclk_pstate.peak = sclk_freq;
1206
1207 pstate_table->uclk_pstate.min = mem_table->min;
1208 pstate_table->uclk_pstate.peak = mem_table->max;
1209
1210 pstate_table->socclk_pstate.min = soc_table->min;
1211 pstate_table->socclk_pstate.peak = soc_table->max;
1212
1213 if (gfx_table->max > NAVI10_UMD_PSTATE_PROFILING_GFXCLK &&
1214 mem_table->max > NAVI10_UMD_PSTATE_PROFILING_MEMCLK &&
1215 soc_table->max > NAVI10_UMD_PSTATE_PROFILING_SOCCLK) {
1216 pstate_table->gfxclk_pstate.standard =
1217 NAVI10_UMD_PSTATE_PROFILING_GFXCLK;
1218 pstate_table->uclk_pstate.standard =
1219 NAVI10_UMD_PSTATE_PROFILING_MEMCLK;
1220 pstate_table->socclk_pstate.standard =
1221 NAVI10_UMD_PSTATE_PROFILING_SOCCLK;
1222 } else {
1223 pstate_table->gfxclk_pstate.standard =
1224 pstate_table->gfxclk_pstate.min;
1225 pstate_table->uclk_pstate.standard =
1226 pstate_table->uclk_pstate.min;
1227 pstate_table->socclk_pstate.standard =
1228 pstate_table->socclk_pstate.min;
1229 }
1230
1231 return 0;
1232 }
1233
navi10_get_clock_by_type_with_latency(struct smu_context * smu,enum smu_clk_type clk_type,struct pp_clock_levels_with_latency * clocks)1234 static int navi10_get_clock_by_type_with_latency(struct smu_context *smu,
1235 enum smu_clk_type clk_type,
1236 struct pp_clock_levels_with_latency *clocks)
1237 {
1238 int ret = 0, i = 0;
1239 uint32_t level_count = 0, freq = 0;
1240
1241 switch (clk_type) {
1242 case SMU_GFXCLK:
1243 case SMU_DCEFCLK:
1244 case SMU_SOCCLK:
1245 case SMU_MCLK:
1246 case SMU_UCLK:
1247 ret = smu_v11_0_get_dpm_level_count(smu, clk_type, &level_count);
1248 if (ret)
1249 return ret;
1250
1251 level_count = min(level_count, (uint32_t)MAX_NUM_CLOCKS);
1252 clocks->num_levels = level_count;
1253
1254 for (i = 0; i < level_count; i++) {
1255 ret = smu_v11_0_get_dpm_freq_by_index(smu, clk_type, i, &freq);
1256 if (ret)
1257 return ret;
1258
1259 clocks->data[i].clocks_in_khz = freq * 1000;
1260 clocks->data[i].latency_in_us = 0;
1261 }
1262 break;
1263 default:
1264 break;
1265 }
1266
1267 return ret;
1268 }
1269
navi10_pre_display_config_changed(struct smu_context * smu)1270 static int navi10_pre_display_config_changed(struct smu_context *smu)
1271 {
1272 int ret = 0;
1273 uint32_t max_freq = 0;
1274
1275 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_NumOfDisplays, 0, NULL);
1276 if (ret)
1277 return ret;
1278
1279 if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) {
1280 ret = smu_v11_0_get_dpm_ultimate_freq(smu, SMU_UCLK, NULL, &max_freq);
1281 if (ret)
1282 return ret;
1283 ret = smu_v11_0_set_hard_freq_limited_range(smu, SMU_UCLK, 0, max_freq);
1284 if (ret)
1285 return ret;
1286 }
1287
1288 return ret;
1289 }
1290
navi10_display_config_changed(struct smu_context * smu)1291 static int navi10_display_config_changed(struct smu_context *smu)
1292 {
1293 int ret = 0;
1294
1295 if ((smu->watermarks_bitmap & WATERMARKS_EXIST) &&
1296 smu_cmn_feature_is_supported(smu, SMU_FEATURE_DPM_DCEFCLK_BIT) &&
1297 smu_cmn_feature_is_supported(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) {
1298 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_NumOfDisplays,
1299 smu->display_config->num_display,
1300 NULL);
1301 if (ret)
1302 return ret;
1303 }
1304
1305 return ret;
1306 }
1307
navi10_get_gpu_power(struct smu_context * smu,uint32_t * value)1308 static int navi10_get_gpu_power(struct smu_context *smu, uint32_t *value)
1309 {
1310 if (!value)
1311 return -EINVAL;
1312
1313 return navi10_get_smu_metrics_data(smu,
1314 METRICS_AVERAGE_SOCKETPOWER,
1315 value);
1316 }
1317
navi10_get_current_activity_percent(struct smu_context * smu,enum amd_pp_sensors sensor,uint32_t * value)1318 static int navi10_get_current_activity_percent(struct smu_context *smu,
1319 enum amd_pp_sensors sensor,
1320 uint32_t *value)
1321 {
1322 int ret = 0;
1323
1324 if (!value)
1325 return -EINVAL;
1326
1327 switch (sensor) {
1328 case AMDGPU_PP_SENSOR_GPU_LOAD:
1329 ret = navi10_get_smu_metrics_data(smu,
1330 METRICS_AVERAGE_GFXACTIVITY,
1331 value);
1332 break;
1333 case AMDGPU_PP_SENSOR_MEM_LOAD:
1334 ret = navi10_get_smu_metrics_data(smu,
1335 METRICS_AVERAGE_MEMACTIVITY,
1336 value);
1337 break;
1338 default:
1339 dev_err(smu->adev->dev, "Invalid sensor for retrieving clock activity\n");
1340 return -EINVAL;
1341 }
1342
1343 return ret;
1344 }
1345
navi10_is_dpm_running(struct smu_context * smu)1346 static bool navi10_is_dpm_running(struct smu_context *smu)
1347 {
1348 int ret = 0;
1349 uint32_t feature_mask[2];
1350 uint64_t feature_enabled;
1351
1352 ret = smu_cmn_get_enabled_mask(smu, feature_mask, 2);
1353 if (ret)
1354 return false;
1355
1356 feature_enabled = (uint64_t)feature_mask[1] << 32 | feature_mask[0];
1357
1358 return !!(feature_enabled & SMC_DPM_FEATURE);
1359 }
1360
navi10_get_fan_speed_rpm(struct smu_context * smu,uint32_t * speed)1361 static int navi10_get_fan_speed_rpm(struct smu_context *smu,
1362 uint32_t *speed)
1363 {
1364 if (!speed)
1365 return -EINVAL;
1366
1367 return navi10_get_smu_metrics_data(smu,
1368 METRICS_CURR_FANSPEED,
1369 speed);
1370 }
1371
navi10_get_fan_parameters(struct smu_context * smu)1372 static int navi10_get_fan_parameters(struct smu_context *smu)
1373 {
1374 PPTable_t *pptable = smu->smu_table.driver_pptable;
1375
1376 smu->fan_max_rpm = pptable->FanMaximumRpm;
1377
1378 return 0;
1379 }
1380
navi10_get_power_profile_mode(struct smu_context * smu,char * buf)1381 static int navi10_get_power_profile_mode(struct smu_context *smu, char *buf)
1382 {
1383 DpmActivityMonitorCoeffInt_t activity_monitor;
1384 uint32_t i, size = 0;
1385 int16_t workload_type = 0;
1386 static const char *profile_name[] = {
1387 "BOOTUP_DEFAULT",
1388 "3D_FULL_SCREEN",
1389 "POWER_SAVING",
1390 "VIDEO",
1391 "VR",
1392 "COMPUTE",
1393 "CUSTOM"};
1394 static const char *title[] = {
1395 "PROFILE_INDEX(NAME)",
1396 "CLOCK_TYPE(NAME)",
1397 "FPS",
1398 "MinFreqType",
1399 "MinActiveFreqType",
1400 "MinActiveFreq",
1401 "BoosterFreqType",
1402 "BoosterFreq",
1403 "PD_Data_limit_c",
1404 "PD_Data_error_coeff",
1405 "PD_Data_error_rate_coeff"};
1406 int result = 0;
1407
1408 if (!buf)
1409 return -EINVAL;
1410
1411 size += sprintf(buf + size, "%16s %s %s %s %s %s %s %s %s %s %s\n",
1412 title[0], title[1], title[2], title[3], title[4], title[5],
1413 title[6], title[7], title[8], title[9], title[10]);
1414
1415 for (i = 0; i <= PP_SMC_POWER_PROFILE_CUSTOM; i++) {
1416 /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
1417 workload_type = smu_cmn_to_asic_specific_index(smu,
1418 CMN2ASIC_MAPPING_WORKLOAD,
1419 i);
1420 if (workload_type < 0)
1421 return -EINVAL;
1422
1423 result = smu_cmn_update_table(smu,
1424 SMU_TABLE_ACTIVITY_MONITOR_COEFF, workload_type,
1425 (void *)(&activity_monitor), false);
1426 if (result) {
1427 dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__);
1428 return result;
1429 }
1430
1431 size += sprintf(buf + size, "%2d %14s%s:\n",
1432 i, profile_name[i], (i == smu->power_profile_mode) ? "*" : " ");
1433
1434 size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
1435 " ",
1436 0,
1437 "GFXCLK",
1438 activity_monitor.Gfx_FPS,
1439 activity_monitor.Gfx_MinFreqStep,
1440 activity_monitor.Gfx_MinActiveFreqType,
1441 activity_monitor.Gfx_MinActiveFreq,
1442 activity_monitor.Gfx_BoosterFreqType,
1443 activity_monitor.Gfx_BoosterFreq,
1444 activity_monitor.Gfx_PD_Data_limit_c,
1445 activity_monitor.Gfx_PD_Data_error_coeff,
1446 activity_monitor.Gfx_PD_Data_error_rate_coeff);
1447
1448 size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
1449 " ",
1450 1,
1451 "SOCCLK",
1452 activity_monitor.Soc_FPS,
1453 activity_monitor.Soc_MinFreqStep,
1454 activity_monitor.Soc_MinActiveFreqType,
1455 activity_monitor.Soc_MinActiveFreq,
1456 activity_monitor.Soc_BoosterFreqType,
1457 activity_monitor.Soc_BoosterFreq,
1458 activity_monitor.Soc_PD_Data_limit_c,
1459 activity_monitor.Soc_PD_Data_error_coeff,
1460 activity_monitor.Soc_PD_Data_error_rate_coeff);
1461
1462 size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
1463 " ",
1464 2,
1465 "MEMLK",
1466 activity_monitor.Mem_FPS,
1467 activity_monitor.Mem_MinFreqStep,
1468 activity_monitor.Mem_MinActiveFreqType,
1469 activity_monitor.Mem_MinActiveFreq,
1470 activity_monitor.Mem_BoosterFreqType,
1471 activity_monitor.Mem_BoosterFreq,
1472 activity_monitor.Mem_PD_Data_limit_c,
1473 activity_monitor.Mem_PD_Data_error_coeff,
1474 activity_monitor.Mem_PD_Data_error_rate_coeff);
1475 }
1476
1477 return size;
1478 }
1479
navi10_set_power_profile_mode(struct smu_context * smu,long * input,uint32_t size)1480 static int navi10_set_power_profile_mode(struct smu_context *smu, long *input, uint32_t size)
1481 {
1482 DpmActivityMonitorCoeffInt_t activity_monitor;
1483 int workload_type, ret = 0;
1484
1485 smu->power_profile_mode = input[size];
1486
1487 if (smu->power_profile_mode > PP_SMC_POWER_PROFILE_CUSTOM) {
1488 dev_err(smu->adev->dev, "Invalid power profile mode %d\n", smu->power_profile_mode);
1489 return -EINVAL;
1490 }
1491
1492 if (smu->power_profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) {
1493
1494 ret = smu_cmn_update_table(smu,
1495 SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT,
1496 (void *)(&activity_monitor), false);
1497 if (ret) {
1498 dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__);
1499 return ret;
1500 }
1501
1502 switch (input[0]) {
1503 case 0: /* Gfxclk */
1504 activity_monitor.Gfx_FPS = input[1];
1505 activity_monitor.Gfx_MinFreqStep = input[2];
1506 activity_monitor.Gfx_MinActiveFreqType = input[3];
1507 activity_monitor.Gfx_MinActiveFreq = input[4];
1508 activity_monitor.Gfx_BoosterFreqType = input[5];
1509 activity_monitor.Gfx_BoosterFreq = input[6];
1510 activity_monitor.Gfx_PD_Data_limit_c = input[7];
1511 activity_monitor.Gfx_PD_Data_error_coeff = input[8];
1512 activity_monitor.Gfx_PD_Data_error_rate_coeff = input[9];
1513 break;
1514 case 1: /* Socclk */
1515 activity_monitor.Soc_FPS = input[1];
1516 activity_monitor.Soc_MinFreqStep = input[2];
1517 activity_monitor.Soc_MinActiveFreqType = input[3];
1518 activity_monitor.Soc_MinActiveFreq = input[4];
1519 activity_monitor.Soc_BoosterFreqType = input[5];
1520 activity_monitor.Soc_BoosterFreq = input[6];
1521 activity_monitor.Soc_PD_Data_limit_c = input[7];
1522 activity_monitor.Soc_PD_Data_error_coeff = input[8];
1523 activity_monitor.Soc_PD_Data_error_rate_coeff = input[9];
1524 break;
1525 case 2: /* Memlk */
1526 activity_monitor.Mem_FPS = input[1];
1527 activity_monitor.Mem_MinFreqStep = input[2];
1528 activity_monitor.Mem_MinActiveFreqType = input[3];
1529 activity_monitor.Mem_MinActiveFreq = input[4];
1530 activity_monitor.Mem_BoosterFreqType = input[5];
1531 activity_monitor.Mem_BoosterFreq = input[6];
1532 activity_monitor.Mem_PD_Data_limit_c = input[7];
1533 activity_monitor.Mem_PD_Data_error_coeff = input[8];
1534 activity_monitor.Mem_PD_Data_error_rate_coeff = input[9];
1535 break;
1536 }
1537
1538 ret = smu_cmn_update_table(smu,
1539 SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT,
1540 (void *)(&activity_monitor), true);
1541 if (ret) {
1542 dev_err(smu->adev->dev, "[%s] Failed to set activity monitor!", __func__);
1543 return ret;
1544 }
1545 }
1546
1547 /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
1548 workload_type = smu_cmn_to_asic_specific_index(smu,
1549 CMN2ASIC_MAPPING_WORKLOAD,
1550 smu->power_profile_mode);
1551 if (workload_type < 0)
1552 return -EINVAL;
1553 smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask,
1554 1 << workload_type, NULL);
1555
1556 return ret;
1557 }
1558
navi10_notify_smc_display_config(struct smu_context * smu)1559 static int navi10_notify_smc_display_config(struct smu_context *smu)
1560 {
1561 struct smu_clocks min_clocks = {0};
1562 struct pp_display_clock_request clock_req;
1563 int ret = 0;
1564
1565 min_clocks.dcef_clock = smu->display_config->min_dcef_set_clk;
1566 min_clocks.dcef_clock_in_sr = smu->display_config->min_dcef_deep_sleep_set_clk;
1567 min_clocks.memory_clock = smu->display_config->min_mem_set_clock;
1568
1569 if (smu_cmn_feature_is_supported(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) {
1570 clock_req.clock_type = amd_pp_dcef_clock;
1571 clock_req.clock_freq_in_khz = min_clocks.dcef_clock * 10;
1572
1573 ret = smu_v11_0_display_clock_voltage_request(smu, &clock_req);
1574 if (!ret) {
1575 if (smu_cmn_feature_is_supported(smu, SMU_FEATURE_DS_DCEFCLK_BIT)) {
1576 ret = smu_cmn_send_smc_msg_with_param(smu,
1577 SMU_MSG_SetMinDeepSleepDcefclk,
1578 min_clocks.dcef_clock_in_sr/100,
1579 NULL);
1580 if (ret) {
1581 dev_err(smu->adev->dev, "Attempt to set divider for DCEFCLK Failed!");
1582 return ret;
1583 }
1584 }
1585 } else {
1586 dev_info(smu->adev->dev, "Attempt to set Hard Min for DCEFCLK Failed!");
1587 }
1588 }
1589
1590 if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) {
1591 ret = smu_v11_0_set_hard_freq_limited_range(smu, SMU_UCLK, min_clocks.memory_clock/100, 0);
1592 if (ret) {
1593 dev_err(smu->adev->dev, "[%s] Set hard min uclk failed!", __func__);
1594 return ret;
1595 }
1596 }
1597
1598 return 0;
1599 }
1600
navi10_set_watermarks_table(struct smu_context * smu,struct pp_smu_wm_range_sets * clock_ranges)1601 static int navi10_set_watermarks_table(struct smu_context *smu,
1602 struct pp_smu_wm_range_sets *clock_ranges)
1603 {
1604 Watermarks_t *table = smu->smu_table.watermarks_table;
1605 int ret = 0;
1606 int i;
1607
1608 if (clock_ranges) {
1609 if (clock_ranges->num_reader_wm_sets > NUM_WM_RANGES ||
1610 clock_ranges->num_writer_wm_sets > NUM_WM_RANGES)
1611 return -EINVAL;
1612
1613 for (i = 0; i < clock_ranges->num_reader_wm_sets; i++) {
1614 table->WatermarkRow[WM_DCEFCLK][i].MinClock =
1615 clock_ranges->reader_wm_sets[i].min_drain_clk_mhz;
1616 table->WatermarkRow[WM_DCEFCLK][i].MaxClock =
1617 clock_ranges->reader_wm_sets[i].max_drain_clk_mhz;
1618 table->WatermarkRow[WM_DCEFCLK][i].MinUclk =
1619 clock_ranges->reader_wm_sets[i].min_fill_clk_mhz;
1620 table->WatermarkRow[WM_DCEFCLK][i].MaxUclk =
1621 clock_ranges->reader_wm_sets[i].max_fill_clk_mhz;
1622
1623 table->WatermarkRow[WM_DCEFCLK][i].WmSetting =
1624 clock_ranges->reader_wm_sets[i].wm_inst;
1625 }
1626
1627 for (i = 0; i < clock_ranges->num_writer_wm_sets; i++) {
1628 table->WatermarkRow[WM_SOCCLK][i].MinClock =
1629 clock_ranges->writer_wm_sets[i].min_fill_clk_mhz;
1630 table->WatermarkRow[WM_SOCCLK][i].MaxClock =
1631 clock_ranges->writer_wm_sets[i].max_fill_clk_mhz;
1632 table->WatermarkRow[WM_SOCCLK][i].MinUclk =
1633 clock_ranges->writer_wm_sets[i].min_drain_clk_mhz;
1634 table->WatermarkRow[WM_SOCCLK][i].MaxUclk =
1635 clock_ranges->writer_wm_sets[i].max_drain_clk_mhz;
1636
1637 table->WatermarkRow[WM_SOCCLK][i].WmSetting =
1638 clock_ranges->writer_wm_sets[i].wm_inst;
1639 }
1640
1641 smu->watermarks_bitmap |= WATERMARKS_EXIST;
1642 }
1643
1644 /* pass data to smu controller */
1645 if ((smu->watermarks_bitmap & WATERMARKS_EXIST) &&
1646 !(smu->watermarks_bitmap & WATERMARKS_LOADED)) {
1647 ret = smu_cmn_write_watermarks_table(smu);
1648 if (ret) {
1649 dev_err(smu->adev->dev, "Failed to update WMTABLE!");
1650 return ret;
1651 }
1652 smu->watermarks_bitmap |= WATERMARKS_LOADED;
1653 }
1654
1655 return 0;
1656 }
1657
navi10_thermal_get_temperature(struct smu_context * smu,enum amd_pp_sensors sensor,uint32_t * value)1658 static int navi10_thermal_get_temperature(struct smu_context *smu,
1659 enum amd_pp_sensors sensor,
1660 uint32_t *value)
1661 {
1662 int ret = 0;
1663
1664 if (!value)
1665 return -EINVAL;
1666
1667 switch (sensor) {
1668 case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
1669 ret = navi10_get_smu_metrics_data(smu,
1670 METRICS_TEMPERATURE_HOTSPOT,
1671 value);
1672 break;
1673 case AMDGPU_PP_SENSOR_EDGE_TEMP:
1674 ret = navi10_get_smu_metrics_data(smu,
1675 METRICS_TEMPERATURE_EDGE,
1676 value);
1677 break;
1678 case AMDGPU_PP_SENSOR_MEM_TEMP:
1679 ret = navi10_get_smu_metrics_data(smu,
1680 METRICS_TEMPERATURE_MEM,
1681 value);
1682 break;
1683 default:
1684 dev_err(smu->adev->dev, "Invalid sensor for retrieving temp\n");
1685 return -EINVAL;
1686 }
1687
1688 return ret;
1689 }
1690
navi10_read_sensor(struct smu_context * smu,enum amd_pp_sensors sensor,void * data,uint32_t * size)1691 static int navi10_read_sensor(struct smu_context *smu,
1692 enum amd_pp_sensors sensor,
1693 void *data, uint32_t *size)
1694 {
1695 int ret = 0;
1696 struct smu_table_context *table_context = &smu->smu_table;
1697 PPTable_t *pptable = table_context->driver_pptable;
1698
1699 if(!data || !size)
1700 return -EINVAL;
1701
1702 mutex_lock(&smu->sensor_lock);
1703 switch (sensor) {
1704 case AMDGPU_PP_SENSOR_MAX_FAN_RPM:
1705 *(uint32_t *)data = pptable->FanMaximumRpm;
1706 *size = 4;
1707 break;
1708 case AMDGPU_PP_SENSOR_MEM_LOAD:
1709 case AMDGPU_PP_SENSOR_GPU_LOAD:
1710 ret = navi10_get_current_activity_percent(smu, sensor, (uint32_t *)data);
1711 *size = 4;
1712 break;
1713 case AMDGPU_PP_SENSOR_GPU_POWER:
1714 ret = navi10_get_gpu_power(smu, (uint32_t *)data);
1715 *size = 4;
1716 break;
1717 case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
1718 case AMDGPU_PP_SENSOR_EDGE_TEMP:
1719 case AMDGPU_PP_SENSOR_MEM_TEMP:
1720 ret = navi10_thermal_get_temperature(smu, sensor, (uint32_t *)data);
1721 *size = 4;
1722 break;
1723 case AMDGPU_PP_SENSOR_GFX_MCLK:
1724 ret = navi10_get_current_clk_freq_by_table(smu, SMU_UCLK, (uint32_t *)data);
1725 *(uint32_t *)data *= 100;
1726 *size = 4;
1727 break;
1728 case AMDGPU_PP_SENSOR_GFX_SCLK:
1729 ret = navi10_get_current_clk_freq_by_table(smu, SMU_GFXCLK, (uint32_t *)data);
1730 *(uint32_t *)data *= 100;
1731 *size = 4;
1732 break;
1733 case AMDGPU_PP_SENSOR_VDDGFX:
1734 ret = smu_v11_0_get_gfx_vdd(smu, (uint32_t *)data);
1735 *size = 4;
1736 break;
1737 default:
1738 ret = -EOPNOTSUPP;
1739 break;
1740 }
1741 mutex_unlock(&smu->sensor_lock);
1742
1743 return ret;
1744 }
1745
navi10_get_uclk_dpm_states(struct smu_context * smu,uint32_t * clocks_in_khz,uint32_t * num_states)1746 static int navi10_get_uclk_dpm_states(struct smu_context *smu, uint32_t *clocks_in_khz, uint32_t *num_states)
1747 {
1748 uint32_t num_discrete_levels = 0;
1749 uint16_t *dpm_levels = NULL;
1750 uint16_t i = 0;
1751 struct smu_table_context *table_context = &smu->smu_table;
1752 PPTable_t *driver_ppt = NULL;
1753
1754 if (!clocks_in_khz || !num_states || !table_context->driver_pptable)
1755 return -EINVAL;
1756
1757 driver_ppt = table_context->driver_pptable;
1758 num_discrete_levels = driver_ppt->DpmDescriptor[PPCLK_UCLK].NumDiscreteLevels;
1759 dpm_levels = driver_ppt->FreqTableUclk;
1760
1761 if (num_discrete_levels == 0 || dpm_levels == NULL)
1762 return -EINVAL;
1763
1764 *num_states = num_discrete_levels;
1765 for (i = 0; i < num_discrete_levels; i++) {
1766 /* convert to khz */
1767 *clocks_in_khz = (*dpm_levels) * 1000;
1768 clocks_in_khz++;
1769 dpm_levels++;
1770 }
1771
1772 return 0;
1773 }
1774
navi10_get_thermal_temperature_range(struct smu_context * smu,struct smu_temperature_range * range)1775 static int navi10_get_thermal_temperature_range(struct smu_context *smu,
1776 struct smu_temperature_range *range)
1777 {
1778 struct smu_table_context *table_context = &smu->smu_table;
1779 struct smu_11_0_powerplay_table *powerplay_table =
1780 table_context->power_play_table;
1781 PPTable_t *pptable = smu->smu_table.driver_pptable;
1782
1783 if (!range)
1784 return -EINVAL;
1785
1786 memcpy(range, &smu11_thermal_policy[0], sizeof(struct smu_temperature_range));
1787
1788 range->max = pptable->TedgeLimit *
1789 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
1790 range->edge_emergency_max = (pptable->TedgeLimit + CTF_OFFSET_EDGE) *
1791 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
1792 range->hotspot_crit_max = pptable->ThotspotLimit *
1793 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
1794 range->hotspot_emergency_max = (pptable->ThotspotLimit + CTF_OFFSET_HOTSPOT) *
1795 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
1796 range->mem_crit_max = pptable->TmemLimit *
1797 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
1798 range->mem_emergency_max = (pptable->TmemLimit + CTF_OFFSET_MEM)*
1799 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
1800 range->software_shutdown_temp = powerplay_table->software_shutdown_temp;
1801
1802 return 0;
1803 }
1804
navi10_display_disable_memory_clock_switch(struct smu_context * smu,bool disable_memory_clock_switch)1805 static int navi10_display_disable_memory_clock_switch(struct smu_context *smu,
1806 bool disable_memory_clock_switch)
1807 {
1808 int ret = 0;
1809 struct smu_11_0_max_sustainable_clocks *max_sustainable_clocks =
1810 (struct smu_11_0_max_sustainable_clocks *)
1811 smu->smu_table.max_sustainable_clocks;
1812 uint32_t min_memory_clock = smu->hard_min_uclk_req_from_dal;
1813 uint32_t max_memory_clock = max_sustainable_clocks->uclock;
1814
1815 if(smu->disable_uclk_switch == disable_memory_clock_switch)
1816 return 0;
1817
1818 if(disable_memory_clock_switch)
1819 ret = smu_v11_0_set_hard_freq_limited_range(smu, SMU_UCLK, max_memory_clock, 0);
1820 else
1821 ret = smu_v11_0_set_hard_freq_limited_range(smu, SMU_UCLK, min_memory_clock, 0);
1822
1823 if(!ret)
1824 smu->disable_uclk_switch = disable_memory_clock_switch;
1825
1826 return ret;
1827 }
1828
navi10_get_power_limit(struct smu_context * smu)1829 static int navi10_get_power_limit(struct smu_context *smu)
1830 {
1831 struct smu_11_0_powerplay_table *powerplay_table =
1832 (struct smu_11_0_powerplay_table *)smu->smu_table.power_play_table;
1833 struct smu_11_0_overdrive_table *od_settings = smu->od_settings;
1834 PPTable_t *pptable = smu->smu_table.driver_pptable;
1835 uint32_t power_limit, od_percent;
1836
1837 if (smu_v11_0_get_current_power_limit(smu, &power_limit)) {
1838 /* the last hope to figure out the ppt limit */
1839 if (!pptable) {
1840 dev_err(smu->adev->dev, "Cannot get PPT limit due to pptable missing!");
1841 return -EINVAL;
1842 }
1843 power_limit =
1844 pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0];
1845 }
1846 smu->current_power_limit = power_limit;
1847
1848 if (smu->od_enabled &&
1849 navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_POWER_LIMIT)) {
1850 od_percent = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_11_0_ODSETTING_POWERPERCENTAGE]);
1851
1852 dev_dbg(smu->adev->dev, "ODSETTING_POWERPERCENTAGE: %d (default: %d)\n", od_percent, power_limit);
1853
1854 power_limit *= (100 + od_percent);
1855 power_limit /= 100;
1856 }
1857 smu->max_power_limit = power_limit;
1858
1859 return 0;
1860 }
1861
navi10_update_pcie_parameters(struct smu_context * smu,uint32_t pcie_gen_cap,uint32_t pcie_width_cap)1862 static int navi10_update_pcie_parameters(struct smu_context *smu,
1863 uint32_t pcie_gen_cap,
1864 uint32_t pcie_width_cap)
1865 {
1866 struct smu_11_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context;
1867 PPTable_t *pptable = smu->smu_table.driver_pptable;
1868 uint32_t smu_pcie_arg;
1869 int ret, i;
1870
1871 /* lclk dpm table setup */
1872 for (i = 0; i < MAX_PCIE_CONF; i++) {
1873 dpm_context->dpm_tables.pcie_table.pcie_gen[i] = pptable->PcieGenSpeed[i];
1874 dpm_context->dpm_tables.pcie_table.pcie_lane[i] = pptable->PcieLaneCount[i];
1875 }
1876
1877 for (i = 0; i < NUM_LINK_LEVELS; i++) {
1878 smu_pcie_arg = (i << 16) |
1879 ((pptable->PcieGenSpeed[i] <= pcie_gen_cap) ? (pptable->PcieGenSpeed[i] << 8) :
1880 (pcie_gen_cap << 8)) | ((pptable->PcieLaneCount[i] <= pcie_width_cap) ?
1881 pptable->PcieLaneCount[i] : pcie_width_cap);
1882 ret = smu_cmn_send_smc_msg_with_param(smu,
1883 SMU_MSG_OverridePcieParameters,
1884 smu_pcie_arg,
1885 NULL);
1886
1887 if (ret)
1888 return ret;
1889
1890 if (pptable->PcieGenSpeed[i] > pcie_gen_cap)
1891 dpm_context->dpm_tables.pcie_table.pcie_gen[i] = pcie_gen_cap;
1892 if (pptable->PcieLaneCount[i] > pcie_width_cap)
1893 dpm_context->dpm_tables.pcie_table.pcie_lane[i] = pcie_width_cap;
1894 }
1895
1896 return 0;
1897 }
1898
navi10_dump_od_table(struct smu_context * smu,OverDriveTable_t * od_table)1899 static inline void navi10_dump_od_table(struct smu_context *smu,
1900 OverDriveTable_t *od_table)
1901 {
1902 dev_dbg(smu->adev->dev, "OD: Gfxclk: (%d, %d)\n", od_table->GfxclkFmin, od_table->GfxclkFmax);
1903 dev_dbg(smu->adev->dev, "OD: Gfx1: (%d, %d)\n", od_table->GfxclkFreq1, od_table->GfxclkVolt1);
1904 dev_dbg(smu->adev->dev, "OD: Gfx2: (%d, %d)\n", od_table->GfxclkFreq2, od_table->GfxclkVolt2);
1905 dev_dbg(smu->adev->dev, "OD: Gfx3: (%d, %d)\n", od_table->GfxclkFreq3, od_table->GfxclkVolt3);
1906 dev_dbg(smu->adev->dev, "OD: UclkFmax: %d\n", od_table->UclkFmax);
1907 dev_dbg(smu->adev->dev, "OD: OverDrivePct: %d\n", od_table->OverDrivePct);
1908 }
1909
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)1910 static int navi10_od_setting_check_range(struct smu_context *smu,
1911 struct smu_11_0_overdrive_table *od_table,
1912 enum SMU_11_0_ODSETTING_ID setting,
1913 uint32_t value)
1914 {
1915 if (value < od_table->min[setting]) {
1916 dev_warn(smu->adev->dev, "OD setting (%d, %d) is less than the minimum allowed (%d)\n", setting, value, od_table->min[setting]);
1917 return -EINVAL;
1918 }
1919 if (value > od_table->max[setting]) {
1920 dev_warn(smu->adev->dev, "OD setting (%d, %d) is greater than the maximum allowed (%d)\n", setting, value, od_table->max[setting]);
1921 return -EINVAL;
1922 }
1923 return 0;
1924 }
1925
navi10_overdrive_get_gfx_clk_base_voltage(struct smu_context * smu,uint16_t * voltage,uint32_t freq)1926 static int navi10_overdrive_get_gfx_clk_base_voltage(struct smu_context *smu,
1927 uint16_t *voltage,
1928 uint32_t freq)
1929 {
1930 uint32_t param = (freq & 0xFFFF) | (PPCLK_GFXCLK << 16);
1931 uint32_t value = 0;
1932 int ret;
1933
1934 ret = smu_cmn_send_smc_msg_with_param(smu,
1935 SMU_MSG_GetVoltageByDpm,
1936 param,
1937 &value);
1938 if (ret) {
1939 dev_err(smu->adev->dev, "[GetBaseVoltage] failed to get GFXCLK AVFS voltage from SMU!");
1940 return ret;
1941 }
1942
1943 *voltage = (uint16_t)value;
1944
1945 return 0;
1946 }
1947
navi10_is_baco_supported(struct smu_context * smu)1948 static bool navi10_is_baco_supported(struct smu_context *smu)
1949 {
1950 struct amdgpu_device *adev = smu->adev;
1951 uint32_t val;
1952
1953 if (amdgpu_sriov_vf(adev) || (!smu_v11_0_baco_is_support(smu)))
1954 return false;
1955
1956 val = RREG32_SOC15(NBIO, 0, mmRCC_BIF_STRAP0);
1957 return (val & RCC_BIF_STRAP0__STRAP_PX_CAPABLE_MASK) ? true : false;
1958 }
1959
navi10_set_default_od_settings(struct smu_context * smu)1960 static int navi10_set_default_od_settings(struct smu_context *smu)
1961 {
1962 OverDriveTable_t *od_table =
1963 (OverDriveTable_t *)smu->smu_table.overdrive_table;
1964 OverDriveTable_t *boot_od_table =
1965 (OverDriveTable_t *)smu->smu_table.boot_overdrive_table;
1966 int ret = 0;
1967
1968 ret = smu_cmn_update_table(smu, SMU_TABLE_OVERDRIVE, 0, (void *)od_table, false);
1969 if (ret) {
1970 dev_err(smu->adev->dev, "Failed to get overdrive table!\n");
1971 return ret;
1972 }
1973
1974 if (!od_table->GfxclkVolt1) {
1975 ret = navi10_overdrive_get_gfx_clk_base_voltage(smu,
1976 &od_table->GfxclkVolt1,
1977 od_table->GfxclkFreq1);
1978 if (ret)
1979 return ret;
1980 }
1981
1982 if (!od_table->GfxclkVolt2) {
1983 ret = navi10_overdrive_get_gfx_clk_base_voltage(smu,
1984 &od_table->GfxclkVolt2,
1985 od_table->GfxclkFreq2);
1986 if (ret)
1987 return ret;
1988 }
1989
1990 if (!od_table->GfxclkVolt3) {
1991 ret = navi10_overdrive_get_gfx_clk_base_voltage(smu,
1992 &od_table->GfxclkVolt3,
1993 od_table->GfxclkFreq3);
1994 if (ret)
1995 return ret;
1996 }
1997
1998 memcpy(boot_od_table, od_table, sizeof(OverDriveTable_t));
1999
2000 navi10_dump_od_table(smu, od_table);
2001
2002 return 0;
2003 }
2004
navi10_od_edit_dpm_table(struct smu_context * smu,enum PP_OD_DPM_TABLE_COMMAND type,long input[],uint32_t size)2005 static int navi10_od_edit_dpm_table(struct smu_context *smu, enum PP_OD_DPM_TABLE_COMMAND type, long input[], uint32_t size) {
2006 int i;
2007 int ret = 0;
2008 struct smu_table_context *table_context = &smu->smu_table;
2009 OverDriveTable_t *od_table;
2010 struct smu_11_0_overdrive_table *od_settings;
2011 enum SMU_11_0_ODSETTING_ID freq_setting, voltage_setting;
2012 uint16_t *freq_ptr, *voltage_ptr;
2013 od_table = (OverDriveTable_t *)table_context->overdrive_table;
2014
2015 if (!smu->od_enabled) {
2016 dev_warn(smu->adev->dev, "OverDrive is not enabled!\n");
2017 return -EINVAL;
2018 }
2019
2020 if (!smu->od_settings) {
2021 dev_err(smu->adev->dev, "OD board limits are not set!\n");
2022 return -ENOENT;
2023 }
2024
2025 od_settings = smu->od_settings;
2026
2027 switch (type) {
2028 case PP_OD_EDIT_SCLK_VDDC_TABLE:
2029 if (!navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_GFXCLK_LIMITS)) {
2030 dev_warn(smu->adev->dev, "GFXCLK_LIMITS not supported!\n");
2031 return -ENOTSUPP;
2032 }
2033 if (!table_context->overdrive_table) {
2034 dev_err(smu->adev->dev, "Overdrive is not initialized\n");
2035 return -EINVAL;
2036 }
2037 for (i = 0; i < size; i += 2) {
2038 if (i + 2 > size) {
2039 dev_info(smu->adev->dev, "invalid number of input parameters %d\n", size);
2040 return -EINVAL;
2041 }
2042 switch (input[i]) {
2043 case 0:
2044 freq_setting = SMU_11_0_ODSETTING_GFXCLKFMIN;
2045 freq_ptr = &od_table->GfxclkFmin;
2046 if (input[i + 1] > od_table->GfxclkFmax) {
2047 dev_info(smu->adev->dev, "GfxclkFmin (%ld) must be <= GfxclkFmax (%u)!\n",
2048 input[i + 1],
2049 od_table->GfxclkFmin);
2050 return -EINVAL;
2051 }
2052 break;
2053 case 1:
2054 freq_setting = SMU_11_0_ODSETTING_GFXCLKFMAX;
2055 freq_ptr = &od_table->GfxclkFmax;
2056 if (input[i + 1] < od_table->GfxclkFmin) {
2057 dev_info(smu->adev->dev, "GfxclkFmax (%ld) must be >= GfxclkFmin (%u)!\n",
2058 input[i + 1],
2059 od_table->GfxclkFmax);
2060 return -EINVAL;
2061 }
2062 break;
2063 default:
2064 dev_info(smu->adev->dev, "Invalid SCLK_VDDC_TABLE index: %ld\n", input[i]);
2065 dev_info(smu->adev->dev, "Supported indices: [0:min,1:max]\n");
2066 return -EINVAL;
2067 }
2068 ret = navi10_od_setting_check_range(smu, od_settings, freq_setting, input[i + 1]);
2069 if (ret)
2070 return ret;
2071 *freq_ptr = input[i + 1];
2072 }
2073 break;
2074 case PP_OD_EDIT_MCLK_VDDC_TABLE:
2075 if (!navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_UCLK_MAX)) {
2076 dev_warn(smu->adev->dev, "UCLK_MAX not supported!\n");
2077 return -ENOTSUPP;
2078 }
2079 if (size < 2) {
2080 dev_info(smu->adev->dev, "invalid number of parameters: %d\n", size);
2081 return -EINVAL;
2082 }
2083 if (input[0] != 1) {
2084 dev_info(smu->adev->dev, "Invalid MCLK_VDDC_TABLE index: %ld\n", input[0]);
2085 dev_info(smu->adev->dev, "Supported indices: [1:max]\n");
2086 return -EINVAL;
2087 }
2088 ret = navi10_od_setting_check_range(smu, od_settings, SMU_11_0_ODSETTING_UCLKFMAX, input[1]);
2089 if (ret)
2090 return ret;
2091 od_table->UclkFmax = input[1];
2092 break;
2093 case PP_OD_RESTORE_DEFAULT_TABLE:
2094 if (!(table_context->overdrive_table && table_context->boot_overdrive_table)) {
2095 dev_err(smu->adev->dev, "Overdrive table was not initialized!\n");
2096 return -EINVAL;
2097 }
2098 memcpy(table_context->overdrive_table, table_context->boot_overdrive_table, sizeof(OverDriveTable_t));
2099 break;
2100 case PP_OD_COMMIT_DPM_TABLE:
2101 navi10_dump_od_table(smu, od_table);
2102 ret = smu_cmn_update_table(smu, SMU_TABLE_OVERDRIVE, 0, (void *)od_table, true);
2103 if (ret) {
2104 dev_err(smu->adev->dev, "Failed to import overdrive table!\n");
2105 return ret;
2106 }
2107 break;
2108 case PP_OD_EDIT_VDDC_CURVE:
2109 if (!navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_GFXCLK_CURVE)) {
2110 dev_warn(smu->adev->dev, "GFXCLK_CURVE not supported!\n");
2111 return -ENOTSUPP;
2112 }
2113 if (size < 3) {
2114 dev_info(smu->adev->dev, "invalid number of parameters: %d\n", size);
2115 return -EINVAL;
2116 }
2117 if (!od_table) {
2118 dev_info(smu->adev->dev, "Overdrive is not initialized\n");
2119 return -EINVAL;
2120 }
2121
2122 switch (input[0]) {
2123 case 0:
2124 freq_setting = SMU_11_0_ODSETTING_VDDGFXCURVEFREQ_P1;
2125 voltage_setting = SMU_11_0_ODSETTING_VDDGFXCURVEVOLTAGE_P1;
2126 freq_ptr = &od_table->GfxclkFreq1;
2127 voltage_ptr = &od_table->GfxclkVolt1;
2128 break;
2129 case 1:
2130 freq_setting = SMU_11_0_ODSETTING_VDDGFXCURVEFREQ_P2;
2131 voltage_setting = SMU_11_0_ODSETTING_VDDGFXCURVEVOLTAGE_P2;
2132 freq_ptr = &od_table->GfxclkFreq2;
2133 voltage_ptr = &od_table->GfxclkVolt2;
2134 break;
2135 case 2:
2136 freq_setting = SMU_11_0_ODSETTING_VDDGFXCURVEFREQ_P3;
2137 voltage_setting = SMU_11_0_ODSETTING_VDDGFXCURVEVOLTAGE_P3;
2138 freq_ptr = &od_table->GfxclkFreq3;
2139 voltage_ptr = &od_table->GfxclkVolt3;
2140 break;
2141 default:
2142 dev_info(smu->adev->dev, "Invalid VDDC_CURVE index: %ld\n", input[0]);
2143 dev_info(smu->adev->dev, "Supported indices: [0, 1, 2]\n");
2144 return -EINVAL;
2145 }
2146 ret = navi10_od_setting_check_range(smu, od_settings, freq_setting, input[1]);
2147 if (ret)
2148 return ret;
2149 // Allow setting zero to disable the OverDrive VDDC curve
2150 if (input[2] != 0) {
2151 ret = navi10_od_setting_check_range(smu, od_settings, voltage_setting, input[2]);
2152 if (ret)
2153 return ret;
2154 *freq_ptr = input[1];
2155 *voltage_ptr = ((uint16_t)input[2]) * NAVI10_VOLTAGE_SCALE;
2156 dev_dbg(smu->adev->dev, "OD: set curve %ld: (%d, %d)\n", input[0], *freq_ptr, *voltage_ptr);
2157 } else {
2158 // If setting 0, disable all voltage curve settings
2159 od_table->GfxclkVolt1 = 0;
2160 od_table->GfxclkVolt2 = 0;
2161 od_table->GfxclkVolt3 = 0;
2162 }
2163 navi10_dump_od_table(smu, od_table);
2164 break;
2165 default:
2166 return -ENOSYS;
2167 }
2168 return ret;
2169 }
2170
navi10_run_btc(struct smu_context * smu)2171 static int navi10_run_btc(struct smu_context *smu)
2172 {
2173 int ret = 0;
2174
2175 ret = smu_cmn_send_smc_msg(smu, SMU_MSG_RunBtc, NULL);
2176 if (ret)
2177 dev_err(smu->adev->dev, "RunBtc failed!\n");
2178
2179 return ret;
2180 }
2181
navi10_need_umc_cdr_workaround(struct smu_context * smu)2182 static bool navi10_need_umc_cdr_workaround(struct smu_context *smu)
2183 {
2184 struct amdgpu_device *adev = smu->adev;
2185
2186 if (!smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT))
2187 return false;
2188
2189 if (adev->asic_type == CHIP_NAVI10 ||
2190 adev->asic_type == CHIP_NAVI14)
2191 return true;
2192
2193 return false;
2194 }
2195
navi10_umc_hybrid_cdr_workaround(struct smu_context * smu)2196 static int navi10_umc_hybrid_cdr_workaround(struct smu_context *smu)
2197 {
2198 uint32_t uclk_count, uclk_min, uclk_max;
2199 int ret = 0;
2200
2201 /* This workaround can be applied only with uclk dpm enabled */
2202 if (!smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT))
2203 return 0;
2204
2205 ret = smu_v11_0_get_dpm_level_count(smu, SMU_UCLK, &uclk_count);
2206 if (ret)
2207 return ret;
2208
2209 ret = smu_v11_0_get_dpm_freq_by_index(smu, SMU_UCLK, (uint16_t)(uclk_count - 1), &uclk_max);
2210 if (ret)
2211 return ret;
2212
2213 /*
2214 * The NAVI10_UMC_HYBRID_CDR_WORKAROUND_UCLK_THRESHOLD is 750Mhz.
2215 * This workaround is needed only when the max uclk frequency
2216 * not greater than that.
2217 */
2218 if (uclk_max > 0x2EE)
2219 return 0;
2220
2221 ret = smu_v11_0_get_dpm_freq_by_index(smu, SMU_UCLK, (uint16_t)0, &uclk_min);
2222 if (ret)
2223 return ret;
2224
2225 /* Force UCLK out of the highest DPM */
2226 ret = smu_v11_0_set_hard_freq_limited_range(smu, SMU_UCLK, 0, uclk_min);
2227 if (ret)
2228 return ret;
2229
2230 /* Revert the UCLK Hardmax */
2231 ret = smu_v11_0_set_hard_freq_limited_range(smu, SMU_UCLK, 0, uclk_max);
2232 if (ret)
2233 return ret;
2234
2235 /*
2236 * In this case, SMU already disabled dummy pstate during enablement
2237 * of UCLK DPM, we have to re-enabled it.
2238 */
2239 return smu_cmn_send_smc_msg(smu, SMU_MSG_DAL_ENABLE_DUMMY_PSTATE_CHANGE, NULL);
2240 }
2241
navi10_set_dummy_pstates_table_location(struct smu_context * smu)2242 static int navi10_set_dummy_pstates_table_location(struct smu_context *smu)
2243 {
2244 struct smu_table_context *smu_table = &smu->smu_table;
2245 struct smu_table *dummy_read_table =
2246 &smu_table->dummy_read_1_table;
2247 char *dummy_table = dummy_read_table->cpu_addr;
2248 int ret = 0;
2249 uint32_t i;
2250
2251 for (i = 0; i < 0x40000; i += 0x1000 * 2) {
2252 memcpy(dummy_table, &NoDbiPrbs7[0], 0x1000);
2253 dummy_table += 0x1000;
2254 memcpy(dummy_table, &DbiPrbs7[0], 0x1000);
2255 dummy_table += 0x1000;
2256 }
2257
2258 amdgpu_asic_flush_hdp(smu->adev, NULL);
2259
2260 ret = smu_cmn_send_smc_msg_with_param(smu,
2261 SMU_MSG_SET_DRIVER_DUMMY_TABLE_DRAM_ADDR_HIGH,
2262 upper_32_bits(dummy_read_table->mc_address),
2263 NULL);
2264 if (ret)
2265 return ret;
2266
2267 return smu_cmn_send_smc_msg_with_param(smu,
2268 SMU_MSG_SET_DRIVER_DUMMY_TABLE_DRAM_ADDR_LOW,
2269 lower_32_bits(dummy_read_table->mc_address),
2270 NULL);
2271 }
2272
navi10_run_umc_cdr_workaround(struct smu_context * smu)2273 static int navi10_run_umc_cdr_workaround(struct smu_context *smu)
2274 {
2275 struct amdgpu_device *adev = smu->adev;
2276 uint8_t umc_fw_greater_than_v136 = false;
2277 uint8_t umc_fw_disable_cdr = false;
2278 uint32_t pmfw_version;
2279 uint32_t param;
2280 int ret = 0;
2281
2282 if (!navi10_need_umc_cdr_workaround(smu))
2283 return 0;
2284
2285 ret = smu_cmn_get_smc_version(smu, NULL, &pmfw_version);
2286 if (ret) {
2287 dev_err(adev->dev, "Failed to get smu version!\n");
2288 return ret;
2289 }
2290
2291 /*
2292 * The messages below are only supported by Navi10 42.53.0 and later
2293 * PMFWs and Navi14 53.29.0 and later PMFWs.
2294 * - PPSMC_MSG_SetDriverDummyTableDramAddrHigh
2295 * - PPSMC_MSG_SetDriverDummyTableDramAddrLow
2296 * - PPSMC_MSG_GetUMCFWWA
2297 */
2298 if (((adev->asic_type == CHIP_NAVI10) && (pmfw_version >= 0x2a3500)) ||
2299 ((adev->asic_type == CHIP_NAVI14) && (pmfw_version >= 0x351D00))) {
2300 ret = smu_cmn_send_smc_msg_with_param(smu,
2301 SMU_MSG_GET_UMC_FW_WA,
2302 0,
2303 ¶m);
2304 if (ret)
2305 return ret;
2306
2307 /* First bit indicates if the UMC f/w is above v137 */
2308 umc_fw_greater_than_v136 = param & 0x1;
2309
2310 /* Second bit indicates if hybrid-cdr is disabled */
2311 umc_fw_disable_cdr = param & 0x2;
2312
2313 /* w/a only allowed if UMC f/w is <= 136 */
2314 if (umc_fw_greater_than_v136)
2315 return 0;
2316
2317 if (umc_fw_disable_cdr) {
2318 if (adev->asic_type == CHIP_NAVI10)
2319 return navi10_umc_hybrid_cdr_workaround(smu);
2320 } else {
2321 return navi10_set_dummy_pstates_table_location(smu);
2322 }
2323 } else {
2324 if (adev->asic_type == CHIP_NAVI10)
2325 return navi10_umc_hybrid_cdr_workaround(smu);
2326 }
2327
2328 return 0;
2329 }
2330
navi10_fill_i2c_req(SwI2cRequest_t * req,bool write,uint8_t address,uint32_t numbytes,uint8_t * data)2331 static void navi10_fill_i2c_req(SwI2cRequest_t *req, bool write,
2332 uint8_t address, uint32_t numbytes,
2333 uint8_t *data)
2334 {
2335 int i;
2336
2337 req->I2CcontrollerPort = 0;
2338 req->I2CSpeed = 2;
2339 req->SlaveAddress = address;
2340 req->NumCmds = numbytes;
2341
2342 for (i = 0; i < numbytes; i++) {
2343 SwI2cCmd_t *cmd = &req->SwI2cCmds[i];
2344
2345 /* First 2 bytes are always write for lower 2b EEPROM address */
2346 if (i < 2)
2347 cmd->Cmd = 1;
2348 else
2349 cmd->Cmd = write;
2350
2351
2352 /* Add RESTART for read after address filled */
2353 cmd->CmdConfig |= (i == 2 && !write) ? CMDCONFIG_RESTART_MASK : 0;
2354
2355 /* Add STOP in the end */
2356 cmd->CmdConfig |= (i == (numbytes - 1)) ? CMDCONFIG_STOP_MASK : 0;
2357
2358 /* Fill with data regardless if read or write to simplify code */
2359 cmd->RegisterAddr = data[i];
2360 }
2361 }
2362
navi10_i2c_read_data(struct i2c_adapter * control,uint8_t address,uint8_t * data,uint32_t numbytes)2363 static int navi10_i2c_read_data(struct i2c_adapter *control,
2364 uint8_t address,
2365 uint8_t *data,
2366 uint32_t numbytes)
2367 {
2368 uint32_t i, ret = 0;
2369 SwI2cRequest_t req;
2370 struct amdgpu_device *adev = to_amdgpu_device(control);
2371 struct smu_table_context *smu_table = &adev->smu.smu_table;
2372 struct smu_table *table = &smu_table->driver_table;
2373
2374 if (numbytes > MAX_SW_I2C_COMMANDS) {
2375 dev_err(adev->dev, "numbytes requested %d is over max allowed %d\n",
2376 numbytes, MAX_SW_I2C_COMMANDS);
2377 return -EINVAL;
2378 }
2379
2380 memset(&req, 0, sizeof(req));
2381 navi10_fill_i2c_req(&req, false, address, numbytes, data);
2382
2383 mutex_lock(&adev->smu.mutex);
2384 /* Now read data starting with that address */
2385 ret = smu_cmn_update_table(&adev->smu, SMU_TABLE_I2C_COMMANDS, 0, &req,
2386 true);
2387 mutex_unlock(&adev->smu.mutex);
2388
2389 if (!ret) {
2390 SwI2cRequest_t *res = (SwI2cRequest_t *)table->cpu_addr;
2391
2392 /* Assume SMU fills res.SwI2cCmds[i].Data with read bytes */
2393 for (i = 0; i < numbytes; i++)
2394 data[i] = res->SwI2cCmds[i].Data;
2395
2396 dev_dbg(adev->dev, "navi10_i2c_read_data, address = %x, bytes = %d, data :",
2397 (uint16_t)address, numbytes);
2398
2399 print_hex_dump(KERN_DEBUG, "data: ", DUMP_PREFIX_NONE,
2400 8, 1, data, numbytes, false);
2401 } else
2402 dev_err(adev->dev, "navi10_i2c_read_data - error occurred :%x", ret);
2403
2404 return ret;
2405 }
2406
navi10_i2c_write_data(struct i2c_adapter * control,uint8_t address,uint8_t * data,uint32_t numbytes)2407 static int navi10_i2c_write_data(struct i2c_adapter *control,
2408 uint8_t address,
2409 uint8_t *data,
2410 uint32_t numbytes)
2411 {
2412 uint32_t ret;
2413 SwI2cRequest_t req;
2414 struct amdgpu_device *adev = to_amdgpu_device(control);
2415
2416 if (numbytes > MAX_SW_I2C_COMMANDS) {
2417 dev_err(adev->dev, "numbytes requested %d is over max allowed %d\n",
2418 numbytes, MAX_SW_I2C_COMMANDS);
2419 return -EINVAL;
2420 }
2421
2422 memset(&req, 0, sizeof(req));
2423 navi10_fill_i2c_req(&req, true, address, numbytes, data);
2424
2425 mutex_lock(&adev->smu.mutex);
2426 ret = smu_cmn_update_table(&adev->smu, SMU_TABLE_I2C_COMMANDS, 0, &req, true);
2427 mutex_unlock(&adev->smu.mutex);
2428
2429 if (!ret) {
2430 dev_dbg(adev->dev, "navi10_i2c_write(), address = %x, bytes = %d , data: ",
2431 (uint16_t)address, numbytes);
2432
2433 print_hex_dump(KERN_DEBUG, "data: ", DUMP_PREFIX_NONE,
2434 8, 1, data, numbytes, false);
2435 /*
2436 * According to EEPROM spec there is a MAX of 10 ms required for
2437 * EEPROM to flush internal RX buffer after STOP was issued at the
2438 * end of write transaction. During this time the EEPROM will not be
2439 * responsive to any more commands - so wait a bit more.
2440 */
2441 msleep(10);
2442
2443 } else
2444 dev_err(adev->dev, "navi10_i2c_write- error occurred :%x", ret);
2445
2446 return ret;
2447 }
2448
navi10_i2c_xfer(struct i2c_adapter * i2c_adap,struct i2c_msg * msgs,int num)2449 static int navi10_i2c_xfer(struct i2c_adapter *i2c_adap,
2450 struct i2c_msg *msgs, int num)
2451 {
2452 uint32_t i, j, ret, data_size, data_chunk_size, next_eeprom_addr = 0;
2453 uint8_t *data_ptr, data_chunk[MAX_SW_I2C_COMMANDS] = { 0 };
2454
2455 for (i = 0; i < num; i++) {
2456 /*
2457 * SMU interface allows at most MAX_SW_I2C_COMMANDS bytes of data at
2458 * once and hence the data needs to be spliced into chunks and sent each
2459 * chunk separately
2460 */
2461 data_size = msgs[i].len - 2;
2462 data_chunk_size = MAX_SW_I2C_COMMANDS - 2;
2463 next_eeprom_addr = (msgs[i].buf[0] << 8 & 0xff00) | (msgs[i].buf[1] & 0xff);
2464 data_ptr = msgs[i].buf + 2;
2465
2466 for (j = 0; j < data_size / data_chunk_size; j++) {
2467 /* Insert the EEPROM dest addess, bits 0-15 */
2468 data_chunk[0] = ((next_eeprom_addr >> 8) & 0xff);
2469 data_chunk[1] = (next_eeprom_addr & 0xff);
2470
2471 if (msgs[i].flags & I2C_M_RD) {
2472 ret = navi10_i2c_read_data(i2c_adap,
2473 (uint8_t)msgs[i].addr,
2474 data_chunk, MAX_SW_I2C_COMMANDS);
2475
2476 memcpy(data_ptr, data_chunk + 2, data_chunk_size);
2477 } else {
2478
2479 memcpy(data_chunk + 2, data_ptr, data_chunk_size);
2480
2481 ret = navi10_i2c_write_data(i2c_adap,
2482 (uint8_t)msgs[i].addr,
2483 data_chunk, MAX_SW_I2C_COMMANDS);
2484 }
2485
2486 if (ret) {
2487 num = -EIO;
2488 goto fail;
2489 }
2490
2491 next_eeprom_addr += data_chunk_size;
2492 data_ptr += data_chunk_size;
2493 }
2494
2495 if (data_size % data_chunk_size) {
2496 data_chunk[0] = ((next_eeprom_addr >> 8) & 0xff);
2497 data_chunk[1] = (next_eeprom_addr & 0xff);
2498
2499 if (msgs[i].flags & I2C_M_RD) {
2500 ret = navi10_i2c_read_data(i2c_adap,
2501 (uint8_t)msgs[i].addr,
2502 data_chunk, (data_size % data_chunk_size) + 2);
2503
2504 memcpy(data_ptr, data_chunk + 2, data_size % data_chunk_size);
2505 } else {
2506 memcpy(data_chunk + 2, data_ptr, data_size % data_chunk_size);
2507
2508 ret = navi10_i2c_write_data(i2c_adap,
2509 (uint8_t)msgs[i].addr,
2510 data_chunk, (data_size % data_chunk_size) + 2);
2511 }
2512
2513 if (ret) {
2514 num = -EIO;
2515 goto fail;
2516 }
2517 }
2518 }
2519
2520 fail:
2521 return num;
2522 }
2523
navi10_i2c_func(struct i2c_adapter * adap)2524 static u32 navi10_i2c_func(struct i2c_adapter *adap)
2525 {
2526 return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
2527 }
2528
2529
2530 static const struct i2c_algorithm navi10_i2c_algo = {
2531 .master_xfer = navi10_i2c_xfer,
2532 .functionality = navi10_i2c_func,
2533 };
2534
navi10_get_gpu_metrics(struct smu_context * smu,void ** table)2535 static ssize_t navi10_get_gpu_metrics(struct smu_context *smu,
2536 void **table)
2537 {
2538 struct smu_table_context *smu_table = &smu->smu_table;
2539 struct gpu_metrics_v1_0 *gpu_metrics =
2540 (struct gpu_metrics_v1_0 *)smu_table->gpu_metrics_table;
2541 struct amdgpu_device *adev = smu->adev;
2542 SmuMetrics_NV12_t nv12_metrics = { 0 };
2543 SmuMetrics_t metrics;
2544 int ret = 0;
2545
2546 mutex_lock(&smu->metrics_lock);
2547
2548 ret = smu_cmn_get_metrics_table_locked(smu,
2549 NULL,
2550 true);
2551 if (ret) {
2552 mutex_unlock(&smu->metrics_lock);
2553 return ret;
2554 }
2555
2556 memcpy(&metrics, smu_table->metrics_table, sizeof(SmuMetrics_t));
2557 if (adev->asic_type == CHIP_NAVI12)
2558 memcpy(&nv12_metrics, smu_table->metrics_table, sizeof(SmuMetrics_NV12_t));
2559
2560 mutex_unlock(&smu->metrics_lock);
2561
2562 smu_v11_0_init_gpu_metrics_v1_0(gpu_metrics);
2563
2564 gpu_metrics->temperature_edge = metrics.TemperatureEdge;
2565 gpu_metrics->temperature_hotspot = metrics.TemperatureHotspot;
2566 gpu_metrics->temperature_mem = metrics.TemperatureMem;
2567 gpu_metrics->temperature_vrgfx = metrics.TemperatureVrGfx;
2568 gpu_metrics->temperature_vrsoc = metrics.TemperatureVrSoc;
2569 gpu_metrics->temperature_vrmem = metrics.TemperatureVrMem0;
2570
2571 gpu_metrics->average_gfx_activity = metrics.AverageGfxActivity;
2572 gpu_metrics->average_umc_activity = metrics.AverageUclkActivity;
2573
2574 gpu_metrics->average_socket_power = metrics.AverageSocketPower;
2575
2576 gpu_metrics->average_gfxclk_frequency = metrics.AverageGfxclkFrequency;
2577 gpu_metrics->average_socclk_frequency = metrics.AverageSocclkFrequency;
2578 gpu_metrics->average_uclk_frequency = metrics.AverageUclkFrequency;
2579
2580 if (adev->asic_type == CHIP_NAVI12) {
2581 gpu_metrics->energy_accumulator = nv12_metrics.EnergyAccumulator;
2582 gpu_metrics->average_vclk0_frequency = nv12_metrics.AverageVclkFrequency;
2583 gpu_metrics->average_dclk0_frequency = nv12_metrics.AverageDclkFrequency;
2584 gpu_metrics->average_mm_activity = nv12_metrics.VcnActivityPercentage;
2585 }
2586
2587 gpu_metrics->current_gfxclk = metrics.CurrClock[PPCLK_GFXCLK];
2588 gpu_metrics->current_socclk = metrics.CurrClock[PPCLK_SOCCLK];
2589 gpu_metrics->current_uclk = metrics.CurrClock[PPCLK_UCLK];
2590 gpu_metrics->current_vclk0 = metrics.CurrClock[PPCLK_VCLK];
2591 gpu_metrics->current_dclk0 = metrics.CurrClock[PPCLK_DCLK];
2592
2593 gpu_metrics->throttle_status = metrics.ThrottlerStatus;
2594
2595 gpu_metrics->current_fan_speed = metrics.CurrFanSpeed;
2596
2597 gpu_metrics->pcie_link_width =
2598 smu_v11_0_get_current_pcie_link_width(smu);
2599 gpu_metrics->pcie_link_speed =
2600 smu_v11_0_get_current_pcie_link_speed(smu);
2601
2602 *table = (void *)gpu_metrics;
2603
2604 return sizeof(struct gpu_metrics_v1_0);
2605 }
2606
navi10_enable_mgpu_fan_boost(struct smu_context * smu)2607 static int navi10_enable_mgpu_fan_boost(struct smu_context *smu)
2608 {
2609 struct smu_table_context *table_context = &smu->smu_table;
2610 PPTable_t *smc_pptable = table_context->driver_pptable;
2611 struct amdgpu_device *adev = smu->adev;
2612 uint32_t param = 0;
2613
2614 /* Navi12 does not support this */
2615 if (adev->asic_type == CHIP_NAVI12)
2616 return 0;
2617
2618 /*
2619 * Skip the MGpuFanBoost setting for those ASICs
2620 * which do not support it
2621 */
2622 if (!smc_pptable->MGpuFanBoostLimitRpm)
2623 return 0;
2624
2625 /* Workaround for WS SKU */
2626 if (adev->pdev->device == 0x7312 &&
2627 adev->pdev->revision == 0)
2628 param = 0xD188;
2629
2630 return smu_cmn_send_smc_msg_with_param(smu,
2631 SMU_MSG_SetMGpuFanBoostLimitRpm,
2632 param,
2633 NULL);
2634 }
2635
navi10_post_smu_init(struct smu_context * smu)2636 static int navi10_post_smu_init(struct smu_context *smu)
2637 {
2638 struct amdgpu_device *adev = smu->adev;
2639 int ret = 0;
2640
2641 if (amdgpu_sriov_vf(adev))
2642 return 0;
2643
2644 ret = navi10_run_umc_cdr_workaround(smu);
2645 if (ret) {
2646 dev_err(adev->dev, "Failed to apply umc cdr workaround!\n");
2647 return ret;
2648 }
2649
2650 if (!smu->dc_controlled_by_gpio) {
2651 /*
2652 * For Navi1X, manually switch it to AC mode as PMFW
2653 * may boot it with DC mode.
2654 */
2655 ret = smu_v11_0_set_power_source(smu,
2656 adev->pm.ac_power ?
2657 SMU_POWER_SOURCE_AC :
2658 SMU_POWER_SOURCE_DC);
2659 if (ret) {
2660 dev_err(adev->dev, "Failed to switch to %s mode!\n",
2661 adev->pm.ac_power ? "AC" : "DC");
2662 return ret;
2663 }
2664 }
2665
2666 return ret;
2667 }
2668
2669 static const struct pptable_funcs navi10_ppt_funcs = {
2670 .get_allowed_feature_mask = navi10_get_allowed_feature_mask,
2671 .set_default_dpm_table = navi10_set_default_dpm_table,
2672 .dpm_set_vcn_enable = navi10_dpm_set_vcn_enable,
2673 .dpm_set_jpeg_enable = navi10_dpm_set_jpeg_enable,
2674 .print_clk_levels = navi10_print_clk_levels,
2675 .force_clk_levels = navi10_force_clk_levels,
2676 .populate_umd_state_clk = navi10_populate_umd_state_clk,
2677 .get_clock_by_type_with_latency = navi10_get_clock_by_type_with_latency,
2678 .pre_display_config_changed = navi10_pre_display_config_changed,
2679 .display_config_changed = navi10_display_config_changed,
2680 .notify_smc_display_config = navi10_notify_smc_display_config,
2681 .is_dpm_running = navi10_is_dpm_running,
2682 .get_fan_speed_rpm = navi10_get_fan_speed_rpm,
2683 .get_power_profile_mode = navi10_get_power_profile_mode,
2684 .set_power_profile_mode = navi10_set_power_profile_mode,
2685 .set_watermarks_table = navi10_set_watermarks_table,
2686 .read_sensor = navi10_read_sensor,
2687 .get_uclk_dpm_states = navi10_get_uclk_dpm_states,
2688 .set_performance_level = smu_v11_0_set_performance_level,
2689 .get_thermal_temperature_range = navi10_get_thermal_temperature_range,
2690 .display_disable_memory_clock_switch = navi10_display_disable_memory_clock_switch,
2691 .get_power_limit = navi10_get_power_limit,
2692 .update_pcie_parameters = navi10_update_pcie_parameters,
2693 .init_microcode = smu_v11_0_init_microcode,
2694 .load_microcode = smu_v11_0_load_microcode,
2695 .fini_microcode = smu_v11_0_fini_microcode,
2696 .init_smc_tables = navi10_init_smc_tables,
2697 .fini_smc_tables = smu_v11_0_fini_smc_tables,
2698 .init_power = smu_v11_0_init_power,
2699 .fini_power = smu_v11_0_fini_power,
2700 .check_fw_status = smu_v11_0_check_fw_status,
2701 .setup_pptable = navi10_setup_pptable,
2702 .get_vbios_bootup_values = smu_v11_0_get_vbios_bootup_values,
2703 .check_fw_version = smu_v11_0_check_fw_version,
2704 .write_pptable = smu_cmn_write_pptable,
2705 .set_driver_table_location = smu_v11_0_set_driver_table_location,
2706 .set_tool_table_location = smu_v11_0_set_tool_table_location,
2707 .notify_memory_pool_location = smu_v11_0_notify_memory_pool_location,
2708 .system_features_control = smu_v11_0_system_features_control,
2709 .send_smc_msg_with_param = smu_cmn_send_smc_msg_with_param,
2710 .send_smc_msg = smu_cmn_send_smc_msg,
2711 .init_display_count = smu_v11_0_init_display_count,
2712 .set_allowed_mask = smu_v11_0_set_allowed_mask,
2713 .get_enabled_mask = smu_cmn_get_enabled_mask,
2714 .feature_is_enabled = smu_cmn_feature_is_enabled,
2715 .disable_all_features_with_exception = smu_cmn_disable_all_features_with_exception,
2716 .notify_display_change = smu_v11_0_notify_display_change,
2717 .set_power_limit = smu_v11_0_set_power_limit,
2718 .init_max_sustainable_clocks = smu_v11_0_init_max_sustainable_clocks,
2719 .enable_thermal_alert = smu_v11_0_enable_thermal_alert,
2720 .disable_thermal_alert = smu_v11_0_disable_thermal_alert,
2721 .set_min_dcef_deep_sleep = smu_v11_0_set_min_deep_sleep_dcefclk,
2722 .display_clock_voltage_request = smu_v11_0_display_clock_voltage_request,
2723 .get_fan_control_mode = smu_v11_0_get_fan_control_mode,
2724 .set_fan_control_mode = smu_v11_0_set_fan_control_mode,
2725 .set_fan_speed_percent = smu_v11_0_set_fan_speed_percent,
2726 .set_fan_speed_rpm = smu_v11_0_set_fan_speed_rpm,
2727 .set_xgmi_pstate = smu_v11_0_set_xgmi_pstate,
2728 .gfx_off_control = smu_v11_0_gfx_off_control,
2729 .register_irq_handler = smu_v11_0_register_irq_handler,
2730 .set_azalia_d3_pme = smu_v11_0_set_azalia_d3_pme,
2731 .get_max_sustainable_clocks_by_dc = smu_v11_0_get_max_sustainable_clocks_by_dc,
2732 .baco_is_support= navi10_is_baco_supported,
2733 .baco_get_state = smu_v11_0_baco_get_state,
2734 .baco_set_state = smu_v11_0_baco_set_state,
2735 .baco_enter = smu_v11_0_baco_enter,
2736 .baco_exit = smu_v11_0_baco_exit,
2737 .get_dpm_ultimate_freq = smu_v11_0_get_dpm_ultimate_freq,
2738 .set_soft_freq_limited_range = smu_v11_0_set_soft_freq_limited_range,
2739 .set_default_od_settings = navi10_set_default_od_settings,
2740 .od_edit_dpm_table = navi10_od_edit_dpm_table,
2741 .run_btc = navi10_run_btc,
2742 .set_power_source = smu_v11_0_set_power_source,
2743 .get_pp_feature_mask = smu_cmn_get_pp_feature_mask,
2744 .set_pp_feature_mask = smu_cmn_set_pp_feature_mask,
2745 .get_gpu_metrics = navi10_get_gpu_metrics,
2746 .enable_mgpu_fan_boost = navi10_enable_mgpu_fan_boost,
2747 .gfx_ulv_control = smu_v11_0_gfx_ulv_control,
2748 .deep_sleep_control = smu_v11_0_deep_sleep_control,
2749 .get_fan_parameters = navi10_get_fan_parameters,
2750 .post_init = navi10_post_smu_init,
2751 .interrupt_work = smu_v11_0_interrupt_work,
2752 };
2753
navi10_set_ppt_funcs(struct smu_context * smu)2754 void navi10_set_ppt_funcs(struct smu_context *smu)
2755 {
2756 smu->ppt_funcs = &navi10_ppt_funcs;
2757 smu->message_map = navi10_message_map;
2758 smu->clock_map = navi10_clk_map;
2759 smu->feature_map = navi10_feature_mask_map;
2760 smu->table_map = navi10_table_map;
2761 smu->pwr_src_map = navi10_pwr_src_map;
2762 smu->workload_map = navi10_workload_map;
2763 }
2764