1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24#include <linux/pci.h>
25
26#include "smumgr.h"
27#include "vega10_inc.h"
28#include "soc15_common.h"
29#include "vega10_smumgr.h"
30#include "vega10_hwmgr.h"
31#include "vega10_ppsmc.h"
32#include "smu9_driver_if.h"
33#include "smu9_smumgr.h"
34#include "ppatomctrl.h"
35#include "pp_debug.h"
36
37
38static int vega10_copy_table_from_smc(struct pp_hwmgr *hwmgr,
39 uint8_t *table, int16_t table_id)
40{
41 struct vega10_smumgr *priv = hwmgr->smu_backend;
42
43 PP_ASSERT_WITH_CODE(table_id < MAX_SMU_TABLE,
44 "Invalid SMU Table ID!", return -EINVAL);
45 PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0,
46 "Invalid SMU Table version!", return -EINVAL);
47 PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0,
48 "Invalid SMU Table Length!", return -EINVAL);
49 smu9_send_msg_to_smc_with_parameter(hwmgr,
50 PPSMC_MSG_SetDriverDramAddrHigh,
51 upper_32_bits(priv->smu_tables.entry[table_id].mc_addr));
52 smu9_send_msg_to_smc_with_parameter(hwmgr,
53 PPSMC_MSG_SetDriverDramAddrLow,
54 lower_32_bits(priv->smu_tables.entry[table_id].mc_addr));
55 smu9_send_msg_to_smc_with_parameter(hwmgr,
56 PPSMC_MSG_TransferTableSmu2Dram,
57 priv->smu_tables.entry[table_id].table_id);
58
59 memcpy(table, priv->smu_tables.entry[table_id].table,
60 priv->smu_tables.entry[table_id].size);
61
62 return 0;
63}
64
65static int vega10_copy_table_to_smc(struct pp_hwmgr *hwmgr,
66 uint8_t *table, int16_t table_id)
67{
68 struct vega10_smumgr *priv = hwmgr->smu_backend;
69
70 PP_ASSERT_WITH_CODE(table_id < MAX_SMU_TABLE,
71 "Invalid SMU Table ID!", return -EINVAL);
72 PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0,
73 "Invalid SMU Table version!", return -EINVAL);
74 PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0,
75 "Invalid SMU Table Length!", return -EINVAL);
76
77 memcpy(priv->smu_tables.entry[table_id].table, table,
78 priv->smu_tables.entry[table_id].size);
79
80 smu9_send_msg_to_smc_with_parameter(hwmgr,
81 PPSMC_MSG_SetDriverDramAddrHigh,
82 upper_32_bits(priv->smu_tables.entry[table_id].mc_addr));
83 smu9_send_msg_to_smc_with_parameter(hwmgr,
84 PPSMC_MSG_SetDriverDramAddrLow,
85 lower_32_bits(priv->smu_tables.entry[table_id].mc_addr));
86 smu9_send_msg_to_smc_with_parameter(hwmgr,
87 PPSMC_MSG_TransferTableDram2Smu,
88 priv->smu_tables.entry[table_id].table_id);
89
90 return 0;
91}
92
93int vega10_enable_smc_features(struct pp_hwmgr *hwmgr,
94 bool enable, uint32_t feature_mask)
95{
96 int msg = enable ? PPSMC_MSG_EnableSmuFeatures :
97 PPSMC_MSG_DisableSmuFeatures;
98
99 return smum_send_msg_to_smc_with_parameter(hwmgr,
100 msg, feature_mask);
101}
102
103int vega10_get_enabled_smc_features(struct pp_hwmgr *hwmgr,
104 uint64_t *features_enabled)
105{
106 if (features_enabled == NULL)
107 return -EINVAL;
108
109 smu9_send_msg_to_smc(hwmgr, PPSMC_MSG_GetEnabledSmuFeatures);
110 *features_enabled = smu9_get_argument(hwmgr);
111
112 return 0;
113}
114
115static bool vega10_is_dpm_running(struct pp_hwmgr *hwmgr)
116{
117 uint64_t features_enabled = 0;
118
119 vega10_get_enabled_smc_features(hwmgr, &features_enabled);
120
121 if (features_enabled & SMC_DPM_FEATURES)
122 return true;
123 else
124 return false;
125}
126
127static int vega10_set_tools_address(struct pp_hwmgr *hwmgr)
128{
129 struct vega10_smumgr *priv = hwmgr->smu_backend;
130
131 if (priv->smu_tables.entry[TOOLSTABLE].mc_addr) {
132 smu9_send_msg_to_smc_with_parameter(hwmgr,
133 PPSMC_MSG_SetToolsDramAddrHigh,
134 upper_32_bits(priv->smu_tables.entry[TOOLSTABLE].mc_addr));
135 smu9_send_msg_to_smc_with_parameter(hwmgr,
136 PPSMC_MSG_SetToolsDramAddrLow,
137 lower_32_bits(priv->smu_tables.entry[TOOLSTABLE].mc_addr));
138 }
139 return 0;
140}
141
142static int vega10_verify_smc_interface(struct pp_hwmgr *hwmgr)
143{
144 uint32_t smc_driver_if_version;
145 struct amdgpu_device *adev = hwmgr->adev;
146 uint32_t dev_id;
147 uint32_t rev_id;
148
149 PP_ASSERT_WITH_CODE(!smu9_send_msg_to_smc(hwmgr,
150 PPSMC_MSG_GetDriverIfVersion),
151 "Attempt to get SMC IF Version Number Failed!",
152 return -EINVAL);
153 smc_driver_if_version = smu9_get_argument(hwmgr);
154
155 dev_id = adev->pdev->device;
156 rev_id = adev->pdev->revision;
157
158 if (!((dev_id == 0x687f) &&
159 ((rev_id == 0xc0) ||
160 (rev_id == 0xc1) ||
161 (rev_id == 0xc3)))) {
162 if (smc_driver_if_version != SMU9_DRIVER_IF_VERSION) {
163 pr_err("Your firmware(0x%x) doesn't match SMU9_DRIVER_IF_VERSION(0x%x). Please update your firmware!\n",
164 smc_driver_if_version, SMU9_DRIVER_IF_VERSION);
165 return -EINVAL;
166 }
167 }
168
169 return 0;
170}
171
172static int vega10_smu_init(struct pp_hwmgr *hwmgr)
173{
174 struct vega10_smumgr *priv;
175 unsigned long tools_size;
176 int ret;
177 struct cgs_firmware_info info = {0};
178
179 ret = cgs_get_firmware_info(hwmgr->device,
180 CGS_UCODE_ID_SMU,
181 &info);
182 if (ret || !info.kptr)
183 return -EINVAL;
184
185 priv = kzalloc(sizeof(struct vega10_smumgr), GFP_KERNEL);
186
187 if (!priv)
188 return -ENOMEM;
189
190 hwmgr->smu_backend = priv;
191
192
193 ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
194 sizeof(PPTable_t),
195 PAGE_SIZE,
196 AMDGPU_GEM_DOMAIN_VRAM,
197 &priv->smu_tables.entry[PPTABLE].handle,
198 &priv->smu_tables.entry[PPTABLE].mc_addr,
199 &priv->smu_tables.entry[PPTABLE].table);
200 if (ret)
201 goto free_backend;
202
203 priv->smu_tables.entry[PPTABLE].version = 0x01;
204 priv->smu_tables.entry[PPTABLE].size = sizeof(PPTable_t);
205 priv->smu_tables.entry[PPTABLE].table_id = TABLE_PPTABLE;
206
207
208 ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
209 sizeof(Watermarks_t),
210 PAGE_SIZE,
211 AMDGPU_GEM_DOMAIN_VRAM,
212 &priv->smu_tables.entry[WMTABLE].handle,
213 &priv->smu_tables.entry[WMTABLE].mc_addr,
214 &priv->smu_tables.entry[WMTABLE].table);
215
216 if (ret)
217 goto err0;
218
219 priv->smu_tables.entry[WMTABLE].version = 0x01;
220 priv->smu_tables.entry[WMTABLE].size = sizeof(Watermarks_t);
221 priv->smu_tables.entry[WMTABLE].table_id = TABLE_WATERMARKS;
222
223
224 ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
225 sizeof(AvfsTable_t),
226 PAGE_SIZE,
227 AMDGPU_GEM_DOMAIN_VRAM,
228 &priv->smu_tables.entry[AVFSTABLE].handle,
229 &priv->smu_tables.entry[AVFSTABLE].mc_addr,
230 &priv->smu_tables.entry[AVFSTABLE].table);
231
232 if (ret)
233 goto err1;
234
235 priv->smu_tables.entry[AVFSTABLE].version = 0x01;
236 priv->smu_tables.entry[AVFSTABLE].size = sizeof(AvfsTable_t);
237 priv->smu_tables.entry[AVFSTABLE].table_id = TABLE_AVFS;
238
239 tools_size = 0x19000;
240 if (tools_size) {
241 ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
242 tools_size,
243 PAGE_SIZE,
244 AMDGPU_GEM_DOMAIN_VRAM,
245 &priv->smu_tables.entry[TOOLSTABLE].handle,
246 &priv->smu_tables.entry[TOOLSTABLE].mc_addr,
247 &priv->smu_tables.entry[TOOLSTABLE].table);
248 if (ret)
249 goto err2;
250 priv->smu_tables.entry[TOOLSTABLE].version = 0x01;
251 priv->smu_tables.entry[TOOLSTABLE].size = tools_size;
252 priv->smu_tables.entry[TOOLSTABLE].table_id = TABLE_PMSTATUSLOG;
253 }
254
255
256 ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
257 sizeof(AvfsFuseOverride_t),
258 PAGE_SIZE,
259 AMDGPU_GEM_DOMAIN_VRAM,
260 &priv->smu_tables.entry[AVFSFUSETABLE].handle,
261 &priv->smu_tables.entry[AVFSFUSETABLE].mc_addr,
262 &priv->smu_tables.entry[AVFSFUSETABLE].table);
263 if (ret)
264 goto err3;
265
266 priv->smu_tables.entry[AVFSFUSETABLE].version = 0x01;
267 priv->smu_tables.entry[AVFSFUSETABLE].size = sizeof(AvfsFuseOverride_t);
268 priv->smu_tables.entry[AVFSFUSETABLE].table_id = TABLE_AVFS_FUSE_OVERRIDE;
269
270
271 return 0;
272
273err3:
274 if (priv->smu_tables.entry[TOOLSTABLE].table)
275 amdgpu_bo_free_kernel(&priv->smu_tables.entry[TOOLSTABLE].handle,
276 &priv->smu_tables.entry[TOOLSTABLE].mc_addr,
277 &priv->smu_tables.entry[TOOLSTABLE].table);
278err2:
279 amdgpu_bo_free_kernel(&priv->smu_tables.entry[AVFSTABLE].handle,
280 &priv->smu_tables.entry[AVFSTABLE].mc_addr,
281 &priv->smu_tables.entry[AVFSTABLE].table);
282err1:
283 amdgpu_bo_free_kernel(&priv->smu_tables.entry[WMTABLE].handle,
284 &priv->smu_tables.entry[WMTABLE].mc_addr,
285 &priv->smu_tables.entry[WMTABLE].table);
286err0:
287 amdgpu_bo_free_kernel(&priv->smu_tables.entry[PPTABLE].handle,
288 &priv->smu_tables.entry[PPTABLE].mc_addr,
289 &priv->smu_tables.entry[PPTABLE].table);
290free_backend:
291 kfree(hwmgr->smu_backend);
292
293 return -EINVAL;
294}
295
296static int vega10_smu_fini(struct pp_hwmgr *hwmgr)
297{
298 struct vega10_smumgr *priv = hwmgr->smu_backend;
299
300 if (priv) {
301 amdgpu_bo_free_kernel(&priv->smu_tables.entry[PPTABLE].handle,
302 &priv->smu_tables.entry[PPTABLE].mc_addr,
303 &priv->smu_tables.entry[PPTABLE].table);
304 amdgpu_bo_free_kernel(&priv->smu_tables.entry[WMTABLE].handle,
305 &priv->smu_tables.entry[WMTABLE].mc_addr,
306 &priv->smu_tables.entry[WMTABLE].table);
307 amdgpu_bo_free_kernel(&priv->smu_tables.entry[AVFSTABLE].handle,
308 &priv->smu_tables.entry[AVFSTABLE].mc_addr,
309 &priv->smu_tables.entry[AVFSTABLE].table);
310 if (priv->smu_tables.entry[TOOLSTABLE].table)
311 amdgpu_bo_free_kernel(&priv->smu_tables.entry[TOOLSTABLE].handle,
312 &priv->smu_tables.entry[TOOLSTABLE].mc_addr,
313 &priv->smu_tables.entry[TOOLSTABLE].table);
314 amdgpu_bo_free_kernel(&priv->smu_tables.entry[AVFSFUSETABLE].handle,
315 &priv->smu_tables.entry[AVFSFUSETABLE].mc_addr,
316 &priv->smu_tables.entry[AVFSFUSETABLE].table);
317 kfree(hwmgr->smu_backend);
318 hwmgr->smu_backend = NULL;
319 }
320 return 0;
321}
322
323static int vega10_start_smu(struct pp_hwmgr *hwmgr)
324{
325 if (!smu9_is_smc_ram_running(hwmgr))
326 return -EINVAL;
327
328 PP_ASSERT_WITH_CODE(!vega10_verify_smc_interface(hwmgr),
329 "Failed to verify SMC interface!",
330 return -EINVAL);
331
332 vega10_set_tools_address(hwmgr);
333
334 return 0;
335}
336
337static int vega10_smc_table_manager(struct pp_hwmgr *hwmgr, uint8_t *table,
338 uint16_t table_id, bool rw)
339{
340 int ret;
341
342 if (rw)
343 ret = vega10_copy_table_from_smc(hwmgr, table, table_id);
344 else
345 ret = vega10_copy_table_to_smc(hwmgr, table, table_id);
346
347 return ret;
348}
349
350const struct pp_smumgr_func vega10_smu_funcs = {
351 .name = "vega10_smu",
352 .smu_init = &vega10_smu_init,
353 .smu_fini = &vega10_smu_fini,
354 .start_smu = &vega10_start_smu,
355 .request_smu_load_specific_fw = NULL,
356 .send_msg_to_smc = &smu9_send_msg_to_smc,
357 .send_msg_to_smc_with_parameter = &smu9_send_msg_to_smc_with_parameter,
358 .download_pptable_settings = NULL,
359 .upload_pptable_settings = NULL,
360 .is_dpm_running = vega10_is_dpm_running,
361 .get_argument = smu9_get_argument,
362 .smc_table_manager = vega10_smc_table_manager,
363};
364