Line data Source code
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 "amdgpu.h"
28 : #include "amdgpu_dpm.h"
29 : #include "amdgpu_smu.h"
30 : #include "atomfirmware.h"
31 : #include "amdgpu_atomfirmware.h"
32 : #include "amdgpu_atombios.h"
33 : #include "smu_v13_0.h"
34 : #include "smu13_driver_if_aldebaran.h"
35 : #include "soc15_common.h"
36 : #include "atom.h"
37 : #include "aldebaran_ppt.h"
38 : #include "smu_v13_0_pptable.h"
39 : #include "aldebaran_ppsmc.h"
40 : #include "nbio/nbio_7_4_offset.h"
41 : #include "nbio/nbio_7_4_sh_mask.h"
42 : #include "thm/thm_11_0_2_offset.h"
43 : #include "thm/thm_11_0_2_sh_mask.h"
44 : #include "amdgpu_xgmi.h"
45 : #include <linux/pci.h>
46 : #include "amdgpu_ras.h"
47 : #include "smu_cmn.h"
48 : #include "mp/mp_13_0_2_offset.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 ALDEBARAN_FEA_MAP(smu_feature, aldebaran_feature) \
61 : [smu_feature] = {1, (aldebaran_feature)}
62 :
63 : #define FEATURE_MASK(feature) (1ULL << feature)
64 : #define SMC_DPM_FEATURE ( \
65 : FEATURE_MASK(FEATURE_DATA_CALCULATIONS) | \
66 : FEATURE_MASK(FEATURE_DPM_GFXCLK_BIT) | \
67 : FEATURE_MASK(FEATURE_DPM_UCLK_BIT) | \
68 : FEATURE_MASK(FEATURE_DPM_SOCCLK_BIT) | \
69 : FEATURE_MASK(FEATURE_DPM_FCLK_BIT) | \
70 : FEATURE_MASK(FEATURE_DPM_LCLK_BIT) | \
71 : FEATURE_MASK(FEATURE_DPM_XGMI_BIT) | \
72 : FEATURE_MASK(FEATURE_DPM_VCN_BIT))
73 :
74 : /* possible frequency drift (1Mhz) */
75 : #define EPSILON 1
76 :
77 : #define smnPCIE_ESM_CTRL 0x111003D0
78 :
79 : /*
80 : * SMU support ECCTABLE since version 68.42.0,
81 : * use this to check ECCTALE feature whether support
82 : */
83 : #define SUPPORT_ECCTABLE_SMU_VERSION 0x00442a00
84 :
85 : /*
86 : * SMU support mca_ceumc_addr in ECCTABLE since version 68.55.0,
87 : * use this to check mca_ceumc_addr record whether support
88 : */
89 : #define SUPPORT_ECCTABLE_V2_SMU_VERSION 0x00443700
90 :
91 : /*
92 : * SMU support BAD CHENNEL info MSG since version 68.51.00,
93 : * use this to check ECCTALE feature whether support
94 : */
95 : #define SUPPORT_BAD_CHANNEL_INFO_MSG_VERSION 0x00443300
96 :
97 : static const struct smu_temperature_range smu13_thermal_policy[] =
98 : {
99 : {-273150, 99000, 99000, -273150, 99000, 99000, -273150, 99000, 99000},
100 : { 120000, 120000, 120000, 120000, 120000, 120000, 120000, 120000, 120000},
101 : };
102 :
103 : static const struct cmn2asic_msg_mapping aldebaran_message_map[SMU_MSG_MAX_COUNT] = {
104 : MSG_MAP(TestMessage, PPSMC_MSG_TestMessage, 0),
105 : MSG_MAP(GetSmuVersion, PPSMC_MSG_GetSmuVersion, 1),
106 : MSG_MAP(GetDriverIfVersion, PPSMC_MSG_GetDriverIfVersion, 1),
107 : MSG_MAP(EnableAllSmuFeatures, PPSMC_MSG_EnableAllSmuFeatures, 0),
108 : MSG_MAP(DisableAllSmuFeatures, PPSMC_MSG_DisableAllSmuFeatures, 0),
109 : MSG_MAP(GetEnabledSmuFeaturesLow, PPSMC_MSG_GetEnabledSmuFeaturesLow, 1),
110 : MSG_MAP(GetEnabledSmuFeaturesHigh, PPSMC_MSG_GetEnabledSmuFeaturesHigh, 1),
111 : MSG_MAP(SetDriverDramAddrHigh, PPSMC_MSG_SetDriverDramAddrHigh, 1),
112 : MSG_MAP(SetDriverDramAddrLow, PPSMC_MSG_SetDriverDramAddrLow, 1),
113 : MSG_MAP(SetToolsDramAddrHigh, PPSMC_MSG_SetToolsDramAddrHigh, 0),
114 : MSG_MAP(SetToolsDramAddrLow, PPSMC_MSG_SetToolsDramAddrLow, 0),
115 : MSG_MAP(TransferTableSmu2Dram, PPSMC_MSG_TransferTableSmu2Dram, 1),
116 : MSG_MAP(TransferTableDram2Smu, PPSMC_MSG_TransferTableDram2Smu, 0),
117 : MSG_MAP(UseDefaultPPTable, PPSMC_MSG_UseDefaultPPTable, 0),
118 : MSG_MAP(SetSystemVirtualDramAddrHigh, PPSMC_MSG_SetSystemVirtualDramAddrHigh, 0),
119 : MSG_MAP(SetSystemVirtualDramAddrLow, PPSMC_MSG_SetSystemVirtualDramAddrLow, 0),
120 : MSG_MAP(SetSoftMinByFreq, PPSMC_MSG_SetSoftMinByFreq, 0),
121 : MSG_MAP(SetSoftMaxByFreq, PPSMC_MSG_SetSoftMaxByFreq, 0),
122 : MSG_MAP(SetHardMinByFreq, PPSMC_MSG_SetHardMinByFreq, 0),
123 : MSG_MAP(SetHardMaxByFreq, PPSMC_MSG_SetHardMaxByFreq, 0),
124 : MSG_MAP(GetMinDpmFreq, PPSMC_MSG_GetMinDpmFreq, 0),
125 : MSG_MAP(GetMaxDpmFreq, PPSMC_MSG_GetMaxDpmFreq, 0),
126 : MSG_MAP(GetDpmFreqByIndex, PPSMC_MSG_GetDpmFreqByIndex, 1),
127 : MSG_MAP(SetWorkloadMask, PPSMC_MSG_SetWorkloadMask, 1),
128 : MSG_MAP(GetVoltageByDpm, PPSMC_MSG_GetVoltageByDpm, 0),
129 : MSG_MAP(GetVoltageByDpmOverdrive, PPSMC_MSG_GetVoltageByDpmOverdrive, 0),
130 : MSG_MAP(SetPptLimit, PPSMC_MSG_SetPptLimit, 0),
131 : MSG_MAP(GetPptLimit, PPSMC_MSG_GetPptLimit, 1),
132 : MSG_MAP(PrepareMp1ForUnload, PPSMC_MSG_PrepareMp1ForUnload, 0),
133 : MSG_MAP(GfxDeviceDriverReset, PPSMC_MSG_GfxDriverReset, 0),
134 : MSG_MAP(RunDcBtc, PPSMC_MSG_RunDcBtc, 0),
135 : MSG_MAP(DramLogSetDramAddrHigh, PPSMC_MSG_DramLogSetDramAddrHigh, 0),
136 : MSG_MAP(DramLogSetDramAddrLow, PPSMC_MSG_DramLogSetDramAddrLow, 0),
137 : MSG_MAP(DramLogSetDramSize, PPSMC_MSG_DramLogSetDramSize, 0),
138 : MSG_MAP(GetDebugData, PPSMC_MSG_GetDebugData, 0),
139 : MSG_MAP(WaflTest, PPSMC_MSG_WaflTest, 0),
140 : MSG_MAP(SetMemoryChannelEnable, PPSMC_MSG_SetMemoryChannelEnable, 0),
141 : MSG_MAP(SetNumBadHbmPagesRetired, PPSMC_MSG_SetNumBadHbmPagesRetired, 0),
142 : MSG_MAP(DFCstateControl, PPSMC_MSG_DFCstateControl, 0),
143 : MSG_MAP(GetGmiPwrDnHyst, PPSMC_MSG_GetGmiPwrDnHyst, 0),
144 : MSG_MAP(SetGmiPwrDnHyst, PPSMC_MSG_SetGmiPwrDnHyst, 0),
145 : MSG_MAP(GmiPwrDnControl, PPSMC_MSG_GmiPwrDnControl, 0),
146 : MSG_MAP(EnterGfxoff, PPSMC_MSG_EnterGfxoff, 0),
147 : MSG_MAP(ExitGfxoff, PPSMC_MSG_ExitGfxoff, 0),
148 : MSG_MAP(SetExecuteDMATest, PPSMC_MSG_SetExecuteDMATest, 0),
149 : MSG_MAP(EnableDeterminism, PPSMC_MSG_EnableDeterminism, 0),
150 : MSG_MAP(DisableDeterminism, PPSMC_MSG_DisableDeterminism, 0),
151 : MSG_MAP(SetUclkDpmMode, PPSMC_MSG_SetUclkDpmMode, 0),
152 : MSG_MAP(GfxDriverResetRecovery, PPSMC_MSG_GfxDriverResetRecovery, 0),
153 : MSG_MAP(BoardPowerCalibration, PPSMC_MSG_BoardPowerCalibration, 0),
154 : MSG_MAP(HeavySBR, PPSMC_MSG_HeavySBR, 0),
155 : MSG_MAP(SetBadHBMPagesRetiredFlagsPerChannel, PPSMC_MSG_SetBadHBMPagesRetiredFlagsPerChannel, 0),
156 : };
157 :
158 : static const struct cmn2asic_mapping aldebaran_clk_map[SMU_CLK_COUNT] = {
159 : CLK_MAP(GFXCLK, PPCLK_GFXCLK),
160 : CLK_MAP(SCLK, PPCLK_GFXCLK),
161 : CLK_MAP(SOCCLK, PPCLK_SOCCLK),
162 : CLK_MAP(FCLK, PPCLK_FCLK),
163 : CLK_MAP(UCLK, PPCLK_UCLK),
164 : CLK_MAP(MCLK, PPCLK_UCLK),
165 : CLK_MAP(DCLK, PPCLK_DCLK),
166 : CLK_MAP(VCLK, PPCLK_VCLK),
167 : CLK_MAP(LCLK, PPCLK_LCLK),
168 : };
169 :
170 : static const struct cmn2asic_mapping aldebaran_feature_mask_map[SMU_FEATURE_COUNT] = {
171 : ALDEBARAN_FEA_MAP(SMU_FEATURE_DATA_CALCULATIONS_BIT, FEATURE_DATA_CALCULATIONS),
172 : ALDEBARAN_FEA_MAP(SMU_FEATURE_DPM_GFXCLK_BIT, FEATURE_DPM_GFXCLK_BIT),
173 : ALDEBARAN_FEA_MAP(SMU_FEATURE_DPM_UCLK_BIT, FEATURE_DPM_UCLK_BIT),
174 : ALDEBARAN_FEA_MAP(SMU_FEATURE_DPM_SOCCLK_BIT, FEATURE_DPM_SOCCLK_BIT),
175 : ALDEBARAN_FEA_MAP(SMU_FEATURE_DPM_FCLK_BIT, FEATURE_DPM_FCLK_BIT),
176 : ALDEBARAN_FEA_MAP(SMU_FEATURE_DPM_LCLK_BIT, FEATURE_DPM_LCLK_BIT),
177 : ALDEBARAN_FEA_MAP(SMU_FEATURE_DPM_XGMI_BIT, FEATURE_DPM_XGMI_BIT),
178 : ALDEBARAN_FEA_MAP(SMU_FEATURE_DS_GFXCLK_BIT, FEATURE_DS_GFXCLK_BIT),
179 : ALDEBARAN_FEA_MAP(SMU_FEATURE_DS_SOCCLK_BIT, FEATURE_DS_SOCCLK_BIT),
180 : ALDEBARAN_FEA_MAP(SMU_FEATURE_DS_LCLK_BIT, FEATURE_DS_LCLK_BIT),
181 : ALDEBARAN_FEA_MAP(SMU_FEATURE_DS_FCLK_BIT, FEATURE_DS_FCLK_BIT),
182 : ALDEBARAN_FEA_MAP(SMU_FEATURE_DS_UCLK_BIT, FEATURE_DS_UCLK_BIT),
183 : ALDEBARAN_FEA_MAP(SMU_FEATURE_GFX_SS_BIT, FEATURE_GFX_SS_BIT),
184 : ALDEBARAN_FEA_MAP(SMU_FEATURE_VCN_DPM_BIT, FEATURE_DPM_VCN_BIT),
185 : ALDEBARAN_FEA_MAP(SMU_FEATURE_RSMU_SMN_CG_BIT, FEATURE_RSMU_SMN_CG_BIT),
186 : ALDEBARAN_FEA_MAP(SMU_FEATURE_WAFL_CG_BIT, FEATURE_WAFL_CG_BIT),
187 : ALDEBARAN_FEA_MAP(SMU_FEATURE_PPT_BIT, FEATURE_PPT_BIT),
188 : ALDEBARAN_FEA_MAP(SMU_FEATURE_TDC_BIT, FEATURE_TDC_BIT),
189 : ALDEBARAN_FEA_MAP(SMU_FEATURE_APCC_PLUS_BIT, FEATURE_APCC_PLUS_BIT),
190 : ALDEBARAN_FEA_MAP(SMU_FEATURE_APCC_DFLL_BIT, FEATURE_APCC_DFLL_BIT),
191 : ALDEBARAN_FEA_MAP(SMU_FEATURE_FUSE_CG_BIT, FEATURE_FUSE_CG_BIT),
192 : ALDEBARAN_FEA_MAP(SMU_FEATURE_MP1_CG_BIT, FEATURE_MP1_CG_BIT),
193 : ALDEBARAN_FEA_MAP(SMU_FEATURE_SMUIO_CG_BIT, FEATURE_SMUIO_CG_BIT),
194 : ALDEBARAN_FEA_MAP(SMU_FEATURE_THM_CG_BIT, FEATURE_THM_CG_BIT),
195 : ALDEBARAN_FEA_MAP(SMU_FEATURE_CLK_CG_BIT, FEATURE_CLK_CG_BIT),
196 : ALDEBARAN_FEA_MAP(SMU_FEATURE_FW_CTF_BIT, FEATURE_FW_CTF_BIT),
197 : ALDEBARAN_FEA_MAP(SMU_FEATURE_THERMAL_BIT, FEATURE_THERMAL_BIT),
198 : ALDEBARAN_FEA_MAP(SMU_FEATURE_OUT_OF_BAND_MONITOR_BIT, FEATURE_OUT_OF_BAND_MONITOR_BIT),
199 : ALDEBARAN_FEA_MAP(SMU_FEATURE_XGMI_PER_LINK_PWR_DWN_BIT,FEATURE_XGMI_PER_LINK_PWR_DWN),
200 : ALDEBARAN_FEA_MAP(SMU_FEATURE_DF_CSTATE_BIT, FEATURE_DF_CSTATE),
201 : };
202 :
203 : static const struct cmn2asic_mapping aldebaran_table_map[SMU_TABLE_COUNT] = {
204 : TAB_MAP(PPTABLE),
205 : TAB_MAP(AVFS_PSM_DEBUG),
206 : TAB_MAP(AVFS_FUSE_OVERRIDE),
207 : TAB_MAP(PMSTATUSLOG),
208 : TAB_MAP(SMU_METRICS),
209 : TAB_MAP(DRIVER_SMU_CONFIG),
210 : TAB_MAP(I2C_COMMANDS),
211 : TAB_MAP(ECCINFO),
212 : };
213 :
214 : static const uint8_t aldebaran_throttler_map[] = {
215 : [THROTTLER_PPT0_BIT] = (SMU_THROTTLER_PPT0_BIT),
216 : [THROTTLER_PPT1_BIT] = (SMU_THROTTLER_PPT1_BIT),
217 : [THROTTLER_TDC_GFX_BIT] = (SMU_THROTTLER_TDC_GFX_BIT),
218 : [THROTTLER_TDC_SOC_BIT] = (SMU_THROTTLER_TDC_SOC_BIT),
219 : [THROTTLER_TDC_HBM_BIT] = (SMU_THROTTLER_TDC_MEM_BIT),
220 : [THROTTLER_TEMP_GPU_BIT] = (SMU_THROTTLER_TEMP_GPU_BIT),
221 : [THROTTLER_TEMP_MEM_BIT] = (SMU_THROTTLER_TEMP_MEM_BIT),
222 : [THROTTLER_TEMP_VR_GFX_BIT] = (SMU_THROTTLER_TEMP_VR_GFX_BIT),
223 : [THROTTLER_TEMP_VR_SOC_BIT] = (SMU_THROTTLER_TEMP_VR_SOC_BIT),
224 : [THROTTLER_TEMP_VR_MEM_BIT] = (SMU_THROTTLER_TEMP_VR_MEM0_BIT),
225 : [THROTTLER_APCC_BIT] = (SMU_THROTTLER_APCC_BIT),
226 : };
227 :
228 0 : static int aldebaran_tables_init(struct smu_context *smu)
229 : {
230 0 : struct smu_table_context *smu_table = &smu->smu_table;
231 0 : struct smu_table *tables = smu_table->tables;
232 :
233 0 : SMU_TABLE_INIT(tables, SMU_TABLE_PPTABLE, sizeof(PPTable_t),
234 : PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
235 :
236 0 : SMU_TABLE_INIT(tables, SMU_TABLE_PMSTATUSLOG, SMU13_TOOL_SIZE,
237 : PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
238 :
239 0 : SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetrics_t),
240 : PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
241 :
242 0 : SMU_TABLE_INIT(tables, SMU_TABLE_I2C_COMMANDS, sizeof(SwI2cRequest_t),
243 : PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
244 :
245 0 : SMU_TABLE_INIT(tables, SMU_TABLE_ECCINFO, sizeof(EccInfoTable_t),
246 : PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
247 :
248 0 : smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_t), GFP_KERNEL);
249 0 : if (!smu_table->metrics_table)
250 : return -ENOMEM;
251 0 : smu_table->metrics_time = 0;
252 :
253 0 : smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v1_3);
254 0 : smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL);
255 0 : if (!smu_table->gpu_metrics_table) {
256 0 : kfree(smu_table->metrics_table);
257 0 : return -ENOMEM;
258 : }
259 :
260 0 : smu_table->ecc_table = kzalloc(tables[SMU_TABLE_ECCINFO].size, GFP_KERNEL);
261 0 : if (!smu_table->ecc_table)
262 : return -ENOMEM;
263 :
264 0 : return 0;
265 : }
266 :
267 : static int aldebaran_allocate_dpm_context(struct smu_context *smu)
268 : {
269 0 : struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
270 :
271 0 : smu_dpm->dpm_context = kzalloc(sizeof(struct smu_13_0_dpm_context),
272 : GFP_KERNEL);
273 0 : if (!smu_dpm->dpm_context)
274 : return -ENOMEM;
275 0 : smu_dpm->dpm_context_size = sizeof(struct smu_13_0_dpm_context);
276 :
277 : return 0;
278 : }
279 :
280 0 : static int aldebaran_init_smc_tables(struct smu_context *smu)
281 : {
282 0 : int ret = 0;
283 :
284 0 : ret = aldebaran_tables_init(smu);
285 0 : if (ret)
286 : return ret;
287 :
288 0 : ret = aldebaran_allocate_dpm_context(smu);
289 0 : if (ret)
290 : return ret;
291 :
292 0 : return smu_v13_0_init_smc_tables(smu);
293 : }
294 :
295 0 : static int aldebaran_get_allowed_feature_mask(struct smu_context *smu,
296 : uint32_t *feature_mask, uint32_t num)
297 : {
298 0 : if (num > 2)
299 : return -EINVAL;
300 :
301 : /* pptable will handle the features to enable */
302 0 : memset(feature_mask, 0xFF, sizeof(uint32_t) * num);
303 :
304 0 : return 0;
305 : }
306 :
307 0 : static int aldebaran_set_default_dpm_table(struct smu_context *smu)
308 : {
309 0 : struct smu_13_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context;
310 0 : struct smu_13_0_dpm_table *dpm_table = NULL;
311 0 : PPTable_t *pptable = smu->smu_table.driver_pptable;
312 0 : int ret = 0;
313 :
314 : /* socclk dpm table setup */
315 0 : dpm_table = &dpm_context->dpm_tables.soc_table;
316 0 : if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) {
317 0 : ret = smu_v13_0_set_single_dpm_table(smu,
318 : SMU_SOCCLK,
319 : dpm_table);
320 0 : if (ret)
321 : return ret;
322 : } else {
323 0 : dpm_table->count = 1;
324 0 : dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.socclk / 100;
325 0 : dpm_table->dpm_levels[0].enabled = true;
326 0 : dpm_table->min = dpm_table->dpm_levels[0].value;
327 0 : dpm_table->max = dpm_table->dpm_levels[0].value;
328 : }
329 :
330 : /* gfxclk dpm table setup */
331 0 : dpm_table = &dpm_context->dpm_tables.gfx_table;
332 0 : if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT)) {
333 : /* in the case of gfxclk, only fine-grained dpm is honored */
334 0 : dpm_table->count = 2;
335 0 : dpm_table->dpm_levels[0].value = pptable->GfxclkFmin;
336 0 : dpm_table->dpm_levels[0].enabled = true;
337 0 : dpm_table->dpm_levels[1].value = pptable->GfxclkFmax;
338 0 : dpm_table->dpm_levels[1].enabled = true;
339 0 : dpm_table->min = dpm_table->dpm_levels[0].value;
340 0 : dpm_table->max = dpm_table->dpm_levels[1].value;
341 : } else {
342 0 : dpm_table->count = 1;
343 0 : dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.gfxclk / 100;
344 0 : dpm_table->dpm_levels[0].enabled = true;
345 0 : dpm_table->min = dpm_table->dpm_levels[0].value;
346 0 : dpm_table->max = dpm_table->dpm_levels[0].value;
347 : }
348 :
349 : /* memclk dpm table setup */
350 0 : dpm_table = &dpm_context->dpm_tables.uclk_table;
351 0 : if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) {
352 0 : ret = smu_v13_0_set_single_dpm_table(smu,
353 : SMU_UCLK,
354 : dpm_table);
355 0 : if (ret)
356 : return ret;
357 : } else {
358 0 : dpm_table->count = 1;
359 0 : dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.uclk / 100;
360 0 : dpm_table->dpm_levels[0].enabled = true;
361 0 : dpm_table->min = dpm_table->dpm_levels[0].value;
362 0 : dpm_table->max = dpm_table->dpm_levels[0].value;
363 : }
364 :
365 : /* fclk dpm table setup */
366 0 : dpm_table = &dpm_context->dpm_tables.fclk_table;
367 0 : if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_FCLK_BIT)) {
368 0 : ret = smu_v13_0_set_single_dpm_table(smu,
369 : SMU_FCLK,
370 : dpm_table);
371 0 : if (ret)
372 : return ret;
373 : } else {
374 0 : dpm_table->count = 1;
375 0 : dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.fclk / 100;
376 0 : dpm_table->dpm_levels[0].enabled = true;
377 0 : dpm_table->min = dpm_table->dpm_levels[0].value;
378 0 : dpm_table->max = dpm_table->dpm_levels[0].value;
379 : }
380 :
381 : return 0;
382 : }
383 :
384 : static int aldebaran_check_powerplay_table(struct smu_context *smu)
385 : {
386 0 : struct smu_table_context *table_context = &smu->smu_table;
387 0 : struct smu_13_0_powerplay_table *powerplay_table =
388 : table_context->power_play_table;
389 :
390 0 : table_context->thermal_controller_type =
391 0 : powerplay_table->thermal_controller_type;
392 :
393 : return 0;
394 : }
395 :
396 : static int aldebaran_store_powerplay_table(struct smu_context *smu)
397 : {
398 0 : struct smu_table_context *table_context = &smu->smu_table;
399 0 : struct smu_13_0_powerplay_table *powerplay_table =
400 : table_context->power_play_table;
401 0 : memcpy(table_context->driver_pptable, &powerplay_table->smc_pptable,
402 : sizeof(PPTable_t));
403 :
404 : return 0;
405 : }
406 :
407 0 : static int aldebaran_append_powerplay_table(struct smu_context *smu)
408 : {
409 0 : struct smu_table_context *table_context = &smu->smu_table;
410 0 : PPTable_t *smc_pptable = table_context->driver_pptable;
411 : struct atom_smc_dpm_info_v4_10 *smc_dpm_table;
412 : int index, ret;
413 :
414 0 : index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
415 : smc_dpm_info);
416 :
417 0 : ret = amdgpu_atombios_get_data_table(smu->adev, index, NULL, NULL, NULL,
418 : (uint8_t **)&smc_dpm_table);
419 0 : if (ret)
420 : return ret;
421 :
422 0 : dev_info(smu->adev->dev, "smc_dpm_info table revision(format.content): %d.%d\n",
423 : smc_dpm_table->table_header.format_revision,
424 : smc_dpm_table->table_header.content_revision);
425 :
426 0 : if ((smc_dpm_table->table_header.format_revision == 4) &&
427 0 : (smc_dpm_table->table_header.content_revision == 10))
428 0 : smu_memcpy_trailing(smc_pptable, GfxMaxCurrent, reserved,
429 : smc_dpm_table, GfxMaxCurrent);
430 : return 0;
431 : }
432 :
433 0 : static int aldebaran_setup_pptable(struct smu_context *smu)
434 : {
435 0 : int ret = 0;
436 :
437 : /* VBIOS pptable is the first choice */
438 0 : smu->smu_table.boot_values.pp_table_id = 0;
439 :
440 0 : ret = smu_v13_0_setup_pptable(smu);
441 0 : if (ret)
442 : return ret;
443 :
444 0 : ret = aldebaran_store_powerplay_table(smu);
445 : if (ret)
446 : return ret;
447 :
448 0 : ret = aldebaran_append_powerplay_table(smu);
449 0 : if (ret)
450 : return ret;
451 :
452 0 : ret = aldebaran_check_powerplay_table(smu);
453 : if (ret)
454 : return ret;
455 :
456 0 : return ret;
457 : }
458 :
459 : static bool aldebaran_is_primary(struct smu_context *smu)
460 : {
461 0 : struct amdgpu_device *adev = smu->adev;
462 :
463 0 : if (adev->smuio.funcs && adev->smuio.funcs->get_die_id)
464 0 : return adev->smuio.funcs->get_die_id(adev) == 0;
465 :
466 : return true;
467 : }
468 :
469 0 : static int aldebaran_run_board_btc(struct smu_context *smu)
470 : {
471 : u32 smu_version;
472 : int ret;
473 :
474 0 : if (!aldebaran_is_primary(smu))
475 : return 0;
476 :
477 0 : ret = smu_cmn_get_smc_version(smu, NULL, &smu_version);
478 0 : if (ret) {
479 0 : dev_err(smu->adev->dev, "Failed to get smu version!\n");
480 0 : return ret;
481 : }
482 0 : if (smu_version <= 0x00441d00)
483 : return 0;
484 :
485 0 : ret = smu_cmn_send_smc_msg(smu, SMU_MSG_BoardPowerCalibration, NULL);
486 0 : if (ret)
487 0 : dev_err(smu->adev->dev, "Board power calibration failed!\n");
488 :
489 : return ret;
490 : }
491 :
492 0 : static int aldebaran_run_btc(struct smu_context *smu)
493 : {
494 : int ret;
495 :
496 0 : ret = smu_cmn_send_smc_msg(smu, SMU_MSG_RunDcBtc, NULL);
497 0 : if (ret)
498 0 : dev_err(smu->adev->dev, "RunDcBtc failed!\n");
499 : else
500 0 : ret = aldebaran_run_board_btc(smu);
501 :
502 0 : return ret;
503 : }
504 :
505 0 : static int aldebaran_populate_umd_state_clk(struct smu_context *smu)
506 : {
507 0 : struct smu_13_0_dpm_context *dpm_context =
508 : smu->smu_dpm.dpm_context;
509 0 : struct smu_13_0_dpm_table *gfx_table =
510 : &dpm_context->dpm_tables.gfx_table;
511 0 : struct smu_13_0_dpm_table *mem_table =
512 : &dpm_context->dpm_tables.uclk_table;
513 0 : struct smu_13_0_dpm_table *soc_table =
514 : &dpm_context->dpm_tables.soc_table;
515 0 : struct smu_umd_pstate_table *pstate_table =
516 : &smu->pstate_table;
517 :
518 0 : pstate_table->gfxclk_pstate.min = gfx_table->min;
519 0 : pstate_table->gfxclk_pstate.peak = gfx_table->max;
520 0 : pstate_table->gfxclk_pstate.curr.min = gfx_table->min;
521 0 : pstate_table->gfxclk_pstate.curr.max = gfx_table->max;
522 :
523 0 : pstate_table->uclk_pstate.min = mem_table->min;
524 0 : pstate_table->uclk_pstate.peak = mem_table->max;
525 0 : pstate_table->uclk_pstate.curr.min = mem_table->min;
526 0 : pstate_table->uclk_pstate.curr.max = mem_table->max;
527 :
528 0 : pstate_table->socclk_pstate.min = soc_table->min;
529 0 : pstate_table->socclk_pstate.peak = soc_table->max;
530 0 : pstate_table->socclk_pstate.curr.min = soc_table->min;
531 0 : pstate_table->socclk_pstate.curr.max = soc_table->max;
532 :
533 0 : if (gfx_table->count > ALDEBARAN_UMD_PSTATE_GFXCLK_LEVEL &&
534 0 : mem_table->count > ALDEBARAN_UMD_PSTATE_MCLK_LEVEL &&
535 0 : soc_table->count > ALDEBARAN_UMD_PSTATE_SOCCLK_LEVEL) {
536 0 : pstate_table->gfxclk_pstate.standard =
537 0 : gfx_table->dpm_levels[ALDEBARAN_UMD_PSTATE_GFXCLK_LEVEL].value;
538 0 : pstate_table->uclk_pstate.standard =
539 0 : mem_table->dpm_levels[ALDEBARAN_UMD_PSTATE_MCLK_LEVEL].value;
540 0 : pstate_table->socclk_pstate.standard =
541 0 : soc_table->dpm_levels[ALDEBARAN_UMD_PSTATE_SOCCLK_LEVEL].value;
542 : } else {
543 0 : pstate_table->gfxclk_pstate.standard =
544 : pstate_table->gfxclk_pstate.min;
545 0 : pstate_table->uclk_pstate.standard =
546 : pstate_table->uclk_pstate.min;
547 0 : pstate_table->socclk_pstate.standard =
548 : pstate_table->socclk_pstate.min;
549 : }
550 :
551 0 : return 0;
552 : }
553 :
554 : static int aldebaran_get_clk_table(struct smu_context *smu,
555 : struct pp_clock_levels_with_latency *clocks,
556 : struct smu_13_0_dpm_table *dpm_table)
557 : {
558 : uint32_t i;
559 :
560 0 : clocks->num_levels = min_t(uint32_t,
561 : dpm_table->count,
562 : (uint32_t)PP_MAX_CLOCK_LEVELS);
563 :
564 0 : for (i = 0; i < clocks->num_levels; i++) {
565 0 : clocks->data[i].clocks_in_khz =
566 0 : dpm_table->dpm_levels[i].value * 1000;
567 : clocks->data[i].latency_in_us = 0;
568 : }
569 :
570 : return 0;
571 : }
572 :
573 : static int aldebaran_freqs_in_same_level(int32_t frequency1,
574 : int32_t frequency2)
575 : {
576 0 : return (abs(frequency1 - frequency2) <= EPSILON);
577 : }
578 :
579 0 : static int aldebaran_get_smu_metrics_data(struct smu_context *smu,
580 : MetricsMember_t member,
581 : uint32_t *value)
582 : {
583 0 : struct smu_table_context *smu_table= &smu->smu_table;
584 0 : SmuMetrics_t *metrics = (SmuMetrics_t *)smu_table->metrics_table;
585 0 : int ret = 0;
586 :
587 0 : ret = smu_cmn_get_metrics_table(smu,
588 : NULL,
589 : false);
590 0 : if (ret)
591 : return ret;
592 :
593 0 : switch (member) {
594 : case METRICS_CURR_GFXCLK:
595 0 : *value = metrics->CurrClock[PPCLK_GFXCLK];
596 0 : break;
597 : case METRICS_CURR_SOCCLK:
598 0 : *value = metrics->CurrClock[PPCLK_SOCCLK];
599 0 : break;
600 : case METRICS_CURR_UCLK:
601 0 : *value = metrics->CurrClock[PPCLK_UCLK];
602 0 : break;
603 : case METRICS_CURR_VCLK:
604 0 : *value = metrics->CurrClock[PPCLK_VCLK];
605 0 : break;
606 : case METRICS_CURR_DCLK:
607 0 : *value = metrics->CurrClock[PPCLK_DCLK];
608 0 : break;
609 : case METRICS_CURR_FCLK:
610 0 : *value = metrics->CurrClock[PPCLK_FCLK];
611 0 : break;
612 : case METRICS_AVERAGE_GFXCLK:
613 0 : *value = metrics->AverageGfxclkFrequency;
614 0 : break;
615 : case METRICS_AVERAGE_SOCCLK:
616 0 : *value = metrics->AverageSocclkFrequency;
617 0 : break;
618 : case METRICS_AVERAGE_UCLK:
619 0 : *value = metrics->AverageUclkFrequency;
620 0 : break;
621 : case METRICS_AVERAGE_GFXACTIVITY:
622 0 : *value = metrics->AverageGfxActivity;
623 0 : break;
624 : case METRICS_AVERAGE_MEMACTIVITY:
625 0 : *value = metrics->AverageUclkActivity;
626 0 : break;
627 : case METRICS_AVERAGE_SOCKETPOWER:
628 : /* Valid power data is available only from primary die */
629 0 : *value = aldebaran_is_primary(smu) ?
630 0 : metrics->AverageSocketPower << 8 :
631 : 0;
632 0 : break;
633 : case METRICS_TEMPERATURE_EDGE:
634 0 : *value = metrics->TemperatureEdge *
635 : SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
636 0 : break;
637 : case METRICS_TEMPERATURE_HOTSPOT:
638 0 : *value = metrics->TemperatureHotspot *
639 : SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
640 0 : break;
641 : case METRICS_TEMPERATURE_MEM:
642 0 : *value = metrics->TemperatureHBM *
643 : SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
644 0 : break;
645 : case METRICS_TEMPERATURE_VRGFX:
646 0 : *value = metrics->TemperatureVrGfx *
647 : SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
648 0 : break;
649 : case METRICS_TEMPERATURE_VRSOC:
650 0 : *value = metrics->TemperatureVrSoc *
651 : SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
652 0 : break;
653 : case METRICS_TEMPERATURE_VRMEM:
654 0 : *value = metrics->TemperatureVrMem *
655 : SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
656 0 : break;
657 : case METRICS_THROTTLER_STATUS:
658 0 : *value = metrics->ThrottlerStatus;
659 0 : break;
660 : case METRICS_UNIQUE_ID_UPPER32:
661 0 : *value = metrics->PublicSerialNumUpper32;
662 0 : break;
663 : case METRICS_UNIQUE_ID_LOWER32:
664 0 : *value = metrics->PublicSerialNumLower32;
665 0 : break;
666 : default:
667 0 : *value = UINT_MAX;
668 0 : break;
669 : }
670 :
671 : return ret;
672 : }
673 :
674 0 : static int aldebaran_get_current_clk_freq_by_table(struct smu_context *smu,
675 : enum smu_clk_type clk_type,
676 : uint32_t *value)
677 : {
678 : MetricsMember_t member_type;
679 0 : int clk_id = 0;
680 :
681 0 : if (!value)
682 : return -EINVAL;
683 :
684 0 : clk_id = smu_cmn_to_asic_specific_index(smu,
685 : CMN2ASIC_MAPPING_CLK,
686 : clk_type);
687 0 : if (clk_id < 0)
688 : return -EINVAL;
689 :
690 0 : switch (clk_id) {
691 : case PPCLK_GFXCLK:
692 : /*
693 : * CurrClock[clk_id] can provide accurate
694 : * output only when the dpm feature is enabled.
695 : * We can use Average_* for dpm disabled case.
696 : * But this is available for gfxclk/uclk/socclk/vclk/dclk.
697 : */
698 0 : if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT))
699 : member_type = METRICS_CURR_GFXCLK;
700 : else
701 0 : member_type = METRICS_AVERAGE_GFXCLK;
702 : break;
703 : case PPCLK_UCLK:
704 0 : if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT))
705 : member_type = METRICS_CURR_UCLK;
706 : else
707 0 : member_type = METRICS_AVERAGE_UCLK;
708 : break;
709 : case PPCLK_SOCCLK:
710 0 : if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT))
711 : member_type = METRICS_CURR_SOCCLK;
712 : else
713 0 : member_type = METRICS_AVERAGE_SOCCLK;
714 : break;
715 : case PPCLK_VCLK:
716 0 : if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT))
717 : member_type = METRICS_CURR_VCLK;
718 : else
719 0 : member_type = METRICS_AVERAGE_VCLK;
720 : break;
721 : case PPCLK_DCLK:
722 0 : if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT))
723 : member_type = METRICS_CURR_DCLK;
724 : else
725 0 : member_type = METRICS_AVERAGE_DCLK;
726 : break;
727 : case PPCLK_FCLK:
728 : member_type = METRICS_CURR_FCLK;
729 : break;
730 : default:
731 : return -EINVAL;
732 : }
733 :
734 0 : return aldebaran_get_smu_metrics_data(smu,
735 : member_type,
736 : value);
737 : }
738 :
739 0 : static int aldebaran_print_clk_levels(struct smu_context *smu,
740 : enum smu_clk_type type, char *buf)
741 : {
742 0 : int i, now, size = 0;
743 0 : int ret = 0;
744 0 : struct smu_umd_pstate_table *pstate_table = &smu->pstate_table;
745 : struct pp_clock_levels_with_latency clocks;
746 : struct smu_13_0_dpm_table *single_dpm_table;
747 0 : struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
748 0 : struct smu_13_0_dpm_context *dpm_context = NULL;
749 : int display_levels;
750 0 : uint32_t freq_values[3] = {0};
751 : uint32_t min_clk, max_clk;
752 :
753 0 : smu_cmn_get_sysfs_buf(&buf, &size);
754 :
755 0 : if (amdgpu_ras_intr_triggered()) {
756 0 : size += sysfs_emit_at(buf, size, "unavailable\n");
757 0 : return size;
758 : }
759 :
760 0 : dpm_context = smu_dpm->dpm_context;
761 :
762 0 : switch (type) {
763 :
764 : case SMU_OD_SCLK:
765 0 : size += sysfs_emit_at(buf, size, "%s:\n", "GFXCLK");
766 : fallthrough;
767 : case SMU_SCLK:
768 0 : ret = aldebaran_get_current_clk_freq_by_table(smu, SMU_GFXCLK, &now);
769 0 : if (ret) {
770 0 : dev_err(smu->adev->dev, "Attempt to get current gfx clk Failed!");
771 0 : return ret;
772 : }
773 :
774 0 : single_dpm_table = &(dpm_context->dpm_tables.gfx_table);
775 0 : ret = aldebaran_get_clk_table(smu, &clocks, single_dpm_table);
776 : if (ret) {
777 : dev_err(smu->adev->dev, "Attempt to get gfx clk levels Failed!");
778 : return ret;
779 : }
780 :
781 0 : display_levels = (clocks.num_levels == 1) ? 1 : 2;
782 :
783 0 : min_clk = pstate_table->gfxclk_pstate.curr.min;
784 0 : max_clk = pstate_table->gfxclk_pstate.curr.max;
785 :
786 0 : freq_values[0] = min_clk;
787 0 : freq_values[1] = max_clk;
788 :
789 : /* fine-grained dpm has only 2 levels */
790 0 : if (now > min_clk && now < max_clk) {
791 0 : display_levels++;
792 0 : freq_values[2] = max_clk;
793 0 : freq_values[1] = now;
794 : }
795 :
796 0 : for (i = 0; i < display_levels; i++)
797 0 : size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", i,
798 : freq_values[i],
799 : (display_levels == 1) ?
800 : "*" :
801 0 : (aldebaran_freqs_in_same_level(
802 0 : freq_values[i], now) ?
803 0 : "*" :
804 : ""));
805 :
806 : break;
807 :
808 : case SMU_OD_MCLK:
809 0 : size += sysfs_emit_at(buf, size, "%s:\n", "MCLK");
810 : fallthrough;
811 : case SMU_MCLK:
812 0 : ret = aldebaran_get_current_clk_freq_by_table(smu, SMU_UCLK, &now);
813 0 : if (ret) {
814 0 : dev_err(smu->adev->dev, "Attempt to get current mclk Failed!");
815 0 : return ret;
816 : }
817 :
818 0 : single_dpm_table = &(dpm_context->dpm_tables.uclk_table);
819 0 : ret = aldebaran_get_clk_table(smu, &clocks, single_dpm_table);
820 : if (ret) {
821 : dev_err(smu->adev->dev, "Attempt to get memory clk levels Failed!");
822 : return ret;
823 : }
824 :
825 0 : for (i = 0; i < clocks.num_levels; i++)
826 0 : size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n",
827 0 : i, clocks.data[i].clocks_in_khz / 1000,
828 : (clocks.num_levels == 1) ? "*" :
829 0 : (aldebaran_freqs_in_same_level(
830 0 : clocks.data[i].clocks_in_khz / 1000,
831 0 : now) ? "*" : ""));
832 : break;
833 :
834 : case SMU_SOCCLK:
835 0 : ret = aldebaran_get_current_clk_freq_by_table(smu, SMU_SOCCLK, &now);
836 0 : if (ret) {
837 0 : dev_err(smu->adev->dev, "Attempt to get current socclk Failed!");
838 0 : return ret;
839 : }
840 :
841 0 : single_dpm_table = &(dpm_context->dpm_tables.soc_table);
842 0 : ret = aldebaran_get_clk_table(smu, &clocks, single_dpm_table);
843 : if (ret) {
844 : dev_err(smu->adev->dev, "Attempt to get socclk levels Failed!");
845 : return ret;
846 : }
847 :
848 0 : for (i = 0; i < clocks.num_levels; i++)
849 0 : size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n",
850 0 : i, clocks.data[i].clocks_in_khz / 1000,
851 : (clocks.num_levels == 1) ? "*" :
852 0 : (aldebaran_freqs_in_same_level(
853 0 : clocks.data[i].clocks_in_khz / 1000,
854 0 : now) ? "*" : ""));
855 : break;
856 :
857 : case SMU_FCLK:
858 0 : ret = aldebaran_get_current_clk_freq_by_table(smu, SMU_FCLK, &now);
859 0 : if (ret) {
860 0 : dev_err(smu->adev->dev, "Attempt to get current fclk Failed!");
861 0 : return ret;
862 : }
863 :
864 0 : single_dpm_table = &(dpm_context->dpm_tables.fclk_table);
865 0 : ret = aldebaran_get_clk_table(smu, &clocks, single_dpm_table);
866 : if (ret) {
867 : dev_err(smu->adev->dev, "Attempt to get fclk levels Failed!");
868 : return ret;
869 : }
870 :
871 0 : for (i = 0; i < single_dpm_table->count; i++)
872 0 : size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n",
873 : i, single_dpm_table->dpm_levels[i].value,
874 : (clocks.num_levels == 1) ? "*" :
875 0 : (aldebaran_freqs_in_same_level(
876 0 : clocks.data[i].clocks_in_khz / 1000,
877 0 : now) ? "*" : ""));
878 : break;
879 :
880 : case SMU_VCLK:
881 0 : ret = aldebaran_get_current_clk_freq_by_table(smu, SMU_VCLK, &now);
882 0 : if (ret) {
883 0 : dev_err(smu->adev->dev, "Attempt to get current vclk Failed!");
884 0 : return ret;
885 : }
886 :
887 0 : single_dpm_table = &(dpm_context->dpm_tables.vclk_table);
888 0 : ret = aldebaran_get_clk_table(smu, &clocks, single_dpm_table);
889 : if (ret) {
890 : dev_err(smu->adev->dev, "Attempt to get vclk levels Failed!");
891 : return ret;
892 : }
893 :
894 0 : for (i = 0; i < single_dpm_table->count; i++)
895 0 : size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n",
896 : i, single_dpm_table->dpm_levels[i].value,
897 : (clocks.num_levels == 1) ? "*" :
898 0 : (aldebaran_freqs_in_same_level(
899 0 : clocks.data[i].clocks_in_khz / 1000,
900 0 : now) ? "*" : ""));
901 : break;
902 :
903 : case SMU_DCLK:
904 0 : ret = aldebaran_get_current_clk_freq_by_table(smu, SMU_DCLK, &now);
905 0 : if (ret) {
906 0 : dev_err(smu->adev->dev, "Attempt to get current dclk Failed!");
907 0 : return ret;
908 : }
909 :
910 0 : single_dpm_table = &(dpm_context->dpm_tables.dclk_table);
911 0 : ret = aldebaran_get_clk_table(smu, &clocks, single_dpm_table);
912 : if (ret) {
913 : dev_err(smu->adev->dev, "Attempt to get dclk levels Failed!");
914 : return ret;
915 : }
916 :
917 0 : for (i = 0; i < single_dpm_table->count; i++)
918 0 : size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n",
919 : i, single_dpm_table->dpm_levels[i].value,
920 : (clocks.num_levels == 1) ? "*" :
921 0 : (aldebaran_freqs_in_same_level(
922 0 : clocks.data[i].clocks_in_khz / 1000,
923 0 : now) ? "*" : ""));
924 : break;
925 :
926 : default:
927 : break;
928 : }
929 :
930 : return size;
931 : }
932 :
933 0 : static int aldebaran_upload_dpm_level(struct smu_context *smu,
934 : bool max,
935 : uint32_t feature_mask,
936 : uint32_t level)
937 : {
938 0 : struct smu_13_0_dpm_context *dpm_context =
939 : smu->smu_dpm.dpm_context;
940 : uint32_t freq;
941 0 : int ret = 0;
942 :
943 0 : if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT) &&
944 : (feature_mask & FEATURE_MASK(FEATURE_DPM_GFXCLK_BIT))) {
945 0 : freq = dpm_context->dpm_tables.gfx_table.dpm_levels[level].value;
946 0 : ret = smu_cmn_send_smc_msg_with_param(smu,
947 : (max ? SMU_MSG_SetSoftMaxByFreq : SMU_MSG_SetSoftMinByFreq),
948 : (PPCLK_GFXCLK << 16) | (freq & 0xffff),
949 : NULL);
950 0 : if (ret) {
951 0 : dev_err(smu->adev->dev, "Failed to set soft %s gfxclk !\n",
952 : max ? "max" : "min");
953 0 : return ret;
954 : }
955 : }
956 :
957 0 : if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT) &&
958 : (feature_mask & FEATURE_MASK(FEATURE_DPM_UCLK_BIT))) {
959 0 : freq = dpm_context->dpm_tables.uclk_table.dpm_levels[level].value;
960 0 : ret = smu_cmn_send_smc_msg_with_param(smu,
961 : (max ? SMU_MSG_SetSoftMaxByFreq : SMU_MSG_SetSoftMinByFreq),
962 0 : (PPCLK_UCLK << 16) | (freq & 0xffff),
963 : NULL);
964 0 : if (ret) {
965 0 : dev_err(smu->adev->dev, "Failed to set soft %s memclk !\n",
966 : max ? "max" : "min");
967 0 : return ret;
968 : }
969 : }
970 :
971 0 : if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT) &&
972 : (feature_mask & FEATURE_MASK(FEATURE_DPM_SOCCLK_BIT))) {
973 0 : freq = dpm_context->dpm_tables.soc_table.dpm_levels[level].value;
974 0 : ret = smu_cmn_send_smc_msg_with_param(smu,
975 : (max ? SMU_MSG_SetSoftMaxByFreq : SMU_MSG_SetSoftMinByFreq),
976 0 : (PPCLK_SOCCLK << 16) | (freq & 0xffff),
977 : NULL);
978 0 : if (ret) {
979 0 : dev_err(smu->adev->dev, "Failed to set soft %s socclk !\n",
980 : max ? "max" : "min");
981 0 : return ret;
982 : }
983 : }
984 :
985 : return ret;
986 : }
987 :
988 0 : static int aldebaran_force_clk_levels(struct smu_context *smu,
989 : enum smu_clk_type type, uint32_t mask)
990 : {
991 0 : struct smu_13_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context;
992 0 : struct smu_13_0_dpm_table *single_dpm_table = NULL;
993 : uint32_t soft_min_level, soft_max_level;
994 0 : int ret = 0;
995 :
996 0 : soft_min_level = mask ? (ffs(mask) - 1) : 0;
997 0 : soft_max_level = mask ? (fls(mask) - 1) : 0;
998 :
999 0 : switch (type) {
1000 : case SMU_SCLK:
1001 0 : single_dpm_table = &(dpm_context->dpm_tables.gfx_table);
1002 0 : if (soft_max_level >= single_dpm_table->count) {
1003 0 : dev_err(smu->adev->dev, "Clock level specified %d is over max allowed %d\n",
1004 : soft_max_level, single_dpm_table->count - 1);
1005 0 : ret = -EINVAL;
1006 0 : break;
1007 : }
1008 :
1009 0 : ret = aldebaran_upload_dpm_level(smu,
1010 : false,
1011 : FEATURE_MASK(FEATURE_DPM_GFXCLK_BIT),
1012 : soft_min_level);
1013 0 : if (ret) {
1014 0 : dev_err(smu->adev->dev, "Failed to upload boot level to lowest!\n");
1015 0 : break;
1016 : }
1017 :
1018 0 : ret = aldebaran_upload_dpm_level(smu,
1019 : true,
1020 : FEATURE_MASK(FEATURE_DPM_GFXCLK_BIT),
1021 : soft_max_level);
1022 0 : if (ret)
1023 0 : dev_err(smu->adev->dev, "Failed to upload dpm max level to highest!\n");
1024 :
1025 : break;
1026 :
1027 : case SMU_MCLK:
1028 : case SMU_SOCCLK:
1029 : case SMU_FCLK:
1030 : /*
1031 : * Should not arrive here since aldebaran does not
1032 : * support mclk/socclk/fclk softmin/softmax settings
1033 : */
1034 0 : ret = -EINVAL;
1035 0 : break;
1036 :
1037 : default:
1038 : break;
1039 : }
1040 :
1041 0 : return ret;
1042 : }
1043 :
1044 0 : static int aldebaran_get_thermal_temperature_range(struct smu_context *smu,
1045 : struct smu_temperature_range *range)
1046 : {
1047 0 : struct smu_table_context *table_context = &smu->smu_table;
1048 0 : struct smu_13_0_powerplay_table *powerplay_table =
1049 : table_context->power_play_table;
1050 0 : PPTable_t *pptable = smu->smu_table.driver_pptable;
1051 :
1052 0 : if (!range)
1053 : return -EINVAL;
1054 :
1055 0 : memcpy(range, &smu13_thermal_policy[0], sizeof(struct smu_temperature_range));
1056 :
1057 0 : range->hotspot_crit_max = pptable->ThotspotLimit *
1058 : SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
1059 0 : range->hotspot_emergency_max = (pptable->ThotspotLimit + CTF_OFFSET_HOTSPOT) *
1060 : SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
1061 0 : range->mem_crit_max = pptable->TmemLimit *
1062 : SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
1063 0 : range->mem_emergency_max = (pptable->TmemLimit + CTF_OFFSET_MEM)*
1064 : SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
1065 0 : range->software_shutdown_temp = powerplay_table->software_shutdown_temp;
1066 :
1067 0 : return 0;
1068 : }
1069 :
1070 0 : static int aldebaran_get_current_activity_percent(struct smu_context *smu,
1071 : enum amd_pp_sensors sensor,
1072 : uint32_t *value)
1073 : {
1074 0 : int ret = 0;
1075 :
1076 0 : if (!value)
1077 : return -EINVAL;
1078 :
1079 0 : switch (sensor) {
1080 : case AMDGPU_PP_SENSOR_GPU_LOAD:
1081 : ret = aldebaran_get_smu_metrics_data(smu,
1082 : METRICS_AVERAGE_GFXACTIVITY,
1083 : value);
1084 : break;
1085 : case AMDGPU_PP_SENSOR_MEM_LOAD:
1086 : ret = aldebaran_get_smu_metrics_data(smu,
1087 : METRICS_AVERAGE_MEMACTIVITY,
1088 : value);
1089 : break;
1090 : default:
1091 0 : dev_err(smu->adev->dev, "Invalid sensor for retrieving clock activity\n");
1092 0 : return -EINVAL;
1093 : }
1094 :
1095 : return ret;
1096 : }
1097 :
1098 : static int aldebaran_get_gpu_power(struct smu_context *smu, uint32_t *value)
1099 : {
1100 0 : if (!value)
1101 : return -EINVAL;
1102 :
1103 0 : return aldebaran_get_smu_metrics_data(smu,
1104 : METRICS_AVERAGE_SOCKETPOWER,
1105 : value);
1106 : }
1107 :
1108 0 : static int aldebaran_thermal_get_temperature(struct smu_context *smu,
1109 : enum amd_pp_sensors sensor,
1110 : uint32_t *value)
1111 : {
1112 0 : int ret = 0;
1113 :
1114 0 : if (!value)
1115 : return -EINVAL;
1116 :
1117 0 : switch (sensor) {
1118 : case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
1119 : ret = aldebaran_get_smu_metrics_data(smu,
1120 : METRICS_TEMPERATURE_HOTSPOT,
1121 : value);
1122 : break;
1123 : case AMDGPU_PP_SENSOR_EDGE_TEMP:
1124 : ret = aldebaran_get_smu_metrics_data(smu,
1125 : METRICS_TEMPERATURE_EDGE,
1126 : value);
1127 : break;
1128 : case AMDGPU_PP_SENSOR_MEM_TEMP:
1129 : ret = aldebaran_get_smu_metrics_data(smu,
1130 : METRICS_TEMPERATURE_MEM,
1131 : value);
1132 : break;
1133 : default:
1134 0 : dev_err(smu->adev->dev, "Invalid sensor for retrieving temp\n");
1135 0 : return -EINVAL;
1136 : }
1137 :
1138 : return ret;
1139 : }
1140 :
1141 0 : static int aldebaran_read_sensor(struct smu_context *smu,
1142 : enum amd_pp_sensors sensor,
1143 : void *data, uint32_t *size)
1144 : {
1145 0 : int ret = 0;
1146 :
1147 0 : if (amdgpu_ras_intr_triggered())
1148 : return 0;
1149 :
1150 0 : if (!data || !size)
1151 : return -EINVAL;
1152 :
1153 0 : switch (sensor) {
1154 : case AMDGPU_PP_SENSOR_MEM_LOAD:
1155 : case AMDGPU_PP_SENSOR_GPU_LOAD:
1156 0 : ret = aldebaran_get_current_activity_percent(smu,
1157 : sensor,
1158 : (uint32_t *)data);
1159 0 : *size = 4;
1160 0 : break;
1161 : case AMDGPU_PP_SENSOR_GPU_POWER:
1162 0 : ret = aldebaran_get_gpu_power(smu, (uint32_t *)data);
1163 0 : *size = 4;
1164 0 : break;
1165 : case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
1166 : case AMDGPU_PP_SENSOR_EDGE_TEMP:
1167 : case AMDGPU_PP_SENSOR_MEM_TEMP:
1168 0 : ret = aldebaran_thermal_get_temperature(smu, sensor,
1169 : (uint32_t *)data);
1170 0 : *size = 4;
1171 0 : break;
1172 : case AMDGPU_PP_SENSOR_GFX_MCLK:
1173 0 : ret = aldebaran_get_current_clk_freq_by_table(smu, SMU_UCLK, (uint32_t *)data);
1174 : /* the output clock frequency in 10K unit */
1175 0 : *(uint32_t *)data *= 100;
1176 0 : *size = 4;
1177 0 : break;
1178 : case AMDGPU_PP_SENSOR_GFX_SCLK:
1179 0 : ret = aldebaran_get_current_clk_freq_by_table(smu, SMU_GFXCLK, (uint32_t *)data);
1180 0 : *(uint32_t *)data *= 100;
1181 0 : *size = 4;
1182 0 : break;
1183 : case AMDGPU_PP_SENSOR_VDDGFX:
1184 0 : ret = smu_v13_0_get_gfx_vdd(smu, (uint32_t *)data);
1185 0 : *size = 4;
1186 0 : break;
1187 : default:
1188 : ret = -EOPNOTSUPP;
1189 : break;
1190 : }
1191 :
1192 : return ret;
1193 : }
1194 :
1195 0 : static int aldebaran_get_power_limit(struct smu_context *smu,
1196 : uint32_t *current_power_limit,
1197 : uint32_t *default_power_limit,
1198 : uint32_t *max_power_limit)
1199 : {
1200 0 : PPTable_t *pptable = smu->smu_table.driver_pptable;
1201 0 : uint32_t power_limit = 0;
1202 : int ret;
1203 :
1204 0 : if (!smu_cmn_feature_is_enabled(smu, SMU_FEATURE_PPT_BIT)) {
1205 0 : if (current_power_limit)
1206 0 : *current_power_limit = 0;
1207 0 : if (default_power_limit)
1208 0 : *default_power_limit = 0;
1209 0 : if (max_power_limit)
1210 0 : *max_power_limit = 0;
1211 :
1212 0 : dev_warn(smu->adev->dev,
1213 : "PPT feature is not enabled, power values can't be fetched.");
1214 :
1215 0 : return 0;
1216 : }
1217 :
1218 : /* Valid power data is available only from primary die.
1219 : * For secondary die show the value as 0.
1220 : */
1221 0 : if (aldebaran_is_primary(smu)) {
1222 0 : ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetPptLimit,
1223 : &power_limit);
1224 :
1225 0 : if (ret) {
1226 : /* the last hope to figure out the ppt limit */
1227 0 : if (!pptable) {
1228 0 : dev_err(smu->adev->dev,
1229 : "Cannot get PPT limit due to pptable missing!");
1230 0 : return -EINVAL;
1231 : }
1232 0 : power_limit = pptable->PptLimit;
1233 : }
1234 : }
1235 :
1236 0 : if (current_power_limit)
1237 0 : *current_power_limit = power_limit;
1238 0 : if (default_power_limit)
1239 0 : *default_power_limit = power_limit;
1240 :
1241 0 : if (max_power_limit) {
1242 0 : if (pptable)
1243 0 : *max_power_limit = pptable->PptLimit;
1244 : }
1245 :
1246 : return 0;
1247 : }
1248 :
1249 0 : static int aldebaran_set_power_limit(struct smu_context *smu,
1250 : enum smu_ppt_limit_type limit_type,
1251 : uint32_t limit)
1252 : {
1253 : /* Power limit can be set only through primary die */
1254 0 : if (aldebaran_is_primary(smu))
1255 0 : return smu_v13_0_set_power_limit(smu, limit_type, limit);
1256 :
1257 : return -EINVAL;
1258 : }
1259 :
1260 0 : static int aldebaran_system_features_control(struct smu_context *smu, bool enable)
1261 : {
1262 : int ret;
1263 :
1264 0 : ret = smu_v13_0_system_features_control(smu, enable);
1265 0 : if (!ret && enable)
1266 0 : ret = aldebaran_run_btc(smu);
1267 :
1268 0 : return ret;
1269 : }
1270 :
1271 0 : static int aldebaran_set_performance_level(struct smu_context *smu,
1272 : enum amd_dpm_forced_level level)
1273 : {
1274 0 : struct smu_dpm_context *smu_dpm = &(smu->smu_dpm);
1275 0 : struct smu_13_0_dpm_context *dpm_context = smu_dpm->dpm_context;
1276 0 : struct smu_13_0_dpm_table *gfx_table =
1277 : &dpm_context->dpm_tables.gfx_table;
1278 0 : struct smu_umd_pstate_table *pstate_table = &smu->pstate_table;
1279 :
1280 : /* Disable determinism if switching to another mode */
1281 0 : if ((smu_dpm->dpm_level == AMD_DPM_FORCED_LEVEL_PERF_DETERMINISM) &&
1282 : (level != AMD_DPM_FORCED_LEVEL_PERF_DETERMINISM)) {
1283 0 : smu_cmn_send_smc_msg(smu, SMU_MSG_DisableDeterminism, NULL);
1284 0 : pstate_table->gfxclk_pstate.curr.max = gfx_table->max;
1285 : }
1286 :
1287 0 : switch (level) {
1288 :
1289 : case AMD_DPM_FORCED_LEVEL_PERF_DETERMINISM:
1290 : return 0;
1291 :
1292 : case AMD_DPM_FORCED_LEVEL_HIGH:
1293 : case AMD_DPM_FORCED_LEVEL_LOW:
1294 : case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD:
1295 : case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK:
1296 : case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK:
1297 : case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK:
1298 : default:
1299 : break;
1300 : }
1301 :
1302 0 : return smu_v13_0_set_performance_level(smu, level);
1303 : }
1304 :
1305 0 : static int aldebaran_set_soft_freq_limited_range(struct smu_context *smu,
1306 : enum smu_clk_type clk_type,
1307 : uint32_t min,
1308 : uint32_t max)
1309 : {
1310 0 : struct smu_dpm_context *smu_dpm = &(smu->smu_dpm);
1311 0 : struct smu_13_0_dpm_context *dpm_context = smu_dpm->dpm_context;
1312 0 : struct smu_umd_pstate_table *pstate_table = &smu->pstate_table;
1313 0 : struct amdgpu_device *adev = smu->adev;
1314 : uint32_t min_clk;
1315 : uint32_t max_clk;
1316 0 : int ret = 0;
1317 :
1318 0 : if (clk_type != SMU_GFXCLK && clk_type != SMU_SCLK)
1319 : return -EINVAL;
1320 :
1321 0 : if ((smu_dpm->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL)
1322 0 : && (smu_dpm->dpm_level != AMD_DPM_FORCED_LEVEL_PERF_DETERMINISM))
1323 : return -EINVAL;
1324 :
1325 0 : if (smu_dpm->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) {
1326 0 : if (min >= max) {
1327 0 : dev_err(smu->adev->dev,
1328 : "Minimum GFX clk should be less than the maximum allowed clock\n");
1329 0 : return -EINVAL;
1330 : }
1331 :
1332 0 : if ((min == pstate_table->gfxclk_pstate.curr.min) &&
1333 0 : (max == pstate_table->gfxclk_pstate.curr.max))
1334 : return 0;
1335 :
1336 0 : ret = smu_v13_0_set_soft_freq_limited_range(smu, SMU_GFXCLK,
1337 : min, max);
1338 0 : if (!ret) {
1339 0 : pstate_table->gfxclk_pstate.curr.min = min;
1340 0 : pstate_table->gfxclk_pstate.curr.max = max;
1341 : }
1342 :
1343 : return ret;
1344 : }
1345 :
1346 0 : if (smu_dpm->dpm_level == AMD_DPM_FORCED_LEVEL_PERF_DETERMINISM) {
1347 0 : if (!max || (max < dpm_context->dpm_tables.gfx_table.min) ||
1348 0 : (max > dpm_context->dpm_tables.gfx_table.max)) {
1349 0 : dev_warn(adev->dev,
1350 : "Invalid max frequency %d MHz specified for determinism\n", max);
1351 0 : return -EINVAL;
1352 : }
1353 :
1354 : /* Restore default min/max clocks and enable determinism */
1355 0 : min_clk = dpm_context->dpm_tables.gfx_table.min;
1356 0 : max_clk = dpm_context->dpm_tables.gfx_table.max;
1357 0 : ret = smu_v13_0_set_soft_freq_limited_range(smu, SMU_GFXCLK, min_clk, max_clk);
1358 0 : if (!ret) {
1359 0 : usleep_range(500, 1000);
1360 0 : ret = smu_cmn_send_smc_msg_with_param(smu,
1361 : SMU_MSG_EnableDeterminism,
1362 : max, NULL);
1363 0 : if (ret) {
1364 0 : dev_err(adev->dev,
1365 : "Failed to enable determinism at GFX clock %d MHz\n", max);
1366 : } else {
1367 0 : pstate_table->gfxclk_pstate.curr.min = min_clk;
1368 0 : pstate_table->gfxclk_pstate.curr.max = max;
1369 : }
1370 : }
1371 : }
1372 :
1373 : return ret;
1374 : }
1375 :
1376 0 : static int aldebaran_usr_edit_dpm_table(struct smu_context *smu, enum PP_OD_DPM_TABLE_COMMAND type,
1377 : long input[], uint32_t size)
1378 : {
1379 0 : struct smu_dpm_context *smu_dpm = &(smu->smu_dpm);
1380 0 : struct smu_13_0_dpm_context *dpm_context = smu_dpm->dpm_context;
1381 0 : struct smu_umd_pstate_table *pstate_table = &smu->pstate_table;
1382 : uint32_t min_clk;
1383 : uint32_t max_clk;
1384 0 : int ret = 0;
1385 :
1386 : /* Only allowed in manual or determinism mode */
1387 0 : if ((smu_dpm->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL)
1388 0 : && (smu_dpm->dpm_level != AMD_DPM_FORCED_LEVEL_PERF_DETERMINISM))
1389 : return -EINVAL;
1390 :
1391 0 : switch (type) {
1392 : case PP_OD_EDIT_SCLK_VDDC_TABLE:
1393 0 : if (size != 2) {
1394 0 : dev_err(smu->adev->dev, "Input parameter number not correct\n");
1395 0 : return -EINVAL;
1396 : }
1397 :
1398 0 : if (input[0] == 0) {
1399 0 : if (input[1] < dpm_context->dpm_tables.gfx_table.min) {
1400 0 : dev_warn(smu->adev->dev, "Minimum GFX clk (%ld) MHz specified is less than the minimum allowed (%d) MHz\n",
1401 : input[1], dpm_context->dpm_tables.gfx_table.min);
1402 0 : pstate_table->gfxclk_pstate.custom.min =
1403 0 : pstate_table->gfxclk_pstate.curr.min;
1404 0 : return -EINVAL;
1405 : }
1406 :
1407 0 : pstate_table->gfxclk_pstate.custom.min = input[1];
1408 0 : } else if (input[0] == 1) {
1409 0 : if (input[1] > dpm_context->dpm_tables.gfx_table.max) {
1410 0 : dev_warn(smu->adev->dev, "Maximum GFX clk (%ld) MHz specified is greater than the maximum allowed (%d) MHz\n",
1411 : input[1], dpm_context->dpm_tables.gfx_table.max);
1412 0 : pstate_table->gfxclk_pstate.custom.max =
1413 0 : pstate_table->gfxclk_pstate.curr.max;
1414 0 : return -EINVAL;
1415 : }
1416 :
1417 0 : pstate_table->gfxclk_pstate.custom.max = input[1];
1418 : } else {
1419 : return -EINVAL;
1420 : }
1421 : break;
1422 : case PP_OD_RESTORE_DEFAULT_TABLE:
1423 0 : if (size != 0) {
1424 0 : dev_err(smu->adev->dev, "Input parameter number not correct\n");
1425 0 : return -EINVAL;
1426 : } else {
1427 : /* Use the default frequencies for manual and determinism mode */
1428 0 : min_clk = dpm_context->dpm_tables.gfx_table.min;
1429 0 : max_clk = dpm_context->dpm_tables.gfx_table.max;
1430 :
1431 0 : return aldebaran_set_soft_freq_limited_range(smu, SMU_GFXCLK, min_clk, max_clk);
1432 : }
1433 : break;
1434 : case PP_OD_COMMIT_DPM_TABLE:
1435 0 : if (size != 0) {
1436 0 : dev_err(smu->adev->dev, "Input parameter number not correct\n");
1437 0 : return -EINVAL;
1438 : } else {
1439 0 : if (!pstate_table->gfxclk_pstate.custom.min)
1440 0 : pstate_table->gfxclk_pstate.custom.min =
1441 0 : pstate_table->gfxclk_pstate.curr.min;
1442 :
1443 0 : if (!pstate_table->gfxclk_pstate.custom.max)
1444 0 : pstate_table->gfxclk_pstate.custom.max =
1445 0 : pstate_table->gfxclk_pstate.curr.max;
1446 :
1447 0 : min_clk = pstate_table->gfxclk_pstate.custom.min;
1448 0 : max_clk = pstate_table->gfxclk_pstate.custom.max;
1449 :
1450 0 : return aldebaran_set_soft_freq_limited_range(smu, SMU_GFXCLK, min_clk, max_clk);
1451 : }
1452 : break;
1453 : default:
1454 : return -ENOSYS;
1455 : }
1456 :
1457 : return ret;
1458 : }
1459 :
1460 0 : static bool aldebaran_is_dpm_running(struct smu_context *smu)
1461 : {
1462 : int ret;
1463 : uint64_t feature_enabled;
1464 :
1465 0 : ret = smu_cmn_get_enabled_mask(smu, &feature_enabled);
1466 0 : if (ret)
1467 : return false;
1468 0 : return !!(feature_enabled & SMC_DPM_FEATURE);
1469 : }
1470 :
1471 0 : static int aldebaran_i2c_xfer(struct i2c_adapter *i2c_adap,
1472 : struct i2c_msg *msg, int num_msgs)
1473 : {
1474 0 : struct amdgpu_smu_i2c_bus *smu_i2c = i2c_get_adapdata(i2c_adap);
1475 0 : struct amdgpu_device *adev = smu_i2c->adev;
1476 0 : struct smu_context *smu = adev->powerplay.pp_handle;
1477 0 : struct smu_table_context *smu_table = &smu->smu_table;
1478 0 : struct smu_table *table = &smu_table->driver_table;
1479 0 : SwI2cRequest_t *req, *res = (SwI2cRequest_t *)table->cpu_addr;
1480 : int i, j, r, c;
1481 : u16 dir;
1482 :
1483 0 : if (!adev->pm.dpm_enabled)
1484 : return -EBUSY;
1485 :
1486 0 : req = kzalloc(sizeof(*req), GFP_KERNEL);
1487 0 : if (!req)
1488 : return -ENOMEM;
1489 :
1490 0 : req->I2CcontrollerPort = smu_i2c->port;
1491 0 : req->I2CSpeed = I2C_SPEED_FAST_400K;
1492 0 : req->SlaveAddress = msg[0].addr << 1; /* wants an 8-bit address */
1493 0 : dir = msg[0].flags & I2C_M_RD;
1494 :
1495 0 : for (c = i = 0; i < num_msgs; i++) {
1496 0 : for (j = 0; j < msg[i].len; j++, c++) {
1497 0 : SwI2cCmd_t *cmd = &req->SwI2cCmds[c];
1498 :
1499 0 : if (!(msg[i].flags & I2C_M_RD)) {
1500 : /* write */
1501 0 : cmd->CmdConfig |= CMDCONFIG_READWRITE_MASK;
1502 0 : cmd->ReadWriteData = msg[i].buf[j];
1503 : }
1504 :
1505 0 : if ((dir ^ msg[i].flags) & I2C_M_RD) {
1506 : /* The direction changes.
1507 : */
1508 0 : dir = msg[i].flags & I2C_M_RD;
1509 0 : cmd->CmdConfig |= CMDCONFIG_RESTART_MASK;
1510 : }
1511 :
1512 0 : req->NumCmds++;
1513 :
1514 : /*
1515 : * Insert STOP if we are at the last byte of either last
1516 : * message for the transaction or the client explicitly
1517 : * requires a STOP at this particular message.
1518 : */
1519 0 : if ((j == msg[i].len - 1) &&
1520 0 : ((i == num_msgs - 1) || (msg[i].flags & I2C_M_STOP))) {
1521 0 : cmd->CmdConfig &= ~CMDCONFIG_RESTART_MASK;
1522 0 : cmd->CmdConfig |= CMDCONFIG_STOP_MASK;
1523 : }
1524 : }
1525 : }
1526 0 : mutex_lock(&adev->pm.mutex);
1527 0 : r = smu_cmn_update_table(smu, SMU_TABLE_I2C_COMMANDS, 0, req, true);
1528 0 : mutex_unlock(&adev->pm.mutex);
1529 0 : if (r)
1530 : goto fail;
1531 :
1532 0 : for (c = i = 0; i < num_msgs; i++) {
1533 0 : if (!(msg[i].flags & I2C_M_RD)) {
1534 0 : c += msg[i].len;
1535 0 : continue;
1536 : }
1537 0 : for (j = 0; j < msg[i].len; j++, c++) {
1538 0 : SwI2cCmd_t *cmd = &res->SwI2cCmds[c];
1539 :
1540 0 : msg[i].buf[j] = cmd->ReadWriteData;
1541 : }
1542 : }
1543 : r = num_msgs;
1544 : fail:
1545 0 : kfree(req);
1546 0 : return r;
1547 : }
1548 :
1549 0 : static u32 aldebaran_i2c_func(struct i2c_adapter *adap)
1550 : {
1551 0 : return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
1552 : }
1553 :
1554 :
1555 : static const struct i2c_algorithm aldebaran_i2c_algo = {
1556 : .master_xfer = aldebaran_i2c_xfer,
1557 : .functionality = aldebaran_i2c_func,
1558 : };
1559 :
1560 : static const struct i2c_adapter_quirks aldebaran_i2c_control_quirks = {
1561 : .flags = I2C_AQ_COMB | I2C_AQ_COMB_SAME_ADDR | I2C_AQ_NO_ZERO_LEN,
1562 : .max_read_len = MAX_SW_I2C_COMMANDS,
1563 : .max_write_len = MAX_SW_I2C_COMMANDS,
1564 : .max_comb_1st_msg_len = 2,
1565 : .max_comb_2nd_msg_len = MAX_SW_I2C_COMMANDS - 2,
1566 : };
1567 :
1568 0 : static int aldebaran_i2c_control_init(struct smu_context *smu)
1569 : {
1570 0 : struct amdgpu_device *adev = smu->adev;
1571 0 : struct amdgpu_smu_i2c_bus *smu_i2c = &adev->pm.smu_i2c[0];
1572 0 : struct i2c_adapter *control = &smu_i2c->adapter;
1573 : int res;
1574 :
1575 0 : smu_i2c->adev = adev;
1576 0 : smu_i2c->port = 0;
1577 0 : mutex_init(&smu_i2c->mutex);
1578 0 : control->owner = THIS_MODULE;
1579 0 : control->class = I2C_CLASS_SPD;
1580 0 : control->dev.parent = &adev->pdev->dev;
1581 0 : control->algo = &aldebaran_i2c_algo;
1582 0 : snprintf(control->name, sizeof(control->name), "AMDGPU SMU 0");
1583 0 : control->quirks = &aldebaran_i2c_control_quirks;
1584 0 : i2c_set_adapdata(control, smu_i2c);
1585 :
1586 0 : res = i2c_add_adapter(control);
1587 0 : if (res) {
1588 0 : DRM_ERROR("Failed to register hw i2c, err: %d\n", res);
1589 : goto Out_err;
1590 : }
1591 :
1592 0 : adev->pm.ras_eeprom_i2c_bus = &adev->pm.smu_i2c[0].adapter;
1593 0 : adev->pm.fru_eeprom_i2c_bus = &adev->pm.smu_i2c[0].adapter;
1594 :
1595 0 : return 0;
1596 : Out_err:
1597 0 : i2c_del_adapter(control);
1598 :
1599 0 : return res;
1600 : }
1601 :
1602 0 : static void aldebaran_i2c_control_fini(struct smu_context *smu)
1603 : {
1604 0 : struct amdgpu_device *adev = smu->adev;
1605 : int i;
1606 :
1607 0 : for (i = 0; i < MAX_SMU_I2C_BUSES; i++) {
1608 0 : struct amdgpu_smu_i2c_bus *smu_i2c = &adev->pm.smu_i2c[i];
1609 0 : struct i2c_adapter *control = &smu_i2c->adapter;
1610 :
1611 0 : i2c_del_adapter(control);
1612 : }
1613 0 : adev->pm.ras_eeprom_i2c_bus = NULL;
1614 0 : adev->pm.fru_eeprom_i2c_bus = NULL;
1615 0 : }
1616 :
1617 0 : static void aldebaran_get_unique_id(struct smu_context *smu)
1618 : {
1619 0 : struct amdgpu_device *adev = smu->adev;
1620 0 : uint32_t upper32 = 0, lower32 = 0;
1621 :
1622 0 : if (aldebaran_get_smu_metrics_data(smu, METRICS_UNIQUE_ID_UPPER32, &upper32))
1623 : goto out;
1624 : if (aldebaran_get_smu_metrics_data(smu, METRICS_UNIQUE_ID_LOWER32, &lower32))
1625 : goto out;
1626 :
1627 : out:
1628 0 : adev->unique_id = ((uint64_t)upper32 << 32) | lower32;
1629 0 : if (adev->serial[0] == '\0')
1630 0 : sprintf(adev->serial, "%016llx", adev->unique_id);
1631 0 : }
1632 :
1633 0 : static bool aldebaran_is_baco_supported(struct smu_context *smu)
1634 : {
1635 : /* aldebaran is not support baco */
1636 :
1637 0 : return false;
1638 : }
1639 :
1640 0 : static int aldebaran_set_df_cstate(struct smu_context *smu,
1641 : enum pp_df_cstate state)
1642 : {
1643 0 : return smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_DFCstateControl, state, NULL);
1644 : }
1645 :
1646 0 : static int aldebaran_allow_xgmi_power_down(struct smu_context *smu, bool en)
1647 : {
1648 0 : struct amdgpu_device *adev = smu->adev;
1649 :
1650 : /* The message only works on master die and NACK will be sent
1651 : back for other dies, only send it on master die */
1652 0 : if (!adev->smuio.funcs->get_socket_id(adev) &&
1653 0 : !adev->smuio.funcs->get_die_id(adev))
1654 0 : return smu_cmn_send_smc_msg_with_param(smu,
1655 : SMU_MSG_GmiPwrDnControl,
1656 0 : en ? 0 : 1,
1657 : NULL);
1658 : else
1659 : return 0;
1660 : }
1661 :
1662 : static const struct throttling_logging_label {
1663 : uint32_t feature_mask;
1664 : const char *label;
1665 : } logging_label[] = {
1666 : {(1U << THROTTLER_TEMP_GPU_BIT), "GPU"},
1667 : {(1U << THROTTLER_TEMP_MEM_BIT), "HBM"},
1668 : {(1U << THROTTLER_TEMP_VR_GFX_BIT), "VR of GFX rail"},
1669 : {(1U << THROTTLER_TEMP_VR_MEM_BIT), "VR of HBM rail"},
1670 : {(1U << THROTTLER_TEMP_VR_SOC_BIT), "VR of SOC rail"},
1671 : };
1672 0 : static void aldebaran_log_thermal_throttling_event(struct smu_context *smu)
1673 : {
1674 : int ret;
1675 0 : int throttler_idx, throtting_events = 0, buf_idx = 0;
1676 0 : struct amdgpu_device *adev = smu->adev;
1677 : uint32_t throttler_status;
1678 : char log_buf[256];
1679 :
1680 0 : ret = aldebaran_get_smu_metrics_data(smu,
1681 : METRICS_THROTTLER_STATUS,
1682 : &throttler_status);
1683 0 : if (ret)
1684 0 : return;
1685 :
1686 0 : memset(log_buf, 0, sizeof(log_buf));
1687 0 : for (throttler_idx = 0; throttler_idx < ARRAY_SIZE(logging_label);
1688 0 : throttler_idx++) {
1689 0 : if (throttler_status & logging_label[throttler_idx].feature_mask) {
1690 0 : throtting_events++;
1691 0 : buf_idx += snprintf(log_buf + buf_idx,
1692 : sizeof(log_buf) - buf_idx,
1693 : "%s%s",
1694 : throtting_events > 1 ? " and " : "",
1695 : logging_label[throttler_idx].label);
1696 0 : if (buf_idx >= sizeof(log_buf)) {
1697 0 : dev_err(adev->dev, "buffer overflow!\n");
1698 0 : log_buf[sizeof(log_buf) - 1] = '\0';
1699 0 : break;
1700 : }
1701 : }
1702 : }
1703 :
1704 0 : dev_warn(adev->dev, "WARN: GPU thermal throttling temperature reached, expect performance decrease. %s.\n",
1705 : log_buf);
1706 0 : kgd2kfd_smi_event_throttle(smu->adev->kfd.dev,
1707 : smu_cmn_get_indep_throttler_status(throttler_status,
1708 : aldebaran_throttler_map));
1709 : }
1710 :
1711 0 : static int aldebaran_get_current_pcie_link_speed(struct smu_context *smu)
1712 : {
1713 0 : struct amdgpu_device *adev = smu->adev;
1714 : uint32_t esm_ctrl;
1715 :
1716 : /* TODO: confirm this on real target */
1717 0 : esm_ctrl = RREG32_PCIE(smnPCIE_ESM_CTRL);
1718 0 : if ((esm_ctrl >> 15) & 0x1FFFF)
1719 0 : return (((esm_ctrl >> 8) & 0x3F) + 128);
1720 :
1721 0 : return smu_v13_0_get_current_pcie_link_speed(smu);
1722 : }
1723 :
1724 0 : static ssize_t aldebaran_get_gpu_metrics(struct smu_context *smu,
1725 : void **table)
1726 : {
1727 0 : struct smu_table_context *smu_table = &smu->smu_table;
1728 0 : struct gpu_metrics_v1_3 *gpu_metrics =
1729 : (struct gpu_metrics_v1_3 *)smu_table->gpu_metrics_table;
1730 : SmuMetrics_t metrics;
1731 0 : int i, ret = 0;
1732 :
1733 0 : ret = smu_cmn_get_metrics_table(smu,
1734 : &metrics,
1735 : true);
1736 0 : if (ret)
1737 0 : return ret;
1738 :
1739 0 : smu_cmn_init_soft_gpu_metrics(gpu_metrics, 1, 3);
1740 :
1741 0 : gpu_metrics->temperature_edge = metrics.TemperatureEdge;
1742 0 : gpu_metrics->temperature_hotspot = metrics.TemperatureHotspot;
1743 0 : gpu_metrics->temperature_mem = metrics.TemperatureHBM;
1744 0 : gpu_metrics->temperature_vrgfx = metrics.TemperatureVrGfx;
1745 0 : gpu_metrics->temperature_vrsoc = metrics.TemperatureVrSoc;
1746 0 : gpu_metrics->temperature_vrmem = metrics.TemperatureVrMem;
1747 :
1748 0 : gpu_metrics->average_gfx_activity = metrics.AverageGfxActivity;
1749 0 : gpu_metrics->average_umc_activity = metrics.AverageUclkActivity;
1750 0 : gpu_metrics->average_mm_activity = 0;
1751 :
1752 : /* Valid power data is available only from primary die */
1753 0 : if (aldebaran_is_primary(smu)) {
1754 0 : gpu_metrics->average_socket_power = metrics.AverageSocketPower;
1755 0 : gpu_metrics->energy_accumulator =
1756 0 : (uint64_t)metrics.EnergyAcc64bitHigh << 32 |
1757 0 : metrics.EnergyAcc64bitLow;
1758 : } else {
1759 0 : gpu_metrics->average_socket_power = 0;
1760 0 : gpu_metrics->energy_accumulator = 0;
1761 : }
1762 :
1763 0 : gpu_metrics->average_gfxclk_frequency = metrics.AverageGfxclkFrequency;
1764 0 : gpu_metrics->average_socclk_frequency = metrics.AverageSocclkFrequency;
1765 0 : gpu_metrics->average_uclk_frequency = metrics.AverageUclkFrequency;
1766 0 : gpu_metrics->average_vclk0_frequency = 0;
1767 0 : gpu_metrics->average_dclk0_frequency = 0;
1768 :
1769 0 : gpu_metrics->current_gfxclk = metrics.CurrClock[PPCLK_GFXCLK];
1770 0 : gpu_metrics->current_socclk = metrics.CurrClock[PPCLK_SOCCLK];
1771 0 : gpu_metrics->current_uclk = metrics.CurrClock[PPCLK_UCLK];
1772 0 : gpu_metrics->current_vclk0 = metrics.CurrClock[PPCLK_VCLK];
1773 0 : gpu_metrics->current_dclk0 = metrics.CurrClock[PPCLK_DCLK];
1774 :
1775 0 : gpu_metrics->throttle_status = metrics.ThrottlerStatus;
1776 0 : gpu_metrics->indep_throttle_status =
1777 0 : smu_cmn_get_indep_throttler_status(metrics.ThrottlerStatus,
1778 : aldebaran_throttler_map);
1779 :
1780 0 : gpu_metrics->current_fan_speed = 0;
1781 :
1782 0 : gpu_metrics->pcie_link_width =
1783 0 : smu_v13_0_get_current_pcie_link_width(smu);
1784 0 : gpu_metrics->pcie_link_speed =
1785 0 : aldebaran_get_current_pcie_link_speed(smu);
1786 :
1787 0 : gpu_metrics->system_clock_counter = ktime_get_boottime_ns();
1788 :
1789 0 : gpu_metrics->gfx_activity_acc = metrics.GfxBusyAcc;
1790 0 : gpu_metrics->mem_activity_acc = metrics.DramBusyAcc;
1791 :
1792 0 : for (i = 0; i < NUM_HBM_INSTANCES; i++)
1793 0 : gpu_metrics->temperature_hbm[i] = metrics.TemperatureAllHBM[i];
1794 :
1795 0 : gpu_metrics->firmware_timestamp = ((uint64_t)metrics.TimeStampHigh << 32) |
1796 0 : metrics.TimeStampLow;
1797 :
1798 0 : *table = (void *)gpu_metrics;
1799 :
1800 0 : return sizeof(struct gpu_metrics_v1_3);
1801 : }
1802 :
1803 0 : static int aldebaran_check_ecc_table_support(struct smu_context *smu,
1804 : int *ecctable_version)
1805 : {
1806 0 : uint32_t if_version = 0xff, smu_version = 0xff;
1807 0 : int ret = 0;
1808 :
1809 0 : ret = smu_cmn_get_smc_version(smu, &if_version, &smu_version);
1810 0 : if (ret) {
1811 : /* return not support if failed get smu_version */
1812 0 : ret = -EOPNOTSUPP;
1813 : }
1814 :
1815 0 : if (smu_version < SUPPORT_ECCTABLE_SMU_VERSION)
1816 : ret = -EOPNOTSUPP;
1817 0 : else if (smu_version >= SUPPORT_ECCTABLE_SMU_VERSION &&
1818 : smu_version < SUPPORT_ECCTABLE_V2_SMU_VERSION)
1819 0 : *ecctable_version = 1;
1820 : else
1821 0 : *ecctable_version = 2;
1822 :
1823 0 : return ret;
1824 : }
1825 :
1826 0 : static ssize_t aldebaran_get_ecc_info(struct smu_context *smu,
1827 : void *table)
1828 : {
1829 0 : struct smu_table_context *smu_table = &smu->smu_table;
1830 0 : EccInfoTable_t *ecc_table = NULL;
1831 0 : struct ecc_info_per_ch *ecc_info_per_channel = NULL;
1832 0 : int i, ret = 0;
1833 0 : int table_version = 0;
1834 0 : struct umc_ecc_info *eccinfo = (struct umc_ecc_info *)table;
1835 :
1836 0 : ret = aldebaran_check_ecc_table_support(smu, &table_version);
1837 0 : if (ret)
1838 0 : return ret;
1839 :
1840 0 : ret = smu_cmn_update_table(smu,
1841 : SMU_TABLE_ECCINFO,
1842 : 0,
1843 : smu_table->ecc_table,
1844 : false);
1845 0 : if (ret) {
1846 0 : dev_info(smu->adev->dev, "Failed to export SMU ecc table!\n");
1847 0 : return ret;
1848 : }
1849 :
1850 0 : ecc_table = (EccInfoTable_t *)smu_table->ecc_table;
1851 :
1852 0 : if (table_version == 1) {
1853 0 : for (i = 0; i < ALDEBARAN_UMC_CHANNEL_NUM; i++) {
1854 0 : ecc_info_per_channel = &(eccinfo->ecc[i]);
1855 0 : ecc_info_per_channel->ce_count_lo_chip =
1856 0 : ecc_table->EccInfo[i].ce_count_lo_chip;
1857 0 : ecc_info_per_channel->ce_count_hi_chip =
1858 0 : ecc_table->EccInfo[i].ce_count_hi_chip;
1859 0 : ecc_info_per_channel->mca_umc_status =
1860 0 : ecc_table->EccInfo[i].mca_umc_status;
1861 0 : ecc_info_per_channel->mca_umc_addr =
1862 0 : ecc_table->EccInfo[i].mca_umc_addr;
1863 : }
1864 0 : } else if (table_version == 2) {
1865 0 : for (i = 0; i < ALDEBARAN_UMC_CHANNEL_NUM; i++) {
1866 0 : ecc_info_per_channel = &(eccinfo->ecc[i]);
1867 0 : ecc_info_per_channel->ce_count_lo_chip =
1868 0 : ecc_table->EccInfo_V2[i].ce_count_lo_chip;
1869 0 : ecc_info_per_channel->ce_count_hi_chip =
1870 0 : ecc_table->EccInfo_V2[i].ce_count_hi_chip;
1871 0 : ecc_info_per_channel->mca_umc_status =
1872 0 : ecc_table->EccInfo_V2[i].mca_umc_status;
1873 0 : ecc_info_per_channel->mca_umc_addr =
1874 0 : ecc_table->EccInfo_V2[i].mca_umc_addr;
1875 0 : ecc_info_per_channel->mca_ceumc_addr =
1876 0 : ecc_table->EccInfo_V2[i].mca_ceumc_addr;
1877 : }
1878 0 : eccinfo->record_ce_addr_supported = 1;
1879 : }
1880 :
1881 0 : return ret;
1882 : }
1883 :
1884 0 : static int aldebaran_mode1_reset(struct smu_context *smu)
1885 : {
1886 : u32 smu_version, fatal_err, param;
1887 0 : int ret = 0;
1888 0 : struct amdgpu_device *adev = smu->adev;
1889 0 : struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
1890 :
1891 0 : fatal_err = 0;
1892 0 : param = SMU_RESET_MODE_1;
1893 :
1894 : /*
1895 : * PM FW support SMU_MSG_GfxDeviceDriverReset from 68.07
1896 : */
1897 0 : smu_cmn_get_smc_version(smu, NULL, &smu_version);
1898 0 : if (smu_version < 0x00440700) {
1899 0 : ret = smu_cmn_send_smc_msg(smu, SMU_MSG_Mode1Reset, NULL);
1900 : }
1901 : else {
1902 : /* fatal error triggered by ras, PMFW supports the flag
1903 : from 68.44.0 */
1904 0 : if ((smu_version >= 0x00442c00) && ras &&
1905 0 : atomic_read(&ras->in_recovery))
1906 0 : fatal_err = 1;
1907 :
1908 0 : param |= (fatal_err << 16);
1909 0 : ret = smu_cmn_send_smc_msg_with_param(smu,
1910 : SMU_MSG_GfxDeviceDriverReset, param, NULL);
1911 : }
1912 :
1913 0 : if (!ret)
1914 0 : msleep(SMU13_MODE1_RESET_WAIT_TIME_IN_MS);
1915 :
1916 0 : return ret;
1917 : }
1918 :
1919 0 : static int aldebaran_mode2_reset(struct smu_context *smu)
1920 : {
1921 : u32 smu_version;
1922 0 : int ret = 0, index;
1923 0 : struct amdgpu_device *adev = smu->adev;
1924 0 : int timeout = 10;
1925 :
1926 0 : smu_cmn_get_smc_version(smu, NULL, &smu_version);
1927 :
1928 0 : index = smu_cmn_to_asic_specific_index(smu, CMN2ASIC_MAPPING_MSG,
1929 : SMU_MSG_GfxDeviceDriverReset);
1930 :
1931 0 : mutex_lock(&smu->message_lock);
1932 0 : if (smu_version >= 0x00441400) {
1933 0 : ret = smu_cmn_send_msg_without_waiting(smu, (uint16_t)index, SMU_RESET_MODE_2);
1934 : /* This is similar to FLR, wait till max FLR timeout */
1935 0 : msleep(100);
1936 : dev_dbg(smu->adev->dev, "restore config space...\n");
1937 : /* Restore the config space saved during init */
1938 0 : amdgpu_device_load_pci_state(adev->pdev);
1939 :
1940 : dev_dbg(smu->adev->dev, "wait for reset ack\n");
1941 0 : while (ret == -ETIME && timeout) {
1942 0 : ret = smu_cmn_wait_for_response(smu);
1943 : /* Wait a bit more time for getting ACK */
1944 0 : if (ret == -ETIME) {
1945 0 : --timeout;
1946 0 : usleep_range(500, 1000);
1947 0 : continue;
1948 : }
1949 :
1950 0 : if (ret != 1) {
1951 0 : dev_err(adev->dev, "failed to send mode2 message \tparam: 0x%08x response %#x\n",
1952 : SMU_RESET_MODE_2, ret);
1953 0 : goto out;
1954 : }
1955 : }
1956 :
1957 : } else {
1958 0 : dev_err(adev->dev, "smu fw 0x%x does not support MSG_GfxDeviceDriverReset MSG\n",
1959 : smu_version);
1960 : }
1961 :
1962 0 : if (ret == 1)
1963 0 : ret = 0;
1964 : out:
1965 0 : mutex_unlock(&smu->message_lock);
1966 :
1967 0 : return ret;
1968 : }
1969 :
1970 0 : static int aldebaran_smu_handle_passthrough_sbr(struct smu_context *smu, bool enable)
1971 : {
1972 0 : int ret = 0;
1973 0 : ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_HeavySBR, enable ? 1 : 0, NULL);
1974 :
1975 0 : return ret;
1976 : }
1977 :
1978 0 : static bool aldebaran_is_mode1_reset_supported(struct smu_context *smu)
1979 : {
1980 : #if 0
1981 : struct amdgpu_device *adev = smu->adev;
1982 : u32 smu_version;
1983 : uint32_t val;
1984 : /**
1985 : * PM FW version support mode1 reset from 68.07
1986 : */
1987 : smu_cmn_get_smc_version(smu, NULL, &smu_version);
1988 : if ((smu_version < 0x00440700))
1989 : return false;
1990 : /**
1991 : * mode1 reset relies on PSP, so we should check if
1992 : * PSP is alive.
1993 : */
1994 : val = RREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_81);
1995 :
1996 : return val != 0x0;
1997 : #endif
1998 0 : return true;
1999 : }
2000 :
2001 0 : static bool aldebaran_is_mode2_reset_supported(struct smu_context *smu)
2002 : {
2003 0 : return true;
2004 : }
2005 :
2006 0 : static int aldebaran_set_mp1_state(struct smu_context *smu,
2007 : enum pp_mp1_state mp1_state)
2008 : {
2009 0 : switch (mp1_state) {
2010 : case PP_MP1_STATE_UNLOAD:
2011 0 : return smu_cmn_set_mp1_state(smu, mp1_state);
2012 : default:
2013 : return 0;
2014 : }
2015 : }
2016 :
2017 0 : static int aldebaran_smu_send_hbm_bad_page_num(struct smu_context *smu,
2018 : uint32_t size)
2019 : {
2020 0 : int ret = 0;
2021 :
2022 : /* message SMU to update the bad page number on SMUBUS */
2023 0 : ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetNumBadHbmPagesRetired, size, NULL);
2024 0 : if (ret)
2025 0 : dev_err(smu->adev->dev, "[%s] failed to message SMU to update HBM bad pages number\n",
2026 : __func__);
2027 :
2028 0 : return ret;
2029 : }
2030 :
2031 0 : static int aldebaran_check_bad_channel_info_support(struct smu_context *smu)
2032 : {
2033 0 : uint32_t if_version = 0xff, smu_version = 0xff;
2034 0 : int ret = 0;
2035 :
2036 0 : ret = smu_cmn_get_smc_version(smu, &if_version, &smu_version);
2037 0 : if (ret) {
2038 : /* return not support if failed get smu_version */
2039 0 : ret = -EOPNOTSUPP;
2040 : }
2041 :
2042 0 : if (smu_version < SUPPORT_BAD_CHANNEL_INFO_MSG_VERSION)
2043 0 : ret = -EOPNOTSUPP;
2044 :
2045 0 : return ret;
2046 : }
2047 :
2048 0 : static int aldebaran_send_hbm_bad_channel_flag(struct smu_context *smu,
2049 : uint32_t size)
2050 : {
2051 0 : int ret = 0;
2052 :
2053 0 : ret = aldebaran_check_bad_channel_info_support(smu);
2054 0 : if (ret)
2055 : return ret;
2056 :
2057 : /* message SMU to update the bad channel info on SMUBUS */
2058 0 : ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetBadHBMPagesRetiredFlagsPerChannel, size, NULL);
2059 0 : if (ret)
2060 0 : dev_err(smu->adev->dev, "[%s] failed to message SMU to update HBM bad channel info\n",
2061 : __func__);
2062 :
2063 : return ret;
2064 : }
2065 :
2066 : static const struct pptable_funcs aldebaran_ppt_funcs = {
2067 : /* init dpm */
2068 : .get_allowed_feature_mask = aldebaran_get_allowed_feature_mask,
2069 : /* dpm/clk tables */
2070 : .set_default_dpm_table = aldebaran_set_default_dpm_table,
2071 : .populate_umd_state_clk = aldebaran_populate_umd_state_clk,
2072 : .get_thermal_temperature_range = aldebaran_get_thermal_temperature_range,
2073 : .print_clk_levels = aldebaran_print_clk_levels,
2074 : .force_clk_levels = aldebaran_force_clk_levels,
2075 : .read_sensor = aldebaran_read_sensor,
2076 : .set_performance_level = aldebaran_set_performance_level,
2077 : .get_power_limit = aldebaran_get_power_limit,
2078 : .is_dpm_running = aldebaran_is_dpm_running,
2079 : .get_unique_id = aldebaran_get_unique_id,
2080 : .init_microcode = smu_v13_0_init_microcode,
2081 : .load_microcode = smu_v13_0_load_microcode,
2082 : .fini_microcode = smu_v13_0_fini_microcode,
2083 : .init_smc_tables = aldebaran_init_smc_tables,
2084 : .fini_smc_tables = smu_v13_0_fini_smc_tables,
2085 : .init_power = smu_v13_0_init_power,
2086 : .fini_power = smu_v13_0_fini_power,
2087 : .check_fw_status = smu_v13_0_check_fw_status,
2088 : /* pptable related */
2089 : .setup_pptable = aldebaran_setup_pptable,
2090 : .get_vbios_bootup_values = smu_v13_0_get_vbios_bootup_values,
2091 : .check_fw_version = smu_v13_0_check_fw_version,
2092 : .write_pptable = smu_cmn_write_pptable,
2093 : .set_driver_table_location = smu_v13_0_set_driver_table_location,
2094 : .set_tool_table_location = smu_v13_0_set_tool_table_location,
2095 : .notify_memory_pool_location = smu_v13_0_notify_memory_pool_location,
2096 : .system_features_control = aldebaran_system_features_control,
2097 : .send_smc_msg_with_param = smu_cmn_send_smc_msg_with_param,
2098 : .send_smc_msg = smu_cmn_send_smc_msg,
2099 : .get_enabled_mask = smu_cmn_get_enabled_mask,
2100 : .feature_is_enabled = smu_cmn_feature_is_enabled,
2101 : .disable_all_features_with_exception = smu_cmn_disable_all_features_with_exception,
2102 : .set_power_limit = aldebaran_set_power_limit,
2103 : .init_max_sustainable_clocks = smu_v13_0_init_max_sustainable_clocks,
2104 : .enable_thermal_alert = smu_v13_0_enable_thermal_alert,
2105 : .disable_thermal_alert = smu_v13_0_disable_thermal_alert,
2106 : .set_xgmi_pstate = smu_v13_0_set_xgmi_pstate,
2107 : .register_irq_handler = smu_v13_0_register_irq_handler,
2108 : .set_azalia_d3_pme = smu_v13_0_set_azalia_d3_pme,
2109 : .get_max_sustainable_clocks_by_dc = smu_v13_0_get_max_sustainable_clocks_by_dc,
2110 : .baco_is_support= aldebaran_is_baco_supported,
2111 : .get_dpm_ultimate_freq = smu_v13_0_get_dpm_ultimate_freq,
2112 : .set_soft_freq_limited_range = aldebaran_set_soft_freq_limited_range,
2113 : .od_edit_dpm_table = aldebaran_usr_edit_dpm_table,
2114 : .set_df_cstate = aldebaran_set_df_cstate,
2115 : .allow_xgmi_power_down = aldebaran_allow_xgmi_power_down,
2116 : .log_thermal_throttling_event = aldebaran_log_thermal_throttling_event,
2117 : .get_pp_feature_mask = smu_cmn_get_pp_feature_mask,
2118 : .set_pp_feature_mask = smu_cmn_set_pp_feature_mask,
2119 : .get_gpu_metrics = aldebaran_get_gpu_metrics,
2120 : .mode1_reset_is_support = aldebaran_is_mode1_reset_supported,
2121 : .mode2_reset_is_support = aldebaran_is_mode2_reset_supported,
2122 : .smu_handle_passthrough_sbr = aldebaran_smu_handle_passthrough_sbr,
2123 : .mode1_reset = aldebaran_mode1_reset,
2124 : .set_mp1_state = aldebaran_set_mp1_state,
2125 : .mode2_reset = aldebaran_mode2_reset,
2126 : .wait_for_event = smu_v13_0_wait_for_event,
2127 : .i2c_init = aldebaran_i2c_control_init,
2128 : .i2c_fini = aldebaran_i2c_control_fini,
2129 : .send_hbm_bad_pages_num = aldebaran_smu_send_hbm_bad_page_num,
2130 : .get_ecc_info = aldebaran_get_ecc_info,
2131 : .send_hbm_bad_channel_flag = aldebaran_send_hbm_bad_channel_flag,
2132 : };
2133 :
2134 0 : void aldebaran_set_ppt_funcs(struct smu_context *smu)
2135 : {
2136 0 : smu->ppt_funcs = &aldebaran_ppt_funcs;
2137 0 : smu->message_map = aldebaran_message_map;
2138 0 : smu->clock_map = aldebaran_clk_map;
2139 0 : smu->feature_map = aldebaran_feature_mask_map;
2140 0 : smu->table_map = aldebaran_table_map;
2141 0 : smu_v13_0_set_smu_mailbox_registers(smu);
2142 0 : }
|