2 * Copyright 2017 Advanced Micro Devices, Inc.
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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.
25 #include "vega12_inc.h"
26 #include "soc15_common.h"
27 #include "smu9_smumgr.h"
28 #include "vega12_smumgr.h"
29 #include "vega12_ppsmc.h"
30 #include "vega12/smu9_driver_if.h"
31 #include "ppatomctrl.h"
36 * Copy table from SMC into driver FB
37 * @param hwmgr the address of the HW manager
38 * @param table_id the driver's table ID to copy from
40 static int vega12_copy_table_from_smc(struct pp_hwmgr
*hwmgr
,
41 uint8_t *table
, int16_t table_id
)
43 struct vega12_smumgr
*priv
=
44 (struct vega12_smumgr
*)(hwmgr
->smu_backend
);
45 struct amdgpu_device
*adev
= hwmgr
->adev
;
47 PP_ASSERT_WITH_CODE(table_id
< TABLE_COUNT
,
48 "Invalid SMU Table ID!", return -EINVAL
);
49 PP_ASSERT_WITH_CODE(priv
->smu_tables
.entry
[table_id
].version
!= 0,
50 "Invalid SMU Table version!", return -EINVAL
);
51 PP_ASSERT_WITH_CODE(priv
->smu_tables
.entry
[table_id
].size
!= 0,
52 "Invalid SMU Table Length!", return -EINVAL
);
53 PP_ASSERT_WITH_CODE(smu9_send_msg_to_smc_with_parameter(hwmgr
,
54 PPSMC_MSG_SetDriverDramAddrHigh
,
55 upper_32_bits(priv
->smu_tables
.entry
[table_id
].mc_addr
)) == 0,
56 "[CopyTableFromSMC] Attempt to Set Dram Addr High Failed!", return -EINVAL
);
57 PP_ASSERT_WITH_CODE(smu9_send_msg_to_smc_with_parameter(hwmgr
,
58 PPSMC_MSG_SetDriverDramAddrLow
,
59 lower_32_bits(priv
->smu_tables
.entry
[table_id
].mc_addr
)) == 0,
60 "[CopyTableFromSMC] Attempt to Set Dram Addr Low Failed!",
62 PP_ASSERT_WITH_CODE(smu9_send_msg_to_smc_with_parameter(hwmgr
,
63 PPSMC_MSG_TransferTableSmu2Dram
,
65 "[CopyTableFromSMC] Attempt to Transfer Table From SMU Failed!",
69 amdgpu_asic_flush_hdp(adev
, NULL
);
71 memcpy(table
, priv
->smu_tables
.entry
[table_id
].table
,
72 priv
->smu_tables
.entry
[table_id
].size
);
78 * Copy table from Driver FB into SMC
79 * @param hwmgr the address of the HW manager
80 * @param table_id the table to copy from
82 static int vega12_copy_table_to_smc(struct pp_hwmgr
*hwmgr
,
83 uint8_t *table
, int16_t table_id
)
85 struct vega12_smumgr
*priv
=
86 (struct vega12_smumgr
*)(hwmgr
->smu_backend
);
87 struct amdgpu_device
*adev
= hwmgr
->adev
;
89 PP_ASSERT_WITH_CODE(table_id
< TABLE_COUNT
,
90 "Invalid SMU Table ID!", return -EINVAL
);
91 PP_ASSERT_WITH_CODE(priv
->smu_tables
.entry
[table_id
].version
!= 0,
92 "Invalid SMU Table version!", return -EINVAL
);
93 PP_ASSERT_WITH_CODE(priv
->smu_tables
.entry
[table_id
].size
!= 0,
94 "Invalid SMU Table Length!", return -EINVAL
);
96 memcpy(priv
->smu_tables
.entry
[table_id
].table
, table
,
97 priv
->smu_tables
.entry
[table_id
].size
);
99 amdgpu_asic_flush_hdp(adev
, NULL
);
101 PP_ASSERT_WITH_CODE(smu9_send_msg_to_smc_with_parameter(hwmgr
,
102 PPSMC_MSG_SetDriverDramAddrHigh
,
103 upper_32_bits(priv
->smu_tables
.entry
[table_id
].mc_addr
)) == 0,
104 "[CopyTableToSMC] Attempt to Set Dram Addr High Failed!",
106 PP_ASSERT_WITH_CODE(smu9_send_msg_to_smc_with_parameter(hwmgr
,
107 PPSMC_MSG_SetDriverDramAddrLow
,
108 lower_32_bits(priv
->smu_tables
.entry
[table_id
].mc_addr
)) == 0,
109 "[CopyTableToSMC] Attempt to Set Dram Addr Low Failed!",
111 PP_ASSERT_WITH_CODE(smu9_send_msg_to_smc_with_parameter(hwmgr
,
112 PPSMC_MSG_TransferTableDram2Smu
,
114 "[CopyTableToSMC] Attempt to Transfer Table To SMU Failed!",
120 int vega12_enable_smc_features(struct pp_hwmgr
*hwmgr
,
121 bool enable
, uint64_t feature_mask
)
123 uint32_t smu_features_low
, smu_features_high
;
125 smu_features_low
= (uint32_t)((feature_mask
& SMU_FEATURES_LOW_MASK
) >> SMU_FEATURES_LOW_SHIFT
);
126 smu_features_high
= (uint32_t)((feature_mask
& SMU_FEATURES_HIGH_MASK
) >> SMU_FEATURES_HIGH_SHIFT
);
129 PP_ASSERT_WITH_CODE(smu9_send_msg_to_smc_with_parameter(hwmgr
,
130 PPSMC_MSG_EnableSmuFeaturesLow
, smu_features_low
) == 0,
131 "[EnableDisableSMCFeatures] Attemp to enable SMU features Low failed!",
133 PP_ASSERT_WITH_CODE(smu9_send_msg_to_smc_with_parameter(hwmgr
,
134 PPSMC_MSG_EnableSmuFeaturesHigh
, smu_features_high
) == 0,
135 "[EnableDisableSMCFeatures] Attemp to enable SMU features High failed!",
138 PP_ASSERT_WITH_CODE(smu9_send_msg_to_smc_with_parameter(hwmgr
,
139 PPSMC_MSG_DisableSmuFeaturesLow
, smu_features_low
) == 0,
140 "[EnableDisableSMCFeatures] Attemp to disable SMU features Low failed!",
142 PP_ASSERT_WITH_CODE(smu9_send_msg_to_smc_with_parameter(hwmgr
,
143 PPSMC_MSG_DisableSmuFeaturesHigh
, smu_features_high
) == 0,
144 "[EnableDisableSMCFeatures] Attemp to disable SMU features High failed!",
151 int vega12_get_enabled_smc_features(struct pp_hwmgr
*hwmgr
,
152 uint64_t *features_enabled
)
154 uint32_t smc_features_low
, smc_features_high
;
156 if (features_enabled
== NULL
)
159 PP_ASSERT_WITH_CODE(smu9_send_msg_to_smc(hwmgr
,
160 PPSMC_MSG_GetEnabledSmuFeaturesLow
) == 0,
161 "[GetEnabledSMCFeatures] Attemp to get SMU features Low failed!",
163 smc_features_low
= smu9_get_argument(hwmgr
);
165 PP_ASSERT_WITH_CODE(smu9_send_msg_to_smc(hwmgr
,
166 PPSMC_MSG_GetEnabledSmuFeaturesHigh
) == 0,
167 "[GetEnabledSMCFeatures] Attemp to get SMU features High failed!",
169 smc_features_high
= smu9_get_argument(hwmgr
);
171 *features_enabled
= ((((uint64_t)smc_features_low
<< SMU_FEATURES_LOW_SHIFT
) & SMU_FEATURES_LOW_MASK
) |
172 (((uint64_t)smc_features_high
<< SMU_FEATURES_HIGH_SHIFT
) & SMU_FEATURES_HIGH_MASK
));
177 static bool vega12_is_dpm_running(struct pp_hwmgr
*hwmgr
)
179 uint64_t features_enabled
= 0;
181 vega12_get_enabled_smc_features(hwmgr
, &features_enabled
);
183 if (features_enabled
& SMC_DPM_FEATURES
)
189 static int vega12_set_tools_address(struct pp_hwmgr
*hwmgr
)
191 struct vega12_smumgr
*priv
=
192 (struct vega12_smumgr
*)(hwmgr
->smu_backend
);
194 if (priv
->smu_tables
.entry
[TABLE_PMSTATUSLOG
].mc_addr
) {
195 if (!smu9_send_msg_to_smc_with_parameter(hwmgr
,
196 PPSMC_MSG_SetToolsDramAddrHigh
,
197 upper_32_bits(priv
->smu_tables
.entry
[TABLE_PMSTATUSLOG
].mc_addr
)))
198 smu9_send_msg_to_smc_with_parameter(hwmgr
,
199 PPSMC_MSG_SetToolsDramAddrLow
,
200 lower_32_bits(priv
->smu_tables
.entry
[TABLE_PMSTATUSLOG
].mc_addr
));
205 static int vega12_smu_init(struct pp_hwmgr
*hwmgr
)
207 struct vega12_smumgr
*priv
;
208 unsigned long tools_size
;
209 struct cgs_firmware_info info
= {0};
212 ret
= cgs_get_firmware_info(hwmgr
->device
, CGS_UCODE_ID_SMU
,
214 if (ret
|| !info
.kptr
)
217 priv
= kzalloc(sizeof(struct vega12_smumgr
), GFP_KERNEL
);
221 hwmgr
->smu_backend
= priv
;
223 /* allocate space for pptable */
224 ret
= amdgpu_bo_create_kernel((struct amdgpu_device
*)hwmgr
->adev
,
227 AMDGPU_GEM_DOMAIN_VRAM
,
228 &priv
->smu_tables
.entry
[TABLE_PPTABLE
].handle
,
229 &priv
->smu_tables
.entry
[TABLE_PPTABLE
].mc_addr
,
230 &priv
->smu_tables
.entry
[TABLE_PPTABLE
].table
);
234 priv
->smu_tables
.entry
[TABLE_PPTABLE
].version
= 0x01;
235 priv
->smu_tables
.entry
[TABLE_PPTABLE
].size
= sizeof(PPTable_t
);
237 /* allocate space for watermarks table */
238 ret
= amdgpu_bo_create_kernel((struct amdgpu_device
*)hwmgr
->adev
,
239 sizeof(Watermarks_t
),
241 AMDGPU_GEM_DOMAIN_VRAM
,
242 &priv
->smu_tables
.entry
[TABLE_WATERMARKS
].handle
,
243 &priv
->smu_tables
.entry
[TABLE_WATERMARKS
].mc_addr
,
244 &priv
->smu_tables
.entry
[TABLE_WATERMARKS
].table
);
249 priv
->smu_tables
.entry
[TABLE_WATERMARKS
].version
= 0x01;
250 priv
->smu_tables
.entry
[TABLE_WATERMARKS
].size
= sizeof(Watermarks_t
);
252 tools_size
= 0x19000;
254 ret
= amdgpu_bo_create_kernel((struct amdgpu_device
*)hwmgr
->adev
,
257 AMDGPU_GEM_DOMAIN_VRAM
,
258 &priv
->smu_tables
.entry
[TABLE_PMSTATUSLOG
].handle
,
259 &priv
->smu_tables
.entry
[TABLE_PMSTATUSLOG
].mc_addr
,
260 &priv
->smu_tables
.entry
[TABLE_PMSTATUSLOG
].table
);
264 priv
->smu_tables
.entry
[TABLE_PMSTATUSLOG
].version
= 0x01;
265 priv
->smu_tables
.entry
[TABLE_PMSTATUSLOG
].size
= tools_size
;
268 /* allocate space for AVFS Fuse table */
269 ret
= amdgpu_bo_create_kernel((struct amdgpu_device
*)hwmgr
->adev
,
270 sizeof(AvfsFuseOverride_t
),
272 AMDGPU_GEM_DOMAIN_VRAM
,
273 &priv
->smu_tables
.entry
[TABLE_AVFS_FUSE_OVERRIDE
].handle
,
274 &priv
->smu_tables
.entry
[TABLE_AVFS_FUSE_OVERRIDE
].mc_addr
,
275 &priv
->smu_tables
.entry
[TABLE_AVFS_FUSE_OVERRIDE
].table
);
280 priv
->smu_tables
.entry
[TABLE_AVFS_FUSE_OVERRIDE
].version
= 0x01;
281 priv
->smu_tables
.entry
[TABLE_AVFS_FUSE_OVERRIDE
].size
= sizeof(AvfsFuseOverride_t
);
283 /* allocate space for OverDrive table */
284 ret
= amdgpu_bo_create_kernel((struct amdgpu_device
*)hwmgr
->adev
,
285 sizeof(OverDriveTable_t
),
287 AMDGPU_GEM_DOMAIN_VRAM
,
288 &priv
->smu_tables
.entry
[TABLE_OVERDRIVE
].handle
,
289 &priv
->smu_tables
.entry
[TABLE_OVERDRIVE
].mc_addr
,
290 &priv
->smu_tables
.entry
[TABLE_OVERDRIVE
].table
);
294 priv
->smu_tables
.entry
[TABLE_OVERDRIVE
].version
= 0x01;
295 priv
->smu_tables
.entry
[TABLE_OVERDRIVE
].size
= sizeof(OverDriveTable_t
);
297 /* allocate space for SMU_METRICS table */
298 ret
= amdgpu_bo_create_kernel((struct amdgpu_device
*)hwmgr
->adev
,
299 sizeof(SmuMetrics_t
),
301 AMDGPU_GEM_DOMAIN_VRAM
,
302 &priv
->smu_tables
.entry
[TABLE_SMU_METRICS
].handle
,
303 &priv
->smu_tables
.entry
[TABLE_SMU_METRICS
].mc_addr
,
304 &priv
->smu_tables
.entry
[TABLE_SMU_METRICS
].table
);
308 priv
->smu_tables
.entry
[TABLE_SMU_METRICS
].version
= 0x01;
309 priv
->smu_tables
.entry
[TABLE_SMU_METRICS
].size
= sizeof(SmuMetrics_t
);
314 amdgpu_bo_free_kernel(&priv
->smu_tables
.entry
[TABLE_OVERDRIVE
].handle
,
315 &priv
->smu_tables
.entry
[TABLE_OVERDRIVE
].mc_addr
,
316 &priv
->smu_tables
.entry
[TABLE_OVERDRIVE
].table
);
318 amdgpu_bo_free_kernel(&priv
->smu_tables
.entry
[TABLE_AVFS_FUSE_OVERRIDE
].handle
,
319 &priv
->smu_tables
.entry
[TABLE_AVFS_FUSE_OVERRIDE
].mc_addr
,
320 &priv
->smu_tables
.entry
[TABLE_AVFS_FUSE_OVERRIDE
].table
);
322 if (priv
->smu_tables
.entry
[TABLE_PMSTATUSLOG
].table
)
323 amdgpu_bo_free_kernel(&priv
->smu_tables
.entry
[TABLE_PMSTATUSLOG
].handle
,
324 &priv
->smu_tables
.entry
[TABLE_PMSTATUSLOG
].mc_addr
,
325 &priv
->smu_tables
.entry
[TABLE_PMSTATUSLOG
].table
);
327 amdgpu_bo_free_kernel(&priv
->smu_tables
.entry
[TABLE_WATERMARKS
].handle
,
328 &priv
->smu_tables
.entry
[TABLE_WATERMARKS
].mc_addr
,
329 &priv
->smu_tables
.entry
[TABLE_WATERMARKS
].table
);
331 amdgpu_bo_free_kernel(&priv
->smu_tables
.entry
[TABLE_PPTABLE
].handle
,
332 &priv
->smu_tables
.entry
[TABLE_PPTABLE
].mc_addr
,
333 &priv
->smu_tables
.entry
[TABLE_PPTABLE
].table
);
335 kfree(hwmgr
->smu_backend
);
340 static int vega12_smu_fini(struct pp_hwmgr
*hwmgr
)
342 struct vega12_smumgr
*priv
=
343 (struct vega12_smumgr
*)(hwmgr
->smu_backend
);
346 amdgpu_bo_free_kernel(&priv
->smu_tables
.entry
[TABLE_PPTABLE
].handle
,
347 &priv
->smu_tables
.entry
[TABLE_PPTABLE
].mc_addr
,
348 &priv
->smu_tables
.entry
[TABLE_PPTABLE
].table
);
349 amdgpu_bo_free_kernel(&priv
->smu_tables
.entry
[TABLE_WATERMARKS
].handle
,
350 &priv
->smu_tables
.entry
[TABLE_WATERMARKS
].mc_addr
,
351 &priv
->smu_tables
.entry
[TABLE_WATERMARKS
].table
);
352 if (priv
->smu_tables
.entry
[TABLE_PMSTATUSLOG
].table
)
353 amdgpu_bo_free_kernel(&priv
->smu_tables
.entry
[TABLE_PMSTATUSLOG
].handle
,
354 &priv
->smu_tables
.entry
[TABLE_PMSTATUSLOG
].mc_addr
,
355 &priv
->smu_tables
.entry
[TABLE_PMSTATUSLOG
].table
);
356 amdgpu_bo_free_kernel(&priv
->smu_tables
.entry
[TABLE_AVFS_FUSE_OVERRIDE
].handle
,
357 &priv
->smu_tables
.entry
[TABLE_AVFS_FUSE_OVERRIDE
].mc_addr
,
358 &priv
->smu_tables
.entry
[TABLE_AVFS_FUSE_OVERRIDE
].table
);
359 amdgpu_bo_free_kernel(&priv
->smu_tables
.entry
[TABLE_OVERDRIVE
].handle
,
360 &priv
->smu_tables
.entry
[TABLE_OVERDRIVE
].mc_addr
,
361 &priv
->smu_tables
.entry
[TABLE_OVERDRIVE
].table
);
362 amdgpu_bo_free_kernel(&priv
->smu_tables
.entry
[TABLE_SMU_METRICS
].handle
,
363 &priv
->smu_tables
.entry
[TABLE_SMU_METRICS
].mc_addr
,
364 &priv
->smu_tables
.entry
[TABLE_SMU_METRICS
].table
);
365 kfree(hwmgr
->smu_backend
);
366 hwmgr
->smu_backend
= NULL
;
371 static int vega12_start_smu(struct pp_hwmgr
*hwmgr
)
373 PP_ASSERT_WITH_CODE(smu9_is_smc_ram_running(hwmgr
),
374 "SMC is not running!",
377 vega12_set_tools_address(hwmgr
);
382 static int vega12_smc_table_manager(struct pp_hwmgr
*hwmgr
, uint8_t *table
,
383 uint16_t table_id
, bool rw
)
388 ret
= vega12_copy_table_from_smc(hwmgr
, table
, table_id
);
390 ret
= vega12_copy_table_to_smc(hwmgr
, table
, table_id
);
395 const struct pp_smumgr_func vega12_smu_funcs
= {
396 .name
= "vega12_smu",
397 .smu_init
= &vega12_smu_init
,
398 .smu_fini
= &vega12_smu_fini
,
399 .start_smu
= &vega12_start_smu
,
400 .request_smu_load_specific_fw
= NULL
,
401 .send_msg_to_smc
= &smu9_send_msg_to_smc
,
402 .send_msg_to_smc_with_parameter
= &smu9_send_msg_to_smc_with_parameter
,
403 .download_pptable_settings
= NULL
,
404 .upload_pptable_settings
= NULL
,
405 .is_dpm_running
= vega12_is_dpm_running
,
406 .get_argument
= smu9_get_argument
,
407 .smc_table_manager
= vega12_smc_table_manager
,