1 /* $NetBSD: amdgpu_vega20_smumgr.c,v 1.2 2021/12/18 23:45:27 riastradh Exp $ */
2
3 /*
4 * Copyright 2018 Advanced Micro Devices, Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
23 *
24 */
25
26 #include <sys/cdefs.h>
27 __KERNEL_RCSID(0, "$NetBSD: amdgpu_vega20_smumgr.c,v 1.2 2021/12/18 23:45:27 riastradh Exp $");
28
29 #include "smumgr.h"
30 #include "vega20_inc.h"
31 #include "soc15_common.h"
32 #include "vega20_smumgr.h"
33 #include "vega20_ppsmc.h"
34 #include "smu11_driver_if.h"
35 #include "ppatomctrl.h"
36 #include "pp_debug.h"
37 #include "smu_ucode_xfer_vi.h"
38 #include "smu7_smumgr.h"
39 #include "vega20_hwmgr.h"
40
41 /* MP Apertures */
42 #define MP0_Public 0x03800000
43 #define MP0_SRAM 0x03900000
44 #define MP1_Public 0x03b00000
45 #define MP1_SRAM 0x03c00004
46
47 /* address block */
48 #define smnMP1_FIRMWARE_FLAGS 0x3010024
49 #define smnMP0_FW_INTF 0x30101c0
50 #define smnMP1_PUB_CTRL 0x3010b14
51
vega20_is_smc_ram_running(struct pp_hwmgr * hwmgr)52 bool vega20_is_smc_ram_running(struct pp_hwmgr *hwmgr)
53 {
54 struct amdgpu_device *adev = hwmgr->adev;
55 uint32_t mp1_fw_flags;
56
57 mp1_fw_flags = RREG32_PCIE(MP1_Public |
58 (smnMP1_FIRMWARE_FLAGS & 0xffffffff));
59
60 if ((mp1_fw_flags & MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED_MASK) >>
61 MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED__SHIFT)
62 return true;
63
64 return false;
65 }
66
67 /*
68 * Check if SMC has responded to previous message.
69 *
70 * @param smumgr the address of the powerplay hardware manager.
71 * @return TRUE SMC has responded, FALSE otherwise.
72 */
vega20_wait_for_response(struct pp_hwmgr * hwmgr)73 static uint32_t vega20_wait_for_response(struct pp_hwmgr *hwmgr)
74 {
75 struct amdgpu_device *adev = hwmgr->adev;
76 uint32_t reg;
77
78 reg = SOC15_REG_OFFSET(MP1, 0, mmMP1_SMN_C2PMSG_90);
79
80 phm_wait_for_register_unequal(hwmgr, reg,
81 0, MP1_C2PMSG_90__CONTENT_MASK);
82
83 return RREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_90);
84 }
85
86 /*
87 * Send a message to the SMC, and do not wait for its response.
88 * @param smumgr the address of the powerplay hardware manager.
89 * @param msg the message to send.
90 * @return Always return 0.
91 */
vega20_send_msg_to_smc_without_waiting(struct pp_hwmgr * hwmgr,uint16_t msg)92 static int vega20_send_msg_to_smc_without_waiting(struct pp_hwmgr *hwmgr,
93 uint16_t msg)
94 {
95 struct amdgpu_device *adev = hwmgr->adev;
96
97 WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_66, msg);
98
99 return 0;
100 }
101
102 /*
103 * Send a message to the SMC, and wait for its response.
104 * @param hwmgr the address of the powerplay hardware manager.
105 * @param msg the message to send.
106 * @return Always return 0.
107 */
vega20_send_msg_to_smc(struct pp_hwmgr * hwmgr,uint16_t msg)108 static int vega20_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg)
109 {
110 struct amdgpu_device *adev = hwmgr->adev;
111 int ret = 0;
112
113 vega20_wait_for_response(hwmgr);
114
115 WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_90, 0);
116
117 vega20_send_msg_to_smc_without_waiting(hwmgr, msg);
118
119 ret = vega20_wait_for_response(hwmgr);
120 if (ret != PPSMC_Result_OK)
121 pr_err("Failed to send message 0x%x, response 0x%x\n", msg, ret);
122
123 return (ret == PPSMC_Result_OK) ? 0 : -EIO;
124 }
125
126 /*
127 * Send a message to the SMC with parameter
128 * @param hwmgr: the address of the powerplay hardware manager.
129 * @param msg: the message to send.
130 * @param parameter: the parameter to send
131 * @return Always return 0.
132 */
vega20_send_msg_to_smc_with_parameter(struct pp_hwmgr * hwmgr,uint16_t msg,uint32_t parameter)133 static int vega20_send_msg_to_smc_with_parameter(struct pp_hwmgr *hwmgr,
134 uint16_t msg, uint32_t parameter)
135 {
136 struct amdgpu_device *adev = hwmgr->adev;
137 int ret = 0;
138
139 vega20_wait_for_response(hwmgr);
140
141 WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_90, 0);
142
143 WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_82, parameter);
144
145 vega20_send_msg_to_smc_without_waiting(hwmgr, msg);
146
147 ret = vega20_wait_for_response(hwmgr);
148 if (ret != PPSMC_Result_OK)
149 pr_err("Failed to send message 0x%x, response 0x%x\n", msg, ret);
150
151 return (ret == PPSMC_Result_OK) ? 0 : -EIO;
152 }
153
vega20_get_argument(struct pp_hwmgr * hwmgr)154 static uint32_t vega20_get_argument(struct pp_hwmgr *hwmgr)
155 {
156 struct amdgpu_device *adev = hwmgr->adev;
157
158 return RREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_82);
159 }
160
161 /*
162 * Copy table from SMC into driver FB
163 * @param hwmgr the address of the HW manager
164 * @param table_id the driver's table ID to copy from
165 */
vega20_copy_table_from_smc(struct pp_hwmgr * hwmgr,uint8_t * table,int16_t table_id)166 static int vega20_copy_table_from_smc(struct pp_hwmgr *hwmgr,
167 uint8_t *table, int16_t table_id)
168 {
169 struct vega20_smumgr *priv =
170 (struct vega20_smumgr *)(hwmgr->smu_backend);
171 struct amdgpu_device *adev = hwmgr->adev;
172 int ret = 0;
173
174 PP_ASSERT_WITH_CODE(table_id < TABLE_COUNT,
175 "Invalid SMU Table ID!", return -EINVAL);
176 PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0,
177 "Invalid SMU Table version!", return -EINVAL);
178 PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0,
179 "Invalid SMU Table Length!", return -EINVAL);
180
181 PP_ASSERT_WITH_CODE((ret = vega20_send_msg_to_smc_with_parameter(hwmgr,
182 PPSMC_MSG_SetDriverDramAddrHigh,
183 upper_32_bits(priv->smu_tables.entry[table_id].mc_addr))) == 0,
184 "[CopyTableFromSMC] Attempt to Set Dram Addr High Failed!",
185 return ret);
186 PP_ASSERT_WITH_CODE((ret = vega20_send_msg_to_smc_with_parameter(hwmgr,
187 PPSMC_MSG_SetDriverDramAddrLow,
188 lower_32_bits(priv->smu_tables.entry[table_id].mc_addr))) == 0,
189 "[CopyTableFromSMC] Attempt to Set Dram Addr Low Failed!",
190 return ret);
191 PP_ASSERT_WITH_CODE((ret = vega20_send_msg_to_smc_with_parameter(hwmgr,
192 PPSMC_MSG_TransferTableSmu2Dram, table_id)) == 0,
193 "[CopyTableFromSMC] Attempt to Transfer Table From SMU Failed!",
194 return ret);
195
196 /* flush hdp cache */
197 amdgpu_asic_flush_hdp(adev, NULL);
198
199 memcpy(table, priv->smu_tables.entry[table_id].table,
200 priv->smu_tables.entry[table_id].size);
201
202 return 0;
203 }
204
205 /*
206 * Copy table from Driver FB into SMC
207 * @param hwmgr the address of the HW manager
208 * @param table_id the table to copy from
209 */
vega20_copy_table_to_smc(struct pp_hwmgr * hwmgr,uint8_t * table,int16_t table_id)210 static int vega20_copy_table_to_smc(struct pp_hwmgr *hwmgr,
211 uint8_t *table, int16_t table_id)
212 {
213 struct vega20_smumgr *priv =
214 (struct vega20_smumgr *)(hwmgr->smu_backend);
215 struct amdgpu_device *adev = hwmgr->adev;
216 int ret = 0;
217
218 PP_ASSERT_WITH_CODE(table_id < TABLE_COUNT,
219 "Invalid SMU Table ID!", return -EINVAL);
220 PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0,
221 "Invalid SMU Table version!", return -EINVAL);
222 PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0,
223 "Invalid SMU Table Length!", return -EINVAL);
224
225 memcpy(priv->smu_tables.entry[table_id].table, table,
226 priv->smu_tables.entry[table_id].size);
227
228 amdgpu_asic_flush_hdp(adev, NULL);
229
230 PP_ASSERT_WITH_CODE((ret = vega20_send_msg_to_smc_with_parameter(hwmgr,
231 PPSMC_MSG_SetDriverDramAddrHigh,
232 upper_32_bits(priv->smu_tables.entry[table_id].mc_addr))) == 0,
233 "[CopyTableToSMC] Attempt to Set Dram Addr High Failed!",
234 return ret);
235 PP_ASSERT_WITH_CODE((ret = vega20_send_msg_to_smc_with_parameter(hwmgr,
236 PPSMC_MSG_SetDriverDramAddrLow,
237 lower_32_bits(priv->smu_tables.entry[table_id].mc_addr))) == 0,
238 "[CopyTableToSMC] Attempt to Set Dram Addr Low Failed!",
239 return ret);
240 PP_ASSERT_WITH_CODE((ret = vega20_send_msg_to_smc_with_parameter(hwmgr,
241 PPSMC_MSG_TransferTableDram2Smu, table_id)) == 0,
242 "[CopyTableToSMC] Attempt to Transfer Table To SMU Failed!",
243 return ret);
244
245 return 0;
246 }
247
vega20_set_activity_monitor_coeff(struct pp_hwmgr * hwmgr,uint8_t * table,uint16_t workload_type)248 int vega20_set_activity_monitor_coeff(struct pp_hwmgr *hwmgr,
249 uint8_t *table, uint16_t workload_type)
250 {
251 struct vega20_smumgr *priv =
252 (struct vega20_smumgr *)(hwmgr->smu_backend);
253 struct amdgpu_device *adev = hwmgr->adev;
254 int ret = 0;
255
256 memcpy(priv->smu_tables.entry[TABLE_ACTIVITY_MONITOR_COEFF].table, table,
257 priv->smu_tables.entry[TABLE_ACTIVITY_MONITOR_COEFF].size);
258
259 amdgpu_asic_flush_hdp(adev, NULL);
260
261 PP_ASSERT_WITH_CODE((ret = vega20_send_msg_to_smc_with_parameter(hwmgr,
262 PPSMC_MSG_SetDriverDramAddrHigh,
263 upper_32_bits(priv->smu_tables.entry[TABLE_ACTIVITY_MONITOR_COEFF].mc_addr))) == 0,
264 "[SetActivityMonitor] Attempt to Set Dram Addr High Failed!",
265 return ret);
266 PP_ASSERT_WITH_CODE((ret = vega20_send_msg_to_smc_with_parameter(hwmgr,
267 PPSMC_MSG_SetDriverDramAddrLow,
268 lower_32_bits(priv->smu_tables.entry[TABLE_ACTIVITY_MONITOR_COEFF].mc_addr))) == 0,
269 "[SetActivityMonitor] Attempt to Set Dram Addr Low Failed!",
270 return ret);
271 PP_ASSERT_WITH_CODE((ret = vega20_send_msg_to_smc_with_parameter(hwmgr,
272 PPSMC_MSG_TransferTableDram2Smu, TABLE_ACTIVITY_MONITOR_COEFF | (workload_type << 16))) == 0,
273 "[SetActivityMonitor] Attempt to Transfer Table To SMU Failed!",
274 return ret);
275
276 return 0;
277 }
278
vega20_get_activity_monitor_coeff(struct pp_hwmgr * hwmgr,uint8_t * table,uint16_t workload_type)279 int vega20_get_activity_monitor_coeff(struct pp_hwmgr *hwmgr,
280 uint8_t *table, uint16_t workload_type)
281 {
282 struct vega20_smumgr *priv =
283 (struct vega20_smumgr *)(hwmgr->smu_backend);
284 struct amdgpu_device *adev = hwmgr->adev;
285 int ret = 0;
286
287 PP_ASSERT_WITH_CODE((ret = vega20_send_msg_to_smc_with_parameter(hwmgr,
288 PPSMC_MSG_SetDriverDramAddrHigh,
289 upper_32_bits(priv->smu_tables.entry[TABLE_ACTIVITY_MONITOR_COEFF].mc_addr))) == 0,
290 "[GetActivityMonitor] Attempt to Set Dram Addr High Failed!",
291 return ret);
292 PP_ASSERT_WITH_CODE((ret = vega20_send_msg_to_smc_with_parameter(hwmgr,
293 PPSMC_MSG_SetDriverDramAddrLow,
294 lower_32_bits(priv->smu_tables.entry[TABLE_ACTIVITY_MONITOR_COEFF].mc_addr))) == 0,
295 "[GetActivityMonitor] Attempt to Set Dram Addr Low Failed!",
296 return ret);
297 PP_ASSERT_WITH_CODE((ret = vega20_send_msg_to_smc_with_parameter(hwmgr,
298 PPSMC_MSG_TransferTableSmu2Dram,
299 TABLE_ACTIVITY_MONITOR_COEFF | (workload_type << 16))) == 0,
300 "[GetActivityMonitor] Attempt to Transfer Table From SMU Failed!",
301 return ret);
302
303 /* flush hdp cache */
304 amdgpu_asic_flush_hdp(adev, NULL);
305
306 memcpy(table, priv->smu_tables.entry[TABLE_ACTIVITY_MONITOR_COEFF].table,
307 priv->smu_tables.entry[TABLE_ACTIVITY_MONITOR_COEFF].size);
308
309 return 0;
310 }
311
vega20_enable_smc_features(struct pp_hwmgr * hwmgr,bool enable,uint64_t feature_mask)312 int vega20_enable_smc_features(struct pp_hwmgr *hwmgr,
313 bool enable, uint64_t feature_mask)
314 {
315 uint32_t smu_features_low, smu_features_high;
316 int ret = 0;
317
318 smu_features_low = (uint32_t)((feature_mask & SMU_FEATURES_LOW_MASK) >> SMU_FEATURES_LOW_SHIFT);
319 smu_features_high = (uint32_t)((feature_mask & SMU_FEATURES_HIGH_MASK) >> SMU_FEATURES_HIGH_SHIFT);
320
321 if (enable) {
322 PP_ASSERT_WITH_CODE((ret = vega20_send_msg_to_smc_with_parameter(hwmgr,
323 PPSMC_MSG_EnableSmuFeaturesLow, smu_features_low)) == 0,
324 "[EnableDisableSMCFeatures] Attempt to enable SMU features Low failed!",
325 return ret);
326 PP_ASSERT_WITH_CODE((ret = vega20_send_msg_to_smc_with_parameter(hwmgr,
327 PPSMC_MSG_EnableSmuFeaturesHigh, smu_features_high)) == 0,
328 "[EnableDisableSMCFeatures] Attempt to enable SMU features High failed!",
329 return ret);
330 } else {
331 PP_ASSERT_WITH_CODE((ret = vega20_send_msg_to_smc_with_parameter(hwmgr,
332 PPSMC_MSG_DisableSmuFeaturesLow, smu_features_low)) == 0,
333 "[EnableDisableSMCFeatures] Attempt to disable SMU features Low failed!",
334 return ret);
335 PP_ASSERT_WITH_CODE((ret = vega20_send_msg_to_smc_with_parameter(hwmgr,
336 PPSMC_MSG_DisableSmuFeaturesHigh, smu_features_high)) == 0,
337 "[EnableDisableSMCFeatures] Attempt to disable SMU features High failed!",
338 return ret);
339 }
340
341 return 0;
342 }
343
vega20_get_enabled_smc_features(struct pp_hwmgr * hwmgr,uint64_t * features_enabled)344 int vega20_get_enabled_smc_features(struct pp_hwmgr *hwmgr,
345 uint64_t *features_enabled)
346 {
347 uint32_t smc_features_low, smc_features_high;
348 int ret = 0;
349
350 if (features_enabled == NULL)
351 return -EINVAL;
352
353 PP_ASSERT_WITH_CODE((ret = vega20_send_msg_to_smc(hwmgr,
354 PPSMC_MSG_GetEnabledSmuFeaturesLow)) == 0,
355 "[GetEnabledSMCFeatures] Attempt to get SMU features Low failed!",
356 return ret);
357 smc_features_low = vega20_get_argument(hwmgr);
358 PP_ASSERT_WITH_CODE((ret = vega20_send_msg_to_smc(hwmgr,
359 PPSMC_MSG_GetEnabledSmuFeaturesHigh)) == 0,
360 "[GetEnabledSMCFeatures] Attempt to get SMU features High failed!",
361 return ret);
362 smc_features_high = vega20_get_argument(hwmgr);
363
364 *features_enabled = ((((uint64_t)smc_features_low << SMU_FEATURES_LOW_SHIFT) & SMU_FEATURES_LOW_MASK) |
365 (((uint64_t)smc_features_high << SMU_FEATURES_HIGH_SHIFT) & SMU_FEATURES_HIGH_MASK));
366
367 return 0;
368 }
369
vega20_set_tools_address(struct pp_hwmgr * hwmgr)370 static int vega20_set_tools_address(struct pp_hwmgr *hwmgr)
371 {
372 struct vega20_smumgr *priv =
373 (struct vega20_smumgr *)(hwmgr->smu_backend);
374 int ret = 0;
375
376 if (priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr) {
377 ret = vega20_send_msg_to_smc_with_parameter(hwmgr,
378 PPSMC_MSG_SetToolsDramAddrHigh,
379 upper_32_bits(priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr));
380 if (!ret)
381 ret = vega20_send_msg_to_smc_with_parameter(hwmgr,
382 PPSMC_MSG_SetToolsDramAddrLow,
383 lower_32_bits(priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr));
384 }
385
386 return ret;
387 }
388
vega20_set_pptable_driver_address(struct pp_hwmgr * hwmgr)389 int vega20_set_pptable_driver_address(struct pp_hwmgr *hwmgr)
390 {
391 struct vega20_smumgr *priv =
392 (struct vega20_smumgr *)(hwmgr->smu_backend);
393 int ret = 0;
394
395 PP_ASSERT_WITH_CODE((ret = vega20_send_msg_to_smc_with_parameter(hwmgr,
396 PPSMC_MSG_SetDriverDramAddrHigh,
397 upper_32_bits(priv->smu_tables.entry[TABLE_PPTABLE].mc_addr))) == 0,
398 "[SetPPtabeDriverAddress] Attempt to Set Dram Addr High Failed!",
399 return ret);
400 PP_ASSERT_WITH_CODE((ret = vega20_send_msg_to_smc_with_parameter(hwmgr,
401 PPSMC_MSG_SetDriverDramAddrLow,
402 lower_32_bits(priv->smu_tables.entry[TABLE_PPTABLE].mc_addr))) == 0,
403 "[SetPPtabeDriverAddress] Attempt to Set Dram Addr Low Failed!",
404 return ret);
405
406 return ret;
407 }
408
vega20_smu_init(struct pp_hwmgr * hwmgr)409 static int vega20_smu_init(struct pp_hwmgr *hwmgr)
410 {
411 struct vega20_smumgr *priv;
412 unsigned long tools_size = 0x19000;
413 int ret = 0;
414
415 struct cgs_firmware_info info = {0};
416
417 ret = cgs_get_firmware_info(hwmgr->device,
418 smu7_convert_fw_type_to_cgs(UCODE_ID_SMU),
419 &info);
420 if (ret || !info.kptr)
421 return -EINVAL;
422
423 priv = kzalloc(sizeof(struct vega20_smumgr), GFP_KERNEL);
424 if (!priv)
425 return -ENOMEM;
426
427 hwmgr->smu_backend = priv;
428
429 /* allocate space for pptable */
430 ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
431 sizeof(PPTable_t),
432 PAGE_SIZE,
433 AMDGPU_GEM_DOMAIN_VRAM,
434 &priv->smu_tables.entry[TABLE_PPTABLE].handle,
435 &priv->smu_tables.entry[TABLE_PPTABLE].mc_addr,
436 &priv->smu_tables.entry[TABLE_PPTABLE].table);
437 if (ret)
438 goto free_backend;
439
440 priv->smu_tables.entry[TABLE_PPTABLE].version = 0x01;
441 priv->smu_tables.entry[TABLE_PPTABLE].size = sizeof(PPTable_t);
442
443 /* allocate space for watermarks table */
444 ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
445 sizeof(Watermarks_t),
446 PAGE_SIZE,
447 AMDGPU_GEM_DOMAIN_VRAM,
448 &priv->smu_tables.entry[TABLE_WATERMARKS].handle,
449 &priv->smu_tables.entry[TABLE_WATERMARKS].mc_addr,
450 &priv->smu_tables.entry[TABLE_WATERMARKS].table);
451 if (ret)
452 goto err0;
453
454 priv->smu_tables.entry[TABLE_WATERMARKS].version = 0x01;
455 priv->smu_tables.entry[TABLE_WATERMARKS].size = sizeof(Watermarks_t);
456
457 /* allocate space for pmstatuslog table */
458 ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
459 tools_size,
460 PAGE_SIZE,
461 AMDGPU_GEM_DOMAIN_VRAM,
462 &priv->smu_tables.entry[TABLE_PMSTATUSLOG].handle,
463 &priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr,
464 &priv->smu_tables.entry[TABLE_PMSTATUSLOG].table);
465 if (ret)
466 goto err1;
467
468 priv->smu_tables.entry[TABLE_PMSTATUSLOG].version = 0x01;
469 priv->smu_tables.entry[TABLE_PMSTATUSLOG].size = tools_size;
470
471 /* allocate space for OverDrive table */
472 ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
473 sizeof(OverDriveTable_t),
474 PAGE_SIZE,
475 AMDGPU_GEM_DOMAIN_VRAM,
476 &priv->smu_tables.entry[TABLE_OVERDRIVE].handle,
477 &priv->smu_tables.entry[TABLE_OVERDRIVE].mc_addr,
478 &priv->smu_tables.entry[TABLE_OVERDRIVE].table);
479 if (ret)
480 goto err2;
481
482 priv->smu_tables.entry[TABLE_OVERDRIVE].version = 0x01;
483 priv->smu_tables.entry[TABLE_OVERDRIVE].size = sizeof(OverDriveTable_t);
484
485 /* allocate space for SmuMetrics table */
486 ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
487 sizeof(SmuMetrics_t),
488 PAGE_SIZE,
489 AMDGPU_GEM_DOMAIN_VRAM,
490 &priv->smu_tables.entry[TABLE_SMU_METRICS].handle,
491 &priv->smu_tables.entry[TABLE_SMU_METRICS].mc_addr,
492 &priv->smu_tables.entry[TABLE_SMU_METRICS].table);
493 if (ret)
494 goto err3;
495
496 priv->smu_tables.entry[TABLE_SMU_METRICS].version = 0x01;
497 priv->smu_tables.entry[TABLE_SMU_METRICS].size = sizeof(SmuMetrics_t);
498
499 /* allocate space for ActivityMonitor table */
500 ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
501 sizeof(DpmActivityMonitorCoeffInt_t),
502 PAGE_SIZE,
503 AMDGPU_GEM_DOMAIN_VRAM,
504 &priv->smu_tables.entry[TABLE_ACTIVITY_MONITOR_COEFF].handle,
505 &priv->smu_tables.entry[TABLE_ACTIVITY_MONITOR_COEFF].mc_addr,
506 &priv->smu_tables.entry[TABLE_ACTIVITY_MONITOR_COEFF].table);
507 if (ret)
508 goto err4;
509
510 priv->smu_tables.entry[TABLE_ACTIVITY_MONITOR_COEFF].version = 0x01;
511 priv->smu_tables.entry[TABLE_ACTIVITY_MONITOR_COEFF].size = sizeof(DpmActivityMonitorCoeffInt_t);
512
513 return 0;
514
515 err4:
516 amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_SMU_METRICS].handle,
517 &priv->smu_tables.entry[TABLE_SMU_METRICS].mc_addr,
518 &priv->smu_tables.entry[TABLE_SMU_METRICS].table);
519 err3:
520 amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_OVERDRIVE].handle,
521 &priv->smu_tables.entry[TABLE_OVERDRIVE].mc_addr,
522 &priv->smu_tables.entry[TABLE_OVERDRIVE].table);
523 err2:
524 amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_PMSTATUSLOG].handle,
525 &priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr,
526 &priv->smu_tables.entry[TABLE_PMSTATUSLOG].table);
527 err1:
528 amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_WATERMARKS].handle,
529 &priv->smu_tables.entry[TABLE_WATERMARKS].mc_addr,
530 &priv->smu_tables.entry[TABLE_WATERMARKS].table);
531 err0:
532 amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_PPTABLE].handle,
533 &priv->smu_tables.entry[TABLE_PPTABLE].mc_addr,
534 &priv->smu_tables.entry[TABLE_PPTABLE].table);
535 free_backend:
536 kfree(hwmgr->smu_backend);
537
538 return -EINVAL;
539 }
540
vega20_smu_fini(struct pp_hwmgr * hwmgr)541 static int vega20_smu_fini(struct pp_hwmgr *hwmgr)
542 {
543 struct vega20_smumgr *priv =
544 (struct vega20_smumgr *)(hwmgr->smu_backend);
545
546 if (priv) {
547 amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_PPTABLE].handle,
548 &priv->smu_tables.entry[TABLE_PPTABLE].mc_addr,
549 &priv->smu_tables.entry[TABLE_PPTABLE].table);
550 amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_WATERMARKS].handle,
551 &priv->smu_tables.entry[TABLE_WATERMARKS].mc_addr,
552 &priv->smu_tables.entry[TABLE_WATERMARKS].table);
553 amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_PMSTATUSLOG].handle,
554 &priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr,
555 &priv->smu_tables.entry[TABLE_PMSTATUSLOG].table);
556 amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_OVERDRIVE].handle,
557 &priv->smu_tables.entry[TABLE_OVERDRIVE].mc_addr,
558 &priv->smu_tables.entry[TABLE_OVERDRIVE].table);
559 amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_SMU_METRICS].handle,
560 &priv->smu_tables.entry[TABLE_SMU_METRICS].mc_addr,
561 &priv->smu_tables.entry[TABLE_SMU_METRICS].table);
562 amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_ACTIVITY_MONITOR_COEFF].handle,
563 &priv->smu_tables.entry[TABLE_ACTIVITY_MONITOR_COEFF].mc_addr,
564 &priv->smu_tables.entry[TABLE_ACTIVITY_MONITOR_COEFF].table);
565 kfree(hwmgr->smu_backend);
566 hwmgr->smu_backend = NULL;
567 }
568 return 0;
569 }
570
vega20_start_smu(struct pp_hwmgr * hwmgr)571 static int vega20_start_smu(struct pp_hwmgr *hwmgr)
572 {
573 int ret;
574
575 ret = vega20_is_smc_ram_running(hwmgr);
576 PP_ASSERT_WITH_CODE(ret,
577 "[Vega20StartSmu] SMC is not running!",
578 return -EINVAL);
579
580 ret = vega20_set_tools_address(hwmgr);
581 PP_ASSERT_WITH_CODE(!ret,
582 "[Vega20StartSmu] Failed to set tools address!",
583 return ret);
584
585 return 0;
586 }
587
vega20_is_dpm_running(struct pp_hwmgr * hwmgr)588 static bool vega20_is_dpm_running(struct pp_hwmgr *hwmgr)
589 {
590 uint64_t features_enabled = 0;
591
592 vega20_get_enabled_smc_features(hwmgr, &features_enabled);
593
594 if (features_enabled & SMC_DPM_FEATURES)
595 return true;
596 else
597 return false;
598 }
599
vega20_smc_table_manager(struct pp_hwmgr * hwmgr,uint8_t * table,uint16_t table_id,bool rw)600 static int vega20_smc_table_manager(struct pp_hwmgr *hwmgr, uint8_t *table,
601 uint16_t table_id, bool rw)
602 {
603 int ret;
604
605 if (rw)
606 ret = vega20_copy_table_from_smc(hwmgr, table, table_id);
607 else
608 ret = vega20_copy_table_to_smc(hwmgr, table, table_id);
609
610 return ret;
611 }
612
613 const struct pp_smumgr_func vega20_smu_funcs = {
614 .name = "vega20_smu",
615 .smu_init = &vega20_smu_init,
616 .smu_fini = &vega20_smu_fini,
617 .start_smu = &vega20_start_smu,
618 .request_smu_load_specific_fw = NULL,
619 .send_msg_to_smc = &vega20_send_msg_to_smc,
620 .send_msg_to_smc_with_parameter = &vega20_send_msg_to_smc_with_parameter,
621 .download_pptable_settings = NULL,
622 .upload_pptable_settings = NULL,
623 .is_dpm_running = vega20_is_dpm_running,
624 .get_argument = vega20_get_argument,
625 .smc_table_manager = vega20_smc_table_manager,
626 };
627